b=374272, browser crashes when viewing page with many animated gifs, r=stuart
--- 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_ */