Merge branch 'master' of git+ssh://znh@git.freedesktop.org/git/mesa/mesa
[mesa.git] / src / mesa / drivers / dri / nouveau / nv04_swtcl.c
1 /*
2 * Copyright 2007 Stephane Marchesin. All Rights Reserved.
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sub license,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice (including the
12 * next paragraph) shall be included in all copies or substantial portions
13 * of the Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
18 * VIA, S3 GRAPHICS, AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
19 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
20 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21 * DEALINGS IN THE SOFTWARE.
22 */
23
24 /* Software TCL for NV04, NV05, NV06 */
25
26 #include <stdio.h>
27 #include <math.h>
28
29 #include "glheader.h"
30 #include "context.h"
31 #include "mtypes.h"
32 #include "macros.h"
33 #include "colormac.h"
34 #include "enums.h"
35
36 #include "swrast/swrast.h"
37 #include "swrast_setup/swrast_setup.h"
38 #include "tnl/t_context.h"
39 #include "tnl/t_pipeline.h"
40
41 #include "nouveau_swtcl.h"
42 #include "nv04_swtcl.h"
43 #include "nouveau_context.h"
44 #include "nouveau_span.h"
45 #include "nouveau_reg.h"
46 #include "nouveau_tex.h"
47 #include "nouveau_fifo.h"
48 #include "nouveau_msg.h"
49 #include "nouveau_object.h"
50
51 static void nv04RasterPrimitive( GLcontext *ctx, GLenum rprim, GLuint hwprim );
52 static void nv04RenderPrimitive( GLcontext *ctx, GLenum prim );
53 static void nv04ResetLineStipple( GLcontext *ctx );
54
55
56 static inline void nv04_2triangles(struct nouveau_context *nmesa,nouveauVertex* v0,nouveauVertex* v1,nouveauVertex* v2,nouveauVertex* v3,nouveauVertex* v4,nouveauVertex* v5)
57 {
58 BEGIN_RING_SIZE(NvSub3D,NV04_DX5_TEXTURED_TRIANGLE_TLVERTEX_SX(0xA),49);
59 OUT_RINGp(v0,8);
60 OUT_RINGp(v1,8);
61 OUT_RINGp(v2,8);
62 OUT_RINGp(v3,8);
63 OUT_RINGp(v4,8);
64 OUT_RINGp(v5,8);
65 OUT_RING(0xFEDCBA);
66 }
67
68 static inline void nv04_1triangle(struct nouveau_context *nmesa,nouveauVertex* v0,nouveauVertex* v1,nouveauVertex* v2)
69 {
70 BEGIN_RING_SIZE(NvSub3D,NV04_DX5_TEXTURED_TRIANGLE_TLVERTEX_SX(0xD),25);
71 OUT_RINGp(v0,8);
72 OUT_RINGp(v1,8);
73 OUT_RINGp(v2,8);
74 OUT_RING(0xFED);
75 }
76
77 static inline void nv04_1quad(struct nouveau_context *nmesa,nouveauVertex* v0,nouveauVertex* v1,nouveauVertex* v2,nouveauVertex* v3)
78 {
79 BEGIN_RING_SIZE(NvSub3D,NV04_DX5_TEXTURED_TRIANGLE_TLVERTEX_SX(0xC),33);
80 OUT_RINGp(v0,8);
81 OUT_RINGp(v1,8);
82 OUT_RINGp(v2,8);
83 OUT_RINGp(v3,8);
84 OUT_RING(0xFECEDC);
85 }
86
87 /**********************************************************************/
88 /* Render unclipped begin/end objects */
89 /**********************************************************************/
90
91 static void nv04_render_points_verts(GLcontext *ctx,GLuint start,GLuint count,GLuint flags)
92 {
93 // erm
94 }
95
96 static void nv04_render_lines_verts(GLcontext *ctx,GLuint start,GLuint count,GLuint flags)
97 {
98 // umm
99 }
100
101 static void nv04_render_line_strip_verts(GLcontext *ctx,GLuint start,GLuint count,GLuint flags)
102 {
103 // yeah
104 }
105
106 static void nv04_render_line_loop_verts(GLcontext *ctx,GLuint start,GLuint count,GLuint flags)
107 {
108 // right
109 }
110
111 static void nv04_render_triangles_verts(GLcontext *ctx,GLuint start,GLuint count,GLuint flags)
112 {
113 struct nouveau_context *nmesa = NOUVEAU_CONTEXT(ctx);
114 GLubyte *vertptr = (GLubyte *)nmesa->verts;
115 GLuint vertsize = nmesa->vertex_size;
116 int i;
117
118 for(i=start;i<count-5;i+=6)
119 nv04_2triangles(nmesa,
120 (nouveauVertex*)(vertptr+(i+0)*vertsize),
121 (nouveauVertex*)(vertptr+(i+1)*vertsize),
122 (nouveauVertex*)(vertptr+(i+2)*vertsize),
123 (nouveauVertex*)(vertptr+(i+3)*vertsize),
124 (nouveauVertex*)(vertptr+(i+4)*vertsize),
125 (nouveauVertex*)(vertptr+(i+5)*vertsize)
126 );
127 if (i!=count)
128 {
129 nv04_1triangle(nmesa,
130 (nouveauVertex*)(vertptr+(i+0)*vertsize),
131 (nouveauVertex*)(vertptr+(i+1)*vertsize),
132 (nouveauVertex*)(vertptr+(i+2)*vertsize)
133 );
134 i+=3;
135 }
136 if (i!=count)
137 printf("oops\n");
138 }
139
140 static void nv04_render_tri_strip_verts(GLcontext *ctx,GLuint start,GLuint count,GLuint flags)
141 {
142 struct nouveau_context *nmesa = NOUVEAU_CONTEXT(ctx);
143 GLubyte *vertptr = (GLubyte *)nmesa->verts;
144 GLuint vertsize = nmesa->vertex_size;
145 uint32_t striptbl[]={0x321210,0x543432,0x765654,0x987876,0xBA9A98,0xDCBCBA,0xFEDEDC};
146 int i,j;
147
148 for(i=start;i<count;i+=14)
149 {
150 int numvert=MIN2(16,count-i);
151 int numtri=numvert-2;
152 if (numvert<3)
153 break;
154
155 BEGIN_RING_SIZE(NvSub3D,NV04_DX5_TEXTURED_TRIANGLE_TLVERTEX_SX(0x0),numvert*8);
156 for(j=0;j<numvert;j++)
157 OUT_RINGp((nouveauVertex*)(vertptr+(i+j)*vertsize),8);
158
159 BEGIN_RING_SIZE(NvSub3D,NV04_DX5_TEXTURED_TRIANGLE_DRAW|NONINC_METHOD,(numtri+1)/2);
160 for(j=0;j<numtri/2;j++)
161 OUT_RING(striptbl[j]);
162 if (numtri%2)
163 OUT_RING(striptbl[numtri/2]&0xFFF);
164 }
165 }
166
167 static void nv04_render_tri_fan_verts(GLcontext *ctx,GLuint start,GLuint count,GLuint flags)
168 {
169 struct nouveau_context *nmesa = NOUVEAU_CONTEXT(ctx);
170 GLubyte *vertptr = (GLubyte *)nmesa->verts;
171 GLuint vertsize = nmesa->vertex_size;
172 uint32_t fantbl[]={0x320210,0x540430,0x760650,0x980870,0xBA0A90,0xDC0CB0,0xFE0ED0};
173 int i,j;
174
175 BEGIN_RING_SIZE(NvSub3D,NV04_DX5_TEXTURED_TRIANGLE_TLVERTEX_SX(0x0),8);
176 OUT_RINGp((nouveauVertex*)(vertptr+start*vertsize),8);
177
178 for(i=start+1;i<count;i+=14)
179 {
180 int numvert=MIN2(15,count-i);
181 int numtri=numvert-1;
182 if (numvert<3)
183 break;
184
185 BEGIN_RING_SIZE(NvSub3D,NV04_DX5_TEXTURED_TRIANGLE_TLVERTEX_SX(0x1),numvert*8);
186
187 for(j=0;j<numvert;j++)
188 OUT_RINGp((nouveauVertex*)(vertptr+(i+j)*vertsize),8);
189
190 BEGIN_RING_SIZE(NvSub3D,NV04_DX5_TEXTURED_TRIANGLE_DRAW|NONINC_METHOD,(numtri+1)/2);
191 for(j=0;j<numtri/2;j++)
192 OUT_RING(fantbl[j]);
193 if (numtri%2)
194 OUT_RING(fantbl[numtri/2]&0xFFF);
195 }
196 }
197
198 static void nv04_render_quads_verts(GLcontext *ctx,GLuint start,GLuint count,GLuint flags)
199 {
200 struct nouveau_context *nmesa = NOUVEAU_CONTEXT(ctx);
201 GLubyte *vertptr = (GLubyte *)nmesa->verts;
202 GLuint vertsize = nmesa->vertex_size;
203 int i;
204
205 for(i=start;i<count;i+=4)
206 nv04_1quad(nmesa,
207 (nouveauVertex*)(vertptr+(i+0)*vertsize),
208 (nouveauVertex*)(vertptr+(i+1)*vertsize),
209 (nouveauVertex*)(vertptr+(i+2)*vertsize),
210 (nouveauVertex*)(vertptr+(i+3)*vertsize)
211 );
212 }
213
214 static void nv04_render_noop_verts(GLcontext *ctx,GLuint start,GLuint count,GLuint flags)
215 {
216 }
217
218 static void (*nv04_render_tab_verts[GL_POLYGON+2])(GLcontext *,
219 GLuint,
220 GLuint,
221 GLuint) =
222 {
223 nv04_render_points_verts,
224 nv04_render_lines_verts,
225 nv04_render_line_loop_verts,
226 nv04_render_line_strip_verts,
227 nv04_render_triangles_verts,
228 nv04_render_tri_strip_verts,
229 nv04_render_tri_fan_verts,
230 nv04_render_quads_verts,
231 nv04_render_tri_strip_verts, //nv04_render_quad_strip_verts
232 nv04_render_tri_fan_verts, //nv04_render_poly_verts
233 nv04_render_noop_verts,
234 };
235
236
237 static void nv04_render_points_elts(GLcontext *ctx,GLuint start,GLuint count,GLuint flags)
238 {
239 // erm
240 }
241
242 static void nv04_render_lines_elts(GLcontext *ctx,GLuint start,GLuint count,GLuint flags)
243 {
244 // umm
245 }
246
247 static void nv04_render_line_strip_elts(GLcontext *ctx,GLuint start,GLuint count,GLuint flags)
248 {
249 // yeah
250 }
251
252 static void nv04_render_line_loop_elts(GLcontext *ctx,GLuint start,GLuint count,GLuint flags)
253 {
254 // right
255 }
256
257 static void nv04_render_triangles_elts(GLcontext *ctx,GLuint start,GLuint count,GLuint flags)
258 {
259 struct nouveau_context *nmesa = NOUVEAU_CONTEXT(ctx);
260 GLubyte *vertptr = (GLubyte *)nmesa->verts;
261 GLuint vertsize = nmesa->vertex_size;
262 const GLuint * const elt = TNL_CONTEXT(ctx)->vb.Elts;
263 int i;
264
265 for(i=start;i<count-5;i+=6)
266 nv04_2triangles(nmesa,
267 (nouveauVertex*)(vertptr+elt[i+0]*vertsize),
268 (nouveauVertex*)(vertptr+elt[i+1]*vertsize),
269 (nouveauVertex*)(vertptr+elt[i+2]*vertsize),
270 (nouveauVertex*)(vertptr+elt[i+3]*vertsize),
271 (nouveauVertex*)(vertptr+elt[i+4]*vertsize),
272 (nouveauVertex*)(vertptr+elt[i+5]*vertsize)
273 );
274 if (i!=count)
275 {
276 nv04_1triangle(nmesa,
277 (nouveauVertex*)(vertptr+elt[i+0]*vertsize),
278 (nouveauVertex*)(vertptr+elt[i+1]*vertsize),
279 (nouveauVertex*)(vertptr+elt[i+2]*vertsize)
280 );
281 i+=3;
282 }
283 if (i!=count)
284 printf("oops\n");
285 }
286
287 static void nv04_render_tri_strip_elts(GLcontext *ctx,GLuint start,GLuint count,GLuint flags)
288 {
289 struct nouveau_context *nmesa = NOUVEAU_CONTEXT(ctx);
290 GLubyte *vertptr = (GLubyte *)nmesa->verts;
291 GLuint vertsize = nmesa->vertex_size;
292 uint32_t striptbl[]={0x321210,0x543432,0x765654,0x987876,0xBA9A98,0xDCBCBA,0xFEDEDC};
293 const GLuint * const elt = TNL_CONTEXT(ctx)->vb.Elts;
294 int i,j;
295
296 for(i=start;i<count;i+=14)
297 {
298 int numvert=MIN2(16,count-i);
299 int numtri=numvert-2;
300 if (numvert<3)
301 break;
302
303 BEGIN_RING_SIZE(NvSub3D,NV04_DX5_TEXTURED_TRIANGLE_TLVERTEX_SX(0x0),numvert*8);
304 for(j=0;j<numvert;j++)
305 OUT_RINGp((nouveauVertex*)(vertptr+elt[i+j]*vertsize),8);
306
307 BEGIN_RING_SIZE(NvSub3D,NV04_DX5_TEXTURED_TRIANGLE_DRAW|NONINC_METHOD,(numtri+1)/2);
308 for(j=0;j<numtri/2;j++)
309 OUT_RING(striptbl[j]);
310 if (numtri%2)
311 OUT_RING(striptbl[numtri/2]&0xFFF);
312 }
313 }
314
315 static void nv04_render_tri_fan_elts(GLcontext *ctx,GLuint start,GLuint count,GLuint flags)
316 {
317 struct nouveau_context *nmesa = NOUVEAU_CONTEXT(ctx);
318 GLubyte *vertptr = (GLubyte *)nmesa->verts;
319 GLuint vertsize = nmesa->vertex_size;
320 uint32_t fantbl[]={0x320210,0x540430,0x760650,0x980870,0xBA0A90,0xDC0CB0,0xFE0ED0};
321 const GLuint * const elt = TNL_CONTEXT(ctx)->vb.Elts;
322 int i,j;
323
324 BEGIN_RING_SIZE(NvSub3D,NV04_DX5_TEXTURED_TRIANGLE_TLVERTEX_SX(0x0),8);
325 OUT_RINGp((nouveauVertex*)(vertptr+elt[start]*vertsize),8);
326
327 for(i=start+1;i<count;i+=14)
328 {
329 int numvert=MIN2(15,count-i);
330 int numtri=numvert-2;
331 if (numvert<3)
332 break;
333
334 BEGIN_RING_SIZE(NvSub3D,NV04_DX5_TEXTURED_TRIANGLE_TLVERTEX_SX(0x1),numvert*8);
335
336 for(j=0;j<numvert;j++)
337 OUT_RINGp((nouveauVertex*)(vertptr+elt[i+j]*vertsize),8);
338
339 BEGIN_RING_SIZE(NvSub3D,NV04_DX5_TEXTURED_TRIANGLE_DRAW|NONINC_METHOD,(numtri+1)/2);
340 for(j=0;j<numtri/2;j++)
341 OUT_RING(fantbl[j]);
342 if (numtri%2)
343 OUT_RING(fantbl[numtri/2]&0xFFF);
344 }
345 }
346
347 static void nv04_render_quads_elts(GLcontext *ctx,GLuint start,GLuint count,GLuint flags)
348 {
349 struct nouveau_context *nmesa = NOUVEAU_CONTEXT(ctx);
350 GLubyte *vertptr = (GLubyte *)nmesa->verts;
351 GLuint vertsize = nmesa->vertex_size;
352 const GLuint * const elt = TNL_CONTEXT(ctx)->vb.Elts;
353 int i;
354
355 for(i=start;i<count;i+=4)
356 nv04_1quad(nmesa,
357 (nouveauVertex*)(vertptr+elt[i+0]*vertsize),
358 (nouveauVertex*)(vertptr+elt[i+1]*vertsize),
359 (nouveauVertex*)(vertptr+elt[i+2]*vertsize),
360 (nouveauVertex*)(vertptr+elt[i+3]*vertsize)
361 );
362 }
363
364 static void nv04_render_noop_elts(GLcontext *ctx,GLuint start,GLuint count,GLuint flags)
365 {
366 }
367
368 static void (*nv04_render_tab_elts[GL_POLYGON+2])(GLcontext *,
369 GLuint,
370 GLuint,
371 GLuint) =
372 {
373 nv04_render_points_elts,
374 nv04_render_lines_elts,
375 nv04_render_line_loop_elts,
376 nv04_render_line_strip_elts,
377 nv04_render_triangles_elts,
378 nv04_render_tri_strip_elts,
379 nv04_render_tri_fan_elts,
380 nv04_render_quads_elts,
381 nv04_render_tri_strip_elts, // nv04_render_quad_strip_elts,
382 nv04_render_tri_fan_elts, // nv04_render_poly_elts,
383 nv04_render_noop_elts,
384 };
385
386
387 /**********************************************************************/
388 /* Choose render functions */
389 /**********************************************************************/
390
391
392 #define EMIT_ATTR( ATTR, STYLE ) \
393 do { \
394 nmesa->vertex_attrs[nmesa->vertex_attr_count].attrib = (ATTR); \
395 nmesa->vertex_attrs[nmesa->vertex_attr_count].format = (STYLE); \
396 nmesa->vertex_attr_count++; \
397 } while (0)
398
399 #define EMIT_PAD( N ) \
400 do { \
401 nmesa->vertex_attrs[nmesa->vertex_attr_count].attrib = 0; \
402 nmesa->vertex_attrs[nmesa->vertex_attr_count].format = EMIT_PAD; \
403 nmesa->vertex_attrs[nmesa->vertex_attr_count].offset = (N); \
404 nmesa->vertex_attr_count++; \
405 } while (0)
406
407
408 static void nv04ChooseRenderState(GLcontext *ctx)
409 {
410 TNLcontext *tnl = TNL_CONTEXT(ctx);
411
412 tnl->Driver.Render.PrimTabVerts = nv04_render_tab_verts;
413 tnl->Driver.Render.PrimTabElts = nv04_render_tab_elts;
414 tnl->Driver.Render.ClippedLine = NULL;
415 tnl->Driver.Render.ClippedPolygon = NULL;
416 }
417
418
419
420 static inline void nv04OutputVertexFormat(struct nouveau_context* nmesa)
421 {
422 GLcontext* ctx=nmesa->glCtx;
423 DECLARE_RENDERINPUTS(index);
424
425 /*
426 * Tell t_vertex about the vertex format
427 */
428 RENDERINPUTS_COPY(index, nmesa->render_inputs_bitset);
429
430 // SX SY SZ INVW
431 // FIXME : we use W instead of INVW, but since W=1 it doesn't matter
432 if (RENDERINPUTS_TEST(index, _TNL_ATTRIB_POS))
433 EMIT_ATTR(_TNL_ATTRIB_POS,EMIT_4F_VIEWPORT);
434 else
435 EMIT_PAD(4*sizeof(float));
436
437 // COLOR
438 if (RENDERINPUTS_TEST(index, _TNL_ATTRIB_COLOR0))
439 EMIT_ATTR(_TNL_ATTRIB_COLOR0,EMIT_4UB_4F_ABGR);
440 else
441 EMIT_PAD(4);
442
443 // SPECULAR
444 if (RENDERINPUTS_TEST(index, _TNL_ATTRIB_COLOR1))
445 EMIT_ATTR(_TNL_ATTRIB_COLOR1,EMIT_4UB_4F_ABGR);
446 else
447 EMIT_PAD(4);
448
449 // TEXTURE
450 if (RENDERINPUTS_TEST(index, _TNL_ATTRIB_TEX0))
451 EMIT_ATTR(_TNL_ATTRIB_TEX0,EMIT_2F);
452 else
453 EMIT_PAD(2*sizeof(float));
454
455 nmesa->vertex_size=_tnl_install_attrs( ctx,
456 nmesa->vertex_attrs,
457 nmesa->vertex_attr_count,
458 ctx->Viewport._WindowMap.m, 0 );
459 }
460
461
462 static void nv04ChooseVertexState( GLcontext *ctx )
463 {
464 struct nouveau_context *nmesa = NOUVEAU_CONTEXT(ctx);
465 TNLcontext *tnl = TNL_CONTEXT(ctx);
466 DECLARE_RENDERINPUTS(index);
467
468 RENDERINPUTS_COPY(index, tnl->render_inputs_bitset);
469 if (!RENDERINPUTS_EQUAL(index, nmesa->render_inputs_bitset))
470 {
471 RENDERINPUTS_COPY(nmesa->render_inputs_bitset, index);
472 nv04OutputVertexFormat(nmesa);
473 }
474 }
475
476
477 /**********************************************************************/
478 /* High level hooks for t_vb_render.c */
479 /**********************************************************************/
480
481
482 static void nv04RenderStart(GLcontext *ctx)
483 {
484 struct nouveau_context *nmesa = NOUVEAU_CONTEXT(ctx);
485
486 if (nmesa->new_state) {
487 nmesa->new_render_state |= nmesa->new_state;
488 }
489
490 if (nmesa->new_render_state) {
491 nv04ChooseVertexState(ctx);
492 nv04ChooseRenderState(ctx);
493 nmesa->new_render_state = 0;
494 }
495 }
496
497 static void nv04RenderFinish(GLcontext *ctx)
498 {
499 }
500
501
502 /* System to flush dma and emit state changes based on the rasterized
503 * primitive.
504 */
505 void nv04RasterPrimitive(GLcontext *ctx,
506 GLenum glprim,
507 GLuint hwprim)
508 {
509 struct nouveau_context *nmesa = NOUVEAU_CONTEXT(ctx);
510
511 assert (!nmesa->new_state);
512
513 if (hwprim != nmesa->current_primitive)
514 {
515 nmesa->current_primitive=hwprim;
516
517 }
518 }
519
520 static const GLuint hw_prim[GL_POLYGON+1] = {
521 GL_POINTS+1,
522 GL_LINES+1,
523 GL_LINE_STRIP+1,
524 GL_LINE_LOOP+1,
525 GL_TRIANGLES+1,
526 GL_TRIANGLE_STRIP+1,
527 GL_TRIANGLE_FAN+1,
528 GL_QUADS+1,
529 GL_QUAD_STRIP+1,
530 GL_POLYGON+1
531 };
532
533 /* Callback for mesa:
534 */
535 static void nv04RenderPrimitive( GLcontext *ctx, GLuint prim )
536 {
537 nv04RasterPrimitive( ctx, prim, hw_prim[prim] );
538 }
539
540 static void nv04ResetLineStipple( GLcontext *ctx )
541 {
542 /* FIXME do something here */
543 WARN_ONCE("Unimplemented nv04ResetLineStipple\n");
544 }
545
546
547 /**********************************************************************/
548 /* Initialization. */
549 /**********************************************************************/
550
551 void nv04TriInitFunctions(GLcontext *ctx)
552 {
553 struct nouveau_context *nmesa = NOUVEAU_CONTEXT(ctx);
554 TNLcontext *tnl = TNL_CONTEXT(ctx);
555
556 tnl->Driver.RunPipeline = nouveauRunPipeline;
557 tnl->Driver.Render.Start = nv04RenderStart;
558 tnl->Driver.Render.Finish = nv04RenderFinish;
559 tnl->Driver.Render.PrimitiveNotify = nv04RenderPrimitive;
560 tnl->Driver.Render.ResetLineStipple = nv04ResetLineStipple;
561 tnl->Driver.Render.BuildVertices = _tnl_build_vertices;
562 tnl->Driver.Render.CopyPV = _tnl_copy_pv;
563 tnl->Driver.Render.Interp = _tnl_interp;
564
565 _tnl_init_vertices( ctx, ctx->Const.MaxArrayLockSize + 12, 32 );
566
567 nmesa->verts = (GLubyte *)tnl->clipspace.vertex_buf;
568 }
569
570