14 static void reset_dirty(struct rect *r);
16 static int32_t mvmat[16];
17 static int32_t pmat[16];
19 static struct rect dirty_rect[2];
20 static unsigned int cur_dirty;
22 unsigned char *g3d_fbpixels;
23 int g3d_width, g3d_height;
30 memset(mvmat, 0, sizeof mvmat);
31 memset(pmat, 0, sizeof pmat);
32 mvmat[0] = mvmat[5] = mvmat[10] = mvmat[15] = 0x10000;
33 pmat[0] = pmat[5] = pmat[10] = pmat[15] = 0x10000;
40 void g3d_shutdown(void)
44 void g3d_framebuffer(int width, int height, void *fb)
46 g3d_fbpixels = fb ? fb : vid_backbuf;
54 reset_dirty(dirty_rect);
55 reset_dirty(dirty_rect + 1);
58 void g3d_framebuf_addr(void *fb)
60 g3d_fbpixels = vid_backbuf;
63 static void reset_dirty(struct rect *r)
71 void g3d_clear_dirty(void)
76 /* we need to clear based not on the last current dirty region, but the one
77 * before that. Then we need to reset the same one we used, and increment
78 * cur_dirty in preperation of this frames drawing
80 cur_dirty = (cur_dirty + 1) & 1;
81 dirty = dirty_rect + cur_dirty;
83 if(dirty->x0 < 0) dirty->x0 = 0;
84 if(dirty->y0 < 0) dirty->y0 = 0;
85 if(dirty->x1 >= XRES) dirty->x1 = XRES - 1;
86 if(dirty->y1 >= YRES) dirty->y1 = YRES - 1;
88 width = dirty->x1 + 1 - dirty->x0;
89 height = dirty->y1 + 1 - dirty->y0;
91 vid_clearfb_rect(dirty->x0, dirty->y0, width, height);
95 void g3d_modelview(const int32_t *m)
97 memcpy(mvmat, m, sizeof mvmat);
100 void g3d_projection(const int32_t *m)
102 memcpy(pmat, m, sizeof pmat);
105 void g3d_color(int cidx)
110 static const int primverts[] = {0, 1, 2, 3, 4};
112 void g3d_draw(int prim, struct g3d_vertex *varr, int vcount)
116 prim_vnum = primverts[prim];
118 for(i=0; i<vcount; i+=prim_vnum) {
119 g3d_draw_prim(prim, varr, 0);
124 void g3d_draw_indexed(int prim, struct g3d_vertex *varr, unsigned short *idxarr,
129 prim_vnum = primverts[prim];
131 for(i=0; i<idxcount; i+=prim_vnum) {
132 g3d_draw_prim(prim, varr, idxarr);
137 int32_t vpscale(int32_t x, int32_t s, int32_t shift);
138 #pragma aux vpscale = \
141 "shrd eax, edx, cl" \
142 parm [eax] [ebx] [ecx] \
147 void g3d_draw_prim(int prim, struct g3d_vertex *varr, unsigned short *idxarr)
149 int i, vcount, x, y, x1, y1;
150 struct g3d_vertex v[4];
152 vcount = primverts[prim];
154 for(i=0; i<vcount; i++) {
155 v[i] = idxarr ? varr[idxarr[i]] : varr[i];
157 /* transform to view space */
158 g3d_xform(v + i, mvmat);
160 /* transform to homogeneous clip space */
161 g3d_xform(v + i, pmat);
165 /* perspective division */
167 v[i].x = (v[i].x << 4) / (v[i].w >> 4);
168 v[i].y = (v[i].y << 4) / (v[i].w >> 4);
174 /* viewport transform */
175 v[i].x = vpscale(v[i].x, vp[2], 1) + (vp[0] << 8);
176 v[i].y = vpscale(-v[i].y, vp[3], 1) + (vp[1] << 8);
178 #if defined(USE_DIRTY_CLEAR) || defined(USE_DIRTY_COPY)
182 struct rect *dirty = dirty_rect + cur_dirty;
183 if(x < dirty->x0) dirty->x0 = x;
184 if(y < dirty->y0) dirty->y0 = y;
185 if(x + 4 > dirty->x1) dirty->x1 = x + 4;
186 if(y > dirty->y1) dirty->y1 = y;
195 if(x >= 0 && y >= 0 && x < XRES && y < YRES) {
196 g3d_fbpixels[y * XRES + x] = g3d_curcidx;