// only have to functions necessary for clients.
friend class GrAtlas;
- // computes vertex layout bits based on the paint. If paint expresses
- // a texture for a stage, the stage coords will be bound to postitions
- // unless hasTexCoords[s]==true in which case stage s's input coords
- // are bound to tex coord index s. hasTexCoords == NULL is a shortcut
- // for an array where all the values are false.
- static int PaintStageVertexLayoutBits(
- const GrPaint& paint,
- const bool hasTexCoords[GrPaint::kTotalStages]);
-
// Needed so GrTexture's returnToCache helper function can call
// addExistingTextureToCache
friend class GrTexture;
(NULL != fMaskSamplers[i].getCustomStage());
}
- // pre-concats sampler matrices for non-NULL textures and masks
- void preConcatActiveSamplerMatrices(const GrMatrix& matrix) {
+ bool hasMask() const {
+ for (int i = 0; i < kMaxMasks; ++i) {
+ if (this->isMaskStageEnabled(i)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ bool hasTexture() const {
for (int i = 0; i < kMaxTextures; ++i) {
- fTextureSamplers[i].preConcatMatrix(matrix);
+ if (this->isTextureStageEnabled(i)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ bool hasTextureOrMask() const { return this->hasTexture() || this->hasMask(); }
+
+ /**
+ * Preconcats the matrix of all samplers in the mask with the inverse of a
+ * matrix. If the matrix inverse cannot be computed (and there is at least
+ * one enabled stage) then false is returned.
+ */
+ bool preConcatSamplerMatricesWithInverse(const GrMatrix& matrix) {
+ GrMatrix inv;
+ bool computed = false;
+ for (int i = 0; i < kMaxTextures; ++i) {
+ if (this->isTextureStageEnabled(i)) {
+ if (!computed && !matrix.invert(&inv)) {
+ return false;
+ } else {
+ computed = true;
+ }
+ fTextureSamplers[i].preConcatMatrix(inv);
+ }
}
for (int i = 0; i < kMaxMasks; ++i) {
- fMaskSamplers[i].preConcatMatrix(matrix);
+ if (this->isMaskStageEnabled(i)) {
+ if (!computed && !matrix.invert(&inv)) {
+ return false;
+ } else {
+ computed = true;
+ }
+ fMaskSamplers[i].preConcatMatrix(inv);
+ }
}
+ return true;
}
// uninitialized
fColorMatrixEnabled = false;
}
- bool hasTexture() const {
- return 0 != this->getActiveTextureStageMask();
- }
-
- bool hasMask() const {
- return 0 != this->getActiveMaskStageMask();
- }
-
- bool hasTextureOrMask() const {
- return this->hasTexture() || this->hasMask();
- }
-
- // helpers for GrContext, GrTextContext
- int getActiveTextureStageMask() const {
- int mask = 0;
- for (int i = 0; i < kMaxTextures; ++i) {
- if ((NULL != fTextures[i]) ||
- (NULL != fTextureSamplers[i].getCustomStage())) {
- mask |= 1 << (i + kFirstTextureStage);
- }
- }
- return mask;
- }
-
- int getActiveMaskStageMask() const {
- int mask = 0;
- for (int i = 0; i < kMaxMasks; ++i) {
- if ((NULL != fMaskTextures[i]) ||
- (NULL != fMaskSamplers[i].getCustomStage())) {
- mask |= 1 << (i + kFirstMaskStage);
- }
- }
- return mask;
- }
-
- int getActiveStageMask() const {
- return this->getActiveTextureStageMask() |
- this->getActiveMaskStageMask();
- }
-
// internal use
// GrPaint's textures and masks map to the first N stages
// of GrDrawTarget in that order (textures followed by masks)
GrPathFill fill,
const GrVec* translate,
GrDrawTarget* target,
- GrDrawState::StageMask stageMask,
bool antiAlias) {
const SkPath* path = &origPath;
if (NULL != translate) {
vm.postTranslate(translate->fX, translate->fY);
}
- GrMatrix ivm;
- if (vm.invert(&ivm)) {
- drawState->preConcatSamplerMatrices(stageMask, ivm);
+ if (!drawState->preConcatSamplerMatricesWithInverse(vm)) {
+ return false;
}
drawState->viewMatrix()->reset();
GrPathFill fill,
const GrVec* translate,
GrDrawTarget* target,
- GrDrawState::StageMask stageMask,
bool antiAlias) SK_OVERRIDE;
};
const SkPath& path,
const GrVec* translate,
GrDrawTarget* target,
- GrDrawState::StageMask stageMask,
int* lineCnt,
int* quadCnt,
GrDrawTarget::AutoReleaseGeometry* arg) {
GrPathFill fill,
const GrVec* translate,
GrDrawTarget* target,
- GrDrawState::StageMask stageMask,
bool antiAlias) {
int lineCnt;
if (!this->createGeom(path,
translate,
target,
- stageMask,
&lineCnt,
&quadCnt,
&arg)) {
asr.set(target,
GrDrawTarget::kPreserve_ASRInit);
drawState = target->drawState();
- GrMatrix ivm;
- if (drawState->getViewInverse(&ivm)) {
- drawState->preConcatSamplerMatrices(stageMask, ivm);
+ if (!drawState->preConcatSamplerMatricesWithInverse(drawState->getViewMatrix())) {
+ return false;
}
drawState->viewMatrix()->reset();
}
GrPathFill fill,
const GrVec* translate,
GrDrawTarget* target,
- GrDrawState::StageMask stageMask,
bool antiAlias) SK_OVERRIDE;
private:
bool createGeom(const SkPath& path,
const GrVec* translate,
GrDrawTarget* target,
- GrDrawState::StageMask stageMask,
int* lineCnt,
int* quadCnt,
GrDrawTarget::AutoReleaseGeometry* arg);
// The ClipMaskManager accumulates the clip mask in the UL corner
GrIRect rect = GrIRect::MakeWH(resultBounds.width(), resultBounds.height());
- GrSWMaskHelper::DrawToTargetWithPathMask(texture, gpu, 0, rect);
+ GrSWMaskHelper::DrawToTargetWithPathMask(texture, gpu, rect);
GrAssert(!GrIsFillInverted(fill));
return true;
return draw_path_in_software(context, gpu, path, fill, doAA, resultBounds);
}
- pr->drawPath(path, fill, NULL, gpu, 0, doAA);
+ pr->drawPath(path, fill, NULL, gpu, doAA);
return true;
}
clipIn.getRect(index),
true);
} else {
- fGpu->drawSimpleRect(clipIn.getRect(index), NULL, 0);
+ fGpu->drawSimpleRect(clipIn.getRect(index), NULL);
}
} else {
return draw_path(this->getContext(), fGpu,
GrRect rect = GrRect::MakeWH(SkIntToScalar(target->width()),
SkIntToScalar(target->height()));
- fGpu->drawSimpleRect(rect, NULL, 1 << 0);
+ fGpu->drawSimpleRect(rect, NULL);
drawState->disableStage(0);
}
SET_RANDOM_COLOR
if (kRect_ClipType == clipCopy.getElementType(c)) {
*drawState->stencil() = gDrawToStencil;
- fGpu->drawSimpleRect(clipCopy.getRect(c), NULL, 0);
+ fGpu->drawSimpleRect(clipCopy.getRect(c), NULL);
} else {
if (canRenderDirectToStencil) {
*drawState->stencil() = gDrawToStencil;
- pr->drawPath(*clipPath, fill, NULL, fGpu, 0, false);
+ pr->drawPath(*clipPath, fill, NULL, fGpu, false);
} else {
pr->drawPathToStencil(*clipPath, fill, fGpu);
}
if (canDrawDirectToClip) {
if (kRect_ClipType == clipCopy.getElementType(c)) {
SET_RANDOM_COLOR
- fGpu->drawSimpleRect(clipCopy.getRect(c), NULL, 0);
+ fGpu->drawSimpleRect(clipCopy.getRect(c), NULL);
} else {
SET_RANDOM_COLOR
- pr->drawPath(*clipPath, fill, NULL, fGpu, 0, false);
+ pr->drawPath(*clipPath, fill, NULL, fGpu, false);
}
} else {
SET_RANDOM_COLOR
SkIntToScalar(bounds.fTop),
SkIntToScalar(bounds.fRight),
SkIntToScalar(bounds.fBottom));
- fGpu->drawSimpleRect(rect, NULL, 0);
+ fGpu->drawSimpleRect(rect, NULL);
}
}
}
////////////////////////////////////////////////////////////////////////////////
-int GrContext::PaintStageVertexLayoutBits(
- const GrPaint& paint,
- const bool hasTexCoords[GrPaint::kTotalStages]) {
- int stageMask = paint.getActiveStageMask();
- int layout = 0;
- for (int i = 0; i < GrPaint::kTotalStages; ++i) {
- if ((1 << i) & stageMask) {
- if (NULL != hasTexCoords && hasTexCoords[i]) {
- layout |= GrDrawTarget::StageTexCoordVertexLayoutBit(i, i);
- }
- }
- }
- return layout;
-}
-
-
-////////////////////////////////////////////////////////////////////////////////
-
GrTexture* GrContext::TextureCacheEntry::texture() const {
if (NULL == fEntry) {
return NULL;
SkAutoTUnref<GrCustomStage> morph(
SkNEW_ARGS(GrMorphologyEffect, (texture, direction, radius, morphType)));
drawState->sampler(0)->setCustomStage(morph);
- gpu->drawSimpleRect(rect, NULL, 1 << 0);
+ gpu->drawSimpleRect(rect, NULL);
}
void convolve_gaussian(GrGpu* gpu,
(texture, direction, radius,
sigma)));
drawState->sampler(0)->setCustomStage(conv);
- gpu->drawSimpleRect(rect, NULL, 1 << 0);
+ gpu->drawSimpleRect(rect, NULL);
}
}
// produce a correct result for some perspective matrices.
if (!this->getMatrix().hasPerspective()) {
if (!fDrawState->getViewInverse(&inverse)) {
- GrPrintf("Could not invert matrix");
+ GrPrintf("Could not invert matrix\n");
return;
}
inverse.mapRect(&r);
} else {
- if (paint.getActiveMaskStageMask() || paint.getActiveStageMask()) {
- if (!fDrawState->getViewInverse(&inverse)) {
- GrPrintf("Could not invert matrix");
- return;
- }
+ if (paint.hasTextureOrMask()) {
tmpPaint.set(paint);
- tmpPaint.get()->preConcatActiveSamplerMatrices(inverse);
p = tmpPaint.get();
+ if (!tmpPaint.get()->preConcatSamplerMatricesWithInverse(fDrawState->getViewMatrix())) {
+ GrPrintf("Could not invert matrix\n");
+ }
}
am.set(this, GrMatrix::I());
}
GrDrawTarget* target = this->prepareToDraw(paint, kUnbuffered_DrawCategory);
GrDrawState::AutoStageDisable atr(fDrawState);
- int stageMask = paint.getActiveStageMask();
GrRect devRect = rect;
GrMatrix combinedMatrix;
&useVertexCoverage);
if (doAA) {
- GrDrawTarget::AutoDeviceCoordDraw adcd(target, stageMask);
+ GrDrawTarget::AutoDeviceCoordDraw adcd(target);
+ if (!adcd.succeeded()) {
+ return;
+ }
if (width >= 0) {
GrVec strokeSize;;
if (width > 0) {
// TODO: consider making static vertex buffers for these cases.
// Hairline could be done by just adding closing vertex to
// unitSquareVertexBuffer()
- GrVertexLayout layout = PaintStageVertexLayoutBits(paint, NULL);
static const int worstCaseVertCount = 10;
- GrDrawTarget::AutoReleaseGeometry geo(target, layout, worstCaseVertCount, 0);
+ GrDrawTarget::AutoReleaseGeometry geo(target, 0, worstCaseVertCount, 0);
if (!geo.succeeded()) {
GrPrintf("Failed to get space for vertices!\n");
GrDrawState* drawState = target->drawState();
avmr.set(drawState);
drawState->preConcatViewMatrix(*matrix);
- drawState->preConcatSamplerMatrices(stageMask, *matrix);
+ drawState->preConcatSamplerMatrices(*matrix);
}
target->drawNonIndexed(primType, 0, vertCount);
} else {
#if GR_STATIC_RECT_VB
- GrVertexLayout layout = PaintStageVertexLayoutBits(paint, NULL);
const GrVertexBuffer* sqVB = fGpu->getUnitSquareVertexBuffer();
if (NULL == sqVB) {
GrPrintf("Failed to create static rect vb.\n");
return;
}
- target->setVertexSourceToBuffer(layout, sqVB);
+ target->setVertexSourceToBuffer(0, sqVB);
GrDrawState* drawState = target->drawState();
GrDrawState::AutoViewMatrixRestore avmr(drawState);
GrMatrix m;
m.postConcat(*matrix);
}
drawState->preConcatViewMatrix(m);
- drawState->preConcatSamplerMatrices(stageMask, m);
+ drawState->preConcatSamplerMatrices(m);
target->drawNonIndexed(kTriangleFan_GrPrimitiveType, 0, 4);
#else
- target->drawSimpleRect(rect, matrix, stageMask);
+ target->drawSimpleRect(rect, matrix);
#endif
}
}
GrDrawTarget* target = this->prepareToDraw(paint, kUnbuffered_DrawCategory);
GrDrawState::AutoStageDisable atr(fDrawState);
GrDrawState* drawState = target->drawState();
- GrVertexLayout layout = PaintStageVertexLayoutBits(paint, NULL);
GrDrawState::AutoViewMatrixRestore avmr(drawState);
GrMatrix m;
}
drawState->preConcatViewMatrix(m);
- // srcRect refers to first stage
- int otherStageMask = paint.getActiveStageMask() &
- (~(1 << GrPaint::kFirstTextureStage));
- if (otherStageMask) {
- drawState->preConcatSamplerMatrices(otherStageMask, m);
+ // we explicitly setup the correct coords for the first stage. The others
+ // must know about the view matrix change.
+ for (int s = 1; s < GrPaint::kTotalStages; ++s) {
+ if (drawState->isStageEnabled(s)) {
+ drawState->sampler(s)->preConcatMatrix(m);
+ }
}
m.setAll(srcRect.width(), 0, srcRect.fLeft,
GrPrintf("Failed to create static rect vb.\n");
return;
}
- target->setVertexSourceToBuffer(layout, sqVB);
+ target->setVertexSourceToBuffer(0, sqVB);
target->drawNonIndexed(kTriangleFan_GrPrimitiveType, 0, 4);
#else
srcRects[0] = &srcRect;
srcMatrices[0] = srcMatrix;
- target->drawRect(dstRect, dstMatrix, 1, srcRects, srcMatrices);
+ target->drawRect(dstRect, dstMatrix, srcRects, srcMatrices);
#endif
}
GrDrawTarget* target = this->prepareToDraw(paint, kUnbuffered_DrawCategory);
GrDrawState::AutoStageDisable atr(fDrawState);
- bool hasTexCoords[GrPaint::kTotalStages] = {
- NULL != texCoords, // texCoordSrc provides explicit stage 0 coords
- 0 // remaining stages use positions
- };
-
- GrVertexLayout layout = PaintStageVertexLayoutBits(paint, hasTexCoords);
-
+ GrVertexLayout layout = 0;
+ if (NULL != texCoords) {
+ layout |= GrDrawTarget::StageTexCoordVertexLayoutBit(0, 0);
+ }
if (NULL != colors) {
layout |= GrDrawTarget::kColor_VertexLayoutBit;
}
return;
}
- GrDrawTarget::AutoDeviceCoordDraw adcd(target, paint.getActiveStageMask());
+ GrDrawTarget::AutoDeviceCoordDraw adcd(target);
+ if (!adcd.succeeded()) {
+ return;
+ }
- GrVertexLayout layout = PaintStageVertexLayoutBits(paint, NULL);
- layout |= GrDrawTarget::kEdge_VertexLayoutBit;
+ GrVertexLayout layout = GrDrawTarget::kEdge_VertexLayoutBit;
GrAssert(sizeof(CircleVertex) == GrDrawTarget::VertexSize(layout));
GrPoint center = GrPoint::Make(rect.centerX(), rect.centerY());
kUnbuffered_DrawCategory;
GrDrawTarget* target = this->prepareToDraw(paint, category);
GrDrawState::AutoStageDisable atr(fDrawState);
- GrDrawState::StageMask stageMask = paint.getActiveStageMask();
bool prAA = paint.fAntiAlias && !this->getRenderTarget()->isMultisampled();
return;
}
- pr->drawPath(path, fill, translate, target, stageMask, prAA);
+ pr->drawPath(path, fill, translate, target, prAA);
}
////////////////////////////////////////////////////////////////////////////////
drawState->sampler(0)->setCustomStage(SkNEW_ARGS(GrSingleTextureEffect, (src)))->unref();
GrRect rect;
rect.setXYWH(0, 0, SK_Scalar1 * width, SK_Scalar1 * height);
- fGpu->drawSimpleRect(rect, NULL, 0x1);
+ fGpu->drawSimpleRect(rect, NULL);
left = 0;
top = 0;
}
SkRect rect = SkRect::MakeXYWH(0, 0,
SK_Scalar1 * src->width(),
SK_Scalar1 * src->height());
- fGpu->drawSimpleRect(rect, NULL, 1 << 0);
+ fGpu->drawSimpleRect(rect, NULL);
}
void GrContext::internalWriteRenderTargetPixels(GrRenderTarget* target,
fDrawState->setColorFilter(paint.fColorFilterColor, paint.fColorFilterXfermode);
fDrawState->setCoverage(paint.fCoverage);
#if GR_DEBUG_PARTIAL_COVERAGE_CHECK
- if ((paint.getActiveMaskStageMask() || 0xff != paint.fCoverage) &&
+ if ((paint.hasMask() || 0xff != paint.fCoverage) &&
!fGpu->canApplyCoverage()) {
GrPrintf("Partial pixel coverage will be incorrectly blended.\n");
}
const GrVec* translate,
GrScalar srcSpaceTol,
GrDrawTarget* target,
- GrDrawState::StageMask stageMask,
GrPrimitiveType* primType,
int* vertexCnt,
int* indexCnt,
GrPathFill fill,
const GrVec* translate,
GrDrawTarget* target,
- GrDrawState::StageMask stageMask,
bool stencilOnly) {
GrMatrix viewM = target->getDrawState().getViewMatrix();
translate,
tol,
target,
- stageMask,
&primType,
&vertexCnt,
&indexCnt,
drawState->getViewInverse(&vmi)) {
vmi.mapRect(&bounds);
} else {
- if (stageMask) {
- if (!drawState->getViewInverse(&vmi)) {
- GrPrintf("Could not invert matrix.");
- return false;
- }
- drawState->preConcatSamplerMatrices(stageMask, vmi);
+ const GrMatrix& vm = drawState->getViewMatrix();
+ if (!drawState->preConcatSamplerMatricesWithInverse(vm)) {
+ GrPrintf("Could not invert matrix.\n");
+ return false;
}
drawState->viewMatrix()->reset();
}
}
}
GrDrawTarget::AutoGeometryPush agp(target);
- target->drawSimpleRect(bounds, NULL, stageMask);
+ target->drawSimpleRect(bounds, NULL);
} else {
if (passCount > 1) {
drawState->enableState(GrDrawState::kNoColorWrites_StateBit);
GrPathFill fill,
const GrVec* translate,
GrDrawTarget* target,
- GrDrawState::StageMask stageMask,
bool antiAlias) {
return this->internalDrawPath(path,
fill,
translate,
target,
- stageMask,
false);
}
GrDrawTarget* target) {
GrAssert(kInverseEvenOdd_GrPathFill != fill);
GrAssert(kInverseWinding_GrPathFill != fill);
- this->internalDrawPath(path, fill, NULL, target, 0, true);
+ this->internalDrawPath(path, fill, NULL, target, true);
}
GrPathFill fill,
const GrVec* translate,
GrDrawTarget* target,
- GrDrawState::StageMask stageMask,
bool antiAlias) SK_OVERRIDE;
bool internalDrawPath(const SkPath& path,
GrPathFill fill,
const GrVec* translate,
GrDrawTarget* target,
- GrDrawState::StageMask stageMask,
bool stencilOnly);
bool createGeom(const SkPath& path,
const GrVec* translate,
GrScalar srcSpaceTol,
GrDrawTarget* target,
- GrDrawState::StageMask stages,
GrPrimitiveType* primType,
int* vertexCnt,
int* indexCnt,
kMaxTexCoords = kNumStages
};
- /**
- * Bitfield used to indicate a set of stages.
- */
- typedef uint32_t StageMask;
- GR_STATIC_ASSERT(sizeof(StageMask)*8 >= GrDrawState::kNumStages);
-
GrDrawState()
: fRenderTarget(NULL) {
}
/**
- * Preconcats the matrix of all samplers in the mask with the same matrix.
+ * Preconcats the matrix of all samplers of enabled stages with a matrix.
*/
- void preConcatSamplerMatrices(StageMask stageMask, const GrMatrix& matrix) {
- GrAssert(!(stageMask & kIllegalStageMaskBits));
+ void preConcatSamplerMatrices(const GrMatrix& matrix) {
for (int i = 0; i < kNumStages; ++i) {
- if ((1 << i) & stageMask) {
+ if (this->isStageEnabled(i)) {
fSamplerStates[i].preConcatMatrix(matrix);
}
}
}
+ /**
+ * Preconcats the matrix of all samplers in the mask with the inverse of a
+ * matrix. If the matrix inverse cannot be computed (and there is at least
+ * one enabled stage) then false is returned.
+ */
+ bool preConcatSamplerMatricesWithInverse(const GrMatrix& matrix) {
+ GrMatrix inv;
+ bool computed = false;
+ for (int i = 0; i < kNumStages; ++i) {
+ if (this->isStageEnabled(i)) {
+ if (!computed && !matrix.invert(&inv)) {
+ return false;
+ } else {
+ computed = true;
+ }
+ fSamplerStates[i].preConcatMatrix(inv);
+ }
+ }
+ return true;
+ }
+
/// @}
///////////////////////////////////////////////////////////////////////////
sizeof(fPodEndMarker);
}
- static const StageMask kIllegalStageMaskBits = ~((1U << kNumStages)-1);
// @{ these fields can be initialized with memset to 0
union {
GrColor fBlendConstant;
void GrDrawTarget::drawRect(const GrRect& rect,
const GrMatrix* matrix,
- StageMask stageMask,
const GrRect* srcRects[],
const GrMatrix* srcMatrices[]) {
- GrVertexLayout layout = GetRectVertexLayout(stageMask, srcRects);
+ GrVertexLayout layout = GetRectVertexLayout(srcRects);
AutoReleaseGeometry geo(this, layout, 4, 0);
if (!geo.succeeded()) {
drawNonIndexed(kTriangleFan_GrPrimitiveType, 0, 4);
}
-GrVertexLayout GrDrawTarget::GetRectVertexLayout(StageMask stageMask,
- const GrRect* srcRects[]) {
- GrVertexLayout layout = 0;
+GrVertexLayout GrDrawTarget::GetRectVertexLayout(const GrRect* srcRects[]) {
+ if (NULL == srcRects) {
+ return 0;
+ }
+ GrVertexLayout layout = 0;
for (int i = 0; i < GrDrawState::kNumStages; ++i) {
int numTC = 0;
- if (stageMask & (1 << i)) {
- if (NULL != srcRects && NULL != srcRects[i]) {
- layout |= StageTexCoordVertexLayoutBit(i, numTC);
- ++numTC;
- }
+ if (NULL != srcRects[i]) {
+ layout |= StageTexCoordVertexLayoutBit(i, numTC);
+ ++numTC;
}
}
return layout;
////////////////////////////////////////////////////////////////////////////////
-GrDrawTarget::AutoDeviceCoordDraw::AutoDeviceCoordDraw(
- GrDrawTarget* target,
- GrDrawState::StageMask stageMask) {
+GrDrawTarget::AutoDeviceCoordDraw::AutoDeviceCoordDraw(GrDrawTarget* target,
+ uint32_t explicitCoordStageMask) {
GrAssert(NULL != target);
GrDrawState* drawState = target->drawState();
fDrawTarget = target;
fViewMatrix = drawState->getViewMatrix();
- fStageMask = stageMask;
- if (fStageMask) {
- GrMatrix invVM;
- if (fViewMatrix.invert(&invVM)) {
- for (int s = 0; s < GrDrawState::kNumStages; ++s) {
- if (fStageMask & (1 << s)) {
- fSamplerMatrices[s] = drawState->getSampler(s).getMatrix();
- }
+ fRestoreMask = 0;
+ GrMatrix invVM;
+ bool inverted = false;
+
+ for (int s = 0; s < GrDrawState::kNumStages; ++s) {
+ if (!(explicitCoordStageMask & (1 << s)) && drawState->isStageEnabled(s)) {
+ if (!inverted && !fViewMatrix.invert(&invVM)) {
+ // sad trombone sound
+ fDrawTarget = NULL;
+ return;
+ } else {
+ inverted = true;
}
- drawState->preConcatSamplerMatrices(fStageMask, invVM);
- } else {
- // sad trombone sound
- fStageMask = 0;
+ fRestoreMask |= (1 << s);
+ GrSamplerState* sampler = drawState->sampler(s);
+ fSamplerMatrices[s] = sampler->getMatrix();
+ sampler->preConcatMatrix(invVM);
}
}
drawState->viewMatrix()->reset();
GrDrawState* drawState = fDrawTarget->drawState();
drawState->setViewMatrix(fViewMatrix);
for (int s = 0; s < GrDrawState::kNumStages; ++s) {
- if (fStageMask & (1 << s)) {
+ if (fRestoreMask & (1 << s)) {
*drawState->sampler(s)->matrix() = fSamplerMatrices[s];
}
}
int fMaxTextureSize;
};
- // for convenience
- typedef GrDrawState::StageMask StageMask;
-
///////////////////////////////////////////////////////////////////////////
GrDrawTarget();
GrDrawState* drawState() { return fDrawState; }
/**
- * Shortcut for drawState()->preConcatSamplerMatrices() on all enabled
- * stages
- *
- * @param matrix the matrix to concat
- */
- void preConcatEnabledSamplerMatrices(const GrMatrix& matrix) {
- StageMask stageMask = this->enabledStages();
- this->drawState()->preConcatSamplerMatrices(stageMask, matrix);
- }
-
- /**
* Color alpha and coverage are two inputs to the drawing pipeline. For some
* blend modes it is safe to fold the coverage into constant or per-vertex
* color alpha value. For other blend modes they must be handled separately.
* drawNonIndexed.
* @param rect the rect to draw
* @param matrix optional matrix applied to rect (before viewMatrix)
- * @param stageMask bitmask indicating which stages are enabled.
- * Bit i indicates whether stage i is enabled.
* @param srcRects specifies rects for stages enabled by stageEnableMask.
* if stageEnableMask bit i is 1, srcRects is not NULL,
* and srcRects[i] is not NULL, then srcRects[i] will be
*/
virtual void drawRect(const GrRect& rect,
const GrMatrix* matrix,
- StageMask stageMask,
const GrRect* srcRects[],
const GrMatrix* srcMatrices[]);
* matrices.
*/
void drawSimpleRect(const GrRect& rect,
- const GrMatrix* matrix,
- StageMask stageEnableBitfield) {
- drawRect(rect, matrix, stageEnableBitfield, NULL, NULL);
+ const GrMatrix* matrix) {
+ drawRect(rect, matrix, NULL, NULL);
}
/**
*/
class AutoDeviceCoordDraw : ::GrNoncopyable {
public:
- AutoDeviceCoordDraw(GrDrawTarget* target, StageMask stageMask);
+ /**
+ * If a stage's texture matrix is applied to explicit per-vertex coords,
+ * rather than to positions, then we don't want to modify its matrix.
+ * The explicitCoordStageMask is used to specify such stages.
+ *
+ * TODO: Remove this when custom stage's control their own texture
+ * matrix and there is a "view matrix has changed" notification to the
+ * custom stages.
+ */
+ AutoDeviceCoordDraw(GrDrawTarget* target,
+ uint32_t explicitCoordStageMask = 0);
+ bool succeeded() const { return NULL != fDrawTarget; }
~AutoDeviceCoordDraw();
private:
GrDrawTarget* fDrawTarget;
GrMatrix fViewMatrix;
GrMatrix fSamplerMatrices[GrDrawState::kNumStages];
- int fStageMask;
+ int fRestoreMask;
};
////////////////////////////////////////////////////////////////////////////
return this->getDrawState().isStageEnabled(stage);
}
- StageMask enabledStages() const {
- StageMask mask = 0;
- for (int s = 0; s < GrDrawState::kNumStages; ++s) {
- mask |= this->isStageEnabled(s) ? 1 : 0;
- }
- return mask;
- }
-
// A sublcass can optionally overload this function to be notified before
// vertex and index space is reserved.
virtual void willReserveVertexAndIndexSpace(GrVertexLayout vertexLayout,
// Helpers for drawRect, protected so subclasses that override drawRect
// can use them.
- static GrVertexLayout GetRectVertexLayout(StageMask stageEnableBitfield,
- const GrRect* srcRects[]);
+ static GrVertexLayout GetRectVertexLayout(const GrRect* srcRects[]);
static void SetRectVertices(const GrRect& rect,
const GrMatrix* matrix,
void GrInOrderDrawBuffer::drawRect(const GrRect& rect,
const GrMatrix* matrix,
- StageMask stageMask,
const GrRect* srcRects[],
const GrMatrix* srcMatrices[]) {
if (fMaxQuads) {
bool appendToPreviousDraw = false;
- GrVertexLayout layout = GetRectVertexLayout(stageMask, srcRects);
+ GrVertexLayout layout = GetRectVertexLayout(srcRects);
AutoReleaseGeometry geo(this, layout, 4, 0);
if (!geo.succeeded()) {
GrPrintf("Failed to get space for vertices!\n");
// then we don't want to modify the sampler matrices. Otherwise we do
// we have to account for the view matrix change in the sampler
// matrices.
- StageMask devCoordMask = (NULL == srcRects) ? stageMask : 0;
- GrDrawTarget::AutoDeviceCoordDraw adcd(this, devCoordMask);
+ uint32_t explicitCoordMask = 0;
+ if (srcRects) {
+ for (int s = 0; s < GrDrawState::kNumStages; ++s) {
+ if (srcRects[s]) {
+ explicitCoordMask |= (1 << s);
+ }
+ }
+ }
+ GrDrawTarget::AutoDeviceCoordDraw adcd(this, explicitCoordMask);
+ if (!adcd.succeeded()) {
+ return;
+ }
if (NULL != matrix) {
combinedMatrix.preConcat(*matrix);
}
}
fInstancedDrawTracker.reset();
} else {
- INHERITED::drawRect(rect, matrix, stageMask, srcRects, srcMatrices);
+ INHERITED::drawRect(rect, matrix, srcRects, srcMatrices);
}
}
// overrides from GrDrawTarget
virtual void drawRect(const GrRect& rect,
const GrMatrix* matrix = NULL,
- StageMask stageEnableMask = 0,
const GrRect* srcRects[] = NULL,
const GrMatrix* srcMatrices[] = NULL) SK_OVERRIDE;
* @param translate optional additional translation applied to
* the path (can be NULL)
* @param target target that the path will be rendered to
- * @param stageMask bitfield that indicates which stages are
- * in use. All enabled stages expect positions
- * as texture coordinates. The path renderer
- * can use the remaining stages for its path
- * filling algorithm.
* @param antiAlias true if anti-aliasing is required.
*/
virtual bool drawPath(const SkPath& path,
GrPathFill fill,
const GrVec* translate,
GrDrawTarget* target,
- GrDrawState::StageMask stageMask,
bool antiAlias) {
GrAssert(this->canDrawPath(path, fill, target, antiAlias));
- return this->onDrawPath(path, fill, translate,
- target, stageMask, antiAlias);
+ return this->onDrawPath(path, fill, translate, target, antiAlias);
}
/**
* @param translate optional additional translation applied to
* the path
* @param target target that the path will be rendered to
- * @param stageMask bitfield that indicates which stages are
- * in use. All enabled stages expect positions
- * as texture coordinates. The path renderer
- * use the remaining stages for its path
- * filling algorithm.
* @param antiAlias whether antialiasing is enabled or not.
*/
virtual bool onDrawPath(const SkPath& path,
GrPathFill fill,
const GrVec* translate,
GrDrawTarget* target,
- GrDrawState::StageMask stageMask,
bool antiAlias) = 0;
private:
void GrSWMaskHelper::DrawToTargetWithPathMask(GrTexture* texture,
GrDrawTarget* target,
- GrDrawState::StageMask stageMask,
const GrIRect& rect) {
GrDrawState* drawState = target->drawState();
- GrDrawTarget::AutoDeviceCoordDraw adcd(target, stageMask);
+ GrDrawTarget::AutoDeviceCoordDraw adcd(target);
+ if (!adcd.succeeded()) {
+ return;
+ }
enum {
// the SW path renderer shares this stage with glyph
// rendering (kGlyphMaskStage in GrBatchedTextContext)
const GrRect* srcRects[GrDrawState::kNumStages] = { NULL };
srcRects[kPathMaskStage] = &maskRect;
- stageMask |= 1 << kPathMaskStage;
GrRect dstRect = GrRect::MakeLTRB(
SK_Scalar1 * rect.fLeft,
SK_Scalar1 * rect.fTop,
SK_Scalar1 * rect.fRight,
SK_Scalar1 * rect.fBottom);
- target->drawRect(dstRect, NULL, stageMask, srcRects, NULL);
+ target->drawRect(dstRect, NULL, srcRects, NULL);
drawState->disableStage(kPathMaskStage);
}
// output of DrawPathMaskToTexture.
static void DrawToTargetWithPathMask(GrTexture* texture,
GrDrawTarget* target,
- GrDrawState::StageMask stageMask,
const GrIRect& rect);
protected:
////////////////////////////////////////////////////////////////////////////////
void draw_around_inv_path(GrDrawTarget* target,
- GrDrawState::StageMask stageMask,
const GrIRect& clipBounds,
const GrIRect& pathBounds) {
- GrDrawTarget::AutoDeviceCoordDraw adcd(target, stageMask);
+ GrDrawTarget::AutoDeviceCoordDraw adcd(target);
+ if (!adcd.succeeded()) {
+ return;
+ }
GrRect rect;
if (clipBounds.fTop < pathBounds.fTop) {
rect.iset(clipBounds.fLeft, clipBounds.fTop,
clipBounds.fRight, pathBounds.fTop);
- target->drawSimpleRect(rect, NULL, stageMask);
+ target->drawSimpleRect(rect, NULL);
}
if (clipBounds.fLeft < pathBounds.fLeft) {
rect.iset(clipBounds.fLeft, pathBounds.fTop,
pathBounds.fLeft, pathBounds.fBottom);
- target->drawSimpleRect(rect, NULL, stageMask);
+ target->drawSimpleRect(rect, NULL);
}
if (clipBounds.fRight > pathBounds.fRight) {
rect.iset(pathBounds.fRight, pathBounds.fTop,
clipBounds.fRight, pathBounds.fBottom);
- target->drawSimpleRect(rect, NULL, stageMask);
+ target->drawSimpleRect(rect, NULL);
}
if (clipBounds.fBottom > pathBounds.fBottom) {
rect.iset(clipBounds.fLeft, pathBounds.fBottom,
clipBounds.fRight, clipBounds.fBottom);
- target->drawSimpleRect(rect, NULL, stageMask);
+ target->drawSimpleRect(rect, NULL);
}
}
GrPathFill fill,
const GrVec* translate,
GrDrawTarget* target,
- GrDrawState::StageMask stageMask,
bool antiAlias) {
if (NULL == fContext) {
if (!get_path_and_clip_bounds(target, path, vm,
&pathBounds, &clipBounds)) {
if (GrIsFillInverted(fill)) {
- draw_around_inv_path(target, stageMask,
- clipBounds, pathBounds);
+ draw_around_inv_path(target, clipBounds, pathBounds);
}
return true;
}
return false;
}
- GrSWMaskHelper::DrawToTargetWithPathMask(texture, target,
- stageMask, pathBounds);
+ GrSWMaskHelper::DrawToTargetWithPathMask(texture, target, pathBounds);
if (GrIsFillInverted(fill)) {
- draw_around_inv_path(target, stageMask,
- clipBounds, pathBounds);
+ draw_around_inv_path(target, clipBounds, pathBounds);
}
return true;
GrPathFill fill,
const GrVec* translate,
GrDrawTarget* target,
- GrDrawState::StageMask stageMask,
bool antiAlias) SK_OVERRIDE;
private:
GrPathFill fill,
const GrVec* translate,
GrDrawTarget* target,
- GrDrawState::StageMask stageMask,
bool antiAlias){
GrAssert(!antiAlias);
GrAssert(kHairLine_GrPathFill != fill);
// theoretically could set bloat = 0, instead leave it because of matrix inversion
// precision.
} else {
- if (stageMask) {
- if (!drawState->getViewInverse(&vmi)) {
- GrPrintf("Could not invert matrix.");
- return false;
- }
- drawState->preConcatSamplerMatrices(stageMask, vmi);
+ if (!drawState->preConcatSamplerMatricesWithInverse(drawState->getViewMatrix())) {
+ GrPrintf("Could not invert matrix.\n");
+ return false;
}
if (avmr.isSet()) {
avmr.set(drawState);
*drawState->stencil() = kInvertedStencilPass;
}
bounds.outset(bloat, bloat);
- target->drawSimpleRect(bounds, NULL, stageMask);
+ target->drawSimpleRect(bounds, NULL);
target->drawState()->stencil()->setDisabled();
return true;
}
GrPathFill fill,
const GrVec* translate,
GrDrawTarget* target,
- GrDrawState::StageMask stageMask,
bool antiAlias) SK_OVERRIDE;
private:
context->setRenderTarget(oldRenderTarget);
context->setClip(oldClip);
- if (grp->hasTextureOrMask()) {
- GrMatrix inverse;
- if (!matrix.invert(&inverse)) {
- return false;
- }
- grp->preConcatActiveSamplerMatrices(inverse);
+ if (!grp->preConcatSamplerMatricesWithInverse(matrix)) {
+ return false;
}
static const int MASK_IDX = GrPaint::kMaxMasks - 1;
// we now have a device-aligned 8bit mask in dstM, ready to be drawn using
// the current clip (and identity matrix) and grpaint settings
- // used to compute inverse view, if necessary
- GrMatrix ivm = matrix;
-
GrContext::AutoMatrix avm(context, GrMatrix::I());
+ if (!grp->preConcatSamplerMatricesWithInverse(matrix)) {
+ return false;
+ }
+
GrTextureDesc desc;
desc.fWidth = dstM.fBounds.width();
desc.fHeight = dstM.fBounds.height();
texture->writePixels(0, 0, desc.fWidth, desc.fHeight, desc.fConfig,
dstM.fImage, dstM.fRowBytes);
- if (grp->hasTextureOrMask() && ivm.invert(&ivm)) {
- grp->preConcatActiveSamplerMatrices(ivm);
- }
-
static const int MASK_IDX = GrPaint::kMaxMasks - 1;
// we assume the last mask index is available for use
GrAssert(!grp->isMaskStageEnabled(MASK_IDX));