summaryrefslogtreecommitdiffstats
path: root/ui
diff options
context:
space:
mode:
authorachaulk <achaulk@chromium.org>2015-04-07 09:22:34 -0700
committerCommit bot <commit-bot@chromium.org>2015-04-07 16:22:59 +0000
commit77f08ab335da814a065dce6859a674b29e9c1294 (patch)
tree7c15af28519a0e14ec595f622f9344a7b250bc2c /ui
parent65212281c5bd5c8f85304232e3f66b8ff876082c (diff)
downloadchromium_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.cc74
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_;