diff options
author | enne@chromium.org <enne@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-11-09 22:37:09 +0000 |
---|---|---|
committer | enne@chromium.org <enne@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-11-09 22:37:09 +0000 |
commit | 3621e18952f50baff1781886ba9997aa6d931877 (patch) | |
tree | 9264738355870a83c9fb49c4e6a4fe306039e04d | |
parent | 78449d188a8fd1883e450fa00d07872239043c08 (diff) | |
download | chromium_src-3621e18952f50baff1781886ba9997aa6d931877.zip chromium_src-3621e18952f50baff1781886ba9997aa6d931877.tar.gz chromium_src-3621e18952f50baff1781886ba9997aa6d931877.tar.bz2 |
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
-rw-r--r-- | cc/picture.cc | 68 | ||||
-rw-r--r-- | cc/picture.h | 29 | ||||
-rw-r--r-- | cc/picture_layer.cc | 20 | ||||
-rw-r--r-- | cc/picture_layer.h | 6 | ||||
-rw-r--r-- | cc/picture_layer_impl.cc | 13 | ||||
-rw-r--r-- | cc/picture_layer_impl.h | 8 | ||||
-rw-r--r-- | cc/picture_pile.cc | 90 | ||||
-rw-r--r-- | cc/picture_pile.h | 24 |
8 files changed, 230 insertions, 28 deletions
diff --git a/cc/picture.cc b/cc/picture.cc index 3fac26e..f7e0a4e 100644 --- a/cc/picture.cc +++ b/cc/picture.cc @@ -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 diff --git a/cc/picture.h b/cc/picture.h index 86a2dd8..540d5e7 100644 --- a/cc/picture.h +++ b/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: + // Make a thread-safe clone for rasterizing with. + scoped_refptr<Picture> Clone(); + + // 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: 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 m_rect; - SkPicture m_picture; + gfx::Rect layer_rect_; + gfx::Rect opaque_rect_; + SkAutoTUnref<SkPicture> picture_; -private: friend class base::RefCountedThreadSafe<Picture>; - DISALLOW_COPY_AND_ASSIGN(Picture); }; diff --git a/cc/picture_layer.cc b/cc/picture_layer.cc index ff69a2c..1b79a3e 100644 --- a/cc/picture_layer.cc +++ b/cc/picture_layer.cc @@ -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 diff --git a/cc/picture_layer.h b/cc/picture_layer.h index d22d9c2..896d561 100644 --- a/cc/picture_layer.h +++ b/cc/picture_layer.h @@ -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*); diff --git a/cc/picture_layer_impl.cc b/cc/picture_layer_impl.cc index 0da0d20..9f42e12 100644 --- a/cc/picture_layer_impl.cc +++ b/cc/picture_layer_impl.cc @@ -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 diff --git a/cc/picture_layer_impl.h b/cc/picture_layer_impl.h index 53ecec1..e2c7675 100644 --- a/cc/picture_layer_impl.h +++ b/cc/picture_layer_impl.h @@ -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); diff --git a/cc/picture_pile.cc b/cc/picture_pile.cc index a33147b..63858d2 100644 --- a/cc/picture_pile.cc +++ b/cc/picture_pile.cc @@ -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); +} + +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::resize(gfx::Size size) { - // 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::update(ContentLayerClient* painter) { - // TODO(enne) +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) { - other.size_ = size_; +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 diff --git a/cc/picture_pile.h b/cc/picture_pile.h index 5d53974..13a0b43 100644 --- a/cc/picture_pile.h +++ b/cc/picture_pile.h @@ -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); }; |