1 /* -*- Mode: c++; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 4; -*- */
2 /* This Source Code Form is subject to the terms of the Mozilla Public
3  * License, v. 2.0. If a copy of the MPL was not distributed with this
4  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
5 
6 #include "skia/include/gpu/GrContext.h"
7 #include "skia/include/gpu/gl/GrGLInterface.h"
8 #include "mozilla/gfx/2D.h"
9 #include "mozilla/ThreadLocal.h"
10 #include "mozilla/DebugOnly.h"
11 
12 /* SkPostConfig.h includes windows.h, which includes windef.h
13  * which redefines min/max. We don't want that. */
14 #ifdef _WIN32
15 #undef min
16 #undef max
17 #endif
18 
19 #include "GLContext.h"
20 #include "SkiaGLGlue.h"
21 
22 using mozilla::gl::GLContext;
23 using mozilla::gl::GLFeature;
24 using mozilla::gl::SkiaGLGlue;
25 
26 template <typename R, typename... A>
WrapGL(RefPtr<GLContext> aContext,R (GLContext::* aFunc)(A...))27 static inline GrGLFunction<R (*)(A...)> WrapGL(RefPtr<GLContext> aContext,
28                                                R (GLContext::*aFunc)(A...)) {
29   return [aContext, aFunc](A... args) -> R {
30     aContext->MakeCurrent();
31     return (aContext->*aFunc)(args...);
32   };
33 }
34 
35 template <typename R, typename... A>
WrapGL(RefPtr<GLContext> aContext,R (* aFunc)(GLContext *,A...))36 static inline GrGLFunction<R (*)(A...)> WrapGL(RefPtr<GLContext> aContext,
37                                                R (*aFunc)(GLContext*, A...)) {
38   return [aContext, aFunc](A... args) -> R {
39     aContext->MakeCurrent();
40     return (*aFunc)(aContext, args...);
41   };
42 }
43 
44 // Core GL functions required by Ganesh
45 
glGetString_mozilla(GLContext * aContext,GrGLenum aName)46 static const GLubyte* glGetString_mozilla(GLContext* aContext, GrGLenum aName) {
47   // GLContext only exposes a OpenGL 2.0 style API, so we have to intercept a
48   // bunch of checks that Ganesh makes to determine which capabilities are
49   // present on the GL implementation and change them to match what GLContext
50   // actually exposes.
51 
52   if (aName == LOCAL_GL_VERSION) {
53     if (aContext->IsGLES()) {
54       return reinterpret_cast<const GLubyte*>("OpenGL ES 2.0");
55     }
56     return reinterpret_cast<const GLubyte*>("2.0");
57   } else if (aName == LOCAL_GL_EXTENSIONS) {
58     // Only expose the bare minimum extensions we want to support to ensure a
59     // functional Ganesh as GLContext only exposes certain extensions
60     static bool extensionsStringBuilt = false;
61     static char extensionsString[1024];
62 
63     if (!extensionsStringBuilt) {
64       extensionsString[0] = '\0';
65 
66       if (aContext->IsGLES()) {
67         // OES is only applicable to GLES2
68         if (aContext->IsExtensionSupported(
69                 GLContext::OES_packed_depth_stencil)) {
70           strcat(extensionsString, "GL_OES_packed_depth_stencil ");
71         }
72 
73         if (aContext->IsExtensionSupported(GLContext::OES_rgb8_rgba8)) {
74           strcat(extensionsString, "GL_OES_rgb8_rgba8 ");
75         }
76 
77         if (aContext->IsExtensionSupported(GLContext::OES_texture_npot)) {
78           strcat(extensionsString, "GL_OES_texture_npot ");
79         }
80 
81         if (aContext->IsExtensionSupported(
82                 GLContext::OES_vertex_array_object)) {
83           strcat(extensionsString, "GL_OES_vertex_array_object ");
84         }
85 
86         if (aContext->IsSupported(GLFeature::standard_derivatives)) {
87           strcat(extensionsString, "GL_OES_standard_derivatives ");
88         }
89       } else {
90         if (aContext->IsSupported(GLFeature::framebuffer_object)) {
91           strcat(extensionsString, "GL_ARB_framebuffer_object ");
92         } else if (aContext->IsExtensionSupported(
93                        GLContext::EXT_framebuffer_object)) {
94           strcat(extensionsString, "GL_EXT_framebuffer_object ");
95         }
96 
97         if (aContext->IsSupported(GLFeature::texture_rg)) {
98           strcat(extensionsString, "GL_ARB_texture_rg ");
99         }
100       }
101 
102       if (aContext->IsExtensionSupported(
103               GLContext::EXT_texture_format_BGRA8888)) {
104         strcat(extensionsString, "GL_EXT_texture_format_BGRA8888 ");
105       }
106 
107       if (aContext->IsExtensionSupported(GLContext::EXT_packed_depth_stencil)) {
108         strcat(extensionsString, "GL_EXT_packed_depth_stencil ");
109       }
110 
111       if (aContext->IsExtensionSupported(GLContext::EXT_bgra)) {
112         strcat(extensionsString, "GL_EXT_bgra ");
113       }
114 
115       if (aContext->IsExtensionSupported(GLContext::EXT_read_format_bgra)) {
116         strcat(extensionsString, "GL_EXT_read_format_bgra ");
117       }
118 
119       extensionsStringBuilt = true;
120 #ifdef DEBUG
121       printf_stderr("Exported SkiaGL extensions: %s\n", extensionsString);
122 #endif
123     }
124 
125     return reinterpret_cast<const GLubyte*>(extensionsString);
126 
127   } else if (aName == LOCAL_GL_SHADING_LANGUAGE_VERSION) {
128     if (aContext->IsGLES()) {
129       return reinterpret_cast<const GLubyte*>("OpenGL ES GLSL ES 1.0");
130     }
131     return reinterpret_cast<const GLubyte*>("1.10");
132   }
133 
134   return aContext->fGetString(aName);
135 }
136 
CreateGrGLInterfaceFromGLContext(GLContext * context)137 static GrGLInterface* CreateGrGLInterfaceFromGLContext(GLContext* context) {
138   auto* i = new GrGLInterface();
139 
140   context->MakeCurrent();
141 
142   // We support both desktop GL and GLES2
143   if (context->IsGLES()) {
144     i->fStandard = kGLES_GrGLStandard;
145   } else {
146     i->fStandard = kGL_GrGLStandard;
147   }
148 
149   GrGLFunction<GrGLGetStringProc> getString =
150       WrapGL(context, &glGetString_mozilla);
151   GrGLFunction<GrGLGetIntegervProc> getIntegerv =
152       WrapGL(context, &GLContext::fGetIntegerv);
153 
154   GrGLExtensions extensions;
155   if (!extensions.init(i->fStandard, getString, nullptr, getIntegerv)) {
156     delete i;
157     return nullptr;
158   }
159 
160   i->fExtensions.swap(&extensions);
161 
162   // Core GL functions required by Ganesh
163   i->fFunctions.fActiveTexture = WrapGL(context, &GLContext::fActiveTexture);
164   i->fFunctions.fAttachShader = WrapGL(context, &GLContext::fAttachShader);
165   i->fFunctions.fBindAttribLocation =
166       WrapGL(context, &GLContext::fBindAttribLocation);
167   i->fFunctions.fBindBuffer = WrapGL(context, &GLContext::fBindBuffer);
168   i->fFunctions.fBindFramebuffer =
169       WrapGL(context, &GLContext::fBindFramebuffer);
170   i->fFunctions.fBindRenderbuffer =
171       WrapGL(context, &GLContext::fBindRenderbuffer);
172   i->fFunctions.fBindTexture = WrapGL(context, &GLContext::fBindTexture);
173   i->fFunctions.fBlendFunc = WrapGL(context, &GLContext::fBlendFunc);
174   i->fFunctions.fBlendColor = WrapGL(context, &GLContext::fBlendColor);
175   i->fFunctions.fBlendEquation = WrapGL(context, &GLContext::fBlendEquation);
176   i->fFunctions.fBufferData = WrapGL(context, &GLContext::fBufferData);
177   i->fFunctions.fBufferSubData = WrapGL(context, &GLContext::fBufferSubData);
178   i->fFunctions.fCheckFramebufferStatus =
179       WrapGL(context, &GLContext::fCheckFramebufferStatus);
180   i->fFunctions.fClear = WrapGL(context, &GLContext::fClear);
181   i->fFunctions.fClearColor = WrapGL(context, &GLContext::fClearColor);
182   i->fFunctions.fClearStencil = WrapGL(context, &GLContext::fClearStencil);
183   i->fFunctions.fColorMask = WrapGL(context, &GLContext::fColorMask);
184   i->fFunctions.fCompileShader = WrapGL(context, &GLContext::fCompileShader);
185   i->fFunctions.fCompressedTexImage2D =
186       WrapGL(context, &GLContext::fCompressedTexImage2D);
187   i->fFunctions.fCompressedTexSubImage2D =
188       WrapGL(context, &GLContext::fCompressedTexSubImage2D);
189   i->fFunctions.fCopyTexSubImage2D =
190       WrapGL(context, &GLContext::fCopyTexSubImage2D);
191   i->fFunctions.fCreateProgram = WrapGL(context, &GLContext::fCreateProgram);
192   i->fFunctions.fCreateShader = WrapGL(context, &GLContext::fCreateShader);
193   i->fFunctions.fCullFace = WrapGL(context, &GLContext::fCullFace);
194   i->fFunctions.fDeleteBuffers = WrapGL(context, &GLContext::fDeleteBuffers);
195   i->fFunctions.fDeleteFramebuffers =
196       WrapGL(context, &GLContext::fDeleteFramebuffers);
197   i->fFunctions.fDeleteProgram = WrapGL(context, &GLContext::fDeleteProgram);
198   i->fFunctions.fDeleteRenderbuffers =
199       WrapGL(context, &GLContext::fDeleteRenderbuffers);
200   i->fFunctions.fDeleteShader = WrapGL(context, &GLContext::fDeleteShader);
201   i->fFunctions.fDeleteTextures = WrapGL(context, &GLContext::fDeleteTextures);
202   i->fFunctions.fDepthMask = WrapGL(context, &GLContext::fDepthMask);
203   i->fFunctions.fDisable = WrapGL(context, &GLContext::fDisable);
204   i->fFunctions.fDisableVertexAttribArray =
205       WrapGL(context, &GLContext::fDisableVertexAttribArray);
206   i->fFunctions.fDrawArrays = WrapGL(context, &GLContext::fDrawArrays);
207   i->fFunctions.fDrawElements = WrapGL(context, &GLContext::fDrawElements);
208   i->fFunctions.fDrawRangeElements =
209       WrapGL(context, &GLContext::fDrawRangeElements);
210   i->fFunctions.fEnable = WrapGL(context, &GLContext::fEnable);
211   i->fFunctions.fEnableVertexAttribArray =
212       WrapGL(context, &GLContext::fEnableVertexAttribArray);
213   i->fFunctions.fFinish = WrapGL(context, &GLContext::fFinish);
214   i->fFunctions.fFlush = WrapGL(context, &GLContext::fFlush);
215   i->fFunctions.fFramebufferRenderbuffer =
216       WrapGL(context, &GLContext::fFramebufferRenderbuffer);
217   i->fFunctions.fFramebufferTexture2D =
218       WrapGL(context, &GLContext::fFramebufferTexture2D);
219   i->fFunctions.fFrontFace = WrapGL(context, &GLContext::fFrontFace);
220   i->fFunctions.fGenBuffers = WrapGL(context, &GLContext::fGenBuffers);
221   i->fFunctions.fGenFramebuffers =
222       WrapGL(context, &GLContext::fGenFramebuffers);
223   i->fFunctions.fGenRenderbuffers =
224       WrapGL(context, &GLContext::fGenRenderbuffers);
225   i->fFunctions.fGetFramebufferAttachmentParameteriv =
226       WrapGL(context, &GLContext::fGetFramebufferAttachmentParameteriv);
227   i->fFunctions.fGenTextures = WrapGL(context, &GLContext::fGenTextures);
228   i->fFunctions.fGenerateMipmap = WrapGL(context, &GLContext::fGenerateMipmap);
229   i->fFunctions.fGetBufferParameteriv =
230       WrapGL(context, &GLContext::fGetBufferParameteriv);
231   i->fFunctions.fGetError = WrapGL(context, &GLContext::fGetError);
232   i->fFunctions.fGetIntegerv = getIntegerv;
233   i->fFunctions.fGetProgramInfoLog =
234       WrapGL(context, &GLContext::fGetProgramInfoLog);
235   i->fFunctions.fGetProgramiv = WrapGL(context, &GLContext::fGetProgramiv);
236   i->fFunctions.fGetRenderbufferParameteriv =
237       WrapGL(context, &GLContext::fGetRenderbufferParameteriv);
238   i->fFunctions.fGetShaderInfoLog =
239       WrapGL(context, &GLContext::fGetShaderInfoLog);
240   i->fFunctions.fGetShaderiv = WrapGL(context, &GLContext::fGetShaderiv);
241   i->fFunctions.fGetShaderPrecisionFormat =
242       WrapGL(context, &GLContext::fGetShaderPrecisionFormat);
243   i->fFunctions.fGetString = getString;
244   i->fFunctions.fGetUniformLocation =
245       WrapGL(context, &GLContext::fGetUniformLocation);
246   i->fFunctions.fIsTexture = WrapGL(context, &GLContext::fIsTexture);
247   i->fFunctions.fLineWidth = WrapGL(context, &GLContext::fLineWidth);
248   i->fFunctions.fLinkProgram = WrapGL(context, &GLContext::fLinkProgram);
249   i->fFunctions.fPixelStorei = WrapGL(context, &GLContext::fPixelStorei);
250   i->fFunctions.fPolygonMode = WrapGL(context, &GLContext::fPolygonMode);
251   i->fFunctions.fReadPixels = WrapGL(context, &GLContext::fReadPixels);
252   i->fFunctions.fRenderbufferStorage =
253       WrapGL(context, &GLContext::fRenderbufferStorage);
254   i->fFunctions.fScissor = WrapGL(context, &GLContext::fScissor);
255   i->fFunctions.fShaderSource = WrapGL(context, &GLContext::fShaderSource);
256   i->fFunctions.fStencilFunc = WrapGL(context, &GLContext::fStencilFunc);
257   i->fFunctions.fStencilFuncSeparate =
258       WrapGL(context, &GLContext::fStencilFuncSeparate);
259   i->fFunctions.fStencilMask = WrapGL(context, &GLContext::fStencilMask);
260   i->fFunctions.fStencilMaskSeparate =
261       WrapGL(context, &GLContext::fStencilMaskSeparate);
262   i->fFunctions.fStencilOp = WrapGL(context, &GLContext::fStencilOp);
263   i->fFunctions.fStencilOpSeparate =
264       WrapGL(context, &GLContext::fStencilOpSeparate);
265   i->fFunctions.fTexImage2D = WrapGL(context, &GLContext::fTexImage2D);
266   i->fFunctions.fTexParameteri = WrapGL(context, &GLContext::fTexParameteri);
267   i->fFunctions.fTexParameteriv = WrapGL(context, &GLContext::fTexParameteriv);
268   i->fFunctions.fTexSubImage2D = WrapGL(context, &GLContext::fTexSubImage2D);
269   i->fFunctions.fUniform1f = WrapGL(context, &GLContext::fUniform1f);
270   i->fFunctions.fUniform1i = WrapGL(context, &GLContext::fUniform1i);
271   i->fFunctions.fUniform1fv = WrapGL(context, &GLContext::fUniform1fv);
272   i->fFunctions.fUniform1iv = WrapGL(context, &GLContext::fUniform1iv);
273   i->fFunctions.fUniform2f = WrapGL(context, &GLContext::fUniform2f);
274   i->fFunctions.fUniform2i = WrapGL(context, &GLContext::fUniform2i);
275   i->fFunctions.fUniform2fv = WrapGL(context, &GLContext::fUniform2fv);
276   i->fFunctions.fUniform2iv = WrapGL(context, &GLContext::fUniform2iv);
277   i->fFunctions.fUniform3f = WrapGL(context, &GLContext::fUniform3f);
278   i->fFunctions.fUniform3i = WrapGL(context, &GLContext::fUniform3i);
279   i->fFunctions.fUniform3fv = WrapGL(context, &GLContext::fUniform3fv);
280   i->fFunctions.fUniform3iv = WrapGL(context, &GLContext::fUniform3iv);
281   i->fFunctions.fUniform4f = WrapGL(context, &GLContext::fUniform4f);
282   i->fFunctions.fUniform4i = WrapGL(context, &GLContext::fUniform4i);
283   i->fFunctions.fUniform4fv = WrapGL(context, &GLContext::fUniform4fv);
284   i->fFunctions.fUniform4iv = WrapGL(context, &GLContext::fUniform4iv);
285   i->fFunctions.fUniformMatrix2fv =
286       WrapGL(context, &GLContext::fUniformMatrix2fv);
287   i->fFunctions.fUniformMatrix3fv =
288       WrapGL(context, &GLContext::fUniformMatrix3fv);
289   i->fFunctions.fUniformMatrix4fv =
290       WrapGL(context, &GLContext::fUniformMatrix4fv);
291   i->fFunctions.fUseProgram = WrapGL(context, &GLContext::fUseProgram);
292   i->fFunctions.fVertexAttrib1f = WrapGL(context, &GLContext::fVertexAttrib1f);
293   i->fFunctions.fVertexAttrib2fv =
294       WrapGL(context, &GLContext::fVertexAttrib2fv);
295   i->fFunctions.fVertexAttrib3fv =
296       WrapGL(context, &GLContext::fVertexAttrib3fv);
297   i->fFunctions.fVertexAttrib4fv =
298       WrapGL(context, &GLContext::fVertexAttrib4fv);
299   i->fFunctions.fVertexAttribPointer =
300       WrapGL(context, &GLContext::fVertexAttribPointer);
301   i->fFunctions.fViewport = WrapGL(context, &GLContext::fViewport);
302 
303   // Required for either desktop OpenGL 2.0 or OpenGL ES 2.0
304   i->fFunctions.fStencilFuncSeparate =
305       WrapGL(context, &GLContext::fStencilFuncSeparate);
306   i->fFunctions.fStencilMaskSeparate =
307       WrapGL(context, &GLContext::fStencilMaskSeparate);
308   i->fFunctions.fStencilOpSeparate =
309       WrapGL(context, &GLContext::fStencilOpSeparate);
310 
311   // GLContext supports glMapBuffer
312   i->fFunctions.fMapBuffer = WrapGL(context, &GLContext::fMapBuffer);
313   i->fFunctions.fUnmapBuffer = WrapGL(context, &GLContext::fUnmapBuffer);
314 
315   // GLContext supports glRenderbufferStorageMultisample/glBlitFramebuffer
316   i->fFunctions.fRenderbufferStorageMultisample =
317       WrapGL(context, &GLContext::fRenderbufferStorageMultisample);
318   i->fFunctions.fBlitFramebuffer =
319       WrapGL(context, &GLContext::fBlitFramebuffer);
320 
321   // GLContext supports glCompressedTexImage2D
322   i->fFunctions.fCompressedTexImage2D =
323       WrapGL(context, &GLContext::fCompressedTexImage2D);
324 
325   // GL_OES_vertex_array_object
326   i->fFunctions.fBindVertexArray =
327       WrapGL(context, &GLContext::fBindVertexArray);
328   i->fFunctions.fDeleteVertexArrays =
329       WrapGL(context, &GLContext::fDeleteVertexArrays);
330   i->fFunctions.fGenVertexArrays =
331       WrapGL(context, &GLContext::fGenVertexArrays);
332 
333   // Desktop GL
334   i->fFunctions.fGetTexLevelParameteriv =
335       WrapGL(context, &GLContext::fGetTexLevelParameteriv);
336   i->fFunctions.fDrawBuffer = WrapGL(context, &GLContext::fDrawBuffer);
337   i->fFunctions.fReadBuffer = WrapGL(context, &GLContext::fReadBuffer);
338 
339   // Desktop OpenGL > 1.5
340   i->fFunctions.fGenQueries = WrapGL(context, &GLContext::fGenQueries);
341   i->fFunctions.fDeleteQueries = WrapGL(context, &GLContext::fDeleteQueries);
342   i->fFunctions.fBeginQuery = WrapGL(context, &GLContext::fBeginQuery);
343   i->fFunctions.fEndQuery = WrapGL(context, &GLContext::fEndQuery);
344   i->fFunctions.fGetQueryiv = WrapGL(context, &GLContext::fGetQueryiv);
345   i->fFunctions.fGetQueryObjectiv =
346       WrapGL(context, &GLContext::fGetQueryObjectiv);
347   i->fFunctions.fGetQueryObjectuiv =
348       WrapGL(context, &GLContext::fGetQueryObjectuiv);
349 
350   // Desktop OpenGL > 2.0
351   i->fFunctions.fDrawBuffers = WrapGL(context, &GLContext::fDrawBuffers);
352 
353   return i;
354 }
355 
SkiaGLGlue(GLContext * context)356 SkiaGLGlue::SkiaGLGlue(GLContext* context) : mGLContext(context) {
357   mGrGLInterface.reset(CreateGrGLInterfaceFromGLContext(mGLContext));
358   mGrContext.reset(GrContext::Create(kOpenGL_GrBackend,
359                                      (GrBackendContext)mGrGLInterface.get()));
360 }
361 
~SkiaGLGlue()362 SkiaGLGlue::~SkiaGLGlue() {
363   /*
364    * These members have inter-dependencies, but do not keep each other alive, so
365    * destruction order is very important here: mGrContext uses mGrGLInterface,
366    * and through it, uses mGLContext
367    */
368   mGrContext = nullptr;
369   if (mGrGLInterface) {
370     // Ensure that no references to the GLContext remain, even if the GrContext
371     // still lives.
372     mGrGLInterface->fFunctions = GrGLInterface::Functions();
373     mGrGLInterface = nullptr;
374   }
375   mGLContext = nullptr;
376 }
377