This moves us towards variable length effect keys. The overall program key now allows for it. After the header it stores an array of offsets to effect keys. This allows us to grab the effect keys to pass to effects when they generate code. It also ensures that we can't get a collision by sets of keys that are different lengths but are the same when appended together.

R=robertphillips@google.com, jvanverth@google.com, egdaniel@google.com

Author: bsalomon@google.com

Review URL: https://codereview.chromium.org/356513003
This commit is contained in:
bsalomon 2014-07-11 10:01:02 -07:00 committed by Commit bot
parent 6ca0b6a46c
commit 848faf00ec
48 changed files with 317 additions and 213 deletions

View File

@ -12,6 +12,7 @@
#include "SkTemplates.h" #include "SkTemplates.h"
#include "SkThread.h" #include "SkThread.h"
#include "SkTypes.h" #include "SkTypes.h"
#include "SkTArray.h"
/** Given a GrEffect of a particular type, creates the corresponding graphics-backend-specific /** 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 effect object. Also tracks equivalence of shaders generated via a key. Each factory instance
@ -27,23 +28,32 @@ class GrGLEffect;
class GrGLCaps; class GrGLCaps;
class GrDrawEffect; 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 { class GrBackendEffectFactory : SkNoncopyable {
public: public:
typedef uint32_t EffectKey; 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; virtual GrGLEffect* createGLInstance(const GrDrawEffect&) const = 0;
bool operator ==(const GrBackendEffectFactory& b) const { bool operator ==(const GrBackendEffectFactory& b) const {
@ -55,10 +65,6 @@ public:
virtual const char* name() const = 0; virtual const char* name() const = 0;
static EffectKey GetTransformKey(EffectKey key) {
return key >> (kEffectKeyBits + kTextureKeyBits) & ((1U << kTransformKeyBits) - 1);
}
protected: protected:
enum { enum {
kIllegalEffectClassID = 0, kIllegalEffectClassID = 0,
@ -69,18 +75,15 @@ protected:
} }
virtual ~GrBackendEffectFactory() {} virtual ~GrBackendEffectFactory() {}
static EffectKey GenID() { static int32_t GenID() {
SkDEBUGCODE(static const int32_t kClassIDBits = 8 * sizeof(EffectKey) -
kTextureKeyBits - kEffectKeyBits - kAttribKeyBits);
// fCurrEffectClassID has been initialized to kIllegalEffectClassID. The // fCurrEffectClassID has been initialized to kIllegalEffectClassID. The
// atomic inc returns the old value not the incremented value. So we add // atomic inc returns the old value not the incremented value. So we add
// 1 to the returned value. // 1 to the returned value.
int32_t id = sk_atomic_inc(&fCurrEffectClassID) + 1; int32_t id = sk_atomic_inc(&fCurrEffectClassID) + 1;
SkASSERT(id < (1 << kClassIDBits)); return id;
return static_cast<EffectKey>(id);
} }
EffectKey fEffectClassID; int32_t fEffectClassID;
private: private:
static int32_t fCurrEffectClassID; static int32_t fCurrEffectClassID;

View File

@ -26,39 +26,30 @@ public:
*/ */
virtual const char* name() const SK_OVERRIDE { return EffectClass::Name(); } virtual const char* name() const SK_OVERRIDE { return EffectClass::Name(); }
/** Returns a value that identifies the GLSL shader code generated by /** Generates an effect's key. This enables caching of generated shaders. Part of the
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
id identifies the GrEffect subclass. The remainder is based GrEffect object's configuration that affect GLSL code generation. If this fails
on the aspects of the GrEffect object's configuration that affect then program generation should be aborted. Failure occurs if the effect uses more
GLSL code generation. */ transforms, attributes, or textures than the key has space for. */
virtual EffectKey glEffectKey(const GrDrawEffect& drawEffect, virtual bool getGLEffectKey(const GrDrawEffect& drawEffect,
const GrGLCaps& caps) const SK_OVERRIDE { const GrGLCaps& caps,
GrEffectKeyBuilder* b) const SK_OVERRIDE {
SkASSERT(kIllegalEffectClassID != fEffectClassID); SkASSERT(kIllegalEffectClassID != fEffectClassID);
EffectKey effectKey = GLEffect::GenKey(drawEffect, caps); EffectKey effectKey = GLEffect::GenKey(drawEffect, caps);
EffectKey textureKey = GrGLProgramEffects::GenTextureKey(drawEffect, caps); EffectKey textureKey = GrGLProgramEffects::GenTextureKey(drawEffect, caps);
EffectKey transformKey = GrGLProgramEffects::GenTransformKey(drawEffect); EffectKey transformKey = GrGLProgramEffects::GenTransformKey(drawEffect);
EffectKey attribKey = GrGLProgramEffects::GenAttribKey(drawEffect); EffectKey attribKey = GrGLProgramEffects::GenAttribKey(drawEffect);
#ifdef SK_DEBUG static const uint32_t kMetaKeyInvalidMask = ~((uint32_t) SK_MaxU16);
static const EffectKey kIllegalEffectKeyMask = (uint16_t) (~((1U << kEffectKeyBits) - 1)); if ((textureKey | transformKey | attribKey | fEffectClassID) & kMetaKeyInvalidMask) {
SkASSERT(!(kIllegalEffectKeyMask & effectKey)); return false;
}
static const EffectKey kIllegalTextureKeyMask = (uint16_t) (~((1U << kTextureKeyBits) - 1)); // effectKey must be first because it is what will be returned by
SkASSERT(!(kIllegalTextureKeyMask & textureKey)); // GrGLProgramDesc::EffectKeyProvider and passed to the GrGLEffect as its key.
b->add32(effectKey);
static const EffectKey kIllegalTransformKeyMask = (uint16_t) (~((1U << kTransformKeyBits) - 1)); b->add32(textureKey << 16 | transformKey);
SkASSERT(!(kIllegalTransformKeyMask & transformKey)); b->add32(fEffectClassID << 16 | attribKey);
return true;
static const EffectKey kIllegalAttribKeyMask = (uint16_t) (~((1U << kAttribKeyBits) - 1));
SkASSERT(!(kIllegalAttribKeyMask & textureKey));
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);
} }
/** Returns a new instance of the appropriate *GL* implementation class /** Returns a new instance of the appropriate *GL* implementation class

View File

@ -783,6 +783,7 @@ void SkXfermode::xferA8(SkAlpha* SK_RESTRICT dst,
#include "GrEffectUnitTest.h" #include "GrEffectUnitTest.h"
#include "GrTBackendEffectFactory.h" #include "GrTBackendEffectFactory.h"
#include "gl/GrGLEffect.h" #include "gl/GrGLEffect.h"
#include "gl/GrGLShaderBuilder.h"
/** /**
* GrEffect that implements the all the separable xfer modes that cannot be expressed as Coeffs. * GrEffect that implements the all the separable xfer modes that cannot be expressed as Coeffs.

View File

@ -48,6 +48,7 @@ SkImageFilter* SkAlphaThresholdFilter::Create(const SkRegion& region,
#include "GrCoordTransform.h" #include "GrCoordTransform.h"
#include "GrEffect.h" #include "GrEffect.h"
#include "gl/GrGLEffect.h" #include "gl/GrGLEffect.h"
#include "gl/GrGLShaderBuilder.h"
#include "GrTBackendEffectFactory.h" #include "GrTBackendEffectFactory.h"
#include "GrTextureAccess.h" #include "GrTextureAccess.h"

View File

@ -15,6 +15,7 @@
#include "GrContext.h" #include "GrContext.h"
#include "GrCoordTransform.h" #include "GrCoordTransform.h"
#include "gl/GrGLEffect.h" #include "gl/GrGLEffect.h"
#include "gl/GrGLShaderBuilder.h"
#include "GrTBackendEffectFactory.h" #include "GrTBackendEffectFactory.h"
#endif #endif

View File

@ -22,6 +22,7 @@
#include "GrTexture.h" #include "GrTexture.h"
#include "GrEffect.h" #include "GrEffect.h"
#include "gl/GrGLEffect.h" #include "gl/GrGLEffect.h"
#include "gl/GrGLShaderBuilder.h"
#include "effects/GrSimpleTextureEffect.h" #include "effects/GrSimpleTextureEffect.h"
#include "GrTBackendEffectFactory.h" #include "GrTBackendEffectFactory.h"
#include "SkGrPixelRef.h" #include "SkGrPixelRef.h"

View File

@ -131,6 +131,7 @@ private:
#include "GrEffectUnitTest.h" #include "GrEffectUnitTest.h"
#include "GrTBackendEffectFactory.h" #include "GrTBackendEffectFactory.h"
#include "gl/GrGLEffect.h" #include "gl/GrGLEffect.h"
#include "gl/GrGLShaderBuilder.h"
#include "SkGr.h" #include "SkGr.h"
namespace { namespace {

View File

@ -327,6 +327,7 @@ bool SkColorMatrixFilter::asColorMatrix(SkScalar matrix[20]) const {
#include "GrEffect.h" #include "GrEffect.h"
#include "GrTBackendEffectFactory.h" #include "GrTBackendEffectFactory.h"
#include "gl/GrGLEffect.h" #include "gl/GrGLEffect.h"
#include "gl/GrGLShaderBuilder.h"
class ColorMatrixEffect : public GrEffect { class ColorMatrixEffect : public GrEffect {
public: public:

View File

@ -14,6 +14,7 @@
#include "GrContext.h" #include "GrContext.h"
#include "GrCoordTransform.h" #include "GrCoordTransform.h"
#include "gl/GrGLEffect.h" #include "gl/GrGLEffect.h"
#include "gl/GrGLShaderBuilder.h"
#include "GrTBackendEffectFactory.h" #include "GrTBackendEffectFactory.h"
#endif #endif

View File

@ -17,6 +17,7 @@
#if SK_SUPPORT_GPU #if SK_SUPPORT_GPU
#include "effects/GrSingleTextureEffect.h" #include "effects/GrSingleTextureEffect.h"
#include "gl/GrGLEffect.h" #include "gl/GrGLEffect.h"
#include "gl/GrGLShaderBuilder.h"
#include "GrEffect.h" #include "GrEffect.h"
#include "GrTBackendEffectFactory.h" #include "GrTBackendEffectFactory.h"

View File

@ -12,6 +12,7 @@
#if SK_SUPPORT_GPU #if SK_SUPPORT_GPU
#include "gl/GrGLEffect.h" #include "gl/GrGLEffect.h"
#include "gl/GrGLShaderBuilder.h"
#include "GrContext.h" #include "GrContext.h"
#include "GrTBackendEffectFactory.h" #include "GrTBackendEffectFactory.h"
#endif #endif

View File

@ -16,6 +16,7 @@
#if SK_SUPPORT_GPU #if SK_SUPPORT_GPU
#include "effects/GrSingleTextureEffect.h" #include "effects/GrSingleTextureEffect.h"
#include "gl/GrGLEffect.h" #include "gl/GrGLEffect.h"
#include "gl/GrGLShaderBuilder.h"
#include "gl/GrGLSL.h" #include "gl/GrGLSL.h"
#include "gl/GrGLTexture.h" #include "gl/GrGLTexture.h"
#include "GrTBackendEffectFactory.h" #include "GrTBackendEffectFactory.h"

View File

@ -15,6 +15,7 @@
#if SK_SUPPORT_GPU #if SK_SUPPORT_GPU
#include "gl/GrGLEffect.h" #include "gl/GrGLEffect.h"
#include "gl/GrGLShaderBuilder.h"
#include "effects/GrSingleTextureEffect.h" #include "effects/GrSingleTextureEffect.h"
#include "GrTBackendEffectFactory.h" #include "GrTBackendEffectFactory.h"
#include "GrTexture.h" #include "GrTexture.h"

View File

@ -17,6 +17,7 @@
#include "GrTexture.h" #include "GrTexture.h"
#include "GrTBackendEffectFactory.h" #include "GrTBackendEffectFactory.h"
#include "gl/GrGLEffect.h" #include "gl/GrGLEffect.h"
#include "gl/GrGLShaderBuilder.h"
#include "effects/Gr1DKernelEffect.h" #include "effects/Gr1DKernelEffect.h"
#endif #endif

View File

@ -18,6 +18,7 @@
#include "GrContext.h" #include "GrContext.h"
#include "GrCoordTransform.h" #include "GrCoordTransform.h"
#include "gl/GrGLEffect.h" #include "gl/GrGLEffect.h"
#include "gl/GrGLShaderBuilder.h"
#include "GrTBackendEffectFactory.h" #include "GrTBackendEffectFactory.h"
#include "SkGr.h" #include "SkGr.h"
#endif #endif

View File

@ -230,6 +230,7 @@ bool SkTable_ColorFilter::asComponentTable(SkBitmap* table) const {
#include "GrEffect.h" #include "GrEffect.h"
#include "GrTBackendEffectFactory.h" #include "GrTBackendEffectFactory.h"
#include "gl/GrGLEffect.h" #include "gl/GrGLEffect.h"
#include "gl/GrGLShaderBuilder.h"
#include "SkGr.h" #include "SkGr.h"
class GLColorTableEffect; class GLColorTableEffect;

View File

@ -852,6 +852,7 @@ SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_END
#include "effects/GrTextureStripAtlas.h" #include "effects/GrTextureStripAtlas.h"
#include "GrTBackendEffectFactory.h" #include "GrTBackendEffectFactory.h"
#include "gl/GrGLShaderBuilder.h"
#include "SkGr.h" #include "SkGr.h"
GrGLGradientEffect::GrGLGradientEffect(const GrBackendEffectFactory& factory) GrGLGradientEffect::GrGLGradientEffect(const GrBackendEffectFactory& factory)

View File

@ -446,6 +446,7 @@ void SkLinearGradient::LinearGradientContext::shadeSpan16(int x, int y,
#if SK_SUPPORT_GPU #if SK_SUPPORT_GPU
#include "GrTBackendEffectFactory.h" #include "GrTBackendEffectFactory.h"
#include "gl/GrGLShaderBuilder.h"
#include "SkGr.h" #include "SkGr.h"
///////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////

View File

@ -458,6 +458,7 @@ void SkRadialGradient::RadialGradientContext::shadeSpan(int x, int y,
#if SK_SUPPORT_GPU #if SK_SUPPORT_GPU
#include "GrTBackendEffectFactory.h" #include "GrTBackendEffectFactory.h"
#include "gl/GrGLShaderBuilder.h"
#include "SkGr.h" #include "SkGr.h"
class GrGLRadialGradient : public GrGLGradientEffect { class GrGLRadialGradient : public GrGLGradientEffect {

View File

@ -174,6 +174,7 @@ void SkSweepGradient::SweepGradientContext::shadeSpan16(int x, int y, uint16_t*
#if SK_SUPPORT_GPU #if SK_SUPPORT_GPU
#include "GrTBackendEffectFactory.h" #include "GrTBackendEffectFactory.h"
#include "gl/GrGLShaderBuilder.h"
#include "SkGr.h" #include "SkGr.h"
class GrGLSweepGradient : public GrGLGradientEffect { class GrGLSweepGradient : public GrGLGradientEffect {

View File

@ -12,6 +12,7 @@
#if SK_SUPPORT_GPU #if SK_SUPPORT_GPU
#include "GrTBackendEffectFactory.h" #include "GrTBackendEffectFactory.h"
#include "gl/GrGLShaderBuilder.h"
// For brevity // For brevity
typedef GrGLUniformManager::UniformHandle UniformHandle; typedef GrGLUniformManager::UniformHandle UniformHandle;

View File

@ -383,6 +383,7 @@ void SkTwoPointRadialGradient::init() {
#if SK_SUPPORT_GPU #if SK_SUPPORT_GPU
#include "GrTBackendEffectFactory.h" #include "GrTBackendEffectFactory.h"
#include "gl/GrGLShaderBuilder.h"
#include "SkGr.h" #include "SkGr.h"
// For brevity // For brevity

View File

@ -19,6 +19,7 @@
#include "SkTraceEvent.h" #include "SkTraceEvent.h"
#include "gl/GrGLEffect.h" #include "gl/GrGLEffect.h"
#include "gl/GrGLShaderBuilder.h"
#include "gl/GrGLSL.h" #include "gl/GrGLSL.h"
#include "gl/GrGLVertexEffect.h" #include "gl/GrGLVertexEffect.h"

View File

@ -8,6 +8,7 @@
#include "GrAARectRenderer.h" #include "GrAARectRenderer.h"
#include "GrGpu.h" #include "GrGpu.h"
#include "gl/GrGLEffect.h" #include "gl/GrGLEffect.h"
#include "gl/GrGLShaderBuilder.h"
#include "gl/GrGLVertexEffect.h" #include "gl/GrGLVertexEffect.h"
#include "GrTBackendEffectFactory.h" #include "GrTBackendEffectFactory.h"
#include "SkColorPriv.h" #include "SkColorPriv.h"

View File

@ -10,6 +10,7 @@
#include "GrEffect.h" #include "GrEffect.h"
#include "gl/GrGLEffect.h" #include "gl/GrGLEffect.h"
#include "gl/GrGLSL.h" #include "gl/GrGLSL.h"
#include "gl/GrGLShaderBuilder.h"
#include "gl/GrGLVertexEffect.h" #include "gl/GrGLVertexEffect.h"
#include "GrTBackendEffectFactory.h" #include "GrTBackendEffectFactory.h"

View File

@ -8,6 +8,7 @@
#include "GrBezierEffect.h" #include "GrBezierEffect.h"
#include "gl/GrGLEffect.h" #include "gl/GrGLEffect.h"
#include "gl/GrGLShaderBuilder.h"
#include "gl/GrGLSL.h" #include "gl/GrGLSL.h"
#include "gl/GrGLVertexEffect.h" #include "gl/GrGLVertexEffect.h"
#include "GrTBackendEffectFactory.h" #include "GrTBackendEffectFactory.h"

View 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 "GrBicubicEffect.h"
#include "gl/GrGLShaderBuilder.h"
#define DS(x) SkDoubleToScalar(x) #define DS(x) SkDoubleToScalar(x)
const SkScalar GrBicubicEffect::gMitchellCoefficients[16] = { const SkScalar GrBicubicEffect::gMitchellCoefficients[16] = {

View File

@ -10,6 +10,7 @@
#include "GrTBackendEffectFactory.h" #include "GrTBackendEffectFactory.h"
#include "GrSimpleTextureEffect.h" #include "GrSimpleTextureEffect.h"
#include "gl/GrGLEffect.h" #include "gl/GrGLEffect.h"
#include "gl/GrGLShaderBuilder.h"
#include "SkMatrix.h" #include "SkMatrix.h"
class GrGLConfigConversionEffect : public GrGLEffect { class GrGLConfigConversionEffect : public GrGLEffect {

View File

@ -8,6 +8,7 @@
#include "GrConvexPolyEffect.h" #include "GrConvexPolyEffect.h"
#include "gl/GrGLEffect.h" #include "gl/GrGLEffect.h"
#include "gl/GrGLShaderBuilder.h"
#include "gl/GrGLSL.h" #include "gl/GrGLSL.h"
#include "GrTBackendEffectFactory.h" #include "GrTBackendEffectFactory.h"

View File

@ -7,6 +7,7 @@
#include "GrConvolutionEffect.h" #include "GrConvolutionEffect.h"
#include "gl/GrGLEffect.h" #include "gl/GrGLEffect.h"
#include "gl/GrGLShaderBuilder.h"
#include "gl/GrGLSL.h" #include "gl/GrGLSL.h"
#include "gl/GrGLTexture.h" #include "gl/GrGLTexture.h"
#include "GrTBackendEffectFactory.h" #include "GrTBackendEffectFactory.h"

View File

@ -7,6 +7,7 @@
#include "GrCustomCoordsTextureEffect.h" #include "GrCustomCoordsTextureEffect.h"
#include "gl/GrGLEffect.h" #include "gl/GrGLEffect.h"
#include "gl/GrGLShaderBuilder.h"
#include "gl/GrGLSL.h" #include "gl/GrGLSL.h"
#include "gl/GrGLTexture.h" #include "gl/GrGLTexture.h"
#include "gl/GrGLVertexEffect.h" #include "gl/GrGLVertexEffect.h"

View File

@ -12,6 +12,7 @@
#include "effects/GrVertexEffect.h" #include "effects/GrVertexEffect.h"
#include "gl/GrGLEffect.h" #include "gl/GrGLEffect.h"
#include "gl/GrGLVertexEffect.h" #include "gl/GrGLVertexEffect.h"
#include "gl/GrGLShaderBuilder.h"
#include "gl/GrGLSL.h" #include "gl/GrGLSL.h"
#include "GrContext.h" #include "GrContext.h"
#include "GrCoordTransform.h" #include "GrCoordTransform.h"

View File

@ -7,6 +7,7 @@
#include "GrDistanceFieldTextureEffect.h" #include "GrDistanceFieldTextureEffect.h"
#include "gl/GrGLEffect.h" #include "gl/GrGLEffect.h"
#include "gl/GrGLShaderBuilder.h"
#include "gl/GrGLSL.h" #include "gl/GrGLSL.h"
#include "gl/GrGLTexture.h" #include "gl/GrGLTexture.h"
#include "gl/GrGLVertexEffect.h" #include "gl/GrGLVertexEffect.h"

View File

@ -8,6 +8,7 @@
#include "GrDitherEffect.h" #include "GrDitherEffect.h"
#include "gl/GrGLEffect.h" #include "gl/GrGLEffect.h"
#include "gl/GrGLShaderBuilder.h"
#include "gl/GrGLSL.h" #include "gl/GrGLSL.h"
#include "GrTBackendEffectFactory.h" #include "GrTBackendEffectFactory.h"

View File

@ -8,6 +8,7 @@
#include "GrOvalEffect.h" #include "GrOvalEffect.h"
#include "gl/GrGLEffect.h" #include "gl/GrGLEffect.h"
#include "gl/GrGLShaderBuilder.h"
#include "gl/GrGLSL.h" #include "gl/GrGLSL.h"
#include "GrTBackendEffectFactory.h" #include "GrTBackendEffectFactory.h"

View File

@ -8,6 +8,7 @@
#include "GrRRectEffect.h" #include "GrRRectEffect.h"
#include "gl/GrGLEffect.h" #include "gl/GrGLEffect.h"
#include "gl/GrGLShaderBuilder.h"
#include "gl/GrGLSL.h" #include "gl/GrGLSL.h"
#include "GrConvexPolyEffect.h" #include "GrConvexPolyEffect.h"
#include "GrOvalEffect.h" #include "GrOvalEffect.h"

View File

@ -7,6 +7,7 @@
#include "GrSimpleTextureEffect.h" #include "GrSimpleTextureEffect.h"
#include "gl/GrGLEffect.h" #include "gl/GrGLEffect.h"
#include "gl/GrGLShaderBuilder.h"
#include "gl/GrGLSL.h" #include "gl/GrGLSL.h"
#include "gl/GrGLTexture.h" #include "gl/GrGLTexture.h"
#include "GrTBackendEffectFactory.h" #include "GrTBackendEffectFactory.h"

View File

@ -9,6 +9,7 @@
#include "GrSimpleTextureEffect.h" #include "GrSimpleTextureEffect.h"
#include "GrTBackendEffectFactory.h" #include "GrTBackendEffectFactory.h"
#include "gl/GrGLEffect.h" #include "gl/GrGLEffect.h"
#include "gl/GrGLShaderBuilder.h"
#include "SkFloatingPoint.h" #include "SkFloatingPoint.h"

View File

@ -10,6 +10,7 @@
#include "GrCoordTransform.h" #include "GrCoordTransform.h"
#include "GrEffect.h" #include "GrEffect.h"
#include "gl/GrGLEffect.h" #include "gl/GrGLEffect.h"
#include "gl/GrGLShaderBuilder.h"
#include "GrTBackendEffectFactory.h" #include "GrTBackendEffectFactory.h"
namespace { namespace {

View File

@ -10,10 +10,11 @@
#include "GrBackendEffectFactory.h" #include "GrBackendEffectFactory.h"
#include "GrGLProgramEffects.h" #include "GrGLProgramEffects.h"
#include "GrGLShaderBuilder.h"
#include "GrGLShaderVar.h" #include "GrGLShaderVar.h"
#include "GrGLSL.h" #include "GrGLSL.h"
class GrGLShaderBuilder;
/** @file /** @file
This file contains specializations for OpenGL of the shader stages declared in 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 include/gpu/GrEffect.h. Objects of type GrGLEffect are responsible for emitting the
@ -43,12 +44,6 @@ public:
typedef GrGLProgramEffects::TextureSampler TextureSampler; typedef GrGLProgramEffects::TextureSampler TextureSampler;
typedef GrGLProgramEffects::TextureSamplerArray TextureSamplerArray; typedef GrGLProgramEffects::TextureSamplerArray TextureSamplerArray;
enum {
kNoEffectKey = GrBackendEffectFactory::kNoEffectKey,
// the number of bits in EffectKey available to GenKey
kEffectKeyBits = GrBackendEffectFactory::kEffectKeyBits,
};
GrGLEffect(const GrBackendEffectFactory& factory) GrGLEffect(const GrBackendEffectFactory& factory)
: fFactory(factory) : fFactory(factory)
, fIsVertexEffect(false) { , fIsVertexEffect(false) {

View File

@ -14,29 +14,28 @@
#include "SkChecksum.h" #include "SkChecksum.h"
namespace { static inline bool get_key_and_update_stats(const GrEffectStage& stage,
inline GrGLEffect::EffectKey get_key_and_update_stats(const GrEffectStage& stage,
const GrGLCaps& caps, const GrGLCaps& caps,
bool useExplicitLocalCoords, bool useExplicitLocalCoords,
GrEffectKeyBuilder* b,
bool* setTrueIfReadsDst, bool* setTrueIfReadsDst,
bool* setTrueIfReadsPos, bool* setTrueIfReadsPos,
bool* setTrueIfHasVertexCode) { bool* setTrueIfHasVertexCode) {
const GrEffect* effect = stage.getEffect(); const GrBackendEffectFactory& factory = stage.getEffect()->getFactory();
const GrBackendEffectFactory& factory = effect->getFactory();
GrDrawEffect drawEffect(stage, useExplicitLocalCoords); GrDrawEffect drawEffect(stage, useExplicitLocalCoords);
if (effect->willReadDstColor()) { if (stage.getEffect()->willReadDstColor()) {
*setTrueIfReadsDst = true; *setTrueIfReadsDst = true;
} }
if (effect->willReadFragmentPosition()) { if (stage.getEffect()->willReadFragmentPosition()) {
*setTrueIfReadsPos = true; *setTrueIfReadsPos = true;
} }
if (effect->hasVertexCode()) { if (stage.getEffect()->hasVertexCode()) {
*setTrueIfHasVertexCode = true; *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, GrGpu::DrawType drawType,
GrDrawState::BlendOptFlags blendOpts, GrDrawState::BlendOptFlags blendOpts,
GrBlendCoeff srcCoeff, GrBlendCoeff srcCoeff,
@ -94,45 +93,68 @@ void GrGLProgramDesc::Build(const GrDrawState& drawState,
(!requiresColorAttrib && 0xffffffff == drawState.getColor()) || (!requiresColorAttrib && 0xffffffff == drawState.getColor()) ||
(!inputColorIsUsed); (!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 readsDst = false;
bool readFragPosition = false; bool readFragPosition = false;
// We use vertexshader-less shader programs only when drawing paths. // We use vertexshader-less shader programs only when drawing paths.
bool hasVertexCode = !(GrGpu::kDrawPath_DrawType == drawType || bool hasVertexCode = !(GrGpu::kDrawPath_DrawType == drawType ||
GrGpu::kDrawPaths_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) { if (!skipColor) {
for (int s = firstEffectiveColorStage; s < drawState.numColorStages(); ++s) { for (int s = firstEffectiveColorStage; s < drawState.numColorStages(); ++s) {
effectKeys[currEffectKey++] = uint32_t* offsetLocation = reinterpret_cast<uint32_t*>(desc->fKey.begin() +
get_key_and_update_stats(drawState.getColorStage(s), gpu->glCaps(), kEffectKeyLengthsOffset +
requiresLocalCoordAttrib, &readsDst, &readFragPosition, offsetIndex * sizeof(uint32_t));
&hasVertexCode); *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) { if (!skipCoverage) {
for (int s = firstEffectiveCoverageStage; s < drawState.numCoverageStages(); ++s) { for (int s = firstEffectiveCoverageStage; s < drawState.numCoverageStages(); ++s) {
effectKeys[currEffectKey++] = uint32_t* offsetLocation = reinterpret_cast<uint32_t*>(desc->fKey.begin() +
get_key_and_update_stats(drawState.getCoverageStage(s), gpu->glCaps(), kEffectKeyLengthsOffset +
requiresLocalCoordAttrib, &readsDst, &readFragPosition, 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); &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->fHasVertexCode = hasVertexCode || requiresLocalCoordAttrib;
header->fEmitsPointSize = GrGpu::kDrawPoints_DrawType == drawType; header->fEmitsPointSize = GrGpu::kDrawPoints_DrawType == drawType;
@ -268,18 +290,23 @@ void GrGLProgramDesc::Build(const GrDrawState& drawState,
header->fColorEffectCnt = colorStages->count(); header->fColorEffectCnt = colorStages->count();
header->fCoverageEffectCnt = coverageStages->count(); header->fCoverageEffectCnt = coverageStages->count();
*desc->checksum() = 0; desc->finalize();
*desc->checksum() = SkChecksum::Compute(reinterpret_cast<uint32_t*>(desc->fKey.get()), return true;
newKeyLength); }
desc->fInitialized = 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) { GrGLProgramDesc& GrGLProgramDesc::operator= (const GrGLProgramDesc& other) {
fInitialized = other.fInitialized;
if (fInitialized) {
size_t keyLength = other.keyLength(); size_t keyLength = other.keyLength();
fKey.reset(keyLength); fKey.reset(keyLength);
memcpy(fKey.get(), other.fKey.get(), keyLength); memcpy(fKey.begin(), other.fKey.begin(), keyLength);
}
return *this; return *this;
} }

View File

@ -10,7 +10,6 @@
#include "GrGLEffect.h" #include "GrGLEffect.h"
#include "GrDrawState.h" #include "GrDrawState.h"
#include "GrGLShaderBuilder.h"
#include "GrGpu.h" #include "GrGpu.h"
class GrGpuGL; class GrGpuGL;
@ -30,13 +29,12 @@ class GrGpuGL;
to be API-neutral then so could this class. */ to be API-neutral then so could this class. */
class GrGLProgramDesc { class GrGLProgramDesc {
public: public:
GrGLProgramDesc() : fInitialized(false) {} GrGLProgramDesc() {}
GrGLProgramDesc(const GrGLProgramDesc& desc) { *this = desc; } GrGLProgramDesc(const GrGLProgramDesc& desc) { *this = desc; }
// Returns this as a uint32_t array to be used as a key in the program cache. // Returns this as a uint32_t array to be used as a key in the program cache.
const uint32_t* asKey() const { const uint32_t* asKey() const {
SkASSERT(fInitialized); return reinterpret_cast<const uint32_t*>(fKey.begin());
return reinterpret_cast<const uint32_t*>(fKey.get());
} }
// Gets the number of bytes in asKey(). It will be a 4-byte aligned value. When comparing two // 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>(); } uint32_t getChecksum() const { return *this->atOffset<uint32_t, kChecksumOffset>(); }
// For unit testing. // For unit testing.
void setRandom(SkRandom*, bool setRandom(SkRandom*,
const GrGpuGL* gpu, const GrGpuGL* gpu,
const GrRenderTarget* dummyDstRenderTarget, const GrRenderTarget* dummyDstRenderTarget,
const GrTexture* dummyDstCopyTexture, const GrTexture* dummyDstCopyTexture,
@ -64,7 +62,7 @@ public:
* not contain all stages from the draw state and coverage stages from the drawState may * not contain all stages from the draw state and coverage stages from the drawState may
* be treated as color stages in the output. * be treated as color stages in the output.
*/ */
static void Build(const GrDrawState&, static bool Build(const GrDrawState&,
GrGpu::DrawType drawType, GrGpu::DrawType drawType,
GrDrawState::BlendOptFlags, GrDrawState::BlendOptFlags,
GrBlendCoeff srcCoeff, GrBlendCoeff srcCoeff,
@ -76,12 +74,10 @@ public:
GrGLProgramDesc* outDesc); GrGLProgramDesc* outDesc);
int numColorEffects() const { int numColorEffects() const {
SkASSERT(fInitialized);
return this->getHeader().fColorEffectCnt; return this->getHeader().fColorEffectCnt;
} }
int numCoverageEffects() const { int numCoverageEffects() const {
SkASSERT(fInitialized);
return this->getHeader().fCoverageEffectCnt; return this->getHeader().fCoverageEffectCnt;
} }
@ -90,7 +86,6 @@ public:
GrGLProgramDesc& operator= (const GrGLProgramDesc& other); GrGLProgramDesc& operator= (const GrGLProgramDesc& other);
bool operator== (const GrGLProgramDesc& other) const { 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. // 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); return 0 == memcmp(this->asKey(), other.asKey(), this->keyLength() & ~0x3);
} }
@ -145,13 +140,12 @@ private:
} }
struct KeyHeader { 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. // are effects that must read the dst.
// Otherwise, 0. // 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. // effects that read the fragment position.
// Otherwise, 0. // Otherwise, 0.
ColorInput fColorInput : 8; ColorInput fColorInput : 8;
ColorInput fCoverageInput : 8; ColorInput fCoverageInput : 8;
CoverageOutput fCoverageOutput : 8; CoverageOutput fCoverageOutput : 8;
@ -174,48 +168,72 @@ private:
int8_t fCoverageEffectCnt; int8_t fCoverageEffectCnt;
}; };
// The key is 1 uint32_t for the length, followed another for the checksum, the header, and then // The key, stored in fKey, is composed of five parts:
// the effect keys. Everything is fixed length except the effect key array. // 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 { enum {
kLengthOffset = 0, kLengthOffset = 0,
kChecksumOffset = kLengthOffset + sizeof(uint32_t), kChecksumOffset = kLengthOffset + sizeof(uint32_t),
kHeaderOffset = kChecksumOffset + sizeof(uint32_t), kHeaderOffset = kChecksumOffset + sizeof(uint32_t),
kHeaderSize = SkAlign4(sizeof(KeyHeader)), kHeaderSize = SkAlign4(sizeof(KeyHeader)),
kEffectKeyOffset = kHeaderOffset + kHeaderSize, kEffectKeyLengthsOffset = kHeaderOffset + kHeaderSize,
}; };
template<typename T, size_t OFFSET> T* atOffset() { 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 { 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>(); } 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 KeyHeader& getHeader() const { return *this->atOffset<KeyHeader, kHeaderOffset>(); }
const EffectKey* getEffectKeys() const { return this->atOffset<EffectKey, kEffectKeyOffset>(); }
static size_t KeyLength(int effectCnt) { /** Used to provide effects' keys to their emitCode() function. */
GR_STATIC_ASSERT(!(sizeof(EffectKey) & 0x3)); class EffectKeyProvider {
return kEffectKeyOffset + effectCnt * sizeof(EffectKey); public:
} enum EffectType {
kColor_EffectType,
enum { kCoverage_EffectType,
kMaxPreallocEffects = 16,
kPreAllocSize = kEffectKeyOffset + kMaxPreallocEffects * sizeof(EffectKey),
}; };
SkAutoSMalloc<kPreAllocSize> fKey; EffectKeyProvider(const GrGLProgramDesc* desc, EffectType type) : fDesc(desc) {
bool fInitialized; // Coverage effect key offsets begin immediately after those of the color effects.
fBaseIndex = kColor_EffectType == type ? 0 : desc->numColorEffects();
}
// GrGLProgram and GrGLShaderBuilder read the private fields to generate code. TODO: Move all EffectKey get(int index) const {
// code generation to GrGLShaderBuilder (and maybe add getters rather than friending). 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 = 8,
kIntsPerEffect = 4, // This is an overestimate of the average effect key size.
kPreAllocSize = kEffectKeyLengthsOffset +
kMaxPreallocEffects * sizeof(uint32_t) * kIntsPerEffect,
};
SkSTArray<kPreAllocSize, uint8_t, true> fKey;
// 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 GrGLProgram;
friend class GrGLShaderBuilder; friend class GrGLShaderBuilder;
friend class GrGLFullShaderBuilder; friend class GrGLFullShaderBuilder;

View File

@ -239,7 +239,7 @@ void GrGLVertexProgramEffects::emitEffect(GrGLFullShaderBuilder* builder,
SkSTArray<4, TextureSampler> samplers(effect->numTextures()); SkSTArray<4, TextureSampler> samplers(effect->numTextures());
this->emitAttributes(builder, stage); this->emitAttributes(builder, stage);
this->emitTransforms(builder, effect, key, &coords); this->emitTransforms(builder, drawEffect, &coords);
this->emitSamplers(builder, effect, &samplers); this->emitSamplers(builder, effect, &samplers);
GrGLEffect* glEffect = effect->getFactory().createGLInstance(drawEffect); GrGLEffect* glEffect = effect->getFactory().createGLInstance(drawEffect);
@ -277,12 +277,11 @@ void GrGLVertexProgramEffects::emitAttributes(GrGLFullShaderBuilder* builder,
} }
void GrGLVertexProgramEffects::emitTransforms(GrGLFullShaderBuilder* builder, void GrGLVertexProgramEffects::emitTransforms(GrGLFullShaderBuilder* builder,
const GrEffect* effect, const GrDrawEffect& drawEffect,
EffectKey effectKey,
TransformedCoordsArray* outCoords) { TransformedCoordsArray* outCoords) {
SkTArray<Transform, true>& transforms = fTransforms.push_back(); SkTArray<Transform, true>& transforms = fTransforms.push_back();
EffectKey totalKey = GrBackendEffectFactory::GetTransformKey(effectKey); EffectKey totalKey = GenTransformKey(drawEffect);
int numTransforms = effect->numTransforms(); int numTransforms = drawEffect.effect()->numTransforms();
transforms.push_back_n(numTransforms); transforms.push_back_n(numTransforms);
for (int t = 0; t < numTransforms; t++) { for (int t = 0; t < numTransforms; t++) {
GrSLType varyingType = kVoid_GrSLType; GrSLType varyingType = kVoid_GrSLType;
@ -398,7 +397,7 @@ void GrGLPathTexGenProgramEffects::emitEffect(GrGLFragmentOnlyShaderBuilder* bui
SkSTArray<4, TextureSampler> samplers(effect->numTextures()); SkSTArray<4, TextureSampler> samplers(effect->numTextures());
SkASSERT(0 == stage.getVertexAttribIndexCount()); SkASSERT(0 == stage.getVertexAttribIndexCount());
this->setupPathTexGen(builder, effect, key, &coords); this->setupPathTexGen(builder, drawEffect, &coords);
this->emitSamplers(builder, effect, &samplers); this->emitSamplers(builder, effect, &samplers);
GrGLEffect* glEffect = effect->getFactory().createGLInstance(drawEffect); GrGLEffect* glEffect = effect->getFactory().createGLInstance(drawEffect);
@ -416,11 +415,10 @@ void GrGLPathTexGenProgramEffects::emitEffect(GrGLFragmentOnlyShaderBuilder* bui
} }
void GrGLPathTexGenProgramEffects::setupPathTexGen(GrGLFragmentOnlyShaderBuilder* builder, void GrGLPathTexGenProgramEffects::setupPathTexGen(GrGLFragmentOnlyShaderBuilder* builder,
const GrEffect* effect, const GrDrawEffect& drawEffect,
EffectKey effectKey,
TransformedCoordsArray* outCoords) { TransformedCoordsArray* outCoords) {
int numTransforms = effect->numTransforms(); int numTransforms = drawEffect.effect()->numTransforms();
EffectKey totalKey = GrBackendEffectFactory::GetTransformKey(effectKey); EffectKey totalKey = GenTransformKey(drawEffect);
int texCoordIndex = builder->addTexCoordSets(numTransforms); int texCoordIndex = builder->addTexCoordSets(numTransforms);
SkNEW_APPEND_TO_TARRAY(&fTransforms, Transforms, (totalKey, texCoordIndex)); SkNEW_APPEND_TO_TARRAY(&fTransforms, Transforms, (totalKey, texCoordIndex));
SkString name; SkString name;

View File

@ -189,8 +189,7 @@ private:
* TransformedCoordsArray* object, which is in turn passed to the effect's emitCode() function. * TransformedCoordsArray* object, which is in turn passed to the effect's emitCode() function.
*/ */
void emitTransforms(GrGLFullShaderBuilder*, void emitTransforms(GrGLFullShaderBuilder*,
const GrEffect*, const GrDrawEffect&,
EffectKey,
TransformedCoordsArray*); TransformedCoordsArray*);
/** /**
@ -277,8 +276,7 @@ private:
* effect's emitCode() function. * effect's emitCode() function.
*/ */
void setupPathTexGen(GrGLFragmentOnlyShaderBuilder*, void setupPathTexGen(GrGLFragmentOnlyShaderBuilder*,
const GrEffect*, const GrDrawEffect&,
EffectKey,
TransformedCoordsArray*); TransformedCoordsArray*);
/** /**

View File

@ -194,14 +194,18 @@ bool GrGLShaderBuilder::genProgram(const GrEffectStage* colorStages[],
/////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////
// emit the per-effect code for both color and coverage effects // 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, fOutput.fColorEffects.reset(this->createAndEmitEffects(colorStages,
this->desc().getEffectKeys(),
this->desc().numColorEffects(), this->desc().numColorEffects(),
colorKeyProvider,
&inputColor)); &inputColor));
GrGLProgramDesc::EffectKeyProvider coverageKeyProvider(
&this->desc(), GrGLProgramDesc::EffectKeyProvider::kCoverage_EffectType);
fOutput.fCoverageEffects.reset(this->createAndEmitEffects(coverageStages, fOutput.fCoverageEffects.reset(this->createAndEmitEffects(coverageStages,
this->desc().getEffectKeys() + this->desc().numColorEffects(),
this->desc().numCoverageEffects(), this->desc().numCoverageEffects(),
coverageKeyProvider,
&inputCoverage)); &inputCoverage));
this->emitCodeAfterEffects(); this->emitCodeAfterEffects();
@ -601,8 +605,8 @@ void GrGLShaderBuilder::appendUniformDecls(ShaderVisibility visibility,
void GrGLShaderBuilder::createAndEmitEffects(GrGLProgramEffectsBuilder* programEffectsBuilder, void GrGLShaderBuilder::createAndEmitEffects(GrGLProgramEffectsBuilder* programEffectsBuilder,
const GrEffectStage* effectStages[], const GrEffectStage* effectStages[],
const EffectKey effectKeys[],
int effectCnt, int effectCnt,
const GrGLProgramDesc::EffectKeyProvider& keyProvider,
GrGLSLExpr4* fsInOutColor) { GrGLSLExpr4* fsInOutColor) {
bool effectEmitted = false; bool effectEmitted = false;
@ -632,7 +636,7 @@ void GrGLShaderBuilder::createAndEmitEffects(GrGLProgramEffectsBuilder* programE
programEffectsBuilder->emitEffect(stage, programEffectsBuilder->emitEffect(stage,
effectKeys[e], keyProvider.get(e),
outColor.c_str(), outColor.c_str(),
inColor.isOnes() ? NULL : inColor.c_str(), inColor.isOnes() ? NULL : inColor.c_str(),
fCodeStage.stageIndex()); fCodeStage.stageIndex());
@ -976,15 +980,15 @@ const SkString* GrGLFullShaderBuilder::getEffectAttributeName(int attributeIndex
GrGLProgramEffects* GrGLFullShaderBuilder::createAndEmitEffects( GrGLProgramEffects* GrGLFullShaderBuilder::createAndEmitEffects(
const GrEffectStage* effectStages[], const GrEffectStage* effectStages[],
const EffectKey effectKeys[],
int effectCnt, int effectCnt,
const GrGLProgramDesc::EffectKeyProvider& keyProvider,
GrGLSLExpr4* inOutFSColor) { GrGLSLExpr4* inOutFSColor) {
GrGLVertexProgramEffectsBuilder programEffectsBuilder(this, effectCnt); GrGLVertexProgramEffectsBuilder programEffectsBuilder(this, effectCnt);
this->INHERITED::createAndEmitEffects(&programEffectsBuilder, this->INHERITED::createAndEmitEffects(&programEffectsBuilder,
effectStages, effectStages,
effectKeys,
effectCnt, effectCnt,
keyProvider,
inOutFSColor); inOutFSColor);
return programEffectsBuilder.finish(); return programEffectsBuilder.finish();
} }
@ -1093,16 +1097,16 @@ int GrGLFragmentOnlyShaderBuilder::addTexCoordSets(int count) {
GrGLProgramEffects* GrGLFragmentOnlyShaderBuilder::createAndEmitEffects( GrGLProgramEffects* GrGLFragmentOnlyShaderBuilder::createAndEmitEffects(
const GrEffectStage* effectStages[], const GrEffectStage* effectStages[],
const EffectKey effectKeys[],
int effectCnt, int effectCnt,
const GrGLProgramDesc::EffectKeyProvider& keyProvider,
GrGLSLExpr4* inOutFSColor) { GrGLSLExpr4* inOutFSColor) {
GrGLPathTexGenProgramEffectsBuilder pathTexGenEffectsBuilder(this, GrGLPathTexGenProgramEffectsBuilder pathTexGenEffectsBuilder(this,
effectCnt); effectCnt);
this->INHERITED::createAndEmitEffects(&pathTexGenEffectsBuilder, this->INHERITED::createAndEmitEffects(&pathTexGenEffectsBuilder,
effectStages, effectStages,
effectKeys,
effectCnt, effectCnt,
keyProvider,
inOutFSColor); inOutFSColor);
return pathTexGenEffectsBuilder.finish(); return pathTexGenEffectsBuilder.finish();
} }

View File

@ -13,6 +13,7 @@
#include "GrColor.h" #include "GrColor.h"
#include "GrEffect.h" #include "GrEffect.h"
#include "SkTypes.h" #include "SkTypes.h"
#include "gl/GrGLProgramDesc.h"
#include "gl/GrGLProgramEffects.h" #include "gl/GrGLProgramEffects.h"
#include "gl/GrGLSL.h" #include "gl/GrGLSL.h"
#include "gl/GrGLUniformManager.h" #include "gl/GrGLUniformManager.h"
@ -253,8 +254,8 @@ protected:
// Helper for emitEffects(). // Helper for emitEffects().
void createAndEmitEffects(GrGLProgramEffectsBuilder*, void createAndEmitEffects(GrGLProgramEffectsBuilder*,
const GrEffectStage* effectStages[], const GrEffectStage* effectStages[],
const EffectKey effectKeys[],
int effectCnt, int effectCnt,
const GrGLProgramDesc::EffectKeyProvider&,
GrGLSLExpr4* inOutFSColor); GrGLSLExpr4* inOutFSColor);
// Generates a name for a variable. The generated string will be name prefixed by the prefix // 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 * 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 * deleting it when finished. effectStages contains the effects to add. The effect key provider
* generated from effectStages[i]. inOutFSColor specifies the input color to the first stage and * is used to communicate the key each effect created in its GenKey function. inOutFSColor
* is updated to be the output color of the last stage. * specifies the input color to the first stage and is updated to be the output color of the
* The handles to texture samplers for effectStage[i] are added to * last stage. The handles to texture samplers for effectStage[i] are added to
* effectSamplerHandles[i]. * effectSamplerHandles[i].
*/ */
virtual GrGLProgramEffects* createAndEmitEffects(const GrEffectStage* effectStages[], virtual GrGLProgramEffects* createAndEmitEffects(const GrEffectStage* effectStages[],
const EffectKey effectKeys[],
int effectCnt, int effectCnt,
const GrGLProgramDesc::EffectKeyProvider&,
GrGLSLExpr4* inOutFSColor) = 0; GrGLSLExpr4* inOutFSColor) = 0;
/** /**
@ -465,8 +466,8 @@ private:
virtual void emitCodeBeforeEffects(GrGLSLExpr4* color, GrGLSLExpr4* coverage) SK_OVERRIDE; virtual void emitCodeBeforeEffects(GrGLSLExpr4* color, GrGLSLExpr4* coverage) SK_OVERRIDE;
virtual GrGLProgramEffects* createAndEmitEffects(const GrEffectStage* effectStages[], virtual GrGLProgramEffects* createAndEmitEffects(const GrEffectStage* effectStages[],
const EffectKey effectKeys[],
int effectCnt, int effectCnt,
const GrGLProgramDesc::EffectKeyProvider&,
GrGLSLExpr4* inOutFSColor) SK_OVERRIDE; GrGLSLExpr4* inOutFSColor) SK_OVERRIDE;
virtual void emitCodeAfterEffects() SK_OVERRIDE; virtual void emitCodeAfterEffects() SK_OVERRIDE;
@ -510,8 +511,8 @@ private:
virtual void emitCodeBeforeEffects(GrGLSLExpr4* color, GrGLSLExpr4* coverage) SK_OVERRIDE {} virtual void emitCodeBeforeEffects(GrGLSLExpr4* color, GrGLSLExpr4* coverage) SK_OVERRIDE {}
virtual GrGLProgramEffects* createAndEmitEffects(const GrEffectStage* effectStages[], virtual GrGLProgramEffects* createAndEmitEffects(const GrEffectStage* effectStages[],
const EffectKey effectKeys[],
int effectCnt, int effectCnt,
const GrGLProgramDesc::EffectKeyProvider&,
GrGLSLExpr4* inOutFSColor) SK_OVERRIDE; GrGLSLExpr4* inOutFSColor) SK_OVERRIDE;
virtual void emitCodeAfterEffects() SK_OVERRIDE {} virtual void emitCodeAfterEffects() SK_OVERRIDE {}

View File

@ -234,7 +234,7 @@ bool GrGpuGL::flushGraphicsState(DrawType type, const GrDeviceCoordTexture* dstC
SkSTArray<8, const GrEffectStage*, true> colorStages; SkSTArray<8, const GrEffectStage*, true> colorStages;
SkSTArray<8, const GrEffectStage*, true> coverageStages; SkSTArray<8, const GrEffectStage*, true> coverageStages;
GrGLProgramDesc desc; GrGLProgramDesc desc;
GrGLProgramDesc::Build(this->getDrawState(), if (!GrGLProgramDesc::Build(this->getDrawState(),
type, type,
blendOpts, blendOpts,
srcCoeff, srcCoeff,
@ -243,7 +243,10 @@ bool GrGpuGL::flushGraphicsState(DrawType type, const GrDeviceCoordTexture* dstC
dstCopy, dstCopy,
&colorStages, &colorStages,
&coverageStages, &coverageStages,
&desc); &desc)) {
SkDEBUGFAIL("Failed to generate GL program descriptor");
return false;
}
fCurrentProgram.reset(fProgramCache->getProgram(desc, fCurrentProgram.reset(fProgramCache->getProgram(desc,
colorStages.begin(), colorStages.begin(),

View File

@ -22,7 +22,7 @@
#include "SkRandom.h" #include "SkRandom.h"
#include "Test.h" #include "Test.h"
void GrGLProgramDesc::setRandom(SkRandom* random, bool GrGLProgramDesc::setRandom(SkRandom* random,
const GrGpuGL* gpu, const GrGpuGL* gpu,
const GrRenderTarget* dstRenderTarget, const GrRenderTarget* dstRenderTarget,
const GrTexture* dstCopyTexture, const GrTexture* dstCopyTexture,
@ -30,13 +30,51 @@ void GrGLProgramDesc::setRandom(SkRandom* random,
int numColorStages, int numColorStages,
int numCoverageStages, int numCoverageStages,
int currAttribIndex) { int currAttribIndex) {
int numEffects = numColorStages + numCoverageStages; bool useLocalCoords = random->nextBool() && currAttribIndex < GrDrawState::kMaxVertexAttribCnt;
size_t keyLength = KeyLength(numEffects);
fKey.reset(keyLength); int numStages = numColorStages + numCoverageStages;
*this->atOffset<uint32_t, kLengthOffset>() = static_cast<uint32_t>(keyLength); fKey.reset();
memset(this->header(), 0, kHeaderSize);
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(); KeyHeader* header = this->header();
memset(header, 0, kHeaderSize);
header->fEmitsPointSize = random->nextBool(); header->fEmitsPointSize = random->nextBool();
header->fPositionAttributeIndex = 0; header->fPositionAttributeIndex = 0;
@ -48,6 +86,7 @@ void GrGLProgramDesc::setRandom(SkRandom* random,
random->nextULessThan(kColorInputCnt)); random->nextULessThan(kColorInputCnt));
} while (GrDrawState::kMaxVertexAttribCnt <= currAttribIndex && } while (GrDrawState::kMaxVertexAttribCnt <= currAttribIndex &&
kAttribute_ColorInput == header->fColorInput); kAttribute_ColorInput == header->fColorInput);
header->fColorAttributeIndex = (header->fColorInput == kAttribute_ColorInput) ? header->fColorAttributeIndex = (header->fColorInput == kAttribute_ColorInput) ?
currAttribIndex++ : currAttribIndex++ :
-1; -1;
@ -65,39 +104,20 @@ void GrGLProgramDesc::setRandom(SkRandom* random,
header->fExperimentalGS = gpu->caps()->geometryShaderSupport() && random->nextBool(); header->fExperimentalGS = gpu->caps()->geometryShaderSupport() && random->nextBool();
#endif #endif
bool useLocalCoords = random->nextBool() && currAttribIndex < GrDrawState::kMaxVertexAttribCnt;
header->fLocalCoordAttributeIndex = useLocalCoords ? currAttribIndex++ : -1; header->fLocalCoordAttributeIndex = useLocalCoords ? currAttribIndex++ : -1;
header->fColorEffectCnt = numColorStages; header->fColorEffectCnt = numColorStages;
header->fCoverageEffectCnt = numCoverageStages; 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) { if (dstRead) {
header->fDstReadKey = GrGLShaderBuilder::KeyForDstRead(dstCopyTexture, gpu->glCaps()); header->fDstReadKey = SkToU8(GrGLShaderBuilder::KeyForDstRead(dstCopyTexture,
gpu->glCaps()));
} else { } else {
header->fDstReadKey = 0; header->fDstReadKey = 0;
} }
if (fragPos) { if (fragPos) {
header->fFragPosKey = GrGLShaderBuilder::KeyForFragmentPosition(dstRenderTarget, header->fFragPosKey = SkToU8(GrGLShaderBuilder::KeyForFragmentPosition(dstRenderTarget,
gpu->glCaps()); gpu->glCaps()));
} else { } else {
header->fFragPosKey = 0; header->fFragPosKey = 0;
} }
@ -118,9 +138,8 @@ void GrGLProgramDesc::setRandom(SkRandom* random,
header->fCoverageOutput = coverageOutput; header->fCoverageOutput = coverageOutput;
*this->checksum() = 0; this->finalize();
*this->checksum() = SkChecksum::Compute(reinterpret_cast<uint32_t*>(fKey.get()), keyLength); return true;
fInitialized = true;
} }
bool GrGpuGL::programUnitTest(int maxStages) { bool GrGpuGL::programUnitTest(int maxStages) {
@ -202,14 +221,16 @@ bool GrGpuGL::programUnitTest(int maxStages) {
++s; ++s;
} }
const GrTexture* dstTexture = random.nextBool() ? dummyTextures[0] : dummyTextures[1]; const GrTexture* dstTexture = random.nextBool() ? dummyTextures[0] : dummyTextures[1];
pdesc.setRandom(&random, if (!pdesc.setRandom(&random,
this, this,
dummyTextures[0]->asRenderTarget(), dummyTextures[0]->asRenderTarget(),
dstTexture, dstTexture,
stages.get(), stages.get(),
numColorStages, numColorStages,
numCoverageStages, numCoverageStages,
currAttribIndex); currAttribIndex)) {
return false;
}
SkAutoTUnref<GrGLProgram> program(GrGLProgram::Create(this, SkAutoTUnref<GrGLProgram> program(GrGLProgram::Create(this,
pdesc, pdesc,