Home | History | Annotate | Download | only in gl
      1 /*
      2  * Copyright 2013 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 "GrGLProgramEffects.h"
      9 #include "gl/GrGLProcessor.h"
     10 #include "gl/GrGLPathRendering.h"
     11 #include "gl/builders/GrGLFullProgramBuilder.h"
     12 #include "gl/builders/GrGLFragmentOnlyProgramBuilder.h"
     13 #include "gl/GrGLGeometryProcessor.h"
     14 #include "gl/GrGpuGL.h"
     15 
     16 typedef GrGLProcessor::TransformedCoords TransformedCoords;
     17 typedef GrGLProcessor::TransformedCoordsArray TransformedCoordsArray;
     18 typedef GrGLProcessor::TextureSampler TextureSampler;
     19 typedef GrGLProcessor::TextureSamplerArray TextureSamplerArray;
     20 
     21 namespace {
     22 /**
     23  * Retrieves the final matrix that a transform needs to apply to its source coords.
     24  */
     25 SkMatrix get_transform_matrix(const GrProcessorStage& effectStage,
     26                               bool useExplicitLocalCoords,
     27                               int transformIdx) {
     28     const GrCoordTransform& coordTransform = effectStage.getProcessor()->coordTransform(transformIdx);
     29     SkMatrix combined;
     30 
     31     if (kLocal_GrCoordSet == coordTransform.sourceCoords()) {
     32         // If we have explicit local coords then we shouldn't need a coord change.
     33         const SkMatrix& ccm =
     34                 useExplicitLocalCoords ? SkMatrix::I() : effectStage.getCoordChangeMatrix();
     35         combined.setConcat(coordTransform.getMatrix(), ccm);
     36     } else {
     37         combined = coordTransform.getMatrix();
     38     }
     39     if (coordTransform.reverseY()) {
     40         // combined.postScale(1,-1);
     41         // combined.postTranslate(0,1);
     42         combined.set(SkMatrix::kMSkewY,
     43             combined[SkMatrix::kMPersp0] - combined[SkMatrix::kMSkewY]);
     44         combined.set(SkMatrix::kMScaleY,
     45             combined[SkMatrix::kMPersp1] - combined[SkMatrix::kMScaleY]);
     46         combined.set(SkMatrix::kMTransY,
     47             combined[SkMatrix::kMPersp2] - combined[SkMatrix::kMTransY]);
     48     }
     49     return combined;
     50 }
     51 }
     52 
     53 ////////////////////////////////////////////////////////////////////////////////
     54 
     55 GrGLProgramEffects::~GrGLProgramEffects() {
     56     int numEffects = fGLProcessors.count();
     57     for (int e = 0; e < numEffects; ++e) {
     58         SkDELETE(fGLProcessors[e]);
     59     }
     60 }
     61 
     62 void GrGLProgramEffects::initSamplers(const GrGLProgramDataManager& programResourceManager, int* texUnitIdx) {
     63     int numEffects = fGLProcessors.count();
     64     SkASSERT(numEffects == fSamplers.count());
     65     for (int e = 0; e < numEffects; ++e) {
     66         SkTArray<Sampler, true>& samplers = fSamplers[e];
     67         int numSamplers = samplers.count();
     68         for (int s = 0; s < numSamplers; ++s) {
     69             SkASSERT(samplers[s].fUniform.isValid());
     70             programResourceManager.setSampler(samplers[s].fUniform, *texUnitIdx);
     71             samplers[s].fTextureUnit = (*texUnitIdx)++;
     72         }
     73     }
     74 }
     75 
     76 void GrGLProgramEffects::bindTextures(GrGpuGL* gpu, const GrProcessor& effect, int effectIdx) {
     77     const SkTArray<Sampler, true>& samplers = fSamplers[effectIdx];
     78     int numSamplers = samplers.count();
     79     SkASSERT(numSamplers == effect.numTextures());
     80     for (int s = 0; s < numSamplers; ++s) {
     81         SkASSERT(samplers[s].fTextureUnit >= 0);
     82         const GrTextureAccess& textureAccess = effect.textureAccess(s);
     83         gpu->bindTexture(samplers[s].fTextureUnit,
     84                          textureAccess.getParams(),
     85                          static_cast<GrGLTexture*>(textureAccess.getTexture()));
     86     }
     87 }
     88 
     89 ////////////////////////////////////////////////////////////////////////////////
     90 
     91 void GrGLVertexProgramEffects::setData(GrGpuGL* gpu,
     92                                        GrGpu::DrawType drawType,
     93                                        const GrGLProgramDataManager& programDataManager,
     94                                        const GrGeometryStage* effectStages) {
     95     SkASSERT(1 == fGLProcessors.count());
     96     SkASSERT(1 == fTransforms.count());
     97     SkASSERT(1 == fSamplers.count());
     98     this->setDataInternal(gpu, drawType, programDataManager, *effectStages, 0);
     99 }
    100 
    101 void GrGLVertexProgramEffects::setData(GrGpuGL* gpu,
    102                                        GrGpu::DrawType drawType,
    103                                        const GrGLProgramDataManager& programDataManager,
    104                                        const GrFragmentStage* effectStages[]) {
    105     int numEffects = fGLProcessors.count();
    106     SkASSERT(numEffects == fTransforms.count());
    107     SkASSERT(numEffects == fSamplers.count());
    108     for (int e = 0; e < numEffects; ++e) {
    109         this->setDataInternal(gpu, drawType, programDataManager, *effectStages[e], e);
    110     }
    111 }
    112 
    113 void GrGLVertexProgramEffects::setDataInternal(GrGpuGL* gpu,
    114                                                GrGpu::DrawType drawType,
    115                                                const GrGLProgramDataManager& programDataManager,
    116                                                const GrProcessorStage& effectStage,
    117                                                int index) {
    118     const GrProcessor& effect = *effectStage.getProcessor();
    119     fGLProcessors[index]->setData(programDataManager, effect);
    120     if (GrGpu::IsPathRenderingDrawType(drawType)) {
    121         this->setPathTransformData(gpu, programDataManager, effectStage, index);
    122     } else {
    123         this->setTransformData(gpu, programDataManager, effectStage, index);
    124     }
    125     this->bindTextures(gpu, effect, index);
    126 }
    127 
    128 void GrGLVertexProgramEffects::setTransformData(GrGpuGL* gpu,
    129                                                 const GrGLProgramDataManager& pdman,
    130                                                 const GrProcessorStage& effectStage,
    131                                                 int effectIdx) {
    132     SkTArray<Transform, true>& transforms = fTransforms[effectIdx];
    133     int numTransforms = transforms.count();
    134     SkASSERT(numTransforms == effectStage.getProcessor()->numTransforms());
    135     for (int t = 0; t < numTransforms; ++t) {
    136         SkASSERT(transforms[t].fHandle.isValid());
    137         const SkMatrix& matrix = get_transform_matrix(effectStage, fHasExplicitLocalCoords, t);
    138         if (!transforms[t].fCurrentValue.cheapEqualTo(matrix)) {
    139             pdman.setSkMatrix(transforms[t].fHandle, matrix);
    140             transforms[t].fCurrentValue = matrix;
    141         }
    142     }
    143 }
    144 
    145 void GrGLVertexProgramEffects::setPathTransformData(GrGpuGL* gpu,
    146                                                     const GrGLProgramDataManager& pdman,
    147                                                     const GrProcessorStage& effectStage,
    148                                                     int effectIdx) {
    149     SkTArray<PathTransform, true>& transforms = fPathTransforms[effectIdx];
    150     int numTransforms = transforms.count();
    151     SkASSERT(numTransforms == effectStage.getProcessor()->numTransforms());
    152     for (int t = 0; t < numTransforms; ++t) {
    153         SkASSERT(transforms[t].fHandle.isValid());
    154         const SkMatrix& transform = get_transform_matrix(effectStage, fHasExplicitLocalCoords, t);
    155         if (transforms[t].fCurrentValue.cheapEqualTo(transform)) {
    156             continue;
    157         }
    158         transforms[t].fCurrentValue = transform;
    159         switch (transforms[t].fType) {
    160             case kVec2f_GrSLType:
    161                 pdman.setProgramPathFragmentInputTransform(transforms[t].fHandle, 2, transform);
    162                 break;
    163             case kVec3f_GrSLType:
    164                 pdman.setProgramPathFragmentInputTransform(transforms[t].fHandle, 3, transform);
    165                 break;
    166             default:
    167                 SkFAIL("Unexpected matrix type.");
    168         }
    169     }
    170 }
    171 
    172 ////////////////////////////////////////////////////////////////////////////////
    173 
    174 void GrGLPathTexGenProgramEffects::setData(GrGpuGL* gpu,
    175                                            GrGpu::DrawType,
    176                                            const GrGLProgramDataManager& pdman,
    177                                            const GrFragmentStage* effectStages[]) {
    178     int numEffects = fGLProcessors.count();
    179     SkASSERT(numEffects == fTransforms.count());
    180     SkASSERT(numEffects == fSamplers.count());
    181     for (int e = 0; e < numEffects; ++e) {
    182         const GrProcessorStage& effectStage = *effectStages[e];
    183         const GrProcessor& effect = *effectStage.getProcessor();
    184         fGLProcessors[e]->setData(pdman, effect);
    185         this->setPathTexGenState(gpu, effectStage, e);
    186         this->bindTextures(gpu, effect, e);
    187     }
    188 }
    189 
    190 void GrGLPathTexGenProgramEffects::setPathTexGenState(GrGpuGL* gpu,
    191                                               const GrProcessorStage& effectStage,
    192                                               int effectIdx) {
    193     int texCoordIndex = fTransforms[effectIdx].fTexCoordIndex;
    194     int numTransforms = effectStage.getProcessor()->numTransforms();
    195     for (int t = 0; t < numTransforms; ++t) {
    196         const SkMatrix& transform = get_transform_matrix(effectStage, false, t);
    197         GrGLPathRendering::PathTexGenComponents components =
    198                 GrGLPathRendering::kST_PathTexGenComponents;
    199         if (effectStage.isPerspectiveCoordTransform(t, false)) {
    200             components = GrGLPathRendering::kSTR_PathTexGenComponents;
    201         }
    202         gpu->glPathRendering()->enablePathTexGen(texCoordIndex++, components, transform);
    203     }
    204 }
    205