Implements ValidateProgram
TRAC #11654
Signed-off-by: Andrew Lewycky
Signed-off-by: Daniel Koch
Author: Shannon Woods
git-svn-id: https://angleproject.googlecode.com/svn/trunk@196 736b8ea6-26fd-11df-bfd4-992fa37f6226
diff --git a/src/libGLESv2/Context.cpp b/src/libGLESv2/Context.cpp
index f21f8b6..a60d7d9 100644
--- a/src/libGLESv2/Context.cpp
+++ b/src/libGLESv2/Context.cpp
@@ -1861,6 +1861,11 @@
return;
}
+ if (!getCurrentProgram()->validateSamplers())
+ {
+ return error(GL_INVALID_OPERATION);
+ }
+
if (!applyRenderTarget(false))
{
return error(GL_INVALID_FRAMEBUFFER_OPERATION);
@@ -1903,6 +1908,11 @@
return;
}
+ if (!getCurrentProgram()->validateSamplers())
+ {
+ return error(GL_INVALID_OPERATION);
+ }
+
if (!applyRenderTarget(false))
{
return error(GL_INVALID_FRAMEBUFFER_OPERATION);
diff --git a/src/libGLESv2/Program.cpp b/src/libGLESv2/Program.cpp
index 52d4016..10ab4a1 100644
--- a/src/libGLESv2/Program.cpp
+++ b/src/libGLESv2/Program.cpp
@@ -48,6 +48,7 @@
mPixelHLSL = NULL;
mVertexHLSL = NULL;
mInfoLog = NULL;
+ mValidated = false;
unlink();
@@ -1882,6 +1883,14 @@
}
}
+void Program::resetInfoLog()
+{
+ if (mInfoLog)
+ {
+ delete [] mInfoLog;
+ }
+}
+
// Returns the program object to an unlinked state, after detaching a shader, before re-linking, or at destruction
void Program::unlink(bool destroy)
{
@@ -1960,6 +1969,11 @@
return mLinked;
}
+bool Program::isValidated() const
+{
+ return mValidated;
+}
+
int Program::getInfoLogLength() const
{
if (!mInfoLog)
@@ -2164,4 +2178,49 @@
{
return mDeleteStatus;
}
+
+void Program::validate()
+{
+ resetInfoLog();
+
+ if (!isLinked())
+ {
+ appendToInfoLog("Program has not been successfully linked.");
+ mValidated = false;
+ }
+ else if (!validateSamplers())
+ {
+ appendToInfoLog("Samplers of conflicting types refer to the same texture image unit.");
+ mValidated = false;
+ }
+ else
+ {
+ mValidated = true;
+ }
+}
+
+bool Program::validateSamplers() const
+{
+ // if any two active samplers in a program are of different types, but refer to the same
+ // texture image unit, and this is the current program, then ValidateProgram will fail, and
+ // DrawArrays and DrawElements will issue the INVALID_OPERATION error.
+ std::map<int, SamplerType> samplerMap;
+ for (unsigned int i = 0; i < MAX_TEXTURE_IMAGE_UNITS; ++i)
+ {
+ if (mSamplers[i].active)
+ {
+ if (samplerMap.find(mSamplers[i].logicalTextureUnit) != samplerMap.end())
+ {
+ if (mSamplers[i].type != samplerMap[mSamplers[i].logicalTextureUnit])
+ return false;
+ }
+ else
+ {
+ samplerMap[mSamplers[i].logicalTextureUnit] = mSamplers[i].type;
+ }
+ }
+ }
+
+ return true;
+}
}
diff --git a/src/libGLESv2/Program.h b/src/libGLESv2/Program.h
index dad3355..6188df9 100644
--- a/src/libGLESv2/Program.h
+++ b/src/libGLESv2/Program.h
@@ -102,6 +102,10 @@
void flagForDeletion();
bool isFlaggedForDeletion() const;
+ void validate();
+ bool validateSamplers() const;
+ bool isValidated() const;
+
private:
DISALLOW_COPY_AND_ASSIGN(Program);
@@ -150,6 +154,7 @@
bool applyUniform4iv(GLint location, GLsizei count, const GLint *v);
void appendToInfoLog(const char *info, ...);
+ void resetInfoLog();
FragmentShader *mFragmentShader;
VertexShader *mVertexShader;
@@ -183,6 +188,7 @@
bool mLinked;
bool mDeleteStatus; // Flag to indicate that the program can be deleted when no longer in use
char *mInfoLog;
+ bool mValidated;
};
}
diff --git a/src/libGLESv2/libGLESv2.cpp b/src/libGLESv2/libGLESv2.cpp
index bda72ea..5bf0d14 100644
--- a/src/libGLESv2/libGLESv2.cpp
+++ b/src/libGLESv2/libGLESv2.cpp
@@ -2424,8 +2424,7 @@
*params = programObject->isLinked();
return;
case GL_VALIDATE_STATUS:
- UNIMPLEMENTED(); // FIXME
- *params = GL_TRUE;
+ *params = programObject->isValidated();
return;
case GL_INFO_LOG_LENGTH:
*params = programObject->getInfoLogLength();
@@ -4723,7 +4722,26 @@
try
{
- UNIMPLEMENTED(); // FIXME
+ gl::Context *context = gl::getContext();
+
+ if (context)
+ {
+ gl::Program *programObject = context->getProgram(program);
+
+ if (!programObject)
+ {
+ if (context->getShader(program))
+ {
+ return error(GL_INVALID_OPERATION);
+ }
+ else
+ {
+ return error(GL_INVALID_VALUE);
+ }
+ }
+
+ programObject->validate();
+ }
}
catch(std::bad_alloc&)
{