Coverage Report

Created: 2018-09-25 14:53

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