am 255bdd3f: Merge "opengles emulator: fix shader parser precision qualifiers"

* commit '255bdd3f1b68c98bdeeea7006132b61e9bade1cb':
  opengles emulator: fix shader parser precision qualifiers
This commit is contained in:
David Turner
2011-08-13 16:10:58 -07:00
committed by Android Git Automerger
3 changed files with 125 additions and 6 deletions

View File

@@ -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(),GL_INVALID_OPERATION);
SET_ERROR_IF(objData.Ptr()->getDataType()!=SHADER_DATA,GL_INVALID_OPERATION); SET_ERROR_IF(objData.Ptr()->getDataType()!=SHADER_DATA,GL_INVALID_OPERATION);
const char* src = ((ShaderParser*)objData.Ptr())->getOriginalSrc(); const char* src = ((ShaderParser*)objData.Ptr())->getOriginalSrc();
int srcLength = strlen(src); int srcLength = 0;
if (src) {
srcLength = strlen(src);
}
int returnLength = bufsize<srcLength ? bufsize-1 : srcLength; int returnLength = bufsize<srcLength ? bufsize-1 : srcLength;
strncpy(source,src, returnLength); if (returnLength) {
source[returnLength] = '\0'; strncpy(source,src, returnLength);
source[returnLength] = '\0';
}
if (length) if (length)
*length = returnLength; *length = returnLength;

View File

@@ -3,6 +3,7 @@
ShaderParser::ShaderParser():ObjectData(SHADER_DATA), ShaderParser::ShaderParser():ObjectData(SHADER_DATA),
m_type(0), m_type(0),
m_originalSrc(NULL),
m_parsedLines(NULL) { m_parsedLines(NULL) {
m_infoLog = new GLchar[1]; m_infoLog = new GLchar[1];
m_infoLog[0] = '\0'; m_infoLog[0] = '\0';
@@ -10,6 +11,7 @@ ShaderParser::ShaderParser():ObjectData(SHADER_DATA),
ShaderParser::ShaderParser(GLenum type):ObjectData(SHADER_DATA), ShaderParser::ShaderParser(GLenum type):ObjectData(SHADER_DATA),
m_type(type), m_type(type),
m_originalSrc(NULL),
m_parsedLines(NULL) { m_parsedLines(NULL) {
m_infoLog = new GLchar[1]; m_infoLog = new GLchar[1];
@@ -20,6 +22,11 @@ void ShaderParser::setSrc(const Version& ver,GLsizei count,const GLchar** string
for(int i = 0;i<count;i++){ for(int i = 0;i<count;i++){
m_src.append(strings[i]); m_src.append(strings[i]);
} }
//store original source
if (m_originalSrc)
free(m_originalSrc);
m_originalSrc = strdup(m_src.c_str());
clearParsedSrc(); clearParsedSrc();
// parseGLSLversion must be called first since #version should be the // parseGLSLversion must be called first since #version should be the
@@ -42,7 +49,7 @@ void ShaderParser::setSrc(const Version& ver,GLsizei count,const GLchar** string
//XXX: Until proved otherwise, glsl doesn't know/use those precision macros, so we omit then //XXX: Until proved otherwise, glsl doesn't know/use those precision macros, so we omit then
parseOmitPrecision(); parseOmitPrecision();
#endif #endif
parseLineNumbers();
parseOriginalSrc(); parseOriginalSrc();
} }
const GLchar** ShaderParser::parsedLines() { const GLchar** ShaderParser::parsedLines() {
@@ -51,7 +58,12 @@ const GLchar** ShaderParser::parsedLines() {
}; };
const char* ShaderParser::getOriginalSrc(){ const char* ShaderParser::getOriginalSrc(){
return m_src.c_str(); return m_originalSrc;
}
void ShaderParser::parseLineNumbers()
{
m_parsedSrc += "#line 1\n";
} }
void ShaderParser::parseOriginalSrc() { void ShaderParser::parseOriginalSrc() {
@@ -173,9 +185,107 @@ void ShaderParser::parseOmitPrecision(){
"#define lowp \n" "#define lowp \n"
"#define mediump \n" "#define mediump \n"
"#define highp \n" "#define highp \n"
"#define precision \n"
}; };
m_parsedSrc+=defines; m_parsedSrc+=defines;
//
// parse the source and blank out precision statements
// which has the following syntax:
// precision {qualifier} {type};
// where {qualifier} is one of lowp,mediump or hightp
// type is any valid GLES defined type (we do not check that here!)
// NOTE: This is needed in order to workaround driver bug in
// Intel/Linux where the compiler does not get statement like
// "float;", otherwise we could just define a macro named
// precision to be empty.
//
const char *src = m_src.c_str();
enum {
PRECISION,
QUALIFIER,
SEMICOLON
} statementState = PRECISION;
const char *precision = NULL;
const char *delimiter = NULL;
enum {
PARSE_NONE,
PARSE_IN_C_COMMENT,
PARSE_IN_LINE_COMMENT
} parseState = PARSE_NONE;
const char *c = src;
const char *t = NULL;
#define IS_DELIMITER(c) ( (c) == ' ' || (c) == '\t' || (c) == '\r' || (c) == '\n' )
#define IS_TOKEN_START(c) ( ((c) >= '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(){ void ShaderParser::parseExtendDefaultPrecision(){
@@ -211,5 +321,7 @@ GLchar* ShaderParser::getInfoLog()
ShaderParser::~ShaderParser(){ ShaderParser::~ShaderParser(){
clearParsedSrc(); clearParsedSrc();
if (m_originalSrc)
free(m_originalSrc);
delete[] m_infoLog; delete[] m_infoLog;
} }

View File

@@ -25,9 +25,11 @@ private:
void parseBuiltinConstants(); void parseBuiltinConstants();
void parseOmitPrecision(); void parseOmitPrecision();
void parseExtendDefaultPrecision(); void parseExtendDefaultPrecision();
void parseLineNumbers();
void clearParsedSrc(); void clearParsedSrc();
GLenum m_type; GLenum m_type;
char* m_originalSrc;
std::string m_src; std::string m_src;
std::string m_parsedSrc; std::string m_parsedSrc;
GLchar* m_parsedLines; GLchar* m_parsedLines;