Add IndexType parameter to GrDrawTarget::drawPaths

Allows the caller to decide whether they sent 8, 16, or 32 bit path
indices.

BUG=skia:

Review URL: https://codereview.chromium.org/746253003
This commit is contained in:
cdalton 2014-11-25 11:00:56 -08:00 committed by Commit bot
parent b116619028
commit 55b24afc17
13 changed files with 152 additions and 88 deletions

View File

@ -617,15 +617,17 @@ void GrDrawTarget::drawPath(GrDrawState* ds,
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
@ -652,8 +654,8 @@ void GrDrawTarget::drawPaths(GrDrawState* ds,
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,

View File

@ -35,7 +35,8 @@ class GrDrawTarget : public SkRefCnt {
public:
SK_DECLARE_INST_COUNT(GrDrawTarget)
typedef GrPathRendering::PathTransformType PathTransformType ;
typedef GrPathRange::PathIndexType PathIndexType;
typedef GrPathRendering::PathTransformType PathTransformType;
///////////////////////////////////////////////////////////////////////////
@ -279,22 +280,24 @@ public:
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);
/**
@ -704,10 +707,11 @@ private:
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;

View File

@ -317,10 +317,11 @@ void GrGpu::drawPath(const GrOptDrawState& ds,
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();
@ -328,7 +329,7 @@ void GrGpu::drawPaths(const GrOptDrawState& ds,
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);
}

View File

@ -365,10 +365,11 @@ public:
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) {

View File

@ -324,24 +324,33 @@ void GrInOrderDrawBuffer::onDrawPath(const GrDrawState& ds,
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
@ -353,7 +362,8 @@ void GrInOrderDrawBuffer::onDrawPaths(const GrDrawState& ds,
// 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()) {
@ -365,9 +375,10 @@ void GrInOrderDrawBuffer::onDrawPaths(const GrDrawState& ds,
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();
@ -522,9 +533,9 @@ void GrInOrderDrawBuffer::DrawPaths::execute(GrInOrderDrawBuffer* buf,
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*) {}

View File

@ -157,9 +157,10 @@ private:
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:
@ -249,10 +250,11 @@ 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;
@ -293,8 +295,8 @@ private:
// 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,
};
@ -318,7 +320,7 @@ private:
GrGpu* fDstGpu;
GrVertexBufferAllocPool& fVertexPool;
GrIndexBufferAllocPool& fIndexPool;
SkTDArray<uint32_t> fPathIndexBuffer;
SkTDArray<char> fPathIndexBuffer;
SkTDArray<float> fPathTransformBuffer;
GeoPoolStateStack fGeoPoolStateStack;
bool fFlushing;

View File

@ -32,17 +32,29 @@ GrPathRange::GrPathRange(GrGpu* gpu,
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);

View File

@ -36,6 +36,23 @@ public:
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.
*/
@ -76,7 +93,8 @@ protected:
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;

View File

@ -34,17 +34,7 @@ class GrPathRendering {
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, //!< []
@ -74,6 +64,18 @@ public:
}
}
// 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.
@ -126,8 +128,8 @@ public:
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() { }

View File

@ -367,9 +367,9 @@ void GrStencilAndCoverTextContext::flush() {
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;
}

View File

@ -57,7 +57,7 @@ private:
float fTextInverseRatio;
SkGlyphCache* fGlyphCache;
GrPathRange* fGlyphs;
uint32_t fIndexBuffer[kGlyphBufferSize];
uint16_t fIndexBuffer[kGlyphBufferSize];
float fTransformBuffer[2 * kGlyphBufferSize];
int fPendingGlyphCount;
SkMatrix fContextInitialMatrix;

View File

@ -21,6 +21,17 @@
#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,
@ -194,9 +205,10 @@ void GrGLPathRendering::drawPath(const GrPath* path, const GrStencilSettings& st
}
}
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();
@ -215,19 +227,18 @@ void GrGLPathRendering::drawPaths(const GrPathRange* pathRange, const uint32_t i
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);
}
}

View File

@ -41,8 +41,8 @@ public:
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. */