Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(364)

Unified Diff: src/core/SkComposeShader.cpp

Issue 1292353005: Added SkComposeShader GPU implementation (Closed) Base URL: https://skia.googlesource.com/skia@cs3_glinstances2
Patch Set: removed children's names from name of GrComposeEffect Created 5 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « include/core/SkComposeShader.h ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/core/SkComposeShader.cpp
diff --git a/src/core/SkComposeShader.cpp b/src/core/SkComposeShader.cpp
index c16d7ffc578f352f948d432934c68c41851c6623..a188e7908c549d5af1c7faa54030187bf52d10d2 100644
--- a/src/core/SkComposeShader.cpp
+++ b/src/core/SkComposeShader.cpp
@@ -194,6 +194,171 @@ void SkComposeShader::ComposeShaderContext::shadeSpan(int x, int y, SkPMColor re
}
}
+#if SK_SUPPORT_GPU
+
+#include "SkGr.h"
+#include "GrProcessor.h"
+#include "gl/GrGLBlend.h"
+#include "gl/builders/GrGLProgramBuilder.h"
+
+/////////////////////////////////////////////////////////////////////
+
+class GrComposeEffect : public GrFragmentProcessor {
+public:
+
+ static GrFragmentProcessor* Create(GrFragmentProcessor* fpA, GrFragmentProcessor* fpB,
+ SkXfermode::Mode mode) {
+ return SkNEW_ARGS(GrComposeEffect, (fpA, fpB, mode));
+ }
+ const char* name() const override {return fName.c_str(); }
+ void onGetGLProcessorKey(const GrGLSLCaps& caps, GrProcessorKeyBuilder* b) const override;
+
+ SkXfermode::Mode getMode() const { return fMode; }
+ int getShaderAChildIndex() const { return fShaderAChildIndex; }
+ int getShaderBChildIndex() const { return fShaderBChildIndex; }
+
+protected:
+ bool onIsEqual(const GrFragmentProcessor&) const override;
+ void onComputeInvariantOutput(GrInvariantOutput* inout) const override;
+
+private:
+ GrComposeEffect(GrFragmentProcessor* fpA, GrFragmentProcessor* fpB, SkXfermode::Mode mode)
+ : fMode(mode) {
+ this->initClassID<GrComposeEffect>();
+ fShaderAChildIndex = this->registerChildProcessor(fpA);
+ fShaderBChildIndex = this->registerChildProcessor(fpB);
+ fName.printf("ComposeShader (Mode: %s)", SkXfermode::ModeName(fMode));
bsalomon 2015/08/27 20:12:24 Maybe we should init this in name()? I believe it
wangyix 2015/08/31 14:10:05 I'm not sure what you mean by this. On another no
bsalomon 2015/08/31 14:48:35 Let's go with that. I just don't want the construc
wangyix 2015/08/31 18:22:09 Done.
+ }
+
+ GrGLFragmentProcessor* onCreateGLInstance() const override;
+
+ SkString fName;
+ int fShaderAChildIndex;
+ int fShaderBChildIndex;
+ SkXfermode::Mode fMode;
+
+ typedef GrFragmentProcessor INHERITED;
+};
+
+/////////////////////////////////////////////////////////////////////
+
+class GrGLComposeEffect : public GrGLFragmentProcessor {
+public:
+ GrGLComposeEffect(const GrProcessor& processor) {
+ const GrComposeEffect& cs = processor.cast<GrComposeEffect>();
+ fShaderAChildIndex = cs.getShaderAChildIndex();
+ fShaderBChildIndex = cs.getShaderBChildIndex();
+ fMode = cs.getMode();
+ }
+
+ void emitCode(EmitArgs&) override;
+
+private:
+ int fShaderAChildIndex;
+ int fShaderBChildIndex;
+ SkXfermode::Mode fMode;
+
+ typedef GrGLFragmentProcessor INHERITED;
+};
+
+bool GrComposeEffect::onIsEqual(const GrFragmentProcessor& other) const {
+ const GrComposeEffect& cs = other.cast<GrComposeEffect>();
+ return fMode == cs.fMode;
+}
+
+void GrComposeEffect::onComputeInvariantOutput(GrInvariantOutput* inout) const {
+ inout->setToUnknown(GrInvariantOutput::kWill_ReadInput);
+}
+
+void GrComposeEffect::onGetGLProcessorKey(const GrGLSLCaps& caps, GrProcessorKeyBuilder* b) const {
+ b->add32(fMode);
+}
+
+GrGLFragmentProcessor* GrComposeEffect::onCreateGLInstance() const{
+ return SkNEW_ARGS(GrGLComposeEffect, (*this));
+}
+
+/////////////////////////////////////////////////////////////////////
+
+void GrGLComposeEffect::emitCode(EmitArgs& args) {
+
+ GrGLFragmentBuilder* fsBuilder = args.fBuilder->getFragmentShaderBuilder();
+
+ // 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.
+ SkString inputAlpha("inputAlpha");
+ fsBuilder->codeAppendf("float %s = %s.a;\n", inputAlpha.c_str(), args.fInputColor);
+ fsBuilder->codeAppendf("%s /= %s.a;\n", args.fInputColor, args.fInputColor);
+
+ // emit the code of the two child shaders
+ SkString mangledOutputColorA;
+ this->emitChild(fShaderAChildIndex, args.fInputColor, &mangledOutputColorA, args);
+ SkString mangledOutputColorB;
+ this->emitChild(fShaderBChildIndex, args.fInputColor, &mangledOutputColorB, args);
+
+ // emit blend code
+ fsBuilder->codeAppend("{\n");
+ fsBuilder->codeAppendf("// Compose Xfer Mode: %s\n", SkXfermode::ModeName(fMode));
+ GrGLBlend::AppendPorterDuffBlend(fsBuilder, mangledOutputColorB.c_str(),
+ mangledOutputColorA.c_str(), args.fOutputColor, fMode);
+ fsBuilder->codeAppend("}\n");
+
+ // re-multiply the output color by the input color's alpha
+ fsBuilder->codeAppendf("%s *= %s;\n", args.fOutputColor, inputAlpha.c_str());
+}
+
+/////////////////////////////////////////////////////////////////////
+
+bool SkComposeShader::asFragmentProcessor(GrContext* context, const SkPaint& paint,
+ const SkMatrix& viewM, const SkMatrix* localMatrix,
+ GrColor* paintColor,
+ GrProcessorDataManager* procDataManager,
+ GrFragmentProcessor** fp) const {
+ // NULL fMode implies src-over
+ SkXfermode::Mode mode = SkXfermode::Mode::kSrcOver_Mode;
+ if (fMode) {
+ // Fragment processor will only support coefficient modes that aren't kClear_Mode.
+ // This is because GrGLBlend::AppendPorterDuffBlend(), which emits the blend code in the
+ // shader, only supports those xfer modes.
+ SkXfermode::Coeff srcCoeff, dstCoeff;
+ if (!fMode->asMode(&mode) || !SkXfermode::ModeAsCoeff(mode, &srcCoeff, &dstCoeff)
+ || mode == SkXfermode::Mode::kClear_Mode) {
wangyix 2015/08/31 14:10:05 What should the behavior be for kClear_Mode under
egdaniel 2015/08/31 14:43:05 Did AppendPorterDuffBlend() ever get fixed to supp
bsalomon 2015/08/31 14:48:35 Hm... I think making kSrc, kDst, kClear FPs is may
wangyix 2015/08/31 15:59:24 If the clear optimization happens in GrComposeEffe
+ return false;
+ }
+ }
+ GrFragmentProcessor* fpA = NULL;
+ if (!fShaderA->asFragmentProcessor(context, paint, viewM, localMatrix, paintColor,
+ procDataManager, &fpA) || !fpA) {
+ return false;
+ }
+ GrFragmentProcessor* fpB = NULL;
+ if (!fShaderB->asFragmentProcessor(context, paint, viewM, localMatrix, paintColor,
+ procDataManager, &fpB) || !fpB) {
+ fpA->unref();
+ return false;
+ }
+
+ *fp = GrComposeEffect::Create(fpA, fpB, mode);
+ fpA->unref();
+ fpB->unref();
+
+ return true;
+}
+
+
+
+#else
bsalomon 2015/08/28 16:15:30 Let's just put the function decl in the header beh
wangyix 2015/08/31 18:22:09 Done.
+bool SkComposeShader::asFragmentProcessor(GrContext*, const SkPaint&, const SkMatrix&,
+ const SkMatrix*, GrColor*, GrProcessorDataManager*,
+ GrFragmentProcessor**) const {
+ SkDEBUGFAIL("Should not call in GPU-less build");
+ return false;
+}
+#endif
+
#ifndef SK_IGNORE_TO_STRING
void SkComposeShader::toString(SkString* str) const {
str->append("SkComposeShader: (");
« no previous file with comments | « include/core/SkComposeShader.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698