DS GX: Start filling in software renderer

This commit is contained in:
Vicki Pfau 2017-02-28 11:06:48 -08:00
parent 778eb8bc3b
commit c6ff504e66
5 changed files with 229 additions and 2 deletions

View File

@ -18,6 +18,9 @@ CXX_GUARD_START
mLOG_DECLARE_CATEGORY(DS_GX);
#define DS_GX_POLYGON_BUFFER_SIZE 2048
#define DS_GX_VERTEX_BUFFER_SIZE 6144
DECL_BITFIELD(DSRegGXSTAT, uint32_t);
DECL_BIT(DSRegGXSTAT, TestBusy, 0);
DECL_BIT(DSRegGXSTAT, BoxTestResult, 1);

View File

@ -0,0 +1,58 @@
/* Copyright (c) 2013-2017 Jeffrey Pfau
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef DS_GX_SOFTWARE_H
#define DS_GX_SOFTWARE_H
#include <mgba-util/common.h>
CXX_GUARD_START
#include <mgba/internal/ds/gx.h>
#include <mgba/internal/ds/video.h>
#include <mgba-util/vector.h>
struct DSGXSoftwarePolygon {
struct DSGXPolygon* poly;
int32_t topY;
int32_t bottomY;
int32_t topZ;
};
struct DSGXSoftwareEdge {
struct DSGXPolygon* poly;
int32_t y0;
int32_t x0;
int32_t w0;
int32_t c0; // 6.6.6.6 ARGB
int16_t s0;
int16_t t0;
int32_t y1;
int32_t x1;
int32_t w1;
int32_t c1; // 6.6.6.6 ARGB
int16_t s1;
int16_t t1;
};
DECLARE_VECTOR(DSGXSoftwarePolygonList, struct DSGXSoftwarePolygon);
DECLARE_VECTOR(DSGXSoftwareEdgeList, struct DSGXSoftwareEdge);
struct DSGXSoftwareRenderer {
struct DSGXRenderer d;
struct DSGXSoftwarePolygonList activePolys;
struct DSGXSoftwareEdgeList activeEdges;
uint16_t depthBuffer[DS_VIDEO_HORIZONTAL_PIXELS];
color_t* scanlineCache;
struct DSGXVertex* verts;
};
CXX_GUARD_END
#endif

View File

@ -12,6 +12,7 @@
#include <mgba/internal/ds/ds.h>
#include <mgba/internal/ds/extra/cli.h>
#include <mgba/internal/ds/renderers/software.h>
#include <mgba/internal/ds/gx/software.h>
#include <mgba-util/memory.h>
#include <mgba-util/patch.h>
#include <mgba-util/vfs.h>
@ -21,6 +22,7 @@ struct DSCore {
struct ARMCore* arm7;
struct ARMCore* arm9;
struct DSVideoSoftwareRenderer renderer;
struct DSGXSoftwareRenderer gxRenderer;
int keys;
int cursorX;
int cursorY;
@ -58,6 +60,7 @@ static bool _DSCoreInit(struct mCore* core) {
ARMInit(arm9);
DSVideoSoftwareRendererCreate(&dscore->renderer);
DSGXSoftwareRendererCreate(&dscore->gxRenderer);
dscore->renderer.outputBuffer = NULL;
dscore->keys = 0;
@ -187,6 +190,9 @@ static void _DSCoreReset(struct mCore* core) {
if (dscore->renderer.outputBuffer) {
struct DSVideoRenderer* renderer = &dscore->renderer.d;
DSVideoAssociateRenderer(&ds->video, renderer);
struct DSGXRenderer* gxRenderer = &dscore->gxRenderer.d;
DSGXAssociateRenderer(&ds->gx, gxRenderer);
}
#if !defined(MINIMAL_CORE) || MINIMAL_CORE < 2

View File

@ -12,8 +12,6 @@ mLOG_DEFINE_CATEGORY(DS_GX, "DS GX");
#define DS_GX_FIFO_SIZE 256
#define DS_GX_PIPE_SIZE 4
#define DS_GX_POLYGON_BUFFER_SIZE 2048
#define DS_GX_VERTEX_BUFFER_SIZE 6144
static void DSGXDummyRendererInit(struct DSGXRenderer* renderer);
static void DSGXDummyRendererReset(struct DSGXRenderer* renderer);

162
src/ds/gx/software.c Normal file
View File

@ -0,0 +1,162 @@
/* Copyright (c) 2013-2017 Jeffrey Pfau
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include <mgba/internal/ds/gx/software.h>
#include <mgba-util/memory.h>
DEFINE_VECTOR(DSGXSoftwarePolygonList, struct DSGXSoftwarePolygon);
DEFINE_VECTOR(DSGXSoftwareEdgeList, struct DSGXSoftwareEdge);
static void DSGXSoftwareRendererInit(struct DSGXRenderer* renderer);
static void DSGXSoftwareRendererReset(struct DSGXRenderer* renderer);
static void DSGXSoftwareRendererDeinit(struct DSGXRenderer* renderer);
static void DSGXSoftwareRendererSetRAM(struct DSGXRenderer* renderer, struct DSGXVertex* verts, struct DSGXPolygon* polys, unsigned polyCount);
static void DSGXSoftwareRendererDrawScanline(struct DSGXRenderer* renderer, int y);
static void DSGXSoftwareRendererGetScanline(struct DSGXRenderer* renderer, int y, color_t** output);
static int _edgeSort(const void* a, const void* b) {
const struct DSGXSoftwareEdge* ea = a;
const struct DSGXSoftwareEdge* eb = b;
if (ea->y0 < eb->y0) {
return -1;
}
if (ea->y0 > eb->y0) {
return 1;
}
if (ea->y1 < eb->y1) {
return -1;
}
if (ea->y1 > eb->y1) {
return 1;
}
return 0;
}
void DSGXSoftwareRendererCreate(struct DSGXSoftwareRenderer* renderer) {
renderer->d.init = DSGXSoftwareRendererInit;
renderer->d.reset = DSGXSoftwareRendererReset;
renderer->d.deinit = DSGXSoftwareRendererDeinit;
renderer->d.setRAM = DSGXSoftwareRendererSetRAM;
renderer->d.drawScanline = DSGXSoftwareRendererDrawScanline;
renderer->d.getScanline = DSGXSoftwareRendererGetScanline;
}
static void DSGXSoftwareRendererInit(struct DSGXRenderer* renderer) {
struct DSGXSoftwareRenderer* softwareRenderer = (struct DSGXSoftwareRenderer*) renderer;
DSGXSoftwarePolygonListInit(&softwareRenderer->activePolys, DS_GX_POLYGON_BUFFER_SIZE / 4);
DSGXSoftwareEdgeListInit(&softwareRenderer->activeEdges, DS_GX_POLYGON_BUFFER_SIZE);
softwareRenderer->scanlineCache = anonymousMemoryMap(sizeof(color_t) * DS_VIDEO_HORIZONTAL_PIXELS * 48);
}
static void DSGXSoftwareRendererReset(struct DSGXRenderer* renderer) {
struct DSGXSoftwareRenderer* softwareRenderer = (struct DSGXSoftwareRenderer*) renderer;
// TODO
}
static void DSGXSoftwareRendererDeinit(struct DSGXRenderer* renderer) {
struct DSGXSoftwareRenderer* softwareRenderer = (struct DSGXSoftwareRenderer*) renderer;
DSGXSoftwarePolygonListDeinit(&softwareRenderer->activePolys);
DSGXSoftwareEdgeListDeinit(&softwareRenderer->activeEdges);
mappedMemoryFree(softwareRenderer->scanlineCache, sizeof(color_t) * DS_VIDEO_HORIZONTAL_PIXELS * 48);
}
static void DSGXSoftwareRendererSetRAM(struct DSGXRenderer* renderer, struct DSGXVertex* verts, struct DSGXPolygon* polys, unsigned polyCount) {
struct DSGXSoftwareRenderer* softwareRenderer = (struct DSGXSoftwareRenderer*) renderer;
softwareRenderer->verts = verts;
DSGXSoftwarePolygonListClear(&softwareRenderer->activePolys);
DSGXSoftwareEdgeListClear(&softwareRenderer->activeEdges);
unsigned i;
for (i = 0; i < polyCount; ++i) {
struct DSGXSoftwarePolygon* poly = DSGXSoftwarePolygonListAppend(&softwareRenderer->activePolys);
struct DSGXSoftwareEdge* edge = DSGXSoftwareEdgeListAppend(&softwareRenderer->activeEdges);
poly->poly = &polys[i];
struct DSGXVertex* v0 = &verts[poly->poly->vertIds[0]];
struct DSGXVertex* v1;
int v;
for (v = 1; v < poly->poly->verts; ++v) {
v1 = &verts[poly->poly->vertIds[v]];
if (v0->vy <= v1->vy) {
edge->y0 = v0->vy;
edge->x0 = v0->vx;
edge->w0 = v0->vw;
edge->c0 = v0->color;
edge->s0 = v0->s;
edge->t0 = v0->t;
edge->y1 = v1->vy;
edge->x1 = v1->vx;
edge->w1 = v1->vw;
edge->c1 = v1->color;
edge->s1 = v1->s;
edge->t1 = v1->t;
} else {
edge->y0 = v1->vy;
edge->x0 = v1->vx;
edge->w0 = v1->vw;
edge->c0 = v1->color;
edge->s0 = v1->s;
edge->t0 = v1->t;
edge->y1 = v0->vy;
edge->x1 = v0->vx;
edge->w1 = v0->vw;
edge->c1 = v0->color;
edge->s1 = v0->s;
edge->t1 = v0->t;
}
edge = DSGXSoftwareEdgeListAppend(&softwareRenderer->activeEdges);
v0 = v1;
}
v1 = &verts[poly->poly->vertIds[0]];
if (v0->vy <= v1->vy) {
edge->y0 = v0->vy;
edge->x0 = v0->vx;
edge->w0 = v0->vw;
edge->c0 = v0->color;
edge->s0 = v0->s;
edge->t0 = v0->t;
edge->y1 = v1->vy;
edge->x1 = v1->vx;
edge->w1 = v1->vw;
edge->c1 = v1->color;
edge->s1 = v1->s;
edge->t1 = v1->t;
} else {
edge->y0 = v1->vy;
edge->x0 = v1->vx;
edge->w0 = v1->vw;
edge->c0 = v1->color;
edge->s0 = v1->s;
edge->t0 = v1->t;
edge->y1 = v0->vy;
edge->x1 = v0->vx;
edge->w1 = v0->vw;
edge->c1 = v0->color;
edge->s1 = v0->s;
edge->t1 = v0->t;
}
}
qsort(DSGXSoftwareEdgeListGetPointer(&softwareRenderer->activeEdges, 0), DSGXSoftwareEdgeListSize(&softwareRenderer->activeEdges), sizeof(struct DSGXSoftwareEdge), _edgeSort);
}
static void DSGXSoftwareRendererDrawScanline(struct DSGXRenderer* renderer, int y) {
struct DSGXSoftwareRenderer* softwareRenderer = (struct DSGXSoftwareRenderer*) renderer;
// TODO
}
static void DSGXSoftwareRendererGetScanline(struct DSGXRenderer* renderer, int y, color_t** output) {
struct DSGXSoftwareRenderer* softwareRenderer = (struct DSGXSoftwareRenderer*) renderer;
y %= 48;
*output = &softwareRenderer->scanlineCache[DS_VIDEO_HORIZONTAL_PIXELS * y];
}