summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authordanakj@chromium.org <danakj@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-01-17 03:44:55 +0000
committerdanakj@chromium.org <danakj@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-01-17 03:44:55 +0000
commit8611f01f36a713d0260e11670f24403be7294b7c (patch)
treee1c56b09d08dcf2d48a8f1bc7081811d7d4ef92c
parent6646043896e02173e61c1d20df278d56577cce08 (diff)
downloadchromium_src-8611f01f36a713d0260e11670f24403be7294b7c.zip
chromium_src-8611f01f36a713d0260e11670f24403be7294b7c.tar.gz
chromium_src-8611f01f36a713d0260e11670f24403be7294b7c.tar.bz2
cc: Clarify the uvRect used for RenderSurfaces and support masks with different bounds.
The texture coords for the mask layer go from 0.0 to 1.0, so there is no need to scale between the size of the mask texture and the render surface texture. The uv rect is there to scale between the unclipped render surface coordinates and the clipped render surface texture. So make this explicit in the code. This remove the mask layer's content size completely from the equations. Tests: cc_unittests:LayerTreeHostImplTest.maskLayerWithDifferentBounds R=piman BUG=170076 Review URL: https://chromiumcodereview.appspot.com/11968007 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@177337 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--cc/layer_tree_host_impl_unittest.cc137
-rw-r--r--cc/render_surface_impl.cc30
2 files changed, 148 insertions, 19 deletions
diff --git a/cc/layer_tree_host_impl_unittest.cc b/cc/layer_tree_host_impl_unittest.cc
index b6a3195..459ab4bb 100644
--- a/cc/layer_tree_host_impl_unittest.cc
+++ b/cc/layer_tree_host_impl_unittest.cc
@@ -4505,8 +4505,8 @@ TEST_P(LayerTreeHostImplTest, maskLayerWithScaling)
ASSERT_EQ(1u, frame.renderPasses[0]->quad_list.size());
ASSERT_EQ(DrawQuad::RENDER_PASS, frame.renderPasses[0]->quad_list[0]->material);
const RenderPassDrawQuad* renderPassQuad = RenderPassDrawQuad::MaterialCast(frame.renderPasses[0]->quad_list[0]);
- EXPECT_EQ(renderPassQuad->rect.ToString(), gfx::Rect(0, 0, 100, 100).ToString());
- EXPECT_EQ(renderPassQuad->mask_uv_rect.ToString(), gfx::RectF(0.f, 0.f, 1.f, 1.f).ToString());
+ EXPECT_EQ(gfx::Rect(0, 0, 100, 100).ToString(), renderPassQuad->rect.ToString());
+ EXPECT_EQ(gfx::RectF(0.f, 0.f, 1.f, 1.f).ToString(), renderPassQuad->mask_uv_rect.ToString());
m_hostImpl->drawLayers(frame);
m_hostImpl->didDrawAllLayers(frame);
@@ -4528,8 +4528,8 @@ TEST_P(LayerTreeHostImplTest, maskLayerWithScaling)
ASSERT_EQ(1u, frame.renderPasses[0]->quad_list.size());
ASSERT_EQ(DrawQuad::RENDER_PASS, frame.renderPasses[0]->quad_list[0]->material);
const RenderPassDrawQuad* renderPassQuad = RenderPassDrawQuad::MaterialCast(frame.renderPasses[0]->quad_list[0]);
- EXPECT_EQ(renderPassQuad->rect.ToString(), gfx::Rect(0, 0, 200, 200).ToString());
- EXPECT_EQ(renderPassQuad->mask_uv_rect.ToString(), gfx::RectF(0.f, 0.f, 1.f, 1.f).ToString());
+ EXPECT_EQ(gfx::Rect(0, 0, 200, 200).ToString(), renderPassQuad->rect.ToString());
+ EXPECT_EQ(gfx::RectF(0.f, 0.f, 1.f, 1.f).ToString(), renderPassQuad->mask_uv_rect.ToString());
m_hostImpl->drawLayers(frame);
m_hostImpl->didDrawAllLayers(frame);
@@ -4552,8 +4552,133 @@ TEST_P(LayerTreeHostImplTest, maskLayerWithScaling)
ASSERT_EQ(1u, frame.renderPasses[0]->quad_list.size());
ASSERT_EQ(DrawQuad::RENDER_PASS, frame.renderPasses[0]->quad_list[0]->material);
const RenderPassDrawQuad* renderPassQuad = RenderPassDrawQuad::MaterialCast(frame.renderPasses[0]->quad_list[0]);
- EXPECT_EQ(renderPassQuad->rect.ToString(), gfx::Rect(0, 0, 200, 200).ToString());
- EXPECT_EQ(renderPassQuad->mask_uv_rect.ToString(), gfx::RectF(0.f, 0.f, 1.f, 1.f).ToString());
+ EXPECT_EQ(gfx::Rect(0, 0, 200, 200).ToString(), renderPassQuad->rect.ToString());
+ EXPECT_EQ(gfx::RectF(0.f, 0.f, 1.f, 1.f).ToString(), renderPassQuad->mask_uv_rect.ToString());
+
+ m_hostImpl->drawLayers(frame);
+ m_hostImpl->didDrawAllLayers(frame);
+ }
+}
+
+TEST_P(LayerTreeHostImplTest, maskLayerWithDifferentBounds)
+{
+ // The mask layer has bounds 100x100 but is attached to a layer with bounds 50x50.
+
+ scoped_ptr<LayerImpl> scopedRoot = LayerImpl::create(m_hostImpl->activeTree(), 1);
+ LayerImpl* root = scopedRoot.get();
+ m_hostImpl->activeTree()->SetRootLayer(scopedRoot.Pass());
+
+ scoped_ptr<LayerImpl> scopedContentLayer = LayerImpl::create(m_hostImpl->activeTree(), 3);
+ LayerImpl* contentLayer = scopedContentLayer.get();
+ root->addChild(scopedContentLayer.Pass());
+
+ scoped_ptr<FakeMaskLayerImpl> scopedMaskLayer = FakeMaskLayerImpl::create(m_hostImpl->activeTree(), 4);
+ FakeMaskLayerImpl* maskLayer = scopedMaskLayer.get();
+ contentLayer->setMaskLayer(scopedMaskLayer.PassAs<LayerImpl>());
+
+ gfx::Size rootSize(100, 100);
+ root->setBounds(rootSize);
+ root->setContentBounds(rootSize);
+ root->setPosition(gfx::PointF());
+ root->setAnchorPoint(gfx::PointF());
+
+ gfx::Size layerSize(50, 50);
+ contentLayer->setBounds(layerSize);
+ contentLayer->setContentBounds(layerSize);
+ contentLayer->setPosition(gfx::PointF());
+ contentLayer->setAnchorPoint(gfx::PointF());
+ contentLayer->setDrawsContent(true);
+
+ gfx::Size maskSize(100, 100);
+ maskLayer->setBounds(maskSize);
+ maskLayer->setContentBounds(maskSize);
+ maskLayer->setPosition(gfx::PointF());
+ maskLayer->setAnchorPoint(gfx::PointF());
+ maskLayer->setDrawsContent(true);
+
+
+ // Check that the mask fills the surface.
+ float deviceScaleFactor = 1.f;
+ m_hostImpl->setViewportSize(rootSize, rootSize);
+ m_hostImpl->setDeviceScaleFactor(deviceScaleFactor);
+ {
+ LayerTreeHostImpl::FrameData frame;
+ EXPECT_TRUE(m_hostImpl->prepareToDraw(frame));
+
+ ASSERT_EQ(1u, frame.renderPasses.size());
+ ASSERT_EQ(1u, frame.renderPasses[0]->quad_list.size());
+ ASSERT_EQ(DrawQuad::RENDER_PASS, frame.renderPasses[0]->quad_list[0]->material);
+ const RenderPassDrawQuad* renderPassQuad = RenderPassDrawQuad::MaterialCast(frame.renderPasses[0]->quad_list[0]);
+ EXPECT_EQ(gfx::Rect(0, 0, 50, 50).ToString(), renderPassQuad->rect.ToString());
+ EXPECT_EQ(gfx::RectF(0.f, 0.f, 1.f, 1.f).ToString(), renderPassQuad->mask_uv_rect.ToString());
+
+ m_hostImpl->drawLayers(frame);
+ m_hostImpl->didDrawAllLayers(frame);
+ }
+
+
+ // Applying a DSF should change the render surface size, but won't affect
+ // which part of the mask is used.
+ deviceScaleFactor = 2.f;
+ gfx::Size deviceViewport(gfx::ToFlooredSize(gfx::ScaleSize(rootSize, deviceScaleFactor)));
+ m_hostImpl->setViewportSize(rootSize, deviceViewport);
+ m_hostImpl->setDeviceScaleFactor(deviceScaleFactor);
+ m_hostImpl->setNeedsUpdateDrawProperties();
+ {
+ LayerTreeHostImpl::FrameData frame;
+ EXPECT_TRUE(m_hostImpl->prepareToDraw(frame));
+
+ ASSERT_EQ(1u, frame.renderPasses.size());
+ ASSERT_EQ(1u, frame.renderPasses[0]->quad_list.size());
+ ASSERT_EQ(DrawQuad::RENDER_PASS, frame.renderPasses[0]->quad_list[0]->material);
+ const RenderPassDrawQuad* renderPassQuad = RenderPassDrawQuad::MaterialCast(frame.renderPasses[0]->quad_list[0]);
+ EXPECT_EQ(gfx::Rect(0, 0, 100, 100).ToString(), renderPassQuad->rect.ToString());
+ EXPECT_EQ(gfx::RectF(0.f, 0.f, 1.f, 1.f).ToString(), renderPassQuad->mask_uv_rect.ToString());
+
+ m_hostImpl->drawLayers(frame);
+ m_hostImpl->didDrawAllLayers(frame);
+ }
+
+
+ // Applying an equivalent content scale on the content layer and the mask
+ // should still result in the same part of the mask being used.
+ gfx::Size layerSizeLarge(gfx::ToRoundedSize(gfx::ScaleSize(layerSize, deviceScaleFactor)));
+ contentLayer->setContentBounds(layerSizeLarge);
+ contentLayer->setContentsScale(deviceScaleFactor, deviceScaleFactor);
+ gfx::Size maskSizeLarge(gfx::ToRoundedSize(gfx::ScaleSize(maskSize, deviceScaleFactor)));
+ maskLayer->setContentBounds(maskSizeLarge);
+ maskLayer->setContentsScale(deviceScaleFactor, deviceScaleFactor);
+ m_hostImpl->setNeedsUpdateDrawProperties();
+ {
+ LayerTreeHostImpl::FrameData frame;
+ EXPECT_TRUE(m_hostImpl->prepareToDraw(frame));
+
+ ASSERT_EQ(1u, frame.renderPasses.size());
+ ASSERT_EQ(1u, frame.renderPasses[0]->quad_list.size());
+ ASSERT_EQ(DrawQuad::RENDER_PASS, frame.renderPasses[0]->quad_list[0]->material);
+ const RenderPassDrawQuad* renderPassQuad = RenderPassDrawQuad::MaterialCast(frame.renderPasses[0]->quad_list[0]);
+ EXPECT_EQ(gfx::Rect(0, 0, 100, 100).ToString(), renderPassQuad->rect.ToString());
+ EXPECT_EQ(gfx::RectF(0.f, 0.f, 1.f, 1.f).ToString(), renderPassQuad->mask_uv_rect.ToString());
+
+ m_hostImpl->drawLayers(frame);
+ m_hostImpl->didDrawAllLayers(frame);
+ }
+
+ // Applying a different contents scale to the mask layer will still result
+ // in the mask covering the owning layer.
+ maskLayer->setContentBounds(maskSize);
+ maskLayer->setContentsScale(deviceScaleFactor, deviceScaleFactor);
+ m_hostImpl->setNeedsUpdateDrawProperties();
+ {
+ LayerTreeHostImpl::FrameData frame;
+ EXPECT_TRUE(m_hostImpl->prepareToDraw(frame));
+
+ ASSERT_EQ(1u, frame.renderPasses.size());
+ ASSERT_EQ(1u, frame.renderPasses[0]->quad_list.size());
+ ASSERT_EQ(DrawQuad::RENDER_PASS, frame.renderPasses[0]->quad_list[0]->material);
+ const RenderPassDrawQuad* renderPassQuad = RenderPassDrawQuad::MaterialCast(frame.renderPasses[0]->quad_list[0]);
+ EXPECT_EQ(gfx::Rect(0, 0, 100, 100).ToString(), renderPassQuad->rect.ToString());
+ EXPECT_EQ(gfx::RectF(0.f, 0.f, 1.f, 1.f).ToString(), renderPassQuad->mask_uv_rect.ToString());
m_hostImpl->drawLayers(frame);
m_hostImpl->didDrawAllLayers(frame);
diff --git a/cc/render_surface_impl.cc b/cc/render_surface_impl.cc
index 8023da6..84758da0 100644
--- a/cc/render_surface_impl.cc
+++ b/cc/render_surface_impl.cc
@@ -224,19 +224,23 @@ void RenderSurfaceImpl::appendQuads(QuadSink& quadSink, AppendQuadsData& appendQ
gfx::RectF maskUVRect(0.0f, 0.0f, 1.0f, 1.0f);
if (maskLayer) {
- // Because the RenderSurface is sized base on the screen footprint,
- // there can be a scale between the RenderSurface and the owning layer,
- // as well as the mask. While the mask doesn't have a drawTransform, the
- // owning layer has it (and should be pure scaling), so use that to
- // scale the mask to the right size.
- gfx::Vector2dF maskDrawScale = MathUtil::computeTransform2dScaleComponents(m_owningLayer->drawTransform(), 1.f);
- float scaleX = contentRect().width() / maskLayer->contentsScaleX() / maskLayer->bounds().width() / maskDrawScale.x();
- float scaleY = contentRect().height() / maskLayer->contentsScaleY() / maskLayer->bounds().height() / maskDrawScale.y();
-
- maskUVRect = gfx::RectF(static_cast<float>(contentRect().x()) / contentRect().width() * scaleX,
- static_cast<float>(contentRect().y()) / contentRect().height() * scaleY,
- scaleX,
- scaleY);
+ gfx::Vector2dF owningLayerDrawScale = MathUtil::computeTransform2dScaleComponents(m_owningLayer->drawTransform(), 1.f);
+ gfx::SizeF unclippedSurfaceSize = gfx::ScaleSize(
+ m_owningLayer->contentBounds(),
+ owningLayerDrawScale.x(),
+ owningLayerDrawScale.y());
+ // This assumes that the owning layer clips its subtree when a mask is
+ // present.
+ DCHECK(gfx::RectF(unclippedSurfaceSize).Contains(contentRect()));
+
+ float uvScaleX = contentRect().width() / unclippedSurfaceSize.width();
+ float uvScaleY = contentRect().height() / unclippedSurfaceSize.height();
+
+ maskUVRect = gfx::RectF(
+ static_cast<float>(contentRect().x()) / contentRect().width() * uvScaleX,
+ static_cast<float>(contentRect().y()) / contentRect().height() * uvScaleY,
+ uvScaleX,
+ uvScaleY);
}
ResourceProvider::ResourceId maskResourceId = maskLayer ? maskLayer->contentsResourceId() : 0;