116a04b84147867b62f92969ac8f4f4a9ab009aeaegdaniel/* 216a04b84147867b62f92969ac8f4f4a9ab009aeaegdaniel * Copyright 2015 Google Inc. 316a04b84147867b62f92969ac8f4f4a9ab009aeaegdaniel * 416a04b84147867b62f92969ac8f4f4a9ab009aeaegdaniel * Use of this source code is governed by a BSD-style license that can be 516a04b84147867b62f92969ac8f4f4a9ab009aeaegdaniel * found in the LICENSE file. 616a04b84147867b62f92969ac8f4f4a9ab009aeaegdaniel */ 716a04b84147867b62f92969ac8f4f4a9ab009aeaegdaniel 816a04b84147867b62f92969ac8f4f4a9ab009aeaegdaniel#include "SkArithmeticMode_gpu.h" 916a04b84147867b62f92969ac8f4f4a9ab009aeaegdaniel 1016a04b84147867b62f92969ac8f4f4a9ab009aeaegdaniel#if SK_SUPPORT_GPU 1116a04b84147867b62f92969ac8f4f4a9ab009aeaegdaniel#include "GrContext.h" 1216a04b84147867b62f92969ac8f4f4a9ab009aeaegdaniel#include "GrFragmentProcessor.h" 1316a04b84147867b62f92969ac8f4f4a9ab009aeaegdaniel#include "GrInvariantOutput.h" 1416a04b84147867b62f92969ac8f4f4a9ab009aeaegdaniel#include "GrProcessor.h" 1516a04b84147867b62f92969ac8f4f4a9ab009aeaegdaniel#include "GrTexture.h" 1616a04b84147867b62f92969ac8f4f4a9ab009aeaegdaniel#include "gl/GrGLCaps.h" 1716a04b84147867b62f92969ac8f4f4a9ab009aeaegdaniel#include "gl/GrGLProcessor.h" 1816a04b84147867b62f92969ac8f4f4a9ab009aeaegdaniel#include "gl/GrGLProgramDataManager.h" 1916a04b84147867b62f92969ac8f4f4a9ab009aeaegdaniel#include "gl/builders/GrGLProgramBuilder.h" 2016a04b84147867b62f92969ac8f4f4a9ab009aeaegdaniel 2116a04b84147867b62f92969ac8f4f4a9ab009aeaegdanielstatic const bool gUseUnpremul = false; 2216a04b84147867b62f92969ac8f4f4a9ab009aeaegdaniel 2329bee0fe657fabf7c396502b69c9167fba13eaaaegdanielstatic void add_arithmetic_code(GrGLFragmentBuilder* fsBuilder, 24f351aa3bf1b1d7639be8e1e6a35137b89a8dd93degdaniel const char* inputColor, 25f351aa3bf1b1d7639be8e1e6a35137b89a8dd93degdaniel const char* dstColor, 26f351aa3bf1b1d7639be8e1e6a35137b89a8dd93degdaniel const char* outputColor, 27f351aa3bf1b1d7639be8e1e6a35137b89a8dd93degdaniel const char* kUni, 28f351aa3bf1b1d7639be8e1e6a35137b89a8dd93degdaniel bool enforcePMColor) { 29f351aa3bf1b1d7639be8e1e6a35137b89a8dd93degdaniel // We don't try to optimize for this case at all 30f351aa3bf1b1d7639be8e1e6a35137b89a8dd93degdaniel if (NULL == inputColor) { 31f351aa3bf1b1d7639be8e1e6a35137b89a8dd93degdaniel fsBuilder->codeAppend("const vec4 src = vec4(1);"); 32f351aa3bf1b1d7639be8e1e6a35137b89a8dd93degdaniel } else { 33f351aa3bf1b1d7639be8e1e6a35137b89a8dd93degdaniel fsBuilder->codeAppendf("vec4 src = %s;", inputColor); 34f351aa3bf1b1d7639be8e1e6a35137b89a8dd93degdaniel if (gUseUnpremul) { 35f351aa3bf1b1d7639be8e1e6a35137b89a8dd93degdaniel fsBuilder->codeAppend("src.rgb = clamp(src.rgb / src.a, 0.0, 1.0);"); 36f351aa3bf1b1d7639be8e1e6a35137b89a8dd93degdaniel } 37f351aa3bf1b1d7639be8e1e6a35137b89a8dd93degdaniel } 38f351aa3bf1b1d7639be8e1e6a35137b89a8dd93degdaniel 39f351aa3bf1b1d7639be8e1e6a35137b89a8dd93degdaniel fsBuilder->codeAppendf("vec4 dst = %s;", dstColor); 40f351aa3bf1b1d7639be8e1e6a35137b89a8dd93degdaniel if (gUseUnpremul) { 41f351aa3bf1b1d7639be8e1e6a35137b89a8dd93degdaniel fsBuilder->codeAppend("dst.rgb = clamp(dst.rgb / dst.a, 0.0, 1.0);"); 42f351aa3bf1b1d7639be8e1e6a35137b89a8dd93degdaniel } 43f351aa3bf1b1d7639be8e1e6a35137b89a8dd93degdaniel 44f351aa3bf1b1d7639be8e1e6a35137b89a8dd93degdaniel fsBuilder->codeAppendf("%s = %s.x * src * dst + %s.y * src + %s.z * dst + %s.w;", 45f351aa3bf1b1d7639be8e1e6a35137b89a8dd93degdaniel outputColor, kUni, kUni, kUni, kUni); 46f351aa3bf1b1d7639be8e1e6a35137b89a8dd93degdaniel fsBuilder->codeAppendf("%s = clamp(%s, 0.0, 1.0);\n", outputColor, outputColor); 47f351aa3bf1b1d7639be8e1e6a35137b89a8dd93degdaniel if (gUseUnpremul) { 48f351aa3bf1b1d7639be8e1e6a35137b89a8dd93degdaniel fsBuilder->codeAppendf("%s.rgb *= %s.a;", outputColor, outputColor); 49f351aa3bf1b1d7639be8e1e6a35137b89a8dd93degdaniel } else if (enforcePMColor) { 50f351aa3bf1b1d7639be8e1e6a35137b89a8dd93degdaniel fsBuilder->codeAppendf("%s.rgb = min(%s.rgb, %s.a);", 51f351aa3bf1b1d7639be8e1e6a35137b89a8dd93degdaniel outputColor, outputColor, outputColor); 52f351aa3bf1b1d7639be8e1e6a35137b89a8dd93degdaniel } 53f351aa3bf1b1d7639be8e1e6a35137b89a8dd93degdaniel} 54f351aa3bf1b1d7639be8e1e6a35137b89a8dd93degdaniel 5516a04b84147867b62f92969ac8f4f4a9ab009aeaegdanielclass GLArithmeticFP : public GrGLFragmentProcessor { 5616a04b84147867b62f92969ac8f4f4a9ab009aeaegdanielpublic: 57f351aa3bf1b1d7639be8e1e6a35137b89a8dd93degdaniel GLArithmeticFP(const GrProcessor&) 58f351aa3bf1b1d7639be8e1e6a35137b89a8dd93degdaniel : fEnforcePMColor(true) { 59f351aa3bf1b1d7639be8e1e6a35137b89a8dd93degdaniel } 6016a04b84147867b62f92969ac8f4f4a9ab009aeaegdaniel 6136352bf5e38f45a70ee4f4fc132a38048d38206dmtklein ~GLArithmeticFP() override {} 62f351aa3bf1b1d7639be8e1e6a35137b89a8dd93degdaniel 63f351aa3bf1b1d7639be8e1e6a35137b89a8dd93degdaniel void emitCode(GrGLFPBuilder* builder, 64f351aa3bf1b1d7639be8e1e6a35137b89a8dd93degdaniel const GrFragmentProcessor& fp, 65f351aa3bf1b1d7639be8e1e6a35137b89a8dd93degdaniel const char* outputColor, 66f351aa3bf1b1d7639be8e1e6a35137b89a8dd93degdaniel const char* inputColor, 67f351aa3bf1b1d7639be8e1e6a35137b89a8dd93degdaniel const TransformedCoordsArray& coords, 6836352bf5e38f45a70ee4f4fc132a38048d38206dmtklein const TextureSamplerArray& samplers) override { 6929bee0fe657fabf7c396502b69c9167fba13eaaaegdaniel GrGLFragmentBuilder* fsBuilder = builder->getFragmentShaderBuilder(); 70f351aa3bf1b1d7639be8e1e6a35137b89a8dd93degdaniel fsBuilder->codeAppend("vec4 bgColor = "); 71f351aa3bf1b1d7639be8e1e6a35137b89a8dd93degdaniel fsBuilder->appendTextureLookup(samplers[0], coords[0].c_str(), coords[0].getType()); 72f351aa3bf1b1d7639be8e1e6a35137b89a8dd93degdaniel fsBuilder->codeAppendf(";"); 73f351aa3bf1b1d7639be8e1e6a35137b89a8dd93degdaniel const char* dstColor = "bgColor"; 74f351aa3bf1b1d7639be8e1e6a35137b89a8dd93degdaniel 75f351aa3bf1b1d7639be8e1e6a35137b89a8dd93degdaniel fKUni = builder->addUniform(GrGLProgramBuilder::kFragment_Visibility, 76f351aa3bf1b1d7639be8e1e6a35137b89a8dd93degdaniel kVec4f_GrSLType, kDefault_GrSLPrecision, 77f351aa3bf1b1d7639be8e1e6a35137b89a8dd93degdaniel "k"); 78f351aa3bf1b1d7639be8e1e6a35137b89a8dd93degdaniel const char* kUni = builder->getUniformCStr(fKUni); 79f351aa3bf1b1d7639be8e1e6a35137b89a8dd93degdaniel 80f351aa3bf1b1d7639be8e1e6a35137b89a8dd93degdaniel add_arithmetic_code(fsBuilder, inputColor, dstColor, outputColor, kUni, fEnforcePMColor); 81f351aa3bf1b1d7639be8e1e6a35137b89a8dd93degdaniel } 8216a04b84147867b62f92969ac8f4f4a9ab009aeaegdaniel 8336352bf5e38f45a70ee4f4fc132a38048d38206dmtklein void setData(const GrGLProgramDataManager& pdman, const GrProcessor& proc) override { 84f351aa3bf1b1d7639be8e1e6a35137b89a8dd93degdaniel const GrArithmeticFP& arith = proc.cast<GrArithmeticFP>(); 85f351aa3bf1b1d7639be8e1e6a35137b89a8dd93degdaniel pdman.set4f(fKUni, arith.k1(), arith.k2(), arith.k3(), arith.k4()); 86f351aa3bf1b1d7639be8e1e6a35137b89a8dd93degdaniel fEnforcePMColor = arith.enforcePMColor(); 87f351aa3bf1b1d7639be8e1e6a35137b89a8dd93degdaniel } 8816a04b84147867b62f92969ac8f4f4a9ab009aeaegdaniel 89cfc18867d982119d9dc2888bf09f1093012daaddjvanverth static void GenKey(const GrProcessor& proc, const GrGLSLCaps& caps, GrProcessorKeyBuilder* b) { 90f351aa3bf1b1d7639be8e1e6a35137b89a8dd93degdaniel const GrArithmeticFP& arith = proc.cast<GrArithmeticFP>(); 91f351aa3bf1b1d7639be8e1e6a35137b89a8dd93degdaniel uint32_t key = arith.enforcePMColor() ? 1 : 0; 92f351aa3bf1b1d7639be8e1e6a35137b89a8dd93degdaniel b->add32(key); 93f351aa3bf1b1d7639be8e1e6a35137b89a8dd93degdaniel } 9416a04b84147867b62f92969ac8f4f4a9ab009aeaegdaniel 9516a04b84147867b62f92969ac8f4f4a9ab009aeaegdanielprivate: 9616a04b84147867b62f92969ac8f4f4a9ab009aeaegdaniel GrGLProgramDataManager::UniformHandle fKUni; 9716a04b84147867b62f92969ac8f4f4a9ab009aeaegdaniel bool fEnforcePMColor; 9816a04b84147867b62f92969ac8f4f4a9ab009aeaegdaniel 9916a04b84147867b62f92969ac8f4f4a9ab009aeaegdaniel typedef GrGLFragmentProcessor INHERITED; 10016a04b84147867b62f92969ac8f4f4a9ab009aeaegdaniel}; 10116a04b84147867b62f92969ac8f4f4a9ab009aeaegdaniel 10216a04b84147867b62f92969ac8f4f4a9ab009aeaegdaniel/////////////////////////////////////////////////////////////////////////////// 10316a04b84147867b62f92969ac8f4f4a9ab009aeaegdaniel 10416a04b84147867b62f92969ac8f4f4a9ab009aeaegdanielGrArithmeticFP::GrArithmeticFP(float k1, float k2, float k3, float k4, 10516a04b84147867b62f92969ac8f4f4a9ab009aeaegdaniel bool enforcePMColor, GrTexture* background) 10616a04b84147867b62f92969ac8f4f4a9ab009aeaegdaniel : fK1(k1), fK2(k2), fK3(k3), fK4(k4), fEnforcePMColor(enforcePMColor) { 10716a04b84147867b62f92969ac8f4f4a9ab009aeaegdaniel this->initClassID<GrArithmeticFP>(); 108f351aa3bf1b1d7639be8e1e6a35137b89a8dd93degdaniel 109f351aa3bf1b1d7639be8e1e6a35137b89a8dd93degdaniel SkASSERT(background); 110f351aa3bf1b1d7639be8e1e6a35137b89a8dd93degdaniel 111f351aa3bf1b1d7639be8e1e6a35137b89a8dd93degdaniel fBackgroundTransform.reset(kLocal_GrCoordSet, background, 112f351aa3bf1b1d7639be8e1e6a35137b89a8dd93degdaniel GrTextureParams::kNone_FilterMode); 113f351aa3bf1b1d7639be8e1e6a35137b89a8dd93degdaniel this->addCoordTransform(&fBackgroundTransform); 114f351aa3bf1b1d7639be8e1e6a35137b89a8dd93degdaniel fBackgroundAccess.reset(background); 115f351aa3bf1b1d7639be8e1e6a35137b89a8dd93degdaniel this->addTextureAccess(&fBackgroundAccess); 11616a04b84147867b62f92969ac8f4f4a9ab009aeaegdaniel} 11716a04b84147867b62f92969ac8f4f4a9ab009aeaegdaniel 118cfc18867d982119d9dc2888bf09f1093012daaddjvanverthvoid GrArithmeticFP::getGLProcessorKey(const GrGLSLCaps& caps, GrProcessorKeyBuilder* b) const { 11916a04b84147867b62f92969ac8f4f4a9ab009aeaegdaniel GLArithmeticFP::GenKey(*this, caps, b); 12016a04b84147867b62f92969ac8f4f4a9ab009aeaegdaniel} 12116a04b84147867b62f92969ac8f4f4a9ab009aeaegdaniel 12216a04b84147867b62f92969ac8f4f4a9ab009aeaegdanielGrGLFragmentProcessor* GrArithmeticFP::createGLInstance() const { 12316a04b84147867b62f92969ac8f4f4a9ab009aeaegdaniel return SkNEW_ARGS(GLArithmeticFP, (*this)); 12416a04b84147867b62f92969ac8f4f4a9ab009aeaegdaniel} 12516a04b84147867b62f92969ac8f4f4a9ab009aeaegdaniel 12616a04b84147867b62f92969ac8f4f4a9ab009aeaegdanielbool GrArithmeticFP::onIsEqual(const GrFragmentProcessor& fpBase) const { 12716a04b84147867b62f92969ac8f4f4a9ab009aeaegdaniel const GrArithmeticFP& fp = fpBase.cast<GrArithmeticFP>(); 12816a04b84147867b62f92969ac8f4f4a9ab009aeaegdaniel return fK1 == fp.fK1 && 12916a04b84147867b62f92969ac8f4f4a9ab009aeaegdaniel fK2 == fp.fK2 && 13016a04b84147867b62f92969ac8f4f4a9ab009aeaegdaniel fK3 == fp.fK3 && 13116a04b84147867b62f92969ac8f4f4a9ab009aeaegdaniel fK4 == fp.fK4 && 13216a04b84147867b62f92969ac8f4f4a9ab009aeaegdaniel fEnforcePMColor == fp.fEnforcePMColor; 13316a04b84147867b62f92969ac8f4f4a9ab009aeaegdaniel} 13416a04b84147867b62f92969ac8f4f4a9ab009aeaegdaniel 13516a04b84147867b62f92969ac8f4f4a9ab009aeaegdanielvoid GrArithmeticFP::onComputeInvariantOutput(GrInvariantOutput* inout) const { 13616a04b84147867b62f92969ac8f4f4a9ab009aeaegdaniel // TODO: optimize this 13716a04b84147867b62f92969ac8f4f4a9ab009aeaegdaniel inout->setToUnknown(GrInvariantOutput::kWill_ReadInput); 13816a04b84147867b62f92969ac8f4f4a9ab009aeaegdaniel} 13916a04b84147867b62f92969ac8f4f4a9ab009aeaegdaniel 14016a04b84147867b62f92969ac8f4f4a9ab009aeaegdaniel/////////////////////////////////////////////////////////////////////////////// 14116a04b84147867b62f92969ac8f4f4a9ab009aeaegdaniel 142f351aa3bf1b1d7639be8e1e6a35137b89a8dd93degdanielGrFragmentProcessor* GrArithmeticFP::TestCreate(SkRandom* rand, 143f351aa3bf1b1d7639be8e1e6a35137b89a8dd93degdaniel GrContext*, 144f351aa3bf1b1d7639be8e1e6a35137b89a8dd93degdaniel const GrDrawTargetCaps&, 145f351aa3bf1b1d7639be8e1e6a35137b89a8dd93degdaniel GrTexture* textures[]) { 146f351aa3bf1b1d7639be8e1e6a35137b89a8dd93degdaniel float k1 = rand->nextF(); 147f351aa3bf1b1d7639be8e1e6a35137b89a8dd93degdaniel float k2 = rand->nextF(); 148f351aa3bf1b1d7639be8e1e6a35137b89a8dd93degdaniel float k3 = rand->nextF(); 149f351aa3bf1b1d7639be8e1e6a35137b89a8dd93degdaniel float k4 = rand->nextF(); 150f351aa3bf1b1d7639be8e1e6a35137b89a8dd93degdaniel bool enforcePMColor = rand->nextBool(); 15116a04b84147867b62f92969ac8f4f4a9ab009aeaegdaniel 152f351aa3bf1b1d7639be8e1e6a35137b89a8dd93degdaniel return SkNEW_ARGS(GrArithmeticFP, (k1, k2, k3, k4, enforcePMColor, textures[0])); 15316a04b84147867b62f92969ac8f4f4a9ab009aeaegdaniel} 15416a04b84147867b62f92969ac8f4f4a9ab009aeaegdaniel 155f351aa3bf1b1d7639be8e1e6a35137b89a8dd93degdanielGR_DEFINE_FRAGMENT_PROCESSOR_TEST(GrArithmeticFP); 15616a04b84147867b62f92969ac8f4f4a9ab009aeaegdaniel 157f351aa3bf1b1d7639be8e1e6a35137b89a8dd93degdaniel/////////////////////////////////////////////////////////////////////////////// 158f351aa3bf1b1d7639be8e1e6a35137b89a8dd93degdaniel// Xfer Processor 159f351aa3bf1b1d7639be8e1e6a35137b89a8dd93degdaniel/////////////////////////////////////////////////////////////////////////////// 16016a04b84147867b62f92969ac8f4f4a9ab009aeaegdaniel 16141d4f09356567ead0216e1a7e4110bd58822b81fegdanielclass ArithmeticXP : public GrXferProcessor { 16241d4f09356567ead0216e1a7e4110bd58822b81fegdanielpublic: 16341d4f09356567ead0216e1a7e4110bd58822b81fegdaniel static GrXferProcessor* Create(float k1, float k2, float k3, float k4, bool enforcePMColor, 16441d4f09356567ead0216e1a7e4110bd58822b81fegdaniel const GrDeviceCoordTexture* dstCopy, 16541d4f09356567ead0216e1a7e4110bd58822b81fegdaniel bool willReadDstColor) { 16641d4f09356567ead0216e1a7e4110bd58822b81fegdaniel return SkNEW_ARGS(ArithmeticXP, (k1, k2, k3, k4, enforcePMColor, dstCopy, 16741d4f09356567ead0216e1a7e4110bd58822b81fegdaniel willReadDstColor)); 16841d4f09356567ead0216e1a7e4110bd58822b81fegdaniel } 16941d4f09356567ead0216e1a7e4110bd58822b81fegdaniel 17036352bf5e38f45a70ee4f4fc132a38048d38206dmtklein ~ArithmeticXP() override {}; 17141d4f09356567ead0216e1a7e4110bd58822b81fegdaniel 17236352bf5e38f45a70ee4f4fc132a38048d38206dmtklein const char* name() const override { return "Arithmetic"; } 17341d4f09356567ead0216e1a7e4110bd58822b81fegdaniel 17436352bf5e38f45a70ee4f4fc132a38048d38206dmtklein GrGLXferProcessor* createGLInstance() const override; 17541d4f09356567ead0216e1a7e4110bd58822b81fegdaniel 17636352bf5e38f45a70ee4f4fc132a38048d38206dmtklein bool hasSecondaryOutput() const override { return false; } 17741d4f09356567ead0216e1a7e4110bd58822b81fegdaniel 17841d4f09356567ead0216e1a7e4110bd58822b81fegdaniel float k1() const { return fK1; } 17941d4f09356567ead0216e1a7e4110bd58822b81fegdaniel float k2() const { return fK2; } 18041d4f09356567ead0216e1a7e4110bd58822b81fegdaniel float k3() const { return fK3; } 18141d4f09356567ead0216e1a7e4110bd58822b81fegdaniel float k4() const { return fK4; } 18241d4f09356567ead0216e1a7e4110bd58822b81fegdaniel bool enforcePMColor() const { return fEnforcePMColor; } 18341d4f09356567ead0216e1a7e4110bd58822b81fegdaniel 18441d4f09356567ead0216e1a7e4110bd58822b81fegdanielprivate: 18541d4f09356567ead0216e1a7e4110bd58822b81fegdaniel ArithmeticXP(float k1, float k2, float k3, float k4, bool enforcePMColor, 18641d4f09356567ead0216e1a7e4110bd58822b81fegdaniel const GrDeviceCoordTexture* dstCopy, bool willReadDstColor); 18741d4f09356567ead0216e1a7e4110bd58822b81fegdaniel 188c19cdc254cc08f334b00c3b9fdb703818c8ca681egdaniel GrXferProcessor::OptFlags onGetOptimizations(const GrProcOptInfo& colorPOI, 189c19cdc254cc08f334b00c3b9fdb703818c8ca681egdaniel const GrProcOptInfo& coveragePOI, 190c19cdc254cc08f334b00c3b9fdb703818c8ca681egdaniel bool doesStencilWrite, 191c19cdc254cc08f334b00c3b9fdb703818c8ca681egdaniel GrColor* overrideColor, 192c19cdc254cc08f334b00c3b9fdb703818c8ca681egdaniel const GrDrawTargetCaps& caps) override; 193c19cdc254cc08f334b00c3b9fdb703818c8ca681egdaniel 194cfc18867d982119d9dc2888bf09f1093012daaddjvanverth void onGetGLProcessorKey(const GrGLSLCaps& caps, GrProcessorKeyBuilder* b) const override; 19541d4f09356567ead0216e1a7e4110bd58822b81fegdaniel 19636352bf5e38f45a70ee4f4fc132a38048d38206dmtklein bool onIsEqual(const GrXferProcessor& xpBase) const override { 19741d4f09356567ead0216e1a7e4110bd58822b81fegdaniel const ArithmeticXP& xp = xpBase.cast<ArithmeticXP>(); 19841d4f09356567ead0216e1a7e4110bd58822b81fegdaniel if (fK1 != xp.fK1 || 19941d4f09356567ead0216e1a7e4110bd58822b81fegdaniel fK2 != xp.fK2 || 20041d4f09356567ead0216e1a7e4110bd58822b81fegdaniel fK3 != xp.fK3 || 20141d4f09356567ead0216e1a7e4110bd58822b81fegdaniel fK4 != xp.fK4 || 20241d4f09356567ead0216e1a7e4110bd58822b81fegdaniel fEnforcePMColor != xp.fEnforcePMColor) { 20341d4f09356567ead0216e1a7e4110bd58822b81fegdaniel return false; 20441d4f09356567ead0216e1a7e4110bd58822b81fegdaniel } 20541d4f09356567ead0216e1a7e4110bd58822b81fegdaniel return true; 20641d4f09356567ead0216e1a7e4110bd58822b81fegdaniel } 20741d4f09356567ead0216e1a7e4110bd58822b81fegdaniel 20841d4f09356567ead0216e1a7e4110bd58822b81fegdaniel float fK1, fK2, fK3, fK4; 20941d4f09356567ead0216e1a7e4110bd58822b81fegdaniel bool fEnforcePMColor; 21041d4f09356567ead0216e1a7e4110bd58822b81fegdaniel 21141d4f09356567ead0216e1a7e4110bd58822b81fegdaniel typedef GrXferProcessor INHERITED; 21241d4f09356567ead0216e1a7e4110bd58822b81fegdaniel}; 21341d4f09356567ead0216e1a7e4110bd58822b81fegdaniel 21441d4f09356567ead0216e1a7e4110bd58822b81fegdaniel/////////////////////////////////////////////////////////////////////////////// 21541d4f09356567ead0216e1a7e4110bd58822b81fegdaniel 216f351aa3bf1b1d7639be8e1e6a35137b89a8dd93degdanielclass GLArithmeticXP : public GrGLXferProcessor { 217f351aa3bf1b1d7639be8e1e6a35137b89a8dd93degdanielpublic: 218f351aa3bf1b1d7639be8e1e6a35137b89a8dd93degdaniel GLArithmeticXP(const GrProcessor&) 219f351aa3bf1b1d7639be8e1e6a35137b89a8dd93degdaniel : fEnforcePMColor(true) { 22016a04b84147867b62f92969ac8f4f4a9ab009aeaegdaniel } 22116a04b84147867b62f92969ac8f4f4a9ab009aeaegdaniel 22236352bf5e38f45a70ee4f4fc132a38048d38206dmtklein ~GLArithmeticXP() override {} 223f351aa3bf1b1d7639be8e1e6a35137b89a8dd93degdaniel 224cfc18867d982119d9dc2888bf09f1093012daaddjvanverth static void GenKey(const GrProcessor& processor, const GrGLSLCaps& caps, 22550785a3d10b53bea5beb6e18431a2449860be237bsalomon GrProcessorKeyBuilder* b) { 22641d4f09356567ead0216e1a7e4110bd58822b81fegdaniel const ArithmeticXP& arith = processor.cast<ArithmeticXP>(); 22750785a3d10b53bea5beb6e18431a2449860be237bsalomon uint32_t key = arith.enforcePMColor() ? 1 : 0; 22850785a3d10b53bea5beb6e18431a2449860be237bsalomon b->add32(key); 22950785a3d10b53bea5beb6e18431a2449860be237bsalomon } 23050785a3d10b53bea5beb6e18431a2449860be237bsalomon 23150785a3d10b53bea5beb6e18431a2449860be237bsalomonprivate: 23236352bf5e38f45a70ee4f4fc132a38048d38206dmtklein void onEmitCode(const EmitArgs& args) override { 23329bee0fe657fabf7c396502b69c9167fba13eaaaegdaniel GrGLXPFragmentBuilder* fsBuilder = args.fPB->getFragmentShaderBuilder(); 234f351aa3bf1b1d7639be8e1e6a35137b89a8dd93degdaniel 235f351aa3bf1b1d7639be8e1e6a35137b89a8dd93degdaniel const char* dstColor = fsBuilder->dstColor(); 236f351aa3bf1b1d7639be8e1e6a35137b89a8dd93degdaniel 237f351aa3bf1b1d7639be8e1e6a35137b89a8dd93degdaniel fKUni = args.fPB->addUniform(GrGLProgramBuilder::kFragment_Visibility, 238f351aa3bf1b1d7639be8e1e6a35137b89a8dd93degdaniel kVec4f_GrSLType, kDefault_GrSLPrecision, 239f351aa3bf1b1d7639be8e1e6a35137b89a8dd93degdaniel "k"); 240f351aa3bf1b1d7639be8e1e6a35137b89a8dd93degdaniel const char* kUni = args.fPB->getUniformCStr(fKUni); 241f351aa3bf1b1d7639be8e1e6a35137b89a8dd93degdaniel 242f351aa3bf1b1d7639be8e1e6a35137b89a8dd93degdaniel add_arithmetic_code(fsBuilder, args.fInputColor, dstColor, args.fOutputPrimary, kUni, 243f351aa3bf1b1d7639be8e1e6a35137b89a8dd93degdaniel fEnforcePMColor); 244f351aa3bf1b1d7639be8e1e6a35137b89a8dd93degdaniel 245f351aa3bf1b1d7639be8e1e6a35137b89a8dd93degdaniel fsBuilder->codeAppendf("%s = %s * %s + (vec4(1.0) - %s) * %s;", 246f351aa3bf1b1d7639be8e1e6a35137b89a8dd93degdaniel args.fOutputPrimary, args.fOutputPrimary, args.fInputCoverage, 247f351aa3bf1b1d7639be8e1e6a35137b89a8dd93degdaniel args.fInputCoverage, dstColor); 24816a04b84147867b62f92969ac8f4f4a9ab009aeaegdaniel } 24916a04b84147867b62f92969ac8f4f4a9ab009aeaegdaniel 25050785a3d10b53bea5beb6e18431a2449860be237bsalomon void onSetData(const GrGLProgramDataManager& pdman, 25136352bf5e38f45a70ee4f4fc132a38048d38206dmtklein const GrXferProcessor& processor) override { 25241d4f09356567ead0216e1a7e4110bd58822b81fegdaniel const ArithmeticXP& arith = processor.cast<ArithmeticXP>(); 253f351aa3bf1b1d7639be8e1e6a35137b89a8dd93degdaniel pdman.set4f(fKUni, arith.k1(), arith.k2(), arith.k3(), arith.k4()); 254f351aa3bf1b1d7639be8e1e6a35137b89a8dd93degdaniel fEnforcePMColor = arith.enforcePMColor(); 255f351aa3bf1b1d7639be8e1e6a35137b89a8dd93degdaniel }; 256f351aa3bf1b1d7639be8e1e6a35137b89a8dd93degdaniel 257f351aa3bf1b1d7639be8e1e6a35137b89a8dd93degdaniel GrGLProgramDataManager::UniformHandle fKUni; 258f351aa3bf1b1d7639be8e1e6a35137b89a8dd93degdaniel bool fEnforcePMColor; 259f351aa3bf1b1d7639be8e1e6a35137b89a8dd93degdaniel 260f351aa3bf1b1d7639be8e1e6a35137b89a8dd93degdaniel typedef GrGLXferProcessor INHERITED; 261f351aa3bf1b1d7639be8e1e6a35137b89a8dd93degdaniel}; 262f351aa3bf1b1d7639be8e1e6a35137b89a8dd93degdaniel 263f351aa3bf1b1d7639be8e1e6a35137b89a8dd93degdaniel/////////////////////////////////////////////////////////////////////////////// 264f351aa3bf1b1d7639be8e1e6a35137b89a8dd93degdaniel 26541d4f09356567ead0216e1a7e4110bd58822b81fegdanielArithmeticXP::ArithmeticXP(float k1, float k2, float k3, float k4, bool enforcePMColor, 26641d4f09356567ead0216e1a7e4110bd58822b81fegdaniel const GrDeviceCoordTexture* dstCopy, bool willReadDstColor) 26750785a3d10b53bea5beb6e18431a2449860be237bsalomon : INHERITED(dstCopy, willReadDstColor) 26850785a3d10b53bea5beb6e18431a2449860be237bsalomon , fK1(k1) 269f351aa3bf1b1d7639be8e1e6a35137b89a8dd93degdaniel , fK2(k2) 270f351aa3bf1b1d7639be8e1e6a35137b89a8dd93degdaniel , fK3(k3) 271f351aa3bf1b1d7639be8e1e6a35137b89a8dd93degdaniel , fK4(k4) 272f351aa3bf1b1d7639be8e1e6a35137b89a8dd93degdaniel , fEnforcePMColor(enforcePMColor) { 27341d4f09356567ead0216e1a7e4110bd58822b81fegdaniel this->initClassID<ArithmeticXP>(); 27416a04b84147867b62f92969ac8f4f4a9ab009aeaegdaniel} 27516a04b84147867b62f92969ac8f4f4a9ab009aeaegdaniel 276cfc18867d982119d9dc2888bf09f1093012daaddjvanverthvoid ArithmeticXP::onGetGLProcessorKey(const GrGLSLCaps& caps, GrProcessorKeyBuilder* b) const { 277f351aa3bf1b1d7639be8e1e6a35137b89a8dd93degdaniel GLArithmeticXP::GenKey(*this, caps, b); 27816a04b84147867b62f92969ac8f4f4a9ab009aeaegdaniel} 27916a04b84147867b62f92969ac8f4f4a9ab009aeaegdaniel 28041d4f09356567ead0216e1a7e4110bd58822b81fegdanielGrGLXferProcessor* ArithmeticXP::createGLInstance() const { 281f351aa3bf1b1d7639be8e1e6a35137b89a8dd93degdaniel return SkNEW_ARGS(GLArithmeticXP, (*this)); 28216a04b84147867b62f92969ac8f4f4a9ab009aeaegdaniel} 28316a04b84147867b62f92969ac8f4f4a9ab009aeaegdaniel 284c19cdc254cc08f334b00c3b9fdb703818c8ca681egdanielGrXferProcessor::OptFlags ArithmeticXP::onGetOptimizations(const GrProcOptInfo& colorPOI, 285c19cdc254cc08f334b00c3b9fdb703818c8ca681egdaniel const GrProcOptInfo& coveragePOI, 286c19cdc254cc08f334b00c3b9fdb703818c8ca681egdaniel bool doesStencilWrite, 287c19cdc254cc08f334b00c3b9fdb703818c8ca681egdaniel GrColor* overrideColor, 288c19cdc254cc08f334b00c3b9fdb703818c8ca681egdaniel const GrDrawTargetCaps& caps) { 289f351aa3bf1b1d7639be8e1e6a35137b89a8dd93degdaniel return GrXferProcessor::kNone_Opt; 290f351aa3bf1b1d7639be8e1e6a35137b89a8dd93degdaniel} 29116a04b84147867b62f92969ac8f4f4a9ab009aeaegdaniel 292f351aa3bf1b1d7639be8e1e6a35137b89a8dd93degdaniel/////////////////////////////////////////////////////////////////////////////// 293f351aa3bf1b1d7639be8e1e6a35137b89a8dd93degdaniel 294f351aa3bf1b1d7639be8e1e6a35137b89a8dd93degdanielGrArithmeticXPFactory::GrArithmeticXPFactory(float k1, float k2, float k3, float k4, 295f351aa3bf1b1d7639be8e1e6a35137b89a8dd93degdaniel bool enforcePMColor) 296f351aa3bf1b1d7639be8e1e6a35137b89a8dd93degdaniel : fK1(k1), fK2(k2), fK3(k3), fK4(k4), fEnforcePMColor(enforcePMColor) { 29754f0e9d784122cfd3f5968e0fea971d5b5a4805aegdaniel this->initClassID<GrArithmeticXPFactory>(); 29816a04b84147867b62f92969ac8f4f4a9ab009aeaegdaniel} 29916a04b84147867b62f92969ac8f4f4a9ab009aeaegdaniel 30041d4f09356567ead0216e1a7e4110bd58822b81fegdanielGrXferProcessor* 3013ad6570e94965d54871eaea8b314f560b82ca792egdanielGrArithmeticXPFactory::onCreateXferProcessor(const GrDrawTargetCaps& caps, 3023ad6570e94965d54871eaea8b314f560b82ca792egdaniel const GrProcOptInfo& colorPOI, 30341d4f09356567ead0216e1a7e4110bd58822b81fegdaniel const GrProcOptInfo& coveragePOI, 30441d4f09356567ead0216e1a7e4110bd58822b81fegdaniel const GrDeviceCoordTexture* dstCopy) const { 30541d4f09356567ead0216e1a7e4110bd58822b81fegdaniel return ArithmeticXP::Create(fK1, fK2, fK3, fK4, fEnforcePMColor, dstCopy, 3063ad6570e94965d54871eaea8b314f560b82ca792egdaniel this->willReadDstColor(caps, colorPOI, coveragePOI)); 30741d4f09356567ead0216e1a7e4110bd58822b81fegdaniel} 30841d4f09356567ead0216e1a7e4110bd58822b81fegdaniel 30941d4f09356567ead0216e1a7e4110bd58822b81fegdaniel 310f351aa3bf1b1d7639be8e1e6a35137b89a8dd93degdanielvoid GrArithmeticXPFactory::getInvariantOutput(const GrProcOptInfo& colorPOI, 311f351aa3bf1b1d7639be8e1e6a35137b89a8dd93degdaniel const GrProcOptInfo& coveragePOI, 312f351aa3bf1b1d7639be8e1e6a35137b89a8dd93degdaniel GrXPFactory::InvariantOutput* output) const { 313f351aa3bf1b1d7639be8e1e6a35137b89a8dd93degdaniel output->fWillBlendWithDst = true; 314f351aa3bf1b1d7639be8e1e6a35137b89a8dd93degdaniel 315f351aa3bf1b1d7639be8e1e6a35137b89a8dd93degdaniel // TODO: We could try to optimize this more. For example if we have solid coverage and fK1 and 316f351aa3bf1b1d7639be8e1e6a35137b89a8dd93degdaniel // fK3 are zero, then we won't be blending the color with dst at all so we can know what the 317f351aa3bf1b1d7639be8e1e6a35137b89a8dd93degdaniel // output color is (up to the valid color components passed in). 318f351aa3bf1b1d7639be8e1e6a35137b89a8dd93degdaniel output->fBlendedColorFlags = 0; 319f351aa3bf1b1d7639be8e1e6a35137b89a8dd93degdaniel} 320f351aa3bf1b1d7639be8e1e6a35137b89a8dd93degdaniel 321f351aa3bf1b1d7639be8e1e6a35137b89a8dd93degdanielGR_DEFINE_XP_FACTORY_TEST(GrArithmeticXPFactory); 322f351aa3bf1b1d7639be8e1e6a35137b89a8dd93degdaniel 323f351aa3bf1b1d7639be8e1e6a35137b89a8dd93degdanielGrXPFactory* GrArithmeticXPFactory::TestCreate(SkRandom* random, 324f351aa3bf1b1d7639be8e1e6a35137b89a8dd93degdaniel GrContext*, 325f351aa3bf1b1d7639be8e1e6a35137b89a8dd93degdaniel const GrDrawTargetCaps&, 326f351aa3bf1b1d7639be8e1e6a35137b89a8dd93degdaniel GrTexture*[]) { 327f351aa3bf1b1d7639be8e1e6a35137b89a8dd93degdaniel float k1 = random->nextF(); 328f351aa3bf1b1d7639be8e1e6a35137b89a8dd93degdaniel float k2 = random->nextF(); 329f351aa3bf1b1d7639be8e1e6a35137b89a8dd93degdaniel float k3 = random->nextF(); 330f351aa3bf1b1d7639be8e1e6a35137b89a8dd93degdaniel float k4 = random->nextF(); 331f351aa3bf1b1d7639be8e1e6a35137b89a8dd93degdaniel bool enforcePMColor = random->nextBool(); 332f351aa3bf1b1d7639be8e1e6a35137b89a8dd93degdaniel 333f351aa3bf1b1d7639be8e1e6a35137b89a8dd93degdaniel return GrArithmeticXPFactory::Create(k1, k2, k3, k4, enforcePMColor); 334f351aa3bf1b1d7639be8e1e6a35137b89a8dd93degdaniel} 33516a04b84147867b62f92969ac8f4f4a9ab009aeaegdaniel 33616a04b84147867b62f92969ac8f4f4a9ab009aeaegdaniel#endif 337