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:
@ -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
|
||||
|
31
cc/picture.h
31
cc/picture.h
@ -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);
|
||||
};
|
||||
|
Reference in New Issue
Block a user