| OLD | NEW |
| 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 Loading... |
| 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, ¶ms); |
| 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 Loading... |
| 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 |
| OLD | NEW |