SkSL sample() now permits specification of coordinates
Bug: skia: Change-Id: I16073008ac852f1864bd1d2bd38087a5b661d05a Reviewed-on: https://skia-review.googlesource.com/c/skia/+/232581 Reviewed-by: Brian Osman <brianosman@google.com> Commit-Queue: Ethan Nicholas <ethannicholas@google.com>
This commit is contained in:
parent
21d726de0b
commit
d4efe685dd
97
gm/fpcoordinateoverride.cpp
Normal file
97
gm/fpcoordinateoverride.cpp
Normal file
@ -0,0 +1,97 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2019 Google LLC.
|
||||||
|
*
|
||||||
|
* Use of this source code is governed by a BSD-style license that can be
|
||||||
|
* found in the LICENSE file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "gm/gm.h"
|
||||||
|
#include "include/core/SkCanvas.h"
|
||||||
|
#include "include/core/SkColor.h"
|
||||||
|
#include "include/core/SkImageInfo.h"
|
||||||
|
#include "include/core/SkMatrix.h"
|
||||||
|
#include "include/core/SkPaint.h"
|
||||||
|
#include "include/core/SkRect.h"
|
||||||
|
#include "include/core/SkShader.h"
|
||||||
|
#include "include/core/SkSize.h"
|
||||||
|
#include "include/core/SkString.h"
|
||||||
|
#include "include/core/SkTileMode.h"
|
||||||
|
#include "include/core/SkTypes.h"
|
||||||
|
#include "include/gpu/GrContext.h"
|
||||||
|
#include "src/gpu/GrCaps.h"
|
||||||
|
#include "src/gpu/GrContextPriv.h"
|
||||||
|
#include "src/gpu/GrCoordTransform.h"
|
||||||
|
#include "src/gpu/GrFragmentProcessor.h"
|
||||||
|
#include "src/gpu/GrRenderTargetContext.h"
|
||||||
|
#include "src/gpu/GrRenderTargetContextPriv.h"
|
||||||
|
#include "src/gpu/effects/GrRRectEffect.h"
|
||||||
|
#include "src/gpu/effects/GrSkSLFP.h"
|
||||||
|
#include "src/gpu/ops/GrFillRectOp.h"
|
||||||
|
#include "tools/Resources.h"
|
||||||
|
#include "tools/ToolUtils.h"
|
||||||
|
|
||||||
|
class SampleCoordEffect : public GrFragmentProcessor {
|
||||||
|
public:
|
||||||
|
static constexpr GrProcessor::ClassID CLASS_ID = (GrProcessor::ClassID) 0;
|
||||||
|
|
||||||
|
SampleCoordEffect(std::unique_ptr<GrFragmentProcessor> child)
|
||||||
|
: INHERITED(CLASS_ID, kNone_OptimizationFlags) {
|
||||||
|
child->setComputeLocalCoordsInVertexShader(false);
|
||||||
|
this->registerChildProcessor(std::move(child));
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* name() const override { return "SampleCoordEffect"; }
|
||||||
|
|
||||||
|
std::unique_ptr<GrFragmentProcessor> clone() const override {
|
||||||
|
SkASSERT(false);
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void onGetGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder*) const override {
|
||||||
|
}
|
||||||
|
|
||||||
|
bool onIsEqual(const GrFragmentProcessor&) const override {
|
||||||
|
SkASSERT(false);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
GrGLSLFragmentProcessor* onCreateGLSLInstance() const override;
|
||||||
|
typedef GrFragmentProcessor INHERITED;
|
||||||
|
};
|
||||||
|
|
||||||
|
class GLSLSampleCoordEffect : public GrGLSLFragmentProcessor {
|
||||||
|
void emitCode(EmitArgs& args) override {
|
||||||
|
GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
|
||||||
|
SkString sample1("sample1");
|
||||||
|
SkString sample2("sample2");
|
||||||
|
this->invokeChild(0, &sample1, args, "float2(sk_FragCoord.x, sk_FragCoord.y)");
|
||||||
|
this->invokeChild(0, &sample2, args, "float2(sk_FragCoord.x, 512 - sk_FragCoord.y)");
|
||||||
|
fragBuilder->codeAppendf("%s = (%s + %s) / 2;\n", args.fOutputColor, sample1.c_str(),
|
||||||
|
sample2.c_str());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
GrGLSLFragmentProcessor* SampleCoordEffect::onCreateGLSLInstance() const {
|
||||||
|
return new GLSLSampleCoordEffect();
|
||||||
|
}
|
||||||
|
|
||||||
|
DEF_SIMPLE_GPU_GM_BG(fpcoordinateoverride, ctx, rtCtx, canvas, 512, 512,
|
||||||
|
ToolUtils::color_to_565(0xFF66AA99)) {
|
||||||
|
SkRect bounds = SkRect::MakeIWH(512, 512);
|
||||||
|
|
||||||
|
SkBitmap bmp;
|
||||||
|
GetResourceAsBitmap("images/mandrill_512_q075.jpg", &bmp);
|
||||||
|
GrProxyProvider* proxyProvider = ctx->priv().proxyProvider();
|
||||||
|
sk_sp<GrTextureProxy> texture = proxyProvider->createProxyFromBitmap(bmp, GrMipMapped::kNo);
|
||||||
|
std::unique_ptr<GrFragmentProcessor> imgFP = GrSimpleTextureEffect::Make(texture, SkMatrix());
|
||||||
|
auto fp = std::unique_ptr<GrFragmentProcessor>(new SampleCoordEffect(std::move(imgFP)));
|
||||||
|
|
||||||
|
GrPaint grPaint;
|
||||||
|
grPaint.addCoverageFragmentProcessor(std::move(fp));
|
||||||
|
|
||||||
|
rtCtx->priv().testingOnly_addDrawOp(GrFillRectOp::MakeNonAARect(ctx,
|
||||||
|
std::move(grPaint),
|
||||||
|
SkMatrix::I(),
|
||||||
|
bounds));
|
||||||
|
}
|
@ -165,6 +165,7 @@ gm_sources = [
|
|||||||
"$_gm/fontregen.cpp",
|
"$_gm/fontregen.cpp",
|
||||||
"$_gm/fontscaler.cpp",
|
"$_gm/fontscaler.cpp",
|
||||||
"$_gm/fontscalerdistortable.cpp",
|
"$_gm/fontscalerdistortable.cpp",
|
||||||
|
"$_gm/fpcoordinateoverride.cpp",
|
||||||
"$_gm/fwidth_squircle.cpp",
|
"$_gm/fwidth_squircle.cpp",
|
||||||
"$_gm/gamma.cpp",
|
"$_gm/gamma.cpp",
|
||||||
"$_gm/gammatext.cpp",
|
"$_gm/gammatext.cpp",
|
||||||
|
@ -16,10 +16,11 @@ skia_sksl_sources = [
|
|||||||
"$_src/sksl/SkSLJIT.cpp",
|
"$_src/sksl/SkSLJIT.cpp",
|
||||||
"$_src/sksl/SkSLLexer.cpp",
|
"$_src/sksl/SkSLLexer.cpp",
|
||||||
"$_src/sksl/SkSLParser.cpp",
|
"$_src/sksl/SkSLParser.cpp",
|
||||||
|
"$_src/sksl/SkSLSectionAndParameterHelper.cpp",
|
||||||
"$_src/sksl/SkSLString.cpp",
|
"$_src/sksl/SkSLString.cpp",
|
||||||
"$_src/sksl/SkSLUtil.cpp",
|
"$_src/sksl/SkSLUtil.cpp",
|
||||||
"$_src/sksl/ir/SkSLSymbolTable.cpp",
|
|
||||||
"$_src/sksl/ir/SkSLSetting.cpp",
|
"$_src/sksl/ir/SkSLSetting.cpp",
|
||||||
|
"$_src/sksl/ir/SkSLSymbolTable.cpp",
|
||||||
"$_src/sksl/ir/SkSLType.cpp",
|
"$_src/sksl/ir/SkSLType.cpp",
|
||||||
"$_src/sksl/ir/SkSLVariableReference.cpp",
|
"$_src/sksl/ir/SkSLVariableReference.cpp",
|
||||||
]
|
]
|
||||||
|
@ -586,15 +586,16 @@ void GrGLDisplacementMapEffect::emitCode(EmitArgs& args) {
|
|||||||
|
|
||||||
GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
|
GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
|
||||||
fragBuilder->codeAppendf("\t\thalf4 %s = ", dColor);
|
fragBuilder->codeAppendf("\t\thalf4 %s = ", dColor);
|
||||||
fragBuilder->appendTextureLookup(args.fTexSamplers[0], args.fTransformedCoords[0].c_str(),
|
fragBuilder->appendTextureLookup(args.fTexSamplers[0],
|
||||||
args.fTransformedCoords[0].getType());
|
args.fTransformedCoords[0].fVaryingPoint.c_str(),
|
||||||
|
args.fTransformedCoords[0].fVaryingPoint.getType());
|
||||||
fragBuilder->codeAppend(";\n");
|
fragBuilder->codeAppend(";\n");
|
||||||
|
|
||||||
// Unpremultiply the displacement
|
// Unpremultiply the displacement
|
||||||
fragBuilder->codeAppendf(
|
fragBuilder->codeAppendf(
|
||||||
"\t\t%s.rgb = (%s.a < %s) ? half3(0.0) : saturate(%s.rgb / %s.a);",
|
"\t\t%s.rgb = (%s.a < %s) ? half3(0.0) : saturate(%s.rgb / %s.a);",
|
||||||
dColor, dColor, nearZero, dColor, dColor);
|
dColor, dColor, nearZero, dColor, dColor);
|
||||||
SkString coords2D = fragBuilder->ensureCoords2D(args.fTransformedCoords[1]);
|
SkString coords2D = fragBuilder->ensureCoords2D(args.fTransformedCoords[1].fVaryingPoint);
|
||||||
fragBuilder->codeAppendf("\t\tfloat2 %s = %s + %s*(%s.",
|
fragBuilder->codeAppendf("\t\tfloat2 %s = %s + %s*(%s.",
|
||||||
cCoords, coords2D.c_str(), scaleUni, dColor);
|
cCoords, coords2D.c_str(), scaleUni, dColor);
|
||||||
|
|
||||||
|
@ -1752,7 +1752,7 @@ void GrGLLightingEffect::emitCode(EmitArgs& args) {
|
|||||||
GrShaderVar("scale", kHalf_GrSLType),
|
GrShaderVar("scale", kHalf_GrSLType),
|
||||||
};
|
};
|
||||||
SkString sobelFuncName;
|
SkString sobelFuncName;
|
||||||
SkString coords2D = fragBuilder->ensureCoords2D(args.fTransformedCoords[0]);
|
SkString coords2D = fragBuilder->ensureCoords2D(args.fTransformedCoords[0].fVaryingPoint);
|
||||||
|
|
||||||
fragBuilder->emitFunction(kHalf_GrSLType,
|
fragBuilder->emitFunction(kHalf_GrSLType,
|
||||||
"sobel",
|
"sobel",
|
||||||
|
@ -286,7 +286,7 @@ void GrGLMorphologyEffect::emitCode(EmitArgs& args) {
|
|||||||
const char* range = uniformHandler->getUniformCStr(fRangeUni);
|
const char* range = uniformHandler->getUniformCStr(fRangeUni);
|
||||||
|
|
||||||
GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
|
GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
|
||||||
SkString coords2D = fragBuilder->ensureCoords2D(args.fTransformedCoords[0]);
|
SkString coords2D = fragBuilder->ensureCoords2D(args.fTransformedCoords[0].fVaryingPoint);
|
||||||
const char* func;
|
const char* func;
|
||||||
switch (me.type()) {
|
switch (me.type()) {
|
||||||
case MorphType::kErode:
|
case MorphType::kErode:
|
||||||
|
@ -23,7 +23,8 @@ public:
|
|||||||
GrCoordTransform()
|
GrCoordTransform()
|
||||||
: fProxy(nullptr)
|
: fProxy(nullptr)
|
||||||
, fNormalize(false)
|
, fNormalize(false)
|
||||||
, fReverseY(false) {
|
, fReverseY(false)
|
||||||
|
, fComputeInVertexShader(true) {
|
||||||
SkDEBUGCODE(fInProcessor = false);
|
SkDEBUGCODE(fInProcessor = false);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -100,6 +101,12 @@ public:
|
|||||||
// successfully instantiated
|
// successfully instantiated
|
||||||
GrTexture* peekTexture() const { return fProxy->peekTexture(); }
|
GrTexture* peekTexture() const { return fProxy->peekTexture(); }
|
||||||
|
|
||||||
|
bool computeInVertexShader() const { return fComputeInVertexShader; }
|
||||||
|
|
||||||
|
void setComputeInVertexShader(bool computeInVertexShader) {
|
||||||
|
fComputeInVertexShader = computeInVertexShader;
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void reset(const SkMatrix& m, GrTextureProxy* proxy = nullptr) {
|
void reset(const SkMatrix& m, GrTextureProxy* proxy = nullptr) {
|
||||||
SkASSERT(!fInProcessor);
|
SkASSERT(!fInProcessor);
|
||||||
@ -108,6 +115,7 @@ private:
|
|||||||
fProxy = proxy;
|
fProxy = proxy;
|
||||||
fNormalize = proxy && proxy->textureType() != GrTextureType::kRectangle;
|
fNormalize = proxy && proxy->textureType() != GrTextureType::kRectangle;
|
||||||
fReverseY = proxy && kBottomLeft_GrSurfaceOrigin == proxy->origin();
|
fReverseY = proxy && kBottomLeft_GrSurfaceOrigin == proxy->origin();
|
||||||
|
fComputeInVertexShader = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// The textures' effect is to optionally normalize the final matrix, so a blind
|
// The textures' effect is to optionally normalize the final matrix, so a blind
|
||||||
@ -119,6 +127,7 @@ private:
|
|||||||
const GrTextureProxy* fProxy;
|
const GrTextureProxy* fProxy;
|
||||||
bool fNormalize;
|
bool fNormalize;
|
||||||
bool fReverseY;
|
bool fReverseY;
|
||||||
|
bool fComputeInVertexShader;
|
||||||
|
|
||||||
#ifdef SK_DEBUG
|
#ifdef SK_DEBUG
|
||||||
public:
|
public:
|
||||||
|
@ -69,7 +69,8 @@ const GrFragmentProcessor::TextureSampler& GrFragmentProcessor::textureSampler(i
|
|||||||
return this->onTextureSampler(i);
|
return this->onTextureSampler(i);
|
||||||
}
|
}
|
||||||
|
|
||||||
void GrFragmentProcessor::addCoordTransform(const GrCoordTransform* transform) {
|
void GrFragmentProcessor::addCoordTransform(GrCoordTransform* transform) {
|
||||||
|
transform->setComputeInVertexShader(this->computeLocalCoordsInVertexShader());
|
||||||
fCoordTransforms.push_back(transform);
|
fCoordTransforms.push_back(transform);
|
||||||
fFlags |= kUsesLocalCoords_Flag;
|
fFlags |= kUsesLocalCoords_Flag;
|
||||||
SkDEBUGCODE(transform->setInProcessor();)
|
SkDEBUGCODE(transform->setInProcessor();)
|
||||||
|
@ -8,10 +8,10 @@
|
|||||||
#ifndef GrFragmentProcessor_DEFINED
|
#ifndef GrFragmentProcessor_DEFINED
|
||||||
#define GrFragmentProcessor_DEFINED
|
#define GrFragmentProcessor_DEFINED
|
||||||
|
|
||||||
|
#include "src/gpu/GrCoordTransform.h"
|
||||||
#include "src/gpu/GrProcessor.h"
|
#include "src/gpu/GrProcessor.h"
|
||||||
#include "src/gpu/ops/GrOp.h"
|
#include "src/gpu/ops/GrOp.h"
|
||||||
|
|
||||||
class GrCoordTransform;
|
|
||||||
class GrGLSLFragmentProcessor;
|
class GrGLSLFragmentProcessor;
|
||||||
class GrPaint;
|
class GrPaint;
|
||||||
class GrPipeline;
|
class GrPipeline;
|
||||||
@ -114,7 +114,7 @@ public:
|
|||||||
numTransforms(). */
|
numTransforms(). */
|
||||||
const GrCoordTransform& coordTransform(int index) const { return *fCoordTransforms[index]; }
|
const GrCoordTransform& coordTransform(int index) const { return *fCoordTransforms[index]; }
|
||||||
|
|
||||||
const SkTArray<const GrCoordTransform*, true>& coordTransforms() const {
|
const SkTArray<GrCoordTransform*, true>& coordTransforms() const {
|
||||||
return fCoordTransforms;
|
return fCoordTransforms;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -127,6 +127,24 @@ public:
|
|||||||
/** Do any of the coordtransforms for this processor require local coords? */
|
/** Do any of the coordtransforms for this processor require local coords? */
|
||||||
bool usesLocalCoords() const { return SkToBool(fFlags & kUsesLocalCoords_Flag); }
|
bool usesLocalCoords() const { return SkToBool(fFlags & kUsesLocalCoords_Flag); }
|
||||||
|
|
||||||
|
bool computeLocalCoordsInVertexShader() const {
|
||||||
|
return SkToBool(fFlags & kComputeLocalCoordsInVertexShader_Flag);
|
||||||
|
}
|
||||||
|
|
||||||
|
void setComputeLocalCoordsInVertexShader(bool value) const {
|
||||||
|
if (value) {
|
||||||
|
fFlags |= kComputeLocalCoordsInVertexShader_Flag;
|
||||||
|
} else {
|
||||||
|
fFlags &= ~kComputeLocalCoordsInVertexShader_Flag;
|
||||||
|
}
|
||||||
|
for (GrCoordTransform* transform : fCoordTransforms) {
|
||||||
|
transform->setComputeInVertexShader(value);
|
||||||
|
}
|
||||||
|
for (const auto& child : fChildProcessors) {
|
||||||
|
child->setComputeLocalCoordsInVertexShader(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A GrDrawOp may premultiply its antialiasing coverage into its GrGeometryProcessor's color
|
* A GrDrawOp may premultiply its antialiasing coverage into its GrGeometryProcessor's color
|
||||||
* output under the following scenario:
|
* output under the following scenario:
|
||||||
@ -284,8 +302,8 @@ protected:
|
|||||||
|
|
||||||
GrFragmentProcessor(ClassID classID, OptimizationFlags optimizationFlags)
|
GrFragmentProcessor(ClassID classID, OptimizationFlags optimizationFlags)
|
||||||
: INHERITED(classID)
|
: INHERITED(classID)
|
||||||
, fFlags(optimizationFlags) {
|
, fFlags(optimizationFlags | kComputeLocalCoordsInVertexShader_Flag) {
|
||||||
SkASSERT((fFlags & ~kAll_OptimizationFlags) == 0);
|
SkASSERT((optimizationFlags & ~kAll_OptimizationFlags) == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
OptimizationFlags optimizationFlags() const {
|
OptimizationFlags optimizationFlags() const {
|
||||||
@ -325,7 +343,7 @@ protected:
|
|||||||
* transforms in a consistent order. The non-virtual implementation of isEqual() automatically
|
* transforms in a consistent order. The non-virtual implementation of isEqual() automatically
|
||||||
* compares transforms and will assume they line up across the two processor instances.
|
* compares transforms and will assume they line up across the two processor instances.
|
||||||
*/
|
*/
|
||||||
void addCoordTransform(const GrCoordTransform*);
|
void addCoordTransform(GrCoordTransform*);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* FragmentProcessor subclasses call this from their constructor to register any child
|
* FragmentProcessor subclasses call this from their constructor to register any child
|
||||||
@ -382,13 +400,14 @@ private:
|
|||||||
enum PrivateFlags {
|
enum PrivateFlags {
|
||||||
kFirstPrivateFlag = kAll_OptimizationFlags + 1,
|
kFirstPrivateFlag = kAll_OptimizationFlags + 1,
|
||||||
kUsesLocalCoords_Flag = kFirstPrivateFlag,
|
kUsesLocalCoords_Flag = kFirstPrivateFlag,
|
||||||
|
kComputeLocalCoordsInVertexShader_Flag = kFirstPrivateFlag << 1,
|
||||||
};
|
};
|
||||||
|
|
||||||
mutable uint32_t fFlags = 0;
|
mutable uint32_t fFlags = kComputeLocalCoordsInVertexShader_Flag;
|
||||||
|
|
||||||
int fTextureSamplerCnt = 0;
|
int fTextureSamplerCnt = 0;
|
||||||
|
|
||||||
SkSTArray<4, const GrCoordTransform*, true> fCoordTransforms;
|
SkSTArray<4, GrCoordTransform*, true> fCoordTransforms;
|
||||||
|
|
||||||
SkSTArray<1, std::unique_ptr<GrFragmentProcessor>, true> fChildProcessors;
|
SkSTArray<1, std::unique_ptr<GrFragmentProcessor>, true> fChildProcessors;
|
||||||
|
|
||||||
|
@ -49,6 +49,11 @@ public:
|
|||||||
fragBuilder->codeAppendf("%s = half4(1);", args.fOutputCoverage);
|
fragBuilder->codeAppendf("%s = half4(1);", args.fOutputCoverage);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SkString matrix_to_sksl(const SkMatrix& m) {
|
||||||
|
return SkStringPrintf("float3x3(%f, %f, %f, %f, %f, %f, %f, %f, %f)", m[0], m[1], m[2],
|
||||||
|
m[3], m[4], m[5], m[6], m[7], m[8]);
|
||||||
|
}
|
||||||
|
|
||||||
void emitTransforms(GrGLSLVaryingHandler* varyingHandler,
|
void emitTransforms(GrGLSLVaryingHandler* varyingHandler,
|
||||||
FPCoordTransformHandler* transformHandler) {
|
FPCoordTransformHandler* transformHandler) {
|
||||||
int i = 0;
|
int i = 0;
|
||||||
@ -66,7 +71,11 @@ public:
|
|||||||
&v).toIndex();
|
&v).toIndex();
|
||||||
fInstalledTransforms.back().fType = varyingType;
|
fInstalledTransforms.back().fType = varyingType;
|
||||||
|
|
||||||
transformHandler->specifyCoordsForCurrCoordTransform(SkString(v.fsIn()), varyingType);
|
transformHandler->specifyCoordsForCurrCoordTransform(
|
||||||
|
matrix_to_sksl(coordTransform->getMatrix()),
|
||||||
|
UniformHandle(),
|
||||||
|
GrShaderVar(SkString(v.fsIn()),
|
||||||
|
varyingType));
|
||||||
++i;
|
++i;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -25,7 +25,7 @@ const GrPrimitiveProcessor::TextureSampler& GrPrimitiveProcessor::textureSampler
|
|||||||
}
|
}
|
||||||
|
|
||||||
uint32_t
|
uint32_t
|
||||||
GrPrimitiveProcessor::getTransformKey(const SkTArray<const GrCoordTransform*, true>& coords,
|
GrPrimitiveProcessor::getTransformKey(const SkTArray<GrCoordTransform*, true>& coords,
|
||||||
int numCoords) const {
|
int numCoords) const {
|
||||||
uint32_t totalKey = 0;
|
uint32_t totalKey = 0;
|
||||||
for (int t = 0; t < numCoords; ++t) {
|
for (int t = 0; t < numCoords; ++t) {
|
||||||
|
@ -174,7 +174,7 @@ public:
|
|||||||
*
|
*
|
||||||
* TODO: A better name for this function would be "compute" instead of "get".
|
* TODO: A better name for this function would be "compute" instead of "get".
|
||||||
*/
|
*/
|
||||||
uint32_t getTransformKey(const SkTArray<const GrCoordTransform*, true>& coords,
|
uint32_t getTransformKey(const SkTArray<GrCoordTransform*, true>& coords,
|
||||||
int numCoords) const;
|
int numCoords) const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -46,7 +46,7 @@ void GrGLBicubicEffect::emitCode(EmitArgs& args) {
|
|||||||
const char* dims = uniformHandler->getUniformCStr(fDimensions);
|
const char* dims = uniformHandler->getUniformCStr(fDimensions);
|
||||||
|
|
||||||
GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
|
GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
|
||||||
SkString coords2D = fragBuilder->ensureCoords2D(args.fTransformedCoords[0]);
|
SkString coords2D = fragBuilder->ensureCoords2D(args.fTransformedCoords[0].fVaryingPoint);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Filter weights come from Don Mitchell & Arun Netravali's 'Reconstruction Filters in Computer
|
* Filter weights come from Don Mitchell & Arun Netravali's 'Reconstruction Filters in Computer
|
||||||
|
@ -56,7 +56,7 @@ void GrGLConvolutionEffect::emitCode(EmitArgs& args) {
|
|||||||
"Kernel", arrayCount);
|
"Kernel", arrayCount);
|
||||||
|
|
||||||
GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
|
GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
|
||||||
SkString coords2D = fragBuilder->ensureCoords2D(args.fTransformedCoords[0]);
|
SkString coords2D = fragBuilder->ensureCoords2D(args.fTransformedCoords[0].fVaryingPoint);
|
||||||
|
|
||||||
fragBuilder->codeAppendf("%s = half4(0, 0, 0, 0);", args.fOutputColor);
|
fragBuilder->codeAppendf("%s = half4(0, 0, 0, 0);", args.fOutputColor);
|
||||||
|
|
||||||
|
@ -63,7 +63,7 @@ void GrGLMatrixConvolutionEffect::emitCode(EmitArgs& args) {
|
|||||||
const char* bias = uniformHandler->getUniformCStr(fBiasUni);
|
const char* bias = uniformHandler->getUniformCStr(fBiasUni);
|
||||||
|
|
||||||
GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
|
GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
|
||||||
SkString coords2D = fragBuilder->ensureCoords2D(args.fTransformedCoords[0]);
|
SkString coords2D = fragBuilder->ensureCoords2D(args.fTransformedCoords[0].fVaryingPoint);
|
||||||
fragBuilder->codeAppend("half4 sum = half4(0, 0, 0, 0);");
|
fragBuilder->codeAppend("half4 sum = half4(0, 0, 0, 0);");
|
||||||
fragBuilder->codeAppendf("float2 coord = %s - %s * %s;", coords2D.c_str(), kernelOffset, imgInc);
|
fragBuilder->codeAppendf("float2 coord = %s - %s * %s;", coords2D.c_str(), kernelOffset, imgInc);
|
||||||
fragBuilder->codeAppend("half4 c;");
|
fragBuilder->codeAppend("half4 c;");
|
||||||
|
@ -167,7 +167,7 @@ public:
|
|||||||
int substringStartIndex = 0;
|
int substringStartIndex = 0;
|
||||||
int formatArgIndex = 0;
|
int formatArgIndex = 0;
|
||||||
SkString coords = args.fTransformedCoords.count()
|
SkString coords = args.fTransformedCoords.count()
|
||||||
? fragBuilder->ensureCoords2D(args.fTransformedCoords[0])
|
? fragBuilder->ensureCoords2D(args.fTransformedCoords[0].fVaryingPoint)
|
||||||
: SkString("sk_FragCoord");
|
: SkString("sk_FragCoord");
|
||||||
for (size_t i = 0; i < fGLSL.length(); ++i) {
|
for (size_t i = 0; i < fGLSL.length(); ++i) {
|
||||||
char c = fGLSL[i];
|
char c = fGLSL[i];
|
||||||
|
@ -315,7 +315,8 @@ GrGLSLFragmentProcessor* GrTextureDomainEffect::onCreateGLSLInstance() const {
|
|||||||
const GrTextureDomain& domain = tde.fTextureDomain;
|
const GrTextureDomain& domain = tde.fTextureDomain;
|
||||||
|
|
||||||
GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
|
GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
|
||||||
SkString coords2D = fragBuilder->ensureCoords2D(args.fTransformedCoords[0]);
|
SkString coords2D =
|
||||||
|
fragBuilder->ensureCoords2D(args.fTransformedCoords[0].fVaryingPoint);
|
||||||
|
|
||||||
fGLDomain.sampleTexture(fragBuilder,
|
fGLDomain.sampleTexture(fragBuilder,
|
||||||
args.fUniformHandler,
|
args.fUniformHandler,
|
||||||
|
@ -98,7 +98,7 @@ GrGLSLFragmentProcessor* GrYUVtoRGBEffect::onCreateGLSLInstance() const {
|
|||||||
|
|
||||||
SkString coords[4];
|
SkString coords[4];
|
||||||
for (int i = 0; i < numSamplers; ++i) {
|
for (int i = 0; i < numSamplers; ++i) {
|
||||||
coords[i] = fragBuilder->ensureCoords2D(args.fTransformedCoords[i]);
|
coords[i] = fragBuilder->ensureCoords2D(args.fTransformedCoords[i].fVaryingPoint);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i = 0; i < numSamplers; ++i) {
|
for (int i = 0; i < numSamplers; ++i) {
|
||||||
|
@ -41,7 +41,8 @@ public:
|
|||||||
"innerThreshold");
|
"innerThreshold");
|
||||||
outerThresholdVar = args.fUniformHandler->addUniform(kFragment_GrShaderFlag, kHalf_GrSLType,
|
outerThresholdVar = args.fUniformHandler->addUniform(kFragment_GrShaderFlag, kHalf_GrSLType,
|
||||||
"outerThreshold");
|
"outerThreshold");
|
||||||
SkString sk_TransformedCoords2D_0 = fragBuilder->ensureCoords2D(args.fTransformedCoords[0]);
|
SkString sk_TransformedCoords2D_0 =
|
||||||
|
fragBuilder->ensureCoords2D(args.fTransformedCoords[0].fVaryingPoint);
|
||||||
fragBuilder->codeAppendf(
|
fragBuilder->codeAppendf(
|
||||||
"half4 color = %s;\nhalf4 mask_color = sample(%s, %s).%s;\nif (mask_color.w < 0.5) "
|
"half4 color = %s;\nhalf4 mask_color = sample(%s, %s).%s;\nif (mask_color.w < 0.5) "
|
||||||
"{\n if (color.w > %s) {\n half scale = %s / color.w;\n color.xyz "
|
"{\n if (color.w > %s) {\n half scale = %s / color.w;\n color.xyz "
|
||||||
@ -50,7 +51,8 @@ public:
|
|||||||
"color.w = %s;\n}\n%s = color;\n",
|
"color.w = %s;\n}\n%s = color;\n",
|
||||||
args.fInputColor,
|
args.fInputColor,
|
||||||
fragBuilder->getProgramBuilder()->samplerVariable(args.fTexSamplers[0]),
|
fragBuilder->getProgramBuilder()->samplerVariable(args.fTexSamplers[0]),
|
||||||
sk_TransformedCoords2D_0.c_str(),
|
_outer.computeLocalCoordsInVertexShader() ? sk_TransformedCoords2D_0.c_str()
|
||||||
|
: "_coords",
|
||||||
fragBuilder->getProgramBuilder()->samplerSwizzle(args.fTexSamplers[0]).c_str(),
|
fragBuilder->getProgramBuilder()->samplerSwizzle(args.fTexSamplers[0]).c_str(),
|
||||||
args.fUniformHandler->getUniformCStr(outerThresholdVar),
|
args.fUniformHandler->getUniformCStr(outerThresholdVar),
|
||||||
args.fUniformHandler->getUniformCStr(outerThresholdVar),
|
args.fUniformHandler->getUniformCStr(outerThresholdVar),
|
||||||
|
@ -47,7 +47,8 @@ public:
|
|||||||
kFragment_GrShaderFlag, kFloat_GrSLType, "yInvInset");
|
kFragment_GrShaderFlag, kFloat_GrSLType, "yInvInset");
|
||||||
offsetVar =
|
offsetVar =
|
||||||
args.fUniformHandler->addUniform(kFragment_GrShaderFlag, kHalf2_GrSLType, "offset");
|
args.fUniformHandler->addUniform(kFragment_GrShaderFlag, kHalf2_GrSLType, "offset");
|
||||||
SkString sk_TransformedCoords2D_0 = fragBuilder->ensureCoords2D(args.fTransformedCoords[0]);
|
SkString sk_TransformedCoords2D_0 =
|
||||||
|
fragBuilder->ensureCoords2D(args.fTransformedCoords[0].fVaryingPoint);
|
||||||
fragBuilder->codeAppendf(
|
fragBuilder->codeAppendf(
|
||||||
"float2 coord = %s;\nfloat2 zoom_coord = float2(%s) + coord * float2(%s, "
|
"float2 coord = %s;\nfloat2 zoom_coord = float2(%s) + coord * float2(%s, "
|
||||||
"%s);\nfloat2 delta = (coord - %s.xy) * %s.zw;\ndelta = min(delta, "
|
"%s);\nfloat2 delta = (coord - %s.xy) * %s.zw;\ndelta = min(delta, "
|
||||||
@ -56,7 +57,8 @@ public:
|
|||||||
"- delta;\n float dist = length(delta);\n dist = max(2.0 - dist, 0.0);\n "
|
"- delta;\n float dist = length(delta);\n dist = max(2.0 - dist, 0.0);\n "
|
||||||
"weight = min(dist * dist, 1.0);\n} else {\n float2 delta_squared = delta * "
|
"weight = min(dist * dist, 1.0);\n} else {\n float2 delta_squared = delta * "
|
||||||
"delta;\n weight = min(min(delta_squared.x, delta_square",
|
"delta;\n weight = min(min(delta_squared.x, delta_square",
|
||||||
sk_TransformedCoords2D_0.c_str(),
|
_outer.computeLocalCoordsInVertexShader() ? sk_TransformedCoords2D_0.c_str()
|
||||||
|
: "_coords",
|
||||||
args.fUniformHandler->getUniformCStr(offsetVar),
|
args.fUniformHandler->getUniformCStr(offsetVar),
|
||||||
args.fUniformHandler->getUniformCStr(xInvZoomVar),
|
args.fUniformHandler->getUniformCStr(xInvZoomVar),
|
||||||
args.fUniformHandler->getUniformCStr(yInvZoomVar),
|
args.fUniformHandler->getUniformCStr(yInvZoomVar),
|
||||||
|
@ -27,14 +27,14 @@ public:
|
|||||||
(void)weight;
|
(void)weight;
|
||||||
weightVar =
|
weightVar =
|
||||||
args.fUniformHandler->addUniform(kFragment_GrShaderFlag, kHalf_GrSLType, "weight");
|
args.fUniformHandler->addUniform(kFragment_GrShaderFlag, kHalf_GrSLType, "weight");
|
||||||
SkString _input0 = SkStringPrintf("%s", args.fInputColor);
|
SkString _input1278 = SkStringPrintf("%s", args.fInputColor);
|
||||||
SkString _sample1278("_sample1278");
|
SkString _sample1278("_sample1278");
|
||||||
this->invokeChild(_outer.fp0_index, _input0.c_str(), &_sample1278, args);
|
this->invokeChild(_outer.fp0_index, _input1278.c_str(), &_sample1278, args);
|
||||||
fragBuilder->codeAppendf("half4 in0 = %s;", _sample1278.c_str());
|
fragBuilder->codeAppendf("half4 in0 = %s;", _sample1278.c_str());
|
||||||
SkString _input1 = SkStringPrintf("%s", args.fInputColor);
|
SkString _input1335 = SkStringPrintf("%s", args.fInputColor);
|
||||||
SkString _sample1335("_sample1335");
|
SkString _sample1335("_sample1335");
|
||||||
if (_outer.fp1_index >= 0) {
|
if (_outer.fp1_index >= 0) {
|
||||||
this->invokeChild(_outer.fp1_index, _input1.c_str(), &_sample1335, args);
|
this->invokeChild(_outer.fp1_index, _input1335.c_str(), &_sample1335, args);
|
||||||
} else {
|
} else {
|
||||||
fragBuilder->codeAppendf("half4 %s;", _sample1335.c_str());
|
fragBuilder->codeAppendf("half4 %s;", _sample1335.c_str());
|
||||||
}
|
}
|
||||||
|
@ -42,9 +42,9 @@ public:
|
|||||||
: "half4(0)",
|
: "half4(0)",
|
||||||
_outer.literalColor.fR, _outer.literalColor.fG, _outer.literalColor.fB,
|
_outer.literalColor.fR, _outer.literalColor.fG, _outer.literalColor.fB,
|
||||||
_outer.literalColor.fA);
|
_outer.literalColor.fA);
|
||||||
SkString _input0("constColor");
|
SkString _input1992("constColor");
|
||||||
SkString _sample1992("_sample1992");
|
SkString _sample1992("_sample1992");
|
||||||
this->invokeChild(_outer.fp_index, _input0.c_str(), &_sample1992, args);
|
this->invokeChild(_outer.fp_index, _input1992.c_str(), &_sample1992, args);
|
||||||
fragBuilder->codeAppendf("\n%s = %s;\n", args.fOutputColor, _sample1992.c_str());
|
fragBuilder->codeAppendf("\n%s = %s;\n", args.fOutputColor, _sample1992.c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -25,11 +25,13 @@ public:
|
|||||||
(void)_outer;
|
(void)_outer;
|
||||||
auto matrix = _outer.matrix;
|
auto matrix = _outer.matrix;
|
||||||
(void)matrix;
|
(void)matrix;
|
||||||
SkString sk_TransformedCoords2D_0 = fragBuilder->ensureCoords2D(args.fTransformedCoords[0]);
|
SkString sk_TransformedCoords2D_0 =
|
||||||
|
fragBuilder->ensureCoords2D(args.fTransformedCoords[0].fVaryingPoint);
|
||||||
fragBuilder->codeAppendf(
|
fragBuilder->codeAppendf(
|
||||||
"%s = %s * sample(%s, %s).%s;\n", args.fOutputColor, args.fInputColor,
|
"%s = %s * sample(%s, %s).%s;\n", args.fOutputColor, args.fInputColor,
|
||||||
fragBuilder->getProgramBuilder()->samplerVariable(args.fTexSamplers[0]),
|
fragBuilder->getProgramBuilder()->samplerVariable(args.fTexSamplers[0]),
|
||||||
sk_TransformedCoords2D_0.c_str(),
|
_outer.computeLocalCoordsInVertexShader() ? sk_TransformedCoords2D_0.c_str()
|
||||||
|
: "_coords",
|
||||||
fragBuilder->getProgramBuilder()->samplerSwizzle(args.fTexSamplers[0]).c_str());
|
fragBuilder->getProgramBuilder()->samplerSwizzle(args.fTexSamplers[0]).c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -38,6 +38,10 @@ private:
|
|||||||
int arrayCount,
|
int arrayCount,
|
||||||
const char** outName) override;
|
const char** outName) override;
|
||||||
|
|
||||||
|
void updateUniformVisibility(UniformHandle u, uint32_t visibility) override {
|
||||||
|
fUniforms[u.toIndex()].fVisibility |= visibility;
|
||||||
|
}
|
||||||
|
|
||||||
SamplerHandle addSampler(const GrTexture*, const GrSamplerState&, const GrSwizzle&,
|
SamplerHandle addSampler(const GrTexture*, const GrSamplerState&, const GrSwizzle&,
|
||||||
const char* name, const GrShaderCaps*) override;
|
const char* name, const GrShaderCaps*) override;
|
||||||
|
|
||||||
|
@ -5,6 +5,7 @@
|
|||||||
* found in the LICENSE file.
|
* found in the LICENSE file.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include "src/gpu/GrCoordTransform.h"
|
||||||
#include "src/gpu/GrFragmentProcessor.h"
|
#include "src/gpu/GrFragmentProcessor.h"
|
||||||
#include "src/gpu/GrProcessor.h"
|
#include "src/gpu/GrProcessor.h"
|
||||||
#include "src/gpu/glsl/GrGLSLFragmentProcessor.h"
|
#include "src/gpu/glsl/GrGLSLFragmentProcessor.h"
|
||||||
@ -16,15 +17,36 @@ void GrGLSLFragmentProcessor::setData(const GrGLSLProgramDataManager& pdman,
|
|||||||
this->onSetData(pdman, processor);
|
this->onSetData(pdman, processor);
|
||||||
}
|
}
|
||||||
|
|
||||||
void GrGLSLFragmentProcessor::invokeChild(int childIndex, const char* inputColor, EmitArgs& args) {
|
void GrGLSLFragmentProcessor::invokeChild(int childIndex, const char* inputColor, EmitArgs& args,
|
||||||
|
SkSL::String skslCoords) {
|
||||||
while (childIndex >= (int) fFunctionNames.size()) {
|
while (childIndex >= (int) fFunctionNames.size()) {
|
||||||
fFunctionNames.emplace_back();
|
fFunctionNames.emplace_back();
|
||||||
}
|
}
|
||||||
this->internalInvokeChild(childIndex, inputColor, args.fOutputColor, args);
|
this->internalInvokeChild(childIndex, inputColor, args.fOutputColor, args, skslCoords);
|
||||||
|
}
|
||||||
|
|
||||||
|
void GrGLSLFragmentProcessor::writeChildCall(GrGLSLFPFragmentBuilder* fragBuilder, int childIndex,
|
||||||
|
TransformedCoordVars coordVars, const char* inputColor,
|
||||||
|
const char* outputColor, EmitArgs& args,
|
||||||
|
SkSL::String skslCoords) {
|
||||||
|
std::vector<SkString> coordParams;
|
||||||
|
for (int i = 0; i < coordVars.count(); ++i) {
|
||||||
|
coordParams.push_back(fragBuilder->ensureCoords2D(coordVars[i].fVaryingPoint));
|
||||||
|
}
|
||||||
|
// if the fragment processor is invoked with overridden coordinates, it must *always* be invoked
|
||||||
|
// with overridden coords
|
||||||
|
SkASSERT(args.fFp.computeLocalCoordsInVertexShader() == (skslCoords.length() == 0));
|
||||||
|
fragBuilder->codeAppendf("%s = %s(%s", outputColor, fFunctionNames[childIndex].c_str(),
|
||||||
|
inputColor ? inputColor : "half4(1)");
|
||||||
|
if (skslCoords.length()) {
|
||||||
|
fragBuilder->codeAppendf(", %s", skslCoords.c_str());
|
||||||
|
}
|
||||||
|
fragBuilder->codeAppend(");\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
void GrGLSLFragmentProcessor::invokeChild(int childIndex, const char* inputColor,
|
void GrGLSLFragmentProcessor::invokeChild(int childIndex, const char* inputColor,
|
||||||
SkString* outputColor, EmitArgs& args) {
|
SkString* outputColor, EmitArgs& args,
|
||||||
|
SkSL::String skslCoords) {
|
||||||
SkASSERT(outputColor);
|
SkASSERT(outputColor);
|
||||||
GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
|
GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
|
||||||
outputColor->append(fragBuilder->getMangleString());
|
outputColor->append(fragBuilder->getMangleString());
|
||||||
@ -32,17 +54,32 @@ void GrGLSLFragmentProcessor::invokeChild(int childIndex, const char* inputColor
|
|||||||
while (childIndex >= (int) fFunctionNames.size()) {
|
while (childIndex >= (int) fFunctionNames.size()) {
|
||||||
fFunctionNames.emplace_back();
|
fFunctionNames.emplace_back();
|
||||||
}
|
}
|
||||||
|
if (!args.fFp.computeLocalCoordsInVertexShader() && skslCoords.length() == 0) {
|
||||||
|
skslCoords = "_coords";
|
||||||
|
}
|
||||||
if (fFunctionNames[childIndex].size() == 0) {
|
if (fFunctionNames[childIndex].size() == 0) {
|
||||||
this->internalInvokeChild(childIndex, inputColor, outputColor->c_str(), args);
|
this->internalInvokeChild(childIndex, inputColor, outputColor->c_str(), args, skslCoords);
|
||||||
} else {
|
} else {
|
||||||
fragBuilder->codeAppendf("%s = %s(%s);", outputColor->c_str(),
|
const GrFragmentProcessor& childProc = args.fFp.childProcessor(childIndex);
|
||||||
fFunctionNames[childIndex].c_str(),
|
|
||||||
inputColor ? inputColor : "half4(1)");
|
TransformedCoordVars coordVars = args.fTransformedCoords.childInputs(childIndex);
|
||||||
|
TextureSamplers textureSamplers = args.fTexSamplers.childInputs(childIndex);
|
||||||
|
EmitArgs childArgs(fragBuilder,
|
||||||
|
args.fUniformHandler,
|
||||||
|
args.fShaderCaps,
|
||||||
|
childProc,
|
||||||
|
outputColor->c_str(),
|
||||||
|
"_input",
|
||||||
|
coordVars,
|
||||||
|
textureSamplers);
|
||||||
|
this->writeChildCall(fragBuilder, childIndex, coordVars, inputColor, outputColor->c_str(),
|
||||||
|
childArgs, skslCoords);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void GrGLSLFragmentProcessor::internalInvokeChild(int childIndex, const char* inputColor,
|
void GrGLSLFragmentProcessor::internalInvokeChild(int childIndex, const char* inputColor,
|
||||||
const char* outputColor, EmitArgs& args) {
|
const char* outputColor, EmitArgs& args,
|
||||||
|
SkSL::String skslCoords) {
|
||||||
GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
|
GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
|
||||||
|
|
||||||
fragBuilder->onBeforeChildProcEmitCode(); // call first so mangleString is updated
|
fragBuilder->onBeforeChildProcEmitCode(); // call first so mangleString is updated
|
||||||
@ -59,7 +96,6 @@ void GrGLSLFragmentProcessor::internalInvokeChild(int childIndex, const char* in
|
|||||||
}
|
}
|
||||||
|
|
||||||
const GrFragmentProcessor& childProc = args.fFp.childProcessor(childIndex);
|
const GrFragmentProcessor& childProc = args.fFp.childProcessor(childIndex);
|
||||||
|
|
||||||
TransformedCoordVars coordVars = args.fTransformedCoords.childInputs(childIndex);
|
TransformedCoordVars coordVars = args.fTransformedCoords.childInputs(childIndex);
|
||||||
TextureSamplers textureSamplers = args.fTexSamplers.childInputs(childIndex);
|
TextureSamplers textureSamplers = args.fTexSamplers.childInputs(childIndex);
|
||||||
|
|
||||||
@ -74,11 +110,8 @@ void GrGLSLFragmentProcessor::internalInvokeChild(int childIndex, const char* in
|
|||||||
fFunctionNames[childIndex] = fragBuilder->writeProcessorFunction(
|
fFunctionNames[childIndex] = fragBuilder->writeProcessorFunction(
|
||||||
this->childProcessor(childIndex),
|
this->childProcessor(childIndex),
|
||||||
childArgs);
|
childArgs);
|
||||||
fragBuilder->codeAppendf("%s = %s(%s);\n", outputColor,
|
this->writeChildCall(fragBuilder, childIndex, coordVars, inputColor, outputColor, childArgs,
|
||||||
fFunctionNames[childIndex].c_str(),
|
skslCoords);
|
||||||
inputName.size() > 0 ? inputName.c_str()
|
|
||||||
: "half4(1)");
|
|
||||||
|
|
||||||
fragBuilder->onAfterChildProcEmitCode();
|
fragBuilder->onAfterChildProcEmitCode();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -10,8 +10,10 @@
|
|||||||
|
|
||||||
#include "src/gpu/GrFragmentProcessor.h"
|
#include "src/gpu/GrFragmentProcessor.h"
|
||||||
#include "src/gpu/GrShaderVar.h"
|
#include "src/gpu/GrShaderVar.h"
|
||||||
|
#include "src/gpu/glsl/GrGLSLPrimitiveProcessor.h"
|
||||||
#include "src/gpu/glsl/GrGLSLProgramDataManager.h"
|
#include "src/gpu/glsl/GrGLSLProgramDataManager.h"
|
||||||
#include "src/gpu/glsl/GrGLSLUniformHandler.h"
|
#include "src/gpu/glsl/GrGLSLUniformHandler.h"
|
||||||
|
#include "src/sksl/SkSLString.h"
|
||||||
|
|
||||||
class GrProcessor;
|
class GrProcessor;
|
||||||
class GrProcessorKeyBuilder;
|
class GrProcessorKeyBuilder;
|
||||||
@ -69,8 +71,8 @@ private:
|
|||||||
};
|
};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
using TransformedCoordVars =
|
using TransformedCoordVars = BuilderInputProvider<GrGLSLPrimitiveProcessor::TransformVar,
|
||||||
BuilderInputProvider<GrShaderVar, &GrFragmentProcessor::numCoordTransforms>;
|
&GrFragmentProcessor::numCoordTransforms>;
|
||||||
using TextureSamplers =
|
using TextureSamplers =
|
||||||
BuilderInputProvider<SamplerHandle, &GrFragmentProcessor::numTextureSamplers>;
|
BuilderInputProvider<SamplerHandle, &GrFragmentProcessor::numTextureSamplers>;
|
||||||
|
|
||||||
@ -137,8 +139,9 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Invoke the child with the default input color (solid white)
|
// Invoke the child with the default input color (solid white)
|
||||||
inline void invokeChild(int childIndex, SkString* outputColor, EmitArgs& parentArgs) {
|
inline void invokeChild(int childIndex, SkString* outputColor, EmitArgs& parentArgs,
|
||||||
this->invokeChild(childIndex, nullptr, outputColor, parentArgs);
|
SkSL::String skslCoords = "") {
|
||||||
|
this->invokeChild(childIndex, nullptr, outputColor, parentArgs, skslCoords);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Invokes a child proc in its own scope. Pass in the parent's EmitArgs and invokeChild will
|
/** Invokes a child proc in its own scope. Pass in the parent's EmitArgs and invokeChild will
|
||||||
@ -150,17 +153,18 @@ public:
|
|||||||
* color.
|
* color.
|
||||||
*/
|
*/
|
||||||
void invokeChild(int childIndex, const char* inputColor, SkString* outputColor,
|
void invokeChild(int childIndex, const char* inputColor, SkString* outputColor,
|
||||||
EmitArgs& parentArgs);
|
EmitArgs& parentArgs, SkSL::String skslCoords = "");
|
||||||
|
|
||||||
// Use the parent's output color to hold child's output, and use the
|
// Use the parent's output color to hold child's output, and use the
|
||||||
// default input color of solid white
|
// default input color of solid white
|
||||||
inline void invokeChild(int childIndex, EmitArgs& args) {
|
inline void invokeChild(int childIndex, EmitArgs& args, SkSL::String skslCoords = "") {
|
||||||
// null pointer cast required to disambiguate the function call
|
// null pointer cast required to disambiguate the function call
|
||||||
this->invokeChild(childIndex, (const char*) nullptr, args);
|
this->invokeChild(childIndex, (const char*) nullptr, args, skslCoords);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Variation that uses the parent's output color variable to hold the child's output.*/
|
/** Variation that uses the parent's output color variable to hold the child's output.*/
|
||||||
void invokeChild(int childIndex, const char* inputColor, EmitArgs& parentArgs);
|
void invokeChild(int childIndex, const char* inputColor, EmitArgs& parentArgs,
|
||||||
|
SkSL::String skslCoords = "");
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Pre-order traversal of a GLSLFP hierarchy, or of multiple trees with roots in an array of
|
* Pre-order traversal of a GLSLFP hierarchy, or of multiple trees with roots in an array of
|
||||||
@ -189,7 +193,12 @@ protected:
|
|||||||
virtual void onSetData(const GrGLSLProgramDataManager&, const GrFragmentProcessor&) {}
|
virtual void onSetData(const GrGLSLProgramDataManager&, const GrFragmentProcessor&) {}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void internalInvokeChild(int, const char*, const char*, EmitArgs&);
|
void writeChildCall(GrGLSLFPFragmentBuilder* fragBuilder, int childIndex,
|
||||||
|
TransformedCoordVars coordVars, const char* inputColor,
|
||||||
|
const char* outputColor, EmitArgs& args,
|
||||||
|
SkSL::String skslCoords);
|
||||||
|
|
||||||
|
void internalInvokeChild(int, const char*, const char*, EmitArgs&, SkSL::String);
|
||||||
|
|
||||||
// one per child; either not present or empty string if not yet emitted
|
// one per child; either not present or empty string if not yet emitted
|
||||||
SkTArray<SkString> fFunctionNames;
|
SkTArray<SkString> fFunctionNames;
|
||||||
|
@ -160,15 +160,27 @@ SkString GrGLSLFPFragmentBuilder::writeProcessorFunction(GrGLSLFragmentProcessor
|
|||||||
GrGLSLFragmentProcessor::EmitArgs& args) {
|
GrGLSLFragmentProcessor::EmitArgs& args) {
|
||||||
this->onBeforeChildProcEmitCode();
|
this->onBeforeChildProcEmitCode();
|
||||||
this->nextStage();
|
this->nextStage();
|
||||||
|
if (!args.fFp.computeLocalCoordsInVertexShader() && args.fTransformedCoords.count() > 0) {
|
||||||
|
// we currently only support overriding a single coordinate pair
|
||||||
|
SkASSERT(args.fTransformedCoords.count() == 1);
|
||||||
|
const GrGLSLProgramDataManager::UniformHandle& mat =
|
||||||
|
args.fTransformedCoords[0].fUniformMatrix;
|
||||||
|
if (mat.isValid()) {
|
||||||
|
args.fUniformHandler->updateUniformVisibility(mat, kFragment_GrShaderFlag);
|
||||||
|
this->codeAppendf("_coords = (float3(_coords, 1) * %s).xy;\n",
|
||||||
|
args.fTransformedCoords[0].fMatrixCode.c_str());
|
||||||
|
}
|
||||||
|
}
|
||||||
this->codeAppendf("half4 %s;\n", args.fOutputColor);
|
this->codeAppendf("half4 %s;\n", args.fOutputColor);
|
||||||
fp->emitCode(args);
|
fp->emitCode(args);
|
||||||
this->codeAppendf("return %s;", args.fOutputColor);
|
this->codeAppendf("return %s;\n", args.fOutputColor);
|
||||||
GrShaderVar inColor(args.fInputColor, kHalf4_GrSLType);
|
GrShaderVar params[] = { GrShaderVar(args.fInputColor, kHalf4_GrSLType),
|
||||||
|
GrShaderVar("_coords", kFloat2_GrSLType) };
|
||||||
SkString result;
|
SkString result;
|
||||||
this->emitFunction(kHalf4_GrSLType,
|
this->emitFunction(kHalf4_GrSLType,
|
||||||
"stage",
|
"stage",
|
||||||
1,
|
args.fFp.computeLocalCoordsInVertexShader() ? 1 : 2,
|
||||||
&inColor,
|
params,
|
||||||
this->code().c_str(),
|
this->code().c_str(),
|
||||||
&result);
|
&result);
|
||||||
this->deleteStage();
|
this->deleteStage();
|
||||||
|
@ -84,15 +84,18 @@ void GrGLSLGeometryProcessor::emitTransforms(GrGLSLVertexBuilder* vb,
|
|||||||
SkString strVaryingName;
|
SkString strVaryingName;
|
||||||
strVaryingName.printf("TransformedCoords_%d", i);
|
strVaryingName.printf("TransformedCoords_%d", i);
|
||||||
GrGLSLVarying v(varyingType);
|
GrGLSLVarying v(varyingType);
|
||||||
varyingHandler->addVarying(strVaryingName.c_str(), &v);
|
if (coordTransform->computeInVertexShader()) {
|
||||||
|
varyingHandler->addVarying(strVaryingName.c_str(), &v);
|
||||||
|
|
||||||
handler->specifyCoordsForCurrCoordTransform(SkString(v.fsIn()), varyingType);
|
if (kFloat2_GrSLType == varyingType) {
|
||||||
|
vb->codeAppendf("%s = (%s * %s).xy;", v.vsOut(), uniName, localCoords.c_str());
|
||||||
if (kFloat2_GrSLType == varyingType) {
|
} else {
|
||||||
vb->codeAppendf("%s = (%s * %s).xy;", v.vsOut(), uniName, localCoords.c_str());
|
vb->codeAppendf("%s = %s * %s;", v.vsOut(), uniName, localCoords.c_str());
|
||||||
} else {
|
}
|
||||||
vb->codeAppendf("%s = %s * %s;", v.vsOut(), uniName, localCoords.c_str());
|
|
||||||
}
|
}
|
||||||
|
handler->specifyCoordsForCurrCoordTransform(SkString(uniName),
|
||||||
|
fInstalledTransforms.back().fHandle,
|
||||||
|
GrShaderVar(SkString(v.fsIn()), varyingType));
|
||||||
++i;
|
++i;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -23,12 +23,29 @@ class GrShaderCaps;
|
|||||||
|
|
||||||
class GrGLSLPrimitiveProcessor {
|
class GrGLSLPrimitiveProcessor {
|
||||||
public:
|
public:
|
||||||
|
using UniformHandle = GrGLSLProgramDataManager::UniformHandle;
|
||||||
|
using SamplerHandle = GrGLSLUniformHandler::SamplerHandle;
|
||||||
using FPCoordTransformIter = GrFragmentProcessor::CoordTransformIter;
|
using FPCoordTransformIter = GrFragmentProcessor::CoordTransformIter;
|
||||||
|
|
||||||
virtual ~GrGLSLPrimitiveProcessor() {}
|
struct TransformVar {
|
||||||
|
TransformVar() = default;
|
||||||
|
|
||||||
using UniformHandle = GrGLSLProgramDataManager::UniformHandle;
|
TransformVar(SkString matrixCode, UniformHandle uniformMatrix, GrShaderVar varyingPoint)
|
||||||
using SamplerHandle = GrGLSLUniformHandler::SamplerHandle;
|
: fMatrixCode(std::move(matrixCode))
|
||||||
|
, fUniformMatrix(uniformMatrix)
|
||||||
|
, fVaryingPoint(varyingPoint) {}
|
||||||
|
|
||||||
|
// a string of SkSL code which resolves to the transformation matrix
|
||||||
|
SkString fMatrixCode;
|
||||||
|
// the variable containing the matrix, if any, otherwise an invalid handle
|
||||||
|
UniformHandle fUniformMatrix;
|
||||||
|
// the transformed coordinate output by the vertex shader and consumed by the fragment
|
||||||
|
// shader
|
||||||
|
GrShaderVar fVaryingPoint;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
virtual ~GrGLSLPrimitiveProcessor() {}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This class provides access to the GrCoordTransforms across all GrFragmentProcessors in a
|
* This class provides access to the GrCoordTransforms across all GrFragmentProcessors in a
|
||||||
@ -40,7 +57,7 @@ public:
|
|||||||
class FPCoordTransformHandler : public SkNoncopyable {
|
class FPCoordTransformHandler : public SkNoncopyable {
|
||||||
public:
|
public:
|
||||||
FPCoordTransformHandler(const GrPipeline& pipeline,
|
FPCoordTransformHandler(const GrPipeline& pipeline,
|
||||||
SkTArray<GrShaderVar>* transformedCoordVars)
|
SkTArray<TransformVar>* transformedCoordVars)
|
||||||
: fIter(pipeline)
|
: fIter(pipeline)
|
||||||
, fTransformedCoordVars(transformedCoordVars) {}
|
, fTransformedCoordVars(transformedCoordVars) {}
|
||||||
|
|
||||||
@ -60,7 +77,7 @@ public:
|
|||||||
GrFragmentProcessor::CoordTransformIter fIter;
|
GrFragmentProcessor::CoordTransformIter fIter;
|
||||||
SkDEBUGCODE(bool fAddedCoord = false;)
|
SkDEBUGCODE(bool fAddedCoord = false;)
|
||||||
SkDEBUGCODE(const GrCoordTransform* fCurr = nullptr;)
|
SkDEBUGCODE(const GrCoordTransform* fCurr = nullptr;)
|
||||||
SkTArray<GrShaderVar>* fTransformedCoordVars;
|
SkTArray<TransformVar>* fTransformedCoordVars;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct EmitArgs {
|
struct EmitArgs {
|
||||||
|
@ -196,7 +196,8 @@ SkString GrGLSLProgramBuilder::emitAndInstallFragProc(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const GrShaderVar* coordVars = fTransformedCoordVars.begin() + transformedCoordVarsIdx;
|
const GrGLSLPrimitiveProcessor::TransformVar* coordVars = fTransformedCoordVars.begin() +
|
||||||
|
transformedCoordVarsIdx;
|
||||||
GrGLSLFragmentProcessor::TransformedCoordVars coords(&fp, coordVars);
|
GrGLSLFragmentProcessor::TransformedCoordVars coords(&fp, coordVars);
|
||||||
GrGLSLFragmentProcessor::TextureSamplers textureSamplers(&fp, texSamplers.begin());
|
GrGLSLFragmentProcessor::TextureSamplers textureSamplers(&fp, texSamplers.begin());
|
||||||
GrGLSLFragmentProcessor::EmitArgs args(&fFS,
|
GrGLSLFragmentProcessor::EmitArgs args(&fFS,
|
||||||
|
@ -169,8 +169,8 @@ private:
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
// These are used to check that we don't excede the allowable number of resources in a shader.
|
// These are used to check that we don't excede the allowable number of resources in a shader.
|
||||||
int fNumFragmentSamplers;
|
int fNumFragmentSamplers;
|
||||||
SkSTArray<4, GrShaderVar> fTransformedCoordVars;
|
SkSTArray<4, GrGLSLPrimitiveProcessor::TransformVar> fTransformedCoordVars;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -63,6 +63,11 @@ public:
|
|||||||
|
|
||||||
virtual const GrShaderVar& getUniformVariable(UniformHandle u) const = 0;
|
virtual const GrShaderVar& getUniformVariable(UniformHandle u) const = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 'Or's the visibility parameter with the current uniform visibililty.
|
||||||
|
*/
|
||||||
|
virtual void updateUniformVisibility(UniformHandle u, uint32_t visibility) = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Shortcut for getUniformVariable(u).c_str()
|
* Shortcut for getUniformVariable(u).c_str()
|
||||||
*/
|
*/
|
||||||
|
@ -46,9 +46,9 @@ public:
|
|||||||
args.fOutputColor, args.fOutputColor,
|
args.fOutputColor, args.fOutputColor,
|
||||||
args.fUniformHandler->getUniformCStr(leftBorderColorVar), args.fOutputColor,
|
args.fUniformHandler->getUniformCStr(leftBorderColorVar), args.fOutputColor,
|
||||||
args.fUniformHandler->getUniformCStr(rightBorderColorVar));
|
args.fUniformHandler->getUniformCStr(rightBorderColorVar));
|
||||||
SkString _input0("t");
|
SkString _input1767("t");
|
||||||
SkString _sample1767("_sample1767");
|
SkString _sample1767("_sample1767");
|
||||||
this->invokeChild(_outer.colorizer_index, _input0.c_str(), &_sample1767, args);
|
this->invokeChild(_outer.colorizer_index, _input1767.c_str(), &_sample1767, args);
|
||||||
fragBuilder->codeAppendf("\n %s = %s;\n}\n@if (%s) {\n %s.xyz *= %s.w;\n}\n",
|
fragBuilder->codeAppendf("\n %s = %s;\n}\n@if (%s) {\n %s.xyz *= %s.w;\n}\n",
|
||||||
args.fOutputColor, _sample1767.c_str(),
|
args.fOutputColor, _sample1767.c_str(),
|
||||||
(_outer.makePremul ? "true" : "false"), args.fOutputColor,
|
(_outer.makePremul ? "true" : "false"), args.fOutputColor,
|
||||||
|
@ -25,10 +25,13 @@ public:
|
|||||||
(void)_outer;
|
(void)_outer;
|
||||||
auto gradientMatrix = _outer.gradientMatrix;
|
auto gradientMatrix = _outer.gradientMatrix;
|
||||||
(void)gradientMatrix;
|
(void)gradientMatrix;
|
||||||
SkString sk_TransformedCoords2D_0 = fragBuilder->ensureCoords2D(args.fTransformedCoords[0]);
|
SkString sk_TransformedCoords2D_0 =
|
||||||
|
fragBuilder->ensureCoords2D(args.fTransformedCoords[0].fVaryingPoint);
|
||||||
fragBuilder->codeAppendf(
|
fragBuilder->codeAppendf(
|
||||||
"half t = half(%s.x) + 9.9999997473787516e-06;\n%s = half4(t, 1.0, 0.0, 0.0);\n",
|
"half t = half(%s.x) + 9.9999997473787516e-06;\n%s = half4(t, 1.0, 0.0, 0.0);\n",
|
||||||
sk_TransformedCoords2D_0.c_str(), args.fOutputColor);
|
_outer.computeLocalCoordsInVertexShader() ? sk_TransformedCoords2D_0.c_str()
|
||||||
|
: "_coords",
|
||||||
|
args.fOutputColor);
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -25,9 +25,13 @@ public:
|
|||||||
(void)_outer;
|
(void)_outer;
|
||||||
auto gradientMatrix = _outer.gradientMatrix;
|
auto gradientMatrix = _outer.gradientMatrix;
|
||||||
(void)gradientMatrix;
|
(void)gradientMatrix;
|
||||||
SkString sk_TransformedCoords2D_0 = fragBuilder->ensureCoords2D(args.fTransformedCoords[0]);
|
SkString sk_TransformedCoords2D_0 =
|
||||||
|
fragBuilder->ensureCoords2D(args.fTransformedCoords[0].fVaryingPoint);
|
||||||
fragBuilder->codeAppendf("half t = half(length(%s));\n%s = half4(t, 1.0, 0.0, 0.0);\n",
|
fragBuilder->codeAppendf("half t = half(length(%s));\n%s = half4(t, 1.0, 0.0, 0.0);\n",
|
||||||
sk_TransformedCoords2D_0.c_str(), args.fOutputColor);
|
_outer.computeLocalCoordsInVertexShader()
|
||||||
|
? sk_TransformedCoords2D_0.c_str()
|
||||||
|
: "_coords",
|
||||||
|
args.fOutputColor);
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -32,15 +32,24 @@ public:
|
|||||||
biasVar = args.fUniformHandler->addUniform(kFragment_GrShaderFlag, kHalf_GrSLType, "bias");
|
biasVar = args.fUniformHandler->addUniform(kFragment_GrShaderFlag, kHalf_GrSLType, "bias");
|
||||||
scaleVar =
|
scaleVar =
|
||||||
args.fUniformHandler->addUniform(kFragment_GrShaderFlag, kHalf_GrSLType, "scale");
|
args.fUniformHandler->addUniform(kFragment_GrShaderFlag, kHalf_GrSLType, "scale");
|
||||||
SkString sk_TransformedCoords2D_0 = fragBuilder->ensureCoords2D(args.fTransformedCoords[0]);
|
SkString sk_TransformedCoords2D_0 =
|
||||||
|
fragBuilder->ensureCoords2D(args.fTransformedCoords[0].fVaryingPoint);
|
||||||
fragBuilder->codeAppendf(
|
fragBuilder->codeAppendf(
|
||||||
"half angle;\nif (sk_Caps.atan2ImplementedAsAtanYOverX) {\n angle = half(2.0 * "
|
"half angle;\nif (sk_Caps.atan2ImplementedAsAtanYOverX) {\n angle = half(2.0 * "
|
||||||
"atan(-%s.y, length(%s) - %s.x));\n} else {\n angle = half(atan(-%s.y, "
|
"atan(-%s.y, length(%s) - %s.x));\n} else {\n angle = half(atan(-%s.y, "
|
||||||
"-%s.x));\n}\nhalf t = ((angle * 0.15915493667125702 + 0.5) + %s) * %s;\n%s = "
|
"-%s.x));\n}\nhalf t = ((angle * 0.15915493667125702 + 0.5) + %s) * %s;\n%s = "
|
||||||
"half4(t, 1.0, 0.0, 0.0);\n",
|
"half4(t, 1.0, 0.0, 0.0);\n",
|
||||||
sk_TransformedCoords2D_0.c_str(), sk_TransformedCoords2D_0.c_str(),
|
_outer.computeLocalCoordsInVertexShader() ? sk_TransformedCoords2D_0.c_str()
|
||||||
sk_TransformedCoords2D_0.c_str(), sk_TransformedCoords2D_0.c_str(),
|
: "_coords",
|
||||||
sk_TransformedCoords2D_0.c_str(), args.fUniformHandler->getUniformCStr(biasVar),
|
_outer.computeLocalCoordsInVertexShader() ? sk_TransformedCoords2D_0.c_str()
|
||||||
|
: "_coords",
|
||||||
|
_outer.computeLocalCoordsInVertexShader() ? sk_TransformedCoords2D_0.c_str()
|
||||||
|
: "_coords",
|
||||||
|
_outer.computeLocalCoordsInVertexShader() ? sk_TransformedCoords2D_0.c_str()
|
||||||
|
: "_coords",
|
||||||
|
_outer.computeLocalCoordsInVertexShader() ? sk_TransformedCoords2D_0.c_str()
|
||||||
|
: "_coords",
|
||||||
|
args.fUniformHandler->getUniformCStr(biasVar),
|
||||||
args.fUniformHandler->getUniformCStr(scaleVar), args.fOutputColor);
|
args.fUniformHandler->getUniformCStr(scaleVar), args.fOutputColor);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -41,9 +41,9 @@ public:
|
|||||||
(_outer.childProcessor(_outer.gradLayout_index).preservesOpaqueInput() ? "true"
|
(_outer.childProcessor(_outer.gradLayout_index).preservesOpaqueInput() ? "true"
|
||||||
: "false"),
|
: "false"),
|
||||||
args.fOutputColor, (_outer.mirror ? "true" : "false"));
|
args.fOutputColor, (_outer.mirror ? "true" : "false"));
|
||||||
SkString _input0("t");
|
SkString _input1464("t");
|
||||||
SkString _sample1464("_sample1464");
|
SkString _sample1464("_sample1464");
|
||||||
this->invokeChild(_outer.colorizer_index, _input0.c_str(), &_sample1464, args);
|
this->invokeChild(_outer.colorizer_index, _input1464.c_str(), &_sample1464, args);
|
||||||
fragBuilder->codeAppendf("\n %s = %s;\n}\n@if (%s) {\n %s.xyz *= %s.w;\n}\n",
|
fragBuilder->codeAppendf("\n %s = %s;\n}\n@if (%s) {\n %s.xyz *= %s.w;\n}\n",
|
||||||
args.fOutputColor, _sample1464.c_str(),
|
args.fOutputColor, _sample1464.c_str(),
|
||||||
(_outer.makePremul ? "true" : "false"), args.fOutputColor,
|
(_outer.makePremul ? "true" : "false"), args.fOutputColor,
|
||||||
|
@ -42,7 +42,8 @@ public:
|
|||||||
(void)focalParams;
|
(void)focalParams;
|
||||||
focalParamsVar = args.fUniformHandler->addUniform(kFragment_GrShaderFlag, kHalf2_GrSLType,
|
focalParamsVar = args.fUniformHandler->addUniform(kFragment_GrShaderFlag, kHalf2_GrSLType,
|
||||||
"focalParams");
|
"focalParams");
|
||||||
SkString sk_TransformedCoords2D_0 = fragBuilder->ensureCoords2D(args.fTransformedCoords[0]);
|
SkString sk_TransformedCoords2D_0 =
|
||||||
|
fragBuilder->ensureCoords2D(args.fTransformedCoords[0].fVaryingPoint);
|
||||||
fragBuilder->codeAppendf(
|
fragBuilder->codeAppendf(
|
||||||
"float2 p = %s;\nfloat t = -1.0;\nhalf v = 1.0;\n@switch (%d) {\n case 1:\n "
|
"float2 p = %s;\nfloat t = -1.0;\nhalf v = 1.0;\n@switch (%d) {\n case 1:\n "
|
||||||
" {\n half r0_2 = %s.y;\n t = float(r0_2) - p.y * p.y;\n "
|
" {\n half r0_2 = %s.y;\n t = float(r0_2) - p.y * p.y;\n "
|
||||||
@ -51,8 +52,9 @@ public:
|
|||||||
"0:\n {\n half r0 = %s.x;\n @if (%s) {\n "
|
"0:\n {\n half r0 = %s.x;\n @if (%s) {\n "
|
||||||
" t = length(p) - float(r0);\n } else {\n t = "
|
" t = length(p) - float(r0);\n } else {\n t = "
|
||||||
"-length(p) - float(r0);\n ",
|
"-length(p) - float(r0);\n ",
|
||||||
sk_TransformedCoords2D_0.c_str(), (int)_outer.type,
|
_outer.computeLocalCoordsInVertexShader() ? sk_TransformedCoords2D_0.c_str()
|
||||||
args.fUniformHandler->getUniformCStr(focalParamsVar),
|
: "_coords",
|
||||||
|
(int)_outer.type, args.fUniformHandler->getUniformCStr(focalParamsVar),
|
||||||
args.fUniformHandler->getUniformCStr(focalParamsVar),
|
args.fUniformHandler->getUniformCStr(focalParamsVar),
|
||||||
(_outer.isRadiusIncreasing ? "true" : "false"));
|
(_outer.isRadiusIncreasing ? "true" : "false"));
|
||||||
fragBuilder->codeAppendf(
|
fragBuilder->codeAppendf(
|
||||||
|
@ -57,6 +57,10 @@ private:
|
|||||||
int arrayCount,
|
int arrayCount,
|
||||||
const char** outName) override;
|
const char** outName) override;
|
||||||
|
|
||||||
|
void updateUniformVisibility(UniformHandle u, uint32_t visibility) override {
|
||||||
|
fUniforms[u.toIndex()].fVisibility |= visibility;
|
||||||
|
}
|
||||||
|
|
||||||
SamplerHandle addSampler(const GrTexture*,
|
SamplerHandle addSampler(const GrTexture*,
|
||||||
const GrSamplerState&,
|
const GrSamplerState&,
|
||||||
const GrSwizzle&,
|
const GrSwizzle&,
|
||||||
|
@ -73,6 +73,10 @@ private:
|
|||||||
int arrayCount,
|
int arrayCount,
|
||||||
const char** outName) override;
|
const char** outName) override;
|
||||||
|
|
||||||
|
void updateUniformVisibility(UniformHandle u, uint32_t visibility) override {
|
||||||
|
fUniforms[u.toIndex()].fVisibility |= visibility;
|
||||||
|
}
|
||||||
|
|
||||||
SamplerHandle addSampler(const GrTexture* texture,
|
SamplerHandle addSampler(const GrTexture* texture,
|
||||||
const GrSamplerState&,
|
const GrSamplerState&,
|
||||||
const GrSwizzle&,
|
const GrSwizzle&,
|
||||||
|
@ -837,7 +837,7 @@ void GrGLPerlinNoise::emitCode(EmitArgs& args) {
|
|||||||
|
|
||||||
GrGLSLFragmentBuilder* fragBuilder = args.fFragBuilder;
|
GrGLSLFragmentBuilder* fragBuilder = args.fFragBuilder;
|
||||||
GrGLSLUniformHandler* uniformHandler = args.fUniformHandler;
|
GrGLSLUniformHandler* uniformHandler = args.fUniformHandler;
|
||||||
SkString vCoords = fragBuilder->ensureCoords2D(args.fTransformedCoords[0]);
|
SkString vCoords = fragBuilder->ensureCoords2D(args.fTransformedCoords[0].fVaryingPoint);
|
||||||
|
|
||||||
fBaseFrequencyUni = uniformHandler->addUniform(kFragment_GrShaderFlag, kHalf2_GrSLType,
|
fBaseFrequencyUni = uniformHandler->addUniform(kFragment_GrShaderFlag, kHalf2_GrSLType,
|
||||||
"baseFrequency");
|
"baseFrequency");
|
||||||
@ -1254,7 +1254,7 @@ void GrGLImprovedPerlinNoise::emitCode(EmitArgs& args) {
|
|||||||
const GrImprovedPerlinNoiseEffect& pne = args.fFp.cast<GrImprovedPerlinNoiseEffect>();
|
const GrImprovedPerlinNoiseEffect& pne = args.fFp.cast<GrImprovedPerlinNoiseEffect>();
|
||||||
GrGLSLFragmentBuilder* fragBuilder = args.fFragBuilder;
|
GrGLSLFragmentBuilder* fragBuilder = args.fFragBuilder;
|
||||||
GrGLSLUniformHandler* uniformHandler = args.fUniformHandler;
|
GrGLSLUniformHandler* uniformHandler = args.fUniformHandler;
|
||||||
SkString vCoords = fragBuilder->ensureCoords2D(args.fTransformedCoords[0]);
|
SkString vCoords = fragBuilder->ensureCoords2D(args.fTransformedCoords[0].fVaryingPoint);
|
||||||
|
|
||||||
fBaseFrequencyUni = uniformHandler->addUniform(kFragment_GrShaderFlag, kHalf2_GrSLType,
|
fBaseFrequencyUni = uniformHandler->addUniform(kFragment_GrShaderFlag, kHalf2_GrSLType,
|
||||||
"baseFrequency");
|
"baseFrequency");
|
||||||
|
@ -25,7 +25,7 @@ CPPCodeGenerator::CPPCodeGenerator(const Context* context, const Program* progra
|
|||||||
: INHERITED(context, program, errors, out)
|
: INHERITED(context, program, errors, out)
|
||||||
, fName(std::move(name))
|
, fName(std::move(name))
|
||||||
, fFullName(String::printf("Gr%s", fName.c_str()))
|
, fFullName(String::printf("Gr%s", fName.c_str()))
|
||||||
, fSectionAndParameterHelper(*program, *errors) {
|
, fSectionAndParameterHelper(program, *errors) {
|
||||||
fLineEnding = "\\n";
|
fLineEnding = "\\n";
|
||||||
fTextureFunctionOverride = "sample";
|
fTextureFunctionOverride = "sample";
|
||||||
}
|
}
|
||||||
@ -122,11 +122,12 @@ void CPPCodeGenerator::writeIndexExpression(const IndexExpression& i) {
|
|||||||
}
|
}
|
||||||
int64_t index = ((IntLiteral&) *i.fIndex).fValue;
|
int64_t index = ((IntLiteral&) *i.fIndex).fValue;
|
||||||
String name = "sk_TransformedCoords2D_" + to_string(index);
|
String name = "sk_TransformedCoords2D_" + to_string(index);
|
||||||
fFormatArgs.push_back(name + ".c_str()");
|
fFormatArgs.push_back("_outer.computeLocalCoordsInVertexShader() ? " + name +
|
||||||
|
".c_str() : \"_coords\"");
|
||||||
if (fWrittenTransformedCoords.find(index) == fWrittenTransformedCoords.end()) {
|
if (fWrittenTransformedCoords.find(index) == fWrittenTransformedCoords.end()) {
|
||||||
addExtraEmitCodeLine("SkString " + name +
|
addExtraEmitCodeLine("SkString " + name +
|
||||||
" = fragBuilder->ensureCoords2D(args.fTransformedCoords[" +
|
" = fragBuilder->ensureCoords2D(args.fTransformedCoords[" +
|
||||||
to_string(index) + "]);");
|
to_string(index) + "].fVaryingPoint);");
|
||||||
fWrittenTransformedCoords.insert(index);
|
fWrittenTransformedCoords.insert(index);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
@ -408,7 +409,7 @@ void CPPCodeGenerator::writeFunctionCall(const FunctionCall& c) {
|
|||||||
if (c.fFunction.fBuiltin && c.fFunction.fName == "sample" &&
|
if (c.fFunction.fBuiltin && c.fFunction.fName == "sample" &&
|
||||||
c.fArguments[0]->fType.kind() != Type::Kind::kSampler_Kind) {
|
c.fArguments[0]->fType.kind() != Type::Kind::kSampler_Kind) {
|
||||||
// Sanity checks that are detected by function definition in sksl_fp.inc
|
// Sanity checks that are detected by function definition in sksl_fp.inc
|
||||||
SkASSERT(c.fArguments.size() == 1 || c.fArguments.size() == 2);
|
SkASSERT(c.fArguments.size() >= 1 && c.fArguments.size() <= 3);
|
||||||
SkASSERT("fragmentProcessor" == c.fArguments[0]->fType.name() ||
|
SkASSERT("fragmentProcessor" == c.fArguments[0]->fType.name() ||
|
||||||
"fragmentProcessor?" == c.fArguments[0]->fType.name());
|
"fragmentProcessor?" == c.fArguments[0]->fType.name());
|
||||||
|
|
||||||
@ -420,12 +421,7 @@ void CPPCodeGenerator::writeFunctionCall(const FunctionCall& c) {
|
|||||||
"sample()'s fragmentProcessor argument must be a variable reference\n");
|
"sample()'s fragmentProcessor argument must be a variable reference\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (c.fArguments.size() > 1) {
|
|
||||||
// Second argument must also be a half4 expression
|
|
||||||
SkASSERT("half4" == c.fArguments[1]->fType.name());
|
|
||||||
}
|
|
||||||
const Variable& child = ((const VariableReference&) *c.fArguments[0]).fVariable;
|
const Variable& child = ((const VariableReference&) *c.fArguments[0]).fVariable;
|
||||||
int index = getChildFPIndex(child);
|
|
||||||
|
|
||||||
// Start a new extra emit code section so that the emitted child processor can depend on
|
// Start a new extra emit code section so that the emitted child processor can depend on
|
||||||
// sksl variables defined in earlier sksl code.
|
// sksl variables defined in earlier sksl code.
|
||||||
@ -435,25 +431,38 @@ void CPPCodeGenerator::writeFunctionCall(const FunctionCall& c) {
|
|||||||
// must be properly formatted with a prefixed comma when the parameter should be inserted
|
// must be properly formatted with a prefixed comma when the parameter should be inserted
|
||||||
// into the invokeChild() parameter list.
|
// into the invokeChild() parameter list.
|
||||||
String inputArg;
|
String inputArg;
|
||||||
if (c.fArguments.size() > 1) {
|
if (c.fArguments.size() > 1 && c.fArguments[1]->fType.name() == "half4") {
|
||||||
SkASSERT(c.fArguments.size() == 2);
|
|
||||||
// Use the invokeChild() variant that accepts an input color, so convert the 2nd
|
// Use the invokeChild() variant that accepts an input color, so convert the 2nd
|
||||||
// argument's expression into C++ code that produces sksl stored in an SkString.
|
// argument's expression into C++ code that produces sksl stored in an SkString.
|
||||||
String inputName = "_input" + to_string(index);
|
String inputName = "_input" + to_string(c.fOffset);
|
||||||
addExtraEmitCodeLine(convertSKSLExpressionToCPP(*c.fArguments[1], inputName));
|
addExtraEmitCodeLine(convertSKSLExpressionToCPP(*c.fArguments[1], inputName));
|
||||||
|
|
||||||
// invokeChild() needs a char*
|
// invokeChild() needs a char*
|
||||||
inputArg = ", " + inputName + ".c_str()";
|
inputArg = ", " + inputName + ".c_str()";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool hasCoords = c.fArguments.back()->fType.name() == "float2";
|
||||||
|
|
||||||
// Write the output handling after the possible input handling
|
// Write the output handling after the possible input handling
|
||||||
String childName = "_sample" + to_string(c.fOffset);
|
String childName = "_sample" + to_string(c.fOffset);
|
||||||
addExtraEmitCodeLine("SkString " + childName + "(\"" + childName + "\");");
|
addExtraEmitCodeLine("SkString " + childName + "(\"" + childName + "\");");
|
||||||
|
String coordsName;
|
||||||
|
if (hasCoords) {
|
||||||
|
coordsName = "_coords" + to_string(c.fOffset);
|
||||||
|
addExtraEmitCodeLine(convertSKSLExpressionToCPP(*c.fArguments.back(), coordsName));
|
||||||
|
}
|
||||||
if (c.fArguments[0]->fType.kind() == Type::kNullable_Kind) {
|
if (c.fArguments[0]->fType.kind() == Type::kNullable_Kind) {
|
||||||
addExtraEmitCodeLine("if (_outer." + String(child.fName) + "_index >= 0) {\n ");
|
addExtraEmitCodeLine("if (_outer." + String(child.fName) + "_index >= 0) {\n ");
|
||||||
}
|
}
|
||||||
addExtraEmitCodeLine("this->invokeChild(_outer." + String(child.fName) + "_index" +
|
if (hasCoords) {
|
||||||
inputArg + ", &" + childName + ", args);");
|
addExtraEmitCodeLine("this->invokeChild(_outer." + String(child.fName) + "_index" +
|
||||||
|
inputArg + ", &" + childName + ", args, " + coordsName +
|
||||||
|
".c_str());");
|
||||||
|
} else {
|
||||||
|
addExtraEmitCodeLine("this->invokeChild(_outer." + String(child.fName) + "_index" +
|
||||||
|
inputArg + ", &" + childName + ", args);");
|
||||||
|
}
|
||||||
|
|
||||||
if (c.fArguments[0]->fType.kind() == Type::kNullable_Kind) {
|
if (c.fArguments[0]->fType.kind() == Type::kNullable_Kind) {
|
||||||
// Null FPs are not emitted, but their output can still be referenced in dependent
|
// Null FPs are not emitted, but their output can still be referenced in dependent
|
||||||
// expressions - thus we always declare the variable.
|
// expressions - thus we always declare the variable.
|
||||||
|
@ -25,7 +25,7 @@ HCodeGenerator::HCodeGenerator(const Context* context, const Program* program,
|
|||||||
, fContext(*context)
|
, fContext(*context)
|
||||||
, fName(std::move(name))
|
, fName(std::move(name))
|
||||||
, fFullName(String::printf("Gr%s", fName.c_str()))
|
, fFullName(String::printf("Gr%s", fName.c_str()))
|
||||||
, fSectionAndParameterHelper(*program, *errors) {}
|
, fSectionAndParameterHelper(program, *errors) {}
|
||||||
|
|
||||||
String HCodeGenerator::ParameterType(const Context& context, const Type& type,
|
String HCodeGenerator::ParameterType(const Context& context, const Type& type,
|
||||||
const Layout& layout) {
|
const Layout& layout) {
|
||||||
@ -281,6 +281,10 @@ void HCodeGenerator::writeConstructor() {
|
|||||||
}
|
}
|
||||||
this->writef(" %s_index = this->numChildProcessors();",
|
this->writef(" %s_index = this->numChildProcessors();",
|
||||||
FieldName(String(param->fName).c_str()).c_str());
|
FieldName(String(param->fName).c_str()).c_str());
|
||||||
|
if (fSectionAndParameterHelper.hasCoordOverrides(*param)) {
|
||||||
|
this->writef(" %s->setComputeLocalCoordsInVertexShader(false);",
|
||||||
|
String(param->fName).c_str());
|
||||||
|
}
|
||||||
this->writef(" this->registerChildProcessor(std::move(%s));",
|
this->writef(" this->registerChildProcessor(std::move(%s));",
|
||||||
String(param->fName).c_str());
|
String(param->fName).c_str());
|
||||||
if (param->fType.kind() == Type::kNullable_Kind) {
|
if (param->fType.kind() == Type::kNullable_Kind) {
|
||||||
|
@ -21,7 +21,7 @@ PipelineStageCodeGenerator::PipelineStageCodeGenerator(
|
|||||||
: INHERITED(context, program, errors, out)
|
: INHERITED(context, program, errors, out)
|
||||||
, fName("Temp")
|
, fName("Temp")
|
||||||
, fFullName(String::printf("Gr%s", fName.c_str()))
|
, fFullName(String::printf("Gr%s", fName.c_str()))
|
||||||
, fSectionAndParameterHelper(*program, *errors)
|
, fSectionAndParameterHelper(program, *errors)
|
||||||
, fFormatArgs(outFormatArgs) {}
|
, fFormatArgs(outFormatArgs) {}
|
||||||
|
|
||||||
void PipelineStageCodeGenerator::writef(const char* s, va_list va) {
|
void PipelineStageCodeGenerator::writef(const char* s, va_list va) {
|
||||||
|
240
src/sksl/SkSLSectionAndParameterHelper.cpp
Normal file
240
src/sksl/SkSLSectionAndParameterHelper.cpp
Normal file
@ -0,0 +1,240 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2019 Google LLC.
|
||||||
|
*
|
||||||
|
* Use of this source code is governed by a BSD-style license that can be
|
||||||
|
* found in the LICENSE file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "src/sksl/SkSLSectionAndParameterHelper.h"
|
||||||
|
#include "src/sksl/ir/SkSLBinaryExpression.h"
|
||||||
|
#include "src/sksl/ir/SkSLConstructor.h"
|
||||||
|
#include "src/sksl/ir/SkSLDoStatement.h"
|
||||||
|
#include "src/sksl/ir/SkSLExpressionStatement.h"
|
||||||
|
#include "src/sksl/ir/SkSLFieldAccess.h"
|
||||||
|
#include "src/sksl/ir/SkSLForStatement.h"
|
||||||
|
#include "src/sksl/ir/SkSLFunctionCall.h"
|
||||||
|
#include "src/sksl/ir/SkSLIfStatement.h"
|
||||||
|
#include "src/sksl/ir/SkSLIndexExpression.h"
|
||||||
|
#include "src/sksl/ir/SkSLPostfixExpression.h"
|
||||||
|
#include "src/sksl/ir/SkSLPrefixExpression.h"
|
||||||
|
#include "src/sksl/ir/SkSLReturnStatement.h"
|
||||||
|
#include "src/sksl/ir/SkSLSwitchStatement.h"
|
||||||
|
#include "src/sksl/ir/SkSLSwizzle.h"
|
||||||
|
#include "src/sksl/ir/SkSLTernaryExpression.h"
|
||||||
|
#include "src/sksl/ir/SkSLVarDeclarationsStatement.h"
|
||||||
|
#include "src/sksl/ir/SkSLWhileStatement.h"
|
||||||
|
|
||||||
|
namespace SkSL {
|
||||||
|
|
||||||
|
SectionAndParameterHelper::SectionAndParameterHelper(const Program* program, ErrorReporter& errors)
|
||||||
|
: fProgram(*program) {
|
||||||
|
for (const auto& p : fProgram) {
|
||||||
|
switch (p.fKind) {
|
||||||
|
case ProgramElement::kVar_Kind: {
|
||||||
|
const VarDeclarations& decls = (const VarDeclarations&) p;
|
||||||
|
for (const auto& raw : decls.fVars) {
|
||||||
|
const VarDeclaration& decl = (VarDeclaration&) *raw;
|
||||||
|
if (IsParameter(*decl.fVar)) {
|
||||||
|
fParameters.push_back(decl.fVar);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case ProgramElement::kSection_Kind: {
|
||||||
|
const Section& s = (const Section&) p;
|
||||||
|
if (IsSupportedSection(s.fName.c_str())) {
|
||||||
|
if (SectionRequiresArgument(s.fName.c_str()) && !s.fArgument.size()) {
|
||||||
|
errors.error(s.fOffset,
|
||||||
|
("section '@" + s.fName +
|
||||||
|
"' requires one parameter").c_str());
|
||||||
|
}
|
||||||
|
if (!SectionAcceptsArgument(s.fName.c_str()) && s.fArgument.size()) {
|
||||||
|
errors.error(s.fOffset,
|
||||||
|
("section '@" + s.fName + "' has no parameters").c_str());
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
errors.error(s.fOffset,
|
||||||
|
("unsupported section '@" + s.fName + "'").c_str());
|
||||||
|
}
|
||||||
|
if (!SectionPermitsDuplicates(s.fName.c_str()) &&
|
||||||
|
fSections.find(s.fName) != fSections.end()) {
|
||||||
|
errors.error(s.fOffset,
|
||||||
|
("duplicate section '@" + s.fName + "'").c_str());
|
||||||
|
}
|
||||||
|
fSections[s.fName].push_back(&s);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SectionAndParameterHelper::hasCoordOverrides(const Variable& fp) {
|
||||||
|
for (const auto& pe : fProgram) {
|
||||||
|
if (this->hasCoordOverrides(pe, fp)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SectionAndParameterHelper::hasCoordOverrides(const ProgramElement& pe, const Variable& fp) {
|
||||||
|
if (pe.fKind == ProgramElement::kFunction_Kind) {
|
||||||
|
return this->hasCoordOverrides(*((const FunctionDefinition&) pe).fBody, fp);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SectionAndParameterHelper::hasCoordOverrides(const Expression& e, const Variable& fp) {
|
||||||
|
switch (e.fKind) {
|
||||||
|
case Expression::kFunctionCall_Kind: {
|
||||||
|
const FunctionCall& fc = (const FunctionCall&) e;
|
||||||
|
const FunctionDeclaration& f = fc.fFunction;
|
||||||
|
if (f.fBuiltin && f.fName == "sample" && fc.fArguments.size() >= 2 &&
|
||||||
|
fc.fArguments.back()->fType == *fProgram.fContext->fFloat2_Type &&
|
||||||
|
fc.fArguments[0]->fKind == Expression::kVariableReference_Kind &&
|
||||||
|
&((VariableReference&) *fc.fArguments[0]).fVariable == &fp) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
for (const auto& e : fc.fArguments) {
|
||||||
|
if (this->hasCoordOverrides(*e, fp)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
case Expression::kConstructor_Kind: {
|
||||||
|
const Constructor& c = (const Constructor&) e;
|
||||||
|
for (const auto& e : c.fArguments) {
|
||||||
|
if (this->hasCoordOverrides(*e, fp)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
case Expression::kFieldAccess_Kind: {
|
||||||
|
return this->hasCoordOverrides(*((const FieldAccess&) e).fBase, fp);
|
||||||
|
}
|
||||||
|
case Expression::kSwizzle_Kind:
|
||||||
|
return this->hasCoordOverrides(*((const Swizzle&) e).fBase, fp);
|
||||||
|
case Expression::kBinary_Kind: {
|
||||||
|
const BinaryExpression& b = (const BinaryExpression&) e;
|
||||||
|
return this->hasCoordOverrides(*b.fLeft, fp) ||
|
||||||
|
this->hasCoordOverrides(*b.fRight, fp);
|
||||||
|
}
|
||||||
|
case Expression::kIndex_Kind: {
|
||||||
|
const IndexExpression& idx = (const IndexExpression&) e;
|
||||||
|
return this->hasCoordOverrides(*idx.fBase, fp) ||
|
||||||
|
this->hasCoordOverrides(*idx.fIndex, fp);
|
||||||
|
}
|
||||||
|
case Expression::kPrefix_Kind:
|
||||||
|
return this->hasCoordOverrides(*((const PrefixExpression&) e).fOperand, fp);
|
||||||
|
case Expression::kPostfix_Kind:
|
||||||
|
return this->hasCoordOverrides(*((const PostfixExpression&) e).fOperand, fp);
|
||||||
|
case Expression::kTernary_Kind: {
|
||||||
|
const TernaryExpression& t = (const TernaryExpression&) e;
|
||||||
|
return this->hasCoordOverrides(*t.fTest, fp) ||
|
||||||
|
this->hasCoordOverrides(*t.fIfTrue, fp) ||
|
||||||
|
this->hasCoordOverrides(*t.fIfFalse, fp);
|
||||||
|
}
|
||||||
|
case Expression::kVariableReference_Kind:
|
||||||
|
return false;
|
||||||
|
case Expression::kAppendStage_Kind:
|
||||||
|
case Expression::kBoolLiteral_Kind:
|
||||||
|
case Expression::kDefined_Kind:
|
||||||
|
case Expression::kExternalFunctionCall_Kind:
|
||||||
|
case Expression::kExternalValue_Kind:
|
||||||
|
case Expression::kFloatLiteral_Kind:
|
||||||
|
case Expression::kFunctionReference_Kind:
|
||||||
|
case Expression::kIntLiteral_Kind:
|
||||||
|
case Expression::kNullLiteral_Kind:
|
||||||
|
case Expression::kSetting_Kind:
|
||||||
|
case Expression::kTypeReference_Kind:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
SkASSERT(false);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SectionAndParameterHelper::hasCoordOverrides(const Statement& s, const Variable& fp) {
|
||||||
|
switch (s.fKind) {
|
||||||
|
case Statement::kBlock_Kind: {
|
||||||
|
for (const auto& child : ((const Block&) s).fStatements) {
|
||||||
|
if (this->hasCoordOverrides(*child, fp)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
case Statement::kVarDeclaration_Kind: {
|
||||||
|
const VarDeclaration& var = (const VarDeclaration&) s;
|
||||||
|
if (var.fValue) {
|
||||||
|
return hasCoordOverrides(*var.fValue, fp);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
case Statement::kVarDeclarations_Kind: {
|
||||||
|
const VarDeclarations& decls = *((const VarDeclarationsStatement&) s).fDeclaration;
|
||||||
|
for (const auto& stmt : decls.fVars) {
|
||||||
|
if (this->hasCoordOverrides(*stmt, fp)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
case Statement::kExpression_Kind:
|
||||||
|
return this->hasCoordOverrides(*((const ExpressionStatement&) s).fExpression, fp);
|
||||||
|
case Statement::kReturn_Kind: {
|
||||||
|
const ReturnStatement& r = (const ReturnStatement&) s;
|
||||||
|
if (r.fExpression) {
|
||||||
|
return this->hasCoordOverrides(*r.fExpression, fp);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
case Statement::kIf_Kind: {
|
||||||
|
const IfStatement& i = (const IfStatement&) s;
|
||||||
|
return this->hasCoordOverrides(*i.fTest, fp) ||
|
||||||
|
this->hasCoordOverrides(*i.fIfTrue, fp) ||
|
||||||
|
(i.fIfFalse && this->hasCoordOverrides(*i.fIfFalse, fp));
|
||||||
|
}
|
||||||
|
case Statement::kFor_Kind: {
|
||||||
|
const ForStatement& f = (const ForStatement&) s;
|
||||||
|
return this->hasCoordOverrides(*f.fInitializer, fp) ||
|
||||||
|
this->hasCoordOverrides(*f.fTest, fp) ||
|
||||||
|
this->hasCoordOverrides(*f.fNext, fp) ||
|
||||||
|
this->hasCoordOverrides(*f.fStatement, fp);
|
||||||
|
}
|
||||||
|
case Statement::kWhile_Kind: {
|
||||||
|
const WhileStatement& w = (const WhileStatement&) s;
|
||||||
|
return this->hasCoordOverrides(*w.fTest, fp) ||
|
||||||
|
this->hasCoordOverrides(*w.fStatement, fp);
|
||||||
|
}
|
||||||
|
case Statement::kDo_Kind: {
|
||||||
|
const DoStatement& d = (const DoStatement&) s;
|
||||||
|
return this->hasCoordOverrides(*d.fTest, fp) ||
|
||||||
|
this->hasCoordOverrides(*d.fStatement, fp);
|
||||||
|
}
|
||||||
|
case Statement::kSwitch_Kind: {
|
||||||
|
const SwitchStatement& sw = (const SwitchStatement&) s;
|
||||||
|
for (const auto& c : sw.fCases) {
|
||||||
|
for (const auto& st : c->fStatements) {
|
||||||
|
if (this->hasCoordOverrides(*st, fp)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return this->hasCoordOverrides(*sw.fValue, fp);
|
||||||
|
}
|
||||||
|
case Statement::kBreak_Kind:
|
||||||
|
case Statement::kContinue_Kind:
|
||||||
|
case Statement::kDiscard_Kind:
|
||||||
|
case Statement::kGroup_Kind:
|
||||||
|
case Statement::kNop_Kind:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
SkASSERT(false);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -38,48 +38,7 @@ namespace SkSL {
|
|||||||
|
|
||||||
class SectionAndParameterHelper {
|
class SectionAndParameterHelper {
|
||||||
public:
|
public:
|
||||||
SectionAndParameterHelper(const Program& program, ErrorReporter& errors) {
|
SectionAndParameterHelper(const Program* program, ErrorReporter& errors);
|
||||||
for (const auto& p : program) {
|
|
||||||
switch (p.fKind) {
|
|
||||||
case ProgramElement::kVar_Kind: {
|
|
||||||
const VarDeclarations& decls = (const VarDeclarations&) p;
|
|
||||||
for (const auto& raw : decls.fVars) {
|
|
||||||
const VarDeclaration& decl = (VarDeclaration&) *raw;
|
|
||||||
if (IsParameter(*decl.fVar)) {
|
|
||||||
fParameters.push_back(decl.fVar);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case ProgramElement::kSection_Kind: {
|
|
||||||
const Section& s = (const Section&) p;
|
|
||||||
if (IsSupportedSection(s.fName.c_str())) {
|
|
||||||
if (SectionRequiresArgument(s.fName.c_str()) && !s.fArgument.size()) {
|
|
||||||
errors.error(s.fOffset,
|
|
||||||
("section '@" + s.fName +
|
|
||||||
"' requires one parameter").c_str());
|
|
||||||
}
|
|
||||||
if (!SectionAcceptsArgument(s.fName.c_str()) && s.fArgument.size()) {
|
|
||||||
errors.error(s.fOffset,
|
|
||||||
("section '@" + s.fName + "' has no parameters").c_str());
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
errors.error(s.fOffset,
|
|
||||||
("unsupported section '@" + s.fName + "'").c_str());
|
|
||||||
}
|
|
||||||
if (!SectionPermitsDuplicates(s.fName.c_str()) &&
|
|
||||||
fSections.find(s.fName) != fSections.end()) {
|
|
||||||
errors.error(s.fOffset,
|
|
||||||
("duplicate section '@" + s.fName + "'").c_str());
|
|
||||||
}
|
|
||||||
fSections[s.fName].push_back(&s);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const Section* getSection(const char* name) {
|
const Section* getSection(const char* name) {
|
||||||
SkASSERT(!SectionPermitsDuplicates(name));
|
SkASSERT(!SectionPermitsDuplicates(name));
|
||||||
@ -103,6 +62,8 @@ public:
|
|||||||
return fParameters;
|
return fParameters;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool hasCoordOverrides(const Variable& fp);
|
||||||
|
|
||||||
static bool IsParameter(const Variable& var) {
|
static bool IsParameter(const Variable& var) {
|
||||||
return (var.fModifiers.fFlags & Modifiers::kIn_Flag) &&
|
return (var.fModifiers.fFlags & Modifiers::kIn_Flag) &&
|
||||||
-1 == var.fModifiers.fLayout.fBuiltin;
|
-1 == var.fModifiers.fLayout.fBuiltin;
|
||||||
@ -148,6 +109,13 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
bool hasCoordOverrides(const Statement& s, const Variable& fp);
|
||||||
|
|
||||||
|
bool hasCoordOverrides(const Expression& e, const Variable& fp);
|
||||||
|
|
||||||
|
bool hasCoordOverrides(const ProgramElement& p, const Variable& fp);
|
||||||
|
|
||||||
|
const Program& fProgram;
|
||||||
std::vector<const Variable*> fParameters;
|
std::vector<const Variable*> fParameters;
|
||||||
std::unordered_map<String, std::vector<const Section*>> fSections;
|
std::unordered_map<String, std::vector<const Section*>> fSections;
|
||||||
};
|
};
|
||||||
|
@ -24,7 +24,11 @@ layout(builtin=10011) half sk_Width;
|
|||||||
layout(builtin=10012) half sk_Height;
|
layout(builtin=10012) half sk_Height;
|
||||||
|
|
||||||
half4 sample(fragmentProcessor fp);
|
half4 sample(fragmentProcessor fp);
|
||||||
|
half4 sample(fragmentProcessor fp, float2 coords);
|
||||||
half4 sample(fragmentProcessor fp, half4 input);
|
half4 sample(fragmentProcessor fp, half4 input);
|
||||||
|
half4 sample(fragmentProcessor fp, half4 input, float2 coords);
|
||||||
half4 sample(fragmentProcessor? fp);
|
half4 sample(fragmentProcessor? fp);
|
||||||
|
half4 sample(fragmentProcessor? fp, float2 coords);
|
||||||
half4 sample(fragmentProcessor? fp, half4 input);
|
half4 sample(fragmentProcessor? fp, half4 input);
|
||||||
|
half4 sample(fragmentProcessor? fp, half4 input, float2 coords);
|
||||||
)
|
)
|
||||||
|
@ -452,9 +452,11 @@ DEF_TEST(SkSLFPTransformedCoords, r) {
|
|||||||
{},
|
{},
|
||||||
{
|
{
|
||||||
"SkString sk_TransformedCoords2D_0 = "
|
"SkString sk_TransformedCoords2D_0 = "
|
||||||
"fragBuilder->ensureCoords2D(args.fTransformedCoords[0]);",
|
"fragBuilder->ensureCoords2D(args.fTransformedCoords[0].fVaryingPoint);",
|
||||||
"fragBuilder->codeAppendf(\"%s = half4(%s, %s);\\n\", args.fOutputColor, "
|
"fragBuilder->codeAppendf(\"%s = half4(%s, %s);\\n\", args.fOutputColor, "
|
||||||
"sk_TransformedCoords2D_0.c_str(), sk_TransformedCoords2D_0.c_str());"
|
"_outer.computeLocalCoordsInVertexShader() ? sk_TransformedCoords2D_0.c_str() :"
|
||||||
|
" \"_coords\", _outer.computeLocalCoordsInVertexShader() ? "
|
||||||
|
"sk_TransformedCoords2D_0.c_str() : \"_coords\");"
|
||||||
});
|
});
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -513,13 +515,13 @@ DEF_TEST(SkSLFPChildProcessorsWithInput, r) {
|
|||||||
"this->registerChildProcessor(std::move(child2));"
|
"this->registerChildProcessor(std::move(child2));"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"SkString _input0(\"childIn\");",
|
"SkString _input128(\"childIn\");",
|
||||||
"SkString _sample128(\"_sample128\");",
|
"SkString _sample128(\"_sample128\");",
|
||||||
"this->invokeChild(_outer.child1_index, _input0.c_str(), &_sample128, args);",
|
"this->invokeChild(_outer.child1_index, _input128.c_str(), &_sample128, args);",
|
||||||
"fragBuilder->codeAppendf(\"\\nhalf4 childOut1 = %s;\", _sample128.c_str());",
|
"fragBuilder->codeAppendf(\"\\nhalf4 childOut1 = %s;\", _sample128.c_str());",
|
||||||
"SkString _input1(\"childOut1\");",
|
"SkString _input174(\"childOut1\");",
|
||||||
"SkString _sample174(\"_sample174\");",
|
"SkString _sample174(\"_sample174\");",
|
||||||
"this->invokeChild(_outer.child2_index, _input1.c_str(), &_sample174, args);",
|
"this->invokeChild(_outer.child2_index, _input174.c_str(), &_sample174, args);",
|
||||||
"this->registerChildProcessor(src.childProcessor(child1_index).clone());",
|
"this->registerChildProcessor(src.childProcessor(child1_index).clone());",
|
||||||
"this->registerChildProcessor(src.childProcessor(child2_index).clone());"
|
"this->registerChildProcessor(src.childProcessor(child2_index).clone());"
|
||||||
});
|
});
|
||||||
@ -536,9 +538,9 @@ DEF_TEST(SkSLFPChildProcessorWithInputExpression, r) {
|
|||||||
"this->registerChildProcessor(std::move(child));",
|
"this->registerChildProcessor(std::move(child));",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"SkString _input0 = SkStringPrintf(\"%s * half4(0.5)\", args.fInputColor);",
|
"SkString _input64 = SkStringPrintf(\"%s * half4(0.5)\", args.fInputColor);",
|
||||||
"SkString _sample64(\"_sample64\");",
|
"SkString _sample64(\"_sample64\");",
|
||||||
"this->invokeChild(_outer.child_index, _input0.c_str(), &_sample64, args);",
|
"this->invokeChild(_outer.child_index, _input64.c_str(), &_sample64, args);",
|
||||||
"fragBuilder->codeAppendf(\"%s = %s;\\n\", args.fOutputColor, _sample64.c_str());",
|
"fragBuilder->codeAppendf(\"%s = %s;\\n\", args.fOutputColor, _sample64.c_str());",
|
||||||
"this->registerChildProcessor(src.childProcessor(child_index).clone());",
|
"this->registerChildProcessor(src.childProcessor(child_index).clone());",
|
||||||
});
|
});
|
||||||
@ -557,12 +559,12 @@ DEF_TEST(SkSLFPNestedChildProcessors, r) {
|
|||||||
"this->registerChildProcessor(std::move(child2));"
|
"this->registerChildProcessor(std::move(child2));"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"SkString _input0 = SkStringPrintf(\"%s * half4(0.5)\", args.fInputColor);",
|
"SkString _input121 = SkStringPrintf(\"%s * half4(0.5)\", args.fInputColor);",
|
||||||
"SkString _sample121(\"_sample121\");",
|
"SkString _sample121(\"_sample121\");",
|
||||||
"this->invokeChild(_outer.child1_index, _input0.c_str(), &_sample121, args);",
|
"this->invokeChild(_outer.child1_index, _input121.c_str(), &_sample121, args);",
|
||||||
"SkString _input1 = SkStringPrintf(\"%s * %s\", args.fInputColor, _sample121.c_str());",
|
"SkString _input93 = SkStringPrintf(\"%s * %s\", args.fInputColor, _sample121.c_str());",
|
||||||
"SkString _sample93(\"_sample93\");",
|
"SkString _sample93(\"_sample93\");",
|
||||||
"this->invokeChild(_outer.child2_index, _input1.c_str(), &_sample93, args);",
|
"this->invokeChild(_outer.child2_index, _input93.c_str(), &_sample93, args);",
|
||||||
"fragBuilder->codeAppendf(\"%s = %s;\\n\", args.fOutputColor, _sample93.c_str());",
|
"fragBuilder->codeAppendf(\"%s = %s;\\n\", args.fOutputColor, _sample93.c_str());",
|
||||||
"this->registerChildProcessor(src.childProcessor(child1_index).clone());",
|
"this->registerChildProcessor(src.childProcessor(child1_index).clone());",
|
||||||
"this->registerChildProcessor(src.childProcessor(child2_index).clone());"
|
"this->registerChildProcessor(src.childProcessor(child2_index).clone());"
|
||||||
@ -588,12 +590,11 @@ DEF_TEST(SkSLFPChildFPAndGlobal, r) {
|
|||||||
"hasCap = sk_Caps.externalTextureSupport;",
|
"hasCap = sk_Caps.externalTextureSupport;",
|
||||||
"fragBuilder->codeAppendf(\"bool hasCap = %s;\\nif (hasCap) {\", (hasCap ? \"true\" : "
|
"fragBuilder->codeAppendf(\"bool hasCap = %s;\\nif (hasCap) {\", (hasCap ? \"true\" : "
|
||||||
"\"false\"));",
|
"\"false\"));",
|
||||||
"SkString _input0 = SkStringPrintf(\"%s\", args.fInputColor);",
|
"SkString _input130 = SkStringPrintf(\"%s\", args.fInputColor);",
|
||||||
"SkString _sample130(\"_sample130\");",
|
"SkString _sample130(\"_sample130\");",
|
||||||
"this->invokeChild(_outer.child_index, _input0.c_str(), &_sample130, args);",
|
"this->invokeChild(_outer.child_index, _input130.c_str(), &_sample130, args);",
|
||||||
"fragBuilder->codeAppendf(\"\\n %s = %s;\\n} else {\\n %s = half4(1.0);\\n}\\n\","
|
"fragBuilder->codeAppendf(\"\\n %s = %s;\\n} else {\\n %s = half4(1.0);\\n}\\n\","
|
||||||
" args.fOutputColor, _sample130.c_str(), args.fOutputColor);",
|
" args.fOutputColor, _sample130.c_str(), args.fOutputColor);",
|
||||||
|
|
||||||
"this->registerChildProcessor(src.childProcessor(child_index).clone());"
|
"this->registerChildProcessor(src.childProcessor(child_index).clone());"
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -615,9 +616,9 @@ DEF_TEST(SkSLFPChildProcessorInlineFieldAccess, r) {
|
|||||||
{
|
{
|
||||||
"fragBuilder->codeAppendf(\"if (%s) {\", "
|
"fragBuilder->codeAppendf(\"if (%s) {\", "
|
||||||
"(_outer.childProcessor(_outer.child_index).preservesOpaqueInput() ? ",
|
"(_outer.childProcessor(_outer.child_index).preservesOpaqueInput() ? ",
|
||||||
"SkString _input0 = SkStringPrintf(\"%s\", args.fInputColor);",
|
"SkString _input105 = SkStringPrintf(\"%s\", args.fInputColor);",
|
||||||
"SkString _sample105(\"_sample105\");",
|
"SkString _sample105(\"_sample105\");",
|
||||||
"this->invokeChild(_outer.child_index, _input0.c_str(), &_sample105, args);",
|
"this->invokeChild(_outer.child_index, _input105.c_str(), &_sample105, args);",
|
||||||
"fragBuilder->codeAppendf(\"\\n %s = %s;\\n} else {\\n %s = half4(1.0);\\n}\\n\","
|
"fragBuilder->codeAppendf(\"\\n %s = %s;\\n} else {\\n %s = half4(1.0);\\n}\\n\","
|
||||||
" args.fOutputColor, _sample105.c_str(), args.fOutputColor);",
|
" args.fOutputColor, _sample105.c_str(), args.fOutputColor);",
|
||||||
"this->registerChildProcessor(src.childProcessor(child_index).clone());"
|
"this->registerChildProcessor(src.childProcessor(child_index).clone());"
|
||||||
@ -685,3 +686,27 @@ DEF_TEST(SkSLFPBadIn, r) {
|
|||||||
"error: 1: 'in' variable must be either 'uniform' or 'layout(key)', or there must be a "
|
"error: 1: 'in' variable must be either 'uniform' or 'layout(key)', or there must be a "
|
||||||
"custom @setData function\n1 error\n");
|
"custom @setData function\n1 error\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DEF_TEST(SkSLFPSampleCoords, r) {
|
||||||
|
test(r,
|
||||||
|
"in fragmentProcessor child;"
|
||||||
|
"@coordTransform { SkMatrix() }"
|
||||||
|
"void main() {"
|
||||||
|
" sk_OutColor = sample(child) + sample(child, sk_TransformedCoords2D[0] / 2);"
|
||||||
|
"}",
|
||||||
|
*SkSL::ShaderCapsFactory::Default(),
|
||||||
|
{},
|
||||||
|
{
|
||||||
|
"SkString _sample94(\"_sample94\");\n",
|
||||||
|
"this->invokeChild(_outer.child_index, &_sample94, args);\n",
|
||||||
|
"SkString _sample110(\"_sample110\");\n",
|
||||||
|
"SkString sk_TransformedCoords2D_0 = fragBuilder->ensureCoords2D("
|
||||||
|
"args.fTransformedCoords[0].fVaryingPoint);\n",
|
||||||
|
"SkString _coords110 = SkStringPrintf(\"%s / 2.0\", "
|
||||||
|
"_outer.computeLocalCoordsInVertexShader() ? sk_TransformedCoords2D_0.c_str() :"
|
||||||
|
" \"_coords\");\n",
|
||||||
|
"this->invokeChild(_outer.child_index, &_sample110, args, _coords110.c_str());\n",
|
||||||
|
"fragBuilder->codeAppendf(\"%s = %s + %s;\\n\", args.fOutputColor, _sample94.c_str(), "
|
||||||
|
"_sample110.c_str());\n"
|
||||||
|
});
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user