VirtualBox

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

Last change on this file since 76474 was 69500, checked in by vboxsync, 7 years ago

*: scm --update-copyright-year

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 42.4 KB
Line 
1/* $Id: state_glsl.c 69500 2017-10-28 15:14:05Z vboxsync $ */
2
3/** @file
4 * VBox OpenGL: GLSL state tracking
5 */
6
7/*
8 * Copyright (C) 2009-2017 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
60#ifdef IN_GUEST
61static void crStateFreeProgramAttribsLocationCache(CRGLSLProgram* pProgram)
62{
63 if (pProgram->pAttribs) crFree(pProgram->pAttribs);
64
65 pProgram->pAttribs = NULL;
66 pProgram->cAttribs = 0;
67}
68#endif
69
70static void crStateFreeProgramAttribs(CRGLSLProgram* pProgram)
71{
72 GLuint i;
73
74 for (i=0; i<pProgram->activeState.cAttribs; ++i)
75 {
76 crFree(pProgram->activeState.pAttribs[i].name);
77 }
78
79 for (i=0; i<pProgram->currentState.cAttribs; ++i)
80 {
81 crFree(pProgram->currentState.pAttribs[i].name);
82 }
83
84 if (pProgram->activeState.pAttribs)
85 crFree(pProgram->activeState.pAttribs);
86
87 if (pProgram->currentState.pAttribs)
88 crFree(pProgram->currentState.pAttribs);
89
90#ifdef IN_GUEST
91 crStateFreeProgramAttribsLocationCache(pProgram);
92
93 pProgram->bAttribsSynced = GL_FALSE;
94#endif
95
96}
97
98static void crStateFreeProgramUniforms(CRGLSLProgram* pProgram)
99{
100 GLuint i;
101
102 for (i=0; i<pProgram->cUniforms; ++i)
103 {
104 if (pProgram->pUniforms[i].name) crFree(pProgram->pUniforms[i].name);
105 if (pProgram->pUniforms[i].data) crFree(pProgram->pUniforms[i].data);
106 }
107
108 if (pProgram->pUniforms) crFree(pProgram->pUniforms);
109
110 pProgram->pUniforms = NULL;
111 pProgram->cUniforms = 0;
112
113#ifdef IN_GUEST
114 pProgram->bUniformsSynced = GL_FALSE;
115#endif
116}
117
118static void crStateShaderDecRefCount(void *data)
119{
120 CRGLSLShader *pShader = (CRGLSLShader *) data;
121
122 CRASSERT(pShader->refCount>0);
123
124 pShader->refCount--;
125
126 if (0==pShader->refCount && pShader->deleted)
127 {
128 CRContext *g = GetCurrentContext();
129 crHashtableDelete(g->glsl.shaders, pShader->id, crStateFreeGLSLShader);
130 }
131}
132
133static void crStateFakeDecRefCountCB(unsigned long key, void *data1, void *data2)
134{
135 CRGLSLShader *pShader = (CRGLSLShader *) data1;
136 CRContext *ctx = (CRContext*) data2;
137 CRGLSLShader *pRealShader;
138 (void) key; (void)ctx;
139
140 pRealShader = crStateGetShaderObj(pShader->id);
141
142 if (pRealShader)
143 {
144 crStateShaderDecRefCount(pRealShader);
145 }
146 else
147 {
148 crWarning("crStateFakeDecRefCountCB: NULL pRealShader");
149 }
150}
151
152static void crStateFreeGLSLProgram(void *data)
153{
154 CRGLSLProgram* pProgram = (CRGLSLProgram *) data;
155
156 crFreeHashtable(pProgram->currentState.attachedShaders, crStateShaderDecRefCount);
157
158 if (pProgram->activeState.attachedShaders)
159 {
160 CRContext *g = GetCurrentContext();
161 crHashtableWalk(pProgram->activeState.attachedShaders, crStateFakeDecRefCountCB, g);
162 crFreeHashtable(pProgram->activeState.attachedShaders, crStateFreeGLSLShader);
163 }
164
165 crStateFreeProgramAttribs(pProgram);
166
167 crStateFreeProgramUniforms(pProgram);
168
169 crFree(pProgram);
170}
171
172DECLEXPORT(void) STATE_APIENTRY crStateGLSLInit(CRContext *ctx)
173{
174 ctx->glsl.shaders = crAllocHashtable();
175 ctx->glsl.programs = crAllocHashtable();
176 ctx->glsl.activeProgram = NULL;
177 ctx->glsl.bResyncNeeded = GL_FALSE;
178
179 if (!ctx->glsl.shaders || !ctx->glsl.programs)
180 {
181 crWarning("crStateGLSLInit: Out of memory!");
182 return;
183 }
184}
185
186DECLEXPORT(void) STATE_APIENTRY crStateGLSLDestroy(CRContext *ctx)
187{
188 CRContext *g = GetCurrentContext();
189
190 /** @todo hack to allow crStateFreeGLSLProgram to work correctly,
191 as the current context isn't the one being destroyed*/
192#ifdef CHROMIUM_THREADSAFE
193 CRASSERT(g != ctx);
194 VBoxTlsRefAddRef(ctx); /* <- this is a hack to avoid subsequent SetCurrentContext(g) do recursive Destroy for ctx */
195 if (g)
196 VBoxTlsRefAddRef(g); /* <- ensure the g is not destroyed by the following SetCurrentContext call */
197 SetCurrentContext(ctx);
198#else
199 __currentContext = ctx;
200#endif
201
202 crFreeHashtable(ctx->glsl.programs, crStateFreeGLSLProgram);
203 crFreeHashtable(ctx->glsl.shaders, crStateFreeGLSLShader);
204
205#ifdef CHROMIUM_THREADSAFE
206 SetCurrentContext(g);
207 if (g)
208 VBoxTlsRefRelease(g);
209 VBoxTlsRefRelease(ctx); /* <- restore back the cRefs (see above) */
210#else
211 __currentContext = g;
212#endif
213
214}
215
216DECLEXPORT(GLuint) STATE_APIENTRY crStateGetShaderHWID(GLuint id)
217{
218 CRGLSLShader *pShader = crStateGetShaderObj(id);
219#ifdef IN_GUEST
220 CRASSERT(!pShader || pShader->hwid == id);
221#endif
222 return pShader ? pShader->hwid : 0;
223}
224
225DECLEXPORT(GLuint) STATE_APIENTRY crStateGetProgramHWID(GLuint id)
226{
227 CRGLSLProgram *pProgram = crStateGetProgramObj(id);
228#ifdef IN_GUEST
229 CRASSERT(!pProgram || pProgram->hwid == id);
230#endif
231 return pProgram ? pProgram->hwid : 0;
232}
233
234static void crStateCheckShaderHWIDCB(unsigned long key, void *data1, void *data2)
235{
236 CRGLSLShader *pShader = (CRGLSLShader *) data1;
237 crCheckIDHWID_t *pParms = (crCheckIDHWID_t*) data2;
238 (void) key;
239
240 if (pShader->hwid==pParms->hwid)
241 pParms->id = pShader->id;
242}
243
244static void crStateCheckProgramHWIDCB(unsigned long key, void *data1, void *data2)
245{
246 CRGLSLProgram *pProgram = (CRGLSLProgram *) data1;
247 crCheckIDHWID_t *pParms = (crCheckIDHWID_t*) data2;
248 (void) key;
249
250 if (pProgram->hwid==pParms->hwid)
251 pParms->id = pProgram->id;
252}
253
254DECLEXPORT(GLuint) STATE_APIENTRY crStateGLSLShaderHWIDtoID(GLuint hwid)
255{
256 CRContext *g = GetCurrentContext();
257 crCheckIDHWID_t parms;
258
259 parms.id = hwid;
260 parms.hwid = hwid;
261
262 crHashtableWalk(g->glsl.shaders, crStateCheckShaderHWIDCB, &parms);
263 return parms.id;
264}
265
266DECLEXPORT(GLuint) STATE_APIENTRY crStateGLSLProgramHWIDtoID(GLuint hwid)
267{
268 CRContext *g = GetCurrentContext();
269 crCheckIDHWID_t parms;
270
271 parms.id = hwid;
272 parms.hwid = hwid;
273
274 crHashtableWalk(g->glsl.programs, crStateCheckProgramHWIDCB, &parms);
275 return parms.id;
276}
277
278DECLEXPORT(GLuint) STATE_APIENTRY crStateDeleteObjectARB( VBoxGLhandleARB obj )
279{
280 GLuint hwId = crStateGetProgramHWID(obj);
281 if (hwId)
282 {
283 crStateDeleteProgram(obj);
284 }
285 else
286 {
287 hwId = crStateGetShaderHWID(obj);
288 crStateDeleteShader(obj);
289 }
290 return hwId;
291}
292
293DECLEXPORT(GLuint) STATE_APIENTRY crStateCreateShader(GLuint hwid, GLenum type)
294{
295 CRGLSLShader *pShader;
296 CRContext *g = GetCurrentContext();
297 GLuint stateId = hwid;
298
299#ifdef IN_GUEST
300 CRASSERT(!crStateGetShaderObj(stateId));
301#else
302 /* the proogram and shader names must not intersect because DeleteObjectARB must distinguish between them
303 * see crStateDeleteObjectARB
304 * this is why use programs table for shader keys allocation */
305 stateId = crHashtableAllocKeys(g->glsl.programs, 1);
306 if (!stateId)
307 {
308 crWarning("failed to allocate program key");
309 return 0;
310 }
311
312 Assert((pShader = crStateGetShaderObj(stateId)) == NULL);
313#endif
314
315 pShader = (CRGLSLShader *) crAlloc(sizeof(*pShader));
316 if (!pShader)
317 {
318 crWarning("crStateCreateShader: Out of memory!");
319 return 0;
320 }
321
322 pShader->id = stateId;
323 pShader->hwid = hwid;
324 pShader->type = type;
325 pShader->source = NULL;
326 pShader->compiled = GL_FALSE;
327 pShader->deleted = GL_FALSE;
328 pShader->refCount = 0;
329
330 crHashtableAdd(g->glsl.shaders, stateId, pShader);
331
332 return stateId;
333}
334
335DECLEXPORT(GLuint) STATE_APIENTRY crStateCreateProgram(GLuint hwid)
336{
337 CRGLSLProgram *pProgram;
338 CRContext *g = GetCurrentContext();
339 GLuint stateId = hwid;
340
341#ifdef IN_GUEST
342 pProgram = crStateGetProgramObj(stateId);
343 if (pProgram)
344 {
345 crWarning("Program object %d already exists!", stateId);
346 crStateDeleteProgram(stateId);
347 CRASSERT(!crStateGetProgramObj(stateId));
348 }
349#else
350 stateId = crHashtableAllocKeys(g->glsl.programs, 1);
351 if (!stateId)
352 {
353 crWarning("failed to allocate program key");
354 return 0;
355 }
356#endif
357
358 pProgram = (CRGLSLProgram *) crAlloc(sizeof(*pProgram));
359 if (!pProgram)
360 {
361 crWarning("crStateCreateProgram: Out of memory!");
362 return 0;
363 }
364
365 pProgram->id = stateId;
366 pProgram->hwid = hwid;
367 pProgram->validated = GL_FALSE;
368 pProgram->linked = GL_FALSE;
369 pProgram->deleted = GL_FALSE;
370 pProgram->activeState.attachedShaders = NULL;
371 pProgram->currentState.attachedShaders = crAllocHashtable();
372
373 pProgram->activeState.cAttribs = 0;
374 pProgram->activeState.pAttribs = NULL;
375 pProgram->currentState.cAttribs = 0;
376 pProgram->currentState.pAttribs = NULL;
377
378 pProgram->pUniforms = NULL;
379 pProgram->cUniforms = 0;
380
381#ifdef IN_GUEST
382 pProgram->pAttribs = NULL;
383 pProgram->cAttribs = 0;
384
385 pProgram->bUniformsSynced = GL_FALSE;
386 pProgram->bAttribsSynced = GL_FALSE;
387#endif
388
389 crHashtableAdd(g->glsl.programs, stateId, pProgram);
390
391 return stateId;
392}
393
394DECLEXPORT(void) STATE_APIENTRY crStateCompileShader(GLuint shader)
395{
396 CRGLSLShader *pShader = crStateGetShaderObj(shader);
397 if (!pShader)
398 {
399 crWarning("Unknown shader %d", shader);
400 return;
401 }
402
403 pShader->compiled = GL_TRUE;
404}
405
406static void crStateDbgCheckNoProgramOfId(void *data)
407{
408 (void)data;
409 crError("Unexpected Program id");
410}
411
412DECLEXPORT(void) STATE_APIENTRY crStateDeleteShader(GLuint shader)
413{
414 CRGLSLShader *pShader = crStateGetShaderObj(shader);
415 if (!pShader)
416 {
417 crWarning("Unknown shader %d", shader);
418 return;
419 }
420
421 pShader->deleted = GL_TRUE;
422
423 if (0==pShader->refCount)
424 {
425 CRContext *g = GetCurrentContext();
426 crHashtableDelete(g->glsl.shaders, shader, crStateFreeGLSLShader);
427 /* since we use programs table for key allocation key allocation, we need to
428 * free the key in the programs table.
429 * See comment in crStateCreateShader */
430 crHashtableDelete(g->glsl.programs, shader, crStateDbgCheckNoProgramOfId);
431 }
432}
433
434DECLEXPORT(void) STATE_APIENTRY crStateAttachShader(GLuint program, GLuint shader)
435{
436 CRGLSLProgram *pProgram = crStateGetProgramObj(program);
437 CRGLSLShader *pShader;
438
439 if (!pProgram)
440 {
441 crWarning("Unknown program %d", program);
442 return;
443 }
444
445 if (crHashtableSearch(pProgram->currentState.attachedShaders, shader))
446 {
447 /*shader already attached to this program*/
448 return;
449 }
450
451 pShader = crStateGetShaderObj(shader);
452
453 if (!pShader)
454 {
455 crWarning("Unknown shader %d", shader);
456 return;
457 }
458
459 pShader->refCount++;
460
461 crHashtableAdd(pProgram->currentState.attachedShaders, shader, pShader);
462}
463
464DECLEXPORT(void) STATE_APIENTRY crStateDetachShader(GLuint program, GLuint shader)
465{
466 CRGLSLProgram *pProgram = crStateGetProgramObj(program);
467 CRGLSLShader *pShader;
468
469 if (!pProgram)
470 {
471 crWarning("Unknown program %d", program);
472 return;
473 }
474
475 pShader = (CRGLSLShader *) crHashtableSearch(pProgram->currentState.attachedShaders, shader);
476 if (!pShader)
477 {
478 crWarning("Shader %d isn't attached to program %d", shader, program);
479 return;
480 }
481
482 crHashtableDelete(pProgram->currentState.attachedShaders, shader, NULL);
483
484 CRASSERT(pShader->refCount>0);
485 pShader->refCount--;
486
487 if (0==pShader->refCount)
488 {
489 CRContext *g = GetCurrentContext();
490 crHashtableDelete(g->glsl.shaders, shader, crStateFreeGLSLShader);
491 }
492}
493
494DECLEXPORT(void) STATE_APIENTRY crStateUseProgram(GLuint program)
495{
496 CRContext *g = GetCurrentContext();
497
498 if (program>0)
499 {
500 CRGLSLProgram *pProgram = crStateGetProgramObj(program);
501
502 if (!pProgram)
503 {
504 crWarning("Unknown program %d", program);
505 return;
506 }
507
508 g->glsl.activeProgram = pProgram;
509 }
510 else
511 {
512 g->glsl.activeProgram = NULL;
513 }
514}
515
516DECLEXPORT(void) STATE_APIENTRY crStateDeleteProgram(GLuint program)
517{
518 CRContext *g = GetCurrentContext();
519 CRGLSLProgram *pProgram = crStateGetProgramObj(program);
520
521 if (!pProgram)
522 {
523 crWarning("Unknown program %d", program);
524 return;
525 }
526
527 if (g->glsl.activeProgram == pProgram)
528 {
529 g->glsl.activeProgram = NULL;
530 }
531
532 crHashtableDelete(g->glsl.programs, program, crStateFreeGLSLProgram);
533}
534
535DECLEXPORT(void) STATE_APIENTRY crStateValidateProgram(GLuint program)
536{
537 CRGLSLProgram *pProgram = crStateGetProgramObj(program);
538
539 if (!pProgram)
540 {
541 crWarning("Unknown program %d", program);
542 return;
543 }
544
545 pProgram->validated = GL_TRUE;
546}
547
548static void crStateCopyShaderCB(unsigned long key, void *data1, void *data2)
549{
550 CRGLSLShader *pRealShader = (CRGLSLShader *) data1;
551 CRGLSLProgram *pProgram = (CRGLSLProgram *) data2;
552 CRGLSLShader *pShader;
553 GLint sLen=0;
554
555 CRASSERT(pRealShader);
556 pRealShader->refCount++;
557
558 pShader = (CRGLSLShader *) crAlloc(sizeof(*pShader));
559 if (!pShader)
560 {
561 crWarning("crStateCopyShaderCB: Out of memory!");
562 return;
563 }
564
565 crMemcpy(pShader, pRealShader, sizeof(*pShader));
566
567 diff_api.GetShaderiv(pShader->hwid, GL_SHADER_SOURCE_LENGTH, &sLen);
568 if (sLen>0)
569 {
570 pShader->source = (GLchar*) crAlloc(sLen);
571 diff_api.GetShaderSource(pShader->hwid, sLen, NULL, pShader->source);
572 }
573
574 crHashtableAdd(pProgram->activeState.attachedShaders, key, pShader);
575}
576
577DECLEXPORT(void) STATE_APIENTRY crStateLinkProgram(GLuint program)
578{
579 CRGLSLProgram *pProgram = crStateGetProgramObj(program);
580 GLuint i;
581
582 if (!pProgram)
583 {
584 crWarning("Unknown program %d", program);
585 return;
586 }
587
588 pProgram->linked = GL_TRUE;
589
590 /*Free program's active state*/
591 if (pProgram->activeState.attachedShaders)
592 {
593 crHashtableWalk(pProgram->activeState.attachedShaders, crStateFakeDecRefCountCB, NULL);
594 crFreeHashtable(pProgram->activeState.attachedShaders, crStateFreeGLSLShader);
595 pProgram->activeState.attachedShaders = NULL;
596 }
597 for (i=0; i<pProgram->activeState.cAttribs; ++i)
598 {
599 crFree(pProgram->activeState.pAttribs[i].name);
600 }
601 if (pProgram->activeState.pAttribs) crFree(pProgram->activeState.pAttribs);
602
603 /*copy current state to active state*/
604 crMemcpy(&pProgram->activeState, &pProgram->currentState, sizeof(CRGLSLProgramState));
605
606 pProgram->activeState.attachedShaders = crAllocHashtable();
607 if (!pProgram->activeState.attachedShaders)
608 {
609 crWarning("crStateLinkProgram: Out of memory!");
610 return;
611 }
612 crHashtableWalk(pProgram->currentState.attachedShaders, crStateCopyShaderCB, pProgram);
613
614 /*that's not a bug, note the memcpy above*/
615 if (pProgram->activeState.pAttribs)
616 {
617 pProgram->activeState.pAttribs = (CRGLSLAttrib *) crAlloc(pProgram->activeState.cAttribs * sizeof(CRGLSLAttrib));
618 }
619
620 for (i=0; i<pProgram->activeState.cAttribs; ++i)
621 {
622 crMemcpy(&pProgram->activeState.pAttribs[i], &pProgram->currentState.pAttribs[i], sizeof(CRGLSLAttrib));
623 pProgram->activeState.pAttribs[i].name = crStrdup(pProgram->currentState.pAttribs[i].name);
624 }
625
626#ifdef IN_GUEST
627 crStateFreeProgramAttribsLocationCache(pProgram);
628#endif
629
630 crStateFreeProgramUniforms(pProgram);
631}
632
633DECLEXPORT(void) STATE_APIENTRY crStateBindAttribLocation(GLuint program, GLuint index, const char * name)
634{
635 CRGLSLProgram *pProgram = crStateGetProgramObj(program);
636 GLuint i;
637 CRGLSLAttrib *pAttribs;
638
639 if (!pProgram)
640 {
641 crWarning("Unknown program %d", program);
642 return;
643 }
644
645 if (index>=CR_MAX_VERTEX_ATTRIBS)
646 {
647 crWarning("crStateBindAttribLocation: Index too big %d", index);
648 return;
649 }
650
651 for (i=0; i<pProgram->currentState.cAttribs; ++i)
652 {
653 if (!crStrcmp(pProgram->currentState.pAttribs[i].name, name))
654 {
655 pProgram->currentState.pAttribs[i].index = index;
656 return;
657 }
658 }
659
660 pAttribs = (CRGLSLAttrib*) crAlloc((pProgram->currentState.cAttribs+1)*sizeof(CRGLSLAttrib));
661 if (!pAttribs)
662 {
663 crWarning("crStateBindAttribLocation: Out of memory!");
664 return;
665 }
666
667 if (pProgram->currentState.cAttribs)
668 {
669 crMemcpy(&pAttribs[0], &pProgram->currentState.pAttribs[0], pProgram->currentState.cAttribs*sizeof(CRGLSLAttrib));
670 }
671 pAttribs[pProgram->currentState.cAttribs].index = index;
672 pAttribs[pProgram->currentState.cAttribs].name = crStrdup(name);
673
674 pProgram->currentState.cAttribs++;
675 if (pProgram->currentState.pAttribs) crFree(pProgram->currentState.pAttribs);
676 pProgram->currentState.pAttribs = pAttribs;
677}
678
679DECLEXPORT(GLint) STATE_APIENTRY crStateGetUniformSize(GLenum type)
680{
681 GLint size;
682
683 switch (type)
684 {
685 case GL_FLOAT:
686 size = 1;
687 break;
688 case GL_FLOAT_VEC2:
689 size = 2;
690 break;
691 case GL_FLOAT_VEC3:
692 size = 3;
693 break;
694 case GL_FLOAT_VEC4:
695 size = 4;
696 break;
697 case GL_INT:
698 size = 1;
699 break;
700 case GL_INT_VEC2:
701 size = 2;
702 break;
703 case GL_INT_VEC3:
704 size = 3;
705 break;
706 case GL_INT_VEC4:
707 size = 4;
708 break;
709 case GL_BOOL:
710 size = 1;
711 break;
712 case GL_BOOL_VEC2:
713 size = 2;
714 break;
715 case GL_BOOL_VEC3:
716 size = 3;
717 break;
718 case GL_BOOL_VEC4:
719 size = 4;
720 break;
721 case GL_FLOAT_MAT2:
722 size = 8;
723 break;
724 case GL_FLOAT_MAT3:
725 size = 12;
726 break;
727 case GL_FLOAT_MAT4:
728 size = 16;
729 break;
730 case GL_SAMPLER_1D:
731 case GL_SAMPLER_2D:
732 case GL_SAMPLER_3D:
733 case GL_SAMPLER_CUBE:
734 case GL_SAMPLER_1D_SHADOW:
735 case GL_SAMPLER_2D_SHADOW:
736 case GL_SAMPLER_2D_RECT_ARB:
737 case GL_SAMPLER_2D_RECT_SHADOW_ARB:
738 size = 1;
739 break;
740#ifdef CR_OPENGL_VERSION_2_1
741 case GL_FLOAT_MAT2x3:
742 size = 8;
743 break;
744 case GL_FLOAT_MAT2x4:
745 size = 8;
746 break;
747 case GL_FLOAT_MAT3x2:
748 size = 12;
749 break;
750 case GL_FLOAT_MAT3x4:
751 size = 12;
752 break;
753 case GL_FLOAT_MAT4x2:
754 size = 16;
755 break;
756 case GL_FLOAT_MAT4x3:
757 size = 16;
758 break;
759#endif
760 default:
761 crWarning("crStateGetUniformSize: unknown uniform type 0x%x", (GLint)type);
762 size = 16;
763 break;
764 }
765
766 return size;
767}
768
769DECLEXPORT(GLboolean) STATE_APIENTRY crStateIsIntUniform(GLenum type)
770{
771 if (GL_INT==type
772 || GL_INT_VEC2==type
773 || GL_INT_VEC3==type
774 || GL_INT_VEC4==type
775 || GL_BOOL==type
776 || GL_BOOL_VEC2==type
777 || GL_BOOL_VEC3==type
778 || GL_BOOL_VEC4==type
779 || GL_SAMPLER_1D==type
780 || GL_SAMPLER_2D==type
781 || GL_SAMPLER_3D==type
782 || GL_SAMPLER_CUBE==type
783 || GL_SAMPLER_1D_SHADOW==type
784 || GL_SAMPLER_2D_SHADOW==type
785 || GL_SAMPLER_2D_RECT_ARB==type
786 || GL_SAMPLER_2D_RECT_SHADOW_ARB==type)
787 {
788 return GL_TRUE;
789 }
790 else return GL_FALSE;
791}
792
793DECLEXPORT(GLboolean) STATE_APIENTRY crStateIsProgramUniformsCached(GLuint program)
794{
795 CRGLSLProgram *pProgram = crStateGetProgramObj(program);
796
797 if (!pProgram)
798 {
799 WARN(("Unknown program %d", program));
800 return GL_FALSE;
801 }
802
803#ifdef IN_GUEST
804 return pProgram->bUniformsSynced;
805#else
806 WARN(("crStateIsProgramUniformsCached called on host side!!"));
807 return GL_FALSE;
808#endif
809}
810
811DECLEXPORT(GLboolean) STATE_APIENTRY crStateIsProgramAttribsCached(GLuint program)
812{
813 CRGLSLProgram *pProgram = crStateGetProgramObj(program);
814
815 if (!pProgram)
816 {
817 WARN(("Unknown program %d", program));
818 return GL_FALSE;
819 }
820
821#ifdef IN_GUEST
822 return pProgram->bAttribsSynced;
823#else
824 WARN(("crStateIsProgramAttribsCached called on host side!!"));
825 return GL_FALSE;
826#endif
827}
828
829/** @todo one of those functions should ignore uniforms starting with "gl"*/
830
831#ifdef IN_GUEST
832DECLEXPORT(void) STATE_APIENTRY
833crStateGLSLProgramCacheUniforms(GLuint program, GLsizei cbData, GLvoid *pData)
834{
835 CRGLSLProgram *pProgram = crStateGetProgramObj(program);
836 char *pCurrent = pData;
837 GLsizei cbRead, cbName;
838 GLuint i;
839
840 if (!pProgram)
841 {
842 crWarning("Unknown program %d", program);
843 return;
844 }
845
846 if (pProgram->bUniformsSynced)
847 {
848 crWarning("crStateGLSLProgramCacheUniforms: this shouldn't happen!");
849 crStateFreeProgramUniforms(pProgram);
850 }
851
852 if (cbData<(GLsizei)sizeof(GLsizei))
853 {
854 crWarning("crStateGLSLProgramCacheUniforms: data too short");
855 return;
856 }
857
858 pProgram->cUniforms = ((GLsizei*)pCurrent)[0];
859 pCurrent += sizeof(GLsizei);
860 cbRead = sizeof(GLsizei);
861
862 /*crDebug("crStateGLSLProgramCacheUniforms: %i active uniforms", pProgram->cUniforms);*/
863
864 if (pProgram->cUniforms)
865 {
866 pProgram->pUniforms = crAlloc(pProgram->cUniforms*sizeof(CRGLSLUniform));
867 if (!pProgram->pUniforms)
868 {
869 crWarning("crStateGLSLProgramCacheUniforms: no memory");
870 pProgram->cUniforms = 0;
871 return;
872 }
873 }
874
875 for (i=0; i<pProgram->cUniforms; ++i)
876 {
877 cbRead += sizeof(GLuint)+sizeof(GLsizei);
878 if (cbRead>cbData)
879 {
880 crWarning("crStateGLSLProgramCacheUniforms: out of data reading uniform %i", i);
881 return;
882 }
883 pProgram->pUniforms[i].data = NULL;
884 pProgram->pUniforms[i].location = ((GLint*)pCurrent)[0];
885 pCurrent += sizeof(GLint);
886 cbName = ((GLsizei*)pCurrent)[0];
887 pCurrent += sizeof(GLsizei);
888
889 cbRead += cbName;
890 if (cbRead>cbData)
891 {
892 crWarning("crStateGLSLProgramCacheUniforms: out of data reading uniform's name %i", i);
893 return;
894 }
895
896 pProgram->pUniforms[i].name = crStrndup(pCurrent, cbName);
897 pCurrent += cbName;
898
899 /*crDebug("crStateGLSLProgramCacheUniforms: uniform[%i]=%d, %s", i, pProgram->pUniforms[i].location, pProgram->pUniforms[i].name);*/
900 }
901
902 pProgram->bUniformsSynced = GL_TRUE;
903
904 CRASSERT((pCurrent-((char*)pData))==cbRead);
905 CRASSERT(cbRead==cbData);
906}
907
908DECLEXPORT(void) STATE_APIENTRY
909crStateGLSLProgramCacheAttribs(GLuint program, GLsizei cbData, GLvoid *pData)
910{
911 CRGLSLProgram *pProgram = crStateGetProgramObj(program);
912 char *pCurrent = pData;
913 GLsizei cbRead, cbName;
914 GLuint i;
915
916 if (!pProgram)
917 {
918 WARN(("Unknown program %d", program));
919 return;
920 }
921
922 if (pProgram->bAttribsSynced)
923 {
924 WARN(("crStateGLSLProgramCacheAttribs: this shouldn't happen!"));
925 crStateFreeProgramAttribsLocationCache(pProgram);
926 }
927
928 if (cbData<(GLsizei)sizeof(GLsizei))
929 {
930 WARN(("crStateGLSLProgramCacheAttribs: data too short"));
931 return;
932 }
933
934 pProgram->cAttribs = ((GLsizei*)pCurrent)[0];
935 pCurrent += sizeof(GLsizei);
936 cbRead = sizeof(GLsizei);
937
938 crDebug("crStateGLSLProgramCacheAttribs: %i active attribs", pProgram->cAttribs);
939
940 if (pProgram->cAttribs)
941 {
942 pProgram->pAttribs = crAlloc(pProgram->cAttribs*sizeof(CRGLSLAttrib));
943 if (!pProgram->pAttribs)
944 {
945 WARN(("crStateGLSLProgramCacheAttribs: no memory"));
946 pProgram->cAttribs = 0;
947 return;
948 }
949 }
950
951 for (i=0; i<pProgram->cAttribs; ++i)
952 {
953 cbRead += sizeof(GLuint)+sizeof(GLsizei);
954 if (cbRead>cbData)
955 {
956 crWarning("crStateGLSLProgramCacheAttribs: out of data reading attrib %i", i);
957 return;
958 }
959 pProgram->pAttribs[i].index = ((GLint*)pCurrent)[0];
960 pCurrent += sizeof(GLint);
961 cbName = ((GLsizei*)pCurrent)[0];
962 pCurrent += sizeof(GLsizei);
963
964 cbRead += cbName;
965 if (cbRead>cbData)
966 {
967 crWarning("crStateGLSLProgramCacheAttribs: out of data reading attrib's name %i", i);
968 return;
969 }
970
971 pProgram->pAttribs[i].name = crStrndup(pCurrent, cbName);
972 pCurrent += cbName;
973
974 crDebug("crStateGLSLProgramCacheAttribs: attribs[%i]=%d, %s", i, pProgram->pAttribs[i].index, pProgram->pAttribs[i].name);
975 }
976
977 pProgram->bAttribsSynced = GL_TRUE;
978
979 CRASSERT((pCurrent-((char*)pData))==cbRead);
980 CRASSERT(cbRead==cbData);
981}
982#else /* IN_GUEST */
983static GLboolean crStateGLSLProgramCacheOneUniform(GLuint location, GLsizei cbName, GLchar *pName,
984 char **pCurrent, GLsizei *pcbWritten, GLsizei maxcbData)
985{
986 *pcbWritten += sizeof(GLint)+sizeof(GLsizei)+cbName;
987 if (*pcbWritten>maxcbData)
988 {
989 crWarning("crStateGLSLProgramCacheUniforms: buffer too small");
990 crFree(pName);
991 return GL_FALSE;
992 }
993
994 /*crDebug("crStateGLSLProgramCacheUniforms: uniform[%i]=%s.", location, pName);*/
995
996 ((GLint*)*pCurrent)[0] = location;
997 *pCurrent += sizeof(GLint);
998 ((GLsizei*)*pCurrent)[0] = cbName;
999 *pCurrent += sizeof(GLsizei);
1000 crMemcpy(*pCurrent, pName, cbName);
1001 *pCurrent += cbName;
1002
1003 return GL_TRUE;
1004}
1005
1006DECLEXPORT(void) STATE_APIENTRY
1007crStateGLSLProgramCacheUniforms(GLuint program, GLsizei maxcbData, GLsizei *cbData, GLvoid *pData)
1008{
1009 CRGLSLProgram *pProgram = crStateGetProgramObj(program);
1010 GLint maxUniformLen = 0, activeUniforms=0, fakeUniformsCount, i, j;
1011 char *pCurrent = pData;
1012 GLsizei cbWritten;
1013
1014 if (!pProgram)
1015 {
1016 crWarning("Unknown program %d", program);
1017 return;
1018 }
1019
1020 /*
1021 * OpenGL spec says about GL_ACTIVE_UNIFORM_MAX_LENGTH:
1022 * "If no active uniform variable exist, 0 is returned."
1023 */
1024 diff_api.GetProgramiv(pProgram->hwid, GL_ACTIVE_UNIFORM_MAX_LENGTH, &maxUniformLen);
1025 if (maxUniformLen > 0)
1026 diff_api.GetProgramiv(pProgram->hwid, GL_ACTIVE_UNIFORMS, &activeUniforms);
1027
1028 *cbData = 0;
1029
1030 cbWritten = sizeof(GLsizei);
1031 if (cbWritten>maxcbData)
1032 {
1033 crWarning("crStateGLSLProgramCacheUniforms: buffer too small");
1034 return;
1035 }
1036 ((GLsizei*)pCurrent)[0] = activeUniforms;
1037 fakeUniformsCount = activeUniforms;
1038 pCurrent += sizeof(GLsizei);
1039
1040 crDebug("crStateGLSLProgramCacheUniforms: %i active uniforms", activeUniforms);
1041
1042 if (activeUniforms>0)
1043 {
1044 /*+8 to make sure our array uniforms with higher indices and [] will fit in as well*/
1045 GLchar *name = (GLchar *) crAlloc(maxUniformLen+8);
1046 GLenum type;
1047 GLint size;
1048 GLsizei cbName;
1049 GLint location;
1050
1051 if (!name)
1052 {
1053 crWarning("crStateGLSLProgramCacheUniforms: no memory");
1054 return;
1055 }
1056
1057 for (i=0; i<activeUniforms; ++i)
1058 {
1059 diff_api.GetActiveUniform(pProgram->hwid, i, maxUniformLen, &cbName, &size, &type, name);
1060 location = diff_api.GetUniformLocation(pProgram->hwid, name);
1061
1062 if (!crStateGLSLProgramCacheOneUniform(location, cbName, name, &pCurrent, &cbWritten, maxcbData))
1063 return;
1064
1065 /* Only one active uniform variable will be reported for a uniform array by glGetActiveUniform,
1066 * so we insert fake elements for other array elements.
1067 */
1068 if (size!=1)
1069 {
1070 char *pIndexStr = crStrchr(name, '[');
1071 GLint firstIndex=1;
1072 fakeUniformsCount += size;
1073
1074 crDebug("crStateGLSLProgramCacheUniforms: expanding array uniform, size=%i", size);
1075
1076 /*For array uniforms it's valid to query location of 1st element as both uniform and uniform[0].
1077 *The name returned by glGetActiveUniform is driver dependent,
1078 *atleast it's with [0] on win/ati and without [0] on linux/nvidia.
1079 */
1080 if (!pIndexStr)
1081 {
1082 pIndexStr = name+cbName;
1083 firstIndex=0;
1084 }
1085 else
1086 {
1087 cbName = pIndexStr-name;
1088 if (!crStateGLSLProgramCacheOneUniform(location, cbName, name, &pCurrent, &cbWritten, maxcbData))
1089 return;
1090 }
1091
1092 for (j=firstIndex; j<size; ++j)
1093 {
1094 sprintf(pIndexStr, "[%i]", j);
1095 cbName = crStrlen(name);
1096
1097 location = diff_api.GetUniformLocation(pProgram->hwid, name);
1098
1099 if (!crStateGLSLProgramCacheOneUniform(location, cbName, name, &pCurrent, &cbWritten, maxcbData))
1100 return;
1101 }
1102 }
1103 }
1104
1105 crFree(name);
1106 }
1107
1108 if (fakeUniformsCount!=activeUniforms)
1109 {
1110 ((GLsizei*)pData)[0] = fakeUniformsCount;
1111 crDebug("FakeCount %i", fakeUniformsCount);
1112 }
1113
1114 *cbData = cbWritten;
1115
1116 CRASSERT((pCurrent-((char*)pData))==cbWritten);
1117}
1118
1119static GLboolean crStateGLSLProgramCacheOneAttrib(GLuint location, GLsizei cbName, GLchar *pName,
1120 char **pCurrent, GLsizei *pcbWritten, GLsizei maxcbData)
1121{
1122 *pcbWritten += sizeof(GLint)+sizeof(GLsizei)+cbName;
1123 if (*pcbWritten>maxcbData)
1124 {
1125 WARN(("crStateGLSLProgramCacheOneAttrib: buffer too small"));
1126 crFree(pName);
1127 return GL_FALSE;
1128 }
1129
1130 crDebug("crStateGLSLProgramCacheOneAttrib: attrib[%i]=%s.", location, pName);
1131
1132 ((GLint*)*pCurrent)[0] = location;
1133 *pCurrent += sizeof(GLint);
1134 ((GLsizei*)*pCurrent)[0] = cbName;
1135 *pCurrent += sizeof(GLsizei);
1136 crMemcpy(*pCurrent, pName, cbName);
1137 *pCurrent += cbName;
1138
1139 return GL_TRUE;
1140}
1141
1142DECLEXPORT(void) STATE_APIENTRY
1143crStateGLSLProgramCacheAttribs(GLuint program, GLsizei maxcbData, GLsizei *cbData, GLvoid *pData)
1144{
1145 CRGLSLProgram *pProgram = crStateGetProgramObj(program);
1146 GLint maxAttribLen, activeAttribs=0, fakeAttribsCount, i, j;
1147 char *pCurrent = pData;
1148 GLsizei cbWritten;
1149
1150 if (!pProgram)
1151 {
1152 crWarning("Unknown program %d", program);
1153 return;
1154 }
1155
1156 diff_api.GetProgramiv(pProgram->hwid, GL_ACTIVE_ATTRIBUTE_MAX_LENGTH, &maxAttribLen);
1157 diff_api.GetProgramiv(pProgram->hwid, GL_ACTIVE_ATTRIBUTES, &activeAttribs);
1158
1159 *cbData = 0;
1160
1161 cbWritten = sizeof(GLsizei);
1162 if (cbWritten>maxcbData)
1163 {
1164 crWarning("crStateGLSLProgramCacheAttribs: buffer too small");
1165 return;
1166 }
1167 ((GLsizei*)pCurrent)[0] = activeAttribs;
1168 fakeAttribsCount = activeAttribs;
1169 pCurrent += sizeof(GLsizei);
1170
1171 crDebug("crStateGLSLProgramCacheAttribs: %i active attribs", activeAttribs);
1172
1173 if (activeAttribs>0)
1174 {
1175 /*+8 to make sure our array attribs with higher indices and [] will fit in as well*/
1176 GLchar *name = (GLchar *) crAlloc(maxAttribLen+8);
1177 GLenum type;
1178 GLint size;
1179 GLsizei cbName;
1180 GLint location;
1181
1182 if (!name)
1183 {
1184 crWarning("crStateGLSLProgramCacheAttribs: no memory");
1185 return;
1186 }
1187
1188 for (i=0; i<activeAttribs; ++i)
1189 {
1190 diff_api.GetActiveAttrib(pProgram->hwid, i, maxAttribLen, &cbName, &size, &type, name);
1191 location = diff_api.GetAttribLocation(pProgram->hwid, name);
1192
1193 if (!crStateGLSLProgramCacheOneAttrib(location, cbName, name, &pCurrent, &cbWritten, maxcbData))
1194 return;
1195
1196 /* Only one active attrib variable will be reported for a attrib array by glGetActiveAttrib,
1197 * so we insert fake elements for other array elements.
1198 */
1199 if (size!=1)
1200 {
1201 char *pIndexStr = crStrchr(name, '[');
1202 GLint firstIndex=1;
1203 fakeAttribsCount += size;
1204
1205 crDebug("crStateGLSLProgramCacheAttribs: expanding array attrib, size=%i", size);
1206
1207 /*For array attribs it's valid to query location of 1st element as both attrib and attrib[0].
1208 *The name returned by glGetActiveAttrib is driver dependent,
1209 *atleast it's with [0] on win/ati and without [0] on linux/nvidia.
1210 */
1211 if (!pIndexStr)
1212 {
1213 pIndexStr = name+cbName;
1214 firstIndex=0;
1215 }
1216 else
1217 {
1218 cbName = pIndexStr-name;
1219 if (!crStateGLSLProgramCacheOneAttrib(location, cbName, name, &pCurrent, &cbWritten, maxcbData))
1220 return;
1221 }
1222
1223 for (j=firstIndex; j<size; ++j)
1224 {
1225 sprintf(pIndexStr, "[%i]", j);
1226 cbName = crStrlen(name);
1227
1228 location = diff_api.GetAttribLocation(pProgram->hwid, name);
1229
1230 if (!crStateGLSLProgramCacheOneAttrib(location, cbName, name, &pCurrent, &cbWritten, maxcbData))
1231 return;
1232 }
1233 }
1234 }
1235
1236 crFree(name);
1237 }
1238
1239 if (fakeAttribsCount!=activeAttribs)
1240 {
1241 ((GLsizei*)pData)[0] = fakeAttribsCount;
1242 crDebug("FakeCount %i", fakeAttribsCount);
1243 }
1244
1245 *cbData = cbWritten;
1246
1247 CRASSERT((pCurrent-((char*)pData))==cbWritten);
1248}
1249#endif
1250
1251DECLEXPORT(GLint) STATE_APIENTRY crStateGetUniformLocation(GLuint program, const char * name)
1252{
1253#ifdef IN_GUEST
1254 CRGLSLProgram *pProgram = crStateGetProgramObj(program);
1255 GLint result=-1;
1256 GLuint i;
1257
1258 if (!pProgram)
1259 {
1260 crWarning("Unknown program %d", program);
1261 return -1;
1262 }
1263
1264 if (!pProgram->bUniformsSynced)
1265 {
1266 crWarning("crStateGetUniformLocation called for uncached uniforms");
1267 return -1;
1268 }
1269
1270 for (i=0; i<pProgram->cUniforms; ++i)
1271 {
1272 if (!crStrcmp(name, pProgram->pUniforms[i].name))
1273 {
1274 result = pProgram->pUniforms[i].location;
1275 break;
1276 }
1277 }
1278
1279 return result;
1280#else
1281 crWarning("crStateGetUniformLocation called on host side!!");
1282 return -1;
1283#endif
1284}
1285
1286DECLEXPORT(GLint) STATE_APIENTRY crStateGetAttribLocation(GLuint program, const char * name)
1287{
1288#ifdef IN_GUEST
1289 CRGLSLProgram *pProgram = crStateGetProgramObj(program);
1290 GLint result=-1;
1291 GLuint i;
1292
1293 if (!pProgram)
1294 {
1295 WARN(("Unknown program %d", program));
1296 return -1;
1297 }
1298
1299 if (!pProgram->bAttribsSynced)
1300 {
1301 WARN(("crStateGetAttribLocation called for uncached attribs"));
1302 return -1;
1303 }
1304
1305 for (i=0; i<pProgram->cAttribs; ++i)
1306 {
1307 if (!crStrcmp(name, pProgram->pAttribs[i].name))
1308 {
1309 result = pProgram->pAttribs[i].index;
1310 break;
1311 }
1312 }
1313
1314 return result;
1315#else
1316 crWarning("crStateGetAttribLocation called on host side!!");
1317 return -1;
1318#endif
1319}
1320
1321static void crStateGLSLCreateShadersCB(unsigned long key, void *data1, void *data2)
1322{
1323 CRGLSLShader *pShader = (CRGLSLShader*) data1;
1324 CRContext *ctx = (CRContext *) data2;
1325 (void)ctx; (void)key;
1326
1327 pShader->hwid = diff_api.CreateShader(pShader->type);
1328}
1329
1330static void crStateFixAttachedShaderHWIDsCB(unsigned long key, void *data1, void *data2)
1331{
1332 CRGLSLShader *pShader = (CRGLSLShader*) data1;
1333 CRGLSLShader *pRealShader;
1334 CRContext *pCtx = (CRContext *) data2;
1335
1336 pRealShader = (CRGLSLShader *) crHashtableSearch(pCtx->glsl.shaders, key);
1337 CRASSERT(pRealShader);
1338
1339 pShader->hwid = pRealShader->hwid;
1340}
1341
1342static void crStateGLSLSyncShadersCB(unsigned long key, void *data1, void *data2)
1343{
1344 CRGLSLShader *pShader = (CRGLSLShader*) data1;
1345 (void) key;
1346 (void) data2;
1347
1348 if (pShader->source)
1349 {
1350 diff_api.ShaderSource(pShader->hwid, 1, (const char**)&pShader->source, NULL);
1351 if (pShader->compiled)
1352 diff_api.CompileShader(pShader->hwid);
1353 crFree(pShader->source);
1354 pShader->source = NULL;
1355 }
1356
1357 if (pShader->deleted)
1358 diff_api.DeleteShader(pShader->hwid);
1359}
1360
1361static void crStateAttachShaderCB(unsigned long key, void *data1, void *data2)
1362{
1363 CRGLSLShader *pShader = (CRGLSLShader*) data1;
1364 CRGLSLProgram *pProgram = (CRGLSLProgram *) data2;
1365 (void) key;
1366
1367 if (pShader->source)
1368 {
1369 diff_api.ShaderSource(pShader->hwid, 1, (const char**)&pShader->source, NULL);
1370 if (pShader->compiled)
1371 diff_api.CompileShader(pShader->hwid);
1372 }
1373
1374 diff_api.AttachShader(pProgram->hwid, pShader->hwid);
1375}
1376
1377static void crStateDetachShaderCB(unsigned long key, void *data1, void *data2)
1378{
1379 CRGLSLShader *pShader = (CRGLSLShader*) data1;
1380 CRGLSLProgram *pProgram = (CRGLSLProgram *) data2;
1381 (void) key;
1382
1383 diff_api.DetachShader(pProgram->hwid, pShader->hwid);
1384}
1385
1386static void crStateGLSLCreateProgramCB(unsigned long key, void *data1, void *data2)
1387{
1388 CRGLSLProgram *pProgram = (CRGLSLProgram*) data1;
1389 CRContext *ctx = (CRContext *) data2;
1390 GLuint i;
1391 (void)key;
1392
1393 pProgram->hwid = diff_api.CreateProgram();
1394
1395 if (pProgram->linked)
1396 {
1397 CRASSERT(pProgram->activeState.attachedShaders);
1398
1399 crHashtableWalk(pProgram->activeState.attachedShaders, crStateFixAttachedShaderHWIDsCB, ctx);
1400 crHashtableWalk(pProgram->activeState.attachedShaders, crStateAttachShaderCB, pProgram);
1401
1402 for (i=0; i<pProgram->activeState.cAttribs; ++i)
1403 {
1404 diff_api.BindAttribLocation(pProgram->hwid, pProgram->activeState.pAttribs[i].index, pProgram->activeState.pAttribs[i].name);
1405 }
1406
1407 if (pProgram->validated)
1408 diff_api.ValidateProgram(pProgram->hwid);
1409
1410 diff_api.LinkProgram(pProgram->hwid);
1411 }
1412
1413 diff_api.UseProgram(pProgram->hwid);
1414
1415 for (i=0; i<pProgram->cUniforms; ++i)
1416 {
1417 GLint location;
1418 GLfloat *pFdata = (GLfloat*)pProgram->pUniforms[i].data;
1419 GLint *pIdata = (GLint*)pProgram->pUniforms[i].data;
1420
1421 location = diff_api.GetUniformLocation(pProgram->hwid, pProgram->pUniforms[i].name);
1422 switch (pProgram->pUniforms[i].type)
1423 {
1424 case GL_FLOAT:
1425 diff_api.Uniform1fv(location, 1, pFdata);
1426 break;
1427 case GL_FLOAT_VEC2:
1428 diff_api.Uniform2fv(location, 1, pFdata);
1429 break;
1430 case GL_FLOAT_VEC3:
1431 diff_api.Uniform3fv(location, 1, pFdata);
1432 break;
1433 case GL_FLOAT_VEC4:
1434 diff_api.Uniform4fv(location, 1, pFdata);
1435 break;
1436 case GL_INT:
1437 case GL_BOOL:
1438 diff_api.Uniform1iv(location, 1, pIdata);
1439 break;
1440 case GL_INT_VEC2:
1441 case GL_BOOL_VEC2:
1442 diff_api.Uniform2iv(location, 1, pIdata);
1443 break;
1444 case GL_INT_VEC3:
1445 case GL_BOOL_VEC3:
1446 diff_api.Uniform3iv(location, 1, pIdata);
1447 break;
1448 case GL_INT_VEC4:
1449 case GL_BOOL_VEC4:
1450 diff_api.Uniform4iv(location, 1, pIdata);
1451 break;
1452 case GL_FLOAT_MAT2:
1453 diff_api.UniformMatrix2fv(location, 1, GL_FALSE, pFdata);
1454 break;
1455 case GL_FLOAT_MAT3:
1456 diff_api.UniformMatrix3fv(location, 1, GL_FALSE, pFdata);
1457 break;
1458 case GL_FLOAT_MAT4:
1459 diff_api.UniformMatrix4fv(location, 1, GL_FALSE, pFdata);
1460 break;
1461 case GL_SAMPLER_1D:
1462 case GL_SAMPLER_2D:
1463 case GL_SAMPLER_3D:
1464 case GL_SAMPLER_CUBE:
1465 case GL_SAMPLER_1D_SHADOW:
1466 case GL_SAMPLER_2D_SHADOW:
1467 case GL_SAMPLER_2D_RECT_ARB:
1468 case GL_SAMPLER_2D_RECT_SHADOW_ARB:
1469 diff_api.Uniform1iv(location, 1, pIdata);
1470 break;
1471#ifdef CR_OPENGL_VERSION_2_1
1472 case GL_FLOAT_MAT2x3:
1473 diff_api.UniformMatrix2x3fv(location, 1, GL_FALSE, pFdata);
1474 break;
1475 case GL_FLOAT_MAT2x4:
1476 diff_api.UniformMatrix2x4fv(location, 1, GL_FALSE, pFdata);
1477 break;
1478 case GL_FLOAT_MAT3x2:
1479 diff_api.UniformMatrix3x2fv(location, 1, GL_FALSE, pFdata);
1480 break;
1481 case GL_FLOAT_MAT3x4:
1482 diff_api.UniformMatrix3x4fv(location, 1, GL_FALSE, pFdata);
1483 break;
1484 case GL_FLOAT_MAT4x2:
1485 diff_api.UniformMatrix4x2fv(location, 1, GL_FALSE, pFdata);
1486 break;
1487 case GL_FLOAT_MAT4x3:
1488 diff_api.UniformMatrix4x3fv(location, 1, GL_FALSE, pFdata);
1489 break;
1490#endif
1491 default:
1492 crWarning("crStateGLSLCreateProgramCB: unknown uniform type 0x%x", (GLint)pProgram->pUniforms[i].type);
1493 break;
1494 }
1495 crFree(pProgram->pUniforms[i].data);
1496 crFree(pProgram->pUniforms[i].name);
1497 } /*for (i=0; i<pProgram->cUniforms; ++i)*/
1498 if (pProgram->pUniforms) crFree(pProgram->pUniforms);
1499 pProgram->pUniforms = NULL;
1500 pProgram->cUniforms = 0;
1501
1502 crHashtableWalk(pProgram->activeState.attachedShaders, crStateDetachShaderCB, pProgram);
1503 crHashtableWalk(pProgram->currentState.attachedShaders, crStateAttachShaderCB, pProgram);
1504}
1505
1506DECLEXPORT(void) STATE_APIENTRY crStateGLSLSwitch(CRContext *from, CRContext *to)
1507{
1508 GLboolean fForceUseProgramSet = GL_FALSE;
1509 if (to->glsl.bResyncNeeded)
1510 {
1511 to->glsl.bResyncNeeded = GL_FALSE;
1512
1513 crHashtableWalk(to->glsl.shaders, crStateGLSLCreateShadersCB, to);
1514
1515 crHashtableWalk(to->glsl.programs, crStateGLSLCreateProgramCB, to);
1516
1517 /* crStateGLSLCreateProgramCB changes the current program, ensure we have the proper program re-sored */
1518 fForceUseProgramSet = GL_TRUE;
1519
1520 crHashtableWalk(to->glsl.shaders, crStateGLSLSyncShadersCB, NULL);
1521 }
1522
1523 if (to->glsl.activeProgram != from->glsl.activeProgram || fForceUseProgramSet)
1524 {
1525 diff_api.UseProgram(to->glsl.activeProgram ? to->glsl.activeProgram->hwid : 0);
1526 }
1527}
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