blob: 289755b1d3a14a29f3ae0c4da88ba7e6456644c1 [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
tfarinadf856e022015-10-29 12:50:4530using gl::GLImage;
31
[email protected]ffcdc9632014-03-27 17:25:2332namespace gfx {
33
[email protected]502371d2014-03-31 17:16:4234namespace {
35
alexst165be972015-03-11 15:37:0936void WaitForFence(EGLDisplay display, EGLSyncKHR fence) {
37 eglClientWaitSyncKHR(display, fence, EGL_SYNC_FLUSH_COMMANDS_BIT_KHR,
38 EGL_FOREVER_KHR);
39}
40
spang0ac9fc32015-09-16 23:11:0341// A thin wrapper around GLSurfaceEGL that owns the EGLNativeWindow.
[email protected]502371d2014-03-31 17:16:4242class GL_EXPORT GLSurfaceOzoneEGL : public NativeViewGLSurfaceEGL {
43 public:
[email protected]aab13e2f2014-07-29 03:01:4544 GLSurfaceOzoneEGL(scoped_ptr<ui::SurfaceOzoneEGL> ozone_surface,
alexste3e46052015-05-04 19:40:5645 AcceleratedWidget widget);
[email protected]502371d2014-03-31 17:16:4246
alexste3e46052015-05-04 19:40:5647 // GLSurface:
48 bool Initialize() override;
jbaumance45e112015-10-30 02:33:5749 bool Resize(const gfx::Size& size, float scale_factor) override;
achaulkec8c2db2015-05-29 16:35:0350 gfx::SwapResult SwapBuffers() override;
alexstfa14b6712015-01-05 19:29:4851 bool ScheduleOverlayPlane(int z_order,
52 OverlayTransform transform,
53 GLImage* image,
54 const Rect& bounds_rect,
alexste3e46052015-05-04 19:40:5655 const RectF& crop_rect) override;
[email protected]5780da092014-04-08 12:04:4156
[email protected]b8211e32014-04-01 22:58:4557 private:
achaulke79d5d852014-08-27 00:16:4258 using NativeViewGLSurfaceEGL::Initialize;
59
alexste3e46052015-05-04 19:40:5660 ~GLSurfaceOzoneEGL() override;
[email protected]502371d2014-03-31 17:16:4261
alexste3e46052015-05-04 19:40:5662 bool ReinitializeNativeSurface();
[email protected]aab13e2f2014-07-29 03:01:4563
[email protected]502371d2014-03-31 17:16:4264 // The native surface. Deleting this is allowed to free the EGLNativeWindow.
[email protected]0e37fc202014-06-20 13:24:0265 scoped_ptr<ui::SurfaceOzoneEGL> ozone_surface_;
[email protected]aab13e2f2014-07-29 03:01:4566 AcceleratedWidget widget_;
[email protected]502371d2014-03-31 17:16:4267
68 DISALLOW_COPY_AND_ASSIGN(GLSurfaceOzoneEGL);
69};
70
alexste3e46052015-05-04 19:40:5671GLSurfaceOzoneEGL::GLSurfaceOzoneEGL(
72 scoped_ptr<ui::SurfaceOzoneEGL> ozone_surface,
73 AcceleratedWidget widget)
74 : NativeViewGLSurfaceEGL(ozone_surface->GetNativeWindow()),
75 ozone_surface_(ozone_surface.Pass()),
spang0ac9fc32015-09-16 23:11:0376 widget_(widget) {}
alexste3e46052015-05-04 19:40:5677
78bool GLSurfaceOzoneEGL::Initialize() {
79 return Initialize(ozone_surface_->CreateVSyncProvider());
80}
81
jbaumance45e112015-10-30 02:33:5782bool GLSurfaceOzoneEGL::Resize(const gfx::Size& size, float scale_factor) {
alexste3e46052015-05-04 19:40:5683 if (!ozone_surface_->ResizeNativeWindow(size)) {
84 if (!ReinitializeNativeSurface() ||
85 !ozone_surface_->ResizeNativeWindow(size))
86 return false;
87 }
88
jbaumance45e112015-10-30 02:33:5789 return NativeViewGLSurfaceEGL::Resize(size, scale_factor);
alexste3e46052015-05-04 19:40:5690}
91
achaulkec8c2db2015-05-29 16:35:0392gfx::SwapResult GLSurfaceOzoneEGL::SwapBuffers() {
93 gfx::SwapResult result = NativeViewGLSurfaceEGL::SwapBuffers();
94 if (result != gfx::SwapResult::SWAP_ACK)
95 return result;
alexste3e46052015-05-04 19:40:5696
achaulkec8c2db2015-05-29 16:35:0397 return ozone_surface_->OnSwapBuffers() ? gfx::SwapResult::SWAP_ACK
98 : gfx::SwapResult::SWAP_FAILED;
alexste3e46052015-05-04 19:40:5699}
100
101bool GLSurfaceOzoneEGL::ScheduleOverlayPlane(int z_order,
102 OverlayTransform transform,
103 GLImage* image,
104 const Rect& bounds_rect,
105 const RectF& crop_rect) {
106 return image->ScheduleOverlayPlane(widget_, z_order, transform, bounds_rect,
107 crop_rect);
108}
109
110GLSurfaceOzoneEGL::~GLSurfaceOzoneEGL() {
spang0ac9fc32015-09-16 23:11:03111 Destroy(); // The EGL surface must be destroyed before SurfaceOzone.
alexste3e46052015-05-04 19:40:56112}
113
114bool GLSurfaceOzoneEGL::ReinitializeNativeSurface() {
115 scoped_ptr<ui::ScopedMakeCurrent> scoped_make_current;
116 GLContext* current_context = GLContext::GetCurrent();
117 bool was_current = current_context && current_context->IsCurrent(this);
118 if (was_current) {
119 scoped_make_current.reset(new ui::ScopedMakeCurrent(current_context, this));
120 }
121
122 Destroy();
dongseong.hwang9162b5fa2015-06-05 16:52:30123 ozone_surface_ = ui::OzonePlatform::GetInstance()
124 ->GetSurfaceFactoryOzone()
spang0ac9fc32015-09-16 23:11:03125 ->CreateEGLSurfaceForWidget(widget_);
alexste3e46052015-05-04 19:40:56126 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;
jbaumance45e112015-10-30 02:33:57147 bool Resize(const gfx::Size& size, float scale_factor) 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),
spang0ac9fc32015-09-16 23:11:03225 crop_rect(crop_rect) {}
alexste3e46052015-05-04 19:40:56226
227bool GLSurfaceOzoneSurfaceless::Overlay::ScheduleOverlayPlane(
228 gfx::AcceleratedWidget widget) const {
229 return image->ScheduleOverlayPlane(widget, z_order, transform, bounds_rect,
230 crop_rect);
231}
232
spang0ac9fc32015-09-16 23:11:03233GLSurfaceOzoneSurfaceless::PendingFrame::PendingFrame() : ready(false) {}
alexste3e46052015-05-04 19:40:56234
235bool GLSurfaceOzoneSurfaceless::PendingFrame::ScheduleOverlayPlanes(
236 gfx::AcceleratedWidget widget) {
237 for (const auto& overlay : overlays)
238 if (!overlay.ScheduleOverlayPlane(widget))
239 return false;
240 return true;
241}
242
243GLSurfaceOzoneSurfaceless::GLSurfaceOzoneSurfaceless(
244 scoped_ptr<ui::SurfaceOzoneEGL> ozone_surface,
245 AcceleratedWidget widget)
246 : SurfacelessEGL(gfx::Size()),
247 ozone_surface_(ozone_surface.Pass()),
248 widget_(widget),
249 has_implicit_external_sync_(
250 HasEGLExtension("EGL_ARM_implicit_external_sync")),
251 last_swap_buffers_result_(true),
252 swap_buffers_pending_(false),
253 weak_factory_(this) {
254 unsubmitted_frames_.push_back(new PendingFrame());
255}
256
257bool GLSurfaceOzoneSurfaceless::Initialize() {
258 if (!SurfacelessEGL::Initialize())
259 return false;
260 vsync_provider_ = ozone_surface_->CreateVSyncProvider();
261 if (!vsync_provider_)
262 return false;
263 return true;
264}
spang0ac9fc32015-09-16 23:11:03265
jbaumance45e112015-10-30 02:33:57266bool GLSurfaceOzoneSurfaceless::Resize(const gfx::Size& size,
267 float scale_factor) {
alexste3e46052015-05-04 19:40:56268 if (!ozone_surface_->ResizeNativeWindow(size))
269 return false;
270
jbaumance45e112015-10-30 02:33:57271 return SurfacelessEGL::Resize(size, scale_factor);
alexste3e46052015-05-04 19:40:56272}
spang0ac9fc32015-09-16 23:11:03273
achaulkec8c2db2015-05-29 16:35:03274gfx::SwapResult GLSurfaceOzoneSurfaceless::SwapBuffers() {
alexste3e46052015-05-04 19:40:56275 glFlush();
276 // TODO: the following should be replaced by a per surface flush as it gets
277 // implemented in GL drivers.
278 if (has_implicit_external_sync_) {
279 EGLSyncKHR fence = InsertFence();
280 if (!fence)
achaulkec8c2db2015-05-29 16:35:03281 return SwapResult::SWAP_FAILED;
alexste3e46052015-05-04 19:40:56282
283 EGLDisplay display = GetDisplay();
284 WaitForFence(display, fence);
285 eglDestroySyncKHR(display, fence);
286 } else if (ozone_surface_->IsUniversalDisplayLinkDevice()) {
287 glFinish();
288 }
289
290 unsubmitted_frames_.back()->ScheduleOverlayPlanes(widget_);
291 unsubmitted_frames_.back()->overlays.clear();
292
achaulkec8c2db2015-05-29 16:35:03293 return ozone_surface_->OnSwapBuffers() ? gfx::SwapResult::SWAP_ACK
294 : gfx::SwapResult::SWAP_FAILED;
alexste3e46052015-05-04 19:40:56295}
spang0ac9fc32015-09-16 23:11:03296
alexste3e46052015-05-04 19:40:56297bool GLSurfaceOzoneSurfaceless::ScheduleOverlayPlane(int z_order,
298 OverlayTransform transform,
299 GLImage* image,
300 const Rect& bounds_rect,
301 const RectF& crop_rect) {
302 unsubmitted_frames_.back()->overlays.push_back(
303 Overlay(z_order, transform, image, bounds_rect, crop_rect));
304 return true;
305}
spang0ac9fc32015-09-16 23:11:03306
alexste3e46052015-05-04 19:40:56307bool GLSurfaceOzoneSurfaceless::IsOffscreen() {
308 return false;
309}
spang0ac9fc32015-09-16 23:11:03310
alexste3e46052015-05-04 19:40:56311VSyncProvider* GLSurfaceOzoneSurfaceless::GetVSyncProvider() {
312 return vsync_provider_.get();
313}
spang0ac9fc32015-09-16 23:11:03314
alexste3e46052015-05-04 19:40:56315bool GLSurfaceOzoneSurfaceless::SupportsPostSubBuffer() {
316 return true;
317}
spang0ac9fc32015-09-16 23:11:03318
achaulkec8c2db2015-05-29 16:35:03319gfx::SwapResult GLSurfaceOzoneSurfaceless::PostSubBuffer(int x,
320 int y,
321 int width,
322 int height) {
alexste3e46052015-05-04 19:40:56323 // The actual sub buffer handling is handled at higher layers.
324 SwapBuffers();
achaulkec8c2db2015-05-29 16:35:03325 return gfx::SwapResult::SWAP_ACK;
alexste3e46052015-05-04 19:40:56326}
spang0ac9fc32015-09-16 23:11:03327
alexste3e46052015-05-04 19:40:56328bool GLSurfaceOzoneSurfaceless::SwapBuffersAsync(
329 const SwapCompletionCallback& callback) {
330 // If last swap failed, don't try to schedule new ones.
331 if (!last_swap_buffers_result_)
332 return false;
333
334 glFlush();
335
achaulkec8c2db2015-05-29 16:35:03336 SwapCompletionCallback surface_swap_callback =
alexste3e46052015-05-04 19:40:56337 base::Bind(&GLSurfaceOzoneSurfaceless::SwapCompleted,
338 weak_factory_.GetWeakPtr(), callback);
339
340 PendingFrame* frame = unsubmitted_frames_.back();
341 frame->callback = surface_swap_callback;
342 unsubmitted_frames_.push_back(new PendingFrame());
343
344 // TODO: the following should be replaced by a per surface flush as it gets
345 // implemented in GL drivers.
346 if (has_implicit_external_sync_) {
347 EGLSyncKHR fence = InsertFence();
348 if (!fence)
349 return false;
350
351 base::Closure fence_wait_task =
352 base::Bind(&WaitForFence, GetDisplay(), fence);
353
354 base::Closure fence_retired_callback =
355 base::Bind(&GLSurfaceOzoneSurfaceless::FenceRetired,
356 weak_factory_.GetWeakPtr(), fence, frame);
357
358 base::WorkerPool::PostTaskAndReply(FROM_HERE, fence_wait_task,
359 fence_retired_callback, false);
360 return true;
361 } else if (ozone_surface_->IsUniversalDisplayLinkDevice()) {
362 glFinish();
363 }
364
365 frame->ready = true;
366 SubmitFrame();
367 return last_swap_buffers_result_;
368}
spang0ac9fc32015-09-16 23:11:03369
alexste3e46052015-05-04 19:40:56370bool GLSurfaceOzoneSurfaceless::PostSubBufferAsync(
371 int x,
372 int y,
373 int width,
374 int height,
375 const SwapCompletionCallback& callback) {
376 return SwapBuffersAsync(callback);
377}
378
379GLSurfaceOzoneSurfaceless::~GLSurfaceOzoneSurfaceless() {
spang0ac9fc32015-09-16 23:11:03380 Destroy(); // The EGL surface must be destroyed before SurfaceOzone.
alexste3e46052015-05-04 19:40:56381}
382
383void GLSurfaceOzoneSurfaceless::SubmitFrame() {
384 DCHECK(!unsubmitted_frames_.empty());
385
386 if (unsubmitted_frames_.front()->ready && !swap_buffers_pending_) {
387 scoped_ptr<PendingFrame> frame(unsubmitted_frames_.front());
388 unsubmitted_frames_.weak_erase(unsubmitted_frames_.begin());
389 swap_buffers_pending_ = true;
390
dnicoara02681f42015-11-12 15:34:38391 if (!frame->ScheduleOverlayPlanes(widget_)) {
392 // |callback| is a wrapper for SwapCompleted(). Call it to properly
393 // propagate the failed state.
394 frame->callback.Run(gfx::SwapResult::SWAP_FAILED);
395 return;
396 }
397
398 ozone_surface_->OnSwapBuffersAsync(frame->callback);
alexste3e46052015-05-04 19:40:56399 }
400}
401
402EGLSyncKHR GLSurfaceOzoneSurfaceless::InsertFence() {
403 const EGLint attrib_list[] = {EGL_SYNC_CONDITION_KHR,
404 EGL_SYNC_PRIOR_COMMANDS_IMPLICIT_EXTERNAL_ARM,
405 EGL_NONE};
406 return eglCreateSyncKHR(GetDisplay(), EGL_SYNC_FENCE_KHR, attrib_list);
407}
408
409void GLSurfaceOzoneSurfaceless::FenceRetired(EGLSyncKHR fence,
410 PendingFrame* frame) {
411 eglDestroySyncKHR(GetDisplay(), fence);
412 frame->ready = true;
413 SubmitFrame();
414}
415
416void GLSurfaceOzoneSurfaceless::SwapCompleted(
achaulkec8c2db2015-05-29 16:35:03417 const SwapCompletionCallback& callback,
418 gfx::SwapResult result) {
419 callback.Run(result);
alexste3e46052015-05-04 19:40:56420 swap_buffers_pending_ = false;
dnicoara02681f42015-11-12 15:34:38421 if (result == gfx::SwapResult::SWAP_FAILED) {
422 last_swap_buffers_result_ = false;
423 return;
424 }
alexste3e46052015-05-04 19:40:56425
426 SubmitFrame();
427}
428
achaulke86e411c2015-03-02 22:45:36429// This provides surface-like semantics implemented through surfaceless.
430// A framebuffer is bound automatically.
431class GL_EXPORT GLSurfaceOzoneSurfacelessSurfaceImpl
432 : public GLSurfaceOzoneSurfaceless {
433 public:
434 GLSurfaceOzoneSurfacelessSurfaceImpl(
435 scoped_ptr<ui::SurfaceOzoneEGL> ozone_surface,
alexste3e46052015-05-04 19:40:56436 AcceleratedWidget widget);
achaulke86e411c2015-03-02 22:45:36437
alexste3e46052015-05-04 19:40:56438 // GLSurface:
439 unsigned int GetBackingFrameBufferObject() override;
440 bool OnMakeCurrent(GLContext* context) override;
jbaumance45e112015-10-30 02:33:57441 bool Resize(const gfx::Size& size, float scale_factor) override;
alexste3e46052015-05-04 19:40:56442 bool SupportsPostSubBuffer() override;
achaulkec8c2db2015-05-29 16:35:03443 gfx::SwapResult SwapBuffers() override;
alexste3e46052015-05-04 19:40:56444 bool SwapBuffersAsync(const SwapCompletionCallback& callback) override;
445 void Destroy() override;
spangb55571ca2015-09-16 22:09:35446 bool IsSurfaceless() const override;
achaulke86e411c2015-03-02 22:45:36447
448 private:
alexste3e46052015-05-04 19:40:56449 ~GLSurfaceOzoneSurfacelessSurfaceImpl() override;
achaulke86e411c2015-03-02 22:45:36450
alexste3e46052015-05-04 19:40:56451 void BindFramebuffer();
452 bool CreatePixmaps();
achaulke86e411c2015-03-02 22:45:36453
achaulk8d645d292015-08-04 14:09:27454 scoped_refptr<GLContext> context_;
achaulke86e411c2015-03-02 22:45:36455 GLuint fbo_;
456 GLuint textures_[2];
457 scoped_refptr<GLImage> images_[2];
458 int current_surface_;
459 DISALLOW_COPY_AND_ASSIGN(GLSurfaceOzoneSurfacelessSurfaceImpl);
460};
461
alexste3e46052015-05-04 19:40:56462GLSurfaceOzoneSurfacelessSurfaceImpl::GLSurfaceOzoneSurfacelessSurfaceImpl(
463 scoped_ptr<ui::SurfaceOzoneEGL> ozone_surface,
464 AcceleratedWidget widget)
465 : GLSurfaceOzoneSurfaceless(ozone_surface.Pass(), widget),
achaulk8d645d292015-08-04 14:09:27466 context_(nullptr),
alexste3e46052015-05-04 19:40:56467 fbo_(0),
468 current_surface_(0) {
469 for (auto& texture : textures_)
470 texture = 0;
471}
472
473unsigned int
474GLSurfaceOzoneSurfacelessSurfaceImpl::GetBackingFrameBufferObject() {
475 return fbo_;
476}
477
478bool GLSurfaceOzoneSurfacelessSurfaceImpl::OnMakeCurrent(GLContext* context) {
achaulk8d645d292015-08-04 14:09:27479 DCHECK(!context_ || context == context_);
480 context_ = context;
alexste3e46052015-05-04 19:40:56481 if (!fbo_) {
482 glGenFramebuffersEXT(1, &fbo_);
483 if (!fbo_)
484 return false;
485 glGenTextures(arraysize(textures_), textures_);
486 if (!CreatePixmaps())
487 return false;
488 }
489 BindFramebuffer();
490 glBindFramebufferEXT(GL_FRAMEBUFFER, fbo_);
491 return SurfacelessEGL::OnMakeCurrent(context);
492}
493
jbaumance45e112015-10-30 02:33:57494bool GLSurfaceOzoneSurfacelessSurfaceImpl::Resize(const gfx::Size& size,
495 float scale_factor) {
alexste3e46052015-05-04 19:40:56496 if (size == GetSize())
497 return true;
jbaumance45e112015-10-30 02:33:57498 return GLSurfaceOzoneSurfaceless::Resize(size, scale_factor) &&
499 CreatePixmaps();
alexste3e46052015-05-04 19:40:56500}
501
502bool GLSurfaceOzoneSurfacelessSurfaceImpl::SupportsPostSubBuffer() {
503 return false;
504}
505
achaulkec8c2db2015-05-29 16:35:03506gfx::SwapResult GLSurfaceOzoneSurfacelessSurfaceImpl::SwapBuffers() {
alexste3e46052015-05-04 19:40:56507 if (!images_[current_surface_]->ScheduleOverlayPlane(
508 widget_, 0, OverlayTransform::OVERLAY_TRANSFORM_NONE,
509 gfx::Rect(GetSize()), gfx::RectF(1, 1)))
achaulkec8c2db2015-05-29 16:35:03510 return gfx::SwapResult::SWAP_FAILED;
511 gfx::SwapResult result = GLSurfaceOzoneSurfaceless::SwapBuffers();
512 if (result != gfx::SwapResult::SWAP_ACK)
513 return result;
alexste3e46052015-05-04 19:40:56514 current_surface_ ^= 1;
515 BindFramebuffer();
achaulkec8c2db2015-05-29 16:35:03516 return gfx::SwapResult::SWAP_ACK;
alexste3e46052015-05-04 19:40:56517}
518
519bool GLSurfaceOzoneSurfacelessSurfaceImpl::SwapBuffersAsync(
520 const SwapCompletionCallback& callback) {
521 if (!images_[current_surface_]->ScheduleOverlayPlane(
522 widget_, 0, OverlayTransform::OVERLAY_TRANSFORM_NONE,
523 gfx::Rect(GetSize()), gfx::RectF(1, 1)))
524 return false;
525 if (!GLSurfaceOzoneSurfaceless::SwapBuffersAsync(callback))
526 return false;
527 current_surface_ ^= 1;
528 BindFramebuffer();
529 return true;
530}
531
532void GLSurfaceOzoneSurfacelessSurfaceImpl::Destroy() {
achaulk8d645d292015-08-04 14:09:27533 if (!context_)
534 return;
wuchengli20824f952015-10-22 05:05:27535 scoped_refptr<gfx::GLContext> previous_context = gfx::GLContext::GetCurrent();
536 scoped_refptr<gfx::GLSurface> previous_surface = gfx::GLSurface::GetCurrent();
537 context_->MakeCurrent(this);
538
alexste3e46052015-05-04 19:40:56539 glBindFramebufferEXT(GL_FRAMEBUFFER, 0);
540 if (fbo_) {
541 glDeleteTextures(arraysize(textures_), textures_);
542 for (auto& texture : textures_)
543 texture = 0;
544 glDeleteFramebuffersEXT(1, &fbo_);
545 fbo_ = 0;
546 }
547 for (auto image : images_) {
548 if (image)
549 image->Destroy(true);
550 }
wuchengli20824f952015-10-22 05:05:27551
552 if (previous_context.get()) {
553 previous_context->MakeCurrent(previous_surface.get());
554 } else {
555 context_->ReleaseCurrent(this);
556 }
alexste3e46052015-05-04 19:40:56557}
558
spangb55571ca2015-09-16 22:09:35559bool GLSurfaceOzoneSurfacelessSurfaceImpl::IsSurfaceless() const {
560 return false;
561}
562
alexste3e46052015-05-04 19:40:56563GLSurfaceOzoneSurfacelessSurfaceImpl::~GLSurfaceOzoneSurfacelessSurfaceImpl() {
wuchengli20824f952015-10-22 05:05:27564 Destroy();
alexste3e46052015-05-04 19:40:56565}
566
567void GLSurfaceOzoneSurfacelessSurfaceImpl::BindFramebuffer() {
568 ScopedFrameBufferBinder fb(fbo_);
569 glFramebufferTexture2DEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
570 textures_[current_surface_], 0);
571}
572
573bool GLSurfaceOzoneSurfacelessSurfaceImpl::CreatePixmaps() {
574 if (!fbo_)
575 return true;
576 for (size_t i = 0; i < arraysize(textures_); i++) {
577 scoped_refptr<ui::NativePixmap> pixmap =
dongseong.hwang9162b5fa2015-06-05 16:52:30578 ui::OzonePlatform::GetInstance()
579 ->GetSurfaceFactoryOzone()
580 ->CreateNativePixmap(widget_, GetSize(),
spangfcf5fab42015-08-04 19:25:35581 gfx::BufferFormat::BGRA_8888,
reveman1108e0b72015-10-30 17:05:44582 gfx::BufferUsage::SCANOUT);
alexste3e46052015-05-04 19:40:56583 if (!pixmap)
584 return false;
dongseong.hwang161c7a22015-07-29 18:28:17585 scoped_refptr<GLImageOzoneNativePixmap> image =
586 new GLImageOzoneNativePixmap(GetSize(), GL_BGRA_EXT);
reveman0bb50d72015-11-16 18:04:52587 if (!image->Initialize(pixmap.get(), gfx::BufferFormat::BGRA_8888))
alexste3e46052015-05-04 19:40:56588 return false;
589 images_[i] = image;
590 // Bind image to texture.
591 ScopedTextureBinder binder(GL_TEXTURE_2D, textures_[i]);
592 if (!images_[i]->BindTexImage(GL_TEXTURE_2D))
593 return false;
594 }
595 return true;
596}
597
spange82006b2015-09-16 18:07:29598scoped_refptr<GLSurface> CreateViewGLSurfaceOzone(
599 gfx::AcceleratedWidget window) {
600 scoped_ptr<ui::SurfaceOzoneEGL> surface_ozone =
601 ui::OzonePlatform::GetInstance()
602 ->GetSurfaceFactoryOzone()
603 ->CreateEGLSurfaceForWidget(window);
604 if (!surface_ozone)
605 return nullptr;
606 scoped_refptr<GLSurface> surface =
607 new GLSurfaceOzoneEGL(surface_ozone.Pass(), window);
608 if (!surface->Initialize())
609 return nullptr;
610 return surface;
611}
612
613scoped_refptr<GLSurface> CreateViewGLSurfaceOzoneSurfacelessSurfaceImpl(
614 gfx::AcceleratedWidget window) {
615 scoped_ptr<ui::SurfaceOzoneEGL> surface_ozone =
616 ui::OzonePlatform::GetInstance()
617 ->GetSurfaceFactoryOzone()
618 ->CreateSurfacelessEGLSurfaceForWidget(window);
619 if (!surface_ozone)
620 return nullptr;
621 scoped_refptr<GLSurface> surface =
622 new GLSurfaceOzoneSurfacelessSurfaceImpl(surface_ozone.Pass(), window);
623 if (!surface->Initialize())
624 return nullptr;
625 return surface;
626}
627
[email protected]502371d2014-03-31 17:16:42628} // namespace
629
[email protected]ffcdc9632014-03-27 17:25:23630// static
631bool GLSurface::InitializeOneOffInternal() {
[email protected]ffcdc9632014-03-27 17:25:23632 switch (GetGLImplementation()) {
633 case kGLImplementationEGLGLES2:
[email protected]ffcdc9632014-03-27 17:25:23634 if (!GLSurfaceEGL::InitializeOneOff()) {
635 LOG(ERROR) << "GLSurfaceEGL::InitializeOneOff failed.";
636 return false;
637 }
[email protected]1fe750572014-03-29 01:22:34638
639 return true;
640 case kGLImplementationOSMesaGL:
641 case kGLImplementationMockGL:
642 return true;
[email protected]ffcdc9632014-03-27 17:25:23643 default:
[email protected]1fe750572014-03-29 01:22:34644 return false;
[email protected]ffcdc9632014-03-27 17:25:23645 }
[email protected]ffcdc9632014-03-27 17:25:23646}
647
648// static
achaulke86e411c2015-03-02 22:45:36649scoped_refptr<GLSurface> GLSurface::CreateSurfacelessViewGLSurface(
650 gfx::AcceleratedWidget window) {
651 if (GetGLImplementation() == kGLImplementationEGLGLES2 &&
652 window != kNullAcceleratedWidget &&
spange82006b2015-09-16 18:07:29653 GLSurfaceEGL::IsEGLSurfacelessContextSupported()) {
achaulke86e411c2015-03-02 22:45:36654 scoped_ptr<ui::SurfaceOzoneEGL> surface_ozone =
dongseong.hwang9162b5fa2015-06-05 16:52:30655 ui::OzonePlatform::GetInstance()
656 ->GetSurfaceFactoryOzone()
achaulke86e411c2015-03-02 22:45:36657 ->CreateSurfacelessEGLSurfaceForWidget(window);
658 if (!surface_ozone)
659 return nullptr;
660 scoped_refptr<GLSurface> surface;
661 surface = new GLSurfaceOzoneSurfaceless(surface_ozone.Pass(), window);
662 if (surface->Initialize())
663 return surface;
664 }
665
666 return nullptr;
667}
668
669// static
[email protected]ffcdc9632014-03-27 17:25:23670scoped_refptr<GLSurface> GLSurface::CreateViewGLSurface(
671 gfx::AcceleratedWidget window) {
672 if (GetGLImplementation() == kGLImplementationOSMesaGL) {
673 scoped_refptr<GLSurface> surface(new GLSurfaceOSMesaHeadless());
674 if (!surface->Initialize())
spang0ac9fc32015-09-16 23:11:03675 return nullptr;
[email protected]ffcdc9632014-03-27 17:25:23676 return surface;
677 }
678 DCHECK(GetGLImplementation() == kGLImplementationEGLGLES2);
679 if (window != kNullAcceleratedWidget) {
achaulke79d5d852014-08-27 00:16:42680 scoped_refptr<GLSurface> surface;
spange82006b2015-09-16 18:07:29681 if (GLSurfaceEGL::IsEGLSurfacelessContextSupported())
682 surface = CreateViewGLSurfaceOzoneSurfacelessSurfaceImpl(window);
683 if (!surface)
684 surface = CreateViewGLSurfaceOzone(window);
[email protected]502371d2014-03-31 17:16:42685 return surface;
[email protected]ffcdc9632014-03-27 17:25:23686 } else {
687 scoped_refptr<GLSurface> surface = new GLSurfaceStub();
688 if (surface->Initialize())
689 return surface;
690 }
spang0ac9fc32015-09-16 23:11:03691 return nullptr;
[email protected]ffcdc9632014-03-27 17:25:23692}
693
694// static
695scoped_refptr<GLSurface> GLSurface::CreateOffscreenGLSurface(
696 const gfx::Size& size) {
697 switch (GetGLImplementation()) {
698 case kGLImplementationOSMesaGL: {
[email protected]dab86622014-08-16 14:34:59699 scoped_refptr<GLSurface> surface(
700 new GLSurfaceOSMesa(OSMesaSurfaceFormatBGRA, size));
[email protected]ffcdc9632014-03-27 17:25:23701 if (!surface->Initialize())
spang0ac9fc32015-09-16 23:11:03702 return nullptr;
[email protected]ffcdc9632014-03-27 17:25:23703
704 return surface;
705 }
706 case kGLImplementationEGLGLES2: {
707 scoped_refptr<GLSurface> surface;
708 if (GLSurfaceEGL::IsEGLSurfacelessContextSupported() &&
709 (size.width() == 0 && size.height() == 0)) {
710 surface = new SurfacelessEGL(size);
711 } else
712 surface = new PbufferGLSurfaceEGL(size);
713
714 if (!surface->Initialize())
spang0ac9fc32015-09-16 23:11:03715 return nullptr;
[email protected]ffcdc9632014-03-27 17:25:23716 return surface;
717 }
zmoeecacfe2015-05-07 05:42:53718 case kGLImplementationMockGL:
719 return new GLSurfaceStub;
[email protected]ffcdc9632014-03-27 17:25:23720 default:
721 NOTREACHED();
spang0ac9fc32015-09-16 23:11:03722 return nullptr;
[email protected]ffcdc9632014-03-27 17:25:23723 }
724}
725
726EGLNativeDisplayType GetPlatformDefaultEGLNativeDisplay() {
dongseong.hwang9162b5fa2015-06-05 16:52:30727 return ui::OzonePlatform::GetInstance()
728 ->GetSurfaceFactoryOzone()
729 ->GetNativeDisplay();
[email protected]ffcdc9632014-03-27 17:25:23730}
731
732} // namespace gfx