| 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..93e1a252159d01b11b9bafc31041737b20676a0e
|
| --- /dev/null
|
| +++ b/skia/ext/raster_handle_allocator_win.cc
|
| @@ -0,0 +1,134 @@
|
| +// Copyright (c) 2017 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/memory/ptr_util.h"
|
| +#include "base/logging.h"
|
| +#include "base/win/win_util.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);
|
| +}
|
| +
|
| +// Allocate the layer and fill in the fields for the Rec, or return false
|
| +// on error.
|
| +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, &pixels);
|
| + if (!hbitmap) {
|
| + LOG(ERROR) << "CreateHBitmap failed";
|
| + return false;
|
| + }
|
| +
|
| + size_t row_bytes = skia::PlatformCanvasStrideForWidth(width);
|
| + if (do_clear)
|
| + sk_bzero(pixels, row_bytes * height);
|
| +
|
| + HDC hdc = CreateCompatibleDC(nullptr);
|
| + if (!hdc) {
|
| + DeleteObject(hbitmap);
|
| + return false;
|
| + }
|
| + SetGraphicsMode(hdc, GM_ADVANCED);
|
| + 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(
|
| + base::MakeUnique<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;
|
| +}
|
| +
|
| +HDC GetNativeDrawingContext(SkCanvas* canvas) {
|
| + return canvas ? static_cast<HDC>(canvas->accessTopRasterHandle()) : nullptr;
|
| +}
|
| +
|
| +} // namespace skia
|
|
|