| 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 | |
| 13 | class SkBitmap; |
| 14 | class SkCanvas; |
| 15 | class 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 | */ |
| 36 | class SK_API SkRasterHandleAllocator { |
| 37 | public: |
| 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 | |
| 81 | private: |
| 82 | friend class SkBitmapDevice; |
| 83 | |
| 84 | Handle allocBitmap(const SkImageInfo&, SkBitmap*); |
| 85 | }; |
| 86 | |
| 87 | #endif |
| 88 | |