aboutsummaryrefslogtreecommitdiffstats
path: root/emulator
diff options
context:
space:
mode:
authorbohu <bohu@google.com>2014-10-28 17:08:44 -0700
committerBo Hu <bohu@google.com>2014-11-18 21:53:45 +0000
commit2f55e596ff1005e7a180e2718ccdb22f8d89726a (patch)
treea5ff2cee573bd9f82a227302d7093ac5d6c80f5d /emulator
parentda28cf0cb266a4f6a0e621807ca415cc123a87ae (diff)
downloadsdk-2f55e596ff1005e7a180e2718ccdb22f8d89726a.zip
sdk-2f55e596ff1005e7a180e2718ccdb22f8d89726a.tar.gz
sdk-2f55e596ff1005e7a180e2718ccdb22f8d89726a.tar.bz2
Properly handle shader deletion
When deleting a shader that is still attached to program, it should not be deleted immediately. Instead, it should be marked for deletion. When a program is deleted, its shaders should be detached. When a shader is detached, it should be deleted if it is marked for deletion. Change-Id: I481dbfe37e3ad4af454574b75d157bdfeb1c9cdd (cherry picked from commit bc42a0598f6e5ffb0ebd646e0bad8d94c50ec193)
Diffstat (limited to 'emulator')
-rw-r--r--emulator/opengl/host/libs/Translator/GLES_V2/GLESv2Imp.cpp49
-rw-r--r--emulator/opengl/host/libs/Translator/GLES_V2/ShaderParser.cpp8
-rw-r--r--emulator/opengl/host/libs/Translator/GLES_V2/ShaderParser.h7
3 files changed, 61 insertions, 3 deletions
diff --git a/emulator/opengl/host/libs/Translator/GLES_V2/GLESv2Imp.cpp b/emulator/opengl/host/libs/Translator/GLES_V2/GLESv2Imp.cpp
index 81f867f..83e263d 100644
--- a/emulator/opengl/host/libs/Translator/GLES_V2/GLESv2Imp.cpp
+++ b/emulator/opengl/host/libs/Translator/GLES_V2/GLESv2Imp.cpp
@@ -116,6 +116,27 @@ GL_APICALL GLESiface* __translator_getIfaces(EGLiface* eglIface){
}
+static void s_attachShader(GLEScontext* ctx, GLuint program, GLuint shader) {
+ if (ctx && program && shader && ctx->shareGroup().Ptr()) {
+ ObjectDataPtr shaderData = ctx->shareGroup()->getObjectData(SHADER,shader);
+ if (!shaderData.Ptr()) return;
+ ShaderParser* shaderParser = (ShaderParser*)shaderData.Ptr();
+ shaderParser->setAttachedProgram(program);
+ }
+}
+
+static void s_detachShader(GLEScontext* ctx, GLuint shader) {
+ if (ctx && shader && ctx->shareGroup().Ptr()) {
+ ObjectDataPtr shaderData = ctx->shareGroup()->getObjectData(SHADER,shader);
+ if (!shaderData.Ptr()) return;
+ ShaderParser* shaderParser = (ShaderParser*)shaderData.Ptr();
+ shaderParser->setAttachedProgram(0);
+ if (shaderParser->getDeleteStatus()) {
+ ctx->shareGroup()->deleteName(SHADER, shader);
+ }
+ }
+}
+
static ObjectLocalName TextureLocalName(GLenum target,unsigned int tex) {
GET_CTX_RET(0);
return (tex!=0? tex : ctx->getDefaultTextureName(target));
@@ -165,6 +186,7 @@ GL_APICALL void GL_APIENTRY glAttachShader(GLuint program, GLuint shader){
ProgramData* pData = (ProgramData*)programData.Ptr();
SET_ERROR_IF((pData->getAttachedShader(shaderType)!=0), GL_INVALID_OPERATION);
pData->attachShader(shader,shaderType);
+ s_attachShader(ctx, program, shader);
ctx->dispatcher().glAttachShader(globalProgramName,globalShaderName);
}
}
@@ -493,6 +515,12 @@ GL_APICALL void GL_APIENTRY glDeleteProgram(GLuint program){
if(program && ctx->shareGroup().Ptr()) {
const GLuint globalProgramName = ctx->shareGroup()->getGlobalName(SHADER,program);
SET_ERROR_IF(!globalProgramName, GL_INVALID_VALUE);
+
+ ObjectDataPtr programData = ctx->shareGroup()->getObjectData(SHADER,program);
+ ProgramData* pData = (ProgramData*)programData.Ptr();
+ s_detachShader(ctx, pData->getAttachedVertexShader());
+ s_detachShader(ctx, pData->getAttachedFragmentShader());
+
ctx->shareGroup()->deleteName(SHADER,program);
ctx->dispatcher().glDeleteProgram(globalProgramName);
}
@@ -503,7 +531,15 @@ GL_APICALL void GL_APIENTRY glDeleteShader(GLuint shader){
if(shader && ctx->shareGroup().Ptr()) {
const GLuint globalShaderName = ctx->shareGroup()->getGlobalName(SHADER,shader);
SET_ERROR_IF(!globalShaderName, GL_INVALID_VALUE);
- ctx->shareGroup()->deleteName(SHADER,shader);
+ ObjectDataPtr objData = ctx->shareGroup()->getObjectData(SHADER,shader);
+ SET_ERROR_IF(!objData.Ptr() ,GL_INVALID_OPERATION);
+ SET_ERROR_IF(objData.Ptr()->getDataType()!=SHADER_DATA,GL_INVALID_OPERATION);
+ ShaderParser* sp = (ShaderParser*)objData.Ptr();
+ if (sp->getAttachedProgram()) {
+ sp->setDeleteStatus(true);
+ } else {
+ ctx->shareGroup()->deleteName(SHADER,shader);
+ }
ctx->dispatcher().glDeleteShader(globalShaderName);
}
@@ -538,6 +574,8 @@ GL_APICALL void GL_APIENTRY glDetachShader(GLuint program, GLuint shader){
SET_ERROR_IF(!programData->isAttached(shader),GL_INVALID_OPERATION);
programData->detachShader(shader);
+ s_detachShader(ctx, shader);
+
ctx->dispatcher().glDetachShader(globalProgramName,globalShaderName);
}
}
@@ -1235,6 +1273,15 @@ GL_APICALL void GL_APIENTRY glGetShaderiv(GLuint shader, GLenum pname, GLint* p
GET_CTX();
if(ctx->shareGroup().Ptr()) {
const GLuint globalShaderName = ctx->shareGroup()->getGlobalName(SHADER,shader);
+ if (pname == GL_DELETE_STATUS) {
+ SET_ERROR_IF(globalShaderName == 0, GL_INVALID_VALUE);
+ ObjectDataPtr objData = ctx->shareGroup()->getObjectData(SHADER,shader);
+ SET_ERROR_IF(!objData.Ptr() ,GL_INVALID_VALUE);
+ SET_ERROR_IF(objData.Ptr()->getDataType()!=SHADER_DATA,GL_INVALID_VALUE);
+ ShaderParser* sp = (ShaderParser*)objData.Ptr();
+ params[0] = (sp->getDeleteStatus()) ? GL_TRUE : GL_FALSE;
+ return;
+ }
SET_ERROR_IF(globalShaderName==0, GL_INVALID_VALUE);
switch(pname) {
case GL_INFO_LOG_LENGTH:
diff --git a/emulator/opengl/host/libs/Translator/GLES_V2/ShaderParser.cpp b/emulator/opengl/host/libs/Translator/GLES_V2/ShaderParser.cpp
index 9bbedbf..ca17514 100644
--- a/emulator/opengl/host/libs/Translator/GLES_V2/ShaderParser.cpp
+++ b/emulator/opengl/host/libs/Translator/GLES_V2/ShaderParser.cpp
@@ -21,7 +21,9 @@
ShaderParser::ShaderParser():ObjectData(SHADER_DATA),
m_type(0),
m_originalSrc(NULL),
- m_parsedLines(NULL) {
+ m_parsedLines(NULL),
+ m_deleteStatus(false),
+ m_program(0) {
m_infoLog = new GLchar[1];
m_infoLog[0] = '\0';
};
@@ -29,7 +31,9 @@ ShaderParser::ShaderParser():ObjectData(SHADER_DATA),
ShaderParser::ShaderParser(GLenum type):ObjectData(SHADER_DATA),
m_type(type),
m_originalSrc(NULL),
- m_parsedLines(NULL) {
+ m_parsedLines(NULL),
+ m_deleteStatus(false),
+ m_program(0) {
m_infoLog = new GLchar[1];
m_infoLog[0] = '\0';
diff --git a/emulator/opengl/host/libs/Translator/GLES_V2/ShaderParser.h b/emulator/opengl/host/libs/Translator/GLES_V2/ShaderParser.h
index 7b538c3..6da5476 100644
--- a/emulator/opengl/host/libs/Translator/GLES_V2/ShaderParser.h
+++ b/emulator/opengl/host/libs/Translator/GLES_V2/ShaderParser.h
@@ -35,6 +35,11 @@ public:
void setInfoLog(GLchar * infoLog);
GLchar* getInfoLog();
+ void setDeleteStatus(bool val) { m_deleteStatus = val; }
+ bool getDeleteStatus() const { return m_deleteStatus; }
+
+ void setAttachedProgram(GLuint program) { m_program = program; }
+ GLuint getAttachedProgram() const { return m_program; }
private:
void parseOriginalSrc();
void parseGLSLversion();
@@ -50,5 +55,7 @@ private:
std::string m_parsedSrc;
GLchar* m_parsedLines;
GLchar* m_infoLog;
+ bool m_deleteStatus;
+ GLuint m_program;
};
#endif