OSDN Git Service

69905039c12061a185025bde1a5df6cc6143618a
[android-x86/external-webkit.git] / Source / WebCore / platform / graphics / android / GraphicsLayerAndroid.cpp
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 #include "config.h"
18 #include "GraphicsLayerAndroid.h"
19
20 #if USE(ACCELERATED_COMPOSITING)
21
22 #include "AndroidAnimation.h"
23 #include "Animation.h"
24 #include "FloatRect.h"
25 #include "GraphicsContext.h"
26 #include "Image.h"
27 #include "ImagesManager.h"
28 #include "Layer.h"
29 #include "Length.h"
30 #include "MediaLayer.h"
31 #include "PlatformBridge.h"
32 #include "PlatformGraphicsContext.h"
33 #include "RenderLayerBacking.h"
34 #include "RenderView.h"
35 #include "RotateTransformOperation.h"
36 #include "ScaleTransformOperation.h"
37 #include "ScrollableLayerAndroid.h"
38 #include "SkCanvas.h"
39 #include "SkRegion.h"
40 #include "TransformationMatrix.h"
41 #include "TranslateTransformOperation.h"
42
43 #include <cutils/log.h>
44 #include <wtf/CurrentTime.h>
45 #include <wtf/text/CString.h>
46
47 #undef LOG
48 #define LOG(...) android_printLog(ANDROID_LOG_DEBUG, "GraphicsLayer", __VA_ARGS__)
49 #define MLOG(...) android_printLog(ANDROID_LOG_DEBUG, "GraphicsLayer", __VA_ARGS__)
50 #define TLOG(...) android_printLog(ANDROID_LOG_DEBUG, "GraphicsLayer", __VA_ARGS__)
51
52 #undef LOG
53 #define LOG(...)
54 #undef MLOG
55 #define MLOG(...)
56 #undef TLOG
57 #define TLOG(...)
58 #undef LAYER_DEBUG
59
60 using namespace std;
61
62 static bool gPaused;
63 static double gPausedDelay;
64
65 namespace WebCore {
66
67 static int gDebugGraphicsLayerAndroidInstances = 0;
68 inline int GraphicsLayerAndroid::instancesCount()
69 {
70     return gDebugGraphicsLayerAndroidInstances;
71 }
72
73 static 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
89 PassOwnPtr<GraphicsLayer> GraphicsLayer::create(GraphicsLayerClient* client)
90 {
91     return new GraphicsLayerAndroid(client);
92 }
93
94 SkLength convertLength(Length len)
95 {
96     SkLength length;
97     length.type = SkLength::Undefined;
98     length.value = 0;
99     if (len.type() == WebCore::Percent) {
100         length.type = SkLength::Percent;
101         length.value = len.percent();
102     }
103     if (len.type() == WebCore::Fixed) {
104         length.type = SkLength::Fixed;
105         length.value = len.value();
106     }
107     return length;
108 }
109
110 static RenderLayer* renderLayerFromClient(GraphicsLayerClient* client)
111 {
112     return client ? client->owningLayer() : 0;
113 }
114
115 GraphicsLayerAndroid::GraphicsLayerAndroid(GraphicsLayerClient* client) :
116     GraphicsLayer(client),
117     m_needsSyncChildren(false),
118     m_needsSyncMask(false),
119     m_needsRepaint(false),
120     m_needsNotifyClient(false),
121     m_haveContents(false),
122     m_newImage(false),
123     m_image(0),
124     m_foregroundLayer(0),
125     m_foregroundClipLayer(0)
126 {
127     RenderLayer* renderLayer = renderLayerFromClient(m_client);
128     m_contentLayer = new LayerAndroid(renderLayer);
129     m_dirtyRegion.setEmpty();
130     gDebugGraphicsLayerAndroidInstances++;
131 }
132
133 GraphicsLayerAndroid::~GraphicsLayerAndroid()
134 {
135     if (m_image)
136         m_image->deref();
137
138     m_contentLayer->unref();
139     SkSafeUnref(m_foregroundLayer);
140     SkSafeUnref(m_foregroundClipLayer);
141     gDebugGraphicsLayerAndroidInstances--;
142 }
143
144 void GraphicsLayerAndroid::setName(const String& name)
145 {
146     GraphicsLayer::setName(name);
147 }
148
149 NativeLayer GraphicsLayerAndroid::nativeLayer() const
150 {
151     LOG("(%x) nativeLayer", this);
152     return 0;
153 }
154
155 bool GraphicsLayerAndroid::setChildren(const Vector<GraphicsLayer*>& children)
156 {
157     bool childrenChanged = GraphicsLayer::setChildren(children);
158     if (childrenChanged) {
159         m_needsSyncChildren = true;
160         askForSync();
161     }
162
163     return childrenChanged;
164 }
165
166 void GraphicsLayerAndroid::addChild(GraphicsLayer* childLayer)
167 {
168 #ifndef NDEBUG
169     const String& name = childLayer->name();
170     LOG("(%x) addChild: %x (%s)", this, childLayer, name.latin1().data());
171 #endif
172     GraphicsLayer::addChild(childLayer);
173     m_needsSyncChildren = true;
174     askForSync();
175 }
176
177 void GraphicsLayerAndroid::addChildAtIndex(GraphicsLayer* childLayer, int index)
178 {
179     LOG("(%x) addChild %x AtIndex %d", this, childLayer, index);
180     GraphicsLayer::addChildAtIndex(childLayer, index);
181     m_needsSyncChildren = true;
182     askForSync();
183 }
184
185 void GraphicsLayerAndroid::addChildBelow(GraphicsLayer* childLayer, GraphicsLayer* sibling)
186 {
187     LOG("(%x) addChild %x Below %x", this, childLayer, sibling);
188     GraphicsLayer::addChildBelow(childLayer, sibling);
189     m_needsSyncChildren = true;
190     askForSync();
191 }
192
193 void GraphicsLayerAndroid::addChildAbove(GraphicsLayer* childLayer, GraphicsLayer* sibling)
194 {
195     LOG("(%x) addChild %x Above %x", this, childLayer, sibling);
196     GraphicsLayer::addChildAbove(childLayer, sibling);
197     m_needsSyncChildren = true;
198     askForSync();
199 }
200
201 bool GraphicsLayerAndroid::replaceChild(GraphicsLayer* oldChild, GraphicsLayer* newChild)
202 {
203     LOG("(%x) replaceChild %x by %x", this, oldChild, newChild);
204     bool ret = GraphicsLayer::replaceChild(oldChild, newChild);
205     if (ret) {
206         m_needsSyncChildren = true;
207         askForSync();
208     }
209     return ret;
210 }
211
212 void GraphicsLayerAndroid::removeFromParent()
213 {
214     LOG("(%x) removeFromParent()", this);
215     GraphicsLayerAndroid* parent = static_cast<GraphicsLayerAndroid*>(m_parent);
216     GraphicsLayer::removeFromParent();
217     // Update the parent's children.
218     if (parent) {
219         parent->m_needsSyncChildren = true;
220         askForSync();
221     }
222 }
223
224 void GraphicsLayerAndroid::updateFixedPosition()
225 {
226     RenderLayer* renderLayer = renderLayerFromClient(m_client);
227     if (!renderLayer)
228         return;
229     RenderView* view = static_cast<RenderView*>(renderLayer->renderer());
230
231     if (!view)
232         return;
233
234     // We will need the Iframe flag in the LayerAndroid tree for fixed position
235     if (view->isRenderIFrame())
236         m_contentLayer->setIsIframe(true);
237     // If we are a fixed position layer, just set it
238     if (view->isPositioned() && view->style()->position() == FixedPosition) {
239         // We need to get the passed CSS properties for the element
240         SkLength left, top, right, bottom;
241         left = convertLength(view->style()->left());
242         top = convertLength(view->style()->top());
243         right = convertLength(view->style()->right());
244         bottom = convertLength(view->style()->bottom());
245
246         // We also need to get the margin...
247         SkLength marginLeft, marginTop, marginRight, marginBottom;
248         marginLeft = convertLength(view->style()->marginLeft());
249         marginTop = convertLength(view->style()->marginTop());
250         marginRight = convertLength(view->style()->marginRight());
251         marginBottom = convertLength(view->style()->marginBottom());
252
253         // In order to compute the fixed element's position, we need the width
254         // and height of the element when bottom or right is defined.
255         // And here we should use the non-overflowed value, that means, the
256         // overflowed content (e.g. outset shadow) will not be counted into the
257         // width and height.
258         int w = view->width();
259         int h = view->height();
260
261         int paintingOffsetX = - offsetFromRenderer().width();
262         int paintingOffsetY = - offsetFromRenderer().height();
263
264         SkRect viewRect;
265         viewRect.set(paintingOffsetX, paintingOffsetY, paintingOffsetX + w, paintingOffsetY + h);
266         IntPoint renderLayerPos(renderLayer->x(), renderLayer->y());
267         m_contentLayer->setFixedPosition(left, top, right, bottom,
268                                          marginLeft, marginTop,
269                                          marginRight, marginBottom,
270                                          renderLayerPos,
271                                          viewRect);
272     }
273 }
274
275 void GraphicsLayerAndroid::setPosition(const FloatPoint& point)
276 {
277     if (point == m_position)
278         return;
279
280     GraphicsLayer::setPosition(point);
281
282 #ifdef LAYER_DEBUG_2
283     LOG("(%x) setPosition(%.2f,%.2f) pos(%.2f, %.2f) anchor(%.2f,%.2f) size(%.2f, %.2f)",
284         this, point.x(), point.y(), m_position.x(), m_position.y(),
285         m_anchorPoint.x(), m_anchorPoint.y(), m_size.width(), m_size.height());
286 #endif
287     m_contentLayer->setPosition(point.x(), point.y());
288     askForSync();
289 }
290
291 void GraphicsLayerAndroid::setPreserves3D(bool preserves3D)
292 {
293     if (preserves3D == m_preserves3D)
294         return;
295
296     GraphicsLayer::setPreserves3D(preserves3D);
297     m_contentLayer->setPreserves3D(preserves3D);
298     askForSync();
299 }
300
301 void GraphicsLayerAndroid::setAnchorPoint(const FloatPoint3D& point)
302 {
303     if (point == m_anchorPoint)
304         return;
305     GraphicsLayer::setAnchorPoint(point);
306     m_contentLayer->setAnchorPoint(point.x(), point.y());
307     m_contentLayer->setAnchorPointZ(point.z());
308     askForSync();
309 }
310
311 void GraphicsLayerAndroid::setSize(const FloatSize& size)
312 {
313     if (size == m_size)
314         return;
315     MLOG("(%x) setSize (%.2f,%.2f)", this, size.width(), size.height());
316     GraphicsLayer::setSize(size);
317
318     // If it is a media layer the size may have changed as a result of the media
319     // element (e.g. plugin) gaining focus. Therefore, we must sync the size of
320     // the focus' outline so that our UI thread can draw accordingly.
321     RenderLayer* layer = renderLayerFromClient(m_client);
322     if (layer && m_contentLayer->isMedia()) {
323         RenderBox* box = layer->renderBox();
324         int outline = box->view()->maximalOutlineSize();
325         static_cast<MediaLayer*>(m_contentLayer)->setOutlineSize(outline);
326         LOG("Media Outline: %d %p %p %p", outline, m_client, layer, box);
327         LOG("Media Size: %g,%g", size.width(), size.height());
328     }
329
330     m_contentLayer->setSize(size.width(), size.height());
331     setNeedsDisplay();
332     askForSync();
333 }
334
335 void GraphicsLayerAndroid::setBackfaceVisibility(bool b)
336 {
337     if (b == m_backfaceVisibility)
338         return;
339
340     GraphicsLayer::setBackfaceVisibility(b);
341     m_contentLayer->setBackfaceVisibility(b);
342     askForSync();
343 }
344
345 void GraphicsLayerAndroid::setTransform(const TransformationMatrix& t)
346 {
347     if (t == m_transform)
348         return;
349
350     GraphicsLayer::setTransform(t);
351     m_contentLayer->setTransform(t);
352     askForSync();
353 }
354
355 void GraphicsLayerAndroid::setChildrenTransform(const TransformationMatrix& t)
356 {
357     if (t == m_childrenTransform)
358        return;
359     LOG("(%x) setChildrenTransform", this);
360
361     GraphicsLayer::setChildrenTransform(t);
362     m_contentLayer->setChildrenTransform(t);
363     for (unsigned int i = 0; i < m_children.size(); i++) {
364         GraphicsLayer* layer = m_children[i];
365         layer->setTransform(t);
366         if (layer->children().size())
367             layer->setChildrenTransform(t);
368     }
369     askForSync();
370 }
371
372 void GraphicsLayerAndroid::setMaskLayer(GraphicsLayer* layer)
373 {
374     if (layer == m_maskLayer)
375         return;
376
377     GraphicsLayer::setMaskLayer(layer);
378     m_needsSyncMask = true;
379     askForSync();
380 }
381
382 void GraphicsLayerAndroid::setMasksToBounds(bool masksToBounds)
383 {
384     if (masksToBounds == m_masksToBounds)
385         return;
386     GraphicsLayer::setMasksToBounds(masksToBounds);
387     m_needsSyncMask = true;
388     askForSync();
389 }
390
391 void GraphicsLayerAndroid::setDrawsContent(bool drawsContent)
392 {
393     if (drawsContent == m_drawsContent)
394         return;
395     GraphicsLayer::setDrawsContent(drawsContent);
396     m_contentLayer->setVisible(drawsContent);
397     if (m_drawsContent) {
398         m_haveContents = true;
399         setNeedsDisplay();
400     }
401     askForSync();
402 }
403
404 void GraphicsLayerAndroid::setBackgroundColor(const Color& color)
405 {
406     if (color == m_backgroundColor && m_backgroundColorSet)
407         return;
408     LOG("(%x) setBackgroundColor", this);
409     GraphicsLayer::setBackgroundColor(color);
410     SkColor c = SkColorSetARGB(color.alpha(), color.red(), color.green(), color.blue());
411     m_contentLayer->setBackgroundColor(c);
412     m_haveContents = true;
413     askForSync();
414 }
415
416 void GraphicsLayerAndroid::clearBackgroundColor()
417 {
418     if (!m_backgroundColorSet)
419         return;
420
421     LOG("(%x) clearBackgroundColor", this);
422     GraphicsLayer::clearBackgroundColor();
423     askForSync();
424 }
425
426 void GraphicsLayerAndroid::setContentsOpaque(bool opaque)
427 {
428     if (opaque == m_contentsOpaque)
429         return;
430     LOG("(%x) setContentsOpaque (%d)", this, opaque);
431     GraphicsLayer::setContentsOpaque(opaque);
432     m_haveContents = true;
433     askForSync();
434 }
435
436 void GraphicsLayerAndroid::setOpacity(float opacity)
437 {
438     LOG("(%x) setOpacity: %.2f", this, opacity);
439     float clampedOpacity = max(0.0f, min(opacity, 1.0f));
440
441     if (clampedOpacity == m_opacity)
442         return;
443
444     MLOG("(%x) setFinalOpacity: %.2f=>%.2f (%.2f)", this,
445         opacity, clampedOpacity, m_opacity);
446     GraphicsLayer::setOpacity(clampedOpacity);
447     m_contentLayer->setOpacity(clampedOpacity);
448     askForSync();
449 }
450
451 void GraphicsLayerAndroid::setNeedsDisplay()
452 {
453     LOG("(%x) setNeedsDisplay()", this);
454     FloatRect rect(0, 0, m_size.width(), m_size.height());
455     setNeedsDisplayInRect(rect);
456 }
457
458 // Helper to set and clear the painting phase as well as auto restore the
459 // original phase.
460 class PaintingPhase {
461 public:
462     PaintingPhase(GraphicsLayer* layer)
463         : m_layer(layer)
464         , m_originalPhase(layer->paintingPhase()) {}
465
466     ~PaintingPhase()
467     {
468         m_layer->setPaintingPhase(m_originalPhase);
469     }
470
471     void set(GraphicsLayerPaintingPhase phase)
472     {
473         m_layer->setPaintingPhase(phase);
474     }
475
476     void clear(GraphicsLayerPaintingPhase phase)
477     {
478         m_layer->setPaintingPhase(
479                 (GraphicsLayerPaintingPhase) (m_originalPhase & ~phase));
480     }
481 private:
482     GraphicsLayer* m_layer;
483     GraphicsLayerPaintingPhase m_originalPhase;
484 };
485
486 void GraphicsLayerAndroid::updateScrollingLayers()
487 {
488 #if ENABLE(ANDROID_OVERFLOW_SCROLL)
489     RenderLayer* layer = renderLayerFromClient(m_client);
490     if (!layer || !m_haveContents)
491         return;
492     bool hasOverflowScroll = m_foregroundLayer || m_contentLayer->contentIsScrollable();
493     bool layerNeedsOverflow = layer->hasOverflowScroll();
494     bool iframeNeedsOverflow = layer->isRootLayer() &&
495         layer->renderer()->frame()->ownerRenderer() &&
496         layer->renderer()->frame()->view()->hasOverflowScroll();
497
498     if (hasOverflowScroll && (layerNeedsOverflow || iframeNeedsOverflow)) {
499         // Already has overflow layers.
500         return;
501     }
502     if (!hasOverflowScroll && !layerNeedsOverflow && !iframeNeedsOverflow) {
503         // Does not need overflow layers.
504         return;
505     }
506     if (layerNeedsOverflow || iframeNeedsOverflow) {
507         ASSERT(!hasOverflowScroll);
508         if (layerNeedsOverflow) {
509             ASSERT(!m_foregroundLayer && !m_foregroundClipLayer);
510             m_foregroundLayer = new ScrollableLayerAndroid(layer);
511             m_foregroundClipLayer = new LayerAndroid(layer);
512             m_foregroundClipLayer->setMasksToBounds(true);
513             m_foregroundClipLayer->addChild(m_foregroundLayer);
514             m_contentLayer->addChild(m_foregroundClipLayer);
515             m_contentLayer->setHasOverflowChildren(true);
516         } else {
517             ASSERT(iframeNeedsOverflow && !m_contentLayer->contentIsScrollable());
518             // No need to copy the children as they will be removed and synced.
519             m_contentLayer->removeChildren();
520             // Replace the content layer with a scrollable layer.
521             LayerAndroid* layer = new ScrollableLayerAndroid(*m_contentLayer);
522             m_contentLayer->unref();
523             m_contentLayer = layer;
524             if (m_parent) {
525                 // The content layer has changed so the parent needs to sync
526                 // children.
527                 static_cast<GraphicsLayerAndroid*>(m_parent)->m_needsSyncChildren = true;
528             }
529         }
530         // Need to rebuild our children based on the new structure.
531         m_needsSyncChildren = true;
532     } else {
533         ASSERT(hasOverflowScroll && !layerNeedsOverflow && !iframeNeedsOverflow);
534         ASSERT(m_contentLayer);
535         // Remove the foreground layers.
536         if (m_foregroundLayer) {
537             m_foregroundLayer->unref();
538             m_foregroundLayer = 0;
539             m_foregroundClipLayer->unref();
540             m_foregroundClipLayer = 0;
541         }
542         // No need to copy over children.
543         m_contentLayer->removeChildren();
544         LayerAndroid* layer = new LayerAndroid(*m_contentLayer);
545         m_contentLayer->unref();
546         m_contentLayer = layer;
547         if (m_parent) {
548             // The content layer has changed so the parent needs to sync
549             // children.
550             static_cast<GraphicsLayerAndroid*>(m_parent)->m_needsSyncChildren = true;
551         }
552         // Children are all re-parented.
553         m_needsSyncChildren = true;
554     }
555 #endif
556 }
557
558 bool GraphicsLayerAndroid::repaint()
559 {
560     LOG("(%x) repaint(), gPaused(%d) m_needsRepaint(%d) m_haveContents(%d) ",
561         this, gPaused, m_needsRepaint, m_haveContents);
562
563     if (!gPaused && m_haveContents && m_needsRepaint && !m_image) {
564         // with SkPicture, we request the entire layer's content.
565         IntRect layerBounds(0, 0, m_size.width(), m_size.height());
566
567         RenderLayer* layer = renderLayerFromClient(m_client);
568         if (!layer)
569             return false;
570         if (m_foregroundLayer) {
571             PaintingPhase phase(this);
572             // Paint the background into a separate context.
573             phase.set(GraphicsLayerPaintBackground);
574             if (!paintContext(m_contentLayer->recordContext(), layerBounds))
575                 return false;
576             m_contentLayer->checkTextPresence();
577
578             // Construct the foreground layer and draw.
579             RenderBox* box = layer->renderBox();
580             int outline = box->view()->maximalOutlineSize();
581             IntRect contentsRect(0, 0,
582                                  box->borderLeft() + box->borderRight() + layer->scrollWidth(),
583                                  box->borderTop() + box->borderBottom() + layer->scrollHeight());
584             contentsRect.inflate(outline);
585             // Update the foreground layer size.
586             m_foregroundLayer->setSize(contentsRect.width(), contentsRect.height());
587             // Paint everything else into the main recording canvas.
588             phase.clear(GraphicsLayerPaintBackground);
589
590             // Paint at 0,0.
591             IntSize scroll = layer->scrolledContentOffset();
592             layer->scrollToOffset(0, 0);
593             // At this point, it doesn't matter if painting failed.
594             (void) paintContext(m_foregroundLayer->recordContext(), contentsRect);
595             m_foregroundLayer->checkTextPresence();
596             layer->scrollToOffset(scroll.width(), scroll.height());
597
598             // Construct the clip layer for masking the contents.
599             IntRect clip = layer->renderer()->absoluteBoundingBoxRect();
600             // absoluteBoundingBoxRect does not include the outline so we need
601             // to offset the position.
602             int x = box->borderLeft() + outline;
603             int y = box->borderTop() + outline;
604             int width = clip.width() - box->borderLeft() - box->borderRight();
605             int height = clip.height() - box->borderTop() - box->borderBottom();
606             m_foregroundClipLayer->setPosition(x, y);
607             m_foregroundClipLayer->setSize(width, height);
608
609             // Need to offset the foreground layer by the clip layer in order
610             // for the contents to be in the correct position.
611             m_foregroundLayer->setPosition(-x, -y);
612             // Set the scrollable bounds of the layer.
613             m_foregroundLayer->setScrollLimits(-x, -y, m_size.width(), m_size.height());
614
615             // Invalidate the entire layer for now, as webkit will only send the
616             // setNeedsDisplayInRect() for the visible (clipped) scrollable area,
617             // offsetting the invals by the scroll position would not be enough.
618             // TODO: have webkit send us invals even for non visible area
619             SkRegion region;
620             region.setRect(0, 0, contentsRect.width(), contentsRect.height());
621             m_foregroundLayer->markAsDirty(region);
622             m_foregroundLayer->needsRepaint();
623         } else {
624             // If there is no contents clip, we can draw everything into one
625             // picture.
626             if (!paintContext(m_contentLayer->recordContext(), layerBounds))
627                 return false;
628             m_contentLayer->checkTextPresence();
629             // Check for a scrollable iframe and report the scrolling
630             // limits based on the view size.
631             if (m_contentLayer->contentIsScrollable()) {
632                 FrameView* view = layer->renderer()->frame()->view();
633                 static_cast<ScrollableLayerAndroid*>(m_contentLayer)->setScrollLimits(
634                     m_position.x(), m_position.y(), view->layoutWidth(), view->layoutHeight());
635             }
636         }
637
638         LOG("(%x) repaint() on (%.2f,%.2f) contentlayer(%.2f,%.2f,%.2f,%.2f)paintGraphicsLayer called!",
639             this, m_size.width(), m_size.height(),
640             m_contentLayer->getPosition().fX,
641             m_contentLayer->getPosition().fY,
642             m_contentLayer->getSize().width(),
643             m_contentLayer->getSize().height());
644
645         m_contentLayer->markAsDirty(m_dirtyRegion);
646         m_dirtyRegion.setEmpty();
647         m_contentLayer->needsRepaint();
648         m_needsRepaint = false;
649
650         return true;
651     }
652     if (m_needsRepaint && m_image && m_newImage) {
653         // We need to tell the GL thread that we will need to repaint the
654         // texture. Only do so if we effectively have a new image!
655         m_contentLayer->markAsDirty(m_dirtyRegion);
656         m_dirtyRegion.setEmpty();
657         m_contentLayer->needsRepaint();
658         m_newImage = false;
659         m_needsRepaint = false;
660         return true;
661     }
662     return false;
663 }
664
665 bool GraphicsLayerAndroid::paintContext(SkPicture* context,
666                                         const IntRect& rect)
667 {
668     SkAutoPictureRecord arp(context, rect.width(), rect.height());
669     SkCanvas* canvas = arp.getRecordingCanvas();
670
671     if (!canvas)
672         return false;
673
674     PlatformGraphicsContext platformContext(canvas);
675     GraphicsContext graphicsContext(&platformContext);
676
677     paintGraphicsLayerContents(graphicsContext, rect);
678     return true;
679 }
680
681 void GraphicsLayerAndroid::setNeedsDisplayInRect(const FloatRect& rect)
682 {
683     // rect is in the render object coordinates
684
685     if (!m_image && !drawsContent()) {
686         LOG("(%x) setNeedsDisplay(%.2f,%.2f,%.2f,%.2f) doesn't have content, bypass...",
687             this, rect.x(), rect.y(), rect.width(), rect.height());
688         return;
689     }
690
691     SkRegion region;
692     region.setRect(rect.x(), rect.y(),
693                    rect.x() + rect.width(),
694                    rect.y() + rect.height());
695     m_dirtyRegion.op(region, SkRegion::kUnion_Op);
696
697     m_needsRepaint = true;
698     askForSync();
699 }
700
701 void GraphicsLayerAndroid::pauseDisplay(bool state)
702 {
703     gPaused = state;
704     if (gPaused)
705         gPausedDelay = WTF::currentTime() + 1;
706 }
707
708 bool GraphicsLayerAndroid::addAnimation(const KeyframeValueList& valueList,
709                                         const IntSize& boxSize,
710                                         const Animation* anim,
711                                         const String& keyframesName,
712                                         double beginTime)
713 {
714     if (!anim || anim->isEmptyOrZeroDuration() || valueList.size() < 2)
715         return false;
716
717     bool createdAnimations = false;
718     if (valueList.property() == AnimatedPropertyWebkitTransform) {
719         createdAnimations = createTransformAnimationsFromKeyframes(valueList,
720                                                                    anim,
721                                                                    keyframesName,
722                                                                    beginTime,
723                                                                    boxSize);
724     } else {
725         createdAnimations = createAnimationFromKeyframes(valueList,
726                                                          anim,
727                                                          keyframesName,
728                                                          beginTime);
729     }
730     if (createdAnimations)
731         askForSync();
732     return createdAnimations;
733 }
734
735 bool GraphicsLayerAndroid::createAnimationFromKeyframes(const KeyframeValueList& valueList,
736      const Animation* animation, const String& keyframesName, double beginTime)
737 {
738     bool isKeyframe = valueList.size() > 2;
739     TLOG("createAnimationFromKeyframes(%d), name(%s) beginTime(%.2f)",
740         isKeyframe, keyframesName.latin1().data(), beginTime);
741
742     switch (valueList.property()) {
743     case AnimatedPropertyInvalid: break;
744     case AnimatedPropertyWebkitTransform: break;
745     case AnimatedPropertyBackgroundColor: break;
746     case AnimatedPropertyOpacity: {
747         MLOG("ANIMATEDPROPERTYOPACITY");
748
749         KeyframeValueList* operationsList = new KeyframeValueList(AnimatedPropertyOpacity);
750         for (unsigned int i = 0; i < valueList.size(); i++) {
751             FloatAnimationValue* originalValue = (FloatAnimationValue*)valueList.at(i);
752             PassRefPtr<TimingFunction> timingFunction(const_cast<TimingFunction*>(originalValue->timingFunction()));
753             FloatAnimationValue* value = new FloatAnimationValue(originalValue->keyTime(),
754                                                                  originalValue->value(),
755                                                                  timingFunction);
756             operationsList->insert(value);
757         }
758
759         RefPtr<AndroidOpacityAnimation> anim = AndroidOpacityAnimation::create(animation,
760                                                                                operationsList,
761                                                                                beginTime);
762         if (keyframesName.isEmpty())
763             anim->setName(propertyIdToString(valueList.property()));
764         else
765             anim->setName(keyframesName);
766
767         m_contentLayer->addAnimation(anim.release());
768         needsNotifyClient();
769         return true;
770     } break;
771     }
772     return false;
773 }
774
775 void GraphicsLayerAndroid::needsNotifyClient()
776 {
777     m_needsNotifyClient = true;
778     askForSync();
779 }
780
781 bool GraphicsLayerAndroid::createTransformAnimationsFromKeyframes(const KeyframeValueList& valueList,
782                                                                   const Animation* animation,
783                                                                   const String& keyframesName,
784                                                                   double beginTime,
785                                                                   const IntSize& boxSize)
786 {
787     ASSERT(valueList.property() == AnimatedPropertyWebkitTransform);
788     TLOG("createTransformAnimationFromKeyframes, name(%s) beginTime(%.2f)",
789         keyframesName.latin1().data(), beginTime);
790
791     KeyframeValueList* operationsList = new KeyframeValueList(AnimatedPropertyWebkitTransform);
792     for (unsigned int i = 0; i < valueList.size(); i++) {
793         TransformAnimationValue* originalValue = (TransformAnimationValue*)valueList.at(i);
794         PassRefPtr<TimingFunction> timingFunction(const_cast<TimingFunction*>(originalValue->timingFunction()));
795         TransformAnimationValue* value = new TransformAnimationValue(originalValue->keyTime(),
796                                                                      originalValue->value(),
797                                                                      timingFunction);
798         operationsList->insert(value);
799     }
800
801     RefPtr<AndroidTransformAnimation> anim = AndroidTransformAnimation::create(animation,
802                                                                                operationsList,
803                                                                                beginTime);
804
805     if (keyframesName.isEmpty())
806         anim->setName(propertyIdToString(valueList.property()));
807     else
808         anim->setName(keyframesName);
809
810
811     m_contentLayer->addAnimation(anim.release());
812
813     needsNotifyClient();
814     return true;
815 }
816
817 void GraphicsLayerAndroid::removeAnimationsForProperty(AnimatedPropertyID anID)
818 {
819     TLOG("NRO removeAnimationsForProperty(%d)", anID);
820     m_contentLayer->removeAnimationsForProperty(anID);
821     askForSync();
822 }
823
824 void GraphicsLayerAndroid::removeAnimationsForKeyframes(const String& keyframesName)
825 {
826     TLOG("NRO removeAnimationsForKeyframes(%s)", keyframesName.latin1().data());
827     m_contentLayer->removeAnimationsForKeyframes(keyframesName);
828     askForSync();
829 }
830
831 void GraphicsLayerAndroid::pauseAnimation(const String& keyframesName)
832 {
833     TLOG("NRO pauseAnimation(%s)", keyframesName.latin1().data());
834 }
835
836 void GraphicsLayerAndroid::suspendAnimations(double time)
837 {
838     TLOG("NRO suspendAnimations(%.2f)", time);
839 }
840
841 void GraphicsLayerAndroid::resumeAnimations()
842 {
843     TLOG("NRO resumeAnimations()");
844 }
845
846 void GraphicsLayerAndroid::setContentsToImage(Image* image)
847 {
848     TLOG("(%x) setContentsToImage", this, image);
849     if (image && image != m_image) {
850         image->ref();
851         if (m_image)
852             m_image->deref();
853         m_image = image;
854
855         SkBitmapRef* bitmap = image->nativeImageForCurrentFrame();
856         m_contentLayer->setContentsImage(bitmap);
857
858         m_haveContents = true;
859         m_newImage = true;
860     }
861     if (!image && m_image) {
862         m_contentLayer->setContentsImage(0);
863         m_image->deref();
864         m_image = 0;
865     }
866
867     setNeedsDisplay();
868     askForSync();
869 }
870
871 void GraphicsLayerAndroid::setContentsToMedia(PlatformLayer* mediaLayer)
872 {
873     // Only fullscreen video on Android, so media doesn't get it's own layer.
874     // We might still have other layers though.
875     if (m_contentLayer != mediaLayer && mediaLayer) {
876
877         // TODO add a copy method to LayerAndroid to sync everything
878         // copy data from the original content layer to the new one
879         mediaLayer->setPosition(m_contentLayer->getPosition().fX,
880                                 m_contentLayer->getPosition().fY);
881         mediaLayer->setSize(m_contentLayer->getWidth(), m_contentLayer->getHeight());
882         mediaLayer->setDrawTransform(*m_contentLayer->drawTransform());
883
884         mediaLayer->ref();
885         m_contentLayer->unref();
886         m_contentLayer = mediaLayer;
887
888         // If the parent exists then notify it to re-sync it's children
889         if (m_parent) {
890             GraphicsLayerAndroid* parent = static_cast<GraphicsLayerAndroid*>(m_parent);
891             parent->m_needsSyncChildren = true;
892         }
893         m_needsSyncChildren = true;
894
895         setNeedsDisplay();
896         askForSync();
897     }
898 }
899
900 PlatformLayer* GraphicsLayerAndroid::platformLayer() const
901 {
902     LOG("platformLayer");
903     return m_contentLayer;
904 }
905
906 #ifndef NDEBUG
907 void GraphicsLayerAndroid::setDebugBackgroundColor(const Color& color)
908 {
909 }
910
911 void GraphicsLayerAndroid::setDebugBorder(const Color& color, float borderWidth)
912 {
913 }
914 #endif
915
916 void GraphicsLayerAndroid::setZPosition(float position)
917 {
918     if (position == m_zPosition)
919         return;
920     LOG("(%x) setZPosition: %.2f", this, position);
921     GraphicsLayer::setZPosition(position);
922     askForSync();
923 }
924
925 void GraphicsLayerAndroid::askForSync()
926 {
927     if (!m_client)
928         return;
929
930     if (m_client)
931         m_client->notifySyncRequired(this);
932 }
933
934 void GraphicsLayerAndroid::syncChildren()
935 {
936     if (m_needsSyncChildren) {
937         m_contentLayer->removeChildren();
938         LayerAndroid* layer = m_contentLayer;
939         if (m_foregroundClipLayer) {
940             m_contentLayer->addChild(m_foregroundClipLayer);
941             // Use the scrollable content layer as the parent of the children so
942             // that they move with the content.
943             layer = m_foregroundLayer;
944             layer->removeChildren();
945         }
946         for (unsigned int i = 0; i < m_children.size(); i++)
947             layer->addChild(m_children[i]->platformLayer());
948         m_needsSyncChildren = false;
949     }
950 }
951
952 void GraphicsLayerAndroid::syncMask()
953 {
954     if (m_needsSyncMask) {
955         if (m_maskLayer) {
956             LayerAndroid* mask = m_maskLayer->platformLayer();
957             m_contentLayer->setMaskLayer(mask);
958         } else
959             m_contentLayer->setMaskLayer(0);
960
961         m_contentLayer->setMasksToBounds(m_masksToBounds);
962         m_needsSyncMask = false;
963     }
964 }
965
966 void GraphicsLayerAndroid::syncCompositingState()
967 {
968     for (unsigned int i = 0; i < m_children.size(); i++)
969         m_children[i]->syncCompositingState();
970
971     updateScrollingLayers();
972     updateFixedPosition();
973     syncChildren();
974     syncMask();
975
976     if (!gPaused || WTF::currentTime() >= gPausedDelay)
977         repaint();
978 }
979
980 void GraphicsLayerAndroid::notifyClientAnimationStarted()
981 {
982     for (unsigned int i = 0; i < m_children.size(); i++)
983         static_cast<GraphicsLayerAndroid*>(m_children[i])->notifyClientAnimationStarted();
984
985     if (m_needsNotifyClient) {
986         if (client())
987             client()->notifyAnimationStarted(this, WTF::currentTime());
988         m_needsNotifyClient = false;
989     }
990 }
991
992 } // namespace WebCore
993
994 #endif // USE(ACCELERATED_COMPOSITING)