GrGLProgram.cpp revision 261dc569b6a53729bea6e4e7a0cf2afa980eb82d
1/*
2 * Copyright 2011 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
8#include "GrGLProgram.h"
9
10#include "GrAllocator.h"
11#include "GrEffect.h"
12#include "GrCoordTransform.h"
13#include "GrDrawEffect.h"
14#include "GrGLEffect.h"
15#include "GrGpuGL.h"
16#include "GrGLShaderVar.h"
17#include "GrGLSL.h"
18#include "SkXfermode.h"
19
20SK_DEFINE_INST_COUNT(GrGLProgram)
21
22#define GL_CALL(X) GR_GL_CALL(fGpu->glInterface(), X)
23#define GL_CALL_RET(R, X) GR_GL_CALL_RET(fGpu->glInterface(), R, X)
24
25GrGLProgram* GrGLProgram::Create(GrGpuGL* gpu,
26                                 const GrGLProgramDesc& desc,
27                                 const GrEffectStage* colorStages[],
28                                 const GrEffectStage* coverageStages[]) {
29    GrGLProgram* program = SkNEW_ARGS(GrGLProgram, (gpu, desc, colorStages, coverageStages));
30    if (!program->succeeded()) {
31        delete program;
32        program = NULL;
33    }
34    return program;
35}
36
37GrGLProgram::GrGLProgram(GrGpuGL* gpu,
38                         const GrGLProgramDesc& desc,
39                         const GrEffectStage* colorStages[],
40                         const GrEffectStage* coverageStages[])
41: fGpu(gpu)
42, fUniformManager(gpu) {
43    fDesc = desc;
44    fProgramID = 0;
45
46    fDstCopyTexUnit = -1;
47
48    fColor = GrColor_ILLEGAL;
49    fColorFilterColor = GrColor_ILLEGAL;
50
51    this->genProgram(colorStages, coverageStages);
52}
53
54GrGLProgram::~GrGLProgram() {
55    if (fProgramID) {
56        GL_CALL(DeleteProgram(fProgramID));
57    }
58}
59
60void GrGLProgram::abandon() {
61    fProgramID = 0;
62}
63
64void GrGLProgram::overrideBlend(GrBlendCoeff* srcCoeff,
65                                GrBlendCoeff* dstCoeff) const {
66    switch (fDesc.getHeader().fCoverageOutput) {
67        case GrGLProgramDesc::kModulate_CoverageOutput:
68            break;
69        // The prog will write a coverage value to the secondary
70        // output and the dst is blended by one minus that value.
71        case GrGLProgramDesc::kSecondaryCoverage_CoverageOutput:
72        case GrGLProgramDesc::kSecondaryCoverageISA_CoverageOutput:
73        case GrGLProgramDesc::kSecondaryCoverageISC_CoverageOutput:
74            *dstCoeff = (GrBlendCoeff)GrGpu::kIS2C_GrBlendCoeff;
75            break;
76        case GrGLProgramDesc::kCombineWithDst_CoverageOutput:
77            // We should only have set this if the blend was specified as (1, 0)
78            SkASSERT(kOne_GrBlendCoeff == *srcCoeff && kZero_GrBlendCoeff == *dstCoeff);
79            break;
80        default:
81            GrCrash("Unexpected coverage output");
82            break;
83    }
84}
85
86namespace {
87// given two blend coefficients determine whether the src
88// and/or dst computation can be omitted.
89inline void need_blend_inputs(SkXfermode::Coeff srcCoeff,
90                              SkXfermode::Coeff dstCoeff,
91                              bool* needSrcValue,
92                              bool* needDstValue) {
93    if (SkXfermode::kZero_Coeff == srcCoeff) {
94        switch (dstCoeff) {
95            // these all read the src
96            case SkXfermode::kSC_Coeff:
97            case SkXfermode::kISC_Coeff:
98            case SkXfermode::kSA_Coeff:
99            case SkXfermode::kISA_Coeff:
100                *needSrcValue = true;
101                break;
102            default:
103                *needSrcValue = false;
104                break;
105        }
106    } else {
107        *needSrcValue = true;
108    }
109    if (SkXfermode::kZero_Coeff == dstCoeff) {
110        switch (srcCoeff) {
111            // these all read the dst
112            case SkXfermode::kDC_Coeff:
113            case SkXfermode::kIDC_Coeff:
114            case SkXfermode::kDA_Coeff:
115            case SkXfermode::kIDA_Coeff:
116                *needDstValue = true;
117                break;
118            default:
119                *needDstValue = false;
120                break;
121        }
122    } else {
123        *needDstValue = true;
124    }
125}
126
127/**
128 * Create a blend_coeff * value string to be used in shader code. Sets empty
129 * string if result is trivially zero.
130 */
131inline void blend_term_string(SkString* str, SkXfermode::Coeff coeff,
132                       const char* src, const char* dst,
133                       const char* value) {
134    switch (coeff) {
135    case SkXfermode::kZero_Coeff:    /** 0 */
136        *str = "";
137        break;
138    case SkXfermode::kOne_Coeff:     /** 1 */
139        *str = value;
140        break;
141    case SkXfermode::kSC_Coeff:
142        str->printf("(%s * %s)", src, value);
143        break;
144    case SkXfermode::kISC_Coeff:
145        str->printf("((%s - %s) * %s)", GrGLSLOnesVecf(4), src, value);
146        break;
147    case SkXfermode::kDC_Coeff:
148        str->printf("(%s * %s)", dst, value);
149        break;
150    case SkXfermode::kIDC_Coeff:
151        str->printf("((%s - %s) * %s)", GrGLSLOnesVecf(4), dst, value);
152        break;
153    case SkXfermode::kSA_Coeff:      /** src alpha */
154        str->printf("(%s.a * %s)", src, value);
155        break;
156    case SkXfermode::kISA_Coeff:     /** inverse src alpha (i.e. 1 - sa) */
157        str->printf("((1.0 - %s.a) * %s)", src, value);
158        break;
159    case SkXfermode::kDA_Coeff:      /** dst alpha */
160        str->printf("(%s.a * %s)", dst, value);
161        break;
162    case SkXfermode::kIDA_Coeff:     /** inverse dst alpha (i.e. 1 - da) */
163        str->printf("((1.0 - %s.a) * %s)", dst, value);
164        break;
165    default:
166        GrCrash("Unexpected xfer coeff.");
167        break;
168    }
169}
170/**
171 * Adds a line to the fragment shader code which modifies the color by
172 * the specified color filter.
173 */
174void add_color_filter(GrGLShaderBuilder* builder,
175                      const char * outputVar,
176                      SkXfermode::Coeff uniformCoeff,
177                      SkXfermode::Coeff colorCoeff,
178                      const char* filterColor,
179                      const char* inColor) {
180    SkString colorStr, constStr;
181    blend_term_string(&colorStr, colorCoeff, filterColor, inColor, inColor);
182    blend_term_string(&constStr, uniformCoeff, filterColor, inColor, filterColor);
183
184    SkString sum;
185    GrGLSLAddf<4>(&sum, colorStr.c_str(), constStr.c_str());
186    builder->fsCodeAppendf("\t%s = %s;\n", outputVar, sum.c_str());
187}
188}
189
190namespace {
191
192void expand_known_value4f(SkString* string, GrSLConstantVec vec) {
193    SkASSERT(string->isEmpty() == (vec != kNone_GrSLConstantVec));
194    switch (vec) {
195        case kNone_GrSLConstantVec:
196            break;
197        case kZeros_GrSLConstantVec:
198            *string = GrGLSLZerosVecf(4);
199            break;
200        case kOnes_GrSLConstantVec:
201            *string = GrGLSLOnesVecf(4);
202            break;
203    }
204}
205
206}
207
208bool GrGLProgram::genProgram(const GrEffectStage* colorStages[],
209                             const GrEffectStage* coverageStages[]) {
210    SkASSERT(0 == fProgramID);
211
212    const GrGLProgramDesc::KeyHeader& header = fDesc.getHeader();
213
214    GrGLFullShaderBuilder builder(fGpu, fUniformManager, fDesc);
215    fUniformHandles.fViewMatrixUni = builder.getViewMatrixUniform();
216
217    // incoming color to current stage being processed.
218    SkString inColor = builder.getInputColor();
219    GrSLConstantVec knownColorValue = builder.getKnownColorValue();
220
221    // Get the coeffs for the Mode-based color filter, determine if color is needed.
222    SkXfermode::Coeff colorCoeff;
223    SkXfermode::Coeff filterColorCoeff;
224    SkAssertResult(
225        SkXfermode::ModeAsCoeff(header.fColorFilterXfermode,
226                                &filterColorCoeff,
227                                &colorCoeff));
228    bool needColor, needFilterColor;
229    need_blend_inputs(filterColorCoeff, colorCoeff, &needFilterColor, &needColor);
230
231    fColorEffects.reset(
232        builder.createAndEmitEffects(colorStages,
233                                     fDesc.effectKeys(),
234                                     needColor ? fDesc.numColorEffects() : 0,
235                                     &inColor,
236                                     &knownColorValue));
237
238    // Insert the color filter. This will soon be replaced by a color effect.
239    if (SkXfermode::kDst_Mode != header.fColorFilterXfermode) {
240        const char* colorFilterColorUniName = NULL;
241        fUniformHandles.fColorFilterUni = builder.addUniform(GrGLShaderBuilder::kFragment_Visibility,
242                                                             kVec4f_GrSLType, "FilterColor",
243                                                             &colorFilterColorUniName);
244
245        builder.fsCodeAppend("\tvec4 filteredColor;\n");
246        const char* color;
247        // add_color_filter requires a real input string.
248        if (knownColorValue == kOnes_GrSLConstantVec) {
249            color = GrGLSLOnesVecf(4);
250        } else if (knownColorValue == kZeros_GrSLConstantVec) {
251            color = GrGLSLZerosVecf(4);
252        } else {
253            color = inColor.c_str();
254        }
255        add_color_filter(&builder, "filteredColor", filterColorCoeff,
256                         colorCoeff, colorFilterColorUniName, color);
257        inColor = "filteredColor";
258    }
259
260    ///////////////////////////////////////////////////////////////////////////
261    // compute the partial coverage
262    SkString inCoverage = builder.getInputCoverage();
263    GrSLConstantVec knownCoverageValue = builder.getKnownCoverageValue();
264
265    fCoverageEffects.reset(
266        builder.createAndEmitEffects(coverageStages,
267                                     fDesc.getEffectKeys() + fDesc.numColorEffects(),
268                                     fDesc.numCoverageEffects(),
269                                     &inCoverage,
270                                     &knownCoverageValue));
271
272    // discard if coverage is zero
273    if (header.fDiscardIfZeroCoverage && kOnes_GrSLConstantVec != knownCoverageValue) {
274        if (kZeros_GrSLConstantVec == knownCoverageValue) {
275            // This is unfortunate.
276            builder.fsCodeAppend("\tdiscard;\n");
277        } else {
278            builder.fsCodeAppendf("\tif (all(lessThanEqual(%s, vec4(0.0)))) {\n\t\tdiscard;\n\t}\n",
279                                  inCoverage.c_str());
280        }
281    }
282
283    if (GrGLProgramDesc::CoverageOutputUsesSecondaryOutput(header.fCoverageOutput)) {
284        const char* secondaryOutputName = builder.enableSecondaryOutput();
285
286        // default coeff to ones for kCoverage_DualSrcOutput
287        SkString coeff;
288        GrSLConstantVec knownCoeffValue = kOnes_GrSLConstantVec;
289        if (GrGLProgramDesc::kSecondaryCoverageISA_CoverageOutput == header.fCoverageOutput) {
290            // Get (1-A) into coeff
291            SkString inColorAlpha;
292            GrGLSLGetComponent4f(&inColorAlpha,
293                                    inColor.c_str(),
294                                    kA_GrColorComponentFlag,
295                                    knownColorValue,
296                                    true);
297            knownCoeffValue = GrGLSLSubtractf<1>(&coeff,
298                                                 NULL,
299                                                 inColorAlpha.c_str(),
300                                                 kOnes_GrSLConstantVec,
301                                                 knownColorValue,
302                                                 true);
303        } else if (GrGLProgramDesc::kSecondaryCoverageISC_CoverageOutput == header.fCoverageOutput) {
304            // Get (1-RGBA) into coeff
305            knownCoeffValue = GrGLSLSubtractf<4>(&coeff,
306                                                 NULL,
307                                                 inColor.c_str(),
308                                                 kOnes_GrSLConstantVec,
309                                                 knownColorValue,
310                                                 true);
311        }
312        // Get coeff * coverage into modulate and then write that to the dual source output.
313        SkString modulate;
314        GrGLSLModulatef<4>(&modulate,
315                           coeff.c_str(),
316                           inCoverage.c_str(),
317                           knownCoeffValue,
318                           knownCoverageValue,
319                           false);
320        builder.fsCodeAppendf("\t%s = %s;\n", secondaryOutputName, modulate.c_str());
321    }
322
323    ///////////////////////////////////////////////////////////////////////////
324    // combine color and coverage as frag color
325
326    // Get "color * coverage" into fragColor
327    SkString fragColor;
328    GrSLConstantVec knownFragColorValue = GrGLSLModulatef<4>(&fragColor,
329                                                             inColor.c_str(),
330                                                             inCoverage.c_str(),
331                                                             knownColorValue,
332                                                             knownCoverageValue,
333                                                             true);
334    // Now tack on "+(1-coverage)dst onto the frag color if we were asked to do so.
335    if (GrGLProgramDesc::kCombineWithDst_CoverageOutput == header.fCoverageOutput) {
336        SkString dstCoeff;
337        GrSLConstantVec knownDstCoeffValue = GrGLSLSubtractf<4>(&dstCoeff,
338                                                                NULL,
339                                                                inCoverage.c_str(),
340                                                                kOnes_GrSLConstantVec,
341                                                                knownCoverageValue,
342                                                                true);
343        SkString dstContribution;
344        GrSLConstantVec knownDstContributionValue = GrGLSLModulatef<4>(&dstContribution,
345                                                                       dstCoeff.c_str(),
346                                                                       builder.dstColor(),
347                                                                       knownDstCoeffValue,
348                                                                       kNone_GrSLConstantVec,
349                                                                       true);
350        SkString oldFragColor = fragColor;
351        fragColor.reset();
352        GrGLSLAddf<4>(&fragColor,
353                      oldFragColor.c_str(),
354                      dstContribution.c_str(),
355                      knownFragColorValue,
356                      knownDstContributionValue,
357                      false);
358    } else {
359        expand_known_value4f(&fragColor, knownFragColorValue);
360    }
361    builder.fsCodeAppendf("\t%s = %s;\n", builder.getColorOutputName(), fragColor.c_str());
362
363    if (!builder.finish(&fProgramID)) {
364        return false;
365    }
366
367    fUniformHandles.fRTHeightUni = builder.getRTHeightUniform();
368    fUniformHandles.fDstCopyTopLeftUni = builder.getDstCopyTopLeftUniform();
369    fUniformHandles.fDstCopyScaleUni = builder.getDstCopyScaleUniform();
370    fUniformHandles.fColorUni = builder.getColorUniform();
371    fUniformHandles.fCoverageUni = builder.getCoverageUniform();
372    fUniformHandles.fDstCopySamplerUni = builder.getDstCopySamplerUniform();
373    // This must be called after we set fDstCopySamplerUni above.
374    this->initSamplerUniforms();
375
376    return true;
377}
378
379void GrGLProgram::initSamplerUniforms() {
380    GL_CALL(UseProgram(fProgramID));
381    GrGLint texUnitIdx = 0;
382    if (fUniformHandles.fDstCopySamplerUni.isValid()) {
383        fUniformManager.setSampler(fUniformHandles.fDstCopySamplerUni, texUnitIdx);
384        fDstCopyTexUnit = texUnitIdx++;
385    }
386    fColorEffects->initSamplers(fUniformManager, &texUnitIdx);
387    fCoverageEffects->initSamplers(fUniformManager, &texUnitIdx);
388}
389
390///////////////////////////////////////////////////////////////////////////////
391
392void GrGLProgram::setData(GrDrawState::BlendOptFlags blendOpts,
393                          const GrEffectStage* colorStages[],
394                          const GrEffectStage* coverageStages[],
395                          const GrDeviceCoordTexture* dstCopy,
396                          SharedGLState* sharedState) {
397    const GrDrawState& drawState = fGpu->getDrawState();
398
399    GrColor color;
400    GrColor coverage;
401    if (blendOpts & GrDrawState::kEmitTransBlack_BlendOptFlag) {
402        color = 0;
403        coverage = 0;
404    } else if (blendOpts & GrDrawState::kEmitCoverage_BlendOptFlag) {
405        color = 0xffffffff;
406        coverage = drawState.getCoverage();
407    } else {
408        color = drawState.getColor();
409        coverage = drawState.getCoverage();
410    }
411
412    this->setColor(drawState, color, sharedState);
413    this->setCoverage(drawState, coverage, sharedState);
414    this->setMatrixAndRenderTargetHeight(drawState);
415
416    // Setup the SkXfermode::Mode-based colorfilter uniform if necessary
417    if (fUniformHandles.fColorFilterUni.isValid() &&
418        fColorFilterColor != drawState.getColorFilterColor()) {
419        GrGLfloat c[4];
420        GrColorToRGBAFloat(drawState.getColorFilterColor(), c);
421        fUniformManager.set4fv(fUniformHandles.fColorFilterUni, 0, 1, c);
422        fColorFilterColor = drawState.getColorFilterColor();
423    }
424
425    if (NULL != dstCopy) {
426        if (fUniformHandles.fDstCopyTopLeftUni.isValid()) {
427            fUniformManager.set2f(fUniformHandles.fDstCopyTopLeftUni,
428                                  static_cast<GrGLfloat>(dstCopy->offset().fX),
429                                  static_cast<GrGLfloat>(dstCopy->offset().fY));
430            fUniformManager.set2f(fUniformHandles.fDstCopyScaleUni,
431                                  1.f / dstCopy->texture()->width(),
432                                  1.f / dstCopy->texture()->height());
433            GrGLTexture* texture = static_cast<GrGLTexture*>(dstCopy->texture());
434            static GrTextureParams kParams; // the default is clamp, nearest filtering.
435            fGpu->bindTexture(fDstCopyTexUnit, kParams, texture);
436        } else {
437            SkASSERT(!fUniformHandles.fDstCopyScaleUni.isValid());
438            SkASSERT(!fUniformHandles.fDstCopySamplerUni.isValid());
439        }
440    } else {
441        SkASSERT(!fUniformHandles.fDstCopyTopLeftUni.isValid());
442        SkASSERT(!fUniformHandles.fDstCopyScaleUni.isValid());
443        SkASSERT(!fUniformHandles.fDstCopySamplerUni.isValid());
444    }
445
446    fColorEffects->setData(fGpu, fUniformManager, colorStages);
447    fCoverageEffects->setData(fGpu, fUniformManager, coverageStages);
448}
449
450void GrGLProgram::setColor(const GrDrawState& drawState,
451                           GrColor color,
452                           SharedGLState* sharedState) {
453    const GrGLProgramDesc::KeyHeader& header = fDesc.getHeader();
454    if (!drawState.hasColorVertexAttribute()) {
455        switch (header.fColorInput) {
456            case GrGLProgramDesc::kAttribute_ColorInput:
457                SkASSERT(-1 != header.fColorAttributeIndex);
458                if (sharedState->fConstAttribColor != color ||
459                    sharedState->fConstAttribColorIndex != header.fColorAttributeIndex) {
460                    // OpenGL ES only supports the float varieties of glVertexAttrib
461                    GrGLfloat c[4];
462                    GrColorToRGBAFloat(color, c);
463                    GL_CALL(VertexAttrib4fv(header.fColorAttributeIndex, c));
464                    sharedState->fConstAttribColor = color;
465                    sharedState->fConstAttribColorIndex = header.fColorAttributeIndex;
466                }
467                break;
468            case GrGLProgramDesc::kUniform_ColorInput:
469                if (fColor != color) {
470                    // OpenGL ES doesn't support unsigned byte varieties of glUniform
471                    GrGLfloat c[4];
472                    GrColorToRGBAFloat(color, c);
473                    fUniformManager.set4fv(fUniformHandles.fColorUni, 0, 1, c);
474                    fColor = color;
475                }
476                sharedState->fConstAttribColorIndex = -1;
477                break;
478            case GrGLProgramDesc::kSolidWhite_ColorInput:
479            case GrGLProgramDesc::kTransBlack_ColorInput:
480                sharedState->fConstAttribColorIndex = -1;
481                break;
482            default:
483                GrCrash("Unknown color type.");
484        }
485    } else {
486        sharedState->fConstAttribColorIndex = -1;
487    }
488}
489
490void GrGLProgram::setCoverage(const GrDrawState& drawState,
491                              GrColor coverage,
492                              SharedGLState* sharedState) {
493    const GrGLProgramDesc::KeyHeader& header = fDesc.getHeader();
494    if (!drawState.hasCoverageVertexAttribute()) {
495        switch (header.fCoverageInput) {
496            case GrGLProgramDesc::kAttribute_ColorInput:
497                if (sharedState->fConstAttribCoverage != coverage ||
498                    sharedState->fConstAttribCoverageIndex != header.fCoverageAttributeIndex) {
499                    // OpenGL ES only supports the float varieties of  glVertexAttrib
500                    GrGLfloat c[4];
501                    GrColorToRGBAFloat(coverage, c);
502                    GL_CALL(VertexAttrib4fv(header.fCoverageAttributeIndex, c));
503                    sharedState->fConstAttribCoverage = coverage;
504                    sharedState->fConstAttribCoverageIndex = header.fCoverageAttributeIndex;
505                }
506                break;
507            case GrGLProgramDesc::kUniform_ColorInput:
508                if (fCoverage != coverage) {
509                    // OpenGL ES doesn't support unsigned byte varieties of glUniform
510                    GrGLfloat c[4];
511                    GrColorToRGBAFloat(coverage, c);
512                    fUniformManager.set4fv(fUniformHandles.fCoverageUni, 0, 1, c);
513                    fCoverage = coverage;
514                }
515                sharedState->fConstAttribCoverageIndex = -1;
516                break;
517            case GrGLProgramDesc::kSolidWhite_ColorInput:
518            case GrGLProgramDesc::kTransBlack_ColorInput:
519                sharedState->fConstAttribCoverageIndex = -1;
520                break;
521            default:
522                GrCrash("Unknown coverage type.");
523        }
524    } else {
525        sharedState->fConstAttribCoverageIndex = -1;
526    }
527}
528
529void GrGLProgram::setMatrixAndRenderTargetHeight(const GrDrawState& drawState) {
530    const GrRenderTarget* rt = drawState.getRenderTarget();
531    SkISize size;
532    size.set(rt->width(), rt->height());
533
534    // Load the RT height uniform if it is needed to y-flip gl_FragCoord.
535    if (fUniformHandles.fRTHeightUni.isValid() &&
536        fMatrixState.fRenderTargetSize.fHeight != size.fHeight) {
537        fUniformManager.set1f(fUniformHandles.fRTHeightUni, SkIntToScalar(size.fHeight));
538    }
539
540    if (fMatrixState.fRenderTargetOrigin != rt->origin() ||
541        !fMatrixState.fViewMatrix.cheapEqualTo(drawState.getViewMatrix()) ||
542        fMatrixState.fRenderTargetSize != size) {
543
544        fMatrixState.fViewMatrix = drawState.getViewMatrix();
545        fMatrixState.fRenderTargetSize = size;
546        fMatrixState.fRenderTargetOrigin = rt->origin();
547
548        GrGLfloat viewMatrix[3 * 3];
549        fMatrixState.getGLMatrix<3>(viewMatrix);
550        fUniformManager.setMatrix3f(fUniformHandles.fViewMatrixUni, viewMatrix);
551    }
552}
553