OSDN Git Service

DO NOT MERGE ANR fix
authorJohn Reck <jreck@google.com>
Fri, 8 Apr 2011 18:41:20 +0000 (11:41 -0700)
committerJohn Reck <jreck@google.com>
Thu, 5 May 2011 21:32:12 +0000 (14:32 -0700)
 Race condition in BaseTile could cause a texture's owner to change
 to a BaseTile, without that BaseTile actually using that texture. This
 could cause two texture's to point to the same BaseTile.

 Bug: 4268381

Change-Id: I66b38a042e66fc32f4e098428d1f4a537d76a9d8

WebCore/platform/graphics/android/BaseTile.cpp
WebCore/platform/graphics/android/BaseTile.h

index d58c549..25ba60f 100644 (file)
@@ -70,7 +70,6 @@ BaseTile::BaseTile()
     , m_lastDirtyPicture(0)
     , m_fullRepaintA(true)
     , m_fullRepaintB(true)
-    , m_painting(false)
     , m_lastPaintedPicture(0)
 {
 #ifdef DEBUG_COUNT
@@ -105,8 +104,7 @@ void BaseTile::reserveTexture()
     BackedDoubleBufferedTexture* texture = TilesManager::instance()->getAvailableTexture(this);
 
     android::AutoMutex lock(m_atomicSync);
-    if (texture && !m_painting &&
-        m_texture != texture) {
+    if (texture && m_texture != texture) {
         m_lastPaintedPicture = 0;
         fullInval();
         m_texture = texture;
@@ -118,8 +116,6 @@ bool BaseTile::removeTexture(BackedDoubleBufferedTexture* texture)
     XLOG("%x removeTexture res: %x... page %x", this, m_texture, m_page);
     // We update atomically, so paintBitmap() can see the correct value
     android::AutoMutex lock(m_atomicSync);
-    if (m_painting)
-        return false;
     if (m_texture == texture)
         m_texture = 0;
     return true;
@@ -261,14 +257,12 @@ void BaseTile::paintBitmap()
     bool dirty = m_dirty;
     BackedDoubleBufferedTexture* texture = m_texture;
     SkRegion dirtyArea = *m_currentDirtyArea;
-    m_painting = true;
     float scale = m_scale;
     const int x = m_x;
     const int y = m_y;
     m_atomicSync.unlock();
 
     if (!dirty || !texture) {
-        m_painting = false;
         return;
     }
 
@@ -281,7 +275,6 @@ void BaseTile::paintBitmap()
     // transferred to another BaseTile under us)
     if (texture->owner() != this || texture->usedLevel() > 1) {
         texture->producerRelease();
-        m_painting = false;
         return;
     }
 
@@ -359,40 +352,40 @@ void BaseTile::paintBitmap()
     texture->setTile(textureInfo, x, y, scale, pictureCount);
     texture->producerReleaseAndSwap();
 
-    m_lastPaintedPicture = pictureCount;
-
-    // set the fullrepaint flags
+    if (texture == m_texture) {
+        m_lastPaintedPicture = pictureCount;
 
-    if ((m_currentDirtyArea == &m_dirtyAreaA) && m_fullRepaintA)
-        m_fullRepaintA = false;
+        // set the fullrepaint flags
 
-    if ((m_currentDirtyArea == &m_dirtyAreaB) && m_fullRepaintB)
-        m_fullRepaintB = false;
+        if ((m_currentDirtyArea == &m_dirtyAreaA) && m_fullRepaintA)
+            m_fullRepaintA = false;
 
-    // The various checks to see if we are still dirty...
+        if ((m_currentDirtyArea == &m_dirtyAreaB) && m_fullRepaintB)
+            m_fullRepaintB = false;
 
-    m_dirty = false;
+        // The various checks to see if we are still dirty...
 
-    if (m_scale != scale)
-        m_dirty = true;
+        m_dirty = false;
 
-    if (!fullRepaint)
-        m_currentDirtyArea->op(dirtyArea, SkRegion::kDifference_Op);
+        if (m_scale != scale)
+            m_dirty = true;
 
-    if (!m_currentDirtyArea->isEmpty())
-        m_dirty = true;
+        if (!fullRepaint)
+            m_currentDirtyArea->op(dirtyArea, SkRegion::kDifference_Op);
 
-    // Now we can swap the dirty areas
+        if (!m_currentDirtyArea->isEmpty())
+            m_dirty = true;
 
-    m_currentDirtyArea = m_currentDirtyArea == &m_dirtyAreaA ? &m_dirtyAreaB : &m_dirtyAreaA;
+        // Now we can swap the dirty areas
 
-    if (!m_currentDirtyArea->isEmpty())
-        m_dirty = true;
+        m_currentDirtyArea = m_currentDirtyArea == &m_dirtyAreaA ? &m_dirtyAreaB : &m_dirtyAreaA;
 
-    if (!m_dirty)
-        m_usable = true;
+        if (!m_currentDirtyArea->isEmpty())
+            m_dirty = true;
 
-    m_painting = false;
+        if (!m_dirty)
+            m_usable = true;
+    }
 
     m_atomicSync.unlock();
 }
index b832eee..63ce117 100644 (file)
@@ -127,7 +127,6 @@ private:
     bool m_fullRepaintA;
     bool m_fullRepaintB;
     SkRegion* m_currentDirtyArea;
-    bool m_painting;
 
     // stores the id of the latest picture painted to the tile. If the id is 0
     // then we know that the picture has not yet been painted an there is nothing