GraphicsLayerAndroid.cpp revision ed2ce36a1fac9f85b65edf34a1c241c2f73d806c
1/*
2 * Copyright (C) 2009 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#define LOG_TAG "GraphicsLayerAndroid"
18#define LOG_NDEBUG 1
19
20#include "config.h"
21#include "GraphicsLayerAndroid.h"
22
23#if USE(ACCELERATED_COMPOSITING)
24
25#include "AndroidAnimation.h"
26#include "AndroidLog.h"
27#include "Animation.h"
28#include "BaseLayerAndroid.h"
29#include "CachedImage.h"
30#include "CanvasLayer.h"
31#include "FixedBackgroundLayerAndroid.h"
32#include "FixedPositioning.h"
33#include "FloatRect.h"
34#include "GraphicsContext.h"
35#include "IFrameContentLayerAndroid.h"
36#include "IFrameLayerAndroid.h"
37#include "Image.h"
38#include "ImagesManager.h"
39#include "Layer.h"
40#include "LayerAndroid.h"
41#include "Length.h"
42#include "MediaLayer.h"
43#include "PictureLayerContent.h"
44#include "PlatformBridge.h"
45#include "PlatformGraphicsContextSkia.h"
46#include "RenderLayerBacking.h"
47#include "RenderView.h"
48#include "RotateTransformOperation.h"
49#include "ScaleTransformOperation.h"
50#include "ScrollableLayerAndroid.h"
51#include "SkCanvas.h"
52#include "SkRegion.h"
53#include "StyleCachedImage.h"
54#include "TransformationMatrix.h"
55#include "TranslateTransformOperation.h"
56
57#include <wtf/CurrentTime.h>
58#include <wtf/text/CString.h>
59
60using namespace std;
61
62static bool gPaused;
63static double gPausedDelay;
64
65namespace WebCore {
66
67static int gDebugGraphicsLayerAndroidInstances = 0;
68inline int GraphicsLayerAndroid::instancesCount()
69{
70    return gDebugGraphicsLayerAndroidInstances;
71}
72
73static String propertyIdToString(AnimatedPropertyID property)
74{
75    switch (property) {
76    case AnimatedPropertyWebkitTransform:
77        return "transform";
78    case AnimatedPropertyOpacity:
79        return "opacity";
80    case AnimatedPropertyBackgroundColor:
81        return "backgroundColor";
82    case AnimatedPropertyInvalid:
83        ASSERT_NOT_REACHED();
84    }
85    ASSERT_NOT_REACHED();
86    return "";
87}
88
89PassOwnPtr<GraphicsLayer> GraphicsLayer::create(GraphicsLayerClient* client)
90{
91    return new GraphicsLayerAndroid(client);
92}
93
94static RenderLayer* renderLayerFromClient(GraphicsLayerClient* client)
95{
96    return client ? client->owningLayer() : 0;
97}
98
99GraphicsLayerAndroid::GraphicsLayerAndroid(GraphicsLayerClient* client) :
100    GraphicsLayer(client),
101    m_needsSyncChildren(false),
102    m_needsSyncMask(false),
103    m_needsRepaint(false),
104    m_needsNotifyClient(false),
105    m_haveContents(false),
106    m_newImage(false),
107    m_image(0),
108    m_fixedBackgroundLayer(0),
109    m_foregroundLayer(0),
110    m_foregroundClipLayer(0)
111{
112    RenderLayer* renderLayer = renderLayerFromClient(m_client);
113    if (renderLayer && renderLayer->renderer()->isCanvas()) {
114        m_contentLayer = new CanvasLayer(renderLayer,
115                static_cast<HTMLCanvasElement*>(renderLayer->renderer()->node()));
116    } else
117        m_contentLayer = new LayerAndroid(renderLayer);
118    m_dirtyRegion.setEmpty();
119    gDebugGraphicsLayerAndroidInstances++;
120}
121
122GraphicsLayerAndroid::~GraphicsLayerAndroid()
123{
124    if (m_image)
125        m_image->deref();
126
127    m_contentLayer->unref();
128    SkSafeUnref(m_fixedBackgroundLayer);
129    SkSafeUnref(m_foregroundLayer);
130    SkSafeUnref(m_foregroundClipLayer);
131    gDebugGraphicsLayerAndroidInstances--;
132}
133
134void GraphicsLayerAndroid::setName(const String& name)
135{
136    GraphicsLayer::setName(name);
137}
138
139NativeLayer GraphicsLayerAndroid::nativeLayer() const
140{
141    ALOGV("(%x) nativeLayer", this);
142    return 0;
143}
144
145bool GraphicsLayerAndroid::setChildren(const Vector<GraphicsLayer*>& children)
146{
147    bool childrenChanged = GraphicsLayer::setChildren(children);
148    if (childrenChanged) {
149        m_needsSyncChildren = true;
150        askForSync();
151    }
152
153    return childrenChanged;
154}
155
156void GraphicsLayerAndroid::addChild(GraphicsLayer* childLayer)
157{
158#ifndef NDEBUG
159    const String& name = childLayer->name();
160    ALOGV("(%x) addChild: %x (%s)", this, childLayer, name.ascii().data());
161#endif
162    GraphicsLayer::addChild(childLayer);
163    m_needsSyncChildren = true;
164    askForSync();
165}
166
167void GraphicsLayerAndroid::addChildAtIndex(GraphicsLayer* childLayer, int index)
168{
169    ALOGV("(%x) addChild %x AtIndex %d", this, childLayer, index);
170    GraphicsLayer::addChildAtIndex(childLayer, index);
171    m_needsSyncChildren = true;
172    askForSync();
173}
174
175void GraphicsLayerAndroid::addChildBelow(GraphicsLayer* childLayer, GraphicsLayer* sibling)
176{
177    ALOGV("(%x) addChild %x Below %x", this, childLayer, sibling);
178    GraphicsLayer::addChildBelow(childLayer, sibling);
179    m_needsSyncChildren = true;
180    askForSync();
181}
182
183void GraphicsLayerAndroid::addChildAbove(GraphicsLayer* childLayer, GraphicsLayer* sibling)
184{
185    ALOGV("(%x) addChild %x Above %x", this, childLayer, sibling);
186    GraphicsLayer::addChildAbove(childLayer, sibling);
187    m_needsSyncChildren = true;
188    askForSync();
189}
190
191bool GraphicsLayerAndroid::replaceChild(GraphicsLayer* oldChild, GraphicsLayer* newChild)
192{
193    ALOGV("(%x) replaceChild %x by %x", this, oldChild, newChild);
194    bool ret = GraphicsLayer::replaceChild(oldChild, newChild);
195    if (ret) {
196        m_needsSyncChildren = true;
197        askForSync();
198    }
199    return ret;
200}
201
202void GraphicsLayerAndroid::setReplicatedLayer(GraphicsLayer* layer)
203{
204    GraphicsLayer::setReplicatedLayer(layer);
205    if (m_replicatedLayer) {
206        GraphicsLayerAndroid* graphicsLayer = static_cast<GraphicsLayerAndroid*>(m_replicatedLayer);
207        if (graphicsLayer->m_contentLayer)
208            graphicsLayer->m_contentLayer->setReplicatedLayer(m_contentLayer);
209        if (maskLayer()) {
210            GraphicsLayerAndroid* maskLayer = static_cast<GraphicsLayerAndroid*>(GraphicsLayer::maskLayer());
211            m_contentLayer->setMaskLayer(maskLayer->m_contentLayer);
212        }
213        m_contentLayer->setReplicatedLayerPosition(replicatedLayerPosition());
214        askForSync();
215    }
216}
217
218void GraphicsLayerAndroid::removeFromParent()
219{
220    ALOGV("(%x) removeFromParent()", this);
221    GraphicsLayerAndroid* parent = static_cast<GraphicsLayerAndroid*>(m_parent);
222    GraphicsLayer::removeFromParent();
223    // Update the parent's children.
224    if (parent) {
225        parent->m_needsSyncChildren = true;
226        askForSync();
227    }
228}
229
230void GraphicsLayerAndroid::updatePositionedLayers()
231{
232    RenderLayer* renderLayer = renderLayerFromClient(m_client);
233    if (!renderLayer)
234        return;
235    RenderView* view = static_cast<RenderView*>(renderLayer->renderer());
236
237    if (!view)
238        return;
239
240    // We will need the Iframe flag in the LayerAndroid tree for fixed position
241    if (view->isRenderIFrame() && !m_contentLayer->isIFrame()) {
242        LayerAndroid* layer = new IFrameLayerAndroid(*m_contentLayer);
243        m_contentLayer->unref();
244        m_contentLayer = layer;
245    }
246
247    // If we are a fixed position layer, just set it
248    if (view->isPositioned() && view->style()->position() == FixedPosition) {
249        m_contentLayer->setAbsolutePosition(false);
250        // We need to get the passed CSS properties for the element
251        SkLength left, top, right, bottom;
252        left = SkLength::convertLength(view->style()->left());
253        top = SkLength::convertLength(view->style()->top());
254        right = SkLength::convertLength(view->style()->right());
255        bottom = SkLength::convertLength(view->style()->bottom());
256
257        // We also need to get the margin...
258        SkLength marginLeft, marginTop, marginRight, marginBottom;
259        marginLeft = SkLength::convertLength(view->style()->marginLeft());
260        marginTop = SkLength::convertLength(view->style()->marginTop());
261        marginRight = SkLength::convertLength(view->style()->marginRight());
262        marginBottom = SkLength::convertLength(view->style()->marginBottom());
263
264        // In order to compute the fixed element's position, we need the width
265        // and height of the element when bottom or right is defined.
266        // And here we should use the non-overflowed value, that means, the
267        // overflowed content (e.g. outset shadow) will not be counted into the
268        // width and height.
269        int w = view->width();
270        int h = view->height();
271
272        int paintingOffsetX = - offsetFromRenderer().width();
273        int paintingOffsetY = - offsetFromRenderer().height();
274
275        SkRect viewRect;
276        viewRect.set(paintingOffsetX, paintingOffsetY, paintingOffsetX + w, paintingOffsetY + h);
277        IntPoint renderLayerPos(renderLayer->x(), renderLayer->y());
278
279        FixedPositioning* fixedPosition = m_contentLayer->fixedPosition();
280        if (!fixedPosition) {
281            fixedPosition = new FixedPositioning();
282            m_contentLayer->setFixedPosition(fixedPosition);
283        }
284
285        fixedPosition->setFixedPosition(left, top, right, bottom,
286                                        marginLeft, marginTop,
287                                        marginRight, marginBottom,
288                                        renderLayerPos,
289                                        viewRect);
290    } else if (view->isPositioned() && view->style()->position() == AbsolutePosition) {
291        m_contentLayer->setAbsolutePosition(true);
292    } else {
293        m_contentLayer->setFixedPosition(0);
294        m_contentLayer->setAbsolutePosition(false);
295    }
296}
297
298void GraphicsLayerAndroid::setPosition(const FloatPoint& point)
299{
300    if (point == m_position)
301        return;
302
303    GraphicsLayer::setPosition(point);
304
305    ALOGV("(%x) setPosition(%.2f,%.2f) pos(%.2f, %.2f) anchor(%.2f,%.2f) size(%.2f, %.2f)",
306        this, point.x(), point.y(), m_position.x(), m_position.y(),
307        m_anchorPoint.x(), m_anchorPoint.y(), m_size.width(), m_size.height());
308
309    m_contentLayer->setPosition(point.x(), point.y());
310    askForSync();
311}
312
313void GraphicsLayerAndroid::setPreserves3D(bool preserves3D)
314{
315    if (preserves3D == m_preserves3D)
316        return;
317
318    GraphicsLayer::setPreserves3D(preserves3D);
319    m_contentLayer->setPreserves3D(preserves3D);
320    askForSync();
321}
322
323void GraphicsLayerAndroid::setAnchorPoint(const FloatPoint3D& point)
324{
325    if (point == m_anchorPoint)
326        return;
327    GraphicsLayer::setAnchorPoint(point);
328    m_contentLayer->setAnchorPoint(point.x(), point.y());
329    m_contentLayer->setAnchorPointZ(point.z());
330    askForSync();
331}
332
333void GraphicsLayerAndroid::setSize(const FloatSize& size)
334{
335    if (size == m_size)
336        return;
337    ALOGV("(%x) layer %d setSize (%.2f,%.2f)", this,
338          m_contentLayer->uniqueId(), size.width(), size.height());
339    GraphicsLayer::setSize(size);
340
341    // If it is a media layer the size may have changed as a result of the media
342    // element (e.g. plugin) gaining focus. Therefore, we must sync the size of
343    // the focus' outline so that our UI thread can draw accordingly.
344    RenderLayer* layer = renderLayerFromClient(m_client);
345    if (layer && m_contentLayer->isMedia()) {
346        RenderBox* box = layer->renderBox();
347        int outline = box->view()->maximalOutlineSize();
348        static_cast<MediaLayer*>(m_contentLayer)->setOutlineSize(outline);
349        ALOGV("Media Outline: %d %p %p %p", outline, m_client, layer, box);
350        ALOGV("Media Size: %g,%g", size.width(), size.height());
351    }
352
353    m_contentLayer->setSize(size.width(), size.height());
354    setNeedsDisplay();
355    askForSync();
356}
357
358void GraphicsLayerAndroid::setBackfaceVisibility(bool b)
359{
360    if (b == m_backfaceVisibility)
361        return;
362
363    GraphicsLayer::setBackfaceVisibility(b);
364    m_contentLayer->setBackfaceVisibility(b);
365    askForSync();
366}
367
368void GraphicsLayerAndroid::setTransform(const TransformationMatrix& t)
369{
370    if (t == m_transform)
371        return;
372
373    GraphicsLayer::setTransform(t);
374    m_contentLayer->setTransform(t);
375    askForSync();
376}
377
378void GraphicsLayerAndroid::setChildrenTransform(const TransformationMatrix& t)
379{
380    if (t == m_childrenTransform)
381       return;
382    ALOGV("(%x) setChildrenTransform", this);
383
384    GraphicsLayer::setChildrenTransform(t);
385    m_contentLayer->setChildrenTransform(t);
386    for (unsigned int i = 0; i < m_children.size(); i++) {
387        GraphicsLayer* layer = m_children[i];
388        layer->setTransform(t);
389        if (layer->children().size())
390            layer->setChildrenTransform(t);
391    }
392    askForSync();
393}
394
395void GraphicsLayerAndroid::setMaskLayer(GraphicsLayer* layer)
396{
397    if (layer == m_maskLayer)
398        return;
399
400    GraphicsLayer::setMaskLayer(layer);
401    m_needsSyncMask = true;
402    askForSync();
403}
404
405void GraphicsLayerAndroid::setMasksToBounds(bool masksToBounds)
406{
407    if (masksToBounds == m_masksToBounds)
408        return;
409    GraphicsLayer::setMasksToBounds(masksToBounds);
410    m_needsSyncMask = true;
411    askForSync();
412}
413
414void GraphicsLayerAndroid::setDrawsContent(bool drawsContent)
415{
416    if (drawsContent == m_drawsContent)
417        return;
418    GraphicsLayer::setDrawsContent(drawsContent);
419    m_contentLayer->setVisible(drawsContent);
420    if (m_drawsContent) {
421        m_haveContents = true;
422        setNeedsDisplay();
423    }
424    askForSync();
425}
426
427void GraphicsLayerAndroid::setBackgroundColor(const Color& color)
428{
429    if (color == m_backgroundColor && m_backgroundColorSet)
430        return;
431    ALOGV("(%x) setBackgroundColor", this);
432    GraphicsLayer::setBackgroundColor(color);
433    SkColor c = SkColorSetARGB(color.alpha(), color.red(), color.green(), color.blue());
434    m_contentLayer->setBackgroundColor(c);
435    m_haveContents = true;
436    askForSync();
437}
438
439void GraphicsLayerAndroid::clearBackgroundColor()
440{
441    if (!m_backgroundColorSet)
442        return;
443
444    ALOGV("(%x) clearBackgroundColor", this);
445    GraphicsLayer::clearBackgroundColor();
446    askForSync();
447}
448
449void GraphicsLayerAndroid::setContentsOpaque(bool opaque)
450{
451    if (opaque == m_contentsOpaque)
452        return;
453    ALOGV("(%x) setContentsOpaque (%d)", this, opaque);
454    GraphicsLayer::setContentsOpaque(opaque);
455    m_haveContents = true;
456    askForSync();
457}
458
459void GraphicsLayerAndroid::setOpacity(float opacity)
460{
461    ALOGV("(%x) setOpacity: %.2f", this, opacity);
462    float clampedOpacity = max(0.0f, min(opacity, 1.0f));
463
464    if (clampedOpacity == m_opacity)
465        return;
466
467    ALOGV("(%x) setFinalOpacity: %.2f=>%.2f (%.2f)", this,
468        opacity, clampedOpacity, m_opacity);
469    GraphicsLayer::setOpacity(clampedOpacity);
470    m_contentLayer->setOpacity(clampedOpacity);
471    askForSync();
472}
473
474void GraphicsLayerAndroid::setNeedsDisplay()
475{
476    ALOGV("(%x) setNeedsDisplay()", this);
477    FloatRect rect(0, 0, m_size.width(), m_size.height());
478    setNeedsDisplayInRect(rect);
479}
480
481// Helper to set and clear the painting phase as well as auto restore the
482// original phase.
483class PaintingPhase {
484public:
485    PaintingPhase(GraphicsLayer* layer)
486        : m_layer(layer)
487        , m_originalPhase(layer->paintingPhase()) {}
488
489    ~PaintingPhase()
490    {
491        m_layer->setPaintingPhase(m_originalPhase);
492    }
493
494    void set(GraphicsLayerPaintingPhase phase)
495    {
496        m_layer->setPaintingPhase(phase);
497    }
498
499    void clear(GraphicsLayerPaintingPhase phase)
500    {
501        m_layer->setPaintingPhase(
502                (GraphicsLayerPaintingPhase) (m_originalPhase & ~phase));
503    }
504private:
505    GraphicsLayer* m_layer;
506    GraphicsLayerPaintingPhase m_originalPhase;
507};
508
509void GraphicsLayerAndroid::updateScrollingLayers()
510{
511#if ENABLE(ANDROID_OVERFLOW_SCROLL)
512    RenderLayer* layer = renderLayerFromClient(m_client);
513    if (!layer || !m_haveContents)
514        return;
515    bool hasOverflowScroll = m_foregroundLayer || m_contentLayer->contentIsScrollable();
516    bool layerNeedsOverflow = layer->hasOverflowScroll();
517    bool iframeNeedsOverflow = layer->isRootLayer() &&
518        layer->renderer()->frame()->ownerRenderer() &&
519        layer->renderer()->frame()->view()->hasOverflowScroll();
520
521    if (hasOverflowScroll && (layerNeedsOverflow || iframeNeedsOverflow)) {
522        // Already has overflow layers.
523        return;
524    }
525    if (!hasOverflowScroll && !layerNeedsOverflow && !iframeNeedsOverflow) {
526        // Does not need overflow layers.
527        return;
528    }
529    if (layerNeedsOverflow || iframeNeedsOverflow) {
530        ASSERT(!hasOverflowScroll);
531        if (layerNeedsOverflow) {
532            ASSERT(!m_foregroundLayer && !m_foregroundClipLayer);
533            m_foregroundLayer = new ScrollableLayerAndroid(layer);
534            m_foregroundLayer->setIntrinsicallyComposited(true);
535
536            m_foregroundClipLayer = new LayerAndroid(layer);
537            m_foregroundClipLayer->setMasksToBounds(true);
538            m_foregroundClipLayer->addChild(m_foregroundLayer);
539            m_contentLayer->addChild(m_foregroundClipLayer);
540            m_contentLayer->setHasOverflowChildren(true);
541        } else {
542            ASSERT(iframeNeedsOverflow && !m_contentLayer->contentIsScrollable());
543            // No need to copy the children as they will be removed and synced.
544            m_contentLayer->removeChildren();
545            // Replace the content layer with a scrollable layer.
546            LayerAndroid* layer = new IFrameContentLayerAndroid(*m_contentLayer);
547            m_contentLayer->unref();
548            m_contentLayer = layer;
549            if (m_parent) {
550                // The content layer has changed so the parent needs to sync
551                // children.
552                static_cast<GraphicsLayerAndroid*>(m_parent)->m_needsSyncChildren = true;
553            }
554        }
555        // Need to rebuild our children based on the new structure.
556        m_needsSyncChildren = true;
557    } else if (!m_contentLayer->isFixedBackground()) {
558        ASSERT(hasOverflowScroll && !layerNeedsOverflow && !iframeNeedsOverflow);
559        ASSERT(m_contentLayer);
560        // Remove the foreground layers.
561        if (m_foregroundLayer) {
562            m_foregroundLayer->unref();
563            m_foregroundLayer = 0;
564            m_foregroundClipLayer->unref();
565            m_foregroundClipLayer = 0;
566        }
567        // No need to copy over children.
568        m_contentLayer->removeChildren();
569        LayerAndroid* layer = new LayerAndroid(*m_contentLayer);
570        m_contentLayer->unref();
571        m_contentLayer = layer;
572        if (m_parent) {
573            // The content layer has changed so the parent needs to sync
574            // children.
575            static_cast<GraphicsLayerAndroid*>(m_parent)->m_needsSyncChildren = true;
576        }
577        // Children are all re-parented.
578        m_needsSyncChildren = true;
579    }
580#endif
581}
582
583void GraphicsLayerAndroid::updateFixedBackgroundLayers() {
584    RenderLayer* renderLayer = renderLayerFromClient(m_client);
585    if (!renderLayer)
586        return;
587    RenderView* view = static_cast<RenderView*>(renderLayer->renderer());
588    if (!view)
589        return;
590    if (view->isBody()) // body element is already handled
591        return;
592    if (!view->style()->hasFixedBackgroundImage())
593        return;
594    if (m_contentLayer->isFixedBackground())
595        return;
596    if (m_fixedBackgroundLayer) // already created
597        return;
598
599    // we will have:
600    // m_contentLayer
601    //   \- m_foregroundClipLayer
602    //     \- m_fixedBackgroundLayer
603    //   \- m_foregroundLayer
604
605    // Grab the background image and create a layer for it
606    // the layer will be fixed positioned.
607
608    Image* image = FixedBackgroundImageLayerAndroid::GetCachedImage(view->style());
609
610    if (!image)
611        return;
612
613    m_fixedBackgroundLayer = new FixedBackgroundImageLayerAndroid(view->style(),
614                                                                  view->width(),
615                                                                  view->height());
616
617    Color color = view->style()->visitedDependentColor(CSSPropertyBackgroundColor);
618    SkColor skiaColor = SkColorSetARGB(color.alpha(),
619                                       color.red(),
620                                       color.green(),
621                                       color.blue());
622    m_fixedBackgroundLayer->setBackgroundColor(skiaColor);
623
624    // We need to clip the background image to the bounds of the original element
625    m_foregroundClipLayer = new LayerAndroid(renderLayer);
626    m_foregroundClipLayer->setMasksToBounds(true);
627    m_foregroundClipLayer->addChild(m_fixedBackgroundLayer);
628
629    // We then want to display the content above the image background; webkit
630    // allow to paint background and foreground separately. For now, we'll create
631    // two layers; the one containing the background will be painted *without* the
632    // background image (but with the decorations, e.g. border)
633    m_foregroundLayer = new LayerAndroid(renderLayer);
634    m_foregroundLayer->setIntrinsicallyComposited(true);
635
636    // Finally, let's assemble all the layers under a FixedBackgroundLayerAndroid layer
637    LayerAndroid* layer = new FixedBackgroundLayerAndroid(*m_contentLayer);
638    m_contentLayer->unref();
639    m_contentLayer = layer;
640
641    m_contentLayer->addChild(m_foregroundClipLayer);
642    m_contentLayer->addChild(m_foregroundLayer);
643
644    m_needsRepaint = true;
645    m_needsSyncChildren = true;
646}
647
648void GraphicsLayerAndroid::updateScrollOffset() {
649    RenderLayer* layer = renderLayerFromClient(m_client);
650    if (!layer || !(m_foregroundLayer || m_contentLayer->contentIsScrollable()))
651        return;
652    if (m_foregroundLayer) {
653        IntSize scroll = layer->scrolledContentOffset();
654        m_foregroundLayer->setScrollOffset(IntPoint(scroll.width(), scroll.height()));
655    } else if (m_contentLayer->isIFrameContent()) {
656        IntPoint p(layer->renderer()->frame()->view()->scrollX(),
657                   layer->renderer()->frame()->view()->scrollY());
658        static_cast<IFrameContentLayerAndroid*>(m_contentLayer)->setIFrameScrollOffset(p);
659    }
660    askForSync();
661}
662
663bool GraphicsLayerAndroid::repaint()
664{
665    ALOGV("(%x) repaint(), gPaused(%d) m_needsRepaint(%d) m_haveContents(%d) ",
666          this, gPaused, m_needsRepaint, m_haveContents);
667
668    if (!gPaused && m_haveContents && m_needsRepaint && !m_image) {
669        // with SkPicture, we request the entire layer's content.
670        IntRect layerBounds(0, 0, m_size.width(), m_size.height());
671
672        RenderLayer* layer = renderLayerFromClient(m_client);
673        if (!layer)
674            return false;
675        if (m_foregroundLayer && !m_contentLayer->isFixedBackground()) {
676            PaintingPhase phase(this);
677            // Paint the background into a separate context.
678            phase.set(GraphicsLayerPaintBackground);
679            if (!paintContext(m_contentLayer, layerBounds))
680                return false;
681
682            // Construct the foreground layer and draw.
683            RenderBox* box = layer->renderBox();
684            int outline = box->view()->maximalOutlineSize();
685            IntRect contentsRect(0, 0,
686                                 box->borderLeft() + box->borderRight() + layer->scrollWidth()
687                                 + layer->verticalScrollbarWidth(),
688                                 box->borderTop() + box->borderBottom() + layer->scrollHeight()
689                                 + layer->horizontalScrollbarHeight());
690            contentsRect.inflate(outline);
691            // Update the foreground layer size.
692            m_foregroundLayer->setSize(contentsRect.width(), contentsRect.height());
693            // Paint everything else into the main recording canvas.
694            phase.clear(GraphicsLayerPaintBackground);
695
696            // Paint at 0,0.
697            IntSize scroll = layer->scrolledContentOffset();
698            layer->scrollToOffset(0, 0);
699            // At this point, it doesn't matter if painting failed.
700            (void) paintContext(m_foregroundLayer, contentsRect);
701            layer->scrollToOffset(scroll.width(), scroll.height());
702
703            // Construct the clip layer for masking the contents.
704            IntRect clip = layer->renderer()->absoluteBoundingBoxRect();
705            // absoluteBoundingBoxRect does not include the outline so we need
706            // to offset the position.
707            int x = box->borderLeft() + outline;
708            int y = box->borderTop() + outline;
709            int width = clip.width() - box->borderLeft() - box->borderRight();
710            int height = clip.height() - box->borderTop() - box->borderBottom();
711            m_foregroundClipLayer->setPosition(x, y);
712            m_foregroundClipLayer->setSize(width, height);
713
714            int rtlOffset = 0; // LTR uses no offset.
715            if (!layer->renderer()->style()->isLeftToRightDirection())
716                rtlOffset = layer->scrollWidth() - width; // Scroll all the way right.
717            m_foregroundLayer->setScrollOffset(IntPoint(scroll.width() + rtlOffset,
718                    scroll.height()));
719            // Need to offset the foreground layer by the clip layer in order
720            // for the contents to be in the correct position.
721            m_foregroundLayer->setPosition(-x, -y);
722            // Set the scrollable bounds of the layer.
723            static_cast<ScrollableLayerAndroid*>(m_foregroundLayer)->setScrollLimits(-x, -y, m_size.width(), m_size.height());
724
725            // Invalidate the entire layer for now, as webkit will only send the
726            // setNeedsDisplayInRect() for the visible (clipped) scrollable area,
727            // offsetting the invals by the scroll position would not be enough.
728            // TODO: have webkit send us invals even for non visible area
729            SkRegion region;
730            region.setRect(0, 0, contentsRect.width(), contentsRect.height());
731            m_foregroundLayer->markAsDirty(region);
732        } else if (m_contentLayer->isFixedBackground()) {
733            SkPicture* picture = new SkPicture();
734            SkCanvas* canvas = picture->beginRecording(layerBounds.width(),
735                                                       layerBounds.height(), 0);
736            if (canvas) {
737                  PaintingPhase phase(this);
738                  PlatformGraphicsContextSkia platformContext(canvas);
739                  GraphicsContext graphicsContext(&platformContext);
740
741                  // Paint the background (without the fixed image)...
742                  phase.set(GraphicsLayerPaintBackgroundDecorations);
743                  paintGraphicsLayerContents(graphicsContext, layerBounds);
744                  phase.clear(GraphicsLayerPaintBackgroundDecorations);
745
746                  // Paint the foreground...
747                  phase.set(GraphicsLayerPaintForeground);
748                  paintGraphicsLayerContents(graphicsContext, layerBounds);
749                  picture->endRecording();
750
751                  // Now set the content for that layer.
752                  PictureLayerContent* layerContent = new PictureLayerContent(picture);
753                  m_foregroundLayer->setContent(layerContent);
754                  SkSafeUnref(layerContent);
755            }
756            SkSafeUnref(picture);
757
758            m_foregroundLayer->setSize(layerBounds.width(), layerBounds.height());
759            m_foregroundClipLayer->setPosition(layerBounds.x(), layerBounds.y());
760            m_foregroundClipLayer->setSize(layerBounds.width(), layerBounds.height());
761        } else {
762
763            // If we are replicated, paint the mask
764            if (isReplicated()) {
765                GraphicsLayerAndroid* replicatedLayer = static_cast<GraphicsLayerAndroid*>(replicaLayer());
766                if (replicatedLayer->maskLayer()) {
767                     GraphicsLayerAndroid* mask = static_cast<GraphicsLayerAndroid*>(replicatedLayer->maskLayer());
768                     mask->paintContext(mask->m_contentLayer, layerBounds, false);
769                }
770            }
771
772            // If there is no contents clip, we can draw everything into one
773            // picture.
774            bool painting = paintContext(m_contentLayer, layerBounds);
775            if (!painting)
776                return false;
777            // Check for a scrollable iframe and report the scrolling
778            // limits based on the view size.
779            if (m_contentLayer->isIFrameContent()) {
780                FrameView* view = layer->renderer()->frame()->view();
781                static_cast<IFrameContentLayerAndroid*>(m_contentLayer)->setScrollLimits(
782                    m_position.x(), m_position.y(), view->layoutWidth(), view->layoutHeight());
783                ALOGV("setScrollLimits(%.2f, %.2f, w: %d h: %d) layer %d, frame scroll position is %d, %d",
784                      m_position.x(), m_position.y(), view->layoutWidth(), view->layoutHeight(),
785                      m_contentLayer->uniqueId(), view->scrollX(), view->scrollY());
786            }
787        }
788
789        ALOGV("(%x) repaint() on (%.2f,%.2f) contentlayer(%.2f,%.2f,%.2f,%.2f)paintGraphicsLayer called!",
790              this, m_size.width(), m_size.height(),
791              m_contentLayer->getPosition().fX,
792              m_contentLayer->getPosition().fY,
793              m_contentLayer->getSize().width(),
794              m_contentLayer->getSize().height());
795
796        m_contentLayer->markAsDirty(m_dirtyRegion);
797        m_dirtyRegion.setEmpty();
798        m_needsRepaint = false;
799
800        return true;
801    }
802    if (m_needsRepaint && m_image && m_newImage) {
803        // We need to tell the GL thread that we will need to repaint the
804        // texture. Only do so if we effectively have a new image!
805        m_contentLayer->markAsDirty(m_dirtyRegion);
806        m_dirtyRegion.setEmpty();
807        m_newImage = false;
808        m_needsRepaint = false;
809        return true;
810    }
811    return false;
812}
813
814SkPicture* GraphicsLayerAndroid::paintPicture(const IntRect& rect)
815{
816    SkPicture* picture = new SkPicture();
817    SkCanvas* canvas = picture->beginRecording(rect.width(), rect.height(), 0);
818    if (!canvas) {
819        picture->endRecording();
820        SkSafeUnref(picture);
821        return 0;
822    }
823
824    PlatformGraphicsContextSkia platformContext(canvas);
825    GraphicsContext graphicsContext(&platformContext);
826
827    paintGraphicsLayerContents(graphicsContext, rect);
828
829    return picture;
830}
831
832bool GraphicsLayerAndroid::paintContext(LayerAndroid* layer,
833                                        const IntRect& rect,
834                                        bool checkOptimisations)
835{
836    if (!layer)
837        return false;
838
839    SkPicture* picture = paintPicture(rect);
840    if (!picture)
841        return false;
842    picture->endRecording();
843
844    PictureLayerContent* layerContent = new PictureLayerContent(picture);
845    if (checkOptimisations)
846        layerContent->checkForOptimisations();
847    else
848        layerContent->setCheckForOptimisations(false);
849    layer->setContent(layerContent);
850    SkSafeUnref(layerContent);
851    SkSafeUnref(picture);
852    return true;
853}
854
855void GraphicsLayerAndroid::setNeedsDisplayInRect(const FloatRect& rect)
856{
857    // rect is in the render object coordinates
858
859    if (!m_image && !drawsContent()) {
860        ALOGV("(%x) setNeedsDisplay(%.2f,%.2f,%.2f,%.2f) doesn't have content, bypass...",
861              this, rect.x(), rect.y(), rect.width(), rect.height());
862        return;
863    }
864
865    SkRegion region;
866    region.setRect(rect.x(), rect.y(),
867                   rect.x() + rect.width(),
868                   rect.y() + rect.height());
869    m_dirtyRegion.op(region, SkRegion::kUnion_Op);
870
871    m_needsRepaint = true;
872    askForSync();
873}
874
875void GraphicsLayerAndroid::pauseDisplay(bool state)
876{
877    gPaused = state;
878    if (gPaused)
879        gPausedDelay = WTF::currentTime() + 1;
880}
881
882bool GraphicsLayerAndroid::addAnimation(const KeyframeValueList& valueList,
883                                        const IntSize& boxSize,
884                                        const Animation* anim,
885                                        const String& keyframesName,
886                                        double beginTime)
887{
888    if (!anim || anim->isEmptyOrZeroDuration() || valueList.size() < 2)
889        return false;
890
891    bool createdAnimations = false;
892    if (valueList.property() == AnimatedPropertyWebkitTransform) {
893        createdAnimations = createTransformAnimationsFromKeyframes(valueList,
894                                                                   anim,
895                                                                   keyframesName,
896                                                                   beginTime,
897                                                                   boxSize);
898    } else {
899        createdAnimations = createAnimationFromKeyframes(valueList,
900                                                         anim,
901                                                         keyframesName,
902                                                         beginTime);
903    }
904    if (createdAnimations)
905        askForSync();
906    return createdAnimations;
907}
908
909bool GraphicsLayerAndroid::createAnimationFromKeyframes(const KeyframeValueList& valueList,
910     const Animation* animation, const String& keyframesName, double beginTime)
911{
912    bool isKeyframe = valueList.size() > 2;
913    ALOGV("createAnimationFromKeyframes(%d), name(%s) beginTime(%.2f)",
914          isKeyframe, keyframesName.ascii().data(), beginTime);
915
916    switch (valueList.property()) {
917    case AnimatedPropertyInvalid: break;
918    case AnimatedPropertyWebkitTransform: break;
919    case AnimatedPropertyBackgroundColor: break;
920    case AnimatedPropertyOpacity: {
921        ALOGV("ANIMATEDPROPERTYOPACITY");
922
923        KeyframeValueList* operationsList = new KeyframeValueList(AnimatedPropertyOpacity);
924        for (unsigned int i = 0; i < valueList.size(); i++) {
925            FloatAnimationValue* originalValue = (FloatAnimationValue*)valueList.at(i);
926            RefPtr<TimingFunction> timingFunction(const_cast<TimingFunction*>(originalValue->timingFunction()));
927            FloatAnimationValue* value = new FloatAnimationValue(originalValue->keyTime(),
928                                                                 originalValue->value(),
929                                                                 timingFunction);
930            operationsList->insert(value);
931        }
932
933        RefPtr<AndroidOpacityAnimation> anim = AndroidOpacityAnimation::create(animation,
934                                                                               operationsList,
935                                                                               beginTime);
936        if (keyframesName.isEmpty())
937            anim->setName(propertyIdToString(valueList.property()));
938        else
939            anim->setName(keyframesName);
940
941        m_contentLayer->addAnimation(anim.release());
942        needsNotifyClient();
943        return true;
944    } break;
945    }
946    return false;
947}
948
949void GraphicsLayerAndroid::needsNotifyClient()
950{
951    m_needsNotifyClient = true;
952    askForSync();
953}
954
955bool GraphicsLayerAndroid::createTransformAnimationsFromKeyframes(const KeyframeValueList& valueList,
956                                                                  const Animation* animation,
957                                                                  const String& keyframesName,
958                                                                  double beginTime,
959                                                                  const IntSize& boxSize)
960{
961    ASSERT(valueList.property() == AnimatedPropertyWebkitTransform);
962    ALOGV("createTransformAnimationFromKeyframes, name(%s) beginTime(%.2f)",
963          keyframesName.ascii().data(), beginTime);
964
965    KeyframeValueList* operationsList = new KeyframeValueList(AnimatedPropertyWebkitTransform);
966    for (unsigned int i = 0; i < valueList.size(); i++) {
967        TransformAnimationValue* originalValue = (TransformAnimationValue*)valueList.at(i);
968        RefPtr<TimingFunction> timingFunction(const_cast<TimingFunction*>(originalValue->timingFunction()));
969        TransformAnimationValue* value = new TransformAnimationValue(originalValue->keyTime(),
970                                                                     originalValue->value(),
971                                                                     timingFunction);
972        operationsList->insert(value);
973    }
974
975    RefPtr<AndroidTransformAnimation> anim = AndroidTransformAnimation::create(animation,
976                                                                               operationsList,
977                                                                               beginTime);
978
979    if (keyframesName.isEmpty())
980        anim->setName(propertyIdToString(valueList.property()));
981    else
982        anim->setName(keyframesName);
983
984
985    m_contentLayer->addAnimation(anim.release());
986
987    needsNotifyClient();
988    return true;
989}
990
991void GraphicsLayerAndroid::removeAnimationsForProperty(AnimatedPropertyID anID)
992{
993    ALOGV("NRO removeAnimationsForProperty(%d)", anID);
994    m_contentLayer->removeAnimationsForProperty(anID);
995    askForSync();
996}
997
998void GraphicsLayerAndroid::removeAnimationsForKeyframes(const String& keyframesName)
999{
1000    ALOGV("NRO removeAnimationsForKeyframes(%s)", keyframesName.ascii().data());
1001    m_contentLayer->removeAnimationsForKeyframes(keyframesName);
1002    askForSync();
1003}
1004
1005void GraphicsLayerAndroid::pauseAnimation(const String& keyframesName)
1006{
1007    ALOGV("NRO pauseAnimation(%s)", keyframesName.ascii().data());
1008}
1009
1010void GraphicsLayerAndroid::suspendAnimations(double time)
1011{
1012    ALOGV("NRO suspendAnimations(%.2f)", time);
1013}
1014
1015void GraphicsLayerAndroid::resumeAnimations()
1016{
1017    ALOGV("NRO resumeAnimations()");
1018}
1019
1020void GraphicsLayerAndroid::setContentsToImage(Image* image)
1021{
1022    ALOGV("(%x) setContentsToImage", this, image);
1023    if (image && image != m_image) {
1024        image->ref();
1025        if (m_image)
1026            m_image->deref();
1027        m_image = image;
1028
1029        SkBitmapRef* bitmap = image->nativeImageForCurrentFrame();
1030        m_contentLayer->setContentsImage(bitmap);
1031
1032        m_haveContents = true;
1033        m_newImage = true;
1034    }
1035    if (!image && m_image) {
1036        m_contentLayer->setContentsImage(0);
1037        m_image->deref();
1038        m_image = 0;
1039    }
1040
1041    setNeedsDisplay();
1042    askForSync();
1043}
1044
1045void GraphicsLayerAndroid::setContentsToMedia(PlatformLayer* mediaLayer)
1046{
1047    // Only fullscreen video on Android, so media doesn't get it's own layer.
1048    // We might still have other layers though.
1049    if (m_contentLayer != mediaLayer && mediaLayer) {
1050
1051        // TODO add a copy method to LayerAndroid to sync everything
1052        // copy data from the original content layer to the new one
1053        mediaLayer->setPosition(m_contentLayer->getPosition().fX,
1054                                m_contentLayer->getPosition().fY);
1055        mediaLayer->setSize(m_contentLayer->getWidth(), m_contentLayer->getHeight());
1056        mediaLayer->setDrawTransform(*m_contentLayer->drawTransform());
1057
1058        mediaLayer->ref();
1059        m_contentLayer->unref();
1060        m_contentLayer = mediaLayer;
1061
1062        // If the parent exists then notify it to re-sync it's children
1063        if (m_parent) {
1064            GraphicsLayerAndroid* parent = static_cast<GraphicsLayerAndroid*>(m_parent);
1065            parent->m_needsSyncChildren = true;
1066        }
1067        m_needsSyncChildren = true;
1068
1069        setNeedsDisplay();
1070        askForSync();
1071    }
1072}
1073
1074PlatformLayer* GraphicsLayerAndroid::platformLayer() const
1075{
1076    ALOGV("platformLayer");
1077    return m_contentLayer;
1078}
1079
1080#ifndef NDEBUG
1081void GraphicsLayerAndroid::setDebugBackgroundColor(const Color& color)
1082{
1083}
1084
1085void GraphicsLayerAndroid::setDebugBorder(const Color& color, float borderWidth)
1086{
1087}
1088#endif
1089
1090void GraphicsLayerAndroid::setZPosition(float position)
1091{
1092    if (position == m_zPosition)
1093        return;
1094    ALOGV("(%x) setZPosition: %.2f", this, position);
1095    GraphicsLayer::setZPosition(position);
1096    askForSync();
1097}
1098
1099void GraphicsLayerAndroid::askForSync()
1100{
1101    if (!m_client)
1102        return;
1103
1104    if (m_client)
1105        m_client->notifySyncRequired(this);
1106}
1107
1108void GraphicsLayerAndroid::syncChildren()
1109{
1110    if (m_needsSyncChildren || isReplicated()) {
1111        m_contentLayer->removeChildren();
1112        LayerAndroid* layer = m_contentLayer;
1113
1114        if (isReplicated()) {
1115            GraphicsLayerAndroid* replicatedLayer = static_cast<GraphicsLayerAndroid*>(replicaLayer());
1116            m_contentLayer->addChild(replicatedLayer->m_contentLayer);
1117        }
1118
1119        if (m_contentLayer->isFixedBackground()) {
1120            m_contentLayer->addChild(m_foregroundClipLayer);
1121            m_contentLayer->addChild(m_foregroundLayer);
1122            layer = m_foregroundLayer;
1123            layer->removeChildren();
1124        } else if (m_foregroundClipLayer) {
1125            m_contentLayer->addChild(m_foregroundClipLayer);
1126            // Use the scrollable content layer as the parent of the children so
1127            // that they move with the content.
1128            layer = m_foregroundLayer;
1129            layer->removeChildren();
1130        }
1131
1132        for (unsigned int i = 0; i < m_children.size(); i++)
1133            layer->addChild(m_children[i]->platformLayer());
1134    }
1135    m_needsSyncChildren = false;
1136}
1137
1138void GraphicsLayerAndroid::syncMask()
1139{
1140    if (m_needsSyncMask) {
1141        if (m_maskLayer) {
1142            LayerAndroid* mask = m_maskLayer->platformLayer();
1143            m_contentLayer->setMaskLayer(mask);
1144        } else
1145            m_contentLayer->setMaskLayer(0);
1146
1147        m_contentLayer->setMasksToBounds(m_masksToBounds);
1148        m_needsSyncMask = false;
1149    }
1150}
1151
1152void GraphicsLayerAndroid::gatherRootLayers(Vector<const RenderLayer*>& list)
1153{
1154    RenderLayer* renderLayer = renderLayerFromClient(m_client);
1155    if (renderLayer) {
1156        const RenderLayer* rootLayer = renderLayer->root();
1157        bool found = false;
1158        for (unsigned int i = 0; i < list.size(); i++) {
1159            const RenderLayer* current = list[i];
1160            if (current == rootLayer) {
1161                found = true;
1162                break;
1163            }
1164        }
1165        if (!found)
1166            list.append(rootLayer);
1167    }
1168
1169    for (unsigned int i = 0; i < m_children.size(); i++) {
1170        GraphicsLayerAndroid* layer = static_cast<GraphicsLayerAndroid*>(m_children[i]);
1171        layer->gatherRootLayers(list);
1172    }
1173}
1174
1175void GraphicsLayerAndroid::syncCompositingStateForThisLayerOnly()
1176{
1177    if (m_contentLayer) {
1178        RenderLayer* renderLayer = renderLayerFromClient(m_client);
1179        int intrinsicallyComposited = renderLayer ? renderLayer->intrinsicallyComposited() : true;
1180        m_contentLayer->setIntrinsicallyComposited(intrinsicallyComposited);
1181    }
1182
1183    updateScrollingLayers();
1184    updateFixedBackgroundLayers();
1185    updatePositionedLayers();
1186    syncChildren();
1187    syncMask();
1188
1189    if (!gPaused || WTF::currentTime() >= gPausedDelay)
1190        repaint();
1191}
1192
1193void GraphicsLayerAndroid::syncCompositingState()
1194{
1195    for (unsigned int i = 0; i < m_children.size(); i++)
1196        m_children[i]->syncCompositingState();
1197
1198    syncCompositingStateForThisLayerOnly();
1199}
1200
1201void GraphicsLayerAndroid::notifyClientAnimationStarted()
1202{
1203    for (unsigned int i = 0; i < m_children.size(); i++)
1204        static_cast<GraphicsLayerAndroid*>(m_children[i])->notifyClientAnimationStarted();
1205
1206    if (m_needsNotifyClient) {
1207        if (client())
1208            client()->notifyAnimationStarted(this, WTF::currentTime());
1209        m_needsNotifyClient = false;
1210    }
1211}
1212
1213} // namespace WebCore
1214
1215#endif // USE(ACCELERATED_COMPOSITING)
1216