| OLD | NEW |
| (Empty) | |
| 1 // Copyright (c) 2017 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/memory/ptr_util.h" |
| 11 #include "base/logging.h" |
| 12 #include "base/win/win_util.h" |
| 13 #include "skia/ext/platform_canvas.h" |
| 14 #include "skia/ext/skia_utils_win.h" |
| 15 #include "third_party/skia/include/core/SkMatrix.h" |
| 16 #include "third_party/skia/include/core/SkPath.h" |
| 17 #include "third_party/skia/include/core/SkRefCnt.h" |
| 18 #include "third_party/skia/include/core/SkRect.h" |
| 19 |
| 20 namespace { |
| 21 |
| 22 static void DeleteHDCCallback(void*, void* context) { |
| 23 HDC hdc = static_cast<HDC>(context); |
| 24 HBITMAP hbitmap = static_cast<HBITMAP>(SelectObject(hdc, nullptr)); |
| 25 DeleteObject(hbitmap); |
| 26 DeleteDC(hdc); |
| 27 } |
| 28 |
| 29 // Allocate the layer and fill in the fields for the Rec, or return false |
| 30 // on error. |
| 31 static bool Create(int width, |
| 32 int height, |
| 33 bool is_opaque, |
| 34 HANDLE shared_section, |
| 35 bool do_clear, |
| 36 SkRasterHandleAllocator::Rec* rec) { |
| 37 void* pixels; |
| 38 HBITMAP hbitmap = |
| 39 skia::CreateHBitmap(width, height, is_opaque, shared_section, &pixels); |
| 40 if (!hbitmap) { |
| 41 LOG(ERROR) << "CreateHBitmap failed"; |
| 42 return false; |
| 43 } |
| 44 |
| 45 size_t row_bytes = skia::PlatformCanvasStrideForWidth(width); |
| 46 if (do_clear) |
| 47 sk_bzero(pixels, row_bytes * height); |
| 48 |
| 49 HDC hdc = CreateCompatibleDC(nullptr); |
| 50 if (!hdc) { |
| 51 DeleteObject(hbitmap); |
| 52 return false; |
| 53 } |
| 54 SetGraphicsMode(hdc, GM_ADVANCED); |
| 55 SelectObject(hdc, hbitmap); |
| 56 |
| 57 rec->fReleaseProc = DeleteHDCCallback; |
| 58 rec->fReleaseCtx = hdc; |
| 59 rec->fPixels = pixels; |
| 60 rec->fRowBytes = row_bytes; |
| 61 rec->fHandle = hdc; |
| 62 return true; |
| 63 } |
| 64 |
| 65 /** |
| 66 * Subclass of SkRasterHandleAllocator that returns an HDC as its "handle". |
| 67 */ |
| 68 class GDIAllocator : public SkRasterHandleAllocator { |
| 69 public: |
| 70 GDIAllocator() {} |
| 71 |
| 72 bool allocHandle(const SkImageInfo& info, Rec* rec) override { |
| 73 SkASSERT(info.colorType() == kN32_SkColorType); |
| 74 return Create(info.width(), info.height(), info.isOpaque(), nullptr, |
| 75 !info.isOpaque(), rec); |
| 76 } |
| 77 |
| 78 void updateHandle(Handle handle, |
| 79 const SkMatrix& ctm, |
| 80 const SkIRect& clip_bounds) override { |
| 81 HDC hdc = static_cast<HDC>(handle); |
| 82 skia::LoadTransformToDC(hdc, ctm); |
| 83 |
| 84 HRGN hrgn = CreateRectRgnIndirect(&skia::SkIRectToRECT(clip_bounds)); |
| 85 int result = SelectClipRgn(hdc, hrgn); |
| 86 DCHECK(result != ERROR); |
| 87 result = DeleteObject(hrgn); |
| 88 DCHECK(result != 0); |
| 89 } |
| 90 }; |
| 91 |
| 92 } // namespace |
| 93 |
| 94 namespace skia { |
| 95 |
| 96 std::unique_ptr<SkCanvas> CreatePlatformCanvasWithSharedSection( |
| 97 int width, |
| 98 int height, |
| 99 bool is_opaque, |
| 100 HANDLE shared_section, |
| 101 OnFailureType failure_type) { |
| 102 SkAlphaType alpha = is_opaque ? kPremul_SkAlphaType : kOpaque_SkAlphaType; |
| 103 SkImageInfo info = SkImageInfo::MakeN32(width, height, alpha); |
| 104 size_t row_bytes = PlatformCanvasStrideForWidth(width); |
| 105 |
| 106 // This function contains an implementation of a Skia platform bitmap for |
| 107 // drawing and compositing graphics. The original implementation uses Windows |
| 108 // GDI to create the backing bitmap memory, however it's possible for a |
| 109 // process to not have access to GDI which will cause this code to fail. It's |
| 110 // possible to detect when GDI is unavailable and instead directly map the |
| 111 // shared memory as the bitmap. |
| 112 if (base::win::IsUser32AndGdi32Available()) { |
| 113 SkRasterHandleAllocator::Rec rec; |
| 114 if (Create(width, height, is_opaque, shared_section, false, &rec)) |
| 115 return SkRasterHandleAllocator::MakeCanvas( |
| 116 base::MakeUnique<GDIAllocator>(), info, &rec); |
| 117 } else { |
| 118 DCHECK(shared_section != NULL); |
| 119 void* pixels = |
| 120 MapViewOfFile(shared_section, FILE_MAP_WRITE, 0, 0, row_bytes * height); |
| 121 if (pixels) |
| 122 return SkCanvas::MakeRasterDirect(info, pixels, row_bytes); |
| 123 } |
| 124 |
| 125 if (failure_type == CRASH_ON_FAILURE) |
| 126 SK_CRASH(); |
| 127 return nullptr; |
| 128 } |
| 129 |
| 130 HDC GetNativeDrawingContext(SkCanvas* canvas) { |
| 131 return canvas ? static_cast<HDC>(canvas->accessTopRasterHandle()) : nullptr; |
| 132 } |
| 133 |
| 134 } // namespace skia |
| OLD | NEW |