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 */ 21static 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 43static 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 */ 65static 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 89bool 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