Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(86)

Side by Side Diff: ui/ozone/platform/drm/gpu/gl_surface_gbm_surfaceless.cc

Issue 2165303002: Convert Ozone GBM to use new surface API. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@ozone_impl
Patch Set: Small fixes. Created 4 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
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
3 // found in the LICENSE file.
4
5 #include "ui/ozone/platform/drm/gpu/gl_surface_gbm_surfaceless.h"
6
7 #include <utility>
8
9 #include "base/bind.h"
10 #include "base/logging.h"
11 #include "base/memory/ptr_util.h"
12 #include "base/threading/worker_pool.h"
13 #include "base/trace_event/trace_event.h"
14 #include "ui/ozone/common/egl_util.h"
15 #include "ui/ozone/platform/drm/gpu/drm_vsync_provider.h"
16 #include "ui/ozone/platform/drm/gpu/drm_window_proxy.h"
17 #include "ui/ozone/platform/drm/gpu/gbm_surface_factory.h"
18 #include "ui/ozone/platform/drm/gpu/scanout_buffer.h"
19
20 namespace ui {
21
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 } // namespace
29
30 GLSurfaceGbmSurfaceless::PendingFrame::PendingFrame() : ready(false) {}
31
32 GLSurfaceGbmSurfaceless::PendingFrame::~PendingFrame() {}
33
34 bool GLSurfaceGbmSurfaceless::PendingFrame::ScheduleOverlayPlanes(
35 gfx::AcceleratedWidget widget) {
36 for (const auto& overlay : overlays)
37 if (!overlay.ScheduleOverlayPlane(widget))
38 return false;
39 return true;
40 }
41
42 void GLSurfaceGbmSurfaceless::PendingFrame::Flush() {
43 for (const auto& overlay : overlays)
44 overlay.Flush();
45 }
46
47 GLSurfaceGbmSurfaceless::GLSurfaceGbmSurfaceless(
48 std::unique_ptr<DrmWindowProxy> window,
49 GbmSurfaceFactory* surface_manager,
50 gfx::AcceleratedWidget widget)
51 : SurfacelessEGL(gfx::Size()),
52 window_(std::move(window)),
53 surface_manager_(surface_manager),
54 widget_(widget),
55 has_implicit_external_sync_(
56 HasEGLExtension("EGL_ARM_implicit_external_sync")),
57 has_image_flush_external_(
58 HasEGLExtension("EGL_EXT_image_flush_external")),
59 last_swap_buffers_result_(true),
60 swap_buffers_pending_(false),
61 weak_factory_(this) {
62 surface_manager_->RegisterSurface(window_->widget(), this);
63 unsubmitted_frames_.push_back(new PendingFrame());
64 }
65
66 void GLSurfaceGbmSurfaceless::QueueOverlayPlane(const OverlayPlane& plane) {
67 planes_.push_back(plane);
68 }
69
70 bool GLSurfaceGbmSurfaceless::Initialize(gl::GLSurface::Format format) {
71 if (!SurfacelessEGL::Initialize(format))
72 return false;
73 vsync_provider_ = base::MakeUnique<DrmVSyncProvider>(window_.get());
74 if (!vsync_provider_)
75 return false;
76 return true;
77 }
78
79 gfx::SwapResult GLSurfaceGbmSurfaceless::SwapBuffers() {
80 return gfx::SwapResult::SWAP_FAILED;
dnicoara 2016/07/21 17:41:38 nit: Add a NOTREACHED() just in case.
kylechar 2016/07/21 18:34:07 Done.
81 }
82
83 bool GLSurfaceGbmSurfaceless::ScheduleOverlayPlane(
84 int z_order,
85 gfx::OverlayTransform transform,
86 gl::GLImage* image,
87 const gfx::Rect& bounds_rect,
88 const gfx::RectF& crop_rect) {
89 unsubmitted_frames_.back()->overlays.push_back(
90 gl::GLSurfaceOverlay(z_order, transform, image, bounds_rect, crop_rect));
91 return true;
92 }
93
94 bool GLSurfaceGbmSurfaceless::IsOffscreen() {
95 return false;
96 }
97
98 gfx::VSyncProvider* GLSurfaceGbmSurfaceless::GetVSyncProvider() {
99 return vsync_provider_.get();
100 }
101
102 bool GLSurfaceGbmSurfaceless::SupportsAsyncSwap() {
103 return true;
104 }
105
106 bool GLSurfaceGbmSurfaceless::SupportsPostSubBuffer() {
107 return true;
108 }
109
110 gfx::SwapResult GLSurfaceGbmSurfaceless::PostSubBuffer(int x,
111 int y,
112 int width,
113 int height) {
114 // The actual sub buffer handling is handled at higher layers.
115 NOTREACHED();
116 return gfx::SwapResult::SWAP_FAILED;
117 }
118
119 void GLSurfaceGbmSurfaceless::SwapBuffersAsync(
120 const SwapCompletionCallback& callback) {
121 TRACE_EVENT0("drm", "GLSurfaceGbmSurfaceless::SwapBuffersAsync");
122 // If last swap failed, don't try to schedule new ones.
123 if (!last_swap_buffers_result_) {
124 callback.Run(gfx::SwapResult::SWAP_FAILED);
125 return;
126 }
127
128 glFlush();
129 unsubmitted_frames_.back()->Flush();
130
131 SwapCompletionCallback surface_swap_callback =
132 base::Bind(&GLSurfaceGbmSurfaceless::SwapCompleted,
133 weak_factory_.GetWeakPtr(), callback);
134
135 PendingFrame* frame = unsubmitted_frames_.back();
136 frame->callback = surface_swap_callback;
137 unsubmitted_frames_.push_back(new PendingFrame());
138
139 // TODO: the following should be replaced by a per surface flush as it gets
140 // implemented in GL drivers.
141 if (has_implicit_external_sync_ || has_image_flush_external_) {
142 EGLSyncKHR fence = InsertFence(has_implicit_external_sync_);
143 if (!fence) {
144 callback.Run(gfx::SwapResult::SWAP_FAILED);
145 return;
146 }
147
148 base::Closure fence_wait_task =
149 base::Bind(&WaitForFence, GetDisplay(), fence);
150
151 base::Closure fence_retired_callback =
152 base::Bind(&GLSurfaceGbmSurfaceless::FenceRetired,
153 weak_factory_.GetWeakPtr(), fence, frame);
154
155 base::WorkerPool::PostTaskAndReply(FROM_HERE, fence_wait_task,
156 fence_retired_callback, false);
157 return; // Defer frame submission until fence signals.
158 }
159
160 frame->ready = true;
161 SubmitFrame();
162 }
163
164 void GLSurfaceGbmSurfaceless::PostSubBufferAsync(
165 int x,
166 int y,
167 int width,
168 int height,
169 const SwapCompletionCallback& callback) {
170 // The actual sub buffer handling is handled at higher layers.
171 SwapBuffersAsync(callback);
172 }
173
174 EGLConfig GLSurfaceGbmSurfaceless::GetConfig() {
175 if (!config_) {
176 EGLint config_attribs[] = {EGL_BUFFER_SIZE,
177 32,
178 EGL_ALPHA_SIZE,
179 8,
180 EGL_BLUE_SIZE,
181 8,
182 EGL_GREEN_SIZE,
183 8,
184 EGL_RED_SIZE,
185 8,
186 EGL_RENDERABLE_TYPE,
187 EGL_OPENGL_ES2_BIT,
188 EGL_SURFACE_TYPE,
189 EGL_DONT_CARE,
190 EGL_NONE};
191 config_ = ChooseEGLConfig(GetDisplay(), config_attribs);
192 }
193 return config_;
194 }
195
196 GLSurfaceGbmSurfaceless::~GLSurfaceGbmSurfaceless() {
197 Destroy(); // The EGL surface must be destroyed before SurfaceOzone.
198 surface_manager_->UnregisterSurface(window_->widget());
199 }
200
201 void GLSurfaceGbmSurfaceless::SubmitFrame() {
202 DCHECK(!unsubmitted_frames_.empty());
203
204 if (unsubmitted_frames_.front()->ready && !swap_buffers_pending_) {
205 std::unique_ptr<PendingFrame> frame(unsubmitted_frames_.front());
206 unsubmitted_frames_.weak_erase(unsubmitted_frames_.begin());
207 swap_buffers_pending_ = true;
208
209 if (!frame->ScheduleOverlayPlanes(widget_)) {
210 // |callback| is a wrapper for SwapCompleted(). Call it to properly
211 // propagate the failed state.
212 frame->callback.Run(gfx::SwapResult::SWAP_FAILED);
213 return;
214 }
215
216 if (IsUniversalDisplayLinkDevice())
217 glFinish();
218
219 window_->SchedulePageFlip(planes_, frame->callback);
220 planes_.clear();
221 }
222 }
223
224 EGLSyncKHR GLSurfaceGbmSurfaceless::InsertFence(bool implicit) {
225 const EGLint attrib_list[] = {EGL_SYNC_CONDITION_KHR,
226 EGL_SYNC_PRIOR_COMMANDS_IMPLICIT_EXTERNAL_ARM,
227 EGL_NONE};
228 return eglCreateSyncKHR(GetDisplay(), EGL_SYNC_FENCE_KHR,
229 implicit ? attrib_list : NULL);
230 }
231
232 void GLSurfaceGbmSurfaceless::FenceRetired(EGLSyncKHR fence,
233 PendingFrame* frame) {
234 eglDestroySyncKHR(GetDisplay(), fence);
235 frame->ready = true;
236 SubmitFrame();
237 }
238
239 void GLSurfaceGbmSurfaceless::SwapCompleted(
240 const SwapCompletionCallback& callback,
241 gfx::SwapResult result) {
242 callback.Run(result);
243 swap_buffers_pending_ = false;
244 if (result == gfx::SwapResult::SWAP_FAILED) {
245 last_swap_buffers_result_ = false;
246 return;
247 }
248
249 SubmitFrame();
250 }
251
252 bool GLSurfaceGbmSurfaceless::IsUniversalDisplayLinkDevice() {
253 return planes_.empty() ? false : planes_[0].buffer->RequiresGlFinish();
254 }
255
256 } // namespace ui
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698