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 "GrProcessor.h"
11 #include "GrGLGpu.h"
12 #include "GrPipeline.h"
13 #include "SkChecksum.h"
14 #include "gl/builders/GrGLFragmentShaderBuilder.h"
15
16 /**
17 * Do we need to either map r,g,b->a or a->r. configComponentMask indicates which channels are
18 * present in the texture's config. swizzleComponentMask indicates the channels present in the
19 * shader swizzle.
20 */
swizzle_requires_alpha_remapping(const GrGLCaps & caps,uint32_t configComponentMask,uint32_t swizzleComponentMask)21 static bool swizzle_requires_alpha_remapping(const GrGLCaps& caps,
22 uint32_t configComponentMask,
23 uint32_t swizzleComponentMask) {
24 if (caps.textureSwizzleSupport()) {
25 // Any remapping is handled using texture swizzling not shader modifications.
26 return false;
27 }
28 // check if the texture is alpha-only
29 if (kA_GrColorComponentFlag == configComponentMask) {
30 if (caps.textureRedSupport() && (kA_GrColorComponentFlag & swizzleComponentMask)) {
31 // we must map the swizzle 'a's to 'r'.
32 return true;
33 }
34 if (kRGB_GrColorComponentFlags & swizzleComponentMask) {
35 // The 'r', 'g', and/or 'b's must be mapped to 'a' according to our semantics that
36 // alpha-only textures smear alpha across all four channels when read.
37 return true;
38 }
39 }
40 return false;
41 }
42
gen_texture_key(const GrProcessor & proc,const GrGLCaps & caps)43 static uint32_t gen_texture_key(const GrProcessor& proc, const GrGLCaps& caps) {
44 uint32_t key = 0;
45 int numTextures = proc.numTextures();
46 for (int t = 0; t < numTextures; ++t) {
47 const GrTextureAccess& access = proc.textureAccess(t);
48 uint32_t configComponentMask = GrPixelConfigComponentMask(access.getTexture()->config());
49 if (swizzle_requires_alpha_remapping(caps, configComponentMask, access.swizzleMask())) {
50 key |= 1 << t;
51 }
52 }
53 return key;
54 }
55
56 /**
57 * A function which emits a meta key into the key builder. This is required because shader code may
58 * be dependent on properties of the effect that the effect itself doesn't use
59 * in its key (e.g. the pixel format of textures used). So we create a meta-key for
60 * every effect using this function. It is also responsible for inserting the effect's class ID
61 * which must be different for every GrProcessor subclass. It can fail if an effect uses too many
62 * textures, transforms, etc, for the space allotted in the meta-key. NOTE, both FPs and GPs share
63 * this function because it is hairy, though FPs do not have attribs, and GPs do not have transforms
64 */
get_meta_key(const GrProcessor & proc,const GrGLCaps & caps,uint32_t transformKey,GrProcessorKeyBuilder * b)65 static bool get_meta_key(const GrProcessor& proc,
66 const GrGLCaps& caps,
67 uint32_t transformKey,
68 GrProcessorKeyBuilder* b) {
69 size_t processorKeySize = b->size();
70 uint32_t textureKey = gen_texture_key(proc, caps);
71 uint32_t classID = proc.classID();
72
73 // Currently we allow 16 bits for each of the above portions of the meta-key. Fail if they
74 // don't fit.
75 static const uint32_t kMetaKeyInvalidMask = ~((uint32_t) SK_MaxU16);
76 if ((textureKey | transformKey | classID) & kMetaKeyInvalidMask) {
77 return false;
78 }
79 if (processorKeySize > SK_MaxU16) {
80 return false;
81 }
82
83 uint32_t* key = b->add32n(2);
84 key[0] = (textureKey << 16 | transformKey);
85 key[1] = (classID << 16 | SkToU16(processorKeySize));
86 return true;
87 }
88
Build(GrProgramDesc * desc,const GrPrimitiveProcessor & primProc,const GrPipeline & pipeline,const GrGLGpu * gpu,const GrBatchTracker & batchTracker)89 bool GrGLProgramDescBuilder::Build(GrProgramDesc* desc,
90 const GrPrimitiveProcessor& primProc,
91 const GrPipeline& pipeline,
92 const GrGLGpu* gpu,
93 const GrBatchTracker& batchTracker) {
94 // The descriptor is used as a cache key. Thus when a field of the
95 // descriptor will not affect program generation (because of the attribute
96 // bindings in use or other descriptor field settings) it should be set
97 // to a canonical value to avoid duplicate programs with different keys.
98
99 GrGLProgramDesc* glDesc = (GrGLProgramDesc*) desc;
100
101 GR_STATIC_ASSERT(0 == kProcessorKeysOffset % sizeof(uint32_t));
102 // Make room for everything up to the effect keys.
103 glDesc->key().reset();
104 glDesc->key().push_back_n(kProcessorKeysOffset);
105
106 GrProcessorKeyBuilder b(&glDesc->key());
107
108 primProc.getGLProcessorKey(batchTracker, *gpu->glCaps().glslCaps(), &b);
109 //**** use glslCaps here?
110 if (!get_meta_key(primProc, gpu->glCaps(), 0, &b)) {
111 glDesc->key().reset();
112 return false;
113 }
114
115 for (int s = 0; s < pipeline.numFragmentStages(); ++s) {
116 const GrPendingFragmentStage& fps = pipeline.getFragmentStage(s);
117 const GrFragmentProcessor& fp = *fps.processor();
118 fp.getGLProcessorKey(*gpu->glCaps().glslCaps(), &b);
119 //**** use glslCaps here?
120 if (!get_meta_key(fp, gpu->glCaps(), primProc.getTransformKey(fp.coordTransforms()), &b)) {
121 glDesc->key().reset();
122 return false;
123 }
124 }
125
126 const GrXferProcessor& xp = *pipeline.getXferProcessor();
127 xp.getGLProcessorKey(*gpu->glCaps().glslCaps(), &b);
128 //**** use glslCaps here?
129 if (!get_meta_key(xp, gpu->glCaps(), 0, &b)) {
130 glDesc->key().reset();
131 return false;
132 }
133
134 // --------DO NOT MOVE HEADER ABOVE THIS LINE--------------------------------------------------
135 // Because header is a pointer into the dynamic array, we can't push any new data into the key
136 // below here.
137 KeyHeader* header = glDesc->atOffset<KeyHeader, kHeaderOffset>();
138
139 // make sure any padding in the header is zeroed.
140 memset(header, 0, kHeaderSize);
141
142 if (pipeline.readsFragPosition()) {
143 header->fFragPosKey =
144 GrGLFragmentShaderBuilder::KeyForFragmentPosition(pipeline.getRenderTarget(),
145 gpu->glCaps());
146 } else {
147 header->fFragPosKey = 0;
148 }
149 header->fSnapVerticesToPixelCenters = pipeline.snapVerticesToPixelCenters();
150 header->fColorEffectCnt = pipeline.numColorFragmentStages();
151 header->fCoverageEffectCnt = pipeline.numCoverageFragmentStages();
152 glDesc->finalize();
153 return true;
154 }
155