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