summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorenne@chromium.org <enne@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-11-09 22:37:09 +0000
committerenne@chromium.org <enne@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-11-09 22:37:09 +0000
commit3621e18952f50baff1781886ba9997aa6d931877 (patch)
tree9264738355870a83c9fb49c4e6a4fe306039e04d
parent78449d188a8fd1883e450fa00d07872239043c08 (diff)
downloadchromium_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.cc68
-rw-r--r--cc/picture.h29
-rw-r--r--cc/picture_layer.cc20
-rw-r--r--cc/picture_layer.h6
-rw-r--r--cc/picture_layer_impl.cc13
-rw-r--r--cc/picture_layer_impl.h8
-rw-r--r--cc/picture_pile.cc90
-rw-r--r--cc/picture_pile.h24
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);
};