Home | History | Annotate | Download | only in compositor
      1 // Copyright 2014 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include "content/browser/compositor/software_output_device_x11.h"
      6 
      7 #include <X11/Xlib.h>
      8 #include <X11/Xutil.h>
      9 
     10 #include "content/public/browser/browser_thread.h"
     11 #include "third_party/skia/include/core/SkBitmap.h"
     12 #include "third_party/skia/include/core/SkDevice.h"
     13 #include "ui/base/x/x11_util.h"
     14 #include "ui/base/x/x11_util_internal.h"
     15 #include "ui/compositor/compositor.h"
     16 #include "ui/gfx/x/x11_types.h"
     17 
     18 namespace content {
     19 
     20 SoftwareOutputDeviceX11::SoftwareOutputDeviceX11(ui::Compositor* compositor)
     21     : compositor_(compositor), display_(gfx::GetXDisplay()), gc_(NULL) {
     22   // TODO(skaslev) Remove this when crbug.com/180702 is fixed.
     23   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
     24 
     25   gc_ = XCreateGC(display_, compositor_->widget(), 0, NULL);
     26   if (!XGetWindowAttributes(display_, compositor_->widget(), &attributes_)) {
     27     LOG(ERROR) << "XGetWindowAttributes failed for window "
     28                << compositor_->widget();
     29     return;
     30   }
     31 }
     32 
     33 SoftwareOutputDeviceX11::~SoftwareOutputDeviceX11() {
     34   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
     35 
     36   XFreeGC(display_, gc_);
     37 }
     38 
     39 void SoftwareOutputDeviceX11::EndPaint(cc::SoftwareFrameData* frame_data) {
     40   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
     41   DCHECK(canvas_);
     42   DCHECK(frame_data);
     43 
     44   if (!canvas_)
     45     return;
     46 
     47   SoftwareOutputDevice::EndPaint(frame_data);
     48 
     49   gfx::Rect rect = damage_rect_;
     50   rect.Intersect(gfx::Rect(viewport_pixel_size_));
     51   if (rect.IsEmpty())
     52     return;
     53 
     54   int bpp = gfx::BitsPerPixelForPixmapDepth(display_, attributes_.depth);
     55 
     56   if (bpp != 32 && bpp != 16 && ui::QueryRenderSupport(display_)) {
     57     // gfx::PutARGBImage only supports 16 and 32 bpp, but Xrender can do other
     58     // conversions.
     59     Pixmap pixmap = XCreatePixmap(
     60         display_, compositor_->widget(), rect.width(), rect.height(), 32);
     61     GC gc = XCreateGC(display_, pixmap, 0, NULL);
     62     XImage image;
     63     memset(&image, 0, sizeof(image));
     64 
     65     SkImageInfo info;
     66     size_t rowBytes;
     67     const void* addr = canvas_->peekPixels(&info, &rowBytes);
     68     image.width = viewport_pixel_size_.width();
     69     image.height = viewport_pixel_size_.height();
     70     image.depth = 32;
     71     image.bits_per_pixel = 32;
     72     image.format = ZPixmap;
     73     image.byte_order = LSBFirst;
     74     image.bitmap_unit = 8;
     75     image.bitmap_bit_order = LSBFirst;
     76     image.bytes_per_line = rowBytes;
     77     image.red_mask = 0xff;
     78     image.green_mask = 0xff00;
     79     image.blue_mask = 0xff0000;
     80     image.data = const_cast<char*>(static_cast<const char*>(addr));
     81 
     82     XPutImage(display_,
     83               pixmap,
     84               gc,
     85               &image,
     86               rect.x(),
     87               rect.y() /* source x, y */,
     88               0,
     89               0 /* dest x, y */,
     90               rect.width(),
     91               rect.height());
     92     XFreeGC(display_, gc);
     93     Picture picture = XRenderCreatePicture(
     94         display_, pixmap, ui::GetRenderARGB32Format(display_), 0, NULL);
     95     XRenderPictFormat* pictformat =
     96         XRenderFindVisualFormat(display_, attributes_.visual);
     97     Picture dest_picture = XRenderCreatePicture(
     98         display_, compositor_->widget(), pictformat, 0, NULL);
     99     XRenderComposite(display_,
    100                      PictOpSrc,       // op
    101                      picture,         // src
    102                      0,               // mask
    103                      dest_picture,    // dest
    104                      0,               // src_x
    105                      0,               // src_y
    106                      0,               // mask_x
    107                      0,               // mask_y
    108                      rect.x(),        // dest_x
    109                      rect.y(),        // dest_y
    110                      rect.width(),    // width
    111                      rect.height());  // height
    112     XRenderFreePicture(display_, picture);
    113     XRenderFreePicture(display_, dest_picture);
    114     XFreePixmap(display_, pixmap);
    115     return;
    116   }
    117 
    118   // TODO(jbauman): Switch to XShmPutImage since it's async.
    119   SkImageInfo info;
    120   size_t rowBytes;
    121   const void* addr = canvas_->peekPixels(&info, &rowBytes);
    122   gfx::PutARGBImage(display_,
    123                     attributes_.visual,
    124                     attributes_.depth,
    125                     compositor_->widget(),
    126                     gc_,
    127                     static_cast<const uint8*>(addr),
    128                     viewport_pixel_size_.width(),
    129                     viewport_pixel_size_.height(),
    130                     rect.x(),
    131                     rect.y(),
    132                     rect.x(),
    133                     rect.y(),
    134                     rect.width(),
    135                     rect.height());
    136 }
    137 
    138 }  // namespace content
    139