| Index: ui/gl/gl_surface_ozone.cc
|
| diff --git a/ui/gl/gl_surface_ozone.cc b/ui/gl/gl_surface_ozone.cc
|
| index 800be1759fe96331573944463123e00ce19968f2..c513e5fb88d1538bb985a1cff9728ce5dbd6d9d2 100644
|
| --- a/ui/gl/gl_surface_ozone.cc
|
| +++ b/ui/gl/gl_surface_ozone.cc
|
| @@ -9,6 +9,7 @@
|
| #include "base/location.h"
|
| #include "base/logging.h"
|
| #include "base/memory/ref_counted.h"
|
| +#include "base/memory/scoped_vector.h"
|
| #include "base/memory/weak_ptr.h"
|
| #include "base/threading/worker_pool.h"
|
| #include "ui/gfx/native_widget_types.h"
|
| @@ -22,6 +23,7 @@
|
| #include "ui/gl/scoped_binders.h"
|
| #include "ui/gl/scoped_make_current.h"
|
| #include "ui/ozone/public/native_pixmap.h"
|
| +#include "ui/ozone/public/ozone_platform.h"
|
| #include "ui/ozone/public/surface_factory_ozone.h"
|
| #include "ui/ozone/public/surface_ozone_egl.h"
|
|
|
| @@ -38,72 +40,25 @@ void WaitForFence(EGLDisplay display, EGLSyncKHR fence) {
|
| class GL_EXPORT GLSurfaceOzoneEGL : public NativeViewGLSurfaceEGL {
|
| public:
|
| GLSurfaceOzoneEGL(scoped_ptr<ui::SurfaceOzoneEGL> ozone_surface,
|
| - AcceleratedWidget widget)
|
| - : NativeViewGLSurfaceEGL(ozone_surface->GetNativeWindow()),
|
| - ozone_surface_(ozone_surface.Pass()),
|
| - widget_(widget) {}
|
| + AcceleratedWidget widget,
|
| + const gfx::SurfaceConfiguration& requested_configuration);
|
|
|
| - bool Initialize() override {
|
| - return Initialize(ozone_surface_->CreateVSyncProvider());
|
| - }
|
| - bool Resize(const gfx::Size& size) override {
|
| - if (!ozone_surface_->ResizeNativeWindow(size)) {
|
| - if (!ReinitializeNativeSurface() ||
|
| - !ozone_surface_->ResizeNativeWindow(size))
|
| - return false;
|
| - }
|
| -
|
| - return NativeViewGLSurfaceEGL::Resize(size);
|
| - }
|
| - bool SwapBuffers() override {
|
| - if (!NativeViewGLSurfaceEGL::SwapBuffers())
|
| - return false;
|
| -
|
| - return ozone_surface_->OnSwapBuffers();
|
| - }
|
| + // GLSurface:
|
| + bool Initialize() override;
|
| + bool Resize(const gfx::Size& size) override;
|
| + gfx::SwapResult SwapBuffers() override;
|
| bool ScheduleOverlayPlane(int z_order,
|
| OverlayTransform transform,
|
| GLImage* image,
|
| const Rect& bounds_rect,
|
| - const RectF& crop_rect) override {
|
| - return image->ScheduleOverlayPlane(
|
| - widget_, z_order, transform, bounds_rect, crop_rect);
|
| - }
|
| + const RectF& crop_rect) override;
|
|
|
| private:
|
| using NativeViewGLSurfaceEGL::Initialize;
|
|
|
| - ~GLSurfaceOzoneEGL() override {
|
| - Destroy(); // EGL surface must be destroyed before SurfaceOzone
|
| - }
|
| + ~GLSurfaceOzoneEGL() override;
|
|
|
| - bool ReinitializeNativeSurface() {
|
| - scoped_ptr<ui::ScopedMakeCurrent> scoped_make_current;
|
| - GLContext* current_context = GLContext::GetCurrent();
|
| - bool was_current =
|
| - current_context && current_context->IsCurrent(this);
|
| - if (was_current) {
|
| - scoped_make_current.reset(
|
| - new ui::ScopedMakeCurrent(current_context, this));
|
| - }
|
| -
|
| - Destroy();
|
| - ozone_surface_ =
|
| - ui::SurfaceFactoryOzone::GetInstance()->CreateEGLSurfaceForWidget(
|
| - widget_).Pass();
|
| - if (!ozone_surface_) {
|
| - LOG(ERROR) << "Failed to create native surface.";
|
| - return false;
|
| - }
|
| -
|
| - window_ = ozone_surface_->GetNativeWindow();
|
| - if (!Initialize()) {
|
| - LOG(ERROR) << "Failed to initialize.";
|
| - return false;
|
| - }
|
| -
|
| - return true;
|
| - }
|
| + bool ReinitializeNativeSurface();
|
|
|
| // The native surface. Deleting this is allowed to free the EGLNativeWindow.
|
| scoped_ptr<ui::SurfaceOzoneEGL> ozone_surface_;
|
| @@ -112,276 +67,396 @@ class GL_EXPORT GLSurfaceOzoneEGL : public NativeViewGLSurfaceEGL {
|
| DISALLOW_COPY_AND_ASSIGN(GLSurfaceOzoneEGL);
|
| };
|
|
|
| -class GL_EXPORT GLSurfaceOzoneSurfaceless : public SurfacelessEGL {
|
| - public:
|
| - GLSurfaceOzoneSurfaceless(scoped_ptr<ui::SurfaceOzoneEGL> ozone_surface,
|
| - AcceleratedWidget widget)
|
| - : SurfacelessEGL(gfx::Size()),
|
| - ozone_surface_(ozone_surface.Pass()),
|
| - widget_(widget),
|
| - has_implicit_external_sync_(
|
| - HasEGLExtension("EGL_ARM_implicit_external_sync")),
|
| - last_swap_buffers_result_(true),
|
| - weak_factory_(this) {}
|
| -
|
| - bool Initialize() override {
|
| - if (!SurfacelessEGL::Initialize())
|
| - return false;
|
| - vsync_provider_ = ozone_surface_->CreateVSyncProvider();
|
| - if (!vsync_provider_)
|
| +GLSurfaceOzoneEGL::GLSurfaceOzoneEGL(
|
| + scoped_ptr<ui::SurfaceOzoneEGL> ozone_surface,
|
| + AcceleratedWidget widget,
|
| + const gfx::SurfaceConfiguration& requested_configuration)
|
| + : NativeViewGLSurfaceEGL(ozone_surface->GetNativeWindow(),
|
| + requested_configuration),
|
| + ozone_surface_(ozone_surface.Pass()),
|
| + widget_(widget) {
|
| +}
|
| +
|
| +bool GLSurfaceOzoneEGL::Initialize() {
|
| + return Initialize(ozone_surface_->CreateVSyncProvider());
|
| +}
|
| +
|
| +bool GLSurfaceOzoneEGL::Resize(const gfx::Size& size) {
|
| + if (!ozone_surface_->ResizeNativeWindow(size)) {
|
| + if (!ReinitializeNativeSurface() ||
|
| + !ozone_surface_->ResizeNativeWindow(size))
|
| return false;
|
| - return true;
|
| }
|
| - bool Resize(const gfx::Size& size) override {
|
| - if (!ozone_surface_->ResizeNativeWindow(size))
|
| - return false;
|
|
|
| - return SurfacelessEGL::Resize(size);
|
| + return NativeViewGLSurfaceEGL::Resize(size);
|
| +}
|
| +
|
| +gfx::SwapResult GLSurfaceOzoneEGL::SwapBuffers() {
|
| + gfx::SwapResult result = NativeViewGLSurfaceEGL::SwapBuffers();
|
| + if (result != gfx::SwapResult::SWAP_ACK)
|
| + return result;
|
| +
|
| + return ozone_surface_->OnSwapBuffers() ? gfx::SwapResult::SWAP_ACK
|
| + : gfx::SwapResult::SWAP_FAILED;
|
| +}
|
| +
|
| +bool GLSurfaceOzoneEGL::ScheduleOverlayPlane(int z_order,
|
| + OverlayTransform transform,
|
| + GLImage* image,
|
| + const Rect& bounds_rect,
|
| + const RectF& crop_rect) {
|
| + return image->ScheduleOverlayPlane(widget_, z_order, transform, bounds_rect,
|
| + crop_rect);
|
| +}
|
| +
|
| +GLSurfaceOzoneEGL::~GLSurfaceOzoneEGL() {
|
| + Destroy(); // EGL surface must be destroyed before SurfaceOzone
|
| +}
|
| +
|
| +bool GLSurfaceOzoneEGL::ReinitializeNativeSurface() {
|
| + scoped_ptr<ui::ScopedMakeCurrent> scoped_make_current;
|
| + GLContext* current_context = GLContext::GetCurrent();
|
| + bool was_current = current_context && current_context->IsCurrent(this);
|
| + if (was_current) {
|
| + scoped_make_current.reset(new ui::ScopedMakeCurrent(current_context, this));
|
| }
|
| - bool SwapBuffers() override {
|
| - glFlush();
|
| - // TODO: the following should be replaced by a per surface flush as it gets
|
| - // implemented in GL drivers.
|
| - if (has_implicit_external_sync_) {
|
| - EGLSyncKHR fence = InsertFence();
|
| - if (!fence)
|
| - return false;
|
|
|
| - EGLDisplay display = GetDisplay();
|
| - WaitForFence(display, fence);
|
| - eglDestroySyncKHR(display, fence);
|
| - } else if (ozone_surface_->IsUniversalDisplayLinkDevice()) {
|
| - glFinish();
|
| - }
|
| + Destroy();
|
| + ozone_surface_ = ui::OzonePlatform::GetInstance()
|
| + ->GetSurfaceFactoryOzone()
|
| + ->CreateEGLSurfaceForWidget(widget_)
|
| + .Pass();
|
| + if (!ozone_surface_) {
|
| + LOG(ERROR) << "Failed to create native surface.";
|
| + return false;
|
| + }
|
|
|
| - return ozone_surface_->OnSwapBuffers();
|
| + window_ = ozone_surface_->GetNativeWindow();
|
| + if (!Initialize()) {
|
| + LOG(ERROR) << "Failed to initialize.";
|
| + return false;
|
| }
|
| +
|
| + return true;
|
| +}
|
| +
|
| +class GL_EXPORT GLSurfaceOzoneSurfaceless : public SurfacelessEGL {
|
| + public:
|
| + GLSurfaceOzoneSurfaceless(
|
| + scoped_ptr<ui::SurfaceOzoneEGL> ozone_surface,
|
| + AcceleratedWidget widget,
|
| + const gfx::SurfaceConfiguration& requested_configuration);
|
| +
|
| + // GLSurface:
|
| + bool Initialize() override;
|
| + bool Resize(const gfx::Size& size) override;
|
| + gfx::SwapResult SwapBuffers() override;
|
| bool ScheduleOverlayPlane(int z_order,
|
| OverlayTransform transform,
|
| GLImage* image,
|
| const Rect& bounds_rect,
|
| - const RectF& crop_rect) override {
|
| - return image->ScheduleOverlayPlane(
|
| - widget_, z_order, transform, bounds_rect, crop_rect);
|
| - }
|
| - bool IsOffscreen() override { return false; }
|
| - VSyncProvider* GetVSyncProvider() override { return vsync_provider_.get(); }
|
| - bool SupportsPostSubBuffer() override { return true; }
|
| - bool PostSubBuffer(int x, int y, int width, int height) override {
|
| - // The actual sub buffer handling is handled at higher layers.
|
| - SwapBuffers();
|
| - return true;
|
| - }
|
| - bool SwapBuffersAsync(const SwapCompletionCallback& callback) override {
|
| - glFlush();
|
| - // TODO: the following should be replaced by a per surface flush as it gets
|
| - // implemented in GL drivers.
|
| - if (has_implicit_external_sync_) {
|
| - // If last swap failed, don't try to schedule new ones.
|
| - if (!last_swap_buffers_result_) {
|
| - last_swap_buffers_result_ = true;
|
| - return false;
|
| - }
|
| -
|
| - EGLSyncKHR fence = InsertFence();
|
| - if (!fence)
|
| - return false;
|
| -
|
| - base::Closure fence_wait_task =
|
| - base::Bind(&WaitForFence, GetDisplay(), fence);
|
| -
|
| - base::Closure fence_retired_callback =
|
| - base::Bind(&GLSurfaceOzoneSurfaceless::FenceRetired,
|
| - weak_factory_.GetWeakPtr(), fence, callback);
|
| -
|
| - base::WorkerPool::PostTaskAndReply(FROM_HERE, fence_wait_task,
|
| - fence_retired_callback, false);
|
| - return true;
|
| - } else if (ozone_surface_->IsUniversalDisplayLinkDevice()) {
|
| - glFinish();
|
| - }
|
| - return ozone_surface_->OnSwapBuffersAsync(callback);
|
| - }
|
| + const RectF& crop_rect) override;
|
| + bool IsOffscreen() override;
|
| + VSyncProvider* GetVSyncProvider() override;
|
| + bool SupportsPostSubBuffer() override;
|
| + gfx::SwapResult PostSubBuffer(int x, int y, int width, int height) override;
|
| + bool SwapBuffersAsync(const SwapCompletionCallback& callback) override;
|
| bool PostSubBufferAsync(int x,
|
| int y,
|
| int width,
|
| int height,
|
| - const SwapCompletionCallback& callback) override {
|
| - return SwapBuffersAsync(callback);
|
| - }
|
| + const SwapCompletionCallback& callback) override;
|
|
|
| protected:
|
| - ~GLSurfaceOzoneSurfaceless() override {
|
| - Destroy(); // EGL surface must be destroyed before SurfaceOzone
|
| - }
|
| + struct Overlay {
|
| + Overlay(int z_order,
|
| + OverlayTransform transform,
|
| + GLImage* image,
|
| + const Rect& bounds_rect,
|
| + const RectF& crop_rect);
|
| +
|
| + bool ScheduleOverlayPlane(gfx::AcceleratedWidget widget) const;
|
| +
|
| + int z_order;
|
| + OverlayTransform transform;
|
| + scoped_refptr<GLImage> image;
|
| + Rect bounds_rect;
|
| + RectF crop_rect;
|
| + };
|
|
|
| - EGLSyncKHR InsertFence() {
|
| - const EGLint attrib_list[] = {EGL_SYNC_CONDITION_KHR,
|
| - EGL_SYNC_PRIOR_COMMANDS_IMPLICIT_EXTERNAL_ARM,
|
| - EGL_NONE};
|
| - return eglCreateSyncKHR(GetDisplay(), EGL_SYNC_FENCE_KHR, attrib_list);
|
| - }
|
| + struct PendingFrame {
|
| + PendingFrame();
|
|
|
| - void FenceRetired(EGLSyncKHR fence, const SwapCompletionCallback& callback) {
|
| - eglDestroySyncKHR(GetDisplay(), fence);
|
| - last_swap_buffers_result_ = ozone_surface_->OnSwapBuffersAsync(callback);
|
| - }
|
| + bool ScheduleOverlayPlanes(gfx::AcceleratedWidget widget);
|
| +
|
| + bool ready;
|
| + std::vector<Overlay> overlays;
|
| + SwapCompletionCallback callback;
|
| + };
|
| +
|
| + ~GLSurfaceOzoneSurfaceless() override;
|
| +
|
| + void SubmitFrame();
|
| +
|
| + EGLSyncKHR InsertFence();
|
| + void FenceRetired(EGLSyncKHR fence, PendingFrame* frame);
|
| +
|
| + void SwapCompleted(const SwapCompletionCallback& callback,
|
| + gfx::SwapResult result);
|
|
|
| // The native surface. Deleting this is allowed to free the EGLNativeWindow.
|
| scoped_ptr<ui::SurfaceOzoneEGL> ozone_surface_;
|
| AcceleratedWidget widget_;
|
| scoped_ptr<VSyncProvider> vsync_provider_;
|
| + ScopedVector<PendingFrame> unsubmitted_frames_;
|
| bool has_implicit_external_sync_;
|
| bool last_swap_buffers_result_;
|
| + bool swap_buffers_pending_;
|
|
|
| base::WeakPtrFactory<GLSurfaceOzoneSurfaceless> weak_factory_;
|
|
|
| DISALLOW_COPY_AND_ASSIGN(GLSurfaceOzoneSurfaceless);
|
| };
|
|
|
| -// This provides surface-like semantics implemented through surfaceless.
|
| -// A framebuffer is bound automatically.
|
| -class GL_EXPORT GLSurfaceOzoneSurfacelessSurfaceImpl
|
| - : public GLSurfaceOzoneSurfaceless {
|
| - public:
|
| - GLSurfaceOzoneSurfacelessSurfaceImpl(
|
| - scoped_ptr<ui::SurfaceOzoneEGL> ozone_surface,
|
| - AcceleratedWidget widget)
|
| - : GLSurfaceOzoneSurfaceless(ozone_surface.Pass(), widget),
|
| - fbo_(0),
|
| - current_surface_(0) {
|
| - for (auto& texture : textures_)
|
| - texture = 0;
|
| - }
|
| +GLSurfaceOzoneSurfaceless::Overlay::Overlay(int z_order,
|
| + OverlayTransform transform,
|
| + GLImage* image,
|
| + const Rect& bounds_rect,
|
| + const RectF& crop_rect)
|
| + : z_order(z_order),
|
| + transform(transform),
|
| + image(image),
|
| + bounds_rect(bounds_rect),
|
| + crop_rect(crop_rect) {
|
| +}
|
|
|
| - unsigned int GetBackingFrameBufferObject() override { return fbo_; }
|
| +bool GLSurfaceOzoneSurfaceless::Overlay::ScheduleOverlayPlane(
|
| + gfx::AcceleratedWidget widget) const {
|
| + return image->ScheduleOverlayPlane(widget, z_order, transform, bounds_rect,
|
| + crop_rect);
|
| +}
|
|
|
| - bool OnMakeCurrent(GLContext* context) override {
|
| - if (!fbo_) {
|
| - glGenFramebuffersEXT(1, &fbo_);
|
| - if (!fbo_)
|
| - return false;
|
| - glGenTextures(arraysize(textures_), textures_);
|
| - if (!CreatePixmaps())
|
| - return false;
|
| - }
|
| - BindFramebuffer();
|
| - glBindFramebufferEXT(GL_FRAMEBUFFER, fbo_);
|
| - return SurfacelessEGL::OnMakeCurrent(context);
|
| - }
|
| +GLSurfaceOzoneSurfaceless::PendingFrame::PendingFrame() : ready(false) {
|
| +}
|
|
|
| - bool Resize(const gfx::Size& size) override {
|
| - if (size == GetSize())
|
| - return true;
|
| - return GLSurfaceOzoneSurfaceless::Resize(size) && CreatePixmaps();
|
| - }
|
| +bool GLSurfaceOzoneSurfaceless::PendingFrame::ScheduleOverlayPlanes(
|
| + gfx::AcceleratedWidget widget) {
|
| + for (const auto& overlay : overlays)
|
| + if (!overlay.ScheduleOverlayPlane(widget))
|
| + return false;
|
| + return true;
|
| +}
|
|
|
| - bool SupportsPostSubBuffer() override { return false; }
|
| +GLSurfaceOzoneSurfaceless::GLSurfaceOzoneSurfaceless(
|
| + scoped_ptr<ui::SurfaceOzoneEGL> ozone_surface,
|
| + AcceleratedWidget widget,
|
| + const gfx::SurfaceConfiguration& requested_configuration)
|
| + : SurfacelessEGL(gfx::Size(), requested_configuration),
|
| + ozone_surface_(ozone_surface.Pass()),
|
| + widget_(widget),
|
| + has_implicit_external_sync_(
|
| + HasEGLExtension("EGL_ARM_implicit_external_sync")),
|
| + last_swap_buffers_result_(true),
|
| + swap_buffers_pending_(false),
|
| + weak_factory_(this) {
|
| + unsubmitted_frames_.push_back(new PendingFrame());
|
| +}
|
|
|
| - bool SwapBuffers() override {
|
| - if (!images_[current_surface_]->ScheduleOverlayPlane(
|
| - widget_, 0, OverlayTransform::OVERLAY_TRANSFORM_NONE,
|
| - gfx::Rect(GetSize()), gfx::RectF(1, 1)))
|
| - return false;
|
| - if (!GLSurfaceOzoneSurfaceless::SwapBuffers())
|
| - return false;
|
| - current_surface_ ^= 1;
|
| - BindFramebuffer();
|
| - return true;
|
| +bool GLSurfaceOzoneSurfaceless::Initialize() {
|
| + if (!SurfacelessEGL::Initialize())
|
| + return false;
|
| + vsync_provider_ = ozone_surface_->CreateVSyncProvider();
|
| + if (!vsync_provider_)
|
| + return false;
|
| + return true;
|
| +}
|
| +bool GLSurfaceOzoneSurfaceless::Resize(const gfx::Size& size) {
|
| + if (!ozone_surface_->ResizeNativeWindow(size))
|
| + return false;
|
| +
|
| + return SurfacelessEGL::Resize(size);
|
| +}
|
| +gfx::SwapResult GLSurfaceOzoneSurfaceless::SwapBuffers() {
|
| + glFlush();
|
| + // TODO: the following should be replaced by a per surface flush as it gets
|
| + // implemented in GL drivers.
|
| + if (has_implicit_external_sync_) {
|
| + EGLSyncKHR fence = InsertFence();
|
| + if (!fence)
|
| + return SwapResult::SWAP_FAILED;
|
| +
|
| + EGLDisplay display = GetDisplay();
|
| + WaitForFence(display, fence);
|
| + eglDestroySyncKHR(display, fence);
|
| + } else if (ozone_surface_->IsUniversalDisplayLinkDevice()) {
|
| + glFinish();
|
| }
|
|
|
| - bool SwapBuffersAsync(const SwapCompletionCallback& callback) override {
|
| - if (!images_[current_surface_]->ScheduleOverlayPlane(
|
| - widget_, 0, OverlayTransform::OVERLAY_TRANSFORM_NONE,
|
| - gfx::Rect(GetSize()), gfx::RectF(1, 1)))
|
| - return false;
|
| - if (!GLSurfaceOzoneSurfaceless::SwapBuffersAsync(callback))
|
| + unsubmitted_frames_.back()->ScheduleOverlayPlanes(widget_);
|
| + unsubmitted_frames_.back()->overlays.clear();
|
| +
|
| + return ozone_surface_->OnSwapBuffers() ? gfx::SwapResult::SWAP_ACK
|
| + : gfx::SwapResult::SWAP_FAILED;
|
| +}
|
| +bool GLSurfaceOzoneSurfaceless::ScheduleOverlayPlane(int z_order,
|
| + OverlayTransform transform,
|
| + GLImage* image,
|
| + const Rect& bounds_rect,
|
| + const RectF& crop_rect) {
|
| + unsubmitted_frames_.back()->overlays.push_back(
|
| + Overlay(z_order, transform, image, bounds_rect, crop_rect));
|
| + return true;
|
| +}
|
| +bool GLSurfaceOzoneSurfaceless::IsOffscreen() {
|
| + return false;
|
| +}
|
| +VSyncProvider* GLSurfaceOzoneSurfaceless::GetVSyncProvider() {
|
| + return vsync_provider_.get();
|
| +}
|
| +bool GLSurfaceOzoneSurfaceless::SupportsPostSubBuffer() {
|
| + return true;
|
| +}
|
| +gfx::SwapResult GLSurfaceOzoneSurfaceless::PostSubBuffer(int x,
|
| + int y,
|
| + int width,
|
| + int height) {
|
| + // The actual sub buffer handling is handled at higher layers.
|
| + SwapBuffers();
|
| + return gfx::SwapResult::SWAP_ACK;
|
| +}
|
| +bool GLSurfaceOzoneSurfaceless::SwapBuffersAsync(
|
| + const SwapCompletionCallback& callback) {
|
| + // If last swap failed, don't try to schedule new ones.
|
| + if (!last_swap_buffers_result_)
|
| + return false;
|
| +
|
| + glFlush();
|
| +
|
| + SwapCompletionCallback surface_swap_callback =
|
| + base::Bind(&GLSurfaceOzoneSurfaceless::SwapCompleted,
|
| + weak_factory_.GetWeakPtr(), callback);
|
| +
|
| + PendingFrame* frame = unsubmitted_frames_.back();
|
| + frame->callback = surface_swap_callback;
|
| + unsubmitted_frames_.push_back(new PendingFrame());
|
| +
|
| + // TODO: the following should be replaced by a per surface flush as it gets
|
| + // implemented in GL drivers.
|
| + if (has_implicit_external_sync_) {
|
| + EGLSyncKHR fence = InsertFence();
|
| + if (!fence)
|
| return false;
|
| - current_surface_ ^= 1;
|
| - BindFramebuffer();
|
| +
|
| + base::Closure fence_wait_task =
|
| + base::Bind(&WaitForFence, GetDisplay(), fence);
|
| +
|
| + base::Closure fence_retired_callback =
|
| + base::Bind(&GLSurfaceOzoneSurfaceless::FenceRetired,
|
| + weak_factory_.GetWeakPtr(), fence, frame);
|
| +
|
| + base::WorkerPool::PostTaskAndReply(FROM_HERE, fence_wait_task,
|
| + fence_retired_callback, false);
|
| return true;
|
| + } else if (ozone_surface_->IsUniversalDisplayLinkDevice()) {
|
| + glFinish();
|
| }
|
|
|
| - void Destroy() override {
|
| - GLContext* current_context = GLContext::GetCurrent();
|
| - DCHECK(current_context && current_context->IsCurrent(this));
|
| - glBindFramebufferEXT(GL_FRAMEBUFFER, 0);
|
| - if (fbo_) {
|
| - glDeleteTextures(arraysize(textures_), textures_);
|
| - for (auto& texture : textures_)
|
| - texture = 0;
|
| - glDeleteFramebuffersEXT(1, &fbo_);
|
| - fbo_ = 0;
|
| - }
|
| - for (auto image : images_) {
|
| - if (image)
|
| - image->Destroy(true);
|
| - }
|
| + frame->ready = true;
|
| + SubmitFrame();
|
| + return last_swap_buffers_result_;
|
| +}
|
| +bool GLSurfaceOzoneSurfaceless::PostSubBufferAsync(
|
| + int x,
|
| + int y,
|
| + int width,
|
| + int height,
|
| + const SwapCompletionCallback& callback) {
|
| + return SwapBuffersAsync(callback);
|
| +}
|
| +
|
| +GLSurfaceOzoneSurfaceless::~GLSurfaceOzoneSurfaceless() {
|
| + Destroy(); // EGL surface must be destroyed before SurfaceOzone
|
| +}
|
| +
|
| +void GLSurfaceOzoneSurfaceless::SubmitFrame() {
|
| + DCHECK(!unsubmitted_frames_.empty());
|
| +
|
| + if (unsubmitted_frames_.front()->ready && !swap_buffers_pending_) {
|
| + scoped_ptr<PendingFrame> frame(unsubmitted_frames_.front());
|
| + unsubmitted_frames_.weak_erase(unsubmitted_frames_.begin());
|
| + swap_buffers_pending_ = true;
|
| +
|
| + last_swap_buffers_result_ =
|
| + frame->ScheduleOverlayPlanes(widget_) &&
|
| + ozone_surface_->OnSwapBuffersAsync(frame->callback);
|
| }
|
| +}
|
| +
|
| +EGLSyncKHR GLSurfaceOzoneSurfaceless::InsertFence() {
|
| + const EGLint attrib_list[] = {EGL_SYNC_CONDITION_KHR,
|
| + EGL_SYNC_PRIOR_COMMANDS_IMPLICIT_EXTERNAL_ARM,
|
| + EGL_NONE};
|
| + return eglCreateSyncKHR(GetDisplay(), EGL_SYNC_FENCE_KHR, attrib_list);
|
| +}
|
| +
|
| +void GLSurfaceOzoneSurfaceless::FenceRetired(EGLSyncKHR fence,
|
| + PendingFrame* frame) {
|
| + eglDestroySyncKHR(GetDisplay(), fence);
|
| + frame->ready = true;
|
| + SubmitFrame();
|
| +}
|
| +
|
| +void GLSurfaceOzoneSurfaceless::SwapCompleted(
|
| + const SwapCompletionCallback& callback,
|
| + gfx::SwapResult result) {
|
| + callback.Run(result);
|
| + swap_buffers_pending_ = false;
|
| +
|
| + SubmitFrame();
|
| +}
|
| +
|
| +// This provides surface-like semantics implemented through surfaceless.
|
| +// A framebuffer is bound automatically.
|
| +class GL_EXPORT GLSurfaceOzoneSurfacelessSurfaceImpl
|
| + : public GLSurfaceOzoneSurfaceless {
|
| + public:
|
| + GLSurfaceOzoneSurfacelessSurfaceImpl(
|
| + scoped_ptr<ui::SurfaceOzoneEGL> ozone_surface,
|
| + AcceleratedWidget widget,
|
| + const gfx::SurfaceConfiguration& requested_configuration);
|
| +
|
| + // GLSurface:
|
| + unsigned int GetBackingFrameBufferObject() override;
|
| + bool OnMakeCurrent(GLContext* context) override;
|
| + bool Resize(const gfx::Size& size) override;
|
| + bool SupportsPostSubBuffer() override;
|
| + gfx::SwapResult SwapBuffers() override;
|
| + bool SwapBuffersAsync(const SwapCompletionCallback& callback) override;
|
| + void Destroy() override;
|
|
|
| private:
|
| class SurfaceImage : public GLImageLinuxDMABuffer {
|
| public:
|
| - SurfaceImage(const gfx::Size& size, unsigned internalformat)
|
| - : GLImageLinuxDMABuffer(size, internalformat) {}
|
| + SurfaceImage(const gfx::Size& size, unsigned internalformat);
|
|
|
| bool Initialize(scoped_refptr<ui::NativePixmap> pixmap,
|
| - gfx::GpuMemoryBuffer::Format format) {
|
| - base::FileDescriptor handle(pixmap->GetDmaBufFd(), false);
|
| - if (!GLImageLinuxDMABuffer::Initialize(handle, format,
|
| - pixmap->GetDmaBufPitch()))
|
| - return false;
|
| - pixmap_ = pixmap;
|
| - return true;
|
| - }
|
| + gfx::GpuMemoryBuffer::Format format);
|
| bool ScheduleOverlayPlane(gfx::AcceleratedWidget widget,
|
| int z_order,
|
| gfx::OverlayTransform transform,
|
| const gfx::Rect& bounds_rect,
|
| - const gfx::RectF& crop_rect) override {
|
| - return ui::SurfaceFactoryOzone::GetInstance()->ScheduleOverlayPlane(
|
| - widget, z_order, transform, pixmap_, bounds_rect, crop_rect);
|
| - }
|
| + const gfx::RectF& crop_rect) override;
|
|
|
| private:
|
| - ~SurfaceImage() override {}
|
| + ~SurfaceImage() override;
|
|
|
| scoped_refptr<ui::NativePixmap> pixmap_;
|
| };
|
|
|
| - ~GLSurfaceOzoneSurfacelessSurfaceImpl() override {
|
| - DCHECK(!fbo_);
|
| - for (size_t i = 0; i < arraysize(textures_); i++)
|
| - DCHECK(!textures_[i]) << "texture " << i << " not released";
|
| - }
|
| -
|
| - void BindFramebuffer() {
|
| - ScopedFrameBufferBinder fb(fbo_);
|
| - glFramebufferTexture2DEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
|
| - GL_TEXTURE_2D, textures_[current_surface_], 0);
|
| - }
|
| + ~GLSurfaceOzoneSurfacelessSurfaceImpl() override;
|
|
|
| - bool CreatePixmaps() {
|
| - if (!fbo_)
|
| - return true;
|
| - for (size_t i = 0; i < arraysize(textures_); i++) {
|
| - scoped_refptr<ui::NativePixmap> pixmap =
|
| - ui::SurfaceFactoryOzone::GetInstance()->CreateNativePixmap(
|
| - widget_, GetSize(), ui::SurfaceFactoryOzone::RGBA_8888,
|
| - ui::SurfaceFactoryOzone::SCANOUT);
|
| - if (!pixmap)
|
| - return false;
|
| - scoped_refptr<SurfaceImage> image = new SurfaceImage(GetSize(), GL_RGBA);
|
| - if (!image->Initialize(pixmap, gfx::GpuMemoryBuffer::Format::BGRA_8888))
|
| - return false;
|
| - images_[i] = image;
|
| - // Bind image to texture.
|
| - ScopedTextureBinder binder(GL_TEXTURE_2D, textures_[i]);
|
| - if (!images_[i]->BindTexImage(GL_TEXTURE_2D))
|
| - return false;
|
| - }
|
| - return true;
|
| - }
|
| + void BindFramebuffer();
|
| + bool CreatePixmaps();
|
|
|
| GLuint fbo_;
|
| GLuint textures_[2];
|
| @@ -390,6 +465,156 @@ class GL_EXPORT GLSurfaceOzoneSurfacelessSurfaceImpl
|
| DISALLOW_COPY_AND_ASSIGN(GLSurfaceOzoneSurfacelessSurfaceImpl);
|
| };
|
|
|
| +GLSurfaceOzoneSurfacelessSurfaceImpl::SurfaceImage::SurfaceImage(
|
| + const gfx::Size& size,
|
| + unsigned internalformat)
|
| + : GLImageLinuxDMABuffer(size, internalformat) {
|
| +}
|
| +
|
| +bool GLSurfaceOzoneSurfacelessSurfaceImpl::SurfaceImage::Initialize(
|
| + scoped_refptr<ui::NativePixmap> pixmap,
|
| + gfx::GpuMemoryBuffer::Format format) {
|
| + base::FileDescriptor handle(pixmap->GetDmaBufFd(), false);
|
| + if (!GLImageLinuxDMABuffer::Initialize(handle, format,
|
| + pixmap->GetDmaBufPitch()))
|
| + return false;
|
| + pixmap_ = pixmap;
|
| + return true;
|
| +}
|
| +bool GLSurfaceOzoneSurfacelessSurfaceImpl::SurfaceImage::ScheduleOverlayPlane(
|
| + gfx::AcceleratedWidget widget,
|
| + int z_order,
|
| + gfx::OverlayTransform transform,
|
| + const gfx::Rect& bounds_rect,
|
| + const gfx::RectF& crop_rect) {
|
| + return pixmap_->ScheduleOverlayPlane(widget, z_order, transform, bounds_rect,
|
| + crop_rect);
|
| +}
|
| +
|
| +GLSurfaceOzoneSurfacelessSurfaceImpl::SurfaceImage::~SurfaceImage() {
|
| +}
|
| +
|
| +GLSurfaceOzoneSurfacelessSurfaceImpl::GLSurfaceOzoneSurfacelessSurfaceImpl(
|
| + scoped_ptr<ui::SurfaceOzoneEGL> ozone_surface,
|
| + AcceleratedWidget widget,
|
| + const gfx::SurfaceConfiguration& requested_configuration)
|
| + : GLSurfaceOzoneSurfaceless(
|
| + ozone_surface.Pass(), widget, requested_configuration),
|
| + fbo_(0),
|
| + current_surface_(0) {
|
| + for (auto& texture : textures_)
|
| + texture = 0;
|
| +}
|
| +
|
| +unsigned int
|
| +GLSurfaceOzoneSurfacelessSurfaceImpl::GetBackingFrameBufferObject() {
|
| + return fbo_;
|
| +}
|
| +
|
| +bool GLSurfaceOzoneSurfacelessSurfaceImpl::OnMakeCurrent(GLContext* context) {
|
| + if (!fbo_) {
|
| + glGenFramebuffersEXT(1, &fbo_);
|
| + if (!fbo_)
|
| + return false;
|
| + glGenTextures(arraysize(textures_), textures_);
|
| + if (!CreatePixmaps())
|
| + return false;
|
| + }
|
| + BindFramebuffer();
|
| + glBindFramebufferEXT(GL_FRAMEBUFFER, fbo_);
|
| + return SurfacelessEGL::OnMakeCurrent(context);
|
| +}
|
| +
|
| +bool GLSurfaceOzoneSurfacelessSurfaceImpl::Resize(const gfx::Size& size) {
|
| + if (size == GetSize())
|
| + return true;
|
| + return GLSurfaceOzoneSurfaceless::Resize(size) && CreatePixmaps();
|
| +}
|
| +
|
| +bool GLSurfaceOzoneSurfacelessSurfaceImpl::SupportsPostSubBuffer() {
|
| + return false;
|
| +}
|
| +
|
| +gfx::SwapResult GLSurfaceOzoneSurfacelessSurfaceImpl::SwapBuffers() {
|
| + if (!images_[current_surface_]->ScheduleOverlayPlane(
|
| + widget_, 0, OverlayTransform::OVERLAY_TRANSFORM_NONE,
|
| + gfx::Rect(GetSize()), gfx::RectF(1, 1)))
|
| + return gfx::SwapResult::SWAP_FAILED;
|
| + gfx::SwapResult result = GLSurfaceOzoneSurfaceless::SwapBuffers();
|
| + if (result != gfx::SwapResult::SWAP_ACK)
|
| + return result;
|
| + current_surface_ ^= 1;
|
| + BindFramebuffer();
|
| + return gfx::SwapResult::SWAP_ACK;
|
| +}
|
| +
|
| +bool GLSurfaceOzoneSurfacelessSurfaceImpl::SwapBuffersAsync(
|
| + const SwapCompletionCallback& callback) {
|
| + if (!images_[current_surface_]->ScheduleOverlayPlane(
|
| + widget_, 0, OverlayTransform::OVERLAY_TRANSFORM_NONE,
|
| + gfx::Rect(GetSize()), gfx::RectF(1, 1)))
|
| + return false;
|
| + if (!GLSurfaceOzoneSurfaceless::SwapBuffersAsync(callback))
|
| + return false;
|
| + current_surface_ ^= 1;
|
| + BindFramebuffer();
|
| + return true;
|
| +}
|
| +
|
| +void GLSurfaceOzoneSurfacelessSurfaceImpl::Destroy() {
|
| + GLContext* current_context = GLContext::GetCurrent();
|
| + DCHECK(current_context && current_context->IsCurrent(this));
|
| + glBindFramebufferEXT(GL_FRAMEBUFFER, 0);
|
| + if (fbo_) {
|
| + glDeleteTextures(arraysize(textures_), textures_);
|
| + for (auto& texture : textures_)
|
| + texture = 0;
|
| + glDeleteFramebuffersEXT(1, &fbo_);
|
| + fbo_ = 0;
|
| + }
|
| + for (auto image : images_) {
|
| + if (image)
|
| + image->Destroy(true);
|
| + }
|
| +}
|
| +
|
| +GLSurfaceOzoneSurfacelessSurfaceImpl::~GLSurfaceOzoneSurfacelessSurfaceImpl() {
|
| + DCHECK(!fbo_);
|
| + for (size_t i = 0; i < arraysize(textures_); i++)
|
| + DCHECK(!textures_[i]) << "texture " << i << " not released";
|
| +}
|
| +
|
| +void GLSurfaceOzoneSurfacelessSurfaceImpl::BindFramebuffer() {
|
| + ScopedFrameBufferBinder fb(fbo_);
|
| + glFramebufferTexture2DEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
|
| + textures_[current_surface_], 0);
|
| +}
|
| +
|
| +bool GLSurfaceOzoneSurfacelessSurfaceImpl::CreatePixmaps() {
|
| + if (!fbo_)
|
| + return true;
|
| + for (size_t i = 0; i < arraysize(textures_); i++) {
|
| + scoped_refptr<ui::NativePixmap> pixmap =
|
| + ui::OzonePlatform::GetInstance()
|
| + ->GetSurfaceFactoryOzone()
|
| + ->CreateNativePixmap(widget_, GetSize(),
|
| + ui::SurfaceFactoryOzone::BGRA_8888,
|
| + ui::SurfaceFactoryOzone::SCANOUT);
|
| + if (!pixmap)
|
| + return false;
|
| + scoped_refptr<SurfaceImage> image =
|
| + new SurfaceImage(GetSize(), GL_BGRA_EXT);
|
| + if (!image->Initialize(pixmap, gfx::GpuMemoryBuffer::Format::BGRA_8888))
|
| + return false;
|
| + images_[i] = image;
|
| + // Bind image to texture.
|
| + ScopedTextureBinder binder(GL_TEXTURE_2D, textures_[i]);
|
| + if (!images_[i]->BindTexImage(GL_TEXTURE_2D))
|
| + return false;
|
| + }
|
| + return true;
|
| +}
|
| +
|
| } // namespace
|
|
|
| // static
|
| @@ -412,18 +637,24 @@ bool GLSurface::InitializeOneOffInternal() {
|
|
|
| // static
|
| scoped_refptr<GLSurface> GLSurface::CreateSurfacelessViewGLSurface(
|
| - gfx::AcceleratedWidget window) {
|
| + gfx::AcceleratedWidget window,
|
| + const gfx::SurfaceConfiguration& requested_configuration) {
|
| if (GetGLImplementation() == kGLImplementationEGLGLES2 &&
|
| window != kNullAcceleratedWidget &&
|
| GLSurfaceEGL::IsEGLSurfacelessContextSupported() &&
|
| - ui::SurfaceFactoryOzone::GetInstance()->CanShowPrimaryPlaneAsOverlay()) {
|
| + ui::OzonePlatform::GetInstance()
|
| + ->GetSurfaceFactoryOzone()
|
| + ->CanShowPrimaryPlaneAsOverlay()) {
|
| scoped_ptr<ui::SurfaceOzoneEGL> surface_ozone =
|
| - ui::SurfaceFactoryOzone::GetInstance()
|
| + ui::OzonePlatform::GetInstance()
|
| + ->GetSurfaceFactoryOzone()
|
| ->CreateSurfacelessEGLSurfaceForWidget(window);
|
| if (!surface_ozone)
|
| return nullptr;
|
| scoped_refptr<GLSurface> surface;
|
| - surface = new GLSurfaceOzoneSurfaceless(surface_ozone.Pass(), window);
|
| + surface = new GLSurfaceOzoneSurfaceless(surface_ozone.Pass(),
|
| + window,
|
| + requested_configuration);
|
| if (surface->Initialize())
|
| return surface;
|
| }
|
| @@ -433,9 +664,11 @@ scoped_refptr<GLSurface> GLSurface::CreateSurfacelessViewGLSurface(
|
|
|
| // static
|
| scoped_refptr<GLSurface> GLSurface::CreateViewGLSurface(
|
| - gfx::AcceleratedWidget window) {
|
| + gfx::AcceleratedWidget window,
|
| + const gfx::SurfaceConfiguration& requested_configuration) {
|
| if (GetGLImplementation() == kGLImplementationOSMesaGL) {
|
| - scoped_refptr<GLSurface> surface(new GLSurfaceOSMesaHeadless());
|
| + scoped_refptr<GLSurface> surface(
|
| + new GLSurfaceOSMesaHeadless(requested_configuration));
|
| if (!surface->Initialize())
|
| return NULL;
|
| return surface;
|
| @@ -444,29 +677,34 @@ scoped_refptr<GLSurface> GLSurface::CreateViewGLSurface(
|
| if (window != kNullAcceleratedWidget) {
|
| scoped_refptr<GLSurface> surface;
|
| if (GLSurfaceEGL::IsEGLSurfacelessContextSupported() &&
|
| - ui::SurfaceFactoryOzone::GetInstance()
|
| + ui::OzonePlatform::GetInstance()
|
| + ->GetSurfaceFactoryOzone()
|
| ->CanShowPrimaryPlaneAsOverlay()) {
|
| scoped_ptr<ui::SurfaceOzoneEGL> surface_ozone =
|
| - ui::SurfaceFactoryOzone::GetInstance()
|
| + ui::OzonePlatform::GetInstance()
|
| + ->GetSurfaceFactoryOzone()
|
| ->CreateSurfacelessEGLSurfaceForWidget(window);
|
| if (!surface_ozone)
|
| return NULL;
|
| - surface = new GLSurfaceOzoneSurfacelessSurfaceImpl(surface_ozone.Pass(),
|
| - window);
|
| + surface = new GLSurfaceOzoneSurfacelessSurfaceImpl(
|
| + surface_ozone.Pass(), window, requested_configuration);
|
| } else {
|
| scoped_ptr<ui::SurfaceOzoneEGL> surface_ozone =
|
| - ui::SurfaceFactoryOzone::GetInstance()->CreateEGLSurfaceForWidget(
|
| - window);
|
| + ui::OzonePlatform::GetInstance()
|
| + ->GetSurfaceFactoryOzone()
|
| + ->CreateEGLSurfaceForWidget(window);
|
| if (!surface_ozone)
|
| return NULL;
|
|
|
| - surface = new GLSurfaceOzoneEGL(surface_ozone.Pass(), window);
|
| + surface = new GLSurfaceOzoneEGL(
|
| + surface_ozone.Pass(), window, requested_configuration);
|
| }
|
| if (!surface->Initialize())
|
| return NULL;
|
| return surface;
|
| } else {
|
| - scoped_refptr<GLSurface> surface = new GLSurfaceStub();
|
| + scoped_refptr<GLSurface> surface = new GLSurfaceStub(
|
| + requested_configuration);
|
| if (surface->Initialize())
|
| return surface;
|
| }
|
| @@ -475,11 +713,12 @@ scoped_refptr<GLSurface> GLSurface::CreateViewGLSurface(
|
|
|
| // static
|
| scoped_refptr<GLSurface> GLSurface::CreateOffscreenGLSurface(
|
| - const gfx::Size& size) {
|
| + const gfx::Size& size,
|
| + const gfx::SurfaceConfiguration& requested_configuration) {
|
| switch (GetGLImplementation()) {
|
| case kGLImplementationOSMesaGL: {
|
| - scoped_refptr<GLSurface> surface(
|
| - new GLSurfaceOSMesa(OSMesaSurfaceFormatBGRA, size));
|
| + scoped_refptr<GLSurface> surface(new GLSurfaceOSMesa(
|
| + OSMesaSurfaceFormatBGRA, size, requested_configuration));
|
| if (!surface->Initialize())
|
| return NULL;
|
|
|
| @@ -489,14 +728,16 @@ scoped_refptr<GLSurface> GLSurface::CreateOffscreenGLSurface(
|
| scoped_refptr<GLSurface> surface;
|
| if (GLSurfaceEGL::IsEGLSurfacelessContextSupported() &&
|
| (size.width() == 0 && size.height() == 0)) {
|
| - surface = new SurfacelessEGL(size);
|
| + surface = new SurfacelessEGL(size, requested_configuration);
|
| } else
|
| - surface = new PbufferGLSurfaceEGL(size);
|
| + surface = new PbufferGLSurfaceEGL(size, requested_configuration);
|
|
|
| if (!surface->Initialize())
|
| return NULL;
|
| return surface;
|
| }
|
| + case kGLImplementationMockGL:
|
| + return new GLSurfaceStub(requested_configuration);
|
| default:
|
| NOTREACHED();
|
| return NULL;
|
| @@ -504,7 +745,9 @@ scoped_refptr<GLSurface> GLSurface::CreateOffscreenGLSurface(
|
| }
|
|
|
| EGLNativeDisplayType GetPlatformDefaultEGLNativeDisplay() {
|
| - return ui::SurfaceFactoryOzone::GetInstance()->GetNativeDisplay();
|
| + return ui::OzonePlatform::GetInstance()
|
| + ->GetSurfaceFactoryOzone()
|
| + ->GetNativeDisplay();
|
| }
|
|
|
| } // namespace gfx
|
|
|