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

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

Issue 2743663006: Allow switching DirectCompositionSurfaceWin between drawing modes. (Closed)
Patch Set: fix release current in resize Created 3 years, 9 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 "base/optional.h"
8 #include "base/synchronization/waitable_event.h"
8 #include "gpu/ipc/service/gpu_channel_manager.h" 9 #include "gpu/ipc/service/gpu_channel_manager.h"
9 #include "gpu/ipc/service/gpu_channel_manager_delegate.h" 10 #include "gpu/ipc/service/gpu_channel_manager_delegate.h"
10 #include "ui/gfx/native_widget_types.h" 11 #include "ui/gfx/native_widget_types.h"
11 #include "ui/gl/egl_util.h" 12 #include "ui/gl/egl_util.h"
12 #include "ui/gl/gl_angle_util_win.h" 13 #include "ui/gl/gl_angle_util_win.h"
13 #include "ui/gl/gl_context.h" 14 #include "ui/gl/gl_context.h"
14 #include "ui/gl/gl_surface_egl.h" 15 #include "ui/gl/gl_surface_egl.h"
15 #include "ui/gl/scoped_make_current.h" 16 #include "ui/gl/scoped_make_current.h"
16 17
17 #ifndef EGL_ANGLE_flexible_surface_compatibility 18 #ifndef EGL_ANGLE_flexible_surface_compatibility
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after
108 pbuffer_attribs.push_back(EGL_WIDTH); 109 pbuffer_attribs.push_back(EGL_WIDTH);
109 pbuffer_attribs.push_back(1); 110 pbuffer_attribs.push_back(1);
110 pbuffer_attribs.push_back(EGL_HEIGHT); 111 pbuffer_attribs.push_back(EGL_HEIGHT);
111 pbuffer_attribs.push_back(1); 112 pbuffer_attribs.push_back(1);
112 113
113 pbuffer_attribs.push_back(EGL_NONE); 114 pbuffer_attribs.push_back(EGL_NONE);
114 default_surface_ = 115 default_surface_ =
115 eglCreatePbufferSurface(display, GetConfig(), &pbuffer_attribs[0]); 116 eglCreatePbufferSurface(display, GetConfig(), &pbuffer_attribs[0]);
116 CHECK(!!default_surface_); 117 CHECK(!!default_surface_);
117 118
118 InitializeSurface();
119
120 return true; 119 return true;
121 } 120 }
122 121
123 void DirectCompositionSurfaceWin::InitializeSurface() { 122 void DirectCompositionSurfaceWin::ReleaseCurrentSurface() {
124 ScopedReleaseCurrent release_current(this);
125 ReleaseDrawTexture(); 123 ReleaseDrawTexture();
126 dcomp_surface_.Release(); 124 dcomp_surface_.Release();
127 HRESULT hr = dcomp_device_->CreateSurface( 125 swap_chain_.Release();
128 size_.width(), size_.height(), DXGI_FORMAT_B8G8R8A8_UNORM, 126 }
129 DXGI_ALPHA_MODE_PREMULTIPLIED, dcomp_surface_.Receive());
130 has_been_rendered_to_ = false;
131 127
132 CHECK(SUCCEEDED(hr)); 128 void DirectCompositionSurfaceWin::InitializeSurface() {
129 DCHECK(!dcomp_surface_);
130 DCHECK(!swap_chain_);
131 if (enable_dc_layers_) {
132 HRESULT hr = dcomp_device_->CreateSurface(
133 size_.width(), size_.height(), DXGI_FORMAT_B8G8R8A8_UNORM,
134 DXGI_ALPHA_MODE_PREMULTIPLIED, dcomp_surface_.Receive());
135 has_been_rendered_to_ = false;
136 CHECK(SUCCEEDED(hr));
137 } else {
138 base::win::ScopedComPtr<IDXGIDevice> dxgi_device;
139 d3d11_device_.QueryInterface(dxgi_device.Receive());
140 base::win::ScopedComPtr<IDXGIAdapter> dxgi_adapter;
141 dxgi_device->GetAdapter(dxgi_adapter.Receive());
142 base::win::ScopedComPtr<IDXGIFactory2> dxgi_factory;
143 dxgi_adapter->GetParent(IID_PPV_ARGS(dxgi_factory.Receive()));
144
145 DXGI_SWAP_CHAIN_DESC1 desc = {};
146 desc.Width = size_.width();
147 desc.Height = size_.height();
148 desc.Format = DXGI_FORMAT_B8G8R8A8_UNORM;
149 desc.Stereo = FALSE;
150 desc.SampleDesc.Count = 1;
151 desc.BufferCount = 2;
152 desc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
153 desc.Scaling = DXGI_SCALING_STRETCH;
154 desc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL;
155 desc.AlphaMode = DXGI_ALPHA_MODE_PREMULTIPLIED;
156 desc.Flags = 0;
157 HRESULT hr = dxgi_factory->CreateSwapChainForComposition(
158 d3d11_device_.get(), &desc, nullptr, swap_chain_.Receive());
159 has_been_rendered_to_ = false;
160 first_swap_ = true;
161 CHECK(SUCCEEDED(hr));
162 }
133 } 163 }
134 164
135 void DirectCompositionSurfaceWin::ReleaseDrawTexture() { 165 void DirectCompositionSurfaceWin::ReleaseDrawTexture() {
136 if (real_surface_) { 166 if (real_surface_) {
137 eglDestroySurface(GetDisplay(), real_surface_); 167 eglDestroySurface(GetDisplay(), real_surface_);
138 real_surface_ = nullptr; 168 real_surface_ = nullptr;
139 } 169 }
140 if (draw_texture_) { 170 if (draw_texture_) {
141 draw_texture_.Release(); 171 draw_texture_.Release();
142 HRESULT hr = dcomp_surface_->EndDraw(); 172 if (dcomp_surface_) {
143 CHECK(SUCCEEDED(hr)); 173 HRESULT hr = dcomp_surface_->EndDraw();
174 CHECK(SUCCEEDED(hr));
175 } else {
176 DXGI_PRESENT_PARAMETERS params = {};
177 RECT dirty_rect = swap_rect_.ToRECT();
178 params.DirtyRectsCount = 1;
179 params.pDirtyRects = &dirty_rect;
180 swap_chain_->Present1(first_swap_ ? 0 : 1, 0, &params);
sunnyps 2017/03/20 23:38:57 This will present a frame if first_swap_ = false a
181 if (first_swap_) {
182 // Wait for the GPU to finish executing its commands before
183 // committing the DirectComposition tree, or else the swapchain
184 // may flicker black when it's first presented.
185 base::win::ScopedComPtr<IDXGIDevice2> dxgi_device2;
186 HRESULT hr = d3d11_device_.QueryInterface(dxgi_device2.Receive());
187 DCHECK(SUCCEEDED(hr));
188 base::WaitableEvent event(
189 base::WaitableEvent::ResetPolicy::AUTOMATIC,
190 base::WaitableEvent::InitialState::NOT_SIGNALED);
191 dxgi_device2->EnqueueSetEvent(event.handle());
192 event.Wait();
193 first_swap_ = false;
194 }
195 }
144 } 196 }
145 if (dcomp_surface_ == g_current_surface) 197 if (dcomp_surface_ == g_current_surface)
146 g_current_surface = nullptr; 198 g_current_surface = nullptr;
147 } 199 }
148 200
149 void DirectCompositionSurfaceWin::Destroy() { 201 void DirectCompositionSurfaceWin::Destroy() {
150 if (default_surface_) { 202 if (default_surface_) {
151 if (!eglDestroySurface(GetDisplay(), default_surface_)) { 203 if (!eglDestroySurface(GetDisplay(), default_surface_)) {
152 DLOG(ERROR) << "eglDestroySurface failed with error " 204 DLOG(ERROR) << "eglDestroySurface failed with error "
153 << ui::GetLastEGLErrorString(); 205 << ui::GetLastEGLErrorString();
154 } 206 }
155 default_surface_ = nullptr; 207 default_surface_ = nullptr;
156 } 208 }
157 if (real_surface_) { 209 if (real_surface_) {
158 if (!eglDestroySurface(GetDisplay(), real_surface_)) { 210 if (!eglDestroySurface(GetDisplay(), real_surface_)) {
159 DLOG(ERROR) << "eglDestroySurface failed with error " 211 DLOG(ERROR) << "eglDestroySurface failed with error "
160 << ui::GetLastEGLErrorString(); 212 << ui::GetLastEGLErrorString();
161 } 213 }
162 real_surface_ = nullptr; 214 real_surface_ = nullptr;
163 } 215 }
164 if (dcomp_surface_ == g_current_surface) 216 if (dcomp_surface_ && (dcomp_surface_ == g_current_surface)) {
217 HRESULT hr = dcomp_surface_->EndDraw();
218 CHECK(SUCCEEDED(hr));
165 g_current_surface = nullptr; 219 g_current_surface = nullptr;
220 }
166 draw_texture_.Release(); 221 draw_texture_.Release();
167 dcomp_surface_.Release(); 222 dcomp_surface_.Release();
168 } 223 }
169 224
170 gfx::Size DirectCompositionSurfaceWin::GetSize() { 225 gfx::Size DirectCompositionSurfaceWin::GetSize() {
171 return size_; 226 return size_;
172 } 227 }
173 228
174 bool DirectCompositionSurfaceWin::IsOffscreen() { 229 bool DirectCompositionSurfaceWin::IsOffscreen() {
175 return false; 230 return false;
176 } 231 }
177 232
178 void* DirectCompositionSurfaceWin::GetHandle() { 233 void* DirectCompositionSurfaceWin::GetHandle() {
179 return real_surface_ ? real_surface_ : default_surface_; 234 return real_surface_ ? real_surface_ : default_surface_;
180 } 235 }
181 236
182 bool DirectCompositionSurfaceWin::Resize(const gfx::Size& size, 237 bool DirectCompositionSurfaceWin::Resize(const gfx::Size& size,
183 float scale_factor, 238 float scale_factor,
184 bool has_alpha) { 239 bool has_alpha) {
185 if (size == GetSize()) 240 if (size == GetSize())
186 return true; 241 return true;
187 242
188 // Force a resize and redraw (but not a move, activate, etc.). 243 // Force a resize and redraw (but not a move, activate, etc.).
189 if (!SetWindowPos(window_, nullptr, 0, 0, size.width(), size.height(), 244 if (!SetWindowPos(window_, nullptr, 0, 0, size.width(), size.height(),
190 SWP_NOMOVE | SWP_NOACTIVATE | SWP_NOCOPYBITS | 245 SWP_NOMOVE | SWP_NOACTIVATE | SWP_NOCOPYBITS |
191 SWP_NOOWNERZORDER | SWP_NOZORDER)) { 246 SWP_NOOWNERZORDER | SWP_NOZORDER)) {
192 return false; 247 return false;
193 } 248 }
194 size_ = size; 249 size_ = size;
195 InitializeSurface(); 250 ScopedReleaseCurrent release_current(this);
251 // New surface will be initialized in SetDrawRectangle.
252 ReleaseCurrentSurface();
196 253
197 return true; 254 return true;
198 } 255 }
199 256
200 gfx::SwapResult DirectCompositionSurfaceWin::SwapBuffers() { 257 gfx::SwapResult DirectCompositionSurfaceWin::SwapBuffers() {
201 { 258 {
202 ScopedReleaseCurrent release_current(this); 259 ScopedReleaseCurrent release_current(this);
203 ReleaseDrawTexture(); 260 ReleaseDrawTexture();
204 visual_->SetContent(dcomp_surface_.get()); 261 DCHECK(dcomp_surface_ || swap_chain_);
262 if (dcomp_surface_)
263 visual_->SetContent(dcomp_surface_.get());
264 else
265 visual_->SetContent(swap_chain_.get());
205 266
206 CommitAndClearPendingOverlays(); 267 CommitAndClearPendingOverlays();
207 dcomp_device_->Commit(); 268 dcomp_device_->Commit();
208 } 269 }
209 // Force the driver to finish drawing before clearing the contents to
210 // transparent, to reduce or eliminate the period of time where the contents
211 // have flashed black.
212 if (first_swap_) {
213 glFinish();
214 first_swap_ = false;
215 }
216 child_window_.ClearInvalidContents(); 270 child_window_.ClearInvalidContents();
217 return gfx::SwapResult::SWAP_ACK; 271 return gfx::SwapResult::SWAP_ACK;
218 } 272 }
219 273
220 gfx::SwapResult DirectCompositionSurfaceWin::PostSubBuffer(int x, 274 gfx::SwapResult DirectCompositionSurfaceWin::PostSubBuffer(int x,
221 int y, 275 int y,
222 int width, 276 int width,
223 int height) { 277 int height) {
sunnyps 2017/03/20 23:38:57 Why do we even support PostSubBuffer for this surf
224 ScopedReleaseCurrent release_current(this); 278 ScopedReleaseCurrent release_current(this);
225 ReleaseDrawTexture(); 279 ReleaseDrawTexture();
226 visual_->SetContent(dcomp_surface_.get()); 280 DCHECK(dcomp_surface_ || swap_chain_);
281 if (dcomp_surface_)
282 visual_->SetContent(dcomp_surface_.get());
283 else
284 visual_->SetContent(swap_chain_.get());
227 CommitAndClearPendingOverlays(); 285 CommitAndClearPendingOverlays();
228 dcomp_device_->Commit(); 286 dcomp_device_->Commit();
229 child_window_.ClearInvalidContents(); 287 child_window_.ClearInvalidContents();
230 return gfx::SwapResult::SWAP_ACK; 288 return gfx::SwapResult::SWAP_ACK;
231 } 289 }
232 290
233 gfx::VSyncProvider* DirectCompositionSurfaceWin::GetVSyncProvider() { 291 gfx::VSyncProvider* DirectCompositionSurfaceWin::GetVSyncProvider() {
234 return vsync_provider_.get(); 292 return vsync_provider_.get();
235 } 293 }
236 294
237 bool DirectCompositionSurfaceWin::ScheduleOverlayPlane( 295 bool DirectCompositionSurfaceWin::ScheduleOverlayPlane(
238 int z_order, 296 int z_order,
239 gfx::OverlayTransform transform, 297 gfx::OverlayTransform transform,
240 gl::GLImage* image, 298 gl::GLImage* image,
241 const gfx::Rect& bounds_rect, 299 const gfx::Rect& bounds_rect,
242 const gfx::RectF& crop_rect) { 300 const gfx::RectF& crop_rect) {
243 pending_overlays_.push_back( 301 pending_overlays_.push_back(
244 Overlay(z_order, transform, image, bounds_rect, crop_rect)); 302 Overlay(z_order, transform, image, bounds_rect, crop_rect));
245 return true; 303 return true;
246 } 304 }
247 305
306 bool DirectCompositionSurfaceWin::SetEnableDCLayers(bool enable) {
307 enable_dc_layers_ = enable;
308 return true;
309 }
310
248 bool DirectCompositionSurfaceWin::CommitAndClearPendingOverlays() { 311 bool DirectCompositionSurfaceWin::CommitAndClearPendingOverlays() {
249 pending_overlays_.clear(); 312 pending_overlays_.clear();
250 return true; 313 return true;
251 } 314 }
252 315
253 bool DirectCompositionSurfaceWin::FlipsVertically() const { 316 bool DirectCompositionSurfaceWin::FlipsVertically() const {
254 return true; 317 return true;
255 } 318 }
256 319
257 bool DirectCompositionSurfaceWin::SupportsPostSubBuffer() { 320 bool DirectCompositionSurfaceWin::SupportsPostSubBuffer() {
258 return true; 321 return true;
259 } 322 }
260 323
261 bool DirectCompositionSurfaceWin::OnMakeCurrent(gl::GLContext* context) { 324 bool DirectCompositionSurfaceWin::OnMakeCurrent(gl::GLContext* context) {
262 if (g_current_surface != dcomp_surface_) { 325 if (g_current_surface != dcomp_surface_) {
263 if (g_current_surface) { 326 if (g_current_surface) {
264 HRESULT hr = g_current_surface->SuspendDraw(); 327 HRESULT hr = g_current_surface->SuspendDraw();
265 CHECK(SUCCEEDED(hr)); 328 CHECK(SUCCEEDED(hr));
266 g_current_surface = nullptr; 329 g_current_surface = nullptr;
267 } 330 }
268 if (draw_texture_) { 331 if (draw_texture_) {
269 HRESULT hr = dcomp_surface_->ResumeDraw(); 332 HRESULT hr = dcomp_surface_->ResumeDraw();
270 CHECK(SUCCEEDED(hr)); 333 CHECK(SUCCEEDED(hr));
271 g_current_surface = dcomp_surface_.get(); 334 g_current_surface = dcomp_surface_.get();
272 } 335 }
273 } 336 }
274 return true; 337 return true;
275 } 338 }
276 339
277 bool DirectCompositionSurfaceWin::SupportsSetDrawRectangle() const { 340 bool DirectCompositionSurfaceWin::SupportsDCLayers() const {
278 return true; 341 return true;
279 } 342 }
280 343
281 bool DirectCompositionSurfaceWin::SetDrawRectangle(const gfx::Rect& rectangle) { 344 bool DirectCompositionSurfaceWin::SetDrawRectangle(const gfx::Rect& rectangle) {
282 if (draw_texture_) 345 if (draw_texture_)
283 return false; 346 return false;
347
348 DCHECK(!real_surface_);
349 ScopedReleaseCurrent release_current(this);
350
351 if ((enable_dc_layers_ && !dcomp_surface_) ||
352 (!enable_dc_layers_ && !swap_chain_)) {
353 ReleaseCurrentSurface();
354 InitializeSurface();
355 }
356
284 if (!gfx::Rect(size_).Contains(rectangle)) { 357 if (!gfx::Rect(size_).Contains(rectangle)) {
285 DLOG(ERROR) << "Draw rectangle must be contained within size of surface"; 358 DLOG(ERROR) << "Draw rectangle must be contained within size of surface";
286 return false; 359 return false;
287 } 360 }
288 if (gfx::Rect(size_) != rectangle && !has_been_rendered_to_) { 361 if (gfx::Rect(size_) != rectangle && !has_been_rendered_to_) {
289 DLOG(ERROR) << "First draw to surface must draw to everything"; 362 DLOG(ERROR) << "First draw to surface must draw to everything";
290 return false; 363 return false;
291 } 364 }
292 365
293 DCHECK(!real_surface_);
294 CHECK(!g_current_surface); 366 CHECK(!g_current_surface);
295 ScopedReleaseCurrent release_current(this);
296 367
297 RECT rect = rectangle.ToRECT(); 368 RECT rect = rectangle.ToRECT();
298 POINT update_offset; 369 if (dcomp_surface_) {
299 370 POINT update_offset;
300 HRESULT hr = dcomp_surface_->BeginDraw( 371 HRESULT hr = dcomp_surface_->BeginDraw(
301 &rect, IID_PPV_ARGS(draw_texture_.Receive()), &update_offset); 372 &rect, IID_PPV_ARGS(draw_texture_.Receive()), &update_offset);
302 CHECK(SUCCEEDED(hr)); 373 draw_offset_ = gfx::Point(update_offset) - gfx::Rect(rect).origin();
374 CHECK(SUCCEEDED(hr));
375 } else {
376 HRESULT hr =
377 swap_chain_->GetBuffer(0, IID_PPV_ARGS(draw_texture_.Receive()));
378 swap_rect_ = rectangle;
379 draw_offset_ = gfx::Vector2d();
380 CHECK(SUCCEEDED(hr));
381 }
303 has_been_rendered_to_ = true; 382 has_been_rendered_to_ = true;
304 383
305 draw_offset_ = gfx::Point(update_offset) - gfx::Rect(rect).origin();
306
307 g_current_surface = dcomp_surface_.get(); 384 g_current_surface = dcomp_surface_.get();
308 385
309 std::vector<EGLint> pbuffer_attribs{ 386 std::vector<EGLint> pbuffer_attribs{
310 EGL_WIDTH, 387 EGL_WIDTH,
311 size_.width(), 388 size_.width(),
312 EGL_HEIGHT, 389 EGL_HEIGHT,
313 size_.height(), 390 size_.height(),
314 EGL_FLEXIBLE_SURFACE_COMPATIBILITY_SUPPORTED_ANGLE, 391 EGL_FLEXIBLE_SURFACE_COMPATIBILITY_SUPPORTED_ANGLE,
315 EGL_TRUE, 392 EGL_TRUE,
316 EGL_NONE}; 393 EGL_NONE};
(...skipping 25 matching lines...) Expand all
342 transform(transform), 419 transform(transform),
343 image(image), 420 image(image),
344 bounds_rect(bounds_rect), 421 bounds_rect(bounds_rect),
345 crop_rect(crop_rect) {} 422 crop_rect(crop_rect) {}
346 423
347 DirectCompositionSurfaceWin::Overlay::Overlay(const Overlay& overlay) = default; 424 DirectCompositionSurfaceWin::Overlay::Overlay(const Overlay& overlay) = default;
348 425
349 DirectCompositionSurfaceWin::Overlay::~Overlay() {} 426 DirectCompositionSurfaceWin::Overlay::~Overlay() {}
350 427
351 } // namespace gpu 428 } // namespace gpu
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698