Move Gpu ArithmeticMode xfer effect to _gpu files.

BUG=skia:

Review URL: https://codereview.chromium.org/827163004
This commit is contained in:
egdaniel 2015-01-14 10:49:18 -08:00 committed by Commit bot
parent 5236cf480d
commit 16a04b8414
4 changed files with 250 additions and 206 deletions

View File

@ -12,6 +12,8 @@
'<(skia_src_path)/effects/SkAlphaThresholdFilter.cpp',
'<(skia_src_path)/effects/SkArcToPathEffect.cpp',
'<(skia_src_path)/effects/SkArithmeticMode.cpp',
'<(skia_src_path)/effects/SkArithmeticMode_gpu.cpp',
'<(skia_src_path)/effects/SkArithmeticMode_gpu.h',
'<(skia_src_path)/effects/SkAvoidXfermode.cpp',
'<(skia_src_path)/effects/SkBitmapSource.cpp',
'<(skia_src_path)/effects/SkBlurDrawLooper.cpp',

View File

@ -12,11 +12,7 @@
#include "SkString.h"
#include "SkUnPreMultiply.h"
#if SK_SUPPORT_GPU
#include "GrContext.h"
#include "GrCoordTransform.h"
#include "GrInvariantOutput.h"
#include "gl/GrGLProcessor.h"
#include "gl/builders/GrGLProgramBuilder.h"
#include "SkArithmeticMode_gpu.h"
#endif
static const bool gUseUnpremul = false;
@ -237,210 +233,15 @@ SkXfermode* SkArithmeticMode::Create(SkScalar k1, SkScalar k2,
//////////////////////////////////////////////////////////////////////////////
#if SK_SUPPORT_GPU
class GrGLArithmeticEffect : public GrGLFragmentProcessor {
public:
GrGLArithmeticEffect(const GrProcessor&);
virtual ~GrGLArithmeticEffect();
virtual void emitCode(GrGLFPBuilder*,
const GrFragmentProcessor&,
const char* outputColor,
const char* inputColor,
const TransformedCoordsArray&,
const TextureSamplerArray&) SK_OVERRIDE;
void setData(const GrGLProgramDataManager&, const GrProcessor&) SK_OVERRIDE;
static void GenKey(const GrProcessor&, const GrGLCaps& caps, GrProcessorKeyBuilder* b);
private:
GrGLProgramDataManager::UniformHandle fKUni;
bool fEnforcePMColor;
typedef GrGLFragmentProcessor INHERITED;
};
///////////////////////////////////////////////////////////////////////////////
class GrArithmeticEffect : public GrFragmentProcessor {
public:
static GrFragmentProcessor* Create(float k1, float k2, float k3, float k4, bool enforcePMColor,
GrTexture* background) {
return SkNEW_ARGS(GrArithmeticEffect, (k1, k2, k3, k4, enforcePMColor, background));
}
virtual ~GrArithmeticEffect();
const char* name() const SK_OVERRIDE { return "Arithmetic"; }
virtual void getGLProcessorKey(const GrGLCaps& caps,
GrProcessorKeyBuilder* b) const SK_OVERRIDE {
GrGLArithmeticEffect::GenKey(*this, caps, b);
}
GrGLFragmentProcessor* createGLInstance() const SK_OVERRIDE {
return SkNEW_ARGS(GrGLArithmeticEffect, (*this));
}
GrTexture* backgroundTexture() const { return fBackgroundAccess.getTexture(); }
float k1() const { return fK1; }
float k2() const { return fK2; }
float k3() const { return fK3; }
float k4() const { return fK4; }
bool enforcePMColor() const { return fEnforcePMColor; }
private:
bool onIsEqual(const GrFragmentProcessor&) const SK_OVERRIDE;
void onComputeInvariantOutput(GrInvariantOutput* inout) const SK_OVERRIDE;
GrArithmeticEffect(float k1, float k2, float k3, float k4, bool enforcePMColor,
GrTexture* background);
float fK1, fK2, fK3, fK4;
bool fEnforcePMColor;
GrCoordTransform fBackgroundTransform;
GrTextureAccess fBackgroundAccess;
GR_DECLARE_FRAGMENT_PROCESSOR_TEST;
typedef GrFragmentProcessor INHERITED;
};
///////////////////////////////////////////////////////////////////////////////
GrArithmeticEffect::GrArithmeticEffect(float k1, float k2, float k3, float k4,
bool enforcePMColor, GrTexture* background)
: fK1(k1), fK2(k2), fK3(k3), fK4(k4), fEnforcePMColor(enforcePMColor) {
this->initClassID<GrArithmeticEffect>();
if (background) {
fBackgroundTransform.reset(kLocal_GrCoordSet, background,
GrTextureParams::kNone_FilterMode);
this->addCoordTransform(&fBackgroundTransform);
fBackgroundAccess.reset(background);
this->addTextureAccess(&fBackgroundAccess);
} else {
this->setWillReadDstColor();
}
}
GrArithmeticEffect::~GrArithmeticEffect() {
}
bool GrArithmeticEffect::onIsEqual(const GrFragmentProcessor& sBase) const {
const GrArithmeticEffect& s = sBase.cast<GrArithmeticEffect>();
return fK1 == s.fK1 &&
fK2 == s.fK2 &&
fK3 == s.fK3 &&
fK4 == s.fK4 &&
fEnforcePMColor == s.fEnforcePMColor;
}
void GrArithmeticEffect::onComputeInvariantOutput(GrInvariantOutput* inout) const {
// TODO: optimize this
inout->setToUnknown(GrInvariantOutput::kWill_ReadInput);
}
///////////////////////////////////////////////////////////////////////////////
GrGLArithmeticEffect::GrGLArithmeticEffect(const GrProcessor&)
: fEnforcePMColor(true) {
}
GrGLArithmeticEffect::~GrGLArithmeticEffect() {
}
void GrGLArithmeticEffect::emitCode(GrGLFPBuilder* builder,
const GrFragmentProcessor& fp,
const char* outputColor,
const char* inputColor,
const TransformedCoordsArray& coords,
const TextureSamplerArray& samplers) {
GrTexture* backgroundTex = fp.cast<GrArithmeticEffect>().backgroundTexture();
GrGLFPFragmentBuilder* fsBuilder = builder->getFragmentShaderBuilder();
const char* dstColor;
if (backgroundTex) {
fsBuilder->codeAppend("\t\tvec4 bgColor = ");
fsBuilder->appendTextureLookup(samplers[0], coords[0].c_str(), coords[0].getType());
fsBuilder->codeAppendf(";\n");
dstColor = "bgColor";
} else {
dstColor = fsBuilder->dstColor();
}
SkASSERT(dstColor);
fKUni = builder->addUniform(GrGLProgramBuilder::kFragment_Visibility,
kVec4f_GrSLType, kDefault_GrSLPrecision,
"k");
const char* kUni = builder->getUniformCStr(fKUni);
// We don't try to optimize for this case at all
if (NULL == inputColor) {
fsBuilder->codeAppendf("\t\tconst vec4 src = vec4(1);\n");
} else {
fsBuilder->codeAppendf("\t\tvec4 src = %s;\n", inputColor);
if (gUseUnpremul) {
fsBuilder->codeAppendf("\t\tsrc.rgb = clamp(src.rgb / src.a, 0.0, 1.0);\n");
}
}
fsBuilder->codeAppendf("\t\tvec4 dst = %s;\n", dstColor);
if (gUseUnpremul) {
fsBuilder->codeAppendf("\t\tdst.rgb = clamp(dst.rgb / dst.a, 0.0, 1.0);\n");
}
fsBuilder->codeAppendf("\t\t%s = %s.x * src * dst + %s.y * src + %s.z * dst + %s.w;\n", outputColor, kUni, kUni, kUni, kUni);
fsBuilder->codeAppendf("\t\t%s = clamp(%s, 0.0, 1.0);\n", outputColor, outputColor);
if (gUseUnpremul) {
fsBuilder->codeAppendf("\t\t%s.rgb *= %s.a;\n", outputColor, outputColor);
} else if (fEnforcePMColor) {
fsBuilder->codeAppendf("\t\t%s.rgb = min(%s.rgb, %s.a);\n", outputColor, outputColor, outputColor);
}
}
void GrGLArithmeticEffect::setData(const GrGLProgramDataManager& pdman,
const GrProcessor& processor) {
const GrArithmeticEffect& arith = processor.cast<GrArithmeticEffect>();
pdman.set4f(fKUni, arith.k1(), arith.k2(), arith.k3(), arith.k4());
fEnforcePMColor = arith.enforcePMColor();
}
void GrGLArithmeticEffect::GenKey(const GrProcessor& processor,
const GrGLCaps&, GrProcessorKeyBuilder* b) {
const GrArithmeticEffect& arith = processor.cast<GrArithmeticEffect>();
uint32_t key = arith.enforcePMColor() ? 1 : 0;
if (arith.backgroundTexture()) {
key |= 2;
}
b->add32(key);
}
GrFragmentProcessor* GrArithmeticEffect::TestCreate(SkRandom* rand,
GrContext*,
const GrDrawTargetCaps&,
GrTexture*[]) {
float k1 = rand->nextF();
float k2 = rand->nextF();
float k3 = rand->nextF();
float k4 = rand->nextF();
bool enforcePMColor = rand->nextBool();
return SkNEW_ARGS(GrArithmeticEffect, (k1, k2, k3, k4, enforcePMColor, NULL));
}
GR_DEFINE_FRAGMENT_PROCESSOR_TEST(GrArithmeticEffect);
bool SkArithmeticMode_scalar::asFragmentProcessor(GrFragmentProcessor** fp,
GrTexture* background) const {
if (fp) {
*fp = GrArithmeticEffect::Create(SkScalarToFloat(fK[0]),
SkScalarToFloat(fK[1]),
SkScalarToFloat(fK[2]),
SkScalarToFloat(fK[3]),
fEnforcePMColor,
background);
*fp = GrArithmeticFP::Create(SkScalarToFloat(fK[0]),
SkScalarToFloat(fK[1]),
SkScalarToFloat(fK[2]),
SkScalarToFloat(fK[3]),
fEnforcePMColor,
background);
}
return true;
}

View File

@ -0,0 +1,174 @@
/*
* Copyright 2015 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#include "SkArithmeticMode_gpu.h"
#if SK_SUPPORT_GPU
#include "GrContext.h"
#include "GrFragmentProcessor.h"
#include "GrInvariantOutput.h"
#include "GrProcessor.h"
#include "GrTexture.h"
#include "gl/GrGLCaps.h"
#include "gl/GrGLProcessor.h"
#include "gl/GrGLProgramDataManager.h"
#include "gl/builders/GrGLProgramBuilder.h"
static const bool gUseUnpremul = false;
class GLArithmeticFP : public GrGLFragmentProcessor {
public:
GLArithmeticFP(const GrProcessor&);
virtual ~GLArithmeticFP();
virtual void emitCode(GrGLFPBuilder*,
const GrFragmentProcessor&,
const char* outputColor,
const char* inputColor,
const TransformedCoordsArray&,
const TextureSamplerArray&) SK_OVERRIDE;
virtual void setData(const GrGLProgramDataManager&, const GrProcessor&) SK_OVERRIDE;
static void GenKey(const GrProcessor&, const GrGLCaps& caps, GrProcessorKeyBuilder* b);
private:
GrGLProgramDataManager::UniformHandle fKUni;
bool fEnforcePMColor;
typedef GrGLFragmentProcessor INHERITED;
};
///////////////////////////////////////////////////////////////////////////////
GrArithmeticFP::GrArithmeticFP(float k1, float k2, float k3, float k4,
bool enforcePMColor, GrTexture* background)
: fK1(k1), fK2(k2), fK3(k3), fK4(k4), fEnforcePMColor(enforcePMColor) {
this->initClassID<GrArithmeticFP>();
if (background) {
fBackgroundTransform.reset(kLocal_GrCoordSet, background,
GrTextureParams::kNone_FilterMode);
this->addCoordTransform(&fBackgroundTransform);
fBackgroundAccess.reset(background);
this->addTextureAccess(&fBackgroundAccess);
} else {
this->setWillReadDstColor();
}
}
void GrArithmeticFP::getGLProcessorKey(const GrGLCaps& caps, GrProcessorKeyBuilder* b) const {
GLArithmeticFP::GenKey(*this, caps, b);
}
GrGLFragmentProcessor* GrArithmeticFP::createGLInstance() const {
return SkNEW_ARGS(GLArithmeticFP, (*this));
}
bool GrArithmeticFP::onIsEqual(const GrFragmentProcessor& fpBase) const {
const GrArithmeticFP& fp = fpBase.cast<GrArithmeticFP>();
return fK1 == fp.fK1 &&
fK2 == fp.fK2 &&
fK3 == fp.fK3 &&
fK4 == fp.fK4 &&
fEnforcePMColor == fp.fEnforcePMColor;
}
void GrArithmeticFP::onComputeInvariantOutput(GrInvariantOutput* inout) const {
// TODO: optimize this
inout->setToUnknown(GrInvariantOutput::kWill_ReadInput);
}
///////////////////////////////////////////////////////////////////////////////
GLArithmeticFP::GLArithmeticFP(const GrProcessor&)
: fEnforcePMColor(true) {
}
GLArithmeticFP::~GLArithmeticFP() {
}
void GLArithmeticFP::emitCode(GrGLFPBuilder* builder,
const GrFragmentProcessor& fp,
const char* outputColor,
const char* inputColor,
const TransformedCoordsArray& coords,
const TextureSamplerArray& samplers) {
GrTexture* backgroundTex = fp.cast<GrArithmeticFP>().backgroundTexture();
GrGLFPFragmentBuilder* fsBuilder = builder->getFragmentShaderBuilder();
const char* dstColor;
if (backgroundTex) {
fsBuilder->codeAppend("\t\tvec4 bgColor = ");
fsBuilder->appendTextureLookup(samplers[0], coords[0].c_str(), coords[0].getType());
fsBuilder->codeAppendf(";\n");
dstColor = "bgColor";
} else {
dstColor = fsBuilder->dstColor();
}
SkASSERT(dstColor);
fKUni = builder->addUniform(GrGLProgramBuilder::kFragment_Visibility,
kVec4f_GrSLType, kDefault_GrSLPrecision,
"k");
const char* kUni = builder->getUniformCStr(fKUni);
// We don't try to optimize for this case at all
if (NULL == inputColor) {
fsBuilder->codeAppendf("\t\tconst vec4 src = vec4(1);\n");
} else {
fsBuilder->codeAppendf("\t\tvec4 src = %s;\n", inputColor);
if (gUseUnpremul) {
fsBuilder->codeAppendf("\t\tsrc.rgb = clamp(src.rgb / src.a, 0.0, 1.0);\n");
}
}
fsBuilder->codeAppendf("\t\tvec4 dst = %s;\n", dstColor);
if (gUseUnpremul) {
fsBuilder->codeAppendf("\t\tdst.rgb = clamp(dst.rgb / dst.a, 0.0, 1.0);\n");
}
fsBuilder->codeAppendf("\t\t%s = %s.x * src * dst + %s.y * src + %s.z * dst + %s.w;\n", outputColor, kUni, kUni, kUni, kUni);
fsBuilder->codeAppendf("\t\t%s = clamp(%s, 0.0, 1.0);\n", outputColor, outputColor);
if (gUseUnpremul) {
fsBuilder->codeAppendf("\t\t%s.rgb *= %s.a;\n", outputColor, outputColor);
} else if (fEnforcePMColor) {
fsBuilder->codeAppendf("\t\t%s.rgb = min(%s.rgb, %s.a);\n", outputColor, outputColor, outputColor);
}
}
void GLArithmeticFP::setData(const GrGLProgramDataManager& pdman, const GrProcessor& processor) {
const GrArithmeticFP& arith = processor.cast<GrArithmeticFP>();
pdman.set4f(fKUni, arith.k1(), arith.k2(), arith.k3(), arith.k4());
fEnforcePMColor = arith.enforcePMColor();
}
void GLArithmeticFP::GenKey(const GrProcessor& processor, const GrGLCaps&,
GrProcessorKeyBuilder* b) {
const GrArithmeticFP& arith = processor.cast<GrArithmeticFP>();
uint32_t key = arith.enforcePMColor() ? 1 : 0;
if (arith.backgroundTexture()) {
key |= 2;
}
b->add32(key);
}
GrFragmentProcessor* GrArithmeticFP::TestCreate(SkRandom* rand,
GrContext*,
const GrDrawTargetCaps&,
GrTexture*[]) {
float k1 = rand->nextF();
float k2 = rand->nextF();
float k3 = rand->nextF();
float k4 = rand->nextF();
bool enforcePMColor = rand->nextBool();
return SkNEW_ARGS(GrArithmeticFP, (k1, k2, k3, k4, enforcePMColor, NULL));
}
GR_DEFINE_FRAGMENT_PROCESSOR_TEST(GrArithmeticFP);
#endif

View File

@ -0,0 +1,67 @@
/*
* Copyright 2015 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#ifndef SkArithmeticMode_gpu_DEFINED
#define SkArithmeticMode_gpu_DEFINED
#if SK_SUPPORT_GPU
#include "GrCoordTransform.h"
#include "GrFragmentProcessor.h"
#include "GrTextureAccess.h"
class GrInvariantOutput;
class GrTexture;
///////////////////////////////////////////////////////////////////////////////
// Fragment Processor
///////////////////////////////////////////////////////////////////////////////
class GrGLArtithmeticFP;
class GrArithmeticFP : public GrFragmentProcessor {
public:
static GrFragmentProcessor* Create(float k1, float k2, float k3, float k4, bool enforcePMColor,
GrTexture* background) {
return SkNEW_ARGS(GrArithmeticFP, (k1, k2, k3, k4, enforcePMColor, background));
}
~GrArithmeticFP() SK_OVERRIDE {};
const char* name() const SK_OVERRIDE { return "Arithmetic"; }
void getGLProcessorKey(const GrGLCaps& caps, GrProcessorKeyBuilder* b) const SK_OVERRIDE;
GrGLFragmentProcessor* createGLInstance() const SK_OVERRIDE;
GrTexture* backgroundTexture() const { return fBackgroundAccess.getTexture(); }
float k1() const { return fK1; }
float k2() const { return fK2; }
float k3() const { return fK3; }
float k4() const { return fK4; }
bool enforcePMColor() const { return fEnforcePMColor; }
private:
bool onIsEqual(const GrFragmentProcessor&) const SK_OVERRIDE;
void onComputeInvariantOutput(GrInvariantOutput* inout) const SK_OVERRIDE;
GrArithmeticFP(float k1, float k2, float k3, float k4, bool enforcePMColor,
GrTexture* background);
float fK1, fK2, fK3, fK4;
bool fEnforcePMColor;
GrCoordTransform fBackgroundTransform;
GrTextureAccess fBackgroundAccess;
GR_DECLARE_FRAGMENT_PROCESSOR_TEST;
typedef GrFragmentProcessor INHERITED;
};
#endif
#endif