Chromium Code Reviews| Index: skia/ext/bitmap_platform_device_win.cc |
| =================================================================== |
| --- skia/ext/bitmap_platform_device_win.cc (revision 109205) |
| +++ skia/ext/bitmap_platform_device_win.cc (working copy) |
| @@ -7,12 +7,62 @@ |
| #include "skia/ext/bitmap_platform_device_win.h" |
| +#include "base/logging.h" |
| +#include "base/memory/scoped_ptr.h" |
| +#include "base/process_util.h" |
| #include "skia/ext/bitmap_platform_device_data.h" |
| #include "third_party/skia/include/core/SkMatrix.h" |
| #include "third_party/skia/include/core/SkRefCnt.h" |
| #include "third_party/skia/include/core/SkRegion.h" |
| #include "third_party/skia/include/core/SkUtils.h" |
| +namespace { |
| +// Crashes the process. This is called when a bitmap allocation fails, and this |
| +// function tries to determine why it might have failed, and crash on different |
| +// lines. This allows us to see in crash dumps the most likely reason for the |
| +// failure. It takes the size of the bitmap we were trying to allocate as its |
| +// arguments so we can check that as well. |
| +// Bitmap allocation failures are occuring under conditions outside of GDI and |
| +// address space pressure, so we only crash when resources are not low. |
| +void CrashForBitmapAllocationFailure(int w, int h) { |
| + // The maximum number of GDI objects per process is 10K. If we're very close |
| + // to that, it's probably the problem. |
| + const int kLotsOfGDIObjs = 9990; |
| + if (GetGuiResources(GetCurrentProcess(), GR_GDIOBJECTS) > kLotsOfGDIObjs) |
| + return; |
| + |
| + // If the bitmap is ginormous, then we probably can't allocate it. |
| + // We use 64M pixels. |
| + const int64 kGinormousBitmapPxl = 64000000; |
| + if (static_cast<int64>(w) * static_cast<int64>(h) > kGinormousBitmapPxl) |
| + return; |
| + |
| + // If we're using a crazy amount of virtual address space, then maybe there |
| + // isn't enough for our bitmap. |
| + const int64 kLotsOfMem = 1500000000; // 1.5GB. |
| + scoped_ptr<base::ProcessMetrics> process_metrics( |
| + base::ProcessMetrics::CreateProcessMetrics(GetCurrentProcess())); |
| + if (process_metrics->GetPagefileUsage() > kLotsOfMem) |
| + return; |
| + |
| + DWORD last_error = GetLastError(); |
|
vandebo (ex-Chrome)
2011/11/10 00:52:13
Wouldn't it be better to call this at the start of
|
| + LPVOID lpMsgBuf = NULL; |
| + FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | |
| + FORMAT_MESSAGE_FROM_SYSTEM | |
| + FORMAT_MESSAGE_IGNORE_INSERTS, |
| + NULL, |
| + last_error, |
| + 0, |
| + reinterpret_cast<LPTSTR>(&lpMsgBuf), |
| + 0, |
| + NULL); |
| + |
| + CHECK(NO_ERROR == last_error); |
| + LocalFree(lpMsgBuf); |
| +} |
| + |
| +} |
| + |
| namespace skia { |
| BitmapPlatformDevice::BitmapPlatformDeviceData::BitmapPlatformDeviceData( |
| @@ -117,11 +167,16 @@ |
| hdr.biClrImportant = 0; |
| void* data = NULL; |
| + |
| + // Force the last error to success so that we can accurately track failures |
| + // in CrashForBitmapAllocationFailure. |
| + SetLastError(ERROR_SUCCESS); |
| HBITMAP hbitmap = CreateDIBSection(screen_dc, |
| reinterpret_cast<BITMAPINFO*>(&hdr), 0, |
| &data, |
| shared_section, 0); |
| if (!hbitmap) { |
| + CrashForBitmapAllocationFailure(width, height); |
| return NULL; |
| } |