diff options
author | achaulk <achaulk@chromium.org> | 2015-04-07 09:22:34 -0700 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2015-04-07 16:22:59 +0000 |
commit | 77f08ab335da814a065dce6859a674b29e9c1294 (patch) | |
tree | 7c15af28519a0e14ec595f622f9344a7b250bc2c /ui | |
parent | 65212281c5bd5c8f85304232e3f66b8ff876082c (diff) | |
download | chromium_src-77f08ab335da814a065dce6859a674b29e9c1294.zip chromium_src-77f08ab335da814a065dce6859a674b29e9c1294.tar.gz chromium_src-77f08ab335da814a065dce6859a674b29e9c1294.tar.bz2 |
Change ozone async swap to fix overlay scheduling
We keep a list of all pending frames insize the GLSurface. Each frame contains
a list of overlays. In the future it can contain overlay sync point info too.
When ready, we set the ready state and submit all completed frames in order
BUG=470185
TEST=link and rockchip
Review URL: https://codereview.chromium.org/1054073002
Cr-Commit-Position: refs/heads/master@{#324053}
Diffstat (limited to 'ui')
-rw-r--r-- | ui/gl/gl_surface_ozone.cc | 74 |
1 files changed, 68 insertions, 6 deletions
diff --git a/ui/gl/gl_surface_ozone.cc b/ui/gl/gl_surface_ozone.cc index 800be17..ba7b02b 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" @@ -122,7 +123,9 @@ class GL_EXPORT GLSurfaceOzoneSurfaceless : public SurfacelessEGL { has_implicit_external_sync_( HasEGLExtension("EGL_ARM_implicit_external_sync")), last_swap_buffers_result_(true), - weak_factory_(this) {} + weak_factory_(this) { + unsubmitted_frames_.push_back(new PendingFrame()); + } bool Initialize() override { if (!SurfacelessEGL::Initialize()) @@ -154,6 +157,9 @@ class GL_EXPORT GLSurfaceOzoneSurfaceless : public SurfacelessEGL { glFinish(); } + unsubmitted_frames_.back()->ScheduleOverlayPlanes(widget_); + unsubmitted_frames_.back()->overlays.clear(); + return ozone_surface_->OnSwapBuffers(); } bool ScheduleOverlayPlane(int z_order, @@ -161,8 +167,9 @@ class GL_EXPORT GLSurfaceOzoneSurfaceless : public SurfacelessEGL { GLImage* image, const Rect& bounds_rect, const RectF& crop_rect) override { - return image->ScheduleOverlayPlane( - widget_, z_order, transform, bounds_rect, crop_rect); + unsubmitted_frames_.back()->overlays.push_back(PendingFrame::Overlay( + z_order, transform, image, bounds_rect, crop_rect)); + return true; } bool IsOffscreen() override { return false; } VSyncProvider* GetVSyncProvider() override { return vsync_provider_.get(); } @@ -190,16 +197,21 @@ class GL_EXPORT GLSurfaceOzoneSurfaceless : public SurfacelessEGL { base::Closure fence_wait_task = base::Bind(&WaitForFence, GetDisplay(), fence); + PendingFrame* frame = unsubmitted_frames_.back(); + frame->callback = callback; base::Closure fence_retired_callback = base::Bind(&GLSurfaceOzoneSurfaceless::FenceRetired, - weak_factory_.GetWeakPtr(), fence, callback); + weak_factory_.GetWeakPtr(), fence, frame); base::WorkerPool::PostTaskAndReply(FROM_HERE, fence_wait_task, fence_retired_callback, false); + unsubmitted_frames_.push_back(new PendingFrame()); return true; } else if (ozone_surface_->IsUniversalDisplayLinkDevice()) { glFinish(); } + unsubmitted_frames_.back()->ScheduleOverlayPlanes(widget_); + unsubmitted_frames_.back()->overlays.clear(); return ozone_surface_->OnSwapBuffersAsync(callback); } bool PostSubBufferAsync(int x, @@ -211,10 +223,58 @@ class GL_EXPORT GLSurfaceOzoneSurfaceless : public SurfacelessEGL { } protected: + struct PendingFrame { + struct 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) {} + + bool ScheduleOverlayPlane(gfx::AcceleratedWidget widget) const { + return image->ScheduleOverlayPlane(widget, z_order, transform, + bounds_rect, crop_rect); + } + + int z_order; + OverlayTransform transform; + scoped_refptr<GLImage> image; + Rect bounds_rect; + RectF crop_rect; + }; + + PendingFrame() : ready(false) {} + + bool ScheduleOverlayPlanes(gfx::AcceleratedWidget widget) { + for (const auto& overlay : overlays) + if (!overlay.ScheduleOverlayPlane(widget)) + return false; + return true; + } + bool ready; + std::vector<Overlay> overlays; + SwapCompletionCallback callback; + }; + ~GLSurfaceOzoneSurfaceless() override { Destroy(); // EGL surface must be destroyed before SurfaceOzone } + void SubmitFrames() { + while (!unsubmitted_frames_.empty() && unsubmitted_frames_.front()->ready) { + PendingFrame* frame = unsubmitted_frames_.front(); + last_swap_buffers_result_ = + last_swap_buffers_result_ && frame->ScheduleOverlayPlanes(widget_) && + ozone_surface_->OnSwapBuffersAsync(frame->callback); + unsubmitted_frames_.erase(unsubmitted_frames_.begin()); + } + } + EGLSyncKHR InsertFence() { const EGLint attrib_list[] = {EGL_SYNC_CONDITION_KHR, EGL_SYNC_PRIOR_COMMANDS_IMPLICIT_EXTERNAL_ARM, @@ -222,15 +282,17 @@ class GL_EXPORT GLSurfaceOzoneSurfaceless : public SurfacelessEGL { return eglCreateSyncKHR(GetDisplay(), EGL_SYNC_FENCE_KHR, attrib_list); } - void FenceRetired(EGLSyncKHR fence, const SwapCompletionCallback& callback) { + void FenceRetired(EGLSyncKHR fence, PendingFrame* frame) { eglDestroySyncKHR(GetDisplay(), fence); - last_swap_buffers_result_ = ozone_surface_->OnSwapBuffersAsync(callback); + frame->ready = true; + SubmitFrames(); } // 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_; |