summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authoralexst@chromium.org <alexst@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-03-28 20:49:07 +0000
committeralexst@chromium.org <alexst@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-03-28 20:49:07 +0000
commit8590da360ec53610e51592836443e86065e9e8aa (patch)
treed1ce10ac87bc47100a6e4dbefc29d18c2d54c14d
parent23dc93ca215537baf312da312ca2a32517e39890 (diff)
downloadchromium_src-8590da360ec53610e51592836443e86065e9e8aa.zip
chromium_src-8590da360ec53610e51592836443e86065e9e8aa.tar.gz
chromium_src-8590da360ec53610e51592836443e86065e9e8aa.tar.bz2
Plumb overlay processing into DirectRenderer.
This change tests for overlays inside DirectRenderer::DrawFrame and if new overlay passes were produced, it skips rendering them and forwards the information to FinishDrawingFrame to allow subclasses like GLRenderer and SoftwareRenderer to schedule overlays in a manner specific to their implementation. GLRenderer schedules overlays via ContextSupport. Adds more tests to ensure overlay quads are not drawn and if no overlays are present, no quads are skipped. BUG= Review URL: https://codereview.chromium.org/208213003 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@260267 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--cc/output/direct_renderer.cc9
-rw-r--r--cc/output/direct_renderer.h4
-rw-r--r--cc/output/gl_renderer.cc35
-rw-r--r--cc/output/gl_renderer.h7
-rw-r--r--cc/output/overlay_candidate.cc26
-rw-r--r--cc/output/overlay_candidate.h18
-rw-r--r--cc/output/overlay_candidate_validator.h2
-rw-r--r--cc/output/overlay_processor.cc9
-rw-r--r--cc/output/overlay_processor.h7
-rw-r--r--cc/output/overlay_strategy_single_on_top.cc30
-rw-r--r--cc/output/overlay_strategy_single_on_top.h4
-rw-r--r--cc/output/overlay_unittest.cc377
-rw-r--r--cc/quads/render_pass.cc19
-rw-r--r--cc/quads/render_pass.h10
-rw-r--r--cc/quads/render_pass_unittest.cc19
-rw-r--r--cc/resources/resource_provider.cc26
-rw-r--r--cc/resources/resource_provider_unittest.cc50
-rw-r--r--cc/surfaces/surface_aggregator.cc6
-rw-r--r--cc/test/test_context_support.cc19
-rw-r--r--cc/test/test_context_support.h15
-rw-r--r--content/common/cc_messages.cc4
-rw-r--r--content/common/cc_messages_unittest.cc9
-rw-r--r--gpu/command_buffer/client/context_support.h9
-rw-r--r--gpu/command_buffer/client/gles2_implementation.cc8
-rw-r--r--gpu/command_buffer/client/gles2_implementation.h5
25 files changed, 604 insertions, 123 deletions
diff --git a/cc/output/direct_renderer.cc b/cc/output/direct_renderer.cc
index 1eb0fbc..0eb2dcb 100644
--- a/cc/output/direct_renderer.cc
+++ b/cc/output/direct_renderer.cc
@@ -133,7 +133,11 @@ DirectRenderer::DirectRenderer(RendererClient* client,
ResourceProvider* resource_provider)
: Renderer(client, settings),
output_surface_(output_surface),
- resource_provider_(resource_provider) {}
+ resource_provider_(resource_provider),
+ overlay_processor_(
+ new OverlayProcessor(output_surface, resource_provider)) {
+ overlay_processor_->Initialize();
+}
DirectRenderer::~DirectRenderer() {}
@@ -218,6 +222,9 @@ void DirectRenderer::DrawFrame(RenderPassList* render_passes_in_draw_order,
frame.disable_picture_quad_image_filtering =
disable_picture_quad_image_filtering;
+ overlay_processor_->ProcessForOverlays(render_passes_in_draw_order,
+ &frame.overlay_list);
+
EnsureBackbuffer();
// Only reshape when we know we are going to draw. Otherwise, the reshape
diff --git a/cc/output/direct_renderer.h b/cc/output/direct_renderer.h
index a08feef..fce36db 100644
--- a/cc/output/direct_renderer.h
+++ b/cc/output/direct_renderer.h
@@ -9,6 +9,7 @@
#include "base/callback.h"
#include "base/containers/scoped_ptr_hash_map.h"
#include "cc/base/cc_export.h"
+#include "cc/output/overlay_processor.h"
#include "cc/output/renderer.h"
#include "cc/resources/resource_provider.h"
#include "cc/resources/scoped_resource.h"
@@ -57,6 +58,8 @@ class CC_EXPORT DirectRenderer : public Renderer {
ContextProvider* offscreen_context_provider;
bool disable_picture_quad_image_filtering;
+
+ OverlayCandidateList overlay_list;
};
void SetEnlargePassTextureAmountForTesting(const gfx::Vector2d& amount);
@@ -123,6 +126,7 @@ class CC_EXPORT DirectRenderer : public Renderer {
base::ScopedPtrHashMap<RenderPass::Id, ScopedResource> render_pass_textures_;
OutputSurface* output_surface_;
ResourceProvider* resource_provider_;
+ scoped_ptr<OverlayProcessor> overlay_processor_;
// For use in coordinate conversion, this stores the output rect, viewport
// rect (= unflipped version of glViewport rect), and the size of target
diff --git a/cc/output/gl_renderer.cc b/cc/output/gl_renderer.cc
index 41beed5..1e16121 100644
--- a/cc/output/gl_renderer.cc
+++ b/cc/output/gl_renderer.cc
@@ -258,6 +258,8 @@ GLRenderer::~GLRenderer() {
pending_async_read_pixels_.pop_back();
}
+ in_use_overlay_resources_.clear();
+
CleanupSharedObjects();
}
@@ -2005,6 +2007,8 @@ void GLRenderer::FinishDrawingFrame(DrawingFrame* frame) {
GLC(gl_, gl_->Disable(GL_BLEND));
blend_shadow_ = false;
+
+ ScheduleOverlays(frame);
}
void GLRenderer::FinishDrawingQuadList() { FlushTextureQuadCache(); }
@@ -2176,6 +2180,11 @@ void GLRenderer::SwapBuffers(const CompositorFrameMetadata& metadata) {
}
output_surface_->SwapBuffers(&compositor_frame);
+ // Release previously used overlay resources and hold onto the pending ones
+ // until the next swap buffers.
+ in_use_overlay_resources_.clear();
+ 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
@@ -3050,4 +3059,30 @@ bool GLRenderer::IsContextLost() {
return output_surface_->context_provider()->IsContextLost();
}
+void GLRenderer::ScheduleOverlays(DrawingFrame* frame) {
+ if (!frame->overlay_list.size())
+ return;
+
+ ResourceProvider::ResourceIdArray resources;
+ OverlayCandidateList& overlays = frame->overlay_list;
+ OverlayCandidateList::iterator it;
+ for (it = overlays.begin(); it != overlays.end(); ++it) {
+ const OverlayCandidate& overlay = *it;
+ // Skip primary plane.
+ if (overlay.plane_z_order == 0)
+ continue;
+
+ pending_overlay_resources_.push_back(
+ make_scoped_ptr(new ResourceProvider::ScopedReadLockGL(
+ resource_provider(), overlay.resource_id)));
+
+ context_support_->ScheduleOverlayPlane(
+ overlay.plane_z_order,
+ overlay.transform,
+ pending_overlay_resources_.back()->texture_id(),
+ overlay.display_rect,
+ overlay.uv_rect);
+ }
+}
+
} // namespace cc
diff --git a/cc/output/gl_renderer.h b/cc/output/gl_renderer.h
index 4dba039..13a9060 100644
--- a/cc/output/gl_renderer.h
+++ b/cc/output/gl_renderer.h
@@ -220,6 +220,13 @@ class CC_EXPORT GLRenderer : public DirectRenderer {
virtual void EnsureBackbuffer() OVERRIDE;
void EnforceMemoryPolicy();
+ void ScheduleOverlays(DrawingFrame* frame);
+
+ typedef ScopedPtrVector<ResourceProvider::ScopedReadLockGL>
+ OverlayResourceLockList;
+ OverlayResourceLockList pending_overlay_resources_;
+ OverlayResourceLockList in_use_overlay_resources_;
+
RendererCapabilitiesImpl capabilities_;
unsigned offscreen_framebuffer_id_;
diff --git a/cc/output/overlay_candidate.cc b/cc/output/overlay_candidate.cc
index dd3ebc2..05a510b 100644
--- a/cc/output/overlay_candidate.cc
+++ b/cc/output/overlay_candidate.cc
@@ -2,7 +2,9 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "cc/output/overlay_candidate_validator.h"
+#include "cc/output/overlay_candidate.h"
+
+#include "ui/gfx/rect_conversions.h"
namespace cc {
@@ -10,8 +12,30 @@ OverlayCandidate::OverlayCandidate()
: transform(NONE),
format(RGBA_8888),
uv_rect(0.f, 0.f, 1.f, 1.f),
+ resource_id(0),
+ plane_z_order(0),
overlay_handled(false) {}
OverlayCandidate::~OverlayCandidate() {}
+// static
+OverlayCandidate::OverlayTransform OverlayCandidate::GetOverlayTransform(
+ const gfx::Transform& quad_transform,
+ bool flipped) {
+ if (!quad_transform.IsIdentityOrTranslation())
+ return INVALID;
+
+ return flipped ? FLIP_VERTICAL : NONE;
+}
+
+// static
+gfx::Rect OverlayCandidate::GetOverlayRect(const gfx::Transform& quad_transform,
+ const gfx::Rect& rect) {
+ DCHECK(quad_transform.IsIdentityOrTranslation());
+
+ gfx::RectF float_rect(rect);
+ quad_transform.TransformRect(&float_rect);
+ return gfx::ToNearestRect(float_rect);
+}
+
} // namespace cc
diff --git a/cc/output/overlay_candidate.h b/cc/output/overlay_candidate.h
index c530136..e6883cc 100644
--- a/cc/output/overlay_candidate.h
+++ b/cc/output/overlay_candidate.h
@@ -11,11 +11,14 @@
#include "cc/base/cc_export.h"
#include "cc/resources/resource_format.h"
#include "ui/gfx/geometry/rect.h"
+#include "ui/gfx/transform.h"
namespace cc {
-struct CC_EXPORT OverlayCandidate {
+class CC_EXPORT OverlayCandidate {
+ public:
enum OverlayTransform {
+ INVALID,
NONE,
FLIP_HORIZONTAL,
FLIP_VERTICAL,
@@ -24,6 +27,12 @@ struct CC_EXPORT OverlayCandidate {
ROTATE_270,
};
+ static OverlayTransform GetOverlayTransform(
+ const gfx::Transform& quad_transform,
+ bool flipped);
+ static gfx::Rect GetOverlayRect(const gfx::Transform& quad_transform,
+ const gfx::Rect& rect);
+
OverlayCandidate();
~OverlayCandidate();
@@ -35,12 +44,19 @@ struct CC_EXPORT OverlayCandidate {
gfx::Rect display_rect;
// Crop within the buffer to be placed inside |display_rect|.
gfx::RectF uv_rect;
+ // Texture resource to present in an overlay.
+ unsigned resource_id;
+ // Stacking order of the overlay plane relative to the main surface,
+ // which is 0. Signed to allow for "underlays".
+ int plane_z_order;
// To be modified by the implementer if this candidate can go into
// an overlay.
bool overlay_handled;
};
+typedef std::vector<OverlayCandidate> OverlayCandidateList;
+
} // namespace cc
#endif // CC_OUTPUT_OVERLAY_CANDIDATE_H_
diff --git a/cc/output/overlay_candidate_validator.h b/cc/output/overlay_candidate_validator.h
index 026f4f3..fb528da 100644
--- a/cc/output/overlay_candidate_validator.h
+++ b/cc/output/overlay_candidate_validator.h
@@ -19,8 +19,6 @@ namespace cc {
// configurations for a particular output device.
class CC_EXPORT OverlayCandidateValidator {
public:
- typedef std::vector<OverlayCandidate> OverlayCandidateList;
-
// A list of possible overlay candidates is presented to this function.
// The expected result is that those candidates that can be in a separate
// plane are marked with |overlay_handled| set to true, otherwise they are
diff --git a/cc/output/overlay_processor.cc b/cc/output/overlay_processor.cc
index afdb966..c13a6cf 100644
--- a/cc/output/overlay_processor.cc
+++ b/cc/output/overlay_processor.cc
@@ -19,7 +19,9 @@ OverlayProcessor::OverlayProcessor(OutputSurface* surface,
void OverlayProcessor::Initialize() {
DCHECK(surface_);
- DCHECK(resource_provider_);
+ if (!resource_provider_)
+ return;
+
OverlayCandidateValidator* candidates =
surface_->overlay_candidate_validator();
if (candidates) {
@@ -31,10 +33,11 @@ void OverlayProcessor::Initialize() {
OverlayProcessor::~OverlayProcessor() {}
void OverlayProcessor::ProcessForOverlays(
- RenderPassList* render_passes_in_draw_order) {
+ RenderPassList* render_passes_in_draw_order,
+ OverlayCandidateList* candidate_list) {
for (StrategyList::iterator it = strategies_.begin(); it != strategies_.end();
++it) {
- if ((*it)->Attempt(render_passes_in_draw_order))
+ if ((*it)->Attempt(render_passes_in_draw_order, candidate_list))
return;
}
}
diff --git a/cc/output/overlay_processor.h b/cc/output/overlay_processor.h
index 41a1f4d..e50972e 100644
--- a/cc/output/overlay_processor.h
+++ b/cc/output/overlay_processor.h
@@ -8,6 +8,7 @@
#include "base/basictypes.h"
#include "base/memory/scoped_ptr.h"
#include "cc/base/cc_export.h"
+#include "cc/output/overlay_candidate.h"
#include "cc/quads/render_pass.h"
namespace cc {
@@ -23,7 +24,8 @@ class CC_EXPORT OverlayProcessor {
// current set of render passes. Returns true if the strategy was successful
// and adds any additional passes necessary to represent overlays to
// |render_passes_in_draw_order|.
- virtual bool Attempt(RenderPassList* render_passes_in_draw_order) = 0;
+ virtual bool Attempt(RenderPassList* render_passes_in_draw_order,
+ OverlayCandidateList* candidates) = 0;
};
typedef ScopedPtrVector<Strategy> StrategyList;
@@ -32,7 +34,8 @@ class CC_EXPORT OverlayProcessor {
// Virtual to allow testing different strategies.
virtual void Initialize();
- void ProcessForOverlays(RenderPassList* render_passes_in_draw_order);
+ void ProcessForOverlays(RenderPassList* render_passes_in_draw_order,
+ OverlayCandidateList* candidate_list);
protected:
StrategyList strategies_;
diff --git a/cc/output/overlay_strategy_single_on_top.cc b/cc/output/overlay_strategy_single_on_top.cc
index 4c20641..d9ac36c 100644
--- a/cc/output/overlay_strategy_single_on_top.cc
+++ b/cc/output/overlay_strategy_single_on_top.cc
@@ -19,7 +19,8 @@ OverlayStrategySingleOnTop::OverlayStrategySingleOnTop(
resource_provider_(resource_provider) {}
bool OverlayStrategySingleOnTop::Attempt(
- RenderPassList* render_passes_in_draw_order) {
+ RenderPassList* render_passes_in_draw_order,
+ OverlayCandidateList* candidate_list) {
// Only attempt to handle very simple case for now.
if (!capability_checker_)
return false;
@@ -37,14 +38,17 @@ bool OverlayStrategySingleOnTop::Attempt(
return false;
// Simple quads only.
- if (!quad.quadTransform().IsIdentityOrTranslation() || quad.needs_blending ||
+ OverlayCandidate::OverlayTransform overlay_transform =
+ OverlayCandidate::GetOverlayTransform(quad.quadTransform(), quad.flipped);
+ if (overlay_transform == OverlayCandidate::INVALID ||
+ !quad.quadTransform().IsIdentityOrTranslation() || quad.needs_blending ||
quad.shared_quad_state->opacity != 1.f ||
quad.shared_quad_state->blend_mode != SkXfermode::kSrcOver_Mode ||
quad.premultiplied_alpha || quad.background_color != SK_ColorTRANSPARENT)
return false;
// Add our primary surface.
- OverlayCandidateValidator::OverlayCandidateList candidates;
+ OverlayCandidateList candidates;
OverlayCandidate main_image;
main_image.display_rect = root_render_pass->output_rect;
main_image.format = RGBA_8888;
@@ -52,13 +56,13 @@ bool OverlayStrategySingleOnTop::Attempt(
// Add the overlay.
OverlayCandidate candidate;
- gfx::RectF float_rect(quad.rect);
- quad.quadTransform().TransformRect(&float_rect);
- candidate.transform =
- quad.flipped ? OverlayCandidate::FLIP_VERTICAL : OverlayCandidate::NONE;
- candidate.display_rect = gfx::ToNearestRect(float_rect);
+ candidate.transform = overlay_transform;
+ candidate.display_rect =
+ OverlayCandidate::GetOverlayRect(quad.quadTransform(), quad.rect);
candidate.uv_rect = BoundingRect(quad.uv_top_left, quad.uv_bottom_right);
candidate.format = RGBA_8888;
+ candidate.resource_id = quad.resource_id;
+ candidate.plane_z_order = 1;
candidates.push_back(candidate);
// Check for support.
@@ -66,16 +70,12 @@ bool OverlayStrategySingleOnTop::Attempt(
// If the candidate can be handled by an overlay, create a pass for it.
if (candidates[1].overlay_handled) {
- scoped_ptr<RenderPass> overlay_pass = RenderPass::Create();
- overlay_pass->overlay_state = RenderPass::SIMPLE_OVERLAY;
-
scoped_ptr<DrawQuad> overlay_quad = quad_list.take(quad_list.begin());
quad_list.erase(quad_list.begin());
- overlay_pass->quad_list.push_back(overlay_quad.Pass());
- render_passes_in_draw_order->insert(render_passes_in_draw_order->begin(),
- overlay_pass.Pass());
+ candidate_list->swap(candidates);
+ return true;
}
- return candidates[1].overlay_handled;
+ return false;
}
} // namespace cc
diff --git a/cc/output/overlay_strategy_single_on_top.h b/cc/output/overlay_strategy_single_on_top.h
index 99005fd..d984d3d 100644
--- a/cc/output/overlay_strategy_single_on_top.h
+++ b/cc/output/overlay_strategy_single_on_top.h
@@ -8,6 +8,7 @@
#include "base/basictypes.h"
#include "base/memory/scoped_ptr.h"
#include "cc/base/cc_export.h"
+#include "cc/output/overlay_candidate.h"
#include "cc/output/overlay_processor.h"
#include "cc/quads/render_pass.h"
@@ -18,7 +19,8 @@ class CC_EXPORT OverlayStrategySingleOnTop : public OverlayProcessor::Strategy {
public:
OverlayStrategySingleOnTop(OverlayCandidateValidator* capability_checker,
ResourceProvider* resource_provider);
- virtual bool Attempt(RenderPassList* render_passes_in_draw_order) OVERRIDE;
+ virtual bool Attempt(RenderPassList* render_passes_in_draw_order,
+ OverlayCandidateList* candidate_list) OVERRIDE;
private:
OverlayCandidateValidator* capability_checker_;
diff --git a/cc/output/overlay_unittest.cc b/cc/output/overlay_unittest.cc
index ab22cb4..c8f069c 100644
--- a/cc/output/overlay_unittest.cc
+++ b/cc/output/overlay_unittest.cc
@@ -3,6 +3,7 @@
// found in the LICENSE file.
#include "cc/base/scoped_ptr_vector.h"
+#include "cc/output/gl_renderer.h"
#include "cc/output/output_surface.h"
#include "cc/output/output_surface_client.h"
#include "cc/output/overlay_candidate_validator.h"
@@ -16,8 +17,12 @@
#include "cc/test/fake_output_surface_client.h"
#include "cc/test/geometry_test_utils.h"
#include "cc/test/test_context_provider.h"
+#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
+using testing::_;
+using testing::Mock;
+
namespace cc {
namespace {
@@ -103,8 +108,7 @@ scoped_ptr<RenderPass> CreateRenderPass() {
output_rect,
output_rect,
gfx::Transform(),
- has_transparent_background,
- RenderPass::NO_OVERLAY);
+ has_transparent_background);
scoped_ptr<SharedQuadState> shared_state = SharedQuadState::Create();
shared_state->opacity = 1.f;
@@ -112,9 +116,8 @@ scoped_ptr<RenderPass> CreateRenderPass() {
return pass.Pass();
}
-scoped_ptr<TextureDrawQuad> CreateCandidateQuad(
- ResourceProvider* resource_provider,
- const SharedQuadState* shared_quad_state) {
+ResourceProvider::ResourceId CreateResource(
+ ResourceProvider* resource_provider) {
unsigned sync_point = 0;
TextureMailbox mailbox =
TextureMailbox(gpu::Mailbox::Generate(), GL_TEXTURE_2D, sync_point);
@@ -122,9 +125,14 @@ scoped_ptr<TextureDrawQuad> CreateCandidateQuad(
scoped_ptr<SingleReleaseCallback> release_callback =
SingleReleaseCallback::Create(base::Bind(&MailboxReleased));
- ResourceProvider::ResourceId resource_id =
- resource_provider->CreateResourceFromTextureMailbox(
- mailbox, release_callback.Pass());
+ return resource_provider->CreateResourceFromTextureMailbox(
+ mailbox, release_callback.Pass());
+}
+
+scoped_ptr<TextureDrawQuad> CreateCandidateQuad(
+ ResourceProvider* resource_provider,
+ const SharedQuadState* shared_quad_state) {
+ ResourceProvider::ResourceId resource_id = CreateResource(resource_provider);
bool premultiplied_alpha = false;
bool flipped = false;
float vertex_opacity[4] = {1.0f, 1.0f, 1.0f, 1.0f};
@@ -169,7 +177,6 @@ static void CompareRenderPassLists(const RenderPassList& expected_list,
EXPECT_RECT_EQ(expected->damage_rect, actual->damage_rect);
EXPECT_EQ(expected->has_transparent_background,
actual->has_transparent_background);
- EXPECT_EQ(expected->overlay_state, actual->overlay_state);
EXPECT_EQ(expected->shared_quad_state_list.size(),
actual->shared_quad_state_list.size());
@@ -252,22 +259,24 @@ TEST_F(SingleOverlayOnTopTest, SuccessfullOverlay) {
pass_list.push_back(pass.Pass());
// Check for potential candidates.
- overlay_processor_->ProcessForOverlays(&pass_list);
+ OverlayCandidateList candidate_list;
+ overlay_processor_->ProcessForOverlays(&pass_list, &candidate_list);
- // This should have one more pass with an overlay.
- ASSERT_EQ(2U, pass_list.size());
+ ASSERT_EQ(1U, pass_list.size());
+ ASSERT_EQ(2U, candidate_list.size());
- RenderPass* overlay_pass = pass_list.front();
- EXPECT_EQ(RenderPass::SIMPLE_OVERLAY, overlay_pass->overlay_state);
RenderPass* main_pass = pass_list.back();
- EXPECT_EQ(RenderPass::NO_OVERLAY, main_pass->overlay_state);
-
- // Check that the quad is what we expect it to be.
- EXPECT_EQ(1U, overlay_pass->quad_list.size());
- const DrawQuad* overlay_quad = overlay_pass->quad_list.front();
- EXPECT_EQ(DrawQuad::TEXTURE_CONTENT, overlay_quad->material);
- EXPECT_EQ(original_quad->resource_id,
- TextureDrawQuad::MaterialCast(overlay_quad)->resource_id);
+ // Check that the quad is gone.
+ EXPECT_EQ(2U, main_pass->quad_list.size());
+ const QuadList& quad_list = main_pass->quad_list;
+ for (QuadList::ConstBackToFrontIterator it = quad_list.BackToFrontBegin();
+ it != quad_list.BackToFrontEnd();
+ ++it) {
+ EXPECT_NE(DrawQuad::TEXTURE_CONTENT, (*it)->material);
+ }
+
+ // Check that the right resource id got extracted.
+ EXPECT_EQ(original_quad->resource_id, candidate_list.back().resource_id);
}
TEST_F(SingleOverlayOnTopTest, NoCandidates) {
@@ -283,7 +292,9 @@ TEST_F(SingleOverlayOnTopTest, NoCandidates) {
RenderPassList original_pass_list;
RenderPass::CopyAll(pass_list, &original_pass_list);
- overlay_processor_->ProcessForOverlays(&pass_list);
+ OverlayCandidateList candidate_list;
+ overlay_processor_->ProcessForOverlays(&pass_list, &candidate_list);
+ EXPECT_EQ(0U, candidate_list.size());
// There should be nothing new here.
CompareRenderPassLists(pass_list, original_pass_list);
}
@@ -306,7 +317,9 @@ TEST_F(SingleOverlayOnTopTest, OccludedCandidates) {
RenderPassList original_pass_list;
RenderPass::CopyAll(pass_list, &original_pass_list);
- overlay_processor_->ProcessForOverlays(&pass_list);
+ OverlayCandidateList candidate_list;
+ overlay_processor_->ProcessForOverlays(&pass_list, &candidate_list);
+ EXPECT_EQ(0U, candidate_list.size());
// There should be nothing new here.
CompareRenderPassLists(pass_list, original_pass_list);
}
@@ -330,11 +343,16 @@ TEST_F(SingleOverlayOnTopTest, MultipleRenderPasses) {
pass_list.push_back(pass.Pass());
+ RenderPassList original_pass_list;
+ RenderPass::CopyAll(pass_list, &original_pass_list);
+
// Check for potential candidates.
- overlay_processor_->ProcessForOverlays(&pass_list);
+ OverlayCandidateList candidate_list;
+ overlay_processor_->ProcessForOverlays(&pass_list, &candidate_list);
+ EXPECT_EQ(2U, candidate_list.size());
- // This should have one more pass with an overlay.
- ASSERT_EQ(3U, pass_list.size());
+ // This should be the same.
+ ASSERT_EQ(2U, pass_list.size());
}
TEST_F(SingleOverlayOnTopTest, RejectPremultipliedAlpha) {
@@ -346,9 +364,10 @@ TEST_F(SingleOverlayOnTopTest, RejectPremultipliedAlpha) {
pass->quad_list.push_back(quad.PassAs<DrawQuad>());
RenderPassList pass_list;
pass_list.push_back(pass.Pass());
- overlay_processor_->ProcessForOverlays(&pass_list);
- ASSERT_EQ(1U, pass_list.size());
- EXPECT_EQ(RenderPass::NO_OVERLAY, pass_list.back()->overlay_state);
+ OverlayCandidateList candidate_list;
+ overlay_processor_->ProcessForOverlays(&pass_list, &candidate_list);
+ EXPECT_EQ(1U, pass_list.size());
+ EXPECT_EQ(0U, candidate_list.size());
}
TEST_F(SingleOverlayOnTopTest, RejectBlending) {
@@ -360,9 +379,10 @@ TEST_F(SingleOverlayOnTopTest, RejectBlending) {
pass->quad_list.push_back(quad.PassAs<DrawQuad>());
RenderPassList pass_list;
pass_list.push_back(pass.Pass());
- overlay_processor_->ProcessForOverlays(&pass_list);
+ OverlayCandidateList candidate_list;
+ overlay_processor_->ProcessForOverlays(&pass_list, &candidate_list);
ASSERT_EQ(1U, pass_list.size());
- EXPECT_EQ(RenderPass::NO_OVERLAY, pass_list.back()->overlay_state);
+ EXPECT_EQ(0U, candidate_list.size());
}
TEST_F(SingleOverlayOnTopTest, RejectBackgroundColor) {
@@ -374,9 +394,10 @@ TEST_F(SingleOverlayOnTopTest, RejectBackgroundColor) {
pass->quad_list.push_back(quad.PassAs<DrawQuad>());
RenderPassList pass_list;
pass_list.push_back(pass.Pass());
- overlay_processor_->ProcessForOverlays(&pass_list);
+ OverlayCandidateList candidate_list;
+ overlay_processor_->ProcessForOverlays(&pass_list, &candidate_list);
ASSERT_EQ(1U, pass_list.size());
- EXPECT_EQ(RenderPass::NO_OVERLAY, pass_list.back()->overlay_state);
+ EXPECT_EQ(0U, candidate_list.size());
}
TEST_F(SingleOverlayOnTopTest, RejectBlendMode) {
@@ -388,9 +409,10 @@ TEST_F(SingleOverlayOnTopTest, RejectBlendMode) {
pass->quad_list.push_back(quad.PassAs<DrawQuad>());
RenderPassList pass_list;
pass_list.push_back(pass.Pass());
- overlay_processor_->ProcessForOverlays(&pass_list);
+ OverlayCandidateList candidate_list;
+ overlay_processor_->ProcessForOverlays(&pass_list, &candidate_list);
ASSERT_EQ(1U, pass_list.size());
- EXPECT_EQ(RenderPass::NO_OVERLAY, pass_list.back()->overlay_state);
+ EXPECT_EQ(0U, candidate_list.size());
}
TEST_F(SingleOverlayOnTopTest, RejectOpacity) {
@@ -402,9 +424,10 @@ TEST_F(SingleOverlayOnTopTest, RejectOpacity) {
pass->quad_list.push_back(quad.PassAs<DrawQuad>());
RenderPassList pass_list;
pass_list.push_back(pass.Pass());
- overlay_processor_->ProcessForOverlays(&pass_list);
+ OverlayCandidateList candidate_list;
+ overlay_processor_->ProcessForOverlays(&pass_list, &candidate_list);
ASSERT_EQ(1U, pass_list.size());
- EXPECT_EQ(RenderPass::NO_OVERLAY, pass_list.back()->overlay_state);
+ EXPECT_EQ(0U, candidate_list.size());
}
TEST_F(SingleOverlayOnTopTest, RejectTransform) {
@@ -417,9 +440,283 @@ TEST_F(SingleOverlayOnTopTest, RejectTransform) {
pass->quad_list.push_back(quad.PassAs<DrawQuad>());
RenderPassList pass_list;
pass_list.push_back(pass.Pass());
- overlay_processor_->ProcessForOverlays(&pass_list);
+ OverlayCandidateList candidate_list;
+ overlay_processor_->ProcessForOverlays(&pass_list, &candidate_list);
ASSERT_EQ(1U, pass_list.size());
- EXPECT_EQ(RenderPass::NO_OVERLAY, pass_list.back()->overlay_state);
+ EXPECT_EQ(0U, candidate_list.size());
+}
+
+class OverlayInfoRendererGL : public GLRenderer {
+ public:
+ OverlayInfoRendererGL(RendererClient* client,
+ const LayerTreeSettings* settings,
+ OutputSurface* output_surface,
+ ResourceProvider* resource_provider)
+ : GLRenderer(client,
+ settings,
+ output_surface,
+ resource_provider,
+ NULL,
+ 0),
+ expect_overlays_(false) {}
+
+ MOCK_METHOD2(DoDrawQuad, void(DrawingFrame* frame, const DrawQuad* quad));
+
+ virtual void FinishDrawingFrame(DrawingFrame* frame) OVERRIDE {
+ GLRenderer::FinishDrawingFrame(frame);
+
+ if (!expect_overlays_) {
+ EXPECT_EQ(0U, frame->overlay_list.size());
+ return;
+ }
+
+ ASSERT_EQ(2U, frame->overlay_list.size());
+ EXPECT_NE(0U, frame->overlay_list.back().resource_id);
+ }
+
+ void set_expect_overlays(bool expect_overlays) {
+ expect_overlays_ = expect_overlays;
+ }
+
+ private:
+ bool expect_overlays_;
+};
+
+class FakeRendererClient : public RendererClient {
+ public:
+ // RendererClient methods.
+ virtual void SetFullRootLayerDamage() OVERRIDE {}
+};
+
+class MockOverlayScheduler {
+ public:
+ MOCK_METHOD5(Schedule,
+ void(int plane_z_order,
+ unsigned plane_transform,
+ unsigned overlay_texture_id,
+ const gfx::Rect& display_bounds,
+ const gfx::RectF& uv_rect));
+};
+
+class GLRendererWithOverlaysTest : public testing::Test {
+ protected:
+ GLRendererWithOverlaysTest() {
+ provider_ = TestContextProvider::Create();
+ output_surface_.reset(new OverlayOutputSurface(provider_));
+ CHECK(output_surface_->BindToClient(&output_surface_client_));
+ resource_provider_ =
+ ResourceProvider::Create(output_surface_.get(), NULL, 0, false, 1);
+
+ provider_->support()->SetScheduleOverlayPlaneCallback(base::Bind(
+ &MockOverlayScheduler::Schedule, base::Unretained(&scheduler_)));
+ }
+
+ void Init(bool use_validator) {
+ if (use_validator)
+ output_surface_->InitWithSingleOverlayValidator();
+
+ renderer_ =
+ make_scoped_ptr(new OverlayInfoRendererGL(&renderer_client_,
+ &settings_,
+ output_surface_.get(),
+ resource_provider_.get()));
+ }
+
+ void SwapBuffers() { renderer_->SwapBuffers(CompositorFrameMetadata()); }
+
+ LayerTreeSettings settings_;
+ FakeOutputSurfaceClient output_surface_client_;
+ scoped_ptr<OverlayOutputSurface> output_surface_;
+ FakeRendererClient renderer_client_;
+ scoped_ptr<ResourceProvider> resource_provider_;
+ scoped_ptr<OverlayInfoRendererGL> renderer_;
+ scoped_refptr<TestContextProvider> provider_;
+ MockOverlayScheduler scheduler_;
+};
+
+TEST_F(GLRendererWithOverlaysTest, OverlayQuadNotDrawn) {
+ bool use_validator = true;
+ Init(use_validator);
+ renderer_->set_expect_overlays(true);
+ gfx::Rect viewport_rect(16, 16);
+
+ scoped_ptr<RenderPass> pass = CreateRenderPass();
+
+ pass->quad_list.push_back(
+ CreateCandidateQuad(resource_provider_.get(),
+ pass->shared_quad_state_list.back())
+ .PassAs<DrawQuad>());
+
+ pass->quad_list.push_back(CreateCheckeredQuad(
+ resource_provider_.get(), pass->shared_quad_state_list.back()));
+ pass->quad_list.push_back(CreateCheckeredQuad(
+ resource_provider_.get(), pass->shared_quad_state_list.back()));
+
+ RenderPassList pass_list;
+ pass_list.push_back(pass.Pass());
+
+ // Candidate pass was taken out and extra skipped pass added,
+ // so only draw 2 quads.
+ EXPECT_CALL(*renderer_, DoDrawQuad(_, _)).Times(2);
+ EXPECT_CALL(scheduler_,
+ Schedule(1,
+ OverlayCandidate::NONE,
+ _,
+ kOverlayRect,
+ BoundingRect(kUVTopLeft, kUVBottomRight))).Times(1);
+ renderer_->DrawFrame(
+ &pass_list, NULL, 1.f, viewport_rect, viewport_rect, false);
+
+ SwapBuffers();
+
+ Mock::VerifyAndClearExpectations(renderer_.get());
+ Mock::VerifyAndClearExpectations(&scheduler_);
+}
+
+TEST_F(GLRendererWithOverlaysTest, OccludedQuadDrawn) {
+ bool use_validator = true;
+ Init(use_validator);
+ renderer_->set_expect_overlays(false);
+ gfx::Rect viewport_rect(16, 16);
+
+ scoped_ptr<RenderPass> pass = CreateRenderPass();
+
+ pass->quad_list.push_back(CreateCheckeredQuad(
+ resource_provider_.get(), pass->shared_quad_state_list.back()));
+ pass->quad_list.push_back(CreateCheckeredQuad(
+ resource_provider_.get(), pass->shared_quad_state_list.back()));
+
+ pass->quad_list.push_back(
+ CreateCandidateQuad(resource_provider_.get(),
+ pass->shared_quad_state_list.back())
+ .PassAs<DrawQuad>());
+
+ RenderPassList pass_list;
+ pass_list.push_back(pass.Pass());
+
+ // 3 quads in the pass, all should draw.
+ EXPECT_CALL(*renderer_, DoDrawQuad(_, _)).Times(3);
+ EXPECT_CALL(scheduler_, Schedule(_, _, _, _, _)).Times(0);
+ renderer_->DrawFrame(
+ &pass_list, NULL, 1.f, viewport_rect, viewport_rect, false);
+
+ SwapBuffers();
+
+ Mock::VerifyAndClearExpectations(renderer_.get());
+ Mock::VerifyAndClearExpectations(&scheduler_);
+}
+
+TEST_F(GLRendererWithOverlaysTest, NoValidatorNoOverlay) {
+ bool use_validator = false;
+ Init(use_validator);
+ renderer_->set_expect_overlays(false);
+ gfx::Rect viewport_rect(16, 16);
+
+ scoped_ptr<RenderPass> pass = CreateRenderPass();
+
+ pass->quad_list.push_back(
+ CreateCandidateQuad(resource_provider_.get(),
+ pass->shared_quad_state_list.back())
+ .PassAs<DrawQuad>());
+
+ pass->quad_list.push_back(CreateCheckeredQuad(
+ resource_provider_.get(), pass->shared_quad_state_list.back()));
+ pass->quad_list.push_back(CreateCheckeredQuad(
+ resource_provider_.get(), pass->shared_quad_state_list.back()));
+
+ RenderPassList pass_list;
+ pass_list.push_back(pass.Pass());
+
+ // Should see no overlays.
+ EXPECT_CALL(*renderer_, DoDrawQuad(_, _)).Times(3);
+ EXPECT_CALL(scheduler_, Schedule(_, _, _, _, _)).Times(0);
+ renderer_->DrawFrame(
+ &pass_list, NULL, 1.f, viewport_rect, viewport_rect, false);
+
+ SwapBuffers();
+
+ Mock::VerifyAndClearExpectations(renderer_.get());
+ Mock::VerifyAndClearExpectations(&scheduler_);
+}
+
+TEST_F(GLRendererWithOverlaysTest, ResourcesExportedAndReturned) {
+ bool use_validator = true;
+ Init(use_validator);
+ renderer_->set_expect_overlays(true);
+
+ ResourceProvider::ResourceId resource1 =
+ CreateResource(resource_provider_.get());
+ ResourceProvider::ResourceId resource2 =
+ CreateResource(resource_provider_.get());
+
+ DirectRenderer::DrawingFrame frame1;
+ frame1.overlay_list.resize(2);
+ OverlayCandidate& overlay1 = frame1.overlay_list.back();
+ overlay1.resource_id = resource1;
+ overlay1.plane_z_order = 1;
+
+ DirectRenderer::DrawingFrame frame2;
+ frame2.overlay_list.resize(2);
+ OverlayCandidate& overlay2 = frame2.overlay_list.back();
+ overlay2.resource_id = resource2;
+ overlay2.plane_z_order = 1;
+
+ EXPECT_CALL(scheduler_, Schedule(_, _, _, _, _)).Times(1);
+ renderer_->FinishDrawingFrame(&frame1);
+ EXPECT_TRUE(resource_provider_->InUseByConsumer(resource1));
+ EXPECT_FALSE(resource_provider_->InUseByConsumer(resource2));
+ SwapBuffers();
+ Mock::VerifyAndClearExpectations(&scheduler_);
+
+ EXPECT_CALL(scheduler_, Schedule(_, _, _, _, _)).Times(1);
+ renderer_->FinishDrawingFrame(&frame2);
+ EXPECT_TRUE(resource_provider_->InUseByConsumer(resource1));
+ EXPECT_TRUE(resource_provider_->InUseByConsumer(resource2));
+ SwapBuffers();
+ EXPECT_FALSE(resource_provider_->InUseByConsumer(resource1));
+ Mock::VerifyAndClearExpectations(&scheduler_);
+
+ EXPECT_CALL(scheduler_, Schedule(_, _, _, _, _)).Times(1);
+ renderer_->FinishDrawingFrame(&frame1);
+ EXPECT_TRUE(resource_provider_->InUseByConsumer(resource1));
+ EXPECT_TRUE(resource_provider_->InUseByConsumer(resource2));
+ SwapBuffers();
+ EXPECT_FALSE(resource_provider_->InUseByConsumer(resource2));
+ Mock::VerifyAndClearExpectations(&scheduler_);
+
+ // No overlays, release the resource.
+ EXPECT_CALL(scheduler_, Schedule(_, _, _, _, _)).Times(0);
+ DirectRenderer::DrawingFrame frame3;
+ renderer_->set_expect_overlays(false);
+ renderer_->FinishDrawingFrame(&frame3);
+ EXPECT_TRUE(resource_provider_->InUseByConsumer(resource1));
+ EXPECT_FALSE(resource_provider_->InUseByConsumer(resource2));
+ SwapBuffers();
+ EXPECT_FALSE(resource_provider_->InUseByConsumer(resource1));
+ Mock::VerifyAndClearExpectations(&scheduler_);
+
+ // Use the same buffer twice.
+ renderer_->set_expect_overlays(true);
+ EXPECT_CALL(scheduler_, Schedule(_, _, _, _, _)).Times(1);
+ renderer_->FinishDrawingFrame(&frame1);
+ EXPECT_TRUE(resource_provider_->InUseByConsumer(resource1));
+ SwapBuffers();
+ Mock::VerifyAndClearExpectations(&scheduler_);
+
+ EXPECT_CALL(scheduler_, Schedule(_, _, _, _, _)).Times(1);
+ renderer_->FinishDrawingFrame(&frame1);
+ EXPECT_TRUE(resource_provider_->InUseByConsumer(resource1));
+ SwapBuffers();
+ EXPECT_TRUE(resource_provider_->InUseByConsumer(resource1));
+ Mock::VerifyAndClearExpectations(&scheduler_);
+
+ EXPECT_CALL(scheduler_, Schedule(_, _, _, _, _)).Times(0);
+ renderer_->set_expect_overlays(false);
+ renderer_->FinishDrawingFrame(&frame3);
+ EXPECT_TRUE(resource_provider_->InUseByConsumer(resource1));
+ SwapBuffers();
+ EXPECT_FALSE(resource_provider_->InUseByConsumer(resource1));
+ Mock::VerifyAndClearExpectations(&scheduler_);
}
} // namespace
diff --git a/cc/quads/render_pass.cc b/cc/quads/render_pass.cc
index 1eeefe4..82deccd 100644
--- a/cc/quads/render_pass.cc
+++ b/cc/quads/render_pass.cc
@@ -33,18 +33,13 @@ scoped_ptr<RenderPass> RenderPass::Create(size_t num_layers) {
return make_scoped_ptr(new RenderPass(num_layers));
}
-RenderPass::RenderPass()
- : id(Id(-1, -1)),
- has_transparent_background(true),
- overlay_state(NO_OVERLAY) {
+RenderPass::RenderPass() : id(Id(-1, -1)), has_transparent_background(true) {
shared_quad_state_list.reserve(kDefaultNumSharedQuadStatesToReserve);
quad_list.reserve(kDefaultNumQuadsToReserve);
}
RenderPass::RenderPass(size_t num_layers)
- : id(Id(-1, -1)),
- has_transparent_background(true),
- overlay_state(NO_OVERLAY) {
+ : id(Id(-1, -1)), has_transparent_background(true) {
// Each layer usually produces one shared quad state, so the number of layers
// is a good hint for what to reserve here.
shared_quad_state_list.reserve(num_layers);
@@ -63,8 +58,7 @@ scoped_ptr<RenderPass> RenderPass::Copy(Id new_id) const {
output_rect,
damage_rect,
transform_to_root_target,
- has_transparent_background,
- overlay_state);
+ has_transparent_background);
return copy_pass.Pass();
}
@@ -83,8 +77,7 @@ void RenderPass::CopyAll(const ScopedPtrVector<RenderPass>& in,
source->output_rect,
source->damage_rect,
source->transform_to_root_target,
- source->has_transparent_background,
- source->overlay_state);
+ source->has_transparent_background);
for (size_t i = 0; i < source->shared_quad_state_list.size(); ++i) {
copy_pass->shared_quad_state_list.push_back(
source->shared_quad_state_list[i]->Copy());
@@ -135,8 +128,7 @@ void RenderPass::SetAll(Id id,
const gfx::Rect& output_rect,
const gfx::RectF& damage_rect,
const gfx::Transform& transform_to_root_target,
- bool has_transparent_background,
- OverlayState overlay_state) {
+ bool has_transparent_background) {
DCHECK_GT(id.layer_id, 0);
DCHECK_GE(id.index, 0);
@@ -145,7 +137,6 @@ void RenderPass::SetAll(Id id,
this->damage_rect = damage_rect;
this->transform_to_root_target = transform_to_root_target;
this->has_transparent_background = has_transparent_background;
- this->overlay_state = overlay_state;
DCHECK(quad_list.empty());
DCHECK(shared_quad_state_list.empty());
diff --git a/cc/quads/render_pass.h b/cc/quads/render_pass.h
index 5cada2a..4285e53 100644
--- a/cc/quads/render_pass.h
+++ b/cc/quads/render_pass.h
@@ -62,11 +62,6 @@ class CC_EXPORT RenderPass {
}
};
- // Specifies whether the pass is going into an overlay, needs to be rendered
- // into a buffer before it can be presented to overlay hardware or a quad
- // inside it is presented as is.
- enum OverlayState { NO_OVERLAY, RENDER_AND_OVERLAY, SIMPLE_OVERLAY, };
-
~RenderPass();
static scoped_ptr<RenderPass> Create();
@@ -89,8 +84,7 @@ class CC_EXPORT RenderPass {
const gfx::Rect& output_rect,
const gfx::RectF& damage_rect,
const gfx::Transform& transform_to_root_target,
- bool has_transparent_background,
- OverlayState overlay_state);
+ bool has_transparent_background);
scoped_ptr<base::Value> AsValue() const;
@@ -117,8 +111,6 @@ class CC_EXPORT RenderPass {
QuadList quad_list;
SharedQuadStateList shared_quad_state_list;
- OverlayState overlay_state;
-
protected:
explicit RenderPass(size_t num_layers);
RenderPass();
diff --git a/cc/quads/render_pass_unittest.cc b/cc/quads/render_pass_unittest.cc
index 1305741..fd58523 100644
--- a/cc/quads/render_pass_unittest.cc
+++ b/cc/quads/render_pass_unittest.cc
@@ -31,7 +31,6 @@ struct RenderPassSize {
gfx::RectF damage_rect;
bool has_transparent_background;
ScopedPtrVector<CopyOutputRequest> copy_callbacks;
- RenderPass::OverlayState overlay_state;
};
static void CompareRenderPassLists(const RenderPassList& expected_list,
@@ -48,7 +47,6 @@ static void CompareRenderPassLists(const RenderPassList& expected_list,
EXPECT_RECT_EQ(expected->damage_rect, actual->damage_rect);
EXPECT_EQ(expected->has_transparent_background,
actual->has_transparent_background);
- EXPECT_EQ(expected->overlay_state, actual->overlay_state);
EXPECT_EQ(expected->shared_quad_state_list.size(),
actual->shared_quad_state_list.size());
@@ -71,15 +69,13 @@ TEST(RenderPassTest, CopyShouldBeIdenticalExceptIdAndQuads) {
gfx::Transform(1.0, 0.5, 0.5, -0.5, -1.0, 0.0);
gfx::Rect damage_rect(56, 123, 19, 43);
bool has_transparent_background = true;
- RenderPass::OverlayState overlay_state = RenderPass::SIMPLE_OVERLAY;
scoped_ptr<TestRenderPass> pass = TestRenderPass::Create();
pass->SetAll(id,
output_rect,
damage_rect,
transform_to_root,
- has_transparent_background,
- overlay_state);
+ has_transparent_background);
pass->copy_requests.push_back(CopyOutputRequest::CreateEmptyRequest());
// Stick a quad in the pass, this should not get copied.
@@ -107,7 +103,6 @@ TEST(RenderPassTest, CopyShouldBeIdenticalExceptIdAndQuads) {
EXPECT_EQ(pass->transform_to_root_target, copy->transform_to_root_target);
EXPECT_RECT_EQ(pass->damage_rect, copy->damage_rect);
EXPECT_EQ(pass->has_transparent_background, copy->has_transparent_background);
- EXPECT_EQ(pass->overlay_state, copy->overlay_state);
EXPECT_EQ(0u, copy->quad_list.size());
// The copy request should not be copied/duplicated.
@@ -126,15 +121,13 @@ TEST(RenderPassTest, CopyAllShouldBeIdentical) {
gfx::Transform(1.0, 0.5, 0.5, -0.5, -1.0, 0.0);
gfx::Rect damage_rect(56, 123, 19, 43);
bool has_transparent_background = true;
- RenderPass::OverlayState overlay_state = RenderPass::SIMPLE_OVERLAY;
scoped_ptr<TestRenderPass> pass = TestRenderPass::Create();
pass->SetAll(id,
output_rect,
damage_rect,
transform_to_root,
- has_transparent_background,
- overlay_state);
+ has_transparent_background);
// Two quads using one shared state.
scoped_ptr<SharedQuadState> shared_state1 = SharedQuadState::Create();
@@ -197,15 +190,13 @@ TEST(RenderPassTest, CopyAllShouldBeIdentical) {
gfx::Transform(1.0, 0.5, 0.5, -0.5, -1.0, 0.0);
gfx::Rect contrib_damage_rect(11, 16, 10, 15);
bool contrib_has_transparent_background = true;
- RenderPass::OverlayState contrib_overlay_state = RenderPass::SIMPLE_OVERLAY;
scoped_ptr<TestRenderPass> contrib = TestRenderPass::Create();
contrib->SetAll(contrib_id,
contrib_output_rect,
contrib_damage_rect,
contrib_transform_to_root,
- contrib_has_transparent_background,
- contrib_overlay_state);
+ contrib_has_transparent_background);
scoped_ptr<SharedQuadState> contrib_shared_state = SharedQuadState::Create();
contrib_shared_state->SetAll(gfx::Transform(),
@@ -258,15 +249,13 @@ TEST(RenderPassTest, CopyAllWithCulledQuads) {
gfx::Transform(1.0, 0.5, 0.5, -0.5, -1.0, 0.0);
gfx::Rect damage_rect(56, 123, 19, 43);
bool has_transparent_background = true;
- RenderPass::OverlayState overlay_state = RenderPass::SIMPLE_OVERLAY;
scoped_ptr<TestRenderPass> pass = TestRenderPass::Create();
pass->SetAll(id,
output_rect,
damage_rect,
transform_to_root,
- has_transparent_background,
- overlay_state);
+ has_transparent_background);
// A shared state with a quad.
scoped_ptr<SharedQuadState> shared_state1 = SharedQuadState::Create();
diff --git a/cc/resources/resource_provider.cc b/cc/resources/resource_provider.cc
index 4e7b2c4..1e7c9d7 100644
--- a/cc/resources/resource_provider.cc
+++ b/cc/resources/resource_provider.cc
@@ -799,12 +799,11 @@ void ResourceProvider::DeleteResource(ResourceId id) {
ResourceMap::iterator it = resources_.find(id);
CHECK(it != resources_.end());
Resource* resource = &it->second;
- DCHECK(!resource->lock_for_read_count);
DCHECK(!resource->marked_for_deletion);
DCHECK_EQ(resource->imported_count, 0);
DCHECK(resource->pending_set_pixels || !resource->locked_for_write);
- if (resource->exported_count > 0) {
+ if (resource->exported_count > 0 || resource->lock_for_read_count > 0) {
resource->marked_for_deletion = true;
return;
} else {
@@ -1087,10 +1086,25 @@ const ResourceProvider::Resource* ResourceProvider::LockForRead(ResourceId id) {
}
void ResourceProvider::UnlockForRead(ResourceId id) {
- Resource* resource = GetResource(id);
+ DCHECK(thread_checker_.CalledOnValidThread());
+ ResourceMap::iterator it = resources_.find(id);
+ CHECK(it != resources_.end());
+
+ Resource* resource = &it->second;
DCHECK_GT(resource->lock_for_read_count, 0);
DCHECK_EQ(resource->exported_count, 0);
resource->lock_for_read_count--;
+ if (resource->marked_for_deletion && !resource->lock_for_read_count) {
+ if (!resource->child_id) {
+ // The resource belongs to this ResourceProvider, so it can be destroyed.
+ DeleteResourceInternal(it, Normal);
+ } else {
+ ChildMap::iterator child_it = children_.find(resource->child_id);
+ ResourceIdArray unused;
+ unused.push_back(id);
+ DeleteAndReturnUnusedResourcesToChild(child_it, Normal, unused);
+ }
+ }
}
const ResourceProvider::Resource* ResourceProvider::LockForWrite(
@@ -1647,7 +1661,6 @@ void ResourceProvider::DeleteAndReturnUnusedResourcesToChild(
Resource& resource = it->second;
DCHECK(!resource.locked_for_write);
- DCHECK(!resource.lock_for_read_count);
DCHECK_EQ(0u, child_info->in_use_resources.count(local_id));
DCHECK(child_info->parent_to_child_map.count(local_id));
@@ -1656,9 +1669,10 @@ void ResourceProvider::DeleteAndReturnUnusedResourcesToChild(
bool is_lost =
resource.lost || (resource.type == GLTexture && lost_output_surface_);
- if (resource.exported_count > 0) {
+ if (resource.exported_count > 0 || resource.lock_for_read_count > 0) {
if (style != ForShutdown) {
- // Defer this until we receive the resource back from the parent.
+ // Defer this until we receive the resource back from the parent or
+ // the read lock is released.
resource.marked_for_deletion = true;
continue;
}
diff --git a/cc/resources/resource_provider_unittest.cc b/cc/resources/resource_provider_unittest.cc
index b106300..21feb89 100644
--- a/cc/resources/resource_provider_unittest.cc
+++ b/cc/resources/resource_provider_unittest.cc
@@ -825,6 +825,56 @@ TEST_P(ResourceProviderTest, TransferGLResources) {
EXPECT_FALSE(returned_to_child[3].lost);
}
+TEST_P(ResourceProviderTest, ReadLockCountStopsReturnToChildOrDelete) {
+ if (GetParam() != ResourceProvider::GLTexture)
+ return;
+ gfx::Size size(1, 1);
+ ResourceFormat format = RGBA_8888;
+
+ ResourceProvider::ResourceId id1 = child_resource_provider_->CreateResource(
+ size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureUsageAny, format);
+ uint8_t data1[4] = {1, 2, 3, 4};
+ gfx::Rect rect(size);
+ child_resource_provider_->SetPixels(id1, data1, rect, rect, gfx::Vector2d());
+
+ ReturnedResourceArray returned_to_child;
+ int child_id =
+ resource_provider_->CreateChild(GetReturnCallback(&returned_to_child));
+ {
+ // Transfer some resources to the parent.
+ ResourceProvider::ResourceIdArray resource_ids_to_transfer;
+ resource_ids_to_transfer.push_back(id1);
+ TransferableResourceArray list;
+ child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
+ &list);
+ ASSERT_EQ(1u, list.size());
+ EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id1));
+
+ resource_provider_->ReceiveFromChild(child_id, list);
+
+ ResourceProvider::ScopedReadLockGL lock(resource_provider_.get(),
+ list[0].id);
+
+ resource_provider_->DeclareUsedResourcesFromChild(
+ child_id, ResourceProvider::ResourceIdArray());
+ EXPECT_EQ(0u, returned_to_child.size());
+ }
+
+ EXPECT_EQ(1u, returned_to_child.size());
+ child_resource_provider_->ReceiveReturnsFromParent(returned_to_child);
+
+ {
+ ResourceProvider::ScopedReadLockGL lock(child_resource_provider_.get(),
+ id1);
+ child_resource_provider_->DeleteResource(id1);
+ EXPECT_EQ(1u, child_resource_provider_->num_resources());
+ EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id1));
+ }
+
+ EXPECT_EQ(0u, child_resource_provider_->num_resources());
+ resource_provider_->DestroyChild(child_id);
+}
+
TEST_P(ResourceProviderTest, TransferSoftwareResources) {
if (GetParam() != ResourceProvider::Bitmap)
return;
diff --git a/cc/surfaces/surface_aggregator.cc b/cc/surfaces/surface_aggregator.cc
index 4d06101..5b108bb 100644
--- a/cc/surfaces/surface_aggregator.cc
+++ b/cc/surfaces/surface_aggregator.cc
@@ -97,8 +97,7 @@ void SurfaceAggregator::HandleSurfaceQuad(const SurfaceDrawQuad* surface_quad,
source.output_rect,
source.damage_rect,
source.transform_to_root_target,
- source.has_transparent_background,
- source.overlay_state);
+ source.has_transparent_background);
// Contributing passes aggregated in to the pass list need to take the
// transform of the surface quad into account to update their transform to
@@ -204,8 +203,7 @@ void SurfaceAggregator::CopyPasses(const RenderPassList& source_pass_list,
source.output_rect,
source.damage_rect,
source.transform_to_root_target,
- source.has_transparent_background,
- source.overlay_state);
+ source.has_transparent_background);
CopyQuadsToPass(source.quad_list,
source.shared_quad_state_list,
diff --git a/cc/test/test_context_support.cc b/cc/test/test_context_support.cc
index 3c2e31a..0e668aa 100644
--- a/cc/test/test_context_support.cc
+++ b/cc/test/test_context_support.cc
@@ -56,6 +56,11 @@ void TestContextSupport::SetSurfaceVisibleCallback(
set_visible_callback_ = set_visible_callback;
}
+void TestContextSupport::SetScheduleOverlayPlaneCallback(
+ const ScheduleOverlayPlaneCallback& schedule_overlay_plane_callback) {
+ schedule_overlay_plane_callback_ = schedule_overlay_plane_callback;
+}
+
void TestContextSupport::Swap() {
last_swap_type_ = SWAP;
base::MessageLoop::current()->PostTask(
@@ -71,6 +76,20 @@ void TestContextSupport::PartialSwapBuffers(const gfx::Rect& sub_buffer) {
weak_ptr_factory_.GetWeakPtr()));
}
+void TestContextSupport::ScheduleOverlayPlane(int plane_z_order,
+ unsigned plane_transform,
+ unsigned overlay_texture_id,
+ const gfx::Rect& display_bounds,
+ const gfx::RectF& uv_rect) {
+ if (!schedule_overlay_plane_callback_.is_null()) {
+ schedule_overlay_plane_callback_.Run(plane_z_order,
+ plane_transform,
+ overlay_texture_id,
+ display_bounds,
+ uv_rect);
+ }
+}
+
void TestContextSupport::SetSwapBuffersCompleteCallback(
const base::Closure& callback) {
swap_buffers_complete_callback_ = callback;
diff --git a/cc/test/test_context_support.h b/cc/test/test_context_support.h
index 7ae657c1..9fd5d1d 100644
--- a/cc/test/test_context_support.h
+++ b/cc/test/test_context_support.h
@@ -29,6 +29,11 @@ class TestContextSupport : public gpu::ContextSupport {
virtual void PartialSwapBuffers(const gfx::Rect& sub_buffer) OVERRIDE;
virtual void SetSwapBuffersCompleteCallback(
const base::Closure& callback) OVERRIDE;
+ virtual void ScheduleOverlayPlane(int plane_z_order,
+ unsigned plane_transform,
+ unsigned overlay_texture_id,
+ const gfx::Rect& display_bounds,
+ const gfx::RectF& uv_rect) OVERRIDE;
void CallAllSyncPointCallbacks();
@@ -36,6 +41,15 @@ class TestContextSupport : public gpu::ContextSupport {
void SetSurfaceVisibleCallback(
const SurfaceVisibleCallback& set_visible_callback);
+ typedef base::Callback<void(int plane_z_order,
+ unsigned plane_transform,
+ unsigned overlay_texture_id,
+ const gfx::Rect& display_bounds,
+ const gfx::RectF& crop_rect)>
+ ScheduleOverlayPlaneCallback;
+ void SetScheduleOverlayPlaneCallback(
+ const ScheduleOverlayPlaneCallback& schedule_overlay_plane_callback);
+
enum SwapType {
NO_SWAP,
SWAP,
@@ -52,6 +66,7 @@ class TestContextSupport : public gpu::ContextSupport {
std::vector<base::Closure> sync_point_callbacks_;
SurfaceVisibleCallback set_visible_callback_;
+ ScheduleOverlayPlaneCallback schedule_overlay_plane_callback_;
base::Closure swap_buffers_complete_callback_;
diff --git a/content/common/cc_messages.cc b/content/common/cc_messages.cc
index 712c608..40e2441 100644
--- a/content/common/cc_messages.cc
+++ b/content/common/cc_messages.cc
@@ -285,7 +285,6 @@ void ParamTraits<gfx::Transform>::Log(
void ParamTraits<cc::RenderPass>::Write(
Message* m, const param_type& p) {
- DCHECK(p.overlay_state == cc::RenderPass::NO_OVERLAY);
WriteParam(m, p.id);
WriteParam(m, p.output_rect);
WriteParam(m, p.damage_rect);
@@ -422,8 +421,7 @@ bool ParamTraits<cc::RenderPass>::Read(
output_rect,
damage_rect,
transform_to_root_target,
- has_transparent_background,
- cc::RenderPass::NO_OVERLAY);
+ has_transparent_background);
size_t last_shared_quad_state_index = kuint32max;
for (size_t i = 0; i < quad_list_size; ++i) {
diff --git a/content/common/cc_messages_unittest.cc b/content/common/cc_messages_unittest.cc
index 01d07a4..fb32ddf 100644
--- a/content/common/cc_messages_unittest.cc
+++ b/content/common/cc_messages_unittest.cc
@@ -439,8 +439,7 @@ TEST_F(CCMessagesTest, AllQuads) {
arbitrary_rect1,
arbitrary_rectf1,
arbitrary_matrix,
- arbitrary_bool1,
- cc::RenderPass::NO_OVERLAY);
+ arbitrary_bool1);
pass_in->shared_quad_state_list.push_back(shared_state1_in.Pass());
pass_in->quad_list.push_back(checkerboard_in.PassAs<DrawQuad>());
@@ -461,8 +460,7 @@ TEST_F(CCMessagesTest, AllQuads) {
arbitrary_rect1,
arbitrary_rectf1,
arbitrary_matrix,
- arbitrary_bool1,
- cc::RenderPass::NO_OVERLAY);
+ arbitrary_bool1);
pass_cmp->shared_quad_state_list.push_back(shared_state1_cmp.Pass());
pass_cmp->quad_list.push_back(checkerboard_cmp.PassAs<DrawQuad>());
@@ -539,8 +537,7 @@ TEST_F(CCMessagesTest, UnusedSharedQuadStates) {
gfx::Rect(100, 100),
gfx::RectF(),
gfx::Transform(),
- false,
- cc::RenderPass::NO_OVERLAY);
+ false);
// The first SharedQuadState is used.
scoped_ptr<SharedQuadState> shared_state1_in = SharedQuadState::Create();
diff --git a/gpu/command_buffer/client/context_support.h b/gpu/command_buffer/client/context_support.h
index b5e7713..7344d1e 100644
--- a/gpu/command_buffer/client/context_support.h
+++ b/gpu/command_buffer/client/context_support.h
@@ -33,6 +33,15 @@ class ContextSupport {
virtual void SetSwapBuffersCompleteCallback(
const base::Closure& callback) = 0;
+ // Schedule a texture to be presented as an overlay synchronously with the
+ // primary surface during the next buffer swap.
+ // This method is not stateful and needs to be re-scheduled every frame.
+ virtual void ScheduleOverlayPlane(int plane_z_order,
+ unsigned plane_transform,
+ unsigned overlay_texture_id,
+ const gfx::Rect& display_bounds,
+ const gfx::RectF& uv_rect) = 0;
+
protected:
ContextSupport() {}
virtual ~ContextSupport() {}
diff --git a/gpu/command_buffer/client/gles2_implementation.cc b/gpu/command_buffer/client/gles2_implementation.cc
index 1c9e482..147714a 100644
--- a/gpu/command_buffer/client/gles2_implementation.cc
+++ b/gpu/command_buffer/client/gles2_implementation.cc
@@ -2791,6 +2791,14 @@ void GLES2Implementation::SetSwapBuffersCompleteCallback(
swap_buffers_complete_callback_ = swap_buffers_complete_callback;
}
+void GLES2Implementation::ScheduleOverlayPlane(int plane_z_order,
+ unsigned plane_transform,
+ unsigned overlay_texture_id,
+ const gfx::Rect& display_bounds,
+ const gfx::RectF& uv_rect) {
+ NOTREACHED() << "Overlay supported isn't finished.";
+}
+
void GLES2Implementation::OnSwapBuffersComplete() {
if (!swap_buffers_complete_callback_.is_null())
swap_buffers_complete_callback_.Run();
diff --git a/gpu/command_buffer/client/gles2_implementation.h b/gpu/command_buffer/client/gles2_implementation.h
index 225a43a..bd5ee04 100644
--- a/gpu/command_buffer/client/gles2_implementation.h
+++ b/gpu/command_buffer/client/gles2_implementation.h
@@ -220,6 +220,11 @@ class GLES2_IMPL_EXPORT GLES2Implementation
virtual void SetSwapBuffersCompleteCallback(
const base::Closure& swap_buffers_complete_callback)
OVERRIDE;
+ virtual void ScheduleOverlayPlane(int plane_z_order,
+ unsigned plane_transform,
+ unsigned overlay_texture_id,
+ const gfx::Rect& display_bounds,
+ const gfx::RectF& uv_rect) OVERRIDE;
void GetProgramInfoCHROMIUMHelper(GLuint program, std::vector<int8>* result);
GLint GetAttribLocationHelper(GLuint program, const char* name);