OSDN Git Service

Serialize LayerAndroid
authorJohn Reck <jreck@google.com>
Tue, 7 Jun 2011 00:31:38 +0000 (17:31 -0700)
committerJohn Reck <jreck@google.com>
Tue, 7 Jun 2011 20:40:23 +0000 (13:40 -0700)
 For now skip other layer types
 Doesn't support animtations

Change-Id: Id1ff75f3d4d213f56561fc5d9c01f7ffee05cc79

Source/WebCore/platform/graphics/android/GLWebViewState.cpp
Source/WebCore/platform/graphics/android/LayerAndroid.cpp
Source/WebCore/platform/graphics/android/LayerAndroid.h
Source/WebCore/platform/graphics/android/ScrollableLayerAndroid.h
Source/WebKit/android/jni/ViewStateSerializer.cpp
Source/WebKit/android/nav/WebView.cpp

index 927b0bb..c2fd9dd 100644 (file)
@@ -225,8 +225,8 @@ void GLWebViewState::inval(const IntRect& rect)
             else
                 m_frameworkInval.unite(rect);
             XLOG("intermediate invalRect(%d, %d, %d, %d) after unite with rect %d %d %d %d", m_frameworkInval.x(),
-                 m_frameworkInval.y(), m_frameworkInval.right(), m_frameworkInval.bottom(),
-                 rect.x(), rect.y(), rect.right(), rect.bottom());
+                 m_frameworkInval.y(), m_frameworkInval.width(), m_frameworkInval.height(),
+                 rect.x(), rect.y(), rect.width(), rect.height());
         }
     } else {
         m_invalidateRegion.op(rect.x(), rect.y(), rect.maxX(), rect.maxY(), SkRegion::kUnion_Op);
@@ -521,7 +521,7 @@ bool GLWebViewState::drawGL(IntRect& rect, SkRect& viewport, IntRect* invalRect,
     }
 
     XLOG("drawGL, rect(%d, %d, %d, %d), viewport(%.2f, %.2f, %.2f, %.2f)",
-         rect.x(), rect.y(), rect.right(), rect.bottom(),
+         rect.x(), rect.y(), rect.width(), rect.height(),
          viewport.fLeft, viewport.fTop, viewport.fRight, viewport.fBottom);
 
     resetLayersDirtyArea();
@@ -553,7 +553,7 @@ bool GLWebViewState::drawGL(IntRect& rect, SkRect& viewport, IntRect* invalRect,
         invalRect->setHeight(inval.height());
 
         XLOG("invalRect(%d, %d, %d, %d)", inval.x(),
-             inval.y(), inval.right(), inval.bottom());
+             inval.y(), inval.width(), inval.height());
     } else {
         resetFrameworkInval();
     }
index 34c02e9..67456a3 100644 (file)
@@ -510,6 +510,9 @@ const LayerAndroid* LayerAndroid::find(int* xPtr, int* yPtr, SkPicture* root) co
 
 void LayerAndroid::updateFixedLayersPositions(SkRect viewport, LayerAndroid* parentIframeLayer)
 {
+    XLOG("updating fixed positions, using viewport %fx%f - %fx%f",
+         viewport.fLeft, viewport.fTop,
+         viewport.width(), viewport.height());
     // If this is an iframe, accumulate the offset from the parent with
     // current position, and change the parent pointer.
     if (m_isIframe) {
@@ -952,9 +955,9 @@ bool LayerAndroid::drawGL(GLWebViewState* glWebViewState, SkMatrix& matrix)
         if (textureInfo && (!m_contentsImage || (ready && m_contentsImage))) {
             SkRect bounds;
             bounds.set(m_drawingTexture->rect());
-            XLOG("LayerAndroid %d %x (%.2f, %.2f) drawGL (texture %x, %d, %d, %d, %d)",
+            XLOG("LayerAndroid %d %x (%.2f, %.2f) drawGL (texture %x, %f, %f, %f, %f)",
                  uniqueId(), this, getWidth(), getHeight(),
-                 m_drawingTexture, bounds.x(), bounds.y(),
+                 m_drawingTexture, bounds.fLeft, bounds.fTop,
                  bounds.width(), bounds.height());
             //TODO determine when drawing if the alpha value is used.
             TilesManager::instance()->shader()->drawLayerQuad(drawTransform(), bounds,
index d4510c5..fe41e35 100644 (file)
@@ -47,6 +47,8 @@ class SkPicture;
 
 namespace android {
 class DrawExtra;
+void serializeLayer(LayerAndroid* layer, SkWStream* stream);
+LayerAndroid* deserializeLayer(SkStream* stream);
 }
 
 using namespace android;
@@ -256,6 +258,9 @@ public:
     void setIsIframe(bool isIframe) { m_isIframe = isIframe; }
     float zValue() const { return m_zValue; }
 
+    friend void android::serializeLayer(LayerAndroid* layer, SkWStream* stream);
+    friend LayerAndroid* android::deserializeLayer(SkStream* stream);
+
 protected:
     virtual void onDraw(SkCanvas*, SkScalar opacity);
 
@@ -269,6 +274,10 @@ private:
     bool prepareContext(bool force = false);
     void clipInner(SkTDArray<SkRect>* region, const SkRect& local) const;
 
+    // -------------------------------------------------------------------
+    // Fields to be serialized
+    // -------------------------------------------------------------------
+
     bool m_haveClip;
     bool m_isFixed;
     bool m_backgroundColorSet;
@@ -284,13 +293,10 @@ private:
     SkLength m_fixedMarginBottom;
     SkRect m_fixedRect;
 
-    SkPoint m_iframeOffset;
     // When fixed element is undefined or auto, the render layer's position
     // is needed for offset computation
     IntPoint m_renderLayerPos;
 
-    TransformationMatrix m_transform;
-    float m_zValue;
     bool m_backfaceVisibility;
     bool m_visible;
 
@@ -299,9 +305,6 @@ private:
     bool m_preserves3D;
     float m_anchorPointZ;
     float m_drawOpacity;
-    TransformationMatrix m_drawTransform;
-    TransformationMatrix m_childrenTransform;
-    FloatRect m_clippingRect;
 
     // Note that m_recordingPicture and m_contentsImage are mutually exclusive;
     // m_recordingPicture is used when WebKit is asked to paint the layer's
@@ -315,6 +318,21 @@ private:
 
     typedef HashMap<pair<String, int>, RefPtr<AndroidAnimation> > KeyframesMap;
     KeyframesMap m_animations;
+
+    TransformationMatrix m_transform;
+    TransformationMatrix m_childrenTransform;
+
+    // -------------------------------------------------------------------
+    // Fields that are not serialized (generated, cached, or non-serializable)
+    // -------------------------------------------------------------------
+
+    SkPoint m_iframeOffset;
+
+    float m_zValue;
+
+    TransformationMatrix m_drawTransform;
+    FloatRect m_clippingRect;
+
     SkPicture* m_extra;
     int m_uniqueId;
 
index b23f056..c3fdecd 100644 (file)
@@ -57,6 +57,9 @@ public:
         m_scrollLimits.set(x, y, x + width, y + height);
     }
 
+    friend void android::serializeLayer(LayerAndroid* layer, SkWStream* stream);
+    friend LayerAndroid* android::deserializeLayer(SkStream* stream);
+
 private:
     SkRect m_scrollLimits;
 };
index c780e07..7ec77ed 100644 (file)
 
 #include "BaseLayerAndroid.h"
 #include "CreateJavaOutputStreamAdaptor.h"
+#include "LayerAndroid.h"
 #include "PictureSet.h"
+#include "ScrollableLayerAndroid.h"
+#include "SkLayer.h"
 #include "SkPicture.h"
 
 #include <JNIUtility.h>
 #include <JNIHelp.h>
 #include <jni.h>
 
+#ifdef DEBUG
+
+#undef XLOG
+#define XLOG(...) android_printLog(ANDROID_LOG_DEBUG, "ViewStateSerializer", __VA_ARGS__)
+
+#else
+
+#undef XLOG
+#define XLOG(...)
+
+#endif // DEBUG
+
 namespace android {
 
+enum LayerTypes {
+    LTNone = 0,
+    LTLayerAndroid = 1,
+    LTScrollableLayerAndroid = 2,
+};
+
 static bool nativeSerializeViewState(JNIEnv* env, jobject, jint jbaseLayer,
                                      jobject jstream, jbyteArray jstorage)
 {
@@ -57,6 +78,13 @@ static bool nativeSerializeViewState(JNIEnv* env, jobject, jint jbaseLayer,
     if (!stream)
         return false;
     picture.serialize(stream);
+    int childCount = baseLayer->countChildren();
+    XLOG("BaseLayer has %d child(ren)", childCount);
+    stream->write32(childCount);
+    for (int i = 0; i < childCount; i++) {
+        LayerAndroid* layer = static_cast<LayerAndroid*>(baseLayer->getChild(i));
+        serializeLayer(layer, stream);
+    }
     delete stream;
     return true;
 }
@@ -73,8 +101,306 @@ static BaseLayerAndroid* nativeDeserializeViewState(JNIEnv* env, jobject, jobjec
     layer->setBackgroundColor(color);
 #endif
     SkPicture* picture = new SkPicture(stream);
-    delete stream;
     layer->setContent(picture);
+    SkSafeUnref(picture);
+    int childCount = stream->readS32();
+    for (int i = 0; i < childCount; i++) {
+        LayerAndroid* childLayer = deserializeLayer(stream);
+        if (childLayer)
+            layer->addChild(childLayer);
+    }
+    delete stream;
+    return layer;
+}
+
+// Serialization helpers
+
+void writeMatrix(SkWStream *stream, const SkMatrix& matrix)
+{
+    for (int i = 0; i < 9; i++)
+        stream->writeScalar(matrix[i]);
+}
+
+SkMatrix readMatrix(SkStream *stream)
+{
+    SkMatrix matrix;
+    for (int i = 0; i < 9; i++)
+        matrix.set(i, stream->readScalar());
+    return matrix;
+}
+
+void writeSkLength(SkWStream *stream, SkLength length)
+{
+    stream->write32(length.type);
+    stream->writeScalar(length.value);
+}
+
+SkLength readSkLength(SkStream *stream)
+{
+    SkLength len;
+    len.type = (SkLength::SkLengthType) stream->readU32();
+    len.value = stream->readScalar();
+    return len;
+}
+
+void writeSkRect(SkWStream *stream, SkRect rect)
+{
+    stream->writeScalar(rect.fLeft);
+    stream->writeScalar(rect.fTop);
+    stream->writeScalar(rect.fRight);
+    stream->writeScalar(rect.fBottom);
+}
+
+SkRect readSkRect(SkStream *stream)
+{
+    SkRect rect;
+    rect.fLeft = stream->readScalar();
+    rect.fTop = stream->readScalar();
+    rect.fRight = stream->readScalar();
+    rect.fBottom = stream->readScalar();
+    return rect;
+}
+
+void writeTransformationMatrix(SkWStream *stream, TransformationMatrix& matrix)
+{
+    double value;
+    int dsize = sizeof(double);
+    value = matrix.m11();
+    stream->write(&value, dsize);
+    value = matrix.m12();
+    stream->write(&value, dsize);
+    value = matrix.m13();
+    stream->write(&value, dsize);
+    value = matrix.m14();
+    stream->write(&value, dsize);
+    value = matrix.m21();
+    stream->write(&value, dsize);
+    value = matrix.m22();
+    stream->write(&value, dsize);
+    value = matrix.m23();
+    stream->write(&value, dsize);
+    value = matrix.m24();
+    stream->write(&value, dsize);
+    value = matrix.m31();
+    stream->write(&value, dsize);
+    value = matrix.m32();
+    stream->write(&value, dsize);
+    value = matrix.m33();
+    stream->write(&value, dsize);
+    value = matrix.m34();
+    stream->write(&value, dsize);
+    value = matrix.m41();
+    stream->write(&value, dsize);
+    value = matrix.m42();
+    stream->write(&value, dsize);
+    value = matrix.m43();
+    stream->write(&value, dsize);
+    value = matrix.m44();
+    stream->write(&value, dsize);
+}
+
+void readTransformationMatrix(SkStream *stream, TransformationMatrix& matrix)
+{
+    double value;
+    int dsize = sizeof(double);
+    stream->read(&value, dsize);
+    matrix.setM11(value);
+    stream->read(&value, dsize);
+    matrix.setM12(value);
+    stream->read(&value, dsize);
+    matrix.setM13(value);
+    stream->read(&value, dsize);
+    matrix.setM14(value);
+    stream->read(&value, dsize);
+    matrix.setM21(value);
+    stream->read(&value, dsize);
+    matrix.setM22(value);
+    stream->read(&value, dsize);
+    matrix.setM23(value);
+    stream->read(&value, dsize);
+    matrix.setM24(value);
+    stream->read(&value, dsize);
+    matrix.setM31(value);
+    stream->read(&value, dsize);
+    matrix.setM32(value);
+    stream->read(&value, dsize);
+    matrix.setM33(value);
+    stream->read(&value, dsize);
+    matrix.setM34(value);
+    stream->read(&value, dsize);
+    matrix.setM41(value);
+    stream->read(&value, dsize);
+    matrix.setM42(value);
+    stream->read(&value, dsize);
+    matrix.setM43(value);
+    stream->read(&value, dsize);
+    matrix.setM44(value);
+}
+
+void serializeLayer(LayerAndroid* layer, SkWStream* stream)
+{
+    if (!layer) {
+        XLOG("NULL layer!");
+        stream->write8(LTNone);
+        return;
+    }
+    if (layer->isMedia() || layer->isVideo()) {
+        XLOG("Layer isn't supported for serialization: isMedia: %s, isVideo: %s",
+             layer->isMedia() ? "true" : "false",
+             layer->isVideo() ? "true" : "false");
+        stream->write8(LTNone);
+        return;
+    }
+    LayerTypes type = layer->contentIsScrollable()
+            ? LTScrollableLayerAndroid
+            : LTLayerAndroid;
+    stream->write8(type);
+
+    // Start with SkLayer fields
+    stream->writeBool(layer->isInheritFromRootTransform());
+    stream->writeScalar(layer->getOpacity());
+    stream->writeScalar(layer->getSize().width());
+    stream->writeScalar(layer->getSize().height());
+    stream->writeScalar(layer->getPosition().x());
+    stream->writeScalar(layer->getPosition().y());
+    stream->writeScalar(layer->getAnchorPoint().x());
+    stream->writeScalar(layer->getAnchorPoint().y());
+    writeMatrix(stream, layer->getMatrix());
+    writeMatrix(stream, layer->getChildrenMatrix());
+
+    // Next up, LayerAndroid fields
+    stream->writeBool(layer->m_haveClip);
+    stream->writeBool(layer->m_isFixed);
+    stream->writeBool(layer->m_backgroundColorSet);
+    stream->writeBool(layer->m_isIframe);
+    writeSkLength(stream, layer->m_fixedLeft);
+    writeSkLength(stream, layer->m_fixedTop);
+    writeSkLength(stream, layer->m_fixedRight);
+    writeSkLength(stream, layer->m_fixedBottom);
+    writeSkLength(stream, layer->m_fixedMarginLeft);
+    writeSkLength(stream, layer->m_fixedMarginTop);
+    writeSkLength(stream, layer->m_fixedMarginRight);
+    writeSkLength(stream, layer->m_fixedMarginBottom);
+    writeSkRect(stream, layer->m_fixedRect);
+    stream->write32(layer->m_renderLayerPos.x());
+    stream->write32(layer->m_renderLayerPos.y());
+    stream->writeBool(layer->m_backfaceVisibility);
+    stream->writeBool(layer->m_visible);
+    stream->write32(layer->m_backgroundColor);
+    stream->writeBool(layer->m_preserves3D);
+    stream->writeScalar(layer->m_anchorPointZ);
+    stream->writeScalar(layer->m_drawOpacity);
+    bool hasContentsImage = layer->m_contentsImage != 0;
+    stream->writeBool(hasContentsImage);
+    if (hasContentsImage) {
+        SkFlattenableWriteBuffer buffer(1024);
+        buffer.setFlags(SkFlattenableWriteBuffer::kCrossProcess_Flag);
+        layer->m_contentsImage->flatten(buffer);
+        stream->write32(buffer.size());
+        buffer.writeToStream(stream);
+    }
+    bool hasRecordingPicture = layer->m_recordingPicture != 0;
+    stream->writeBool(hasRecordingPicture);
+    if (hasRecordingPicture)
+        layer->m_recordingPicture->serialize(stream);
+    // TODO: support m_animations (maybe?)
+    stream->write32(0); // placeholder for m_animations.size();
+    writeTransformationMatrix(stream, layer->m_transform);
+    writeTransformationMatrix(stream, layer->m_childrenTransform);
+    if (type == LTScrollableLayerAndroid) {
+        ScrollableLayerAndroid* scrollableLayer =
+                static_cast<ScrollableLayerAndroid*>(layer);
+        stream->writeScalar(scrollableLayer->m_scrollLimits.fLeft);
+        stream->writeScalar(scrollableLayer->m_scrollLimits.fTop);
+        stream->writeScalar(scrollableLayer->m_scrollLimits.width());
+        stream->writeScalar(scrollableLayer->m_scrollLimits.height());
+    }
+    int childCount = layer->countChildren();
+    stream->write32(childCount);
+    for (int i = 0; i < childCount; i++)
+        serializeLayer(layer->getChild(i), stream);
+}
+
+LayerAndroid* deserializeLayer(SkStream* stream)
+{
+    int type = stream->readU8();
+    if (type == LTNone)
+        return 0;
+    // Cast is to disambiguate between ctors.
+    LayerAndroid *layer;
+    if (type == LTLayerAndroid)
+        layer = new LayerAndroid((RenderLayer*) 0);
+    else if (type == LTScrollableLayerAndroid)
+        layer = new ScrollableLayerAndroid((RenderLayer*) 0);
+    else {
+        XLOG("Unexpected layer type: %d, aborting!", type);
+        return 0;
+    }
+
+    // SkLayer fields
+    layer->setInheritFromRootTransform(stream->readBool());
+    layer->setOpacity(stream->readScalar());
+    layer->setSize(stream->readScalar(), stream->readScalar());
+    layer->setPosition(stream->readScalar(), stream->readScalar());
+    layer->setAnchorPoint(stream->readScalar(), stream->readScalar());
+    layer->setMatrix(readMatrix(stream));
+    layer->setChildrenMatrix(readMatrix(stream));
+
+    // LayerAndroid fields
+    layer->m_haveClip = stream->readBool();
+    layer->m_isFixed = stream->readBool();
+    layer->m_backgroundColorSet = stream->readBool();
+    layer->m_isIframe = stream->readBool();
+    layer->m_fixedLeft = readSkLength(stream);
+    layer->m_fixedTop = readSkLength(stream);
+    layer->m_fixedRight = readSkLength(stream);
+    layer->m_fixedBottom = readSkLength(stream);
+    layer->m_fixedMarginLeft = readSkLength(stream);
+    layer->m_fixedMarginTop = readSkLength(stream);
+    layer->m_fixedMarginRight = readSkLength(stream);
+    layer->m_fixedMarginBottom = readSkLength(stream);
+    layer->m_fixedRect = readSkRect(stream);
+    layer->m_renderLayerPos.setX(stream->readS32());
+    layer->m_renderLayerPos.setY(stream->readS32());
+    layer->m_backfaceVisibility = stream->readBool();
+    layer->m_visible = stream->readBool();
+    layer->m_backgroundColor = stream->readU32();
+    layer->m_preserves3D = stream->readBool();
+    layer->m_anchorPointZ = stream->readScalar();
+    layer->m_drawOpacity = stream->readScalar();
+    bool hasContentsImage = stream->readBool();
+    if (hasContentsImage) {
+        int size = stream->readU32();
+        SkAutoMalloc storage(size);
+        stream->read(storage.get(), size);
+        SkFlattenableReadBuffer buffer(storage.get(), size);
+        layer->m_contentsImage = new SkBitmap();
+        layer->m_contentsImage->unflatten(buffer);
+    }
+    bool hasRecordingPicture = stream->readBool();
+    if (hasRecordingPicture) {
+        layer->m_recordingPicture = new SkPicture(stream);
+    }
+    int animationCount = stream->readU32(); // TODO: Support (maybe?)
+    readTransformationMatrix(stream, layer->m_transform);
+    readTransformationMatrix(stream, layer->m_childrenTransform);
+    if (type == LTScrollableLayerAndroid) {
+        ScrollableLayerAndroid* scrollableLayer =
+                static_cast<ScrollableLayerAndroid*>(layer);
+        scrollableLayer->m_scrollLimits.set(
+                stream->readScalar(),
+                stream->readScalar(),
+                stream->readScalar(),
+                stream->readScalar());
+    }
+    int childCount = stream->readU32();
+    for (int i = 0; i < childCount; i++) {
+        LayerAndroid *childLayer = deserializeLayer(stream);
+        if (childLayer)
+            layer->addChild(childLayer);
+    }
+    layer->needsRepaint();
+    XLOG("Created layer with id %d", layer->uniqueId());
     return layer;
 }
 
index 8d3082b..61bc159 100644 (file)
@@ -507,6 +507,11 @@ bool drawGL(WebCore::IntRect& viewRect, WebCore::IntRect* invalRect, WebCore::In
 
     SkRect visibleRect;
     calcOurContentVisibleRect(&visibleRect);
+    // Make sure we have valid coordinates. We might not have valid coords
+    // if the zoom manager is still initializing. We will be redrawn
+    // once the correct scale is set
+    if (!visibleRect.hasValidCoordinates())
+        return false;
     bool ret = m_glWebViewState->drawGL(viewRect, visibleRect, invalRect,
                                         webViewRect, titleBarHeight, clip, scale);
     if (ret || m_glWebViewState->currentPictureCounter() != pic)