OLD | NEW |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 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 "ui/gl/gl_surface.h" | 5 #include "ui/gl/gl_surface.h" |
6 | 6 |
7 #include "base/bind.h" | 7 #include "base/bind.h" |
8 #include "base/callback.h" | 8 #include "base/callback.h" |
9 #include "base/location.h" | 9 #include "base/location.h" |
10 #include "base/logging.h" | 10 #include "base/logging.h" |
(...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
116 class GL_EXPORT GLSurfaceOzoneSurfaceless : public SurfacelessEGL { | 116 class GL_EXPORT GLSurfaceOzoneSurfaceless : public SurfacelessEGL { |
117 public: | 117 public: |
118 GLSurfaceOzoneSurfaceless(scoped_ptr<ui::SurfaceOzoneEGL> ozone_surface, | 118 GLSurfaceOzoneSurfaceless(scoped_ptr<ui::SurfaceOzoneEGL> ozone_surface, |
119 AcceleratedWidget widget) | 119 AcceleratedWidget widget) |
120 : SurfacelessEGL(gfx::Size()), | 120 : SurfacelessEGL(gfx::Size()), |
121 ozone_surface_(ozone_surface.Pass()), | 121 ozone_surface_(ozone_surface.Pass()), |
122 widget_(widget), | 122 widget_(widget), |
123 has_implicit_external_sync_( | 123 has_implicit_external_sync_( |
124 HasEGLExtension("EGL_ARM_implicit_external_sync")), | 124 HasEGLExtension("EGL_ARM_implicit_external_sync")), |
125 last_swap_buffers_result_(true), | 125 last_swap_buffers_result_(true), |
| 126 swap_buffers_pending_(false), |
126 weak_factory_(this) { | 127 weak_factory_(this) { |
127 unsubmitted_frames_.push_back(new PendingFrame()); | 128 unsubmitted_frames_.push_back(new PendingFrame()); |
128 } | 129 } |
129 | 130 |
130 bool Initialize() override { | 131 bool Initialize() override { |
131 if (!SurfacelessEGL::Initialize()) | 132 if (!SurfacelessEGL::Initialize()) |
132 return false; | 133 return false; |
133 vsync_provider_ = ozone_surface_->CreateVSyncProvider(); | 134 vsync_provider_ = ozone_surface_->CreateVSyncProvider(); |
134 if (!vsync_provider_) | 135 if (!vsync_provider_) |
135 return false; | 136 return false; |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
173 } | 174 } |
174 bool IsOffscreen() override { return false; } | 175 bool IsOffscreen() override { return false; } |
175 VSyncProvider* GetVSyncProvider() override { return vsync_provider_.get(); } | 176 VSyncProvider* GetVSyncProvider() override { return vsync_provider_.get(); } |
176 bool SupportsPostSubBuffer() override { return true; } | 177 bool SupportsPostSubBuffer() override { return true; } |
177 bool PostSubBuffer(int x, int y, int width, int height) override { | 178 bool PostSubBuffer(int x, int y, int width, int height) override { |
178 // The actual sub buffer handling is handled at higher layers. | 179 // The actual sub buffer handling is handled at higher layers. |
179 SwapBuffers(); | 180 SwapBuffers(); |
180 return true; | 181 return true; |
181 } | 182 } |
182 bool SwapBuffersAsync(const SwapCompletionCallback& callback) override { | 183 bool SwapBuffersAsync(const SwapCompletionCallback& callback) override { |
| 184 // If last swap failed, don't try to schedule new ones. |
| 185 if (!last_swap_buffers_result_) |
| 186 return false; |
| 187 |
183 glFlush(); | 188 glFlush(); |
| 189 |
| 190 base::Closure surface_swap_callback = |
| 191 base::Bind(&GLSurfaceOzoneSurfaceless::SwapCompleted, |
| 192 weak_factory_.GetWeakPtr(), callback); |
| 193 |
| 194 PendingFrame* frame = unsubmitted_frames_.back(); |
| 195 frame->callback = surface_swap_callback; |
| 196 unsubmitted_frames_.push_back(new PendingFrame()); |
| 197 |
184 // TODO: the following should be replaced by a per surface flush as it gets | 198 // TODO: the following should be replaced by a per surface flush as it gets |
185 // implemented in GL drivers. | 199 // implemented in GL drivers. |
186 if (has_implicit_external_sync_) { | 200 if (has_implicit_external_sync_) { |
187 // If last swap failed, don't try to schedule new ones. | |
188 if (!last_swap_buffers_result_) { | |
189 last_swap_buffers_result_ = true; | |
190 return false; | |
191 } | |
192 | |
193 EGLSyncKHR fence = InsertFence(); | 201 EGLSyncKHR fence = InsertFence(); |
194 if (!fence) | 202 if (!fence) |
195 return false; | 203 return false; |
196 | 204 |
197 base::Closure fence_wait_task = | 205 base::Closure fence_wait_task = |
198 base::Bind(&WaitForFence, GetDisplay(), fence); | 206 base::Bind(&WaitForFence, GetDisplay(), fence); |
199 | 207 |
200 PendingFrame* frame = unsubmitted_frames_.back(); | |
201 frame->callback = callback; | |
202 base::Closure fence_retired_callback = | 208 base::Closure fence_retired_callback = |
203 base::Bind(&GLSurfaceOzoneSurfaceless::FenceRetired, | 209 base::Bind(&GLSurfaceOzoneSurfaceless::FenceRetired, |
204 weak_factory_.GetWeakPtr(), fence, frame); | 210 weak_factory_.GetWeakPtr(), fence, frame); |
205 | 211 |
206 base::WorkerPool::PostTaskAndReply(FROM_HERE, fence_wait_task, | 212 base::WorkerPool::PostTaskAndReply(FROM_HERE, fence_wait_task, |
207 fence_retired_callback, false); | 213 fence_retired_callback, false); |
208 unsubmitted_frames_.push_back(new PendingFrame()); | |
209 return true; | 214 return true; |
210 } else if (ozone_surface_->IsUniversalDisplayLinkDevice()) { | 215 } else if (ozone_surface_->IsUniversalDisplayLinkDevice()) { |
211 glFinish(); | 216 glFinish(); |
212 } | 217 } |
213 unsubmitted_frames_.back()->ScheduleOverlayPlanes(widget_); | 218 |
214 unsubmitted_frames_.back()->overlays.clear(); | 219 frame->ready = true; |
215 return ozone_surface_->OnSwapBuffersAsync(callback); | 220 SubmitFrame(); |
| 221 return last_swap_buffers_result_; |
216 } | 222 } |
217 bool PostSubBufferAsync(int x, | 223 bool PostSubBufferAsync(int x, |
218 int y, | 224 int y, |
219 int width, | 225 int width, |
220 int height, | 226 int height, |
221 const SwapCompletionCallback& callback) override { | 227 const SwapCompletionCallback& callback) override { |
222 return SwapBuffersAsync(callback); | 228 return SwapBuffersAsync(callback); |
223 } | 229 } |
224 | 230 |
225 protected: | 231 protected: |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
258 } | 264 } |
259 bool ready; | 265 bool ready; |
260 std::vector<Overlay> overlays; | 266 std::vector<Overlay> overlays; |
261 SwapCompletionCallback callback; | 267 SwapCompletionCallback callback; |
262 }; | 268 }; |
263 | 269 |
264 ~GLSurfaceOzoneSurfaceless() override { | 270 ~GLSurfaceOzoneSurfaceless() override { |
265 Destroy(); // EGL surface must be destroyed before SurfaceOzone | 271 Destroy(); // EGL surface must be destroyed before SurfaceOzone |
266 } | 272 } |
267 | 273 |
268 void SubmitFrames() { | 274 void SubmitFrame() { |
269 while (!unsubmitted_frames_.empty() && unsubmitted_frames_.front()->ready) { | 275 DCHECK(!unsubmitted_frames_.empty()); |
270 PendingFrame* frame = unsubmitted_frames_.front(); | 276 |
| 277 if (unsubmitted_frames_.front()->ready && !swap_buffers_pending_) { |
| 278 scoped_ptr<PendingFrame> frame(unsubmitted_frames_.front()); |
| 279 unsubmitted_frames_.weak_erase(unsubmitted_frames_.begin()); |
| 280 swap_buffers_pending_ = true; |
| 281 |
271 last_swap_buffers_result_ = | 282 last_swap_buffers_result_ = |
272 last_swap_buffers_result_ && frame->ScheduleOverlayPlanes(widget_) && | 283 frame->ScheduleOverlayPlanes(widget_) && |
273 ozone_surface_->OnSwapBuffersAsync(frame->callback); | 284 ozone_surface_->OnSwapBuffersAsync(frame->callback); |
274 unsubmitted_frames_.erase(unsubmitted_frames_.begin()); | |
275 } | 285 } |
276 } | 286 } |
277 | 287 |
278 EGLSyncKHR InsertFence() { | 288 EGLSyncKHR InsertFence() { |
279 const EGLint attrib_list[] = {EGL_SYNC_CONDITION_KHR, | 289 const EGLint attrib_list[] = {EGL_SYNC_CONDITION_KHR, |
280 EGL_SYNC_PRIOR_COMMANDS_IMPLICIT_EXTERNAL_ARM, | 290 EGL_SYNC_PRIOR_COMMANDS_IMPLICIT_EXTERNAL_ARM, |
281 EGL_NONE}; | 291 EGL_NONE}; |
282 return eglCreateSyncKHR(GetDisplay(), EGL_SYNC_FENCE_KHR, attrib_list); | 292 return eglCreateSyncKHR(GetDisplay(), EGL_SYNC_FENCE_KHR, attrib_list); |
283 } | 293 } |
284 | 294 |
285 void FenceRetired(EGLSyncKHR fence, PendingFrame* frame) { | 295 void FenceRetired(EGLSyncKHR fence, PendingFrame* frame) { |
286 eglDestroySyncKHR(GetDisplay(), fence); | 296 eglDestroySyncKHR(GetDisplay(), fence); |
287 frame->ready = true; | 297 frame->ready = true; |
288 SubmitFrames(); | 298 SubmitFrame(); |
| 299 } |
| 300 |
| 301 void SwapCompleted(const SwapCompletionCallback& callback) { |
| 302 callback.Run(); |
| 303 swap_buffers_pending_ = false; |
| 304 |
| 305 SubmitFrame(); |
289 } | 306 } |
290 | 307 |
291 // The native surface. Deleting this is allowed to free the EGLNativeWindow. | 308 // The native surface. Deleting this is allowed to free the EGLNativeWindow. |
292 scoped_ptr<ui::SurfaceOzoneEGL> ozone_surface_; | 309 scoped_ptr<ui::SurfaceOzoneEGL> ozone_surface_; |
293 AcceleratedWidget widget_; | 310 AcceleratedWidget widget_; |
294 scoped_ptr<VSyncProvider> vsync_provider_; | 311 scoped_ptr<VSyncProvider> vsync_provider_; |
295 ScopedVector<PendingFrame> unsubmitted_frames_; | 312 ScopedVector<PendingFrame> unsubmitted_frames_; |
296 bool has_implicit_external_sync_; | 313 bool has_implicit_external_sync_; |
297 bool last_swap_buffers_result_; | 314 bool last_swap_buffers_result_; |
| 315 bool swap_buffers_pending_; |
298 | 316 |
299 base::WeakPtrFactory<GLSurfaceOzoneSurfaceless> weak_factory_; | 317 base::WeakPtrFactory<GLSurfaceOzoneSurfaceless> weak_factory_; |
300 | 318 |
301 DISALLOW_COPY_AND_ASSIGN(GLSurfaceOzoneSurfaceless); | 319 DISALLOW_COPY_AND_ASSIGN(GLSurfaceOzoneSurfaceless); |
302 }; | 320 }; |
303 | 321 |
304 // This provides surface-like semantics implemented through surfaceless. | 322 // This provides surface-like semantics implemented through surfaceless. |
305 // A framebuffer is bound automatically. | 323 // A framebuffer is bound automatically. |
306 class GL_EXPORT GLSurfaceOzoneSurfacelessSurfaceImpl | 324 class GL_EXPORT GLSurfaceOzoneSurfacelessSurfaceImpl |
307 : public GLSurfaceOzoneSurfaceless { | 325 : public GLSurfaceOzoneSurfaceless { |
(...skipping 255 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
563 NOTREACHED(); | 581 NOTREACHED(); |
564 return NULL; | 582 return NULL; |
565 } | 583 } |
566 } | 584 } |
567 | 585 |
568 EGLNativeDisplayType GetPlatformDefaultEGLNativeDisplay() { | 586 EGLNativeDisplayType GetPlatformDefaultEGLNativeDisplay() { |
569 return ui::SurfaceFactoryOzone::GetInstance()->GetNativeDisplay(); | 587 return ui::SurfaceFactoryOzone::GetInstance()->GetNativeDisplay(); |
570 } | 588 } |
571 | 589 |
572 } // namespace gfx | 590 } // namespace gfx |
OLD | NEW |