Chromium Code Reviews| OLD | NEW | 
|---|---|
| 1 // Copyright 2017 The Chromium Authors. All rights reserved. | 1 // Copyright 2017 The Chromium Authors. All rights reserved. | 
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be | 
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. | 
| 4 | 4 | 
| 5 #include "gpu/ipc/service/direct_composition_surface_win.h" | 5 #include "gpu/ipc/service/direct_composition_surface_win.h" | 
| 6 | 6 | 
| 7 #include <d3d11_1.h> | 7 #include <d3d11_1.h> | 
| 8 #include <dcomptypes.h> | 8 #include <dcomptypes.h> | 
| 9 | 9 | 
| 10 #include <deque> | 10 #include <deque> | 
| 11 | 11 | 
| 12 #include "base/feature_list.h" | 12 #include "base/feature_list.h" | 
| 13 #include "base/memory/ptr_util.h" | 13 #include "base/memory/ptr_util.h" | 
| 14 #include "base/metrics/histogram_macros.h" | 14 #include "base/metrics/histogram_macros.h" | 
| 15 #include "base/optional.h" | 15 #include "base/optional.h" | 
| 16 #include "base/synchronization/waitable_event.h" | 16 #include "base/synchronization/waitable_event.h" | 
| 17 #include "base/trace_event/trace_event.h" | 17 #include "base/trace_event/trace_event.h" | 
| 18 #include "base/win/scoped_handle.h" | 18 #include "base/win/scoped_handle.h" | 
| 19 #include "base/win/windows_version.h" | 19 #include "base/win/windows_version.h" | 
| 20 #include "gpu/command_buffer/service/feature_info.h" | |
| 20 #include "gpu/ipc/service/gpu_channel_manager.h" | 21 #include "gpu/ipc/service/gpu_channel_manager.h" | 
| 21 #include "gpu/ipc/service/gpu_channel_manager_delegate.h" | 22 #include "gpu/ipc/service/gpu_channel_manager_delegate.h" | 
| 22 #include "gpu/ipc/service/switches.h" | 23 #include "gpu/ipc/service/switches.h" | 
| 23 #include "ui/display/display_switches.h" | 24 #include "ui/display/display_switches.h" | 
| 24 #include "ui/gfx/color_space_win.h" | 25 #include "ui/gfx/color_space_win.h" | 
| 25 #include "ui/gfx/geometry/size_conversions.h" | 26 #include "ui/gfx/geometry/size_conversions.h" | 
| 26 #include "ui/gfx/native_widget_types.h" | 27 #include "ui/gfx/native_widget_types.h" | 
| 27 #include "ui/gfx/transform.h" | 28 #include "ui/gfx/transform.h" | 
| 28 #include "ui/gl/dc_renderer_layer_params.h" | 29 #include "ui/gl/dc_renderer_layer_params.h" | 
| 29 #include "ui/gl/egl_util.h" | 30 #include "ui/gl/egl_util.h" | 
| (...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 98 bool valid() const { return presents_.size() >= kPresentsToStore; } | 99 bool valid() const { return presents_.size() >= kPresentsToStore; } | 
| 99 int composed_count() const { return composed_count_; } | 100 int composed_count() const { return composed_count_; } | 
| 100 | 101 | 
| 101 private: | 102 private: | 
| 102 std::deque<DXGI_FRAME_PRESENTATION_MODE> presents_; | 103 std::deque<DXGI_FRAME_PRESENTATION_MODE> presents_; | 
| 103 int composed_count_ = 0; | 104 int composed_count_ = 0; | 
| 104 | 105 | 
| 105 DISALLOW_COPY_AND_ASSIGN(PresentationHistory); | 106 DISALLOW_COPY_AND_ASSIGN(PresentationHistory); | 
| 106 }; | 107 }; | 
| 107 | 108 | 
| 109 gfx::Size g_overlay_monitor_size; | |
| 110 | |
| 108 // This is the raw support info, which shouldn't depend on field trial state. | 111 // This is the raw support info, which shouldn't depend on field trial state. | 
| 109 bool HardwareSupportsOverlays() { | 112 bool HardwareSupportsOverlays() { | 
| 110 if (!gl::GLSurfaceEGL::IsDirectCompositionSupported()) | 113 if (!gl::GLSurfaceEGL::IsDirectCompositionSupported()) | 
| 111 return false; | 114 return false; | 
| 112 | 115 | 
| 113 base::CommandLine* command_line = base::CommandLine::ForCurrentProcess(); | 116 base::CommandLine* command_line = base::CommandLine::ForCurrentProcess(); | 
| 114 if (command_line->HasSwitch(switches::kEnableDirectCompositionLayers)) | 117 if (command_line->HasSwitch(switches::kEnableDirectCompositionLayers)) | 
| 115 return true; | 118 return true; | 
| 116 if (command_line->HasSwitch(switches::kDisableDirectCompositionLayers)) | 119 if (command_line->HasSwitch(switches::kDisableDirectCompositionLayers)) | 
| 117 return false; | 120 return false; | 
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 150 | 153 | 
| 151 UMA_HISTOGRAM_SPARSE_SLOWLY("GPU.DirectComposition.OverlaySupportFlags", | 154 UMA_HISTOGRAM_SPARSE_SLOWLY("GPU.DirectComposition.OverlaySupportFlags", | 
| 152 flags); | 155 flags); | 
| 153 | 156 | 
| 154 // Some new Intel drivers only claim to support unscaled overlays, but | 157 // Some new Intel drivers only claim to support unscaled overlays, but | 
| 155 // scaled overlays still work. Even when scaled overlays aren't actually | 158 // scaled overlays still work. Even when scaled overlays aren't actually | 
| 156 // supported, presentation using the overlay path should be relatively | 159 // supported, presentation using the overlay path should be relatively | 
| 157 // efficient. | 160 // efficient. | 
| 158 if (flags & (DXGI_OVERLAY_SUPPORT_FLAG_SCALING | | 161 if (flags & (DXGI_OVERLAY_SUPPORT_FLAG_SCALING | | 
| 159 DXGI_OVERLAY_SUPPORT_FLAG_DIRECT)) { | 162 DXGI_OVERLAY_SUPPORT_FLAG_DIRECT)) { | 
| 163 DXGI_OUTPUT_DESC monitor_desc = {}; | |
| 164 if (FAILED(output3->GetDesc(&monitor_desc))) | |
| 165 continue; | |
| 166 g_overlay_monitor_size = | |
| 167 gfx::Rect(monitor_desc.DesktopCoordinates).size(); | |
| 160 return true; | 168 return true; | 
| 161 } | 169 } | 
| 162 } | 170 } | 
| 163 return false; | 171 return false; | 
| 164 } | 172 } | 
| 165 | 173 | 
| 166 // Only one DirectComposition surface can be rendered into at a time. Track | 174 // Only one DirectComposition surface can be rendered into at a time. Track | 
| 167 // here which IDCompositionSurface is being rendered into. If another context | 175 // here which IDCompositionSurface is being rendered into. If another context | 
| 168 // is made current, then this surface will be suspended. | 176 // is made current, then this surface will be suspended. | 
| 169 IDCompositionSurface* g_current_surface; | 177 IDCompositionSurface* g_current_surface; | 
| (...skipping 18 matching lines...) Expand all Loading... | |
| 188 const base::win::ScopedComPtr<ID3D11VideoProcessor>& video_processor() const { | 196 const base::win::ScopedComPtr<ID3D11VideoProcessor>& video_processor() const { | 
| 189 return video_processor_; | 197 return video_processor_; | 
| 190 } | 198 } | 
| 191 const base::win::ScopedComPtr<ID3D11VideoProcessorEnumerator>& | 199 const base::win::ScopedComPtr<ID3D11VideoProcessorEnumerator>& | 
| 192 video_processor_enumerator() const { | 200 video_processor_enumerator() const { | 
| 193 return video_processor_enumerator_; | 201 return video_processor_enumerator_; | 
| 194 } | 202 } | 
| 195 base::win::ScopedComPtr<IDXGISwapChain1> GetLayerSwapChainForTesting( | 203 base::win::ScopedComPtr<IDXGISwapChain1> GetLayerSwapChainForTesting( | 
| 196 size_t index) const; | 204 size_t index) const; | 
| 197 | 205 | 
| 206 const GpuDriverBugWorkarounds& workarounds() const { | |
| 207 return surface_->workarounds(); | |
| 208 } | |
| 209 | |
| 198 private: | 210 private: | 
| 199 class SwapChainPresenter; | 211 class SwapChainPresenter; | 
| 200 | 212 | 
| 201 // This struct is used to cache information about what visuals are currently | 213 // This struct is used to cache information about what visuals are currently | 
| 202 // being presented so that properties that aren't changed aren't sent to | 214 // being presented so that properties that aren't changed aren't sent to | 
| 203 // DirectComposition. | 215 // DirectComposition. | 
| 204 struct VisualInfo { | 216 struct VisualInfo { | 
| 205 base::win::ScopedComPtr<IDCompositionVisual2> content_visual; | 217 base::win::ScopedComPtr<IDCompositionVisual2> content_visual; | 
| 206 base::win::ScopedComPtr<IDCompositionVisual2> clip_visual; | 218 base::win::ScopedComPtr<IDCompositionVisual2> clip_visual; | 
| 207 | 219 | 
| (...skipping 413 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 621 TRUE, &source_rect); | 633 TRUE, &source_rect); | 
| 622 | 634 | 
| 623 video_context_->VideoProcessorSetStreamAutoProcessingMode( | 635 video_context_->VideoProcessorSetStreamAutoProcessingMode( | 
| 624 video_processor_.Get(), 0, FALSE); | 636 video_processor_.Get(), 0, FALSE); | 
| 625 | 637 | 
| 626 hr = video_context_->VideoProcessorBlt(video_processor_.Get(), | 638 hr = video_context_->VideoProcessorBlt(video_processor_.Get(), | 
| 627 out_view_.Get(), 0, 1, &stream); | 639 out_view_.Get(), 0, 1, &stream); | 
| 628 CHECK(SUCCEEDED(hr)); | 640 CHECK(SUCCEEDED(hr)); | 
| 629 } | 641 } | 
| 630 | 642 | 
| 643 if (surface_->workarounds().disable_larger_than_screen_overlays) { | |
| 644 // Because of the rounding when converting between pixels and DIPs, a | |
| 645 // fullscreen video can become slightly larger than the monitor - e.g. on | |
| 646 // a 3000x2000 monitor with a scale factor of 1.75 a 1920x1079 video can | |
| 647 // become 3002x1689. | |
| 648 // On older Intel drivers, swapchains that are bigger than the monitor | |
| 649 // won't be put into overlays, which will hurt power usage a lot. On those | |
| 650 // systems, the scaling can be adjusted very slightly so that it's less | |
| 651 // than the monitor size. This should be close to imperceptible. | |
| 652 // TODO(jbauman): Remove when http://crbug.com/668278 is fixed. | |
| 653 const int kOversizeMargin = 3; | |
| 654 | |
| 655 if ((bounds_rect.x() >= 0) && | |
| 
 
sunnyps
2017/05/16 00:00:44
nit: what's the reason for the x/y checks? instead
 
 | |
| 656 (bounds_rect.width() > g_overlay_monitor_size.width()) && | |
| 657 (bounds_rect.width() <= | |
| 658 g_overlay_monitor_size.width() + kOversizeMargin)) { | |
| 659 bounds_rect.set_width(g_overlay_monitor_size.width()); | |
| 660 } | |
| 661 | |
| 662 if ((bounds_rect.y() >= 0) && | |
| 663 (bounds_rect.height() > g_overlay_monitor_size.height()) && | |
| 664 (bounds_rect.height() <= | |
| 665 g_overlay_monitor_size.height() + kOversizeMargin)) { | |
| 666 bounds_rect.set_height(g_overlay_monitor_size.height()); | |
| 667 } | |
| 668 } | |
| 669 | |
| 631 swap_chain_scale_x_ = bounds_rect.width() * 1.0f / swap_chain_size.width(); | 670 swap_chain_scale_x_ = bounds_rect.width() * 1.0f / swap_chain_size.width(); | 
| 632 swap_chain_scale_y_ = bounds_rect.height() * 1.0f / swap_chain_size.height(); | 671 swap_chain_scale_y_ = bounds_rect.height() * 1.0f / swap_chain_size.height(); | 
| 633 | 672 | 
| 634 if (first_present) { | 673 if (first_present) { | 
| 635 swap_chain_->Present(0, 0); | 674 swap_chain_->Present(0, 0); | 
| 636 | 675 | 
| 637 // DirectComposition can display black for a swapchain between the first | 676 // DirectComposition can display black for a swapchain between the first | 
| 638 // and second time it's presented to - maybe the first Present can get | 677 // and second time it's presented to - maybe the first Present can get | 
| 639 // lost somehow and it shows the wrong buffer. In that case copy the | 678 // lost somehow and it shows the wrong buffer. In that case copy the | 
| 640 // buffers so both have the correct contents, which seems to help. The | 679 // buffers so both have the correct contents, which seems to help. The | 
| (...skipping 300 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 941 base::MakeUnique<ui::DCRendererLayerParams>(params)); | 980 base::MakeUnique<ui::DCRendererLayerParams>(params)); | 
| 942 return true; | 981 return true; | 
| 943 } | 982 } | 
| 944 | 983 | 
| 945 DirectCompositionSurfaceWin::DirectCompositionSurfaceWin( | 984 DirectCompositionSurfaceWin::DirectCompositionSurfaceWin( | 
| 946 std::unique_ptr<gfx::VSyncProvider> vsync_provider, | 985 std::unique_ptr<gfx::VSyncProvider> vsync_provider, | 
| 947 base::WeakPtr<ImageTransportSurfaceDelegate> delegate, | 986 base::WeakPtr<ImageTransportSurfaceDelegate> delegate, | 
| 948 HWND parent_window) | 987 HWND parent_window) | 
| 949 : gl::GLSurfaceEGL(), | 988 : gl::GLSurfaceEGL(), | 
| 950 child_window_(delegate, parent_window), | 989 child_window_(delegate, parent_window), | 
| 990 workarounds_(delegate->GetFeatureInfo()->workarounds()), | |
| 951 vsync_provider_(std::move(vsync_provider)) {} | 991 vsync_provider_(std::move(vsync_provider)) {} | 
| 952 | 992 | 
| 953 DirectCompositionSurfaceWin::~DirectCompositionSurfaceWin() { | 993 DirectCompositionSurfaceWin::~DirectCompositionSurfaceWin() { | 
| 954 Destroy(); | 994 Destroy(); | 
| 955 } | 995 } | 
| 956 | 996 | 
| 957 // static | 997 // static | 
| 958 bool DirectCompositionSurfaceWin::AreOverlaysSupported() { | 998 bool DirectCompositionSurfaceWin::AreOverlaysSupported() { | 
| 959 if (!HardwareSupportsOverlays()) | 999 if (!HardwareSupportsOverlays()) | 
| 960 return false; | 1000 return false; | 
| (...skipping 319 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1280 DirectCompositionSurfaceWin::GetWindowTaskRunnerForTesting() { | 1320 DirectCompositionSurfaceWin::GetWindowTaskRunnerForTesting() { | 
| 1281 return child_window_.GetTaskRunnerForTesting(); | 1321 return child_window_.GetTaskRunnerForTesting(); | 
| 1282 } | 1322 } | 
| 1283 | 1323 | 
| 1284 base::win::ScopedComPtr<IDXGISwapChain1> | 1324 base::win::ScopedComPtr<IDXGISwapChain1> | 
| 1285 DirectCompositionSurfaceWin::GetLayerSwapChainForTesting(size_t index) const { | 1325 DirectCompositionSurfaceWin::GetLayerSwapChainForTesting(size_t index) const { | 
| 1286 return layer_tree_->GetLayerSwapChainForTesting(index); | 1326 return layer_tree_->GetLayerSwapChainForTesting(index); | 
| 1287 } | 1327 } | 
| 1288 | 1328 | 
| 1289 } // namespace gpu | 1329 } // namespace gpu | 
| OLD | NEW |