From f79a58ed62c4f0a595468737e4f72dd9ae7abbf7 Mon Sep 17 00:00:00 2001 From: Yochai Shefi Simchon Date: Wed, 10 Aug 2011 15:04:27 +0300 Subject: [PATCH] opengles emulator: fix shader parser precision qualifiers Workaround to intel/linux driver issue. Desktop OpenGL does not support precision qulifiers in shaders, so we remove them by defining "precision" "mediump" "lowp" and "highp" to blank. That translates the line "precision mediump float;" to "float;" which is a valid command according to the GLSL spec however it fails to compile using the intel/linux driver. This change adds a parser which removes completely the precision command from the shader source. Change-Id: I29a16bb78ac0000d624aa2f83e93ef5c6ad60345 --- .../libs/Translator/GLES_V2/GLESv2Imp.cpp | 11 +- .../libs/Translator/GLES_V2/ShaderParser.cpp | 118 +++++++++++++++++- .../libs/Translator/GLES_V2/ShaderParser.h | 2 + 3 files changed, 125 insertions(+), 6 deletions(-) diff --git a/tools/emulator/opengl/host/libs/Translator/GLES_V2/GLESv2Imp.cpp b/tools/emulator/opengl/host/libs/Translator/GLES_V2/GLESv2Imp.cpp index c81b3462b..d768dd4a2 100644 --- a/tools/emulator/opengl/host/libs/Translator/GLES_V2/GLESv2Imp.cpp +++ b/tools/emulator/opengl/host/libs/Translator/GLES_V2/GLESv2Imp.cpp @@ -1296,11 +1296,16 @@ GL_APICALL void GL_APIENTRY glGetShaderSource(GLuint shader, GLsizei bufsize, G 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); + int srcLength = 0; + if (src) { + srcLength = strlen(src); + } int returnLength = bufsize= 'a' && (c) <='z') || ((c) >= 'A' && (c) <= 'Z') ) + #define IS_TOKEN_DELIMITER(c) ( IS_DELIMITER(c) || (c) == ';' ) + + while( c && *c != '\0') { + if (parseState == PARSE_IN_C_COMMENT) { + if (*c == '*' && *(c+1) == '/') { + parseState = PARSE_NONE; + c += 2; + } + else c++; + } + else if (parseState == PARSE_IN_LINE_COMMENT) { + if (*c == '\n') { + parseState = PARSE_NONE; + } + c++; + } + else if (*c == '/' && *(c+1) == '/') { + parseState = PARSE_IN_LINE_COMMENT; + c += 2; + } + else if (*c == '/' && *(c+1) == '*') { + parseState = PARSE_IN_C_COMMENT; + c += 2; + } + else if (t && IS_TOKEN_DELIMITER(*c)) { + int tokenLen = c - t; + switch (statementState) { + case PRECISION: + if (tokenLen == 9 && !strncmp(t,"precision",9)) { + statementState = QUALIFIER; + precision = t; + } + break; + case QUALIFIER: + if ((tokenLen == 4 && !strncmp(t,"lowp",4)) || + (tokenLen == 7 && !strncmp(t,"mediump",7)) || + (tokenLen == 5 && !strncmp(t,"highp",5))) { + statementState = SEMICOLON; + } + else { + statementState = PRECISION; + } + break; + case SEMICOLON: + if (*c == ';') { + for (char *r = (char *)precision; r<=c ; ++r) { + *r = ' '; //blank the character + } + } + statementState = PRECISION; //search for the next precision line + break; + default: + break; + } + c++; + t = NULL; + } + else if (IS_DELIMITER(*c)) { + c++; + } + else { + if (!t && IS_TOKEN_START(*c)) { + t = c; + } + c++; + } + } } void ShaderParser::parseExtendDefaultPrecision(){ @@ -211,5 +321,7 @@ GLchar* ShaderParser::getInfoLog() ShaderParser::~ShaderParser(){ clearParsedSrc(); + if (m_originalSrc) + free(m_originalSrc); delete[] m_infoLog; } diff --git a/tools/emulator/opengl/host/libs/Translator/GLES_V2/ShaderParser.h b/tools/emulator/opengl/host/libs/Translator/GLES_V2/ShaderParser.h index 88e4b2ab5..8c0ff3e69 100644 --- a/tools/emulator/opengl/host/libs/Translator/GLES_V2/ShaderParser.h +++ b/tools/emulator/opengl/host/libs/Translator/GLES_V2/ShaderParser.h @@ -25,9 +25,11 @@ private: void parseBuiltinConstants(); void parseOmitPrecision(); void parseExtendDefaultPrecision(); + void parseLineNumbers(); void clearParsedSrc(); GLenum m_type; + char* m_originalSrc; std::string m_src; std::string m_parsedSrc; GLchar* m_parsedLines;