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 kConvertVideoToBT601{"ConvertVideoToBT601", | |
sunnyps
2017/04/11 21:27:23
nit: Can the name be something like FallbackBT709V
| |
50 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()))) { | |
sunnyps
2017/04/11 21:27:23
Can you explain in a comment the difference betwee
| |
343 context1->VideoProcessorSetStreamColorSpace1( | |
344 video_processor_.get(), 0, | |
345 gfx::ColorSpaceWin::GetDXGIColorSpace(src_color_space)); | |
346 } else { | |
347 D3D11_VIDEO_PROCESSOR_COLOR_SPACE color_space = | |
348 gfx::ColorSpaceWin::GetD3D11ColorSpace(src_color_space); | |
349 video_context_->VideoProcessorSetStreamColorSpace(video_processor_.get(), 0, | |
350 &color_space); | |
351 } | |
352 | |
353 gfx::ColorSpace output_color_space = | |
354 is_yuy2_swapchain_ ? src_color_space : gfx::ColorSpace::CreateSRGB(); | |
355 if (base::FeatureList::IsEnabled(kConvertVideoToBT601) && | |
sunnyps
2017/04/11 21:27:23
If the FeatureList singleton isn't initialized, Is
jbauman
2017/04/11 21:43:53
This is initialized in InitializeFieldTrialAndFeat
| |
356 (output_color_space == gfx::ColorSpace::CreateREC709())) { | |
357 output_color_space = gfx::ColorSpace::CreateREC601(); | |
358 } | |
359 | |
360 base::win::ScopedComPtr<IDXGISwapChain3> swap_chain3; | |
sunnyps
2017/04/11 21:27:23
It doesn't seem like you can IDXGISwapChain3 but n
jbauman
2017/04/11 21:43:53
Just because it's first available in Windows 10 do
| |
361 if (SUCCEEDED(swap_chain_.QueryInterface(swap_chain3.Receive()))) { | |
362 DXGI_COLOR_SPACE_TYPE color_space = | |
363 gfx::ColorSpaceWin::GetDXGIColorSpace(output_color_space); | |
364 HRESULT hr = swap_chain3->SetColorSpace1(color_space); | |
365 CHECK(SUCCEEDED(hr)); | |
366 if (context1) { | |
367 context1->VideoProcessorSetOutputColorSpace1(video_processor_.get(), | |
368 color_space); | |
369 } else { | |
370 D3D11_VIDEO_PROCESSOR_COLOR_SPACE d3d11_color_space = | |
371 gfx::ColorSpaceWin::GetD3D11ColorSpace(output_color_space); | |
372 video_context_->VideoProcessorSetOutputColorSpace(video_processor_.get(), | |
373 &d3d11_color_space); | |
374 } | |
375 } | |
376 | |
330 { | 377 { |
331 D3D11_VIDEO_PROCESSOR_INPUT_VIEW_DESC in_desc = {}; | 378 D3D11_VIDEO_PROCESSOR_INPUT_VIEW_DESC in_desc = {}; |
332 in_desc.ViewDimension = D3D11_VPIV_DIMENSION_TEXTURE2D; | 379 in_desc.ViewDimension = D3D11_VPIV_DIMENSION_TEXTURE2D; |
333 in_desc.Texture2D.ArraySlice = (UINT)image_dxgi->level(); | 380 in_desc.Texture2D.ArraySlice = (UINT)image_dxgi->level(); |
334 base::win::ScopedComPtr<ID3D11VideoProcessorInputView> in_view; | 381 base::win::ScopedComPtr<ID3D11VideoProcessorInputView> in_view; |
335 HRESULT hr = video_device_->CreateVideoProcessorInputView( | 382 HRESULT hr = video_device_->CreateVideoProcessorInputView( |
336 image_dxgi->texture().get(), video_processor_enumerator_.get(), | 383 image_dxgi->texture().get(), video_processor_enumerator_.get(), |
337 &in_desc, in_view.Receive()); | 384 &in_desc, in_view.Receive()); |
338 CHECK(SUCCEEDED(hr)); | 385 CHECK(SUCCEEDED(hr)); |
339 | 386 |
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
419 desc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL; | 466 desc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL; |
420 desc.AlphaMode = DXGI_ALPHA_MODE_IGNORE; | 467 desc.AlphaMode = DXGI_ALPHA_MODE_IGNORE; |
421 desc.Flags = | 468 desc.Flags = |
422 DXGI_SWAP_CHAIN_FLAG_YUV_VIDEO | DXGI_SWAP_CHAIN_FLAG_FULLSCREEN_VIDEO; | 469 DXGI_SWAP_CHAIN_FLAG_YUV_VIDEO | DXGI_SWAP_CHAIN_FLAG_FULLSCREEN_VIDEO; |
423 | 470 |
424 HANDLE handle; | 471 HANDLE handle; |
425 create_surface_handle_function_(COMPOSITIONOBJECT_ALL_ACCESS, nullptr, | 472 create_surface_handle_function_(COMPOSITIONOBJECT_ALL_ACCESS, nullptr, |
426 &handle); | 473 &handle); |
427 swap_chain_handle_.Set(handle); | 474 swap_chain_handle_.Set(handle); |
428 | 475 |
476 is_yuy2_swapchain_ = true; | |
429 // The composition surface handle isn't actually used, but | 477 // The composition surface handle isn't actually used, but |
430 // CreateSwapChainForComposition can't create YUY2 swapchains. | 478 // CreateSwapChainForComposition can't create YUY2 swapchains. |
431 HRESULT hr = media_factory->CreateSwapChainForCompositionSurfaceHandle( | 479 HRESULT hr = media_factory->CreateSwapChainForCompositionSurfaceHandle( |
432 d3d11_device_.get(), swap_chain_handle_.Get(), &desc, nullptr, | 480 d3d11_device_.get(), swap_chain_handle_.Get(), &desc, nullptr, |
433 swap_chain_.Receive()); | 481 swap_chain_.Receive()); |
434 | 482 |
435 bool yuy2_swapchain = true; | |
436 | |
437 if (FAILED(hr)) { | 483 if (FAILED(hr)) { |
438 // This should not be hit in production but is a simple fallback for | 484 // This should not be hit in production but is a simple fallback for |
439 // testing on systems without YUY2 swapchain support. | 485 // testing on systems without YUY2 swapchain support. |
440 DLOG(ERROR) << "YUY2 creation failed with " << std::hex << hr | 486 DLOG(ERROR) << "YUY2 creation failed with " << std::hex << hr |
441 << ". Falling back to BGRA"; | 487 << ". Falling back to BGRA"; |
488 is_yuy2_swapchain_ = false; | |
442 desc.Format = DXGI_FORMAT_B8G8R8A8_UNORM; | 489 desc.Format = DXGI_FORMAT_B8G8R8A8_UNORM; |
443 desc.Flags = 0; | 490 desc.Flags = 0; |
444 hr = media_factory->CreateSwapChainForCompositionSurfaceHandle( | 491 hr = media_factory->CreateSwapChainForCompositionSurfaceHandle( |
445 d3d11_device_.get(), swap_chain_handle_.Get(), &desc, nullptr, | 492 d3d11_device_.get(), swap_chain_handle_.Get(), &desc, nullptr, |
446 swap_chain_.Receive()); | 493 swap_chain_.Receive()); |
447 CHECK(SUCCEEDED(hr)); | 494 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 } | 495 } |
458 UMA_HISTOGRAM_BOOLEAN("GPU.DirectComposition.SwapchainFormat", | 496 UMA_HISTOGRAM_BOOLEAN("GPU.DirectComposition.SwapchainFormat", |
459 yuy2_swapchain); | 497 is_yuy2_swapchain_); |
460 out_view_.Reset(); | 498 out_view_.Reset(); |
461 } | 499 } |
462 | 500 |
463 void DCLayerTree::InitVisual(size_t i) { | 501 void DCLayerTree::InitVisual(size_t i) { |
464 DCHECK_GT(visual_info_.size(), i); | 502 DCHECK_GT(visual_info_.size(), i); |
465 VisualInfo* visual_info = &visual_info_[i]; | 503 VisualInfo* visual_info = &visual_info_[i]; |
466 if (visual_info->content_visual) | 504 if (visual_info->content_visual) |
467 return; | 505 return; |
468 DCHECK(!visual_info->clip_visual); | 506 DCHECK(!visual_info->clip_visual); |
469 base::win::ScopedComPtr<IDCompositionVisual2> visual; | 507 base::win::ScopedComPtr<IDCompositionVisual2> visual; |
(...skipping 554 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1024 DirectCompositionSurfaceWin::GetWindowTaskRunnerForTesting() { | 1062 DirectCompositionSurfaceWin::GetWindowTaskRunnerForTesting() { |
1025 return child_window_.GetTaskRunnerForTesting(); | 1063 return child_window_.GetTaskRunnerForTesting(); |
1026 } | 1064 } |
1027 | 1065 |
1028 base::win::ScopedComPtr<IDXGISwapChain1> | 1066 base::win::ScopedComPtr<IDXGISwapChain1> |
1029 DirectCompositionSurfaceWin::GetLayerSwapChainForTesting(size_t index) const { | 1067 DirectCompositionSurfaceWin::GetLayerSwapChainForTesting(size_t index) const { |
1030 return layer_tree_->GetLayerSwapChainForTesting(index); | 1068 return layer_tree_->GetLayerSwapChainForTesting(index); |
1031 } | 1069 } |
1032 | 1070 |
1033 } // namespace gpu | 1071 } // namespace gpu |
OLD | NEW |