blob: 74078e30b388b6cec4fc0b6afa95f069451d263e [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
bsalomon@google.com91961302011-05-09 18:39:58 +000073 static int PositionAttributeIdx() { return 0; }
74 static int TexCoordAttributeIdx(int tcIdx) { return 1 + tcIdx; }
75 static int ColorAttributeIdx() { return 1 + GrDrawTarget::kMaxTexCoords; }
76 static int ViewMatrixAttributeIdx() {
77 return 2 + GrDrawTarget::kMaxTexCoords;
78 }
79 static int TextureMatrixAttributeIdx(int stage) {
80 return 5 + GrDrawTarget::kMaxTexCoords + 3 * stage;
81 }
82
junov@google.comf93e7172011-03-31 21:26:24 +000083private:
84
85 //Parameters that affect code generation
86 struct ProgramDesc {
bsalomon@google.com4be283f2011-04-19 21:15:09 +000087 ProgramDesc() {
88 // since we use this as part of a key we can't have any unitialized
89 // padding
90 memset(this, 0, sizeof(ProgramDesc));
91 }
92
93 // stripped of bits that don't affect prog generation
junov@google.comf93e7172011-03-31 21:26:24 +000094 GrVertexLayout fVertexLayout;
95
96 enum {
bsalomon@google.com4be283f2011-04-19 21:15:09 +000097 kNone_ColorType = 0,
98 kAttribute_ColorType = 1,
99 kUniform_ColorType = 2,
100 } fColorType;
101
102 bool fEmitsPointSize;
senorblanco@chromium.org92e0f222011-05-12 15:49:15 +0000103 bool fUsesEdgeAA;
junov@google.comf93e7172011-03-31 21:26:24 +0000104
Scroggo97c88c22011-05-11 14:05:25 +0000105 SkXfermode::Mode fColorFilterXfermode;
106
junov@google.comf93e7172011-03-31 21:26:24 +0000107 struct StageDesc {
108 enum OptFlagBits {
junov@google.com6acc9b32011-05-16 18:32:07 +0000109 kNoPerspective_OptFlagBit = 1 << 0,
110 kIdentityMatrix_OptFlagBit = 1 << 1,
111 kCustomTextureDomain_OptFlagBit = 1 << 2
junov@google.comf93e7172011-03-31 21:26:24 +0000112 };
113
bsalomon@google.com6aef1fb2011-05-05 12:33:22 +0000114 unsigned fOptFlags;
115 bool fEnabled;
junov@google.comf93e7172011-03-31 21:26:24 +0000116
117 enum Modulation {
118 kColor_Modulation,
119 kAlpha_Modulation
bsalomon@google.com6aef1fb2011-05-05 12:33:22 +0000120 } fModulation;
121
122 enum FetchMode {
123 kSingle_FetchMode,
124 k2x2_FetchMode
125 } fFetchMode;
junov@google.comf93e7172011-03-31 21:26:24 +0000126
127 enum CoordMapping {
128 kIdentity_CoordMapping,
129 kRadialGradient_CoordMapping,
130 kSweepGradient_CoordMapping,
131 kRadial2Gradient_CoordMapping
bsalomon@google.com6aef1fb2011-05-05 12:33:22 +0000132 } fCoordMapping;
junov@google.comf93e7172011-03-31 21:26:24 +0000133 } fStages[GrDrawTarget::kNumStages];
134 } fProgramDesc;
135
bsalomon@google.com4be283f2011-04-19 21:15:09 +0000136 const ProgramDesc& getDesc() { return fProgramDesc; }
137
junov@google.comf93e7172011-03-31 21:26:24 +0000138public:
bsalomon@google.com91961302011-05-09 18:39:58 +0000139 enum {
140 kUnusedUniform = -1,
141 kSetAsAttribute = 1000,
142 };
143
junov@google.comf93e7172011-03-31 21:26:24 +0000144 struct StageUniLocations {
145 GrGLint fTextureMatrixUni;
bsalomon@google.com6aef1fb2011-05-05 12:33:22 +0000146 GrGLint fNormalizedTexelSizeUni;
junov@google.comf93e7172011-03-31 21:26:24 +0000147 GrGLint fSamplerUni;
148 GrGLint fRadial2Uni;
junov@google.com6acc9b32011-05-16 18:32:07 +0000149 GrGLint fTexDomUni;
bsalomon@google.com91961302011-05-09 18:39:58 +0000150 void reset() {
151 fTextureMatrixUni = kUnusedUniform;
152 fNormalizedTexelSizeUni = kUnusedUniform;
153 fSamplerUni = kUnusedUniform;
154 fRadial2Uni = kUnusedUniform;
junov@google.com6acc9b32011-05-16 18:32:07 +0000155 fTexDomUni = kUnusedUniform;
bsalomon@google.com91961302011-05-09 18:39:58 +0000156 }
junov@google.comf93e7172011-03-31 21:26:24 +0000157 };
158
159 struct UniLocations {
160 GrGLint fViewMatrixUni;
bsalomon@google.com4be283f2011-04-19 21:15:09 +0000161 GrGLint fColorUni;
senorblanco@chromium.org92e0f222011-05-12 15:49:15 +0000162 GrGLint fEdgesUni;
Scroggo97c88c22011-05-11 14:05:25 +0000163 GrGLint fColorFilterUni;
junov@google.comf93e7172011-03-31 21:26:24 +0000164 StageUniLocations fStages[GrDrawTarget::kNumStages];
bsalomon@google.com91961302011-05-09 18:39:58 +0000165 void reset() {
166 fViewMatrixUni = kUnusedUniform;
167 fColorUni = kUnusedUniform;
senorblanco@chromium.org92e0f222011-05-12 15:49:15 +0000168 fEdgesUni = kUnusedUniform;
Scroggo97c88c22011-05-11 14:05:25 +0000169 fColorFilterUni = kUnusedUniform;
bsalomon@google.com91961302011-05-09 18:39:58 +0000170 for (int s = 0; s < GrDrawTarget::kNumStages; ++s) {
171 fStages[s].reset();
172 }
173 }
junov@google.comf93e7172011-03-31 21:26:24 +0000174 };
175
176 class CachedData : public ::GrNoncopyable {
177 public:
178 CachedData() {
179 GR_DEBUGCODE(fEffectUniCount = 0;)
180 fEffectUniLocationsExtended = NULL;
181 }
182
183 ~CachedData() {
184 GrFree(fEffectUniLocationsExtended);
185 }
186
187 void copyAndTakeOwnership(CachedData& other) {
bsalomon@google.com2d9ddf92011-05-11 16:52:59 +0000188 memcpy(this, &other, sizeof(*this));
junov@google.comf93e7172011-03-31 21:26:24 +0000189 other.fEffectUniLocationsExtended = NULL; // ownership transfer
190 GR_DEBUGCODE(other.fEffectUniCount = 0;)
191 }
192
193 void setEffectUniformCount(size_t effectUniforms) {
194 GR_DEBUGCODE(fEffectUniCount = effectUniforms;)
195 GrFree(fEffectUniLocationsExtended);
196 if (effectUniforms > kUniLocationPreAllocSize) {
197 fEffectUniLocationsExtended = (GrGLint*)GrMalloc(sizeof(GrGLint)*(effectUniforms-kUniLocationPreAllocSize));
198 } else {
199 fEffectUniLocationsExtended = NULL;
200 }
201 }
202
203 GrGLint& effectUniLocation(size_t index) {
204 GrAssert(index < fEffectUniCount);
205 return (index < kUniLocationPreAllocSize) ?
206 fEffectUniLocations[index] :
207 fEffectUniLocationsExtended[index - kUniLocationPreAllocSize];
208 }
209
210 public:
211
212 // IDs
213 GrGLuint fVShaderID;
214 GrGLuint fFShaderID;
215 GrGLuint fProgramID;
216 // shader uniform locations (-1 if shader doesn't use them)
217 UniLocations fUniLocations;
218
219 GrMatrix fViewMatrix;
220
221 // these reflect the current values of uniforms
222 // (GL uniform values travel with program)
bsalomon@google.com4be283f2011-04-19 21:15:09 +0000223 GrColor fColor;
Scroggo97c88c22011-05-11 14:05:25 +0000224 GrColor fColorFilterColor;
junov@google.comf93e7172011-03-31 21:26:24 +0000225 GrMatrix fTextureMatrices[GrDrawTarget::kNumStages];
bsalomon@google.com6aef1fb2011-05-05 12:33:22 +0000226 // width and height used for normalized texel size
227 int fTextureWidth[GrDrawTarget::kNumStages];
228 int fTextureHeight[GrDrawTarget::kNumStages];
junov@google.comf93e7172011-03-31 21:26:24 +0000229 GrScalar fRadial2CenterX1[GrDrawTarget::kNumStages];
230 GrScalar fRadial2Radius0[GrDrawTarget::kNumStages];
231 bool fRadial2PosRoot[GrDrawTarget::kNumStages];
232
233 private:
234 enum Constants {
235 kUniLocationPreAllocSize = 8
236 };
237
238 GrGLint fEffectUniLocations[kUniLocationPreAllocSize];
239 GrGLint* fEffectUniLocationsExtended;
240 GR_DEBUGCODE(size_t fEffectUniCount;)
241 }; // CachedData
242
243 GrGLEffect* fStageEffects[GrDrawTarget::kNumStages];
244
245private:
bsalomon@google.com91961302011-05-09 18:39:58 +0000246 enum {
247 kUseUniform = 2000
248 };
249
250 // should set all fields in locations var to kUseUniform if the
251 // corresponding uniform is required for the program.
junov@google.comf93e7172011-03-31 21:26:24 +0000252 void genStageCode(int stageNum,
253 const ProgramDesc::StageDesc& desc,
254 const char* fsInColor, // NULL means no incoming color
255 const char* fsOutColor,
256 const char* vsInCoord,
257 ShaderCodeSegments* segments,
258 StageUniLocations* locations) const;
259
bsalomon@google.com91961302011-05-09 18:39:58 +0000260 static bool CompileFSAndVS(const ShaderCodeSegments& segments,
261 CachedData* programData);
262
junov@google.comf93e7172011-03-31 21:26:24 +0000263 // Compiles a GL shader, returns shader ID or 0 if failed
264 // params have same meaning as glShaderSource
265 static GrGLuint CompileShader(GrGLenum type, int stringCnt,
266 const char** strings,
267 int* stringLengths);
268
bsalomon@google.com91961302011-05-09 18:39:58 +0000269 // Creates a GL program ID, binds shader attributes to GL vertex attrs, and
270 // links the program
271 bool bindAttribsAndLinkProgram(GrStringBuilder texCoordAttrNames[GrDrawTarget::kMaxTexCoords],
272 CachedData* programData) const;
273
274 // Gets locations for all uniforms set to kUseUniform and initializes cache
275 // to invalid values.
276 void getUniformLocationsAndInitCache(CachedData* programData) const;
277
junov@google.comf93e7172011-03-31 21:26:24 +0000278 friend class GrGpuGLShaders;
279};
280
281#endif