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     fUsingBindUniform = fGpu->glInterface()->fBindUniformLocation != NULL;
     20 }
     21 
     22 GrGLUniformManager::UniformHandle GrGLUniformManager::appendUniform(GrSLType type, int arrayCount) {
     23     int idx = fUniforms.count();
     24     Uniform& uni = fUniforms.push_back();
     25     SkASSERT(GrGLShaderVar::kNonArray == arrayCount || arrayCount > 0);
     26     uni.fArrayCount = arrayCount;
     27     uni.fType = type;
     28     uni.fVSLocation = kUnusedUniform;
     29     uni.fFSLocation = kUnusedUniform;
     30     return GrGLUniformManager::UniformHandle::CreateFromUniformIndex(idx);
     31 }
     32 
     33 void GrGLUniformManager::setSampler(UniformHandle u, GrGLint texUnit) const {
     34     const Uniform& uni = fUniforms[u.toUniformIndex()];
     35     SkASSERT(uni.fType == kSampler2D_GrSLType);
     36     SkASSERT(GrGLShaderVar::kNonArray == uni.fArrayCount);
     37     // FIXME: We still insert a single sampler uniform for every stage. If the shader does not
     38     // reference the sampler then the compiler may have optimized it out. Uncomment this assert
     39     // once stages insert their own samplers.
     40     // SkASSERT(kUnusedUniform != uni.fFSLocation || kUnusedUniform != uni.fVSLocation);
     41     if (kUnusedUniform != uni.fFSLocation) {
     42         GR_GL_CALL(fGpu->glInterface(), Uniform1i(uni.fFSLocation, texUnit));
     43     }
     44     if (kUnusedUniform != uni.fVSLocation && uni.fVSLocation != uni.fFSLocation) {
     45         GR_GL_CALL(fGpu->glInterface(), Uniform1i(uni.fVSLocation, texUnit));
     46     }
     47 }
     48 
     49 void GrGLUniformManager::set1f(UniformHandle u, GrGLfloat v0) const {
     50     const Uniform& uni = fUniforms[u.toUniformIndex()];
     51     SkASSERT(uni.fType == kFloat_GrSLType);
     52     SkASSERT(GrGLShaderVar::kNonArray == uni.fArrayCount);
     53     SkASSERT(kUnusedUniform != uni.fFSLocation || kUnusedUniform != uni.fVSLocation);
     54     if (kUnusedUniform != uni.fFSLocation) {
     55         GR_GL_CALL(fGpu->glInterface(), Uniform1f(uni.fFSLocation, v0));
     56     }
     57     if (kUnusedUniform != uni.fVSLocation && uni.fVSLocation != uni.fFSLocation) {
     58         GR_GL_CALL(fGpu->glInterface(), Uniform1f(uni.fVSLocation, v0));
     59     }
     60 }
     61 
     62 void GrGLUniformManager::set1fv(UniformHandle u,
     63                                 int arrayCount,
     64                                 const GrGLfloat v[]) const {
     65     const Uniform& uni = fUniforms[u.toUniformIndex()];
     66     SkASSERT(uni.fType == kFloat_GrSLType);
     67     SkASSERT(arrayCount > 0);
     68     ASSERT_ARRAY_UPLOAD_IN_BOUNDS(uni, arrayCount);
     69     // This assert fires in some instances of the two-pt gradient for its VSParams.
     70     // Once the uniform manager is responsible for inserting the duplicate uniform
     71     // arrays in VS and FS driver bug workaround, this can be enabled.
     72     //SkASSERT(kUnusedUniform != uni.fFSLocation || kUnusedUniform != uni.fVSLocation);
     73     if (kUnusedUniform != uni.fFSLocation) {
     74         GR_GL_CALL(fGpu->glInterface(), Uniform1fv(uni.fFSLocation, arrayCount, v));
     75     }
     76     if (kUnusedUniform != uni.fVSLocation && uni.fVSLocation != uni.fFSLocation) {
     77         GR_GL_CALL(fGpu->glInterface(), Uniform1fv(uni.fVSLocation, arrayCount, v));
     78     }
     79 }
     80 
     81 void GrGLUniformManager::set2f(UniformHandle u, GrGLfloat v0, GrGLfloat v1) const {
     82     const Uniform& uni = fUniforms[u.toUniformIndex()];
     83     SkASSERT(uni.fType == kVec2f_GrSLType);
     84     SkASSERT(GrGLShaderVar::kNonArray == uni.fArrayCount);
     85     SkASSERT(kUnusedUniform != uni.fFSLocation || kUnusedUniform != uni.fVSLocation);
     86     if (kUnusedUniform != uni.fFSLocation) {
     87         GR_GL_CALL(fGpu->glInterface(), Uniform2f(uni.fFSLocation, v0, v1));
     88     }
     89     if (kUnusedUniform != uni.fVSLocation && uni.fVSLocation != uni.fFSLocation) {
     90         GR_GL_CALL(fGpu->glInterface(), Uniform2f(uni.fVSLocation, v0, v1));
     91     }
     92 }
     93 
     94 void GrGLUniformManager::set2fv(UniformHandle u,
     95                                 int arrayCount,
     96                                 const GrGLfloat v[]) const {
     97     const Uniform& uni = fUniforms[u.toUniformIndex()];
     98     SkASSERT(uni.fType == kVec2f_GrSLType);
     99     SkASSERT(arrayCount > 0);
    100     ASSERT_ARRAY_UPLOAD_IN_BOUNDS(uni, arrayCount);
    101     SkASSERT(kUnusedUniform != uni.fFSLocation || kUnusedUniform != uni.fVSLocation);
    102     if (kUnusedUniform != uni.fFSLocation) {
    103         GR_GL_CALL(fGpu->glInterface(), Uniform2fv(uni.fFSLocation, arrayCount, v));
    104     }
    105     if (kUnusedUniform != uni.fVSLocation && uni.fVSLocation != uni.fFSLocation) {
    106         GR_GL_CALL(fGpu->glInterface(), Uniform2fv(uni.fVSLocation, arrayCount, v));
    107     }
    108 }
    109 
    110 void GrGLUniformManager::set3f(UniformHandle u, GrGLfloat v0, GrGLfloat v1, GrGLfloat v2) const {
    111     const Uniform& uni = fUniforms[u.toUniformIndex()];
    112     SkASSERT(uni.fType == kVec3f_GrSLType);
    113     SkASSERT(GrGLShaderVar::kNonArray == uni.fArrayCount);
    114     SkASSERT(kUnusedUniform != uni.fFSLocation || kUnusedUniform != uni.fVSLocation);
    115     if (kUnusedUniform != uni.fFSLocation) {
    116         GR_GL_CALL(fGpu->glInterface(), Uniform3f(uni.fFSLocation, v0, v1, v2));
    117     }
    118     if (kUnusedUniform != uni.fVSLocation && uni.fVSLocation != uni.fFSLocation) {
    119         GR_GL_CALL(fGpu->glInterface(), Uniform3f(uni.fVSLocation, v0, v1, v2));
    120     }
    121 }
    122 
    123 void GrGLUniformManager::set3fv(UniformHandle u,
    124                                 int arrayCount,
    125                                 const GrGLfloat v[]) const {
    126     const Uniform& uni = fUniforms[u.toUniformIndex()];
    127     SkASSERT(uni.fType == kVec3f_GrSLType);
    128     SkASSERT(arrayCount > 0);
    129     ASSERT_ARRAY_UPLOAD_IN_BOUNDS(uni, arrayCount);
    130     SkASSERT(kUnusedUniform != uni.fFSLocation || kUnusedUniform != uni.fVSLocation);
    131     if (kUnusedUniform != uni.fFSLocation) {
    132         GR_GL_CALL(fGpu->glInterface(), Uniform3fv(uni.fFSLocation, arrayCount, v));
    133     }
    134     if (kUnusedUniform != uni.fVSLocation && uni.fVSLocation != uni.fFSLocation) {
    135         GR_GL_CALL(fGpu->glInterface(), Uniform3fv(uni.fVSLocation, arrayCount, v));
    136     }
    137 }
    138 
    139 void GrGLUniformManager::set4f(UniformHandle u,
    140                                GrGLfloat v0,
    141                                GrGLfloat v1,
    142                                GrGLfloat v2,
    143                                GrGLfloat v3) const {
    144     const Uniform& uni = fUniforms[u.toUniformIndex()];
    145     SkASSERT(uni.fType == kVec4f_GrSLType);
    146     SkASSERT(GrGLShaderVar::kNonArray == uni.fArrayCount);
    147     SkASSERT(kUnusedUniform != uni.fFSLocation || kUnusedUniform != uni.fVSLocation);
    148     if (kUnusedUniform != uni.fFSLocation) {
    149         GR_GL_CALL(fGpu->glInterface(), Uniform4f(uni.fFSLocation, v0, v1, v2, v3));
    150     }
    151     if (kUnusedUniform != uni.fVSLocation && uni.fVSLocation != uni.fFSLocation) {
    152         GR_GL_CALL(fGpu->glInterface(), Uniform4f(uni.fVSLocation, v0, v1, v2, v3));
    153     }
    154 }
    155 
    156 void GrGLUniformManager::set4fv(UniformHandle u,
    157                                 int arrayCount,
    158                                 const GrGLfloat v[]) const {
    159     const Uniform& uni = fUniforms[u.toUniformIndex()];
    160     SkASSERT(uni.fType == kVec4f_GrSLType);
    161     SkASSERT(arrayCount > 0);
    162     ASSERT_ARRAY_UPLOAD_IN_BOUNDS(uni, arrayCount);
    163     SkASSERT(kUnusedUniform != uni.fFSLocation || kUnusedUniform != uni.fVSLocation);
    164     if (kUnusedUniform != uni.fFSLocation) {
    165         GR_GL_CALL(fGpu->glInterface(), Uniform4fv(uni.fFSLocation, arrayCount, v));
    166     }
    167     if (kUnusedUniform != uni.fVSLocation && uni.fVSLocation != uni.fFSLocation) {
    168         GR_GL_CALL(fGpu->glInterface(), Uniform4fv(uni.fVSLocation, arrayCount, v));
    169     }
    170 }
    171 
    172 void GrGLUniformManager::setMatrix3f(UniformHandle u, const GrGLfloat matrix[]) const {
    173     const Uniform& uni = fUniforms[u.toUniformIndex()];
    174     SkASSERT(uni.fType == kMat33f_GrSLType);
    175     SkASSERT(GrGLShaderVar::kNonArray == uni.fArrayCount);
    176     // TODO: Re-enable this assert once texture matrices aren't forced on all effects
    177     // SkASSERT(kUnusedUniform != uni.fFSLocation || kUnusedUniform != uni.fVSLocation);
    178     if (kUnusedUniform != uni.fFSLocation) {
    179         GR_GL_CALL(fGpu->glInterface(), UniformMatrix3fv(uni.fFSLocation, 1, false, matrix));
    180     }
    181     if (kUnusedUniform != uni.fVSLocation && uni.fVSLocation != uni.fFSLocation) {
    182         GR_GL_CALL(fGpu->glInterface(), UniformMatrix3fv(uni.fVSLocation, 1, false, matrix));
    183     }
    184 }
    185 
    186 void GrGLUniformManager::setMatrix4f(UniformHandle u, const GrGLfloat matrix[]) const {
    187     const Uniform& uni = fUniforms[u.toUniformIndex()];
    188     SkASSERT(uni.fType == kMat44f_GrSLType);
    189     SkASSERT(GrGLShaderVar::kNonArray == uni.fArrayCount);
    190     SkASSERT(kUnusedUniform != uni.fFSLocation || kUnusedUniform != uni.fVSLocation);
    191     if (kUnusedUniform != uni.fFSLocation) {
    192         GR_GL_CALL(fGpu->glInterface(), UniformMatrix4fv(uni.fFSLocation, 1, false, matrix));
    193     }
    194     if (kUnusedUniform != uni.fVSLocation && uni.fVSLocation != uni.fFSLocation) {
    195         GR_GL_CALL(fGpu->glInterface(), UniformMatrix4fv(uni.fVSLocation, 1, false, matrix));
    196     }
    197 }
    198 
    199 void GrGLUniformManager::setMatrix3fv(UniformHandle u,
    200                                       int arrayCount,
    201                                       const GrGLfloat matrices[]) const {
    202     const Uniform& uni = fUniforms[u.toUniformIndex()];
    203     SkASSERT(uni.fType == kMat33f_GrSLType);
    204     SkASSERT(arrayCount > 0);
    205     ASSERT_ARRAY_UPLOAD_IN_BOUNDS(uni, arrayCount);
    206     SkASSERT(kUnusedUniform != uni.fFSLocation || kUnusedUniform != uni.fVSLocation);
    207     if (kUnusedUniform != uni.fFSLocation) {
    208         GR_GL_CALL(fGpu->glInterface(),
    209                    UniformMatrix3fv(uni.fFSLocation, arrayCount, false, matrices));
    210     }
    211     if (kUnusedUniform != uni.fVSLocation && uni.fVSLocation != uni.fFSLocation) {
    212         GR_GL_CALL(fGpu->glInterface(),
    213                    UniformMatrix3fv(uni.fVSLocation, arrayCount, false, matrices));
    214     }
    215 }
    216 
    217 void GrGLUniformManager::setMatrix4fv(UniformHandle u,
    218                                       int arrayCount,
    219                                       const GrGLfloat matrices[]) const {
    220     const Uniform& uni = fUniforms[u.toUniformIndex()];
    221     SkASSERT(uni.fType == kMat44f_GrSLType);
    222     SkASSERT(arrayCount > 0);
    223     ASSERT_ARRAY_UPLOAD_IN_BOUNDS(uni, arrayCount);
    224     SkASSERT(kUnusedUniform != uni.fFSLocation || kUnusedUniform != uni.fVSLocation);
    225     if (kUnusedUniform != uni.fFSLocation) {
    226         GR_GL_CALL(fGpu->glInterface(),
    227                    UniformMatrix4fv(uni.fFSLocation, arrayCount, false, matrices));
    228     }
    229     if (kUnusedUniform != uni.fVSLocation && uni.fVSLocation != uni.fFSLocation) {
    230         GR_GL_CALL(fGpu->glInterface(),
    231                    UniformMatrix4fv(uni.fVSLocation, arrayCount, false, matrices));
    232     }
    233 }
    234 
    235 void GrGLUniformManager::setSkMatrix(UniformHandle u, const SkMatrix& matrix) const {
    236 //    GR_STATIC_ASSERT(SK_SCALAR_IS_FLOAT);
    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