blob: ac1b79cd55f02c59eb3d011a2db8866d2940a7f0 [file] [log] [blame]
/*
* 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 "GrFlushToGpuDrawTarget.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 GrFlushToGpuDrawTarget {
public:
/**
* Creates a GrInOrderDrawBuffer
*
* @param gpu the gpu object that this draw buffer flushes to.
* @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(GrGpu* gpu,
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 willReserveVertexAndIndexSpace(int vertexCount,
size_t vertexStride,
int indexCount) override;
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);
}
}
bool canConcatToIndexBuffer(const GrIndexBuffer** ib) {
const GrDrawTarget::GeometrySrcState& geomSrc = this->getGeomSrc();
// we only attempt to concat when reserved verts are used with a client-specified
// index buffer. To make this work with client-specified VBs we'd need to know if the VB
// was updated between draws.
if (kReserved_GeometrySrcType != geomSrc.fVertexSrc ||
kBuffer_GeometrySrcType != geomSrc.fIndexSrc) {
return false;
}
*ib = geomSrc.fIndexBuffer;
return true;
}
private:
friend class GrTargetCommands;
void onReset() override;
void onFlush() override;
// overrides from GrDrawTarget
void onDraw(const GrGeometryProcessor*, const DrawInfo&, const PipelineInfo&) override;
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;
bool onCopySurface(GrSurface* dst,
GrSurface* src,
const SkIRect& srcRect,
const SkIPoint& dstPoint) override;
// Attempts to concat instances from info onto the previous draw. info must represent an
// instanced draw. The caller must have already recorded a new draw state and clip if necessary.
int concatInstancedDraw(const DrawInfo&);
// 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 GrFlushToGpuDrawTarget INHERITED;
};
#endif