This moves us towards variable length effect keys. The overall program key now allows...
authorbsalomon <bsalomon@google.com>
Fri, 11 Jul 2014 17:01:02 +0000 (10:01 -0700)
committerCommit bot <commit-bot@chromium.org>
Fri, 11 Jul 2014 17:01:02 +0000 (10:01 -0700)
R=robertphillips@google.com, jvanverth@google.com, egdaniel@google.com

Author: bsalomon@google.com

Review URL: https://codereview.chromium.org/356513003

48 files changed:
include/gpu/GrBackendEffectFactory.h
include/gpu/GrTBackendEffectFactory.h
src/core/SkXfermode.cpp
src/effects/SkAlphaThresholdFilter.cpp
src/effects/SkArithmeticMode.cpp
src/effects/SkBlurMaskFilter.cpp
src/effects/SkColorFilters.cpp
src/effects/SkColorMatrixFilter.cpp
src/effects/SkDisplacementMapEffect.cpp
src/effects/SkLightingImageFilter.cpp
src/effects/SkLumaColorFilter.cpp
src/effects/SkMagnifierImageFilter.cpp
src/effects/SkMatrixConvolutionImageFilter.cpp
src/effects/SkMorphologyImageFilter.cpp
src/effects/SkPerlinNoiseShader.cpp
src/effects/SkTableColorFilter.cpp
src/effects/gradients/SkGradientShader.cpp
src/effects/gradients/SkLinearGradient.cpp
src/effects/gradients/SkRadialGradient.cpp
src/effects/gradients/SkSweepGradient.cpp
src/effects/gradients/SkTwoPointConicalGradient_gpu.cpp
src/effects/gradients/SkTwoPointRadialGradient.cpp
src/gpu/GrAAConvexPathRenderer.cpp
src/gpu/GrAARectRenderer.cpp
src/gpu/GrOvalRenderer.cpp
src/gpu/effects/GrBezierEffect.cpp
src/gpu/effects/GrBicubicEffect.cpp
src/gpu/effects/GrConfigConversionEffect.cpp
src/gpu/effects/GrConvexPolyEffect.cpp
src/gpu/effects/GrConvolutionEffect.cpp
src/gpu/effects/GrCustomCoordsTextureEffect.cpp
src/gpu/effects/GrDashingEffect.cpp
src/gpu/effects/GrDistanceFieldTextureEffect.cpp
src/gpu/effects/GrDitherEffect.cpp
src/gpu/effects/GrOvalEffect.cpp
src/gpu/effects/GrRRectEffect.cpp
src/gpu/effects/GrSimpleTextureEffect.cpp
src/gpu/effects/GrTextureDomain.cpp
src/gpu/effects/GrYUVtoRGBEffect.cpp
src/gpu/gl/GrGLEffect.h
src/gpu/gl/GrGLProgramDesc.cpp
src/gpu/gl/GrGLProgramDesc.h
src/gpu/gl/GrGLProgramEffects.cpp
src/gpu/gl/GrGLProgramEffects.h
src/gpu/gl/GrGLShaderBuilder.cpp
src/gpu/gl/GrGLShaderBuilder.h
src/gpu/gl/GrGpuGL_program.cpp
tests/GLProgramsTest.cpp

index af8d5c7..32f14f2 100644 (file)
@@ -12,6 +12,7 @@
 #include "SkTemplates.h"
 #include "SkThread.h"
 #include "SkTypes.h"
+#include "SkTArray.h"
 
 /** Given a GrEffect of a particular type, creates the corresponding graphics-backend-specific
     effect object. Also tracks equivalence of shaders generated via a key. Each factory instance
@@ -27,23 +28,32 @@ class GrGLEffect;
 class GrGLCaps;
 class GrDrawEffect;
 
+/**
+ * Used by effects to build their keys. It incorpates each per-effect key into a larger shader key.
+ */
+class GrEffectKeyBuilder {
+public:
+    GrEffectKeyBuilder(SkTArray<unsigned char, true>* data) : fData(data), fCount(0) {
+        SkASSERT(0 == fData->count() % sizeof(uint32_t));
+    }
+
+    void add32(uint32_t v) {
+        ++fCount;
+        fData->push_back_n(4, reinterpret_cast<uint8_t*>(&v));
+    }
+
+    size_t size() const { return sizeof(uint32_t) * fCount; }
+
+private:
+    SkTArray<uint8_t, true>* fData; // unowned ptr to the larger key.
+    int fCount;                     // number of uint32_ts added to fData by the effect.
+};
+
 class GrBackendEffectFactory : SkNoncopyable {
 public:
     typedef uint32_t EffectKey;
-    enum {
-        kNoEffectKey = 0,
-        kEffectKeyBits = 10,
-        /**
-         * The framework automatically includes coord transforms and texture accesses in their
-         * effect's EffectKey, so effects don't need to account for them in GenKey().
-         */
-        kTextureKeyBits = 4,
-        kTransformKeyBits = 6,
-        kAttribKeyBits = 6,
-        kClassIDBits = 6
-    };
 
-    virtual EffectKey glEffectKey(const GrDrawEffect&, const GrGLCaps&) const = 0;
+    virtual bool getGLEffectKey(const GrDrawEffect&, const GrGLCaps&, GrEffectKeyBuilder*) const = 0;
     virtual GrGLEffect* createGLInstance(const GrDrawEffect&) const = 0;
 
     bool operator ==(const GrBackendEffectFactory& b) const {
@@ -55,10 +65,6 @@ public:
 
     virtual const char* name() const = 0;
 
-    static EffectKey GetTransformKey(EffectKey key) {
-        return key >> (kEffectKeyBits + kTextureKeyBits) & ((1U << kTransformKeyBits) - 1);
-    }
-
 protected:
     enum {
         kIllegalEffectClassID = 0,
@@ -69,18 +75,15 @@ protected:
     }
     virtual ~GrBackendEffectFactory() {}
 
-    static EffectKey GenID() {
-        SkDEBUGCODE(static const int32_t kClassIDBits = 8 * sizeof(EffectKey) -
-                           kTextureKeyBits - kEffectKeyBits - kAttribKeyBits);
+    static int32_t GenID() {
         // fCurrEffectClassID has been initialized to kIllegalEffectClassID. The
         // atomic inc returns the old value not the incremented value. So we add
         // 1 to the returned value.
         int32_t id = sk_atomic_inc(&fCurrEffectClassID) + 1;
-        SkASSERT(id < (1 << kClassIDBits));
-        return static_cast<EffectKey>(id);
+        return id;
     }
 
-    EffectKey fEffectClassID;
+    int32_t fEffectClassID;
 
 private:
     static int32_t fCurrEffectClassID;
index fd14b4f..cd4c0a4 100644 (file)
@@ -26,39 +26,30 @@ public:
      */
     virtual const char* name() const SK_OVERRIDE { return EffectClass::Name(); }
 
-    /** Returns a value that identifies the GLSL shader code generated by
-        a GrEffect. This enables caching of generated shaders. Part of the
-        id identifies the GrEffect subclass. The remainder is based
-        on the aspects of the GrEffect object's configuration that affect
-        GLSL code generation. */
-    virtual EffectKey glEffectKey(const GrDrawEffect& drawEffect,
-                                  const GrGLCaps& caps) const SK_OVERRIDE {
+    /** Generates an effect's key. This enables caching of generated shaders. Part of the
+        id identifies the GrEffect subclass. The remainder is based on the aspects of the
+        GrEffect object's configuration that affect GLSL code generation. If this fails
+        then program generation should be aborted. Failure occurs if the effect uses more
+        transforms, attributes, or textures than the key has space for. */
+    virtual bool getGLEffectKey(const GrDrawEffect& drawEffect,
+                                const GrGLCaps& caps,
+                                GrEffectKeyBuilder* b) const SK_OVERRIDE {
         SkASSERT(kIllegalEffectClassID != fEffectClassID);
         EffectKey effectKey = GLEffect::GenKey(drawEffect, caps);
         EffectKey textureKey = GrGLProgramEffects::GenTextureKey(drawEffect, caps);
         EffectKey transformKey = GrGLProgramEffects::GenTransformKey(drawEffect);
         EffectKey attribKey = GrGLProgramEffects::GenAttribKey(drawEffect);
-#ifdef SK_DEBUG
-        static const EffectKey kIllegalEffectKeyMask = (uint16_t) (~((1U << kEffectKeyBits) - 1));
-        SkASSERT(!(kIllegalEffectKeyMask & effectKey));
-
-        static const EffectKey kIllegalTextureKeyMask = (uint16_t) (~((1U << kTextureKeyBits) - 1));
-        SkASSERT(!(kIllegalTextureKeyMask & textureKey));
-
-        static const EffectKey kIllegalTransformKeyMask = (uint16_t) (~((1U << kTransformKeyBits) - 1));
-        SkASSERT(!(kIllegalTransformKeyMask & transformKey));
-
-        static const EffectKey kIllegalAttribKeyMask = (uint16_t) (~((1U << kAttribKeyBits) - 1));
-        SkASSERT(!(kIllegalAttribKeyMask & textureKey));
+        static const uint32_t kMetaKeyInvalidMask = ~((uint32_t) SK_MaxU16);
+        if ((textureKey | transformKey | attribKey | fEffectClassID) & kMetaKeyInvalidMask) {
+            return false;
+        }
 
-        static const EffectKey kIllegalClassIDMask = (uint16_t) (~((1U << kClassIDBits) - 1));
-        SkASSERT(!(kIllegalClassIDMask & fEffectClassID));
-#endif
-        return (fEffectClassID << (kEffectKeyBits+kTextureKeyBits+kTransformKeyBits+kAttribKeyBits)) |
-               (attribKey << (kEffectKeyBits+kTextureKeyBits+kTransformKeyBits)) |
-               (transformKey << (kEffectKeyBits+kTextureKeyBits)) |
-               (textureKey << kEffectKeyBits) |
-               (effectKey);
+        // effectKey must be first because it is what will be returned by
+        // GrGLProgramDesc::EffectKeyProvider and passed to the GrGLEffect as its key. 
+        b->add32(effectKey);
+        b->add32(textureKey << 16 | transformKey);
+        b->add32(fEffectClassID << 16 | attribKey);
+        return true;
     }
 
     /** Returns a new instance of the appropriate *GL* implementation class
index 4b15af0..d020857 100644 (file)
@@ -783,6 +783,7 @@ void SkXfermode::xferA8(SkAlpha* SK_RESTRICT dst,
 #include "GrEffectUnitTest.h"
 #include "GrTBackendEffectFactory.h"
 #include "gl/GrGLEffect.h"
+#include "gl/GrGLShaderBuilder.h"
 
 /**
  * GrEffect that implements the all the separable xfer modes that cannot be expressed as Coeffs.
index 23937cc..f8b8497 100644 (file)
@@ -48,6 +48,7 @@ SkImageFilter* SkAlphaThresholdFilter::Create(const SkRegion& region,
 #include "GrCoordTransform.h"
 #include "GrEffect.h"
 #include "gl/GrGLEffect.h"
+#include "gl/GrGLShaderBuilder.h"
 #include "GrTBackendEffectFactory.h"
 #include "GrTextureAccess.h"
 
index 0424a6e..6e01504 100644 (file)
@@ -15,6 +15,7 @@
 #include "GrContext.h"
 #include "GrCoordTransform.h"
 #include "gl/GrGLEffect.h"
+#include "gl/GrGLShaderBuilder.h"
 #include "GrTBackendEffectFactory.h"
 #endif
 
index e400663..4ab9944 100644 (file)
@@ -22,6 +22,7 @@
 #include "GrTexture.h"
 #include "GrEffect.h"
 #include "gl/GrGLEffect.h"
+#include "gl/GrGLShaderBuilder.h"
 #include "effects/GrSimpleTextureEffect.h"
 #include "GrTBackendEffectFactory.h"
 #include "SkGrPixelRef.h"
index 35b7825..0e2fd6c 100644 (file)
@@ -131,6 +131,7 @@ private:
 #include "GrEffectUnitTest.h"
 #include "GrTBackendEffectFactory.h"
 #include "gl/GrGLEffect.h"
+#include "gl/GrGLShaderBuilder.h"
 #include "SkGr.h"
 
 namespace {
index cf2e3b7..c24a2b7 100644 (file)
@@ -327,6 +327,7 @@ bool SkColorMatrixFilter::asColorMatrix(SkScalar matrix[20]) const {
 #include "GrEffect.h"
 #include "GrTBackendEffectFactory.h"
 #include "gl/GrGLEffect.h"
+#include "gl/GrGLShaderBuilder.h"
 
 class ColorMatrixEffect : public GrEffect {
 public:
index b270640..a6897ea 100644 (file)
@@ -14,6 +14,7 @@
 #include "GrContext.h"
 #include "GrCoordTransform.h"
 #include "gl/GrGLEffect.h"
+#include "gl/GrGLShaderBuilder.h"
 #include "GrTBackendEffectFactory.h"
 #endif
 
index c5b8fc6..682f2ba 100644 (file)
@@ -17,6 +17,7 @@
 #if SK_SUPPORT_GPU
 #include "effects/GrSingleTextureEffect.h"
 #include "gl/GrGLEffect.h"
+#include "gl/GrGLShaderBuilder.h"
 #include "GrEffect.h"
 #include "GrTBackendEffectFactory.h"
 
index 4c5e98a..7564307 100644 (file)
@@ -12,6 +12,7 @@
 
 #if SK_SUPPORT_GPU
 #include "gl/GrGLEffect.h"
+#include "gl/GrGLShaderBuilder.h"
 #include "GrContext.h"
 #include "GrTBackendEffectFactory.h"
 #endif
index 7601603..4a730c2 100644 (file)
@@ -16,6 +16,7 @@
 #if SK_SUPPORT_GPU
 #include "effects/GrSingleTextureEffect.h"
 #include "gl/GrGLEffect.h"
+#include "gl/GrGLShaderBuilder.h"
 #include "gl/GrGLSL.h"
 #include "gl/GrGLTexture.h"
 #include "GrTBackendEffectFactory.h"
index 5baf36b..fa7d205 100644 (file)
@@ -15,6 +15,7 @@
 
 #if SK_SUPPORT_GPU
 #include "gl/GrGLEffect.h"
+#include "gl/GrGLShaderBuilder.h"
 #include "effects/GrSingleTextureEffect.h"
 #include "GrTBackendEffectFactory.h"
 #include "GrTexture.h"
index 53180fa..10c6fe5 100644 (file)
@@ -17,6 +17,7 @@
 #include "GrTexture.h"
 #include "GrTBackendEffectFactory.h"
 #include "gl/GrGLEffect.h"
+#include "gl/GrGLShaderBuilder.h"
 #include "effects/Gr1DKernelEffect.h"
 #endif
 
index f57fcf3..e481162 100644 (file)
@@ -18,6 +18,7 @@
 #include "GrContext.h"
 #include "GrCoordTransform.h"
 #include "gl/GrGLEffect.h"
+#include "gl/GrGLShaderBuilder.h"
 #include "GrTBackendEffectFactory.h"
 #include "SkGr.h"
 #endif
index 09024d3..4cf0987 100644 (file)
@@ -230,6 +230,7 @@ bool SkTable_ColorFilter::asComponentTable(SkBitmap* table) const {
 #include "GrEffect.h"
 #include "GrTBackendEffectFactory.h"
 #include "gl/GrGLEffect.h"
+#include "gl/GrGLShaderBuilder.h"
 #include "SkGr.h"
 
 class GLColorTableEffect;
index fe720b8..fb8a7e5 100644 (file)
@@ -852,6 +852,7 @@ SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_END
 
 #include "effects/GrTextureStripAtlas.h"
 #include "GrTBackendEffectFactory.h"
+#include "gl/GrGLShaderBuilder.h"
 #include "SkGr.h"
 
 GrGLGradientEffect::GrGLGradientEffect(const GrBackendEffectFactory& factory)
index 113877c..332c9b4 100644 (file)
@@ -446,6 +446,7 @@ void SkLinearGradient::LinearGradientContext::shadeSpan16(int x, int y,
 #if SK_SUPPORT_GPU
 
 #include "GrTBackendEffectFactory.h"
+#include "gl/GrGLShaderBuilder.h"
 #include "SkGr.h"
 
 /////////////////////////////////////////////////////////////////////
index 2267d8d..e3aaea3 100644 (file)
@@ -458,6 +458,7 @@ void SkRadialGradient::RadialGradientContext::shadeSpan(int x, int y,
 #if SK_SUPPORT_GPU
 
 #include "GrTBackendEffectFactory.h"
+#include "gl/GrGLShaderBuilder.h"
 #include "SkGr.h"
 
 class GrGLRadialGradient : public GrGLGradientEffect {
index 1ba0443..bb9d628 100644 (file)
@@ -174,6 +174,7 @@ void SkSweepGradient::SweepGradientContext::shadeSpan16(int x, int y, uint16_t*
 #if SK_SUPPORT_GPU
 
 #include "GrTBackendEffectFactory.h"
+#include "gl/GrGLShaderBuilder.h"
 #include "SkGr.h"
 
 class GrGLSweepGradient : public GrGLGradientEffect {
index 4d0aa0f..8beb6fb 100644 (file)
@@ -12,6 +12,7 @@
 
 #if SK_SUPPORT_GPU
 #include "GrTBackendEffectFactory.h"
+#include "gl/GrGLShaderBuilder.h"
 // For brevity
 typedef GrGLUniformManager::UniformHandle UniformHandle;
 
index 79c231d..a97cc0c 100644 (file)
@@ -383,6 +383,7 @@ void SkTwoPointRadialGradient::init() {
 #if SK_SUPPORT_GPU
 
 #include "GrTBackendEffectFactory.h"
+#include "gl/GrGLShaderBuilder.h"
 #include "SkGr.h"
 
 // For brevity
index 7765eb1..3116712 100644 (file)
@@ -19,6 +19,7 @@
 #include "SkTraceEvent.h"
 
 #include "gl/GrGLEffect.h"
+#include "gl/GrGLShaderBuilder.h"
 #include "gl/GrGLSL.h"
 #include "gl/GrGLVertexEffect.h"
 
index 48024a6..761c63f 100644 (file)
@@ -8,6 +8,7 @@
 #include "GrAARectRenderer.h"
 #include "GrGpu.h"
 #include "gl/GrGLEffect.h"
+#include "gl/GrGLShaderBuilder.h"
 #include "gl/GrGLVertexEffect.h"
 #include "GrTBackendEffectFactory.h"
 #include "SkColorPriv.h"
index fe4c03e..648bc14 100644 (file)
@@ -10,6 +10,7 @@
 #include "GrEffect.h"
 #include "gl/GrGLEffect.h"
 #include "gl/GrGLSL.h"
+#include "gl/GrGLShaderBuilder.h"
 #include "gl/GrGLVertexEffect.h"
 #include "GrTBackendEffectFactory.h"
 
index 0736b5a..d710c64 100644 (file)
@@ -8,6 +8,7 @@
 #include "GrBezierEffect.h"
 
 #include "gl/GrGLEffect.h"
+#include "gl/GrGLShaderBuilder.h"
 #include "gl/GrGLSL.h"
 #include "gl/GrGLVertexEffect.h"
 #include "GrTBackendEffectFactory.h"
index 132d2f4..118efaf 100644 (file)
@@ -1,5 +1,14 @@
+/*
+ * Copyright 2014 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
 #include "GrBicubicEffect.h"
 
+#include "gl/GrGLShaderBuilder.h"
+
 #define DS(x) SkDoubleToScalar(x)
 
 const SkScalar GrBicubicEffect::gMitchellCoefficients[16] = {
index ff18ef2..c421867 100644 (file)
@@ -10,6 +10,7 @@
 #include "GrTBackendEffectFactory.h"
 #include "GrSimpleTextureEffect.h"
 #include "gl/GrGLEffect.h"
+#include "gl/GrGLShaderBuilder.h"
 #include "SkMatrix.h"
 
 class GrGLConfigConversionEffect : public GrGLEffect {
index 49521ca..dd104bd 100644 (file)
@@ -8,6 +8,7 @@
 #include "GrConvexPolyEffect.h"
 
 #include "gl/GrGLEffect.h"
+#include "gl/GrGLShaderBuilder.h"
 #include "gl/GrGLSL.h"
 #include "GrTBackendEffectFactory.h"
 
index 14ba4d7..43ef7e7 100644 (file)
@@ -7,6 +7,7 @@
 
 #include "GrConvolutionEffect.h"
 #include "gl/GrGLEffect.h"
+#include "gl/GrGLShaderBuilder.h"
 #include "gl/GrGLSL.h"
 #include "gl/GrGLTexture.h"
 #include "GrTBackendEffectFactory.h"
index 62326b9..feb9d62 100644 (file)
@@ -7,6 +7,7 @@
 
 #include "GrCustomCoordsTextureEffect.h"
 #include "gl/GrGLEffect.h"
+#include "gl/GrGLShaderBuilder.h"
 #include "gl/GrGLSL.h"
 #include "gl/GrGLTexture.h"
 #include "gl/GrGLVertexEffect.h"
index 723f59d..488d1ba 100644 (file)
@@ -12,6 +12,7 @@
 #include "effects/GrVertexEffect.h"
 #include "gl/GrGLEffect.h"
 #include "gl/GrGLVertexEffect.h"
+#include "gl/GrGLShaderBuilder.h"
 #include "gl/GrGLSL.h"
 #include "GrContext.h"
 #include "GrCoordTransform.h"
index 5ae0129..f69980d 100755 (executable)
@@ -7,6 +7,7 @@
 
 #include "GrDistanceFieldTextureEffect.h"
 #include "gl/GrGLEffect.h"
+#include "gl/GrGLShaderBuilder.h"
 #include "gl/GrGLSL.h"
 #include "gl/GrGLTexture.h"
 #include "gl/GrGLVertexEffect.h"
index fc37d1a..37354c6 100644 (file)
@@ -8,6 +8,7 @@
 #include "GrDitherEffect.h"
 
 #include "gl/GrGLEffect.h"
+#include "gl/GrGLShaderBuilder.h"
 #include "gl/GrGLSL.h"
 #include "GrTBackendEffectFactory.h"
 
index ddda4b9..a80b08d 100644 (file)
@@ -8,6 +8,7 @@
 #include "GrOvalEffect.h"
 
 #include "gl/GrGLEffect.h"
+#include "gl/GrGLShaderBuilder.h"
 #include "gl/GrGLSL.h"
 #include "GrTBackendEffectFactory.h"
 
index d39ab0d..efad436 100644 (file)
@@ -8,6 +8,7 @@
 #include "GrRRectEffect.h"
 
 #include "gl/GrGLEffect.h"
+#include "gl/GrGLShaderBuilder.h"
 #include "gl/GrGLSL.h"
 #include "GrConvexPolyEffect.h"
 #include "GrOvalEffect.h"
index b5ad386..c93abf9 100644 (file)
@@ -7,6 +7,7 @@
 
 #include "GrSimpleTextureEffect.h"
 #include "gl/GrGLEffect.h"
+#include "gl/GrGLShaderBuilder.h"
 #include "gl/GrGLSL.h"
 #include "gl/GrGLTexture.h"
 #include "GrTBackendEffectFactory.h"
index f12fec5..108ec78 100644 (file)
@@ -9,6 +9,7 @@
 #include "GrSimpleTextureEffect.h"
 #include "GrTBackendEffectFactory.h"
 #include "gl/GrGLEffect.h"
+#include "gl/GrGLShaderBuilder.h"
 #include "SkFloatingPoint.h"
 
 
index 01ff6d6..76b8581 100644 (file)
@@ -10,6 +10,7 @@
 #include "GrCoordTransform.h"
 #include "GrEffect.h"
 #include "gl/GrGLEffect.h"
+#include "gl/GrGLShaderBuilder.h"
 #include "GrTBackendEffectFactory.h"
 
 namespace {
index 1cc3df2..0727372 100644 (file)
 
 #include "GrBackendEffectFactory.h"
 #include "GrGLProgramEffects.h"
-#include "GrGLShaderBuilder.h"
 #include "GrGLShaderVar.h"
 #include "GrGLSL.h"
 
+class GrGLShaderBuilder;
+
 /** @file
     This file contains specializations for OpenGL of the shader stages declared in
     include/gpu/GrEffect.h. Objects of type GrGLEffect are responsible for emitting the
@@ -43,12 +44,6 @@ public:
     typedef GrGLProgramEffects::TextureSampler TextureSampler;
     typedef GrGLProgramEffects::TextureSamplerArray TextureSamplerArray;
 
-    enum {
-        kNoEffectKey = GrBackendEffectFactory::kNoEffectKey,
-        // the number of bits in EffectKey available to GenKey
-        kEffectKeyBits = GrBackendEffectFactory::kEffectKeyBits,
-    };
-
     GrGLEffect(const GrBackendEffectFactory& factory)
         : fFactory(factory)
         , fIsVertexEffect(false) {
index ecd48e0..2c260cd 100644 (file)
 
 #include "SkChecksum.h"
 
-namespace {
-inline GrGLEffect::EffectKey get_key_and_update_stats(const GrEffectStage& stage,
-                                                      const GrGLCaps& caps,
-                                                      bool useExplicitLocalCoords,
-                                                      bool* setTrueIfReadsDst,
-                                                      bool* setTrueIfReadsPos,
-                                                      bool* setTrueIfHasVertexCode) {
-    const GrEffect* effect = stage.getEffect();
-    const GrBackendEffectFactory& factory = effect->getFactory();
+static inline bool get_key_and_update_stats(const GrEffectStage& stage,
+                                            const GrGLCaps& caps,
+                                            bool useExplicitLocalCoords,
+                                            GrEffectKeyBuilder* b, 
+                                            bool* setTrueIfReadsDst,
+                                            bool* setTrueIfReadsPos,
+                                            bool* setTrueIfHasVertexCode) {
+    const GrBackendEffectFactory& factory = stage.getEffect()->getFactory();
     GrDrawEffect drawEffect(stage, useExplicitLocalCoords);
-    if (effect->willReadDstColor()) {
+    if (stage.getEffect()->willReadDstColor()) {
         *setTrueIfReadsDst = true;
     }
-    if (effect->willReadFragmentPosition()) {
+    if (stage.getEffect()->willReadFragmentPosition()) {
         *setTrueIfReadsPos = true;
     }
-    if (effect->hasVertexCode()) {
+    if (stage.getEffect()->hasVertexCode()) {
         *setTrueIfHasVertexCode = true;
     }
-    return factory.glEffectKey(drawEffect, caps);
+    return factory.getGLEffectKey(drawEffect, caps, b);
 }
-}
-void GrGLProgramDesc::Build(const GrDrawState& drawState,
+
+bool GrGLProgramDesc::Build(const GrDrawState& drawState,
                             GrGpu::DrawType drawType,
                             GrDrawState::BlendOptFlags blendOpts,
                             GrBlendCoeff srcCoeff,
@@ -94,45 +93,68 @@ void GrGLProgramDesc::Build(const GrDrawState& drawState,
                              (!requiresColorAttrib && 0xffffffff == drawState.getColor()) ||
                              (!inputColorIsUsed);
 
-    int numEffects = (skipColor ? 0 : (drawState.numColorStages() - firstEffectiveColorStage)) +
-                     (skipCoverage ? 0 : (drawState.numCoverageStages() - firstEffectiveCoverageStage));
-
-    size_t newKeyLength = KeyLength(numEffects);
-    bool allocChanged;
-    desc->fKey.reset(newKeyLength, SkAutoMalloc::kAlloc_OnShrink, &allocChanged);
-    if (allocChanged || !desc->fInitialized) {
-        // make sure any padding in the header is zero if we we haven't used this allocation before.
-        memset(desc->header(), 0, kHeaderSize);
-    }
-    // write the key length
-    *desc->atOffset<uint32_t, kLengthOffset>() = SkToU32(newKeyLength);
-
-    KeyHeader* header = desc->header();
-    EffectKey* effectKeys = desc->effectKeys();
-
-    int currEffectKey = 0;
     bool readsDst = false;
     bool readFragPosition = false;
     // We use vertexshader-less shader programs only when drawing paths.
     bool hasVertexCode = !(GrGpu::kDrawPath_DrawType == drawType ||
                            GrGpu::kDrawPaths_DrawType == drawType);
+    int numStages = 0;
+    if (!skipColor) {
+        numStages += drawState.numColorStages() - firstEffectiveColorStage;
+    }
+    if (!skipCoverage) {
+        numStages += drawState.numCoverageStages() - firstEffectiveCoverageStage;
+    }
+    GR_STATIC_ASSERT(0 == kEffectKeyLengthsOffset % sizeof(uint32_t));
+    // Make room for everything up to and including the array of offsets to effect keys.
+    desc->fKey.reset();
+    desc->fKey.push_back_n(kEffectKeyLengthsOffset + sizeof(uint32_t) * numStages);
 
+    size_t offset = desc->fKey.count();
+    int offsetIndex = 0;
+
+    bool effectKeySuccess = true;
     if (!skipColor) {
         for (int s = firstEffectiveColorStage; s < drawState.numColorStages(); ++s) {
-            effectKeys[currEffectKey++] =
-                get_key_and_update_stats(drawState.getColorStage(s), gpu->glCaps(),
-                                         requiresLocalCoordAttrib, &readsDst, &readFragPosition,
-                                         &hasVertexCode);
+            uint32_t* offsetLocation = reinterpret_cast<uint32_t*>(desc->fKey.begin() +
+                                                                   kEffectKeyLengthsOffset +
+                                                                   offsetIndex * sizeof(uint32_t));
+            *offsetLocation = offset;
+            ++offsetIndex;
+
+            GrEffectKeyBuilder b(&desc->fKey);
+            effectKeySuccess |= get_key_and_update_stats(drawState.getColorStage(s), gpu->glCaps(),
+                                                         requiresLocalCoordAttrib, &b, &readsDst,
+                                                         &readFragPosition, &hasVertexCode);
+            offset += b.size();
         }
     }
     if (!skipCoverage) {
         for (int s = firstEffectiveCoverageStage; s < drawState.numCoverageStages(); ++s) {
-            effectKeys[currEffectKey++] =
-                get_key_and_update_stats(drawState.getCoverageStage(s), gpu->glCaps(),
-                                         requiresLocalCoordAttrib, &readsDst, &readFragPosition,
-                                         &hasVertexCode);
+            uint32_t* offsetLocation = reinterpret_cast<uint32_t*>(desc->fKey.begin() +
+                                                                   kEffectKeyLengthsOffset +
+                                                                   offsetIndex * sizeof(uint32_t));
+            *offsetLocation = offset;
+            ++offsetIndex;
+            GrEffectKeyBuilder b(&desc->fKey);
+            effectKeySuccess |= get_key_and_update_stats(drawState.getCoverageStage(s),
+                                                         gpu->glCaps(), requiresLocalCoordAttrib,
+                                                         &b, &readsDst, &readFragPosition,
+                                                         &hasVertexCode);
+            offset += b.size();
         }
     }
+    if (!effectKeySuccess) {
+        desc->fKey.reset();
+        return false;
+    }
+
+    KeyHeader* header = desc->header();
+    // make sure any padding in the header is zeroed.
+    memset(desc->header(), 0, kHeaderSize);
+
+    // Because header is a pointer into the dynamic array, we can't push any new data into the key
+    // below here.
 
     header->fHasVertexCode = hasVertexCode || requiresLocalCoordAttrib;
     header->fEmitsPointSize = GrGpu::kDrawPoints_DrawType == drawType;
@@ -268,18 +290,23 @@ void GrGLProgramDesc::Build(const GrDrawState& drawState,
     header->fColorEffectCnt = colorStages->count();
     header->fCoverageEffectCnt = coverageStages->count();
 
-    *desc->checksum() = 0;
-    *desc->checksum() = SkChecksum::Compute(reinterpret_cast<uint32_t*>(desc->fKey.get()),
-                                            newKeyLength);
-    desc->fInitialized = true;
+    desc->finalize();
+    return true;
+}
+
+void GrGLProgramDesc::finalize() {
+    int keyLength = fKey.count();
+    SkASSERT(0 == (keyLength % 4));
+    *this->atOffset<uint32_t, kLengthOffset>() = SkToU32(keyLength);
+
+    uint32_t* checksum = this->atOffset<uint32_t, kChecksumOffset>();
+    *checksum = 0;
+    *checksum = SkChecksum::Compute(reinterpret_cast<uint32_t*>(fKey.begin()), keyLength);
 }
 
 GrGLProgramDesc& GrGLProgramDesc::operator= (const GrGLProgramDesc& other) {
-    fInitialized = other.fInitialized;
-    if (fInitialized) {
-        size_t keyLength = other.keyLength();
-        fKey.reset(keyLength);
-        memcpy(fKey.get(), other.fKey.get(), keyLength);
-    }
+    size_t keyLength = other.keyLength();
+    fKey.reset(keyLength);
+    memcpy(fKey.begin(), other.fKey.begin(), keyLength);
     return *this;
 }
index 9165f4e..d7652f4 100644 (file)
@@ -10,7 +10,6 @@
 
 #include "GrGLEffect.h"
 #include "GrDrawState.h"
-#include "GrGLShaderBuilder.h"
 #include "GrGpu.h"
 
 class GrGpuGL;
@@ -30,13 +29,12 @@ class GrGpuGL;
     to be API-neutral then so could this class. */
 class GrGLProgramDesc {
 public:
-    GrGLProgramDesc() : fInitialized(false) {}
+    GrGLProgramDesc() {}
     GrGLProgramDesc(const GrGLProgramDesc& desc) { *this = desc; }
 
     // Returns this as a uint32_t array to be used as a key in the program cache.
     const uint32_t* asKey() const {
-        SkASSERT(fInitialized);
-        return reinterpret_cast<const uint32_t*>(fKey.get());
+        return reinterpret_cast<const uint32_t*>(fKey.begin());
     }
 
     // Gets the number of bytes in asKey(). It will be a 4-byte aligned value. When comparing two
@@ -48,7 +46,7 @@ public:
     uint32_t getChecksum() const { return *this->atOffset<uint32_t, kChecksumOffset>(); }
 
     // For unit testing.
-    void setRandom(SkRandom*,
+    bool setRandom(SkRandom*,
                    const GrGpuGL* gpu,
                    const GrRenderTarget* dummyDstRenderTarget,
                    const GrTexture* dummyDstCopyTexture,
@@ -64,7 +62,7 @@ public:
      * not contain all stages from the draw state and coverage stages from the drawState may
      * be treated as color stages in the output.
      */
-    static void Build(const GrDrawState&,
+    static bool Build(const GrDrawState&,
                       GrGpu::DrawType drawType,
                       GrDrawState::BlendOptFlags,
                       GrBlendCoeff srcCoeff,
@@ -76,12 +74,10 @@ public:
                       GrGLProgramDesc* outDesc);
 
     int numColorEffects() const {
-        SkASSERT(fInitialized);
         return this->getHeader().fColorEffectCnt;
     }
 
     int numCoverageEffects() const {
-        SkASSERT(fInitialized);
         return this->getHeader().fCoverageEffectCnt;
     }
 
@@ -90,7 +86,6 @@ public:
     GrGLProgramDesc& operator= (const GrGLProgramDesc& other);
 
     bool operator== (const GrGLProgramDesc& other) const {
-        SkASSERT(fInitialized && other.fInitialized);
         // The length is masked as a hint to the compiler that the address will be 4 byte aligned.
         return 0 == memcmp(this->asKey(), other.asKey(), this->keyLength() & ~0x3);
     }
@@ -145,13 +140,12 @@ private:
     }
 
     struct KeyHeader {
-        GrGLShaderBuilder::DstReadKey fDstReadKey;      // set by GrGLShaderBuilder if there
+        uint8_t                     fDstReadKey;        // set by GrGLShaderBuilder if there
                                                         // are effects that must read the dst.
                                                         // Otherwise, 0.
-        GrGLShaderBuilder::FragPosKey fFragPosKey;      // set by GrGLShaderBuilder if there are
+        uint8_t                     fFragPosKey;        // set by GrGLShaderBuilder if there are
                                                         // effects that read the fragment position.
                                                         // Otherwise, 0.
-
         ColorInput                  fColorInput : 8;
         ColorInput                  fCoverageInput : 8;
         CoverageOutput              fCoverageOutput : 8;
@@ -174,48 +168,72 @@ private:
         int8_t                      fCoverageEffectCnt;
     };
 
-    // The key is 1 uint32_t for the length, followed another for the checksum, the header, and then
-    // the effect keys. Everything is fixed length except the effect key array.
+    // The key, stored in fKey, is composed of five parts:
+    // 1. uint32_t for total key length.
+    // 2. uint32_t for a checksum.
+    // 3. Header struct defined above.
+    // 4. uint32_t offsets to beginning of every effects' key (see 5).
+    // 5. per-effect keys. Each effect's key is a variable length array of uint32_t.
     enum {
         kLengthOffset = 0,
         kChecksumOffset = kLengthOffset + sizeof(uint32_t),
         kHeaderOffset = kChecksumOffset + sizeof(uint32_t),
         kHeaderSize = SkAlign4(sizeof(KeyHeader)),
-        kEffectKeyOffset = kHeaderOffset + kHeaderSize,
+        kEffectKeyLengthsOffset = kHeaderOffset + kHeaderSize,
     };
 
     template<typename T, size_t OFFSET> T* atOffset() {
-        return reinterpret_cast<T*>(reinterpret_cast<intptr_t>(fKey.get()) + OFFSET);
+        return reinterpret_cast<T*>(reinterpret_cast<intptr_t>(fKey.begin()) + OFFSET);
     }
 
     template<typename T, size_t OFFSET> const T* atOffset() const {
-        return reinterpret_cast<const T*>(reinterpret_cast<intptr_t>(fKey.get()) + OFFSET);
+        return reinterpret_cast<const T*>(reinterpret_cast<intptr_t>(fKey.begin()) + OFFSET);
     }
 
-    typedef GrGLEffect::EffectKey EffectKey;
+    typedef GrBackendEffectFactory::EffectKey EffectKey;
 
-    uint32_t* checksum() { return this->atOffset<uint32_t, kChecksumOffset>(); }
     KeyHeader* header() { return this->atOffset<KeyHeader, kHeaderOffset>(); }
-    EffectKey* effectKeys() { return this->atOffset<EffectKey, kEffectKeyOffset>(); }
+
+    void finalize();
 
     const KeyHeader& getHeader() const { return *this->atOffset<KeyHeader, kHeaderOffset>(); }
-    const EffectKey* getEffectKeys() const { return this->atOffset<EffectKey, kEffectKeyOffset>(); }
 
-    static size_t KeyLength(int effectCnt) {
-        GR_STATIC_ASSERT(!(sizeof(EffectKey) & 0x3));
-        return kEffectKeyOffset + effectCnt * sizeof(EffectKey);
-    }
+    /** Used to provide effects' keys to their emitCode() function. */
+    class EffectKeyProvider {
+    public:
+        enum EffectType {
+            kColor_EffectType,
+            kCoverage_EffectType,
+        };
+
+        EffectKeyProvider(const GrGLProgramDesc* desc, EffectType type) : fDesc(desc) {
+            // Coverage effect key offsets begin immediately after those of the color effects.
+            fBaseIndex = kColor_EffectType == type ? 0 : desc->numColorEffects();
+        }
+
+        EffectKey get(int index) const {
+            const uint32_t* offsets = reinterpret_cast<const uint32_t*>(fDesc->fKey.begin() +
+                                                                        kEffectKeyLengthsOffset);
+            uint32_t offset = offsets[fBaseIndex + index];
+            return *reinterpret_cast<const EffectKey*>(fDesc->fKey.begin() + offset);
+        }
+    private:
+        const GrGLProgramDesc*  fDesc;
+        int                     fBaseIndex;
+    };
 
     enum {
-        kMaxPreallocEffects = 16,
-        kPreAllocSize = kEffectKeyOffset +  kMaxPreallocEffects * sizeof(EffectKey),
+        kMaxPreallocEffects = 8,
+        kIntsPerEffect      = 4,    // This is an overestimate of the average effect key size.
+        kPreAllocSize = kEffectKeyLengthsOffset +
+                        kMaxPreallocEffects * sizeof(uint32_t) * kIntsPerEffect,
     };
 
-    SkAutoSMalloc<kPreAllocSize> fKey;
-    bool fInitialized;
+    SkSTArray<kPreAllocSize, uint8_t, true> fKey;
 
-    // GrGLProgram and GrGLShaderBuilder read the private fields to generate code. TODO: Move all
-    // code generation to GrGLShaderBuilder (and maybe add getters rather than friending).
+    // GrGLProgram and GrGLShaderBuilder read the private fields to generate code. TODO: Split out
+    // part of GrGLShaderBuilder that is used by effects so that this header doesn't need to be
+    // visible to GrGLEffects. Then make public accessors as necessary and remove friends.
     friend class GrGLProgram;
     friend class GrGLShaderBuilder;
     friend class GrGLFullShaderBuilder;
index fd91f58..65d14fd 100644 (file)
@@ -239,7 +239,7 @@ void GrGLVertexProgramEffects::emitEffect(GrGLFullShaderBuilder* builder,
     SkSTArray<4, TextureSampler> samplers(effect->numTextures());
 
     this->emitAttributes(builder, stage);
-    this->emitTransforms(builder, effect, key, &coords);
+    this->emitTransforms(builder, drawEffect, &coords);
     this->emitSamplers(builder, effect, &samplers);
 
     GrGLEffect* glEffect = effect->getFactory().createGLInstance(drawEffect);
@@ -277,12 +277,11 @@ void GrGLVertexProgramEffects::emitAttributes(GrGLFullShaderBuilder* builder,
 }
 
 void GrGLVertexProgramEffects::emitTransforms(GrGLFullShaderBuilder* builder,
-                                              const GrEffect* effect,
-                                              EffectKey effectKey,
+                                              const GrDrawEffect& drawEffect,
                                               TransformedCoordsArray* outCoords) {
     SkTArray<Transform, true>& transforms = fTransforms.push_back();
-    EffectKey totalKey = GrBackendEffectFactory::GetTransformKey(effectKey);
-    int numTransforms = effect->numTransforms();
+    EffectKey totalKey = GenTransformKey(drawEffect);
+    int numTransforms = drawEffect.effect()->numTransforms();
     transforms.push_back_n(numTransforms);
     for (int t = 0; t < numTransforms; t++) {
         GrSLType varyingType = kVoid_GrSLType;
@@ -398,7 +397,7 @@ void GrGLPathTexGenProgramEffects::emitEffect(GrGLFragmentOnlyShaderBuilder* bui
     SkSTArray<4, TextureSampler> samplers(effect->numTextures());
 
     SkASSERT(0 == stage.getVertexAttribIndexCount());
-    this->setupPathTexGen(builder, effect, key, &coords);
+    this->setupPathTexGen(builder, drawEffect, &coords);
     this->emitSamplers(builder, effect, &samplers);
 
     GrGLEffect* glEffect = effect->getFactory().createGLInstance(drawEffect);
@@ -416,11 +415,10 @@ void GrGLPathTexGenProgramEffects::emitEffect(GrGLFragmentOnlyShaderBuilder* bui
 }
 
 void GrGLPathTexGenProgramEffects::setupPathTexGen(GrGLFragmentOnlyShaderBuilder* builder,
-                                           const GrEffect* effect,
-                                           EffectKey effectKey,
+                                           const GrDrawEffect& drawEffect,
                                            TransformedCoordsArray* outCoords) {
-    int numTransforms = effect->numTransforms();
-    EffectKey totalKey = GrBackendEffectFactory::GetTransformKey(effectKey);
+    int numTransforms = drawEffect.effect()->numTransforms();
+    EffectKey totalKey = GenTransformKey(drawEffect);
     int texCoordIndex = builder->addTexCoordSets(numTransforms);
     SkNEW_APPEND_TO_TARRAY(&fTransforms, Transforms, (totalKey, texCoordIndex));
     SkString name;
index 137befd..5a2fefd 100644 (file)
@@ -189,8 +189,7 @@ private:
      * TransformedCoordsArray* object, which is in turn passed to the effect's emitCode() function.
      */
     void emitTransforms(GrGLFullShaderBuilder*,
-                        const GrEffect*,
-                        EffectKey,
+                        const GrDrawEffect&,
                         TransformedCoordsArray*);
 
     /**
@@ -277,8 +276,7 @@ private:
      * effect's emitCode() function.
      */
     void setupPathTexGen(GrGLFragmentOnlyShaderBuilder*,
-                         const GrEffect*,
-                         EffectKey,
+                         const GrDrawEffect&,
                          TransformedCoordsArray*);
 
     /**
index 4b7de02..7a57d8e 100644 (file)
@@ -194,15 +194,19 @@ bool GrGLShaderBuilder::genProgram(const GrEffectStage* colorStages[],
     ///////////////////////////////////////////////////////////////////////////
     // emit the per-effect code for both color and coverage effects
 
+    GrGLProgramDesc::EffectKeyProvider colorKeyProvider(
+        &this->desc(), GrGLProgramDesc::EffectKeyProvider::kColor_EffectType);
     fOutput.fColorEffects.reset(this->createAndEmitEffects(colorStages,
-                                                           this->desc().getEffectKeys(),
                                                            this->desc().numColorEffects(),
+                                                           colorKeyProvider,
                                                            &inputColor));
 
+    GrGLProgramDesc::EffectKeyProvider coverageKeyProvider(
+        &this->desc(), GrGLProgramDesc::EffectKeyProvider::kCoverage_EffectType);
     fOutput.fCoverageEffects.reset(this->createAndEmitEffects(coverageStages,
-                                    this->desc().getEffectKeys() + this->desc().numColorEffects(),
-                                    this->desc().numCoverageEffects(),
-                                    &inputCoverage));
+                                   this->desc().numCoverageEffects(),
+                                   coverageKeyProvider,
+                                   &inputCoverage));
 
     this->emitCodeAfterEffects();
 
@@ -601,8 +605,8 @@ void GrGLShaderBuilder::appendUniformDecls(ShaderVisibility visibility,
 
 void GrGLShaderBuilder::createAndEmitEffects(GrGLProgramEffectsBuilder* programEffectsBuilder,
                                              const GrEffectStage* effectStages[],
-                                             const EffectKey effectKeys[],
                                              int effectCnt,
+                                             const GrGLProgramDesc::EffectKeyProvider& keyProvider,
                                              GrGLSLExpr4* fsInOutColor) {
     bool effectEmitted = false;
 
@@ -632,7 +636,7 @@ void GrGLShaderBuilder::createAndEmitEffects(GrGLProgramEffectsBuilder* programE
 
 
         programEffectsBuilder->emitEffect(stage,
-                                          effectKeys[e],
+                                          keyProvider.get(e),
                                           outColor.c_str(),
                                           inColor.isOnes() ? NULL : inColor.c_str(),
                                           fCodeStage.stageIndex());
@@ -976,15 +980,15 @@ const SkString* GrGLFullShaderBuilder::getEffectAttributeName(int attributeIndex
 
 GrGLProgramEffects* GrGLFullShaderBuilder::createAndEmitEffects(
         const GrEffectStage* effectStages[],
-        const EffectKey effectKeys[],
         int effectCnt,
+        const GrGLProgramDesc::EffectKeyProvider& keyProvider,
         GrGLSLExpr4* inOutFSColor) {
 
     GrGLVertexProgramEffectsBuilder programEffectsBuilder(this, effectCnt);
     this->INHERITED::createAndEmitEffects(&programEffectsBuilder,
                                           effectStages,
-                                          effectKeys,
                                           effectCnt,
+                                          keyProvider,
                                           inOutFSColor);
     return programEffectsBuilder.finish();
 }
@@ -1093,16 +1097,16 @@ int GrGLFragmentOnlyShaderBuilder::addTexCoordSets(int count) {
 
 GrGLProgramEffects* GrGLFragmentOnlyShaderBuilder::createAndEmitEffects(
         const GrEffectStage* effectStages[],
-        const EffectKey effectKeys[],
         int effectCnt,
+        const GrGLProgramDesc::EffectKeyProvider& keyProvider,
         GrGLSLExpr4* inOutFSColor) {
 
     GrGLPathTexGenProgramEffectsBuilder pathTexGenEffectsBuilder(this,
                                                                  effectCnt);
     this->INHERITED::createAndEmitEffects(&pathTexGenEffectsBuilder,
                                           effectStages,
-                                          effectKeys,
                                           effectCnt,
+                                          keyProvider,
                                           inOutFSColor);
     return pathTexGenEffectsBuilder.finish();
 }
index 7e71acf..c28cd09 100644 (file)
@@ -13,6 +13,7 @@
 #include "GrColor.h"
 #include "GrEffect.h"
 #include "SkTypes.h"
+#include "gl/GrGLProgramDesc.h"
 #include "gl/GrGLProgramEffects.h"
 #include "gl/GrGLSL.h"
 #include "gl/GrGLUniformManager.h"
@@ -253,8 +254,8 @@ protected:
     // Helper for emitEffects().
     void createAndEmitEffects(GrGLProgramEffectsBuilder*,
                               const GrEffectStage* effectStages[],
-                              const EffectKey effectKeys[],
                               int effectCnt,
+                              const GrGLProgramDesc::EffectKeyProvider&,
                               GrGLSLExpr4* inOutFSColor);
 
     // Generates a name for a variable. The generated string will be name prefixed by the prefix
@@ -338,15 +339,15 @@ private:
 
     /**
     * Adds code for effects and returns a GrGLProgramEffects* object. The caller is responsible for
-    * deleting it when finished. effectStages contains the effects to add. effectKeys[i] is the key
-    * generated from effectStages[i]. inOutFSColor specifies the input color to the first stage and
-    * is updated to be the output color of the last stage.
-    * The handles to texture samplers for effectStage[i] are added to
+    * deleting it when finished. effectStages contains the effects to add. The effect key provider 
+    * is used to communicate the key each effect created in its GenKey function. inOutFSColor
+    * specifies the input color to the first stage and is updated to be the output color of the
+    * last stage. The handles to texture samplers for effectStage[i] are added to
     * effectSamplerHandles[i].
     */
     virtual GrGLProgramEffects* createAndEmitEffects(const GrEffectStage* effectStages[],
-                                                     const EffectKey effectKeys[],
                                                      int effectCnt,
+                                                     const GrGLProgramDesc::EffectKeyProvider&,
                                                      GrGLSLExpr4* inOutFSColor) = 0;
 
     /**
@@ -465,8 +466,8 @@ private:
     virtual void emitCodeBeforeEffects(GrGLSLExpr4* color, GrGLSLExpr4* coverage) SK_OVERRIDE;
 
     virtual GrGLProgramEffects* createAndEmitEffects(const GrEffectStage* effectStages[],
-                                                     const EffectKey effectKeys[],
                                                      int effectCnt,
+                                                     const GrGLProgramDesc::EffectKeyProvider&,
                                                      GrGLSLExpr4* inOutFSColor) SK_OVERRIDE;
 
     virtual void emitCodeAfterEffects() SK_OVERRIDE;
@@ -510,8 +511,8 @@ private:
     virtual void emitCodeBeforeEffects(GrGLSLExpr4* color, GrGLSLExpr4* coverage) SK_OVERRIDE {}
 
     virtual GrGLProgramEffects* createAndEmitEffects(const GrEffectStage* effectStages[],
-                                                     const EffectKey effectKeys[],
                                                      int effectCnt,
+                                                     const GrGLProgramDesc::EffectKeyProvider&,
                                                      GrGLSLExpr4* inOutFSColor) SK_OVERRIDE;
 
     virtual void emitCodeAfterEffects() SK_OVERRIDE {}
index bd4758c..9e1b6f5 100644 (file)
@@ -234,7 +234,7 @@ bool GrGpuGL::flushGraphicsState(DrawType type, const GrDeviceCoordTexture* dstC
         SkSTArray<8, const GrEffectStage*, true> colorStages;
         SkSTArray<8, const GrEffectStage*, true> coverageStages;
         GrGLProgramDesc desc;
-        GrGLProgramDesc::Build(this->getDrawState(),
+        if (!GrGLProgramDesc::Build(this->getDrawState(),
                                type,
                                blendOpts,
                                srcCoeff,
@@ -243,7 +243,10 @@ bool GrGpuGL::flushGraphicsState(DrawType type, const GrDeviceCoordTexture* dstC
                                dstCopy,
                                &colorStages,
                                &coverageStages,
-                               &desc);
+                               &desc)) {
+            SkDEBUGFAIL("Failed to generate GL program descriptor");
+            return false;
+        }
 
         fCurrentProgram.reset(fProgramCache->getProgram(desc,
                                                         colorStages.begin(),
index 6ee4890..dd0f80f 100644 (file)
@@ -22,7 +22,7 @@
 #include "SkRandom.h"
 #include "Test.h"
 
-void GrGLProgramDesc::setRandom(SkRandom* random,
+bool GrGLProgramDesc::setRandom(SkRandom* random,
                                 const GrGpuGL* gpu,
                                 const GrRenderTarget* dstRenderTarget,
                                 const GrTexture* dstCopyTexture,
@@ -30,13 +30,51 @@ void GrGLProgramDesc::setRandom(SkRandom* random,
                                 int numColorStages,
                                 int numCoverageStages,
                                 int currAttribIndex) {
-    int numEffects = numColorStages + numCoverageStages;
-    size_t keyLength = KeyLength(numEffects);
-    fKey.reset(keyLength);
-    *this->atOffset<uint32_t, kLengthOffset>() = static_cast<uint32_t>(keyLength);
-    memset(this->header(), 0, kHeaderSize);
+    bool useLocalCoords = random->nextBool() && currAttribIndex < GrDrawState::kMaxVertexAttribCnt;
+
+    int numStages = numColorStages + numCoverageStages;
+    fKey.reset();
+
+    GR_STATIC_ASSERT(0 == kEffectKeyLengthsOffset % sizeof(uint32_t));
+
+    // Make room for everything up to and including the array of offsets to effect keys.
+    fKey.push_back_n(kEffectKeyLengthsOffset + sizeof(uint32_t) * numStages);
+
+    size_t offset = fKey.count();
+    int offsetIndex = 0;
+
+    bool dstRead = false;
+    bool fragPos = false;
+    bool vertexCode = false;
+    for (int s = 0; s < numStages; ++s) {
+        uint32_t* offsetLocation = reinterpret_cast<uint32_t*>(fKey.begin() +
+                                                               kEffectKeyLengthsOffset +
+                                                               offsetIndex * sizeof(uint32_t));
+        *offsetLocation = offset;
+        ++offsetIndex;
+
+        const GrBackendEffectFactory& factory = stages[s]->getEffect()->getFactory();
+        GrDrawEffect drawEffect(*stages[s], useLocalCoords);
+        GrEffectKeyBuilder b(&fKey);
+        if (!factory.getGLEffectKey(drawEffect, gpu->glCaps(), &b)) {
+            fKey.reset();
+            return false;
+        }
+        if (stages[s]->getEffect()->willReadDstColor()) {
+            dstRead = true;
+        }
+        if (stages[s]->getEffect()->willReadFragmentPosition()) {
+            fragPos = true;
+        }
+        if (stages[s]->getEffect()->hasVertexCode()) {
+            vertexCode = true;
+        }
+
+        offset += b.size();
+    }
 
     KeyHeader* header = this->header();
+    memset(header, 0, kHeaderSize);
     header->fEmitsPointSize = random->nextBool();
 
     header->fPositionAttributeIndex = 0;
@@ -48,6 +86,7 @@ void GrGLProgramDesc::setRandom(SkRandom* random,
                                   random->nextULessThan(kColorInputCnt));
     } while (GrDrawState::kMaxVertexAttribCnt <= currAttribIndex &&
              kAttribute_ColorInput == header->fColorInput);
+
     header->fColorAttributeIndex = (header->fColorInput == kAttribute_ColorInput) ?
                                         currAttribIndex++ :
                                         -1;
@@ -65,39 +104,20 @@ void GrGLProgramDesc::setRandom(SkRandom* random,
     header->fExperimentalGS = gpu->caps()->geometryShaderSupport() && random->nextBool();
 #endif
 
-    bool useLocalCoords = random->nextBool() && currAttribIndex < GrDrawState::kMaxVertexAttribCnt;
     header->fLocalCoordAttributeIndex = useLocalCoords ? currAttribIndex++ : -1;
 
     header->fColorEffectCnt = numColorStages;
     header->fCoverageEffectCnt = numCoverageStages;
 
-    bool dstRead = false;
-    bool fragPos = false;
-    bool vertexCode = false;
-    int numStages = numColorStages + numCoverageStages;
-    for (int s = 0; s < numStages; ++s) {
-        const GrBackendEffectFactory& factory = stages[s]->getEffect()->getFactory();
-        GrDrawEffect drawEffect(*stages[s], useLocalCoords);
-        this->effectKeys()[s] = factory.glEffectKey(drawEffect, gpu->glCaps());
-        if (stages[s]->getEffect()->willReadDstColor()) {
-            dstRead = true;
-        }
-        if (stages[s]->getEffect()->willReadFragmentPosition()) {
-            fragPos = true;
-        }
-        if (stages[s]->getEffect()->hasVertexCode()) {
-            vertexCode = true;
-        }
-    }
-
     if (dstRead) {
-        header->fDstReadKey = GrGLShaderBuilder::KeyForDstRead(dstCopyTexture, gpu->glCaps());
+        header->fDstReadKey = SkToU8(GrGLShaderBuilder::KeyForDstRead(dstCopyTexture,
+                                                                      gpu->glCaps()));
     } else {
         header->fDstReadKey = 0;
     }
     if (fragPos) {
-        header->fFragPosKey = GrGLShaderBuilder::KeyForFragmentPosition(dstRenderTarget,
-                                                                         gpu->glCaps());
+        header->fFragPosKey = SkToU8(GrGLShaderBuilder::KeyForFragmentPosition(dstRenderTarget,
+                                                                               gpu->glCaps()));
     } else {
         header->fFragPosKey = 0;
     }
@@ -118,9 +138,8 @@ void GrGLProgramDesc::setRandom(SkRandom* random,
 
     header->fCoverageOutput = coverageOutput;
 
-    *this->checksum() = 0;
-    *this->checksum() = SkChecksum::Compute(reinterpret_cast<uint32_t*>(fKey.get()), keyLength);
-    fInitialized = true;
+    this->finalize();
+    return true;
 }
 
 bool GrGpuGL::programUnitTest(int maxStages) {
@@ -202,14 +221,16 @@ bool GrGpuGL::programUnitTest(int maxStages) {
             ++s;
         }
         const GrTexture* dstTexture = random.nextBool() ? dummyTextures[0] : dummyTextures[1];
-        pdesc.setRandom(&random,
-                        this,
-                        dummyTextures[0]->asRenderTarget(),
-                        dstTexture,
-                        stages.get(),
-                        numColorStages,
-                        numCoverageStages,
-                        currAttribIndex);
+        if (!pdesc.setRandom(&random,
+                             this,
+                             dummyTextures[0]->asRenderTarget(),
+                             dstTexture,
+                             stages.get(),
+                             numColorStages,
+                             numCoverageStages,
+                             currAttribIndex)) {
+            return false;
+        }
 
         SkAutoTUnref<GrGLProgram> program(GrGLProgram::Create(this,
                                                               pdesc,