Rev 72 | Details | Compare with Previous | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
56 | pj | 1 | /* $XFree86$ */ |
2 | /************************************************************************** |
||
3 | |||
4 | Copyright 2002 Tungsten Graphics Inc., Cedar Park, Texas. |
||
5 | |||
6 | All Rights Reserved. |
||
7 | |||
8 | Permission is hereby granted, free of charge, to any person obtaining a |
||
9 | copy of this software and associated documentation files (the "Software"), |
||
10 | to deal in the Software without restriction, including without limitation |
||
11 | on the rights to use, copy, modify, merge, publish, distribute, sub |
||
12 | license, and/or sell copies of the Software, and to permit persons to whom |
||
13 | the Software is furnished to do so, subject to the following conditions: |
||
14 | |||
15 | The above copyright notice and this permission notice (including the next |
||
16 | paragraph) shall be included in all copies or substantial portions of the |
||
17 | Software. |
||
18 | |||
19 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
||
20 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
||
21 | FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL |
||
22 | TUNGSTEN GRAPHICS AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, |
||
23 | DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR |
||
24 | OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE |
||
25 | USE OR OTHER DEALINGS IN THE SOFTWARE. |
||
26 | |||
27 | **************************************************************************/ |
||
28 | |||
29 | /* |
||
30 | * Authors: |
||
31 | * Keith Whitwell <keith@tungstengraphics.com> |
||
32 | * |
||
33 | */ |
||
34 | #include "api_noop.h" |
||
35 | #include "api_arrayelt.h" |
||
36 | #include "context.h" |
||
37 | #include "imports.h" |
||
38 | #include "mmath.h" |
||
39 | #include "mtypes.h" |
||
40 | #include "enums.h" |
||
41 | #include "glapi.h" |
||
42 | #include "colormac.h" |
||
43 | #include "light.h" |
||
44 | #include "state.h" |
||
45 | #include "vtxfmt.h" |
||
46 | |||
72 | giacomo | 47 | #include "tnl.h" |
48 | #include "t_context.h" |
||
49 | #include "t_array_api.h" |
||
56 | pj | 50 | |
51 | static void _tnl_FlushVertices( GLcontext *, GLuint ); |
||
52 | |||
53 | |||
54 | void tnl_copy_to_current( GLcontext *ctx ) |
||
55 | { |
||
56 | TNLcontext *tnl = TNL_CONTEXT(ctx); |
||
57 | GLuint flag = tnl->vertex_format; |
||
58 | GLint i; |
||
59 | |||
60 | assert(ctx->Driver.NeedFlush & FLUSH_UPDATE_CURRENT); |
||
61 | |||
62 | for (i = 0 ; i < 16 ; i++) |
||
63 | if (flag & (1<<i)) |
||
64 | COPY_4FV( ctx->Current.Attrib[i], tnl->attribptr[i] ); |
||
65 | |||
66 | if (flag & VERT_BIT_INDEX) |
||
67 | ctx->Current.Index = tnl->indexptr[0]; |
||
68 | |||
69 | if (flag & VERT_BIT_EDGEFLAG) |
||
70 | ctx->Current.EdgeFlag = tnl->edgeflagptr[0]; |
||
71 | |||
72 | if (flag & VERT_BIT_MATERIAL) { |
||
73 | _mesa_update_material( ctx, |
||
74 | IM->Material[IM->LastMaterial], |
||
75 | IM->MaterialOrMask ); |
||
76 | |||
77 | tnl->Driver.NotifyMaterialChange( ctx ); |
||
78 | } |
||
79 | |||
80 | |||
81 | ctx->Driver.NeedFlush &= ~FLUSH_UPDATE_CURRENT; |
||
82 | } |
||
83 | |||
84 | static GLboolean discreet_gl_prim[GL_POLYGON+1] = { |
||
85 | 1, /* 0 points */ |
||
86 | 1, /* 1 lines */ |
||
87 | 0, /* 2 line_strip */ |
||
88 | 0, /* 3 line_loop */ |
||
89 | 1, /* 4 tris */ |
||
90 | 0, /* 5 tri_fan */ |
||
91 | 0, /* 6 tri_strip */ |
||
92 | 1, /* 7 quads */ |
||
93 | 0, /* 8 quadstrip */ |
||
94 | 0, /* 9 poly */ |
||
95 | }; |
||
96 | |||
97 | /* Optimize the primitive list: ONLY FOR EXECUTE ATM |
||
98 | */ |
||
99 | static void optimize_prims( TNLcontext *tnl ) |
||
100 | { |
||
101 | int i, j; |
||
102 | |||
103 | if (tnl->nrprims <= 1) |
||
104 | return; |
||
105 | |||
106 | for (j = 0, i = 1 ; i < tnl->nrprims; i++) { |
||
107 | int pj = tnl->primlist[j].prim & 0xf; |
||
108 | int pi = tnl->primlist[i].prim & 0xf; |
||
109 | |||
110 | if (pj == pi && discreet_gl_prim[pj] && |
||
111 | tnl->primlist[i].start == tnl->primlist[j].end) { |
||
112 | tnl->primlist[j].end = tnl->primlist[i].end; |
||
113 | } |
||
114 | else { |
||
115 | j++; |
||
116 | if (j != i) tnl->primlist[j] = tnl->primlist[i]; |
||
117 | } |
||
118 | } |
||
119 | |||
120 | tnl->nrprims = j+1; |
||
121 | } |
||
122 | |||
123 | |||
124 | /* Bind vertex buffer pointers, run pipeline: |
||
125 | */ |
||
126 | static void flush_prims( TNLcontext *tnl ) |
||
127 | { |
||
128 | int i,j; |
||
129 | |||
130 | tnl->dma.current.ptr = tnl->dma.current.start += |
||
131 | (tnl->initial_counter - tnl->counter) * tnl->vertex_size * 4; |
||
132 | |||
133 | tnl->tcl.vertex_format = tnl->vertex_format; |
||
134 | tnl->tcl.aos_components[0] = &tmp; |
||
135 | tnl->tcl.nr_aos_components = 1; |
||
136 | tnl->dma.flush = 0; |
||
137 | |||
138 | tnl->Driver.RunPipeline( ... ); |
||
139 | |||
140 | tnl->nrprims = 0; |
||
141 | } |
||
142 | |||
143 | |||
144 | static void start_prim( TNLcontext *tnl, GLuint mode ) |
||
145 | { |
||
146 | if (MESA_VERBOSE & DEBUG_VFMT) |
||
147 | _mesa_debug(NULL, "%s %d\n", __FUNCTION__, |
||
148 | tnl->initial_counter - tnl->counter); |
||
149 | |||
150 | tnl->primlist[tnl->nrprims].start = tnl->initial_counter - tnl->counter; |
||
151 | tnl->primlist[tnl->nrprims].prim = mode; |
||
152 | } |
||
153 | |||
154 | static void note_last_prim( TNLcontext *tnl, GLuint flags ) |
||
155 | { |
||
156 | if (MESA_VERBOSE & DEBUG_VFMT) |
||
157 | _mesa_debug(NULL, "%s %d\n", __FUNCTION__, |
||
158 | tnl->initial_counter - tnl->counter); |
||
159 | |||
160 | if (tnl->prim[0] != GL_POLYGON+1) { |
||
161 | tnl->primlist[tnl->nrprims].prim |= flags; |
||
162 | tnl->primlist[tnl->nrprims].end = tnl->initial_counter - tnl->counter; |
||
163 | |||
164 | if (++tnl->nrprims == TNL_MAX_PRIMS) |
||
165 | flush_prims( tnl ); |
||
166 | } |
||
167 | } |
||
168 | |||
169 | |||
170 | static void copy_vertex( TNLcontext *tnl, GLuint n, GLfloat *dst ) |
||
171 | { |
||
172 | GLuint i; |
||
173 | GLfloat *src = (GLfloat *)(tnl->dma.current.address + |
||
174 | tnl->dma.current.ptr + |
||
175 | (tnl->primlist[tnl->nrprims].start + n) * |
||
176 | tnl->vertex_size * 4); |
||
177 | |||
178 | if (MESA_VERBOSE & DEBUG_VFMT) |
||
179 | _mesa_debug(NULL, "copy_vertex %d\n", |
||
180 | tnl->primlist[tnl->nrprims].start + n); |
||
181 | |||
182 | for (i = 0 ; i < tnl->vertex_size; i++) { |
||
183 | dst[i] = src[i]; |
||
184 | } |
||
185 | } |
||
186 | |||
187 | static GLuint copy_wrapped_verts( TNLcontext *tnl, GLfloat (*tmp)[15] ) |
||
188 | { |
||
189 | GLuint ovf, i; |
||
190 | GLuint nr = (tnl->initial_counter - tnl->counter) - tnl->primlist[tnl->nrprims].start; |
||
191 | |||
192 | if (MESA_VERBOSE & DEBUG_VFMT) |
||
193 | _mesa_debug(NULL, "%s %d verts\n", __FUNCTION__, nr); |
||
194 | |||
195 | switch( tnl->prim[0] ) |
||
196 | { |
||
197 | case GL_POINTS: |
||
198 | return 0; |
||
199 | case GL_LINES: |
||
200 | ovf = nr&1; |
||
201 | for (i = 0 ; i < ovf ; i++) |
||
202 | copy_vertex( tnl, nr-ovf+i, tmp[i] ); |
||
203 | return i; |
||
204 | case GL_TRIANGLES: |
||
205 | ovf = nr%3; |
||
206 | for (i = 0 ; i < ovf ; i++) |
||
207 | copy_vertex( tnl, nr-ovf+i, tmp[i] ); |
||
208 | return i; |
||
209 | case GL_QUADS: |
||
210 | ovf = nr&3; |
||
211 | for (i = 0 ; i < ovf ; i++) |
||
212 | copy_vertex( tnl, nr-ovf+i, tmp[i] ); |
||
213 | return i; |
||
214 | case GL_LINE_STRIP: |
||
215 | if (nr == 0) |
||
216 | return 0; |
||
217 | copy_vertex( tnl, nr-1, tmp[0] ); |
||
218 | return 1; |
||
219 | case GL_LINE_LOOP: |
||
220 | case GL_TRIANGLE_FAN: |
||
221 | case GL_POLYGON: |
||
222 | if (nr == 0) |
||
223 | return 0; |
||
224 | else if (nr == 1) { |
||
225 | copy_vertex( tnl, 0, tmp[0] ); |
||
226 | return 1; |
||
227 | } else { |
||
228 | copy_vertex( tnl, 0, tmp[0] ); |
||
229 | copy_vertex( tnl, nr-1, tmp[1] ); |
||
230 | return 2; |
||
231 | } |
||
232 | case GL_TRIANGLE_STRIP: |
||
233 | ovf = MIN2( nr-1, 2 ); |
||
234 | for (i = 0 ; i < ovf ; i++) |
||
235 | copy_vertex( tnl, nr-ovf+i, tmp[i] ); |
||
236 | return i; |
||
237 | case GL_QUAD_STRIP: |
||
238 | ovf = MIN2( nr-1, 2 ); |
||
239 | if (nr > 2) ovf += nr&1; |
||
240 | for (i = 0 ; i < ovf ; i++) |
||
241 | copy_vertex( tnl, nr-ovf+i, tmp[i] ); |
||
242 | return i; |
||
243 | default: |
||
244 | assert(0); |
||
245 | return 0; |
||
246 | } |
||
247 | } |
||
248 | |||
249 | |||
250 | |||
251 | /* Extend for vertex-format changes on wrap: |
||
252 | */ |
||
253 | static void wrap_buffer( void ) |
||
254 | { |
||
255 | TNLcontext *tnl = tnl->tnl; |
||
256 | GLfloat tmp[3][15]; |
||
257 | GLuint i, nrverts; |
||
258 | |||
259 | if (MESA_VERBOSE & (DEBUG_VFMT|DEBUG_PRIMS)) |
||
260 | _mesa_debug(NULL, "%s %d\n", __FUNCTION__, |
||
261 | tnl->initial_counter - tnl->counter); |
||
262 | |||
263 | /* Don't deal with parity. *** WONT WORK FOR COMPILE |
||
264 | */ |
||
265 | if ((((tnl->initial_counter - tnl->counter) - |
||
266 | tnl->primlist[tnl->nrprims].start) & 1)) { |
||
267 | tnl->counter++; |
||
268 | tnl->initial_counter++; |
||
269 | return; |
||
270 | } |
||
271 | |||
272 | /* Copy vertices out of dma: |
||
273 | */ |
||
274 | nrverts = copy_dma_verts( tnl, tmp ); |
||
275 | |||
276 | if (MESA_VERBOSE & DEBUG_VFMT) |
||
277 | _mesa_debug(NULL, "%d vertices to copy\n", nrverts); |
||
278 | |||
279 | |||
280 | /* Finish the prim at this point: |
||
281 | */ |
||
282 | note_last_prim( tnl, 0 ); |
||
283 | flush_prims( tnl ); |
||
284 | |||
285 | /* Reset counter, dmaptr |
||
286 | */ |
||
287 | tnl->dmaptr = (int *)(tnl->dma.current.ptr + tnl->dma.current.address); |
||
288 | tnl->counter = (tnl->dma.current.end - tnl->dma.current.ptr) / |
||
289 | (tnl->vertex_size * 4); |
||
290 | tnl->counter--; |
||
291 | tnl->initial_counter = tnl->counter; |
||
292 | tnl->notify = wrap_buffer; |
||
293 | |||
294 | tnl->dma.flush = flush_prims; |
||
295 | start_prim( tnl, tnl->prim[0] ); |
||
296 | |||
297 | |||
298 | /* Reemit saved vertices |
||
299 | * *** POSSIBLY IN NEW FORMAT |
||
300 | * --> Can't always extend at end of vertex? |
||
301 | */ |
||
302 | for (i = 0 ; i < nrverts; i++) { |
||
303 | if (MESA_VERBOSE & DEBUG_VERTS) { |
||
304 | int j; |
||
305 | _mesa_debug(NULL, "re-emit vertex %d to %p\n", i, tnl->dmaptr); |
||
306 | if (MESA_VERBOSE & DEBUG_VERBOSE) |
||
307 | for (j = 0 ; j < tnl->vertex_size; j++) |
||
308 | _mesa_debug(NULL, "\t%08x/%f\n", *(int*)&tmp[i][j], tmp[i][j]); |
||
309 | } |
||
310 | |||
311 | memcpy( tnl->dmaptr, tmp[i], tnl->vertex_size * 4 ); |
||
312 | tnl->dmaptr += tnl->vertex_size; |
||
313 | tnl->counter--; |
||
314 | } |
||
315 | } |
||
316 | |||
317 | |||
318 | |||
319 | /* Always follow data, don't try to predict what's necessary. |
||
320 | */ |
||
321 | static GLboolean check_vtx_fmt( GLcontext *ctx ) |
||
322 | { |
||
323 | TNLcontext *tnl = TNL_CONTEXT(ctx); |
||
324 | |||
325 | if (ctx->Driver.NeedFlush & FLUSH_UPDATE_CURRENT) |
||
326 | ctx->Driver.FlushVertices( ctx, FLUSH_UPDATE_CURRENT ); |
||
327 | |||
328 | |||
329 | TNL_NEWPRIM(tnl); |
||
330 | tnl->vertex_format = VERT_BIT_POS; |
||
331 | tnl->prim = &ctx->Driver.CurrentExecPrimitive; |
||
332 | |||
333 | |||
334 | /* Currently allow the full 4 components per attrib. Can use the |
||
335 | * mechanism from radeon driver color handling to reduce this (and |
||
336 | * also to store ubyte colors where these are incoming). This |
||
337 | * won't work for compile mode. |
||
338 | * |
||
339 | * Only adding components when they are first received eliminates |
||
340 | * the need for displaylist fixup, as there are no 'empty' slots |
||
341 | * at the start of buffers. |
||
342 | */ |
||
343 | for (i = 0 ; i < 16 ; i++) { |
||
344 | if (ind & (1<<i)) { |
||
345 | tnl->attribptr[i] = &tnl->vertex[tnl->vertex_size].f; |
||
346 | tnl->vertex_size += 4; |
||
347 | tnl->attribptr[i][0] = ctx->Current.Attrib[i][0]; |
||
348 | tnl->attribptr[i][1] = ctx->Current.Attrib[i][1]; |
||
349 | tnl->attribptr[i][2] = ctx->Current.Attrib[i][2]; |
||
350 | tnl->attribptr[i][3] = ctx->Current.Attrib[i][3]; |
||
351 | } |
||
352 | else |
||
353 | tnl->attribptr[i] = ctx->Current.Attrib[i]; |
||
354 | } |
||
355 | |||
356 | /* Edgeflag, Index: |
||
357 | */ |
||
358 | for (i = 16 ; i < 18 ; i++) |
||
359 | ; |
||
360 | |||
361 | /* Materials: |
||
362 | */ |
||
363 | for (i = 18 ; i < 28 ; i++) |
||
364 | ; |
||
365 | |||
366 | /* Eval: |
||
367 | */ |
||
368 | for (i = 28 ; i < 29 ; i++) |
||
369 | ; |
||
370 | |||
371 | |||
372 | if (tnl->installed_vertex_format != tnl->vertex_format) { |
||
373 | if (MESA_VERBOSE & DEBUG_VFMT) |
||
374 | _mesa_debug(NULL, "reinstall on vertex_format change\n"); |
||
375 | _mesa_install_exec_vtxfmt( ctx, &tnl->vtxfmt ); |
||
376 | tnl->installed_vertex_format = tnl->vertex_format; |
||
377 | } |
||
378 | |||
379 | return GL_TRUE; |
||
380 | } |
||
381 | |||
382 | |||
383 | void _tnl_InvalidateVtxfmt( GLcontext *ctx ) |
||
384 | { |
||
385 | tnl->recheck = GL_TRUE; |
||
386 | tnl->fell_back = GL_FALSE; |
||
387 | } |
||
388 | |||
389 | |||
390 | |||
391 | |||
392 | static void _tnl_ValidateVtxfmt( GLcontext *ctx ) |
||
393 | { |
||
394 | if (MESA_VERBOSE & DEBUG_VFMT) |
||
395 | _mesa_debug(NULL, "%s\n", __FUNCTION__); |
||
396 | |||
397 | if (ctx->Driver.NeedFlush) |
||
398 | ctx->Driver.FlushVertices( ctx, ctx->Driver.NeedFlush ); |
||
399 | |||
400 | tnl->recheck = GL_FALSE; |
||
401 | |||
402 | if (check_vtx_fmt( ctx )) { |
||
403 | if (!tnl->installed) { |
||
404 | if (MESA_VERBOSE & DEBUG_VFMT) |
||
405 | _mesa_debug(NULL, "reinstall (new install)\n"); |
||
406 | |||
407 | _mesa_install_exec_vtxfmt( ctx, &tnl->vtxfmt ); |
||
408 | ctx->Driver.FlushVertices = _tnl_FlushVertices; |
||
409 | tnl->installed = GL_TRUE; |
||
410 | } |
||
411 | else |
||
412 | _mesa_debug(NULL, "%s: already installed", __FUNCTION__); |
||
413 | } |
||
414 | else { |
||
415 | if (MESA_VERBOSE & DEBUG_VFMT) |
||
416 | _mesa_debug(NULL, "%s: failed\n", __FUNCTION__); |
||
417 | |||
418 | if (tnl->installed) { |
||
419 | if (tnl->tnl->dma.flush) |
||
420 | tnl->tnl->dma.flush( tnl->tnl ); |
||
421 | _tnl_wakeup_exec( ctx ); |
||
422 | tnl->installed = GL_FALSE; |
||
423 | } |
||
424 | } |
||
425 | } |
||
426 | |||
427 | |||
428 | |||
429 | |||
430 | |||
431 | /* Begin/End |
||
432 | */ |
||
433 | static void _tnl_Begin( GLenum mode ) |
||
434 | { |
||
435 | GLcontext *ctx = tnl->context; |
||
436 | TNLcontext *tnl = tnl->tnl; |
||
437 | |||
438 | if (MESA_VERBOSE & DEBUG_VFMT) |
||
439 | _mesa_debug(NULL, "%s\n", __FUNCTION__); |
||
440 | |||
441 | if (mode > GL_POLYGON) { |
||
442 | _mesa_error( ctx, GL_INVALID_ENUM, "glBegin" ); |
||
443 | return; |
||
444 | } |
||
445 | |||
446 | if (tnl->prim[0] != GL_POLYGON+1) { |
||
447 | _mesa_error( ctx, GL_INVALID_OPERATION, "glBegin" ); |
||
448 | return; |
||
449 | } |
||
450 | |||
451 | if (ctx->NewState) |
||
452 | _mesa_update_state( ctx ); |
||
453 | |||
454 | if (tnl->recheck) |
||
455 | _tnl_ValidateVtxfmt( ctx ); |
||
456 | |||
457 | if (tnl->dma.flush && tnl->counter < 12) { |
||
458 | if (MESA_VERBOSE & DEBUG_VFMT) |
||
459 | _mesa_debug(NULL, "%s: flush almost-empty buffers\n", __FUNCTION__); |
||
460 | flush_prims( tnl ); |
||
461 | } |
||
462 | |||
463 | if (!tnl->dma.flush) { |
||
464 | if (tnl->dma.current.ptr + 12*tnl->vertex_size*4 > |
||
465 | tnl->dma.current.end) { |
||
466 | TNL_NEWPRIM( tnl ); |
||
467 | _tnl_RefillCurrentDmaRegion( tnl ); |
||
468 | } |
||
469 | |||
470 | tnl->dmaptr = (int *)(tnl->dma.current.address + tnl->dma.current.ptr); |
||
471 | tnl->counter = (tnl->dma.current.end - tnl->dma.current.ptr) / |
||
472 | (tnl->vertex_size * 4); |
||
473 | tnl->counter--; |
||
474 | tnl->initial_counter = tnl->counter; |
||
475 | tnl->notify = wrap_buffer; |
||
476 | tnl->dma.flush = flush_prims; |
||
477 | tnl->context->Driver.NeedFlush |= FLUSH_STORED_VERTICES; |
||
478 | } |
||
479 | |||
480 | |||
481 | tnl->prim[0] = mode; |
||
482 | start_prim( tnl, mode | PRIM_BEGIN ); |
||
483 | } |
||
484 | |||
485 | |||
486 | |||
487 | |||
488 | |||
489 | static void _tnl_End( void ) |
||
490 | { |
||
491 | TNLcontext *tnl = tnl->tnl; |
||
492 | GLcontext *ctx = tnl->context; |
||
493 | |||
494 | if (MESA_VERBOSE & DEBUG_VFMT) |
||
495 | _mesa_debug(NULL, "%s\n", __FUNCTION__); |
||
496 | |||
497 | if (tnl->prim[0] == GL_POLYGON+1) { |
||
498 | _mesa_error( ctx, GL_INVALID_OPERATION, "glEnd" ); |
||
499 | return; |
||
500 | } |
||
501 | |||
502 | note_last_prim( tnl, PRIM_END ); |
||
503 | tnl->prim[0] = GL_POLYGON+1; |
||
504 | } |
||
505 | |||
506 | |||
507 | static void _tnl_FlushVertices( GLcontext *ctx, GLuint flags ) |
||
508 | { |
||
509 | if (MESA_VERBOSE & DEBUG_VFMT) |
||
510 | _mesa_debug(NULL, "%s\n", __FUNCTION__); |
||
511 | |||
512 | assert(tnl->installed); |
||
513 | |||
514 | if (flags & FLUSH_UPDATE_CURRENT) { |
||
515 | _tnl_copy_to_current( ctx ); |
||
516 | if (MESA_VERBOSE & DEBUG_VFMT) |
||
517 | _mesa_debug(NULL, "reinstall on update_current\n"); |
||
518 | _mesa_install_exec_vtxfmt( ctx, &tnl->vtxfmt ); |
||
519 | ctx->Driver.NeedFlush &= ~FLUSH_UPDATE_CURRENT; |
||
520 | } |
||
521 | |||
522 | if (flags & FLUSH_STORED_VERTICES) { |
||
523 | TNLcontext *tnl = TNL_CONTEXT( ctx ); |
||
524 | assert (tnl->dma.flush == 0 || |
||
525 | tnl->dma.flush == flush_prims); |
||
526 | if (tnl->dma.flush == flush_prims) |
||
527 | flush_prims( TNL_CONTEXT( ctx ) ); |
||
528 | ctx->Driver.NeedFlush &= ~FLUSH_STORED_VERTICES; |
||
529 | } |
||
530 | } |
||
531 | |||
532 | |||
533 | |||
534 | /* At this point, don't expect very many versions of each function to |
||
535 | * be generated, so not concerned about freeing them? |
||
536 | */ |
||
537 | |||
538 | |||
539 | static void _tnl_InitVtxfmt( GLcontext *ctx ) |
||
540 | { |
||
541 | GLvertexformat *vfmt = &(tnl->vtxfmt); |
||
542 | |||
543 | MEMSET( vfmt, 0, sizeof(GLvertexformat) ); |
||
544 | |||
545 | /* Hook in chooser functions for codegen, etc: |
||
546 | */ |
||
547 | _tnl_InitVtxfmtChoosers( vfmt ); |
||
548 | |||
549 | /* Handled fully in supported states, but no codegen: |
||
550 | */ |
||
551 | vfmt->ArrayElement = _ae_loopback_array_elt; /* generic helper */ |
||
552 | vfmt->Rectf = _mesa_noop_Rectf; /* generic helper */ |
||
553 | vfmt->Begin = _tnl_Begin; |
||
554 | vfmt->End = _tnl_End; |
||
555 | |||
556 | tnl->context = ctx; |
||
557 | tnl->tnl = TNL_CONTEXT(ctx); |
||
558 | tnl->prim = &ctx->Driver.CurrentExecPrimitive; |
||
559 | tnl->primflags = 0; |
||
560 | |||
561 | make_empty_list( &tnl->dfn_cache.Vertex2f ); |
||
562 | make_empty_list( &tnl->dfn_cache.Vertex2fv ); |
||
563 | make_empty_list( &tnl->dfn_cache.Vertex3f ); |
||
564 | make_empty_list( &tnl->dfn_cache.Vertex3fv ); |
||
565 | make_empty_list( &tnl->dfn_cache.Color4ub ); |
||
566 | make_empty_list( &tnl->dfn_cache.Color4ubv ); |
||
567 | make_empty_list( &tnl->dfn_cache.Color3ub ); |
||
568 | make_empty_list( &tnl->dfn_cache.Color3ubv ); |
||
569 | make_empty_list( &tnl->dfn_cache.Color4f ); |
||
570 | make_empty_list( &tnl->dfn_cache.Color4fv ); |
||
571 | make_empty_list( &tnl->dfn_cache.Color3f ); |
||
572 | make_empty_list( &tnl->dfn_cache.Color3fv ); |
||
573 | make_empty_list( &tnl->dfn_cache.SecondaryColor3fEXT ); |
||
574 | make_empty_list( &tnl->dfn_cache.SecondaryColor3fvEXT ); |
||
575 | make_empty_list( &tnl->dfn_cache.SecondaryColor3ubEXT ); |
||
576 | make_empty_list( &tnl->dfn_cache.SecondaryColor3ubvEXT ); |
||
577 | make_empty_list( &tnl->dfn_cache.Normal3f ); |
||
578 | make_empty_list( &tnl->dfn_cache.Normal3fv ); |
||
579 | make_empty_list( &tnl->dfn_cache.TexCoord2f ); |
||
580 | make_empty_list( &tnl->dfn_cache.TexCoord2fv ); |
||
581 | make_empty_list( &tnl->dfn_cache.TexCoord1f ); |
||
582 | make_empty_list( &tnl->dfn_cache.TexCoord1fv ); |
||
583 | make_empty_list( &tnl->dfn_cache.MultiTexCoord2fARB ); |
||
584 | make_empty_list( &tnl->dfn_cache.MultiTexCoord2fvARB ); |
||
585 | make_empty_list( &tnl->dfn_cache.MultiTexCoord1fARB ); |
||
586 | make_empty_list( &tnl->dfn_cache.MultiTexCoord1fvARB ); |
||
587 | |||
588 | _tnl_InitCodegen( &tnl->codegen ); |
||
589 | } |
||
590 | |||
591 | static void free_funcs( struct dynfn *l ) |
||
592 | { |
||
593 | struct dynfn *f, *tmp; |
||
594 | foreach_s (f, tmp, l) { |
||
595 | remove_from_list( f ); |
||
596 | ALIGN_FREE( f->code ); |
||
597 | FREE( f ); |
||
598 | } |
||
599 | } |
||
600 | |||
601 | |||
602 | static void _tnl_DestroyVtxfmt( GLcontext *ctx ) |
||
603 | { |
||
604 | count_funcs(); |
||
605 | free_funcs( &tnl->dfn_cache.Vertex2f ); |
||
606 | free_funcs( &tnl->dfn_cache.Vertex2fv ); |
||
607 | free_funcs( &tnl->dfn_cache.Vertex3f ); |
||
608 | free_funcs( &tnl->dfn_cache.Vertex3fv ); |
||
609 | free_funcs( &tnl->dfn_cache.Color4ub ); |
||
610 | free_funcs( &tnl->dfn_cache.Color4ubv ); |
||
611 | free_funcs( &tnl->dfn_cache.Color3ub ); |
||
612 | free_funcs( &tnl->dfn_cache.Color3ubv ); |
||
613 | free_funcs( &tnl->dfn_cache.Color4f ); |
||
614 | free_funcs( &tnl->dfn_cache.Color4fv ); |
||
615 | free_funcs( &tnl->dfn_cache.Color3f ); |
||
616 | free_funcs( &tnl->dfn_cache.Color3fv ); |
||
617 | free_funcs( &tnl->dfn_cache.SecondaryColor3ubEXT ); |
||
618 | free_funcs( &tnl->dfn_cache.SecondaryColor3ubvEXT ); |
||
619 | free_funcs( &tnl->dfn_cache.SecondaryColor3fEXT ); |
||
620 | free_funcs( &tnl->dfn_cache.SecondaryColor3fvEXT ); |
||
621 | free_funcs( &tnl->dfn_cache.Normal3f ); |
||
622 | free_funcs( &tnl->dfn_cache.Normal3fv ); |
||
623 | free_funcs( &tnl->dfn_cache.TexCoord2f ); |
||
624 | free_funcs( &tnl->dfn_cache.TexCoord2fv ); |
||
625 | free_funcs( &tnl->dfn_cache.TexCoord1f ); |
||
626 | free_funcs( &tnl->dfn_cache.TexCoord1fv ); |
||
627 | free_funcs( &tnl->dfn_cache.MultiTexCoord2fARB ); |
||
628 | free_funcs( &tnl->dfn_cache.MultiTexCoord2fvARB ); |
||
629 | free_funcs( &tnl->dfn_cache.MultiTexCoord1fARB ); |
||
630 | free_funcs( &tnl->dfn_cache.MultiTexCoord1fvARB ); |
||
631 | } |
||
632 |