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

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

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