Make skpaint->grpaint flow work for composing draws (verts and atlas)
One side effect is that the SkShader's (or implicit shader's) fragment processor is responsible for the transition from an unpremul paint color to a premul color.
Review URL: https://codereview.chromium.org/1348583002
diff --git a/gm/constcolorprocessor.cpp b/gm/constcolorprocessor.cpp
index 40eb1a0..539119e 100644
--- a/gm/constcolorprocessor.cpp
+++ b/gm/constcolorprocessor.cpp
@@ -15,7 +15,7 @@
#include "GrContext.h"
#include "GrTest.h"
#include "effects/GrConstColorProcessor.h"
-#include "SkGr.h"
+#include "SkGrPriv.h"
#include "SkGradientShader.h"
namespace skiagm {
@@ -104,7 +104,7 @@
} else {
skPaint.setColor(kPaintColors[paintType]);
}
- SkAssertResult(SkPaint2GrPaint(context, skPaint, viewMatrix, false, &grPaint));
+ SkAssertResult(SkPaintToGrPaint(context, skPaint, viewMatrix, &grPaint));
GrConstColorProcessor::InputMode mode = (GrConstColorProcessor::InputMode) m;
GrColor color = kColors[procColor];
diff --git a/gm/dcshader.cpp b/gm/dcshader.cpp
index 051430e..60fdddd 100644
--- a/gm/dcshader.cpp
+++ b/gm/dcshader.cpp
@@ -104,7 +104,7 @@
SkFilterQuality,
GrProcessorDataManager* procDataManager) const {
SkAutoTUnref<const GrFragmentProcessor> inner(new DCFP(procDataManager, fDeviceMatrix));
- return GrFragmentProcessor::MulOuputByInputAlpha(inner);
+ return GrFragmentProcessor::MulOutputByInputAlpha(inner);
}
class DCShaderGM : public GM {
diff --git a/gyp/gpu.gypi b/gyp/gpu.gypi
index 6038023..4670057 100644
--- a/gyp/gpu.gypi
+++ b/gyp/gpu.gypi
@@ -379,6 +379,7 @@
'<(skia_src_path)/gpu/SkGpuDevice.h',
'<(skia_src_path)/gpu/SkGr.cpp',
'<(skia_src_path)/gpu/SkGrPixelRef.cpp',
+ '<(skia_src_path)/gpu/SkGrPriv.h',
'<(skia_src_path)/gpu/SkGrTexturePixelRef.cpp',
'<(skia_src_path)/image/SkImage_Gpu.h',
diff --git a/include/core/SkShader.h b/include/core/SkShader.h
index a95e7e7..1b33ccf 100644
--- a/include/core/SkShader.h
+++ b/include/core/SkShader.h
@@ -315,6 +315,9 @@
*
* The GrContext may be used by the to create textures that are required by the returned
* processor.
+ *
+ * The returned GrFragmentProcessor should expect an unpremultiplied input color and
+ * produce a premultiplied output.
*/
virtual const GrFragmentProcessor* asFragmentProcessor(GrContext*,
const SkMatrix& viewMatrix,
diff --git a/include/gpu/GrColor.h b/include/gpu/GrColor.h
index 7e2b3b2..6b83237 100644
--- a/include/gpu/GrColor.h
+++ b/include/gpu/GrColor.h
@@ -17,8 +17,8 @@
#include "SkUnPreMultiply.h"
/**
- * GrColor is 4 bytes for R, G, B, A, in a specific order defined below. The components are stored
- * premultiplied.
+ * GrColor is 4 bytes for R, G, B, A, in a specific order defined below. Whether the color is
+ * premultiplied or not depends on the context in which it is being used.
*/
typedef uint32_t GrColor;
diff --git a/include/gpu/GrFragmentProcessor.h b/include/gpu/GrFragmentProcessor.h
index 4b0e1e1..776e893 100644
--- a/include/gpu/GrFragmentProcessor.h
+++ b/include/gpu/GrFragmentProcessor.h
@@ -31,7 +31,21 @@
* does so by returning a parent FP that multiplies the passed in FPs output by the parent's
* input alpha. The passed in FP will not receive an input color.
*/
- static const GrFragmentProcessor* MulOuputByInputAlpha(const GrFragmentProcessor*);
+ static const GrFragmentProcessor* MulOutputByInputAlpha(const GrFragmentProcessor*);
+
+ /**
+ * Similar to the above but it modulates the output r,g,b of the child processor by the input
+ * rgb and then multiplies all the components by the input alpha. This effectively modulates
+ * the child processor's premul color by a unpremul'ed input and produces a premul output
+ */
+ static const GrFragmentProcessor* MulOutputByInputUnpremulColor(const GrFragmentProcessor*);
+
+ /**
+ * Returns a parent fragment processor that adopts the passed fragment processor as a child. The
+ * parent will ignore its input color and instead feed the passed in color as input to the
+ * child.
+ */
+ static const GrFragmentProcessor* OverrideInput(const GrFragmentProcessor*, GrColor);
GrFragmentProcessor()
: INHERITED()
diff --git a/include/gpu/GrInvariantOutput.h b/include/gpu/GrInvariantOutput.h
index 83deac3..8cf4bf5 100644
--- a/include/gpu/GrInvariantOutput.h
+++ b/include/gpu/GrInvariantOutput.h
@@ -222,11 +222,6 @@
if (GetAlphaAndCheckSingleChannel(color, &a)) {
fIsSingleComponent = true;
}
- } else if (kA_GrColorComponentFlag & fValidFlags) {
- // Assuming fColor is premul means if a is 0 the color must be all 0s.
- if (!GrColorUnpackA(fColor)) {
- this->internalSetToTransparentBlack();
- }
}
SkDEBUGCODE(this->validate());
}
@@ -249,6 +244,7 @@
GrColor color() const { return fColor; }
GrColorComponentFlags validFlags() const { return fValidFlags; }
+ bool willUseInputColor() const { return fWillUseInputColor; }
/**
* If isSingleComponent is true, then the flag values for r, g, b, and a must all be the
@@ -308,7 +304,6 @@
bool isSingleComponent() const { return fIsSingleComponent; }
- bool willUseInputColor() const { return fWillUseInputColor; }
void resetWillUseInputColor() { fWillUseInputColor = true; }
bool allStagesMulInput() const { return !fNonMulStageFound; }
diff --git a/include/gpu/SkGr.h b/include/gpu/SkGr.h
index 145d409..74d880a 100644
--- a/include/gpu/SkGr.h
+++ b/include/gpu/SkGr.h
@@ -54,7 +54,7 @@
bool GrPixelConfig2ColorAndProfileType(GrPixelConfig, SkColorType*, SkColorProfileType*);
-static inline GrColor SkColor2GrColor(SkColor c) {
+static inline GrColor SkColorToPremulGrColor(SkColor c) {
SkPMColor pm = SkPreMultiplyColor(c);
unsigned r = SkGetPackedR32(pm);
unsigned g = SkGetPackedG32(pm);
@@ -63,7 +63,23 @@
return GrColorPackRGBA(r, g, b, a);
}
-static inline GrColor SkColor2GrColorJustAlpha(SkColor c) {
+static inline GrColor SkColorToUnpremulGrColor(SkColor c) {
+ unsigned r = SkColorGetR(c);
+ unsigned g = SkColorGetG(c);
+ unsigned b = SkColorGetB(c);
+ unsigned a = SkColorGetA(c);
+ return GrColorPackRGBA(r, g, b, a);
+}
+
+static inline GrColor SkColorToOpaqueGrColor(SkColor c) {
+ unsigned r = SkColorGetR(c);
+ unsigned g = SkColorGetG(c);
+ unsigned b = SkColorGetB(c);
+ return GrColorPackRGBA(r, g, b, 0xFF);
+}
+
+/** Replicates the SkColor's alpha to all four channels of the GrColor. */
+static inline GrColor SkColorAlphaToGrColor(SkColor c) {
U8CPU a = SkColorGetA(c);
return GrColorPackRGBA(a, a, a, a);
}
@@ -108,23 +124,6 @@
////////////////////////////////////////////////////////////////////////////////
-// Converts a SkPaint to a GrPaint, ignoring the SkPaint's shader.
-// Sets the color of GrPaint to the value of the parameter paintColor
-// Callers may subsequently modify the GrPaint. Setting constantColor indicates
-// that the final paint will draw the same color at every pixel. This allows
-// an optimization where the color filter can be applied to the SkPaint's
-// color once while converting to GrPaint and then ignored. TODO: Remove this
-// bool and use the invariant info to automatically apply the color filter.
-bool SkPaint2GrPaintNoShader(GrContext* context, const SkPaint& skPaint, GrColor paintColor,
- bool constantColor, GrPaint* grPaint);
-
-// This function is similar to skPaint2GrPaintNoShader but also converts
-// skPaint's shader to a GrFragmentProcessor if possible.
-// constantColor has the same meaning as in skPaint2GrPaintNoShader.
-bool SkPaint2GrPaint(GrContext* context, const SkPaint& skPaint, const SkMatrix& viewM,
- bool constantColor, GrPaint* grPaint);
-
-
SkImageInfo GrMakeInfoFromTexture(GrTexture* tex, int w, int h, bool isOpaque);
// Using the dreaded SkGrPixelRef ...
diff --git a/include/gpu/effects/GrXfermodeFragmentProcessor.h b/include/gpu/effects/GrXfermodeFragmentProcessor.h
index e2d1c0a..fb07d00 100644
--- a/include/gpu/effects/GrXfermodeFragmentProcessor.h
+++ b/include/gpu/effects/GrXfermodeFragmentProcessor.h
@@ -23,6 +23,9 @@
const GrFragmentProcessor* CreateFromSrcProcessor(const GrFragmentProcessor* src,
SkXfermode::Mode mode);
+ /** Takes the input color, which is assumed to be unpremultiplied, passes it as an opaque color
+ to both src and dst. The outputs of a src and dst are blended using mode and the original
+ input's alpha is applied to the blended color to produce a premul output. */
const GrFragmentProcessor* CreateFromTwoProcessors(const GrFragmentProcessor* src,
const GrFragmentProcessor* dst,
SkXfermode::Mode mode);
diff --git a/src/core/SkBitmapProcShader.cpp b/src/core/SkBitmapProcShader.cpp
index 8a5e03c..602e4e3 100644
--- a/src/core/SkBitmapProcShader.cpp
+++ b/src/core/SkBitmapProcShader.cpp
@@ -408,9 +408,9 @@
}
if (kAlpha_8_SkColorType == fRawBitmap.colorType()) {
- return SkRef(inner.get());
+ return GrFragmentProcessor::MulOutputByInputUnpremulColor(inner);
}
- return GrFragmentProcessor::MulOuputByInputAlpha(inner);
+ return GrFragmentProcessor::MulOutputByInputAlpha(inner);
}
#endif
diff --git a/src/core/SkDevice.cpp b/src/core/SkDevice.cpp
index a76a2ff..1f270af 100644
--- a/src/core/SkDevice.cpp
+++ b/src/core/SkDevice.cpp
@@ -204,7 +204,7 @@
}
pnt.setShader(shader);
- if (colors && colors[i] != SK_ColorWHITE) {
+ if (colors) {
SkAutoTUnref<SkColorFilter> cf(SkColorFilter::CreateModeFilter(colors[i], mode));
pnt.setColorFilter(cf);
}
diff --git a/src/core/SkLightingShader.cpp b/src/core/SkLightingShader.cpp
index b23acfd..15b4614 100644
--- a/src/core/SkLightingShader.cpp
+++ b/src/core/SkLightingShader.cpp
@@ -400,7 +400,7 @@
SkAutoTUnref<const GrFragmentProcessor> inner (
new LightingFP(pdm, diffuseTexture, normalTexture, diffM, normM, diffParams, normParams,
fLights, fInvNormRotation));
- return GrFragmentProcessor::MulOuputByInputAlpha(inner);
+ return GrFragmentProcessor::MulOutputByInputAlpha(inner);
}
#endif
diff --git a/src/core/SkShader.cpp b/src/core/SkShader.cpp
index 2a1c28e..6aadb43 100644
--- a/src/core/SkShader.cpp
+++ b/src/core/SkShader.cpp
@@ -335,7 +335,7 @@
const GrFragmentProcessor* SkColorShader::asFragmentProcessor(GrContext*, const SkMatrix&,
const SkMatrix*, SkFilterQuality,
GrProcessorDataManager*) const {
- GrColor color = SkColor2GrColor(fColor);
+ GrColor color = SkColorToPremulGrColor(fColor);
return GrConstColorProcessor::Create(color, GrConstColorProcessor::kModulateA_InputMode);
}
diff --git a/src/effects/SkColorFilters.cpp b/src/effects/SkColorFilters.cpp
index ece3295..0c6a612 100644
--- a/src/effects/SkColorFilters.cpp
+++ b/src/effects/SkColorFilters.cpp
@@ -74,7 +74,7 @@
SkTDArray<const GrFragmentProcessor*>* array) const {
if (SkXfermode::kDst_Mode != fMode) {
SkAutoTUnref<const GrFragmentProcessor> constFP(
- GrConstColorProcessor::Create(SkColor2GrColor(fColor),
+ GrConstColorProcessor::Create(SkColorToPremulGrColor(fColor),
GrConstColorProcessor::kIgnore_InputMode));
const GrFragmentProcessor* fp =
GrXfermodeFragmentProcessor::CreateFromSrcProcessor(constFP, fMode);
diff --git a/src/effects/SkPerlinNoiseShader.cpp b/src/effects/SkPerlinNoiseShader.cpp
index 842c32c..9a6c671 100644
--- a/src/effects/SkPerlinNoiseShader.cpp
+++ b/src/effects/SkPerlinNoiseShader.cpp
@@ -934,7 +934,7 @@
SkAutoTUnref<const GrFragmentProcessor> inner(
GrConstColorProcessor::Create(0x80404040,
GrConstColorProcessor::kModulateRGBA_InputMode));
- return GrFragmentProcessor::MulOuputByInputAlpha(inner);
+ return GrFragmentProcessor::MulOutputByInputAlpha(inner);
}
// Emit zero.
return GrConstColorProcessor::Create(0x0, GrConstColorProcessor::kIgnore_InputMode);
@@ -962,7 +962,7 @@
paintingData,
permutationsTexture, noiseTexture,
m));
- return GrFragmentProcessor::MulOuputByInputAlpha(inner);
+ return GrFragmentProcessor::MulOutputByInputAlpha(inner);
}
delete paintingData;
return nullptr;
diff --git a/src/effects/gradients/SkLinearGradient.cpp b/src/effects/gradients/SkLinearGradient.cpp
index 21d368c..31fcd3f 100644
--- a/src/effects/gradients/SkLinearGradient.cpp
+++ b/src/effects/gradients/SkLinearGradient.cpp
@@ -561,7 +561,7 @@
SkAutoTUnref<const GrFragmentProcessor> inner(
GrLinearGradient::Create(context, procDataManager, *this, matrix, fTileMode));
- return GrFragmentProcessor::MulOuputByInputAlpha(inner);
+ return GrFragmentProcessor::MulOutputByInputAlpha(inner);
}
diff --git a/src/effects/gradients/SkRadialGradient.cpp b/src/effects/gradients/SkRadialGradient.cpp
index bf46f70..d402ad9 100644
--- a/src/effects/gradients/SkRadialGradient.cpp
+++ b/src/effects/gradients/SkRadialGradient.cpp
@@ -533,7 +533,7 @@
matrix.postConcat(fPtsToUnit);
SkAutoTUnref<const GrFragmentProcessor> inner(
GrRadialGradient::Create(context, procDataManager, *this, matrix, fTileMode));
- return GrFragmentProcessor::MulOuputByInputAlpha(inner);
+ return GrFragmentProcessor::MulOutputByInputAlpha(inner);
}
#endif
diff --git a/src/effects/gradients/SkSweepGradient.cpp b/src/effects/gradients/SkSweepGradient.cpp
index 207308a..7e57ebe 100644
--- a/src/effects/gradients/SkSweepGradient.cpp
+++ b/src/effects/gradients/SkSweepGradient.cpp
@@ -291,7 +291,7 @@
SkAutoTUnref<const GrFragmentProcessor> inner(
GrSweepGradient::Create(context, procDataManager, *this, matrix));
- return GrFragmentProcessor::MulOuputByInputAlpha(inner);
+ return GrFragmentProcessor::MulOutputByInputAlpha(inner);
}
#endif
diff --git a/src/effects/gradients/SkTwoPointConicalGradient.cpp b/src/effects/gradients/SkTwoPointConicalGradient.cpp
index f6462b3..05957d6 100644
--- a/src/effects/gradients/SkTwoPointConicalGradient.cpp
+++ b/src/effects/gradients/SkTwoPointConicalGradient.cpp
@@ -371,7 +371,7 @@
SkAutoTUnref<const GrFragmentProcessor> inner(
Gr2PtConicalGradientEffect::Create(context, procDataManager, *this, fTileMode,
localMatrix));
- return GrFragmentProcessor::MulOuputByInputAlpha(inner);
+ return GrFragmentProcessor::MulOutputByInputAlpha(inner);
}
#endif
diff --git a/src/gpu/GrAtlasTextContext.cpp b/src/gpu/GrAtlasTextContext.cpp
index 81cc647..108d63c 100644
--- a/src/gpu/GrAtlasTextContext.cpp
+++ b/src/gpu/GrAtlasTextContext.cpp
@@ -29,7 +29,7 @@
#include "SkDrawProcs.h"
#include "SkGlyphCache.h"
#include "SkGpuDevice.h"
-#include "SkGr.h"
+#include "SkGrPriv.h"
#include "SkPath.h"
#include "SkRTConf.h"
#include "SkStrokeRec.h"
@@ -389,7 +389,7 @@
// Though for the time being runs in the textblob can override the paint, they only touch font
// info.
GrPaint grPaint;
- if (!SkPaint2GrPaint(fContext, skPaint, viewMatrix, true, &grPaint)) {
+ if (!SkPaintToGrPaint(fContext, skPaint, viewMatrix, &grPaint)) {
return;
}
@@ -2265,7 +2265,7 @@
skPaint.setSubpixelText(random->nextBool());
GrPaint grPaint;
- if (!SkPaint2GrPaint(context, skPaint, viewMatrix, true, &grPaint)) {
+ if (!SkPaintToGrPaint(context, skPaint, viewMatrix, &grPaint)) {
SkFAIL("couldn't convert paint\n");
}
diff --git a/src/gpu/GrBlurUtils.cpp b/src/gpu/GrBlurUtils.cpp
index b601a20..463691d 100644
--- a/src/gpu/GrBlurUtils.cpp
+++ b/src/gpu/GrBlurUtils.cpp
@@ -14,7 +14,7 @@
#include "GrTexture.h"
#include "GrTextureProvider.h"
#include "SkDraw.h"
-#include "SkGr.h"
+#include "SkGrPriv.h"
#include "SkMaskFilter.h"
#include "SkPaint.h"
@@ -197,7 +197,7 @@
SkDEBUGCODE(prePathMatrix = (const SkMatrix*)0x50FF8001;)
GrPaint grPaint;
- if (!SkPaint2GrPaint(context, paint, viewMatrix, true, &grPaint)) {
+ if (!SkPaintToGrPaint(context, paint, viewMatrix, &grPaint)) {
return;
}
diff --git a/src/gpu/GrFragmentProcessor.cpp b/src/gpu/GrFragmentProcessor.cpp
index fcc9c74..b6a80ab 100644
--- a/src/gpu/GrFragmentProcessor.cpp
+++ b/src/gpu/GrFragmentProcessor.cpp
@@ -9,6 +9,7 @@
#include "GrFragmentProcessor.h"
#include "GrCoordTransform.h"
#include "gl/GrGLFragmentProcessor.h"
+#include "gl/builders/GrGLProgramBuilder.h"
#include "effects/GrXfermodeFragmentProcessor.h"
GrFragmentProcessor::~GrFragmentProcessor() {
@@ -122,8 +123,159 @@
return true;
}
-const GrFragmentProcessor* GrFragmentProcessor::MulOuputByInputAlpha(
+const GrFragmentProcessor* GrFragmentProcessor::MulOutputByInputAlpha(
const GrFragmentProcessor* fp) {
+ if (!fp) {
+ return nullptr;
+ }
return GrXfermodeFragmentProcessor::CreateFromDstProcessor(fp, SkXfermode::kDstIn_Mode);
}
+const GrFragmentProcessor* GrFragmentProcessor::MulOutputByInputUnpremulColor(
+ const GrFragmentProcessor* fp) {
+
+ class PremulFragmentProcessor : public GrFragmentProcessor {
+ public:
+ PremulFragmentProcessor(const GrFragmentProcessor* processor) {
+ this->initClassID<PremulFragmentProcessor>();
+ this->registerChildProcessor(processor);
+ }
+
+ const char* name() const override { return "Premultiply"; }
+
+ private:
+ GrGLFragmentProcessor* onCreateGLInstance() const override {
+ class GLFP : public GrGLFragmentProcessor {
+ public:
+ GLFP() {}
+
+ void emitCode(EmitArgs& args) override {
+ GrGLFragmentBuilder* fsBuilder = args.fBuilder->getFragmentShaderBuilder();
+ this->emitChild(0, nullptr, args);
+ fsBuilder->codeAppendf("%s.rgb *= %s.rgb;", args.fOutputColor,
+ args.fInputColor);
+ fsBuilder->codeAppendf("%s *= %s.a;", args.fOutputColor, args.fInputColor);
+ }
+ };
+ return new GLFP;
+ }
+
+ void onGetGLProcessorKey(const GrGLSLCaps&, GrProcessorKeyBuilder*) const override {}
+
+ bool onIsEqual(const GrFragmentProcessor&) const override { return true; }
+
+ void onComputeInvariantOutput(GrInvariantOutput* inout) const override {
+ // TODO: Add a helper to GrInvariantOutput that handles multiplying by color with flags?
+ if (!(inout->validFlags() & kA_GrColorComponentFlag)) {
+ inout->setToUnknown(GrInvariantOutput::kWill_ReadInput);
+ return;
+ }
+
+ GrInvariantOutput childOutput(GrColor_WHITE, kRGBA_GrColorComponentFlags, false);
+ this->childProcessor(0).computeInvariantOutput(&childOutput);
+
+ if (0 == GrColorUnpackA(inout->color()) || 0 == GrColorUnpackA(childOutput.color())) {
+ inout->mulByKnownFourComponents(0x0);
+ return;
+ }
+ GrColorComponentFlags commonFlags = childOutput.validFlags() & inout->validFlags();
+ GrColor c0 = GrPremulColor(inout->color());
+ GrColor c1 = childOutput.color();
+ GrColor color = 0x0;
+ if (commonFlags & kR_GrColorComponentFlag) {
+ color |= SkMulDiv255Round(GrColorUnpackR(c0), GrColorUnpackR(c1)) <<
+ GrColor_SHIFT_R;
+ }
+ if (commonFlags & kG_GrColorComponentFlag) {
+ color |= SkMulDiv255Round(GrColorUnpackG(c0), GrColorUnpackG(c1)) <<
+ GrColor_SHIFT_G;
+ }
+ if (commonFlags & kB_GrColorComponentFlag) {
+ color |= SkMulDiv255Round(GrColorUnpackB(c0), GrColorUnpackB(c1)) <<
+ GrColor_SHIFT_B;
+ }
+ inout->setToOther(commonFlags, color, GrInvariantOutput::kWill_ReadInput);
+ }
+ };
+ if (!fp) {
+ return nullptr;
+ }
+ return new PremulFragmentProcessor(fp);
+}
+
+//////////////////////////////////////////////////////////////////////////////
+
+const GrFragmentProcessor* GrFragmentProcessor::OverrideInput(const GrFragmentProcessor* fp,
+ GrColor color) {
+ class ReplaceInputFragmentProcessor : public GrFragmentProcessor {
+ public:
+ ReplaceInputFragmentProcessor(const GrFragmentProcessor* child, GrColor color)
+ : fColor(color) {
+ this->initClassID<ReplaceInputFragmentProcessor>();
+ this->registerChildProcessor(child);
+ }
+
+ const char* name() const override { return "Replace Color"; }
+
+ GrGLFragmentProcessor* onCreateGLInstance() const override {
+ class GLFP : public GrGLFragmentProcessor {
+ public:
+ GLFP() : fHaveSetColor(false) {}
+ void emitCode(EmitArgs& args) override {
+ const char* colorName;
+ fColorUni = args.fBuilder->addUniform(GrGLProgramBuilder::kFragment_Visibility,
+ kVec4f_GrSLType, kDefault_GrSLPrecision,
+ "Color", &colorName);
+ this->emitChild(0, colorName, args);
+ }
+
+ private:
+ void onSetData(const GrGLProgramDataManager& pdman,
+ const GrProcessor& fp) override {
+ GrColor color = fp.cast<ReplaceInputFragmentProcessor>().fColor;
+ if (!fHaveSetColor || color != fPreviousColor) {
+ static const GrGLfloat scale = 1.f / 255.f;
+ GrGLfloat floatColor[4] = {
+ GrColorUnpackR(color) * scale,
+ GrColorUnpackG(color) * scale,
+ GrColorUnpackB(color) * scale,
+ GrColorUnpackA(color) * scale,
+ };
+ pdman.set4fv(fColorUni, 1, floatColor);
+ fPreviousColor = color;
+ fHaveSetColor = true;
+ }
+ }
+
+ GrGLProgramDataManager::UniformHandle fColorUni;
+ bool fHaveSetColor;
+ GrColor fPreviousColor;
+ };
+
+ return new GLFP;
+ }
+
+ private:
+ void onGetGLProcessorKey(const GrGLSLCaps& caps, GrProcessorKeyBuilder* b) const override {}
+
+ bool onIsEqual(const GrFragmentProcessor& that) const override {
+ return fColor == that.cast<ReplaceInputFragmentProcessor>().fColor;
+ }
+
+ void onComputeInvariantOutput(GrInvariantOutput* inout) const override {
+ inout->setToOther(kRGBA_GrColorComponentFlags, fColor,
+ GrInvariantOutput::kWillNot_ReadInput);
+ this->childProcessor(0).computeInvariantOutput(inout);
+ }
+
+ GrColor fColor;
+ };
+
+ GrInvariantOutput childOut(0x0, kNone_GrColorComponentFlags, false);
+ fp->computeInvariantOutput(&childOut);
+ if (childOut.willUseInputColor()) {
+ return new ReplaceInputFragmentProcessor(fp, color);
+ } else {
+ return SkRef(fp);
+ }
+}
diff --git a/src/gpu/GrInvariantOutput.cpp b/src/gpu/GrInvariantOutput.cpp
index 4c77df3..8de5817 100644
--- a/src/gpu/GrInvariantOutput.cpp
+++ b/src/gpu/GrInvariantOutput.cpp
@@ -17,8 +17,6 @@
}
}
- SkASSERT(this->validPreMulColor());
-
// If we claim that we are not using the input color we must not be modulating the input.
SkASSERT(fNonMulStageFound || fWillUseInputColor);
}
@@ -30,28 +28,5 @@
GrColorUnpackB(fColor) == colorA);
}
-bool GrInvariantOutput::validPreMulColor() const {
- if (kA_GrColorComponentFlag & fValidFlags) {
- float c[4];
- GrColorToRGBAFloat(fColor, c);
- if (kR_GrColorComponentFlag & fValidFlags) {
- if (c[0] > c[3]) {
- return false;
- }
- }
- if (kG_GrColorComponentFlag & fValidFlags) {
- if (c[1] > c[3]) {
- return false;
- }
- }
- if (kB_GrColorComponentFlag & fValidFlags) {
- if (c[2] > c[3]) {
- return false;
- }
- }
- }
- return true;
-}
-
#endif // end DEBUG
diff --git a/src/gpu/GrTextContext.cpp b/src/gpu/GrTextContext.cpp
index 32c056f..1041b88 100644
--- a/src/gpu/GrTextContext.cpp
+++ b/src/gpu/GrTextContext.cpp
@@ -16,6 +16,7 @@
#include "SkDrawProcs.h"
#include "SkGlyphCache.h"
#include "SkGpuDevice.h"
+#include "SkGrPriv.h"
#include "SkTextBlob.h"
#include "SkTextMapStateProc.h"
#include "SkTextToPathIter.h"
@@ -130,7 +131,7 @@
runPaint.setFlags(FilterTextFlags(fSurfaceProps, runPaint));
GrPaint grPaint;
- if (!SkPaint2GrPaint(fContext, runPaint, viewMatrix, true, &grPaint)) {
+ if (!SkPaintToGrPaint(fContext, runPaint, viewMatrix, &grPaint)) {
return;
}
diff --git a/src/gpu/SkGpuDevice.cpp b/src/gpu/SkGpuDevice.cpp
index 0920605..5289019 100644
--- a/src/gpu/SkGpuDevice.cpp
+++ b/src/gpu/SkGpuDevice.cpp
@@ -23,6 +23,7 @@
#include "SkErrorInternals.h"
#include "SkGlyphCache.h"
#include "SkGrTexturePixelRef.h"
+#include "SkGrPriv.h"
#include "SkImage_Base.h"
#include "SkImageFilter.h"
#include "SkLayerInfo.h"
@@ -383,7 +384,7 @@
GR_CREATE_TRACE_MARKER_CONTEXT("SkGpuDevice::drawPaint", fContext);
GrPaint grPaint;
- if (!SkPaint2GrPaint(this->context(), paint, *draw.fMatrix, true, &grPaint)) {
+ if (!SkPaintToGrPaint(this->context(), paint, *draw.fMatrix, &grPaint)) {
return;
}
@@ -432,7 +433,7 @@
if (paint.getPathEffect() && 2 == count && SkCanvas::kLines_PointMode == mode) {
GrStrokeInfo strokeInfo(paint, SkPaint::kStroke_Style);
GrPaint grPaint;
- if (!SkPaint2GrPaint(this->context(), paint, *draw.fMatrix, true, &grPaint)) {
+ if (!SkPaintToGrPaint(this->context(), paint, *draw.fMatrix, &grPaint)) {
return;
}
SkPath path;
@@ -452,7 +453,7 @@
}
GrPaint grPaint;
- if (!SkPaint2GrPaint(this->context(), paint, *draw.fMatrix, true, &grPaint)) {
+ if (!SkPaintToGrPaint(this->context(), paint, *draw.fMatrix, &grPaint)) {
return;
}
@@ -515,7 +516,7 @@
}
GrPaint grPaint;
- if (!SkPaint2GrPaint(this->context(), paint, *draw.fMatrix, true, &grPaint)) {
+ if (!SkPaintToGrPaint(this->context(), paint, *draw.fMatrix, &grPaint)) {
return;
}
@@ -531,7 +532,7 @@
CHECK_SHOULD_DRAW(draw);
GrPaint grPaint;
- if (!SkPaint2GrPaint(this->context(), paint, *draw.fMatrix, true, &grPaint)) {
+ if (!SkPaintToGrPaint(this->context(), paint, *draw.fMatrix, &grPaint)) {
return;
}
@@ -602,7 +603,7 @@
CHECK_SHOULD_DRAW(draw);
GrPaint grPaint;
- if (!SkPaint2GrPaint(this->context(), paint, *draw.fMatrix, true, &grPaint)) {
+ if (!SkPaintToGrPaint(this->context(), paint, *draw.fMatrix, &grPaint)) {
return;
}
@@ -654,7 +655,7 @@
}
GrPaint grPaint;
- if (!SkPaint2GrPaint(this->context(), paint, *draw.fMatrix, true, &grPaint)) {
+ if (!SkPaintToGrPaint(this->context(), paint, *draw.fMatrix, &grPaint)) {
return;
}
@@ -989,10 +990,6 @@
return;
}
- // Setup paint
- GrColor paintColor = (kAlpha_8_SkColorType == bitmapPtr->colorType()) ?
- SkColor2GrColor(paint.getColor()) :
- SkColor2GrColorJustAlpha(paint.getColor());
GrPaint grPaint;
@@ -1007,14 +1004,15 @@
SkMatrix::I(), params));
}
- // The bitmap read has to be first
- grPaint.addColorFragmentProcessor(fp);
- if (!SkPaint2GrPaintNoShader(context, paint, SkColor2GrColor(paint.getColor()), false,
- &grPaint)) {
- return;
+ if (kAlpha_8_SkColorType == bitmapPtr->colorType()) {
+ fp.reset(GrFragmentProcessor::MulOutputByInputUnpremulColor(fp));
+ } else {
+ fp.reset(GrFragmentProcessor::MulOutputByInputAlpha(fp));
}
- grPaint.setColor(paintColor);
+ if (!SkPaintToGrPaintReplaceShader(context, paint, fp, &grPaint)) {
+ return;
+ }
// Setup dst rect and final matrix
SkRect dstRect = {0, 0, dstSize.fWidth, dstSize.fHeight};
@@ -1311,7 +1309,7 @@
// Construct a GrPaint by setting the bitmap texture as the first effect and then configuring
// the rest from the SkPaint.
GrPaint grPaint;
- SkAutoTUnref<GrFragmentProcessor> fp;
+ SkAutoTUnref<const GrFragmentProcessor> fp;
if (needsTextureDomain && (SkCanvas::kStrict_SrcRectConstraint == constraint)) {
// Use a constrained texture domain to avoid color bleeding
@@ -1352,11 +1350,13 @@
SkMatrix::I(), params));
}
- grPaint.addColorFragmentProcessor(fp);
- bool alphaOnly = !(kAlpha_8_SkColorType == bitmap.colorType());
- GrColor paintColor = (alphaOnly) ? SkColor2GrColorJustAlpha(paint.getColor()) :
- SkColor2GrColor(paint.getColor());
- if (!SkPaint2GrPaintNoShader(this->context(), paint, paintColor, false, &grPaint)) {
+ if (kAlpha_8_SkColorType == bitmap.colorType()) {
+ fp.reset(GrFragmentProcessor::MulOutputByInputUnpremulColor(fp));
+ } else {
+ fp.reset(GrFragmentProcessor::MulOutputByInputAlpha(fp));
+ }
+
+ if (!SkPaintToGrPaintReplaceShader(this->context(), paint, fp, &grPaint)) {
return;
}
@@ -1401,6 +1401,8 @@
return;
}
+ bool alphaOnly = kAlpha_8_SkColorType == bitmap.colorType();
+
SkImageFilter* filter = paint.getImageFilter();
// This bitmap will own the filtered result as a texture.
SkBitmap filteredBitmap;
@@ -1424,13 +1426,19 @@
} else {
return;
}
+ SkASSERT(!GrPixelConfigIsAlphaOnly(texture->config()));
+ alphaOnly = false;
}
GrPaint grPaint;
- grPaint.addColorTextureProcessor(texture, SkMatrix::I());
-
- if (!SkPaint2GrPaintNoShader(this->context(), paint,
- SkColor2GrColorJustAlpha(paint.getColor()), false, &grPaint)) {
+ SkAutoTUnref<const GrFragmentProcessor> fp(
+ GrSimpleTextureEffect::Create(grPaint.getProcessorDataManager(), texture, SkMatrix::I()));
+ if (alphaOnly) {
+ fp.reset(GrFragmentProcessor::MulOutputByInputUnpremulColor(fp));
+ } else {
+ fp.reset(GrFragmentProcessor::MulOutputByInputAlpha(fp));
+ }
+ if (!SkPaintToGrPaintReplaceShader(this->context(), paint, fp, &grPaint)) {
return;
}
@@ -1542,10 +1550,16 @@
}
GrPaint grPaint;
- grPaint.addColorTextureProcessor(devTex, SkMatrix::I());
+ SkAutoTUnref<const GrFragmentProcessor> fp(
+ GrSimpleTextureEffect::Create(grPaint.getProcessorDataManager(), devTex, SkMatrix::I()));
+ if (GrPixelConfigIsAlphaOnly(devTex->config())) {
+ // Can this happen?
+ fp.reset(GrFragmentProcessor::MulOutputByInputUnpremulColor(fp));
+ } else {
+ fp.reset(GrFragmentProcessor::MulOutputByInputAlpha(fp));
+ }
- if (!SkPaint2GrPaintNoShader(this->context(), paint,
- SkColor2GrColorJustAlpha(paint.getColor()), false, &grPaint)) {
+ if (!SkPaintToGrPaintReplaceShader(this->context(), paint, fp, &grPaint)) {
return;
}
@@ -1666,11 +1680,6 @@
CHECK_SHOULD_DRAW(draw);
GR_CREATE_TRACE_MARKER_CONTEXT("SkGpuDevice::drawVertices", fContext);
- const uint16_t* outIndices;
- SkAutoTDeleteArray<uint16_t> outAlloc(nullptr);
- GrPrimitiveType primType;
- GrPaint grPaint;
-
// If both textures and vertex-colors are nullptr, strokes hairlines with the paint's color.
if ((nullptr == texs || nullptr == paint.getShader()) && nullptr == colors) {
@@ -1680,13 +1689,12 @@
copy.setStyle(SkPaint::kStroke_Style);
copy.setStrokeWidth(0);
+ GrPaint grPaint;
// we ignore the shader if texs is null.
- if (!SkPaint2GrPaintNoShader(this->context(), copy,
- SkColor2GrColor(copy.getColor()), nullptr == colors, &grPaint)) {
+ if (!SkPaintToGrPaintNoShader(this->context(), copy, &grPaint)) {
return;
}
- primType = kLines_GrPrimitiveType;
int triangleCount = 0;
int n = (nullptr == indices) ? vertexCount : indexCount;
switch (vmode) {
@@ -1705,45 +1713,32 @@
//number of indices for lines per triangle with kLines
indexCount = triangleCount * 6;
- outAlloc.reset(new uint16_t[indexCount]);
- outIndices = outAlloc.get();
- uint16_t* auxIndices = outAlloc.get();
+ SkAutoTDeleteArray<uint16_t> lineIndices(new uint16_t[indexCount]);
int i = 0;
while (vertProc(&state)) {
- auxIndices[i] = state.f0;
- auxIndices[i + 1] = state.f1;
- auxIndices[i + 2] = state.f1;
- auxIndices[i + 3] = state.f2;
- auxIndices[i + 4] = state.f2;
- auxIndices[i + 5] = state.f0;
+ lineIndices[i] = state.f0;
+ lineIndices[i + 1] = state.f1;
+ lineIndices[i + 2] = state.f1;
+ lineIndices[i + 3] = state.f2;
+ lineIndices[i + 4] = state.f2;
+ lineIndices[i + 5] = state.f0;
i += 6;
}
- } else {
- outIndices = indices;
- primType = gVertexMode2PrimitiveType[vmode];
-
- if (nullptr == texs || nullptr == paint.getShader()) {
- if (!SkPaint2GrPaintNoShader(this->context(), paint,
- SkColor2GrColor(paint.getColor()),
- nullptr == colors, &grPaint)) {
- return;
- }
- } else {
- if (!SkPaint2GrPaint(this->context(), paint, *draw.fMatrix,
- nullptr == colors, &grPaint)) {
- return;
- }
- }
+ fDrawContext->drawVertices(fRenderTarget,
+ fClip,
+ grPaint,
+ *draw.fMatrix,
+ kLines_GrPrimitiveType,
+ vertexCount,
+ vertices,
+ texs,
+ colors,
+ lineIndices.get(),
+ indexCount);
+ return;
}
-#if 0
- if (xmode && texs && colors) {
- if (!SkXfermode::IsMode(xmode, SkXfermode::kModulate_Mode)) {
- SkDebugf("Unsupported vertex-color/texture xfer mode.\n");
- return;
- }
- }
-#endif
+ GrPrimitiveType primType = gVertexMode2PrimitiveType[vmode];
SkAutoSTMalloc<128, GrColor> convertedColors(0);
if (colors) {
@@ -1755,10 +1750,36 @@
if (paint.getAlpha() != 255) {
color = SkColorSetA(color, SkMulDiv255Round(SkColorGetA(color), paint.getAlpha()));
}
- convertedColors[i] = SkColor2GrColor(color);
+ /// TODO: Perform the premul after interpolating
+ convertedColors[i] = SkColorToPremulGrColor(color);
}
colors = convertedColors.get();
}
+ GrPaint grPaint;
+ if (texs && colors && paint.getShader()) {
+ // When there are texs and colors the shader and colors are combined using xmode. A null
+ // xmode is defined to mean modulate.
+ SkXfermode::Mode colorMode;
+ if (xmode) {
+ if (!xmode->asMode(&colorMode)) {
+ return;
+ }
+ } else {
+ colorMode = SkXfermode::kModulate_Mode;
+ }
+ if (!SkPaintToGrPaintWithXfermode(this->context(), paint, *draw.fMatrix, colorMode, false,
+ &grPaint)) {
+ return;
+ }
+ } else if (!texs) {
+ // Defined to ignore the shader unless texs is provided.
+ if (!SkPaintToGrPaintNoShader(this->context(), paint, &grPaint)) {
+ return;
+ }
+ } else if (!SkPaintToGrPaint(this->context(), paint, *draw.fMatrix, &grPaint)) {
+ return;
+ }
+
fDrawContext->drawVertices(fRenderTarget,
fClip,
grPaint,
@@ -1768,7 +1789,7 @@
vertices,
texs,
colors,
- outIndices,
+ indices,
indexCount);
}
@@ -1789,21 +1810,18 @@
p.setShader(atlas->newShader(SkShader::kClamp_TileMode, SkShader::kClamp_TileMode))->unref();
GrPaint grPaint;
- if (!SkPaint2GrPaint(this->context(), p, *draw.fMatrix, !colors, &grPaint)) {
- return;
- }
-
- SkDEBUGCODE(this->validate();)
-
-#if 0
if (colors) {
- if (SkXfermode::kModulate_Mode != mode) {
- SkDebugf("Unsupported vertex-color/texture xfer mode.\n");
+ if (!SkPaintToGrPaintWithXfermode(this->context(), p, *draw.fMatrix, mode, true,
+ &grPaint)) {
+ return;
+ }
+ } else {
+ if (!SkPaintToGrPaint(this->context(), p, *draw.fMatrix, &grPaint)) {
return;
}
}
-#endif
-
+
+ SkDEBUGCODE(this->validate();)
fDrawContext->drawAtlas(fRenderTarget, fClip, grPaint, *draw.fMatrix,
count, xform, texRect, colors);
}
@@ -1817,7 +1835,7 @@
GR_CREATE_TRACE_MARKER_CONTEXT("SkGpuDevice::drawText", fContext);
GrPaint grPaint;
- if (!SkPaint2GrPaint(this->context(), paint, *draw.fMatrix, true, &grPaint)) {
+ if (!SkPaintToGrPaint(this->context(), paint, *draw.fMatrix, &grPaint)) {
return;
}
@@ -1834,7 +1852,7 @@
CHECK_SHOULD_DRAW(draw);
GrPaint grPaint;
- if (!SkPaint2GrPaint(this->context(), paint, *draw.fMatrix, true, &grPaint)) {
+ if (!SkPaintToGrPaint(this->context(), paint, *draw.fMatrix, &grPaint)) {
return;
}
diff --git a/src/gpu/SkGr.cpp b/src/gpu/SkGr.cpp
index 09c83b9..e0892d8 100644
--- a/src/gpu/SkGr.cpp
+++ b/src/gpu/SkGr.cpp
@@ -24,8 +24,10 @@
#include "SkTextureCompressor.h"
#include "SkYUVPlanesCache.h"
#include "effects/GrBicubicEffect.h"
+#include "effects/GrConstColorProcessor.h"
#include "effects/GrDitherEffect.h"
#include "effects/GrPorterDuffXferProcessor.h"
+#include "effects/GrXfermodeFragmentProcessor.h"
#include "effects/GrYUVtoRGBEffect.h"
#ifndef SK_IGNORE_ETC1_SUPPORT
@@ -706,13 +708,122 @@
return true;
}
-///////////////////////////////////////////////////////////////////////////////
-bool SkPaint2GrPaintNoShader(GrContext* context, const SkPaint& skPaint, GrColor paintColor,
- bool constantColor, GrPaint* grPaint) {
+////////////////////////////////////////////////////////////////////////////////////////////////
+static inline bool skpaint_to_grpaint_impl(GrContext* context,
+ const SkPaint& skPaint,
+ const SkMatrix& viewM,
+ const GrFragmentProcessor** shaderProcessor,
+ SkXfermode::Mode* primColorMode,
+ bool primitiveIsSrc,
+ GrPaint* grPaint) {
grPaint->setAntiAlias(skPaint.isAntiAlias());
+ // Setup the initial color considering the shader, the SkPaint color, and the presence or not
+ // of per-vertex colors.
+ SkAutoTUnref<const GrFragmentProcessor> aufp;
+ const GrFragmentProcessor* shaderFP = NULL;
+ if (shaderProcessor) {
+ shaderFP = *shaderProcessor;
+ } else if (const SkShader* shader = skPaint.getShader()) {
+ aufp.reset(shader->asFragmentProcessor(context, viewM, NULL, skPaint.getFilterQuality(),
+ grPaint->getProcessorDataManager()));
+ shaderFP = aufp;
+ if (!shaderFP) {
+ return false;
+ }
+ }
+
+ // Set this in below cases if the output of the shader/paint-color/paint-alpha/primXfermode is
+ // a known constant value. In that case we can simply apply a color filter during this
+ // conversion without converting the color filter to a GrFragmentProcessor.
+ bool applyColorFilterToPaintColor = false;
+ if (shaderFP) {
+ if (primColorMode) {
+ // There is a blend between the primitive color and the shader color. The shader sees
+ // the opaque paint color. The shader's output is blended using the provided mode by
+ // the primitive color. The blended color is then modulated by the paint's alpha.
+
+ // The geometry processor will insert the primitive color to start the color chain, so
+ // the GrPaint color will be ignored.
+
+ GrColor shaderInput = SkColorToOpaqueGrColor(skPaint.getColor());
+
+ shaderFP = GrFragmentProcessor::OverrideInput(shaderFP, shaderInput);
+ aufp.reset(shaderFP);
+
+ if (primitiveIsSrc) {
+ shaderFP = GrXfermodeFragmentProcessor::CreateFromDstProcessor(shaderFP,
+ *primColorMode);
+ } else {
+ shaderFP = GrXfermodeFragmentProcessor::CreateFromSrcProcessor(shaderFP,
+ *primColorMode);
+ }
+ aufp.reset(shaderFP);
+ // The above may return null if compose results in a pass through of the prim color.
+ if (shaderFP) {
+ grPaint->addColorFragmentProcessor(shaderFP);
+ }
+
+ GrColor paintAlpha = SkColorAlphaToGrColor(skPaint.getColor());
+ if (GrColor_WHITE != paintAlpha) {
+ grPaint->addColorFragmentProcessor(GrConstColorProcessor::Create(
+ paintAlpha, GrConstColorProcessor::kModulateRGBA_InputMode))->unref();
+ }
+ } else {
+ // The shader's FP sees the paint unpremul color
+ grPaint->setColor(SkColorToUnpremulGrColor(skPaint.getColor()));
+ grPaint->addColorFragmentProcessor(shaderFP);
+ }
+ } else {
+ if (primColorMode) {
+ // There is a blend between the primitive color and the paint color. The blend considers
+ // the opaque paint color. The paint's alpha is applied to the post-blended color.
+ SkAutoTUnref<const GrFragmentProcessor> processor(
+ GrConstColorProcessor::Create(SkColorToOpaqueGrColor(skPaint.getColor()),
+ GrConstColorProcessor::kIgnore_InputMode));
+ if (primitiveIsSrc) {
+ processor.reset(GrXfermodeFragmentProcessor::CreateFromDstProcessor(processor,
+ *primColorMode));
+ } else {
+ processor.reset(GrXfermodeFragmentProcessor::CreateFromSrcProcessor(processor,
+ *primColorMode));
+
+ }
+ if (processor) {
+ grPaint->addColorFragmentProcessor(processor);
+ }
+
+ grPaint->setColor(SkColorToUnpremulGrColor(skPaint.getColor()) | 0xFF000000);
+
+ GrColor paintAlpha = SkColorAlphaToGrColor(skPaint.getColor());
+ grPaint->addColorFragmentProcessor(GrConstColorProcessor::Create(
+ paintAlpha, GrConstColorProcessor::kModulateRGBA_InputMode))->unref();
+ } else {
+ // No shader, no primitive color.
+ grPaint->setColor(SkColorToPremulGrColor(skPaint.getColor()));
+ applyColorFilterToPaintColor = true;
+ }
+ }
+
+ SkColorFilter* colorFilter = skPaint.getColorFilter();
+ if (colorFilter) {
+ if (applyColorFilterToPaintColor) {
+ grPaint->setColor(SkColorToPremulGrColor(colorFilter->filterColor(skPaint.getColor())));
+ } else {
+ SkTDArray<const GrFragmentProcessor*> array;
+ if (colorFilter->asFragmentProcessors(context, grPaint->getProcessorDataManager(),
+ &array)) {
+ for (int i = 0; i < array.count(); ++i) {
+ grPaint->addColorFragmentProcessor(array[i])->unref();
+ }
+ } else {
+ return false;
+ }
+ }
+ }
+
SkXfermode* mode = skPaint.getXfermode();
GrXPFactory* xpFactory = nullptr;
if (!SkXfermode::AsXPFactory(mode, &xpFactory)) {
@@ -723,29 +834,6 @@
SkASSERT(xpFactory);
grPaint->setXPFactory(xpFactory)->unref();
- //set the color of the paint to the one of the parameter
- grPaint->setColor(paintColor);
-
- SkColorFilter* colorFilter = skPaint.getColorFilter();
- if (colorFilter) {
- // if the source color is a constant then apply the filter here once rather than per pixel
- // in a shader.
- if (constantColor) {
- SkColor filtered = colorFilter->filterColor(skPaint.getColor());
- grPaint->setColor(SkColor2GrColor(filtered));
- } else {
- SkTDArray<const GrFragmentProcessor*> array;
- // return false if failed?
- if (colorFilter->asFragmentProcessors(context, grPaint->getProcessorDataManager(),
- &array)) {
- for (int i = 0; i < array.count(); ++i) {
- grPaint->addColorFragmentProcessor(array[i]);
- array[i]->unref();
- }
- }
- }
- }
-
#ifndef SK_IGNORE_GPU_DITHER
if (skPaint.isDither() && grPaint->numColorFragmentProcessors() > 0) {
grPaint->addColorFragmentProcessor(GrDitherEffect::Create())->unref();
@@ -754,29 +842,49 @@
return true;
}
-bool SkPaint2GrPaint(GrContext* context,const SkPaint& skPaint, const SkMatrix& viewM,
- bool constantColor, GrPaint* grPaint) {
- SkShader* shader = skPaint.getShader();
- if (nullptr == shader) {
- return SkPaint2GrPaintNoShader(context, skPaint, SkColor2GrColor(skPaint.getColor()),
- constantColor, grPaint);
- }
+bool SkPaintToGrPaint(GrContext* context, const SkPaint& skPaint, const SkMatrix& viewM,
+ GrPaint* grPaint) {
+ return skpaint_to_grpaint_impl(context, skPaint, viewM, nullptr, nullptr, false, grPaint);
+}
- GrColor paintColor = SkColor2GrColor(skPaint.getColor());
-
- const GrFragmentProcessor* fp = shader->asFragmentProcessor(context, viewM, NULL,
- skPaint.getFilterQuality(), grPaint->getProcessorDataManager());
- if (!fp) {
+/** Replaces the SkShader (if any) on skPaint with the passed in GrFragmentProcessor. */
+bool SkPaintToGrPaintReplaceShader(GrContext* context,
+ const SkPaint& skPaint,
+ const GrFragmentProcessor* shaderFP,
+ GrPaint* grPaint) {
+ if (!shaderFP) {
return false;
}
- grPaint->addColorFragmentProcessor(fp)->unref();
- constantColor = false;
-
- // The grcolor is automatically set when calling asFragmentProcessor.
- // If the shader can be seen as an effect it returns true and adds its effect to the grpaint.
- return SkPaint2GrPaintNoShader(context, skPaint, paintColor, constantColor, grPaint);
+ return skpaint_to_grpaint_impl(context, skPaint, SkMatrix::I(), &shaderFP, nullptr, false,
+ grPaint);
}
+/** Ignores the SkShader (if any) on skPaint. */
+bool SkPaintToGrPaintNoShader(GrContext* context,
+ const SkPaint& skPaint,
+ GrPaint* grPaint) {
+ // Use a ptr to a nullptr to to indicate that the SkShader is ignored and not replaced.
+ static const GrFragmentProcessor* kNullShaderFP = nullptr;
+ static const GrFragmentProcessor** kIgnoreShader = &kNullShaderFP;
+ return skpaint_to_grpaint_impl(context, skPaint, SkMatrix::I(), kIgnoreShader, nullptr, false,
+ grPaint);
+}
+
+/** Blends the SkPaint's shader (or color if no shader) with a per-primitive color which must
+be setup as a vertex attribute using the specified SkXfermode::Mode. */
+bool SkPaintToGrPaintWithXfermode(GrContext* context,
+ const SkPaint& skPaint,
+ const SkMatrix& viewM,
+ SkXfermode::Mode primColorMode,
+ bool primitiveIsSrc,
+ GrPaint* grPaint) {
+ return skpaint_to_grpaint_impl(context, skPaint, viewM, nullptr, &primColorMode, primitiveIsSrc,
+ grPaint);
+}
+
+
+////////////////////////////////////////////////////////////////////////////////////////////////
+
SkImageInfo GrMakeInfoFromTexture(GrTexture* tex, int w, int h, bool isOpaque) {
#ifdef SK_DEBUG
const GrSurfaceDesc& desc = tex->desc();
diff --git a/src/gpu/SkGrPriv.h b/src/gpu/SkGrPriv.h
index 5cf4dd2..56a086e 100644
--- a/src/gpu/SkGrPriv.h
+++ b/src/gpu/SkGrPriv.h
@@ -9,10 +9,17 @@
#define SkGrPriv_DEFINED
#include "GrTypes.h"
-#include "SkPoint.h"
+#include "SkImageInfo.h"
+#include "SkXfermode.h"
class GrCaps;
+class GrContext;
+class GrFragmentProcessor;
+class GrPaint;
class GrUniqueKey;
+class SkPaint;
+class SkMatrix;
+struct SkIRect;
/**
* Our key includes the offset, width, and height so that bitmaps created by extractSubset()
@@ -28,4 +35,35 @@
void GrMakeKeyFromImageID(GrUniqueKey* key, uint32_t imageID, const SkIRect& imageBounds,
const GrCaps&, SkImageUsageType);
+/** Converts an SkPaint to a GrPaint for a given GrContext. The matrix is required in order
+ to convert the SkShader (if any) on the SkPaint. */
+bool SkPaintToGrPaint(GrContext*,
+ const SkPaint& skPaint,
+ const SkMatrix& viewM,
+ GrPaint* grPaint);
+
+/** Ignores the SkShader (if any) on skPaint. */
+bool SkPaintToGrPaintNoShader(GrContext* context,
+ const SkPaint& skPaint,
+ GrPaint* grPaint);
+
+/** Replaces the SkShader (if any) on skPaint with the passed in GrFragmentProcessor. The processor
+ should expect an unpremul input color and produce a premultiplied output color. */
+bool SkPaintToGrPaintReplaceShader(GrContext*,
+ const SkPaint& skPaint,
+ const GrFragmentProcessor* shaderFP,
+ GrPaint* grPaint);
+
+/** Blends the SkPaint's shader (or color if no shader) with the color which specified via a
+ GrBatch's GrPrimitiveProcesssor. Currently there is a bool param to indicate whether the
+ primitive color is the dst or src color to the blend in order to work around differences between
+ drawVertices and drawAtlas.
+ */
+bool SkPaintToGrPaintWithXfermode(GrContext* context,
+ const SkPaint& skPaint,
+ const SkMatrix& viewM,
+ SkXfermode::Mode primColorMode,
+ bool primitiveIsSrc,
+ GrPaint* grPaint);
+
#endif
diff --git a/src/gpu/batches/GrDrawAtlasBatch.cpp b/src/gpu/batches/GrDrawAtlasBatch.cpp
index 2254e9c..5ecdc1f 100644
--- a/src/gpu/batches/GrDrawAtlasBatch.cpp
+++ b/src/gpu/batches/GrDrawAtlasBatch.cpp
@@ -13,12 +13,21 @@
#include "SkRSXform.h"
void GrDrawAtlasBatch::initBatchTracker(const GrPipelineOptimizations& opt) {
+ SkASSERT(fGeoData.count() == 1);
// Handle any color overrides
if (!opt.readsColor()) {
fGeoData[0].fColor = GrColor_ILLEGAL;
}
- opt.getOverrideColorIfSet(&fGeoData[0].fColor);
-
+ if (opt.getOverrideColorIfSet(&fGeoData[0].fColor) && fHasColors) {
+ size_t vertexStride = sizeof(SkPoint) + sizeof(SkPoint) +
+ (this->hasColors() ? sizeof(GrColor) : 0);
+ uint8_t* currVertex = fGeoData[0].fVerts.begin();
+ for (int i = 0; i < 4*fQuadCount; ++i) {
+ *(reinterpret_cast<GrColor*>(currVertex + sizeof(SkPoint))) = fGeoData[0].fColor;
+ currVertex += vertexStride;
+ }
+ }
+
// setup batch properties
fColorIgnored = !opt.readsColor();
fColor = fGeoData[0].fColor;
@@ -117,7 +126,7 @@
if (paintAlpha != 255) {
color = SkColorSetA(color, SkMulDiv255Round(SkColorGetA(color), paintAlpha));
}
- GrColor grColor = SkColor2GrColor(color);
+ GrColor grColor = SkColorToPremulGrColor(color);
*(reinterpret_cast<GrColor*>(currVertex+sizeof(SkPoint))) = grColor;
*(reinterpret_cast<GrColor*>(currVertex+vertexStride+sizeof(SkPoint))) = grColor;
diff --git a/src/gpu/effects/GrXfermodeFragmentProcessor.cpp b/src/gpu/effects/GrXfermodeFragmentProcessor.cpp
index 2bd6412..ec2f1f3 100644
--- a/src/gpu/effects/GrXfermodeFragmentProcessor.cpp
+++ b/src/gpu/effects/GrXfermodeFragmentProcessor.cpp
@@ -90,27 +90,18 @@
GrGLFragmentBuilder* fsBuilder = args.fBuilder->getFragmentShaderBuilder();
const ComposeTwoFragmentProcessor& cs = args.fFp.cast<ComposeTwoFragmentProcessor>();
- // Store alpha of input color and un-premultiply the input color by its alpha. We will
- // re-multiply by this alpha after blending the output colors of the two child procs.
- // This is because we don't want the paint's alpha to affect either child proc's output
- // before the blend; we want to apply the paint's alpha AFTER the blend. This mirrors the
- // software implementation of SkComposeShader.
- const char* opaqueInput = nullptr;
- const char* inputAlpha = nullptr;
+ const char* inputColor = nullptr;
if (args.fInputColor) {
- inputAlpha = "inputAlpha";
- opaqueInput = "opaqueInput";
- fsBuilder->codeAppendf("float inputAlpha = %s.a;", args.fInputColor);
- fsBuilder->codeAppendf("vec4 opaqueInput = vec4(%s.rgb / inputAlpha, 1);",
- args.fInputColor);
+ inputColor = "inputColor";
+ fsBuilder->codeAppendf("vec4 inputColor = vec4(%s.rgb, 1.0);", args.fInputColor);
}
// declare outputColor and emit the code for each of the two children
SkString srcColor("src");
- this->emitChild(0, opaqueInput, &srcColor, args);
+ this->emitChild(0, inputColor, &srcColor, args);
SkString dstColor("dst");
- this->emitChild(1, opaqueInput, &dstColor, args);
+ this->emitChild(1, inputColor, &dstColor, args);
// emit blend code
SkXfermode::Mode mode = cs.getMode();
@@ -118,8 +109,8 @@
GrGLSLBlend::AppendMode(fsBuilder, srcColor.c_str(), dstColor.c_str(), args.fOutputColor, mode);
// re-multiply the output color by the input color's alpha
- if (inputAlpha) {
- fsBuilder->codeAppendf("%s *= %s;", args.fOutputColor, inputAlpha);
+ if (args.fInputColor) {
+ fsBuilder->codeAppendf("%s *= %s.a;", args.fOutputColor, args.fInputColor);
}
}
diff --git a/src/image/SkImageShader.cpp b/src/image/SkImageShader.cpp
index 957081d..fde0f0c 100644
--- a/src/image/SkImageShader.cpp
+++ b/src/image/SkImageShader.cpp
@@ -138,7 +138,7 @@
if (GrPixelConfigIsAlphaOnly(texture->config())) {
return SkRef(inner.get());
}
- return GrFragmentProcessor::MulOuputByInputAlpha(inner);
+ return GrFragmentProcessor::MulOutputByInputAlpha(inner);
}
#endif
diff --git a/tests/GpuColorFilterTest.cpp b/tests/GpuColorFilterTest.cpp
index 7e99063..a99e91b 100644
--- a/tests/GpuColorFilterTest.cpp
+++ b/tests/GpuColorFilterTest.cpp
@@ -62,8 +62,8 @@
const SkColor c1 = SkColorSetARGB(200, 200, 200, 200);
const SkColor c2 = SkColorSetARGB(60, 60, 60, 60);
- const GrColor gr_c1 = SkColor2GrColor(c1);
- const GrColor gr_c2 = SkColor2GrColor(c2);
+ const GrColor gr_c1 = SkColorToPremulGrColor(c1);
+ const GrColor gr_c2 = SkColorToPremulGrColor(c2);
const GrColor gr_black = GrColorPackA4(0);
const GrColor gr_white = GrColorPackA4(255);