| Index: src/gpu/gl/GrGLProgramDesc.cpp
|
| diff --git a/src/gpu/gl/GrGLProgramDesc.cpp b/src/gpu/gl/GrGLProgramDesc.cpp
|
| index b8740912643012d2bbef2008774bc2b8fc7e6874..c6560be2b257e91991d1dffd106a7a2fdcd46f38 100644
|
| --- a/src/gpu/gl/GrGLProgramDesc.cpp
|
| +++ b/src/gpu/gl/GrGLProgramDesc.cpp
|
| @@ -14,6 +14,133 @@
|
|
|
| #include "SkChecksum.h"
|
|
|
| +/**
|
| + * The key for an individual coord transform is made up of a matrix type and a bit that
|
| + * indicates the source of the input coords.
|
| + */
|
| +enum {
|
| + kMatrixTypeKeyBits = 1,
|
| + kMatrixTypeKeyMask = (1 << kMatrixTypeKeyBits) - 1,
|
| + kPositionCoords_Flag = (1 << kMatrixTypeKeyBits),
|
| + kTransformKeyBits = kMatrixTypeKeyBits + 1,
|
| +};
|
| +
|
| +/**
|
| + * We specialize the vertex code for each of these matrix types.
|
| + */
|
| +enum MatrixType {
|
| + kNoPersp_MatrixType = 0,
|
| + kGeneral_MatrixType = 1,
|
| +};
|
| +
|
| +/**
|
| + * Do we need to either map r,g,b->a or a->r. configComponentMask indicates which channels are
|
| + * present in the texture's config. swizzleComponentMask indicates the channels present in the
|
| + * shader swizzle.
|
| + */
|
| +static bool swizzle_requires_alpha_remapping(const GrGLCaps& caps,
|
| + uint32_t configComponentMask,
|
| + uint32_t swizzleComponentMask) {
|
| + if (caps.textureSwizzleSupport()) {
|
| + // Any remapping is handled using texture swizzling not shader modifications.
|
| + return false;
|
| + }
|
| + // check if the texture is alpha-only
|
| + if (kA_GrColorComponentFlag == configComponentMask) {
|
| + if (caps.textureRedSupport() && (kA_GrColorComponentFlag & swizzleComponentMask)) {
|
| + // we must map the swizzle 'a's to 'r'.
|
| + return true;
|
| + }
|
| + if (kRGB_GrColorComponentFlags & swizzleComponentMask) {
|
| + // The 'r', 'g', and/or 'b's must be mapped to 'a' according to our semantics that
|
| + // alpha-only textures smear alpha across all four channels when read.
|
| + return true;
|
| + }
|
| + }
|
| + return false;
|
| +}
|
| +
|
| +static uint32_t gen_attrib_key(const GrEffect* effect) {
|
| + uint32_t key = 0;
|
| +
|
| + const GrEffect::VertexAttribArray& vars = effect->getVertexAttribs();
|
| + int numAttributes = vars.count();
|
| + SkASSERT(numAttributes <= 2);
|
| + for (int a = 0; a < numAttributes; ++a) {
|
| + uint32_t value = 1 << a;
|
| + key |= value;
|
| + }
|
| + return key;
|
| +}
|
| +
|
| +static uint32_t gen_transform_key(const GrEffectStage& effectStage,
|
| + bool useExplicitLocalCoords) {
|
| + uint32_t totalKey = 0;
|
| + int numTransforms = effectStage.getEffect()->numTransforms();
|
| + for (int t = 0; t < numTransforms; ++t) {
|
| + uint32_t key = 0;
|
| + if (effectStage.isPerspectiveCoordTransform(t, useExplicitLocalCoords)) {
|
| + key |= kGeneral_MatrixType;
|
| + } else {
|
| + key |= kNoPersp_MatrixType;
|
| + }
|
| +
|
| + const GrCoordTransform& coordTransform = effectStage.getEffect()->coordTransform(t);
|
| + if (kLocal_GrCoordSet != coordTransform.sourceCoords() && useExplicitLocalCoords) {
|
| + key |= kPositionCoords_Flag;
|
| + }
|
| + key <<= kTransformKeyBits * t;
|
| + SkASSERT(0 == (totalKey & key)); // keys for each transform ought not to overlap
|
| + totalKey |= key;
|
| + }
|
| + return totalKey;
|
| +}
|
| +
|
| +static uint32_t gen_texture_key(const GrEffect* effect, const GrGLCaps& caps) {
|
| + uint32_t key = 0;
|
| + int numTextures = effect->numTextures();
|
| + for (int t = 0; t < numTextures; ++t) {
|
| + const GrTextureAccess& access = effect->textureAccess(t);
|
| + uint32_t configComponentMask = GrPixelConfigComponentMask(access.getTexture()->config());
|
| + if (swizzle_requires_alpha_remapping(caps, configComponentMask, access.swizzleMask())) {
|
| + key |= 1 << t;
|
| + }
|
| + }
|
| + return key;
|
| +}
|
| +
|
| +/**
|
| + * A function which emits a meta key into the key builder. This is required because shader code may
|
| + * be dependent on properties of the effect that the effect itself doesn't use
|
| + * in its key (e.g. the pixel format of textures used). So we create a meta-key for
|
| + * every effect using this function. It is also responsible for inserting the effect's class ID
|
| + * which must be different for every GrEffect subclass. It can fail if an effect uses too many
|
| + * textures, attributes, etc for the space allotted in the meta-key.
|
| + */
|
| +
|
| +static bool gen_effect_meta_key(const GrEffectStage& effectStage,
|
| + bool useExplicitLocalCoords,
|
| + const GrGLCaps& caps,
|
| + GrEffectKeyBuilder* b) {
|
| +
|
| + uint32_t textureKey = gen_texture_key(effectStage.getEffect(), caps);
|
| + uint32_t transformKey = gen_transform_key(effectStage,useExplicitLocalCoords);
|
| + uint32_t attribKey = gen_attrib_key(effectStage.getEffect());
|
| + uint32_t classID = effectStage.getEffect()->getFactory().effectClassID();
|
| +
|
| + // Currently we allow 16 bits for each of the above portions of the meta-key. Fail if they
|
| + // don't fit.
|
| + static const uint32_t kMetaKeyInvalidMask = ~((uint32_t) SK_MaxU16);
|
| + if ((textureKey | transformKey | attribKey | classID) & kMetaKeyInvalidMask) {
|
| + return false;
|
| + }
|
| +
|
| + uint32_t* key = b->add32n(2);
|
| + key[0] = (textureKey << 16 | transformKey);
|
| + key[1] = (classID << 16 | attribKey);
|
| + return true;
|
| +}
|
| +
|
| bool GrGLProgramDesc::GetEffectKey(const GrEffectStage& stage, const GrGLCaps& caps,
|
| bool useExplicitLocalCoords, GrEffectKeyBuilder* b,
|
| uint16_t* effectKeySize) {
|
| @@ -26,10 +153,7 @@ bool GrGLProgramDesc::GetEffectKey(const GrEffectStage& stage, const GrGLCaps& c
|
| return false;
|
| }
|
| *effectKeySize = SkToU16(size);
|
| - if (!GrGLProgramEffects::GenEffectMetaKey(stage,
|
| - useExplicitLocalCoords,
|
| - caps,
|
| - b)) {
|
| + if (!gen_effect_meta_key(stage, useExplicitLocalCoords, caps, b)) {
|
| return false;
|
| }
|
| return true;
|
|
|