blob: 1611ca21c4bac72c0524360c189df649e93a319c [file] [log] [blame]
junov@google.comf93e7172011-03-31 21:26:24 +00001/*
2 Copyright 2011 Google Inc.
3
4 Licensed under the Apache License, Version 2.0 (the "License");
5 you may not use this file except in compliance with the License.
6 You may obtain a copy of the License at
7
8 http://www.apache.org/licenses/LICENSE-2.0
9
10 Unless required by applicable law or agreed to in writing, software
11 distributed under the License is distributed on an "AS IS" BASIS,
12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 See the License for the specific language governing permissions and
14 limitations under the License.
15 */
16
17#ifndef GrGLProgram_DEFINED
18#define GrGLProgram_DEFINED
19
20#include "GrGLInterface.h"
bsalomon@google.com91961302011-05-09 18:39:58 +000021#include "GrStringBuilder.h"
junov@google.comf93e7172011-03-31 21:26:24 +000022#include "GrDrawTarget.h"
23
Scroggo97c88c22011-05-11 14:05:25 +000024#include "SkXfermode.h"
25
junov@google.comf93e7172011-03-31 21:26:24 +000026class GrBinHashKeyBuilder;
27class GrGLEffect;
28struct ShaderCodeSegments;
29
30/**
31 * This class manages a GPU program and records per-program information.
32 * We can specify the attribute locations so that they are constant
33 * across our shaders. But the driver determines the uniform locations
34 * at link time. We don't need to remember the sampler uniform location
35 * because we will bind a texture slot to it and never change it
36 * Uniforms are program-local so we can't rely on fHWState to hold the
37 * previous uniform state after a program change.
38 */
39class GrGLProgram {
40public:
41 class CachedData;
42
43 GrGLProgram();
44 ~GrGLProgram();
45
46 /**
47 * Streams data that can uniquely identifies the generated
48 * gpu program into a key, for cache indexing purposes.
49 *
50 * @param key The key object to receive the key data
51 */
52 void buildKey(GrBinHashKeyBuilder& key) const;
53
54 /**
55 * This is the heavy initilization routine for building a GLProgram.
56 * The result of heavy init is not stored in datamembers of GrGLProgam,
57 * but in a separate cacheable container.
58 */
bsalomon@google.com91961302011-05-09 18:39:58 +000059 bool genProgram(CachedData* programData) const;
junov@google.comf93e7172011-03-31 21:26:24 +000060
61 /**
62 * Routine that is called before rendering. Sets-up all the state and
63 * other initializations required for the Gpu Program to run.
64 */
65 bool doGLSetup(GrPrimitiveType type, CachedData* programData) const;
66
67 /**
68 * Routine that is called after rendering. Performs state restoration.
69 * May perform secondary render passes.
70 */
71 void doGLPost() const;
72
73 /**
74 * Configures the GrGLProgram based on the state of a GrDrawTarget
75 * object. This is the fast and light initialization. Retrieves all the
76 * state that is required for performing the heavy init (i.e. genProgram),
77 * or for retrieving heavy init results from cache.
78 */
79 void buildFromTarget(const GrDrawTarget* target);
80
bsalomon@google.com91961302011-05-09 18:39:58 +000081 static int PositionAttributeIdx() { return 0; }
82 static int TexCoordAttributeIdx(int tcIdx) { return 1 + tcIdx; }
83 static int ColorAttributeIdx() { return 1 + GrDrawTarget::kMaxTexCoords; }
84 static int ViewMatrixAttributeIdx() {
85 return 2 + GrDrawTarget::kMaxTexCoords;
86 }
87 static int TextureMatrixAttributeIdx(int stage) {
88 return 5 + GrDrawTarget::kMaxTexCoords + 3 * stage;
89 }
90
junov@google.comf93e7172011-03-31 21:26:24 +000091private:
92
93 //Parameters that affect code generation
94 struct ProgramDesc {
bsalomon@google.com4be283f2011-04-19 21:15:09 +000095 ProgramDesc() {
96 // since we use this as part of a key we can't have any unitialized
97 // padding
98 memset(this, 0, sizeof(ProgramDesc));
99 }
100
101 // stripped of bits that don't affect prog generation
junov@google.comf93e7172011-03-31 21:26:24 +0000102 GrVertexLayout fVertexLayout;
103
104 enum {
bsalomon@google.com4be283f2011-04-19 21:15:09 +0000105 kNone_ColorType = 0,
106 kAttribute_ColorType = 1,
107 kUniform_ColorType = 2,
108 } fColorType;
109
110 bool fEmitsPointSize;
senorblanco@chromium.org92e0f222011-05-12 15:49:15 +0000111 bool fUsesEdgeAA;
junov@google.comf93e7172011-03-31 21:26:24 +0000112
Scroggo97c88c22011-05-11 14:05:25 +0000113 SkXfermode::Mode fColorFilterXfermode;
114
junov@google.comf93e7172011-03-31 21:26:24 +0000115 struct StageDesc {
116 enum OptFlagBits {
117 kNoPerspective_OptFlagBit = 0x1,
118 kIdentityMatrix_OptFlagBit = 0x2
119 };
120
bsalomon@google.com6aef1fb2011-05-05 12:33:22 +0000121 unsigned fOptFlags;
122 bool fEnabled;
junov@google.comf93e7172011-03-31 21:26:24 +0000123
124 enum Modulation {
125 kColor_Modulation,
126 kAlpha_Modulation
bsalomon@google.com6aef1fb2011-05-05 12:33:22 +0000127 } fModulation;
128
129 enum FetchMode {
130 kSingle_FetchMode,
131 k2x2_FetchMode
132 } fFetchMode;
junov@google.comf93e7172011-03-31 21:26:24 +0000133
134 enum CoordMapping {
135 kIdentity_CoordMapping,
136 kRadialGradient_CoordMapping,
137 kSweepGradient_CoordMapping,
138 kRadial2Gradient_CoordMapping
bsalomon@google.com6aef1fb2011-05-05 12:33:22 +0000139 } fCoordMapping;
junov@google.comf93e7172011-03-31 21:26:24 +0000140 } fStages[GrDrawTarget::kNumStages];
141 } fProgramDesc;
142
bsalomon@google.com4be283f2011-04-19 21:15:09 +0000143 const ProgramDesc& getDesc() { return fProgramDesc; }
144
junov@google.comf93e7172011-03-31 21:26:24 +0000145public:
bsalomon@google.com91961302011-05-09 18:39:58 +0000146 enum {
147 kUnusedUniform = -1,
148 kSetAsAttribute = 1000,
149 };
150
junov@google.comf93e7172011-03-31 21:26:24 +0000151 struct StageUniLocations {
152 GrGLint fTextureMatrixUni;
bsalomon@google.com6aef1fb2011-05-05 12:33:22 +0000153 GrGLint fNormalizedTexelSizeUni;
junov@google.comf93e7172011-03-31 21:26:24 +0000154 GrGLint fSamplerUni;
155 GrGLint fRadial2Uni;
bsalomon@google.com91961302011-05-09 18:39:58 +0000156 void reset() {
157 fTextureMatrixUni = kUnusedUniform;
158 fNormalizedTexelSizeUni = kUnusedUniform;
159 fSamplerUni = kUnusedUniform;
160 fRadial2Uni = kUnusedUniform;
161 }
junov@google.comf93e7172011-03-31 21:26:24 +0000162 };
163
164 struct UniLocations {
165 GrGLint fViewMatrixUni;
bsalomon@google.com4be283f2011-04-19 21:15:09 +0000166 GrGLint fColorUni;
senorblanco@chromium.org92e0f222011-05-12 15:49:15 +0000167 GrGLint fEdgesUni;
Scroggo97c88c22011-05-11 14:05:25 +0000168 GrGLint fColorFilterUni;
junov@google.comf93e7172011-03-31 21:26:24 +0000169 StageUniLocations fStages[GrDrawTarget::kNumStages];
bsalomon@google.com91961302011-05-09 18:39:58 +0000170 void reset() {
171 fViewMatrixUni = kUnusedUniform;
172 fColorUni = kUnusedUniform;
senorblanco@chromium.org92e0f222011-05-12 15:49:15 +0000173 fEdgesUni = kUnusedUniform;
Scroggo97c88c22011-05-11 14:05:25 +0000174 fColorFilterUni = kUnusedUniform;
bsalomon@google.com91961302011-05-09 18:39:58 +0000175 for (int s = 0; s < GrDrawTarget::kNumStages; ++s) {
176 fStages[s].reset();
177 }
178 }
junov@google.comf93e7172011-03-31 21:26:24 +0000179 };
180
181 class CachedData : public ::GrNoncopyable {
182 public:
183 CachedData() {
184 GR_DEBUGCODE(fEffectUniCount = 0;)
185 fEffectUniLocationsExtended = NULL;
186 }
187
188 ~CachedData() {
189 GrFree(fEffectUniLocationsExtended);
190 }
191
192 void copyAndTakeOwnership(CachedData& other) {
bsalomon@google.com2d9ddf92011-05-11 16:52:59 +0000193 memcpy(this, &other, sizeof(*this));
junov@google.comf93e7172011-03-31 21:26:24 +0000194 other.fEffectUniLocationsExtended = NULL; // ownership transfer
195 GR_DEBUGCODE(other.fEffectUniCount = 0;)
196 }
197
198 void setEffectUniformCount(size_t effectUniforms) {
199 GR_DEBUGCODE(fEffectUniCount = effectUniforms;)
200 GrFree(fEffectUniLocationsExtended);
201 if (effectUniforms > kUniLocationPreAllocSize) {
202 fEffectUniLocationsExtended = (GrGLint*)GrMalloc(sizeof(GrGLint)*(effectUniforms-kUniLocationPreAllocSize));
203 } else {
204 fEffectUniLocationsExtended = NULL;
205 }
206 }
207
208 GrGLint& effectUniLocation(size_t index) {
209 GrAssert(index < fEffectUniCount);
210 return (index < kUniLocationPreAllocSize) ?
211 fEffectUniLocations[index] :
212 fEffectUniLocationsExtended[index - kUniLocationPreAllocSize];
213 }
214
215 public:
216
217 // IDs
218 GrGLuint fVShaderID;
219 GrGLuint fFShaderID;
220 GrGLuint fProgramID;
221 // shader uniform locations (-1 if shader doesn't use them)
222 UniLocations fUniLocations;
223
224 GrMatrix fViewMatrix;
225
226 // these reflect the current values of uniforms
227 // (GL uniform values travel with program)
bsalomon@google.com4be283f2011-04-19 21:15:09 +0000228 GrColor fColor;
Scroggo97c88c22011-05-11 14:05:25 +0000229 GrColor fColorFilterColor;
junov@google.comf93e7172011-03-31 21:26:24 +0000230 GrMatrix fTextureMatrices[GrDrawTarget::kNumStages];
bsalomon@google.com6aef1fb2011-05-05 12:33:22 +0000231 // width and height used for normalized texel size
232 int fTextureWidth[GrDrawTarget::kNumStages];
233 int fTextureHeight[GrDrawTarget::kNumStages];
junov@google.comf93e7172011-03-31 21:26:24 +0000234 GrScalar fRadial2CenterX1[GrDrawTarget::kNumStages];
235 GrScalar fRadial2Radius0[GrDrawTarget::kNumStages];
236 bool fRadial2PosRoot[GrDrawTarget::kNumStages];
237
238 private:
239 enum Constants {
240 kUniLocationPreAllocSize = 8
241 };
242
243 GrGLint fEffectUniLocations[kUniLocationPreAllocSize];
244 GrGLint* fEffectUniLocationsExtended;
245 GR_DEBUGCODE(size_t fEffectUniCount;)
246 }; // CachedData
247
248 GrGLEffect* fStageEffects[GrDrawTarget::kNumStages];
249
250private:
bsalomon@google.com91961302011-05-09 18:39:58 +0000251 enum {
252 kUseUniform = 2000
253 };
254
255 // should set all fields in locations var to kUseUniform if the
256 // corresponding uniform is required for the program.
junov@google.comf93e7172011-03-31 21:26:24 +0000257 void genStageCode(int stageNum,
258 const ProgramDesc::StageDesc& desc,
259 const char* fsInColor, // NULL means no incoming color
260 const char* fsOutColor,
261 const char* vsInCoord,
262 ShaderCodeSegments* segments,
263 StageUniLocations* locations) const;
264
bsalomon@google.com91961302011-05-09 18:39:58 +0000265 static bool CompileFSAndVS(const ShaderCodeSegments& segments,
266 CachedData* programData);
267
junov@google.comf93e7172011-03-31 21:26:24 +0000268 // Compiles a GL shader, returns shader ID or 0 if failed
269 // params have same meaning as glShaderSource
270 static GrGLuint CompileShader(GrGLenum type, int stringCnt,
271 const char** strings,
272 int* stringLengths);
273
bsalomon@google.com91961302011-05-09 18:39:58 +0000274 // Creates a GL program ID, binds shader attributes to GL vertex attrs, and
275 // links the program
276 bool bindAttribsAndLinkProgram(GrStringBuilder texCoordAttrNames[GrDrawTarget::kMaxTexCoords],
277 CachedData* programData) const;
278
279 // Gets locations for all uniforms set to kUseUniform and initializes cache
280 // to invalid values.
281 void getUniformLocationsAndInitCache(CachedData* programData) const;
282
junov@google.comf93e7172011-03-31 21:26:24 +0000283 friend class GrGpuGLShaders;
284};
285
286#endif