gfx/gl/GLContext.cpp

branch
TOR_BUG_9701
changeset 15
b8a032363ba2
equal deleted inserted replaced
-1:000000000000 0:26c5a4b31368
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /* vim: set ts=8 sts=4 et sw=4 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6
7 #include <algorithm>
8 #include <stdio.h>
9 #include <string.h>
10 #include <ctype.h>
11
12 #include "GLContext.h"
13 #include "GLBlitHelper.h"
14 #include "GLBlitTextureImageHelper.h"
15 #include "GLReadTexImageHelper.h"
16
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"
32
33 #include "OGLShaderProgram.h" // for ShaderProgramType
34
35 #include "mozilla/DebugOnly.h"
36
37 #ifdef XP_MACOSX
38 #include <CoreServices/CoreServices.h>
39 #include "gfxColor.h"
40 #endif
41
42 #if defined(MOZ_WIDGET_COCOA)
43 #include "nsCocoaFeatures.h"
44 #endif
45
46 using namespace mozilla::gfx;
47 using namespace mozilla::layers;
48
49 namespace mozilla {
50 namespace gl {
51
52 #ifdef DEBUG
53 unsigned GLContext::sCurrentGLContextTLS = -1;
54 #endif
55
56 uint32_t GLContext::sDebugMode = 0;
57
58
59 #define MAX_SYMBOL_LENGTH 128
60 #define MAX_SYMBOL_NAMES 5
61
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_ARB_depth_texture",
74 "GL_OES_depth_texture",
75 "GL_OES_packed_depth_stencil",
76 "GL_IMG_read_format",
77 "GL_EXT_read_format_bgra",
78 "GL_APPLE_client_storage",
79 "GL_APPLE_texture_range",
80 "GL_ARB_texture_non_power_of_two",
81 "GL_ARB_pixel_buffer_object",
82 "GL_ARB_ES2_compatibility",
83 "GL_ARB_ES3_compatibility",
84 "GL_OES_texture_float",
85 "GL_OES_texture_float_linear",
86 "GL_ARB_texture_float",
87 "GL_OES_texture_half_float",
88 "GL_OES_texture_half_float_linear",
89 "GL_NV_half_float",
90 "GL_EXT_color_buffer_float",
91 "GL_EXT_color_buffer_half_float",
92 "GL_ARB_color_buffer_float",
93 "GL_EXT_unpack_subimage",
94 "GL_OES_standard_derivatives",
95 "GL_EXT_texture_filter_anisotropic",
96 "GL_EXT_texture_compression_s3tc",
97 "GL_EXT_texture_compression_dxt1",
98 "GL_ANGLE_texture_compression_dxt3",
99 "GL_ANGLE_texture_compression_dxt5",
100 "GL_AMD_compressed_ATC_texture",
101 "GL_IMG_texture_compression_pvrtc",
102 "GL_EXT_framebuffer_blit",
103 "GL_ANGLE_framebuffer_blit",
104 "GL_EXT_framebuffer_multisample",
105 "GL_ANGLE_framebuffer_multisample",
106 "GL_OES_rgb8_rgba8",
107 "GL_ARB_robustness",
108 "GL_EXT_robustness",
109 "GL_ARB_sync",
110 "GL_OES_EGL_image",
111 "GL_OES_EGL_sync",
112 "GL_OES_EGL_image_external",
113 "GL_EXT_packed_depth_stencil",
114 "GL_OES_element_index_uint",
115 "GL_OES_vertex_array_object",
116 "GL_ARB_vertex_array_object",
117 "GL_APPLE_vertex_array_object",
118 "GL_ARB_draw_buffers",
119 "GL_EXT_draw_buffers",
120 "GL_EXT_gpu_shader4",
121 "GL_EXT_blend_minmax",
122 "GL_ARB_draw_instanced",
123 "GL_EXT_draw_instanced",
124 "GL_NV_draw_instanced",
125 "GL_ARB_instanced_arrays",
126 "GL_NV_instanced_arrays",
127 "GL_ANGLE_instanced_arrays",
128 "GL_EXT_occlusion_query_boolean",
129 "GL_ARB_occlusion_query2",
130 "GL_EXT_transform_feedback",
131 "GL_NV_transform_feedback",
132 "GL_ANGLE_depth_texture",
133 "GL_EXT_sRGB",
134 "GL_EXT_texture_sRGB",
135 "GL_ARB_framebuffer_sRGB",
136 "GL_EXT_framebuffer_sRGB",
137 "GL_KHR_debug",
138 "GL_ARB_half_float_pixel",
139 "GL_EXT_frag_depth",
140 "GL_OES_compressed_ETC1_RGB8_texture",
141 "GL_EXT_draw_range_elements",
142 nullptr
143 };
144
145 static bool
146 ParseGLVersion(GLContext* gl, unsigned int* version)
147 {
148 GLenum error = gl->fGetError();
149 if (error != LOCAL_GL_NO_ERROR) {
150 MOZ_ASSERT(false, "An OpenGL error has been triggered before.");
151 return false;
152 }
153
154 /**
155 * B2G emulator bug work around: The emulator implements OpenGL ES 2.0 on
156 * OpenGL 3.2. The bug is that GetIntegerv(LOCAL_GL_{MAJOR,MINOR}_VERSION)
157 * returns OpenGL 3.2 instead of generating an error.
158 */
159 if (!gl->IsGLES())
160 {
161 /**
162 * OpenGL 3.1 and OpenGL ES 3.0 both introduce GL_{MAJOR,MINOR}_VERSION
163 * with GetIntegerv. So we first try those constants even though we
164 * might not have an OpenGL context supporting them, has this is a
165 * better way than parsing GL_VERSION.
166 */
167 GLint majorVersion = 0;
168 GLint minorVersion = 0;
169
170 gl->fGetIntegerv(LOCAL_GL_MAJOR_VERSION, &majorVersion);
171 gl->fGetIntegerv(LOCAL_GL_MINOR_VERSION, &minorVersion);
172
173 // If it's not an OpenGL (ES) 3.0 context, we will have an error
174 error = gl->fGetError();
175 if (error == LOCAL_GL_NO_ERROR &&
176 majorVersion > 0 &&
177 minorVersion >= 0)
178 {
179 *version = majorVersion * 100 + minorVersion * 10;
180 return true;
181 }
182 }
183
184 /**
185 * We were not able to use GL_{MAJOR,MINOR}_VERSION, so we parse
186 * GL_VERSION.
187 *
188 *
189 * OpenGL 2.x, 3.x, 4.x specifications:
190 * The VERSION and SHADING_LANGUAGE_VERSION strings are laid out as follows:
191 *
192 * <version number><space><vendor-specific information>
193 *
194 * The version number is either of the form major_number.minor_number or
195 * major_number.minor_number.release_number, where the numbers all have
196 * one or more digits.
197 *
198 *
199 * OpenGL ES 2.0, 3.0 specifications:
200 * The VERSION string is laid out as follows:
201 *
202 * "OpenGL ES N.M vendor-specific information"
203 *
204 * The version number is either of the form major_number.minor_number or
205 * major_number.minor_number.release_number, where the numbers all have
206 * one or more digits.
207 *
208 *
209 * Note:
210 * We don't care about release_number.
211 */
212 const char* versionString = (const char*)gl->fGetString(LOCAL_GL_VERSION);
213
214 error = gl->fGetError();
215 if (error != LOCAL_GL_NO_ERROR) {
216 MOZ_ASSERT(false, "glGetString(GL_VERSION) has generated an error");
217 return false;
218 } else if (!versionString) {
219 MOZ_ASSERT(false, "glGetString(GL_VERSION) has returned 0");
220 return false;
221 }
222
223 const char kGLESVersionPrefix[] = "OpenGL ES ";
224 if (strncmp(versionString, kGLESVersionPrefix, strlen(kGLESVersionPrefix)) == 0) {
225 versionString += strlen(kGLESVersionPrefix);
226 }
227
228 const char* itr = versionString;
229 char* end = nullptr;
230 int majorVersion = (int)strtol(itr, &end, 10);
231
232 if (!end) {
233 MOZ_ASSERT(false, "Failed to parse the GL major version number.");
234 return false;
235 } else if (*end != '.') {
236 MOZ_ASSERT(false, "Failed to parse GL's major-minor version number separator.");
237 return false;
238 }
239
240 // we skip the '.' between the major and the minor version
241 itr = end + 1;
242
243 end = nullptr;
244
245 int minorVersion = (int)strtol(itr, &end, 10);
246 if (!end) {
247 MOZ_ASSERT(false, "Failed to parse GL's minor version number.");
248 return false;
249 }
250
251 if (majorVersion <= 0 || majorVersion >= 100) {
252 MOZ_ASSERT(false, "Invalid major version.");
253 return false;
254 } else if (minorVersion < 0 || minorVersion >= 10) {
255 MOZ_ASSERT(false, "Invalid minor version.");
256 return false;
257 }
258
259 *version = (unsigned int)(majorVersion * 100 + minorVersion * 10);
260 return true;
261 }
262
263 GLContext::GLContext(const SurfaceCaps& caps,
264 GLContext* sharedContext,
265 bool isOffscreen)
266 : mInitialized(false),
267 mIsOffscreen(isOffscreen),
268 mContextLost(false),
269 mVersion(0),
270 mProfile(ContextProfile::Unknown),
271 mVendor(GLVendor::Other),
272 mRenderer(GLRenderer::Other),
273 mHasRobustness(false),
274 #ifdef DEBUG
275 mGLError(LOCAL_GL_NO_ERROR),
276 #endif
277 mSharedContext(sharedContext),
278 mCaps(caps),
279 mScreen(nullptr),
280 mLockedSurface(nullptr),
281 mMaxTextureSize(0),
282 mMaxCubeMapTextureSize(0),
283 mMaxTextureImageSize(0),
284 mMaxRenderbufferSize(0),
285 mNeedsTextureSizeChecks(false),
286 mWorkAroundDriverBugs(true)
287 {
288 mOwningThread = NS_GetCurrentThread();
289 }
290
291 GLContext::~GLContext() {
292 NS_ASSERTION(IsDestroyed(), "GLContext implementation must call MarkDestroyed in destructor!");
293 #ifdef DEBUG
294 if (mSharedContext) {
295 GLContext *tip = mSharedContext;
296 while (tip->mSharedContext)
297 tip = tip->mSharedContext;
298 tip->SharedContextDestroyed(this);
299 tip->ReportOutstandingNames();
300 } else {
301 ReportOutstandingNames();
302 }
303 #endif
304 }
305
306 bool
307 GLContext::InitWithPrefix(const char *prefix, bool trygl)
308 {
309 ScopedGfxFeatureReporter reporter("GL Context");
310
311 if (mInitialized) {
312 reporter.SetSuccessful();
313 return true;
314 }
315
316 mWorkAroundDriverBugs = gfxPrefs::WorkAroundDriverBugs();
317
318 SymLoadStruct symbols[] = {
319 { (PRFuncPtr*) &mSymbols.fActiveTexture, { "ActiveTexture", "ActiveTextureARB", nullptr } },
320 { (PRFuncPtr*) &mSymbols.fAttachShader, { "AttachShader", "AttachShaderARB", nullptr } },
321 { (PRFuncPtr*) &mSymbols.fBindAttribLocation, { "BindAttribLocation", "BindAttribLocationARB", nullptr } },
322 { (PRFuncPtr*) &mSymbols.fBindBuffer, { "BindBuffer", "BindBufferARB", nullptr } },
323 { (PRFuncPtr*) &mSymbols.fBindTexture, { "BindTexture", "BindTextureARB", nullptr } },
324 { (PRFuncPtr*) &mSymbols.fBlendColor, { "BlendColor", nullptr } },
325 { (PRFuncPtr*) &mSymbols.fBlendEquation, { "BlendEquation", nullptr } },
326 { (PRFuncPtr*) &mSymbols.fBlendEquationSeparate, { "BlendEquationSeparate", "BlendEquationSeparateEXT", nullptr } },
327 { (PRFuncPtr*) &mSymbols.fBlendFunc, { "BlendFunc", nullptr } },
328 { (PRFuncPtr*) &mSymbols.fBlendFuncSeparate, { "BlendFuncSeparate", "BlendFuncSeparateEXT", nullptr } },
329 { (PRFuncPtr*) &mSymbols.fBufferData, { "BufferData", nullptr } },
330 { (PRFuncPtr*) &mSymbols.fBufferSubData, { "BufferSubData", nullptr } },
331 { (PRFuncPtr*) &mSymbols.fClear, { "Clear", nullptr } },
332 { (PRFuncPtr*) &mSymbols.fClearColor, { "ClearColor", nullptr } },
333 { (PRFuncPtr*) &mSymbols.fClearStencil, { "ClearStencil", nullptr } },
334 { (PRFuncPtr*) &mSymbols.fColorMask, { "ColorMask", nullptr } },
335 { (PRFuncPtr*) &mSymbols.fCompressedTexImage2D, {"CompressedTexImage2D", nullptr} },
336 { (PRFuncPtr*) &mSymbols.fCompressedTexSubImage2D, {"CompressedTexSubImage2D", nullptr} },
337 { (PRFuncPtr*) &mSymbols.fCullFace, { "CullFace", nullptr } },
338 { (PRFuncPtr*) &mSymbols.fDetachShader, { "DetachShader", "DetachShaderARB", nullptr } },
339 { (PRFuncPtr*) &mSymbols.fDepthFunc, { "DepthFunc", nullptr } },
340 { (PRFuncPtr*) &mSymbols.fDepthMask, { "DepthMask", nullptr } },
341 { (PRFuncPtr*) &mSymbols.fDisable, { "Disable", nullptr } },
342 { (PRFuncPtr*) &mSymbols.fDisableVertexAttribArray, { "DisableVertexAttribArray", "DisableVertexAttribArrayARB", nullptr } },
343 { (PRFuncPtr*) &mSymbols.fDrawArrays, { "DrawArrays", nullptr } },
344 { (PRFuncPtr*) &mSymbols.fDrawElements, { "DrawElements", nullptr } },
345 { (PRFuncPtr*) &mSymbols.fEnable, { "Enable", nullptr } },
346 { (PRFuncPtr*) &mSymbols.fEnableVertexAttribArray, { "EnableVertexAttribArray", "EnableVertexAttribArrayARB", nullptr } },
347 { (PRFuncPtr*) &mSymbols.fFinish, { "Finish", nullptr } },
348 { (PRFuncPtr*) &mSymbols.fFlush, { "Flush", nullptr } },
349 { (PRFuncPtr*) &mSymbols.fFrontFace, { "FrontFace", nullptr } },
350 { (PRFuncPtr*) &mSymbols.fGetActiveAttrib, { "GetActiveAttrib", "GetActiveAttribARB", nullptr } },
351 { (PRFuncPtr*) &mSymbols.fGetActiveUniform, { "GetActiveUniform", "GetActiveUniformARB", nullptr } },
352 { (PRFuncPtr*) &mSymbols.fGetAttachedShaders, { "GetAttachedShaders", "GetAttachedShadersARB", nullptr } },
353 { (PRFuncPtr*) &mSymbols.fGetAttribLocation, { "GetAttribLocation", "GetAttribLocationARB", nullptr } },
354 { (PRFuncPtr*) &mSymbols.fGetIntegerv, { "GetIntegerv", nullptr } },
355 { (PRFuncPtr*) &mSymbols.fGetFloatv, { "GetFloatv", nullptr } },
356 { (PRFuncPtr*) &mSymbols.fGetBooleanv, { "GetBooleanv", nullptr } },
357 { (PRFuncPtr*) &mSymbols.fGetBufferParameteriv, { "GetBufferParameteriv", "GetBufferParameterivARB", nullptr } },
358 { (PRFuncPtr*) &mSymbols.fGetError, { "GetError", nullptr } },
359 { (PRFuncPtr*) &mSymbols.fGetProgramiv, { "GetProgramiv", "GetProgramivARB", nullptr } },
360 { (PRFuncPtr*) &mSymbols.fGetProgramInfoLog, { "GetProgramInfoLog", "GetProgramInfoLogARB", nullptr } },
361 { (PRFuncPtr*) &mSymbols.fTexParameteri, { "TexParameteri", nullptr } },
362 { (PRFuncPtr*) &mSymbols.fTexParameteriv, { "TexParameteriv", nullptr } },
363 { (PRFuncPtr*) &mSymbols.fTexParameterf, { "TexParameterf", nullptr } },
364 { (PRFuncPtr*) &mSymbols.fGetString, { "GetString", nullptr } },
365 { (PRFuncPtr*) &mSymbols.fGetTexParameterfv, { "GetTexParameterfv", nullptr } },
366 { (PRFuncPtr*) &mSymbols.fGetTexParameteriv, { "GetTexParameteriv", nullptr } },
367 { (PRFuncPtr*) &mSymbols.fGetUniformfv, { "GetUniformfv", "GetUniformfvARB", nullptr } },
368 { (PRFuncPtr*) &mSymbols.fGetUniformiv, { "GetUniformiv", "GetUniformivARB", nullptr } },
369 { (PRFuncPtr*) &mSymbols.fGetUniformLocation, { "GetUniformLocation", "GetUniformLocationARB", nullptr } },
370 { (PRFuncPtr*) &mSymbols.fGetVertexAttribfv, { "GetVertexAttribfv", "GetVertexAttribfvARB", nullptr } },
371 { (PRFuncPtr*) &mSymbols.fGetVertexAttribiv, { "GetVertexAttribiv", "GetVertexAttribivARB", nullptr } },
372 { (PRFuncPtr*) &mSymbols.fGetVertexAttribPointerv, { "GetVertexAttribPointerv", nullptr } },
373 { (PRFuncPtr*) &mSymbols.fHint, { "Hint", nullptr } },
374 { (PRFuncPtr*) &mSymbols.fIsBuffer, { "IsBuffer", "IsBufferARB", nullptr } },
375 { (PRFuncPtr*) &mSymbols.fIsEnabled, { "IsEnabled", nullptr } },
376 { (PRFuncPtr*) &mSymbols.fIsProgram, { "IsProgram", "IsProgramARB", nullptr } },
377 { (PRFuncPtr*) &mSymbols.fIsShader, { "IsShader", "IsShaderARB", nullptr } },
378 { (PRFuncPtr*) &mSymbols.fIsTexture, { "IsTexture", "IsTextureARB", nullptr } },
379 { (PRFuncPtr*) &mSymbols.fLineWidth, { "LineWidth", nullptr } },
380 { (PRFuncPtr*) &mSymbols.fLinkProgram, { "LinkProgram", "LinkProgramARB", nullptr } },
381 { (PRFuncPtr*) &mSymbols.fPixelStorei, { "PixelStorei", nullptr } },
382 { (PRFuncPtr*) &mSymbols.fPolygonOffset, { "PolygonOffset", nullptr } },
383 { (PRFuncPtr*) &mSymbols.fReadPixels, { "ReadPixels", nullptr } },
384 { (PRFuncPtr*) &mSymbols.fSampleCoverage, { "SampleCoverage", nullptr } },
385 { (PRFuncPtr*) &mSymbols.fScissor, { "Scissor", nullptr } },
386 { (PRFuncPtr*) &mSymbols.fStencilFunc, { "StencilFunc", nullptr } },
387 { (PRFuncPtr*) &mSymbols.fStencilFuncSeparate, { "StencilFuncSeparate", "StencilFuncSeparateEXT", nullptr } },
388 { (PRFuncPtr*) &mSymbols.fStencilMask, { "StencilMask", nullptr } },
389 { (PRFuncPtr*) &mSymbols.fStencilMaskSeparate, { "StencilMaskSeparate", "StencilMaskSeparateEXT", nullptr } },
390 { (PRFuncPtr*) &mSymbols.fStencilOp, { "StencilOp", nullptr } },
391 { (PRFuncPtr*) &mSymbols.fStencilOpSeparate, { "StencilOpSeparate", "StencilOpSeparateEXT", nullptr } },
392 { (PRFuncPtr*) &mSymbols.fTexImage2D, { "TexImage2D", nullptr } },
393 { (PRFuncPtr*) &mSymbols.fTexSubImage2D, { "TexSubImage2D", nullptr } },
394 { (PRFuncPtr*) &mSymbols.fUniform1f, { "Uniform1f", nullptr } },
395 { (PRFuncPtr*) &mSymbols.fUniform1fv, { "Uniform1fv", nullptr } },
396 { (PRFuncPtr*) &mSymbols.fUniform1i, { "Uniform1i", nullptr } },
397 { (PRFuncPtr*) &mSymbols.fUniform1iv, { "Uniform1iv", nullptr } },
398 { (PRFuncPtr*) &mSymbols.fUniform2f, { "Uniform2f", nullptr } },
399 { (PRFuncPtr*) &mSymbols.fUniform2fv, { "Uniform2fv", nullptr } },
400 { (PRFuncPtr*) &mSymbols.fUniform2i, { "Uniform2i", nullptr } },
401 { (PRFuncPtr*) &mSymbols.fUniform2iv, { "Uniform2iv", nullptr } },
402 { (PRFuncPtr*) &mSymbols.fUniform3f, { "Uniform3f", nullptr } },
403 { (PRFuncPtr*) &mSymbols.fUniform3fv, { "Uniform3fv", nullptr } },
404 { (PRFuncPtr*) &mSymbols.fUniform3i, { "Uniform3i", nullptr } },
405 { (PRFuncPtr*) &mSymbols.fUniform3iv, { "Uniform3iv", nullptr } },
406 { (PRFuncPtr*) &mSymbols.fUniform4f, { "Uniform4f", nullptr } },
407 { (PRFuncPtr*) &mSymbols.fUniform4fv, { "Uniform4fv", nullptr } },
408 { (PRFuncPtr*) &mSymbols.fUniform4i, { "Uniform4i", nullptr } },
409 { (PRFuncPtr*) &mSymbols.fUniform4iv, { "Uniform4iv", nullptr } },
410 { (PRFuncPtr*) &mSymbols.fUniformMatrix2fv, { "UniformMatrix2fv", nullptr } },
411 { (PRFuncPtr*) &mSymbols.fUniformMatrix3fv, { "UniformMatrix3fv", nullptr } },
412 { (PRFuncPtr*) &mSymbols.fUniformMatrix4fv, { "UniformMatrix4fv", nullptr } },
413 { (PRFuncPtr*) &mSymbols.fUseProgram, { "UseProgram", nullptr } },
414 { (PRFuncPtr*) &mSymbols.fValidateProgram, { "ValidateProgram", nullptr } },
415 { (PRFuncPtr*) &mSymbols.fVertexAttribPointer, { "VertexAttribPointer", nullptr } },
416 { (PRFuncPtr*) &mSymbols.fVertexAttrib1f, { "VertexAttrib1f", nullptr } },
417 { (PRFuncPtr*) &mSymbols.fVertexAttrib2f, { "VertexAttrib2f", nullptr } },
418 { (PRFuncPtr*) &mSymbols.fVertexAttrib3f, { "VertexAttrib3f", nullptr } },
419 { (PRFuncPtr*) &mSymbols.fVertexAttrib4f, { "VertexAttrib4f", nullptr } },
420 { (PRFuncPtr*) &mSymbols.fVertexAttrib1fv, { "VertexAttrib1fv", nullptr } },
421 { (PRFuncPtr*) &mSymbols.fVertexAttrib2fv, { "VertexAttrib2fv", nullptr } },
422 { (PRFuncPtr*) &mSymbols.fVertexAttrib3fv, { "VertexAttrib3fv", nullptr } },
423 { (PRFuncPtr*) &mSymbols.fVertexAttrib4fv, { "VertexAttrib4fv", nullptr } },
424 { (PRFuncPtr*) &mSymbols.fViewport, { "Viewport", nullptr } },
425 { (PRFuncPtr*) &mSymbols.fCompileShader, { "CompileShader", nullptr } },
426 { (PRFuncPtr*) &mSymbols.fCopyTexImage2D, { "CopyTexImage2D", nullptr } },
427 { (PRFuncPtr*) &mSymbols.fCopyTexSubImage2D, { "CopyTexSubImage2D", nullptr } },
428 { (PRFuncPtr*) &mSymbols.fGetShaderiv, { "GetShaderiv", nullptr } },
429 { (PRFuncPtr*) &mSymbols.fGetShaderInfoLog, { "GetShaderInfoLog", nullptr } },
430 { (PRFuncPtr*) &mSymbols.fGetShaderSource, { "GetShaderSource", nullptr } },
431 { (PRFuncPtr*) &mSymbols.fShaderSource, { "ShaderSource", nullptr } },
432 { (PRFuncPtr*) &mSymbols.fVertexAttribPointer, { "VertexAttribPointer", nullptr } },
433 { (PRFuncPtr*) &mSymbols.fBindFramebuffer, { "BindFramebuffer", "BindFramebufferEXT", nullptr } },
434 { (PRFuncPtr*) &mSymbols.fBindRenderbuffer, { "BindRenderbuffer", "BindRenderbufferEXT", nullptr } },
435 { (PRFuncPtr*) &mSymbols.fCheckFramebufferStatus, { "CheckFramebufferStatus", "CheckFramebufferStatusEXT", nullptr } },
436 { (PRFuncPtr*) &mSymbols.fFramebufferRenderbuffer, { "FramebufferRenderbuffer", "FramebufferRenderbufferEXT", nullptr } },
437 { (PRFuncPtr*) &mSymbols.fFramebufferTexture2D, { "FramebufferTexture2D", "FramebufferTexture2DEXT", nullptr } },
438 { (PRFuncPtr*) &mSymbols.fGenerateMipmap, { "GenerateMipmap", "GenerateMipmapEXT", nullptr } },
439 { (PRFuncPtr*) &mSymbols.fGetFramebufferAttachmentParameteriv, { "GetFramebufferAttachmentParameteriv", "GetFramebufferAttachmentParameterivEXT", nullptr } },
440 { (PRFuncPtr*) &mSymbols.fGetRenderbufferParameteriv, { "GetRenderbufferParameteriv", "GetRenderbufferParameterivEXT", nullptr } },
441 { (PRFuncPtr*) &mSymbols.fIsFramebuffer, { "IsFramebuffer", "IsFramebufferEXT", nullptr } },
442 { (PRFuncPtr*) &mSymbols.fIsRenderbuffer, { "IsRenderbuffer", "IsRenderbufferEXT", nullptr } },
443 { (PRFuncPtr*) &mSymbols.fRenderbufferStorage, { "RenderbufferStorage", "RenderbufferStorageEXT", nullptr } },
444
445 { (PRFuncPtr*) &mSymbols.fGenBuffers, { "GenBuffers", "GenBuffersARB", nullptr } },
446 { (PRFuncPtr*) &mSymbols.fGenTextures, { "GenTextures", nullptr } },
447 { (PRFuncPtr*) &mSymbols.fCreateProgram, { "CreateProgram", "CreateProgramARB", nullptr } },
448 { (PRFuncPtr*) &mSymbols.fCreateShader, { "CreateShader", "CreateShaderARB", nullptr } },
449 { (PRFuncPtr*) &mSymbols.fGenFramebuffers, { "GenFramebuffers", "GenFramebuffersEXT", nullptr } },
450 { (PRFuncPtr*) &mSymbols.fGenRenderbuffers, { "GenRenderbuffers", "GenRenderbuffersEXT", nullptr } },
451
452 { (PRFuncPtr*) &mSymbols.fDeleteBuffers, { "DeleteBuffers", "DeleteBuffersARB", nullptr } },
453 { (PRFuncPtr*) &mSymbols.fDeleteTextures, { "DeleteTextures", "DeleteTexturesARB", nullptr } },
454 { (PRFuncPtr*) &mSymbols.fDeleteProgram, { "DeleteProgram", "DeleteProgramARB", nullptr } },
455 { (PRFuncPtr*) &mSymbols.fDeleteShader, { "DeleteShader", "DeleteShaderARB", nullptr } },
456 { (PRFuncPtr*) &mSymbols.fDeleteFramebuffers, { "DeleteFramebuffers", "DeleteFramebuffersEXT", nullptr } },
457 { (PRFuncPtr*) &mSymbols.fDeleteRenderbuffers, { "DeleteRenderbuffers", "DeleteRenderbuffersEXT", nullptr } },
458
459 { nullptr, { nullptr } },
460
461 };
462
463 mInitialized = LoadSymbols(&symbols[0], trygl, prefix);
464 MakeCurrent();
465 if (mInitialized) {
466 unsigned int version = 0;
467
468 ParseGLVersion(this, &version);
469
470 #ifdef DEBUG
471 printf_stderr("OpenGL version detected: %u\n", version);
472 printf_stderr("OpenGL vendor: %s\n", fGetString(LOCAL_GL_VENDOR));
473 printf_stderr("OpenGL renderer: %s\n", fGetString(LOCAL_GL_RENDERER));
474 #endif
475
476 if (version >= mVersion) {
477 mVersion = version;
478 }
479 // Don't fail if version < mVersion, see bug 999445,
480 // Mac OSX 10.6/10.7 machines with Intel GPUs claim only OpenGL 1.4 but
481 // have all the GL2+ extensions that we need.
482 }
483
484 // Load OpenGL ES 2.0 symbols, or desktop if we aren't using ES 2.
485 if (mInitialized) {
486 if (IsGLES()) {
487 SymLoadStruct symbols_ES2[] = {
488 { (PRFuncPtr*) &mSymbols.fGetShaderPrecisionFormat, { "GetShaderPrecisionFormat", nullptr } },
489 { (PRFuncPtr*) &mSymbols.fClearDepthf, { "ClearDepthf", nullptr } },
490 { (PRFuncPtr*) &mSymbols.fDepthRangef, { "DepthRangef", nullptr } },
491 { nullptr, { nullptr } },
492 };
493
494 if (!LoadSymbols(&symbols_ES2[0], trygl, prefix)) {
495 NS_ERROR("OpenGL ES 2.0 supported, but symbols could not be loaded.");
496 mInitialized = false;
497 }
498 } else {
499 SymLoadStruct symbols_desktop[] = {
500 { (PRFuncPtr*) &mSymbols.fClearDepth, { "ClearDepth", nullptr } },
501 { (PRFuncPtr*) &mSymbols.fDepthRange, { "DepthRange", nullptr } },
502 { (PRFuncPtr*) &mSymbols.fReadBuffer, { "ReadBuffer", nullptr } },
503 { (PRFuncPtr*) &mSymbols.fMapBuffer, { "MapBuffer", nullptr } },
504 { (PRFuncPtr*) &mSymbols.fUnmapBuffer, { "UnmapBuffer", nullptr } },
505 { (PRFuncPtr*) &mSymbols.fPointParameterf, { "PointParameterf", nullptr } },
506 { (PRFuncPtr*) &mSymbols.fDrawBuffer, { "DrawBuffer", nullptr } },
507 // These functions are only used by Skia/GL in desktop mode.
508 // Other parts of Gecko should avoid using these
509 { (PRFuncPtr*) &mSymbols.fDrawBuffers, { "DrawBuffers", nullptr } },
510 { (PRFuncPtr*) &mSymbols.fClientActiveTexture, { "ClientActiveTexture", nullptr } },
511 { (PRFuncPtr*) &mSymbols.fDisableClientState, { "DisableClientState", nullptr } },
512 { (PRFuncPtr*) &mSymbols.fEnableClientState, { "EnableClientState", nullptr } },
513 { (PRFuncPtr*) &mSymbols.fLoadIdentity, { "LoadIdentity", nullptr } },
514 { (PRFuncPtr*) &mSymbols.fLoadMatrixf, { "LoadMatrixf", nullptr } },
515 { (PRFuncPtr*) &mSymbols.fMatrixMode, { "MatrixMode", nullptr } },
516 { (PRFuncPtr*) &mSymbols.fTexGeni, { "TexGeni", nullptr } },
517 { (PRFuncPtr*) &mSymbols.fTexGenf, { "TexGenf", nullptr } },
518 { (PRFuncPtr*) &mSymbols.fTexGenfv, { "TexGenfv", nullptr } },
519 { (PRFuncPtr*) &mSymbols.fVertexPointer, { "VertexPointer", nullptr } },
520 { nullptr, { nullptr } },
521 };
522
523 if (!LoadSymbols(&symbols_desktop[0], trygl, prefix)) {
524 NS_ERROR("Desktop symbols failed to load.");
525 mInitialized = false;
526 }
527 }
528 }
529
530 const char *glVendorString = nullptr;
531 const char *glRendererString = nullptr;
532
533 if (mInitialized) {
534 // The order of these strings must match up with the order of the enum
535 // defined in GLContext.h for vendor IDs
536 glVendorString = (const char *)fGetString(LOCAL_GL_VENDOR);
537 if (!glVendorString)
538 mInitialized = false;
539
540 const char *vendorMatchStrings[size_t(GLVendor::Other)] = {
541 "Intel",
542 "NVIDIA",
543 "ATI",
544 "Qualcomm",
545 "Imagination",
546 "nouveau",
547 "Vivante",
548 "VMware, Inc."
549 };
550
551 mVendor = GLVendor::Other;
552 for (size_t i = 0; i < size_t(GLVendor::Other); ++i) {
553 if (DoesStringMatch(glVendorString, vendorMatchStrings[i])) {
554 mVendor = GLVendor(i);
555 break;
556 }
557 }
558
559 // The order of these strings must match up with the order of the enum
560 // defined in GLContext.h for renderer IDs
561 glRendererString = (const char *)fGetString(LOCAL_GL_RENDERER);
562 if (!glRendererString)
563 mInitialized = false;
564
565 const char *rendererMatchStrings[size_t(GLRenderer::Other)] = {
566 "Adreno 200",
567 "Adreno 205",
568 "Adreno (TM) 205",
569 "Adreno (TM) 320",
570 "PowerVR SGX 530",
571 "PowerVR SGX 540",
572 "NVIDIA Tegra",
573 "Android Emulator",
574 "Gallium 0.4 on llvmpipe"
575 };
576
577 mRenderer = GLRenderer::Other;
578 for (size_t i = 0; i < size_t(GLRenderer::Other); ++i) {
579 if (DoesStringMatch(glRendererString, rendererMatchStrings[i])) {
580 mRenderer = GLRenderer(i);
581 break;
582 }
583 }
584 }
585
586
587 #ifdef DEBUG
588 if (PR_GetEnv("MOZ_GL_DEBUG"))
589 sDebugMode |= DebugEnabled;
590
591 // enables extra verbose output, informing of the start and finish of every GL call.
592 // useful e.g. to record information to investigate graphics system crashes/lockups
593 if (PR_GetEnv("MOZ_GL_DEBUG_VERBOSE"))
594 sDebugMode |= DebugTrace;
595
596 // aborts on GL error. Can be useful to debug quicker code that is known not to generate any GL error in principle.
597 if (PR_GetEnv("MOZ_GL_DEBUG_ABORT_ON_ERROR"))
598 sDebugMode |= DebugAbortOnError;
599 #endif
600
601 if (mInitialized) {
602 #ifdef DEBUG
603 static bool firstRun = true;
604 if (firstRun && DebugMode()) {
605 const char *vendors[size_t(GLVendor::Other)] = {
606 "Intel",
607 "NVIDIA",
608 "ATI",
609 "Qualcomm"
610 };
611
612 MOZ_ASSERT(glVendorString);
613 if (mVendor < GLVendor::Other) {
614 printf_stderr("OpenGL vendor ('%s') recognized as: %s\n",
615 glVendorString, vendors[size_t(mVendor)]);
616 } else {
617 printf_stderr("OpenGL vendor ('%s') unrecognized\n", glVendorString);
618 }
619 }
620 firstRun = false;
621 #endif
622
623 InitExtensions();
624 InitFeatures();
625
626 // Disable extensions with partial or incorrect support.
627 if (WorkAroundDriverBugs()) {
628 if (Renderer() == GLRenderer::AdrenoTM320) {
629 MarkUnsupported(GLFeature::standard_derivatives);
630 }
631
632 if (Vendor() == GLVendor::Vivante) {
633 // bug 958256
634 MarkUnsupported(GLFeature::standard_derivatives);
635 }
636
637 if (Vendor() == GLVendor::Imagination &&
638 Renderer() == GLRenderer::SGX540) {
639 // Bug 980048
640 MarkExtensionUnsupported(OES_EGL_sync);
641 }
642
643 #ifdef XP_MACOSX
644 // The Mac Nvidia driver, for versions up to and including 10.8, don't seem
645 // to properly support this. See 814839
646 // this has been fixed in Mac OS X 10.9. See 907946
647 if (Vendor() == gl::GLVendor::NVIDIA &&
648 !nsCocoaFeatures::OnMavericksOrLater())
649 {
650 MarkUnsupported(GLFeature::depth_texture);
651 }
652 #endif
653 // ANGLE's divisor support is busted. (see bug 916816)
654 if (IsANGLE()) {
655 MarkUnsupported(GLFeature::instanced_arrays);
656 }
657 }
658
659 NS_ASSERTION(!IsExtensionSupported(GLContext::ARB_pixel_buffer_object) ||
660 (mSymbols.fMapBuffer && mSymbols.fUnmapBuffer),
661 "ARB_pixel_buffer_object supported without glMapBuffer/UnmapBuffer being available!");
662
663 if (SupportsRobustness()) {
664 mHasRobustness = false;
665
666 if (IsExtensionSupported(ARB_robustness)) {
667 SymLoadStruct robustnessSymbols[] = {
668 { (PRFuncPtr*) &mSymbols.fGetGraphicsResetStatus, { "GetGraphicsResetStatusARB", nullptr } },
669 { nullptr, { nullptr } },
670 };
671
672 if (!LoadSymbols(&robustnessSymbols[0], trygl, prefix)) {
673 NS_ERROR("GL supports ARB_robustness without supplying GetGraphicsResetStatusARB.");
674
675 mSymbols.fGetGraphicsResetStatus = nullptr;
676 } else {
677 mHasRobustness = true;
678 }
679 }
680 if (!IsExtensionSupported(ARB_robustness) &&
681 IsExtensionSupported(EXT_robustness)) {
682 SymLoadStruct robustnessSymbols[] = {
683 { (PRFuncPtr*) &mSymbols.fGetGraphicsResetStatus, { "GetGraphicsResetStatusEXT", nullptr } },
684 { nullptr, { nullptr } },
685 };
686
687 if (!LoadSymbols(&robustnessSymbols[0], trygl, prefix)) {
688 NS_ERROR("GL supports EXT_robustness without supplying GetGraphicsResetStatusEXT.");
689
690 mSymbols.fGetGraphicsResetStatus = nullptr;
691 } else {
692 mHasRobustness = true;
693 }
694 }
695
696 if (!mHasRobustness) {
697 MarkUnsupported(GLFeature::robustness);
698 }
699 }
700
701 // Check for aux symbols based on extensions
702 if (IsSupported(GLFeature::framebuffer_blit))
703 {
704 SymLoadStruct auxSymbols[] = {
705 {
706 (PRFuncPtr*) &mSymbols.fBlitFramebuffer,
707 {
708 "BlitFramebuffer",
709 "BlitFramebufferEXT",
710 "BlitFramebufferANGLE",
711 nullptr
712 }
713 },
714 { nullptr, { nullptr } },
715 };
716 if (!LoadSymbols(&auxSymbols[0], trygl, prefix)) {
717 NS_ERROR("GL supports framebuffer_blit without supplying glBlitFramebuffer");
718
719 MarkUnsupported(GLFeature::framebuffer_blit);
720 mSymbols.fBlitFramebuffer = nullptr;
721 }
722 }
723
724 if (IsSupported(GLFeature::framebuffer_multisample))
725 {
726 SymLoadStruct auxSymbols[] = {
727 {
728 (PRFuncPtr*) &mSymbols.fRenderbufferStorageMultisample,
729 {
730 "RenderbufferStorageMultisample",
731 "RenderbufferStorageMultisampleEXT",
732 "RenderbufferStorageMultisampleANGLE",
733 nullptr
734 }
735 },
736 { nullptr, { nullptr } },
737 };
738 if (!LoadSymbols(&auxSymbols[0], trygl, prefix)) {
739 NS_ERROR("GL supports framebuffer_multisample without supplying glRenderbufferStorageMultisample");
740
741 MarkUnsupported(GLFeature::framebuffer_multisample);
742 mSymbols.fRenderbufferStorageMultisample = nullptr;
743 }
744 }
745
746 if (IsExtensionSupported(ARB_sync)) {
747 SymLoadStruct syncSymbols[] = {
748 { (PRFuncPtr*) &mSymbols.fFenceSync, { "FenceSync", nullptr } },
749 { (PRFuncPtr*) &mSymbols.fIsSync, { "IsSync", nullptr } },
750 { (PRFuncPtr*) &mSymbols.fDeleteSync, { "DeleteSync", nullptr } },
751 { (PRFuncPtr*) &mSymbols.fClientWaitSync, { "ClientWaitSync", nullptr } },
752 { (PRFuncPtr*) &mSymbols.fWaitSync, { "WaitSync", nullptr } },
753 { (PRFuncPtr*) &mSymbols.fGetInteger64v, { "GetInteger64v", nullptr } },
754 { (PRFuncPtr*) &mSymbols.fGetSynciv, { "GetSynciv", nullptr } },
755 { nullptr, { nullptr } },
756 };
757
758 if (!LoadSymbols(&syncSymbols[0], trygl, prefix)) {
759 NS_ERROR("GL supports ARB_sync without supplying its functions.");
760
761 MarkExtensionUnsupported(ARB_sync);
762 mSymbols.fFenceSync = nullptr;
763 mSymbols.fIsSync = nullptr;
764 mSymbols.fDeleteSync = nullptr;
765 mSymbols.fClientWaitSync = nullptr;
766 mSymbols.fWaitSync = nullptr;
767 mSymbols.fGetInteger64v = nullptr;
768 mSymbols.fGetSynciv = nullptr;
769 }
770 }
771
772 if (IsExtensionSupported(OES_EGL_image)) {
773 SymLoadStruct imageSymbols[] = {
774 { (PRFuncPtr*) &mSymbols.fEGLImageTargetTexture2D, { "EGLImageTargetTexture2DOES", nullptr } },
775 { (PRFuncPtr*) &mSymbols.fEGLImageTargetRenderbufferStorage, { "EGLImageTargetRenderbufferStorageOES", nullptr } },
776 { nullptr, { nullptr } },
777 };
778
779 if (!LoadSymbols(&imageSymbols[0], trygl, prefix)) {
780 NS_ERROR("GL supports OES_EGL_image without supplying its functions.");
781
782 MarkExtensionUnsupported(OES_EGL_image);
783 mSymbols.fEGLImageTargetTexture2D = nullptr;
784 mSymbols.fEGLImageTargetRenderbufferStorage = nullptr;
785 }
786 }
787
788 if (IsExtensionSupported(APPLE_texture_range)) {
789 SymLoadStruct vaoSymbols[] = {
790 { (PRFuncPtr*) &mSymbols.fTextureRangeAPPLE, { "TextureRangeAPPLE", nullptr } },
791 { nullptr, { nullptr } },
792 };
793
794 if (!LoadSymbols(&vaoSymbols[0], trygl, prefix)) {
795 mSymbols.fTextureRangeAPPLE = nullptr;
796 }
797 }
798
799 if (IsExtensionSupported(ARB_vertex_array_object) ||
800 IsExtensionSupported(OES_vertex_array_object)) {
801 SymLoadStruct vaoSymbols[] = {
802 { (PRFuncPtr*) &mSymbols.fIsVertexArray, { "IsVertexArray", "IsVertexArrayOES", nullptr } },
803 { (PRFuncPtr*) &mSymbols.fGenVertexArrays, { "GenVertexArrays", "GenVertexArraysOES", nullptr } },
804 { (PRFuncPtr*) &mSymbols.fBindVertexArray, { "BindVertexArray", "BindVertexArrayOES", nullptr } },
805 { (PRFuncPtr*) &mSymbols.fDeleteVertexArrays, { "DeleteVertexArrays", "DeleteVertexArraysOES", nullptr } },
806 { nullptr, { nullptr } },
807 };
808
809 if (!LoadSymbols(&vaoSymbols[0], trygl, prefix)) {
810 NS_ERROR("GL supports Vertex Array Object without supplying its functions.");
811
812 MarkUnsupported(GLFeature::vertex_array_object);
813 mSymbols.fIsVertexArray = nullptr;
814 mSymbols.fGenVertexArrays = nullptr;
815 mSymbols.fBindVertexArray = nullptr;
816 mSymbols.fDeleteVertexArrays = nullptr;
817 }
818 }
819 else if (IsExtensionSupported(APPLE_vertex_array_object)) {
820 /*
821 * separate call to LoadSymbols with APPLE_vertex_array_object to work around
822 * a driver bug : the IsVertexArray symbol (without suffix) can be present but unusable.
823 */
824 SymLoadStruct vaoSymbols[] = {
825 { (PRFuncPtr*) &mSymbols.fIsVertexArray, { "IsVertexArrayAPPLE", nullptr } },
826 { (PRFuncPtr*) &mSymbols.fGenVertexArrays, { "GenVertexArraysAPPLE", nullptr } },
827 { (PRFuncPtr*) &mSymbols.fBindVertexArray, { "BindVertexArrayAPPLE", nullptr } },
828 { (PRFuncPtr*) &mSymbols.fDeleteVertexArrays, { "DeleteVertexArraysAPPLE", nullptr } },
829 { nullptr, { nullptr } },
830 };
831
832 if (!LoadSymbols(&vaoSymbols[0], trygl, prefix)) {
833 NS_ERROR("GL supports Vertex Array Object without supplying its functions.");
834
835 MarkUnsupported(GLFeature::vertex_array_object);
836 mSymbols.fIsVertexArray = nullptr;
837 mSymbols.fGenVertexArrays = nullptr;
838 mSymbols.fBindVertexArray = nullptr;
839 mSymbols.fDeleteVertexArrays = nullptr;
840 }
841 }
842
843 if (IsSupported(GLFeature::draw_instanced)) {
844 SymLoadStruct drawInstancedSymbols[] = {
845 { (PRFuncPtr*) &mSymbols.fDrawArraysInstanced,
846 { "DrawArraysInstanced",
847 "DrawArraysInstancedARB",
848 "DrawArraysInstancedEXT",
849 "DrawArraysInstancedNV",
850 "DrawArraysInstancedANGLE",
851 nullptr
852 }
853 },
854 { (PRFuncPtr*) &mSymbols.fDrawElementsInstanced,
855 { "DrawElementsInstanced",
856 "DrawElementsInstancedARB",
857 "DrawElementsInstancedEXT",
858 "DrawElementsInstancedNV",
859 "DrawElementsInstancedANGLE",
860 nullptr
861 }
862 },
863 { nullptr, { nullptr } },
864 };
865
866 if (!LoadSymbols(drawInstancedSymbols, trygl, prefix)) {
867 NS_ERROR("GL supports instanced draws without supplying its functions.");
868
869 MarkUnsupported(GLFeature::draw_instanced);
870 mSymbols.fDrawArraysInstanced = nullptr;
871 mSymbols.fDrawElementsInstanced = nullptr;
872 }
873 }
874
875 if (IsSupported(GLFeature::instanced_arrays)) {
876 SymLoadStruct instancedArraySymbols[] = {
877 { (PRFuncPtr*) &mSymbols.fVertexAttribDivisor,
878 { "VertexAttribDivisor",
879 "VertexAttribDivisorARB",
880 "VertexAttribDivisorNV",
881 "VertexAttribDivisorANGLE",
882 nullptr
883 }
884 },
885 { nullptr, { nullptr } },
886 };
887
888 if (!LoadSymbols(instancedArraySymbols, trygl, prefix)) {
889 NS_ERROR("GL supports array instanced without supplying it function.");
890
891 MarkUnsupported(GLFeature::instanced_arrays);
892 mSymbols.fVertexAttribDivisor = nullptr;
893 }
894 }
895
896 if (IsSupported(GLFeature::transform_feedback)) {
897 SymLoadStruct transformFeedbackSymbols[] = {
898 { (PRFuncPtr*) &mSymbols.fBindBufferBase,
899 { "BindBufferBase",
900 "BindBufferBaseEXT",
901 "BindBufferBaseNV",
902 nullptr
903 }
904 },
905 { (PRFuncPtr*) &mSymbols.fBindBufferRange,
906 { "BindBufferRange",
907 "BindBufferRangeEXT",
908 "BindBufferRangeNV",
909 nullptr
910 }
911 },
912 { (PRFuncPtr*) &mSymbols.fBeginTransformFeedback,
913 { "BeginTransformFeedback",
914 "BeginTransformFeedbackEXT",
915 "BeginTransformFeedbackNV",
916 nullptr
917 }
918 },
919 { (PRFuncPtr*) &mSymbols.fEndTransformFeedback,
920 { "EndTransformFeedback",
921 "EndTransformFeedbackEXT",
922 "EndTransformFeedbackNV",
923 nullptr
924 }
925 },
926 { (PRFuncPtr*) &mSymbols.fTransformFeedbackVaryings,
927 { "TransformFeedbackVaryings",
928 "TransformFeedbackVaryingsEXT",
929 "TransformFeedbackVaryingsNV",
930 nullptr
931 }
932 },
933 { (PRFuncPtr*) &mSymbols.fGetTransformFeedbackVarying,
934 { "GetTransformFeedbackVarying",
935 "GetTransformFeedbackVaryingEXT",
936 "GetTransformFeedbackVaryingNV",
937 nullptr
938 }
939 },
940 { (PRFuncPtr*) &mSymbols.fGetIntegeri_v,
941 { "GetIntegeri_v",
942 "GetIntegerIndexedvEXT",
943 "GetIntegerIndexedvNV",
944 nullptr
945 }
946 },
947 { nullptr, { nullptr } },
948 };
949
950 if (!LoadSymbols(transformFeedbackSymbols, trygl, prefix)) {
951 NS_ERROR("GL supports transform feedback without supplying its functions.");
952
953 MarkUnsupported(GLFeature::transform_feedback);
954 MarkUnsupported(GLFeature::bind_buffer_offset);
955 mSymbols.fBindBufferBase = nullptr;
956 mSymbols.fBindBufferRange = nullptr;
957 mSymbols.fBeginTransformFeedback = nullptr;
958 mSymbols.fEndTransformFeedback = nullptr;
959 mSymbols.fTransformFeedbackVaryings = nullptr;
960 mSymbols.fGetTransformFeedbackVarying = nullptr;
961 mSymbols.fGetIntegeri_v = nullptr;
962 }
963 }
964
965 if (IsSupported(GLFeature::bind_buffer_offset)) {
966 SymLoadStruct bindBufferOffsetSymbols[] = {
967 { (PRFuncPtr*) &mSymbols.fBindBufferOffset,
968 { "BindBufferOffset",
969 "BindBufferOffsetEXT",
970 "BindBufferOffsetNV",
971 nullptr
972 }
973 },
974 { nullptr, { nullptr } },
975 };
976
977 if (!LoadSymbols(bindBufferOffsetSymbols, trygl, prefix)) {
978 NS_ERROR("GL supports BindBufferOffset without supplying its function.");
979
980 MarkUnsupported(GLFeature::bind_buffer_offset);
981 mSymbols.fBindBufferOffset = nullptr;
982 }
983 }
984
985 if (IsSupported(GLFeature::query_objects)) {
986 SymLoadStruct queryObjectsSymbols[] = {
987 { (PRFuncPtr*) &mSymbols.fBeginQuery, { "BeginQuery", "BeginQueryEXT", nullptr } },
988 { (PRFuncPtr*) &mSymbols.fGenQueries, { "GenQueries", "GenQueriesEXT", nullptr } },
989 { (PRFuncPtr*) &mSymbols.fDeleteQueries, { "DeleteQueries", "DeleteQueriesEXT", nullptr } },
990 { (PRFuncPtr*) &mSymbols.fEndQuery, { "EndQuery", "EndQueryEXT", nullptr } },
991 { (PRFuncPtr*) &mSymbols.fGetQueryiv, { "GetQueryiv", "GetQueryivEXT", nullptr } },
992 { (PRFuncPtr*) &mSymbols.fGetQueryObjectuiv, { "GetQueryObjectuiv", "GetQueryObjectuivEXT", nullptr } },
993 { (PRFuncPtr*) &mSymbols.fIsQuery, { "IsQuery", "IsQueryEXT", nullptr } },
994 { nullptr, { nullptr } },
995 };
996
997 if (!LoadSymbols(queryObjectsSymbols, trygl, prefix)) {
998 NS_ERROR("GL supports query objects without supplying its functions.");
999
1000 MarkUnsupported(GLFeature::query_objects);
1001 MarkUnsupported(GLFeature::get_query_object_iv);
1002 MarkUnsupported(GLFeature::occlusion_query);
1003 MarkUnsupported(GLFeature::occlusion_query_boolean);
1004 MarkUnsupported(GLFeature::occlusion_query2);
1005 mSymbols.fBeginQuery = nullptr;
1006 mSymbols.fGenQueries = nullptr;
1007 mSymbols.fDeleteQueries = nullptr;
1008 mSymbols.fEndQuery = nullptr;
1009 mSymbols.fGetQueryiv = nullptr;
1010 mSymbols.fGetQueryObjectuiv = nullptr;
1011 mSymbols.fIsQuery = nullptr;
1012 }
1013 }
1014
1015 if (IsSupported(GLFeature::get_query_object_iv)) {
1016 SymLoadStruct queryObjectsSymbols[] = {
1017 { (PRFuncPtr*) &mSymbols.fGetQueryObjectiv, { "GetQueryObjectiv", "GetQueryObjectivEXT", nullptr } },
1018 { nullptr, { nullptr } },
1019 };
1020
1021 if (!LoadSymbols(queryObjectsSymbols, trygl, prefix)) {
1022 NS_ERROR("GL supports query objects iv getter without supplying its function.");
1023
1024 MarkUnsupported(GLFeature::get_query_object_iv);
1025 mSymbols.fGetQueryObjectiv = nullptr;
1026 }
1027 }
1028
1029 if (IsSupported(GLFeature::draw_buffers)) {
1030 SymLoadStruct drawBuffersSymbols[] = {
1031 { (PRFuncPtr*) &mSymbols.fDrawBuffers, { "DrawBuffers", nullptr } },
1032 { nullptr, { nullptr } },
1033 };
1034
1035 if (!LoadSymbols(drawBuffersSymbols, trygl, prefix)) {
1036 NS_ERROR("GL supports draw_buffers without supplying its functions.");
1037
1038 MarkUnsupported(GLFeature::draw_buffers);
1039 mSymbols.fDrawBuffers = nullptr;
1040 }
1041 }
1042
1043 if (IsExtensionSupported(KHR_debug)) {
1044 SymLoadStruct extSymbols[] = {
1045 { (PRFuncPtr*) &mSymbols.fDebugMessageControl, { "DebugMessageControl", "DebugMessageControlKHR", nullptr } },
1046 { (PRFuncPtr*) &mSymbols.fDebugMessageInsert, { "DebugMessageInsert", "DebugMessageInsertKHR", nullptr } },
1047 { (PRFuncPtr*) &mSymbols.fDebugMessageCallback, { "DebugMessageCallback", "DebugMessageCallbackKHR", nullptr } },
1048 { (PRFuncPtr*) &mSymbols.fGetDebugMessageLog, { "GetDebugMessageLog", "GetDebugMessageLogKHR", nullptr } },
1049 { (PRFuncPtr*) &mSymbols.fGetPointerv, { "GetPointerv", "GetPointervKHR", nullptr } },
1050 { (PRFuncPtr*) &mSymbols.fPushDebugGroup, { "PushDebugGroup", "PushDebugGroupKHR", nullptr } },
1051 { (PRFuncPtr*) &mSymbols.fPopDebugGroup, { "PopDebugGroup", "PopDebugGroupKHR", nullptr } },
1052 { (PRFuncPtr*) &mSymbols.fObjectLabel, { "ObjectLabel", "ObjectLabelKHR", nullptr } },
1053 { (PRFuncPtr*) &mSymbols.fGetObjectLabel, { "GetObjectLabel", "GetObjectLabelKHR", nullptr } },
1054 { (PRFuncPtr*) &mSymbols.fObjectPtrLabel, { "ObjectPtrLabel", "ObjectPtrLabelKHR", nullptr } },
1055 { (PRFuncPtr*) &mSymbols.fGetObjectPtrLabel, { "GetObjectPtrLabel", "GetObjectPtrLabelKHR", nullptr } },
1056 { nullptr, { nullptr } },
1057 };
1058
1059 if (!LoadSymbols(&extSymbols[0], trygl, prefix)) {
1060 NS_ERROR("GL supports KHR_debug without supplying its functions.");
1061
1062 MarkExtensionUnsupported(KHR_debug);
1063 mSymbols.fDebugMessageControl = nullptr;
1064 mSymbols.fDebugMessageInsert = nullptr;
1065 mSymbols.fDebugMessageCallback = nullptr;
1066 mSymbols.fGetDebugMessageLog = nullptr;
1067 mSymbols.fGetPointerv = nullptr;
1068 mSymbols.fPushDebugGroup = nullptr;
1069 mSymbols.fPopDebugGroup = nullptr;
1070 mSymbols.fObjectLabel = nullptr;
1071 mSymbols.fGetObjectLabel = nullptr;
1072 mSymbols.fObjectPtrLabel = nullptr;
1073 mSymbols.fGetObjectPtrLabel = nullptr;
1074 }
1075 }
1076
1077 if (IsSupported(GLFeature::draw_range_elements)) {
1078 SymLoadStruct imageSymbols[] = {
1079 { (PRFuncPtr*) &mSymbols.fDrawRangeElements, { "DrawRangeElementsEXT", "DrawRangeElements", nullptr } },
1080 { nullptr, { nullptr } },
1081 };
1082
1083 if (!LoadSymbols(&imageSymbols[0], trygl, prefix)) {
1084 NS_ERROR("GL supports draw_range_elements without supplying its functions.");
1085
1086 MarkUnsupported(GLFeature::draw_range_elements);
1087 mSymbols.fDrawRangeElements = nullptr;
1088 }
1089 }
1090
1091 // Load developer symbols, don't fail if we can't find them.
1092 SymLoadStruct auxSymbols[] = {
1093 { (PRFuncPtr*) &mSymbols.fGetTexImage, { "GetTexImage", nullptr } },
1094 { (PRFuncPtr*) &mSymbols.fGetTexLevelParameteriv, { "GetTexLevelParameteriv", nullptr } },
1095 { nullptr, { nullptr } },
1096 };
1097 bool warnOnFailures = DebugMode();
1098 LoadSymbols(&auxSymbols[0], trygl, prefix, warnOnFailures);
1099 }
1100
1101 if (mInitialized) {
1102 raw_fGetIntegerv(LOCAL_GL_VIEWPORT, mViewportRect);
1103 raw_fGetIntegerv(LOCAL_GL_SCISSOR_BOX, mScissorRect);
1104 raw_fGetIntegerv(LOCAL_GL_MAX_TEXTURE_SIZE, &mMaxTextureSize);
1105 raw_fGetIntegerv(LOCAL_GL_MAX_CUBE_MAP_TEXTURE_SIZE, &mMaxCubeMapTextureSize);
1106 raw_fGetIntegerv(LOCAL_GL_MAX_RENDERBUFFER_SIZE, &mMaxRenderbufferSize);
1107
1108 #ifdef XP_MACOSX
1109 if (mWorkAroundDriverBugs) {
1110 if (mVendor == GLVendor::Intel) {
1111 // see bug 737182 for 2D textures, bug 684882 for cube map textures.
1112 mMaxTextureSize = std::min(mMaxTextureSize, 4096);
1113 mMaxCubeMapTextureSize = std::min(mMaxCubeMapTextureSize, 512);
1114 // for good measure, we align renderbuffers on what we do for 2D textures
1115 mMaxRenderbufferSize = std::min(mMaxRenderbufferSize, 4096);
1116 mNeedsTextureSizeChecks = true;
1117 } else if (mVendor == GLVendor::NVIDIA) {
1118 if (nsCocoaFeatures::OnMountainLionOrLater()) {
1119 // See bug 879656. 8192 fails, 8191 works.
1120 mMaxTextureSize = std::min(mMaxTextureSize, 8191);
1121 mMaxRenderbufferSize = std::min(mMaxRenderbufferSize, 8191);
1122 }
1123 else {
1124 // See bug 877949.
1125 mMaxTextureSize = std::min(mMaxTextureSize, 4096);
1126 mMaxRenderbufferSize = std::min(mMaxRenderbufferSize, 4096);
1127 }
1128
1129 // Part of the bug 879656, but it also doesn't hurt the 877949
1130 mNeedsTextureSizeChecks = true;
1131 }
1132 }
1133 #endif
1134 #ifdef MOZ_X11
1135 if (mWorkAroundDriverBugs &&
1136 mVendor == GLVendor::Nouveau) {
1137 // see bug 814716. Clamp MaxCubeMapTextureSize at 2K for Nouveau.
1138 mMaxCubeMapTextureSize = std::min(mMaxCubeMapTextureSize, 2048);
1139 mNeedsTextureSizeChecks = true;
1140 }
1141 #endif
1142
1143 mMaxTextureImageSize = mMaxTextureSize;
1144
1145 mMaxSamples = 0;
1146 if (IsSupported(GLFeature::framebuffer_multisample)) {
1147 fGetIntegerv(LOCAL_GL_MAX_SAMPLES, (GLint*)&mMaxSamples);
1148 }
1149
1150 // We're ready for final setup.
1151 fBindFramebuffer(LOCAL_GL_FRAMEBUFFER, 0);
1152
1153 if (mCaps.any)
1154 DetermineCaps();
1155
1156 UpdatePixelFormat();
1157 UpdateGLFormats(mCaps);
1158
1159 mTexGarbageBin = new TextureGarbageBin(this);
1160
1161 MOZ_ASSERT(IsCurrent());
1162 }
1163
1164 if (mInitialized)
1165 reporter.SetSuccessful();
1166 else {
1167 // if initialization fails, ensure all symbols are zero, to avoid hard-to-understand bugs
1168 mSymbols.Zero();
1169 NS_WARNING("InitWithPrefix failed!");
1170 }
1171
1172 mVersionString = nsPrintfCString("%u.%u.%u", mVersion / 100, (mVersion / 10) % 10, mVersion % 10);
1173
1174 return mInitialized;
1175 }
1176
1177 void
1178 GLContext::InitExtensions()
1179 {
1180 MakeCurrent();
1181 const char* extensions = (const char*)fGetString(LOCAL_GL_EXTENSIONS);
1182 if (!extensions)
1183 return;
1184
1185 #ifdef DEBUG
1186 static bool firstRun = true;
1187 #else
1188 // Non-DEBUG, so never spew.
1189 const bool firstRun = false;
1190 #endif
1191
1192 InitializeExtensionsBitSet(mAvailableExtensions, extensions, sExtensionNames, firstRun && DebugMode());
1193
1194 if (WorkAroundDriverBugs() &&
1195 Vendor() == GLVendor::Qualcomm) {
1196
1197 // Some Adreno drivers do not report GL_OES_EGL_sync, but they really do support it.
1198 MarkExtensionSupported(OES_EGL_sync);
1199 }
1200
1201 if (WorkAroundDriverBugs() &&
1202 Renderer() == GLRenderer::AndroidEmulator) {
1203 // the Android emulator, which we use to run B2G reftests on,
1204 // doesn't expose the OES_rgb8_rgba8 extension, but it seems to
1205 // support it (tautologically, as it only runs on desktop GL).
1206 MarkExtensionSupported(OES_rgb8_rgba8);
1207 }
1208
1209 if (WorkAroundDriverBugs() &&
1210 Vendor() == GLVendor::VMware &&
1211 Renderer() == GLRenderer::GalliumLlvmpipe)
1212 {
1213 // The llvmpipe driver that is used on linux try servers appears to have
1214 // buggy support for s3tc/dxt1 compressed textures.
1215 // See Bug 975824.
1216 MarkExtensionUnsupported(EXT_texture_compression_s3tc);
1217 MarkExtensionUnsupported(EXT_texture_compression_dxt1);
1218 MarkExtensionUnsupported(ANGLE_texture_compression_dxt3);
1219 MarkExtensionUnsupported(ANGLE_texture_compression_dxt5);
1220 }
1221
1222 #ifdef DEBUG
1223 firstRun = false;
1224 #endif
1225 }
1226
1227 void
1228 GLContext::PlatformStartup()
1229 {
1230 RegisterStrongMemoryReporter(new GfxTexturesReporter());
1231 }
1232
1233 // Common code for checking for both GL extensions and GLX extensions.
1234 bool
1235 GLContext::ListHasExtension(const GLubyte *extensions, const char *extension)
1236 {
1237 // fix bug 612572 - we were crashing as we were calling this function with extensions==null
1238 if (extensions == nullptr || extension == nullptr)
1239 return false;
1240
1241 const GLubyte *start;
1242 GLubyte *where, *terminator;
1243
1244 /* Extension names should not have spaces. */
1245 where = (GLubyte *) strchr(extension, ' ');
1246 if (where || *extension == '\0')
1247 return false;
1248
1249 /*
1250 * It takes a bit of care to be fool-proof about parsing the
1251 * OpenGL extensions string. Don't be fooled by sub-strings,
1252 * etc.
1253 */
1254 start = extensions;
1255 for (;;) {
1256 where = (GLubyte *) strstr((const char *) start, extension);
1257 if (!where) {
1258 break;
1259 }
1260 terminator = where + strlen(extension);
1261 if (where == start || *(where - 1) == ' ') {
1262 if (*terminator == ' ' || *terminator == '\0') {
1263 return true;
1264 }
1265 }
1266 start = terminator;
1267 }
1268 return false;
1269 }
1270
1271 void
1272 GLContext::DetermineCaps()
1273 {
1274 PixelBufferFormat format = QueryPixelFormat();
1275
1276 SurfaceCaps caps;
1277 caps.color = !!format.red && !!format.green && !!format.blue;
1278 caps.bpp16 = caps.color && format.ColorBits() == 16;
1279 caps.alpha = !!format.alpha;
1280 caps.depth = !!format.depth;
1281 caps.stencil = !!format.stencil;
1282 caps.antialias = format.samples > 1;
1283 caps.preserve = true;
1284
1285 mCaps = caps;
1286 }
1287
1288 PixelBufferFormat
1289 GLContext::QueryPixelFormat()
1290 {
1291 PixelBufferFormat format;
1292
1293 ScopedBindFramebuffer autoFB(this, 0);
1294
1295 fGetIntegerv(LOCAL_GL_RED_BITS , &format.red );
1296 fGetIntegerv(LOCAL_GL_GREEN_BITS, &format.green);
1297 fGetIntegerv(LOCAL_GL_BLUE_BITS , &format.blue );
1298 fGetIntegerv(LOCAL_GL_ALPHA_BITS, &format.alpha);
1299
1300 fGetIntegerv(LOCAL_GL_DEPTH_BITS, &format.depth);
1301 fGetIntegerv(LOCAL_GL_STENCIL_BITS, &format.stencil);
1302
1303 fGetIntegerv(LOCAL_GL_SAMPLES, &format.samples);
1304
1305 return format;
1306 }
1307
1308 void
1309 GLContext::UpdatePixelFormat()
1310 {
1311 PixelBufferFormat format = QueryPixelFormat();
1312 #ifdef DEBUG
1313 const SurfaceCaps& caps = Caps();
1314 MOZ_ASSERT(!caps.any, "Did you forget to DetermineCaps()?");
1315
1316 MOZ_ASSERT(caps.color == !!format.red);
1317 MOZ_ASSERT(caps.color == !!format.green);
1318 MOZ_ASSERT(caps.color == !!format.blue);
1319
1320 MOZ_ASSERT(caps.alpha == !!format.alpha);
1321
1322 // These we either must have if they're requested, or
1323 // we can have if they're not.
1324 MOZ_ASSERT(caps.depth == !!format.depth || !caps.depth);
1325 MOZ_ASSERT(caps.stencil == !!format.stencil || !caps.stencil);
1326
1327 MOZ_ASSERT(caps.antialias == (format.samples > 1));
1328 #endif
1329 mPixelFormat = new PixelBufferFormat(format);
1330 }
1331
1332 GLFormats
1333 GLContext::ChooseGLFormats(const SurfaceCaps& caps) const
1334 {
1335 GLFormats formats;
1336
1337 // If we're on ES2 hardware and we have an explicit request for 16 bits of color or less
1338 // OR we don't support full 8-bit color, return a 4444 or 565 format.
1339 bool bpp16 = caps.bpp16;
1340 if (IsGLES()) {
1341 if (!IsExtensionSupported(OES_rgb8_rgba8))
1342 bpp16 = true;
1343 } else {
1344 // RGB565 is uncommon on desktop, requiring ARB_ES2_compatibility.
1345 // Since it's also vanishingly useless there, let's not support it.
1346 bpp16 = false;
1347 }
1348
1349 if (bpp16) {
1350 MOZ_ASSERT(IsGLES());
1351 if (caps.alpha) {
1352 formats.color_texInternalFormat = LOCAL_GL_RGBA;
1353 formats.color_texFormat = LOCAL_GL_RGBA;
1354 formats.color_texType = LOCAL_GL_UNSIGNED_SHORT_4_4_4_4;
1355 formats.color_rbFormat = LOCAL_GL_RGBA4;
1356 } else {
1357 formats.color_texInternalFormat = LOCAL_GL_RGB;
1358 formats.color_texFormat = LOCAL_GL_RGB;
1359 formats.color_texType = LOCAL_GL_UNSIGNED_SHORT_5_6_5;
1360 formats.color_rbFormat = LOCAL_GL_RGB565;
1361 }
1362 } else {
1363 formats.color_texType = LOCAL_GL_UNSIGNED_BYTE;
1364
1365 if (caps.alpha) {
1366 formats.color_texInternalFormat = IsGLES() ? LOCAL_GL_RGBA : LOCAL_GL_RGBA8;
1367 formats.color_texFormat = LOCAL_GL_RGBA;
1368 formats.color_rbFormat = LOCAL_GL_RGBA8;
1369 } else {
1370 formats.color_texInternalFormat = IsGLES() ? LOCAL_GL_RGB : LOCAL_GL_RGB8;
1371 formats.color_texFormat = LOCAL_GL_RGB;
1372 formats.color_rbFormat = LOCAL_GL_RGB8;
1373 }
1374 }
1375
1376 uint32_t msaaLevel = gfxPrefs::MSAALevel();
1377 GLsizei samples = msaaLevel * msaaLevel;
1378 samples = std::min(samples, mMaxSamples);
1379
1380 // Bug 778765.
1381 if (WorkAroundDriverBugs() && samples == 1) {
1382 samples = 0;
1383 }
1384 formats.samples = samples;
1385
1386
1387 // Be clear that these are 0 if unavailable.
1388 formats.depthStencil = 0;
1389 if (!IsGLES() || IsExtensionSupported(OES_packed_depth_stencil)) {
1390 formats.depthStencil = LOCAL_GL_DEPTH24_STENCIL8;
1391 }
1392
1393 formats.depth = 0;
1394 if (IsGLES()) {
1395 if (IsExtensionSupported(OES_depth24)) {
1396 formats.depth = LOCAL_GL_DEPTH_COMPONENT24;
1397 } else {
1398 formats.depth = LOCAL_GL_DEPTH_COMPONENT16;
1399 }
1400 } else {
1401 formats.depth = LOCAL_GL_DEPTH_COMPONENT24;
1402 }
1403
1404 formats.stencil = LOCAL_GL_STENCIL_INDEX8;
1405
1406 return formats;
1407 }
1408
1409 bool
1410 GLContext::IsFramebufferComplete(GLuint fb, GLenum* pStatus)
1411 {
1412 MOZ_ASSERT(fb);
1413
1414 ScopedBindFramebuffer autoFB(this, fb);
1415 MOZ_ASSERT(fIsFramebuffer(fb));
1416
1417 GLenum status = fCheckFramebufferStatus(LOCAL_GL_FRAMEBUFFER);
1418 if (pStatus)
1419 *pStatus = status;
1420
1421 return status == LOCAL_GL_FRAMEBUFFER_COMPLETE;
1422 }
1423
1424 void
1425 GLContext::AttachBuffersToFB(GLuint colorTex, GLuint colorRB,
1426 GLuint depthRB, GLuint stencilRB,
1427 GLuint fb, GLenum target)
1428 {
1429 MOZ_ASSERT(fb);
1430 MOZ_ASSERT( !(colorTex && colorRB) );
1431
1432 ScopedBindFramebuffer autoFB(this, fb);
1433 MOZ_ASSERT(fIsFramebuffer(fb)); // It only counts after being bound.
1434
1435 if (colorTex) {
1436 MOZ_ASSERT(fIsTexture(colorTex));
1437 MOZ_ASSERT(target == LOCAL_GL_TEXTURE_2D ||
1438 target == LOCAL_GL_TEXTURE_RECTANGLE_ARB);
1439 fFramebufferTexture2D(LOCAL_GL_FRAMEBUFFER,
1440 LOCAL_GL_COLOR_ATTACHMENT0,
1441 target,
1442 colorTex,
1443 0);
1444 } else if (colorRB) {
1445 MOZ_ASSERT(fIsRenderbuffer(colorRB));
1446 fFramebufferRenderbuffer(LOCAL_GL_FRAMEBUFFER,
1447 LOCAL_GL_COLOR_ATTACHMENT0,
1448 LOCAL_GL_RENDERBUFFER,
1449 colorRB);
1450 }
1451
1452 if (depthRB) {
1453 MOZ_ASSERT(fIsRenderbuffer(depthRB));
1454 fFramebufferRenderbuffer(LOCAL_GL_FRAMEBUFFER,
1455 LOCAL_GL_DEPTH_ATTACHMENT,
1456 LOCAL_GL_RENDERBUFFER,
1457 depthRB);
1458 }
1459
1460 if (stencilRB) {
1461 MOZ_ASSERT(fIsRenderbuffer(stencilRB));
1462 fFramebufferRenderbuffer(LOCAL_GL_FRAMEBUFFER,
1463 LOCAL_GL_STENCIL_ATTACHMENT,
1464 LOCAL_GL_RENDERBUFFER,
1465 stencilRB);
1466 }
1467 }
1468
1469 bool
1470 GLContext::AssembleOffscreenFBs(const GLuint colorMSRB,
1471 const GLuint depthRB,
1472 const GLuint stencilRB,
1473 const GLuint texture,
1474 GLuint* drawFB_out,
1475 GLuint* readFB_out)
1476 {
1477 if (!colorMSRB && !texture) {
1478 MOZ_ASSERT(!depthRB && !stencilRB);
1479
1480 if (drawFB_out)
1481 *drawFB_out = 0;
1482 if (readFB_out)
1483 *readFB_out = 0;
1484
1485 return true;
1486 }
1487
1488 ScopedBindFramebuffer autoFB(this);
1489
1490 GLuint drawFB = 0;
1491 GLuint readFB = 0;
1492
1493 if (texture) {
1494 readFB = 0;
1495 fGenFramebuffers(1, &readFB);
1496 BindFB(readFB);
1497 fFramebufferTexture2D(LOCAL_GL_FRAMEBUFFER,
1498 LOCAL_GL_COLOR_ATTACHMENT0,
1499 LOCAL_GL_TEXTURE_2D,
1500 texture,
1501 0);
1502 }
1503
1504 if (colorMSRB) {
1505 drawFB = 0;
1506 fGenFramebuffers(1, &drawFB);
1507 BindFB(drawFB);
1508 fFramebufferRenderbuffer(LOCAL_GL_FRAMEBUFFER,
1509 LOCAL_GL_COLOR_ATTACHMENT0,
1510 LOCAL_GL_RENDERBUFFER,
1511 colorMSRB);
1512 } else {
1513 drawFB = readFB;
1514 }
1515 MOZ_ASSERT(GetFB() == drawFB);
1516
1517 if (depthRB) {
1518 fFramebufferRenderbuffer(LOCAL_GL_FRAMEBUFFER,
1519 LOCAL_GL_DEPTH_ATTACHMENT,
1520 LOCAL_GL_RENDERBUFFER,
1521 depthRB);
1522 }
1523
1524 if (stencilRB) {
1525 fFramebufferRenderbuffer(LOCAL_GL_FRAMEBUFFER,
1526 LOCAL_GL_STENCIL_ATTACHMENT,
1527 LOCAL_GL_RENDERBUFFER,
1528 stencilRB);
1529 }
1530
1531 // We should be all resized. Check for framebuffer completeness.
1532 GLenum status;
1533 bool isComplete = true;
1534
1535 if (!IsFramebufferComplete(drawFB, &status)) {
1536 NS_WARNING("DrawFBO: Incomplete");
1537 #ifdef DEBUG
1538 if (DebugMode()) {
1539 printf_stderr("Framebuffer status: %X\n", status);
1540 }
1541 #endif
1542 isComplete = false;
1543 }
1544
1545 if (!IsFramebufferComplete(readFB, &status)) {
1546 NS_WARNING("ReadFBO: Incomplete");
1547 #ifdef DEBUG
1548 if (DebugMode()) {
1549 printf_stderr("Framebuffer status: %X\n", status);
1550 }
1551 #endif
1552 isComplete = false;
1553 }
1554
1555 if (drawFB_out) {
1556 *drawFB_out = drawFB;
1557 } else if (drawFB) {
1558 NS_RUNTIMEABORT("drawFB created when not requested!");
1559 }
1560
1561 if (readFB_out) {
1562 *readFB_out = readFB;
1563 } else if (readFB) {
1564 NS_RUNTIMEABORT("readFB created when not requested!");
1565 }
1566
1567 return isComplete;
1568 }
1569
1570
1571
1572 bool
1573 GLContext::PublishFrame()
1574 {
1575 MOZ_ASSERT(mScreen);
1576
1577 if (!mScreen->PublishFrame(OffscreenSize()))
1578 return false;
1579
1580 return true;
1581 }
1582
1583 SharedSurface_GL*
1584 GLContext::RequestFrame()
1585 {
1586 MOZ_ASSERT(mScreen);
1587
1588 SharedSurface* ret = mScreen->Stream()->SwapConsumer();
1589 if (!ret)
1590 return nullptr;
1591
1592 return SharedSurface_GL::Cast(ret);
1593 }
1594
1595
1596
1597 void
1598 GLContext::ClearSafely()
1599 {
1600 // bug 659349 --- we must be very careful here: clearing a GL framebuffer is nontrivial, relies on a lot of state,
1601 // and in the case of the backbuffer of a WebGL context, state is exposed to scripts.
1602 //
1603 // The code here is taken from WebGLContext::ForceClearFramebufferWithDefaultValues, but I didn't find a good way of
1604 // sharing code with it. WebGL's code is somewhat performance-critical as it is typically called on every frame, so
1605 // WebGL keeps track of GL state to avoid having to query it everytime, and also tries to only do work for actually
1606 // present buffers (e.g. stencil buffer). Doing that here seems like premature optimization,
1607 // as ClearSafely() is called only when e.g. a canvas is resized, not on every animation frame.
1608
1609 realGLboolean scissorTestEnabled;
1610 realGLboolean ditherEnabled;
1611 realGLboolean colorWriteMask[4];
1612 realGLboolean depthWriteMask;
1613 GLint stencilWriteMaskFront, stencilWriteMaskBack;
1614 GLfloat colorClearValue[4];
1615 GLfloat depthClearValue;
1616 GLint stencilClearValue;
1617
1618 // save current GL state
1619 fGetBooleanv(LOCAL_GL_SCISSOR_TEST, &scissorTestEnabled);
1620 fGetBooleanv(LOCAL_GL_DITHER, &ditherEnabled);
1621 fGetBooleanv(LOCAL_GL_COLOR_WRITEMASK, colorWriteMask);
1622 fGetBooleanv(LOCAL_GL_DEPTH_WRITEMASK, &depthWriteMask);
1623 fGetIntegerv(LOCAL_GL_STENCIL_WRITEMASK, &stencilWriteMaskFront);
1624 fGetIntegerv(LOCAL_GL_STENCIL_BACK_WRITEMASK, &stencilWriteMaskBack);
1625 fGetFloatv(LOCAL_GL_COLOR_CLEAR_VALUE, colorClearValue);
1626 fGetFloatv(LOCAL_GL_DEPTH_CLEAR_VALUE, &depthClearValue);
1627 fGetIntegerv(LOCAL_GL_STENCIL_CLEAR_VALUE, &stencilClearValue);
1628
1629 // prepare GL state for clearing
1630 fDisable(LOCAL_GL_SCISSOR_TEST);
1631 fDisable(LOCAL_GL_DITHER);
1632
1633 fColorMask(1, 1, 1, 1);
1634 fClearColor(0.f, 0.f, 0.f, 0.f);
1635
1636 fDepthMask(1);
1637 fClearDepth(1.0f);
1638
1639 fStencilMask(0xffffffff);
1640 fClearStencil(0);
1641
1642 // do clear
1643 fClear(LOCAL_GL_COLOR_BUFFER_BIT |
1644 LOCAL_GL_DEPTH_BUFFER_BIT |
1645 LOCAL_GL_STENCIL_BUFFER_BIT);
1646
1647 // restore GL state after clearing
1648 fColorMask(colorWriteMask[0],
1649 colorWriteMask[1],
1650 colorWriteMask[2],
1651 colorWriteMask[3]);
1652 fClearColor(colorClearValue[0],
1653 colorClearValue[1],
1654 colorClearValue[2],
1655 colorClearValue[3]);
1656
1657 fDepthMask(depthWriteMask);
1658 fClearDepth(depthClearValue);
1659
1660 fStencilMaskSeparate(LOCAL_GL_FRONT, stencilWriteMaskFront);
1661 fStencilMaskSeparate(LOCAL_GL_BACK, stencilWriteMaskBack);
1662 fClearStencil(stencilClearValue);
1663
1664 if (ditherEnabled)
1665 fEnable(LOCAL_GL_DITHER);
1666 else
1667 fDisable(LOCAL_GL_DITHER);
1668
1669 if (scissorTestEnabled)
1670 fEnable(LOCAL_GL_SCISSOR_TEST);
1671 else
1672 fDisable(LOCAL_GL_SCISSOR_TEST);
1673
1674 }
1675
1676 void
1677 GLContext::MarkDestroyed()
1678 {
1679 if (IsDestroyed())
1680 return;
1681
1682 if (MakeCurrent()) {
1683 DestroyScreenBuffer();
1684
1685 mBlitHelper = nullptr;
1686 mBlitTextureImageHelper = nullptr;
1687 mReadTexImageHelper = nullptr;
1688
1689 mTexGarbageBin->GLContextTeardown();
1690 } else {
1691 NS_WARNING("MakeCurrent() failed during MarkDestroyed! Skipping GL object teardown.");
1692 }
1693
1694 mSymbols.Zero();
1695 }
1696
1697 #ifdef MOZ_ENABLE_GL_TRACKING
1698 void
1699 GLContext::CreatedProgram(GLContext *aOrigin, GLuint aName)
1700 {
1701 mTrackedPrograms.AppendElement(NamedResource(aOrigin, aName));
1702 }
1703
1704 void
1705 GLContext::CreatedShader(GLContext *aOrigin, GLuint aName)
1706 {
1707 mTrackedShaders.AppendElement(NamedResource(aOrigin, aName));
1708 }
1709
1710 void
1711 GLContext::CreatedBuffers(GLContext *aOrigin, GLsizei aCount, GLuint *aNames)
1712 {
1713 for (GLsizei i = 0; i < aCount; ++i) {
1714 mTrackedBuffers.AppendElement(NamedResource(aOrigin, aNames[i]));
1715 }
1716 }
1717
1718 void
1719 GLContext::CreatedQueries(GLContext *aOrigin, GLsizei aCount, GLuint *aNames)
1720 {
1721 for (GLsizei i = 0; i < aCount; ++i) {
1722 mTrackedQueries.AppendElement(NamedResource(aOrigin, aNames[i]));
1723 }
1724 }
1725
1726 void
1727 GLContext::CreatedTextures(GLContext *aOrigin, GLsizei aCount, GLuint *aNames)
1728 {
1729 for (GLsizei i = 0; i < aCount; ++i) {
1730 mTrackedTextures.AppendElement(NamedResource(aOrigin, aNames[i]));
1731 }
1732 }
1733
1734 void
1735 GLContext::CreatedFramebuffers(GLContext *aOrigin, GLsizei aCount, GLuint *aNames)
1736 {
1737 for (GLsizei i = 0; i < aCount; ++i) {
1738 mTrackedFramebuffers.AppendElement(NamedResource(aOrigin, aNames[i]));
1739 }
1740 }
1741
1742 void
1743 GLContext::CreatedRenderbuffers(GLContext *aOrigin, GLsizei aCount, GLuint *aNames)
1744 {
1745 for (GLsizei i = 0; i < aCount; ++i) {
1746 mTrackedRenderbuffers.AppendElement(NamedResource(aOrigin, aNames[i]));
1747 }
1748 }
1749
1750 static void
1751 RemoveNamesFromArray(GLContext *aOrigin, GLsizei aCount, const GLuint *aNames, nsTArray<GLContext::NamedResource>& aArray)
1752 {
1753 for (GLsizei j = 0; j < aCount; ++j) {
1754 GLuint name = aNames[j];
1755 // name 0 can be ignored
1756 if (name == 0)
1757 continue;
1758
1759 for (uint32_t i = 0; i < aArray.Length(); ++i) {
1760 if (aArray[i].name == name) {
1761 aArray.RemoveElementAt(i);
1762 break;
1763 }
1764 }
1765 }
1766 }
1767
1768 void
1769 GLContext::DeletedProgram(GLContext *aOrigin, GLuint aName)
1770 {
1771 RemoveNamesFromArray(aOrigin, 1, &aName, mTrackedPrograms);
1772 }
1773
1774 void
1775 GLContext::DeletedShader(GLContext *aOrigin, GLuint aName)
1776 {
1777 RemoveNamesFromArray(aOrigin, 1, &aName, mTrackedShaders);
1778 }
1779
1780 void
1781 GLContext::DeletedBuffers(GLContext *aOrigin, GLsizei aCount, const GLuint *aNames)
1782 {
1783 RemoveNamesFromArray(aOrigin, aCount, aNames, mTrackedBuffers);
1784 }
1785
1786 void
1787 GLContext::DeletedQueries(GLContext *aOrigin, GLsizei aCount, const GLuint *aNames)
1788 {
1789 RemoveNamesFromArray(aOrigin, aCount, aNames, mTrackedQueries);
1790 }
1791
1792 void
1793 GLContext::DeletedTextures(GLContext *aOrigin, GLsizei aCount, const GLuint *aNames)
1794 {
1795 RemoveNamesFromArray(aOrigin, aCount, aNames, mTrackedTextures);
1796 }
1797
1798 void
1799 GLContext::DeletedFramebuffers(GLContext *aOrigin, GLsizei aCount, const GLuint *aNames)
1800 {
1801 RemoveNamesFromArray(aOrigin, aCount, aNames, mTrackedFramebuffers);
1802 }
1803
1804 void
1805 GLContext::DeletedRenderbuffers(GLContext *aOrigin, GLsizei aCount, const GLuint *aNames)
1806 {
1807 RemoveNamesFromArray(aOrigin, aCount, aNames, mTrackedRenderbuffers);
1808 }
1809
1810 static void
1811 MarkContextDestroyedInArray(GLContext *aContext, nsTArray<GLContext::NamedResource>& aArray)
1812 {
1813 for (uint32_t i = 0; i < aArray.Length(); ++i) {
1814 if (aArray[i].origin == aContext)
1815 aArray[i].originDeleted = true;
1816 }
1817 }
1818
1819 void
1820 GLContext::SharedContextDestroyed(GLContext *aChild)
1821 {
1822 MarkContextDestroyedInArray(aChild, mTrackedPrograms);
1823 MarkContextDestroyedInArray(aChild, mTrackedShaders);
1824 MarkContextDestroyedInArray(aChild, mTrackedTextures);
1825 MarkContextDestroyedInArray(aChild, mTrackedFramebuffers);
1826 MarkContextDestroyedInArray(aChild, mTrackedRenderbuffers);
1827 MarkContextDestroyedInArray(aChild, mTrackedBuffers);
1828 MarkContextDestroyedInArray(aChild, mTrackedQueries);
1829 }
1830
1831 static void
1832 ReportArrayContents(const char *title, const nsTArray<GLContext::NamedResource>& aArray)
1833 {
1834 if (aArray.Length() == 0)
1835 return;
1836
1837 printf_stderr("%s:\n", title);
1838
1839 nsTArray<GLContext::NamedResource> copy(aArray);
1840 copy.Sort();
1841
1842 GLContext *lastContext = nullptr;
1843 for (uint32_t i = 0; i < copy.Length(); ++i) {
1844 if (lastContext != copy[i].origin) {
1845 if (lastContext)
1846 printf_stderr("\n");
1847 printf_stderr(" [%p - %s] ", copy[i].origin, copy[i].originDeleted ? "deleted" : "live");
1848 lastContext = copy[i].origin;
1849 }
1850 printf_stderr("%d ", copy[i].name);
1851 }
1852 printf_stderr("\n");
1853 }
1854
1855 void
1856 GLContext::ReportOutstandingNames()
1857 {
1858 if (!DebugMode())
1859 return;
1860
1861 printf_stderr("== GLContext %p Outstanding ==\n", this);
1862
1863 ReportArrayContents("Outstanding Textures", mTrackedTextures);
1864 ReportArrayContents("Outstanding Buffers", mTrackedBuffers);
1865 ReportArrayContents("Outstanding Queries", mTrackedQueries);
1866 ReportArrayContents("Outstanding Programs", mTrackedPrograms);
1867 ReportArrayContents("Outstanding Shaders", mTrackedShaders);
1868 ReportArrayContents("Outstanding Framebuffers", mTrackedFramebuffers);
1869 ReportArrayContents("Outstanding Renderbuffers", mTrackedRenderbuffers);
1870 }
1871
1872 #endif /* DEBUG */
1873
1874
1875 void
1876 GLContext::GuaranteeResolve()
1877 {
1878 if (mScreen) {
1879 mScreen->AssureBlitted();
1880 }
1881 fFinish();
1882 }
1883
1884 const gfx::IntSize&
1885 GLContext::OffscreenSize() const
1886 {
1887 MOZ_ASSERT(IsOffscreen());
1888 return mScreen->Size();
1889 }
1890
1891 bool
1892 GLContext::CreateScreenBufferImpl(const IntSize& size, const SurfaceCaps& caps)
1893 {
1894 GLScreenBuffer* newScreen = GLScreenBuffer::Create(this, size, caps);
1895 if (!newScreen)
1896 return false;
1897
1898 if (!newScreen->Resize(size)) {
1899 delete newScreen;
1900 return false;
1901 }
1902
1903 DestroyScreenBuffer();
1904
1905 // This will rebind to 0 (Screen) if needed when
1906 // it falls out of scope.
1907 ScopedBindFramebuffer autoFB(this);
1908
1909 mScreen = newScreen;
1910
1911 return true;
1912 }
1913
1914 bool
1915 GLContext::ResizeScreenBuffer(const IntSize& size)
1916 {
1917 if (!IsOffscreenSizeAllowed(size))
1918 return false;
1919
1920 return mScreen->Resize(size);
1921 }
1922
1923
1924 void
1925 GLContext::DestroyScreenBuffer()
1926 {
1927 delete mScreen;
1928 mScreen = nullptr;
1929 }
1930
1931 void
1932 GLContext::ForceDirtyScreen()
1933 {
1934 ScopedBindFramebuffer autoFB(0);
1935
1936 BeforeGLDrawCall();
1937 // no-op; just pretend we did something
1938 AfterGLDrawCall();
1939 }
1940
1941 void
1942 GLContext::CleanDirtyScreen()
1943 {
1944 ScopedBindFramebuffer autoFB(0);
1945
1946 BeforeGLReadCall();
1947 // no-op; we just want to make sure the Read FBO is updated if it needs to be
1948 AfterGLReadCall();
1949 }
1950
1951 void
1952 GLContext::EmptyTexGarbageBin()
1953 {
1954 TexGarbageBin()->EmptyGarbage();
1955 }
1956
1957 bool
1958 GLContext::IsOffscreenSizeAllowed(const IntSize& aSize) const {
1959 int32_t biggerDimension = std::max(aSize.width, aSize.height);
1960 int32_t maxAllowed = std::min(mMaxRenderbufferSize, mMaxTextureSize);
1961 return biggerDimension <= maxAllowed;
1962 }
1963
1964 bool
1965 GLContext::IsOwningThreadCurrent()
1966 {
1967 return NS_GetCurrentThread() == mOwningThread;
1968 }
1969
1970 void
1971 GLContext::DispatchToOwningThread(nsIRunnable *event)
1972 {
1973 // Before dispatching, we need to ensure we're not in the middle of
1974 // shutting down. Dispatching runnables in the middle of shutdown
1975 // (that is, when the main thread is no longer get-able) can cause them
1976 // to leak. See Bug 741319, and Bug 744115.
1977 nsCOMPtr<nsIThread> mainThread;
1978 if (NS_SUCCEEDED(NS_GetMainThread(getter_AddRefs(mainThread)))) {
1979 mOwningThread->Dispatch(event, NS_DISPATCH_NORMAL);
1980 }
1981 }
1982
1983 GLBlitHelper*
1984 GLContext::BlitHelper()
1985 {
1986 if (!mBlitHelper) {
1987 mBlitHelper = new GLBlitHelper(this);
1988 }
1989
1990 return mBlitHelper;
1991 }
1992
1993 GLBlitTextureImageHelper*
1994 GLContext::BlitTextureImageHelper()
1995 {
1996 if (!mBlitTextureImageHelper) {
1997 mBlitTextureImageHelper = new GLBlitTextureImageHelper(this);
1998 }
1999
2000 return mBlitTextureImageHelper;
2001 }
2002
2003 GLReadTexImageHelper*
2004 GLContext::ReadTexImageHelper()
2005 {
2006 if (!mReadTexImageHelper) {
2007 mReadTexImageHelper = new GLReadTexImageHelper(this);
2008 }
2009
2010 return mReadTexImageHelper;
2011 }
2012
2013 bool
2014 DoesStringMatch(const char* aString, const char *aWantedString)
2015 {
2016 if (!aString || !aWantedString)
2017 return false;
2018
2019 const char *occurrence = strstr(aString, aWantedString);
2020
2021 // aWanted not found
2022 if (!occurrence)
2023 return false;
2024
2025 // aWantedString preceded by alpha character
2026 if (occurrence != aString && isalpha(*(occurrence-1)))
2027 return false;
2028
2029 // aWantedVendor followed by alpha character
2030 const char *afterOccurrence = occurrence + strlen(aWantedString);
2031 if (isalpha(*afterOccurrence))
2032 return false;
2033
2034 return true;
2035 }
2036
2037 } /* namespace gl */
2038 } /* namespace mozilla */

mercurial