| /* |
| * 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 GrBufferedDrawTarget_DEFINED |
| #define GrBufferedDrawTarget_DEFINED |
| |
| #include "GrDrawTarget.h" |
| #include "GrCommandBuilder.h" |
| #include "SkChunkAlloc.h" |
| |
| /** |
| * GrBufferedDrawTarget is an implementation of GrDrawTarget that queues up draws for eventual |
| * playback into a GrGpu. In theory one draw buffer could playback into another. 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. |
| */ |
| class GrBufferedDrawTarget : public GrClipTarget { |
| public: |
| |
| /** |
| * Creates a GrBufferedDrawTarget |
| * |
| * @param context the context object that owns this draw buffer. |
| */ |
| GrBufferedDrawTarget(GrContext* context); |
| |
| ~GrBufferedDrawTarget() override; |
| |
| 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 GrInOrderCommandBuilder; |
| friend class GrTargetCommands; |
| |
| typedef GrTargetCommands::StateForPathDraw StateForPathDraw; |
| |
| StateForPathDraw* allocState(const GrPrimitiveProcessor* primProc = NULL) { |
| void* allocation = fPipelineBuffer.alloc(sizeof(StateForPathDraw), |
| SkChunkAlloc::kThrow_AllocFailType); |
| return SkNEW_PLACEMENT_ARGS(allocation, StateForPathDraw, (primProc)); |
| } |
| |
| void unallocState(StateForPathDraw* state) { |
| state->unref(); |
| fPipelineBuffer.unalloc(state); |
| } |
| |
| void onReset() override; |
| void onFlush() override; |
| |
| // overrides from GrDrawTarget |
| void onDrawBatch(GrBatch*) 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, |
| GrRenderTarget* renderTarget) override; |
| void onCopySurface(GrSurface* dst, |
| GrSurface* src, |
| const SkIRect& srcRect, |
| const SkIPoint& dstPoint) override; |
| |
| // 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; } |
| |
| StateForPathDraw* SK_WARN_UNUSED_RESULT createStateForPathDraw( |
| const GrPrimitiveProcessor*, |
| const GrDrawTarget::PipelineInfo&, |
| GrPipelineOptimizations* opts); |
| |
| // TODO: Use a single allocator for commands and records |
| enum { |
| kPathIdxBufferMinReserve = 2 * 64, // 64 uint16_t's |
| kPathXformBufferMinReserve = 2 * 64, // 64 two-float transforms |
| kPipelineBufferMinReserve = 32 * sizeof(StateForPathDraw), |
| }; |
| |
| // every 100 flushes we should reset our fPipelineBuffer to prevent us from holding at a |
| // highwater mark |
| static const int kPipelineBufferHighWaterMark = 100; |
| |
| SkAutoTDelete<GrCommandBuilder> fCommands; |
| SkTArray<GrTraceMarkerSet, false> fGpuCmdMarkers; |
| SkChunkAlloc fPathIndexBuffer; |
| SkChunkAlloc fPathTransformBuffer; |
| SkChunkAlloc fPipelineBuffer; |
| uint32_t fDrawID; |
| SkAutoTUnref<StateForPathDraw> fPrevState; |
| |
| typedef GrClipTarget INHERITED; |
| }; |
| |
| #endif |