Coverage Report

Created: 2018-09-25 14:53

/src/mozilla-central/gfx/thebes/gfxXlibSurface.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
#include "gfxXlibSurface.h"
7
8
#include "cairo.h"
9
#include "cairo-xlib.h"
10
#include "cairo-xlib-xrender.h"
11
#include <X11/Xlibint.h>  /* For XESetCloseDisplay */
12
#undef max // Xlibint.h defines this and it breaks std::max
13
#undef min // Xlibint.h defines this and it breaks std::min
14
#undef Data
15
16
#include "nsTArray.h"
17
#include "nsAlgorithm.h"
18
#include "mozilla/gfx/2D.h"
19
#include "mozilla/Preferences.h"
20
#include <algorithm>
21
#include "mozilla/CheckedInt.h"
22
23
using namespace mozilla;
24
using namespace mozilla::gfx;
25
26
gfxXlibSurface::gfxXlibSurface(Display *dpy, Drawable drawable, Visual *visual)
27
    : mPixmapTaken(false), mDisplay(dpy), mDrawable(drawable)
28
    , mGLXPixmap(X11None)
29
0
{
30
0
    const gfx::IntSize size = DoSizeQuery();
31
0
    cairo_surface_t *surf = cairo_xlib_surface_create(dpy, drawable, visual, size.width, size.height);
32
0
    Init(surf);
33
0
}
34
35
gfxXlibSurface::gfxXlibSurface(Display *dpy, Drawable drawable, Visual *visual, const gfx::IntSize& size)
36
    : mPixmapTaken(false), mDisplay(dpy), mDrawable(drawable)
37
    , mGLXPixmap(X11None)
38
0
{
39
0
    NS_ASSERTION(Factory::CheckSurfaceSize(size, XLIB_IMAGE_SIDE_SIZE_LIMIT),
40
0
                 "Bad size");
41
0
42
0
    cairo_surface_t *surf = cairo_xlib_surface_create(dpy, drawable, visual, size.width, size.height);
43
0
    Init(surf);
44
0
}
45
46
gfxXlibSurface::gfxXlibSurface(Screen *screen, Drawable drawable, XRenderPictFormat *format,
47
                               const gfx::IntSize& size)
48
    : mPixmapTaken(false)
49
    , mDisplay(DisplayOfScreen(screen))
50
    , mDrawable(drawable)
51
    , mGLXPixmap(X11None)
52
0
{
53
0
    NS_ASSERTION(Factory::CheckSurfaceSize(size, XLIB_IMAGE_SIDE_SIZE_LIMIT),
54
0
                 "Bad Size");
55
0
56
0
    cairo_surface_t *surf =
57
0
        cairo_xlib_surface_create_with_xrender_format(mDisplay, drawable,
58
0
                                                      screen, format,
59
0
                                                      size.width, size.height);
60
0
    Init(surf);
61
0
}
62
63
gfxXlibSurface::gfxXlibSurface(cairo_surface_t *csurf)
64
    : mPixmapTaken(false)
65
    , mGLXPixmap(X11None)
66
0
{
67
0
    MOZ_ASSERT(cairo_surface_status(csurf) == 0,
68
0
               "Not expecting an error surface");
69
0
70
0
    mDrawable = cairo_xlib_surface_get_drawable(csurf);
71
0
    mDisplay = cairo_xlib_surface_get_display(csurf);
72
0
73
0
    Init(csurf, true);
74
0
}
75
76
gfxXlibSurface::~gfxXlibSurface()
77
0
{
78
0
    // gfxASurface's destructor calls RecordMemoryFreed().
79
0
    if (mPixmapTaken) {
80
0
        if (mGLXPixmap) {
81
0
            gl::sGLXLibrary.DestroyPixmap(mDisplay, mGLXPixmap);
82
0
        }
83
0
        XFreePixmap (mDisplay, mDrawable);
84
0
    }
85
0
}
86
87
static Drawable
88
CreatePixmap(Screen *screen, const gfx::IntSize& size, unsigned int depth,
89
             Drawable relatedDrawable)
90
0
{
91
0
    if (!Factory::CheckSurfaceSize(size, XLIB_IMAGE_SIDE_SIZE_LIMIT))
92
0
        return X11None;
93
0
94
0
    if (relatedDrawable == X11None) {
95
0
        relatedDrawable = RootWindowOfScreen(screen);
96
0
    }
97
0
    Display *dpy = DisplayOfScreen(screen);
98
0
    // X gives us a fatal error if we try to create a pixmap of width
99
0
    // or height 0
100
0
    return XCreatePixmap(dpy, relatedDrawable,
101
0
                         std::max(1, size.width), std::max(1, size.height),
102
0
                         depth);
103
0
}
104
105
void
106
gfxXlibSurface::TakePixmap()
107
0
{
108
0
    NS_ASSERTION(!mPixmapTaken, "I already own the Pixmap!");
109
0
    mPixmapTaken = true;
110
0
111
0
    // The bit depth returned from Cairo is technically int, but this is
112
0
    // the last place we'd be worried about that scenario.
113
0
    unsigned int bitDepth = cairo_xlib_surface_get_depth(CairoSurface());
114
0
    MOZ_ASSERT((bitDepth % 8) == 0, "Memory used not recorded correctly");    
115
0
116
0
    // Divide by 8 because surface_get_depth gives us the number of *bits* per
117
0
    // pixel.
118
0
    gfx::IntSize size = GetSize();
119
0
    CheckedInt32 totalBytes = CheckedInt32(size.width) * CheckedInt32(size.height) * (bitDepth/8);
120
0
121
0
    // Don't do anything in the "else" case.  We could add INT32_MAX, but that
122
0
    // would overflow the memory used counter.  It would also mean we tried for
123
0
    // a 2G image.  For now, we'll just assert,
124
0
    MOZ_ASSERT(totalBytes.isValid(),"Did not expect to exceed 2Gb image");
125
0
    if (totalBytes.isValid()) {
126
0
        RecordMemoryUsed(totalBytes.value());
127
0
    }
128
0
}
129
130
Drawable
131
0
gfxXlibSurface::ReleasePixmap() {
132
0
    NS_ASSERTION(mPixmapTaken, "I don't own the Pixmap!");
133
0
    mPixmapTaken = false;
134
0
    RecordMemoryFreed();
135
0
    return mDrawable;
136
0
}
137
138
static cairo_user_data_key_t gDestroyPixmapKey;
139
140
struct DestroyPixmapClosure {
141
0
    DestroyPixmapClosure(Drawable d, Screen *s) : mPixmap(d), mScreen(s) {}
142
    Drawable mPixmap;
143
    Screen *mScreen;
144
};
145
146
static void
147
DestroyPixmap(void *data)
148
0
{
149
0
    DestroyPixmapClosure *closure = static_cast<DestroyPixmapClosure*>(data);
150
0
    XFreePixmap(DisplayOfScreen(closure->mScreen), closure->mPixmap);
151
0
    delete closure;
152
0
}
153
154
/* static */
155
cairo_surface_t *
156
gfxXlibSurface::CreateCairoSurface(Screen *screen, Visual *visual,
157
                                   const gfx::IntSize& size, Drawable relatedDrawable)
158
0
{
159
0
    Drawable drawable =
160
0
        CreatePixmap(screen, size, DepthOfVisual(screen, visual),
161
0
                     relatedDrawable);
162
0
    if (!drawable)
163
0
        return nullptr;
164
0
165
0
    cairo_surface_t* surface =
166
0
        cairo_xlib_surface_create(DisplayOfScreen(screen), drawable, visual,
167
0
                                  size.width, size.height);
168
0
    if (cairo_surface_status(surface)) {
169
0
        cairo_surface_destroy(surface);
170
0
        XFreePixmap(DisplayOfScreen(screen), drawable);
171
0
        return nullptr;
172
0
    }
173
0
174
0
    DestroyPixmapClosure *closure = new DestroyPixmapClosure(drawable, screen);
175
0
    cairo_surface_set_user_data(surface, &gDestroyPixmapKey,
176
0
                                closure, DestroyPixmap);
177
0
    return surface;
178
0
}
179
180
/* static */
181
already_AddRefed<gfxXlibSurface>
182
gfxXlibSurface::Create(Screen *screen, Visual *visual,
183
                       const gfx::IntSize& size, Drawable relatedDrawable)
184
0
{
185
0
    Drawable drawable =
186
0
        CreatePixmap(screen, size, DepthOfVisual(screen, visual),
187
0
                     relatedDrawable);
188
0
    if (!drawable)
189
0
        return nullptr;
190
0
191
0
    RefPtr<gfxXlibSurface> result =
192
0
        new gfxXlibSurface(DisplayOfScreen(screen), drawable, visual, size);
193
0
    result->TakePixmap();
194
0
195
0
    if (result->CairoStatus() != 0)
196
0
        return nullptr;
197
0
198
0
    return result.forget();
199
0
}
200
201
/* static */
202
already_AddRefed<gfxXlibSurface>
203
gfxXlibSurface::Create(Screen *screen, XRenderPictFormat *format,
204
                       const gfx::IntSize& size, Drawable relatedDrawable)
205
0
{
206
0
    Drawable drawable =
207
0
        CreatePixmap(screen, size, format->depth, relatedDrawable);
208
0
    if (!drawable)
209
0
        return nullptr;
210
0
211
0
    RefPtr<gfxXlibSurface> result =
212
0
        new gfxXlibSurface(screen, drawable, format, size);
213
0
    result->TakePixmap();
214
0
215
0
    if (result->CairoStatus() != 0)
216
0
        return nullptr;
217
0
218
0
    return result.forget();
219
0
}
220
221
static bool GetForce24bppPref()
222
0
{
223
0
    return Preferences::GetBool("mozilla.widget.force-24bpp", false);
224
0
}
225
226
already_AddRefed<gfxASurface>
227
gfxXlibSurface::CreateSimilarSurface(gfxContentType aContent,
228
                                     const gfx::IntSize& aSize)
229
0
{
230
0
    if (!mSurface || !mSurfaceValid) {
231
0
      return nullptr;
232
0
    }
233
0
234
0
    if (aContent == gfxContentType::COLOR) {
235
0
        // cairo_surface_create_similar will use a matching visual if it can.
236
0
        // However, systems with 16-bit or indexed default visuals may benefit
237
0
        // from rendering with 24-bit formats.
238
0
        static bool force24bpp = GetForce24bppPref();
239
0
        if (force24bpp
240
0
            && cairo_xlib_surface_get_depth(CairoSurface()) != 24) {
241
0
            XRenderPictFormat* format =
242
0
                XRenderFindStandardFormat(mDisplay, PictStandardRGB24);
243
0
            if (format) {
244
0
                // Cairo only performs simple self-copies as desired if it
245
0
                // knows that this is a Pixmap surface.  It only knows that
246
0
                // surfaces are pixmap surfaces if it creates the Pixmap
247
0
                // itself, so we use cairo_surface_create_similar with a
248
0
                // temporary reference surface to indicate the format.
249
0
                Screen* screen = cairo_xlib_surface_get_screen(CairoSurface());
250
0
                RefPtr<gfxXlibSurface> depth24reference =
251
0
                    gfxXlibSurface::Create(screen, format,
252
0
                                           gfx::IntSize(1, 1), mDrawable);
253
0
                if (depth24reference)
254
0
                    return depth24reference->
255
0
                        gfxASurface::CreateSimilarSurface(aContent, aSize);
256
0
            }
257
0
        }
258
0
    }
259
0
260
0
    return gfxASurface::CreateSimilarSurface(aContent, aSize);
261
0
}
262
263
void
264
gfxXlibSurface::Finish()
265
0
{
266
0
    if (mPixmapTaken && mGLXPixmap) {
267
0
        gl::sGLXLibrary.DestroyPixmap(mDisplay, mGLXPixmap);
268
0
        mGLXPixmap = X11None;
269
0
    }
270
0
    gfxASurface::Finish();
271
0
}
272
273
const gfx::IntSize
274
gfxXlibSurface::GetSize() const
275
0
{
276
0
    if (!mSurfaceValid)
277
0
        return gfx::IntSize(0,0);
278
0
279
0
    return gfx::IntSize(cairo_xlib_surface_get_width(mSurface),
280
0
                      cairo_xlib_surface_get_height(mSurface));
281
0
}
282
283
const gfx::IntSize
284
gfxXlibSurface::DoSizeQuery()
285
0
{
286
0
    // figure out width/height/depth
287
0
    Window root_ignore;
288
0
    int x_ignore, y_ignore;
289
0
    unsigned int bwidth_ignore, width, height, depth;
290
0
291
0
    XGetGeometry(mDisplay,
292
0
                 mDrawable,
293
0
                 &root_ignore, &x_ignore, &y_ignore,
294
0
                 &width, &height,
295
0
                 &bwidth_ignore, &depth);
296
0
297
0
    return gfx::IntSize(width, height);
298
0
}
299
300
class DisplayTable {
301
public:
302
    static bool GetColormapAndVisual(Screen* screen,
303
                                       XRenderPictFormat* format,
304
                                       Visual* visual, Colormap* colormap,
305
                                       Visual** visualForColormap);
306
307
private:
308
    struct ColormapEntry {
309
        XRenderPictFormat* mFormat;
310
        // The Screen is needed here because colormaps (and their visuals) may
311
        // only be used on one Screen, but XRenderPictFormats are not unique
312
        // to any one Screen.
313
        Screen* mScreen;
314
        Visual* mVisual;
315
        Colormap mColormap;
316
    };
317
318
    class DisplayInfo {
319
    public:
320
0
        explicit DisplayInfo(Display* display) : mDisplay(display) { }
321
        Display* mDisplay;
322
        nsTArray<ColormapEntry> mColormapEntries;
323
    };
324
325
    // Comparator for finding the DisplayInfo
326
    class FindDisplay {
327
    public:
328
        bool Equals(const DisplayInfo& info, const Display *display) const
329
0
        {
330
0
            return info.mDisplay == display;
331
0
        }
332
    };
333
334
    static int DisplayClosing(Display *display, XExtCodes* codes);
335
336
    nsTArray<DisplayInfo> mDisplays;
337
    static DisplayTable* sDisplayTable;
338
};
339
340
DisplayTable* DisplayTable::sDisplayTable;
341
342
// Pixmaps don't have a particular associated visual but the pixel values are
343
// interpreted according to a visual/colormap pairs.
344
//
345
// cairo is designed for surfaces with either TrueColor visuals or the
346
// default visual (which may not be true color).  TrueColor visuals don't
347
// really need a colormap because the visual indicates the pixel format,
348
// and cairo uses the default visual with the default colormap, so cairo
349
// surfaces don't need an explicit colormap.
350
//
351
// However, some toolkits (e.g. GDK) need a colormap even with TrueColor
352
// visuals.  We can create a colormap for these visuals, but it will use about
353
// 20kB of memory in the server, so we use the default colormap when
354
// suitable and share colormaps between surfaces.  Another reason for
355
// minimizing colormap turnover is that the plugin process must leak resources
356
// for each new colormap id when using older GDK libraries (bug 569775).
357
//
358
// Only the format of the pixels is important for rendering to Pixmaps, so if
359
// the format of a visual matches that of the surface, then that visual can be
360
// used for rendering to the surface.  Multiple visuals can match the same
361
// format (but have different GLX properties), so the visual returned may
362
// differ from the visual passed in.  Colormaps are tied to a visual, so
363
// should only be used with their visual.
364
365
/* static */ bool
366
DisplayTable::GetColormapAndVisual(Screen* aScreen, XRenderPictFormat* aFormat,
367
                                   Visual* aVisual, Colormap* aColormap,
368
                                   Visual** aVisualForColormap)
369
370
0
{
371
0
    Display* display = DisplayOfScreen(aScreen);
372
0
373
0
    // Use the default colormap if the default visual matches.
374
0
    Visual *defaultVisual = DefaultVisualOfScreen(aScreen);
375
0
    if (aVisual == defaultVisual
376
0
        || (aFormat
377
0
            && aFormat == XRenderFindVisualFormat(display, defaultVisual)))
378
0
    {
379
0
        *aColormap = DefaultColormapOfScreen(aScreen);
380
0
        *aVisualForColormap = defaultVisual;
381
0
        return true;
382
0
    }
383
0
384
0
    // Only supporting TrueColor non-default visuals
385
0
    if (!aVisual || aVisual->c_class != TrueColor)
386
0
        return false;
387
0
388
0
    if (!sDisplayTable) {
389
0
        sDisplayTable = new DisplayTable();
390
0
    }
391
0
392
0
    nsTArray<DisplayInfo>* displays = &sDisplayTable->mDisplays;
393
0
    size_t d = displays->IndexOf(display, 0, FindDisplay());
394
0
395
0
    if (d == displays->NoIndex) {
396
0
        d = displays->Length();
397
0
        // Register for notification of display closing, when this info
398
0
        // becomes invalid.
399
0
        XExtCodes *codes = XAddExtension(display);
400
0
        if (!codes)
401
0
            return false;
402
0
403
0
        XESetCloseDisplay(display, codes->extension, DisplayClosing);
404
0
        // Add a new DisplayInfo.
405
0
        displays->AppendElement(display);
406
0
    }
407
0
408
0
    nsTArray<ColormapEntry>* entries =
409
0
        &displays->ElementAt(d).mColormapEntries;
410
0
411
0
    // Only a small number of formats are expected to be used, so just do a
412
0
    // simple linear search.
413
0
    for (uint32_t i = 0; i < entries->Length(); ++i) {
414
0
        const ColormapEntry& entry = entries->ElementAt(i);
415
0
        // Only the format and screen need to match.  (The visual may differ.)
416
0
        // If there is no format (e.g. no RENDER extension) then just compare
417
0
        // the visual.
418
0
        if ((aFormat && entry.mFormat == aFormat && entry.mScreen == aScreen)
419
0
            || aVisual == entry.mVisual) {
420
0
            *aColormap = entry.mColormap;
421
0
            *aVisualForColormap = entry.mVisual;
422
0
            return true;
423
0
        }
424
0
    }
425
0
426
0
    // No existing entry.  Create a colormap and add an entry.
427
0
    Colormap colormap = XCreateColormap(display, RootWindowOfScreen(aScreen),
428
0
                                        aVisual, AllocNone);
429
0
    ColormapEntry* newEntry = entries->AppendElement();
430
0
    newEntry->mFormat = aFormat;
431
0
    newEntry->mScreen = aScreen;
432
0
    newEntry->mVisual = aVisual;
433
0
    newEntry->mColormap = colormap;
434
0
435
0
    *aColormap = colormap;
436
0
    *aVisualForColormap = aVisual;
437
0
    return true;
438
0
}
439
440
/* static */ int
441
DisplayTable::DisplayClosing(Display *display, XExtCodes* codes)
442
0
{
443
0
    // No need to free the colormaps explicitly as they will be released when
444
0
    // the connection is closed.
445
0
    sDisplayTable->mDisplays.RemoveElement(display, FindDisplay());
446
0
    if (sDisplayTable->mDisplays.Length() == 0) {
447
0
        delete sDisplayTable;
448
0
        sDisplayTable = nullptr;
449
0
    }
450
0
    return 0;
451
0
}
452
453
/* static */
454
bool
455
gfxXlibSurface::GetColormapAndVisual(cairo_surface_t* aXlibSurface,
456
                                     Colormap* aColormap, Visual** aVisual)
457
0
{
458
0
    XRenderPictFormat* format =
459
0
        cairo_xlib_surface_get_xrender_format(aXlibSurface);
460
0
    Screen* screen = cairo_xlib_surface_get_screen(aXlibSurface);
461
0
    Visual* visual = cairo_xlib_surface_get_visual(aXlibSurface);
462
0
463
0
    return DisplayTable::GetColormapAndVisual(screen, format, visual,
464
0
                                              aColormap, aVisual);
465
0
}
466
467
bool
468
gfxXlibSurface::GetColormapAndVisual(Colormap* aColormap, Visual** aVisual)
469
0
{
470
0
    if (!mSurfaceValid)
471
0
        return false;
472
0
473
0
    return GetColormapAndVisual(CairoSurface(), aColormap, aVisual);
474
0
}
475
476
/* static */
477
int
478
gfxXlibSurface::DepthOfVisual(const Screen* screen, const Visual* visual)
479
0
{
480
0
    for (int d = 0; d < screen->ndepths; d++) {
481
0
        const Depth& d_info = screen->depths[d];
482
0
        if (visual >= &d_info.visuals[0]
483
0
            && visual < &d_info.visuals[d_info.nvisuals])
484
0
            return d_info.depth;
485
0
    }
486
0
487
0
    NS_ERROR("Visual not on Screen.");
488
0
    return 0;
489
0
}
490
    
491
/* static */
492
Visual*
493
gfxXlibSurface::FindVisual(Screen *screen, gfxImageFormat format)
494
0
{
495
0
    int depth;
496
0
    unsigned long red_mask, green_mask, blue_mask;
497
0
    switch (format) {
498
0
        case gfx::SurfaceFormat::A8R8G8B8_UINT32:
499
0
            depth = 32;
500
0
            red_mask = 0xff0000;
501
0
            green_mask = 0xff00;
502
0
            blue_mask = 0xff;
503
0
            break;
504
0
        case gfx::SurfaceFormat::X8R8G8B8_UINT32:
505
0
            depth = 24;
506
0
            red_mask = 0xff0000;
507
0
            green_mask = 0xff00;
508
0
            blue_mask = 0xff;
509
0
            break;
510
0
        case gfx::SurfaceFormat::R5G6B5_UINT16:
511
0
            depth = 16;
512
0
            red_mask = 0xf800;
513
0
            green_mask = 0x7e0;
514
0
            blue_mask = 0x1f;
515
0
            break;
516
0
        case gfx::SurfaceFormat::A8:
517
0
        default:
518
0
            return nullptr;
519
0
    }
520
0
521
0
    for (int d = 0; d < screen->ndepths; d++) {
522
0
        const Depth& d_info = screen->depths[d];
523
0
        if (d_info.depth != depth)
524
0
            continue;
525
0
526
0
        for (int v = 0; v < d_info.nvisuals; v++) {
527
0
            Visual* visual = &d_info.visuals[v];
528
0
529
0
            if (visual->c_class == TrueColor &&
530
0
                visual->red_mask == red_mask &&
531
0
                visual->green_mask == green_mask &&
532
0
                visual->blue_mask == blue_mask)
533
0
                return visual;
534
0
        }
535
0
    }
536
0
537
0
    return nullptr;
538
0
}
539
540
/* static */
541
XRenderPictFormat*
542
gfxXlibSurface::FindRenderFormat(Display *dpy, gfxImageFormat format)
543
0
{
544
0
    switch (format) {
545
0
        case gfx::SurfaceFormat::A8R8G8B8_UINT32:
546
0
            return XRenderFindStandardFormat (dpy, PictStandardARGB32);
547
0
        case gfx::SurfaceFormat::X8R8G8B8_UINT32:
548
0
            return XRenderFindStandardFormat (dpy, PictStandardRGB24);
549
0
        case gfx::SurfaceFormat::R5G6B5_UINT16: {
550
0
            // PictStandardRGB16_565 is not standard Xrender format
551
0
            // we should try to find related visual
552
0
            // and find xrender format by visual
553
0
            Visual *visual = FindVisual(DefaultScreenOfDisplay(dpy), format);
554
0
            if (!visual)
555
0
                return nullptr;
556
0
            return XRenderFindVisualFormat(dpy, visual);
557
0
        }
558
0
        case gfx::SurfaceFormat::A8:
559
0
            return XRenderFindStandardFormat (dpy, PictStandardA8);
560
0
        default:
561
0
            break;
562
0
    }
563
0
564
0
    return nullptr;
565
0
}
566
567
Screen*
568
gfxXlibSurface::XScreen()
569
0
{
570
0
    return cairo_xlib_surface_get_screen(CairoSurface());
571
0
}
572
573
XRenderPictFormat*
574
gfxXlibSurface::XRenderFormat()
575
0
{
576
0
    return cairo_xlib_surface_get_xrender_format(CairoSurface());
577
0
}
578
579
GLXPixmap
580
gfxXlibSurface::GetGLXPixmap()
581
0
{
582
0
    if (!mGLXPixmap) {
583
#ifdef DEBUG
584
        // cairo_surface_has_show_text_glyphs is used solely for the
585
        // side-effect of setting the error on surface if
586
        // cairo_surface_finish() has been called.
587
        cairo_surface_has_show_text_glyphs(CairoSurface());
588
        NS_ASSERTION(CairoStatus() != CAIRO_STATUS_SURFACE_FINISHED,
589
            "GetGLXPixmap called after surface finished");
590
#endif
591
        mGLXPixmap = gl::sGLXLibrary.CreatePixmap(this);
592
0
    }
593
0
    return mGLXPixmap;
594
0
}
595
596
void
597
gfxXlibSurface::BindGLXPixmap(GLXPixmap aPixmap)
598
0
{
599
0
    MOZ_ASSERT(!mGLXPixmap, "A GLXPixmap is already bound!");
600
0
    mGLXPixmap = aPixmap;
601
0
}
602