VirtualBox

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

最後變更 在這個檔案從39265是 37773,由 vboxsync 提交於 14 年 前

crOpenGL: more missing uniform types

  • 屬性 svn:eol-style 設為 native
  • 屬性 svn:keywords 設為 Author Date Id Revision
檔案大小: 32.1 KB
 
1/* $Id: state_glsl.c 37773 2011-07-04 18:07:09Z 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.alldomusa.eu.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 case GL_SAMPLER_2D_RECT_ARB:
645 case GL_SAMPLER_2D_RECT_SHADOW_ARB:
646 size = 1;
647 break;
648#ifdef CR_OPENGL_VERSION_2_1
649 case GL_FLOAT_MAT2x3:
650 size = 8;
651 break;
652 case GL_FLOAT_MAT2x4:
653 size = 8;
654 break;
655 case GL_FLOAT_MAT3x2:
656 size = 12;
657 break;
658 case GL_FLOAT_MAT3x4:
659 size = 12;
660 break;
661 case GL_FLOAT_MAT4x2:
662 size = 16;
663 break;
664 case GL_FLOAT_MAT4x3:
665 size = 16;
666 break;
667#endif
668 default:
669 crWarning("crStateGetUniformSize: unknown uniform type 0x%x", (GLint)type);
670 size = 16;
671 break;
672 }
673
674 return size;
675}
676
677DECLEXPORT(GLboolean) STATE_APIENTRY crStateIsIntUniform(GLenum type)
678{
679 if (GL_INT==type
680 || GL_INT_VEC2==type
681 || GL_INT_VEC3==type
682 || GL_INT_VEC4==type
683 || GL_BOOL==type
684 || GL_BOOL_VEC2==type
685 || GL_BOOL_VEC3==type
686 || GL_BOOL_VEC4==type
687 || GL_SAMPLER_1D==type
688 || GL_SAMPLER_2D==type
689 || GL_SAMPLER_3D==type
690 || GL_SAMPLER_CUBE==type
691 || GL_SAMPLER_1D_SHADOW==type
692 || GL_SAMPLER_2D_SHADOW==type
693 || GL_SAMPLER_2D_RECT_ARB==type
694 || GL_SAMPLER_2D_RECT_SHADOW_ARB==type)
695 {
696 return GL_TRUE;
697 }
698 else return GL_FALSE;
699}
700
701DECLEXPORT(GLboolean) STATE_APIENTRY crStateIsProgramUniformsCached(GLuint program)
702{
703 CRGLSLProgram *pProgram = crStateGetProgramObj(program);
704
705 if (!pProgram)
706 {
707 crWarning("Unknown program %d", program);
708 return GL_FALSE;
709 }
710
711#ifdef IN_GUEST
712 return pProgram->bUniformsSynced;
713#else
714 crWarning("crStateIsProgramUniformsCached called on host side!!");
715 return GL_FALSE;
716#endif
717}
718
719/*@todo: one of those functions should ignore uniforms starting with "gl"*/
720
721#ifdef IN_GUEST
722DECLEXPORT(void) STATE_APIENTRY
723crStateGLSLProgramCacheUniforms(GLuint program, GLsizei cbData, GLvoid *pData)
724{
725 CRGLSLProgram *pProgram = crStateGetProgramObj(program);
726 char *pCurrent = pData;
727 GLsizei cbRead, cbName;
728 GLuint i;
729
730 if (!pProgram)
731 {
732 crWarning("Unknown program %d", program);
733 return;
734 }
735
736 if (pProgram->bUniformsSynced)
737 {
738 crWarning("crStateGLSLProgramCacheUniforms: this shouldn't happen!");
739 crStateFreeProgramUniforms(pProgram);
740 }
741
742 if (cbData<sizeof(GLsizei))
743 {
744 crWarning("crStateGLSLProgramCacheUniforms: data too short");
745 return;
746 }
747
748 pProgram->cUniforms = ((GLsizei*)pCurrent)[0];
749 pCurrent += sizeof(GLsizei);
750 cbRead = sizeof(GLsizei);
751
752 crDebug("crStateGLSLProgramCacheUniforms: %i active uniforms", pProgram->cUniforms);
753
754 if (pProgram->cUniforms)
755 {
756 pProgram->pUniforms = crAlloc(pProgram->cUniforms*sizeof(CRGLSLUniform));
757 if (!pProgram->pUniforms)
758 {
759 crWarning("crStateGLSLProgramCacheUniforms: no memory");
760 pProgram->cUniforms = 0;
761 return;
762 }
763 }
764
765 for (i=0; i<pProgram->cUniforms; ++i)
766 {
767 cbRead += sizeof(GLuint)+sizeof(GLsizei);
768 if (cbRead>cbData)
769 {
770 crWarning("crStateGLSLProgramCacheUniforms: out of data reading uniform %i", i);
771 return;
772 }
773 pProgram->pUniforms[i].data = NULL;
774 pProgram->pUniforms[i].location = ((GLint*)pCurrent)[0];
775 pCurrent += sizeof(GLint);
776 cbName = ((GLsizei*)pCurrent)[0];
777 pCurrent += sizeof(GLsizei);
778
779 cbRead += cbName;
780 if (cbRead>cbData)
781 {
782 crWarning("crStateGLSLProgramCacheUniforms: out of data reading uniform's name %i", i);
783 return;
784 }
785
786 pProgram->pUniforms[i].name = crStrndup(pCurrent, cbName);
787 pCurrent += cbName;
788
789 crDebug("crStateGLSLProgramCacheUniforms: uniform[%i]=%d, %s", i, pProgram->pUniforms[i].location, pProgram->pUniforms[i].name);
790 }
791
792 pProgram->bUniformsSynced = GL_TRUE;
793
794 CRASSERT((pCurrent-((char*)pData))==cbRead);
795 CRASSERT(cbRead==cbData);
796}
797#else
798static GLboolean crStateGLSLProgramCacheOneUniform(GLuint location, GLsizei cbName, GLchar *pName,
799 char **pCurrent, GLsizei *pcbWritten, GLsizei maxcbData)
800{
801 *pcbWritten += sizeof(GLint)+sizeof(GLsizei)+cbName;
802 if (*pcbWritten>maxcbData)
803 {
804 crWarning("crStateGLSLProgramCacheUniforms: buffer too small");
805 crFree(pName);
806 return GL_FALSE;
807 }
808
809 crDebug("crStateGLSLProgramCacheUniforms: uniform[%i]=%s.", location, pName);
810
811 ((GLint*)*pCurrent)[0] = location;
812 *pCurrent += sizeof(GLint);
813 ((GLsizei*)*pCurrent)[0] = cbName;
814 *pCurrent += sizeof(GLsizei);
815 crMemcpy(*pCurrent, pName, cbName);
816 *pCurrent += cbName;
817
818 return GL_TRUE;
819}
820
821DECLEXPORT(void) STATE_APIENTRY
822crStateGLSLProgramCacheUniforms(GLuint program, GLsizei maxcbData, GLsizei *cbData, GLvoid *pData)
823{
824 CRGLSLProgram *pProgram = crStateGetProgramObj(program);
825 GLint maxUniformLen, activeUniforms=0, fakeUniformsCount, i, j;
826 char *pCurrent = pData;
827 GLsizei cbWritten;
828
829 if (!pProgram)
830 {
831 crWarning("Unknown program %d", program);
832 return;
833 }
834
835 diff_api.GetProgramiv(pProgram->hwid, GL_ACTIVE_UNIFORM_MAX_LENGTH, &maxUniformLen);
836 diff_api.GetProgramiv(pProgram->hwid, GL_ACTIVE_UNIFORMS, &activeUniforms);
837
838 *cbData = 0;
839
840 cbWritten = sizeof(GLsizei);
841 if (cbWritten>maxcbData)
842 {
843 crWarning("crStateGLSLProgramCacheUniforms: buffer too small");
844 return;
845 }
846 ((GLsizei*)pCurrent)[0] = activeUniforms;
847 fakeUniformsCount = activeUniforms;
848 pCurrent += sizeof(GLsizei);
849
850 crDebug("crStateGLSLProgramCacheUniforms: %i active uniforms", activeUniforms);
851
852 if (activeUniforms>0)
853 {
854 /*+8 to make sure our array uniforms with higher indices and [] will fit in as well*/
855 GLchar *name = (GLchar *) crAlloc(maxUniformLen+8);
856 GLenum type;
857 GLint size;
858 GLsizei cbName;
859 GLint location;
860
861 if (!name)
862 {
863 crWarning("crStateGLSLProgramCacheUniforms: no memory");
864 return;
865 }
866
867 for (i=0; i<activeUniforms; ++i)
868 {
869 diff_api.GetActiveUniform(pProgram->hwid, i, maxUniformLen, &cbName, &size, &type, name);
870 location = diff_api.GetUniformLocation(pProgram->hwid, name);
871
872 if (!crStateGLSLProgramCacheOneUniform(location, cbName, name, &pCurrent, &cbWritten, maxcbData))
873 return;
874
875 /* Only one active uniform variable will be reported for a uniform array by glGetActiveUniform,
876 * so we insert fake elements for other array elements.
877 */
878 if (size!=1)
879 {
880 char *pIndexStr = crStrchr(name, '[');
881 GLint firstIndex=1;
882 fakeUniformsCount += size;
883
884 crDebug("crStateGLSLProgramCacheUniforms: expanding array uniform, size=%i", size);
885
886 /*For array uniforms it's valid to query location of 1st element as both uniform and uniform[0].
887 *The name returned by glGetActiveUniform is driver dependent,
888 *atleast it's with [0] on win/ati and without [0] on linux/nvidia.
889 */
890 if (!pIndexStr)
891 {
892 pIndexStr = name+cbName;
893 firstIndex=0;
894 }
895 else
896 {
897 cbName = pIndexStr-name;
898 if (!crStateGLSLProgramCacheOneUniform(location, cbName, name, &pCurrent, &cbWritten, maxcbData))
899 return;
900 }
901
902 for (j=firstIndex; j<size; ++j)
903 {
904 sprintf(pIndexStr, "[%i]", j);
905 cbName = crStrlen(name);
906
907 location = diff_api.GetUniformLocation(pProgram->hwid, name);
908
909 if (!crStateGLSLProgramCacheOneUniform(location, cbName, name, &pCurrent, &cbWritten, maxcbData))
910 return;
911 }
912 }
913 }
914
915 crFree(name);
916 }
917
918 if (fakeUniformsCount!=activeUniforms)
919 {
920 ((GLsizei*)pData)[0] = fakeUniformsCount;
921 crDebug("FakeCount %i", fakeUniformsCount);
922 }
923
924 *cbData = cbWritten;
925
926 CRASSERT((pCurrent-((char*)pData))==cbWritten);
927}
928#endif
929
930DECLEXPORT(GLint) STATE_APIENTRY crStateGetUniformLocation(GLuint program, const char * name)
931{
932#ifdef IN_GUEST
933 CRGLSLProgram *pProgram = crStateGetProgramObj(program);
934 GLint result=-1;
935 GLuint i;
936
937 if (!pProgram)
938 {
939 crWarning("Unknown program %d", program);
940 return -1;
941 }
942
943 if (!pProgram->bUniformsSynced)
944 {
945 crWarning("crStateGetUniformLocation called for uncached uniforms");
946 return -1;
947 }
948
949 for (i=0; i<pProgram->cUniforms; ++i)
950 {
951 if (!crStrcmp(name, pProgram->pUniforms[i].name))
952 {
953 result = pProgram->pUniforms[i].location;
954 break;
955 }
956 }
957
958 return result;
959#else
960 crWarning("crStateGetUniformLocation called on host side!!");
961 return -1;
962#endif
963}
964
965static void crStateGLSLCreateShadersCB(unsigned long key, void *data1, void *data2)
966{
967 CRGLSLShader *pShader = (CRGLSLShader*) data1;
968 CRContext *ctx = (CRContext *) data2;
969
970 pShader->hwid = diff_api.CreateShader(pShader->type);
971}
972
973static void crStateFixAttachedShaderHWIDsCB(unsigned long key, void *data1, void *data2)
974{
975 CRGLSLShader *pShader = (CRGLSLShader*) data1;
976 CRGLSLShader *pRealShader;
977 CRContext *pCtx = (CRContext *) data2;
978
979 pRealShader = (CRGLSLShader *) crHashtableSearch(pCtx->glsl.shaders, key);
980 CRASSERT(pRealShader);
981
982 pShader->hwid = pRealShader->hwid;
983}
984
985static void crStateGLSLSyncShadersCB(unsigned long key, void *data1, void *data2)
986{
987 CRGLSLShader *pShader = (CRGLSLShader*) data1;
988 (void) key;
989 (void) data2;
990
991 if (pShader->source)
992 {
993 diff_api.ShaderSource(pShader->hwid, 1, (const char**)&pShader->source, NULL);
994 if (pShader->compiled)
995 diff_api.CompileShader(pShader->hwid);
996 crFree(pShader->source);
997 pShader->source = NULL;
998 }
999
1000 if (pShader->deleted)
1001 diff_api.DeleteShader(pShader->hwid);
1002}
1003
1004static void crStateAttachShaderCB(unsigned long key, void *data1, void *data2)
1005{
1006 CRGLSLShader *pShader = (CRGLSLShader*) data1;
1007 CRGLSLProgram *pProgram = (CRGLSLProgram *) data2;
1008 (void) key;
1009
1010 if (pShader->source)
1011 {
1012 diff_api.ShaderSource(pShader->hwid, 1, (const char**)&pShader->source, NULL);
1013 if (pShader->compiled)
1014 diff_api.CompileShader(pShader->hwid);
1015 }
1016
1017 diff_api.AttachShader(pProgram->hwid, pShader->hwid);
1018}
1019
1020static void crStateDetachShaderCB(unsigned long key, void *data1, void *data2)
1021{
1022 CRGLSLShader *pShader = (CRGLSLShader*) data1;
1023 CRGLSLProgram *pProgram = (CRGLSLProgram *) data2;
1024 (void) key;
1025
1026 diff_api.DetachShader(pProgram->hwid, pShader->hwid);
1027}
1028
1029static void crStateGLSLCreateProgramCB(unsigned long key, void *data1, void *data2)
1030{
1031 CRGLSLProgram *pProgram = (CRGLSLProgram*) data1;
1032 CRContext *ctx = (CRContext *) data2;
1033 GLuint i;
1034
1035 pProgram->hwid = diff_api.CreateProgram();
1036
1037 if (pProgram->linked)
1038 {
1039 CRASSERT(pProgram->activeState.attachedShaders);
1040
1041 crHashtableWalk(pProgram->activeState.attachedShaders, crStateFixAttachedShaderHWIDsCB, ctx);
1042 crHashtableWalk(pProgram->activeState.attachedShaders, crStateAttachShaderCB, pProgram);
1043
1044 for (i=0; i<pProgram->activeState.cAttribs; ++i)
1045 {
1046 diff_api.BindAttribLocation(pProgram->hwid, pProgram->activeState.pAttribs[i].index, pProgram->activeState.pAttribs[i].name);
1047 }
1048
1049 if (pProgram->validated)
1050 diff_api.ValidateProgram(pProgram->hwid);
1051
1052 diff_api.LinkProgram(pProgram->hwid);
1053 }
1054
1055 diff_api.UseProgram(pProgram->hwid);
1056
1057 for (i=0; i<pProgram->cUniforms; ++i)
1058 {
1059 GLint location;
1060 GLfloat *pFdata = (GLfloat*)pProgram->pUniforms[i].data;
1061 GLint *pIdata = (GLint*)pProgram->pUniforms[i].data;
1062
1063 location = diff_api.GetUniformLocation(pProgram->hwid, pProgram->pUniforms[i].name);
1064 switch (pProgram->pUniforms[i].type)
1065 {
1066 case GL_FLOAT:
1067 diff_api.Uniform1fv(location, 1, pFdata);
1068 break;
1069 case GL_FLOAT_VEC2:
1070 diff_api.Uniform2fv(location, 1, pFdata);
1071 break;
1072 case GL_FLOAT_VEC3:
1073 diff_api.Uniform3fv(location, 1, pFdata);
1074 break;
1075 case GL_FLOAT_VEC4:
1076 diff_api.Uniform4fv(location, 1, pFdata);
1077 break;
1078 case GL_INT:
1079 case GL_BOOL:
1080 diff_api.Uniform1iv(location, 1, pIdata);
1081 break;
1082 case GL_INT_VEC2:
1083 case GL_BOOL_VEC2:
1084 diff_api.Uniform2iv(location, 1, pIdata);
1085 break;
1086 case GL_INT_VEC3:
1087 case GL_BOOL_VEC3:
1088 diff_api.Uniform3iv(location, 1, pIdata);
1089 break;
1090 case GL_INT_VEC4:
1091 case GL_BOOL_VEC4:
1092 diff_api.Uniform4iv(location, 1, pIdata);
1093 break;
1094 case GL_FLOAT_MAT2:
1095 diff_api.UniformMatrix2fv(location, 1, GL_FALSE, pFdata);
1096 break;
1097 case GL_FLOAT_MAT3:
1098 diff_api.UniformMatrix3fv(location, 1, GL_FALSE, pFdata);
1099 break;
1100 case GL_FLOAT_MAT4:
1101 diff_api.UniformMatrix4fv(location, 1, GL_FALSE, pFdata);
1102 break;
1103 case GL_SAMPLER_1D:
1104 case GL_SAMPLER_2D:
1105 case GL_SAMPLER_3D:
1106 case GL_SAMPLER_CUBE:
1107 case GL_SAMPLER_1D_SHADOW:
1108 case GL_SAMPLER_2D_SHADOW:
1109 case GL_SAMPLER_2D_RECT_ARB:
1110 case GL_SAMPLER_2D_RECT_SHADOW_ARB:
1111 diff_api.Uniform1iv(location, 1, pIdata);
1112 break;
1113#ifdef CR_OPENGL_VERSION_2_1
1114 case GL_FLOAT_MAT2x3:
1115 diff_api.UniformMatrix2x3fv(location, 1, GL_FALSE, pFdata);
1116 break;
1117 case GL_FLOAT_MAT2x4:
1118 diff_api.UniformMatrix2x4fv(location, 1, GL_FALSE, pFdata);
1119 break;
1120 case GL_FLOAT_MAT3x2:
1121 diff_api.UniformMatrix3x2fv(location, 1, GL_FALSE, pFdata);
1122 break;
1123 case GL_FLOAT_MAT3x4:
1124 diff_api.UniformMatrix3x4fv(location, 1, GL_FALSE, pFdata);
1125 break;
1126 case GL_FLOAT_MAT4x2:
1127 diff_api.UniformMatrix4x2fv(location, 1, GL_FALSE, pFdata);
1128 break;
1129 case GL_FLOAT_MAT4x3:
1130 diff_api.UniformMatrix4x3fv(location, 1, GL_FALSE, pFdata);
1131 break;
1132#endif
1133 default:
1134 crWarning("crStateGLSLCreateProgramCB: unknown uniform type 0x%x", (GLint)pProgram->pUniforms[i].type);
1135 break;
1136 }
1137 crFree(pProgram->pUniforms[i].data);
1138 crFree(pProgram->pUniforms[i].name);
1139 } /*for (i=0; i<pProgram->cUniforms; ++i)*/
1140 if (pProgram->pUniforms) crFree(pProgram->pUniforms);
1141 pProgram->pUniforms = NULL;
1142 pProgram->cUniforms = 0;
1143
1144 crHashtableWalk(pProgram->activeState.attachedShaders, crStateDetachShaderCB, pProgram);
1145 crHashtableWalk(pProgram->currentState.attachedShaders, crStateAttachShaderCB, pProgram);
1146}
1147
1148DECLEXPORT(void) STATE_APIENTRY crStateGLSLSwitch(CRContext *from, CRContext *to)
1149{
1150 if (to->glsl.bResyncNeeded)
1151 {
1152 to->glsl.bResyncNeeded = GL_FALSE;
1153
1154 crHashtableWalk(to->glsl.shaders, crStateGLSLCreateShadersCB, to);
1155
1156 crHashtableWalk(to->glsl.programs, crStateGLSLCreateProgramCB, to);
1157
1158 crHashtableWalk(to->glsl.shaders, crStateGLSLSyncShadersCB, NULL);
1159 }
1160
1161 if (to->glsl.activeProgram != from->glsl.activeProgram)
1162 {
1163 diff_api.UseProgram(to->glsl.activeProgram ? to->glsl.activeProgram->hwid : 0);
1164 }
1165}
注意: 瀏覽 TracBrowser 來幫助您使用儲存庫瀏覽器

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette