| 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..ba7b02b036814056100705915fcd4bd4033603a5 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_;
|
|
|
|
|