/* $Id$ */
/** @file
* VBox OpenGL: GLSL state tracking
*/
/*
* Copyright (C) 2009-2012 Oracle Corporation
*
* This file is part of VirtualBox Open Source Edition (OSE), as
* available from http://www.virtualbox.org. This file is free software;
* General Public License (GPL) as published by the Free Software
* Foundation, in version 2 as it comes in the "COPYING" file of the
* VirtualBox OSE distribution. VirtualBox OSE is distributed in the
* hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
*/
#include "state.h"
#include "state/cr_statetypes.h"
#include "state/cr_statefuncs.h"
#include "state_internals.h"
#include "cr_mem.h"
#include "cr_string.h"
{
CRContext *g = GetCurrentContext();
if (!g)
{
crWarning("crStateGetShaderObj called without current ctx");
}
}
{
CRContext *g = GetCurrentContext();
if (!g)
{
crWarning("crStateGetProgramObj called without current ctx");
}
}
{
}
#ifdef IN_GUEST
{
}
#endif
{
GLuint i;
{
}
{
}
#ifdef IN_GUEST
#endif
}
{
GLuint i;
{
}
#ifdef IN_GUEST
#endif
}
{
{
CRContext *g = GetCurrentContext();
}
}
{
(void) key;
if (pRealShader)
{
}
else
{
crWarning("crStateFakeDecRefCountCB: NULL pRealShader");
}
}
{
{
CRContext *g = GetCurrentContext();
}
}
{
{
crWarning("crStateGLSLInit: Out of memory!");
return;
}
}
{
CRContext *g = GetCurrentContext();
/*@todo: hack to allow crStateFreeGLSLProgram to work correctly,
as the current context isn't the one being destroyed*/
#ifdef CHROMIUM_THREADSAFE
VBoxTlsRefAddRef(ctx); /* <- this is a hack to avoid subsequent SetCurrentContext(g) do recursive Destroy for ctx */
if (g)
VBoxTlsRefAddRef(g); /* <- ensure the g is not destroyed by the following SetCurrentContext call */
#else
#endif
#ifdef CHROMIUM_THREADSAFE
if (g)
#else
__currentContext = g;
#endif
}
{
#ifdef IN_GUEST
#endif
}
{
#ifdef IN_GUEST
#endif
}
{
(void) key;
}
{
(void) key;
}
{
CRContext *g = GetCurrentContext();
}
{
CRContext *g = GetCurrentContext();
}
{
if (hwId)
{
}
else
{
}
return hwId;
}
{
CRContext *g = GetCurrentContext();
#ifdef IN_GUEST
#else
/* the proogram and shader names must not intersect because DeleteObjectARB must distinguish between them
* see crStateDeleteObjectARB
* this is why use programs table for shader keys allocation */
if (!stateId)
{
crWarning("failed to allocate program key");
return 0;
}
#endif
if (!pShader)
{
crWarning("crStateCreateShader: Out of memory!");
return 0;
}
return stateId;
}
{
CRContext *g = GetCurrentContext();
#ifdef IN_GUEST
if (pProgram)
{
}
#else
if (!stateId)
{
crWarning("failed to allocate program key");
return 0;
}
#endif
if (!pProgram)
{
crWarning("crStateCreateProgram: Out of memory!");
return 0;
}
#ifdef IN_GUEST
#endif
return stateId;
}
{
if (!pShader)
{
return;
}
}
{
crError("Unexpected Program id");
}
{
if (!pShader)
{
return;
}
{
CRContext *g = GetCurrentContext();
/* since we use programs table for key allocation key allocation, we need to
* free the key in the programs table.
* See comment in crStateCreateShader */
}
}
{
if (!pProgram)
{
return;
}
{
/*shader already attached to this program*/
return;
}
if (!pShader)
{
return;
}
}
{
if (!pProgram)
{
return;
}
if (!pShader)
{
return;
}
{
CRContext *g = GetCurrentContext();
}
}
{
CRContext *g = GetCurrentContext();
if (program>0)
{
if (!pProgram)
{
return;
}
}
else
{
}
}
{
CRContext *g = GetCurrentContext();
if (!pProgram)
{
return;
}
{
}
}
{
if (!pProgram)
{
return;
}
}
{
pRealShader->refCount++;
if (!pShader)
{
crWarning("crStateCopyShaderCB: Out of memory!");
return;
}
if (sLen>0)
{
}
}
{
GLuint i;
if (!pProgram)
{
return;
}
/*Free program's active state*/
{
}
{
}
/*copy current state to active state*/
{
crWarning("crStateLinkProgram: Out of memory!");
return;
}
/*that's not a bug, note the memcpy above*/
{
pProgram->activeState.pAttribs = (CRGLSLAttrib *) crAlloc(pProgram->activeState.cAttribs * sizeof(CRGLSLAttrib));
}
{
crMemcpy(&pProgram->activeState.pAttribs[i], &pProgram->currentState.pAttribs[i], sizeof(CRGLSLAttrib));
}
#ifdef IN_GUEST
#endif
}
DECLEXPORT(void) STATE_APIENTRY crStateBindAttribLocation(GLuint program, GLuint index, const char * name)
{
GLuint i;
if (!pProgram)
{
return;
}
if (index>=CR_MAX_VERTEX_ATTRIBS)
{
return;
}
{
{
return;
}
}
if (!pAttribs)
{
crWarning("crStateBindAttribLocation: Out of memory!");
return;
}
{
crMemcpy(&pAttribs[0], &pProgram->currentState.pAttribs[0], pProgram->currentState.cAttribs*sizeof(CRGLSLAttrib));
}
}
{
switch (type)
{
case GL_FLOAT:
size = 1;
break;
case GL_FLOAT_VEC2:
size = 2;
break;
case GL_FLOAT_VEC3:
size = 3;
break;
case GL_FLOAT_VEC4:
size = 4;
break;
case GL_INT:
size = 1;
break;
case GL_INT_VEC2:
size = 2;
break;
case GL_INT_VEC3:
size = 3;
break;
case GL_INT_VEC4:
size = 4;
break;
case GL_BOOL:
size = 1;
break;
case GL_BOOL_VEC2:
size = 2;
break;
case GL_BOOL_VEC3:
size = 3;
break;
case GL_BOOL_VEC4:
size = 4;
break;
case GL_FLOAT_MAT2:
size = 8;
break;
case GL_FLOAT_MAT3:
size = 12;
break;
case GL_FLOAT_MAT4:
size = 16;
break;
case GL_SAMPLER_1D:
case GL_SAMPLER_2D:
case GL_SAMPLER_3D:
case GL_SAMPLER_CUBE:
case GL_SAMPLER_1D_SHADOW:
case GL_SAMPLER_2D_SHADOW:
case GL_SAMPLER_2D_RECT_ARB:
size = 1;
break;
#ifdef CR_OPENGL_VERSION_2_1
case GL_FLOAT_MAT2x3:
size = 8;
break;
case GL_FLOAT_MAT2x4:
size = 8;
break;
case GL_FLOAT_MAT3x2:
size = 12;
break;
case GL_FLOAT_MAT3x4:
size = 12;
break;
case GL_FLOAT_MAT4x2:
size = 16;
break;
case GL_FLOAT_MAT4x3:
size = 16;
break;
#endif
default:
size = 16;
break;
}
return size;
}
{
|| GL_INT_VEC2==type
|| GL_INT_VEC3==type
|| GL_INT_VEC4==type
|| GL_BOOL_VEC2==type
|| GL_BOOL_VEC3==type
|| GL_BOOL_VEC4==type
|| GL_SAMPLER_1D==type
|| GL_SAMPLER_2D==type
|| GL_SAMPLER_3D==type
|| GL_SAMPLER_CUBE==type
{
return GL_TRUE;
}
else return GL_FALSE;
}
{
if (!pProgram)
{
return GL_FALSE;
}
#ifdef IN_GUEST
return pProgram->bUniformsSynced;
#else
WARN(("crStateIsProgramUniformsCached called on host side!!"));
return GL_FALSE;
#endif
}
{
if (!pProgram)
{
return GL_FALSE;
}
#ifdef IN_GUEST
return pProgram->bAttribsSynced;
#else
WARN(("crStateIsProgramAttribsCached called on host side!!"));
return GL_FALSE;
#endif
}
/*@todo: one of those functions should ignore uniforms starting with "gl"*/
#ifdef IN_GUEST
DECLEXPORT(void) STATE_APIENTRY
{
GLuint i;
if (!pProgram)
{
return;
}
if (pProgram->bUniformsSynced)
{
crWarning("crStateGLSLProgramCacheUniforms: this shouldn't happen!");
}
{
crWarning("crStateGLSLProgramCacheUniforms: data too short");
return;
}
//crDebug("crStateGLSLProgramCacheUniforms: %i active uniforms", pProgram->cUniforms);
{
{
crWarning("crStateGLSLProgramCacheUniforms: no memory");
return;
}
}
{
{
crWarning("crStateGLSLProgramCacheUniforms: out of data reading uniform %i", i);
return;
}
{
crWarning("crStateGLSLProgramCacheUniforms: out of data reading uniform's name %i", i);
return;
}
//crDebug("crStateGLSLProgramCacheUniforms: uniform[%i]=%d, %s", i, pProgram->pUniforms[i].location, pProgram->pUniforms[i].name);
}
}
DECLEXPORT(void) STATE_APIENTRY
{
GLuint i;
if (!pProgram)
{
return;
}
if (pProgram->bAttribsSynced)
{
WARN(("crStateGLSLProgramCacheAttribs: this shouldn't happen!"));
}
{
WARN(("crStateGLSLProgramCacheAttribs: data too short"));
return;
}
{
{
WARN(("crStateGLSLProgramCacheAttribs: no memory"));
return;
}
}
{
{
crWarning("crStateGLSLProgramCacheAttribs: out of data reading attrib %i", i);
return;
}
{
crWarning("crStateGLSLProgramCacheAttribs: out of data reading attrib's name %i", i);
return;
}
crDebug("crStateGLSLProgramCacheAttribs: attribs[%i]=%d, %s", i, pProgram->pAttribs[i].index, pProgram->pAttribs[i].name);
}
}
#else /* IN_GUEST */
{
if (*pcbWritten>maxcbData)
{
crWarning("crStateGLSLProgramCacheUniforms: buffer too small");
return GL_FALSE;
}
//crDebug("crStateGLSLProgramCacheUniforms: uniform[%i]=%s.", location, pName);
return GL_TRUE;
}
DECLEXPORT(void) STATE_APIENTRY
{
if (!pProgram)
{
return;
}
*cbData = 0;
{
crWarning("crStateGLSLProgramCacheUniforms: buffer too small");
return;
}
if (activeUniforms>0)
{
/*+8 to make sure our array uniforms with higher indices and [] will fit in as well*/
if (!name)
{
crWarning("crStateGLSLProgramCacheUniforms: no memory");
return;
}
for (i=0; i<activeUniforms; ++i)
{
return;
/* Only one active uniform variable will be reported for a uniform array by glGetActiveUniform,
* so we insert fake elements for other array elements.
*/
if (size!=1)
{
/*For array uniforms it's valid to query location of 1st element as both uniform and uniform[0].
*The name returned by glGetActiveUniform is driver dependent,
*/
if (!pIndexStr)
{
firstIndex=0;
}
else
{
return;
}
for (j=firstIndex; j<size; ++j)
{
return;
}
}
}
}
{
}
}
{
if (*pcbWritten>maxcbData)
{
WARN(("crStateGLSLProgramCacheOneAttrib: buffer too small"));
return GL_FALSE;
}
return GL_TRUE;
}
DECLEXPORT(void) STATE_APIENTRY
{
if (!pProgram)
{
return;
}
*cbData = 0;
{
crWarning("crStateGLSLProgramCacheAttribs: buffer too small");
return;
}
if (activeAttribs>0)
{
/*+8 to make sure our array attribs with higher indices and [] will fit in as well*/
if (!name)
{
crWarning("crStateGLSLProgramCacheAttribs: no memory");
return;
}
for (i=0; i<activeAttribs; ++i)
{
return;
/* Only one active attrib variable will be reported for a attrib array by glGetActiveAttrib,
* so we insert fake elements for other array elements.
*/
if (size!=1)
{
fakeAttribsCount += size;
/*For array attribs it's valid to query location of 1st element as both attrib and attrib[0].
*The name returned by glGetActiveAttrib is driver dependent,
*/
if (!pIndexStr)
{
firstIndex=0;
}
else
{
return;
}
for (j=firstIndex; j<size; ++j)
{
return;
}
}
}
}
{
}
}
#endif
{
#ifdef IN_GUEST
GLuint i;
if (!pProgram)
{
return -1;
}
if (!pProgram->bUniformsSynced)
{
crWarning("crStateGetUniformLocation called for uncached uniforms");
return -1;
}
{
{
break;
}
}
return result;
#else
crWarning("crStateGetUniformLocation called on host side!!");
return -1;
#endif
}
{
#ifdef IN_GUEST
GLuint i;
if (!pProgram)
{
return -1;
}
if (!pProgram->bAttribsSynced)
{
WARN(("crStateGetAttribLocation called for uncached attribs"));
return -1;
}
{
{
break;
}
}
return result;
#else
crWarning("crStateGetAttribLocation called on host side!!");
return -1;
#endif
}
{
}
{
}
{
(void) key;
(void) data2;
{
}
}
{
(void) key;
{
}
}
{
(void) key;
}
{
GLuint i;
{
{
diff_api.BindAttribLocation(pProgram->hwid, pProgram->activeState.pAttribs[i].index, pProgram->activeState.pAttribs[i].name);
}
}
{
{
case GL_FLOAT:
break;
case GL_FLOAT_VEC2:
break;
case GL_FLOAT_VEC3:
break;
case GL_FLOAT_VEC4:
break;
case GL_INT:
case GL_BOOL:
break;
case GL_INT_VEC2:
case GL_BOOL_VEC2:
break;
case GL_INT_VEC3:
case GL_BOOL_VEC3:
break;
case GL_INT_VEC4:
case GL_BOOL_VEC4:
break;
case GL_FLOAT_MAT2:
break;
case GL_FLOAT_MAT3:
break;
case GL_FLOAT_MAT4:
break;
case GL_SAMPLER_1D:
case GL_SAMPLER_2D:
case GL_SAMPLER_3D:
case GL_SAMPLER_CUBE:
case GL_SAMPLER_1D_SHADOW:
case GL_SAMPLER_2D_SHADOW:
case GL_SAMPLER_2D_RECT_ARB:
break;
#ifdef CR_OPENGL_VERSION_2_1
case GL_FLOAT_MAT2x3:
break;
case GL_FLOAT_MAT2x4:
break;
case GL_FLOAT_MAT3x2:
break;
case GL_FLOAT_MAT3x4:
break;
case GL_FLOAT_MAT4x2:
break;
case GL_FLOAT_MAT4x3:
break;
#endif
default:
crWarning("crStateGLSLCreateProgramCB: unknown uniform type 0x%x", (GLint)pProgram->pUniforms[i].type);
break;
}
} /*for (i=0; i<pProgram->cUniforms; ++i)*/
}
{
{
/* crStateGLSLCreateProgramCB changes the current program, ensure we have the proper program re-sored */
}
{
}
}