| // Copyright 2014 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "content/browser/compositor/software_output_device_x11.h" |
| |
| #include <X11/Xlib.h> |
| #include <X11/Xutil.h> |
| |
| #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" |
| |
| namespace content { |
| |
| SoftwareOutputDeviceX11::SoftwareOutputDeviceX11(ui::Compositor* compositor) |
| : compositor_(compositor), display_(gfx::GetXDisplay()), gc_(NULL) { |
| // TODO(skaslev) Remove this when crbug.com/180702 is fixed. |
| DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| |
| gc_ = XCreateGC(display_, compositor_->widget(), 0, NULL); |
| if (!XGetWindowAttributes(display_, compositor_->widget(), &attributes_)) { |
| LOG(ERROR) << "XGetWindowAttributes failed for window " |
| << compositor_->widget(); |
| return; |
| } |
| } |
| |
| SoftwareOutputDeviceX11::~SoftwareOutputDeviceX11() { |
| DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| |
| XFreeGC(display_, gc_); |
| } |
| |
| void SoftwareOutputDeviceX11::EndPaint(cc::SoftwareFrameData* frame_data) { |
| DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| DCHECK(surface_); |
| DCHECK(frame_data); |
| |
| if (!surface_) |
| return; |
| |
| SoftwareOutputDevice::EndPaint(frame_data); |
| |
| gfx::Rect rect = damage_rect_; |
| rect.Intersect(gfx::Rect(viewport_pixel_size_)); |
| 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 = surface_->peekPixels(&info, &rowBytes); |
| image.width = viewport_pixel_size_.width(); |
| image.height = viewport_pixel_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. |
| SkImageInfo info; |
| size_t rowBytes; |
| const void* addr = surface_->peekPixels(&info, &rowBytes); |
| gfx::PutARGBImage(display_, |
| attributes_.visual, |
| attributes_.depth, |
| compositor_->widget(), |
| gc_, |
| static_cast<const uint8*>(addr), |
| viewport_pixel_size_.width(), |
| viewport_pixel_size_.height(), |
| rect.x(), |
| rect.y(), |
| rect.x(), |
| rect.y(), |
| rect.width(), |
| rect.height()); |
| } |
| |
| } // namespace content |