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 |