blob: c596c2928b328223d8d4431ad45649163cfaaf86 [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"
watke6e68b1e2015-12-01 04:04:0322#include "ui/gl/gl_surface_overlay.h"
[email protected]ffcdc9632014-03-27 17:25:2323#include "ui/gl/gl_surface_stub.h"
achaulke86e411c2015-03-02 22:45:3624#include "ui/gl/scoped_binders.h"
[email protected]aab13e2f2014-07-29 03:01:4525#include "ui/gl/scoped_make_current.h"
achaulke86e411c2015-03-02 22:45:3626#include "ui/ozone/public/native_pixmap.h"
dongseong.hwang9162b5fa2015-06-05 16:52:3027#include "ui/ozone/public/ozone_platform.h"
[email protected]0e37fc202014-06-20 13:24:0228#include "ui/ozone/public/surface_factory_ozone.h"
29#include "ui/ozone/public/surface_ozone_egl.h"
[email protected]ffcdc9632014-03-27 17:25:2330
tfarinadf856e022015-10-29 12:50:4531using gl::GLImage;
32
[email protected]ffcdc9632014-03-27 17:25:2333namespace gfx {
34
[email protected]502371d2014-03-31 17:16:4235namespace {
36
alexst165be972015-03-11 15:37:0937void WaitForFence(EGLDisplay display, EGLSyncKHR fence) {
38 eglClientWaitSyncKHR(display, fence, EGL_SYNC_FLUSH_COMMANDS_BIT_KHR,
39 EGL_FOREVER_KHR);
40}
41
spang0ac9fc32015-09-16 23:11:0342// A thin wrapper around GLSurfaceEGL that owns the EGLNativeWindow.
[email protected]502371d2014-03-31 17:16:4243class GL_EXPORT GLSurfaceOzoneEGL : public NativeViewGLSurfaceEGL {
44 public:
[email protected]aab13e2f2014-07-29 03:01:4545 GLSurfaceOzoneEGL(scoped_ptr<ui::SurfaceOzoneEGL> ozone_surface,
alexste3e46052015-05-04 19:40:5646 AcceleratedWidget widget);
[email protected]502371d2014-03-31 17:16:4247
alexste3e46052015-05-04 19:40:5648 // GLSurface:
49 bool Initialize() override;
jbauman16205872015-12-15 21:27:2750 bool Resize(const gfx::Size& size,
51 float scale_factor,
52 bool has_alpha) override;
achaulkec8c2db2015-05-29 16:35:0353 gfx::SwapResult SwapBuffers() override;
alexstfa14b6712015-01-05 19:29:4854 bool ScheduleOverlayPlane(int z_order,
55 OverlayTransform transform,
56 GLImage* image,
57 const Rect& bounds_rect,
alexste3e46052015-05-04 19:40:5658 const RectF& crop_rect) override;
[email protected]5780da092014-04-08 12:04:4159
[email protected]b8211e32014-04-01 22:58:4560 private:
achaulke79d5d852014-08-27 00:16:4261 using NativeViewGLSurfaceEGL::Initialize;
62
alexste3e46052015-05-04 19:40:5663 ~GLSurfaceOzoneEGL() override;
[email protected]502371d2014-03-31 17:16:4264
alexste3e46052015-05-04 19:40:5665 bool ReinitializeNativeSurface();
[email protected]aab13e2f2014-07-29 03:01:4566
[email protected]502371d2014-03-31 17:16:4267 // The native surface. Deleting this is allowed to free the EGLNativeWindow.
[email protected]0e37fc202014-06-20 13:24:0268 scoped_ptr<ui::SurfaceOzoneEGL> ozone_surface_;
[email protected]aab13e2f2014-07-29 03:01:4569 AcceleratedWidget widget_;
[email protected]502371d2014-03-31 17:16:4270
71 DISALLOW_COPY_AND_ASSIGN(GLSurfaceOzoneEGL);
72};
73
alexste3e46052015-05-04 19:40:5674GLSurfaceOzoneEGL::GLSurfaceOzoneEGL(
75 scoped_ptr<ui::SurfaceOzoneEGL> ozone_surface,
76 AcceleratedWidget widget)
77 : NativeViewGLSurfaceEGL(ozone_surface->GetNativeWindow()),
martina.kollarova66bdb2b2015-12-17 08:35:4678 ozone_surface_(std::move(ozone_surface)),
spang0ac9fc32015-09-16 23:11:0379 widget_(widget) {}
alexste3e46052015-05-04 19:40:5680
81bool GLSurfaceOzoneEGL::Initialize() {
82 return Initialize(ozone_surface_->CreateVSyncProvider());
83}
84
jbauman16205872015-12-15 21:27:2785bool GLSurfaceOzoneEGL::Resize(const gfx::Size& size,
86 float scale_factor,
87 bool has_alpha) {
alexste3e46052015-05-04 19:40:5688 if (!ozone_surface_->ResizeNativeWindow(size)) {
89 if (!ReinitializeNativeSurface() ||
90 !ozone_surface_->ResizeNativeWindow(size))
91 return false;
92 }
93
jbauman16205872015-12-15 21:27:2794 return NativeViewGLSurfaceEGL::Resize(size, scale_factor, has_alpha);
alexste3e46052015-05-04 19:40:5695}
96
achaulkec8c2db2015-05-29 16:35:0397gfx::SwapResult GLSurfaceOzoneEGL::SwapBuffers() {
98 gfx::SwapResult result = NativeViewGLSurfaceEGL::SwapBuffers();
99 if (result != gfx::SwapResult::SWAP_ACK)
100 return result;
alexste3e46052015-05-04 19:40:56101
achaulkec8c2db2015-05-29 16:35:03102 return ozone_surface_->OnSwapBuffers() ? gfx::SwapResult::SWAP_ACK
103 : gfx::SwapResult::SWAP_FAILED;
alexste3e46052015-05-04 19:40:56104}
105
106bool GLSurfaceOzoneEGL::ScheduleOverlayPlane(int z_order,
107 OverlayTransform transform,
108 GLImage* image,
109 const Rect& bounds_rect,
110 const RectF& crop_rect) {
111 return image->ScheduleOverlayPlane(widget_, z_order, transform, bounds_rect,
112 crop_rect);
113}
114
115GLSurfaceOzoneEGL::~GLSurfaceOzoneEGL() {
spang0ac9fc32015-09-16 23:11:03116 Destroy(); // The EGL surface must be destroyed before SurfaceOzone.
alexste3e46052015-05-04 19:40:56117}
118
119bool GLSurfaceOzoneEGL::ReinitializeNativeSurface() {
120 scoped_ptr<ui::ScopedMakeCurrent> scoped_make_current;
121 GLContext* current_context = GLContext::GetCurrent();
122 bool was_current = current_context && current_context->IsCurrent(this);
123 if (was_current) {
124 scoped_make_current.reset(new ui::ScopedMakeCurrent(current_context, this));
125 }
126
127 Destroy();
dongseong.hwang9162b5fa2015-06-05 16:52:30128 ozone_surface_ = ui::OzonePlatform::GetInstance()
129 ->GetSurfaceFactoryOzone()
spang0ac9fc32015-09-16 23:11:03130 ->CreateEGLSurfaceForWidget(widget_);
alexste3e46052015-05-04 19:40:56131 if (!ozone_surface_) {
132 LOG(ERROR) << "Failed to create native surface.";
133 return false;
134 }
135
136 window_ = ozone_surface_->GetNativeWindow();
137 if (!Initialize()) {
138 LOG(ERROR) << "Failed to initialize.";
139 return false;
140 }
141
142 return true;
143}
144
achaulke79d5d852014-08-27 00:16:42145class GL_EXPORT GLSurfaceOzoneSurfaceless : public SurfacelessEGL {
146 public:
147 GLSurfaceOzoneSurfaceless(scoped_ptr<ui::SurfaceOzoneEGL> ozone_surface,
alexste3e46052015-05-04 19:40:56148 AcceleratedWidget widget);
achaulke79d5d852014-08-27 00:16:42149
alexste3e46052015-05-04 19:40:56150 // GLSurface:
151 bool Initialize() override;
jbauman16205872015-12-15 21:27:27152 bool Resize(const gfx::Size& size,
153 float scale_factor,
154 bool has_alpha) override;
achaulkec8c2db2015-05-29 16:35:03155 gfx::SwapResult SwapBuffers() override;
alexstfa14b6712015-01-05 19:29:48156 bool ScheduleOverlayPlane(int z_order,
157 OverlayTransform transform,
158 GLImage* image,
159 const Rect& bounds_rect,
alexste3e46052015-05-04 19:40:56160 const RectF& crop_rect) override;
161 bool IsOffscreen() override;
162 VSyncProvider* GetVSyncProvider() override;
spangf960a9502015-11-18 21:04:26163 bool SupportsAsyncSwap() override;
alexste3e46052015-05-04 19:40:56164 bool SupportsPostSubBuffer() override;
achaulkec8c2db2015-05-29 16:35:03165 gfx::SwapResult PostSubBuffer(int x, int y, int width, int height) override;
spangf960a9502015-11-18 21:04:26166 void SwapBuffersAsync(const SwapCompletionCallback& callback) override;
167 void PostSubBufferAsync(int x,
alexst409e3e02015-01-05 22:20:24168 int y,
169 int width,
170 int height,
alexste3e46052015-05-04 19:40:56171 const SwapCompletionCallback& callback) override;
achaulke79d5d852014-08-27 00:16:42172
achaulke86e411c2015-03-02 22:45:36173 protected:
achaulk77f08ab2015-04-07 16:22:34174 struct PendingFrame {
alexste3e46052015-05-04 19:40:56175 PendingFrame();
achaulk77f08ab2015-04-07 16:22:34176
alexste3e46052015-05-04 19:40:56177 bool ScheduleOverlayPlanes(gfx::AcceleratedWidget widget);
achaulk77f08ab2015-04-07 16:22:34178
achaulk77f08ab2015-04-07 16:22:34179 bool ready;
watke6e68b1e2015-12-01 04:04:03180 std::vector<GLSurfaceOverlay> overlays;
achaulk77f08ab2015-04-07 16:22:34181 SwapCompletionCallback callback;
182 };
183
alexste3e46052015-05-04 19:40:56184 ~GLSurfaceOzoneSurfaceless() override;
achaulke79d5d852014-08-27 00:16:42185
alexste3e46052015-05-04 19:40:56186 void SubmitFrame();
alexst9c973212015-04-24 14:28:45187
alexste3e46052015-05-04 19:40:56188 EGLSyncKHR InsertFence();
189 void FenceRetired(EGLSyncKHR fence, PendingFrame* frame);
alexst9c973212015-04-24 14:28:45190
achaulkec8c2db2015-05-29 16:35:03191 void SwapCompleted(const SwapCompletionCallback& callback,
192 gfx::SwapResult result);
dbehr5addbd52015-02-07 03:18:05193
achaulke79d5d852014-08-27 00:16:42194 // The native surface. Deleting this is allowed to free the EGLNativeWindow.
195 scoped_ptr<ui::SurfaceOzoneEGL> ozone_surface_;
196 AcceleratedWidget widget_;
197 scoped_ptr<VSyncProvider> vsync_provider_;
achaulk77f08ab2015-04-07 16:22:34198 ScopedVector<PendingFrame> unsubmitted_frames_;
dbehr5addbd52015-02-07 03:18:05199 bool has_implicit_external_sync_;
alexst165be972015-03-11 15:37:09200 bool last_swap_buffers_result_;
alexst9c973212015-04-24 14:28:45201 bool swap_buffers_pending_;
alexst165be972015-03-11 15:37:09202
203 base::WeakPtrFactory<GLSurfaceOzoneSurfaceless> weak_factory_;
204
achaulke79d5d852014-08-27 00:16:42205 DISALLOW_COPY_AND_ASSIGN(GLSurfaceOzoneSurfaceless);
206};
207
spang0ac9fc32015-09-16 23:11:03208GLSurfaceOzoneSurfaceless::PendingFrame::PendingFrame() : ready(false) {}
alexste3e46052015-05-04 19:40:56209
210bool GLSurfaceOzoneSurfaceless::PendingFrame::ScheduleOverlayPlanes(
211 gfx::AcceleratedWidget widget) {
212 for (const auto& overlay : overlays)
213 if (!overlay.ScheduleOverlayPlane(widget))
214 return false;
215 return true;
216}
217
218GLSurfaceOzoneSurfaceless::GLSurfaceOzoneSurfaceless(
219 scoped_ptr<ui::SurfaceOzoneEGL> ozone_surface,
220 AcceleratedWidget widget)
221 : SurfacelessEGL(gfx::Size()),
martina.kollarova66bdb2b2015-12-17 08:35:46222 ozone_surface_(std::move(ozone_surface)),
alexste3e46052015-05-04 19:40:56223 widget_(widget),
224 has_implicit_external_sync_(
225 HasEGLExtension("EGL_ARM_implicit_external_sync")),
226 last_swap_buffers_result_(true),
227 swap_buffers_pending_(false),
228 weak_factory_(this) {
229 unsubmitted_frames_.push_back(new PendingFrame());
230}
231
232bool GLSurfaceOzoneSurfaceless::Initialize() {
233 if (!SurfacelessEGL::Initialize())
234 return false;
235 vsync_provider_ = ozone_surface_->CreateVSyncProvider();
236 if (!vsync_provider_)
237 return false;
238 return true;
239}
spang0ac9fc32015-09-16 23:11:03240
jbaumance45e112015-10-30 02:33:57241bool GLSurfaceOzoneSurfaceless::Resize(const gfx::Size& size,
jbauman16205872015-12-15 21:27:27242 float scale_factor,
243 bool has_alpha) {
alexste3e46052015-05-04 19:40:56244 if (!ozone_surface_->ResizeNativeWindow(size))
245 return false;
246
jbauman16205872015-12-15 21:27:27247 return SurfacelessEGL::Resize(size, scale_factor, has_alpha);
alexste3e46052015-05-04 19:40:56248}
spang0ac9fc32015-09-16 23:11:03249
achaulkec8c2db2015-05-29 16:35:03250gfx::SwapResult GLSurfaceOzoneSurfaceless::SwapBuffers() {
alexste3e46052015-05-04 19:40:56251 glFlush();
252 // TODO: the following should be replaced by a per surface flush as it gets
253 // implemented in GL drivers.
254 if (has_implicit_external_sync_) {
255 EGLSyncKHR fence = InsertFence();
256 if (!fence)
achaulkec8c2db2015-05-29 16:35:03257 return SwapResult::SWAP_FAILED;
alexste3e46052015-05-04 19:40:56258
259 EGLDisplay display = GetDisplay();
260 WaitForFence(display, fence);
261 eglDestroySyncKHR(display, fence);
262 } else if (ozone_surface_->IsUniversalDisplayLinkDevice()) {
263 glFinish();
264 }
265
266 unsubmitted_frames_.back()->ScheduleOverlayPlanes(widget_);
267 unsubmitted_frames_.back()->overlays.clear();
268
achaulkec8c2db2015-05-29 16:35:03269 return ozone_surface_->OnSwapBuffers() ? gfx::SwapResult::SWAP_ACK
270 : gfx::SwapResult::SWAP_FAILED;
alexste3e46052015-05-04 19:40:56271}
spang0ac9fc32015-09-16 23:11:03272
alexste3e46052015-05-04 19:40:56273bool GLSurfaceOzoneSurfaceless::ScheduleOverlayPlane(int z_order,
274 OverlayTransform transform,
275 GLImage* image,
276 const Rect& bounds_rect,
277 const RectF& crop_rect) {
278 unsubmitted_frames_.back()->overlays.push_back(
watke6e68b1e2015-12-01 04:04:03279 GLSurfaceOverlay(z_order, transform, image, bounds_rect, crop_rect));
alexste3e46052015-05-04 19:40:56280 return true;
281}
spang0ac9fc32015-09-16 23:11:03282
alexste3e46052015-05-04 19:40:56283bool GLSurfaceOzoneSurfaceless::IsOffscreen() {
284 return false;
285}
spang0ac9fc32015-09-16 23:11:03286
alexste3e46052015-05-04 19:40:56287VSyncProvider* GLSurfaceOzoneSurfaceless::GetVSyncProvider() {
288 return vsync_provider_.get();
289}
spang0ac9fc32015-09-16 23:11:03290
spangf960a9502015-11-18 21:04:26291bool GLSurfaceOzoneSurfaceless::SupportsAsyncSwap() {
292 return true;
293}
294
alexste3e46052015-05-04 19:40:56295bool GLSurfaceOzoneSurfaceless::SupportsPostSubBuffer() {
296 return true;
297}
spang0ac9fc32015-09-16 23:11:03298
achaulkec8c2db2015-05-29 16:35:03299gfx::SwapResult GLSurfaceOzoneSurfaceless::PostSubBuffer(int x,
300 int y,
301 int width,
302 int height) {
alexste3e46052015-05-04 19:40:56303 // The actual sub buffer handling is handled at higher layers.
spangf960a9502015-11-18 21:04:26304 NOTREACHED();
305 return gfx::SwapResult::SWAP_FAILED;
alexste3e46052015-05-04 19:40:56306}
spang0ac9fc32015-09-16 23:11:03307
spangf960a9502015-11-18 21:04:26308void GLSurfaceOzoneSurfaceless::SwapBuffersAsync(
alexste3e46052015-05-04 19:40:56309 const SwapCompletionCallback& callback) {
310 // If last swap failed, don't try to schedule new ones.
spangf960a9502015-11-18 21:04:26311 if (!last_swap_buffers_result_) {
312 callback.Run(gfx::SwapResult::SWAP_FAILED);
313 return;
314 }
alexste3e46052015-05-04 19:40:56315
316 glFlush();
317
achaulkec8c2db2015-05-29 16:35:03318 SwapCompletionCallback surface_swap_callback =
alexste3e46052015-05-04 19:40:56319 base::Bind(&GLSurfaceOzoneSurfaceless::SwapCompleted,
320 weak_factory_.GetWeakPtr(), callback);
321
322 PendingFrame* frame = unsubmitted_frames_.back();
323 frame->callback = surface_swap_callback;
324 unsubmitted_frames_.push_back(new PendingFrame());
325
326 // TODO: the following should be replaced by a per surface flush as it gets
327 // implemented in GL drivers.
328 if (has_implicit_external_sync_) {
329 EGLSyncKHR fence = InsertFence();
spangf960a9502015-11-18 21:04:26330 if (!fence) {
331 callback.Run(gfx::SwapResult::SWAP_FAILED);
332 return;
333 }
alexste3e46052015-05-04 19:40:56334
335 base::Closure fence_wait_task =
336 base::Bind(&WaitForFence, GetDisplay(), fence);
337
338 base::Closure fence_retired_callback =
339 base::Bind(&GLSurfaceOzoneSurfaceless::FenceRetired,
340 weak_factory_.GetWeakPtr(), fence, frame);
341
342 base::WorkerPool::PostTaskAndReply(FROM_HERE, fence_wait_task,
343 fence_retired_callback, false);
spangc63975d2015-11-24 16:08:11344 return; // Defer frame submission until fence signals.
alexste3e46052015-05-04 19:40:56345 }
346
spangc63975d2015-11-24 16:08:11347 if (ozone_surface_->IsUniversalDisplayLinkDevice())
348 glFinish();
349
alexste3e46052015-05-04 19:40:56350 frame->ready = true;
351 SubmitFrame();
alexste3e46052015-05-04 19:40:56352}
spang0ac9fc32015-09-16 23:11:03353
spangf960a9502015-11-18 21:04:26354void GLSurfaceOzoneSurfaceless::PostSubBufferAsync(
alexste3e46052015-05-04 19:40:56355 int x,
356 int y,
357 int width,
358 int height,
359 const SwapCompletionCallback& callback) {
spangf960a9502015-11-18 21:04:26360 // The actual sub buffer handling is handled at higher layers.
361 SwapBuffersAsync(callback);
alexste3e46052015-05-04 19:40:56362}
363
364GLSurfaceOzoneSurfaceless::~GLSurfaceOzoneSurfaceless() {
spang0ac9fc32015-09-16 23:11:03365 Destroy(); // The EGL surface must be destroyed before SurfaceOzone.
alexste3e46052015-05-04 19:40:56366}
367
368void GLSurfaceOzoneSurfaceless::SubmitFrame() {
369 DCHECK(!unsubmitted_frames_.empty());
370
371 if (unsubmitted_frames_.front()->ready && !swap_buffers_pending_) {
372 scoped_ptr<PendingFrame> frame(unsubmitted_frames_.front());
373 unsubmitted_frames_.weak_erase(unsubmitted_frames_.begin());
374 swap_buffers_pending_ = true;
375
dnicoara02681f42015-11-12 15:34:38376 if (!frame->ScheduleOverlayPlanes(widget_)) {
377 // |callback| is a wrapper for SwapCompleted(). Call it to properly
378 // propagate the failed state.
379 frame->callback.Run(gfx::SwapResult::SWAP_FAILED);
380 return;
381 }
382
383 ozone_surface_->OnSwapBuffersAsync(frame->callback);
alexste3e46052015-05-04 19:40:56384 }
385}
386
387EGLSyncKHR GLSurfaceOzoneSurfaceless::InsertFence() {
388 const EGLint attrib_list[] = {EGL_SYNC_CONDITION_KHR,
389 EGL_SYNC_PRIOR_COMMANDS_IMPLICIT_EXTERNAL_ARM,
390 EGL_NONE};
391 return eglCreateSyncKHR(GetDisplay(), EGL_SYNC_FENCE_KHR, attrib_list);
392}
393
394void GLSurfaceOzoneSurfaceless::FenceRetired(EGLSyncKHR fence,
395 PendingFrame* frame) {
396 eglDestroySyncKHR(GetDisplay(), fence);
397 frame->ready = true;
398 SubmitFrame();
399}
400
401void GLSurfaceOzoneSurfaceless::SwapCompleted(
achaulkec8c2db2015-05-29 16:35:03402 const SwapCompletionCallback& callback,
403 gfx::SwapResult result) {
404 callback.Run(result);
alexste3e46052015-05-04 19:40:56405 swap_buffers_pending_ = false;
dnicoara02681f42015-11-12 15:34:38406 if (result == gfx::SwapResult::SWAP_FAILED) {
407 last_swap_buffers_result_ = false;
408 return;
409 }
alexste3e46052015-05-04 19:40:56410
411 SubmitFrame();
412}
413
achaulke86e411c2015-03-02 22:45:36414// This provides surface-like semantics implemented through surfaceless.
415// A framebuffer is bound automatically.
416class GL_EXPORT GLSurfaceOzoneSurfacelessSurfaceImpl
417 : public GLSurfaceOzoneSurfaceless {
418 public:
419 GLSurfaceOzoneSurfacelessSurfaceImpl(
420 scoped_ptr<ui::SurfaceOzoneEGL> ozone_surface,
alexste3e46052015-05-04 19:40:56421 AcceleratedWidget widget);
achaulke86e411c2015-03-02 22:45:36422
alexste3e46052015-05-04 19:40:56423 // GLSurface:
424 unsigned int GetBackingFrameBufferObject() override;
425 bool OnMakeCurrent(GLContext* context) override;
jbauman16205872015-12-15 21:27:27426 bool Resize(const gfx::Size& size,
427 float scale_factor,
428 bool has_alpha) override;
alexste3e46052015-05-04 19:40:56429 bool SupportsPostSubBuffer() override;
achaulkec8c2db2015-05-29 16:35:03430 gfx::SwapResult SwapBuffers() override;
spangf960a9502015-11-18 21:04:26431 void SwapBuffersAsync(const SwapCompletionCallback& callback) override;
alexste3e46052015-05-04 19:40:56432 void Destroy() override;
spangb55571ca2015-09-16 22:09:35433 bool IsSurfaceless() const override;
achaulke86e411c2015-03-02 22:45:36434
435 private:
alexste3e46052015-05-04 19:40:56436 ~GLSurfaceOzoneSurfacelessSurfaceImpl() override;
achaulke86e411c2015-03-02 22:45:36437
alexste3e46052015-05-04 19:40:56438 void BindFramebuffer();
439 bool CreatePixmaps();
achaulke86e411c2015-03-02 22:45:36440
achaulk8d645d292015-08-04 14:09:27441 scoped_refptr<GLContext> context_;
achaulke86e411c2015-03-02 22:45:36442 GLuint fbo_;
443 GLuint textures_[2];
444 scoped_refptr<GLImage> images_[2];
445 int current_surface_;
446 DISALLOW_COPY_AND_ASSIGN(GLSurfaceOzoneSurfacelessSurfaceImpl);
447};
448
alexste3e46052015-05-04 19:40:56449GLSurfaceOzoneSurfacelessSurfaceImpl::GLSurfaceOzoneSurfacelessSurfaceImpl(
450 scoped_ptr<ui::SurfaceOzoneEGL> ozone_surface,
451 AcceleratedWidget widget)
martina.kollarova66bdb2b2015-12-17 08:35:46452 : GLSurfaceOzoneSurfaceless(std::move(ozone_surface), widget),
achaulk8d645d292015-08-04 14:09:27453 context_(nullptr),
alexste3e46052015-05-04 19:40:56454 fbo_(0),
455 current_surface_(0) {
456 for (auto& texture : textures_)
457 texture = 0;
458}
459
460unsigned int
461GLSurfaceOzoneSurfacelessSurfaceImpl::GetBackingFrameBufferObject() {
462 return fbo_;
463}
464
465bool GLSurfaceOzoneSurfacelessSurfaceImpl::OnMakeCurrent(GLContext* context) {
achaulk8d645d292015-08-04 14:09:27466 DCHECK(!context_ || context == context_);
467 context_ = context;
alexste3e46052015-05-04 19:40:56468 if (!fbo_) {
469 glGenFramebuffersEXT(1, &fbo_);
470 if (!fbo_)
471 return false;
472 glGenTextures(arraysize(textures_), textures_);
473 if (!CreatePixmaps())
474 return false;
475 }
476 BindFramebuffer();
477 glBindFramebufferEXT(GL_FRAMEBUFFER, fbo_);
478 return SurfacelessEGL::OnMakeCurrent(context);
479}
480
jbaumance45e112015-10-30 02:33:57481bool GLSurfaceOzoneSurfacelessSurfaceImpl::Resize(const gfx::Size& size,
jbauman16205872015-12-15 21:27:27482 float scale_factor,
483 bool has_alpha) {
alexste3e46052015-05-04 19:40:56484 if (size == GetSize())
485 return true;
jbauman16205872015-12-15 21:27:27486 // Alpha value isn't actually used in allocating buffers yet, so always use
487 // true instead.
488 return GLSurfaceOzoneSurfaceless::Resize(size, scale_factor, true) &&
jbaumance45e112015-10-30 02:33:57489 CreatePixmaps();
alexste3e46052015-05-04 19:40:56490}
491
492bool GLSurfaceOzoneSurfacelessSurfaceImpl::SupportsPostSubBuffer() {
493 return false;
494}
495
achaulkec8c2db2015-05-29 16:35:03496gfx::SwapResult GLSurfaceOzoneSurfacelessSurfaceImpl::SwapBuffers() {
alexste3e46052015-05-04 19:40:56497 if (!images_[current_surface_]->ScheduleOverlayPlane(
498 widget_, 0, OverlayTransform::OVERLAY_TRANSFORM_NONE,
499 gfx::Rect(GetSize()), gfx::RectF(1, 1)))
achaulkec8c2db2015-05-29 16:35:03500 return gfx::SwapResult::SWAP_FAILED;
501 gfx::SwapResult result = GLSurfaceOzoneSurfaceless::SwapBuffers();
502 if (result != gfx::SwapResult::SWAP_ACK)
503 return result;
alexste3e46052015-05-04 19:40:56504 current_surface_ ^= 1;
505 BindFramebuffer();
achaulkec8c2db2015-05-29 16:35:03506 return gfx::SwapResult::SWAP_ACK;
alexste3e46052015-05-04 19:40:56507}
508
spangf960a9502015-11-18 21:04:26509void GLSurfaceOzoneSurfacelessSurfaceImpl::SwapBuffersAsync(
alexste3e46052015-05-04 19:40:56510 const SwapCompletionCallback& callback) {
511 if (!images_[current_surface_]->ScheduleOverlayPlane(
512 widget_, 0, OverlayTransform::OVERLAY_TRANSFORM_NONE,
spangf960a9502015-11-18 21:04:26513 gfx::Rect(GetSize()), gfx::RectF(1, 1))) {
514 callback.Run(gfx::SwapResult::SWAP_FAILED);
515 return;
516 }
517 GLSurfaceOzoneSurfaceless::SwapBuffersAsync(callback);
alexste3e46052015-05-04 19:40:56518 current_surface_ ^= 1;
519 BindFramebuffer();
alexste3e46052015-05-04 19:40:56520}
521
522void GLSurfaceOzoneSurfacelessSurfaceImpl::Destroy() {
achaulk8d645d292015-08-04 14:09:27523 if (!context_)
524 return;
wuchengli20824f952015-10-22 05:05:27525 scoped_refptr<gfx::GLContext> previous_context = gfx::GLContext::GetCurrent();
526 scoped_refptr<gfx::GLSurface> previous_surface = gfx::GLSurface::GetCurrent();
527 context_->MakeCurrent(this);
528
alexste3e46052015-05-04 19:40:56529 glBindFramebufferEXT(GL_FRAMEBUFFER, 0);
530 if (fbo_) {
531 glDeleteTextures(arraysize(textures_), textures_);
532 for (auto& texture : textures_)
533 texture = 0;
534 glDeleteFramebuffersEXT(1, &fbo_);
535 fbo_ = 0;
536 }
537 for (auto image : images_) {
538 if (image)
539 image->Destroy(true);
540 }
wuchengli20824f952015-10-22 05:05:27541
542 if (previous_context.get()) {
543 previous_context->MakeCurrent(previous_surface.get());
544 } else {
545 context_->ReleaseCurrent(this);
546 }
alexste3e46052015-05-04 19:40:56547}
548
spangb55571ca2015-09-16 22:09:35549bool GLSurfaceOzoneSurfacelessSurfaceImpl::IsSurfaceless() const {
550 return false;
551}
552
alexste3e46052015-05-04 19:40:56553GLSurfaceOzoneSurfacelessSurfaceImpl::~GLSurfaceOzoneSurfacelessSurfaceImpl() {
wuchengli20824f952015-10-22 05:05:27554 Destroy();
alexste3e46052015-05-04 19:40:56555}
556
557void GLSurfaceOzoneSurfacelessSurfaceImpl::BindFramebuffer() {
558 ScopedFrameBufferBinder fb(fbo_);
559 glFramebufferTexture2DEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
560 textures_[current_surface_], 0);
561}
562
563bool GLSurfaceOzoneSurfacelessSurfaceImpl::CreatePixmaps() {
564 if (!fbo_)
565 return true;
566 for (size_t i = 0; i < arraysize(textures_); i++) {
567 scoped_refptr<ui::NativePixmap> pixmap =
dongseong.hwang9162b5fa2015-06-05 16:52:30568 ui::OzonePlatform::GetInstance()
569 ->GetSurfaceFactoryOzone()
570 ->CreateNativePixmap(widget_, GetSize(),
spangfcf5fab42015-08-04 19:25:35571 gfx::BufferFormat::BGRA_8888,
reveman1108e0b72015-10-30 17:05:44572 gfx::BufferUsage::SCANOUT);
alexste3e46052015-05-04 19:40:56573 if (!pixmap)
574 return false;
dongseong.hwang161c7a22015-07-29 18:28:17575 scoped_refptr<GLImageOzoneNativePixmap> image =
576 new GLImageOzoneNativePixmap(GetSize(), GL_BGRA_EXT);
reveman0bb50d72015-11-16 18:04:52577 if (!image->Initialize(pixmap.get(), gfx::BufferFormat::BGRA_8888))
alexste3e46052015-05-04 19:40:56578 return false;
579 images_[i] = image;
580 // Bind image to texture.
581 ScopedTextureBinder binder(GL_TEXTURE_2D, textures_[i]);
582 if (!images_[i]->BindTexImage(GL_TEXTURE_2D))
583 return false;
584 }
585 return true;
586}
587
spange82006b2015-09-16 18:07:29588scoped_refptr<GLSurface> CreateViewGLSurfaceOzone(
589 gfx::AcceleratedWidget window) {
590 scoped_ptr<ui::SurfaceOzoneEGL> surface_ozone =
591 ui::OzonePlatform::GetInstance()
592 ->GetSurfaceFactoryOzone()
593 ->CreateEGLSurfaceForWidget(window);
594 if (!surface_ozone)
595 return nullptr;
596 scoped_refptr<GLSurface> surface =
martina.kollarova66bdb2b2015-12-17 08:35:46597 new GLSurfaceOzoneEGL(std::move(surface_ozone), window);
spange82006b2015-09-16 18:07:29598 if (!surface->Initialize())
599 return nullptr;
600 return surface;
601}
602
603scoped_refptr<GLSurface> CreateViewGLSurfaceOzoneSurfacelessSurfaceImpl(
604 gfx::AcceleratedWidget window) {
605 scoped_ptr<ui::SurfaceOzoneEGL> surface_ozone =
606 ui::OzonePlatform::GetInstance()
607 ->GetSurfaceFactoryOzone()
608 ->CreateSurfacelessEGLSurfaceForWidget(window);
609 if (!surface_ozone)
610 return nullptr;
martina.kollarova66bdb2b2015-12-17 08:35:46611 scoped_refptr<GLSurface> surface = new GLSurfaceOzoneSurfacelessSurfaceImpl(
612 std::move(surface_ozone), window);
spange82006b2015-09-16 18:07:29613 if (!surface->Initialize())
614 return nullptr;
615 return surface;
616}
617
[email protected]502371d2014-03-31 17:16:42618} // namespace
619
[email protected]ffcdc9632014-03-27 17:25:23620// static
621bool GLSurface::InitializeOneOffInternal() {
[email protected]ffcdc9632014-03-27 17:25:23622 switch (GetGLImplementation()) {
623 case kGLImplementationEGLGLES2:
[email protected]ffcdc9632014-03-27 17:25:23624 if (!GLSurfaceEGL::InitializeOneOff()) {
625 LOG(ERROR) << "GLSurfaceEGL::InitializeOneOff failed.";
626 return false;
627 }
[email protected]1fe750572014-03-29 01:22:34628
629 return true;
630 case kGLImplementationOSMesaGL:
631 case kGLImplementationMockGL:
632 return true;
[email protected]ffcdc9632014-03-27 17:25:23633 default:
[email protected]1fe750572014-03-29 01:22:34634 return false;
[email protected]ffcdc9632014-03-27 17:25:23635 }
[email protected]ffcdc9632014-03-27 17:25:23636}
637
638// static
achaulke86e411c2015-03-02 22:45:36639scoped_refptr<GLSurface> GLSurface::CreateSurfacelessViewGLSurface(
640 gfx::AcceleratedWidget window) {
641 if (GetGLImplementation() == kGLImplementationEGLGLES2 &&
642 window != kNullAcceleratedWidget &&
spange82006b2015-09-16 18:07:29643 GLSurfaceEGL::IsEGLSurfacelessContextSupported()) {
achaulke86e411c2015-03-02 22:45:36644 scoped_ptr<ui::SurfaceOzoneEGL> surface_ozone =
dongseong.hwang9162b5fa2015-06-05 16:52:30645 ui::OzonePlatform::GetInstance()
646 ->GetSurfaceFactoryOzone()
achaulke86e411c2015-03-02 22:45:36647 ->CreateSurfacelessEGLSurfaceForWidget(window);
648 if (!surface_ozone)
649 return nullptr;
650 scoped_refptr<GLSurface> surface;
martina.kollarova66bdb2b2015-12-17 08:35:46651 surface = new GLSurfaceOzoneSurfaceless(std::move(surface_ozone), window);
achaulke86e411c2015-03-02 22:45:36652 if (surface->Initialize())
653 return surface;
654 }
655
656 return nullptr;
657}
658
659// static
[email protected]ffcdc9632014-03-27 17:25:23660scoped_refptr<GLSurface> GLSurface::CreateViewGLSurface(
661 gfx::AcceleratedWidget window) {
662 if (GetGLImplementation() == kGLImplementationOSMesaGL) {
663 scoped_refptr<GLSurface> surface(new GLSurfaceOSMesaHeadless());
664 if (!surface->Initialize())
spang0ac9fc32015-09-16 23:11:03665 return nullptr;
[email protected]ffcdc9632014-03-27 17:25:23666 return surface;
667 }
668 DCHECK(GetGLImplementation() == kGLImplementationEGLGLES2);
669 if (window != kNullAcceleratedWidget) {
achaulke79d5d852014-08-27 00:16:42670 scoped_refptr<GLSurface> surface;
spange82006b2015-09-16 18:07:29671 if (GLSurfaceEGL::IsEGLSurfacelessContextSupported())
672 surface = CreateViewGLSurfaceOzoneSurfacelessSurfaceImpl(window);
673 if (!surface)
674 surface = CreateViewGLSurfaceOzone(window);
[email protected]502371d2014-03-31 17:16:42675 return surface;
[email protected]ffcdc9632014-03-27 17:25:23676 } else {
677 scoped_refptr<GLSurface> surface = new GLSurfaceStub();
678 if (surface->Initialize())
679 return surface;
680 }
spang0ac9fc32015-09-16 23:11:03681 return nullptr;
[email protected]ffcdc9632014-03-27 17:25:23682}
683
684// static
685scoped_refptr<GLSurface> GLSurface::CreateOffscreenGLSurface(
686 const gfx::Size& size) {
687 switch (GetGLImplementation()) {
688 case kGLImplementationOSMesaGL: {
[email protected]dab86622014-08-16 14:34:59689 scoped_refptr<GLSurface> surface(
690 new GLSurfaceOSMesa(OSMesaSurfaceFormatBGRA, size));
[email protected]ffcdc9632014-03-27 17:25:23691 if (!surface->Initialize())
spang0ac9fc32015-09-16 23:11:03692 return nullptr;
[email protected]ffcdc9632014-03-27 17:25:23693
694 return surface;
695 }
696 case kGLImplementationEGLGLES2: {
697 scoped_refptr<GLSurface> surface;
698 if (GLSurfaceEGL::IsEGLSurfacelessContextSupported() &&
699 (size.width() == 0 && size.height() == 0)) {
700 surface = new SurfacelessEGL(size);
701 } else
702 surface = new PbufferGLSurfaceEGL(size);
703
704 if (!surface->Initialize())
spang0ac9fc32015-09-16 23:11:03705 return nullptr;
[email protected]ffcdc9632014-03-27 17:25:23706 return surface;
707 }
zmoeecacfe2015-05-07 05:42:53708 case kGLImplementationMockGL:
709 return new GLSurfaceStub;
[email protected]ffcdc9632014-03-27 17:25:23710 default:
711 NOTREACHED();
spang0ac9fc32015-09-16 23:11:03712 return nullptr;
[email protected]ffcdc9632014-03-27 17:25:23713 }
714}
715
716EGLNativeDisplayType GetPlatformDefaultEGLNativeDisplay() {
dongseong.hwang9162b5fa2015-06-05 16:52:30717 return ui::OzonePlatform::GetInstance()
718 ->GetSurfaceFactoryOzone()
719 ->GetNativeDisplay();
[email protected]ffcdc9632014-03-27 17:25:23720}
721
722} // namespace gfx