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/screen_capturer.h" 123d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org 133d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org#include <string.h> 143d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org#include <set> 153d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org 163d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org#include <X11/extensions/Xdamage.h> 173d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org#include <X11/extensions/Xfixes.h> 183d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org#include <X11/Xlib.h> 193d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org#include <X11/Xutil.h> 203d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org 214f847da5a004ae18a5527232d8e982fe0d4cb77dpbos#include "webrtc/base/checks.h" 2200b8f6b3643332cce1ee711715f7fbb824d793cakwiberg@webrtc.org#include "webrtc/base/scoped_ptr.h" 23894e6fe9ea16a63537ec6d453c81566d02f66059sergeyu@chromium.org#include "webrtc/modules/desktop_capture/desktop_capture_options.h" 243d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org#include "webrtc/modules/desktop_capture/desktop_frame.h" 253d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org#include "webrtc/modules/desktop_capture/differ.h" 263d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org#include "webrtc/modules/desktop_capture/screen_capture_frame_queue.h" 273d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org#include "webrtc/modules/desktop_capture/screen_capturer_helper.h" 283d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org#include "webrtc/modules/desktop_capture/x11/x_server_pixel_buffer.h" 2998f53510b222f71fdd8b799b2f33737ceeb28c61Henrik Kjellander#include "webrtc/system_wrappers/include/logging.h" 3098f53510b222f71fdd8b799b2f33737ceeb28c61Henrik Kjellander#include "webrtc/system_wrappers/include/tick_util.h" 313d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org 323d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.orgnamespace webrtc { 333d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.orgnamespace { 343d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org 353d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org// A class to perform video frame capturing for Linux. 367419a723832e7b74d1fbbd21d95f86a65c0e1da7sergeyu@chromium.orgclass ScreenCapturerLinux : public ScreenCapturer, 377419a723832e7b74d1fbbd21d95f86a65c0e1da7sergeyu@chromium.org public SharedXDisplay::XEventHandler { 383d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org public: 393d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org ScreenCapturerLinux(); 403d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org virtual ~ScreenCapturerLinux(); 413d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org 423d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org // TODO(ajwong): Do we really want this to be synchronous? 43894e6fe9ea16a63537ec6d453c81566d02f66059sergeyu@chromium.org bool Init(const DesktopCaptureOptions& options); 443d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org 453d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org // DesktopCapturer interface. 4614665ff7d4024d07e58622f498b23fd980001871kjellander@webrtc.org void Start(Callback* delegate) override; 4714665ff7d4024d07e58622f498b23fd980001871kjellander@webrtc.org void Capture(const DesktopRegion& region) override; 483d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org 493d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org // ScreenCapturer interface. 5014665ff7d4024d07e58622f498b23fd980001871kjellander@webrtc.org bool GetScreenList(ScreenList* screens) override; 5114665ff7d4024d07e58622f498b23fd980001871kjellander@webrtc.org bool SelectScreen(ScreenId id) override; 523d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org 533d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org private: 54894e6fe9ea16a63537ec6d453c81566d02f66059sergeyu@chromium.org Display* display() { return options_.x_display()->display(); } 55894e6fe9ea16a63537ec6d453c81566d02f66059sergeyu@chromium.org 567419a723832e7b74d1fbbd21d95f86a65c0e1da7sergeyu@chromium.org // SharedXDisplay::XEventHandler interface. 5714665ff7d4024d07e58622f498b23fd980001871kjellander@webrtc.org bool HandleXEvent(const XEvent& event) override; 583d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org 597419a723832e7b74d1fbbd21d95f86a65c0e1da7sergeyu@chromium.org void InitXDamage(); 603d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org 613d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org // Capture screen pixels to the current buffer in the queue. In the DAMAGE 623d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org // case, the ScreenCapturerHelper already holds the list of invalid rectangles 637419a723832e7b74d1fbbd21d95f86a65c0e1da7sergeyu@chromium.org // from HandleXEvent(). In the non-DAMAGE case, this captures the 643d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org // whole screen, then calculates some invalid rectangles that include any 653d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org // differences between this and the previous capture. 663d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org DesktopFrame* CaptureScreen(); 673d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org 689f282403f258162ca53eb2f16b8e9a26e7970096sergeyu@chromium.org // Called when the screen configuration is changed. 699f282403f258162ca53eb2f16b8e9a26e7970096sergeyu@chromium.org void ScreenConfigurationChanged(); 703d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org 713d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org // Synchronize the current buffer with |last_buffer_|, by copying pixels from 723d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org // the area of |last_invalid_rects|. 733d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org // Note this only works on the assumption that kNumBuffers == 2, as 743d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org // |last_invalid_rects| holds the differences from the previous buffer and 753d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org // the one prior to that (which will then be the current buffer). 763d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org void SynchronizeFrame(); 773d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org 783d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org void DeinitXlib(); 793d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org 80894e6fe9ea16a63537ec6d453c81566d02f66059sergeyu@chromium.org DesktopCaptureOptions options_; 81894e6fe9ea16a63537ec6d453c81566d02f66059sergeyu@chromium.org 823d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org Callback* callback_; 833d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org 843d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org // X11 graphics context. 853d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org GC gc_; 863d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org Window root_window_; 873d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org 883d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org // XFixes. 893d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org bool has_xfixes_; 903d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org int xfixes_event_base_; 913d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org int xfixes_error_base_; 923d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org 933d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org // XDamage information. 943d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org bool use_damage_; 953d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org Damage damage_handle_; 963d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org int damage_event_base_; 973d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org int damage_error_base_; 983d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org XserverRegion damage_region_; 993d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org 1003d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org // Access to the X Server's pixel buffer. 1013d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org XServerPixelBuffer x_server_pixel_buffer_; 1023d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org 1033d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org // A thread-safe list of invalid rectangles, and the size of the most 1043d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org // recently captured screen. 1053d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org ScreenCapturerHelper helper_; 1063d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org 1073d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org // Queue of the frames buffers. 1083d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org ScreenCaptureFrameQueue queue_; 1093d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org 1103d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org // Invalid region from the previous capture. This is used to synchronize the 1113d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org // current with the last buffer used. 1123d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org DesktopRegion last_invalid_region_; 1133d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org 1143d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org // |Differ| for use when polling for changes. 11500b8f6b3643332cce1ee711715f7fbb824d793cakwiberg@webrtc.org rtc::scoped_ptr<Differ> differ_; 1163d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org 1173c089d751ede283e21e186885eaf705c3257ccd2henrikg RTC_DISALLOW_COPY_AND_ASSIGN(ScreenCapturerLinux); 1183d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org}; 1193d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org 1203d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.orgScreenCapturerLinux::ScreenCapturerLinux() 1213d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org : callback_(NULL), 1223d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org gc_(NULL), 1233d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org root_window_(BadValue), 1243d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org has_xfixes_(false), 1253d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org xfixes_event_base_(-1), 1263d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org xfixes_error_base_(-1), 1273d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org use_damage_(false), 1283d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org damage_handle_(0), 1293d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org damage_event_base_(-1), 1303d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org damage_error_base_(-1), 1313d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org damage_region_(0) { 1323d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org helper_.SetLogGridSize(4); 1333d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org} 1343d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org 1353d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.orgScreenCapturerLinux::~ScreenCapturerLinux() { 1367419a723832e7b74d1fbbd21d95f86a65c0e1da7sergeyu@chromium.org options_.x_display()->RemoveEventHandler(ConfigureNotify, this); 1377419a723832e7b74d1fbbd21d95f86a65c0e1da7sergeyu@chromium.org if (use_damage_) { 1387419a723832e7b74d1fbbd21d95f86a65c0e1da7sergeyu@chromium.org options_.x_display()->RemoveEventHandler( 1397419a723832e7b74d1fbbd21d95f86a65c0e1da7sergeyu@chromium.org damage_event_base_ + XDamageNotify, this); 1407419a723832e7b74d1fbbd21d95f86a65c0e1da7sergeyu@chromium.org } 1413d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org DeinitXlib(); 1423d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org} 1433d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org 144894e6fe9ea16a63537ec6d453c81566d02f66059sergeyu@chromium.orgbool ScreenCapturerLinux::Init(const DesktopCaptureOptions& options) { 145894e6fe9ea16a63537ec6d453c81566d02f66059sergeyu@chromium.org options_ = options; 1463d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org 147894e6fe9ea16a63537ec6d453c81566d02f66059sergeyu@chromium.org root_window_ = RootWindow(display(), DefaultScreen(display())); 1483d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org if (root_window_ == BadValue) { 1493d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org LOG(LS_ERROR) << "Unable to get the root window"; 1503d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org DeinitXlib(); 1513d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org return false; 1523d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org } 1533d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org 154894e6fe9ea16a63537ec6d453c81566d02f66059sergeyu@chromium.org gc_ = XCreateGC(display(), root_window_, 0, NULL); 1553d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org if (gc_ == NULL) { 1563d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org LOG(LS_ERROR) << "Unable to get graphics context"; 1573d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org DeinitXlib(); 1583d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org return false; 1593d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org } 1603d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org 1617419a723832e7b74d1fbbd21d95f86a65c0e1da7sergeyu@chromium.org options_.x_display()->AddEventHandler(ConfigureNotify, this); 1627419a723832e7b74d1fbbd21d95f86a65c0e1da7sergeyu@chromium.org 1633d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org // Check for XFixes extension. This is required for cursor shape 1643d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org // notifications, and for our use of XDamage. 165894e6fe9ea16a63537ec6d453c81566d02f66059sergeyu@chromium.org if (XFixesQueryExtension(display(), &xfixes_event_base_, 1663d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org &xfixes_error_base_)) { 1673d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org has_xfixes_ = true; 1683d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org } else { 1693d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org LOG(LS_INFO) << "X server does not support XFixes."; 1703d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org } 1713d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org 1723d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org // Register for changes to the dimensions of the root window. 173894e6fe9ea16a63537ec6d453c81566d02f66059sergeyu@chromium.org XSelectInput(display(), root_window_, StructureNotifyMask); 1743d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org 175894e6fe9ea16a63537ec6d453c81566d02f66059sergeyu@chromium.org if (!x_server_pixel_buffer_.Init(display(), DefaultRootWindow(display()))) { 1769f282403f258162ca53eb2f16b8e9a26e7970096sergeyu@chromium.org LOG(LS_ERROR) << "Failed to initialize pixel buffer."; 1779f282403f258162ca53eb2f16b8e9a26e7970096sergeyu@chromium.org return false; 1789f282403f258162ca53eb2f16b8e9a26e7970096sergeyu@chromium.org } 1793d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org 180894e6fe9ea16a63537ec6d453c81566d02f66059sergeyu@chromium.org if (options_.use_update_notifications()) { 1813d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org InitXDamage(); 1823d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org } 1833d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org 1843d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org return true; 1853d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org} 1863d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org 1873d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.orgvoid ScreenCapturerLinux::InitXDamage() { 1883d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org // Our use of XDamage requires XFixes. 1893d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org if (!has_xfixes_) { 1903d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org return; 1913d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org } 1923d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org 1933d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org // Check for XDamage extension. 194894e6fe9ea16a63537ec6d453c81566d02f66059sergeyu@chromium.org if (!XDamageQueryExtension(display(), &damage_event_base_, 1953d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org &damage_error_base_)) { 1963d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org LOG(LS_INFO) << "X server does not support XDamage."; 1973d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org return; 1983d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org } 1993d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org 2003d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org // TODO(lambroslambrou): Disable DAMAGE in situations where it is known 2013d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org // to fail, such as when Desktop Effects are enabled, with graphics 2023d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org // drivers (nVidia, ATI) that fail to report DAMAGE notifications 2033d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org // properly. 2043d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org 2053d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org // Request notifications every time the screen becomes damaged. 206894e6fe9ea16a63537ec6d453c81566d02f66059sergeyu@chromium.org damage_handle_ = XDamageCreate(display(), root_window_, 2073d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org XDamageReportNonEmpty); 2083d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org if (!damage_handle_) { 2093d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org LOG(LS_ERROR) << "Unable to initialize XDamage."; 2103d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org return; 2113d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org } 2123d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org 2133d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org // Create an XFixes server-side region to collate damage into. 214894e6fe9ea16a63537ec6d453c81566d02f66059sergeyu@chromium.org damage_region_ = XFixesCreateRegion(display(), 0, 0); 2153d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org if (!damage_region_) { 216894e6fe9ea16a63537ec6d453c81566d02f66059sergeyu@chromium.org XDamageDestroy(display(), damage_handle_); 2173d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org LOG(LS_ERROR) << "Unable to create XFixes region."; 2183d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org return; 2193d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org } 2203d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org 2217419a723832e7b74d1fbbd21d95f86a65c0e1da7sergeyu@chromium.org options_.x_display()->AddEventHandler( 2227419a723832e7b74d1fbbd21d95f86a65c0e1da7sergeyu@chromium.org damage_event_base_ + XDamageNotify, this); 2237419a723832e7b74d1fbbd21d95f86a65c0e1da7sergeyu@chromium.org 2243d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org use_damage_ = true; 2253d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org LOG(LS_INFO) << "Using XDamage extension."; 2263d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org} 2273d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org 2283d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.orgvoid ScreenCapturerLinux::Start(Callback* callback) { 22991d6edef35e7275879c30ce16ecb8b6dc73c6e4ahenrikg RTC_DCHECK(!callback_); 23091d6edef35e7275879c30ce16ecb8b6dc73c6e4ahenrikg RTC_DCHECK(callback); 2313d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org 2323d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org callback_ = callback; 2333d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org} 2343d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org 2353d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.orgvoid ScreenCapturerLinux::Capture(const DesktopRegion& region) { 2363d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org TickTime capture_start_time = TickTime::Now(); 2373d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org 2383d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org queue_.MoveToNextFrame(); 2393d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org 2403d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org // Process XEvents for XDamage and cursor shape tracking. 2417419a723832e7b74d1fbbd21d95f86a65c0e1da7sergeyu@chromium.org options_.x_display()->ProcessPendingXEvents(); 2423d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org 2439f282403f258162ca53eb2f16b8e9a26e7970096sergeyu@chromium.org // ProcessPendingXEvents() may call ScreenConfigurationChanged() which 2449f282403f258162ca53eb2f16b8e9a26e7970096sergeyu@chromium.org // reinitializes |x_server_pixel_buffer_|. Check if the pixel buffer is still 2459f282403f258162ca53eb2f16b8e9a26e7970096sergeyu@chromium.org // in a good shape. 2469f282403f258162ca53eb2f16b8e9a26e7970096sergeyu@chromium.org if (!x_server_pixel_buffer_.is_initialized()) { 2479f282403f258162ca53eb2f16b8e9a26e7970096sergeyu@chromium.org // We failed to initialize pixel buffer. 2489f282403f258162ca53eb2f16b8e9a26e7970096sergeyu@chromium.org callback_->OnCaptureCompleted(NULL); 2499f282403f258162ca53eb2f16b8e9a26e7970096sergeyu@chromium.org return; 2509f282403f258162ca53eb2f16b8e9a26e7970096sergeyu@chromium.org } 2519f282403f258162ca53eb2f16b8e9a26e7970096sergeyu@chromium.org 2523d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org // If the current frame is from an older generation then allocate a new one. 2533d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org // Note that we can't reallocate other buffers at this point, since the caller 2543d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org // may still be reading from them. 2553d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org if (!queue_.current_frame()) { 25600b8f6b3643332cce1ee711715f7fbb824d793cakwiberg@webrtc.org rtc::scoped_ptr<DesktopFrame> frame( 2579f282403f258162ca53eb2f16b8e9a26e7970096sergeyu@chromium.org new BasicDesktopFrame(x_server_pixel_buffer_.window_size())); 2583d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org queue_.ReplaceCurrentFrame(frame.release()); 2593d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org } 2603d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org 2613d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org // Refresh the Differ helper used by CaptureFrame(), if needed. 2623d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org DesktopFrame* frame = queue_.current_frame(); 2633d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org if (!use_damage_ && ( 2643d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org !differ_.get() || 2653d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org (differ_->width() != frame->size().width()) || 2663d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org (differ_->height() != frame->size().height()) || 2673d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org (differ_->bytes_per_row() != frame->stride()))) { 2683d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org differ_.reset(new Differ(frame->size().width(), frame->size().height(), 2693d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org DesktopFrame::kBytesPerPixel, 2703d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org frame->stride())); 2713d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org } 2723d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org 2733d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org DesktopFrame* result = CaptureScreen(); 2743d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org last_invalid_region_ = result->updated_region(); 2753d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org result->set_capture_time_ms( 2763d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org (TickTime::Now() - capture_start_time).Milliseconds()); 2773d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org callback_->OnCaptureCompleted(result); 2783d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org} 2793d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org 280017b6190106cb8309b70ef9d04e0655f6ed9e656jiayl@webrtc.orgbool ScreenCapturerLinux::GetScreenList(ScreenList* screens) { 28191d6edef35e7275879c30ce16ecb8b6dc73c6e4ahenrikg RTC_DCHECK(screens->size() == 0); 282017b6190106cb8309b70ef9d04e0655f6ed9e656jiayl@webrtc.org // TODO(jiayl): implement screen enumeration. 283017b6190106cb8309b70ef9d04e0655f6ed9e656jiayl@webrtc.org Screen default_screen; 284017b6190106cb8309b70ef9d04e0655f6ed9e656jiayl@webrtc.org default_screen.id = 0; 285017b6190106cb8309b70ef9d04e0655f6ed9e656jiayl@webrtc.org screens->push_back(default_screen); 286017b6190106cb8309b70ef9d04e0655f6ed9e656jiayl@webrtc.org return true; 287017b6190106cb8309b70ef9d04e0655f6ed9e656jiayl@webrtc.org} 288017b6190106cb8309b70ef9d04e0655f6ed9e656jiayl@webrtc.org 289017b6190106cb8309b70ef9d04e0655f6ed9e656jiayl@webrtc.orgbool ScreenCapturerLinux::SelectScreen(ScreenId id) { 290017b6190106cb8309b70ef9d04e0655f6ed9e656jiayl@webrtc.org // TODO(jiayl): implement screen selection. 291017b6190106cb8309b70ef9d04e0655f6ed9e656jiayl@webrtc.org return true; 292017b6190106cb8309b70ef9d04e0655f6ed9e656jiayl@webrtc.org} 293017b6190106cb8309b70ef9d04e0655f6ed9e656jiayl@webrtc.org 2947419a723832e7b74d1fbbd21d95f86a65c0e1da7sergeyu@chromium.orgbool ScreenCapturerLinux::HandleXEvent(const XEvent& event) { 2957419a723832e7b74d1fbbd21d95f86a65c0e1da7sergeyu@chromium.org if (use_damage_ && (event.type == damage_event_base_ + XDamageNotify)) { 2967419a723832e7b74d1fbbd21d95f86a65c0e1da7sergeyu@chromium.org const XDamageNotifyEvent* damage_event = 2977419a723832e7b74d1fbbd21d95f86a65c0e1da7sergeyu@chromium.org reinterpret_cast<const XDamageNotifyEvent*>(&event); 2987419a723832e7b74d1fbbd21d95f86a65c0e1da7sergeyu@chromium.org if (damage_event->damage != damage_handle_) 2997419a723832e7b74d1fbbd21d95f86a65c0e1da7sergeyu@chromium.org return false; 30091d6edef35e7275879c30ce16ecb8b6dc73c6e4ahenrikg RTC_DCHECK(damage_event->level == XDamageReportNonEmpty); 3017419a723832e7b74d1fbbd21d95f86a65c0e1da7sergeyu@chromium.org return true; 3027419a723832e7b74d1fbbd21d95f86a65c0e1da7sergeyu@chromium.org } else if (event.type == ConfigureNotify) { 3037419a723832e7b74d1fbbd21d95f86a65c0e1da7sergeyu@chromium.org ScreenConfigurationChanged(); 3047419a723832e7b74d1fbbd21d95f86a65c0e1da7sergeyu@chromium.org return true; 3053d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org } 3067419a723832e7b74d1fbbd21d95f86a65c0e1da7sergeyu@chromium.org return false; 3073d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org} 3083d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org 3093d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.orgDesktopFrame* ScreenCapturerLinux::CaptureScreen() { 3103d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org DesktopFrame* frame = queue_.current_frame()->Share(); 3119f282403f258162ca53eb2f16b8e9a26e7970096sergeyu@chromium.org assert(x_server_pixel_buffer_.window_size().equals(frame->size())); 3123d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org 3133d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org // Pass the screen size to the helper, so it can clip the invalid region if it 3143d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org // expands that region to a grid. 3153d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org helper_.set_size_most_recent(frame->size()); 3163d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org 3173d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org // In the DAMAGE case, ensure the frame is up-to-date with the previous frame 3183d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org // if any. If there isn't a previous frame, that means a screen-resolution 3193d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org // change occurred, and |invalid_rects| will be updated to include the whole 3203d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org // screen. 3213d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org if (use_damage_ && queue_.previous_frame()) 3223d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org SynchronizeFrame(); 3233d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org 3243d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org DesktopRegion* updated_region = frame->mutable_updated_region(); 3253d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org 3263d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org x_server_pixel_buffer_.Synchronize(); 3273d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org if (use_damage_ && queue_.previous_frame()) { 3283d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org // Atomically fetch and clear the damage region. 329894e6fe9ea16a63537ec6d453c81566d02f66059sergeyu@chromium.org XDamageSubtract(display(), damage_handle_, None, damage_region_); 3303d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org int rects_num = 0; 3313d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org XRectangle bounds; 332894e6fe9ea16a63537ec6d453c81566d02f66059sergeyu@chromium.org XRectangle* rects = XFixesFetchRegionAndBounds(display(), damage_region_, 3333d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org &rects_num, &bounds); 3343d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org for (int i = 0; i < rects_num; ++i) { 3353d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org updated_region->AddRect(DesktopRect::MakeXYWH( 3363d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org rects[i].x, rects[i].y, rects[i].width, rects[i].height)); 3373d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org } 3383d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org XFree(rects); 3393d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org helper_.InvalidateRegion(*updated_region); 3403d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org 3413d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org // Capture the damaged portions of the desktop. 3423d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org helper_.TakeInvalidRegion(updated_region); 3433d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org 3443d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org // Clip the damaged portions to the current screen size, just in case some 3453d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org // spurious XDamage notifications were received for a previous (larger) 3463d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org // screen size. 3473d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org updated_region->IntersectWith( 3489f282403f258162ca53eb2f16b8e9a26e7970096sergeyu@chromium.org DesktopRect::MakeSize(x_server_pixel_buffer_.window_size())); 3493d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org 3503d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org for (DesktopRegion::Iterator it(*updated_region); 3513d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org !it.IsAtEnd(); it.Advance()) { 3529f282403f258162ca53eb2f16b8e9a26e7970096sergeyu@chromium.org x_server_pixel_buffer_.CaptureRect(it.rect(), frame); 3533d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org } 3543d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org } else { 3553d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org // Doing full-screen polling, or this is the first capture after a 3563d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org // screen-resolution change. In either case, need a full-screen capture. 3579f282403f258162ca53eb2f16b8e9a26e7970096sergeyu@chromium.org DesktopRect screen_rect = DesktopRect::MakeSize(frame->size()); 3589f282403f258162ca53eb2f16b8e9a26e7970096sergeyu@chromium.org x_server_pixel_buffer_.CaptureRect(screen_rect, frame); 3593d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org 3603d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org if (queue_.previous_frame()) { 3613d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org // Full-screen polling, so calculate the invalid rects here, based on the 3623d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org // changed pixels between current and previous buffers. 36391d6edef35e7275879c30ce16ecb8b6dc73c6e4ahenrikg RTC_DCHECK(differ_.get() != NULL); 36491d6edef35e7275879c30ce16ecb8b6dc73c6e4ahenrikg RTC_DCHECK(queue_.previous_frame()->data()); 3653d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org differ_->CalcDirtyRegion(queue_.previous_frame()->data(), 3663d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org frame->data(), updated_region); 3673d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org } else { 3683d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org // No previous buffer, so always invalidate the whole screen, whether 3693d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org // or not DAMAGE is being used. DAMAGE doesn't necessarily send a 3703d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org // full-screen notification after a screen-resolution change, so 3713d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org // this is done here. 3723d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org updated_region->SetRect(screen_rect); 3733d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org } 3743d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org } 3753d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org 3763d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org return frame; 3773d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org} 3783d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org 3799f282403f258162ca53eb2f16b8e9a26e7970096sergeyu@chromium.orgvoid ScreenCapturerLinux::ScreenConfigurationChanged() { 3803d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org // Make sure the frame buffers will be reallocated. 3813d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org queue_.Reset(); 3823d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org 3833d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org helper_.ClearInvalidRegion(); 384894e6fe9ea16a63537ec6d453c81566d02f66059sergeyu@chromium.org if (!x_server_pixel_buffer_.Init(display(), DefaultRootWindow(display()))) { 3859f282403f258162ca53eb2f16b8e9a26e7970096sergeyu@chromium.org LOG(LS_ERROR) << "Failed to initialize pixel buffer after screen " 3869f282403f258162ca53eb2f16b8e9a26e7970096sergeyu@chromium.org "configuration change."; 3879f282403f258162ca53eb2f16b8e9a26e7970096sergeyu@chromium.org } 3883d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org} 3893d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org 3903d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.orgvoid ScreenCapturerLinux::SynchronizeFrame() { 3913d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org // Synchronize the current buffer with the previous one since we do not 3923d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org // capture the entire desktop. Note that encoder may be reading from the 3933d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org // previous buffer at this time so thread access complaints are false 3943d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org // positives. 3953d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org 3963d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org // TODO(hclam): We can reduce the amount of copying here by subtracting 3973d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org // |capturer_helper_|s region from |last_invalid_region_|. 3983d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org // http://crbug.com/92354 39991d6edef35e7275879c30ce16ecb8b6dc73c6e4ahenrikg RTC_DCHECK(queue_.previous_frame()); 4003d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org 4013d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org DesktopFrame* current = queue_.current_frame(); 4023d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org DesktopFrame* last = queue_.previous_frame(); 40391d6edef35e7275879c30ce16ecb8b6dc73c6e4ahenrikg RTC_DCHECK(current != last); 4043d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org for (DesktopRegion::Iterator it(last_invalid_region_); 4053d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org !it.IsAtEnd(); it.Advance()) { 4065d85819dd21842cc3e6d74676a292cf9d9142f4esergeyu@chromium.org current->CopyPixelsFrom(*last, it.rect().top_left(), it.rect()); 4073d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org } 4083d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org} 4093d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org 4103d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.orgvoid ScreenCapturerLinux::DeinitXlib() { 4113d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org if (gc_) { 412894e6fe9ea16a63537ec6d453c81566d02f66059sergeyu@chromium.org XFreeGC(display(), gc_); 4133d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org gc_ = NULL; 4143d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org } 4153d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org 4163d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org x_server_pixel_buffer_.Release(); 4173d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org 418894e6fe9ea16a63537ec6d453c81566d02f66059sergeyu@chromium.org if (display()) { 419894e6fe9ea16a63537ec6d453c81566d02f66059sergeyu@chromium.org if (damage_handle_) { 420894e6fe9ea16a63537ec6d453c81566d02f66059sergeyu@chromium.org XDamageDestroy(display(), damage_handle_); 421894e6fe9ea16a63537ec6d453c81566d02f66059sergeyu@chromium.org damage_handle_ = 0; 422894e6fe9ea16a63537ec6d453c81566d02f66059sergeyu@chromium.org } 423894e6fe9ea16a63537ec6d453c81566d02f66059sergeyu@chromium.org 424894e6fe9ea16a63537ec6d453c81566d02f66059sergeyu@chromium.org if (damage_region_) { 425894e6fe9ea16a63537ec6d453c81566d02f66059sergeyu@chromium.org XFixesDestroyRegion(display(), damage_region_); 426894e6fe9ea16a63537ec6d453c81566d02f66059sergeyu@chromium.org damage_region_ = 0; 427894e6fe9ea16a63537ec6d453c81566d02f66059sergeyu@chromium.org } 4283d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org } 4293d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org} 4303d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org 4313d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org} // namespace 4323d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org 4333d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org// static 434894e6fe9ea16a63537ec6d453c81566d02f66059sergeyu@chromium.orgScreenCapturer* ScreenCapturer::Create(const DesktopCaptureOptions& options) { 435894e6fe9ea16a63537ec6d453c81566d02f66059sergeyu@chromium.org if (!options.x_display()) 436894e6fe9ea16a63537ec6d453c81566d02f66059sergeyu@chromium.org return NULL; 4373d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org 43800b8f6b3643332cce1ee711715f7fbb824d793cakwiberg@webrtc.org rtc::scoped_ptr<ScreenCapturerLinux> capturer(new ScreenCapturerLinux()); 439894e6fe9ea16a63537ec6d453c81566d02f66059sergeyu@chromium.org if (!capturer->Init(options)) 4403d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org capturer.reset(); 4413d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org return capturer.release(); 4423d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org} 4433d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org 4443d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org} // namespace webrtc 445