| 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..0d6000250cd4344e0bb939d66ffaac4a9bc1d060 100644
|
| --- a/gpu/ipc/service/direct_composition_surface_win.cc
|
| +++ b/gpu/ipc/service/direct_composition_surface_win.cc
|
| @@ -12,12 +12,12 @@
|
| #include "base/feature_list.h"
|
| #include "base/memory/ptr_util.h"
|
| #include "base/metrics/histogram_macros.h"
|
| -#include "base/optional.h"
|
| #include "base/synchronization/waitable_event.h"
|
| #include "base/trace_event/trace_event.h"
|
| #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 +40,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 {
|
|
|
| @@ -53,24 +48,6 @@ namespace {
|
| const base::Feature kFallbackBT709VideoToBT601{
|
| "FallbackBT709VideoToBT601", base::FEATURE_DISABLED_BY_DEFAULT};
|
|
|
| -// This class is used to make sure a specified surface isn't current, and upon
|
| -// destruction it will make the surface current again if it had been before.
|
| -class ScopedReleaseCurrent {
|
| - public:
|
| - explicit ScopedReleaseCurrent(gl::GLSurface* this_surface) {
|
| - gl::GLContext* current_context = gl::GLContext::GetCurrent();
|
| - bool was_current =
|
| - current_context && current_context->IsCurrent(this_surface);
|
| - if (was_current) {
|
| - make_current_.emplace(current_context, this_surface);
|
| - current_context->ReleaseCurrent(this_surface);
|
| - }
|
| - }
|
| -
|
| - private:
|
| - base::Optional<ui::ScopedMakeCurrent> make_current_;
|
| -};
|
| -
|
| bool SizeContains(const gfx::Size& a, const gfx::Size& b) {
|
| return gfx::Rect(a).Contains(gfx::Rect(b));
|
| }
|
| @@ -175,11 +152,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 +1030,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 +1041,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 +1054,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,
|
| @@ -1200,17 +1071,14 @@ 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;
|
| + ui::ScopedReleaseCurrent release_current(this);
|
| + return RecreateRootSurface();
|
| }
|
|
|
| gfx::SwapResult DirectCompositionSurfaceWin::SwapBuffers() {
|
| {
|
| - ScopedReleaseCurrent release_current(this);
|
| - ReleaseDrawTexture(false);
|
| + ui::ScopedReleaseCurrent release_current(this);
|
| + root_surface_->SwapBuffers();
|
|
|
| layer_tree_->CommitAndClearPendingOverlays();
|
| }
|
| @@ -1237,8 +1105,11 @@ bool DirectCompositionSurfaceWin::ScheduleDCLayer(
|
| }
|
|
|
| bool DirectCompositionSurfaceWin::SetEnableDCLayers(bool enable) {
|
| + if (enable_dc_layers_ == enable)
|
| + return true;
|
| + ui::ScopedReleaseCurrent release_current(this);
|
| enable_dc_layers_ = enable;
|
| - return true;
|
| + return RecreateRootSurface();
|
| }
|
|
|
|
|
| @@ -1251,18 +1122,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 +1132,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 +1148,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();
|
|
|