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

Unified Diff: gpu/ipc/service/direct_composition_child_surface_win.cc

Issue 2926763002: Split DirectCompositionSurfaceWin into two parts. (Closed)
Patch Set: add disallow copy and assign Created 3 years, 6 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 side-by-side diff with in-line comments
Download patch
Index: gpu/ipc/service/direct_composition_child_surface_win.cc
diff --git a/gpu/ipc/service/direct_composition_child_surface_win.cc b/gpu/ipc/service/direct_composition_child_surface_win.cc
new file mode 100644
index 0000000000000000000000000000000000000000..e93aae934e96235c9c618ec1761d61ad93ce2054
--- /dev/null
+++ b/gpu/ipc/service/direct_composition_child_surface_win.cc
@@ -0,0 +1,298 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "gpu/ipc/service/direct_composition_child_surface_win.h"
+
+#include <d3d11_1.h>
+#include <dcomptypes.h>
+
+#include "base/memory/ptr_util.h"
+#include "base/metrics/histogram_macros.h"
+#include "base/synchronization/waitable_event.h"
+#include "base/trace_event/trace_event.h"
+#include "ui/display/display_switches.h"
+#include "ui/gfx/native_widget_types.h"
+#include "ui/gl/egl_util.h"
+#include "ui/gl/gl_angle_util_win.h"
+#include "ui/gl/gl_context.h"
+#include "ui/gl/gl_surface_egl.h"
+#include "ui/gl/scoped_make_current.h"
+
+#ifndef EGL_ANGLE_flexible_surface_compatibility
+#define EGL_ANGLE_flexible_surface_compatibility 1
+#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 {
+// 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;
+}
+
+DirectCompositionChildSurfaceWin::DirectCompositionChildSurfaceWin(
+ const gfx::Size& size,
+ bool has_alpha,
+ bool enable_dc_layers)
+ : gl::GLSurfaceEGL(),
+ size_(size),
+ has_alpha_(has_alpha),
+ enable_dc_layers_(enable_dc_layers) {}
+
+DirectCompositionChildSurfaceWin::~DirectCompositionChildSurfaceWin() {
+ Destroy();
+}
+
+bool DirectCompositionChildSurfaceWin::Initialize(gl::GLSurfaceFormat format) {
+ d3d11_device_ = gl::QueryD3D11DeviceObjectFromANGLE();
+ dcomp_device_ = gl::QueryDirectCompositionDevice(d3d11_device_);
+ if (!dcomp_device_)
+ return false;
+
+ EGLDisplay display = GetDisplay();
+
+ std::vector<EGLint> pbuffer_attribs;
+ pbuffer_attribs.push_back(EGL_WIDTH);
+ pbuffer_attribs.push_back(1);
+ pbuffer_attribs.push_back(EGL_HEIGHT);
+ pbuffer_attribs.push_back(1);
+
+ pbuffer_attribs.push_back(EGL_NONE);
+ default_surface_ =
+ eglCreatePbufferSurface(display, GetConfig(), &pbuffer_attribs[0]);
+ CHECK(!!default_surface_);
+
+ return true;
+}
+
+void DirectCompositionChildSurfaceWin::ReleaseCurrentSurface() {
+ ReleaseDrawTexture(true);
+ dcomp_surface_.Reset();
+ swap_chain_.Reset();
+}
+
+void DirectCompositionChildSurfaceWin::InitializeSurface() {
+ TRACE_EVENT1("gpu", "DirectCompositionChildSurfaceWin::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 DirectCompositionChildSurfaceWin::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, &params);
+ 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;
+}
+
+void DirectCompositionChildSurfaceWin::Destroy() {
+ if (default_surface_) {
+ if (!eglDestroySurface(GetDisplay(), default_surface_)) {
+ DLOG(ERROR) << "eglDestroySurface failed with error "
+ << ui::GetLastEGLErrorString();
+ }
+ 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();
+}
+
+gfx::Size DirectCompositionChildSurfaceWin::GetSize() {
+ return size_;
+}
+
+bool DirectCompositionChildSurfaceWin::IsOffscreen() {
+ return false;
+}
+
+void* DirectCompositionChildSurfaceWin::GetHandle() {
+ return real_surface_ ? real_surface_ : default_surface_;
+}
+
+gfx::SwapResult DirectCompositionChildSurfaceWin::SwapBuffers() {
+ ReleaseDrawTexture(false);
+ return gfx::SwapResult::SWAP_ACK;
+}
+
+bool DirectCompositionChildSurfaceWin::FlipsVertically() const {
+ return true;
+}
+
+bool DirectCompositionChildSurfaceWin::SupportsPostSubBuffer() {
+ return true;
+}
+
+bool DirectCompositionChildSurfaceWin::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();
+ }
+ }
+ return true;
+}
+
+bool DirectCompositionChildSurfaceWin::SupportsDCLayers() const {
+ return true;
+}
+
+bool DirectCompositionChildSurfaceWin::SetDrawRectangle(
+ const gfx::Rect& rectangle) {
+ if (draw_texture_)
+ return false;
+ DCHECK(!real_surface_);
+ ui::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;
+}
+
+gfx::Vector2d DirectCompositionChildSurfaceWin::GetDrawOffset() const {
+ return draw_offset_;
+}
+
+} // namespace gpu
« no previous file with comments | « gpu/ipc/service/direct_composition_child_surface_win.h ('k') | gpu/ipc/service/direct_composition_surface_win.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698