blob: 173b7e4b2141cf04f626c2f463cecee2f95fd26b [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
achaulke86e411c2015-03-02 22:45:367#include "base/bind.h"
alexst165be972015-03-11 15:37:098#include "base/callback.h"
9#include "base/location.h"
[email protected]ffcdc9632014-03-27 17:25:2310#include "base/logging.h"
11#include "base/memory/ref_counted.h"
achaulk77f08ab2015-04-07 16:22:3412#include "base/memory/scoped_vector.h"
alexst165be972015-03-11 15:37:0913#include "base/memory/weak_ptr.h"
14#include "base/threading/worker_pool.h"
[email protected]ffcdc9632014-03-27 17:25:2315#include "ui/gfx/native_widget_types.h"
[email protected]aab13e2f2014-07-29 03:01:4516#include "ui/gl/gl_context.h"
[email protected]f46c2bd2014-08-16 07:47:0917#include "ui/gl/gl_image.h"
dongseong.hwang161c7a22015-07-29 18:28:1718#include "ui/gl/gl_image_ozone_native_pixmap.h"
[email protected]ffcdc9632014-03-27 17:25:2319#include "ui/gl/gl_implementation.h"
20#include "ui/gl/gl_surface_egl.h"
21#include "ui/gl/gl_surface_osmesa.h"
22#include "ui/gl/gl_surface_stub.h"
achaulke86e411c2015-03-02 22:45:3623#include "ui/gl/scoped_binders.h"
[email protected]aab13e2f2014-07-29 03:01:4524#include "ui/gl/scoped_make_current.h"
achaulke86e411c2015-03-02 22:45:3625#include "ui/ozone/public/native_pixmap.h"
dongseong.hwang9162b5fa2015-06-05 16:52:3026#include "ui/ozone/public/ozone_platform.h"
[email protected]0e37fc202014-06-20 13:24:0227#include "ui/ozone/public/surface_factory_ozone.h"
28#include "ui/ozone/public/surface_ozone_egl.h"
[email protected]ffcdc9632014-03-27 17:25:2329
30namespace gfx {
31
[email protected]502371d2014-03-31 17:16:4232namespace {
33
alexst165be972015-03-11 15:37:0934void WaitForFence(EGLDisplay display, EGLSyncKHR fence) {
35 eglClientWaitSyncKHR(display, fence, EGL_SYNC_FLUSH_COMMANDS_BIT_KHR,
36 EGL_FOREVER_KHR);
37}
38
[email protected]502371d2014-03-31 17:16:4239// A thin wrapper around GLSurfaceEGL that owns the EGLNativeWindow
40class GL_EXPORT GLSurfaceOzoneEGL : public NativeViewGLSurfaceEGL {
41 public:
[email protected]aab13e2f2014-07-29 03:01:4542 GLSurfaceOzoneEGL(scoped_ptr<ui::SurfaceOzoneEGL> ozone_surface,
alexste3e46052015-05-04 19:40:5643 AcceleratedWidget widget);
[email protected]502371d2014-03-31 17:16:4244
alexste3e46052015-05-04 19:40:5645 // GLSurface:
46 bool Initialize() override;
47 bool Resize(const gfx::Size& size) override;
achaulkec8c2db2015-05-29 16:35:0348 gfx::SwapResult SwapBuffers() override;
alexstfa14b6712015-01-05 19:29:4849 bool ScheduleOverlayPlane(int z_order,
50 OverlayTransform transform,
51 GLImage* image,
52 const Rect& bounds_rect,
alexste3e46052015-05-04 19:40:5653 const RectF& crop_rect) override;
[email protected]5780da092014-04-08 12:04:4154
[email protected]b8211e32014-04-01 22:58:4555 private:
achaulke79d5d852014-08-27 00:16:4256 using NativeViewGLSurfaceEGL::Initialize;
57
alexste3e46052015-05-04 19:40:5658 ~GLSurfaceOzoneEGL() override;
[email protected]502371d2014-03-31 17:16:4259
alexste3e46052015-05-04 19:40:5660 bool ReinitializeNativeSurface();
[email protected]aab13e2f2014-07-29 03:01:4561
[email protected]502371d2014-03-31 17:16:4262 // The native surface. Deleting this is allowed to free the EGLNativeWindow.
[email protected]0e37fc202014-06-20 13:24:0263 scoped_ptr<ui::SurfaceOzoneEGL> ozone_surface_;
[email protected]aab13e2f2014-07-29 03:01:4564 AcceleratedWidget widget_;
[email protected]502371d2014-03-31 17:16:4265
66 DISALLOW_COPY_AND_ASSIGN(GLSurfaceOzoneEGL);
67};
68
alexste3e46052015-05-04 19:40:5669GLSurfaceOzoneEGL::GLSurfaceOzoneEGL(
70 scoped_ptr<ui::SurfaceOzoneEGL> ozone_surface,
71 AcceleratedWidget widget)
72 : NativeViewGLSurfaceEGL(ozone_surface->GetNativeWindow()),
73 ozone_surface_(ozone_surface.Pass()),
74 widget_(widget) {
75}
76
77bool GLSurfaceOzoneEGL::Initialize() {
78 return Initialize(ozone_surface_->CreateVSyncProvider());
79}
80
81bool GLSurfaceOzoneEGL::Resize(const gfx::Size& size) {
82 if (!ozone_surface_->ResizeNativeWindow(size)) {
83 if (!ReinitializeNativeSurface() ||
84 !ozone_surface_->ResizeNativeWindow(size))
85 return false;
86 }
87
88 return NativeViewGLSurfaceEGL::Resize(size);
89}
90
achaulkec8c2db2015-05-29 16:35:0391gfx::SwapResult GLSurfaceOzoneEGL::SwapBuffers() {
92 gfx::SwapResult result = NativeViewGLSurfaceEGL::SwapBuffers();
93 if (result != gfx::SwapResult::SWAP_ACK)
94 return result;
alexste3e46052015-05-04 19:40:5695
achaulkec8c2db2015-05-29 16:35:0396 return ozone_surface_->OnSwapBuffers() ? gfx::SwapResult::SWAP_ACK
97 : gfx::SwapResult::SWAP_FAILED;
alexste3e46052015-05-04 19:40:5698}
99
100bool GLSurfaceOzoneEGL::ScheduleOverlayPlane(int z_order,
101 OverlayTransform transform,
102 GLImage* image,
103 const Rect& bounds_rect,
104 const RectF& crop_rect) {
105 return image->ScheduleOverlayPlane(widget_, z_order, transform, bounds_rect,
106 crop_rect);
107}
108
109GLSurfaceOzoneEGL::~GLSurfaceOzoneEGL() {
110 Destroy(); // EGL surface must be destroyed before SurfaceOzone
111}
112
113bool GLSurfaceOzoneEGL::ReinitializeNativeSurface() {
114 scoped_ptr<ui::ScopedMakeCurrent> scoped_make_current;
115 GLContext* current_context = GLContext::GetCurrent();
116 bool was_current = current_context && current_context->IsCurrent(this);
117 if (was_current) {
118 scoped_make_current.reset(new ui::ScopedMakeCurrent(current_context, this));
119 }
120
121 Destroy();
dongseong.hwang9162b5fa2015-06-05 16:52:30122 ozone_surface_ = ui::OzonePlatform::GetInstance()
123 ->GetSurfaceFactoryOzone()
alexste3e46052015-05-04 19:40:56124 ->CreateEGLSurfaceForWidget(widget_)
125 .Pass();
126 if (!ozone_surface_) {
127 LOG(ERROR) << "Failed to create native surface.";
128 return false;
129 }
130
131 window_ = ozone_surface_->GetNativeWindow();
132 if (!Initialize()) {
133 LOG(ERROR) << "Failed to initialize.";
134 return false;
135 }
136
137 return true;
138}
139
achaulke79d5d852014-08-27 00:16:42140class GL_EXPORT GLSurfaceOzoneSurfaceless : public SurfacelessEGL {
141 public:
142 GLSurfaceOzoneSurfaceless(scoped_ptr<ui::SurfaceOzoneEGL> ozone_surface,
alexste3e46052015-05-04 19:40:56143 AcceleratedWidget widget);
achaulke79d5d852014-08-27 00:16:42144
alexste3e46052015-05-04 19:40:56145 // GLSurface:
146 bool Initialize() override;
147 bool Resize(const gfx::Size& size) override;
achaulkec8c2db2015-05-29 16:35:03148 gfx::SwapResult SwapBuffers() override;
alexstfa14b6712015-01-05 19:29:48149 bool ScheduleOverlayPlane(int z_order,
150 OverlayTransform transform,
151 GLImage* image,
152 const Rect& bounds_rect,
alexste3e46052015-05-04 19:40:56153 const RectF& crop_rect) override;
154 bool IsOffscreen() override;
155 VSyncProvider* GetVSyncProvider() override;
156 bool SupportsPostSubBuffer() override;
achaulkec8c2db2015-05-29 16:35:03157 gfx::SwapResult PostSubBuffer(int x, int y, int width, int height) override;
alexste3e46052015-05-04 19:40:56158 bool SwapBuffersAsync(const SwapCompletionCallback& callback) override;
alexst409e3e02015-01-05 22:20:24159 bool PostSubBufferAsync(int x,
160 int y,
161 int width,
162 int height,
alexste3e46052015-05-04 19:40:56163 const SwapCompletionCallback& callback) override;
achaulke79d5d852014-08-27 00:16:42164
achaulke86e411c2015-03-02 22:45:36165 protected:
alexste3e46052015-05-04 19:40:56166 struct Overlay {
167 Overlay(int z_order,
168 OverlayTransform transform,
169 GLImage* image,
170 const Rect& bounds_rect,
171 const RectF& crop_rect);
172
173 bool ScheduleOverlayPlane(gfx::AcceleratedWidget widget) const;
174
175 int z_order;
176 OverlayTransform transform;
177 scoped_refptr<GLImage> image;
178 Rect bounds_rect;
179 RectF crop_rect;
180 };
181
achaulk77f08ab2015-04-07 16:22:34182 struct PendingFrame {
alexste3e46052015-05-04 19:40:56183 PendingFrame();
achaulk77f08ab2015-04-07 16:22:34184
alexste3e46052015-05-04 19:40:56185 bool ScheduleOverlayPlanes(gfx::AcceleratedWidget widget);
achaulk77f08ab2015-04-07 16:22:34186
achaulk77f08ab2015-04-07 16:22:34187 bool ready;
188 std::vector<Overlay> overlays;
189 SwapCompletionCallback callback;
190 };
191
alexste3e46052015-05-04 19:40:56192 ~GLSurfaceOzoneSurfaceless() override;
achaulke79d5d852014-08-27 00:16:42193
alexste3e46052015-05-04 19:40:56194 void SubmitFrame();
alexst9c973212015-04-24 14:28:45195
alexste3e46052015-05-04 19:40:56196 EGLSyncKHR InsertFence();
197 void FenceRetired(EGLSyncKHR fence, PendingFrame* frame);
alexst9c973212015-04-24 14:28:45198
achaulkec8c2db2015-05-29 16:35:03199 void SwapCompleted(const SwapCompletionCallback& callback,
200 gfx::SwapResult result);
dbehr5addbd52015-02-07 03:18:05201
achaulke79d5d852014-08-27 00:16:42202 // The native surface. Deleting this is allowed to free the EGLNativeWindow.
203 scoped_ptr<ui::SurfaceOzoneEGL> ozone_surface_;
204 AcceleratedWidget widget_;
205 scoped_ptr<VSyncProvider> vsync_provider_;
achaulk77f08ab2015-04-07 16:22:34206 ScopedVector<PendingFrame> unsubmitted_frames_;
dbehr5addbd52015-02-07 03:18:05207 bool has_implicit_external_sync_;
alexst165be972015-03-11 15:37:09208 bool last_swap_buffers_result_;
alexst9c973212015-04-24 14:28:45209 bool swap_buffers_pending_;
alexst165be972015-03-11 15:37:09210
211 base::WeakPtrFactory<GLSurfaceOzoneSurfaceless> weak_factory_;
212
achaulke79d5d852014-08-27 00:16:42213 DISALLOW_COPY_AND_ASSIGN(GLSurfaceOzoneSurfaceless);
214};
215
alexste3e46052015-05-04 19:40:56216GLSurfaceOzoneSurfaceless::Overlay::Overlay(int z_order,
217 OverlayTransform transform,
218 GLImage* image,
219 const Rect& bounds_rect,
220 const RectF& crop_rect)
221 : z_order(z_order),
222 transform(transform),
223 image(image),
224 bounds_rect(bounds_rect),
225 crop_rect(crop_rect) {
226}
227
228bool GLSurfaceOzoneSurfaceless::Overlay::ScheduleOverlayPlane(
229 gfx::AcceleratedWidget widget) const {
230 return image->ScheduleOverlayPlane(widget, z_order, transform, bounds_rect,
231 crop_rect);
232}
233
234GLSurfaceOzoneSurfaceless::PendingFrame::PendingFrame() : ready(false) {
235}
236
237bool GLSurfaceOzoneSurfaceless::PendingFrame::ScheduleOverlayPlanes(
238 gfx::AcceleratedWidget widget) {
239 for (const auto& overlay : overlays)
240 if (!overlay.ScheduleOverlayPlane(widget))
241 return false;
242 return true;
243}
244
245GLSurfaceOzoneSurfaceless::GLSurfaceOzoneSurfaceless(
246 scoped_ptr<ui::SurfaceOzoneEGL> ozone_surface,
247 AcceleratedWidget widget)
248 : SurfacelessEGL(gfx::Size()),
249 ozone_surface_(ozone_surface.Pass()),
250 widget_(widget),
251 has_implicit_external_sync_(
252 HasEGLExtension("EGL_ARM_implicit_external_sync")),
253 last_swap_buffers_result_(true),
254 swap_buffers_pending_(false),
255 weak_factory_(this) {
256 unsubmitted_frames_.push_back(new PendingFrame());
257}
258
259bool GLSurfaceOzoneSurfaceless::Initialize() {
260 if (!SurfacelessEGL::Initialize())
261 return false;
262 vsync_provider_ = ozone_surface_->CreateVSyncProvider();
263 if (!vsync_provider_)
264 return false;
265 return true;
266}
267bool GLSurfaceOzoneSurfaceless::Resize(const gfx::Size& size) {
268 if (!ozone_surface_->ResizeNativeWindow(size))
269 return false;
270
271 return SurfacelessEGL::Resize(size);
272}
achaulkec8c2db2015-05-29 16:35:03273gfx::SwapResult GLSurfaceOzoneSurfaceless::SwapBuffers() {
alexste3e46052015-05-04 19:40:56274 glFlush();
275 // TODO: the following should be replaced by a per surface flush as it gets
276 // implemented in GL drivers.
277 if (has_implicit_external_sync_) {
278 EGLSyncKHR fence = InsertFence();
279 if (!fence)
achaulkec8c2db2015-05-29 16:35:03280 return SwapResult::SWAP_FAILED;
alexste3e46052015-05-04 19:40:56281
282 EGLDisplay display = GetDisplay();
283 WaitForFence(display, fence);
284 eglDestroySyncKHR(display, fence);
285 } else if (ozone_surface_->IsUniversalDisplayLinkDevice()) {
286 glFinish();
287 }
288
289 unsubmitted_frames_.back()->ScheduleOverlayPlanes(widget_);
290 unsubmitted_frames_.back()->overlays.clear();
291
achaulkec8c2db2015-05-29 16:35:03292 return ozone_surface_->OnSwapBuffers() ? gfx::SwapResult::SWAP_ACK
293 : gfx::SwapResult::SWAP_FAILED;
alexste3e46052015-05-04 19:40:56294}
295bool GLSurfaceOzoneSurfaceless::ScheduleOverlayPlane(int z_order,
296 OverlayTransform transform,
297 GLImage* image,
298 const Rect& bounds_rect,
299 const RectF& crop_rect) {
300 unsubmitted_frames_.back()->overlays.push_back(
301 Overlay(z_order, transform, image, bounds_rect, crop_rect));
302 return true;
303}
304bool GLSurfaceOzoneSurfaceless::IsOffscreen() {
305 return false;
306}
307VSyncProvider* GLSurfaceOzoneSurfaceless::GetVSyncProvider() {
308 return vsync_provider_.get();
309}
310bool GLSurfaceOzoneSurfaceless::SupportsPostSubBuffer() {
311 return true;
312}
achaulkec8c2db2015-05-29 16:35:03313gfx::SwapResult GLSurfaceOzoneSurfaceless::PostSubBuffer(int x,
314 int y,
315 int width,
316 int height) {
alexste3e46052015-05-04 19:40:56317 // The actual sub buffer handling is handled at higher layers.
318 SwapBuffers();
achaulkec8c2db2015-05-29 16:35:03319 return gfx::SwapResult::SWAP_ACK;
alexste3e46052015-05-04 19:40:56320}
321bool GLSurfaceOzoneSurfaceless::SwapBuffersAsync(
322 const SwapCompletionCallback& callback) {
323 // If last swap failed, don't try to schedule new ones.
324 if (!last_swap_buffers_result_)
325 return false;
326
327 glFlush();
328
achaulkec8c2db2015-05-29 16:35:03329 SwapCompletionCallback surface_swap_callback =
alexste3e46052015-05-04 19:40:56330 base::Bind(&GLSurfaceOzoneSurfaceless::SwapCompleted,
331 weak_factory_.GetWeakPtr(), callback);
332
333 PendingFrame* frame = unsubmitted_frames_.back();
334 frame->callback = surface_swap_callback;
335 unsubmitted_frames_.push_back(new PendingFrame());
336
337 // TODO: the following should be replaced by a per surface flush as it gets
338 // implemented in GL drivers.
339 if (has_implicit_external_sync_) {
340 EGLSyncKHR fence = InsertFence();
341 if (!fence)
342 return false;
343
344 base::Closure fence_wait_task =
345 base::Bind(&WaitForFence, GetDisplay(), fence);
346
347 base::Closure fence_retired_callback =
348 base::Bind(&GLSurfaceOzoneSurfaceless::FenceRetired,
349 weak_factory_.GetWeakPtr(), fence, frame);
350
351 base::WorkerPool::PostTaskAndReply(FROM_HERE, fence_wait_task,
352 fence_retired_callback, false);
353 return true;
354 } else if (ozone_surface_->IsUniversalDisplayLinkDevice()) {
355 glFinish();
356 }
357
358 frame->ready = true;
359 SubmitFrame();
360 return last_swap_buffers_result_;
361}
362bool GLSurfaceOzoneSurfaceless::PostSubBufferAsync(
363 int x,
364 int y,
365 int width,
366 int height,
367 const SwapCompletionCallback& callback) {
368 return SwapBuffersAsync(callback);
369}
370
371GLSurfaceOzoneSurfaceless::~GLSurfaceOzoneSurfaceless() {
372 Destroy(); // EGL surface must be destroyed before SurfaceOzone
373}
374
375void GLSurfaceOzoneSurfaceless::SubmitFrame() {
376 DCHECK(!unsubmitted_frames_.empty());
377
378 if (unsubmitted_frames_.front()->ready && !swap_buffers_pending_) {
379 scoped_ptr<PendingFrame> frame(unsubmitted_frames_.front());
380 unsubmitted_frames_.weak_erase(unsubmitted_frames_.begin());
381 swap_buffers_pending_ = true;
382
383 last_swap_buffers_result_ =
384 frame->ScheduleOverlayPlanes(widget_) &&
385 ozone_surface_->OnSwapBuffersAsync(frame->callback);
386 }
387}
388
389EGLSyncKHR GLSurfaceOzoneSurfaceless::InsertFence() {
390 const EGLint attrib_list[] = {EGL_SYNC_CONDITION_KHR,
391 EGL_SYNC_PRIOR_COMMANDS_IMPLICIT_EXTERNAL_ARM,
392 EGL_NONE};
393 return eglCreateSyncKHR(GetDisplay(), EGL_SYNC_FENCE_KHR, attrib_list);
394}
395
396void GLSurfaceOzoneSurfaceless::FenceRetired(EGLSyncKHR fence,
397 PendingFrame* frame) {
398 eglDestroySyncKHR(GetDisplay(), fence);
399 frame->ready = true;
400 SubmitFrame();
401}
402
403void GLSurfaceOzoneSurfaceless::SwapCompleted(
achaulkec8c2db2015-05-29 16:35:03404 const SwapCompletionCallback& callback,
405 gfx::SwapResult result) {
406 callback.Run(result);
alexste3e46052015-05-04 19:40:56407 swap_buffers_pending_ = false;
408
409 SubmitFrame();
410}
411
achaulke86e411c2015-03-02 22:45:36412// This provides surface-like semantics implemented through surfaceless.
413// A framebuffer is bound automatically.
414class GL_EXPORT GLSurfaceOzoneSurfacelessSurfaceImpl
415 : public GLSurfaceOzoneSurfaceless {
416 public:
417 GLSurfaceOzoneSurfacelessSurfaceImpl(
418 scoped_ptr<ui::SurfaceOzoneEGL> ozone_surface,
alexste3e46052015-05-04 19:40:56419 AcceleratedWidget widget);
achaulke86e411c2015-03-02 22:45:36420
alexste3e46052015-05-04 19:40:56421 // GLSurface:
422 unsigned int GetBackingFrameBufferObject() override;
423 bool OnMakeCurrent(GLContext* context) override;
424 bool Resize(const gfx::Size& size) override;
425 bool SupportsPostSubBuffer() override;
achaulkec8c2db2015-05-29 16:35:03426 gfx::SwapResult SwapBuffers() override;
alexste3e46052015-05-04 19:40:56427 bool SwapBuffersAsync(const SwapCompletionCallback& callback) override;
428 void Destroy() override;
achaulke86e411c2015-03-02 22:45:36429
430 private:
alexste3e46052015-05-04 19:40:56431 ~GLSurfaceOzoneSurfacelessSurfaceImpl() override;
achaulke86e411c2015-03-02 22:45:36432
alexste3e46052015-05-04 19:40:56433 void BindFramebuffer();
434 bool CreatePixmaps();
achaulke86e411c2015-03-02 22:45:36435
achaulk8d645d292015-08-04 14:09:27436 scoped_refptr<GLContext> context_;
achaulke86e411c2015-03-02 22:45:36437 GLuint fbo_;
438 GLuint textures_[2];
439 scoped_refptr<GLImage> images_[2];
440 int current_surface_;
441 DISALLOW_COPY_AND_ASSIGN(GLSurfaceOzoneSurfacelessSurfaceImpl);
442};
443
alexste3e46052015-05-04 19:40:56444GLSurfaceOzoneSurfacelessSurfaceImpl::GLSurfaceOzoneSurfacelessSurfaceImpl(
445 scoped_ptr<ui::SurfaceOzoneEGL> ozone_surface,
446 AcceleratedWidget widget)
447 : GLSurfaceOzoneSurfaceless(ozone_surface.Pass(), widget),
achaulk8d645d292015-08-04 14:09:27448 context_(nullptr),
alexste3e46052015-05-04 19:40:56449 fbo_(0),
450 current_surface_(0) {
451 for (auto& texture : textures_)
452 texture = 0;
453}
454
455unsigned int
456GLSurfaceOzoneSurfacelessSurfaceImpl::GetBackingFrameBufferObject() {
457 return fbo_;
458}
459
460bool GLSurfaceOzoneSurfacelessSurfaceImpl::OnMakeCurrent(GLContext* context) {
achaulk8d645d292015-08-04 14:09:27461 DCHECK(!context_ || context == context_);
462 context_ = context;
alexste3e46052015-05-04 19:40:56463 if (!fbo_) {
464 glGenFramebuffersEXT(1, &fbo_);
465 if (!fbo_)
466 return false;
467 glGenTextures(arraysize(textures_), textures_);
468 if (!CreatePixmaps())
469 return false;
470 }
471 BindFramebuffer();
472 glBindFramebufferEXT(GL_FRAMEBUFFER, fbo_);
473 return SurfacelessEGL::OnMakeCurrent(context);
474}
475
476bool GLSurfaceOzoneSurfacelessSurfaceImpl::Resize(const gfx::Size& size) {
477 if (size == GetSize())
478 return true;
479 return GLSurfaceOzoneSurfaceless::Resize(size) && CreatePixmaps();
480}
481
482bool GLSurfaceOzoneSurfacelessSurfaceImpl::SupportsPostSubBuffer() {
483 return false;
484}
485
achaulkec8c2db2015-05-29 16:35:03486gfx::SwapResult GLSurfaceOzoneSurfacelessSurfaceImpl::SwapBuffers() {
alexste3e46052015-05-04 19:40:56487 if (!images_[current_surface_]->ScheduleOverlayPlane(
488 widget_, 0, OverlayTransform::OVERLAY_TRANSFORM_NONE,
489 gfx::Rect(GetSize()), gfx::RectF(1, 1)))
achaulkec8c2db2015-05-29 16:35:03490 return gfx::SwapResult::SWAP_FAILED;
491 gfx::SwapResult result = GLSurfaceOzoneSurfaceless::SwapBuffers();
492 if (result != gfx::SwapResult::SWAP_ACK)
493 return result;
alexste3e46052015-05-04 19:40:56494 current_surface_ ^= 1;
495 BindFramebuffer();
achaulkec8c2db2015-05-29 16:35:03496 return gfx::SwapResult::SWAP_ACK;
alexste3e46052015-05-04 19:40:56497}
498
499bool GLSurfaceOzoneSurfacelessSurfaceImpl::SwapBuffersAsync(
500 const SwapCompletionCallback& callback) {
501 if (!images_[current_surface_]->ScheduleOverlayPlane(
502 widget_, 0, OverlayTransform::OVERLAY_TRANSFORM_NONE,
503 gfx::Rect(GetSize()), gfx::RectF(1, 1)))
504 return false;
505 if (!GLSurfaceOzoneSurfaceless::SwapBuffersAsync(callback))
506 return false;
507 current_surface_ ^= 1;
508 BindFramebuffer();
509 return true;
510}
511
512void GLSurfaceOzoneSurfacelessSurfaceImpl::Destroy() {
achaulk8d645d292015-08-04 14:09:27513 if (!context_)
514 return;
515 ui::ScopedMakeCurrent context(context_.get(), this);
alexste3e46052015-05-04 19:40:56516 glBindFramebufferEXT(GL_FRAMEBUFFER, 0);
517 if (fbo_) {
518 glDeleteTextures(arraysize(textures_), textures_);
519 for (auto& texture : textures_)
520 texture = 0;
521 glDeleteFramebuffersEXT(1, &fbo_);
522 fbo_ = 0;
523 }
524 for (auto image : images_) {
525 if (image)
526 image->Destroy(true);
527 }
528}
529
530GLSurfaceOzoneSurfacelessSurfaceImpl::~GLSurfaceOzoneSurfacelessSurfaceImpl() {
531 DCHECK(!fbo_);
532 for (size_t i = 0; i < arraysize(textures_); i++)
533 DCHECK(!textures_[i]) << "texture " << i << " not released";
534}
535
536void GLSurfaceOzoneSurfacelessSurfaceImpl::BindFramebuffer() {
537 ScopedFrameBufferBinder fb(fbo_);
538 glFramebufferTexture2DEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
539 textures_[current_surface_], 0);
540}
541
542bool GLSurfaceOzoneSurfacelessSurfaceImpl::CreatePixmaps() {
543 if (!fbo_)
544 return true;
545 for (size_t i = 0; i < arraysize(textures_); i++) {
546 scoped_refptr<ui::NativePixmap> pixmap =
dongseong.hwang9162b5fa2015-06-05 16:52:30547 ui::OzonePlatform::GetInstance()
548 ->GetSurfaceFactoryOzone()
549 ->CreateNativePixmap(widget_, GetSize(),
spangfcf5fab42015-08-04 19:25:35550 gfx::BufferFormat::BGRA_8888,
551 gfx::BufferUsage::SCANOUT);
alexste3e46052015-05-04 19:40:56552 if (!pixmap)
553 return false;
dongseong.hwang161c7a22015-07-29 18:28:17554 scoped_refptr<GLImageOzoneNativePixmap> image =
555 new GLImageOzoneNativePixmap(GetSize(), GL_BGRA_EXT);
spangfcf5fab42015-08-04 19:25:35556 if (!image->Initialize(pixmap.get(), gfx::BufferFormat::BGRA_8888))
alexste3e46052015-05-04 19:40:56557 return false;
558 images_[i] = image;
559 // Bind image to texture.
560 ScopedTextureBinder binder(GL_TEXTURE_2D, textures_[i]);
561 if (!images_[i]->BindTexImage(GL_TEXTURE_2D))
562 return false;
563 }
564 return true;
565}
566
spange82006b2015-09-16 18:07:29567scoped_refptr<GLSurface> CreateViewGLSurfaceOzone(
568 gfx::AcceleratedWidget window) {
569 scoped_ptr<ui::SurfaceOzoneEGL> surface_ozone =
570 ui::OzonePlatform::GetInstance()
571 ->GetSurfaceFactoryOzone()
572 ->CreateEGLSurfaceForWidget(window);
573 if (!surface_ozone)
574 return nullptr;
575 scoped_refptr<GLSurface> surface =
576 new GLSurfaceOzoneEGL(surface_ozone.Pass(), window);
577 if (!surface->Initialize())
578 return nullptr;
579 return surface;
580}
581
582scoped_refptr<GLSurface> CreateViewGLSurfaceOzoneSurfacelessSurfaceImpl(
583 gfx::AcceleratedWidget window) {
584 scoped_ptr<ui::SurfaceOzoneEGL> surface_ozone =
585 ui::OzonePlatform::GetInstance()
586 ->GetSurfaceFactoryOzone()
587 ->CreateSurfacelessEGLSurfaceForWidget(window);
588 if (!surface_ozone)
589 return nullptr;
590 scoped_refptr<GLSurface> surface =
591 new GLSurfaceOzoneSurfacelessSurfaceImpl(surface_ozone.Pass(), window);
592 if (!surface->Initialize())
593 return nullptr;
594 return surface;
595}
596
[email protected]502371d2014-03-31 17:16:42597} // namespace
598
[email protected]ffcdc9632014-03-27 17:25:23599// static
600bool GLSurface::InitializeOneOffInternal() {
[email protected]ffcdc9632014-03-27 17:25:23601 switch (GetGLImplementation()) {
602 case kGLImplementationEGLGLES2:
[email protected]ffcdc9632014-03-27 17:25:23603 if (!GLSurfaceEGL::InitializeOneOff()) {
604 LOG(ERROR) << "GLSurfaceEGL::InitializeOneOff failed.";
605 return false;
606 }
[email protected]1fe750572014-03-29 01:22:34607
608 return true;
609 case kGLImplementationOSMesaGL:
610 case kGLImplementationMockGL:
611 return true;
[email protected]ffcdc9632014-03-27 17:25:23612 default:
[email protected]1fe750572014-03-29 01:22:34613 return false;
[email protected]ffcdc9632014-03-27 17:25:23614 }
[email protected]ffcdc9632014-03-27 17:25:23615}
616
617// static
achaulke86e411c2015-03-02 22:45:36618scoped_refptr<GLSurface> GLSurface::CreateSurfacelessViewGLSurface(
619 gfx::AcceleratedWidget window) {
620 if (GetGLImplementation() == kGLImplementationEGLGLES2 &&
621 window != kNullAcceleratedWidget &&
spange82006b2015-09-16 18:07:29622 GLSurfaceEGL::IsEGLSurfacelessContextSupported()) {
achaulke86e411c2015-03-02 22:45:36623 scoped_ptr<ui::SurfaceOzoneEGL> surface_ozone =
dongseong.hwang9162b5fa2015-06-05 16:52:30624 ui::OzonePlatform::GetInstance()
625 ->GetSurfaceFactoryOzone()
achaulke86e411c2015-03-02 22:45:36626 ->CreateSurfacelessEGLSurfaceForWidget(window);
627 if (!surface_ozone)
628 return nullptr;
629 scoped_refptr<GLSurface> surface;
630 surface = new GLSurfaceOzoneSurfaceless(surface_ozone.Pass(), window);
631 if (surface->Initialize())
632 return surface;
633 }
634
635 return nullptr;
636}
637
638// static
[email protected]ffcdc9632014-03-27 17:25:23639scoped_refptr<GLSurface> GLSurface::CreateViewGLSurface(
640 gfx::AcceleratedWidget window) {
641 if (GetGLImplementation() == kGLImplementationOSMesaGL) {
642 scoped_refptr<GLSurface> surface(new GLSurfaceOSMesaHeadless());
643 if (!surface->Initialize())
644 return NULL;
645 return surface;
646 }
647 DCHECK(GetGLImplementation() == kGLImplementationEGLGLES2);
648 if (window != kNullAcceleratedWidget) {
achaulke79d5d852014-08-27 00:16:42649 scoped_refptr<GLSurface> surface;
spange82006b2015-09-16 18:07:29650 if (GLSurfaceEGL::IsEGLSurfacelessContextSupported())
651 surface = CreateViewGLSurfaceOzoneSurfacelessSurfaceImpl(window);
652 if (!surface)
653 surface = CreateViewGLSurfaceOzone(window);
[email protected]502371d2014-03-31 17:16:42654 return surface;
[email protected]ffcdc9632014-03-27 17:25:23655 } else {
656 scoped_refptr<GLSurface> surface = new GLSurfaceStub();
657 if (surface->Initialize())
658 return surface;
659 }
660 return NULL;
661}
662
663// static
664scoped_refptr<GLSurface> GLSurface::CreateOffscreenGLSurface(
665 const gfx::Size& size) {
666 switch (GetGLImplementation()) {
667 case kGLImplementationOSMesaGL: {
[email protected]dab86622014-08-16 14:34:59668 scoped_refptr<GLSurface> surface(
669 new GLSurfaceOSMesa(OSMesaSurfaceFormatBGRA, size));
[email protected]ffcdc9632014-03-27 17:25:23670 if (!surface->Initialize())
671 return NULL;
672
673 return surface;
674 }
675 case kGLImplementationEGLGLES2: {
676 scoped_refptr<GLSurface> surface;
677 if (GLSurfaceEGL::IsEGLSurfacelessContextSupported() &&
678 (size.width() == 0 && size.height() == 0)) {
679 surface = new SurfacelessEGL(size);
680 } else
681 surface = new PbufferGLSurfaceEGL(size);
682
683 if (!surface->Initialize())
684 return NULL;
685 return surface;
686 }
zmoeecacfe2015-05-07 05:42:53687 case kGLImplementationMockGL:
688 return new GLSurfaceStub;
[email protected]ffcdc9632014-03-27 17:25:23689 default:
690 NOTREACHED();
691 return NULL;
692 }
693}
694
695EGLNativeDisplayType GetPlatformDefaultEGLNativeDisplay() {
dongseong.hwang9162b5fa2015-06-05 16:52:30696 return ui::OzonePlatform::GetInstance()
697 ->GetSurfaceFactoryOzone()
698 ->GetNativeDisplay();
[email protected]ffcdc9632014-03-27 17:25:23699}
700
701} // namespace gfx