summaryrefslogtreecommitdiffstats
path: root/cc
diff options
context:
space:
mode:
authorreveman@chromium.org <reveman@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-04-23 14:05:43 +0000
committerreveman@chromium.org <reveman@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-04-23 14:05:43 +0000
commit9b9ed013945b7f2cdefc595a4c0384ada51f8d56 (patch)
tree1f3b07927ffaeca0ed27918bd43cd6e1456178af /cc
parentb2e755dfdd4c8bfa172fb9f6653ab459a6644ef8 (diff)
downloadchromium_src-9b9ed013945b7f2cdefc595a4c0384ada51f8d56.zip
chromium_src-9b9ed013945b7f2cdefc595a4c0384ada51f8d56.tar.gz
chromium_src-9b9ed013945b7f2cdefc595a4c0384ada51f8d56.tar.bz2
cc: Use CHROMIUM_sync_query in GLRenderer when available.
Use COMMANDS_COMPLETED queries instead of making assumptions about the pipeline depth to determine when resources can be reused. BUG=273274 Review URL: https://codereview.chromium.org/242513011 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@265635 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'cc')
-rw-r--r--cc/output/gl_renderer.cc123
-rw-r--r--cc/output/gl_renderer.h7
-rw-r--r--cc/resources/resource_provider.h5
3 files changed, 109 insertions, 26 deletions
diff --git a/cc/output/gl_renderer.cc b/cc/output/gl_renderer.cc
index 9ce3731..8719574 100644
--- a/cc/output/gl_renderer.cc
+++ b/cc/output/gl_renderer.cc
@@ -58,25 +58,34 @@
using gpu::gles2::GLES2Interface;
namespace cc {
-
namespace {
-// TODO(epenner): This should probably be moved to output surface.
-//
-// This implements a simple fence based on client side swaps.
-// This is to isolate the ResourceProvider from 'frames' which
-// it shouldn't need to care about, while still allowing us to
-// enforce good texture recycling behavior strictly throughout
-// the compositor (don't recycle a texture while it's in use).
-class SimpleSwapFence : public ResourceProvider::Fence {
+class FallbackFence : public ResourceProvider::Fence {
public:
- SimpleSwapFence() : has_passed_(false) {}
- virtual bool HasPassed() OVERRIDE { return has_passed_; }
- void SetHasPassed() { has_passed_ = true; }
+ explicit FallbackFence(gpu::gles2::GLES2Interface* gl)
+ : gl_(gl), has_passed_(false) {}
+
+ // Overridden from ResourceProvider::Fence:
+ virtual bool HasPassed() OVERRIDE {
+ if (!has_passed_) {
+ has_passed_ = true;
+ Synchronize();
+ }
+ return true;
+ }
private:
- virtual ~SimpleSwapFence() {}
+ virtual ~FallbackFence() {}
+
+ void Synchronize() {
+ TRACE_EVENT0("cc", "FallbackFence::Synchronize");
+ gl_->Finish();
+ }
+
+ gpu::gles2::GLES2Interface* gl_;
bool has_passed_;
+
+ DISALLOW_COPY_AND_ASSIGN(FallbackFence);
};
class OnDemandRasterTaskImpl : public Task {
@@ -179,6 +188,58 @@ struct GLRenderer::PendingAsyncReadPixels {
DISALLOW_COPY_AND_ASSIGN(PendingAsyncReadPixels);
};
+class GLRenderer::SyncQuery {
+ public:
+ explicit SyncQuery(gpu::gles2::GLES2Interface* gl)
+ : gl_(gl), query_id_(0u), weak_ptr_factory_(this) {
+ gl_->GenQueriesEXT(1, &query_id_);
+ }
+ virtual ~SyncQuery() { gl_->DeleteQueriesEXT(1, &query_id_); }
+
+ scoped_refptr<ResourceProvider::Fence> Begin() {
+ DCHECK(!weak_ptr_factory_.HasWeakPtrs() || !IsPending());
+ // Invalidate weak pointer held by old fence.
+ weak_ptr_factory_.InvalidateWeakPtrs();
+ gl_->BeginQueryEXT(GL_COMMANDS_COMPLETED_CHROMIUM, query_id_);
+ return make_scoped_refptr<ResourceProvider::Fence>(
+ new Fence(weak_ptr_factory_.GetWeakPtr()));
+ }
+
+ void End() { gl_->EndQueryEXT(GL_COMMANDS_COMPLETED_CHROMIUM); }
+
+ bool IsPending() {
+ unsigned available = 1;
+ gl_->GetQueryObjectuivEXT(
+ query_id_, GL_QUERY_RESULT_AVAILABLE_EXT, &available);
+ return !available;
+ }
+
+ private:
+ class Fence : public ResourceProvider::Fence {
+ public:
+ explicit Fence(base::WeakPtr<GLRenderer::SyncQuery> query)
+ : query_(query) {}
+
+ // Overridden from ResourceProvider::Fence:
+ virtual bool HasPassed() OVERRIDE {
+ return !query_ || !query_->IsPending();
+ }
+
+ private:
+ virtual ~Fence() {}
+
+ base::WeakPtr<SyncQuery> query_;
+
+ DISALLOW_COPY_AND_ASSIGN(Fence);
+ };
+
+ gpu::gles2::GLES2Interface* gl_;
+ unsigned query_id_;
+ base::WeakPtrFactory<SyncQuery> weak_ptr_factory_;
+
+ DISALLOW_COPY_AND_ASSIGN(SyncQuery);
+};
+
scoped_ptr<GLRenderer> GLRenderer::Create(
RendererClient* client,
const LayerTreeSettings* settings,
@@ -214,6 +275,7 @@ GLRenderer::GLRenderer(RendererClient* client,
blend_shadow_(false),
highp_threshold_min_(highp_threshold_min),
highp_threshold_cache_(0),
+ use_sync_query_(false),
on_demand_tile_raster_resource_id_(0) {
DCHECK(gl_);
DCHECK(context_support_);
@@ -248,6 +310,8 @@ GLRenderer::GLRenderer(RendererClient* client,
capabilities_.allow_rasterize_on_demand = true;
+ use_sync_query_ = context_caps.gpu.sync_query;
+
InitializeSharedObjects();
}
@@ -349,6 +413,25 @@ void GLRenderer::BeginDrawingFrame(DrawingFrame* frame) {
TRACE_EVENT0("cc", "GLRenderer::BeginDrawingFrame");
+ scoped_refptr<ResourceProvider::Fence> read_lock_fence;
+ if (use_sync_query_) {
+ while (!pending_sync_queries_.empty()) {
+ if (pending_sync_queries_.front()->IsPending())
+ break;
+
+ available_sync_queries_.push_back(pending_sync_queries_.take_front());
+ }
+
+ current_sync_query_ = available_sync_queries_.empty()
+ ? make_scoped_ptr(new SyncQuery(gl_))
+ : available_sync_queries_.take_front();
+
+ read_lock_fence = current_sync_query_->Begin();
+ } else {
+ read_lock_fence = make_scoped_refptr(new FallbackFence(gl_));
+ }
+ resource_provider_->SetReadLockFence(read_lock_fence.get());
+
// TODO(enne): Do we need to reinitialize all of this state per frame?
ReinitializeGLState();
}
@@ -1997,6 +2080,12 @@ void GLRenderer::DrawIOSurfaceQuad(const DrawingFrame* frame,
}
void GLRenderer::FinishDrawingFrame(DrawingFrame* frame) {
+ if (use_sync_query_) {
+ DCHECK(current_sync_query_);
+ current_sync_query_->End();
+ pending_sync_queries_.push_back(current_sync_query_.Pass());
+ }
+
current_framebuffer_lock_.reset();
swap_buffer_rect_.Union(gfx::ToEnclosingRect(frame->root_damage_rect));
@@ -2181,14 +2270,6 @@ void GLRenderer::SwapBuffers(const CompositorFrameMetadata& metadata) {
in_use_overlay_resources_.swap(pending_overlay_resources_);
swap_buffer_rect_ = gfx::Rect();
-
- // We don't have real fences, so we mark read fences as passed
- // assuming a double-buffered GPU pipeline. A texture can be
- // written to after one full frame has past since it was last read.
- if (last_swap_fence_.get())
- static_cast<SimpleSwapFence*>(last_swap_fence_.get())->SetHasPassed();
- last_swap_fence_ = resource_provider_->GetReadLockFence();
- resource_provider_->SetReadLockFence(new SimpleSwapFence());
}
void GLRenderer::EnforceMemoryPolicy() {
diff --git a/cc/output/gl_renderer.h b/cc/output/gl_renderer.h
index 13a9060..e776082 100644
--- a/cc/output/gl_renderer.h
+++ b/cc/output/gl_renderer.h
@@ -7,6 +7,7 @@
#include "base/cancelable_callback.h"
#include "cc/base/cc_export.h"
+#include "cc/base/scoped_ptr_deque.h"
#include "cc/base/scoped_ptr_vector.h"
#include "cc/output/direct_renderer.h"
#include "cc/output/gl_renderer_draw_cache.h"
@@ -431,7 +432,11 @@ class CC_EXPORT GLRenderer : public DirectRenderer {
scoped_ptr<ResourceProvider::ScopedWriteLockGL> current_framebuffer_lock_;
- scoped_refptr<ResourceProvider::Fence> last_swap_fence_;
+ class SyncQuery;
+ ScopedPtrDeque<SyncQuery> pending_sync_queries_;
+ ScopedPtrDeque<SyncQuery> available_sync_queries_;
+ scoped_ptr<SyncQuery> current_sync_query_;
+ bool use_sync_query_;
SkBitmap on_demand_tile_raster_bitmap_;
ResourceProvider::ResourceId on_demand_tile_raster_resource_id_;
diff --git a/cc/resources/resource_provider.h b/cc/resources/resource_provider.h
index 6136015..312dd7c 100644
--- a/cc/resources/resource_provider.h
+++ b/cc/resources/resource_provider.h
@@ -360,10 +360,7 @@ class CC_EXPORT ResourceProvider {
// Sets the current read fence. If a resource is locked for read
// and has read fences enabled, the resource will not allow writes
// until this fence has passed.
- void SetReadLockFence(scoped_refptr<Fence> fence) {
- current_read_lock_fence_ = fence;
- }
- Fence* GetReadLockFence() { return current_read_lock_fence_.get(); }
+ void SetReadLockFence(Fence* fence) { current_read_lock_fence_ = fence; }
// Enable read lock fences for a specific resource.
void EnableReadLockFences(ResourceProvider::ResourceId id, bool enable);