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 "GrAllocator.h"
     11 #include "GrProcessor.h"
     12 #include "GrCoordTransform.h"
     13 #include "GrGLGpu.h"
     14 #include "GrGLBuffer.h"
     15 #include "GrGLPathRendering.h"
     16 #include "GrPathProcessor.h"
     17 #include "GrPipeline.h"
     18 #include "GrXferProcessor.h"
     19 #include "glsl/GrGLSLFragmentProcessor.h"
     20 #include "glsl/GrGLSLGeometryProcessor.h"
     21 #include "glsl/GrGLSLXferProcessor.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 ///////////////////////////////////////////////////////////////////////////////////////////////////
     27 
     28 GrGLProgram::GrGLProgram(GrGLGpu* gpu,
     29                          const GrProgramDesc& desc,
     30                          const BuiltinUniformHandles& builtinUniforms,
     31                          GrGLuint programID,
     32                          const UniformInfoArray& uniforms,
     33                          const UniformInfoArray& samplers,
     34                          const UniformInfoArray& imageStorages,
     35                          const VaryingInfoArray& pathProcVaryings,
     36                          GrGLSLPrimitiveProcessor* geometryProcessor,
     37                          GrGLSLXferProcessor* xferProcessor,
     38                          const GrGLSLFragProcs& fragmentProcessors)
     39     : fBuiltinUniformHandles(builtinUniforms)
     40     , fProgramID(programID)
     41     , fGeometryProcessor(geometryProcessor)
     42     , fXferProcessor(xferProcessor)
     43     , fFragmentProcessors(fragmentProcessors)
     44     , fDesc(desc)
     45     , fGpu(gpu)
     46     , fProgramDataManager(gpu, programID, uniforms, pathProcVaryings) {
     47     // Assign texture units to sampler uniforms one time up front.
     48     GL_CALL(UseProgram(fProgramID));
     49     fProgramDataManager.setSamplers(samplers);
     50     fProgramDataManager.setImageStorages(imageStorages);
     51 }
     52 
     53 GrGLProgram::~GrGLProgram() {
     54     if (fProgramID) {
     55         GL_CALL(DeleteProgram(fProgramID));
     56     }
     57     for (int i = 0; i < fFragmentProcessors.count(); ++i) {
     58         delete fFragmentProcessors[i];
     59     }
     60 }
     61 
     62 void GrGLProgram::abandon() {
     63     fProgramID = 0;
     64 }
     65 
     66 ///////////////////////////////////////////////////////////////////////////////
     67 
     68 void GrGLProgram::setData(const GrPrimitiveProcessor& primProc, const GrPipeline& pipeline) {
     69     this->setRenderTargetState(primProc, pipeline);
     70 
     71     // we set the textures, and uniforms for installed processors in a generic way, but subclasses
     72     // of GLProgram determine how to set coord transforms
     73     int nextSamplerIdx = 0;
     74     fGeometryProcessor->setData(fProgramDataManager, primProc,
     75                                 GrFragmentProcessor::CoordTransformIter(pipeline));
     76     this->bindTextures(primProc, pipeline.getAllowSRGBInputs(), &nextSamplerIdx);
     77 
     78     this->setFragmentData(primProc, pipeline, &nextSamplerIdx);
     79 
     80     const GrXferProcessor& xp = pipeline.getXferProcessor();
     81     fXferProcessor->setData(fProgramDataManager, xp);
     82     this->bindTextures(xp, pipeline.getAllowSRGBInputs(), &nextSamplerIdx);
     83 }
     84 
     85 void GrGLProgram::generateMipmaps(const GrPrimitiveProcessor& primProc,
     86                                   const GrPipeline& pipeline) {
     87     this->generateMipmaps(primProc, pipeline.getAllowSRGBInputs());
     88 
     89     GrFragmentProcessor::Iter iter(pipeline);
     90     while (const GrFragmentProcessor* fp  = iter.next()) {
     91         this->generateMipmaps(*fp, pipeline.getAllowSRGBInputs());
     92     }
     93 }
     94 
     95 void GrGLProgram::setFragmentData(const GrPrimitiveProcessor& primProc,
     96                                   const GrPipeline& pipeline,
     97                                   int* nextSamplerIdx) {
     98     GrFragmentProcessor::Iter iter(pipeline);
     99     GrGLSLFragmentProcessor::Iter glslIter(fFragmentProcessors.begin(),
    100                                            fFragmentProcessors.count());
    101     const GrFragmentProcessor* fp = iter.next();
    102     GrGLSLFragmentProcessor* glslFP = glslIter.next();
    103     while (fp && glslFP) {
    104         glslFP->setData(fProgramDataManager, *fp);
    105         this->bindTextures(*fp, pipeline.getAllowSRGBInputs(), nextSamplerIdx);
    106         fp = iter.next();
    107         glslFP = glslIter.next();
    108     }
    109     SkASSERT(!fp && !glslFP);
    110 }
    111 
    112 
    113 void GrGLProgram::setRenderTargetState(const GrPrimitiveProcessor& primProc,
    114                                        const GrPipeline& pipeline) {
    115     // Load the RT height uniform if it is needed to y-flip gl_FragCoord.
    116     if (fBuiltinUniformHandles.fRTHeightUni.isValid() &&
    117         fRenderTargetState.fRenderTargetSize.fHeight != pipeline.getRenderTarget()->height()) {
    118         fProgramDataManager.set1f(fBuiltinUniformHandles.fRTHeightUni,
    119                                    SkIntToScalar(pipeline.getRenderTarget()->height()));
    120     }
    121 
    122     // set RT adjustment
    123     const GrRenderTarget* rt = pipeline.getRenderTarget();
    124     SkISize size;
    125     size.set(rt->width(), rt->height());
    126     if (!primProc.isPathRendering()) {
    127         if (fRenderTargetState.fRenderTargetOrigin != rt->origin() ||
    128             fRenderTargetState.fRenderTargetSize != size) {
    129             fRenderTargetState.fRenderTargetSize = size;
    130             fRenderTargetState.fRenderTargetOrigin = rt->origin();
    131 
    132             float rtAdjustmentVec[4];
    133             fRenderTargetState.getRTAdjustmentVec(rtAdjustmentVec);
    134             fProgramDataManager.set4fv(fBuiltinUniformHandles.fRTAdjustmentUni, 1, rtAdjustmentVec);
    135         }
    136     } else {
    137         SkASSERT(fGpu->glCaps().shaderCaps()->pathRenderingSupport());
    138         const GrPathProcessor& pathProc = primProc.cast<GrPathProcessor>();
    139         fGpu->glPathRendering()->setProjectionMatrix(pathProc.viewMatrix(),
    140                                                      size, rt->origin());
    141     }
    142 }
    143 
    144 void GrGLProgram::bindTextures(const GrProcessor& processor,
    145                                bool allowSRGBInputs,
    146                                int* nextSamplerIdx) {
    147     for (int i = 0; i < processor.numTextureSamplers(); ++i) {
    148         const GrProcessor::TextureSampler& sampler = processor.textureSampler(i);
    149         fGpu->bindTexture((*nextSamplerIdx)++, sampler.params(),
    150                           allowSRGBInputs, static_cast<GrGLTexture*>(sampler.texture()));
    151     }
    152     for (int i = 0; i < processor.numBuffers(); ++i) {
    153         const GrProcessor::BufferAccess& access = processor.bufferAccess(i);
    154         fGpu->bindTexelBuffer((*nextSamplerIdx)++, access.texelConfig(),
    155                               static_cast<GrGLBuffer*>(access.buffer()));
    156     }
    157     for (int i = 0; i < processor.numImageStorages(); ++i) {
    158         const GrProcessor::ImageStorageAccess& access = processor.imageStorageAccess(i);
    159         fGpu->bindImageStorage((*nextSamplerIdx)++, access.ioType(),
    160                                static_cast<GrGLTexture *>(access.texture()));
    161     }
    162 }
    163 
    164 void GrGLProgram::generateMipmaps(const GrProcessor& processor,
    165                                   bool allowSRGBInputs) {
    166     for (int i = 0; i < processor.numTextureSamplers(); ++i) {
    167         const GrProcessor::TextureSampler& sampler = processor.textureSampler(i);
    168         fGpu->generateMipmaps(sampler.params(), allowSRGBInputs,
    169                               static_cast<GrGLTexture*>(sampler.texture()));
    170     }
    171 }
    172