summaryrefslogtreecommitdiffstats
path: root/gfx/gl/SkiaGLGlue.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'gfx/gl/SkiaGLGlue.cpp')
-rwxr-xr-xgfx/gl/SkiaGLGlue.cpp327
1 files changed, 327 insertions, 0 deletions
diff --git a/gfx/gl/SkiaGLGlue.cpp b/gfx/gl/SkiaGLGlue.cpp
new file mode 100755
index 000000000..eb84934a6
--- /dev/null
+++ b/gfx/gl/SkiaGLGlue.cpp
@@ -0,0 +1,327 @@
+/* -*- Mode: c++; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40; -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "skia/include/gpu/GrContext.h"
+#include "skia/include/gpu/gl/GrGLInterface.h"
+#include "mozilla/gfx/2D.h"
+#include "mozilla/ThreadLocal.h"
+#include "mozilla/DebugOnly.h"
+
+/* SkPostConfig.h includes windows.h, which includes windef.h
+ * which redefines min/max. We don't want that. */
+#ifdef _WIN32
+#undef min
+#undef max
+#endif
+
+#include "GLContext.h"
+#include "SkiaGLGlue.h"
+
+using mozilla::gl::GLContext;
+using mozilla::gl::GLFeature;
+using mozilla::gl::SkiaGLGlue;
+using mozilla::gfx::DrawTarget;
+
+template<typename R, typename... A>
+static inline GrGLFunction<R (*)(A...)>
+WrapGL(RefPtr<GLContext> aContext, R (GLContext::*aFunc)(A...))
+{
+ return [aContext, aFunc] (A... args) -> R
+ {
+ aContext->MakeCurrent();
+ return (aContext->*aFunc)(args...);
+ };
+}
+
+template<typename R, typename... A>
+static inline GrGLFunction<R (*)(A...)>
+WrapGL(RefPtr<GLContext> aContext, R (*aFunc)(GLContext*, A...))
+{
+ return [aContext, aFunc] (A... args) -> R
+ {
+ aContext->MakeCurrent();
+ return (*aFunc)(aContext, args...);
+ };
+}
+
+// Core GL functions required by Ganesh
+
+static const GLubyte*
+glGetString_mozilla(GLContext* aContext, GrGLenum aName)
+{
+ // GLContext only exposes a OpenGL 2.0 style API, so we have to intercept a bunch
+ // of checks that Ganesh makes to determine which capabilities are present
+ // on the GL implementation and change them to match what GLContext actually exposes.
+
+ if (aName == LOCAL_GL_VERSION) {
+ if (aContext->IsGLES()) {
+ return reinterpret_cast<const GLubyte*>("OpenGL ES 2.0");
+ } else {
+ return reinterpret_cast<const GLubyte*>("2.0");
+ }
+ } else if (aName == LOCAL_GL_EXTENSIONS) {
+ // Only expose the bare minimum extensions we want to support to ensure a functional Ganesh
+ // as GLContext only exposes certain extensions
+ static bool extensionsStringBuilt = false;
+ static char extensionsString[1024];
+
+ if (!extensionsStringBuilt) {
+ extensionsString[0] = '\0';
+
+ if (aContext->IsGLES()) {
+ // OES is only applicable to GLES2
+ if (aContext->IsExtensionSupported(GLContext::OES_packed_depth_stencil)) {
+ strcat(extensionsString, "GL_OES_packed_depth_stencil ");
+ }
+
+ if (aContext->IsExtensionSupported(GLContext::OES_rgb8_rgba8)) {
+ strcat(extensionsString, "GL_OES_rgb8_rgba8 ");
+ }
+
+ if (aContext->IsExtensionSupported(GLContext::OES_texture_npot)) {
+ strcat(extensionsString, "GL_OES_texture_npot ");
+ }
+
+ if (aContext->IsExtensionSupported(GLContext::OES_vertex_array_object)) {
+ strcat(extensionsString, "GL_OES_vertex_array_object ");
+ }
+
+ if (aContext->IsSupported(GLFeature::standard_derivatives)) {
+ strcat(extensionsString, "GL_OES_standard_derivatives ");
+ }
+ } else {
+ if (aContext->IsSupported(GLFeature::framebuffer_object)) {
+ strcat(extensionsString, "GL_ARB_framebuffer_object ");
+ } else if (aContext->IsExtensionSupported(GLContext::EXT_framebuffer_object)) {
+ strcat(extensionsString, "GL_EXT_framebuffer_object ");
+ }
+
+ if (aContext->IsSupported(GLFeature::texture_rg)) {
+ strcat(extensionsString, "GL_ARB_texture_rg ");
+ }
+ }
+
+ if (aContext->IsExtensionSupported(GLContext::EXT_texture_format_BGRA8888)) {
+ strcat(extensionsString, "GL_EXT_texture_format_BGRA8888 ");
+ }
+
+ if (aContext->IsExtensionSupported(GLContext::EXT_packed_depth_stencil)) {
+ strcat(extensionsString, "GL_EXT_packed_depth_stencil ");
+ }
+
+ if (aContext->IsExtensionSupported(GLContext::EXT_bgra)) {
+ strcat(extensionsString, "GL_EXT_bgra ");
+ }
+
+ if (aContext->IsExtensionSupported(GLContext::EXT_read_format_bgra)) {
+ strcat(extensionsString, "GL_EXT_read_format_bgra ");
+ }
+
+ extensionsStringBuilt = true;
+#ifdef DEBUG
+ printf_stderr("Exported SkiaGL extensions: %s\n", extensionsString);
+#endif
+ }
+
+ return reinterpret_cast<const GLubyte*>(extensionsString);
+
+ } else if (aName == LOCAL_GL_SHADING_LANGUAGE_VERSION) {
+ if (aContext->IsGLES()) {
+ return reinterpret_cast<const GLubyte*>("OpenGL ES GLSL ES 1.0");
+ } else {
+ return reinterpret_cast<const GLubyte*>("1.10");
+ }
+ }
+
+ return aContext->fGetString(aName);
+}
+
+static GrGLInterface* CreateGrGLInterfaceFromGLContext(GLContext* context)
+{
+ GrGLInterface* i = new GrGLInterface();
+
+ context->MakeCurrent();
+
+ // We support both desktop GL and GLES2
+ if (context->IsGLES()) {
+ i->fStandard = kGLES_GrGLStandard;
+ } else {
+ i->fStandard = kGL_GrGLStandard;
+ }
+
+ GrGLFunction<GrGLGetStringProc> getString = WrapGL(context, &glGetString_mozilla);
+ GrGLFunction<GrGLGetIntegervProc> getIntegerv = WrapGL(context, &GLContext::fGetIntegerv);
+
+ GrGLExtensions extensions;
+ if (!extensions.init(i->fStandard, getString, nullptr, getIntegerv)) {
+ delete i;
+ return nullptr;
+ }
+
+ i->fExtensions.swap(&extensions);
+
+ // Core GL functions required by Ganesh
+ i->fFunctions.fActiveTexture = WrapGL(context, &GLContext::fActiveTexture);
+ i->fFunctions.fAttachShader = WrapGL(context, &GLContext::fAttachShader);
+ i->fFunctions.fBindAttribLocation = WrapGL(context, &GLContext::fBindAttribLocation);
+ i->fFunctions.fBindBuffer = WrapGL(context, &GLContext::fBindBuffer);
+ i->fFunctions.fBindFramebuffer = WrapGL(context, &GLContext::fBindFramebuffer);
+ i->fFunctions.fBindRenderbuffer = WrapGL(context, &GLContext::fBindRenderbuffer);
+ i->fFunctions.fBindTexture = WrapGL(context, &GLContext::fBindTexture);
+ i->fFunctions.fBlendFunc = WrapGL(context, &GLContext::fBlendFunc);
+ i->fFunctions.fBlendColor = WrapGL(context, &GLContext::fBlendColor);
+ i->fFunctions.fBlendEquation = WrapGL(context, &GLContext::fBlendEquation);
+ i->fFunctions.fBufferData = WrapGL(context, &GLContext::fBufferData);
+ i->fFunctions.fBufferSubData = WrapGL(context, &GLContext::fBufferSubData);
+ i->fFunctions.fCheckFramebufferStatus = WrapGL(context, &GLContext::fCheckFramebufferStatus);
+ i->fFunctions.fClear = WrapGL(context, &GLContext::fClear);
+ i->fFunctions.fClearColor = WrapGL(context, &GLContext::fClearColor);
+ i->fFunctions.fClearStencil = WrapGL(context, &GLContext::fClearStencil);
+ i->fFunctions.fColorMask = WrapGL(context, &GLContext::fColorMask);
+ i->fFunctions.fCompileShader = WrapGL(context, &GLContext::fCompileShader);
+ i->fFunctions.fCopyTexSubImage2D = WrapGL(context, &GLContext::fCopyTexSubImage2D);
+ i->fFunctions.fCreateProgram = WrapGL(context, &GLContext::fCreateProgram);
+ i->fFunctions.fCreateShader = WrapGL(context, &GLContext::fCreateShader);
+ i->fFunctions.fCullFace = WrapGL(context, &GLContext::fCullFace);
+ i->fFunctions.fDeleteBuffers = WrapGL(context, &GLContext::fDeleteBuffers);
+ i->fFunctions.fDeleteFramebuffers = WrapGL(context, &GLContext::fDeleteFramebuffers);
+ i->fFunctions.fDeleteProgram = WrapGL(context, &GLContext::fDeleteProgram);
+ i->fFunctions.fDeleteRenderbuffers = WrapGL(context, &GLContext::fDeleteRenderbuffers);
+ i->fFunctions.fDeleteShader = WrapGL(context, &GLContext::fDeleteShader);
+ i->fFunctions.fDeleteTextures = WrapGL(context, &GLContext::fDeleteTextures);
+ i->fFunctions.fDepthMask = WrapGL(context, &GLContext::fDepthMask);
+ i->fFunctions.fDisable = WrapGL(context, &GLContext::fDisable);
+ i->fFunctions.fDisableVertexAttribArray = WrapGL(context, &GLContext::fDisableVertexAttribArray);
+ i->fFunctions.fDrawArrays = WrapGL(context, &GLContext::fDrawArrays);
+ i->fFunctions.fDrawElements = WrapGL(context, &GLContext::fDrawElements);
+ i->fFunctions.fDrawRangeElements = WrapGL(context, &GLContext::fDrawRangeElements);
+ i->fFunctions.fEnable = WrapGL(context, &GLContext::fEnable);
+ i->fFunctions.fEnableVertexAttribArray = WrapGL(context, &GLContext::fEnableVertexAttribArray);
+ i->fFunctions.fFinish = WrapGL(context, &GLContext::fFinish);
+ i->fFunctions.fFlush = WrapGL(context, &GLContext::fFlush);
+ i->fFunctions.fFramebufferRenderbuffer = WrapGL(context, &GLContext::fFramebufferRenderbuffer);
+ i->fFunctions.fFramebufferTexture2D = WrapGL(context, &GLContext::fFramebufferTexture2D);
+ i->fFunctions.fFrontFace = WrapGL(context, &GLContext::fFrontFace);
+ i->fFunctions.fGenBuffers = WrapGL(context, &GLContext::fGenBuffers);
+ i->fFunctions.fGenFramebuffers = WrapGL(context, &GLContext::fGenFramebuffers);
+ i->fFunctions.fGenRenderbuffers = WrapGL(context, &GLContext::fGenRenderbuffers);
+ i->fFunctions.fGetFramebufferAttachmentParameteriv = WrapGL(context, &GLContext::fGetFramebufferAttachmentParameteriv);
+ i->fFunctions.fGenTextures = WrapGL(context, &GLContext::fGenTextures);
+ i->fFunctions.fGenerateMipmap = WrapGL(context, &GLContext::fGenerateMipmap);
+ i->fFunctions.fGetBufferParameteriv = WrapGL(context, &GLContext::fGetBufferParameteriv);
+ i->fFunctions.fGetError = WrapGL(context, &GLContext::fGetError);
+ i->fFunctions.fGetIntegerv = getIntegerv;
+ i->fFunctions.fGetProgramInfoLog = WrapGL(context, &GLContext::fGetProgramInfoLog);
+ i->fFunctions.fGetProgramiv = WrapGL(context, &GLContext::fGetProgramiv);
+ i->fFunctions.fGetRenderbufferParameteriv = WrapGL(context, &GLContext::fGetRenderbufferParameteriv);
+ i->fFunctions.fGetShaderInfoLog = WrapGL(context, &GLContext::fGetShaderInfoLog);
+ i->fFunctions.fGetShaderiv = WrapGL(context, &GLContext::fGetShaderiv);
+ i->fFunctions.fGetShaderPrecisionFormat = WrapGL(context, &GLContext::fGetShaderPrecisionFormat);
+ i->fFunctions.fGetString = getString;
+ i->fFunctions.fGetUniformLocation = WrapGL(context, &GLContext::fGetUniformLocation);
+ i->fFunctions.fLineWidth = WrapGL(context, &GLContext::fLineWidth);
+ i->fFunctions.fLinkProgram = WrapGL(context, &GLContext::fLinkProgram);
+ i->fFunctions.fPixelStorei = WrapGL(context, &GLContext::fPixelStorei);
+ i->fFunctions.fReadPixels = WrapGL(context, &GLContext::fReadPixels);
+ i->fFunctions.fRenderbufferStorage = WrapGL(context, &GLContext::fRenderbufferStorage);
+ i->fFunctions.fScissor = WrapGL(context, &GLContext::fScissor);
+ i->fFunctions.fShaderSource = WrapGL(context, &GLContext::fShaderSource);
+ i->fFunctions.fStencilFunc = WrapGL(context, &GLContext::fStencilFunc);
+ i->fFunctions.fStencilMask = WrapGL(context, &GLContext::fStencilMask);
+ i->fFunctions.fStencilOp = WrapGL(context, &GLContext::fStencilOp);
+ i->fFunctions.fTexImage2D = WrapGL(context, &GLContext::fTexImage2D);
+ i->fFunctions.fTexParameteri = WrapGL(context, &GLContext::fTexParameteri);
+ i->fFunctions.fTexParameteriv = WrapGL(context, &GLContext::fTexParameteriv);
+ i->fFunctions.fTexSubImage2D = WrapGL(context, &GLContext::fTexSubImage2D);
+ i->fFunctions.fUniform1f = WrapGL(context, &GLContext::fUniform1f);
+ i->fFunctions.fUniform1i = WrapGL(context, &GLContext::fUniform1i);
+ i->fFunctions.fUniform1fv = WrapGL(context, &GLContext::fUniform1fv);
+ i->fFunctions.fUniform1iv = WrapGL(context, &GLContext::fUniform1iv);
+ i->fFunctions.fUniform2f = WrapGL(context, &GLContext::fUniform2f);
+ i->fFunctions.fUniform2i = WrapGL(context, &GLContext::fUniform2i);
+ i->fFunctions.fUniform2fv = WrapGL(context, &GLContext::fUniform2fv);
+ i->fFunctions.fUniform2iv = WrapGL(context, &GLContext::fUniform2iv);
+ i->fFunctions.fUniform3f = WrapGL(context, &GLContext::fUniform3f);
+ i->fFunctions.fUniform3i = WrapGL(context, &GLContext::fUniform3i);
+ i->fFunctions.fUniform3fv = WrapGL(context, &GLContext::fUniform3fv);
+ i->fFunctions.fUniform3iv = WrapGL(context, &GLContext::fUniform3iv);
+ i->fFunctions.fUniform4f = WrapGL(context, &GLContext::fUniform4f);
+ i->fFunctions.fUniform4i = WrapGL(context, &GLContext::fUniform4i);
+ i->fFunctions.fUniform4fv = WrapGL(context, &GLContext::fUniform4fv);
+ i->fFunctions.fUniform4iv = WrapGL(context, &GLContext::fUniform4iv);
+ i->fFunctions.fUniformMatrix2fv = WrapGL(context, &GLContext::fUniformMatrix2fv);
+ i->fFunctions.fUniformMatrix3fv = WrapGL(context, &GLContext::fUniformMatrix3fv);
+ i->fFunctions.fUniformMatrix4fv = WrapGL(context, &GLContext::fUniformMatrix4fv);
+ i->fFunctions.fUseProgram = WrapGL(context, &GLContext::fUseProgram);
+ i->fFunctions.fVertexAttrib1f = WrapGL(context, &GLContext::fVertexAttrib1f);
+ i->fFunctions.fVertexAttrib2fv = WrapGL(context, &GLContext::fVertexAttrib2fv);
+ i->fFunctions.fVertexAttrib3fv = WrapGL(context, &GLContext::fVertexAttrib3fv);
+ i->fFunctions.fVertexAttrib4fv = WrapGL(context, &GLContext::fVertexAttrib4fv);
+ i->fFunctions.fVertexAttribPointer = WrapGL(context, &GLContext::fVertexAttribPointer);
+ i->fFunctions.fViewport = WrapGL(context, &GLContext::fViewport);
+
+ // Required for either desktop OpenGL 2.0 or OpenGL ES 2.0
+ i->fFunctions.fStencilFuncSeparate = WrapGL(context, &GLContext::fStencilFuncSeparate);
+ i->fFunctions.fStencilMaskSeparate = WrapGL(context, &GLContext::fStencilMaskSeparate);
+ i->fFunctions.fStencilOpSeparate = WrapGL(context, &GLContext::fStencilOpSeparate);
+
+ // GLContext supports glMapBuffer
+ i->fFunctions.fMapBuffer = WrapGL(context, &GLContext::fMapBuffer);
+ i->fFunctions.fUnmapBuffer = WrapGL(context, &GLContext::fUnmapBuffer);
+
+ // GLContext supports glRenderbufferStorageMultisample/glBlitFramebuffer
+ i->fFunctions.fRenderbufferStorageMultisample = WrapGL(context, &GLContext::fRenderbufferStorageMultisample);
+ i->fFunctions.fBlitFramebuffer = WrapGL(context, &GLContext::fBlitFramebuffer);
+
+ // GLContext supports glCompressedTexImage2D
+ i->fFunctions.fCompressedTexImage2D = WrapGL(context, &GLContext::fCompressedTexImage2D);
+
+ // GL_OES_vertex_array_object
+ i->fFunctions.fBindVertexArray = WrapGL(context, &GLContext::fBindVertexArray);
+ i->fFunctions.fDeleteVertexArrays = WrapGL(context, &GLContext::fDeleteVertexArrays);
+ i->fFunctions.fGenVertexArrays = WrapGL(context, &GLContext::fGenVertexArrays);
+
+ // Desktop GL
+ i->fFunctions.fGetTexLevelParameteriv = WrapGL(context, &GLContext::fGetTexLevelParameteriv);
+ i->fFunctions.fDrawBuffer = WrapGL(context, &GLContext::fDrawBuffer);
+ i->fFunctions.fReadBuffer = WrapGL(context, &GLContext::fReadBuffer);
+
+ // Desktop OpenGL > 1.5
+ i->fFunctions.fGenQueries = WrapGL(context, &GLContext::fGenQueries);
+ i->fFunctions.fDeleteQueries = WrapGL(context, &GLContext::fDeleteQueries);
+ i->fFunctions.fBeginQuery = WrapGL(context, &GLContext::fBeginQuery);
+ i->fFunctions.fEndQuery = WrapGL(context, &GLContext::fEndQuery);
+ i->fFunctions.fGetQueryiv = WrapGL(context, &GLContext::fGetQueryiv);
+ i->fFunctions.fGetQueryObjectiv = WrapGL(context, &GLContext::fGetQueryObjectiv);
+ i->fFunctions.fGetQueryObjectuiv = WrapGL(context, &GLContext::fGetQueryObjectuiv);
+
+ // Desktop OpenGL > 2.0
+ i->fFunctions.fDrawBuffers = WrapGL(context, &GLContext::fDrawBuffers);
+
+ return i;
+}
+
+SkiaGLGlue::SkiaGLGlue(GLContext* context)
+ : mGLContext(context)
+{
+ mGrGLInterface.reset(CreateGrGLInterfaceFromGLContext(mGLContext));
+ mGrContext.reset(GrContext::Create(kOpenGL_GrBackend, (GrBackendContext)mGrGLInterface.get()));
+}
+
+SkiaGLGlue::~SkiaGLGlue()
+{
+ /*
+ * These members have inter-dependencies, but do not keep each other alive, so
+ * destruction order is very important here: mGrContext uses mGrGLInterface, and
+ * through it, uses mGLContext
+ */
+ mGrContext = nullptr;
+ if (mGrGLInterface) {
+ // Ensure that no references to the GLContext remain, even if the GrContext still lives.
+ mGrGLInterface->fFunctions = GrGLInterface::Functions();
+ mGrGLInterface = nullptr;
+ }
+ mGLContext = nullptr;
+}