2 * Copyright 2011 Google Inc.
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
8 #include "GrGLProgram.h"
10 #include "GrAllocator.h"
11 #include "GrProcessor.h"
12 #include "GrCoordTransform.h"
13 #include "GrGLGeometryProcessor.h"
14 #include "GrGLProcessor.h"
16 #include "GrGLPathRendering.h"
17 #include "GrGLShaderVar.h"
19 #include "GrOptDrawState.h"
20 #include "SkXfermode.h"
22 #define GL_CALL(X) GR_GL_CALL(fGpu->glInterface(), X)
23 #define GL_CALL_RET(R, X) GR_GL_CALL_RET(fGpu->glInterface(), R, X)
26 * Retrieves the final matrix that a transform needs to apply to its source coords.
28 static SkMatrix get_transform_matrix(const GrFragmentStage& processorStage,
29 bool useExplicitLocalCoords,
31 const GrCoordTransform& coordTransform =
32 processorStage.getProcessor()->coordTransform(transformIdx);
35 if (kLocal_GrCoordSet == coordTransform.sourceCoords()) {
36 // If we have explicit local coords then we shouldn't need a coord change.
38 useExplicitLocalCoords ? SkMatrix::I() : processorStage.getCoordChangeMatrix();
39 combined.setConcat(coordTransform.getMatrix(), ccm);
41 combined = coordTransform.getMatrix();
43 if (coordTransform.reverseY()) {
44 // combined.postScale(1,-1);
45 // combined.postTranslate(0,1);
46 combined.set(SkMatrix::kMSkewY,
47 combined[SkMatrix::kMPersp0] - combined[SkMatrix::kMSkewY]);
48 combined.set(SkMatrix::kMScaleY,
49 combined[SkMatrix::kMPersp1] - combined[SkMatrix::kMScaleY]);
50 combined.set(SkMatrix::kMTransY,
51 combined[SkMatrix::kMPersp2] - combined[SkMatrix::kMTransY]);
56 ///////////////////////////////////////////////////////////////////////////////////////////////////
58 GrGLProgram::GrGLProgram(GrGpuGL* gpu,
59 const GrProgramDesc& desc,
60 const BuiltinUniformHandles& builtinUniforms,
62 const UniformInfoArray& uniforms,
63 GrGLInstalledGeoProc* geometryProcessor,
64 GrGLInstalledFragProcs* fragmentProcessors)
65 : fColor(GrColor_ILLEGAL)
68 , fBuiltinUniformHandles(builtinUniforms)
69 , fProgramID(programID)
70 , fGeometryProcessor(geometryProcessor)
71 , fFragmentProcessors(SkRef(fragmentProcessors))
74 , fProgramDataManager(gpu, uniforms) {
75 this->initSamplerUniforms();
78 GrGLProgram::~GrGLProgram() {
80 GL_CALL(DeleteProgram(fProgramID));
84 void GrGLProgram::abandon() {
88 void GrGLProgram::initSamplerUniforms() {
89 GL_CALL(UseProgram(fProgramID));
90 GrGLint texUnitIdx = 0;
91 if (fBuiltinUniformHandles.fDstCopySamplerUni.isValid()) {
92 fProgramDataManager.setSampler(fBuiltinUniformHandles.fDstCopySamplerUni, texUnitIdx);
93 fDstCopyTexUnit = texUnitIdx++;
95 if (fGeometryProcessor.get()) {
96 this->initSamplers(fGeometryProcessor.get(), &texUnitIdx);
98 int numProcs = fFragmentProcessors->fProcs.count();
99 for (int i = 0; i < numProcs; i++) {
100 this->initSamplers(fFragmentProcessors->fProcs[i], &texUnitIdx);
104 void GrGLProgram::initSamplers(GrGLInstalledProc* ip, int* texUnitIdx) {
105 SkTArray<GrGLInstalledProc::Sampler, true>& samplers = ip->fSamplers;
106 int numSamplers = samplers.count();
107 for (int s = 0; s < numSamplers; ++s) {
108 SkASSERT(samplers[s].fUniform.isValid());
109 fProgramDataManager.setSampler(samplers[s].fUniform, *texUnitIdx);
110 samplers[s].fTextureUnit = (*texUnitIdx)++;
114 void GrGLProgram::bindTextures(const GrGLInstalledProc* ip, const GrProcessor& processor) {
115 const SkTArray<GrGLInstalledProc::Sampler, true>& samplers = ip->fSamplers;
116 int numSamplers = samplers.count();
117 SkASSERT(numSamplers == processor.numTextures());
118 for (int s = 0; s < numSamplers; ++s) {
119 SkASSERT(samplers[s].fTextureUnit >= 0);
120 const GrTextureAccess& textureAccess = processor.textureAccess(s);
121 fGpu->bindTexture(samplers[s].fTextureUnit,
122 textureAccess.getParams(),
123 static_cast<GrGLTexture*>(textureAccess.getTexture()));
128 ///////////////////////////////////////////////////////////////////////////////
130 void GrGLProgram::setData(const GrOptDrawState& optState,
131 GrGpu::DrawType drawType,
132 const GrDeviceCoordTexture* dstCopy) {
133 GrColor color = optState.getColor();
134 uint8_t coverage = optState.getCoverage();
136 this->setColor(optState, color);
137 this->setCoverage(optState, coverage);
138 this->setMatrixAndRenderTargetHeight(drawType, optState);
141 if (fBuiltinUniformHandles.fDstCopyTopLeftUni.isValid()) {
142 fProgramDataManager.set2f(fBuiltinUniformHandles.fDstCopyTopLeftUni,
143 static_cast<GrGLfloat>(dstCopy->offset().fX),
144 static_cast<GrGLfloat>(dstCopy->offset().fY));
145 fProgramDataManager.set2f(fBuiltinUniformHandles.fDstCopyScaleUni,
146 1.f / dstCopy->texture()->width(),
147 1.f / dstCopy->texture()->height());
148 GrGLTexture* texture = static_cast<GrGLTexture*>(dstCopy->texture());
149 static GrTextureParams kParams; // the default is clamp, nearest filtering.
150 fGpu->bindTexture(fDstCopyTexUnit, kParams, texture);
152 SkASSERT(!fBuiltinUniformHandles.fDstCopyScaleUni.isValid());
153 SkASSERT(!fBuiltinUniformHandles.fDstCopySamplerUni.isValid());
156 SkASSERT(!fBuiltinUniformHandles.fDstCopyTopLeftUni.isValid());
157 SkASSERT(!fBuiltinUniformHandles.fDstCopyScaleUni.isValid());
158 SkASSERT(!fBuiltinUniformHandles.fDstCopySamplerUni.isValid());
161 // we set the textures, and uniforms for installed processors in a generic way, but subclasses
162 // of GLProgram determine how to set coord transforms
163 if (fGeometryProcessor.get()) {
164 SkASSERT(optState.hasGeometryProcessor());
165 const GrGeometryProcessor& gp = *optState.getGeometryProcessor();
166 fGeometryProcessor->fGLProc->setData(fProgramDataManager, gp);
167 this->bindTextures(fGeometryProcessor, gp);
169 this->setFragmentData(optState);
171 // Some of GrGLProgram subclasses need to update state here
172 this->didSetData(drawType);
175 void GrGLProgram::setFragmentData(const GrOptDrawState& optState) {
176 int numProcessors = fFragmentProcessors->fProcs.count();
177 for (int e = 0; e < numProcessors; ++e) {
178 const GrFragmentStage& stage = optState.getFragmentStage(e);
179 const GrProcessor& processor = *stage.getProcessor();
180 fFragmentProcessors->fProcs[e]->fGLProc->setData(fProgramDataManager, processor);
181 this->setTransformData(stage, fFragmentProcessors->fProcs[e]);
182 this->bindTextures(fFragmentProcessors->fProcs[e], processor);
185 void GrGLProgram::setTransformData(const GrFragmentStage& processor, GrGLInstalledFragProc* ip) {
186 SkTArray<GrGLInstalledFragProc::Transform, true>& transforms = ip->fTransforms;
187 int numTransforms = transforms.count();
188 SkASSERT(numTransforms == processor.getProcessor()->numTransforms());
189 for (int t = 0; t < numTransforms; ++t) {
190 SkASSERT(transforms[t].fHandle.isValid());
191 const SkMatrix& matrix = get_transform_matrix(processor, ip->fLocalCoordAttrib, t);
192 if (!transforms[t].fCurrentValue.cheapEqualTo(matrix)) {
193 fProgramDataManager.setSkMatrix(transforms[t].fHandle.convertToUniformHandle(), matrix);
194 transforms[t].fCurrentValue = matrix;
199 void GrGLProgram::didSetData(GrGpu::DrawType drawType) {
200 SkASSERT(!GrGpu::IsPathRenderingDrawType(drawType));
203 void GrGLProgram::setColor(const GrOptDrawState& optState, GrColor color) {
204 const GrProgramDesc::KeyHeader& header = fDesc.header();
205 switch (header.fColorInput) {
206 case GrProgramDesc::kAttribute_ColorInput:
207 // Attribute case is handled in GrGpuGL::setupGeometry
209 case GrProgramDesc::kUniform_ColorInput:
210 if (fColor != color && fBuiltinUniformHandles.fColorUni.isValid()) {
211 // OpenGL ES doesn't support unsigned byte varieties of glUniform
213 GrColorToRGBAFloat(color, c);
214 fProgramDataManager.set4fv(fBuiltinUniformHandles.fColorUni, 1, c);
218 case GrProgramDesc::kAllOnes_ColorInput:
219 // Handled by shader creation
222 SkFAIL("Unexpected color type.");
226 void GrGLProgram::setCoverage(const GrOptDrawState& optState, uint8_t coverage) {
227 const GrProgramDesc::KeyHeader& header = fDesc.header();
228 switch (header.fCoverageInput) {
229 case GrProgramDesc::kAttribute_ColorInput:
230 // Attribute case is handled in GrGpuGL::setupGeometry
232 case GrProgramDesc::kUniform_ColorInput:
233 if (fCoverage != coverage) {
234 // OpenGL ES doesn't support unsigned byte varieties of glUniform
235 GrGLfloat c = GrNormalizeByteToFloat(coverage);
236 fProgramDataManager.set1f(fBuiltinUniformHandles.fCoverageUni, c);
237 fCoverage = coverage;
240 case GrProgramDesc::kAllOnes_ColorInput:
241 // Handled by shader creation
244 SkFAIL("Unexpected coverage type.");
248 void GrGLProgram::setMatrixAndRenderTargetHeight(GrGpu::DrawType drawType,
249 const GrOptDrawState& optState) {
250 // Load the RT height uniform if it is needed to y-flip gl_FragCoord.
251 if (fBuiltinUniformHandles.fRTHeightUni.isValid() &&
252 fMatrixState.fRenderTargetSize.fHeight != optState.getRenderTarget()->height()) {
253 fProgramDataManager.set1f(fBuiltinUniformHandles.fRTHeightUni,
254 SkIntToScalar(optState.getRenderTarget()->height()));
257 // call subclasses to set the actual view matrix
258 this->onSetMatrixAndRenderTargetHeight(drawType, optState);
261 void GrGLProgram::onSetMatrixAndRenderTargetHeight(GrGpu::DrawType drawType,
262 const GrOptDrawState& optState) {
263 const GrRenderTarget* rt = optState.getRenderTarget();
265 size.set(rt->width(), rt->height());
266 if (fMatrixState.fRenderTargetOrigin != rt->origin() ||
267 fMatrixState.fRenderTargetSize != size ||
268 !fMatrixState.fViewMatrix.cheapEqualTo(optState.getViewMatrix())) {
269 SkASSERT(fBuiltinUniformHandles.fViewMatrixUni.isValid());
271 fMatrixState.fViewMatrix = optState.getViewMatrix();
272 fMatrixState.fRenderTargetSize = size;
273 fMatrixState.fRenderTargetOrigin = rt->origin();
275 GrGLfloat viewMatrix[3 * 3];
276 fMatrixState.getGLMatrix<3>(viewMatrix);
277 fProgramDataManager.setMatrix3f(fBuiltinUniformHandles.fViewMatrixUni, viewMatrix);
279 GrGLfloat rtAdjustmentVec[4];
280 fMatrixState.getRTAdjustmentVec(rtAdjustmentVec);
281 fProgramDataManager.set4fv(fBuiltinUniformHandles.fRTAdjustmentUni, 1, rtAdjustmentVec);
285 /////////////////////////////////////////////////////////////////////////////////////////
287 GrGLNvprProgramBase::GrGLNvprProgramBase(GrGpuGL* gpu,
288 const GrProgramDesc& desc,
289 const BuiltinUniformHandles& builtinUniforms,
291 const UniformInfoArray& uniforms,
292 GrGLInstalledFragProcs* fragmentProcessors)
293 : INHERITED(gpu, desc, builtinUniforms, programID, uniforms, NULL, fragmentProcessors) {
296 void GrGLNvprProgramBase::onSetMatrixAndRenderTargetHeight(GrGpu::DrawType drawType,
297 const GrOptDrawState& optState) {
298 SkASSERT(GrGpu::IsPathRenderingDrawType(drawType));
299 const GrRenderTarget* rt = optState.getRenderTarget();
301 size.set(rt->width(), rt->height());
302 fGpu->glPathRendering()->setProjectionMatrix(optState.getViewMatrix(), size, rt->origin());
305 /////////////////////////////////////////////////////////////////////////////////////////
307 GrGLNvprProgram::GrGLNvprProgram(GrGpuGL* gpu,
308 const GrProgramDesc& desc,
309 const BuiltinUniformHandles& builtinUniforms,
311 const UniformInfoArray& uniforms,
312 GrGLInstalledFragProcs* fragmentProcessors,
313 const SeparableVaryingInfoArray& separableVaryings)
314 : INHERITED(gpu, desc, builtinUniforms, programID, uniforms, fragmentProcessors) {
315 int count = separableVaryings.count();
316 fVaryings.push_back_n(count);
317 for (int i = 0; i < count; i++) {
318 Varying& varying = fVaryings[i];
319 const SeparableVaryingInfo& builderVarying = separableVaryings[i];
320 SkASSERT(GrGLShaderVar::kNonArray == builderVarying.fVariable.getArrayCount());
322 varying.fType = builderVarying.fVariable.getType();
324 varying.fLocation = builderVarying.fLocation;
328 void GrGLNvprProgram::didSetData(GrGpu::DrawType drawType) {
329 SkASSERT(GrGpu::IsPathRenderingDrawType(drawType));
332 void GrGLNvprProgram::setTransformData(const GrFragmentStage& proc, GrGLInstalledFragProc* ip) {
333 SkTArray<GrGLInstalledFragProc::Transform, true>& transforms = ip->fTransforms;
334 int numTransforms = transforms.count();
335 SkASSERT(numTransforms == proc.getProcessor()->numTransforms());
336 for (int t = 0; t < numTransforms; ++t) {
337 SkASSERT(transforms[t].fHandle.isValid());
338 const SkMatrix& transform = get_transform_matrix(proc, false, t);
339 if (transforms[t].fCurrentValue.cheapEqualTo(transform)) {
342 transforms[t].fCurrentValue = transform;
343 const Varying& fragmentInput = fVaryings[transforms[t].fHandle.handle()];
344 SkASSERT(transforms[t].fType == kVec2f_GrSLType || transforms[t].fType == kVec3f_GrSLType);
345 unsigned components = transforms[t].fType == kVec2f_GrSLType ? 2 : 3;
346 fGpu->glPathRendering()->setProgramPathFragmentInputTransform(fProgramID,
347 fragmentInput.fLocation,
354 //////////////////////////////////////////////////////////////////////////////////////
356 GrGLLegacyNvprProgram::GrGLLegacyNvprProgram(GrGpuGL* gpu,
357 const GrProgramDesc& desc,
358 const BuiltinUniformHandles& builtinUniforms,
360 const UniformInfoArray& uniforms,
361 GrGLInstalledFragProcs* fps,
363 : INHERITED(gpu, desc, builtinUniforms, programID, uniforms, fps)
364 , fTexCoordSetCnt(texCoordSetCnt) {
367 void GrGLLegacyNvprProgram::didSetData(GrGpu::DrawType drawType) {
368 SkASSERT(GrGpu::IsPathRenderingDrawType(drawType));
369 fGpu->glPathRendering()->flushPathTexGenSettings(fTexCoordSetCnt);
373 GrGLLegacyNvprProgram::setTransformData(const GrFragmentStage& proc, GrGLInstalledFragProc* ip) {
374 // We've hidden the texcoord index in the first entry of the transforms array for each effect
375 int texCoordIndex = ip->fTransforms[0].fHandle.handle();
376 int numTransforms = proc.getProcessor()->numTransforms();
377 for (int t = 0; t < numTransforms; ++t) {
378 const SkMatrix& transform = get_transform_matrix(proc, false, t);
379 GrGLPathRendering::PathTexGenComponents components =
380 GrGLPathRendering::kST_PathTexGenComponents;
381 if (proc.isPerspectiveCoordTransform(t, false)) {
382 components = GrGLPathRendering::kSTR_PathTexGenComponents;
384 fGpu->glPathRendering()->enablePathTexGen(texCoordIndex++, components, transform);