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

Side by Side Diff: ui/ozone/platform/drm/gpu/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: Add missing dep. 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
« no previous file with comments | « ui/ozone/platform/drm/gpu/gbm_surfaceless.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2014 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"
10 #include "base/logging.h"
9 #include "base/memory/ptr_util.h" 11 #include "base/memory/ptr_util.h"
12 #include "base/threading/worker_pool.h"
10 #include "base/trace_event/trace_event.h" 13 #include "base/trace_event/trace_event.h"
11 #include "third_party/khronos/EGL/egl.h"
12 #include "ui/ozone/common/egl_util.h" 14 #include "ui/ozone/common/egl_util.h"
13 #include "ui/ozone/platform/drm/gpu/drm_device.h"
14 #include "ui/ozone/platform/drm/gpu/drm_vsync_provider.h" 15 #include "ui/ozone/platform/drm/gpu/drm_vsync_provider.h"
15 #include "ui/ozone/platform/drm/gpu/drm_window_proxy.h" 16 #include "ui/ozone/platform/drm/gpu/drm_window_proxy.h"
16 #include "ui/ozone/platform/drm/gpu/gbm_surface_factory.h" 17 #include "ui/ozone/platform/drm/gpu/gbm_surface_factory.h"
17 #include "ui/ozone/platform/drm/gpu/scanout_buffer.h" 18 #include "ui/ozone/platform/drm/gpu/scanout_buffer.h"
18 19
19 namespace ui { 20 namespace ui {
20 21
21 GbmSurfaceless::GbmSurfaceless(std::unique_ptr<DrmWindowProxy> window, 22 namespace {
22 GbmSurfaceFactory* surface_manager) 23
23 : window_(std::move(window)), surface_manager_(surface_manager) { 24 void WaitForFence(EGLDisplay display, EGLSyncKHR fence) {
24 surface_manager_->RegisterSurface(window_->widget(), this); 25 eglClientWaitSyncKHR(display, fence, EGL_SYNC_FLUSH_COMMANDS_BIT_KHR,
25 } 26 EGL_FOREVER_KHR);
26 27 }
27 GbmSurfaceless::~GbmSurfaceless() { 28
28 surface_manager_->UnregisterSurface(window_->widget()); 29 } // namespace
30
31 GbmSurfaceless::GbmSurfaceless(GbmSurfaceFactory* surface_factory,
32 std::unique_ptr<DrmWindowProxy> window,
33 gfx::AcceleratedWidget widget)
34 : SurfacelessEGL(gfx::Size()),
35 surface_factory_(surface_factory),
36 window_(std::move(window)),
37 widget_(widget),
38 has_implicit_external_sync_(
39 HasEGLExtension("EGL_ARM_implicit_external_sync")),
40 has_image_flush_external_(
41 HasEGLExtension("EGL_EXT_image_flush_external")),
42 weak_factory_(this) {
43 surface_factory_->RegisterSurface(window_->widget(), this);
44 unsubmitted_frames_.push_back(new PendingFrame());
29 } 45 }
30 46
31 void GbmSurfaceless::QueueOverlayPlane(const OverlayPlane& plane) { 47 void GbmSurfaceless::QueueOverlayPlane(const OverlayPlane& plane) {
32 planes_.push_back(plane); 48 planes_.push_back(plane);
33 } 49 }
34 50
35 intptr_t GbmSurfaceless::GetNativeWindow() { 51 bool GbmSurfaceless::Initialize(gl::GLSurface::Format format) {
52 if (!SurfacelessEGL::Initialize(format))
53 return false;
54 vsync_provider_ = base::MakeUnique<DrmVSyncProvider>(window_.get());
55 if (!vsync_provider_)
56 return false;
57 return true;
58 }
59
60 gfx::SwapResult GbmSurfaceless::SwapBuffers() {
36 NOTREACHED(); 61 NOTREACHED();
37 return 0; 62 return gfx::SwapResult::SWAP_FAILED;
38 } 63 }
39 64
40 bool GbmSurfaceless::ResizeNativeWindow(const gfx::Size& viewport_size) { 65 bool GbmSurfaceless::ScheduleOverlayPlane(int z_order,
41 return true; 66 gfx::OverlayTransform transform,
42 } 67 gl::GLImage* image,
43 68 const gfx::Rect& bounds_rect,
44 bool GbmSurfaceless::OnSwapBuffers() { 69 const gfx::RectF& crop_rect) {
70 unsubmitted_frames_.back()->overlays.push_back(
71 gl::GLSurfaceOverlay(z_order, transform, image, bounds_rect, crop_rect));
72 return true;
73 }
74
75 bool GbmSurfaceless::IsOffscreen() {
76 return false;
77 }
78
79 gfx::VSyncProvider* GbmSurfaceless::GetVSyncProvider() {
80 return vsync_provider_.get();
81 }
82
83 bool GbmSurfaceless::SupportsAsyncSwap() {
84 return true;
85 }
86
87 bool GbmSurfaceless::SupportsPostSubBuffer() {
88 return true;
89 }
90
91 gfx::SwapResult GbmSurfaceless::PostSubBuffer(int x,
92 int y,
93 int width,
94 int height) {
95 // The actual sub buffer handling is handled at higher layers.
45 NOTREACHED(); 96 NOTREACHED();
46 return false; 97 return gfx::SwapResult::SWAP_FAILED;
47 } 98 }
48 99
49 void GbmSurfaceless::OnSwapBuffersAsync( 100 void GbmSurfaceless::SwapBuffersAsync(const SwapCompletionCallback& callback) {
101 TRACE_EVENT0("drm", "GbmSurfaceless::SwapBuffersAsync");
102 // If last swap failed, don't try to schedule new ones.
103 if (!last_swap_buffers_result_) {
104 callback.Run(gfx::SwapResult::SWAP_FAILED);
105 return;
106 }
107
108 glFlush();
109 unsubmitted_frames_.back()->Flush();
110
111 SwapCompletionCallback surface_swap_callback = base::Bind(
112 &GbmSurfaceless::SwapCompleted, weak_factory_.GetWeakPtr(), callback);
113
114 PendingFrame* frame = unsubmitted_frames_.back();
115 frame->callback = surface_swap_callback;
116 unsubmitted_frames_.push_back(new PendingFrame());
117
118 // TODO: the following should be replaced by a per surface flush as it gets
119 // implemented in GL drivers.
120 if (has_implicit_external_sync_ || has_image_flush_external_) {
121 EGLSyncKHR fence = InsertFence(has_implicit_external_sync_);
122 if (!fence) {
123 callback.Run(gfx::SwapResult::SWAP_FAILED);
124 return;
125 }
126
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.
137 }
138
139 frame->ready = true;
140 SubmitFrame();
141 }
142
143 void GbmSurfaceless::PostSubBufferAsync(
144 int x,
145 int y,
146 int width,
147 int height,
50 const SwapCompletionCallback& callback) { 148 const SwapCompletionCallback& callback) {
51 TRACE_EVENT0("drm", "GbmSurfaceless::OnSwapBuffersAsync"); 149 // The actual sub buffer handling is handled at higher layers.
52 window_->SchedulePageFlip(planes_, callback); 150 SwapBuffersAsync(callback);
53 planes_.clear(); 151 }
54 } 152
55 153 EGLConfig GbmSurfaceless::GetConfig() {
56 std::unique_ptr<gfx::VSyncProvider> GbmSurfaceless::CreateVSyncProvider() { 154 if (!config_) {
57 return base::WrapUnique(new DrmVSyncProvider(window_.get())); 155 EGLint config_attribs[] = {EGL_BUFFER_SIZE,
156 32,
157 EGL_ALPHA_SIZE,
158 8,
159 EGL_BLUE_SIZE,
160 8,
161 EGL_GREEN_SIZE,
162 8,
163 EGL_RED_SIZE,
164 8,
165 EGL_RENDERABLE_TYPE,
166 EGL_OPENGL_ES2_BIT,
167 EGL_SURFACE_TYPE,
168 EGL_DONT_CARE,
169 EGL_NONE};
170 config_ = ChooseEGLConfig(GetDisplay(), config_attribs);
171 }
172 return config_;
173 }
174
175 GbmSurfaceless::~GbmSurfaceless() {
176 Destroy(); // The EGL surface must be destroyed before SurfaceOzone.
177 surface_factory_->UnregisterSurface(window_->widget());
178 }
179
180 GbmSurfaceless::PendingFrame::PendingFrame() {}
181
182 GbmSurfaceless::PendingFrame::~PendingFrame() {}
183
184 bool GbmSurfaceless::PendingFrame::ScheduleOverlayPlanes(
185 gfx::AcceleratedWidget widget) {
186 for (const auto& overlay : overlays)
187 if (!overlay.ScheduleOverlayPlane(widget))
188 return false;
189 return true;
190 }
191
192 void GbmSurfaceless::PendingFrame::Flush() {
193 for (const auto& overlay : overlays)
194 overlay.Flush();
195 }
196
197 void GbmSurfaceless::SubmitFrame() {
198 DCHECK(!unsubmitted_frames_.empty());
199
200 if (unsubmitted_frames_.front()->ready && !swap_buffers_pending_) {
201 std::unique_ptr<PendingFrame> frame(unsubmitted_frames_.front());
202 unsubmitted_frames_.weak_erase(unsubmitted_frames_.begin());
203 swap_buffers_pending_ = true;
204
205 if (!frame->ScheduleOverlayPlanes(widget_)) {
206 // |callback| is a wrapper for SwapCompleted(). Call it to properly
207 // propagate the failed state.
208 frame->callback.Run(gfx::SwapResult::SWAP_FAILED);
209 return;
210 }
211
212 if (IsUniversalDisplayLinkDevice())
213 glFinish();
214
215 window_->SchedulePageFlip(planes_, frame->callback);
216 planes_.clear();
217 }
218 }
219
220 EGLSyncKHR GbmSurfaceless::InsertFence(bool implicit) {
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;
231 SubmitFrame();
232 }
233
234 void GbmSurfaceless::SwapCompleted(const SwapCompletionCallback& callback,
235 gfx::SwapResult result) {
236 callback.Run(result);
237 swap_buffers_pending_ = false;
238 if (result == gfx::SwapResult::SWAP_FAILED) {
239 last_swap_buffers_result_ = false;
240 return;
241 }
242
243 SubmitFrame();
58 } 244 }
59 245
60 bool GbmSurfaceless::IsUniversalDisplayLinkDevice() { 246 bool GbmSurfaceless::IsUniversalDisplayLinkDevice() {
61 return planes_.empty() ? false : planes_[0].buffer->RequiresGlFinish(); 247 return planes_.empty() ? false : planes_[0].buffer->RequiresGlFinish();
62 } 248 }
63 249
64 void* /* EGLConfig */ GbmSurfaceless::GetEGLSurfaceConfig(
65 const EglConfigCallbacks& egl) {
66 EGLint config_attribs[] = {EGL_BUFFER_SIZE,
67 32,
68 EGL_ALPHA_SIZE,
69 8,
70 EGL_BLUE_SIZE,
71 8,
72 EGL_GREEN_SIZE,
73 8,
74 EGL_RED_SIZE,
75 8,
76 EGL_RENDERABLE_TYPE,
77 EGL_OPENGL_ES2_BIT,
78 EGL_SURFACE_TYPE,
79 EGL_DONT_CARE,
80 EGL_NONE};
81 return ChooseEGLConfig(egl, config_attribs);
82 }
83
84 } // namespace ui 250 } // namespace ui
OLDNEW
« no previous file with comments | « ui/ozone/platform/drm/gpu/gbm_surfaceless.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698