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