summaryrefslogtreecommitdiff
path: root/src/VBox/GuestHost/OpenGL/state_tracker/state_enable.c
blob: 185de9ebf8967f87ec1b569a2b369157e8a65dbd (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
/* Copyright (c) 2001, Stanford University
 * All rights reserved
 *
 * See the file LICENSE.txt for information on redistributing this software.
 */

#include <stdio.h>
#include "state.h"
#include "state/cr_statetypes.h"
#include "state_internals.h"

static void __enableSet (CRContext *g, CRStateBits *sb, CRbitvalue *neg_bitid,
				GLenum cap, GLboolean val)
{
	unsigned int i;
	i = cap - GL_CLIP_PLANE0;
	if (i < g->limits.maxClipPlanes) {
		g->transform.clip[i] = val;
		DIRTY(sb->transform.enable, neg_bitid);
		DIRTY(sb->transform.dirty, neg_bitid);
		return;
	}
	i = cap - GL_LIGHT0;
	if (i < g->limits.maxLights) {
		g->lighting.light[i].enable = val;
		DIRTY(sb->lighting.light[i].dirty, neg_bitid);
		DIRTY(sb->lighting.light[i].enable, neg_bitid);
		DIRTY(sb->lighting.dirty, neg_bitid);
		return;
	}

	switch (cap) {
		case GL_AUTO_NORMAL:
			g->eval.autoNormal = val;
			DIRTY(sb->eval.enable, neg_bitid);
			DIRTY(sb->eval.dirty, neg_bitid);
			break;
		case GL_ALPHA_TEST:
			g->buffer.alphaTest = val;
			DIRTY(sb->buffer.enable, neg_bitid);
			DIRTY(sb->buffer.dirty, neg_bitid);
			break;
		case GL_BLEND:
			g->buffer.blend = val;
			DIRTY(sb->buffer.enable, neg_bitid);
			DIRTY(sb->buffer.dirty, neg_bitid);
			break;
		case GL_COLOR_MATERIAL :
			if (!val)
			{
				/* We're TURNING OFF color material.  In this case,
				 * we should make sure that the very very latest
				 * color that was specified gets copied into the
				 * material parameters, since this might be our
				 * last chance (see frame 1 of progs/kirchner
				 * for an example of why). */

				crStateCurrentRecover( );
				crStateColorMaterialRecover( );
			}
			g->lighting.colorMaterial = val;
			DIRTY(sb->lighting.enable, neg_bitid);
			DIRTY(sb->lighting.dirty, neg_bitid);
			break;
#ifdef CR_EXT_secondary_color
		case GL_COLOR_SUM_EXT :
			if (g->extensions.EXT_secondary_color) { /* XXX does EXT_separate_specular color support this enable, too? */
				g->lighting.colorSumEXT = val;
				DIRTY(sb->lighting.enable, neg_bitid);
				DIRTY(sb->lighting.dirty, neg_bitid);
			}
			else {
				crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glEnable/glDisable(GL_COLOR_SUM_EXT) - No support for secondary color!");
				return;
			}
			break;
#endif
		case GL_CULL_FACE :
			g->polygon.cullFace = val;
			DIRTY(sb->polygon.enable, neg_bitid);
			DIRTY(sb->polygon.dirty, neg_bitid);
			break;
		case GL_DEPTH_TEST :
			g->buffer.depthTest = val;
			DIRTY(sb->buffer.enable, neg_bitid);
			DIRTY(sb->buffer.dirty, neg_bitid);
			break;
		case GL_DITHER :
			g->buffer.dither = val;
			DIRTY(sb->buffer.enable, neg_bitid);
			DIRTY(sb->buffer.dirty, neg_bitid);
			break;
		case GL_FOG :
			g->fog.enable = val;
			DIRTY(sb->fog.enable, neg_bitid);
			DIRTY(sb->fog.dirty, neg_bitid);
			break;
		case GL_LIGHTING :
			g->lighting.lighting = val;
			DIRTY(sb->lighting.enable, neg_bitid);
			DIRTY(sb->lighting.dirty, neg_bitid);
			break;
		case GL_LINE_SMOOTH :
			g->line.lineSmooth = val;
			DIRTY(sb->line.enable, neg_bitid);
			DIRTY(sb->line.dirty, neg_bitid);
			break;
		case GL_LINE_STIPPLE :
			g->line.lineStipple = val;
			DIRTY(sb->line.enable, neg_bitid);
			DIRTY(sb->line.dirty, neg_bitid);
			break;
		case GL_COLOR_LOGIC_OP :
			g->buffer.logicOp = val;
			DIRTY(sb->buffer.enable, neg_bitid);
			DIRTY(sb->buffer.dirty, neg_bitid);
			break;
		case GL_INDEX_LOGIC_OP : 	
			g->buffer.indexLogicOp = val;
			DIRTY(sb->buffer.enable, neg_bitid);
			DIRTY(sb->buffer.dirty, neg_bitid);
			break;
		case GL_NORMALIZE :
			g->transform.normalize = val;
			DIRTY(sb->transform.enable, neg_bitid);
			DIRTY(sb->transform.dirty, neg_bitid);
			break;
		case GL_POINT_SMOOTH :
			g->point.pointSmooth = val;
			DIRTY(sb->point.enableSmooth, neg_bitid);
			DIRTY(sb->point.dirty, neg_bitid);
			break;
		case GL_POLYGON_OFFSET_FILL:
			g->polygon.polygonOffsetFill = val;
			DIRTY(sb->polygon.enable, neg_bitid);
			DIRTY(sb->polygon.dirty, neg_bitid);
			break;
		case GL_POLYGON_OFFSET_LINE:
			g->polygon.polygonOffsetLine = val;
			DIRTY(sb->polygon.enable, neg_bitid);
			DIRTY(sb->polygon.dirty, neg_bitid);
			break;
		case GL_POLYGON_OFFSET_POINT:
			g->polygon.polygonOffsetPoint = val;
			DIRTY(sb->polygon.enable, neg_bitid);
			DIRTY(sb->polygon.dirty, neg_bitid);
			break;
		case GL_POLYGON_SMOOTH :
			g->polygon.polygonSmooth = val;
			DIRTY(sb->polygon.enable, neg_bitid);
			DIRTY(sb->polygon.dirty, neg_bitid);
			break;
		case GL_POLYGON_STIPPLE :
			g->polygon.polygonStipple = val;
			DIRTY(sb->polygon.enable, neg_bitid);
			DIRTY(sb->polygon.dirty, neg_bitid);
			break;
#ifdef CR_NV_register_combiners
		case GL_REGISTER_COMBINERS_NV :
			if (g->extensions.NV_register_combiners) {
				g->regcombiner.enabledRegCombiners = val;
				DIRTY(sb->regcombiner.enable, neg_bitid);
				DIRTY(sb->regcombiner.dirty, neg_bitid);
			}
			else {
				crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glEnable/glDisable(GL_REGISTER_COMBINERS_NV) - No support for NV_register_combiners");
				return;
			}
			break;
#endif
#ifdef CR_NV_register_combiners2
		case GL_PER_STAGE_CONSTANTS_NV :
			if (g->extensions.NV_register_combiners2) {
				g->regcombiner.enabledPerStageConstants = val;
				DIRTY(sb->regcombiner.enable, neg_bitid);
				DIRTY(sb->regcombiner.dirty, neg_bitid);
			}
			else {
				crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glEnable/glDisable(GL_PER_STAGE_CONSTANTS_NV) - No support for NV_register_combiners2");
				return;
			}
			break;
#endif
#ifdef CR_NV_texture_rectangle
		case GL_TEXTURE_RECTANGLE_NV:
			if (g->extensions.NV_texture_rectangle) {
				g->texture.unit[g->texture.curTextureUnit].enabledRect = val;
				DIRTY(sb->texture.enable[g->texture.curTextureUnit], neg_bitid);
				DIRTY(sb->texture.dirty, neg_bitid);
			}
			else {
				crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glEnable/glDisable(0x%x)", cap);
				return;
			}
			break;
#endif /* CR_NV_texture_rectangle */
#ifdef CR_OPENGL_VERSION_1_2
		case GL_RESCALE_NORMAL :
			g->transform.rescaleNormals = val;
			DIRTY(sb->transform.enable, neg_bitid);
			DIRTY(sb->transform.dirty, neg_bitid);
			break;
#endif
		case GL_SCISSOR_TEST :
			g->viewport.scissorTest = val;
			DIRTY(sb->viewport.enable, neg_bitid);
			DIRTY(sb->viewport.dirty, neg_bitid);
			break;
		case GL_STENCIL_TEST :
			g->stencil.stencilTest= val;
			DIRTY(sb->stencil.enable, neg_bitid);
			DIRTY(sb->stencil.dirty, neg_bitid);
			break;
		case GL_TEXTURE_1D :
			g->texture.unit[g->texture.curTextureUnit].enabled1D = val;
			DIRTY(sb->texture.enable[g->texture.curTextureUnit], neg_bitid);
			DIRTY(sb->texture.dirty, neg_bitid);
			break;
		case GL_TEXTURE_2D :
			g->texture.unit[g->texture.curTextureUnit].enabled2D = val;
			DIRTY(sb->texture.enable[g->texture.curTextureUnit], neg_bitid);
			DIRTY(sb->texture.dirty, neg_bitid);
			break;
#ifdef CR_OPENGL_VERSION_1_2
		case GL_TEXTURE_3D :
			g->texture.unit[g->texture.curTextureUnit].enabled3D = val;
			DIRTY(sb->texture.enable[g->texture.curTextureUnit], neg_bitid);
			DIRTY(sb->texture.dirty, neg_bitid);
			break;
#endif
#ifdef CR_ARB_texture_cube_map
		case GL_TEXTURE_CUBE_MAP_ARB:
			if (g->extensions.ARB_texture_cube_map) {
				g->texture.unit[g->texture.curTextureUnit].enabledCubeMap = val;
				DIRTY(sb->texture.enable[g->texture.curTextureUnit], neg_bitid);
				DIRTY(sb->texture.dirty, neg_bitid);
			}
			else {
				crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glEnable/glDisable(0x%x)", cap);
				return;
			}
			break;
#endif /* CR_ARB_texture_cube_map */
		case GL_TEXTURE_GEN_Q :
			g->texture.unit[g->texture.curTextureUnit].textureGen.q = val;
			DIRTY(sb->texture.enable[g->texture.curTextureUnit], neg_bitid);
			DIRTY(sb->texture.dirty, neg_bitid);
			break;
		case GL_TEXTURE_GEN_R :
			g->texture.unit[g->texture.curTextureUnit].textureGen.r = val;
			DIRTY(sb->texture.enable[g->texture.curTextureUnit], neg_bitid);
			DIRTY(sb->texture.dirty, neg_bitid);
			break;
		case GL_TEXTURE_GEN_S :
			g->texture.unit[g->texture.curTextureUnit].textureGen.s = val;
			DIRTY(sb->texture.enable[g->texture.curTextureUnit], neg_bitid);
			DIRTY(sb->texture.dirty, neg_bitid);
			break;
		case GL_TEXTURE_GEN_T :
			g->texture.unit[g->texture.curTextureUnit].textureGen.t = val;
			DIRTY(sb->texture.enable[g->texture.curTextureUnit], neg_bitid);
			DIRTY(sb->texture.dirty, neg_bitid);
			break;
		case GL_MAP1_COLOR_4 :
		case GL_MAP1_INDEX :
		case GL_MAP1_NORMAL :
		case GL_MAP1_TEXTURE_COORD_1 :
		case GL_MAP1_TEXTURE_COORD_2 :
		case GL_MAP1_TEXTURE_COORD_3 :
		case GL_MAP1_TEXTURE_COORD_4 :
		case GL_MAP1_VERTEX_3 :
		case GL_MAP1_VERTEX_4 :
			if (g->texture.curTextureUnit != 0)
			{
				crStateError( __LINE__, __FILE__, GL_INVALID_OPERATION, "Map stuff was enabled while the current texture unit was not GL_TEXTURE0_ARB!" );
				return;
			}
			g->eval.enable1D[cap - GL_MAP1_COLOR_4] = val;
			DIRTY(sb->eval.enable1D[cap - GL_MAP1_COLOR_4], neg_bitid);
			DIRTY(sb->eval.dirty, neg_bitid);
			break;
		case GL_MAP2_COLOR_4 :
		case GL_MAP2_INDEX :
		case GL_MAP2_NORMAL :
		case GL_MAP2_TEXTURE_COORD_1 :
		case GL_MAP2_TEXTURE_COORD_2 :
		case GL_MAP2_TEXTURE_COORD_3 :
		case GL_MAP2_TEXTURE_COORD_4 :
		case GL_MAP2_VERTEX_3 :
		case GL_MAP2_VERTEX_4 :
#if 0
			if (g->texture.curTextureUnit != 0)
			{
				crStateError( __LINE__, __FILE__, GL_INVALID_OPERATION, "Map stuff was enabled while the current texture unit was not GL_TEXTURE0_ARB!" );
				return;
			}
#endif
			g->eval.enable2D[cap - GL_MAP2_COLOR_4] = val;
			DIRTY(sb->eval.enable2D[cap - GL_MAP2_COLOR_4], neg_bitid);
			DIRTY(sb->eval.dirty, neg_bitid);
			break;
#ifdef CR_ARB_multisample
		case GL_MULTISAMPLE_ARB:
			g->multisample.enabled = val;
			DIRTY(sb->multisample.enable, neg_bitid);
			DIRTY(sb->multisample.dirty, neg_bitid);
			break;
		case GL_SAMPLE_ALPHA_TO_COVERAGE_ARB:
			g->multisample.sampleAlphaToCoverage = val;
			DIRTY(sb->multisample.sampleAlphaToCoverage, neg_bitid);
			DIRTY(sb->multisample.dirty, neg_bitid);
			break;
		case GL_SAMPLE_ALPHA_TO_ONE_ARB:
			g->multisample.sampleAlphaToOne = val;
			DIRTY(sb->multisample.sampleAlphaToOne, neg_bitid);
			DIRTY(sb->multisample.dirty, neg_bitid);
			break;
		case GL_SAMPLE_COVERAGE_ARB:
			g->multisample.sampleCoverage = val;
			DIRTY(sb->multisample.sampleCoverage, neg_bitid);
			DIRTY(sb->multisample.dirty, neg_bitid);
			break;
#endif
#ifdef CR_NV_vertex_program
		case GL_VERTEX_PROGRAM_NV:
			if (g->extensions.NV_vertex_program) {
				g->program.vpEnabled = val;
				DIRTY(sb->program.vpEnable, neg_bitid);
				DIRTY(sb->program.dirty, neg_bitid);
			}
			else if (g->extensions.ARB_vertex_program) {
				g->program.vpEnabled = val;
				DIRTY(sb->program.vpEnable, neg_bitid);
				DIRTY(sb->program.dirty, neg_bitid);
			}
			else {
				crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glEnable/glDisable(0x%x)", cap);
				return;
			}
			break;
		case GL_VERTEX_PROGRAM_POINT_SIZE_NV:
			if (g->extensions.NV_vertex_program) {
				g->program.vpPointSize = val;
				DIRTY(sb->program.vpEnable, neg_bitid);
				DIRTY(sb->program.dirty, neg_bitid);
			}
			else if (g->extensions.ARB_vertex_program) {
				g->program.vpPointSize = val;
				DIRTY(sb->program.vpEnable, neg_bitid);
				DIRTY(sb->program.dirty, neg_bitid);
			}
			else {
				crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glEnable/glDisable(0x%x)", cap);
				return;
			}
			break;
		case GL_VERTEX_PROGRAM_TWO_SIDE_NV:
			if (g->extensions.NV_vertex_program) {
				g->program.vpTwoSide = val;
				DIRTY(sb->program.vpEnable, neg_bitid);
				DIRTY(sb->program.dirty, neg_bitid);
			}
			else if (g->extensions.ARB_vertex_program) {
				g->program.vpTwoSide = val;
				DIRTY(sb->program.vpEnable, neg_bitid);
				DIRTY(sb->program.dirty, neg_bitid);
			}
			else {
				crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glEnable/glDisable(0x%x)", cap);
				return;
			}
			break;

		case GL_MAP1_VERTEX_ATTRIB0_4_NV:
		case GL_MAP1_VERTEX_ATTRIB1_4_NV:
		case GL_MAP1_VERTEX_ATTRIB2_4_NV:
		case GL_MAP1_VERTEX_ATTRIB3_4_NV:
		case GL_MAP1_VERTEX_ATTRIB4_4_NV:
		case GL_MAP1_VERTEX_ATTRIB5_4_NV:
		case GL_MAP1_VERTEX_ATTRIB6_4_NV:
		case GL_MAP1_VERTEX_ATTRIB7_4_NV:
		case GL_MAP1_VERTEX_ATTRIB8_4_NV:
		case GL_MAP1_VERTEX_ATTRIB9_4_NV:
		case GL_MAP1_VERTEX_ATTRIB10_4_NV:
		case GL_MAP1_VERTEX_ATTRIB11_4_NV:
		case GL_MAP1_VERTEX_ATTRIB12_4_NV:
		case GL_MAP1_VERTEX_ATTRIB13_4_NV:
		case GL_MAP1_VERTEX_ATTRIB14_4_NV:
		case GL_MAP1_VERTEX_ATTRIB15_4_NV:
			{
				const GLint i = cap - GL_MAP1_VERTEX_ATTRIB0_4_NV;
				g->eval.enableAttrib1D[i] = val;
				DIRTY(sb->program.map1AttribArrayEnable[i], neg_bitid);
				DIRTY(sb->program.dirty, neg_bitid);
			}
			break;
		case GL_MAP2_VERTEX_ATTRIB0_4_NV:
		case GL_MAP2_VERTEX_ATTRIB1_4_NV:
		case GL_MAP2_VERTEX_ATTRIB2_4_NV:
		case GL_MAP2_VERTEX_ATTRIB3_4_NV:
		case GL_MAP2_VERTEX_ATTRIB4_4_NV:
		case GL_MAP2_VERTEX_ATTRIB5_4_NV:
		case GL_MAP2_VERTEX_ATTRIB6_4_NV:
		case GL_MAP2_VERTEX_ATTRIB7_4_NV:
		case GL_MAP2_VERTEX_ATTRIB8_4_NV:
		case GL_MAP2_VERTEX_ATTRIB9_4_NV:
		case GL_MAP2_VERTEX_ATTRIB10_4_NV:
		case GL_MAP2_VERTEX_ATTRIB11_4_NV:
		case GL_MAP2_VERTEX_ATTRIB12_4_NV:
		case GL_MAP2_VERTEX_ATTRIB13_4_NV:
		case GL_MAP2_VERTEX_ATTRIB14_4_NV:
		case GL_MAP2_VERTEX_ATTRIB15_4_NV:
			{
				const GLint i = cap - GL_MAP2_VERTEX_ATTRIB0_4_NV;
				g->eval.enableAttrib2D[i] = val;
				DIRTY(sb->program.map2AttribArrayEnable[i], neg_bitid);
				DIRTY(sb->program.dirty, neg_bitid);
			}
			break;
#endif
#ifdef CR_NV_fragment_program
		case GL_FRAGMENT_PROGRAM_NV:
			if (g->extensions.NV_fragment_program) {
				g->program.fpEnabled = val;
				DIRTY(sb->program.fpEnable, neg_bitid);
				DIRTY(sb->program.dirty, neg_bitid);
			}
			else {
				crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glEnable/glDisable(0x%x)", cap);
				return;
			}
			break;
#endif
#ifdef CR_ARB_fragment_program
		case GL_FRAGMENT_PROGRAM_ARB:
			if (g->extensions.ARB_fragment_program) {
				g->program.fpEnabledARB = val;
				DIRTY(sb->program.fpEnable, neg_bitid);
				DIRTY(sb->program.dirty, neg_bitid);
			}
			else {
				crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glEnable/glDisable(0x%x)", cap);
				return;
			}
			break;
#endif
#ifdef CR_IBM_rasterpos_clip
		case GL_RASTER_POSITION_UNCLIPPED_IBM:
			g->transform.rasterPositionUnclipped = val;
			DIRTY(sb->transform.enable, neg_bitid);
			DIRTY(sb->transform.dirty, neg_bitid);
			break;
#endif

#ifdef CR_ARB_point_sprite
		case GL_POINT_SPRITE_ARB:
			g->point.pointSprite = val;
			DIRTY(sb->point.enableSprite, neg_bitid);
			DIRTY(sb->point.dirty, neg_bitid);
			break;
#endif

		/* Client-side enables */
		case GL_VERTEX_ARRAY:
		case GL_COLOR_ARRAY:
		case GL_NORMAL_ARRAY:
		case GL_INDEX_ARRAY:
		case GL_TEXTURE_COORD_ARRAY:
		case GL_EDGE_FLAG_ARRAY:
#ifdef CR_EXT_fog_coord
		case GL_FOG_COORDINATE_ARRAY_POINTER_EXT:
#endif
#ifdef CR_EXT_secondary_color
		case GL_SECONDARY_COLOR_ARRAY_EXT:
#endif
#ifdef CR_NV_vertex_program
		case GL_VERTEX_ATTRIB_ARRAY0_NV:
		case GL_VERTEX_ATTRIB_ARRAY1_NV:
		case GL_VERTEX_ATTRIB_ARRAY2_NV:
		case GL_VERTEX_ATTRIB_ARRAY3_NV:
		case GL_VERTEX_ATTRIB_ARRAY4_NV:
		case GL_VERTEX_ATTRIB_ARRAY5_NV:
		case GL_VERTEX_ATTRIB_ARRAY6_NV:
		case GL_VERTEX_ATTRIB_ARRAY7_NV:
		case GL_VERTEX_ATTRIB_ARRAY8_NV:
		case GL_VERTEX_ATTRIB_ARRAY9_NV:
		case GL_VERTEX_ATTRIB_ARRAY10_NV:
		case GL_VERTEX_ATTRIB_ARRAY11_NV:
		case GL_VERTEX_ATTRIB_ARRAY12_NV:
		case GL_VERTEX_ATTRIB_ARRAY13_NV:
		case GL_VERTEX_ATTRIB_ARRAY14_NV:
		case GL_VERTEX_ATTRIB_ARRAY15_NV:
#endif
			if (val)
				crStateEnableClientState(cap);
			else
				crStateDisableClientState(cap);
			break;
#ifdef CR_EXT_stencil_two_side
		case GL_STENCIL_TEST_TWO_SIDE_EXT:
            g->stencil.stencilTwoSideEXT= val;
            DIRTY(sb->stencil.enableTwoSideEXT, neg_bitid);
            DIRTY(sb->stencil.dirty, neg_bitid);
		    break;
#endif
		default:
			crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glEnable/glDisable called with bogus cap: 0x%x", cap);
			return;
	}
}


void STATE_APIENTRY crStateEnable (GLenum cap)
{
	CRContext *g = GetCurrentContext();
	CRStateBits *sb = GetCurrentBits();

	if (g->current.inBeginEnd)
	{
		crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, "glEnable called in begin/end");
		return;
	}

	FLUSH();

	__enableSet(g, sb, g->neg_bitid, cap, GL_TRUE);
}


void STATE_APIENTRY crStateDisable (GLenum cap)
{
	CRContext *g = GetCurrentContext();
	CRStateBits *sb = GetCurrentBits();

	if (g->current.inBeginEnd)
	{
		crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, "glDisable called in begin/end");
		return;
	}

	FLUSH();

	__enableSet(g, sb, g->neg_bitid, cap, GL_FALSE);
}