rev |
line source |
nuclear@0
|
1 #include <stdio.h>
|
nuclear@0
|
2 #include <stdlib.h>
|
nuclear@0
|
3 #include <string.h>
|
nuclear@9
|
4 #include <limits.h>
|
nuclear@0
|
5 #include <assert.h>
|
nuclear@0
|
6 #include "mingl.h"
|
nuclear@0
|
7 #include "mglimpl.h"
|
nuclear@0
|
8
|
nuclear@0
|
9
|
nuclear@25
|
10 #ifdef RAST_FLOAT
|
nuclear@25
|
11 typedef struct vertex VERTEX;
|
nuclear@25
|
12 #else
|
nuclear@25
|
13 typedef struct fixed_vertex VERTEX;
|
nuclear@25
|
14 #endif
|
nuclear@25
|
15
|
nuclear@25
|
16 static VERTEX *vleft, *vright;
|
nuclear@0
|
17 static struct framebuffer *fb;
|
nuclear@0
|
18 static struct state *st;
|
nuclear@0
|
19
|
nuclear@0
|
20
|
nuclear@0
|
21 #define SCAN_EDGE scan_edge_flat
|
nuclear@0
|
22 #define SCAN_LINE scan_line_flat
|
nuclear@0
|
23 #undef INTERP_DEPTH
|
nuclear@0
|
24 #undef INTERP_ENERGY
|
nuclear@3
|
25 #undef INTERP_TEX
|
nuclear@0
|
26 #include "scantmpl.h"
|
nuclear@0
|
27 #undef SCAN_EDGE
|
nuclear@0
|
28 #undef SCAN_LINE
|
nuclear@0
|
29
|
nuclear@0
|
30 #define SCAN_EDGE scan_edge_z
|
nuclear@0
|
31 #define SCAN_LINE scan_line_z
|
nuclear@0
|
32 #define INTERP_DEPTH
|
nuclear@0
|
33 #undef INTERP_ENERGY
|
nuclear@3
|
34 #undef INTERP_TEX
|
nuclear@0
|
35 #include "scantmpl.h"
|
nuclear@0
|
36 #undef SCAN_EDGE
|
nuclear@0
|
37 #undef SCAN_LINE
|
nuclear@0
|
38
|
nuclear@0
|
39 #define SCAN_EDGE scan_edge_e
|
nuclear@0
|
40 #define SCAN_LINE scan_line_e
|
nuclear@0
|
41 #undef INTERP_DEPTH
|
nuclear@0
|
42 #define INTERP_ENERGY
|
nuclear@3
|
43 #undef INTERP_TEX
|
nuclear@0
|
44 #include "scantmpl.h"
|
nuclear@0
|
45 #undef SCAN_EDGE
|
nuclear@0
|
46 #undef SCAN_LINE
|
nuclear@0
|
47
|
nuclear@0
|
48 #define SCAN_EDGE scan_edge_ze
|
nuclear@0
|
49 #define SCAN_LINE scan_line_ze
|
nuclear@0
|
50 #define INTERP_DEPTH
|
nuclear@0
|
51 #define INTERP_ENERGY
|
nuclear@3
|
52 #undef INTERP_TEX
|
nuclear@0
|
53 #include "scantmpl.h"
|
nuclear@0
|
54 #undef SCAN_EDGE
|
nuclear@0
|
55 #undef SCAN_LINE
|
nuclear@0
|
56
|
nuclear@3
|
57 #define SCAN_EDGE scan_edge_t
|
nuclear@3
|
58 #define SCAN_LINE scan_line_t
|
nuclear@3
|
59 #undef INTERP_DEPTH
|
nuclear@3
|
60 #undef INTERP_ENERGY
|
nuclear@3
|
61 #define INTERP_TEX
|
nuclear@3
|
62 #include "scantmpl.h"
|
nuclear@3
|
63 #undef SCAN_EDGE
|
nuclear@3
|
64 #undef SCAN_LINE
|
nuclear@3
|
65
|
nuclear@3
|
66 #define SCAN_EDGE scan_edge_zt
|
nuclear@3
|
67 #define SCAN_LINE scan_line_zt
|
nuclear@3
|
68 #define INTERP_DEPTH
|
nuclear@3
|
69 #undef INTERP_ENERGY
|
nuclear@3
|
70 #define INTERP_TEX
|
nuclear@3
|
71 #include "scantmpl.h"
|
nuclear@3
|
72 #undef SCAN_EDGE
|
nuclear@3
|
73 #undef SCAN_LINE
|
nuclear@3
|
74
|
nuclear@3
|
75 #define SCAN_EDGE scan_edge_et
|
nuclear@3
|
76 #define SCAN_LINE scan_line_et
|
nuclear@3
|
77 #undef INTERP_DEPTH
|
nuclear@3
|
78 #define INTERP_ENERGY
|
nuclear@3
|
79 #define INTERP_TEX
|
nuclear@3
|
80 #include "scantmpl.h"
|
nuclear@3
|
81 #undef SCAN_EDGE
|
nuclear@3
|
82 #undef SCAN_LINE
|
nuclear@3
|
83
|
nuclear@3
|
84 #define SCAN_EDGE scan_edge_zet
|
nuclear@3
|
85 #define SCAN_LINE scan_line_zet
|
nuclear@3
|
86 #define INTERP_DEPTH
|
nuclear@3
|
87 #define INTERP_ENERGY
|
nuclear@3
|
88 #define INTERP_TEX
|
nuclear@3
|
89 #include "scantmpl.h"
|
nuclear@3
|
90 #undef SCAN_EDGE
|
nuclear@3
|
91 #undef SCAN_LINE
|
nuclear@3
|
92
|
nuclear@3
|
93
|
nuclear@25
|
94 static void (*scan_edge)(VERTEX*, VERTEX*);
|
nuclear@0
|
95 static void (*scan_line)(int, unsigned char*);
|
nuclear@0
|
96
|
nuclear@25
|
97
|
nuclear@0
|
98 int mgl_rast_init(struct state *state, struct framebuffer *fbuf)
|
nuclear@0
|
99 {
|
nuclear@0
|
100 fb = fbuf;
|
nuclear@0
|
101 st = state;
|
nuclear@0
|
102
|
nuclear@0
|
103 if(!(vleft = malloc(fb->height * sizeof *vleft))) {
|
nuclear@0
|
104 return -1;
|
nuclear@0
|
105 }
|
nuclear@0
|
106 if(!(vright = malloc(fb->height * sizeof *vright))) {
|
nuclear@0
|
107 free(vleft);
|
nuclear@0
|
108 return -1;
|
nuclear@0
|
109 }
|
nuclear@0
|
110
|
nuclear@0
|
111 scan_edge = scan_edge_flat;
|
nuclear@0
|
112 scan_line = scan_line_flat;
|
nuclear@0
|
113
|
nuclear@0
|
114 return 0;
|
nuclear@0
|
115 }
|
nuclear@0
|
116
|
nuclear@0
|
117 void mgl_rast_cleanup(void)
|
nuclear@0
|
118 {
|
nuclear@0
|
119 free(vleft);
|
nuclear@0
|
120 free(vright);
|
nuclear@0
|
121 }
|
nuclear@0
|
122
|
nuclear@0
|
123 void mgl_rast_prepare(void)
|
nuclear@0
|
124 {
|
nuclear@25
|
125 static void (*sedge[])(VERTEX*, VERTEX*) = {
|
nuclear@3
|
126 /* tez */
|
nuclear@3
|
127 scan_edge_flat, /* 000 */
|
nuclear@3
|
128 scan_edge_z, /* 001 */
|
nuclear@3
|
129 scan_edge_e, /* 010 */
|
nuclear@3
|
130 scan_edge_ze, /* 011 */
|
nuclear@3
|
131 scan_edge_t, /* 100 */
|
nuclear@3
|
132 scan_edge_zt, /* 101 */
|
nuclear@3
|
133 scan_edge_et, /* 110 */
|
nuclear@3
|
134 scan_edge_zet /* 111 */
|
nuclear@0
|
135 };
|
nuclear@0
|
136 static void (*sline[])(int, unsigned char*) = {
|
nuclear@3
|
137 /* tez */
|
nuclear@3
|
138 scan_line_flat, /* 000 */
|
nuclear@3
|
139 scan_line_z, /* 001 */
|
nuclear@3
|
140 scan_line_e, /* 010 */
|
nuclear@3
|
141 scan_line_ze, /* 011 */
|
nuclear@3
|
142 scan_line_t, /* 100 */
|
nuclear@3
|
143 scan_line_zt, /* 101 */
|
nuclear@3
|
144 scan_line_et, /* 110 */
|
nuclear@3
|
145 scan_line_zet /* 111 */
|
nuclear@0
|
146 };
|
nuclear@0
|
147 int bits = 0;
|
nuclear@0
|
148
|
nuclear@28
|
149 if(IS_ENABLED(st->flags, MGL_TEXTURE_2D) && st->tex.pixels) {
|
nuclear@3
|
150 bits |= 4;
|
nuclear@3
|
151 }
|
nuclear@28
|
152 if(IS_ENABLED(st->flags, MGL_SMOOTH)) {
|
nuclear@0
|
153 bits |= 2;
|
nuclear@0
|
154 }
|
nuclear@28
|
155 if(IS_ENABLED(st->flags, MGL_DEPTH_TEST) && fb->zbuf) {
|
nuclear@0
|
156 bits |= 1;
|
nuclear@0
|
157 }
|
nuclear@0
|
158
|
nuclear@0
|
159 scan_edge = sedge[bits];
|
nuclear@0
|
160 scan_line = sline[bits];
|
nuclear@0
|
161 }
|
nuclear@0
|
162
|
nuclear@0
|
163 void mgl_draw_point(struct vertex *v)
|
nuclear@0
|
164 {
|
nuclear@0
|
165 int x = (int)ROUND(v->pos.x);
|
nuclear@0
|
166 int y = (int)ROUND(v->pos.y);
|
nuclear@0
|
167
|
nuclear@0
|
168 if(x >= 0 && x < fb->width && y >= 0 && y < fb->height) {
|
nuclear@0
|
169 int cidx = v->cidx + v->energy * st->col_range;
|
nuclear@0
|
170 fb->pixels[y * fb->width + x] = cidx;
|
nuclear@0
|
171 }
|
nuclear@0
|
172 }
|
nuclear@0
|
173
|
nuclear@0
|
174 void mgl_draw_line(struct vertex *v0, struct vertex *v1)
|
nuclear@0
|
175 {
|
nuclear@0
|
176 /* TODO */
|
nuclear@0
|
177 fprintf(stderr, "draw_line unimplemented\n");
|
nuclear@0
|
178 abort();
|
nuclear@0
|
179 }
|
nuclear@0
|
180
|
nuclear@0
|
181 void mgl_draw_poly(struct vertex *v, int numv)
|
nuclear@0
|
182 {
|
nuclear@25
|
183 #ifdef RAST_FLOAT
|
nuclear@0
|
184 int ybeg, yend, i;
|
nuclear@0
|
185 unsigned char *sline;
|
nuclear@0
|
186
|
nuclear@0
|
187 ybeg = fb->height;
|
nuclear@0
|
188 yend = 0;
|
nuclear@0
|
189
|
nuclear@0
|
190 for(i=0; i<numv; i++) {
|
nuclear@0
|
191 struct vertex *v0 = v + i;
|
nuclear@0
|
192 struct vertex *v1 = v + (i + 1) % numv;
|
nuclear@0
|
193 int y = (int)ROUND(v0->pos.y);
|
nuclear@0
|
194
|
nuclear@0
|
195 scan_edge(v0, v1);
|
nuclear@0
|
196
|
nuclear@0
|
197 if(y > yend) yend = y;
|
nuclear@0
|
198 if(y < ybeg) ybeg = y;
|
nuclear@0
|
199 }
|
nuclear@0
|
200
|
nuclear@0
|
201 if(ybeg < 0) ybeg = 0;
|
nuclear@0
|
202 if(yend >= fb->height) yend = fb->height - 1;
|
nuclear@0
|
203
|
nuclear@0
|
204 sline = fb->pixels + ybeg * fb->width;
|
nuclear@0
|
205 for(i=ybeg; i<yend; i++) {
|
nuclear@0
|
206 scan_line(i, sline);
|
nuclear@0
|
207 sline += fb->width;
|
nuclear@0
|
208 }
|
nuclear@25
|
209 #else
|
nuclear@25
|
210 int ybeg, yend, i;
|
nuclear@25
|
211 unsigned char *sline;
|
nuclear@25
|
212
|
nuclear@25
|
213 ybeg = fb->height;
|
nuclear@25
|
214 yend = 0;
|
nuclear@25
|
215
|
nuclear@25
|
216 for(i=0; i<numv; i++) {
|
nuclear@25
|
217 int y;
|
nuclear@25
|
218 struct vertex *v0 = v + i;
|
nuclear@25
|
219 struct vertex *v1 = v + (i + 1) % numv;
|
nuclear@25
|
220 struct fixed_vertex vx0, vx1;
|
nuclear@25
|
221
|
nuclear@25
|
222 vertex_to_fixedvertex(*v0, vx0);
|
nuclear@25
|
223 vertex_to_fixedvertex(*v1, vx1);
|
nuclear@25
|
224
|
nuclear@25
|
225 y = fixed_round(vx0.pos.y);
|
nuclear@25
|
226
|
nuclear@25
|
227 scan_edge(&vx0, &vx1);
|
nuclear@25
|
228
|
nuclear@25
|
229 if(y > yend) yend = y;
|
nuclear@25
|
230 if(y < ybeg) ybeg = y;
|
nuclear@25
|
231 }
|
nuclear@25
|
232
|
nuclear@25
|
233 if(ybeg < 0) ybeg = 0;
|
nuclear@25
|
234 if(yend >= fb->height) yend = fb->height - 1;
|
nuclear@25
|
235
|
nuclear@25
|
236 sline = fb->pixels + ybeg * fb->width;
|
nuclear@25
|
237 for(i=ybeg; i<yend; i++) {
|
nuclear@25
|
238 scan_line(i, sline);
|
nuclear@25
|
239 sline += fb->width;
|
nuclear@25
|
240 }
|
nuclear@25
|
241 #endif
|
nuclear@0
|
242 }
|