 Chromium Code Reviews
 Chromium Code Reviews Issue 2926763002:
  Split DirectCompositionSurfaceWin into two parts.  (Closed)
    
  
    Issue 2926763002:
  Split DirectCompositionSurfaceWin into two parts.  (Closed) 
  | 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 43b0ae97c4e24c0b2ae98caa1690adc35ac963df..ff593f9f44af5b302b59b5090fa46999c811395c 100644 | 
| --- a/gpu/ipc/service/direct_composition_surface_win.cc | 
| +++ b/gpu/ipc/service/direct_composition_surface_win.cc | 
| @@ -18,6 +18,7 @@ | 
| #include "base/win/scoped_handle.h" | 
| #include "base/win/windows_version.h" | 
| #include "gpu/command_buffer/service/feature_info.h" | 
| +#include "gpu/ipc/service/direct_composition_child_surface_win.h" | 
| #include "gpu/ipc/service/gpu_channel_manager.h" | 
| #include "gpu/ipc/service/gpu_channel_manager_delegate.h" | 
| #include "gpu/ipc/service/switches.h" | 
| @@ -40,11 +41,6 @@ | 
| #define EGL_FLEXIBLE_SURFACE_COMPATIBILITY_SUPPORTED_ANGLE 0x33A6 | 
| #endif /* EGL_ANGLE_flexible_surface_compatibility */ | 
| -#ifndef EGL_ANGLE_d3d_texture_client_buffer | 
| -#define EGL_ANGLE_d3d_texture_client_buffer 1 | 
| -#define EGL_D3D_TEXTURE_ANGLE 0x33A3 | 
| -#endif /* EGL_ANGLE_d3d_texture_client_buffer */ | 
| - | 
| namespace gpu { | 
| namespace { | 
| @@ -175,11 +171,6 @@ bool HardwareSupportsOverlays() { | 
| return false; | 
| } | 
| -// Only one DirectComposition surface can be rendered into at a time. Track | 
| -// here which IDCompositionSurface is being rendered into. If another context | 
| -// is made current, then this surface will be suspended. | 
| -IDCompositionSurface* g_current_surface; | 
| - | 
| } // namespace | 
| class DCLayerTree { | 
| @@ -1058,96 +1049,7 @@ bool DirectCompositionSurfaceWin::Initialize(gl::GLSurfaceFormat format) { | 
| eglCreatePbufferSurface(display, GetConfig(), &pbuffer_attribs[0]); | 
| CHECK(!!default_surface_); | 
| - return true; | 
| -} | 
| - | 
| -void DirectCompositionSurfaceWin::ReleaseCurrentSurface() { | 
| - ReleaseDrawTexture(true); | 
| - dcomp_surface_.Reset(); | 
| - swap_chain_.Reset(); | 
| -} | 
| - | 
| -void DirectCompositionSurfaceWin::InitializeSurface() { | 
| - TRACE_EVENT1("gpu", "DirectCompositionSurfaceWin::InitializeSurface()", | 
| - "enable_dc_layers_", enable_dc_layers_); | 
| - DCHECK(!dcomp_surface_); | 
| - DCHECK(!swap_chain_); | 
| - DXGI_FORMAT output_format = | 
| - base::CommandLine::ForCurrentProcess()->HasSwitch(switches::kEnableHDR) | 
| - ? DXGI_FORMAT_R16G16B16A16_FLOAT | 
| - : DXGI_FORMAT_B8G8R8A8_UNORM; | 
| - if (enable_dc_layers_) { | 
| - // Always treat as premultiplied, because an underlay could cause it to | 
| - // become transparent. | 
| - HRESULT hr = dcomp_device_->CreateSurface( | 
| - size_.width(), size_.height(), output_format, | 
| - DXGI_ALPHA_MODE_PREMULTIPLIED, dcomp_surface_.GetAddressOf()); | 
| - has_been_rendered_to_ = false; | 
| - CHECK(SUCCEEDED(hr)); | 
| - } else { | 
| - DXGI_ALPHA_MODE alpha_mode = | 
| - has_alpha_ ? DXGI_ALPHA_MODE_PREMULTIPLIED : DXGI_ALPHA_MODE_IGNORE; | 
| - base::win::ScopedComPtr<IDXGIDevice> dxgi_device; | 
| - d3d11_device_.CopyTo(dxgi_device.GetAddressOf()); | 
| - base::win::ScopedComPtr<IDXGIAdapter> dxgi_adapter; | 
| - dxgi_device->GetAdapter(dxgi_adapter.GetAddressOf()); | 
| - base::win::ScopedComPtr<IDXGIFactory2> dxgi_factory; | 
| - dxgi_adapter->GetParent(IID_PPV_ARGS(dxgi_factory.GetAddressOf())); | 
| - | 
| - DXGI_SWAP_CHAIN_DESC1 desc = {}; | 
| - desc.Width = size_.width(); | 
| - desc.Height = size_.height(); | 
| - desc.Format = output_format; | 
| - 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 = alpha_mode; | 
| - desc.Flags = 0; | 
| - HRESULT hr = dxgi_factory->CreateSwapChainForComposition( | 
| - d3d11_device_.Get(), &desc, nullptr, swap_chain_.GetAddressOf()); | 
| - has_been_rendered_to_ = false; | 
| - first_swap_ = true; | 
| - CHECK(SUCCEEDED(hr)); | 
| - } | 
| -} | 
| - | 
| -void DirectCompositionSurfaceWin::ReleaseDrawTexture(bool will_discard) { | 
| - if (real_surface_) { | 
| - eglDestroySurface(GetDisplay(), real_surface_); | 
| - real_surface_ = nullptr; | 
| - } | 
| - if (draw_texture_) { | 
| - draw_texture_.Reset(); | 
| - if (dcomp_surface_) { | 
| - HRESULT hr = dcomp_surface_->EndDraw(); | 
| - CHECK(SUCCEEDED(hr)); | 
| - } else if (!will_discard) { | 
| - 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); | 
| - 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_.CopyTo(dxgi_device2.GetAddressOf()); | 
| - 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; | 
| + return RecreateRootSurface(); | 
| } | 
| void DirectCompositionSurfaceWin::Destroy() { | 
| @@ -1158,20 +1060,8 @@ void DirectCompositionSurfaceWin::Destroy() { | 
| } | 
| default_surface_ = nullptr; | 
| } | 
| - if (real_surface_) { | 
| - if (!eglDestroySurface(GetDisplay(), real_surface_)) { | 
| - DLOG(ERROR) << "eglDestroySurface failed with error " | 
| - << ui::GetLastEGLErrorString(); | 
| - } | 
| - real_surface_ = nullptr; | 
| - } | 
| - if (dcomp_surface_ && (dcomp_surface_ == g_current_surface)) { | 
| - HRESULT hr = dcomp_surface_->EndDraw(); | 
| - CHECK(SUCCEEDED(hr)); | 
| - g_current_surface = nullptr; | 
| - } | 
| - draw_texture_.Reset(); | 
| - dcomp_surface_.Reset(); | 
| + if (root_surface_) | 
| + root_surface_->Destroy(); | 
| } | 
| gfx::Size DirectCompositionSurfaceWin::GetSize() { | 
| @@ -1183,7 +1073,7 @@ bool DirectCompositionSurfaceWin::IsOffscreen() { | 
| } | 
| void* DirectCompositionSurfaceWin::GetHandle() { | 
| - return real_surface_ ? real_surface_ : default_surface_; | 
| + return root_surface_ ? root_surface_->GetHandle() : default_surface_; | 
| } | 
| bool DirectCompositionSurfaceWin::Resize(const gfx::Size& size, | 
| @@ -1201,16 +1091,13 @@ bool DirectCompositionSurfaceWin::Resize(const gfx::Size& size, | 
| size_ = size; | 
| has_alpha_ = has_alpha; | 
| ScopedReleaseCurrent release_current(this); | 
| - // New surface will be initialized in SetDrawRectangle. | 
| - ReleaseCurrentSurface(); | 
| - | 
| - return true; | 
| + return RecreateRootSurface(); | 
| 
sunnyps
2017/06/10 00:11:11
nit: This seems like a change in behavior if multi
 | 
| } | 
| gfx::SwapResult DirectCompositionSurfaceWin::SwapBuffers() { | 
| { | 
| ScopedReleaseCurrent release_current(this); | 
| - ReleaseDrawTexture(false); | 
| + root_surface_->SwapBuffers(); | 
| layer_tree_->CommitAndClearPendingOverlays(); | 
| } | 
| @@ -1237,8 +1124,11 @@ bool DirectCompositionSurfaceWin::ScheduleDCLayer( | 
| } | 
| bool DirectCompositionSurfaceWin::SetEnableDCLayers(bool enable) { | 
| + if (enable_dc_layers_ == enable) | 
| + return true; | 
| + ScopedReleaseCurrent release_current(this); | 
| enable_dc_layers_ = enable; | 
| - return true; | 
| + return RecreateRootSurface(); | 
| } | 
| @@ -1251,18 +1141,8 @@ bool DirectCompositionSurfaceWin::SupportsPostSubBuffer() { | 
| } | 
| bool DirectCompositionSurfaceWin::OnMakeCurrent(gl::GLContext* context) { | 
| - if (g_current_surface != dcomp_surface_) { | 
| - if (g_current_surface) { | 
| - HRESULT hr = g_current_surface->SuspendDraw(); | 
| - CHECK(SUCCEEDED(hr)); | 
| - g_current_surface = nullptr; | 
| - } | 
| - if (draw_texture_) { | 
| - HRESULT hr = dcomp_surface_->ResumeDraw(); | 
| - CHECK(SUCCEEDED(hr)); | 
| - g_current_surface = dcomp_surface_.Get(); | 
| - } | 
| - } | 
| + if (root_surface_) | 
| + return root_surface_->OnMakeCurrent(context); | 
| return true; | 
| } | 
| @@ -1271,66 +1151,15 @@ bool DirectCompositionSurfaceWin::SupportsDCLayers() const { | 
| } | 
| 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; | 
| - } | 
| - if (gfx::Rect(size_) != rectangle && !has_been_rendered_to_) { | 
| - DLOG(ERROR) << "First draw to surface must draw to everything"; | 
| - return false; | 
| - } | 
| - | 
| - CHECK(!g_current_surface); | 
| - | 
| - RECT rect = rectangle.ToRECT(); | 
| - if (dcomp_surface_) { | 
| - POINT update_offset; | 
| - HRESULT hr = dcomp_surface_->BeginDraw( | 
| - &rect, IID_PPV_ARGS(draw_texture_.GetAddressOf()), &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_.GetAddressOf())); | 
| - swap_rect_ = rectangle; | 
| - draw_offset_ = gfx::Vector2d(); | 
| - CHECK(SUCCEEDED(hr)); | 
| - } | 
| - has_been_rendered_to_ = true; | 
| - | 
| - g_current_surface = dcomp_surface_.Get(); | 
| - | 
| - std::vector<EGLint> pbuffer_attribs{ | 
| - EGL_WIDTH, | 
| - size_.width(), | 
| - EGL_HEIGHT, | 
| - size_.height(), | 
| - EGL_FLEXIBLE_SURFACE_COMPATIBILITY_SUPPORTED_ANGLE, | 
| - EGL_TRUE, | 
| - EGL_NONE}; | 
| - | 
| - EGLClientBuffer buffer = | 
| - reinterpret_cast<EGLClientBuffer>(draw_texture_.Get()); | 
| - real_surface_ = eglCreatePbufferFromClientBuffer( | 
| - GetDisplay(), EGL_D3D_TEXTURE_ANGLE, buffer, GetConfig(), | 
| - &pbuffer_attribs[0]); | 
| - | 
| - return true; | 
| + if (root_surface_) | 
| + return root_surface_->SetDrawRectangle(rectangle); | 
| + return false; | 
| } | 
| gfx::Vector2d DirectCompositionSurfaceWin::GetDrawOffset() const { | 
| - return draw_offset_; | 
| + if (root_surface_) | 
| + return root_surface_->GetDrawOffset(); | 
| + return gfx::Vector2d(); | 
| } | 
| void DirectCompositionSurfaceWin::WaitForSnapshotRendering() { | 
| @@ -1338,6 +1167,22 @@ void DirectCompositionSurfaceWin::WaitForSnapshotRendering() { | 
| glFinish(); | 
| } | 
| +bool DirectCompositionSurfaceWin::RecreateRootSurface() { | 
| + root_surface_ = new DirectCompositionChildSurfaceWin(size_, has_alpha_, | 
| + enable_dc_layers_); | 
| + return root_surface_->Initialize(); | 
| +} | 
| + | 
| +const base::win::ScopedComPtr<IDCompositionSurface> | 
| +DirectCompositionSurfaceWin::dcomp_surface() const { | 
| + return root_surface_ ? root_surface_->dcomp_surface() : nullptr; | 
| +} | 
| + | 
| +const base::win::ScopedComPtr<IDXGISwapChain1> | 
| +DirectCompositionSurfaceWin::swap_chain() const { | 
| + return root_surface_ ? root_surface_->swap_chain() : nullptr; | 
| +} | 
| + | 
| scoped_refptr<base::TaskRunner> | 
| DirectCompositionSurfaceWin::GetWindowTaskRunnerForTesting() { | 
| return child_window_.GetTaskRunnerForTesting(); |