VirtualBox

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

Last change on this file since 43491 was 43184, checked in by vboxsync, 13 years ago

crOpenGL: fix retval

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