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

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: 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 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
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()))) {
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
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
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
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