aboutsummaryrefslogtreecommitdiffstats
path: root/src/gpu/gl/GrGLInterface.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/gpu/gl/GrGLInterface.cpp')
-rw-r--r--src/gpu/gl/GrGLInterface.cpp534
1 files changed, 534 insertions, 0 deletions
diff --git a/src/gpu/gl/GrGLInterface.cpp b/src/gpu/gl/GrGLInterface.cpp
new file mode 100644
index 0000000..6475306
--- /dev/null
+++ b/src/gpu/gl/GrGLInterface.cpp
@@ -0,0 +1,534 @@
+
+/*
+ * Copyright 2011 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+
+#include "GrTypes.h"
+#include "gl/GrGLInterface.h"
+#include "gl/GrGLDefines.h"
+
+#include <stdio.h>
+
+#if GR_GL_PER_GL_FUNC_CALLBACK
+namespace {
+void GrGLDefaultInterfaceCallback(const GrGLInterface*) {}
+}
+#endif
+
+GrGLBinding GrGLGetBindingInUseFromString(const char* versionString) {
+ if (NULL == versionString) {
+ GrAssert(!"NULL GL version string.");
+ return kNone_GrGLBinding;
+ }
+
+ int major, minor;
+
+ // check for desktop
+ int n = sscanf(versionString, "%d.%d", &major, &minor);
+ if (2 == n) {
+ return kDesktop_GrGLBinding;
+ }
+
+ // check for ES 1
+ char profile[2];
+ n = sscanf(versionString, "OpenGL ES-%c%c %d.%d", profile, profile+1,
+ &major, &minor);
+ if (4 == n) {
+ // we no longer support ES1.
+ return kNone_GrGLBinding;
+ }
+
+ // check for ES2
+ n = sscanf(versionString, "OpenGL ES %d.%d", &major, &minor);
+ if (2 == n) {
+ return kES2_GrGLBinding;
+ }
+ return kNone_GrGLBinding;
+}
+
+GrGLVersion GrGLGetVersionFromString(const char* versionString) {
+ if (NULL == versionString) {
+ GrAssert(!"NULL GL version string.");
+ return 0;
+ }
+
+ int major, minor;
+
+ int n = sscanf(versionString, "%d.%d", &major, &minor);
+ if (2 == n) {
+ return GR_GL_VER(major, minor);
+ }
+
+ char profile[2];
+ n = sscanf(versionString, "OpenGL ES-%c%c %d.%d", profile, profile+1,
+ &major, &minor);
+ if (4 == n) {
+ return GR_GL_VER(major, minor);
+ }
+
+ n = sscanf(versionString, "OpenGL ES %d.%d", &major, &minor);
+ if (2 == n) {
+ return GR_GL_VER(major, minor);
+ }
+
+ return 0;
+}
+
+GrGLSLVersion GrGLGetGLSLVersionFromString(const char* versionString) {
+ if (NULL == versionString) {
+ GrAssert(!"NULL GLSL version string.");
+ return 0;
+ }
+
+ int major, minor;
+
+ int n = sscanf(versionString, "%d.%d", &major, &minor);
+ if (2 == n) {
+ return GR_GLSL_VER(major, minor);
+ }
+
+ n = sscanf(versionString, "OpenGL ES GLSL ES %d.%d", &major, &minor);
+ if (2 == n) {
+ return GR_GLSL_VER(major, minor);
+ }
+
+ // android hack
+ n = sscanf(versionString, "OpenGL ES GLSL %d.%d", &major, &minor);
+ if (2 == n) {
+ return GR_GLSL_VER(major, minor);
+ }
+
+ return 0;
+}
+
+bool GrGLHasExtensionFromString(const char* ext, const char* extensionString) {
+ int extLength = strlen(ext);
+
+ while (true) {
+ int n = strcspn(extensionString, " ");
+ if (n == extLength && 0 == strncmp(ext, extensionString, n)) {
+ return true;
+ }
+ if (0 == extensionString[n]) {
+ return false;
+ }
+ extensionString += n+1;
+ }
+
+ return false;
+}
+
+bool GrGLHasExtension(const GrGLInterface* gl, const char* ext) {
+ const GrGLubyte* glstr;
+ GR_GL_CALL_RET(gl, glstr, GetString(GR_GL_EXTENSIONS));
+ return GrGLHasExtensionFromString(ext, (const char*) glstr);
+}
+
+GrGLBinding GrGLGetBindingInUse(const GrGLInterface* gl) {
+ const GrGLubyte* v;
+ GR_GL_CALL_RET(gl, v, GetString(GR_GL_VERSION));
+ return GrGLGetBindingInUseFromString((const char*) v);
+}
+
+GrGLVersion GrGLGetVersion(const GrGLInterface* gl) {
+ const GrGLubyte* v;
+ GR_GL_CALL_RET(gl, v, GetString(GR_GL_VERSION));
+ return GrGLGetVersionFromString((const char*) v);
+}
+
+GrGLSLVersion GrGLGetGLSLVersion(const GrGLInterface* gl) {
+ const GrGLubyte* v;
+ GR_GL_CALL_RET(gl, v, GetString(GR_GL_SHADING_LANGUAGE_VERSION));
+ return GrGLGetGLSLVersionFromString((const char*) v);
+}
+
+GrGLInterface::GrGLInterface() {
+ fBindingsExported = kNone_GrGLBinding;
+
+ fActiveTexture = NULL;
+ fAttachShader = NULL;
+ fBeginQuery = NULL;
+ fBindAttribLocation = NULL;
+ fBindBuffer = NULL;
+ fBindFragDataLocation = NULL;
+ fBindTexture = NULL;
+ fBlendColor = NULL;
+ fBlendFunc = NULL;
+ fBufferData = NULL;
+ fBufferSubData = NULL;
+ fClear = NULL;
+ fClearColor = NULL;
+ fClearStencil = NULL;
+ fColorMask = NULL;
+ fColorPointer = NULL;
+ fCompileShader = NULL;
+ fCompressedTexImage2D = NULL;
+ fCreateProgram = NULL;
+ fCreateShader = NULL;
+ fCullFace = NULL;
+ fDeleteBuffers = NULL;
+ fDeleteProgram = NULL;
+ fDeleteQueries = NULL;
+ fDeleteShader = NULL;
+ fDeleteTextures = NULL;
+ fDepthMask = NULL;
+ fDisable = NULL;
+ fDisableVertexAttribArray = NULL;
+ fDrawArrays = NULL;
+ fDrawBuffer = NULL;
+ fDrawBuffers = NULL;
+ fDrawElements = NULL;
+ fEndQuery = NULL;
+ fFinish = NULL;
+ fFlush = NULL;
+ fEnable = NULL;
+ fEnableVertexAttribArray = NULL;
+ fFrontFace = NULL;
+ fGenBuffers = NULL;
+ fGenQueries = NULL;
+ fGenTextures = NULL;
+ fGetBufferParameteriv = NULL;
+ fGetError = NULL;
+ fGetIntegerv = NULL;
+ fGetQueryiv = NULL;
+ fGetQueryObjecti64v = NULL;
+ fGetQueryObjectiv = NULL;
+ fGetQueryObjectui64v = NULL;
+ fGetQueryObjectuiv = NULL;
+ fGetProgramInfoLog = NULL;
+ fGetProgramiv = NULL;
+ fGetShaderInfoLog = NULL;
+ fGetShaderiv = NULL;
+ fGetString = NULL;
+ fGetTexLevelParameteriv = NULL;
+ fGetUniformLocation = NULL;
+ fLineWidth = NULL;
+ fLinkProgram = NULL;
+ fPixelStorei = NULL;
+ fQueryCounter = NULL;
+ fReadBuffer = NULL;
+ fReadPixels = NULL;
+ fScissor = NULL;
+ fShaderSource = NULL;
+ fStencilFunc = NULL;
+ fStencilFuncSeparate = NULL;
+ fStencilMask = NULL;
+ fStencilMaskSeparate = NULL;
+ fStencilOp = NULL;
+ fStencilOpSeparate = NULL;
+ fTexImage2D = NULL;
+ fTexParameteri = NULL;
+ fTexStorage2D = NULL;
+ fTexSubImage2D = 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 = NULL;
+ fViewport = NULL;
+ fBindFramebuffer = NULL;
+ fBindRenderbuffer = NULL;
+ fCheckFramebufferStatus = NULL;
+ fDeleteFramebuffers = NULL;
+ fDeleteRenderbuffers = NULL;
+ fFramebufferRenderbuffer = NULL;
+ fFramebufferTexture2D = NULL;
+ fGenFramebuffers = NULL;
+ fGenRenderbuffers = NULL;
+ fGetFramebufferAttachmentParameteriv = NULL;
+ fGetRenderbufferParameteriv = NULL;
+ fRenderbufferStorage = NULL;
+ fRenderbufferStorageMultisample = NULL;
+ fBlitFramebuffer = NULL;
+ fResolveMultisampleFramebuffer = NULL;
+ fMapBuffer = NULL;
+ fUnmapBuffer = NULL;
+ fBindFragDataLocationIndexed = NULL;
+
+#if GR_GL_PER_GL_FUNC_CALLBACK
+ fCallback = GrGLDefaultInterfaceCallback;
+ fCallbackData = 0;
+#endif
+}
+
+bool GrGLInterface::validate(GrGLBinding binding) const {
+
+ // kNone must be 0 so that the check we're about to do can never succeed if
+ // binding == kNone.
+ GR_STATIC_ASSERT(kNone_GrGLBinding == 0);
+
+ if (0 == (binding & fBindingsExported)) {
+ return false;
+ }
+
+ // functions that are always required
+ if (NULL == fActiveTexture ||
+ NULL == fAttachShader ||
+ NULL == fBindAttribLocation ||
+ NULL == fBindBuffer ||
+ NULL == fBindTexture ||
+ NULL == fBlendFunc ||
+ NULL == fBufferData ||
+ NULL == fBufferSubData ||
+ NULL == fClear ||
+ NULL == fClearColor ||
+ NULL == fClearStencil ||
+ NULL == fColorMask ||
+ NULL == fCompileShader ||
+ NULL == fCreateProgram ||
+ NULL == fCreateShader ||
+ NULL == fCullFace ||
+ NULL == fDeleteBuffers ||
+ NULL == fDeleteProgram ||
+ NULL == fDeleteShader ||
+ NULL == fDeleteTextures ||
+ NULL == fDepthMask ||
+ NULL == fDisable ||
+ NULL == fDisableVertexAttribArray ||
+ NULL == fDrawArrays ||
+ NULL == fDrawElements ||
+ NULL == fEnable ||
+ NULL == fEnableVertexAttribArray ||
+ NULL == fFrontFace ||
+ NULL == fGenBuffers ||
+ NULL == fGenTextures ||
+ NULL == fGetBufferParameteriv ||
+ NULL == fGetError ||
+ NULL == fGetIntegerv ||
+ NULL == fGetProgramInfoLog ||
+ NULL == fGetProgramiv ||
+ NULL == fGetShaderInfoLog ||
+ NULL == fGetShaderiv ||
+ NULL == fGetString ||
+ NULL == fGetUniformLocation ||
+ NULL == fLinkProgram ||
+ NULL == fPixelStorei ||
+ NULL == fReadPixels ||
+ NULL == fScissor ||
+ NULL == fShaderSource ||
+ NULL == fStencilFunc ||
+ NULL == fStencilMask ||
+ NULL == fStencilOp ||
+ NULL == fTexImage2D ||
+ NULL == fTexParameteri ||
+ NULL == fTexSubImage2D ||
+ 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 ||
+ NULL == fViewport ||
+ NULL == fBindFramebuffer ||
+ NULL == fBindRenderbuffer ||
+ NULL == fCheckFramebufferStatus ||
+ NULL == fDeleteFramebuffers ||
+ NULL == fDeleteRenderbuffers ||
+ NULL == fFinish ||
+ NULL == fFlush ||
+ NULL == fFramebufferRenderbuffer ||
+ NULL == fFramebufferTexture2D ||
+ NULL == fGetFramebufferAttachmentParameteriv ||
+ NULL == fGetRenderbufferParameteriv ||
+ NULL == fGenFramebuffers ||
+ NULL == fGenRenderbuffers ||
+ NULL == fRenderbufferStorage) {
+ return false;
+ }
+
+ const char* ext;
+ GrGLVersion glVer = GrGLGetVersion(this);
+ 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 == binding) {
+ if (NULL == fBlendColor ||
+ NULL == fStencilFuncSeparate ||
+ NULL == fStencilMaskSeparate ||
+ NULL == fStencilOpSeparate) {
+ return false;
+ }
+ } else if (kDesktop_GrGLBinding == binding) {
+ if (glVer >= GR_GL_VER(2,0)) {
+ if (NULL == fStencilFuncSeparate ||
+ NULL == fStencilMaskSeparate ||
+ NULL == fStencilOpSeparate) {
+ return false;
+ }
+ }
+ if (glVer >= GR_GL_VER(3,0) && NULL == fBindFragDataLocation) {
+ return false;
+ }
+ if (glVer >= GR_GL_VER(2,0) ||
+ GrGLHasExtensionFromString("GL_ARB_draw_buffers", ext)) {
+ if (NULL == fDrawBuffers) {
+ return false;
+ }
+ }
+ if (glVer >= GR_GL_VER(1,4) ||
+ GrGLHasExtensionFromString("GL_EXT_blend_color", ext)) {
+ if (NULL == fBlendColor) {
+ return false;
+ }
+ }
+ if (glVer >= GR_GL_VER(1,5) ||
+ GrGLHasExtensionFromString("GL_ARB_occlusion_query", ext)) {
+ if (NULL == fGenQueries ||
+ NULL == fDeleteQueries ||
+ NULL == fBeginQuery ||
+ NULL == fEndQuery ||
+ NULL == fGetQueryiv ||
+ NULL == fGetQueryObjectiv ||
+ NULL == fGetQueryObjectuiv) {
+ return false;
+ }
+ }
+ if (glVer >= GR_GL_VER(3,3) ||
+ GrGLHasExtensionFromString("GL_ARB_timer_query", ext) ||
+ GrGLHasExtensionFromString("GL_EXT_timer_query", ext)) {
+ if (NULL == fGetQueryObjecti64v ||
+ NULL == fGetQueryObjectui64v) {
+ return false;
+ }
+ }
+ if (glVer >= GR_GL_VER(3,3) ||
+ GrGLHasExtensionFromString("GL_ARB_timer_query", ext)) {
+ if (NULL == fQueryCounter) {
+ return false;
+ }
+ }
+ }
+
+ // optional function on desktop before 1.3
+ if (kDesktop_GrGLBinding != binding ||
+ (glVer >= GR_GL_VER(1,3) ||
+ GrGLHasExtensionFromString("GL_ARB_texture_compression", ext))) {
+ if (NULL == fCompressedTexImage2D) {
+ return false;
+ }
+ }
+
+ // part of desktop GL, but not ES
+ if (kDesktop_GrGLBinding == binding &&
+ (NULL == fLineWidth ||
+ NULL == fGetTexLevelParameteriv ||
+ NULL == fDrawBuffer ||
+ NULL == fReadBuffer)) {
+ return false;
+ }
+
+ // GL_EXT_texture_storage is part of desktop 4.2
+ // There is a desktop ARB extension and an ES+desktop EXT extension
+ if (kDesktop_GrGLBinding == binding) {
+ if (glVer >= GR_GL_VER(4,2) ||
+ GrGLHasExtensionFromString("GL_ARB_texture_storage", ext) ||
+ GrGLHasExtensionFromString("GL_EXT_texture_storage", ext)) {
+ if (NULL == fTexStorage2D) {
+ return false;
+ }
+ }
+ } else if (GrGLHasExtensionFromString("GL_EXT_texture_storage", ext)) {
+ if (NULL == fTexStorage2D) {
+ return false;
+ }
+ }
+
+ // FBO MSAA
+ if (kDesktop_GrGLBinding == binding) {
+ // GL 3.0 and the ARB extension have multisample + blit
+ if (glVer >= GR_GL_VER(3,0) || GrGLHasExtensionFromString("GL_ARB_framebuffer_object", ext)) {
+ if (NULL == fRenderbufferStorageMultisample ||
+ NULL == fBlitFramebuffer) {
+ return false;
+ }
+ } else {
+ if (GrGLHasExtensionFromString("GL_EXT_framebuffer_blit", ext) &&
+ NULL == fBlitFramebuffer) {
+ return false;
+ }
+ if (GrGLHasExtensionFromString("GL_EXT_framebuffer_multisample", ext) &&
+ NULL == fRenderbufferStorageMultisample) {
+ return false;
+ }
+ }
+ } else {
+ if (GrGLHasExtensionFromString("GL_CHROMIUM_framebuffer_multisample", ext)) {
+ if (NULL == fRenderbufferStorageMultisample ||
+ NULL == fBlitFramebuffer) {
+ return false;
+ }
+ }
+ if (GrGLHasExtensionFromString("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 == binding ||
+ GrGLHasExtensionFromString("GL_OES_mapbuffer", ext)) {
+ if (NULL == fMapBuffer ||
+ NULL == fUnmapBuffer) {
+ return false;
+ }
+ }
+
+ // Dual source blending
+ if (kDesktop_GrGLBinding == binding &&
+ (glVer >= GR_GL_VER(3,3) ||
+ GrGLHasExtensionFromString("GL_ARB_blend_func_extended", ext))) {
+ if (NULL == fBindFragDataLocationIndexed) {
+ return false;
+ }
+ }
+
+ return true;
+}
+