VirtualBox

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

Last change on this file since 47638 was 46462, checked in by vboxsync, 12 years ago

crOpenGL: fix glsl state

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 34.4 KB
Line 
1/* $Id: state_glsl.c 46462 2013-06-10 12:11:05Z 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
60static void crStateFreeProgramAttribs(CRGLSLProgram* pProgram)
61{
62 GLuint i;
63
64 for (i=0; i<pProgram->activeState.cAttribs; ++i)
65 {
66 crFree(pProgram->activeState.pAttribs[i].name);
67 }
68
69 for (i=0; i<pProgram->currentState.cAttribs; ++i)
70 {
71 crFree(pProgram->currentState.pAttribs[i].name);
72 }
73
74 if (pProgram->activeState.pAttribs)
75 crFree(pProgram->activeState.pAttribs);
76
77 if (pProgram->currentState.pAttribs)
78 crFree(pProgram->currentState.pAttribs);
79}
80
81static void crStateFreeProgramUniforms(CRGLSLProgram* pProgram)
82{
83 GLuint i;
84
85 for (i=0; i<pProgram->cUniforms; ++i)
86 {
87 if (pProgram->pUniforms[i].name) crFree(pProgram->pUniforms[i].name);
88 if (pProgram->pUniforms[i].data) crFree(pProgram->pUniforms[i].data);
89 }
90
91 if (pProgram->pUniforms) crFree(pProgram->pUniforms);
92
93 pProgram->pUniforms = NULL;
94 pProgram->cUniforms = 0;
95
96#ifdef IN_GUEST
97 pProgram->bUniformsSynced = GL_FALSE;
98#endif
99}
100
101static void crStateShaderDecRefCount(void *data)
102{
103 CRGLSLShader *pShader = (CRGLSLShader *) data;
104
105 CRASSERT(pShader->refCount>0);
106
107 pShader->refCount--;
108
109 if (0==pShader->refCount && pShader->deleted)
110 {
111 CRContext *g = GetCurrentContext();
112 crHashtableDelete(g->glsl.shaders, pShader->id, crStateFreeGLSLShader);
113 }
114}
115
116static void crStateFakeDecRefCountCB(unsigned long key, void *data1, void *data2)
117{
118 CRGLSLShader *pShader = (CRGLSLShader *) data1;
119 CRContext *ctx = (CRContext*) data2;
120 CRGLSLShader *pRealShader;
121 (void) key;
122
123 pRealShader = crStateGetShaderObj(pShader->id);
124
125 if (pRealShader)
126 {
127 crStateShaderDecRefCount(pRealShader);
128 }
129 else
130 {
131 crWarning("crStateFakeDecRefCountCB: NULL pRealShader");
132 }
133}
134
135static void crStateFreeGLSLProgram(void *data)
136{
137 CRGLSLProgram* pProgram = (CRGLSLProgram *) data;
138
139 crFreeHashtable(pProgram->currentState.attachedShaders, crStateShaderDecRefCount);
140
141 if (pProgram->activeState.attachedShaders)
142 {
143 CRContext *g = GetCurrentContext();
144 crHashtableWalk(pProgram->activeState.attachedShaders, crStateFakeDecRefCountCB, g);
145 crFreeHashtable(pProgram->activeState.attachedShaders, crStateFreeGLSLShader);
146 }
147
148 crStateFreeProgramAttribs(pProgram);
149
150 crStateFreeProgramUniforms(pProgram);
151
152 crFree(pProgram);
153}
154
155DECLEXPORT(void) STATE_APIENTRY crStateGLSLInit(CRContext *ctx)
156{
157 ctx->glsl.shaders = crAllocHashtable();
158 ctx->glsl.programs = crAllocHashtable();
159 ctx->glsl.activeProgram = NULL;
160 ctx->glsl.bResyncNeeded = GL_FALSE;
161
162 if (!ctx->glsl.shaders || !ctx->glsl.programs)
163 {
164 crWarning("crStateGLSLInit: Out of memory!");
165 return;
166 }
167}
168
169DECLEXPORT(void) STATE_APIENTRY crStateGLSLDestroy(CRContext *ctx)
170{
171 CRContext *g = GetCurrentContext();
172
173 /*@todo: hack to allow crStateFreeGLSLProgram to work correctly,
174 as the current context isn't the one being destroyed*/
175#ifdef CHROMIUM_THREADSAFE
176 CRASSERT(g != ctx);
177 VBoxTlsRefAddRef(ctx); /* <- this is a hack to avoid subsequent SetCurrentContext(g) do recursive Destroy for ctx */
178 if (g)
179 VBoxTlsRefAddRef(g); /* <- ensure the g is not destroyed by the following SetCurrentContext call */
180 SetCurrentContext(ctx);
181#else
182 __currentContext = ctx;
183#endif
184
185 crFreeHashtable(ctx->glsl.programs, crStateFreeGLSLProgram);
186 crFreeHashtable(ctx->glsl.shaders, crStateFreeGLSLShader);
187
188#ifdef CHROMIUM_THREADSAFE
189 SetCurrentContext(g);
190 if (g)
191 VBoxTlsRefRelease(g);
192 VBoxTlsRefRelease(ctx); /* <- restore back the cRefs (see above) */
193#else
194 __currentContext = g;
195#endif
196
197}
198
199DECLEXPORT(GLuint) STATE_APIENTRY crStateGetShaderHWID(GLuint id)
200{
201 CRGLSLShader *pShader = crStateGetShaderObj(id);
202#ifdef IN_GUEST
203 CRASSERT(!pShader || pShader->hwid == id);
204#endif
205 return pShader ? pShader->hwid : 0;
206}
207
208DECLEXPORT(GLuint) STATE_APIENTRY crStateGetProgramHWID(GLuint id)
209{
210 CRGLSLProgram *pProgram = crStateGetProgramObj(id);
211#ifdef IN_GUEST
212 CRASSERT(!pProgram || pProgram->hwid == id);
213#endif
214 return pProgram ? pProgram->hwid : 0;
215}
216
217static void crStateCheckShaderHWIDCB(unsigned long key, void *data1, void *data2)
218{
219 CRGLSLShader *pShader = (CRGLSLShader *) data1;
220 crCheckIDHWID_t *pParms = (crCheckIDHWID_t*) data2;
221 (void) key;
222
223 if (pShader->hwid==pParms->hwid)
224 pParms->id = pShader->id;
225}
226
227static void crStateCheckProgramHWIDCB(unsigned long key, void *data1, void *data2)
228{
229 CRGLSLProgram *pProgram = (CRGLSLProgram *) data1;
230 crCheckIDHWID_t *pParms = (crCheckIDHWID_t*) data2;
231 (void) key;
232
233 if (pProgram->hwid==pParms->hwid)
234 pParms->id = pProgram->id;
235}
236
237DECLEXPORT(GLuint) STATE_APIENTRY crStateGLSLShaderHWIDtoID(GLuint hwid)
238{
239 CRContext *g = GetCurrentContext();
240 crCheckIDHWID_t parms;
241
242 parms.id = hwid;
243 parms.hwid = hwid;
244
245 crHashtableWalk(g->glsl.shaders, crStateCheckShaderHWIDCB, &parms);
246 return parms.id;
247}
248
249DECLEXPORT(GLuint) STATE_APIENTRY crStateGLSLProgramHWIDtoID(GLuint hwid)
250{
251 CRContext *g = GetCurrentContext();
252 crCheckIDHWID_t parms;
253
254 parms.id = hwid;
255 parms.hwid = hwid;
256
257 crHashtableWalk(g->glsl.programs, crStateCheckProgramHWIDCB, &parms);
258 return parms.id;
259}
260
261DECLEXPORT(GLuint) STATE_APIENTRY crStateDeleteObjectARB( GLhandleARB obj )
262{
263 GLuint hwId = crStateGetProgramHWID(obj);
264 if (hwId)
265 {
266 crStateDeleteProgram(obj);
267 }
268 else
269 {
270 hwId = crStateGetShaderHWID(obj);
271 crStateDeleteShader(obj);
272 }
273 return hwId;
274}
275
276DECLEXPORT(GLuint) STATE_APIENTRY crStateCreateShader(GLuint hwid, GLenum type)
277{
278 CRGLSLShader *pShader;
279 CRContext *g = GetCurrentContext();
280 GLuint stateId = hwid;
281
282#ifdef IN_GUEST
283 CRASSERT(!crStateGetShaderObj(stateId));
284#else
285 /* the proogram and shader names must not intersect because DeleteObjectARB must distinguish between them
286 * see crStateDeleteObjectARB
287 * this is why use programs table for shader keys allocation */
288 stateId = crHashtableAllocKeys(g->glsl.programs, 1);
289 if (!stateId)
290 {
291 crWarning("failed to allocate program key");
292 return 0;
293 }
294
295 /* the id may not necesserily be hwid after save state restoration */
296 while ((pShader = crStateGetShaderObj(stateId)) != NULL)
297 {
298 GLuint newStateId = stateId + 7;
299 crDebug("Shader object %d already exists, generating a new one, %d", stateId, newStateId);
300 stateId = newStateId;
301 }
302#endif
303
304 pShader = (CRGLSLShader *) crAlloc(sizeof(*pShader));
305 if (!pShader)
306 {
307 crWarning("crStateCreateShader: Out of memory!");
308 return 0;
309 }
310
311 pShader->id = stateId;
312 pShader->hwid = hwid;
313 pShader->type = type;
314 pShader->source = NULL;
315 pShader->compiled = GL_FALSE;
316 pShader->deleted = GL_FALSE;
317 pShader->refCount = 0;
318
319 crHashtableAdd(g->glsl.shaders, stateId, pShader);
320
321 return stateId;
322}
323
324DECLEXPORT(GLuint) STATE_APIENTRY crStateCreateProgram(GLuint hwid)
325{
326 CRGLSLProgram *pProgram;
327 CRContext *g = GetCurrentContext();
328 GLuint stateId = hwid;
329
330#ifdef IN_GUEST
331 pProgram = crStateGetProgramObj(stateId);
332 if (pProgram)
333 {
334 crWarning("Program object %d already exists!", stateId);
335 crStateDeleteProgram(stateId);
336 CRASSERT(!crStateGetProgramObj(stateId));
337 }
338#else
339 stateId = crHashtableAllocKeys(g->glsl.programs, 1);
340 if (!stateId)
341 {
342 crWarning("failed to allocate program key");
343 return 0;
344 }
345#endif
346
347 pProgram = (CRGLSLProgram *) crAlloc(sizeof(*pProgram));
348 if (!pProgram)
349 {
350 crWarning("crStateCreateProgram: Out of memory!");
351 return 0;
352 }
353
354 pProgram->id = stateId;
355 pProgram->hwid = hwid;
356 pProgram->validated = GL_FALSE;
357 pProgram->linked = GL_FALSE;
358 pProgram->deleted = GL_FALSE;
359 pProgram->activeState.attachedShaders = NULL;
360 pProgram->currentState.attachedShaders = crAllocHashtable();
361
362 pProgram->activeState.cAttribs = 0;
363 pProgram->activeState.pAttribs = NULL;
364 pProgram->currentState.cAttribs = 0;
365 pProgram->currentState.pAttribs = NULL;
366
367 pProgram->pUniforms = NULL;
368 pProgram->cUniforms = 0;
369#ifdef IN_GUEST
370 pProgram->bUniformsSynced = GL_FALSE;
371#endif
372
373 crHashtableAdd(g->glsl.programs, stateId, pProgram);
374
375 return stateId;
376}
377
378DECLEXPORT(void) STATE_APIENTRY crStateCompileShader(GLuint shader)
379{
380 CRGLSLShader *pShader = crStateGetShaderObj(shader);
381 if (!pShader)
382 {
383 crWarning("Unknown shader %d", shader);
384 return;
385 }
386
387 pShader->compiled = GL_TRUE;
388}
389
390static void crStateDbgCheckNoProgramOfId(void *data)
391{
392 crError("Unexpected Program id");
393}
394
395DECLEXPORT(void) STATE_APIENTRY crStateDeleteShader(GLuint shader)
396{
397 CRGLSLShader *pShader = crStateGetShaderObj(shader);
398 if (!pShader)
399 {
400 crWarning("Unknown shader %d", shader);
401 return;
402 }
403
404 pShader->deleted = GL_TRUE;
405
406 if (0==pShader->refCount)
407 {
408 CRContext *g = GetCurrentContext();
409 crHashtableDelete(g->glsl.shaders, shader, crStateFreeGLSLShader);
410 /* since we use programs table for key allocation key allocation, we need to
411 * free the key in the programs table.
412 * See comment in crStateCreateShader */
413 crHashtableDelete(g->glsl.programs, shader, crStateDbgCheckNoProgramOfId);
414 }
415}
416
417DECLEXPORT(void) STATE_APIENTRY crStateAttachShader(GLuint program, GLuint shader)
418{
419 CRGLSLProgram *pProgram = crStateGetProgramObj(program);
420 CRGLSLShader *pShader;
421
422 if (!pProgram)
423 {
424 crWarning("Unknown program %d", program);
425 return;
426 }
427
428 if (crHashtableSearch(pProgram->currentState.attachedShaders, shader))
429 {
430 /*shader already attached to this program*/
431 return;
432 }
433
434 pShader = crStateGetShaderObj(shader);
435
436 if (!pShader)
437 {
438 crWarning("Unknown shader %d", shader);
439 return;
440 }
441
442 pShader->refCount++;
443
444 crHashtableAdd(pProgram->currentState.attachedShaders, shader, pShader);
445}
446
447DECLEXPORT(void) STATE_APIENTRY crStateDetachShader(GLuint program, GLuint shader)
448{
449 CRGLSLProgram *pProgram = crStateGetProgramObj(program);
450 CRGLSLShader *pShader;
451
452 if (!pProgram)
453 {
454 crWarning("Unknown program %d", program);
455 return;
456 }
457
458 pShader = (CRGLSLShader *) crHashtableSearch(pProgram->currentState.attachedShaders, shader);
459 if (!pShader)
460 {
461 crWarning("Shader %d isn't attached to program %d", shader, program);
462 return;
463 }
464
465 crHashtableDelete(pProgram->currentState.attachedShaders, shader, NULL);
466
467 CRASSERT(pShader->refCount>0);
468 pShader->refCount--;
469
470 if (0==pShader->refCount)
471 {
472 CRContext *g = GetCurrentContext();
473 crHashtableDelete(g->glsl.shaders, shader, crStateFreeGLSLShader);
474 }
475}
476
477DECLEXPORT(void) STATE_APIENTRY crStateUseProgram(GLuint program)
478{
479 CRContext *g = GetCurrentContext();
480
481 if (program>0)
482 {
483 CRGLSLProgram *pProgram = crStateGetProgramObj(program);
484
485 if (!pProgram)
486 {
487 crWarning("Unknown program %d", program);
488 return;
489 }
490
491 g->glsl.activeProgram = pProgram;
492 }
493 else
494 {
495 g->glsl.activeProgram = NULL;
496 }
497}
498
499DECLEXPORT(void) STATE_APIENTRY crStateDeleteProgram(GLuint program)
500{
501 CRContext *g = GetCurrentContext();
502 CRGLSLProgram *pProgram = crStateGetProgramObj(program);
503
504 if (!pProgram)
505 {
506 crWarning("Unknown program %d", program);
507 return;
508 }
509
510 if (g->glsl.activeProgram == pProgram)
511 {
512 g->glsl.activeProgram = NULL;
513 }
514
515 crHashtableDelete(g->glsl.programs, program, crStateFreeGLSLProgram);
516}
517
518DECLEXPORT(void) STATE_APIENTRY crStateValidateProgram(GLuint program)
519{
520 CRGLSLProgram *pProgram = crStateGetProgramObj(program);
521
522 if (!pProgram)
523 {
524 crWarning("Unknown program %d", program);
525 return;
526 }
527
528 pProgram->validated = GL_TRUE;
529}
530
531static void crStateCopyShaderCB(unsigned long key, void *data1, void *data2)
532{
533 CRGLSLShader *pRealShader = (CRGLSLShader *) data1;
534 CRGLSLProgram *pProgram = (CRGLSLProgram *) data2;
535 CRGLSLShader *pShader;
536 GLint sLen=0;
537
538 CRASSERT(pRealShader);
539 pRealShader->refCount++;
540
541 pShader = (CRGLSLShader *) crAlloc(sizeof(*pShader));
542 if (!pShader)
543 {
544 crWarning("crStateCopyShaderCB: Out of memory!");
545 return;
546 }
547
548 crMemcpy(pShader, pRealShader, sizeof(*pShader));
549
550 diff_api.GetShaderiv(pShader->hwid, GL_SHADER_SOURCE_LENGTH, &sLen);
551 if (sLen>0)
552 {
553 pShader->source = (GLchar*) crAlloc(sLen);
554 diff_api.GetShaderSource(pShader->hwid, sLen, NULL, pShader->source);
555 }
556
557 crHashtableAdd(pProgram->activeState.attachedShaders, key, pShader);
558}
559
560DECLEXPORT(void) STATE_APIENTRY crStateLinkProgram(GLuint program)
561{
562 CRGLSLProgram *pProgram = crStateGetProgramObj(program);
563 GLuint i;
564
565 if (!pProgram)
566 {
567 crWarning("Unknown program %d", program);
568 return;
569 }
570
571 pProgram->linked = GL_TRUE;
572
573 /*Free program's active state*/
574 if (pProgram->activeState.attachedShaders)
575 {
576 crHashtableWalk(pProgram->activeState.attachedShaders, crStateFakeDecRefCountCB, NULL);
577 crFreeHashtable(pProgram->activeState.attachedShaders, crStateFreeGLSLShader);
578 pProgram->activeState.attachedShaders = NULL;
579 }
580 for (i=0; i<pProgram->activeState.cAttribs; ++i)
581 {
582 crFree(pProgram->activeState.pAttribs[i].name);
583 }
584 if (pProgram->activeState.pAttribs) crFree(pProgram->activeState.pAttribs);
585
586 /*copy current state to active state*/
587 crMemcpy(&pProgram->activeState, &pProgram->currentState, sizeof(CRGLSLProgramState));
588
589 pProgram->activeState.attachedShaders = crAllocHashtable();
590 if (!pProgram->activeState.attachedShaders)
591 {
592 crWarning("crStateLinkProgram: Out of memory!");
593 return;
594 }
595 crHashtableWalk(pProgram->currentState.attachedShaders, crStateCopyShaderCB, pProgram);
596
597 /*that's not a bug, note the memcpy above*/
598 if (pProgram->activeState.pAttribs)
599 {
600 pProgram->activeState.pAttribs = (CRGLSLAttrib *) crAlloc(pProgram->activeState.cAttribs * sizeof(CRGLSLAttrib));
601 }
602
603 for (i=0; i<pProgram->activeState.cAttribs; ++i)
604 {
605 crMemcpy(&pProgram->activeState.pAttribs[i], &pProgram->currentState.pAttribs[i], sizeof(CRGLSLAttrib));
606 pProgram->activeState.pAttribs[i].name = crStrdup(pProgram->currentState.pAttribs[i].name);
607 }
608
609 crStateFreeProgramUniforms(pProgram);
610}
611
612DECLEXPORT(void) STATE_APIENTRY crStateBindAttribLocation(GLuint program, GLuint index, const char * name)
613{
614 CRGLSLProgram *pProgram = crStateGetProgramObj(program);
615 GLuint i;
616 CRGLSLAttrib *pAttribs;
617
618 if (!pProgram)
619 {
620 crWarning("Unknown program %d", program);
621 return;
622 }
623
624 if (index>=CR_MAX_VERTEX_ATTRIBS)
625 {
626 crWarning("crStateBindAttribLocation: Index too big %d", index);
627 return;
628 }
629
630 for (i=0; i<pProgram->currentState.cAttribs; ++i)
631 {
632 if (!crStrcmp(pProgram->currentState.pAttribs[i].name, name))
633 {
634 pProgram->currentState.pAttribs[i].index = index;
635 return;
636 }
637 }
638
639 pAttribs = (CRGLSLAttrib*) crAlloc((pProgram->currentState.cAttribs+1)*sizeof(CRGLSLAttrib));
640 if (!pAttribs)
641 {
642 crWarning("crStateBindAttribLocation: Out of memory!");
643 return;
644 }
645
646 if (pProgram->currentState.cAttribs)
647 {
648 crMemcpy(&pAttribs[0], &pProgram->currentState.pAttribs[0], pProgram->currentState.cAttribs*sizeof(CRGLSLAttrib));
649 }
650 pAttribs[pProgram->currentState.cAttribs].index = index;
651 pAttribs[pProgram->currentState.cAttribs].name = crStrdup(name);
652
653 pProgram->currentState.cAttribs++;
654 if (pProgram->currentState.pAttribs) crFree(pProgram->currentState.pAttribs);
655 pProgram->currentState.pAttribs = pAttribs;
656}
657
658DECLEXPORT(GLint) STATE_APIENTRY crStateGetUniformSize(GLenum type)
659{
660 GLint size;
661
662 switch (type)
663 {
664 case GL_FLOAT:
665 size = 1;
666 break;
667 case GL_FLOAT_VEC2:
668 size = 2;
669 break;
670 case GL_FLOAT_VEC3:
671 size = 3;
672 break;
673 case GL_FLOAT_VEC4:
674 size = 4;
675 break;
676 case GL_INT:
677 size = 1;
678 break;
679 case GL_INT_VEC2:
680 size = 2;
681 break;
682 case GL_INT_VEC3:
683 size = 3;
684 break;
685 case GL_INT_VEC4:
686 size = 4;
687 break;
688 case GL_BOOL:
689 size = 1;
690 break;
691 case GL_BOOL_VEC2:
692 size = 2;
693 break;
694 case GL_BOOL_VEC3:
695 size = 3;
696 break;
697 case GL_BOOL_VEC4:
698 size = 4;
699 break;
700 case GL_FLOAT_MAT2:
701 size = 8;
702 break;
703 case GL_FLOAT_MAT3:
704 size = 12;
705 break;
706 case GL_FLOAT_MAT4:
707 size = 16;
708 break;
709 case GL_SAMPLER_1D:
710 case GL_SAMPLER_2D:
711 case GL_SAMPLER_3D:
712 case GL_SAMPLER_CUBE:
713 case GL_SAMPLER_1D_SHADOW:
714 case GL_SAMPLER_2D_SHADOW:
715 case GL_SAMPLER_2D_RECT_ARB:
716 case GL_SAMPLER_2D_RECT_SHADOW_ARB:
717 size = 1;
718 break;
719#ifdef CR_OPENGL_VERSION_2_1
720 case GL_FLOAT_MAT2x3:
721 size = 8;
722 break;
723 case GL_FLOAT_MAT2x4:
724 size = 8;
725 break;
726 case GL_FLOAT_MAT3x2:
727 size = 12;
728 break;
729 case GL_FLOAT_MAT3x4:
730 size = 12;
731 break;
732 case GL_FLOAT_MAT4x2:
733 size = 16;
734 break;
735 case GL_FLOAT_MAT4x3:
736 size = 16;
737 break;
738#endif
739 default:
740 crWarning("crStateGetUniformSize: unknown uniform type 0x%x", (GLint)type);
741 size = 16;
742 break;
743 }
744
745 return size;
746}
747
748DECLEXPORT(GLboolean) STATE_APIENTRY crStateIsIntUniform(GLenum type)
749{
750 if (GL_INT==type
751 || GL_INT_VEC2==type
752 || GL_INT_VEC3==type
753 || GL_INT_VEC4==type
754 || GL_BOOL==type
755 || GL_BOOL_VEC2==type
756 || GL_BOOL_VEC3==type
757 || GL_BOOL_VEC4==type
758 || GL_SAMPLER_1D==type
759 || GL_SAMPLER_2D==type
760 || GL_SAMPLER_3D==type
761 || GL_SAMPLER_CUBE==type
762 || GL_SAMPLER_1D_SHADOW==type
763 || GL_SAMPLER_2D_SHADOW==type
764 || GL_SAMPLER_2D_RECT_ARB==type
765 || GL_SAMPLER_2D_RECT_SHADOW_ARB==type)
766 {
767 return GL_TRUE;
768 }
769 else return GL_FALSE;
770}
771
772DECLEXPORT(GLboolean) STATE_APIENTRY crStateIsProgramUniformsCached(GLuint program)
773{
774 CRGLSLProgram *pProgram = crStateGetProgramObj(program);
775
776 if (!pProgram)
777 {
778 crWarning("Unknown program %d", program);
779 return GL_FALSE;
780 }
781
782#ifdef IN_GUEST
783 return pProgram->bUniformsSynced;
784#else
785 crWarning("crStateIsProgramUniformsCached called on host side!!");
786 return GL_FALSE;
787#endif
788}
789
790/*@todo: one of those functions should ignore uniforms starting with "gl"*/
791
792#ifdef IN_GUEST
793DECLEXPORT(void) STATE_APIENTRY
794crStateGLSLProgramCacheUniforms(GLuint program, GLsizei cbData, GLvoid *pData)
795{
796 CRGLSLProgram *pProgram = crStateGetProgramObj(program);
797 char *pCurrent = pData;
798 GLsizei cbRead, cbName;
799 GLuint i;
800
801 if (!pProgram)
802 {
803 crWarning("Unknown program %d", program);
804 return;
805 }
806
807 if (pProgram->bUniformsSynced)
808 {
809 crWarning("crStateGLSLProgramCacheUniforms: this shouldn't happen!");
810 crStateFreeProgramUniforms(pProgram);
811 }
812
813 if (cbData<sizeof(GLsizei))
814 {
815 crWarning("crStateGLSLProgramCacheUniforms: data too short");
816 return;
817 }
818
819 pProgram->cUniforms = ((GLsizei*)pCurrent)[0];
820 pCurrent += sizeof(GLsizei);
821 cbRead = sizeof(GLsizei);
822
823 crDebug("crStateGLSLProgramCacheUniforms: %i active uniforms", pProgram->cUniforms);
824
825 if (pProgram->cUniforms)
826 {
827 pProgram->pUniforms = crAlloc(pProgram->cUniforms*sizeof(CRGLSLUniform));
828 if (!pProgram->pUniforms)
829 {
830 crWarning("crStateGLSLProgramCacheUniforms: no memory");
831 pProgram->cUniforms = 0;
832 return;
833 }
834 }
835
836 for (i=0; i<pProgram->cUniforms; ++i)
837 {
838 cbRead += sizeof(GLuint)+sizeof(GLsizei);
839 if (cbRead>cbData)
840 {
841 crWarning("crStateGLSLProgramCacheUniforms: out of data reading uniform %i", i);
842 return;
843 }
844 pProgram->pUniforms[i].data = NULL;
845 pProgram->pUniforms[i].location = ((GLint*)pCurrent)[0];
846 pCurrent += sizeof(GLint);
847 cbName = ((GLsizei*)pCurrent)[0];
848 pCurrent += sizeof(GLsizei);
849
850 cbRead += cbName;
851 if (cbRead>cbData)
852 {
853 crWarning("crStateGLSLProgramCacheUniforms: out of data reading uniform's name %i", i);
854 return;
855 }
856
857 pProgram->pUniforms[i].name = crStrndup(pCurrent, cbName);
858 pCurrent += cbName;
859
860 crDebug("crStateGLSLProgramCacheUniforms: uniform[%i]=%d, %s", i, pProgram->pUniforms[i].location, pProgram->pUniforms[i].name);
861 }
862
863 pProgram->bUniformsSynced = GL_TRUE;
864
865 CRASSERT((pCurrent-((char*)pData))==cbRead);
866 CRASSERT(cbRead==cbData);
867}
868#else
869static GLboolean crStateGLSLProgramCacheOneUniform(GLuint location, GLsizei cbName, GLchar *pName,
870 char **pCurrent, GLsizei *pcbWritten, GLsizei maxcbData)
871{
872 *pcbWritten += sizeof(GLint)+sizeof(GLsizei)+cbName;
873 if (*pcbWritten>maxcbData)
874 {
875 crWarning("crStateGLSLProgramCacheUniforms: buffer too small");
876 crFree(pName);
877 return GL_FALSE;
878 }
879
880 crDebug("crStateGLSLProgramCacheUniforms: uniform[%i]=%s.", location, pName);
881
882 ((GLint*)*pCurrent)[0] = location;
883 *pCurrent += sizeof(GLint);
884 ((GLsizei*)*pCurrent)[0] = cbName;
885 *pCurrent += sizeof(GLsizei);
886 crMemcpy(*pCurrent, pName, cbName);
887 *pCurrent += cbName;
888
889 return GL_TRUE;
890}
891
892DECLEXPORT(void) STATE_APIENTRY
893crStateGLSLProgramCacheUniforms(GLuint program, GLsizei maxcbData, GLsizei *cbData, GLvoid *pData)
894{
895 CRGLSLProgram *pProgram = crStateGetProgramObj(program);
896 GLint maxUniformLen, activeUniforms=0, fakeUniformsCount, i, j;
897 char *pCurrent = pData;
898 GLsizei cbWritten;
899
900 if (!pProgram)
901 {
902 crWarning("Unknown program %d", program);
903 return;
904 }
905
906 diff_api.GetProgramiv(pProgram->hwid, GL_ACTIVE_UNIFORM_MAX_LENGTH, &maxUniformLen);
907 diff_api.GetProgramiv(pProgram->hwid, GL_ACTIVE_UNIFORMS, &activeUniforms);
908
909 *cbData = 0;
910
911 cbWritten = sizeof(GLsizei);
912 if (cbWritten>maxcbData)
913 {
914 crWarning("crStateGLSLProgramCacheUniforms: buffer too small");
915 return;
916 }
917 ((GLsizei*)pCurrent)[0] = activeUniforms;
918 fakeUniformsCount = activeUniforms;
919 pCurrent += sizeof(GLsizei);
920
921 crDebug("crStateGLSLProgramCacheUniforms: %i active uniforms", activeUniforms);
922
923 if (activeUniforms>0)
924 {
925 /*+8 to make sure our array uniforms with higher indices and [] will fit in as well*/
926 GLchar *name = (GLchar *) crAlloc(maxUniformLen+8);
927 GLenum type;
928 GLint size;
929 GLsizei cbName;
930 GLint location;
931
932 if (!name)
933 {
934 crWarning("crStateGLSLProgramCacheUniforms: no memory");
935 return;
936 }
937
938 for (i=0; i<activeUniforms; ++i)
939 {
940 diff_api.GetActiveUniform(pProgram->hwid, i, maxUniformLen, &cbName, &size, &type, name);
941 location = diff_api.GetUniformLocation(pProgram->hwid, name);
942
943 if (!crStateGLSLProgramCacheOneUniform(location, cbName, name, &pCurrent, &cbWritten, maxcbData))
944 return;
945
946 /* Only one active uniform variable will be reported for a uniform array by glGetActiveUniform,
947 * so we insert fake elements for other array elements.
948 */
949 if (size!=1)
950 {
951 char *pIndexStr = crStrchr(name, '[');
952 GLint firstIndex=1;
953 fakeUniformsCount += size;
954
955 crDebug("crStateGLSLProgramCacheUniforms: expanding array uniform, size=%i", size);
956
957 /*For array uniforms it's valid to query location of 1st element as both uniform and uniform[0].
958 *The name returned by glGetActiveUniform is driver dependent,
959 *atleast it's with [0] on win/ati and without [0] on linux/nvidia.
960 */
961 if (!pIndexStr)
962 {
963 pIndexStr = name+cbName;
964 firstIndex=0;
965 }
966 else
967 {
968 cbName = pIndexStr-name;
969 if (!crStateGLSLProgramCacheOneUniform(location, cbName, name, &pCurrent, &cbWritten, maxcbData))
970 return;
971 }
972
973 for (j=firstIndex; j<size; ++j)
974 {
975 sprintf(pIndexStr, "[%i]", j);
976 cbName = crStrlen(name);
977
978 location = diff_api.GetUniformLocation(pProgram->hwid, name);
979
980 if (!crStateGLSLProgramCacheOneUniform(location, cbName, name, &pCurrent, &cbWritten, maxcbData))
981 return;
982 }
983 }
984 }
985
986 crFree(name);
987 }
988
989 if (fakeUniformsCount!=activeUniforms)
990 {
991 ((GLsizei*)pData)[0] = fakeUniformsCount;
992 crDebug("FakeCount %i", fakeUniformsCount);
993 }
994
995 *cbData = cbWritten;
996
997 CRASSERT((pCurrent-((char*)pData))==cbWritten);
998}
999#endif
1000
1001DECLEXPORT(GLint) STATE_APIENTRY crStateGetUniformLocation(GLuint program, const char * name)
1002{
1003#ifdef IN_GUEST
1004 CRGLSLProgram *pProgram = crStateGetProgramObj(program);
1005 GLint result=-1;
1006 GLuint i;
1007
1008 if (!pProgram)
1009 {
1010 crWarning("Unknown program %d", program);
1011 return -1;
1012 }
1013
1014 if (!pProgram->bUniformsSynced)
1015 {
1016 crWarning("crStateGetUniformLocation called for uncached uniforms");
1017 return -1;
1018 }
1019
1020 for (i=0; i<pProgram->cUniforms; ++i)
1021 {
1022 if (!crStrcmp(name, pProgram->pUniforms[i].name))
1023 {
1024 result = pProgram->pUniforms[i].location;
1025 break;
1026 }
1027 }
1028
1029 return result;
1030#else
1031 crWarning("crStateGetUniformLocation called on host side!!");
1032 return -1;
1033#endif
1034}
1035
1036static void crStateGLSLCreateShadersCB(unsigned long key, void *data1, void *data2)
1037{
1038 CRGLSLShader *pShader = (CRGLSLShader*) data1;
1039 CRContext *ctx = (CRContext *) data2;
1040
1041 pShader->hwid = diff_api.CreateShader(pShader->type);
1042}
1043
1044static void crStateFixAttachedShaderHWIDsCB(unsigned long key, void *data1, void *data2)
1045{
1046 CRGLSLShader *pShader = (CRGLSLShader*) data1;
1047 CRGLSLShader *pRealShader;
1048 CRContext *pCtx = (CRContext *) data2;
1049
1050 pRealShader = (CRGLSLShader *) crHashtableSearch(pCtx->glsl.shaders, key);
1051 CRASSERT(pRealShader);
1052
1053 pShader->hwid = pRealShader->hwid;
1054}
1055
1056static void crStateGLSLSyncShadersCB(unsigned long key, void *data1, void *data2)
1057{
1058 CRGLSLShader *pShader = (CRGLSLShader*) data1;
1059 (void) key;
1060 (void) data2;
1061
1062 if (pShader->source)
1063 {
1064 diff_api.ShaderSource(pShader->hwid, 1, (const char**)&pShader->source, NULL);
1065 if (pShader->compiled)
1066 diff_api.CompileShader(pShader->hwid);
1067 crFree(pShader->source);
1068 pShader->source = NULL;
1069 }
1070
1071 if (pShader->deleted)
1072 diff_api.DeleteShader(pShader->hwid);
1073}
1074
1075static void crStateAttachShaderCB(unsigned long key, void *data1, void *data2)
1076{
1077 CRGLSLShader *pShader = (CRGLSLShader*) data1;
1078 CRGLSLProgram *pProgram = (CRGLSLProgram *) data2;
1079 (void) key;
1080
1081 if (pShader->source)
1082 {
1083 diff_api.ShaderSource(pShader->hwid, 1, (const char**)&pShader->source, NULL);
1084 if (pShader->compiled)
1085 diff_api.CompileShader(pShader->hwid);
1086 }
1087
1088 diff_api.AttachShader(pProgram->hwid, pShader->hwid);
1089}
1090
1091static void crStateDetachShaderCB(unsigned long key, void *data1, void *data2)
1092{
1093 CRGLSLShader *pShader = (CRGLSLShader*) data1;
1094 CRGLSLProgram *pProgram = (CRGLSLProgram *) data2;
1095 (void) key;
1096
1097 diff_api.DetachShader(pProgram->hwid, pShader->hwid);
1098}
1099
1100static void crStateGLSLCreateProgramCB(unsigned long key, void *data1, void *data2)
1101{
1102 CRGLSLProgram *pProgram = (CRGLSLProgram*) data1;
1103 CRContext *ctx = (CRContext *) data2;
1104 GLuint i;
1105
1106 pProgram->hwid = diff_api.CreateProgram();
1107
1108 if (pProgram->linked)
1109 {
1110 CRASSERT(pProgram->activeState.attachedShaders);
1111
1112 crHashtableWalk(pProgram->activeState.attachedShaders, crStateFixAttachedShaderHWIDsCB, ctx);
1113 crHashtableWalk(pProgram->activeState.attachedShaders, crStateAttachShaderCB, pProgram);
1114
1115 for (i=0; i<pProgram->activeState.cAttribs; ++i)
1116 {
1117 diff_api.BindAttribLocation(pProgram->hwid, pProgram->activeState.pAttribs[i].index, pProgram->activeState.pAttribs[i].name);
1118 }
1119
1120 if (pProgram->validated)
1121 diff_api.ValidateProgram(pProgram->hwid);
1122
1123 diff_api.LinkProgram(pProgram->hwid);
1124 }
1125
1126 diff_api.UseProgram(pProgram->hwid);
1127
1128 for (i=0; i<pProgram->cUniforms; ++i)
1129 {
1130 GLint location;
1131 GLfloat *pFdata = (GLfloat*)pProgram->pUniforms[i].data;
1132 GLint *pIdata = (GLint*)pProgram->pUniforms[i].data;
1133
1134 location = diff_api.GetUniformLocation(pProgram->hwid, pProgram->pUniforms[i].name);
1135 switch (pProgram->pUniforms[i].type)
1136 {
1137 case GL_FLOAT:
1138 diff_api.Uniform1fv(location, 1, pFdata);
1139 break;
1140 case GL_FLOAT_VEC2:
1141 diff_api.Uniform2fv(location, 1, pFdata);
1142 break;
1143 case GL_FLOAT_VEC3:
1144 diff_api.Uniform3fv(location, 1, pFdata);
1145 break;
1146 case GL_FLOAT_VEC4:
1147 diff_api.Uniform4fv(location, 1, pFdata);
1148 break;
1149 case GL_INT:
1150 case GL_BOOL:
1151 diff_api.Uniform1iv(location, 1, pIdata);
1152 break;
1153 case GL_INT_VEC2:
1154 case GL_BOOL_VEC2:
1155 diff_api.Uniform2iv(location, 1, pIdata);
1156 break;
1157 case GL_INT_VEC3:
1158 case GL_BOOL_VEC3:
1159 diff_api.Uniform3iv(location, 1, pIdata);
1160 break;
1161 case GL_INT_VEC4:
1162 case GL_BOOL_VEC4:
1163 diff_api.Uniform4iv(location, 1, pIdata);
1164 break;
1165 case GL_FLOAT_MAT2:
1166 diff_api.UniformMatrix2fv(location, 1, GL_FALSE, pFdata);
1167 break;
1168 case GL_FLOAT_MAT3:
1169 diff_api.UniformMatrix3fv(location, 1, GL_FALSE, pFdata);
1170 break;
1171 case GL_FLOAT_MAT4:
1172 diff_api.UniformMatrix4fv(location, 1, GL_FALSE, pFdata);
1173 break;
1174 case GL_SAMPLER_1D:
1175 case GL_SAMPLER_2D:
1176 case GL_SAMPLER_3D:
1177 case GL_SAMPLER_CUBE:
1178 case GL_SAMPLER_1D_SHADOW:
1179 case GL_SAMPLER_2D_SHADOW:
1180 case GL_SAMPLER_2D_RECT_ARB:
1181 case GL_SAMPLER_2D_RECT_SHADOW_ARB:
1182 diff_api.Uniform1iv(location, 1, pIdata);
1183 break;
1184#ifdef CR_OPENGL_VERSION_2_1
1185 case GL_FLOAT_MAT2x3:
1186 diff_api.UniformMatrix2x3fv(location, 1, GL_FALSE, pFdata);
1187 break;
1188 case GL_FLOAT_MAT2x4:
1189 diff_api.UniformMatrix2x4fv(location, 1, GL_FALSE, pFdata);
1190 break;
1191 case GL_FLOAT_MAT3x2:
1192 diff_api.UniformMatrix3x2fv(location, 1, GL_FALSE, pFdata);
1193 break;
1194 case GL_FLOAT_MAT3x4:
1195 diff_api.UniformMatrix3x4fv(location, 1, GL_FALSE, pFdata);
1196 break;
1197 case GL_FLOAT_MAT4x2:
1198 diff_api.UniformMatrix4x2fv(location, 1, GL_FALSE, pFdata);
1199 break;
1200 case GL_FLOAT_MAT4x3:
1201 diff_api.UniformMatrix4x3fv(location, 1, GL_FALSE, pFdata);
1202 break;
1203#endif
1204 default:
1205 crWarning("crStateGLSLCreateProgramCB: unknown uniform type 0x%x", (GLint)pProgram->pUniforms[i].type);
1206 break;
1207 }
1208 crFree(pProgram->pUniforms[i].data);
1209 crFree(pProgram->pUniforms[i].name);
1210 } /*for (i=0; i<pProgram->cUniforms; ++i)*/
1211 if (pProgram->pUniforms) crFree(pProgram->pUniforms);
1212 pProgram->pUniforms = NULL;
1213 pProgram->cUniforms = 0;
1214
1215 crHashtableWalk(pProgram->activeState.attachedShaders, crStateDetachShaderCB, pProgram);
1216 crHashtableWalk(pProgram->currentState.attachedShaders, crStateAttachShaderCB, pProgram);
1217}
1218
1219DECLEXPORT(void) STATE_APIENTRY crStateGLSLSwitch(CRContext *from, CRContext *to)
1220{
1221 GLboolean fForceUseProgramSet = GL_FALSE;
1222 if (to->glsl.bResyncNeeded)
1223 {
1224 to->glsl.bResyncNeeded = GL_FALSE;
1225
1226 crHashtableWalk(to->glsl.shaders, crStateGLSLCreateShadersCB, to);
1227
1228 crHashtableWalk(to->glsl.programs, crStateGLSLCreateProgramCB, to);
1229
1230 /* crStateGLSLCreateProgramCB changes the current program, ensure we have the proper program re-sored */
1231 fForceUseProgramSet = GL_TRUE;
1232
1233 crHashtableWalk(to->glsl.shaders, crStateGLSLSyncShadersCB, NULL);
1234 }
1235
1236 if (to->glsl.activeProgram != from->glsl.activeProgram || fForceUseProgramSet)
1237 {
1238 diff_api.UseProgram(to->glsl.activeProgram ? to->glsl.activeProgram->hwid : 0);
1239 }
1240}
Note: See TracBrowser for help on using the repository browser.

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