VirtualBox

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

Last change on this file since 36300 was 33540, checked in by vboxsync, 14 years ago

*: spelling fixes, thanks Timeless!

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