Bug 1022205 - disable sync fence on AdrenoTM200 r=jgilbert
[gecko.git] / gfx / gl / GLContext.cpp
blobba9d4a3762239d8d1ea1ca55be670a1fefea01e0
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/. */
7 #include <algorithm>
8 #include <stdio.h>
9 #include <string.h>
10 #include <ctype.h>
12 #include "GLContext.h"
13 #include "GLBlitHelper.h"
14 #include "GLBlitTextureImageHelper.h"
15 #include "GLReadTexImageHelper.h"
17 #include "gfxCrashReporterUtils.h"
18 #include "gfxUtils.h"
19 #include "GLContextProvider.h"
20 #include "GLTextureImage.h"
21 #include "nsPrintfCString.h"
22 #include "nsThreadUtils.h"
23 #include "prenv.h"
24 #include "prlink.h"
25 #include "ScopedGLHelpers.h"
26 #include "SharedSurfaceGL.h"
27 #include "SurfaceStream.h"
28 #include "GfxTexturesReporter.h"
29 #include "TextureGarbageBin.h"
30 #include "gfx2DGlue.h"
31 #include "gfxPrefs.h"
33 #include "OGLShaderProgram.h" // for ShaderProgramType
35 #include "mozilla/DebugOnly.h"
37 #ifdef XP_MACOSX
38 #include <CoreServices/CoreServices.h>
39 #include "gfxColor.h"
40 #endif
42 #if defined(MOZ_WIDGET_COCOA)
43 #include "nsCocoaFeatures.h"
44 #endif
46 namespace mozilla {
47 namespace gl {
49 using namespace mozilla::gfx;
50 using namespace mozilla::layers;
52 #ifdef DEBUG
53 unsigned GLContext::sCurrentGLContextTLS = -1;
54 #endif
56 uint32_t GLContext::sDebugMode = 0;
59 #define MAX_SYMBOL_LENGTH 128
60 #define MAX_SYMBOL_NAMES 5
62 // should match the order of GLExtensions, and be null-terminated.
63 static const char *sExtensionNames[] = {
64 "GL_EXT_framebuffer_object",
65 "GL_ARB_framebuffer_object",
66 "GL_ARB_texture_rectangle",
67 "GL_EXT_bgra",
68 "GL_EXT_texture_format_BGRA8888",
69 "GL_OES_depth24",
70 "GL_OES_depth32",
71 "GL_OES_stencil8",
72 "GL_OES_texture_npot",
73 "GL_IMG_texture_npot",
74 "GL_ARB_depth_texture",
75 "GL_OES_depth_texture",
76 "GL_OES_packed_depth_stencil",
77 "GL_IMG_read_format",
78 "GL_EXT_read_format_bgra",
79 "GL_APPLE_client_storage",
80 "GL_APPLE_texture_range",
81 "GL_ARB_texture_non_power_of_two",
82 "GL_ARB_pixel_buffer_object",
83 "GL_ARB_ES2_compatibility",
84 "GL_ARB_ES3_compatibility",
85 "GL_OES_texture_float",
86 "GL_OES_texture_float_linear",
87 "GL_ARB_texture_float",
88 "GL_OES_texture_half_float",
89 "GL_OES_texture_half_float_linear",
90 "GL_NV_half_float",
91 "GL_EXT_color_buffer_float",
92 "GL_EXT_color_buffer_half_float",
93 "GL_ARB_color_buffer_float",
94 "GL_EXT_unpack_subimage",
95 "GL_OES_standard_derivatives",
96 "GL_EXT_texture_filter_anisotropic",
97 "GL_EXT_texture_compression_s3tc",
98 "GL_EXT_texture_compression_dxt1",
99 "GL_ANGLE_texture_compression_dxt3",
100 "GL_ANGLE_texture_compression_dxt5",
101 "GL_AMD_compressed_ATC_texture",
102 "GL_IMG_texture_compression_pvrtc",
103 "GL_EXT_framebuffer_blit",
104 "GL_ANGLE_framebuffer_blit",
105 "GL_EXT_framebuffer_multisample",
106 "GL_ANGLE_framebuffer_multisample",
107 "GL_OES_rgb8_rgba8",
108 "GL_ARB_robustness",
109 "GL_EXT_robustness",
110 "GL_ARB_sync",
111 "GL_OES_EGL_image",
112 "GL_OES_EGL_sync",
113 "GL_OES_EGL_image_external",
114 "GL_EXT_packed_depth_stencil",
115 "GL_OES_element_index_uint",
116 "GL_OES_vertex_array_object",
117 "GL_ARB_vertex_array_object",
118 "GL_APPLE_vertex_array_object",
119 "GL_ARB_draw_buffers",
120 "GL_EXT_draw_buffers",
121 "GL_EXT_gpu_shader4",
122 "GL_EXT_blend_minmax",
123 "GL_ARB_draw_instanced",
124 "GL_EXT_draw_instanced",
125 "GL_NV_draw_instanced",
126 "GL_ARB_instanced_arrays",
127 "GL_NV_instanced_arrays",
128 "GL_ANGLE_instanced_arrays",
129 "GL_EXT_occlusion_query_boolean",
130 "GL_ARB_occlusion_query2",
131 "GL_EXT_transform_feedback",
132 "GL_NV_transform_feedback",
133 "GL_ANGLE_depth_texture",
134 "GL_EXT_sRGB",
135 "GL_EXT_texture_sRGB",
136 "GL_ARB_framebuffer_sRGB",
137 "GL_EXT_framebuffer_sRGB",
138 "GL_KHR_debug",
139 "GL_ARB_half_float_pixel",
140 "GL_EXT_frag_depth",
141 "GL_OES_compressed_ETC1_RGB8_texture",
142 "GL_EXT_draw_range_elements",
143 nullptr
146 static bool
147 ParseGLVersion(GLContext* gl, unsigned int* version)
149 GLenum error = gl->fGetError();
150 if (error != LOCAL_GL_NO_ERROR) {
151 MOZ_ASSERT(false, "An OpenGL error has been triggered before.");
152 return false;
156 * B2G emulator bug work around: The emulator implements OpenGL ES 2.0 on
157 * OpenGL 3.2. The bug is that GetIntegerv(LOCAL_GL_{MAJOR,MINOR}_VERSION)
158 * returns OpenGL 3.2 instead of generating an error.
160 if (!gl->IsGLES())
163 * OpenGL 3.1 and OpenGL ES 3.0 both introduce GL_{MAJOR,MINOR}_VERSION
164 * with GetIntegerv. So we first try those constants even though we
165 * might not have an OpenGL context supporting them, has this is a
166 * better way than parsing GL_VERSION.
168 GLint majorVersion = 0;
169 GLint minorVersion = 0;
171 gl->fGetIntegerv(LOCAL_GL_MAJOR_VERSION, &majorVersion);
172 gl->fGetIntegerv(LOCAL_GL_MINOR_VERSION, &minorVersion);
174 // If it's not an OpenGL (ES) 3.0 context, we will have an error
175 error = gl->fGetError();
176 if (error == LOCAL_GL_NO_ERROR &&
177 majorVersion > 0 &&
178 minorVersion >= 0)
180 *version = majorVersion * 100 + minorVersion * 10;
181 return true;
186 * We were not able to use GL_{MAJOR,MINOR}_VERSION, so we parse
187 * GL_VERSION.
190 * OpenGL 2.x, 3.x, 4.x specifications:
191 * The VERSION and SHADING_LANGUAGE_VERSION strings are laid out as follows:
193 * <version number><space><vendor-specific information>
195 * The version number is either of the form major_number.minor_number or
196 * major_number.minor_number.release_number, where the numbers all have
197 * one or more digits.
200 * OpenGL ES 2.0, 3.0 specifications:
201 * The VERSION string is laid out as follows:
203 * "OpenGL ES N.M vendor-specific information"
205 * The version number is either of the form major_number.minor_number or
206 * major_number.minor_number.release_number, where the numbers all have
207 * one or more digits.
210 * Note:
211 * We don't care about release_number.
213 const char* versionString = (const char*)gl->fGetString(LOCAL_GL_VERSION);
215 error = gl->fGetError();
216 if (error != LOCAL_GL_NO_ERROR) {
217 MOZ_ASSERT(false, "glGetString(GL_VERSION) has generated an error");
218 return false;
219 } else if (!versionString) {
220 MOZ_ASSERT(false, "glGetString(GL_VERSION) has returned 0");
221 return false;
224 const char kGLESVersionPrefix[] = "OpenGL ES ";
225 if (strncmp(versionString, kGLESVersionPrefix, strlen(kGLESVersionPrefix)) == 0) {
226 versionString += strlen(kGLESVersionPrefix);
229 const char* itr = versionString;
230 char* end = nullptr;
231 int majorVersion = (int)strtol(itr, &end, 10);
233 if (!end) {
234 MOZ_ASSERT(false, "Failed to parse the GL major version number.");
235 return false;
236 } else if (*end != '.') {
237 MOZ_ASSERT(false, "Failed to parse GL's major-minor version number separator.");
238 return false;
241 // we skip the '.' between the major and the minor version
242 itr = end + 1;
244 end = nullptr;
246 int minorVersion = (int)strtol(itr, &end, 10);
247 if (!end) {
248 MOZ_ASSERT(false, "Failed to parse GL's minor version number.");
249 return false;
252 if (majorVersion <= 0 || majorVersion >= 100) {
253 MOZ_ASSERT(false, "Invalid major version.");
254 return false;
255 } else if (minorVersion < 0 || minorVersion >= 10) {
256 MOZ_ASSERT(false, "Invalid minor version.");
257 return false;
260 *version = (unsigned int)(majorVersion * 100 + minorVersion * 10);
261 return true;
264 GLContext::GLContext(const SurfaceCaps& caps,
265 GLContext* sharedContext,
266 bool isOffscreen)
267 : mInitialized(false),
268 mIsOffscreen(isOffscreen),
269 mContextLost(false),
270 mVersion(0),
271 mProfile(ContextProfile::Unknown),
272 mVendor(GLVendor::Other),
273 mRenderer(GLRenderer::Other),
274 mHasRobustness(false),
275 #ifdef DEBUG
276 mGLError(LOCAL_GL_NO_ERROR),
277 #endif
278 mSharedContext(sharedContext),
279 mCaps(caps),
280 mScreen(nullptr),
281 mLockedSurface(nullptr),
282 mMaxTextureSize(0),
283 mMaxCubeMapTextureSize(0),
284 mMaxTextureImageSize(0),
285 mMaxRenderbufferSize(0),
286 mNeedsTextureSizeChecks(false),
287 mWorkAroundDriverBugs(true)
289 mOwningThreadId = PlatformThread::CurrentId();
292 GLContext::~GLContext() {
293 NS_ASSERTION(IsDestroyed(), "GLContext implementation must call MarkDestroyed in destructor!");
294 #ifdef DEBUG
295 if (mSharedContext) {
296 GLContext *tip = mSharedContext;
297 while (tip->mSharedContext)
298 tip = tip->mSharedContext;
299 tip->SharedContextDestroyed(this);
300 tip->ReportOutstandingNames();
301 } else {
302 ReportOutstandingNames();
304 #endif
307 /*static*/ void
308 GLContext::StaticDebugCallback(GLenum source,
309 GLenum type,
310 GLuint id,
311 GLenum severity,
312 GLsizei length,
313 const GLchar* message,
314 const GLvoid* userParam)
316 GLContext* gl = (GLContext*)userParam;
317 gl->DebugCallback(source, type, id, severity, length, message);
320 bool
321 GLContext::InitWithPrefix(const char *prefix, bool trygl)
323 ScopedGfxFeatureReporter reporter("GL Context");
325 if (mInitialized) {
326 reporter.SetSuccessful();
327 return true;
330 mWorkAroundDriverBugs = gfxPrefs::WorkAroundDriverBugs();
332 SymLoadStruct symbols[] = {
333 { (PRFuncPtr*) &mSymbols.fActiveTexture, { "ActiveTexture", "ActiveTextureARB", nullptr } },
334 { (PRFuncPtr*) &mSymbols.fAttachShader, { "AttachShader", "AttachShaderARB", nullptr } },
335 { (PRFuncPtr*) &mSymbols.fBindAttribLocation, { "BindAttribLocation", "BindAttribLocationARB", nullptr } },
336 { (PRFuncPtr*) &mSymbols.fBindBuffer, { "BindBuffer", "BindBufferARB", nullptr } },
337 { (PRFuncPtr*) &mSymbols.fBindTexture, { "BindTexture", "BindTextureARB", nullptr } },
338 { (PRFuncPtr*) &mSymbols.fBlendColor, { "BlendColor", nullptr } },
339 { (PRFuncPtr*) &mSymbols.fBlendEquation, { "BlendEquation", nullptr } },
340 { (PRFuncPtr*) &mSymbols.fBlendEquationSeparate, { "BlendEquationSeparate", "BlendEquationSeparateEXT", nullptr } },
341 { (PRFuncPtr*) &mSymbols.fBlendFunc, { "BlendFunc", nullptr } },
342 { (PRFuncPtr*) &mSymbols.fBlendFuncSeparate, { "BlendFuncSeparate", "BlendFuncSeparateEXT", nullptr } },
343 { (PRFuncPtr*) &mSymbols.fBufferData, { "BufferData", nullptr } },
344 { (PRFuncPtr*) &mSymbols.fBufferSubData, { "BufferSubData", nullptr } },
345 { (PRFuncPtr*) &mSymbols.fClear, { "Clear", nullptr } },
346 { (PRFuncPtr*) &mSymbols.fClearColor, { "ClearColor", nullptr } },
347 { (PRFuncPtr*) &mSymbols.fClearStencil, { "ClearStencil", nullptr } },
348 { (PRFuncPtr*) &mSymbols.fColorMask, { "ColorMask", nullptr } },
349 { (PRFuncPtr*) &mSymbols.fCompressedTexImage2D, {"CompressedTexImage2D", nullptr} },
350 { (PRFuncPtr*) &mSymbols.fCompressedTexSubImage2D, {"CompressedTexSubImage2D", nullptr} },
351 { (PRFuncPtr*) &mSymbols.fCullFace, { "CullFace", nullptr } },
352 { (PRFuncPtr*) &mSymbols.fDetachShader, { "DetachShader", "DetachShaderARB", nullptr } },
353 { (PRFuncPtr*) &mSymbols.fDepthFunc, { "DepthFunc", nullptr } },
354 { (PRFuncPtr*) &mSymbols.fDepthMask, { "DepthMask", nullptr } },
355 { (PRFuncPtr*) &mSymbols.fDisable, { "Disable", nullptr } },
356 { (PRFuncPtr*) &mSymbols.fDisableVertexAttribArray, { "DisableVertexAttribArray", "DisableVertexAttribArrayARB", nullptr } },
357 { (PRFuncPtr*) &mSymbols.fDrawArrays, { "DrawArrays", nullptr } },
358 { (PRFuncPtr*) &mSymbols.fDrawElements, { "DrawElements", nullptr } },
359 { (PRFuncPtr*) &mSymbols.fEnable, { "Enable", nullptr } },
360 { (PRFuncPtr*) &mSymbols.fEnableVertexAttribArray, { "EnableVertexAttribArray", "EnableVertexAttribArrayARB", nullptr } },
361 { (PRFuncPtr*) &mSymbols.fFinish, { "Finish", nullptr } },
362 { (PRFuncPtr*) &mSymbols.fFlush, { "Flush", nullptr } },
363 { (PRFuncPtr*) &mSymbols.fFrontFace, { "FrontFace", nullptr } },
364 { (PRFuncPtr*) &mSymbols.fGetActiveAttrib, { "GetActiveAttrib", "GetActiveAttribARB", nullptr } },
365 { (PRFuncPtr*) &mSymbols.fGetActiveUniform, { "GetActiveUniform", "GetActiveUniformARB", nullptr } },
366 { (PRFuncPtr*) &mSymbols.fGetAttachedShaders, { "GetAttachedShaders", "GetAttachedShadersARB", nullptr } },
367 { (PRFuncPtr*) &mSymbols.fGetAttribLocation, { "GetAttribLocation", "GetAttribLocationARB", nullptr } },
368 { (PRFuncPtr*) &mSymbols.fGetIntegerv, { "GetIntegerv", nullptr } },
369 { (PRFuncPtr*) &mSymbols.fGetFloatv, { "GetFloatv", nullptr } },
370 { (PRFuncPtr*) &mSymbols.fGetBooleanv, { "GetBooleanv", nullptr } },
371 { (PRFuncPtr*) &mSymbols.fGetBufferParameteriv, { "GetBufferParameteriv", "GetBufferParameterivARB", nullptr } },
372 { (PRFuncPtr*) &mSymbols.fGetError, { "GetError", nullptr } },
373 { (PRFuncPtr*) &mSymbols.fGetProgramiv, { "GetProgramiv", "GetProgramivARB", nullptr } },
374 { (PRFuncPtr*) &mSymbols.fGetProgramInfoLog, { "GetProgramInfoLog", "GetProgramInfoLogARB", nullptr } },
375 { (PRFuncPtr*) &mSymbols.fTexParameteri, { "TexParameteri", nullptr } },
376 { (PRFuncPtr*) &mSymbols.fTexParameteriv, { "TexParameteriv", nullptr } },
377 { (PRFuncPtr*) &mSymbols.fTexParameterf, { "TexParameterf", nullptr } },
378 { (PRFuncPtr*) &mSymbols.fGetString, { "GetString", nullptr } },
379 { (PRFuncPtr*) &mSymbols.fGetTexParameterfv, { "GetTexParameterfv", nullptr } },
380 { (PRFuncPtr*) &mSymbols.fGetTexParameteriv, { "GetTexParameteriv", nullptr } },
381 { (PRFuncPtr*) &mSymbols.fGetUniformfv, { "GetUniformfv", "GetUniformfvARB", nullptr } },
382 { (PRFuncPtr*) &mSymbols.fGetUniformiv, { "GetUniformiv", "GetUniformivARB", nullptr } },
383 { (PRFuncPtr*) &mSymbols.fGetUniformLocation, { "GetUniformLocation", "GetUniformLocationARB", nullptr } },
384 { (PRFuncPtr*) &mSymbols.fGetVertexAttribfv, { "GetVertexAttribfv", "GetVertexAttribfvARB", nullptr } },
385 { (PRFuncPtr*) &mSymbols.fGetVertexAttribiv, { "GetVertexAttribiv", "GetVertexAttribivARB", nullptr } },
386 { (PRFuncPtr*) &mSymbols.fGetVertexAttribPointerv, { "GetVertexAttribPointerv", nullptr } },
387 { (PRFuncPtr*) &mSymbols.fHint, { "Hint", nullptr } },
388 { (PRFuncPtr*) &mSymbols.fIsBuffer, { "IsBuffer", "IsBufferARB", nullptr } },
389 { (PRFuncPtr*) &mSymbols.fIsEnabled, { "IsEnabled", nullptr } },
390 { (PRFuncPtr*) &mSymbols.fIsProgram, { "IsProgram", "IsProgramARB", nullptr } },
391 { (PRFuncPtr*) &mSymbols.fIsShader, { "IsShader", "IsShaderARB", nullptr } },
392 { (PRFuncPtr*) &mSymbols.fIsTexture, { "IsTexture", "IsTextureARB", nullptr } },
393 { (PRFuncPtr*) &mSymbols.fLineWidth, { "LineWidth", nullptr } },
394 { (PRFuncPtr*) &mSymbols.fLinkProgram, { "LinkProgram", "LinkProgramARB", nullptr } },
395 { (PRFuncPtr*) &mSymbols.fPixelStorei, { "PixelStorei", nullptr } },
396 { (PRFuncPtr*) &mSymbols.fPolygonOffset, { "PolygonOffset", nullptr } },
397 { (PRFuncPtr*) &mSymbols.fReadPixels, { "ReadPixels", nullptr } },
398 { (PRFuncPtr*) &mSymbols.fSampleCoverage, { "SampleCoverage", nullptr } },
399 { (PRFuncPtr*) &mSymbols.fScissor, { "Scissor", nullptr } },
400 { (PRFuncPtr*) &mSymbols.fStencilFunc, { "StencilFunc", nullptr } },
401 { (PRFuncPtr*) &mSymbols.fStencilFuncSeparate, { "StencilFuncSeparate", "StencilFuncSeparateEXT", nullptr } },
402 { (PRFuncPtr*) &mSymbols.fStencilMask, { "StencilMask", nullptr } },
403 { (PRFuncPtr*) &mSymbols.fStencilMaskSeparate, { "StencilMaskSeparate", "StencilMaskSeparateEXT", nullptr } },
404 { (PRFuncPtr*) &mSymbols.fStencilOp, { "StencilOp", nullptr } },
405 { (PRFuncPtr*) &mSymbols.fStencilOpSeparate, { "StencilOpSeparate", "StencilOpSeparateEXT", nullptr } },
406 { (PRFuncPtr*) &mSymbols.fTexImage2D, { "TexImage2D", nullptr } },
407 { (PRFuncPtr*) &mSymbols.fTexSubImage2D, { "TexSubImage2D", nullptr } },
408 { (PRFuncPtr*) &mSymbols.fUniform1f, { "Uniform1f", nullptr } },
409 { (PRFuncPtr*) &mSymbols.fUniform1fv, { "Uniform1fv", nullptr } },
410 { (PRFuncPtr*) &mSymbols.fUniform1i, { "Uniform1i", nullptr } },
411 { (PRFuncPtr*) &mSymbols.fUniform1iv, { "Uniform1iv", nullptr } },
412 { (PRFuncPtr*) &mSymbols.fUniform2f, { "Uniform2f", nullptr } },
413 { (PRFuncPtr*) &mSymbols.fUniform2fv, { "Uniform2fv", nullptr } },
414 { (PRFuncPtr*) &mSymbols.fUniform2i, { "Uniform2i", nullptr } },
415 { (PRFuncPtr*) &mSymbols.fUniform2iv, { "Uniform2iv", nullptr } },
416 { (PRFuncPtr*) &mSymbols.fUniform3f, { "Uniform3f", nullptr } },
417 { (PRFuncPtr*) &mSymbols.fUniform3fv, { "Uniform3fv", nullptr } },
418 { (PRFuncPtr*) &mSymbols.fUniform3i, { "Uniform3i", nullptr } },
419 { (PRFuncPtr*) &mSymbols.fUniform3iv, { "Uniform3iv", nullptr } },
420 { (PRFuncPtr*) &mSymbols.fUniform4f, { "Uniform4f", nullptr } },
421 { (PRFuncPtr*) &mSymbols.fUniform4fv, { "Uniform4fv", nullptr } },
422 { (PRFuncPtr*) &mSymbols.fUniform4i, { "Uniform4i", nullptr } },
423 { (PRFuncPtr*) &mSymbols.fUniform4iv, { "Uniform4iv", nullptr } },
424 { (PRFuncPtr*) &mSymbols.fUniformMatrix2fv, { "UniformMatrix2fv", nullptr } },
425 { (PRFuncPtr*) &mSymbols.fUniformMatrix3fv, { "UniformMatrix3fv", nullptr } },
426 { (PRFuncPtr*) &mSymbols.fUniformMatrix4fv, { "UniformMatrix4fv", nullptr } },
427 { (PRFuncPtr*) &mSymbols.fUseProgram, { "UseProgram", nullptr } },
428 { (PRFuncPtr*) &mSymbols.fValidateProgram, { "ValidateProgram", nullptr } },
429 { (PRFuncPtr*) &mSymbols.fVertexAttribPointer, { "VertexAttribPointer", nullptr } },
430 { (PRFuncPtr*) &mSymbols.fVertexAttrib1f, { "VertexAttrib1f", nullptr } },
431 { (PRFuncPtr*) &mSymbols.fVertexAttrib2f, { "VertexAttrib2f", nullptr } },
432 { (PRFuncPtr*) &mSymbols.fVertexAttrib3f, { "VertexAttrib3f", nullptr } },
433 { (PRFuncPtr*) &mSymbols.fVertexAttrib4f, { "VertexAttrib4f", nullptr } },
434 { (PRFuncPtr*) &mSymbols.fVertexAttrib1fv, { "VertexAttrib1fv", nullptr } },
435 { (PRFuncPtr*) &mSymbols.fVertexAttrib2fv, { "VertexAttrib2fv", nullptr } },
436 { (PRFuncPtr*) &mSymbols.fVertexAttrib3fv, { "VertexAttrib3fv", nullptr } },
437 { (PRFuncPtr*) &mSymbols.fVertexAttrib4fv, { "VertexAttrib4fv", nullptr } },
438 { (PRFuncPtr*) &mSymbols.fViewport, { "Viewport", nullptr } },
439 { (PRFuncPtr*) &mSymbols.fCompileShader, { "CompileShader", nullptr } },
440 { (PRFuncPtr*) &mSymbols.fCopyTexImage2D, { "CopyTexImage2D", nullptr } },
441 { (PRFuncPtr*) &mSymbols.fCopyTexSubImage2D, { "CopyTexSubImage2D", nullptr } },
442 { (PRFuncPtr*) &mSymbols.fGetShaderiv, { "GetShaderiv", nullptr } },
443 { (PRFuncPtr*) &mSymbols.fGetShaderInfoLog, { "GetShaderInfoLog", nullptr } },
444 { (PRFuncPtr*) &mSymbols.fGetShaderSource, { "GetShaderSource", nullptr } },
445 { (PRFuncPtr*) &mSymbols.fShaderSource, { "ShaderSource", nullptr } },
446 { (PRFuncPtr*) &mSymbols.fVertexAttribPointer, { "VertexAttribPointer", nullptr } },
447 { (PRFuncPtr*) &mSymbols.fBindFramebuffer, { "BindFramebuffer", "BindFramebufferEXT", nullptr } },
448 { (PRFuncPtr*) &mSymbols.fBindRenderbuffer, { "BindRenderbuffer", "BindRenderbufferEXT", nullptr } },
449 { (PRFuncPtr*) &mSymbols.fCheckFramebufferStatus, { "CheckFramebufferStatus", "CheckFramebufferStatusEXT", nullptr } },
450 { (PRFuncPtr*) &mSymbols.fFramebufferRenderbuffer, { "FramebufferRenderbuffer", "FramebufferRenderbufferEXT", nullptr } },
451 { (PRFuncPtr*) &mSymbols.fFramebufferTexture2D, { "FramebufferTexture2D", "FramebufferTexture2DEXT", nullptr } },
452 { (PRFuncPtr*) &mSymbols.fGenerateMipmap, { "GenerateMipmap", "GenerateMipmapEXT", nullptr } },
453 { (PRFuncPtr*) &mSymbols.fGetFramebufferAttachmentParameteriv, { "GetFramebufferAttachmentParameteriv", "GetFramebufferAttachmentParameterivEXT", nullptr } },
454 { (PRFuncPtr*) &mSymbols.fGetRenderbufferParameteriv, { "GetRenderbufferParameteriv", "GetRenderbufferParameterivEXT", nullptr } },
455 { (PRFuncPtr*) &mSymbols.fIsFramebuffer, { "IsFramebuffer", "IsFramebufferEXT", nullptr } },
456 { (PRFuncPtr*) &mSymbols.fIsRenderbuffer, { "IsRenderbuffer", "IsRenderbufferEXT", nullptr } },
457 { (PRFuncPtr*) &mSymbols.fRenderbufferStorage, { "RenderbufferStorage", "RenderbufferStorageEXT", nullptr } },
459 { (PRFuncPtr*) &mSymbols.fGenBuffers, { "GenBuffers", "GenBuffersARB", nullptr } },
460 { (PRFuncPtr*) &mSymbols.fGenTextures, { "GenTextures", nullptr } },
461 { (PRFuncPtr*) &mSymbols.fCreateProgram, { "CreateProgram", "CreateProgramARB", nullptr } },
462 { (PRFuncPtr*) &mSymbols.fCreateShader, { "CreateShader", "CreateShaderARB", nullptr } },
463 { (PRFuncPtr*) &mSymbols.fGenFramebuffers, { "GenFramebuffers", "GenFramebuffersEXT", nullptr } },
464 { (PRFuncPtr*) &mSymbols.fGenRenderbuffers, { "GenRenderbuffers", "GenRenderbuffersEXT", nullptr } },
466 { (PRFuncPtr*) &mSymbols.fDeleteBuffers, { "DeleteBuffers", "DeleteBuffersARB", nullptr } },
467 { (PRFuncPtr*) &mSymbols.fDeleteTextures, { "DeleteTextures", "DeleteTexturesARB", nullptr } },
468 { (PRFuncPtr*) &mSymbols.fDeleteProgram, { "DeleteProgram", "DeleteProgramARB", nullptr } },
469 { (PRFuncPtr*) &mSymbols.fDeleteShader, { "DeleteShader", "DeleteShaderARB", nullptr } },
470 { (PRFuncPtr*) &mSymbols.fDeleteFramebuffers, { "DeleteFramebuffers", "DeleteFramebuffersEXT", nullptr } },
471 { (PRFuncPtr*) &mSymbols.fDeleteRenderbuffers, { "DeleteRenderbuffers", "DeleteRenderbuffersEXT", nullptr } },
473 { nullptr, { nullptr } },
477 mInitialized = LoadSymbols(&symbols[0], trygl, prefix);
478 MakeCurrent();
479 if (mInitialized) {
480 unsigned int version = 0;
482 ParseGLVersion(this, &version);
484 #ifdef DEBUG
485 printf_stderr("OpenGL version detected: %u\n", version);
486 printf_stderr("OpenGL vendor: %s\n", fGetString(LOCAL_GL_VENDOR));
487 printf_stderr("OpenGL renderer: %s\n", fGetString(LOCAL_GL_RENDERER));
488 #endif
490 if (version >= mVersion) {
491 mVersion = version;
493 // Don't fail if version < mVersion, see bug 999445,
494 // Mac OSX 10.6/10.7 machines with Intel GPUs claim only OpenGL 1.4 but
495 // have all the GL2+ extensions that we need.
498 // Load OpenGL ES 2.0 symbols, or desktop if we aren't using ES 2.
499 if (mInitialized) {
500 if (IsGLES()) {
501 SymLoadStruct symbols_ES2[] = {
502 { (PRFuncPtr*) &mSymbols.fGetShaderPrecisionFormat, { "GetShaderPrecisionFormat", nullptr } },
503 { (PRFuncPtr*) &mSymbols.fClearDepthf, { "ClearDepthf", nullptr } },
504 { (PRFuncPtr*) &mSymbols.fDepthRangef, { "DepthRangef", nullptr } },
505 { nullptr, { nullptr } },
508 if (!LoadSymbols(&symbols_ES2[0], trygl, prefix)) {
509 NS_ERROR("OpenGL ES 2.0 supported, but symbols could not be loaded.");
510 mInitialized = false;
512 } else {
513 SymLoadStruct symbols_desktop[] = {
514 { (PRFuncPtr*) &mSymbols.fClearDepth, { "ClearDepth", nullptr } },
515 { (PRFuncPtr*) &mSymbols.fDepthRange, { "DepthRange", nullptr } },
516 { (PRFuncPtr*) &mSymbols.fReadBuffer, { "ReadBuffer", nullptr } },
517 { (PRFuncPtr*) &mSymbols.fMapBuffer, { "MapBuffer", nullptr } },
518 { (PRFuncPtr*) &mSymbols.fUnmapBuffer, { "UnmapBuffer", nullptr } },
519 { (PRFuncPtr*) &mSymbols.fPointParameterf, { "PointParameterf", nullptr } },
520 { (PRFuncPtr*) &mSymbols.fDrawBuffer, { "DrawBuffer", nullptr } },
521 // These functions are only used by Skia/GL in desktop mode.
522 // Other parts of Gecko should avoid using these
523 { (PRFuncPtr*) &mSymbols.fDrawBuffers, { "DrawBuffers", nullptr } },
524 { (PRFuncPtr*) &mSymbols.fClientActiveTexture, { "ClientActiveTexture", nullptr } },
525 { (PRFuncPtr*) &mSymbols.fDisableClientState, { "DisableClientState", nullptr } },
526 { (PRFuncPtr*) &mSymbols.fEnableClientState, { "EnableClientState", nullptr } },
527 { (PRFuncPtr*) &mSymbols.fLoadIdentity, { "LoadIdentity", nullptr } },
528 { (PRFuncPtr*) &mSymbols.fLoadMatrixf, { "LoadMatrixf", nullptr } },
529 { (PRFuncPtr*) &mSymbols.fMatrixMode, { "MatrixMode", nullptr } },
530 { (PRFuncPtr*) &mSymbols.fTexGeni, { "TexGeni", nullptr } },
531 { (PRFuncPtr*) &mSymbols.fTexGenf, { "TexGenf", nullptr } },
532 { (PRFuncPtr*) &mSymbols.fTexGenfv, { "TexGenfv", nullptr } },
533 { (PRFuncPtr*) &mSymbols.fVertexPointer, { "VertexPointer", nullptr } },
534 { nullptr, { nullptr } },
537 if (!LoadSymbols(&symbols_desktop[0], trygl, prefix)) {
538 NS_ERROR("Desktop symbols failed to load.");
539 mInitialized = false;
544 const char *glVendorString = nullptr;
545 const char *glRendererString = nullptr;
547 if (mInitialized) {
548 // The order of these strings must match up with the order of the enum
549 // defined in GLContext.h for vendor IDs
550 glVendorString = (const char *)fGetString(LOCAL_GL_VENDOR);
551 if (!glVendorString)
552 mInitialized = false;
554 const char *vendorMatchStrings[size_t(GLVendor::Other)] = {
555 "Intel",
556 "NVIDIA",
557 "ATI",
558 "Qualcomm",
559 "Imagination",
560 "nouveau",
561 "Vivante",
562 "VMware, Inc."
565 mVendor = GLVendor::Other;
566 for (size_t i = 0; i < size_t(GLVendor::Other); ++i) {
567 if (DoesStringMatch(glVendorString, vendorMatchStrings[i])) {
568 mVendor = GLVendor(i);
569 break;
573 // The order of these strings must match up with the order of the enum
574 // defined in GLContext.h for renderer IDs
575 glRendererString = (const char *)fGetString(LOCAL_GL_RENDERER);
576 if (!glRendererString)
577 mInitialized = false;
579 const char *rendererMatchStrings[size_t(GLRenderer::Other)] = {
580 "Adreno 200",
581 "Adreno 205",
582 "Adreno (TM) 200",
583 "Adreno (TM) 205",
584 "Adreno (TM) 320",
585 "PowerVR SGX 530",
586 "PowerVR SGX 540",
587 "NVIDIA Tegra",
588 "Android Emulator",
589 "Gallium 0.4 on llvmpipe",
590 "Intel HD Graphics 3000 OpenGL Engine",
593 mRenderer = GLRenderer::Other;
594 for (size_t i = 0; i < size_t(GLRenderer::Other); ++i) {
595 if (DoesStringMatch(glRendererString, rendererMatchStrings[i])) {
596 mRenderer = GLRenderer(i);
597 break;
603 #ifdef DEBUG
604 if (PR_GetEnv("MOZ_GL_DEBUG"))
605 sDebugMode |= DebugEnabled;
607 // enables extra verbose output, informing of the start and finish of every GL call.
608 // useful e.g. to record information to investigate graphics system crashes/lockups
609 if (PR_GetEnv("MOZ_GL_DEBUG_VERBOSE"))
610 sDebugMode |= DebugTrace;
612 // aborts on GL error. Can be useful to debug quicker code that is known not to generate any GL error in principle.
613 if (PR_GetEnv("MOZ_GL_DEBUG_ABORT_ON_ERROR"))
614 sDebugMode |= DebugAbortOnError;
615 #endif
617 if (mInitialized) {
618 #ifdef DEBUG
619 static bool firstRun = true;
620 if (firstRun && DebugMode()) {
621 const char *vendors[size_t(GLVendor::Other)] = {
622 "Intel",
623 "NVIDIA",
624 "ATI",
625 "Qualcomm"
628 MOZ_ASSERT(glVendorString);
629 if (mVendor < GLVendor::Other) {
630 printf_stderr("OpenGL vendor ('%s') recognized as: %s\n",
631 glVendorString, vendors[size_t(mVendor)]);
632 } else {
633 printf_stderr("OpenGL vendor ('%s') unrecognized\n", glVendorString);
636 firstRun = false;
637 #endif
639 InitExtensions();
640 InitFeatures();
642 // Disable extensions with partial or incorrect support.
643 if (WorkAroundDriverBugs()) {
644 if (Renderer() == GLRenderer::AdrenoTM320) {
645 MarkUnsupported(GLFeature::standard_derivatives);
648 if (Vendor() == GLVendor::Vivante) {
649 // bug 958256
650 MarkUnsupported(GLFeature::standard_derivatives);
653 if (Vendor() == GLVendor::Imagination &&
654 Renderer() == GLRenderer::SGX540) {
655 // Bug 980048
656 MarkExtensionUnsupported(OES_EGL_sync);
659 #ifdef XP_MACOSX
660 // The Mac Nvidia driver, for versions up to and including 10.8, don't seem
661 // to properly support this. See 814839
662 // this has been fixed in Mac OS X 10.9. See 907946
663 if (Vendor() == gl::GLVendor::NVIDIA &&
664 !nsCocoaFeatures::OnMavericksOrLater())
666 MarkUnsupported(GLFeature::depth_texture);
668 #endif
669 // ANGLE's divisor support is busted. (see bug 916816)
670 if (IsANGLE()) {
671 MarkUnsupported(GLFeature::instanced_arrays);
675 NS_ASSERTION(!IsExtensionSupported(GLContext::ARB_pixel_buffer_object) ||
676 (mSymbols.fMapBuffer && mSymbols.fUnmapBuffer),
677 "ARB_pixel_buffer_object supported without glMapBuffer/UnmapBuffer being available!");
679 if (SupportsRobustness()) {
680 mHasRobustness = false;
682 if (IsExtensionSupported(ARB_robustness)) {
683 SymLoadStruct robustnessSymbols[] = {
684 { (PRFuncPtr*) &mSymbols.fGetGraphicsResetStatus, { "GetGraphicsResetStatusARB", nullptr } },
685 { nullptr, { nullptr } },
688 if (!LoadSymbols(&robustnessSymbols[0], trygl, prefix)) {
689 NS_ERROR("GL supports ARB_robustness without supplying GetGraphicsResetStatusARB.");
691 mSymbols.fGetGraphicsResetStatus = nullptr;
692 } else {
693 mHasRobustness = true;
696 if (!IsExtensionSupported(ARB_robustness) &&
697 IsExtensionSupported(EXT_robustness)) {
698 SymLoadStruct robustnessSymbols[] = {
699 { (PRFuncPtr*) &mSymbols.fGetGraphicsResetStatus, { "GetGraphicsResetStatusEXT", nullptr } },
700 { nullptr, { nullptr } },
703 if (!LoadSymbols(&robustnessSymbols[0], trygl, prefix)) {
704 NS_ERROR("GL supports EXT_robustness without supplying GetGraphicsResetStatusEXT.");
706 mSymbols.fGetGraphicsResetStatus = nullptr;
707 } else {
708 mHasRobustness = true;
712 if (!mHasRobustness) {
713 MarkUnsupported(GLFeature::robustness);
717 // Check for aux symbols based on extensions
718 if (IsSupported(GLFeature::framebuffer_blit))
720 SymLoadStruct auxSymbols[] = {
722 (PRFuncPtr*) &mSymbols.fBlitFramebuffer,
724 "BlitFramebuffer",
725 "BlitFramebufferEXT",
726 "BlitFramebufferANGLE",
727 nullptr
730 { nullptr, { nullptr } },
732 if (!LoadSymbols(&auxSymbols[0], trygl, prefix)) {
733 NS_ERROR("GL supports framebuffer_blit without supplying glBlitFramebuffer");
735 MarkUnsupported(GLFeature::framebuffer_blit);
736 mSymbols.fBlitFramebuffer = nullptr;
740 if (IsSupported(GLFeature::framebuffer_multisample))
742 SymLoadStruct auxSymbols[] = {
744 (PRFuncPtr*) &mSymbols.fRenderbufferStorageMultisample,
746 "RenderbufferStorageMultisample",
747 "RenderbufferStorageMultisampleEXT",
748 "RenderbufferStorageMultisampleANGLE",
749 nullptr
752 { nullptr, { nullptr } },
754 if (!LoadSymbols(&auxSymbols[0], trygl, prefix)) {
755 NS_ERROR("GL supports framebuffer_multisample without supplying glRenderbufferStorageMultisample");
757 MarkUnsupported(GLFeature::framebuffer_multisample);
758 mSymbols.fRenderbufferStorageMultisample = nullptr;
762 if (IsExtensionSupported(ARB_sync)) {
763 SymLoadStruct syncSymbols[] = {
764 { (PRFuncPtr*) &mSymbols.fFenceSync, { "FenceSync", nullptr } },
765 { (PRFuncPtr*) &mSymbols.fIsSync, { "IsSync", nullptr } },
766 { (PRFuncPtr*) &mSymbols.fDeleteSync, { "DeleteSync", nullptr } },
767 { (PRFuncPtr*) &mSymbols.fClientWaitSync, { "ClientWaitSync", nullptr } },
768 { (PRFuncPtr*) &mSymbols.fWaitSync, { "WaitSync", nullptr } },
769 { (PRFuncPtr*) &mSymbols.fGetInteger64v, { "GetInteger64v", nullptr } },
770 { (PRFuncPtr*) &mSymbols.fGetSynciv, { "GetSynciv", nullptr } },
771 { nullptr, { nullptr } },
774 if (!LoadSymbols(&syncSymbols[0], trygl, prefix)) {
775 NS_ERROR("GL supports ARB_sync without supplying its functions.");
777 MarkExtensionUnsupported(ARB_sync);
778 mSymbols.fFenceSync = nullptr;
779 mSymbols.fIsSync = nullptr;
780 mSymbols.fDeleteSync = nullptr;
781 mSymbols.fClientWaitSync = nullptr;
782 mSymbols.fWaitSync = nullptr;
783 mSymbols.fGetInteger64v = nullptr;
784 mSymbols.fGetSynciv = nullptr;
788 if (IsExtensionSupported(OES_EGL_image)) {
789 SymLoadStruct imageSymbols[] = {
790 { (PRFuncPtr*) &mSymbols.fEGLImageTargetTexture2D, { "EGLImageTargetTexture2DOES", nullptr } },
791 { (PRFuncPtr*) &mSymbols.fEGLImageTargetRenderbufferStorage, { "EGLImageTargetRenderbufferStorageOES", nullptr } },
792 { nullptr, { nullptr } },
795 if (!LoadSymbols(&imageSymbols[0], trygl, prefix)) {
796 NS_ERROR("GL supports OES_EGL_image without supplying its functions.");
798 MarkExtensionUnsupported(OES_EGL_image);
799 mSymbols.fEGLImageTargetTexture2D = nullptr;
800 mSymbols.fEGLImageTargetRenderbufferStorage = nullptr;
804 if (IsExtensionSupported(APPLE_texture_range)) {
805 SymLoadStruct vaoSymbols[] = {
806 { (PRFuncPtr*) &mSymbols.fTextureRangeAPPLE, { "TextureRangeAPPLE", nullptr } },
807 { nullptr, { nullptr } },
810 if (!LoadSymbols(&vaoSymbols[0], trygl, prefix)) {
811 mSymbols.fTextureRangeAPPLE = nullptr;
815 if (IsExtensionSupported(ARB_vertex_array_object) ||
816 IsExtensionSupported(OES_vertex_array_object)) {
817 SymLoadStruct vaoSymbols[] = {
818 { (PRFuncPtr*) &mSymbols.fIsVertexArray, { "IsVertexArray", "IsVertexArrayOES", nullptr } },
819 { (PRFuncPtr*) &mSymbols.fGenVertexArrays, { "GenVertexArrays", "GenVertexArraysOES", nullptr } },
820 { (PRFuncPtr*) &mSymbols.fBindVertexArray, { "BindVertexArray", "BindVertexArrayOES", nullptr } },
821 { (PRFuncPtr*) &mSymbols.fDeleteVertexArrays, { "DeleteVertexArrays", "DeleteVertexArraysOES", nullptr } },
822 { nullptr, { nullptr } },
825 if (!LoadSymbols(&vaoSymbols[0], trygl, prefix)) {
826 NS_ERROR("GL supports Vertex Array Object without supplying its functions.");
828 MarkUnsupported(GLFeature::vertex_array_object);
829 mSymbols.fIsVertexArray = nullptr;
830 mSymbols.fGenVertexArrays = nullptr;
831 mSymbols.fBindVertexArray = nullptr;
832 mSymbols.fDeleteVertexArrays = nullptr;
835 else if (IsExtensionSupported(APPLE_vertex_array_object)) {
837 * separate call to LoadSymbols with APPLE_vertex_array_object to work around
838 * a driver bug : the IsVertexArray symbol (without suffix) can be present but unusable.
840 SymLoadStruct vaoSymbols[] = {
841 { (PRFuncPtr*) &mSymbols.fIsVertexArray, { "IsVertexArrayAPPLE", nullptr } },
842 { (PRFuncPtr*) &mSymbols.fGenVertexArrays, { "GenVertexArraysAPPLE", nullptr } },
843 { (PRFuncPtr*) &mSymbols.fBindVertexArray, { "BindVertexArrayAPPLE", nullptr } },
844 { (PRFuncPtr*) &mSymbols.fDeleteVertexArrays, { "DeleteVertexArraysAPPLE", nullptr } },
845 { nullptr, { nullptr } },
848 if (!LoadSymbols(&vaoSymbols[0], trygl, prefix)) {
849 NS_ERROR("GL supports Vertex Array Object without supplying its functions.");
851 MarkUnsupported(GLFeature::vertex_array_object);
852 mSymbols.fIsVertexArray = nullptr;
853 mSymbols.fGenVertexArrays = nullptr;
854 mSymbols.fBindVertexArray = nullptr;
855 mSymbols.fDeleteVertexArrays = nullptr;
859 if (IsSupported(GLFeature::draw_instanced)) {
860 SymLoadStruct drawInstancedSymbols[] = {
861 { (PRFuncPtr*) &mSymbols.fDrawArraysInstanced,
862 { "DrawArraysInstanced",
863 "DrawArraysInstancedARB",
864 "DrawArraysInstancedEXT",
865 "DrawArraysInstancedNV",
866 "DrawArraysInstancedANGLE",
867 nullptr
870 { (PRFuncPtr*) &mSymbols.fDrawElementsInstanced,
871 { "DrawElementsInstanced",
872 "DrawElementsInstancedARB",
873 "DrawElementsInstancedEXT",
874 "DrawElementsInstancedNV",
875 "DrawElementsInstancedANGLE",
876 nullptr
879 { nullptr, { nullptr } },
882 if (!LoadSymbols(drawInstancedSymbols, trygl, prefix)) {
883 NS_ERROR("GL supports instanced draws without supplying its functions.");
885 MarkUnsupported(GLFeature::draw_instanced);
886 mSymbols.fDrawArraysInstanced = nullptr;
887 mSymbols.fDrawElementsInstanced = nullptr;
891 if (IsSupported(GLFeature::instanced_arrays)) {
892 SymLoadStruct instancedArraySymbols[] = {
893 { (PRFuncPtr*) &mSymbols.fVertexAttribDivisor,
894 { "VertexAttribDivisor",
895 "VertexAttribDivisorARB",
896 "VertexAttribDivisorNV",
897 "VertexAttribDivisorANGLE",
898 nullptr
901 { nullptr, { nullptr } },
904 if (!LoadSymbols(instancedArraySymbols, trygl, prefix)) {
905 NS_ERROR("GL supports array instanced without supplying it function.");
907 MarkUnsupported(GLFeature::instanced_arrays);
908 mSymbols.fVertexAttribDivisor = nullptr;
912 if (IsSupported(GLFeature::transform_feedback)) {
913 SymLoadStruct transformFeedbackSymbols[] = {
914 { (PRFuncPtr*) &mSymbols.fBindBufferBase,
915 { "BindBufferBase",
916 "BindBufferBaseEXT",
917 "BindBufferBaseNV",
918 nullptr
921 { (PRFuncPtr*) &mSymbols.fBindBufferRange,
922 { "BindBufferRange",
923 "BindBufferRangeEXT",
924 "BindBufferRangeNV",
925 nullptr
928 { (PRFuncPtr*) &mSymbols.fBeginTransformFeedback,
929 { "BeginTransformFeedback",
930 "BeginTransformFeedbackEXT",
931 "BeginTransformFeedbackNV",
932 nullptr
935 { (PRFuncPtr*) &mSymbols.fEndTransformFeedback,
936 { "EndTransformFeedback",
937 "EndTransformFeedbackEXT",
938 "EndTransformFeedbackNV",
939 nullptr
942 { (PRFuncPtr*) &mSymbols.fTransformFeedbackVaryings,
943 { "TransformFeedbackVaryings",
944 "TransformFeedbackVaryingsEXT",
945 "TransformFeedbackVaryingsNV",
946 nullptr
949 { (PRFuncPtr*) &mSymbols.fGetTransformFeedbackVarying,
950 { "GetTransformFeedbackVarying",
951 "GetTransformFeedbackVaryingEXT",
952 "GetTransformFeedbackVaryingNV",
953 nullptr
956 { (PRFuncPtr*) &mSymbols.fGetIntegeri_v,
957 { "GetIntegeri_v",
958 "GetIntegerIndexedvEXT",
959 "GetIntegerIndexedvNV",
960 nullptr
963 { nullptr, { nullptr } },
966 if (!LoadSymbols(transformFeedbackSymbols, trygl, prefix)) {
967 NS_ERROR("GL supports transform feedback without supplying its functions.");
969 MarkUnsupported(GLFeature::transform_feedback);
970 MarkUnsupported(GLFeature::bind_buffer_offset);
971 mSymbols.fBindBufferBase = nullptr;
972 mSymbols.fBindBufferRange = nullptr;
973 mSymbols.fBeginTransformFeedback = nullptr;
974 mSymbols.fEndTransformFeedback = nullptr;
975 mSymbols.fTransformFeedbackVaryings = nullptr;
976 mSymbols.fGetTransformFeedbackVarying = nullptr;
977 mSymbols.fGetIntegeri_v = nullptr;
981 if (IsSupported(GLFeature::bind_buffer_offset)) {
982 SymLoadStruct bindBufferOffsetSymbols[] = {
983 { (PRFuncPtr*) &mSymbols.fBindBufferOffset,
984 { "BindBufferOffset",
985 "BindBufferOffsetEXT",
986 "BindBufferOffsetNV",
987 nullptr
990 { nullptr, { nullptr } },
993 if (!LoadSymbols(bindBufferOffsetSymbols, trygl, prefix)) {
994 NS_ERROR("GL supports BindBufferOffset without supplying its function.");
996 MarkUnsupported(GLFeature::bind_buffer_offset);
997 mSymbols.fBindBufferOffset = nullptr;
1001 if (IsSupported(GLFeature::query_objects)) {
1002 SymLoadStruct queryObjectsSymbols[] = {
1003 { (PRFuncPtr*) &mSymbols.fBeginQuery, { "BeginQuery", "BeginQueryEXT", nullptr } },
1004 { (PRFuncPtr*) &mSymbols.fGenQueries, { "GenQueries", "GenQueriesEXT", nullptr } },
1005 { (PRFuncPtr*) &mSymbols.fDeleteQueries, { "DeleteQueries", "DeleteQueriesEXT", nullptr } },
1006 { (PRFuncPtr*) &mSymbols.fEndQuery, { "EndQuery", "EndQueryEXT", nullptr } },
1007 { (PRFuncPtr*) &mSymbols.fGetQueryiv, { "GetQueryiv", "GetQueryivEXT", nullptr } },
1008 { (PRFuncPtr*) &mSymbols.fGetQueryObjectuiv, { "GetQueryObjectuiv", "GetQueryObjectuivEXT", nullptr } },
1009 { (PRFuncPtr*) &mSymbols.fIsQuery, { "IsQuery", "IsQueryEXT", nullptr } },
1010 { nullptr, { nullptr } },
1013 if (!LoadSymbols(queryObjectsSymbols, trygl, prefix)) {
1014 NS_ERROR("GL supports query objects without supplying its functions.");
1016 MarkUnsupported(GLFeature::query_objects);
1017 MarkUnsupported(GLFeature::get_query_object_iv);
1018 MarkUnsupported(GLFeature::occlusion_query);
1019 MarkUnsupported(GLFeature::occlusion_query_boolean);
1020 MarkUnsupported(GLFeature::occlusion_query2);
1021 mSymbols.fBeginQuery = nullptr;
1022 mSymbols.fGenQueries = nullptr;
1023 mSymbols.fDeleteQueries = nullptr;
1024 mSymbols.fEndQuery = nullptr;
1025 mSymbols.fGetQueryiv = nullptr;
1026 mSymbols.fGetQueryObjectuiv = nullptr;
1027 mSymbols.fIsQuery = nullptr;
1031 if (IsSupported(GLFeature::get_query_object_iv)) {
1032 SymLoadStruct queryObjectsSymbols[] = {
1033 { (PRFuncPtr*) &mSymbols.fGetQueryObjectiv, { "GetQueryObjectiv", "GetQueryObjectivEXT", nullptr } },
1034 { nullptr, { nullptr } },
1037 if (!LoadSymbols(queryObjectsSymbols, trygl, prefix)) {
1038 NS_ERROR("GL supports query objects iv getter without supplying its function.");
1040 MarkUnsupported(GLFeature::get_query_object_iv);
1041 mSymbols.fGetQueryObjectiv = nullptr;
1045 if (IsSupported(GLFeature::draw_buffers)) {
1046 SymLoadStruct drawBuffersSymbols[] = {
1047 { (PRFuncPtr*) &mSymbols.fDrawBuffers, { "DrawBuffers", nullptr } },
1048 { nullptr, { nullptr } },
1051 if (!LoadSymbols(drawBuffersSymbols, trygl, prefix)) {
1052 NS_ERROR("GL supports draw_buffers without supplying its functions.");
1054 MarkUnsupported(GLFeature::draw_buffers);
1055 mSymbols.fDrawBuffers = nullptr;
1059 if (IsExtensionSupported(KHR_debug)) {
1060 SymLoadStruct extSymbols[] = {
1061 { (PRFuncPtr*) &mSymbols.fDebugMessageControl, { "DebugMessageControl", "DebugMessageControlKHR", nullptr } },
1062 { (PRFuncPtr*) &mSymbols.fDebugMessageInsert, { "DebugMessageInsert", "DebugMessageInsertKHR", nullptr } },
1063 { (PRFuncPtr*) &mSymbols.fDebugMessageCallback, { "DebugMessageCallback", "DebugMessageCallbackKHR", nullptr } },
1064 { (PRFuncPtr*) &mSymbols.fGetDebugMessageLog, { "GetDebugMessageLog", "GetDebugMessageLogKHR", nullptr } },
1065 { (PRFuncPtr*) &mSymbols.fGetPointerv, { "GetPointerv", "GetPointervKHR", nullptr } },
1066 { (PRFuncPtr*) &mSymbols.fPushDebugGroup, { "PushDebugGroup", "PushDebugGroupKHR", nullptr } },
1067 { (PRFuncPtr*) &mSymbols.fPopDebugGroup, { "PopDebugGroup", "PopDebugGroupKHR", nullptr } },
1068 { (PRFuncPtr*) &mSymbols.fObjectLabel, { "ObjectLabel", "ObjectLabelKHR", nullptr } },
1069 { (PRFuncPtr*) &mSymbols.fGetObjectLabel, { "GetObjectLabel", "GetObjectLabelKHR", nullptr } },
1070 { (PRFuncPtr*) &mSymbols.fObjectPtrLabel, { "ObjectPtrLabel", "ObjectPtrLabelKHR", nullptr } },
1071 { (PRFuncPtr*) &mSymbols.fGetObjectPtrLabel, { "GetObjectPtrLabel", "GetObjectPtrLabelKHR", nullptr } },
1072 { nullptr, { nullptr } },
1075 if (!LoadSymbols(&extSymbols[0], trygl, prefix)) {
1076 NS_ERROR("GL supports KHR_debug without supplying its functions.");
1078 MarkExtensionUnsupported(KHR_debug);
1079 mSymbols.fDebugMessageControl = nullptr;
1080 mSymbols.fDebugMessageInsert = nullptr;
1081 mSymbols.fDebugMessageCallback = nullptr;
1082 mSymbols.fGetDebugMessageLog = nullptr;
1083 mSymbols.fGetPointerv = nullptr;
1084 mSymbols.fPushDebugGroup = nullptr;
1085 mSymbols.fPopDebugGroup = nullptr;
1086 mSymbols.fObjectLabel = nullptr;
1087 mSymbols.fGetObjectLabel = nullptr;
1088 mSymbols.fObjectPtrLabel = nullptr;
1089 mSymbols.fGetObjectPtrLabel = nullptr;
1093 if (IsSupported(GLFeature::draw_range_elements)) {
1094 SymLoadStruct imageSymbols[] = {
1095 { (PRFuncPtr*) &mSymbols.fDrawRangeElements, { "DrawRangeElementsEXT", "DrawRangeElements", nullptr } },
1096 { nullptr, { nullptr } },
1099 if (!LoadSymbols(&imageSymbols[0], trygl, prefix)) {
1100 NS_ERROR("GL supports draw_range_elements without supplying its functions.");
1102 MarkUnsupported(GLFeature::draw_range_elements);
1103 mSymbols.fDrawRangeElements = nullptr;
1107 // Load developer symbols, don't fail if we can't find them.
1108 SymLoadStruct auxSymbols[] = {
1109 { (PRFuncPtr*) &mSymbols.fGetTexImage, { "GetTexImage", nullptr } },
1110 { (PRFuncPtr*) &mSymbols.fGetTexLevelParameteriv, { "GetTexLevelParameteriv", nullptr } },
1111 { nullptr, { nullptr } },
1113 bool warnOnFailures = DebugMode();
1114 LoadSymbols(&auxSymbols[0], trygl, prefix, warnOnFailures);
1117 if (mInitialized) {
1118 raw_fGetIntegerv(LOCAL_GL_VIEWPORT, mViewportRect);
1119 raw_fGetIntegerv(LOCAL_GL_SCISSOR_BOX, mScissorRect);
1120 raw_fGetIntegerv(LOCAL_GL_MAX_TEXTURE_SIZE, &mMaxTextureSize);
1121 raw_fGetIntegerv(LOCAL_GL_MAX_CUBE_MAP_TEXTURE_SIZE, &mMaxCubeMapTextureSize);
1122 raw_fGetIntegerv(LOCAL_GL_MAX_RENDERBUFFER_SIZE, &mMaxRenderbufferSize);
1124 #ifdef XP_MACOSX
1125 if (mWorkAroundDriverBugs) {
1126 if (mVendor == GLVendor::Intel) {
1127 // see bug 737182 for 2D textures, bug 684882 for cube map textures.
1128 mMaxTextureSize = std::min(mMaxTextureSize, 4096);
1129 mMaxCubeMapTextureSize = std::min(mMaxCubeMapTextureSize, 512);
1130 // for good measure, we align renderbuffers on what we do for 2D textures
1131 mMaxRenderbufferSize = std::min(mMaxRenderbufferSize, 4096);
1132 mNeedsTextureSizeChecks = true;
1133 } else if (mVendor == GLVendor::NVIDIA) {
1134 if (nsCocoaFeatures::OnMountainLionOrLater()) {
1135 // See bug 879656. 8192 fails, 8191 works.
1136 mMaxTextureSize = std::min(mMaxTextureSize, 8191);
1137 mMaxRenderbufferSize = std::min(mMaxRenderbufferSize, 8191);
1139 else {
1140 // See bug 877949.
1141 mMaxTextureSize = std::min(mMaxTextureSize, 4096);
1142 mMaxRenderbufferSize = std::min(mMaxRenderbufferSize, 4096);
1145 // Part of the bug 879656, but it also doesn't hurt the 877949
1146 mNeedsTextureSizeChecks = true;
1149 #endif
1150 #ifdef MOZ_X11
1151 if (mWorkAroundDriverBugs &&
1152 mVendor == GLVendor::Nouveau) {
1153 // see bug 814716. Clamp MaxCubeMapTextureSize at 2K for Nouveau.
1154 mMaxCubeMapTextureSize = std::min(mMaxCubeMapTextureSize, 2048);
1155 mNeedsTextureSizeChecks = true;
1157 #endif
1159 mMaxTextureImageSize = mMaxTextureSize;
1161 mMaxSamples = 0;
1162 if (IsSupported(GLFeature::framebuffer_multisample)) {
1163 fGetIntegerv(LOCAL_GL_MAX_SAMPLES, (GLint*)&mMaxSamples);
1166 // We're ready for final setup.
1167 fBindFramebuffer(LOCAL_GL_FRAMEBUFFER, 0);
1169 if (mCaps.any)
1170 DetermineCaps();
1172 UpdatePixelFormat();
1173 UpdateGLFormats(mCaps);
1175 mTexGarbageBin = new TextureGarbageBin(this);
1177 MOZ_ASSERT(IsCurrent());
1179 if (DebugMode() && IsExtensionSupported(KHR_debug)) {
1180 fEnable(LOCAL_GL_DEBUG_OUTPUT);
1181 fDisable(LOCAL_GL_DEBUG_OUTPUT_SYNCHRONOUS);
1182 fDebugMessageCallback(&StaticDebugCallback, (void*)this);
1183 fDebugMessageControl(LOCAL_GL_DONT_CARE,
1184 LOCAL_GL_DONT_CARE,
1185 LOCAL_GL_DONT_CARE,
1186 0, nullptr,
1187 true);
1190 reporter.SetSuccessful();
1191 } else {
1192 // if initialization fails, ensure all symbols are zero, to avoid hard-to-understand bugs
1193 mSymbols.Zero();
1194 NS_WARNING("InitWithPrefix failed!");
1197 mVersionString = nsPrintfCString("%u.%u.%u", mVersion / 100, (mVersion / 10) % 10, mVersion % 10);
1199 return mInitialized;
1202 void
1203 GLContext::DebugCallback(GLenum source,
1204 GLenum type,
1205 GLuint id,
1206 GLenum severity,
1207 GLsizei length,
1208 const GLchar* message)
1210 nsAutoCString sourceStr;
1211 switch (source) {
1212 case LOCAL_GL_DEBUG_SOURCE_API:
1213 sourceStr = NS_LITERAL_CSTRING("SOURCE_API");
1214 break;
1215 case LOCAL_GL_DEBUG_SOURCE_WINDOW_SYSTEM:
1216 sourceStr = NS_LITERAL_CSTRING("SOURCE_WINDOW_SYSTEM");
1217 break;
1218 case LOCAL_GL_DEBUG_SOURCE_SHADER_COMPILER:
1219 sourceStr = NS_LITERAL_CSTRING("SOURCE_SHADER_COMPILER");
1220 break;
1221 case LOCAL_GL_DEBUG_SOURCE_THIRD_PARTY:
1222 sourceStr = NS_LITERAL_CSTRING("SOURCE_THIRD_PARTY");
1223 break;
1224 case LOCAL_GL_DEBUG_SOURCE_APPLICATION:
1225 sourceStr = NS_LITERAL_CSTRING("SOURCE_APPLICATION");
1226 break;
1227 case LOCAL_GL_DEBUG_SOURCE_OTHER:
1228 sourceStr = NS_LITERAL_CSTRING("SOURCE_OTHER");
1229 break;
1230 default:
1231 sourceStr = nsPrintfCString("<source 0x%04x>", source);
1232 break;
1235 nsAutoCString typeStr;
1236 switch (type) {
1237 case LOCAL_GL_DEBUG_TYPE_ERROR:
1238 typeStr = NS_LITERAL_CSTRING("TYPE_ERROR");
1239 break;
1240 case LOCAL_GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR:
1241 typeStr = NS_LITERAL_CSTRING("TYPE_DEPRECATED_BEHAVIOR");
1242 break;
1243 case LOCAL_GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR:
1244 typeStr = NS_LITERAL_CSTRING("TYPE_UNDEFINED_BEHAVIOR");
1245 break;
1246 case LOCAL_GL_DEBUG_TYPE_PORTABILITY:
1247 typeStr = NS_LITERAL_CSTRING("TYPE_PORTABILITY");
1248 break;
1249 case LOCAL_GL_DEBUG_TYPE_PERFORMANCE:
1250 typeStr = NS_LITERAL_CSTRING("TYPE_PERFORMANCE");
1251 break;
1252 case LOCAL_GL_DEBUG_TYPE_OTHER:
1253 typeStr = NS_LITERAL_CSTRING("TYPE_OTHER");
1254 break;
1255 case LOCAL_GL_DEBUG_TYPE_MARKER:
1256 typeStr = NS_LITERAL_CSTRING("TYPE_MARKER");
1257 break;
1258 default:
1259 typeStr = nsPrintfCString("<type 0x%04x>", type);
1260 break;
1263 nsAutoCString sevStr;
1264 switch (severity) {
1265 case LOCAL_GL_DEBUG_SEVERITY_HIGH:
1266 sevStr = NS_LITERAL_CSTRING("SEVERITY_HIGH");
1267 break;
1268 case LOCAL_GL_DEBUG_SEVERITY_MEDIUM:
1269 sevStr = NS_LITERAL_CSTRING("SEVERITY_MEDIUM");
1270 break;
1271 case LOCAL_GL_DEBUG_SEVERITY_LOW:
1272 sevStr = NS_LITERAL_CSTRING("SEVERITY_LOW");
1273 break;
1274 case LOCAL_GL_DEBUG_SEVERITY_NOTIFICATION:
1275 sevStr = NS_LITERAL_CSTRING("SEVERITY_NOTIFICATION");
1276 break;
1277 default:
1278 sevStr = nsPrintfCString("<severity 0x%04x>", severity);
1279 break;
1282 printf_stderr("[KHR_debug: 0x%x] ID %u: %s %s %s:\n %s",
1283 (uintptr_t)this,
1285 sourceStr.BeginReading(),
1286 typeStr.BeginReading(),
1287 sevStr.BeginReading(),
1288 message);
1291 void
1292 GLContext::InitExtensions()
1294 MakeCurrent();
1295 const char* extensions = (const char*)fGetString(LOCAL_GL_EXTENSIONS);
1296 if (!extensions)
1297 return;
1299 #ifdef DEBUG
1300 static bool firstRun = true;
1301 #else
1302 // Non-DEBUG, so never spew.
1303 const bool firstRun = false;
1304 #endif
1306 InitializeExtensionsBitSet(mAvailableExtensions, extensions, sExtensionNames, firstRun && DebugMode());
1308 if (WorkAroundDriverBugs() &&
1309 Vendor() == GLVendor::Qualcomm) {
1311 // Some Adreno drivers do not report GL_OES_EGL_sync, but they really do support it.
1312 MarkExtensionSupported(OES_EGL_sync);
1315 if (WorkAroundDriverBugs() &&
1316 Renderer() == GLRenderer::AndroidEmulator) {
1317 // the Android emulator, which we use to run B2G reftests on,
1318 // doesn't expose the OES_rgb8_rgba8 extension, but it seems to
1319 // support it (tautologically, as it only runs on desktop GL).
1320 MarkExtensionSupported(OES_rgb8_rgba8);
1323 if (WorkAroundDriverBugs() &&
1324 Vendor() == GLVendor::VMware &&
1325 Renderer() == GLRenderer::GalliumLlvmpipe)
1327 // The llvmpipe driver that is used on linux try servers appears to have
1328 // buggy support for s3tc/dxt1 compressed textures.
1329 // See Bug 975824.
1330 MarkExtensionUnsupported(EXT_texture_compression_s3tc);
1331 MarkExtensionUnsupported(EXT_texture_compression_dxt1);
1332 MarkExtensionUnsupported(ANGLE_texture_compression_dxt3);
1333 MarkExtensionUnsupported(ANGLE_texture_compression_dxt5);
1336 #ifdef XP_MACOSX
1337 // Bug 1009642: On OSX Mavericks (10.9), the driver for Intel HD
1338 // 3000 appears to be buggy WRT updating sub-images of S3TC
1339 // textures with glCompressedTexSubImage2D. Works on Intel HD 4000
1340 // and Intel HD 5000/Iris that I tested.
1341 if (WorkAroundDriverBugs() &&
1342 nsCocoaFeatures::OSXVersionMajor() == 10 &&
1343 nsCocoaFeatures::OSXVersionMinor() == 9 &&
1344 Renderer() == GLRenderer::IntelHD3000)
1346 MarkExtensionUnsupported(EXT_texture_compression_s3tc);
1348 #endif
1350 #ifdef DEBUG
1351 firstRun = false;
1352 #endif
1355 void
1356 GLContext::PlatformStartup()
1358 RegisterStrongMemoryReporter(new GfxTexturesReporter());
1361 // Common code for checking for both GL extensions and GLX extensions.
1362 bool
1363 GLContext::ListHasExtension(const GLubyte *extensions, const char *extension)
1365 // fix bug 612572 - we were crashing as we were calling this function with extensions==null
1366 if (extensions == nullptr || extension == nullptr)
1367 return false;
1369 const GLubyte *start;
1370 GLubyte *where, *terminator;
1372 /* Extension names should not have spaces. */
1373 where = (GLubyte *) strchr(extension, ' ');
1374 if (where || *extension == '\0')
1375 return false;
1378 * It takes a bit of care to be fool-proof about parsing the
1379 * OpenGL extensions string. Don't be fooled by sub-strings,
1380 * etc.
1382 start = extensions;
1383 for (;;) {
1384 where = (GLubyte *) strstr((const char *) start, extension);
1385 if (!where) {
1386 break;
1388 terminator = where + strlen(extension);
1389 if (where == start || *(where - 1) == ' ') {
1390 if (*terminator == ' ' || *terminator == '\0') {
1391 return true;
1394 start = terminator;
1396 return false;
1399 void
1400 GLContext::DetermineCaps()
1402 PixelBufferFormat format = QueryPixelFormat();
1404 SurfaceCaps caps;
1405 caps.color = !!format.red && !!format.green && !!format.blue;
1406 caps.bpp16 = caps.color && format.ColorBits() == 16;
1407 caps.alpha = !!format.alpha;
1408 caps.depth = !!format.depth;
1409 caps.stencil = !!format.stencil;
1410 caps.antialias = format.samples > 1;
1411 caps.preserve = true;
1413 mCaps = caps;
1416 PixelBufferFormat
1417 GLContext::QueryPixelFormat()
1419 PixelBufferFormat format;
1421 ScopedBindFramebuffer autoFB(this, 0);
1423 fGetIntegerv(LOCAL_GL_RED_BITS , &format.red );
1424 fGetIntegerv(LOCAL_GL_GREEN_BITS, &format.green);
1425 fGetIntegerv(LOCAL_GL_BLUE_BITS , &format.blue );
1426 fGetIntegerv(LOCAL_GL_ALPHA_BITS, &format.alpha);
1428 fGetIntegerv(LOCAL_GL_DEPTH_BITS, &format.depth);
1429 fGetIntegerv(LOCAL_GL_STENCIL_BITS, &format.stencil);
1431 fGetIntegerv(LOCAL_GL_SAMPLES, &format.samples);
1433 return format;
1436 void
1437 GLContext::UpdatePixelFormat()
1439 PixelBufferFormat format = QueryPixelFormat();
1440 #ifdef DEBUG
1441 const SurfaceCaps& caps = Caps();
1442 MOZ_ASSERT(!caps.any, "Did you forget to DetermineCaps()?");
1444 MOZ_ASSERT(caps.color == !!format.red);
1445 MOZ_ASSERT(caps.color == !!format.green);
1446 MOZ_ASSERT(caps.color == !!format.blue);
1448 MOZ_ASSERT(caps.alpha == !!format.alpha);
1450 // These we either must have if they're requested, or
1451 // we can have if they're not.
1452 MOZ_ASSERT(caps.depth == !!format.depth || !caps.depth);
1453 MOZ_ASSERT(caps.stencil == !!format.stencil || !caps.stencil);
1455 MOZ_ASSERT(caps.antialias == (format.samples > 1));
1456 #endif
1457 mPixelFormat = new PixelBufferFormat(format);
1460 GLFormats
1461 GLContext::ChooseGLFormats(const SurfaceCaps& caps) const
1463 GLFormats formats;
1465 // If we're on ES2 hardware and we have an explicit request for 16 bits of color or less
1466 // OR we don't support full 8-bit color, return a 4444 or 565 format.
1467 bool bpp16 = caps.bpp16;
1468 if (IsGLES()) {
1469 if (!IsExtensionSupported(OES_rgb8_rgba8))
1470 bpp16 = true;
1471 } else {
1472 // RGB565 is uncommon on desktop, requiring ARB_ES2_compatibility.
1473 // Since it's also vanishingly useless there, let's not support it.
1474 bpp16 = false;
1477 if (bpp16) {
1478 MOZ_ASSERT(IsGLES());
1479 if (caps.alpha) {
1480 formats.color_texInternalFormat = LOCAL_GL_RGBA;
1481 formats.color_texFormat = LOCAL_GL_RGBA;
1482 formats.color_texType = LOCAL_GL_UNSIGNED_SHORT_4_4_4_4;
1483 formats.color_rbFormat = LOCAL_GL_RGBA4;
1484 } else {
1485 formats.color_texInternalFormat = LOCAL_GL_RGB;
1486 formats.color_texFormat = LOCAL_GL_RGB;
1487 formats.color_texType = LOCAL_GL_UNSIGNED_SHORT_5_6_5;
1488 formats.color_rbFormat = LOCAL_GL_RGB565;
1490 } else {
1491 formats.color_texType = LOCAL_GL_UNSIGNED_BYTE;
1493 if (caps.alpha) {
1494 formats.color_texInternalFormat = IsGLES() ? LOCAL_GL_RGBA : LOCAL_GL_RGBA8;
1495 formats.color_texFormat = LOCAL_GL_RGBA;
1496 formats.color_rbFormat = LOCAL_GL_RGBA8;
1497 } else {
1498 formats.color_texInternalFormat = IsGLES() ? LOCAL_GL_RGB : LOCAL_GL_RGB8;
1499 formats.color_texFormat = LOCAL_GL_RGB;
1500 formats.color_rbFormat = LOCAL_GL_RGB8;
1504 uint32_t msaaLevel = gfxPrefs::MSAALevel();
1505 GLsizei samples = msaaLevel * msaaLevel;
1506 samples = std::min(samples, mMaxSamples);
1508 // Bug 778765.
1509 if (WorkAroundDriverBugs() && samples == 1) {
1510 samples = 0;
1512 formats.samples = samples;
1515 // Be clear that these are 0 if unavailable.
1516 formats.depthStencil = 0;
1517 if (!IsGLES() || IsExtensionSupported(OES_packed_depth_stencil)) {
1518 formats.depthStencil = LOCAL_GL_DEPTH24_STENCIL8;
1521 formats.depth = 0;
1522 if (IsGLES()) {
1523 if (IsExtensionSupported(OES_depth24)) {
1524 formats.depth = LOCAL_GL_DEPTH_COMPONENT24;
1525 } else {
1526 formats.depth = LOCAL_GL_DEPTH_COMPONENT16;
1528 } else {
1529 formats.depth = LOCAL_GL_DEPTH_COMPONENT24;
1532 formats.stencil = LOCAL_GL_STENCIL_INDEX8;
1534 return formats;
1537 bool
1538 GLContext::IsFramebufferComplete(GLuint fb, GLenum* pStatus)
1540 MOZ_ASSERT(fb);
1542 ScopedBindFramebuffer autoFB(this, fb);
1543 MOZ_ASSERT(fIsFramebuffer(fb));
1545 GLenum status = fCheckFramebufferStatus(LOCAL_GL_FRAMEBUFFER);
1546 if (pStatus)
1547 *pStatus = status;
1549 return status == LOCAL_GL_FRAMEBUFFER_COMPLETE;
1552 void
1553 GLContext::AttachBuffersToFB(GLuint colorTex, GLuint colorRB,
1554 GLuint depthRB, GLuint stencilRB,
1555 GLuint fb, GLenum target)
1557 MOZ_ASSERT(fb);
1558 MOZ_ASSERT( !(colorTex && colorRB) );
1560 ScopedBindFramebuffer autoFB(this, fb);
1561 MOZ_ASSERT(fIsFramebuffer(fb)); // It only counts after being bound.
1563 if (colorTex) {
1564 MOZ_ASSERT(fIsTexture(colorTex));
1565 MOZ_ASSERT(target == LOCAL_GL_TEXTURE_2D ||
1566 target == LOCAL_GL_TEXTURE_RECTANGLE_ARB);
1567 fFramebufferTexture2D(LOCAL_GL_FRAMEBUFFER,
1568 LOCAL_GL_COLOR_ATTACHMENT0,
1569 target,
1570 colorTex,
1572 } else if (colorRB) {
1573 MOZ_ASSERT(fIsRenderbuffer(colorRB));
1574 fFramebufferRenderbuffer(LOCAL_GL_FRAMEBUFFER,
1575 LOCAL_GL_COLOR_ATTACHMENT0,
1576 LOCAL_GL_RENDERBUFFER,
1577 colorRB);
1580 if (depthRB) {
1581 MOZ_ASSERT(fIsRenderbuffer(depthRB));
1582 fFramebufferRenderbuffer(LOCAL_GL_FRAMEBUFFER,
1583 LOCAL_GL_DEPTH_ATTACHMENT,
1584 LOCAL_GL_RENDERBUFFER,
1585 depthRB);
1588 if (stencilRB) {
1589 MOZ_ASSERT(fIsRenderbuffer(stencilRB));
1590 fFramebufferRenderbuffer(LOCAL_GL_FRAMEBUFFER,
1591 LOCAL_GL_STENCIL_ATTACHMENT,
1592 LOCAL_GL_RENDERBUFFER,
1593 stencilRB);
1597 bool
1598 GLContext::AssembleOffscreenFBs(const GLuint colorMSRB,
1599 const GLuint depthRB,
1600 const GLuint stencilRB,
1601 const GLuint texture,
1602 GLuint* drawFB_out,
1603 GLuint* readFB_out)
1605 if (!colorMSRB && !texture) {
1606 MOZ_ASSERT(!depthRB && !stencilRB);
1608 if (drawFB_out)
1609 *drawFB_out = 0;
1610 if (readFB_out)
1611 *readFB_out = 0;
1613 return true;
1616 ScopedBindFramebuffer autoFB(this);
1618 GLuint drawFB = 0;
1619 GLuint readFB = 0;
1621 if (texture) {
1622 readFB = 0;
1623 fGenFramebuffers(1, &readFB);
1624 BindFB(readFB);
1625 fFramebufferTexture2D(LOCAL_GL_FRAMEBUFFER,
1626 LOCAL_GL_COLOR_ATTACHMENT0,
1627 LOCAL_GL_TEXTURE_2D,
1628 texture,
1632 if (colorMSRB) {
1633 drawFB = 0;
1634 fGenFramebuffers(1, &drawFB);
1635 BindFB(drawFB);
1636 fFramebufferRenderbuffer(LOCAL_GL_FRAMEBUFFER,
1637 LOCAL_GL_COLOR_ATTACHMENT0,
1638 LOCAL_GL_RENDERBUFFER,
1639 colorMSRB);
1640 } else {
1641 drawFB = readFB;
1643 MOZ_ASSERT(GetFB() == drawFB);
1645 if (depthRB) {
1646 fFramebufferRenderbuffer(LOCAL_GL_FRAMEBUFFER,
1647 LOCAL_GL_DEPTH_ATTACHMENT,
1648 LOCAL_GL_RENDERBUFFER,
1649 depthRB);
1652 if (stencilRB) {
1653 fFramebufferRenderbuffer(LOCAL_GL_FRAMEBUFFER,
1654 LOCAL_GL_STENCIL_ATTACHMENT,
1655 LOCAL_GL_RENDERBUFFER,
1656 stencilRB);
1659 // We should be all resized. Check for framebuffer completeness.
1660 GLenum status;
1661 bool isComplete = true;
1663 if (!IsFramebufferComplete(drawFB, &status)) {
1664 NS_WARNING("DrawFBO: Incomplete");
1665 #ifdef DEBUG
1666 if (DebugMode()) {
1667 printf_stderr("Framebuffer status: %X\n", status);
1669 #endif
1670 isComplete = false;
1673 if (!IsFramebufferComplete(readFB, &status)) {
1674 NS_WARNING("ReadFBO: Incomplete");
1675 #ifdef DEBUG
1676 if (DebugMode()) {
1677 printf_stderr("Framebuffer status: %X\n", status);
1679 #endif
1680 isComplete = false;
1683 if (drawFB_out) {
1684 *drawFB_out = drawFB;
1685 } else if (drawFB) {
1686 NS_RUNTIMEABORT("drawFB created when not requested!");
1689 if (readFB_out) {
1690 *readFB_out = readFB;
1691 } else if (readFB) {
1692 NS_RUNTIMEABORT("readFB created when not requested!");
1695 return isComplete;
1700 bool
1701 GLContext::PublishFrame()
1703 MOZ_ASSERT(mScreen);
1705 if (!mScreen->PublishFrame(OffscreenSize()))
1706 return false;
1708 return true;
1711 SharedSurface_GL*
1712 GLContext::RequestFrame()
1714 MOZ_ASSERT(mScreen);
1716 SharedSurface* ret = mScreen->Stream()->SwapConsumer();
1717 if (!ret)
1718 return nullptr;
1720 return SharedSurface_GL::Cast(ret);
1725 void
1726 GLContext::ClearSafely()
1728 // bug 659349 --- we must be very careful here: clearing a GL framebuffer is nontrivial, relies on a lot of state,
1729 // and in the case of the backbuffer of a WebGL context, state is exposed to scripts.
1731 // The code here is taken from WebGLContext::ForceClearFramebufferWithDefaultValues, but I didn't find a good way of
1732 // sharing code with it. WebGL's code is somewhat performance-critical as it is typically called on every frame, so
1733 // WebGL keeps track of GL state to avoid having to query it everytime, and also tries to only do work for actually
1734 // present buffers (e.g. stencil buffer). Doing that here seems like premature optimization,
1735 // as ClearSafely() is called only when e.g. a canvas is resized, not on every animation frame.
1737 realGLboolean scissorTestEnabled;
1738 realGLboolean ditherEnabled;
1739 realGLboolean colorWriteMask[4];
1740 realGLboolean depthWriteMask;
1741 GLint stencilWriteMaskFront, stencilWriteMaskBack;
1742 GLfloat colorClearValue[4];
1743 GLfloat depthClearValue;
1744 GLint stencilClearValue;
1746 // save current GL state
1747 fGetBooleanv(LOCAL_GL_SCISSOR_TEST, &scissorTestEnabled);
1748 fGetBooleanv(LOCAL_GL_DITHER, &ditherEnabled);
1749 fGetBooleanv(LOCAL_GL_COLOR_WRITEMASK, colorWriteMask);
1750 fGetBooleanv(LOCAL_GL_DEPTH_WRITEMASK, &depthWriteMask);
1751 fGetIntegerv(LOCAL_GL_STENCIL_WRITEMASK, &stencilWriteMaskFront);
1752 fGetIntegerv(LOCAL_GL_STENCIL_BACK_WRITEMASK, &stencilWriteMaskBack);
1753 fGetFloatv(LOCAL_GL_COLOR_CLEAR_VALUE, colorClearValue);
1754 fGetFloatv(LOCAL_GL_DEPTH_CLEAR_VALUE, &depthClearValue);
1755 fGetIntegerv(LOCAL_GL_STENCIL_CLEAR_VALUE, &stencilClearValue);
1757 // prepare GL state for clearing
1758 fDisable(LOCAL_GL_SCISSOR_TEST);
1759 fDisable(LOCAL_GL_DITHER);
1761 fColorMask(1, 1, 1, 1);
1762 fClearColor(0.f, 0.f, 0.f, 0.f);
1764 fDepthMask(1);
1765 fClearDepth(1.0f);
1767 fStencilMask(0xffffffff);
1768 fClearStencil(0);
1770 // do clear
1771 fClear(LOCAL_GL_COLOR_BUFFER_BIT |
1772 LOCAL_GL_DEPTH_BUFFER_BIT |
1773 LOCAL_GL_STENCIL_BUFFER_BIT);
1775 // restore GL state after clearing
1776 fColorMask(colorWriteMask[0],
1777 colorWriteMask[1],
1778 colorWriteMask[2],
1779 colorWriteMask[3]);
1780 fClearColor(colorClearValue[0],
1781 colorClearValue[1],
1782 colorClearValue[2],
1783 colorClearValue[3]);
1785 fDepthMask(depthWriteMask);
1786 fClearDepth(depthClearValue);
1788 fStencilMaskSeparate(LOCAL_GL_FRONT, stencilWriteMaskFront);
1789 fStencilMaskSeparate(LOCAL_GL_BACK, stencilWriteMaskBack);
1790 fClearStencil(stencilClearValue);
1792 if (ditherEnabled)
1793 fEnable(LOCAL_GL_DITHER);
1794 else
1795 fDisable(LOCAL_GL_DITHER);
1797 if (scissorTestEnabled)
1798 fEnable(LOCAL_GL_SCISSOR_TEST);
1799 else
1800 fDisable(LOCAL_GL_SCISSOR_TEST);
1804 void
1805 GLContext::MarkDestroyed()
1807 if (IsDestroyed())
1808 return;
1810 if (MakeCurrent()) {
1811 DestroyScreenBuffer();
1813 mBlitHelper = nullptr;
1814 mBlitTextureImageHelper = nullptr;
1815 mReadTexImageHelper = nullptr;
1817 mTexGarbageBin->GLContextTeardown();
1818 } else {
1819 NS_WARNING("MakeCurrent() failed during MarkDestroyed! Skipping GL object teardown.");
1822 mSymbols.Zero();
1825 #ifdef DEBUG
1826 /* static */ void
1827 GLContext::AssertNotPassingStackBufferToTheGL(const void* ptr)
1829 int somethingOnTheStack;
1830 const void* someStackPtr = &somethingOnTheStack;
1831 const int page_bits = 12;
1832 intptr_t page = reinterpret_cast<uintptr_t>(ptr) >> page_bits;
1833 intptr_t someStackPage = reinterpret_cast<uintptr_t>(someStackPtr) >> page_bits;
1834 uintptr_t pageDistance = std::abs(page - someStackPage);
1836 // Explanation for the "distance <= 1" check here as opposed to just
1837 // an equality check.
1839 // Here we assume that pages immediately adjacent to the someStackAddress page,
1840 // are also stack pages. That allows to catch the case where the calling frame put
1841 // a buffer on the stack, and we just crossed the page boundary. That is likely
1842 // to happen, precisely, when using stack arrays. I hit that specifically
1843 // with CompositorOGL::Initialize.
1845 // In theory we could be unlucky and wrongly assert here. If that happens,
1846 // it will only affect debug builds, and looking at stacks we'll be able to
1847 // see that this assert is wrong and revert to the conservative and safe
1848 // approach of only asserting when address and someStackAddress are
1849 // on the same page.
1850 bool isStackAddress = pageDistance <= 1;
1851 MOZ_ASSERT(!isStackAddress,
1852 "Please don't pass stack arrays to the GL. "
1853 "Consider using HeapCopyOfStackArray. "
1854 "See bug 1005658.");
1857 void
1858 GLContext::CreatedProgram(GLContext *aOrigin, GLuint aName)
1860 mTrackedPrograms.AppendElement(NamedResource(aOrigin, aName));
1863 void
1864 GLContext::CreatedShader(GLContext *aOrigin, GLuint aName)
1866 mTrackedShaders.AppendElement(NamedResource(aOrigin, aName));
1869 void
1870 GLContext::CreatedBuffers(GLContext *aOrigin, GLsizei aCount, GLuint *aNames)
1872 for (GLsizei i = 0; i < aCount; ++i) {
1873 mTrackedBuffers.AppendElement(NamedResource(aOrigin, aNames[i]));
1877 void
1878 GLContext::CreatedQueries(GLContext *aOrigin, GLsizei aCount, GLuint *aNames)
1880 for (GLsizei i = 0; i < aCount; ++i) {
1881 mTrackedQueries.AppendElement(NamedResource(aOrigin, aNames[i]));
1885 void
1886 GLContext::CreatedTextures(GLContext *aOrigin, GLsizei aCount, GLuint *aNames)
1888 for (GLsizei i = 0; i < aCount; ++i) {
1889 mTrackedTextures.AppendElement(NamedResource(aOrigin, aNames[i]));
1893 void
1894 GLContext::CreatedFramebuffers(GLContext *aOrigin, GLsizei aCount, GLuint *aNames)
1896 for (GLsizei i = 0; i < aCount; ++i) {
1897 mTrackedFramebuffers.AppendElement(NamedResource(aOrigin, aNames[i]));
1901 void
1902 GLContext::CreatedRenderbuffers(GLContext *aOrigin, GLsizei aCount, GLuint *aNames)
1904 for (GLsizei i = 0; i < aCount; ++i) {
1905 mTrackedRenderbuffers.AppendElement(NamedResource(aOrigin, aNames[i]));
1909 static void
1910 RemoveNamesFromArray(GLContext *aOrigin, GLsizei aCount, const GLuint *aNames, nsTArray<GLContext::NamedResource>& aArray)
1912 for (GLsizei j = 0; j < aCount; ++j) {
1913 GLuint name = aNames[j];
1914 // name 0 can be ignored
1915 if (name == 0)
1916 continue;
1918 for (uint32_t i = 0; i < aArray.Length(); ++i) {
1919 if (aArray[i].name == name) {
1920 aArray.RemoveElementAt(i);
1921 break;
1927 void
1928 GLContext::DeletedProgram(GLContext *aOrigin, GLuint aName)
1930 RemoveNamesFromArray(aOrigin, 1, &aName, mTrackedPrograms);
1933 void
1934 GLContext::DeletedShader(GLContext *aOrigin, GLuint aName)
1936 RemoveNamesFromArray(aOrigin, 1, &aName, mTrackedShaders);
1939 void
1940 GLContext::DeletedBuffers(GLContext *aOrigin, GLsizei aCount, const GLuint *aNames)
1942 RemoveNamesFromArray(aOrigin, aCount, aNames, mTrackedBuffers);
1945 void
1946 GLContext::DeletedQueries(GLContext *aOrigin, GLsizei aCount, const GLuint *aNames)
1948 RemoveNamesFromArray(aOrigin, aCount, aNames, mTrackedQueries);
1951 void
1952 GLContext::DeletedTextures(GLContext *aOrigin, GLsizei aCount, const GLuint *aNames)
1954 RemoveNamesFromArray(aOrigin, aCount, aNames, mTrackedTextures);
1957 void
1958 GLContext::DeletedFramebuffers(GLContext *aOrigin, GLsizei aCount, const GLuint *aNames)
1960 RemoveNamesFromArray(aOrigin, aCount, aNames, mTrackedFramebuffers);
1963 void
1964 GLContext::DeletedRenderbuffers(GLContext *aOrigin, GLsizei aCount, const GLuint *aNames)
1966 RemoveNamesFromArray(aOrigin, aCount, aNames, mTrackedRenderbuffers);
1969 static void
1970 MarkContextDestroyedInArray(GLContext *aContext, nsTArray<GLContext::NamedResource>& aArray)
1972 for (uint32_t i = 0; i < aArray.Length(); ++i) {
1973 if (aArray[i].origin == aContext)
1974 aArray[i].originDeleted = true;
1978 void
1979 GLContext::SharedContextDestroyed(GLContext *aChild)
1981 MarkContextDestroyedInArray(aChild, mTrackedPrograms);
1982 MarkContextDestroyedInArray(aChild, mTrackedShaders);
1983 MarkContextDestroyedInArray(aChild, mTrackedTextures);
1984 MarkContextDestroyedInArray(aChild, mTrackedFramebuffers);
1985 MarkContextDestroyedInArray(aChild, mTrackedRenderbuffers);
1986 MarkContextDestroyedInArray(aChild, mTrackedBuffers);
1987 MarkContextDestroyedInArray(aChild, mTrackedQueries);
1990 static void
1991 ReportArrayContents(const char *title, const nsTArray<GLContext::NamedResource>& aArray)
1993 if (aArray.Length() == 0)
1994 return;
1996 printf_stderr("%s:\n", title);
1998 nsTArray<GLContext::NamedResource> copy(aArray);
1999 copy.Sort();
2001 GLContext *lastContext = nullptr;
2002 for (uint32_t i = 0; i < copy.Length(); ++i) {
2003 if (lastContext != copy[i].origin) {
2004 if (lastContext)
2005 printf_stderr("\n");
2006 printf_stderr(" [%p - %s] ", copy[i].origin, copy[i].originDeleted ? "deleted" : "live");
2007 lastContext = copy[i].origin;
2009 printf_stderr("%d ", copy[i].name);
2011 printf_stderr("\n");
2014 void
2015 GLContext::ReportOutstandingNames()
2017 if (!DebugMode())
2018 return;
2020 printf_stderr("== GLContext %p Outstanding ==\n", this);
2022 ReportArrayContents("Outstanding Textures", mTrackedTextures);
2023 ReportArrayContents("Outstanding Buffers", mTrackedBuffers);
2024 ReportArrayContents("Outstanding Queries", mTrackedQueries);
2025 ReportArrayContents("Outstanding Programs", mTrackedPrograms);
2026 ReportArrayContents("Outstanding Shaders", mTrackedShaders);
2027 ReportArrayContents("Outstanding Framebuffers", mTrackedFramebuffers);
2028 ReportArrayContents("Outstanding Renderbuffers", mTrackedRenderbuffers);
2031 #endif /* DEBUG */
2034 void
2035 GLContext::GuaranteeResolve()
2037 if (mScreen) {
2038 mScreen->AssureBlitted();
2040 fFinish();
2043 const gfx::IntSize&
2044 GLContext::OffscreenSize() const
2046 MOZ_ASSERT(IsOffscreen());
2047 return mScreen->Size();
2050 bool
2051 GLContext::CreateScreenBufferImpl(const IntSize& size, const SurfaceCaps& caps)
2053 GLScreenBuffer* newScreen = GLScreenBuffer::Create(this, size, caps);
2054 if (!newScreen)
2055 return false;
2057 if (!newScreen->Resize(size)) {
2058 delete newScreen;
2059 return false;
2062 DestroyScreenBuffer();
2064 // This will rebind to 0 (Screen) if needed when
2065 // it falls out of scope.
2066 ScopedBindFramebuffer autoFB(this);
2068 mScreen = newScreen;
2070 return true;
2073 bool
2074 GLContext::ResizeScreenBuffer(const IntSize& size)
2076 if (!IsOffscreenSizeAllowed(size))
2077 return false;
2079 return mScreen->Resize(size);
2083 void
2084 GLContext::DestroyScreenBuffer()
2086 delete mScreen;
2087 mScreen = nullptr;
2090 void
2091 GLContext::ForceDirtyScreen()
2093 ScopedBindFramebuffer autoFB(0);
2095 BeforeGLDrawCall();
2096 // no-op; just pretend we did something
2097 AfterGLDrawCall();
2100 void
2101 GLContext::CleanDirtyScreen()
2103 ScopedBindFramebuffer autoFB(0);
2105 BeforeGLReadCall();
2106 // no-op; we just want to make sure the Read FBO is updated if it needs to be
2107 AfterGLReadCall();
2110 void
2111 GLContext::EmptyTexGarbageBin()
2113 TexGarbageBin()->EmptyGarbage();
2116 bool
2117 GLContext::IsOffscreenSizeAllowed(const IntSize& aSize) const {
2118 int32_t biggerDimension = std::max(aSize.width, aSize.height);
2119 int32_t maxAllowed = std::min(mMaxRenderbufferSize, mMaxTextureSize);
2120 return biggerDimension <= maxAllowed;
2123 bool
2124 GLContext::IsOwningThreadCurrent()
2126 return PlatformThread::CurrentId() == mOwningThreadId;
2129 GLBlitHelper*
2130 GLContext::BlitHelper()
2132 if (!mBlitHelper) {
2133 mBlitHelper = new GLBlitHelper(this);
2136 return mBlitHelper;
2139 GLBlitTextureImageHelper*
2140 GLContext::BlitTextureImageHelper()
2142 if (!mBlitTextureImageHelper) {
2143 mBlitTextureImageHelper = new GLBlitTextureImageHelper(this);
2146 return mBlitTextureImageHelper;
2149 GLReadTexImageHelper*
2150 GLContext::ReadTexImageHelper()
2152 if (!mReadTexImageHelper) {
2153 mReadTexImageHelper = new GLReadTexImageHelper(this);
2156 return mReadTexImageHelper;
2159 bool
2160 DoesStringMatch(const char* aString, const char *aWantedString)
2162 if (!aString || !aWantedString)
2163 return false;
2165 const char *occurrence = strstr(aString, aWantedString);
2167 // aWanted not found
2168 if (!occurrence)
2169 return false;
2171 // aWantedString preceded by alpha character
2172 if (occurrence != aString && isalpha(*(occurrence-1)))
2173 return false;
2175 // aWantedVendor followed by alpha character
2176 const char *afterOccurrence = occurrence + strlen(aWantedString);
2177 if (isalpha(*afterOccurrence))
2178 return false;
2180 return true;
2183 } /* namespace gl */
2184 } /* namespace mozilla */