Re-subimission of https://codereview.chromium.org/1041213003/
[chromium-blink-merge.git] / content / browser / compositor / software_output_device_x11.cc
blob6570c41082d99ac9ff88a23dab87028d4648e4f7
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.
5 #include "content/browser/compositor/software_output_device_x11.h"
7 #include <X11/Xlib.h>
8 #include <X11/Xutil.h>
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"
18 namespace content {
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_CURRENTLY_ON(BrowserThread::UI);
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;
33 SoftwareOutputDeviceX11::~SoftwareOutputDeviceX11() {
34 DCHECK_CURRENTLY_ON(BrowserThread::UI);
36 XFreeGC(display_, gc_);
39 void SoftwareOutputDeviceX11::EndPaint(cc::SoftwareFrameData* frame_data) {
40 DCHECK_CURRENTLY_ON(BrowserThread::UI);
41 DCHECK(surface_);
42 DCHECK(frame_data);
44 if (!surface_)
45 return;
47 SoftwareOutputDevice::EndPaint(frame_data);
49 gfx::Rect rect = damage_rect_;
50 rect.Intersect(gfx::Rect(viewport_pixel_size_));
51 if (rect.IsEmpty())
52 return;
54 int bpp = gfx::BitsPerPixelForPixmapDepth(display_, attributes_.depth);
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));
65 SkImageInfo info;
66 size_t rowBytes;
67 const void* addr = surface_->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));
82 XPutImage(display_,
83 pixmap,
84 gc,
85 &image,
86 rect.x(),
87 rect.y() /* source x, y */,
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;
118 // TODO(jbauman): Switch to XShmPutImage since it's async.
119 SkImageInfo info;
120 size_t rowBytes;
121 const void* addr = surface_->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());
138 } // namespace content