0

cc: Make Picture/PicturePile handle recording/raster

It's not efficient (or tested), but this should be enough to start being useful
once we add the raster/upload/appendQuads path.

Next steps are probably to add tilings to the PictureLayerImpl.

R=nduca@chromium.org
BUG=155209


Review URL: https://chromiumcodereview.appspot.com/11293188

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@166999 0039d316-1c4b-4281-b951-d872f2087c98
This commit is contained in:
enne@chromium.org
2012-11-09 22:37:09 +00:00
parent 78449d188a
commit 3621e18952
8 changed files with 231 additions and 29 deletions

@ -4,14 +4,80 @@
#include "config.h"
#include "base/debug/trace_event.h"
#include "cc/content_layer_client.h"
#include "cc/picture.h"
#include "cc/rendering_stats.h"
#include "third_party/skia/include/core/SkCanvas.h"
#include "ui/gfx/rect_conversions.h"
namespace cc {
Picture::Picture() {
scoped_refptr<Picture> Picture::Create() {
return make_scoped_refptr(new Picture());
}
Picture::Picture() : picture_(new SkPicture()) {
}
Picture::Picture(SkPicture* picture, gfx::Rect layer_rect,
gfx::Rect opaque_rect) :
layer_rect_(layer_rect),
opaque_rect_(opaque_rect),
picture_(picture) {
}
Picture::~Picture() {
}
scoped_refptr<Picture> Picture::Clone() {
// SkPicture is not thread-safe to rasterize with, so return a thread-safe
// clone of it.
SkPicture* clone = picture_->clone();
return make_scoped_refptr(new Picture(clone, layer_rect_, opaque_rect_));
}
void Picture::Record(ContentLayerClient* painter, gfx::Rect layer_rect,
RenderingStats& stats) {
TRACE_EVENT0("cc", "Picture::Record");
SkCanvas* canvas = picture_->beginRecording(
layer_rect.width(),
layer_rect.height(),
SkPicture::kOptimizeForClippedPlayback_RecordingFlag);
canvas->save();
canvas->translate(SkFloatToScalar(-layer_rect.x()),
SkFloatToScalar(-layer_rect.y()));
SkPaint paint;
paint.setAntiAlias(false);
paint.setXfermodeMode(SkXfermode::kClear_Mode);
SkRect layer_skrect = SkRect::MakeXYWH(layer_rect.x(),
layer_rect.y(),
layer_rect.width(),
layer_rect.height());
canvas->drawRect(layer_skrect, paint);
canvas->clipRect(layer_skrect);
gfx::RectF opaque_layer_rect;
base::TimeTicks beginPaintTime = base::TimeTicks::Now();
painter->paintContents(canvas, layer_rect, opaque_layer_rect);
double delta = (base::TimeTicks::Now() - beginPaintTime).InSecondsF();
stats.totalPaintTimeInSeconds += delta;
canvas->restore();
picture_->endRecording();
opaque_rect_ = gfx::ToEnclosedRect(opaque_layer_rect);
layer_rect_ = layer_rect;
}
void Picture::Raster(SkCanvas* canvas) {
TRACE_EVENT0("cc", "Picture::Raster");
canvas->translate(layer_rect_.x(), layer_rect_.y());
canvas->save();
canvas->drawPicture(*picture_);
canvas->restore();
}
} // namespace cc

@ -14,25 +14,38 @@
namespace cc {
class ContentLayerClient;
struct RenderingStats;
class CC_EXPORT Picture
: public base::RefCountedThreadSafe<Picture> {
public:
scoped_refptr<Picture> create(ContentLayerClient*, gfx::Rect);
static scoped_refptr<Picture> Create();
const gfx::Rect& rect();
scoped_refptr<Picture> clone();
const gfx::Rect& LayerRect() const { return layer_rect_; }
const gfx::Rect& OpaqueRect() const { return opaque_rect_; }
protected:
Picture();
~Picture();
// Make a thread-safe clone for rasterizing with.
scoped_refptr<Picture> Clone();
gfx::Rect m_rect;
SkPicture m_picture;
// Record a paint operation (clobbering any previous recording).
void Record(ContentLayerClient*, gfx::Rect layer_rect, RenderingStats&);
// Raster this Picture's layer_rect into the given canvas.
// Assumes contentsScale have already been applied.
void Raster(SkCanvas* canvas);
private:
friend class base::RefCountedThreadSafe<Picture>;
Picture();
// This constructor assumes SkPicture is already ref'd and transfers
// ownership to this picture.
Picture(SkPicture*, gfx::Rect layer_rect, gfx::Rect opaque_rect);
~Picture();
gfx::Rect layer_rect_;
gfx::Rect opaque_rect_;
SkAutoTUnref<SkPicture> picture_;
friend class base::RefCountedThreadSafe<Picture>;
DISALLOW_COPY_AND_ASSIGN(Picture);
};

@ -6,6 +6,7 @@
#include "cc/picture_layer.h"
#include "cc/picture_layer_impl.h"
#include "ui/gfx/rect_conversions.h"
namespace cc {
@ -28,9 +29,22 @@ scoped_ptr<LayerImpl> PictureLayer::createLayerImpl() {
return PictureLayerImpl::create(id()).PassAs<LayerImpl>();
}
void PictureLayer::pushPropertiesTo(LayerImpl* baseLayerImpl) {
PictureLayerImpl* layerImpl = static_cast<PictureLayerImpl*>(baseLayerImpl);
pile_.pushPropertiesTo(layerImpl->pile_);
void PictureLayer::pushPropertiesTo(LayerImpl* base_layer) {
PictureLayerImpl* layer_impl = static_cast<PictureLayerImpl*>(base_layer);
pile_.PushPropertiesTo(layer_impl->pile_);
// TODO(nduca): Need to invalidate tiles here from pile's invalidation info.
}
void PictureLayer::setNeedsDisplayRect(const gfx::RectF& layer_rect) {
gfx::Rect rect = gfx::ToEnclosedRect(layer_rect);
pile_.Invalidate(rect);
}
void PictureLayer::update(ResourceUpdateQueue&, const OcclusionTracker*,
RenderingStats& stats) {
pile_.Resize(bounds());
pile_.Update(client_, stats);
}
} // namespace cc

@ -7,10 +7,13 @@
#include "cc/layer.h"
#include "cc/picture_pile.h"
#include "cc/occlusion_tracker.h"
namespace cc {
class ContentLayerClient;
class ResourceUpdateQueue;
struct RenderingStats;
class CC_EXPORT PictureLayer : public Layer {
public:
@ -22,6 +25,9 @@ public:
virtual bool drawsContent() const OVERRIDE;
virtual scoped_ptr<LayerImpl> createLayerImpl() OVERRIDE;
virtual void pushPropertiesTo(LayerImpl*) OVERRIDE;
virtual void setNeedsDisplayRect(const gfx::RectF& layerRect) OVERRIDE;
virtual void update(ResourceUpdateQueue&, const OcclusionTracker*,
RenderingStats&) OVERRIDE;
protected:
explicit PictureLayer(ContentLayerClient*);

@ -15,4 +15,17 @@ PictureLayerImpl::PictureLayerImpl(int id) :
PictureLayerImpl::~PictureLayerImpl() {
}
const char* PictureLayerImpl::layerTypeAsString() const {
return "PictureLayer";
}
void PictureLayerImpl::appendQuads(QuadSink&, AppendQuadsData&) {
// TODO(enne): implement me
}
void PictureLayerImpl::dumpLayerProperties(std::string*, int indent) const {
// TODO(enne): implement me
}
} // namespace cc

@ -10,6 +10,9 @@
namespace cc {
struct AppendQuadsData;
class QuadSink;
class CC_EXPORT PictureLayerImpl : public LayerImpl {
public:
static scoped_ptr<PictureLayerImpl> create(int id)
@ -18,6 +21,11 @@ public:
}
virtual ~PictureLayerImpl();
// LayerImpl overrides.
virtual const char* layerTypeAsString() const OVERRIDE;
virtual void appendQuads(QuadSink&, AppendQuadsData&) OVERRIDE;
virtual void dumpLayerProperties(std::string*, int indent) const OVERRIDE;
protected:
PictureLayerImpl(int id);

@ -4,7 +4,10 @@
#include "config.h"
#include <algorithm>
#include "cc/picture_pile.h"
#include "third_party/skia/include/core/SkCanvas.h"
namespace cc {
@ -14,23 +17,94 @@ PicturePile::PicturePile() {
PicturePile::~PicturePile() {
}
void PicturePile::invalidate(gfx::Rect rect) {
// TODO(enne)
void PicturePile::Invalidate(gfx::Rect rect) {
invalidation_.Union(rect);
}
void PicturePile::resize(gfx::Size size) {
// TODO(enne)
class OutOfBoundsPredicate {
public:
OutOfBoundsPredicate(gfx::Size size) : layer_rect_(gfx::Point(), size) { }
bool operator()(const scoped_refptr<Picture>& picture) {
return !picture->LayerRect().Intersects(layer_rect_);
}
gfx::Rect layer_rect_;
};
void PicturePile::Resize(gfx::Size size) {
if (size.width() > size_.width()) {
gfx::Rect invalid(
size_.width(),
0,
size.width() - size_.width(),
size.height());
Invalidate(invalid);
}
if (size.height() > size_.height()) {
gfx::Rect invalid(
0,
size_.height(),
size.width(),
size.height() - size_.height());
Invalidate(invalid);
}
// Remove pictures that aren't in bounds anymore.
if (size.width() < size_.width() || size.height() < size_.height()) {
OutOfBoundsPredicate oob(size);
pile_.erase(std::remove_if(pile_.begin(), pile_.end(), oob), pile_.end());
}
size_ = size;
}
void PicturePile::update(ContentLayerClient* painter) {
// TODO(enne)
void PicturePile::Update(ContentLayerClient* painter, RenderingStats& stats) {
// WebKit paints (i.e. recording) can cause invalidations, so record previous.
invalidation_.Swap(prev_invalidation_);
invalidation_.Clear();
// TODO(enne): Add things to the pile, consolidate if needed, etc...
if (pile_.size() == 0)
pile_.push_back(Picture::Create());
pile_[0]->Record(painter, gfx::Rect(gfx::Point(), size_), stats);
}
void PicturePile::pushPropertiesTo(PicturePile& other) {
other.size_ = size_;
void PicturePile::CopyAllButPile(PicturePile& from, PicturePile& to) {
to.size_ = from.size_;
to.invalidation_ = from.invalidation_;
to.prev_invalidation_ = from.prev_invalidation_;
}
void PicturePile::PushPropertiesTo(PicturePile& other) {
CopyAllButPile(*this, other);
other.pile_.resize(pile_.size());
for (size_t i = 0; i < pile_.size(); ++i)
other.pile_[i] = pile_[i];
}
scoped_ptr<PicturePile> PicturePile::CloneForDrawing() {
scoped_ptr<PicturePile> clone = make_scoped_ptr(new PicturePile);
CopyAllButPile(*this, *clone);
clone->pile_.resize(pile_.size());
for (size_t i = 0; i < pile_.size(); ++i)
clone->pile_[i] = pile_[i]->Clone();
return clone.Pass();
}
void PicturePile::Raster(SkCanvas* canvas, gfx::Rect rect) {
// TODO(enne): do this more efficiently, i.e. top down with Skia clips
canvas->save();
SkRect layer_skrect = SkRect::MakeXYWH(rect.x(), rect.y(),
rect.width(), rect.height());
canvas->clipRect(layer_skrect);
for (size_t i = 0; i < pile_.size(); ++i) {
if (!pile_[i]->LayerRect().Intersects(rect))
continue;
pile_[i]->Raster(canvas);
}
canvas->restore();
}
} // namespace cc

@ -8,12 +8,15 @@
#include "base/basictypes.h"
#include "cc/cc_export.h"
#include "cc/picture.h"
#include "cc/region.h"
#include "cc/scoped_ptr_vector.h"
#include "ui/gfx/rect.h"
#include "ui/gfx/size.h"
namespace cc {
struct RenderingStats;
class CC_EXPORT PicturePile {
public:
PicturePile();
@ -21,27 +24,32 @@ public:
// Mark a portion of the PicturePile as invalid and needing to be re-recorded
// the next time update is called.
void invalidate(gfx::Rect);
void Invalidate(gfx::Rect);
// Resize the PicturePile, invalidating / dropping recorded pictures as necessary.
void resize(gfx::Size);
void Resize(gfx::Size);
// Rerecord parts of the picture that are invalid.
void update(ContentLayerClient* painter);
// Re-record parts of the picture that are invalid.
void Update(ContentLayerClient* painter, RenderingStats&);
// Update other with a shallow copy of this (main => compositor thread commit)
void pushPropertiesTo(PicturePile& other);
void PushPropertiesTo(PicturePile& other);
// Clone a paint-safe version of this picture (with cloned PicturePileRecords)
scoped_ptr<PicturePile> cloneForDrawing(gfx::Rect rect);
scoped_ptr<PicturePile> CloneForDrawing();
// Raster a subrect of this PicturePile into the given canvas.
// It's only safe to call paint on a cloned version.
void paint(SkCanvas* canvas, gfx::Rect rect);
// It is assumed that contentsScale has already been applied to this canvas.
void Raster(SkCanvas* canvas, gfx::Rect rect);
private:
void CopyAllButPile(PicturePile& from, PicturePile& to);
protected:
std::vector<scoped_refptr<Picture> > pile_;
gfx::Size size_;
Region invalidation_;
Region prev_invalidation_;
DISALLOW_COPY_AND_ASSIGN(PicturePile);
};