diff --git a/content/browser/compositor/software_output_device_x11.cc b/content/browser/compositor/software_output_device_x11.cc index 016b4915f834f8..44267d4d31ff98 100644 --- a/content/browser/compositor/software_output_device_x11.cc +++ b/content/browser/compositor/software_output_device_x11.cc @@ -10,6 +10,8 @@ #include "content/public/browser/browser_thread.h" #include "third_party/skia/include/core/SkBitmap.h" #include "third_party/skia/include/core/SkDevice.h" +#include "ui/base/x/x11_util.h" +#include "ui/base/x/x11_util_internal.h" #include "ui/compositor/compositor.h" #include "ui/gfx/x/x11_types.h" @@ -49,6 +51,70 @@ void SoftwareOutputDeviceX11::EndPaint(cc::SoftwareFrameData* frame_data) { if (rect.IsEmpty()) return; + int bpp = gfx::BitsPerPixelForPixmapDepth(display_, attributes_.depth); + + if (bpp != 32 && bpp != 16 && ui::QueryRenderSupport(display_)) { + // gfx::PutARGBImage only supports 16 and 32 bpp, but Xrender can do other + // conversions. + Pixmap pixmap = XCreatePixmap( + display_, compositor_->widget(), rect.width(), rect.height(), 32); + GC gc = XCreateGC(display_, pixmap, 0, NULL); + XImage image; + memset(&image, 0, sizeof(image)); + + SkImageInfo info; + size_t rowBytes; + const void* addr = canvas_->peekPixels(&info, &rowBytes); + image.width = viewport_size_.width(); + image.height = viewport_size_.height(); + image.depth = 32; + image.bits_per_pixel = 32; + image.format = ZPixmap; + image.byte_order = LSBFirst; + image.bitmap_unit = 8; + image.bitmap_bit_order = LSBFirst; + image.bytes_per_line = rowBytes; + image.red_mask = 0xff; + image.green_mask = 0xff00; + image.blue_mask = 0xff0000; + image.data = const_cast(static_cast(addr)); + + XPutImage(display_, + pixmap, + gc, + &image, + rect.x(), + rect.y() /* source x, y */, + 0, + 0 /* dest x, y */, + rect.width(), + rect.height()); + XFreeGC(display_, gc); + Picture picture = XRenderCreatePicture( + display_, pixmap, ui::GetRenderARGB32Format(display_), 0, NULL); + XRenderPictFormat* pictformat = + XRenderFindVisualFormat(display_, attributes_.visual); + Picture dest_picture = XRenderCreatePicture( + display_, compositor_->widget(), pictformat, 0, NULL); + XRenderComposite(display_, + PictOpSrc, // op + picture, // src + 0, // mask + dest_picture, // dest + 0, // src_x + 0, // src_y + 0, // mask_x + 0, // mask_y + rect.x(), // dest_x + rect.y(), // dest_y + rect.width(), // width + rect.height()); // height + XRenderFreePicture(display_, picture); + XRenderFreePicture(display_, dest_picture); + XFreePixmap(display_, pixmap); + return; + } + // TODO(jbauman): Switch to XShmPutImage since it's async. SkImageInfo info; size_t rowBytes; diff --git a/ui/base/x/x11_util.cc b/ui/base/x/x11_util.cc index b2b5ef4b82ac39..4bfd5c7ee9f9d8 100644 --- a/ui/base/x/x11_util.cc +++ b/ui/base/x/x11_util.cc @@ -300,6 +300,15 @@ SharedMemorySupport QuerySharedMemorySupport(XDisplay* dpy) { return shared_memory_support; } +bool QueryRenderSupport(Display* dpy) { + int dummy; + // We don't care about the version of Xrender since all the features which + // we use are included in every version. + static bool render_supported = XRenderQueryExtension(dpy, &dummy, &dummy); + + return render_supported; +} + ::Cursor GetXCursor(int cursor_shape) { if (!cursor_cache) cursor_cache = new XCursorCache; diff --git a/ui/base/x/x11_util.h b/ui/base/x/x11_util.h index e9af790902a7c2..cd347c63c6fe8f 100644 --- a/ui/base/x/x11_util.h +++ b/ui/base/x/x11_util.h @@ -58,6 +58,9 @@ enum SharedMemorySupport { // Return the shared memory type of our X connection. UI_BASE_EXPORT SharedMemorySupport QuerySharedMemorySupport(XDisplay* dpy); +// Return true iff the display supports Xrender +UI_BASE_EXPORT bool QueryRenderSupport(XDisplay* dpy); + // Returns an X11 Cursor, sharable across the process. // |cursor_shape| is an X font cursor shape, see XCreateFontCursor(). UI_BASE_EXPORT ::Cursor GetXCursor(int cursor_shape);