void GrDrawTarget::drawPaths(GrDrawState* ds,
const GrPathRange* pathRange,
- const uint32_t indices[],
+ const void* indices,
+ PathIndexType indexType,
+ const float transformValues[],
+ PathTransformType transformType,
int count,
- const float transforms[],
- PathTransformType transformsType,
GrPathRendering::FillType fill) {
SkASSERT(this->caps()->pathRenderingSupport());
SkASSERT(pathRange);
SkASSERT(indices);
- SkASSERT(transforms);
+ SkASSERT(0 == reinterpret_cast<long>(indices) % GrPathRange::PathIndexSizeInBytes(indexType));
+ SkASSERT(transformValues);
SkASSERT(ds);
// Setup clip
return;
}
- this->onDrawPaths(*ds, pathRange, indices, count, transforms, transformsType, scissorState,
- stencilSettings, dstCopy.texture() ? &dstCopy : NULL);
+ this->onDrawPaths(*ds, pathRange, indices, indexType, transformValues, transformType, count,
+ scissorState, stencilSettings, dstCopy.texture() ? &dstCopy : NULL);
}
void GrDrawTarget::clear(const SkIRect* rect,
public:
SK_DECLARE_INST_COUNT(GrDrawTarget)
- typedef GrPathRendering::PathTransformType PathTransformType ;
+ typedef GrPathRange::PathIndexType PathIndexType;
+ typedef GrPathRendering::PathTransformType PathTransformType;
///////////////////////////////////////////////////////////////////////////
void drawPath(GrDrawState*, const GrPath*, GrPathRendering::FillType fill);
/**
- * Draws many paths. It will respect the HW
- * antialias flag on the draw state (if possible in the 3D API).
+ * Draws the aggregate path from combining multiple. Note that this will not
+ * always be equivalent to back-to-back calls to drawPath(). It will respect
+ * the HW antialias flag on the draw state (if possible in the 3D API).
*
- * @param pathRange Source of paths to draw from
- * @param indices Array of indices into the the pathRange
- * @param count Number of paths to draw (length of indices array)
- * @param transforms Array of individual transforms, one for each path
- * @param transformsType Type of transformations in the array. Array contains
- PathTransformSize(transformsType) * count elements
+ * @param pathRange Source paths to draw from
+ * @param indices Array of path indices to draw
+ * @param indexType Data type of the array elements in indexBuffer
+ * @param transformValues Array of transforms for the individual paths
+ * @param transformType Type of transforms in transformBuffer
+ * @param count Number of paths to draw
* @param fill Fill type for drawing all the paths
*/
void drawPaths(GrDrawState*, const GrPathRange* pathRange,
- const uint32_t indices[],
+ const void* indices,
+ PathIndexType indexType,
+ const float transformValues[],
+ PathTransformType transformType,
int count,
- const float transforms[],
- PathTransformType transformsType,
GrPathRendering::FillType fill);
/**
const GrDeviceCoordTexture* dstCopy) = 0;
virtual void onDrawPaths(const GrDrawState&,
const GrPathRange*,
- const uint32_t indices[],
- int count,
- const float transforms[],
+ const void* indices,
+ PathIndexType,
+ const float transformValues[],
PathTransformType,
+ int count,
const GrClipMaskManager::ScissorState&,
const GrStencilSettings&,
const GrDeviceCoordTexture*) = 0;
void GrGpu::drawPaths(const GrOptDrawState& ds,
const GrPathRange* pathRange,
- const uint32_t indices[],
+ const void* indices,
+ GrDrawTarget::PathIndexType indexType,
+ const float transformValues[],
+ GrDrawTarget::PathTransformType transformType,
int count,
- const float transforms[],
- GrDrawTarget::PathTransformType transformsType,
const GrStencilSettings& stencilSettings) {
this->handleDirtyContext();
return;
}
- pathRange->willDrawPaths(indices, count);
- this->pathRendering()->drawPaths(pathRange, indices, count, transforms, transformsType,
- stencilSettings);
+ pathRange->willDrawPaths(indices, indexType, count);
+ this->pathRendering()->drawPaths(pathRange, indices, indexType, transformValues,
+ transformType, count, stencilSettings);
}
const GrStencilSettings&);
virtual void drawPaths(const GrOptDrawState&,
const GrPathRange*,
- const uint32_t indices[],
- int count,
- const float transforms[],
+ const void* indices,
+ GrDrawTarget::PathIndexType,
+ const float transformValues[],
GrDrawTarget::PathTransformType,
+ int count,
const GrStencilSettings&);
static DrawType PrimTypeToDrawType(GrPrimitiveType type) {
void GrInOrderDrawBuffer::onDrawPaths(const GrDrawState& ds,
const GrPathRange* pathRange,
- const uint32_t indices[],
+ const void* indices,
+ PathIndexType indexType,
+ const float transformValues[],
+ PathTransformType transformType,
int count,
- const float transforms[],
- PathTransformType transformsType,
const GrClipMaskManager::ScissorState& scissorState,
const GrStencilSettings& stencilSettings,
const GrDeviceCoordTexture* dstCopy) {
SkASSERT(pathRange);
SkASSERT(indices);
- SkASSERT(transforms);
+ SkASSERT(transformValues);
if (!this->recordStateAndShouldDraw(ds, GrGpu::kDrawPath_DrawType, scissorState, dstCopy)) {
return;
}
- uint32_t* savedIndices = fPathIndexBuffer.append(count, indices);
- float* savedTransforms = fPathTransformBuffer.append(count *
- GrPathRendering::PathTransformSize(transformsType), transforms);
+ int indexBytes = GrPathRange::PathIndexSizeInBytes(indexType);
+ if (int misalign = fPathIndexBuffer.count() % indexBytes) {
+ // Add padding to the index buffer so the indices are aligned properly.
+ fPathIndexBuffer.append(indexBytes - misalign);
+ }
+
+ char* savedIndices = fPathIndexBuffer.append(count * indexBytes,
+ reinterpret_cast<const char*>(indices));
+ float* savedTransforms = fPathTransformBuffer.append(
+ count * GrPathRendering::PathTransformSize(transformType),
+ transformValues);
if (kDrawPaths_Cmd == strip_trace_bit(fCmdBuffer.back().fType)) {
// The previous command was also DrawPaths. Try to collapse this call into the one
// font tend to all wind in the same direction.
DrawPaths* previous = static_cast<DrawPaths*>(&fCmdBuffer.back());
if (pathRange == previous->pathRange() &&
- transformsType == previous->fTransformsType &&
+ indexType == previous->fIndexType &&
+ transformType == previous->fTransformType &&
stencilSettings == previous->fStencilSettings &&
path_fill_type_is_winding(stencilSettings) &&
!ds.willBlendWithDst()) {
DrawPaths* dp = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, DrawPaths, (pathRange));
dp->fIndicesLocation = savedIndices - fPathIndexBuffer.begin();
- dp->fCount = count;
+ dp->fIndexType = indexType;
dp->fTransformsLocation = savedTransforms - fPathTransformBuffer.begin();
- dp->fTransformsType = transformsType;
+ dp->fTransformType = transformType;
+ dp->fCount = count;
dp->fStencilSettings = stencilSettings;
this->recordTraceMarkersIfNecessary();
const GrOptDrawState* optState) {
SkASSERT(optState);
buf->fDstGpu->drawPaths(*optState, this->pathRange(),
- &buf->fPathIndexBuffer[fIndicesLocation], fCount,
- &buf->fPathTransformBuffer[fTransformsLocation], fTransformsType,
- fStencilSettings);
+ &buf->fPathIndexBuffer[fIndicesLocation], fIndexType,
+ &buf->fPathTransformBuffer[fTransformsLocation], fTransformType,
+ fCount, fStencilSettings);
}
void GrInOrderDrawBuffer::SetState::execute(GrInOrderDrawBuffer*, const GrOptDrawState*) {}
void execute(GrInOrderDrawBuffer*, const GrOptDrawState*) SK_OVERRIDE;
int fIndicesLocation;
- size_t fCount;
+ PathIndexType fIndexType;
int fTransformsLocation;
- PathTransformType fTransformsType;
+ PathTransformType fTransformType;
+ int fCount;
GrStencilSettings fStencilSettings;
private:
const GrDeviceCoordTexture* dstCopy) SK_OVERRIDE;
void onDrawPaths(const GrDrawState&,
const GrPathRange*,
- const uint32_t indices[],
- int count,
- const float transforms[],
+ const void* indices,
+ PathIndexType,
+ const float transformValues[],
PathTransformType,
+ int count,
const ScissorState&,
const GrStencilSettings&,
const GrDeviceCoordTexture*) SK_OVERRIDE;
// TODO: Use a single allocator for commands and records
enum {
kCmdBufferInitialSizeInBytes = 8 * 1024,
- kPathIdxBufferMinReserve = 64,
- kPathXformBufferMinReserve = 2 * kPathIdxBufferMinReserve,
+ kPathIdxBufferMinReserve = 2 * 64, // 64 uint16_t's
+ kPathXformBufferMinReserve = 2 * 64, // 64 two-float transforms
kGeoPoolStatePreAllocCnt = 4,
};
GrGpu* fDstGpu;
GrVertexBufferAllocPool& fVertexPool;
GrIndexBufferAllocPool& fIndexPool;
- SkTDArray<uint32_t> fPathIndexBuffer;
+ SkTDArray<char> fPathIndexBuffer;
SkTDArray<float> fPathTransformBuffer;
GeoPoolStateStack fGeoPoolStateStack;
bool fFlushing;
fStroke(stroke) {
}
-void GrPathRange::willDrawPaths(const uint32_t indices[], int count) const {
- if (NULL == fPathGenerator.get()) {
+void GrPathRange::willDrawPaths(const void* indices, PathIndexType indexType, int count) const {
+ if (!fPathGenerator) {
return;
}
+ switch (indexType) {
+ case kU8_PathIndexType: return this->willDrawPaths<uint8_t>(indices, count);
+ case kU16_PathIndexType: return this->willDrawPaths<uint16_t>(indices, count);
+ case kU32_PathIndexType: return this->willDrawPaths<uint32_t>(indices, count);
+ default: SkFAIL("Unknown path index type");
+ }
+}
+
+template<typename IndexType> void GrPathRange::willDrawPaths(const void* indices, int count) const {
+ SkASSERT(fPathGenerator);
+
+ const IndexType* indexArray = reinterpret_cast<const IndexType*>(indices);
bool didLoadPaths = false;
for (int i = 0; i < count; ++i) {
- SkASSERT(indices[i] < static_cast<uint32_t>(fNumPaths));
+ SkASSERT(indexArray[i] < static_cast<uint32_t>(fNumPaths));
- const int groupIndex = indices[i] / kPathsPerGroup;
+ const int groupIndex = indexArray[i] / kPathsPerGroup;
const int groupByte = groupIndex / 8;
const uint8_t groupBit = 1 << (groupIndex % 8);
return type;
}
+ enum PathIndexType {
+ kU8_PathIndexType, //!< uint8_t
+ kU16_PathIndexType, //!< uint16_t
+ kU32_PathIndexType, //!< uint32_t
+
+ kLast_PathIndexType = kU32_PathIndexType
+ };
+
+ static inline int PathIndexSizeInBytes(PathIndexType type) {
+ GR_STATIC_ASSERT(0 == kU8_PathIndexType);
+ GR_STATIC_ASSERT(1 == kU16_PathIndexType);
+ GR_STATIC_ASSERT(2 == kU32_PathIndexType);
+ GR_STATIC_ASSERT(kU32_PathIndexType == kLast_PathIndexType);
+
+ return 1 << type;
+ }
+
/**
- * Class that generates the paths for a specific range.
+ * Class that generates the paths for a specific range.
*/
class PathGenerator : public SkRefCnt {
public:
private:
// Notify when paths will be drawn in case this is a lazy-loaded path range.
friend class GrGpu;
- void willDrawPaths(const uint32_t indices[], int count) const;
+ void willDrawPaths(const void* indices, PathIndexType, int count) const;
+ template<typename IndexType> void willDrawPaths(const void* indices, int count) const;
mutable SkAutoTUnref<PathGenerator> fPathGenerator;
mutable SkTArray<uint8_t, true /*MEM_COPY*/> fGeneratedPaths;
public:
virtual ~GrPathRendering() { }
- // No native support for inverse at this time
- enum FillType {
- /** Specifies that "inside" is computed by a non-zero sum of signed
- edge crossings
- */
- kWinding_FillType,
- /** Specifies that "inside" is computed by an odd number of edge
- crossings
- */
- kEvenOdd_FillType,
- };
+ typedef GrPathRange::PathIndexType PathIndexType;
enum PathTransformType {
kNone_PathTransformType, //!< []
}
}
+ // No native support for inverse at this time
+ enum FillType {
+ /** Specifies that "inside" is computed by a non-zero sum of signed
+ edge crossings
+ */
+ kWinding_FillType,
+ /** Specifies that "inside" is computed by an odd number of edge
+ crossings
+ */
+ kEvenOdd_FillType,
+ };
+
/**
* Creates a new gpu path, based on the specified path and stroke and returns it.
* The caller owns a ref on the returned path which must be balanced by a call to unref.
virtual void stencilPath(const GrPath*, const GrStencilSettings&) = 0;
virtual void drawPath(const GrPath*, const GrStencilSettings&) = 0;
- virtual void drawPaths(const GrPathRange*, const uint32_t indices[], int count,
- const float transforms[], PathTransformType,
+ virtual void drawPaths(const GrPathRange*, const void* indices, PathIndexType,
+ const float transformValues[], PathTransformType, int count,
const GrStencilSettings&) = 0;
protected:
GrPathRendering() { }
return;
}
- fDrawTarget->drawPaths(&fDrawState, fGlyphs, fIndexBuffer, fPendingGlyphCount, fTransformBuffer,
- GrPathRendering::kTranslate_PathTransformType,
- GrPathRendering::kWinding_FillType);
+ fDrawTarget->drawPaths(&fDrawState, fGlyphs, fIndexBuffer, GrPathRange::kU16_PathIndexType,
+ fTransformBuffer, GrPathRendering::kTranslate_PathTransformType,
+ fPendingGlyphCount, GrPathRendering::kWinding_FillType);
fPendingGlyphCount = 0;
}
float fTextInverseRatio;
SkGlyphCache* fGlyphCache;
GrPathRange* fGlyphs;
- uint32_t fIndexBuffer[kGlyphBufferSize];
+ uint16_t fIndexBuffer[kGlyphBufferSize];
float fTransformBuffer[2 * kGlyphBufferSize];
int fPendingGlyphCount;
SkMatrix fContextInitialMatrix;
#define GL_CALL_RET(RET, X) GR_GL_CALL_RET(fGpu->glInterface(), RET, X)
+static const GrGLenum gIndexType2GLType[] = {
+ GR_GL_UNSIGNED_BYTE,
+ GR_GL_UNSIGNED_SHORT,
+ GR_GL_UNSIGNED_INT
+};
+
+GR_STATIC_ASSERT(0 == GrPathRange::kU8_PathIndexType);
+GR_STATIC_ASSERT(1 == GrPathRange::kU16_PathIndexType);
+GR_STATIC_ASSERT(2 == GrPathRange::kU32_PathIndexType);
+GR_STATIC_ASSERT(GrPathRange::kU32_PathIndexType == GrPathRange::kLast_PathIndexType);
+
static const GrGLenum gXformType2GLType[] = {
GR_GL_NONE,
GR_GL_TRANSLATE_X,
}
}
-void GrGLPathRendering::drawPaths(const GrPathRange* pathRange, const uint32_t indices[], int count,
- const float transforms[], PathTransformType transformsType,
- const GrStencilSettings& stencilSettings) {
+void GrGLPathRendering::drawPaths(const GrPathRange* pathRange,
+ const void* indices, PathIndexType indexType,
+ const float transformValues[], PathTransformType transformType,
+ int count, const GrStencilSettings& stencilSettings) {
SkASSERT(fGpu->caps()->pathRenderingSupport());
GrGLuint baseID = static_cast<const GrGLPathRange*>(pathRange)->basePathID();
if (stroke.needToApply()) {
if (SkStrokeRec::kStrokeAndFill_Style == stroke.getStyle()) {
GL_CALL(StencilFillPathInstanced(
- count, GR_GL_UNSIGNED_INT, indices, baseID, fillMode,
- writeMask, gXformType2GLType[transformsType],
- transforms));
+ count, gIndexType2GLType[indexType], indices, baseID, fillMode,
+ writeMask, gXformType2GLType[transformType], transformValues));
}
this->stencilThenCoverStrokePathInstanced(
- count, GR_GL_UNSIGNED_INT, indices, baseID, 0xffff, writeMask,
- GR_GL_BOUNDING_BOX_OF_BOUNDING_BOXES,
- gXformType2GLType[transformsType], transforms);
+ count, gIndexType2GLType[indexType], indices, baseID,
+ 0xffff, writeMask, GR_GL_BOUNDING_BOX_OF_BOUNDING_BOXES,
+ gXformType2GLType[transformType], transformValues);
} else {
this->stencilThenCoverFillPathInstanced(
- count, GR_GL_UNSIGNED_INT, indices, baseID, fillMode, writeMask,
- GR_GL_BOUNDING_BOX_OF_BOUNDING_BOXES,
- gXformType2GLType[transformsType], transforms);
+ count, gIndexType2GLType[indexType], indices, baseID,
+ fillMode, writeMask, GR_GL_BOUNDING_BOX_OF_BOUNDING_BOXES,
+ gXformType2GLType[transformType], transformValues);
}
}
const SkStrokeRec&) SK_OVERRIDE;
virtual void stencilPath(const GrPath*, const GrStencilSettings&) SK_OVERRIDE;
virtual void drawPath(const GrPath*, const GrStencilSettings&) SK_OVERRIDE;
- virtual void drawPaths(const GrPathRange*, const uint32_t indices[], int count,
- const float transforms[], PathTransformType,
+ virtual void drawPaths(const GrPathRange*, const void* indices, PathIndexType,
+ const float transformValues[], PathTransformType, int count,
const GrStencilSettings&) SK_OVERRIDE;
/* Called when the 3D context state is unknown. */