| Index: src/gpu/glsl/GrGLSLFragmentShaderBuilder.cpp
|
| diff --git a/src/gpu/glsl/GrGLSLFragmentShaderBuilder.cpp b/src/gpu/glsl/GrGLSLFragmentShaderBuilder.cpp
|
| index bd0108407f076d5fce9ee45e2dcba8c80939107a..1d1b7b9832ac9a1747bb2f80539b96b5c3500658 100644
|
| --- a/src/gpu/glsl/GrGLSLFragmentShaderBuilder.cpp
|
| +++ b/src/gpu/glsl/GrGLSLFragmentShaderBuilder.cpp
|
| @@ -7,6 +7,7 @@
|
|
|
| #include "GrGLSLFragmentShaderBuilder.h"
|
| #include "GrRenderTarget.h"
|
| +#include "GrRenderTargetPriv.h"
|
| #include "gl/GrGLGpu.h"
|
| #include "glsl/GrGLSL.h"
|
| #include "glsl/GrGLSLCaps.h"
|
| @@ -16,6 +17,18 @@
|
|
|
| const char* GrGLSLFragmentShaderBuilder::kDstTextureColorName = "_dstColor";
|
|
|
| +static const char* sample_offset_array_name(GrGLSLFPFragmentBuilder::Coordinates coords) {
|
| + static const char* kArrayNames[] = {
|
| + "deviceSpaceSampleOffsets",
|
| + "windowSpaceSampleOffsets"
|
| + };
|
| + return kArrayNames[coords];
|
| +
|
| + GR_STATIC_ASSERT(0 == GrGLSLFPFragmentBuilder::kSkiaDevice_Coordinates);
|
| + GR_STATIC_ASSERT(1 == GrGLSLFPFragmentBuilder::kGLSLWindow_Coordinates);
|
| + GR_STATIC_ASSERT(SK_ARRAY_COUNT(kArrayNames) == GrGLSLFPFragmentBuilder::kLast_Coordinates + 1);
|
| +}
|
| +
|
| static const char* specific_layout_qualifier_name(GrBlendEquation equation) {
|
| SkASSERT(GrBlendEquationIsAdvanced(equation));
|
|
|
| @@ -57,23 +70,21 @@ static const char* specific_layout_qualifier_name(GrBlendEquation equation) {
|
| kGrBlendEquationCnt - kFirstAdvancedGrBlendEquation);
|
| }
|
|
|
| -GrGLSLFragmentShaderBuilder::FragPosKey
|
| -GrGLSLFragmentShaderBuilder::KeyForFragmentPosition(const GrRenderTarget* dst) {
|
| - if (kTopLeft_GrSurfaceOrigin == dst->origin()) {
|
| - return kTopLeftFragPosRead_FragPosKey;
|
| - } else {
|
| - return kBottomLeftFragPosRead_FragPosKey;
|
| - }
|
| +uint8_t GrGLSLFragmentShaderBuilder::KeyForSurfaceOrigin(GrSurfaceOrigin origin) {
|
| + SkASSERT(kTopLeft_GrSurfaceOrigin == origin || kBottomLeft_GrSurfaceOrigin == origin);
|
| + return origin;
|
| +
|
| + GR_STATIC_ASSERT(1 == kTopLeft_GrSurfaceOrigin);
|
| + GR_STATIC_ASSERT(2 == kBottomLeft_GrSurfaceOrigin);
|
| }
|
|
|
| -GrGLSLFragmentShaderBuilder::GrGLSLFragmentShaderBuilder(GrGLSLProgramBuilder* program,
|
| - uint8_t fragPosKey)
|
| +GrGLSLFragmentShaderBuilder::GrGLSLFragmentShaderBuilder(GrGLSLProgramBuilder* program)
|
| : GrGLSLFragmentBuilder(program)
|
| , fSetupFragPosition(false)
|
| - , fTopLeftFragPosRead(kTopLeftFragPosRead_FragPosKey == fragPosKey)
|
| , fHasCustomColorOutput(false)
|
| , fCustomColorOutputIndex(-1)
|
| , fHasSecondaryOutput(false)
|
| + , fUsedSampleOffsetArrays(0)
|
| , fHasInitializedSampleMask(false) {
|
| fSubstageIndices.push_back(0);
|
| #ifdef SK_DEBUG
|
| @@ -82,10 +93,6 @@ GrGLSLFragmentShaderBuilder::GrGLSLFragmentShaderBuilder(GrGLSLProgramBuilder* p
|
| #endif
|
| }
|
|
|
| -bool GrGLSLFragmentShaderBuilder::hasFragmentPosition() const {
|
| - return 0 != fProgramBuilder->header().fFragPosKey;
|
| -}
|
| -
|
| bool GrGLSLFragmentShaderBuilder::enableFeature(GLSLFeature feature) {
|
| switch (feature) {
|
| case kStandardDerivatives_GLSLFeature: {
|
| @@ -129,14 +136,13 @@ SkString GrGLSLFragmentShaderBuilder::ensureFSCoords2D(const GrGLSLTransformedCo
|
| }
|
|
|
| const char* GrGLSLFragmentShaderBuilder::fragmentPosition() {
|
| - SkASSERT(this->hasFragmentPosition());
|
| SkDEBUGCODE(fUsedProcessorFeatures |= GrProcessor::kFragmentPosition_RequiredFeature;)
|
|
|
| const GrGLSLCaps* glslCaps = fProgramBuilder->glslCaps();
|
| // We only declare "gl_FragCoord" when we're in the case where we want to use layout qualifiers
|
| // to reverse y. Otherwise it isn't necessary and whether the "in" qualifier appears in the
|
| // declaration varies in earlier GLSL specs. So it is simpler to omit it.
|
| - if (fTopLeftFragPosRead) {
|
| + if (kTopLeft_GrSurfaceOrigin == this->getSurfaceOrigin()) {
|
| fSetupFragPosition = true;
|
| return "gl_FragCoord";
|
| } else if (const char* extension = glslCaps->fragCoordConventionsExtensionString()) {
|
| @@ -177,6 +183,17 @@ const char* GrGLSLFragmentShaderBuilder::fragmentPosition() {
|
| }
|
| }
|
|
|
| +void GrGLSLFragmentShaderBuilder::appendOffsetToSample(const char* sampleIdx, Coordinates coords) {
|
| + SkASSERT(fProgramBuilder->header().fSamplePatternKey);
|
| + SkDEBUGCODE(fUsedProcessorFeatures |= GrProcessor::kSampleLocations_RequiredFeature);
|
| + if (kTopLeft_GrSurfaceOrigin == this->getSurfaceOrigin()) {
|
| + // With a top left origin, device and window space are equal, so we only use device coords.
|
| + coords = kSkiaDevice_Coordinates;
|
| + }
|
| + this->codeAppendf("%s[%s]", sample_offset_array_name(coords), sampleIdx);
|
| + fUsedSampleOffsetArrays |= (1 << coords);
|
| +}
|
| +
|
| void GrGLSLFragmentShaderBuilder::maskSampleCoverage(const char* mask, bool invert) {
|
| const GrGLSLCaps& glslCaps = *fProgramBuilder->glslCaps();
|
| if (!glslCaps.sampleVariablesSupport()) {
|
| @@ -308,11 +325,50 @@ const char* GrGLSLFragmentShaderBuilder::getSecondaryColorOutputName() const {
|
| : "gl_SecondaryFragColorEXT";
|
| }
|
|
|
| +GrSurfaceOrigin GrGLSLFragmentShaderBuilder::getSurfaceOrigin() const {
|
| + SkASSERT(fProgramBuilder->header().fSurfaceOriginKey);
|
| + return static_cast<GrSurfaceOrigin>(fProgramBuilder->header().fSurfaceOriginKey);
|
| +
|
| + GR_STATIC_ASSERT(1 == kTopLeft_GrSurfaceOrigin);
|
| + GR_STATIC_ASSERT(2 == kBottomLeft_GrSurfaceOrigin);
|
| +}
|
| +
|
| void GrGLSLFragmentShaderBuilder::onFinalize() {
|
| fProgramBuilder->varyingHandler()->getFragDecls(&this->inputs(), &this->outputs());
|
| GrGLSLAppendDefaultFloatPrecisionDeclaration(kDefault_GrSLPrecision,
|
| *fProgramBuilder->glslCaps(),
|
| &this->precisionQualifier());
|
| + if (fUsedSampleOffsetArrays & (1 << kSkiaDevice_Coordinates)) {
|
| + this->defineSampleOffsetArray(sample_offset_array_name(kSkiaDevice_Coordinates),
|
| + SkMatrix::MakeTrans(-0.5f, -0.5f));
|
| + }
|
| + if (fUsedSampleOffsetArrays & (1 << kGLSLWindow_Coordinates)) {
|
| + // With a top left origin, device and window space are equal, so we only use device coords.
|
| + SkASSERT(kBottomLeft_GrSurfaceOrigin == this->getSurfaceOrigin());
|
| + SkMatrix m;
|
| + m.setScale(1, -1);
|
| + m.preTranslate(-0.5f, -0.5f);
|
| + this->defineSampleOffsetArray(sample_offset_array_name(kGLSLWindow_Coordinates), m);
|
| + }
|
| +}
|
| +
|
| +void GrGLSLFragmentShaderBuilder::defineSampleOffsetArray(const char* name, const SkMatrix& m) {
|
| + SkASSERT(fProgramBuilder->caps()->sampleLocationsSupport());
|
| + const GrPipeline& pipeline = fProgramBuilder->pipeline();
|
| + const GrRenderTargetPriv& rtp = pipeline.getRenderTarget()->renderTargetPriv();
|
| + const GrGpu::MultisampleSpecs& specs = rtp.getMultisampleSpecs(pipeline.getStencil());
|
| + SkSTArray<16, SkPoint, true> offsets;
|
| + offsets.push_back_n(specs.fEffectiveSampleCnt);
|
| + m.mapPoints(offsets.begin(), specs.fSampleLocations.get(), specs.fEffectiveSampleCnt);
|
| + this->definitions().append("const ");
|
| + if (fProgramBuilder->glslCaps()->usesPrecisionModifiers()) {
|
| + this->definitions().append("highp ");
|
| + }
|
| + this->definitions().appendf("vec2 %s[] = vec2[](", name);
|
| + for (int i = 0; i < specs.fEffectiveSampleCnt; ++i) {
|
| + this->definitions().appendf("vec2(%f, %f)", offsets[i].x(), offsets[i].y());
|
| + this->definitions().append(i + 1 != specs.fEffectiveSampleCnt ? ", " : ");\n");
|
| + }
|
| }
|
|
|
| void GrGLSLFragmentShaderBuilder::onBeforeChildProcEmitCode() {
|
|
|