| OLD | NEW |
| 1 // Copyright 2016 The Chromium Authors. All rights reserved. | 1 // Copyright 2016 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/ozone/platform/drm/gpu/gbm_surfaceless.h" | 5 #include "ui/ozone/platform/drm/gpu/gbm_surfaceless.h" |
| 6 | 6 |
| 7 #include <utility> | 7 #include <utility> |
| 8 | 8 |
| 9 #include "base/bind.h" | 9 #include "base/bind.h" |
| 10 #include "base/logging.h" | 10 #include "base/logging.h" |
| 11 #include "base/memory/ptr_util.h" | 11 #include "base/memory/ptr_util.h" |
| 12 #include "base/threading/worker_pool.h" | |
| 13 #include "base/trace_event/trace_event.h" | 12 #include "base/trace_event/trace_event.h" |
| 14 #include "ui/ozone/common/egl_util.h" | 13 #include "ui/ozone/common/egl_util.h" |
| 15 #include "ui/ozone/platform/drm/gpu/drm_vsync_provider.h" | 14 #include "ui/ozone/platform/drm/gpu/drm_vsync_provider.h" |
| 16 #include "ui/ozone/platform/drm/gpu/drm_window_proxy.h" | 15 #include "ui/ozone/platform/drm/gpu/drm_window_proxy.h" |
| 17 #include "ui/ozone/platform/drm/gpu/gbm_surface_factory.h" | 16 #include "ui/ozone/platform/drm/gpu/gbm_surface_factory.h" |
| 18 #include "ui/ozone/platform/drm/gpu/scanout_buffer.h" | 17 #include "ui/ozone/platform/drm/gpu/scanout_buffer.h" |
| 19 | 18 |
| 20 namespace ui { | 19 namespace ui { |
| 21 | 20 |
| 22 namespace { | |
| 23 | |
| 24 void WaitForFence(EGLDisplay display, EGLSyncKHR fence) { | |
| 25 eglClientWaitSyncKHR(display, fence, EGL_SYNC_FLUSH_COMMANDS_BIT_KHR, | |
| 26 EGL_FOREVER_KHR); | |
| 27 } | |
| 28 | |
| 29 } // namespace | |
| 30 | |
| 31 GbmSurfaceless::GbmSurfaceless(GbmSurfaceFactory* surface_factory, | 21 GbmSurfaceless::GbmSurfaceless(GbmSurfaceFactory* surface_factory, |
| 32 std::unique_ptr<DrmWindowProxy> window, | 22 std::unique_ptr<DrmWindowProxy> window, |
| 33 gfx::AcceleratedWidget widget) | 23 gfx::AcceleratedWidget widget) |
| 34 : SurfacelessEGL(gfx::Size()), | 24 : SurfacelessEGL(gfx::Size()), |
| 35 surface_factory_(surface_factory), | 25 surface_factory_(surface_factory), |
| 36 window_(std::move(window)), | 26 window_(std::move(window)), |
| 37 widget_(widget), | 27 widget_(widget), |
| 38 has_implicit_external_sync_( | 28 has_implicit_external_sync_( |
| 39 HasEGLExtension("EGL_ARM_implicit_external_sync")), | 29 HasEGLExtension("EGL_ARM_implicit_external_sync")), |
| 40 has_image_flush_external_( | 30 has_image_flush_external_( |
| (...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 111 SwapCompletionCallback surface_swap_callback = base::Bind( | 101 SwapCompletionCallback surface_swap_callback = base::Bind( |
| 112 &GbmSurfaceless::SwapCompleted, weak_factory_.GetWeakPtr(), callback); | 102 &GbmSurfaceless::SwapCompleted, weak_factory_.GetWeakPtr(), callback); |
| 113 | 103 |
| 114 PendingFrame* frame = unsubmitted_frames_.back(); | 104 PendingFrame* frame = unsubmitted_frames_.back(); |
| 115 frame->callback = surface_swap_callback; | 105 frame->callback = surface_swap_callback; |
| 116 unsubmitted_frames_.push_back(new PendingFrame()); | 106 unsubmitted_frames_.push_back(new PendingFrame()); |
| 117 | 107 |
| 118 // TODO: the following should be replaced by a per surface flush as it gets | 108 // TODO: the following should be replaced by a per surface flush as it gets |
| 119 // implemented in GL drivers. | 109 // implemented in GL drivers. |
| 120 if (has_implicit_external_sync_ || has_image_flush_external_) { | 110 if (has_implicit_external_sync_ || has_image_flush_external_) { |
| 121 EGLSyncKHR fence = InsertFence(has_implicit_external_sync_); | 111 const EGLint attrib_list[] = {EGL_SYNC_CONDITION_KHR, |
| 122 if (!fence) { | 112 EGL_SYNC_PRIOR_COMMANDS_IMPLICIT_EXTERNAL_ARM, |
| 113 EGL_NONE}; |
| 114 base::Closure frame_ready_callback = base::Bind( |
| 115 &GbmSurfaceless::FrameReady, weak_factory_.GetWeakPtr(), frame); |
| 116 if (!InsertSyncFence(has_implicit_external_sync_ ? attrib_list : nullptr, |
| 117 frame_ready_callback)) { |
| 123 callback.Run(gfx::SwapResult::SWAP_FAILED); | 118 callback.Run(gfx::SwapResult::SWAP_FAILED); |
| 124 return; | 119 return; |
| 125 } | 120 } |
| 126 | 121 |
| 127 base::Closure fence_wait_task = | |
| 128 base::Bind(&WaitForFence, GetDisplay(), fence); | |
| 129 | |
| 130 base::Closure fence_retired_callback = | |
| 131 base::Bind(&GbmSurfaceless::FenceRetired, weak_factory_.GetWeakPtr(), | |
| 132 fence, frame); | |
| 133 | |
| 134 base::WorkerPool::PostTaskAndReply(FROM_HERE, fence_wait_task, | |
| 135 fence_retired_callback, false); | |
| 136 return; // Defer frame submission until fence signals. | 122 return; // Defer frame submission until fence signals. |
| 137 } | 123 } |
| 138 | 124 |
| 139 frame->ready = true; | 125 FrameReady(frame); |
| 140 SubmitFrame(); | |
| 141 } | 126 } |
| 142 | 127 |
| 143 void GbmSurfaceless::PostSubBufferAsync( | 128 void GbmSurfaceless::PostSubBufferAsync( |
| 144 int x, | 129 int x, |
| 145 int y, | 130 int y, |
| 146 int width, | 131 int width, |
| 147 int height, | 132 int height, |
| 148 const SwapCompletionCallback& callback) { | 133 const SwapCompletionCallback& callback) { |
| 149 // The actual sub buffer handling is handled at higher layers. | 134 // The actual sub buffer handling is handled at higher layers. |
| 150 SwapBuffersAsync(callback); | 135 SwapBuffersAsync(callback); |
| (...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 210 } | 195 } |
| 211 | 196 |
| 212 if (IsUniversalDisplayLinkDevice()) | 197 if (IsUniversalDisplayLinkDevice()) |
| 213 glFinish(); | 198 glFinish(); |
| 214 | 199 |
| 215 window_->SchedulePageFlip(planes_, frame->callback); | 200 window_->SchedulePageFlip(planes_, frame->callback); |
| 216 planes_.clear(); | 201 planes_.clear(); |
| 217 } | 202 } |
| 218 } | 203 } |
| 219 | 204 |
| 220 EGLSyncKHR GbmSurfaceless::InsertFence(bool implicit) { | 205 void GbmSurfaceless::FrameReady(PendingFrame* frame) { |
| 221 const EGLint attrib_list[] = {EGL_SYNC_CONDITION_KHR, | |
| 222 EGL_SYNC_PRIOR_COMMANDS_IMPLICIT_EXTERNAL_ARM, | |
| 223 EGL_NONE}; | |
| 224 return eglCreateSyncKHR(GetDisplay(), EGL_SYNC_FENCE_KHR, | |
| 225 implicit ? attrib_list : NULL); | |
| 226 } | |
| 227 | |
| 228 void GbmSurfaceless::FenceRetired(EGLSyncKHR fence, PendingFrame* frame) { | |
| 229 eglDestroySyncKHR(GetDisplay(), fence); | |
| 230 frame->ready = true; | 206 frame->ready = true; |
| 231 SubmitFrame(); | 207 SubmitFrame(); |
| 232 } | 208 } |
| 233 | 209 |
| 234 void GbmSurfaceless::SwapCompleted(const SwapCompletionCallback& callback, | 210 void GbmSurfaceless::SwapCompleted(const SwapCompletionCallback& callback, |
| 235 gfx::SwapResult result) { | 211 gfx::SwapResult result) { |
| 236 callback.Run(result); | 212 callback.Run(result); |
| 237 swap_buffers_pending_ = false; | 213 swap_buffers_pending_ = false; |
| 238 if (result == gfx::SwapResult::SWAP_FAILED) { | 214 if (result == gfx::SwapResult::SWAP_FAILED) { |
| 239 last_swap_buffers_result_ = false; | 215 last_swap_buffers_result_ = false; |
| 240 return; | 216 return; |
| 241 } | 217 } |
| 242 | 218 |
| 243 SubmitFrame(); | 219 SubmitFrame(); |
| 244 } | 220 } |
| 245 | 221 |
| 246 bool GbmSurfaceless::IsUniversalDisplayLinkDevice() { | 222 bool GbmSurfaceless::IsUniversalDisplayLinkDevice() { |
| 247 return planes_.empty() ? false : planes_[0].buffer->RequiresGlFinish(); | 223 return planes_.empty() ? false : planes_[0].buffer->RequiresGlFinish(); |
| 248 } | 224 } |
| 249 | 225 |
| 250 } // namespace ui | 226 } // namespace ui |
| OLD | NEW |