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 "src/gpu/gl/GrGLProgramDataManager.h"
13 #include "src/gpu/glsl/GrGLSLProgramDataManager.h"
14 #include "src/gpu/glsl/GrGLSLUniformHandler.h"
15 
16 class GrGLSLFragmentProcessor;
17 class GrGLSLPrimitiveProcessor;
18 class GrGLSLXferProcessor;
19 class GrPipeline;
20 class GrPrimitiveProcessor;
21 class GrProgramInfo;
22 class GrRenderTarget;
23 class GrTextureProxy;
24 
25 /**
26  * This class manages a GPU program and records per-program information. It also records the vertex
27  * and instance attribute layouts that are to be used with the program.
28  */
29 class GrGLProgram : public SkRefCnt {
30 public:
31     /**
32      * This class has its own Attribute representation as it does not need the name and we don't
33      * want to worry about copying the name string to memory with life time of GrGLProgram.
34      * Additionally, these store the attribute location.
35      */
36     struct Attribute {
37         GrVertexAttribType fCPUType;
38         GrSLType fGPUType;
39         size_t fOffset;
40         GrGLint fLocation;
41     };
42 
43     using UniformHandle = GrGLSLProgramDataManager::UniformHandle;
44     using UniformInfoArray = GrGLProgramDataManager::UniformInfoArray;
45     using VaryingInfoArray = GrGLProgramDataManager::VaryingInfoArray;
46 
47     /**
48      * The attribute array consists of vertexAttributeCnt + instanceAttributeCnt elements with
49      * the vertex attributes preceding the instance attributes.
50      */
51     GrGLProgram(GrGLGpu*,
52                 const GrGLSLBuiltinUniformHandles&,
53                 GrGLuint programID,
54                 const UniformInfoArray& uniforms,
55                 const UniformInfoArray& textureSamplers,
56                 const VaryingInfoArray&, // used for NVPR only currently
57                 std::unique_ptr<GrGLSLPrimitiveProcessor> geometryProcessor,
58                 std::unique_ptr<GrGLSLXferProcessor> xferProcessor,
59                 std::unique_ptr<std::unique_ptr<GrGLSLFragmentProcessor>[]> fragmentProcessors,
60                 int fragmentProcessorCnt,
61                 std::unique_ptr<Attribute[]>,
62                 int vertexAttributeCnt,
63                 int instanceAttributeCnt,
64                 int vertexStride,
65                 int instanceStride);
66 
67     ~GrGLProgram();
68 
69     /**
70      * Call to abandon GL objects owned by this program.
71      */
72     void abandon();
73 
74     /**
75      * Gets the GL program ID for this program.
76      */
programID()77     GrGLuint programID() const { return fProgramID; }
78 
79     /**
80      * We use the RT's size and origin to adjust from Skia device space to OpenGL normalized device
81      * space and to make device space positions have the correct origin for processors that require
82      * them.
83      */
84     struct RenderTargetState {
85         SkISize         fRenderTargetSize;
86         GrSurfaceOrigin fRenderTargetOrigin;
87 
RenderTargetStateRenderTargetState88         RenderTargetState() { this->invalidate(); }
invalidateRenderTargetState89         void invalidate() {
90             fRenderTargetSize.fWidth = -1;
91             fRenderTargetSize.fHeight = -1;
92             fRenderTargetOrigin = (GrSurfaceOrigin) -1;
93         }
94 
95         /**
96          * Gets a float4 that adjusts the position from Skia device coords to GL's normalized device
97          * coords. Assuming the transformed position, pos, is a homogeneous float3, the vec, v, is
98          * applied as such:
99          * pos.x = dot(v.xy, pos.xz)
100          * pos.y = dot(v.zw, pos.yz)
101          */
getRTAdjustmentVecRenderTargetState102         void getRTAdjustmentVec(float* destVec) {
103             destVec[0] = 2.f / fRenderTargetSize.fWidth;
104             destVec[1] = -1.f;
105             if (kBottomLeft_GrSurfaceOrigin == fRenderTargetOrigin) {
106                 destVec[2] = -2.f / fRenderTargetSize.fHeight;
107                 destVec[3] = 1.f;
108             } else {
109                 destVec[2] = 2.f / fRenderTargetSize.fHeight;
110                 destVec[3] = -1.f;
111             }
112         }
113     };
114 
115     /**
116      * This function uploads uniforms, calls each GrGLSL*Processor's setData. It binds all fragment
117      * processor textures. Primitive process textures can be bound using this function or by
118      * calling updatePrimitiveProcessorTextureBindings.
119      *
120      * It is the caller's responsibility to ensure the program is bound before calling.
121      */
122     void updateUniformsAndTextureBindings(const GrRenderTarget*, const GrProgramInfo&);
123 
124     void updatePrimitiveProcessorTextureBindings(const GrPrimitiveProcessor&,
125                                                  const GrTextureProxy* const[]);
126 
vertexStride()127     int vertexStride() const { return fVertexStride; }
instanceStride()128     int instanceStride() const { return fInstanceStride; }
129 
numVertexAttributes()130     int numVertexAttributes() const { return fVertexAttributeCnt; }
vertexAttribute(int i)131     const Attribute& vertexAttribute(int i) const {
132         SkASSERT(i >= 0 && i < fVertexAttributeCnt);
133         return fAttributes[i];
134     }
135 
numInstanceAttributes()136     int numInstanceAttributes() const { return fInstanceAttributeCnt; }
instanceAttribute(int i)137     const Attribute& instanceAttribute(int i) const {
138         SkASSERT(i >= 0 && i < fInstanceAttributeCnt);
139         return fAttributes[i + fVertexAttributeCnt];
140     }
141 
142 private:
143     // A helper to loop over effects, set the transforms (via subclass) and bind textures
144     void setFragmentData(const GrPipeline&, int* nextTexSamplerIdx);
145 
146     // Helper for setData() that sets the view matrix and loads the render target height uniform
147     void setRenderTargetState(const GrRenderTarget*, GrSurfaceOrigin, const GrPrimitiveProcessor&);
148 
149     // these reflect the current values of uniforms (GL uniform values travel with program)
150     RenderTargetState fRenderTargetState;
151     GrGLSLBuiltinUniformHandles fBuiltinUniformHandles;
152     GrGLuint fProgramID;
153 
154     // the installed effects
155     std::unique_ptr<GrGLSLPrimitiveProcessor> fPrimitiveProcessor;
156     std::unique_ptr<GrGLSLXferProcessor> fXferProcessor;
157     std::unique_ptr<std::unique_ptr<GrGLSLFragmentProcessor>[]> fFragmentProcessors;
158     int fFragmentProcessorCnt;
159 
160     std::unique_ptr<Attribute[]> fAttributes;
161     int fVertexAttributeCnt;
162     int fInstanceAttributeCnt;
163     int fVertexStride;
164     int fInstanceStride;
165 
166     GrGLGpu* fGpu;
167     GrGLProgramDataManager fProgramDataManager;
168 
169     int fNumTextureSamplers;
170 
171     typedef SkRefCnt INHERITED;
172 };
173 
174 #endif
175