1356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed/*
2356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed * Copyright 2016 Google Inc.
3356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed *
4356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed * Use of this source code is governed by a BSD-style license that can be
5356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed * found in the LICENSE file.
6356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed */
7356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed
8356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed#ifndef SkRasterHandleAllocator_DEFINED
9356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed#define SkRasterHandleAllocator_DEFINED
10356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed
11356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed#include "SkImageInfo.h"
12356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed
136b20a559968e1ed0d3aa4ecbd6ddda9e681b4f86Hal Canaryclass SkBitmap;
14356f7c2600ef54237fb8678cf63d5953f065b7daMike Reedclass SkCanvas;
15356f7c2600ef54237fb8678cf63d5953f065b7daMike Reedclass SkMatrix;
16356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed
17356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed/**
18356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed *  If a client wants to control the allocation of raster layers in a canvas, it should subclass
19356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed *  SkRasterHandleAllocator. This allocator performs two tasks:
20356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed *      1. controls how the memory for the pixels is allocated
21356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed *      2. associates a "handle" to a private object that can track the matrix/clip of the SkCanvas
22356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed *
23356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed *  This example allocates a canvas, and defers to the allocator to create the base layer.
24356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed *
25356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed *      std::unique_ptr<SkCanvas> canvas = SkRasterHandleAllocator::MakeCanvas(
26356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed *              SkImageInfo::Make(...),
27356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed *              skstd::make_unique<MySubclassRasterHandleAllocator>(...),
28356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed *              nullptr);
29356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed *
30356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed *  If you have already allocated the base layer (and its handle, release-proc etc.) then you
31356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed *  can pass those in using the last parameter to MakeCanvas().
32356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed *
33356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed *  Regardless of how the base layer is allocated, each time canvas->saveLayer() is called,
34356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed *  your allocator's allocHandle() will be called.
35356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed */
36356f7c2600ef54237fb8678cf63d5953f065b7daMike Reedclass SK_API SkRasterHandleAllocator {
37356f7c2600ef54237fb8678cf63d5953f065b7daMike Reedpublic:
38356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed    virtual ~SkRasterHandleAllocator() {}
39356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed
40356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed    // The value that is returned to clients of the canvas that has this allocator installed.
41356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed    typedef void* Handle;
42356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed
43356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed    struct Rec {
44356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed        // When the allocation goes out of scope, this proc is called to free everything associated
45356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed        // with it: the pixels, the "handle", etc. This is passed the pixel address and fReleaseCtx.
46356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed        void    (*fReleaseProc)(void* pixels, void* ctx);
47356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed        void*   fReleaseCtx;    // context passed to fReleaseProc
48356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed        void*   fPixels;        // pixels for this allocation
49356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed        size_t  fRowBytes;      // rowbytes for these pixels
50356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed        Handle  fHandle;        // public handle returned by SkCanvas::accessTopRasterHandle()
51356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed    };
52356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed
53356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed    /**
54356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed     *  Given a requested info, allocate the corresponding pixels/rowbytes, and whatever handle
55356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed     *  is desired to give clients access to those pixels. The rec also contains a proc and context
56356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed     *  which will be called when this allocation goes out of scope.
57356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed     *
58356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed     *  e.g.
59356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed     *      when canvas->saveLayer() is called, the allocator will be called to allocate the pixels
60356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed     *      for the layer. When canvas->restore() is called, the fReleaseProc will be called.
61356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed     */
62356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed    virtual bool allocHandle(const SkImageInfo&, Rec*) = 0;
63356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed
64356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed    /**
65356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed     *  Clients access the handle for a given layer by calling SkCanvas::accessTopRasterHandle().
66356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed     *  To allow the handle to reflect the current matrix/clip in the canvs, updateHandle() is
67356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed     *  is called. The subclass is responsible to update the handle as it sees fit.
68356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed     */
69356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed    virtual void updateHandle(Handle, const SkMatrix&, const SkIRect&) = 0;
70356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed
71356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed    /**
72356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed     *  This creates a canvas which will use the allocator to manage pixel allocations, including
73356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed     *  all calls to saveLayer().
74356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed     *
75356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed     *  If rec is non-null, then it will be used as the base-layer of pixels/handle.
76356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed     *  If rec is null, then the allocator will be called for the base-layer as well.
77356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed     */
78356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed    static std::unique_ptr<SkCanvas> MakeCanvas(std::unique_ptr<SkRasterHandleAllocator>,
79356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed                                                const SkImageInfo&, const Rec* rec = nullptr);
80356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed
81356f7c2600ef54237fb8678cf63d5953f065b7daMike Reedprivate:
82356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed    friend class SkBitmapDevice;
83356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed
84356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed    Handle allocBitmap(const SkImageInfo&, SkBitmap*);
85356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed};
86356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed
87356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed#endif
88