VirtualBox

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

Last change on this file since 42932 was 41928, checked in by vboxsync, 13 years ago

crOpenGL: fix shader deletion

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