1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /* vim: set ts=8 sts=4 et sw=4 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6
7 #include "GLContext.h"
8
9 #include <algorithm>
10 #include <stdio.h>
11 #include <string.h>
12 #include <ctype.h>
13 #include <regex>
14 #include <string>
15 #include <vector>
16 #ifdef MOZ_WIDGET_ANDROID
17 #include <sys/mman.h>
18 #endif
19
20 #include "GLBlitHelper.h"
21 #include "GLReadTexImageHelper.h"
22 #include "GLScreenBuffer.h"
23
24 #include "gfxCrashReporterUtils.h"
25 #include "gfxEnv.h"
26 #include "gfxUtils.h"
27 #include "GLContextProvider.h"
28 #include "GLTextureImage.h"
29 #include "nsPrintfCString.h"
30 #include "nsThreadUtils.h"
31 #include "prenv.h"
32 #include "prlink.h"
33 #include "ScopedGLHelpers.h"
34 #include "SharedSurfaceGL.h"
35 #include "GfxTexturesReporter.h"
36 #include "gfx2DGlue.h"
37 #include "gfxPrefs.h"
38 #include "mozilla/IntegerPrintfMacros.h"
39 #include "mozilla/gfx/Logging.h"
40
41 #include "OGLShaderProgram.h" // for ShaderProgramType
42
43 #include "mozilla/DebugOnly.h"
44
45 #ifdef XP_MACOSX
46 #include <CoreServices/CoreServices.h>
47 #endif
48
49 #if defined(MOZ_WIDGET_COCOA)
50 #include "nsCocoaFeatures.h"
51 #endif
52
53 #ifdef MOZ_WIDGET_ANDROID
54 #include "AndroidBridge.h"
55 #endif
56
57 namespace mozilla {
58 namespace gl {
59
60 using namespace mozilla::gfx;
61 using namespace mozilla::layers;
62
63 MOZ_THREAD_LOCAL(uintptr_t) GLContext::sCurrentContext;
64
65 // If adding defines, don't forget to undefine symbols. See #undef block below.
66 // clang-format off
67 #define CORE_SYMBOL(x) { (PRFuncPtr*) &mSymbols.f##x, { #x, nullptr } }
68 #define CORE_EXT_SYMBOL2(x,y,z) { (PRFuncPtr*) &mSymbols.f##x, { #x, #x #y, #x #z, nullptr } }
69 #define EXT_SYMBOL2(x,y,z) { (PRFuncPtr*) &mSymbols.f##x, { #x #y, #x #z, nullptr } }
70 #define EXT_SYMBOL3(x,y,z,w) { (PRFuncPtr*) &mSymbols.f##x, { #x #y, #x #z, #x #w, nullptr } }
71 #define END_SYMBOLS { nullptr, { nullptr } }
72 // clang-format on
73
74 // should match the order of GLExtensions, and be null-terminated.
75 static const char* const sExtensionNames[] = {
76 "NO_EXTENSION",
77 "GL_AMD_compressed_ATC_texture",
78 "GL_ANGLE_depth_texture",
79 "GL_ANGLE_framebuffer_blit",
80 "GL_ANGLE_framebuffer_multisample",
81 "GL_ANGLE_instanced_arrays",
82 "GL_ANGLE_texture_compression_dxt3",
83 "GL_ANGLE_texture_compression_dxt5",
84 "GL_ANGLE_timer_query",
85 "GL_APPLE_client_storage",
86 "GL_APPLE_framebuffer_multisample",
87 "GL_APPLE_sync",
88 "GL_APPLE_texture_range",
89 "GL_APPLE_vertex_array_object",
90 "GL_ARB_ES2_compatibility",
91 "GL_ARB_ES3_compatibility",
92 "GL_ARB_color_buffer_float",
93 "GL_ARB_compatibility",
94 "GL_ARB_copy_buffer",
95 "GL_ARB_depth_texture",
96 "GL_ARB_draw_buffers",
97 "GL_ARB_draw_instanced",
98 "GL_ARB_framebuffer_object",
99 "GL_ARB_framebuffer_sRGB",
100 "GL_ARB_geometry_shader4",
101 "GL_ARB_half_float_pixel",
102 "GL_ARB_instanced_arrays",
103 "GL_ARB_internalformat_query",
104 "GL_ARB_invalidate_subdata",
105 "GL_ARB_map_buffer_range",
106 "GL_ARB_occlusion_query2",
107 "GL_ARB_pixel_buffer_object",
108 "GL_ARB_robust_buffer_access_behavior",
109 "GL_ARB_robustness",
110 "GL_ARB_sampler_objects",
111 "GL_ARB_seamless_cube_map",
112 "GL_ARB_shader_texture_lod",
113 "GL_ARB_sync",
114 "GL_ARB_texture_compression",
115 "GL_ARB_texture_float",
116 "GL_ARB_texture_non_power_of_two",
117 "GL_ARB_texture_rectangle",
118 "GL_ARB_texture_rg",
119 "GL_ARB_texture_storage",
120 "GL_ARB_texture_swizzle",
121 "GL_ARB_timer_query",
122 "GL_ARB_transform_feedback2",
123 "GL_ARB_uniform_buffer_object",
124 "GL_ARB_vertex_array_object",
125 "GL_EXT_bgra",
126 "GL_EXT_blend_minmax",
127 "GL_EXT_color_buffer_float",
128 "GL_EXT_color_buffer_half_float",
129 "GL_EXT_copy_texture",
130 "GL_EXT_disjoint_timer_query",
131 "GL_EXT_draw_buffers",
132 "GL_EXT_draw_buffers2",
133 "GL_EXT_draw_instanced",
134 "GL_EXT_draw_range_elements",
135 "GL_EXT_frag_depth",
136 "GL_EXT_framebuffer_blit",
137 "GL_EXT_framebuffer_multisample",
138 "GL_EXT_framebuffer_object",
139 "GL_EXT_framebuffer_sRGB",
140 "GL_EXT_gpu_shader4",
141 "GL_EXT_multisampled_render_to_texture",
142 "GL_EXT_occlusion_query_boolean",
143 "GL_EXT_packed_depth_stencil",
144 "GL_EXT_read_format_bgra",
145 "GL_EXT_robustness",
146 "GL_EXT_sRGB",
147 "GL_EXT_sRGB_write_control",
148 "GL_EXT_shader_texture_lod",
149 "GL_EXT_texture3D",
150 "GL_EXT_texture_compression_dxt1",
151 "GL_EXT_texture_compression_s3tc",
152 "GL_EXT_texture_compression_s3tc_srgb",
153 "GL_EXT_texture_filter_anisotropic",
154 "GL_EXT_texture_format_BGRA8888",
155 "GL_EXT_texture_sRGB",
156 "GL_EXT_texture_storage",
157 "GL_EXT_timer_query",
158 "GL_EXT_transform_feedback",
159 "GL_EXT_unpack_subimage",
160 "GL_IMG_read_format",
161 "GL_IMG_texture_compression_pvrtc",
162 "GL_IMG_texture_npot",
163 "GL_KHR_debug",
164 "GL_KHR_robust_buffer_access_behavior",
165 "GL_KHR_robustness",
166 "GL_KHR_texture_compression_astc_hdr",
167 "GL_KHR_texture_compression_astc_ldr",
168 "GL_NV_draw_instanced",
169 "GL_NV_fence",
170 "GL_NV_framebuffer_blit",
171 "GL_NV_geometry_program4",
172 "GL_NV_half_float",
173 "GL_NV_instanced_arrays",
174 "GL_NV_primitive_restart",
175 "GL_NV_texture_barrier",
176 "GL_NV_transform_feedback",
177 "GL_NV_transform_feedback2",
178 "GL_OES_EGL_image",
179 "GL_OES_EGL_image_external",
180 "GL_OES_EGL_sync",
181 "GL_OES_compressed_ETC1_RGB8_texture",
182 "GL_OES_depth24",
183 "GL_OES_depth32",
184 "GL_OES_depth_texture",
185 "GL_OES_element_index_uint",
186 "GL_OES_framebuffer_object",
187 "GL_OES_packed_depth_stencil",
188 "GL_OES_rgb8_rgba8",
189 "GL_OES_standard_derivatives",
190 "GL_OES_stencil8",
191 "GL_OES_texture_3D",
192 "GL_OES_texture_float",
193 "GL_OES_texture_float_linear",
194 "GL_OES_texture_half_float",
195 "GL_OES_texture_half_float_linear",
196 "GL_OES_texture_npot",
197 "GL_OES_vertex_array_object"};
198
ShouldUseTLSIsCurrent(bool useTLSIsCurrent)199 static bool ShouldUseTLSIsCurrent(bool useTLSIsCurrent) {
200 if (gfxPrefs::UseTLSIsCurrent() == 0) return useTLSIsCurrent;
201
202 return gfxPrefs::UseTLSIsCurrent() > 0;
203 }
204
ParseVersion(const std::string & versionStr,uint32_t * const out_major,uint32_t * const out_minor)205 static bool ParseVersion(const std::string& versionStr,
206 uint32_t* const out_major, uint32_t* const out_minor) {
207 static const std::regex kVersionRegex("([0-9]+)\\.([0-9]+)");
208 std::smatch match;
209 if (!std::regex_search(versionStr, match, kVersionRegex)) return false;
210
211 const auto& majorStr = match.str(1);
212 const auto& minorStr = match.str(2);
213 *out_major = atoi(majorStr.c_str());
214 *out_minor = atoi(minorStr.c_str());
215 return true;
216 }
217
ChooseDebugFlags(CreateContextFlags createFlags)218 static uint8_t ChooseDebugFlags(CreateContextFlags createFlags) {
219 uint8_t debugFlags = 0;
220
221 #ifdef MOZ_GL_DEBUG
222 if (gfxEnv::GlDebug()) {
223 debugFlags |= GLContext::DebugFlagEnabled;
224 }
225
226 // Enables extra verbose output, informing of the start and finish of every GL
227 // call. Useful e.g. to record information to investigate graphics system
228 // crashes/lockups
229 if (gfxEnv::GlDebugVerbose()) {
230 debugFlags |= GLContext::DebugFlagTrace;
231 }
232
233 // Aborts on GL error. Can be useful to debug quicker code that is known not
234 // to generate any GL error in principle.
235 bool abortOnError = false;
236
237 if (createFlags & CreateContextFlags::NO_VALIDATION) {
238 abortOnError = true;
239
240 const auto fnStringsMatch = [](const char* a, const char* b) {
241 return strcmp(a, b) == 0;
242 };
243
244 const char* envAbortOnError = PR_GetEnv("MOZ_GL_DEBUG_ABORT_ON_ERROR");
245 if (envAbortOnError && fnStringsMatch(envAbortOnError, "0")) {
246 abortOnError = false;
247 }
248 }
249
250 if (abortOnError) {
251 debugFlags |= GLContext::DebugFlagAbortOnError;
252 }
253 #endif
254
255 return debugFlags;
256 }
257
GLContext(CreateContextFlags flags,const SurfaceCaps & caps,GLContext * sharedContext,bool isOffscreen,bool useTLSIsCurrent)258 GLContext::GLContext(CreateContextFlags flags, const SurfaceCaps& caps,
259 GLContext* sharedContext, bool isOffscreen,
260 bool useTLSIsCurrent)
261 : mImplicitMakeCurrent(false),
262 mUseTLSIsCurrent(ShouldUseTLSIsCurrent(useTLSIsCurrent)),
263 mIsOffscreen(isOffscreen),
264 mContextLost(false),
265 mVersion(0),
266 mProfile(ContextProfile::Unknown),
267 mShadingLanguageVersion(0),
268 mVendor(GLVendor::Other),
269 mRenderer(GLRenderer::Other),
270 mTopError(LOCAL_GL_NO_ERROR),
271 mDebugFlags(ChooseDebugFlags(flags)),
272 mSharedContext(sharedContext),
273 mSymbols{},
274 mCaps(caps),
275 mScreen(nullptr),
276 mLockedSurface(nullptr),
277 mMaxTextureSize(0),
278 mMaxCubeMapTextureSize(0),
279 mMaxTextureImageSize(0),
280 mMaxRenderbufferSize(0),
281 mMaxSamples(0),
282 mNeedsTextureSizeChecks(false),
283 mNeedsFlushBeforeDeleteFB(false),
284 mTextureAllocCrashesOnMapFailure(false),
285 mNeedsCheckAfterAttachTextureToFb(false),
286 mWorkAroundDriverBugs(true),
287 mSyncGLCallCount(0),
288 mHeavyGLCallsSinceLastFlush(false) {
289 mMaxViewportDims[0] = 0;
290 mMaxViewportDims[1] = 0;
291 mOwningThreadId = PlatformThread::CurrentId();
292 MOZ_ALWAYS_TRUE(sCurrentContext.init());
293 sCurrentContext.set(0);
294 }
295
~GLContext()296 GLContext::~GLContext() {
297 NS_ASSERTION(
298 IsDestroyed(),
299 "GLContext implementation must call MarkDestroyed in destructor!");
300 #ifdef MOZ_GL_DEBUG
301 if (mSharedContext) {
302 GLContext* tip = mSharedContext;
303 while (tip->mSharedContext) tip = tip->mSharedContext;
304 tip->SharedContextDestroyed(this);
305 tip->ReportOutstandingNames();
306 } else {
307 ReportOutstandingNames();
308 }
309 #endif
310 }
311
StaticDebugCallback(GLenum source,GLenum type,GLuint id,GLenum severity,GLsizei length,const GLchar * message,const GLvoid * userParam)312 /*static*/ void GLContext::StaticDebugCallback(GLenum source, GLenum type,
313 GLuint id, GLenum severity,
314 GLsizei length,
315 const GLchar* message,
316 const GLvoid* userParam) {
317 GLContext* gl = (GLContext*)userParam;
318 gl->DebugCallback(source, type, id, severity, length, message);
319 }
320
ClearSymbols(const GLLibraryLoader::SymLoadStruct * symbols)321 static void ClearSymbols(const GLLibraryLoader::SymLoadStruct* symbols) {
322 while (symbols->symPointer) {
323 *symbols->symPointer = nullptr;
324 symbols++;
325 }
326 }
327
InitWithPrefix(const char * prefix,bool trygl)328 bool GLContext::InitWithPrefix(const char* prefix, bool trygl) {
329 MOZ_RELEASE_ASSERT(!mSymbols.fBindFramebuffer,
330 "GFX: InitWithPrefix should only be called once.");
331
332 ScopedGfxFeatureReporter reporter("GL Context");
333
334 if (!InitWithPrefixImpl(prefix, trygl)) {
335 // If initialization fails, zero the symbols to avoid hard-to-understand
336 // bugs.
337 mSymbols = {};
338 NS_WARNING("GLContext::InitWithPrefix failed!");
339 return false;
340 }
341
342 reporter.SetSuccessful();
343 return true;
344 }
345
LoadGLSymbols(GLContext * gl,const char * prefix,bool trygl,const GLLibraryLoader::SymLoadStruct * list,const char * desc)346 static bool LoadGLSymbols(GLContext* gl, const char* prefix, bool trygl,
347 const GLLibraryLoader::SymLoadStruct* list,
348 const char* desc) {
349 if (gl->LoadSymbols(list, trygl, prefix)) return true;
350
351 ClearSymbols(list);
352
353 if (desc) {
354 const nsPrintfCString err("Failed to load symbols for %s.", desc);
355 NS_ERROR(err.BeginReading());
356 }
357 return false;
358 }
359
LoadExtSymbols(const char * prefix,bool trygl,const SymLoadStruct * list,GLExtensions ext)360 bool GLContext::LoadExtSymbols(const char* prefix, bool trygl,
361 const SymLoadStruct* list, GLExtensions ext) {
362 const char* extName = sExtensionNames[size_t(ext)];
363 if (!LoadGLSymbols(this, prefix, trygl, list, extName)) {
364 MarkExtensionUnsupported(ext);
365 return false;
366 }
367 return true;
368 };
369
LoadFeatureSymbols(const char * prefix,bool trygl,const SymLoadStruct * list,GLFeature feature)370 bool GLContext::LoadFeatureSymbols(const char* prefix, bool trygl,
371 const SymLoadStruct* list,
372 GLFeature feature) {
373 const char* featureName = GetFeatureName(feature);
374 if (!LoadGLSymbols(this, prefix, trygl, list, featureName)) {
375 MarkUnsupported(feature);
376 return false;
377 }
378 return true;
379 };
380
InitWithPrefixImpl(const char * prefix,bool trygl)381 bool GLContext::InitWithPrefixImpl(const char* prefix, bool trygl) {
382 mWorkAroundDriverBugs = gfxPrefs::WorkAroundDriverBugs();
383
384 // clang-format off
385 const SymLoadStruct coreSymbols[] = {
386 { (PRFuncPtr*) &mSymbols.fActiveTexture, { "ActiveTexture", "ActiveTextureARB", nullptr } },
387 { (PRFuncPtr*) &mSymbols.fAttachShader, { "AttachShader", "AttachShaderARB", nullptr } },
388 { (PRFuncPtr*) &mSymbols.fBindAttribLocation, { "BindAttribLocation", "BindAttribLocationARB", nullptr } },
389 { (PRFuncPtr*) &mSymbols.fBindBuffer, { "BindBuffer", "BindBufferARB", nullptr } },
390 { (PRFuncPtr*) &mSymbols.fBindTexture, { "BindTexture", "BindTextureARB", nullptr } },
391 { (PRFuncPtr*) &mSymbols.fBlendColor, { "BlendColor", nullptr } },
392 { (PRFuncPtr*) &mSymbols.fBlendEquation, { "BlendEquation", nullptr } },
393 { (PRFuncPtr*) &mSymbols.fBlendEquationSeparate, { "BlendEquationSeparate", "BlendEquationSeparateEXT", nullptr } },
394 { (PRFuncPtr*) &mSymbols.fBlendFunc, { "BlendFunc", nullptr } },
395 { (PRFuncPtr*) &mSymbols.fBlendFuncSeparate, { "BlendFuncSeparate", "BlendFuncSeparateEXT", nullptr } },
396 { (PRFuncPtr*) &mSymbols.fBufferData, { "BufferData", nullptr } },
397 { (PRFuncPtr*) &mSymbols.fBufferSubData, { "BufferSubData", nullptr } },
398 { (PRFuncPtr*) &mSymbols.fClear, { "Clear", nullptr } },
399 { (PRFuncPtr*) &mSymbols.fClearColor, { "ClearColor", nullptr } },
400 { (PRFuncPtr*) &mSymbols.fClearStencil, { "ClearStencil", nullptr } },
401 { (PRFuncPtr*) &mSymbols.fColorMask, { "ColorMask", nullptr } },
402 { (PRFuncPtr*) &mSymbols.fCompressedTexImage2D, {"CompressedTexImage2D", nullptr} },
403 { (PRFuncPtr*) &mSymbols.fCompressedTexSubImage2D, {"CompressedTexSubImage2D", nullptr} },
404 { (PRFuncPtr*) &mSymbols.fCullFace, { "CullFace", nullptr } },
405 { (PRFuncPtr*) &mSymbols.fDetachShader, { "DetachShader", "DetachShaderARB", nullptr } },
406 { (PRFuncPtr*) &mSymbols.fDepthFunc, { "DepthFunc", nullptr } },
407 { (PRFuncPtr*) &mSymbols.fDepthMask, { "DepthMask", nullptr } },
408 { (PRFuncPtr*) &mSymbols.fDisable, { "Disable", nullptr } },
409 { (PRFuncPtr*) &mSymbols.fDisableVertexAttribArray, { "DisableVertexAttribArray", "DisableVertexAttribArrayARB", nullptr } },
410 { (PRFuncPtr*) &mSymbols.fDrawArrays, { "DrawArrays", nullptr } },
411 { (PRFuncPtr*) &mSymbols.fDrawElements, { "DrawElements", nullptr } },
412 { (PRFuncPtr*) &mSymbols.fEnable, { "Enable", nullptr } },
413 { (PRFuncPtr*) &mSymbols.fEnableVertexAttribArray, { "EnableVertexAttribArray", "EnableVertexAttribArrayARB", nullptr } },
414 { (PRFuncPtr*) &mSymbols.fFinish, { "Finish", nullptr } },
415 { (PRFuncPtr*) &mSymbols.fFlush, { "Flush", nullptr } },
416 { (PRFuncPtr*) &mSymbols.fFrontFace, { "FrontFace", nullptr } },
417 { (PRFuncPtr*) &mSymbols.fGetActiveAttrib, { "GetActiveAttrib", "GetActiveAttribARB", nullptr } },
418 { (PRFuncPtr*) &mSymbols.fGetActiveUniform, { "GetActiveUniform", "GetActiveUniformARB", nullptr } },
419 { (PRFuncPtr*) &mSymbols.fGetAttachedShaders, { "GetAttachedShaders", "GetAttachedShadersARB", nullptr } },
420 { (PRFuncPtr*) &mSymbols.fGetAttribLocation, { "GetAttribLocation", "GetAttribLocationARB", nullptr } },
421 { (PRFuncPtr*) &mSymbols.fGetIntegerv, { "GetIntegerv", nullptr } },
422 { (PRFuncPtr*) &mSymbols.fGetFloatv, { "GetFloatv", nullptr } },
423 { (PRFuncPtr*) &mSymbols.fGetBooleanv, { "GetBooleanv", nullptr } },
424 { (PRFuncPtr*) &mSymbols.fGetBufferParameteriv, { "GetBufferParameteriv", "GetBufferParameterivARB", nullptr } },
425 { (PRFuncPtr*) &mSymbols.fGetError, { "GetError", nullptr } },
426 { (PRFuncPtr*) &mSymbols.fGetProgramiv, { "GetProgramiv", "GetProgramivARB", nullptr } },
427 { (PRFuncPtr*) &mSymbols.fGetProgramInfoLog, { "GetProgramInfoLog", "GetProgramInfoLogARB", nullptr } },
428 { (PRFuncPtr*) &mSymbols.fTexParameteri, { "TexParameteri", nullptr } },
429 { (PRFuncPtr*) &mSymbols.fTexParameteriv, { "TexParameteriv", nullptr } },
430 { (PRFuncPtr*) &mSymbols.fTexParameterf, { "TexParameterf", nullptr } },
431 { (PRFuncPtr*) &mSymbols.fGetString, { "GetString", nullptr } },
432 { (PRFuncPtr*) &mSymbols.fGetTexParameterfv, { "GetTexParameterfv", nullptr } },
433 { (PRFuncPtr*) &mSymbols.fGetTexParameteriv, { "GetTexParameteriv", nullptr } },
434 { (PRFuncPtr*) &mSymbols.fGetUniformfv, { "GetUniformfv", "GetUniformfvARB", nullptr } },
435 { (PRFuncPtr*) &mSymbols.fGetUniformiv, { "GetUniformiv", "GetUniformivARB", nullptr } },
436 { (PRFuncPtr*) &mSymbols.fGetUniformLocation, { "GetUniformLocation", "GetUniformLocationARB", nullptr } },
437 { (PRFuncPtr*) &mSymbols.fGetVertexAttribfv, { "GetVertexAttribfv", "GetVertexAttribfvARB", nullptr } },
438 { (PRFuncPtr*) &mSymbols.fGetVertexAttribiv, { "GetVertexAttribiv", "GetVertexAttribivARB", nullptr } },
439 { (PRFuncPtr*) &mSymbols.fGetVertexAttribPointerv, { "GetVertexAttribPointerv", nullptr } },
440 { (PRFuncPtr*) &mSymbols.fHint, { "Hint", nullptr } },
441 { (PRFuncPtr*) &mSymbols.fIsBuffer, { "IsBuffer", "IsBufferARB", nullptr } },
442 { (PRFuncPtr*) &mSymbols.fIsEnabled, { "IsEnabled", nullptr } },
443 { (PRFuncPtr*) &mSymbols.fIsProgram, { "IsProgram", "IsProgramARB", nullptr } },
444 { (PRFuncPtr*) &mSymbols.fIsShader, { "IsShader", "IsShaderARB", nullptr } },
445 { (PRFuncPtr*) &mSymbols.fIsTexture, { "IsTexture", "IsTextureARB", nullptr } },
446 { (PRFuncPtr*) &mSymbols.fLineWidth, { "LineWidth", nullptr } },
447 { (PRFuncPtr*) &mSymbols.fLinkProgram, { "LinkProgram", "LinkProgramARB", nullptr } },
448 { (PRFuncPtr*) &mSymbols.fPixelStorei, { "PixelStorei", nullptr } },
449 { (PRFuncPtr*) &mSymbols.fPolygonOffset, { "PolygonOffset", nullptr } },
450 { (PRFuncPtr*) &mSymbols.fReadPixels, { "ReadPixels", nullptr } },
451 { (PRFuncPtr*) &mSymbols.fSampleCoverage, { "SampleCoverage", nullptr } },
452 { (PRFuncPtr*) &mSymbols.fScissor, { "Scissor", nullptr } },
453 { (PRFuncPtr*) &mSymbols.fStencilFunc, { "StencilFunc", nullptr } },
454 { (PRFuncPtr*) &mSymbols.fStencilFuncSeparate, { "StencilFuncSeparate", "StencilFuncSeparateEXT", nullptr } },
455 { (PRFuncPtr*) &mSymbols.fStencilMask, { "StencilMask", nullptr } },
456 { (PRFuncPtr*) &mSymbols.fStencilMaskSeparate, { "StencilMaskSeparate", "StencilMaskSeparateEXT", nullptr } },
457 { (PRFuncPtr*) &mSymbols.fStencilOp, { "StencilOp", nullptr } },
458 { (PRFuncPtr*) &mSymbols.fStencilOpSeparate, { "StencilOpSeparate", "StencilOpSeparateEXT", nullptr } },
459 { (PRFuncPtr*) &mSymbols.fTexImage2D, { "TexImage2D", nullptr } },
460 { (PRFuncPtr*) &mSymbols.fTexSubImage2D, { "TexSubImage2D", nullptr } },
461 { (PRFuncPtr*) &mSymbols.fUniform1f, { "Uniform1f", nullptr } },
462 { (PRFuncPtr*) &mSymbols.fUniform1fv, { "Uniform1fv", nullptr } },
463 { (PRFuncPtr*) &mSymbols.fUniform1i, { "Uniform1i", nullptr } },
464 { (PRFuncPtr*) &mSymbols.fUniform1iv, { "Uniform1iv", nullptr } },
465 { (PRFuncPtr*) &mSymbols.fUniform2f, { "Uniform2f", nullptr } },
466 { (PRFuncPtr*) &mSymbols.fUniform2fv, { "Uniform2fv", nullptr } },
467 { (PRFuncPtr*) &mSymbols.fUniform2i, { "Uniform2i", nullptr } },
468 { (PRFuncPtr*) &mSymbols.fUniform2iv, { "Uniform2iv", nullptr } },
469 { (PRFuncPtr*) &mSymbols.fUniform3f, { "Uniform3f", nullptr } },
470 { (PRFuncPtr*) &mSymbols.fUniform3fv, { "Uniform3fv", nullptr } },
471 { (PRFuncPtr*) &mSymbols.fUniform3i, { "Uniform3i", nullptr } },
472 { (PRFuncPtr*) &mSymbols.fUniform3iv, { "Uniform3iv", nullptr } },
473 { (PRFuncPtr*) &mSymbols.fUniform4f, { "Uniform4f", nullptr } },
474 { (PRFuncPtr*) &mSymbols.fUniform4fv, { "Uniform4fv", nullptr } },
475 { (PRFuncPtr*) &mSymbols.fUniform4i, { "Uniform4i", nullptr } },
476 { (PRFuncPtr*) &mSymbols.fUniform4iv, { "Uniform4iv", nullptr } },
477 { (PRFuncPtr*) &mSymbols.fUniformMatrix2fv, { "UniformMatrix2fv", nullptr } },
478 { (PRFuncPtr*) &mSymbols.fUniformMatrix3fv, { "UniformMatrix3fv", nullptr } },
479 { (PRFuncPtr*) &mSymbols.fUniformMatrix4fv, { "UniformMatrix4fv", nullptr } },
480 { (PRFuncPtr*) &mSymbols.fUseProgram, { "UseProgram", nullptr } },
481 { (PRFuncPtr*) &mSymbols.fValidateProgram, { "ValidateProgram", nullptr } },
482 { (PRFuncPtr*) &mSymbols.fVertexAttribPointer, { "VertexAttribPointer", nullptr } },
483 { (PRFuncPtr*) &mSymbols.fVertexAttrib1f, { "VertexAttrib1f", nullptr } },
484 { (PRFuncPtr*) &mSymbols.fVertexAttrib2f, { "VertexAttrib2f", nullptr } },
485 { (PRFuncPtr*) &mSymbols.fVertexAttrib3f, { "VertexAttrib3f", nullptr } },
486 { (PRFuncPtr*) &mSymbols.fVertexAttrib4f, { "VertexAttrib4f", nullptr } },
487 { (PRFuncPtr*) &mSymbols.fVertexAttrib1fv, { "VertexAttrib1fv", nullptr } },
488 { (PRFuncPtr*) &mSymbols.fVertexAttrib2fv, { "VertexAttrib2fv", nullptr } },
489 { (PRFuncPtr*) &mSymbols.fVertexAttrib3fv, { "VertexAttrib3fv", nullptr } },
490 { (PRFuncPtr*) &mSymbols.fVertexAttrib4fv, { "VertexAttrib4fv", nullptr } },
491 { (PRFuncPtr*) &mSymbols.fViewport, { "Viewport", nullptr } },
492 { (PRFuncPtr*) &mSymbols.fCompileShader, { "CompileShader", nullptr } },
493 { (PRFuncPtr*) &mSymbols.fCopyTexImage2D, { "CopyTexImage2D", nullptr } },
494 { (PRFuncPtr*) &mSymbols.fCopyTexSubImage2D, { "CopyTexSubImage2D", nullptr } },
495 { (PRFuncPtr*) &mSymbols.fGetShaderiv, { "GetShaderiv", nullptr } },
496 { (PRFuncPtr*) &mSymbols.fGetShaderInfoLog, { "GetShaderInfoLog", nullptr } },
497 { (PRFuncPtr*) &mSymbols.fGetShaderSource, { "GetShaderSource", nullptr } },
498 { (PRFuncPtr*) &mSymbols.fShaderSource, { "ShaderSource", nullptr } },
499 { (PRFuncPtr*) &mSymbols.fVertexAttribPointer, { "VertexAttribPointer", nullptr } },
500
501 { (PRFuncPtr*) &mSymbols.fGenBuffers, { "GenBuffers", "GenBuffersARB", nullptr } },
502 { (PRFuncPtr*) &mSymbols.fGenTextures, { "GenTextures", nullptr } },
503 { (PRFuncPtr*) &mSymbols.fCreateProgram, { "CreateProgram", "CreateProgramARB", nullptr } },
504 { (PRFuncPtr*) &mSymbols.fCreateShader, { "CreateShader", "CreateShaderARB", nullptr } },
505
506 { (PRFuncPtr*) &mSymbols.fDeleteBuffers, { "DeleteBuffers", "DeleteBuffersARB", nullptr } },
507 { (PRFuncPtr*) &mSymbols.fDeleteTextures, { "DeleteTextures", "DeleteTexturesARB", nullptr } },
508 { (PRFuncPtr*) &mSymbols.fDeleteProgram, { "DeleteProgram", "DeleteProgramARB", nullptr } },
509 { (PRFuncPtr*) &mSymbols.fDeleteShader, { "DeleteShader", "DeleteShaderARB", nullptr } },
510
511 END_SYMBOLS
512 };
513 // clang-format on
514
515 if (!LoadGLSymbols(this, prefix, trygl, coreSymbols, "GL")) return false;
516
517 ////////////////
518
519 if (!MakeCurrent()) {
520 return false;
521 }
522
523 const std::string versionStr = (const char*)fGetString(LOCAL_GL_VERSION);
524 if (versionStr.find("OpenGL ES") == 0) {
525 mProfile = ContextProfile::OpenGLES;
526 }
527
528 uint32_t majorVer, minorVer;
529 if (!ParseVersion(versionStr, &majorVer, &minorVer)) {
530 MOZ_ASSERT(false, "Failed to parse GL_VERSION");
531 return false;
532 }
533 MOZ_ASSERT(majorVer < 10);
534 MOZ_ASSERT(minorVer < 10);
535 mVersion = majorVer * 100 + minorVer * 10;
536 if (mVersion < 200) return false;
537
538 ////
539
540 const auto glslVersionStr =
541 (const char*)fGetString(LOCAL_GL_SHADING_LANGUAGE_VERSION);
542 if (!glslVersionStr) {
543 // This happens on the Android emulators. We'll just return 100
544 mShadingLanguageVersion = 100;
545 } else if (ParseVersion(glslVersionStr, &majorVer, &minorVer)) {
546 MOZ_ASSERT(majorVer < 10);
547 MOZ_ASSERT(minorVer < 100);
548 mShadingLanguageVersion = majorVer * 100 + minorVer;
549 } else {
550 MOZ_ASSERT(false, "Failed to parse GL_SHADING_LANGUAGE_VERSION");
551 return false;
552 }
553
554 if (ShouldSpew()) {
555 printf_stderr("GL version detected: %u\n", mVersion);
556 printf_stderr("GLSL version detected: %u\n", mShadingLanguageVersion);
557 printf_stderr("OpenGL vendor: %s\n", fGetString(LOCAL_GL_VENDOR));
558 printf_stderr("OpenGL renderer: %s\n", fGetString(LOCAL_GL_RENDERER));
559 }
560
561 ////////////////
562
563 // Load OpenGL ES 2.0 symbols, or desktop if we aren't using ES 2.
564 if (mProfile == ContextProfile::OpenGLES) {
565 const SymLoadStruct symbols[] = {CORE_SYMBOL(GetShaderPrecisionFormat),
566 CORE_SYMBOL(ClearDepthf),
567 CORE_SYMBOL(DepthRangef), END_SYMBOLS};
568
569 if (!LoadGLSymbols(this, prefix, trygl, symbols, "OpenGL ES")) return false;
570 } else {
571 const SymLoadStruct symbols[] = {
572 CORE_SYMBOL(ClearDepth), CORE_SYMBOL(DepthRange),
573 CORE_SYMBOL(ReadBuffer), CORE_SYMBOL(MapBuffer),
574 CORE_SYMBOL(UnmapBuffer), CORE_SYMBOL(PointParameterf),
575 CORE_SYMBOL(DrawBuffer),
576 // The following functions are only used by Skia/GL in desktop mode.
577 // Other parts of Gecko should avoid using these
578 CORE_SYMBOL(DrawBuffers), CORE_SYMBOL(ClientActiveTexture),
579 CORE_SYMBOL(DisableClientState), CORE_SYMBOL(EnableClientState),
580 CORE_SYMBOL(LoadIdentity), CORE_SYMBOL(LoadMatrixf),
581 CORE_SYMBOL(MatrixMode), CORE_SYMBOL(PolygonMode), CORE_SYMBOL(TexGeni),
582 CORE_SYMBOL(TexGenf), CORE_SYMBOL(TexGenfv), CORE_SYMBOL(VertexPointer),
583 END_SYMBOLS};
584
585 if (!LoadGLSymbols(this, prefix, trygl, symbols, "Desktop OpenGL"))
586 return false;
587 }
588
589 ////////////////
590
591 const char* glVendorString = (const char*)fGetString(LOCAL_GL_VENDOR);
592 const char* glRendererString = (const char*)fGetString(LOCAL_GL_RENDERER);
593 if (!glVendorString || !glRendererString) return false;
594
595 // The order of these strings must match up with the order of the enum
596 // defined in GLContext.h for vendor IDs.
597 const char* vendorMatchStrings[size_t(GLVendor::Other) + 1] = {
598 "Intel", "NVIDIA", "ATI", "Qualcomm", "Imagination",
599 "nouveau", "Vivante", "VMware, Inc.", "ARM", "Unknown"};
600
601 mVendor = GLVendor::Other;
602 for (size_t i = 0; i < size_t(GLVendor::Other); ++i) {
603 if (DoesStringMatch(glVendorString, vendorMatchStrings[i])) {
604 mVendor = GLVendor(i);
605 break;
606 }
607 }
608
609 // The order of these strings must match up with the order of the enum
610 // defined in GLContext.h for renderer IDs.
611 const char* rendererMatchStrings[size_t(GLRenderer::Other) + 1] = {
612 "Adreno 200",
613 "Adreno 205",
614 "Adreno (TM) 200",
615 "Adreno (TM) 205",
616 "Adreno (TM) 305",
617 "Adreno (TM) 320",
618 "Adreno (TM) 330",
619 "Adreno (TM) 420",
620 "Mali-400 MP",
621 "Mali-450 MP",
622 "PowerVR SGX 530",
623 "PowerVR SGX 540",
624 "PowerVR SGX 544MP",
625 "NVIDIA Tegra",
626 "Android Emulator",
627 "Gallium 0.4 on llvmpipe",
628 "Intel HD Graphics 3000 OpenGL Engine",
629 "Microsoft Basic Render Driver",
630 "Unknown"};
631
632 mRenderer = GLRenderer::Other;
633 for (size_t i = 0; i < size_t(GLRenderer::Other); ++i) {
634 if (DoesStringMatch(glRendererString, rendererMatchStrings[i])) {
635 mRenderer = GLRenderer(i);
636 break;
637 }
638 }
639
640 if (ShouldSpew()) {
641 printf_stderr("GL_VENDOR: %s\n", glVendorString);
642 printf_stderr("mVendor: %s\n", vendorMatchStrings[size_t(mVendor)]);
643 printf_stderr("GL_RENDERER: %s\n", glRendererString);
644 printf_stderr("mRenderer: %s\n", rendererMatchStrings[size_t(mRenderer)]);
645 }
646
647 ////////////////
648
649 if (mVersion >= 300) { // Both GL3 and ES3.
650 const SymLoadStruct symbols[] = {
651 {(PRFuncPtr*)&mSymbols.fGetStringi, {"GetStringi", nullptr}},
652 END_SYMBOLS};
653
654 if (!LoadGLSymbols(this, prefix, trygl, symbols, "GetStringi")) {
655 MOZ_RELEASE_ASSERT(false, "GFX: GetStringi is required!");
656 return false;
657 }
658 }
659
660 InitExtensions();
661 if (mProfile != ContextProfile::OpenGLES) {
662 if (mVersion >= 310 && !IsExtensionSupported(ARB_compatibility)) {
663 mProfile = ContextProfile::OpenGLCore;
664 } else {
665 mProfile = ContextProfile::OpenGLCompatibility;
666 }
667 }
668 MOZ_ASSERT(mProfile != ContextProfile::Unknown);
669
670 if (ShouldSpew()) {
671 const char* profileStr = "";
672 if (mProfile == ContextProfile::OpenGLES) {
673 profileStr = " es";
674 } else if (mProfile == ContextProfile::OpenGLCore) {
675 profileStr = " core";
676 }
677 printf_stderr("Detected profile: %u%s\n", mVersion, profileStr);
678 }
679
680 InitFeatures();
681
682 ////
683
684 // Disable extensions with partial or incorrect support.
685 if (WorkAroundDriverBugs()) {
686 if (Renderer() == GLRenderer::AdrenoTM320) {
687 MarkUnsupported(GLFeature::standard_derivatives);
688 }
689
690 if (Vendor() == GLVendor::Vivante) {
691 // bug 958256
692 MarkUnsupported(GLFeature::standard_derivatives);
693 }
694
695 if (Renderer() == GLRenderer::MicrosoftBasicRenderDriver) {
696 // Bug 978966: on Microsoft's "Basic Render Driver" (software renderer)
697 // multisampling hardcodes blending with the default blendfunc, which
698 // breaks WebGL.
699 MarkUnsupported(GLFeature::framebuffer_multisample);
700 }
701
702 #ifdef XP_MACOSX
703 // The Mac Nvidia driver, for versions up to and including 10.8,
704 // don't seem to properly support this. See 814839
705 // this has been fixed in Mac OS X 10.9. See 907946
706 // and it also works in 10.8.3 and higher. See 1094338.
707 if (Vendor() == gl::GLVendor::NVIDIA &&
708 !nsCocoaFeatures::IsAtLeastVersion(10, 8, 3)) {
709 MarkUnsupported(GLFeature::depth_texture);
710 }
711 #endif
712
713 const auto versionStr = (const char*)fGetString(LOCAL_GL_VERSION);
714 if (strstr(versionStr, "Mesa")) {
715 // DrawElementsInstanced hangs the driver.
716 MarkUnsupported(GLFeature::robust_buffer_access_behavior);
717 }
718 }
719
720 if (IsExtensionSupported(GLContext::ARB_pixel_buffer_object)) {
721 MOZ_ASSERT(
722 (mSymbols.fMapBuffer && mSymbols.fUnmapBuffer),
723 "ARB_pixel_buffer_object supported without glMapBuffer/UnmapBuffer"
724 " being available!");
725 }
726
727 ////////////////////////////////////////////////////////////////////////////
728
729 const auto fnLoadForFeature = [this, prefix, trygl](const SymLoadStruct* list,
730 GLFeature feature) {
731 return this->LoadFeatureSymbols(prefix, trygl, list, feature);
732 };
733
734 // Check for ARB_framebuffer_objects
735 if (IsSupported(GLFeature::framebuffer_object)) {
736 // https://www.opengl.org/registry/specs/ARB/framebuffer_object.txt
737 const SymLoadStruct symbols[] = {
738 CORE_SYMBOL(IsRenderbuffer),
739 CORE_SYMBOL(BindRenderbuffer),
740 CORE_SYMBOL(DeleteRenderbuffers),
741 CORE_SYMBOL(GenRenderbuffers),
742 CORE_SYMBOL(RenderbufferStorage),
743 CORE_SYMBOL(RenderbufferStorageMultisample),
744 CORE_SYMBOL(GetRenderbufferParameteriv),
745 CORE_SYMBOL(IsFramebuffer),
746 CORE_SYMBOL(BindFramebuffer),
747 CORE_SYMBOL(DeleteFramebuffers),
748 CORE_SYMBOL(GenFramebuffers),
749 CORE_SYMBOL(CheckFramebufferStatus),
750 CORE_SYMBOL(FramebufferTexture2D),
751 CORE_SYMBOL(FramebufferTextureLayer),
752 CORE_SYMBOL(FramebufferRenderbuffer),
753 CORE_SYMBOL(GetFramebufferAttachmentParameteriv),
754 CORE_SYMBOL(BlitFramebuffer),
755 CORE_SYMBOL(GenerateMipmap),
756 END_SYMBOLS};
757 fnLoadForFeature(symbols, GLFeature::framebuffer_object);
758 }
759
760 if (!IsSupported(GLFeature::framebuffer_object)) {
761 // Check for aux symbols based on extensions
762 if (IsSupported(GLFeature::framebuffer_object_EXT_OES)) {
763 const SymLoadStruct symbols[] = {
764 CORE_EXT_SYMBOL2(IsRenderbuffer, EXT, OES),
765 CORE_EXT_SYMBOL2(BindRenderbuffer, EXT, OES),
766 CORE_EXT_SYMBOL2(DeleteRenderbuffers, EXT, OES),
767 CORE_EXT_SYMBOL2(GenRenderbuffers, EXT, OES),
768 CORE_EXT_SYMBOL2(RenderbufferStorage, EXT, OES),
769 CORE_EXT_SYMBOL2(GetRenderbufferParameteriv, EXT, OES),
770 CORE_EXT_SYMBOL2(IsFramebuffer, EXT, OES),
771 CORE_EXT_SYMBOL2(BindFramebuffer, EXT, OES),
772 CORE_EXT_SYMBOL2(DeleteFramebuffers, EXT, OES),
773 CORE_EXT_SYMBOL2(GenFramebuffers, EXT, OES),
774 CORE_EXT_SYMBOL2(CheckFramebufferStatus, EXT, OES),
775 CORE_EXT_SYMBOL2(FramebufferTexture2D, EXT, OES),
776 CORE_EXT_SYMBOL2(FramebufferRenderbuffer, EXT, OES),
777 CORE_EXT_SYMBOL2(GetFramebufferAttachmentParameteriv, EXT, OES),
778 CORE_EXT_SYMBOL2(GenerateMipmap, EXT, OES),
779 END_SYMBOLS};
780 fnLoadForFeature(symbols, GLFeature::framebuffer_object_EXT_OES);
781 }
782
783 if (IsSupported(GLFeature::framebuffer_blit)) {
784 const SymLoadStruct symbols[] = {
785 EXT_SYMBOL3(BlitFramebuffer, ANGLE, EXT, NV), END_SYMBOLS};
786 fnLoadForFeature(symbols, GLFeature::framebuffer_blit);
787 }
788
789 if (IsSupported(GLFeature::framebuffer_multisample)) {
790 const SymLoadStruct symbols[] = {
791 EXT_SYMBOL3(RenderbufferStorageMultisample, ANGLE, APPLE, EXT),
792 END_SYMBOLS};
793 fnLoadForFeature(symbols, GLFeature::framebuffer_multisample);
794 }
795
796 if (IsExtensionSupported(GLContext::ARB_geometry_shader4) ||
797 IsExtensionSupported(GLContext::NV_geometry_program4)) {
798 const SymLoadStruct symbols[] = {
799 EXT_SYMBOL2(FramebufferTextureLayer, ARB, EXT), END_SYMBOLS};
800 if (!LoadGLSymbols(this, prefix, trygl, symbols,
801 "ARB_geometry_shader4/NV_geometry_program4")) {
802 MarkExtensionUnsupported(GLContext::ARB_geometry_shader4);
803 MarkExtensionUnsupported(GLContext::NV_geometry_program4);
804 }
805 }
806 }
807
808 if (!IsSupported(GLFeature::framebuffer_object) &&
809 !IsSupported(GLFeature::framebuffer_object_EXT_OES)) {
810 NS_ERROR("GLContext requires support for framebuffer objects.");
811 return false;
812 }
813 MOZ_RELEASE_ASSERT(mSymbols.fBindFramebuffer,
814 "GFX: mSymbols.fBindFramebuffer zero or not set.");
815
816 ////////////////
817
818 const auto err = mSymbols.fGetError();
819 MOZ_RELEASE_ASSERT(!err);
820 if (err) return false;
821
822 LoadMoreSymbols(prefix, trygl);
823
824 ////////////////////////////////////////////////////////////////////////////
825
826 raw_fGetIntegerv(LOCAL_GL_VIEWPORT, mViewportRect);
827 raw_fGetIntegerv(LOCAL_GL_SCISSOR_BOX, mScissorRect);
828 raw_fGetIntegerv(LOCAL_GL_MAX_TEXTURE_SIZE, &mMaxTextureSize);
829 raw_fGetIntegerv(LOCAL_GL_MAX_CUBE_MAP_TEXTURE_SIZE, &mMaxCubeMapTextureSize);
830 raw_fGetIntegerv(LOCAL_GL_MAX_RENDERBUFFER_SIZE, &mMaxRenderbufferSize);
831 raw_fGetIntegerv(LOCAL_GL_MAX_VIEWPORT_DIMS, mMaxViewportDims);
832
833 #ifdef XP_MACOSX
834 if (mWorkAroundDriverBugs && nsCocoaFeatures::OSXVersionMajor() == 10 &&
835 nsCocoaFeatures::OSXVersionMinor() < 12) {
836 if (mVendor == GLVendor::Intel) {
837 // see bug 737182 for 2D textures, bug 684882 for cube map textures.
838 mMaxTextureSize = std::min(mMaxTextureSize, 4096);
839 mMaxCubeMapTextureSize = std::min(mMaxCubeMapTextureSize, 512);
840 // for good measure, we align renderbuffers on what we do for 2D textures
841 mMaxRenderbufferSize = std::min(mMaxRenderbufferSize, 4096);
842 mNeedsTextureSizeChecks = true;
843 } else if (mVendor == GLVendor::NVIDIA) {
844 // See bug 879656. 8192 fails, 8191 works.
845 mMaxTextureSize = std::min(mMaxTextureSize, 8191);
846 mMaxRenderbufferSize = std::min(mMaxRenderbufferSize, 8191);
847
848 // Part of the bug 879656, but it also doesn't hurt the 877949
849 mNeedsTextureSizeChecks = true;
850 }
851 }
852 #endif
853 #ifdef MOZ_X11
854 if (mWorkAroundDriverBugs) {
855 if (mVendor == GLVendor::Nouveau) {
856 // see bug 814716. Clamp MaxCubeMapTextureSize at 2K for Nouveau.
857 mMaxCubeMapTextureSize = std::min(mMaxCubeMapTextureSize, 2048);
858 mNeedsTextureSizeChecks = true;
859 } else if (mVendor == GLVendor::Intel) {
860 // Bug 1199923. Driver seems to report a larger max size than
861 // actually supported.
862 mMaxTextureSize /= 2;
863 mMaxRenderbufferSize /= 2;
864 mNeedsTextureSizeChecks = true;
865 }
866 // Bug 1367570. Explicitly set vertex attributes [1,3] to opaque
867 // black because Nvidia doesn't do it for us.
868 if (mVendor == GLVendor::NVIDIA) {
869 for (size_t i = 1; i <= 3; ++i) {
870 mSymbols.fVertexAttrib4f(i, 0, 0, 0, 1);
871 }
872 }
873 }
874 #endif
875 if (mWorkAroundDriverBugs && Renderer() == GLRenderer::AdrenoTM420) {
876 // see bug 1194923. Calling glFlush before glDeleteFramebuffers
877 // prevents occasional driver crash.
878 mNeedsFlushBeforeDeleteFB = true;
879 }
880 #ifdef MOZ_WIDGET_ANDROID
881 if (mWorkAroundDriverBugs &&
882 (Renderer() == GLRenderer::AdrenoTM305 ||
883 Renderer() == GLRenderer::AdrenoTM320 ||
884 Renderer() == GLRenderer::AdrenoTM330) &&
885 AndroidBridge::Bridge()->GetAPIVersion() < 21) {
886 // Bug 1164027. Driver crashes when functions such as
887 // glTexImage2D fail due to virtual memory exhaustion.
888 mTextureAllocCrashesOnMapFailure = true;
889 }
890 #endif
891 #if MOZ_WIDGET_ANDROID
892 if (mWorkAroundDriverBugs && Renderer() == GLRenderer::SGX540 &&
893 AndroidBridge::Bridge()->GetAPIVersion() <= 15) {
894 // Bug 1288446. Driver sometimes crashes when uploading data to a
895 // texture if the render target has changed since the texture was
896 // rendered from. Calling glCheckFramebufferStatus after
897 // glFramebufferTexture2D prevents the crash.
898 mNeedsCheckAfterAttachTextureToFb = true;
899 }
900 #endif
901
902 mMaxTextureImageSize = mMaxTextureSize;
903
904 if (IsSupported(GLFeature::framebuffer_multisample)) {
905 fGetIntegerv(LOCAL_GL_MAX_SAMPLES, (GLint*)&mMaxSamples);
906 }
907
908 mMaxTexOrRbSize = std::min(mMaxTextureSize, mMaxRenderbufferSize);
909
910 ////////////////////////////////////////////////////////////////////////////
911
912 // We're ready for final setup.
913 fBindFramebuffer(LOCAL_GL_FRAMEBUFFER, 0);
914
915 // TODO: Remove SurfaceCaps::any.
916 if (mCaps.any) {
917 mCaps.any = false;
918 mCaps.color = true;
919 mCaps.alpha = false;
920 }
921
922 MOZ_ASSERT(IsCurrent());
923
924 if (ShouldSpew() && IsExtensionSupported(KHR_debug)) {
925 fEnable(LOCAL_GL_DEBUG_OUTPUT);
926 fDisable(LOCAL_GL_DEBUG_OUTPUT_SYNCHRONOUS);
927 fDebugMessageCallback(&StaticDebugCallback, (void*)this);
928 fDebugMessageControl(LOCAL_GL_DONT_CARE, LOCAL_GL_DONT_CARE,
929 LOCAL_GL_DONT_CARE, 0, nullptr, true);
930 }
931
932 return true;
933 }
934
LoadMoreSymbols(const char * prefix,bool trygl)935 void GLContext::LoadMoreSymbols(const char* prefix, bool trygl) {
936 const auto fnLoadForExt = [this, prefix, trygl](const SymLoadStruct* list,
937 GLExtensions ext) {
938 return this->LoadExtSymbols(prefix, trygl, list, ext);
939 };
940
941 const auto fnLoadForFeature = [this, prefix, trygl](const SymLoadStruct* list,
942 GLFeature feature) {
943 return this->LoadFeatureSymbols(prefix, trygl, list, feature);
944 };
945
946 const auto fnLoadFeatureByCore = [this, fnLoadForFeature](
947 const SymLoadStruct* coreList,
948 const SymLoadStruct* extList,
949 GLFeature feature) {
950 const bool useCore = this->IsFeatureProvidedByCoreSymbols(feature);
951 const auto list = useCore ? coreList : extList;
952 return fnLoadForFeature(list, feature);
953 };
954
955 if (IsSupported(GLFeature::robustness)) {
956 const auto resetStrategy =
957 GetIntAs<GLuint>(LOCAL_GL_RESET_NOTIFICATION_STRATEGY);
958 if (resetStrategy != LOCAL_GL_LOSE_CONTEXT_ON_RESET) {
959 NS_WARNING(
960 "Robustness supported, strategy is not LOSE_CONTEXT_ON_RESET!");
961 if (ShouldSpew()) {
962 const bool isDisabled =
963 (resetStrategy == LOCAL_GL_NO_RESET_NOTIFICATION);
964 printf_stderr("Strategy: %s (0x%04x)",
965 (isDisabled ? "disabled" : "unrecognized"),
966 resetStrategy);
967 }
968 MarkUnsupported(GLFeature::robustness);
969 }
970 }
971 if (IsSupported(GLFeature::robustness)) {
972 const SymLoadStruct symbols[] = {
973 {(PRFuncPtr*)&mSymbols.fGetGraphicsResetStatus,
974 {"GetGraphicsResetStatus", "GetGraphicsResetStatusARB",
975 "GetGraphicsResetStatusKHR", "GetGraphicsResetStatusEXT", nullptr}},
976 END_SYMBOLS};
977 if (fnLoadForFeature(symbols, GLFeature::robustness)) {
978 const auto status = mSymbols.fGetGraphicsResetStatus();
979 MOZ_ALWAYS_TRUE(!status);
980
981 const auto err = mSymbols.fGetError();
982 MOZ_ALWAYS_TRUE(!err);
983 }
984 }
985
986 if (IsSupported(GLFeature::sync)) {
987 const SymLoadStruct symbols[] = {
988 CORE_SYMBOL(FenceSync), CORE_SYMBOL(IsSync),
989 CORE_SYMBOL(DeleteSync), CORE_SYMBOL(ClientWaitSync),
990 CORE_SYMBOL(WaitSync), CORE_SYMBOL(GetInteger64v),
991 CORE_SYMBOL(GetSynciv), END_SYMBOLS};
992 fnLoadForFeature(symbols, GLFeature::sync);
993 }
994
995 if (IsExtensionSupported(OES_EGL_image)) {
996 const SymLoadStruct symbols[] = {
997 {(PRFuncPtr*)&mSymbols.fEGLImageTargetTexture2D,
998 {"EGLImageTargetTexture2DOES", nullptr}},
999 {(PRFuncPtr*)&mSymbols.fEGLImageTargetRenderbufferStorage,
1000 {"EGLImageTargetRenderbufferStorageOES", nullptr}},
1001 END_SYMBOLS};
1002 fnLoadForExt(symbols, OES_EGL_image);
1003 }
1004
1005 if (IsExtensionSupported(APPLE_texture_range)) {
1006 const SymLoadStruct symbols[] = {CORE_SYMBOL(TextureRangeAPPLE),
1007 END_SYMBOLS};
1008 fnLoadForExt(symbols, APPLE_texture_range);
1009 }
1010
1011 // clang-format off
1012
1013 if (IsSupported(GLFeature::vertex_array_object)) {
1014 const SymLoadStruct coreSymbols[] = {
1015 { (PRFuncPtr*) &mSymbols.fIsVertexArray, { "IsVertexArray", nullptr } },
1016 { (PRFuncPtr*) &mSymbols.fGenVertexArrays, { "GenVertexArrays", nullptr } },
1017 { (PRFuncPtr*) &mSymbols.fBindVertexArray, { "BindVertexArray", nullptr } },
1018 { (PRFuncPtr*) &mSymbols.fDeleteVertexArrays, { "DeleteVertexArrays", nullptr } },
1019 END_SYMBOLS
1020 };
1021 const SymLoadStruct extSymbols[] = {
1022 { (PRFuncPtr*) &mSymbols.fIsVertexArray, { "IsVertexArrayARB", "IsVertexArrayOES", "IsVertexArrayAPPLE", nullptr } },
1023 { (PRFuncPtr*) &mSymbols.fGenVertexArrays, { "GenVertexArraysARB", "GenVertexArraysOES", "GenVertexArraysAPPLE", nullptr } },
1024 { (PRFuncPtr*) &mSymbols.fBindVertexArray, { "BindVertexArrayARB", "BindVertexArrayOES", "BindVertexArrayAPPLE", nullptr } },
1025 { (PRFuncPtr*) &mSymbols.fDeleteVertexArrays, { "DeleteVertexArraysARB", "DeleteVertexArraysOES", "DeleteVertexArraysAPPLE", nullptr } },
1026 END_SYMBOLS
1027 };
1028 fnLoadFeatureByCore(coreSymbols, extSymbols, GLFeature::vertex_array_object);
1029 }
1030
1031 if (IsSupported(GLFeature::draw_instanced)) {
1032 const SymLoadStruct coreSymbols[] = {
1033 { (PRFuncPtr*) &mSymbols.fDrawArraysInstanced, { "DrawArraysInstanced", nullptr } },
1034 { (PRFuncPtr*) &mSymbols.fDrawElementsInstanced, { "DrawElementsInstanced", nullptr } },
1035 END_SYMBOLS
1036 };
1037 const SymLoadStruct extSymbols[] = {
1038 { (PRFuncPtr*) &mSymbols.fDrawArraysInstanced, { "DrawArraysInstancedARB", "DrawArraysInstancedEXT", "DrawArraysInstancedNV", "DrawArraysInstancedANGLE", nullptr } },
1039 { (PRFuncPtr*) &mSymbols.fDrawElementsInstanced, { "DrawElementsInstancedARB", "DrawElementsInstancedEXT", "DrawElementsInstancedNV", "DrawElementsInstancedANGLE", nullptr }
1040 },
1041 END_SYMBOLS
1042 };
1043 fnLoadFeatureByCore(coreSymbols, extSymbols, GLFeature::draw_instanced);
1044 }
1045
1046 if (IsSupported(GLFeature::instanced_arrays)) {
1047 const SymLoadStruct coreSymbols[] = {
1048 { (PRFuncPtr*) &mSymbols.fVertexAttribDivisor, { "VertexAttribDivisor", nullptr } },
1049 END_SYMBOLS
1050 };
1051 const SymLoadStruct extSymbols[] = {
1052 { (PRFuncPtr*) &mSymbols.fVertexAttribDivisor, { "VertexAttribDivisorARB", "VertexAttribDivisorNV", "VertexAttribDivisorANGLE", nullptr } },
1053 END_SYMBOLS
1054 };
1055 fnLoadFeatureByCore(coreSymbols, extSymbols, GLFeature::instanced_arrays);
1056 }
1057
1058 if (IsSupported(GLFeature::texture_storage)) {
1059 const SymLoadStruct coreSymbols[] = {
1060 { (PRFuncPtr*) &mSymbols.fTexStorage2D, { "TexStorage2D", nullptr } },
1061 { (PRFuncPtr*) &mSymbols.fTexStorage3D, { "TexStorage3D", nullptr } },
1062 END_SYMBOLS
1063 };
1064 const SymLoadStruct extSymbols[] = {
1065 { (PRFuncPtr*) &mSymbols.fTexStorage2D, { "TexStorage2DEXT", nullptr } },
1066 { (PRFuncPtr*) &mSymbols.fTexStorage3D, { "TexStorage3DEXT", nullptr } },
1067 END_SYMBOLS
1068 };
1069 fnLoadFeatureByCore(coreSymbols, extSymbols, GLFeature::texture_storage);
1070 }
1071
1072 if (IsSupported(GLFeature::sampler_objects)) {
1073 const SymLoadStruct symbols[] = {
1074 { (PRFuncPtr*) &mSymbols.fGenSamplers, { "GenSamplers", nullptr } },
1075 { (PRFuncPtr*) &mSymbols.fDeleteSamplers, { "DeleteSamplers", nullptr } },
1076 { (PRFuncPtr*) &mSymbols.fIsSampler, { "IsSampler", nullptr } },
1077 { (PRFuncPtr*) &mSymbols.fBindSampler, { "BindSampler", nullptr } },
1078 { (PRFuncPtr*) &mSymbols.fSamplerParameteri, { "SamplerParameteri", nullptr } },
1079 { (PRFuncPtr*) &mSymbols.fSamplerParameteriv, { "SamplerParameteriv", nullptr } },
1080 { (PRFuncPtr*) &mSymbols.fSamplerParameterf, { "SamplerParameterf", nullptr } },
1081 { (PRFuncPtr*) &mSymbols.fSamplerParameterfv, { "SamplerParameterfv", nullptr } },
1082 { (PRFuncPtr*) &mSymbols.fGetSamplerParameteriv, { "GetSamplerParameteriv", nullptr } },
1083 { (PRFuncPtr*) &mSymbols.fGetSamplerParameterfv, { "GetSamplerParameterfv", nullptr } },
1084 END_SYMBOLS
1085 };
1086 fnLoadForFeature(symbols, GLFeature::sampler_objects);
1087 }
1088
1089 // ARB_transform_feedback2/NV_transform_feedback2 is a
1090 // superset of EXT_transform_feedback/NV_transform_feedback
1091 // and adds glPauseTransformFeedback &
1092 // glResumeTransformFeedback, which are required for WebGL2.
1093 if (IsSupported(GLFeature::transform_feedback2)) {
1094 const SymLoadStruct coreSymbols[] = {
1095 { (PRFuncPtr*) &mSymbols.fBindBufferBase, { "BindBufferBase", nullptr } },
1096 { (PRFuncPtr*) &mSymbols.fBindBufferRange, { "BindBufferRange", nullptr } },
1097 { (PRFuncPtr*) &mSymbols.fGenTransformFeedbacks, { "GenTransformFeedbacks", nullptr } },
1098 { (PRFuncPtr*) &mSymbols.fBindTransformFeedback, { "BindTransformFeedback", nullptr } },
1099 { (PRFuncPtr*) &mSymbols.fDeleteTransformFeedbacks, { "DeleteTransformFeedbacks", nullptr } },
1100 { (PRFuncPtr*) &mSymbols.fIsTransformFeedback, { "IsTransformFeedback", nullptr } },
1101 { (PRFuncPtr*) &mSymbols.fBeginTransformFeedback, { "BeginTransformFeedback", nullptr } },
1102 { (PRFuncPtr*) &mSymbols.fEndTransformFeedback, { "EndTransformFeedback", nullptr } },
1103 { (PRFuncPtr*) &mSymbols.fTransformFeedbackVaryings, { "TransformFeedbackVaryings", nullptr } },
1104 { (PRFuncPtr*) &mSymbols.fGetTransformFeedbackVarying, { "GetTransformFeedbackVarying", nullptr } },
1105 { (PRFuncPtr*) &mSymbols.fPauseTransformFeedback, { "PauseTransformFeedback", nullptr } },
1106 { (PRFuncPtr*) &mSymbols.fResumeTransformFeedback, { "ResumeTransformFeedback", nullptr } },
1107 END_SYMBOLS
1108 };
1109 const SymLoadStruct extSymbols[] = {
1110 { (PRFuncPtr*) &mSymbols.fBindBufferBase, { "BindBufferBaseEXT", "BindBufferBaseNV", nullptr } },
1111 { (PRFuncPtr*) &mSymbols.fBindBufferRange, { "BindBufferRangeEXT", "BindBufferRangeNV", nullptr } },
1112 { (PRFuncPtr*) &mSymbols.fGenTransformFeedbacks, { "GenTransformFeedbacksNV", nullptr } },
1113 { (PRFuncPtr*) &mSymbols.fBindTransformFeedback, { "BindTransformFeedbackNV", nullptr } },
1114 { (PRFuncPtr*) &mSymbols.fDeleteTransformFeedbacks, { "DeleteTransformFeedbacksNV", nullptr } },
1115 { (PRFuncPtr*) &mSymbols.fIsTransformFeedback, { "IsTransformFeedbackNV", nullptr } },
1116 { (PRFuncPtr*) &mSymbols.fBeginTransformFeedback, { "BeginTransformFeedbackEXT", "BeginTransformFeedbackNV", nullptr } },
1117 { (PRFuncPtr*) &mSymbols.fEndTransformFeedback, { "EndTransformFeedbackEXT", "EndTransformFeedbackNV", nullptr } },
1118 { (PRFuncPtr*) &mSymbols.fTransformFeedbackVaryings, { "TransformFeedbackVaryingsEXT", "TransformFeedbackVaryingsNV", nullptr } },
1119 { (PRFuncPtr*) &mSymbols.fGetTransformFeedbackVarying, { "GetTransformFeedbackVaryingEXT", "GetTransformFeedbackVaryingNV", nullptr } },
1120 { (PRFuncPtr*) &mSymbols.fPauseTransformFeedback, { "PauseTransformFeedbackNV", nullptr } },
1121 { (PRFuncPtr*) &mSymbols.fResumeTransformFeedback, { "ResumeTransformFeedbackNV", nullptr } },
1122 END_SYMBOLS
1123 };
1124 if (!fnLoadFeatureByCore(coreSymbols, extSymbols, GLFeature::texture_storage)) {
1125 // Also mark bind_buffer_offset as unsupported.
1126 MarkUnsupported(GLFeature::bind_buffer_offset);
1127 }
1128 }
1129
1130 if (IsSupported(GLFeature::bind_buffer_offset)) {
1131 const SymLoadStruct coreSymbols[] = {
1132 { (PRFuncPtr*) &mSymbols.fBindBufferOffset, { "BindBufferOffset", nullptr } },
1133 END_SYMBOLS
1134 };
1135 const SymLoadStruct extSymbols[] = {
1136 { (PRFuncPtr*) &mSymbols.fBindBufferOffset,
1137 { "BindBufferOffsetEXT", "BindBufferOffsetNV", nullptr }
1138 },
1139 END_SYMBOLS
1140 };
1141 fnLoadFeatureByCore(coreSymbols, extSymbols, GLFeature::bind_buffer_offset);
1142 }
1143
1144 if (IsSupported(GLFeature::query_counter)) {
1145 const SymLoadStruct coreSymbols[] = {
1146 { (PRFuncPtr*) &mSymbols.fQueryCounter, { "QueryCounter", nullptr } },
1147 END_SYMBOLS
1148 };
1149 const SymLoadStruct extSymbols[] = {
1150 { (PRFuncPtr*) &mSymbols.fQueryCounter, { "QueryCounterEXT", "QueryCounterANGLE", nullptr } },
1151 END_SYMBOLS
1152 };
1153 fnLoadFeatureByCore(coreSymbols, extSymbols, GLFeature::query_counter);
1154 }
1155
1156 if (IsSupported(GLFeature::query_objects)) {
1157 const SymLoadStruct coreSymbols[] = {
1158 { (PRFuncPtr*) &mSymbols.fBeginQuery, { "BeginQuery", nullptr } },
1159 { (PRFuncPtr*) &mSymbols.fGenQueries, { "GenQueries", nullptr } },
1160 { (PRFuncPtr*) &mSymbols.fDeleteQueries, { "DeleteQueries", nullptr } },
1161 { (PRFuncPtr*) &mSymbols.fEndQuery, { "EndQuery", nullptr } },
1162 { (PRFuncPtr*) &mSymbols.fGetQueryiv, { "GetQueryiv", nullptr } },
1163 { (PRFuncPtr*) &mSymbols.fGetQueryObjectuiv, { "GetQueryObjectuiv", nullptr } },
1164 { (PRFuncPtr*) &mSymbols.fIsQuery, { "IsQuery", nullptr } },
1165 END_SYMBOLS
1166 };
1167 const SymLoadStruct extSymbols[] = {
1168 { (PRFuncPtr*) &mSymbols.fBeginQuery, { "BeginQueryEXT", "BeginQueryANGLE", nullptr } },
1169 { (PRFuncPtr*) &mSymbols.fGenQueries, { "GenQueriesEXT", "GenQueriesANGLE", nullptr } },
1170 { (PRFuncPtr*) &mSymbols.fDeleteQueries, { "DeleteQueriesEXT", "DeleteQueriesANGLE", nullptr } },
1171 { (PRFuncPtr*) &mSymbols.fEndQuery, { "EndQueryEXT", "EndQueryANGLE", nullptr } },
1172 { (PRFuncPtr*) &mSymbols.fGetQueryiv, { "GetQueryivEXT", "GetQueryivANGLE", nullptr } },
1173 { (PRFuncPtr*) &mSymbols.fGetQueryObjectuiv, { "GetQueryObjectuivEXT", "GetQueryObjectuivANGLE", nullptr } },
1174 { (PRFuncPtr*) &mSymbols.fIsQuery, { "IsQueryEXT", "IsQueryANGLE", nullptr } },
1175 END_SYMBOLS
1176 };
1177 if (!fnLoadFeatureByCore(coreSymbols, extSymbols, GLFeature::query_objects)) {
1178 MarkUnsupported(GLFeature::get_query_object_i64v);
1179 MarkUnsupported(GLFeature::get_query_object_iv);
1180 MarkUnsupported(GLFeature::occlusion_query);
1181 MarkUnsupported(GLFeature::occlusion_query_boolean);
1182 MarkUnsupported(GLFeature::occlusion_query2);
1183 }
1184 }
1185
1186 if (IsSupported(GLFeature::get_query_object_i64v)) {
1187 const SymLoadStruct coreSymbols[] = {
1188 { (PRFuncPtr*) &mSymbols.fGetQueryObjecti64v, { "GetQueryObjecti64v", nullptr } },
1189 { (PRFuncPtr*) &mSymbols.fGetQueryObjectui64v, { "GetQueryObjectui64v", nullptr } },
1190 END_SYMBOLS
1191 };
1192 const SymLoadStruct extSymbols[] = {
1193 { (PRFuncPtr*) &mSymbols.fGetQueryObjecti64v, { "GetQueryObjecti64vEXT", "GetQueryObjecti64vANGLE", nullptr } },
1194 { (PRFuncPtr*) &mSymbols.fGetQueryObjectui64v, { "GetQueryObjectui64vEXT", "GetQueryObjectui64vANGLE", nullptr } },
1195 END_SYMBOLS
1196 };
1197 if (!fnLoadFeatureByCore(coreSymbols, extSymbols, GLFeature::get_query_object_i64v)) {
1198 MarkUnsupported(GLFeature::query_counter);
1199 }
1200 }
1201
1202 if (IsSupported(GLFeature::get_query_object_iv)) {
1203 const SymLoadStruct coreSymbols[] = {
1204 { (PRFuncPtr*) &mSymbols.fGetQueryObjectiv, { "GetQueryObjectiv", nullptr } },
1205 END_SYMBOLS
1206 };
1207 const SymLoadStruct extSymbols[] = {
1208 { (PRFuncPtr*) &mSymbols.fGetQueryObjectiv, { "GetQueryObjectivEXT", "GetQueryObjectivANGLE", nullptr } },
1209 END_SYMBOLS
1210 };
1211 fnLoadFeatureByCore(coreSymbols, extSymbols, GLFeature::get_query_object_iv);
1212 }
1213
1214 if (IsSupported(GLFeature::clear_buffers)) {
1215 const SymLoadStruct symbols[] = {
1216 { (PRFuncPtr*) &mSymbols.fClearBufferfi, { "ClearBufferfi", nullptr } },
1217 { (PRFuncPtr*) &mSymbols.fClearBufferfv, { "ClearBufferfv", nullptr } },
1218 { (PRFuncPtr*) &mSymbols.fClearBufferiv, { "ClearBufferiv", nullptr } },
1219 { (PRFuncPtr*) &mSymbols.fClearBufferuiv, { "ClearBufferuiv", nullptr } },
1220 END_SYMBOLS
1221 };
1222 fnLoadForFeature(symbols, GLFeature::clear_buffers);
1223 }
1224
1225 if (IsSupported(GLFeature::copy_buffer)) {
1226 const SymLoadStruct symbols[] = {
1227 { (PRFuncPtr*) &mSymbols.fCopyBufferSubData, { "CopyBufferSubData", nullptr } },
1228 END_SYMBOLS
1229 };
1230 fnLoadForFeature(symbols, GLFeature::copy_buffer);
1231 }
1232
1233 if (IsSupported(GLFeature::draw_buffers)) {
1234 const SymLoadStruct coreSymbols[] = {
1235 { (PRFuncPtr*) &mSymbols.fDrawBuffers, { "DrawBuffers", nullptr } },
1236 END_SYMBOLS
1237 };
1238 const SymLoadStruct extSymbols[] = {
1239 { (PRFuncPtr*) &mSymbols.fDrawBuffers, { "DrawBuffersARB", "DrawBuffersEXT", nullptr } },
1240 END_SYMBOLS
1241 };
1242 fnLoadFeatureByCore(coreSymbols, extSymbols, GLFeature::draw_buffers);
1243 }
1244
1245 if (IsSupported(GLFeature::draw_range_elements)) {
1246 const SymLoadStruct coreSymbols[] = {
1247 { (PRFuncPtr*) &mSymbols.fDrawRangeElements, { "DrawRangeElements", nullptr } },
1248 END_SYMBOLS
1249 };
1250 const SymLoadStruct extSymbols[] = {
1251 { (PRFuncPtr*) &mSymbols.fDrawRangeElements, { "DrawRangeElementsEXT", nullptr } },
1252 END_SYMBOLS
1253 };
1254 fnLoadFeatureByCore(coreSymbols, extSymbols, GLFeature::draw_range_elements);
1255 }
1256
1257 if (IsSupported(GLFeature::get_integer_indexed)) {
1258 const SymLoadStruct coreSymbols[] = {
1259 { (PRFuncPtr*) &mSymbols.fGetIntegeri_v, { "GetIntegeri_v", nullptr } },
1260 END_SYMBOLS
1261 };
1262 const SymLoadStruct extSymbols[] ={
1263 { (PRFuncPtr*) &mSymbols.fGetIntegeri_v, { "GetIntegerIndexedvEXT", nullptr } },
1264 END_SYMBOLS
1265 };
1266 fnLoadFeatureByCore(coreSymbols, extSymbols, GLFeature::get_integer_indexed);
1267 }
1268
1269 if (IsSupported(GLFeature::get_integer64_indexed)) {
1270 const SymLoadStruct symbols[] = {
1271 { (PRFuncPtr*) &mSymbols.fGetInteger64i_v, { "GetInteger64i_v", nullptr } },
1272 END_SYMBOLS
1273 };
1274 fnLoadForFeature(symbols, GLFeature::get_integer64_indexed);
1275 }
1276
1277 if (IsSupported(GLFeature::gpu_shader4)) {
1278 const SymLoadStruct symbols[] = {
1279 { (PRFuncPtr*) &mSymbols.fGetVertexAttribIiv, { "GetVertexAttribIiv", "GetVertexAttribIivEXT", nullptr } },
1280 { (PRFuncPtr*) &mSymbols.fGetVertexAttribIuiv, { "GetVertexAttribIuiv", "GetVertexAttribIuivEXT", nullptr } },
1281 { (PRFuncPtr*) &mSymbols.fVertexAttribI4i, { "VertexAttribI4i", "VertexAttribI4iEXT", nullptr } },
1282 { (PRFuncPtr*) &mSymbols.fVertexAttribI4iv, { "VertexAttribI4iv","VertexAttribI4ivEXT", nullptr } },
1283 { (PRFuncPtr*) &mSymbols.fVertexAttribI4ui, { "VertexAttribI4ui", "VertexAttribI4uiEXT", nullptr } },
1284 { (PRFuncPtr*) &mSymbols.fVertexAttribI4uiv, { "VertexAttribI4uiv", "VertexAttribI4uivEXT", nullptr } },
1285 { (PRFuncPtr*) &mSymbols.fVertexAttribIPointer, { "VertexAttribIPointer", "VertexAttribIPointerEXT", nullptr } },
1286 { (PRFuncPtr*) &mSymbols.fUniform1ui, { "Uniform1ui", "Uniform1uiEXT", nullptr } },
1287 { (PRFuncPtr*) &mSymbols.fUniform2ui, { "Uniform2ui", "Uniform2uiEXT", nullptr } },
1288 { (PRFuncPtr*) &mSymbols.fUniform3ui, { "Uniform3ui", "Uniform3uiEXT", nullptr } },
1289 { (PRFuncPtr*) &mSymbols.fUniform4ui, { "Uniform4ui", "Uniform4uiEXT", nullptr } },
1290 { (PRFuncPtr*) &mSymbols.fUniform1uiv, { "Uniform1uiv", "Uniform1uivEXT", nullptr } },
1291 { (PRFuncPtr*) &mSymbols.fUniform2uiv, { "Uniform2uiv", "Uniform2uivEXT", nullptr } },
1292 { (PRFuncPtr*) &mSymbols.fUniform3uiv, { "Uniform3uiv", "Uniform3uivEXT", nullptr } },
1293 { (PRFuncPtr*) &mSymbols.fUniform4uiv, { "Uniform4uiv", "Uniform4uivEXT", nullptr } },
1294 { (PRFuncPtr*) &mSymbols.fGetFragDataLocation, { "GetFragDataLocation", "GetFragDataLocationEXT", nullptr } },
1295 { (PRFuncPtr*) &mSymbols.fGetUniformuiv, { "GetUniformuiv", "GetUniformuivEXT", nullptr } },
1296 END_SYMBOLS
1297 };
1298 fnLoadForFeature(symbols, GLFeature::gpu_shader4);
1299 }
1300
1301 if (IsSupported(GLFeature::map_buffer_range)) {
1302 const SymLoadStruct symbols[] = {
1303 { (PRFuncPtr*) &mSymbols.fMapBufferRange, { "MapBufferRange", nullptr } },
1304 { (PRFuncPtr*) &mSymbols.fFlushMappedBufferRange, { "FlushMappedBufferRange", nullptr } },
1305 { (PRFuncPtr*) &mSymbols.fUnmapBuffer, { "UnmapBuffer", nullptr } },
1306 END_SYMBOLS
1307 };
1308 fnLoadForFeature(symbols, GLFeature::map_buffer_range);
1309 }
1310
1311 if (IsSupported(GLFeature::texture_3D)) {
1312 const SymLoadStruct coreSymbols[] = {
1313 { (PRFuncPtr*) &mSymbols.fTexImage3D, { "TexImage3D", nullptr } },
1314 { (PRFuncPtr*) &mSymbols.fTexSubImage3D, { "TexSubImage3D", nullptr } },
1315 END_SYMBOLS
1316 };
1317 const SymLoadStruct extSymbols[] = {
1318 { (PRFuncPtr*) &mSymbols.fTexSubImage3D, { "TexSubImage3DEXT", "TexSubImage3DOES", nullptr } },
1319 END_SYMBOLS
1320 };
1321 fnLoadFeatureByCore(coreSymbols, extSymbols, GLFeature::texture_3D);
1322 }
1323
1324 if (IsSupported(GLFeature::texture_3D_compressed)) {
1325 const SymLoadStruct coreSymbols[] = {
1326 { (PRFuncPtr*) &mSymbols.fCompressedTexImage3D, { "CompressedTexImage3D", nullptr } },
1327 { (PRFuncPtr*) &mSymbols.fCompressedTexSubImage3D, { "CompressedTexSubImage3D", nullptr } },
1328 END_SYMBOLS
1329 };
1330 const SymLoadStruct extSymbols[] = {
1331 { (PRFuncPtr*) &mSymbols.fCompressedTexImage3D, { "CompressedTexImage3DARB", "CompressedTexImage3DOES", nullptr } },
1332 { (PRFuncPtr*) &mSymbols.fCompressedTexSubImage3D, { "CompressedTexSubImage3DARB", "CompressedTexSubImage3DOES", nullptr } },
1333 END_SYMBOLS
1334 };
1335 fnLoadFeatureByCore(coreSymbols, extSymbols, GLFeature::texture_3D_compressed);
1336 }
1337
1338 if (IsSupported(GLFeature::texture_3D_copy)) {
1339 const SymLoadStruct coreSymbols[] = {
1340 { (PRFuncPtr*) &mSymbols.fCopyTexSubImage3D, { "CopyTexSubImage3D", nullptr } },
1341 END_SYMBOLS
1342 };
1343 const SymLoadStruct extSymbols[] = {
1344 { (PRFuncPtr*) &mSymbols.fCopyTexSubImage3D, { "CopyTexSubImage3DEXT", "CopyTexSubImage3DOES", nullptr } },
1345 END_SYMBOLS
1346 };
1347 fnLoadFeatureByCore(coreSymbols, extSymbols, GLFeature::texture_3D_copy);
1348 }
1349
1350 if (IsSupported(GLFeature::uniform_buffer_object)) {
1351 // Note: Don't query for glGetActiveUniformName because it is not
1352 // supported by GL ES 3.
1353 const SymLoadStruct symbols[] = {
1354 { (PRFuncPtr*) &mSymbols.fGetUniformIndices, { "GetUniformIndices", nullptr } },
1355 { (PRFuncPtr*) &mSymbols.fGetActiveUniformsiv, { "GetActiveUniformsiv", nullptr } },
1356 { (PRFuncPtr*) &mSymbols.fGetUniformBlockIndex, { "GetUniformBlockIndex", nullptr } },
1357 { (PRFuncPtr*) &mSymbols.fGetActiveUniformBlockiv, { "GetActiveUniformBlockiv", nullptr } },
1358 { (PRFuncPtr*) &mSymbols.fGetActiveUniformBlockName, { "GetActiveUniformBlockName", nullptr } },
1359 { (PRFuncPtr*) &mSymbols.fUniformBlockBinding, { "UniformBlockBinding", nullptr } },
1360 END_SYMBOLS
1361 };
1362 fnLoadForFeature(symbols, GLFeature::uniform_buffer_object);
1363 }
1364
1365 if (IsSupported(GLFeature::uniform_matrix_nonsquare)) {
1366 const SymLoadStruct symbols[] = {
1367 { (PRFuncPtr*) &mSymbols.fUniformMatrix2x3fv, { "UniformMatrix2x3fv", nullptr } },
1368 { (PRFuncPtr*) &mSymbols.fUniformMatrix2x4fv, { "UniformMatrix2x4fv", nullptr } },
1369 { (PRFuncPtr*) &mSymbols.fUniformMatrix3x2fv, { "UniformMatrix3x2fv", nullptr } },
1370 { (PRFuncPtr*) &mSymbols.fUniformMatrix3x4fv, { "UniformMatrix3x4fv", nullptr } },
1371 { (PRFuncPtr*) &mSymbols.fUniformMatrix4x2fv, { "UniformMatrix4x2fv", nullptr } },
1372 { (PRFuncPtr*) &mSymbols.fUniformMatrix4x3fv, { "UniformMatrix4x3fv", nullptr } },
1373 END_SYMBOLS
1374 };
1375 fnLoadForFeature(symbols, GLFeature::uniform_matrix_nonsquare);
1376 }
1377
1378 if (IsSupported(GLFeature::internalformat_query)) {
1379 const SymLoadStruct symbols[] = {
1380 CORE_SYMBOL(GetInternalformativ),
1381 END_SYMBOLS
1382 };
1383 fnLoadForFeature(symbols, GLFeature::internalformat_query);
1384 }
1385
1386 if (IsSupported(GLFeature::invalidate_framebuffer)) {
1387 const SymLoadStruct symbols[] = {
1388 { (PRFuncPtr*) &mSymbols.fInvalidateFramebuffer, { "InvalidateFramebuffer", nullptr } },
1389 { (PRFuncPtr*) &mSymbols.fInvalidateSubFramebuffer, { "InvalidateSubFramebuffer", nullptr } },
1390 END_SYMBOLS
1391 };
1392 fnLoadForFeature(symbols, GLFeature::invalidate_framebuffer);
1393 }
1394
1395 if (IsSupported(GLFeature::prim_restart)) {
1396 const SymLoadStruct symbols[] = {
1397 { (PRFuncPtr*) &mSymbols.fPrimitiveRestartIndex, { "PrimitiveRestartIndex", "PrimitiveRestartIndexNV", nullptr } },
1398 END_SYMBOLS
1399 };
1400 fnLoadForFeature(symbols, GLFeature::prim_restart);
1401 }
1402
1403 if (IsExtensionSupported(KHR_debug)) {
1404 const SymLoadStruct symbols[] = {
1405 { (PRFuncPtr*) &mSymbols.fDebugMessageControl, { "DebugMessageControl", "DebugMessageControlKHR", nullptr } },
1406 { (PRFuncPtr*) &mSymbols.fDebugMessageInsert, { "DebugMessageInsert", "DebugMessageInsertKHR", nullptr } },
1407 { (PRFuncPtr*) &mSymbols.fDebugMessageCallback, { "DebugMessageCallback", "DebugMessageCallbackKHR", nullptr } },
1408 { (PRFuncPtr*) &mSymbols.fGetDebugMessageLog, { "GetDebugMessageLog", "GetDebugMessageLogKHR", nullptr } },
1409 { (PRFuncPtr*) &mSymbols.fGetPointerv, { "GetPointerv", "GetPointervKHR", nullptr } },
1410 { (PRFuncPtr*) &mSymbols.fPushDebugGroup, { "PushDebugGroup", "PushDebugGroupKHR", nullptr } },
1411 { (PRFuncPtr*) &mSymbols.fPopDebugGroup, { "PopDebugGroup", "PopDebugGroupKHR", nullptr } },
1412 { (PRFuncPtr*) &mSymbols.fObjectLabel, { "ObjectLabel", "ObjectLabelKHR", nullptr } },
1413 { (PRFuncPtr*) &mSymbols.fGetObjectLabel, { "GetObjectLabel", "GetObjectLabelKHR", nullptr } },
1414 { (PRFuncPtr*) &mSymbols.fObjectPtrLabel, { "ObjectPtrLabel", "ObjectPtrLabelKHR", nullptr } },
1415 { (PRFuncPtr*) &mSymbols.fGetObjectPtrLabel, { "GetObjectPtrLabel", "GetObjectPtrLabelKHR", nullptr } },
1416 END_SYMBOLS
1417 };
1418 fnLoadForExt(symbols, KHR_debug);
1419 }
1420
1421 if (IsExtensionSupported(NV_fence)) {
1422 const SymLoadStruct symbols[] = {
1423 { (PRFuncPtr*) &mSymbols.fGenFences, { "GenFencesNV", nullptr } },
1424 { (PRFuncPtr*) &mSymbols.fDeleteFences, { "DeleteFencesNV", nullptr } },
1425 { (PRFuncPtr*) &mSymbols.fSetFence, { "SetFenceNV", nullptr } },
1426 { (PRFuncPtr*) &mSymbols.fTestFence, { "TestFenceNV", nullptr } },
1427 { (PRFuncPtr*) &mSymbols.fFinishFence, { "FinishFenceNV", nullptr } },
1428 { (PRFuncPtr*) &mSymbols.fIsFence, { "IsFenceNV", nullptr } },
1429 { (PRFuncPtr*) &mSymbols.fGetFenceiv, { "GetFenceivNV", nullptr } },
1430 END_SYMBOLS
1431 };
1432 fnLoadForExt(symbols, NV_fence);
1433 }
1434
1435 // clang-format on
1436
1437 if (IsExtensionSupported(NV_texture_barrier)) {
1438 const SymLoadStruct symbols[] = {
1439 {(PRFuncPtr*)&mSymbols.fTextureBarrier, {"TextureBarrierNV", nullptr}},
1440 END_SYMBOLS};
1441 fnLoadForExt(symbols, NV_texture_barrier);
1442 }
1443
1444 if (IsSupported(GLFeature::read_buffer)) {
1445 const SymLoadStruct symbols[] = {CORE_SYMBOL(ReadBuffer), END_SYMBOLS};
1446 fnLoadForFeature(symbols, GLFeature::read_buffer);
1447 }
1448
1449 if (IsExtensionSupported(APPLE_framebuffer_multisample)) {
1450 const SymLoadStruct symbols[] = {
1451 CORE_SYMBOL(ResolveMultisampleFramebufferAPPLE), END_SYMBOLS};
1452 fnLoadForExt(symbols, APPLE_framebuffer_multisample);
1453 }
1454
1455 // Load developer symbols, don't fail if we can't find them.
1456 const SymLoadStruct devSymbols[] = {CORE_SYMBOL(GetTexImage),
1457 CORE_SYMBOL(GetTexLevelParameteriv),
1458 END_SYMBOLS};
1459 const bool warnOnFailures = ShouldSpew();
1460 LoadSymbols(devSymbols, trygl, prefix, warnOnFailures);
1461 }
1462
1463 #undef CORE_SYMBOL
1464 #undef CORE_EXT_SYMBOL2
1465 #undef EXT_SYMBOL2
1466 #undef EXT_SYMBOL3
1467 #undef END_SYMBOLS
1468
DebugCallback(GLenum source,GLenum type,GLuint id,GLenum severity,GLsizei length,const GLchar * message)1469 void GLContext::DebugCallback(GLenum source, GLenum type, GLuint id,
1470 GLenum severity, GLsizei length,
1471 const GLchar* message) {
1472 nsAutoCString sourceStr;
1473 switch (source) {
1474 case LOCAL_GL_DEBUG_SOURCE_API:
1475 sourceStr = NS_LITERAL_CSTRING("SOURCE_API");
1476 break;
1477 case LOCAL_GL_DEBUG_SOURCE_WINDOW_SYSTEM:
1478 sourceStr = NS_LITERAL_CSTRING("SOURCE_WINDOW_SYSTEM");
1479 break;
1480 case LOCAL_GL_DEBUG_SOURCE_SHADER_COMPILER:
1481 sourceStr = NS_LITERAL_CSTRING("SOURCE_SHADER_COMPILER");
1482 break;
1483 case LOCAL_GL_DEBUG_SOURCE_THIRD_PARTY:
1484 sourceStr = NS_LITERAL_CSTRING("SOURCE_THIRD_PARTY");
1485 break;
1486 case LOCAL_GL_DEBUG_SOURCE_APPLICATION:
1487 sourceStr = NS_LITERAL_CSTRING("SOURCE_APPLICATION");
1488 break;
1489 case LOCAL_GL_DEBUG_SOURCE_OTHER:
1490 sourceStr = NS_LITERAL_CSTRING("SOURCE_OTHER");
1491 break;
1492 default:
1493 sourceStr = nsPrintfCString("<source 0x%04x>", source);
1494 break;
1495 }
1496
1497 nsAutoCString typeStr;
1498 switch (type) {
1499 case LOCAL_GL_DEBUG_TYPE_ERROR:
1500 typeStr = NS_LITERAL_CSTRING("TYPE_ERROR");
1501 break;
1502 case LOCAL_GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR:
1503 typeStr = NS_LITERAL_CSTRING("TYPE_DEPRECATED_BEHAVIOR");
1504 break;
1505 case LOCAL_GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR:
1506 typeStr = NS_LITERAL_CSTRING("TYPE_UNDEFINED_BEHAVIOR");
1507 break;
1508 case LOCAL_GL_DEBUG_TYPE_PORTABILITY:
1509 typeStr = NS_LITERAL_CSTRING("TYPE_PORTABILITY");
1510 break;
1511 case LOCAL_GL_DEBUG_TYPE_PERFORMANCE:
1512 typeStr = NS_LITERAL_CSTRING("TYPE_PERFORMANCE");
1513 break;
1514 case LOCAL_GL_DEBUG_TYPE_OTHER:
1515 typeStr = NS_LITERAL_CSTRING("TYPE_OTHER");
1516 break;
1517 case LOCAL_GL_DEBUG_TYPE_MARKER:
1518 typeStr = NS_LITERAL_CSTRING("TYPE_MARKER");
1519 break;
1520 default:
1521 typeStr = nsPrintfCString("<type 0x%04x>", type);
1522 break;
1523 }
1524
1525 nsAutoCString sevStr;
1526 switch (severity) {
1527 case LOCAL_GL_DEBUG_SEVERITY_HIGH:
1528 sevStr = NS_LITERAL_CSTRING("SEVERITY_HIGH");
1529 break;
1530 case LOCAL_GL_DEBUG_SEVERITY_MEDIUM:
1531 sevStr = NS_LITERAL_CSTRING("SEVERITY_MEDIUM");
1532 break;
1533 case LOCAL_GL_DEBUG_SEVERITY_LOW:
1534 sevStr = NS_LITERAL_CSTRING("SEVERITY_LOW");
1535 break;
1536 case LOCAL_GL_DEBUG_SEVERITY_NOTIFICATION:
1537 sevStr = NS_LITERAL_CSTRING("SEVERITY_NOTIFICATION");
1538 break;
1539 default:
1540 sevStr = nsPrintfCString("<severity 0x%04x>", severity);
1541 break;
1542 }
1543
1544 printf_stderr("[KHR_debug: 0x%" PRIxPTR "] ID %u: %s, %s, %s:\n %s\n",
1545 (uintptr_t)this, id, sourceStr.BeginReading(),
1546 typeStr.BeginReading(), sevStr.BeginReading(), message);
1547 }
1548
InitExtensions()1549 void GLContext::InitExtensions() {
1550 MOZ_ASSERT(IsCurrent());
1551
1552 std::vector<nsCString> driverExtensionList;
1553
1554 [&]() {
1555 if (mSymbols.fGetStringi) {
1556 GLuint count = 0;
1557 if (GetPotentialInteger(LOCAL_GL_NUM_EXTENSIONS, (GLint*)&count)) {
1558 for (GLuint i = 0; i < count; i++) {
1559 // This is UTF-8.
1560 const char* rawExt = (const char*)fGetStringi(LOCAL_GL_EXTENSIONS, i);
1561
1562 // We CANNOT use nsDependentCString here, because the spec doesn't
1563 // guarantee that the pointers returned are different, only that their
1564 // contents are. On Flame, each of these index string queries returns
1565 // the same address.
1566 driverExtensionList.push_back(nsCString(rawExt));
1567 }
1568 return;
1569 }
1570 }
1571
1572 const char* rawExts = (const char*)fGetString(LOCAL_GL_EXTENSIONS);
1573 if (rawExts) {
1574 nsDependentCString exts(rawExts);
1575 SplitByChar(exts, ' ', &driverExtensionList);
1576 }
1577 }();
1578 const auto err = fGetError();
1579 MOZ_ALWAYS_TRUE(!err);
1580
1581 const bool shouldDumpExts = ShouldDumpExts();
1582 if (shouldDumpExts) {
1583 printf_stderr("%i GL driver extensions: (*: recognized)\n",
1584 (uint32_t)driverExtensionList.size());
1585 }
1586
1587 MarkBitfieldByStrings(driverExtensionList, shouldDumpExts, sExtensionNames,
1588 &mAvailableExtensions);
1589
1590 if (WorkAroundDriverBugs()) {
1591 if (Vendor() == GLVendor::Qualcomm) {
1592 // Some Adreno drivers do not report GL_OES_EGL_sync, but they really do
1593 // support it.
1594 MarkExtensionSupported(OES_EGL_sync);
1595 }
1596
1597 if (Vendor() == GLVendor::ATI) {
1598 // ATI drivers say this extension exists, but we can't
1599 // actually find the EGLImageTargetRenderbufferStorageOES
1600 // extension function pointer in the drivers.
1601 MarkExtensionUnsupported(OES_EGL_image);
1602 }
1603
1604 if (Vendor() == GLVendor::Imagination && Renderer() == GLRenderer::SGX540) {
1605 // Bug 980048
1606 MarkExtensionUnsupported(OES_EGL_sync);
1607 }
1608
1609 #ifdef MOZ_WIDGET_ANDROID
1610 if (Vendor() == GLVendor::Imagination &&
1611 Renderer() == GLRenderer::SGX544MP &&
1612 AndroidBridge::Bridge()->GetAPIVersion() < 21) {
1613 // Bug 1026404
1614 MarkExtensionUnsupported(OES_EGL_image);
1615 MarkExtensionUnsupported(OES_EGL_image_external);
1616 }
1617 #endif
1618
1619 if (Vendor() == GLVendor::ARM && (Renderer() == GLRenderer::Mali400MP ||
1620 Renderer() == GLRenderer::Mali450MP)) {
1621 // Bug 1264505
1622 MarkExtensionUnsupported(OES_EGL_image_external);
1623 }
1624
1625 if (Renderer() == GLRenderer::AndroidEmulator) {
1626 // the Android emulator, which we use to run B2G reftests on,
1627 // doesn't expose the OES_rgb8_rgba8 extension, but it seems to
1628 // support it (tautologically, as it only runs on desktop GL).
1629 MarkExtensionSupported(OES_rgb8_rgba8);
1630 }
1631
1632 if (Vendor() == GLVendor::VMware &&
1633 Renderer() == GLRenderer::GalliumLlvmpipe) {
1634 // The llvmpipe driver that is used on linux try servers appears to have
1635 // buggy support for s3tc/dxt1 compressed textures.
1636 // See Bug 975824.
1637 MarkExtensionUnsupported(EXT_texture_compression_s3tc);
1638 MarkExtensionUnsupported(EXT_texture_compression_dxt1);
1639 MarkExtensionUnsupported(ANGLE_texture_compression_dxt3);
1640 MarkExtensionUnsupported(ANGLE_texture_compression_dxt5);
1641 }
1642
1643 #ifdef XP_MACOSX
1644 // Bug 1009642: On OSX Mavericks (10.9), the driver for Intel HD
1645 // 3000 appears to be buggy WRT updating sub-images of S3TC
1646 // textures with glCompressedTexSubImage2D. Works on Intel HD 4000
1647 // and Intel HD 5000/Iris that I tested.
1648 // Bug 1124996: Appears to be the same on OSX Yosemite (10.10)
1649 if (nsCocoaFeatures::OSXVersionMajor() == 10 &&
1650 nsCocoaFeatures::OSXVersionMinor() >= 9 &&
1651 Renderer() == GLRenderer::IntelHD3000) {
1652 MarkExtensionUnsupported(EXT_texture_compression_s3tc);
1653 }
1654
1655 // OSX supports EXT_texture_sRGB in Legacy contexts, but not in Core
1656 // contexts. Though EXT_texture_sRGB was included into GL2.1, it *excludes*
1657 // the interactions with s3tc. Strictly speaking, you must advertize support
1658 // for EXT_texture_sRGB in order to allow for srgb+s3tc on desktop GL. The
1659 // omission of EXT_texture_sRGB in OSX Core contexts appears to be a bug.
1660 MarkExtensionSupported(EXT_texture_sRGB);
1661 #endif
1662 }
1663
1664 if (shouldDumpExts) {
1665 printf_stderr("\nActivated extensions:\n");
1666
1667 for (size_t i = 0; i < mAvailableExtensions.size(); i++) {
1668 if (!mAvailableExtensions[i]) continue;
1669
1670 const char* ext = sExtensionNames[i];
1671 printf_stderr("[%i] %s\n", (uint32_t)i, ext);
1672 }
1673 }
1674 }
1675
PlatformStartup()1676 void GLContext::PlatformStartup() {
1677 RegisterStrongMemoryReporter(new GfxTexturesReporter());
1678 }
1679
1680 // Common code for checking for both GL extensions and GLX extensions.
ListHasExtension(const GLubyte * extensions,const char * extension)1681 bool GLContext::ListHasExtension(const GLubyte* extensions,
1682 const char* extension) {
1683 // fix bug 612572 - we were crashing as we were calling this function with
1684 // extensions==null
1685 if (extensions == nullptr || extension == nullptr) return false;
1686
1687 const GLubyte* start;
1688 GLubyte* where;
1689 GLubyte* terminator;
1690
1691 /* Extension names should not have spaces. */
1692 where = (GLubyte*)strchr(extension, ' ');
1693 if (where || *extension == '\0') return false;
1694
1695 /*
1696 * It takes a bit of care to be fool-proof about parsing the
1697 * OpenGL extensions string. Don't be fooled by sub-strings,
1698 * etc.
1699 */
1700 start = extensions;
1701 for (;;) {
1702 where = (GLubyte*)strstr((const char*)start, extension);
1703 if (!where) {
1704 break;
1705 }
1706 terminator = where + strlen(extension);
1707 if (where == start || *(where - 1) == ' ') {
1708 if (*terminator == ' ' || *terminator == '\0') {
1709 return true;
1710 }
1711 }
1712 start = terminator;
1713 }
1714 return false;
1715 }
1716
ChooseGLFormats(const SurfaceCaps & caps) const1717 GLFormats GLContext::ChooseGLFormats(const SurfaceCaps& caps) const {
1718 GLFormats formats;
1719
1720 // If we're on ES2 hardware and we have an explicit request for 16 bits of
1721 // color or less OR we don't support full 8-bit color, return a 4444 or 565
1722 // format.
1723 bool bpp16 = caps.bpp16;
1724 if (IsGLES()) {
1725 if (!IsExtensionSupported(OES_rgb8_rgba8)) bpp16 = true;
1726 } else {
1727 // RGB565 is uncommon on desktop, requiring ARB_ES2_compatibility.
1728 // Since it's also vanishingly useless there, let's not support it.
1729 bpp16 = false;
1730 }
1731
1732 if (bpp16) {
1733 MOZ_ASSERT(IsGLES());
1734 if (caps.alpha) {
1735 formats.color_texInternalFormat = LOCAL_GL_RGBA;
1736 formats.color_texFormat = LOCAL_GL_RGBA;
1737 formats.color_texType = LOCAL_GL_UNSIGNED_SHORT_4_4_4_4;
1738 formats.color_rbFormat = LOCAL_GL_RGBA4;
1739 } else {
1740 formats.color_texInternalFormat = LOCAL_GL_RGB;
1741 formats.color_texFormat = LOCAL_GL_RGB;
1742 formats.color_texType = LOCAL_GL_UNSIGNED_SHORT_5_6_5;
1743 formats.color_rbFormat = LOCAL_GL_RGB565;
1744 }
1745 } else {
1746 formats.color_texType = LOCAL_GL_UNSIGNED_BYTE;
1747
1748 if (caps.alpha) {
1749 formats.color_texInternalFormat =
1750 IsGLES() ? LOCAL_GL_RGBA : LOCAL_GL_RGBA8;
1751 formats.color_texFormat = LOCAL_GL_RGBA;
1752 formats.color_rbFormat = LOCAL_GL_RGBA8;
1753 } else {
1754 formats.color_texInternalFormat = IsGLES() ? LOCAL_GL_RGB : LOCAL_GL_RGB8;
1755 formats.color_texFormat = LOCAL_GL_RGB;
1756 formats.color_rbFormat = LOCAL_GL_RGB8;
1757 }
1758 }
1759
1760 uint32_t msaaLevel = gfxPrefs::MSAALevel();
1761 GLsizei samples = msaaLevel * msaaLevel;
1762 samples = std::min(samples, mMaxSamples);
1763
1764 // Bug 778765.
1765 if (WorkAroundDriverBugs() && samples == 1) {
1766 samples = 0;
1767 }
1768 formats.samples = samples;
1769
1770 // Be clear that these are 0 if unavailable.
1771 formats.depthStencil = 0;
1772 if (IsSupported(GLFeature::packed_depth_stencil)) {
1773 formats.depthStencil = LOCAL_GL_DEPTH24_STENCIL8;
1774 }
1775
1776 formats.depth = 0;
1777 if (IsGLES()) {
1778 if (IsExtensionSupported(OES_depth24)) {
1779 formats.depth = LOCAL_GL_DEPTH_COMPONENT24;
1780 } else {
1781 formats.depth = LOCAL_GL_DEPTH_COMPONENT16;
1782 }
1783 } else {
1784 formats.depth = LOCAL_GL_DEPTH_COMPONENT24;
1785 }
1786
1787 formats.stencil = LOCAL_GL_STENCIL_INDEX8;
1788
1789 return formats;
1790 }
1791
IsFramebufferComplete(GLuint fb,GLenum * pStatus)1792 bool GLContext::IsFramebufferComplete(GLuint fb, GLenum* pStatus) {
1793 MOZ_ASSERT(fb);
1794
1795 ScopedBindFramebuffer autoFB(this, fb);
1796 MOZ_ASSERT(fIsFramebuffer(fb));
1797
1798 GLenum status = fCheckFramebufferStatus(LOCAL_GL_FRAMEBUFFER);
1799 if (pStatus) *pStatus = status;
1800
1801 return status == LOCAL_GL_FRAMEBUFFER_COMPLETE;
1802 }
1803
AttachBuffersToFB(GLuint colorTex,GLuint colorRB,GLuint depthRB,GLuint stencilRB,GLuint fb,GLenum target)1804 void GLContext::AttachBuffersToFB(GLuint colorTex, GLuint colorRB,
1805 GLuint depthRB, GLuint stencilRB, GLuint fb,
1806 GLenum target) {
1807 MOZ_ASSERT(fb);
1808 MOZ_ASSERT(!(colorTex && colorRB));
1809
1810 ScopedBindFramebuffer autoFB(this, fb);
1811 MOZ_ASSERT(fIsFramebuffer(fb)); // It only counts after being bound.
1812
1813 if (colorTex) {
1814 MOZ_ASSERT(fIsTexture(colorTex));
1815 MOZ_ASSERT(target == LOCAL_GL_TEXTURE_2D ||
1816 target == LOCAL_GL_TEXTURE_RECTANGLE_ARB);
1817 fFramebufferTexture2D(LOCAL_GL_FRAMEBUFFER, LOCAL_GL_COLOR_ATTACHMENT0,
1818 target, colorTex, 0);
1819 } else if (colorRB) {
1820 // On the Android 4.3 emulator, IsRenderbuffer may return false incorrectly.
1821 MOZ_ASSERT_IF(Renderer() != GLRenderer::AndroidEmulator,
1822 fIsRenderbuffer(colorRB));
1823 fFramebufferRenderbuffer(LOCAL_GL_FRAMEBUFFER, LOCAL_GL_COLOR_ATTACHMENT0,
1824 LOCAL_GL_RENDERBUFFER, colorRB);
1825 }
1826
1827 if (depthRB) {
1828 MOZ_ASSERT_IF(Renderer() != GLRenderer::AndroidEmulator,
1829 fIsRenderbuffer(depthRB));
1830 fFramebufferRenderbuffer(LOCAL_GL_FRAMEBUFFER, LOCAL_GL_DEPTH_ATTACHMENT,
1831 LOCAL_GL_RENDERBUFFER, depthRB);
1832 }
1833
1834 if (stencilRB) {
1835 MOZ_ASSERT_IF(Renderer() != GLRenderer::AndroidEmulator,
1836 fIsRenderbuffer(stencilRB));
1837 fFramebufferRenderbuffer(LOCAL_GL_FRAMEBUFFER, LOCAL_GL_STENCIL_ATTACHMENT,
1838 LOCAL_GL_RENDERBUFFER, stencilRB);
1839 }
1840 }
1841
AssembleOffscreenFBs(const GLuint colorMSRB,const GLuint depthRB,const GLuint stencilRB,const GLuint texture,GLuint * drawFB_out,GLuint * readFB_out)1842 bool GLContext::AssembleOffscreenFBs(const GLuint colorMSRB,
1843 const GLuint depthRB,
1844 const GLuint stencilRB,
1845 const GLuint texture, GLuint* drawFB_out,
1846 GLuint* readFB_out) {
1847 if (!colorMSRB && !texture) {
1848 MOZ_ASSERT(!depthRB && !stencilRB);
1849
1850 if (drawFB_out) *drawFB_out = 0;
1851 if (readFB_out) *readFB_out = 0;
1852
1853 return true;
1854 }
1855
1856 ScopedBindFramebuffer autoFB(this);
1857
1858 GLuint drawFB = 0;
1859 GLuint readFB = 0;
1860
1861 if (texture) {
1862 readFB = 0;
1863 fGenFramebuffers(1, &readFB);
1864 BindFB(readFB);
1865 fFramebufferTexture2D(LOCAL_GL_FRAMEBUFFER, LOCAL_GL_COLOR_ATTACHMENT0,
1866 LOCAL_GL_TEXTURE_2D, texture, 0);
1867 }
1868
1869 if (colorMSRB) {
1870 drawFB = 0;
1871 fGenFramebuffers(1, &drawFB);
1872 BindFB(drawFB);
1873 fFramebufferRenderbuffer(LOCAL_GL_FRAMEBUFFER, LOCAL_GL_COLOR_ATTACHMENT0,
1874 LOCAL_GL_RENDERBUFFER, colorMSRB);
1875 } else {
1876 drawFB = readFB;
1877 }
1878 MOZ_ASSERT(GetFB() == drawFB);
1879
1880 if (depthRB) {
1881 fFramebufferRenderbuffer(LOCAL_GL_FRAMEBUFFER, LOCAL_GL_DEPTH_ATTACHMENT,
1882 LOCAL_GL_RENDERBUFFER, depthRB);
1883 }
1884
1885 if (stencilRB) {
1886 fFramebufferRenderbuffer(LOCAL_GL_FRAMEBUFFER, LOCAL_GL_STENCIL_ATTACHMENT,
1887 LOCAL_GL_RENDERBUFFER, stencilRB);
1888 }
1889
1890 // We should be all resized. Check for framebuffer completeness.
1891 GLenum status;
1892 bool isComplete = true;
1893
1894 if (!IsFramebufferComplete(drawFB, &status)) {
1895 NS_WARNING("DrawFBO: Incomplete");
1896 #ifdef MOZ_GL_DEBUG
1897 if (ShouldSpew()) {
1898 printf_stderr("Framebuffer status: %X\n", status);
1899 }
1900 #endif
1901 isComplete = false;
1902 }
1903
1904 if (!IsFramebufferComplete(readFB, &status)) {
1905 NS_WARNING("ReadFBO: Incomplete");
1906 #ifdef MOZ_GL_DEBUG
1907 if (ShouldSpew()) {
1908 printf_stderr("Framebuffer status: %X\n", status);
1909 }
1910 #endif
1911 isComplete = false;
1912 }
1913
1914 if (drawFB_out) {
1915 *drawFB_out = drawFB;
1916 } else if (drawFB) {
1917 MOZ_CRASH("drawFB created when not requested!");
1918 }
1919
1920 if (readFB_out) {
1921 *readFB_out = readFB;
1922 } else if (readFB) {
1923 MOZ_CRASH("readFB created when not requested!");
1924 }
1925
1926 return isComplete;
1927 }
1928
MarkDestroyed()1929 void GLContext::MarkDestroyed() {
1930 if (IsDestroyed()) return;
1931
1932 // Null these before they're naturally nulled after dtor, as we want GLContext
1933 // to still be alive in *their* dtors.
1934 mScreen = nullptr;
1935 mBlitHelper = nullptr;
1936 mReadTexImageHelper = nullptr;
1937
1938 if (!MakeCurrent()) {
1939 NS_WARNING(
1940 "MakeCurrent() failed during MarkDestroyed! Skipping GL object "
1941 "teardown.");
1942 }
1943
1944 mSymbols = {};
1945 }
1946
1947 #ifdef MOZ_GL_DEBUG
AssertNotPassingStackBufferToTheGL(const void * ptr)1948 /* static */ void GLContext::AssertNotPassingStackBufferToTheGL(
1949 const void* ptr) {
1950 int somethingOnTheStack;
1951 const void* someStackPtr = &somethingOnTheStack;
1952 const int page_bits = 12;
1953 intptr_t page = reinterpret_cast<uintptr_t>(ptr) >> page_bits;
1954 intptr_t someStackPage =
1955 reinterpret_cast<uintptr_t>(someStackPtr) >> page_bits;
1956 uintptr_t pageDistance = std::abs(page - someStackPage);
1957
1958 // Explanation for the "distance <= 1" check here as opposed to just
1959 // an equality check.
1960 //
1961 // Here we assume that pages immediately adjacent to the someStackAddress
1962 // page, are also stack pages. That allows to catch the case where the calling
1963 // frame put a buffer on the stack, and we just crossed the page boundary.
1964 // That is likely to happen, precisely, when using stack arrays. I hit that
1965 // specifically with CompositorOGL::Initialize.
1966 //
1967 // In theory we could be unlucky and wrongly assert here. If that happens,
1968 // it will only affect debug builds, and looking at stacks we'll be able to
1969 // see that this assert is wrong and revert to the conservative and safe
1970 // approach of only asserting when address and someStackAddress are
1971 // on the same page.
1972 bool isStackAddress = pageDistance <= 1;
1973 MOZ_ASSERT(!isStackAddress,
1974 "Please don't pass stack arrays to the GL. "
1975 "Consider using HeapCopyOfStackArray. "
1976 "See bug 1005658.");
1977 }
1978
CreatedProgram(GLContext * aOrigin,GLuint aName)1979 void GLContext::CreatedProgram(GLContext* aOrigin, GLuint aName) {
1980 mTrackedPrograms.AppendElement(NamedResource(aOrigin, aName));
1981 }
1982
CreatedShader(GLContext * aOrigin,GLuint aName)1983 void GLContext::CreatedShader(GLContext* aOrigin, GLuint aName) {
1984 mTrackedShaders.AppendElement(NamedResource(aOrigin, aName));
1985 }
1986
CreatedBuffers(GLContext * aOrigin,GLsizei aCount,GLuint * aNames)1987 void GLContext::CreatedBuffers(GLContext* aOrigin, GLsizei aCount,
1988 GLuint* aNames) {
1989 for (GLsizei i = 0; i < aCount; ++i) {
1990 mTrackedBuffers.AppendElement(NamedResource(aOrigin, aNames[i]));
1991 }
1992 }
1993
CreatedQueries(GLContext * aOrigin,GLsizei aCount,GLuint * aNames)1994 void GLContext::CreatedQueries(GLContext* aOrigin, GLsizei aCount,
1995 GLuint* aNames) {
1996 for (GLsizei i = 0; i < aCount; ++i) {
1997 mTrackedQueries.AppendElement(NamedResource(aOrigin, aNames[i]));
1998 }
1999 }
2000
CreatedTextures(GLContext * aOrigin,GLsizei aCount,GLuint * aNames)2001 void GLContext::CreatedTextures(GLContext* aOrigin, GLsizei aCount,
2002 GLuint* aNames) {
2003 for (GLsizei i = 0; i < aCount; ++i) {
2004 mTrackedTextures.AppendElement(NamedResource(aOrigin, aNames[i]));
2005 }
2006 }
2007
CreatedFramebuffers(GLContext * aOrigin,GLsizei aCount,GLuint * aNames)2008 void GLContext::CreatedFramebuffers(GLContext* aOrigin, GLsizei aCount,
2009 GLuint* aNames) {
2010 for (GLsizei i = 0; i < aCount; ++i) {
2011 mTrackedFramebuffers.AppendElement(NamedResource(aOrigin, aNames[i]));
2012 }
2013 }
2014
CreatedRenderbuffers(GLContext * aOrigin,GLsizei aCount,GLuint * aNames)2015 void GLContext::CreatedRenderbuffers(GLContext* aOrigin, GLsizei aCount,
2016 GLuint* aNames) {
2017 for (GLsizei i = 0; i < aCount; ++i) {
2018 mTrackedRenderbuffers.AppendElement(NamedResource(aOrigin, aNames[i]));
2019 }
2020 }
2021
RemoveNamesFromArray(GLContext * aOrigin,GLsizei aCount,const GLuint * aNames,nsTArray<GLContext::NamedResource> & aArray)2022 static void RemoveNamesFromArray(GLContext* aOrigin, GLsizei aCount,
2023 const GLuint* aNames,
2024 nsTArray<GLContext::NamedResource>& aArray) {
2025 for (GLsizei j = 0; j < aCount; ++j) {
2026 GLuint name = aNames[j];
2027 // name 0 can be ignored
2028 if (name == 0) continue;
2029
2030 for (uint32_t i = 0; i < aArray.Length(); ++i) {
2031 if (aArray[i].name == name) {
2032 aArray.RemoveElementAt(i);
2033 break;
2034 }
2035 }
2036 }
2037 }
2038
DeletedProgram(GLContext * aOrigin,GLuint aName)2039 void GLContext::DeletedProgram(GLContext* aOrigin, GLuint aName) {
2040 RemoveNamesFromArray(aOrigin, 1, &aName, mTrackedPrograms);
2041 }
2042
DeletedShader(GLContext * aOrigin,GLuint aName)2043 void GLContext::DeletedShader(GLContext* aOrigin, GLuint aName) {
2044 RemoveNamesFromArray(aOrigin, 1, &aName, mTrackedShaders);
2045 }
2046
DeletedBuffers(GLContext * aOrigin,GLsizei aCount,const GLuint * aNames)2047 void GLContext::DeletedBuffers(GLContext* aOrigin, GLsizei aCount,
2048 const GLuint* aNames) {
2049 RemoveNamesFromArray(aOrigin, aCount, aNames, mTrackedBuffers);
2050 }
2051
DeletedQueries(GLContext * aOrigin,GLsizei aCount,const GLuint * aNames)2052 void GLContext::DeletedQueries(GLContext* aOrigin, GLsizei aCount,
2053 const GLuint* aNames) {
2054 RemoveNamesFromArray(aOrigin, aCount, aNames, mTrackedQueries);
2055 }
2056
DeletedTextures(GLContext * aOrigin,GLsizei aCount,const GLuint * aNames)2057 void GLContext::DeletedTextures(GLContext* aOrigin, GLsizei aCount,
2058 const GLuint* aNames) {
2059 RemoveNamesFromArray(aOrigin, aCount, aNames, mTrackedTextures);
2060 }
2061
DeletedFramebuffers(GLContext * aOrigin,GLsizei aCount,const GLuint * aNames)2062 void GLContext::DeletedFramebuffers(GLContext* aOrigin, GLsizei aCount,
2063 const GLuint* aNames) {
2064 RemoveNamesFromArray(aOrigin, aCount, aNames, mTrackedFramebuffers);
2065 }
2066
DeletedRenderbuffers(GLContext * aOrigin,GLsizei aCount,const GLuint * aNames)2067 void GLContext::DeletedRenderbuffers(GLContext* aOrigin, GLsizei aCount,
2068 const GLuint* aNames) {
2069 RemoveNamesFromArray(aOrigin, aCount, aNames, mTrackedRenderbuffers);
2070 }
2071
MarkContextDestroyedInArray(GLContext * aContext,nsTArray<GLContext::NamedResource> & aArray)2072 static void MarkContextDestroyedInArray(
2073 GLContext* aContext, nsTArray<GLContext::NamedResource>& aArray) {
2074 for (uint32_t i = 0; i < aArray.Length(); ++i) {
2075 if (aArray[i].origin == aContext) aArray[i].originDeleted = true;
2076 }
2077 }
2078
SharedContextDestroyed(GLContext * aChild)2079 void GLContext::SharedContextDestroyed(GLContext* aChild) {
2080 MarkContextDestroyedInArray(aChild, mTrackedPrograms);
2081 MarkContextDestroyedInArray(aChild, mTrackedShaders);
2082 MarkContextDestroyedInArray(aChild, mTrackedTextures);
2083 MarkContextDestroyedInArray(aChild, mTrackedFramebuffers);
2084 MarkContextDestroyedInArray(aChild, mTrackedRenderbuffers);
2085 MarkContextDestroyedInArray(aChild, mTrackedBuffers);
2086 MarkContextDestroyedInArray(aChild, mTrackedQueries);
2087 }
2088
ReportArrayContents(const char * title,const nsTArray<GLContext::NamedResource> & aArray)2089 static void ReportArrayContents(
2090 const char* title, const nsTArray<GLContext::NamedResource>& aArray) {
2091 if (aArray.Length() == 0) return;
2092
2093 printf_stderr("%s:\n", title);
2094
2095 nsTArray<GLContext::NamedResource> copy(aArray);
2096 copy.Sort();
2097
2098 GLContext* lastContext = nullptr;
2099 for (uint32_t i = 0; i < copy.Length(); ++i) {
2100 if (lastContext != copy[i].origin) {
2101 if (lastContext) printf_stderr("\n");
2102 printf_stderr(" [%p - %s] ", copy[i].origin,
2103 copy[i].originDeleted ? "deleted" : "live");
2104 lastContext = copy[i].origin;
2105 }
2106 printf_stderr("%d ", copy[i].name);
2107 }
2108 printf_stderr("\n");
2109 }
2110
ReportOutstandingNames()2111 void GLContext::ReportOutstandingNames() {
2112 if (!ShouldSpew()) return;
2113
2114 printf_stderr("== GLContext %p Outstanding ==\n", this);
2115
2116 ReportArrayContents("Outstanding Textures", mTrackedTextures);
2117 ReportArrayContents("Outstanding Buffers", mTrackedBuffers);
2118 ReportArrayContents("Outstanding Queries", mTrackedQueries);
2119 ReportArrayContents("Outstanding Programs", mTrackedPrograms);
2120 ReportArrayContents("Outstanding Shaders", mTrackedShaders);
2121 ReportArrayContents("Outstanding Framebuffers", mTrackedFramebuffers);
2122 ReportArrayContents("Outstanding Renderbuffers", mTrackedRenderbuffers);
2123 }
2124
2125 #endif /* DEBUG */
2126
GuaranteeResolve()2127 void GLContext::GuaranteeResolve() {
2128 if (mScreen) {
2129 mScreen->AssureBlitted();
2130 }
2131 fFinish();
2132 }
2133
OffscreenSize() const2134 const gfx::IntSize& GLContext::OffscreenSize() const {
2135 MOZ_ASSERT(IsOffscreen());
2136 return mScreen->Size();
2137 }
2138
CreateScreenBufferImpl(const IntSize & size,const SurfaceCaps & caps)2139 bool GLContext::CreateScreenBufferImpl(const IntSize& size,
2140 const SurfaceCaps& caps) {
2141 UniquePtr<GLScreenBuffer> newScreen =
2142 GLScreenBuffer::Create(this, size, caps);
2143 if (!newScreen) return false;
2144
2145 if (!newScreen->Resize(size)) {
2146 return false;
2147 }
2148
2149 // This will rebind to 0 (Screen) if needed when
2150 // it falls out of scope.
2151 ScopedBindFramebuffer autoFB(this);
2152
2153 mScreen = Move(newScreen);
2154
2155 return true;
2156 }
2157
ResizeScreenBuffer(const IntSize & size)2158 bool GLContext::ResizeScreenBuffer(const IntSize& size) {
2159 if (!IsOffscreenSizeAllowed(size)) return false;
2160
2161 return mScreen->Resize(size);
2162 }
2163
ForceDirtyScreen()2164 void GLContext::ForceDirtyScreen() {
2165 ScopedBindFramebuffer autoFB(0);
2166
2167 BeforeGLDrawCall();
2168 // no-op; just pretend we did something
2169 AfterGLDrawCall();
2170 }
2171
CleanDirtyScreen()2172 void GLContext::CleanDirtyScreen() {
2173 ScopedBindFramebuffer autoFB(0);
2174
2175 BeforeGLReadCall();
2176 // no-op; we just want to make sure the Read FBO is updated if it needs to be
2177 AfterGLReadCall();
2178 }
2179
IsOffscreenSizeAllowed(const IntSize & aSize) const2180 bool GLContext::IsOffscreenSizeAllowed(const IntSize& aSize) const {
2181 int32_t biggerDimension = std::max(aSize.width, aSize.height);
2182 int32_t maxAllowed = std::min(mMaxRenderbufferSize, mMaxTextureSize);
2183 return biggerDimension <= maxAllowed;
2184 }
2185
IsOwningThreadCurrent()2186 bool GLContext::IsOwningThreadCurrent() {
2187 return PlatformThread::CurrentId() == mOwningThreadId;
2188 }
2189
BlitHelper()2190 GLBlitHelper* GLContext::BlitHelper() {
2191 if (!mBlitHelper) {
2192 mBlitHelper.reset(new GLBlitHelper(this));
2193 }
2194
2195 return mBlitHelper.get();
2196 }
2197
ReadTexImageHelper()2198 GLReadTexImageHelper* GLContext::ReadTexImageHelper() {
2199 if (!mReadTexImageHelper) {
2200 mReadTexImageHelper = MakeUnique<GLReadTexImageHelper>(this);
2201 }
2202
2203 return mReadTexImageHelper.get();
2204 }
2205
FlushIfHeavyGLCallsSinceLastFlush()2206 void GLContext::FlushIfHeavyGLCallsSinceLastFlush() {
2207 if (!mHeavyGLCallsSinceLastFlush) {
2208 return;
2209 }
2210 if (MakeCurrent()) {
2211 fFlush();
2212 }
2213 }
2214
ShouldDumpExts()2215 /*static*/ bool GLContext::ShouldDumpExts() {
2216 return gfxEnv::GlDumpExtensions();
2217 }
2218
DoesStringMatch(const char * aString,const char * aWantedString)2219 bool DoesStringMatch(const char* aString, const char* aWantedString) {
2220 if (!aString || !aWantedString) return false;
2221
2222 const char* occurrence = strstr(aString, aWantedString);
2223
2224 // aWanted not found
2225 if (!occurrence) return false;
2226
2227 // aWantedString preceded by alpha character
2228 if (occurrence != aString && isalpha(*(occurrence - 1))) return false;
2229
2230 // aWantedVendor followed by alpha character
2231 const char* afterOccurrence = occurrence + strlen(aWantedString);
2232 if (isalpha(*afterOccurrence)) return false;
2233
2234 return true;
2235 }
2236
ShouldSpew()2237 /*static*/ bool GLContext::ShouldSpew() { return gfxEnv::GlSpew(); }
2238
SplitByChar(const nsACString & str,const char delim,std::vector<nsCString> * const out)2239 void SplitByChar(const nsACString& str, const char delim,
2240 std::vector<nsCString>* const out) {
2241 uint32_t start = 0;
2242 while (true) {
2243 int32_t end = str.FindChar(' ', start);
2244 if (end == -1) break;
2245
2246 uint32_t len = (uint32_t)end - start;
2247 nsDependentCSubstring substr(str, start, len);
2248 out->push_back(nsCString(substr));
2249
2250 start = end + 1;
2251 }
2252
2253 nsDependentCSubstring substr(str, start);
2254 out->push_back(nsCString(substr));
2255 }
2256
Readback(SharedSurface * src,gfx::DataSourceSurface * dest)2257 bool GLContext::Readback(SharedSurface* src, gfx::DataSourceSurface* dest) {
2258 MOZ_ASSERT(src && dest);
2259 MOZ_ASSERT(dest->GetSize() == src->mSize);
2260
2261 if (!MakeCurrent()) {
2262 return false;
2263 }
2264
2265 SharedSurface* prev = GetLockedSurface();
2266
2267 const bool needsSwap = src != prev;
2268 if (needsSwap) {
2269 if (prev) prev->UnlockProd();
2270 src->LockProd();
2271 }
2272
2273 GLuint tempFB = 0;
2274 GLuint tempTex = 0;
2275
2276 {
2277 ScopedBindFramebuffer autoFB(this);
2278
2279 // We're consuming from the producer side, so which do we use?
2280 // Really, we just want a read-only lock, so ConsumerAcquire is the best
2281 // match.
2282 src->ProducerReadAcquire();
2283
2284 if (src->mAttachType == AttachmentType::Screen) {
2285 fBindFramebuffer(LOCAL_GL_FRAMEBUFFER, 0);
2286 } else {
2287 fGenFramebuffers(1, &tempFB);
2288 fBindFramebuffer(LOCAL_GL_FRAMEBUFFER, tempFB);
2289
2290 switch (src->mAttachType) {
2291 case AttachmentType::GLTexture:
2292 fFramebufferTexture2D(
2293 LOCAL_GL_FRAMEBUFFER, LOCAL_GL_COLOR_ATTACHMENT0,
2294 src->ProdTextureTarget(), src->ProdTexture(), 0);
2295 break;
2296 case AttachmentType::GLRenderbuffer:
2297 fFramebufferRenderbuffer(
2298 LOCAL_GL_FRAMEBUFFER, LOCAL_GL_COLOR_ATTACHMENT0,
2299 LOCAL_GL_RENDERBUFFER, src->ProdRenderbuffer());
2300 break;
2301 default:
2302 MOZ_CRASH("GFX: bad `src->mAttachType`.");
2303 }
2304
2305 DebugOnly<GLenum> status = fCheckFramebufferStatus(LOCAL_GL_FRAMEBUFFER);
2306 MOZ_ASSERT(status == LOCAL_GL_FRAMEBUFFER_COMPLETE);
2307 }
2308
2309 if (src->NeedsIndirectReads()) {
2310 fGenTextures(1, &tempTex);
2311 {
2312 ScopedBindTexture autoTex(this, tempTex);
2313
2314 GLenum format = src->mHasAlpha ? LOCAL_GL_RGBA : LOCAL_GL_RGB;
2315 auto width = src->mSize.width;
2316 auto height = src->mSize.height;
2317 fCopyTexImage2D(LOCAL_GL_TEXTURE_2D, 0, format, 0, 0, width, height, 0);
2318 }
2319
2320 fFramebufferTexture2D(LOCAL_GL_FRAMEBUFFER, LOCAL_GL_COLOR_ATTACHMENT0,
2321 LOCAL_GL_TEXTURE_2D, tempTex, 0);
2322 }
2323
2324 ReadPixelsIntoDataSurface(this, dest);
2325
2326 src->ProducerReadRelease();
2327 }
2328
2329 if (tempFB) fDeleteFramebuffers(1, &tempFB);
2330
2331 if (tempTex) {
2332 fDeleteTextures(1, &tempTex);
2333 }
2334
2335 if (needsSwap) {
2336 src->UnlockProd();
2337 if (prev) prev->LockProd();
2338 }
2339
2340 return true;
2341 }
2342
2343 // Do whatever tear-down is necessary after drawing to our offscreen FBO,
2344 // if it's bound.
AfterGLDrawCall()2345 void GLContext::AfterGLDrawCall() {
2346 if (mScreen) {
2347 mScreen->AfterDrawCall();
2348 }
2349 mHeavyGLCallsSinceLastFlush = true;
2350 }
2351
2352 // Do whatever setup is necessary to read from our offscreen FBO, if it's
2353 // bound.
BeforeGLReadCall()2354 void GLContext::BeforeGLReadCall() {
2355 if (mScreen) mScreen->BeforeReadCall();
2356 }
2357
fBindFramebuffer(GLenum target,GLuint framebuffer)2358 void GLContext::fBindFramebuffer(GLenum target, GLuint framebuffer) {
2359 if (!mScreen) {
2360 raw_fBindFramebuffer(target, framebuffer);
2361 return;
2362 }
2363
2364 switch (target) {
2365 case LOCAL_GL_DRAW_FRAMEBUFFER_EXT:
2366 mScreen->BindDrawFB(framebuffer);
2367 return;
2368
2369 case LOCAL_GL_READ_FRAMEBUFFER_EXT:
2370 mScreen->BindReadFB(framebuffer);
2371 return;
2372
2373 case LOCAL_GL_FRAMEBUFFER:
2374 mScreen->BindFB(framebuffer);
2375 return;
2376
2377 default:
2378 // Nothing we care about, likely an error.
2379 break;
2380 }
2381
2382 raw_fBindFramebuffer(target, framebuffer);
2383 }
2384
fCopyTexImage2D(GLenum target,GLint level,GLenum internalformat,GLint x,GLint y,GLsizei width,GLsizei height,GLint border)2385 void GLContext::fCopyTexImage2D(GLenum target, GLint level,
2386 GLenum internalformat, GLint x, GLint y,
2387 GLsizei width, GLsizei height, GLint border) {
2388 if (!IsTextureSizeSafeToPassToDriver(target, width, height)) {
2389 // pass wrong values to cause the GL to generate GL_INVALID_VALUE.
2390 // See bug 737182 and the comment in IsTextureSizeSafeToPassToDriver.
2391 level = -1;
2392 width = -1;
2393 height = -1;
2394 border = -1;
2395 }
2396
2397 BeforeGLReadCall();
2398 bool didCopyTexImage2D = false;
2399 if (mScreen) {
2400 didCopyTexImage2D = mScreen->CopyTexImage2D(target, level, internalformat,
2401 x, y, width, height, border);
2402 }
2403
2404 if (!didCopyTexImage2D) {
2405 raw_fCopyTexImage2D(target, level, internalformat, x, y, width, height,
2406 border);
2407 }
2408 AfterGLReadCall();
2409 }
2410
fGetIntegerv(GLenum pname,GLint * params)2411 void GLContext::fGetIntegerv(GLenum pname, GLint* params) {
2412 switch (pname) {
2413 // LOCAL_GL_FRAMEBUFFER_BINDING is equal to
2414 // LOCAL_GL_DRAW_FRAMEBUFFER_BINDING_EXT,
2415 // so we don't need two cases.
2416 case LOCAL_GL_DRAW_FRAMEBUFFER_BINDING_EXT:
2417 if (mScreen) {
2418 *params = mScreen->GetDrawFB();
2419 } else {
2420 raw_fGetIntegerv(pname, params);
2421 }
2422 break;
2423
2424 case LOCAL_GL_READ_FRAMEBUFFER_BINDING_EXT:
2425 if (mScreen) {
2426 *params = mScreen->GetReadFB();
2427 } else {
2428 raw_fGetIntegerv(pname, params);
2429 }
2430 break;
2431
2432 case LOCAL_GL_MAX_TEXTURE_SIZE:
2433 MOZ_ASSERT(mMaxTextureSize > 0);
2434 *params = mMaxTextureSize;
2435 break;
2436
2437 case LOCAL_GL_MAX_CUBE_MAP_TEXTURE_SIZE:
2438 MOZ_ASSERT(mMaxCubeMapTextureSize > 0);
2439 *params = mMaxCubeMapTextureSize;
2440 break;
2441
2442 case LOCAL_GL_MAX_RENDERBUFFER_SIZE:
2443 MOZ_ASSERT(mMaxRenderbufferSize > 0);
2444 *params = mMaxRenderbufferSize;
2445 break;
2446
2447 case LOCAL_GL_VIEWPORT:
2448 for (size_t i = 0; i < 4; i++) {
2449 params[i] = mViewportRect[i];
2450 }
2451 break;
2452
2453 case LOCAL_GL_SCISSOR_BOX:
2454 for (size_t i = 0; i < 4; i++) {
2455 params[i] = mScissorRect[i];
2456 }
2457 break;
2458
2459 default:
2460 raw_fGetIntegerv(pname, params);
2461 break;
2462 }
2463 }
2464
fReadPixels(GLint x,GLint y,GLsizei width,GLsizei height,GLenum format,GLenum type,GLvoid * pixels)2465 void GLContext::fReadPixels(GLint x, GLint y, GLsizei width, GLsizei height,
2466 GLenum format, GLenum type, GLvoid* pixels) {
2467 BeforeGLReadCall();
2468
2469 bool didReadPixels = false;
2470 if (mScreen) {
2471 didReadPixels =
2472 mScreen->ReadPixels(x, y, width, height, format, type, pixels);
2473 }
2474
2475 if (!didReadPixels) {
2476 raw_fReadPixels(x, y, width, height, format, type, pixels);
2477 }
2478
2479 AfterGLReadCall();
2480
2481 // Check if GL is giving back 1.0 alpha for
2482 // RGBA reads to RGBA images from no-alpha buffers.
2483 #ifdef XP_MACOSX
2484 if (WorkAroundDriverBugs() && Vendor() == gl::GLVendor::NVIDIA &&
2485 format == LOCAL_GL_RGBA && type == LOCAL_GL_UNSIGNED_BYTE &&
2486 !IsCoreProfile() && width && height) {
2487 GLint alphaBits = 0;
2488 fGetIntegerv(LOCAL_GL_ALPHA_BITS, &alphaBits);
2489 if (!alphaBits) {
2490 const uint32_t alphaMask = 0xff000000;
2491
2492 uint32_t* itr = (uint32_t*)pixels;
2493 uint32_t testPixel = *itr;
2494 if ((testPixel & alphaMask) != alphaMask) {
2495 // We need to set the alpha channel to 1.0 manually.
2496 uint32_t* itrEnd =
2497 itr + width * height; // Stride is guaranteed to be width*4.
2498
2499 for (; itr != itrEnd; itr++) {
2500 *itr |= alphaMask;
2501 }
2502 }
2503 }
2504 }
2505 #endif
2506 }
2507
fDeleteFramebuffers(GLsizei n,const GLuint * names)2508 void GLContext::fDeleteFramebuffers(GLsizei n, const GLuint* names) {
2509 if (mScreen) {
2510 // Notify mScreen which framebuffers we're deleting.
2511 // Otherwise, we will get framebuffer binding mispredictions.
2512 for (int i = 0; i < n; i++) {
2513 mScreen->DeletingFB(names[i]);
2514 }
2515 }
2516
2517 // Avoid crash by flushing before glDeleteFramebuffers. See bug 1194923.
2518 if (mNeedsFlushBeforeDeleteFB) {
2519 fFlush();
2520 }
2521
2522 if (n == 1 && *names == 0) {
2523 // Deleting framebuffer 0 causes hangs on the DROID. See bug 623228.
2524 } else {
2525 raw_fDeleteFramebuffers(n, names);
2526 }
2527 TRACKING_CONTEXT(DeletedFramebuffers(this, n, names));
2528 }
2529
2530 #ifdef MOZ_WIDGET_ANDROID
2531 /**
2532 * Conservatively estimate whether there is enough available
2533 * contiguous virtual address space to map a newly allocated texture.
2534 */
WillTextureMapSucceed(GLsizei width,GLsizei height,GLenum format,GLenum type)2535 static bool WillTextureMapSucceed(GLsizei width, GLsizei height, GLenum format,
2536 GLenum type) {
2537 bool willSucceed = false;
2538 // Some drivers leave large gaps between textures, so require
2539 // there to be double the actual size of the texture available.
2540 size_t size = width * height * GetBytesPerTexel(format, type) * 2;
2541
2542 void* p = mmap(nullptr, size, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
2543 if (p != MAP_FAILED) {
2544 willSucceed = true;
2545 munmap(p, size);
2546 }
2547
2548 return willSucceed;
2549 }
2550 #endif // MOZ_WIDGET_ANDROID
2551
fTexImage2D(GLenum target,GLint level,GLint internalformat,GLsizei width,GLsizei height,GLint border,GLenum format,GLenum type,const GLvoid * pixels)2552 void GLContext::fTexImage2D(GLenum target, GLint level, GLint internalformat,
2553 GLsizei width, GLsizei height, GLint border,
2554 GLenum format, GLenum type, const GLvoid* pixels) {
2555 if (!IsTextureSizeSafeToPassToDriver(target, width, height)) {
2556 // pass wrong values to cause the GL to generate GL_INVALID_VALUE.
2557 // See bug 737182 and the comment in IsTextureSizeSafeToPassToDriver.
2558 level = -1;
2559 width = -1;
2560 height = -1;
2561 border = -1;
2562 }
2563 #if MOZ_WIDGET_ANDROID
2564 if (mTextureAllocCrashesOnMapFailure) {
2565 // We have no way of knowing whether this texture already has
2566 // storage allocated for it, and therefore whether this check
2567 // is necessary. We must therefore assume it does not and
2568 // always perform the check.
2569 if (!WillTextureMapSucceed(width, height, internalformat, type)) {
2570 return;
2571 }
2572 }
2573 #endif
2574 raw_fTexImage2D(target, level, internalformat, width, height, border, format,
2575 type, pixels);
2576 }
2577
GetDrawFB()2578 GLuint GLContext::GetDrawFB() {
2579 if (mScreen) return mScreen->GetDrawFB();
2580
2581 GLuint ret = 0;
2582 GetUIntegerv(LOCAL_GL_DRAW_FRAMEBUFFER_BINDING_EXT, &ret);
2583 return ret;
2584 }
2585
GetReadFB()2586 GLuint GLContext::GetReadFB() {
2587 if (mScreen) return mScreen->GetReadFB();
2588
2589 GLenum bindEnum = IsSupported(GLFeature::split_framebuffer)
2590 ? LOCAL_GL_READ_FRAMEBUFFER_BINDING_EXT
2591 : LOCAL_GL_FRAMEBUFFER_BINDING;
2592
2593 GLuint ret = 0;
2594 GetUIntegerv(bindEnum, &ret);
2595 return ret;
2596 }
2597
GetFB()2598 GLuint GLContext::GetFB() {
2599 if (mScreen) {
2600 // This has a very important extra assert that checks that we're
2601 // not accidentally ignoring a situation where the draw and read
2602 // FBs differ.
2603 return mScreen->GetFB();
2604 }
2605
2606 GLuint ret = 0;
2607 GetUIntegerv(LOCAL_GL_FRAMEBUFFER_BINDING, &ret);
2608 return ret;
2609 }
2610
InitOffscreen(const gfx::IntSize & size,const SurfaceCaps & caps)2611 bool GLContext::InitOffscreen(const gfx::IntSize& size,
2612 const SurfaceCaps& caps) {
2613 if (!CreateScreenBuffer(size, caps)) return false;
2614
2615 if (!MakeCurrent()) {
2616 return false;
2617 }
2618 fBindFramebuffer(LOCAL_GL_FRAMEBUFFER, 0);
2619 fScissor(0, 0, size.width, size.height);
2620 fViewport(0, 0, size.width, size.height);
2621
2622 mCaps = mScreen->mCaps;
2623 MOZ_ASSERT(!mCaps.any);
2624
2625 return true;
2626 }
2627
IsDrawingToDefaultFramebuffer()2628 bool GLContext::IsDrawingToDefaultFramebuffer() {
2629 return Screen()->IsDrawFramebufferDefault();
2630 }
2631
CreateTexture(GLContext * aGL,GLenum aInternalFormat,GLenum aFormat,GLenum aType,const gfx::IntSize & aSize,bool linear)2632 GLuint CreateTexture(GLContext* aGL, GLenum aInternalFormat, GLenum aFormat,
2633 GLenum aType, const gfx::IntSize& aSize, bool linear) {
2634 GLuint tex = 0;
2635 aGL->fGenTextures(1, &tex);
2636 ScopedBindTexture autoTex(aGL, tex);
2637
2638 aGL->fTexParameteri(LOCAL_GL_TEXTURE_2D, LOCAL_GL_TEXTURE_MIN_FILTER,
2639 linear ? LOCAL_GL_LINEAR : LOCAL_GL_NEAREST);
2640 aGL->fTexParameteri(LOCAL_GL_TEXTURE_2D, LOCAL_GL_TEXTURE_MAG_FILTER,
2641 linear ? LOCAL_GL_LINEAR : LOCAL_GL_NEAREST);
2642 aGL->fTexParameteri(LOCAL_GL_TEXTURE_2D, LOCAL_GL_TEXTURE_WRAP_S,
2643 LOCAL_GL_CLAMP_TO_EDGE);
2644 aGL->fTexParameteri(LOCAL_GL_TEXTURE_2D, LOCAL_GL_TEXTURE_WRAP_T,
2645 LOCAL_GL_CLAMP_TO_EDGE);
2646
2647 aGL->fTexImage2D(LOCAL_GL_TEXTURE_2D, 0, aInternalFormat, aSize.width,
2648 aSize.height, 0, aFormat, aType, nullptr);
2649
2650 return tex;
2651 }
2652
CreateTextureForOffscreen(GLContext * aGL,const GLFormats & aFormats,const gfx::IntSize & aSize)2653 GLuint CreateTextureForOffscreen(GLContext* aGL, const GLFormats& aFormats,
2654 const gfx::IntSize& aSize) {
2655 MOZ_ASSERT(aFormats.color_texInternalFormat);
2656 MOZ_ASSERT(aFormats.color_texFormat);
2657 MOZ_ASSERT(aFormats.color_texType);
2658
2659 GLenum internalFormat = aFormats.color_texInternalFormat;
2660 GLenum unpackFormat = aFormats.color_texFormat;
2661 GLenum unpackType = aFormats.color_texType;
2662 if (aGL->IsANGLE()) {
2663 MOZ_ASSERT(internalFormat == LOCAL_GL_RGBA);
2664 MOZ_ASSERT(unpackFormat == LOCAL_GL_RGBA);
2665 MOZ_ASSERT(unpackType == LOCAL_GL_UNSIGNED_BYTE);
2666 internalFormat = LOCAL_GL_BGRA_EXT;
2667 unpackFormat = LOCAL_GL_BGRA_EXT;
2668 }
2669
2670 return CreateTexture(aGL, internalFormat, unpackFormat, unpackType, aSize);
2671 }
2672
GetBytesPerTexel(GLenum format,GLenum type)2673 uint32_t GetBytesPerTexel(GLenum format, GLenum type) {
2674 // If there is no defined format or type, we're not taking up any memory
2675 if (!format || !type) {
2676 return 0;
2677 }
2678
2679 if (format == LOCAL_GL_DEPTH_COMPONENT) {
2680 if (type == LOCAL_GL_UNSIGNED_SHORT)
2681 return 2;
2682 else if (type == LOCAL_GL_UNSIGNED_INT)
2683 return 4;
2684 } else if (format == LOCAL_GL_DEPTH_STENCIL) {
2685 if (type == LOCAL_GL_UNSIGNED_INT_24_8_EXT) return 4;
2686 }
2687
2688 if (type == LOCAL_GL_UNSIGNED_BYTE || type == LOCAL_GL_FLOAT ||
2689 type == LOCAL_GL_UNSIGNED_INT_8_8_8_8_REV) {
2690 uint32_t multiplier = type == LOCAL_GL_UNSIGNED_BYTE ? 1 : 4;
2691 switch (format) {
2692 case LOCAL_GL_ALPHA:
2693 case LOCAL_GL_LUMINANCE:
2694 return 1 * multiplier;
2695 case LOCAL_GL_LUMINANCE_ALPHA:
2696 return 2 * multiplier;
2697 case LOCAL_GL_RGB:
2698 return 3 * multiplier;
2699 case LOCAL_GL_RGBA:
2700 case LOCAL_GL_BGRA_EXT:
2701 return 4 * multiplier;
2702 default:
2703 break;
2704 }
2705 } else if (type == LOCAL_GL_UNSIGNED_SHORT_4_4_4_4 ||
2706 type == LOCAL_GL_UNSIGNED_SHORT_5_5_5_1 ||
2707 type == LOCAL_GL_UNSIGNED_SHORT_5_6_5 ||
2708 type == LOCAL_GL_UNSIGNED_SHORT) {
2709 return 2;
2710 }
2711
2712 gfxCriticalError() << "Unknown texture type " << type << " or format "
2713 << format;
2714 return 0;
2715 }
2716
MakeCurrent(bool aForce) const2717 bool GLContext::MakeCurrent(bool aForce) const {
2718 if (MOZ_UNLIKELY(IsDestroyed())) return false;
2719
2720 if (MOZ_LIKELY(!aForce)) {
2721 bool isCurrent;
2722 if (mUseTLSIsCurrent) {
2723 isCurrent = (sCurrentContext.get() == reinterpret_cast<uintptr_t>(this));
2724 } else {
2725 isCurrent = IsCurrentImpl();
2726 }
2727 if (MOZ_LIKELY(isCurrent)) {
2728 MOZ_ASSERT(IsCurrentImpl());
2729 return true;
2730 }
2731 }
2732
2733 if (!MakeCurrentImpl()) return false;
2734
2735 sCurrentContext.set(reinterpret_cast<uintptr_t>(this));
2736 return true;
2737 }
2738
ResetSyncCallCount(const char * resetReason) const2739 void GLContext::ResetSyncCallCount(const char* resetReason) const {
2740 if (ShouldSpew()) {
2741 printf_stderr("On %s, mSyncGLCallCount = %" PRIu64 "\n", resetReason,
2742 mSyncGLCallCount);
2743 }
2744
2745 mSyncGLCallCount = 0;
2746 }
2747
2748 // --
2749
BeforeGLCall_Debug(const char * const funcName) const2750 void GLContext::BeforeGLCall_Debug(const char* const funcName) const {
2751 MOZ_ASSERT(mDebugFlags);
2752
2753 FlushErrors();
2754
2755 if (mDebugFlags & DebugFlagTrace) {
2756 printf_stderr("[gl:%p] > %s\n", this, funcName);
2757 }
2758 }
2759
AfterGLCall_Debug(const char * const funcName) const2760 void GLContext::AfterGLCall_Debug(const char* const funcName) const {
2761 MOZ_ASSERT(mDebugFlags);
2762
2763 // calling fFinish() immediately after every GL call makes sure that if this
2764 // GL command crashes, the stack trace will actually point to it. Otherwise,
2765 // OpenGL being an asynchronous API, stack traces tend to be meaningless
2766 mSymbols.fFinish();
2767 GLenum err = FlushErrors();
2768
2769 if (mDebugFlags & DebugFlagTrace) {
2770 printf_stderr("[gl:%p] < %s [%s (0x%04x)]\n", this, funcName,
2771 GLErrorToString(err), err);
2772 }
2773
2774 if (err != LOCAL_GL_NO_ERROR && !mLocalErrorScopeStack.size()) {
2775 printf_stderr(
2776 "[gl:%p] %s: Generated unexpected %s error."
2777 " (0x%04x)\n",
2778 this, funcName, GLErrorToString(err), err);
2779
2780 if (mDebugFlags & DebugFlagAbortOnError) {
2781 MOZ_CRASH(
2782 "Unexpected error with MOZ_GL_DEBUG_ABORT_ON_ERROR. (Run"
2783 " with MOZ_GL_DEBUG_ABORT_ON_ERROR=0 to disable)");
2784 }
2785 }
2786 }
2787
OnImplicitMakeCurrentFailure(const char * const funcName)2788 /*static*/ void GLContext::OnImplicitMakeCurrentFailure(
2789 const char* const funcName) {
2790 gfxCriticalError() << "Ignoring call to " << funcName << " with failed"
2791 << " mImplicitMakeCurrent.";
2792 }
2793
2794 } /* namespace gl */
2795 } /* namespace mozilla */
2796