summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNicolas Roard <nicolasroard@google.com>2012-03-09 15:48:14 -0800
committerNicolas Roard <nicolasroard@google.com>2012-03-09 17:25:29 -0800
commitb3f4d3af0b06dc168453641e249d0cb9eec9b570 (patch)
tree860279e3446097a24a3b606ff491300134685afe
parent296d05c7bd54360261dedc8d387a7bf9f52ca41b (diff)
downloadexternal_webkit-b3f4d3af0b06dc168453641e249d0cb9eec9b570.zip
external_webkit-b3f4d3af0b06dc168453641e249d0cb9eec9b570.tar.gz
external_webkit-b3f4d3af0b06dc168453641e249d0cb9eec9b570.tar.bz2
Introduce a LayerContent interface
Layers can now use a LayerContent object to draw their content. We currently have two subclasses, one using an SkPicture (currently used for composited layers), the other using a PictureSet (that we use for the base layer). First step toward unification... Change-Id: I5e7fd06a653f02f8721613fd3a39d36fb64a8614
-rw-r--r--Source/WebCore/Android.mk2
-rw-r--r--Source/WebCore/platform/graphics/android/BaseLayerAndroid.cpp23
-rw-r--r--Source/WebCore/platform/graphics/android/BaseLayerAndroid.h8
-rw-r--r--Source/WebCore/platform/graphics/android/GraphicsLayerAndroid.cpp32
-rw-r--r--Source/WebCore/platform/graphics/android/GraphicsLayerAndroid.h3
-rw-r--r--Source/WebCore/platform/graphics/android/LayerAndroid.cpp104
-rw-r--r--Source/WebCore/platform/graphics/android/LayerAndroid.h25
-rw-r--r--Source/WebCore/platform/graphics/android/LayerContent.h51
-rw-r--r--Source/WebCore/platform/graphics/android/PictureLayerContent.cpp103
-rw-r--r--Source/WebCore/platform/graphics/android/PictureLayerContent.h55
-rw-r--r--Source/WebCore/platform/graphics/android/PictureSetLayerContent.cpp35
-rw-r--r--Source/WebCore/platform/graphics/android/PictureSetLayerContent.h53
-rw-r--r--Source/WebKit/android/jni/ViewStateSerializer.cpp26
-rw-r--r--Source/WebKit/android/jni/WebViewCore.cpp6
-rw-r--r--Source/WebKit/android/nav/WebView.cpp10
15 files changed, 406 insertions, 130 deletions
diff --git a/Source/WebCore/Android.mk b/Source/WebCore/Android.mk
index 4884e5b..816b163 100644
--- a/Source/WebCore/Android.mk
+++ b/Source/WebCore/Android.mk
@@ -672,6 +672,8 @@ LOCAL_SRC_FILES := $(LOCAL_SRC_FILES) \
platform/graphics/android/PaintTileOperation.cpp \
platform/graphics/android/PathAndroid.cpp \
platform/graphics/android/PatternAndroid.cpp \
+ platform/graphics/android/PictureLayerContent.cpp \
+ platform/graphics/android/PictureSetLayerContent.cpp \
platform/graphics/android/PlatformGraphicsContext.cpp \
platform/graphics/android/PerformanceMonitor.cpp \
platform/graphics/android/RasterRenderer.cpp \
diff --git a/Source/WebCore/platform/graphics/android/BaseLayerAndroid.cpp b/Source/WebCore/platform/graphics/android/BaseLayerAndroid.cpp
index ded25a7..c9a8b9a 100644
--- a/Source/WebCore/platform/graphics/android/BaseLayerAndroid.cpp
+++ b/Source/WebCore/platform/graphics/android/BaseLayerAndroid.cpp
@@ -68,6 +68,7 @@ using namespace android;
BaseLayerAndroid::BaseLayerAndroid()
#if USE(ACCELERATED_COMPOSITING)
: m_color(Color::white)
+ , m_content(0)
, m_scrollState(NotScrolling)
#endif
{
@@ -78,23 +79,17 @@ BaseLayerAndroid::BaseLayerAndroid()
BaseLayerAndroid::~BaseLayerAndroid()
{
- m_content.clear();
+ SkSafeUnref(m_content);
#ifdef DEBUG_COUNT
ClassTracker::instance()->decrement("BaseLayerAndroid");
#endif
}
-void BaseLayerAndroid::setContent(const PictureSet& src)
+void BaseLayerAndroid::setContent(LayerContent* content)
{
-#if USE(ACCELERATED_COMPOSITING)
- // FIXME: We lock here because we do not want
- // to paint and change the m_content concurrently.
- // We should instead refactor PictureSet to use
- // an atomic refcounting scheme and use atomic operations
- // to swap PictureSets.
- android::Mutex::Autolock lock(m_drawLock);
-#endif
- m_content.set(src);
+ SkSafeRef(content);
+ SkSafeUnref(m_content);
+ m_content = content;
// FIXME: We cannot set the size of the base layer because it will screw up
// the matrix used. We need to fix matrix computation for the base layer
// and then we can set the size.
@@ -103,11 +98,9 @@ void BaseLayerAndroid::setContent(const PictureSet& src)
bool BaseLayerAndroid::drawCanvas(SkCanvas* canvas)
{
-#if USE(ACCELERATED_COMPOSITING)
android::Mutex::Autolock lock(m_drawLock);
-#endif
- if (!m_content.isEmpty())
- m_content.draw(canvas);
+ if (m_content && !m_content->isEmpty())
+ m_content->draw(canvas);
return true;
}
diff --git a/Source/WebCore/platform/graphics/android/BaseLayerAndroid.h b/Source/WebCore/platform/graphics/android/BaseLayerAndroid.h
index e7d0471..a807b8b 100644
--- a/Source/WebCore/platform/graphics/android/BaseLayerAndroid.h
+++ b/Source/WebCore/platform/graphics/android/BaseLayerAndroid.h
@@ -29,6 +29,7 @@
#include "Color.h"
#include "Layer.h"
#include "PictureSet.h"
+#include "LayerContent.h"
namespace WebCore {
@@ -50,8 +51,9 @@ public:
void setBackgroundColor(Color& color) { m_color = color; }
Color getBackgroundColor() { return m_color; }
#endif
- void setContent(const android::PictureSet& src);
- android::PictureSet* content() { return &m_content; }
+ void setContent(LayerContent* content);
+ LayerContent* content() { return m_content; }
+
// This method will paint using the current PictureSet onto
// the passed canvas. We used it to paint the GL tiles as well as
// WebView::copyBaseContentToPicture(), so a lock is necessary as
@@ -78,7 +80,7 @@ private:
android::Mutex m_drawLock;
Color m_color;
#endif
- android::PictureSet m_content;
+ LayerContent* m_content;
ScrollState m_scrollState;
};
diff --git a/Source/WebCore/platform/graphics/android/GraphicsLayerAndroid.cpp b/Source/WebCore/platform/graphics/android/GraphicsLayerAndroid.cpp
index c6a69b7..6bc2dc7 100644
--- a/Source/WebCore/platform/graphics/android/GraphicsLayerAndroid.cpp
+++ b/Source/WebCore/platform/graphics/android/GraphicsLayerAndroid.cpp
@@ -31,6 +31,7 @@
#include "Layer.h"
#include "Length.h"
#include "MediaLayer.h"
+#include "PictureLayerContent.h"
#include "PlatformBridge.h"
#include "PlatformGraphicsContext.h"
#include "RenderLayerBacking.h"
@@ -603,9 +604,8 @@ bool GraphicsLayerAndroid::repaint()
PaintingPhase phase(this);
// Paint the background into a separate context.
phase.set(GraphicsLayerPaintBackground);
- if (!paintContext(m_contentLayer->recordContext(), layerBounds))
+ if (!paintContext(m_contentLayer, layerBounds))
return false;
- m_contentLayer->checkForPictureOptimizations();
// Construct the foreground layer and draw.
RenderBox* box = layer->renderBox();
@@ -625,8 +625,7 @@ bool GraphicsLayerAndroid::repaint()
IntSize scroll = layer->scrolledContentOffset();
layer->scrollToOffset(0, 0);
// At this point, it doesn't matter if painting failed.
- (void) paintContext(m_foregroundLayer->recordContext(), contentsRect);
- m_foregroundLayer->checkForPictureOptimizations();
+ (void) paintContext(m_foregroundLayer, contentsRect);
layer->scrollToOffset(scroll.width(), scroll.height());
// Construct the clip layer for masking the contents.
@@ -661,11 +660,9 @@ bool GraphicsLayerAndroid::repaint()
} else {
// If there is no contents clip, we can draw everything into one
// picture.
- bool painting = paintContext(m_contentLayer->recordContext(), layerBounds);
+ bool painting = paintContext(m_contentLayer, layerBounds);
if (!painting)
return false;
- // We painted new content
- m_contentLayer->checkForPictureOptimizations();
// Check for a scrollable iframe and report the scrolling
// limits based on the view size.
if (m_contentLayer->isIFrameContent()) {
@@ -703,19 +700,32 @@ bool GraphicsLayerAndroid::repaint()
return false;
}
-bool GraphicsLayerAndroid::paintContext(SkPicture* context,
+bool GraphicsLayerAndroid::paintContext(LayerAndroid* layer,
const IntRect& rect)
{
- SkAutoPictureRecord arp(context, rect.width(), rect.height());
- SkCanvas* canvas = arp.getRecordingCanvas();
+ if (!layer)
+ return false;
- if (!canvas)
+ SkPicture* picture = new SkPicture();
+ SkCanvas* canvas = picture->beginRecording(rect.width(), rect.height(), 0);
+ if (!canvas) {
+ picture->endRecording();
+ SkSafeUnref(picture);
return false;
+ }
PlatformGraphicsContext platformContext(canvas);
GraphicsContext graphicsContext(&platformContext);
paintGraphicsLayerContents(graphicsContext, rect);
+
+ picture->endRecording();
+
+ PictureLayerContent* layerContent = new PictureLayerContent(picture);
+ layerContent->checkForOptimisations();
+ layer->setContent(layerContent);
+ SkSafeUnref(layerContent);
+ SkSafeUnref(picture);
return true;
}
diff --git a/Source/WebCore/platform/graphics/android/GraphicsLayerAndroid.h b/Source/WebCore/platform/graphics/android/GraphicsLayerAndroid.h
index 4c049cd..1eb77d6 100644
--- a/Source/WebCore/platform/graphics/android/GraphicsLayerAndroid.h
+++ b/Source/WebCore/platform/graphics/android/GraphicsLayerAndroid.h
@@ -24,6 +24,7 @@
#include "GraphicsLayer.h"
#include "GraphicsLayerClient.h"
#include "LayerAndroid.h"
+#include "LayerContent.h"
#include "RefPtr.h"
#include "ScrollableLayerAndroid.h"
#include "SkBitmapRef.h"
@@ -143,7 +144,7 @@ private:
bool repaint();
void needsNotifyClient();
- bool paintContext(SkPicture* context, const IntRect& rect);
+ bool paintContext(LayerAndroid* layer, const IntRect& rect);
bool m_needsSyncChildren;
bool m_needsSyncMask;
diff --git a/Source/WebCore/platform/graphics/android/LayerAndroid.cpp b/Source/WebCore/platform/graphics/android/LayerAndroid.cpp
index cef3d1c..7886d7b 100644
--- a/Source/WebCore/platform/graphics/android/LayerAndroid.cpp
+++ b/Source/WebCore/platform/graphics/android/LayerAndroid.cpp
@@ -11,9 +11,11 @@
#include "GLUtils.h"
#include "ImagesManager.h"
#include "InspectorCanvas.h"
+#include "LayerContent.h"
#include "LayerGroup.h"
#include "MediaLayer.h"
#include "ParseCanvas.h"
+#include "PictureLayerContent.h"
#include "SkBitmapRef.h"
#include "SkDrawFilter.h"
#include "SkPaint.h"
@@ -72,15 +74,14 @@ LayerAndroid::LayerAndroid(RenderLayer* owner) : Layer(),
m_preserves3D(false),
m_anchorPointZ(0),
m_fixedPosition(0),
- m_recordingPicture(0),
m_zValue(0),
m_uniqueId(++gUniqueId),
+ m_content(0),
m_imageCRC(0),
m_scale(1),
m_lastComputeTextureSize(0),
m_owningLayer(owner),
m_type(LayerAndroid::WebCoreLayer),
- m_hasText(true),
m_intrinsicallyComposited(true),
m_layerGroup(0)
{
@@ -101,7 +102,6 @@ LayerAndroid::LayerAndroid(const LayerAndroid& layer) : Layer(layer),
m_uniqueId(layer.m_uniqueId),
m_owningLayer(layer.m_owningLayer),
m_type(LayerAndroid::UILayer),
- m_hasText(layer.m_hasText),
m_intrinsicallyComposited(layer.m_intrinsicallyComposited),
m_layerGroup(0)
{
@@ -115,8 +115,9 @@ LayerAndroid::LayerAndroid(const LayerAndroid& layer) : Layer(layer),
m_backgroundColor = layer.m_backgroundColor;
m_offset = layer.m_offset;
- m_recordingPicture = layer.m_recordingPicture;
- SkSafeRef(m_recordingPicture);
+
+ m_content = layer.m_content;
+ SkSafeRef(m_content);
m_preserves3D = layer.m_preserves3D;
m_anchorPointZ = layer.m_anchorPointZ;
@@ -146,33 +147,9 @@ LayerAndroid::LayerAndroid(const LayerAndroid& layer) : Layer(layer),
#endif
}
-void LayerAndroid::checkForPictureOptimizations()
-{
- if (m_recordingPicture) {
- // Let's check if we have text or not. If we don't, we can limit
- // ourselves to scale 1!
- InspectorBounder inspectorBounder;
- InspectorCanvas checker(&inspectorBounder, m_recordingPicture);
- SkBitmap bitmap;
- bitmap.setConfig(SkBitmap::kARGB_8888_Config,
- m_recordingPicture->width(),
- m_recordingPicture->height());
- checker.setBitmapDevice(bitmap);
- checker.drawPicture(*m_recordingPicture);
- m_hasText = checker.hasText();
- if (!checker.hasContent()) {
- // no content to draw, discard picture so UI / tile generation
- // doesn't bother with it
- SkSafeUnref(m_recordingPicture);
- m_recordingPicture = 0;
- }
- }
-}
-
LayerAndroid::LayerAndroid(SkPicture* picture) : Layer(),
m_haveClip(false),
m_fixedPosition(0),
- m_recordingPicture(picture),
m_zValue(0),
m_uniqueId(++gUniqueId),
m_imageCRC(0),
@@ -180,12 +157,11 @@ LayerAndroid::LayerAndroid(SkPicture* picture) : Layer(),
m_lastComputeTextureSize(0),
m_owningLayer(0),
m_type(LayerAndroid::NavCacheLayer),
- m_hasText(true),
m_intrinsicallyComposited(true),
m_layerGroup(0)
{
m_backgroundColor = 0;
- SkSafeRef(m_recordingPicture);
+ m_content = new PictureLayerContent(picture);
m_dirtyRegion.setEmpty();
#ifdef DEBUG_COUNT
ClassTracker::instance()->increment("LayerAndroid - from picture");
@@ -200,7 +176,7 @@ LayerAndroid::~LayerAndroid()
if (m_fixedPosition)
delete m_fixedPosition;
- SkSafeUnref(m_recordingPicture);
+ SkSafeUnref(m_content);
// Don't unref m_layerGroup, owned by BaseLayerAndroid
m_animations.clear();
#ifdef DEBUG_COUNT
@@ -214,6 +190,11 @@ LayerAndroid::~LayerAndroid()
#endif
}
+bool LayerAndroid::hasText()
+{
+ return m_content && m_content->hasText();
+}
+
static int gDebugNbAnims = 0;
bool LayerAndroid::evaluateAnimations()
@@ -381,7 +362,7 @@ void LayerAndroid::clipInner(SkTDArray<SkRect>* region,
localBounds.intersect(local);
if (localBounds.isEmpty())
return;
- if (m_recordingPicture && boundsIsUnique(*region, localBounds))
+ if (m_content && boundsIsUnique(*region, localBounds))
*region->append() = localBounds;
for (int i = 0; i < countChildren(); i++)
getChild(i)->clipInner(region, m_haveClip ? localBounds : local);
@@ -536,10 +517,16 @@ void LayerAndroid::setContentsImage(SkBitmapRef* img)
m_imageCRC = image ? image->imageCRC() : 0;
}
+void LayerAndroid::setContent(LayerContent* content)
+{
+ SkSafeRef(content);
+ SkSafeUnref(m_content);
+ m_content = content;
+}
+
bool LayerAndroid::needsTexture()
{
- return (m_recordingPicture
- && m_recordingPicture->width() && m_recordingPicture->height());
+ return m_content && !m_content->isEmpty();
}
IntRect LayerAndroid::clippedRect() const
@@ -592,7 +579,7 @@ void LayerAndroid::showLayer(int indent)
IntRect clip(m_clippingRect.x(), m_clippingRect.y(),
m_clippingRect.width(), m_clippingRect.height());
XLOGC("%s %s (%d) [%d:0x%x] - %s %s - area (%d, %d, %d, %d) - visible (%d, %d, %d, %d) "
- "clip (%d, %d, %d, %d) %s %s prepareContext(%x), pic w: %d h: %d",
+ "clip (%d, %d, %d, %d) %s %s m_content(%x), pic w: %d h: %d",
spaces, subclassName().latin1().data(), subclassType(), uniqueId(), m_owningLayer,
needsTexture() ? "needs a texture" : "no texture",
m_imageCRC ? "has an image" : "no image",
@@ -601,9 +588,9 @@ void LayerAndroid::showLayer(int indent)
clip.x(), clip.y(), clip.width(), clip.height(),
contentIsScrollable() ? "SCROLLABLE" : "",
isFixed() ? "FIXED" : "",
- m_recordingPicture,
- m_recordingPicture ? m_recordingPicture->width() : -1,
- m_recordingPicture ? m_recordingPicture->height() : -1);
+ m_content,
+ m_content ? m_content->width() : -1,
+ m_content ? m_content->height() : -1);
int count = this->countChildren();
for (int i = 0; i < count; i++)
@@ -658,7 +645,7 @@ bool LayerAndroid::updateWithLayer(LayerAndroid* layer)
if (m_imageCRC != layer->m_imageCRC)
m_visible = false;
- if ((m_recordingPicture != layer->m_recordingPicture)
+ if ((m_content != layer->m_content)
|| (m_imageCRC != layer->m_imageCRC))
return true;
@@ -703,7 +690,7 @@ bool LayerAndroid::canJoinGroup(LayerGroup* group)
// currently, we don't group zoomable with non-zoomable layers (unless the
// group or the layer doesn't need a texture)
- if (group->needsTexture() && needsTexture() && m_hasText != group->hasText())
+ if (group->needsTexture() && needsTexture() && m_content->hasText() != group->hasText())
return false;
// TODO: compare other layer properties - fixed? overscroll? transformed?
@@ -893,8 +880,8 @@ bool LayerAndroid::drawChildrenCanvas(SkCanvas* canvas, PaintStyle style)
void LayerAndroid::contentDraw(SkCanvas* canvas, PaintStyle style)
{
- if (m_recordingPicture)
- canvas->drawPicture(*m_recordingPicture);
+ if (m_content)
+ m_content->draw(canvas);
if (TilesManager::instance()->getShowVisualIndicator()) {
float w = getSize().width();
@@ -931,7 +918,7 @@ void LayerAndroid::onDraw(SkCanvas* canvas, SkScalar opacity,
return;
}
- if (!prepareContext())
+ if (masksToBounds() || !m_content)
return;
// we just have this save/restore for opacity...
@@ -956,29 +943,6 @@ void LayerAndroid::onDraw(SkCanvas* canvas, SkScalar opacity,
extra->draw(canvas, this);
}
-SkPicture* LayerAndroid::recordContext()
-{
- if (prepareContext(true))
- return m_recordingPicture;
- return 0;
-}
-
-bool LayerAndroid::prepareContext(bool force)
-{
- if (masksToBounds())
- return false;
-
- if (force || !m_recordingPicture ||
- (m_recordingPicture &&
- ((m_recordingPicture->width() != (int) getSize().width()) ||
- (m_recordingPicture->height() != (int) getSize().height())))) {
- SkSafeUnref(m_recordingPicture);
- m_recordingPicture = new SkPicture();
- }
-
- return m_recordingPicture;
-}
-
void LayerAndroid::setFixedPosition(FixedPositioning* position) {
if (m_fixedPosition && m_fixedPosition != position)
delete m_fixedPosition;
@@ -1001,9 +965,9 @@ void LayerAndroid::dumpLayer(FILE* file, int indentLevel) const
writeMatrix(file, indentLevel + 1, "transformMatrix", m_transform);
writeRect(file, indentLevel + 1, "clippingRect", SkRect(m_clippingRect));
- if (m_recordingPicture) {
- writeIntVal(file, indentLevel + 1, "m_recordingPicture.width", m_recordingPicture->width());
- writeIntVal(file, indentLevel + 1, "m_recordingPicture.height", m_recordingPicture->height());
+ if (m_content) {
+ writeIntVal(file, indentLevel + 1, "m_content.width", m_content->width());
+ writeIntVal(file, indentLevel + 1, "m_content.height", m_content->height());
}
if (m_fixedPosition)
diff --git a/Source/WebCore/platform/graphics/android/LayerAndroid.h b/Source/WebCore/platform/graphics/android/LayerAndroid.h
index 2b8ad5d..459c159 100644
--- a/Source/WebCore/platform/graphics/android/LayerAndroid.h
+++ b/Source/WebCore/platform/graphics/android/LayerAndroid.h
@@ -48,6 +48,7 @@ class SkPicture;
namespace WebCore {
class LayerAndroid;
+class LayerContent;
class LayerGroup;
class ImageTexture;
}
@@ -170,7 +171,8 @@ public:
}
bool masksToBounds() const { return m_haveClip; }
- SkPicture* recordContext();
+ LayerContent* content() { return m_content; }
+ void setContent(LayerContent* content);
void addAnimation(PassRefPtr<AndroidAnimation> anim);
void removeAnimationsForProperty(AnimatedPropertyID property);
@@ -181,8 +183,6 @@ public:
bool hasAnimations() const;
void addDirtyArea();
- SkPicture* picture() const { return m_recordingPicture; }
-
virtual void dumpLayer(FILE*, int indentLevel) const;
void dumpLayers(FILE*, int indentLevel) const;
void dumpToLog() const;
@@ -261,8 +261,7 @@ public:
LayerType type() { return m_type; }
virtual SubclassType subclassType() { return LayerAndroid::StandardLayer; }
- bool hasText() { return m_hasText; }
- void checkForPictureOptimizations();
+ bool hasText();
void copyAnimationStartTimesRecursive(LayerAndroid* oldTree);
@@ -308,14 +307,6 @@ private:
FixedPositioning* m_fixedPosition;
- // Note that m_recordingPicture and m_imageRef are mutually exclusive;
- // m_recordingPicture is used when WebKit is asked to paint the layer's
- // content, while m_imageRef contains an image that we directly
- // composite, using the layer's dimensions as a destination rect.
- // We do this as if the layer only contains an image, directly compositing
- // it is a much faster method than using m_recordingPicture.
- SkPicture* m_recordingPicture;
-
typedef HashMap<pair<String, int>, RefPtr<AndroidAnimation> > KeyframesMap;
KeyframesMap m_animations;
@@ -332,6 +323,13 @@ private:
int m_uniqueId;
+ // Note that m_content and m_imageCRC are mutually exclusive;
+ // m_content is used when WebKit is asked to paint the layer's
+ // content, while m_imageCRC references an image that we directly
+ // composite, using the layer's dimensions as a destination rect.
+ // We do this as if the layer only contains an image, directly compositing
+ // it is a much faster method than using m_content.
+ LayerContent* m_content;
unsigned m_imageCRC;
// used to signal the framework we need a repaint
@@ -353,7 +351,6 @@ private:
LayerType m_type;
SubclassType m_subclassType;
- bool m_hasText;
bool m_intrinsicallyComposited;
LayerGroup* m_layerGroup;
diff --git a/Source/WebCore/platform/graphics/android/LayerContent.h b/Source/WebCore/platform/graphics/android/LayerContent.h
new file mode 100644
index 0000000..32108ec
--- /dev/null
+++ b/Source/WebCore/platform/graphics/android/LayerContent.h
@@ -0,0 +1,51 @@
+/*
+ * Copyright 2012, The Android Open Source Project
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef LayerContent_h
+#define LayerContent_h
+
+#include "SkRefCnt.h"
+
+class SkCanvas;
+class SkPicture;
+class SkWStream;
+
+namespace WebCore {
+
+class LayerContent : public SkRefCnt {
+public:
+ virtual int width() = 0;
+ virtual int height() = 0;
+ virtual bool isEmpty() = 0;
+ virtual void checkForOptimisations() = 0;
+ virtual bool hasText() = 0;
+ virtual void draw(SkCanvas* canvas) = 0;
+
+ virtual void serialize(SkWStream* stream) = 0;
+};
+
+} // WebCore
+
+#endif // LayerContent_h
diff --git a/Source/WebCore/platform/graphics/android/PictureLayerContent.cpp b/Source/WebCore/platform/graphics/android/PictureLayerContent.cpp
new file mode 100644
index 0000000..cf2e569
--- /dev/null
+++ b/Source/WebCore/platform/graphics/android/PictureLayerContent.cpp
@@ -0,0 +1,103 @@
+#include "config.h"
+#include "PictureLayerContent.h"
+
+#include "InspectorCanvas.h"
+#include "SkPicture.h"
+
+namespace WebCore {
+
+PictureLayerContent::PictureLayerContent(SkPicture* picture)
+ : m_picture(picture)
+ , m_checkedContent(false)
+ , m_hasText(true)
+{
+ SkSafeRef(m_picture);
+}
+
+PictureLayerContent::PictureLayerContent(const PictureLayerContent& content)
+ : m_picture(content.m_picture)
+ , m_checkedContent(content.m_checkedContent)
+ , m_hasText(content.m_hasText)
+{
+ SkSafeRef(m_picture);
+}
+
+PictureLayerContent::~PictureLayerContent()
+{
+ SkSafeUnref(m_picture);
+}
+
+int PictureLayerContent::width()
+{
+ if (!m_picture)
+ return 0;
+ return m_picture->width();
+}
+
+int PictureLayerContent::height()
+{
+ if (!m_picture)
+ return 0;
+ return m_picture->height();
+}
+
+bool PictureLayerContent::isEmpty()
+{
+ if (!m_picture)
+ return true;
+ if (m_picture->width() == 0
+ || m_picture->height() == 0)
+ return true;
+ return false;
+}
+
+void PictureLayerContent::checkForOptimisations()
+{
+ if (!m_checkedContent)
+ hasText(); // for now only check the presence of text
+}
+
+bool PictureLayerContent::hasText()
+{
+ if (m_checkedContent)
+ return m_hasText;
+
+ // Let's check if we have text or not. If we don't, we can limit
+ // ourselves to scale 1!
+ InspectorBounder inspectorBounder;
+ InspectorCanvas checker(&inspectorBounder, m_picture);
+ SkBitmap bitmap;
+ bitmap.setConfig(SkBitmap::kARGB_8888_Config,
+ m_picture->width(),
+ m_picture->height());
+ checker.setBitmapDevice(bitmap);
+ checker.drawPicture(*m_picture);
+ m_hasText = checker.hasText();
+ if (!checker.hasContent()) {
+ // no content to draw, discard picture so UI / tile generation
+ // doesn't bother with it
+ SkSafeUnref(m_picture);
+ m_picture = 0;
+ }
+
+ m_checkedContent = true;
+
+ return m_hasText;
+}
+
+void PictureLayerContent::draw(SkCanvas* canvas)
+{
+ if (!m_picture)
+ return;
+
+ canvas->drawPicture(*m_picture);
+}
+
+void PictureLayerContent::serialize(SkWStream* stream)
+{
+ if (!m_picture)
+ return;
+ m_picture->serialize(stream);
+}
+
+} // namespace WebCore
diff --git a/Source/WebCore/platform/graphics/android/PictureLayerContent.h b/Source/WebCore/platform/graphics/android/PictureLayerContent.h
new file mode 100644
index 0000000..94bdfac
--- /dev/null
+++ b/Source/WebCore/platform/graphics/android/PictureLayerContent.h
@@ -0,0 +1,55 @@
+/*
+ * Copyright 2012, The Android Open Source Project
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef PictureLayerContent_h
+#define PictureLayerContent_h
+
+#include "LayerContent.h"
+
+namespace WebCore {
+
+class PictureLayerContent : public LayerContent {
+public:
+ PictureLayerContent(SkPicture* picture);
+ PictureLayerContent(const PictureLayerContent& content);
+ ~PictureLayerContent();
+
+ virtual int width();
+ virtual int height();
+ virtual bool isEmpty();
+ virtual void checkForOptimisations();
+ virtual bool hasText();
+ virtual void draw(SkCanvas* canvas);
+ virtual void serialize(SkWStream* stream);
+
+private:
+ SkPicture* m_picture;
+ bool m_checkedContent;
+ bool m_hasText;
+};
+
+} // WebCore
+
+#endif // PictureLayerContent_h
diff --git a/Source/WebCore/platform/graphics/android/PictureSetLayerContent.cpp b/Source/WebCore/platform/graphics/android/PictureSetLayerContent.cpp
new file mode 100644
index 0000000..bc024eb
--- /dev/null
+++ b/Source/WebCore/platform/graphics/android/PictureSetLayerContent.cpp
@@ -0,0 +1,35 @@
+#include "config.h"
+#include "PictureSetLayerContent.h"
+
+#include "SkPicture.h"
+
+namespace WebCore {
+
+PictureSetLayerContent::PictureSetLayerContent(const android::PictureSet& pictureSet)
+{
+ m_pictureSet.set(pictureSet);
+}
+
+PictureSetLayerContent::~PictureSetLayerContent()
+{
+ m_pictureSet.clear();
+}
+
+void PictureSetLayerContent::draw(SkCanvas* canvas)
+{
+ if (!m_pictureSet.isEmpty())
+ m_pictureSet.draw(canvas);
+}
+
+void PictureSetLayerContent::serialize(SkWStream* stream)
+{
+ if (!stream)
+ return;
+ SkPicture picture;
+ draw(picture.beginRecording(m_pictureSet.width(), m_pictureSet.height(),
+ SkPicture::kUsePathBoundsForClip_RecordingFlag));
+ picture.endRecording();
+ picture.serialize(stream);
+}
+
+} // namespace WebCore
diff --git a/Source/WebCore/platform/graphics/android/PictureSetLayerContent.h b/Source/WebCore/platform/graphics/android/PictureSetLayerContent.h
new file mode 100644
index 0000000..61fc3f4
--- /dev/null
+++ b/Source/WebCore/platform/graphics/android/PictureSetLayerContent.h
@@ -0,0 +1,53 @@
+/*
+ * Copyright 2012, The Android Open Source Project
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef PictureSetLayerContent_h
+#define PictureSetLayerContent_h
+
+#include "LayerContent.h"
+#include "PictureSet.h"
+
+namespace WebCore {
+
+class PictureSetLayerContent : public LayerContent {
+public:
+ PictureSetLayerContent(const android::PictureSet& pictureSet);
+ ~PictureSetLayerContent();
+
+ virtual int width() { return m_pictureSet.width(); }
+ virtual int height() { return m_pictureSet.height(); }
+ virtual bool isEmpty() { return m_pictureSet.isEmpty(); }
+ virtual void checkForOptimisations() {}
+ virtual bool hasText() { return true; }
+ virtual void draw(SkCanvas* canvas);
+ virtual void serialize(SkWStream* stream);
+
+private:
+ android::PictureSet m_pictureSet;
+};
+
+} // WebCore
+
+#endif // PictureLayerContent_h
diff --git a/Source/WebKit/android/jni/ViewStateSerializer.cpp b/Source/WebKit/android/jni/ViewStateSerializer.cpp
index dc9c72d..d3075a2 100644
--- a/Source/WebKit/android/jni/ViewStateSerializer.cpp
+++ b/Source/WebKit/android/jni/ViewStateSerializer.cpp
@@ -33,6 +33,8 @@
#include "IFrameLayerAndroid.h"
#include "Layer.h"
#include "LayerAndroid.h"
+#include "LayerContent.h"
+#include "PictureLayerContent.h"
#include "PictureSet.h"
#include "ScrollableLayerAndroid.h"
#include "SkPicture.h"
@@ -79,14 +81,12 @@ static bool nativeSerializeViewState(JNIEnv* env, jobject, jint jbaseLayer,
#else
stream->write32(0);
#endif
- SkPicture picture;
- PictureSet* content = baseLayer->content();
- baseLayer->drawCanvas(picture.beginRecording(content->width(), content->height(),
- SkPicture::kUsePathBoundsForClip_RecordingFlag));
- picture.endRecording();
if (!stream)
return false;
- picture.serialize(stream);
+ if (baseLayer->content())
+ baseLayer->content()->serialize(stream);
+ else
+ return false;
int childCount = baseLayer->countChildren();
XLOG("BaseLayer has %d child(ren)", childCount);
stream->write32(childCount);
@@ -110,7 +110,9 @@ static BaseLayerAndroid* nativeDeserializeViewState(JNIEnv* env, jobject, jint v
layer->setBackgroundColor(color);
#endif
SkPicture* picture = new SkPicture(stream);
- layer->setContent(picture);
+ PictureLayerContent* content = new PictureLayerContent(picture);
+ layer->setContent(content);
+ SkSafeUnref(content);
SkSafeUnref(picture);
int childCount = stream->readS32();
for (int i = 0; i < childCount; i++) {
@@ -335,10 +337,10 @@ void serializeLayer(LayerAndroid* layer, SkWStream* stream)
stream->write32(buffer.size());
buffer.writeToStream(stream);
}
- bool hasRecordingPicture = layer->m_recordingPicture != 0;
+ bool hasRecordingPicture = layer->m_content != 0 && !layer->m_content->isEmpty();
stream->writeBool(hasRecordingPicture);
if (hasRecordingPicture)
- layer->m_recordingPicture->serialize(stream);
+ layer->m_content->serialize(stream);
// TODO: support m_animations (maybe?)
stream->write32(0); // placeholder for m_animations.size();
writeTransformationMatrix(stream, layer->m_transform);
@@ -453,7 +455,11 @@ LayerAndroid* deserializeLayer(int version, SkStream* stream)
}
bool hasRecordingPicture = stream->readBool();
if (hasRecordingPicture) {
- layer->m_recordingPicture = new SkPicture(stream);
+ SkPicture* picture = new SkPicture(stream);
+ PictureLayerContent* content = new PictureLayerContent(picture);
+ layer->setContent(content);
+ SkSafeUnref(content);
+ SkSafeUnref(picture);
}
int animationCount = stream->readU32(); // TODO: Support (maybe?)
readTransformationMatrix(stream, layer->m_transform);
diff --git a/Source/WebKit/android/jni/WebViewCore.cpp b/Source/WebKit/android/jni/WebViewCore.cpp
index af25b3b..0589468 100644
--- a/Source/WebKit/android/jni/WebViewCore.cpp
+++ b/Source/WebKit/android/jni/WebViewCore.cpp
@@ -87,6 +87,7 @@
#include "NodeList.h"
#include "Page.h"
#include "PageGroup.h"
+#include "PictureSetLayerContent.h"
#include "PlatformKeyboardEvent.h"
#include "PlatformString.h"
#include "PluginWidgetAndroid.h"
@@ -819,7 +820,10 @@ void WebViewCore::notifyAnimationStarted()
BaseLayerAndroid* WebViewCore::createBaseLayer(SkRegion* region)
{
BaseLayerAndroid* base = new BaseLayerAndroid();
- base->setContent(m_content);
+
+ PictureSetLayerContent* content = new PictureSetLayerContent(m_content);
+ base->setContent(content);
+ SkSafeUnref(content);
m_skipContentDraw = true;
bool layoutSucceeded = layoutIfNeededRecursive(m_mainFrame);
diff --git a/Source/WebKit/android/nav/WebView.cpp b/Source/WebKit/android/nav/WebView.cpp
index 5f5ff62..03dd866 100644
--- a/Source/WebKit/android/nav/WebView.cpp
+++ b/Source/WebKit/android/nav/WebView.cpp
@@ -294,14 +294,14 @@ PictureSet* draw(SkCanvas* canvas, SkColor bgColor, DrawExtras extras, bool spli
}
// draw the content of the base layer first
- PictureSet* content = m_baseLayer->content();
+ LayerContent* content = m_baseLayer->content();
+
int sc = canvas->save(SkCanvas::kClip_SaveFlag);
canvas->clipRect(SkRect::MakeLTRB(0, 0, content->width(),
content->height()), SkRegion::kDifference_Op);
canvas->drawColor(bgColor);
canvas->restoreToCount(sc);
- if (content->draw(canvas))
- ret = split ? new PictureSet(*content) : 0;
+ content->draw(canvas);
DrawExtra* extra = getDrawExtra(extras);
if (extra)
@@ -559,7 +559,7 @@ void replaceBaseContent(PictureSet* set)
{
if (!m_baseLayer)
return;
- m_baseLayer->setContent(*set);
+ // TODO: remove the split picture codepath
delete set;
}
@@ -567,7 +567,7 @@ void copyBaseContentToPicture(SkPicture* picture)
{
if (!m_baseLayer)
return;
- PictureSet* content = m_baseLayer->content();
+ LayerContent* content = m_baseLayer->content();
m_baseLayer->drawCanvas(picture->beginRecording(content->width(), content->height(),
SkPicture::kUsePathBoundsForClip_RecordingFlag));
picture->endRecording();