Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(209)

Side by Side Diff: gpu/ipc/service/direct_composition_surface_win.cc

Issue 2801193003: Add feature flag to convert BT.709 to BT.601 video in overlays. (Closed)
Patch Set: some changes Created 3 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698