| 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 } |
| 213 unsubmitted_frames_.back()->ScheduleOverlayPlanes(widget_); |
| 214 unsubmitted_frames_.back()->overlays.clear(); |
| 203 return ozone_surface_->OnSwapBuffersAsync(callback); | 215 return ozone_surface_->OnSwapBuffersAsync(callback); |
| 204 } | 216 } |
| 205 bool PostSubBufferAsync(int x, | 217 bool PostSubBufferAsync(int x, |
| 206 int y, | 218 int y, |
| 207 int width, | 219 int width, |
| 208 int height, | 220 int height, |
| 209 const SwapCompletionCallback& callback) override { | 221 const SwapCompletionCallback& callback) override { |
| 210 return SwapBuffersAsync(callback); | 222 return SwapBuffersAsync(callback); |
| 211 } | 223 } |
| 212 | 224 |
| 213 protected: | 225 protected: |
| 226 struct PendingFrame { |
| 227 struct Overlay { |
| 228 Overlay(int z_order, |
| 229 OverlayTransform transform, |
| 230 GLImage* image, |
| 231 const Rect& bounds_rect, |
| 232 const RectF& crop_rect) |
| 233 : z_order(z_order), |
| 234 transform(transform), |
| 235 image(image), |
| 236 bounds_rect(bounds_rect), |
| 237 crop_rect(crop_rect) {} |
| 238 |
| 239 bool ScheduleOverlayPlane(gfx::AcceleratedWidget widget) const { |
| 240 return image->ScheduleOverlayPlane(widget, z_order, transform, |
| 241 bounds_rect, crop_rect); |
| 242 } |
| 243 |
| 244 int z_order; |
| 245 OverlayTransform transform; |
| 246 scoped_refptr<GLImage> image; |
| 247 Rect bounds_rect; |
| 248 RectF crop_rect; |
| 249 }; |
| 250 |
| 251 PendingFrame() : ready(false) {} |
| 252 |
| 253 bool ScheduleOverlayPlanes(gfx::AcceleratedWidget widget) { |
| 254 for (const auto& overlay : overlays) |
| 255 if (!overlay.ScheduleOverlayPlane(widget)) |
| 256 return false; |
| 257 return true; |
| 258 } |
| 259 bool ready; |
| 260 std::vector<Overlay> overlays; |
| 261 SwapCompletionCallback callback; |
| 262 }; |
| 263 |
| 214 ~GLSurfaceOzoneSurfaceless() override { | 264 ~GLSurfaceOzoneSurfaceless() override { |
| 215 Destroy(); // EGL surface must be destroyed before SurfaceOzone | 265 Destroy(); // EGL surface must be destroyed before SurfaceOzone |
| 216 } | 266 } |
| 217 | 267 |
| 268 void SubmitFrames() { |
| 269 while (!unsubmitted_frames_.empty() && unsubmitted_frames_.front()->ready) { |
| 270 PendingFrame* frame = unsubmitted_frames_.front(); |
| 271 last_swap_buffers_result_ = |
| 272 last_swap_buffers_result_ && frame->ScheduleOverlayPlanes(widget_) && |
| 273 ozone_surface_->OnSwapBuffersAsync(frame->callback); |
| 274 unsubmitted_frames_.erase(unsubmitted_frames_.begin()); |
| 275 } |
| 276 } |
| 277 |
| 218 EGLSyncKHR InsertFence() { | 278 EGLSyncKHR InsertFence() { |
| 219 const EGLint attrib_list[] = {EGL_SYNC_CONDITION_KHR, | 279 const EGLint attrib_list[] = {EGL_SYNC_CONDITION_KHR, |
| 220 EGL_SYNC_PRIOR_COMMANDS_IMPLICIT_EXTERNAL_ARM, | 280 EGL_SYNC_PRIOR_COMMANDS_IMPLICIT_EXTERNAL_ARM, |
| 221 EGL_NONE}; | 281 EGL_NONE}; |
| 222 return eglCreateSyncKHR(GetDisplay(), EGL_SYNC_FENCE_KHR, attrib_list); | 282 return eglCreateSyncKHR(GetDisplay(), EGL_SYNC_FENCE_KHR, attrib_list); |
| 223 } | 283 } |
| 224 | 284 |
| 225 void FenceRetired(EGLSyncKHR fence, const SwapCompletionCallback& callback) { | 285 void FenceRetired(EGLSyncKHR fence, PendingFrame* frame) { |
| 226 eglDestroySyncKHR(GetDisplay(), fence); | 286 eglDestroySyncKHR(GetDisplay(), fence); |
| 227 last_swap_buffers_result_ = ozone_surface_->OnSwapBuffersAsync(callback); | 287 frame->ready = true; |
| 288 SubmitFrames(); |
| 228 } | 289 } |
| 229 | 290 |
| 230 // The native surface. Deleting this is allowed to free the EGLNativeWindow. | 291 // The native surface. Deleting this is allowed to free the EGLNativeWindow. |
| 231 scoped_ptr<ui::SurfaceOzoneEGL> ozone_surface_; | 292 scoped_ptr<ui::SurfaceOzoneEGL> ozone_surface_; |
| 232 AcceleratedWidget widget_; | 293 AcceleratedWidget widget_; |
| 233 scoped_ptr<VSyncProvider> vsync_provider_; | 294 scoped_ptr<VSyncProvider> vsync_provider_; |
| 295 ScopedVector<PendingFrame> unsubmitted_frames_; |
| 234 bool has_implicit_external_sync_; | 296 bool has_implicit_external_sync_; |
| 235 bool last_swap_buffers_result_; | 297 bool last_swap_buffers_result_; |
| 236 | 298 |
| 237 base::WeakPtrFactory<GLSurfaceOzoneSurfaceless> weak_factory_; | 299 base::WeakPtrFactory<GLSurfaceOzoneSurfaceless> weak_factory_; |
| 238 | 300 |
| 239 DISALLOW_COPY_AND_ASSIGN(GLSurfaceOzoneSurfaceless); | 301 DISALLOW_COPY_AND_ASSIGN(GLSurfaceOzoneSurfaceless); |
| 240 }; | 302 }; |
| 241 | 303 |
| 242 // This provides surface-like semantics implemented through surfaceless. | 304 // This provides surface-like semantics implemented through surfaceless. |
| 243 // A framebuffer is bound automatically. | 305 // A framebuffer is bound automatically. |
| (...skipping 257 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 501 NOTREACHED(); | 563 NOTREACHED(); |
| 502 return NULL; | 564 return NULL; |
| 503 } | 565 } |
| 504 } | 566 } |
| 505 | 567 |
| 506 EGLNativeDisplayType GetPlatformDefaultEGLNativeDisplay() { | 568 EGLNativeDisplayType GetPlatformDefaultEGLNativeDisplay() { |
| 507 return ui::SurfaceFactoryOzone::GetInstance()->GetNativeDisplay(); | 569 return ui::SurfaceFactoryOzone::GetInstance()->GetNativeDisplay(); |
| 508 } | 570 } |
| 509 | 571 |
| 510 } // namespace gfx | 572 } // namespace gfx |
| OLD | NEW |