Beispiel #1
0
bool LayerAndroid::canJoinSurface(Surface* surface)
{
#ifdef DISABLE_LAYER_MERGE
    return false;
#else
    // returns true if the layer can be merged onto the surface (group of layers)
    if (!surface)
        return false;

    LayerAndroid* lastLayer = surface->getFirstLayer();

    // isolate intrinsically composited layers
    if (needsIsolatedSurface() || lastLayer->needsIsolatedSurface())
        return false;

    // TODO: investigate potential for combining transformed layers
    if (!m_drawTransform.isIdentityOrTranslation()
        || !lastLayer->m_drawTransform.isIdentityOrTranslation())
        return false;

    // TODO: compare other layer properties - fixed? overscroll? transformed?
	// SAMSUNG CHANGE ++ 
	if(m_drawOpacity <= 0)	// google handwriting icon('g') display error. opacity:0 layer is not updated properly due to MergedLayers logic.
		return false;
	// SAMSUNG CHANGE --
		
    return true;
#endif
}
// This is called on the UI thread only.
// The video layers are composited on the webkit thread and then copied over
// to the UI thread with the same ID. For rendering, we are only using the
// video layers on the UI thread. Therefore, on the UI thread, we have to use
// the videoLayerId from Java side to find the exact video layer in the tree
// to set the surface texture.
// Every time a play call into Java side, the videoLayerId will be sent and
// saved in Java side. Then every time setBaseLayer call, the saved
// videoLayerId will be passed to this function to find the Video Layer.
// Return value: true when the video layer is found.
static bool SendSurfaceTexture(JNIEnv* env, jobject obj, jobject surfTex,
                               int baseLayer, int videoLayerId,
                               int textureName, int playerState) {
    if (!surfTex)
        return false;

    sp<SurfaceTexture> texture = android::SurfaceTexture_getSurfaceTexture(env, surfTex);
    if (!texture.get())
        return false;

    BaseLayerAndroid* layerImpl = reinterpret_cast<BaseLayerAndroid*>(baseLayer);
    if (!layerImpl)
        return false;
    if (!layerImpl->countChildren())
        return false;
    LayerAndroid* compositedRoot = static_cast<LayerAndroid*>(layerImpl->getChild(0));
    if (!compositedRoot)
        return false;

    VideoLayerAndroid* videoLayer =
        static_cast<VideoLayerAndroid*>(compositedRoot->findById(videoLayerId));
    if (!videoLayer)
        return false;

    // Set the SurfaceTexture to the layer we found
    videoLayer->setSurfaceTexture(texture, textureName, static_cast<PlayerState>(playerState));
    return true;
}
bool BaseLayerAndroid::drawGL(IntRect& viewRect, SkRect& visibleRect,
                              float scale)
{
    XLOG("drawing BLA %p", this);

    // TODO: consider moving drawBackground outside of prepare (into tree manager)
    m_state->drawBackground(m_color);
    drawBasePictureInGL();

    bool needsRedraw = false;

#if USE(ACCELERATED_COMPOSITING)

    LayerAndroid* compositedRoot = static_cast<LayerAndroid*>(getChild(0));
    if (compositedRoot) {
        updateLayerPositions(visibleRect);
        // For now, we render layers only if the rendering mode
        // is kAllTextures or kClippedTextures
        if (compositedRoot->drawGL()) {
            if (TilesManager::instance()->layerTexturesRemain()) {
                // only try redrawing for layers if layer textures remain,
                // otherwise we'll repaint without getting anything done
                needsRedraw = true;
            }
        }
    }

#endif // USE(ACCELERATED_COMPOSITING)
#ifdef DEBUG
    ClassTracker::instance()->show();
#endif
    return needsRedraw;
}
Beispiel #4
0
void PaintedSurface::prepare(GLWebViewState* state)
{
    XLOG("PS %p has PL %p, DL %p", this, m_paintingLayer, m_drawingLayer);
    LayerAndroid* paintingLayer = m_paintingLayer;
    if (!paintingLayer)
        paintingLayer = m_drawingLayer;

    if (!paintingLayer)
        return;

    bool startFastSwap = false;
    if (state->isScrolling()) {
        // when scrolling, block updates and swap tiles as soon as they're ready
        startFastSwap = true;
    }

    XLOG("prepare layer %d %x at scale %.2f",
         paintingLayer->uniqueId(), paintingLayer,
         paintingLayer->getScale());

    IntRect visibleArea = computeVisibleArea(paintingLayer);
    IntRect prepareArea = computePrepareArea(paintingLayer); // SAMSUNG CHANGE

    m_scale = state->scale();

    // If we do not have text, we may as well limit ourselves to
    // a scale factor of one... this saves up textures.
    if (m_scale > 1 && !paintingLayer->hasText())
        m_scale = 1;

    m_tiledTexture->prepare(state, m_scale, m_pictureUsed != paintingLayer->pictureUsed(),
                            startFastSwap, visibleArea, prepareArea); // SAMSUNG CHANGE
}
void TreeManager::updateScrollableLayerInTree(Layer* tree, int layerId, int x, int y)
{
    LayerAndroid* layer;
    if (tree && tree->countChildren()) {
        layer = static_cast<LayerAndroid*>(tree->getChild(0))->findById(layerId);
        if (layer && layer->contentIsScrollable())
            static_cast<ScrollableLayerAndroid*>(layer)->scrollTo(x, y);
    }
}
Beispiel #6
0
void LayerAndroid::mergeInvalsInto(LayerAndroid* replacementTree)
{
    int count = this->countChildren();
    for (int i = 0; i < count; i++)
        this->getChild(i)->mergeInvalsInto(replacementTree);

    LayerAndroid* replacementLayer = replacementTree->findById(uniqueId());
    if (replacementLayer)
        replacementLayer->markAsDirty(m_dirtyRegion);
}
Beispiel #7
0
bool LayerAndroid::visible() {
    // TODO: avoid climbing tree each access
    LayerAndroid* current = this;
    while (current->getParent()) {
        if (!current->m_visible)
            return false;
        current = static_cast<LayerAndroid*>(current->getParent());
    }
    return true;
}
void ChromeClientAndroid::enterFullscreenForNode(Node* node)
{
      if (!node->hasTagName(HTMLNames::videoTag))
          return;

      HTMLMediaElement* videoElement = static_cast<HTMLMediaElement*>(node);
      String url = videoElement->currentSrc();
      LayerAndroid* layer = videoElement->platformLayer();
      if (!layer)
          return;

      FrameView* frameView = m_webFrame->page()->mainFrame()->view();
      android::WebViewCore* core = android::WebViewCore::getWebViewCore(frameView);
      if (core)
          core->enterFullscreenForVideoLayer(layer->uniqueId(), url);
}
Beispiel #9
0
void GraphicsLayerAndroid::syncChildren()
{
    if (m_needsSyncChildren) {
        m_contentLayer->removeChildren();
        LayerAndroid* layer = m_contentLayer;
        if (m_foregroundClipLayer) {
            m_contentLayer->addChild(m_foregroundClipLayer);
            // Use the scrollable content layer as the parent of the children so
            // that they move with the content.
            layer = m_foregroundLayer;
            layer->removeChildren();
        }
        for (unsigned int i = 0; i < m_children.size(); i++)
            layer->addChild(m_children[i]->platformLayer());
        m_needsSyncChildren = false;
    }
}
bool BaseLayerAndroid::prepare(double currentTime, IntRect& viewRect,
                               SkRect& visibleRect, float scale)
{
    XLOG("preparing BLA %p", this);

    // base layer is simply drawn in prepare, since there is always a base layer it doesn't matter
    bool needsRedraw = prepareBasePictureInGL(visibleRect, scale, currentTime);

    LayerAndroid* compositedRoot = static_cast<LayerAndroid*>(getChild(0));
    if (compositedRoot) {
        updateLayerPositions(visibleRect);

        XLOG("preparing BLA %p, root %p", this, compositedRoot);
        compositedRoot->prepare();
    }

    return needsRedraw;
}
Beispiel #11
0
bool LayerAndroid::drawChildrenCanvas(SkCanvas* canvas, PaintStyle style)
{
    bool askScreenUpdate = false;
    int count = this->countChildren();
    if (count > 0) {
        Vector <LayerAndroid*> sublayers;
        for (int i = 0; i < count; i++)
            sublayers.append(this->getChild(i));

        // now we sort for the transparency
        std::stable_sort(sublayers.begin(), sublayers.end(), compareLayerZ);
        for (int i = 0; i < count; i++) {
            LayerAndroid* layer = sublayers[i];
            askScreenUpdate |= layer->drawCanvas(canvas, true, style);
        }
    }

    return askScreenUpdate;
}
LayerAndroid::LayerAndroid(const LayerAndroid& layer) : SkLayer(layer),
    m_isRootLayer(layer.m_isRootLayer),
    m_haveClip(layer.m_haveClip),
    m_extra(0), // deliberately not copied
    m_uniqueId(layer.m_uniqueId)
{
    m_doRotation = layer.m_doRotation;
    m_isFixed = layer.m_isFixed;

    m_angleTransform = layer.m_angleTransform;
    m_translation = layer.m_translation;
    m_scale = layer.m_scale;
    m_backgroundColor = layer.m_backgroundColor;

    m_fixedLeft = layer.m_fixedLeft;
    m_fixedTop = layer.m_fixedTop;
    m_fixedRight = layer.m_fixedRight;
    m_fixedBottom = layer.m_fixedBottom;
    m_fixedMarginLeft = layer.m_fixedMarginLeft;
    m_fixedMarginTop = layer.m_fixedMarginTop;
    m_fixedMarginRight = layer.m_fixedMarginRight;
    m_fixedMarginBottom = layer.m_fixedMarginBottom;
    m_fixedOffset = layer.m_fixedOffset;
    m_fixedWidth = layer.m_fixedWidth;
    m_fixedHeight = layer.m_fixedHeight;

    m_recordingPicture = layer.m_recordingPicture;
    SkSafeRef(m_recordingPicture);

#if ENABLE(WEBGL)
    m_context = layer.m_context;
#endif

    for (int i = 0; i < layer.countChildren(); i++)
        addChild(new LayerAndroid(*layer.getChild(i)))->unref();

    KeyframesMap::const_iterator end = layer.m_animations.end();
    for (KeyframesMap::const_iterator it = layer.m_animations.begin(); it != end; ++it)
        m_animations.add((it->second)->name(), (it->second)->copy());

    gDebugLayerAndroidInstances++;
}
bool BaseLayerAndroid::isReady()
{
    ZoomManager* zoomManager = m_state->zoomManager();
    if (ZoomManager::kNoScaleRequest != zoomManager->scaleRequestState()) {
        XLOG("base layer not ready, still zooming");
        return false; // still zooming
    }

    if (!m_state->frontPage()->isReady(m_state->preZoomBounds())) {
        XLOG("base layer not ready, front page not done painting");
        return false;
    }

    LayerAndroid* compositedRoot = static_cast<LayerAndroid*>(getChild(0));
    if (compositedRoot) {
        XLOG("base layer is ready, how about children?");
        return compositedRoot->isReady();
    }

    return true;
}
void BaseLayerAndroid::updateLayerPositions(SkRect& visibleRect)
{
    LayerAndroid* compositedRoot = static_cast<LayerAndroid*>(getChild(0));
    TransformationMatrix ident;
    compositedRoot->updateFixedLayersPositions(visibleRect);
    FloatRect clip(0, 0, content()->width(), content()->height());
    compositedRoot->updateGLPositionsAndScale(
        ident, clip, 1, m_state->zoomManager()->layersScale());

#ifdef DEBUG
    compositedRoot->showLayer(0);
    XLOG("We have %d layers, %d textured",
         compositedRoot->nbLayers(),
         compositedRoot->nbTexturedLayers());
#endif
}
Beispiel #15
0
void PaintedSurface::computeTexturesAmount(TexturesResult* result)
{
    if (!m_tiledTexture)
        return;

    // for now, always done on drawinglayer
    LayerAndroid* layer = m_drawingLayer;

    if (!layer)
        return;

    IntRect unclippedArea = layer->unclippedArea();
    IntRect clippedVisibleArea = layer->visibleArea();
    // get two numbers here:
    // - textures needed for a clipped area
    // - textures needed for an un-clipped area
    int nbTexturesUnclipped = m_tiledTexture->nbTextures(unclippedArea, m_scale);
    int nbTexturesClipped = m_tiledTexture->nbTextures(clippedVisibleArea, m_scale);

    // Set kFixedLayers level
    if (layer->isFixed())
        result->fixed += nbTexturesClipped;

    // Set kScrollableAndFixedLayers level
    if (layer->contentIsScrollable()
        || layer->isFixed())
        result->scrollable += nbTexturesClipped;

    // Set kClippedTextures level
    result->clipped += nbTexturesClipped;

    // Set kAllTextures level
    if (layer->contentIsScrollable())
        result->full += nbTexturesClipped;
    else
        result->full += nbTexturesUnclipped;
}
void SurfaceCollection::updateScrollableLayer(int layerId, int x, int y)
{
    LayerAndroid* layer = m_compositedRoot->findById(layerId);
    if (layer && layer->contentIsScrollable())
        static_cast<ScrollableLayerAndroid*>(layer)->scrollTo(x, y);
}
Beispiel #17
0
LayerAndroid::LayerAndroid(const LayerAndroid& layer) : Layer(layer),
    m_uniqueId(layer.m_uniqueId),
    m_haveClip(layer.m_haveClip),
    m_backfaceVisibility(layer.m_backfaceVisibility),
    m_visible(layer.m_visible),
    m_backgroundColor(layer.m_backgroundColor),
    m_preserves3D(layer.m_preserves3D),
    m_anchorPointZ(layer.m_anchorPointZ),
    m_isPositionAbsolute(layer.m_isPositionAbsolute),
    m_fixedPosition(0),
    m_zValue(layer.m_zValue),
    m_content(layer.m_content),
    m_imageCRC(layer.m_imageCRC),
    m_scale(layer.m_scale),
    m_lastComputeTextureSize(0),
    m_owningLayer(layer.m_owningLayer),
    m_type(LayerAndroid::UILayer),
    m_intrinsicallyComposited(layer.m_intrinsicallyComposited),
    m_surface(0),
    m_replicatedLayer(0),
    m_originalLayer(0),
    m_maskLayer(0)
{
    if (m_imageCRC)
        ImagesManager::instance()->retainImage(m_imageCRC);

    SkSafeRef(m_content);

    if (layer.m_fixedPosition) {
        m_fixedPosition = layer.m_fixedPosition->copy(this);
        Layer::setShouldInheritFromRootTransform(true);
    }

    m_transform = layer.m_transform;
    m_drawTransform = layer.m_drawTransform;
    m_drawTransformUnfudged = layer.m_drawTransformUnfudged;
    m_childrenTransform = layer.m_childrenTransform;
    m_dirtyRegion = layer.m_dirtyRegion;

    m_replicatedLayerPosition = layer.m_replicatedLayerPosition;

#ifdef ABSOLUTE_POSITION
    // If we have absolute elements, we may need to reorder them if they
    // are followed by another layer that is not also absolutely positioned.
    // (as absolutely positioned elements are out of the normal flow)
    bool hasAbsoluteChildren = false;
    bool hasOnlyAbsoluteFollowers = true;

    for (int i = 0; i < layer.countChildren(); i++) {
        if (layer.getChild(i)->isPositionAbsolute()) {
            hasAbsoluteChildren = true;
            continue;
        }
        if (hasAbsoluteChildren
            && !layer.getChild(i)->isPositionAbsolute()) {
            hasOnlyAbsoluteFollowers = false;
            break;
        }
    }

    if (hasAbsoluteChildren && !hasOnlyAbsoluteFollowers) {
        Vector<LayerAndroid*> normalLayers;
        Vector<LayerAndroid*> absoluteLayers;
        for (int i = 0; i < layer.countChildren(); i++) {
            LayerAndroid* child = layer.getChild(i);
            if (child->isPositionAbsolute()
                || child->isPositionFixed())
                absoluteLayers.append(child);
            else
                normalLayers.append(child);
        }
        for (unsigned int i = 0; i < normalLayers.size(); i++)
            addChild(normalLayers[i]->copy())->unref();
        for (unsigned int i = 0; i < absoluteLayers.size(); i++)
            addChild(absoluteLayers[i]->copy())->unref();
    } else {
        for (int i = 0; i < layer.countChildren(); i++)
            addChild(layer.getChild(i)->copy())->unref();
    }
#else
    for (int i = 0; i < layer.countChildren(); i++)
        addChild(layer.getChild(i)->copy())->unref();
#endif

    KeyframesMap::const_iterator end = layer.m_animations.end();
    for (KeyframesMap::const_iterator it = layer.m_animations.begin(); it != end; ++it) {
        m_animations.add(it->first, it->second);
    }

    if (layer.m_replicatedLayer) {
        // The replicated layer is always the first child
        m_replicatedLayer = getChild(0);
        m_replicatedLayer->setOriginalLayer(this);
    }

    if (layer.m_maskLayer)
        m_maskLayer = layer.m_maskLayer->copy();

#ifdef DEBUG_COUNT
    ClassTracker::instance()->increment("LayerAndroid - recopy (UI)");
    ClassTracker::instance()->add(this);
#endif
}
LayerAndroid* deserializeLayer(int version, 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 {
        ALOGV("Unexpected layer type: %d, aborting!", type);
        return 0;
    }

    // Layer fields
    layer->setShouldInheritFromRootTransform(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();

    // Keep the legacy serialization/deserialization format...
    bool isFixed = stream->readBool();

    layer->m_backgroundColorSet = stream->readBool();

    bool isIframe = stream->readBool();
    // If we are a scrollable layer android, we are an iframe content
    if (isIframe && type == LTScrollableLayerAndroid) {
         IFrameContentLayerAndroid* iframeContent = new IFrameContentLayerAndroid(*layer);
         layer->unref();
         layer = iframeContent;
    } else if (isIframe) { // otherwise we are just the iframe (we use it to compute offset)
         IFrameLayerAndroid* iframe = new IFrameLayerAndroid(*layer);
         layer->unref();
         layer = iframe;
    }

    if (isFixed) {
        FixedPositioning* fixedPosition = new FixedPositioning(layer);

        fixedPosition->m_fixedLeft = readSkLength(stream);
        fixedPosition->m_fixedTop = readSkLength(stream);
        fixedPosition->m_fixedRight = readSkLength(stream);
        fixedPosition->m_fixedBottom = readSkLength(stream);
        fixedPosition->m_fixedMarginLeft = readSkLength(stream);
        fixedPosition->m_fixedMarginTop = readSkLength(stream);
        fixedPosition->m_fixedMarginRight = readSkLength(stream);
        fixedPosition->m_fixedMarginBottom = readSkLength(stream);
        fixedPosition->m_fixedRect = readSkRect(stream);
        fixedPosition->m_renderLayerPos.setX(stream->readS32());
        fixedPosition->m_renderLayerPos.setY(stream->readS32());

        layer->setFixedPosition(fixedPosition);
    } else {
        // Not a fixed element, bypass the values in the stream
        readSkLength(stream); // fixedLeft
        readSkLength(stream); // fixedTop
        readSkLength(stream); // fixedRight
        readSkLength(stream); // fixedBottom
        readSkLength(stream); // fixedMarginLeft
        readSkLength(stream); // fixedMarginTop
        readSkLength(stream); // fixedMarginRight
        readSkLength(stream); // fixedMarginBottom
        readSkRect(stream);   // fixedRect
        stream->readS32();    // renderLayerPos.x()
        stream->readS32();    // renderLayerPos.y()
    }

    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);
        SkBitmap contentsImage;
        contentsImage.unflatten(buffer);
        SkBitmapRef* imageRef = new SkBitmapRef(contentsImage);
        layer->setContentsImage(imageRef);
        delete imageRef;
    }
    bool hasRecordingPicture = stream->readBool();
    if (hasRecordingPicture) {
        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);
    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(version, stream);
        if (childLayer)
            layer->addChild(childLayer);
    }
    ALOGV("Created layer with id %d", layer->uniqueId());
    return layer;
}
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;
    }

    // Layer fields
    layer->setShouldInheritFromRootTransform(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);
        SkBitmap contentsImage;
        contentsImage.unflatten(buffer);
        SkBitmapRef* imageRef = new SkBitmapRef(contentsImage);
        layer->setContentsImage(imageRef);
        delete imageRef;
    }
    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;
}
bool TreeManager::drawGL(double currentTime, IntRect& viewRect,
                         SkRect& visibleRect, float scale,
                         bool enterFastSwapMode, bool* treesSwappedPtr, bool* newTreeHasAnimPtr,
                         TexturesResult* texturesResultPtr)
{
    m_fastSwapMode |= enterFastSwapMode;

    XLOG("drawGL, D %p, P %p, Q %p, fastSwap %d",
         m_drawingTree, m_paintingTree, m_queuedTree, m_fastSwapMode);

    bool ret = false;
    bool didTreeSwap = false;
    if (m_paintingTree) {
        XLOG("preparing painting tree %p", m_paintingTree);

        LayerAndroid* laTree = 0;
        if (m_paintingTree->countChildren()) {
            laTree = static_cast<LayerAndroid*>(m_paintingTree->getChild(0));
            ret |= laTree->evaluateAnimations(currentTime);
        }

        ret |= m_paintingTree->prepare(currentTime, viewRect,
                                       visibleRect, scale);

        if (laTree)
            laTree->computeTexturesAmount(texturesResultPtr);

        if (/*!m_fastSwapMode && */ m_paintingTree->isReady()) {
            XLOG("have painting tree %p ready, swapping!", m_paintingTree);
            didTreeSwap = true;
            swap();
            if (treesSwappedPtr)
                *treesSwappedPtr = true;
            if (laTree && newTreeHasAnimPtr)
                *newTreeHasAnimPtr = laTree->hasAnimations();
        }
    } else if (m_drawingTree) {
        XLOG("preparing drawing tree %p", m_drawingTree);
        ret |= m_drawingTree->prepare(currentTime, viewRect,
                                      visibleRect, scale);
        if (m_drawingTree->countChildren()) {
            LayerAndroid* laTree = static_cast<LayerAndroid*>(m_drawingTree->getChild(0));
            laTree->computeTexturesAmount(texturesResultPtr);
        }
    }


    if (m_drawingTree) {
        bool drawingReady = didTreeSwap || m_drawingTree->isReady();

        if (didTreeSwap || m_fastSwapMode || (drawingReady && !m_paintingTree))
            m_drawingTree->swapTiles();

        if (drawingReady) {
            // exit fast swap mode, as content is up to date
            m_fastSwapMode = false;
        } else {
            // drawing isn't ready, must redraw
            ret = true;
        }

        if (m_drawingTree->countChildren()) {
            LayerAndroid* laTree = static_cast<LayerAndroid*>(m_drawingTree->getChild(0));
            ret |= laTree->evaluateAnimations(currentTime);
        }
        XLOG("drawing tree %p", m_drawingTree);
        ret |= m_drawingTree->drawGL(viewRect, visibleRect, scale);
    } else if (m_paintingTree && m_paintingTree->state()) {
        // Dont have a drawing tree, draw white background
        Color defaultBackground = Color::white;
        m_paintingTree->state()->drawBackground(defaultBackground);
    }

    if (m_paintingTree) {
        XLOG("still have painting tree %p", m_paintingTree);
        return true;
    }

    return ret;
}