16b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org/*
26b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org *  Copyright (c) 2014 The WebRTC project authors. All Rights Reserved.
36b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org *
46b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org *  Use of this source code is governed by a BSD-style license
56b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org *  that can be found in the LICENSE file in the root of the source
66b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org *  tree. An additional intellectual property rights grant can be found
76b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org *  in the file PATENTS.  All contributing project authors may
86b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org *  be found in the AUTHORS file in the root of the source tree.
96b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org */
106b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org
116b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org#include "webrtc/modules/desktop_capture/win/screen_capturer_win_gdi.h"
126b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org
13e38123c801909a3e357f317a6811748aaf81c0ebhenrike@webrtc.org#include <assert.h>
14e38123c801909a3e357f317a6811748aaf81c0ebhenrike@webrtc.org
156b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org#include "webrtc/modules/desktop_capture/desktop_capture_options.h"
166b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org#include "webrtc/modules/desktop_capture/desktop_frame.h"
176b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org#include "webrtc/modules/desktop_capture/desktop_frame_win.h"
186b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org#include "webrtc/modules/desktop_capture/desktop_region.h"
196b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org#include "webrtc/modules/desktop_capture/differ.h"
206b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org#include "webrtc/modules/desktop_capture/mouse_cursor.h"
216b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org#include "webrtc/modules/desktop_capture/win/cursor.h"
226b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org#include "webrtc/modules/desktop_capture/win/desktop.h"
236b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org#include "webrtc/modules/desktop_capture/win/screen_capture_utils.h"
246b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org#include "webrtc/system_wrappers/interface/logging.h"
256b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org#include "webrtc/system_wrappers/interface/tick_util.h"
266b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org
276b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.orgnamespace webrtc {
286b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org
296b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.orgnamespace {
306b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org
316b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org// Constants from dwmapi.h.
326b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.orgconst UINT DWM_EC_DISABLECOMPOSITION = 0;
336b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.orgconst UINT DWM_EC_ENABLECOMPOSITION = 1;
346b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org
356b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.orgconst wchar_t kDwmapiLibraryName[] = L"dwmapi.dll";
366b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org
376b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org}  // namespace
386b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org
396b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.orgScreenCapturerWinGdi::ScreenCapturerWinGdi(const DesktopCaptureOptions& options)
406b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org    : callback_(NULL),
416b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org      mouse_shape_observer_(NULL),
426b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org      current_screen_id_(kFullDesktopScreenId),
436b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org      desktop_dc_(NULL),
446b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org      memory_dc_(NULL),
456b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org      dwmapi_library_(NULL),
466b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org      composition_func_(NULL),
476b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org      set_thread_execution_state_failed_(false) {
486b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org  if (options.disable_effects()) {
496b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org    // Load dwmapi.dll dynamically since it is not available on XP.
506b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org    if (!dwmapi_library_)
516b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org      dwmapi_library_ = LoadLibrary(kDwmapiLibraryName);
526b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org
536b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org    if (dwmapi_library_) {
546b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org      composition_func_ = reinterpret_cast<DwmEnableCompositionFunc>(
556b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org          GetProcAddress(dwmapi_library_, "DwmEnableComposition"));
566b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org    }
576b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org  }
586b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org}
596b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org
606b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.orgScreenCapturerWinGdi::~ScreenCapturerWinGdi() {
616b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org  if (desktop_dc_)
626b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org    ReleaseDC(NULL, desktop_dc_);
636b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org  if (memory_dc_)
646b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org    DeleteDC(memory_dc_);
656b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org
666b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org  // Restore Aero.
676b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org  if (composition_func_)
686b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org    (*composition_func_)(DWM_EC_ENABLECOMPOSITION);
696b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org
706b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org  if (dwmapi_library_)
716b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org    FreeLibrary(dwmapi_library_);
726b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org}
736b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org
746b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.orgvoid ScreenCapturerWinGdi::Capture(const DesktopRegion& region) {
756b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org  TickTime capture_start_time = TickTime::Now();
766b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org
776b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org  queue_.MoveToNextFrame();
786b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org
796b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org  // Request that the system not power-down the system, or the display hardware.
806b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org  if (!SetThreadExecutionState(ES_DISPLAY_REQUIRED | ES_SYSTEM_REQUIRED)) {
816b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org    if (!set_thread_execution_state_failed_) {
826b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org      set_thread_execution_state_failed_ = true;
836b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org      LOG_F(LS_WARNING) << "Failed to make system & display power assertion: "
846b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org                        << GetLastError();
856b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org    }
866b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org  }
876b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org
886b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org  // Make sure the GDI capture resources are up-to-date.
896b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org  PrepareCaptureResources();
906b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org
916b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org  if (!CaptureImage()) {
926b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org    callback_->OnCaptureCompleted(NULL);
936b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org    return;
946b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org  }
956b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org
966b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org  const DesktopFrame* current_frame = queue_.current_frame();
976b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org  const DesktopFrame* last_frame = queue_.previous_frame();
986b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org  if (last_frame && last_frame->size().equals(current_frame->size())) {
996b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org    // Make sure the differencer is set up correctly for these previous and
1006b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org    // current screens.
1016b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org    if (!differ_.get() ||
1026b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org        (differ_->width() != current_frame->size().width()) ||
1036b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org        (differ_->height() != current_frame->size().height()) ||
1046b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org        (differ_->bytes_per_row() != current_frame->stride())) {
1056b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org      differ_.reset(new Differ(current_frame->size().width(),
1066b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org                               current_frame->size().height(),
1076b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org                               DesktopFrame::kBytesPerPixel,
1086b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org                               current_frame->stride()));
1096b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org    }
1106b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org
1116b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org    // Calculate difference between the two last captured frames.
1126b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org    DesktopRegion region;
1136b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org    differ_->CalcDirtyRegion(last_frame->data(), current_frame->data(),
1146b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org                             &region);
1156b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org    helper_.InvalidateRegion(region);
1166b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org  } else {
1176b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org    // No previous frame is available, or the screen is resized. Invalidate the
1186b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org    // whole screen.
1196b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org    helper_.InvalidateScreen(current_frame->size());
1206b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org  }
1216b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org
1226b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org  helper_.set_size_most_recent(current_frame->size());
1236b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org
1246b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org  // Emit the current frame.
1256b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org  DesktopFrame* frame = queue_.current_frame()->Share();
1266b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org  frame->set_dpi(DesktopVector(
1276b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org      GetDeviceCaps(desktop_dc_, LOGPIXELSX),
1286b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org      GetDeviceCaps(desktop_dc_, LOGPIXELSY)));
1296b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org  frame->mutable_updated_region()->Clear();
1306b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org  helper_.TakeInvalidRegion(frame->mutable_updated_region());
1316b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org  frame->set_capture_time_ms(
1326b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org      (TickTime::Now() - capture_start_time).Milliseconds());
1336b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org  callback_->OnCaptureCompleted(frame);
1346b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org
1356b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org  // Check for cursor shape update.
136e5c55dac67a6e86d2cdb74563d8845847e5ecf18jiayl@webrtc.org  if (mouse_shape_observer_)
137e5c55dac67a6e86d2cdb74563d8845847e5ecf18jiayl@webrtc.org    CaptureCursor();
1386b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org}
1396b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org
1406b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.orgvoid ScreenCapturerWinGdi::SetMouseShapeObserver(
1416b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org    MouseShapeObserver* mouse_shape_observer) {
1426b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org  assert(!mouse_shape_observer_);
1436b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org  assert(mouse_shape_observer);
1446b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org
1456b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org  mouse_shape_observer_ = mouse_shape_observer;
1466b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org}
1476b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org
1486b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.orgbool ScreenCapturerWinGdi::GetScreenList(ScreenList* screens) {
1496b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org  return webrtc::GetScreenList(screens);
1506b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org}
1516b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org
1526b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.orgbool ScreenCapturerWinGdi::SelectScreen(ScreenId id) {
1536b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org  bool valid = IsScreenValid(id, &current_device_key_);
1546b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org  if (valid)
1556b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org    current_screen_id_ = id;
1566b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org  return valid;
1576b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org}
1586b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org
1596b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.orgvoid ScreenCapturerWinGdi::Start(Callback* callback) {
1606b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org  assert(!callback_);
1616b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org  assert(callback);
1626b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org
1636b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org  callback_ = callback;
1646b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org
1656b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org  // Vote to disable Aero composited desktop effects while capturing. Windows
1666b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org  // will restore Aero automatically if the process exits. This has no effect
1676b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org  // under Windows 8 or higher.  See crbug.com/124018.
1686b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org  if (composition_func_)
1696b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org    (*composition_func_)(DWM_EC_DISABLECOMPOSITION);
1706b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org}
1716b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org
1726b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.orgvoid ScreenCapturerWinGdi::PrepareCaptureResources() {
1736b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org  // Switch to the desktop receiving user input if different from the current
1746b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org  // one.
1756b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org  scoped_ptr<Desktop> input_desktop(Desktop::GetInputDesktop());
1766b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org  if (input_desktop.get() != NULL && !desktop_.IsSame(*input_desktop)) {
1776b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org    // Release GDI resources otherwise SetThreadDesktop will fail.
1786b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org    if (desktop_dc_) {
1796b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org      ReleaseDC(NULL, desktop_dc_);
1806b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org      desktop_dc_ = NULL;
1816b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org    }
1826b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org
1836b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org    if (memory_dc_) {
1846b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org      DeleteDC(memory_dc_);
1856b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org      memory_dc_ = NULL;
1866b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org    }
1876b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org
1886b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org    // If SetThreadDesktop() fails, the thread is still assigned a desktop.
1896b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org    // So we can continue capture screen bits, just from the wrong desktop.
1906b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org    desktop_.SetThreadDesktop(input_desktop.release());
1916b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org
1926b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org    // Re-assert our vote to disable Aero.
1936b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org    // See crbug.com/124018 and crbug.com/129906.
1946b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org    if (composition_func_ != NULL) {
1956b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org      (*composition_func_)(DWM_EC_DISABLECOMPOSITION);
1966b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org    }
1976b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org  }
1986b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org
1996b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org  // If the display bounds have changed then recreate GDI resources.
2006b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org  // TODO(wez): Also check for pixel format changes.
2016b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org  DesktopRect screen_rect(DesktopRect::MakeXYWH(
2026b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org      GetSystemMetrics(SM_XVIRTUALSCREEN),
2036b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org      GetSystemMetrics(SM_YVIRTUALSCREEN),
2046b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org      GetSystemMetrics(SM_CXVIRTUALSCREEN),
2056b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org      GetSystemMetrics(SM_CYVIRTUALSCREEN)));
2066b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org  if (!screen_rect.equals(desktop_dc_rect_)) {
2076b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org    if (desktop_dc_) {
2086b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org      ReleaseDC(NULL, desktop_dc_);
2096b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org      desktop_dc_ = NULL;
2106b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org    }
2116b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org    if (memory_dc_) {
2126b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org      DeleteDC(memory_dc_);
2136b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org      memory_dc_ = NULL;
2146b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org    }
2156b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org    desktop_dc_rect_ = DesktopRect();
2166b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org  }
2176b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org
2186b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org  if (desktop_dc_ == NULL) {
2196b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org    assert(memory_dc_ == NULL);
2206b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org
2216b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org    // Create GDI device contexts to capture from the desktop into memory.
2226b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org    desktop_dc_ = GetDC(NULL);
2236b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org    if (!desktop_dc_)
2246b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org      abort();
2256b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org    memory_dc_ = CreateCompatibleDC(desktop_dc_);
2266b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org    if (!memory_dc_)
2276b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org      abort();
2286b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org
2296b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org    desktop_dc_rect_ = screen_rect;
2306b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org
2316b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org    // Make sure the frame buffers will be reallocated.
2326b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org    queue_.Reset();
2336b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org
2346b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org    helper_.ClearInvalidRegion();
2356b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org  }
2366b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org}
2376b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org
2386b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.orgbool ScreenCapturerWinGdi::CaptureImage() {
2396b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org  DesktopRect screen_rect =
2406b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org      GetScreenRect(current_screen_id_, current_device_key_);
2416b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org  if (screen_rect.is_empty())
2426b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org    return false;
2436b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org
2446b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org  DesktopSize size = screen_rect.size();
2456b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org  // If the current buffer is from an older generation then allocate a new one.
2466b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org  // Note that we can't reallocate other buffers at this point, since the caller
2476b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org  // may still be reading from them.
2486b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org  if (!queue_.current_frame() ||
2496b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org      !queue_.current_frame()->size().equals(screen_rect.size())) {
2506b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org    assert(desktop_dc_ != NULL);
2516b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org    assert(memory_dc_ != NULL);
2526b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org
2536b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org    size_t buffer_size = size.width() * size.height() *
2546b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org        DesktopFrame::kBytesPerPixel;
2556b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org    SharedMemory* shared_memory = callback_->CreateSharedMemory(buffer_size);
2566b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org
2576b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org    scoped_ptr<DesktopFrame> buffer;
2586b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org    buffer.reset(
2596b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org        DesktopFrameWin::Create(size, shared_memory, desktop_dc_));
2606b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org    queue_.ReplaceCurrentFrame(buffer.release());
2616b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org  }
2626b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org
2636b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org  // Select the target bitmap into the memory dc and copy the rect from desktop
2646b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org  // to memory.
2656b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org  DesktopFrameWin* current = static_cast<DesktopFrameWin*>(
2666b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org      queue_.current_frame()->GetUnderlyingFrame());
2676b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org  HGDIOBJ previous_object = SelectObject(memory_dc_, current->bitmap());
2686b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org  if (previous_object != NULL) {
2696b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org    BitBlt(memory_dc_,
2706b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org           0, 0, screen_rect.width(), screen_rect.height(),
2716b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org           desktop_dc_,
2726b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org           screen_rect.left(), screen_rect.top(),
2736b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org           SRCCOPY | CAPTUREBLT);
2746b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org
2756b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org    // Select back the previously selected object to that the device contect
2766b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org    // could be destroyed independently of the bitmap if needed.
2776b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org    SelectObject(memory_dc_, previous_object);
2786b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org  }
2796b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org  return true;
2806b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org}
2816b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org
2826b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.orgvoid ScreenCapturerWinGdi::CaptureCursor() {
283e5c55dac67a6e86d2cdb74563d8845847e5ecf18jiayl@webrtc.org  assert(mouse_shape_observer_);
284e5c55dac67a6e86d2cdb74563d8845847e5ecf18jiayl@webrtc.org
2856b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org  CURSORINFO cursor_info;
2866b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org  cursor_info.cbSize = sizeof(CURSORINFO);
2876b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org  if (!GetCursorInfo(&cursor_info)) {
2886b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org    LOG_F(LS_ERROR) << "Unable to get cursor info. Error = " << GetLastError();
2896b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org    return;
2906b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org  }
2916b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org
2926b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org  // Note that |cursor_info.hCursor| does not need to be freed.
2936b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org  scoped_ptr<MouseCursor> cursor_image(
2946b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org      CreateMouseCursorFromHCursor(desktop_dc_, cursor_info.hCursor));
2956b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org  if (!cursor_image.get())
2966b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org    return;
2976b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org
2986b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org  scoped_ptr<MouseCursorShape> cursor(new MouseCursorShape);
2996b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org  cursor->hotspot = cursor_image->hotspot();
3006b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org  cursor->size = cursor_image->image()->size();
3016b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org  uint8_t* current_row = cursor_image->image()->data();
3026b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org  for (int y = 0; y < cursor_image->image()->size().height(); ++y) {
3036b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org    cursor->data.append(current_row,
3046b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org                        current_row + cursor_image->image()->size().width() *
3056b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org                                        DesktopFrame::kBytesPerPixel);
3066b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org    current_row += cursor_image->image()->stride();
3076b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org  }
3086b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org
3096b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org  // Compare the current cursor with the last one we sent to the client. If
3106b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org  // they're the same, then don't bother sending the cursor again.
3116b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org  if (last_cursor_.size.equals(cursor->size) &&
3126b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org      last_cursor_.hotspot.equals(cursor->hotspot) &&
3136b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org      last_cursor_.data == cursor->data) {
3146b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org    return;
3156b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org  }
3166b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org
3176b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org  LOG(LS_VERBOSE) << "Sending updated cursor: " << cursor->size.width() << "x"
3186b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org                  << cursor->size.height();
3196b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org
3206b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org  // Record the last cursor image that we sent to the client.
3216b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org  last_cursor_ = *cursor;
3226b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org
323e5c55dac67a6e86d2cdb74563d8845847e5ecf18jiayl@webrtc.org  mouse_shape_observer_->OnCursorShapeChanged(cursor.release());
3246b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org}
3256b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org
3266b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org}  // namespace webrtc
327