VirtualBox

source: vbox/trunk/src/VBox/GuestHost/OpenGL/state_tracker/state_client.c@ 21563

Last change on this file since 21563 was 21563, checked in by vboxsync, 15 years ago

crOpenGL: fix some rare crashes when using server side VBOs

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 61.0 KB
Line 
1/* Copyright (c) 2001, Stanford University
2 * All rights reserved
3 *
4 * See the file LICENSE.txt for information on redistributing this software.
5 */
6
7/*
8 * This file manages all the client-side state including:
9 * Pixel pack/unpack parameters
10 * Vertex arrays
11 */
12
13
14#include "cr_mem.h"
15#include "state.h"
16#include "state/cr_statetypes.h"
17#include "state/cr_statefuncs.h"
18#include "state_internals.h"
19
20#define GLCLIENT_BIT_ALLOC 1024
21
22
23const CRPixelPackState crStateNativePixelPacking = {
24 0, /* rowLength */
25 0, /* skipRows */
26 0, /* skipPixels */
27 1, /* alignment */
28 0, /* imageHeight */
29 0, /* skipImages */
30 GL_FALSE, /* swapBytes */
31 GL_FALSE, /* psLSBFirst */
32};
33
34
35void crStateClientInitBits (CRClientBits *c)
36{
37 int i;
38
39 /* XXX why GLCLIENT_BIT_ALLOC? */
40 c->v = (CRbitvalue *) crCalloc(GLCLIENT_BIT_ALLOC*sizeof(CRbitvalue));
41 c->n = (CRbitvalue *) crCalloc(GLCLIENT_BIT_ALLOC*sizeof(CRbitvalue));
42 c->c = (CRbitvalue *) crCalloc(GLCLIENT_BIT_ALLOC*sizeof(CRbitvalue));
43 c->s = (CRbitvalue *) crCalloc(GLCLIENT_BIT_ALLOC*sizeof(CRbitvalue));
44 c->i = (CRbitvalue *) crCalloc(GLCLIENT_BIT_ALLOC*sizeof(CRbitvalue));
45 for ( i = 0; i < CR_MAX_TEXTURE_UNITS; i++ )
46 c->t[i] = (CRbitvalue *) crCalloc(GLCLIENT_BIT_ALLOC*sizeof(CRbitvalue));
47 c->e = (CRbitvalue *) crCalloc(GLCLIENT_BIT_ALLOC*sizeof(CRbitvalue));
48 c->f = (CRbitvalue *) crCalloc(GLCLIENT_BIT_ALLOC*sizeof(CRbitvalue));
49
50#ifdef CR_NV_vertex_program
51 for ( i = 0; i < CR_MAX_VERTEX_ATTRIBS; i++ )
52 c->a[i] = (CRbitvalue *) crCalloc(GLCLIENT_BIT_ALLOC*sizeof(CRbitvalue));
53#endif
54}
55
56void crStateClientDestroy(CRClientState *c)
57{
58}
59
60void crStateClientInit(CRClientState *c)
61{
62 unsigned int i;
63
64 /* pixel pack/unpack */
65 c->unpack.rowLength = 0;
66 c->unpack.skipRows = 0;
67 c->unpack.skipPixels = 0;
68 c->unpack.skipImages = 0;
69 c->unpack.alignment = 4;
70 c->unpack.imageHeight = 0;
71 c->unpack.swapBytes = GL_FALSE;
72 c->unpack.psLSBFirst = GL_FALSE;
73 c->pack.rowLength = 0;
74 c->pack.skipRows = 0;
75 c->pack.skipPixels = 0;
76 c->pack.skipImages = 0;
77 c->pack.alignment = 4;
78 c->pack.imageHeight = 0;
79 c->pack.swapBytes = GL_FALSE;
80 c->pack.psLSBFirst = GL_FALSE;
81
82 /* ARB multitexture */
83 c->curClientTextureUnit = 0;
84
85 /* vertex array */
86 c->array.v.p = NULL;
87 c->array.v.size = 4;
88 c->array.v.type = GL_FLOAT;
89 c->array.v.stride = 0;
90 c->array.v.enabled = 0;
91#ifdef CR_ARB_vertex_buffer_object2
92 c->array.v.buffer = g->bufferobject.vertexBuffer;
93#endif
94
95 /* color array */
96 c->array.c.p = NULL;
97 c->array.c.size = 4;
98 c->array.c.type = GL_FLOAT;
99 c->array.c.stride = 0;
100 c->array.c.enabled = 0;
101#ifdef CR_ARB_vertex_buffer_object2
102 c->array.c.buffer = g->bufferobject.vertexBuffer;
103#endif
104
105 /* fog array */
106 c->array.f.p = NULL;
107 c->array.f.size = 0;
108 c->array.f.type = GL_FLOAT;
109 c->array.f.stride = 0;
110 c->array.f.enabled = 0;
111#ifdef CR_ARB_vertex_buffer_object2
112 c->array.f.buffer = g->bufferobject.vertexBuffer;
113#endif
114
115 /* secondary color array */
116 c->array.s.p = NULL;
117 c->array.s.size = 3;
118 c->array.s.type = GL_FLOAT;
119 c->array.s.stride = 0;
120 c->array.s.enabled = 0;
121#ifdef CR_ARB_vertex_buffer_object2
122 c->array.s.buffer = g->bufferobject.vertexBuffer;
123#endif
124
125 /* edge flag array */
126 c->array.e.p = NULL;
127 c->array.e.size = 0;
128 c->array.e.type = GL_FLOAT;
129 c->array.e.stride = 0;
130 c->array.e.enabled = 0;
131#ifdef CR_ARB_vertex_buffer_object2
132 c->array.e.buffer = g->bufferobject.vertexBuffer;
133#endif
134
135 /* color index array */
136 c->array.i.p = NULL;
137 c->array.i.size = 0;
138 c->array.i.type = GL_FLOAT;
139 c->array.i.stride = 0;
140 c->array.i.enabled = 0;
141#ifdef CR_ARB_vertex_buffer_object2
142 c->array.i.buffer = g->bufferobject.vertexBuffer;
143#endif
144
145 /* normal array */
146 c->array.n.p = NULL;
147 c->array.n.size = 4;
148 c->array.n.type = GL_FLOAT;
149 c->array.n.stride = 0;
150 c->array.n.enabled = 0;
151#ifdef CR_ARB_vertex_buffer_object2
152 c->array.n.buffer = g->bufferobject.vertexBuffer;
153#endif
154
155 /* texcoord arrays */
156 for (i = 0 ; i < CR_MAX_TEXTURE_UNITS ; i++)
157 {
158 c->array.t[i].p = NULL;
159 c->array.t[i].size = 4;
160 c->array.t[i].type = GL_FLOAT;
161 c->array.t[i].stride = 0;
162 c->array.t[i].enabled = 0;
163#ifdef CR_ARB_vertex_buffer_object2
164 c->array.t[i].buffer = g->bufferobject.vertexBuffer;
165#endif
166 }
167
168 /* generic vertex attributes */
169#ifdef CR_NV_vertex_program
170 for (i = 0; i < CR_MAX_VERTEX_ATTRIBS; i++) {
171 c->array.a[i].enabled = GL_FALSE;
172 c->array.a[i].type = 0;
173 c->array.a[i].size = 0;
174 c->array.a[i].stride = 0;
175#ifdef CR_ARB_vertex_buffer_object2
176 c->array.a[i].buffer = g->bufferobject.vertexBuffer;
177#endif
178 }
179#endif
180}
181
182
183/*
184 * PixelStore functions are here, not in state_pixel.c because this
185 * is client-side state, like vertex arrays.
186 */
187
188void STATE_APIENTRY crStatePixelStoref (GLenum pname, GLfloat param)
189{
190
191 /* The GL SPEC says I can do this on page 76. */
192 switch( pname )
193 {
194 case GL_PACK_SWAP_BYTES:
195 case GL_PACK_LSB_FIRST:
196 case GL_UNPACK_SWAP_BYTES:
197 case GL_UNPACK_LSB_FIRST:
198 crStatePixelStorei( pname, param == 0.0f ? 0: 1 );
199 break;
200 default:
201 crStatePixelStorei( pname, (GLint) param );
202 break;
203 }
204}
205
206void STATE_APIENTRY crStatePixelStorei (GLenum pname, GLint param)
207{
208 CRContext *g = GetCurrentContext();
209 CRClientState *c = &(g->client);
210 CRStateBits *sb = GetCurrentBits();
211 CRClientBits *cb = &(sb->client);
212
213 if (g->current.inBeginEnd)
214 {
215 crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, "PixelStore{if} called in Begin/End");
216 return;
217 }
218
219 FLUSH();
220
221 switch(pname) {
222 case GL_PACK_SWAP_BYTES:
223 c->pack.swapBytes = (GLboolean) param;
224 DIRTY(cb->pack, g->neg_bitid);
225 break;
226 case GL_PACK_LSB_FIRST:
227 c->pack.psLSBFirst = (GLboolean) param;
228 DIRTY(cb->pack, g->neg_bitid);
229 break;
230 case GL_PACK_ROW_LENGTH:
231 if (param < 0.0f)
232 {
233 crStateError(__LINE__, __FILE__, GL_INVALID_VALUE, "Negative Row Length: %f", param);
234 return;
235 }
236 c->pack.rowLength = param;
237 DIRTY(cb->pack, g->neg_bitid);
238 break;
239#ifdef CR_OPENGL_VERSION_1_2
240 case GL_PACK_IMAGE_HEIGHT:
241 if (param < 0.0f)
242 {
243 crStateError(__LINE__, __FILE__, GL_INVALID_VALUE, "Negative Image Height: %f", param);
244 return;
245 }
246 c->pack.imageHeight = param;
247 DIRTY(cb->pack, g->neg_bitid);
248 break;
249#endif
250 case GL_PACK_SKIP_IMAGES:
251 if (param < 0.0f)
252 {
253 crStateError(__LINE__, __FILE__, GL_INVALID_VALUE, "Negative Skip Images: %f", param);
254 return;
255 }
256 c->pack.skipImages = param;
257 DIRTY(cb->pack, g->neg_bitid);
258 break;
259 case GL_PACK_SKIP_PIXELS:
260 if (param < 0.0f)
261 {
262 crStateError(__LINE__, __FILE__, GL_INVALID_VALUE, "Negative Skip Pixels: %f", param);
263 return;
264 }
265 c->pack.skipPixels = param;
266 DIRTY(cb->pack, g->neg_bitid);
267 break;
268 case GL_PACK_SKIP_ROWS:
269 if (param < 0.0f)
270 {
271 crStateError(__LINE__, __FILE__, GL_INVALID_VALUE, "Negative Row Skip: %f", param);
272 return;
273 }
274 c->pack.skipRows = param;
275 DIRTY(cb->pack, g->neg_bitid);
276 break;
277 case GL_PACK_ALIGNMENT:
278 if (((GLint) param) != 1 &&
279 ((GLint) param) != 2 &&
280 ((GLint) param) != 4 &&
281 ((GLint) param) != 8)
282 {
283 crStateError(__LINE__, __FILE__, GL_INVALID_VALUE, "Invalid Alignment: %f", param);
284 return;
285 }
286 c->pack.alignment = param;
287 DIRTY(cb->pack, g->neg_bitid);
288 break;
289
290 case GL_UNPACK_SWAP_BYTES:
291 c->unpack.swapBytes = (GLboolean) param;
292 DIRTY(cb->unpack, g->neg_bitid);
293 break;
294 case GL_UNPACK_LSB_FIRST:
295 c->unpack.psLSBFirst = (GLboolean) param;
296 DIRTY(cb->unpack, g->neg_bitid);
297 break;
298 case GL_UNPACK_ROW_LENGTH:
299 if (param < 0.0f)
300 {
301 crStateError(__LINE__, __FILE__, GL_INVALID_VALUE, "Negative Row Length: %f", param);
302 return;
303 }
304 c->unpack.rowLength = param;
305 DIRTY(cb->unpack, g->neg_bitid);
306 break;
307#ifdef CR_OPENGL_VERSION_1_2
308 case GL_UNPACK_IMAGE_HEIGHT:
309 if (param < 0.0f)
310 {
311 crStateError(__LINE__, __FILE__, GL_INVALID_VALUE, "Negative Image Height: %f", param);
312 return;
313 }
314 c->unpack.imageHeight = param;
315 DIRTY(cb->unpack, g->neg_bitid);
316 break;
317#endif
318 case GL_UNPACK_SKIP_IMAGES:
319 if (param < 0.0f)
320 {
321 crStateError(__LINE__, __FILE__, GL_INVALID_VALUE, "Negative Skip Images: %f", param);
322 return;
323 }
324 c->unpack.skipImages = param;
325 DIRTY(cb->unpack, g->neg_bitid);
326 break;
327 case GL_UNPACK_SKIP_PIXELS:
328 if (param < 0.0f)
329 {
330 crStateError(__LINE__, __FILE__, GL_INVALID_VALUE, "Negative Skip Pixels: %f", param);
331 return;
332 }
333 c->unpack.skipPixels = param;
334 DIRTY(cb->unpack, g->neg_bitid);
335 break;
336 case GL_UNPACK_SKIP_ROWS:
337 if (param < 0.0f)
338 {
339 crStateError(__LINE__, __FILE__, GL_INVALID_VALUE, "Negative Row Skip: %f", param);
340 return;
341 }
342 c->unpack.skipRows = param;
343 DIRTY(cb->unpack, g->neg_bitid);
344 break;
345 case GL_UNPACK_ALIGNMENT:
346 if (((GLint) param) != 1 &&
347 ((GLint) param) != 2 &&
348 ((GLint) param) != 4 &&
349 ((GLint) param) != 8)
350 {
351 crStateError(__LINE__, __FILE__, GL_INVALID_VALUE, "Invalid Alignment: %f", param);
352 return;
353 }
354 c->unpack.alignment = param;
355 DIRTY(cb->unpack, g->neg_bitid);
356 break;
357 default:
358 crStateError(__LINE__, __FILE__, GL_INVALID_VALUE, "Unknown glPixelStore Pname: %d", pname);
359 return;
360 }
361 DIRTY(cb->dirty, g->neg_bitid);
362}
363
364
365static void setClientState(CRClientState *c, CRClientBits *cb,
366 CRbitvalue *neg_bitid, GLenum array, GLboolean state)
367{
368 CRContext *g = GetCurrentContext();
369
370 switch (array)
371 {
372#ifdef CR_NV_vertex_program
373 case GL_VERTEX_ATTRIB_ARRAY0_NV:
374 case GL_VERTEX_ATTRIB_ARRAY1_NV:
375 case GL_VERTEX_ATTRIB_ARRAY2_NV:
376 case GL_VERTEX_ATTRIB_ARRAY3_NV:
377 case GL_VERTEX_ATTRIB_ARRAY4_NV:
378 case GL_VERTEX_ATTRIB_ARRAY5_NV:
379 case GL_VERTEX_ATTRIB_ARRAY6_NV:
380 case GL_VERTEX_ATTRIB_ARRAY7_NV:
381 case GL_VERTEX_ATTRIB_ARRAY8_NV:
382 case GL_VERTEX_ATTRIB_ARRAY9_NV:
383 case GL_VERTEX_ATTRIB_ARRAY10_NV:
384 case GL_VERTEX_ATTRIB_ARRAY11_NV:
385 case GL_VERTEX_ATTRIB_ARRAY12_NV:
386 case GL_VERTEX_ATTRIB_ARRAY13_NV:
387 case GL_VERTEX_ATTRIB_ARRAY14_NV:
388 case GL_VERTEX_ATTRIB_ARRAY15_NV:
389 {
390 const GLuint i = array - GL_VERTEX_ATTRIB_ARRAY0_NV;
391 c->array.a[i].enabled = state;
392 }
393 break;
394#endif
395 case GL_VERTEX_ARRAY:
396 c->array.v.enabled = state;
397 break;
398 case GL_COLOR_ARRAY:
399 c->array.c.enabled = state;
400 break;
401 case GL_NORMAL_ARRAY:
402 c->array.n.enabled = state;
403 break;
404 case GL_INDEX_ARRAY:
405 c->array.i.enabled = state;
406 break;
407 case GL_TEXTURE_COORD_ARRAY:
408 c->array.t[c->curClientTextureUnit].enabled = state;
409 break;
410 case GL_EDGE_FLAG_ARRAY:
411 c->array.e.enabled = state;
412 break;
413#ifdef CR_EXT_fog_coord
414 case GL_FOG_COORDINATE_ARRAY_EXT:
415 c->array.f.enabled = state;
416 break;
417#endif
418#ifdef CR_EXT_secondary_color
419 case GL_SECONDARY_COLOR_ARRAY_EXT:
420 if( g->extensions.EXT_secondary_color ){
421 c->array.s.enabled = state;
422 }
423 else {
424 crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "Invalid Enum passed to Enable/Disable Client State: SECONDARY_COLOR_ARRAY_EXT - EXT_secondary_color is not enabled." );
425 return;
426 }
427 break;
428#endif
429 default:
430 crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "Invalid Enum passed to Enable/Disable Client State: 0x%x", array );
431 return;
432 }
433 DIRTY(cb->dirty, neg_bitid);
434 DIRTY(cb->enableClientState, neg_bitid);
435}
436
437void STATE_APIENTRY crStateEnableClientState (GLenum array)
438{
439 CRContext *g = GetCurrentContext();
440 CRClientState *c = &(g->client);
441 CRStateBits *sb = GetCurrentBits();
442 CRClientBits *cb = &(sb->client);
443
444 FLUSH();
445
446 setClientState(c, cb, g->neg_bitid, array, GL_TRUE);
447}
448
449void STATE_APIENTRY crStateDisableClientState (GLenum array)
450{
451 CRContext *g = GetCurrentContext();
452 CRClientState *c = &(g->client);
453 CRStateBits *sb = GetCurrentBits();
454 CRClientBits *cb = &(sb->client);
455
456 FLUSH();
457
458 setClientState(c, cb, g->neg_bitid, array, GL_FALSE);
459}
460
461static void
462crStateClientSetPointer(CRClientPointer *cp, GLint size,
463 GLenum type, GLboolean normalized,
464 GLsizei stride, const GLvoid *pointer)
465{
466 CRContext *g = GetCurrentContext();
467
468 cp->p = (unsigned char *) pointer;
469 cp->size = size;
470 cp->type = type;
471 cp->normalized = normalized;
472
473 /* Calculate the bytes per index for address calculation */
474 cp->bytesPerIndex = size;
475 switch (type)
476 {
477 case GL_BYTE:
478 case GL_UNSIGNED_BYTE:
479 break;
480 case GL_SHORT:
481 case GL_UNSIGNED_SHORT:
482 cp->bytesPerIndex *= sizeof(GLshort);
483 break;
484 case GL_INT:
485 case GL_UNSIGNED_INT:
486 cp->bytesPerIndex *= sizeof(GLint);
487 break;
488 case GL_FLOAT:
489 cp->bytesPerIndex *= sizeof(GLfloat);
490 break;
491 case GL_DOUBLE:
492 cp->bytesPerIndex *= sizeof(GLdouble);
493 break;
494 default:
495 crStateError( __LINE__, __FILE__, GL_INVALID_VALUE,
496 "Unknown type of vertex array: %d", type );
497 return;
498 }
499
500 /*
501 ** Note: If stride==0 then we set the
502 ** stride equal address offset
503 ** therefore stride can never equal
504 ** zero.
505 */
506 if (stride)
507 cp->stride = stride;
508 else
509 cp->stride = cp->bytesPerIndex;
510
511#ifdef CR_ARB_vertex_buffer_object
512 cp->buffer = g->bufferobject.arrayBuffer;
513#endif
514}
515
516void STATE_APIENTRY crStateVertexPointer(GLint size, GLenum type,
517 GLsizei stride, const GLvoid *p)
518{
519 CRContext *g = GetCurrentContext();
520 CRClientState *c = &(g->client);
521 CRStateBits *sb = GetCurrentBits();
522 CRClientBits *cb = &(sb->client);
523
524 FLUSH();
525
526 if (size != 2 && size != 3 && size != 4)
527 {
528 crStateError(__LINE__, __FILE__, GL_INVALID_VALUE, "glVertexPointer: invalid size: %d", size);
529 return;
530 }
531 if (type != GL_SHORT && type != GL_INT &&
532 type != GL_FLOAT && type != GL_DOUBLE)
533 {
534 crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glVertexPointer: invalid type: 0x%x", type);
535 return;
536 }
537 if (stride < 0)
538 {
539 crStateError(__LINE__, __FILE__, GL_INVALID_VALUE, "glVertexPointer: stride was negative: %d", stride);
540 return;
541 }
542
543 crStateClientSetPointer(&(c->array.v), size, type, GL_FALSE, stride, p);
544 DIRTY(cb->dirty, g->neg_bitid);
545 DIRTY(cb->clientPointer, g->neg_bitid);
546 DIRTY(cb->v, g->neg_bitid);
547}
548
549void STATE_APIENTRY crStateColorPointer(GLint size, GLenum type,
550 GLsizei stride, const GLvoid *p)
551{
552 CRContext *g = GetCurrentContext();
553 CRClientState *c = &(g->client);
554 CRStateBits *sb = GetCurrentBits();
555 CRClientBits *cb = &(sb->client);
556
557 FLUSH();
558
559 if (size != 3 && size != 4)
560 {
561 crStateError(__LINE__, __FILE__, GL_INVALID_VALUE, "glColorPointer: invalid size: %d", size);
562 return;
563 }
564 if (type != GL_BYTE && type != GL_UNSIGNED_BYTE &&
565 type != GL_SHORT && type != GL_UNSIGNED_SHORT &&
566 type != GL_INT && type != GL_UNSIGNED_INT &&
567 type != GL_FLOAT && type != GL_DOUBLE)
568 {
569 crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glColorPointer: invalid type: 0x%x", type);
570 return;
571 }
572 if (stride < 0)
573 {
574 crStateError(__LINE__, __FILE__, GL_INVALID_VALUE, "glColorPointer: stride was negative: %d", stride);
575 return;
576 }
577
578 crStateClientSetPointer(&(c->array.c), size, type, GL_TRUE, stride, p);
579 DIRTY(cb->dirty, g->neg_bitid);
580 DIRTY(cb->clientPointer, g->neg_bitid);
581 DIRTY(cb->c, g->neg_bitid);
582}
583
584void STATE_APIENTRY crStateSecondaryColorPointerEXT(GLint size,
585 GLenum type, GLsizei stride, const GLvoid *p)
586{
587 CRContext *g = GetCurrentContext();
588 CRClientState *c = &(g->client);
589 CRStateBits *sb = GetCurrentBits();
590 CRClientBits *cb = &(sb->client);
591
592 FLUSH();
593
594 if ( !g->extensions.EXT_secondary_color )
595 {
596 crError( "glSecondaryColorPointerEXT called but EXT_secondary_color is disabled." );
597 return;
598 }
599
600 /*Note: According to opengl spec, only size==3 should be accepted here.
601 *But it turns out that most drivers accept size==4 here as well, and 4th value
602 *could even be accessed in shaders code.
603 *Having a strict check here, leads to difference between guest and host gpu states, which
604 *in turn could lead to crashes when using server side VBOs.
605 *@todo: add error reporting to state's VBO related functions and abort dispatching to
606 *real gpu on any failure to prevent other possible issues.
607 */
608
609 if ((size != 3) && (size != 4))
610 {
611 crStateError(__LINE__, __FILE__, GL_INVALID_VALUE, "glSecondaryColorPointerEXT: invalid size: %d", size);
612 return;
613 }
614 if (type != GL_BYTE && type != GL_UNSIGNED_BYTE &&
615 type != GL_SHORT && type != GL_UNSIGNED_SHORT &&
616 type != GL_INT && type != GL_UNSIGNED_INT &&
617 type != GL_FLOAT && type != GL_DOUBLE)
618 {
619 crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glSecondaryColorPointerEXT: invalid type: 0x%x", type);
620 return;
621 }
622 if (stride < 0)
623 {
624 crStateError(__LINE__, __FILE__, GL_INVALID_VALUE, "glSecondaryColorPointerEXT: stride was negative: %d", stride);
625 return;
626 }
627
628 crStateClientSetPointer(&(c->array.s), size, type, GL_TRUE, stride, p);
629 DIRTY(cb->dirty, g->neg_bitid);
630 DIRTY(cb->clientPointer, g->neg_bitid);
631 DIRTY(cb->s, g->neg_bitid);
632}
633
634void STATE_APIENTRY crStateIndexPointer(GLenum type, GLsizei stride,
635 const GLvoid *p)
636{
637 CRContext *g = GetCurrentContext();
638 CRClientState *c = &(g->client);
639 CRStateBits *sb = GetCurrentBits();
640 CRClientBits *cb = &(sb->client);
641
642 FLUSH();
643
644 if (type != GL_SHORT && type != GL_INT && type != GL_UNSIGNED_BYTE &&
645 type != GL_FLOAT && type != GL_DOUBLE)
646 {
647 crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glIndexPointer: invalid type: 0x%x", type);
648 return;
649 }
650 if (stride < 0)
651 {
652 crStateError(__LINE__, __FILE__, GL_INVALID_VALUE, "glIndexPointer: stride was negative: %d", stride);
653 return;
654 }
655
656 crStateClientSetPointer(&(c->array.i), 1, type, GL_TRUE, stride, p);
657 DIRTY(cb->dirty, g->neg_bitid);
658 DIRTY(cb->clientPointer, g->neg_bitid);
659 DIRTY(cb->i, g->neg_bitid);
660}
661
662void STATE_APIENTRY crStateNormalPointer(GLenum type, GLsizei stride,
663 const GLvoid *p)
664{
665 CRContext *g = GetCurrentContext();
666 CRClientState *c = &(g->client);
667 CRStateBits *sb = GetCurrentBits();
668 CRClientBits *cb = &(sb->client);
669
670 FLUSH();
671
672 if (type != GL_BYTE && type != GL_SHORT &&
673 type != GL_INT && type != GL_FLOAT &&
674 type != GL_DOUBLE)
675 {
676 crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glNormalPointer: invalid type: 0x%x", type);
677 return;
678 }
679 if (stride < 0)
680 {
681 crStateError(__LINE__, __FILE__, GL_INVALID_VALUE, "glNormalPointer: stride was negative: %d", stride);
682 return;
683 }
684
685 crStateClientSetPointer(&(c->array.n), 3, type, GL_TRUE, stride, p);
686 DIRTY(cb->dirty, g->neg_bitid);
687 DIRTY(cb->clientPointer, g->neg_bitid);
688 DIRTY(cb->n, g->neg_bitid);
689}
690
691void STATE_APIENTRY crStateTexCoordPointer(GLint size, GLenum type,
692 GLsizei stride, const GLvoid *p)
693{
694 CRContext *g = GetCurrentContext();
695 CRClientState *c = &(g->client);
696 CRStateBits *sb = GetCurrentBits();
697 CRClientBits *cb = &(sb->client);
698
699 FLUSH();
700
701 if (size != 1 && size != 2 && size != 3 && size != 4)
702 {
703 crStateError(__LINE__, __FILE__, GL_INVALID_VALUE, "glTexCoordPointer: invalid size: %d", size);
704 return;
705 }
706 if (type != GL_SHORT && type != GL_INT &&
707 type != GL_FLOAT && type != GL_DOUBLE)
708 {
709 crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glTexCoordPointer: invalid type: 0x%x", type);
710 return;
711 }
712 if (stride < 0)
713 {
714 crStateError(__LINE__, __FILE__, GL_INVALID_VALUE, "glTexCoordPointer: stride was negative: %d", stride);
715 return;
716 }
717
718 crStateClientSetPointer(&(c->array.t[c->curClientTextureUnit]), size, type, GL_FALSE, stride, p);
719 DIRTY(cb->dirty, g->neg_bitid);
720 DIRTY(cb->clientPointer, g->neg_bitid);
721 DIRTY(cb->t[c->curClientTextureUnit], g->neg_bitid);
722}
723
724void STATE_APIENTRY crStateEdgeFlagPointer(GLsizei stride, const GLvoid *p)
725{
726 CRContext *g = GetCurrentContext();
727 CRClientState *c = &(g->client);
728 CRStateBits *sb = GetCurrentBits();
729 CRClientBits *cb = &(sb->client);
730
731 FLUSH();
732
733 if (stride < 0)
734 {
735 crStateError(__LINE__, __FILE__, GL_INVALID_VALUE, "glTexCoordPointer: stride was negative: %d", stride);
736 return;
737 }
738
739 crStateClientSetPointer(&(c->array.e), 1, GL_UNSIGNED_BYTE, GL_FALSE, stride, p);
740 DIRTY(cb->dirty, g->neg_bitid);
741 DIRTY(cb->clientPointer, g->neg_bitid);
742 DIRTY(cb->e, g->neg_bitid);
743}
744
745void STATE_APIENTRY crStateFogCoordPointerEXT(GLenum type, GLsizei stride, const GLvoid *p)
746{
747 CRContext *g = GetCurrentContext();
748 CRClientState *c = &(g->client);
749 CRStateBits *sb = GetCurrentBits();
750 CRClientBits *cb = &(sb->client);
751
752 FLUSH();
753
754 if (type != GL_BYTE && type != GL_UNSIGNED_BYTE &&
755 type != GL_SHORT && type != GL_UNSIGNED_SHORT &&
756 type != GL_INT && type != GL_UNSIGNED_INT &&
757 type != GL_FLOAT && type != GL_DOUBLE)
758 {
759 crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glFogCoordPointerEXT: invalid type: 0x%x", type);
760 return;
761 }
762 if (stride < 0)
763 {
764 crStateError(__LINE__, __FILE__, GL_INVALID_VALUE, "glFogCoordPointerEXT: stride was negative: %d", stride);
765 return;
766 }
767
768 crStateClientSetPointer(&(c->array.f), 1, type, GL_FALSE, stride, p);
769 DIRTY(cb->dirty, g->neg_bitid);
770 DIRTY(cb->clientPointer, g->neg_bitid);
771 DIRTY(cb->f, g->neg_bitid);
772}
773
774
775void STATE_APIENTRY crStateVertexAttribPointerNV(GLuint index, GLint size, GLenum type, GLsizei stride, const GLvoid *p)
776{
777 GLboolean normalized = GL_FALSE;
778 /* Extra error checking for NV arrays */
779 if (type != GL_UNSIGNED_BYTE && type != GL_SHORT &&
780 type != GL_FLOAT && type != GL_DOUBLE) {
781 crStateError(__LINE__, __FILE__, GL_INVALID_ENUM,
782 "glVertexAttribPointerNV: invalid type: 0x%x", type);
783 return;
784 }
785 crStateVertexAttribPointerARB(index, size, type, normalized, stride, p);
786}
787
788
789void STATE_APIENTRY crStateVertexAttribPointerARB(GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const GLvoid *p)
790{
791 CRContext *g = GetCurrentContext();
792 CRClientState *c = &(g->client);
793 CRStateBits *sb = GetCurrentBits();
794 CRClientBits *cb = &(sb->client);
795
796 FLUSH();
797
798 if (index > CR_MAX_VERTEX_ATTRIBS)
799 {
800 crStateError(__LINE__, __FILE__, GL_INVALID_VALUE, "glVertexAttribPointerARB: invalid index: %d", (int) index);
801 return;
802 }
803 if (size != 1 && size != 2 && size != 3 && size != 4)
804 {
805 crStateError(__LINE__, __FILE__, GL_INVALID_VALUE, "glVertexAttribPointerARB: invalid size: %d", size);
806 return;
807 }
808 if (type != GL_BYTE && type != GL_UNSIGNED_BYTE &&
809 type != GL_SHORT && type != GL_UNSIGNED_SHORT &&
810 type != GL_INT && type != GL_UNSIGNED_INT &&
811 type != GL_FLOAT && type != GL_DOUBLE)
812 {
813 crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glVertexAttribPointerARB: invalid type: 0x%x", type);
814 return;
815 }
816 if (stride < 0)
817 {
818 crStateError(__LINE__, __FILE__, GL_INVALID_VALUE, "glVertexAttribPointerARB: stride was negative: %d", stride);
819 return;
820 }
821
822 crStateClientSetPointer(&(c->array.a[index]), size, type, normalized, stride, p);
823 DIRTY(cb->dirty, g->neg_bitid);
824 DIRTY(cb->clientPointer, g->neg_bitid);
825 DIRTY(cb->a[index], g->neg_bitid);
826}
827
828
829void STATE_APIENTRY crStateGetVertexAttribPointervNV(GLuint index, GLenum pname, GLvoid **pointer)
830{
831 CRContext *g = GetCurrentContext();
832
833 if (g->current.inBeginEnd) {
834 crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION,
835 "glGetVertexAttribPointervNV called in Begin/End");
836 return;
837 }
838
839 if (index >= CR_MAX_VERTEX_ATTRIBS) {
840 crStateError(__LINE__, __FILE__, GL_INVALID_VALUE,
841 "glGetVertexAttribPointervNV(index)");
842 return;
843 }
844
845 if (pname != GL_ATTRIB_ARRAY_POINTER_NV) {
846 crStateError(__LINE__, __FILE__, GL_INVALID_ENUM,
847 "glGetVertexAttribPointervNV(pname)");
848 return;
849 }
850
851 *pointer = g->client.array.a[index].p;
852}
853
854
855void STATE_APIENTRY crStateGetVertexAttribPointervARB(GLuint index, GLenum pname, GLvoid **pointer)
856{
857 crStateGetVertexAttribPointervNV(index, pname, pointer);
858}
859
860
861
862/*
863** Currently I treat Interleaved Arrays as if the
864** user uses them as separate arrays.
865** Certainly not the most efficient method but it
866** lets me use the same glDrawArrays method.
867*/
868void STATE_APIENTRY crStateInterleavedArrays(GLenum format, GLsizei stride, const GLvoid *p)
869{
870 CRContext *g = GetCurrentContext();
871 CRClientState *c = &(g->client);
872 CRStateBits *sb = GetCurrentBits();
873 CRClientBits *cb = &(sb->client);
874 CRClientPointer *cp;
875 unsigned char *base = (unsigned char *) p;
876
877 if (g->current.inBeginEnd)
878 {
879 crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, "glInterleavedArrays called in begin/end");
880 return;
881 }
882
883 FLUSH();
884
885 if (stride < 0)
886 {
887 crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, "glInterleavedArrays: stride < 0: %d", stride);
888 return;
889 }
890
891 switch (format)
892 {
893 case GL_T4F_C4F_N3F_V4F:
894 case GL_T2F_C4F_N3F_V3F:
895 case GL_C4F_N3F_V3F:
896 case GL_T4F_V4F:
897 case GL_T2F_C3F_V3F:
898 case GL_T2F_N3F_V3F:
899 case GL_C3F_V3F:
900 case GL_N3F_V3F:
901 case GL_T2F_C4UB_V3F:
902 case GL_T2F_V3F:
903 case GL_C4UB_V3F:
904 case GL_V3F:
905 case GL_C4UB_V2F:
906 case GL_V2F:
907 break;
908 default:
909 crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glInterleavedArrays: Unrecognized format: %d", format);
910 return;
911 }
912
913 DIRTY(cb->dirty, g->neg_bitid);
914 DIRTY(cb->clientPointer, g->neg_bitid);
915
916/* p, size, type, stride, enabled, bytesPerIndex */
917/*
918** VertexPointer
919*/
920
921 cp = &(c->array.v);
922 cp->type = GL_FLOAT;
923 cp->enabled = GL_TRUE;
924
925 switch (format)
926 {
927 case GL_T4F_C4F_N3F_V4F:
928 cp->p = base+4*sizeof(GLfloat)+4*sizeof(GLfloat)+3*sizeof(GLfloat);
929 cp->size = 4;
930 break;
931 case GL_T2F_C4F_N3F_V3F:
932 cp->p = base+2*sizeof(GLfloat)+4*sizeof(GLfloat)+3*sizeof(GLfloat);
933 cp->size = 3;
934 break;
935 case GL_C4F_N3F_V3F:
936 cp->p = base+4*sizeof(GLfloat)+3*sizeof(GLfloat);
937 cp->size = 3;
938 break;
939 case GL_T4F_V4F:
940 cp->p = base+4*sizeof(GLfloat);
941 cp->size = 4;
942 break;
943 case GL_T2F_C3F_V3F:
944 cp->p = base+2*sizeof(GLfloat)+3*sizeof(GLfloat);
945 cp->size = 3;
946 break;
947 case GL_T2F_N3F_V3F:
948 cp->p = base+2*sizeof(GLfloat)+3*sizeof(GLfloat);
949 cp->size = 3;
950 break;
951 case GL_C3F_V3F:
952 cp->p = base+3*sizeof(GLfloat);
953 cp->size = 3;
954 break;
955 case GL_N3F_V3F:
956 cp->p = base+3*sizeof(GLfloat);
957 cp->size = 3;
958 break;
959 case GL_T2F_C4UB_V3F:
960 cp->p = base+2*sizeof(GLfloat)+4*sizeof(GLubyte);
961 cp->size = 3;
962 break;
963 case GL_T2F_V3F:
964 cp->p = base+2*sizeof(GLfloat);
965 cp->size = 3;
966 break;
967 case GL_C4UB_V3F:
968 cp->p = base+4*sizeof(GLubyte);
969 cp->size = 3;
970 break;
971 case GL_V3F:
972 cp->p = base;
973 cp->size = 3;
974 break;
975 case GL_C4UB_V2F:
976 cp->p = base+4*sizeof(GLubyte);
977 cp->size = 2;
978 break;
979 case GL_V2F:
980 cp->p = base;
981 cp->size = 2;
982 break;
983 default:
984 crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glInterleavedArrays: Unrecognized format: %d", format);
985 return;
986 }
987
988 cp->bytesPerIndex = cp->size * sizeof (GLfloat);
989
990 if (stride==0)
991 stride = cp->bytesPerIndex + (cp->p - base);
992 cp->stride = stride;
993
994/*
995** NormalPointer
996*/
997
998 cp = &(c->array.n);
999 cp->enabled = GL_TRUE;
1000 cp->stride = stride;
1001 switch (format)
1002 {
1003 case GL_T4F_C4F_N3F_V4F:
1004 cp->p = base+4*sizeof(GLfloat)+4*sizeof(GLfloat);
1005 break;
1006 case GL_T2F_C4F_N3F_V3F:
1007 cp->p = base+2*sizeof(GLfloat)+4*sizeof(GLfloat);
1008 break;
1009 case GL_C4F_N3F_V3F:
1010 cp->p = base+4*sizeof(GLfloat);
1011 break;
1012 case GL_T2F_N3F_V3F:
1013 cp->p = base+2*sizeof(GLfloat);
1014 break;
1015 case GL_N3F_V3F:
1016 cp->p = base;
1017 break;
1018 case GL_T4F_V4F:
1019 case GL_T2F_C3F_V3F:
1020 case GL_C3F_V3F:
1021 case GL_T2F_C4UB_V3F:
1022 case GL_T2F_V3F:
1023 case GL_C4UB_V3F:
1024 case GL_V3F:
1025 case GL_C4UB_V2F:
1026 case GL_V2F:
1027 cp->enabled = GL_FALSE;
1028 break;
1029 default:
1030 crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glInterleavedArrays: Unrecognized format: %d", format);
1031 return;
1032 }
1033
1034 if (cp->enabled)
1035 {
1036 cp->type = GL_FLOAT;
1037 cp->size = 3;
1038 cp->bytesPerIndex = cp->size * sizeof (GLfloat);
1039 }
1040
1041/*
1042** ColorPointer
1043*/
1044
1045 cp = &(c->array.c);
1046 cp->enabled = GL_TRUE;
1047 cp->stride = stride;
1048 switch (format)
1049 {
1050 case GL_T4F_C4F_N3F_V4F:
1051 cp->size = 4;
1052 cp->type = GL_FLOAT;
1053 cp->bytesPerIndex = cp->size * sizeof(GLfloat);
1054 cp->p = base+4*sizeof(GLfloat);
1055 break;
1056 case GL_T2F_C4F_N3F_V3F:
1057 cp->size = 4;
1058 cp->type = GL_FLOAT;
1059 cp->bytesPerIndex = cp->size * sizeof(GLfloat);
1060 cp->p = base+2*sizeof(GLfloat);
1061 break;
1062 case GL_C4F_N3F_V3F:
1063 cp->size = 4;
1064 cp->type = GL_FLOAT;
1065 cp->bytesPerIndex = cp->size * sizeof(GLfloat);
1066 cp->p = base;
1067 break;
1068 case GL_T2F_C3F_V3F:
1069 cp->size = 3;
1070 cp->type = GL_FLOAT;
1071 cp->bytesPerIndex = cp->size * sizeof(GLfloat);
1072 cp->p = base+2*sizeof(GLfloat);
1073 break;
1074 case GL_C3F_V3F:
1075 cp->size = 3;
1076 cp->type = GL_FLOAT;
1077 cp->bytesPerIndex = cp->size * sizeof(GLfloat);
1078 cp->p = base;
1079 break;
1080 case GL_T2F_C4UB_V3F:
1081 cp->size = 4;
1082 cp->type = GL_UNSIGNED_BYTE;
1083 cp->bytesPerIndex = cp->size * sizeof(GLubyte);
1084 cp->p = base+2*sizeof(GLfloat);
1085 break;
1086 case GL_C4UB_V3F:
1087 cp->size = 4;
1088 cp->type = GL_UNSIGNED_BYTE;
1089 cp->bytesPerIndex = cp->size * sizeof(GLubyte);
1090 cp->p = base;
1091 break;
1092 case GL_C4UB_V2F:
1093 cp->size = 4;
1094 cp->type = GL_UNSIGNED_BYTE;
1095 cp->bytesPerIndex = cp->size * sizeof(GLubyte);
1096 cp->p = base;
1097 break;
1098 case GL_T2F_N3F_V3F:
1099 case GL_N3F_V3F:
1100 case GL_T4F_V4F:
1101 case GL_T2F_V3F:
1102 case GL_V3F:
1103 case GL_V2F:
1104 cp->enabled = GL_FALSE;
1105 break;
1106 default:
1107 crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glInterleavedArrays: Unrecognized format: %d", format);
1108 return;
1109 }
1110
1111/*
1112** TexturePointer
1113*/
1114
1115 cp = &(c->array.t[c->curClientTextureUnit]);
1116 cp->enabled = GL_TRUE;
1117 cp->stride = stride;
1118 switch (format)
1119 {
1120 case GL_T4F_C4F_N3F_V4F:
1121 cp->size = 4;
1122 cp->p = base;
1123 break;
1124 case GL_T2F_C4F_N3F_V3F:
1125 cp->size = 3;
1126 cp->p = base;
1127 break;
1128 case GL_T2F_C3F_V3F:
1129 case GL_T2F_N3F_V3F:
1130 cp->size = 3;
1131 cp->p = base;
1132 break;
1133 case GL_T2F_C4UB_V3F:
1134 cp->size = 3;
1135 cp->p = base;
1136 break;
1137 case GL_T4F_V4F:
1138 cp->size = 4;
1139 cp->p = base;
1140 break;
1141 case GL_T2F_V3F:
1142 cp->size = 3;
1143 cp->p = base;
1144 break;
1145 case GL_C4UB_V3F:
1146 case GL_C4UB_V2F:
1147 case GL_C3F_V3F:
1148 case GL_C4F_N3F_V3F:
1149 case GL_N3F_V3F:
1150 case GL_V3F:
1151 case GL_V2F:
1152 cp->enabled = GL_FALSE;
1153 break;
1154 default:
1155 crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glInterleavedArrays: Unrecognized format: %d", format);
1156 return;
1157 }
1158
1159 if (cp->enabled)
1160 {
1161 cp->type = GL_FLOAT;
1162 cp->bytesPerIndex = cp->size * sizeof (GLfloat);
1163 }
1164}
1165
1166void STATE_APIENTRY crStateGetPointerv(GLenum pname, GLvoid * * params)
1167{
1168 CRContext *g = GetCurrentContext();
1169 CRClientState *c = &(g->client);
1170
1171 if (g->current.inBeginEnd)
1172 {
1173 crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION,
1174 "GetPointerv called in begin/end");
1175 return;
1176 }
1177
1178 switch (pname)
1179 {
1180 case GL_VERTEX_ARRAY_POINTER:
1181 *params = (GLvoid *) c->array.v.p;
1182 break;
1183 case GL_COLOR_ARRAY_POINTER:
1184 *params = (GLvoid *) c->array.c.p;
1185 break;
1186 case GL_NORMAL_ARRAY_POINTER:
1187 *params = (GLvoid *) c->array.n.p;
1188 break;
1189 case GL_INDEX_ARRAY_POINTER:
1190 *params = (GLvoid *) c->array.i.p;
1191 break;
1192 case GL_TEXTURE_COORD_ARRAY_POINTER:
1193 *params = (GLvoid *) c->array.t[c->curClientTextureUnit].p;
1194 break;
1195 case GL_EDGE_FLAG_ARRAY_POINTER:
1196 *params = (GLvoid *) c->array.e.p;
1197 break;
1198#ifdef CR_EXT_fog_coord
1199 case GL_FOG_COORDINATE_ARRAY_POINTER_EXT:
1200 *params = (GLvoid *) c->array.f.p;
1201 break;
1202#endif
1203#ifdef CR_EXT_secondary_color
1204 case GL_SECONDARY_COLOR_ARRAY_POINTER_EXT:
1205 if( g->extensions.EXT_secondary_color ){
1206 *params = (GLvoid *) c->array.s.p;
1207 }
1208 else {
1209 crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "Invalid Enum passed to glGetPointerv: SECONDARY_COLOR_ARRAY_EXT - EXT_secondary_color is not enabled." );
1210 return;
1211 }
1212 break;
1213#endif
1214 case GL_FEEDBACK_BUFFER_POINTER:
1215 case GL_SELECTION_BUFFER_POINTER:
1216 /* do nothing - API switching should pick this up */
1217 break;
1218 default:
1219 crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION,
1220 "glGetPointerv: invalid pname: %d", pname);
1221 return;
1222 }
1223}
1224
1225
1226void STATE_APIENTRY crStatePushClientAttrib( GLbitfield mask )
1227{
1228 CRContext *g = GetCurrentContext();
1229 CRClientState *c = &(g->client);
1230
1231 if (g->current.inBeginEnd) {
1232 crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION,
1233 "glPushClientAttrib called in Begin/End");
1234 return;
1235 }
1236
1237 if (c->attribStackDepth == CR_MAX_CLIENT_ATTRIB_STACK_DEPTH - 1) {
1238 crStateError(__LINE__, __FILE__, GL_STACK_OVERFLOW,
1239 "glPushClientAttrib called with a full stack!" );
1240 return;
1241 }
1242
1243 FLUSH();
1244
1245 c->pushMaskStack[c->attribStackDepth++] = mask;
1246
1247 if (mask & GL_CLIENT_PIXEL_STORE_BIT) {
1248 c->pixelPackStoreStack[c->pixelStoreStackDepth] = c->pack;
1249 c->pixelUnpackStoreStack[c->pixelStoreStackDepth] = c->unpack;
1250 c->pixelStoreStackDepth++;
1251 }
1252 if (mask & GL_CLIENT_VERTEX_ARRAY_BIT) {
1253 c->vertexArrayStack[c->vertexArrayStackDepth] = c->array;
1254 c->vertexArrayStackDepth++;
1255 }
1256
1257 /* dirty? - no, because we haven't really changed any state */
1258}
1259
1260
1261void STATE_APIENTRY crStatePopClientAttrib( void )
1262{
1263 CRContext *g = GetCurrentContext();
1264 CRClientState *c = &(g->client);
1265 CRStateBits *sb = GetCurrentBits();
1266 CRClientBits *cb = &(sb->client);
1267 CRbitvalue mask;
1268
1269 if (g->current.inBeginEnd) {
1270 crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION,
1271 "glPopClientAttrib called in Begin/End");
1272 return;
1273 }
1274
1275 if (c->attribStackDepth == 0) {
1276 crStateError(__LINE__, __FILE__, GL_STACK_UNDERFLOW,
1277 "glPopClientAttrib called with an empty stack!" );
1278 return;
1279 }
1280
1281 FLUSH();
1282
1283 mask = c->pushMaskStack[--c->attribStackDepth];
1284
1285 if (mask & GL_CLIENT_PIXEL_STORE_BIT) {
1286 if (c->pixelStoreStackDepth == 0) {
1287 crError("bug in glPopClientAttrib (pixel store) ");
1288 return;
1289 }
1290 c->pixelStoreStackDepth--;
1291 c->pack = c->pixelPackStoreStack[c->pixelStoreStackDepth];
1292 c->unpack = c->pixelUnpackStoreStack[c->pixelStoreStackDepth];
1293 DIRTY(cb->pack, g->neg_bitid);
1294 }
1295
1296 if (mask & GL_CLIENT_VERTEX_ARRAY_BIT) {
1297 if (c->vertexArrayStackDepth == 0) {
1298 crError("bug in glPopClientAttrib (vertex array) ");
1299 return;
1300 }
1301 c->vertexArrayStackDepth--;
1302 c->array = c->vertexArrayStack[c->vertexArrayStackDepth];
1303 DIRTY(cb->clientPointer, g->neg_bitid);
1304 }
1305
1306 DIRTY(cb->dirty, g->neg_bitid);
1307}
1308
1309
1310void STATE_APIENTRY crStateVertexArrayRangeNV(GLsizei length, const GLvoid *pointer)
1311{
1312 /* XXX todo */
1313 crWarning("crStateVertexArrayRangeNV not implemented");
1314}
1315
1316
1317void STATE_APIENTRY crStateFlushVertexArrayRangeNV(void)
1318{
1319 /* XXX todo */
1320 crWarning("crStateFlushVertexArrayRangeNV not implemented");
1321}
1322
1323/*Returns if the given clientpointer could be used on server side directly*/
1324#define CRSTATE_IS_SERVER_CP(cp) (!(cp).enabled || !(cp).p || ((cp).buffer && (cp).buffer->name))
1325
1326static void crStateDumpClientPointer(CRClientPointer *cp, const char *name, int i)
1327{
1328 if (i<0 && cp->enabled)
1329 {
1330 crDebug("CP(%s): enabled:%d ptr:%p buffer:%p buffer.name:%i %s",
1331 name, cp->enabled, cp->p, cp->buffer, cp->buffer? cp->buffer->name:-1,
1332 CRSTATE_IS_SERVER_CP(*cp) ? "":"!FAIL!");
1333 }
1334 else if (0==i || cp->enabled)
1335 {
1336 crDebug("CP(%s%i): enabled:%d ptr:%p buffer:%p buffer.name:%i %s",
1337 name, i, cp->enabled, cp->p, cp->buffer, cp->buffer? cp->buffer->name:-1,
1338 CRSTATE_IS_SERVER_CP(*cp) ? "":"!FAIL!");
1339 }
1340}
1341
1342/*
1343 * Determine if the enabled arrays all live on the server
1344 * (via GL_ARB_vertex_buffer_object).
1345 */
1346GLboolean crStateUseServerArrays(void)
1347{
1348#ifdef CR_ARB_vertex_buffer_object
1349 CRContext *g = GetCurrentContext();
1350 CRClientState *c = &(g->client);
1351 int i;
1352 GLboolean res;
1353
1354 res = CRSTATE_IS_SERVER_CP(c->array.v)
1355 && CRSTATE_IS_SERVER_CP(c->array.n)
1356 && CRSTATE_IS_SERVER_CP(c->array.c)
1357 && CRSTATE_IS_SERVER_CP(c->array.i)
1358 && CRSTATE_IS_SERVER_CP(c->array.e)
1359 && CRSTATE_IS_SERVER_CP(c->array.s)
1360 && CRSTATE_IS_SERVER_CP(c->array.f);
1361
1362 for (i = 0; (unsigned int)i < g->limits.maxTextureUnits; i++)
1363 if (!CRSTATE_IS_SERVER_CP(c->array.t[i]))
1364 {
1365 res = GL_FALSE;
1366 break;
1367 }
1368
1369 for (i = 0; (unsigned int)i < g->limits.maxVertexProgramAttribs; i++)
1370 if (!CRSTATE_IS_SERVER_CP(c->array.a[i]))
1371 {
1372 res = GL_FALSE;
1373 break;
1374 }
1375
1376 if (!res)
1377 {
1378 crStateDumpClientPointer(&c->array.v, "v", -1);
1379 crStateDumpClientPointer(&c->array.n, "n", -1);
1380 crStateDumpClientPointer(&c->array.c, "c", -1);
1381 crStateDumpClientPointer(&c->array.i, "i", -1);
1382 crStateDumpClientPointer(&c->array.e, "e", -1);
1383 crStateDumpClientPointer(&c->array.s, "s", -1);
1384 crStateDumpClientPointer(&c->array.f, "f", -1);
1385 for (i = 0; (unsigned int)i < g->limits.maxTextureUnits; i++)
1386 crStateDumpClientPointer(&c->array.t[i], "tex", i);
1387 for (i = 0; (unsigned int)i < g->limits.maxVertexProgramAttribs; i++)
1388 crStateDumpClientPointer(&c->array.a[i], "attrib", i);
1389 crDebug("crStateUseServerArrays->%d", res);
1390 }
1391
1392 return res;
1393#else
1394 return GL_FALSE;
1395#endif
1396}
1397
1398
1399/**
1400 * Determine if there's a server-side array element buffer.
1401 * Called by glDrawElements() in packing SPUs to determine if glDrawElements
1402 * should be evaluated (unrolled) locally or if glDrawElements should be
1403 * packed and sent to the server.
1404 */
1405GLboolean
1406crStateUseServerArrayElements(void)
1407{
1408#ifdef CR_ARB_vertex_buffer_object
1409 CRContext *g = GetCurrentContext();
1410 if (g->bufferobject.elementsBuffer &&
1411 g->bufferobject.elementsBuffer->name > 0)
1412 return GL_TRUE;
1413 else
1414 return GL_FALSE;
1415#else
1416 return GL_FALSE;
1417#endif
1418}
1419
1420
1421void
1422crStateClientDiff(CRClientBits *cb, CRbitvalue *bitID,
1423 CRContext *fromCtx, CRContext *toCtx)
1424{
1425 CRClientState *from = &(fromCtx->client);
1426 const CRClientState *to = &(toCtx->client);
1427 int i;
1428
1429 if (CHECKDIRTY(cb->clientPointer, bitID)) {
1430 /* one or more vertex pointers is dirty */
1431 if (CHECKDIRTY(cb->v, bitID)) {
1432 if (from->array.v.size != to->array.v.size ||
1433 from->array.v.type != to->array.v.type ||
1434 from->array.v.stride != to->array.v.stride ||
1435 from->array.v.buffer != to->array.v.buffer) {
1436 diff_api.VertexPointer(to->array.v.size, to->array.v.type,
1437 to->array.v.stride, to->array.v.p);
1438 from->array.v.size = to->array.v.size;
1439 from->array.v.type = to->array.v.type;
1440 from->array.v.stride = to->array.v.stride;
1441 from->array.v.p = to->array.v.p;
1442 from->array.v.buffer = to->array.v.buffer;
1443 }
1444 CLEARDIRTY2(cb->v, bitID);
1445 }
1446 /* normal */
1447 if (CHECKDIRTY(cb->n, bitID)) {
1448 if (from->array.n.type != to->array.n.type ||
1449 from->array.n.stride != to->array.n.stride ||
1450 from->array.n.buffer != to->array.n.buffer) {
1451 diff_api.NormalPointer(to->array.n.type,
1452 to->array.n.stride, to->array.n.p);
1453 from->array.n.type = to->array.n.type;
1454 from->array.n.stride = to->array.n.stride;
1455 from->array.n.p = to->array.n.p;
1456 from->array.n.buffer = to->array.n.buffer;
1457 }
1458 CLEARDIRTY2(cb->n, bitID);
1459 }
1460 /* color */
1461 if (CHECKDIRTY(cb->c, bitID)) {
1462 if (from->array.c.size != to->array.c.size ||
1463 from->array.c.type != to->array.c.type ||
1464 from->array.c.stride != to->array.c.stride ||
1465 from->array.c.buffer != to->array.c.buffer) {
1466 diff_api.ColorPointer(to->array.c.size, to->array.c.type,
1467 to->array.c.stride, to->array.c.p);
1468 from->array.c.size = to->array.c.size;
1469 from->array.c.type = to->array.c.type;
1470 from->array.c.stride = to->array.c.stride;
1471 from->array.c.p = to->array.c.p;
1472 from->array.c.buffer = to->array.c.buffer;
1473 }
1474 CLEARDIRTY2(cb->c, bitID);
1475 }
1476 /* index */
1477 if (CHECKDIRTY(cb->i, bitID)) {
1478 if (from->array.i.type != to->array.i.type ||
1479 from->array.i.stride != to->array.i.stride ||
1480 from->array.i.buffer != to->array.i.buffer) {
1481 diff_api.IndexPointer(to->array.i.type,
1482 to->array.i.stride, to->array.i.p);
1483 from->array.i.type = to->array.i.type;
1484 from->array.i.stride = to->array.i.stride;
1485 from->array.i.p = to->array.i.p;
1486 from->array.i.buffer = to->array.i.buffer;
1487 }
1488 CLEARDIRTY2(cb->i, bitID);
1489 }
1490 /* texcoords */
1491 for (i = 0; (unsigned int)i < toCtx->limits.maxTextureUnits; i++) {
1492 if (CHECKDIRTY(cb->t[i], bitID)) {
1493 if (from->array.t[i].size != to->array.t[i].size ||
1494 from->array.t[i].type != to->array.t[i].type ||
1495 from->array.t[i].stride != to->array.t[i].stride ||
1496 from->array.t[i].buffer != to->array.t[i].buffer) {
1497 diff_api.ClientActiveTextureARB(GL_TEXTURE0_ARB + i);
1498 diff_api.TexCoordPointer(to->array.t[i].size, to->array.t[i].type,
1499 to->array.t[i].stride, to->array.t[i].p);
1500 from->array.t[i].size = to->array.t[i].size;
1501 from->array.t[i].type = to->array.t[i].type;
1502 from->array.t[i].stride = to->array.t[i].stride;
1503 from->array.t[i].p = to->array.t[i].p;
1504 from->array.t[i].buffer = to->array.t[i].buffer;
1505 }
1506 CLEARDIRTY2(cb->t[i], bitID);
1507 }
1508 }
1509 /* edge flag */
1510 if (CHECKDIRTY(cb->e, bitID)) {
1511 if (from->array.e.stride != to->array.e.stride ||
1512 from->array.e.buffer != to->array.e.buffer) {
1513 diff_api.EdgeFlagPointer(to->array.e.stride, to->array.e.p);
1514 from->array.e.stride = to->array.e.stride;
1515 from->array.e.p = to->array.e.p;
1516 from->array.e.buffer = to->array.e.buffer;
1517 }
1518 CLEARDIRTY2(cb->e, bitID);
1519 }
1520 /* secondary color */
1521 if (CHECKDIRTY(cb->s, bitID)) {
1522 if (from->array.s.size != to->array.s.size ||
1523 from->array.s.type != to->array.s.type ||
1524 from->array.s.stride != to->array.s.stride ||
1525 from->array.s.buffer != to->array.s.buffer) {
1526 diff_api.SecondaryColorPointerEXT(to->array.s.size, to->array.s.type,
1527 to->array.s.stride, to->array.s.p);
1528 from->array.s.size = to->array.s.size;
1529 from->array.s.type = to->array.s.type;
1530 from->array.s.stride = to->array.s.stride;
1531 from->array.s.p = to->array.s.p;
1532 from->array.s.buffer = to->array.s.buffer;
1533 }
1534 CLEARDIRTY2(cb->s, bitID);
1535 }
1536 /* fog coord */
1537 if (CHECKDIRTY(cb->f, bitID)) {
1538 if (from->array.f.type != to->array.f.type ||
1539 from->array.f.stride != to->array.f.stride ||
1540 from->array.f.buffer != to->array.f.buffer) {
1541 diff_api.FogCoordPointerEXT(to->array.f.type,
1542 to->array.f.stride, to->array.f.p);
1543 from->array.f.type = to->array.f.type;
1544 from->array.f.stride = to->array.f.stride;
1545 from->array.f.p = to->array.f.p;
1546 from->array.f.buffer = to->array.f.buffer;
1547 }
1548 CLEARDIRTY2(cb->f, bitID);
1549 }
1550#if defined(CR_NV_vertex_program) || defined(CR_ARB_vertex_program)
1551 /* vertex attributes */
1552 for (i = 0; (unsigned int)i < toCtx->limits.maxVertexProgramAttribs; i++) {
1553 if (CHECKDIRTY(cb->a[i], bitID)) {
1554 if (from->array.a[i].size != to->array.a[i].size ||
1555 from->array.a[i].type != to->array.a[i].type ||
1556 from->array.a[i].stride != to->array.a[i].stride ||
1557 from->array.a[i].normalized != to->array.a[i].normalized ||
1558 from->array.a[i].buffer != to->array.a[i].buffer) {
1559 diff_api.VertexAttribPointerARB(i, to->array.a[i].size,
1560 to->array.a[i].type,
1561 to->array.a[i].normalized,
1562 to->array.a[i].stride,
1563 to->array.a[i].p);
1564 from->array.a[i].size = to->array.a[i].size;
1565 from->array.a[i].type = to->array.a[i].type;
1566 from->array.a[i].stride = to->array.a[i].stride;
1567 from->array.a[i].normalized = to->array.a[i].normalized;
1568 from->array.a[i].p = to->array.a[i].p;
1569 from->array.a[i].buffer = to->array.a[i].buffer;
1570 }
1571 CLEARDIRTY2(cb->a[i], bitID);
1572 }
1573 }
1574#endif
1575 }
1576
1577 if (CHECKDIRTY(cb->enableClientState, bitID)) {
1578 /* update vertex array enable/disable flags */
1579 glAble able[2];
1580 able[0] = diff_api.Disable;
1581 able[1] = diff_api.Enable;
1582 if (from->array.v.enabled != to->array.v.enabled) {
1583 able[to->array.v.enabled](GL_VERTEX_ARRAY);
1584 from->array.v.enabled = to->array.v.enabled;
1585 }
1586 if (from->array.n.enabled != to->array.n.enabled) {
1587 able[to->array.n.enabled](GL_NORMAL_ARRAY);
1588 from->array.n.enabled = to->array.n.enabled;
1589 }
1590 if (from->array.c.enabled != to->array.c.enabled) {
1591 able[to->array.c.enabled](GL_COLOR_ARRAY);
1592 from->array.c.enabled = to->array.c.enabled;
1593 }
1594 if (from->array.i.enabled != to->array.i.enabled) {
1595 able[to->array.i.enabled](GL_INDEX_ARRAY);
1596 from->array.i.enabled = to->array.i.enabled;
1597 }
1598 for (i = 0; (unsigned int)i < toCtx->limits.maxTextureUnits; i++) {
1599 if (from->array.t[i].enabled != to->array.t[i].enabled) {
1600 diff_api.ClientActiveTextureARB(GL_TEXTURE0_ARB + i);
1601 able[to->array.t[i].enabled](GL_TEXTURE_COORD_ARRAY);
1602 from->array.t[i].enabled = to->array.t[i].enabled;
1603 }
1604 }
1605 if (from->array.e.enabled != to->array.e.enabled) {
1606 able[to->array.e.enabled](GL_EDGE_FLAG_ARRAY);
1607 from->array.e.enabled = to->array.e.enabled;
1608 }
1609 if (from->array.s.enabled != to->array.s.enabled) {
1610 able[to->array.s.enabled](GL_SECONDARY_COLOR_ARRAY_EXT);
1611 from->array.s.enabled = to->array.s.enabled;
1612 }
1613 if (from->array.f.enabled != to->array.f.enabled) {
1614 able[to->array.f.enabled](GL_FOG_COORDINATE_ARRAY_EXT);
1615 from->array.f.enabled = to->array.f.enabled;
1616 }
1617 for (i = 0; (unsigned int)i < toCtx->limits.maxVertexProgramAttribs; i++) {
1618 if (from->array.a[i].enabled != to->array.a[i].enabled) {
1619 able[to->array.a[i].enabled](GL_VERTEX_ATTRIB_ARRAY0_NV + i);
1620 from->array.a[i].enabled = to->array.a[i].enabled;
1621 }
1622 }
1623 CLEARDIRTY2(cb->enableClientState, bitID);
1624 }
1625}
1626
1627
1628void
1629crStateClientSwitch(CRClientBits *cb, CRbitvalue *bitID,
1630 CRContext *fromCtx, CRContext *toCtx)
1631{
1632 const CRClientState *from = &(fromCtx->client);
1633 const CRClientState *to = &(toCtx->client);
1634 int i;
1635
1636 if (CHECKDIRTY(cb->clientPointer, bitID)) {
1637 /* one or more vertex pointers is dirty */
1638 if (CHECKDIRTY(cb->v, bitID)) {
1639 if (from->array.v.size != to->array.v.size ||
1640 from->array.v.type != to->array.v.type ||
1641 from->array.v.stride != to->array.v.stride ||
1642 from->array.v.buffer != to->array.v.buffer) {
1643 diff_api.VertexPointer(to->array.v.size, to->array.v.type,
1644 to->array.v.stride, to->array.v.p);
1645 FILLDIRTY(cb->v);
1646 FILLDIRTY(cb->clientPointer);
1647 }
1648 CLEARDIRTY2(cb->v, bitID);
1649 }
1650 /* normal */
1651 if (CHECKDIRTY(cb->n, bitID)) {
1652 if (from->array.n.type != to->array.n.type ||
1653 from->array.n.stride != to->array.n.stride ||
1654 from->array.n.buffer != to->array.n.buffer) {
1655 diff_api.NormalPointer(to->array.n.type,
1656 to->array.n.stride, to->array.n.p);
1657 FILLDIRTY(cb->n);
1658 FILLDIRTY(cb->clientPointer);
1659 }
1660 CLEARDIRTY2(cb->n, bitID);
1661 }
1662 /* color */
1663 if (CHECKDIRTY(cb->c, bitID)) {
1664 if (from->array.c.size != to->array.c.size ||
1665 from->array.c.type != to->array.c.type ||
1666 from->array.c.stride != to->array.c.stride ||
1667 from->array.c.buffer != to->array.c.buffer) {
1668 diff_api.ColorPointer(to->array.c.size, to->array.c.type,
1669 to->array.c.stride, to->array.c.p);
1670 FILLDIRTY(cb->c);
1671 FILLDIRTY(cb->clientPointer);
1672 }
1673 CLEARDIRTY2(cb->c, bitID);
1674 }
1675 /* index */
1676 if (CHECKDIRTY(cb->i, bitID)) {
1677 if (from->array.i.type != to->array.i.type ||
1678 from->array.i.stride != to->array.i.stride ||
1679 from->array.i.buffer != to->array.i.buffer) {
1680 diff_api.IndexPointer(to->array.i.type,
1681 to->array.i.stride, to->array.i.p);
1682 FILLDIRTY(cb->i);
1683 FILLDIRTY(cb->clientPointer);
1684 }
1685 CLEARDIRTY2(cb->i, bitID);
1686 }
1687 /* texcoords */
1688 for (i = 0; (unsigned int)i < toCtx->limits.maxTextureUnits; i++) {
1689 if (CHECKDIRTY(cb->t[i], bitID)) {
1690 if (from->array.t[i].size != to->array.t[i].size ||
1691 from->array.t[i].type != to->array.t[i].type ||
1692 from->array.t[i].stride != to->array.t[i].stride ||
1693 from->array.t[i].buffer != to->array.t[i].buffer) {
1694 diff_api.ClientActiveTextureARB(GL_TEXTURE0_ARB + i);
1695 diff_api.TexCoordPointer(to->array.t[i].size, to->array.t[i].type,
1696 to->array.t[i].stride, to->array.t[i].p);
1697 FILLDIRTY(cb->t[i]);
1698 FILLDIRTY(cb->clientPointer);
1699 }
1700 CLEARDIRTY2(cb->t[i], bitID);
1701 }
1702 }
1703 /* edge flag */
1704 if (CHECKDIRTY(cb->e, bitID)) {
1705 if (from->array.e.stride != to->array.e.stride ||
1706 from->array.e.buffer != to->array.e.buffer) {
1707 diff_api.EdgeFlagPointer(to->array.e.stride, to->array.e.p);
1708 FILLDIRTY(cb->e);
1709 FILLDIRTY(cb->clientPointer);
1710 }
1711 CLEARDIRTY2(cb->e, bitID);
1712 }
1713 /* secondary color */
1714 if (CHECKDIRTY(cb->s, bitID)) {
1715 if (from->array.s.size != to->array.s.size ||
1716 from->array.s.type != to->array.s.type ||
1717 from->array.s.stride != to->array.s.stride ||
1718 from->array.s.buffer != to->array.s.buffer) {
1719 diff_api.SecondaryColorPointerEXT(to->array.s.size, to->array.s.type,
1720 to->array.s.stride, to->array.s.p);
1721 FILLDIRTY(cb->s);
1722 FILLDIRTY(cb->clientPointer);
1723 }
1724 CLEARDIRTY2(cb->s, bitID);
1725 }
1726 /* fog coord */
1727 if (CHECKDIRTY(cb->f, bitID)) {
1728 if (from->array.f.type != to->array.f.type ||
1729 from->array.f.stride != to->array.f.stride ||
1730 from->array.f.buffer != to->array.f.buffer) {
1731 diff_api.FogCoordPointerEXT(to->array.f.type,
1732 to->array.f.stride, to->array.f.p);
1733 FILLDIRTY(cb->f);
1734 FILLDIRTY(cb->clientPointer);
1735 }
1736 CLEARDIRTY2(cb->f, bitID);
1737 }
1738#if defined(CR_NV_vertex_program) || defined(CR_ARB_vertex_program)
1739 /* vertex attributes */
1740 for (i = 0; (unsigned int)i < toCtx->limits.maxVertexProgramAttribs; i++) {
1741 if (CHECKDIRTY(cb->a[i], bitID)) {
1742 if (from->array.a[i].size != to->array.a[i].size ||
1743 from->array.a[i].type != to->array.a[i].type ||
1744 from->array.a[i].stride != to->array.a[i].stride ||
1745 from->array.a[i].normalized != to->array.a[i].normalized ||
1746 from->array.a[i].buffer != to->array.a[i].buffer) {
1747 diff_api.VertexAttribPointerARB(i, to->array.a[i].size,
1748 to->array.a[i].type,
1749 to->array.a[i].normalized,
1750 to->array.a[i].stride,
1751 to->array.a[i].p);
1752 FILLDIRTY(cb->a[i]);
1753 FILLDIRTY(cb->clientPointer);
1754 }
1755 CLEARDIRTY2(cb->a[i], bitID);
1756 }
1757 }
1758#endif
1759 }
1760
1761 if (CHECKDIRTY(cb->enableClientState, bitID)) {
1762 /* update vertex array enable/disable flags */
1763 glAble able[2];
1764 able[0] = diff_api.Disable;
1765 able[1] = diff_api.Enable;
1766 if (from->array.v.enabled != to->array.v.enabled) {
1767 able[to->array.v.enabled](GL_VERTEX_ARRAY);
1768 FILLDIRTY(cb->enableClientState);
1769 }
1770 if (from->array.n.enabled != to->array.n.enabled) {
1771 able[to->array.n.enabled](GL_NORMAL_ARRAY);
1772 FILLDIRTY(cb->enableClientState);
1773 }
1774 if (from->array.c.enabled != to->array.c.enabled) {
1775 able[to->array.c.enabled](GL_COLOR_ARRAY);
1776 FILLDIRTY(cb->enableClientState);
1777 }
1778 if (from->array.i.enabled != to->array.i.enabled) {
1779 able[to->array.i.enabled](GL_INDEX_ARRAY);
1780 FILLDIRTY(cb->enableClientState);
1781 }
1782 for (i = 0; (unsigned int)i < toCtx->limits.maxTextureUnits; i++) {
1783 if (from->array.t[i].enabled != to->array.t[i].enabled) {
1784 diff_api.ClientActiveTextureARB(GL_TEXTURE0_ARB + i);
1785 able[to->array.t[i].enabled](GL_TEXTURE_COORD_ARRAY);
1786 FILLDIRTY(cb->enableClientState);
1787 }
1788 }
1789 if (from->array.e.enabled != to->array.e.enabled) {
1790 able[to->array.e.enabled](GL_EDGE_FLAG_ARRAY);
1791 FILLDIRTY(cb->enableClientState);
1792 }
1793 if (from->array.s.enabled != to->array.s.enabled) {
1794 able[to->array.s.enabled](GL_SECONDARY_COLOR_ARRAY_EXT);
1795 FILLDIRTY(cb->enableClientState);
1796 }
1797 if (from->array.f.enabled != to->array.f.enabled) {
1798 able[to->array.f.enabled](GL_FOG_COORDINATE_ARRAY_EXT);
1799 FILLDIRTY(cb->enableClientState);
1800 }
1801 for (i = 0; (unsigned int)i < toCtx->limits.maxVertexProgramAttribs; i++) {
1802 if (from->array.a[i].enabled != to->array.a[i].enabled) {
1803 able[to->array.a[i].enabled](GL_VERTEX_ATTRIB_ARRAY0_NV + i);
1804 FILLDIRTY(cb->enableClientState);
1805 }
1806 }
1807 CLEARDIRTY2(cb->enableClientState, bitID);
1808 }
1809}
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette