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 
9 #ifndef GrGLProgram_DEFINED
10 #define GrGLProgram_DEFINED
11 
12 #include "GrGLContext.h"
13 #include "GrProgramDesc.h"
14 #include "GrGLTexture.h"
15 #include "GrGLProgramDataManager.h"
16 #include "glsl/GrGLSLProgramDataManager.h"
17 #include "glsl/GrGLSLUniformHandler.h"
18 
19 #include "SkString.h"
20 
21 #include "builders/GrGLProgramBuilder.h"
22 
23 class GrGLInstalledProcessors;
24 class GrGLProgramBuilder;
25 class GrPipeline;
26 
27 /**
28  * This class manages a GPU program and records per-program information.
29  * We can specify the attribute locations so that they are constant
30  * across our shaders. But the driver determines the uniform locations
31  * at link time. We don't need to remember the sampler uniform location
32  * because we will bind a texture slot to it and never change it
33  * Uniforms are program-local so we can't rely on fHWState to hold the
34  * previous uniform state after a program change.
35  */
36 class GrGLProgram : public SkRefCnt {
37 public:
38     typedef GrGLSLProgramBuilder::BuiltinUniformHandles BuiltinUniformHandles;
39 
40     ~GrGLProgram();
41 
42     /**
43      * Call to abandon GL objects owned by this program.
44      */
45     void abandon();
46 
getDesc()47     const GrProgramDesc& getDesc() { return fDesc; }
48 
49     /**
50      * Gets the GL program ID for this program.
51      */
programID()52     GrGLuint programID() const { return fProgramID; }
53 
54     /**
55      * We use the RT's size and origin to adjust from Skia device space to OpenGL normalized device
56      * space and to make device space positions have the correct origin for processors that require
57      * them.
58      */
59     struct RenderTargetState {
60         SkISize         fRenderTargetSize;
61         GrSurfaceOrigin fRenderTargetOrigin;
62 
RenderTargetStateRenderTargetState63         RenderTargetState() { this->invalidate(); }
invalidateRenderTargetState64         void invalidate() {
65             fRenderTargetSize.fWidth = -1;
66             fRenderTargetSize.fHeight = -1;
67             fRenderTargetOrigin = (GrSurfaceOrigin) -1;
68         }
69 
70         /**
71          * Gets a vec4 that adjusts the position from Skia device coords to GL's normalized device
72          * coords. Assuming the transformed position, pos, is a homogeneous vec3, the vec, v, is
73          * applied as such:
74          * pos.x = dot(v.xy, pos.xz)
75          * pos.y = dot(v.zw, pos.yz)
76          */
getRTAdjustmentVecRenderTargetState77         void getRTAdjustmentVec(float* destVec) {
78             destVec[0] = 2.f / fRenderTargetSize.fWidth;
79             destVec[1] = -1.f;
80             if (kBottomLeft_GrSurfaceOrigin == fRenderTargetOrigin) {
81                 destVec[2] = -2.f / fRenderTargetSize.fHeight;
82                 destVec[3] = 1.f;
83             } else {
84                 destVec[2] = 2.f / fRenderTargetSize.fHeight;
85                 destVec[3] = -1.f;
86             }
87         }
88     };
89 
90     /**
91      * This function uploads uniforms, calls each GrGL*Processor's setData, and retrieves the
92      * textures that need to be bound on each unit. It is the caller's responsibility to ensure
93      * the program is bound before calling, and to bind the outgoing textures to their respective
94      * units upon return. (Each index in the array corresponds to its matching GL texture unit.)
95      */
96     void setData(const GrPrimitiveProcessor&, const GrPipeline&);
97 
98     /**
99      * This function retrieves the textures that need to be used by each GrGL*Processor, and
100      * ensures that any textures requiring mipmaps have their mipmaps correctly built.
101      */
102     void generateMipmaps(const GrPrimitiveProcessor&, const GrPipeline&);
103 
104 protected:
105     using UniformHandle    = GrGLSLProgramDataManager::UniformHandle ;
106     using UniformInfoArray = GrGLProgramDataManager::UniformInfoArray;
107     using VaryingInfoArray = GrGLProgramDataManager::VaryingInfoArray;
108 
109     GrGLProgram(GrGLGpu*,
110                 const GrProgramDesc&,
111                 const BuiltinUniformHandles&,
112                 GrGLuint programID,
113                 const UniformInfoArray& uniforms,
114                 const UniformInfoArray& samplers,
115                 const UniformInfoArray& imageStorages,
116                 const VaryingInfoArray&, // used for NVPR only currently
117                 GrGLSLPrimitiveProcessor* geometryProcessor,
118                 GrGLSLXferProcessor* xferProcessor,
119                 const GrGLSLFragProcs& fragmentProcessors);
120 
121     // A helper to loop over effects, set the transforms (via subclass) and bind textures
122     void setFragmentData(const GrPrimitiveProcessor&, const GrPipeline&, int* nextSamplerIdx);
123 
124     // Helper for setData() that sets the view matrix and loads the render target height uniform
125     void setRenderTargetState(const GrPrimitiveProcessor&, const GrPipeline&);
126 
127     // Helper for setData() that binds textures and texel buffers to the appropriate texture units
128     void bindTextures(const GrProcessor&, bool allowSRGBInputs, int* nextSamplerIdx);
129 
130     // Helper for generateMipmaps() that ensures mipmaps are up to date
131     void generateMipmaps(const GrProcessor&, bool allowSRGBInputs);
132 
133     // these reflect the current values of uniforms (GL uniform values travel with program)
134     RenderTargetState fRenderTargetState;
135     BuiltinUniformHandles fBuiltinUniformHandles;
136     GrGLuint fProgramID;
137 
138     // the installed effects
139     std::unique_ptr<GrGLSLPrimitiveProcessor> fGeometryProcessor;
140     std::unique_ptr<GrGLSLXferProcessor> fXferProcessor;
141     GrGLSLFragProcs fFragmentProcessors;
142 
143     GrProgramDesc fDesc;
144     GrGLGpu* fGpu;
145     GrGLProgramDataManager fProgramDataManager;
146 
147     friend class GrGLProgramBuilder;
148 
149     typedef SkRefCnt INHERITED;
150 };
151 
152 #endif
153