VirtualBox

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

Last change on this file since 39815 was 39602, checked in by vboxsync, 13 years ago

wine/XPDM: 1. Additional swapchain creation fixes 2. De-libwine'ize wined3d 3. Single context per swapchain 4. wine & crOgl current context sync fixes 5. Proper Get/ReleaseDC handling

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