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 "base/feature_list.h" |
10 #include "base/memory/ptr_util.h" | 11 #include "base/memory/ptr_util.h" |
11 #include "base/metrics/histogram_macros.h" | 12 #include "base/metrics/histogram_macros.h" |
12 #include "base/optional.h" | 13 #include "base/optional.h" |
13 #include "base/synchronization/waitable_event.h" | 14 #include "base/synchronization/waitable_event.h" |
14 #include "base/trace_event/trace_event.h" | 15 #include "base/trace_event/trace_event.h" |
15 #include "base/win/scoped_handle.h" | 16 #include "base/win/scoped_handle.h" |
16 #include "base/win/windows_version.h" | 17 #include "base/win/windows_version.h" |
17 #include "gpu/ipc/service/gpu_channel_manager.h" | 18 #include "gpu/ipc/service/gpu_channel_manager.h" |
18 #include "gpu/ipc/service/gpu_channel_manager_delegate.h" | 19 #include "gpu/ipc/service/gpu_channel_manager_delegate.h" |
19 #include "gpu/ipc/service/switches.h" | 20 #include "gpu/ipc/service/switches.h" |
20 #include "ui/display/display_switches.h" | 21 #include "ui/display/display_switches.h" |
| 22 #include "ui/gfx/color_space_win.h" |
21 #include "ui/gfx/geometry/size_conversions.h" | 23 #include "ui/gfx/geometry/size_conversions.h" |
22 #include "ui/gfx/native_widget_types.h" | 24 #include "ui/gfx/native_widget_types.h" |
23 #include "ui/gfx/transform.h" | 25 #include "ui/gfx/transform.h" |
24 #include "ui/gl/dc_renderer_layer_params.h" | 26 #include "ui/gl/dc_renderer_layer_params.h" |
25 #include "ui/gl/egl_util.h" | 27 #include "ui/gl/egl_util.h" |
26 #include "ui/gl/gl_angle_util_win.h" | 28 #include "ui/gl/gl_angle_util_win.h" |
27 #include "ui/gl/gl_context.h" | 29 #include "ui/gl/gl_context.h" |
28 #include "ui/gl/gl_image_dxgi.h" | 30 #include "ui/gl/gl_image_dxgi.h" |
29 #include "ui/gl/gl_surface_egl.h" | 31 #include "ui/gl/gl_surface_egl.h" |
30 #include "ui/gl/scoped_make_current.h" | 32 #include "ui/gl/scoped_make_current.h" |
31 | 33 |
32 #ifndef EGL_ANGLE_flexible_surface_compatibility | 34 #ifndef EGL_ANGLE_flexible_surface_compatibility |
33 #define EGL_ANGLE_flexible_surface_compatibility 1 | 35 #define EGL_ANGLE_flexible_surface_compatibility 1 |
34 #define EGL_FLEXIBLE_SURFACE_COMPATIBILITY_SUPPORTED_ANGLE 0x33A6 | 36 #define EGL_FLEXIBLE_SURFACE_COMPATIBILITY_SUPPORTED_ANGLE 0x33A6 |
35 #endif /* EGL_ANGLE_flexible_surface_compatibility */ | 37 #endif /* EGL_ANGLE_flexible_surface_compatibility */ |
36 | 38 |
37 #ifndef EGL_ANGLE_d3d_texture_client_buffer | 39 #ifndef EGL_ANGLE_d3d_texture_client_buffer |
38 #define EGL_ANGLE_d3d_texture_client_buffer 1 | 40 #define EGL_ANGLE_d3d_texture_client_buffer 1 |
39 #define EGL_D3D_TEXTURE_ANGLE 0x33A3 | 41 #define EGL_D3D_TEXTURE_ANGLE 0x33A3 |
40 #endif /* EGL_ANGLE_d3d_texture_client_buffer */ | 42 #endif /* EGL_ANGLE_d3d_texture_client_buffer */ |
41 | 43 |
42 namespace gpu { | 44 namespace gpu { |
43 namespace { | 45 namespace { |
44 | 46 |
| 47 // Some drivers fail to correctly handle BT.709 video in overlays. This flag |
| 48 // converts them to BT.601 in the video processor. |
| 49 const base::Feature kFallbackBT709VideoToBT601{ |
| 50 "FallbackBT709VideoToBT601", base::FEATURE_ENABLED_BY_DEFAULT}; |
| 51 |
45 // This class is used to make sure a specified surface isn't current, and upon | 52 // This class is used to make sure a specified surface isn't current, and upon |
46 // destruction it will make the surface current again if it had been before. | 53 // destruction it will make the surface current again if it had been before. |
47 class ScopedReleaseCurrent { | 54 class ScopedReleaseCurrent { |
48 public: | 55 public: |
49 explicit ScopedReleaseCurrent(gl::GLSurface* this_surface) { | 56 explicit ScopedReleaseCurrent(gl::GLSurface* this_surface) { |
50 gl::GLContext* current_context = gl::GLContext::GetCurrent(); | 57 gl::GLContext* current_context = gl::GLContext::GetCurrent(); |
51 bool was_current = | 58 bool was_current = |
52 current_context && current_context->IsCurrent(this_surface); | 59 current_context && current_context->IsCurrent(this_surface); |
53 if (was_current) { | 60 if (was_current) { |
54 make_current_.emplace(current_context, this_surface); | 61 make_current_.emplace(current_context, this_surface); |
(...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
172 bool InitializeVideoProcessor(const gfx::Size& in_size, | 179 bool InitializeVideoProcessor(const gfx::Size& in_size, |
173 const gfx::Size& out_size); | 180 const gfx::Size& out_size); |
174 void ReallocateSwapChain(); | 181 void ReallocateSwapChain(); |
175 | 182 |
176 DCLayerTree* surface_; | 183 DCLayerTree* surface_; |
177 PFN_DCOMPOSITION_CREATE_SURFACE_HANDLE create_surface_handle_function_; | 184 PFN_DCOMPOSITION_CREATE_SURFACE_HANDLE create_surface_handle_function_; |
178 | 185 |
179 gfx::Size swap_chain_size_; | 186 gfx::Size swap_chain_size_; |
180 gfx::Size processor_input_size_; | 187 gfx::Size processor_input_size_; |
181 gfx::Size processor_output_size_; | 188 gfx::Size processor_output_size_; |
| 189 bool is_yuy2_swapchain_ = false; |
182 | 190 |
183 // This is the scale from the swapchain size to the size of the contents | 191 // This is the scale from the swapchain size to the size of the contents |
184 // onscreen. | 192 // onscreen. |
185 float swap_chain_scale_x_ = 0.0f; | 193 float swap_chain_scale_x_ = 0.0f; |
186 float swap_chain_scale_y_ = 0.0f; | 194 float swap_chain_scale_y_ = 0.0f; |
187 | 195 |
188 // This is the GLImage that was presented in the last frame. | 196 // This is the GLImage that was presented in the last frame. |
189 scoped_refptr<gl::GLImageDXGI> last_gl_image_; | 197 scoped_refptr<gl::GLImageDXGI> last_gl_image_; |
190 | 198 |
191 base::win::ScopedComPtr<ID3D11Device> d3d11_device_; | 199 base::win::ScopedComPtr<ID3D11Device> d3d11_device_; |
(...skipping 128 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
320 base::win::ScopedComPtr<ID3D11Texture2D> texture; | 328 base::win::ScopedComPtr<ID3D11Texture2D> texture; |
321 swap_chain_->GetBuffer(0, IID_PPV_ARGS(texture.Receive())); | 329 swap_chain_->GetBuffer(0, IID_PPV_ARGS(texture.Receive())); |
322 D3D11_VIDEO_PROCESSOR_OUTPUT_VIEW_DESC out_desc = {}; | 330 D3D11_VIDEO_PROCESSOR_OUTPUT_VIEW_DESC out_desc = {}; |
323 out_desc.ViewDimension = D3D11_VPOV_DIMENSION_TEXTURE2D; | 331 out_desc.ViewDimension = D3D11_VPOV_DIMENSION_TEXTURE2D; |
324 out_desc.Texture2D.MipSlice = 0; | 332 out_desc.Texture2D.MipSlice = 0; |
325 HRESULT hr = video_device_->CreateVideoProcessorOutputView( | 333 HRESULT hr = video_device_->CreateVideoProcessorOutputView( |
326 texture.get(), video_processor_enumerator_.get(), &out_desc, | 334 texture.get(), video_processor_enumerator_.get(), &out_desc, |
327 out_view_.Receive()); | 335 out_view_.Receive()); |
328 CHECK(SUCCEEDED(hr)); | 336 CHECK(SUCCEEDED(hr)); |
329 } | 337 } |
| 338 |
| 339 // TODO(jbauman): Use correct colorspace. |
| 340 gfx::ColorSpace src_color_space = gfx::ColorSpace::CreateREC709(); |
| 341 base::win::ScopedComPtr<ID3D11VideoContext1> context1; |
| 342 if (SUCCEEDED(video_context_.QueryInterface(context1.Receive()))) { |
| 343 context1->VideoProcessorSetStreamColorSpace1( |
| 344 video_processor_.get(), 0, |
| 345 gfx::ColorSpaceWin::GetDXGIColorSpace(src_color_space)); |
| 346 } else { |
| 347 // This can't handle as many different types of color spaces, so use it |
| 348 // only if ID3D11VideoContext1 isn't available. |
| 349 D3D11_VIDEO_PROCESSOR_COLOR_SPACE color_space = |
| 350 gfx::ColorSpaceWin::GetD3D11ColorSpace(src_color_space); |
| 351 video_context_->VideoProcessorSetStreamColorSpace(video_processor_.get(), 0, |
| 352 &color_space); |
| 353 } |
| 354 |
| 355 gfx::ColorSpace output_color_space = |
| 356 is_yuy2_swapchain_ ? src_color_space : gfx::ColorSpace::CreateSRGB(); |
| 357 if (base::FeatureList::IsEnabled(kFallbackBT709VideoToBT601) && |
| 358 (output_color_space == gfx::ColorSpace::CreateREC709())) { |
| 359 output_color_space = gfx::ColorSpace::CreateREC601(); |
| 360 } |
| 361 |
| 362 base::win::ScopedComPtr<IDXGISwapChain3> swap_chain3; |
| 363 if (SUCCEEDED(swap_chain_.QueryInterface(swap_chain3.Receive()))) { |
| 364 DXGI_COLOR_SPACE_TYPE color_space = |
| 365 gfx::ColorSpaceWin::GetDXGIColorSpace(output_color_space); |
| 366 HRESULT hr = swap_chain3->SetColorSpace1(color_space); |
| 367 CHECK(SUCCEEDED(hr)); |
| 368 if (context1) { |
| 369 context1->VideoProcessorSetOutputColorSpace1(video_processor_.get(), |
| 370 color_space); |
| 371 } else { |
| 372 D3D11_VIDEO_PROCESSOR_COLOR_SPACE d3d11_color_space = |
| 373 gfx::ColorSpaceWin::GetD3D11ColorSpace(output_color_space); |
| 374 video_context_->VideoProcessorSetOutputColorSpace(video_processor_.get(), |
| 375 &d3d11_color_space); |
| 376 } |
| 377 } |
| 378 |
330 { | 379 { |
331 D3D11_VIDEO_PROCESSOR_INPUT_VIEW_DESC in_desc = {}; | 380 D3D11_VIDEO_PROCESSOR_INPUT_VIEW_DESC in_desc = {}; |
332 in_desc.ViewDimension = D3D11_VPIV_DIMENSION_TEXTURE2D; | 381 in_desc.ViewDimension = D3D11_VPIV_DIMENSION_TEXTURE2D; |
333 in_desc.Texture2D.ArraySlice = (UINT)image_dxgi->level(); | 382 in_desc.Texture2D.ArraySlice = (UINT)image_dxgi->level(); |
334 base::win::ScopedComPtr<ID3D11VideoProcessorInputView> in_view; | 383 base::win::ScopedComPtr<ID3D11VideoProcessorInputView> in_view; |
335 HRESULT hr = video_device_->CreateVideoProcessorInputView( | 384 HRESULT hr = video_device_->CreateVideoProcessorInputView( |
336 image_dxgi->texture().get(), video_processor_enumerator_.get(), | 385 image_dxgi->texture().get(), video_processor_enumerator_.get(), |
337 &in_desc, in_view.Receive()); | 386 &in_desc, in_view.Receive()); |
338 CHECK(SUCCEEDED(hr)); | 387 CHECK(SUCCEEDED(hr)); |
339 | 388 |
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
419 desc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL; | 468 desc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL; |
420 desc.AlphaMode = DXGI_ALPHA_MODE_IGNORE; | 469 desc.AlphaMode = DXGI_ALPHA_MODE_IGNORE; |
421 desc.Flags = | 470 desc.Flags = |
422 DXGI_SWAP_CHAIN_FLAG_YUV_VIDEO | DXGI_SWAP_CHAIN_FLAG_FULLSCREEN_VIDEO; | 471 DXGI_SWAP_CHAIN_FLAG_YUV_VIDEO | DXGI_SWAP_CHAIN_FLAG_FULLSCREEN_VIDEO; |
423 | 472 |
424 HANDLE handle; | 473 HANDLE handle; |
425 create_surface_handle_function_(COMPOSITIONOBJECT_ALL_ACCESS, nullptr, | 474 create_surface_handle_function_(COMPOSITIONOBJECT_ALL_ACCESS, nullptr, |
426 &handle); | 475 &handle); |
427 swap_chain_handle_.Set(handle); | 476 swap_chain_handle_.Set(handle); |
428 | 477 |
| 478 is_yuy2_swapchain_ = true; |
429 // The composition surface handle isn't actually used, but | 479 // The composition surface handle isn't actually used, but |
430 // CreateSwapChainForComposition can't create YUY2 swapchains. | 480 // CreateSwapChainForComposition can't create YUY2 swapchains. |
431 HRESULT hr = media_factory->CreateSwapChainForCompositionSurfaceHandle( | 481 HRESULT hr = media_factory->CreateSwapChainForCompositionSurfaceHandle( |
432 d3d11_device_.get(), swap_chain_handle_.Get(), &desc, nullptr, | 482 d3d11_device_.get(), swap_chain_handle_.Get(), &desc, nullptr, |
433 swap_chain_.Receive()); | 483 swap_chain_.Receive()); |
434 | 484 |
435 bool yuy2_swapchain = true; | |
436 | |
437 if (FAILED(hr)) { | 485 if (FAILED(hr)) { |
438 // This should not be hit in production but is a simple fallback for | 486 // This should not be hit in production but is a simple fallback for |
439 // testing on systems without YUY2 swapchain support. | 487 // testing on systems without YUY2 swapchain support. |
440 DLOG(ERROR) << "YUY2 creation failed with " << std::hex << hr | 488 DLOG(ERROR) << "YUY2 creation failed with " << std::hex << hr |
441 << ". Falling back to BGRA"; | 489 << ". Falling back to BGRA"; |
| 490 is_yuy2_swapchain_ = false; |
442 desc.Format = DXGI_FORMAT_B8G8R8A8_UNORM; | 491 desc.Format = DXGI_FORMAT_B8G8R8A8_UNORM; |
443 desc.Flags = 0; | 492 desc.Flags = 0; |
444 hr = media_factory->CreateSwapChainForCompositionSurfaceHandle( | 493 hr = media_factory->CreateSwapChainForCompositionSurfaceHandle( |
445 d3d11_device_.get(), swap_chain_handle_.Get(), &desc, nullptr, | 494 d3d11_device_.get(), swap_chain_handle_.Get(), &desc, nullptr, |
446 swap_chain_.Receive()); | 495 swap_chain_.Receive()); |
447 CHECK(SUCCEEDED(hr)); | 496 CHECK(SUCCEEDED(hr)); |
448 yuy2_swapchain = false; | |
449 } else { | |
450 // This is a sensible default colorspace for most videos. | |
451 // TODO(jbauman): Use correct colorspace. | |
452 base::win::ScopedComPtr<IDXGISwapChain3> swap_chain3; | |
453 swap_chain_.QueryInterface(swap_chain3.Receive()); | |
454 hr = swap_chain3->SetColorSpace1( | |
455 DXGI_COLOR_SPACE_YCBCR_STUDIO_G22_LEFT_P709); | |
456 CHECK(SUCCEEDED(hr)); | |
457 } | 497 } |
458 UMA_HISTOGRAM_BOOLEAN("GPU.DirectComposition.SwapchainFormat", | 498 UMA_HISTOGRAM_BOOLEAN("GPU.DirectComposition.SwapchainFormat", |
459 yuy2_swapchain); | 499 is_yuy2_swapchain_); |
460 out_view_.Reset(); | 500 out_view_.Reset(); |
461 } | 501 } |
462 | 502 |
463 void DCLayerTree::InitVisual(size_t i) { | 503 void DCLayerTree::InitVisual(size_t i) { |
464 DCHECK_GT(visual_info_.size(), i); | 504 DCHECK_GT(visual_info_.size(), i); |
465 VisualInfo* visual_info = &visual_info_[i]; | 505 VisualInfo* visual_info = &visual_info_[i]; |
466 if (visual_info->content_visual) | 506 if (visual_info->content_visual) |
467 return; | 507 return; |
468 DCHECK(!visual_info->clip_visual); | 508 DCHECK(!visual_info->clip_visual); |
469 base::win::ScopedComPtr<IDCompositionVisual2> visual; | 509 base::win::ScopedComPtr<IDCompositionVisual2> visual; |
(...skipping 551 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1021 DirectCompositionSurfaceWin::GetWindowTaskRunnerForTesting() { | 1061 DirectCompositionSurfaceWin::GetWindowTaskRunnerForTesting() { |
1022 return child_window_.GetTaskRunnerForTesting(); | 1062 return child_window_.GetTaskRunnerForTesting(); |
1023 } | 1063 } |
1024 | 1064 |
1025 base::win::ScopedComPtr<IDXGISwapChain1> | 1065 base::win::ScopedComPtr<IDXGISwapChain1> |
1026 DirectCompositionSurfaceWin::GetLayerSwapChainForTesting(size_t index) const { | 1066 DirectCompositionSurfaceWin::GetLayerSwapChainForTesting(size_t index) const { |
1027 return layer_tree_->GetLayerSwapChainForTesting(index); | 1067 return layer_tree_->GetLayerSwapChainForTesting(index); |
1028 } | 1068 } |
1029 | 1069 |
1030 } // namespace gpu | 1070 } // namespace gpu |
OLD | NEW |