Coverage Report

Created: 2018-09-25 14:53

/src/mozilla-central/gfx/gl/GLContextProviderGLX.cpp
Line
Count
Source (jump to first uncovered line)
1
/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2
/* This Source Code Form is subject to the terms of the Mozilla Public
3
 * License, v. 2.0. If a copy of the MPL was not distributed with this
4
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
5
6
#ifdef MOZ_WIDGET_GTK
7
#include <gdk/gdk.h>
8
#include <gdk/gdkx.h>
9
0
#define GET_NATIVE_WINDOW(aWidget) GDK_WINDOW_XID((GdkWindow*) aWidget->GetNativeData(NS_NATIVE_WINDOW))
10
#endif
11
12
#include <X11/Xlib.h>
13
#include <X11/Xutil.h>
14
#include "X11UndefineNone.h"
15
16
#include "mozilla/MathAlgorithms.h"
17
#include "mozilla/StaticPtr.h"
18
#include "mozilla/layers/CompositorOptions.h"
19
#include "mozilla/Range.h"
20
#include "mozilla/ScopeExit.h"
21
#include "mozilla/widget/CompositorWidget.h"
22
#include "mozilla/widget/GtkCompositorWidget.h"
23
#include "mozilla/Unused.h"
24
25
#include "prenv.h"
26
#include "GLContextProvider.h"
27
#include "GLLibraryLoader.h"
28
#include "nsDebug.h"
29
#include "nsIWidget.h"
30
#include "GLXLibrary.h"
31
#include "gfxXlibSurface.h"
32
#include "gfxContext.h"
33
#include "gfxEnv.h"
34
#include "gfxPlatform.h"
35
#include "GLContextGLX.h"
36
#include "gfxUtils.h"
37
#include "gfx2DGlue.h"
38
#include "GLScreenBuffer.h"
39
#include "gfxPrefs.h"
40
41
#include "gfxCrashReporterUtils.h"
42
43
#ifdef MOZ_WIDGET_GTK
44
#include "gfxPlatformGtk.h"
45
#endif
46
47
namespace mozilla {
48
namespace gl {
49
50
using namespace mozilla::gfx;
51
using namespace mozilla::widget;
52
53
GLXLibrary sGLXLibrary;
54
55
static inline bool
56
HasExtension(const char* aExtensions, const char* aRequiredExtension)
57
0
{
58
0
    return GLContext::ListHasExtension(
59
0
        reinterpret_cast<const GLubyte*>(aExtensions), aRequiredExtension);
60
0
}
61
62
bool
63
GLXLibrary::EnsureInitialized()
64
0
{
65
0
    if (mInitialized) {
66
0
        return true;
67
0
    }
68
0
69
0
    // Don't repeatedly try to initialize.
70
0
    if (mTriedInitializing) {
71
0
        return false;
72
0
    }
73
0
    mTriedInitializing = true;
74
0
75
0
    // Force enabling s3 texture compression. (Bug 774134)
76
0
    PR_SetEnv("force_s3tc_enable=true");
77
0
78
0
    if (!mOGLLibrary) {
79
0
        const char* libGLfilename = nullptr;
80
0
        bool forceFeatureReport = false;
81
0
82
0
        // see e.g. bug 608526: it is intrinsically interesting to know whether we have dynamically linked to libGL.so.1
83
0
        // because at least the NVIDIA implementation requires an executable stack, which causes mprotect calls,
84
0
        // which trigger glibc bug http://sourceware.org/bugzilla/show_bug.cgi?id=12225
85
#ifdef __OpenBSD__
86
        libGLfilename = "libGL.so";
87
#else
88
        libGLfilename = "libGL.so.1";
89
0
#endif
90
0
91
0
        ScopedGfxFeatureReporter reporter(libGLfilename, forceFeatureReport);
92
0
        mOGLLibrary = PR_LoadLibrary(libGLfilename);
93
0
        if (!mOGLLibrary) {
94
0
            NS_WARNING("Couldn't load OpenGL shared library.");
95
0
            return false;
96
0
        }
97
0
        reporter.SetSuccessful();
98
0
    }
99
0
100
0
    if (gfxEnv::GlxDebug()) {
101
0
        mDebug = true;
102
0
    }
103
0
104
0
#define SYMBOL(X) { (PRFuncPtr*)&mSymbols.f##X, { "glX" #X, nullptr } }
105
0
#define END_OF_SYMBOLS { nullptr, { nullptr } }
106
0
107
0
    const GLLibraryLoader::SymLoadStruct symbols[] = {
108
0
        /* functions that were in GLX 1.0 */
109
0
        SYMBOL(DestroyContext),
110
0
        SYMBOL(MakeCurrent),
111
0
        SYMBOL(SwapBuffers),
112
0
        SYMBOL(QueryVersion),
113
0
        SYMBOL(GetConfig),
114
0
        SYMBOL(GetCurrentContext),
115
0
        SYMBOL(WaitGL),
116
0
        SYMBOL(WaitX),
117
0
118
0
        /* functions introduced in GLX 1.1 */
119
0
        SYMBOL(QueryExtensionsString),
120
0
        SYMBOL(GetClientString),
121
0
        SYMBOL(QueryServerString),
122
0
123
0
        /* functions introduced in GLX 1.3 */
124
0
        SYMBOL(ChooseFBConfig),
125
0
        SYMBOL(ChooseVisual),
126
0
        SYMBOL(GetFBConfigAttrib),
127
0
        SYMBOL(GetFBConfigs),
128
0
        SYMBOL(CreatePixmap),
129
0
        SYMBOL(DestroyPixmap),
130
0
        SYMBOL(CreateNewContext),
131
0
132
0
        // Core in GLX 1.4, ARB extension before.
133
0
        { (PRFuncPtr*)&mSymbols.fGetProcAddress, { "glXGetProcAddress",
134
0
                                                   "glXGetProcAddressARB",
135
0
                                                   nullptr } },
136
0
        END_OF_SYMBOLS
137
0
    };
138
0
    if (!GLLibraryLoader::LoadSymbols(mOGLLibrary, symbols)) {
139
0
        NS_WARNING("Couldn't load required GLX symbols.");
140
0
        return false;
141
0
    }
142
0
143
0
    Display* display = DefaultXDisplay();
144
0
    int screen = DefaultScreen(display);
145
0
146
0
    {
147
0
        int major, minor;
148
0
        if (!fQueryVersion(display, &major, &minor) ||
149
0
            major != 1 || minor < 3)
150
0
        {
151
0
            NS_ERROR("GLX version older than 1.3. (released in 1998)");
152
0
            return false;
153
0
        }
154
0
    }
155
0
156
0
    const GLLibraryLoader::SymLoadStruct symbols_texturefrompixmap[] = {
157
0
        SYMBOL(BindTexImageEXT),
158
0
        SYMBOL(ReleaseTexImageEXT),
159
0
        END_OF_SYMBOLS
160
0
    };
161
0
162
0
    const GLLibraryLoader::SymLoadStruct symbols_createcontext[] = {
163
0
        SYMBOL(CreateContextAttribsARB),
164
0
        END_OF_SYMBOLS
165
0
    };
166
0
167
0
    const GLLibraryLoader::SymLoadStruct symbols_videosync[] = {
168
0
        SYMBOL(GetVideoSyncSGI),
169
0
        SYMBOL(WaitVideoSyncSGI),
170
0
        END_OF_SYMBOLS
171
0
    };
172
0
173
0
    const GLLibraryLoader::SymLoadStruct symbols_swapcontrol[] = {
174
0
        SYMBOL(SwapIntervalEXT),
175
0
        END_OF_SYMBOLS
176
0
    };
177
0
178
0
    const auto lookupFunction =
179
0
        (GLLibraryLoader::PlatformLookupFunction)mSymbols.fGetProcAddress;
180
0
181
0
    const auto fnLoadSymbols = [&](const GLLibraryLoader::SymLoadStruct* symbols) {
182
0
        if (GLLibraryLoader::LoadSymbols(mOGLLibrary, symbols, lookupFunction))
183
0
            return true;
184
0
185
0
        GLLibraryLoader::ClearSymbols(symbols);
186
0
        return false;
187
0
    };
188
0
189
0
    const char* clientVendor = fGetClientString(display, LOCAL_GLX_VENDOR);
190
0
    const char* serverVendor = fQueryServerString(display, screen, LOCAL_GLX_VENDOR);
191
0
    const char* extensionsStr = fQueryExtensionsString(display, screen);
192
0
193
0
    if (HasExtension(extensionsStr, "GLX_EXT_texture_from_pixmap") &&
194
0
        fnLoadSymbols(symbols_texturefrompixmap))
195
0
    {
196
0
        mUseTextureFromPixmap = gfxPrefs::UseGLXTextureFromPixmap();
197
0
    } else {
198
0
        mUseTextureFromPixmap = false;
199
0
        NS_WARNING("Texture from pixmap disabled");
200
0
    }
201
0
202
0
    if (HasExtension(extensionsStr, "GLX_ARB_create_context") &&
203
0
        HasExtension(extensionsStr, "GLX_ARB_create_context_profile") &&
204
0
        fnLoadSymbols(symbols_createcontext))
205
0
    {
206
0
        mHasCreateContextAttribs = true;
207
0
    }
208
0
209
0
    if (HasExtension(extensionsStr, "GLX_ARB_create_context_robustness")) {
210
0
        mHasRobustness = true;
211
0
    }
212
0
213
0
    if (HasExtension(extensionsStr, "GLX_NV_robustness_video_memory_purge")) {
214
0
        mHasVideoMemoryPurge = true;
215
0
    }
216
0
217
0
    if (HasExtension(extensionsStr, "GLX_SGI_video_sync") &&
218
0
        fnLoadSymbols(symbols_videosync))
219
0
    {
220
0
        mHasVideoSync = true;
221
0
    }
222
0
223
0
    if (!HasExtension(extensionsStr, "GLX_EXT_swap_control") ||
224
0
        !fnLoadSymbols(symbols_swapcontrol))
225
0
    {
226
0
        NS_WARNING("GLX_swap_control unsupported, ASAP mode may still block on buffer swaps.");
227
0
    }
228
0
229
0
    mIsATI = serverVendor && DoesStringMatch(serverVendor, "ATI");
230
0
    mIsNVIDIA = serverVendor && DoesStringMatch(serverVendor, "NVIDIA Corporation");
231
0
    mClientIsMesa = clientVendor && DoesStringMatch(clientVendor, "Mesa");
232
0
233
0
    mInitialized = true;
234
0
235
0
    return true;
236
0
}
237
238
bool
239
GLXLibrary::SupportsTextureFromPixmap(gfxASurface* aSurface)
240
0
{
241
0
    if (!EnsureInitialized()) {
242
0
        return false;
243
0
    }
244
0
245
0
    if (aSurface->GetType() != gfxSurfaceType::Xlib || !mUseTextureFromPixmap) {
246
0
        return false;
247
0
    }
248
0
249
0
    return true;
250
0
}
251
252
bool
253
GLXLibrary::SupportsVideoSync()
254
0
{
255
0
    if (!EnsureInitialized()) {
256
0
        return false;
257
0
    }
258
0
259
0
    return mHasVideoSync;
260
0
}
261
262
GLXPixmap
263
GLXLibrary::CreatePixmap(gfxASurface* aSurface)
264
0
{
265
0
    if (!SupportsTextureFromPixmap(aSurface)) {
266
0
        return X11None;
267
0
    }
268
0
269
0
    gfxXlibSurface* xs = static_cast<gfxXlibSurface*>(aSurface);
270
0
    const XRenderPictFormat* format = xs->XRenderFormat();
271
0
    if (!format || format->type != PictTypeDirect) {
272
0
        return X11None;
273
0
    }
274
0
    const XRenderDirectFormat& direct = format->direct;
275
0
    int alphaSize = FloorLog2(direct.alphaMask + 1);
276
0
    NS_ASSERTION((1 << alphaSize) - 1 == direct.alphaMask,
277
0
                 "Unexpected render format with non-adjacent alpha bits");
278
0
279
0
    int attribs[] = { LOCAL_GLX_DOUBLEBUFFER, False,
280
0
                      LOCAL_GLX_DRAWABLE_TYPE, LOCAL_GLX_PIXMAP_BIT,
281
0
                      LOCAL_GLX_ALPHA_SIZE, alphaSize,
282
0
                      (alphaSize ? LOCAL_GLX_BIND_TO_TEXTURE_RGBA_EXT
283
0
                       : LOCAL_GLX_BIND_TO_TEXTURE_RGB_EXT), True,
284
0
                      LOCAL_GLX_RENDER_TYPE, LOCAL_GLX_RGBA_BIT,
285
0
                      X11None };
286
0
287
0
    int numConfigs = 0;
288
0
    Display* display = xs->XDisplay();
289
0
    int xscreen = DefaultScreen(display);
290
0
291
0
    ScopedXFree<GLXFBConfig> cfgs(fChooseFBConfig(display,
292
0
                                                  xscreen,
293
0
                                                  attribs,
294
0
                                                  &numConfigs));
295
0
296
0
    // Find an fbconfig that matches the pixel format used on the Pixmap.
297
0
    int matchIndex = -1;
298
0
    unsigned long redMask =
299
0
        static_cast<unsigned long>(direct.redMask) << direct.red;
300
0
    unsigned long greenMask =
301
0
        static_cast<unsigned long>(direct.greenMask) << direct.green;
302
0
    unsigned long blueMask =
303
0
        static_cast<unsigned long>(direct.blueMask) << direct.blue;
304
0
    // This is true if the Pixmap has bits for alpha or unused bits.
305
0
    bool haveNonColorBits =
306
0
        ~(redMask | greenMask | blueMask) != -1UL << format->depth;
307
0
308
0
    for (int i = 0; i < numConfigs; i++) {
309
0
        int id = X11None;
310
0
        sGLXLibrary.fGetFBConfigAttrib(display, cfgs[i], LOCAL_GLX_VISUAL_ID, &id);
311
0
        Visual* visual;
312
0
        int depth;
313
0
        FindVisualAndDepth(display, id, &visual, &depth);
314
0
        if (!visual ||
315
0
            visual->c_class != TrueColor ||
316
0
            visual->red_mask != redMask ||
317
0
            visual->green_mask != greenMask ||
318
0
            visual->blue_mask != blueMask ) {
319
0
            continue;
320
0
        }
321
0
322
0
        // Historically Xlib Visuals did not try to represent an alpha channel
323
0
        // and there was no means to use an alpha channel on a Pixmap.  The
324
0
        // Xlib Visual from the fbconfig was not intended to have any
325
0
        // information about alpha bits.
326
0
        //
327
0
        // Since then, RENDER has added formats for 32 bit depth Pixmaps.
328
0
        // Some of these formats have bits for alpha and some have unused
329
0
        // bits.
330
0
        //
331
0
        // Then the Composite extension added a 32 bit depth Visual intended
332
0
        // for Windows with an alpha channel, so bits not in the visual color
333
0
        // masks were expected to be treated as alpha bits.
334
0
        //
335
0
        // Usually GLX counts only color bits in the Visual depth, but the
336
0
        // depth of Composite's ARGB Visual includes alpha bits.  However,
337
0
        // bits not in the color masks are not necessarily alpha bits because
338
0
        // sometimes (NVIDIA) 32 bit Visuals are added for fbconfigs with 32
339
0
        // bit BUFFER_SIZE but zero alpha bits and 24 color bits (NVIDIA
340
0
        // again).
341
0
        //
342
0
        // This checks that the depth matches in one of the two ways.
343
0
        // NVIDIA now forces format->depth == depth so only the first way
344
0
        // is checked for NVIDIA
345
0
        if (depth != format->depth &&
346
0
            (mIsNVIDIA || depth != format->depth - alphaSize) ) {
347
0
            continue;
348
0
        }
349
0
350
0
        // If all bits of the Pixmap are color bits and the Pixmap depth
351
0
        // matches the depth of the fbconfig visual, then we can assume that
352
0
        // the driver will do whatever is necessary to ensure that any
353
0
        // GLXPixmap alpha bits are treated as set.  We can skip the
354
0
        // ALPHA_SIZE check in this situation.  We need to skip this check for
355
0
        // situations (ATI) where there are no fbconfigs without alpha bits.
356
0
        //
357
0
        // glXChooseFBConfig should prefer configs with smaller
358
0
        // LOCAL_GLX_BUFFER_SIZE, so we should still get zero alpha bits if
359
0
        // available, except perhaps with NVIDIA drivers where buffer size is
360
0
        // not the specified sum of the component sizes.
361
0
        if (haveNonColorBits) {
362
0
            // There are bits in the Pixmap format that haven't been matched
363
0
            // against the fbconfig visual.  These bits could either represent
364
0
            // alpha or be unused, so just check that the number of alpha bits
365
0
            // matches.
366
0
            int size = 0;
367
0
            sGLXLibrary.fGetFBConfigAttrib(display, cfgs[i],
368
0
                                           LOCAL_GLX_ALPHA_SIZE, &size);
369
0
            if (size != alphaSize) {
370
0
                continue;
371
0
            }
372
0
        }
373
0
374
0
        matchIndex = i;
375
0
        break;
376
0
    }
377
0
    if (matchIndex == -1) {
378
0
        // GLX can't handle A8 surfaces, so this is not really unexpected. The
379
0
        // caller should deal with this situation.
380
0
        NS_WARNING_ASSERTION(
381
0
          format->depth == 8,
382
0
          "[GLX] Couldn't find a FBConfig matching Pixmap format");
383
0
        return X11None;
384
0
    }
385
0
386
0
    int pixmapAttribs[] = { LOCAL_GLX_TEXTURE_TARGET_EXT, LOCAL_GLX_TEXTURE_2D_EXT,
387
0
                            LOCAL_GLX_TEXTURE_FORMAT_EXT,
388
0
                            (alphaSize ? LOCAL_GLX_TEXTURE_FORMAT_RGBA_EXT
389
0
                             : LOCAL_GLX_TEXTURE_FORMAT_RGB_EXT),
390
0
                            X11None};
391
0
392
0
    GLXPixmap glxpixmap = fCreatePixmap(display,
393
0
                                        cfgs[matchIndex],
394
0
                                        xs->XDrawable(),
395
0
                                        pixmapAttribs);
396
0
397
0
    return glxpixmap;
398
0
}
399
400
void
401
GLXLibrary::DestroyPixmap(Display* aDisplay, GLXPixmap aPixmap)
402
0
{
403
0
    if (!mUseTextureFromPixmap) {
404
0
        return;
405
0
    }
406
0
407
0
    fDestroyPixmap(aDisplay, aPixmap);
408
0
}
409
410
void
411
GLXLibrary::BindTexImage(Display* aDisplay, GLXPixmap aPixmap)
412
0
{
413
0
    if (!mUseTextureFromPixmap) {
414
0
        return;
415
0
    }
416
0
417
0
    // Make sure all X drawing to the surface has finished before binding to a texture.
418
0
    if (mClientIsMesa) {
419
0
        // Using XSync instead of Mesa's glXWaitX, because its glxWaitX is a
420
0
        // noop when direct rendering unless the current drawable is a
421
0
        // single-buffer window.
422
0
        FinishX(aDisplay);
423
0
    } else {
424
0
        fWaitX();
425
0
    }
426
0
    fBindTexImage(aDisplay, aPixmap, LOCAL_GLX_FRONT_LEFT_EXT, nullptr);
427
0
}
428
429
void
430
GLXLibrary::ReleaseTexImage(Display* aDisplay, GLXPixmap aPixmap)
431
0
{
432
0
    if (!mUseTextureFromPixmap) {
433
0
        return;
434
0
    }
435
0
436
0
    fReleaseTexImage(aDisplay, aPixmap, LOCAL_GLX_FRONT_LEFT_EXT);
437
0
}
438
439
void
440
GLXLibrary::UpdateTexImage(Display* aDisplay, GLXPixmap aPixmap)
441
0
{
442
0
    // NVIDIA drivers don't require a rebind of the pixmap in order
443
0
    // to display an updated image, and it's faster not to do it.
444
0
    if (mIsNVIDIA) {
445
0
        fWaitX();
446
0
        return;
447
0
    }
448
0
449
0
    ReleaseTexImage(aDisplay, aPixmap);
450
0
    BindTexImage(aDisplay, aPixmap);
451
0
}
452
453
static int (*sOldErrorHandler)(Display*, XErrorEvent*);
454
ScopedXErrorHandler::ErrorEvent sErrorEvent;
455
static int GLXErrorHandler(Display* display, XErrorEvent* ev)
456
0
{
457
0
    if (!sErrorEvent.mError.error_code) {
458
0
        sErrorEvent.mError = *ev;
459
0
    }
460
0
    return 0;
461
0
}
462
463
void
464
GLXLibrary::BeforeGLXCall() const
465
0
{
466
0
    if (mDebug) {
467
0
        sOldErrorHandler = XSetErrorHandler(GLXErrorHandler);
468
0
    }
469
0
}
470
471
void
472
GLXLibrary::AfterGLXCall() const
473
0
{
474
0
    if (mDebug) {
475
0
        FinishX(DefaultXDisplay());
476
0
        if (sErrorEvent.mError.error_code) {
477
0
            char buffer[2048];
478
0
            XGetErrorText(DefaultXDisplay(), sErrorEvent.mError.error_code, buffer, sizeof(buffer));
479
0
            printf_stderr("X ERROR: %s (%i) - Request: %i.%i, Serial: %lu",
480
0
                          buffer,
481
0
                          sErrorEvent.mError.error_code,
482
0
                          sErrorEvent.mError.request_code,
483
0
                          sErrorEvent.mError.minor_code,
484
0
                          sErrorEvent.mError.serial);
485
0
            MOZ_ASSERT_UNREACHABLE("AfterGLXCall sErrorEvent");
486
0
        }
487
0
        XSetErrorHandler(sOldErrorHandler);
488
0
    }
489
0
}
490
491
already_AddRefed<GLContextGLX>
492
GLContextGLX::CreateGLContext(CreateContextFlags flags, const SurfaceCaps& caps,
493
                              bool isOffscreen, Display* display, GLXDrawable drawable,
494
                              GLXFBConfig cfg, bool deleteDrawable,
495
                              gfxXlibSurface* pixmap)
496
0
{
497
0
    GLXLibrary& glx = sGLXLibrary;
498
0
499
0
    int db = 0;
500
0
    int err = glx.fGetFBConfigAttrib(display, cfg,
501
0
                                      LOCAL_GLX_DOUBLEBUFFER, &db);
502
0
    if (LOCAL_GLX_BAD_ATTRIBUTE != err) {
503
0
        if (ShouldSpew()) {
504
0
            printf("[GLX] FBConfig is %sdouble-buffered\n", db ? "" : "not ");
505
0
        }
506
0
    }
507
0
508
0
    GLXContext context;
509
0
    RefPtr<GLContextGLX> glContext;
510
0
    bool error;
511
0
512
0
    OffMainThreadScopedXErrorHandler xErrorHandler;
513
0
514
0
    do {
515
0
        error = false;
516
0
517
0
        if (glx.HasCreateContextAttribs()) {
518
0
            AutoTArray<int, 13> attrib_list;
519
0
            if (glx.HasRobustness()) {
520
0
                const int robust_attribs[] = {
521
0
                    LOCAL_GLX_CONTEXT_FLAGS_ARB,
522
0
                    LOCAL_GLX_CONTEXT_ROBUST_ACCESS_BIT_ARB,
523
0
                    LOCAL_GLX_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB,
524
0
                    LOCAL_GLX_LOSE_CONTEXT_ON_RESET_ARB,
525
0
                };
526
0
                attrib_list.AppendElements(robust_attribs, MOZ_ARRAY_LENGTH(robust_attribs));
527
0
            }
528
0
            if (glx.HasVideoMemoryPurge()) {
529
0
                const int memory_purge_attribs[] = {
530
0
                    LOCAL_GLX_GENERATE_RESET_ON_VIDEO_MEMORY_PURGE_NV,
531
0
                    LOCAL_GL_TRUE,
532
0
                };
533
0
                attrib_list.AppendElements(memory_purge_attribs, MOZ_ARRAY_LENGTH(memory_purge_attribs));
534
0
            }
535
0
            if (!(flags & CreateContextFlags::REQUIRE_COMPAT_PROFILE)) {
536
0
                int core_attribs[] = {
537
0
                    LOCAL_GLX_CONTEXT_MAJOR_VERSION_ARB, 3,
538
0
                    LOCAL_GLX_CONTEXT_MINOR_VERSION_ARB, 2,
539
0
                    LOCAL_GLX_CONTEXT_PROFILE_MASK_ARB, LOCAL_GLX_CONTEXT_CORE_PROFILE_BIT_ARB,
540
0
                };
541
0
                attrib_list.AppendElements(core_attribs, MOZ_ARRAY_LENGTH(core_attribs));
542
0
            };
543
0
            attrib_list.AppendElement(0);
544
0
545
0
            context = glx.fCreateContextAttribs(
546
0
                display,
547
0
                cfg,
548
0
                nullptr,
549
0
                True,
550
0
                attrib_list.Elements());
551
0
        } else {
552
0
            context = glx.fCreateNewContext(
553
0
                display,
554
0
                cfg,
555
0
                LOCAL_GLX_RGBA_TYPE,
556
0
                nullptr,
557
0
                True);
558
0
        }
559
0
560
0
        if (context) {
561
0
            glContext = new GLContextGLX(flags, caps, isOffscreen, display, drawable,
562
0
                                         context, deleteDrawable, db, pixmap);
563
0
            if (!glContext->Init())
564
0
                error = true;
565
0
        } else {
566
0
            error = true;
567
0
        }
568
0
569
0
        error |= xErrorHandler.SyncAndGetError(display);
570
0
571
0
        if (error) {
572
0
            NS_WARNING("Failed to create GLXContext!");
573
0
            glContext = nullptr; // note: this must be done while the graceful X error handler is set,
574
0
                                // because glxMakeCurrent can give a GLXBadDrawable error
575
0
        }
576
0
577
0
        return glContext.forget();
578
0
    } while (true);
579
0
}
580
581
GLContextGLX::~GLContextGLX()
582
0
{
583
0
    MarkDestroyed();
584
0
585
0
    // Wrapped context should not destroy glxContext/Surface
586
0
    if (!mOwnsContext) {
587
0
        return;
588
0
    }
589
0
590
0
    // see bug 659842 comment 76
591
#ifdef DEBUG
592
    bool success =
593
#endif
594
0
    mGLX->fMakeCurrent(mDisplay, X11None, nullptr);
595
0
    MOZ_ASSERT(success,
596
0
               "glXMakeCurrent failed to release GL context before we call "
597
0
               "glXDestroyContext!");
598
0
599
0
    mGLX->fDestroyContext(mDisplay, mContext);
600
0
601
0
    if (mDeleteDrawable) {
602
0
        mGLX->fDestroyPixmap(mDisplay, mDrawable);
603
0
    }
604
0
}
605
606
607
bool
608
GLContextGLX::Init()
609
0
{
610
0
    SetupLookupFunction();
611
0
    if (!InitWithPrefix("gl", true)) {
612
0
        return false;
613
0
    }
614
0
615
0
    // EXT_framebuffer_object is not supported on Core contexts
616
0
    // so we'll also check for ARB_framebuffer_object
617
0
    if (!IsExtensionSupported(EXT_framebuffer_object) && !IsSupported(GLFeature::framebuffer_object))
618
0
        return false;
619
0
620
0
    return true;
621
0
}
622
623
bool
624
GLContextGLX::MakeCurrentImpl() const
625
0
{
626
0
    if (mGLX->IsMesa()) {
627
0
        // Read into the event queue to ensure that Mesa receives a
628
0
        // DRI2InvalidateBuffers event before drawing. See bug 1280653.
629
0
        Unused << XPending(mDisplay);
630
0
    }
631
0
632
0
    const bool succeeded = mGLX->fMakeCurrent(mDisplay, mDrawable, mContext);
633
0
    NS_ASSERTION(succeeded, "Failed to make GL context current!");
634
0
635
0
    if (!IsOffscreen() && mGLX->SupportsSwapControl()) {
636
0
        // Many GLX implementations default to blocking until the next
637
0
        // VBlank when calling glXSwapBuffers. We want to run unthrottled
638
0
        // in ASAP mode. See bug 1280744.
639
0
        const bool isASAP = (gfxPrefs::LayoutFrameRate() == 0);
640
0
        mGLX->fSwapInterval(mDisplay, mDrawable, isASAP ? 0 : 1);
641
0
    }
642
0
    return succeeded;
643
0
}
644
645
bool
646
GLContextGLX::IsCurrentImpl() const
647
0
{
648
0
    return mGLX->fGetCurrentContext() == mContext;
649
0
}
650
651
bool
652
GLContextGLX::SetupLookupFunction()
653
0
{
654
0
    mLookupFunc = (PlatformLookupFunction)sGLXLibrary.GetGetProcAddress();
655
0
    return true;
656
0
}
657
658
bool
659
GLContextGLX::IsDoubleBuffered() const
660
0
{
661
0
    return mDoubleBuffered;
662
0
}
663
664
bool
665
GLContextGLX::SwapBuffers()
666
0
{
667
0
    if (!mDoubleBuffered)
668
0
        return false;
669
0
    mGLX->fSwapBuffers(mDisplay, mDrawable);
670
0
    return true;
671
0
}
672
673
void
674
GLContextGLX::GetWSIInfo(nsCString* const out) const
675
0
{
676
0
    Display* display = DefaultXDisplay();
677
0
    int screen = DefaultScreen(display);
678
0
679
0
    int majorVersion, minorVersion;
680
0
    sGLXLibrary.fQueryVersion(display, &majorVersion, &minorVersion);
681
0
682
0
    out->Append(nsPrintfCString("GLX %u.%u", majorVersion, minorVersion));
683
0
684
0
    out->AppendLiteral("\nGLX_VENDOR(client): ");
685
0
    out->Append(sGLXLibrary.fGetClientString(display, LOCAL_GLX_VENDOR));
686
0
687
0
    out->AppendLiteral("\nGLX_VENDOR(server): ");
688
0
    out->Append(sGLXLibrary.fQueryServerString(display, screen, LOCAL_GLX_VENDOR));
689
0
690
0
    out->AppendLiteral("\nExtensions: ");
691
0
    out->Append(sGLXLibrary.fQueryExtensionsString(display, screen));
692
0
}
693
694
bool
695
GLContextGLX::OverrideDrawable(GLXDrawable drawable)
696
0
{
697
0
    if (Screen())
698
0
        Screen()->AssureBlitted();
699
0
    Bool result = mGLX->fMakeCurrent(mDisplay, drawable, mContext);
700
0
    return result;
701
0
}
702
703
bool
704
GLContextGLX::RestoreDrawable()
705
0
{
706
0
    return mGLX->fMakeCurrent(mDisplay, mDrawable, mContext);
707
0
}
708
709
GLContextGLX::GLContextGLX(
710
                  CreateContextFlags flags,
711
                  const SurfaceCaps& caps,
712
                  bool isOffscreen,
713
                  Display* aDisplay,
714
                  GLXDrawable aDrawable,
715
                  GLXContext aContext,
716
                  bool aDeleteDrawable,
717
                  bool aDoubleBuffered,
718
                  gfxXlibSurface* aPixmap)
719
    : GLContext(flags, caps, nullptr, isOffscreen),
720
      mContext(aContext),
721
      mDisplay(aDisplay),
722
      mDrawable(aDrawable),
723
      mDeleteDrawable(aDeleteDrawable),
724
      mDoubleBuffered(aDoubleBuffered),
725
      mGLX(&sGLXLibrary),
726
      mPixmap(aPixmap)
727
0
{
728
0
}
729
730
static bool
731
AreCompatibleVisuals(Visual* one, Visual* two)
732
0
{
733
0
    if (one->c_class != two->c_class) {
734
0
        return false;
735
0
    }
736
0
737
0
    if (one->red_mask != two->red_mask ||
738
0
        one->green_mask != two->green_mask ||
739
0
        one->blue_mask != two->blue_mask) {
740
0
        return false;
741
0
    }
742
0
743
0
    if (one->bits_per_rgb != two->bits_per_rgb) {
744
0
        return false;
745
0
    }
746
0
747
0
    return true;
748
0
}
749
750
already_AddRefed<GLContext>
751
GLContextProviderGLX::CreateWrappingExisting(void* aContext, void* aSurface)
752
0
{
753
0
    if (!sGLXLibrary.EnsureInitialized()) {
754
0
        return nullptr;
755
0
    }
756
0
757
0
    if (aContext && aSurface) {
758
0
        SurfaceCaps caps = SurfaceCaps::Any();
759
0
        RefPtr<GLContextGLX> glContext =
760
0
            new GLContextGLX(CreateContextFlags::NONE, caps,
761
0
                             false, // Offscreen
762
0
                             (Display*)DefaultXDisplay(), // Display
763
0
                             (GLXDrawable)aSurface, (GLXContext)aContext,
764
0
                             false, // aDeleteDrawable,
765
0
                             true,
766
0
                             (gfxXlibSurface*)nullptr);
767
0
768
0
        glContext->mOwnsContext = false;
769
0
        return glContext.forget();
770
0
    }
771
0
772
0
    return nullptr;
773
0
}
774
775
already_AddRefed<GLContext>
776
CreateForWidget(Display* aXDisplay, Window aXWindow,
777
                bool aWebRender,
778
                bool aForceAccelerated)
779
0
{
780
0
    if (!sGLXLibrary.EnsureInitialized()) {
781
0
        return nullptr;
782
0
    }
783
0
784
0
    // Currently, we take whatever Visual the window already has, and
785
0
    // try to create an fbconfig for that visual.  This isn't
786
0
    // necessarily what we want in the long run; an fbconfig may not
787
0
    // be available for the existing visual, or if it is, the GL
788
0
    // performance might be suboptimal.  But using the existing visual
789
0
    // is a relatively safe intermediate step.
790
0
791
0
    if (!aXDisplay) {
792
0
        NS_ERROR("X Display required for GLX Context provider");
793
0
        return nullptr;
794
0
    }
795
0
796
0
    int xscreen = DefaultScreen(aXDisplay);
797
0
798
0
    ScopedXFree<GLXFBConfig> cfgs;
799
0
    GLXFBConfig config;
800
0
    int visid;
801
0
    if (!GLContextGLX::FindFBConfigForWindow(aXDisplay, xscreen, aXWindow, &cfgs,
802
0
                                             &config, &visid, aWebRender))
803
0
    {
804
0
        return nullptr;
805
0
    }
806
0
807
0
    CreateContextFlags flags;
808
0
    if (aWebRender) {
809
0
        flags = CreateContextFlags::NONE; // WR needs GL3.2+
810
0
    } else {
811
0
        flags = CreateContextFlags::REQUIRE_COMPAT_PROFILE;
812
0
    }
813
0
    return GLContextGLX::CreateGLContext(flags, SurfaceCaps::Any(), false, aXDisplay,
814
0
                                         aXWindow, config, false, nullptr);
815
0
}
816
817
already_AddRefed<GLContext>
818
GLContextProviderGLX::CreateForCompositorWidget(CompositorWidget* aCompositorWidget, bool aForceAccelerated)
819
0
{
820
0
    GtkCompositorWidget* compWidget = aCompositorWidget->AsX11();
821
0
    MOZ_ASSERT(compWidget);
822
0
823
0
    return CreateForWidget(compWidget->XDisplay(),
824
0
                           compWidget->XWindow(),
825
0
                           compWidget->GetCompositorOptions().UseWebRender(),
826
0
                           aForceAccelerated);
827
0
}
828
829
already_AddRefed<GLContext>
830
GLContextProviderGLX::CreateForWindow(nsIWidget* aWidget,
831
                                      bool aWebRender,
832
                                      bool aForceAccelerated)
833
0
{
834
0
    Display* display = (Display*)aWidget->GetNativeData(NS_NATIVE_COMPOSITOR_DISPLAY);
835
0
    Window window = GET_NATIVE_WINDOW(aWidget);
836
0
837
0
    return CreateForWidget(display,
838
0
                           window,
839
0
                           aWebRender,
840
0
                           aForceAccelerated);
841
0
}
842
843
static bool
844
ChooseConfig(GLXLibrary* glx, Display* display, int screen, const SurfaceCaps& minCaps,
845
             ScopedXFree<GLXFBConfig>* const out_scopedConfigArr,
846
             GLXFBConfig* const out_config, int* const out_visid)
847
0
{
848
0
    ScopedXFree<GLXFBConfig>& scopedConfigArr = *out_scopedConfigArr;
849
0
850
0
    if (minCaps.antialias)
851
0
        return false;
852
0
853
0
    int attribs[] = {
854
0
        LOCAL_GLX_DRAWABLE_TYPE, LOCAL_GLX_PIXMAP_BIT,
855
0
        LOCAL_GLX_X_RENDERABLE, True,
856
0
        LOCAL_GLX_RED_SIZE, 8,
857
0
        LOCAL_GLX_GREEN_SIZE, 8,
858
0
        LOCAL_GLX_BLUE_SIZE, 8,
859
0
        LOCAL_GLX_ALPHA_SIZE, minCaps.alpha ? 8 : 0,
860
0
        LOCAL_GLX_DEPTH_SIZE, minCaps.depth ? 16 : 0,
861
0
        LOCAL_GLX_STENCIL_SIZE, minCaps.stencil ? 8 : 0,
862
0
        0
863
0
    };
864
0
865
0
    int numConfigs = 0;
866
0
    scopedConfigArr = glx->fChooseFBConfig(display, screen, attribs, &numConfigs);
867
0
    if (!scopedConfigArr || !numConfigs)
868
0
        return false;
869
0
870
0
    // Issues with glxChooseFBConfig selection and sorting:
871
0
    // * ALPHA_SIZE is sorted as 'largest total RGBA bits first'. If we don't request
872
0
    //   alpha bits, we'll probably get RGBA anyways, since 32 is more than 24.
873
0
    // * DEPTH_SIZE is sorted largest first, including for `0` inputs.
874
0
    // * STENCIL_SIZE is smallest first, but it might return `8` even though we ask for
875
0
    //   `0`.
876
0
877
0
    // For now, we don't care about these. We *will* care when we do XPixmap sharing.
878
0
879
0
    for (int i = 0; i < numConfigs; ++i) {
880
0
        GLXFBConfig curConfig = scopedConfigArr[i];
881
0
882
0
        int visid;
883
0
        if (glx->fGetFBConfigAttrib(display, curConfig, LOCAL_GLX_VISUAL_ID, &visid)
884
0
            != Success)
885
0
        {
886
0
            continue;
887
0
        }
888
0
889
0
        if (!visid)
890
0
            continue;
891
0
892
0
        *out_config = curConfig;
893
0
        *out_visid = visid;
894
0
        return true;
895
0
    }
896
0
897
0
    return false;
898
0
}
899
900
bool
901
GLContextGLX::FindVisual(Display* display, int screen, bool useWebRender,
902
                         bool useAlpha, int* const out_visualId)
903
0
{
904
0
    if (!sGLXLibrary.EnsureInitialized()) {
905
0
        return false;
906
0
    }
907
0
908
0
    XVisualInfo visualTemplate;
909
0
    visualTemplate.screen = screen;
910
0
911
0
    // Get all visuals of screen
912
0
913
0
    int visualsLen = 0;
914
0
    XVisualInfo* xVisuals = XGetVisualInfo(display, VisualScreenMask, &visualTemplate, &visualsLen);
915
0
    if (!xVisuals) {
916
0
        return false;
917
0
    }
918
0
    const Range<XVisualInfo> visualInfos(xVisuals, visualsLen);
919
0
    auto cleanupVisuals = MakeScopeExit([&] {
920
0
        XFree(xVisuals);
921
0
    });
922
0
923
0
    // Get default visual info
924
0
925
0
    Visual* defaultVisual = DefaultVisual(display, screen);
926
0
    const auto defaultVisualInfo = [&]() -> const XVisualInfo* {
927
0
        for (const auto& cur : visualInfos) {
928
0
            if (cur.visual == defaultVisual) {
929
0
                return &cur;
930
0
            }
931
0
        }
932
0
        return nullptr;
933
0
    }();
934
0
    if (!defaultVisualInfo) {
935
0
        MOZ_ASSERT(false);
936
0
        return false;
937
0
    }
938
0
939
0
    const int bpp = useAlpha ? 32 : 24;
940
0
    const int alphaSize = useAlpha ? 8 : 0;
941
0
    const int depthSize = useWebRender ? 24 : 0;
942
0
943
0
    for (auto& cur : visualInfos) {
944
0
945
0
        const auto fnConfigMatches = [&](const int pname, const int expected) {
946
0
            int actual;
947
0
            if (sGLXLibrary.fGetConfig(display, &cur, pname, &actual)) {
948
0
                return false;
949
0
            }
950
0
            return actual == expected;
951
0
        };
952
0
953
0
        // Check if visual is compatible.
954
0
        if (cur.depth != bpp ||
955
0
            cur.c_class != defaultVisualInfo->c_class) {
956
0
            continue;
957
0
        }
958
0
959
0
        // Check if visual is compatible to GL requests.
960
0
        if (fnConfigMatches(LOCAL_GLX_USE_GL, 1) &&
961
0
            fnConfigMatches(LOCAL_GLX_DOUBLEBUFFER, 1) &&
962
0
            fnConfigMatches(LOCAL_GLX_RED_SIZE, 8) &&
963
0
            fnConfigMatches(LOCAL_GLX_GREEN_SIZE, 8) &&
964
0
            fnConfigMatches(LOCAL_GLX_BLUE_SIZE, 8) &&
965
0
            fnConfigMatches(LOCAL_GLX_ALPHA_SIZE, alphaSize) &&
966
0
            fnConfigMatches(LOCAL_GLX_DEPTH_SIZE, depthSize))
967
0
        {
968
0
            *out_visualId = cur.visualid;
969
0
            return true;
970
0
        }
971
0
    }
972
0
973
0
    return false;
974
0
}
975
976
bool
977
GLContextGLX::FindFBConfigForWindow(Display* display, int screen, Window window,
978
                                    ScopedXFree<GLXFBConfig>* const out_scopedConfigArr,
979
                                    GLXFBConfig* const out_config, int* const out_visid,
980
                                    bool aWebRender)
981
0
{
982
0
    // XXX the visual ID is almost certainly the LOCAL_GLX_FBCONFIG_ID, so
983
0
    // we could probably do this first and replace the glXGetFBConfigs
984
0
    // with glXChooseConfigs.  Docs are sparklingly clear as always.
985
0
    XWindowAttributes windowAttrs;
986
0
    if (!XGetWindowAttributes(display, window, &windowAttrs)) {
987
0
        NS_WARNING("[GLX] XGetWindowAttributes() failed");
988
0
        return false;
989
0
    }
990
0
991
0
    ScopedXFree<GLXFBConfig>& cfgs = *out_scopedConfigArr;
992
0
    int numConfigs;
993
0
    const int webrenderAttribs[] = {
994
0
        LOCAL_GLX_ALPHA_SIZE, windowAttrs.depth == 32 ? 8 : 0,
995
0
        LOCAL_GLX_DEPTH_SIZE, 24,
996
0
        LOCAL_GLX_DOUBLEBUFFER, True,
997
0
        0
998
0
    };
999
0
1000
0
    if (aWebRender) {
1001
0
      cfgs = sGLXLibrary.fChooseFBConfig(display,
1002
0
                                         screen,
1003
0
                                         webrenderAttribs,
1004
0
                                         &numConfigs);
1005
0
    } else {
1006
0
      cfgs = sGLXLibrary.fGetFBConfigs(display,
1007
0
                                       screen,
1008
0
                                       &numConfigs);
1009
0
    }
1010
0
1011
0
    if (!cfgs) {
1012
0
        NS_WARNING("[GLX] glXGetFBConfigs() failed");
1013
0
        return false;
1014
0
    }
1015
0
    NS_ASSERTION(numConfigs > 0, "No FBConfigs found!");
1016
0
1017
0
    const VisualID windowVisualID = XVisualIDFromVisual(windowAttrs.visual);
1018
#ifdef DEBUG
1019
    printf("[GLX] window %lx has VisualID 0x%lx\n", window, windowVisualID);
1020
#endif
1021
1022
0
    for (int i = 0; i < numConfigs; i++) {
1023
0
        int visid = X11None;
1024
0
        sGLXLibrary.fGetFBConfigAttrib(display, cfgs[i], LOCAL_GLX_VISUAL_ID, &visid);
1025
0
        if (visid) {
1026
0
            // WebRender compatible GLX visual is configured
1027
0
            // at nsWindow::Create() by GLContextGLX::FindVisual(),
1028
0
            // just reuse it here.
1029
0
            if (windowVisualID == static_cast<VisualID>(visid)) {
1030
0
                *out_config = cfgs[i];
1031
0
                *out_visid = visid;
1032
0
                return true;
1033
0
            }
1034
0
        }
1035
0
    }
1036
0
1037
0
    // We don't have a frame buffer visual which matches the GLX visual
1038
0
    // from GLContextGLX::FindVisual(). Let's try to find a near one and hope
1039
0
    // we're not on NVIDIA (Bug 1478454) as it causes X11 BadMatch error there.
1040
0
    for (int i = 0; i < numConfigs; i++) {
1041
0
        int visid = X11None;
1042
0
        sGLXLibrary.fGetFBConfigAttrib(display, cfgs[i], LOCAL_GLX_VISUAL_ID, &visid);
1043
0
        if (visid) {
1044
0
            int depth;
1045
0
            Visual* visual;
1046
0
            FindVisualAndDepth(display, visid, &visual, &depth);
1047
0
            if (depth == windowAttrs.depth &&
1048
0
                AreCompatibleVisuals(windowAttrs.visual, visual)) {
1049
0
                *out_config = cfgs[i];
1050
0
                *out_visid = visid;
1051
0
                return true;
1052
0
            }
1053
0
        }
1054
0
    }
1055
0
1056
0
1057
0
    NS_WARNING("[GLX] Couldn't find a FBConfig matching window visual");
1058
0
    return false;
1059
0
}
1060
1061
static already_AddRefed<GLContextGLX>
1062
CreateOffscreenPixmapContext(CreateContextFlags flags, const IntSize& size,
1063
                             const SurfaceCaps& minCaps, nsACString* const out_failureId)
1064
0
{
1065
0
    GLXLibrary* glx = &sGLXLibrary;
1066
0
    if (!glx->EnsureInitialized())
1067
0
        return nullptr;
1068
0
1069
0
    Display* display = DefaultXDisplay();
1070
0
    int screen = DefaultScreen(display);
1071
0
1072
0
    ScopedXFree<GLXFBConfig> scopedConfigArr;
1073
0
    GLXFBConfig config;
1074
0
    int visid;
1075
0
    if (!ChooseConfig(glx, display, screen, minCaps, &scopedConfigArr, &config, &visid)) {
1076
0
        NS_WARNING("Failed to find a compatible config.");
1077
0
        return nullptr;
1078
0
    }
1079
0
1080
0
    Visual* visual;
1081
0
    int depth;
1082
0
    FindVisualAndDepth(display, visid, &visual, &depth);
1083
0
1084
0
    OffMainThreadScopedXErrorHandler xErrorHandler;
1085
0
    bool error = false;
1086
0
1087
0
    gfx::IntSize dummySize(16, 16);
1088
0
    RefPtr<gfxXlibSurface> surface = gfxXlibSurface::Create(DefaultScreenOfDisplay(display),
1089
0
                                                            visual,
1090
0
                                                            dummySize);
1091
0
    if (surface->CairoStatus() != 0) {
1092
0
        mozilla::Unused << xErrorHandler.SyncAndGetError(display);
1093
0
        return nullptr;
1094
0
    }
1095
0
1096
0
    // Handle slightly different signature between glXCreatePixmap and
1097
0
    // its pre-GLX-1.3 extension equivalent (though given the ABI, we
1098
0
    // might not need to).
1099
0
    const auto drawable = surface->XDrawable();
1100
0
    const auto pixmap = glx->fCreatePixmap(display, config, drawable, nullptr);
1101
0
    if (pixmap == 0) {
1102
0
        error = true;
1103
0
    }
1104
0
1105
0
    bool serverError = xErrorHandler.SyncAndGetError(display);
1106
0
    if (error || serverError)
1107
0
        return nullptr;
1108
0
1109
0
    return GLContextGLX::CreateGLContext(flags, minCaps, true, display, pixmap, config,
1110
0
                                         true, surface);
1111
0
}
1112
1113
/*static*/ already_AddRefed<GLContext>
1114
GLContextProviderGLX::CreateHeadless(CreateContextFlags flags,
1115
                                     nsACString* const out_failureId)
1116
0
{
1117
0
    IntSize dummySize = IntSize(16, 16);
1118
0
    SurfaceCaps dummyCaps = SurfaceCaps::Any();
1119
0
    return CreateOffscreenPixmapContext(flags, dummySize, dummyCaps, out_failureId);
1120
0
}
1121
1122
/*static*/ already_AddRefed<GLContext>
1123
GLContextProviderGLX::CreateOffscreen(const IntSize& size,
1124
                                      const SurfaceCaps& minCaps,
1125
                                      CreateContextFlags flags,
1126
                                      nsACString* const out_failureId)
1127
0
{
1128
0
    SurfaceCaps minBackbufferCaps = minCaps;
1129
0
    if (minCaps.antialias) {
1130
0
        minBackbufferCaps.antialias = false;
1131
0
        minBackbufferCaps.depth = false;
1132
0
        minBackbufferCaps.stencil = false;
1133
0
    }
1134
0
1135
0
    RefPtr<GLContext> gl;
1136
0
    gl = CreateOffscreenPixmapContext(flags, size, minBackbufferCaps, out_failureId);
1137
0
    if (!gl)
1138
0
        return nullptr;
1139
0
1140
0
    if (!gl->InitOffscreen(size, minCaps)) {
1141
0
        *out_failureId = NS_LITERAL_CSTRING("FEATURE_FAILURE_GLX_INIT");
1142
0
        return nullptr;
1143
0
    }
1144
0
1145
0
    return gl.forget();
1146
0
}
1147
1148
/*static*/ GLContext*
1149
GLContextProviderGLX::GetGlobalContext()
1150
0
{
1151
0
    // Context sharing not supported.
1152
0
    return nullptr;
1153
0
}
1154
1155
/*static*/ void
1156
GLContextProviderGLX::Shutdown()
1157
0
{
1158
0
}
1159
1160
} /* namespace gl */
1161
} /* namespace mozilla */