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