Chromium Code Reviews| Index: gpu/ipc/service/direct_composition_surface_win.cc |
| diff --git a/gpu/ipc/service/direct_composition_surface_win.cc b/gpu/ipc/service/direct_composition_surface_win.cc |
| index 9454f787361fe6ff1eca8a0f557a58a889e2b946..f09db01b1d0e4ae7d7d8cebb69c5a972db0684b5 100644 |
| --- a/gpu/ipc/service/direct_composition_surface_win.cc |
| +++ b/gpu/ipc/service/direct_composition_surface_win.cc |
| @@ -5,6 +5,7 @@ |
| #include "gpu/ipc/service/direct_composition_surface_win.h" |
| #include "base/optional.h" |
| +#include "base/synchronization/waitable_event.h" |
| #include "gpu/ipc/service/gpu_channel_manager.h" |
| #include "gpu/ipc/service/gpu_channel_manager_delegate.h" |
| #include "ui/gfx/native_widget_types.h" |
| @@ -115,21 +116,50 @@ bool DirectCompositionSurfaceWin::Initialize(gl::GLSurfaceFormat format) { |
| eglCreatePbufferSurface(display, GetConfig(), &pbuffer_attribs[0]); |
| CHECK(!!default_surface_); |
| - InitializeSurface(); |
| - |
| return true; |
| } |
| -void DirectCompositionSurfaceWin::InitializeSurface() { |
| - ScopedReleaseCurrent release_current(this); |
| +void DirectCompositionSurfaceWin::ReleaseCurrentSurface() { |
| ReleaseDrawTexture(); |
| dcomp_surface_.Release(); |
| - HRESULT hr = dcomp_device_->CreateSurface( |
| - size_.width(), size_.height(), DXGI_FORMAT_B8G8R8A8_UNORM, |
| - DXGI_ALPHA_MODE_PREMULTIPLIED, dcomp_surface_.Receive()); |
| - has_been_rendered_to_ = false; |
| + swap_chain_.Release(); |
| +} |
| - CHECK(SUCCEEDED(hr)); |
| +void DirectCompositionSurfaceWin::InitializeSurface() { |
| + DCHECK(!dcomp_surface_); |
| + DCHECK(!swap_chain_); |
| + if (enable_dc_layers_) { |
| + HRESULT hr = dcomp_device_->CreateSurface( |
| + size_.width(), size_.height(), DXGI_FORMAT_B8G8R8A8_UNORM, |
| + DXGI_ALPHA_MODE_PREMULTIPLIED, dcomp_surface_.Receive()); |
| + has_been_rendered_to_ = false; |
| + CHECK(SUCCEEDED(hr)); |
| + } else { |
| + base::win::ScopedComPtr<IDXGIDevice> dxgi_device; |
| + d3d11_device_.QueryInterface(dxgi_device.Receive()); |
| + base::win::ScopedComPtr<IDXGIAdapter> dxgi_adapter; |
| + dxgi_device->GetAdapter(dxgi_adapter.Receive()); |
| + base::win::ScopedComPtr<IDXGIFactory2> dxgi_factory; |
| + dxgi_adapter->GetParent(IID_PPV_ARGS(dxgi_factory.Receive())); |
| + |
| + DXGI_SWAP_CHAIN_DESC1 desc = {}; |
| + desc.Width = size_.width(); |
| + desc.Height = size_.height(); |
| + desc.Format = DXGI_FORMAT_B8G8R8A8_UNORM; |
| + desc.Stereo = FALSE; |
| + desc.SampleDesc.Count = 1; |
| + desc.BufferCount = 2; |
| + desc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; |
| + desc.Scaling = DXGI_SCALING_STRETCH; |
| + desc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL; |
| + desc.AlphaMode = DXGI_ALPHA_MODE_PREMULTIPLIED; |
| + desc.Flags = 0; |
| + HRESULT hr = dxgi_factory->CreateSwapChainForComposition( |
| + d3d11_device_.get(), &desc, nullptr, swap_chain_.Receive()); |
| + has_been_rendered_to_ = false; |
| + first_swap_ = true; |
| + CHECK(SUCCEEDED(hr)); |
| + } |
| } |
| void DirectCompositionSurfaceWin::ReleaseDrawTexture() { |
| @@ -139,8 +169,30 @@ void DirectCompositionSurfaceWin::ReleaseDrawTexture() { |
| } |
| if (draw_texture_) { |
| draw_texture_.Release(); |
| - HRESULT hr = dcomp_surface_->EndDraw(); |
| - CHECK(SUCCEEDED(hr)); |
| + if (dcomp_surface_) { |
| + HRESULT hr = dcomp_surface_->EndDraw(); |
| + CHECK(SUCCEEDED(hr)); |
| + } else { |
| + DXGI_PRESENT_PARAMETERS params = {}; |
| + RECT dirty_rect = swap_rect_.ToRECT(); |
| + params.DirtyRectsCount = 1; |
| + params.pDirtyRects = &dirty_rect; |
| + swap_chain_->Present1(first_swap_ ? 0 : 1, 0, ¶ms); |
|
sunnyps
2017/03/20 23:38:57
This will present a frame if first_swap_ = false a
|
| + if (first_swap_) { |
| + // Wait for the GPU to finish executing its commands before |
| + // committing the DirectComposition tree, or else the swapchain |
| + // may flicker black when it's first presented. |
| + base::win::ScopedComPtr<IDXGIDevice2> dxgi_device2; |
| + HRESULT hr = d3d11_device_.QueryInterface(dxgi_device2.Receive()); |
| + DCHECK(SUCCEEDED(hr)); |
| + base::WaitableEvent event( |
| + base::WaitableEvent::ResetPolicy::AUTOMATIC, |
| + base::WaitableEvent::InitialState::NOT_SIGNALED); |
| + dxgi_device2->EnqueueSetEvent(event.handle()); |
| + event.Wait(); |
| + first_swap_ = false; |
| + } |
| + } |
| } |
| if (dcomp_surface_ == g_current_surface) |
| g_current_surface = nullptr; |
| @@ -161,8 +213,11 @@ void DirectCompositionSurfaceWin::Destroy() { |
| } |
| real_surface_ = nullptr; |
| } |
| - if (dcomp_surface_ == g_current_surface) |
| + if (dcomp_surface_ && (dcomp_surface_ == g_current_surface)) { |
| + HRESULT hr = dcomp_surface_->EndDraw(); |
| + CHECK(SUCCEEDED(hr)); |
| g_current_surface = nullptr; |
| + } |
| draw_texture_.Release(); |
| dcomp_surface_.Release(); |
| } |
| @@ -192,7 +247,9 @@ bool DirectCompositionSurfaceWin::Resize(const gfx::Size& size, |
| return false; |
| } |
| size_ = size; |
| - InitializeSurface(); |
| + ScopedReleaseCurrent release_current(this); |
| + // New surface will be initialized in SetDrawRectangle. |
| + ReleaseCurrentSurface(); |
| return true; |
| } |
| @@ -201,18 +258,15 @@ gfx::SwapResult DirectCompositionSurfaceWin::SwapBuffers() { |
| { |
| ScopedReleaseCurrent release_current(this); |
| ReleaseDrawTexture(); |
| - visual_->SetContent(dcomp_surface_.get()); |
| + DCHECK(dcomp_surface_ || swap_chain_); |
| + if (dcomp_surface_) |
| + visual_->SetContent(dcomp_surface_.get()); |
| + else |
| + visual_->SetContent(swap_chain_.get()); |
| CommitAndClearPendingOverlays(); |
| dcomp_device_->Commit(); |
| } |
| - // Force the driver to finish drawing before clearing the contents to |
| - // transparent, to reduce or eliminate the period of time where the contents |
| - // have flashed black. |
| - if (first_swap_) { |
| - glFinish(); |
| - first_swap_ = false; |
| - } |
| child_window_.ClearInvalidContents(); |
| return gfx::SwapResult::SWAP_ACK; |
| } |
| @@ -223,7 +277,11 @@ gfx::SwapResult DirectCompositionSurfaceWin::PostSubBuffer(int x, |
| int height) { |
|
sunnyps
2017/03/20 23:38:57
Why do we even support PostSubBuffer for this surf
|
| ScopedReleaseCurrent release_current(this); |
| ReleaseDrawTexture(); |
| - visual_->SetContent(dcomp_surface_.get()); |
| + DCHECK(dcomp_surface_ || swap_chain_); |
| + if (dcomp_surface_) |
| + visual_->SetContent(dcomp_surface_.get()); |
| + else |
| + visual_->SetContent(swap_chain_.get()); |
| CommitAndClearPendingOverlays(); |
| dcomp_device_->Commit(); |
| child_window_.ClearInvalidContents(); |
| @@ -245,6 +303,11 @@ bool DirectCompositionSurfaceWin::ScheduleOverlayPlane( |
| return true; |
| } |
| +bool DirectCompositionSurfaceWin::SetEnableDCLayers(bool enable) { |
| + enable_dc_layers_ = enable; |
| + return true; |
| +} |
| + |
| bool DirectCompositionSurfaceWin::CommitAndClearPendingOverlays() { |
| pending_overlays_.clear(); |
| return true; |
| @@ -274,13 +337,23 @@ bool DirectCompositionSurfaceWin::OnMakeCurrent(gl::GLContext* context) { |
| return true; |
| } |
| -bool DirectCompositionSurfaceWin::SupportsSetDrawRectangle() const { |
| +bool DirectCompositionSurfaceWin::SupportsDCLayers() const { |
| return true; |
| } |
| bool DirectCompositionSurfaceWin::SetDrawRectangle(const gfx::Rect& rectangle) { |
| if (draw_texture_) |
| return false; |
| + |
| + DCHECK(!real_surface_); |
| + ScopedReleaseCurrent release_current(this); |
| + |
| + if ((enable_dc_layers_ && !dcomp_surface_) || |
| + (!enable_dc_layers_ && !swap_chain_)) { |
| + ReleaseCurrentSurface(); |
| + InitializeSurface(); |
| + } |
| + |
| if (!gfx::Rect(size_).Contains(rectangle)) { |
| DLOG(ERROR) << "Draw rectangle must be contained within size of surface"; |
| return false; |
| @@ -290,20 +363,24 @@ bool DirectCompositionSurfaceWin::SetDrawRectangle(const gfx::Rect& rectangle) { |
| return false; |
| } |
| - DCHECK(!real_surface_); |
| CHECK(!g_current_surface); |
| - ScopedReleaseCurrent release_current(this); |
| RECT rect = rectangle.ToRECT(); |
| - POINT update_offset; |
| - |
| - HRESULT hr = dcomp_surface_->BeginDraw( |
| - &rect, IID_PPV_ARGS(draw_texture_.Receive()), &update_offset); |
| - CHECK(SUCCEEDED(hr)); |
| + if (dcomp_surface_) { |
| + POINT update_offset; |
| + HRESULT hr = dcomp_surface_->BeginDraw( |
| + &rect, IID_PPV_ARGS(draw_texture_.Receive()), &update_offset); |
| + draw_offset_ = gfx::Point(update_offset) - gfx::Rect(rect).origin(); |
| + CHECK(SUCCEEDED(hr)); |
| + } else { |
| + HRESULT hr = |
| + swap_chain_->GetBuffer(0, IID_PPV_ARGS(draw_texture_.Receive())); |
| + swap_rect_ = rectangle; |
| + draw_offset_ = gfx::Vector2d(); |
| + CHECK(SUCCEEDED(hr)); |
| + } |
| has_been_rendered_to_ = true; |
| - draw_offset_ = gfx::Point(update_offset) - gfx::Rect(rect).origin(); |
| - |
| g_current_surface = dcomp_surface_.get(); |
| std::vector<EGLint> pbuffer_attribs{ |