VirtualBox

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

Last change on this file since 27159 was 26031, checked in by vboxsync, 15 years ago

warning

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