diff options
author | kalyan.kondapally <kalyan.kondapally@intel.com> | 2014-12-23 18:02:02 -0800 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2014-12-24 02:02:54 +0000 |
commit | ae4355c2148da9d549134da9d81d68fd1892724e (patch) | |
tree | 7f5364c9e1fb20462c73d5443b4ce8eb77932165 | |
parent | 529e7f1c22bbb63fa91160b8d4fc5701c2a6415c (diff) | |
download | chromium_src-ae4355c2148da9d549134da9d81d68fd1892724e.zip chromium_src-ae4355c2148da9d549134da9d81d68fd1892724e.tar.gz chromium_src-ae4355c2148da9d549134da9d81d68fd1892724e.tar.bz2 |
Add support to delay sending SwapbufferAck as needed.
On platforms (i.e. ChromeOS using Ozone) where Chromium is responsible for
displaying the buffers, we want to delay SwapBufferAck till we know that
the buffer is displayed on screen. Currently, we block the GPU main thread till
that data is available. This patch introduces SwapBufferAsync apis, which are
similar to current SwapBuffer calls except that it adds a callback function
which can be used to delay sending SwapBufferAck as needed.
BUG=443543,chrome-os-partner:34292
Review URL: https://codereview.chromium.org/797843005
Cr-Commit-Position: refs/heads/master@{#309602}
-rw-r--r-- | content/common/gpu/image_transport_surface.cc | 31 | ||||
-rw-r--r-- | content/common/gpu/image_transport_surface.h | 2 | ||||
-rw-r--r-- | ui/gl/gl_surface.cc | 28 | ||||
-rw-r--r-- | ui/gl/gl_surface.h | 26 |
4 files changed, 75 insertions, 12 deletions
diff --git a/content/common/gpu/image_transport_surface.cc b/content/common/gpu/image_transport_surface.cc index f0665f6..bb11dd8 100644 --- a/content/common/gpu/image_transport_surface.cc +++ b/content/common/gpu/image_transport_surface.cc @@ -188,7 +188,8 @@ PassThroughImageTransportSurface::PassThroughImageTransportSurface( GpuCommandBufferStub* stub, gfx::GLSurface* surface) : GLSurfaceAdapter(surface), - did_set_swap_interval_(false) { + did_set_swap_interval_(false), + weak_ptr_factory_(this) { helper_.reset(new ImageTransportHelper(this, manager, stub, @@ -214,21 +215,28 @@ bool PassThroughImageTransportSurface::SwapBuffers() { // GetVsyncValues before SwapBuffers to work around Mali driver bug: // crbug.com/223558. SendVSyncUpdateIfAvailable(); - bool result = gfx::GLSurfaceAdapter::SwapBuffers(); - for (size_t i = 0; i < latency_info_.size(); i++) { - latency_info_[i].AddLatencyNumber( - ui::INPUT_EVENT_LATENCY_TERMINATED_FRAME_SWAP_COMPONENT, 0, 0); - } - - helper_->SwapBuffersCompleted(latency_info_); - latency_info_.clear(); - return result; + // We use WeakPtr here to avoid manual management of life time of an instance + // of this class. Callback will not be called once the instance of this class + // is destroyed. However, this also means that the callback can be run on + // the calling thread only. + return gfx::GLSurfaceAdapter::SwapBuffersAsync( + base::Bind(&PassThroughImageTransportSurface::SwapBuffersCallBack, + weak_ptr_factory_.GetWeakPtr())); } bool PassThroughImageTransportSurface::PostSubBuffer( int x, int y, int width, int height) { SendVSyncUpdateIfAvailable(); - bool result = gfx::GLSurfaceAdapter::PostSubBuffer(x, y, width, height); + // We use WeakPtr here to avoid manual management of life time of an instance + // of this class. Callback will not be called once the instance of this class + // is destroyed. However, this also means that the callback can be run on + // the calling thread only. + return gfx::GLSurfaceAdapter::PostSubBufferAsync(x, y, width, height, + base::Bind(&PassThroughImageTransportSurface::SwapBuffersCallBack, + weak_ptr_factory_.GetWeakPtr())); +} + +void PassThroughImageTransportSurface::SwapBuffersCallBack() { for (size_t i = 0; i < latency_info_.size(); i++) { latency_info_[i].AddLatencyNumber( ui::INPUT_EVENT_LATENCY_TERMINATED_FRAME_SWAP_COMPONENT, 0, 0); @@ -236,7 +244,6 @@ bool PassThroughImageTransportSurface::PostSubBuffer( helper_->SwapBuffersCompleted(latency_info_); latency_info_.clear(); - return result; } bool PassThroughImageTransportSurface::OnMakeCurrent(gfx::GLContext* context) { diff --git a/content/common/gpu/image_transport_surface.h b/content/common/gpu/image_transport_surface.h index 0c34e86..420690e 100644 --- a/content/common/gpu/image_transport_surface.h +++ b/content/common/gpu/image_transport_surface.h @@ -200,6 +200,7 @@ class PassThroughImageTransportSurface // If updated vsync parameters can be determined, send this information to // the browser. virtual void SendVSyncUpdateIfAvailable(); + void SwapBuffersCallBack(); ImageTransportHelper* GetHelper() { return helper_.get(); } @@ -207,6 +208,7 @@ class PassThroughImageTransportSurface scoped_ptr<ImageTransportHelper> helper_; bool did_set_swap_interval_; std::vector<ui::LatencyInfo> latency_info_; + base::WeakPtrFactory<PassThroughImageTransportSurface> weak_ptr_factory_; DISALLOW_COPY_AND_ASSIGN(PassThroughImageTransportSurface); }; diff --git a/ui/gl/gl_surface.cc b/ui/gl/gl_surface.cc index aaf12ac..e1369e5 100644 --- a/ui/gl/gl_surface.cc +++ b/ui/gl/gl_surface.cc @@ -192,10 +192,27 @@ unsigned int GLSurface::GetBackingFrameBufferObject() { return 0; } +bool GLSurface::SwapBuffersAsync(const SwapCompletionCallback& callback) { + DCHECK(!IsSurfaceless()); + bool success = SwapBuffers(); + callback.Run(); + return success; +} + bool GLSurface::PostSubBuffer(int x, int y, int width, int height) { return false; } +bool GLSurface::PostSubBufferAsync(int x, + int y, + int width, + int height, + const SwapCompletionCallback& callback) { + bool success = PostSubBuffer(x, y, width, height); + callback.Run(); + return success; +} + bool GLSurface::OnMakeCurrent(GLContext* context) { return true; } @@ -303,10 +320,21 @@ bool GLSurfaceAdapter::SwapBuffers() { return surface_->SwapBuffers(); } +bool GLSurfaceAdapter::SwapBuffersAsync( + const SwapCompletionCallback& callback) { + return surface_->SwapBuffersAsync(callback); +} + bool GLSurfaceAdapter::PostSubBuffer(int x, int y, int width, int height) { return surface_->PostSubBuffer(x, y, width, height); } +bool GLSurfaceAdapter::PostSubBufferAsync( + int x, int y, int width, int height, + const SwapCompletionCallback& callback) { + return surface_->PostSubBufferAsync(x, y, width, height, callback); +} + bool GLSurfaceAdapter::SupportsPostSubBuffer() { return surface_->SupportsPostSubBuffer(); } diff --git a/ui/gl/gl_surface.h b/ui/gl/gl_surface.h index ec04c96..8993845 100644 --- a/ui/gl/gl_surface.h +++ b/ui/gl/gl_surface.h @@ -7,6 +7,7 @@ #include <string> +#include "base/callback.h" #include "base/memory/ref_counted.h" #include "build/build_config.h" #include "ui/gfx/native_widget_types.h" @@ -72,9 +73,28 @@ class GL_EXPORT GLSurface : public base::RefCounted<GLSurface> { // FBO. Otherwise returns 0. virtual unsigned int GetBackingFrameBufferObject(); + typedef base::Callback<void()> SwapCompletionCallback; + // Swaps front and back buffers. This has no effect for off-screen + // contexts. On some platforms, we want to send SwapBufferAck only after the + // surface is displayed on screen. The callback can be used to delay sending + // SwapBufferAck till that data is available. The callback should be run on + // the calling thread (i.e. same thread SwapBuffersAsync is called) + virtual bool SwapBuffersAsync(const SwapCompletionCallback& callback); + // Copy part of the backbuffer to the frontbuffer. virtual bool PostSubBuffer(int x, int y, int width, int height); + // Copy part of the backbuffer to the frontbuffer. On some platforms, we want + // to send SwapBufferAck only after the surface is displayed on screen. The + // callback can be used to delay sending SwapBufferAck till that data is + // available. The callback should be run on the calling thread (i.e. same + // thread PostSubBufferAsync is called) + virtual bool PostSubBufferAsync(int x, + int y, + int width, + int height, + const SwapCompletionCallback& callback); + // Initialize GL bindings. static bool InitializeOneOff(); @@ -173,7 +193,13 @@ class GL_EXPORT GLSurfaceAdapter : public GLSurface { bool DeferDraws() override; bool IsOffscreen() override; bool SwapBuffers() override; + bool SwapBuffersAsync(const SwapCompletionCallback& callback) override; bool PostSubBuffer(int x, int y, int width, int height) override; + bool PostSubBufferAsync(int x, + int y, + int width, + int height, + const SwapCompletionCallback& callback) override; bool SupportsPostSubBuffer() override; gfx::Size GetSize() override; void* GetHandle() override; |