15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "media/tools/player_x11/x11_video_renderer.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <dlfcn.h>
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <X11/Xutil.h>
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <X11/extensions/Xrender.h>
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <X11/extensions/Xcomposite.h>
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/bind.h"
13ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch#include "base/message_loop/message_loop.h"
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "media/base/video_frame.h"
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "media/base/yuv_convert.h"
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Creates a 32-bit XImage.
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static XImage* CreateImage(Display* display, int width, int height) {
19f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  VLOG(0) << "Allocating XImage " << width << "x" << height;
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return  XCreateImage(display,
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       DefaultVisual(display, DefaultScreen(display)),
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       DefaultDepth(display, DefaultScreen(display)),
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       ZPixmap,
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       0,
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       static_cast<char*>(malloc(width * height * 4)),
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       width,
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       height,
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       32,
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       width * 4);
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Returns the picture format for ARGB.
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This method is originally from chrome/common/x11_util.cc.
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static XRenderPictFormat* GetRenderARGB32Format(Display* dpy) {
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static XRenderPictFormat* pictformat = NULL;
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (pictformat)
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return pictformat;
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // First look for a 32-bit format which ignores the alpha value.
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  XRenderPictFormat templ;
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  templ.depth = 32;
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  templ.type = PictTypeDirect;
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  templ.direct.red = 16;
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  templ.direct.green = 8;
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  templ.direct.blue = 0;
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  templ.direct.redMask = 0xff;
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  templ.direct.greenMask = 0xff;
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  templ.direct.blueMask = 0xff;
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  templ.direct.alphaMask = 0;
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static const unsigned long kMask =
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      PictFormatType | PictFormatDepth |
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      PictFormatRed | PictFormatRedMask |
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      PictFormatGreen | PictFormatGreenMask |
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      PictFormatBlue | PictFormatBlueMask |
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      PictFormatAlphaMask;
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pictformat = XRenderFindFormat(dpy, kMask, &templ, 0 /* first result */);
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!pictformat) {
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Not all X servers support xRGB32 formats. However, the XRender spec
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // says that they must support an ARGB32 format, so we can always return
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // that.
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pictformat = XRenderFindStandardFormat(dpy, PictStandardARGB32);
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CHECK(pictformat) << "XRender ARGB32 not supported.";
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return pictformat;
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)X11VideoRenderer::X11VideoRenderer(Display* display, Window window)
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : display_(display),
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      window_(window),
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      image_(NULL),
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      picture_(0),
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      use_render_(false) {
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)X11VideoRenderer::~X11VideoRenderer() {
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (image_)
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    XDestroyImage(image_);
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (use_render_)
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    XRenderFreePicture(display_, picture_);
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
865c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liuvoid X11VideoRenderer::Paint(
875c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    const scoped_refptr<media::VideoFrame>& video_frame) {
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!image_)
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Initialize(video_frame->coded_size(), video_frame->visible_rect());
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const int coded_width = video_frame->coded_size().width();
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const int coded_height = video_frame->coded_size().height();
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const int visible_width = video_frame->visible_rect().width();
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const int visible_height = video_frame->visible_rect().height();
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Check if we need to reallocate our XImage.
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (image_->width != coded_width || image_->height != coded_height) {
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    XDestroyImage(image_);
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    image_ = CreateImage(display_, coded_width, coded_height);
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Convert YUV frame to RGB.
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(video_frame->format() == media::VideoFrame::YV12 ||
104c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch         video_frame->format() == media::VideoFrame::I420 ||
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         video_frame->format() == media::VideoFrame::YV16);
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(video_frame->stride(media::VideoFrame::kUPlane) ==
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         video_frame->stride(media::VideoFrame::kVPlane));
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(image_->data);
110c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  media::YUVType yuv_type = (video_frame->format() == media::VideoFrame::YV12 ||
111c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch                             video_frame->format() == media::VideoFrame::I420)
112c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch                                ? media::YV12
113c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch                                : media::YV16;
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  media::ConvertYUVToRGB32(video_frame->data(media::VideoFrame::kYPlane),
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           video_frame->data(media::VideoFrame::kUPlane),
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           video_frame->data(media::VideoFrame::kVPlane),
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           (uint8*)image_->data, coded_width, coded_height,
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           video_frame->stride(media::VideoFrame::kYPlane),
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           video_frame->stride(media::VideoFrame::kUPlane),
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           image_->bytes_per_line,
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           yuv_type);
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (use_render_) {
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // If XRender is used, we'll upload the image to a pixmap. And then
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // creats a picture from the pixmap and composite the picture over
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // the picture represending the window.
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Creates a XImage.
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    XImage image;
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    memset(&image, 0, sizeof(image));
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    image.width = coded_width;
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    image.height = coded_height;
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    image.depth = 32;
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    image.bits_per_pixel = 32;
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    image.format = ZPixmap;
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    image.byte_order = LSBFirst;
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    image.bitmap_unit = 8;
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    image.bitmap_bit_order = LSBFirst;
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    image.bytes_per_line = image_->bytes_per_line;
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    image.red_mask = 0xff;
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    image.green_mask = 0xff00;
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    image.blue_mask = 0xff0000;
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    image.data = image_->data;
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Creates a pixmap and uploads from the XImage.
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    unsigned long pixmap = XCreatePixmap(display_, window_,
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                         visible_width, visible_height,
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                         32);
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    GC gc = XCreateGC(display_, pixmap, 0, NULL);
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    XPutImage(display_, pixmap, gc, &image,
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              video_frame->visible_rect().x(),
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              video_frame->visible_rect().y(),
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              0, 0,
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              visible_width, visible_height);
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    XFreeGC(display_, gc);
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Creates the picture representing the pixmap.
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    unsigned long picture = XRenderCreatePicture(
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        display_, pixmap, GetRenderARGB32Format(display_), 0, NULL);
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Composite the picture over the picture representing the window.
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    XRenderComposite(display_, PictOpSrc, picture, 0,
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     picture_, 0, 0, 0, 0, 0, 0,
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     visible_width, visible_height);
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    XRenderFreePicture(display_, picture);
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    XFreePixmap(display_, pixmap);
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // If XRender is not used, simply put the image to the server.
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // This will have a tearing effect but this is OK.
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // TODO(hclam): Upload the image to a pixmap and do XCopyArea()
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // to the window.
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GC gc = XCreateGC(display_, window_, 0, NULL);
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  XPutImage(display_, window_, gc, image_,
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            video_frame->visible_rect().x(),
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            video_frame->visible_rect().y(),
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            0, 0, visible_width, visible_height);
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  XFlush(display_);
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  XFreeGC(display_, gc);
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void X11VideoRenderer::Initialize(gfx::Size coded_size,
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                  gfx::Rect visible_rect) {
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CHECK(!image_);
187f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  VLOG(0) << "Initializing X11 Renderer...";
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Resize the window to fit that of the video.
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  XResizeWindow(display_, window_, visible_rect.width(), visible_rect.height());
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  image_ = CreateImage(display_, coded_size.width(), coded_size.height());
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Testing XRender support. We'll use the very basic of XRender
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // so if it presents it is already good enough. We don't need
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // to check its version.
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int dummy;
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  use_render_ = XRenderQueryExtension(display_, &dummy, &dummy);
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (use_render_) {
200f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    VLOG(0) << "Using XRender extension.";
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // If we are using XRender, we'll create a picture representing the
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // window.
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    XWindowAttributes attr;
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    XGetWindowAttributes(display_, window_, &attr);
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    XRenderPictFormat* pictformat = XRenderFindVisualFormat(
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        display_,
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        attr.visual);
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CHECK(pictformat) << "XRender does not support default visual";
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    picture_ = XRenderCreatePicture(display_, window_, pictformat, 0, NULL);
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CHECK(picture_) << "Backing picture not created";
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
216