Home | History | Annotate | Download | only in gl
      1 /*
      2  * Copyright 2012 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 "gl/builders/GrGLProgramBuilder.h"
      9 #include "gl/GrGLPathRendering.h"
     10 #include "gl/GrGLProgram.h"
     11 #include "gl/GrGLUniformHandle.h"
     12 #include "gl/GrGpuGL.h"
     13 #include "SkMatrix.h"
     14 
     15 #define ASSERT_ARRAY_UPLOAD_IN_BOUNDS(UNI, COUNT) \
     16          SkASSERT(arrayCount <= uni.fArrayCount || \
     17                   (1 == arrayCount && GrGLShaderVar::kNonArray == uni.fArrayCount))
     18 
     19 GrGLProgramDataManager::GrGLProgramDataManager(GrGpuGL* gpu,
     20                                                GrGLProgram* program,
     21                                                const GrGLProgramBuilder& builder)
     22     : fGpu(gpu),
     23       fProgram(program) {
     24     int count = builder.getUniformInfos().count();
     25     fUniforms.push_back_n(count);
     26     for (int i = 0; i < count; i++) {
     27         Uniform& uniform = fUniforms[i];
     28         const GrGLProgramBuilder::UniformInfo& builderUniform = builder.getUniformInfos()[i];
     29         SkASSERT(GrGLShaderVar::kNonArray == builderUniform.fVariable.getArrayCount() ||
     30                  builderUniform.fVariable.getArrayCount() > 0);
     31         SkDEBUGCODE(
     32             uniform.fArrayCount = builderUniform.fVariable.getArrayCount();
     33             uniform.fType = builderUniform.fVariable.getType();
     34         );
     35         // TODO: Move the Xoom uniform array in both FS and VS bug workaround here.
     36 
     37         if (GrGLProgramBuilder::kVertex_Visibility & builderUniform.fVisibility) {
     38             uniform.fVSLocation = builderUniform.fLocation;
     39         } else {
     40             uniform.fVSLocation = kUnusedUniform;
     41             }
     42         if (GrGLProgramBuilder::kFragment_Visibility & builderUniform.fVisibility) {
     43             uniform.fFSLocation = builderUniform.fLocation;
     44         } else {
     45             uniform.fFSLocation = kUnusedUniform;
     46         }
     47     }
     48 
     49     count = builder.getSeparableVaryingInfos().count();
     50     fVaryings.push_back_n(count);
     51     for (int i = 0; i < count; i++) {
     52         Varying& varying = fVaryings[i];
     53         const GrGLProgramBuilder::SeparableVaryingInfo& builderVarying =
     54             builder.getSeparableVaryingInfos()[i];
     55         SkASSERT(GrGLShaderVar::kNonArray == builderVarying.fVariable.getArrayCount());
     56         SkDEBUGCODE(
     57             varying.fType = builderVarying.fVariable.getType();
     58         );
     59         varying.fLocation = builderVarying.fLocation;
     60     }
     61 }
     62 
     63 void GrGLProgramDataManager::setSampler(UniformHandle u, GrGLint texUnit) const {
     64     const Uniform& uni = fUniforms[u.toProgramDataIndex()];
     65     SkASSERT(uni.fType == kSampler2D_GrSLType);
     66     SkASSERT(GrGLShaderVar::kNonArray == uni.fArrayCount);
     67     // FIXME: We still insert a single sampler uniform for every stage. If the shader does not
     68     // reference the sampler then the compiler may have optimized it out. Uncomment this assert
     69     // once stages insert their own samplers.
     70     // SkASSERT(kUnusedUniform != uni.fFSLocation || kUnusedUniform != uni.fVSLocation);
     71     if (kUnusedUniform != uni.fFSLocation) {
     72         GR_GL_CALL(fGpu->glInterface(), Uniform1i(uni.fFSLocation, texUnit));
     73     }
     74     if (kUnusedUniform != uni.fVSLocation && uni.fVSLocation != uni.fFSLocation) {
     75         GR_GL_CALL(fGpu->glInterface(), Uniform1i(uni.fVSLocation, texUnit));
     76     }
     77 }
     78 
     79 void GrGLProgramDataManager::set1f(UniformHandle u, GrGLfloat v0) const {
     80     const Uniform& uni = fUniforms[u.toProgramDataIndex()];
     81     SkASSERT(uni.fType == kFloat_GrSLType);
     82     SkASSERT(GrGLShaderVar::kNonArray == uni.fArrayCount);
     83     SkASSERT(kUnusedUniform != uni.fFSLocation || kUnusedUniform != uni.fVSLocation);
     84     if (kUnusedUniform != uni.fFSLocation) {
     85         GR_GL_CALL(fGpu->glInterface(), Uniform1f(uni.fFSLocation, v0));
     86     }
     87     if (kUnusedUniform != uni.fVSLocation && uni.fVSLocation != uni.fFSLocation) {
     88         GR_GL_CALL(fGpu->glInterface(), Uniform1f(uni.fVSLocation, v0));
     89     }
     90 }
     91 
     92 void GrGLProgramDataManager::set1fv(UniformHandle u,
     93                                     int arrayCount,
     94                                     const GrGLfloat v[]) const {
     95     const Uniform& uni = fUniforms[u.toProgramDataIndex()];
     96     SkASSERT(uni.fType == kFloat_GrSLType);
     97     SkASSERT(arrayCount > 0);
     98     ASSERT_ARRAY_UPLOAD_IN_BOUNDS(uni, arrayCount);
     99     // This assert fires in some instances of the two-pt gradient for its VSParams.
    100     // Once the uniform manager is responsible for inserting the duplicate uniform
    101     // arrays in VS and FS driver bug workaround, this can be enabled.
    102     //SkASSERT(kUnusedUniform != uni.fFSLocation || kUnusedUniform != uni.fVSLocation);
    103     if (kUnusedUniform != uni.fFSLocation) {
    104         GR_GL_CALL(fGpu->glInterface(), Uniform1fv(uni.fFSLocation, arrayCount, v));
    105     }
    106     if (kUnusedUniform != uni.fVSLocation && uni.fVSLocation != uni.fFSLocation) {
    107         GR_GL_CALL(fGpu->glInterface(), Uniform1fv(uni.fVSLocation, arrayCount, v));
    108     }
    109 }
    110 
    111 void GrGLProgramDataManager::set2f(UniformHandle u, GrGLfloat v0, GrGLfloat v1) const {
    112     const Uniform& uni = fUniforms[u.toProgramDataIndex()];
    113     SkASSERT(uni.fType == kVec2f_GrSLType);
    114     SkASSERT(GrGLShaderVar::kNonArray == uni.fArrayCount);
    115     SkASSERT(kUnusedUniform != uni.fFSLocation || kUnusedUniform != uni.fVSLocation);
    116     if (kUnusedUniform != uni.fFSLocation) {
    117         GR_GL_CALL(fGpu->glInterface(), Uniform2f(uni.fFSLocation, v0, v1));
    118     }
    119     if (kUnusedUniform != uni.fVSLocation && uni.fVSLocation != uni.fFSLocation) {
    120         GR_GL_CALL(fGpu->glInterface(), Uniform2f(uni.fVSLocation, v0, v1));
    121     }
    122 }
    123 
    124 void GrGLProgramDataManager::set2fv(UniformHandle u,
    125                                     int arrayCount,
    126                                     const GrGLfloat v[]) const {
    127     const Uniform& uni = fUniforms[u.toProgramDataIndex()];
    128     SkASSERT(uni.fType == kVec2f_GrSLType);
    129     SkASSERT(arrayCount > 0);
    130     ASSERT_ARRAY_UPLOAD_IN_BOUNDS(uni, arrayCount);
    131     SkASSERT(kUnusedUniform != uni.fFSLocation || kUnusedUniform != uni.fVSLocation);
    132     if (kUnusedUniform != uni.fFSLocation) {
    133         GR_GL_CALL(fGpu->glInterface(), Uniform2fv(uni.fFSLocation, arrayCount, v));
    134     }
    135     if (kUnusedUniform != uni.fVSLocation && uni.fVSLocation != uni.fFSLocation) {
    136         GR_GL_CALL(fGpu->glInterface(), Uniform2fv(uni.fVSLocation, arrayCount, v));
    137     }
    138 }
    139 
    140 void GrGLProgramDataManager::set3f(UniformHandle u, GrGLfloat v0, GrGLfloat v1, GrGLfloat v2) const {
    141     const Uniform& uni = fUniforms[u.toProgramDataIndex()];
    142     SkASSERT(uni.fType == kVec3f_GrSLType);
    143     SkASSERT(GrGLShaderVar::kNonArray == uni.fArrayCount);
    144     SkASSERT(kUnusedUniform != uni.fFSLocation || kUnusedUniform != uni.fVSLocation);
    145     if (kUnusedUniform != uni.fFSLocation) {
    146         GR_GL_CALL(fGpu->glInterface(), Uniform3f(uni.fFSLocation, v0, v1, v2));
    147     }
    148     if (kUnusedUniform != uni.fVSLocation && uni.fVSLocation != uni.fFSLocation) {
    149         GR_GL_CALL(fGpu->glInterface(), Uniform3f(uni.fVSLocation, v0, v1, v2));
    150     }
    151 }
    152 
    153 void GrGLProgramDataManager::set3fv(UniformHandle u,
    154                                     int arrayCount,
    155                                     const GrGLfloat v[]) const {
    156     const Uniform& uni = fUniforms[u.toProgramDataIndex()];
    157     SkASSERT(uni.fType == kVec3f_GrSLType);
    158     SkASSERT(arrayCount > 0);
    159     ASSERT_ARRAY_UPLOAD_IN_BOUNDS(uni, arrayCount);
    160     SkASSERT(kUnusedUniform != uni.fFSLocation || kUnusedUniform != uni.fVSLocation);
    161     if (kUnusedUniform != uni.fFSLocation) {
    162         GR_GL_CALL(fGpu->glInterface(), Uniform3fv(uni.fFSLocation, arrayCount, v));
    163     }
    164     if (kUnusedUniform != uni.fVSLocation && uni.fVSLocation != uni.fFSLocation) {
    165         GR_GL_CALL(fGpu->glInterface(), Uniform3fv(uni.fVSLocation, arrayCount, v));
    166     }
    167 }
    168 
    169 void GrGLProgramDataManager::set4f(UniformHandle u,
    170                                    GrGLfloat v0,
    171                                    GrGLfloat v1,
    172                                    GrGLfloat v2,
    173                                    GrGLfloat v3) const {
    174     const Uniform& uni = fUniforms[u.toProgramDataIndex()];
    175     SkASSERT(uni.fType == kVec4f_GrSLType);
    176     SkASSERT(GrGLShaderVar::kNonArray == uni.fArrayCount);
    177     SkASSERT(kUnusedUniform != uni.fFSLocation || kUnusedUniform != uni.fVSLocation);
    178     if (kUnusedUniform != uni.fFSLocation) {
    179         GR_GL_CALL(fGpu->glInterface(), Uniform4f(uni.fFSLocation, v0, v1, v2, v3));
    180     }
    181     if (kUnusedUniform != uni.fVSLocation && uni.fVSLocation != uni.fFSLocation) {
    182         GR_GL_CALL(fGpu->glInterface(), Uniform4f(uni.fVSLocation, v0, v1, v2, v3));
    183     }
    184 }
    185 
    186 void GrGLProgramDataManager::set4fv(UniformHandle u,
    187                                     int arrayCount,
    188                                     const GrGLfloat v[]) const {
    189     const Uniform& uni = fUniforms[u.toProgramDataIndex()];
    190     SkASSERT(uni.fType == kVec4f_GrSLType);
    191     SkASSERT(arrayCount > 0);
    192     ASSERT_ARRAY_UPLOAD_IN_BOUNDS(uni, arrayCount);
    193     SkASSERT(kUnusedUniform != uni.fFSLocation || kUnusedUniform != uni.fVSLocation);
    194     if (kUnusedUniform != uni.fFSLocation) {
    195         GR_GL_CALL(fGpu->glInterface(), Uniform4fv(uni.fFSLocation, arrayCount, v));
    196     }
    197     if (kUnusedUniform != uni.fVSLocation && uni.fVSLocation != uni.fFSLocation) {
    198         GR_GL_CALL(fGpu->glInterface(), Uniform4fv(uni.fVSLocation, arrayCount, v));
    199     }
    200 }
    201 
    202 void GrGLProgramDataManager::setMatrix3f(UniformHandle u, const GrGLfloat matrix[]) const {
    203     const Uniform& uni = fUniforms[u.toProgramDataIndex()];
    204     SkASSERT(uni.fType == kMat33f_GrSLType);
    205     SkASSERT(GrGLShaderVar::kNonArray == uni.fArrayCount);
    206     // TODO: Re-enable this assert once texture matrices aren't forced on all effects
    207     // SkASSERT(kUnusedUniform != uni.fFSLocation || kUnusedUniform != uni.fVSLocation);
    208     if (kUnusedUniform != uni.fFSLocation) {
    209         GR_GL_CALL(fGpu->glInterface(), UniformMatrix3fv(uni.fFSLocation, 1, false, matrix));
    210     }
    211     if (kUnusedUniform != uni.fVSLocation && uni.fVSLocation != uni.fFSLocation) {
    212         GR_GL_CALL(fGpu->glInterface(), UniformMatrix3fv(uni.fVSLocation, 1, false, matrix));
    213     }
    214 }
    215 
    216 void GrGLProgramDataManager::setMatrix4f(UniformHandle u, const GrGLfloat matrix[]) const {
    217     const Uniform& uni = fUniforms[u.toProgramDataIndex()];
    218     SkASSERT(uni.fType == kMat44f_GrSLType);
    219     SkASSERT(GrGLShaderVar::kNonArray == uni.fArrayCount);
    220     SkASSERT(kUnusedUniform != uni.fFSLocation || kUnusedUniform != uni.fVSLocation);
    221     if (kUnusedUniform != uni.fFSLocation) {
    222         GR_GL_CALL(fGpu->glInterface(), UniformMatrix4fv(uni.fFSLocation, 1, false, matrix));
    223     }
    224     if (kUnusedUniform != uni.fVSLocation && uni.fVSLocation != uni.fFSLocation) {
    225         GR_GL_CALL(fGpu->glInterface(), UniformMatrix4fv(uni.fVSLocation, 1, false, matrix));
    226     }
    227 }
    228 
    229 void GrGLProgramDataManager::setMatrix3fv(UniformHandle u,
    230                                           int arrayCount,
    231                                           const GrGLfloat matrices[]) const {
    232     const Uniform& uni = fUniforms[u.toProgramDataIndex()];
    233     SkASSERT(uni.fType == kMat33f_GrSLType);
    234     SkASSERT(arrayCount > 0);
    235     ASSERT_ARRAY_UPLOAD_IN_BOUNDS(uni, arrayCount);
    236     SkASSERT(kUnusedUniform != uni.fFSLocation || kUnusedUniform != uni.fVSLocation);
    237     if (kUnusedUniform != uni.fFSLocation) {
    238         GR_GL_CALL(fGpu->glInterface(),
    239                    UniformMatrix3fv(uni.fFSLocation, arrayCount, false, matrices));
    240     }
    241     if (kUnusedUniform != uni.fVSLocation && uni.fVSLocation != uni.fFSLocation) {
    242         GR_GL_CALL(fGpu->glInterface(),
    243                    UniformMatrix3fv(uni.fVSLocation, arrayCount, false, matrices));
    244     }
    245 }
    246 
    247 void GrGLProgramDataManager::setMatrix4fv(UniformHandle u,
    248                                           int arrayCount,
    249                                           const GrGLfloat matrices[]) const {
    250     const Uniform& uni = fUniforms[u.toProgramDataIndex()];
    251     SkASSERT(uni.fType == kMat44f_GrSLType);
    252     SkASSERT(arrayCount > 0);
    253     ASSERT_ARRAY_UPLOAD_IN_BOUNDS(uni, arrayCount);
    254     SkASSERT(kUnusedUniform != uni.fFSLocation || kUnusedUniform != uni.fVSLocation);
    255     if (kUnusedUniform != uni.fFSLocation) {
    256         GR_GL_CALL(fGpu->glInterface(),
    257                    UniformMatrix4fv(uni.fFSLocation, arrayCount, false, matrices));
    258     }
    259     if (kUnusedUniform != uni.fVSLocation && uni.fVSLocation != uni.fFSLocation) {
    260         GR_GL_CALL(fGpu->glInterface(),
    261                    UniformMatrix4fv(uni.fVSLocation, arrayCount, false, matrices));
    262     }
    263 }
    264 
    265 void GrGLProgramDataManager::setSkMatrix(UniformHandle u, const SkMatrix& matrix) const {
    266     GrGLfloat mt[] = {
    267         matrix.get(SkMatrix::kMScaleX),
    268         matrix.get(SkMatrix::kMSkewY),
    269         matrix.get(SkMatrix::kMPersp0),
    270         matrix.get(SkMatrix::kMSkewX),
    271         matrix.get(SkMatrix::kMScaleY),
    272         matrix.get(SkMatrix::kMPersp1),
    273         matrix.get(SkMatrix::kMTransX),
    274         matrix.get(SkMatrix::kMTransY),
    275         matrix.get(SkMatrix::kMPersp2),
    276     };
    277     this->setMatrix3f(u, mt);
    278 }
    279 
    280 void GrGLProgramDataManager::setProgramPathFragmentInputTransform(VaryingHandle i,
    281                                                                   unsigned components,
    282                                                                   const SkMatrix& matrix) const {
    283     const Varying& fragmentInput = fVaryings[i.toProgramDataIndex()];
    284     fGpu->glPathRendering()->setProgramPathFragmentInputTransform(fProgram->programID(),
    285                                                                   fragmentInput.fLocation,
    286                                                                   GR_GL_OBJECT_LINEAR,
    287                                                                   components,
    288                                                                   matrix);
    289 }
    290