summaryrefslogtreecommitdiffstats
path: root/cc
diff options
context:
space:
mode:
authorbrianderson@chromium.org <brianderson@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-02-13 04:31:16 +0000
committerbrianderson@chromium.org <brianderson@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-02-13 04:31:16 +0000
commitb64e1d345295c669252c40976c78e3737e447edf (patch)
tree41715dc96ca06af59bce73fc73169ac3f319967e /cc
parent48a8ca3ed1782d239d38fef2ac03765f2d38eb5f (diff)
downloadchromium_src-b64e1d345295c669252c40976c78e3737e447edf.zip
chromium_src-b64e1d345295c669252c40976c78e3737e447edf.tar.gz
chromium_src-b64e1d345295c669252c40976c78e3737e447edf.tar.bz2
cc: Stretch textures by .5 texels to prevent out of bounds sampling
This will allow us to revert texture clamping logic that reduces the fill rate on some devices. Instead of requiring us to clamp texture sampling, this patch stretches textures by .5 texels past quad bounds to avoid blending in invalid texels when GL_LINEAR filtering is used. BUG=173480 Review URL: https://chromiumcodereview.appspot.com/12220133 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@182116 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'cc')
-rw-r--r--cc/picture_layer_impl.cc17
-rw-r--r--cc/picture_layer_impl_unittest.cc12
-rw-r--r--cc/picture_layer_tiling.cc21
-rw-r--r--cc/picture_layer_tiling.h12
-rw-r--r--cc/picture_layer_tiling_set.cc7
-rw-r--r--cc/picture_layer_tiling_set.h7
-rw-r--r--cc/picture_layer_tiling_set_unittest.cc6
-rw-r--r--cc/picture_layer_tiling_unittest.cc9
8 files changed, 68 insertions, 23 deletions
diff --git a/cc/picture_layer_impl.cc b/cc/picture_layer_impl.cc
index 9cf3dca..fc0e9d0 100644
--- a/cc/picture_layer_impl.cc
+++ b/cc/picture_layer_impl.cc
@@ -96,11 +96,17 @@ void PictureLayerImpl::appendQuads(QuadSink& quadSink,
bool isAxisAlignedInTarget = !clipped && target_quad.IsRectilinear();
bool useAA = !isAxisAlignedInTarget;
+ bool isPixelAligned = isAxisAlignedInTarget && drawTransform().IsIdentityOrIntegerTranslation();
+ PictureLayerTiling::LayerDeviceAlignment layerDeviceAlignment =
+ isPixelAligned ? PictureLayerTiling::LayerAlignedToDevice
+ : PictureLayerTiling::LayerNotAlignedToDevice;
+
if (showDebugBorders()) {
for (PictureLayerTilingSet::Iterator iter(tilings_.get(),
contentsScaleX(),
rect,
- ideal_contents_scale_);
+ ideal_contents_scale_,
+ layerDeviceAlignment);
iter;
++iter) {
SkColor color;
@@ -139,7 +145,8 @@ void PictureLayerImpl::appendQuads(QuadSink& quadSink,
for (PictureLayerTilingSet::Iterator iter(tilings_.get(),
contentsScaleX(),
rect,
- ideal_contents_scale_);
+ ideal_contents_scale_,
+ layerDeviceAlignment);
iter;
++iter) {
ResourceProvider::ResourceId resource = 0;
@@ -431,7 +438,8 @@ ResourceProvider::ResourceId PictureLayerImpl::contentsResourceId() const {
for (PictureLayerTilingSet::Iterator iter(tilings_.get(),
scale,
content_rect,
- ideal_contents_scale_);
+ ideal_contents_scale_,
+ PictureLayerTiling::LayerDeviceAlignmentUnknown);
iter;
++iter) {
// Mask resource not ready yet.
@@ -479,7 +487,8 @@ bool PictureLayerImpl::areVisibleResourcesReady() const {
for (PictureLayerTiling::Iterator iter(tiling,
contentsScaleX(),
- rect);
+ rect,
+ PictureLayerTiling::LayerDeviceAlignmentUnknown);
iter;
++iter) {
// A null tile (i.e. no recording) is considered "ready".
diff --git a/cc/picture_layer_impl_unittest.cc b/cc/picture_layer_impl_unittest.cc
index c1845ce..b4b9f4c 100644
--- a/cc/picture_layer_impl_unittest.cc
+++ b/cc/picture_layer_impl_unittest.cc
@@ -174,7 +174,8 @@ class PictureLayerImplTest : public testing::Test {
PicturePileImpl* pile) {
for (PictureLayerTiling::Iterator iter(tiling,
tiling->contents_scale(),
- tiling->ContentRect());
+ tiling->ContentRect(),
+ PictureLayerTiling::LayerDeviceAlignmentUnknown);
iter; ++iter) {
EXPECT_TRUE(*iter);
EXPECT_EQ(pile, iter->picture_pile());
@@ -249,7 +250,8 @@ TEST_F(PictureLayerImplTest, clonePartialInvalidation) {
tiling->contents_scale()));
for (PictureLayerTiling::Iterator iter(tiling,
tiling->contents_scale(),
- tiling->ContentRect());
+ tiling->ContentRect(),
+ PictureLayerTiling::LayerDeviceAlignmentUnknown);
iter; ++iter) {
EXPECT_TRUE(*iter);
EXPECT_FALSE(iter.geometry_rect().IsEmpty());
@@ -309,7 +311,8 @@ TEST_F(PictureLayerImplTest, noInvalidationBoundsChange) {
tiling->contents_scale()));
for (PictureLayerTiling::Iterator iter(tiling,
tiling->contents_scale(),
- tiling->ContentRect());
+ tiling->ContentRect(),
+ PictureLayerTiling::LayerDeviceAlignmentUnknown);
iter; ++iter) {
EXPECT_TRUE(*iter);
EXPECT_FALSE(iter.geometry_rect().IsEmpty());
@@ -358,7 +361,8 @@ TEST_F(PictureLayerImplTest, addTilesFromNewRecording) {
for (PictureLayerTiling::Iterator iter(tiling,
tiling->contents_scale(),
- tiling->ContentRect());
+ tiling->ContentRect(),
+ PictureLayerTiling::LayerDeviceAlignmentUnknown);
iter; ++iter) {
EXPECT_FALSE(iter.full_tile_geometry_rect().IsEmpty());
// Ensure there is a recording for this tile.
diff --git a/cc/picture_layer_tiling.cc b/cc/picture_layer_tiling.cc
index b63e0cc..9189d46 100644
--- a/cc/picture_layer_tiling.cc
+++ b/cc/picture_layer_tiling.cc
@@ -135,7 +135,8 @@ void PictureLayerTiling::Invalidate(const Region& layer_invalidation) {
gfx::Rect rect =
gfx::ToEnclosingRect(ScaleRect(layer_invalidation, contents_scale_));
- for (PictureLayerTiling::Iterator tile_iter(this, contents_scale_, rect);
+ for (PictureLayerTiling::Iterator tile_iter(this, contents_scale_, rect,
+ PictureLayerTiling::LayerDeviceAlignmentUnknown);
tile_iter;
++tile_iter) {
TileMapKey key(tile_iter.tile_i_, tile_iter.tile_j_);
@@ -182,7 +183,8 @@ PictureLayerTiling::Iterator::Iterator()
PictureLayerTiling::Iterator::Iterator(const PictureLayerTiling* tiling,
float dest_scale,
- gfx::Rect dest_rect)
+ gfx::Rect dest_rect,
+ LayerDeviceAlignment layerDeviceAlignment)
: tiling_(tiling),
dest_rect_(dest_rect),
current_tile_(NULL),
@@ -215,6 +217,21 @@ PictureLayerTiling::Iterator::Iterator(const PictureLayerTiling* tiling,
dest_to_content_scale_y_ = content_size_floor.height() /
static_cast<float>(dest_content_size.height());
+ // It's possible that when drawing a quad with texel:pixel ratio < 1
+ // GL_LINEAR will cause us to blend in invalid texels.
+ // We stretch the content a little more to prevent sampling past the
+ // middle of the last texel.
+ if (layerDeviceAlignment == LayerAlignedToDevice){
+ if (dest_to_content_scale_x_ < 1.0)
+ dest_to_content_scale_x_ -= 0.5f / dest_content_size.width();
+ if (dest_to_content_scale_y_ < 1.0)
+ dest_to_content_scale_y_ -= 0.5f / dest_content_size.height();
+ }
+ else if (layerDeviceAlignment == LayerNotAlignedToDevice) {
+ dest_to_content_scale_x_ -= 0.5f / dest_content_size.width();
+ dest_to_content_scale_y_ -= 0.5f / dest_content_size.height();
+ }
+
gfx::Rect content_rect =
gfx::ToEnclosingRect(gfx::ScaleRect(dest_rect_,
dest_to_content_scale_x_,
diff --git a/cc/picture_layer_tiling.h b/cc/picture_layer_tiling.h
index e357dfd..4c4bb14 100644
--- a/cc/picture_layer_tiling.h
+++ b/cc/picture_layer_tiling.h
@@ -65,6 +65,12 @@ class CC_EXPORT PictureLayerTiling {
return all_tiles;
}
+ enum LayerDeviceAlignment {
+ LayerDeviceAlignmentUnknown,
+ LayerAlignedToDevice,
+ LayerNotAlignedToDevice,
+ };
+
// Iterate over all tiles to fill content_rect. Even if tiles are invalid
// (i.e. no valid resource) this tiling should still iterate over them.
// The union of all geometry_rect calls for each element iterated over should
@@ -72,10 +78,10 @@ class CC_EXPORT PictureLayerTiling {
class CC_EXPORT Iterator {
public:
Iterator();
- Iterator(
- const PictureLayerTiling* tiling,
+ Iterator(const PictureLayerTiling* tiling,
float dest_scale,
- gfx::Rect rect);
+ gfx::Rect rect,
+ LayerDeviceAlignment layerDeviceAlignment);
~Iterator();
// Visible rect (no borders), always in the space of content_rect,
diff --git a/cc/picture_layer_tiling_set.cc b/cc/picture_layer_tiling_set.cc
index c8ce5f4..d2a5349 100644
--- a/cc/picture_layer_tiling_set.cc
+++ b/cc/picture_layer_tiling_set.cc
@@ -106,10 +106,12 @@ PictureLayerTilingSet::Iterator::Iterator(
const PictureLayerTilingSet* set,
float contents_scale,
gfx::Rect content_rect,
- float ideal_contents_scale)
+ float ideal_contents_scale,
+ PictureLayerTiling::LayerDeviceAlignment layerDeviceAlignment)
: set_(set),
contents_scale_(contents_scale),
ideal_contents_scale_(ideal_contents_scale),
+ layer_device_alignment_(layerDeviceAlignment),
current_tiling_(-1) {
missing_region_.Union(content_rect);
@@ -242,7 +244,8 @@ PictureLayerTilingSet::Iterator& PictureLayerTilingSet::Iterator::operator++() {
tiling_iter_ = PictureLayerTiling::Iterator(
set_->tilings_[current_tiling_],
contents_scale_,
- last_rect);
+ last_rect,
+ layer_device_alignment_);
}
return *this;
diff --git a/cc/picture_layer_tiling_set.h b/cc/picture_layer_tiling_set.h
index ef24e41..ef059ab 100644
--- a/cc/picture_layer_tiling_set.h
+++ b/cc/picture_layer_tiling_set.h
@@ -72,11 +72,11 @@ class CC_EXPORT PictureLayerTilingSet {
// exactly fill rect with no overlap.
class CC_EXPORT Iterator {
public:
- Iterator(
- const PictureLayerTilingSet* set,
+ Iterator(const PictureLayerTilingSet* set,
float contents_scale,
gfx::Rect content_rect,
- float ideal_contents_scale);
+ float ideal_contents_scale,
+ PictureLayerTiling::LayerDeviceAlignment layerDeviceAlignment);
~Iterator();
// Visible rect (no borders), always in the space of rect,
@@ -101,6 +101,7 @@ class CC_EXPORT PictureLayerTilingSet {
const PictureLayerTilingSet* set_;
float contents_scale_;
float ideal_contents_scale_;
+ PictureLayerTiling::LayerDeviceAlignment layer_device_alignment_;
PictureLayerTiling::Iterator tiling_iter_;
int current_tiling_;
int ideal_tiling_;
diff --git a/cc/picture_layer_tiling_set_unittest.cc b/cc/picture_layer_tiling_set_unittest.cc
index 17affd7..e3a008b 100644
--- a/cc/picture_layer_tiling_set_unittest.cc
+++ b/cc/picture_layer_tiling_set_unittest.cc
@@ -37,7 +37,8 @@ TEST(PictureLayerTilingSetTest, NoResources) {
&set,
contents_scale,
content_rect,
- contents_scale);
+ contents_scale,
+ PictureLayerTiling::LayerDeviceAlignmentUnknown);
for (; iter; ++iter) {
gfx::Rect geometry_rect = iter.geometry_rect();
EXPECT_TRUE(content_rect.Contains(geometry_rect));
@@ -95,7 +96,8 @@ class PictureLayerTilingSetTestWithResources : public testing::Test {
&set,
max_contents_scale,
content_rect,
- ideal_contents_scale);
+ ideal_contents_scale,
+ PictureLayerTiling::LayerDeviceAlignmentUnknown);
for (; iter; ++iter) {
gfx::Rect geometry_rect = iter.geometry_rect();
EXPECT_TRUE(content_rect.Contains(geometry_rect));
diff --git a/cc/picture_layer_tiling_unittest.cc b/cc/picture_layer_tiling_unittest.cc
index 9e840d9..8b825d1 100644
--- a/cc/picture_layer_tiling_unittest.cc
+++ b/cc/picture_layer_tiling_unittest.cc
@@ -42,7 +42,8 @@ class PictureLayerTilingIteratorTest : public testing::Test {
Region remaining = expect_rect;
for (PictureLayerTiling::Iterator iter(tiling_.get(),
rect_scale,
- request_rect);
+ request_rect,
+ PictureLayerTiling::LayerDeviceAlignmentUnknown);
iter;
++iter) {
@@ -143,14 +144,16 @@ TEST_F(PictureLayerTilingIteratorTest, IteratorEmptyRect) {
Initialize(gfx::Size(100, 100), 1.0f, gfx::Size(800, 600));
gfx::Rect empty;
- PictureLayerTiling::Iterator iter(tiling_.get(), 1.0f, empty);
+ PictureLayerTiling::Iterator iter(tiling_.get(), 1.0f, empty,
+ PictureLayerTiling::LayerDeviceAlignmentUnknown);
EXPECT_FALSE(iter);
}
TEST_F(PictureLayerTilingIteratorTest, NonIntersectingRect) {
Initialize(gfx::Size(100, 100), 1.0f, gfx::Size(800, 600));
gfx::Rect non_intersecting(1000, 1000, 50, 50);
- PictureLayerTiling::Iterator iter(tiling_.get(), 1, non_intersecting);
+ PictureLayerTiling::Iterator iter(tiling_.get(), 1, non_intersecting,
+ PictureLayerTiling::LayerDeviceAlignmentUnknown);
EXPECT_FALSE(iter);
}