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