• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "GrProcessor.h"
10 #include "GrPipeline.h"
11 #include "SkChecksum.h"
12 #include "gl/GrGLDefines.h"
13 #include "gl/GrGLTexture.h"
14 #include "gl/GrGLTypes.h"
15 #include "glsl/GrGLSLFragmentProcessor.h"
16 #include "glsl/GrGLSLFragmentShaderBuilder.h"
17 #include "glsl/GrGLSLCaps.h"
18 
texture_target_key(GrGLenum target)19 static uint8_t texture_target_key(GrGLenum target) {
20     switch (target) {
21         case GR_GL_TEXTURE_2D:
22             return 0;
23         case GR_GL_TEXTURE_EXTERNAL:
24             return 1;
25         case GR_GL_TEXTURE_RECTANGLE:
26             return 2;
27         default:
28             SkFAIL("Unexpected texture target.");
29             return 0;
30     }
31 }
32 
add_texture_key(GrProcessorKeyBuilder * b,const GrProcessor & proc,const GrGLSLCaps & caps)33 static void add_texture_key(GrProcessorKeyBuilder* b, const GrProcessor& proc,
34                             const GrGLSLCaps& caps) {
35     int numTextures = proc.numTextures();
36     // Need two bytes per key (swizzle and target).
37     int word32Count = (proc.numTextures() + 1) / 2;
38     if (0 == word32Count) {
39         return;
40     }
41     uint16_t* k16 = SkTCast<uint16_t*>(b->add32n(word32Count));
42     for (int i = 0; i < numTextures; ++i) {
43         const GrTextureAccess& access = proc.textureAccess(i);
44         GrGLTexture* texture = static_cast<GrGLTexture*>(access.getTexture());
45         k16[i] = SkToU16(caps.configTextureSwizzle(texture->config()).asKey() |
46                          (texture_target_key(texture->target()) << 8));
47     }
48     // zero the last 16 bits if the number of textures is odd.
49     if (numTextures & 0x1) {
50         k16[numTextures] = 0;
51     }
52 }
53 
54 /**
55  * A function which emits a meta key into the key builder.  This is required because shader code may
56  * be dependent on properties of the effect that the effect itself doesn't use
57  * in its key (e.g. the pixel format of textures used). So we create a meta-key for
58  * every effect using this function. It is also responsible for inserting the effect's class ID
59  * which must be different for every GrProcessor subclass. It can fail if an effect uses too many
60  * transforms, etc, for the space allotted in the meta-key.  NOTE, both FPs and GPs share this
61  * function because it is hairy, though FPs do not have attribs, and GPs do not have transforms
62  */
gen_meta_key(const GrProcessor & proc,const GrGLSLCaps & glslCaps,uint32_t transformKey,GrProcessorKeyBuilder * b)63 static bool gen_meta_key(const GrProcessor& proc,
64                          const GrGLSLCaps& glslCaps,
65                          uint32_t transformKey,
66                          GrProcessorKeyBuilder* b) {
67     size_t processorKeySize = b->size();
68     uint32_t classID = proc.classID();
69 
70     // Currently we allow 16 bits for the class id and the overall processor key size.
71     static const uint32_t kMetaKeyInvalidMask = ~((uint32_t) SK_MaxU16);
72     if ((processorKeySize | classID) & kMetaKeyInvalidMask) {
73         return false;
74     }
75 
76     add_texture_key(b, proc, glslCaps);
77 
78     uint32_t* key = b->add32n(2);
79     key[0] = (classID << 16) | SkToU32(processorKeySize);
80     key[1] = transformKey;
81     return true;
82 }
83 
gen_frag_proc_and_meta_keys(const GrPrimitiveProcessor & primProc,const GrFragmentProcessor & fp,const GrGLSLCaps & glslCaps,GrProcessorKeyBuilder * b)84 static bool gen_frag_proc_and_meta_keys(const GrPrimitiveProcessor& primProc,
85                                         const GrFragmentProcessor& fp,
86                                         const GrGLSLCaps& glslCaps,
87                                         GrProcessorKeyBuilder* b) {
88     for (int i = 0; i < fp.numChildProcessors(); ++i) {
89         if (!gen_frag_proc_and_meta_keys(primProc, fp.childProcessor(i), glslCaps, b)) {
90             return false;
91         }
92     }
93 
94     fp.getGLSLProcessorKey(glslCaps, b);
95 
96     return gen_meta_key(fp, glslCaps, primProc.getTransformKey(fp.coordTransforms(),
97                                                                fp.numTransformsExclChildren()), b);
98 }
99 
Build(GrProgramDesc * desc,const GrPrimitiveProcessor & primProc,const GrPipeline & pipeline,const GrGLSLCaps & glslCaps)100 bool GrGLProgramDescBuilder::Build(GrProgramDesc* desc,
101                                    const GrPrimitiveProcessor& primProc,
102                                    const GrPipeline& pipeline,
103                                    const GrGLSLCaps& glslCaps) {
104     // The descriptor is used as a cache key. Thus when a field of the
105     // descriptor will not affect program generation (because of the attribute
106     // bindings in use or other descriptor field settings) it should be set
107     // to a canonical value to avoid duplicate programs with different keys.
108 
109     GrGLProgramDesc* glDesc = (GrGLProgramDesc*) desc;
110 
111     GR_STATIC_ASSERT(0 == kProcessorKeysOffset % sizeof(uint32_t));
112     // Make room for everything up to the effect keys.
113     glDesc->key().reset();
114     glDesc->key().push_back_n(kProcessorKeysOffset);
115 
116     GrProcessorKeyBuilder b(&glDesc->key());
117 
118     primProc.getGLSLProcessorKey(glslCaps, &b);
119     if (!gen_meta_key(primProc, glslCaps, 0, &b)) {
120         glDesc->key().reset();
121         return false;
122     }
123 
124     for (int i = 0; i < pipeline.numFragmentProcessors(); ++i) {
125         const GrFragmentProcessor& fp = pipeline.getFragmentProcessor(i);
126         if (!gen_frag_proc_and_meta_keys(primProc, fp, glslCaps, &b)) {
127             glDesc->key().reset();
128             return false;
129         }
130     }
131 
132     const GrXferProcessor& xp = pipeline.getXferProcessor();
133     xp.getGLSLProcessorKey(glslCaps, &b);
134     if (!gen_meta_key(xp, glslCaps, 0, &b)) {
135         glDesc->key().reset();
136         return false;
137     }
138 
139     // --------DO NOT MOVE HEADER ABOVE THIS LINE--------------------------------------------------
140     // Because header is a pointer into the dynamic array, we can't push any new data into the key
141     // below here.
142     KeyHeader* header = glDesc->atOffset<KeyHeader, kHeaderOffset>();
143 
144     // make sure any padding in the header is zeroed.
145     memset(header, 0, kHeaderSize);
146 
147     if (pipeline.readsFragPosition()) {
148         header->fFragPosKey =
149                 GrGLSLFragmentShaderBuilder::KeyForFragmentPosition(pipeline.getRenderTarget());
150     } else {
151         header->fFragPosKey = 0;
152     }
153 
154     header->fOutputSwizzle =
155         glslCaps.configOutputSwizzle(pipeline.getRenderTarget()->config()).asKey();
156 
157     if (pipeline.ignoresCoverage()) {
158         header->fIgnoresCoverage = 1;
159     } else {
160         header->fIgnoresCoverage = 0;
161     }
162 
163     header->fSnapVerticesToPixelCenters = pipeline.snapVerticesToPixelCenters();
164     header->fColorEffectCnt = pipeline.numColorFragmentProcessors();
165     header->fCoverageEffectCnt = pipeline.numCoverageFragmentProcessors();
166     glDesc->finalize();
167     return true;
168 }
169