OSDN Git Service

Fix image layer codepath
[android-x86/external-webkit.git] / Source / WebCore / platform / graphics / android / GraphicsLayerAndroid.cpp
index fc9d85f..ab45f1b 100644 (file)
@@ -24,6 +24,7 @@
 #include "FloatRect.h"
 #include "GraphicsContext.h"
 #include "Image.h"
+#include "ImagesManager.h"
 #include "Layer.h"
 #include "Length.h"
 #include "MediaLayer.h"
@@ -35,6 +36,7 @@
 #include "ScaleTransformOperation.h"
 #include "ScrollableLayerAndroid.h"
 #include "SkCanvas.h"
+#include "SkRegion.h"
 #include "TransformationMatrix.h"
 #include "TranslateTransformOperation.h"
 
@@ -107,9 +109,7 @@ SkLength convertLength(Length len)
 
 static RenderLayer* renderLayerFromClient(GraphicsLayerClient* client)
 {
-    if (client)
-        return static_cast<RenderLayerBacking*>(client)->owningLayer();
-    return 0;
+    return client ? client->owningLayer() : 0;
 }
 
 GraphicsLayerAndroid::GraphicsLayerAndroid(GraphicsLayerClient* client) :
@@ -119,19 +119,22 @@ GraphicsLayerAndroid::GraphicsLayerAndroid(GraphicsLayerClient* client) :
     m_needsRepaint(false),
     m_needsNotifyClient(false),
     m_haveContents(false),
-    m_haveImage(false),
     m_newImage(false),
-    m_imageRef(0),
+    m_image(0),
     m_foregroundLayer(0),
     m_foregroundClipLayer(0)
 {
     RenderLayer* renderLayer = renderLayerFromClient(m_client);
     m_contentLayer = new LayerAndroid(renderLayer);
+    m_dirtyRegion.setEmpty();
     gDebugGraphicsLayerAndroidInstances++;
 }
 
 GraphicsLayerAndroid::~GraphicsLayerAndroid()
 {
+    if (m_image)
+        m_image->deref();
+
     m_contentLayer->unref();
     SkSafeUnref(m_foregroundLayer);
     SkSafeUnref(m_foregroundClipLayer);
@@ -220,10 +223,9 @@ void GraphicsLayerAndroid::removeFromParent()
 
 void GraphicsLayerAndroid::updateFixedPosition()
 {
-    if (!m_client)
-        return;
-
     RenderLayer* renderLayer = renderLayerFromClient(m_client);
+    if (!renderLayer)
+        return;
     RenderView* view = static_cast<RenderView*>(renderLayer->renderer());
 
     if (!view)
@@ -316,8 +318,8 @@ void GraphicsLayerAndroid::setSize(const FloatSize& size)
     // If it is a media layer the size may have changed as a result of the media
     // element (e.g. plugin) gaining focus. Therefore, we must sync the size of
     // the focus' outline so that our UI thread can draw accordingly.
-    if (m_contentLayer->isMedia() && m_client) {
-        RenderLayer* layer = renderLayerFromClient(m_client);
+    RenderLayer* layer = renderLayerFromClient(m_client);
+    if (layer && m_contentLayer->isMedia()) {
         RenderBox* box = layer->renderBox();
         int outline = box->view()->maximalOutlineSize();
         static_cast<MediaLayer*>(m_contentLayer)->setOutlineSize(outline);
@@ -326,11 +328,15 @@ void GraphicsLayerAndroid::setSize(const FloatSize& size)
     }
 
     m_contentLayer->setSize(size.width(), size.height());
+    setNeedsDisplay();
     askForSync();
 }
 
 void GraphicsLayerAndroid::setBackfaceVisibility(bool b)
 {
+    if (b == m_backfaceVisibility)
+        return;
+
     GraphicsLayer::setBackfaceVisibility(b);
     m_contentLayer->setBackfaceVisibility(b);
     askForSync();
@@ -387,6 +393,7 @@ void GraphicsLayerAndroid::setDrawsContent(bool drawsContent)
     if (drawsContent == m_drawsContent)
         return;
     GraphicsLayer::setDrawsContent(drawsContent);
+    m_contentLayer->setVisible(drawsContent);
     if (m_drawsContent) {
         m_haveContents = true;
         setNeedsDisplay();
@@ -396,7 +403,7 @@ void GraphicsLayerAndroid::setDrawsContent(bool drawsContent)
 
 void GraphicsLayerAndroid::setBackgroundColor(const Color& color)
 {
-    if (color == m_backgroundColor)
+    if (color == m_backgroundColor && m_backgroundColorSet)
         return;
     LOG("(%x) setBackgroundColor", this);
     GraphicsLayer::setBackgroundColor(color);
@@ -408,6 +415,9 @@ void GraphicsLayerAndroid::setBackgroundColor(const Color& color)
 
 void GraphicsLayerAndroid::clearBackgroundColor()
 {
+    if (!m_backgroundColorSet)
+        return;
+
     LOG("(%x) clearBackgroundColor", this);
     GraphicsLayer::clearBackgroundColor();
     askForSync();
@@ -502,6 +512,7 @@ void GraphicsLayerAndroid::updateScrollingLayers()
             m_foregroundClipLayer->setMasksToBounds(true);
             m_foregroundClipLayer->addChild(m_foregroundLayer);
             m_contentLayer->addChild(m_foregroundClipLayer);
+            m_contentLayer->setHasOverflowChildren(true);
         } else {
             ASSERT(iframeNeedsOverflow && !m_contentLayer->contentIsScrollable());
             // No need to copy the children as they will be removed and synced.
@@ -549,17 +560,20 @@ bool GraphicsLayerAndroid::repaint()
     LOG("(%x) repaint(), gPaused(%d) m_needsRepaint(%d) m_haveContents(%d) ",
         this, gPaused, m_needsRepaint, m_haveContents);
 
-    if (!gPaused && m_haveContents && m_needsRepaint && !m_haveImage) {
+    if (!gPaused && m_haveContents && m_needsRepaint && !m_image) {
         // with SkPicture, we request the entire layer's content.
         IntRect layerBounds(0, 0, m_size.width(), m_size.height());
 
         RenderLayer* layer = renderLayerFromClient(m_client);
+        if (!layer)
+            return false;
         if (m_foregroundLayer) {
             PaintingPhase phase(this);
             // Paint the background into a separate context.
             phase.set(GraphicsLayerPaintBackground);
             if (!paintContext(m_contentLayer->recordContext(), layerBounds))
                 return false;
+            m_contentLayer->checkTextPresence();
 
             // Construct the foreground layer and draw.
             RenderBox* box = layer->renderBox();
@@ -578,6 +592,7 @@ bool GraphicsLayerAndroid::repaint()
             layer->scrollToOffset(0, 0);
             // At this point, it doesn't matter if painting failed.
             (void) paintContext(m_foregroundLayer->recordContext(), contentsRect);
+            m_foregroundLayer->checkTextPresence();
             layer->scrollToOffset(scroll.width(), scroll.height());
 
             // Construct the clip layer for masking the contents.
@@ -596,12 +611,14 @@ bool GraphicsLayerAndroid::repaint()
             m_foregroundLayer->setPosition(-x, -y);
             // Set the scrollable bounds of the layer.
             m_foregroundLayer->setScrollLimits(-x, -y, m_size.width(), m_size.height());
+            m_foregroundLayer->markAsDirty(m_dirtyRegion);
             m_foregroundLayer->needsRepaint();
         } else {
             // If there is no contents clip, we can draw everything into one
             // picture.
             if (!paintContext(m_contentLayer->recordContext(), layerBounds))
                 return false;
+            m_contentLayer->checkTextPresence();
             // Check for a scrollable iframe and report the scrolling
             // limits based on the view size.
             if (m_contentLayer->contentIsScrollable()) {
@@ -618,15 +635,18 @@ bool GraphicsLayerAndroid::repaint()
             m_contentLayer->getSize().width(),
             m_contentLayer->getSize().height());
 
+        m_contentLayer->markAsDirty(m_dirtyRegion);
+        m_dirtyRegion.setEmpty();
         m_contentLayer->needsRepaint();
         m_needsRepaint = false;
-        m_invalidatedRects.clear();
 
         return true;
     }
-    if (m_needsRepaint && m_haveImage && m_newImage) {
+    if (m_needsRepaint && m_image && m_newImage) {
         // We need to tell the GL thread that we will need to repaint the
         // texture. Only do so if we effectively have a new image!
+        m_contentLayer->markAsDirty(m_dirtyRegion);
+        m_dirtyRegion.setEmpty();
         m_contentLayer->needsRepaint();
         m_newImage = false;
         m_needsRepaint = false;
@@ -644,7 +664,7 @@ bool GraphicsLayerAndroid::paintContext(SkPicture* context,
     if (!canvas)
         return false;
 
-    PlatformGraphicsContext platformContext(canvas, 0);
+    PlatformGraphicsContext platformContext(canvas);
     GraphicsContext graphicsContext(&platformContext);
 
     paintGraphicsLayerContents(graphicsContext, rect);
@@ -653,40 +673,19 @@ bool GraphicsLayerAndroid::paintContext(SkPicture* context,
 
 void GraphicsLayerAndroid::setNeedsDisplayInRect(const FloatRect& rect)
 {
-    for (unsigned int i = 0; i < m_children.size(); i++) {
-        GraphicsLayer* layer = m_children[i];
-        if (layer) {
-           FloatRect childrenRect = m_transform.mapRect(rect);
-           layer->setNeedsDisplayInRect(childrenRect);
-        }
-    }
+    // rect is in the render object coordinates
 
-    if (!m_haveImage && !drawsContent()) {
+    if (!m_image && !drawsContent()) {
         LOG("(%x) setNeedsDisplay(%.2f,%.2f,%.2f,%.2f) doesn't have content, bypass...",
             this, rect.x(), rect.y(), rect.width(), rect.height());
         return;
     }
 
-    bool addInval = true;
-    const size_t maxDirtyRects = 8;
-    for (size_t i = 0; i < m_invalidatedRects.size(); ++i) {
-        if (m_invalidatedRects[i].contains(rect)) {
-            addInval = false;
-            break;
-        }
-    }
-
-#ifdef LAYER_DEBUG
-    LOG("(%x) layer %d setNeedsDisplayInRect(%d) - (%.2f, %.2f, %.2f, %.2f)", this,
-        m_contentLayer->uniqueId(), m_needsRepaint, rect.x(), rect.y(), rect.width(), rect.height());
-#endif
-
-    if (addInval) {
-        if (m_invalidatedRects.size() < maxDirtyRects)
-            m_invalidatedRects.append(rect);
-        else
-            m_invalidatedRects[0].unite(rect);
-    }
+    SkRegion region;
+    region.setRect(rect.x(), rect.y(),
+                   rect.x() + rect.width(),
+                   rect.y() + rect.height());
+    m_dirtyRegion.op(region, SkRegion::kUnion_Op);
 
     m_needsRepaint = true;
     askForSync();
@@ -840,19 +839,26 @@ void GraphicsLayerAndroid::resumeAnimations()
 void GraphicsLayerAndroid::setContentsToImage(Image* image)
 {
     TLOG("(%x) setContentsToImage", this, image);
-    if (image) {
+    if (image && image != m_image) {
+        image->ref();
+        if (m_image)
+            m_image->deref();
+        m_image = image;
+
+        SkBitmapRef* bitmap = image->nativeImageForCurrentFrame();
+        m_contentLayer->setContentsImage(bitmap);
+
         m_haveContents = true;
-        m_haveImage = true;
-        // Only pass the new image if it's a different one
-        if (image->nativeImageForCurrentFrame() != m_imageRef) {
-            m_newImage = true;
-            m_contentLayer->setContentsImage(image->nativeImageForCurrentFrame());
-            // remember the passed image.
-            m_imageRef = image->nativeImageForCurrentFrame();
-            setNeedsDisplay();
-            askForSync();
-        }
+        m_newImage = true;
     }
+    if (!image && m_image) {
+        m_contentLayer->setContentsImage(0);
+        m_image->deref();
+        m_image = 0;
+    }
+
+    setNeedsDisplay();
+    askForSync();
 }
 
 void GraphicsLayerAndroid::setContentsToMedia(PlatformLayer* mediaLayer)
@@ -866,7 +872,7 @@ void GraphicsLayerAndroid::setContentsToMedia(PlatformLayer* mediaLayer)
         mediaLayer->setPosition(m_contentLayer->getPosition().fX,
                                 m_contentLayer->getPosition().fY);
         mediaLayer->setSize(m_contentLayer->getWidth(), m_contentLayer->getHeight());
-        mediaLayer->setDrawTransform(m_contentLayer->drawTransform());
+        mediaLayer->setDrawTransform(*m_contentLayer->drawTransform());
 
         mediaLayer->ref();
         m_contentLayer->unref();