Use coverage stages for supersample AA resolve, edgeAA, and glyph masks. Expose a mask stage through GrPaint
Review URL: http://codereview.appspot.com/4548048/
git-svn-id: http://skia.googlecode.com/svn/trunk@1356 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/gpu/include/GrContext.h b/gpu/include/GrContext.h
index c29526a..2fecca5 100644
--- a/gpu/include/GrContext.h
+++ b/gpu/include/GrContext.h
@@ -579,11 +579,6 @@
GrPathRenderer* getPathRenderer(const GrDrawTarget*, const GrPath&, GrPathFill);
struct OffscreenRecord;
- // we currently only expose stage 0 through the paint so use stage 1. We
- // use stage 1 for the offscreen.
- enum {
- kOffscreenStage = 1,
- };
bool doOffscreenAA(GrDrawTarget* target,
const GrPaint& paint,
@@ -602,6 +597,15 @@
const GrIRect& boundRect,
OffscreenRecord* record);
+ // 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]);
+
};
/**
diff --git a/gpu/include/GrContext_impl.h b/gpu/include/GrContext_impl.h
index fae4e92..c79a191 100644
--- a/gpu/include/GrContext_impl.h
+++ b/gpu/include/GrContext_impl.h
@@ -40,19 +40,15 @@
const COL_SRC* colorSrc,
const IDX_SRC* idxSrc) {
- GrVertexLayout layout = 0;
-
GrDrawTarget::AutoReleaseGeometry geo;
GrDrawTarget* target = this->prepareToDraw(paint, kUnbuffered_DrawCategory);
- if (NULL != paint.getTexture()) {
- if (NULL != texCoordSrc) {
- layout |= GrDrawTarget::StageTexCoordVertexLayoutBit(0,0);
- } else {
- layout |= GrDrawTarget::StagePosAsTexCoordVertexLayoutBit(0);
- }
- }
+ bool hasTexCoords[GrPaint::kTotalStages] = {
+ NULL != texCoordSrc, // texCoordSrc provides explicit stage 0 coords
+ 0 // remaining stages use positions
+ };
+ GrVertexLayout layout = PaintStageVertexLayoutBits(paint, hasTexCoords);
if (NULL != colorSrc) {
layout |= GrDrawTarget::kColor_VertexLayoutBit;
diff --git a/gpu/include/GrDrawTarget.h b/gpu/include/GrDrawTarget.h
index 9a00b57..985cca7 100644
--- a/gpu/include/GrDrawTarget.h
+++ b/gpu/include/GrDrawTarget.h
@@ -50,7 +50,7 @@
* or not.
*/
enum {
- kNumStages = 2,
+ kNumStages = 3,
kMaxTexCoords = kNumStages
};
@@ -147,6 +147,7 @@
// default stencil setting should be disabled
GrAssert(fStencilSettings.isDisabled());
+ fFirstCoverageStage = kNumStages;
}
uint32_t fFlagBits;
GrBlendCoeff fSrcBlend;
@@ -250,6 +251,18 @@
}
/**
+ * Shortcut for preConcatSamplerMatrix on all stages in mask with same
+ * matrix
+ */
+ void preConcatSamplerMatrices(int stageMask, const GrMatrix& matrix) {
+ for (int i = 0; i < kNumStages; ++i) {
+ if ((1 << i) & stageMask) {
+ this->preConcatSamplerMatrix(i, matrix);
+ }
+ }
+ }
+
+ /**
* Gets the matrix of a stage's sampler
*
* @param stage the stage to of sampler to get
diff --git a/gpu/include/GrPaint.h b/gpu/include/GrPaint.h
index 3035ca1..f7ca34c 100644
--- a/gpu/include/GrPaint.h
+++ b/gpu/include/GrPaint.h
@@ -25,12 +25,17 @@
/**
* The paint describes how pixels are colored when the context draws to
- * them.
+ * them. TODO: Make this a "real" class with getters and setters, default
+ * values, and documentation.
*/
class GrPaint {
public:
+ enum {
+ kMaxTextures = 1,
+ kMaxMasks = 1,
+ };
- // All the paint fields are public except texture (it's ref-counted)
+ // All the paint fields are public except textures/samplers
GrBlendCoeff fSrcBlendCoeff;
GrBlendCoeff fDstBlendCoeff;
bool fAntiAlias;
@@ -38,22 +43,75 @@
GrColor fColor;
- GrSamplerState fSampler;
-
GrColor fColorFilterColor;
SkXfermode::Mode fColorFilterXfermode;
- void setTexture(GrTexture* texture) {
+ void setTexture(int i, GrTexture* texture) {
+ GrAssert((unsigned)i < kMaxTextures);
GrSafeRef(texture);
- GrSafeUnref(fTexture);
- fTexture = texture;
+ GrSafeUnref(fTextures[i]);
+ fTextures[i] = texture;
}
- GrTexture* getTexture() const { return fTexture; }
+ GrTexture* getTexture(int i) const {
+ GrAssert((unsigned)i < kMaxTextures);
+ return fTextures[i];
+ }
+
+ GrSamplerState* getTextureSampler(int i) {
+ GrAssert((unsigned)i < kMaxTextures);
+ return fTextureSamplers + i;
+ }
+
+ const GrSamplerState* getTextureSampler(int i) const {
+ GrAssert((unsigned)i < kMaxTextures);
+ return fTextureSamplers + i;
+ }
+
+ // The mask can be alpha-only or per channel. It is applied
+ // after the colorfilter
+ void setMask(int i, GrTexture* mask) {
+ GrAssert((unsigned)i < kMaxMasks);
+ GrSafeRef(mask);
+ GrSafeUnref(fMaskTextures[i]);
+ fMaskTextures[i] = mask;
+ }
+
+ GrTexture* getMask(int i) const {
+ GrAssert((unsigned)i < kMaxMasks);
+ return fMaskTextures[i];
+ }
+
+ // mask's sampler matrix is always applied to the positions
+ // (i.e. no explicit texture coordinates)
+ GrSamplerState* getMaskSampler(int i) {
+ GrAssert((unsigned)i < kMaxMasks);
+ return fMaskSamplers + i;
+ }
+
+ const GrSamplerState* getMaskSampler(int i) const {
+ GrAssert((unsigned)i < kMaxMasks);
+ return fMaskSamplers + i;
+ }
+
+ // pre-concats sampler matrices for non-NULL textures and masks
+ void preConcatActiveSamplerMatrices(const GrMatrix& matrix) {
+ for (int i = 0; i < kMaxTextures; ++i) {
+ fTextureSamplers[i].preConcatMatrix(matrix);
+ }
+ for (int i = 0; i < kMaxMasks; ++i) {
+ fMaskSamplers[i].preConcatMatrix(matrix);
+ }
+ }
// uninitialized
GrPaint() {
- fTexture = NULL;
+ for (int i = 0; i < kMaxTextures; ++i) {
+ fTextures[i] = NULL;
+ }
+ for (int i = 0; i < kMaxMasks; ++i) {
+ fMaskTextures[i] = NULL;
+ }
}
GrPaint(const GrPaint& paint) {
@@ -67,22 +125,35 @@
fColorFilterColor = paint.fColorFilterColor;
fColorFilterXfermode = paint.fColorFilterXfermode;
- fSampler = paint.fSampler;
- fTexture = paint.fTexture;
- GrSafeRef(fTexture);
+ for (int i = 0; i < kMaxTextures; ++i) {
+ fTextureSamplers[i] = paint.fTextureSamplers[i];
+ fTextures[i] = paint.fTextures[i];
+ GrSafeRef(fTextures[i]);
+ }
+ for (int i = 0; i < kMaxMasks; ++i) {
+ fMaskSamplers[i] = paint.fMaskSamplers[i];
+ fMaskTextures[i] = paint.fMaskTextures[i];
+ GrSafeRef(fMaskTextures[i]);
+ }
}
~GrPaint() {
- GrSafeUnref(fTexture);
+ for (int i = 0; i < kMaxTextures; ++i) {
+ GrSafeUnref(fTextures[i]);
+ }
+ for (int i = 0; i < kMaxMasks; ++i) {
+ GrSafeUnref(fMaskTextures[i]);
+ }
}
- // sets paint to src-over, solid white, no texture
+ // sets paint to src-over, solid white, no texture, no mask
void reset() {
- resetBlend();
- resetOptions();
- resetColor();
- resetTexture();
- resetColorFilter();
+ this->resetBlend();
+ this->resetOptions();
+ this->resetColor();
+ this->resetTextures();
+ this->resetColorFilter();
+ this->resetMasks();
}
void resetColorFilter() {
@@ -90,8 +161,60 @@
fColorFilterColor = GrColorPackRGBA(0xff, 0xff, 0xff, 0xff);
}
+ 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]) {
+ mask |= 1 << (i + kFirstTextureStage);
+ }
+ }
+ return mask;
+ }
+
+ int getActiveMaskStageMask() const {
+ int mask;
+ for (int i = 0; i < kMaxMasks; ++i) {
+ if (NULL != fMaskTextures[i]) {
+ 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)
+ enum {
+ kFirstTextureStage = 0,
+ kFirstMaskStage = kMaxTextures,
+ kTotalStages = kMaxTextures + kMaxMasks,
+ };
+
private:
- GrTexture* fTexture;
+
+ GrSamplerState fTextureSamplers[kMaxTextures];
+ GrSamplerState fMaskSamplers[kMaxMasks];
+
+ GrTexture* fTextures[kMaxTextures];
+ GrTexture* fMaskTextures[kMaxMasks];
void resetBlend() {
fSrcBlendCoeff = kOne_BlendCoeff;
@@ -107,11 +230,19 @@
fColor = GrColorPackRGBA(0xff, 0xff, 0xff, 0xff);
}
- void resetTexture() {
- setTexture(NULL);
- fSampler.setClampNoFilter();
+ void resetTextures() {
+ for (int i = 0; i < kMaxTextures; ++i) {
+ this->setTexture(i, NULL);
+ fTextureSamplers[i].setClampNoFilter();
+ }
}
+ void resetMasks() {
+ for (int i = 0; i < kMaxMasks; ++i) {
+ this->setMask(i, NULL);
+ fMaskSamplers[i].setClampNoFilter();
+ }
+ }
};
#endif
diff --git a/gpu/src/GrContext.cpp b/gpu/src/GrContext.cpp
index 3a4233a..af777c1 100644
--- a/gpu/src/GrContext.cpp
+++ b/gpu/src/GrContext.cpp
@@ -106,6 +106,26 @@
////////////////////////////////////////////////////////////////////////////////
+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);
+ } else {
+ layout |= GrDrawTarget::StagePosAsTexCoordVertexLayoutBit(i);
+ }
+ }
+ }
+ return layout;
+}
+
+
+////////////////////////////////////////////////////////////////////////////////
+
enum {
kNPOTBit = 0x1,
kFilterBit = 0x2,
@@ -576,6 +596,10 @@
GrTexture* src = record->fEntry0->texture();
int scale;
+ enum {
+ kOffscreenStage = GrPaint::kTotalStages,
+ };
+
if (OffscreenRecord::k4x4TwoPass_Downsample == record->fDownsample) {
GrAssert(NULL != record->fEntry1);
scale = 2;
@@ -605,11 +629,14 @@
}
// setup for draw back to main RT
+ int stageMask = paint.getActiveStageMask();
+
target->restoreDrawState(record->fSavedState);
- if (NULL != paint.getTexture()) {
+
+ if (stageMask) {
GrMatrix invVM;
if (target->getViewInverse(&invVM)) {
- target->preConcatSamplerMatrix(0, invVM);
+ target->preConcatSamplerMatrices(stageMask, invVM);
}
}
target->setViewMatrix(GrMatrix::I());
@@ -623,7 +650,7 @@
target->setSamplerState(kOffscreenStage, sampler);
GrRect dstRect;
- int stages = (1 << kOffscreenStage) | (NULL == paint.getTexture() ? 0 : 1);
+ int stages = (1 << kOffscreenStage) | stageMask;
dstRect.set(boundRect);
target->drawSimpleRect(dstRect, NULL, stages);
@@ -661,11 +688,14 @@
}
static GrColor getColorForMesh(const GrPaint& paint) {
- if (NULL == paint.getTexture()) {
- return paint.fColor;
- } else {
+ // FIXME: This was copied from SkGpuDevice, seems like
+ // we should have already smeared a in caller if that
+ // is what is desired.
+ if (paint.hasTexture()) {
unsigned a = GrColorUnpackA(paint.fColor);
return GrColorPackRGBA(a, a, a, a);
+ } else {
+ return paint.fColor;
}
}
@@ -741,10 +771,8 @@
const GrPaint& paint,
const GrRect& devRect) {
- GrVertexLayout layout = GrDrawTarget::kColor_VertexLayoutBit;
- if (NULL != paint.getTexture()) {
- layout |= GrDrawTarget::StagePosAsTexCoordVertexLayoutBit(0);
- }
+ GrVertexLayout layout = PaintStageVertexLayoutBits(paint, NULL) |
+ GrDrawTarget::kColor_VertexLayoutBit;
size_t vsize = GrDrawTarget::VertexSize(layout);
@@ -782,11 +810,8 @@
const GrScalar rx = GrMul(dx, GR_ScalarHalf);
const GrScalar ry = GrMul(dy, GR_ScalarHalf);
- GrVertexLayout layout = GrDrawTarget::kColor_VertexLayoutBit;
-
- if (NULL != paint.getTexture()) {
- layout |= GrDrawTarget::StagePosAsTexCoordVertexLayoutBit(0);
- }
+ GrVertexLayout layout = PaintStageVertexLayoutBits(paint, NULL) |
+ GrDrawTarget::kColor_VertexLayoutBit;
GrScalar spare;
{
@@ -902,9 +927,9 @@
GrScalar width,
const GrMatrix* matrix) {
- bool textured = NULL != paint.getTexture();
GrDrawTarget* target = this->prepareToDraw(paint, kUnbuffered_DrawCategory);
+ int stageMask = paint.getActiveStageMask();
GrRect devRect = rect;
GrMatrix combinedMatrix;
@@ -913,10 +938,10 @@
if (doAA) {
GrDrawTarget::AutoViewMatrixRestore avm(target);
- if (textured) {
+ if (stageMask) {
GrMatrix inv;
if (combinedMatrix.invert(&inv)) {
- target->preConcatSamplerMatrix(0, inv);
+ target->preConcatSamplerMatrices(stageMask, inv);
}
}
target->setViewMatrix(GrMatrix::I());
@@ -940,9 +965,8 @@
// TODO: consider making static vertex buffers for these cases.
// Hairline could be done by just adding closing vertex to
// unitSquareVertexBuffer()
- GrVertexLayout layout = textured ?
- GrDrawTarget::StagePosAsTexCoordVertexLayoutBit(0) :
- 0;
+ GrVertexLayout layout = PaintStageVertexLayoutBits(paint, NULL);
+
static const int worstCaseVertCount = 10;
GrDrawTarget::AutoReleaseGeometry geo(target, layout, worstCaseVertCount, 0);
@@ -973,17 +997,14 @@
if (NULL != matrix) {
avmr.set(target);
target->preConcatViewMatrix(*matrix);
- if (textured) {
- target->preConcatSamplerMatrix(0, *matrix);
- }
+ target->preConcatSamplerMatrices(stageMask, *matrix);
}
target->drawNonIndexed(primType, 0, vertCount);
} else {
#if GR_STATIC_RECT_VB
- GrVertexLayout layout = (textured) ?
- GrDrawTarget::StagePosAsTexCoordVertexLayoutBit(0) :
- 0;
+ GrVertexLayout layout = PaintStageVertexLayoutBits(paint, NULL);
+
target->setVertexSourceToBuffer(layout,
fGpu->getUnitSquareVertexBuffer());
GrDrawTarget::AutoViewMatrixRestore avmr(target);
@@ -997,13 +1018,11 @@
}
target->preConcatViewMatrix(m);
-
- if (textured) {
- target->preConcatSamplerMatrix(0, m);
- }
+ target->preConcatSamplerMatrices(stageMask, m);
+
target->drawNonIndexed(kTriangleFan_PrimitiveType, 0, 4);
#else
- target->drawSimpleRect(rect, matrix, textured ? 1 : 0);
+ target->drawSimpleRect(rect, matrix, stageMask);
#endif
}
}
@@ -1014,7 +1033,8 @@
const GrMatrix* dstMatrix,
const GrMatrix* srcMatrix) {
- if (NULL == paint.getTexture()) {
+ // srcRect refers to paint's first texture
+ if (NULL == paint.getTexture(0)) {
drawRect(paint, dstRect, -1, dstMatrix);
return;
}
@@ -1023,8 +1043,8 @@
#if GR_STATIC_RECT_VB
GrDrawTarget* target = this->prepareToDraw(paint, kUnbuffered_DrawCategory);
-
- GrVertexLayout layout = GrDrawTarget::StagePosAsTexCoordVertexLayoutBit(0);
+
+ GrVertexLayout layout = PaintStageVertexLayoutBits(paint, NULL);
GrDrawTarget::AutoViewMatrixRestore avmr(target);
GrMatrix m;
@@ -1037,13 +1057,20 @@
}
target->preConcatViewMatrix(m);
+ // srcRect refers to first stage
+ int otherStageMask = paint.getActiveStageMask() &
+ (~(1 << GrPaint::kFirstTextureStage));
+ if (otherStageMask) {
+ target->preConcatSamplerMatrices(otherStageMask, m);
+ }
+
m.setAll(srcRect.width(), 0, srcRect.fLeft,
0, srcRect.height(), srcRect.fTop,
0, 0, GrMatrix::I()[8]);
if (NULL != srcMatrix) {
m.postConcat(*srcMatrix);
}
- target->preConcatSamplerMatrix(0, m);
+ target->preConcatSamplerMatrix(GrPaint::kFirstTextureStage, m);
target->setVertexSourceToBuffer(layout, fGpu->getUnitSquareVertexBuffer());
target->drawNonIndexed(kTriangleFan_PrimitiveType, 0, 4);
@@ -1073,26 +1100,22 @@
const GrColor colors[],
const uint16_t indices[],
int indexCount) {
- GrVertexLayout layout = 0;
- int vertexSize = sizeof(GrPoint);
GrDrawTarget::AutoReleaseGeometry geo;
GrDrawTarget* target = this->prepareToDraw(paint, kUnbuffered_DrawCategory);
- if (NULL != paint.getTexture()) {
- if (NULL == texCoords) {
- layout |= GrDrawTarget::StagePosAsTexCoordVertexLayoutBit(0);
- } else {
- layout |= GrDrawTarget::StageTexCoordVertexLayoutBit(0,0);
- vertexSize += sizeof(GrPoint);
- }
- }
+ bool hasTexCoords[GrPaint::kTotalStages] = {
+ NULL != texCoords, // texCoordSrc provides explicit stage 0 coords
+ 0 // remaining stages use positions
+ };
+
+ GrVertexLayout layout = PaintStageVertexLayoutBits(paint, hasTexCoords);
if (NULL != colors) {
layout |= GrDrawTarget::kColor_VertexLayoutBit;
- vertexSize += sizeof(GrColor);
}
+ int vertexSize = GrDrawTarget::VertexSize(layout);
bool doAA = false;
OffscreenRecord record;
@@ -1105,9 +1128,9 @@
}
int texOffsets[GrDrawTarget::kMaxTexCoords];
int colorOffset;
- int vsize = GrDrawTarget::VertexSizeAndOffsetsByIdx(layout,
- texOffsets,
- &colorOffset);
+ GrDrawTarget::VertexSizeAndOffsetsByIdx(layout,
+ texOffsets,
+ &colorOffset);
void* curVertex = geo.vertices();
for (int i = 0; i < vertexCount; ++i) {
@@ -1119,7 +1142,7 @@
if (colorOffset > 0) {
*(GrColor*)((intptr_t)curVertex + colorOffset) = colors[i];
}
- curVertex = (void*)((intptr_t)curVertex + vsize);
+ curVertex = (void*)((intptr_t)curVertex + vertexSize);
}
} else {
// we don't do offscreen AA when we have per-vertex tex coords or colors
@@ -1193,10 +1216,7 @@
return;
}
}
- GrDrawTarget::StageBitfield enabledStages = 0;
- if (NULL != paint.getTexture()) {
- enabledStages |= 1;
- }
+ GrDrawTarget::StageBitfield enabledStages = paint.getActiveStageMask();
pr->drawPath(target, enabledStages, path, fill, translate);
}
@@ -1308,8 +1328,21 @@
////////////////////////////////////////////////////////////////////////////////
void GrContext::SetPaint(const GrPaint& paint, GrDrawTarget* target) {
- target->setTexture(0, paint.getTexture());
- target->setSamplerState(0, paint.fSampler);
+
+ for (int i = 0; i < GrPaint::kMaxTextures; ++i) {
+ int s = i + GrPaint::kFirstTextureStage;
+ target->setTexture(s, paint.getTexture(i));
+ target->setSamplerState(s, *paint.getTextureSampler(i));
+ }
+
+ target->setFirstCoverageStage(GrPaint::kFirstMaskStage);
+
+ for (int i = 0; i < GrPaint::kMaxMasks; ++i) {
+ int s = i + GrPaint::kFirstMaskStage;
+ target->setTexture(s, paint.getMask(i));
+ target->setSamplerState(s, *paint.getMaskSampler(i));
+ }
+
target->setColor(paint.fColor);
if (paint.fDither) {
diff --git a/gpu/src/GrTextContext.cpp b/gpu/src/GrTextContext.cpp
index 9e8e40a..2aacfa2 100644
--- a/gpu/src/GrTextContext.cpp
+++ b/gpu/src/GrTextContext.cpp
@@ -25,11 +25,9 @@
#include "GrGpuVertex.h"
#include "GrDrawTarget.h"
-static const int TEXT_STAGE = 1;
-
-static const GrVertexLayout BASE_VLAYOUT =
- GrDrawTarget::kTextFormat_VertexLayoutBit |
- GrDrawTarget::StageTexCoordVertexLayoutBit(TEXT_STAGE,0);
+enum {
+ kGlyphMaskStage = GrPaint::kTotalStages,
+};
void GrTextContext::flushGlyphs() {
if (fCurrVertex > 0) {
@@ -45,17 +43,17 @@
GrSamplerState sampler(GrSamplerState::kRepeat_WrapMode,
GrSamplerState::kRepeat_WrapMode,
filter);
- fDrawTarget->setSamplerState(TEXT_STAGE, sampler);
+ fDrawTarget->setSamplerState(kGlyphMaskStage, sampler);
GrAssert(GrIsALIGN4(fCurrVertex));
int nIndices = fCurrVertex + (fCurrVertex >> 1);
GrAssert(fCurrTexture);
- fDrawTarget->setTexture(TEXT_STAGE, fCurrTexture);
+ fDrawTarget->setTexture(kGlyphMaskStage, fCurrTexture);
if (!GrPixelConfigIsAlphaOnly(fCurrTexture->config())) {
if (kOne_BlendCoeff != fPaint.fSrcBlendCoeff ||
kISA_BlendCoeff != fPaint.fDstBlendCoeff ||
- NULL != fPaint.getTexture()) {
+ fPaint.hasTexture()) {
GrPrintf("LCD Text will not draw correctly.\n");
}
// setup blend so that we get mask * paintColor + (1-mask)*dstColor
@@ -117,18 +115,31 @@
fOrigViewMatrix = fContext->getMatrix();
fContext->setMatrix(fExtMatrix);
- fVertexLayout = BASE_VLAYOUT;
- if (NULL != paint.getTexture()) {
- fVertexLayout |= GrDrawTarget::StagePosAsTexCoordVertexLayoutBit(0);
- GrMatrix inverseViewMatrix;
- if (fOrigViewMatrix.invert(&inverseViewMatrix)) {
- fPaint.fSampler.preConcatMatrix(inverseViewMatrix);
- }
- }
+ fDrawTarget = fContext->getTextTarget(fPaint);
fVertices = NULL;
fMaxVertices = 0;
- fDrawTarget = fContext->getTextTarget(fPaint);
+
+ fVertexLayout =
+ GrDrawTarget::kTextFormat_VertexLayoutBit |
+ GrDrawTarget::StageTexCoordVertexLayoutBit(kGlyphMaskStage, 0);
+
+ int stageMask = paint.getActiveStageMask();
+ if (stageMask) {
+ GrMatrix inverseViewMatrix;
+ if (fOrigViewMatrix.invert(&inverseViewMatrix)) {
+ fDrawTarget->preConcatSamplerMatrices(stageMask,
+ inverseViewMatrix);
+ }
+ for (int i = 0; i < GrPaint::kTotalStages; ++i) {
+ if ((1 << i) & stageMask) {
+ fVertexLayout |=
+ GrDrawTarget::StagePosAsTexCoordVertexLayoutBit(i);
+ GrAssert(i != kGlyphMaskStage);
+ }
+ }
+ }
+
}
GrTextContext::~GrTextContext() {
diff --git a/src/gpu/SkGpuDevice.cpp b/src/gpu/SkGpuDevice.cpp
index 508e493..624cc68 100644
--- a/src/gpu/SkGpuDevice.cpp
+++ b/src/gpu/SkGpuDevice.cpp
@@ -40,6 +40,13 @@
#define CHECK_SHOULD_DRAW(draw) this->prepareRenderTarget(draw)
#endif
+// we use the same texture slot on GrPaint for bitmaps and shaders
+// (since drawBitmap, drawSprite, and drawDevice ignore skia's shader)
+enum {
+ kBitmapTextureIdx = 0,
+ kShaderTextureIdx = 0
+};
+
///////////////////////////////////////////////////////////////////////////////
SkGpuDevice::SkAutoCachedTexture::
@@ -316,7 +323,7 @@
bool SkGpuDevice::bindDeviceAsTexture(GrPaint* paint) {
if (NULL != fTexture) {
- paint->setTexture(fTexture);
+ paint->setTexture(kBitmapTextureIdx, fTexture);
return true;
}
return false;
@@ -371,7 +378,7 @@
GrAssert(!constantColor);
} else {
grPaint->fColor = SkGr::SkColor2GrColor(skPaint.getColor());
- grPaint->setTexture(NULL);
+ grPaint->setTexture(kShaderTextureIdx, NULL);
}
SkColorFilter* colorFilter = skPaint.getColorFilter();
SkColor color;
@@ -423,26 +430,27 @@
SkDebugf("shader->asABitmap() == kNone_BitmapType\n");
return false;
}
- grPaint->fSampler.setSampleMode(sampleMode);
+ GrSamplerState* sampler = grPaint->getTextureSampler(kShaderTextureIdx);
+ sampler->setSampleMode(sampleMode);
if (skPaint.isFilterBitmap()) {
- grPaint->fSampler.setFilter(GrSamplerState::kBilinear_Filter);
+ sampler->setFilter(GrSamplerState::kBilinear_Filter);
} else {
- grPaint->fSampler.setFilter(GrSamplerState::kNearest_Filter);
+ sampler->setFilter(GrSamplerState::kNearest_Filter);
}
- grPaint->fSampler.setWrapX(sk_tile_mode_to_grwrap(tileModes[0]));
- grPaint->fSampler.setWrapY(sk_tile_mode_to_grwrap(tileModes[1]));
+ sampler->setWrapX(sk_tile_mode_to_grwrap(tileModes[0]));
+ sampler->setWrapY(sk_tile_mode_to_grwrap(tileModes[1]));
if (GrSamplerState::kRadial2_SampleMode == sampleMode) {
- grPaint->fSampler.setRadial2Params(twoPointParams[0],
- twoPointParams[1],
- twoPointParams[2] < 0);
+ sampler->setRadial2Params(twoPointParams[0],
+ twoPointParams[1],
+ twoPointParams[2] < 0);
}
- GrTexture* texture = act->set(this, bitmap, grPaint->fSampler);
+ GrTexture* texture = act->set(this, bitmap, *sampler);
if (NULL == texture) {
SkDebugf("Couldn't convert bitmap to texture.\n");
return false;
}
- grPaint->setTexture(texture);
+ grPaint->setTexture(kShaderTextureIdx, texture);
// since our texture coords will be in local space, we wack the texture
// matrix to map them back into 0...1 before we load it
@@ -461,7 +469,7 @@
GrScalar s = GrFixedToScalar(GR_Fixed1 / bitmap.width());
matrix.postScale(s, s);
}
- grPaint->fSampler.setMatrix(matrix);
+ sampler->setMatrix(matrix);
return true;
}
@@ -737,6 +745,9 @@
// 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 = context->getMatrix();
+
GrAutoMatrix avm(context, GrMatrix::I());
const GrTextureDesc desc = {
@@ -753,18 +764,29 @@
return false;
}
- grp->setTexture(texture);
+ 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(NULL == grp->getMask(MASK_IDX));
+ grp->setMask(MASK_IDX, texture);
texture->unref();
- grp->fSampler.setClampNoFilter();
+ grp->getMaskSampler(MASK_IDX)->setClampNoFilter();
GrRect d;
d.setLTRB(GrIntToScalar(dstM.fBounds.fLeft),
GrIntToScalar(dstM.fBounds.fTop),
GrIntToScalar(dstM.fBounds.fRight),
GrIntToScalar(dstM.fBounds.fBottom));
- GrRect s;
- s.setLTRB(0, 0, GR_Scalar1, GR_Scalar1);
- context->drawRectToRect(*grp, d, s);
+
+ GrMatrix m;
+ m.setTranslate(-dstM.fBounds.fLeft, -dstM.fBounds.fTop);
+ m.postIDiv(dstM.fBounds.width(), dstM.fBounds.height());
+ grp->getMaskSampler(MASK_IDX)->setMatrix(m);
+
+ context->drawRect(*grp, d);
return true;
}
@@ -881,12 +903,12 @@
if (!this->skPaint2GrPaintNoShader(paint, true, &grPaint, false)) {
return;
}
+ GrSamplerState* sampler = grPaint.getTextureSampler(kBitmapTextureIdx);
if (paint.isFilterBitmap()) {
- grPaint.fSampler.setFilter(GrSamplerState::kBilinear_Filter);
+ sampler->setFilter(GrSamplerState::kBilinear_Filter);
} else {
- grPaint.fSampler.setFilter(GrSamplerState::kNearest_Filter);
+ sampler->setFilter(GrSamplerState::kNearest_Filter);
}
-
const int maxTextureDim = fContext->getMaxTextureDimension();
if (bitmap.getTexture() || (bitmap.width() <= maxTextureDim &&
@@ -968,18 +990,20 @@
return;
}
- grPaint->fSampler.setWrapX(GrSamplerState::kClamp_WrapMode);
- grPaint->fSampler.setWrapY(GrSamplerState::kClamp_WrapMode);
- grPaint->fSampler.setSampleMode(GrSamplerState::kNormal_SampleMode);
- grPaint->fSampler.setMatrix(GrMatrix::I());
+ GrSamplerState* sampler = grPaint->getTextureSampler(kBitmapTextureIdx);
+
+ sampler->setWrapX(GrSamplerState::kClamp_WrapMode);
+ sampler->setWrapY(GrSamplerState::kClamp_WrapMode);
+ sampler->setSampleMode(GrSamplerState::kNormal_SampleMode);
+ sampler->setMatrix(GrMatrix::I());
GrTexture* texture;
- SkAutoCachedTexture act(this, bitmap, grPaint->fSampler, &texture);
+ SkAutoCachedTexture act(this, bitmap, *sampler, &texture);
if (NULL == texture) {
return;
}
- grPaint->setTexture(texture);
+ grPaint->setTexture(kShaderTextureIdx, texture);
GrRect dstRect = SkRect::MakeWH(GrIntToScalar(srcRect.width()),
GrIntToScalar(srcRect.height()));
@@ -989,9 +1013,9 @@
GrFixedToScalar((srcRect.fRight << 16) / bitmap.width()),
GrFixedToScalar((srcRect.fBottom << 16) / bitmap.height()));
- if (GrSamplerState::kNearest_Filter != grPaint->fSampler.getFilter() &&
+ if (GrSamplerState::kNearest_Filter != sampler->getFilter() &&
(srcRect.width() < bitmap.width() ||
- srcRect.height() < bitmap.height())) {
+ srcRect.height() < bitmap.height())) {
// If drawing a subrect of the bitmap and filtering is enabled,
// use a constrained texture domain to avoid color bleeding
GrScalar left, top, right, bottom;
@@ -1011,7 +1035,7 @@
}
GrRect textureDomain;
textureDomain.setLTRB(left, top, right, bottom);
- grPaint->fSampler.setTextureDomain(textureDomain);
+ sampler->setTextureDomain(textureDomain);
}
fContext->drawRectToRect(*grPaint, dstRect, paintRect, &m);
@@ -1033,11 +1057,13 @@
GrAutoMatrix avm(fContext, GrMatrix::I());
- GrTexture* texture;
- grPaint.fSampler.setClampNoFilter();
- SkAutoCachedTexture act(this, bitmap, grPaint.fSampler, &texture);
+ GrSamplerState* sampler = grPaint.getTextureSampler(kBitmapTextureIdx);
- grPaint.setTexture(texture);
+ GrTexture* texture;
+ sampler->setClampNoFilter();
+ SkAutoCachedTexture act(this, bitmap, *sampler, &texture);
+
+ grPaint.setTexture(kBitmapTextureIdx, texture);
fContext->drawRectToRect(grPaint,
GrRect::MakeXYWH(GrIntToScalar(left),
@@ -1057,7 +1083,7 @@
return;
}
- SkASSERT(NULL != grPaint.getTexture());
+ SkASSERT(NULL != grPaint.getTexture(0));
const SkBitmap& bm = dev->accessBitmap(false);
int w = bm.width();
@@ -1065,7 +1091,7 @@
GrAutoMatrix avm(fContext, GrMatrix::I());
- grPaint.fSampler.setClampNoFilter();
+ grPaint.getTextureSampler(kBitmapTextureIdx)->setClampNoFilter();
fContext->drawRectToRect(grPaint,
GrRect::MakeXYWH(GrIntToScalar(x),