aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/gpu/glsl
diff options
context:
space:
mode:
authorGravatar egdaniel <egdaniel@google.com>2015-11-13 09:55:43 -0800
committerGravatar Commit bot <commit-bot@chromium.org>2015-11-13 09:55:43 -0800
commite659a581f63fdccb64dce2dc8a478cf56831feea (patch)
treeefef38bff117135e343b7b2b192af10b1f2262e3 /src/gpu/glsl
parent60795d99fff8caedc2e82bebcfa8bd4fa07231b7 (diff)
Move GrGLPrimitive/GeometryProc to GLSL
Diffstat (limited to 'src/gpu/glsl')
-rw-r--r--src/gpu/glsl/GrGLSLGeometryProcessor.cpp157
-rw-r--r--src/gpu/glsl/GrGLSLGeometryProcessor.h110
-rw-r--r--src/gpu/glsl/GrGLSLPrimitiveProcessor.cpp47
-rw-r--r--src/gpu/glsl/GrGLSLPrimitiveProcessor.h92
4 files changed, 406 insertions, 0 deletions
diff --git a/src/gpu/glsl/GrGLSLGeometryProcessor.cpp b/src/gpu/glsl/GrGLSLGeometryProcessor.cpp
new file mode 100644
index 0000000000..c9f8c71383
--- /dev/null
+++ b/src/gpu/glsl/GrGLSLGeometryProcessor.cpp
@@ -0,0 +1,157 @@
+/*
+ * Copyright 2014 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "GrGLSLGeometryProcessor.h"
+
+#include "glsl/GrGLSLFragmentShaderBuilder.h"
+#include "glsl/GrGLSLProcessorTypes.h"
+#include "glsl/GrGLSLProgramBuilder.h"
+#include "glsl/GrGLSLVertexShaderBuilder.h"
+
+void GrGLSLGeometryProcessor::emitCode(EmitArgs& args) {
+ GrGLSLVertexBuilder* vsBuilder = args.fPB->getVertexShaderBuilder();
+ GrGPArgs gpArgs;
+ this->onEmitCode(args, &gpArgs);
+ vsBuilder->transformToNormalizedDeviceSpace(gpArgs.fPositionVar);
+}
+
+void GrGLSLGeometryProcessor::emitTransforms(GrGLSLGPBuilder* pb,
+ const GrShaderVar& posVar,
+ const char* localCoords,
+ const SkMatrix& localMatrix,
+ const TransformsIn& tin,
+ TransformsOut* tout) {
+ GrGLSLVertexBuilder* vb = pb->getVertexShaderBuilder();
+ tout->push_back_n(tin.count());
+ fInstalledTransforms.push_back_n(tin.count());
+ for (int i = 0; i < tin.count(); i++) {
+ const ProcCoords& coordTransforms = tin[i];
+ fInstalledTransforms[i].push_back_n(coordTransforms.count());
+ for (int t = 0; t < coordTransforms.count(); t++) {
+ SkString strUniName("StageMatrix");
+ strUniName.appendf("_%i_%i", i, t);
+ GrSLType varyingType;
+
+ GrCoordSet coordType = coordTransforms[t]->sourceCoords();
+ uint32_t type = coordTransforms[t]->getMatrix().getType();
+ if (kLocal_GrCoordSet == coordType) {
+ type |= localMatrix.getType();
+ }
+ varyingType = SkToBool(SkMatrix::kPerspective_Mask & type) ? kVec3f_GrSLType :
+ kVec2f_GrSLType;
+ GrSLPrecision precision = coordTransforms[t]->precision();
+
+ const char* uniName;
+ fInstalledTransforms[i][t].fHandle =
+ pb->addUniform(GrGLSLProgramBuilder::kVertex_Visibility,
+ kMat33f_GrSLType, precision,
+ strUniName.c_str(),
+ &uniName).toIndex();
+
+ SkString strVaryingName("MatrixCoord");
+ strVaryingName.appendf("_%i_%i", i, t);
+
+ GrGLSLVertToFrag v(varyingType);
+ pb->addVarying(strVaryingName.c_str(), &v, precision);
+
+ SkASSERT(kVec2f_GrSLType == varyingType || kVec3f_GrSLType == varyingType);
+ SkNEW_APPEND_TO_TARRAY(&(*tout)[i], GrGLSLTransformedCoords,
+ (SkString(v.fsIn()), varyingType));
+
+ // varying = matrix * coords (logically)
+ if (kDevice_GrCoordSet == coordType) {
+ if (kVec2f_GrSLType == varyingType) {
+ if (kVec2f_GrSLType == posVar.getType()) {
+ vb->codeAppendf("%s = (%s * vec3(%s, 1)).xy;",
+ v.vsOut(), uniName, posVar.c_str());
+ } else {
+ // The brackets here are just to scope the temp variable
+ vb->codeAppendf("{ vec3 temp = %s * %s;", uniName, posVar.c_str());
+ vb->codeAppendf("%s = vec2(temp.x/temp.z, temp.y/temp.z); }", v.vsOut());
+ }
+ } else {
+ if (kVec2f_GrSLType == posVar.getType()) {
+ vb->codeAppendf("%s = %s * vec3(%s, 1);",
+ v.vsOut(), uniName, posVar.c_str());
+ } else {
+ vb->codeAppendf("%s = %s * %s;", v.vsOut(), uniName, posVar.c_str());
+ }
+ }
+ } else {
+ if (kVec2f_GrSLType == varyingType) {
+ vb->codeAppendf("%s = (%s * vec3(%s, 1)).xy;", v.vsOut(), uniName, localCoords);
+ } else {
+ vb->codeAppendf("%s = %s * vec3(%s, 1);", v.vsOut(), uniName, localCoords);
+ }
+ }
+ }
+ }
+}
+
+void GrGLSLGeometryProcessor::emitTransforms(GrGLSLGPBuilder* pb,
+ const char* localCoords,
+ const TransformsIn& tin,
+ TransformsOut* tout) {
+ GrGLSLVertexBuilder* vb = pb->getVertexShaderBuilder();
+ tout->push_back_n(tin.count());
+ for (int i = 0; i < tin.count(); i++) {
+ const ProcCoords& coordTransforms = tin[i];
+ for (int t = 0; t < coordTransforms.count(); t++) {
+ GrSLType varyingType = kVec2f_GrSLType;
+
+ // Device coords aren't supported
+ SkASSERT(kDevice_GrCoordSet != coordTransforms[t]->sourceCoords());
+ GrSLPrecision precision = coordTransforms[t]->precision();
+
+ SkString strVaryingName("MatrixCoord");
+ strVaryingName.appendf("_%i_%i", i, t);
+
+ GrGLSLVertToFrag v(varyingType);
+ pb->addVarying(strVaryingName.c_str(), &v, precision);
+ vb->codeAppendf("%s = %s;", v.vsOut(), localCoords);
+
+ SkNEW_APPEND_TO_TARRAY(&(*tout)[i],
+ GrGLSLTransformedCoords,
+ (SkString(v.fsIn()), varyingType));
+ }
+ }
+}
+
+void GrGLSLGeometryProcessor::setupPosition(GrGLSLGPBuilder* pb,
+ GrGPArgs* gpArgs,
+ const char* posName) {
+ GrGLSLVertexBuilder* vsBuilder = pb->getVertexShaderBuilder();
+ gpArgs->fPositionVar.set(kVec2f_GrSLType, "pos2");
+ vsBuilder->codeAppendf("vec2 %s = %s;", gpArgs->fPositionVar.c_str(), posName);
+}
+
+void GrGLSLGeometryProcessor::setupPosition(GrGLSLGPBuilder* pb,
+ GrGPArgs* gpArgs,
+ const char* posName,
+ const SkMatrix& mat,
+ UniformHandle* viewMatrixUniform) {
+ GrGLSLVertexBuilder* vsBuilder = pb->getVertexShaderBuilder();
+ if (mat.isIdentity()) {
+ gpArgs->fPositionVar.set(kVec2f_GrSLType, "pos2");
+ vsBuilder->codeAppendf("vec2 %s = %s;", gpArgs->fPositionVar.c_str(), posName);
+ } else {
+ const char* viewMatrixName;
+ *viewMatrixUniform = pb->addUniform(GrGLSLProgramBuilder::kVertex_Visibility,
+ kMat33f_GrSLType, kHigh_GrSLPrecision,
+ "uViewM",
+ &viewMatrixName);
+ if (!mat.hasPerspective()) {
+ gpArgs->fPositionVar.set(kVec2f_GrSLType, "pos2");
+ vsBuilder->codeAppendf("vec2 %s = vec2(%s * vec3(%s, 1));",
+ gpArgs->fPositionVar.c_str(), viewMatrixName, posName);
+ } else {
+ gpArgs->fPositionVar.set(kVec3f_GrSLType, "pos3");
+ vsBuilder->codeAppendf("vec3 %s = %s * vec3(%s, 1);",
+ gpArgs->fPositionVar.c_str(), viewMatrixName, posName);
+ }
+ }
+}
diff --git a/src/gpu/glsl/GrGLSLGeometryProcessor.h b/src/gpu/glsl/GrGLSLGeometryProcessor.h
new file mode 100644
index 0000000000..1064eb02c2
--- /dev/null
+++ b/src/gpu/glsl/GrGLSLGeometryProcessor.h
@@ -0,0 +1,110 @@
+/*
+ * Copyright 2013 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef GrGLSLGeometryProcessor_DEFINED
+#define GrGLSLGeometryProcessor_DEFINED
+
+#include "GrGLSLPrimitiveProcessor.h"
+
+class GrGLSLGPBuilder;
+
+/**
+ * If a GL effect needs a GrGLFullShaderBuilder* object to emit vertex code, then it must inherit
+ * from this class. Since paths don't have vertices, this class is only meant to be used internally
+ * by skia, for special cases.
+ */
+class GrGLSLGeometryProcessor : public GrGLSLPrimitiveProcessor {
+public:
+ /* Any general emit code goes in the base class emitCode. Subclasses override onEmitCode */
+ void emitCode(EmitArgs&) override;
+
+ // By default we use the identity matrix
+ void setTransformData(const GrPrimitiveProcessor&,
+ const GrGLSLProgramDataManager& pdman,
+ int index,
+ const SkTArray<const GrCoordTransform*, true>& transforms) override {
+ this->setTransformDataMatrix(SkMatrix::I(), pdman, index, transforms);
+ }
+
+ // A helper which subclasses can use if needed
+ template <class GeometryProcessor>
+ void setTransformDataHelper(const GrPrimitiveProcessor& primProc,
+ const GrGLSLProgramDataManager& pdman,
+ int index,
+ const SkTArray<const GrCoordTransform*, true>& transforms) {
+ const GeometryProcessor& gp = primProc.cast<GeometryProcessor>();
+ this->setTransformDataMatrix(gp.localMatrix(), pdman, index, transforms);
+ }
+
+protected:
+ // Emit a uniform matrix for each coord transform.
+ void emitTransforms(GrGLSLGPBuilder* gp,
+ const GrShaderVar& posVar,
+ const char* localCoords,
+ const TransformsIn& tin,
+ TransformsOut* tout) {
+ this->emitTransforms(gp, posVar, localCoords, SkMatrix::I(), tin, tout);
+ }
+
+ // Emit pre-transformed coords as a vertex attribute per coord-transform.
+ void emitTransforms(GrGLSLGPBuilder*,
+ const GrShaderVar& posVar,
+ const char* localCoords,
+ const SkMatrix& localMatrix,
+ const TransformsIn&,
+ TransformsOut*);
+
+ // caller has emitted transforms via attributes
+ void emitTransforms(GrGLSLGPBuilder*,
+ const char* localCoords,
+ const TransformsIn& tin,
+ TransformsOut* tout);
+
+ struct GrGPArgs {
+ // The variable used by a GP to store its position. It can be
+ // either a vec2 or a vec3 depending on the presence of perspective.
+ GrShaderVar fPositionVar;
+ };
+
+ // Create the correct type of position variable given the CTM
+ void setupPosition(GrGLSLGPBuilder*, GrGPArgs*, const char* posName);
+ void setupPosition(GrGLSLGPBuilder*, GrGPArgs*, const char* posName, const SkMatrix& mat,
+ UniformHandle* viewMatrixUniform);
+
+ static uint32_t ComputePosKey(const SkMatrix& mat) {
+ if (mat.isIdentity()) {
+ return 0x0;
+ } else if (!mat.hasPerspective()) {
+ return 0x01;
+ } else {
+ return 0x02;
+ }
+ }
+
+private:
+ void setTransformDataMatrix(const SkMatrix& localMatrix,
+ const GrGLSLProgramDataManager& pdman,
+ int index,
+ const SkTArray<const GrCoordTransform*, true>& transforms) {
+ SkSTArray<2, Transform, true>& procTransforms = fInstalledTransforms[index];
+ int numTransforms = transforms.count();
+ for (int t = 0; t < numTransforms; ++t) {
+ SkASSERT(procTransforms[t].fHandle.isValid());
+ const SkMatrix& transform = GetTransformMatrix(localMatrix, *transforms[t]);
+ if (!procTransforms[t].fCurrentValue.cheapEqualTo(transform)) {
+ pdman.setSkMatrix(procTransforms[t].fHandle.toIndex(), transform);
+ procTransforms[t].fCurrentValue = transform;
+ }
+ }
+ }
+
+ virtual void onEmitCode(EmitArgs&, GrGPArgs*) = 0;
+
+ typedef GrGLSLPrimitiveProcessor INHERITED;
+};
+
+#endif
diff --git a/src/gpu/glsl/GrGLSLPrimitiveProcessor.cpp b/src/gpu/glsl/GrGLSLPrimitiveProcessor.cpp
new file mode 100644
index 0000000000..abb3abcb0d
--- /dev/null
+++ b/src/gpu/glsl/GrGLSLPrimitiveProcessor.cpp
@@ -0,0 +1,47 @@
+/*
+ * Copyright 2014 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "GrGLSLPrimitiveProcessor.h"
+
+#include "glsl/GrGLSLProgramBuilder.h"
+#include "glsl/GrGLSLFragmentShaderBuilder.h"
+
+SkMatrix GrGLSLPrimitiveProcessor::GetTransformMatrix(const SkMatrix& localMatrix,
+ const GrCoordTransform& coordTransform) {
+ SkMatrix combined;
+ // We only apply the localmatrix to localcoords
+ if (kLocal_GrCoordSet == coordTransform.sourceCoords()) {
+ combined.setConcat(coordTransform.getMatrix(), localMatrix);
+ } else {
+ combined = coordTransform.getMatrix();
+ }
+ if (coordTransform.reverseY()) {
+ // combined.postScale(1,-1);
+ // combined.postTranslate(0,1);
+ combined.set(SkMatrix::kMSkewY,
+ combined[SkMatrix::kMPersp0] - combined[SkMatrix::kMSkewY]);
+ combined.set(SkMatrix::kMScaleY,
+ combined[SkMatrix::kMPersp1] - combined[SkMatrix::kMScaleY]);
+ combined.set(SkMatrix::kMTransY,
+ combined[SkMatrix::kMPersp2] - combined[SkMatrix::kMTransY]);
+ }
+ return combined;
+}
+
+void GrGLSLPrimitiveProcessor::setupUniformColor(GrGLSLGPBuilder* pb,
+ const char* outputName,
+ UniformHandle* colorUniform) {
+ GrGLSLFragmentBuilder* fs = pb->getFragmentShaderBuilder();
+ SkASSERT(colorUniform);
+ const char* stagedLocalVarName;
+ *colorUniform = pb->addUniform(GrGLSLProgramBuilder::kFragment_Visibility,
+ kVec4f_GrSLType,
+ kDefault_GrSLPrecision,
+ "Color",
+ &stagedLocalVarName);
+ fs->codeAppendf("%s = %s;", outputName, stagedLocalVarName);
+}
diff --git a/src/gpu/glsl/GrGLSLPrimitiveProcessor.h b/src/gpu/glsl/GrGLSLPrimitiveProcessor.h
new file mode 100644
index 0000000000..537aaed8f2
--- /dev/null
+++ b/src/gpu/glsl/GrGLSLPrimitiveProcessor.h
@@ -0,0 +1,92 @@
+/*
+ * Copyright 2013 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef GrGLSLPrimitiveProcessor_DEFINED
+#define GrGLSLPrimitiveProcessor_DEFINED
+
+#include "GrPrimitiveProcessor.h"
+#include "glsl/GrGLSLProcessorTypes.h"
+#include "glsl/GrGLSLProgramDataManager.h"
+#include "glsl/GrGLSLTextureSampler.h"
+
+class GrBatchTracker;
+class GrPrimitiveProcessor;
+class GrGLSLGPBuilder;
+
+class GrGLSLPrimitiveProcessor {
+public:
+ virtual ~GrGLSLPrimitiveProcessor() {}
+
+ typedef GrGLSLProgramDataManager::UniformHandle UniformHandle;
+ typedef GrGLSLTextureSampler::TextureSamplerArray TextureSamplerArray;
+
+ typedef SkSTArray<2, const GrCoordTransform*, true> ProcCoords;
+ typedef SkSTArray<8, ProcCoords> TransformsIn;
+ typedef SkSTArray<8, GrGLSLTransformedCoordsArray> TransformsOut;
+
+ struct EmitArgs {
+ EmitArgs(GrGLSLGPBuilder* pb,
+ const GrPrimitiveProcessor& gp,
+ const char* outputColor,
+ const char* outputCoverage,
+ const TextureSamplerArray& samplers,
+ const TransformsIn& transformsIn,
+ TransformsOut* transformsOut)
+ : fPB(pb)
+ , fGP(gp)
+ , fOutputColor(outputColor)
+ , fOutputCoverage(outputCoverage)
+ , fSamplers(samplers)
+ , fTransformsIn(transformsIn)
+ , fTransformsOut(transformsOut) {}
+ GrGLSLGPBuilder* fPB;
+ const GrPrimitiveProcessor& fGP;
+ const char* fOutputColor;
+ const char* fOutputCoverage;
+ const TextureSamplerArray& fSamplers;
+ const TransformsIn& fTransformsIn;
+ TransformsOut* fTransformsOut;
+ };
+
+ /**
+ * This is similar to emitCode() in the base class, except it takes a full shader builder.
+ * This allows the effect subclass to emit vertex code.
+ */
+ virtual void emitCode(EmitArgs&) = 0;
+
+
+ /** A GrGLSLPrimitiveProcessor instance can be reused with any GrGLSLPrimitiveProcessor that
+ produces the same stage key; this function reads data from a GrGLSLPrimitiveProcessor and
+ uploads any uniform variables required by the shaders created in emitCode(). The
+ GrPrimitiveProcessor parameter is guaranteed to be of the same type that created this
+ GrGLSLPrimitiveProcessor and to have an identical processor key as the one that created this
+ GrGLSLPrimitiveProcessor. */
+ virtual void setData(const GrGLSLProgramDataManager&, const GrPrimitiveProcessor&) = 0;
+
+ static SkMatrix GetTransformMatrix(const SkMatrix& localMatrix, const GrCoordTransform&);
+
+ virtual void setTransformData(const GrPrimitiveProcessor&,
+ const GrGLSLProgramDataManager& pdman,
+ int index,
+ const SkTArray<const GrCoordTransform*, true>& transforms) = 0;
+
+protected:
+ void setupUniformColor(GrGLSLGPBuilder* pb,
+ const char* outputName,
+ UniformHandle* colorUniform);
+
+ struct Transform {
+ Transform() : fType(kVoid_GrSLType) { fCurrentValue = SkMatrix::InvalidMatrix(); }
+ UniformHandle fHandle;
+ SkMatrix fCurrentValue;
+ GrSLType fType;
+ };
+
+ SkSTArray<8, SkSTArray<2, Transform, true> > fInstalledTransforms;
+};
+
+#endif