Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / third_party / skia / src / gpu / gl / GrGLProgram.cpp
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 #include "GrGLProgram.h"
9
10 #include "GrAllocator.h"
11 #include "GrProcessor.h"
12 #include "GrCoordTransform.h"
13 #include "GrGLGeometryProcessor.h"
14 #include "GrGLProcessor.h"
15 #include "GrGpuGL.h"
16 #include "GrGLPathRendering.h"
17 #include "GrGLShaderVar.h"
18 #include "GrGLSL.h"
19 #include "GrOptDrawState.h"
20 #include "SkXfermode.h"
21
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)
24
25 /**
26  * Retrieves the final matrix that a transform needs to apply to its source coords.
27  */
28 static SkMatrix get_transform_matrix(const GrFragmentStage& processorStage,
29                                      bool useExplicitLocalCoords,
30                                      int transformIdx) {
31     const GrCoordTransform& coordTransform =
32             processorStage.getProcessor()->coordTransform(transformIdx);
33     SkMatrix combined;
34
35     if (kLocal_GrCoordSet == coordTransform.sourceCoords()) {
36         // If we have explicit local coords then we shouldn't need a coord change.
37         const SkMatrix& ccm =
38                 useExplicitLocalCoords ? SkMatrix::I() : processorStage.getCoordChangeMatrix();
39         combined.setConcat(coordTransform.getMatrix(), ccm);
40     } else {
41         combined = coordTransform.getMatrix();
42     }
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]);
52     }
53     return combined;
54 }
55
56 ///////////////////////////////////////////////////////////////////////////////////////////////////
57
58 GrGLProgram::GrGLProgram(GrGpuGL* gpu,
59                          const GrProgramDesc& desc,
60                          const BuiltinUniformHandles& builtinUniforms,
61                          GrGLuint programID,
62                          const UniformInfoArray& uniforms,
63                          GrGLInstalledGeoProc* geometryProcessor,
64                          GrGLInstalledFragProcs* fragmentProcessors)
65     : fColor(GrColor_ILLEGAL)
66     , fCoverage(0)
67     , fDstCopyTexUnit(-1)
68     , fBuiltinUniformHandles(builtinUniforms)
69     , fProgramID(programID)
70     , fGeometryProcessor(geometryProcessor)
71     , fFragmentProcessors(SkRef(fragmentProcessors))
72     , fDesc(desc)
73     , fGpu(gpu)
74     , fProgramDataManager(gpu, uniforms) {
75     this->initSamplerUniforms();
76 }
77
78 GrGLProgram::~GrGLProgram() {
79     if (fProgramID) {
80         GL_CALL(DeleteProgram(fProgramID));
81     }
82 }
83
84 void GrGLProgram::abandon() {
85     fProgramID = 0;
86 }
87
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++;
94     }
95     if (fGeometryProcessor.get()) {
96         this->initSamplers(fGeometryProcessor.get(), &texUnitIdx);
97     }
98     int numProcs = fFragmentProcessors->fProcs.count();
99     for (int i = 0; i < numProcs; i++) {
100         this->initSamplers(fFragmentProcessors->fProcs[i], &texUnitIdx);
101     }
102 }
103
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)++;
111     }
112 }
113
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()));
124     }
125 }
126
127
128 ///////////////////////////////////////////////////////////////////////////////
129
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();
135
136     this->setColor(optState, color);
137     this->setCoverage(optState, coverage);
138     this->setMatrixAndRenderTargetHeight(drawType, optState);
139
140     if (dstCopy) {
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);
151         } else {
152             SkASSERT(!fBuiltinUniformHandles.fDstCopyScaleUni.isValid());
153             SkASSERT(!fBuiltinUniformHandles.fDstCopySamplerUni.isValid());
154         }
155     } else {
156         SkASSERT(!fBuiltinUniformHandles.fDstCopyTopLeftUni.isValid());
157         SkASSERT(!fBuiltinUniformHandles.fDstCopyScaleUni.isValid());
158         SkASSERT(!fBuiltinUniformHandles.fDstCopySamplerUni.isValid());
159     }
160
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);
168     }
169     this->setFragmentData(optState);
170
171     // Some of GrGLProgram subclasses need to update state here
172     this->didSetData(drawType);
173 }
174
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);
183     }
184 }
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;
195         }
196     }
197 }
198
199 void GrGLProgram::didSetData(GrGpu::DrawType drawType) {
200     SkASSERT(!GrGpu::IsPathRenderingDrawType(drawType));
201 }
202
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
208             break;
209         case GrProgramDesc::kUniform_ColorInput:
210             if (fColor != color && fBuiltinUniformHandles.fColorUni.isValid()) {
211                 // OpenGL ES doesn't support unsigned byte varieties of glUniform
212                 GrGLfloat c[4];
213                 GrColorToRGBAFloat(color, c);
214                 fProgramDataManager.set4fv(fBuiltinUniformHandles.fColorUni, 1, c);
215                 fColor = color;
216             }
217             break;
218         case GrProgramDesc::kAllOnes_ColorInput:
219             // Handled by shader creation
220             break;
221         default:
222             SkFAIL("Unexpected color type.");
223     }
224 }
225
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
231             break;
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;
238             }
239             break;
240         case GrProgramDesc::kAllOnes_ColorInput:
241             // Handled by shader creation
242             break;
243         default:
244             SkFAIL("Unexpected coverage type.");
245     }
246 }
247
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()));
255     }
256
257     // call subclasses to set the actual view matrix
258     this->onSetMatrixAndRenderTargetHeight(drawType, optState);
259 }
260
261 void GrGLProgram::onSetMatrixAndRenderTargetHeight(GrGpu::DrawType drawType,
262                                                    const GrOptDrawState& optState) {
263     const GrRenderTarget* rt = optState.getRenderTarget();
264     SkISize size;
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());
270
271         fMatrixState.fViewMatrix = optState.getViewMatrix();
272         fMatrixState.fRenderTargetSize = size;
273         fMatrixState.fRenderTargetOrigin = rt->origin();
274
275         GrGLfloat viewMatrix[3 * 3];
276         fMatrixState.getGLMatrix<3>(viewMatrix);
277         fProgramDataManager.setMatrix3f(fBuiltinUniformHandles.fViewMatrixUni, viewMatrix);
278
279         GrGLfloat rtAdjustmentVec[4];
280         fMatrixState.getRTAdjustmentVec(rtAdjustmentVec);
281         fProgramDataManager.set4fv(fBuiltinUniformHandles.fRTAdjustmentUni, 1, rtAdjustmentVec);
282     }
283 }
284
285 /////////////////////////////////////////////////////////////////////////////////////////
286
287 GrGLNvprProgramBase::GrGLNvprProgramBase(GrGpuGL* gpu,
288                                          const GrProgramDesc& desc,
289                                          const BuiltinUniformHandles& builtinUniforms,
290                                          GrGLuint programID,
291                                          const UniformInfoArray& uniforms,
292                                          GrGLInstalledFragProcs* fragmentProcessors)
293     : INHERITED(gpu, desc, builtinUniforms, programID, uniforms, NULL, fragmentProcessors) {
294 }
295
296 void GrGLNvprProgramBase::onSetMatrixAndRenderTargetHeight(GrGpu::DrawType drawType,
297                                                            const GrOptDrawState& optState) {
298     SkASSERT(GrGpu::IsPathRenderingDrawType(drawType));
299     const GrRenderTarget* rt = optState.getRenderTarget();
300     SkISize size;
301     size.set(rt->width(), rt->height());
302     fGpu->glPathRendering()->setProjectionMatrix(optState.getViewMatrix(), size, rt->origin());
303 }
304
305 /////////////////////////////////////////////////////////////////////////////////////////
306
307 GrGLNvprProgram::GrGLNvprProgram(GrGpuGL* gpu,
308                                  const GrProgramDesc& desc,
309                                  const BuiltinUniformHandles& builtinUniforms,
310                                  GrGLuint programID,
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());
321         SkDEBUGCODE(
322             varying.fType = builderVarying.fVariable.getType();
323         );
324         varying.fLocation = builderVarying.fLocation;
325     }
326 }
327
328 void GrGLNvprProgram::didSetData(GrGpu::DrawType drawType) {
329     SkASSERT(GrGpu::IsPathRenderingDrawType(drawType));
330 }
331
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)) {
340             continue;
341         }
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,
348                                                                       GR_GL_OBJECT_LINEAR,
349                                                                       components,
350                                                                       transform);
351     }
352 }
353
354 //////////////////////////////////////////////////////////////////////////////////////
355
356 GrGLLegacyNvprProgram::GrGLLegacyNvprProgram(GrGpuGL* gpu,
357                                              const GrProgramDesc& desc,
358                                              const BuiltinUniformHandles& builtinUniforms,
359                                              GrGLuint programID,
360                                              const UniformInfoArray& uniforms,
361                                              GrGLInstalledFragProcs* fps,
362                                              int texCoordSetCnt)
363     : INHERITED(gpu, desc, builtinUniforms, programID, uniforms, fps)
364     , fTexCoordSetCnt(texCoordSetCnt) {
365 }
366
367 void GrGLLegacyNvprProgram::didSetData(GrGpu::DrawType drawType) {
368     SkASSERT(GrGpu::IsPathRenderingDrawType(drawType));
369     fGpu->glPathRendering()->flushPathTexGenSettings(fTexCoordSetCnt);
370 }
371
372 void
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;
383         }
384         fGpu->glPathRendering()->enablePathTexGen(texCoordIndex++, components, transform);
385     }
386 }