Add all ES2 glUniform functions to GrGLInterface. Add interface validation for fixed pipe or shader pipe use.

Review URL: http://codereview.appspot.com/4435082/



git-svn-id: http://skia.googlecode.com/svn/trunk@1234 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/gpu/src/GrGLInterface.cpp b/gpu/src/GrGLInterface.cpp
index 5dfc03c..319d33f 100644
--- a/gpu/src/GrGLInterface.cpp
+++ b/gpu/src/GrGLInterface.cpp
@@ -93,3 +93,246 @@
                 GrGLGetGLInterface()->fGetString(GR_GL_VERSION));
     gl_version_from_string(major, minor, v);
 }
+
+bool GrGLInterface::validateShaderFunctions() const {
+    // required for GrGpuGLShaders
+    if (NULL == fAttachShader ||
+        NULL == fBindAttribLocation ||
+        NULL == fCompileShader ||
+        NULL == fCreateProgram ||
+        NULL == fCreateShader ||
+        NULL == fDeleteProgram ||
+        NULL == fDeleteShader ||
+        NULL == fDisableVertexAttribArray ||
+        NULL == fEnableVertexAttribArray ||
+        NULL == fGetProgramInfoLog ||
+        NULL == fGetProgramiv ||
+        NULL == fGetShaderInfoLog ||
+        NULL == fGetShaderiv ||
+        NULL == fGetUniformLocation ||
+        NULL == fLinkProgram ||
+        NULL == fShaderSource ||
+        NULL == fUniform1f ||
+        NULL == fUniform1i ||
+        NULL == fUniform1fv ||
+        NULL == fUniform1iv ||
+        NULL == fUniform2f ||
+        NULL == fUniform2i ||
+        NULL == fUniform2fv ||
+        NULL == fUniform2iv ||
+        NULL == fUniform3f ||
+        NULL == fUniform3i ||
+        NULL == fUniform3fv ||
+        NULL == fUniform3iv ||
+        NULL == fUniform4f ||
+        NULL == fUniform4i ||
+        NULL == fUniform4fv ||
+        NULL == fUniform4iv ||
+        NULL == fUniformMatrix2fv ||
+        NULL == fUniformMatrix3fv ||
+        NULL == fUniformMatrix4fv ||
+        NULL == fUseProgram ||
+        NULL == fVertexAttrib4fv ||
+        NULL == fVertexAttribPointer) {
+        return false;
+    }
+    return true;
+}
+
+bool GrGLInterface::validateFixedFunctions() const {
+    if (NULL == fClientActiveTexture ||
+        NULL == fColor4ub ||
+        NULL == fColorPointer ||
+        NULL == fDisableClientState ||
+        NULL == fEnableClientState ||
+        NULL == fLoadMatrixf ||
+        NULL == fMatrixMode ||
+        NULL == fPointSize ||
+        NULL == fShadeModel ||
+        NULL == fTexCoordPointer ||
+        NULL == fVertexPointer) {
+        return false;
+    }
+    return true;
+}
+
+bool GrGLInterface::validate(GrEngine engine) const {
+
+    bool isDesktop = kDesktop_GrGLBinding == fBindingsExported;
+
+    // ES1 and 2 can be supported in the same interface
+    bool isES = ((kES1_GrGLBinding | kES2_GrGLBinding) & fBindingsExported &&
+                 !(~(kES1_GrGLBinding | kES2_GrGLBinding) & fBindingsExported));
+    
+    if (!isDesktop && !isES) {
+        return false;
+    }
+
+    // functions that are always required
+    if (NULL == fActiveTexture ||
+        NULL == fBindBuffer ||
+        NULL == fBindTexture ||
+        NULL == fBlendFunc ||
+        NULL == fBufferData ||
+        NULL == fBufferSubData ||
+        NULL == fClear ||
+        NULL == fClearColor ||
+        NULL == fClearStencil ||
+        NULL == fColorMask ||
+        NULL == fCullFace ||
+        NULL == fDeleteBuffers ||
+        NULL == fDeleteTextures ||
+        NULL == fDepthMask ||
+        NULL == fDisable ||
+        NULL == fDrawArrays ||
+        NULL == fDrawElements ||
+        NULL == fEnable ||
+        NULL == fFrontFace ||
+        NULL == fGenBuffers ||
+        NULL == fGenTextures ||
+        NULL == fGetBufferParameteriv ||
+        NULL == fGetError ||
+        NULL == fGetIntegerv ||
+        NULL == fGetString ||
+        NULL == fPixelStorei ||
+        NULL == fReadPixels ||
+        NULL == fScissor ||
+        NULL == fStencilFunc ||
+        NULL == fStencilMask ||
+        NULL == fStencilOp ||
+        NULL == fTexEnvi ||
+        NULL == fTexImage2D ||
+        NULL == fTexParameteri ||
+        NULL == fTexSubImage2D ||
+        NULL == fViewport ||
+        NULL == fBindFramebuffer ||
+        NULL == fBindRenderbuffer ||
+        NULL == fCheckFramebufferStatus ||
+        NULL == fDeleteFramebuffers ||
+        NULL == fDeleteRenderbuffers ||
+        NULL == fFramebufferRenderbuffer ||
+        NULL == fFramebufferTexture2D ||
+        NULL == fGenFramebuffers ||
+        NULL == fGenRenderbuffers ||
+        NULL == fRenderbufferStorage) {
+        return false;
+    }
+
+    switch (engine) {
+        case kOpenGL_Shaders_GrEngine:
+            if (kES1_GrGLBinding == fBindingsExported) {
+                return false;
+            }
+            if (!this->validateShaderFunctions()) {
+                return false;
+            }
+            break;
+        case kOpenGL_Fixed_GrEngine:
+            if (kES1_GrGLBinding == fBindingsExported) {
+                return false;
+            }
+            if (!this->validateFixedFunctions()) {
+                return false;
+            }
+            break;
+        default:
+            return false;
+    }
+
+    int major, minor;
+    const char* ext;
+
+    gl_version(&major, &minor);
+    ext = (const char*)fGetString(GR_GL_EXTENSIONS);
+
+    // Now check that baseline ES/Desktop fns not covered above are present
+    // and that we have fn pointers for any advertised extensions that we will
+    // try to use.
+
+    // these functions are part of ES2, we assume they are available
+    // On the desktop we assume they are available if the extension
+    // is present or GL version is high enough.
+    if ((kES2_GrGLBinding & fBindingsExported)) {
+        if (NULL == fBlendColor ||
+            NULL == fStencilFuncSeparate ||
+            NULL == fStencilMaskSeparate ||
+            NULL == fStencilOpSeparate) {
+            return false;
+        }
+    } else if (kDesktop_GrGLBinding == fBindingsExported) {
+        if (major >= 2) {
+            if (NULL == fStencilFuncSeparate ||
+                NULL == fStencilMaskSeparate ||
+                NULL == fStencilOpSeparate) {
+                return false;
+            }
+        }
+        if (1 < major || (1 == major && 4 <= minor) ||
+            has_gl_extension_from_string("GL_EXT_blend_color", ext)) {
+            if (NULL == fBlendColor) {
+                return false;
+            }
+        }
+    }
+
+    // optional function on desktop before 1.3
+    if (kDesktop_GrGLBinding != fBindingsExported ||
+        (1 < major || (1 == major && 3 <= minor)) ||
+        has_gl_extension_from_string("GL_ARB_texture_compression", ext)) {
+        if (NULL == fCompressedTexImage2D) {
+            return false;
+        }
+    }
+
+    // part of desktop GL
+    if (kDesktop_GrGLBinding == fBindingsExported &&
+        NULL == fLineWidth) {
+        return false;
+    }
+    // FBO MSAA
+    if (kDesktop_GrGLBinding == fBindingsExported) {
+        // GL 3.0 and the ARB extension have multisample + blit
+        if ((major >= 3) || has_gl_extension_from_string("GL_ARB_framebuffer_object", ext)) {
+            if (NULL == fRenderbufferStorageMultisample ||
+                NULL == fBlitFramebuffer) {
+                return false;
+            }
+        } else {
+            if (has_gl_extension_from_string("GL_EXT_framebuffer_blit", ext) &&
+                NULL == fBlitFramebuffer) {
+                return false;
+            }
+            if (has_gl_extension_from_string("GL_EXT_framebuffer_multisample", ext) &&
+                NULL == fRenderbufferStorageMultisample) {
+                return false;
+            }
+        }
+    } else {
+        if (has_gl_extension_from_string("GL_CHROMIUM_framebuffer_multisample", ext)) {
+            if (NULL == fRenderbufferStorageMultisample ||
+                NULL == fBlitFramebuffer) {
+                return false;
+            }
+        }
+        if (has_gl_extension_from_string("GL_APPLE_framebuffer_multisample", ext)) {
+            if (NULL == fRenderbufferStorageMultisample ||
+                NULL == fResolveMultisampleFramebuffer) {
+                return false;
+            }
+        }
+    }
+
+    // On ES buffer mapping is an extension. On Desktop
+    // buffer mapping was part of original VBO extension
+    // which we require.
+    if (kDesktop_GrGLBinding == fBindingsExported  || 
+        has_gl_extension_from_string("GL_OES_mapbuffer", ext)) {
+        if (NULL == fMapBuffer ||
+            NULL == fUnmapBuffer) {
+            return false;
+        }
+    }
+
+    return true;
+}
+