1/*
2 * Copyright 2015 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 GrResourceProvider_DEFINED
9#define GrResourceProvider_DEFINED
10
11#include "GrBatchAtlas.h"
12#include "GrIndexBuffer.h"
13#include "GrTextureProvider.h"
14#include "GrPathRange.h"
15
16class GrBatchAtlas;
17class GrIndexBuffer;
18class GrPath;
19class GrRenderTarget;
20class GrSingleOwner;
21class GrStencilAttachment;
22class GrStrokeInfo;
23class GrVertexBuffer;
24class SkDescriptor;
25class SkPath;
26class SkTypeface;
27
28/**
29 * An extension of the texture provider for arbitrary resource types. This class is intended for
30 * use within the Gr code base, not by clients or extensions (e.g. third party GrProcessor
31 * derivatives).
32 *
33 * This currently inherits from GrTextureProvider non-publically to force callers to provider
34 * make a flags (pendingIO) decision and not use the GrTP methods that don't take flags. This
35 * can be relaxed once https://bug.skia.org/4156 is fixed.
36 */
37class GrResourceProvider : protected GrTextureProvider {
38public:
39    GrResourceProvider(GrGpu* gpu, GrResourceCache* cache, GrSingleOwner* owner);
40
41    template <typename T> T* findAndRefTByUniqueKey(const GrUniqueKey& key) {
42        return static_cast<T*>(this->findAndRefResourceByUniqueKey(key));
43    }
44
45    /**
46     * Either finds and refs, or creates an index buffer for instanced drawing with a specific
47     * pattern if the index buffer is not found. If the return is non-null, the caller owns
48     * a ref on the returned GrIndexBuffer.
49     *
50     * @param pattern     the pattern of indices to repeat
51     * @param patternSize size in bytes of the pattern
52     * @param reps        number of times to repeat the pattern
53     * @param vertCount   number of vertices the pattern references
54     * @param key         Key to be assigned to the index buffer.
55     *
56     * @return The index buffer if successful, otherwise nullptr.
57     */
58    const GrIndexBuffer* findOrCreateInstancedIndexBuffer(const uint16_t* pattern,
59                                                          int patternSize,
60                                                          int reps,
61                                                          int vertCount,
62                                                          const GrUniqueKey& key) {
63        if (GrIndexBuffer* buffer = this->findAndRefTByUniqueKey<GrIndexBuffer>(key)) {
64            return buffer;
65        }
66        return this->createInstancedIndexBuffer(pattern, patternSize, reps, vertCount, key);
67    }
68
69    /**
70     * Returns an index buffer that can be used to render quads.
71     * Six indices per quad: 0, 1, 2, 0, 2, 3, etc.
72     * The max number of quads can be queried using GrIndexBuffer::maxQuads().
73     * Draw with kTriangles_GrPrimitiveType
74     * @ return the quad index buffer
75     */
76    const GrIndexBuffer* refQuadIndexBuffer() {
77        if (GrIndexBuffer* buffer =
78            this->findAndRefTByUniqueKey<GrIndexBuffer>(fQuadIndexBufferKey)) {
79            return buffer;
80        }
81        return this->createQuadIndexBuffer();
82    }
83
84    /**
85     * Factories for GrPath and GrPathRange objects. It's an error to call these if path rendering
86     * is not supported.
87     */
88    GrPath* createPath(const SkPath&, const GrStrokeInfo&);
89    GrPathRange* createPathRange(GrPathRange::PathGenerator*, const GrStrokeInfo&);
90    GrPathRange* createGlyphs(const SkTypeface*, const SkDescriptor*, const GrStrokeInfo&);
91
92    using GrTextureProvider::assignUniqueKeyToResource;
93    using GrTextureProvider::findAndRefResourceByUniqueKey;
94    using GrTextureProvider::findAndRefTextureByUniqueKey;
95    using GrTextureProvider::abandon;
96
97    enum Flags {
98        /** If the caller intends to do direct reads/writes to/from the CPU then this flag must be
99         *  set when accessing resources during a GrDrawTarget flush. This includes the execution of
100         *  GrBatch objects. The reason is that these memory operations are done immediately and
101         *  will occur out of order WRT the operations being flushed.
102         *  Make this automatic: https://bug.skia.org/4156
103         */
104        kNoPendingIO_Flag = kNoPendingIO_ScratchTextureFlag,
105    };
106
107    enum BufferUsage {
108        /** Caller intends to specify the buffer data rarely with respect to the number of draws
109            that read the data. */
110        kStatic_BufferUsage,
111        /** Caller intends to respecify the buffer data frequently between draws. */
112        kDynamic_BufferUsage,
113    };
114    GrIndexBuffer* createIndexBuffer(size_t size, BufferUsage, uint32_t flags);
115    GrVertexBuffer* createVertexBuffer(size_t size, BufferUsage, uint32_t flags);
116    GrTransferBuffer* createTransferBuffer(size_t size, TransferType, uint32_t flags);
117
118    GrTexture* createApproxTexture(const GrSurfaceDesc& desc, uint32_t flags) {
119        SkASSERT(0 == flags || kNoPendingIO_Flag == flags);
120        return this->internalCreateApproxTexture(desc, flags);
121    }
122
123    /**  Returns a GrBatchAtlas. This function can be called anywhere, but the returned atlas should
124     *   only be used inside of GrBatch::generateGeometry
125     *   @param GrPixelConfig    The pixel config which this atlas will store
126     *   @param width            width in pixels of the atlas
127     *   @param height           height in pixels of the atlas
128     *   @param numPlotsX        The number of plots the atlas should be broken up into in the X
129     *                           direction
130     *   @param numPlotsY        The number of plots the atlas should be broken up into in the Y
131     *                           direction
132     *   @param func             An eviction function which will be called whenever the atlas has to
133     *                           evict data
134     *   @param data             User supplied data which will be passed into func whenver an
135     *                           eviction occurs
136     *
137     *   @return                 An initialized GrBatchAtlas, or nullptr if creation fails
138     */
139    GrBatchAtlas* createAtlas(GrPixelConfig, int width, int height, int numPlotsX, int numPlotsY,
140                              GrBatchAtlas::EvictionFunc func, void* data);
141
142    /**
143     * If passed in render target already has a stencil buffer, return it. Otherwise attempt to
144     * attach one.
145     */
146    GrStencilAttachment* attachStencilAttachment(GrRenderTarget* rt);
147
148    const GrCaps* caps() { return this->gpu()->caps(); }
149
150     /**
151      * Wraps an existing texture with a GrRenderTarget object. This is useful when the provided
152      * texture has a format that cannot be textured from by Skia, but we want to raster to it.
153      *
154      * @return GrRenderTarget object or NULL on failure.
155      */
156     GrRenderTarget* wrapBackendTextureAsRenderTarget(const GrBackendTextureDesc& desc,
157                                                      GrWrapOwnership = kBorrow_GrWrapOwnership);
158
159private:
160    const GrIndexBuffer* createInstancedIndexBuffer(const uint16_t* pattern,
161                                                    int patternSize,
162                                                    int reps,
163                                                    int vertCount,
164                                                    const GrUniqueKey& key);
165
166    const GrIndexBuffer* createQuadIndexBuffer();
167
168    GrUniqueKey fQuadIndexBufferKey;
169
170    typedef GrTextureProvider INHERITED;
171};
172
173#endif
174