13d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org/* 23d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org * Copyright (c) 2013 The WebRTC project authors. All Rights Reserved. 33d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org * 43d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org * Use of this source code is governed by a BSD-style license 53d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org * that can be found in the LICENSE file in the root of the source 63d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org * tree. An additional intellectual property rights grant can be found 73d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org * in the file PATENTS. All contributing project authors may 83d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org * be found in the AUTHORS file in the root of the source tree. 93d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org */ 103d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org 113d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org#include "webrtc/modules/desktop_capture/x11/x_server_pixel_buffer.h" 123d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org 1312dc1a38ca54a000e4fecfbc6d41138b895c9ca5pbos@webrtc.org#include <assert.h> 149f282403f258162ca53eb2f16b8e9a26e7970096sergeyu@chromium.org#include <string.h> 153d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org#include <sys/shm.h> 163d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org 179f282403f258162ca53eb2f16b8e9a26e7970096sergeyu@chromium.org#include "webrtc/modules/desktop_capture/desktop_frame.h" 189f282403f258162ca53eb2f16b8e9a26e7970096sergeyu@chromium.org#include "webrtc/modules/desktop_capture/x11/x_error_trap.h" 1998f53510b222f71fdd8b799b2f33737ceeb28c61Henrik Kjellander#include "webrtc/system_wrappers/include/logging.h" 203d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org 213d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.orgnamespace { 223d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org 239f282403f258162ca53eb2f16b8e9a26e7970096sergeyu@chromium.org// Returns the number of bits |mask| has to be shifted left so its last 249f282403f258162ca53eb2f16b8e9a26e7970096sergeyu@chromium.org// (most-significant) bit set becomes the most-significant bit of the word. 259f282403f258162ca53eb2f16b8e9a26e7970096sergeyu@chromium.org// When |mask| is 0 the function returns 31. 269f282403f258162ca53eb2f16b8e9a26e7970096sergeyu@chromium.orguint32_t MaskToShift(uint32_t mask) { 279f282403f258162ca53eb2f16b8e9a26e7970096sergeyu@chromium.org int shift = 0; 289f282403f258162ca53eb2f16b8e9a26e7970096sergeyu@chromium.org if ((mask & 0xffff0000u) == 0) { 299f282403f258162ca53eb2f16b8e9a26e7970096sergeyu@chromium.org mask <<= 16; 309f282403f258162ca53eb2f16b8e9a26e7970096sergeyu@chromium.org shift += 16; 319f282403f258162ca53eb2f16b8e9a26e7970096sergeyu@chromium.org } 329f282403f258162ca53eb2f16b8e9a26e7970096sergeyu@chromium.org if ((mask & 0xff000000u) == 0) { 339f282403f258162ca53eb2f16b8e9a26e7970096sergeyu@chromium.org mask <<= 8; 349f282403f258162ca53eb2f16b8e9a26e7970096sergeyu@chromium.org shift += 8; 359f282403f258162ca53eb2f16b8e9a26e7970096sergeyu@chromium.org } 369f282403f258162ca53eb2f16b8e9a26e7970096sergeyu@chromium.org if ((mask & 0xf0000000u) == 0) { 379f282403f258162ca53eb2f16b8e9a26e7970096sergeyu@chromium.org mask <<= 4; 389f282403f258162ca53eb2f16b8e9a26e7970096sergeyu@chromium.org shift += 4; 399f282403f258162ca53eb2f16b8e9a26e7970096sergeyu@chromium.org } 409f282403f258162ca53eb2f16b8e9a26e7970096sergeyu@chromium.org if ((mask & 0xc0000000u) == 0) { 419f282403f258162ca53eb2f16b8e9a26e7970096sergeyu@chromium.org mask <<= 2; 429f282403f258162ca53eb2f16b8e9a26e7970096sergeyu@chromium.org shift += 2; 439f282403f258162ca53eb2f16b8e9a26e7970096sergeyu@chromium.org } 449f282403f258162ca53eb2f16b8e9a26e7970096sergeyu@chromium.org if ((mask & 0x80000000u) == 0) 459f282403f258162ca53eb2f16b8e9a26e7970096sergeyu@chromium.org shift += 1; 463d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org 479f282403f258162ca53eb2f16b8e9a26e7970096sergeyu@chromium.org return shift; 483d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org} 493d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org 509f282403f258162ca53eb2f16b8e9a26e7970096sergeyu@chromium.org// Returns true if |image| is in RGB format. 519f282403f258162ca53eb2f16b8e9a26e7970096sergeyu@chromium.orgbool IsXImageRGBFormat(XImage* image) { 529f282403f258162ca53eb2f16b8e9a26e7970096sergeyu@chromium.org return image->bits_per_pixel == 32 && 539f282403f258162ca53eb2f16b8e9a26e7970096sergeyu@chromium.org image->red_mask == 0xff0000 && 549f282403f258162ca53eb2f16b8e9a26e7970096sergeyu@chromium.org image->green_mask == 0xff00 && 559f282403f258162ca53eb2f16b8e9a26e7970096sergeyu@chromium.org image->blue_mask == 0xff; 563d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org} 573d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org 583d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org} // namespace 593d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org 603d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.orgnamespace webrtc { 613d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org 623d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.orgXServerPixelBuffer::XServerPixelBuffer() 639f282403f258162ca53eb2f16b8e9a26e7970096sergeyu@chromium.org : display_(NULL), window_(0), 643d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org x_image_(NULL), 653d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org shm_segment_info_(NULL), shm_pixmap_(0), shm_gc_(NULL) { 663d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org} 673d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org 683d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.orgXServerPixelBuffer::~XServerPixelBuffer() { 693d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org Release(); 703d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org} 713d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org 723d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.orgvoid XServerPixelBuffer::Release() { 733d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org if (x_image_) { 743d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org XDestroyImage(x_image_); 753d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org x_image_ = NULL; 763d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org } 773d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org if (shm_pixmap_) { 783d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org XFreePixmap(display_, shm_pixmap_); 793d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org shm_pixmap_ = 0; 803d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org } 813d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org if (shm_gc_) { 823d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org XFreeGC(display_, shm_gc_); 833d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org shm_gc_ = NULL; 843d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org } 853d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org if (shm_segment_info_) { 863d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org if (shm_segment_info_->shmaddr != reinterpret_cast<char*>(-1)) 873d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org shmdt(shm_segment_info_->shmaddr); 883d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org if (shm_segment_info_->shmid != -1) 893d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org shmctl(shm_segment_info_->shmid, IPC_RMID, 0); 903d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org delete shm_segment_info_; 913d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org shm_segment_info_ = NULL; 923d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org } 939f282403f258162ca53eb2f16b8e9a26e7970096sergeyu@chromium.org window_ = 0; 943d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org} 953d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org 969f282403f258162ca53eb2f16b8e9a26e7970096sergeyu@chromium.orgbool XServerPixelBuffer::Init(Display* display, Window window) { 973d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org Release(); 983d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org display_ = display; 993d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org 1009f282403f258162ca53eb2f16b8e9a26e7970096sergeyu@chromium.org XWindowAttributes attributes; 1019f282403f258162ca53eb2f16b8e9a26e7970096sergeyu@chromium.org { 1029f282403f258162ca53eb2f16b8e9a26e7970096sergeyu@chromium.org XErrorTrap error_trap(display_); 1039f282403f258162ca53eb2f16b8e9a26e7970096sergeyu@chromium.org if (!XGetWindowAttributes(display_, window, &attributes) || 1049f282403f258162ca53eb2f16b8e9a26e7970096sergeyu@chromium.org error_trap.GetLastErrorAndDisable() != 0) { 1059f282403f258162ca53eb2f16b8e9a26e7970096sergeyu@chromium.org return false; 1069f282403f258162ca53eb2f16b8e9a26e7970096sergeyu@chromium.org } 1079f282403f258162ca53eb2f16b8e9a26e7970096sergeyu@chromium.org } 1089f282403f258162ca53eb2f16b8e9a26e7970096sergeyu@chromium.org 1099f282403f258162ca53eb2f16b8e9a26e7970096sergeyu@chromium.org window_size_ = DesktopSize(attributes.width, attributes.height); 1109f282403f258162ca53eb2f16b8e9a26e7970096sergeyu@chromium.org window_ = window; 1119f282403f258162ca53eb2f16b8e9a26e7970096sergeyu@chromium.org InitShm(attributes); 1129f282403f258162ca53eb2f16b8e9a26e7970096sergeyu@chromium.org 1139f282403f258162ca53eb2f16b8e9a26e7970096sergeyu@chromium.org return true; 1143d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org} 1153d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org 1169f282403f258162ca53eb2f16b8e9a26e7970096sergeyu@chromium.orgvoid XServerPixelBuffer::InitShm(const XWindowAttributes& attributes) { 1179f282403f258162ca53eb2f16b8e9a26e7970096sergeyu@chromium.org Visual* default_visual = attributes.visual; 1189f282403f258162ca53eb2f16b8e9a26e7970096sergeyu@chromium.org int default_depth = attributes.depth; 1193d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org 1203d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org int major, minor; 1219f282403f258162ca53eb2f16b8e9a26e7970096sergeyu@chromium.org Bool have_pixmaps; 1229f282403f258162ca53eb2f16b8e9a26e7970096sergeyu@chromium.org if (!XShmQueryVersion(display_, &major, &minor, &have_pixmaps)) { 1233d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org // Shared memory not supported. CaptureRect will use the XImage API instead. 1243d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org return; 1259f282403f258162ca53eb2f16b8e9a26e7970096sergeyu@chromium.org } 1263d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org 1273d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org bool using_shm = false; 1283d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org shm_segment_info_ = new XShmSegmentInfo; 1293d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org shm_segment_info_->shmid = -1; 1303d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org shm_segment_info_->shmaddr = reinterpret_cast<char*>(-1); 1313d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org shm_segment_info_->readOnly = False; 1323d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org x_image_ = XShmCreateImage(display_, default_visual, default_depth, ZPixmap, 1339f282403f258162ca53eb2f16b8e9a26e7970096sergeyu@chromium.org 0, shm_segment_info_, window_size_.width(), 1349f282403f258162ca53eb2f16b8e9a26e7970096sergeyu@chromium.org window_size_.height()); 1353d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org if (x_image_) { 1363d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org shm_segment_info_->shmid = shmget( 1373d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org IPC_PRIVATE, x_image_->bytes_per_line * x_image_->height, 1383d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org IPC_CREAT | 0600); 1393d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org if (shm_segment_info_->shmid != -1) { 1403d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org shm_segment_info_->shmaddr = x_image_->data = 1413d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org reinterpret_cast<char*>(shmat(shm_segment_info_->shmid, 0, 0)); 1423d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org if (x_image_->data != reinterpret_cast<char*>(-1)) { 1439f282403f258162ca53eb2f16b8e9a26e7970096sergeyu@chromium.org XErrorTrap error_trap(display_); 1443d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org using_shm = XShmAttach(display_, shm_segment_info_); 1453d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org XSync(display_, False); 1469f282403f258162ca53eb2f16b8e9a26e7970096sergeyu@chromium.org if (error_trap.GetLastErrorAndDisable() != 0) 1473d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org using_shm = false; 1483d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org if (using_shm) { 1493d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org LOG(LS_VERBOSE) << "Using X shared memory segment " 1503d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org << shm_segment_info_->shmid; 1513d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org } 1523d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org } 1533d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org } else { 1543d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org LOG(LS_WARNING) << "Failed to get shared memory segment. " 1553d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org "Performance may be degraded."; 1563d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org } 1573d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org } 1583d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org 1593d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org if (!using_shm) { 1603d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org LOG(LS_WARNING) << "Not using shared memory. Performance may be degraded."; 1613d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org Release(); 1623d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org return; 1633d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org } 1643d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org 1659f282403f258162ca53eb2f16b8e9a26e7970096sergeyu@chromium.org if (have_pixmaps) 1669f282403f258162ca53eb2f16b8e9a26e7970096sergeyu@chromium.org have_pixmaps = InitPixmaps(default_depth); 1673d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org 1683d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org shmctl(shm_segment_info_->shmid, IPC_RMID, 0); 1693d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org shm_segment_info_->shmid = -1; 1703d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org 1713d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org LOG(LS_VERBOSE) << "Using X shared memory extension v" 1723d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org << major << "." << minor 1739f282403f258162ca53eb2f16b8e9a26e7970096sergeyu@chromium.org << " with" << (have_pixmaps ? "" : "out") << " pixmaps."; 1743d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org} 1753d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org 1763d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.orgbool XServerPixelBuffer::InitPixmaps(int depth) { 1773d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org if (XShmPixmapFormat(display_) != ZPixmap) 1783d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org return false; 1793d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org 1809f282403f258162ca53eb2f16b8e9a26e7970096sergeyu@chromium.org { 1819f282403f258162ca53eb2f16b8e9a26e7970096sergeyu@chromium.org XErrorTrap error_trap(display_); 1829f282403f258162ca53eb2f16b8e9a26e7970096sergeyu@chromium.org shm_pixmap_ = XShmCreatePixmap(display_, window_, 1839f282403f258162ca53eb2f16b8e9a26e7970096sergeyu@chromium.org shm_segment_info_->shmaddr, 1849f282403f258162ca53eb2f16b8e9a26e7970096sergeyu@chromium.org shm_segment_info_, 1859f282403f258162ca53eb2f16b8e9a26e7970096sergeyu@chromium.org window_size_.width(), 1869f282403f258162ca53eb2f16b8e9a26e7970096sergeyu@chromium.org window_size_.height(), depth); 1879f282403f258162ca53eb2f16b8e9a26e7970096sergeyu@chromium.org XSync(display_, False); 1889f282403f258162ca53eb2f16b8e9a26e7970096sergeyu@chromium.org if (error_trap.GetLastErrorAndDisable() != 0) { 1899f282403f258162ca53eb2f16b8e9a26e7970096sergeyu@chromium.org // |shm_pixmap_| is not not valid because the request was not processed 1909f282403f258162ca53eb2f16b8e9a26e7970096sergeyu@chromium.org // by the X Server, so zero it. 1919f282403f258162ca53eb2f16b8e9a26e7970096sergeyu@chromium.org shm_pixmap_ = 0; 1929f282403f258162ca53eb2f16b8e9a26e7970096sergeyu@chromium.org return false; 1939f282403f258162ca53eb2f16b8e9a26e7970096sergeyu@chromium.org } 1943d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org } 1953d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org 1969f282403f258162ca53eb2f16b8e9a26e7970096sergeyu@chromium.org { 1979f282403f258162ca53eb2f16b8e9a26e7970096sergeyu@chromium.org XErrorTrap error_trap(display_); 1989f282403f258162ca53eb2f16b8e9a26e7970096sergeyu@chromium.org XGCValues shm_gc_values; 1999f282403f258162ca53eb2f16b8e9a26e7970096sergeyu@chromium.org shm_gc_values.subwindow_mode = IncludeInferiors; 2009f282403f258162ca53eb2f16b8e9a26e7970096sergeyu@chromium.org shm_gc_values.graphics_exposures = False; 2019f282403f258162ca53eb2f16b8e9a26e7970096sergeyu@chromium.org shm_gc_ = XCreateGC(display_, window_, 2029f282403f258162ca53eb2f16b8e9a26e7970096sergeyu@chromium.org GCSubwindowMode | GCGraphicsExposures, 2039f282403f258162ca53eb2f16b8e9a26e7970096sergeyu@chromium.org &shm_gc_values); 2049f282403f258162ca53eb2f16b8e9a26e7970096sergeyu@chromium.org XSync(display_, False); 2059f282403f258162ca53eb2f16b8e9a26e7970096sergeyu@chromium.org if (error_trap.GetLastErrorAndDisable() != 0) { 2069f282403f258162ca53eb2f16b8e9a26e7970096sergeyu@chromium.org XFreePixmap(display_, shm_pixmap_); 2079f282403f258162ca53eb2f16b8e9a26e7970096sergeyu@chromium.org shm_pixmap_ = 0; 2089f282403f258162ca53eb2f16b8e9a26e7970096sergeyu@chromium.org shm_gc_ = 0; // See shm_pixmap_ comment above. 2099f282403f258162ca53eb2f16b8e9a26e7970096sergeyu@chromium.org return false; 2109f282403f258162ca53eb2f16b8e9a26e7970096sergeyu@chromium.org } 2113d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org } 2123d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org 2133d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org return true; 2143d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org} 2153d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org 216cc1ba15fe737bfc58ef279d50d7e713cbd8b9310jiayl@webrtc.orgbool XServerPixelBuffer::IsWindowValid() const { 217cc1ba15fe737bfc58ef279d50d7e713cbd8b9310jiayl@webrtc.org XWindowAttributes attributes; 218cc1ba15fe737bfc58ef279d50d7e713cbd8b9310jiayl@webrtc.org { 219cc1ba15fe737bfc58ef279d50d7e713cbd8b9310jiayl@webrtc.org XErrorTrap error_trap(display_); 220cc1ba15fe737bfc58ef279d50d7e713cbd8b9310jiayl@webrtc.org if (!XGetWindowAttributes(display_, window_, &attributes) || 221cc1ba15fe737bfc58ef279d50d7e713cbd8b9310jiayl@webrtc.org error_trap.GetLastErrorAndDisable() != 0) { 222cc1ba15fe737bfc58ef279d50d7e713cbd8b9310jiayl@webrtc.org return false; 223cc1ba15fe737bfc58ef279d50d7e713cbd8b9310jiayl@webrtc.org } 224cc1ba15fe737bfc58ef279d50d7e713cbd8b9310jiayl@webrtc.org } 225cc1ba15fe737bfc58ef279d50d7e713cbd8b9310jiayl@webrtc.org return true; 226cc1ba15fe737bfc58ef279d50d7e713cbd8b9310jiayl@webrtc.org} 227cc1ba15fe737bfc58ef279d50d7e713cbd8b9310jiayl@webrtc.org 2283d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.orgvoid XServerPixelBuffer::Synchronize() { 2293d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org if (shm_segment_info_ && !shm_pixmap_) { 2303d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org // XShmGetImage can fail if the display is being reconfigured. 2319f282403f258162ca53eb2f16b8e9a26e7970096sergeyu@chromium.org XErrorTrap error_trap(display_); 2329f282403f258162ca53eb2f16b8e9a26e7970096sergeyu@chromium.org XShmGetImage(display_, window_, x_image_, 0, 0, AllPlanes); 2333d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org } 2343d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org} 2353d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org 2369f282403f258162ca53eb2f16b8e9a26e7970096sergeyu@chromium.orgvoid XServerPixelBuffer::CaptureRect(const DesktopRect& rect, 2379f282403f258162ca53eb2f16b8e9a26e7970096sergeyu@chromium.org DesktopFrame* frame) { 2389f282403f258162ca53eb2f16b8e9a26e7970096sergeyu@chromium.org assert(rect.right() <= window_size_.width()); 2399f282403f258162ca53eb2f16b8e9a26e7970096sergeyu@chromium.org assert(rect.bottom() <= window_size_.height()); 2409f282403f258162ca53eb2f16b8e9a26e7970096sergeyu@chromium.org 2419f282403f258162ca53eb2f16b8e9a26e7970096sergeyu@chromium.org uint8_t* data; 2423d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org 2433d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org if (shm_segment_info_) { 2443d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org if (shm_pixmap_) { 2459f282403f258162ca53eb2f16b8e9a26e7970096sergeyu@chromium.org XCopyArea(display_, window_, shm_pixmap_, shm_gc_, 2463d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org rect.left(), rect.top(), rect.width(), rect.height(), 2473d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org rect.left(), rect.top()); 2483d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org XSync(display_, False); 2493d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org } 2509f282403f258162ca53eb2f16b8e9a26e7970096sergeyu@chromium.org data = reinterpret_cast<uint8_t*>(x_image_->data) + 2513d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org rect.top() * x_image_->bytes_per_line + 2523d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org rect.left() * x_image_->bits_per_pixel / 8; 2533d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org } else { 2543d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org if (x_image_) 2553d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org XDestroyImage(x_image_); 2569f282403f258162ca53eb2f16b8e9a26e7970096sergeyu@chromium.org x_image_ = XGetImage(display_, window_, rect.left(), rect.top(), 2573d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org rect.width(), rect.height(), AllPlanes, ZPixmap); 2589f282403f258162ca53eb2f16b8e9a26e7970096sergeyu@chromium.org data = reinterpret_cast<uint8_t*>(x_image_->data); 2593d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org } 2603d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org 2619f282403f258162ca53eb2f16b8e9a26e7970096sergeyu@chromium.org if (IsXImageRGBFormat(x_image_)) { 2629f282403f258162ca53eb2f16b8e9a26e7970096sergeyu@chromium.org FastBlit(data, rect, frame); 2639f282403f258162ca53eb2f16b8e9a26e7970096sergeyu@chromium.org } else { 2649f282403f258162ca53eb2f16b8e9a26e7970096sergeyu@chromium.org SlowBlit(data, rect, frame); 2659f282403f258162ca53eb2f16b8e9a26e7970096sergeyu@chromium.org } 2663d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org} 2673d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org 2689f282403f258162ca53eb2f16b8e9a26e7970096sergeyu@chromium.orgvoid XServerPixelBuffer::FastBlit(uint8_t* image, 2699f282403f258162ca53eb2f16b8e9a26e7970096sergeyu@chromium.org const DesktopRect& rect, 2709f282403f258162ca53eb2f16b8e9a26e7970096sergeyu@chromium.org DesktopFrame* frame) { 2719f282403f258162ca53eb2f16b8e9a26e7970096sergeyu@chromium.org uint8_t* src_pos = image; 2729f282403f258162ca53eb2f16b8e9a26e7970096sergeyu@chromium.org int src_stride = x_image_->bytes_per_line; 2739f282403f258162ca53eb2f16b8e9a26e7970096sergeyu@chromium.org int dst_x = rect.left(), dst_y = rect.top(); 2749f282403f258162ca53eb2f16b8e9a26e7970096sergeyu@chromium.org 2759f282403f258162ca53eb2f16b8e9a26e7970096sergeyu@chromium.org uint8_t* dst_pos = frame->data() + frame->stride() * dst_y; 2769f282403f258162ca53eb2f16b8e9a26e7970096sergeyu@chromium.org dst_pos += dst_x * DesktopFrame::kBytesPerPixel; 2779f282403f258162ca53eb2f16b8e9a26e7970096sergeyu@chromium.org 2789f282403f258162ca53eb2f16b8e9a26e7970096sergeyu@chromium.org int height = rect.height(); 2799f282403f258162ca53eb2f16b8e9a26e7970096sergeyu@chromium.org int row_bytes = rect.width() * DesktopFrame::kBytesPerPixel; 2809f282403f258162ca53eb2f16b8e9a26e7970096sergeyu@chromium.org for (int y = 0; y < height; ++y) { 2819f282403f258162ca53eb2f16b8e9a26e7970096sergeyu@chromium.org memcpy(dst_pos, src_pos, row_bytes); 2829f282403f258162ca53eb2f16b8e9a26e7970096sergeyu@chromium.org src_pos += src_stride; 2839f282403f258162ca53eb2f16b8e9a26e7970096sergeyu@chromium.org dst_pos += frame->stride(); 2849f282403f258162ca53eb2f16b8e9a26e7970096sergeyu@chromium.org } 2853d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org} 2863d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org 2879f282403f258162ca53eb2f16b8e9a26e7970096sergeyu@chromium.orgvoid XServerPixelBuffer::SlowBlit(uint8_t* image, 2889f282403f258162ca53eb2f16b8e9a26e7970096sergeyu@chromium.org const DesktopRect& rect, 2899f282403f258162ca53eb2f16b8e9a26e7970096sergeyu@chromium.org DesktopFrame* frame) { 2909f282403f258162ca53eb2f16b8e9a26e7970096sergeyu@chromium.org int src_stride = x_image_->bytes_per_line; 2919f282403f258162ca53eb2f16b8e9a26e7970096sergeyu@chromium.org int dst_x = rect.left(), dst_y = rect.top(); 2929f282403f258162ca53eb2f16b8e9a26e7970096sergeyu@chromium.org int width = rect.width(), height = rect.height(); 2939f282403f258162ca53eb2f16b8e9a26e7970096sergeyu@chromium.org 2949f282403f258162ca53eb2f16b8e9a26e7970096sergeyu@chromium.org uint32_t red_mask = x_image_->red_mask; 2959f282403f258162ca53eb2f16b8e9a26e7970096sergeyu@chromium.org uint32_t green_mask = x_image_->red_mask; 2969f282403f258162ca53eb2f16b8e9a26e7970096sergeyu@chromium.org uint32_t blue_mask = x_image_->blue_mask; 2979f282403f258162ca53eb2f16b8e9a26e7970096sergeyu@chromium.org 2989f282403f258162ca53eb2f16b8e9a26e7970096sergeyu@chromium.org uint32_t red_shift = MaskToShift(red_mask); 2999f282403f258162ca53eb2f16b8e9a26e7970096sergeyu@chromium.org uint32_t green_shift = MaskToShift(green_mask); 3009f282403f258162ca53eb2f16b8e9a26e7970096sergeyu@chromium.org uint32_t blue_shift = MaskToShift(blue_mask); 3019f282403f258162ca53eb2f16b8e9a26e7970096sergeyu@chromium.org 3029f282403f258162ca53eb2f16b8e9a26e7970096sergeyu@chromium.org int bits_per_pixel = x_image_->bits_per_pixel; 3039f282403f258162ca53eb2f16b8e9a26e7970096sergeyu@chromium.org 3049f282403f258162ca53eb2f16b8e9a26e7970096sergeyu@chromium.org uint8_t* dst_pos = frame->data() + frame->stride() * dst_y; 3059f282403f258162ca53eb2f16b8e9a26e7970096sergeyu@chromium.org uint8_t* src_pos = image; 3069f282403f258162ca53eb2f16b8e9a26e7970096sergeyu@chromium.org dst_pos += dst_x * DesktopFrame::kBytesPerPixel; 3079f282403f258162ca53eb2f16b8e9a26e7970096sergeyu@chromium.org // TODO(hclam): Optimize, perhaps using MMX code or by converting to 3089f282403f258162ca53eb2f16b8e9a26e7970096sergeyu@chromium.org // YUV directly. 3099f282403f258162ca53eb2f16b8e9a26e7970096sergeyu@chromium.org // TODO(sergeyu): This code doesn't handle XImage byte order properly and 3109f282403f258162ca53eb2f16b8e9a26e7970096sergeyu@chromium.org // won't work with 24bpp images. Fix it. 3119f282403f258162ca53eb2f16b8e9a26e7970096sergeyu@chromium.org for (int y = 0; y < height; y++) { 3129f282403f258162ca53eb2f16b8e9a26e7970096sergeyu@chromium.org uint32_t* dst_pos_32 = reinterpret_cast<uint32_t*>(dst_pos); 3139f282403f258162ca53eb2f16b8e9a26e7970096sergeyu@chromium.org uint32_t* src_pos_32 = reinterpret_cast<uint32_t*>(src_pos); 3149f282403f258162ca53eb2f16b8e9a26e7970096sergeyu@chromium.org uint16_t* src_pos_16 = reinterpret_cast<uint16_t*>(src_pos); 3159f282403f258162ca53eb2f16b8e9a26e7970096sergeyu@chromium.org for (int x = 0; x < width; x++) { 3169f282403f258162ca53eb2f16b8e9a26e7970096sergeyu@chromium.org // Dereference through an appropriately-aligned pointer. 3179f282403f258162ca53eb2f16b8e9a26e7970096sergeyu@chromium.org uint32_t pixel; 3189f282403f258162ca53eb2f16b8e9a26e7970096sergeyu@chromium.org if (bits_per_pixel == 32) { 3199f282403f258162ca53eb2f16b8e9a26e7970096sergeyu@chromium.org pixel = src_pos_32[x]; 3209f282403f258162ca53eb2f16b8e9a26e7970096sergeyu@chromium.org } else if (bits_per_pixel == 16) { 3219f282403f258162ca53eb2f16b8e9a26e7970096sergeyu@chromium.org pixel = src_pos_16[x]; 3229f282403f258162ca53eb2f16b8e9a26e7970096sergeyu@chromium.org } else { 3239f282403f258162ca53eb2f16b8e9a26e7970096sergeyu@chromium.org pixel = src_pos[x]; 3249f282403f258162ca53eb2f16b8e9a26e7970096sergeyu@chromium.org } 3259f282403f258162ca53eb2f16b8e9a26e7970096sergeyu@chromium.org uint32_t r = (pixel & red_mask) << red_shift; 3269f282403f258162ca53eb2f16b8e9a26e7970096sergeyu@chromium.org uint32_t g = (pixel & green_mask) << green_shift; 3279f282403f258162ca53eb2f16b8e9a26e7970096sergeyu@chromium.org uint32_t b = (pixel & blue_mask) << blue_shift; 3289f282403f258162ca53eb2f16b8e9a26e7970096sergeyu@chromium.org // Write as 32-bit RGB. 3299f282403f258162ca53eb2f16b8e9a26e7970096sergeyu@chromium.org dst_pos_32[x] = ((r >> 8) & 0xff0000) | ((g >> 16) & 0xff00) | 3309f282403f258162ca53eb2f16b8e9a26e7970096sergeyu@chromium.org ((b >> 24) & 0xff); 3319f282403f258162ca53eb2f16b8e9a26e7970096sergeyu@chromium.org } 3329f282403f258162ca53eb2f16b8e9a26e7970096sergeyu@chromium.org dst_pos += frame->stride(); 3339f282403f258162ca53eb2f16b8e9a26e7970096sergeyu@chromium.org src_pos += src_stride; 3349f282403f258162ca53eb2f16b8e9a26e7970096sergeyu@chromium.org } 3353d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org} 3363d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org 3373d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org} // namespace webrtc 338