mirror of https://github.com/mgba-emu/mgba.git
DS GX: Basic tri rendering
This commit is contained in:
parent
f2fd53af07
commit
a3cd5f8ca4
|
@ -6,6 +6,7 @@
|
||||||
#include <mgba/internal/ds/gx/software.h>
|
#include <mgba/internal/ds/gx/software.h>
|
||||||
|
|
||||||
#include <mgba-util/memory.h>
|
#include <mgba-util/memory.h>
|
||||||
|
#include "gba/renderers/software-private.h"
|
||||||
|
|
||||||
#define SCREEN_SIZE (DS_VIDEO_VERTICAL_PIXELS << 12)
|
#define SCREEN_SIZE (DS_VIDEO_VERTICAL_PIXELS << 12)
|
||||||
|
|
||||||
|
@ -101,6 +102,34 @@ static int _spanSort(const void* a, const void* b) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static color_t _lerpColor(const struct DSGXSoftwareSpan* span, unsigned x) {
|
||||||
|
int64_t width = span->x1 - span->x0;
|
||||||
|
int64_t xw = ((uint64_t) x << 12) - span->x0;
|
||||||
|
if (width) {
|
||||||
|
xw <<= 19;
|
||||||
|
xw /= width;
|
||||||
|
} else {
|
||||||
|
return 0; // TODO?
|
||||||
|
}
|
||||||
|
// Clamp to bounds
|
||||||
|
if (xw < 0) {
|
||||||
|
xw = 0;
|
||||||
|
} else if (xw > width) {
|
||||||
|
xw = width;
|
||||||
|
}
|
||||||
|
color_t r = ((int32_t) (span->cr1 - span->cr0) * xw) / width + span->cr0;
|
||||||
|
color_t g = ((int32_t) (span->cg1 - span->cg0) * xw) / width + span->cg0;
|
||||||
|
color_t b = ((int32_t) (span->cb1 - span->cb0) * xw) / width + span->cb0;
|
||||||
|
#ifndef COLOR_16_BIT
|
||||||
|
color_t rgb = (r << 2) & 0xF8;
|
||||||
|
rgb |= (g << 10) & 0xF800;
|
||||||
|
rgb |= (b << 18) & 0xF80000;
|
||||||
|
return rgb;
|
||||||
|
#else
|
||||||
|
#error Unsupported color depth
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
void DSGXSoftwareRendererCreate(struct DSGXSoftwareRenderer* renderer) {
|
void DSGXSoftwareRendererCreate(struct DSGXSoftwareRenderer* renderer) {
|
||||||
renderer->d.init = DSGXSoftwareRendererInit;
|
renderer->d.init = DSGXSoftwareRendererInit;
|
||||||
renderer->d.reset = DSGXSoftwareRendererReset;
|
renderer->d.reset = DSGXSoftwareRendererReset;
|
||||||
|
@ -252,6 +281,38 @@ static void DSGXSoftwareRendererDrawScanline(struct DSGXRenderer* renderer, int
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
qsort(DSGXSoftwareSpanListGetPointer(&softwareRenderer->activeSpans, 0), DSGXSoftwareSpanListSize(&softwareRenderer->activeSpans), sizeof(struct DSGXSoftwareSpan), _spanSort);
|
qsort(DSGXSoftwareSpanListGetPointer(&softwareRenderer->activeSpans, 0), DSGXSoftwareSpanListSize(&softwareRenderer->activeSpans), sizeof(struct DSGXSoftwareSpan), _spanSort);
|
||||||
|
|
||||||
|
y %= 48;
|
||||||
|
color_t* scanline = &softwareRenderer->scanlineCache[DS_VIDEO_HORIZONTAL_PIXELS * y];
|
||||||
|
|
||||||
|
size_t nextSpanX = DS_VIDEO_HORIZONTAL_PIXELS;
|
||||||
|
if (DSGXSoftwareSpanListSize(&softwareRenderer->activeSpans)) {
|
||||||
|
nextSpanX = DSGXSoftwareSpanListGetPointer(&softwareRenderer->activeSpans, DSGXSoftwareSpanListSize(&softwareRenderer->activeSpans) - 1)->x0;
|
||||||
|
nextSpanX >>= 12;
|
||||||
|
}
|
||||||
|
for (i = 0; i < DS_VIDEO_HORIZONTAL_PIXELS; ++i) {
|
||||||
|
struct DSGXSoftwareSpan* span = NULL;
|
||||||
|
if (i >= nextSpanX) {
|
||||||
|
size_t nextSpanId = DSGXSoftwareSpanListSize(&softwareRenderer->activeSpans);
|
||||||
|
span = DSGXSoftwareSpanListGetPointer(&softwareRenderer->activeSpans, nextSpanId - 1);
|
||||||
|
while (i > (uint32_t) (span->x1 >> 12)) {
|
||||||
|
DSGXSoftwareSpanListShift(&softwareRenderer->activeSpans, nextSpanId - 1, 1);
|
||||||
|
--nextSpanId;
|
||||||
|
if (!nextSpanId) {
|
||||||
|
nextSpanX = DS_VIDEO_HORIZONTAL_PIXELS;
|
||||||
|
span = NULL;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
span = DSGXSoftwareSpanListGetPointer(&softwareRenderer->activeSpans, nextSpanId - 1);
|
||||||
|
nextSpanX = span->x0 >> 12;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (span) {
|
||||||
|
scanline[i] = _lerpColor(span, i);
|
||||||
|
} else {
|
||||||
|
scanline[i] = FLAG_UNWRITTEN; // TODO
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void DSGXSoftwareRendererGetScanline(struct DSGXRenderer* renderer, int y, color_t** output) {
|
static void DSGXSoftwareRendererGetScanline(struct DSGXRenderer* renderer, int y, color_t** output) {
|
||||||
|
|
|
@ -385,7 +385,13 @@ static void DSVideoSoftwareRendererDrawGBAScanline(struct GBAVideoRenderer* rend
|
||||||
if (DSRegisterDISPCNTIs3D(softwareRenderer->dispcnt) && gx) {
|
if (DSRegisterDISPCNTIs3D(softwareRenderer->dispcnt) && gx) {
|
||||||
color_t* scanline;
|
color_t* scanline;
|
||||||
gx->renderer->getScanline(gx->renderer, y, &scanline);
|
gx->renderer->getScanline(gx->renderer, y, &scanline);
|
||||||
// TODO
|
uint32_t flags = (softwareRenderer->bg[0].priority << OFFSET_PRIORITY) | FLAG_IS_BACKGROUND;
|
||||||
|
int x;
|
||||||
|
for (x = softwareRenderer->start; x < softwareRenderer->end; ++x) {
|
||||||
|
if ((scanline[x] & FLAG_UNWRITTEN) != FLAG_UNWRITTEN) {
|
||||||
|
_compositeNoBlendNoObjwin(softwareRenderer, &softwareRenderer->row[x], scanline[x] | flags, softwareRenderer->row[x]);
|
||||||
|
}
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
GBAVideoSoftwareRendererDrawBackgroundMode0(softwareRenderer, &softwareRenderer->bg[0], y);
|
GBAVideoSoftwareRendererDrawBackgroundMode0(softwareRenderer, &softwareRenderer->bg[0], y);
|
||||||
}
|
}
|
||||||
|
|
|
@ -201,6 +201,7 @@ void DSVideoAssociateRenderer(struct DSVideo* video, struct DSVideoRenderer* ren
|
||||||
memcpy(renderer->vramBBGExtPal, video->vramBBGExtPal, sizeof(renderer->vramBBGExtPal));
|
memcpy(renderer->vramBBGExtPal, video->vramBBGExtPal, sizeof(renderer->vramBBGExtPal));
|
||||||
renderer->vramBOBJExtPal = video->vramBOBJExtPal;
|
renderer->vramBOBJExtPal = video->vramBOBJExtPal;
|
||||||
renderer->oam = &video->oam;
|
renderer->oam = &video->oam;
|
||||||
|
renderer->gx = &video->p->gx;
|
||||||
video->renderer->init(video->renderer);
|
video->renderer->init(video->renderer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -321,8 +322,8 @@ void _startHblank9(struct mTiming* timing, void* context, uint32_t cyclesLate) {
|
||||||
dispstat = GBARegisterDISPSTATFillInHblank(dispstat);
|
dispstat = GBARegisterDISPSTATFillInHblank(dispstat);
|
||||||
if (video->frameskipCounter <= 0) {
|
if (video->frameskipCounter <= 0) {
|
||||||
if (video->vcount < DS_VIDEO_VERTICAL_PIXELS) {
|
if (video->vcount < DS_VIDEO_VERTICAL_PIXELS) {
|
||||||
video->p->gx.renderer->drawScanline(video->p->gx.renderer, video->vcount + 48);
|
|
||||||
video->renderer->drawScanline(video->renderer, video->vcount);
|
video->renderer->drawScanline(video->renderer, video->vcount);
|
||||||
|
video->p->gx.renderer->drawScanline(video->p->gx.renderer, video->vcount + 48);
|
||||||
}
|
}
|
||||||
if (video->vcount >= DS_VIDEO_VERTICAL_TOTAL_PIXELS - 48) {
|
if (video->vcount >= DS_VIDEO_VERTICAL_TOTAL_PIXELS - 48) {
|
||||||
video->p->gx.renderer->drawScanline(video->p->gx.renderer, video->vcount + 48 - DS_VIDEO_VERTICAL_TOTAL_PIXELS);
|
video->p->gx.renderer->drawScanline(video->p->gx.renderer, video->vcount + 48 - DS_VIDEO_VERTICAL_TOTAL_PIXELS);
|
||||||
|
|
Loading…
Reference in New Issue