1/*
2 * Copyright 2016 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
8#ifndef SkRasterHandleAllocator_DEFINED
9#define SkRasterHandleAllocator_DEFINED
10
11#include "include/core/SkImageInfo.h"
12
13class SkBitmap;
14class SkCanvas;
15class SkMatrix;
16
17/**
18 * If a client wants to control the allocation of raster layers in a canvas, it should subclass
19 * SkRasterHandleAllocator. This allocator performs two tasks:
20 * 1. controls how the memory for the pixels is allocated
21 * 2. associates a "handle" to a private object that can track the matrix/clip of the SkCanvas
22 *
23 * This example allocates a canvas, and defers to the allocator to create the base layer.
24 *
25 * std::unique_ptr<SkCanvas> canvas = SkRasterHandleAllocator::MakeCanvas(
26 * SkImageInfo::Make(...),
27 * std::make_unique<MySubclassRasterHandleAllocator>(...),
28 * nullptr);
29 *
30 * If you have already allocated the base layer (and its handle, release-proc etc.) then you
31 * can pass those in using the last parameter to MakeCanvas().
32 *
33 * Regardless of how the base layer is allocated, each time canvas->saveLayer() is called,
34 * your allocator's allocHandle() will be called.
35 */
36class SK_API SkRasterHandleAllocator {
37public:
38 virtual ~SkRasterHandleAllocator() {}
39
40 // The value that is returned to clients of the canvas that has this allocator installed.
41 typedef void* Handle;
42
43 struct Rec {
44 // When the allocation goes out of scope, this proc is called to free everything associated
45 // with it: the pixels, the "handle", etc. This is passed the pixel address and fReleaseCtx.
46 void (*fReleaseProc)(void* pixels, void* ctx);
47 void* fReleaseCtx; // context passed to fReleaseProc
48 void* fPixels; // pixels for this allocation
49 size_t fRowBytes; // rowbytes for these pixels
50 Handle fHandle; // public handle returned by SkCanvas::accessTopRasterHandle()
51 };
52
53 /**
54 * Given a requested info, allocate the corresponding pixels/rowbytes, and whatever handle
55 * is desired to give clients access to those pixels. The rec also contains a proc and context
56 * which will be called when this allocation goes out of scope.
57 *
58 * e.g.
59 * when canvas->saveLayer() is called, the allocator will be called to allocate the pixels
60 * for the layer. When canvas->restore() is called, the fReleaseProc will be called.
61 */
62 virtual bool allocHandle(const SkImageInfo&, Rec*) = 0;
63
64 /**
65 * Clients access the handle for a given layer by calling SkCanvas::accessTopRasterHandle().
66 * To allow the handle to reflect the current matrix/clip in the canvs, updateHandle() is
67 * is called. The subclass is responsible to update the handle as it sees fit.
68 */
69 virtual void updateHandle(Handle, const SkMatrix&, const SkIRect&) = 0;
70
71 /**
72 * This creates a canvas which will use the allocator to manage pixel allocations, including
73 * all calls to saveLayer().
74 *
75 * If rec is non-null, then it will be used as the base-layer of pixels/handle.
76 * If rec is null, then the allocator will be called for the base-layer as well.
77 */
78 static std::unique_ptr<SkCanvas> MakeCanvas(std::unique_ptr<SkRasterHandleAllocator>,
79 const SkImageInfo&, const Rec* rec = nullptr);
80
81private:
82 friend class SkBitmapDevice;
83
84 Handle allocBitmap(const SkImageInfo&, SkBitmap*);
85};
86
87#endif
88