Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(112)

Side by Side Diff: skia/ext/bitmap_platform_device_win.cc

Issue 2618323005: override raster-allocator (Closed)
Patch Set: add new file Created 3 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include <windows.h>
6 #include <psapi.h>
7 #include <stddef.h>
8
9 #include "base/debug/gdi_debug_util_win.h"
10 #include "base/logging.h"
11 #include "base/memory/ptr_util.h"
12 #include "base/win/win_util.h"
13 #include "skia/ext/bitmap_platform_device_win.h"
14 #include "skia/ext/platform_canvas.h"
15 #include "skia/ext/skia_utils_win.h"
16 #include "third_party/skia/include/core/SkMatrix.h"
17 #include "third_party/skia/include/core/SkPath.h"
18 #include "third_party/skia/include/core/SkRefCnt.h"
19 #include "third_party/skia/include/core/SkRect.h"
20
21 namespace {
22
23 void LoadClippingRegionToDC(HDC context,
24 const SkIRect& clip_bounds,
25 const SkMatrix& transformation) {
26 HRGN hrgn = CreateRectRgnIndirect(&skia::SkIRectToRECT(clip_bounds));
27 int result = SelectClipRgn(context, hrgn);
28 SkASSERT(result != ERROR);
29 result = DeleteObject(hrgn);
30 SkASSERT(result != 0);
31 }
32
33 } // namespace
34
35 namespace skia {
36
37 HDC GetNativeDrawingContext(SkCanvas* canvas) {
38 PlatformDevice* platform_device = GetPlatformDevice(canvas->getTopDevice(true) );
39 if (!platform_device)
40 return nullptr;
41
42 // Compensate for drawing to a layer rather than the entire canvas
43 SkMatrix ctm;
44 SkIRect clip_bounds;
45 canvas->temporary_internal_describeTopLayer(&ctm, &clip_bounds);
46
47 return platform_device->BeginPlatformPaint(ctm, clip_bounds);
48 }
49
50 HDC BitmapPlatformDevice::GetBitmapDC(const SkMatrix& transform,
51 const SkIRect& clip_bounds) {
52 if (!hdc_) {
53 hdc_ = CreateCompatibleDC(NULL);
54 InitializeDC(hdc_);
55 old_hbitmap_ = static_cast<HBITMAP>(SelectObject(hdc_, hbitmap_));
56 }
57
58 LoadConfig(transform, clip_bounds);
59 return hdc_;
60 }
61
62 void BitmapPlatformDevice::ReleaseBitmapDC() {
63 SkASSERT(hdc_);
64 SelectObject(hdc_, old_hbitmap_);
65 DeleteDC(hdc_);
66 hdc_ = NULL;
67 old_hbitmap_ = NULL;
68 }
69
70 bool BitmapPlatformDevice::IsBitmapDCCreated()
71 const {
72 return hdc_ != NULL;
73 }
74
75 void BitmapPlatformDevice::LoadConfig(const SkMatrix& transform,
76 const SkIRect& clip_bounds) {
77 if (!hdc_)
78 return; // Nothing to do.
79
80 // Transform.
81 skia::LoadTransformToDC(hdc_, transform);
82 LoadClippingRegionToDC(hdc_, clip_bounds, transform);
83 }
84
85 static void DeleteHBitmapCallback(void* addr, void* context) {
86 // If context is not NULL then it's a valid HBITMAP to delete.
87 // Otherwise we just unmap the pixel memory.
88 if (context)
89 DeleteObject(static_cast<HBITMAP>(context));
90 else
91 UnmapViewOfFile(addr);
92 }
93
94 static bool InstallHBitmapPixels(SkBitmap* bitmap, int width, int height,
95 bool is_opaque, void* data, HBITMAP hbitmap) {
96 const SkAlphaType at = is_opaque ? kOpaque_SkAlphaType : kPremul_SkAlphaType;
97 const SkImageInfo info = SkImageInfo::MakeN32(width, height, at);
98 const size_t rowBytes = info.minRowBytes();
99 SkColorTable* color_table = NULL;
100 return bitmap->installPixels(info, data, rowBytes, color_table,
101 DeleteHBitmapCallback, hbitmap);
102 }
103
104 // We use this static factory function instead of the regular constructor so
105 // that we can create the pixel data before calling the constructor. This is
106 // required so that we can call the base class' constructor with the pixel
107 // data.
108 BitmapPlatformDevice* BitmapPlatformDevice::Create(
109 int width,
110 int height,
111 bool is_opaque,
112 HANDLE shared_section,
113 bool do_clear) {
114
115 void* data;
116 HBITMAP hbitmap = NULL;
117
118 // This function contains an implementation of a Skia platform bitmap for
119 // drawing and compositing graphics. The original implementation uses Windows
120 // GDI to create the backing bitmap memory, however it's possible for a
121 // process to not have access to GDI which will cause this code to fail. It's
122 // possible to detect when GDI is unavailable and instead directly map the
123 // shared memory as the bitmap.
124 if (base::win::IsUser32AndGdi32Available()) {
125 hbitmap = skia::CreateHBitmap(width, height, is_opaque, shared_section,
126 &data);
127 if (!hbitmap) {
128 LOG(ERROR) << "CreateHBitmap failed";
129 return NULL;
130 }
131 } else {
132 DCHECK(shared_section != NULL);
133 data = MapViewOfFile(shared_section, FILE_MAP_WRITE, 0, 0,
134 PlatformCanvasStrideForWidth(width) * height);
135 if (!data) {
136 LOG(ERROR) << "MapViewOfFile failed";
137 return NULL;
138 }
139 }
140
141 SkBitmap bitmap;
142 if (!InstallHBitmapPixels(&bitmap, width, height, is_opaque, data, hbitmap)) {
143 LOG(ERROR) << "InstallHBitmapPixels failed";
144 return NULL;
145 }
146
147 if (do_clear)
148 bitmap.eraseColor(0);
149
150 #ifndef NDEBUG
151 // If we were given data, then don't clobber it!
152 if (!shared_section && is_opaque)
153 // To aid in finding bugs, we set the background color to something
154 // obviously wrong so it will be noticable when it is not cleared
155 bitmap.eraseARGB(255, 0, 255, 128); // bright bluish green
156 #endif
157
158 // The device object will take ownership of the HBITMAP. The initial refcount
159 // of the data object will be 1, which is what the constructor expects.
160 return new BitmapPlatformDevice(hbitmap, bitmap);
161 }
162
163 // static
164 BitmapPlatformDevice* BitmapPlatformDevice::Create(int width, int height,
165 bool is_opaque) {
166 const HANDLE shared_section = NULL;
167 const bool do_clear = false;
168 return Create(width, height, is_opaque, shared_section, do_clear);
169 }
170
171 // The device will own the HBITMAP, which corresponds to also owning the pixel
172 // data. Therefore, we do not transfer ownership to the SkBitmapDevice's bitmap.
173 BitmapPlatformDevice::BitmapPlatformDevice(
174 HBITMAP hbitmap,
175 const SkBitmap& bitmap)
176 : SkBitmapDevice(bitmap),
177 hbitmap_(hbitmap),
178 old_hbitmap_(NULL),
179 hdc_(NULL) {
180 // The data object is already ref'ed for us by create().
181 if (hbitmap) {
182 SetPlatformDevice(this, this);
183 BITMAP bitmap_data;
184 GetObject(hbitmap_, sizeof(BITMAP), &bitmap_data);
185 }
186 }
187
188 BitmapPlatformDevice::~BitmapPlatformDevice() {
189 if (hdc_)
190 ReleaseBitmapDC();
191 }
192
193 HDC BitmapPlatformDevice::BeginPlatformPaint(const SkMatrix& transform,
194 const SkIRect& clip_bounds) {
195 return GetBitmapDC(transform, clip_bounds);
196 }
197
198 SkBaseDevice* BitmapPlatformDevice::onCreateDevice(const CreateInfo& cinfo,
199 const SkPaint*) {
200 const SkImageInfo& info = cinfo.fInfo;
201 const bool do_clear = !info.isOpaque();
202 SkASSERT(info.colorType() == kN32_SkColorType);
203 return Create(info.width(), info.height(), info.isOpaque(), NULL, do_clear);
204 }
205
206 // PlatformCanvas impl
207
208 std::unique_ptr<SkCanvas> CreatePlatformCanvasWithSharedSection(
209 int width,
210 int height,
211 bool is_opaque,
212 HANDLE shared_section,
213 OnFailureType failureType) {
214 sk_sp<SkBaseDevice> device(
215 BitmapPlatformDevice::Create(width, height, is_opaque, shared_section));
216 if (!device) {
217 if (CRASH_ON_FAILURE == failureType)
218 SK_CRASH();
219 return nullptr;
220 }
221
222 return base::MakeUnique<SkCanvas>(device.get());
223 }
224
225 } // namespace skia
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698