aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/gpu
diff options
context:
space:
mode:
Diffstat (limited to 'src/gpu')
-rw-r--r--src/gpu/GrGpu.h4
-rw-r--r--src/gpu/effects/GrVertexEffect.h2
-rw-r--r--src/gpu/gl/GrGLCaps.cpp3
-rw-r--r--src/gpu/gl/GrGLDefines.h7
-rw-r--r--src/gpu/gl/GrGLPathRendering.cpp30
-rw-r--r--src/gpu/gl/GrGLProgram.cpp26
-rw-r--r--src/gpu/gl/GrGLProgram.h5
-rw-r--r--src/gpu/gl/GrGLProgramDataManager.cpp30
-rw-r--r--src/gpu/gl/GrGLProgramDataManager.h55
-rw-r--r--src/gpu/gl/GrGLProgramDesc.cpp24
-rw-r--r--src/gpu/gl/GrGLProgramDesc.h4
-rw-r--r--src/gpu/gl/GrGLProgramEffects.cpp71
-rw-r--r--src/gpu/gl/GrGLProgramEffects.h17
-rw-r--r--src/gpu/gl/GrGpuGL.h7
-rw-r--r--src/gpu/gl/GrGpuGL_program.cpp6
-rw-r--r--src/gpu/gl/builders/GrGLProgramBuilder.cpp29
-rw-r--r--src/gpu/gl/builders/GrGLProgramBuilder.h26
17 files changed, 263 insertions, 83 deletions
diff --git a/src/gpu/GrGpu.h b/src/gpu/GrGpu.h
index 353ec33437..e495de9afa 100644
--- a/src/gpu/GrGpu.h
+++ b/src/gpu/GrGpu.h
@@ -336,6 +336,10 @@ public:
kDrawPaths_DrawType,
};
+ static bool IsPathRenderingDrawType(DrawType type) {
+ return kDrawPath_DrawType == type || kDrawPaths_DrawType == type;
+ }
+
protected:
DrawType PrimTypeToDrawType(GrPrimitiveType type) {
switch (type) {
diff --git a/src/gpu/effects/GrVertexEffect.h b/src/gpu/effects/GrVertexEffect.h
index 387ec7aee9..323c85e34e 100644
--- a/src/gpu/effects/GrVertexEffect.h
+++ b/src/gpu/effects/GrVertexEffect.h
@@ -17,7 +17,7 @@
*/
class GrVertexEffect : public GrEffect {
public:
- GrVertexEffect() { fHasVertexCode = true; }
+ GrVertexEffect() { fRequiresVertexShader = true; }
protected:
/**
diff --git a/src/gpu/gl/GrGLCaps.cpp b/src/gpu/gl/GrGLCaps.cpp
index f12871192c..f9030d84d7 100644
--- a/src/gpu/gl/GrGLCaps.cpp
+++ b/src/gpu/gl/GrGLCaps.cpp
@@ -342,8 +342,7 @@ bool GrGLCaps::init(const GrGLContextInfo& ctxInfo, const GrGLInterface* gli) {
ctxInfo.hasExtension("GL_ARB_program_interface_query")) &&
NULL != gli->fFunctions.fProgramPathFragmentInputGen));
} else {
- // Note: path rendering is not yet implemented for GLES.
- fPathRenderingSupport = ctxInfo.version() >= GR_GL_VER(3,1) && false;
+ fPathRenderingSupport = ctxInfo.version() >= GR_GL_VER(3,1);
}
}
diff --git a/src/gpu/gl/GrGLDefines.h b/src/gpu/gl/GrGLDefines.h
index 06dd99dae1..048ad54df6 100644
--- a/src/gpu/gl/GrGLDefines.h
+++ b/src/gpu/gl/GrGLDefines.h
@@ -900,8 +900,13 @@
// shader stage of <program> (if a fragment stage exists).
#define GR_GL_FRAGMENT_INPUT 0x936D
+// NV_path_rendering extension to EXT_direct_state_access:
+// [the matrix functions] must support the PATH_PROJECTION_NV and
+// PATH_MODELVIEW_NV tokens for matrixMode.
+#define GR_GL_PATH_PROJECTION 0x1701
+#define GR_GL_PATH_MODELVIEW 0x1700
+
/* ARM specific define for MSAA support on framebuffer fetch */
#define GR_GL_FETCH_PER_SAMPLE_ARM 0x8F65
-
#endif
diff --git a/src/gpu/gl/GrGLPathRendering.cpp b/src/gpu/gl/GrGLPathRendering.cpp
index 135eb16866..337e83e811 100644
--- a/src/gpu/gl/GrGLPathRendering.cpp
+++ b/src/gpu/gl/GrGLPathRendering.cpp
@@ -54,8 +54,12 @@ GrGLPathRendering::GrGLPathRendering(GrGpuGL* gpu)
NULL != glInterface->fFunctions.fStencilThenCoverFillPathInstanced &&
NULL != glInterface->fFunctions.fStencilThenCoverStrokePathInstanced;
fCaps.fragmentInputGenSupport =
+ kGLES_GrGLStandard == glInterface->fStandard &&
NULL != glInterface->fFunctions.fProgramPathFragmentInputGen;
- fHWPathTexGenSettings.reset(fGpu->glCaps().maxFixedFunctionTextureCoords());
+
+ if (!fCaps.fragmentInputGenSupport) {
+ fHWPathTexGenSettings.reset(fGpu->glCaps().maxFixedFunctionTextureCoords());
+ }
}
GrGLPathRendering::~GrGLPathRendering() {
@@ -68,14 +72,18 @@ void GrGLPathRendering::abandonGpuResources() {
void GrGLPathRendering::resetContext() {
fHWProjectionMatrixState.invalidate();
// we don't use the model view matrix.
- GL_CALL(MatrixLoadIdentity(GR_GL_MODELVIEW));
-
- for (int i = 0; i < fGpu->glCaps().maxFixedFunctionTextureCoords(); ++i) {
- GL_CALL(PathTexGen(GR_GL_TEXTURE0 + i, GR_GL_NONE, 0, NULL));
- fHWPathTexGenSettings[i].fMode = GR_GL_NONE;
- fHWPathTexGenSettings[i].fNumComponents = 0;
+ GrGLenum matrixMode =
+ fGpu->glStandard() == kGLES_GrGLStandard ? GR_GL_PATH_MODELVIEW : GR_GL_MODELVIEW;
+ GL_CALL(MatrixLoadIdentity(matrixMode));
+
+ if (!caps().fragmentInputGenSupport) {
+ for (int i = 0; i < fGpu->glCaps().maxFixedFunctionTextureCoords(); ++i) {
+ GL_CALL(PathTexGen(GR_GL_TEXTURE0 + i, GR_GL_NONE, 0, NULL));
+ fHWPathTexGenSettings[i].fMode = GR_GL_NONE;
+ fHWPathTexGenSettings[i].fNumComponents = 0;
+ }
+ fHWActivePathTexGenSets = 0;
}
- fHWActivePathTexGenSets = 0;
fHWPathStencilSettings.invalidate();
}
@@ -105,7 +113,6 @@ void GrGLPathRendering::drawPath(const GrPath* path, SkPath::FillType fill) {
GrGLuint id = static_cast<const GrGLPath*>(path)->pathID();
SkASSERT(NULL != fGpu->drawState()->getRenderTarget());
SkASSERT(NULL != fGpu->drawState()->getRenderTarget()->getStencilBuffer());
- SkASSERT(!fGpu->fCurrentProgram->hasVertexShader());
this->flushPathStencilSettings(fill);
SkASSERT(!fHWPathStencilSettings.isTwoSided());
@@ -162,7 +169,6 @@ void GrGLPathRendering::drawPaths(const GrPathRange* pathRange, const uint32_t i
SkASSERT(fGpu->caps()->pathRenderingSupport());
SkASSERT(NULL != fGpu->drawState()->getRenderTarget());
SkASSERT(NULL != fGpu->drawState()->getRenderTarget()->getStencilBuffer());
- SkASSERT(!fGpu->fCurrentProgram->hasVertexShader());
GrGLuint baseID = static_cast<const GrGLPathRange*>(pathRange)->basePathID();
@@ -347,7 +353,9 @@ void GrGLPathRendering::setProjectionMatrix(const SkMatrix& matrix,
GrGLfloat glMatrix[4 * 4];
fHWProjectionMatrixState.getRTAdjustedGLMatrix<4>(glMatrix);
- GL_CALL(MatrixLoadf(GR_GL_PROJECTION, glMatrix));
+ GrGLenum matrixMode =
+ fGpu->glStandard() == kGLES_GrGLStandard ? GR_GL_PATH_PROJECTION : GR_GL_PROJECTION;
+ GL_CALL(MatrixLoadf(matrixMode, glMatrix));
}
GrGLuint GrGLPathRendering::genPaths(GrGLsizei range) {
diff --git a/src/gpu/gl/GrGLProgram.cpp b/src/gpu/gl/GrGLProgram.cpp
index d49d000fe3..11efda9214 100644
--- a/src/gpu/gl/GrGLProgram.cpp
+++ b/src/gpu/gl/GrGLProgram.cpp
@@ -13,6 +13,7 @@
#include "GrDrawEffect.h"
#include "GrGLEffect.h"
#include "GrGpuGL.h"
+#include "GrGLPathRendering.h"
#include "GrGLShaderVar.h"
#include "GrGLSL.h"
#include "SkXfermode.h"
@@ -25,10 +26,12 @@ GrGLProgram* GrGLProgram::Create(GrGpuGL* gpu,
const GrEffectStage* colorStages[],
const GrEffectStage* coverageStages[]) {
SkAutoTDelete<GrGLProgramBuilder> builder;
- if (desc.getHeader().fHasVertexCode ||!gpu->shouldUseFixedFunctionTexturing()) {
- builder.reset(SkNEW_ARGS(GrGLFullProgramBuilder, (gpu, desc)));
- } else {
+ if (!desc.getHeader().fRequiresVertexShader &&
+ gpu->glCaps().pathRenderingSupport() &&
+ gpu->glPathRendering()->texturingMode() == GrGLPathRendering::FixedFunction_TexturingMode) {
builder.reset(SkNEW_ARGS(GrGLFragmentOnlyProgramBuilder, (gpu, desc)));
+ } else {
+ builder.reset(SkNEW_ARGS(GrGLFullProgramBuilder, (gpu, desc)));
}
if (builder->genProgram(colorStages, coverageStages)) {
SkASSERT(0 != builder->getProgramID());
@@ -100,7 +103,8 @@ void GrGLProgram::initSamplerUniforms() {
///////////////////////////////////////////////////////////////////////////////
-void GrGLProgram::setData(GrDrawState::BlendOptFlags blendOpts,
+void GrGLProgram::setData(GrGpu::DrawType drawType,
+ GrDrawState::BlendOptFlags blendOpts,
const GrEffectStage* colorStages[],
const GrEffectStage* coverageStages[],
const GrDeviceCoordTexture* dstCopy,
@@ -122,7 +126,7 @@ void GrGLProgram::setData(GrDrawState::BlendOptFlags blendOpts,
this->setColor(drawState, color, sharedState);
this->setCoverage(drawState, coverage, sharedState);
- this->setMatrixAndRenderTargetHeight(drawState);
+ this->setMatrixAndRenderTargetHeight(drawType, drawState);
if (NULL != dstCopy) {
if (fBuiltinUniformHandles.fDstCopyTopLeftUni.isValid()) {
@@ -145,9 +149,8 @@ void GrGLProgram::setData(GrDrawState::BlendOptFlags blendOpts,
SkASSERT(!fBuiltinUniformHandles.fDstCopySamplerUni.isValid());
}
- fColorEffects->setData(fGpu, fProgramDataManager, colorStages);
- fCoverageEffects->setData(fGpu, fProgramDataManager, coverageStages);
-
+ fColorEffects->setData(fGpu, drawType,fProgramDataManager, colorStages);
+ fCoverageEffects->setData(fGpu, drawType,fProgramDataManager, coverageStages);
// PathTexGen state applies to the the fixed function vertex shader. For
// custom shaders, it's ignored, so we don't need to change the texgen
@@ -231,7 +234,8 @@ void GrGLProgram::setCoverage(const GrDrawState& drawState,
}
}
-void GrGLProgram::setMatrixAndRenderTargetHeight(const GrDrawState& drawState) {
+void GrGLProgram::setMatrixAndRenderTargetHeight(GrGpu::DrawType drawType,
+ const GrDrawState& drawState) {
const GrRenderTarget* rt = drawState.getRenderTarget();
SkISize size;
size.set(rt->width(), rt->height());
@@ -243,9 +247,7 @@ void GrGLProgram::setMatrixAndRenderTargetHeight(const GrDrawState& drawState) {
SkIntToScalar(size.fHeight));
}
- if (!fHasVertexShader) {
- SkASSERT(!fBuiltinUniformHandles.fViewMatrixUni.isValid());
- SkASSERT(!fBuiltinUniformHandles.fRTAdjustmentUni.isValid());
+ if (GrGpu::IsPathRenderingDrawType(drawType)) {
fGpu->glPathRendering()->setProjectionMatrix(drawState.getViewMatrix(), size, rt->origin());
} else if (fMatrixState.fRenderTargetOrigin != rt->origin() ||
fMatrixState.fRenderTargetSize != size ||
diff --git a/src/gpu/gl/GrGLProgram.h b/src/gpu/gl/GrGLProgram.h
index 7af55f10ee..5b9deb9f91 100644
--- a/src/gpu/gl/GrGLProgram.h
+++ b/src/gpu/gl/GrGLProgram.h
@@ -156,7 +156,8 @@ public:
* GrGpuGL object to bind the textures required by the GrGLEffects. The color and coverage
* stages come from GrGLProgramDesc::Build().
*/
- void setData(GrDrawState::BlendOptFlags,
+ void setData(GrGpu::DrawType,
+ GrDrawState::BlendOptFlags,
const GrEffectStage* colorStages[],
const GrEffectStage* coverageStages[],
const GrDeviceCoordTexture* dstCopy, // can be NULL
@@ -181,7 +182,7 @@ private:
void setCoverage(const GrDrawState&, GrColor coverage, SharedGLState*);
// Helper for setData() that sets the view matrix and loads the render target height uniform
- void setMatrixAndRenderTargetHeight(const GrDrawState&);
+ void setMatrixAndRenderTargetHeight(GrGpu::DrawType drawType, const GrDrawState&);
// these reflect the current values of uniforms (GL uniform values travel with program)
MatrixState fMatrixState;
diff --git a/src/gpu/gl/GrGLProgramDataManager.cpp b/src/gpu/gl/GrGLProgramDataManager.cpp
index eed9d1935d..c53abd79ab 100644
--- a/src/gpu/gl/GrGLProgramDataManager.cpp
+++ b/src/gpu/gl/GrGLProgramDataManager.cpp
@@ -6,6 +6,7 @@
*/
#include "gl/builders/GrGLProgramBuilder.h"
+#include "gl/GrGLPathRendering.h"
#include "gl/GrGLProgram.h"
#include "gl/GrGLUniformHandle.h"
#include "gl/GrGpuGL.h"
@@ -16,9 +17,10 @@
(1 == arrayCount && GrGLShaderVar::kNonArray == uni.fArrayCount))
GrGLProgramDataManager::GrGLProgramDataManager(GrGpuGL* gpu,
- GrGLProgram*,
+ GrGLProgram* program,
const GrGLProgramBuilder& builder)
- : fGpu(gpu) {
+ : fGpu(gpu),
+ fProgram(program) {
int count = builder.getUniformInfos().count();
fUniforms.push_back_n(count);
for (int i = 0; i < count; i++) {
@@ -43,6 +45,19 @@ GrGLProgramDataManager::GrGLProgramDataManager(GrGpuGL* gpu,
uniform.fFSLocation = kUnusedUniform;
}
}
+
+ count = builder.getSeparableVaryingInfos().count();
+ fVaryings.push_back_n(count);
+ for (int i = 0; i < count; i++) {
+ Varying& varying = fVaryings[i];
+ const GrGLProgramBuilder::SeparableVaryingInfo& builderVarying =
+ builder.getSeparableVaryingInfos()[i];
+ SkASSERT(GrGLShaderVar::kNonArray == builderVarying.fVariable.getArrayCount());
+ SkDEBUGCODE(
+ varying.fType = builderVarying.fVariable.getType();
+ );
+ varying.fLocation = builderVarying.fLocation;
+ }
}
void GrGLProgramDataManager::setSampler(UniformHandle u, GrGLint texUnit) const {
@@ -261,3 +276,14 @@ void GrGLProgramDataManager::setSkMatrix(UniformHandle u, const SkMatrix& matrix
};
this->setMatrix3f(u, mt);
}
+
+void GrGLProgramDataManager::setProgramPathFragmentInputTransform(VaryingHandle i,
+ unsigned components,
+ const SkMatrix& matrix) const {
+ const Varying& fragmentInput = fVaryings[i.toProgramDataIndex()];
+ fGpu->glPathRendering()->setProgramPathFragmentInputTransform(fProgram->programID(),
+ fragmentInput.fLocation,
+ GR_GL_OBJECT_LINEAR,
+ components,
+ matrix);
+}
diff --git a/src/gpu/gl/GrGLProgramDataManager.h b/src/gpu/gl/GrGLProgramDataManager.h
index 3082f6f02b..8a98a75cae 100644
--- a/src/gpu/gl/GrGLProgramDataManager.h
+++ b/src/gpu/gl/GrGLProgramDataManager.h
@@ -26,34 +26,51 @@ class GrGLProgramBuilder;
class GrGLProgramDataManager : public SkRefCnt {
public:
// Opaque handle to a uniform
- class UniformHandle {
+ class ShaderResourceHandle {
public:
- /** Creates a reference to an unifrom of a GrGLShaderBuilder.
- * The ref can be used to set the uniform with corresponding the GrGLProgramDataManager.*/
- static UniformHandle CreateFromUniformIndex(int i);
-
bool isValid() const { return -1 != fValue; }
-
- bool operator==(const UniformHandle& other) const { return other.fValue == fValue; }
-
- UniformHandle()
+ ShaderResourceHandle()
: fValue(-1) {
}
-
- private:
- UniformHandle(int value)
+ protected:
+ ShaderResourceHandle(int value)
: fValue(value) {
SkASSERT(isValid());
}
+ int fValue;
+ };
+ class UniformHandle : public ShaderResourceHandle {
+ public:
+ /** Creates a reference to an unifrom of a GrGLShaderBuilder.
+ * The ref can be used to set the uniform with corresponding the GrGLProgramDataManager.*/
+ static UniformHandle CreateFromUniformIndex(int i);
+ UniformHandle() { }
+ bool operator==(const UniformHandle& other) const { return other.fValue == fValue; }
+ private:
+ UniformHandle(int value) : ShaderResourceHandle(value) { }
int toProgramDataIndex() const { SkASSERT(isValid()); return fValue; }
int toShaderBuilderIndex() const { return toProgramDataIndex(); }
- int fValue;
friend class GrGLProgramDataManager; // For accessing toProgramDataIndex().
friend class GrGLProgramBuilder; // For accessing toShaderBuilderIndex().
};
+ class VaryingHandle : public ShaderResourceHandle {
+ public:
+ /** Creates a reference to a varying in separable varyings of a GrGLShaderBuilder.
+ * The ref can be used to set the varying with the corresponding GrGLProgramDataManager.*/
+ static VaryingHandle CreateFromSeparableVaryingIndex(int i) {
+ return VaryingHandle(i);
+ }
+ VaryingHandle() { }
+ bool operator==(const VaryingHandle& other) const { return other.fValue == fValue; }
+ private:
+ VaryingHandle(int value) : ShaderResourceHandle(value) { }
+ int toProgramDataIndex() const { SkASSERT(isValid()); return fValue; }
+ friend class GrGLProgramDataManager; // For accessing toProgramDataIndex().
+ };
+
GrGLProgramDataManager(GrGpuGL*, GrGLProgram*, const GrGLProgramBuilder&);
/** Functions for uploading uniform values. The varities ending in v can be used to upload to an
@@ -78,6 +95,10 @@ public:
// convenience method for uploading a SkMatrix to a 3x3 matrix uniform
void setSkMatrix(UniformHandle, const SkMatrix&) const;
+ void setProgramPathFragmentInputTransform(VaryingHandle i,
+ unsigned components,
+ const SkMatrix& matrix) const;
+
private:
enum {
kUnusedUniform = -1,
@@ -91,9 +112,17 @@ private:
int fArrayCount;
);
};
+ struct Varying {
+ GrGLint fLocation;
+ SkDEBUGCODE(
+ GrSLType fType;
+ );
+ };
SkTArray<Uniform, true> fUniforms;
+ SkTArray<Varying, true> fVaryings;
GrGpuGL* fGpu;
+ GrGLProgram* fProgram;
typedef SkRefCnt INHERITED;
};
diff --git a/src/gpu/gl/GrGLProgramDesc.cpp b/src/gpu/gl/GrGLProgramDesc.cpp
index 7cdbcd0efc..286924e1ef 100644
--- a/src/gpu/gl/GrGLProgramDesc.cpp
+++ b/src/gpu/gl/GrGLProgramDesc.cpp
@@ -21,7 +21,7 @@ bool GrGLProgramDesc::GetEffectKeyAndUpdateStats(const GrEffectStage& stage,
uint16_t* effectKeySize,
bool* setTrueIfReadsDst,
bool* setTrueIfReadsPos,
- bool* setTrueIfHasVertexCode) {
+ bool* setTrueIfRequiresVertexShader) {
const GrBackendEffectFactory& factory = stage.getEffect()->getFactory();
GrDrawEffect drawEffect(stage, useExplicitLocalCoords);
if (stage.getEffect()->willReadDstColor()) {
@@ -30,8 +30,8 @@ bool GrGLProgramDesc::GetEffectKeyAndUpdateStats(const GrEffectStage& stage,
if (stage.getEffect()->willReadFragmentPosition()) {
*setTrueIfReadsPos = true;
}
- if (stage.getEffect()->hasVertexCode()) {
- *setTrueIfHasVertexCode = true;
+ if (stage.getEffect()->requiresVertexShader()) {
+ *setTrueIfRequiresVertexShader = true;
}
factory.getGLEffectKey(drawEffect, caps, b);
size_t size = b->size();
@@ -102,9 +102,10 @@ bool GrGLProgramDesc::Build(const GrDrawState& drawState,
bool readsDst = false;
bool readFragPosition = false;
- // We use vertexshader-less shader programs only when drawing paths.
- bool hasVertexCode = !(GrGpu::kDrawPath_DrawType == drawType ||
- GrGpu::kDrawPaths_DrawType == drawType);
+
+ // Provide option for shader programs without vertex shader only when drawing paths.
+ bool requiresVertexShader = !GrGpu::IsPathRenderingDrawType(drawType);
+
int numStages = 0;
if (!skipColor) {
numStages += drawState.numColorStages() - firstEffectiveColorStage;
@@ -118,7 +119,6 @@ bool GrGLProgramDesc::Build(const GrDrawState& drawState,
desc->fKey.push_back_n(kEffectKeyOffsetsAndLengthOffset + 2 * sizeof(uint16_t) * numStages);
int offsetAndSizeIndex = 0;
-
bool effectKeySuccess = true;
if (!skipColor) {
for (int s = firstEffectiveColorStage; s < drawState.numColorStages(); ++s) {
@@ -133,7 +133,7 @@ bool GrGLProgramDesc::Build(const GrDrawState& drawState,
drawState.getColorStage(s), gpu->glCaps(),
requiresLocalCoordAttrib, &b,
&effectKeySize, &readsDst,
- &readFragPosition, &hasVertexCode);
+ &readFragPosition, &requiresVertexShader);
effectKeySuccess |= (effectOffset <= SK_MaxU16);
offsetAndSize[0] = SkToU16(effectOffset);
@@ -154,7 +154,7 @@ bool GrGLProgramDesc::Build(const GrDrawState& drawState,
drawState.getCoverageStage(s), gpu->glCaps(),
requiresLocalCoordAttrib, &b,
&effectKeySize, &readsDst,
- &readFragPosition, &hasVertexCode);
+ &readFragPosition, &requiresVertexShader);
effectKeySuccess |= (effectOffset <= SK_MaxU16);
offsetAndSize[0] = SkToU16(effectOffset);
@@ -174,7 +174,7 @@ bool GrGLProgramDesc::Build(const GrDrawState& drawState,
// Because header is a pointer into the dynamic array, we can't push any new data into the key
// below here.
- header->fHasVertexCode = hasVertexCode || requiresLocalCoordAttrib;
+ header->fRequiresVertexShader = requiresVertexShader || requiresLocalCoordAttrib;
header->fEmitsPointSize = GrGpu::kDrawPoints_DrawType == drawType;
// Currently the experimental GS will only work with triangle prims (and it doesn't do anything
@@ -192,7 +192,7 @@ bool GrGLProgramDesc::Build(const GrDrawState& drawState,
header->fColorInput = kUniform_ColorInput;
} else {
header->fColorInput = kAttribute_ColorInput;
- header->fHasVertexCode = true;
+ header->fRequiresVertexShader = true;
}
bool covIsSolidWhite = !requiresCoverageAttrib && 0xffffffff == drawState.getCoverageColor();
@@ -203,7 +203,7 @@ bool GrGLProgramDesc::Build(const GrDrawState& drawState,
header->fCoverageInput = kUniform_ColorInput;
} else {
header->fCoverageInput = kAttribute_ColorInput;
- header->fHasVertexCode = true;
+ header->fRequiresVertexShader = true;
}
if (readsDst) {
diff --git a/src/gpu/gl/GrGLProgramDesc.h b/src/gpu/gl/GrGLProgramDesc.h
index e8925d0c5c..4796d5a4b3 100644
--- a/src/gpu/gl/GrGLProgramDesc.h
+++ b/src/gpu/gl/GrGLProgramDesc.h
@@ -147,7 +147,7 @@ private:
ColorInput fCoverageInput : 8;
CoverageOutput fCoverageOutput : 8;
- SkBool8 fHasVertexCode;
+ SkBool8 fRequiresVertexShader;
SkBool8 fEmitsPointSize;
// To enable experimental geometry shader code (not for use in
@@ -203,7 +203,7 @@ private:
uint16_t* effectKeySize,
bool* setTrueIfReadsDst,
bool* setTrueIfReadsPos,
- bool* setTrueIfHasVertexCode);
+ bool* setTrueIfRequiresVertexShader);
void finalize();
diff --git a/src/gpu/gl/GrGLProgramEffects.cpp b/src/gpu/gl/GrGLProgramEffects.cpp
index efb64fe640..8d97b42329 100644
--- a/src/gpu/gl/GrGLProgramEffects.cpp
+++ b/src/gpu/gl/GrGLProgramEffects.cpp
@@ -9,6 +9,8 @@
#include "GrGLProgramEffects.h"
#include "GrDrawEffect.h"
#include "gl/GrGLEffect.h"
+#include "gl/GrGLPathRendering.h"
+#include "gl/builders/GrGLProgramBuilder.h"
#include "gl/GrGLVertexEffect.h"
#include "gl/GrGpuGL.h"
@@ -294,6 +296,16 @@ void GrGLVertexProgramEffects::emitTransforms(GrGLFullProgramBuilder* builder,
uint32_t totalKey = GenTransformKey(drawEffect);
int numTransforms = drawEffect.effect()->numTransforms();
transforms.push_back_n(numTransforms);
+
+ SkTArray<PathTransform, true>* pathTransforms = NULL;
+ const GrGLCaps* glCaps = builder->ctxInfo().caps();
+ if (glCaps->pathRenderingSupport() &&
+ builder->gpu()->glPathRendering()->texturingMode() ==
+ GrGLPathRendering::SeparableShaders_TexturingMode) {
+ pathTransforms = &fPathTransforms.push_back();
+ pathTransforms->push_back_n(numTransforms);
+ }
+
for (int t = 0; t < numTransforms; t++) {
GrSLType varyingType = kVoid_GrSLType;
const char* uniName;
@@ -330,7 +342,13 @@ void GrGLVertexProgramEffects::emitTransforms(GrGLFullProgramBuilder* builder,
const char* vsVaryingName;
const char* fsVaryingName;
GrGLVertexShaderBuilder* vsBuilder = builder->getVertexShaderBuilder();
- builder->addVarying(varyingType, varyingName, &vsVaryingName, &fsVaryingName);
+ if (pathTransforms) {
+ (*pathTransforms)[t].fHandle =
+ builder->addSeparableVarying(varyingType, varyingName, &vsVaryingName, &fsVaryingName);
+ (*pathTransforms)[t].fType = varyingType;
+ } else {
+ builder->addVarying(varyingType, varyingName, &vsVaryingName, &fsVaryingName);
+ }
const GrGLShaderVar& coords = kPosition_GrCoordSet == get_source_coords(totalKey, t) ?
vsBuilder->positionAttribute() :
@@ -350,20 +368,27 @@ void GrGLVertexProgramEffects::emitTransforms(GrGLFullProgramBuilder* builder,
}
void GrGLVertexProgramEffects::setData(GrGpuGL* gpu,
- const GrGLProgramDataManager& programResourceManager,
+ GrGpu::DrawType drawType,
+ const GrGLProgramDataManager& programDataManager,
const GrEffectStage* effectStages[]) {
int numEffects = fGLEffects.count();
SkASSERT(numEffects == fTransforms.count());
SkASSERT(numEffects == fSamplers.count());
for (int e = 0; e < numEffects; ++e) {
GrDrawEffect drawEffect(*effectStages[e], fHasExplicitLocalCoords);
- fGLEffects[e]->setData(programResourceManager, drawEffect);
- this->setTransformData(programResourceManager, drawEffect, e);
+ fGLEffects[e]->setData(programDataManager, drawEffect);
+ if (GrGpu::IsPathRenderingDrawType(drawType)) {
+ this->setPathTransformData(gpu, programDataManager, drawEffect, e);
+ } else {
+ this->setTransformData(gpu, programDataManager, drawEffect, e);
+ }
+
this->bindTextures(gpu, drawEffect.effect(), e);
}
}
-void GrGLVertexProgramEffects::setTransformData(const GrGLProgramDataManager& programResourceManager,
+void GrGLVertexProgramEffects::setTransformData(GrGpuGL* gpu,
+ const GrGLProgramDataManager& pdman,
const GrDrawEffect& drawEffect,
int effectIdx) {
SkTArray<Transform, true>& transforms = fTransforms[effectIdx];
@@ -373,12 +398,39 @@ void GrGLVertexProgramEffects::setTransformData(const GrGLProgramDataManager& pr
SkASSERT(transforms[t].fHandle.isValid());
const SkMatrix& matrix = get_transform_matrix(drawEffect, t);
if (!transforms[t].fCurrentValue.cheapEqualTo(matrix)) {
- programResourceManager.setSkMatrix(transforms[t].fHandle, matrix);
+ pdman.setSkMatrix(transforms[t].fHandle, matrix);
transforms[t].fCurrentValue = matrix;
}
}
}
+void GrGLVertexProgramEffects::setPathTransformData(GrGpuGL* gpu,
+ const GrGLProgramDataManager& pdman,
+ const GrDrawEffect& drawEffect,
+ int effectIdx) {
+ SkTArray<PathTransform, true>& transforms = fPathTransforms[effectIdx];
+ int numTransforms = transforms.count();
+ SkASSERT(numTransforms == drawEffect.effect()->numTransforms());
+ for (int t = 0; t < numTransforms; ++t) {
+ SkASSERT(transforms[t].fHandle.isValid());
+ const SkMatrix& transform = get_transform_matrix(drawEffect, t);
+ if (transforms[t].fCurrentValue.cheapEqualTo(transform)) {
+ continue;
+ }
+ transforms[t].fCurrentValue = transform;
+ switch (transforms[t].fType) {
+ case kVec2f_GrSLType:
+ pdman.setProgramPathFragmentInputTransform(transforms[t].fHandle, 2, transform);
+ break;
+ case kVec3f_GrSLType:
+ pdman.setProgramPathFragmentInputTransform(transforms[t].fHandle, 3, transform);
+ break;
+ default:
+ SkFAIL("Unexpected matrix type.");
+ }
+ }
+}
+
GrGLVertexProgramEffectsBuilder::GrGLVertexProgramEffectsBuilder(GrGLFullProgramBuilder* builder,
int reserveCount)
: fBuilder(builder)
@@ -445,14 +497,15 @@ void GrGLPathTexGenProgramEffects::setupPathTexGen(GrGLFragmentOnlyProgramBuilde
}
void GrGLPathTexGenProgramEffects::setData(GrGpuGL* gpu,
- const GrGLProgramDataManager& programResourceManager,
- const GrEffectStage* effectStages[]) {
+ GrGpu::DrawType,
+ const GrGLProgramDataManager& pdman,
+ const GrEffectStage* effectStages[]) {
int numEffects = fGLEffects.count();
SkASSERT(numEffects == fTransforms.count());
SkASSERT(numEffects == fSamplers.count());
for (int e = 0; e < numEffects; ++e) {
GrDrawEffect drawEffect(*effectStages[e], false);
- fGLEffects[e]->setData(programResourceManager, drawEffect);
+ fGLEffects[e]->setData(pdman, drawEffect);
this->setPathTexGenState(gpu, drawEffect, e);
this->bindTextures(gpu, drawEffect.effect(), e);
}
diff --git a/src/gpu/gl/GrGLProgramEffects.h b/src/gpu/gl/GrGLProgramEffects.h
index e4d84a013b..0eaff53b76 100644
--- a/src/gpu/gl/GrGLProgramEffects.h
+++ b/src/gpu/gl/GrGLProgramEffects.h
@@ -10,6 +10,7 @@
#include "GrBackendEffectFactory.h"
#include "GrGLProgramDataManager.h"
+#include "GrGpu.h"
#include "GrTexture.h"
#include "GrTextureAccess.h"
@@ -28,6 +29,7 @@ class GrGLFragmentOnlyProgramBuilder;
class GrGLProgramEffects : public SkRefCnt {
public:
typedef GrGLProgramDataManager::UniformHandle UniformHandle;
+ typedef GrGLProgramDataManager::VaryingHandle VaryingHandle;
/**
* This class emits some of the code inserted into the shaders for an effect. The code it
@@ -51,6 +53,7 @@ public:
* Calls setData() on each effect, and sets their transformation matrices and texture bindings.
*/
virtual void setData(GrGpuGL*,
+ GrGpu::DrawType,
const GrGLProgramDataManager&,
const GrEffectStage* effectStages[]) = 0;
@@ -165,6 +168,7 @@ public:
class GrGLVertexProgramEffects : public GrGLProgramEffects {
public:
virtual void setData(GrGpuGL*,
+ GrGpu::DrawType,
const GrGLProgramDataManager&,
const GrEffectStage* effectStages[]) SK_OVERRIDE;
@@ -205,7 +209,9 @@ private:
/**
* Helper for setData(). Sets all the transform matrices for an effect.
*/
- void setTransformData(const GrGLProgramDataManager&, const GrDrawEffect&, int effectIdx);
+ void setTransformData(GrGpuGL* gpu, const GrGLProgramDataManager&, const GrDrawEffect&, int effectIdx);
+ void setPathTransformData(GrGpuGL* gpu, const GrGLProgramDataManager&, const GrDrawEffect&,
+ int effectIdx);
struct Transform {
Transform() { fCurrentValue = SkMatrix::InvalidMatrix(); }
@@ -213,7 +219,15 @@ private:
SkMatrix fCurrentValue;
};
+ struct PathTransform {
+ PathTransform() { fCurrentValue = SkMatrix::InvalidMatrix(); }
+ VaryingHandle fHandle;
+ SkMatrix fCurrentValue;
+ GrSLType fType;
+ };
+
SkTArray<SkSTArray<2, Transform, true> > fTransforms;
+ SkTArray<SkTArray<PathTransform, true> > fPathTransforms;
bool fHasExplicitLocalCoords;
friend class GrGLVertexProgramEffectsBuilder;
@@ -253,6 +267,7 @@ private:
class GrGLPathTexGenProgramEffects : public GrGLProgramEffects {
public:
virtual void setData(GrGpuGL*,
+ GrGpu::DrawType,
const GrGLProgramDataManager&,
const GrEffectStage* effectStages[]) SK_OVERRIDE;
diff --git a/src/gpu/gl/GrGpuGL.h b/src/gpu/gl/GrGpuGL.h
index 110a6671ba..94fd307f6d 100644
--- a/src/gpu/gl/GrGpuGL.h
+++ b/src/gpu/gl/GrGpuGL.h
@@ -52,13 +52,6 @@ public:
// state.
void bindTexture(int unitIdx, const GrTextureParams& params, GrGLTexture* texture);
- bool shouldUseFixedFunctionTexturing() const {
- // At the moment non-fixed-function texturing is not implemented
- // even though the GrGLPathRendering would support it. Thus just
- // return the below.
- return this->glCaps().pathRenderingSupport();
- }
-
bool programUnitTest(int maxStages);
// GrGpu overrides
diff --git a/src/gpu/gl/GrGpuGL_program.cpp b/src/gpu/gl/GrGpuGL_program.cpp
index dac7443d17..b19676adb9 100644
--- a/src/gpu/gl/GrGpuGL_program.cpp
+++ b/src/gpu/gl/GrGpuGL_program.cpp
@@ -247,9 +247,6 @@ bool GrGpuGL::flushGraphicsState(DrawType type, const GrDeviceCoordTexture* dstC
return false;
}
- SkASSERT((kDrawPath_DrawType != type && kDrawPaths_DrawType != type)
- || !fCurrentProgram->hasVertexShader());
-
fCurrentProgram.get()->ref();
GrGLuint programID = fCurrentProgram->programID();
@@ -261,7 +258,8 @@ bool GrGpuGL::flushGraphicsState(DrawType type, const GrDeviceCoordTexture* dstC
fCurrentProgram->overrideBlend(&srcCoeff, &dstCoeff);
this->flushBlend(kDrawLines_DrawType == type, srcCoeff, dstCoeff);
- fCurrentProgram->setData(blendOpts,
+ fCurrentProgram->setData(type,
+ blendOpts,
colorStages.begin(),
coverageStages.begin(),
dstCopy,
diff --git a/src/gpu/gl/builders/GrGLProgramBuilder.cpp b/src/gpu/gl/builders/GrGLProgramBuilder.cpp
index f4ee32b48d..41b84d806a 100644
--- a/src/gpu/gl/builders/GrGLProgramBuilder.cpp
+++ b/src/gpu/gl/builders/GrGLProgramBuilder.cpp
@@ -99,10 +99,13 @@ bool GrGLProgramBuilder::genProgram(const GrEffectStage* colorStages[],
GrGLProgramBuilder::GrGLProgramBuilder(GrGpuGL* gpu,
const GrGLProgramDesc& desc)
- : fFragOnly(!desc.getHeader().fHasVertexCode && gpu->shouldUseFixedFunctionTexturing())
+ : fFragOnly(!desc.getHeader().fRequiresVertexShader &&
+ gpu->glCaps().pathRenderingSupport() &&
+ gpu->glPathRendering()->texturingMode() == GrGLPathRendering::FixedFunction_TexturingMode)
, fTexCoordSetCnt(0)
, fProgramID(0)
, fFS(this, desc)
+ , fSeparableVaryingInfos(kVarsPerBlock)
, fDesc(desc)
, fGpu(gpu)
, fUniforms(kVarsPerBlock) {
@@ -304,6 +307,16 @@ void GrGLProgramBuilder::resolveProgramLocations(GrGLuint programId) {
fUniforms[i].fLocation = location;
}
}
+
+ int count = fSeparableVaryingInfos.count();
+ for (int i = 0; i < count; ++i) {
+ GrGLint location;
+ GL_CALL_RET(location,
+ GetProgramResourceLocation(programId,
+ GR_GL_FRAGMENT_INPUT,
+ fSeparableVaryingInfos[i].fVariable.c_str()));
+ fSeparableVaryingInfos[i].fLocation = location;
+ }
}
const GrGLContextInfo& GrGLProgramBuilder::ctxInfo() const {
@@ -345,6 +358,18 @@ void GrGLFullProgramBuilder::addVarying(GrSLType type,
fFS.addVarying(type, fsInputName->c_str(), fsInName);
}
+GrGLFullProgramBuilder::VaryingHandle
+GrGLFullProgramBuilder::addSeparableVarying(GrSLType type,
+ const char* name,
+ const char** vsOutName,
+ const char** fsInName) {
+ addVarying(type, name, vsOutName, fsInName);
+ SeparableVaryingInfo& varying = fSeparableVaryingInfos.push_back();
+ varying.fVariable = fFS.fInputs.back();
+ return VaryingHandle::CreateFromSeparableVaryingIndex(fSeparableVaryingInfos.count() - 1);
+}
+
+
GrGLProgramEffects* GrGLFullProgramBuilder::createAndEmitEffects(
const GrEffectStage* effectStages[],
int effectCnt,
@@ -381,7 +406,7 @@ void GrGLFullProgramBuilder::bindProgramLocations(GrGLuint programId) {
GrGLFragmentOnlyProgramBuilder::GrGLFragmentOnlyProgramBuilder(GrGpuGL* gpu,
const GrGLProgramDesc& desc)
: INHERITED(gpu, desc) {
- SkASSERT(!desc.getHeader().fHasVertexCode);
+ SkASSERT(!desc.getHeader().fRequiresVertexShader);
SkASSERT(gpu->glCaps().pathRenderingSupport());
SkASSERT(GrGLProgramDesc::kAttribute_ColorInput != desc.getHeader().fColorInput);
SkASSERT(GrGLProgramDesc::kAttribute_ColorInput != desc.getHeader().fCoverageInput);
diff --git a/src/gpu/gl/builders/GrGLProgramBuilder.h b/src/gpu/gl/builders/GrGLProgramBuilder.h
index 09f7eba511..d1af63fc4e 100644
--- a/src/gpu/gl/builders/GrGLProgramBuilder.h
+++ b/src/gpu/gl/builders/GrGLProgramBuilder.h
@@ -40,6 +40,7 @@ public:
};
typedef GrGLProgramDataManager::UniformHandle UniformHandle;
+ typedef GrGLProgramDataManager::VaryingHandle VaryingHandle;
// Handles for program uniforms (other than per-effect uniforms)
struct BuiltinUniformHandles {
@@ -69,6 +70,13 @@ public:
// name strings. Otherwise, we'd have to hand out copies.
typedef GrTAllocator<UniformInfo> UniformInfoArray;
+ struct SeparableVaryingInfo {
+ GrGLShaderVar fVariable;
+ GrGLint fLocation;
+ };
+
+ typedef GrTAllocator<SeparableVaryingInfo> SeparableVaryingInfoArray;
+
/** Generates a shader program.
*
* The program implements what is specified in the stages given as input.
@@ -91,6 +99,9 @@ public:
bool hasVertexShader() const { SkASSERT(fProgramID); return !fFragOnly; }
int getTexCoordSetCount() const { SkASSERT(fProgramID); return fTexCoordSetCnt; }
const UniformInfoArray& getUniformInfos() const { return fUniforms; }
+ const SeparableVaryingInfoArray& getSeparableVaryingInfos() const {
+ return fSeparableVaryingInfos;
+ }
virtual ~GrGLProgramBuilder() {}
@@ -126,13 +137,12 @@ public:
const GrGLContextInfo& ctxInfo() const;
GrGLFragmentShaderBuilder* getFragmentShaderBuilder() { return &fFS; }
+ GrGpuGL* gpu() const { return fGpu; }
protected:
typedef GrTAllocator<GrGLShaderVar> VarArray;
GrGLProgramBuilder(GrGpuGL*, const GrGLProgramDesc&);
- GrGpuGL* gpu() const { return fGpu; }
-
const GrGLProgramDesc& desc() const { return fDesc; }
// Helper for emitEffects().
@@ -162,6 +172,7 @@ protected:
int fTexCoordSetCnt;
GrGLuint fProgramID;
GrGLFragmentShaderBuilder fFS;
+ SeparableVaryingInfoArray fSeparableVaryingInfos;
private:
class CodeStage : SkNoncopyable {
public:
@@ -271,6 +282,17 @@ public:
const char** vsOutName = NULL,
const char** fsInName = NULL);
+ /** Add a separable varying input variable to the current program.
+ * A separable varying (fragment shader input) is a varying that can be used also when vertex
+ * shaders are not used. With a vertex shader, the operation is same as with other
+ * varyings. Without a vertex shader, such as with NV_path_rendering, GL APIs are used to
+ * populate the variable. The APIs can refer to the variable through the returned handle.
+ */
+ VaryingHandle addSeparableVarying(GrSLType type,
+ const char* name,
+ const char** vsOutName,
+ const char** fsInName);
+
GrGLVertexShaderBuilder* getVertexShaderBuilder() { return &fVS; }
private: