/****************************************************************************** @File OGLES2/PVRTShader.cpp @Title OGLES2/PVRTShader @Version @Copyright Copyright (c) Imagination Technologies Limited. @Platform ANSI compatible @Description Shader handling for OpenGL ES 2.0 ******************************************************************************/ #include "PVRTString.h" #include "PVRTShader.h" #include "PVRTResourceFile.h" #include "PVRTGlobal.h" #include #include /*!*************************************************************************** @Function PVRTShaderLoadSourceFromMemory @Input pszShaderCode shader source code @Input Type type of shader (GL_VERTEX_SHADER or GL_FRAGMENT_SHADER) @Output pObject the resulting shader object @Output pReturnError the error message if it failed @Input aszDefineArray Array of defines to be pre-appended to shader string @Input uiDefArraySize Size of the define array @Return PVR_SUCCESS on success and PVR_FAIL on failure (also fills the str string) @Description Loads a shader source code into memory and compiles it. It also pre-appends the array of defines that have been passed in to the source code before compilation. *****************************************************************************/ EPVRTError PVRTShaderLoadSourceFromMemory( const char* pszShaderCode, const GLenum Type, GLuint* const pObject, CPVRTString* const pReturnError, const char* const* aszDefineArray, GLuint uiDefArraySize) { // Append define's here if there are any CPVRTString pszShaderString; if(uiDefArraySize > 0) { while(isspace(*pszShaderCode)) ++pszShaderCode; if(*pszShaderCode == '#') { const char* tmp = pszShaderCode + 1; while(isspace(*tmp)) ++tmp; if(strncmp(tmp, "version", 7) == 0) { const char* c = strchr(pszShaderCode, '\n'); if(c) { size_t length = c - pszShaderCode + 1; pszShaderString = CPVRTString(pszShaderCode, length); pszShaderCode += length; } else { pszShaderString = CPVRTString(pszShaderCode) + "\n"; pszShaderCode = '\0'; } } } for(GLuint i = 0 ; i < uiDefArraySize; ++i) { pszShaderString += "#define "; pszShaderString += aszDefineArray[i]; pszShaderString += "\n"; } } // Append the shader code to the string pszShaderString += pszShaderCode; /* Create and compile the shader object */ *pObject = glCreateShader(Type); const char* pszString(pszShaderString.c_str()); glShaderSource(*pObject, 1, &pszString, NULL); glCompileShader(*pObject); /* Test if compilation succeeded */ GLint ShaderCompiled; glGetShaderiv(*pObject, GL_COMPILE_STATUS, &ShaderCompiled); if (!ShaderCompiled) { int i32InfoLogLength, i32CharsWritten; glGetShaderiv(*pObject, GL_INFO_LOG_LENGTH, &i32InfoLogLength); char* pszInfoLog = new char[i32InfoLogLength]; glGetShaderInfoLog(*pObject, i32InfoLogLength, &i32CharsWritten, pszInfoLog); *pReturnError = CPVRTString("Failed to compile shader: ") + pszInfoLog + "\n"; delete [] pszInfoLog; glDeleteShader(*pObject); return PVR_FAIL; } return PVR_SUCCESS; } /*!*************************************************************************** @Function PVRTShaderLoadBinaryFromMemory @Input ShaderData shader compiled binary data @Input Size size of shader binary data in bytes @Input Type type of shader (GL_VERTEX_SHADER or GL_FRAGMENT_SHADER) @Input Format shader binary format @Output pObject the resulting shader object @Output pReturnError the error message if it failed @Return PVR_SUCCESS on success and PVR_FAIL on failure (also fills the str string) @Description Takes a shader binary from memory and passes it to the GL. *****************************************************************************/ EPVRTError PVRTShaderLoadBinaryFromMemory( const void* const ShaderData, const size_t Size, const GLenum Type, const GLenum Format, GLuint* const pObject, CPVRTString* const pReturnError) { /* Create and compile the shader object */ *pObject = glCreateShader(Type); // Get the list of supported binary formats // and if (more then 0) find given Format among them GLint numFormats = 0; GLint *listFormats; int i; glGetIntegerv(GL_NUM_SHADER_BINARY_FORMATS,&numFormats); if(numFormats != 0) { listFormats = new GLint[numFormats]; for(i=0;i