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

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

Issue 1321913002: Modified platform bitmap to support GDI being unavailable (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Made policy check static and added comment. Created 5 years, 3 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
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 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 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 <windows.h> 5 #include <windows.h>
6 #include <psapi.h> 6 #include <psapi.h>
7 7
8 #include "base/debug/gdi_debug_util_win.h" 8 #include "base/debug/gdi_debug_util_win.h"
9 #include "base/lazy_instance.h"
9 #include "base/logging.h" 10 #include "base/logging.h"
10 #include "skia/ext/bitmap_platform_device_win.h" 11 #include "skia/ext/bitmap_platform_device_win.h"
11 #include "skia/ext/platform_canvas.h" 12 #include "skia/ext/platform_canvas.h"
12 #include "third_party/skia/include/core/SkMatrix.h" 13 #include "third_party/skia/include/core/SkMatrix.h"
13 #include "third_party/skia/include/core/SkRefCnt.h" 14 #include "third_party/skia/include/core/SkRefCnt.h"
14 #include "third_party/skia/include/core/SkRegion.h" 15 #include "third_party/skia/include/core/SkRegion.h"
15 #include "third_party/skia/include/core/SkUtils.h" 16 #include "third_party/skia/include/core/SkUtils.h"
16 17
17 namespace { 18 namespace {
18 19
20 // This file contains an implementation of a Skia platform bitmap for drawing
21 // and compositing graphics. The original implementation uses Windows GDI
22 // to create the backing bitmap memory, however when using the sandbox security
23 // policy win32k lockdown it's not possible to use GDI for security reasons.
24 // Therefore this code also implements a fallback mechanism when a process is
25 // under this security policy to directly map the shared section as memory
26 // instead of using GDI. To catch new code which tries to explicitly rely on
27 // this code using GDI some additional DCHECKs have been added to catch that
28 // code during development.
29 typedef decltype(GetProcessMitigationPolicy)* GetProcessMitigationPolicyType;
30
31 // Get win32k lockdown policy using a lazy instance so it's only initialized
32 // once and is thread-safe.
33 class LazyIsWin32kLockdownEnabled {
34 public:
35 LazyIsWin32kLockdownEnabled()
36 : value_(IsWin32kLockdownEnabled()) {}
37
38 ~LazyIsWin32kLockdownEnabled() {}
39
40 bool value() { return value_; }
41
42 private:
43 static bool IsWin32kLockdownEnabled() {
44 GetProcessMitigationPolicyType get_process_mitigation_policy_func =
45 reinterpret_cast<GetProcessMitigationPolicyType>(
46 GetProcAddress(
47 GetModuleHandle(L"kernel32.dll"),
48 "GetProcessMitigationPolicy"));
49
50 if (!get_process_mitigation_policy_func)
51 return false;
52
53 PROCESS_MITIGATION_SYSTEM_CALL_DISABLE_POLICY policy = {0};
54 if (get_process_mitigation_policy_func(GetCurrentProcess(),
55 ProcessSystemCallDisablePolicy,
56 &policy,
57 sizeof(policy)))
58 return policy.DisallowWin32kSystemCalls != 0;
59
60 return false;
61 }
62
63 const bool value_;
64
65 DISALLOW_COPY_AND_ASSIGN(LazyIsWin32kLockdownEnabled);
66 };
67
68 bool IsWin32kLockdownEnabled() {
69 static base::LazyInstance<LazyIsWin32kLockdownEnabled> win32k_lockdown;
Will Harris 2015/09/10 17:34:45 I think this needs a LAZY_INSTANCE_INITIALIZER
70 return win32k_lockdown.Get().value();
71 }
72
19 HBITMAP CreateHBitmap(int width, int height, bool is_opaque, 73 HBITMAP CreateHBitmap(int width, int height, bool is_opaque,
20 HANDLE shared_section, void** data) { 74 HANDLE shared_section, void** data) {
21 // CreateDIBSection appears to get unhappy if we create an empty bitmap, so 75 // CreateDIBSection appears to get unhappy if we create an empty bitmap, so
22 // just create a minimal bitmap 76 // just create a minimal bitmap
23 if ((width == 0) || (height == 0)) { 77 if ((width == 0) || (height == 0)) {
24 width = 1; 78 width = 1;
25 height = 1; 79 height = 1;
26 } 80 }
27 81
28 BITMAPINFOHEADER hdr = {0}; 82 BITMAPINFOHEADER hdr = {0};
(...skipping 21 matching lines...) Expand all
50 104
51 return hbitmap; 105 return hbitmap;
52 } 106 }
53 107
54 } // namespace 108 } // namespace
55 109
56 namespace skia { 110 namespace skia {
57 111
58 void DrawToNativeContext(SkCanvas* canvas, HDC hdc, int x, int y, 112 void DrawToNativeContext(SkCanvas* canvas, HDC hdc, int x, int y,
59 const RECT* src_rect) { 113 const RECT* src_rect) {
114 DCHECK(!IsWin32kLockdownEnabled());
60 PlatformDevice* platform_device = GetPlatformDevice(GetTopDevice(*canvas)); 115 PlatformDevice* platform_device = GetPlatformDevice(GetTopDevice(*canvas));
61 if (platform_device) 116 if (platform_device)
62 platform_device->DrawToHDC(hdc, x, y, src_rect); 117 platform_device->DrawToHDC(hdc, x, y, src_rect);
63 } 118 }
64 119
65 void PlatformDevice::DrawToHDC(HDC, int x, int y, const RECT* src_rect) {} 120 void PlatformDevice::DrawToHDC(HDC, int x, int y, const RECT* src_rect) {}
66 121
67 HDC BitmapPlatformDevice::GetBitmapDC() { 122 HDC BitmapPlatformDevice::GetBitmapDC() {
123 DCHECK(!IsWin32kLockdownEnabled());
68 if (!hdc_) { 124 if (!hdc_) {
69 hdc_ = CreateCompatibleDC(NULL); 125 hdc_ = CreateCompatibleDC(NULL);
70 InitializeDC(hdc_); 126 InitializeDC(hdc_);
71 old_hbitmap_ = static_cast<HBITMAP>(SelectObject(hdc_, hbitmap_)); 127 old_hbitmap_ = static_cast<HBITMAP>(SelectObject(hdc_, hbitmap_));
72 } 128 }
73 129
74 LoadConfig(); 130 LoadConfig();
75 return hdc_; 131 return hdc_;
76 } 132 }
77 133
78 void BitmapPlatformDevice::ReleaseBitmapDC() { 134 void BitmapPlatformDevice::ReleaseBitmapDC() {
79 SkASSERT(hdc_); 135 if (!IsWin32kLockdownEnabled()) {
80 SelectObject(hdc_, old_hbitmap_); 136 SkASSERT(hdc_);
81 DeleteDC(hdc_); 137 SelectObject(hdc_, old_hbitmap_);
82 hdc_ = NULL; 138 DeleteDC(hdc_);
83 old_hbitmap_ = NULL; 139 hdc_ = NULL;
140 old_hbitmap_ = NULL;
141 }
84 } 142 }
85 143
86 bool BitmapPlatformDevice::IsBitmapDCCreated() 144 bool BitmapPlatformDevice::IsBitmapDCCreated()
87 const { 145 const {
88 return hdc_ != NULL; 146 return hdc_ != NULL;
89 } 147 }
90 148
91 149
92 void BitmapPlatformDevice::SetMatrixClip( 150 void BitmapPlatformDevice::SetMatrixClip(
93 const SkMatrix& transform, 151 const SkMatrix& transform,
94 const SkRegion& region) { 152 const SkRegion& region) {
95 transform_ = transform; 153 transform_ = transform;
96 clip_region_ = region; 154 clip_region_ = region;
97 config_dirty_ = true; 155 config_dirty_ = true;
98 } 156 }
99 157
100 void BitmapPlatformDevice::LoadConfig() { 158 void BitmapPlatformDevice::LoadConfig() {
101 if (!config_dirty_ || !hdc_) 159 if (!config_dirty_ || !hdc_)
102 return; // Nothing to do. 160 return; // Nothing to do.
103 config_dirty_ = false; 161 config_dirty_ = false;
104 162
105 // Transform. 163 // Transform.
106 LoadTransformToDC(hdc_, transform_); 164 LoadTransformToDC(hdc_, transform_);
107 LoadClippingRegionToDC(hdc_, clip_region_, transform_); 165 LoadClippingRegionToDC(hdc_, clip_region_, transform_);
108 } 166 }
109 167
110 static void DeleteHBitmapCallback(void* addr, void* context) { 168 static void DeleteHBitmapCallback(void* addr, void* context) {
111 DeleteObject(static_cast<HBITMAP>(context)); 169 // If context is not NULL then it's a valid HBITMAP to delete.
170 // Otherwise we just unmap the pixel memory.
171 if (context)
172 DeleteObject(static_cast<HBITMAP>(context));
173 else
174 UnmapViewOfFile(addr);
112 } 175 }
113 176
114 static bool InstallHBitmapPixels(SkBitmap* bitmap, int width, int height, 177 static bool InstallHBitmapPixels(SkBitmap* bitmap, int width, int height,
115 bool is_opaque, void* data, HBITMAP hbitmap) { 178 bool is_opaque, void* data, HBITMAP hbitmap) {
116 const SkAlphaType at = is_opaque ? kOpaque_SkAlphaType : kPremul_SkAlphaType; 179 const SkAlphaType at = is_opaque ? kOpaque_SkAlphaType : kPremul_SkAlphaType;
117 const SkImageInfo info = SkImageInfo::MakeN32(width, height, at); 180 const SkImageInfo info = SkImageInfo::MakeN32(width, height, at);
118 const size_t rowBytes = info.minRowBytes(); 181 const size_t rowBytes = info.minRowBytes();
119 SkColorTable* color_table = NULL; 182 SkColorTable* color_table = NULL;
120 return bitmap->installPixels(info, data, rowBytes, color_table, 183 return bitmap->installPixels(info, data, rowBytes, color_table,
121 DeleteHBitmapCallback, hbitmap); 184 DeleteHBitmapCallback, hbitmap);
122 } 185 }
123 186
124 // We use this static factory function instead of the regular constructor so 187 // We use this static factory function instead of the regular constructor so
125 // that we can create the pixel data before calling the constructor. This is 188 // that we can create the pixel data before calling the constructor. This is
126 // required so that we can call the base class' constructor with the pixel 189 // required so that we can call the base class' constructor with the pixel
127 // data. 190 // data.
128 BitmapPlatformDevice* BitmapPlatformDevice::Create( 191 BitmapPlatformDevice* BitmapPlatformDevice::Create(
129 int width, 192 int width,
130 int height, 193 int height,
131 bool is_opaque, 194 bool is_opaque,
132 HANDLE shared_section, 195 HANDLE shared_section,
133 bool do_clear) { 196 bool do_clear) {
134 197
135 void* data; 198 void* data;
136 HBITMAP hbitmap = CreateHBitmap(width, height, is_opaque, shared_section, 199
200 HBITMAP hbitmap = NULL;
201
202 if (IsWin32kLockdownEnabled()) {
203 CHECK(shared_section != NULL);
204 data = MapViewOfFile(shared_section, FILE_MAP_WRITE,
205 0, 0, width * height * 4);
206 DCHECK(data != NULL);
207 if (!data)
208 return NULL;
209 } else {
210 hbitmap = CreateHBitmap(width, height, is_opaque, shared_section,
137 &data); 211 &data);
138 if (!hbitmap) 212 if (!hbitmap)
139 return NULL; 213 return NULL;
214 }
140 215
141 SkBitmap bitmap; 216 SkBitmap bitmap;
142 if (!InstallHBitmapPixels(&bitmap, width, height, is_opaque, data, hbitmap)) 217 if (!InstallHBitmapPixels(&bitmap, width, height, is_opaque, data, hbitmap))
143 return NULL; 218 return NULL;
144 219
145 if (do_clear) 220 if (do_clear)
146 bitmap.eraseColor(0); 221 bitmap.eraseColor(0);
147 222
148 #ifndef NDEBUG 223 #ifndef NDEBUG
149 // If we were given data, then don't clobber it! 224 // If we were given data, then don't clobber it!
(...skipping 23 matching lines...) Expand all
173 const SkBitmap& bitmap) 248 const SkBitmap& bitmap)
174 : SkBitmapDevice(bitmap), 249 : SkBitmapDevice(bitmap),
175 hbitmap_(hbitmap), 250 hbitmap_(hbitmap),
176 old_hbitmap_(NULL), 251 old_hbitmap_(NULL),
177 hdc_(NULL), 252 hdc_(NULL),
178 config_dirty_(true), // Want to load the config next time. 253 config_dirty_(true), // Want to load the config next time.
179 transform_(SkMatrix::I()) { 254 transform_(SkMatrix::I()) {
180 // The data object is already ref'ed for us by create(). 255 // The data object is already ref'ed for us by create().
181 SkDEBUGCODE(begin_paint_count_ = 0); 256 SkDEBUGCODE(begin_paint_count_ = 0);
182 SetPlatformDevice(this, this); 257 SetPlatformDevice(this, this);
183 // Initialize the clip region to the entire bitmap. 258 if (hbitmap) {
184 BITMAP bitmap_data; 259 // Initialize the clip region to the entire bitmap.
185 if (GetObject(hbitmap_, sizeof(BITMAP), &bitmap_data)) { 260 BITMAP bitmap_data;
186 SkIRect rect; 261 if (GetObject(hbitmap_, sizeof(BITMAP), &bitmap_data)) {
187 rect.set(0, 0, bitmap_data.bmWidth, bitmap_data.bmHeight); 262 SkIRect rect;
188 clip_region_ = SkRegion(rect); 263 rect.set(0, 0, bitmap_data.bmWidth, bitmap_data.bmHeight);
264 clip_region_ = SkRegion(rect);
265 }
189 } 266 }
190 } 267 }
191 268
192 BitmapPlatformDevice::~BitmapPlatformDevice() { 269 BitmapPlatformDevice::~BitmapPlatformDevice() {
193 SkASSERT(begin_paint_count_ == 0); 270 SkASSERT(begin_paint_count_ == 0);
194 if (hdc_) 271 if (hdc_)
195 ReleaseBitmapDC(); 272 ReleaseBitmapDC();
196 } 273 }
197 274
198 HDC BitmapPlatformDevice::BeginPlatformPaint() { 275 HDC BitmapPlatformDevice::BeginPlatformPaint() {
199 SkDEBUGCODE(begin_paint_count_++); 276 SkDEBUGCODE(begin_paint_count_++);
200 return GetBitmapDC(); 277 return GetBitmapDC();
201 } 278 }
202 279
203 void BitmapPlatformDevice::EndPlatformPaint() { 280 void BitmapPlatformDevice::EndPlatformPaint() {
204 SkASSERT(begin_paint_count_--); 281 SkASSERT(begin_paint_count_--);
205 PlatformDevice::EndPlatformPaint(); 282 PlatformDevice::EndPlatformPaint();
206 } 283 }
207 284
208 void BitmapPlatformDevice::setMatrixClip(const SkMatrix& transform, 285 void BitmapPlatformDevice::setMatrixClip(const SkMatrix& transform,
209 const SkRegion& region, 286 const SkRegion& region,
210 const SkClipStack&) { 287 const SkClipStack&) {
211 SetMatrixClip(transform, region); 288 SetMatrixClip(transform, region);
212 } 289 }
213 290
214 void BitmapPlatformDevice::DrawToHDC(HDC dc, int x, int y, 291 void BitmapPlatformDevice::DrawToHDC(HDC dc, int x, int y,
215 const RECT* src_rect) { 292 const RECT* src_rect) {
293 DCHECK(!IsWin32kLockdownEnabled());
294
216 bool created_dc = !IsBitmapDCCreated(); 295 bool created_dc = !IsBitmapDCCreated();
217 HDC source_dc = BeginPlatformPaint(); 296 HDC source_dc = BeginPlatformPaint();
218 297
219 RECT temp_rect; 298 RECT temp_rect;
220 if (!src_rect) { 299 if (!src_rect) {
221 temp_rect.left = 0; 300 temp_rect.left = 0;
222 temp_rect.right = width(); 301 temp_rect.right = width();
223 temp_rect.top = 0; 302 temp_rect.top = 0;
224 temp_rect.bottom = height(); 303 temp_rect.bottom = height();
225 src_rect = &temp_rect; 304 src_rect = &temp_rect;
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after
298 377
299 PlatformBitmap::~PlatformBitmap() { 378 PlatformBitmap::~PlatformBitmap() {
300 if (surface_) { 379 if (surface_) {
301 if (platform_extra_) 380 if (platform_extra_)
302 SelectObject(surface_, reinterpret_cast<HGDIOBJ>(platform_extra_)); 381 SelectObject(surface_, reinterpret_cast<HGDIOBJ>(platform_extra_));
303 DeleteDC(surface_); 382 DeleteDC(surface_);
304 } 383 }
305 } 384 }
306 385
307 bool PlatformBitmap::Allocate(int width, int height, bool is_opaque) { 386 bool PlatformBitmap::Allocate(int width, int height, bool is_opaque) {
387 DCHECK(!IsWin32kLockdownEnabled());
308 void* data; 388 void* data;
309 HBITMAP hbitmap = CreateHBitmap(width, height, is_opaque, 0, &data); 389 HBITMAP hbitmap = CreateHBitmap(width, height, is_opaque, 0, &data);
310 if (!hbitmap) 390 if (!hbitmap)
311 return false; 391 return false;
312 392
313 surface_ = CreateCompatibleDC(NULL); 393 surface_ = CreateCompatibleDC(NULL);
314 InitializeDC(surface_); 394 InitializeDC(surface_);
315 // When the memory DC is created, its display surface is exactly one 395 // When the memory DC is created, its display surface is exactly one
316 // monochrome pixel wide and one monochrome pixel high. Save this object 396 // monochrome pixel wide and one monochrome pixel high. Save this object
317 // off, we'll restore it just before deleting the memory DC. 397 // off, we'll restore it just before deleting the memory DC.
318 HGDIOBJ stock_bitmap = SelectObject(surface_, hbitmap); 398 HGDIOBJ stock_bitmap = SelectObject(surface_, hbitmap);
319 platform_extra_ = reinterpret_cast<intptr_t>(stock_bitmap); 399 platform_extra_ = reinterpret_cast<intptr_t>(stock_bitmap);
320 400
321 if (!InstallHBitmapPixels(&bitmap_, width, height, is_opaque, data, hbitmap)) 401 if (!InstallHBitmapPixels(&bitmap_, width, height, is_opaque, data, hbitmap))
322 return false; 402 return false;
323 bitmap_.lockPixels(); 403 bitmap_.lockPixels();
324 404
325 return true; 405 return true;
326 } 406 }
327 407
328 } // namespace skia 408 } // namespace skia
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698