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 <deque> | 10 #include <deque> |
(...skipping 12 matching lines...) Expand all Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 |
OLD | NEW |