From 3c457bda2f70aec527f220b57be77947815ed2a0 Mon Sep 17 00:00:00 2001 From: Liran Date: Sun, 17 Jul 2011 16:20:41 +0300 Subject: [PATCH] GLES2 translaotr: fix glLinkProgram and object names Do not allow glLinkProgram to succeed if only one shader type has been attached to the program, GL allows this, but GLES2 does not. added state tracking for program objects to check which shaders are attached to the program object. add a way to define object data type being held for each object in objectNameManager ProgramData and ShaderParser are both valid objectData for objects in SHADER namespace we need a way to determine object type to generate correct errors Change-Id: Ic232549df0bb6daf6ec528cb039482cd68e896bb --- .../libs/Translator/GLES_CM/GLEScmImp.cpp | 6 +- .../host/libs/Translator/GLES_V2/Android.mk | 1 + .../libs/Translator/GLES_V2/GLESv2Imp.cpp | 55 ++++++++++++- .../libs/Translator/GLES_V2/ProgramData.cpp | 82 +++++++++++++++++++ .../libs/Translator/GLES_V2/ProgramData.h | 40 +++++++++ .../libs/Translator/GLES_V2/ShaderParser.cpp | 12 ++- .../libs/Translator/GLES_V2/ShaderParser.h | 1 + .../Translator/include/GLcommon/GLESbuffer.h | 2 +- .../include/GLcommon/GLESvalidate.h | 2 +- .../include/GLcommon/TranslatorIfaces.h | 9 +- .../libs/Translator/include/GLcommon/gldefs.h | 6 +- .../include/GLcommon/objectNameManager.h | 17 +++- 12 files changed, 215 insertions(+), 18 deletions(-) create mode 100644 tools/emulator/opengl/host/libs/Translator/GLES_V2/ProgramData.cpp create mode 100644 tools/emulator/opengl/host/libs/Translator/GLES_V2/ProgramData.h diff --git a/tools/emulator/opengl/host/libs/Translator/GLES_CM/GLEScmImp.cpp b/tools/emulator/opengl/host/libs/Translator/GLES_CM/GLEScmImp.cpp index 592265226..68aa2a839 100644 --- a/tools/emulator/opengl/host/libs/Translator/GLES_CM/GLEScmImp.cpp +++ b/tools/emulator/opengl/host/libs/Translator/GLES_CM/GLEScmImp.cpp @@ -793,7 +793,7 @@ GL_API void GL_APIENTRY glGetFixedv( GLenum pname, GLfixed *params) { for (int i=0; i extern "C" { @@ -128,6 +129,17 @@ GL_APICALL void GL_APIENTRY glAttachShader(GLuint program, GLuint shader){ SET_ERROR_IF(globalProgramName==0, GL_INVALID_VALUE); const GLuint globalShaderName = thrd->shareGroup->getGlobalName(SHADER,shader); SET_ERROR_IF(globalShaderName==0, GL_INVALID_VALUE); + + ObjectDataPtr programData = thrd->shareGroup->getObjectData(SHADER,program); + ObjectDataPtr shaderData = thrd->shareGroup->getObjectData(SHADER,shader); + SET_ERROR_IF(!shaderData.Ptr() || !programData.Ptr() ,GL_INVALID_OPERATION); + SET_ERROR_IF(!(shaderData.Ptr()->getDataType() ==SHADER_DATA) || + !(programData.Ptr()->getDataType()==PROGRAM_DATA) ,GL_INVALID_OPERATION); + + GLenum shaderType = ((ShaderParser*)shaderData.Ptr())->getType(); + ProgramData* pData = (ProgramData*)programData.Ptr(); + SET_ERROR_IF((pData->getAttachedShader(shaderType)!=0), GL_INVALID_OPERATION); + pData->attachShader(shader,shaderType); ctx->dispatcher().glAttachShader(globalProgramName,globalShaderName); } } @@ -319,8 +331,10 @@ GL_APICALL GLuint GL_APIENTRY glCreateProgram(void){ GET_CTX_RET(0); const GLuint globalProgramName = ctx->dispatcher().glCreateProgram(); if(thrd->shareGroup.Ptr() && globalProgramName) { + ProgramData* programInfo = new ProgramData(); const GLuint localProgramName = thrd->shareGroup->genName(SHADER, 0, true); thrd->shareGroup->replaceGlobalName(SHADER,localProgramName,globalProgramName); + thrd->shareGroup->setObjectData(SHADER,localProgramName,ObjectDataPtr(programInfo)); return localProgramName; } if(globalProgramName){ @@ -400,7 +414,7 @@ GL_APICALL void GL_APIENTRY glDeleteProgram(GLuint program){ GET_CTX(); if(program && thrd->shareGroup.Ptr()) { const GLuint globalProgramName = thrd->shareGroup->getGlobalName(SHADER,program); - SET_ERROR_IF(!globalProgramName,GL_INVALID_VALUE); + SET_ERROR_IF(!globalProgramName, GL_INVALID_VALUE); thrd->shareGroup->deleteName(SHADER,program); ctx->dispatcher().glDeleteProgram(globalProgramName); } @@ -410,7 +424,7 @@ GL_APICALL void GL_APIENTRY glDeleteShader(GLuint shader){ GET_CTX(); if(shader && thrd->shareGroup.Ptr()) { const GLuint globalShaderName = thrd->shareGroup->getGlobalName(SHADER,shader); - SET_ERROR_IF(!globalShaderName,GL_INVALID_VALUE); + SET_ERROR_IF(!globalShaderName, GL_INVALID_VALUE); thrd->shareGroup->deleteName(SHADER,shader); ctx->dispatcher().glDeleteShader(globalShaderName); } @@ -437,6 +451,15 @@ GL_APICALL void GL_APIENTRY glDetachShader(GLuint program, GLuint shader){ SET_ERROR_IF(globalProgramName==0, GL_INVALID_VALUE); const GLuint globalShaderName = thrd->shareGroup->getGlobalName(SHADER,shader); SET_ERROR_IF(globalShaderName==0, GL_INVALID_VALUE); + + ObjectDataPtr objData = thrd->shareGroup->getObjectData(SHADER,program); + SET_ERROR_IF(!objData.Ptr(),GL_INVALID_OPERATION); + SET_ERROR_IF(!(objData.Ptr()->getDataType()==PROGRAM_DATA) ,GL_INVALID_OPERATION); + + ProgramData* programData = (ProgramData*)objData.Ptr(); + SET_ERROR_IF(!programData->isAttached(shader),GL_INVALID_OPERATION); + programData->detachShader(shader); + ctx->dispatcher().glDetachShader(globalProgramName,globalShaderName); } } @@ -858,7 +881,19 @@ GL_APICALL void GL_APIENTRY glGetProgramiv(GLuint program, GLenum pname, GLint* if(thrd->shareGroup.Ptr()) { const GLuint globalProgramName = thrd->shareGroup->getGlobalName(SHADER,program); SET_ERROR_IF(globalProgramName==0, GL_INVALID_VALUE); - ctx->dispatcher().glGetProgramiv(globalProgramName,pname,params); + switch(pname) { + case GL_LINK_STATUS: + { + ObjectDataPtr objData = thrd->shareGroup->getObjectData(SHADER,program); + SET_ERROR_IF(!objData.Ptr() ,GL_INVALID_OPERATION); + SET_ERROR_IF(objData.Ptr()->getDataType()!=PROGRAM_DATA,GL_INVALID_OPERATION); + ProgramData* programData = (ProgramData*)objData.Ptr(); + params[0] = programData->getLinkStatus(); + } + break; + default: + ctx->dispatcher().glGetProgramiv(globalProgramName,pname,params); + } } } @@ -925,6 +960,7 @@ GL_APICALL void GL_APIENTRY glGetShaderSource(GLuint shader, GLsizei bufsize, G SET_ERROR_IF(globalShaderName == 0,GL_INVALID_VALUE); ObjectDataPtr objData = thrd->shareGroup->getObjectData(SHADER,shader); SET_ERROR_IF(!objData.Ptr(),GL_INVALID_OPERATION); + SET_ERROR_IF(objData.Ptr()->getDataType()!=SHADER_DATA,GL_INVALID_OPERATION); const char* src = ((ShaderParser*)objData.Ptr())->getOriginalSrc(); int srcLength = strlen(src); @@ -1155,10 +1191,20 @@ GL_APICALL void GL_APIENTRY glLineWidth(GLfloat width){ GL_APICALL void GL_APIENTRY glLinkProgram(GLuint program){ GET_CTX(); + GLint linkStatus = GL_FALSE; if(thrd->shareGroup.Ptr()) { const GLuint globalProgramName = thrd->shareGroup->getGlobalName(SHADER,program); SET_ERROR_IF(globalProgramName==0, GL_INVALID_VALUE); - ctx->dispatcher().glLinkProgram(globalProgramName); + + ObjectDataPtr objData = thrd->shareGroup->getObjectData(SHADER,program); + SET_ERROR_IF(!objData.Ptr(), GL_INVALID_OPERATION); + SET_ERROR_IF(objData.Ptr()->getDataType()!=PROGRAM_DATA, GL_INVALID_OPERATION); + ProgramData* programData = (ProgramData*)objData.Ptr(); + if (programData->getAttachedVertexShader()!=0 && programData->getAttachedFragmentShader()!=0) { + ctx->dispatcher().glLinkProgram(globalProgramName); + ctx->dispatcher().glGetProgramiv(globalProgramName,GL_LINK_STATUS,&linkStatus); + } + programData->setLinkStatus(linkStatus); } } @@ -1229,6 +1275,7 @@ GL_APICALL void GL_APIENTRY glShaderSource(GLuint shader, GLsizei count, const SET_ERROR_IF(globalShaderName == 0,GL_INVALID_VALUE); ObjectDataPtr objData = thrd->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(); sp->setSrc(ctx->glslVersion(),count,string,length); ctx->dispatcher().glShaderSource(globalShaderName,1,sp->parsedLines(),NULL); diff --git a/tools/emulator/opengl/host/libs/Translator/GLES_V2/ProgramData.cpp b/tools/emulator/opengl/host/libs/Translator/GLES_V2/ProgramData.cpp new file mode 100644 index 000000000..b3e4a1e7e --- /dev/null +++ b/tools/emulator/opengl/host/libs/Translator/GLES_V2/ProgramData.cpp @@ -0,0 +1,82 @@ +/* +* Copyright (C) 2011 The Android Open Source Project +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ +#include +#include +#include "ProgramData.h" + +ProgramData::ProgramData() : ObjectData(PROGRAM_DATA), + AttachedVertexShader(0), + AttachedFragmentShader(0), + LinkStatus(GL_FALSE) {} + +ProgramData::~ProgramData () {}; + +GLuint ProgramData::getAttachedVertexShader() { + return AttachedVertexShader; +} + +GLuint ProgramData::getAttachedFragmentShader() { + return AttachedFragmentShader; +} + +GLuint ProgramData::getAttachedShader(GLenum type) { + GLuint shader = 0; + switch (type) { + case GL_VERTEX_SHADER: + shader = AttachedVertexShader; + break; + case GL_FRAGMENT_SHADER: + shader = AttachedFragmentShader; + break; + } + return shader; +} + +bool ProgramData::attachShader(GLuint shader,GLenum type) { + if (type==GL_VERTEX_SHADER && AttachedVertexShader==0) { + AttachedVertexShader=shader; + return true; + } + else if (type==GL_FRAGMENT_SHADER && AttachedFragmentShader==0) { + AttachedFragmentShader=shader; + return true; + } + return false; +} + +bool ProgramData::isAttached(GLuint shader) { + return (AttachedFragmentShader==shader || AttachedVertexShader==shader); +} + +bool ProgramData::detachShader(GLuint shader) { + if (AttachedVertexShader==shader) { + AttachedVertexShader = 0; + return true; + } + else if (AttachedFragmentShader==shader) { + AttachedFragmentShader = 0; + return true; + } + return false; +} + +void ProgramData::setLinkStatus(GLint status) { + LinkStatus = status; +} + +GLint ProgramData::getLinkStatus() { + return LinkStatus; +} diff --git a/tools/emulator/opengl/host/libs/Translator/GLES_V2/ProgramData.h b/tools/emulator/opengl/host/libs/Translator/GLES_V2/ProgramData.h new file mode 100644 index 000000000..2bf752470 --- /dev/null +++ b/tools/emulator/opengl/host/libs/Translator/GLES_V2/ProgramData.h @@ -0,0 +1,40 @@ +/* +* Copyright (C) 2011 The Android Open Source Project +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ +#ifndef PROGRAM_DATA_H +#define PROGRAM_DATA_H + +class ProgramData:public ObjectData{ +public: + ProgramData(); + virtual ~ProgramData(); + + GLuint getAttachedVertexShader(); + GLuint getAttachedFragmentShader(); + GLuint getAttachedShader(GLenum type); + + bool attachShader(GLuint shader,GLenum type); + bool isAttached(GLuint shader); + bool detachShader(GLuint shader); + + void setLinkStatus(GLint status); + GLint getLinkStatus(); + +private: + GLuint AttachedVertexShader; + GLuint AttachedFragmentShader; + GLint LinkStatus; +}; +#endif diff --git a/tools/emulator/opengl/host/libs/Translator/GLES_V2/ShaderParser.cpp b/tools/emulator/opengl/host/libs/Translator/GLES_V2/ShaderParser.cpp index fa7bcd5bf..0a8390fe5 100644 --- a/tools/emulator/opengl/host/libs/Translator/GLES_V2/ShaderParser.cpp +++ b/tools/emulator/opengl/host/libs/Translator/GLES_V2/ShaderParser.cpp @@ -1,12 +1,14 @@ #include "ShaderParser.h" #include -ShaderParser::ShaderParser():m_type(0), +ShaderParser::ShaderParser():ObjectData(SHADER_DATA), + m_type(0), m_src(NULL), m_parsedLines(NULL){}; -ShaderParser::ShaderParser(GLenum type):m_type(type), - m_parsedLines(NULL){}; +ShaderParser::ShaderParser(GLenum type):ObjectData(SHADER_DATA), + m_type(type), + m_parsedLines(NULL){}; void ShaderParser::setSrc(const Version& ver,GLsizei count,const GLchar** strings,const GLint* length){ for(int i = 0;i(&m_parsedLines);}; + GLenum getType(); ~ShaderParser(); private: diff --git a/tools/emulator/opengl/host/libs/Translator/include/GLcommon/GLESbuffer.h b/tools/emulator/opengl/host/libs/Translator/include/GLcommon/GLESbuffer.h index f4dcc7a8f..3353ec114 100644 --- a/tools/emulator/opengl/host/libs/Translator/include/GLcommon/GLESbuffer.h +++ b/tools/emulator/opengl/host/libs/Translator/include/GLcommon/GLESbuffer.h @@ -23,7 +23,7 @@ class GLESbuffer: public ObjectData { public: - GLESbuffer():m_size(0),m_usage(GL_STATIC_DRAW),m_data(NULL),m_wasBound(false){} + GLESbuffer():ObjectData(BUFFER_DATA),m_size(0),m_usage(GL_STATIC_DRAW),m_data(NULL),m_wasBound(false){} GLuint getSize(){return m_size;}; GLuint getUsage(){return m_usage;}; GLvoid* getData(){ return m_data;} diff --git a/tools/emulator/opengl/host/libs/Translator/include/GLcommon/GLESvalidate.h b/tools/emulator/opengl/host/libs/Translator/include/GLcommon/GLESvalidate.h index 11a0741cd..3daaa7cca 100644 --- a/tools/emulator/opengl/host/libs/Translator/include/GLcommon/GLESvalidate.h +++ b/tools/emulator/opengl/host/libs/Translator/include/GLcommon/GLESvalidate.h @@ -22,7 +22,7 @@ struct GLESvalidate { static bool textureEnum(GLenum e,unsigned int maxTex); static bool pixelType(GLEScontext * ctx,GLenum type); -static bool pixelOp(GLenum format,GLenum type); +static bool pixelOp(GLenum format,GLenum type); static bool pixelFrmt(GLEScontext* ctx , GLenum format); static bool bufferTarget(GLenum target); static bool bufferParam(GLenum param); diff --git a/tools/emulator/opengl/host/libs/Translator/include/GLcommon/TranslatorIfaces.h b/tools/emulator/opengl/host/libs/Translator/include/GLcommon/TranslatorIfaces.h index b0d069888..1da457306 100644 --- a/tools/emulator/opengl/host/libs/Translator/include/GLcommon/TranslatorIfaces.h +++ b/tools/emulator/opengl/host/libs/Translator/include/GLcommon/TranslatorIfaces.h @@ -37,7 +37,14 @@ public: ~TextureData() { if (sourceEGLImage && eglImageDetach) (*eglImageDetach)(sourceEGLImage); } - TextureData():width(0),height(0),border(0),internalFormat(GL_RGBA),sourceEGLImage(0),wasBound(false),requiresAutoMipmap(false){ + TextureData(): ObjectData(TEXTURE_DATA), + width(0), + height(0), + border(0), + internalFormat(GL_RGBA), + sourceEGLImage(0), + wasBound(false), + requiresAutoMipmap(false){ memset(crop_rect,0,4*sizeof(int)); }; diff --git a/tools/emulator/opengl/host/libs/Translator/include/GLcommon/gldefs.h b/tools/emulator/opengl/host/libs/Translator/include/GLcommon/gldefs.h index adefffa0e..24e4a23e3 100644 --- a/tools/emulator/opengl/host/libs/Translator/include/GLcommon/gldefs.h +++ b/tools/emulator/opengl/host/libs/Translator/include/GLcommon/gldefs.h @@ -17,9 +17,9 @@ typedef double GLclampd; /* double precision float in [0,1] */ typedef double GLdouble; /* double precision float */ -#define GL_TEXTURE_GEN_S 0x0C60 -#define GL_TEXTURE_GEN_T 0x0C61 -#define GL_TEXTURE_GEN_R 0x0C62 +#define GL_TEXTURE_GEN_S 0x0C60 +#define GL_TEXTURE_GEN_T 0x0C61 +#define GL_TEXTURE_GEN_R 0x0C62 #define GL_CLIENT_VERTEX_ARRAY_BIT 0x00000002 #define GL_TRANSFORM_BIT 0x00001000 #define GL_INT 0x1404 diff --git a/tools/emulator/opengl/host/libs/Translator/include/GLcommon/objectNameManager.h b/tools/emulator/opengl/host/libs/Translator/include/GLcommon/objectNameManager.h index fdc4666c0..aeb01f60b 100644 --- a/tools/emulator/opengl/host/libs/Translator/include/GLcommon/objectNameManager.h +++ b/tools/emulator/opengl/host/libs/Translator/include/GLcommon/objectNameManager.h @@ -28,13 +28,26 @@ enum NamedObjectType { RENDERBUFFER = 2, FRAMEBUFFER = 3, SHADER = 4, - NUM_OBJECT_TYPES = 6 // Must be last + NUM_OBJECT_TYPES = 5 // Must be last +}; + +enum ObjectDataType { + SHADER_DATA, + PROGRAM_DATA, + TEXTURE_DATA, + BUFFER_DATA, + UNDEFINED_DATA }; class ObjectData { public: - virtual ~ObjectData() {} + ObjectData() : m_dataType(UNDEFINED_DATA) {}; + ObjectData(ObjectDataType type): m_dataType(type) {}; + ObjectDataType getDataType() { return m_dataType; }; + virtual ~ObjectData() {}; +private: + ObjectDataType m_dataType; }; typedef SmartPtr ObjectDataPtr;