|  | /* | 
|  | * Copyright 2011 Google Inc. | 
|  | * | 
|  | * Use of this source code is governed by a BSD-style license that can be | 
|  | * found in the LICENSE file. | 
|  | */ | 
|  |  | 
|  | #ifndef GrInOrderDrawBuffer_DEFINED | 
|  | #define GrInOrderDrawBuffer_DEFINED | 
|  |  | 
|  | #include "GrDrawTarget.h" | 
|  | #include "GrTargetCommands.h" | 
|  | #include "SkChunkAlloc.h" | 
|  |  | 
|  | /** | 
|  | * GrInOrderDrawBuffer is an implementation of GrDrawTarget that queues up draws for eventual | 
|  | * playback into a GrGpu. In theory one draw buffer could playback into another. When index or | 
|  | * vertex buffers are used as geometry sources it is the callers the draw buffer only holds | 
|  | * references to the buffers. It is the callers responsibility to ensure that the data is still | 
|  | * valid when the draw buffer is played back into a GrGpu. Similarly, it is the caller's | 
|  | * responsibility to ensure that all referenced textures, buffers, and render-targets are associated | 
|  | * in the GrGpu object that the buffer is played back into. The buffer requires VB and IB pools to | 
|  | * store geometry. | 
|  | */ | 
|  | class GrInOrderDrawBuffer : public GrClipTarget { | 
|  | public: | 
|  |  | 
|  | /** | 
|  | * Creates a GrInOrderDrawBuffer | 
|  | * | 
|  | * @param context    the context object that owns this draw buffer. | 
|  | * @param vertexPool pool where vertices for queued draws will be saved when | 
|  | *                   the vertex source is either reserved or array. | 
|  | * @param indexPool  pool where indices for queued draws will be saved when | 
|  | *                   the index source is either reserved or array. | 
|  | */ | 
|  | GrInOrderDrawBuffer(GrContext* context, | 
|  | GrVertexBufferAllocPool* vertexPool, | 
|  | GrIndexBufferAllocPool* indexPool); | 
|  |  | 
|  | ~GrInOrderDrawBuffer() override; | 
|  |  | 
|  | // tracking for draws | 
|  | DrawToken getCurrentDrawToken() override { return DrawToken(this, fDrawID); } | 
|  |  | 
|  | void clearStencilClip(const SkIRect& rect, | 
|  | bool insideClip, | 
|  | GrRenderTarget* renderTarget) override; | 
|  |  | 
|  | void discard(GrRenderTarget*) override; | 
|  |  | 
|  | protected: | 
|  | void appendIndicesAndTransforms(const void* indexValues, PathIndexType indexType, | 
|  | const float* transformValues, PathTransformType transformType, | 
|  | int count, char** indicesLocation, float** xformsLocation) { | 
|  | int indexBytes = GrPathRange::PathIndexSizeInBytes(indexType); | 
|  | *indicesLocation = (char*) fPathIndexBuffer.alloc(count * indexBytes, | 
|  | SkChunkAlloc::kThrow_AllocFailType); | 
|  | SkASSERT(SkIsAlign4((uintptr_t)*indicesLocation)); | 
|  | memcpy(*indicesLocation, reinterpret_cast<const char*>(indexValues), count * indexBytes); | 
|  |  | 
|  | const int xformBytes = GrPathRendering::PathTransformSize(transformType) * sizeof(float); | 
|  | *xformsLocation = NULL; | 
|  |  | 
|  | if (0 != xformBytes) { | 
|  | *xformsLocation = (float*) fPathTransformBuffer.alloc(count * xformBytes, | 
|  | SkChunkAlloc::kThrow_AllocFailType); | 
|  | SkASSERT(SkIsAlign4((uintptr_t)*xformsLocation)); | 
|  | memcpy(*xformsLocation, transformValues, count * xformBytes); | 
|  | } | 
|  | } | 
|  |  | 
|  | private: | 
|  | friend class GrTargetCommands; | 
|  |  | 
|  | void onReset() override; | 
|  | void onFlush() override; | 
|  |  | 
|  | // overrides from GrDrawTarget | 
|  | void onDrawBatch(GrBatch*, const PipelineInfo&) override; | 
|  | void onDrawRect(GrPipelineBuilder*, | 
|  | GrColor, | 
|  | const SkMatrix& viewMatrix, | 
|  | const SkRect& rect, | 
|  | const SkRect* localRect, | 
|  | const SkMatrix* localMatrix) override; | 
|  |  | 
|  | void onStencilPath(const GrPipelineBuilder&, | 
|  | const GrPathProcessor*, | 
|  | const GrPath*, | 
|  | const GrScissorState&, | 
|  | const GrStencilSettings&) override; | 
|  | void onDrawPath(const GrPathProcessor*, | 
|  | const GrPath*, | 
|  | const GrStencilSettings&, | 
|  | const PipelineInfo&) override; | 
|  | void onDrawPaths(const GrPathProcessor*, | 
|  | const GrPathRange*, | 
|  | const void* indices, | 
|  | PathIndexType, | 
|  | const float transformValues[], | 
|  | PathTransformType, | 
|  | int count, | 
|  | const GrStencilSettings&, | 
|  | const PipelineInfo&) override; | 
|  | void onClear(const SkIRect* rect, | 
|  | GrColor color, | 
|  | bool canIgnoreRect, | 
|  | GrRenderTarget* renderTarget) override; | 
|  | void onCopySurface(GrSurface* dst, | 
|  | GrSurface* src, | 
|  | const SkIRect& srcRect, | 
|  | const SkIPoint& dstPoint) override; | 
|  |  | 
|  | // We lazily record clip changes in order to skip clips that have no effect. | 
|  | void recordClipIfNecessary(); | 
|  | // Records any trace markers for a command | 
|  | void recordTraceMarkersIfNecessary(GrTargetCommands::Cmd*); | 
|  | SkString getCmdString(int index) const { | 
|  | SkASSERT(index < fGpuCmdMarkers.count()); | 
|  | return fGpuCmdMarkers[index].toString(); | 
|  | } | 
|  | bool isIssued(uint32_t drawID) override { return drawID != fDrawID; } | 
|  |  | 
|  | // TODO: Use a single allocator for commands and records | 
|  | enum { | 
|  | kPathIdxBufferMinReserve     = 2 * 64,  // 64 uint16_t's | 
|  | kPathXformBufferMinReserve   = 2 * 64,  // 64 two-float transforms | 
|  | }; | 
|  |  | 
|  | GrTargetCommands                    fCommands; | 
|  | SkTArray<GrTraceMarkerSet, false>   fGpuCmdMarkers; | 
|  | SkChunkAlloc                        fPathIndexBuffer; | 
|  | SkChunkAlloc                        fPathTransformBuffer; | 
|  | uint32_t                            fDrawID; | 
|  |  | 
|  | typedef GrClipTarget INHERITED; | 
|  | }; | 
|  |  | 
|  | #endif |