| Index: ui/gl/gl_surface_ozone.cc
|
| diff --git a/ui/gl/gl_surface_ozone.cc b/ui/gl/gl_surface_ozone.cc
|
| index 47ea8d6dd9b6c1e63b22febcfc364cd6b5d71039..800be1759fe96331573944463123e00ce19968f2 100644
|
| --- a/ui/gl/gl_surface_ozone.cc
|
| +++ b/ui/gl/gl_surface_ozone.cc
|
| @@ -5,8 +5,12 @@
|
| #include "ui/gl/gl_surface.h"
|
|
|
| #include "base/bind.h"
|
| +#include "base/callback.h"
|
| +#include "base/location.h"
|
| #include "base/logging.h"
|
| #include "base/memory/ref_counted.h"
|
| +#include "base/memory/weak_ptr.h"
|
| +#include "base/threading/worker_pool.h"
|
| #include "ui/gfx/native_widget_types.h"
|
| #include "ui/gl/gl_context.h"
|
| #include "ui/gl/gl_image.h"
|
| @@ -25,6 +29,11 @@ namespace gfx {
|
|
|
| namespace {
|
|
|
| +void WaitForFence(EGLDisplay display, EGLSyncKHR fence) {
|
| + eglClientWaitSyncKHR(display, fence, EGL_SYNC_FLUSH_COMMANDS_BIT_KHR,
|
| + EGL_FOREVER_KHR);
|
| +}
|
| +
|
| // A thin wrapper around GLSurfaceEGL that owns the EGLNativeWindow
|
| class GL_EXPORT GLSurfaceOzoneEGL : public NativeViewGLSurfaceEGL {
|
| public:
|
| @@ -111,7 +120,9 @@ class GL_EXPORT GLSurfaceOzoneSurfaceless : public SurfacelessEGL {
|
| ozone_surface_(ozone_surface.Pass()),
|
| widget_(widget),
|
| has_implicit_external_sync_(
|
| - HasEGLExtension("EGL_ARM_implicit_external_sync")) {}
|
| + HasEGLExtension("EGL_ARM_implicit_external_sync")),
|
| + last_swap_buffers_result_(true),
|
| + weak_factory_(this) {}
|
|
|
| bool Initialize() override {
|
| if (!SurfacelessEGL::Initialize())
|
| @@ -128,8 +139,21 @@ class GL_EXPORT GLSurfaceOzoneSurfaceless : public SurfacelessEGL {
|
| return SurfacelessEGL::Resize(size);
|
| }
|
| bool SwapBuffers() override {
|
| - if (!Flush())
|
| - return false;
|
| + 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();
|
| + }
|
| +
|
| return ozone_surface_->OnSwapBuffers();
|
| }
|
| bool ScheduleOverlayPlane(int z_order,
|
| @@ -149,8 +173,33 @@ class GL_EXPORT GLSurfaceOzoneSurfaceless : public SurfacelessEGL {
|
| return true;
|
| }
|
| bool SwapBuffersAsync(const SwapCompletionCallback& callback) override {
|
| - if (!Flush())
|
| - return false;
|
| + 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);
|
| }
|
| bool PostSubBufferAsync(int x,
|
| @@ -166,30 +215,16 @@ class GL_EXPORT GLSurfaceOzoneSurfaceless : public SurfacelessEGL {
|
| Destroy(); // EGL surface must be destroyed before SurfaceOzone
|
| }
|
|
|
| - bool Flush() {
|
| - glFlush();
|
| - // TODO: crbug.com/462360 the following should be replaced by a per surface
|
| - // flush as it gets implemented in GL drivers.
|
| - if (has_implicit_external_sync_) {
|
| - const EGLint attrib_list[] = {
|
| - EGL_SYNC_CONDITION_KHR,
|
| - EGL_SYNC_PRIOR_COMMANDS_IMPLICIT_EXTERNAL_ARM,
|
| - EGL_NONE};
|
| - EGLSyncKHR fence =
|
| - eglCreateSyncKHR(GetDisplay(), EGL_SYNC_FENCE_KHR, attrib_list);
|
| - if (fence) {
|
| - // TODO(dbehr): piman@ suggests we could improve here by moving
|
| - // following wait to right before drmModePageFlip crbug.com/456417.
|
| - eglClientWaitSyncKHR(GetDisplay(), fence,
|
| - EGL_SYNC_FLUSH_COMMANDS_BIT_KHR, EGL_FOREVER_KHR);
|
| - eglDestroySyncKHR(GetDisplay(), fence);
|
| - } else {
|
| - return false;
|
| - }
|
| - } else if (ozone_surface_->IsUniversalDisplayLinkDevice()) {
|
| - glFinish();
|
| - }
|
| - return true;
|
| + 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);
|
| + }
|
| +
|
| + void FenceRetired(EGLSyncKHR fence, const SwapCompletionCallback& callback) {
|
| + eglDestroySyncKHR(GetDisplay(), fence);
|
| + last_swap_buffers_result_ = ozone_surface_->OnSwapBuffersAsync(callback);
|
| }
|
|
|
| // The native surface. Deleting this is allowed to free the EGLNativeWindow.
|
| @@ -197,6 +232,10 @@ class GL_EXPORT GLSurfaceOzoneSurfaceless : public SurfacelessEGL {
|
| AcceleratedWidget widget_;
|
| scoped_ptr<VSyncProvider> vsync_provider_;
|
| bool has_implicit_external_sync_;
|
| + bool last_swap_buffers_result_;
|
| +
|
| + base::WeakPtrFactory<GLSurfaceOzoneSurfaceless> weak_factory_;
|
| +
|
| DISALLOW_COPY_AND_ASSIGN(GLSurfaceOzoneSurfaceless);
|
| };
|
|
|
|
|