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

Side by Side Diff: gpu/ipc/service/direct_composition_surface_win.cc

Issue 2646243002: Use IDCompositionSurface to implement DirectCompositionSurfaceWin. (Closed)
Patch Set: better 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 unified diff | Download patch
OLDNEW
1 // Copyright 2017 The Chromium Authors. All rights reserved. 1 // Copyright 2017 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "gpu/ipc/service/direct_composition_surface_win.h" 5 #include "gpu/ipc/service/direct_composition_surface_win.h"
6 6
7 #include "base/optional.h"
7 #include "gpu/ipc/service/gpu_channel_manager.h" 8 #include "gpu/ipc/service/gpu_channel_manager.h"
8 #include "gpu/ipc/service/gpu_channel_manager_delegate.h" 9 #include "gpu/ipc/service/gpu_channel_manager_delegate.h"
9 #include "ui/gfx/native_widget_types.h" 10 #include "ui/gfx/native_widget_types.h"
10 #include "ui/gl/egl_util.h" 11 #include "ui/gl/egl_util.h"
12 #include "ui/gl/gl_angle_util_win.h"
11 #include "ui/gl/gl_context.h" 13 #include "ui/gl/gl_context.h"
12 #include "ui/gl/gl_surface_egl.h" 14 #include "ui/gl/gl_surface_egl.h"
15 #include "ui/gl/scoped_make_current.h"
16
17 #ifndef EGL_ANGLE_flexible_surface_compatibility
18 #define EGL_ANGLE_flexible_surface_compatibility 1
19 #define EGL_FLEXIBLE_SURFACE_COMPATIBILITY_SUPPORTED_ANGLE 0x33A6
20 #endif /* EGL_ANGLE_flexible_surface_compatibility */
21
22 #ifndef EGL_ANGLE_d3d_texture_client_buffer
23 #define EGL_ANGLE_d3d_texture_client_buffer 1
24 #define EGL_D3D_TEXTURE_ANGLE 0x33A3
25 #endif /* EGL_ANGLE_d3d_texture_client_buffer */
13 26
14 namespace gpu { 27 namespace gpu {
28 namespace {
29
30 // This class is used to make sure a specified surface isn't current, and upon
31 // destruction it will make the surface current again if it had been before.
32 class ScopedReleaseCurrent {
33 public:
34 explicit ScopedReleaseCurrent(gl::GLSurface* this_surface) {
35 gl::GLContext* current_context = gl::GLContext::GetCurrent();
36 bool was_current =
37 current_context && current_context->IsCurrent(this_surface);
38 if (was_current) {
39 make_current_.emplace(current_context, this_surface);
40 current_context->ReleaseCurrent(this_surface);
41 }
42 }
43
44 private:
45 base::Optional<ui::ScopedMakeCurrent> make_current_;
46 };
47
48 // Only one DirectComposition surface can be rendered into at a time. Track
49 // here which IDCompositionSurface is being rendered into. If another context
50 // is made current, then this surface will be suspended.
51 IDCompositionSurface* g_current_surface;
52
53 } // namespace
15 54
16 DirectCompositionSurfaceWin::DirectCompositionSurfaceWin( 55 DirectCompositionSurfaceWin::DirectCompositionSurfaceWin(
17 base::WeakPtr<ImageTransportSurfaceDelegate> delegate, 56 base::WeakPtr<ImageTransportSurfaceDelegate> delegate,
18 HWND parent_window) 57 HWND parent_window)
19 : gl::GLSurfaceEGL(), 58 : gl::GLSurfaceEGL(), child_window_(delegate, parent_window), size_(1, 1) {}
20 child_window_(delegate, parent_window), 59
21 window_(nullptr), 60 DirectCompositionSurfaceWin::~DirectCompositionSurfaceWin() {
22 surface_(0), 61 Destroy();
23 first_swap_(true) {} 62 }
24 63
25 bool DirectCompositionSurfaceWin::InitializeNativeWindow() { 64 bool DirectCompositionSurfaceWin::InitializeNativeWindow() {
26 if (window_) 65 if (window_)
27 return true; 66 return true;
28 67
29 bool result = child_window_.Initialize(); 68 bool result = child_window_.Initialize();
30 window_ = child_window_.window(); 69 window_ = child_window_.window();
31 return result; 70 return result;
32 } 71 }
33 72
73 bool DirectCompositionSurfaceWin::Initialize(
74 std::unique_ptr<gfx::VSyncProvider> vsync_provider) {
75 vsync_provider_ = std::move(vsync_provider);
76 return Initialize(gl::GLSurfaceFormat());
77 }
78
34 bool DirectCompositionSurfaceWin::Initialize(gl::GLSurfaceFormat format) { 79 bool DirectCompositionSurfaceWin::Initialize(gl::GLSurfaceFormat format) {
80 d3d11_device_ = gl::QueryD3D11DeviceObjectFromANGLE();
81 dcomp_device_ = gl::QueryDirectCompositionDevice(d3d11_device_);
82 if (!dcomp_device_)
83 return false;
84
35 EGLDisplay display = GetDisplay(); 85 EGLDisplay display = GetDisplay();
36 if (!window_) { 86 if (!window_) {
37 if (!InitializeNativeWindow()) { 87 if (!InitializeNativeWindow()) {
38 LOG(ERROR) << "Failed to initialize native window"; 88 LOG(ERROR) << "Failed to initialize native window";
39 return false; 89 return false;
40 } 90 }
41 } 91 }
92
93 base::win::ScopedComPtr<IDCompositionDesktopDevice> desktop_device;
94 dcomp_device_.QueryInterface(desktop_device.Receive());
95
96 HRESULT hr = desktop_device->CreateTargetForHwnd(window_, TRUE,
97 dcomp_target_.Receive());
98 if (FAILED(hr))
99 return false;
100
101 hr = dcomp_device_->CreateVisual(visual_.Receive());
102 if (FAILED(hr))
103 return false;
104
105 dcomp_target_->SetRoot(visual_.get());
106
42 std::vector<EGLint> pbuffer_attribs; 107 std::vector<EGLint> pbuffer_attribs;
43 pbuffer_attribs.push_back(EGL_WIDTH); 108 pbuffer_attribs.push_back(EGL_WIDTH);
44 pbuffer_attribs.push_back(1); 109 pbuffer_attribs.push_back(1);
45 pbuffer_attribs.push_back(EGL_HEIGHT); 110 pbuffer_attribs.push_back(EGL_HEIGHT);
46 pbuffer_attribs.push_back(1); 111 pbuffer_attribs.push_back(1);
47 112
48 pbuffer_attribs.push_back(EGL_NONE); 113 pbuffer_attribs.push_back(EGL_NONE);
49 surface_ = eglCreatePbufferSurface(display, GetConfig(), &pbuffer_attribs[0]); 114 default_surface_ =
50 CHECK(!!surface_); 115 eglCreatePbufferSurface(display, GetConfig(), &pbuffer_attribs[0]);
116 CHECK(!!default_surface_);
117
118 InitializeSurface();
51 119
52 return true; 120 return true;
53 } 121 }
54 122
123 void DirectCompositionSurfaceWin::InitializeSurface() {
124 ScopedReleaseCurrent release_current(this);
125 ReleaseDrawTexture();
126 dcomp_surface_.Release();
127 HRESULT hr = dcomp_device_->CreateSurface(
128 size_.width(), size_.height(), DXGI_FORMAT_B8G8R8A8_UNORM,
129 DXGI_ALPHA_MODE_PREMULTIPLIED, dcomp_surface_.Receive());
130 has_been_rendered_to_ = false;
131
132 CHECK(SUCCEEDED(hr));
133 }
134
135 void DirectCompositionSurfaceWin::ReleaseDrawTexture() {
136 if (real_surface_) {
137 eglDestroySurface(GetDisplay(), real_surface_);
138 real_surface_ = nullptr;
139 }
140 if (draw_texture_) {
141 draw_texture_.Release();
142 HRESULT hr = dcomp_surface_->EndDraw();
143 CHECK(SUCCEEDED(hr));
144 }
145 if (dcomp_surface_ == g_current_surface)
146 g_current_surface = nullptr;
147 }
148
55 void DirectCompositionSurfaceWin::Destroy() { 149 void DirectCompositionSurfaceWin::Destroy() {
56 if (surface_) { 150 if (default_surface_) {
57 if (!eglDestroySurface(GetDisplay(), surface_)) { 151 if (!eglDestroySurface(GetDisplay(), default_surface_)) {
58 LOG(ERROR) << "eglDestroySurface failed with error " 152 LOG(ERROR) << "eglDestroySurface failed with error "
59 << ui::GetLastEGLErrorString(); 153 << ui::GetLastEGLErrorString();
60 } 154 }
61 surface_ = NULL; 155 default_surface_ = NULL;
62 } 156 }
157 if (real_surface_) {
158 if (!eglDestroySurface(GetDisplay(), real_surface_)) {
159 LOG(ERROR) << "eglDestroySurface failed with error "
160 << ui::GetLastEGLErrorString();
161 }
162 real_surface_ = NULL;
163 }
164 if (dcomp_surface_ == g_current_surface)
165 g_current_surface = nullptr;
166 draw_texture_.Release();
167 dcomp_surface_.Release();
63 } 168 }
64 169
65 gfx::Size DirectCompositionSurfaceWin::GetSize() { 170 gfx::Size DirectCompositionSurfaceWin::GetSize() {
66 return size_; 171 return size_;
67 } 172 }
68 173
69 bool DirectCompositionSurfaceWin::IsOffscreen() { 174 bool DirectCompositionSurfaceWin::IsOffscreen() {
70 return false; 175 return false;
71 } 176 }
72 177
73 void* DirectCompositionSurfaceWin::GetHandle() { 178 void* DirectCompositionSurfaceWin::GetHandle() {
74 return surface_; 179 return real_surface_ ? real_surface_ : default_surface_;
75 } 180 }
76 181
77 bool DirectCompositionSurfaceWin::Resize(const gfx::Size& size, 182 bool DirectCompositionSurfaceWin::Resize(const gfx::Size& size,
78 float scale_factor, 183 float scale_factor,
79 bool has_alpha) { 184 bool has_alpha) {
80 if (size == GetSize()) 185 if (size == GetSize())
81 return true; 186 return true;
82 187
83 // Force a resize and redraw (but not a move, activate, etc.). 188 // Force a resize and redraw (but not a move, activate, etc.).
84 if (!SetWindowPos(window_, nullptr, 0, 0, size.width(), size.height(), 189 if (!SetWindowPos(window_, nullptr, 0, 0, size.width(), size.height(),
85 SWP_NOMOVE | SWP_NOACTIVATE | SWP_NOCOPYBITS | 190 SWP_NOMOVE | SWP_NOACTIVATE | SWP_NOCOPYBITS |
86 SWP_NOOWNERZORDER | SWP_NOZORDER)) { 191 SWP_NOOWNERZORDER | SWP_NOZORDER)) {
87 return false; 192 return false;
88 } 193 }
89 size_ = size; 194 size_ = size;
195 InitializeSurface();
196
90 return true; 197 return true;
91 } 198 }
92 199
93 gfx::SwapResult DirectCompositionSurfaceWin::SwapBuffers() { 200 gfx::SwapResult DirectCompositionSurfaceWin::SwapBuffers() {
94 CommitAndClearPendingOverlays(); 201 {
202 ScopedReleaseCurrent release_current(this);
203 ReleaseDrawTexture();
204 visual_->SetContent(dcomp_surface_.get());
205
206 CommitAndClearPendingOverlays();
207 dcomp_device_->Commit();
208 }
95 // Force the driver to finish drawing before clearing the contents to 209 // Force the driver to finish drawing before clearing the contents to
96 // transparent, to reduce or eliminate the period of time where the contents 210 // transparent, to reduce or eliminate the period of time where the contents
97 // have flashed black. 211 // have flashed black.
98 if (first_swap_) { 212 if (first_swap_) {
99 glFinish(); 213 glFinish();
100 first_swap_ = false; 214 first_swap_ = false;
101 } 215 }
102 child_window_.ClearInvalidContents(); 216 child_window_.ClearInvalidContents();
103 return gfx::SwapResult::SWAP_ACK; 217 return gfx::SwapResult::SWAP_ACK;
104 } 218 }
105 219
106 gfx::SwapResult DirectCompositionSurfaceWin::PostSubBuffer(int x, 220 gfx::SwapResult DirectCompositionSurfaceWin::PostSubBuffer(int x,
107 int y, 221 int y,
108 int width, 222 int width,
109 int height) { 223 int height) {
224 ScopedReleaseCurrent release_current(this);
225 ReleaseDrawTexture();
226 visual_->SetContent(dcomp_surface_.get());
110 CommitAndClearPendingOverlays(); 227 CommitAndClearPendingOverlays();
228 dcomp_device_->Commit();
111 child_window_.ClearInvalidContents(); 229 child_window_.ClearInvalidContents();
112 return gfx::SwapResult::SWAP_ACK; 230 return gfx::SwapResult::SWAP_ACK;
113 } 231 }
114 232
115 gfx::VSyncProvider* DirectCompositionSurfaceWin::GetVSyncProvider() { 233 gfx::VSyncProvider* DirectCompositionSurfaceWin::GetVSyncProvider() {
116 return vsync_provider_.get(); 234 return vsync_provider_.get();
117 } 235 }
118 236
119 bool DirectCompositionSurfaceWin::Initialize(
120 std::unique_ptr<gfx::VSyncProvider> vsync_provider) {
121 vsync_provider_ = std::move(vsync_provider);
122 return Initialize(gl::GLSurfaceFormat());
123 }
124
125 bool DirectCompositionSurfaceWin::ScheduleOverlayPlane( 237 bool DirectCompositionSurfaceWin::ScheduleOverlayPlane(
126 int z_order, 238 int z_order,
127 gfx::OverlayTransform transform, 239 gfx::OverlayTransform transform,
128 gl::GLImage* image, 240 gl::GLImage* image,
129 const gfx::Rect& bounds_rect, 241 const gfx::Rect& bounds_rect,
130 const gfx::RectF& crop_rect) { 242 const gfx::RectF& crop_rect) {
131 pending_overlays_.push_back( 243 pending_overlays_.push_back(
132 Overlay(z_order, transform, image, bounds_rect, crop_rect)); 244 Overlay(z_order, transform, image, bounds_rect, crop_rect));
133 return true; 245 return true;
134 } 246 }
135 247
248 bool DirectCompositionSurfaceWin::CommitAndClearPendingOverlays() {
249 pending_overlays_.clear();
250 return true;
251 }
252
253 bool DirectCompositionSurfaceWin::FlipsVertically() const {
254 return true;
255 }
256
136 bool DirectCompositionSurfaceWin::SupportsPostSubBuffer() { 257 bool DirectCompositionSurfaceWin::SupportsPostSubBuffer() {
137 return true; 258 return true;
138 } 259 }
139 260
261 bool DirectCompositionSurfaceWin::OnMakeCurrent(gl::GLContext* context) {
262 if (g_current_surface != dcomp_surface_) {
263 if (g_current_surface) {
264 HRESULT hr = g_current_surface->SuspendDraw();
265 CHECK(SUCCEEDED(hr));
266 g_current_surface = nullptr;
267 }
268 if (draw_texture_) {
269 HRESULT hr = dcomp_surface_->ResumeDraw();
270 CHECK(SUCCEEDED(hr));
271 g_current_surface = dcomp_surface_.get();
272 }
273 }
274 return true;
275 }
276
277 bool DirectCompositionSurfaceWin::SupportsSetDrawRectangle() const {
278 return true;
279 }
280
281 bool DirectCompositionSurfaceWin::SetDrawRectangle(const gfx::Rect& rectangle) {
282 if (draw_texture_)
283 return false;
284 if (!gfx::Rect(size_).Contains(rectangle)) {
285 LOG(ERROR) << "Draw rectangle must be contained within size of surface";
286 return false;
287 }
288 if (gfx::Rect(size_) != rectangle && !has_been_rendered_to_) {
289 LOG(ERROR) << "First draw to surface must draw to everything";
290 return false;
291 }
292
293 DCHECK(!real_surface_);
294 CHECK(!g_current_surface);
295 ScopedReleaseCurrent release_current(this);
296
297 RECT rect = rectangle.ToRECT();
298 // TODO(jbauman): Use update_offset
299 POINT update_offset;
300
301 HRESULT hr = dcomp_surface_->BeginDraw(
302 &rect, IID_PPV_ARGS(draw_texture_.Receive()), &update_offset);
303 CHECK(SUCCEEDED(hr));
304 has_been_rendered_to_ = true;
305
306 g_current_surface = dcomp_surface_.get();
307
308 std::vector<EGLint> pbuffer_attribs;
309 pbuffer_attribs.push_back(EGL_WIDTH);
310 pbuffer_attribs.push_back(size_.width());
311 pbuffer_attribs.push_back(EGL_HEIGHT);
312 pbuffer_attribs.push_back(size_.height());
313 pbuffer_attribs.push_back(EGL_FLEXIBLE_SURFACE_COMPATIBILITY_SUPPORTED_ANGLE);
314 pbuffer_attribs.push_back(EGL_TRUE);
315 pbuffer_attribs.push_back(EGL_NONE);
316
317 EGLClientBuffer buffer =
318 reinterpret_cast<EGLClientBuffer>(draw_texture_.get());
319 real_surface_ = eglCreatePbufferFromClientBuffer(
320 GetDisplay(), EGL_D3D_TEXTURE_ANGLE, buffer, GetConfig(),
321 &pbuffer_attribs[0]);
322
323 return true;
324 }
325
140 DirectCompositionSurfaceWin::Overlay::Overlay(int z_order, 326 DirectCompositionSurfaceWin::Overlay::Overlay(int z_order,
141 gfx::OverlayTransform transform, 327 gfx::OverlayTransform transform,
142 scoped_refptr<gl::GLImage> image, 328 scoped_refptr<gl::GLImage> image,
143 gfx::Rect bounds_rect, 329 gfx::Rect bounds_rect,
144 gfx::RectF crop_rect) 330 gfx::RectF crop_rect)
145 : z_order(z_order), 331 : z_order(z_order),
146 transform(transform), 332 transform(transform),
147 image(image), 333 image(image),
148 bounds_rect(bounds_rect), 334 bounds_rect(bounds_rect),
149 crop_rect(crop_rect) {} 335 crop_rect(crop_rect) {}
150 336
151 DirectCompositionSurfaceWin::Overlay::Overlay(const Overlay& overlay) = default; 337 DirectCompositionSurfaceWin::Overlay::Overlay(const Overlay& overlay) = default;
152 338
153 DirectCompositionSurfaceWin::Overlay::~Overlay() {} 339 DirectCompositionSurfaceWin::Overlay::~Overlay() {}
154 340
155 bool DirectCompositionSurfaceWin::CommitAndClearPendingOverlays() {
156 pending_overlays_.clear();
157 return true;
158 }
159
160 DirectCompositionSurfaceWin::~DirectCompositionSurfaceWin() {}
161
162 } // namespace gpu 341 } // namespace gpu
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698