Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / third_party / skia / src / gpu / gl / GrGLProgramDesc.cpp
1 /*
2  * Copyright 2013 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 #include "GrGLProgramDesc.h"
8
9 #include "GrGLProcessor.h"
10 #include "GrBackendProcessorFactory.h"
11 #include "GrProcessor.h"
12 #include "GrGpuGL.h"
13 #include "GrOptDrawState.h"
14 #include "SkChecksum.h"
15 #include "gl/builders/GrGLFragmentShaderBuilder.h"
16
17 /**
18  * The key for an individual coord transform is made up of a matrix type and a bit that
19  * indicates the source of the input coords.
20  */
21 enum {
22     kMatrixTypeKeyBits   = 1,
23     kMatrixTypeKeyMask   = (1 << kMatrixTypeKeyBits) - 1,
24     kPositionCoords_Flag = (1 << kMatrixTypeKeyBits),
25     kTransformKeyBits    = kMatrixTypeKeyBits + 1,
26 };
27
28 /**
29  * We specialize the vertex code for each of these matrix types.
30  */
31 enum MatrixType {
32     kNoPersp_MatrixType  = 0,
33     kGeneral_MatrixType  = 1,
34 };
35
36 /**
37  * Do we need to either map r,g,b->a or a->r. configComponentMask indicates which channels are
38  * present in the texture's config. swizzleComponentMask indicates the channels present in the
39  * shader swizzle.
40  */
41 static bool swizzle_requires_alpha_remapping(const GrGLCaps& caps,
42                                              uint32_t configComponentMask,
43                                              uint32_t swizzleComponentMask) {
44     if (caps.textureSwizzleSupport()) {
45         // Any remapping is handled using texture swizzling not shader modifications.
46         return false;
47     }
48     // check if the texture is alpha-only
49     if (kA_GrColorComponentFlag == configComponentMask) {
50         if (caps.textureRedSupport() && (kA_GrColorComponentFlag & swizzleComponentMask)) {
51             // we must map the swizzle 'a's to 'r'.
52             return true;
53         }
54         if (kRGB_GrColorComponentFlags & swizzleComponentMask) {
55             // The 'r', 'g', and/or 'b's must be mapped to 'a' according to our semantics that
56             // alpha-only textures smear alpha across all four channels when read.
57             return true;
58         }
59     }
60     return false;
61 }
62
63 static uint32_t gen_attrib_key(const GrGeometryProcessor& proc) {
64     uint32_t key = 0;
65
66     const GrGeometryProcessor::VertexAttribArray& vars = proc.getVertexAttribs();
67     int numAttributes = vars.count();
68     SkASSERT(numAttributes <= 2);
69     for (int a = 0; a < numAttributes; ++a) {
70         uint32_t value = 1 << a;
71         key |= value;
72     }
73     return key;
74 }
75
76 static uint32_t gen_transform_key(const GrFragmentStage& effectStage,
77                                   bool useExplicitLocalCoords) {
78     uint32_t totalKey = 0;
79     int numTransforms = effectStage.getProcessor()->numTransforms();
80     for (int t = 0; t < numTransforms; ++t) {
81         uint32_t key = 0;
82         if (effectStage.isPerspectiveCoordTransform(t, useExplicitLocalCoords)) {
83             key |= kGeneral_MatrixType;
84         } else {
85             key |= kNoPersp_MatrixType;
86         }
87
88         const GrCoordTransform& coordTransform = effectStage.getProcessor()->coordTransform(t);
89         if (kLocal_GrCoordSet != coordTransform.sourceCoords() && useExplicitLocalCoords) {
90             key |= kPositionCoords_Flag;
91         }
92         key <<= kTransformKeyBits * t;
93         SkASSERT(0 == (totalKey & key)); // keys for each transform ought not to overlap
94         totalKey |= key;
95     }
96     return totalKey;
97 }
98
99 static uint32_t gen_texture_key(const GrProcessor& proc, const GrGLCaps& caps) {
100     uint32_t key = 0;
101     int numTextures = proc.numTextures();
102     for (int t = 0; t < numTextures; ++t) {
103         const GrTextureAccess& access = proc.textureAccess(t);
104         uint32_t configComponentMask = GrPixelConfigComponentMask(access.getTexture()->config());
105         if (swizzle_requires_alpha_remapping(caps, configComponentMask, access.swizzleMask())) {
106             key |= 1 << t;
107         }
108     }
109     return key;
110 }
111
112 /**
113  * A function which emits a meta key into the key builder.  This is required because shader code may
114  * be dependent on properties of the effect that the effect itself doesn't use
115  * in its key (e.g. the pixel format of textures used). So we create a meta-key for
116  * every effect using this function. It is also responsible for inserting the effect's class ID
117  * which must be different for every GrProcessor subclass. It can fail if an effect uses too many
118  * textures, transforms, etc, for the space allotted in the meta-key.  NOTE, both FPs and GPs share
119  * this function because it is hairy, though FPs do not have attribs, and GPs do not have transforms
120  */
121 static bool get_meta_key(const GrProcessor& proc,
122                          const GrGLCaps& caps,
123                          uint32_t transformKey,
124                          uint32_t attribKey,
125                          GrProcessorKeyBuilder* b,
126                          uint16_t* processorKeySize) {
127     const GrBackendProcessorFactory& factory = proc.getFactory();
128     factory.getGLProcessorKey(proc, caps, b);
129     size_t size = b->size();
130     if (size > SK_MaxU16) {
131         *processorKeySize = 0; // suppresses a warning.
132         return false;
133     }
134     *processorKeySize = SkToU16(size);
135     uint32_t textureKey = gen_texture_key(proc, caps);
136     uint32_t classID = proc.getFactory().classID();
137
138     // Currently we allow 16 bits for each of the above portions of the meta-key. Fail if they
139     // don't fit.
140     static const uint32_t kMetaKeyInvalidMask = ~((uint32_t) SK_MaxU16);
141     if ((textureKey | transformKey | classID) & kMetaKeyInvalidMask) {
142         return false;
143     }
144
145     uint32_t* key = b->add32n(2);
146     key[0] = (textureKey << 16 | transformKey);
147     key[1] = (classID << 16);
148     return true;
149 }
150
151 struct GeometryProcessorKeyBuilder {
152     typedef GrGeometryProcessor StagedProcessor;
153     static bool GetProcessorKey(const GrGeometryProcessor& gp,
154                                 const GrGLCaps& caps,
155                                 bool,
156                                 GrProcessorKeyBuilder* b,
157                                 uint16_t* keySize) {
158         /* 0 because no transforms on a GP */
159         return get_meta_key(gp, caps, 0, gen_attrib_key(gp), b, keySize);
160     }
161 };
162
163 struct FragmentProcessorKeyBuilder {
164     typedef GrFragmentStage StagedProcessor;
165     static bool GetProcessorKey(const GrFragmentStage& fps,
166                                 const GrGLCaps& caps,
167                                 bool useLocalCoords,
168                                 GrProcessorKeyBuilder* b,
169                                 uint16_t* keySize) {
170         /* 0 because no attribs on a fP */
171         return get_meta_key(*fps.getProcessor(), caps, gen_transform_key(fps, useLocalCoords), 0,
172                             b, keySize);
173     }
174 };
175
176
177 template <class ProcessorKeyBuilder>
178 bool
179 GrGLProgramDescBuilder::BuildStagedProcessorKey(const typename ProcessorKeyBuilder::StagedProcessor& stage,
180                                          const GrGLCaps& caps,
181                                          bool requiresLocalCoordAttrib,
182                                          GrProgramDesc* desc,
183                                          int* offsetAndSizeIndex) {
184     GrProcessorKeyBuilder b(&desc->fKey);
185     uint16_t processorKeySize;
186     uint32_t processorOffset = desc->fKey.count();
187     if (processorOffset > SK_MaxU16 ||
188             !ProcessorKeyBuilder::GetProcessorKey(stage, caps, requiresLocalCoordAttrib, &b,
189                                                   &processorKeySize)){
190         desc->fKey.reset();
191         return false;
192     }
193
194     uint16_t* offsetAndSize =
195             reinterpret_cast<uint16_t*>(desc->fKey.begin() + kProcessorKeyOffsetsAndLengthOffset +
196                                         *offsetAndSizeIndex * 2 * sizeof(uint16_t));
197     offsetAndSize[0] = SkToU16(processorOffset);
198     offsetAndSize[1] = processorKeySize;
199     ++(*offsetAndSizeIndex);
200     return true;
201 }
202
203 bool GrGLProgramDescBuilder::Build(const GrOptDrawState& optState,
204                             const GrProgramDesc::DescInfo& descInfo,
205                             GrGpu::DrawType drawType,
206                             GrGpuGL* gpu,
207                             const GrDeviceCoordTexture* dstCopy,
208                             GrProgramDesc* desc) {
209     bool inputColorIsUsed = descInfo.fInputColorIsUsed;
210     bool inputCoverageIsUsed = descInfo.fInputCoverageIsUsed;
211
212     // The descriptor is used as a cache key. Thus when a field of the
213     // descriptor will not affect program generation (because of the attribute
214     // bindings in use or other descriptor field settings) it should be set
215     // to a canonical value to avoid duplicate programs with different keys.
216
217     bool requiresLocalCoordAttrib = descInfo.fRequiresLocalCoordAttrib;
218
219     int numStages = optState.numTotalStages();
220
221     GR_STATIC_ASSERT(0 == kProcessorKeyOffsetsAndLengthOffset % sizeof(uint32_t));
222     // Make room for everything up to and including the array of offsets to effect keys.
223     desc->fKey.reset();
224     desc->fKey.push_back_n(kProcessorKeyOffsetsAndLengthOffset + 2 * sizeof(uint16_t) * numStages);
225
226     int offsetAndSizeIndex = 0;
227
228     // We can only have one effect which touches the vertex shader
229     if (optState.hasGeometryProcessor()) {
230         if (!BuildStagedProcessorKey<GeometryProcessorKeyBuilder>(*optState.getGeometryProcessor(),
231                                                                   gpu->glCaps(),
232                                                                   false,
233                                                                   desc,
234                                                                   &offsetAndSizeIndex)) {
235             return false;
236         }
237     }
238
239     for (int s = 0; s < optState.numFragmentStages(); ++s) {
240         if (!BuildStagedProcessorKey<FragmentProcessorKeyBuilder>(optState.getFragmentStage(s),
241                                                                   gpu->glCaps(),
242                                                                   requiresLocalCoordAttrib,
243                                                                   desc,
244                                                                   &offsetAndSizeIndex)) {
245             return false;
246         }
247     }
248
249     // --------DO NOT MOVE HEADER ABOVE THIS LINE--------------------------------------------------
250     // Because header is a pointer into the dynamic array, we can't push any new data into the key
251     // below here.
252     GLKeyHeader* header = desc->atOffset<GLKeyHeader, kHeaderOffset>();
253
254     // make sure any padding in the header is zeroed.
255     memset(header, 0, kHeaderSize);
256
257     header->fHasGeometryProcessor = optState.hasGeometryProcessor();
258
259     header->fEmitsPointSize = GrGpu::kDrawPoints_DrawType == drawType;
260
261     bool isPathRendering = GrGpu::IsPathRenderingDrawType(drawType);
262     if (gpu->caps()->pathRenderingSupport() && isPathRendering) {
263         header->fUseNvpr = true;
264         SkASSERT(!optState.hasGeometryProcessor());
265     } else {
266         header->fUseNvpr = false;
267     }
268
269     bool hasUniformColor = inputColorIsUsed &&
270                            (isPathRendering || !descInfo.hasColorVertexAttribute());
271
272     bool hasUniformCoverage = inputCoverageIsUsed &&
273                               (isPathRendering || !descInfo.hasCoverageVertexAttribute());
274
275     if (!inputColorIsUsed) {
276         header->fColorInput = GrProgramDesc::kAllOnes_ColorInput;
277     } else if (hasUniformColor) {
278         header->fColorInput = GrProgramDesc::kUniform_ColorInput;
279     } else {
280         header->fColorInput = GrProgramDesc::kAttribute_ColorInput;
281         SkASSERT(!header->fUseNvpr);
282     }
283
284     bool covIsSolidWhite = !descInfo.hasCoverageVertexAttribute() &&
285                            0xffffffff == optState.getCoverageColor();
286
287     if (covIsSolidWhite || !inputCoverageIsUsed) {
288         header->fCoverageInput = GrProgramDesc::kAllOnes_ColorInput;
289     } else if (hasUniformCoverage) {
290         header->fCoverageInput = GrProgramDesc::kUniform_ColorInput;
291     } else {
292         header->fCoverageInput = GrProgramDesc::kAttribute_ColorInput;
293         SkASSERT(!header->fUseNvpr);
294     }
295
296     if (descInfo.fReadsDst) {
297         SkASSERT(dstCopy || gpu->caps()->dstReadInShaderSupport());
298         const GrTexture* dstCopyTexture = NULL;
299         if (dstCopy) {
300             dstCopyTexture = dstCopy->texture();
301         }
302         header->fDstReadKey = GrGLFragmentShaderBuilder::KeyForDstRead(dstCopyTexture,
303                                                                        gpu->glCaps());
304         SkASSERT(0 != header->fDstReadKey);
305     } else {
306         header->fDstReadKey = 0;
307     }
308
309     if (descInfo.fReadsFragPosition) {
310         header->fFragPosKey =
311                 GrGLFragmentShaderBuilder::KeyForFragmentPosition(optState.getRenderTarget(),
312                                                                   gpu->glCaps());
313     } else {
314         header->fFragPosKey = 0;
315     }
316
317     // Record attribute indices
318     header->fPositionAttributeIndex = descInfo.positionAttributeIndex();
319     header->fLocalCoordAttributeIndex = descInfo.localCoordAttributeIndex();
320
321     // For constant color and coverage we need an attribute with an index beyond those already set
322     int availableAttributeIndex = optState.getVertexAttribCount();
323     if (descInfo.hasColorVertexAttribute()) {
324         header->fColorAttributeIndex = descInfo.colorVertexAttributeIndex();
325     } else if (GrProgramDesc::kAttribute_ColorInput == header->fColorInput) {
326         SkASSERT(availableAttributeIndex < GrDrawState::kMaxVertexAttribCnt);
327         header->fColorAttributeIndex = availableAttributeIndex;
328         availableAttributeIndex++;
329     } else {
330         header->fColorAttributeIndex = -1;
331     }
332
333     if (descInfo.hasCoverageVertexAttribute()) {
334         header->fCoverageAttributeIndex = descInfo.coverageVertexAttributeIndex();
335     } else if (GrProgramDesc::kAttribute_ColorInput == header->fCoverageInput) {
336         SkASSERT(availableAttributeIndex < GrDrawState::kMaxVertexAttribCnt);
337         header->fCoverageAttributeIndex = availableAttributeIndex;
338     } else {
339         header->fCoverageAttributeIndex = -1;
340     }
341
342     header->fPrimaryOutputType = descInfo.fPrimaryOutputType;
343     header->fSecondaryOutputType = descInfo.fSecondaryOutputType;
344
345     header->fColorEffectCnt = optState.numColorStages();
346     header->fCoverageEffectCnt = optState.numCoverageStages();
347     desc->finalize();
348     return true;
349 }