Upstream version 7.36.149.0
[platform/framework/web/crosswalk.git] / src / content / browser / compositor / software_output_device_x11.cc
index 3e376f6..44267d4 100644 (file)
@@ -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"
 
@@ -36,10 +38,10 @@ SoftwareOutputDeviceX11::~SoftwareOutputDeviceX11() {
 
 void SoftwareOutputDeviceX11::EndPaint(cc::SoftwareFrameData* frame_data) {
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
-  DCHECK(device_);
+  DCHECK(canvas_);
   DCHECK(frame_data);
 
-  if (!device_)
+  if (!canvas_)
     return;
 
   SoftwareOutputDevice::EndPaint(frame_data);
@@ -49,14 +51,80 @@ 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<char*>(static_cast<const char*>(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.
-  const SkBitmap& bitmap = device_->accessBitmap(false);
+  SkImageInfo info;
+  size_t rowBytes;
+  const void* addr = canvas_->peekPixels(&info, &rowBytes);
   gfx::PutARGBImage(display_,
                     attributes_.visual,
                     attributes_.depth,
                     compositor_->widget(),
                     gc_,
-                    static_cast<const uint8*>(bitmap.getPixels()),
+                    static_cast<const uint8*>(addr),
                     viewport_size_.width(),
                     viewport_size_.height(),
                     rect.x(),