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/. */
12 #include "GLContext.h"
13 #include "GLBlitHelper.h"
14 #include "GLBlitTextureImageHelper.h"
15 #include "GLReadTexImageHelper.h"
17 #include "gfxCrashReporterUtils.h"
19 #include "GLContextProvider.h"
20 #include "GLTextureImage.h"
21 #include "nsPrintfCString.h"
22 #include "nsThreadUtils.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"
33 #include "OGLShaderProgram.h" // for ShaderProgramType
35 #include "mozilla/DebugOnly.h"
38 #include <CoreServices/CoreServices.h>
42 #if defined(MOZ_WIDGET_COCOA)
43 #include "nsCocoaFeatures.h"
49 using namespace mozilla::gfx
;
50 using namespace mozilla::layers
;
53 unsigned GLContext::sCurrentGLContextTLS
= -1;
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",
68 "GL_EXT_texture_format_BGRA8888",
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",
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",
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",
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",
135 "GL_EXT_texture_sRGB",
136 "GL_ARB_framebuffer_sRGB",
137 "GL_EXT_framebuffer_sRGB",
139 "GL_ARB_half_float_pixel",
141 "GL_OES_compressed_ETC1_RGB8_texture",
142 "GL_EXT_draw_range_elements",
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.");
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.
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
&&
180 *version
= majorVersion
* 100 + minorVersion
* 10;
186 * We were not able to use GL_{MAJOR,MINOR}_VERSION, so we parse
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.
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");
219 } else if (!versionString
) {
220 MOZ_ASSERT(false, "glGetString(GL_VERSION) has returned 0");
224 const char kGLESVersionPrefix
[] = "OpenGL ES ";
225 if (strncmp(versionString
, kGLESVersionPrefix
, strlen(kGLESVersionPrefix
)) == 0) {
226 versionString
+= strlen(kGLESVersionPrefix
);
229 const char* itr
= versionString
;
231 int majorVersion
= (int)strtol(itr
, &end
, 10);
234 MOZ_ASSERT(false, "Failed to parse the GL major version number.");
236 } else if (*end
!= '.') {
237 MOZ_ASSERT(false, "Failed to parse GL's major-minor version number separator.");
241 // we skip the '.' between the major and the minor version
246 int minorVersion
= (int)strtol(itr
, &end
, 10);
248 MOZ_ASSERT(false, "Failed to parse GL's minor version number.");
252 if (majorVersion
<= 0 || majorVersion
>= 100) {
253 MOZ_ASSERT(false, "Invalid major version.");
255 } else if (minorVersion
< 0 || minorVersion
>= 10) {
256 MOZ_ASSERT(false, "Invalid minor version.");
260 *version
= (unsigned int)(majorVersion
* 100 + minorVersion
* 10);
264 GLContext::GLContext(const SurfaceCaps
& caps
,
265 GLContext
* sharedContext
,
267 : mInitialized(false),
268 mIsOffscreen(isOffscreen
),
271 mProfile(ContextProfile::Unknown
),
272 mVendor(GLVendor::Other
),
273 mRenderer(GLRenderer::Other
),
274 mHasRobustness(false),
276 mGLError(LOCAL_GL_NO_ERROR
),
278 mSharedContext(sharedContext
),
281 mLockedSurface(nullptr),
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!");
295 if (mSharedContext
) {
296 GLContext
*tip
= mSharedContext
;
297 while (tip
->mSharedContext
)
298 tip
= tip
->mSharedContext
;
299 tip
->SharedContextDestroyed(this);
300 tip
->ReportOutstandingNames();
302 ReportOutstandingNames();
308 GLContext::StaticDebugCallback(GLenum source
,
313 const GLchar
* message
,
314 const GLvoid
* userParam
)
316 GLContext
* gl
= (GLContext
*)userParam
;
317 gl
->DebugCallback(source
, type
, id
, severity
, length
, message
);
321 GLContext::InitWithPrefix(const char *prefix
, bool trygl
)
323 ScopedGfxFeatureReporter
reporter("GL Context");
326 reporter
.SetSuccessful();
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
);
480 unsigned int version
= 0;
482 ParseGLVersion(this, &version
);
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
));
490 if (version
>= mVersion
) {
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.
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;
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;
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
);
552 mInitialized
= false;
554 const char *vendorMatchStrings
[size_t(GLVendor::Other
)] = {
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
);
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
)] = {
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
);
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
;
619 static bool firstRun
= true;
620 if (firstRun
&& DebugMode()) {
621 const char *vendors
[size_t(GLVendor::Other
)] = {
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
)]);
633 printf_stderr("OpenGL vendor ('%s') unrecognized\n", glVendorString
);
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
) {
650 MarkUnsupported(GLFeature::standard_derivatives
);
653 if (Vendor() == GLVendor::Imagination
&&
654 Renderer() == GLRenderer::SGX540
) {
656 MarkExtensionUnsupported(OES_EGL_sync
);
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
);
669 // ANGLE's divisor support is busted. (see bug 916816)
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;
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;
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
,
725 "BlitFramebufferEXT",
726 "BlitFramebufferANGLE",
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",
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",
870 { (PRFuncPtr
*) &mSymbols
.fDrawElementsInstanced
,
871 { "DrawElementsInstanced",
872 "DrawElementsInstancedARB",
873 "DrawElementsInstancedEXT",
874 "DrawElementsInstancedNV",
875 "DrawElementsInstancedANGLE",
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",
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
,
921 { (PRFuncPtr
*) &mSymbols
.fBindBufferRange
,
923 "BindBufferRangeEXT",
928 { (PRFuncPtr
*) &mSymbols
.fBeginTransformFeedback
,
929 { "BeginTransformFeedback",
930 "BeginTransformFeedbackEXT",
931 "BeginTransformFeedbackNV",
935 { (PRFuncPtr
*) &mSymbols
.fEndTransformFeedback
,
936 { "EndTransformFeedback",
937 "EndTransformFeedbackEXT",
938 "EndTransformFeedbackNV",
942 { (PRFuncPtr
*) &mSymbols
.fTransformFeedbackVaryings
,
943 { "TransformFeedbackVaryings",
944 "TransformFeedbackVaryingsEXT",
945 "TransformFeedbackVaryingsNV",
949 { (PRFuncPtr
*) &mSymbols
.fGetTransformFeedbackVarying
,
950 { "GetTransformFeedbackVarying",
951 "GetTransformFeedbackVaryingEXT",
952 "GetTransformFeedbackVaryingNV",
956 { (PRFuncPtr
*) &mSymbols
.fGetIntegeri_v
,
958 "GetIntegerIndexedvEXT",
959 "GetIntegerIndexedvNV",
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",
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
);
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
);
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);
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;
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;
1159 mMaxTextureImageSize
= mMaxTextureSize
;
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);
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
,
1190 reporter
.SetSuccessful();
1192 // if initialization fails, ensure all symbols are zero, to avoid hard-to-understand bugs
1194 NS_WARNING("InitWithPrefix failed!");
1197 mVersionString
= nsPrintfCString("%u.%u.%u", mVersion
/ 100, (mVersion
/ 10) % 10, mVersion
% 10);
1199 return mInitialized
;
1203 GLContext::DebugCallback(GLenum source
,
1208 const GLchar
* message
)
1210 nsAutoCString sourceStr
;
1212 case LOCAL_GL_DEBUG_SOURCE_API
:
1213 sourceStr
= NS_LITERAL_CSTRING("SOURCE_API");
1215 case LOCAL_GL_DEBUG_SOURCE_WINDOW_SYSTEM
:
1216 sourceStr
= NS_LITERAL_CSTRING("SOURCE_WINDOW_SYSTEM");
1218 case LOCAL_GL_DEBUG_SOURCE_SHADER_COMPILER
:
1219 sourceStr
= NS_LITERAL_CSTRING("SOURCE_SHADER_COMPILER");
1221 case LOCAL_GL_DEBUG_SOURCE_THIRD_PARTY
:
1222 sourceStr
= NS_LITERAL_CSTRING("SOURCE_THIRD_PARTY");
1224 case LOCAL_GL_DEBUG_SOURCE_APPLICATION
:
1225 sourceStr
= NS_LITERAL_CSTRING("SOURCE_APPLICATION");
1227 case LOCAL_GL_DEBUG_SOURCE_OTHER
:
1228 sourceStr
= NS_LITERAL_CSTRING("SOURCE_OTHER");
1231 sourceStr
= nsPrintfCString("<source 0x%04x>", source
);
1235 nsAutoCString typeStr
;
1237 case LOCAL_GL_DEBUG_TYPE_ERROR
:
1238 typeStr
= NS_LITERAL_CSTRING("TYPE_ERROR");
1240 case LOCAL_GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR
:
1241 typeStr
= NS_LITERAL_CSTRING("TYPE_DEPRECATED_BEHAVIOR");
1243 case LOCAL_GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR
:
1244 typeStr
= NS_LITERAL_CSTRING("TYPE_UNDEFINED_BEHAVIOR");
1246 case LOCAL_GL_DEBUG_TYPE_PORTABILITY
:
1247 typeStr
= NS_LITERAL_CSTRING("TYPE_PORTABILITY");
1249 case LOCAL_GL_DEBUG_TYPE_PERFORMANCE
:
1250 typeStr
= NS_LITERAL_CSTRING("TYPE_PERFORMANCE");
1252 case LOCAL_GL_DEBUG_TYPE_OTHER
:
1253 typeStr
= NS_LITERAL_CSTRING("TYPE_OTHER");
1255 case LOCAL_GL_DEBUG_TYPE_MARKER
:
1256 typeStr
= NS_LITERAL_CSTRING("TYPE_MARKER");
1259 typeStr
= nsPrintfCString("<type 0x%04x>", type
);
1263 nsAutoCString sevStr
;
1265 case LOCAL_GL_DEBUG_SEVERITY_HIGH
:
1266 sevStr
= NS_LITERAL_CSTRING("SEVERITY_HIGH");
1268 case LOCAL_GL_DEBUG_SEVERITY_MEDIUM
:
1269 sevStr
= NS_LITERAL_CSTRING("SEVERITY_MEDIUM");
1271 case LOCAL_GL_DEBUG_SEVERITY_LOW
:
1272 sevStr
= NS_LITERAL_CSTRING("SEVERITY_LOW");
1274 case LOCAL_GL_DEBUG_SEVERITY_NOTIFICATION
:
1275 sevStr
= NS_LITERAL_CSTRING("SEVERITY_NOTIFICATION");
1278 sevStr
= nsPrintfCString("<severity 0x%04x>", severity
);
1282 printf_stderr("[KHR_debug: 0x%x] ID %u: %s %s %s:\n %s",
1285 sourceStr
.BeginReading(),
1286 typeStr
.BeginReading(),
1287 sevStr
.BeginReading(),
1292 GLContext::InitExtensions()
1295 const char* extensions
= (const char*)fGetString(LOCAL_GL_EXTENSIONS
);
1300 static bool firstRun
= true;
1302 // Non-DEBUG, so never spew.
1303 const bool firstRun
= false;
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.
1330 MarkExtensionUnsupported(EXT_texture_compression_s3tc
);
1331 MarkExtensionUnsupported(EXT_texture_compression_dxt1
);
1332 MarkExtensionUnsupported(ANGLE_texture_compression_dxt3
);
1333 MarkExtensionUnsupported(ANGLE_texture_compression_dxt5
);
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
);
1356 GLContext::PlatformStartup()
1358 RegisterStrongMemoryReporter(new GfxTexturesReporter());
1361 // Common code for checking for both GL extensions and GLX extensions.
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)
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')
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,
1384 where
= (GLubyte
*) strstr((const char *) start
, extension
);
1388 terminator
= where
+ strlen(extension
);
1389 if (where
== start
|| *(where
- 1) == ' ') {
1390 if (*terminator
== ' ' || *terminator
== '\0') {
1400 GLContext::DetermineCaps()
1402 PixelBufferFormat format
= QueryPixelFormat();
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;
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
);
1437 GLContext::UpdatePixelFormat()
1439 PixelBufferFormat format
= QueryPixelFormat();
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));
1457 mPixelFormat
= new PixelBufferFormat(format
);
1461 GLContext::ChooseGLFormats(const SurfaceCaps
& caps
) const
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
;
1469 if (!IsExtensionSupported(OES_rgb8_rgba8
))
1472 // RGB565 is uncommon on desktop, requiring ARB_ES2_compatibility.
1473 // Since it's also vanishingly useless there, let's not support it.
1478 MOZ_ASSERT(IsGLES());
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
;
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
;
1491 formats
.color_texType
= LOCAL_GL_UNSIGNED_BYTE
;
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
;
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
);
1509 if (WorkAroundDriverBugs() && samples
== 1) {
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
;
1523 if (IsExtensionSupported(OES_depth24
)) {
1524 formats
.depth
= LOCAL_GL_DEPTH_COMPONENT24
;
1526 formats
.depth
= LOCAL_GL_DEPTH_COMPONENT16
;
1529 formats
.depth
= LOCAL_GL_DEPTH_COMPONENT24
;
1532 formats
.stencil
= LOCAL_GL_STENCIL_INDEX8
;
1538 GLContext::IsFramebufferComplete(GLuint fb
, GLenum
* pStatus
)
1542 ScopedBindFramebuffer
autoFB(this, fb
);
1543 MOZ_ASSERT(fIsFramebuffer(fb
));
1545 GLenum status
= fCheckFramebufferStatus(LOCAL_GL_FRAMEBUFFER
);
1549 return status
== LOCAL_GL_FRAMEBUFFER_COMPLETE
;
1553 GLContext::AttachBuffersToFB(GLuint colorTex
, GLuint colorRB
,
1554 GLuint depthRB
, GLuint stencilRB
,
1555 GLuint fb
, GLenum target
)
1558 MOZ_ASSERT( !(colorTex
&& colorRB
) );
1560 ScopedBindFramebuffer
autoFB(this, fb
);
1561 MOZ_ASSERT(fIsFramebuffer(fb
)); // It only counts after being bound.
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
,
1572 } else if (colorRB
) {
1573 MOZ_ASSERT(fIsRenderbuffer(colorRB
));
1574 fFramebufferRenderbuffer(LOCAL_GL_FRAMEBUFFER
,
1575 LOCAL_GL_COLOR_ATTACHMENT0
,
1576 LOCAL_GL_RENDERBUFFER
,
1581 MOZ_ASSERT(fIsRenderbuffer(depthRB
));
1582 fFramebufferRenderbuffer(LOCAL_GL_FRAMEBUFFER
,
1583 LOCAL_GL_DEPTH_ATTACHMENT
,
1584 LOCAL_GL_RENDERBUFFER
,
1589 MOZ_ASSERT(fIsRenderbuffer(stencilRB
));
1590 fFramebufferRenderbuffer(LOCAL_GL_FRAMEBUFFER
,
1591 LOCAL_GL_STENCIL_ATTACHMENT
,
1592 LOCAL_GL_RENDERBUFFER
,
1598 GLContext::AssembleOffscreenFBs(const GLuint colorMSRB
,
1599 const GLuint depthRB
,
1600 const GLuint stencilRB
,
1601 const GLuint texture
,
1605 if (!colorMSRB
&& !texture
) {
1606 MOZ_ASSERT(!depthRB
&& !stencilRB
);
1616 ScopedBindFramebuffer
autoFB(this);
1623 fGenFramebuffers(1, &readFB
);
1625 fFramebufferTexture2D(LOCAL_GL_FRAMEBUFFER
,
1626 LOCAL_GL_COLOR_ATTACHMENT0
,
1627 LOCAL_GL_TEXTURE_2D
,
1634 fGenFramebuffers(1, &drawFB
);
1636 fFramebufferRenderbuffer(LOCAL_GL_FRAMEBUFFER
,
1637 LOCAL_GL_COLOR_ATTACHMENT0
,
1638 LOCAL_GL_RENDERBUFFER
,
1643 MOZ_ASSERT(GetFB() == drawFB
);
1646 fFramebufferRenderbuffer(LOCAL_GL_FRAMEBUFFER
,
1647 LOCAL_GL_DEPTH_ATTACHMENT
,
1648 LOCAL_GL_RENDERBUFFER
,
1653 fFramebufferRenderbuffer(LOCAL_GL_FRAMEBUFFER
,
1654 LOCAL_GL_STENCIL_ATTACHMENT
,
1655 LOCAL_GL_RENDERBUFFER
,
1659 // We should be all resized. Check for framebuffer completeness.
1661 bool isComplete
= true;
1663 if (!IsFramebufferComplete(drawFB
, &status
)) {
1664 NS_WARNING("DrawFBO: Incomplete");
1667 printf_stderr("Framebuffer status: %X\n", status
);
1673 if (!IsFramebufferComplete(readFB
, &status
)) {
1674 NS_WARNING("ReadFBO: Incomplete");
1677 printf_stderr("Framebuffer status: %X\n", status
);
1684 *drawFB_out
= drawFB
;
1685 } else if (drawFB
) {
1686 NS_RUNTIMEABORT("drawFB created when not requested!");
1690 *readFB_out
= readFB
;
1691 } else if (readFB
) {
1692 NS_RUNTIMEABORT("readFB created when not requested!");
1701 GLContext::PublishFrame()
1703 MOZ_ASSERT(mScreen
);
1705 if (!mScreen
->PublishFrame(OffscreenSize()))
1712 GLContext::RequestFrame()
1714 MOZ_ASSERT(mScreen
);
1716 SharedSurface
* ret
= mScreen
->Stream()->SwapConsumer();
1720 return SharedSurface_GL::Cast(ret
);
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
);
1767 fStencilMask(0xffffffff);
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],
1780 fClearColor(colorClearValue
[0],
1783 colorClearValue
[3]);
1785 fDepthMask(depthWriteMask
);
1786 fClearDepth(depthClearValue
);
1788 fStencilMaskSeparate(LOCAL_GL_FRONT
, stencilWriteMaskFront
);
1789 fStencilMaskSeparate(LOCAL_GL_BACK
, stencilWriteMaskBack
);
1790 fClearStencil(stencilClearValue
);
1793 fEnable(LOCAL_GL_DITHER
);
1795 fDisable(LOCAL_GL_DITHER
);
1797 if (scissorTestEnabled
)
1798 fEnable(LOCAL_GL_SCISSOR_TEST
);
1800 fDisable(LOCAL_GL_SCISSOR_TEST
);
1805 GLContext::MarkDestroyed()
1810 if (MakeCurrent()) {
1811 DestroyScreenBuffer();
1813 mBlitHelper
= nullptr;
1814 mBlitTextureImageHelper
= nullptr;
1815 mReadTexImageHelper
= nullptr;
1817 mTexGarbageBin
->GLContextTeardown();
1819 NS_WARNING("MakeCurrent() failed during MarkDestroyed! Skipping GL object teardown.");
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.");
1858 GLContext::CreatedProgram(GLContext
*aOrigin
, GLuint aName
)
1860 mTrackedPrograms
.AppendElement(NamedResource(aOrigin
, aName
));
1864 GLContext::CreatedShader(GLContext
*aOrigin
, GLuint aName
)
1866 mTrackedShaders
.AppendElement(NamedResource(aOrigin
, aName
));
1870 GLContext::CreatedBuffers(GLContext
*aOrigin
, GLsizei aCount
, GLuint
*aNames
)
1872 for (GLsizei i
= 0; i
< aCount
; ++i
) {
1873 mTrackedBuffers
.AppendElement(NamedResource(aOrigin
, aNames
[i
]));
1878 GLContext::CreatedQueries(GLContext
*aOrigin
, GLsizei aCount
, GLuint
*aNames
)
1880 for (GLsizei i
= 0; i
< aCount
; ++i
) {
1881 mTrackedQueries
.AppendElement(NamedResource(aOrigin
, aNames
[i
]));
1886 GLContext::CreatedTextures(GLContext
*aOrigin
, GLsizei aCount
, GLuint
*aNames
)
1888 for (GLsizei i
= 0; i
< aCount
; ++i
) {
1889 mTrackedTextures
.AppendElement(NamedResource(aOrigin
, aNames
[i
]));
1894 GLContext::CreatedFramebuffers(GLContext
*aOrigin
, GLsizei aCount
, GLuint
*aNames
)
1896 for (GLsizei i
= 0; i
< aCount
; ++i
) {
1897 mTrackedFramebuffers
.AppendElement(NamedResource(aOrigin
, aNames
[i
]));
1902 GLContext::CreatedRenderbuffers(GLContext
*aOrigin
, GLsizei aCount
, GLuint
*aNames
)
1904 for (GLsizei i
= 0; i
< aCount
; ++i
) {
1905 mTrackedRenderbuffers
.AppendElement(NamedResource(aOrigin
, aNames
[i
]));
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
1918 for (uint32_t i
= 0; i
< aArray
.Length(); ++i
) {
1919 if (aArray
[i
].name
== name
) {
1920 aArray
.RemoveElementAt(i
);
1928 GLContext::DeletedProgram(GLContext
*aOrigin
, GLuint aName
)
1930 RemoveNamesFromArray(aOrigin
, 1, &aName
, mTrackedPrograms
);
1934 GLContext::DeletedShader(GLContext
*aOrigin
, GLuint aName
)
1936 RemoveNamesFromArray(aOrigin
, 1, &aName
, mTrackedShaders
);
1940 GLContext::DeletedBuffers(GLContext
*aOrigin
, GLsizei aCount
, const GLuint
*aNames
)
1942 RemoveNamesFromArray(aOrigin
, aCount
, aNames
, mTrackedBuffers
);
1946 GLContext::DeletedQueries(GLContext
*aOrigin
, GLsizei aCount
, const GLuint
*aNames
)
1948 RemoveNamesFromArray(aOrigin
, aCount
, aNames
, mTrackedQueries
);
1952 GLContext::DeletedTextures(GLContext
*aOrigin
, GLsizei aCount
, const GLuint
*aNames
)
1954 RemoveNamesFromArray(aOrigin
, aCount
, aNames
, mTrackedTextures
);
1958 GLContext::DeletedFramebuffers(GLContext
*aOrigin
, GLsizei aCount
, const GLuint
*aNames
)
1960 RemoveNamesFromArray(aOrigin
, aCount
, aNames
, mTrackedFramebuffers
);
1964 GLContext::DeletedRenderbuffers(GLContext
*aOrigin
, GLsizei aCount
, const GLuint
*aNames
)
1966 RemoveNamesFromArray(aOrigin
, aCount
, aNames
, mTrackedRenderbuffers
);
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;
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
);
1991 ReportArrayContents(const char *title
, const nsTArray
<GLContext::NamedResource
>& aArray
)
1993 if (aArray
.Length() == 0)
1996 printf_stderr("%s:\n", title
);
1998 nsTArray
<GLContext::NamedResource
> copy(aArray
);
2001 GLContext
*lastContext
= nullptr;
2002 for (uint32_t i
= 0; i
< copy
.Length(); ++i
) {
2003 if (lastContext
!= copy
[i
].origin
) {
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");
2015 GLContext::ReportOutstandingNames()
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
);
2035 GLContext::GuaranteeResolve()
2038 mScreen
->AssureBlitted();
2044 GLContext::OffscreenSize() const
2046 MOZ_ASSERT(IsOffscreen());
2047 return mScreen
->Size();
2051 GLContext::CreateScreenBufferImpl(const IntSize
& size
, const SurfaceCaps
& caps
)
2053 GLScreenBuffer
* newScreen
= GLScreenBuffer::Create(this, size
, caps
);
2057 if (!newScreen
->Resize(size
)) {
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
;
2074 GLContext::ResizeScreenBuffer(const IntSize
& size
)
2076 if (!IsOffscreenSizeAllowed(size
))
2079 return mScreen
->Resize(size
);
2084 GLContext::DestroyScreenBuffer()
2091 GLContext::ForceDirtyScreen()
2093 ScopedBindFramebuffer
autoFB(0);
2096 // no-op; just pretend we did something
2101 GLContext::CleanDirtyScreen()
2103 ScopedBindFramebuffer
autoFB(0);
2106 // no-op; we just want to make sure the Read FBO is updated if it needs to be
2111 GLContext::EmptyTexGarbageBin()
2113 TexGarbageBin()->EmptyGarbage();
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
;
2124 GLContext::IsOwningThreadCurrent()
2126 return PlatformThread::CurrentId() == mOwningThreadId
;
2130 GLContext::BlitHelper()
2133 mBlitHelper
= new GLBlitHelper(this);
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
;
2160 DoesStringMatch(const char* aString
, const char *aWantedString
)
2162 if (!aString
|| !aWantedString
)
2165 const char *occurrence
= strstr(aString
, aWantedString
);
2167 // aWanted not found
2171 // aWantedString preceded by alpha character
2172 if (occurrence
!= aString
&& isalpha(*(occurrence
-1)))
2175 // aWantedVendor followed by alpha character
2176 const char *afterOccurrence
= occurrence
+ strlen(aWantedString
);
2177 if (isalpha(*afterOccurrence
))
2183 } /* namespace gl */
2184 } /* namespace mozilla */