aboutsummaryrefslogtreecommitdiffhomepage
path: root/src
diff options
context:
space:
mode:
authorGravatar jvanverth <jvanverth@google.com>2015-04-29 11:18:05 -0700
committerGravatar Commit bot <commit-bot@chromium.org>2015-04-29 11:18:05 -0700
commite9c0fc616d2a1632c285885b9b656b68ca8d4f24 (patch)
tree70325926996eb9e0cd63db76ea5aaec288091a84 /src
parent23c5f5137106221f9a00ac1e12740ee33e09767f (diff)
Pull out shader-specific caps into GrShaderCaps and GrGLSLCaps
Diffstat (limited to 'src')
-rw-r--r--src/gpu/GrAAConvexPathRenderer.cpp4
-rwxr-xr-xsrc/gpu/GrAADistanceFieldPathRenderer.cpp4
-rw-r--r--src/gpu/GrAAHairLinePathRenderer.cpp2
-rw-r--r--src/gpu/GrAtlasTextContext.cpp2
-rwxr-xr-xsrc/gpu/GrContext.cpp4
-rw-r--r--src/gpu/GrCoordTransform.cpp4
-rw-r--r--src/gpu/GrDrawTarget.cpp151
-rw-r--r--src/gpu/GrDrawTargetCaps.h109
-rw-r--r--src/gpu/GrOvalRenderer.cpp2
-rw-r--r--src/gpu/GrPrimitiveProcessor.h3
-rw-r--r--src/gpu/GrStencilAndCoverPathRenderer.cpp4
-rw-r--r--src/gpu/GrXferProcessor.cpp5
-rw-r--r--src/gpu/effects/GrBezierEffect.h12
-rw-r--r--src/gpu/effects/GrPorterDuffXferProcessor.cpp4
-rw-r--r--src/gpu/gl/GrGLCaps.cpp362
-rw-r--r--src/gpu/gl/GrGLCaps.h89
-rw-r--r--src/gpu/gl/GrGLGpu.cpp6
-rw-r--r--src/gpu/gl/GrGLGpu.h2
-rw-r--r--src/gpu/gl/GrGLPathRendering.cpp4
-rw-r--r--src/gpu/gl/GrGLProgramDesc.cpp6
-rw-r--r--src/gpu/gl/builders/GrGLFragmentShaderBuilder.cpp12
-rw-r--r--src/gpu/gl/builders/GrGLProgramBuilder.cpp4
22 files changed, 473 insertions, 322 deletions
diff --git a/src/gpu/GrAAConvexPathRenderer.cpp b/src/gpu/GrAAConvexPathRenderer.cpp
index e02e5693c3..01241c4c8c 100644
--- a/src/gpu/GrAAConvexPathRenderer.cpp
+++ b/src/gpu/GrAAConvexPathRenderer.cpp
@@ -687,7 +687,7 @@ GrGeometryProcessor* QuadEdgeEffect::TestCreate(SkRandom* random,
const GrDrawTargetCaps& caps,
GrTexture*[]) {
// Doesn't work without derivative instructions.
- return caps.shaderDerivativeSupport() ?
+ return caps.shaderCaps()->shaderDerivativeSupport() ?
QuadEdgeEffect::Create(GrRandomColor(random),
GrTest::TestMatrix(random)) : NULL;
}
@@ -700,7 +700,7 @@ bool GrAAConvexPathRenderer::canDrawPath(const GrDrawTarget* target,
const SkPath& path,
const GrStrokeInfo& stroke,
bool antiAlias) const {
- return (target->caps()->shaderDerivativeSupport() && antiAlias &&
+ return (target->caps()->shaderCaps()->shaderDerivativeSupport() && antiAlias &&
stroke.isFillStyle() && !path.isInverseFillType() && path.isConvex());
}
diff --git a/src/gpu/GrAADistanceFieldPathRenderer.cpp b/src/gpu/GrAADistanceFieldPathRenderer.cpp
index 48427fa083..ea338bba29 100755
--- a/src/gpu/GrAADistanceFieldPathRenderer.cpp
+++ b/src/gpu/GrAADistanceFieldPathRenderer.cpp
@@ -92,8 +92,8 @@ bool GrAADistanceFieldPathRenderer::canDrawPath(const GrDrawTarget* target,
// TODO: Support inverse fill
// TODO: Support strokes
- if (!target->caps()->shaderDerivativeSupport() || !antiAlias || path.isInverseFillType()
- || path.isVolatile() || !stroke.isFillStyle()) {
+ if (!target->caps()->shaderCaps()->shaderDerivativeSupport() || !antiAlias
+ || path.isInverseFillType() || path.isVolatile() || !stroke.isFillStyle()) {
return false;
}
diff --git a/src/gpu/GrAAHairLinePathRenderer.cpp b/src/gpu/GrAAHairLinePathRenderer.cpp
index 477385467e..9ab5c8eef2 100644
--- a/src/gpu/GrAAHairLinePathRenderer.cpp
+++ b/src/gpu/GrAAHairLinePathRenderer.cpp
@@ -649,7 +649,7 @@ bool GrAAHairLinePathRenderer::canDrawPath(const GrDrawTarget* target,
}
if (SkPath::kLine_SegmentMask == path.getSegmentMasks() ||
- target->caps()->shaderDerivativeSupport()) {
+ target->caps()->shaderCaps()->shaderDerivativeSupport()) {
return true;
}
return false;
diff --git a/src/gpu/GrAtlasTextContext.cpp b/src/gpu/GrAtlasTextContext.cpp
index dee3be7635..f1906c3f72 100644
--- a/src/gpu/GrAtlasTextContext.cpp
+++ b/src/gpu/GrAtlasTextContext.cpp
@@ -447,7 +447,7 @@ inline bool GrAtlasTextContext::canDrawAsDistanceFields(const SkPaint& skPaint,
// rasterizers and mask filters modify alpha, which doesn't
// translate well to distance
if (skPaint.getRasterizer() || skPaint.getMaskFilter() ||
- !fContext->getTextTarget()->caps()->shaderDerivativeSupport()) {
+ !fContext->getTextTarget()->caps()->shaderCaps()->shaderDerivativeSupport()) {
return false;
}
diff --git a/src/gpu/GrContext.cpp b/src/gpu/GrContext.cpp
index c396f1d21a..b5c8e3e592 100755
--- a/src/gpu/GrContext.cpp
+++ b/src/gpu/GrContext.cpp
@@ -226,7 +226,7 @@ GrTextContext* GrContext::createTextContext(GrRenderTarget* renderTarget,
const SkDeviceProperties&
leakyProperties,
bool enableDistanceFieldFonts) {
- if (fGpu->caps()->pathRenderingSupport() && renderTarget->isMultisampled()) {
+ if (fGpu->caps()->shaderCaps()->pathRenderingSupport() && renderTarget->isMultisampled()) {
GrStencilAttachment* sb = renderTarget->renderTargetPriv().attachStencilAttachment();
if (sb) {
return GrStencilAndCoverTextContext::Create(this, gpuDevice, leakyProperties);
@@ -1888,7 +1888,7 @@ int GrContext::getRecommendedSampleCount(GrPixelConfig config,
return 0;
}
int chosenSampleCount = 0;
- if (fGpu->caps()->pathRenderingSupport()) {
+ if (fGpu->caps()->shaderCaps()->pathRenderingSupport()) {
if (dpi >= 250.0f) {
chosenSampleCount = 4;
} else {
diff --git a/src/gpu/GrCoordTransform.cpp b/src/gpu/GrCoordTransform.cpp
index a08d454bad..19c4ce197c 100644
--- a/src/gpu/GrCoordTransform.cpp
+++ b/src/gpu/GrCoordTransform.cpp
@@ -27,10 +27,10 @@ void GrCoordTransform::reset(GrCoordSet sourceCoords, const SkMatrix& m, const G
int subPixelThresh = filter > GrTextureParams::kNone_FilterMode ? 4 : 1;
fPrecision = kDefault_GrSLPrecision;
if (texture->getContext()) {
- const GrDrawTargetCaps* caps = texture->getContext()->getGpu()->caps();
+ const GrShaderCaps* caps = texture->getContext()->getGpu()->caps()->shaderCaps();
if (caps->floatPrecisionVaries()) {
int maxD = SkTMax(texture->width(), texture->height());
- const GrDrawTargetCaps::PrecisionInfo* info;
+ const GrShaderCaps::PrecisionInfo* info;
info = &caps->getFloatShaderPrecisionInfo(kFragment_GrShaderType, fPrecision);
do {
SkASSERT(info->supported());
diff --git a/src/gpu/GrDrawTarget.cpp b/src/gpu/GrDrawTarget.cpp
index 00f6a8ad80..e52e4f976b 100644
--- a/src/gpu/GrDrawTarget.cpp
+++ b/src/gpu/GrDrawTarget.cpp
@@ -213,7 +213,7 @@ void GrDrawTarget::stencilPath(GrPipelineBuilder* pipelineBuilder,
GrPathRendering::FillType fill) {
// TODO: extract portions of checkDraw that are relevant to path stenciling.
SkASSERT(path);
- SkASSERT(this->caps()->pathRenderingSupport());
+ SkASSERT(this->caps()->shaderCaps()->pathRenderingSupport());
SkASSERT(pipelineBuilder);
// Setup clip
@@ -239,7 +239,7 @@ void GrDrawTarget::drawPath(GrPipelineBuilder* pipelineBuilder,
GrPathRendering::FillType fill) {
// TODO: extract portions of checkDraw that are relevant to path rendering.
SkASSERT(path);
- SkASSERT(this->caps()->pathRenderingSupport());
+ SkASSERT(this->caps()->shaderCaps()->pathRenderingSupport());
SkASSERT(pipelineBuilder);
SkRect devBounds = path->getBounds();
@@ -277,7 +277,7 @@ void GrDrawTarget::drawPaths(GrPipelineBuilder* pipelineBuilder,
PathTransformType transformType,
int count,
GrPathRendering::FillType fill) {
- SkASSERT(this->caps()->pathRenderingSupport());
+ SkASSERT(this->caps()->shaderCaps()->pathRenderingSupport());
SkASSERT(pathRange);
SkASSERT(indices);
SkASSERT(0 == reinterpret_cast<long>(indices) % GrPathRange::PathIndexSizeInBytes(indexType));
@@ -541,16 +541,92 @@ GrDrawTarget::PipelineInfo::PipelineInfo(GrPipelineBuilder* pipelineBuilder,
///////////////////////////////////////////////////////////////////////////////
+void GrShaderCaps::reset() {
+ fShaderDerivativeSupport = false;
+ fGeometryShaderSupport = false;
+ fPathRenderingSupport = false;
+ fDstReadInShaderSupport = false;
+ fDualSourceBlendingSupport = false;
+
+ fShaderPrecisionVaries = false;
+}
+
+GrShaderCaps& GrShaderCaps::operator=(const GrShaderCaps& other) {
+ fShaderDerivativeSupport = other.fShaderDerivativeSupport;
+ fGeometryShaderSupport = other.fGeometryShaderSupport;
+ fPathRenderingSupport = other.fPathRenderingSupport;
+ fDstReadInShaderSupport = other.fDstReadInShaderSupport;
+ fDualSourceBlendingSupport = other.fDualSourceBlendingSupport;
+
+ fShaderPrecisionVaries = other.fShaderPrecisionVaries;
+ for (int s = 0; s < kGrShaderTypeCount; ++s) {
+ for (int p = 0; p < kGrSLPrecisionCount; ++p) {
+ fFloatPrecisions[s][p] = other.fFloatPrecisions[s][p];
+ }
+ }
+ return *this;
+}
+
+static const char* shader_type_to_string(GrShaderType type) {
+ switch (type) {
+ case kVertex_GrShaderType:
+ return "vertex";
+ case kGeometry_GrShaderType:
+ return "geometry";
+ case kFragment_GrShaderType:
+ return "fragment";
+ }
+ return "";
+}
+
+static const char* precision_to_string(GrSLPrecision p) {
+ switch (p) {
+ case kLow_GrSLPrecision:
+ return "low";
+ case kMedium_GrSLPrecision:
+ return "medium";
+ case kHigh_GrSLPrecision:
+ return "high";
+ }
+ return "";
+}
+
+SkString GrShaderCaps::dump() const {
+ SkString r;
+ static const char* gNY[] = { "NO", "YES" };
+ r.appendf("Shader Derivative Support : %s\n", gNY[fShaderDerivativeSupport]);
+ r.appendf("Geometry Shader Support : %s\n", gNY[fGeometryShaderSupport]);
+ r.appendf("Path Rendering Support : %s\n", gNY[fPathRenderingSupport]);
+ r.appendf("Dst Read In Shader Support : %s\n", gNY[fDstReadInShaderSupport]);
+ r.appendf("Dual Source Blending Support : %s\n", gNY[fDualSourceBlendingSupport]);
+
+ r.appendf("Shader Float Precisions (varies: %s):\n", gNY[fShaderPrecisionVaries]);
+
+ for (int s = 0; s < kGrShaderTypeCount; ++s) {
+ GrShaderType shaderType = static_cast<GrShaderType>(s);
+ r.appendf("\t%s:\n", shader_type_to_string(shaderType));
+ for (int p = 0; p < kGrSLPrecisionCount; ++p) {
+ if (fFloatPrecisions[s][p].supported()) {
+ GrSLPrecision precision = static_cast<GrSLPrecision>(p);
+ r.appendf("\t\t%s: log_low: %d log_high: %d bits: %d\n",
+ precision_to_string(precision),
+ fFloatPrecisions[s][p].fLogRangeLow,
+ fFloatPrecisions[s][p].fLogRangeHigh,
+ fFloatPrecisions[s][p].fBits);
+ }
+ }
+ }
+
+ return r;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
void GrDrawTargetCaps::reset() {
fMipMapSupport = false;
fNPOTTextureTileSupport = false;
fTwoSidedStencilSupport = false;
fStencilWrapOpsSupport = false;
- fShaderDerivativeSupport = false;
- fGeometryShaderSupport = false;
- fDualSourceBlendingSupport = false;
- fPathRenderingSupport = false;
- fDstReadInShaderSupport = false;
fDiscardRenderTargetSupport = false;
fReuseScratchTextures = true;
fGpuTracingSupport = false;
@@ -566,8 +642,6 @@ void GrDrawTargetCaps::reset() {
fMaxTextureSize = 0;
fMaxSampleCount = 0;
- fShaderPrecisionVaries = false;
-
memset(fConfigRenderSupport, 0, sizeof(fConfigRenderSupport));
memset(fConfigTextureSupport, 0, sizeof(fConfigTextureSupport));
}
@@ -577,11 +651,6 @@ GrDrawTargetCaps& GrDrawTargetCaps::operator=(const GrDrawTargetCaps& other) {
fNPOTTextureTileSupport = other.fNPOTTextureTileSupport;
fTwoSidedStencilSupport = other.fTwoSidedStencilSupport;
fStencilWrapOpsSupport = other.fStencilWrapOpsSupport;
- fShaderDerivativeSupport = other.fShaderDerivativeSupport;
- fGeometryShaderSupport = other.fGeometryShaderSupport;
- fDualSourceBlendingSupport = other.fDualSourceBlendingSupport;
- fPathRenderingSupport = other.fPathRenderingSupport;
- fDstReadInShaderSupport = other.fDstReadInShaderSupport;
fDiscardRenderTargetSupport = other.fDiscardRenderTargetSupport;
fReuseScratchTextures = other.fReuseScratchTextures;
fGpuTracingSupport = other.fGpuTracingSupport;
@@ -600,12 +669,6 @@ GrDrawTargetCaps& GrDrawTargetCaps::operator=(const GrDrawTargetCaps& other) {
memcpy(fConfigRenderSupport, other.fConfigRenderSupport, sizeof(fConfigRenderSupport));
memcpy(fConfigTextureSupport, other.fConfigTextureSupport, sizeof(fConfigTextureSupport));
- fShaderPrecisionVaries = other.fShaderPrecisionVaries;
- for (int s = 0; s < kGrShaderTypeCount; ++s) {
- for (int p = 0; p < kGrSLPrecisionCount; ++p) {
- fFloatPrecisions[s][p] = other.fFloatPrecisions[s][p];
- }
- }
return *this;
}
@@ -629,30 +692,6 @@ static SkString map_flags_to_string(uint32_t flags) {
return str;
}
-static const char* shader_type_to_string(GrShaderType type) {
- switch (type) {
- case kVertex_GrShaderType:
- return "vertex";
- case kGeometry_GrShaderType:
- return "geometry";
- case kFragment_GrShaderType:
- return "fragment";
- }
- return "";
-}
-
-static const char* precision_to_string(GrSLPrecision p) {
- switch (p) {
- case kLow_GrSLPrecision:
- return "low";
- case kMedium_GrSLPrecision:
- return "medium";
- case kHigh_GrSLPrecision:
- return "high";
- }
- return "";
-}
-
SkString GrDrawTargetCaps::dump() const {
SkString r;
static const char* gNY[] = {"NO", "YES"};
@@ -660,11 +699,6 @@ SkString GrDrawTargetCaps::dump() const {
r.appendf("NPOT Texture Tile Support : %s\n", gNY[fNPOTTextureTileSupport]);
r.appendf("Two Sided Stencil Support : %s\n", gNY[fTwoSidedStencilSupport]);
r.appendf("Stencil Wrap Ops Support : %s\n", gNY[fStencilWrapOpsSupport]);
- r.appendf("Shader Derivative Support : %s\n", gNY[fShaderDerivativeSupport]);
- r.appendf("Geometry Shader Support : %s\n", gNY[fGeometryShaderSupport]);
- r.appendf("Dual Source Blending Support : %s\n", gNY[fDualSourceBlendingSupport]);
- r.appendf("Path Rendering Support : %s\n", gNY[fPathRenderingSupport]);
- r.appendf("Dst Read In Shader Support : %s\n", gNY[fDstReadInShaderSupport]);
r.appendf("Discard Render Target Support : %s\n", gNY[fDiscardRenderTargetSupport]);
r.appendf("Reuse Scratch Textures : %s\n", gNY[fReuseScratchTextures]);
r.appendf("Gpu Tracing Support : %s\n", gNY[fGpuTracingSupport]);
@@ -730,23 +764,6 @@ SkString GrDrawTargetCaps::dump() const {
gNY[fConfigTextureSupport[i]]);
}
- r.appendf("Shader Float Precisions (varies: %s):\n", gNY[fShaderPrecisionVaries]);
-
- for (int s = 0; s < kGrShaderTypeCount; ++s) {
- GrShaderType shaderType = static_cast<GrShaderType>(s);
- r.appendf("\t%s:\n", shader_type_to_string(shaderType));
- for (int p = 0; p < kGrSLPrecisionCount; ++p) {
- if (fFloatPrecisions[s][p].supported()) {
- GrSLPrecision precision = static_cast<GrSLPrecision>(p);
- r.appendf("\t\t%s: log_low: %d log_high: %d bits: %d\n",
- precision_to_string(precision),
- fFloatPrecisions[s][p].fLogRangeLow,
- fFloatPrecisions[s][p].fLogRangeHigh,
- fFloatPrecisions[s][p].fBits);
- }
- }
- }
-
return r;
}
diff --git a/src/gpu/GrDrawTargetCaps.h b/src/gpu/GrDrawTargetCaps.h
index e1fd1cf403..310703caca 100644
--- a/src/gpu/GrDrawTargetCaps.h
+++ b/src/gpu/GrDrawTargetCaps.h
@@ -14,12 +14,9 @@
#include "SkRefCnt.h"
#include "SkString.h"
-/**
- * Represents the draw target capabilities.
- */
-class GrDrawTargetCaps : public SkRefCnt {
+class GrShaderCaps : public SkRefCnt {
public:
- SK_DECLARE_INST_COUNT(GrDrawTargetCaps)
+ SK_DECLARE_INST_COUNT(GrShaderCaps)
/** Info about shader variable precision within a given shader stage. That is, this info
is relevant to a float (or vecNf) variable declared with a GrSLPrecision
@@ -44,19 +41,76 @@ public:
int fLogRangeLow;
/** floor(log2(|max_value|)) */
int fLogRangeHigh;
- /** Number of bits of precision. As defined in OpenGL (with names modified to reflect this
+ /** Number of bits of precision. As defined in OpenGL (with names modified to reflect this
struct) :
"""
- If the smallest representable value greater than 1 is 1 + e, then fBits will
- contain floor(log2(e)), and every value in the range [2^fLogRangeLow,
- 2^fLogRangeHigh] can be represented to at least one part in 2^fBits.
- """
+ If the smallest representable value greater than 1 is 1 + e, then fBits will
+ contain floor(log2(e)), and every value in the range [2^fLogRangeLow,
+ 2^fLogRangeHigh] can be represented to at least one part in 2^fBits.
+ """
*/
int fBits;
};
+ GrShaderCaps() {
+ this->reset();
+ }
+ virtual ~GrShaderCaps() {}
+ GrShaderCaps(const GrShaderCaps& other) : INHERITED() {
+ *this = other;
+ }
+ GrShaderCaps& operator= (const GrShaderCaps&);
+
+ virtual void reset();
+ virtual SkString dump() const;
+
+ bool shaderDerivativeSupport() const { return fShaderDerivativeSupport; }
+ bool geometryShaderSupport() const { return fGeometryShaderSupport; }
+ bool pathRenderingSupport() const { return fPathRenderingSupport; }
+ bool dstReadInShaderSupport() const { return fDstReadInShaderSupport; }
+ bool dualSourceBlendingSupport() const { return fDualSourceBlendingSupport; }
+
+ /**
+ * Get the precision info for a variable of type kFloat_GrSLType, kVec2f_GrSLType, etc in a
+ * given shader type. If the shader type is not supported or the precision level is not
+ * supported in that shader type then the returned struct will report false when supported() is
+ * called.
+ */
+ const PrecisionInfo& getFloatShaderPrecisionInfo(GrShaderType shaderType,
+ GrSLPrecision precision) const {
+ return fFloatPrecisions[shaderType][precision];
+ };
+
+ /**
+ * Is there any difference between the float shader variable precision types? If this is true
+ * then unless the shader type is not supported, any call to getFloatShaderPrecisionInfo() would
+ * report the same info for all precisions in all shader types.
+ */
+ bool floatPrecisionVaries() const { return fShaderPrecisionVaries; }
+
+protected:
+ bool fShaderDerivativeSupport : 1;
+ bool fGeometryShaderSupport : 1;
+ bool fPathRenderingSupport : 1;
+ bool fDstReadInShaderSupport : 1;
+ bool fDualSourceBlendingSupport : 1;
+
+ bool fShaderPrecisionVaries;
+ PrecisionInfo fFloatPrecisions[kGrShaderTypeCount][kGrSLPrecisionCount];
+
+private:
+ typedef SkRefCnt INHERITED;
+};
+
+/**
+ * Represents the draw target capabilities.
+ */
+class GrDrawTargetCaps : public SkRefCnt {
+public:
+ SK_DECLARE_INST_COUNT(GrDrawTargetCaps)
GrDrawTargetCaps() {
+ fShaderCaps.reset(NULL);
this->reset();
}
GrDrawTargetCaps(const GrDrawTargetCaps& other) : INHERITED() {
@@ -67,17 +121,14 @@ public:
virtual void reset();
virtual SkString dump() const;
+ GrShaderCaps* shaderCaps() const { return fShaderCaps; }
+
bool npotTextureTileSupport() const { return fNPOTTextureTileSupport; }
/** To avoid as-yet-unnecessary complexity we don't allow any partial support of MIP Maps (e.g.
only for POT textures) */
bool mipMapSupport() const { return fMipMapSupport; }
bool twoSidedStencilSupport() const { return fTwoSidedStencilSupport; }
bool stencilWrapOpsSupport() const { return fStencilWrapOpsSupport; }
- bool shaderDerivativeSupport() const { return fShaderDerivativeSupport; }
- bool geometryShaderSupport() const { return fGeometryShaderSupport; }
- bool dualSourceBlendingSupport() const { return fDualSourceBlendingSupport; }
- bool pathRenderingSupport() const { return fPathRenderingSupport; }
- bool dstReadInShaderSupport() const { return fDstReadInShaderSupport; }
bool discardRenderTargetSupport() const { return fDiscardRenderTargetSupport; }
#if GR_FORCE_GPU_TRACE_DEBUGGING
bool gpuTracingSupport() const { return true; }
@@ -125,34 +176,13 @@ public:
return fConfigTextureSupport[config];
}
- /**
- * Get the precision info for a variable of type kFloat_GrSLType, kVec2f_GrSLType, etc in a
- * given shader type. If the shader type is not supported or the precision level is not
- * supported in that shader type then the returned struct will report false when supported() is
- * called.
- */
- const PrecisionInfo& getFloatShaderPrecisionInfo(GrShaderType shaderType,
- GrSLPrecision precision) const {
- return fFloatPrecisions[shaderType][precision];
- };
-
- /**
- * Is there any difference between the float shader variable precision types? If this is true
- * then unless the shader type is not supported, any call to getFloatShaderPrecisionInfo() would
- * report the same info for all precisions in all shader types.
- */
- bool floatPrecisionVaries() const { return fShaderPrecisionVaries; }
-
protected:
+ SkAutoTUnref<GrShaderCaps> fShaderCaps;
+
bool fNPOTTextureTileSupport : 1;
bool fMipMapSupport : 1;
bool fTwoSidedStencilSupport : 1;
bool fStencilWrapOpsSupport : 1;
- bool fShaderDerivativeSupport : 1;
- bool fGeometryShaderSupport : 1;
- bool fDualSourceBlendingSupport : 1;
- bool fPathRenderingSupport : 1;
- bool fDstReadInShaderSupport : 1;
bool fDiscardRenderTargetSupport : 1;
bool fReuseScratchTextures : 1;
bool fGpuTracingSupport : 1;
@@ -172,9 +202,6 @@ protected:
bool fConfigRenderSupport[kGrPixelConfigCnt][2];
bool fConfigTextureSupport[kGrPixelConfigCnt];
- bool fShaderPrecisionVaries;
- PrecisionInfo fFloatPrecisions[kGrShaderTypeCount][kGrSLPrecisionCount];
-
private:
typedef SkRefCnt INHERITED;
};
diff --git a/src/gpu/GrOvalRenderer.cpp b/src/gpu/GrOvalRenderer.cpp
index c89ece806e..a1c80f5b8b 100644
--- a/src/gpu/GrOvalRenderer.cpp
+++ b/src/gpu/GrOvalRenderer.cpp
@@ -669,7 +669,7 @@ bool GrOvalRenderer::drawOval(GrDrawTarget* target,
if (SkScalarNearlyEqual(oval.width(), oval.height()) && circle_stays_circle(viewMatrix)) {
this->drawCircle(target, pipelineBuilder, color, viewMatrix, useCoverageAA, oval, stroke);
// if we have shader derivative support, render as device-independent
- } else if (target->caps()->shaderDerivativeSupport()) {
+ } else if (target->caps()->shaderCaps()->shaderDerivativeSupport()) {
return this->drawDIEllipse(target, pipelineBuilder, color, viewMatrix, useCoverageAA, oval,
stroke);
// otherwise axis-aligned ellipses only
diff --git a/src/gpu/GrPrimitiveProcessor.h b/src/gpu/GrPrimitiveProcessor.h
index ea1237b9a2..d66aed1ddc 100644
--- a/src/gpu/GrPrimitiveProcessor.h
+++ b/src/gpu/GrPrimitiveProcessor.h
@@ -67,8 +67,7 @@ private:
};
class GrIndexBufferAllocPool;
-class GrGLCaps;
-typedef GrGLCaps GrGLSLCaps;
+class GrGLSLCaps;
class GrGLPrimitiveProcessor;
class GrVertexBufferAllocPool;
diff --git a/src/gpu/GrStencilAndCoverPathRenderer.cpp b/src/gpu/GrStencilAndCoverPathRenderer.cpp
index 8451e632d3..4c9fdea34e 100644
--- a/src/gpu/GrStencilAndCoverPathRenderer.cpp
+++ b/src/gpu/GrStencilAndCoverPathRenderer.cpp
@@ -35,7 +35,7 @@ static GrPathRendering::FillType convert_skpath_filltype(SkPath::FillType fill)
GrPathRenderer* GrStencilAndCoverPathRenderer::Create(GrContext* context) {
SkASSERT(context);
SkASSERT(context->getGpu());
- if (context->getGpu()->caps()->pathRenderingSupport()) {
+ if (context->getGpu()->caps()->shaderCaps()->pathRenderingSupport()) {
return SkNEW_ARGS(GrStencilAndCoverPathRenderer, (context->getGpu()));
} else {
return NULL;
@@ -43,7 +43,7 @@ GrPathRenderer* GrStencilAndCoverPathRenderer::Create(GrContext* context) {
}
GrStencilAndCoverPathRenderer::GrStencilAndCoverPathRenderer(GrGpu* gpu) {
- SkASSERT(gpu->caps()->pathRenderingSupport());
+ SkASSERT(gpu->caps()->shaderCaps()->pathRenderingSupport());
fGpu = gpu;
gpu->ref();
}
diff --git a/src/gpu/GrXferProcessor.cpp b/src/gpu/GrXferProcessor.cpp
index 61cacac62e..de08ef0ee6 100644
--- a/src/gpu/GrXferProcessor.cpp
+++ b/src/gpu/GrXferProcessor.cpp
@@ -40,7 +40,7 @@ GrXferProcessor* GrXPFactory::createXferProcessor(const GrProcOptInfo& colorPOI,
const GrDrawTargetCaps& caps) const {
#ifdef SK_DEBUG
if (this->willReadDstColor(caps, colorPOI, coveragePOI)) {
- if (!caps.dstReadInShaderSupport()) {
+ if (!caps.shaderCaps()->dstReadInShaderSupport()) {
SkASSERT(dstCopy && dstCopy->texture());
} else {
SkASSERT(!dstCopy || !dstCopy->texture());
@@ -54,6 +54,7 @@ GrXferProcessor* GrXPFactory::createXferProcessor(const GrProcOptInfo& colorPOI,
bool GrXPFactory::willNeedDstCopy(const GrDrawTargetCaps& caps, const GrProcOptInfo& colorPOI,
const GrProcOptInfo& coveragePOI) const {
- return (this->willReadDstColor(caps, colorPOI, coveragePOI) && !caps.dstReadInShaderSupport());
+ return (this->willReadDstColor(caps, colorPOI, coveragePOI)
+ && !caps.shaderCaps()->dstReadInShaderSupport());
}
diff --git a/src/gpu/effects/GrBezierEffect.h b/src/gpu/effects/GrBezierEffect.h
index 7f79988470..07d255c3b2 100644
--- a/src/gpu/effects/GrBezierEffect.h
+++ b/src/gpu/effects/GrBezierEffect.h
@@ -66,14 +66,14 @@ public:
uint8_t coverage = 0xff) {
switch (edgeType) {
case kFillAA_GrProcessorEdgeType:
- if (!caps.shaderDerivativeSupport()) {
+ if (!caps.shaderCaps()->shaderDerivativeSupport()) {
return NULL;
}
return SkNEW_ARGS(GrConicEffect, (color, viewMatrix, coverage,
kFillAA_GrProcessorEdgeType,
localMatrix));
case kHairlineAA_GrProcessorEdgeType:
- if (!caps.shaderDerivativeSupport()) {
+ if (!caps.shaderCaps()->shaderDerivativeSupport()) {
return NULL;
}
return SkNEW_ARGS(GrConicEffect, (color, viewMatrix, coverage,
@@ -151,14 +151,14 @@ public:
uint8_t coverage = 0xff) {
switch (edgeType) {
case kFillAA_GrProcessorEdgeType:
- if (!caps.shaderDerivativeSupport()) {
+ if (!caps.shaderCaps()->shaderDerivativeSupport()) {
return NULL;
}
return SkNEW_ARGS(GrQuadEffect, (color, viewMatrix, coverage,
kFillAA_GrProcessorEdgeType,
localMatrix));
case kHairlineAA_GrProcessorEdgeType:
- if (!caps.shaderDerivativeSupport()) {
+ if (!caps.shaderCaps()->shaderDerivativeSupport()) {
return NULL;
}
return SkNEW_ARGS(GrQuadEffect, (color, viewMatrix, coverage,
@@ -236,12 +236,12 @@ public:
const GrDrawTargetCaps& caps) {
switch (edgeType) {
case kFillAA_GrProcessorEdgeType:
- if (!caps.shaderDerivativeSupport()) {
+ if (!caps.shaderCaps()->shaderDerivativeSupport()) {
return NULL;
}
return SkNEW_ARGS(GrCubicEffect, (color, viewMatrix, kFillAA_GrProcessorEdgeType));
case kHairlineAA_GrProcessorEdgeType:
- if (!caps.shaderDerivativeSupport()) {
+ if (!caps.shaderCaps()->shaderDerivativeSupport()) {
return NULL;
}
return SkNEW_ARGS(GrCubicEffect, (color, viewMatrix,
diff --git a/src/gpu/effects/GrPorterDuffXferProcessor.cpp b/src/gpu/effects/GrPorterDuffXferProcessor.cpp
index eebf2e4ac7..2be2f4e57b 100644
--- a/src/gpu/effects/GrPorterDuffXferProcessor.cpp
+++ b/src/gpu/effects/GrPorterDuffXferProcessor.cpp
@@ -351,7 +351,7 @@ void PorterDuffXferProcessor::calcOutputTypes(GrXferProcessor::OptFlags optFlags
// blending if we have any effective coverage stages OR the geometry processor doesn't emits
// solid coverage.
if (!(optFlags & kSetCoverageDrawing_OptFlag) && !hasSolidCoverage) {
- if (caps.dualSourceBlendingSupport()) {
+ if (caps.shaderCaps()->dualSourceBlendingSupport()) {
if (kZero_GrBlendCoeff == fDstBlend) {
// write the coverage value to second color
fSecondaryOutputType = kCoverage_SecondaryOutputType;
@@ -668,7 +668,7 @@ bool GrPorterDuffXPFactory::willReadDstColor(const GrDrawTargetCaps& caps,
const GrProcOptInfo& colorPOI,
const GrProcOptInfo& coveragePOI) const {
// We can always blend correctly if we have dual source blending.
- if (caps.dualSourceBlendingSupport()) {
+ if (caps.shaderCaps()->dualSourceBlendingSupport()) {
return false;
}
diff --git a/src/gpu/gl/GrGLCaps.cpp b/src/gpu/gl/GrGLCaps.cpp
index b4287cced9..2edf1d0219 100644
--- a/src/gpu/gl/GrGLCaps.cpp
+++ b/src/gpu/gl/GrGLCaps.cpp
@@ -47,14 +47,12 @@ void GrGLCaps::reset() {
fUseNonVBOVertexAndIndexDynamicData = false;
fIsCoreProfile = false;
fFullClearIsFree = false;
- fDropsTileOnZeroDivide = false;
- fFBFetchSupport = false;
- fFBFetchNeedsCustomOutput = false;
- fFBFetchColorName = NULL;
- fFBFetchExtensionString = NULL;
fFBMixedSamplesSupport = false;
fReadPixelsSupportedCache.reset();
+
+ fShaderCaps.reset(SkNEW(GrGLSLCaps));
+
}
GrGLCaps::GrGLCaps(const GrGLCaps& caps) : GrDrawTargetCaps() {
@@ -91,13 +89,11 @@ GrGLCaps& GrGLCaps::operator= (const GrGLCaps& caps) {
fUseNonVBOVertexAndIndexDynamicData = caps.fUseNonVBOVertexAndIndexDynamicData;
fIsCoreProfile = caps.fIsCoreProfile;
fFullClearIsFree = caps.fFullClearIsFree;
- fDropsTileOnZeroDivide = caps.fDropsTileOnZeroDivide;
- fFBFetchSupport = caps.fFBFetchSupport;
- fFBFetchNeedsCustomOutput = caps.fFBFetchNeedsCustomOutput;
- fFBFetchColorName = caps.fFBFetchColorName;
- fFBFetchExtensionString = caps.fFBFetchExtensionString;
fFBMixedSamplesSupport = caps.fFBMixedSamplesSupport;
+ *(reinterpret_cast<GrGLSLCaps*>(fShaderCaps.get())) =
+ *(reinterpret_cast<GrGLSLCaps*>(caps.fShaderCaps.get()));
+
return *this;
}
@@ -253,30 +249,6 @@ bool GrGLCaps::init(const GrGLContextInfo& ctxInfo, const GrGLInterface* gli) {
fES2CompatibilitySupport = true;
}
- if (kGLES_GrGLStandard == standard) {
- if (ctxInfo.hasExtension("GL_EXT_shader_framebuffer_fetch")) {
- fFBFetchNeedsCustomOutput = (version >= GR_GL_VER(3, 0));
- fFBFetchSupport = true;
- fFBFetchColorName = "gl_LastFragData[0]";
- fFBFetchExtensionString = "GL_EXT_shader_framebuffer_fetch";
- } else if (ctxInfo.hasExtension("GL_NV_shader_framebuffer_fetch")) {
- // Actually, we haven't seen an ES3.0 device with this extension yet, so we don't know
- fFBFetchNeedsCustomOutput = false;
- fFBFetchSupport = true;
- fFBFetchColorName = "gl_LastFragData[0]";
- fFBFetchExtensionString = "GL_NV_shader_framebuffer_fetch";
- } else if (ctxInfo.hasExtension("GL_ARM_shader_framebuffer_fetch")) {
- // The arm extension also requires an additional flag which we will set onResetContext
- fFBFetchNeedsCustomOutput = false;
- fFBFetchSupport = true;
- fFBFetchColorName = "gl_LastFragColorARM";
- fFBFetchExtensionString = "GL_ARM_shader_framebuffer_fetch";
- }
- }
-
- // Adreno GPUs have a tendency to drop tiles when there is a divide-by-zero in a shader
- fDropsTileOnZeroDivide = kQualcomm_GrGLVendor == ctxInfo.vendor();
-
this->initFSAASupport(ctxInfo, gli);
this->initStencilFormats(ctxInfo);
@@ -344,46 +316,14 @@ bool GrGLCaps::init(const GrGLContextInfo& ctxInfo, const GrGLInterface* gli) {
// attachment, hence this min:
fMaxRenderTargetSize = SkTMin(fMaxTextureSize, fMaxRenderTargetSize);
- fPathRenderingSupport = ctxInfo.hasExtension("GL_NV_path_rendering");
-
- if (fPathRenderingSupport) {
- if (kGL_GrGLStandard == standard) {
- // We only support v1.3+ of GL_NV_path_rendering which allows us to
- // set individual fragment inputs with ProgramPathFragmentInputGen. The API
- // additions are detected by checking the existence of the function.
- fPathRenderingSupport = ctxInfo.hasExtension("GL_EXT_direct_state_access") &&
- ((ctxInfo.version() >= GR_GL_VER(4,3) ||
- ctxInfo.hasExtension("GL_ARB_program_interface_query")) &&
- gli->fFunctions.fProgramPathFragmentInputGen);
- } else {
- fPathRenderingSupport = ctxInfo.version() >= GR_GL_VER(3,1);
- }
- }
-
fFBMixedSamplesSupport = ctxInfo.hasExtension("GL_NV_framebuffer_mixed_samples");
fGpuTracingSupport = ctxInfo.hasExtension("GL_EXT_debug_marker");
- // For now these two are equivalent but we could have dst read in shader via some other method
- fDstReadInShaderSupport = fFBFetchSupport;
-
// Disable scratch texture reuse on Mali and Adreno devices
fReuseScratchTextures = kARM_GrGLVendor != ctxInfo.vendor() &&
kQualcomm_GrGLVendor != ctxInfo.vendor();
- // Enable supported shader-related caps
- if (kGL_GrGLStandard == standard) {
- fDualSourceBlendingSupport = ctxInfo.version() >= GR_GL_VER(3,3) ||
- ctxInfo.hasExtension("GL_ARB_blend_func_extended");
- fShaderDerivativeSupport = true;
- // we don't support GL_ARB_geometry_shader4, just GL 3.2+ GS
- fGeometryShaderSupport = ctxInfo.version() >= GR_GL_VER(3,2) &&
- ctxInfo.glslGeneration() >= k150_GrGLSLGeneration;
- } else {
- fShaderDerivativeSupport = ctxInfo.version() >= GR_GL_VER(3, 0) ||
- ctxInfo.hasExtension("GL_OES_standard_derivatives");
- }
-
if (GrGLCaps::kES_IMG_MsToTexture_MSFBOType == fMSFBOType) {
GR_GL_GetIntegerv(gli, GR_GL_MAX_SAMPLES_IMG, &fMaxSampleCount);
} else if (GrGLCaps::kNone_MSFBOType != fMSFBOType) {
@@ -412,7 +352,7 @@ bool GrGLCaps::init(const GrGLContextInfo& ctxInfo, const GrGLInterface* gli) {
this->initConfigTexturableTable(ctxInfo, gli);
this->initConfigRenderableTable(ctxInfo);
- this->initShaderPrecisionTable(ctxInfo, gli);
+ reinterpret_cast<GrGLSLCaps*>(fShaderCaps.get())->init(ctxInfo, gli);
return true;
}
@@ -835,85 +775,6 @@ void GrGLCaps::initStencilFormats(const GrGLContextInfo& ctxInfo) {
fStencilVerifiedColorConfigs.push_back_n(fStencilFormats.count());
}
-static GrGLenum precision_to_gl_float_type(GrSLPrecision p) {
- switch (p) {
- case kLow_GrSLPrecision:
- return GR_GL_LOW_FLOAT;
- case kMedium_GrSLPrecision:
- return GR_GL_MEDIUM_FLOAT;
- case kHigh_GrSLPrecision:
- return GR_GL_HIGH_FLOAT;
- }
- SkFAIL("Unknown precision.");
- return -1;
-}
-
-static GrGLenum shader_type_to_gl_shader(GrShaderType type) {
- switch (type) {
- case kVertex_GrShaderType:
- return GR_GL_VERTEX_SHADER;
- case kGeometry_GrShaderType:
- return GR_GL_GEOMETRY_SHADER;
- case kFragment_GrShaderType:
- return GR_GL_FRAGMENT_SHADER;
- }
- SkFAIL("Unknown shader type.");
- return -1;
-}
-
-void GrGLCaps::initShaderPrecisionTable(const GrGLContextInfo& ctxInfo, const GrGLInterface* intf) {
- if (kGLES_GrGLStandard == ctxInfo.standard() || ctxInfo.version() >= GR_GL_VER(4,1) ||
- ctxInfo.hasExtension("GL_ARB_ES2_compatibility")) {
- for (int s = 0; s < kGrShaderTypeCount; ++s) {
- if (kGeometry_GrShaderType != s) {
- GrShaderType shaderType = static_cast<GrShaderType>(s);
- GrGLenum glShader = shader_type_to_gl_shader(shaderType);
- PrecisionInfo* first = NULL;
- fShaderPrecisionVaries = false;
- for (int p = 0; p < kGrSLPrecisionCount; ++p) {
- GrSLPrecision precision = static_cast<GrSLPrecision>(p);
- GrGLenum glPrecision = precision_to_gl_float_type(precision);
- GrGLint range[2];
- GrGLint bits;
- GR_GL_GetShaderPrecisionFormat(intf, glShader, glPrecision, range, &bits);
- if (bits) {
- fFloatPrecisions[s][p].fLogRangeLow = range[0];
- fFloatPrecisions[s][p].fLogRangeHigh = range[1];
- fFloatPrecisions[s][p].fBits = bits;
- if (!first) {
- first = &fFloatPrecisions[s][p];
- } else if (!fShaderPrecisionVaries) {
- fShaderPrecisionVaries = (*first != fFloatPrecisions[s][p]);
- }
- }
- }
- }
- }
- } else {
- // We're on a desktop GL that doesn't have precision info. Assume they're all 32bit float.
- fShaderPrecisionVaries = false;
- for (int s = 0; s < kGrShaderTypeCount; ++s) {
- if (kGeometry_GrShaderType != s) {
- for (int p = 0; p < kGrSLPrecisionCount; ++p) {
- fFloatPrecisions[s][p].fLogRangeLow = 127;
- fFloatPrecisions[s][p].fLogRangeHigh = 127;
- fFloatPrecisions[s][p].fBits = 23;
- }
- }
- }
- }
- // GetShaderPrecisionFormat doesn't accept GL_GEOMETRY_SHADER as a shader type. Assume they're
- // the same as the vertex shader. Only fragment shaders were ever allowed to omit support for
- // highp. GS was added after GetShaderPrecisionFormat was added to the list of features that
- // are recommended against.
- if (fGeometryShaderSupport) {
- for (int p = 0; p < kGrSLPrecisionCount; ++p) {
- fFloatPrecisions[kGeometry_GrShaderType][p] = fFloatPrecisions[kVertex_GrShaderType][p];
- }
- }
-}
-
-
void GrGLCaps::markColorConfigAndStencilFormatAsVerified(
GrPixelConfig config,
const GrGLStencilAttachment::Format& format) {
@@ -1013,7 +874,6 @@ SkString GrGLCaps::dump() const {
r.appendf("Core Profile: %s\n", (fIsCoreProfile ? "YES" : "NO"));
r.appendf("MSAA Type: %s\n", kMSFBOExtStr[fMSFBOType]);
- r.appendf("FB Fetch Support: %s\n", (fFBFetchSupport ? "YES" : "NO"));
r.appendf("Invalidate FB Type: %s\n", kInvalidateFBTypeStr[fInvalidateFBType]);
r.appendf("Map Buffer Type: %s\n", kMapBufferTypeStr[fMapBufferType]);
r.appendf("Max FS Uniform Vectors: %d\n", fMaxFragmentUniformVectors);
@@ -1038,6 +898,214 @@ SkString GrGLCaps::dump() const {
r.appendf("Use non-VBO for dynamic data: %s\n",
(fUseNonVBOVertexAndIndexDynamicData ? "YES" : "NO"));
r.appendf("Full screen clear is free: %s\n", (fFullClearIsFree ? "YES" : "NO"));
+ return r;
+}
+
+////////////////////////////////////////////////////////////////////////////////////////////
+
+GrGLSLCaps::GrGLSLCaps() {
+ this->reset();
+}
+
+
+void GrGLSLCaps::reset() {
+ INHERITED::reset();
+
+ fDropsTileOnZeroDivide = false;
+ fFBFetchSupport = false;
+ fFBFetchNeedsCustomOutput = false;
+ fFBFetchColorName = NULL;
+ fFBFetchExtensionString = NULL;
+}
+
+GrGLSLCaps::GrGLSLCaps(const GrGLSLCaps& caps) : GrShaderCaps() {
+ *this = caps;
+}
+
+GrGLSLCaps& GrGLSLCaps::operator= (const GrGLSLCaps& caps) {
+ INHERITED::operator=(caps);
+ fDropsTileOnZeroDivide = caps.fDropsTileOnZeroDivide;
+ fFBFetchSupport = caps.fFBFetchSupport;
+ fFBFetchNeedsCustomOutput = caps.fFBFetchNeedsCustomOutput;
+ fFBFetchColorName = caps.fFBFetchColorName;
+ fFBFetchExtensionString = caps.fFBFetchExtensionString;
+
+ return *this;
+}
+
+bool GrGLSLCaps::init(const GrGLContextInfo& ctxInfo, const GrGLInterface* gli) {
+ this->reset();
+ if (!ctxInfo.isInitialized()) {
+ return false;
+ }
+
+ GrGLStandard standard = ctxInfo.standard();
+ GrGLVersion version = ctxInfo.version();
+
+ /**************************************************************************
+ * Caps specific to GrGLSLCaps
+ **************************************************************************/
+
+ if (kGLES_GrGLStandard == standard) {
+ if (ctxInfo.hasExtension("GL_EXT_shader_framebuffer_fetch")) {
+ fFBFetchNeedsCustomOutput = (version >= GR_GL_VER(3, 0));
+ fFBFetchSupport = true;
+ fFBFetchColorName = "gl_LastFragData[0]";
+ fFBFetchExtensionString = "GL_EXT_shader_framebuffer_fetch";
+ }
+ else if (ctxInfo.hasExtension("GL_NV_shader_framebuffer_fetch")) {
+ // Actually, we haven't seen an ES3.0 device with this extension yet, so we don't know
+ fFBFetchNeedsCustomOutput = false;
+ fFBFetchSupport = true;
+ fFBFetchColorName = "gl_LastFragData[0]";
+ fFBFetchExtensionString = "GL_NV_shader_framebuffer_fetch";
+ }
+ else if (ctxInfo.hasExtension("GL_ARM_shader_framebuffer_fetch")) {
+ // The arm extension also requires an additional flag which we will set onResetContext
+ fFBFetchNeedsCustomOutput = false;
+ fFBFetchSupport = true;
+ fFBFetchColorName = "gl_LastFragColorARM";
+ fFBFetchExtensionString = "GL_ARM_shader_framebuffer_fetch";
+ }
+ }
+
+ // Adreno GPUs have a tendency to drop tiles when there is a divide-by-zero in a shader
+ fDropsTileOnZeroDivide = kQualcomm_GrGLVendor == ctxInfo.vendor();
+
+ /**************************************************************************
+ * GrShaderCaps fields
+ **************************************************************************/
+
+ fPathRenderingSupport = ctxInfo.hasExtension("GL_NV_path_rendering");
+
+ if (fPathRenderingSupport) {
+ if (kGL_GrGLStandard == standard) {
+ // We only support v1.3+ of GL_NV_path_rendering which allows us to
+ // set individual fragment inputs with ProgramPathFragmentInputGen. The API
+ // additions are detected by checking the existence of the function.
+ fPathRenderingSupport = ctxInfo.hasExtension("GL_EXT_direct_state_access") &&
+ ((ctxInfo.version() >= GR_GL_VER(4, 3) ||
+ ctxInfo.hasExtension("GL_ARB_program_interface_query")) &&
+ gli->fFunctions.fProgramPathFragmentInputGen);
+ }
+ else {
+ fPathRenderingSupport = ctxInfo.version() >= GR_GL_VER(3, 1);
+ }
+ }
+
+ // For now these two are equivalent but we could have dst read in shader via some other method
+ fDstReadInShaderSupport = fFBFetchSupport;
+
+ // Enable supported shader-related caps
+ if (kGL_GrGLStandard == standard) {
+ fDualSourceBlendingSupport = ctxInfo.version() >= GR_GL_VER(3, 3) ||
+ ctxInfo.hasExtension("GL_ARB_blend_func_extended");
+ fShaderDerivativeSupport = true;
+ // we don't support GL_ARB_geometry_shader4, just GL 3.2+ GS
+ fGeometryShaderSupport = ctxInfo.version() >= GR_GL_VER(3, 2) &&
+ ctxInfo.glslGeneration() >= k150_GrGLSLGeneration;
+ }
+ else {
+ fShaderDerivativeSupport = ctxInfo.version() >= GR_GL_VER(3, 0) ||
+ ctxInfo.hasExtension("GL_OES_standard_derivatives");
+ }
+
+ this->initShaderPrecisionTable(ctxInfo, gli);
+
+ return true;
+}
+
+SkString GrGLSLCaps::dump() const {
+ SkString r = INHERITED::dump();
+
+ r.appendf("--- GLSL-Specific ---\n");
+
+ r.appendf("FB Fetch Support: %s\n", (fFBFetchSupport ? "YES" : "NO"));
r.appendf("Drops tile on zero divide: %s\n", (fDropsTileOnZeroDivide ? "YES" : "NO"));
return r;
}
+
+static GrGLenum precision_to_gl_float_type(GrSLPrecision p) {
+ switch (p) {
+ case kLow_GrSLPrecision:
+ return GR_GL_LOW_FLOAT;
+ case kMedium_GrSLPrecision:
+ return GR_GL_MEDIUM_FLOAT;
+ case kHigh_GrSLPrecision:
+ return GR_GL_HIGH_FLOAT;
+ }
+ SkFAIL("Unknown precision.");
+ return -1;
+}
+
+static GrGLenum shader_type_to_gl_shader(GrShaderType type) {
+ switch (type) {
+ case kVertex_GrShaderType:
+ return GR_GL_VERTEX_SHADER;
+ case kGeometry_GrShaderType:
+ return GR_GL_GEOMETRY_SHADER;
+ case kFragment_GrShaderType:
+ return GR_GL_FRAGMENT_SHADER;
+ }
+ SkFAIL("Unknown shader type.");
+ return -1;
+}
+
+void GrGLSLCaps::initShaderPrecisionTable(const GrGLContextInfo& ctxInfo,
+ const GrGLInterface* intf) {
+ if (kGLES_GrGLStandard == ctxInfo.standard() || ctxInfo.version() >= GR_GL_VER(4, 1) ||
+ ctxInfo.hasExtension("GL_ARB_ES2_compatibility")) {
+ for (int s = 0; s < kGrShaderTypeCount; ++s) {
+ if (kGeometry_GrShaderType != s) {
+ GrShaderType shaderType = static_cast<GrShaderType>(s);
+ GrGLenum glShader = shader_type_to_gl_shader(shaderType);
+ PrecisionInfo* first = NULL;
+ fShaderPrecisionVaries = false;
+ for (int p = 0; p < kGrSLPrecisionCount; ++p) {
+ GrSLPrecision precision = static_cast<GrSLPrecision>(p);
+ GrGLenum glPrecision = precision_to_gl_float_type(precision);
+ GrGLint range[2];
+ GrGLint bits;
+ GR_GL_GetShaderPrecisionFormat(intf, glShader, glPrecision, range, &bits);
+ if (bits) {
+ fFloatPrecisions[s][p].fLogRangeLow = range[0];
+ fFloatPrecisions[s][p].fLogRangeHigh = range[1];
+ fFloatPrecisions[s][p].fBits = bits;
+ if (!first) {
+ first = &fFloatPrecisions[s][p];
+ }
+ else if (!fShaderPrecisionVaries) {
+ fShaderPrecisionVaries = (*first != fFloatPrecisions[s][p]);
+ }
+ }
+ }
+ }
+ }
+ }
+ else {
+ // We're on a desktop GL that doesn't have precision info. Assume they're all 32bit float.
+ fShaderPrecisionVaries = false;
+ for (int s = 0; s < kGrShaderTypeCount; ++s) {
+ if (kGeometry_GrShaderType != s) {
+ for (int p = 0; p < kGrSLPrecisionCount; ++p) {
+ fFloatPrecisions[s][p].fLogRangeLow = 127;
+ fFloatPrecisions[s][p].fLogRangeHigh = 127;
+ fFloatPrecisions[s][p].fBits = 23;
+ }
+ }
+ }
+ }
+ // GetShaderPrecisionFormat doesn't accept GL_GEOMETRY_SHADER as a shader type. Assume they're
+ // the same as the vertex shader. Only fragment shaders were ever allowed to omit support for
+ // highp. GS was added after GetShaderPrecisionFormat was added to the list of features that
+ // are recommended against.
+ if (fGeometryShaderSupport) {
+ for (int p = 0; p < kGrSLPrecisionCount; ++p) {
+ fFloatPrecisions[kGeometry_GrShaderType][p] = fFloatPrecisions[kVertex_GrShaderType][p];
+ }
+ }
+}
+
+
+
+
diff --git a/src/gpu/gl/GrGLCaps.h b/src/gpu/gl/GrGLCaps.h
index 954b158809..13ba3863b1 100644
--- a/src/gpu/gl/GrGLCaps.h
+++ b/src/gpu/gl/GrGLCaps.h
@@ -16,6 +16,7 @@
#include "SkTArray.h"
class GrGLContextInfo;
+class GrGLSLCaps;
/**
* Stores some capabilities of a GL context. Most are determined by the GL
@@ -165,19 +166,6 @@ public:
kES_EXT_MsToTexture_MSFBOType == fMSFBOType;
}
- /**
- * Some helper functions for encapsulating various extensions to read FB Buffer on openglES
- *
- * TODO(joshualitt) On desktop opengl 4.2+ we can achieve something similar to this effect
- */
- bool fbFetchSupport() const { return fFBFetchSupport; }
-
- bool fbFetchNeedsCustomOutput() const { return fFBFetchNeedsCustomOutput; }
-
- const char* fbFetchColorName() const { return fFBFetchColorName; }
-
- const char* fbFetchExtensionString() const { return fFBFetchExtensionString; }
-
bool fbMixedSamplesSupport() const { return fFBMixedSamplesSupport; }
InvalidateFBType invalidateFBType() const { return fInvalidateFBType; }
@@ -265,8 +253,6 @@ public:
bool fullClearIsFree() const { return fFullClearIsFree; }
- bool dropsTileOnZeroDivide() const { return fDropsTileOnZeroDivide; }
-
/**
* Returns a string containing the caps info.
*/
@@ -285,6 +271,8 @@ public:
LATCAlias latcAlias() const { return fLATCAlias; }
+ GrGLSLCaps* glslCaps() const { return reinterpret_cast<GrGLSLCaps*>(fShaderCaps.get()); }
+
private:
/**
* Maintains a bit per GrPixelConfig. It is used to avoid redundantly
@@ -329,9 +317,6 @@ private:
void initConfigRenderableTable(const GrGLContextInfo&);
void initConfigTexturableTable(const GrGLContextInfo&, const GrGLInterface*);
- // Must be called after fGeometryShaderSupport is initialized.
- void initShaderPrecisionTable(const GrGLContextInfo&, const GrGLInterface*);
-
bool doReadPixelsSupported(const GrGLInterface* intf, GrGLenum format, GrGLenum type) const;
// tracks configs that have been verified to pass the FBO completeness when
@@ -371,14 +356,8 @@ private:
bool fUseNonVBOVertexAndIndexDynamicData : 1;
bool fIsCoreProfile : 1;
bool fFullClearIsFree : 1;
- bool fDropsTileOnZeroDivide : 1;
- bool fFBFetchSupport : 1;
- bool fFBFetchNeedsCustomOutput : 1;
bool fFBMixedSamplesSupport : 1;
- const char* fFBFetchColorName;
- const char* fFBFetchExtensionString;
-
struct ReadPixelsSupportedFormat {
GrGLenum fFormat;
GrGLenum fType;
@@ -395,6 +374,66 @@ private:
typedef GrDrawTargetCaps INHERITED;
};
-typedef GrGLCaps GrGLSLCaps;
+
+class GrGLSLCaps : public GrShaderCaps {
+public:
+ SK_DECLARE_INST_COUNT(GrGLSLCaps)
+
+ /**
+ * Creates a GrGLSLCaps that advertises no support for any extensions,
+ * formats, etc. Call init to initialize from a GrGLContextInfo.
+ */
+ GrGLSLCaps();
+ ~GrGLSLCaps() override {}
+
+ GrGLSLCaps(const GrGLSLCaps& caps);
+
+ GrGLSLCaps& operator = (const GrGLSLCaps& caps);
+
+ /**
+ * Resets the caps such that nothing is supported.
+ */
+ void reset() override;
+
+ /**
+ * Initializes the GrGLSLCaps to the set of features supported in the current
+ * OpenGL context accessible via ctxInfo.
+ */
+ bool init(const GrGLContextInfo& ctxInfo, const GrGLInterface* glInterface);
+
+ /**
+ * Some helper functions for encapsulating various extensions to read FB Buffer on openglES
+ *
+ * TODO(joshualitt) On desktop opengl 4.2+ we can achieve something similar to this effect
+ */
+ bool fbFetchSupport() const { return fFBFetchSupport; }
+
+ bool fbFetchNeedsCustomOutput() const { return fFBFetchNeedsCustomOutput; }
+
+ const char* fbFetchColorName() const { return fFBFetchColorName; }
+
+ const char* fbFetchExtensionString() const { return fFBFetchExtensionString; }
+
+ bool dropsTileOnZeroDivide() const { return fDropsTileOnZeroDivide; }
+
+ /**
+ * Returns a string containing the caps info.
+ */
+ SkString dump() const override;
+
+private:
+ // Must be called after fGeometryShaderSupport is initialized.
+ void initShaderPrecisionTable(const GrGLContextInfo&, const GrGLInterface*);
+
+ bool fDropsTileOnZeroDivide : 1;
+ bool fFBFetchSupport : 1;
+ bool fFBFetchNeedsCustomOutput : 1;
+
+ const char* fFBFetchColorName;
+ const char* fFBFetchExtensionString;
+
+ typedef GrShaderCaps INHERITED;
+};
+
#endif
diff --git a/src/gpu/gl/GrGLGpu.cpp b/src/gpu/gl/GrGLGpu.cpp
index 9120100966..2c46f9b343 100644
--- a/src/gpu/gl/GrGLGpu.cpp
+++ b/src/gpu/gl/GrGLGpu.cpp
@@ -155,7 +155,7 @@ GrGLGpu::GrGLGpu(const GrGLContext& ctx, GrContext* context)
fTempDstFBOID = 0;
fStencilClearFBOID = 0;
- if (this->glCaps().pathRenderingSupport()) {
+ if (this->glCaps().shaderCaps()->pathRenderingSupport()) {
fPathRendering.reset(new GrGLPathRendering(this));
}
}
@@ -188,7 +188,7 @@ void GrGLGpu::contextAbandoned() {
fTempSrcFBOID = 0;
fTempDstFBOID = 0;
fStencilClearFBOID = 0;
- if (this->glCaps().pathRenderingSupport()) {
+ if (this->glCaps().shaderCaps()->pathRenderingSupport()) {
this->glPathRendering()->abandonGpuResources();
}
}
@@ -335,7 +335,7 @@ void GrGLGpu::onResetContext(uint32_t resetBits) {
}
if (resetBits & kPathRendering_GrGLBackendState) {
- if (this->caps()->pathRenderingSupport()) {
+ if (this->caps()->shaderCaps()->pathRenderingSupport()) {
this->glPathRendering()->resetContext();
}
}
diff --git a/src/gpu/gl/GrGLGpu.h b/src/gpu/gl/GrGLGpu.h
index a8d8c2e71d..d833ca5bf1 100644
--- a/src/gpu/gl/GrGLGpu.h
+++ b/src/gpu/gl/GrGLGpu.h
@@ -46,7 +46,7 @@ public:
const GrGLCaps& glCaps() const { return *fGLContext.caps(); }
GrGLPathRendering* glPathRendering() {
- SkASSERT(glCaps().pathRenderingSupport());
+ SkASSERT(glCaps().shaderCaps()->pathRenderingSupport());
return static_cast<GrGLPathRendering*>(pathRendering());
}
diff --git a/src/gpu/gl/GrGLPathRendering.cpp b/src/gpu/gl/GrGLPathRendering.cpp
index 06f22d0750..8a0b35c661 100644
--- a/src/gpu/gl/GrGLPathRendering.cpp
+++ b/src/gpu/gl/GrGLPathRendering.cpp
@@ -197,7 +197,7 @@ void GrGLPathRendering::drawPaths(const GrPathRange* pathRange,
const void* indices, PathIndexType indexType,
const float transformValues[], PathTransformType transformType,
int count, const GrStencilSettings& stencilSettings) {
- SkASSERT(fGpu->caps()->pathRenderingSupport());
+ SkASSERT(fGpu->caps()->shaderCaps()->pathRenderingSupport());
GrGLuint baseID = static_cast<const GrGLPathRange*>(pathRange)->basePathID();
@@ -260,7 +260,7 @@ void GrGLPathRendering::setProjectionMatrix(const SkMatrix& matrix,
const SkISize& renderTargetSize,
GrSurfaceOrigin renderTargetOrigin) {
- SkASSERT(fGpu->glCaps().pathRenderingSupport());
+ SkASSERT(fGpu->glCaps().shaderCaps()->pathRenderingSupport());
if (renderTargetOrigin == fHWProjectionMatrixState.fRenderTargetOrigin &&
renderTargetSize == fHWProjectionMatrixState.fRenderTargetSize &&
diff --git a/src/gpu/gl/GrGLProgramDesc.cpp b/src/gpu/gl/GrGLProgramDesc.cpp
index af688129ba..34cb11463b 100644
--- a/src/gpu/gl/GrGLProgramDesc.cpp
+++ b/src/gpu/gl/GrGLProgramDesc.cpp
@@ -105,7 +105,7 @@ bool GrGLProgramDescBuilder::Build(GrProgramDesc* desc,
GrProcessorKeyBuilder b(&glDesc->key());
- primProc.getGLProcessorKey(batchTracker, gpu->glCaps(), &b);
+ primProc.getGLProcessorKey(batchTracker, *gpu->glCaps().glslCaps(), &b);
//**** use glslCaps here?
if (!get_meta_key(primProc, gpu->glCaps(), 0, &b)) {
glDesc->key().reset();
@@ -115,7 +115,7 @@ bool GrGLProgramDescBuilder::Build(GrProgramDesc* desc,
for (int s = 0; s < pipeline.numFragmentStages(); ++s) {
const GrPendingFragmentStage& fps = pipeline.getFragmentStage(s);
const GrFragmentProcessor& fp = *fps.processor();
- fp.getGLProcessorKey(gpu->glCaps(), &b);
+ fp.getGLProcessorKey(*gpu->glCaps().glslCaps(), &b);
//**** use glslCaps here?
if (!get_meta_key(fp, gpu->glCaps(), primProc.getTransformKey(fp.coordTransforms()), &b)) {
glDesc->key().reset();
@@ -124,7 +124,7 @@ bool GrGLProgramDescBuilder::Build(GrProgramDesc* desc,
}
const GrXferProcessor& xp = *pipeline.getXferProcessor();
- xp.getGLProcessorKey(gpu->glCaps(), &b);
+ xp.getGLProcessorKey(*gpu->glCaps().glslCaps(), &b);
//**** use glslCaps here?
if (!get_meta_key(xp, gpu->glCaps(), 0, &b)) {
glDesc->key().reset();
diff --git a/src/gpu/gl/builders/GrGLFragmentShaderBuilder.cpp b/src/gpu/gl/builders/GrGLFragmentShaderBuilder.cpp
index c739f1162a..daea878b26 100644
--- a/src/gpu/gl/builders/GrGLFragmentShaderBuilder.cpp
+++ b/src/gpu/gl/builders/GrGLFragmentShaderBuilder.cpp
@@ -39,7 +39,7 @@ static void append_default_precision_qualifier(GrSLPrecision p,
GrGLFragmentShaderBuilder::DstReadKey
GrGLFragmentShaderBuilder::KeyForDstRead(const GrTexture* dstCopy, const GrGLCaps& caps) {
uint32_t key = kYesDstRead_DstReadKeyBit;
- if (caps.fbFetchSupport()) {
+ if (caps.glslCaps()->fbFetchSupport()) {
return key;
}
SkASSERT(dstCopy);
@@ -79,7 +79,7 @@ bool GrGLFragmentShaderBuilder::enableFeature(GLSLFeature feature) {
switch (feature) {
case kStandardDerivatives_GLSLFeature: {
GrGLGpu* gpu = fProgramBuilder->gpu();
- if (!gpu->glCaps().shaderDerivativeSupport()) {
+ if (!gpu->glCaps().shaderCaps()->shaderDerivativeSupport()) {
return false;
}
if (kGLES_GrGLStandard == gpu->glStandard() &&
@@ -166,13 +166,13 @@ const char* GrGLFragmentShaderBuilder::dstColor() {
fHasReadDstColor = true;
GrGLGpu* gpu = fProgramBuilder->gpu();
- if (gpu->glCaps().fbFetchSupport()) {
+ if (gpu->glCaps().glslCaps()->fbFetchSupport()) {
this->addFeature(1 << (GrGLFragmentShaderBuilder::kLastGLSLPrivateFeature + 1),
- gpu->glCaps().fbFetchExtensionString());
+ gpu->glCaps().glslCaps()->fbFetchExtensionString());
// Some versions of this extension string require declaring custom color output on ES 3.0+
- const char* fbFetchColorName = gpu->glCaps().fbFetchColorName();
- if (gpu->glCaps().fbFetchNeedsCustomOutput()) {
+ const char* fbFetchColorName = gpu->glCaps().glslCaps()->fbFetchColorName();
+ if (gpu->glCaps().glslCaps()->fbFetchNeedsCustomOutput()) {
this->enableCustomOutput();
fOutputs[fCustomColorOutputIndex].setTypeModifier(GrShaderVar::kInOut_TypeModifier);
fbFetchColorName = declared_color_output_name();
diff --git a/src/gpu/gl/builders/GrGLProgramBuilder.cpp b/src/gpu/gl/builders/GrGLProgramBuilder.cpp
index e65ea880c3..37ba3dc942 100644
--- a/src/gpu/gl/builders/GrGLProgramBuilder.cpp
+++ b/src/gpu/gl/builders/GrGLProgramBuilder.cpp
@@ -75,7 +75,7 @@ GrGLProgram* GrGLProgramBuilder::CreateProgram(const DrawArgs& args, GrGLGpu* gp
GrGLProgramBuilder* GrGLProgramBuilder::CreateProgramBuilder(const DrawArgs& args,
GrGLGpu* gpu) {
if (args.fPrimitiveProcessor->isPathRendering()) {
- SkASSERT(gpu->glCaps().pathRenderingSupport() &&
+ SkASSERT(gpu->glCaps().shaderCaps()->pathRenderingSupport() &&
!args.fPrimitiveProcessor->willUseGeoShader() &&
args.fPrimitiveProcessor->numAttribs() == 0);
return SkNEW_ARGS(GrGLNvprProgramBuilder, (gpu, args));
@@ -302,7 +302,7 @@ void GrGLProgramBuilder::emitAndInstallProc(const GrPrimitiveProcessor& gp,
fGeometryProcessor = SkNEW(GrGLInstalledGeoProc);
const GrBatchTracker& bt = this->batchTracker();
- fGeometryProcessor->fGLProc.reset(gp.createGLInstance(bt, fGpu->glCaps()));
+ fGeometryProcessor->fGLProc.reset(gp.createGLInstance(bt, *fGpu->glCaps().glslCaps()));
SkSTArray<4, GrGLProcessor::TextureSampler> samplers(gp.numTextures());
this->emitSamplers(gp, &samplers, fGeometryProcessor);