summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--cc/layer_impl.cc5
-rw-r--r--cc/layer_impl.h3
-rw-r--r--cc/layer_tree_host.cc5
-rw-r--r--cc/layer_tree_host.h4
-rw-r--r--cc/layer_tree_host_impl.cc26
-rw-r--r--cc/layer_tree_host_impl.h6
-rw-r--r--cc/layer_tree_host_unittest.cc69
-rw-r--r--cc/picture.h2
-rw-r--r--cc/picture_layer_impl.cc4
-rw-r--r--cc/picture_layer_impl.h3
-rw-r--r--cc/picture_pile_impl.cc25
-rw-r--r--cc/picture_pile_impl.h4
-rw-r--r--cc/proxy.h6
-rw-r--r--cc/single_thread_proxy.cc7
-rw-r--r--cc/single_thread_proxy.h1
-rw-r--r--cc/test/fake_proxy.cc5
-rw-r--r--cc/test/fake_proxy.h1
-rw-r--r--cc/thread_proxy.cc23
-rw-r--r--cc/thread_proxy.h2
19 files changed, 199 insertions, 2 deletions
diff --git a/cc/layer_impl.cc b/cc/layer_impl.cc
index c588fe2..9840eff 100644
--- a/cc/layer_impl.cc
+++ b/cc/layer_impl.cc
@@ -287,6 +287,11 @@ gfx::Rect LayerImpl::layerRectToContentRect(const gfx::RectF& layerRect) const
return gfx::ToEnclosingRect(contentRect);
}
+skia::RefPtr<SkPicture> LayerImpl::getPicture()
+{
+ return skia::RefPtr<SkPicture>();
+}
+
std::string LayerImpl::indentString(int indent)
{
std::string str;
diff --git a/cc/layer_impl.h b/cc/layer_impl.h
index 2219cf7..8b43f9f 100644
--- a/cc/layer_impl.h
+++ b/cc/layer_impl.h
@@ -24,6 +24,7 @@
#include "third_party/WebKit/Source/Platform/chromium/public/WebFilterOperations.h"
#include "third_party/skia/include/core/SkColor.h"
#include "third_party/skia/include/core/SkImageFilter.h"
+#include "third_party/skia/include/core/SkPicture.h"
#include "ui/gfx/rect.h"
#include "ui/gfx/rect_f.h"
#include "ui/gfx/transform.h"
@@ -288,6 +289,8 @@ public:
gfx::Rect layerRectToContentRect(const gfx::RectF& layerRect) const;
+ virtual skia::RefPtr<SkPicture> getPicture();
+
protected:
LayerImpl(LayerTreeImpl* layerImpl, int);
diff --git a/cc/layer_tree_host.cc b/cc/layer_tree_host.cc
index 9a42c63..862cccd 100644
--- a/cc/layer_tree_host.cc
+++ b/cc/layer_tree_host.cc
@@ -890,4 +890,9 @@ void LayerTreeHost::setAnimationEventsRecursive(const AnimationEventsVector& eve
setAnimationEventsRecursive(events, layer->children()[childIndex].get(), wallClockTime);
}
+skia::RefPtr<SkPicture> LayerTreeHost::capturePicture()
+{
+ return m_proxy->capturePicture();
+}
+
} // namespace cc
diff --git a/cc/layer_tree_host.h b/cc/layer_tree_host.h
index 664c92a..67ac48c 100644
--- a/cc/layer_tree_host.h
+++ b/cc/layer_tree_host.h
@@ -24,7 +24,9 @@
#include "cc/rate_limiter.h"
#include "cc/rendering_stats.h"
#include "cc/scoped_ptr_vector.h"
+#include "skia/ext/refptr.h"
#include "third_party/skia/include/core/SkColor.h"
+#include "third_party/skia/include/core/SkPicture.h"
#include "ui/gfx/rect.h"
#if defined(COMPILER_GCC)
@@ -199,6 +201,8 @@ public:
AnimationRegistrar* animationRegistrar() const { return m_animationRegistrar.get(); }
+ skia::RefPtr<SkPicture> capturePicture();
+
protected:
LayerTreeHost(LayerTreeHostClient*, const LayerTreeSettings&);
bool initialize(scoped_ptr<Thread> implThread);
diff --git a/cc/layer_tree_host_impl.cc b/cc/layer_tree_host_impl.cc
index 9d42698..9c217b0 100644
--- a/cc/layer_tree_host_impl.cc
+++ b/cc/layer_tree_host_impl.cc
@@ -1709,4 +1709,30 @@ void LayerTreeHostImpl::animateScrollbarsRecursive(LayerImpl* layer, base::TimeT
animateScrollbarsRecursive(layer->children()[i], time);
}
+// static
+LayerImpl* LayerTreeHostImpl::getNonCompositedContentLayerRecursive(LayerImpl* layer)
+{
+ if (!layer)
+ return NULL;
+
+ if (layer->drawsContent())
+ return layer;
+
+ for (LayerImpl::LayerList::const_iterator it = layer->children().begin();
+ it != layer->children().end(); ++it) {
+ LayerImpl* nccr = getNonCompositedContentLayerRecursive(*it);
+ if (nccr)
+ return nccr;
+ }
+
+ return NULL;
+}
+
+skia::RefPtr<SkPicture> LayerTreeHostImpl::capturePicture()
+{
+ LayerTreeImpl* tree = pendingTree() ? pendingTree() : activeTree();
+ LayerImpl* layer = getNonCompositedContentLayerRecursive(tree->RootLayer());
+ return layer ? layer->getPicture() : skia::RefPtr<SkPicture>();
+}
+
} // namespace cc
diff --git a/cc/layer_tree_host_impl.h b/cc/layer_tree_host_impl.h
index 5f46811..4091d48 100644
--- a/cc/layer_tree_host_impl.h
+++ b/cc/layer_tree_host_impl.h
@@ -17,7 +17,9 @@
#include "cc/render_pass_sink.h"
#include "cc/renderer.h"
#include "cc/tile_manager.h"
+#include "skia/ext/refptr.h"
#include "third_party/skia/include/core/SkColor.h"
+#include "third_party/skia/include/core/SkPicture.h"
#include "ui/gfx/rect.h"
namespace cc {
@@ -300,6 +302,8 @@ public:
const PinchZoomViewport& pinchZoomViewport() const { return m_pinchZoomViewport; }
+ skia::RefPtr<SkPicture> capturePicture();
+
protected:
LayerTreeHostImpl(const LayerTreeSettings&, LayerTreeHostImplClient*, Proxy*);
void activatePendingTree();
@@ -346,6 +350,8 @@ private:
void dumpRenderSurfaces(std::string*, int indent, const LayerImpl*) const;
+ static LayerImpl* getNonCompositedContentLayerRecursive(LayerImpl* layer);
+
scoped_ptr<OutputSurface> m_outputSurface;
scoped_ptr<ResourceProvider> m_resourceProvider;
scoped_ptr<Renderer> m_renderer;
diff --git a/cc/layer_tree_host_unittest.cc b/cc/layer_tree_host_unittest.cc
index de4035a..703217d 100644
--- a/cc/layer_tree_host_unittest.cc
+++ b/cc/layer_tree_host_unittest.cc
@@ -11,6 +11,7 @@
#include "cc/layer_tree_host_impl.h"
#include "cc/layer_tree_impl.h"
#include "cc/output_surface.h"
+#include "cc/picture_layer.h"
#include "cc/prioritized_resource.h"
#include "cc/single_thread_proxy.h"
#include "cc/test/fake_content_layer.h"
@@ -24,10 +25,12 @@
#include "cc/resource_update_queue.h"
#include "cc/test/occlusion_tracker_test_common.h"
#include "cc/timing_function.h"
+#include "skia/ext/refptr.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "third_party/WebKit/Source/Platform/chromium/public/WebSize.h"
#include "third_party/khronos/GLES2/gl2.h"
#include "third_party/khronos/GLES2/gl2ext.h"
+#include "third_party/skia/include/core/SkPicture.h"
#include "ui/gfx/point_conversions.h"
#include "ui/gfx/size_conversions.h"
#include "ui/gfx/vector2d_conversions.h"
@@ -2019,5 +2022,71 @@ TEST(LayerTreeHostTest, PartialUpdatesWithDelegatingRendererAndSoftwareContent)
EXPECT_EQ(0u, host->settings().maxPartialTextureUpdates);
}
+class LayerTreeHostTestCapturePicture : public LayerTreeHostTest {
+public:
+ LayerTreeHostTestCapturePicture()
+ : m_bounds(gfx::Size(100, 100))
+ , m_layer(PictureLayer::create(&m_contentClient))
+ {
+ m_settings.implSidePainting = true;
+ }
+
+ class FillRectContentLayerClient : public ContentLayerClient {
+ public:
+ virtual void paintContents(SkCanvas* canvas, const gfx::Rect& clip, gfx::RectF& opaque) OVERRIDE
+ {
+ SkPaint paint;
+ paint.setColor(SK_ColorGREEN);
+
+ SkRect rect = SkRect::MakeWH(canvas->getDeviceSize().width(), canvas->getDeviceSize().height());
+ opaque = gfx::RectF(rect.width(), rect.height());
+ canvas->drawRect(rect, paint);
+ }
+ };
+
+ virtual void beginTest() OVERRIDE
+ {
+ m_layer->setIsDrawable(true);
+ m_layer->setBounds(m_bounds);
+ m_layerTreeHost->setViewportSize(m_bounds, m_bounds);
+ m_layerTreeHost->setRootLayer(m_layer);
+
+ EXPECT_TRUE(m_layerTreeHost->initializeRendererIfNeeded());
+ postSetNeedsCommitToMainThread();
+ }
+
+ virtual void didCommitAndDrawFrame() OVERRIDE
+ {
+ m_picture = m_layerTreeHost->capturePicture();
+ endTest();
+ }
+
+ virtual void afterTest() OVERRIDE
+ {
+ EXPECT_EQ(m_bounds, gfx::Size(m_picture->width(), m_picture->height()));
+
+ SkBitmap bitmap;
+ bitmap.setConfig(SkBitmap::kARGB_8888_Config, m_bounds.width(), m_bounds.height());
+ bitmap.allocPixels();
+ bitmap.eraseARGB(0, 0, 0, 0);
+ SkCanvas canvas(bitmap);
+
+ m_picture->draw(&canvas);
+
+ bitmap.lockPixels();
+ SkColor* pixels = reinterpret_cast<SkColor*>(bitmap.getPixels());
+ EXPECT_EQ(SK_ColorGREEN, pixels[0]);
+ bitmap.unlockPixels();
+ }
+
+private:
+ gfx::Size m_bounds;
+ FillRectContentLayerClient m_contentClient;
+ scoped_refptr<PictureLayer> m_layer;
+ skia::RefPtr<SkPicture> m_picture;
+};
+
+MULTI_THREAD_TEST_F(LayerTreeHostTestCapturePicture);
+
} // namespace
} // namespace cc
diff --git a/cc/picture.h b/cc/picture.h
index 4672c36..cee8b89 100644
--- a/cc/picture.h
+++ b/cc/picture.h
@@ -37,7 +37,7 @@ public:
void Record(ContentLayerClient*, RenderingStats&);
// Has Record() been called yet?
- bool HasRecording() const { return picture_.get(); }
+ bool HasRecording() const { return picture_.get() != NULL; }
// Apply this contents scale and raster the content rect into the canvas.
void Raster(SkCanvas* canvas, gfx::Rect content_rect, float contents_scale);
diff --git a/cc/picture_layer_impl.cc b/cc/picture_layer_impl.cc
index e4c113a..5a6f111 100644
--- a/cc/picture_layer_impl.cc
+++ b/cc/picture_layer_impl.cc
@@ -192,6 +192,10 @@ void PictureLayerImpl::calculateContentsScale(
gfx::ScaleSize(bounds(), max_contents_scale, max_contents_scale));
}
+skia::RefPtr<SkPicture> PictureLayerImpl::getPicture() {
+ return pile_->GetFlattenedPicture();
+}
+
scoped_refptr<Tile> PictureLayerImpl::CreateTile(PictureLayerTiling* tiling,
gfx::Rect rect) {
TileManager* tile_manager = layerTreeImpl()->tile_manager();
diff --git a/cc/picture_layer_impl.h b/cc/picture_layer_impl.h
index 60e2c8d..94c1ac3 100644
--- a/cc/picture_layer_impl.h
+++ b/cc/picture_layer_impl.h
@@ -10,6 +10,8 @@
#include "cc/picture_layer_tiling_set.h"
#include "cc/picture_pile_impl.h"
#include "cc/scoped_ptr_vector.h"
+#include "skia/ext/refptr.h"
+#include "third_party/skia/include/core/SkPicture.h"
namespace cc {
@@ -35,6 +37,7 @@ public:
float* contents_scale_x,
float* contents_scale_y,
gfx::Size* content_bounds) OVERRIDE;
+ virtual skia::RefPtr<SkPicture> getPicture() OVERRIDE;
// PictureLayerTilingClient overrides.
virtual scoped_refptr<Tile> CreateTile(PictureLayerTiling*,
diff --git a/cc/picture_pile_impl.cc b/cc/picture_pile_impl.cc
index 571dcc6..cb4ff2b 100644
--- a/cc/picture_pile_impl.cc
+++ b/cc/picture_pile_impl.cc
@@ -97,4 +97,29 @@ void PicturePileImpl::GatherPixelRefs(
}
}
+skia::RefPtr<SkPicture> PicturePileImpl::GetFlattenedPicture() {
+ TRACE_EVENT0("cc", "PicturePileImpl::GetFlattenedPicture");
+
+ gfx::Rect layer_rect;
+ for (PicturePile::Pile::const_iterator i = pile_.begin();
+ i != pile_.end(); ++i) {
+ layer_rect.Union((*i)->LayerRect());
+ }
+
+ skia::RefPtr<SkPicture> picture = skia::AdoptRef(new SkPicture);
+ if (layer_rect.IsEmpty())
+ return picture;
+
+ SkCanvas* canvas = picture->beginRecording(
+ layer_rect.width(),
+ layer_rect.height(),
+ SkPicture::kUsePathBoundsForClip_RecordingFlag);
+
+ RenderingStats stats;
+ Raster(canvas, layer_rect, 1.0, &stats);
+ picture->endRecording();
+
+ return picture;
+}
+
} // namespace cc
diff --git a/cc/picture_pile_impl.h b/cc/picture_pile_impl.h
index b20d2c9..9418e90 100644
--- a/cc/picture_pile_impl.h
+++ b/cc/picture_pile_impl.h
@@ -15,6 +15,8 @@
#include "cc/picture.h"
#include "cc/picture_pile.h"
#include "cc/scoped_ptr_vector.h"
+#include "skia/ext/refptr.h"
+#include "third_party/skia/include/core/SkPicture.h"
#include "ui/gfx/rect.h"
namespace cc {
@@ -41,6 +43,8 @@ public:
void GatherPixelRefs(const gfx::Rect&, std::list<skia::LazyPixelRef*>&);
+ skia::RefPtr<SkPicture> GetFlattenedPicture();
+
private:
friend class PicturePile;
diff --git a/cc/proxy.h b/cc/proxy.h
index 253dbd7..f84a3f3 100644
--- a/cc/proxy.h
+++ b/cc/proxy.h
@@ -7,9 +7,11 @@
#include "base/basictypes.h"
#include "base/logging.h"
-#include "base/time.h"
#include "base/memory/scoped_ptr.h"
+#include "base/time.h"
#include "cc/cc_export.h"
+#include "skia/ext/refptr.h"
+#include "third_party/skia/include/core/SkPicture.h"
namespace gfx {
class Rect;
@@ -96,6 +98,8 @@ public:
virtual void acquireLayerTextures() = 0;
+ virtual skia::RefPtr<SkPicture> capturePicture() = 0;
+
// Testing hooks
virtual bool commitPendingForTesting() = 0;
diff --git a/cc/single_thread_proxy.cc b/cc/single_thread_proxy.cc
index 33a3f58..9cccd0ff 100644
--- a/cc/single_thread_proxy.cc
+++ b/cc/single_thread_proxy.cc
@@ -398,4 +398,11 @@ bool SingleThreadProxy::commitPendingForTesting()
return false;
}
+skia::RefPtr<SkPicture> SingleThreadProxy::capturePicture()
+{
+ // Requires impl-side painting, which is only supported in threaded compositing.
+ NOTREACHED();
+ return skia::RefPtr<SkPicture>();
+}
+
} // namespace cc
diff --git a/cc/single_thread_proxy.h b/cc/single_thread_proxy.h
index 5e0a92a..b4e1ad9 100644
--- a/cc/single_thread_proxy.h
+++ b/cc/single_thread_proxy.h
@@ -45,6 +45,7 @@ public:
virtual void acquireLayerTextures() OVERRIDE { }
virtual void forceSerializeOnSwapBuffers() OVERRIDE;
virtual bool commitPendingForTesting() OVERRIDE;
+ virtual skia::RefPtr<SkPicture> capturePicture() OVERRIDE;
// LayerTreeHostImplClient implementation
virtual void didLoseOutputSurfaceOnImplThread() OVERRIDE { }
diff --git a/cc/test/fake_proxy.cc b/cc/test/fake_proxy.cc
index 8b6315a..df382b8 100644
--- a/cc/test/fake_proxy.cc
+++ b/cc/test/fake_proxy.cc
@@ -61,4 +61,9 @@ bool FakeProxy::commitPendingForTesting()
return false;
}
+skia::RefPtr<SkPicture> FakeProxy::capturePicture()
+{
+ return skia::RefPtr<SkPicture>();
+}
+
} // namespace cc
diff --git a/cc/test/fake_proxy.h b/cc/test/fake_proxy.h
index e28ab33..6951a6c 100644
--- a/cc/test/fake_proxy.h
+++ b/cc/test/fake_proxy.h
@@ -38,6 +38,7 @@ public:
virtual size_t maxPartialTextureUpdates() const OVERRIDE;
virtual void acquireLayerTextures() OVERRIDE { }
virtual bool commitPendingForTesting() OVERRIDE;
+ virtual skia::RefPtr<SkPicture> capturePicture() OVERRIDE;
virtual RendererCapabilities& rendererCapabilities();
void setMaxPartialTextureUpdates(size_t);
diff --git a/cc/thread_proxy.cc b/cc/thread_proxy.cc
index 68bb890..6979a15 100644
--- a/cc/thread_proxy.cc
+++ b/cc/thread_proxy.cc
@@ -1017,4 +1017,27 @@ void ThreadProxy::commitPendingOnImplThreadForTesting(CommitPendingRequest* requ
request->completion.signal();
}
+skia::RefPtr<SkPicture> ThreadProxy::capturePicture()
+{
+ DCHECK(isMainThread());
+ CompletionEvent completion;
+ skia::RefPtr<SkPicture> picture;
+ {
+ DebugScopedSetMainThreadBlocked mainThreadBlocked(this);
+ Proxy::implThread()->postTask(base::Bind(&ThreadProxy::capturePictureOnImplThread,
+ m_implThreadWeakPtr,
+ &completion,
+ &picture));
+ completion.wait();
+ }
+ return picture;
+}
+
+void ThreadProxy::capturePictureOnImplThread(CompletionEvent* completion, skia::RefPtr<SkPicture>* picture)
+{
+ DCHECK(isImplThread());
+ *picture = m_layerTreeHostImpl->capturePicture();
+ completion->signal();
+}
+
} // namespace cc
diff --git a/cc/thread_proxy.h b/cc/thread_proxy.h
index 39bbb16..500ee1c 100644
--- a/cc/thread_proxy.h
+++ b/cc/thread_proxy.h
@@ -54,6 +54,7 @@ public:
virtual void acquireLayerTextures() OVERRIDE;
virtual void forceSerializeOnSwapBuffers() OVERRIDE;
virtual bool commitPendingForTesting() OVERRIDE;
+ virtual skia::RefPtr<SkPicture> capturePicture() OVERRIDE;
// LayerTreeHostImplClient implementation
virtual void didLoseOutputSurfaceOnImplThread() OVERRIDE;
@@ -133,6 +134,7 @@ private:
void forceSerializeOnSwapBuffersOnImplThread(CompletionEvent*);
void setNeedsForcedCommitOnImplThread();
void commitPendingOnImplThreadForTesting(CommitPendingRequest* request);
+ void capturePictureOnImplThread(CompletionEvent*, skia::RefPtr<SkPicture>*);
// Accessed on main thread only.
bool m_animateRequested; // Set only when setNeedsAnimate is called.