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& textureSamplers,
     34                          const UniformInfoArray& texelBuffers,
     35                          const VaryingInfoArray& pathProcVaryings,
     36                          std::unique_ptr<GrGLSLPrimitiveProcessor> geometryProcessor,
     37                          std::unique_ptr<GrGLSLXferProcessor> xferProcessor,
     38                          const GrGLSLFragProcs& fragmentProcessors)
     39     : fBuiltinUniformHandles(builtinUniforms)
     40     , fProgramID(programID)
     41     , fGeometryProcessor(std::move(geometryProcessor))
     42     , fXferProcessor(std::move(xferProcessor))
     43     , fFragmentProcessors(fragmentProcessors)
     44     , fDesc(desc)
     45     , fGpu(gpu)
     46     , fProgramDataManager(gpu, programID, uniforms, pathProcVaryings)
     47     , fNumTextureSamplers(textureSamplers.count())
     48     , fNumTexelBuffers(texelBuffers.count()) {
     49     // Assign texture units to sampler uniforms one time up front.
     50     GL_CALL(UseProgram(fProgramID));
     51     fProgramDataManager.setSamplerUniforms(textureSamplers, 0);
     52     fProgramDataManager.setSamplerUniforms(texelBuffers, fNumTextureSamplers);
     53 }
     54 
     55 GrGLProgram::~GrGLProgram() {
     56     if (fProgramID) {
     57         GL_CALL(DeleteProgram(fProgramID));
     58     }
     59     for (int i = 0; i < fFragmentProcessors.count(); ++i) {
     60         delete fFragmentProcessors[i];
     61     }
     62 }
     63 
     64 void GrGLProgram::abandon() {
     65     fProgramID = 0;
     66 }
     67 
     68 ///////////////////////////////////////////////////////////////////////////////
     69 
     70 void GrGLProgram::setData(const GrPrimitiveProcessor& primProc, const GrPipeline& pipeline) {
     71     this->setRenderTargetState(primProc, pipeline.proxy());
     72 
     73     // we set the textures, and uniforms for installed processors in a generic way, but subclasses
     74     // of GLProgram determine how to set coord transforms
     75 
     76     // We must bind to texture units in the same order in which we set the uniforms in
     77     // GrGLProgramDataManager. That is first all texture samplers and then texel buffers.
     78     // Within each group we will bind them in primProc, fragProcs, XP order.
     79     int nextTexSamplerIdx = 0;
     80     int nextTexelBufferIdx = fNumTextureSamplers;
     81     fGeometryProcessor->setData(fProgramDataManager, primProc,
     82                                 GrFragmentProcessor::CoordTransformIter(pipeline));
     83     this->bindTextures(primProc, pipeline.getAllowSRGBInputs(), &nextTexSamplerIdx,
     84                        &nextTexelBufferIdx);
     85 
     86     this->setFragmentData(primProc, pipeline, &nextTexSamplerIdx, &nextTexelBufferIdx);
     87 
     88     const GrXferProcessor& xp = pipeline.getXferProcessor();
     89     SkIPoint offset;
     90     GrTexture* dstTexture = pipeline.peekDstTexture(&offset);
     91 
     92     fXferProcessor->setData(fProgramDataManager, xp, dstTexture, offset);
     93     if (dstTexture) {
     94         fGpu->bindTexture(nextTexSamplerIdx++, GrSamplerState::ClampNearest(), true,
     95                           static_cast<GrGLTexture*>(dstTexture),
     96                           pipeline.dstTextureProxy()->origin());
     97     }
     98     SkASSERT(nextTexSamplerIdx == fNumTextureSamplers);
     99     SkASSERT(nextTexelBufferIdx == fNumTextureSamplers + fNumTexelBuffers);
    100 }
    101 
    102 void GrGLProgram::generateMipmaps(const GrPrimitiveProcessor& primProc,
    103                                   const GrPipeline& pipeline) {
    104     this->generateMipmaps(primProc, pipeline.getAllowSRGBInputs());
    105 
    106     GrFragmentProcessor::Iter iter(pipeline);
    107     while (const GrFragmentProcessor* fp  = iter.next()) {
    108         this->generateMipmaps(*fp, pipeline.getAllowSRGBInputs());
    109     }
    110 }
    111 
    112 void GrGLProgram::setFragmentData(const GrPrimitiveProcessor& primProc,
    113                                   const GrPipeline& pipeline,
    114                                   int* nextTexSamplerIdx,
    115                                   int* nextTexelBufferIdx) {
    116     GrFragmentProcessor::Iter iter(pipeline);
    117     GrGLSLFragmentProcessor::Iter glslIter(fFragmentProcessors.begin(),
    118                                            fFragmentProcessors.count());
    119     const GrFragmentProcessor* fp = iter.next();
    120     GrGLSLFragmentProcessor* glslFP = glslIter.next();
    121     while (fp && glslFP) {
    122         glslFP->setData(fProgramDataManager, *fp);
    123         this->bindTextures(*fp, pipeline.getAllowSRGBInputs(), nextTexSamplerIdx,
    124                            nextTexelBufferIdx);
    125         fp = iter.next();
    126         glslFP = glslIter.next();
    127     }
    128     SkASSERT(!fp && !glslFP);
    129 }
    130 
    131 
    132 void GrGLProgram::setRenderTargetState(const GrPrimitiveProcessor& primProc,
    133                                        const GrRenderTargetProxy* proxy) {
    134     GrRenderTarget* rt = proxy->priv().peekRenderTarget();
    135     // Load the RT height uniform if it is needed to y-flip gl_FragCoord.
    136     if (fBuiltinUniformHandles.fRTHeightUni.isValid() &&
    137         fRenderTargetState.fRenderTargetSize.fHeight != rt->height()) {
    138         fProgramDataManager.set1f(fBuiltinUniformHandles.fRTHeightUni, SkIntToScalar(rt->height()));
    139     }
    140 
    141     // set RT adjustment
    142     SkISize size;
    143     size.set(rt->width(), rt->height());
    144     if (!primProc.isPathRendering()) {
    145         if (fRenderTargetState.fRenderTargetOrigin != proxy->origin() ||
    146             fRenderTargetState.fRenderTargetSize != size) {
    147             fRenderTargetState.fRenderTargetSize = size;
    148             fRenderTargetState.fRenderTargetOrigin = proxy->origin();
    149 
    150             float rtAdjustmentVec[4];
    151             fRenderTargetState.getRTAdjustmentVec(rtAdjustmentVec);
    152             fProgramDataManager.set4fv(fBuiltinUniformHandles.fRTAdjustmentUni, 1, rtAdjustmentVec);
    153         }
    154     } else {
    155         SkASSERT(fGpu->glCaps().shaderCaps()->pathRenderingSupport());
    156         const GrPathProcessor& pathProc = primProc.cast<GrPathProcessor>();
    157         fGpu->glPathRendering()->setProjectionMatrix(pathProc.viewMatrix(),
    158                                                      size, proxy->origin());
    159     }
    160 }
    161 
    162 void GrGLProgram::bindTextures(const GrResourceIOProcessor& processor,
    163                                bool allowSRGBInputs,
    164                                int* nextTexSamplerIdx,
    165                                int* nextTexelBufferIdx) {
    166     for (int i = 0; i < processor.numTextureSamplers(); ++i) {
    167         const GrResourceIOProcessor::TextureSampler& sampler = processor.textureSampler(i);
    168         fGpu->bindTexture((*nextTexSamplerIdx)++, sampler.samplerState(), allowSRGBInputs,
    169                           static_cast<GrGLTexture*>(sampler.peekTexture()),
    170                           sampler.proxy()->origin());
    171     }
    172     for (int i = 0; i < processor.numBuffers(); ++i) {
    173         const GrResourceIOProcessor::BufferAccess& access = processor.bufferAccess(i);
    174         fGpu->bindTexelBuffer((*nextTexelBufferIdx)++, access.texelConfig(),
    175                               static_cast<GrGLBuffer*>(access.buffer()));
    176     }
    177 }
    178 
    179 void GrGLProgram::generateMipmaps(const GrResourceIOProcessor& processor, bool allowSRGBInputs) {
    180     for (int i = 0; i < processor.numTextureSamplers(); ++i) {
    181         const GrResourceIOProcessor::TextureSampler& sampler = processor.textureSampler(i);
    182         fGpu->generateMipmaps(sampler.samplerState(), allowSRGBInputs,
    183                               static_cast<GrGLTexture*>(sampler.peekTexture()),
    184                               sampler.proxy()->origin());
    185     }
    186 }
    187