Bug 1053264 - Do not use CAPTUREBLT when Desktop Composition is enabled. r=jimm

This commit is contained in:
Gian-Carlo Pascutto 2014-09-01 10:10:00 +02:00
Родитель 25f27d0783
Коммит 70ab7f05a1
1 изменённых файлов: 45 добавлений и 21 удалений

Просмотреть файл

@ -37,6 +37,7 @@ const UINT DWM_EC_DISABLECOMPOSITION = 0;
const UINT DWM_EC_ENABLECOMPOSITION = 1;
typedef HRESULT (WINAPI * DwmEnableCompositionFunc)(UINT);
typedef HRESULT (WINAPI * DwmIsCompositionEnabledFunc)(BOOL*);
const wchar_t kDwmapiLibraryName[] = L"dwmapi.dll";
@ -102,6 +103,9 @@ class ScreenCapturerWin : public ScreenCapturer {
HMODULE dwmapi_library_;
DwmEnableCompositionFunc composition_func_;
DwmIsCompositionEnabledFunc composition_enabled_func_;
bool disable_composition_;
// Used to suppress duplicate logging of SetThreadExecutionState errors.
bool set_thread_execution_state_failed_;
@ -118,16 +122,18 @@ ScreenCapturerWin::ScreenCapturerWin(const DesktopCaptureOptions& options)
dwmapi_library_(NULL),
composition_func_(NULL),
set_thread_execution_state_failed_(false) {
if (options.disable_effects()) {
// Load dwmapi.dll dynamically since it is not available on XP.
if (!dwmapi_library_)
dwmapi_library_ = LoadLibrary(kDwmapiLibraryName);
// Load dwmapi.dll dynamically since it is not available on XP.
if (!dwmapi_library_)
dwmapi_library_ = LoadLibrary(kDwmapiLibraryName);
if (dwmapi_library_) {
composition_func_ = reinterpret_cast<DwmEnableCompositionFunc>(
GetProcAddress(dwmapi_library_, "DwmEnableComposition"));
}
if (dwmapi_library_) {
composition_func_ = reinterpret_cast<DwmEnableCompositionFunc>(
GetProcAddress(dwmapi_library_, "DwmEnableComposition"));
composition_enabled_func_ = reinterpret_cast<DwmIsCompositionEnabledFunc>
(GetProcAddress(dwmapi_library_, "DwmIsCompositionEnabled"));
}
disable_composition_ = options.disable_effects();
}
ScreenCapturerWin::~ScreenCapturerWin() {
@ -136,9 +142,11 @@ ScreenCapturerWin::~ScreenCapturerWin() {
if (memory_dc_)
DeleteDC(memory_dc_);
// Restore Aero.
if (composition_func_)
(*composition_func_)(DWM_EC_ENABLECOMPOSITION);
if (disable_composition_) {
// Restore Aero.
if (composition_func_)
(*composition_func_)(DWM_EC_ENABLECOMPOSITION);
}
if (dwmapi_library_)
FreeLibrary(dwmapi_library_);
@ -261,11 +269,13 @@ void ScreenCapturerWin::Start(Callback* callback) {
callback_ = callback;
// Vote to disable Aero composited desktop effects while capturing. Windows
// will restore Aero automatically if the process exits. This has no effect
// under Windows 8 or higher. See crbug.com/124018.
if (composition_func_)
(*composition_func_)(DWM_EC_DISABLECOMPOSITION);
if (disable_composition_) {
// Vote to disable Aero composited desktop effects while capturing. Windows
// will restore Aero automatically if the process exits. This has no effect
// under Windows 8 or higher. See crbug.com/124018.
if (composition_func_)
(*composition_func_)(DWM_EC_DISABLECOMPOSITION);
}
}
void ScreenCapturerWin::PrepareCaptureResources() {
@ -288,10 +298,12 @@ void ScreenCapturerWin::PrepareCaptureResources() {
// So we can continue capture screen bits, just from the wrong desktop.
desktop_.SetThreadDesktop(input_desktop.release());
// Re-assert our vote to disable Aero.
// See crbug.com/124018 and crbug.com/129906.
if (composition_func_ != NULL) {
(*composition_func_)(DWM_EC_DISABLECOMPOSITION);
if (disable_composition_) {
// Re-assert our vote to disable Aero.
// See crbug.com/124018 and crbug.com/129906.
if (composition_func_ != NULL) {
(*composition_func_)(DWM_EC_DISABLECOMPOSITION);
}
}
}
@ -360,12 +372,24 @@ bool ScreenCapturerWin::CaptureImage() {
DesktopFrameWin* current = static_cast<DesktopFrameWin*>(
queue_.current_frame()->GetUnderlyingFrame());
HGDIOBJ previous_object = SelectObject(memory_dc_, current->bitmap());
DWORD rop = SRCCOPY;
if (composition_enabled_func_) {
BOOL enabled;
(*composition_enabled_func_)(&enabled);
if (!enabled) {
// Vista or Windows 7, Aero disabled
rop |= CAPTUREBLT;
}
} else {
// Windows XP, required to get layered windows
rop |= CAPTUREBLT;
}
if (previous_object != NULL) {
BitBlt(memory_dc_,
0, 0, screen_rect.width(), screen_rect.height(),
desktop_dc_,
screen_rect.left(), screen_rect.top(),
SRCCOPY | CAPTUREBLT);
rop);
// Select back the previously selected object to that the device contect
// could be destroyed independently of the bitmap if needed.