OLD | NEW |
1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "base/gfx/bitmap_platform_device_win.h" | 5 #include "base/gfx/bitmap_platform_device_win.h" |
6 | 6 |
7 #include "base/gfx/gdi_util.h" | 7 #include "base/gfx/gdi_util.h" |
8 #include "base/logging.h" | 8 #include "base/logging.h" |
9 #include "base/process_util.h" | |
10 #include "SkMatrix.h" | 9 #include "SkMatrix.h" |
11 #include "SkRegion.h" | 10 #include "SkRegion.h" |
12 #include "SkUtils.h" | 11 #include "SkUtils.h" |
13 | 12 |
14 namespace gfx { | 13 namespace gfx { |
15 | 14 |
16 // When Windows draws text, is sets the fourth byte (which Skia uses for alpha) | 15 // When Windows draws text, is sets the fourth byte (which Skia uses for alpha) |
17 // to zero. This means that if we try compositing with text that Windows has | 16 // to zero. This means that if we try compositing with text that Windows has |
18 // drawn, we get invalid color values (if the alpha is 0, the other channels | 17 // drawn, we get invalid color values (if the alpha is 0, the other channels |
19 // should be 0 since Skia uses premultiplied colors) and strange results. | 18 // should be 0 since Skia uses premultiplied colors) and strange results. |
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
92 } | 91 } |
93 | 92 |
94 // See the declaration of kMagicTransparencyColor at the top of the file. | 93 // See the declaration of kMagicTransparencyColor at the top of the file. |
95 void FixupAlphaBeforeCompositing(uint32_t* pixel) { | 94 void FixupAlphaBeforeCompositing(uint32_t* pixel) { |
96 if (*pixel == kMagicTransparencyColor) | 95 if (*pixel == kMagicTransparencyColor) |
97 *pixel = 0; | 96 *pixel = 0; |
98 else | 97 else |
99 *pixel |= 0xFF000000; | 98 *pixel |= 0xFF000000; |
100 } | 99 } |
101 | 100 |
102 // Crashes the process. This is called when a bitmap allocation fails, and this | |
103 // function tries to determine why it might have failed, and crash on different | |
104 // lines. This allows us to see in crash dumps the most likely reason for the | |
105 // failure. It takes the size of the bitmap we were trying to allocate as its | |
106 // arguments so we can check that as well. | |
107 void CrashForBitmapAllocationFailure(int w, int h) { | |
108 // The maximum number of GDI objects per process is 10K. If we're very close | |
109 // to that, it's probably the problem. | |
110 const int kLotsOfGDIObjs = 9990; | |
111 CHECK(GetGuiResources(GetCurrentProcess(), GR_GDIOBJECTS) < kLotsOfGDIObjs); | |
112 | |
113 // If the bitmap is ginormous, then we probably can't allocate it. | |
114 // We use 64M pixels = 256MB @ 4 bytes per pixel. | |
115 const int64 kGinormousBitmapPxl = 64000000; | |
116 CHECK(static_cast<int64>(w) * static_cast<int64>(h) < kGinormousBitmapPxl); | |
117 | |
118 // If we're using a crazy amount of virtual address space, then maybe there | |
119 // isn't enough for our bitmap. | |
120 const int64 kLotsOfMem = 1500000000; // 1.5GB. | |
121 scoped_ptr<process_util::ProcessMetrics> process_metrics( | |
122 process_util::ProcessMetrics::CreateProcessMetrics(GetCurrentProcess())); | |
123 CHECK(process_metrics->GetPagefileUsage() < kLotsOfMem); | |
124 | |
125 // Everything else. | |
126 CHECK(0); | |
127 } | |
128 | |
129 } // namespace | 101 } // namespace |
130 | 102 |
131 class BitmapPlatformDeviceWin::BitmapPlatformDeviceWinData | 103 class BitmapPlatformDeviceWin::BitmapPlatformDeviceWinData |
132 : public base::RefCounted<BitmapPlatformDeviceWinData> { | 104 : public base::RefCounted<BitmapPlatformDeviceWinData> { |
133 public: | 105 public: |
134 explicit BitmapPlatformDeviceWinData(HBITMAP hbitmap); | 106 explicit BitmapPlatformDeviceWinData(HBITMAP hbitmap); |
135 | 107 |
136 // Create/destroy hdc_, which is the memory DC for our bitmap data. | 108 // Create/destroy hdc_, which is the memory DC for our bitmap data. |
137 HDC GetBitmapDC(); | 109 HDC GetBitmapDC(); |
138 void ReleaseBitmapDC(); | 110 void ReleaseBitmapDC(); |
(...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
256 // required so that we can call the base class' constructor with the pixel | 228 // required so that we can call the base class' constructor with the pixel |
257 // data. | 229 // data. |
258 BitmapPlatformDeviceWin* BitmapPlatformDeviceWin::create(HDC screen_dc, | 230 BitmapPlatformDeviceWin* BitmapPlatformDeviceWin::create(HDC screen_dc, |
259 int width, | 231 int width, |
260 int height, | 232 int height, |
261 bool is_opaque, | 233 bool is_opaque, |
262 HANDLE shared_section) { | 234 HANDLE shared_section) { |
263 SkBitmap bitmap; | 235 SkBitmap bitmap; |
264 | 236 |
265 // CreateDIBSection appears to get unhappy if we create an empty bitmap, so | 237 // CreateDIBSection appears to get unhappy if we create an empty bitmap, so |
266 // we just expand it here. | 238 // just create a minimal bitmap |
267 if (width == 0) | 239 if ((width == 0) || (height == 0)) { |
268 width = 1; | 240 width = 1; |
269 if (height == 0) | |
270 height = 1; | 241 height = 1; |
| 242 } |
271 | 243 |
272 BITMAPINFOHEADER hdr; | 244 BITMAPINFOHEADER hdr = {0}; |
273 CreateBitmapHeader(width, height, &hdr); | 245 CreateBitmapHeader(width, height, &hdr); |
274 | 246 |
275 void* data; | 247 void* data = NULL; |
276 HBITMAP hbitmap = CreateDIBSection(screen_dc, | 248 HBITMAP hbitmap = CreateDIBSection(screen_dc, |
277 reinterpret_cast<BITMAPINFO*>(&hdr), 0, | 249 reinterpret_cast<BITMAPINFO*>(&hdr), 0, |
278 &data, | 250 &data, |
279 shared_section, 0); | 251 shared_section, 0); |
280 | 252 |
281 // If we run out of GDI objects or some other error occurs, we won't get a | 253 // If we run out of GDI objects or some other error occurs, we won't get a |
282 // bitmap here. This will cause us to crash later because the data pointer is | 254 // bitmap here. This will cause us to crash later because the data pointer is |
283 // NULL. To make sure that we can assign blame for those crashes to this code, | 255 // NULL. To make sure that we can assign blame for those crashes to this code, |
284 // we deliberately crash here, even in release mode. | 256 // we deliberately crash here, even in release mode. |
285 if (!hbitmap) | 257 if (!hbitmap) { |
286 CrashForBitmapAllocationFailure(width, height); | 258 DWORD error = GetLastError(); |
| 259 NOTREACHED() << "CreateDIBSection Failed. Error: " << error << "\n"; |
| 260 return NULL; |
| 261 } |
287 | 262 |
288 bitmap.setConfig(SkBitmap::kARGB_8888_Config, width, height); | 263 bitmap.setConfig(SkBitmap::kARGB_8888_Config, width, height); |
289 bitmap.setPixels(data); | 264 bitmap.setPixels(data); |
290 bitmap.setIsOpaque(is_opaque); | 265 bitmap.setIsOpaque(is_opaque); |
291 | 266 |
292 if (is_opaque) { | 267 if (is_opaque) { |
293 #ifndef NDEBUG | 268 #ifndef NDEBUG |
294 // To aid in finding bugs, we set the background color to something | 269 // To aid in finding bugs, we set the background color to something |
295 // obviously wrong so it will be noticable when it is not cleared | 270 // obviously wrong so it will be noticable when it is not cleared |
296 bitmap.eraseARGB(255, 0, 255, 128); // bright bluish green | 271 bitmap.eraseARGB(255, 0, 255, 128); // bright bluish green |
(...skipping 165 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
462 for (int j = 0; j < width; j++) { | 437 for (int j = 0; j < width; j++) { |
463 adjustor(data + j); | 438 adjustor(data + j); |
464 } | 439 } |
465 data += row_words; | 440 data += row_words; |
466 } | 441 } |
467 } | 442 } |
468 } | 443 } |
469 | 444 |
470 } // namespace gfx | 445 } // namespace gfx |
471 | 446 |
OLD | NEW |