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