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" |
11 #include "base/memory/ref_counted.h" | 11 #include "base/memory/ref_counted.h" |
12 #include "base/memory/scoped_vector.h" | |
12 #include "base/memory/weak_ptr.h" | 13 #include "base/memory/weak_ptr.h" |
13 #include "base/threading/worker_pool.h" | 14 #include "base/threading/worker_pool.h" |
14 #include "ui/gfx/native_widget_types.h" | 15 #include "ui/gfx/native_widget_types.h" |
15 #include "ui/gl/gl_context.h" | 16 #include "ui/gl/gl_context.h" |
16 #include "ui/gl/gl_image.h" | 17 #include "ui/gl/gl_image.h" |
17 #include "ui/gl/gl_image_linux_dma_buffer.h" | 18 #include "ui/gl/gl_image_linux_dma_buffer.h" |
18 #include "ui/gl/gl_implementation.h" | 19 #include "ui/gl/gl_implementation.h" |
19 #include "ui/gl/gl_surface_egl.h" | 20 #include "ui/gl/gl_surface_egl.h" |
20 #include "ui/gl/gl_surface_osmesa.h" | 21 #include "ui/gl/gl_surface_osmesa.h" |
21 #include "ui/gl/gl_surface_stub.h" | 22 #include "ui/gl/gl_surface_stub.h" |
(...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
115 class GL_EXPORT GLSurfaceOzoneSurfaceless : public SurfacelessEGL { | 116 class GL_EXPORT GLSurfaceOzoneSurfaceless : public SurfacelessEGL { |
116 public: | 117 public: |
117 GLSurfaceOzoneSurfaceless(scoped_ptr<ui::SurfaceOzoneEGL> ozone_surface, | 118 GLSurfaceOzoneSurfaceless(scoped_ptr<ui::SurfaceOzoneEGL> ozone_surface, |
118 AcceleratedWidget widget) | 119 AcceleratedWidget widget) |
119 : SurfacelessEGL(gfx::Size()), | 120 : SurfacelessEGL(gfx::Size()), |
120 ozone_surface_(ozone_surface.Pass()), | 121 ozone_surface_(ozone_surface.Pass()), |
121 widget_(widget), | 122 widget_(widget), |
122 has_implicit_external_sync_( | 123 has_implicit_external_sync_( |
123 HasEGLExtension("EGL_ARM_implicit_external_sync")), | 124 HasEGLExtension("EGL_ARM_implicit_external_sync")), |
124 last_swap_buffers_result_(true), | 125 last_swap_buffers_result_(true), |
125 weak_factory_(this) {} | 126 weak_factory_(this) { |
127 unsubmitted_frames_.push_back(new PendingFrame()); | |
128 } | |
126 | 129 |
127 bool Initialize() override { | 130 bool Initialize() override { |
128 if (!SurfacelessEGL::Initialize()) | 131 if (!SurfacelessEGL::Initialize()) |
129 return false; | 132 return false; |
130 vsync_provider_ = ozone_surface_->CreateVSyncProvider(); | 133 vsync_provider_ = ozone_surface_->CreateVSyncProvider(); |
131 if (!vsync_provider_) | 134 if (!vsync_provider_) |
132 return false; | 135 return false; |
133 return true; | 136 return true; |
134 } | 137 } |
135 bool Resize(const gfx::Size& size) override { | 138 bool Resize(const gfx::Size& size) override { |
(...skipping 11 matching lines...) Expand all Loading... | |
147 if (!fence) | 150 if (!fence) |
148 return false; | 151 return false; |
149 | 152 |
150 EGLDisplay display = GetDisplay(); | 153 EGLDisplay display = GetDisplay(); |
151 WaitForFence(display, fence); | 154 WaitForFence(display, fence); |
152 eglDestroySyncKHR(display, fence); | 155 eglDestroySyncKHR(display, fence); |
153 } else if (ozone_surface_->IsUniversalDisplayLinkDevice()) { | 156 } else if (ozone_surface_->IsUniversalDisplayLinkDevice()) { |
154 glFinish(); | 157 glFinish(); |
155 } | 158 } |
156 | 159 |
160 unsubmitted_frames_.back()->ScheduleOverlayPlanes(widget_); | |
161 unsubmitted_frames_.back()->overlays.clear(); | |
162 | |
157 return ozone_surface_->OnSwapBuffers(); | 163 return ozone_surface_->OnSwapBuffers(); |
158 } | 164 } |
159 bool ScheduleOverlayPlane(int z_order, | 165 bool ScheduleOverlayPlane(int z_order, |
160 OverlayTransform transform, | 166 OverlayTransform transform, |
161 GLImage* image, | 167 GLImage* image, |
162 const Rect& bounds_rect, | 168 const Rect& bounds_rect, |
163 const RectF& crop_rect) override { | 169 const RectF& crop_rect) override { |
164 return image->ScheduleOverlayPlane( | 170 unsubmitted_frames_.back()->overlays.push_back(PendingFrame::Overlay( |
165 widget_, z_order, transform, bounds_rect, crop_rect); | 171 z_order, transform, image, bounds_rect, crop_rect)); |
172 return true; | |
166 } | 173 } |
167 bool IsOffscreen() override { return false; } | 174 bool IsOffscreen() override { return false; } |
168 VSyncProvider* GetVSyncProvider() override { return vsync_provider_.get(); } | 175 VSyncProvider* GetVSyncProvider() override { return vsync_provider_.get(); } |
169 bool SupportsPostSubBuffer() override { return true; } | 176 bool SupportsPostSubBuffer() override { return true; } |
170 bool PostSubBuffer(int x, int y, int width, int height) override { | 177 bool PostSubBuffer(int x, int y, int width, int height) override { |
171 // The actual sub buffer handling is handled at higher layers. | 178 // The actual sub buffer handling is handled at higher layers. |
172 SwapBuffers(); | 179 SwapBuffers(); |
173 return true; | 180 return true; |
174 } | 181 } |
175 bool SwapBuffersAsync(const SwapCompletionCallback& callback) override { | 182 bool SwapBuffersAsync(const SwapCompletionCallback& callback) override { |
176 glFlush(); | 183 glFlush(); |
177 // TODO: the following should be replaced by a per surface flush as it gets | 184 // TODO: the following should be replaced by a per surface flush as it gets |
178 // implemented in GL drivers. | 185 // implemented in GL drivers. |
179 if (has_implicit_external_sync_) { | 186 if (has_implicit_external_sync_) { |
180 // If last swap failed, don't try to schedule new ones. | 187 // If last swap failed, don't try to schedule new ones. |
181 if (!last_swap_buffers_result_) { | 188 if (!last_swap_buffers_result_) { |
182 last_swap_buffers_result_ = true; | 189 last_swap_buffers_result_ = true; |
183 return false; | 190 return false; |
184 } | 191 } |
185 | 192 |
186 EGLSyncKHR fence = InsertFence(); | 193 EGLSyncKHR fence = InsertFence(); |
187 if (!fence) | 194 if (!fence) |
188 return false; | 195 return false; |
189 | 196 |
190 base::Closure fence_wait_task = | 197 base::Closure fence_wait_task = |
191 base::Bind(&WaitForFence, GetDisplay(), fence); | 198 base::Bind(&WaitForFence, GetDisplay(), fence); |
192 | 199 |
200 PendingFrame* frame = unsubmitted_frames_.back(); | |
201 frame->callback = callback; | |
193 base::Closure fence_retired_callback = | 202 base::Closure fence_retired_callback = |
194 base::Bind(&GLSurfaceOzoneSurfaceless::FenceRetired, | 203 base::Bind(&GLSurfaceOzoneSurfaceless::FenceRetired, |
195 weak_factory_.GetWeakPtr(), fence, callback); | 204 weak_factory_.GetWeakPtr(), fence, frame); |
196 | 205 |
197 base::WorkerPool::PostTaskAndReply(FROM_HERE, fence_wait_task, | 206 base::WorkerPool::PostTaskAndReply(FROM_HERE, fence_wait_task, |
198 fence_retired_callback, false); | 207 fence_retired_callback, false); |
208 unsubmitted_frames_.push_back(new PendingFrame()); | |
199 return true; | 209 return true; |
200 } else if (ozone_surface_->IsUniversalDisplayLinkDevice()) { | 210 } else if (ozone_surface_->IsUniversalDisplayLinkDevice()) { |
201 glFinish(); | 211 glFinish(); |
202 } | 212 } |
alexst (slow to review)
2015/04/02 19:48:53
I think you are missing:
unsubmitted_frames_.back
| |
203 return ozone_surface_->OnSwapBuffersAsync(callback); | 213 return ozone_surface_->OnSwapBuffersAsync(callback); |
204 } | 214 } |
205 bool PostSubBufferAsync(int x, | 215 bool PostSubBufferAsync(int x, |
206 int y, | 216 int y, |
207 int width, | 217 int width, |
208 int height, | 218 int height, |
209 const SwapCompletionCallback& callback) override { | 219 const SwapCompletionCallback& callback) override { |
210 return SwapBuffersAsync(callback); | 220 return SwapBuffersAsync(callback); |
211 } | 221 } |
212 | 222 |
213 protected: | 223 protected: |
224 struct PendingFrame { | |
225 struct Overlay { | |
226 Overlay(int z_order, | |
227 OverlayTransform transform, | |
228 GLImage* image, | |
229 const Rect& bounds_rect, | |
230 const RectF& crop_rect) | |
231 : z_order(z_order), | |
232 transform(transform), | |
233 image(image), | |
234 bounds_rect(bounds_rect), | |
235 crop_rect(crop_rect) {} | |
236 | |
237 bool ScheduleOverlayPlane(gfx::AcceleratedWidget widget) const { | |
238 return image->ScheduleOverlayPlane(widget, z_order, transform, | |
239 bounds_rect, crop_rect); | |
240 } | |
241 | |
242 int z_order; | |
243 OverlayTransform transform; | |
244 scoped_refptr<GLImage> image; | |
245 const Rect& bounds_rect; | |
246 const RectF& crop_rect; | |
247 }; | |
248 | |
249 PendingFrame() : ready(false) {} | |
250 | |
251 bool ScheduleOverlayPlanes(gfx::AcceleratedWidget widget) { | |
252 for (const auto& overlay : overlays) | |
253 if (!overlay.ScheduleOverlayPlane(widget)) | |
254 return false; | |
255 return true; | |
256 } | |
257 bool ready; | |
258 std::vector<Overlay> overlays; | |
259 SwapCompletionCallback callback; | |
260 }; | |
261 | |
214 ~GLSurfaceOzoneSurfaceless() override { | 262 ~GLSurfaceOzoneSurfaceless() override { |
215 Destroy(); // EGL surface must be destroyed before SurfaceOzone | 263 Destroy(); // EGL surface must be destroyed before SurfaceOzone |
216 } | 264 } |
217 | 265 |
266 void SubmitFrames() { | |
267 while (!unsubmitted_frames_.empty() && unsubmitted_frames_.front()->ready) { | |
268 PendingFrame* frame = unsubmitted_frames_.front(); | |
269 last_swap_buffers_result_ = | |
270 last_swap_buffers_result_ && frame->ScheduleOverlayPlanes(widget_) && | |
271 ozone_surface_->OnSwapBuffersAsync(frame->callback); | |
272 unsubmitted_frames_.erase(unsubmitted_frames_.begin()); | |
273 } | |
274 } | |
275 | |
218 EGLSyncKHR InsertFence() { | 276 EGLSyncKHR InsertFence() { |
219 const EGLint attrib_list[] = {EGL_SYNC_CONDITION_KHR, | 277 const EGLint attrib_list[] = {EGL_SYNC_CONDITION_KHR, |
220 EGL_SYNC_PRIOR_COMMANDS_IMPLICIT_EXTERNAL_ARM, | 278 EGL_SYNC_PRIOR_COMMANDS_IMPLICIT_EXTERNAL_ARM, |
221 EGL_NONE}; | 279 EGL_NONE}; |
222 return eglCreateSyncKHR(GetDisplay(), EGL_SYNC_FENCE_KHR, attrib_list); | 280 return eglCreateSyncKHR(GetDisplay(), EGL_SYNC_FENCE_KHR, attrib_list); |
223 } | 281 } |
224 | 282 |
225 void FenceRetired(EGLSyncKHR fence, const SwapCompletionCallback& callback) { | 283 void FenceRetired(EGLSyncKHR fence, PendingFrame* frame) { |
226 eglDestroySyncKHR(GetDisplay(), fence); | 284 eglDestroySyncKHR(GetDisplay(), fence); |
227 last_swap_buffers_result_ = ozone_surface_->OnSwapBuffersAsync(callback); | 285 frame->ready = true; |
286 SubmitFrames(); | |
228 } | 287 } |
229 | 288 |
230 // The native surface. Deleting this is allowed to free the EGLNativeWindow. | 289 // The native surface. Deleting this is allowed to free the EGLNativeWindow. |
231 scoped_ptr<ui::SurfaceOzoneEGL> ozone_surface_; | 290 scoped_ptr<ui::SurfaceOzoneEGL> ozone_surface_; |
232 AcceleratedWidget widget_; | 291 AcceleratedWidget widget_; |
233 scoped_ptr<VSyncProvider> vsync_provider_; | 292 scoped_ptr<VSyncProvider> vsync_provider_; |
293 ScopedVector<PendingFrame> unsubmitted_frames_; | |
234 bool has_implicit_external_sync_; | 294 bool has_implicit_external_sync_; |
235 bool last_swap_buffers_result_; | 295 bool last_swap_buffers_result_; |
236 | 296 |
237 base::WeakPtrFactory<GLSurfaceOzoneSurfaceless> weak_factory_; | 297 base::WeakPtrFactory<GLSurfaceOzoneSurfaceless> weak_factory_; |
238 | 298 |
239 DISALLOW_COPY_AND_ASSIGN(GLSurfaceOzoneSurfaceless); | 299 DISALLOW_COPY_AND_ASSIGN(GLSurfaceOzoneSurfaceless); |
240 }; | 300 }; |
241 | 301 |
242 // This provides surface-like semantics implemented through surfaceless. | 302 // This provides surface-like semantics implemented through surfaceless. |
243 // A framebuffer is bound automatically. | 303 // A framebuffer is bound automatically. |
(...skipping 257 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
501 NOTREACHED(); | 561 NOTREACHED(); |
502 return NULL; | 562 return NULL; |
503 } | 563 } |
504 } | 564 } |
505 | 565 |
506 EGLNativeDisplayType GetPlatformDefaultEGLNativeDisplay() { | 566 EGLNativeDisplayType GetPlatformDefaultEGLNativeDisplay() { |
507 return ui::SurfaceFactoryOzone::GetInstance()->GetNativeDisplay(); | 567 return ui::SurfaceFactoryOzone::GetInstance()->GetNativeDisplay(); |
508 } | 568 } |
509 | 569 |
510 } // namespace gfx | 570 } // namespace gfx |
OLD | NEW |