1798c8c4fe61f2172ae52cb626843a64069e18882bsalomon@google.com/* 2798c8c4fe61f2172ae52cb626843a64069e18882bsalomon@google.com * Copyright 2013 Google Inc. 3798c8c4fe61f2172ae52cb626843a64069e18882bsalomon@google.com * 4798c8c4fe61f2172ae52cb626843a64069e18882bsalomon@google.com * Use of this source code is governed by a BSD-style license that can be 5798c8c4fe61f2172ae52cb626843a64069e18882bsalomon@google.com * found in the LICENSE file. 6798c8c4fe61f2172ae52cb626843a64069e18882bsalomon@google.com */ 7798c8c4fe61f2172ae52cb626843a64069e18882bsalomon@google.com 830ba436f04e61d4505fb854d5fc56079636e0788joshualitt#include "gl/builders/GrGLProgramBuilder.h" 9798c8c4fe61f2172ae52cb626843a64069e18882bsalomon@google.com#include "GrGLProgramDesc.h" 10b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt#include "GrBackendProcessorFactory.h" 11b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt#include "GrProcessor.h" 12798c8c4fe61f2172ae52cb626843a64069e18882bsalomon@google.com#include "GrGpuGL.h" 13170f90b4576f291879371ecd6ae4bc2b1d85c64aegdaniel#include "GrOptDrawState.h" 14798c8c4fe61f2172ae52cb626843a64069e18882bsalomon@google.com 152db3ded335fdb6697623bece61cabc307a414770bsalomon@google.com#include "SkChecksum.h" 162db3ded335fdb6697623bece61cabc307a414770bsalomon@google.com 1723e280d1f227d94f6b3dfd0b47359cca1569e1b4joshualitt/** 1823e280d1f227d94f6b3dfd0b47359cca1569e1b4joshualitt * The key for an individual coord transform is made up of a matrix type and a bit that 1923e280d1f227d94f6b3dfd0b47359cca1569e1b4joshualitt * indicates the source of the input coords. 2023e280d1f227d94f6b3dfd0b47359cca1569e1b4joshualitt */ 2123e280d1f227d94f6b3dfd0b47359cca1569e1b4joshualittenum { 2223e280d1f227d94f6b3dfd0b47359cca1569e1b4joshualitt kMatrixTypeKeyBits = 1, 2323e280d1f227d94f6b3dfd0b47359cca1569e1b4joshualitt kMatrixTypeKeyMask = (1 << kMatrixTypeKeyBits) - 1, 2423e280d1f227d94f6b3dfd0b47359cca1569e1b4joshualitt kPositionCoords_Flag = (1 << kMatrixTypeKeyBits), 2523e280d1f227d94f6b3dfd0b47359cca1569e1b4joshualitt kTransformKeyBits = kMatrixTypeKeyBits + 1, 2623e280d1f227d94f6b3dfd0b47359cca1569e1b4joshualitt}; 2723e280d1f227d94f6b3dfd0b47359cca1569e1b4joshualitt 2823e280d1f227d94f6b3dfd0b47359cca1569e1b4joshualitt/** 2923e280d1f227d94f6b3dfd0b47359cca1569e1b4joshualitt * We specialize the vertex code for each of these matrix types. 3023e280d1f227d94f6b3dfd0b47359cca1569e1b4joshualitt */ 3123e280d1f227d94f6b3dfd0b47359cca1569e1b4joshualittenum MatrixType { 3223e280d1f227d94f6b3dfd0b47359cca1569e1b4joshualitt kNoPersp_MatrixType = 0, 3323e280d1f227d94f6b3dfd0b47359cca1569e1b4joshualitt kGeneral_MatrixType = 1, 3423e280d1f227d94f6b3dfd0b47359cca1569e1b4joshualitt}; 3523e280d1f227d94f6b3dfd0b47359cca1569e1b4joshualitt 3623e280d1f227d94f6b3dfd0b47359cca1569e1b4joshualitt/** 3723e280d1f227d94f6b3dfd0b47359cca1569e1b4joshualitt * Do we need to either map r,g,b->a or a->r. configComponentMask indicates which channels are 3823e280d1f227d94f6b3dfd0b47359cca1569e1b4joshualitt * present in the texture's config. swizzleComponentMask indicates the channels present in the 3923e280d1f227d94f6b3dfd0b47359cca1569e1b4joshualitt * shader swizzle. 4023e280d1f227d94f6b3dfd0b47359cca1569e1b4joshualitt */ 4123e280d1f227d94f6b3dfd0b47359cca1569e1b4joshualittstatic bool swizzle_requires_alpha_remapping(const GrGLCaps& caps, 4223e280d1f227d94f6b3dfd0b47359cca1569e1b4joshualitt uint32_t configComponentMask, 4323e280d1f227d94f6b3dfd0b47359cca1569e1b4joshualitt uint32_t swizzleComponentMask) { 4423e280d1f227d94f6b3dfd0b47359cca1569e1b4joshualitt if (caps.textureSwizzleSupport()) { 4523e280d1f227d94f6b3dfd0b47359cca1569e1b4joshualitt // Any remapping is handled using texture swizzling not shader modifications. 4623e280d1f227d94f6b3dfd0b47359cca1569e1b4joshualitt return false; 4723e280d1f227d94f6b3dfd0b47359cca1569e1b4joshualitt } 4823e280d1f227d94f6b3dfd0b47359cca1569e1b4joshualitt // check if the texture is alpha-only 4923e280d1f227d94f6b3dfd0b47359cca1569e1b4joshualitt if (kA_GrColorComponentFlag == configComponentMask) { 5023e280d1f227d94f6b3dfd0b47359cca1569e1b4joshualitt if (caps.textureRedSupport() && (kA_GrColorComponentFlag & swizzleComponentMask)) { 5123e280d1f227d94f6b3dfd0b47359cca1569e1b4joshualitt // we must map the swizzle 'a's to 'r'. 5223e280d1f227d94f6b3dfd0b47359cca1569e1b4joshualitt return true; 5323e280d1f227d94f6b3dfd0b47359cca1569e1b4joshualitt } 5423e280d1f227d94f6b3dfd0b47359cca1569e1b4joshualitt if (kRGB_GrColorComponentFlags & swizzleComponentMask) { 5523e280d1f227d94f6b3dfd0b47359cca1569e1b4joshualitt // The 'r', 'g', and/or 'b's must be mapped to 'a' according to our semantics that 5623e280d1f227d94f6b3dfd0b47359cca1569e1b4joshualitt // alpha-only textures smear alpha across all four channels when read. 5723e280d1f227d94f6b3dfd0b47359cca1569e1b4joshualitt return true; 5823e280d1f227d94f6b3dfd0b47359cca1569e1b4joshualitt } 5923e280d1f227d94f6b3dfd0b47359cca1569e1b4joshualitt } 6023e280d1f227d94f6b3dfd0b47359cca1569e1b4joshualitt return false; 6123e280d1f227d94f6b3dfd0b47359cca1569e1b4joshualitt} 6223e280d1f227d94f6b3dfd0b47359cca1569e1b4joshualitt 63b0a8a377f832c59cee939ad721e1f87d378b7142joshualittstatic uint32_t gen_attrib_key(const GrGeometryProcessor* effect) { 6423e280d1f227d94f6b3dfd0b47359cca1569e1b4joshualitt uint32_t key = 0; 6523e280d1f227d94f6b3dfd0b47359cca1569e1b4joshualitt 66b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt const GrGeometryProcessor::VertexAttribArray& vars = effect->getVertexAttribs(); 6723e280d1f227d94f6b3dfd0b47359cca1569e1b4joshualitt int numAttributes = vars.count(); 6823e280d1f227d94f6b3dfd0b47359cca1569e1b4joshualitt SkASSERT(numAttributes <= 2); 6923e280d1f227d94f6b3dfd0b47359cca1569e1b4joshualitt for (int a = 0; a < numAttributes; ++a) { 7023e280d1f227d94f6b3dfd0b47359cca1569e1b4joshualitt uint32_t value = 1 << a; 7123e280d1f227d94f6b3dfd0b47359cca1569e1b4joshualitt key |= value; 7223e280d1f227d94f6b3dfd0b47359cca1569e1b4joshualitt } 7323e280d1f227d94f6b3dfd0b47359cca1569e1b4joshualitt return key; 7423e280d1f227d94f6b3dfd0b47359cca1569e1b4joshualitt} 7523e280d1f227d94f6b3dfd0b47359cca1569e1b4joshualitt 76b0a8a377f832c59cee939ad721e1f87d378b7142joshualittstatic uint32_t gen_transform_key(const GrProcessorStage& effectStage, 7723e280d1f227d94f6b3dfd0b47359cca1569e1b4joshualitt bool useExplicitLocalCoords) { 7823e280d1f227d94f6b3dfd0b47359cca1569e1b4joshualitt uint32_t totalKey = 0; 79b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt int numTransforms = effectStage.getProcessor()->numTransforms(); 8023e280d1f227d94f6b3dfd0b47359cca1569e1b4joshualitt for (int t = 0; t < numTransforms; ++t) { 8123e280d1f227d94f6b3dfd0b47359cca1569e1b4joshualitt uint32_t key = 0; 8223e280d1f227d94f6b3dfd0b47359cca1569e1b4joshualitt if (effectStage.isPerspectiveCoordTransform(t, useExplicitLocalCoords)) { 8323e280d1f227d94f6b3dfd0b47359cca1569e1b4joshualitt key |= kGeneral_MatrixType; 8423e280d1f227d94f6b3dfd0b47359cca1569e1b4joshualitt } else { 8523e280d1f227d94f6b3dfd0b47359cca1569e1b4joshualitt key |= kNoPersp_MatrixType; 8623e280d1f227d94f6b3dfd0b47359cca1569e1b4joshualitt } 8723e280d1f227d94f6b3dfd0b47359cca1569e1b4joshualitt 88b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt const GrCoordTransform& coordTransform = effectStage.getProcessor()->coordTransform(t); 8923e280d1f227d94f6b3dfd0b47359cca1569e1b4joshualitt if (kLocal_GrCoordSet != coordTransform.sourceCoords() && useExplicitLocalCoords) { 9023e280d1f227d94f6b3dfd0b47359cca1569e1b4joshualitt key |= kPositionCoords_Flag; 9123e280d1f227d94f6b3dfd0b47359cca1569e1b4joshualitt } 9223e280d1f227d94f6b3dfd0b47359cca1569e1b4joshualitt key <<= kTransformKeyBits * t; 9323e280d1f227d94f6b3dfd0b47359cca1569e1b4joshualitt SkASSERT(0 == (totalKey & key)); // keys for each transform ought not to overlap 9423e280d1f227d94f6b3dfd0b47359cca1569e1b4joshualitt totalKey |= key; 9523e280d1f227d94f6b3dfd0b47359cca1569e1b4joshualitt } 9623e280d1f227d94f6b3dfd0b47359cca1569e1b4joshualitt return totalKey; 9723e280d1f227d94f6b3dfd0b47359cca1569e1b4joshualitt} 9823e280d1f227d94f6b3dfd0b47359cca1569e1b4joshualitt 99b0a8a377f832c59cee939ad721e1f87d378b7142joshualittstatic uint32_t gen_texture_key(const GrProcessor* effect, const GrGLCaps& caps) { 10023e280d1f227d94f6b3dfd0b47359cca1569e1b4joshualitt uint32_t key = 0; 10123e280d1f227d94f6b3dfd0b47359cca1569e1b4joshualitt int numTextures = effect->numTextures(); 10223e280d1f227d94f6b3dfd0b47359cca1569e1b4joshualitt for (int t = 0; t < numTextures; ++t) { 10323e280d1f227d94f6b3dfd0b47359cca1569e1b4joshualitt const GrTextureAccess& access = effect->textureAccess(t); 10423e280d1f227d94f6b3dfd0b47359cca1569e1b4joshualitt uint32_t configComponentMask = GrPixelConfigComponentMask(access.getTexture()->config()); 10523e280d1f227d94f6b3dfd0b47359cca1569e1b4joshualitt if (swizzle_requires_alpha_remapping(caps, configComponentMask, access.swizzleMask())) { 10623e280d1f227d94f6b3dfd0b47359cca1569e1b4joshualitt key |= 1 << t; 10723e280d1f227d94f6b3dfd0b47359cca1569e1b4joshualitt } 10823e280d1f227d94f6b3dfd0b47359cca1569e1b4joshualitt } 10923e280d1f227d94f6b3dfd0b47359cca1569e1b4joshualitt return key; 11023e280d1f227d94f6b3dfd0b47359cca1569e1b4joshualitt} 11123e280d1f227d94f6b3dfd0b47359cca1569e1b4joshualitt 11223e280d1f227d94f6b3dfd0b47359cca1569e1b4joshualitt/** 11323e280d1f227d94f6b3dfd0b47359cca1569e1b4joshualitt * A function which emits a meta key into the key builder. This is required because shader code may 11423e280d1f227d94f6b3dfd0b47359cca1569e1b4joshualitt * be dependent on properties of the effect that the effect itself doesn't use 11523e280d1f227d94f6b3dfd0b47359cca1569e1b4joshualitt * in its key (e.g. the pixel format of textures used). So we create a meta-key for 11623e280d1f227d94f6b3dfd0b47359cca1569e1b4joshualitt * every effect using this function. It is also responsible for inserting the effect's class ID 117b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt * which must be different for every GrProcessor subclass. It can fail if an effect uses too many 118b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt * textures, transforms, etc, for the space allotted in the meta-key. 11923e280d1f227d94f6b3dfd0b47359cca1569e1b4joshualitt */ 12023e280d1f227d94f6b3dfd0b47359cca1569e1b4joshualitt 121b0a8a377f832c59cee939ad721e1f87d378b7142joshualittstatic uint32_t* get_processor_meta_key(const GrProcessorStage& processorStage, 122b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt bool useExplicitLocalCoords, 123b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt const GrGLCaps& caps, 124b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt GrProcessorKeyBuilder* b) { 12523e280d1f227d94f6b3dfd0b47359cca1569e1b4joshualitt 126b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt uint32_t textureKey = gen_texture_key(processorStage.getProcessor(), caps); 127b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt uint32_t transformKey = gen_transform_key(processorStage,useExplicitLocalCoords); 128b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt uint32_t classID = processorStage.getProcessor()->getFactory().effectClassID(); 12923e280d1f227d94f6b3dfd0b47359cca1569e1b4joshualitt 13023e280d1f227d94f6b3dfd0b47359cca1569e1b4joshualitt // Currently we allow 16 bits for each of the above portions of the meta-key. Fail if they 13123e280d1f227d94f6b3dfd0b47359cca1569e1b4joshualitt // don't fit. 13223e280d1f227d94f6b3dfd0b47359cca1569e1b4joshualitt static const uint32_t kMetaKeyInvalidMask = ~((uint32_t) SK_MaxU16); 133b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt if ((textureKey | transformKey | classID) & kMetaKeyInvalidMask) { 134b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt return NULL; 13523e280d1f227d94f6b3dfd0b47359cca1569e1b4joshualitt } 13623e280d1f227d94f6b3dfd0b47359cca1569e1b4joshualitt 13723e280d1f227d94f6b3dfd0b47359cca1569e1b4joshualitt uint32_t* key = b->add32n(2); 13823e280d1f227d94f6b3dfd0b47359cca1569e1b4joshualitt key[0] = (textureKey << 16 | transformKey); 139b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt key[1] = (classID << 16); 140b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt return key; 141b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt} 142b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt 143b0a8a377f832c59cee939ad721e1f87d378b7142joshualittbool GrGLProgramDesc::GetProcessorKey(const GrProcessorStage& stage, 144b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt const GrGLCaps& caps, 145b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt bool useExplicitLocalCoords, 146b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt GrProcessorKeyBuilder* b, 147b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt uint16_t* processorKeySize) { 148b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt const GrProcessor& effect = *stage.getProcessor(); 149b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt const GrBackendProcessorFactory& factory = effect.getFactory(); 150b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt factory.getGLProcessorKey(effect, caps, b); 151b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt size_t size = b->size(); 152b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt if (size > SK_MaxU16) { 153b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt *processorKeySize = 0; // suppresses a warning. 154b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt return false; 155b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt } 156b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt *processorKeySize = SkToU16(size); 157b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt if (NULL == get_processor_meta_key(stage, useExplicitLocalCoords, caps, b)) { 158b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt return false; 159b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt } 16023e280d1f227d94f6b3dfd0b47359cca1569e1b4joshualitt return true; 16123e280d1f227d94f6b3dfd0b47359cca1569e1b4joshualitt} 16223e280d1f227d94f6b3dfd0b47359cca1569e1b4joshualitt 163b0a8a377f832c59cee939ad721e1f87d378b7142joshualittbool GrGLProgramDesc::GetGeometryProcessorKey(const GrGeometryStage& stage, 164b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt const GrGLCaps& caps, 165b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt bool useExplicitLocalCoords, 166b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt GrProcessorKeyBuilder* b, 167b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt uint16_t* processorKeySize) { 168b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt const GrProcessor& effect = *stage.getProcessor(); 169b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt const GrBackendProcessorFactory& factory = effect.getFactory(); 170b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt factory.getGLProcessorKey(effect, caps, b); 171929f29a5c1bffa7f7c1b5a376351d0762b8ac561bsalomon size_t size = b->size(); 172929f29a5c1bffa7f7c1b5a376351d0762b8ac561bsalomon if (size > SK_MaxU16) { 173b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt *processorKeySize = 0; // suppresses a warning. 174929f29a5c1bffa7f7c1b5a376351d0762b8ac561bsalomon return false; 175929f29a5c1bffa7f7c1b5a376351d0762b8ac561bsalomon } 176b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt *processorKeySize = SkToU16(size); 177b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt uint32_t* key = get_processor_meta_key(stage, useExplicitLocalCoords, caps, b); 178b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt if (NULL == key) { 179929f29a5c1bffa7f7c1b5a376351d0762b8ac561bsalomon return false; 180929f29a5c1bffa7f7c1b5a376351d0762b8ac561bsalomon } 181b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt uint32_t attribKey = gen_attrib_key(stage.getGeometryProcessor()); 182b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt 183b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt // Currently we allow 16 bits for each of the above portions of the meta-key. Fail if they 184b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt // don't fit. 185b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt static const uint32_t kMetaKeyInvalidMask = ~((uint32_t) SK_MaxU16); 186b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt if ((attribKey) & kMetaKeyInvalidMask) { 187b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt return false; 188b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt } 189b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt 190b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt key[1] |= attribKey; 191929f29a5c1bffa7f7c1b5a376351d0762b8ac561bsalomon return true; 192eb6879f50a5564eeb981ec5616b55bf685eb76fcbsalomon@google.com} 193848faf00ec33d39ab3e31e9a11d805cae6ac6562bsalomon 194b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt 195170f90b4576f291879371ecd6ae4bc2b1d85c64aegdanielbool GrGLProgramDesc::Build(const GrOptDrawState& optState, 1960a6fe71f1bc0e601b41b7ae6d28b8c96a2c41116commit-bot@chromium.org GrGpu::DrawType drawType, 197798c8c4fe61f2172ae52cb626843a64069e18882bsalomon@google.com GrBlendCoeff srcCoeff, 198798c8c4fe61f2172ae52cb626843a64069e18882bsalomon@google.com GrBlendCoeff dstCoeff, 199ae444965c43ad16575730ce8e3abdcaded296d94egdaniel GrGpuGL* gpu, 20026e18b593ab65e4d92dfbce92579d8bc180d4c2cbsalomon@google.com const GrDeviceCoordTexture* dstCopy, 201b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt const GrGeometryStage** geometryProcessor, 202b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt SkTArray<const GrFragmentStage*, true>* colorStages, 203b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt SkTArray<const GrFragmentStage*, true>* coverageStages, 204798c8c4fe61f2172ae52cb626843a64069e18882bsalomon@google.com GrGLProgramDesc* desc) { 2052c84aa35988c661b3e5513c8ba9b3959832ff288bsalomon@google.com colorStages->reset(); 2062c84aa35988c661b3e5513c8ba9b3959832ff288bsalomon@google.com coverageStages->reset(); 2072c84aa35988c661b3e5513c8ba9b3959832ff288bsalomon@google.com 208170f90b4576f291879371ecd6ae4bc2b1d85c64aegdaniel bool inputColorIsUsed = optState.inputColorIsUsed(); 209033ea7f2ad65e567d1812546ef60e55a54ac88dfegdaniel bool inputCoverageIsUsed = optState.inputCoverageIsUsed(); 210798c8c4fe61f2172ae52cb626843a64069e18882bsalomon@google.com 211798c8c4fe61f2172ae52cb626843a64069e18882bsalomon@google.com // The descriptor is used as a cache key. Thus when a field of the 212798c8c4fe61f2172ae52cb626843a64069e18882bsalomon@google.com // descriptor will not affect program generation (because of the attribute 213798c8c4fe61f2172ae52cb626843a64069e18882bsalomon@google.com // bindings in use or other descriptor field settings) it should be set 214798c8c4fe61f2172ae52cb626843a64069e18882bsalomon@google.com // to a canonical value to avoid duplicate programs with different keys. 215798c8c4fe61f2172ae52cb626843a64069e18882bsalomon@google.com 216a7dc0a83f0b59424a61e01bf3435cd7957e84e35egdaniel bool requiresLocalCoordAttrib = optState.requiresLocalCoordAttrib(); 217ec56e4545477e30d4f165ca55ed99f90525c6c38kkinnunen 218170f90b4576f291879371ecd6ae4bc2b1d85c64aegdaniel int numStages = optState.numTotalStages(); 219170f90b4576f291879371ecd6ae4bc2b1d85c64aegdaniel 220929f29a5c1bffa7f7c1b5a376351d0762b8ac561bsalomon GR_STATIC_ASSERT(0 == kEffectKeyOffsetsAndLengthOffset % sizeof(uint32_t)); 221848faf00ec33d39ab3e31e9a11d805cae6ac6562bsalomon // Make room for everything up to and including the array of offsets to effect keys. 222848faf00ec33d39ab3e31e9a11d805cae6ac6562bsalomon desc->fKey.reset(); 223929f29a5c1bffa7f7c1b5a376351d0762b8ac561bsalomon desc->fKey.push_back_n(kEffectKeyOffsetsAndLengthOffset + 2 * sizeof(uint16_t) * numStages); 2240a6fe71f1bc0e601b41b7ae6d28b8c96a2c41116commit-bot@chromium.org 225929f29a5c1bffa7f7c1b5a376351d0762b8ac561bsalomon int offsetAndSizeIndex = 0; 226bd769d0f1c8cf6ccbb2738dfad1624a4c828e4ebjoshualitt 227bd769d0f1c8cf6ccbb2738dfad1624a4c828e4ebjoshualitt KeyHeader* header = desc->header(); 228bd769d0f1c8cf6ccbb2738dfad1624a4c828e4ebjoshualitt // make sure any padding in the header is zeroed. 229bd769d0f1c8cf6ccbb2738dfad1624a4c828e4ebjoshualitt memset(desc->header(), 0, kHeaderSize); 230bd769d0f1c8cf6ccbb2738dfad1624a4c828e4ebjoshualitt 231bd769d0f1c8cf6ccbb2738dfad1624a4c828e4ebjoshualitt // We can only have one effect which touches the vertex shader 232170f90b4576f291879371ecd6ae4bc2b1d85c64aegdaniel if (optState.hasGeometryProcessor()) { 233bd769d0f1c8cf6ccbb2738dfad1624a4c828e4ebjoshualitt uint16_t* offsetAndSize = 234bd769d0f1c8cf6ccbb2738dfad1624a4c828e4ebjoshualitt reinterpret_cast<uint16_t*>(desc->fKey.begin() + kEffectKeyOffsetsAndLengthOffset + 235bd769d0f1c8cf6ccbb2738dfad1624a4c828e4ebjoshualitt offsetAndSizeIndex * 2 * sizeof(uint16_t)); 236bd769d0f1c8cf6ccbb2738dfad1624a4c828e4ebjoshualitt 237b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt GrProcessorKeyBuilder b(&desc->fKey); 238b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt uint16_t processorKeySize; 239b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt uint32_t processorOffset = desc->fKey.count(); 240b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt const GrGeometryStage& gpStage = *optState.getGeometryProcessor(); 241b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt if (processorOffset > SK_MaxU16 || 242b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt !GetGeometryProcessorKey(gpStage, gpu->glCaps(), requiresLocalCoordAttrib, &b, 243b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt &processorKeySize)) { 244b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt desc->fKey.reset(); 245b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt return false; 246b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt } 247b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt 248b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt offsetAndSize[0] = SkToU16(processorOffset); 249b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt offsetAndSize[1] = processorKeySize; 250b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt ++offsetAndSizeIndex; 251b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt *geometryProcessor = &gpStage; 252b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt header->fHasGeometryProcessor = true; 253bd769d0f1c8cf6ccbb2738dfad1624a4c828e4ebjoshualitt } 254bd769d0f1c8cf6ccbb2738dfad1624a4c828e4ebjoshualitt 255170f90b4576f291879371ecd6ae4bc2b1d85c64aegdaniel for (int s = 0; s < optState.numColorStages(); ++s) { 256170f90b4576f291879371ecd6ae4bc2b1d85c64aegdaniel uint16_t* offsetAndSize = 257170f90b4576f291879371ecd6ae4bc2b1d85c64aegdaniel reinterpret_cast<uint16_t*>(desc->fKey.begin() + kEffectKeyOffsetsAndLengthOffset + 258170f90b4576f291879371ecd6ae4bc2b1d85c64aegdaniel offsetAndSizeIndex * 2 * sizeof(uint16_t)); 259170f90b4576f291879371ecd6ae4bc2b1d85c64aegdaniel 260b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt GrProcessorKeyBuilder b(&desc->fKey); 261b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt uint16_t processorKeySize; 262b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt uint32_t processorOffset = desc->fKey.count(); 263b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt if (processorOffset > SK_MaxU16 || 264b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt !GetProcessorKey(optState.getColorStage(s), gpu->glCaps(), 265b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt requiresLocalCoordAttrib, &b, &processorKeySize)) { 266b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt desc->fKey.reset(); 267b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt return false; 268b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt } 269170f90b4576f291879371ecd6ae4bc2b1d85c64aegdaniel 270b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt offsetAndSize[0] = SkToU16(processorOffset); 271b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt offsetAndSize[1] = processorKeySize; 272170f90b4576f291879371ecd6ae4bc2b1d85c64aegdaniel ++offsetAndSizeIndex; 273798c8c4fe61f2172ae52cb626843a64069e18882bsalomon@google.com } 2748a4c1030ff4b8336b5ac5b0712691e2f65383440egdaniel 275170f90b4576f291879371ecd6ae4bc2b1d85c64aegdaniel for (int s = 0; s < optState.numCoverageStages(); ++s) { 276170f90b4576f291879371ecd6ae4bc2b1d85c64aegdaniel uint16_t* offsetAndSize = 277170f90b4576f291879371ecd6ae4bc2b1d85c64aegdaniel reinterpret_cast<uint16_t*>(desc->fKey.begin() + kEffectKeyOffsetsAndLengthOffset + 278170f90b4576f291879371ecd6ae4bc2b1d85c64aegdaniel offsetAndSizeIndex * 2 * sizeof(uint16_t)); 279170f90b4576f291879371ecd6ae4bc2b1d85c64aegdaniel 280b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt GrProcessorKeyBuilder b(&desc->fKey); 281b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt uint16_t processorKeySize; 282b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt uint32_t processorOffset = desc->fKey.count(); 283b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt if (processorOffset > SK_MaxU16 || 284b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt !GetProcessorKey(optState.getCoverageStage(s), gpu->glCaps(), 285b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt requiresLocalCoordAttrib, &b, &processorKeySize)) { 286b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt desc->fKey.reset(); 287b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt return false; 288b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt } 289170f90b4576f291879371ecd6ae4bc2b1d85c64aegdaniel 290b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt offsetAndSize[0] = SkToU16(processorOffset); 291b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt offsetAndSize[1] = processorKeySize; 292170f90b4576f291879371ecd6ae4bc2b1d85c64aegdaniel ++offsetAndSizeIndex; 2938a4c1030ff4b8336b5ac5b0712691e2f65383440egdaniel } 294170f90b4576f291879371ecd6ae4bc2b1d85c64aegdaniel 295848faf00ec33d39ab3e31e9a11d805cae6ac6562bsalomon // Because header is a pointer into the dynamic array, we can't push any new data into the key 296848faf00ec33d39ab3e31e9a11d805cae6ac6562bsalomon // below here. 297798c8c4fe61f2172ae52cb626843a64069e18882bsalomon@google.com 298ae444965c43ad16575730ce8e3abdcaded296d94egdaniel 2990a6fe71f1bc0e601b41b7ae6d28b8c96a2c41116commit-bot@chromium.org header->fEmitsPointSize = GrGpu::kDrawPoints_DrawType == drawType; 3002db3ded335fdb6697623bece61cabc307a414770bsalomon@google.com 3012db3ded335fdb6697623bece61cabc307a414770bsalomon@google.com // Currently the experimental GS will only work with triangle prims (and it doesn't do anything 3022db3ded335fdb6697623bece61cabc307a414770bsalomon@google.com // other than pass through values from the VS to the FS anyway). 3032db3ded335fdb6697623bece61cabc307a414770bsalomon@google.com#if GR_GL_EXPERIMENTAL_GS 3042db3ded335fdb6697623bece61cabc307a414770bsalomon@google.com#if 0 3052db3ded335fdb6697623bece61cabc307a414770bsalomon@google.com header->fExperimentalGS = gpu->caps().geometryShaderSupport(); 3062db3ded335fdb6697623bece61cabc307a414770bsalomon@google.com#else 3072db3ded335fdb6697623bece61cabc307a414770bsalomon@google.com header->fExperimentalGS = false; 3082db3ded335fdb6697623bece61cabc307a414770bsalomon@google.com#endif 3092db3ded335fdb6697623bece61cabc307a414770bsalomon@google.com#endif 310cd523ebe2be30f268cdcec2d0b59eba609b9901bbsalomon 311cd523ebe2be30f268cdcec2d0b59eba609b9901bbsalomon if (gpu->caps()->pathRenderingSupport() && 312cd523ebe2be30f268cdcec2d0b59eba609b9901bbsalomon GrGpu::IsPathRenderingDrawType(drawType) && 313cd523ebe2be30f268cdcec2d0b59eba609b9901bbsalomon gpu->glPathRendering()->texturingMode() == GrGLPathRendering::FixedFunction_TexturingMode) { 314cd523ebe2be30f268cdcec2d0b59eba609b9901bbsalomon header->fUseFragShaderOnly = true; 315cd523ebe2be30f268cdcec2d0b59eba609b9901bbsalomon SkASSERT(!optState.hasGeometryProcessor()); 316cd523ebe2be30f268cdcec2d0b59eba609b9901bbsalomon } else { 317cd523ebe2be30f268cdcec2d0b59eba609b9901bbsalomon header->fUseFragShaderOnly = false; 318cd523ebe2be30f268cdcec2d0b59eba609b9901bbsalomon } 319cd523ebe2be30f268cdcec2d0b59eba609b9901bbsalomon 320cd523ebe2be30f268cdcec2d0b59eba609b9901bbsalomon bool defaultToUniformInputs = GrGpu::IsPathRenderingDrawType(drawType) || 321cd523ebe2be30f268cdcec2d0b59eba609b9901bbsalomon GR_GL_NO_CONSTANT_ATTRIBUTES; 322c4dc0ad8e252a7e30d19b47d3d0d9f2c69faf854commit-bot@chromium.org 323170f90b4576f291879371ecd6ae4bc2b1d85c64aegdaniel if (!inputColorIsUsed) { 324842b086a3c876061e1279d47e6009629c9818b03egdaniel header->fColorInput = kAllOnes_ColorInput; 325cd523ebe2be30f268cdcec2d0b59eba609b9901bbsalomon } else if (defaultToUniformInputs && !optState.hasColorVertexAttribute()) { 3262db3ded335fdb6697623bece61cabc307a414770bsalomon@google.com header->fColorInput = kUniform_ColorInput; 3272db3ded335fdb6697623bece61cabc307a414770bsalomon@google.com } else { 3282db3ded335fdb6697623bece61cabc307a414770bsalomon@google.com header->fColorInput = kAttribute_ColorInput; 329cd523ebe2be30f268cdcec2d0b59eba609b9901bbsalomon SkASSERT(!header->fUseFragShaderOnly); 3302db3ded335fdb6697623bece61cabc307a414770bsalomon@google.com } 3312db3ded335fdb6697623bece61cabc307a414770bsalomon@google.com 332cd523ebe2be30f268cdcec2d0b59eba609b9901bbsalomon bool covIsSolidWhite = !optState.hasCoverageVertexAttribute() && 333cd523ebe2be30f268cdcec2d0b59eba609b9901bbsalomon 0xffffffff == optState.getCoverageColor(); 3342db3ded335fdb6697623bece61cabc307a414770bsalomon@google.com 335170f90b4576f291879371ecd6ae4bc2b1d85c64aegdaniel if (covIsSolidWhite || !inputCoverageIsUsed) { 336842b086a3c876061e1279d47e6009629c9818b03egdaniel header->fCoverageInput = kAllOnes_ColorInput; 337cd523ebe2be30f268cdcec2d0b59eba609b9901bbsalomon } else if (defaultToUniformInputs && !optState.hasCoverageVertexAttribute()) { 3382db3ded335fdb6697623bece61cabc307a414770bsalomon@google.com header->fCoverageInput = kUniform_ColorInput; 3392db3ded335fdb6697623bece61cabc307a414770bsalomon@google.com } else { 3402db3ded335fdb6697623bece61cabc307a414770bsalomon@google.com header->fCoverageInput = kAttribute_ColorInput; 341cd523ebe2be30f268cdcec2d0b59eba609b9901bbsalomon SkASSERT(!header->fUseFragShaderOnly); 3422db3ded335fdb6697623bece61cabc307a414770bsalomon@google.com } 3432db3ded335fdb6697623bece61cabc307a414770bsalomon@google.com 344a7dc0a83f0b59424a61e01bf3435cd7957e84e35egdaniel if (optState.readsDst()) { 34549f085dddff10473b6ebf832a974288300224e60bsalomon SkASSERT(dstCopy || gpu->caps()->dstReadInShaderSupport()); 3466b0cf0273fdffbbdf69235b57b5b5a311e7f1ca6bsalomon@google.com const GrTexture* dstCopyTexture = NULL; 34749f085dddff10473b6ebf832a974288300224e60bsalomon if (dstCopy) { 3486b0cf0273fdffbbdf69235b57b5b5a311e7f1ca6bsalomon@google.com dstCopyTexture = dstCopy->texture(); 3496b0cf0273fdffbbdf69235b57b5b5a311e7f1ca6bsalomon@google.com } 35030ba436f04e61d4505fb854d5fc56079636e0788joshualitt header->fDstReadKey = GrGLFragmentShaderBuilder::KeyForDstRead(dstCopyTexture, 35130ba436f04e61d4505fb854d5fc56079636e0788joshualitt gpu->glCaps()); 352f6de475e5cbd143f348ff7738919e397b7fe7f57tfarina@chromium.org SkASSERT(0 != header->fDstReadKey); 353b515881446c303a50d9b2dd38b9163b4e5c625a2bsalomon@google.com } else { 3542db3ded335fdb6697623bece61cabc307a414770bsalomon@google.com header->fDstReadKey = 0; 355b515881446c303a50d9b2dd38b9163b4e5c625a2bsalomon@google.com } 356b515881446c303a50d9b2dd38b9163b4e5c625a2bsalomon@google.com 357a7dc0a83f0b59424a61e01bf3435cd7957e84e35egdaniel if (optState.readsFragPosition()) { 35830ba436f04e61d4505fb854d5fc56079636e0788joshualitt header->fFragPosKey = GrGLFragmentShaderBuilder::KeyForFragmentPosition( 359170f90b4576f291879371ecd6ae4bc2b1d85c64aegdaniel optState.getRenderTarget(), gpu->glCaps()); 36026e18b593ab65e4d92dfbce92579d8bc180d4c2cbsalomon@google.com } else { 3612db3ded335fdb6697623bece61cabc307a414770bsalomon@google.com header->fFragPosKey = 0; 36226e18b593ab65e4d92dfbce92579d8bc180d4c2cbsalomon@google.com } 36326e18b593ab65e4d92dfbce92579d8bc180d4c2cbsalomon@google.com 3642db3ded335fdb6697623bece61cabc307a414770bsalomon@google.com // Record attribute indices 365170f90b4576f291879371ecd6ae4bc2b1d85c64aegdaniel header->fPositionAttributeIndex = optState.positionAttributeIndex(); 366170f90b4576f291879371ecd6ae4bc2b1d85c64aegdaniel header->fLocalCoordAttributeIndex = optState.localCoordAttributeIndex(); 3672d816ad36e806e5b1cf3c447e547829bbbe74fd1skia.committer@gmail.com 3682db3ded335fdb6697623bece61cabc307a414770bsalomon@google.com // For constant color and coverage we need an attribute with an index beyond those already set 369170f90b4576f291879371ecd6ae4bc2b1d85c64aegdaniel int availableAttributeIndex = optState.getVertexAttribCount(); 370cd523ebe2be30f268cdcec2d0b59eba609b9901bbsalomon if (optState.hasColorVertexAttribute()) { 371170f90b4576f291879371ecd6ae4bc2b1d85c64aegdaniel header->fColorAttributeIndex = optState.colorVertexAttributeIndex(); 3722db3ded335fdb6697623bece61cabc307a414770bsalomon@google.com } else if (GrGLProgramDesc::kAttribute_ColorInput == header->fColorInput) { 373f6de475e5cbd143f348ff7738919e397b7fe7f57tfarina@chromium.org SkASSERT(availableAttributeIndex < GrDrawState::kMaxVertexAttribCnt); 3742db3ded335fdb6697623bece61cabc307a414770bsalomon@google.com header->fColorAttributeIndex = availableAttributeIndex; 3752db3ded335fdb6697623bece61cabc307a414770bsalomon@google.com availableAttributeIndex++; 3762db3ded335fdb6697623bece61cabc307a414770bsalomon@google.com } else { 3772db3ded335fdb6697623bece61cabc307a414770bsalomon@google.com header->fColorAttributeIndex = -1; 3782db3ded335fdb6697623bece61cabc307a414770bsalomon@google.com } 3792d816ad36e806e5b1cf3c447e547829bbbe74fd1skia.committer@gmail.com 380cd523ebe2be30f268cdcec2d0b59eba609b9901bbsalomon if (optState.hasCoverageVertexAttribute()) { 381170f90b4576f291879371ecd6ae4bc2b1d85c64aegdaniel header->fCoverageAttributeIndex = optState.coverageVertexAttributeIndex(); 3822db3ded335fdb6697623bece61cabc307a414770bsalomon@google.com } else if (GrGLProgramDesc::kAttribute_ColorInput == header->fCoverageInput) { 383f6de475e5cbd143f348ff7738919e397b7fe7f57tfarina@chromium.org SkASSERT(availableAttributeIndex < GrDrawState::kMaxVertexAttribCnt); 3842db3ded335fdb6697623bece61cabc307a414770bsalomon@google.com header->fCoverageAttributeIndex = availableAttributeIndex; 3852db3ded335fdb6697623bece61cabc307a414770bsalomon@google.com } else { 3862db3ded335fdb6697623bece61cabc307a414770bsalomon@google.com header->fCoverageAttributeIndex = -1; 387798c8c4fe61f2172ae52cb626843a64069e18882bsalomon@google.com } 388798c8c4fe61f2172ae52cb626843a64069e18882bsalomon@google.com 389c06482494d2be6481a3666a66254b6c66890f994egdaniel header->fPrimaryOutputType = optState.getPrimaryOutputType(); 390c06482494d2be6481a3666a66254b6c66890f994egdaniel header->fSecondaryOutputType = optState.getSecondaryOutputType(); 391bd769d0f1c8cf6ccbb2738dfad1624a4c828e4ebjoshualitt 392170f90b4576f291879371ecd6ae4bc2b1d85c64aegdaniel for (int s = 0; s < optState.numColorStages(); ++s) { 393170f90b4576f291879371ecd6ae4bc2b1d85c64aegdaniel colorStages->push_back(&optState.getColorStage(s)); 394ee6206572b42fec11f83ad0c1e6d435903640518egdaniel } 395170f90b4576f291879371ecd6ae4bc2b1d85c64aegdaniel for (int s = 0; s < optState.numCoverageStages(); ++s) { 396c06482494d2be6481a3666a66254b6c66890f994egdaniel coverageStages->push_back(&optState.getCoverageStage(s)); 397c7bf2963f00a29bd28e5e2a446da79f93c1d9383jvanverth@google.com } 398170f90b4576f291879371ecd6ae4bc2b1d85c64aegdaniel 399a34995e18b1f0a7d8c9f23451718bb30ff0105b0commit-bot@chromium.org header->fColorEffectCnt = colorStages->count(); 400a34995e18b1f0a7d8c9f23451718bb30ff0105b0commit-bot@chromium.org header->fCoverageEffectCnt = coverageStages->count(); 401c7bf2963f00a29bd28e5e2a446da79f93c1d9383jvanverth@google.com 402848faf00ec33d39ab3e31e9a11d805cae6ac6562bsalomon desc->finalize(); 403848faf00ec33d39ab3e31e9a11d805cae6ac6562bsalomon return true; 404848faf00ec33d39ab3e31e9a11d805cae6ac6562bsalomon} 405848faf00ec33d39ab3e31e9a11d805cae6ac6562bsalomon 406848faf00ec33d39ab3e31e9a11d805cae6ac6562bsalomonvoid GrGLProgramDesc::finalize() { 407848faf00ec33d39ab3e31e9a11d805cae6ac6562bsalomon int keyLength = fKey.count(); 408848faf00ec33d39ab3e31e9a11d805cae6ac6562bsalomon SkASSERT(0 == (keyLength % 4)); 409848faf00ec33d39ab3e31e9a11d805cae6ac6562bsalomon *this->atOffset<uint32_t, kLengthOffset>() = SkToU32(keyLength); 410848faf00ec33d39ab3e31e9a11d805cae6ac6562bsalomon 411848faf00ec33d39ab3e31e9a11d805cae6ac6562bsalomon uint32_t* checksum = this->atOffset<uint32_t, kChecksumOffset>(); 412848faf00ec33d39ab3e31e9a11d805cae6ac6562bsalomon *checksum = 0; 413848faf00ec33d39ab3e31e9a11d805cae6ac6562bsalomon *checksum = SkChecksum::Compute(reinterpret_cast<uint32_t*>(fKey.begin()), keyLength); 4142db3ded335fdb6697623bece61cabc307a414770bsalomon@google.com} 4152db3ded335fdb6697623bece61cabc307a414770bsalomon@google.com 4162db3ded335fdb6697623bece61cabc307a414770bsalomon@google.comGrGLProgramDesc& GrGLProgramDesc::operator= (const GrGLProgramDesc& other) { 417848faf00ec33d39ab3e31e9a11d805cae6ac6562bsalomon size_t keyLength = other.keyLength(); 418848faf00ec33d39ab3e31e9a11d805cae6ac6562bsalomon fKey.reset(keyLength); 419848faf00ec33d39ab3e31e9a11d805cae6ac6562bsalomon memcpy(fKey.begin(), other.fKey.begin(), keyLength); 4202db3ded335fdb6697623bece61cabc307a414770bsalomon@google.com return *this; 421798c8c4fe61f2172ae52cb626843a64069e18882bsalomon@google.com} 422