Home | History | Annotate | Download | only in gl
      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 "builders/GrGLFullProgramBuilder.h"
     11 #include "builders/GrGLFragmentOnlyProgramBuilder.h"
     12 #include "GrAllocator.h"
     13 #include "GrProcessor.h"
     14 #include "GrCoordTransform.h"
     15 #include "GrGLProcessor.h"
     16 #include "GrGpuGL.h"
     17 #include "GrGLPathRendering.h"
     18 #include "GrGLShaderVar.h"
     19 #include "GrGLSL.h"
     20 #include "GrOptDrawState.h"
     21 #include "SkXfermode.h"
     22 
     23 #define GL_CALL(X) GR_GL_CALL(fGpu->glInterface(), X)
     24 #define GL_CALL_RET(R, X) GR_GL_CALL_RET(fGpu->glInterface(), R, X)
     25 
     26 GrGLProgram* GrGLProgram::Create(GrGpuGL* gpu,
     27                                  const GrGLProgramDesc& desc,
     28                                  const GrGeometryStage* geometryProcessor,
     29                                  const GrFragmentStage* colorStages[],
     30                                  const GrFragmentStage* coverageStages[]) {
     31     SkAutoTDelete<GrGLProgramBuilder> builder;
     32     if (desc.getHeader().fUseFragShaderOnly) {
     33         SkASSERT(gpu->glCaps().pathRenderingSupport());
     34         SkASSERT(gpu->glPathRendering()->texturingMode() ==
     35                  GrGLPathRendering::FixedFunction_TexturingMode);
     36         SkASSERT(NULL == geometryProcessor);
     37         builder.reset(SkNEW_ARGS(GrGLFragmentOnlyProgramBuilder, (gpu, desc)));
     38     } else {
     39         builder.reset(SkNEW_ARGS(GrGLFullProgramBuilder, (gpu, desc)));
     40     }
     41     if (builder->genProgram(geometryProcessor, colorStages, coverageStages)) {
     42         SkASSERT(0 != builder->getProgramID());
     43         return SkNEW_ARGS(GrGLProgram, (gpu, desc, *builder));
     44     }
     45     return NULL;
     46 }
     47 
     48 GrGLProgram::GrGLProgram(GrGpuGL* gpu,
     49                          const GrGLProgramDesc& desc,
     50                          const GrGLProgramBuilder& builder)
     51     : fColor(GrColor_ILLEGAL)
     52     , fCoverage(GrColor_ILLEGAL)
     53     , fDstCopyTexUnit(-1)
     54     , fBuiltinUniformHandles(builder.getBuiltinUniformHandles())
     55     , fGeometryProcessor(SkSafeRef(builder.getGeometryProcessor()))
     56     , fColorEffects(SkRef(builder.getColorEffects()))
     57     , fCoverageEffects(SkRef(builder.getCoverageEffects()))
     58     , fProgramID(builder.getProgramID())
     59     , fHasVertexShader(builder.hasVertexShader())
     60     , fTexCoordSetCnt(builder.getTexCoordSetCount())
     61     , fDesc(desc)
     62     , fGpu(gpu)
     63     , fProgramDataManager(gpu, this, builder) {
     64     this->initSamplerUniforms();
     65 }
     66 
     67 GrGLProgram::~GrGLProgram() {
     68     if (fProgramID) {
     69         GL_CALL(DeleteProgram(fProgramID));
     70     }
     71 }
     72 
     73 void GrGLProgram::abandon() {
     74     fProgramID = 0;
     75 }
     76 
     77 void GrGLProgram::initSamplerUniforms() {
     78     GL_CALL(UseProgram(fProgramID));
     79     GrGLint texUnitIdx = 0;
     80     if (fBuiltinUniformHandles.fDstCopySamplerUni.isValid()) {
     81         fProgramDataManager.setSampler(fBuiltinUniformHandles.fDstCopySamplerUni, texUnitIdx);
     82         fDstCopyTexUnit = texUnitIdx++;
     83     }
     84     if (fGeometryProcessor.get()) {
     85         fGeometryProcessor->initSamplers(fProgramDataManager, &texUnitIdx);
     86     }
     87     fColorEffects->initSamplers(fProgramDataManager, &texUnitIdx);
     88     fCoverageEffects->initSamplers(fProgramDataManager, &texUnitIdx);
     89 }
     90 
     91 ///////////////////////////////////////////////////////////////////////////////
     92 
     93 void GrGLProgram::setData(const GrOptDrawState& optState,
     94                           GrGpu::DrawType drawType,
     95                           const GrGeometryStage* geometryProcessor,
     96                           const GrFragmentStage* colorStages[],
     97                           const GrFragmentStage* coverageStages[],
     98                           const GrDeviceCoordTexture* dstCopy,
     99                           SharedGLState* sharedState) {
    100     GrColor color = optState.getColor();
    101     GrColor coverage = optState.getCoverageColor();
    102 
    103     this->setColor(optState, color, sharedState);
    104     this->setCoverage(optState, coverage, sharedState);
    105     this->setMatrixAndRenderTargetHeight(drawType, optState);
    106 
    107     if (dstCopy) {
    108         if (fBuiltinUniformHandles.fDstCopyTopLeftUni.isValid()) {
    109             fProgramDataManager.set2f(fBuiltinUniformHandles.fDstCopyTopLeftUni,
    110                                        static_cast<GrGLfloat>(dstCopy->offset().fX),
    111                                        static_cast<GrGLfloat>(dstCopy->offset().fY));
    112             fProgramDataManager.set2f(fBuiltinUniformHandles.fDstCopyScaleUni,
    113                                        1.f / dstCopy->texture()->width(),
    114                                        1.f / dstCopy->texture()->height());
    115             GrGLTexture* texture = static_cast<GrGLTexture*>(dstCopy->texture());
    116             static GrTextureParams kParams; // the default is clamp, nearest filtering.
    117             fGpu->bindTexture(fDstCopyTexUnit, kParams, texture);
    118         } else {
    119             SkASSERT(!fBuiltinUniformHandles.fDstCopyScaleUni.isValid());
    120             SkASSERT(!fBuiltinUniformHandles.fDstCopySamplerUni.isValid());
    121         }
    122     } else {
    123         SkASSERT(!fBuiltinUniformHandles.fDstCopyTopLeftUni.isValid());
    124         SkASSERT(!fBuiltinUniformHandles.fDstCopyScaleUni.isValid());
    125         SkASSERT(!fBuiltinUniformHandles.fDstCopySamplerUni.isValid());
    126     }
    127 
    128     if (fGeometryProcessor.get()) {
    129         SkASSERT(geometryProcessor);
    130         fGeometryProcessor->setData(fGpu, drawType, fProgramDataManager, geometryProcessor);
    131     }
    132     fColorEffects->setData(fGpu, drawType, fProgramDataManager, colorStages);
    133     fCoverageEffects->setData(fGpu, drawType, fProgramDataManager, coverageStages);
    134 
    135     // PathTexGen state applies to the the fixed function vertex shader. For
    136     // custom shaders, it's ignored, so we don't need to change the texgen
    137     // settings in that case.
    138     if (!fHasVertexShader) {
    139         fGpu->glPathRendering()->flushPathTexGenSettings(fTexCoordSetCnt);
    140     }
    141 }
    142 
    143 void GrGLProgram::setColor(const GrOptDrawState& optState,
    144                            GrColor color,
    145                            SharedGLState* sharedState) {
    146     const GrGLProgramDesc::KeyHeader& header = fDesc.getHeader();
    147     if (!optState.hasColorVertexAttribute()) {
    148         switch (header.fColorInput) {
    149             case GrGLProgramDesc::kAttribute_ColorInput:
    150                 SkASSERT(-1 != header.fColorAttributeIndex);
    151                 if (sharedState->fConstAttribColor != color ||
    152                     sharedState->fConstAttribColorIndex != header.fColorAttributeIndex) {
    153                     // OpenGL ES only supports the float varieties of glVertexAttrib
    154                     GrGLfloat c[4];
    155                     GrColorToRGBAFloat(color, c);
    156                     GL_CALL(VertexAttrib4fv(header.fColorAttributeIndex, c));
    157                     sharedState->fConstAttribColor = color;
    158                     sharedState->fConstAttribColorIndex = header.fColorAttributeIndex;
    159                 }
    160                 break;
    161             case GrGLProgramDesc::kUniform_ColorInput:
    162                 if (fColor != color && fBuiltinUniformHandles.fColorUni.isValid()) {
    163                     // OpenGL ES doesn't support unsigned byte varieties of glUniform
    164                     GrGLfloat c[4];
    165                     GrColorToRGBAFloat(color, c);
    166                     fProgramDataManager.set4fv(fBuiltinUniformHandles.fColorUni, 1, c);
    167                     fColor = color;
    168                 }
    169                 sharedState->fConstAttribColorIndex = -1;
    170                 break;
    171             case GrGLProgramDesc::kAllOnes_ColorInput:
    172                 sharedState->fConstAttribColorIndex = -1;
    173                 break;
    174             default:
    175                 SkFAIL("Unexpected color type.");
    176         }
    177     } else {
    178         sharedState->fConstAttribColorIndex = -1;
    179     }
    180 }
    181 
    182 void GrGLProgram::setCoverage(const GrOptDrawState& optState,
    183                               GrColor coverage,
    184                               SharedGLState* sharedState) {
    185     const GrGLProgramDesc::KeyHeader& header = fDesc.getHeader();
    186     if (!optState.hasCoverageVertexAttribute()) {
    187         switch (header.fCoverageInput) {
    188             case GrGLProgramDesc::kAttribute_ColorInput:
    189                 if (sharedState->fConstAttribCoverage != coverage ||
    190                     sharedState->fConstAttribCoverageIndex != header.fCoverageAttributeIndex) {
    191                     // OpenGL ES only supports the float varieties of  glVertexAttrib
    192                     GrGLfloat c[4];
    193                     GrColorToRGBAFloat(coverage, c);
    194                     GL_CALL(VertexAttrib4fv(header.fCoverageAttributeIndex, c));
    195                     sharedState->fConstAttribCoverage = coverage;
    196                     sharedState->fConstAttribCoverageIndex = header.fCoverageAttributeIndex;
    197                 }
    198                 break;
    199             case GrGLProgramDesc::kUniform_ColorInput:
    200                 if (fCoverage != coverage) {
    201                     // OpenGL ES doesn't support unsigned byte varieties of glUniform
    202                     GrGLfloat c[4];
    203                     GrColorToRGBAFloat(coverage, c);
    204                     fProgramDataManager.set4fv(fBuiltinUniformHandles.fCoverageUni, 1, c);
    205                     fCoverage = coverage;
    206                 }
    207                 sharedState->fConstAttribCoverageIndex = -1;
    208                 break;
    209             case GrGLProgramDesc::kAllOnes_ColorInput:
    210                 sharedState->fConstAttribCoverageIndex = -1;
    211                 break;
    212             default:
    213                 SkFAIL("Unexpected coverage type.");
    214         }
    215     } else {
    216         sharedState->fConstAttribCoverageIndex = -1;
    217     }
    218 }
    219 
    220 void GrGLProgram::setMatrixAndRenderTargetHeight(GrGpu::DrawType drawType,
    221                                                  const GrOptDrawState& optState) {
    222     const GrRenderTarget* rt = optState.getRenderTarget();
    223     SkISize size;
    224     size.set(rt->width(), rt->height());
    225 
    226     // Load the RT height uniform if it is needed to y-flip gl_FragCoord.
    227     if (fBuiltinUniformHandles.fRTHeightUni.isValid() &&
    228         fMatrixState.fRenderTargetSize.fHeight != size.fHeight) {
    229         fProgramDataManager.set1f(fBuiltinUniformHandles.fRTHeightUni,
    230                                    SkIntToScalar(size.fHeight));
    231     }
    232 
    233     if (GrGpu::IsPathRenderingDrawType(drawType)) {
    234         fGpu->glPathRendering()->setProjectionMatrix(optState.getViewMatrix(), size, rt->origin());
    235     } else if (fMatrixState.fRenderTargetOrigin != rt->origin() ||
    236                fMatrixState.fRenderTargetSize != size ||
    237                !fMatrixState.fViewMatrix.cheapEqualTo(optState.getViewMatrix())) {
    238         SkASSERT(fBuiltinUniformHandles.fViewMatrixUni.isValid());
    239 
    240         fMatrixState.fViewMatrix = optState.getViewMatrix();
    241         fMatrixState.fRenderTargetSize = size;
    242         fMatrixState.fRenderTargetOrigin = rt->origin();
    243 
    244         GrGLfloat viewMatrix[3 * 3];
    245         fMatrixState.getGLMatrix<3>(viewMatrix);
    246         fProgramDataManager.setMatrix3f(fBuiltinUniformHandles.fViewMatrixUni, viewMatrix);
    247 
    248         GrGLfloat rtAdjustmentVec[4];
    249         fMatrixState.getRTAdjustmentVec(rtAdjustmentVec);
    250         fProgramDataManager.set4fv(fBuiltinUniformHandles.fRTAdjustmentUni, 1, rtAdjustmentVec);
    251     }
    252 }
    253