src/ds/gx/software.c (view raw)
1/* Copyright (c) 2013-2017 Jeffrey Pfau
2 *
3 * This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6#include <mgba/internal/ds/gx/software.h>
7
8#include <mgba-util/memory.h>
9
10DEFINE_VECTOR(DSGXSoftwarePolygonList, struct DSGXSoftwarePolygon);
11DEFINE_VECTOR(DSGXSoftwareEdgeList, struct DSGXSoftwareEdge);
12
13static void DSGXSoftwareRendererInit(struct DSGXRenderer* renderer);
14static void DSGXSoftwareRendererReset(struct DSGXRenderer* renderer);
15static void DSGXSoftwareRendererDeinit(struct DSGXRenderer* renderer);
16static void DSGXSoftwareRendererSetRAM(struct DSGXRenderer* renderer, struct DSGXVertex* verts, struct DSGXPolygon* polys, unsigned polyCount);
17static void DSGXSoftwareRendererDrawScanline(struct DSGXRenderer* renderer, int y);
18static void DSGXSoftwareRendererGetScanline(struct DSGXRenderer* renderer, int y, color_t** output);
19
20static int _edgeSort(const void* a, const void* b) {
21 const struct DSGXSoftwareEdge* ea = a;
22 const struct DSGXSoftwareEdge* eb = b;
23
24 if (ea->y0 < eb->y0) {
25 return -1;
26 }
27 if (ea->y0 > eb->y0) {
28 return 1;
29 }
30 if (ea->y1 < eb->y1) {
31 return -1;
32 }
33 if (ea->y1 > eb->y1) {
34 return 1;
35 }
36 return 0;
37}
38
39void DSGXSoftwareRendererCreate(struct DSGXSoftwareRenderer* renderer) {
40 renderer->d.init = DSGXSoftwareRendererInit;
41 renderer->d.reset = DSGXSoftwareRendererReset;
42 renderer->d.deinit = DSGXSoftwareRendererDeinit;
43 renderer->d.setRAM = DSGXSoftwareRendererSetRAM;
44 renderer->d.drawScanline = DSGXSoftwareRendererDrawScanline;
45 renderer->d.getScanline = DSGXSoftwareRendererGetScanline;
46}
47
48static void DSGXSoftwareRendererInit(struct DSGXRenderer* renderer) {
49 struct DSGXSoftwareRenderer* softwareRenderer = (struct DSGXSoftwareRenderer*) renderer;
50 DSGXSoftwarePolygonListInit(&softwareRenderer->activePolys, DS_GX_POLYGON_BUFFER_SIZE / 4);
51 DSGXSoftwareEdgeListInit(&softwareRenderer->activeEdges, DS_GX_POLYGON_BUFFER_SIZE);
52 softwareRenderer->scanlineCache = anonymousMemoryMap(sizeof(color_t) * DS_VIDEO_HORIZONTAL_PIXELS * 48);
53}
54
55static void DSGXSoftwareRendererReset(struct DSGXRenderer* renderer) {
56 struct DSGXSoftwareRenderer* softwareRenderer = (struct DSGXSoftwareRenderer*) renderer;
57 // TODO
58}
59
60static void DSGXSoftwareRendererDeinit(struct DSGXRenderer* renderer) {
61 struct DSGXSoftwareRenderer* softwareRenderer = (struct DSGXSoftwareRenderer*) renderer;
62 DSGXSoftwarePolygonListDeinit(&softwareRenderer->activePolys);
63 DSGXSoftwareEdgeListDeinit(&softwareRenderer->activeEdges);
64 mappedMemoryFree(softwareRenderer->scanlineCache, sizeof(color_t) * DS_VIDEO_HORIZONTAL_PIXELS * 48);
65}
66
67static void DSGXSoftwareRendererSetRAM(struct DSGXRenderer* renderer, struct DSGXVertex* verts, struct DSGXPolygon* polys, unsigned polyCount) {
68 struct DSGXSoftwareRenderer* softwareRenderer = (struct DSGXSoftwareRenderer*) renderer;
69
70 softwareRenderer->verts = verts;
71 DSGXSoftwarePolygonListClear(&softwareRenderer->activePolys);
72 DSGXSoftwareEdgeListClear(&softwareRenderer->activeEdges);
73 unsigned i;
74 for (i = 0; i < polyCount; ++i) {
75 struct DSGXSoftwarePolygon* poly = DSGXSoftwarePolygonListAppend(&softwareRenderer->activePolys);
76 struct DSGXSoftwareEdge* edge = DSGXSoftwareEdgeListAppend(&softwareRenderer->activeEdges);
77 poly->poly = &polys[i];
78
79 struct DSGXVertex* v0 = &verts[poly->poly->vertIds[0]];
80 struct DSGXVertex* v1;
81
82 int v;
83 for (v = 1; v < poly->poly->verts; ++v) {
84 v1 = &verts[poly->poly->vertIds[v]];
85 if (v0->vy <= v1->vy) {
86 edge->y0 = v0->vy;
87 edge->x0 = v0->vx;
88 edge->w0 = v0->vw;
89 edge->c0 = v0->color;
90 edge->s0 = v0->s;
91 edge->t0 = v0->t;
92
93 edge->y1 = v1->vy;
94 edge->x1 = v1->vx;
95 edge->w1 = v1->vw;
96 edge->c1 = v1->color;
97 edge->s1 = v1->s;
98 edge->t1 = v1->t;
99 } else {
100 edge->y0 = v1->vy;
101 edge->x0 = v1->vx;
102 edge->w0 = v1->vw;
103 edge->c0 = v1->color;
104 edge->s0 = v1->s;
105 edge->t0 = v1->t;
106
107 edge->y1 = v0->vy;
108 edge->x1 = v0->vx;
109 edge->w1 = v0->vw;
110 edge->c1 = v0->color;
111 edge->s1 = v0->s;
112 edge->t1 = v0->t;
113 }
114
115 edge = DSGXSoftwareEdgeListAppend(&softwareRenderer->activeEdges);
116 v0 = v1;
117 }
118
119 v1 = &verts[poly->poly->vertIds[0]];
120 if (v0->vy <= v1->vy) {
121 edge->y0 = v0->vy;
122 edge->x0 = v0->vx;
123 edge->w0 = v0->vw;
124 edge->c0 = v0->color;
125 edge->s0 = v0->s;
126 edge->t0 = v0->t;
127
128 edge->y1 = v1->vy;
129 edge->x1 = v1->vx;
130 edge->w1 = v1->vw;
131 edge->c1 = v1->color;
132 edge->s1 = v1->s;
133 edge->t1 = v1->t;
134 } else {
135 edge->y0 = v1->vy;
136 edge->x0 = v1->vx;
137 edge->w0 = v1->vw;
138 edge->c0 = v1->color;
139 edge->s0 = v1->s;
140 edge->t0 = v1->t;
141
142 edge->y1 = v0->vy;
143 edge->x1 = v0->vx;
144 edge->w1 = v0->vw;
145 edge->c1 = v0->color;
146 edge->s1 = v0->s;
147 edge->t1 = v0->t;
148 }
149 }
150 qsort(DSGXSoftwareEdgeListGetPointer(&softwareRenderer->activeEdges, 0), DSGXSoftwareEdgeListSize(&softwareRenderer->activeEdges), sizeof(struct DSGXSoftwareEdge), _edgeSort);
151}
152
153static void DSGXSoftwareRendererDrawScanline(struct DSGXRenderer* renderer, int y) {
154 struct DSGXSoftwareRenderer* softwareRenderer = (struct DSGXSoftwareRenderer*) renderer;
155 // TODO
156}
157
158static void DSGXSoftwareRendererGetScanline(struct DSGXRenderer* renderer, int y, color_t** output) {
159 struct DSGXSoftwareRenderer* softwareRenderer = (struct DSGXSoftwareRenderer*) renderer;
160 y %= 48;
161 *output = &softwareRenderer->scanlineCache[DS_VIDEO_HORIZONTAL_PIXELS * y];
162}