Commit 6a41ea0c authored by alokp@chromium.org's avatar alokp@chromium.org

cc: Let skia veto gpu rasterization.

Once gpu rasterization is disabled on a layer, it will stay disabled.

BUG=329722

Review URL: https://codereview.chromium.org/222903005

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@262994 0039d316-1c4b-4281-b951-d872f2087c98
parent bca53b0d
......@@ -20,7 +20,7 @@ PictureLayer::PictureLayer(ContentLayerClient* client)
pile_(make_scoped_refptr(new PicturePile())),
instrumentation_object_tracker_(id()),
is_mask_(false),
has_gpu_rasterization_hint_(false),
has_gpu_rasterization_hint_(TRIBOOL_UNKNOWN),
update_source_frame_number_(-1) {}
PictureLayer::~PictureLayer() {
......@@ -50,7 +50,7 @@ void PictureLayer::PushPropertiesTo(LayerImpl* base_layer) {
}
layer_impl->SetIsMask(is_mask_);
layer_impl->SetHasGpuRasterizationHint(has_gpu_rasterization_hint_);
layer_impl->SetUseGpuRasterization(ShouldUseGpuRasterization());
// Unlike other properties, invalidation must always be set on layer_impl.
// See PictureLayerImpl::PushPropertiesTo for more details.
......@@ -138,11 +138,37 @@ void PictureLayer::SetIsMask(bool is_mask) {
}
void PictureLayer::SetHasGpuRasterizationHint(bool has_hint) {
DCHECK(IsPropertyChangeAllowed());
if (has_gpu_rasterization_hint_ == has_hint)
return;
has_gpu_rasterization_hint_ = has_hint;
SetNeedsCommit();
switch (has_gpu_rasterization_hint_) {
case TRIBOOL_UNKNOWN: // Fall-through.
case TRIBOOL_TRUE:
has_gpu_rasterization_hint_ = has_hint ? TRIBOOL_TRUE : TRIBOOL_FALSE;
break;
case TRIBOOL_FALSE:
// GPU rasterization cannot be enabled once disabled.
// This is done to prevent frequent invalidations and visual flashing.
break;
default:
NOTREACHED();
}
// No need to set needs commit or push-properties.
// If only the hint changes and the layer is still valid, there is no need
// to invalidate the rasterization for the whole layer. If there is an
// invalidation (current or future) we will re-raster everything so that it
// is consistent across the layer.
}
bool PictureLayer::ShouldUseGpuRasterization() const {
switch (layer_tree_host()->settings().rasterization_site) {
case LayerTreeSettings::CpuRasterization:
return false;
case LayerTreeSettings::HybridRasterization:
return has_gpu_rasterization_hint_ == TRIBOOL_TRUE &&
pile_->is_suitable_for_gpu_rasterization();
case LayerTreeSettings::GpuRasterization:
return true;
}
NOTREACHED();
return false;
}
bool PictureLayer::SupportsLCDText() const {
......
......@@ -41,6 +41,9 @@ class CC_EXPORT PictureLayer : public Layer {
ContentLayerClient* client() { return client_; }
void SetHasGpuRasterizationHint(bool has_hint);
bool ShouldUseGpuRasterization() const;
PicturePile* GetPicturePileForTesting() const { return pile_.get(); }
protected:
explicit PictureLayer(ContentLayerClient* client);
......@@ -57,7 +60,9 @@ class CC_EXPORT PictureLayer : public Layer {
Region pile_invalidation_;
gfx::Rect last_updated_visible_content_rect_;
bool is_mask_;
bool has_gpu_rasterization_hint_;
enum TriBool { TRIBOOL_UNKNOWN, TRIBOOL_FALSE, TRIBOOL_TRUE };
TriBool has_gpu_rasterization_hint_;
int update_source_frame_number_;
......
......@@ -54,8 +54,8 @@ PictureLayerImpl::PictureLayerImpl(LayerTreeImpl* tree_impl, int id)
is_using_lcd_text_(tree_impl->settings().can_use_lcd_text),
needs_post_commit_initialization_(true),
should_update_tile_priorities_(false),
has_gpu_rasterization_hint_(false),
should_use_low_res_tiling_(tree_impl->settings().create_low_res_tiling),
use_gpu_rasterization_(false),
layer_needs_to_register_itself_(true) {}
PictureLayerImpl::~PictureLayerImpl() {
......@@ -96,7 +96,7 @@ void PictureLayerImpl::PushPropertiesTo(LayerImpl* base_layer) {
layer_impl->SetIsMask(is_mask_);
layer_impl->pile_ = pile_;
layer_impl->SetHasGpuRasterizationHint(has_gpu_rasterization_hint_);
layer_impl->use_gpu_rasterization_ = use_gpu_rasterization_;
// Tilings would be expensive to push, so we swap.
layer_impl->tilings_.swap(tilings_);
......@@ -490,24 +490,12 @@ skia::RefPtr<SkPicture> PictureLayerImpl::GetPicture() {
return pile_->GetFlattenedPicture();
}
void PictureLayerImpl::SetHasGpuRasterizationHint(bool has_hint) {
bool old_should_use_gpu_rasterization = ShouldUseGpuRasterization();
has_gpu_rasterization_hint_ = has_hint;
if (ShouldUseGpuRasterization() != old_should_use_gpu_rasterization)
RemoveAllTilings();
}
void PictureLayerImpl::SetUseGpuRasterization(bool use_gpu) {
if (use_gpu_rasterization_ == use_gpu)
return;
bool PictureLayerImpl::ShouldUseGpuRasterization() const {
switch (layer_tree_impl()->settings().rasterization_site) {
case LayerTreeSettings::CpuRasterization:
return false;
case LayerTreeSettings::HybridRasterization:
return has_gpu_rasterization_hint_;
case LayerTreeSettings::GpuRasterization:
return true;
}
NOTREACHED();
return false;
use_gpu_rasterization_ = use_gpu;
RemoveAllTilings();
}
scoped_refptr<Tile> PictureLayerImpl::CreateTile(PictureLayerTiling* tiling,
......
......@@ -129,8 +129,8 @@ class CC_EXPORT PictureLayerImpl
virtual void RunMicroBenchmark(MicroBenchmarkImpl* benchmark) OVERRIDE;
void SetHasGpuRasterizationHint(bool has_hint);
bool ShouldUseGpuRasterization() const;
void SetUseGpuRasterization(bool use_gpu);
bool ShouldUseGpuRasterization() const { return use_gpu_rasterization_; }
// Functions used by tile manager.
void DidUnregisterLayer();
......@@ -208,8 +208,8 @@ class CC_EXPORT PictureLayerImpl
// A sanity state check to make sure UpdateTilePriorities only gets called
// after a CalculateContentsScale/ManageTilings.
bool should_update_tile_priorities_;
bool has_gpu_rasterization_hint_;
bool should_use_low_res_tiling_;
bool use_gpu_rasterization_;
bool layer_needs_to_register_itself_;
......
......@@ -18,8 +18,6 @@
#include "cc/test/fake_picture_layer_impl.h"
#include "cc/test/fake_picture_pile_impl.h"
#include "cc/test/geometry_test_utils.h"
#include "cc/test/gpu_rasterization_settings.h"
#include "cc/test/hybrid_rasterization_settings.h"
#include "cc/test/impl_side_painting_settings.h"
#include "cc/test/mock_quad_culler.h"
#include "cc/test/test_shared_bitmap_manager.h"
......@@ -1634,7 +1632,7 @@ TEST_F(PictureLayerImplTest, SyncTilingAfterReleaseResource) {
EXPECT_EQ(HIGH_RESOLUTION, high_res->resolution());
}
TEST_F(PictureLayerImplTest, TilingWithoutGpuRasterization) {
TEST_F(PictureLayerImplTest, NoLowResTilingWithGpuRasterization) {
gfx::Size default_tile_size(host_impl_.settings().default_tile_size);
gfx::Size layer_bounds(default_tile_size.width() * 4,
default_tile_size.height() * 4);
......@@ -1654,6 +1652,20 @@ TEST_F(PictureLayerImplTest, TilingWithoutGpuRasterization) {
&result_bounds);
// Should have a low-res and a high-res tiling.
ASSERT_EQ(2u, pending_layer_->tilings()->num_tilings());
pending_layer_->SetUseGpuRasterization(true);
EXPECT_TRUE(pending_layer_->ShouldUseGpuRasterization());
EXPECT_EQ(0u, pending_layer_->tilings()->num_tilings());
pending_layer_->CalculateContentsScale(1.f,
1.f,
1.f,
1.f,
false,
&result_scale_x,
&result_scale_y,
&result_bounds);
// Should only have the high-res tiling.
ASSERT_EQ(1u, pending_layer_->tilings()->num_tilings());
}
TEST_F(PictureLayerImplTest, NoTilingIfDoesNotDrawContent) {
......@@ -1768,54 +1780,9 @@ TEST_F(DeferredInitPictureLayerImplTest,
host_impl_.active_tree()->UpdateDrawProperties();
}
class HybridRasterizationPictureLayerImplTest : public PictureLayerImplTest {
public:
HybridRasterizationPictureLayerImplTest()
: PictureLayerImplTest(HybridRasterizationSettings()) {}
};
TEST_F(HybridRasterizationPictureLayerImplTest, Tiling) {
gfx::Size default_tile_size(host_impl_.settings().default_tile_size);
gfx::Size layer_bounds(default_tile_size.width() * 4,
default_tile_size.height() * 4);
float result_scale_x, result_scale_y;
gfx::Size result_bounds;
SetupDefaultTrees(layer_bounds);
EXPECT_FALSE(pending_layer_->ShouldUseGpuRasterization());
EXPECT_EQ(0u, pending_layer_->tilings()->num_tilings());
pending_layer_->CalculateContentsScale(1.f,
1.f,
1.f,
1.f,
false,
&result_scale_x,
&result_scale_y,
&result_bounds);
// Should have a low-res and a high-res tiling.
ASSERT_EQ(2u, pending_layer_->tilings()->num_tilings());
pending_layer_->SetHasGpuRasterizationHint(true);
EXPECT_TRUE(pending_layer_->ShouldUseGpuRasterization());
EXPECT_EQ(0u, pending_layer_->tilings()->num_tilings());
pending_layer_->CalculateContentsScale(1.f,
1.f,
1.f,
1.f,
false,
&result_scale_x,
&result_scale_y,
&result_bounds);
// Should only have the high-res tiling.
ASSERT_EQ(1u, pending_layer_->tilings()->num_tilings());
}
TEST_F(HybridRasterizationPictureLayerImplTest,
HighResTilingDuringAnimationForCpuRasterization) {
TEST_F(PictureLayerImplTest, HighResTilingDuringAnimationForCpuRasterization) {
gfx::Size tile_size(host_impl_.settings().default_tile_size);
SetupDefaultTrees(tile_size);
pending_layer_->SetHasGpuRasterizationHint(false);
active_layer_->SetHasGpuRasterizationHint(false);
float contents_scale = 1.f;
float device_scale = 1.3f;
......@@ -1901,12 +1868,11 @@ TEST_F(HybridRasterizationPictureLayerImplTest,
EXPECT_BOTH_EQ(HighResTiling()->contents_scale(), 4.f);
}
TEST_F(HybridRasterizationPictureLayerImplTest,
HighResTilingDuringAnimationForGpuRasterization) {
TEST_F(PictureLayerImplTest, HighResTilingDuringAnimationForGpuRasterization) {
gfx::Size tile_size(host_impl_.settings().default_tile_size);
SetupDefaultTrees(tile_size);
pending_layer_->SetHasGpuRasterizationHint(true);
active_layer_->SetHasGpuRasterizationHint(true);
pending_layer_->SetUseGpuRasterization(true);
active_layer_->SetUseGpuRasterization(true);
float contents_scale = 1.f;
float device_scale = 1.f;
......@@ -1956,50 +1922,6 @@ TEST_F(HybridRasterizationPictureLayerImplTest,
EXPECT_BOTH_EQ(HighResTiling()->contents_scale(), 4.f);
}
class GpuRasterizationPictureLayerImplTest : public PictureLayerImplTest {
public:
GpuRasterizationPictureLayerImplTest()
: PictureLayerImplTest(GpuRasterizationSettings()) {}
};
TEST_F(GpuRasterizationPictureLayerImplTest, Tiling) {
gfx::Size default_tile_size(host_impl_.settings().default_tile_size);
gfx::Size layer_bounds(default_tile_size.width() * 4,
default_tile_size.height() * 4);
float result_scale_x, result_scale_y;
gfx::Size result_bounds;
SetupDefaultTrees(layer_bounds);
pending_layer_->SetHasGpuRasterizationHint(true);
EXPECT_TRUE(pending_layer_->ShouldUseGpuRasterization());
EXPECT_EQ(0u, pending_layer_->tilings()->num_tilings());
pending_layer_->CalculateContentsScale(1.f,
1.f,
1.f,
1.f,
false,
&result_scale_x,
&result_scale_y,
&result_bounds);
// Should only have the high-res tiling.
ASSERT_EQ(1u, pending_layer_->tilings()->num_tilings());
pending_layer_->SetHasGpuRasterizationHint(false);
EXPECT_TRUE(pending_layer_->ShouldUseGpuRasterization());
// Should still have the high-res tiling.
EXPECT_EQ(1u, pending_layer_->tilings()->num_tilings());
pending_layer_->CalculateContentsScale(1.f,
1.f,
1.f,
1.f,
false,
&result_scale_x,
&result_scale_y,
&result_bounds);
// Should still only have the high-res tiling.
ASSERT_EQ(1u, pending_layer_->tilings()->num_tilings());
}
TEST_F(PictureLayerImplTest, LayerRasterTileIterator) {
gfx::Size tile_size(100, 100);
gfx::Size layer_bounds(1000, 1000);
......
......@@ -10,6 +10,8 @@
#include "cc/test/fake_layer_tree_host.h"
#include "cc/test/fake_picture_layer_impl.h"
#include "cc/test/fake_proxy.h"
#include "cc/test/gpu_rasterization_settings.h"
#include "cc/test/hybrid_rasterization_settings.h"
#include "cc/test/impl_side_painting_settings.h"
#include "cc/trees/occlusion_tracker.h"
#include "cc/trees/single_thread_proxy.h"
......@@ -67,5 +69,86 @@ TEST(PictureLayerTest, NoTilesIfEmptyBounds) {
}
}
TEST(PictureLayerTest, ForcedCpuRaster) {
MockContentLayerClient client;
scoped_refptr<PictureLayer> layer = PictureLayer::Create(&client);
scoped_ptr<FakeLayerTreeHost> host = FakeLayerTreeHost::Create();
host->SetRootLayer(layer);
// The default value is false.
EXPECT_FALSE(layer->ShouldUseGpuRasterization());
// Gpu rasterization cannot be enabled even with raster hint.
layer->SetHasGpuRasterizationHint(true);
EXPECT_FALSE(layer->ShouldUseGpuRasterization());
}
TEST(PictureLayerTest, ForcedGpuRaster) {
MockContentLayerClient client;
scoped_refptr<PictureLayer> layer = PictureLayer::Create(&client);
scoped_ptr<FakeLayerTreeHost> host =
FakeLayerTreeHost::Create(GpuRasterizationSettings());
host->SetRootLayer(layer);
// The default value is true.
EXPECT_TRUE(layer->ShouldUseGpuRasterization());
// Gpu rasterization cannot be disabled even with raster hint.
layer->SetHasGpuRasterizationHint(false);
EXPECT_TRUE(layer->ShouldUseGpuRasterization());
// Gpu rasterization cannot be disabled even with skia veto.
PicturePile* pile = layer->GetPicturePileForTesting();
EXPECT_TRUE(pile->is_suitable_for_gpu_rasterization());
pile->SetUnsuitableForGpuRasterizationForTesting();
EXPECT_TRUE(layer->ShouldUseGpuRasterization());
}
TEST(PictureLayerTest, HybridRaster) {
MockContentLayerClient client;
scoped_refptr<PictureLayer> layer = PictureLayer::Create(&client);
scoped_ptr<FakeLayerTreeHost> host =
FakeLayerTreeHost::Create(HybridRasterizationSettings());
host->SetRootLayer(layer);
// The default value is false.
EXPECT_FALSE(layer->ShouldUseGpuRasterization());
// Gpu rasterization can be enabled first time.
layer->SetHasGpuRasterizationHint(true);
EXPECT_TRUE(layer->ShouldUseGpuRasterization());
// Gpu rasterization can always be disabled.
layer->SetHasGpuRasterizationHint(false);
EXPECT_FALSE(layer->ShouldUseGpuRasterization());
// Gpu rasterization cannot be enabled once disabled.
layer->SetHasGpuRasterizationHint(true);
EXPECT_FALSE(layer->ShouldUseGpuRasterization());
}
TEST(PictureLayerTest, VetoGpuRaster) {
MockContentLayerClient client;
scoped_refptr<PictureLayer> layer = PictureLayer::Create(&client);
scoped_ptr<FakeLayerTreeHost> host =
FakeLayerTreeHost::Create(HybridRasterizationSettings());
host->SetRootLayer(layer);
EXPECT_FALSE(layer->ShouldUseGpuRasterization());
layer->SetHasGpuRasterizationHint(true);
EXPECT_TRUE(layer->ShouldUseGpuRasterization());
// Veto gpu rasterization.
PicturePile* pile = layer->GetPicturePileForTesting();
EXPECT_TRUE(pile->is_suitable_for_gpu_rasterization());
pile->SetUnsuitableForGpuRasterizationForTesting();
EXPECT_FALSE(layer->ShouldUseGpuRasterization());
}
} // namespace
} // namespace cc
......@@ -197,6 +197,19 @@ Picture* Picture::GetCloneForDrawingOnThread(unsigned thread_index) {
return thread_index == clones_.size() ? this : clones_[thread_index].get();
}
bool Picture::IsSuitableForGpuRasterization() const {
DCHECK(picture_);
// TODO(alokp): SkPicture::suitableForGpuRasterization needs a GrContext.
// Ideally this GrContext should be the same as that for rasterizing this
// picture. But we are on the main thread while the rasterization context
// may be on the compositor or raster thread.
// SkPicture::suitableForGpuRasterization is not implemented yet.
// Pass a NULL context for now and discuss with skia folks if the context
// is really needed.
return picture_->suitableForGpuRasterization(NULL);
}
void Picture::CloneForDrawing(int num_threads) {
TRACE_EVENT1("cc", "Picture::CloneForDrawing", "num_threads", num_threads);
......
......@@ -70,6 +70,8 @@ class CC_EXPORT Picture
// Has Record() been called yet?
bool HasRecording() const { return picture_.get() != NULL; }
bool IsSuitableForGpuRasterization() const;
// Apply this scale and raster the negated region into the canvas. See comment
// in PicturePileImpl::RasterCommon for explanation on negated content region.
int Raster(SkCanvas* canvas,
......
......@@ -141,8 +141,7 @@ float ClusterTiles(const std::vector<gfx::Rect>& invalid_tiles,
namespace cc {
PicturePile::PicturePile() {
}
PicturePile::PicturePile() : is_suitable_for_gpu_rasterization_(true) {}
PicturePile::~PicturePile() {
}
......@@ -245,6 +244,14 @@ bool PicturePile::Update(ContentLayerClient* painter,
gather_pixel_refs,
num_raster_threads,
Picture::RECORD_NORMALLY);
// Note the '&&' with previous is-suitable state.
// This means that once a picture-pile becomes unsuitable for gpu
// rasterization due to some content, it will continue to be unsuitable
// even if that content is replaced by gpu-friendly content.
// This is an optimization to avoid iterating though all pictures in
// the pile after each invalidation.
is_suitable_for_gpu_rasterization_ &=
picture->IsSuitableForGpuRasterization();
base::TimeDelta duration =
stats_instrumentation->EndRecording(start_time);
best_duration = std::min(duration, best_duration);
......
......@@ -37,12 +37,21 @@ class CC_EXPORT PicturePile : public PicturePileBase {
show_debug_picture_borders_ = show;
}
bool is_suitable_for_gpu_rasterization() const {
return is_suitable_for_gpu_rasterization_;
}
void SetUnsuitableForGpuRasterizationForTesting() {
is_suitable_for_gpu_rasterization_ = false;
}
protected:
virtual ~PicturePile();
private:
friend class PicturePileImpl;
bool is_suitable_for_gpu_rasterization_;
DISALLOW_COPY_AND_ASSIGN(PicturePile);
};
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment