blob: d28d081adbae32bc79ce166c18e06a6a03555edc [file] [log] [blame]
[email protected]ffcdc9632014-03-27 17:25:231// Copyright 2014 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/gl/gl_surface.h"
6
avi739878c2015-12-24 18:06:177#include <stddef.h>
8
achaulke86e411c2015-03-02 22:45:369#include "base/bind.h"
alexst165be972015-03-11 15:37:0910#include "base/callback.h"
11#include "base/location.h"
[email protected]ffcdc9632014-03-27 17:25:2312#include "base/logging.h"
avi739878c2015-12-24 18:06:1713#include "base/macros.h"
[email protected]ffcdc9632014-03-27 17:25:2314#include "base/memory/ref_counted.h"
achaulk77f08ab2015-04-07 16:22:3415#include "base/memory/scoped_vector.h"
alexst165be972015-03-11 15:37:0916#include "base/memory/weak_ptr.h"
17#include "base/threading/worker_pool.h"
[email protected]ffcdc9632014-03-27 17:25:2318#include "ui/gfx/native_widget_types.h"
kylechar53c91f22016-02-11 20:57:4419#include "ui/gl/egl_util.h"
[email protected]aab13e2f2014-07-29 03:01:4520#include "ui/gl/gl_context.h"
[email protected]f46c2bd2014-08-16 07:47:0921#include "ui/gl/gl_image.h"
dongseong.hwang161c7a22015-07-29 18:28:1722#include "ui/gl/gl_image_ozone_native_pixmap.h"
[email protected]ffcdc9632014-03-27 17:25:2323#include "ui/gl/gl_implementation.h"
24#include "ui/gl/gl_surface_egl.h"
25#include "ui/gl/gl_surface_osmesa.h"
watke6e68b1e2015-12-01 04:04:0326#include "ui/gl/gl_surface_overlay.h"
[email protected]ffcdc9632014-03-27 17:25:2327#include "ui/gl/gl_surface_stub.h"
achaulke86e411c2015-03-02 22:45:3628#include "ui/gl/scoped_binders.h"
[email protected]aab13e2f2014-07-29 03:01:4529#include "ui/gl/scoped_make_current.h"
achaulke86e411c2015-03-02 22:45:3630#include "ui/ozone/public/native_pixmap.h"
dongseong.hwang9162b5fa2015-06-05 16:52:3031#include "ui/ozone/public/ozone_platform.h"
[email protected]0e37fc202014-06-20 13:24:0232#include "ui/ozone/public/surface_factory_ozone.h"
33#include "ui/ozone/public/surface_ozone_egl.h"
[email protected]ffcdc9632014-03-27 17:25:2334
tfarinadf856e022015-10-29 12:50:4535using gl::GLImage;
36
[email protected]ffcdc9632014-03-27 17:25:2337namespace gfx {
38
[email protected]502371d2014-03-31 17:16:4239namespace {
40
kylechar53c91f22016-02-11 20:57:4441// Helper function for base::Bind to create callback to eglChooseConfig.
42bool EglChooseConfig(EGLDisplay display,
43 const int32_t* attribs,
44 EGLConfig* configs,
45 int32_t config_size,
46 int32_t* num_configs) {
47 return eglChooseConfig(display, attribs, configs, config_size, num_configs);
48}
49
50// Helper function for base::Bind to create callback to eglGetConfigAttrib.
51bool EglGetConfigAttribute(EGLDisplay display,
52 EGLConfig config,
53 int32_t attribute,
54 int32_t* value) {
55 return eglGetConfigAttrib(display, config, attribute, value);
56}
57
kylechar445089ac2016-03-09 19:23:4458// Populates EglConfigCallbacks with appropriate callbacks.
59ui::EglConfigCallbacks GetEglConfigCallbacks(EGLDisplay display) {
60 ui::EglConfigCallbacks callbacks;
61 callbacks.choose_config = base::Bind(EglChooseConfig, display);
62 callbacks.get_config_attribute = base::Bind(EglGetConfigAttribute, display);
63 callbacks.get_last_error_string = base::Bind(&ui::GetLastEGLErrorString);
64 return callbacks;
65}
66
alexst165be972015-03-11 15:37:0967void WaitForFence(EGLDisplay display, EGLSyncKHR fence) {
68 eglClientWaitSyncKHR(display, fence, EGL_SYNC_FLUSH_COMMANDS_BIT_KHR,
69 EGL_FOREVER_KHR);
70}
71
spang0ac9fc32015-09-16 23:11:0372// A thin wrapper around GLSurfaceEGL that owns the EGLNativeWindow.
[email protected]502371d2014-03-31 17:16:4273class GL_EXPORT GLSurfaceOzoneEGL : public NativeViewGLSurfaceEGL {
74 public:
[email protected]aab13e2f2014-07-29 03:01:4575 GLSurfaceOzoneEGL(scoped_ptr<ui::SurfaceOzoneEGL> ozone_surface,
alexste3e46052015-05-04 19:40:5676 AcceleratedWidget widget);
[email protected]502371d2014-03-31 17:16:4277
alexste3e46052015-05-04 19:40:5678 // GLSurface:
jinsukkim25219612016-01-20 23:24:0779 bool Initialize(gfx::GLSurface::Format format) override;
jbauman16205872015-12-15 21:27:2780 bool Resize(const gfx::Size& size,
81 float scale_factor,
82 bool has_alpha) override;
achaulkec8c2db2015-05-29 16:35:0383 gfx::SwapResult SwapBuffers() override;
alexstfa14b6712015-01-05 19:29:4884 bool ScheduleOverlayPlane(int z_order,
85 OverlayTransform transform,
86 GLImage* image,
87 const Rect& bounds_rect,
alexste3e46052015-05-04 19:40:5688 const RectF& crop_rect) override;
kylechar53c91f22016-02-11 20:57:4489 EGLConfig GetConfig() override;
[email protected]5780da092014-04-08 12:04:4190
[email protected]b8211e32014-04-01 22:58:4591 private:
achaulke79d5d852014-08-27 00:16:4292 using NativeViewGLSurfaceEGL::Initialize;
93
alexste3e46052015-05-04 19:40:5694 ~GLSurfaceOzoneEGL() override;
[email protected]502371d2014-03-31 17:16:4295
alexste3e46052015-05-04 19:40:5696 bool ReinitializeNativeSurface();
[email protected]aab13e2f2014-07-29 03:01:4597
[email protected]502371d2014-03-31 17:16:4298 // The native surface. Deleting this is allowed to free the EGLNativeWindow.
[email protected]0e37fc202014-06-20 13:24:0299 scoped_ptr<ui::SurfaceOzoneEGL> ozone_surface_;
[email protected]aab13e2f2014-07-29 03:01:45100 AcceleratedWidget widget_;
[email protected]502371d2014-03-31 17:16:42101
102 DISALLOW_COPY_AND_ASSIGN(GLSurfaceOzoneEGL);
103};
104
alexste3e46052015-05-04 19:40:56105GLSurfaceOzoneEGL::GLSurfaceOzoneEGL(
106 scoped_ptr<ui::SurfaceOzoneEGL> ozone_surface,
107 AcceleratedWidget widget)
108 : NativeViewGLSurfaceEGL(ozone_surface->GetNativeWindow()),
martina.kollarova66bdb2b2015-12-17 08:35:46109 ozone_surface_(std::move(ozone_surface)),
spang0ac9fc32015-09-16 23:11:03110 widget_(widget) {}
alexste3e46052015-05-04 19:40:56111
jinsukkim25219612016-01-20 23:24:07112bool GLSurfaceOzoneEGL::Initialize(gfx::GLSurface::Format format) {
113 format_ = format;
alexste3e46052015-05-04 19:40:56114 return Initialize(ozone_surface_->CreateVSyncProvider());
115}
116
jbauman16205872015-12-15 21:27:27117bool GLSurfaceOzoneEGL::Resize(const gfx::Size& size,
118 float scale_factor,
119 bool has_alpha) {
alexste3e46052015-05-04 19:40:56120 if (!ozone_surface_->ResizeNativeWindow(size)) {
121 if (!ReinitializeNativeSurface() ||
122 !ozone_surface_->ResizeNativeWindow(size))
123 return false;
124 }
125
jbauman16205872015-12-15 21:27:27126 return NativeViewGLSurfaceEGL::Resize(size, scale_factor, has_alpha);
alexste3e46052015-05-04 19:40:56127}
128
achaulkec8c2db2015-05-29 16:35:03129gfx::SwapResult GLSurfaceOzoneEGL::SwapBuffers() {
130 gfx::SwapResult result = NativeViewGLSurfaceEGL::SwapBuffers();
131 if (result != gfx::SwapResult::SWAP_ACK)
132 return result;
alexste3e46052015-05-04 19:40:56133
achaulkec8c2db2015-05-29 16:35:03134 return ozone_surface_->OnSwapBuffers() ? gfx::SwapResult::SWAP_ACK
135 : gfx::SwapResult::SWAP_FAILED;
alexste3e46052015-05-04 19:40:56136}
137
138bool GLSurfaceOzoneEGL::ScheduleOverlayPlane(int z_order,
139 OverlayTransform transform,
140 GLImage* image,
141 const Rect& bounds_rect,
142 const RectF& crop_rect) {
143 return image->ScheduleOverlayPlane(widget_, z_order, transform, bounds_rect,
144 crop_rect);
145}
146
kylechar53c91f22016-02-11 20:57:44147EGLConfig GLSurfaceOzoneEGL::GetConfig() {
148 if (!config_) {
kylechar445089ac2016-03-09 19:23:44149 ui::EglConfigCallbacks callbacks = GetEglConfigCallbacks(GetDisplay());
150 config_ = ozone_surface_->GetEGLSurfaceConfig(callbacks);
kylechar53c91f22016-02-11 20:57:44151 }
152 if (config_)
153 return config_;
154 return NativeViewGLSurfaceEGL::GetConfig();
155}
156
alexste3e46052015-05-04 19:40:56157GLSurfaceOzoneEGL::~GLSurfaceOzoneEGL() {
spang0ac9fc32015-09-16 23:11:03158 Destroy(); // The EGL surface must be destroyed before SurfaceOzone.
alexste3e46052015-05-04 19:40:56159}
160
161bool GLSurfaceOzoneEGL::ReinitializeNativeSurface() {
162 scoped_ptr<ui::ScopedMakeCurrent> scoped_make_current;
163 GLContext* current_context = GLContext::GetCurrent();
164 bool was_current = current_context && current_context->IsCurrent(this);
165 if (was_current) {
166 scoped_make_current.reset(new ui::ScopedMakeCurrent(current_context, this));
167 }
168
169 Destroy();
dongseong.hwang9162b5fa2015-06-05 16:52:30170 ozone_surface_ = ui::OzonePlatform::GetInstance()
171 ->GetSurfaceFactoryOzone()
spang0ac9fc32015-09-16 23:11:03172 ->CreateEGLSurfaceForWidget(widget_);
alexste3e46052015-05-04 19:40:56173 if (!ozone_surface_) {
174 LOG(ERROR) << "Failed to create native surface.";
175 return false;
176 }
177
178 window_ = ozone_surface_->GetNativeWindow();
jinsukkim25219612016-01-20 23:24:07179 if (!Initialize(format_)) {
alexste3e46052015-05-04 19:40:56180 LOG(ERROR) << "Failed to initialize.";
181 return false;
182 }
183
184 return true;
185}
186
achaulke79d5d852014-08-27 00:16:42187class GL_EXPORT GLSurfaceOzoneSurfaceless : public SurfacelessEGL {
188 public:
189 GLSurfaceOzoneSurfaceless(scoped_ptr<ui::SurfaceOzoneEGL> ozone_surface,
alexste3e46052015-05-04 19:40:56190 AcceleratedWidget widget);
achaulke79d5d852014-08-27 00:16:42191
alexste3e46052015-05-04 19:40:56192 // GLSurface:
jinsukkim25219612016-01-20 23:24:07193 bool Initialize(gfx::GLSurface::Format format) override;
jbauman16205872015-12-15 21:27:27194 bool Resize(const gfx::Size& size,
195 float scale_factor,
196 bool has_alpha) override;
achaulkec8c2db2015-05-29 16:35:03197 gfx::SwapResult SwapBuffers() override;
alexstfa14b6712015-01-05 19:29:48198 bool ScheduleOverlayPlane(int z_order,
199 OverlayTransform transform,
200 GLImage* image,
201 const Rect& bounds_rect,
alexste3e46052015-05-04 19:40:56202 const RectF& crop_rect) override;
203 bool IsOffscreen() override;
204 VSyncProvider* GetVSyncProvider() override;
spangf960a9502015-11-18 21:04:26205 bool SupportsAsyncSwap() override;
alexste3e46052015-05-04 19:40:56206 bool SupportsPostSubBuffer() override;
achaulkec8c2db2015-05-29 16:35:03207 gfx::SwapResult PostSubBuffer(int x, int y, int width, int height) override;
spangf960a9502015-11-18 21:04:26208 void SwapBuffersAsync(const SwapCompletionCallback& callback) override;
209 void PostSubBufferAsync(int x,
alexst409e3e02015-01-05 22:20:24210 int y,
211 int width,
212 int height,
alexste3e46052015-05-04 19:40:56213 const SwapCompletionCallback& callback) override;
kylechar445089ac2016-03-09 19:23:44214 EGLConfig GetConfig() override;
achaulke79d5d852014-08-27 00:16:42215
achaulke86e411c2015-03-02 22:45:36216 protected:
achaulk77f08ab2015-04-07 16:22:34217 struct PendingFrame {
alexste3e46052015-05-04 19:40:56218 PendingFrame();
achaulk77f08ab2015-04-07 16:22:34219
alexste3e46052015-05-04 19:40:56220 bool ScheduleOverlayPlanes(gfx::AcceleratedWidget widget);
achaulk77f08ab2015-04-07 16:22:34221
achaulk77f08ab2015-04-07 16:22:34222 bool ready;
watke6e68b1e2015-12-01 04:04:03223 std::vector<GLSurfaceOverlay> overlays;
achaulk77f08ab2015-04-07 16:22:34224 SwapCompletionCallback callback;
225 };
226
alexste3e46052015-05-04 19:40:56227 ~GLSurfaceOzoneSurfaceless() override;
achaulke79d5d852014-08-27 00:16:42228
alexste3e46052015-05-04 19:40:56229 void SubmitFrame();
alexst9c973212015-04-24 14:28:45230
alexste3e46052015-05-04 19:40:56231 EGLSyncKHR InsertFence();
232 void FenceRetired(EGLSyncKHR fence, PendingFrame* frame);
alexst9c973212015-04-24 14:28:45233
achaulkec8c2db2015-05-29 16:35:03234 void SwapCompleted(const SwapCompletionCallback& callback,
235 gfx::SwapResult result);
dbehr5addbd52015-02-07 03:18:05236
achaulke79d5d852014-08-27 00:16:42237 // The native surface. Deleting this is allowed to free the EGLNativeWindow.
238 scoped_ptr<ui::SurfaceOzoneEGL> ozone_surface_;
239 AcceleratedWidget widget_;
240 scoped_ptr<VSyncProvider> vsync_provider_;
achaulk77f08ab2015-04-07 16:22:34241 ScopedVector<PendingFrame> unsubmitted_frames_;
dbehr5addbd52015-02-07 03:18:05242 bool has_implicit_external_sync_;
alexst165be972015-03-11 15:37:09243 bool last_swap_buffers_result_;
alexst9c973212015-04-24 14:28:45244 bool swap_buffers_pending_;
alexst165be972015-03-11 15:37:09245
246 base::WeakPtrFactory<GLSurfaceOzoneSurfaceless> weak_factory_;
247
kylechar53c91f22016-02-11 20:57:44248 private:
achaulke79d5d852014-08-27 00:16:42249 DISALLOW_COPY_AND_ASSIGN(GLSurfaceOzoneSurfaceless);
250};
251
spang0ac9fc32015-09-16 23:11:03252GLSurfaceOzoneSurfaceless::PendingFrame::PendingFrame() : ready(false) {}
alexste3e46052015-05-04 19:40:56253
254bool GLSurfaceOzoneSurfaceless::PendingFrame::ScheduleOverlayPlanes(
255 gfx::AcceleratedWidget widget) {
256 for (const auto& overlay : overlays)
257 if (!overlay.ScheduleOverlayPlane(widget))
258 return false;
259 return true;
260}
261
262GLSurfaceOzoneSurfaceless::GLSurfaceOzoneSurfaceless(
263 scoped_ptr<ui::SurfaceOzoneEGL> ozone_surface,
264 AcceleratedWidget widget)
265 : SurfacelessEGL(gfx::Size()),
martina.kollarova66bdb2b2015-12-17 08:35:46266 ozone_surface_(std::move(ozone_surface)),
alexste3e46052015-05-04 19:40:56267 widget_(widget),
268 has_implicit_external_sync_(
269 HasEGLExtension("EGL_ARM_implicit_external_sync")),
270 last_swap_buffers_result_(true),
271 swap_buffers_pending_(false),
272 weak_factory_(this) {
273 unsubmitted_frames_.push_back(new PendingFrame());
274}
275
jinsukkim25219612016-01-20 23:24:07276bool GLSurfaceOzoneSurfaceless::Initialize(gfx::GLSurface::Format format) {
277 if (!SurfacelessEGL::Initialize(format))
alexste3e46052015-05-04 19:40:56278 return false;
279 vsync_provider_ = ozone_surface_->CreateVSyncProvider();
280 if (!vsync_provider_)
281 return false;
282 return true;
283}
spang0ac9fc32015-09-16 23:11:03284
jbaumance45e112015-10-30 02:33:57285bool GLSurfaceOzoneSurfaceless::Resize(const gfx::Size& size,
jbauman16205872015-12-15 21:27:27286 float scale_factor,
287 bool has_alpha) {
alexste3e46052015-05-04 19:40:56288 if (!ozone_surface_->ResizeNativeWindow(size))
289 return false;
290
jbauman16205872015-12-15 21:27:27291 return SurfacelessEGL::Resize(size, scale_factor, has_alpha);
alexste3e46052015-05-04 19:40:56292}
spang0ac9fc32015-09-16 23:11:03293
achaulkec8c2db2015-05-29 16:35:03294gfx::SwapResult GLSurfaceOzoneSurfaceless::SwapBuffers() {
alexste3e46052015-05-04 19:40:56295 glFlush();
296 // TODO: the following should be replaced by a per surface flush as it gets
297 // implemented in GL drivers.
298 if (has_implicit_external_sync_) {
299 EGLSyncKHR fence = InsertFence();
300 if (!fence)
achaulkec8c2db2015-05-29 16:35:03301 return SwapResult::SWAP_FAILED;
alexste3e46052015-05-04 19:40:56302
303 EGLDisplay display = GetDisplay();
304 WaitForFence(display, fence);
305 eglDestroySyncKHR(display, fence);
alexste3e46052015-05-04 19:40:56306 }
307
308 unsubmitted_frames_.back()->ScheduleOverlayPlanes(widget_);
309 unsubmitted_frames_.back()->overlays.clear();
310
hshi66cf41e22016-01-07 21:10:23311 if (ozone_surface_->IsUniversalDisplayLinkDevice())
312 glFinish();
313
achaulkec8c2db2015-05-29 16:35:03314 return ozone_surface_->OnSwapBuffers() ? gfx::SwapResult::SWAP_ACK
315 : gfx::SwapResult::SWAP_FAILED;
alexste3e46052015-05-04 19:40:56316}
spang0ac9fc32015-09-16 23:11:03317
alexste3e46052015-05-04 19:40:56318bool GLSurfaceOzoneSurfaceless::ScheduleOverlayPlane(int z_order,
319 OverlayTransform transform,
320 GLImage* image,
321 const Rect& bounds_rect,
322 const RectF& crop_rect) {
323 unsubmitted_frames_.back()->overlays.push_back(
watke6e68b1e2015-12-01 04:04:03324 GLSurfaceOverlay(z_order, transform, image, bounds_rect, crop_rect));
alexste3e46052015-05-04 19:40:56325 return true;
326}
spang0ac9fc32015-09-16 23:11:03327
alexste3e46052015-05-04 19:40:56328bool GLSurfaceOzoneSurfaceless::IsOffscreen() {
329 return false;
330}
spang0ac9fc32015-09-16 23:11:03331
alexste3e46052015-05-04 19:40:56332VSyncProvider* GLSurfaceOzoneSurfaceless::GetVSyncProvider() {
333 return vsync_provider_.get();
334}
spang0ac9fc32015-09-16 23:11:03335
spangf960a9502015-11-18 21:04:26336bool GLSurfaceOzoneSurfaceless::SupportsAsyncSwap() {
337 return true;
338}
339
alexste3e46052015-05-04 19:40:56340bool GLSurfaceOzoneSurfaceless::SupportsPostSubBuffer() {
341 return true;
342}
spang0ac9fc32015-09-16 23:11:03343
achaulkec8c2db2015-05-29 16:35:03344gfx::SwapResult GLSurfaceOzoneSurfaceless::PostSubBuffer(int x,
345 int y,
346 int width,
347 int height) {
alexste3e46052015-05-04 19:40:56348 // The actual sub buffer handling is handled at higher layers.
spangf960a9502015-11-18 21:04:26349 NOTREACHED();
350 return gfx::SwapResult::SWAP_FAILED;
alexste3e46052015-05-04 19:40:56351}
spang0ac9fc32015-09-16 23:11:03352
spangf960a9502015-11-18 21:04:26353void GLSurfaceOzoneSurfaceless::SwapBuffersAsync(
alexste3e46052015-05-04 19:40:56354 const SwapCompletionCallback& callback) {
355 // If last swap failed, don't try to schedule new ones.
spangf960a9502015-11-18 21:04:26356 if (!last_swap_buffers_result_) {
357 callback.Run(gfx::SwapResult::SWAP_FAILED);
358 return;
359 }
alexste3e46052015-05-04 19:40:56360
361 glFlush();
362
achaulkec8c2db2015-05-29 16:35:03363 SwapCompletionCallback surface_swap_callback =
alexste3e46052015-05-04 19:40:56364 base::Bind(&GLSurfaceOzoneSurfaceless::SwapCompleted,
365 weak_factory_.GetWeakPtr(), callback);
366
367 PendingFrame* frame = unsubmitted_frames_.back();
368 frame->callback = surface_swap_callback;
369 unsubmitted_frames_.push_back(new PendingFrame());
370
371 // TODO: the following should be replaced by a per surface flush as it gets
372 // implemented in GL drivers.
373 if (has_implicit_external_sync_) {
374 EGLSyncKHR fence = InsertFence();
spangf960a9502015-11-18 21:04:26375 if (!fence) {
376 callback.Run(gfx::SwapResult::SWAP_FAILED);
377 return;
378 }
alexste3e46052015-05-04 19:40:56379
380 base::Closure fence_wait_task =
381 base::Bind(&WaitForFence, GetDisplay(), fence);
382
383 base::Closure fence_retired_callback =
384 base::Bind(&GLSurfaceOzoneSurfaceless::FenceRetired,
385 weak_factory_.GetWeakPtr(), fence, frame);
386
387 base::WorkerPool::PostTaskAndReply(FROM_HERE, fence_wait_task,
388 fence_retired_callback, false);
spangc63975d2015-11-24 16:08:11389 return; // Defer frame submission until fence signals.
alexste3e46052015-05-04 19:40:56390 }
391
392 frame->ready = true;
393 SubmitFrame();
alexste3e46052015-05-04 19:40:56394}
spang0ac9fc32015-09-16 23:11:03395
spangf960a9502015-11-18 21:04:26396void GLSurfaceOzoneSurfaceless::PostSubBufferAsync(
alexste3e46052015-05-04 19:40:56397 int x,
398 int y,
399 int width,
400 int height,
401 const SwapCompletionCallback& callback) {
spangf960a9502015-11-18 21:04:26402 // The actual sub buffer handling is handled at higher layers.
403 SwapBuffersAsync(callback);
alexste3e46052015-05-04 19:40:56404}
405
kylechar445089ac2016-03-09 19:23:44406EGLConfig GLSurfaceOzoneSurfaceless::GetConfig() {
407 if (!config_) {
408 ui::EglConfigCallbacks callbacks = GetEglConfigCallbacks(GetDisplay());
409 config_ = ozone_surface_->GetEGLSurfaceConfig(callbacks);
410 }
411 if (config_)
412 return config_;
413 return SurfacelessEGL::GetConfig();
414}
415
alexste3e46052015-05-04 19:40:56416GLSurfaceOzoneSurfaceless::~GLSurfaceOzoneSurfaceless() {
spang0ac9fc32015-09-16 23:11:03417 Destroy(); // The EGL surface must be destroyed before SurfaceOzone.
alexste3e46052015-05-04 19:40:56418}
419
420void GLSurfaceOzoneSurfaceless::SubmitFrame() {
421 DCHECK(!unsubmitted_frames_.empty());
422
423 if (unsubmitted_frames_.front()->ready && !swap_buffers_pending_) {
424 scoped_ptr<PendingFrame> frame(unsubmitted_frames_.front());
425 unsubmitted_frames_.weak_erase(unsubmitted_frames_.begin());
426 swap_buffers_pending_ = true;
427
dnicoara02681f42015-11-12 15:34:38428 if (!frame->ScheduleOverlayPlanes(widget_)) {
429 // |callback| is a wrapper for SwapCompleted(). Call it to properly
430 // propagate the failed state.
431 frame->callback.Run(gfx::SwapResult::SWAP_FAILED);
432 return;
433 }
434
hshi66cf41e22016-01-07 21:10:23435 if (ozone_surface_->IsUniversalDisplayLinkDevice())
436 glFinish();
437
dnicoara02681f42015-11-12 15:34:38438 ozone_surface_->OnSwapBuffersAsync(frame->callback);
alexste3e46052015-05-04 19:40:56439 }
440}
441
442EGLSyncKHR GLSurfaceOzoneSurfaceless::InsertFence() {
443 const EGLint attrib_list[] = {EGL_SYNC_CONDITION_KHR,
444 EGL_SYNC_PRIOR_COMMANDS_IMPLICIT_EXTERNAL_ARM,
445 EGL_NONE};
446 return eglCreateSyncKHR(GetDisplay(), EGL_SYNC_FENCE_KHR, attrib_list);
447}
448
449void GLSurfaceOzoneSurfaceless::FenceRetired(EGLSyncKHR fence,
450 PendingFrame* frame) {
451 eglDestroySyncKHR(GetDisplay(), fence);
452 frame->ready = true;
453 SubmitFrame();
454}
455
456void GLSurfaceOzoneSurfaceless::SwapCompleted(
achaulkec8c2db2015-05-29 16:35:03457 const SwapCompletionCallback& callback,
458 gfx::SwapResult result) {
459 callback.Run(result);
alexste3e46052015-05-04 19:40:56460 swap_buffers_pending_ = false;
dnicoara02681f42015-11-12 15:34:38461 if (result == gfx::SwapResult::SWAP_FAILED) {
462 last_swap_buffers_result_ = false;
463 return;
464 }
alexste3e46052015-05-04 19:40:56465
466 SubmitFrame();
467}
468
achaulke86e411c2015-03-02 22:45:36469// This provides surface-like semantics implemented through surfaceless.
470// A framebuffer is bound automatically.
471class GL_EXPORT GLSurfaceOzoneSurfacelessSurfaceImpl
472 : public GLSurfaceOzoneSurfaceless {
473 public:
474 GLSurfaceOzoneSurfacelessSurfaceImpl(
475 scoped_ptr<ui::SurfaceOzoneEGL> ozone_surface,
alexste3e46052015-05-04 19:40:56476 AcceleratedWidget widget);
achaulke86e411c2015-03-02 22:45:36477
alexste3e46052015-05-04 19:40:56478 // GLSurface:
479 unsigned int GetBackingFrameBufferObject() override;
480 bool OnMakeCurrent(GLContext* context) override;
jbauman16205872015-12-15 21:27:27481 bool Resize(const gfx::Size& size,
482 float scale_factor,
483 bool has_alpha) override;
alexste3e46052015-05-04 19:40:56484 bool SupportsPostSubBuffer() override;
achaulkec8c2db2015-05-29 16:35:03485 gfx::SwapResult SwapBuffers() override;
spangf960a9502015-11-18 21:04:26486 void SwapBuffersAsync(const SwapCompletionCallback& callback) override;
alexste3e46052015-05-04 19:40:56487 void Destroy() override;
spangb55571ca2015-09-16 22:09:35488 bool IsSurfaceless() const override;
achaulke86e411c2015-03-02 22:45:36489
490 private:
alexste3e46052015-05-04 19:40:56491 ~GLSurfaceOzoneSurfacelessSurfaceImpl() override;
achaulke86e411c2015-03-02 22:45:36492
alexste3e46052015-05-04 19:40:56493 void BindFramebuffer();
494 bool CreatePixmaps();
achaulke86e411c2015-03-02 22:45:36495
achaulk8d645d292015-08-04 14:09:27496 scoped_refptr<GLContext> context_;
achaulke86e411c2015-03-02 22:45:36497 GLuint fbo_;
498 GLuint textures_[2];
499 scoped_refptr<GLImage> images_[2];
500 int current_surface_;
501 DISALLOW_COPY_AND_ASSIGN(GLSurfaceOzoneSurfacelessSurfaceImpl);
502};
503
alexste3e46052015-05-04 19:40:56504GLSurfaceOzoneSurfacelessSurfaceImpl::GLSurfaceOzoneSurfacelessSurfaceImpl(
505 scoped_ptr<ui::SurfaceOzoneEGL> ozone_surface,
506 AcceleratedWidget widget)
martina.kollarova66bdb2b2015-12-17 08:35:46507 : GLSurfaceOzoneSurfaceless(std::move(ozone_surface), widget),
achaulk8d645d292015-08-04 14:09:27508 context_(nullptr),
alexste3e46052015-05-04 19:40:56509 fbo_(0),
510 current_surface_(0) {
511 for (auto& texture : textures_)
512 texture = 0;
513}
514
515unsigned int
516GLSurfaceOzoneSurfacelessSurfaceImpl::GetBackingFrameBufferObject() {
517 return fbo_;
518}
519
520bool GLSurfaceOzoneSurfacelessSurfaceImpl::OnMakeCurrent(GLContext* context) {
achaulk8d645d292015-08-04 14:09:27521 DCHECK(!context_ || context == context_);
522 context_ = context;
alexste3e46052015-05-04 19:40:56523 if (!fbo_) {
524 glGenFramebuffersEXT(1, &fbo_);
525 if (!fbo_)
526 return false;
527 glGenTextures(arraysize(textures_), textures_);
528 if (!CreatePixmaps())
529 return false;
530 }
531 BindFramebuffer();
532 glBindFramebufferEXT(GL_FRAMEBUFFER, fbo_);
533 return SurfacelessEGL::OnMakeCurrent(context);
534}
535
jbaumance45e112015-10-30 02:33:57536bool GLSurfaceOzoneSurfacelessSurfaceImpl::Resize(const gfx::Size& size,
jbauman16205872015-12-15 21:27:27537 float scale_factor,
538 bool has_alpha) {
alexste3e46052015-05-04 19:40:56539 if (size == GetSize())
540 return true;
jbauman16205872015-12-15 21:27:27541 // Alpha value isn't actually used in allocating buffers yet, so always use
542 // true instead.
543 return GLSurfaceOzoneSurfaceless::Resize(size, scale_factor, true) &&
jbaumance45e112015-10-30 02:33:57544 CreatePixmaps();
alexste3e46052015-05-04 19:40:56545}
546
547bool GLSurfaceOzoneSurfacelessSurfaceImpl::SupportsPostSubBuffer() {
548 return false;
549}
550
achaulkec8c2db2015-05-29 16:35:03551gfx::SwapResult GLSurfaceOzoneSurfacelessSurfaceImpl::SwapBuffers() {
alexste3e46052015-05-04 19:40:56552 if (!images_[current_surface_]->ScheduleOverlayPlane(
553 widget_, 0, OverlayTransform::OVERLAY_TRANSFORM_NONE,
554 gfx::Rect(GetSize()), gfx::RectF(1, 1)))
achaulkec8c2db2015-05-29 16:35:03555 return gfx::SwapResult::SWAP_FAILED;
556 gfx::SwapResult result = GLSurfaceOzoneSurfaceless::SwapBuffers();
557 if (result != gfx::SwapResult::SWAP_ACK)
558 return result;
alexste3e46052015-05-04 19:40:56559 current_surface_ ^= 1;
560 BindFramebuffer();
achaulkec8c2db2015-05-29 16:35:03561 return gfx::SwapResult::SWAP_ACK;
alexste3e46052015-05-04 19:40:56562}
563
spangf960a9502015-11-18 21:04:26564void GLSurfaceOzoneSurfacelessSurfaceImpl::SwapBuffersAsync(
alexste3e46052015-05-04 19:40:56565 const SwapCompletionCallback& callback) {
566 if (!images_[current_surface_]->ScheduleOverlayPlane(
567 widget_, 0, OverlayTransform::OVERLAY_TRANSFORM_NONE,
spangf960a9502015-11-18 21:04:26568 gfx::Rect(GetSize()), gfx::RectF(1, 1))) {
569 callback.Run(gfx::SwapResult::SWAP_FAILED);
570 return;
571 }
572 GLSurfaceOzoneSurfaceless::SwapBuffersAsync(callback);
alexste3e46052015-05-04 19:40:56573 current_surface_ ^= 1;
574 BindFramebuffer();
alexste3e46052015-05-04 19:40:56575}
576
577void GLSurfaceOzoneSurfacelessSurfaceImpl::Destroy() {
achaulk8d645d292015-08-04 14:09:27578 if (!context_)
579 return;
wuchengli20824f952015-10-22 05:05:27580 scoped_refptr<gfx::GLContext> previous_context = gfx::GLContext::GetCurrent();
581 scoped_refptr<gfx::GLSurface> previous_surface = gfx::GLSurface::GetCurrent();
582 context_->MakeCurrent(this);
583
alexste3e46052015-05-04 19:40:56584 glBindFramebufferEXT(GL_FRAMEBUFFER, 0);
585 if (fbo_) {
586 glDeleteTextures(arraysize(textures_), textures_);
587 for (auto& texture : textures_)
588 texture = 0;
589 glDeleteFramebuffersEXT(1, &fbo_);
590 fbo_ = 0;
591 }
592 for (auto image : images_) {
593 if (image)
594 image->Destroy(true);
595 }
wuchengli20824f952015-10-22 05:05:27596
597 if (previous_context.get()) {
598 previous_context->MakeCurrent(previous_surface.get());
599 } else {
600 context_->ReleaseCurrent(this);
601 }
alexste3e46052015-05-04 19:40:56602}
603
spangb55571ca2015-09-16 22:09:35604bool GLSurfaceOzoneSurfacelessSurfaceImpl::IsSurfaceless() const {
605 return false;
606}
607
alexste3e46052015-05-04 19:40:56608GLSurfaceOzoneSurfacelessSurfaceImpl::~GLSurfaceOzoneSurfacelessSurfaceImpl() {
wuchengli20824f952015-10-22 05:05:27609 Destroy();
alexste3e46052015-05-04 19:40:56610}
611
612void GLSurfaceOzoneSurfacelessSurfaceImpl::BindFramebuffer() {
613 ScopedFrameBufferBinder fb(fbo_);
614 glFramebufferTexture2DEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
615 textures_[current_surface_], 0);
616}
617
618bool GLSurfaceOzoneSurfacelessSurfaceImpl::CreatePixmaps() {
619 if (!fbo_)
620 return true;
621 for (size_t i = 0; i < arraysize(textures_); i++) {
622 scoped_refptr<ui::NativePixmap> pixmap =
dongseong.hwang9162b5fa2015-06-05 16:52:30623 ui::OzonePlatform::GetInstance()
624 ->GetSurfaceFactoryOzone()
625 ->CreateNativePixmap(widget_, GetSize(),
spangfcf5fab42015-08-04 19:25:35626 gfx::BufferFormat::BGRA_8888,
reveman1108e0b72015-10-30 17:05:44627 gfx::BufferUsage::SCANOUT);
alexste3e46052015-05-04 19:40:56628 if (!pixmap)
629 return false;
dongseong.hwang161c7a22015-07-29 18:28:17630 scoped_refptr<GLImageOzoneNativePixmap> image =
631 new GLImageOzoneNativePixmap(GetSize(), GL_BGRA_EXT);
reveman0bb50d72015-11-16 18:04:52632 if (!image->Initialize(pixmap.get(), gfx::BufferFormat::BGRA_8888))
alexste3e46052015-05-04 19:40:56633 return false;
634 images_[i] = image;
635 // Bind image to texture.
636 ScopedTextureBinder binder(GL_TEXTURE_2D, textures_[i]);
637 if (!images_[i]->BindTexImage(GL_TEXTURE_2D))
638 return false;
639 }
640 return true;
641}
642
spange82006b2015-09-16 18:07:29643scoped_refptr<GLSurface> CreateViewGLSurfaceOzone(
644 gfx::AcceleratedWidget window) {
645 scoped_ptr<ui::SurfaceOzoneEGL> surface_ozone =
646 ui::OzonePlatform::GetInstance()
647 ->GetSurfaceFactoryOzone()
648 ->CreateEGLSurfaceForWidget(window);
649 if (!surface_ozone)
650 return nullptr;
651 scoped_refptr<GLSurface> surface =
martina.kollarova66bdb2b2015-12-17 08:35:46652 new GLSurfaceOzoneEGL(std::move(surface_ozone), window);
spange82006b2015-09-16 18:07:29653 if (!surface->Initialize())
654 return nullptr;
655 return surface;
656}
657
658scoped_refptr<GLSurface> CreateViewGLSurfaceOzoneSurfacelessSurfaceImpl(
659 gfx::AcceleratedWidget window) {
660 scoped_ptr<ui::SurfaceOzoneEGL> surface_ozone =
661 ui::OzonePlatform::GetInstance()
662 ->GetSurfaceFactoryOzone()
663 ->CreateSurfacelessEGLSurfaceForWidget(window);
664 if (!surface_ozone)
665 return nullptr;
martina.kollarova66bdb2b2015-12-17 08:35:46666 scoped_refptr<GLSurface> surface = new GLSurfaceOzoneSurfacelessSurfaceImpl(
667 std::move(surface_ozone), window);
spange82006b2015-09-16 18:07:29668 if (!surface->Initialize())
669 return nullptr;
670 return surface;
671}
672
[email protected]502371d2014-03-31 17:16:42673} // namespace
674
[email protected]ffcdc9632014-03-27 17:25:23675// static
676bool GLSurface::InitializeOneOffInternal() {
[email protected]ffcdc9632014-03-27 17:25:23677 switch (GetGLImplementation()) {
678 case kGLImplementationEGLGLES2:
[email protected]ffcdc9632014-03-27 17:25:23679 if (!GLSurfaceEGL::InitializeOneOff()) {
680 LOG(ERROR) << "GLSurfaceEGL::InitializeOneOff failed.";
681 return false;
682 }
[email protected]1fe750572014-03-29 01:22:34683
684 return true;
685 case kGLImplementationOSMesaGL:
686 case kGLImplementationMockGL:
687 return true;
[email protected]ffcdc9632014-03-27 17:25:23688 default:
[email protected]1fe750572014-03-29 01:22:34689 return false;
[email protected]ffcdc9632014-03-27 17:25:23690 }
[email protected]ffcdc9632014-03-27 17:25:23691}
692
693// static
achaulke86e411c2015-03-02 22:45:36694scoped_refptr<GLSurface> GLSurface::CreateSurfacelessViewGLSurface(
695 gfx::AcceleratedWidget window) {
696 if (GetGLImplementation() == kGLImplementationEGLGLES2 &&
697 window != kNullAcceleratedWidget &&
spange82006b2015-09-16 18:07:29698 GLSurfaceEGL::IsEGLSurfacelessContextSupported()) {
achaulke86e411c2015-03-02 22:45:36699 scoped_ptr<ui::SurfaceOzoneEGL> surface_ozone =
dongseong.hwang9162b5fa2015-06-05 16:52:30700 ui::OzonePlatform::GetInstance()
701 ->GetSurfaceFactoryOzone()
achaulke86e411c2015-03-02 22:45:36702 ->CreateSurfacelessEGLSurfaceForWidget(window);
703 if (!surface_ozone)
704 return nullptr;
705 scoped_refptr<GLSurface> surface;
martina.kollarova66bdb2b2015-12-17 08:35:46706 surface = new GLSurfaceOzoneSurfaceless(std::move(surface_ozone), window);
achaulke86e411c2015-03-02 22:45:36707 if (surface->Initialize())
708 return surface;
709 }
710
711 return nullptr;
712}
713
714// static
[email protected]ffcdc9632014-03-27 17:25:23715scoped_refptr<GLSurface> GLSurface::CreateViewGLSurface(
716 gfx::AcceleratedWidget window) {
717 if (GetGLImplementation() == kGLImplementationOSMesaGL) {
718 scoped_refptr<GLSurface> surface(new GLSurfaceOSMesaHeadless());
719 if (!surface->Initialize())
spang0ac9fc32015-09-16 23:11:03720 return nullptr;
[email protected]ffcdc9632014-03-27 17:25:23721 return surface;
722 }
723 DCHECK(GetGLImplementation() == kGLImplementationEGLGLES2);
724 if (window != kNullAcceleratedWidget) {
achaulke79d5d852014-08-27 00:16:42725 scoped_refptr<GLSurface> surface;
spange82006b2015-09-16 18:07:29726 if (GLSurfaceEGL::IsEGLSurfacelessContextSupported())
727 surface = CreateViewGLSurfaceOzoneSurfacelessSurfaceImpl(window);
728 if (!surface)
729 surface = CreateViewGLSurfaceOzone(window);
[email protected]502371d2014-03-31 17:16:42730 return surface;
[email protected]ffcdc9632014-03-27 17:25:23731 } else {
732 scoped_refptr<GLSurface> surface = new GLSurfaceStub();
733 if (surface->Initialize())
734 return surface;
735 }
spang0ac9fc32015-09-16 23:11:03736 return nullptr;
[email protected]ffcdc9632014-03-27 17:25:23737}
738
739// static
740scoped_refptr<GLSurface> GLSurface::CreateOffscreenGLSurface(
jinsukkim556e80df2016-02-24 01:01:32741 const gfx::Size& size) {
[email protected]ffcdc9632014-03-27 17:25:23742 switch (GetGLImplementation()) {
743 case kGLImplementationOSMesaGL: {
[email protected]dab86622014-08-16 14:34:59744 scoped_refptr<GLSurface> surface(
jinsukkim556e80df2016-02-24 01:01:32745 new GLSurfaceOSMesa(SURFACE_OSMESA_BGRA, size));
746 if (!surface->Initialize())
spang0ac9fc32015-09-16 23:11:03747 return nullptr;
[email protected]ffcdc9632014-03-27 17:25:23748
749 return surface;
750 }
751 case kGLImplementationEGLGLES2: {
752 scoped_refptr<GLSurface> surface;
753 if (GLSurfaceEGL::IsEGLSurfacelessContextSupported() &&
754 (size.width() == 0 && size.height() == 0)) {
755 surface = new SurfacelessEGL(size);
kylechar53c91f22016-02-11 20:57:44756 } else {
[email protected]ffcdc9632014-03-27 17:25:23757 surface = new PbufferGLSurfaceEGL(size);
kylechar53c91f22016-02-11 20:57:44758 }
[email protected]ffcdc9632014-03-27 17:25:23759
jinsukkim556e80df2016-02-24 01:01:32760 if (!surface->Initialize())
spang0ac9fc32015-09-16 23:11:03761 return nullptr;
[email protected]ffcdc9632014-03-27 17:25:23762 return surface;
763 }
zmoeecacfe2015-05-07 05:42:53764 case kGLImplementationMockGL:
765 return new GLSurfaceStub;
[email protected]ffcdc9632014-03-27 17:25:23766 default:
767 NOTREACHED();
spang0ac9fc32015-09-16 23:11:03768 return nullptr;
[email protected]ffcdc9632014-03-27 17:25:23769 }
770}
771
772EGLNativeDisplayType GetPlatformDefaultEGLNativeDisplay() {
dongseong.hwang9162b5fa2015-06-05 16:52:30773 return ui::OzonePlatform::GetInstance()
774 ->GetSurfaceFactoryOzone()
775 ->GetNativeDisplay();
[email protected]ffcdc9632014-03-27 17:25:23776}
777
778} // namespace gfx