b=374272, browser crashes when viewing page with many animated gifs, r=stuart
authorvladimir@pobox.com
Mon, 02 Apr 2007 12:57:58 -0700
changeset 271 92d135c14e0970e2492f46cbb3b527b275e75d22
parent 270 fe36cc47cecf2b2c487628c0ffd91d6ebf88a9b6
child 272 2377528d47a111aa89ac39e7056bf96db2282ed3
push id1
push userroot
push dateTue, 26 Apr 2011 22:38:44 +0000
treeherdermozilla-beta@bfdb6e623a36 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersstuart
bugs374272
milestone1.9a4pre
b=374272, browser crashes when viewing page with many animated gifs, r=stuart
gfx/src/thebes/nsThebesImage.cpp
gfx/src/thebes/nsThebesImage.h
--- a/gfx/src/thebes/nsThebesImage.cpp
+++ b/gfx/src/thebes/nsThebesImage.cpp
@@ -93,18 +93,20 @@ nsThebesImage::Init(PRInt32 aWidth, PRIn
             format = gfxImageSurface::ImageFormatRGB24;
             mAlphaDepth = 0;
             break;
     }
 
     mFormat = format;
 
 #ifdef XP_WIN
-    mWinSurface = new gfxWindowsSurface(gfxIntSize(mWidth, mHeight), format);
-    mImageSurface = mWinSurface->GetImageSurface();
+    if (!ShouldUseImageSurfaces()) {
+        mWinSurface = new gfxWindowsSurface(gfxIntSize(mWidth, mHeight), format);
+        mImageSurface = mWinSurface->GetImageSurface();
+    }
 
     if (!mImageSurface) {
         mWinSurface = nsnull;
         mImageSurface = new gfxImageSurface(gfxIntSize(mWidth, mHeight), format);
     }
 #else
     mImageSurface = new gfxImageSurface(gfxIntSize(mWidth, mHeight), format);
 #endif
@@ -213,16 +215,21 @@ nsThebesImage::Optimize(nsIDeviceContext
 
             return NS_OK;
         }
 
         // if it's not RGB24/ARGB32, don't optimize, but we should
         // never hit this.
     }
 
+    // if we're being forced to use image surfaces due to
+    // resource constraints, don't try to optimize beyond single-pixel.
+    if (ShouldUseImageSurfaces())
+        return NS_OK;
+
 #ifdef XP_WIN
     // we need to special-case windows here, because windows has
     // a distinction between DIB and DDB and we want to use DDBs as much
     // as we can.
     if (mWinSurface) {
         // Don't do DDBs for large images; see bug 359147
         // We use 1024 as a reasonable sized maximum; the real fix
         // will be to make sure we don't ever make a DDB that's bigger
@@ -537,8 +544,31 @@ nsThebesImage::DrawToImage(nsIImage* aDs
     dst->Rectangle(gfxRect(0, 0, aDWidth, aDHeight), PR_TRUE);
     dst->Scale(double(aDWidth)/mWidth, double(aDHeight)/mHeight);
 
     dst->SetSource(ThebesSurface());
     dst->Paint();
 
     return NS_OK;
 }
+
+PRBool
+nsThebesImage::ShouldUseImageSurfaces()
+{
+#ifdef XP_WIN
+    static const DWORD kGDIObjectsHighWaterMark = 7000;
+
+    // at 7000 GDI objects, stop allocating normal images to make sure
+    // we never hit the 10k hard limit.
+    // GetCurrentProcess() just returns (HANDLE)-1, it's inlined afaik
+    DWORD count = GetGuiResources(GetCurrentProcess(), GR_GDIOBJECTS);
+    if (count == 0 ||
+        count > kGDIObjectsHighWaterMark)
+    {
+        // either something's broken (count == 0),
+        // or we hit our high water mark; disable
+        // image allocations for a bit.
+        return PR_TRUE;
+    }
+#endif
+
+    return PR_FALSE;
+}
--- a/gfx/src/thebes/nsThebesImage.h
+++ b/gfx/src/thebes/nsThebesImage.h
@@ -152,11 +152,17 @@ protected:
 
     nsRefPtr<gfxImageSurface> mImageSurface;
     nsRefPtr<gfxASurface> mOptSurface;
 #ifdef XP_WIN
     nsRefPtr<gfxWindowsSurface> mWinSurface;
 #endif
 
     PRUint8 mAlphaDepth;
+
+    // this function should return true if
+    // we should (temporarily) not allocate any
+    // platform native surfaces and instead use
+    // image surfaces for everything.
+    static PRBool ShouldUseImageSurfaces();
 };
 
 #endif /* _NSTHEBESIMAGE_H_ */