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