VirtualBox

source: vbox/trunk/src/VBox/GuestHost/OpenGL/state_tracker/state_program.c@ 59454

最後變更 在這個檔案從59454是 48491,由 vboxsync 提交於 11 年 前

crOpenGL: chrome fixes

  • 屬性 svn:eol-style 設為 native
  • 屬性 svn:keywords 設為 Id
檔案大小: 81.8 KB
 
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#include "state.h"
8#include "state_internals.h"
9#include "cr_mem.h"
10#include "cr_string.h"
11
12
13/*
14 * General notes:
15 *
16 * Vertex programs can change vertices so bounding boxes may not be
17 * practical for tilesort. Tilesort may have to broadcast geometry
18 * when vertex programs are in effect. We could semi-parse vertex
19 * programs to determine if they write to the o[HPOS] register.
20 */
21
22
23/*
24 * Lookup the named program and return a pointer to it.
25 * If the program doesn't exist, create it and reserve its Id and put
26 * it into the hash table.
27 */
28static CRProgram *
29GetProgram(CRProgramState *p, GLenum target, GLuint id)
30{
31 CRProgram *prog;
32
33 prog = crHashtableSearch(p->programHash, id);
34 if (!prog) {
35 prog = (CRProgram *) crCalloc(sizeof(CRProgram));
36 if (!prog)
37 return NULL;
38 prog->target = target;
39 prog->id = id;
40 prog->format = GL_PROGRAM_FORMAT_ASCII_ARB;
41 prog->resident = GL_TRUE;
42 prog->symbolTable = NULL;
43
44 if (id > 0)
45 crHashtableAdd(p->programHash, id, (void *) prog);
46 }
47 return prog;
48}
49
50
51/*
52 * Delete a CRProgram object and all attached data.
53 */
54static void
55DeleteProgram(CRProgram *prog)
56{
57 CRProgramSymbol *symbol, *next;
58
59 if (prog->string)
60 crFree((void *) prog->string);
61
62 for (symbol = prog->symbolTable; symbol; symbol = next) {
63 next = symbol->next;
64 crFree((void *) symbol->name);
65 crFree(symbol);
66 }
67 crFree(prog);
68}
69
70
71/*
72 * Set the named symbol to the value (x, y, z, w).
73 * NOTE: Symbols should only really be added during parsing of the program.
74 * However, the state tracker does not parse the programs (yet). So, when
75 * someone calls glProgramNamedParameter4fNV() we always enter the symbol
76 * since we don't know if it's really valid or not.
77 */
78static void
79SetProgramSymbol(CRProgram *prog, const char *name, GLsizei len,
80 GLfloat x, GLfloat y, GLfloat z, GLfloat w)
81{
82 CRProgramSymbol *symbol;
83
84 for (symbol = prog->symbolTable; symbol; symbol = symbol->next) {
85 /* NOTE: <name> may not be null-terminated! */
86 if (crStrncmp(symbol->name, name, len) == 0 && symbol->name[len] == 0) {
87 /* found it */
88 symbol->value[0] = x;
89 symbol->value[1] = y;
90 symbol->value[2] = z;
91 symbol->value[3] = w;
92 FILLDIRTY(symbol->dirty);
93 return;
94 }
95 }
96 /* add new symbol table entry */
97 symbol = (CRProgramSymbol *) crAlloc(sizeof(CRProgramSymbol));
98 if (symbol) {
99 symbol->name = crStrndup(name, len);
100 symbol->cbName = len;
101 symbol->value[0] = x;
102 symbol->value[1] = y;
103 symbol->value[2] = z;
104 symbol->value[3] = w;
105 symbol->next = prog->symbolTable;
106 prog->symbolTable = symbol;
107 FILLDIRTY(symbol->dirty);
108 }
109}
110
111
112/*
113 * Return a pointer to the values for the given symbol. Return NULL if
114 * the name doesn't exist in the symbol table.
115 */
116static const GLfloat *
117GetProgramSymbol(const CRProgram *prog, const char *name, GLsizei len)
118{
119 CRProgramSymbol *symbol = prog->symbolTable;
120 for (symbol = prog->symbolTable; symbol; symbol = symbol->next) {
121 /* NOTE: <name> may not be null-terminated! */
122 if (crStrncmp(symbol->name, name, len) == 0 && symbol->name[len] == 0) {
123 return symbol->value;
124 }
125 }
126 return NULL;
127}
128
129
130/*
131 * Used by both glBindProgramNV and glBindProgramARB
132 */
133static CRProgram *
134BindProgram(GLenum target, GLuint id,
135 GLenum vertexTarget, GLenum fragmentTarget)
136{
137 CRContext *g = GetCurrentContext();
138 CRProgramState *p = &(g->program);
139 CRStateBits *sb = GetCurrentBits();
140 CRProgramBits *pb = &(sb->program);
141 CRProgram *prog;
142
143 if (g->current.inBeginEnd) {
144 crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION,
145 "glBindProgram called in Begin/End");
146 return NULL;
147 }
148
149 if (id == 0) {
150 if (target == vertexTarget) {
151 prog = p->defaultVertexProgram;
152 }
153 else if (target == fragmentTarget) {
154 prog = p->defaultFragmentProgram;
155 }
156 else {
157 crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION,
158 "glBindProgram(bad target)");
159 return NULL;
160 }
161 }
162 else {
163 prog = GetProgram(p, target, id );
164 }
165
166 if (!prog) {
167 crStateError(__LINE__, __FILE__, GL_OUT_OF_MEMORY, "glBindProgram");
168 return NULL;
169 }
170 else if (prog->target != target) {
171 crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION,
172 "glBindProgram target mismatch");
173 return NULL;
174 }
175
176 if (target == vertexTarget) {
177 p->currentVertexProgram = prog;
178 p->vpProgramBinding = id;
179 DIRTY(pb->dirty, g->neg_bitid);
180 DIRTY(pb->vpBinding, g->neg_bitid);
181 }
182 else if (target == fragmentTarget) {
183 p->currentFragmentProgram = prog;
184 p->fpProgramBinding = id;
185 DIRTY(pb->dirty, g->neg_bitid);
186 DIRTY(pb->fpBinding, g->neg_bitid);
187 }
188 return prog;
189}
190
191
192void STATE_APIENTRY crStateBindProgramNV(GLenum target, GLuint id)
193{
194 CRProgram *prog = BindProgram(target, id, GL_VERTEX_PROGRAM_NV,
195 GL_FRAGMENT_PROGRAM_NV);
196 if (prog) {
197 prog->isARBprogram = GL_FALSE;
198 }
199}
200
201
202void STATE_APIENTRY crStateBindProgramARB(GLenum target, GLuint id)
203{
204 CRProgram *prog = BindProgram(target, id, GL_VERTEX_PROGRAM_ARB,
205 GL_FRAGMENT_PROGRAM_ARB);
206 if (prog) {
207 prog->isARBprogram = GL_TRUE;
208 }
209}
210
211
212void STATE_APIENTRY crStateDeleteProgramsARB(GLsizei n, const GLuint *ids)
213{
214 CRContext *g = GetCurrentContext();
215 CRProgramState *p = &(g->program);
216 CRStateBits *sb = GetCurrentBits();
217 CRProgramBits *pb = &(sb->program);
218 GLint i;
219
220 if (g->current.inBeginEnd) {
221 crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION,
222 "glDeleteProgramsNV called in Begin/End");
223 return;
224 }
225
226 if (n < 0)
227 {
228 crStateError(__LINE__, __FILE__, GL_INVALID_VALUE, "glDeleteProgramsNV(n)");
229 return;
230 }
231
232 for (i = 0; i < n; i++) {
233 CRProgram *prog;
234 if (ids[i] > 0) {
235 prog = (CRProgram *) crHashtableSearch(p->programHash, ids[i]);
236 if (prog == p->currentVertexProgram) {
237 p->currentVertexProgram = p->defaultVertexProgram;
238 DIRTY(pb->dirty, g->neg_bitid);
239 DIRTY(pb->vpBinding, g->neg_bitid);
240 }
241 else if (prog == p->currentFragmentProgram) {
242 p->currentFragmentProgram = p->defaultFragmentProgram;
243 DIRTY(pb->dirty, g->neg_bitid);
244 DIRTY(pb->fpBinding, g->neg_bitid);
245 }
246 if (prog) {
247 DeleteProgram(prog);
248 }
249 crHashtableDelete(p->programHash, ids[i], GL_FALSE);
250 }
251 }
252}
253
254
255void STATE_APIENTRY crStateExecuteProgramNV(GLenum target, GLuint id, const GLfloat *params)
256{
257 /* Hmmm, this is really hard to do if we don't actually execute
258 * the program in a software simulation.
259 */
260 (void)params;
261 (void)target;
262 (void)id;
263}
264
265
266void STATE_APIENTRY crStateGenProgramsNV(GLsizei n, GLuint *ids)
267{
268 CRContext *g = GetCurrentContext();
269 CRProgramState *p = &(g->program);
270
271 crStateGenNames(g, p->programHash, n, ids);
272}
273
274void STATE_APIENTRY crStateGenProgramsARB(GLsizei n, GLuint *ids)
275{
276 crStateGenProgramsNV(n, ids);
277}
278
279
280GLboolean STATE_APIENTRY crStateIsProgramARB(GLuint id)
281{
282 CRContext *g = GetCurrentContext();
283 CRProgramState *p = &(g->program);
284 CRProgram *prog;
285
286 if (g->current.inBeginEnd) {
287 crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION,
288 "glIsProgram called in Begin/End");
289 return GL_FALSE;
290 }
291
292 if (id == 0) {
293 crStateError(__LINE__, __FILE__, GL_INVALID_VALUE,
294 "glIsProgram(id==0)");
295 return GL_FALSE;
296 }
297
298 prog = (CRProgram *) crHashtableSearch(p->programHash, id);
299 if (prog)
300 return GL_TRUE;
301 else
302 return GL_FALSE;
303}
304
305
306GLboolean STATE_APIENTRY crStateAreProgramsResidentNV(GLsizei n, const GLuint *ids, GLboolean *residences)
307{
308 CRContext *g = GetCurrentContext();
309 CRProgramState *p = &(g->program);
310 int i;
311 GLboolean retVal = GL_TRUE;
312
313 if (n < 0) {
314 crStateError(__LINE__, __FILE__, GL_INVALID_VALUE,
315 "glAreProgramsResidentNV(n)");
316 return GL_FALSE;
317 }
318
319 for (i = 0; i < n; i++) {
320 CRProgram *prog;
321
322 if (ids[i] == 0) {
323 crStateError(__LINE__, __FILE__, GL_INVALID_VALUE,
324 "glAreProgramsResidentNV(id)");
325 return GL_FALSE;
326 }
327
328 prog = (CRProgram *) crHashtableSearch(p->programHash, ids[i]);
329 if (!prog) {
330 crStateError(__LINE__, __FILE__, GL_INVALID_VALUE,
331 "glAreProgramsResidentNV(id)");
332 return GL_FALSE;
333 }
334
335 if (!prog->resident) {
336 retVal = GL_FALSE;
337 break;
338 }
339 }
340
341 if (retVal == GL_FALSE) {
342 for (i = 0; i < n; i++) {
343 CRProgram *prog = (CRProgram *)
344 crHashtableSearch(p->programHash, ids[i]);
345 residences[i] = prog->resident;
346 }
347 }
348
349 return retVal;
350}
351
352
353void STATE_APIENTRY crStateRequestResidentProgramsNV(GLsizei n, const GLuint *ids)
354{
355 CRContext *g = GetCurrentContext();
356 CRProgramState *p = &(g->program);
357 GLint i;
358
359 if (g->current.inBeginEnd) {
360 crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION,
361 "glRequestResidentProgramsNV called in Begin/End");
362 return;
363 }
364
365 if (n < 0) {
366 crStateError(__LINE__, __FILE__, GL_INVALID_VALUE,
367 "glRequestResidentProgramsNV(n<0)");
368 return;
369 }
370
371 for (i = 0; i < n ; i++) {
372 CRProgram *prog = (CRProgram *) crHashtableSearch(p->programHash, ids[i]);
373 if (prog)
374 prog->resident = GL_TRUE;
375 }
376}
377
378
379void STATE_APIENTRY crStateLoadProgramNV(GLenum target, GLuint id, GLsizei len,
380 const GLubyte *program)
381{
382 CRContext *g = GetCurrentContext();
383 CRProgramState *p = &(g->program);
384 CRStateBits *sb = GetCurrentBits();
385 CRProgramBits *pb = &(sb->program);
386 CRProgram *prog;
387 GLubyte *progCopy;
388
389 if (g->current.inBeginEnd) {
390 crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION,
391 "glLoadProgramNV called in Begin/End");
392 return;
393 }
394
395 if (id == 0) {
396 crStateError(__LINE__, __FILE__, GL_INVALID_VALUE,
397 "glLoadProgramNV(id==0)");
398 return;
399 }
400
401 prog = GetProgram(p, target, id);
402
403 if (!prog) {
404 crStateError(__LINE__, __FILE__, GL_OUT_OF_MEMORY, "glLoadProgramNV");
405 return;
406 }
407 else if (prog && prog->target != target) {
408 crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION,
409 "glLoadProgramNV(target)");
410 return;
411 }
412
413 progCopy = crAlloc(len);
414 if (!progCopy) {
415 crStateError(__LINE__, __FILE__, GL_OUT_OF_MEMORY, "glLoadProgramNV");
416 return;
417 }
418 if (crStrncmp((const char *) program,"!!FP1.0", 7) != 0
419 && crStrncmp((const char *) program,"!!FCP1.0", 8) != 0
420 && crStrncmp((const char *) program,"!!VP1.0", 7) != 0
421 && crStrncmp((const char *) program,"!!VP1.1", 7) != 0
422 && crStrncmp((const char *) program,"!!VP2.0", 7) != 0
423 && crStrncmp((const char *) program,"!!VSP1.0", 8) != 0) {
424 crStateError(__LINE__, __FILE__, GL_INVALID_VALUE, "glLoadProgramNV");
425 crDebug("program = (%s)\n",program);
426 return;
427 }
428 crMemcpy(progCopy, program, len);
429 if (prog->string)
430 crFree((void *) prog->string);
431
432 prog->string = progCopy;
433 prog->length = len;
434 prog->isARBprogram = GL_FALSE;
435
436 DIRTY(prog->dirtyProgram, g->neg_bitid);
437 DIRTY(pb->dirty, g->neg_bitid);
438}
439
440
441void STATE_APIENTRY crStateProgramStringARB(GLenum target, GLenum format,
442 GLsizei len, const GLvoid *string)
443{
444 CRContext *g = GetCurrentContext();
445 CRProgramState *p = &(g->program);
446 CRStateBits *sb = GetCurrentBits();
447 CRProgramBits *pb = &(sb->program);
448 CRProgram *prog;
449 GLubyte *progCopy;
450
451 if (g->current.inBeginEnd) {
452 crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION,
453 "glProgramStringARB called in Begin/End");
454 return;
455 }
456
457 if (format != GL_PROGRAM_FORMAT_ASCII_ARB) {
458 crStateError(__LINE__, __FILE__, GL_INVALID_ENUM,
459 "glProgramStringARB(format)");
460 return;
461 }
462
463 if (target == GL_FRAGMENT_PROGRAM_ARB
464 && g->extensions.ARB_fragment_program) {
465 prog = p->currentFragmentProgram;
466 }
467 else if (target == GL_VERTEX_PROGRAM_ARB
468 && g->extensions.ARB_vertex_program) {
469 prog = p->currentVertexProgram;
470 }
471 else {
472 crStateError(__LINE__, __FILE__, GL_INVALID_ENUM,
473 "glProgramStringARB(target)");
474 return;
475 }
476
477 CRASSERT(prog);
478
479
480 progCopy = crAlloc(len);
481 if (!progCopy) {
482 crStateError(__LINE__, __FILE__, GL_OUT_OF_MEMORY, "glProgramStringARB");
483 return;
484 }
485 if (crStrncmp(string,"!!ARBvp1.0", 10) != 0
486 && crStrncmp(string,"!!ARBfp1.0", 10) != 0) {
487 crStateError(__LINE__, __FILE__, GL_INVALID_VALUE, "glProgramStringARB");
488 return;
489 }
490 crMemcpy(progCopy, string, len);
491 if (prog->string)
492 crFree((void *) prog->string);
493
494 prog->string = progCopy;
495 prog->length = len;
496 prog->format = format;
497 prog->isARBprogram = GL_TRUE;
498
499 DIRTY(prog->dirtyProgram, g->neg_bitid);
500 DIRTY(pb->dirty, g->neg_bitid);
501}
502
503
504void STATE_APIENTRY crStateGetProgramivNV(GLuint id, GLenum pname, GLint *params)
505{
506 CRContext *g = GetCurrentContext();
507 CRProgramState *p = &(g->program);
508 CRProgram *prog;
509
510 if (g->current.inBeginEnd) {
511 crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION,
512 "glGetProgramivNV called in Begin/End");
513 return;
514 }
515
516 if (id == 0) {
517 crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION,
518 "glGetProgramivNV(bad id)");
519 return;
520 }
521
522 prog = (CRProgram *) crHashtableSearch(p->programHash, id);
523 if (!prog) {
524 crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION,
525 "glGetProgramivNV(bad id)");
526 return;
527 }
528
529 switch (pname) {
530 case GL_PROGRAM_TARGET_NV:
531 *params = prog->target;
532 return;
533 case GL_PROGRAM_LENGTH_NV:
534 *params = prog->length;
535 return;
536 case GL_PROGRAM_RESIDENT_NV:
537 *params = prog->resident;
538 return;
539 default:
540 crStateError(__LINE__, __FILE__, GL_INVALID_ENUM,
541 "glGetProgramivNV(pname)");
542 return;
543 }
544}
545
546
547void STATE_APIENTRY crStateGetProgramStringNV(GLuint id, GLenum pname, GLubyte *program)
548{
549 CRContext *g = GetCurrentContext();
550 CRProgramState *p = &(g->program);
551 CRProgram *prog;
552
553 if (pname != GL_PROGRAM_STRING_NV) {
554 crStateError(__LINE__, __FILE__, GL_INVALID_ENUM,
555 "glGetProgramStringNV(pname)");
556 return;
557 }
558
559 if (g->current.inBeginEnd) {
560 crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION,
561 "glGetProgramStringNV called in Begin/End");
562 return;
563 }
564
565 if (id == 0) {
566 crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION,
567 "glGetProgramStringNV(bad id)");
568 return;
569 }
570
571 prog = (CRProgram *) crHashtableSearch(p->programHash, id);
572 if (!prog) {
573 crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION,
574 "glGetProgramStringNV(bad id)");
575 return;
576 }
577
578 crMemcpy(program, prog->string, prog->length);
579}
580
581
582void STATE_APIENTRY crStateGetProgramStringARB(GLenum target, GLenum pname, GLvoid *string)
583{
584 CRContext *g = GetCurrentContext();
585 CRProgramState *p = &(g->program);
586 CRProgram *prog;
587
588 if (target == GL_VERTEX_PROGRAM_ARB) {
589 prog = p->currentVertexProgram;
590 }
591 else if (target == GL_FRAGMENT_PROGRAM_ARB) {
592 prog = p->currentFragmentProgram;
593 }
594 else {
595 crStateError(__LINE__, __FILE__, GL_INVALID_ENUM,
596 "glGetProgramStringNV(target)");
597 return;
598 }
599
600 if (pname != GL_PROGRAM_STRING_NV) {
601 crStateError(__LINE__, __FILE__, GL_INVALID_ENUM,
602 "glGetProgramStringNV(pname)");
603 return;
604 }
605
606 if (g->current.inBeginEnd) {
607 crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION,
608 "glGetProgramStringNV called in Begin/End");
609 return;
610 }
611
612 crMemcpy(string, prog->string, prog->length);
613}
614
615
616void STATE_APIENTRY crStateProgramParameter4dNV(GLenum target, GLuint index,
617 GLdouble x, GLdouble y, GLdouble z, GLdouble w)
618{
619 crStateProgramParameter4fNV(target, index, (GLfloat) x, (GLfloat) y,
620 (GLfloat) z, (GLfloat) w);
621}
622
623
624void STATE_APIENTRY crStateProgramParameter4dvNV(GLenum target, GLuint index,
625 const GLdouble *params)
626{
627 crStateProgramParameter4fNV(target, index,
628 (GLfloat) params[0], (GLfloat) params[1],
629 (GLfloat) params[2], (GLfloat) params[3]);
630}
631
632
633void STATE_APIENTRY crStateProgramParameter4fNV(GLenum target, GLuint index,
634 GLfloat x, GLfloat y, GLfloat z, GLfloat w)
635{
636 CRContext *g = GetCurrentContext();
637 CRProgramState *p = &(g->program);
638 CRStateBits *sb = GetCurrentBits();
639 CRProgramBits *pb = &(sb->program);
640
641 if (g->current.inBeginEnd) {
642 crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION,
643 "glProgramParameterNV called in Begin/End");
644 return;
645 }
646
647 if (target == GL_VERTEX_PROGRAM_NV) {
648 if (index < g->limits.maxVertexProgramEnvParams) {
649 p->vertexParameters[index][0] = x;
650 p->vertexParameters[index][1] = y;
651 p->vertexParameters[index][2] = z;
652 p->vertexParameters[index][3] = w;
653 DIRTY(pb->dirty, g->neg_bitid);
654 DIRTY(pb->vertexEnvParameter[index], g->neg_bitid);
655 DIRTY(pb->vertexEnvParameters, g->neg_bitid);
656 }
657 else {
658 crStateError(__LINE__, __FILE__, GL_INVALID_VALUE,
659 "glProgramParameterNV(index=%d)", index);
660 return;
661 }
662 }
663 else {
664 crStateError(__LINE__, __FILE__, GL_INVALID_ENUM,
665 "glProgramParameterNV(target)");
666 return;
667 }
668}
669
670
671void STATE_APIENTRY crStateProgramParameter4fvNV(GLenum target, GLuint index,
672 const GLfloat *params)
673{
674 crStateProgramParameter4fNV(target, index,
675 params[0], params[1], params[2], params[3]);
676}
677
678
679void STATE_APIENTRY crStateProgramParameters4dvNV(GLenum target, GLuint index,
680 GLuint num, const GLdouble *params)
681{
682 CRContext *g = GetCurrentContext();
683 CRProgramState *p = &(g->program);
684 CRStateBits *sb = GetCurrentBits();
685 CRProgramBits *pb = &(sb->program);
686
687 if (g->current.inBeginEnd) {
688 crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION,
689 "glProgramParameters4dvNV called in Begin/End");
690 return;
691 }
692
693 if (target == GL_VERTEX_PROGRAM_NV) {
694 if (index + num < g->limits.maxVertexProgramEnvParams) {
695 GLuint i;
696 for (i = 0; i < num; i++) {
697 p->vertexParameters[index+i][0] = (GLfloat) params[i*4+0];
698 p->vertexParameters[index+i][1] = (GLfloat) params[i*4+1];
699 p->vertexParameters[index+i][2] = (GLfloat) params[i*4+2];
700 p->vertexParameters[index+i][3] = (GLfloat) params[i*4+3];
701 }
702 DIRTY(pb->dirty, g->neg_bitid);
703 DIRTY(pb->vertexEnvParameters, g->neg_bitid);
704 }
705 else {
706 crStateError(__LINE__, __FILE__, GL_INVALID_VALUE,
707 "glProgramParameters4dvNV(index+num)");
708 return;
709 }
710 }
711 else {
712 crStateError(__LINE__, __FILE__, GL_INVALID_ENUM,
713 "glProgramParameterNV(target)");
714 return;
715 }
716}
717
718
719void STATE_APIENTRY crStateProgramParameters4fvNV(GLenum target, GLuint index,
720 GLuint num, const GLfloat *params)
721{
722 CRContext *g = GetCurrentContext();
723 CRProgramState *p = &(g->program);
724 CRStateBits *sb = GetCurrentBits();
725 CRProgramBits *pb = &(sb->program);
726
727 if (g->current.inBeginEnd) {
728 crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION,
729 "glProgramParameters4dvNV called in Begin/End");
730 return;
731 }
732
733 if (target == GL_VERTEX_PROGRAM_NV) {
734 if (index + num < g->limits.maxVertexProgramEnvParams) {
735 GLuint i;
736 for (i = 0; i < num; i++) {
737 p->vertexParameters[index+i][0] = params[i*4+0];
738 p->vertexParameters[index+i][1] = params[i*4+1];
739 p->vertexParameters[index+i][2] = params[i*4+2];
740 p->vertexParameters[index+i][3] = params[i*4+3];
741 }
742 DIRTY(pb->dirty, g->neg_bitid);
743 DIRTY(pb->vertexEnvParameters, g->neg_bitid);
744 }
745 else {
746 crStateError(__LINE__, __FILE__, GL_INVALID_VALUE,
747 "glProgramParameters4dvNV(index+num)");
748 return;
749 }
750 }
751 else {
752 crStateError(__LINE__, __FILE__, GL_INVALID_ENUM,
753 "glProgramParameterNV(target)");
754 return;
755 }
756}
757
758
759void STATE_APIENTRY crStateGetProgramParameterfvNV(GLenum target, GLuint index,
760 GLenum pname, GLfloat *params)
761{
762 CRContext *g = GetCurrentContext();
763 CRProgramState *p = &(g->program);
764
765 if (g->current.inBeginEnd) {
766 crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION,
767 "glGetProgramParameterfvNV called in Begin/End");
768 return;
769 }
770
771 if (target == GL_VERTEX_PROGRAM_NV) {
772 if (pname == GL_PROGRAM_PARAMETER_NV) {
773 if (index < g->limits.maxVertexProgramEnvParams) {
774 params[0] = p->vertexParameters[index][0];
775 params[1] = p->vertexParameters[index][1];
776 params[2] = p->vertexParameters[index][2];
777 params[3] = p->vertexParameters[index][3];
778 }
779 else {
780 crStateError(__LINE__, __FILE__, GL_INVALID_VALUE,
781 "glGetProgramParameterfvNV(index)");
782 return;
783 }
784 }
785 else {
786 crStateError(__LINE__, __FILE__, GL_INVALID_ENUM,
787 "glGetProgramParameterfvNV(pname)");
788 return;
789 }
790 }
791 else {
792 crStateError(__LINE__, __FILE__, GL_INVALID_ENUM,
793 "glGetProgramParameterfvNV(target)");
794 return;
795 }
796}
797
798
799void STATE_APIENTRY crStateGetProgramParameterdvNV(GLenum target, GLuint index,
800 GLenum pname, GLdouble *params)
801{
802 CRContext *g = GetCurrentContext();
803 CRProgramState *p = &(g->program);
804
805 if (g->current.inBeginEnd) {
806 crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION,
807 "glGetProgramParameterdvNV called in Begin/End");
808 return;
809 }
810
811 if (target == GL_VERTEX_PROGRAM_NV) {
812 if (pname == GL_PROGRAM_PARAMETER_NV) {
813 if (index < g->limits.maxVertexProgramEnvParams) {
814 params[0] = p->vertexParameters[index][0];
815 params[1] = p->vertexParameters[index][1];
816 params[2] = p->vertexParameters[index][2];
817 params[3] = p->vertexParameters[index][3];
818 }
819 else {
820 crStateError(__LINE__, __FILE__, GL_INVALID_VALUE,
821 "glGetProgramParameterdvNV(index)");
822 return;
823 }
824 }
825 else {
826 crStateError(__LINE__, __FILE__, GL_INVALID_ENUM,
827 "glGetProgramParameterdvNV(pname)");
828 return;
829 }
830 }
831 else {
832 crStateError(__LINE__, __FILE__, GL_INVALID_ENUM,
833 "glGetProgramParameterdvNV(target)");
834 return;
835 }
836}
837
838
839void STATE_APIENTRY crStateTrackMatrixNV(GLenum target, GLuint address,
840 GLenum matrix, GLenum transform)
841{
842 CRContext *g = GetCurrentContext();
843 CRProgramState *p = &(g->program);
844 CRStateBits *sb = GetCurrentBits();
845 CRProgramBits *pb = &(sb->program);
846
847 if (g->current.inBeginEnd) {
848 crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION,
849 "glGetTrackMatrixivNV called in Begin/End");
850 return;
851 }
852
853 if (target == GL_VERTEX_PROGRAM_NV) {
854 if (address & 0x3) {
855 /* addr must be multiple of four */
856 crStateError(__LINE__, __FILE__, GL_INVALID_VALUE,
857 "glTrackMatrixNV(address)");
858 return;
859 }
860
861 switch (matrix) {
862 case GL_NONE:
863 case GL_MODELVIEW:
864 case GL_PROJECTION:
865 case GL_TEXTURE:
866 case GL_COLOR:
867 case GL_MODELVIEW_PROJECTION_NV:
868 case GL_MATRIX0_NV:
869 case GL_MATRIX1_NV:
870 case GL_MATRIX2_NV:
871 case GL_MATRIX3_NV:
872 case GL_MATRIX4_NV:
873 case GL_MATRIX5_NV:
874 case GL_MATRIX6_NV:
875 case GL_MATRIX7_NV:
876 case GL_TEXTURE0_ARB:
877 case GL_TEXTURE1_ARB:
878 case GL_TEXTURE2_ARB:
879 case GL_TEXTURE3_ARB:
880 case GL_TEXTURE4_ARB:
881 case GL_TEXTURE5_ARB:
882 case GL_TEXTURE6_ARB:
883 case GL_TEXTURE7_ARB:
884 /* OK, fallthrough */
885 break;
886 default:
887 crStateError(__LINE__, __FILE__, GL_INVALID_ENUM,
888 "glTrackMatrixNV(matrix = %x)",matrix);
889 return;
890 }
891
892 switch (transform) {
893 case GL_IDENTITY_NV:
894 case GL_INVERSE_NV:
895 case GL_TRANSPOSE_NV:
896 case GL_INVERSE_TRANSPOSE_NV:
897 /* OK, fallthrough */
898 break;
899 default:
900 crStateError(__LINE__, __FILE__, GL_INVALID_ENUM,
901 "glTrackMatrixNV(transform = %x)",transform);
902 return;
903 }
904
905 p->TrackMatrix[address / 4] = matrix;
906 p->TrackMatrixTransform[address / 4] = transform;
907 DIRTY(pb->trackMatrix[address/4], g->neg_bitid);
908 DIRTY(pb->dirty, g->neg_bitid);
909 }
910 else {
911 crStateError(__LINE__, __FILE__, GL_INVALID_ENUM,
912 "glTrackMatrixNV(target = %x)",target);
913 }
914}
915
916
917void STATE_APIENTRY crStateGetTrackMatrixivNV(GLenum target, GLuint address,
918 GLenum pname, GLint *params)
919{
920 CRContext *g = GetCurrentContext();
921 CRProgramState *p = &(g->program);
922
923 if (g->current.inBeginEnd) {
924 crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION,
925 "glGetTrackMatrixivNV called in Begin/End");
926 return;
927 }
928
929 if (target == GL_VERTEX_PROGRAM_NV) {
930 if ((address & 0x3) || address >= g->limits.maxVertexProgramEnvParams) {
931 crStateError(__LINE__, __FILE__, GL_INVALID_VALUE,
932 "glGetTrackMatrixivNV(address)");
933 return;
934 }
935 if (pname == GL_TRACK_MATRIX_NV) {
936 params[0] = (GLint) p->TrackMatrix[address / 4];
937 }
938 else if (pname == GL_TRACK_MATRIX_TRANSFORM_NV) {
939 params[0] = (GLint) p->TrackMatrixTransform[address / 4];
940 }
941 else {
942 crStateError(__LINE__, __FILE__, GL_INVALID_ENUM,
943 "glGetTrackMatrixivNV(pname)");
944 return;
945 }
946 }
947 else {
948 crStateError(__LINE__, __FILE__, GL_INVALID_ENUM,
949 "glGetTrackMatrixivNV(target)");
950 return;
951 }
952}
953
954
955void STATE_APIENTRY crStateGetVertexAttribdvNV(GLuint index, GLenum pname, GLdouble *params)
956{
957 /* init vars to prevent compiler warnings/errors */
958 GLfloat floatParams[4] = { 0.0, 0.0, 0.0, 0.0 };
959 crStateGetVertexAttribfvNV(index, pname, floatParams);
960 params[0] = floatParams[0];
961 if (pname == GL_CURRENT_ATTRIB_NV) {
962 params[1] = floatParams[1];
963 params[2] = floatParams[2];
964 params[3] = floatParams[3];
965 }
966}
967
968
969void STATE_APIENTRY crStateGetVertexAttribfvNV(GLuint index, GLenum pname, GLfloat *params)
970{
971 CRContext *g = GetCurrentContext();
972
973 if (g->current.inBeginEnd) {
974 crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION,
975 "glGetVertexAttribfvNV called in Begin/End");
976 return;
977 }
978
979 if (index >= CR_MAX_VERTEX_ATTRIBS) {
980 crStateError(__LINE__, __FILE__, GL_INVALID_VALUE,
981 "glGetVertexAttribfvNV(index)");
982 return;
983 }
984
985 switch (pname) {
986 case GL_ATTRIB_ARRAY_SIZE_NV:
987 params[0] = (GLfloat) g->client.array.a[index].size;
988 break;
989 case GL_ATTRIB_ARRAY_STRIDE_NV:
990 params[0] = (GLfloat) g->client.array.a[index].stride;
991 break;
992 case GL_ATTRIB_ARRAY_TYPE_NV:
993 params[0] = (GLfloat) g->client.array.a[index].type;
994 break;
995 case GL_CURRENT_ATTRIB_NV:
996 crStateCurrentRecover();
997 COPY_4V(params , g->current.vertexAttrib[index]);
998 break;
999 default:
1000 crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glGetVertexAttribfvNV");
1001 return;
1002 }
1003}
1004
1005
1006void STATE_APIENTRY crStateGetVertexAttribivNV(GLuint index, GLenum pname, GLint *params)
1007{
1008 /* init vars to prevent compiler warnings/errors */
1009 GLfloat floatParams[4] = { 0.0, 0.0, 0.0, 0.0 };
1010 crStateGetVertexAttribfvNV(index, pname, floatParams);
1011 params[0] = (GLint) floatParams[0];
1012 if (pname == GL_CURRENT_ATTRIB_NV) {
1013 params[1] = (GLint) floatParams[1];
1014 params[2] = (GLint) floatParams[2];
1015 params[3] = (GLint) floatParams[3];
1016 }
1017}
1018
1019
1020
1021void STATE_APIENTRY crStateGetVertexAttribfvARB(GLuint index, GLenum pname, GLfloat *params)
1022{
1023 CRContext *g = GetCurrentContext();
1024
1025 if (g->current.inBeginEnd) {
1026 crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION,
1027 "glGetVertexAttribfvARB called in Begin/End");
1028 return;
1029 }
1030
1031 if (index >= CR_MAX_VERTEX_ATTRIBS) {
1032 crStateError(__LINE__, __FILE__, GL_INVALID_VALUE,
1033 "glGetVertexAttribfvARB(index)");
1034 return;
1035 }
1036
1037 switch (pname) {
1038 case GL_VERTEX_ATTRIB_ARRAY_ENABLED_ARB:
1039 params[0] = (GLfloat) g->client.array.a[index].enabled;
1040 break;
1041 case GL_VERTEX_ATTRIB_ARRAY_SIZE_ARB:
1042 params[0] = (GLfloat) g->client.array.a[index].size;
1043 break;
1044 case GL_VERTEX_ATTRIB_ARRAY_STRIDE_ARB:
1045 params[0] = (GLfloat) g->client.array.a[index].stride;
1046 break;
1047 case GL_VERTEX_ATTRIB_ARRAY_TYPE_ARB:
1048 params[0] = (GLfloat) g->client.array.a[index].type;
1049 break;
1050 case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED_ARB:
1051 params[0] = (GLfloat) g->client.array.a[index].normalized;
1052 break;
1053 case GL_CURRENT_VERTEX_ATTRIB_ARB:
1054 crStateCurrentRecover();
1055 COPY_4V(params , g->current.vertexAttrib[index]);
1056 break;
1057 default:
1058 crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glGetVertexAttribfvARB");
1059 return;
1060 }
1061}
1062
1063
1064void STATE_APIENTRY crStateGetVertexAttribivARB(GLuint index, GLenum pname, GLint *params)
1065{
1066 /* init vars to prevent compiler warnings/errors */
1067 GLfloat floatParams[4] = { 0.0, 0.0, 0.0, 0.0 };
1068 crStateGetVertexAttribfvARB(index, pname, floatParams);
1069 params[0] = (GLint) floatParams[0];
1070 if (pname == GL_CURRENT_VERTEX_ATTRIB_ARB) {
1071 params[1] = (GLint) floatParams[1];
1072 params[2] = (GLint) floatParams[2];
1073 params[3] = (GLint) floatParams[3];
1074 }
1075}
1076
1077
1078void STATE_APIENTRY crStateGetVertexAttribdvARB(GLuint index, GLenum pname, GLdouble *params)
1079{
1080 /* init vars to prevent compiler warnings/errors */
1081 GLfloat floatParams[4] = { 0.0, 0.0, 0.0, 0.0 };
1082 crStateGetVertexAttribfvARB(index, pname, floatParams);
1083 params[0] = floatParams[0];
1084 if (pname == GL_CURRENT_VERTEX_ATTRIB_ARB) {
1085 params[1] = floatParams[1];
1086 params[2] = floatParams[2];
1087 params[3] = floatParams[3];
1088 }
1089}
1090
1091
1092/**********************************************************************/
1093
1094/*
1095 * Added by GL_NV_fragment_program
1096 */
1097
1098void STATE_APIENTRY crStateProgramNamedParameter4fNV(GLuint id, GLsizei len, const GLubyte *name, GLfloat x, GLfloat y, GLfloat z, GLfloat w)
1099{
1100 CRContext *g = GetCurrentContext();
1101 CRProgramState *p = &(g->program);
1102 CRProgram *prog;
1103 CRStateBits *sb = GetCurrentBits();
1104 CRProgramBits *pb = &(sb->program);
1105
1106 if (g->current.inBeginEnd) {
1107 crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION,
1108 "glProgramNamedParameterfNV called in Begin/End");
1109 return;
1110 }
1111
1112 prog = (CRProgram *) crHashtableSearch(p->programHash, id);
1113 if (!prog) {
1114 crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION,
1115 "glProgramNamedParameterNV(bad id %d)", id);
1116 return;
1117 }
1118
1119 if (prog->target != GL_FRAGMENT_PROGRAM_NV) {
1120 crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION,
1121 "glProgramNamedParameterNV(target)");
1122 return;
1123 }
1124
1125 SetProgramSymbol(prog, (const char *)name, len, x, y, z, w);
1126 DIRTY(prog->dirtyNamedParams, g->neg_bitid);
1127 DIRTY(pb->dirty, g->neg_bitid);
1128}
1129
1130
1131void STATE_APIENTRY crStateProgramNamedParameter4dNV(GLuint id, GLsizei len, const GLubyte *name, GLdouble x, GLdouble y, GLdouble z, GLdouble w)
1132{
1133 crStateProgramNamedParameter4fNV(id, len, name, (GLfloat) x, (GLfloat) y, (GLfloat) z, (GLfloat) w);
1134}
1135
1136
1137void STATE_APIENTRY crStateProgramNamedParameter4fvNV(GLuint id, GLsizei len, const GLubyte *name, const GLfloat v[])
1138{
1139 crStateProgramNamedParameter4fNV(id, len, name, v[0], v[1], v[2], v[3]);
1140}
1141
1142
1143void STATE_APIENTRY crStateProgramNamedParameter4dvNV(GLuint id, GLsizei len, const GLubyte *name, const GLdouble v[])
1144{
1145 crStateProgramNamedParameter4fNV(id, len, name, (GLfloat) v[0], (GLfloat) v[1], (GLfloat) v[2], (GLfloat) v[3]);
1146}
1147
1148
1149void STATE_APIENTRY crStateGetProgramNamedParameterfvNV(GLuint id, GLsizei len, const GLubyte *name, GLfloat *params)
1150{
1151 CRContext *g = GetCurrentContext();
1152 CRProgramState *p = &(g->program);
1153 const CRProgram *prog;
1154 const GLfloat *value;
1155
1156 if (g->current.inBeginEnd) {
1157 crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION,
1158 "glGetProgramNamedParameterfNV called in Begin/End");
1159 return;
1160 }
1161
1162 prog = (const CRProgram *) crHashtableSearch(p->programHash, id);
1163 if (!prog) {
1164 crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION,
1165 "glGetProgramNamedParameterNV(bad id)");
1166 return;
1167 }
1168
1169 if (prog->target != GL_FRAGMENT_PROGRAM_NV) {
1170 crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION,
1171 "glGetProgramNamedParameterNV(target)");
1172 return;
1173 }
1174
1175 value = GetProgramSymbol(prog, (const char *)name, len);
1176 if (!value) {
1177 crStateError(__LINE__, __FILE__, GL_INVALID_VALUE,
1178 "glGetProgramNamedParameterNV(name)");
1179 return;
1180 }
1181
1182 params[0] = value[0];
1183 params[1] = value[1];
1184 params[2] = value[2];
1185 params[3] = value[3];
1186}
1187
1188
1189void STATE_APIENTRY crStateGetProgramNamedParameterdvNV(GLuint id, GLsizei len, const GLubyte *name, GLdouble *params)
1190{
1191 GLfloat floatParams[4];
1192 crStateGetProgramNamedParameterfvNV(id, len, name, floatParams);
1193 params[0] = floatParams[0];
1194 params[1] = floatParams[1];
1195 params[2] = floatParams[2];
1196 params[3] = floatParams[3];
1197}
1198
1199
1200void STATE_APIENTRY crStateProgramLocalParameter4dARB(GLenum target, GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w)
1201{
1202 crStateProgramLocalParameter4fARB(target, index, (GLfloat) x, (GLfloat) y, (GLfloat) z, (GLfloat) w);
1203}
1204
1205
1206void STATE_APIENTRY crStateProgramLocalParameter4dvARB(GLenum target, GLuint index, const GLdouble *params)
1207{
1208 crStateProgramLocalParameter4fARB(target, index, (GLfloat) params[0], (GLfloat) params[1],
1209 (GLfloat) params[2], (GLfloat) params[3]);
1210}
1211
1212
1213void STATE_APIENTRY crStateProgramLocalParameter4fARB(GLenum target, GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w)
1214{
1215 CRContext *g = GetCurrentContext();
1216 CRProgramState *p = &(g->program);
1217 CRProgram *prog;
1218 CRStateBits *sb = GetCurrentBits();
1219 CRProgramBits *pb = &(sb->program);
1220
1221 if (g->current.inBeginEnd) {
1222 crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION,
1223 "glProgramLocalParameterARB called in Begin/End");
1224 return;
1225 }
1226
1227 if (target == GL_FRAGMENT_PROGRAM_ARB || target == GL_FRAGMENT_PROGRAM_NV) {
1228 if (index >= CR_MAX_FRAGMENT_PROGRAM_LOCAL_PARAMS) {
1229 crStateError(__LINE__, __FILE__, GL_INVALID_VALUE,
1230 "glProgramLocalParameterARB(index)");
1231 return;
1232 }
1233 prog = p->currentFragmentProgram;
1234 }
1235 else if (target == GL_VERTEX_PROGRAM_ARB) {
1236 if (index >= CR_MAX_VERTEX_PROGRAM_LOCAL_PARAMS) {
1237 crStateError(__LINE__, __FILE__, GL_INVALID_VALUE,
1238 "glProgramLocalParameterARB(index)");
1239 return;
1240 }
1241 prog = p->currentVertexProgram;
1242 }
1243 else {
1244 crStateError(__LINE__, __FILE__, GL_INVALID_ENUM,
1245 "glProgramLocalParameterARB(target)");
1246 return;
1247 }
1248
1249 CRASSERT(prog);
1250
1251 prog->parameters[index][0] = x;
1252 prog->parameters[index][1] = y;
1253 prog->parameters[index][2] = z;
1254 prog->parameters[index][3] = w;
1255 DIRTY(prog->dirtyParam[index], g->neg_bitid);
1256 DIRTY(prog->dirtyParams, g->neg_bitid);
1257 DIRTY(pb->dirty, g->neg_bitid);
1258}
1259
1260
1261void STATE_APIENTRY crStateProgramLocalParameter4fvARB(GLenum target, GLuint index, const GLfloat *params)
1262{
1263 crStateProgramLocalParameter4fARB(target, index, params[0], params[1], params[2], params[3]);
1264}
1265
1266
1267void STATE_APIENTRY crStateGetProgramLocalParameterfvARB(GLenum target, GLuint index, GLfloat *params)
1268{
1269 CRContext *g = GetCurrentContext();
1270 CRProgramState *p = &(g->program);
1271 const CRProgram *prog = NULL;
1272
1273 if (g->current.inBeginEnd) {
1274 crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION,
1275 "glGetProgramLocalParameterARB called in Begin/End");
1276 return;
1277 }
1278
1279 if (target == GL_FRAGMENT_PROGRAM_ARB || target == GL_FRAGMENT_PROGRAM_NV) {
1280 prog = p->currentFragmentProgram;
1281 if (index >= g->limits.maxFragmentProgramLocalParams) {
1282 crStateError(__LINE__, __FILE__, GL_INVALID_VALUE,
1283 "glGetProgramLocalParameterARB(index)");
1284 return;
1285 }
1286 }
1287 else if (target == GL_VERTEX_PROGRAM_ARB || target == GL_VERTEX_PROGRAM_NV) {
1288 prog = p->currentVertexProgram;
1289 if (index >= g->limits.maxVertexProgramLocalParams) {
1290 crStateError(__LINE__, __FILE__, GL_INVALID_VALUE,
1291 "glGetProgramLocalParameterARB(index)");
1292 return;
1293 }
1294 }
1295 else {
1296 crStateError(__LINE__, __FILE__, GL_INVALID_ENUM,
1297 "glGetProgramLocalParameterARB(target)");
1298 return;
1299 }
1300 if (!prog) {
1301 crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION,
1302 "glGetProgramLocalParameterARB(no program)");
1303 return;
1304 }
1305
1306 if (!prog) {
1307 crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION,
1308 "glGetProgramLocalParameterARB(no program)");
1309 return;
1310 }
1311
1312 CRASSERT(prog);
1313 CRASSERT(index < CR_MAX_PROGRAM_LOCAL_PARAMS);
1314 params[0] = prog->parameters[index][0];
1315 params[1] = prog->parameters[index][1];
1316 params[2] = prog->parameters[index][2];
1317 params[3] = prog->parameters[index][3];
1318}
1319
1320
1321void STATE_APIENTRY crStateGetProgramLocalParameterdvARB(GLenum target, GLuint index, GLdouble *params)
1322{
1323 GLfloat floatParams[4];
1324 crStateGetProgramLocalParameterfvARB(target, index, floatParams);
1325 params[0] = floatParams[0];
1326 params[1] = floatParams[1];
1327 params[2] = floatParams[2];
1328 params[3] = floatParams[3];
1329}
1330
1331
1332
1333void STATE_APIENTRY crStateGetProgramivARB(GLenum target, GLenum pname, GLint *params)
1334{
1335 CRProgram *prog;
1336 CRContext *g = GetCurrentContext();
1337 CRProgramState *p = &(g->program);
1338
1339 if (g->current.inBeginEnd) {
1340 crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION,
1341 "glGetProgramivARB called in Begin/End");
1342 return;
1343 }
1344
1345 if (target == GL_VERTEX_PROGRAM_ARB) {
1346 prog = p->currentVertexProgram;
1347 }
1348 else if (target == GL_FRAGMENT_PROGRAM_ARB) {
1349 prog = p->currentFragmentProgram;
1350 }
1351 else {
1352 crStateError(__LINE__, __FILE__, GL_INVALID_ENUM,
1353 "glGetProgramivARB(target)");
1354 return;
1355 }
1356
1357 CRASSERT(prog);
1358
1359 switch (pname) {
1360 case GL_PROGRAM_LENGTH_ARB:
1361 *params = prog->length;
1362 break;
1363 case GL_PROGRAM_FORMAT_ARB:
1364 *params = prog->format;
1365 break;
1366 case GL_PROGRAM_BINDING_ARB:
1367 *params = prog->id;
1368 break;
1369 case GL_PROGRAM_INSTRUCTIONS_ARB:
1370 *params = prog->numInstructions;
1371 break;
1372 case GL_MAX_PROGRAM_INSTRUCTIONS_ARB:
1373 if (target == GL_VERTEX_PROGRAM_ARB)
1374 *params = g->limits.maxVertexProgramInstructions;
1375 else
1376 *params = g->limits.maxFragmentProgramInstructions;
1377 break;
1378 case GL_PROGRAM_NATIVE_INSTRUCTIONS_ARB:
1379 *params = prog->numInstructions;
1380 break;
1381 case GL_MAX_PROGRAM_NATIVE_INSTRUCTIONS_ARB:
1382 if (target == GL_VERTEX_PROGRAM_ARB)
1383 *params = g->limits.maxVertexProgramInstructions;
1384 else
1385 *params = g->limits.maxFragmentProgramInstructions;
1386 break;
1387 case GL_PROGRAM_TEMPORARIES_ARB:
1388 *params = prog->numTemporaries;
1389 break;
1390 case GL_MAX_PROGRAM_TEMPORARIES_ARB:
1391 if (target == GL_VERTEX_PROGRAM_ARB)
1392 *params = g->limits.maxVertexProgramTemps;
1393 else
1394 *params = g->limits.maxFragmentProgramTemps;
1395 break;
1396 case GL_PROGRAM_NATIVE_TEMPORARIES_ARB:
1397 /* XXX same as GL_PROGRAM_TEMPORARIES_ARB? */
1398 *params = prog->numTemporaries;
1399 break;
1400 case GL_MAX_PROGRAM_NATIVE_TEMPORARIES_ARB:
1401 /* XXX same as GL_MAX_PROGRAM_TEMPORARIES_ARB? */
1402 if (target == GL_VERTEX_PROGRAM_ARB)
1403 *params = g->limits.maxVertexProgramTemps;
1404 else
1405 *params = g->limits.maxFragmentProgramTemps;
1406 break;
1407 case GL_PROGRAM_PARAMETERS_ARB:
1408 *params = prog->numParameters;
1409 break;
1410 case GL_MAX_PROGRAM_PARAMETERS_ARB:
1411 if (target == GL_VERTEX_PROGRAM_ARB)
1412 *params = g->limits.maxVertexProgramLocalParams;
1413 else
1414 *params = g->limits.maxFragmentProgramLocalParams;
1415 break;
1416 case GL_PROGRAM_NATIVE_PARAMETERS_ARB:
1417 /* XXX same as GL_MAX_PROGRAM_PARAMETERS_ARB? */
1418 *params = prog->numParameters;
1419 break;
1420 case GL_MAX_PROGRAM_NATIVE_PARAMETERS_ARB:
1421 /* XXX same as GL_MAX_PROGRAM_PARAMETERS_ARB? */
1422 if (target == GL_VERTEX_PROGRAM_ARB)
1423 *params = g->limits.maxVertexProgramLocalParams;
1424 else
1425 *params = g->limits.maxFragmentProgramLocalParams;
1426 break;
1427 case GL_PROGRAM_ATTRIBS_ARB:
1428 *params = prog->numAttributes;
1429 break;
1430 case GL_MAX_PROGRAM_ATTRIBS_ARB:
1431 if (target == GL_VERTEX_PROGRAM_ARB)
1432 *params = g->limits.maxVertexProgramAttribs;
1433 else
1434 *params = g->limits.maxFragmentProgramAttribs;
1435 break;
1436 case GL_PROGRAM_NATIVE_ATTRIBS_ARB:
1437 /* XXX same as GL_PROGRAM_ATTRIBS_ARB? */
1438 *params = prog->numAttributes;
1439 break;
1440 case GL_MAX_PROGRAM_NATIVE_ATTRIBS_ARB:
1441 /* XXX same as GL_MAX_PROGRAM_ATTRIBS_ARB? */
1442 if (target == GL_VERTEX_PROGRAM_ARB)
1443 *params = g->limits.maxVertexProgramAttribs;
1444 else
1445 *params = g->limits.maxFragmentProgramAttribs;
1446 break;
1447 case GL_PROGRAM_ADDRESS_REGISTERS_ARB:
1448 *params = prog->numAddressRegs;
1449 break;
1450 case GL_MAX_PROGRAM_ADDRESS_REGISTERS_ARB:
1451 if (target == GL_VERTEX_PROGRAM_ARB)
1452 *params = g->limits.maxVertexProgramAddressRegs;
1453 else
1454 *params = g->limits.maxFragmentProgramAddressRegs;
1455 break;
1456 case GL_PROGRAM_NATIVE_ADDRESS_REGISTERS_ARB:
1457 /* XXX same as GL_PROGRAM_ADDRESS_REGISTERS_ARB? */
1458 *params = prog->numAddressRegs;
1459 break;
1460 case GL_MAX_PROGRAM_NATIVE_ADDRESS_REGISTERS_ARB:
1461 /* XXX same as GL_MAX_PROGRAM_ADDRESS_REGISTERS_ARB? */
1462 if (target == GL_VERTEX_PROGRAM_ARB)
1463 *params = g->limits.maxVertexProgramAddressRegs;
1464 else
1465 *params = g->limits.maxFragmentProgramAddressRegs;
1466 break;
1467 case GL_MAX_PROGRAM_LOCAL_PARAMETERS_ARB:
1468 if (target == GL_VERTEX_PROGRAM_ARB)
1469 *params = g->limits.maxVertexProgramLocalParams;
1470 else
1471 *params = g->limits.maxFragmentProgramLocalParams;
1472 break;
1473 case GL_MAX_PROGRAM_ENV_PARAMETERS_ARB:
1474 if (target == GL_VERTEX_PROGRAM_ARB)
1475 *params = g->limits.maxVertexProgramEnvParams;
1476 else
1477 *params = g->limits.maxFragmentProgramEnvParams;
1478 break;
1479 case GL_PROGRAM_UNDER_NATIVE_LIMITS_ARB:
1480 /* XXX ok? */
1481 *params = GL_TRUE;
1482 break;
1483
1484 /*
1485 * These are for fragment programs only
1486 */
1487 case GL_PROGRAM_ALU_INSTRUCTIONS_ARB:
1488 if (target != GL_FRAGMENT_PROGRAM_ARB || !g->extensions.ARB_fragment_program) {
1489 crStateError(__LINE__, __FILE__, GL_INVALID_ENUM,
1490 "crStateGetProgramivARB(target or pname)");
1491 return;
1492 }
1493 *params = prog->numAluInstructions;
1494 break;
1495 case GL_PROGRAM_TEX_INSTRUCTIONS_ARB:
1496 if (target != GL_FRAGMENT_PROGRAM_ARB || !g->extensions.ARB_fragment_program) {
1497 crStateError(__LINE__, __FILE__, GL_INVALID_ENUM,
1498 "crStateGetProgramivARB(target or pname)");
1499 return;
1500 }
1501 *params = prog->numTexInstructions;
1502 break;
1503 case GL_PROGRAM_TEX_INDIRECTIONS_ARB:
1504 if (target != GL_FRAGMENT_PROGRAM_ARB || !g->extensions.ARB_fragment_program) {
1505 crStateError(__LINE__, __FILE__, GL_INVALID_ENUM,
1506 "crStateGetProgramivARB(target or pname)");
1507 return;
1508 }
1509 *params = prog->numTexIndirections;
1510 break;
1511 case GL_PROGRAM_NATIVE_ALU_INSTRUCTIONS_ARB:
1512 /* XXX same as GL_PROGRAM_ALU_INSTRUCTIONS_ARB? */
1513 if (target != GL_FRAGMENT_PROGRAM_ARB || !g->extensions.ARB_fragment_program) {
1514 crStateError(__LINE__, __FILE__, GL_INVALID_ENUM,
1515 "crStateGetProgramivARB(target or pname)");
1516 return;
1517 }
1518 *params = prog->numAluInstructions;
1519 break;
1520 case GL_PROGRAM_NATIVE_TEX_INSTRUCTIONS_ARB:
1521 /* XXX same as GL_PROGRAM_ALU_INSTRUCTIONS_ARB? */
1522 if (target != GL_FRAGMENT_PROGRAM_ARB || !g->extensions.ARB_fragment_program) {
1523 crStateError(__LINE__, __FILE__, GL_INVALID_ENUM,
1524 "crStateGetProgramivARB(target or pname)");
1525 return;
1526 }
1527 *params = prog->numTexInstructions;
1528 break;
1529 case GL_PROGRAM_NATIVE_TEX_INDIRECTIONS_ARB:
1530 if (target != GL_FRAGMENT_PROGRAM_ARB || !g->extensions.ARB_fragment_program) {
1531 crStateError(__LINE__, __FILE__, GL_INVALID_ENUM,
1532 "crStateGetProgramivARB(target or pname)");
1533 return;
1534 }
1535 *params = prog->numTexIndirections;
1536 break;
1537 case GL_MAX_PROGRAM_ALU_INSTRUCTIONS_ARB:
1538 case GL_MAX_PROGRAM_NATIVE_ALU_INSTRUCTIONS_ARB:
1539 if (target != GL_FRAGMENT_PROGRAM_ARB || !g->extensions.ARB_fragment_program) {
1540 crStateError(__LINE__, __FILE__, GL_INVALID_ENUM,
1541 "crStateGetProgramivARB(target or pname)");
1542 return;
1543 }
1544 *params = g->limits.maxFragmentProgramAluInstructions;
1545 break;
1546 case GL_MAX_PROGRAM_TEX_INSTRUCTIONS_ARB:
1547 case GL_MAX_PROGRAM_NATIVE_TEX_INSTRUCTIONS_ARB:
1548 if (target != GL_FRAGMENT_PROGRAM_ARB || !g->extensions.ARB_fragment_program) {
1549 crStateError(__LINE__, __FILE__, GL_INVALID_ENUM,
1550 "crStateGetProgramivARB(target or pname)");
1551 return;
1552 }
1553 *params = g->limits.maxFragmentProgramTexInstructions;
1554 break;
1555 case GL_MAX_PROGRAM_TEX_INDIRECTIONS_ARB:
1556 case GL_MAX_PROGRAM_NATIVE_TEX_INDIRECTIONS_ARB:
1557 if (target != GL_FRAGMENT_PROGRAM_ARB || !g->extensions.ARB_fragment_program) {
1558 crStateError(__LINE__, __FILE__, GL_INVALID_ENUM,
1559 "crStateGetProgramivARB(target or pname)");
1560 return;
1561 }
1562 *params = g->limits.maxFragmentProgramTexIndirections;
1563 break;
1564 default:
1565 crStateError(__LINE__, __FILE__, GL_INVALID_ENUM,
1566 "crStateGetProgramivARB(pname)");
1567 return;
1568 }
1569}
1570
1571
1572/* XXX maybe move these two functions into state_client.c? */
1573void STATE_APIENTRY crStateDisableVertexAttribArrayARB(GLuint index)
1574{
1575 CRContext *g = GetCurrentContext();
1576 CRClientState *c = &(g->client);
1577 CRStateBits *sb = GetCurrentBits();
1578 CRClientBits *cb = &(sb->client);
1579
1580 if (index >= g->limits.maxVertexProgramAttribs) {
1581 crStateError(__LINE__, __FILE__, GL_INVALID_VALUE,
1582 "glDisableVertexAttribArrayARB(index)");
1583 return;
1584 }
1585 c->array.a[index].enabled = GL_FALSE;
1586 DIRTY(cb->dirty, g->neg_bitid);
1587 DIRTY(cb->enableClientState, g->neg_bitid);
1588}
1589
1590
1591void STATE_APIENTRY crStateEnableVertexAttribArrayARB(GLuint index)
1592{
1593 CRContext *g = GetCurrentContext();
1594 CRClientState *c = &(g->client);
1595 CRStateBits *sb = GetCurrentBits();
1596 CRClientBits *cb = &(sb->client);
1597
1598 if (index >= g->limits.maxVertexProgramAttribs) {
1599 crStateError(__LINE__, __FILE__, GL_INVALID_VALUE,
1600 "glEnableVertexAttribArrayARB(index)");
1601 return;
1602 }
1603 c->array.a[index].enabled = GL_TRUE;
1604 DIRTY(cb->dirty, g->neg_bitid);
1605 DIRTY(cb->enableClientState, g->neg_bitid);
1606}
1607
1608
1609void STATE_APIENTRY crStateGetProgramEnvParameterdvARB(GLenum target, GLuint index, GLdouble *params)
1610{
1611 GLfloat fparams[4];
1612 crStateGetProgramEnvParameterfvARB(target, index, fparams);
1613 params[0] = fparams[0];
1614 params[1] = fparams[1];
1615 params[2] = fparams[2];
1616 params[3] = fparams[3];
1617}
1618
1619void STATE_APIENTRY crStateGetProgramEnvParameterfvARB(GLenum target, GLuint index, GLfloat *params)
1620{
1621 CRContext *g = GetCurrentContext();
1622 CRProgramState *p = &(g->program);
1623
1624 if (g->current.inBeginEnd) {
1625 crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION,
1626 "glGetProgramEnvParameterARB called in Begin/End");
1627 return;
1628 }
1629
1630 if (target == GL_FRAGMENT_PROGRAM_ARB || target == GL_FRAGMENT_PROGRAM_NV) {
1631 if (index >= g->limits.maxFragmentProgramEnvParams) {
1632 crStateError(__LINE__, __FILE__, GL_INVALID_VALUE,
1633 "glGetProgramEnvParameterARB(index)");
1634 return;
1635 }
1636 params[0] = p->fragmentParameters[index][0];
1637 params[1] = p->fragmentParameters[index][1];
1638 params[2] = p->fragmentParameters[index][2];
1639 params[3] = p->fragmentParameters[index][3];
1640 }
1641 else if (target == GL_VERTEX_PROGRAM_ARB || target == GL_VERTEX_PROGRAM_NV) {
1642 if (index >= g->limits.maxVertexProgramEnvParams) {
1643 crStateError(__LINE__, __FILE__, GL_INVALID_VALUE,
1644 "glGetProgramEnvParameterARB(index)");
1645 return;
1646 }
1647 params[0] = p->vertexParameters[index][0];
1648 params[1] = p->vertexParameters[index][1];
1649 params[2] = p->vertexParameters[index][2];
1650 params[3] = p->vertexParameters[index][3];
1651 }
1652 else {
1653 crStateError(__LINE__, __FILE__, GL_INVALID_ENUM,
1654 "glGetProgramEnvParameterARB(target)");
1655 return;
1656 }
1657}
1658
1659
1660void STATE_APIENTRY crStateProgramEnvParameter4dARB(GLenum target, GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w)
1661{
1662 crStateProgramEnvParameter4fARB(target, index, (GLfloat) x, (GLfloat) y, (GLfloat) z, (GLfloat) w);
1663}
1664
1665void STATE_APIENTRY crStateProgramEnvParameter4dvARB(GLenum target, GLuint index, const GLdouble *params)
1666{
1667 crStateProgramEnvParameter4fARB(target, index, (GLfloat) params[0], (GLfloat) params[1], (GLfloat) params[2], (GLfloat) params[3]);
1668}
1669
1670void STATE_APIENTRY crStateProgramEnvParameter4fARB(GLenum target, GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w)
1671{
1672 CRContext *g = GetCurrentContext();
1673 CRProgramState *p = &(g->program);
1674 CRStateBits *sb = GetCurrentBits();
1675 CRProgramBits *pb = &(sb->program);
1676
1677 if (g->current.inBeginEnd) {
1678 crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION,
1679 "glProgramEnvParameterARB called in Begin/End");
1680 return;
1681 }
1682
1683 if (target == GL_FRAGMENT_PROGRAM_ARB || target == GL_FRAGMENT_PROGRAM_NV) {
1684 if (index >= g->limits.maxFragmentProgramEnvParams) {
1685 crStateError(__LINE__, __FILE__, GL_INVALID_VALUE,
1686 "glProgramEnvParameterARB(index)");
1687 return;
1688 }
1689 p->fragmentParameters[index][0] = x;
1690 p->fragmentParameters[index][1] = y;
1691 p->fragmentParameters[index][2] = z;
1692 p->fragmentParameters[index][3] = w;
1693 DIRTY(pb->fragmentEnvParameter[index], g->neg_bitid);
1694 DIRTY(pb->fragmentEnvParameters, g->neg_bitid);
1695 }
1696 else if (target == GL_VERTEX_PROGRAM_ARB || target == GL_VERTEX_PROGRAM_NV) {
1697 if (index >= g->limits.maxVertexProgramEnvParams) {
1698 crStateError(__LINE__, __FILE__, GL_INVALID_VALUE,
1699 "glProgramEnvParameterARB(index)");
1700 return;
1701 }
1702 p->vertexParameters[index][0] = x;
1703 p->vertexParameters[index][1] = y;
1704 p->vertexParameters[index][2] = z;
1705 p->vertexParameters[index][3] = w;
1706 DIRTY(pb->vertexEnvParameter[index], g->neg_bitid);
1707 DIRTY(pb->vertexEnvParameters, g->neg_bitid);
1708 }
1709 else {
1710 crStateError(__LINE__, __FILE__, GL_INVALID_ENUM,
1711 "glProgramEnvParameterARB(target)");
1712 return;
1713 }
1714
1715 DIRTY(pb->dirty, g->neg_bitid);
1716}
1717
1718void STATE_APIENTRY crStateProgramEnvParameter4fvARB(GLenum target, GLuint index, const GLfloat *params)
1719{
1720 crStateProgramEnvParameter4fARB(target, index, params[0], params[1], params[2], params[3]);
1721}
1722
1723
1724/**********************************************************************/
1725
1726
1727void crStateProgramInit( CRContext *ctx )
1728{
1729 CRProgramState *p = &(ctx->program);
1730 CRStateBits *sb = GetCurrentBits();
1731 CRProgramBits *pb = &(sb->program);
1732 GLuint i;
1733
1734 CRASSERT(CR_MAX_PROGRAM_ENV_PARAMS >= CR_MAX_VERTEX_PROGRAM_ENV_PARAMS);
1735 CRASSERT(CR_MAX_PROGRAM_ENV_PARAMS >= CR_MAX_FRAGMENT_PROGRAM_ENV_PARAMS);
1736
1737 CRASSERT(CR_MAX_PROGRAM_LOCAL_PARAMS >= CR_MAX_VERTEX_PROGRAM_LOCAL_PARAMS);
1738 CRASSERT(CR_MAX_PROGRAM_LOCAL_PARAMS >= CR_MAX_FRAGMENT_PROGRAM_LOCAL_PARAMS);
1739
1740 p->programHash = crAllocHashtable();
1741
1742 /* ARB_vertex/fragment_program define default program objects */
1743 p->defaultVertexProgram = GetProgram(p, GL_VERTEX_PROGRAM_ARB, 0);
1744 p->defaultFragmentProgram = GetProgram(p, GL_FRAGMENT_PROGRAM_ARB, 0);
1745
1746 p->currentVertexProgram = p->defaultVertexProgram;
1747 p->currentFragmentProgram = p->defaultFragmentProgram;
1748 p->errorPos = -1;
1749 p->errorString = NULL;
1750
1751 for (i = 0; i < ctx->limits.maxVertexProgramEnvParams / 4; i++) {
1752 p->TrackMatrix[i] = GL_NONE;
1753 p->TrackMatrixTransform[i] = GL_IDENTITY_NV;
1754 }
1755 for (i = 0; i < ctx->limits.maxVertexProgramEnvParams; i++) {
1756 p->vertexParameters[i][0] = 0.0;
1757 p->vertexParameters[i][1] = 0.0;
1758 p->vertexParameters[i][2] = 0.0;
1759 p->vertexParameters[i][3] = 0.0;
1760 }
1761 for (i = 0; i < CR_MAX_FRAGMENT_PROGRAM_ENV_PARAMS; i++) {
1762 p->fragmentParameters[i][0] = 0.0;
1763 p->fragmentParameters[i][1] = 0.0;
1764 p->fragmentParameters[i][2] = 0.0;
1765 p->fragmentParameters[i][3] = 0.0;
1766 }
1767
1768 p->vpEnabled = GL_FALSE;
1769 p->fpEnabled = GL_FALSE;
1770 p->fpEnabledARB = GL_FALSE;
1771 p->vpPointSize = GL_FALSE;
1772 p->vpTwoSide = GL_FALSE;
1773 RESET(pb->dirty, ctx->bitid);
1774}
1775
1776
1777static void DeleteProgramCallback( void *data )
1778{
1779 CRProgram *prog = (CRProgram *) data;
1780 DeleteProgram(prog);
1781}
1782
1783void crStateProgramDestroy(CRContext *ctx)
1784{
1785 CRProgramState *p = &(ctx->program);
1786 crFreeHashtable(p->programHash, DeleteProgramCallback);
1787 DeleteProgram(p->defaultVertexProgram);
1788 DeleteProgram(p->defaultFragmentProgram);
1789}
1790
1791
1792/* XXX it would be nice to autogenerate this, but we can't for now.
1793 */
1794void
1795crStateProgramDiff(CRProgramBits *b, CRbitvalue *bitID,
1796 CRContext *fromCtx, CRContext *toCtx)
1797{
1798 CRProgramState *from = &(fromCtx->program);
1799 CRProgramState *to = &(toCtx->program);
1800 unsigned int i, j;
1801 CRbitvalue nbitID[CR_MAX_BITARRAY];
1802
1803 CRASSERT(from->currentVertexProgram);
1804 CRASSERT(to->currentVertexProgram);
1805 CRASSERT(from->currentFragmentProgram);
1806 CRASSERT(to->currentFragmentProgram);
1807
1808 for (j=0;j<CR_MAX_BITARRAY;j++)
1809 nbitID[j] = ~bitID[j];
1810
1811 /* vertex program enable */
1812 if (CHECKDIRTY(b->vpEnable, bitID)) {
1813 glAble able[2];
1814 CRProgram *toProg = to->currentVertexProgram;
1815
1816 able[0] = diff_api.Disable;
1817 able[1] = diff_api.Enable;
1818 if (from->vpEnabled != to->vpEnabled) {
1819 if (toProg->isARBprogram)
1820 able[to->vpEnabled](GL_VERTEX_PROGRAM_ARB);
1821 else
1822 able[to->vpEnabled](GL_VERTEX_PROGRAM_NV);
1823 from->vpEnabled = to->vpEnabled;
1824 }
1825 if (from->vpTwoSide != to->vpTwoSide) {
1826 able[to->vpTwoSide](GL_VERTEX_PROGRAM_TWO_SIDE_NV);
1827 from->vpTwoSide = to->vpTwoSide;
1828 }
1829 if (from->vpPointSize != to->vpPointSize) {
1830 able[to->vpPointSize](GL_VERTEX_PROGRAM_POINT_SIZE_NV);
1831 from->vpPointSize = to->vpPointSize;
1832 }
1833 CLEARDIRTY(b->vpEnable, nbitID);
1834 }
1835
1836 /* fragment program enable */
1837 if (CHECKDIRTY(b->fpEnable, bitID)) {
1838 glAble able[2];
1839 able[0] = diff_api.Disable;
1840 able[1] = diff_api.Enable;
1841 if (from->fpEnabled != to->fpEnabled) {
1842 able[to->fpEnabled](GL_FRAGMENT_PROGRAM_NV);
1843 from->fpEnabled = to->fpEnabled;
1844 }
1845 if (from->fpEnabledARB != to->fpEnabledARB) {
1846 able[to->fpEnabledARB](GL_FRAGMENT_PROGRAM_ARB);
1847 from->fpEnabledARB = to->fpEnabledARB;
1848 }
1849 CLEARDIRTY(b->fpEnable, nbitID);
1850 }
1851
1852 /* program/track matrices */
1853 if (to->vpEnabled) {
1854 for (i = 0; i < toCtx->limits.maxVertexProgramEnvParams / 4; i++) {
1855 if (CHECKDIRTY(b->trackMatrix[i], bitID)) {
1856 if (from->TrackMatrix[i] != to->TrackMatrix[i] ||
1857 from->TrackMatrixTransform[i] != to->TrackMatrixTransform[i]) {
1858 diff_api.TrackMatrixNV(GL_VERTEX_PROGRAM_NV, i * 4,
1859 to->TrackMatrix[i],
1860 to->TrackMatrixTransform[i]);
1861 from->TrackMatrix[i] = to->TrackMatrix[i];
1862 from->TrackMatrixTransform[i] = to->TrackMatrixTransform[i];
1863 }
1864 CLEARDIRTY(b->trackMatrix[i], nbitID);
1865 }
1866 }
1867 }
1868
1869 if (to->vpEnabled) {
1870 /* vertex program binding */
1871 CRProgram *fromProg = from->currentVertexProgram;
1872 CRProgram *toProg = to->currentVertexProgram;
1873
1874 if (CHECKDIRTY(b->vpBinding, bitID)) {
1875 if (fromProg->id != toProg->id) {
1876 if (toProg->isARBprogram)
1877 diff_api.BindProgramARB(GL_VERTEX_PROGRAM_ARB, toProg->id);
1878 else
1879 diff_api.BindProgramNV(GL_VERTEX_PROGRAM_NV, toProg->id);
1880 from->currentVertexProgram = toProg;
1881 }
1882 CLEARDIRTY(b->vpBinding, nbitID);
1883 }
1884
1885 if (toProg) {
1886 /* vertex program text */
1887 if (CHECKDIRTY(toProg->dirtyProgram, bitID)) {
1888 if (toProg->isARBprogram) {
1889 diff_api.ProgramStringARB( GL_VERTEX_PROGRAM_ARB, toProg->format, toProg->length, toProg->string );
1890 }
1891 else {
1892 diff_api.LoadProgramNV( GL_VERTEX_PROGRAM_NV, toProg->id, toProg->length, toProg->string );
1893 }
1894 CLEARDIRTY(toProg->dirtyProgram, nbitID);
1895 }
1896
1897 /* vertex program global/env parameters */
1898 if (CHECKDIRTY(b->vertexEnvParameters, bitID)) {
1899 for (i = 0; i < toCtx->limits.maxVertexProgramEnvParams; i++) {
1900 if (CHECKDIRTY(b->vertexEnvParameter[i], bitID)) {
1901 if (toProg->isARBprogram)
1902 diff_api.ProgramEnvParameter4fvARB(GL_VERTEX_PROGRAM_ARB, i,
1903 to->vertexParameters[i]);
1904 else
1905 diff_api.ProgramParameter4fvNV(GL_VERTEX_PROGRAM_NV, i,
1906 to->vertexParameters[i]);
1907 if (fromProg) {
1908 COPY_4V(from->vertexParameters[i],
1909 to->vertexParameters[i]);
1910 }
1911 CLEARDIRTY(b->vertexEnvParameter[i], nbitID);
1912 }
1913 }
1914 CLEARDIRTY(b->vertexEnvParameters, nbitID);
1915 }
1916
1917 /* vertex program local parameters */
1918 if (CHECKDIRTY(toProg->dirtyParams, bitID)) {
1919 for (i = 0; i < toCtx->limits.maxVertexProgramLocalParams; i++) {
1920 if (CHECKDIRTY(toProg->dirtyParam[i], bitID)) {
1921 if (toProg->isARBprogram)
1922 diff_api.ProgramLocalParameter4fvARB(GL_VERTEX_PROGRAM_ARB, i, toProg->parameters[i]);
1923 else
1924 diff_api.ProgramLocalParameter4fvARB(GL_VERTEX_PROGRAM_NV, i, toProg->parameters[i]);
1925 CLEARDIRTY(toProg->dirtyParam[i], nbitID);
1926 }
1927 }
1928 CLEARDIRTY(toProg->dirtyParams, nbitID);
1929 }
1930 }
1931 }
1932
1933 /*
1934 * Separate paths for NV vs ARB fragment program
1935 */
1936 if (to->fpEnabled) {
1937 /* NV fragment program binding */
1938 CRProgram *fromProg = from->currentFragmentProgram;
1939 CRProgram *toProg = to->currentFragmentProgram;
1940 if (CHECKDIRTY(b->fpBinding, bitID)) {
1941 if (fromProg->id != toProg->id) {
1942 diff_api.BindProgramNV(GL_FRAGMENT_PROGRAM_NV, toProg->id);
1943 from->currentFragmentProgram = toProg;
1944 }
1945 CLEARDIRTY(b->fpBinding, nbitID);
1946 }
1947
1948 if (toProg) {
1949 /* fragment program text */
1950 if (CHECKDIRTY(toProg->dirtyProgram, bitID)) {
1951 diff_api.LoadProgramNV( GL_FRAGMENT_PROGRAM_NV, toProg->id,
1952 toProg->length, toProg->string );
1953 CLEARDIRTY(toProg->dirtyProgram, nbitID);
1954 }
1955
1956 /* fragment program global/env parameters */
1957 if (CHECKDIRTY(b->fragmentEnvParameters, bitID)) {
1958 for (i = 0; i < toCtx->limits.maxFragmentProgramEnvParams; i++) {
1959 if (CHECKDIRTY(b->fragmentEnvParameter[i], bitID)) {
1960 diff_api.ProgramParameter4fvNV(GL_FRAGMENT_PROGRAM_NV, i,
1961 to->fragmentParameters[i]);
1962 if (fromProg) {
1963 COPY_4V(from->fragmentParameters[i],
1964 to->fragmentParameters[i]);
1965 }
1966 CLEARDIRTY(b->fragmentEnvParameter[i], nbitID);
1967 }
1968 }
1969 CLEARDIRTY(b->fragmentEnvParameters, nbitID);
1970 }
1971
1972 /* named local parameters */
1973 if (CHECKDIRTY(toProg->dirtyNamedParams, bitID)) {
1974 CRProgramSymbol *symbol;
1975 for (symbol = toProg->symbolTable; symbol; symbol = symbol->next) {
1976 if (CHECKDIRTY(symbol->dirty, bitID)) {
1977 GLint len = crStrlen(symbol->name);
1978 diff_api.ProgramNamedParameter4fvNV(toProg->id, len,
1979 (const GLubyte *) symbol->name,
1980 symbol->value);
1981 if (fromProg) {
1982 SetProgramSymbol(fromProg, symbol->name, len,
1983 symbol->value[0], symbol->value[1],
1984 symbol->value[2], symbol->value[3]);
1985 }
1986 CLEARDIRTY(symbol->dirty, nbitID);
1987 }
1988 }
1989 CLEARDIRTY(toProg->dirtyNamedParams, nbitID);
1990 }
1991
1992 /* numbered local parameters */
1993 if (CHECKDIRTY(toProg->dirtyParams, bitID)) {
1994 for (i = 0; i < CR_MAX_FRAGMENT_PROGRAM_LOCAL_PARAMS; i++) {
1995 if (CHECKDIRTY(toProg->dirtyParam[i], bitID)) {
1996 diff_api.ProgramLocalParameter4fvARB(GL_FRAGMENT_PROGRAM_NV, i,
1997 toProg->parameters[i]);
1998 if (fromProg) {
1999 COPY_4V(fromProg->parameters[i], toProg->parameters[i]);
2000 }
2001 CLEARDIRTY(toProg->dirtyParam[i], nbitID);
2002 }
2003 }
2004 CLEARDIRTY(toProg->dirtyParams, nbitID);
2005 }
2006 }
2007 }
2008 else if (to->fpEnabledARB) {
2009 /* ARB fragment program binding */
2010 CRProgram *fromProg = from->currentFragmentProgram;
2011 CRProgram *toProg = to->currentFragmentProgram;
2012 if (CHECKDIRTY(b->fpBinding, bitID)) {
2013 if (fromProg->id != toProg->id) {
2014 diff_api.BindProgramARB(GL_FRAGMENT_PROGRAM_ARB, toProg->id);
2015 from->currentFragmentProgram = toProg;
2016 }
2017 CLEARDIRTY(b->fpBinding, nbitID);
2018 }
2019
2020 if (toProg) {
2021 /* fragment program text */
2022 if (CHECKDIRTY(toProg->dirtyProgram, bitID)) {
2023 diff_api.ProgramStringARB( GL_FRAGMENT_PROGRAM_ARB, toProg->format,
2024 toProg->length, toProg->string );
2025 CLEARDIRTY(toProg->dirtyProgram, nbitID);
2026 }
2027
2028 /* fragment program global/env parameters */
2029 if (CHECKDIRTY(b->fragmentEnvParameters, bitID)) {
2030 for (i = 0; i < toCtx->limits.maxFragmentProgramEnvParams; i++) {
2031 if (CHECKDIRTY(b->fragmentEnvParameter[i], bitID)) {
2032 diff_api.ProgramEnvParameter4fvARB(GL_FRAGMENT_PROGRAM_ARB, i,
2033 to->fragmentParameters[i]);
2034 if (fromProg) {
2035 COPY_4V(from->fragmentParameters[i],
2036 to->fragmentParameters[i]);
2037 }
2038 CLEARDIRTY(b->fragmentEnvParameter[i], nbitID);
2039 }
2040 }
2041 CLEARDIRTY(b->fragmentEnvParameters, nbitID);
2042 }
2043
2044 /* numbered local parameters */
2045 if (CHECKDIRTY(toProg->dirtyParams, bitID)) {
2046 for (i = 0; i < CR_MAX_FRAGMENT_PROGRAM_LOCAL_PARAMS; i++) {
2047 if (CHECKDIRTY(toProg->dirtyParam[i], bitID)) {
2048 diff_api.ProgramLocalParameter4fvARB(GL_FRAGMENT_PROGRAM_ARB, i,
2049 toProg->parameters[i]);
2050 if (fromProg) {
2051 COPY_4V(fromProg->parameters[i], toProg->parameters[i]);
2052 }
2053 CLEARDIRTY(toProg->dirtyParam[i], nbitID);
2054 }
2055 }
2056 CLEARDIRTY(toProg->dirtyParams, nbitID);
2057 }
2058 }
2059 }
2060
2061 CLEARDIRTY(b->dirty, nbitID);
2062}
2063
2064
2065void
2066crStateProgramSwitch(CRProgramBits *b, CRbitvalue *bitID,
2067 CRContext *fromCtx, CRContext *toCtx)
2068{
2069 CRProgramState *from = &(fromCtx->program);
2070 CRProgramState *to = &(toCtx->program);
2071 unsigned int i, j;
2072 CRbitvalue nbitID[CR_MAX_BITARRAY];
2073 GLenum whichVert = fromCtx->extensions.ARB_vertex_program && toCtx->extensions.ARB_vertex_program ? GL_VERTEX_PROGRAM_ARB : GL_VERTEX_PROGRAM_NV;
2074
2075
2076 for (j=0;j<CR_MAX_BITARRAY;j++)
2077 nbitID[j] = ~bitID[j];
2078
2079 /* vertex program enable */
2080 if (CHECKDIRTY(b->vpEnable, bitID)) {
2081 glAble able[2];
2082 able[0] = diff_api.Disable;
2083 able[1] = diff_api.Enable;
2084 if (from->vpEnabled != to->vpEnabled) {
2085 able[to->vpEnabled](whichVert);
2086 }
2087 if (from->vpTwoSide != to->vpTwoSide) {
2088 able[to->vpTwoSide](GL_VERTEX_PROGRAM_TWO_SIDE_NV);
2089 }
2090 if (from->vpPointSize != to->vpPointSize) {
2091 able[to->vpPointSize](GL_VERTEX_PROGRAM_POINT_SIZE_NV);
2092 }
2093 DIRTY(b->vpEnable, nbitID);
2094 }
2095
2096 /* fragment program enable */
2097 if (CHECKDIRTY(b->fpEnable, bitID)) {
2098 glAble able[2];
2099 able[0] = diff_api.Disable;
2100 able[1] = diff_api.Enable;
2101 if (from->fpEnabled != to->fpEnabled) {
2102 able[to->fpEnabled](GL_FRAGMENT_PROGRAM_NV);
2103 }
2104 if (from->fpEnabledARB != to->fpEnabledARB) {
2105 able[to->fpEnabledARB](GL_FRAGMENT_PROGRAM_ARB);
2106 }
2107 DIRTY(b->fpEnable, nbitID);
2108 }
2109
2110 /* program/track matrices */
2111 if (to->vpEnabled) {
2112 for (i = 0; i < toCtx->limits.maxVertexProgramEnvParams / 4; i++) {
2113 if (CHECKDIRTY(b->trackMatrix[i], bitID)) {
2114 if (from->TrackMatrix[i] != to->TrackMatrix[i]) {
2115 diff_api.TrackMatrixNV(GL_VERTEX_PROGRAM_NV, i * 4,
2116 to->TrackMatrix[i],
2117 to->TrackMatrixTransform[i]);
2118 }
2119 DIRTY(b->trackMatrix[i], nbitID);
2120 }
2121 }
2122 }
2123
2124 if (to->vpEnabled) {
2125 /* vertex program binding */
2126 CRProgram *fromProg = from->currentVertexProgram;
2127 CRProgram *toProg = to->currentVertexProgram;
2128 if (CHECKDIRTY(b->vpBinding, bitID)) {
2129 if (fromProg->id != toProg->id) {
2130 if (toProg->isARBprogram)
2131 diff_api.BindProgramARB(GL_VERTEX_PROGRAM_ARB, toProg->id);
2132 else
2133 diff_api.BindProgramNV(GL_VERTEX_PROGRAM_NV, toProg->id);
2134 }
2135 DIRTY(b->vpBinding, nbitID);
2136 }
2137
2138 if (toProg) {
2139 /* vertex program text */
2140 if (CHECKDIRTY(toProg->dirtyProgram, bitID)) {
2141 if (toProg->isARBprogram)
2142 diff_api.ProgramStringARB(GL_VERTEX_PROGRAM_ARB, toProg->format, toProg->length, toProg->string);
2143 else
2144 diff_api.LoadProgramNV(GL_VERTEX_PROGRAM_NV, toProg->id, toProg->length, toProg->string);
2145
2146 DIRTY(toProg->dirtyProgram, nbitID);
2147 }
2148
2149 /* vertex program global/env parameters */
2150 if (CHECKDIRTY(b->vertexEnvParameters, bitID)) {
2151 for (i = 0; i < toCtx->limits.maxVertexProgramEnvParams; i++) {
2152 if (CHECKDIRTY(b->vertexEnvParameter[i], bitID)) {
2153 if (toProg->isARBprogram)
2154 diff_api.ProgramEnvParameter4fvARB(GL_VERTEX_PROGRAM_ARB, i, to->vertexParameters[i]);
2155 else
2156 diff_api.ProgramParameter4fvNV(GL_VERTEX_PROGRAM_NV, i, to->vertexParameters[i]);
2157
2158 DIRTY(b->vertexEnvParameter[i], nbitID);
2159 }
2160 }
2161 DIRTY(b->vertexEnvParameters, nbitID);
2162 }
2163
2164 /* vertex program local parameters */
2165 if (CHECKDIRTY(toProg->dirtyParams, bitID)) {
2166 for (i = 0; i < toCtx->limits.maxVertexProgramLocalParams; i++) {
2167 if (CHECKDIRTY(toProg->dirtyParam[i], bitID)) {
2168
2169
2170 if (toProg->isARBprogram)
2171 diff_api.ProgramLocalParameter4fvARB(GL_VERTEX_PROGRAM_ARB, i, toProg->parameters[i]);
2172 else
2173 diff_api.ProgramLocalParameter4fvARB(GL_VERTEX_PROGRAM_NV, i, toProg->parameters[i]);
2174 }
2175 }
2176 DIRTY(toProg->dirtyParams, nbitID);
2177 }
2178 }
2179 }
2180
2181 /*
2182 * Separate paths for NV vs ARB fragment program
2183 */
2184 if (to->fpEnabled) {
2185 /* NV fragment program binding */
2186 CRProgram *fromProg = from->currentFragmentProgram;
2187 CRProgram *toProg = to->currentFragmentProgram;
2188 if (CHECKDIRTY(b->fpBinding, bitID)) {
2189 if (fromProg->id != toProg->id) {
2190 diff_api.BindProgramNV(GL_FRAGMENT_PROGRAM_NV, toProg->id);
2191 }
2192 DIRTY(b->fpBinding, nbitID);
2193 }
2194
2195 if (toProg) {
2196 /* fragment program text */
2197 if (CHECKDIRTY(toProg->dirtyProgram, bitID)) {
2198 diff_api.LoadProgramNV(GL_FRAGMENT_PROGRAM_NV, toProg->id, toProg->length, toProg->string);
2199 DIRTY(toProg->dirtyProgram, nbitID);
2200 }
2201
2202 /* fragment program global/env parameters */
2203 if (CHECKDIRTY(b->fragmentEnvParameters, bitID)) {
2204 for (i = 0; i < toCtx->limits.maxFragmentProgramEnvParams; i++) {
2205 if (CHECKDIRTY(b->fragmentEnvParameter[i], bitID)) {
2206 diff_api.ProgramParameter4fvNV(GL_FRAGMENT_PROGRAM_NV, i,
2207 to->fragmentParameters[i]);
2208 DIRTY(b->fragmentEnvParameter[i], nbitID);
2209 }
2210 }
2211 DIRTY(b->fragmentEnvParameters, nbitID);
2212 }
2213
2214 /* named local parameters */
2215 if (CHECKDIRTY(toProg->dirtyNamedParams, bitID)) {
2216 CRProgramSymbol *symbol;
2217 for (symbol = toProg->symbolTable; symbol; symbol = symbol->next) {
2218 if (CHECKDIRTY(symbol->dirty, bitID)) {
2219 GLint len = crStrlen(symbol->name);
2220 diff_api.ProgramNamedParameter4fvNV(toProg->id, len,
2221 (const GLubyte *) symbol->name,
2222 symbol->value);
2223 DIRTY(symbol->dirty, nbitID);
2224 }
2225 }
2226 DIRTY(toProg->dirtyNamedParams, nbitID);
2227 }
2228
2229 /* numbered local parameters */
2230 if (CHECKDIRTY(toProg->dirtyParams, bitID)) {
2231 for (i = 0; i < CR_MAX_FRAGMENT_PROGRAM_LOCAL_PARAMS; i++) {
2232 if (CHECKDIRTY(toProg->dirtyParam[i], bitID)) {
2233 if (toProg->isARBprogram)
2234 diff_api.ProgramLocalParameter4fvARB(GL_FRAGMENT_PROGRAM_ARB, i, toProg->parameters[i]);
2235 else
2236 diff_api.ProgramLocalParameter4fvARB(GL_FRAGMENT_PROGRAM_NV, i, toProg->parameters[i]);
2237 }
2238 }
2239 DIRTY(toProg->dirtyParams, nbitID);
2240 }
2241 }
2242 }
2243 else if (to->fpEnabledARB) {
2244 /* ARB fragment program binding */
2245 CRProgram *fromProg = from->currentFragmentProgram;
2246 CRProgram *toProg = to->currentFragmentProgram;
2247 if (CHECKDIRTY(b->fpBinding, bitID)) {
2248 if (fromProg->id != toProg->id) {
2249 diff_api.BindProgramARB(GL_FRAGMENT_PROGRAM_ARB, toProg->id);
2250 }
2251 DIRTY(b->fpBinding, nbitID);
2252 }
2253
2254 if (toProg) {
2255 /* fragment program text */
2256 if (CHECKDIRTY(toProg->dirtyProgram, bitID)) {
2257 diff_api.ProgramStringARB(GL_FRAGMENT_PROGRAM_ARB, toProg->format, toProg->length, toProg->string);
2258 DIRTY(toProg->dirtyProgram, nbitID);
2259 }
2260
2261 /* fragment program global/env parameters */
2262 if (CHECKDIRTY(b->fragmentEnvParameters, bitID)) {
2263 for (i = 0; i < toCtx->limits.maxFragmentProgramEnvParams; i++) {
2264 if (CHECKDIRTY(b->fragmentEnvParameter[i], bitID)) {
2265 diff_api.ProgramEnvParameter4fvARB(GL_FRAGMENT_PROGRAM_ARB, i, to->fragmentParameters[i]);
2266 DIRTY(b->fragmentEnvParameter[i], nbitID);
2267 }
2268 }
2269 DIRTY(b->fragmentEnvParameters, nbitID);
2270 }
2271
2272 /* numbered local parameters */
2273 if (CHECKDIRTY(toProg->dirtyParams, bitID)) {
2274 for (i = 0; i < CR_MAX_FRAGMENT_PROGRAM_LOCAL_PARAMS; i++) {
2275 if (CHECKDIRTY(toProg->dirtyParam[i], bitID)) {
2276 diff_api.ProgramLocalParameter4fvARB(GL_FRAGMENT_PROGRAM_ARB, i, toProg->parameters[i]);
2277 DIRTY(toProg->dirtyParam[i], nbitID);
2278 }
2279 }
2280 DIRTY(toProg->dirtyParams, nbitID);
2281 }
2282 }
2283 }
2284
2285 DIRTY(b->dirty, nbitID);
2286
2287 /* Resend program data */
2288 if (toCtx->program.bResyncNeeded)
2289 {
2290 toCtx->program.bResyncNeeded = GL_FALSE;
2291
2292 crStateDiffAllPrograms(toCtx, bitID, GL_TRUE);
2293 }
2294}
2295
2296/*@todo support NVprograms and add some data validity checks*/
2297static void
2298DiffProgramCallback(unsigned long key, void *pProg, void *pCtx)
2299{
2300 CRContext *pContext = (CRContext *) pCtx;
2301 CRProgram *pProgram = (CRProgram *) pProg;
2302 uint32_t i;
2303
2304 if (pProgram->isARBprogram)
2305 {
2306 diff_api.BindProgramARB(pProgram->target, pProgram->id);
2307 diff_api.ProgramStringARB(pProgram->target, pProgram->format, pProgram->length, pProgram->string);
2308
2309 if (GL_VERTEX_PROGRAM_ARB == pProgram->target)
2310 {
2311 /* vertex program global/env parameters */
2312 for (i = 0; i < pContext->limits.maxVertexProgramEnvParams; i++)
2313 {
2314 diff_api.ProgramEnvParameter4fvARB(GL_VERTEX_PROGRAM_ARB, i, pContext->program.vertexParameters[i]);
2315 }
2316 /* vertex program local parameters */
2317 for (i = 0; i < pContext->limits.maxVertexProgramLocalParams; i++)
2318 {
2319 diff_api.ProgramLocalParameter4fvARB(GL_VERTEX_PROGRAM_ARB, i, pProgram->parameters[i]);
2320 }
2321 }
2322 else if (GL_FRAGMENT_PROGRAM_ARB == pProgram->target)
2323 {
2324 /* vertex program global/env parameters */
2325 for (i = 0; i < pContext->limits.maxFragmentProgramEnvParams; i++)
2326 {
2327 diff_api.ProgramEnvParameter4fvARB(GL_FRAGMENT_PROGRAM_ARB, i, pContext->program.fragmentParameters[i]);
2328 }
2329 /* vertex program local parameters */
2330 for (i = 0; i < CR_MAX_FRAGMENT_PROGRAM_LOCAL_PARAMS; i++)
2331 {
2332 diff_api.ProgramLocalParameter4fvARB(GL_FRAGMENT_PROGRAM_ARB, i, pProgram->parameters[i]);
2333 }
2334 }
2335 else
2336 {
2337 crError("Unexpected program target");
2338 }
2339 }
2340 else
2341 {
2342 diff_api.BindProgramNV(pProgram->target, pProgram->id);
2343 }
2344}
2345
2346void crStateDiffAllPrograms(CRContext *g, CRbitvalue *bitID, GLboolean bForceUpdate)
2347{
2348 CRProgram *pOrigVP, *pOrigFP;
2349
2350 (void) bForceUpdate;
2351
2352 /* save original bindings */
2353 pOrigVP = g->program.currentVertexProgram;
2354 pOrigFP = g->program.currentFragmentProgram;
2355
2356 crHashtableWalk(g->program.programHash, DiffProgramCallback, g);
2357
2358 /* restore original bindings */
2359 if (pOrigVP->isARBprogram)
2360 diff_api.BindProgramARB(pOrigVP->target, pOrigVP->id);
2361 else
2362 diff_api.BindProgramNV(pOrigVP->target, pOrigVP->id);
2363
2364 if (pOrigFP->isARBprogram)
2365 diff_api.BindProgramARB(pOrigFP->target, pOrigFP->id);
2366 else
2367 diff_api.BindProgramNV(pOrigFP->target, pOrigFP->id);
2368}
注意: 瀏覽 TracBrowser 來幫助您使用儲存庫瀏覽器

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