1 /*
2  * Copyright 2011 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 GrInOrderDrawBuffer_DEFINED
9 #define GrInOrderDrawBuffer_DEFINED
10 
11 #include "GrDrawTarget.h"
12 #include "GrCommandBuilder.h"
13 #include "SkChunkAlloc.h"
14 
15 /**
16  * GrInOrderDrawBuffer is an implementation of GrDrawTarget that queues up draws for eventual
17  * playback into a GrGpu. In theory one draw buffer could playback into another. When index or
18  * vertex buffers are used as geometry sources it is the callers the draw buffer only holds
19  * references to the buffers. It is the callers responsibility to ensure that the data is still
20  * valid when the draw buffer is played back into a GrGpu. Similarly, it is the caller's
21  * responsibility to ensure that all referenced textures, buffers, and render-targets are associated
22  * in the GrGpu object that the buffer is played back into. The buffer requires VB and IB pools to
23  * store geometry.
24  */
25 class GrInOrderDrawBuffer : public GrClipTarget {
26 public:
27 
28     /**
29      * Creates a GrInOrderDrawBuffer
30      *
31      * @param context    the context object that owns this draw buffer.
32      */
33     GrInOrderDrawBuffer(GrContext* context);
34 
35     ~GrInOrderDrawBuffer() override;
36 
37     // tracking for draws
getCurrentDrawToken()38     DrawToken getCurrentDrawToken() override { return DrawToken(this, fDrawID); }
39 
40     void clearStencilClip(const SkIRect& rect,
41                           bool insideClip,
42                           GrRenderTarget* renderTarget) override;
43 
44     void discard(GrRenderTarget*) override;
45 
46 protected:
appendIndicesAndTransforms(const void * indexValues,PathIndexType indexType,const float * transformValues,PathTransformType transformType,int count,char ** indicesLocation,float ** xformsLocation)47     void appendIndicesAndTransforms(const void* indexValues, PathIndexType indexType,
48                                     const float* transformValues, PathTransformType transformType,
49                                     int count, char** indicesLocation, float** xformsLocation) {
50         int indexBytes = GrPathRange::PathIndexSizeInBytes(indexType);
51         *indicesLocation = (char*) fPathIndexBuffer.alloc(count * indexBytes,
52                                                           SkChunkAlloc::kThrow_AllocFailType);
53         SkASSERT(SkIsAlign4((uintptr_t)*indicesLocation));
54         memcpy(*indicesLocation, reinterpret_cast<const char*>(indexValues), count * indexBytes);
55 
56         const int xformBytes = GrPathRendering::PathTransformSize(transformType) * sizeof(float);
57         *xformsLocation = NULL;
58 
59         if (0 != xformBytes) {
60             *xformsLocation = (float*) fPathTransformBuffer.alloc(count * xformBytes,
61                                                                SkChunkAlloc::kThrow_AllocFailType);
62             SkASSERT(SkIsAlign4((uintptr_t)*xformsLocation));
63             memcpy(*xformsLocation, transformValues, count * xformBytes);
64         }
65     }
66 
67 private:
68     friend class GrInOrderCommandBuilder;
69     friend class GrTargetCommands;
70 
71     typedef GrTargetCommands::State State;
72 
73     State* allocState(const GrPrimitiveProcessor* primProc = NULL) {
74         void* allocation = fPipelineBuffer.alloc(sizeof(State), SkChunkAlloc::kThrow_AllocFailType);
75         return SkNEW_PLACEMENT_ARGS(allocation, State, (primProc));
76     }
77 
unallocState(State * state)78     void unallocState(State* state) {
79         state->unref();
80         fPipelineBuffer.unalloc(state);
81     }
82 
83     void onReset() override;
84     void onFlush() override;
85 
86     // overrides from GrDrawTarget
87     void onDrawBatch(GrBatch*, const PipelineInfo&) override;
88     void onStencilPath(const GrPipelineBuilder&,
89                        const GrPathProcessor*,
90                        const GrPath*,
91                        const GrScissorState&,
92                        const GrStencilSettings&) override;
93     void onDrawPath(const GrPathProcessor*,
94                     const GrPath*,
95                     const GrStencilSettings&,
96                     const PipelineInfo&) override;
97     void onDrawPaths(const GrPathProcessor*,
98                      const GrPathRange*,
99                      const void* indices,
100                      PathIndexType,
101                      const float transformValues[],
102                      PathTransformType,
103                      int count,
104                      const GrStencilSettings&,
105                      const PipelineInfo&) override;
106     void onClear(const SkIRect* rect,
107                  GrColor color,
108                  bool canIgnoreRect,
109                  GrRenderTarget* renderTarget) override;
110     void onCopySurface(GrSurface* dst,
111                        GrSurface* src,
112                        const SkIRect& srcRect,
113                        const SkIPoint& dstPoint) override;
114 
115     // We lazily record clip changes in order to skip clips that have no effect.
116     void recordClipIfNecessary();
117     // Records any trace markers for a command
118     void recordTraceMarkersIfNecessary(GrTargetCommands::Cmd*);
getCmdString(int index)119     SkString getCmdString(int index) const {
120         SkASSERT(index < fGpuCmdMarkers.count());
121         return fGpuCmdMarkers[index].toString();
122     }
isIssued(uint32_t drawID)123     bool isIssued(uint32_t drawID) override { return drawID != fDrawID; }
124 
125     State* SK_WARN_UNUSED_RESULT setupPipelineAndShouldDraw(const GrPrimitiveProcessor*,
126                                                             const GrDrawTarget::PipelineInfo&);
127     State* SK_WARN_UNUSED_RESULT setupPipelineAndShouldDraw(GrBatch*,
128                                                             const GrDrawTarget::PipelineInfo&);
129 
130     // TODO: Use a single allocator for commands and records
131     enum {
132         kPathIdxBufferMinReserve     = 2 * 64,  // 64 uint16_t's
133         kPathXformBufferMinReserve   = 2 * 64,  // 64 two-float transforms
134         kPipelineBufferMinReserve    = 32 * sizeof(State),
135     };
136 
137     // every 100 flushes we should reset our fPipelineBuffer to prevent us from holding at a
138     // highwater mark
139     static const int kPipelineBufferHighWaterMark = 100;
140 
141     SkAutoTDelete<GrCommandBuilder>     fCommands;
142     SkTArray<GrTraceMarkerSet, false>   fGpuCmdMarkers;
143     SkChunkAlloc                        fPathIndexBuffer;
144     SkChunkAlloc                        fPathTransformBuffer;
145     SkChunkAlloc                        fPipelineBuffer;
146     uint32_t                            fDrawID;
147     SkAutoTUnref<State>                 fPrevState;
148 
149     typedef GrClipTarget INHERITED;
150 };
151 
152 #endif
153