1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/gfx/thebes/gfxXlibSurface.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,619 @@ 1.4 +/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*- 1.5 + * This Source Code Form is subject to the terms of the Mozilla Public 1.6 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.7 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.8 + 1.9 +#include "gfxXlibSurface.h" 1.10 + 1.11 +#include "cairo.h" 1.12 +#include "cairo-xlib.h" 1.13 +#include "cairo-xlib-xrender.h" 1.14 +#include <X11/Xlibint.h> /* For XESetCloseDisplay */ 1.15 +#undef max // Xlibint.h defines this and it breaks std::max 1.16 +#undef min // Xlibint.h defines this and it breaks std::min 1.17 + 1.18 +#include "nsAutoPtr.h" 1.19 +#include "nsTArray.h" 1.20 +#include "nsAlgorithm.h" 1.21 +#include "mozilla/Preferences.h" 1.22 +#include <algorithm> 1.23 +#include "mozilla/CheckedInt.h" 1.24 + 1.25 +using namespace mozilla; 1.26 + 1.27 +// Although the dimension parameters in the xCreatePixmapReq wire protocol are 1.28 +// 16-bit unsigned integers, the server's CreatePixmap returns BadAlloc if 1.29 +// either dimension cannot be represented by a 16-bit *signed* integer. 1.30 +#define XLIB_IMAGE_SIDE_SIZE_LIMIT 0x7fff 1.31 + 1.32 +gfxXlibSurface::gfxXlibSurface(Display *dpy, Drawable drawable, Visual *visual) 1.33 + : mPixmapTaken(false), mDisplay(dpy), mDrawable(drawable) 1.34 +#if defined(GL_PROVIDER_GLX) 1.35 + , mGLXPixmap(None) 1.36 +#endif 1.37 +{ 1.38 + const gfxIntSize size = DoSizeQuery(); 1.39 + cairo_surface_t *surf = cairo_xlib_surface_create(dpy, drawable, visual, size.width, size.height); 1.40 + Init(surf); 1.41 +} 1.42 + 1.43 +gfxXlibSurface::gfxXlibSurface(Display *dpy, Drawable drawable, Visual *visual, const gfxIntSize& size) 1.44 + : mPixmapTaken(false), mDisplay(dpy), mDrawable(drawable) 1.45 +#if defined(GL_PROVIDER_GLX) 1.46 + , mGLXPixmap(None) 1.47 +#endif 1.48 +{ 1.49 + NS_ASSERTION(CheckSurfaceSize(size, XLIB_IMAGE_SIDE_SIZE_LIMIT), 1.50 + "Bad size"); 1.51 + 1.52 + cairo_surface_t *surf = cairo_xlib_surface_create(dpy, drawable, visual, size.width, size.height); 1.53 + Init(surf); 1.54 +} 1.55 + 1.56 +gfxXlibSurface::gfxXlibSurface(Screen *screen, Drawable drawable, XRenderPictFormat *format, 1.57 + const gfxIntSize& size) 1.58 + : mPixmapTaken(false), mDisplay(DisplayOfScreen(screen)), 1.59 + mDrawable(drawable) 1.60 +#if defined(GL_PROVIDER_GLX) 1.61 + , mGLXPixmap(None) 1.62 +#endif 1.63 +{ 1.64 + NS_ASSERTION(CheckSurfaceSize(size, XLIB_IMAGE_SIDE_SIZE_LIMIT), 1.65 + "Bad Size"); 1.66 + 1.67 + cairo_surface_t *surf = 1.68 + cairo_xlib_surface_create_with_xrender_format(mDisplay, drawable, 1.69 + screen, format, 1.70 + size.width, size.height); 1.71 + Init(surf); 1.72 +} 1.73 + 1.74 +gfxXlibSurface::gfxXlibSurface(cairo_surface_t *csurf) 1.75 + : mPixmapTaken(false) 1.76 +#if defined(GL_PROVIDER_GLX) 1.77 + , mGLXPixmap(None) 1.78 +#endif 1.79 +{ 1.80 + NS_PRECONDITION(cairo_surface_status(csurf) == 0, 1.81 + "Not expecting an error surface"); 1.82 + 1.83 + mDrawable = cairo_xlib_surface_get_drawable(csurf); 1.84 + mDisplay = cairo_xlib_surface_get_display(csurf); 1.85 + 1.86 + Init(csurf, true); 1.87 +} 1.88 + 1.89 +gfxXlibSurface::~gfxXlibSurface() 1.90 +{ 1.91 +#if defined(GL_PROVIDER_GLX) 1.92 + if (mGLXPixmap) { 1.93 + gl::sGLXLibrary.DestroyPixmap(mDisplay, mGLXPixmap); 1.94 + } 1.95 +#endif 1.96 + // gfxASurface's destructor calls RecordMemoryFreed(). 1.97 + if (mPixmapTaken) { 1.98 + XFreePixmap (mDisplay, mDrawable); 1.99 + } 1.100 +} 1.101 + 1.102 +static Drawable 1.103 +CreatePixmap(Screen *screen, const gfxIntSize& size, unsigned int depth, 1.104 + Drawable relatedDrawable) 1.105 +{ 1.106 + if (!gfxASurface::CheckSurfaceSize(size, XLIB_IMAGE_SIDE_SIZE_LIMIT)) 1.107 + return None; 1.108 + 1.109 + if (relatedDrawable == None) { 1.110 + relatedDrawable = RootWindowOfScreen(screen); 1.111 + } 1.112 + Display *dpy = DisplayOfScreen(screen); 1.113 + // X gives us a fatal error if we try to create a pixmap of width 1.114 + // or height 0 1.115 + return XCreatePixmap(dpy, relatedDrawable, 1.116 + std::max(1, size.width), std::max(1, size.height), 1.117 + depth); 1.118 +} 1.119 + 1.120 +void 1.121 +gfxXlibSurface::TakePixmap() 1.122 +{ 1.123 + NS_ASSERTION(!mPixmapTaken, "I already own the Pixmap!"); 1.124 + mPixmapTaken = true; 1.125 + 1.126 + // The bit depth returned from Cairo is technically int, but this is 1.127 + // the last place we'd be worried about that scenario. 1.128 + unsigned int bitDepth = cairo_xlib_surface_get_depth(CairoSurface()); 1.129 + MOZ_ASSERT((bitDepth % 8) == 0, "Memory used not recorded correctly"); 1.130 + 1.131 + // Divide by 8 because surface_get_depth gives us the number of *bits* per 1.132 + // pixel. 1.133 + gfxIntSize size = GetSize(); 1.134 + CheckedInt32 totalBytes = CheckedInt32(size.width) * CheckedInt32(size.height) * (bitDepth/8); 1.135 + 1.136 + // Don't do anything in the "else" case. We could add INT32_MAX, but that 1.137 + // would overflow the memory used counter. It would also mean we tried for 1.138 + // a 2G image. For now, we'll just assert, 1.139 + MOZ_ASSERT(totalBytes.isValid(),"Did not expect to exceed 2Gb image"); 1.140 + if (totalBytes.isValid()) { 1.141 + RecordMemoryUsed(totalBytes.value()); 1.142 + } 1.143 +} 1.144 + 1.145 +Drawable 1.146 +gfxXlibSurface::ReleasePixmap() { 1.147 + NS_ASSERTION(mPixmapTaken, "I don't own the Pixmap!"); 1.148 + mPixmapTaken = false; 1.149 + RecordMemoryFreed(); 1.150 + return mDrawable; 1.151 +} 1.152 + 1.153 +static cairo_user_data_key_t gDestroyPixmapKey; 1.154 + 1.155 +struct DestroyPixmapClosure { 1.156 + DestroyPixmapClosure(Drawable d, Screen *s) : mPixmap(d), mScreen(s) {} 1.157 + Drawable mPixmap; 1.158 + Screen *mScreen; 1.159 +}; 1.160 + 1.161 +static void 1.162 +DestroyPixmap(void *data) 1.163 +{ 1.164 + DestroyPixmapClosure *closure = static_cast<DestroyPixmapClosure*>(data); 1.165 + XFreePixmap(DisplayOfScreen(closure->mScreen), closure->mPixmap); 1.166 + delete closure; 1.167 +} 1.168 + 1.169 +/* static */ 1.170 +cairo_surface_t * 1.171 +gfxXlibSurface::CreateCairoSurface(Screen *screen, Visual *visual, 1.172 + const gfxIntSize& size, Drawable relatedDrawable) 1.173 +{ 1.174 + Drawable drawable = 1.175 + CreatePixmap(screen, size, DepthOfVisual(screen, visual), 1.176 + relatedDrawable); 1.177 + if (!drawable) 1.178 + return nullptr; 1.179 + 1.180 + cairo_surface_t* surface = 1.181 + cairo_xlib_surface_create(DisplayOfScreen(screen), drawable, visual, 1.182 + size.width, size.height); 1.183 + if (cairo_surface_status(surface)) { 1.184 + cairo_surface_destroy(surface); 1.185 + XFreePixmap(DisplayOfScreen(screen), drawable); 1.186 + return nullptr; 1.187 + } 1.188 + 1.189 + DestroyPixmapClosure *closure = new DestroyPixmapClosure(drawable, screen); 1.190 + cairo_surface_set_user_data(surface, &gDestroyPixmapKey, 1.191 + closure, DestroyPixmap); 1.192 + return surface; 1.193 +} 1.194 + 1.195 +/* static */ 1.196 +already_AddRefed<gfxXlibSurface> 1.197 +gfxXlibSurface::Create(Screen *screen, Visual *visual, 1.198 + const gfxIntSize& size, Drawable relatedDrawable) 1.199 +{ 1.200 + Drawable drawable = 1.201 + CreatePixmap(screen, size, DepthOfVisual(screen, visual), 1.202 + relatedDrawable); 1.203 + if (!drawable) 1.204 + return nullptr; 1.205 + 1.206 + nsRefPtr<gfxXlibSurface> result = 1.207 + new gfxXlibSurface(DisplayOfScreen(screen), drawable, visual, size); 1.208 + result->TakePixmap(); 1.209 + 1.210 + if (result->CairoStatus() != 0) 1.211 + return nullptr; 1.212 + 1.213 + return result.forget(); 1.214 +} 1.215 + 1.216 +/* static */ 1.217 +already_AddRefed<gfxXlibSurface> 1.218 +gfxXlibSurface::Create(Screen *screen, XRenderPictFormat *format, 1.219 + const gfxIntSize& size, Drawable relatedDrawable) 1.220 +{ 1.221 + Drawable drawable = 1.222 + CreatePixmap(screen, size, format->depth, relatedDrawable); 1.223 + if (!drawable) 1.224 + return nullptr; 1.225 + 1.226 + nsRefPtr<gfxXlibSurface> result = 1.227 + new gfxXlibSurface(screen, drawable, format, size); 1.228 + result->TakePixmap(); 1.229 + 1.230 + if (result->CairoStatus() != 0) 1.231 + return nullptr; 1.232 + 1.233 + return result.forget(); 1.234 +} 1.235 + 1.236 +static bool GetForce24bppPref() 1.237 +{ 1.238 + return Preferences::GetBool("mozilla.widget.force-24bpp", false); 1.239 +} 1.240 + 1.241 +already_AddRefed<gfxASurface> 1.242 +gfxXlibSurface::CreateSimilarSurface(gfxContentType aContent, 1.243 + const gfxIntSize& aSize) 1.244 +{ 1.245 + if (!mSurface || !mSurfaceValid) { 1.246 + return nullptr; 1.247 + } 1.248 + 1.249 + if (aContent == gfxContentType::COLOR) { 1.250 + // cairo_surface_create_similar will use a matching visual if it can. 1.251 + // However, systems with 16-bit or indexed default visuals may benefit 1.252 + // from rendering with 24-bit formats. 1.253 + static bool force24bpp = GetForce24bppPref(); 1.254 + if (force24bpp 1.255 + && cairo_xlib_surface_get_depth(CairoSurface()) != 24) { 1.256 + XRenderPictFormat* format = 1.257 + XRenderFindStandardFormat(mDisplay, PictStandardRGB24); 1.258 + if (format) { 1.259 + // Cairo only performs simple self-copies as desired if it 1.260 + // knows that this is a Pixmap surface. It only knows that 1.261 + // surfaces are pixmap surfaces if it creates the Pixmap 1.262 + // itself, so we use cairo_surface_create_similar with a 1.263 + // temporary reference surface to indicate the format. 1.264 + Screen* screen = cairo_xlib_surface_get_screen(CairoSurface()); 1.265 + nsRefPtr<gfxXlibSurface> depth24reference = 1.266 + gfxXlibSurface::Create(screen, format, 1.267 + gfxIntSize(1, 1), mDrawable); 1.268 + if (depth24reference) 1.269 + return depth24reference-> 1.270 + gfxASurface::CreateSimilarSurface(aContent, aSize); 1.271 + } 1.272 + } 1.273 + } 1.274 + 1.275 + return gfxASurface::CreateSimilarSurface(aContent, aSize); 1.276 +} 1.277 + 1.278 +void 1.279 +gfxXlibSurface::Finish() 1.280 +{ 1.281 +#if defined(GL_PROVIDER_GLX) 1.282 + if (mGLXPixmap) { 1.283 + gl::sGLXLibrary.DestroyPixmap(mDisplay, mGLXPixmap); 1.284 + mGLXPixmap = None; 1.285 + } 1.286 +#endif 1.287 + gfxASurface::Finish(); 1.288 +} 1.289 + 1.290 +const gfxIntSize 1.291 +gfxXlibSurface::GetSize() const 1.292 +{ 1.293 + if (!mSurfaceValid) 1.294 + return gfxIntSize(0,0); 1.295 + 1.296 + return gfxIntSize(cairo_xlib_surface_get_width(mSurface), 1.297 + cairo_xlib_surface_get_height(mSurface)); 1.298 +} 1.299 + 1.300 +const gfxIntSize 1.301 +gfxXlibSurface::DoSizeQuery() 1.302 +{ 1.303 + // figure out width/height/depth 1.304 + Window root_ignore; 1.305 + int x_ignore, y_ignore; 1.306 + unsigned int bwidth_ignore, width, height, depth; 1.307 + 1.308 + XGetGeometry(mDisplay, 1.309 + mDrawable, 1.310 + &root_ignore, &x_ignore, &y_ignore, 1.311 + &width, &height, 1.312 + &bwidth_ignore, &depth); 1.313 + 1.314 + return gfxIntSize(width, height); 1.315 +} 1.316 + 1.317 +class DisplayTable { 1.318 +public: 1.319 + static bool GetColormapAndVisual(Screen* screen, 1.320 + XRenderPictFormat* format, 1.321 + Visual* visual, Colormap* colormap, 1.322 + Visual** visualForColormap); 1.323 + 1.324 +private: 1.325 + struct ColormapEntry { 1.326 + XRenderPictFormat* mFormat; 1.327 + // The Screen is needed here because colormaps (and their visuals) may 1.328 + // only be used on one Screen, but XRenderPictFormats are not unique 1.329 + // to any one Screen. 1.330 + Screen* mScreen; 1.331 + Visual* mVisual; 1.332 + Colormap mColormap; 1.333 + }; 1.334 + 1.335 + class DisplayInfo { 1.336 + public: 1.337 + DisplayInfo(Display* display) : mDisplay(display) { } 1.338 + Display* mDisplay; 1.339 + nsTArray<ColormapEntry> mColormapEntries; 1.340 + }; 1.341 + 1.342 + // Comparator for finding the DisplayInfo 1.343 + class FindDisplay { 1.344 + public: 1.345 + bool Equals(const DisplayInfo& info, const Display *display) const 1.346 + { 1.347 + return info.mDisplay == display; 1.348 + } 1.349 + }; 1.350 + 1.351 + static int DisplayClosing(Display *display, XExtCodes* codes); 1.352 + 1.353 + nsTArray<DisplayInfo> mDisplays; 1.354 + static DisplayTable* sDisplayTable; 1.355 +}; 1.356 + 1.357 +DisplayTable* DisplayTable::sDisplayTable; 1.358 + 1.359 +// Pixmaps don't have a particular associated visual but the pixel values are 1.360 +// interpreted according to a visual/colormap pairs. 1.361 +// 1.362 +// cairo is designed for surfaces with either TrueColor visuals or the 1.363 +// default visual (which may not be true color). TrueColor visuals don't 1.364 +// really need a colormap because the visual indicates the pixel format, 1.365 +// and cairo uses the default visual with the default colormap, so cairo 1.366 +// surfaces don't need an explicit colormap. 1.367 +// 1.368 +// However, some toolkits (e.g. GDK) need a colormap even with TrueColor 1.369 +// visuals. We can create a colormap for these visuals, but it will use about 1.370 +// 20kB of memory in the server, so we use the default colormap when 1.371 +// suitable and share colormaps between surfaces. Another reason for 1.372 +// minimizing colormap turnover is that the plugin process must leak resources 1.373 +// for each new colormap id when using older GDK libraries (bug 569775). 1.374 +// 1.375 +// Only the format of the pixels is important for rendering to Pixmaps, so if 1.376 +// the format of a visual matches that of the surface, then that visual can be 1.377 +// used for rendering to the surface. Multiple visuals can match the same 1.378 +// format (but have different GLX properties), so the visual returned may 1.379 +// differ from the visual passed in. Colormaps are tied to a visual, so 1.380 +// should only be used with their visual. 1.381 + 1.382 +/* static */ bool 1.383 +DisplayTable::GetColormapAndVisual(Screen* aScreen, XRenderPictFormat* aFormat, 1.384 + Visual* aVisual, Colormap* aColormap, 1.385 + Visual** aVisualForColormap) 1.386 + 1.387 +{ 1.388 + Display* display = DisplayOfScreen(aScreen); 1.389 + 1.390 + // Use the default colormap if the default visual matches. 1.391 + Visual *defaultVisual = DefaultVisualOfScreen(aScreen); 1.392 + if (aVisual == defaultVisual 1.393 + || (aFormat 1.394 + && aFormat == XRenderFindVisualFormat(display, defaultVisual))) 1.395 + { 1.396 + *aColormap = DefaultColormapOfScreen(aScreen); 1.397 + *aVisualForColormap = defaultVisual; 1.398 + return true; 1.399 + } 1.400 + 1.401 + // Only supporting TrueColor non-default visuals 1.402 + if (!aVisual || aVisual->c_class != TrueColor) 1.403 + return false; 1.404 + 1.405 + if (!sDisplayTable) { 1.406 + sDisplayTable = new DisplayTable(); 1.407 + } 1.408 + 1.409 + nsTArray<DisplayInfo>* displays = &sDisplayTable->mDisplays; 1.410 + uint32_t d = displays->IndexOf(display, 0, FindDisplay()); 1.411 + 1.412 + if (d == displays->NoIndex) { 1.413 + d = displays->Length(); 1.414 + // Register for notification of display closing, when this info 1.415 + // becomes invalid. 1.416 + XExtCodes *codes = XAddExtension(display); 1.417 + if (!codes) 1.418 + return false; 1.419 + 1.420 + XESetCloseDisplay(display, codes->extension, DisplayClosing); 1.421 + // Add a new DisplayInfo. 1.422 + displays->AppendElement(display); 1.423 + } 1.424 + 1.425 + nsTArray<ColormapEntry>* entries = 1.426 + &displays->ElementAt(d).mColormapEntries; 1.427 + 1.428 + // Only a small number of formats are expected to be used, so just do a 1.429 + // simple linear search. 1.430 + for (uint32_t i = 0; i < entries->Length(); ++i) { 1.431 + const ColormapEntry& entry = entries->ElementAt(i); 1.432 + // Only the format and screen need to match. (The visual may differ.) 1.433 + // If there is no format (e.g. no RENDER extension) then just compare 1.434 + // the visual. 1.435 + if ((aFormat && entry.mFormat == aFormat && entry.mScreen == aScreen) 1.436 + || aVisual == entry.mVisual) { 1.437 + *aColormap = entry.mColormap; 1.438 + *aVisualForColormap = entry.mVisual; 1.439 + return true; 1.440 + } 1.441 + } 1.442 + 1.443 + // No existing entry. Create a colormap and add an entry. 1.444 + Colormap colormap = XCreateColormap(display, RootWindowOfScreen(aScreen), 1.445 + aVisual, AllocNone); 1.446 + ColormapEntry* newEntry = entries->AppendElement(); 1.447 + newEntry->mFormat = aFormat; 1.448 + newEntry->mScreen = aScreen; 1.449 + newEntry->mVisual = aVisual; 1.450 + newEntry->mColormap = colormap; 1.451 + 1.452 + *aColormap = colormap; 1.453 + *aVisualForColormap = aVisual; 1.454 + return true; 1.455 +} 1.456 + 1.457 +/* static */ int 1.458 +DisplayTable::DisplayClosing(Display *display, XExtCodes* codes) 1.459 +{ 1.460 + // No need to free the colormaps explicitly as they will be released when 1.461 + // the connection is closed. 1.462 + sDisplayTable->mDisplays.RemoveElement(display, FindDisplay()); 1.463 + if (sDisplayTable->mDisplays.Length() == 0) { 1.464 + delete sDisplayTable; 1.465 + sDisplayTable = nullptr; 1.466 + } 1.467 + return 0; 1.468 +} 1.469 + 1.470 +/* static */ 1.471 +bool 1.472 +gfxXlibSurface::GetColormapAndVisual(cairo_surface_t* aXlibSurface, 1.473 + Colormap* aColormap, Visual** aVisual) 1.474 +{ 1.475 + XRenderPictFormat* format = 1.476 + cairo_xlib_surface_get_xrender_format(aXlibSurface); 1.477 + Screen* screen = cairo_xlib_surface_get_screen(aXlibSurface); 1.478 + Visual* visual = cairo_xlib_surface_get_visual(aXlibSurface); 1.479 + 1.480 + return DisplayTable::GetColormapAndVisual(screen, format, visual, 1.481 + aColormap, aVisual); 1.482 +} 1.483 + 1.484 +bool 1.485 +gfxXlibSurface::GetColormapAndVisual(Colormap* aColormap, Visual** aVisual) 1.486 +{ 1.487 + if (!mSurfaceValid) 1.488 + return false; 1.489 + 1.490 + return GetColormapAndVisual(CairoSurface(), aColormap, aVisual); 1.491 +} 1.492 + 1.493 +/* static */ 1.494 +int 1.495 +gfxXlibSurface::DepthOfVisual(const Screen* screen, const Visual* visual) 1.496 +{ 1.497 + for (int d = 0; d < screen->ndepths; d++) { 1.498 + const Depth& d_info = screen->depths[d]; 1.499 + if (visual >= &d_info.visuals[0] 1.500 + && visual < &d_info.visuals[d_info.nvisuals]) 1.501 + return d_info.depth; 1.502 + } 1.503 + 1.504 + NS_ERROR("Visual not on Screen."); 1.505 + return 0; 1.506 +} 1.507 + 1.508 +/* static */ 1.509 +Visual* 1.510 +gfxXlibSurface::FindVisual(Screen *screen, gfxImageFormat format) 1.511 +{ 1.512 + int depth; 1.513 + unsigned long red_mask, green_mask, blue_mask; 1.514 + switch (format) { 1.515 + case gfxImageFormat::ARGB32: 1.516 + depth = 32; 1.517 + red_mask = 0xff0000; 1.518 + green_mask = 0xff00; 1.519 + blue_mask = 0xff; 1.520 + break; 1.521 + case gfxImageFormat::RGB24: 1.522 + depth = 24; 1.523 + red_mask = 0xff0000; 1.524 + green_mask = 0xff00; 1.525 + blue_mask = 0xff; 1.526 + break; 1.527 + case gfxImageFormat::RGB16_565: 1.528 + depth = 16; 1.529 + red_mask = 0xf800; 1.530 + green_mask = 0x7e0; 1.531 + blue_mask = 0x1f; 1.532 + break; 1.533 + case gfxImageFormat::A8: 1.534 + case gfxImageFormat::A1: 1.535 + default: 1.536 + return nullptr; 1.537 + } 1.538 + 1.539 + for (int d = 0; d < screen->ndepths; d++) { 1.540 + const Depth& d_info = screen->depths[d]; 1.541 + if (d_info.depth != depth) 1.542 + continue; 1.543 + 1.544 + for (int v = 0; v < d_info.nvisuals; v++) { 1.545 + Visual* visual = &d_info.visuals[v]; 1.546 + 1.547 + if (visual->c_class == TrueColor && 1.548 + visual->red_mask == red_mask && 1.549 + visual->green_mask == green_mask && 1.550 + visual->blue_mask == blue_mask) 1.551 + return visual; 1.552 + } 1.553 + } 1.554 + 1.555 + return nullptr; 1.556 +} 1.557 + 1.558 +/* static */ 1.559 +XRenderPictFormat* 1.560 +gfxXlibSurface::FindRenderFormat(Display *dpy, gfxImageFormat format) 1.561 +{ 1.562 + switch (format) { 1.563 + case gfxImageFormat::ARGB32: 1.564 + return XRenderFindStandardFormat (dpy, PictStandardARGB32); 1.565 + case gfxImageFormat::RGB24: 1.566 + return XRenderFindStandardFormat (dpy, PictStandardRGB24); 1.567 + case gfxImageFormat::RGB16_565: { 1.568 + // PictStandardRGB16_565 is not standard Xrender format 1.569 + // we should try to find related visual 1.570 + // and find xrender format by visual 1.571 + Visual *visual = FindVisual(DefaultScreenOfDisplay(dpy), format); 1.572 + if (!visual) 1.573 + return nullptr; 1.574 + return XRenderFindVisualFormat(dpy, visual); 1.575 + } 1.576 + case gfxImageFormat::A8: 1.577 + return XRenderFindStandardFormat (dpy, PictStandardA8); 1.578 + case gfxImageFormat::A1: 1.579 + return XRenderFindStandardFormat (dpy, PictStandardA1); 1.580 + default: 1.581 + break; 1.582 + } 1.583 + 1.584 + return nullptr; 1.585 +} 1.586 + 1.587 +Screen* 1.588 +gfxXlibSurface::XScreen() 1.589 +{ 1.590 + return cairo_xlib_surface_get_screen(CairoSurface()); 1.591 +} 1.592 + 1.593 +XRenderPictFormat* 1.594 +gfxXlibSurface::XRenderFormat() 1.595 +{ 1.596 + return cairo_xlib_surface_get_xrender_format(CairoSurface()); 1.597 +} 1.598 + 1.599 +#if defined(GL_PROVIDER_GLX) 1.600 +GLXPixmap 1.601 +gfxXlibSurface::GetGLXPixmap() 1.602 +{ 1.603 + if (!mGLXPixmap) { 1.604 +#ifdef DEBUG 1.605 + // cairo_surface_has_show_text_glyphs is used solely for the 1.606 + // side-effect of setting the error on surface if 1.607 + // cairo_surface_finish() has been called. 1.608 + cairo_surface_has_show_text_glyphs(CairoSurface()); 1.609 + NS_ASSERTION(CairoStatus() != CAIRO_STATUS_SURFACE_FINISHED, 1.610 + "GetGLXPixmap called after surface finished"); 1.611 +#endif 1.612 + mGLXPixmap = gl::sGLXLibrary.CreatePixmap(this); 1.613 + } 1.614 + return mGLXPixmap; 1.615 +} 1.616 +#endif 1.617 + 1.618 +gfxMemoryLocation 1.619 +gfxXlibSurface::GetMemoryLocation() const 1.620 +{ 1.621 + return gfxMemoryLocation::OUT_OF_PROCESS; 1.622 +}