Backout changeset 07d34812bdee, b879d413ce2d, 0c59eeb18700 due to android opengl regression on chrome pages; r=backout
authorBenoit Girard <b56girard@gmail.com>
Tue, 23 Aug 2011 17:12:15 -0400
changeset 75782 0432558816ac53af208768975ffe1f6b0c70a13f
parent 75781 87a72f57507e6c882e657b9d40f8f6a9b8da4c7c
child 75783 36e5a31b8f88980a4cb7c3bd081916f2c47b2efa
push id3
push userfelipc@gmail.com
push dateFri, 30 Sep 2011 20:09:13 +0000
reviewersbackout
milestone9.0a1
backs out07d34812bdee0abbce80d719973615129aa9a265
Backout changeset 07d34812bdee, b879d413ce2d, 0c59eeb18700 due to android opengl regression on chrome pages; r=backout
gfx/layers/opengl/ThebesLayerOGL.cpp
gfx/thebes/GLContext.cpp
gfx/thebes/GLContext.h
gfx/thebes/GLContextProviderEGL.cpp
--- a/gfx/layers/opengl/ThebesLayerOGL.cpp
+++ b/gfx/layers/opengl/ThebesLayerOGL.cpp
@@ -186,106 +186,50 @@ ThebesLayerBufferOGL::RenderTo(const nsI
       // entire visible region's bounds, and we should draw it all in one quad
       // to avoid unexpected aliasing.
       tmpRegion = visibleRegion.GetBounds();
       renderRegion = &tmpRegion;
     } else {
       renderRegion = &visibleRegion;
     }
 
+    mTexImage->BeginTileIteration();
+    if (mTexImageOnWhite) {
+      mTexImageOnWhite->BeginTileIteration();
+      NS_ASSERTION(mTexImageOnWhite->GetTileRect() == mTexImage->GetTileRect(), "component alpha textures should be the same size.");
+    }
     nsIntRegion region(*renderRegion);
     nsIntPoint origin = GetOriginOffset();
     region.MoveBy(-origin);           // translate into TexImage space, buffer origin might not be at texture (0,0)
 
-    // Figure out the intersecting draw region
-    nsIntSize texSize = mTexImage->GetSize();
-    nsIntRect textureRect = nsIntRect(0, 0, texSize.width, texSize.height);
-    textureRect.MoveBy(region.GetBounds().TopLeft());
-    nsIntRegion subregion;
-    subregion.And(region, textureRect);
-    if (subregion.IsEmpty())  // Region is empty, nothing to draw
-      return;
-
-    nsIntRegion screenRects;
-    nsIntRegion regionRects;
-
-    // Collect texture/screen coordinates for drawing
-    nsIntRegionRectIterator iter(subregion);
-    while (const nsIntRect* iterRect = iter.Next()) {
-        nsIntRect regionRect = *iterRect;
-        nsIntRect screenRect = regionRect;
-        screenRect.MoveBy(origin);
-
-        screenRects.Or(screenRects, screenRect);
-        regionRects.Or(regionRects, regionRect);
-    }
-
-    mTexImage->BeginTileIteration();
-    if (mTexImageOnWhite) {
-      NS_ASSERTION(mTexImage->GetTileCount() == mTexImageOnWhite->GetTileCount(),
-                   "Tile count mismatch on component alpha texture");
-      mTexImageOnWhite->BeginTileIteration();
-    }
-
-    bool usingTiles = (mTexImage->GetTileCount() > 1);
     do {
-      if (mTexImageOnWhite) {
-        NS_ASSERTION(mTexImageOnWhite->GetTileRect() == mTexImage->GetTileRect(), "component alpha textures should be the same size.");
+      nsIntRect textureRect = mTexImage->GetTileRect();
+      textureRect.MoveBy(region.GetBounds().x, region.GetBounds().y);
+      nsIntRegion subregion(region);
+      subregion.And(region, textureRect); // region this texture is visible in
+      if (subregion.IsEmpty()) {
+        continue;
       }
-
-      nsIntRect tileRect = mTexImage->GetTileRect();
-
       // Bind textures.
       TextureImage::ScopedBindTexture texBind(mTexImage, LOCAL_GL_TEXTURE0);
       TextureImage::ScopedBindTexture texOnWhiteBind(mTexImageOnWhite, LOCAL_GL_TEXTURE1);
 
-      // Draw texture. If we're using tiles, we do repeating manually, as texture
-      // repeat would cause each individual tile to repeat instead of the
-      // compound texture as a whole. This involves drawing at most 4 sections,
-      // 2 for each axis that has texture repeat.
-      for (int y = 0; y < (usingTiles ? 2 : 1); y++) {
-        for (int x = 0; x < (usingTiles ? 2 : 1); x++) {
-          nsIntRect currentTileRect(tileRect);
-          currentTileRect.MoveBy(x * texSize.width, y * texSize.height);
-
-          nsIntRegionRectIterator screenIter(screenRects);
-          nsIntRegionRectIterator regionIter(regionRects);
-
-          const nsIntRect* screenRect;
-          const nsIntRect* regionRect;
-          while ((screenRect = screenIter.Next()) &&
-                 (regionRect = regionIter.Next())) {
-              nsIntRect tileScreenRect(*screenRect);
-              nsIntRect tileRegionRect(*regionRect);
+      nsIntRegionRectIterator iter(subregion);
+      while (const nsIntRect *iterRect = iter.Next()) {
+        nsIntRect regionRect = *iterRect;  // one rectangle of this texture's region
+        // translate into the correct place for this texture sub-region
+        nsIntRect screenRect = regionRect;
+        screenRect.MoveBy(origin);
+        program->SetLayerQuadRect(screenRect);
 
-              // When we're using tiles, find the intersection between the tile
-              // rect and this region rect. Tiling is then handled by the
-              // outer for-loops and modifying the tile rect.
-              if (usingTiles) {
-                  tileScreenRect.MoveBy(-origin);
-                  tileScreenRect = tileScreenRect.Intersect(currentTileRect);
-                  tileScreenRect.MoveBy(origin);
-
-                  if (tileScreenRect.IsEmpty())
-                    continue;
-
-                  tileRegionRect = regionRect->Intersect(currentTileRect);
-                  tileRegionRect.MoveBy(-currentTileRect.TopLeft());
-              }
-
-              program->SetLayerQuadRect(tileScreenRect);
-              aManager->BindAndDrawQuadWithTextureRect(program, tileRegionRect,
-                                                       tileRect.Size(),
-                                                       mTexImage->GetWrapMode());
-          }
-        }
+        regionRect.MoveBy(-mTexImage->GetTileRect().TopLeft()); // get region of tile
+        aManager->BindAndDrawQuadWithTextureRect(program, regionRect,
+                                                 textureRect.Size(),
+                                                 mTexImage->GetWrapMode());
       }
-
-      if (mTexImageOnWhite)
-          mTexImageOnWhite->NextTile();
     } while (mTexImage->NextTile());
   }
 
   if (mTexImageOnWhite) {
     // Restore defaults
     gl()->fBlendFuncSeparate(LOCAL_GL_ONE, LOCAL_GL_ONE_MINUS_SRC_ALPHA,
                              LOCAL_GL_ONE, LOCAL_GL_ONE);
   }
@@ -842,28 +786,16 @@ ShadowBufferOGL::Upload(gfxASurface* aUp
   }
 
   nsIntRegion destRegion(aUpdated);
   // aUpdated is in screen coordinates.  Move it so that the layer's
   // top-left is 0,0
   nsIntPoint visTopLeft = mLayer->GetVisibleRegion().GetBounds().TopLeft();
   destRegion.MoveBy(-visTopLeft);
 
-  // Correct for rotation
-  destRegion.MoveBy(aRotation);
-  nsIntRect destBounds = destRegion.GetBounds();
-  destRegion.MoveBy((destBounds.x >= size.width) ? -size.width : 0,
-                    (destBounds.y >= size.height) ? -size.height : 0);
-
-  // There's code to make sure that updated regions don't cross rotation
-  // boundaries, so assert here that this is the case
-  NS_ASSERTION(((destBounds.x % size.width) + destBounds.width <= size.width) &&
-               ((destBounds.y % size.height) + destBounds.height <= size.height),
-               "Updated region lies across rotation boundaries!");
-
   // NB: this gfxContext must not escape EndUpdate() below
   mTexImage->DirectUpdate(aUpdate, destRegion);
 
   mBufferRect = aRect;
   mBufferRotation = aRotation;
 }
 
 ShadowThebesLayerOGL::ShadowThebesLayerOGL(LayerManagerOGL *aManager)
--- a/gfx/thebes/GLContext.cpp
+++ b/gfx/thebes/GLContext.cpp
@@ -570,52 +570,51 @@ BasicTextureImage::~BasicTextureImage()
 }
 
 gfxASurface*
 BasicTextureImage::BeginUpdate(nsIntRegion& aRegion)
 {
     NS_ASSERTION(!mUpdateSurface, "BeginUpdate() without EndUpdate()?");
 
     // determine the region the client will need to repaint
-    GetUpdateRegion(aRegion);
-    mUpdateRegion = aRegion;
+    ImageFormat format =
+        (GetContentType() == gfxASurface::CONTENT_COLOR) ?
+        gfxASurface::ImageFormatRGB24 : gfxASurface::ImageFormatARGB32;
+    if (mTextureState != Valid)
+    {
+        // if the texture hasn't been initialized yet, or something important
+        // changed, we need to recreate our backing surface and force the
+        // client to paint everything
+        mUpdateRegion = nsIntRect(nsIntPoint(0, 0), mSize);
+    } else {
+        mUpdateRegion = aRegion;
+    }
+
+    aRegion = mUpdateRegion;
 
     nsIntRect rgnSize = mUpdateRegion.GetBounds();
     if (!nsIntRect(nsIntPoint(0, 0), mSize).Contains(rgnSize)) {
         NS_ERROR("update outside of image");
         return NULL;
     }
 
-    ImageFormat format =
-        (GetContentType() == gfxASurface::CONTENT_COLOR) ?
-        gfxASurface::ImageFormatRGB24 : gfxASurface::ImageFormatARGB32;
-    mUpdateSurface =
+    mUpdateSurface = 
         GetSurfaceForUpdate(gfxIntSize(rgnSize.width, rgnSize.height), format);
 
     if (!mUpdateSurface || mUpdateSurface->CairoStatus()) {
         mUpdateSurface = NULL;
         return NULL;
     }
 
     mUpdateSurface->SetDeviceOffset(gfxPoint(-rgnSize.x, -rgnSize.y));
 
     return mUpdateSurface;
 }
 
 void
-BasicTextureImage::GetUpdateRegion(nsIntRegion& aForRegion)
-{
-  // if the texture hasn't been initialized yet, or something important
-  // changed, we need to recreate our backing surface and force the
-  // client to paint everything
-  if (mTextureState != Valid)
-      aForRegion = nsIntRect(nsIntPoint(0, 0), mSize);
-}
-
-void
 BasicTextureImage::EndUpdate()
 {
     NS_ASSERTION(!!mUpdateSurface, "EndUpdate() without BeginUpdate()?");
 
     // FIXME: this is the slow boat.  Make me fast (with GLXPixmap?).
 
     // Undo the device offset that BeginUpdate set; doesn't much matter for us here,
     // but important if we ever do anything directly with the surface.
@@ -725,139 +724,89 @@ TiledTextureImage::TiledTextureImage(GLC
 
 TiledTextureImage::~TiledTextureImage()
 {
 }
 
 bool 
 TiledTextureImage::DirectUpdate(gfxASurface* aSurf, const nsIntRegion& aRegion, const nsIntPoint& aFrom /* = nsIntPoint(0, 0) */)
 {
+    nsIntRect bounds = aRegion.GetBounds();
     nsIntRegion region;
     if (mTextureState != Valid) {
-        nsIntRect bounds = nsIntRect(0, 0, mSize.width, mSize.height);
+        bounds = nsIntRect(0, 0, mSize.width, mSize.height);
         region = nsIntRegion(bounds);
     } else {
         region = aRegion;
     }
 
     PRBool result = PR_TRUE;
     for (unsigned i = 0; i < mImages.Length(); i++) {
-        int xPos = (i % mColumns) * mTileSize;
-        int yPos = (i / mColumns) * mTileSize;
+        unsigned int xPos = (i % mColumns) * mTileSize;
+        unsigned int yPos = (i / mColumns) * mTileSize;
         nsIntRegion tileRegion;
         tileRegion.And(region, nsIntRect(nsIntPoint(xPos,yPos), mImages[i]->GetSize())); // intersect with tile
         if (tileRegion.IsEmpty())
             continue;
         tileRegion.MoveBy(-xPos, -yPos); // translate into tile local space
         result &= mImages[i]->DirectUpdate(aSurf,
                                            tileRegion,
                                            aFrom + nsIntPoint(xPos, yPos));
     }
     mShaderType = mImages[0]->GetShaderProgramType();
     mIsRGBFormat = mImages[0]->IsRGB();
     mTextureState = Valid;
     return result;
 }
 
-void
-TiledTextureImage::GetUpdateRegion(nsIntRegion& aForRegion)
-{
-    if (mTextureState != Valid) {
-        // if the texture hasn't been initialized yet, or something important
-        // changed, we need to recreate our backing surface and force the
-        // client to paint everything
-        aForRegion = nsIntRect(nsIntPoint(0, 0), mSize);
-        return;
-    }
-
-    nsIntRegion newRegion;
-
-    // We need to query each texture with the region it will be drawing and
-    // set aForRegion to be the combination of all of these regions
-    for (unsigned i = 0; i < mImages.Length(); i++) {
-        int xPos = (i % mColumns) * mTileSize;
-        int yPos = (i / mColumns) * mTileSize;
-        nsIntRect imageRect = nsIntRect(nsIntRect(nsIntPoint(xPos,yPos), mImages[i]->GetSize()));
-
-        if (aForRegion.Intersects(imageRect)) {
-            // Make a copy of the region
-            nsIntRegion subRegion;
-            subRegion.And(aForRegion, imageRect);
-            // Translate it into tile-space
-            subRegion.MoveBy(-xPos, -yPos);
-            // Query region
-            mImages[i]->GetUpdateRegion(subRegion);
-            // Translate back
-            subRegion.MoveBy(xPos, yPos);
-            // Add to the accumulated region
-            newRegion.Or(newRegion, subRegion);
-        }
-    }
-
-    aForRegion = newRegion;
-}
-
 gfxASurface*
 TiledTextureImage::BeginUpdate(nsIntRegion& aRegion)
 {
     NS_ASSERTION(!mInUpdate, "nested update");
     mInUpdate = PR_TRUE;
 
-    // Note, we don't call GetUpdateRegion here as if the updated region is
-    // fully contained in a single tile, we get to avoid iterating through
-    // the tiles again (and a little copying).
     if (mTextureState != Valid)
     {
         // if the texture hasn't been initialized yet, or something important
         // changed, we need to recreate our backing surface and force the
         // client to paint everything
-        aRegion = nsIntRect(nsIntPoint(0, 0), mSize);
+        mUpdateRegion = nsIntRect(nsIntPoint(0, 0), mSize);
+    } else {
+        mUpdateRegion = aRegion;
     }
 
-    nsIntRect bounds = aRegion.GetBounds();
-
     for (unsigned i = 0; i < mImages.Length(); i++) {
-        int xPos = (i % mColumns) * mTileSize;
-        int yPos = (i / mColumns) * mTileSize;
+        unsigned int xPos = (i % mColumns) * mTileSize;
+        unsigned int yPos = (i / mColumns) * mTileSize;
         nsIntRegion imageRegion = nsIntRegion(nsIntRect(nsIntPoint(xPos,yPos), mImages[i]->GetSize()));
 
         // a single Image can handle this update request
         if (imageRegion.Contains(aRegion)) {
             // adjust for tile offset
             aRegion.MoveBy(-xPos, -yPos);
             // forward the actual call
             nsRefPtr<gfxASurface> surface = mImages[i]->BeginUpdate(aRegion);
             // caller expects container space
             aRegion.MoveBy(xPos, yPos);
-            // Correct the device offset
-            gfxPoint offset = surface->GetDeviceOffset();
-            surface->SetDeviceOffset(gfxPoint(offset.x - xPos,
-                                              offset.y - yPos));
             // we don't have a temp surface
             mUpdateSurface = nsnull;
             // remember which image to EndUpdate
             mCurrentImage = i;
             return surface.get();
         }
     }
-
-    // Get the real updated region, taking into account the capabilities of
-    // each TextureImage tile
-    GetUpdateRegion(aRegion);
-    mUpdateRegion = aRegion;
-    bounds = aRegion.GetBounds();
-
     // update covers multiple Images - create a temp surface to paint in
     gfxASurface::gfxImageFormat format =
         (GetContentType() == gfxASurface::CONTENT_COLOR) ?
         gfxASurface::ImageFormatRGB24 : gfxASurface::ImageFormatARGB32;
+
+    nsIntRect bounds = aRegion.GetBounds();
     mUpdateSurface = gfxPlatform::GetPlatform()->
         CreateOffscreenSurface(gfxIntSize(bounds.width, bounds.height), gfxASurface::ContentFromFormat(format));
     mUpdateSurface->SetDeviceOffset(gfxPoint(-bounds.x, -bounds.y));
-
     return mUpdateSurface;
 }
 
 void
 TiledTextureImage::EndUpdate()
 {
     NS_ASSERTION(mInUpdate, "EndUpdate not in update");
     if (!mUpdateSurface) { // update was to a single TextureImage
@@ -866,20 +815,19 @@ TiledTextureImage::EndUpdate()
         mTextureState = Valid;
         mShaderType = mImages[mCurrentImage]->GetShaderProgramType();
         mIsRGBFormat = mImages[mCurrentImage]->IsRGB();
         return;
     }
 
     // upload tiles from temp surface
     for (unsigned i = 0; i < mImages.Length(); i++) {
-        int xPos = (i % mColumns) * mTileSize;
-        int yPos = (i / mColumns) * mTileSize;
+        unsigned int xPos = (i % mColumns) * mTileSize;
+        unsigned int yPos = (i / mColumns) * mTileSize;
         nsIntRect imageRect = nsIntRect(nsIntPoint(xPos,yPos), mImages[i]->GetSize());
-
         nsIntRegion subregion;
         subregion.And(mUpdateRegion, imageRect);
         if (subregion.IsEmpty())
             continue;
         subregion.MoveBy(-xPos, -yPos); // Tile-local space
         // copy tile from temp surface
         gfxASurface* surf = mImages[i]->BeginUpdate(subregion);
         nsRefPtr<gfxContext> ctx = new gfxContext(surf);
@@ -889,17 +837,16 @@ TiledTextureImage::EndUpdate()
         ctx->Paint();
         mImages[i]->EndUpdate();
     }
 
     mUpdateSurface = nsnull;
     mInUpdate = PR_FALSE;
     mShaderType = mImages[0]->GetShaderProgramType();
     mIsRGBFormat = mImages[0]->IsRGB();
-    mTextureState = Valid;
 }
 
 void TiledTextureImage::BeginTileIteration()
 {
     mCurrentImage = 0;
 }
 
 PRBool TiledTextureImage::NextTile()
@@ -949,21 +896,16 @@ void TiledTextureImage::Resize(const nsI
           nsRefPtr<TextureImage> teximg =
                   mGL->TileGenFunc(size, mContentType, mUseNearestFilter);
           mImages.AppendElement(teximg.forget());
       }
     }
     mTextureState = Allocated;
 }
 
-PRUint32 TiledTextureImage::GetTileCount()
-{
-    return mImages.Length();
-}
-
 PRBool
 GLContext::ResizeOffscreenFBO(const gfxIntSize& aSize)
 {
     if (!IsOffscreenSizeAllowed(aSize))
         return PR_FALSE;
 
     MakeCurrent();
 
--- a/gfx/thebes/GLContext.h
+++ b/gfx/thebes/GLContext.h
@@ -189,25 +189,16 @@ public:
      * BeginUpdate() calls cannot be "nested", and each successful
      * BeginUpdate() must be followed by exactly one EndUpdate() (see
      * below).  Failure to do so can leave this in a possibly
      * inconsistent state.  Unsuccessful BeginUpdate()s must not be
      * followed by EndUpdate().
      */
     virtual gfxASurface* BeginUpdate(nsIntRegion& aRegion) = 0;
     /**
-     * Retrieves the region that will require updating, given a
-     * region that needs to be updated. This can be used for
-     * making decisions about updating before calling BeginUpdate().
-     *
-     * |aRegion| is an inout param.
-     */
-    virtual void GetUpdateRegion(nsIntRegion& aForRegion) {
-    };
-    /**
      * Finish the active update and synchronize with the server, if
      * necessary.
      *
      * BeginUpdate() must have been called exactly once before
      * EndUpdate().
      */
     virtual void EndUpdate() = 0;
 
@@ -222,21 +213,16 @@ public:
         return PR_FALSE;
     };
 
     virtual nsIntRect GetTileRect() {
         return nsIntRect(nsIntPoint(0,0), mSize);
     };
 
     virtual GLuint GetTextureID() = 0;
-
-    virtual PRUint32 GetTileCount() {
-        return 1;
-    };
-
     /**
      * Set this TextureImage's size, and ensure a texture has been
      * allocated.  Must not be called between BeginUpdate and EndUpdate.
      * After a resize, the contents are undefined.
      *
      * If this isn't implemented by a subclass, it will just perform
      * a dummy BeginUpdate/EndUpdate pair.
      */
@@ -357,17 +343,16 @@ public:
         , mTextureState(Created)
         , mGLContext(aContext)
         , mUpdateOffset(0, 0)
     {}
 
     virtual void BindTexture(GLenum aTextureUnit);
 
     virtual gfxASurface* BeginUpdate(nsIntRegion& aRegion);
-    virtual void GetUpdateRegion(nsIntRegion& aForRegion);
     virtual void EndUpdate();
     virtual bool DirectUpdate(gfxASurface* aSurf, const nsIntRegion& aRegion, const nsIntPoint& aFrom = nsIntPoint(0,0));
     virtual GLuint GetTextureID() { return mTexture; };
     // Returns a surface to draw into
     virtual already_AddRefed<gfxASurface>
       GetSurfaceForUpdate(const gfxIntSize& aSize, ImageFormat aFmt);
 
     // Call when drawing into the update surface is complete.
@@ -402,20 +387,18 @@ class TiledTextureImage
     : public TextureImage
 {
 public:
     TiledTextureImage(GLContext* aGL, nsIntSize aSize,
         TextureImage::ContentType, PRBool aUseNearestFilter = PR_FALSE);
     ~TiledTextureImage();
     void DumpDiv();
     virtual gfxASurface* BeginUpdate(nsIntRegion& aRegion);
-    virtual void GetUpdateRegion(nsIntRegion& aForRegion);
     virtual void EndUpdate();
     virtual void Resize(const nsIntSize& aSize);
-    virtual PRUint32 GetTileCount();
     virtual void BeginTileIteration();
     virtual PRBool NextTile();
     virtual nsIntRect GetTileRect();
     virtual GLuint GetTextureID() {
         return mImages[mCurrentImage]->GetTextureID();
     };
     virtual bool DirectUpdate(gfxASurface* aSurf, const nsIntRegion& aRegion, const nsIntPoint& aFrom = nsIntPoint(0,0));
     virtual PRBool InUpdate() const { return mInUpdate; };
--- a/gfx/thebes/GLContextProviderEGL.cpp
+++ b/gfx/thebes/GLContextProviderEGL.cpp
@@ -1227,38 +1227,37 @@ public:
         if (ctx && !ctx->IsDestroyed()) {
             ctx->MakeCurrent();
             ctx->fDeleteTextures(1, &mTexture);
             ReleaseTexImage();
             DestroyEGLSurface();
         }
     }
 
-    virtual void GetUpdateRegion(nsIntRegion& aForRegion)
-    {
-        if (mTextureState != Valid) {
-            // if the texture hasn't been initialized yet, force the
-            // client to paint everything
-            aForRegion = nsIntRect(nsIntPoint(0, 0), mSize);
-        } else if (!mBackingSurface) {
-            // We can only draw a rectangle, not subregions due to
-            // the way that our texture upload functions work.  If
-            // needed, we /could/ do multiple texture uploads if we have
-            // non-overlapping rects, but that's a tradeoff.
-            aForRegion = nsIntRegion(mUpdateRect);
-        }
-    }
-
     virtual gfxASurface* BeginUpdate(nsIntRegion& aRegion)
     {
         NS_ASSERTION(!mUpdateSurface, "BeginUpdate() without EndUpdate()?");
 
         // determine the region the client will need to repaint
-        GetUpdateRegion(aRegion);
-        mUpdateRect = aRegion.GetBounds();
+        if (mTextureState != Valid) {
+            // if the texture hasn't been initialized yet, force the
+            // client to paint everything
+            mUpdateRect = nsIntRect(nsIntPoint(0, 0), mSize);
+            //printf_stderr("v Forcing full paint\n");
+            aRegion = nsIntRegion(mUpdateRect);
+        } else {
+            mUpdateRect = aRegion.GetBounds();
+            if (!mBackingSurface) {
+                // We can only draw a rectangle, not subregions due to
+                // the way that our texture upload functions work.  If
+                // needed, we /could/ do multiple texture uploads if we have
+                // non-overlapping rects, but that's a tradeoff.
+                aRegion = nsIntRegion(mUpdateRect);
+            }
+        }
 
         //printf_stderr("BeginUpdate with updateRect [%d %d %d %d]\n", mUpdateRect.x, mUpdateRect.y, mUpdateRect.width, mUpdateRect.height);
         if (!nsIntRect(nsIntPoint(0, 0), mSize).Contains(mUpdateRect)) {
             NS_ERROR("update outside of image");
             return NULL;
         }
 
         if (mBackingSurface) {