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

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

Issue 2646243002: Use IDCompositionSurface to implement DirectCompositionSurfaceWin. (Closed)
Patch Set: rebase Created 3 years, 10 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_surface_win.cc
diff --git a/gpu/ipc/service/direct_composition_surface_win.cc b/gpu/ipc/service/direct_composition_surface_win.cc
index d4255619863f407e078d8a830607130954966946..317964e52229a8212250631c6ba69032eba7f4c8 100644
--- a/gpu/ipc/service/direct_composition_surface_win.cc
+++ b/gpu/ipc/service/direct_composition_surface_win.cc
@@ -4,23 +4,62 @@
#include "gpu/ipc/service/direct_composition_surface_win.h"
+#include "base/optional.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"
#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 {
+
+// 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_;
+};
+
+// 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
DirectCompositionSurfaceWin::DirectCompositionSurfaceWin(
base::WeakPtr<ImageTransportSurfaceDelegate> delegate,
HWND parent_window)
- : gl::GLSurfaceEGL(),
- child_window_(delegate, parent_window),
- window_(nullptr),
- surface_(0),
- first_swap_(true) {}
+ : gl::GLSurfaceEGL(), child_window_(delegate, parent_window) {}
+
+DirectCompositionSurfaceWin::~DirectCompositionSurfaceWin() {
+ Destroy();
+}
bool DirectCompositionSurfaceWin::InitializeNativeWindow() {
if (window_)
@@ -31,14 +70,40 @@ bool DirectCompositionSurfaceWin::InitializeNativeWindow() {
return result;
}
+bool DirectCompositionSurfaceWin::Initialize(
+ std::unique_ptr<gfx::VSyncProvider> vsync_provider) {
+ vsync_provider_ = std::move(vsync_provider);
+ return Initialize(gl::GLSurfaceFormat());
+}
+
bool DirectCompositionSurfaceWin::Initialize(gl::GLSurfaceFormat format) {
+ d3d11_device_ = gl::QueryD3D11DeviceObjectFromANGLE();
+ dcomp_device_ = gl::QueryDirectCompositionDevice(d3d11_device_);
+ if (!dcomp_device_)
+ return false;
+
EGLDisplay display = GetDisplay();
if (!window_) {
if (!InitializeNativeWindow()) {
- LOG(ERROR) << "Failed to initialize native window";
+ DLOG(ERROR) << "Failed to initialize native window";
return false;
}
}
+
+ base::win::ScopedComPtr<IDCompositionDesktopDevice> desktop_device;
+ dcomp_device_.QueryInterface(desktop_device.Receive());
+
+ HRESULT hr = desktop_device->CreateTargetForHwnd(window_, TRUE,
+ dcomp_target_.Receive());
+ if (FAILED(hr))
+ return false;
+
+ hr = dcomp_device_->CreateVisual(visual_.Receive());
+ if (FAILED(hr))
+ return false;
+
+ dcomp_target_->SetRoot(visual_.get());
+
std::vector<EGLint> pbuffer_attribs;
pbuffer_attribs.push_back(EGL_WIDTH);
pbuffer_attribs.push_back(1);
@@ -46,20 +111,60 @@ bool DirectCompositionSurfaceWin::Initialize(gl::GLSurfaceFormat format) {
pbuffer_attribs.push_back(1);
pbuffer_attribs.push_back(EGL_NONE);
- surface_ = eglCreatePbufferSurface(display, GetConfig(), &pbuffer_attribs[0]);
- CHECK(!!surface_);
+ default_surface_ =
+ eglCreatePbufferSurface(display, GetConfig(), &pbuffer_attribs[0]);
+ CHECK(!!default_surface_);
+
+ InitializeSurface();
return true;
}
+void DirectCompositionSurfaceWin::InitializeSurface() {
+ ScopedReleaseCurrent release_current(this);
+ 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;
+
+ CHECK(SUCCEEDED(hr));
+}
+
+void DirectCompositionSurfaceWin::ReleaseDrawTexture() {
+ if (real_surface_) {
+ eglDestroySurface(GetDisplay(), real_surface_);
+ real_surface_ = nullptr;
+ }
+ if (draw_texture_) {
+ draw_texture_.Release();
+ HRESULT hr = dcomp_surface_->EndDraw();
+ CHECK(SUCCEEDED(hr));
+ }
+ if (dcomp_surface_ == g_current_surface)
+ g_current_surface = nullptr;
+}
+
void DirectCompositionSurfaceWin::Destroy() {
- if (surface_) {
- if (!eglDestroySurface(GetDisplay(), surface_)) {
- LOG(ERROR) << "eglDestroySurface failed with error "
- << ui::GetLastEGLErrorString();
+ 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();
}
- surface_ = NULL;
+ real_surface_ = nullptr;
}
+ if (dcomp_surface_ == g_current_surface)
+ g_current_surface = nullptr;
+ draw_texture_.Release();
+ dcomp_surface_.Release();
}
gfx::Size DirectCompositionSurfaceWin::GetSize() {
@@ -71,7 +176,7 @@ bool DirectCompositionSurfaceWin::IsOffscreen() {
}
void* DirectCompositionSurfaceWin::GetHandle() {
- return surface_;
+ return real_surface_ ? real_surface_ : default_surface_;
}
bool DirectCompositionSurfaceWin::Resize(const gfx::Size& size,
@@ -87,11 +192,20 @@ bool DirectCompositionSurfaceWin::Resize(const gfx::Size& size,
return false;
}
size_ = size;
+ InitializeSurface();
+
return true;
}
gfx::SwapResult DirectCompositionSurfaceWin::SwapBuffers() {
- CommitAndClearPendingOverlays();
+ {
+ ScopedReleaseCurrent release_current(this);
+ ReleaseDrawTexture();
+ visual_->SetContent(dcomp_surface_.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.
@@ -107,7 +221,11 @@ gfx::SwapResult DirectCompositionSurfaceWin::PostSubBuffer(int x,
int y,
int width,
int height) {
+ ScopedReleaseCurrent release_current(this);
+ ReleaseDrawTexture();
+ visual_->SetContent(dcomp_surface_.get());
CommitAndClearPendingOverlays();
+ dcomp_device_->Commit();
child_window_.ClearInvalidContents();
return gfx::SwapResult::SWAP_ACK;
}
@@ -116,12 +234,6 @@ gfx::VSyncProvider* DirectCompositionSurfaceWin::GetVSyncProvider() {
return vsync_provider_.get();
}
-bool DirectCompositionSurfaceWin::Initialize(
- std::unique_ptr<gfx::VSyncProvider> vsync_provider) {
- vsync_provider_ = std::move(vsync_provider);
- return Initialize(gl::GLSurfaceFormat());
-}
-
bool DirectCompositionSurfaceWin::ScheduleOverlayPlane(
int z_order,
gfx::OverlayTransform transform,
@@ -133,10 +245,84 @@ bool DirectCompositionSurfaceWin::ScheduleOverlayPlane(
return true;
}
+bool DirectCompositionSurfaceWin::CommitAndClearPendingOverlays() {
+ pending_overlays_.clear();
+ return true;
+}
+
+bool DirectCompositionSurfaceWin::FlipsVertically() const {
+ return true;
+}
+
bool DirectCompositionSurfaceWin::SupportsPostSubBuffer() {
return true;
}
+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();
+ }
+ }
+ return true;
+}
+
+bool DirectCompositionSurfaceWin::SupportsSetDrawRectangle() const {
+ return true;
+}
+
+bool DirectCompositionSurfaceWin::SetDrawRectangle(const gfx::Rect& rectangle) {
+ if (draw_texture_)
+ return false;
+ 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;
+ }
+
+ DCHECK(!real_surface_);
+ CHECK(!g_current_surface);
+ ScopedReleaseCurrent release_current(this);
+
+ RECT rect = rectangle.ToRECT();
+ // TODO(jbauman): Use update_offset
+ POINT update_offset;
+
+ HRESULT hr = dcomp_surface_->BeginDraw(
+ &rect, IID_PPV_ARGS(draw_texture_.Receive()), &update_offset);
+ 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;
+}
+
DirectCompositionSurfaceWin::Overlay::Overlay(int z_order,
gfx::OverlayTransform transform,
scoped_refptr<gl::GLImage> image,
@@ -152,11 +338,4 @@ DirectCompositionSurfaceWin::Overlay::Overlay(const Overlay& overlay) = default;
DirectCompositionSurfaceWin::Overlay::~Overlay() {}
-bool DirectCompositionSurfaceWin::CommitAndClearPendingOverlays() {
- pending_overlays_.clear();
- return true;
-}
-
-DirectCompositionSurfaceWin::~DirectCompositionSurfaceWin() {}
-
} // namespace gpu
« no previous file with comments | « gpu/ipc/service/direct_composition_surface_win.h ('k') | gpu/ipc/service/direct_composition_surface_win_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698