VirtualBox

source: vbox/trunk/src/VBox/GuestHost/OpenGL/state_tracker/state_glsl.c@ 61334

Last change on this file since 61334 was 58151, checked in by vboxsync, 9 years ago

GuestHost/OpenGL: get the number of active uniforms only if they exist.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 42.3 KB
Line 
1/* $Id: state_glsl.c 58151 2015-10-09 13:36:35Z vboxsync $ */
2
3/** @file
4 * VBox OpenGL: GLSL state tracking
5 */
6
7/*
8 * Copyright (C) 2009-2012 Oracle Corporation
9 *
10 * This file is part of VirtualBox Open Source Edition (OSE), as
11 * available from http://www.virtualbox.org. This file is free software;
12 * you can redistribute it and/or modify it under the terms of the GNU
13 * General Public License (GPL) as published by the Free Software
14 * Foundation, in version 2 as it comes in the "COPYING" file of the
15 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
16 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
17 */
18
19#include "state.h"
20#include "state/cr_statetypes.h"
21#include "state/cr_statefuncs.h"
22#include "state_internals.h"
23#include "cr_mem.h"
24#include "cr_string.h"
25
26static CRGLSLShader* crStateGetShaderObj(GLuint id)
27{
28 CRContext *g = GetCurrentContext();
29
30 if (!g)
31 {
32 crWarning("crStateGetShaderObj called without current ctx");
33 }
34
35 return !g ? NULL : (CRGLSLShader *) crHashtableSearch(g->glsl.shaders, id);
36}
37
38static CRGLSLProgram* crStateGetProgramObj(GLuint id)
39{
40 CRContext *g = GetCurrentContext();
41
42 if (!g)
43 {
44 crWarning("crStateGetProgramObj called without current ctx");
45 }
46
47 return !g ? NULL : (CRGLSLProgram *) crHashtableSearch(g->glsl.programs, id);
48}
49
50static void crStateFreeGLSLShader(void *data)
51{
52 CRGLSLShader* pShader = (CRGLSLShader *) data;
53
54 if (pShader->source)
55 crFree(pShader->source);
56
57 crFree(pShader);
58}
59
60#ifdef IN_GUEST
61static void crStateFreeProgramAttribsLocationCache(CRGLSLProgram* pProgram)
62{
63 if (pProgram->pAttribs) crFree(pProgram->pAttribs);
64
65 pProgram->pAttribs = NULL;
66 pProgram->cAttribs = 0;
67}
68#endif
69
70static void crStateFreeProgramAttribs(CRGLSLProgram* pProgram)
71{
72 GLuint i;
73
74 for (i=0; i<pProgram->activeState.cAttribs; ++i)
75 {
76 crFree(pProgram->activeState.pAttribs[i].name);
77 }
78
79 for (i=0; i<pProgram->currentState.cAttribs; ++i)
80 {
81 crFree(pProgram->currentState.pAttribs[i].name);
82 }
83
84 if (pProgram->activeState.pAttribs)
85 crFree(pProgram->activeState.pAttribs);
86
87 if (pProgram->currentState.pAttribs)
88 crFree(pProgram->currentState.pAttribs);
89
90#ifdef IN_GUEST
91 crStateFreeProgramAttribsLocationCache(pProgram);
92
93 pProgram->bAttribsSynced = GL_FALSE;
94#endif
95
96}
97
98static void crStateFreeProgramUniforms(CRGLSLProgram* pProgram)
99{
100 GLuint i;
101
102 for (i=0; i<pProgram->cUniforms; ++i)
103 {
104 if (pProgram->pUniforms[i].name) crFree(pProgram->pUniforms[i].name);
105 if (pProgram->pUniforms[i].data) crFree(pProgram->pUniforms[i].data);
106 }
107
108 if (pProgram->pUniforms) crFree(pProgram->pUniforms);
109
110 pProgram->pUniforms = NULL;
111 pProgram->cUniforms = 0;
112
113#ifdef IN_GUEST
114 pProgram->bUniformsSynced = GL_FALSE;
115#endif
116}
117
118static void crStateShaderDecRefCount(void *data)
119{
120 CRGLSLShader *pShader = (CRGLSLShader *) data;
121
122 CRASSERT(pShader->refCount>0);
123
124 pShader->refCount--;
125
126 if (0==pShader->refCount && pShader->deleted)
127 {
128 CRContext *g = GetCurrentContext();
129 crHashtableDelete(g->glsl.shaders, pShader->id, crStateFreeGLSLShader);
130 }
131}
132
133static void crStateFakeDecRefCountCB(unsigned long key, void *data1, void *data2)
134{
135 CRGLSLShader *pShader = (CRGLSLShader *) data1;
136 CRContext *ctx = (CRContext*) data2;
137 CRGLSLShader *pRealShader;
138 (void) key;
139
140 pRealShader = crStateGetShaderObj(pShader->id);
141
142 if (pRealShader)
143 {
144 crStateShaderDecRefCount(pRealShader);
145 }
146 else
147 {
148 crWarning("crStateFakeDecRefCountCB: NULL pRealShader");
149 }
150}
151
152static void crStateFreeGLSLProgram(void *data)
153{
154 CRGLSLProgram* pProgram = (CRGLSLProgram *) data;
155
156 crFreeHashtable(pProgram->currentState.attachedShaders, crStateShaderDecRefCount);
157
158 if (pProgram->activeState.attachedShaders)
159 {
160 CRContext *g = GetCurrentContext();
161 crHashtableWalk(pProgram->activeState.attachedShaders, crStateFakeDecRefCountCB, g);
162 crFreeHashtable(pProgram->activeState.attachedShaders, crStateFreeGLSLShader);
163 }
164
165 crStateFreeProgramAttribs(pProgram);
166
167 crStateFreeProgramUniforms(pProgram);
168
169 crFree(pProgram);
170}
171
172DECLEXPORT(void) STATE_APIENTRY crStateGLSLInit(CRContext *ctx)
173{
174 ctx->glsl.shaders = crAllocHashtable();
175 ctx->glsl.programs = crAllocHashtable();
176 ctx->glsl.activeProgram = NULL;
177 ctx->glsl.bResyncNeeded = GL_FALSE;
178
179 if (!ctx->glsl.shaders || !ctx->glsl.programs)
180 {
181 crWarning("crStateGLSLInit: Out of memory!");
182 return;
183 }
184}
185
186DECLEXPORT(void) STATE_APIENTRY crStateGLSLDestroy(CRContext *ctx)
187{
188 CRContext *g = GetCurrentContext();
189
190 /*@todo: hack to allow crStateFreeGLSLProgram to work correctly,
191 as the current context isn't the one being destroyed*/
192#ifdef CHROMIUM_THREADSAFE
193 CRASSERT(g != ctx);
194 VBoxTlsRefAddRef(ctx); /* <- this is a hack to avoid subsequent SetCurrentContext(g) do recursive Destroy for ctx */
195 if (g)
196 VBoxTlsRefAddRef(g); /* <- ensure the g is not destroyed by the following SetCurrentContext call */
197 SetCurrentContext(ctx);
198#else
199 __currentContext = ctx;
200#endif
201
202 crFreeHashtable(ctx->glsl.programs, crStateFreeGLSLProgram);
203 crFreeHashtable(ctx->glsl.shaders, crStateFreeGLSLShader);
204
205#ifdef CHROMIUM_THREADSAFE
206 SetCurrentContext(g);
207 if (g)
208 VBoxTlsRefRelease(g);
209 VBoxTlsRefRelease(ctx); /* <- restore back the cRefs (see above) */
210#else
211 __currentContext = g;
212#endif
213
214}
215
216DECLEXPORT(GLuint) STATE_APIENTRY crStateGetShaderHWID(GLuint id)
217{
218 CRGLSLShader *pShader = crStateGetShaderObj(id);
219#ifdef IN_GUEST
220 CRASSERT(!pShader || pShader->hwid == id);
221#endif
222 return pShader ? pShader->hwid : 0;
223}
224
225DECLEXPORT(GLuint) STATE_APIENTRY crStateGetProgramHWID(GLuint id)
226{
227 CRGLSLProgram *pProgram = crStateGetProgramObj(id);
228#ifdef IN_GUEST
229 CRASSERT(!pProgram || pProgram->hwid == id);
230#endif
231 return pProgram ? pProgram->hwid : 0;
232}
233
234static void crStateCheckShaderHWIDCB(unsigned long key, void *data1, void *data2)
235{
236 CRGLSLShader *pShader = (CRGLSLShader *) data1;
237 crCheckIDHWID_t *pParms = (crCheckIDHWID_t*) data2;
238 (void) key;
239
240 if (pShader->hwid==pParms->hwid)
241 pParms->id = pShader->id;
242}
243
244static void crStateCheckProgramHWIDCB(unsigned long key, void *data1, void *data2)
245{
246 CRGLSLProgram *pProgram = (CRGLSLProgram *) data1;
247 crCheckIDHWID_t *pParms = (crCheckIDHWID_t*) data2;
248 (void) key;
249
250 if (pProgram->hwid==pParms->hwid)
251 pParms->id = pProgram->id;
252}
253
254DECLEXPORT(GLuint) STATE_APIENTRY crStateGLSLShaderHWIDtoID(GLuint hwid)
255{
256 CRContext *g = GetCurrentContext();
257 crCheckIDHWID_t parms;
258
259 parms.id = hwid;
260 parms.hwid = hwid;
261
262 crHashtableWalk(g->glsl.shaders, crStateCheckShaderHWIDCB, &parms);
263 return parms.id;
264}
265
266DECLEXPORT(GLuint) STATE_APIENTRY crStateGLSLProgramHWIDtoID(GLuint hwid)
267{
268 CRContext *g = GetCurrentContext();
269 crCheckIDHWID_t parms;
270
271 parms.id = hwid;
272 parms.hwid = hwid;
273
274 crHashtableWalk(g->glsl.programs, crStateCheckProgramHWIDCB, &parms);
275 return parms.id;
276}
277
278DECLEXPORT(GLuint) STATE_APIENTRY crStateDeleteObjectARB( VBoxGLhandleARB obj )
279{
280 GLuint hwId = crStateGetProgramHWID(obj);
281 if (hwId)
282 {
283 crStateDeleteProgram(obj);
284 }
285 else
286 {
287 hwId = crStateGetShaderHWID(obj);
288 crStateDeleteShader(obj);
289 }
290 return hwId;
291}
292
293DECLEXPORT(GLuint) STATE_APIENTRY crStateCreateShader(GLuint hwid, GLenum type)
294{
295 CRGLSLShader *pShader;
296 CRContext *g = GetCurrentContext();
297 GLuint stateId = hwid;
298
299#ifdef IN_GUEST
300 CRASSERT(!crStateGetShaderObj(stateId));
301#else
302 /* the proogram and shader names must not intersect because DeleteObjectARB must distinguish between them
303 * see crStateDeleteObjectARB
304 * this is why use programs table for shader keys allocation */
305 stateId = crHashtableAllocKeys(g->glsl.programs, 1);
306 if (!stateId)
307 {
308 crWarning("failed to allocate program key");
309 return 0;
310 }
311
312 Assert((pShader = crStateGetShaderObj(stateId)) == NULL);
313#endif
314
315 pShader = (CRGLSLShader *) crAlloc(sizeof(*pShader));
316 if (!pShader)
317 {
318 crWarning("crStateCreateShader: Out of memory!");
319 return 0;
320 }
321
322 pShader->id = stateId;
323 pShader->hwid = hwid;
324 pShader->type = type;
325 pShader->source = NULL;
326 pShader->compiled = GL_FALSE;
327 pShader->deleted = GL_FALSE;
328 pShader->refCount = 0;
329
330 crHashtableAdd(g->glsl.shaders, stateId, pShader);
331
332 return stateId;
333}
334
335DECLEXPORT(GLuint) STATE_APIENTRY crStateCreateProgram(GLuint hwid)
336{
337 CRGLSLProgram *pProgram;
338 CRContext *g = GetCurrentContext();
339 GLuint stateId = hwid;
340
341#ifdef IN_GUEST
342 pProgram = crStateGetProgramObj(stateId);
343 if (pProgram)
344 {
345 crWarning("Program object %d already exists!", stateId);
346 crStateDeleteProgram(stateId);
347 CRASSERT(!crStateGetProgramObj(stateId));
348 }
349#else
350 stateId = crHashtableAllocKeys(g->glsl.programs, 1);
351 if (!stateId)
352 {
353 crWarning("failed to allocate program key");
354 return 0;
355 }
356#endif
357
358 pProgram = (CRGLSLProgram *) crAlloc(sizeof(*pProgram));
359 if (!pProgram)
360 {
361 crWarning("crStateCreateProgram: Out of memory!");
362 return 0;
363 }
364
365 pProgram->id = stateId;
366 pProgram->hwid = hwid;
367 pProgram->validated = GL_FALSE;
368 pProgram->linked = GL_FALSE;
369 pProgram->deleted = GL_FALSE;
370 pProgram->activeState.attachedShaders = NULL;
371 pProgram->currentState.attachedShaders = crAllocHashtable();
372
373 pProgram->activeState.cAttribs = 0;
374 pProgram->activeState.pAttribs = NULL;
375 pProgram->currentState.cAttribs = 0;
376 pProgram->currentState.pAttribs = NULL;
377
378 pProgram->pUniforms = NULL;
379 pProgram->cUniforms = 0;
380
381#ifdef IN_GUEST
382 pProgram->pAttribs = NULL;
383 pProgram->cAttribs = 0;
384
385 pProgram->bUniformsSynced = GL_FALSE;
386 pProgram->bAttribsSynced = GL_FALSE;
387#endif
388
389 crHashtableAdd(g->glsl.programs, stateId, pProgram);
390
391 return stateId;
392}
393
394DECLEXPORT(void) STATE_APIENTRY crStateCompileShader(GLuint shader)
395{
396 CRGLSLShader *pShader = crStateGetShaderObj(shader);
397 if (!pShader)
398 {
399 crWarning("Unknown shader %d", shader);
400 return;
401 }
402
403 pShader->compiled = GL_TRUE;
404}
405
406static void crStateDbgCheckNoProgramOfId(void *data)
407{
408 crError("Unexpected Program id");
409}
410
411DECLEXPORT(void) STATE_APIENTRY crStateDeleteShader(GLuint shader)
412{
413 CRGLSLShader *pShader = crStateGetShaderObj(shader);
414 if (!pShader)
415 {
416 crWarning("Unknown shader %d", shader);
417 return;
418 }
419
420 pShader->deleted = GL_TRUE;
421
422 if (0==pShader->refCount)
423 {
424 CRContext *g = GetCurrentContext();
425 crHashtableDelete(g->glsl.shaders, shader, crStateFreeGLSLShader);
426 /* since we use programs table for key allocation key allocation, we need to
427 * free the key in the programs table.
428 * See comment in crStateCreateShader */
429 crHashtableDelete(g->glsl.programs, shader, crStateDbgCheckNoProgramOfId);
430 }
431}
432
433DECLEXPORT(void) STATE_APIENTRY crStateAttachShader(GLuint program, GLuint shader)
434{
435 CRGLSLProgram *pProgram = crStateGetProgramObj(program);
436 CRGLSLShader *pShader;
437
438 if (!pProgram)
439 {
440 crWarning("Unknown program %d", program);
441 return;
442 }
443
444 if (crHashtableSearch(pProgram->currentState.attachedShaders, shader))
445 {
446 /*shader already attached to this program*/
447 return;
448 }
449
450 pShader = crStateGetShaderObj(shader);
451
452 if (!pShader)
453 {
454 crWarning("Unknown shader %d", shader);
455 return;
456 }
457
458 pShader->refCount++;
459
460 crHashtableAdd(pProgram->currentState.attachedShaders, shader, pShader);
461}
462
463DECLEXPORT(void) STATE_APIENTRY crStateDetachShader(GLuint program, GLuint shader)
464{
465 CRGLSLProgram *pProgram = crStateGetProgramObj(program);
466 CRGLSLShader *pShader;
467
468 if (!pProgram)
469 {
470 crWarning("Unknown program %d", program);
471 return;
472 }
473
474 pShader = (CRGLSLShader *) crHashtableSearch(pProgram->currentState.attachedShaders, shader);
475 if (!pShader)
476 {
477 crWarning("Shader %d isn't attached to program %d", shader, program);
478 return;
479 }
480
481 crHashtableDelete(pProgram->currentState.attachedShaders, shader, NULL);
482
483 CRASSERT(pShader->refCount>0);
484 pShader->refCount--;
485
486 if (0==pShader->refCount)
487 {
488 CRContext *g = GetCurrentContext();
489 crHashtableDelete(g->glsl.shaders, shader, crStateFreeGLSLShader);
490 }
491}
492
493DECLEXPORT(void) STATE_APIENTRY crStateUseProgram(GLuint program)
494{
495 CRContext *g = GetCurrentContext();
496
497 if (program>0)
498 {
499 CRGLSLProgram *pProgram = crStateGetProgramObj(program);
500
501 if (!pProgram)
502 {
503 crWarning("Unknown program %d", program);
504 return;
505 }
506
507 g->glsl.activeProgram = pProgram;
508 }
509 else
510 {
511 g->glsl.activeProgram = NULL;
512 }
513}
514
515DECLEXPORT(void) STATE_APIENTRY crStateDeleteProgram(GLuint program)
516{
517 CRContext *g = GetCurrentContext();
518 CRGLSLProgram *pProgram = crStateGetProgramObj(program);
519
520 if (!pProgram)
521 {
522 crWarning("Unknown program %d", program);
523 return;
524 }
525
526 if (g->glsl.activeProgram == pProgram)
527 {
528 g->glsl.activeProgram = NULL;
529 }
530
531 crHashtableDelete(g->glsl.programs, program, crStateFreeGLSLProgram);
532}
533
534DECLEXPORT(void) STATE_APIENTRY crStateValidateProgram(GLuint program)
535{
536 CRGLSLProgram *pProgram = crStateGetProgramObj(program);
537
538 if (!pProgram)
539 {
540 crWarning("Unknown program %d", program);
541 return;
542 }
543
544 pProgram->validated = GL_TRUE;
545}
546
547static void crStateCopyShaderCB(unsigned long key, void *data1, void *data2)
548{
549 CRGLSLShader *pRealShader = (CRGLSLShader *) data1;
550 CRGLSLProgram *pProgram = (CRGLSLProgram *) data2;
551 CRGLSLShader *pShader;
552 GLint sLen=0;
553
554 CRASSERT(pRealShader);
555 pRealShader->refCount++;
556
557 pShader = (CRGLSLShader *) crAlloc(sizeof(*pShader));
558 if (!pShader)
559 {
560 crWarning("crStateCopyShaderCB: Out of memory!");
561 return;
562 }
563
564 crMemcpy(pShader, pRealShader, sizeof(*pShader));
565
566 diff_api.GetShaderiv(pShader->hwid, GL_SHADER_SOURCE_LENGTH, &sLen);
567 if (sLen>0)
568 {
569 pShader->source = (GLchar*) crAlloc(sLen);
570 diff_api.GetShaderSource(pShader->hwid, sLen, NULL, pShader->source);
571 }
572
573 crHashtableAdd(pProgram->activeState.attachedShaders, key, pShader);
574}
575
576DECLEXPORT(void) STATE_APIENTRY crStateLinkProgram(GLuint program)
577{
578 CRGLSLProgram *pProgram = crStateGetProgramObj(program);
579 GLuint i;
580
581 if (!pProgram)
582 {
583 crWarning("Unknown program %d", program);
584 return;
585 }
586
587 pProgram->linked = GL_TRUE;
588
589 /*Free program's active state*/
590 if (pProgram->activeState.attachedShaders)
591 {
592 crHashtableWalk(pProgram->activeState.attachedShaders, crStateFakeDecRefCountCB, NULL);
593 crFreeHashtable(pProgram->activeState.attachedShaders, crStateFreeGLSLShader);
594 pProgram->activeState.attachedShaders = NULL;
595 }
596 for (i=0; i<pProgram->activeState.cAttribs; ++i)
597 {
598 crFree(pProgram->activeState.pAttribs[i].name);
599 }
600 if (pProgram->activeState.pAttribs) crFree(pProgram->activeState.pAttribs);
601
602 /*copy current state to active state*/
603 crMemcpy(&pProgram->activeState, &pProgram->currentState, sizeof(CRGLSLProgramState));
604
605 pProgram->activeState.attachedShaders = crAllocHashtable();
606 if (!pProgram->activeState.attachedShaders)
607 {
608 crWarning("crStateLinkProgram: Out of memory!");
609 return;
610 }
611 crHashtableWalk(pProgram->currentState.attachedShaders, crStateCopyShaderCB, pProgram);
612
613 /*that's not a bug, note the memcpy above*/
614 if (pProgram->activeState.pAttribs)
615 {
616 pProgram->activeState.pAttribs = (CRGLSLAttrib *) crAlloc(pProgram->activeState.cAttribs * sizeof(CRGLSLAttrib));
617 }
618
619 for (i=0; i<pProgram->activeState.cAttribs; ++i)
620 {
621 crMemcpy(&pProgram->activeState.pAttribs[i], &pProgram->currentState.pAttribs[i], sizeof(CRGLSLAttrib));
622 pProgram->activeState.pAttribs[i].name = crStrdup(pProgram->currentState.pAttribs[i].name);
623 }
624
625#ifdef IN_GUEST
626 crStateFreeProgramAttribsLocationCache(pProgram);
627#endif
628
629 crStateFreeProgramUniforms(pProgram);
630}
631
632DECLEXPORT(void) STATE_APIENTRY crStateBindAttribLocation(GLuint program, GLuint index, const char * name)
633{
634 CRGLSLProgram *pProgram = crStateGetProgramObj(program);
635 GLuint i;
636 CRGLSLAttrib *pAttribs;
637
638 if (!pProgram)
639 {
640 crWarning("Unknown program %d", program);
641 return;
642 }
643
644 if (index>=CR_MAX_VERTEX_ATTRIBS)
645 {
646 crWarning("crStateBindAttribLocation: Index too big %d", index);
647 return;
648 }
649
650 for (i=0; i<pProgram->currentState.cAttribs; ++i)
651 {
652 if (!crStrcmp(pProgram->currentState.pAttribs[i].name, name))
653 {
654 pProgram->currentState.pAttribs[i].index = index;
655 return;
656 }
657 }
658
659 pAttribs = (CRGLSLAttrib*) crAlloc((pProgram->currentState.cAttribs+1)*sizeof(CRGLSLAttrib));
660 if (!pAttribs)
661 {
662 crWarning("crStateBindAttribLocation: Out of memory!");
663 return;
664 }
665
666 if (pProgram->currentState.cAttribs)
667 {
668 crMemcpy(&pAttribs[0], &pProgram->currentState.pAttribs[0], pProgram->currentState.cAttribs*sizeof(CRGLSLAttrib));
669 }
670 pAttribs[pProgram->currentState.cAttribs].index = index;
671 pAttribs[pProgram->currentState.cAttribs].name = crStrdup(name);
672
673 pProgram->currentState.cAttribs++;
674 if (pProgram->currentState.pAttribs) crFree(pProgram->currentState.pAttribs);
675 pProgram->currentState.pAttribs = pAttribs;
676}
677
678DECLEXPORT(GLint) STATE_APIENTRY crStateGetUniformSize(GLenum type)
679{
680 GLint size;
681
682 switch (type)
683 {
684 case GL_FLOAT:
685 size = 1;
686 break;
687 case GL_FLOAT_VEC2:
688 size = 2;
689 break;
690 case GL_FLOAT_VEC3:
691 size = 3;
692 break;
693 case GL_FLOAT_VEC4:
694 size = 4;
695 break;
696 case GL_INT:
697 size = 1;
698 break;
699 case GL_INT_VEC2:
700 size = 2;
701 break;
702 case GL_INT_VEC3:
703 size = 3;
704 break;
705 case GL_INT_VEC4:
706 size = 4;
707 break;
708 case GL_BOOL:
709 size = 1;
710 break;
711 case GL_BOOL_VEC2:
712 size = 2;
713 break;
714 case GL_BOOL_VEC3:
715 size = 3;
716 break;
717 case GL_BOOL_VEC4:
718 size = 4;
719 break;
720 case GL_FLOAT_MAT2:
721 size = 8;
722 break;
723 case GL_FLOAT_MAT3:
724 size = 12;
725 break;
726 case GL_FLOAT_MAT4:
727 size = 16;
728 break;
729 case GL_SAMPLER_1D:
730 case GL_SAMPLER_2D:
731 case GL_SAMPLER_3D:
732 case GL_SAMPLER_CUBE:
733 case GL_SAMPLER_1D_SHADOW:
734 case GL_SAMPLER_2D_SHADOW:
735 case GL_SAMPLER_2D_RECT_ARB:
736 case GL_SAMPLER_2D_RECT_SHADOW_ARB:
737 size = 1;
738 break;
739#ifdef CR_OPENGL_VERSION_2_1
740 case GL_FLOAT_MAT2x3:
741 size = 8;
742 break;
743 case GL_FLOAT_MAT2x4:
744 size = 8;
745 break;
746 case GL_FLOAT_MAT3x2:
747 size = 12;
748 break;
749 case GL_FLOAT_MAT3x4:
750 size = 12;
751 break;
752 case GL_FLOAT_MAT4x2:
753 size = 16;
754 break;
755 case GL_FLOAT_MAT4x3:
756 size = 16;
757 break;
758#endif
759 default:
760 crWarning("crStateGetUniformSize: unknown uniform type 0x%x", (GLint)type);
761 size = 16;
762 break;
763 }
764
765 return size;
766}
767
768DECLEXPORT(GLboolean) STATE_APIENTRY crStateIsIntUniform(GLenum type)
769{
770 if (GL_INT==type
771 || GL_INT_VEC2==type
772 || GL_INT_VEC3==type
773 || GL_INT_VEC4==type
774 || GL_BOOL==type
775 || GL_BOOL_VEC2==type
776 || GL_BOOL_VEC3==type
777 || GL_BOOL_VEC4==type
778 || GL_SAMPLER_1D==type
779 || GL_SAMPLER_2D==type
780 || GL_SAMPLER_3D==type
781 || GL_SAMPLER_CUBE==type
782 || GL_SAMPLER_1D_SHADOW==type
783 || GL_SAMPLER_2D_SHADOW==type
784 || GL_SAMPLER_2D_RECT_ARB==type
785 || GL_SAMPLER_2D_RECT_SHADOW_ARB==type)
786 {
787 return GL_TRUE;
788 }
789 else return GL_FALSE;
790}
791
792DECLEXPORT(GLboolean) STATE_APIENTRY crStateIsProgramUniformsCached(GLuint program)
793{
794 CRGLSLProgram *pProgram = crStateGetProgramObj(program);
795
796 if (!pProgram)
797 {
798 WARN(("Unknown program %d", program));
799 return GL_FALSE;
800 }
801
802#ifdef IN_GUEST
803 return pProgram->bUniformsSynced;
804#else
805 WARN(("crStateIsProgramUniformsCached called on host side!!"));
806 return GL_FALSE;
807#endif
808}
809
810DECLEXPORT(GLboolean) STATE_APIENTRY crStateIsProgramAttribsCached(GLuint program)
811{
812 CRGLSLProgram *pProgram = crStateGetProgramObj(program);
813
814 if (!pProgram)
815 {
816 WARN(("Unknown program %d", program));
817 return GL_FALSE;
818 }
819
820#ifdef IN_GUEST
821 return pProgram->bAttribsSynced;
822#else
823 WARN(("crStateIsProgramAttribsCached called on host side!!"));
824 return GL_FALSE;
825#endif
826}
827
828/*@todo: one of those functions should ignore uniforms starting with "gl"*/
829
830#ifdef IN_GUEST
831DECLEXPORT(void) STATE_APIENTRY
832crStateGLSLProgramCacheUniforms(GLuint program, GLsizei cbData, GLvoid *pData)
833{
834 CRGLSLProgram *pProgram = crStateGetProgramObj(program);
835 char *pCurrent = pData;
836 GLsizei cbRead, cbName;
837 GLuint i;
838
839 if (!pProgram)
840 {
841 crWarning("Unknown program %d", program);
842 return;
843 }
844
845 if (pProgram->bUniformsSynced)
846 {
847 crWarning("crStateGLSLProgramCacheUniforms: this shouldn't happen!");
848 crStateFreeProgramUniforms(pProgram);
849 }
850
851 if (cbData<sizeof(GLsizei))
852 {
853 crWarning("crStateGLSLProgramCacheUniforms: data too short");
854 return;
855 }
856
857 pProgram->cUniforms = ((GLsizei*)pCurrent)[0];
858 pCurrent += sizeof(GLsizei);
859 cbRead = sizeof(GLsizei);
860
861 //crDebug("crStateGLSLProgramCacheUniforms: %i active uniforms", pProgram->cUniforms);
862
863 if (pProgram->cUniforms)
864 {
865 pProgram->pUniforms = crAlloc(pProgram->cUniforms*sizeof(CRGLSLUniform));
866 if (!pProgram->pUniforms)
867 {
868 crWarning("crStateGLSLProgramCacheUniforms: no memory");
869 pProgram->cUniforms = 0;
870 return;
871 }
872 }
873
874 for (i=0; i<pProgram->cUniforms; ++i)
875 {
876 cbRead += sizeof(GLuint)+sizeof(GLsizei);
877 if (cbRead>cbData)
878 {
879 crWarning("crStateGLSLProgramCacheUniforms: out of data reading uniform %i", i);
880 return;
881 }
882 pProgram->pUniforms[i].data = NULL;
883 pProgram->pUniforms[i].location = ((GLint*)pCurrent)[0];
884 pCurrent += sizeof(GLint);
885 cbName = ((GLsizei*)pCurrent)[0];
886 pCurrent += sizeof(GLsizei);
887
888 cbRead += cbName;
889 if (cbRead>cbData)
890 {
891 crWarning("crStateGLSLProgramCacheUniforms: out of data reading uniform's name %i", i);
892 return;
893 }
894
895 pProgram->pUniforms[i].name = crStrndup(pCurrent, cbName);
896 pCurrent += cbName;
897
898 //crDebug("crStateGLSLProgramCacheUniforms: uniform[%i]=%d, %s", i, pProgram->pUniforms[i].location, pProgram->pUniforms[i].name);
899 }
900
901 pProgram->bUniformsSynced = GL_TRUE;
902
903 CRASSERT((pCurrent-((char*)pData))==cbRead);
904 CRASSERT(cbRead==cbData);
905}
906
907DECLEXPORT(void) STATE_APIENTRY
908crStateGLSLProgramCacheAttribs(GLuint program, GLsizei cbData, GLvoid *pData)
909{
910 CRGLSLProgram *pProgram = crStateGetProgramObj(program);
911 char *pCurrent = pData;
912 GLsizei cbRead, cbName;
913 GLuint i;
914
915 if (!pProgram)
916 {
917 WARN(("Unknown program %d", program));
918 return;
919 }
920
921 if (pProgram->bAttribsSynced)
922 {
923 WARN(("crStateGLSLProgramCacheAttribs: this shouldn't happen!"));
924 crStateFreeProgramAttribsLocationCache(pProgram);
925 }
926
927 if (cbData<sizeof(GLsizei))
928 {
929 WARN(("crStateGLSLProgramCacheAttribs: data too short"));
930 return;
931 }
932
933 pProgram->cAttribs = ((GLsizei*)pCurrent)[0];
934 pCurrent += sizeof(GLsizei);
935 cbRead = sizeof(GLsizei);
936
937 crDebug("crStateGLSLProgramCacheAttribs: %i active attribs", pProgram->cAttribs);
938
939 if (pProgram->cAttribs)
940 {
941 pProgram->pAttribs = crAlloc(pProgram->cAttribs*sizeof(CRGLSLAttrib));
942 if (!pProgram->pAttribs)
943 {
944 WARN(("crStateGLSLProgramCacheAttribs: no memory"));
945 pProgram->cAttribs = 0;
946 return;
947 }
948 }
949
950 for (i=0; i<pProgram->cAttribs; ++i)
951 {
952 cbRead += sizeof(GLuint)+sizeof(GLsizei);
953 if (cbRead>cbData)
954 {
955 crWarning("crStateGLSLProgramCacheAttribs: out of data reading attrib %i", i);
956 return;
957 }
958 pProgram->pAttribs[i].index = ((GLint*)pCurrent)[0];
959 pCurrent += sizeof(GLint);
960 cbName = ((GLsizei*)pCurrent)[0];
961 pCurrent += sizeof(GLsizei);
962
963 cbRead += cbName;
964 if (cbRead>cbData)
965 {
966 crWarning("crStateGLSLProgramCacheAttribs: out of data reading attrib's name %i", i);
967 return;
968 }
969
970 pProgram->pAttribs[i].name = crStrndup(pCurrent, cbName);
971 pCurrent += cbName;
972
973 crDebug("crStateGLSLProgramCacheAttribs: attribs[%i]=%d, %s", i, pProgram->pAttribs[i].index, pProgram->pAttribs[i].name);
974 }
975
976 pProgram->bAttribsSynced = GL_TRUE;
977
978 CRASSERT((pCurrent-((char*)pData))==cbRead);
979 CRASSERT(cbRead==cbData);
980}
981#else /* IN_GUEST */
982static GLboolean crStateGLSLProgramCacheOneUniform(GLuint location, GLsizei cbName, GLchar *pName,
983 char **pCurrent, GLsizei *pcbWritten, GLsizei maxcbData)
984{
985 *pcbWritten += sizeof(GLint)+sizeof(GLsizei)+cbName;
986 if (*pcbWritten>maxcbData)
987 {
988 crWarning("crStateGLSLProgramCacheUniforms: buffer too small");
989 crFree(pName);
990 return GL_FALSE;
991 }
992
993 //crDebug("crStateGLSLProgramCacheUniforms: uniform[%i]=%s.", location, pName);
994
995 ((GLint*)*pCurrent)[0] = location;
996 *pCurrent += sizeof(GLint);
997 ((GLsizei*)*pCurrent)[0] = cbName;
998 *pCurrent += sizeof(GLsizei);
999 crMemcpy(*pCurrent, pName, cbName);
1000 *pCurrent += cbName;
1001
1002 return GL_TRUE;
1003}
1004
1005DECLEXPORT(void) STATE_APIENTRY
1006crStateGLSLProgramCacheUniforms(GLuint program, GLsizei maxcbData, GLsizei *cbData, GLvoid *pData)
1007{
1008 CRGLSLProgram *pProgram = crStateGetProgramObj(program);
1009 GLint maxUniformLen = 0, activeUniforms=0, fakeUniformsCount, i, j;
1010 char *pCurrent = pData;
1011 GLsizei cbWritten;
1012
1013 if (!pProgram)
1014 {
1015 crWarning("Unknown program %d", program);
1016 return;
1017 }
1018
1019 /*
1020 * OpenGL spec says about GL_ACTIVE_UNIFORM_MAX_LENGTH:
1021 * "If no active uniform variable exist, 0 is returned."
1022 */
1023 diff_api.GetProgramiv(pProgram->hwid, GL_ACTIVE_UNIFORM_MAX_LENGTH, &maxUniformLen);
1024 if (maxUniformLen > 0)
1025 diff_api.GetProgramiv(pProgram->hwid, GL_ACTIVE_UNIFORMS, &activeUniforms);
1026
1027 *cbData = 0;
1028
1029 cbWritten = sizeof(GLsizei);
1030 if (cbWritten>maxcbData)
1031 {
1032 crWarning("crStateGLSLProgramCacheUniforms: buffer too small");
1033 return;
1034 }
1035 ((GLsizei*)pCurrent)[0] = activeUniforms;
1036 fakeUniformsCount = activeUniforms;
1037 pCurrent += sizeof(GLsizei);
1038
1039 crDebug("crStateGLSLProgramCacheUniforms: %i active uniforms", activeUniforms);
1040
1041 if (activeUniforms>0)
1042 {
1043 /*+8 to make sure our array uniforms with higher indices and [] will fit in as well*/
1044 GLchar *name = (GLchar *) crAlloc(maxUniformLen+8);
1045 GLenum type;
1046 GLint size;
1047 GLsizei cbName;
1048 GLint location;
1049
1050 if (!name)
1051 {
1052 crWarning("crStateGLSLProgramCacheUniforms: no memory");
1053 return;
1054 }
1055
1056 for (i=0; i<activeUniforms; ++i)
1057 {
1058 diff_api.GetActiveUniform(pProgram->hwid, i, maxUniformLen, &cbName, &size, &type, name);
1059 location = diff_api.GetUniformLocation(pProgram->hwid, name);
1060
1061 if (!crStateGLSLProgramCacheOneUniform(location, cbName, name, &pCurrent, &cbWritten, maxcbData))
1062 return;
1063
1064 /* Only one active uniform variable will be reported for a uniform array by glGetActiveUniform,
1065 * so we insert fake elements for other array elements.
1066 */
1067 if (size!=1)
1068 {
1069 char *pIndexStr = crStrchr(name, '[');
1070 GLint firstIndex=1;
1071 fakeUniformsCount += size;
1072
1073 crDebug("crStateGLSLProgramCacheUniforms: expanding array uniform, size=%i", size);
1074
1075 /*For array uniforms it's valid to query location of 1st element as both uniform and uniform[0].
1076 *The name returned by glGetActiveUniform is driver dependent,
1077 *atleast it's with [0] on win/ati and without [0] on linux/nvidia.
1078 */
1079 if (!pIndexStr)
1080 {
1081 pIndexStr = name+cbName;
1082 firstIndex=0;
1083 }
1084 else
1085 {
1086 cbName = pIndexStr-name;
1087 if (!crStateGLSLProgramCacheOneUniform(location, cbName, name, &pCurrent, &cbWritten, maxcbData))
1088 return;
1089 }
1090
1091 for (j=firstIndex; j<size; ++j)
1092 {
1093 sprintf(pIndexStr, "[%i]", j);
1094 cbName = crStrlen(name);
1095
1096 location = diff_api.GetUniformLocation(pProgram->hwid, name);
1097
1098 if (!crStateGLSLProgramCacheOneUniform(location, cbName, name, &pCurrent, &cbWritten, maxcbData))
1099 return;
1100 }
1101 }
1102 }
1103
1104 crFree(name);
1105 }
1106
1107 if (fakeUniformsCount!=activeUniforms)
1108 {
1109 ((GLsizei*)pData)[0] = fakeUniformsCount;
1110 crDebug("FakeCount %i", fakeUniformsCount);
1111 }
1112
1113 *cbData = cbWritten;
1114
1115 CRASSERT((pCurrent-((char*)pData))==cbWritten);
1116}
1117
1118static GLboolean crStateGLSLProgramCacheOneAttrib(GLuint location, GLsizei cbName, GLchar *pName,
1119 char **pCurrent, GLsizei *pcbWritten, GLsizei maxcbData)
1120{
1121 *pcbWritten += sizeof(GLint)+sizeof(GLsizei)+cbName;
1122 if (*pcbWritten>maxcbData)
1123 {
1124 WARN(("crStateGLSLProgramCacheOneAttrib: buffer too small"));
1125 crFree(pName);
1126 return GL_FALSE;
1127 }
1128
1129 crDebug("crStateGLSLProgramCacheOneAttrib: attrib[%i]=%s.", location, pName);
1130
1131 ((GLint*)*pCurrent)[0] = location;
1132 *pCurrent += sizeof(GLint);
1133 ((GLsizei*)*pCurrent)[0] = cbName;
1134 *pCurrent += sizeof(GLsizei);
1135 crMemcpy(*pCurrent, pName, cbName);
1136 *pCurrent += cbName;
1137
1138 return GL_TRUE;
1139}
1140
1141DECLEXPORT(void) STATE_APIENTRY
1142crStateGLSLProgramCacheAttribs(GLuint program, GLsizei maxcbData, GLsizei *cbData, GLvoid *pData)
1143{
1144 CRGLSLProgram *pProgram = crStateGetProgramObj(program);
1145 GLint maxAttribLen, activeAttribs=0, fakeAttribsCount, i, j;
1146 char *pCurrent = pData;
1147 GLsizei cbWritten;
1148
1149 if (!pProgram)
1150 {
1151 crWarning("Unknown program %d", program);
1152 return;
1153 }
1154
1155 diff_api.GetProgramiv(pProgram->hwid, GL_ACTIVE_ATTRIBUTE_MAX_LENGTH, &maxAttribLen);
1156 diff_api.GetProgramiv(pProgram->hwid, GL_ACTIVE_ATTRIBUTES, &activeAttribs);
1157
1158 *cbData = 0;
1159
1160 cbWritten = sizeof(GLsizei);
1161 if (cbWritten>maxcbData)
1162 {
1163 crWarning("crStateGLSLProgramCacheAttribs: buffer too small");
1164 return;
1165 }
1166 ((GLsizei*)pCurrent)[0] = activeAttribs;
1167 fakeAttribsCount = activeAttribs;
1168 pCurrent += sizeof(GLsizei);
1169
1170 crDebug("crStateGLSLProgramCacheAttribs: %i active attribs", activeAttribs);
1171
1172 if (activeAttribs>0)
1173 {
1174 /*+8 to make sure our array attribs with higher indices and [] will fit in as well*/
1175 GLchar *name = (GLchar *) crAlloc(maxAttribLen+8);
1176 GLenum type;
1177 GLint size;
1178 GLsizei cbName;
1179 GLint location;
1180
1181 if (!name)
1182 {
1183 crWarning("crStateGLSLProgramCacheAttribs: no memory");
1184 return;
1185 }
1186
1187 for (i=0; i<activeAttribs; ++i)
1188 {
1189 diff_api.GetActiveAttrib(pProgram->hwid, i, maxAttribLen, &cbName, &size, &type, name);
1190 location = diff_api.GetAttribLocation(pProgram->hwid, name);
1191
1192 if (!crStateGLSLProgramCacheOneAttrib(location, cbName, name, &pCurrent, &cbWritten, maxcbData))
1193 return;
1194
1195 /* Only one active attrib variable will be reported for a attrib array by glGetActiveAttrib,
1196 * so we insert fake elements for other array elements.
1197 */
1198 if (size!=1)
1199 {
1200 char *pIndexStr = crStrchr(name, '[');
1201 GLint firstIndex=1;
1202 fakeAttribsCount += size;
1203
1204 crDebug("crStateGLSLProgramCacheAttribs: expanding array attrib, size=%i", size);
1205
1206 /*For array attribs it's valid to query location of 1st element as both attrib and attrib[0].
1207 *The name returned by glGetActiveAttrib is driver dependent,
1208 *atleast it's with [0] on win/ati and without [0] on linux/nvidia.
1209 */
1210 if (!pIndexStr)
1211 {
1212 pIndexStr = name+cbName;
1213 firstIndex=0;
1214 }
1215 else
1216 {
1217 cbName = pIndexStr-name;
1218 if (!crStateGLSLProgramCacheOneAttrib(location, cbName, name, &pCurrent, &cbWritten, maxcbData))
1219 return;
1220 }
1221
1222 for (j=firstIndex; j<size; ++j)
1223 {
1224 sprintf(pIndexStr, "[%i]", j);
1225 cbName = crStrlen(name);
1226
1227 location = diff_api.GetAttribLocation(pProgram->hwid, name);
1228
1229 if (!crStateGLSLProgramCacheOneAttrib(location, cbName, name, &pCurrent, &cbWritten, maxcbData))
1230 return;
1231 }
1232 }
1233 }
1234
1235 crFree(name);
1236 }
1237
1238 if (fakeAttribsCount!=activeAttribs)
1239 {
1240 ((GLsizei*)pData)[0] = fakeAttribsCount;
1241 crDebug("FakeCount %i", fakeAttribsCount);
1242 }
1243
1244 *cbData = cbWritten;
1245
1246 CRASSERT((pCurrent-((char*)pData))==cbWritten);
1247}
1248#endif
1249
1250DECLEXPORT(GLint) STATE_APIENTRY crStateGetUniformLocation(GLuint program, const char * name)
1251{
1252#ifdef IN_GUEST
1253 CRGLSLProgram *pProgram = crStateGetProgramObj(program);
1254 GLint result=-1;
1255 GLuint i;
1256
1257 if (!pProgram)
1258 {
1259 crWarning("Unknown program %d", program);
1260 return -1;
1261 }
1262
1263 if (!pProgram->bUniformsSynced)
1264 {
1265 crWarning("crStateGetUniformLocation called for uncached uniforms");
1266 return -1;
1267 }
1268
1269 for (i=0; i<pProgram->cUniforms; ++i)
1270 {
1271 if (!crStrcmp(name, pProgram->pUniforms[i].name))
1272 {
1273 result = pProgram->pUniforms[i].location;
1274 break;
1275 }
1276 }
1277
1278 return result;
1279#else
1280 crWarning("crStateGetUniformLocation called on host side!!");
1281 return -1;
1282#endif
1283}
1284
1285DECLEXPORT(GLint) STATE_APIENTRY crStateGetAttribLocation(GLuint program, const char * name)
1286{
1287#ifdef IN_GUEST
1288 CRGLSLProgram *pProgram = crStateGetProgramObj(program);
1289 GLint result=-1;
1290 GLuint i;
1291
1292 if (!pProgram)
1293 {
1294 WARN(("Unknown program %d", program));
1295 return -1;
1296 }
1297
1298 if (!pProgram->bAttribsSynced)
1299 {
1300 WARN(("crStateGetAttribLocation called for uncached attribs"));
1301 return -1;
1302 }
1303
1304 for (i=0; i<pProgram->cAttribs; ++i)
1305 {
1306 if (!crStrcmp(name, pProgram->pAttribs[i].name))
1307 {
1308 result = pProgram->pAttribs[i].index;
1309 break;
1310 }
1311 }
1312
1313 return result;
1314#else
1315 crWarning("crStateGetAttribLocation called on host side!!");
1316 return -1;
1317#endif
1318}
1319
1320static void crStateGLSLCreateShadersCB(unsigned long key, void *data1, void *data2)
1321{
1322 CRGLSLShader *pShader = (CRGLSLShader*) data1;
1323 CRContext *ctx = (CRContext *) data2;
1324
1325 pShader->hwid = diff_api.CreateShader(pShader->type);
1326}
1327
1328static void crStateFixAttachedShaderHWIDsCB(unsigned long key, void *data1, void *data2)
1329{
1330 CRGLSLShader *pShader = (CRGLSLShader*) data1;
1331 CRGLSLShader *pRealShader;
1332 CRContext *pCtx = (CRContext *) data2;
1333
1334 pRealShader = (CRGLSLShader *) crHashtableSearch(pCtx->glsl.shaders, key);
1335 CRASSERT(pRealShader);
1336
1337 pShader->hwid = pRealShader->hwid;
1338}
1339
1340static void crStateGLSLSyncShadersCB(unsigned long key, void *data1, void *data2)
1341{
1342 CRGLSLShader *pShader = (CRGLSLShader*) data1;
1343 (void) key;
1344 (void) data2;
1345
1346 if (pShader->source)
1347 {
1348 diff_api.ShaderSource(pShader->hwid, 1, (const char**)&pShader->source, NULL);
1349 if (pShader->compiled)
1350 diff_api.CompileShader(pShader->hwid);
1351 crFree(pShader->source);
1352 pShader->source = NULL;
1353 }
1354
1355 if (pShader->deleted)
1356 diff_api.DeleteShader(pShader->hwid);
1357}
1358
1359static void crStateAttachShaderCB(unsigned long key, void *data1, void *data2)
1360{
1361 CRGLSLShader *pShader = (CRGLSLShader*) data1;
1362 CRGLSLProgram *pProgram = (CRGLSLProgram *) data2;
1363 (void) key;
1364
1365 if (pShader->source)
1366 {
1367 diff_api.ShaderSource(pShader->hwid, 1, (const char**)&pShader->source, NULL);
1368 if (pShader->compiled)
1369 diff_api.CompileShader(pShader->hwid);
1370 }
1371
1372 diff_api.AttachShader(pProgram->hwid, pShader->hwid);
1373}
1374
1375static void crStateDetachShaderCB(unsigned long key, void *data1, void *data2)
1376{
1377 CRGLSLShader *pShader = (CRGLSLShader*) data1;
1378 CRGLSLProgram *pProgram = (CRGLSLProgram *) data2;
1379 (void) key;
1380
1381 diff_api.DetachShader(pProgram->hwid, pShader->hwid);
1382}
1383
1384static void crStateGLSLCreateProgramCB(unsigned long key, void *data1, void *data2)
1385{
1386 CRGLSLProgram *pProgram = (CRGLSLProgram*) data1;
1387 CRContext *ctx = (CRContext *) data2;
1388 GLuint i;
1389
1390 pProgram->hwid = diff_api.CreateProgram();
1391
1392 if (pProgram->linked)
1393 {
1394 CRASSERT(pProgram->activeState.attachedShaders);
1395
1396 crHashtableWalk(pProgram->activeState.attachedShaders, crStateFixAttachedShaderHWIDsCB, ctx);
1397 crHashtableWalk(pProgram->activeState.attachedShaders, crStateAttachShaderCB, pProgram);
1398
1399 for (i=0; i<pProgram->activeState.cAttribs; ++i)
1400 {
1401 diff_api.BindAttribLocation(pProgram->hwid, pProgram->activeState.pAttribs[i].index, pProgram->activeState.pAttribs[i].name);
1402 }
1403
1404 if (pProgram->validated)
1405 diff_api.ValidateProgram(pProgram->hwid);
1406
1407 diff_api.LinkProgram(pProgram->hwid);
1408 }
1409
1410 diff_api.UseProgram(pProgram->hwid);
1411
1412 for (i=0; i<pProgram->cUniforms; ++i)
1413 {
1414 GLint location;
1415 GLfloat *pFdata = (GLfloat*)pProgram->pUniforms[i].data;
1416 GLint *pIdata = (GLint*)pProgram->pUniforms[i].data;
1417
1418 location = diff_api.GetUniformLocation(pProgram->hwid, pProgram->pUniforms[i].name);
1419 switch (pProgram->pUniforms[i].type)
1420 {
1421 case GL_FLOAT:
1422 diff_api.Uniform1fv(location, 1, pFdata);
1423 break;
1424 case GL_FLOAT_VEC2:
1425 diff_api.Uniform2fv(location, 1, pFdata);
1426 break;
1427 case GL_FLOAT_VEC3:
1428 diff_api.Uniform3fv(location, 1, pFdata);
1429 break;
1430 case GL_FLOAT_VEC4:
1431 diff_api.Uniform4fv(location, 1, pFdata);
1432 break;
1433 case GL_INT:
1434 case GL_BOOL:
1435 diff_api.Uniform1iv(location, 1, pIdata);
1436 break;
1437 case GL_INT_VEC2:
1438 case GL_BOOL_VEC2:
1439 diff_api.Uniform2iv(location, 1, pIdata);
1440 break;
1441 case GL_INT_VEC3:
1442 case GL_BOOL_VEC3:
1443 diff_api.Uniform3iv(location, 1, pIdata);
1444 break;
1445 case GL_INT_VEC4:
1446 case GL_BOOL_VEC4:
1447 diff_api.Uniform4iv(location, 1, pIdata);
1448 break;
1449 case GL_FLOAT_MAT2:
1450 diff_api.UniformMatrix2fv(location, 1, GL_FALSE, pFdata);
1451 break;
1452 case GL_FLOAT_MAT3:
1453 diff_api.UniformMatrix3fv(location, 1, GL_FALSE, pFdata);
1454 break;
1455 case GL_FLOAT_MAT4:
1456 diff_api.UniformMatrix4fv(location, 1, GL_FALSE, pFdata);
1457 break;
1458 case GL_SAMPLER_1D:
1459 case GL_SAMPLER_2D:
1460 case GL_SAMPLER_3D:
1461 case GL_SAMPLER_CUBE:
1462 case GL_SAMPLER_1D_SHADOW:
1463 case GL_SAMPLER_2D_SHADOW:
1464 case GL_SAMPLER_2D_RECT_ARB:
1465 case GL_SAMPLER_2D_RECT_SHADOW_ARB:
1466 diff_api.Uniform1iv(location, 1, pIdata);
1467 break;
1468#ifdef CR_OPENGL_VERSION_2_1
1469 case GL_FLOAT_MAT2x3:
1470 diff_api.UniformMatrix2x3fv(location, 1, GL_FALSE, pFdata);
1471 break;
1472 case GL_FLOAT_MAT2x4:
1473 diff_api.UniformMatrix2x4fv(location, 1, GL_FALSE, pFdata);
1474 break;
1475 case GL_FLOAT_MAT3x2:
1476 diff_api.UniformMatrix3x2fv(location, 1, GL_FALSE, pFdata);
1477 break;
1478 case GL_FLOAT_MAT3x4:
1479 diff_api.UniformMatrix3x4fv(location, 1, GL_FALSE, pFdata);
1480 break;
1481 case GL_FLOAT_MAT4x2:
1482 diff_api.UniformMatrix4x2fv(location, 1, GL_FALSE, pFdata);
1483 break;
1484 case GL_FLOAT_MAT4x3:
1485 diff_api.UniformMatrix4x3fv(location, 1, GL_FALSE, pFdata);
1486 break;
1487#endif
1488 default:
1489 crWarning("crStateGLSLCreateProgramCB: unknown uniform type 0x%x", (GLint)pProgram->pUniforms[i].type);
1490 break;
1491 }
1492 crFree(pProgram->pUniforms[i].data);
1493 crFree(pProgram->pUniforms[i].name);
1494 } /*for (i=0; i<pProgram->cUniforms; ++i)*/
1495 if (pProgram->pUniforms) crFree(pProgram->pUniforms);
1496 pProgram->pUniforms = NULL;
1497 pProgram->cUniforms = 0;
1498
1499 crHashtableWalk(pProgram->activeState.attachedShaders, crStateDetachShaderCB, pProgram);
1500 crHashtableWalk(pProgram->currentState.attachedShaders, crStateAttachShaderCB, pProgram);
1501}
1502
1503DECLEXPORT(void) STATE_APIENTRY crStateGLSLSwitch(CRContext *from, CRContext *to)
1504{
1505 GLboolean fForceUseProgramSet = GL_FALSE;
1506 if (to->glsl.bResyncNeeded)
1507 {
1508 to->glsl.bResyncNeeded = GL_FALSE;
1509
1510 crHashtableWalk(to->glsl.shaders, crStateGLSLCreateShadersCB, to);
1511
1512 crHashtableWalk(to->glsl.programs, crStateGLSLCreateProgramCB, to);
1513
1514 /* crStateGLSLCreateProgramCB changes the current program, ensure we have the proper program re-sored */
1515 fForceUseProgramSet = GL_TRUE;
1516
1517 crHashtableWalk(to->glsl.shaders, crStateGLSLSyncShadersCB, NULL);
1518 }
1519
1520 if (to->glsl.activeProgram != from->glsl.activeProgram || fForceUseProgramSet)
1521 {
1522 diff_api.UseProgram(to->glsl.activeProgram ? to->glsl.activeProgram->hwid : 0);
1523 }
1524}
Note: See TracBrowser for help on using the repository browser.

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