Chromium Code Reviews| Index: skia/ext/raster_handle_allocator_win.cc |
| diff --git a/skia/ext/raster_handle_allocator_win.cc b/skia/ext/raster_handle_allocator_win.cc |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..cda8a7ba71e4e4fb8519ed87beab06856a7b38a4 |
| --- /dev/null |
| +++ b/skia/ext/raster_handle_allocator_win.cc |
| @@ -0,0 +1,133 @@ |
| +// Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| +// Use of this source code is governed by a BSD-style license that can be |
| +// found in the LICENSE file. |
| + |
| +#include <windows.h> |
| +#include <psapi.h> |
| +#include <stddef.h> |
| + |
| +#include "base/debug/gdi_debug_util_win.h" |
| +#include "base/logging.h" |
| +#include "base/win/win_util.h" |
| +#include "skia/ext/bitmap_platform_device_win.h" |
| +#include "skia/ext/platform_canvas.h" |
| +#include "skia/ext/skia_utils_win.h" |
| +#include "third_party/skia/include/core/SkMatrix.h" |
| +#include "third_party/skia/include/core/SkPath.h" |
| +#include "third_party/skia/include/core/SkRefCnt.h" |
| +#include "third_party/skia/include/core/SkRect.h" |
| + |
| +namespace { |
| + |
| +static void DeleteHDCCallback(void*, void* context) { |
| + HDC hdc = static_cast<HDC>(context); |
| + HBITMAP hbitmap = static_cast<HBITMAP> SelectObject(hdc, nullptr); |
| + DeleteObject(hbitmap); |
| + DeleteDC(hdc); |
| +} |
| + |
| +// We use this static factory function instead of the regular constructor so |
| +// that we can create the pixel data before calling the constructor. This is |
| +// required so that we can call the base class' constructor with the pixel |
| +// data. |
| +static bool Create(int width, |
| + int height, |
| + bool is_opaque, |
| + HANDLE shared_section, |
| + bool do_clear, |
| + SkRasterHandleAllocator::Rec* rec) { |
| + void* pixels; |
| + HBITMAP hbitmap = |
| + skia::CreateHBitmap(width, height, is_opaque, shared_section, &data); |
|
f(malita)
2017/01/10 16:10:15
s/data/pixels?
|
| + if (!hbitmap) { |
| + LOG(ERROR) << "CreateHBitmap failed"; |
| + return false; |
| + } |
| + |
| + size_t row_bytes = PlatformCanvasStrideForWidth(width); |
| + if (do_clear) |
| + sk_bzero(pixels, row_bytes * height); |
| + |
| + HDC hdc = CreateCompatibleDC(nullptr); |
| + if (!hdc) { |
| + DeleteObject(hbitmap); |
| + return false; |
| + } |
| + SelectObject(hdc, hbitmap); |
| + |
| + rec->fReleaseProc = DeleteHDCCallback; |
| + rec->fReleaseCtx = hdc; |
| + rec->fPixels = pixels; |
| + rec->fRowBytes = row_bytes; |
| + rec->fHandle = hdc; |
| + return true; |
| +} |
| + |
| +/** |
| + * Subclass of SkRasterHandleAllocator that returns an HDC as its "handle". |
| + */ |
| +class GDIAllocator : public SkRasterHandleAllocator { |
| + public: |
| + GDIAllocator() {} |
| + |
| + bool allocHandle(const SkImageInfo& info, Rec* rec) override { |
| + SkASSERT(info.colorType() == kN32_SkColorType); |
| + return Create(info.width(), info.height(), info.isOpaque(), nullptr, |
| + !info.isOpaque(), rec); |
| + } |
| + |
| + void updateHandle(Handle handle, |
| + const SkMatrix& ctm, |
| + const SkIRect& clip_bounds) override { |
| + HDC hdc = static_cast<HDC>(handle); |
| + |
| + skia::LoadTransformToDC(hdc, ctm); |
| + |
| + HRGN hrgn = CreateRectRgnIndirect(&skia::SkIRectToRECT(clip_bounds)); |
| + int result = SelectClipRgn(hdc, hrgn); |
| + DCHECK(result != ERROR); |
| + result = DeleteObject(hrgn); |
| + DCHECK(result != 0); |
| + } |
| +}; |
| + |
| +} // namespace |
| + |
| +namespace skia { |
| + |
| +std::unique_ptr<SkCanvas> CreatePlatformCanvasWithSharedSection( |
| + int width, |
| + int height, |
| + bool is_opaque, |
| + HANDLE shared_section, |
| + OnFailureType failure_type) { |
| + SkAlphaType alpha = is_opaque ? kPremul_SkAlphaType : kOpaque_SkAlphaType; |
| + SkImageInfo info = SkImageInfo::MakeN32(width, height, alpha); |
| + size_t row_bytes = PlatformCanvasStrideForWidth(width); |
| + |
| + // This function contains an implementation of a Skia platform bitmap for |
| + // drawing and compositing graphics. The original implementation uses Windows |
| + // GDI to create the backing bitmap memory, however it's possible for a |
| + // process to not have access to GDI which will cause this code to fail. It's |
| + // possible to detect when GDI is unavailable and instead directly map the |
| + // shared memory as the bitmap. |
| + if (base::win::IsUser32AndGdi32Available()) { |
| + SkRasterHandleAllocator::Rec rec; |
| + if (Create(width, height, is_opaque, shared_section, false, &rec)) |
| + return SkRasterHandleAllocator::MakeCanvas( |
| + std::unique_ptr<SkRasterHandleAllocator>(new GDIAllocator), info, |
| + &rec); |
| + } else { |
| + DCHECK(shared_section != NULL); |
| + void* pixels = |
| + MapViewOfFile(shared_section, FILE_MAP_WRITE, 0, 0, row_bytes * height); |
| + if (pixels) |
| + return SkCanvas::MakeRasterDirect(info, pixels, row_bytes); |
| + } |
| + |
| + if (failure_type == CRASH_ON_FAILURE) |
| + SK_CRASH(); |
| + return nullptr; |
| +} |
| + |
| +} // namespace skia |