# quality improvements to imagemagnifier GM
imagemagnifier
+#joshualitt
+textblobshader
+coloremoji
+
#reed
modecolorfilters
#include "gm.h"
#include "Resources.h"
+#include "SkBlurImageFilter.h"
+#include "SkColorFilterImageFilter.h"
+#include "SkColorMatrixFilter.h"
#include "SkCanvas.h"
+#include "SkGradientShader.h"
#include "SkStream.h"
#include "SkTypeface.h"
+/*
+ * Spits out a dummy gradient to test blur with shader on paint
+ */
+static SkShader* MakeLinear() {
+ static const SkPoint kPts[] = { { 0, 0 }, { 32, 32 } };
+ static const SkScalar kPos[] = { 0, SK_Scalar1/2, SK_Scalar1 };
+ static const SkColor kColors[] = {0x80F00080, 0xF0F08000, 0x800080F0 };
+ return SkGradientShader::CreateLinear(kPts, kColors, kPos,
+ SK_ARRAY_COUNT(kColors), SkShader::kClamp_TileMode);
+}
+
+static SkImageFilter* make_grayscale(SkImageFilter* input = NULL) {
+ SkScalar matrix[20];
+ memset(matrix, 0, 20 * sizeof(SkScalar));
+ matrix[0] = matrix[5] = matrix[10] = 0.2126f;
+ matrix[1] = matrix[6] = matrix[11] = 0.7152f;
+ matrix[2] = matrix[7] = matrix[12] = 0.0722f;
+ matrix[18] = 1.0f;
+ SkAutoTUnref<SkColorFilter> filter(SkColorMatrixFilter::Create(matrix));
+ return SkColorFilterImageFilter::Create(filter, input);
+}
+
+static SkImageFilter* make_blur(float amount, SkImageFilter* input = NULL) {
+ return SkBlurImageFilter::Create(amount, amount, input);
+}
+
namespace skiagm {
class ColorEmojiGM : public GM {
}
virtual SkISize onISize() {
- return SkISize::Make(640, 480);
+ return SkISize::Make(650, 480);
}
virtual void onDraw(SkCanvas* canvas) {
const char* text = "hamburgerfons";
// draw text at different point sizes
- const int textSize[] = { 10, 30, 50 };
- const int textYOffset[] = { 10, 40, 100};
+ const int textSize[] = { 10, 30, 50, };
+ const int textYOffset[] = { 10, 40, 100, };
SkASSERT(sizeof(textSize) == sizeof(textYOffset));
- for (size_t y = 0; y < sizeof(textSize) / sizeof(int); ++y) {
+ size_t y_offset = 0;
+ for (size_t y = 0; y < sizeof(textSize) / sizeof(int); y++) {
paint.setTextSize(SkIntToScalar(textSize[y]));
canvas->drawText(text, strlen(text), 10, SkIntToScalar(textYOffset[y]), paint);
+ y_offset += textYOffset[y];
+ }
+
+ // draw with shaders and image filters
+ for (int i = 0; i < 2; i++) {
+ for (int j = 0; j < 2; j++) {
+ for (int k = 0; k < 2; k++) {
+ SkPaint shaderPaint;
+ shaderPaint.setTypeface(fTypeface);
+ if (SkToBool(i)) {
+ shaderPaint.setShader(MakeLinear());
+ }
+
+ if (SkToBool(j) && SkToBool(k)) {
+ SkAutoTUnref<SkImageFilter> grayScale(make_grayscale(NULL));
+ SkAutoTUnref<SkImageFilter> blur(make_blur(3.0f, grayScale));
+ shaderPaint.setImageFilter(blur);
+ } else if (SkToBool(j)) {
+ SkAutoTUnref<SkImageFilter> blur(make_blur(3.0f, NULL));
+ shaderPaint.setImageFilter(blur);
+ } else if (SkToBool(k)) {
+ SkAutoTUnref<SkImageFilter> grayScale(make_grayscale(NULL));
+ shaderPaint.setImageFilter(grayScale);
+ }
+ shaderPaint.setTextSize(30);
+ canvas->drawText(text, strlen(text), 380, SkIntToScalar(y_offset), shaderPaint);
+ y_offset += 32;
+ }
+ }
}
// setup work needed to draw text with different clips
GrFragmentProcessor()
: INHERITED()
, fWillReadDstColor(false)
- , fWillUseInputColor(true) {}
+ , fWillUseInputColor(true)
+ , fUsesLocalCoords(false) {}
/** Implemented using GLFragmentProcessor::GenKey as described in this class's comment. */
virtual void getGLProcessorKey(const GrGLCaps& caps,
/** Will this prceossor read the source color value? */
bool willUseInputColor() const { return fWillUseInputColor; }
+ /** Do any of the coordtransforms for this processor require local coords? */
+ bool usesLocalCoords() const { return fUsesLocalCoords; }
+
/** Returns true if this and other processor conservatively draw identically. It can only return
true when the two processor are of the same subclass (i.e. they return the same object from
from getFactory()).
SkSTArray<4, const GrCoordTransform*, true> fCoordTransforms;
bool fWillReadDstColor;
bool fWillUseInputColor;
+ bool fUsesLocalCoords;
typedef GrProcessor INHERITED;
};
* DO NOT USE THESE
* TODO Remove remaining use cases and delete these
*/
- void localCoordChange(const SkMatrix& oldToNew) {
- for (int i = 0; i < fColorStages.count(); ++i) {
- fColorStages[i].localCoordChange(oldToNew);
- }
- for (int i = 0; i < fCoverageStages.count(); ++i) {
- fCoverageStages[i].localCoordChange(oldToNew);
- }
- }
-
bool localCoordChangeInverse(const SkMatrix& newToOld) {
SkMatrix oldToNew;
bool computed = false;
void initBatchTracker(GrBatchTracker* bt, const InitBT& init) const SK_OVERRIDE {
BatchTracker* local = bt->cast<BatchTracker>();
local->fInputColorType = GetColorInputType(&local->fColor, this->color(), init, false);
+ local->fUsesLocalCoords = init.fUsesLocalCoords;
}
- bool onCanMakeEqual(const GrBatchTracker& m, const GrBatchTracker& t) const SK_OVERRIDE {
+ bool onCanMakeEqual(const GrBatchTracker& m,
+ const GrGeometryProcessor& that,
+ const GrBatchTracker& t) const SK_OVERRIDE {
const BatchTracker& mine = m.cast<BatchTracker>();
const BatchTracker& theirs = t.cast<BatchTracker>();
- return CanCombineOutput(mine.fInputColorType, mine.fColor,
+ return CanCombineLocalMatrices(*this, mine.fUsesLocalCoords,
+ that, theirs.fUsesLocalCoords) &&
+ CanCombineOutput(mine.fInputColorType, mine.fColor,
theirs.fInputColorType, theirs.fColor);
}
struct BatchTracker {
GrGPInput fInputColorType;
GrColor fColor;
+ bool fUsesLocalCoords;
};
const GrAttribute* fInPosition;
} else {
local->fInputCoverageType = kIgnored_GrGPInput;
}
+
+ local->fUsesLocalCoords = init.fUsesLocalCoords;
}
- bool onCanMakeEqual(const GrBatchTracker& m, const GrBatchTracker& t) const SK_OVERRIDE {
+ bool onCanMakeEqual(const GrBatchTracker& m,
+ const GrGeometryProcessor& that,
+ const GrBatchTracker& t) const SK_OVERRIDE {
const BatchTracker& mine = m.cast<BatchTracker>();
const BatchTracker& theirs = t.cast<BatchTracker>();
- return CanCombineOutput(mine.fInputColorType, mine.fColor,
+ return CanCombineLocalMatrices(*this, mine.fUsesLocalCoords,
+ that, theirs.fUsesLocalCoords) &&
+ CanCombineOutput(mine.fInputColorType, mine.fColor,
theirs.fInputColorType, theirs.fColor) &&
CanCombineOutput(mine.fInputCoverageType, mine.fCoverage,
theirs.fInputCoverageType, theirs.fCoverage);
GrGPInput fInputCoverageType;
GrColor fColor;
GrColor fCoverage;
+ bool fUsesLocalCoords;
};
const GrAttribute* fInPosition;
GrGPInput fInputColorType;
GrGPInput fInputCoverageType;
GrColor fColor;
+ bool fUsesLocalCoords;
};
class GrGLPathProcessor : public GrGLGeometryProcessor {
typedef GrGLGeometryProcessor INHERITED;
};
-GrPathProcessor::GrPathProcessor(GrColor color) : fColor(color) {
+GrPathProcessor::GrPathProcessor(GrColor color, const SkMatrix& localMatrix)
+ : INHERITED(localMatrix)
+ , fColor(color) {
this->initClassID<GrPathProcessor>();
}
}
local->fInputCoverageType = init.fCoverageIgnored ? kIgnored_GrGPInput : kAllOnes_GrGPInput;
+ local->fUsesLocalCoords = init.fUsesLocalCoords;
}
bool GrPathProcessor::canMakeEqual(const GrBatchTracker& m,
const PathBatchTracker& mine = m.cast<PathBatchTracker>();
const PathBatchTracker& theirs = t.cast<PathBatchTracker>();
- return CanCombineOutput(mine.fInputColorType, mine.fColor,
+ return CanCombineLocalMatrices(*this, mine.fUsesLocalCoords,
+ that, theirs.fUsesLocalCoords) &&
+ CanCombineOutput(mine.fInputColorType, mine.fColor,
theirs.fInputColorType, theirs.fColor) &&
CanCombineOutput(mine.fInputCoverageType, 0xff,
theirs.fInputCoverageType, 0xff);
*/
class GrPrimitiveProcessor : public GrProcessor {
public:
+ // TODO let the PrimProc itself set this in its setData call, this should really live on the
+ // bundle of primitive data
+ const SkMatrix& localMatrix() const { return fLocalMatrix; }
+
/*
* This struct allows the optstate to communicate requirements to the GrPrimitiveProcessor.
*/
bool fColorIgnored;
bool fCoverageIgnored;
GrColor fOverrideColor;
+ bool fUsesLocalCoords;
};
virtual void initBatchTracker(GrBatchTracker*, const InitBT&) const = 0;
virtual GrGLGeometryProcessor* createGLInstance(const GrBatchTracker& bt) const = 0;
protected:
+ GrPrimitiveProcessor(const SkMatrix& localMatrix) : fLocalMatrix(localMatrix) {}
+
/*
* CanCombineOutput will return true if two draws are 'batchable' from a color perspective.
* TODO remove this when GPs can upgrade to attribute color
return true;
}
+ static bool CanCombineLocalMatrices(const GrPrimitiveProcessor& left,
+ bool leftUsesLocalCoords,
+ const GrPrimitiveProcessor& right,
+ bool rightUsesLocalCoords) {
+ if (leftUsesLocalCoords != rightUsesLocalCoords) {
+ return false;
+ }
+
+ if (leftUsesLocalCoords && !left.localMatrix().cheapEqualTo(right.localMatrix())) {
+ return false;
+ }
+ return true;
+ }
+
private:
+ SkMatrix fLocalMatrix;
+
typedef GrProcessor INHERITED;
};
public:
// TODO the Hint can be handled in a much more clean way when we have deferred geometry or
// atleast bundles
- GrGeometryProcessor(GrColor color, bool opaqueVertexColors = false)
- : fVertexStride(0)
+ GrGeometryProcessor(GrColor color,
+ bool opaqueVertexColors = false,
+ const SkMatrix& localMatrix = SkMatrix::I())
+ : INHERITED(localMatrix)
+ , fVertexStride(0)
, fColor(color)
, fOpaqueVertexColors(opaqueVertexColors)
, fWillUseGeoShader(false)
return false;
}
- return this->onCanMakeEqual(mine, theirs);
+ return this->onCanMakeEqual(mine, other, theirs);
}
virtual void onGetInvariantOutputCoverage(GrInitInvariantOutput*) const = 0;
private:
- virtual bool onCanMakeEqual(const GrBatchTracker& mine, const GrBatchTracker& theirs) const = 0;
+ virtual bool onCanMakeEqual(const GrBatchTracker& mine,
+ const GrGeometryProcessor& that,
+ const GrBatchTracker& theirs) const = 0;
// TODO delete this when we have more advanced equality testing via bundles and the BT
virtual bool onIsEqual(const GrGeometryProcessor&) const = 0;
bool fHasVertexColor;
bool fHasLocalCoords;
- typedef GrProcessor INHERITED;
+ typedef GrPrimitiveProcessor INHERITED;
};
/*
*/
class GrPathProcessor : public GrPrimitiveProcessor {
public:
- static GrPathProcessor* Create(GrColor color) {
- return SkNEW_ARGS(GrPathProcessor, (color));
+ static GrPathProcessor* Create(GrColor color, const SkMatrix& localMatrix = SkMatrix::I()) {
+ return SkNEW_ARGS(GrPathProcessor, (color, localMatrix));
}
void initBatchTracker(GrBatchTracker*, const InitBT&) const SK_OVERRIDE;
virtual GrGLGeometryProcessor* createGLInstance(const GrBatchTracker& bt) const SK_OVERRIDE;
private:
- GrPathProcessor(GrColor color);
+ GrPathProcessor(GrColor color, const SkMatrix& localMatrix);
GrColor fColor;
- typedef GrProcessor INHERITED;
+ typedef GrPrimitiveProcessor INHERITED;
};
#endif
fDescInfo.fRequiresLocalCoordAttrib = hasLocalCoords;
+ bool usesLocalCoords = false;
+
// Copy Stages from DS to ODS
for (int i = firstColorStageIdx; i < drawState.numColorStages(); ++i) {
SkNEW_APPEND_TO_TARRAY(&fFragmentStages,
GrPendingFragmentStage,
(drawState.fColorStages[i], hasLocalCoords));
+ usesLocalCoords = usesLocalCoords ||
+ drawState.fColorStages[i].getProcessor()->usesLocalCoords();
}
fNumColorStages = fFragmentStages.count();
SkNEW_APPEND_TO_TARRAY(&fFragmentStages,
GrPendingFragmentStage,
(drawState.fCoverageStages[i], hasLocalCoords));
+ usesLocalCoords = usesLocalCoords ||
+ drawState.fCoverageStages[i].getProcessor()->usesLocalCoords();
}
// let the GP init the batch tracker
init.fColorIgnored = SkToBool(optFlags & GrXferProcessor::kIgnoreColor_OptFlag);
init.fOverrideColor = init.fColorIgnored ? GrColor_ILLEGAL : overrideColor;
init.fCoverageIgnored = SkToBool(optFlags & GrXferProcessor::kIgnoreCoverage_OptFlag);
+ init.fUsesLocalCoords = usesLocalCoords;
fPrimitiveProcessor->initBatchTracker(&fBatchTracker, init);
}
void initBatchTracker(GrBatchTracker* bt, const InitBT& init) const SK_OVERRIDE {
BatchTracker* local = bt->cast<BatchTracker>();
local->fInputColorType = GetColorInputType(&local->fColor, this->color(), init, false);
-
+ local->fUsesLocalCoords = init.fUsesLocalCoords;
}
- bool onCanMakeEqual(const GrBatchTracker& m, const GrBatchTracker& t) const SK_OVERRIDE {
+ bool onCanMakeEqual(const GrBatchTracker& m,
+ const GrGeometryProcessor& that,
+ const GrBatchTracker& t) const SK_OVERRIDE {
const BatchTracker& mine = m.cast<BatchTracker>();
const BatchTracker& theirs = t.cast<BatchTracker>();
- return CanCombineOutput(mine.fInputColorType, mine.fColor,
+ return CanCombineLocalMatrices(*this, mine.fUsesLocalCoords,
+ that, theirs.fUsesLocalCoords) &&
+ CanCombineOutput(mine.fInputColorType, mine.fColor,
theirs.fInputColorType, theirs.fColor);
}
struct BatchTracker {
GrGPInput fInputColorType;
GrColor fColor;
+ bool fUsesLocalCoords;
};
const GrAttribute* fInPosition;
void initBatchTracker(GrBatchTracker* bt, const InitBT& init) const SK_OVERRIDE {
BatchTracker* local = bt->cast<BatchTracker>();
local->fInputColorType = GetColorInputType(&local->fColor, this->color(), init, false);
+ local->fUsesLocalCoords = init.fUsesLocalCoords;
}
- bool onCanMakeEqual(const GrBatchTracker& m, const GrBatchTracker& t) const SK_OVERRIDE {
+ bool onCanMakeEqual(const GrBatchTracker& m,
+ const GrGeometryProcessor& that,
+ const GrBatchTracker& t) const SK_OVERRIDE {
const BatchTracker& mine = m.cast<BatchTracker>();
const BatchTracker& theirs = t.cast<BatchTracker>();
- return CanCombineOutput(mine.fInputColorType, mine.fColor,
+ return CanCombineLocalMatrices(*this, mine.fUsesLocalCoords,
+ that, theirs.fUsesLocalCoords) &&
+ CanCombineOutput(mine.fInputColorType, mine.fColor,
theirs.fInputColorType, theirs.fColor);
}
struct BatchTracker {
GrGPInput fInputColorType;
GrColor fColor;
+ bool fUsesLocalCoords;
};
const GrAttribute* fInPosition;
void initBatchTracker(GrBatchTracker* bt, const InitBT& init) const SK_OVERRIDE {
BatchTracker* local = bt->cast<BatchTracker>();
local->fInputColorType = GetColorInputType(&local->fColor, this->color(), init, false);
+ local->fUsesLocalCoords = init.fUsesLocalCoords;
}
- bool onCanMakeEqual(const GrBatchTracker& m, const GrBatchTracker& t) const SK_OVERRIDE {
+ bool onCanMakeEqual(const GrBatchTracker& m,
+ const GrGeometryProcessor& that,
+ const GrBatchTracker& t) const SK_OVERRIDE {
const BatchTracker& mine = m.cast<BatchTracker>();
const BatchTracker& theirs = t.cast<BatchTracker>();
- return CanCombineOutput(mine.fInputColorType, mine.fColor,
+ return CanCombineLocalMatrices(*this, mine.fUsesLocalCoords,
+ that, theirs.fUsesLocalCoords) &&
+ CanCombineOutput(mine.fInputColorType, mine.fColor,
theirs.fInputColorType, theirs.fColor);
}
struct BatchTracker {
GrGPInput fInputColorType;
GrColor fColor;
+ bool fUsesLocalCoords;
};
const GrAttribute* fInPosition;
void GrFragmentProcessor::addCoordTransform(const GrCoordTransform* transform) {
fCoordTransforms.push_back(transform);
+ fUsesLocalCoords = fUsesLocalCoords || transform->sourceCoords() == kLocal_GrCoordSet;
SkDEBUGCODE(transform->setInProcessor();)
}
fContextInitialMatrix = viewMatrix;
fViewMatrix = viewMatrix;
+ fLocalMatrix = SkMatrix::I();
const bool otherBackendsWillDrawAsPaths =
SkDraw::ShouldDrawTextAsPaths(skPaint, fContextInitialMatrix);
// the paint preConcats the inverse.
m = fContextInitialMatrix;
m.postScale(1, -1);
- fPaint.localCoordChangeInverse(m);
+ if (!m.invert(&fLocalMatrix)) {
+ SkDebugf("Not invertible!\n");
+ return;
+ }
fGlyphCache = fSkPaint.detachCache(&fDeviceProperties, &fContextInitialMatrix,
true /*ignoreGamma*/);
SkMatrix textMatrix;
// Glyphs loaded by GPU path rendering have an inverted y-direction.
textMatrix.setScale(fTextRatio, -fTextRatio);
- fPaint.localCoordChange(textMatrix);
fViewMatrix.preConcat(textMatrix);
+ fLocalMatrix = textMatrix;
fGlyphCache = fSkPaint.detachCache(&fDeviceProperties, NULL, true /*ignoreGamma*/);
fGlyphs = canUseRawPaths ?
void GrStencilAndCoverTextContext::flush() {
if (fQueuedGlyphCount > 0) {
- SkAutoTUnref<GrPathProcessor> pp(GrPathProcessor::Create(fPaint.getColor()));
+ SkAutoTUnref<GrPathProcessor> pp(GrPathProcessor::Create(fPaint.getColor(), fLocalMatrix));
fDrawTarget->drawPaths(&fDrawState, pp, fGlyphs,
fGlyphIndices, GrPathRange::kU16_PathIndexType,
get_xy_scalar_array(fGlyphPositions),
SkMatrix inverse;
if (this->mapToFallbackContext(&inverse)) {
- paintFallback.localCoordChangeInverse(inverse);
inverse.mapPoints(&fGlyphPositions[fFallbackGlyphsIdx], fallbackGlyphCount);
}
int fFallbackGlyphsIdx;
SkMatrix fContextInitialMatrix;
SkMatrix fViewMatrix;
+ SkMatrix fLocalMatrix;
bool fUsingDeviceSpaceGlyphs;
GrStencilAndCoverTextContext(GrContext*, const SkDeviceProperties&);
GrGPInput fInputColorType;
GrColor fColor;
uint8_t fCoverageScale;
+ bool fUsesLocalCoords;
};
class GrGLConicEffect : public GrGLGeometryProcessor {
ConicBatchTracker* local = bt->cast<ConicBatchTracker>();
local->fInputColorType = GetColorInputType(&local->fColor, this->color(), init, false);
local->fCoverageScale = fCoverageScale;
+ local->fUsesLocalCoords = init.fUsesLocalCoords;
}
-bool GrConicEffect::onCanMakeEqual(const GrBatchTracker& m, const GrBatchTracker& t) const {
+bool GrConicEffect::onCanMakeEqual(const GrBatchTracker& m,
+ const GrGeometryProcessor& that,
+ const GrBatchTracker& t) const {
const ConicBatchTracker& mine = m.cast<ConicBatchTracker>();
const ConicBatchTracker& theirs = t.cast<ConicBatchTracker>();
- return CanCombineOutput(mine.fInputColorType, mine.fColor,
+ return CanCombineLocalMatrices(*this, mine.fUsesLocalCoords,
+ that, theirs.fUsesLocalCoords) &&
+ CanCombineOutput(mine.fInputColorType, mine.fColor,
theirs.fInputColorType, theirs.fColor) &&
mine.fCoverageScale == theirs.fCoverageScale;
}
GrGPInput fInputColorType;
GrColor fColor;
uint8_t fCoverageScale;
+ bool fUsesLocalCoords;
};
class GrGLQuadEffect : public GrGLGeometryProcessor {
QuadBatchTracker* local = bt->cast<QuadBatchTracker>();
local->fInputColorType = GetColorInputType(&local->fColor, this->color(), init, false);
local->fCoverageScale = fCoverageScale;
+ local->fUsesLocalCoords = init.fUsesLocalCoords;
}
-bool GrQuadEffect::onCanMakeEqual(const GrBatchTracker& m, const GrBatchTracker& t) const {
+bool GrQuadEffect::onCanMakeEqual(const GrBatchTracker& m,
+ const GrGeometryProcessor& that,
+ const GrBatchTracker& t) const {
const QuadBatchTracker& mine = m.cast<QuadBatchTracker>();
const QuadBatchTracker& theirs = t.cast<QuadBatchTracker>();
- return CanCombineOutput(mine.fInputColorType, mine.fColor,
+ return CanCombineLocalMatrices(*this, mine.fUsesLocalCoords,
+ that, theirs.fUsesLocalCoords) &&
+ CanCombineOutput(mine.fInputColorType, mine.fColor,
theirs.fInputColorType, theirs.fColor) &&
mine.fCoverageScale == theirs.fCoverageScale;
}
struct CubicBatchTracker {
GrGPInput fInputColorType;
GrColor fColor;
+ bool fUsesLocalCoords;
};
class GrGLCubicEffect : public GrGLGeometryProcessor {
void GrCubicEffect::initBatchTracker(GrBatchTracker* bt, const InitBT& init) const {
CubicBatchTracker* local = bt->cast<CubicBatchTracker>();
local->fInputColorType = GetColorInputType(&local->fColor, this->color(), init, false);
+ local->fUsesLocalCoords = init.fUsesLocalCoords;
}
-bool GrCubicEffect::onCanMakeEqual(const GrBatchTracker& m, const GrBatchTracker& t) const {
+bool GrCubicEffect::onCanMakeEqual(const GrBatchTracker& m,
+ const GrGeometryProcessor& that,
+ const GrBatchTracker& t) const {
const CubicBatchTracker& mine = m.cast<CubicBatchTracker>();
const CubicBatchTracker& theirs = t.cast<CubicBatchTracker>();
- return CanCombineOutput(mine.fInputColorType, mine.fColor,
+ return CanCombineLocalMatrices(*this, mine.fUsesLocalCoords,
+ that, theirs.fUsesLocalCoords) &&
+ CanCombineOutput(mine.fInputColorType, mine.fColor,
theirs.fInputColorType, theirs.fColor);
}
virtual GrGLGeometryProcessor* createGLInstance(const GrBatchTracker& bt) const SK_OVERRIDE;
void initBatchTracker(GrBatchTracker*, const InitBT&) const SK_OVERRIDE;
- bool onCanMakeEqual(const GrBatchTracker&, const GrBatchTracker&) const SK_OVERRIDE;
+ bool onCanMakeEqual(const GrBatchTracker&,
+ const GrGeometryProcessor&,
+ const GrBatchTracker&) const SK_OVERRIDE;
private:
GrConicEffect(GrColor, uint8_t coverage, GrPrimitiveEdgeType);
virtual GrGLGeometryProcessor* createGLInstance(const GrBatchTracker& bt) const SK_OVERRIDE;
void initBatchTracker(GrBatchTracker*, const InitBT&) const SK_OVERRIDE;
- bool onCanMakeEqual(const GrBatchTracker&, const GrBatchTracker&) const SK_OVERRIDE;
+ bool onCanMakeEqual(const GrBatchTracker&,
+ const GrGeometryProcessor&,
+ const GrBatchTracker&) const SK_OVERRIDE;
private:
GrQuadEffect(GrColor, uint8_t coverage, GrPrimitiveEdgeType);
virtual GrGLGeometryProcessor* createGLInstance(const GrBatchTracker& bt) const SK_OVERRIDE;
void initBatchTracker(GrBatchTracker*, const InitBT&) const SK_OVERRIDE;
- bool onCanMakeEqual(const GrBatchTracker&, const GrBatchTracker&) const SK_OVERRIDE;
+ bool onCanMakeEqual(const GrBatchTracker&,
+ const GrGeometryProcessor&,
+ const GrBatchTracker&) const SK_OVERRIDE;
private:
GrCubicEffect(GrColor, GrPrimitiveEdgeType);
struct BitmapTextBatchTracker {
GrGPInput fInputColorType;
GrColor fColor;
+ bool fUsesLocalCoords;
};
class GrGLBitmapTextGeoProc : public GrGLGeometryProcessor {
BitmapTextBatchTracker* local = bt->cast<BitmapTextBatchTracker>();
local->fInputColorType = GetColorInputType(&local->fColor, this->color(), init,
SkToBool(fInColor));
+ local->fUsesLocalCoords = init.fUsesLocalCoords;
}
-bool GrBitmapTextGeoProc::onCanMakeEqual(const GrBatchTracker& m, const GrBatchTracker& t) const {
+bool GrBitmapTextGeoProc::onCanMakeEqual(const GrBatchTracker& m,
+ const GrGeometryProcessor& that,
+ const GrBatchTracker& t) const {
const BitmapTextBatchTracker& mine = m.cast<BitmapTextBatchTracker>();
const BitmapTextBatchTracker& theirs = t.cast<BitmapTextBatchTracker>();
- return CanCombineOutput(mine.fInputColorType, mine.fColor,
+ return CanCombineLocalMatrices(*this, mine.fUsesLocalCoords,
+ that, theirs.fUsesLocalCoords) &&
+ CanCombineOutput(mine.fInputColorType, mine.fColor,
theirs.fInputColorType, theirs.fColor);
}
virtual GrGLGeometryProcessor* createGLInstance(const GrBatchTracker& bt) const SK_OVERRIDE;
void initBatchTracker(GrBatchTracker*, const InitBT&) const SK_OVERRIDE;
- bool onCanMakeEqual(const GrBatchTracker&, const GrBatchTracker&) const SK_OVERRIDE;
+ bool onCanMakeEqual(const GrBatchTracker&,
+ const GrGeometryProcessor&,
+ const GrBatchTracker&) const SK_OVERRIDE;
private:
GrBitmapTextGeoProc(GrColor, GrTexture* texture, const GrTextureParams& params,
struct DashingCircleBatchTracker {
GrGPInput fInputColorType;
GrColor fColor;
+ bool fUsesLocalCoords;
};
/*
void initBatchTracker(GrBatchTracker* bt, const InitBT& init) const SK_OVERRIDE;
- bool onCanMakeEqual(const GrBatchTracker&, const GrBatchTracker&) const SK_OVERRIDE;
+ bool onCanMakeEqual(const GrBatchTracker&,
+ const GrGeometryProcessor&,
+ const GrBatchTracker&) const SK_OVERRIDE;
private:
DashingCircleEffect(GrColor, GrPrimitiveEdgeType edgeType, const DashInfo& info,
void DashingCircleEffect::initBatchTracker(GrBatchTracker* bt, const InitBT& init) const {
DashingCircleBatchTracker* local = bt->cast<DashingCircleBatchTracker>();
local->fInputColorType = GetColorInputType(&local->fColor, this->color(), init, false);
+ local->fUsesLocalCoords = init.fUsesLocalCoords;
}
-bool DashingCircleEffect::onCanMakeEqual(const GrBatchTracker& m, const GrBatchTracker& t) const {
+bool DashingCircleEffect::onCanMakeEqual(const GrBatchTracker& m,
+ const GrGeometryProcessor& that,
+ const GrBatchTracker& t) const {
const DashingCircleBatchTracker& mine = m.cast<DashingCircleBatchTracker>();
const DashingCircleBatchTracker& theirs = t.cast<DashingCircleBatchTracker>();
- return CanCombineOutput(mine.fInputColorType, mine.fColor,
+ return CanCombineLocalMatrices(*this, mine.fUsesLocalCoords,
+ that, theirs.fUsesLocalCoords) &&
+ CanCombineOutput(mine.fInputColorType, mine.fColor,
theirs.fInputColorType, theirs.fColor);
}
struct DashingLineBatchTracker {
GrGPInput fInputColorType;
GrColor fColor;
+ bool fUsesLocalCoords;
};
/*
void initBatchTracker(GrBatchTracker* bt, const InitBT& init) const SK_OVERRIDE;
- bool onCanMakeEqual(const GrBatchTracker&, const GrBatchTracker&) const SK_OVERRIDE;
+ bool onCanMakeEqual(const GrBatchTracker&,
+ const GrGeometryProcessor&,
+ const GrBatchTracker&) const SK_OVERRIDE;
private:
DashingLineEffect(GrColor, GrPrimitiveEdgeType edgeType, const DashInfo& info,
void DashingLineEffect::initBatchTracker(GrBatchTracker* bt, const InitBT& init) const {
DashingLineBatchTracker* local = bt->cast<DashingLineBatchTracker>();
local->fInputColorType = GetColorInputType(&local->fColor, this->color(), init, false);
+ local->fUsesLocalCoords = init.fUsesLocalCoords;
}
-bool DashingLineEffect::onCanMakeEqual(const GrBatchTracker& m, const GrBatchTracker& t) const {
+bool DashingLineEffect::onCanMakeEqual(const GrBatchTracker& m,
+ const GrGeometryProcessor& that,
+ const GrBatchTracker& t) const {
const DashingLineBatchTracker& mine = m.cast<DashingLineBatchTracker>();
const DashingLineBatchTracker& theirs = t.cast<DashingLineBatchTracker>();
- return CanCombineOutput(mine.fInputColorType, mine.fColor,
+ return CanCombineLocalMatrices(*this, mine.fUsesLocalCoords,
+ that, theirs.fUsesLocalCoords) &&
+ CanCombineOutput(mine.fInputColorType, mine.fColor,
theirs.fInputColorType, theirs.fColor);
}
struct DistanceFieldBatchTracker {
GrGPInput fInputColorType;
GrColor fColor;
+ bool fUsesLocalCoords;
};
class GrGLDistanceFieldTextureEffect : public GrGLGeometryProcessor {
DistanceFieldBatchTracker* local = bt->cast<DistanceFieldBatchTracker>();
local->fInputColorType = GetColorInputType(&local->fColor, this->color(), init,
SkToBool(fInColor));
+ local->fUsesLocalCoords = init.fUsesLocalCoords;
}
bool GrDistanceFieldTextureEffect::onCanMakeEqual(const GrBatchTracker& m,
+ const GrGeometryProcessor& that,
const GrBatchTracker& t) const {
const DistanceFieldBatchTracker& mine = m.cast<DistanceFieldBatchTracker>();
const DistanceFieldBatchTracker& theirs = t.cast<DistanceFieldBatchTracker>();
- return CanCombineOutput(mine.fInputColorType, mine.fColor,
+ return CanCombineLocalMatrices(*this, mine.fUsesLocalCoords,
+ that, theirs.fUsesLocalCoords) &&
+ CanCombineOutput(mine.fInputColorType, mine.fColor,
theirs.fInputColorType, theirs.fColor);
}
struct DistanceFieldNoGammaBatchTracker {
GrGPInput fInputColorType;
GrColor fColor;
+ bool fUsesLocalCoords;
};
class GrGLDistanceFieldNoGammaTextureEffect : public GrGLGeometryProcessor {
DistanceFieldNoGammaBatchTracker* local = bt->cast<DistanceFieldNoGammaBatchTracker>();
local->fInputColorType = GetColorInputType(&local->fColor, this->color(), init,
SkToBool(fInColor));
+ local->fUsesLocalCoords = init.fUsesLocalCoords;
}
bool GrDistanceFieldNoGammaTextureEffect::onCanMakeEqual(const GrBatchTracker& m,
+ const GrGeometryProcessor& that,
const GrBatchTracker& t) const {
const DistanceFieldNoGammaBatchTracker& mine = m.cast<DistanceFieldNoGammaBatchTracker>();
const DistanceFieldNoGammaBatchTracker& theirs = t.cast<DistanceFieldNoGammaBatchTracker>();
- return CanCombineOutput(mine.fInputColorType, mine.fColor,
+ return CanCombineLocalMatrices(*this, mine.fUsesLocalCoords,
+ that, theirs.fUsesLocalCoords) &&
+ CanCombineOutput(mine.fInputColorType, mine.fColor,
theirs.fInputColorType, theirs.fColor);
}
struct DistanceFieldLCDBatchTracker {
GrGPInput fInputColorType;
GrColor fColor;
+ bool fUsesLocalCoords;
};
class GrGLDistanceFieldLCDTextureEffect : public GrGLGeometryProcessor {
const InitBT& init) const {
DistanceFieldLCDBatchTracker* local = bt->cast<DistanceFieldLCDBatchTracker>();
local->fInputColorType = GetColorInputType(&local->fColor, this->color(), init, false);
+ local->fUsesLocalCoords = init.fUsesLocalCoords;
}
bool GrDistanceFieldLCDTextureEffect::onCanMakeEqual(const GrBatchTracker& m,
+ const GrGeometryProcessor& that,
const GrBatchTracker& t) const {
const DistanceFieldLCDBatchTracker& mine = m.cast<DistanceFieldLCDBatchTracker>();
const DistanceFieldLCDBatchTracker& theirs = t.cast<DistanceFieldLCDBatchTracker>();
- return CanCombineOutput(mine.fInputColorType, mine.fColor,
+ return CanCombineLocalMatrices(*this, mine.fUsesLocalCoords,
+ that, theirs.fUsesLocalCoords) &&
+ CanCombineOutput(mine.fInputColorType, mine.fColor,
theirs.fInputColorType, theirs.fColor);
}
void initBatchTracker(GrBatchTracker* bt, const InitBT& init) const SK_OVERRIDE;
- bool onCanMakeEqual(const GrBatchTracker&, const GrBatchTracker&) const SK_OVERRIDE;
+ bool onCanMakeEqual(const GrBatchTracker&,
+ const GrGeometryProcessor&,
+ const GrBatchTracker&) const SK_OVERRIDE;
private:
GrDistanceFieldTextureEffect(GrColor, GrTexture* texture, const GrTextureParams& params,
void initBatchTracker(GrBatchTracker* bt, const InitBT& init) const SK_OVERRIDE;
- bool onCanMakeEqual(const GrBatchTracker&, const GrBatchTracker&) const SK_OVERRIDE;
+ bool onCanMakeEqual(const GrBatchTracker&,
+ const GrGeometryProcessor&,
+ const GrBatchTracker&) const SK_OVERRIDE;
private:
GrDistanceFieldNoGammaTextureEffect(GrColor, GrTexture* texture, const GrTextureParams& params,
void initBatchTracker(GrBatchTracker* bt, const InitBT& init) const SK_OVERRIDE;
- bool onCanMakeEqual(const GrBatchTracker&, const GrBatchTracker&) const SK_OVERRIDE;
+ bool onCanMakeEqual(const GrBatchTracker&,
+ const GrGeometryProcessor&,
+ const GrBatchTracker&) const SK_OVERRIDE;
private:
GrDistanceFieldLCDTextureEffect(GrColor, GrTexture* texture, const GrTextureParams& params,
/**
* Retrieves the final matrix that a transform needs to apply to its source coords.
*/
-static SkMatrix get_transform_matrix(const GrPendingFragmentStage& stage, int transformIdx) {
+static SkMatrix get_transform_matrix(const GrPendingFragmentStage& stage,
+ int transformIdx,
+ const SkMatrix& localMatrix) {
const GrCoordTransform& coordTransform = stage.getProcessor()->coordTransform(transformIdx);
SkMatrix combined;
if (kLocal_GrCoordSet == coordTransform.sourceCoords()) {
// If we have explicit local coords or are in device coords then we shouldn't need a coord
// change.
- const SkMatrix& ccm = stage.getCoordChangeMatrix();
- combined.setConcat(coordTransform.getMatrix(), ccm);
+ // TODO shortly we will get rid of coord change matrices entirely, and the PrimProc will
+ // always have a local matrix, often Identity, which can be used to transform coord
+ // transforms. Until we actually do this, we need some way for a PrimProc to say 'use my
+ // matrix' instead of the coord change mechanism. Temporarily, we have overloaded
+ // The identity matrix to be this value, ie if a primproc has an identity matrix for a
+ // local matrix then use the coord change matrix, otherwise use the matrix on the primproc
+ if (localMatrix.isIdentity()) {
+ const SkMatrix& ccm = stage.getCoordChangeMatrix();
+ combined.setConcat(coordTransform.getMatrix(), ccm);
+ } else {
+ combined.setConcat(coordTransform.getMatrix(), localMatrix);
+ }
} else {
combined = coordTransform.getMatrix();
}
const GrPendingFragmentStage& stage = optState.getFragmentStage(e);
const GrProcessor& processor = *stage.getProcessor();
fFragmentProcessors->fProcs[e]->fGLProc->setData(fProgramDataManager, processor);
- this->setTransformData(stage, fFragmentProcessors->fProcs[e]);
+ const SkMatrix& localMatrix = optState.getPrimitiveProcessor()->localMatrix();
+ this->setTransformData(stage, localMatrix, fFragmentProcessors->fProcs[e]);
this->bindTextures(fFragmentProcessors->fProcs[e], processor);
}
}
void GrGLProgram::setTransformData(const GrPendingFragmentStage& processor,
+ const SkMatrix& localMatrix,
GrGLInstalledFragProc* ip) {
SkTArray<GrGLInstalledFragProc::Transform, true>& transforms = ip->fTransforms;
int numTransforms = transforms.count();
SkASSERT(numTransforms == processor.getProcessor()->numTransforms());
for (int t = 0; t < numTransforms; ++t) {
SkASSERT(transforms[t].fHandle.isValid());
- const SkMatrix& matrix = get_transform_matrix(processor, t);
+ const SkMatrix& matrix = get_transform_matrix(processor, t, localMatrix);
if (!transforms[t].fCurrentValue.cheapEqualTo(matrix)) {
fProgramDataManager.setSkMatrix(transforms[t].fHandle.convertToUniformHandle(), matrix);
transforms[t].fCurrentValue = matrix;
}
void GrGLNvprProgram::setTransformData(const GrPendingFragmentStage& proc,
+ const SkMatrix& localMatrix,
GrGLInstalledFragProc* ip) {
SkTArray<GrGLInstalledFragProc::Transform, true>& transforms = ip->fTransforms;
int numTransforms = transforms.count();
SkASSERT(numTransforms == proc.getProcessor()->numTransforms());
for (int t = 0; t < numTransforms; ++t) {
SkASSERT(transforms[t].fHandle.isValid());
- const SkMatrix& transform = get_transform_matrix(proc, t);
+ const SkMatrix& transform = get_transform_matrix(proc, t, localMatrix);
if (transforms[t].fCurrentValue.cheapEqualTo(transform)) {
continue;
}
void
GrGLLegacyNvprProgram::setTransformData(const GrPendingFragmentStage& proc,
+ const SkMatrix& localMatrix,
GrGLInstalledFragProc* ip) {
// We've hidden the texcoord index in the first entry of the transforms array for each effect
int texCoordIndex = ip->fTransforms[0].fHandle.handle();
int numTransforms = proc.getProcessor()->numTransforms();
for (int t = 0; t < numTransforms; ++t) {
- const SkMatrix& transform = get_transform_matrix(proc, t);
+ const SkMatrix& transform = get_transform_matrix(proc, t, localMatrix);
GrGLPathRendering::PathTexGenComponents components =
GrGLPathRendering::kST_PathTexGenComponents;
if (proc.isPerspectiveCoordTransform(t)) {
// A templated helper to loop over effects, set the transforms(via subclass) and bind textures
void setFragmentData(const GrOptDrawState&);
- virtual void setTransformData(const GrPendingFragmentStage&, GrGLInstalledFragProc*);
+ virtual void setTransformData(const GrPendingFragmentStage&,
+ const SkMatrix& localMatrix,
+ GrGLInstalledFragProc*);
void bindTextures(const GrGLInstalledProc*, const GrProcessor&);
/*
const SeparableVaryingInfoArray& separableVaryings);
virtual void didSetData(GrGpu::DrawType) SK_OVERRIDE;
virtual void setTransformData(const GrPendingFragmentStage&,
+ const SkMatrix& localMatrix,
GrGLInstalledFragProc*) SK_OVERRIDE;
struct Varying {
int texCoordSetCnt);
virtual void didSetData(GrGpu::DrawType) SK_OVERRIDE;
virtual void setTransformData(const GrPendingFragmentStage&,
+ const SkMatrix& localMatrix,
GrGLInstalledFragProc*) SK_OVERRIDE;
int fTexCoordSetCnt;