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

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

Issue 2849963003: Allow putting NV12 software GMBs into overlays on windows (Closed)
Patch Set: post-review changes Created 3 years, 7 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 | gpu/ipc/service/direct_composition_surface_win_unittest.cc » ('j') | 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 <deque> 10 #include <deque>
(...skipping 12 matching lines...) Expand all
23 #include "ui/display/display_switches.h" 23 #include "ui/display/display_switches.h"
24 #include "ui/gfx/color_space_win.h" 24 #include "ui/gfx/color_space_win.h"
25 #include "ui/gfx/geometry/size_conversions.h" 25 #include "ui/gfx/geometry/size_conversions.h"
26 #include "ui/gfx/native_widget_types.h" 26 #include "ui/gfx/native_widget_types.h"
27 #include "ui/gfx/transform.h" 27 #include "ui/gfx/transform.h"
28 #include "ui/gl/dc_renderer_layer_params.h" 28 #include "ui/gl/dc_renderer_layer_params.h"
29 #include "ui/gl/egl_util.h" 29 #include "ui/gl/egl_util.h"
30 #include "ui/gl/gl_angle_util_win.h" 30 #include "ui/gl/gl_angle_util_win.h"
31 #include "ui/gl/gl_context.h" 31 #include "ui/gl/gl_context.h"
32 #include "ui/gl/gl_image_dxgi.h" 32 #include "ui/gl/gl_image_dxgi.h"
33 #include "ui/gl/gl_image_memory.h"
33 #include "ui/gl/gl_surface_egl.h" 34 #include "ui/gl/gl_surface_egl.h"
34 #include "ui/gl/scoped_make_current.h" 35 #include "ui/gl/scoped_make_current.h"
35 36
36 #ifndef EGL_ANGLE_flexible_surface_compatibility 37 #ifndef EGL_ANGLE_flexible_surface_compatibility
37 #define EGL_ANGLE_flexible_surface_compatibility 1 38 #define EGL_ANGLE_flexible_surface_compatibility 1
38 #define EGL_FLEXIBLE_SURFACE_COMPATIBILITY_SUPPORTED_ANGLE 0x33A6 39 #define EGL_FLEXIBLE_SURFACE_COMPATIBILITY_SUPPORTED_ANGLE 0x33A6
39 #endif /* EGL_ANGLE_flexible_surface_compatibility */ 40 #endif /* EGL_ANGLE_flexible_surface_compatibility */
40 41
41 #ifndef EGL_ANGLE_d3d_texture_client_buffer 42 #ifndef EGL_ANGLE_d3d_texture_client_buffer
42 #define EGL_ANGLE_d3d_texture_client_buffer 1 43 #define EGL_ANGLE_d3d_texture_client_buffer 1
(...skipping 206 matching lines...) Expand 10 before | Expand all | Expand 10 after
249 float swap_chain_scale_x() const { return swap_chain_scale_x_; } 250 float swap_chain_scale_x() const { return swap_chain_scale_x_; }
250 float swap_chain_scale_y() const { return swap_chain_scale_y_; } 251 float swap_chain_scale_y() const { return swap_chain_scale_y_; }
251 const base::win::ScopedComPtr<IDXGISwapChain1>& swap_chain() const { 252 const base::win::ScopedComPtr<IDXGISwapChain1>& swap_chain() const {
252 return swap_chain_; 253 return swap_chain_;
253 } 254 }
254 255
255 private: 256 private:
256 using PFN_DCOMPOSITION_CREATE_SURFACE_HANDLE = 257 using PFN_DCOMPOSITION_CREATE_SURFACE_HANDLE =
257 HRESULT(WINAPI*)(DWORD, SECURITY_ATTRIBUTES*, HANDLE*); 258 HRESULT(WINAPI*)(DWORD, SECURITY_ATTRIBUTES*, HANDLE*);
258 259
260 bool UploadVideoImages(gl::GLImageMemory* y_image_memory,
261 gl::GLImageMemory* uv_image_memory);
259 // Returns true if the video processor changed. 262 // Returns true if the video processor changed.
260 bool InitializeVideoProcessor(const gfx::Size& in_size, 263 bool InitializeVideoProcessor(const gfx::Size& in_size,
261 const gfx::Size& out_size); 264 const gfx::Size& out_size);
262 void ReallocateSwapChain(bool yuy2); 265 void ReallocateSwapChain(bool yuy2);
263 bool ShouldBeYUY2(); 266 bool ShouldBeYUY2();
264 267
265 DCLayerTree* surface_; 268 DCLayerTree* surface_;
266 PFN_DCOMPOSITION_CREATE_SURFACE_HANDLE create_surface_handle_function_; 269 PFN_DCOMPOSITION_CREATE_SURFACE_HANDLE create_surface_handle_function_;
267 270
268 gfx::Size swap_chain_size_; 271 gfx::Size swap_chain_size_;
269 gfx::Size processor_input_size_; 272 gfx::Size processor_input_size_;
270 gfx::Size processor_output_size_; 273 gfx::Size processor_output_size_;
271 bool is_yuy2_swapchain_ = false; 274 bool is_yuy2_swapchain_ = false;
272 275
273 // This is the scale from the swapchain size to the size of the contents 276 // This is the scale from the swapchain size to the size of the contents
274 // onscreen. 277 // onscreen.
275 float swap_chain_scale_x_ = 0.0f; 278 float swap_chain_scale_x_ = 0.0f;
276 float swap_chain_scale_y_ = 0.0f; 279 float swap_chain_scale_y_ = 0.0f;
277 280
278 PresentationHistory presentation_history_; 281 PresentationHistory presentation_history_;
279 bool failed_to_create_yuy2_swapchain_ = false; 282 bool failed_to_create_yuy2_swapchain_ = false;
280 int frames_since_color_space_change_ = 0; 283 int frames_since_color_space_change_ = 0;
281 284
282 // This is the GLImage that was presented in the last frame. 285 // These are the GLImages that were presented in the last frame.
283 scoped_refptr<gl::GLImageDXGI> last_gl_image_; 286 std::vector<scoped_refptr<gl::GLImage>> last_gl_images_;
287
288 base::win::ScopedComPtr<ID3D11Texture2D> staging_texture_;
289 gfx::Size staging_texture_size_;
284 290
285 base::win::ScopedComPtr<ID3D11Device> d3d11_device_; 291 base::win::ScopedComPtr<ID3D11Device> d3d11_device_;
286 base::win::ScopedComPtr<IDXGISwapChain1> swap_chain_; 292 base::win::ScopedComPtr<IDXGISwapChain1> swap_chain_;
287 base::win::ScopedComPtr<ID3D11VideoProcessorOutputView> out_view_; 293 base::win::ScopedComPtr<ID3D11VideoProcessorOutputView> out_view_;
288 base::win::ScopedComPtr<ID3D11VideoProcessor> video_processor_; 294 base::win::ScopedComPtr<ID3D11VideoProcessor> video_processor_;
289 base::win::ScopedComPtr<ID3D11VideoProcessorEnumerator> 295 base::win::ScopedComPtr<ID3D11VideoProcessorEnumerator>
290 video_processor_enumerator_; 296 video_processor_enumerator_;
291 base::win::ScopedComPtr<ID3D11VideoDevice> video_device_; 297 base::win::ScopedComPtr<ID3D11VideoDevice> video_device_;
292 base::win::ScopedComPtr<ID3D11VideoContext> video_context_; 298 base::win::ScopedComPtr<ID3D11VideoContext> video_context_;
293 299
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after
385 391
386 if (is_yuy2_swapchain_) { 392 if (is_yuy2_swapchain_) {
387 // Switch to BGRA once 3/4 of presents are composed. 393 // Switch to BGRA once 3/4 of presents are composed.
388 return composition_count < (PresentationHistory::kPresentsToStore * 3 / 4); 394 return composition_count < (PresentationHistory::kPresentsToStore * 3 / 4);
389 } else { 395 } else {
390 // Switch to YUY2 once 3/4 are using overlays (or unknown). 396 // Switch to YUY2 once 3/4 are using overlays (or unknown).
391 return composition_count < (PresentationHistory::kPresentsToStore / 4); 397 return composition_count < (PresentationHistory::kPresentsToStore / 4);
392 } 398 }
393 } 399 }
394 400
401 bool DCLayerTree::SwapChainPresenter::UploadVideoImages(
402 gl::GLImageMemory* y_image_memory,
403 gl::GLImageMemory* uv_image_memory) {
404 gfx::Size texture_size = y_image_memory->GetSize();
405 gfx::Size uv_image_size = uv_image_memory->GetSize();
406 if (uv_image_size.height() != texture_size.height() / 2 ||
407 uv_image_size.width() != texture_size.width() / 2 ||
408 y_image_memory->format() != gfx::BufferFormat::R_8 ||
409 uv_image_memory->format() != gfx::BufferFormat::RG_88) {
410 DVLOG(ERROR) << "Invalid NV12 GLImageMemory properties.";
411 return false;
412 }
413
414 if (!staging_texture_ || (staging_texture_size_ != texture_size)) {
415 staging_texture_.Reset();
416 D3D11_TEXTURE2D_DESC desc = {};
417 desc.Width = texture_size.width();
418 desc.Height = texture_size.height();
419 desc.Format = DXGI_FORMAT_NV12;
420 desc.MipLevels = 1;
421 desc.ArraySize = 1;
422 desc.Usage = D3D11_USAGE_DYNAMIC;
423
424 // This isn't actually bound to a decoder, but dynamic textures need
425 // BindFlags to be nonzero and D3D11_BIND_DECODER also works when creating
426 // a VideoProcessorInputView.
427 desc.BindFlags = D3D11_BIND_DECODER;
428 desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
429 desc.MiscFlags = 0;
430 desc.SampleDesc.Count = 1;
431 base::win::ScopedComPtr<ID3D11Texture2D> texture;
432 HRESULT hr = d3d11_device_->CreateTexture2D(&desc, nullptr,
433 staging_texture_.Receive());
434 CHECK(SUCCEEDED(hr)) << "Creating D3D11 video upload texture failed: "
435 << std::hex << hr;
436 staging_texture_size_ = texture_size;
437 }
438 base::win::ScopedComPtr<ID3D11DeviceContext> context;
439 d3d11_device_->GetImmediateContext(context.Receive());
440 D3D11_MAPPED_SUBRESOURCE mapped_resource;
441 HRESULT hr = context->Map(staging_texture_.Get(), 0, D3D11_MAP_WRITE_DISCARD,
442 0, &mapped_resource);
443 CHECK(SUCCEEDED(hr)) << "Mapping D3D11 video upload texture failed: "
444 << std::hex << hr;
445
446 size_t dest_stride = mapped_resource.RowPitch;
447 for (int y = 0; y < texture_size.height(); y++) {
448 const uint8_t* y_source =
449 y_image_memory->memory() + y * y_image_memory->stride();
450 uint8_t* dest =
451 reinterpret_cast<uint8_t*>(mapped_resource.pData) + dest_stride * y;
452 memcpy(dest, y_source, texture_size.width());
453 }
454
455 uint8_t* uv_dest_plane_start =
456 reinterpret_cast<uint8_t*>(mapped_resource.pData) +
457 dest_stride * texture_size.height();
458 for (int y = 0; y < uv_image_size.height(); y++) {
459 const uint8_t* uv_source =
460 uv_image_memory->memory() + y * uv_image_memory->stride();
461 uint8_t* dest = uv_dest_plane_start + dest_stride * y;
462 memcpy(dest, uv_source, texture_size.width());
463 }
464 context->Unmap(staging_texture_.Get(), 0);
465 return true;
466 }
467
395 void DCLayerTree::SwapChainPresenter::PresentToSwapChain( 468 void DCLayerTree::SwapChainPresenter::PresentToSwapChain(
396 const ui::DCRendererLayerParams& params) { 469 const ui::DCRendererLayerParams& params) {
397 gl::GLImageDXGI* image_dxgi = 470 gl::GLImageDXGI* image_dxgi =
398 gl::GLImageDXGI::FromGLImage(params.image[0].get()); 471 gl::GLImageDXGI::FromGLImage(params.image[0].get());
399 DCHECK(image_dxgi); 472 gl::GLImageMemory* y_image_memory = nullptr;
473 gl::GLImageMemory* uv_image_memory = nullptr;
474 if (params.image.size() >= 2) {
475 y_image_memory = gl::GLImageMemory::FromGLImage(params.image[0].get());
476 uv_image_memory = gl::GLImageMemory::FromGLImage(params.image[1].get());
477 }
478
479 if (!image_dxgi && (!y_image_memory || !uv_image_memory)) {
480 DLOG(ERROR) << "Video GLImages are missing";
481 last_gl_images_.clear();
482 return;
483 }
400 484
401 // Swap chain size is the minimum of the on-screen size and the source 485 // Swap chain size is the minimum of the on-screen size and the source
402 // size so the video processor can do the minimal amount of work and 486 // size so the video processor can do the minimal amount of work and
403 // the overlay has to read the minimal amount of data. 487 // the overlay has to read the minimal amount of data.
404 // DWM is also less likely to promote a surface to an overlay if it's 488 // DWM is also less likely to promote a surface to an overlay if it's
405 // much larger than its area on-screen. 489 // much larger than its area on-screen.
406 gfx::Rect bounds_rect = params.rect; 490 gfx::Rect bounds_rect = params.rect;
407 gfx::Size ceiled_input_size = gfx::ToCeiledSize(params.contents_rect.size()); 491 gfx::Size ceiled_input_size = gfx::ToCeiledSize(params.contents_rect.size());
408 gfx::Size swap_chain_size = bounds_rect.size(); 492 gfx::Size swap_chain_size = bounds_rect.size();
409 swap_chain_size.SetToMin(ceiled_input_size); 493 swap_chain_size.SetToMin(ceiled_input_size);
410 494
411 // YUY2 surfaces must have an even width. 495 // YUY2 surfaces must have an even width.
412 if (swap_chain_size.width() % 2 == 1) 496 if (swap_chain_size.width() % 2 == 1)
413 swap_chain_size.set_width(swap_chain_size.width() + 1); 497 swap_chain_size.set_width(swap_chain_size.width() + 1);
414 498
415 InitializeVideoProcessor(ceiled_input_size, swap_chain_size); 499 InitializeVideoProcessor(ceiled_input_size, swap_chain_size);
416 500
417 bool yuy2_swapchain = ShouldBeYUY2(); 501 bool yuy2_swapchain = ShouldBeYUY2();
418 bool first_present = false; 502 bool first_present = false;
419 if (!swap_chain_ || swap_chain_size_ != swap_chain_size || 503 if (!swap_chain_ || swap_chain_size_ != swap_chain_size ||
420 ((yuy2_swapchain != is_yuy2_swapchain_) && 504 ((yuy2_swapchain != is_yuy2_swapchain_) &&
421 !failed_to_create_yuy2_swapchain_)) { 505 !failed_to_create_yuy2_swapchain_)) {
422 first_present = true; 506 first_present = true;
423 swap_chain_size_ = swap_chain_size; 507 swap_chain_size_ = swap_chain_size;
424 swap_chain_.Reset(); 508 swap_chain_.Reset();
425 ReallocateSwapChain(yuy2_swapchain); 509 ReallocateSwapChain(yuy2_swapchain);
426 } else if (last_gl_image_ == image_dxgi) { 510 } else if (last_gl_images_ == params.image) {
427 // The swap chain is presenting the same image as last swap, which means 511 // The swap chain is presenting the same images as last swap, which means
428 // that the image was never returned to the video decoder and should have 512 // that the images were never returned to the video decoder and should
429 // the same contents as last time. It shouldn't need to be redrawn. 513 // have the same contents as last time. It shouldn't need to be redrawn.
430 return; 514 return;
431 } 515 }
432 516
433 last_gl_image_ = image_dxgi; 517 last_gl_images_ = params.image;
518
519 base::win::ScopedComPtr<ID3D11Texture2D> input_texture;
520 UINT input_level;
521 if (image_dxgi) {
522 input_texture = image_dxgi->texture();
523 input_level = (UINT)image_dxgi->level();
524 staging_texture_.Reset();
525 } else {
526 DCHECK(y_image_memory);
527 DCHECK(uv_image_memory);
528 if (!UploadVideoImages(y_image_memory, uv_image_memory))
529 return;
530 DCHECK(staging_texture_);
531 input_texture = staging_texture_;
532 input_level = 0;
533 }
434 534
435 if (!out_view_) { 535 if (!out_view_) {
436 base::win::ScopedComPtr<ID3D11Texture2D> texture; 536 base::win::ScopedComPtr<ID3D11Texture2D> texture;
437 swap_chain_->GetBuffer(0, IID_PPV_ARGS(texture.Receive())); 537 swap_chain_->GetBuffer(0, IID_PPV_ARGS(texture.Receive()));
438 D3D11_VIDEO_PROCESSOR_OUTPUT_VIEW_DESC out_desc = {}; 538 D3D11_VIDEO_PROCESSOR_OUTPUT_VIEW_DESC out_desc = {};
439 out_desc.ViewDimension = D3D11_VPOV_DIMENSION_TEXTURE2D; 539 out_desc.ViewDimension = D3D11_VPOV_DIMENSION_TEXTURE2D;
440 out_desc.Texture2D.MipSlice = 0; 540 out_desc.Texture2D.MipSlice = 0;
441 HRESULT hr = video_device_->CreateVideoProcessorOutputView( 541 HRESULT hr = video_device_->CreateVideoProcessorOutputView(
442 texture.Get(), video_processor_enumerator_.Get(), &out_desc, 542 texture.Get(), video_processor_enumerator_.Get(), &out_desc,
443 out_view_.Receive()); 543 out_view_.Receive());
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
480 D3D11_VIDEO_PROCESSOR_COLOR_SPACE d3d11_color_space = 580 D3D11_VIDEO_PROCESSOR_COLOR_SPACE d3d11_color_space =
481 gfx::ColorSpaceWin::GetD3D11ColorSpace(output_color_space); 581 gfx::ColorSpaceWin::GetD3D11ColorSpace(output_color_space);
482 video_context_->VideoProcessorSetOutputColorSpace(video_processor_.Get(), 582 video_context_->VideoProcessorSetOutputColorSpace(video_processor_.Get(),
483 &d3d11_color_space); 583 &d3d11_color_space);
484 } 584 }
485 } 585 }
486 586
487 { 587 {
488 D3D11_VIDEO_PROCESSOR_INPUT_VIEW_DESC in_desc = {}; 588 D3D11_VIDEO_PROCESSOR_INPUT_VIEW_DESC in_desc = {};
489 in_desc.ViewDimension = D3D11_VPIV_DIMENSION_TEXTURE2D; 589 in_desc.ViewDimension = D3D11_VPIV_DIMENSION_TEXTURE2D;
490 in_desc.Texture2D.ArraySlice = (UINT)image_dxgi->level(); 590 in_desc.Texture2D.ArraySlice = input_level;
491 base::win::ScopedComPtr<ID3D11VideoProcessorInputView> in_view; 591 base::win::ScopedComPtr<ID3D11VideoProcessorInputView> in_view;
492 HRESULT hr = video_device_->CreateVideoProcessorInputView( 592 HRESULT hr = video_device_->CreateVideoProcessorInputView(
493 image_dxgi->texture().Get(), video_processor_enumerator_.Get(), 593 input_texture.Get(), video_processor_enumerator_.Get(), &in_desc,
494 &in_desc, in_view.Receive()); 594 in_view.Receive());
495 CHECK(SUCCEEDED(hr)); 595 CHECK(SUCCEEDED(hr));
496 596
497 D3D11_VIDEO_PROCESSOR_STREAM stream = {}; 597 D3D11_VIDEO_PROCESSOR_STREAM stream = {};
498 stream.Enable = true; 598 stream.Enable = true;
499 stream.OutputIndex = 0; 599 stream.OutputIndex = 0;
500 stream.InputFrameOrField = 0; 600 stream.InputFrameOrField = 0;
501 stream.PastFrames = 0; 601 stream.PastFrames = 0;
502 stream.FutureFrames = 0; 602 stream.FutureFrames = 0;
503 stream.pInputSurface = in_view.Get(); 603 stream.pInputSurface = in_view.Get();
504 RECT dest_rect = gfx::Rect(swap_chain_size).ToRECT(); 604 RECT dest_rect = gfx::Rect(swap_chain_size).ToRECT();
(...skipping 297 matching lines...) Expand 10 before | Expand all | Expand 10 after
802 // The overall visual tree has one clip visual for every overlay (including 902 // The overall visual tree has one clip visual for every overlay (including
803 // the main plane). The clip visuals are in z_order and are all children of 903 // the main plane). The clip visuals are in z_order and are all children of
804 // a root visual. Each clip visual has a child visual that has the actual 904 // a root visual. Each clip visual has a child visual that has the actual
805 // plane content. 905 // plane content.
806 906
807 for (size_t i = 0; i < pending_overlays_.size(); i++) { 907 for (size_t i = 0; i < pending_overlays_.size(); i++) {
808 ui::DCRendererLayerParams& params = *pending_overlays_[i]; 908 ui::DCRendererLayerParams& params = *pending_overlays_[i];
809 VisualInfo* visual_info = &visual_info_[i]; 909 VisualInfo* visual_info = &visual_info_[i];
810 910
811 InitVisual(i); 911 InitVisual(i);
812 if (params.image.size() > 0 && params.image[0] && 912 if (params.image.size() >= 1 && params.image[0]) {
813 params.image[0]->GetType() == gl::GLImage::Type::DXGI_IMAGE) {
814 UpdateVisualForVideo(visual_info, params); 913 UpdateVisualForVideo(visual_info, params);
815 } else if (params.image.empty()) { 914 } else if (params.image.empty()) {
816 UpdateVisualForBackbuffer(visual_info, params); 915 UpdateVisualForBackbuffer(visual_info, params);
817 } else { 916 } else {
818 CHECK(false); 917 CHECK(false);
819 } 918 }
820 UpdateVisualClip(visual_info, params); 919 UpdateVisualClip(visual_info, params);
821 } 920 }
822 921
823 HRESULT hr = dcomp_device_->Commit(); 922 HRESULT hr = dcomp_device_->Commit();
(...skipping 347 matching lines...) Expand 10 before | Expand all | Expand 10 after
1171 DirectCompositionSurfaceWin::GetWindowTaskRunnerForTesting() { 1270 DirectCompositionSurfaceWin::GetWindowTaskRunnerForTesting() {
1172 return child_window_.GetTaskRunnerForTesting(); 1271 return child_window_.GetTaskRunnerForTesting();
1173 } 1272 }
1174 1273
1175 base::win::ScopedComPtr<IDXGISwapChain1> 1274 base::win::ScopedComPtr<IDXGISwapChain1>
1176 DirectCompositionSurfaceWin::GetLayerSwapChainForTesting(size_t index) const { 1275 DirectCompositionSurfaceWin::GetLayerSwapChainForTesting(size_t index) const {
1177 return layer_tree_->GetLayerSwapChainForTesting(index); 1276 return layer_tree_->GetLayerSwapChainForTesting(index);
1178 } 1277 }
1179 1278
1180 } // namespace gpu 1279 } // namespace gpu
OLDNEW
« no previous file with comments | « no previous file | gpu/ipc/service/direct_composition_surface_win_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698