Revert of Makes GrGLProgramDesc's key store the lengths as well as offsets of the effect keys. (https://codereview.chromium.org/379113004/)

Reason for revert:
Most likely candidate for Valgrind failures:

[21:10:08.755668] ==3036== Use of uninitialised value of size 8
[21:10:08.755753] ==3036==    at 0x734AB2: GrGpuGL::ProgramCache::getProgram(GrGLProgramDesc const&, GrEffectStage const**, GrEffectStage const**) (GrGpuGL_program.cpp:107)
[21:10:08.755788] ==3036==    by 0x734ED2: GrGpuGL::flushGraphicsState(GrGpu::DrawType, GrDeviceCoordTexture const*) (GrGpuGL_program.cpp:253)
[21:10:08.755811] ==3036==    by 0x6E81C2: GrGpu::setupClipAndFlushState(GrGpu::DrawType, GrDeviceCoordTexture const*, GrDrawState::AutoRestoreEffects*, SkRect const*) (GrGpu.cpp:350)
[21:10:08.755837] ==3036==    by 0x6E9BE8: GrGpu::onDraw(GrDrawTarget::DrawInfo const&) (GrGpu.cpp:390)
[21:10:08.755858] ==3036==    by 0x6EEECE: GrInOrderDrawBuffer::flush() (GrDrawTarget.h:506)
[21:10:08.755879] ==3036==    by 0x6D0EB4: GrContext::flush(int) (GrContext.cpp:1327)
[21:10:08.755900] ==3036==    by 0x6D3F8F: GrContext::writeTexturePixels(GrTexture*, int, int, int, int, GrPixelConfig, void const*, unsigned long, unsigned int) (GrContext.cpp:1349)
[21:10:08.755922] ==3036==    by 0x6D39D7: GrContext::writeRenderTargetPixels(GrRenderTarget*, int, int, int, int, GrPixelConfig, void const*, unsigned long, unsigned int) (GrContext.cpp:1632)
[21:10:08.755949] ==3036==    by 0x6FFDF3: GrRenderTarget::writePixels(int, int, int, int, GrPixelConfig, void const*, unsigned long, unsigned int) (GrRenderTarget.cpp:45)
[21:10:08.755978] ==3036==    by 0x735563: SkGpuDevice::onWritePixels(SkImageInfo const&, void const*, unsigned long, int, int) (SkGpuDevice.cpp:280)
[21:10:08.756003] ==3036==    by 0x57A048: SkBaseDevice::writePixels(SkImageInfo const&, void const*, unsigned long, int, int) (SkDevice.cpp:106)
[21:10:08.756025] ==3036==    by 0x56D0AE: SkCanvas::writePixels(SkImageInfo const&, void const*, unsigned long, int, int) (SkCanvas.cpp:700)
[21:10:08.756050] ==3036==    by 0x56D156: SkCanvas::writePixels(SkBitmap const&, int, int) (SkCanvas.cpp:652)
[21:10:08.756077] ==3036==    by 0x5109B6: test_WritePixels(skiatest::Reporter*, GrContextFactory*) (WritePixelsTest.cpp:464)
[21:10:08.756099] ==3036==    by 0x51114C: skiatest::WritePixelsClass::onRun(skiatest::Reporter*) (WritePixelsTest.cpp:361)
[21:10:08.756122] ==3036==    by 0x406BE8: skiatest::Test::run() (Test.cpp:107)
[21:10:08.756145] ==3036==    by 0x4064C2: SkTestRunnable::run() (skia_test.cpp:109)
[21:10:08.756167] ==3036==    by 0x405D1A: tool_main(int, char**) (skia_test.cpp:221)
[21:10:08.756189] ==3036==    by 0x405F75: main (skia_test.cpp:239)
[21:10:08.756211] ==3036==  Uninitialised value was created by a stack allocation
[21:10:08.756233] ==3036==    at 0x734CC8: GrGpuGL::flushGraphicsState(GrGpu::DrawType, GrDeviceCoordTexture const*) (GrGpuGL_program.cpp:213)

Original issue's description:
> Makes GrGLProgramDesc's key store the lengths as well as offsets of the effect keys.
>
> Makes it possible to use GrBackendEffectFactories other than GrTBEF by moving meta-key generation out of GrTBEF.
>
> Cleans up docs around GrBackendEffectFactory.
>
> Committed: https://skia.googlesource.com/skia/+/c0ea398aff8254e31152cbb94c9ab6150428e252

R=robertphillips@google.com, jvanverth@google.com, bsalomon@google.com
TBR=bsalomon@google.com, jvanverth@google.com, robertphillips@google.com
NOTREECHECKS=true
NOTRY=true

Author: mtklein@google.com

Review URL: https://codereview.chromium.org/394213002
This commit is contained in:
mtklein 2014-07-16 06:16:43 -07:00 коммит произвёл Commit bot
Родитель e9d2d09ea5
Коммит 7940100fae
7 изменённых файлов: 124 добавлений и 213 удалений

Просмотреть файл

@ -14,12 +14,22 @@
#include "SkTypes.h" #include "SkTypes.h"
#include "SkTArray.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
is assigned a generation ID at construction. The ID of the return of GrEffect::getFactory()
is used as a type identifier. Thus a GrEffect subclass must return a singleton from
getFactory(). GrEffect subclasses should use the derived class GrTBackendEffectFactory that is
templated on the GrEffect subclass as their factory object. It requires that the GrEffect
subclass has a nested class (or typedef) GLEffect which is its GL implementation and a subclass
of GrGLEffect.
*/
class GrGLEffect; class GrGLEffect;
class GrGLCaps; class GrGLCaps;
class GrDrawEffect; class GrDrawEffect;
/** /**
* Used by effects to build their keys. It incorporates each per-effect key into a larger shader key. * Used by effects to build their keys. It incorpates each per-effect key into a larger shader key.
*/ */
class GrEffectKeyBuilder { class GrEffectKeyBuilder {
public: public:
@ -32,14 +42,6 @@ public:
fData->push_back_n(4, reinterpret_cast<uint8_t*>(&v)); fData->push_back_n(4, reinterpret_cast<uint8_t*>(&v));
} }
/** Inserts count uint32_ts into the key. The returned pointer is only valid until the next
add*() call. */
uint32_t* SK_WARN_UNUSED_RESULT add32n(int count) {
SkASSERT(count > 0);
fCount += count;
return reinterpret_cast<uint32_t*>(fData->push_back_n(4 * count));
}
size_t size() const { return sizeof(uint32_t) * fCount; } size_t size() const { return sizeof(uint32_t) * fCount; }
private: private:
@ -47,74 +49,43 @@ private:
int fCount; // number of uint32_ts added to fData by the effect. int fCount; // number of uint32_ts added to fData by the effect.
}; };
/**
* Given a GrEffect of a particular type, creates the corresponding graphics-backend-specific
* effect object. It also tracks equivalence of shaders generated via a key. The factory for an
* effect is accessed via GrEffect::getFactory(). Each factory instance is assigned an ID at
* construction. The ID of GrEffect::getFactory() is used as a type identifier. Thus, a GrEffect
* subclass must always return the same object from getFactory() and that factory object must be
* unique to the GrEffect subclass (and unique from any further derived subclasses).
*
* Rather than subclassing this class themselves, it is recommended that GrEffect authors use
* the templated subclass GrTBackendEffectFactory by writing their getFactory() method as:
*
* const GrBackendEffectFactory& MyEffect::getFactory() const {
* return GrTBackendEffectFactory<MyEffect>::getInstance();
* }
*
* Using GrTBackendEffectFactory places a few constraints on the effect. See that class's comments.
*/
class GrBackendEffectFactory : SkNoncopyable { class GrBackendEffectFactory : SkNoncopyable {
public: public:
typedef uint32_t EffectKey; typedef uint32_t EffectKey;
/** virtual bool getGLEffectKey(const GrDrawEffect&, const GrGLCaps&, GrEffectKeyBuilder*) const = 0;
* Generates an effect's key. The key is based on the aspects of the GrEffect object's
* configuration that affect GLSL code generation. Two GrEffect instances that would cause
* this->createGLInstance()->emitCode() to produce different code must produce different keys.
*/
virtual void getGLEffectKey(const GrDrawEffect&, const GrGLCaps&, GrEffectKeyBuilder*) const = 0;
/**
* Creates a GrGLEffect instance that is used both to generate code for the GrEffect in a GLSL
* program and to manage updating uniforms for the program when it is used.
*/
virtual GrGLEffect* createGLInstance(const GrDrawEffect&) const = 0; virtual GrGLEffect* createGLInstance(const GrDrawEffect&) const = 0;
/** bool operator ==(const GrBackendEffectFactory& b) const {
* Produces a human-reable name for the effect. return fEffectClassID == b.fEffectClassID;
*/ }
bool operator !=(const GrBackendEffectFactory& b) const {
return !(*this == b);
}
virtual const char* name() const = 0; virtual const char* name() const = 0;
/**
* A unique value for every instance of this factory. It is automatically incorporated into the
* effect's key. This allows keys generated by getGLEffectKey() to only be unique within a
* GrEffect subclass and not necessarily across subclasses.
*/
uint32_t effectClassID() const { return fEffectClassID; }
protected: protected:
GrBackendEffectFactory() : fEffectClassID(GenID()) {}
virtual ~GrBackendEffectFactory() {}
private:
enum { enum {
kIllegalEffectClassID = 0, kIllegalEffectClassID = 0,
}; };
static uint32_t GenID() { GrBackendEffectFactory() {
fEffectClassID = kIllegalEffectClassID;
}
virtual ~GrBackendEffectFactory() {}
static int32_t GenID() {
// 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.
uint32_t id = static_cast<uint32_t>(sk_atomic_inc(&fCurrEffectClassID)) + 1; int32_t id = sk_atomic_inc(&fCurrEffectClassID) + 1;
if (!id) {
SkFAIL("This should never wrap as it should only be called once for each GrEffect "
"subclass.");
}
return id; return id;
} }
const uint32_t fEffectClassID; int32_t fEffectClassID;
private:
static int32_t fCurrEffectClassID; static int32_t fCurrEffectClassID;
}; };

Просмотреть файл

@ -13,26 +13,7 @@
#include "gl/GrGLProgramEffects.h" #include "gl/GrGLProgramEffects.h"
/** /**
* Implements GrBackendEffectFactory for a GrEffect subclass as a singleton. This can be used by * Implements GrBackendEffectFactory for a GrEffect subclass as a singleton.
* most GrEffect subclasses to implement the GrEffect::getFactory() method:
*
* const GrBackendEffectFactory& MyEffect::getFactory() const {
* return GrTBackendEffectFactory<MyEffect>::getInstance();
* }
*
* Using this class requires that the GrEffect subclass always produces the same GrGLEffect
* subclass. Additionally, It adds the following requirements to the GrEffect and GrGLEffect
* subclasses:
*
* 1. The GrGLEffect used by GrEffect subclass MyEffect must be named or typedef'ed to
* MyEffect::GLEffect.
* 2. MyEffect::GLEffect must have a static function:
* EffectKey GenKey(const GrDrawEffect, const GrGLCaps&)
* which generates a key that maps 1 to 1 with code variations emitted by
* MyEffect::GLEffect::emitCode().
* 3. MyEffect must have a static function:
* const char* Name()
* which returns a human-readable name for the effect.
*/ */
template <typename EffectClass> template <typename EffectClass>
class GrTBackendEffectFactory : public GrBackendEffectFactory { class GrTBackendEffectFactory : public GrBackendEffectFactory {
@ -40,17 +21,35 @@ class GrTBackendEffectFactory : public GrBackendEffectFactory {
public: public:
typedef typename EffectClass::GLEffect GLEffect; typedef typename EffectClass::GLEffect GLEffect;
/** Returns a human-readable name for the effect. Implemented using GLEffect::Name as described /** Returns a human-readable name that is accessible via GrEffect or
* in this class's comment. */ GrGLEffect and is consistent between the two of them.
*/
virtual const char* name() const SK_OVERRIDE { return EffectClass::Name(); } virtual const char* name() const SK_OVERRIDE { return EffectClass::Name(); }
/** Generates an effect's key. This enables caching of generated shaders. Part of the
/** Implemented using GLEffect::GenKey as described in this class's comment. */ id identifies the GrEffect subclass. The remainder is based on the aspects of the
virtual void getGLEffectKey(const GrDrawEffect& drawEffect, 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, const GrGLCaps& caps,
GrEffectKeyBuilder* b) const SK_OVERRIDE { GrEffectKeyBuilder* b) const SK_OVERRIDE {
SkASSERT(kIllegalEffectClassID != fEffectClassID);
EffectKey effectKey = GLEffect::GenKey(drawEffect, caps); EffectKey effectKey = GLEffect::GenKey(drawEffect, caps);
EffectKey textureKey = GrGLProgramEffects::GenTextureKey(drawEffect, caps);
EffectKey transformKey = GrGLProgramEffects::GenTransformKey(drawEffect);
EffectKey attribKey = GrGLProgramEffects::GenAttribKey(drawEffect);
static const uint32_t kMetaKeyInvalidMask = ~((uint32_t) SK_MaxU16);
if ((textureKey | transformKey | attribKey | fEffectClassID) & kMetaKeyInvalidMask) {
return false;
}
// 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(effectKey);
b->add32(textureKey << 16 | transformKey);
b->add32(fEffectClassID << 16 | attribKey);
return true;
} }
/** Returns a new instance of the appropriate *GL* implementation class /** Returns a new instance of the appropriate *GL* implementation class
@ -60,7 +59,8 @@ public:
return SkNEW_ARGS(GLEffect, (*this, drawEffect)); return SkNEW_ARGS(GLEffect, (*this, drawEffect));
} }
/** This class is a singleton. This function returns the single instance. */ /** This class is a singleton. This function returns the single instance.
*/
static const GrBackendEffectFactory& getInstance() { static const GrBackendEffectFactory& getInstance() {
static SkAlignedSTStorage<1, GrTBackendEffectFactory> gInstanceMem; static SkAlignedSTStorage<1, GrTBackendEffectFactory> gInstanceMem;
static const GrTBackendEffectFactory* gInstance; static const GrTBackendEffectFactory* gInstance;
@ -72,7 +72,9 @@ public:
} }
protected: protected:
GrTBackendEffectFactory() {} GrTBackendEffectFactory() {
fEffectClassID = GenID();
}
}; };
#endif #endif

Просмотреть файл

@ -14,14 +14,13 @@
#include "SkChecksum.h" #include "SkChecksum.h"
bool GrGLProgramDesc::GetEffectKeyAndUpdateStats(const GrEffectStage& stage, static inline bool get_key_and_update_stats(const GrEffectStage& stage,
const GrGLCaps& caps, const GrGLCaps& caps,
bool useExplicitLocalCoords, bool useExplicitLocalCoords,
GrEffectKeyBuilder* b, GrEffectKeyBuilder* b,
uint16_t* effectKeySize, bool* setTrueIfReadsDst,
bool* setTrueIfReadsDst, bool* setTrueIfReadsPos,
bool* setTrueIfReadsPos, bool* setTrueIfHasVertexCode) {
bool* setTrueIfHasVertexCode) {
const GrBackendEffectFactory& factory = stage.getEffect()->getFactory(); const GrBackendEffectFactory& factory = stage.getEffect()->getFactory();
GrDrawEffect drawEffect(stage, useExplicitLocalCoords); GrDrawEffect drawEffect(stage, useExplicitLocalCoords);
if (stage.getEffect()->willReadDstColor()) { if (stage.getEffect()->willReadDstColor()) {
@ -33,17 +32,7 @@ bool GrGLProgramDesc::GetEffectKeyAndUpdateStats(const GrEffectStage& stage,
if (stage.getEffect()->hasVertexCode()) { if (stage.getEffect()->hasVertexCode()) {
*setTrueIfHasVertexCode = true; *setTrueIfHasVertexCode = true;
} }
factory.getGLEffectKey(drawEffect, caps, b); return factory.getGLEffectKey(drawEffect, caps, b);
size_t size = b->size();
if (size > SK_MaxU16) {
*effectKeySize = 0; // suppresses a warning.
return false;
}
*effectKeySize = SkToU16(size);
if (!GrGLProgramEffects::GenEffectMetaKey(drawEffect, caps, b)) {
return false;
}
return true;
} }
bool GrGLProgramDesc::Build(const GrDrawState& drawState, bool GrGLProgramDesc::Build(const GrDrawState& drawState,
@ -116,54 +105,43 @@ bool GrGLProgramDesc::Build(const GrDrawState& drawState,
if (!skipCoverage) { if (!skipCoverage) {
numStages += drawState.numCoverageStages() - firstEffectiveCoverageStage; numStages += drawState.numCoverageStages() - firstEffectiveCoverageStage;
} }
GR_STATIC_ASSERT(0 == kEffectKeyOffsetsAndLengthOffset % sizeof(uint32_t)); GR_STATIC_ASSERT(0 == kEffectKeyLengthsOffset % sizeof(uint32_t));
// Make room for everything up to and including the array of offsets to effect keys. // Make room for everything up to and including the array of offsets to effect keys.
desc->fKey.reset(); desc->fKey.reset();
desc->fKey.push_back_n(kEffectKeyOffsetsAndLengthOffset + 2 * sizeof(uint32_t) * numStages); desc->fKey.push_back_n(kEffectKeyLengthsOffset + sizeof(uint32_t) * numStages);
int offsetAndSizeIndex = 0; size_t offset = desc->fKey.count();
int offsetIndex = 0;
bool effectKeySuccess = true; bool effectKeySuccess = true;
if (!skipColor) { if (!skipColor) {
for (int s = firstEffectiveColorStage; s < drawState.numColorStages(); ++s) { for (int s = firstEffectiveColorStage; s < drawState.numColorStages(); ++s) {
uint16_t* offsetAndSize = uint32_t* offsetLocation = reinterpret_cast<uint32_t*>(desc->fKey.begin() +
reinterpret_cast<uint16_t*>(desc->fKey.begin() + kEffectKeyOffsetsAndLengthOffset + kEffectKeyLengthsOffset +
offsetAndSizeIndex * 2 * sizeof(uint16_t)); offsetIndex * sizeof(uint32_t));
*offsetLocation = offset;
++offsetIndex;
GrEffectKeyBuilder b(&desc->fKey); GrEffectKeyBuilder b(&desc->fKey);
uint16_t effectKeySize; effectKeySuccess |= get_key_and_update_stats(drawState.getColorStage(s), gpu->glCaps(),
uint32_t effectOffset = desc->fKey.count(); requiresLocalCoordAttrib, &b, &readsDst,
effectKeySuccess |= GetEffectKeyAndUpdateStats( &readFragPosition, &hasVertexCode);
drawState.getColorStage(s), gpu->glCaps(), offset += b.size();
requiresLocalCoordAttrib, &b,
&effectKeySize, &readsDst,
&readFragPosition, &hasVertexCode);
effectKeySuccess |= (effectOffset <= SK_MaxU16);
offsetAndSize[0] = SkToU16(effectOffset);
offsetAndSize[1] = effectKeySize;
++offsetAndSizeIndex;
} }
} }
if (!skipCoverage) { if (!skipCoverage) {
for (int s = firstEffectiveCoverageStage; s < drawState.numCoverageStages(); ++s) { for (int s = firstEffectiveCoverageStage; s < drawState.numCoverageStages(); ++s) {
uint16_t* offsetAndSize = uint32_t* offsetLocation = reinterpret_cast<uint32_t*>(desc->fKey.begin() +
reinterpret_cast<uint16_t*>(desc->fKey.begin() + kEffectKeyOffsetsAndLengthOffset + kEffectKeyLengthsOffset +
offsetAndSizeIndex * 2 * sizeof(uint16_t)); offsetIndex * sizeof(uint32_t));
*offsetLocation = offset;
++offsetIndex;
GrEffectKeyBuilder b(&desc->fKey); GrEffectKeyBuilder b(&desc->fKey);
uint16_t effectKeySize; effectKeySuccess |= get_key_and_update_stats(drawState.getCoverageStage(s),
uint32_t effectOffset = desc->fKey.count(); gpu->glCaps(), requiresLocalCoordAttrib,
effectKeySuccess |= GetEffectKeyAndUpdateStats( &b, &readsDst, &readFragPosition,
drawState.getCoverageStage(s), gpu->glCaps(), &hasVertexCode);
requiresLocalCoordAttrib, &b, offset += b.size();
&effectKeySize, &readsDst,
&readFragPosition, &hasVertexCode);
effectKeySuccess |= (effectOffset <= SK_MaxU16);
offsetAndSize[0] = SkToU16(effectOffset);
offsetAndSize[1] = effectKeySize;
++offsetAndSizeIndex;
} }
} }
if (!effectKeySuccess) { if (!effectKeySuccess) {

Просмотреть файл

@ -172,20 +172,14 @@ private:
// 1. uint32_t for total key length. // 1. uint32_t for total key length.
// 2. uint32_t for a checksum. // 2. uint32_t for a checksum.
// 3. Header struct defined above. // 3. Header struct defined above.
// 4. An array of offsets to effect keys and their sizes (see 5). uint16_t for each // 4. uint32_t offsets to beginning of every effects' key (see 5).
// offset and size.
// 5. per-effect keys. Each effect's key is a variable length array of uint32_t. // 5. per-effect keys. Each effect's key is a variable length array of uint32_t.
enum { enum {
// Part 1.
kLengthOffset = 0, kLengthOffset = 0,
// Part 2.
kChecksumOffset = kLengthOffset + sizeof(uint32_t), kChecksumOffset = kLengthOffset + sizeof(uint32_t),
// Part 3.
kHeaderOffset = kChecksumOffset + sizeof(uint32_t), kHeaderOffset = kChecksumOffset + sizeof(uint32_t),
kHeaderSize = SkAlign4(sizeof(KeyHeader)), kHeaderSize = SkAlign4(sizeof(KeyHeader)),
// Part 4. kEffectKeyLengthsOffset = kHeaderOffset + kHeaderSize,
// This is the offset in the overall key to the array of per-effect offset,length pairs.
kEffectKeyOffsetsAndLengthOffset = kHeaderOffset + kHeaderSize,
}; };
template<typename T, size_t OFFSET> T* atOffset() { template<typename T, size_t OFFSET> T* atOffset() {
@ -200,16 +194,6 @@ private:
KeyHeader* header() { return this->atOffset<KeyHeader, kHeaderOffset>(); } KeyHeader* header() { return this->atOffset<KeyHeader, kHeaderOffset>(); }
// Shared code between setRandom() and Build().
static bool GetEffectKeyAndUpdateStats(const GrEffectStage& stage,
const GrGLCaps& caps,
bool useExplicitLocalCoords,
GrEffectKeyBuilder* b,
uint16_t* effectKeySize,
bool* setTrueIfReadsDst,
bool* setTrueIfReadsPos,
bool* setTrueIfHasVertexCode);
void finalize(); void finalize();
const KeyHeader& getHeader() const { return *this->atOffset<KeyHeader, kHeaderOffset>(); } const KeyHeader& getHeader() const { return *this->atOffset<KeyHeader, kHeaderOffset>(); }
@ -228,11 +212,9 @@ private:
} }
EffectKey get(int index) const { EffectKey get(int index) const {
const uint16_t* offsets = reinterpret_cast<const uint16_t*>( const uint32_t* offsets = reinterpret_cast<const uint32_t*>(fDesc->fKey.begin() +
fDesc->fKey.begin() + kEffectKeyOffsetsAndLengthOffset); kEffectKeyLengthsOffset);
// We store two uint16_ts per effect, one for the offset to the effect's key and one for uint32_t offset = offsets[fBaseIndex + index];
// its length. Here we just need the offset.
uint16_t offset = offsets[2 * (fBaseIndex + index)];
return *reinterpret_cast<const EffectKey*>(fDesc->fKey.begin() + offset); return *reinterpret_cast<const EffectKey*>(fDesc->fKey.begin() + offset);
} }
private: private:
@ -243,7 +225,7 @@ private:
enum { enum {
kMaxPreallocEffects = 8, kMaxPreallocEffects = 8,
kIntsPerEffect = 4, // This is an overestimate of the average effect key size. kIntsPerEffect = 4, // This is an overestimate of the average effect key size.
kPreAllocSize = kEffectKeyOffsetsAndLengthOffset + kPreAllocSize = kEffectKeyLengthsOffset +
kMaxPreallocEffects * sizeof(uint32_t) * kIntsPerEffect, kMaxPreallocEffects * sizeof(uint32_t) * kIntsPerEffect,
}; };

Просмотреть файл

@ -114,27 +114,6 @@ SkMatrix get_transform_matrix(const GrDrawEffect& drawEffect, int transformIdx)
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
bool GrGLProgramEffects::GenEffectMetaKey(const GrDrawEffect& drawEffect, const GrGLCaps& caps,
GrEffectKeyBuilder* b) {
EffectKey textureKey = GrGLProgramEffects::GenTextureKey(drawEffect, caps);
EffectKey transformKey = GrGLProgramEffects::GenTransformKey(drawEffect);
EffectKey attribKey = GrGLProgramEffects::GenAttribKey(drawEffect);
uint32_t classID = drawEffect.effect()->getFactory().effectClassID();
// Currently we allow 16 bits for each of the above portions of the meta-key. Fail if they
// don't fit.
static const uint32_t kMetaKeyInvalidMask = ~((uint32_t) SK_MaxU16);
if ((textureKey | transformKey | attribKey | classID) & kMetaKeyInvalidMask) {
return false;
}
uint32_t* key = b->add32n(2);
key[0] = (textureKey << 16 | transformKey);
key[1] = (classID << 16 | attribKey);
return true;
}
EffectKey GrGLProgramEffects::GenAttribKey(const GrDrawEffect& drawEffect) { EffectKey GrGLProgramEffects::GenAttribKey(const GrDrawEffect& drawEffect) {
EffectKey key = 0; EffectKey key = 0;
int numAttributes = drawEffect.getVertexAttribIndexCount(); int numAttributes = drawEffect.getVertexAttribIndexCount();

Просмотреть файл

@ -9,9 +9,9 @@
#define GrGLProgramEffects_DEFINED #define GrGLProgramEffects_DEFINED
#include "GrBackendEffectFactory.h" #include "GrBackendEffectFactory.h"
#include "GrGLUniformManager.h"
#include "GrTexture.h" #include "GrTexture.h"
#include "GrTextureAccess.h" #include "GrTextureAccess.h"
#include "GrGLUniformManager.h"
class GrEffect; class GrEffect;
class GrEffectStage; class GrEffectStage;
@ -31,14 +31,11 @@ public:
typedef GrGLUniformManager::UniformHandle UniformHandle; typedef GrGLUniformManager::UniformHandle UniformHandle;
/** /**
* This class emits some of the code inserted into the shaders for an effect. The code it * These methods generate different portions of an effect's final key.
* creates may be dependent on properties of the effect that the effect itself doesn't use
* in its key (e.g. the pixel format of textures used). So this class inserts a meta-key for
* every effect using this function. It is also responsible for inserting the effect's class ID
* which must be different for every GrEffect subclass. It can fail if an effect uses too many
* textures, attributes, etc for the space allotted in the meta-key.
*/ */
static bool GenEffectMetaKey(const GrDrawEffect&, const GrGLCaps&, GrEffectKeyBuilder*); static EffectKey GenAttribKey(const GrDrawEffect&);
static EffectKey GenTransformKey(const GrDrawEffect&);
static EffectKey GenTextureKey(const GrDrawEffect&, const GrGLCaps&);
virtual ~GrGLProgramEffects(); virtual ~GrGLProgramEffects();
@ -101,13 +98,6 @@ public:
typedef SkTArray<TextureSampler> TextureSamplerArray; typedef SkTArray<TextureSampler> TextureSamplerArray;
protected: protected:
/**
* Helpers for GenEffectMetaKey.
*/
static EffectKey GenAttribKey(const GrDrawEffect&);
static EffectKey GenTransformKey(const GrDrawEffect&);
static EffectKey GenTextureKey(const GrDrawEffect&, const GrGLCaps&);
GrGLProgramEffects(int reserveCount) GrGLProgramEffects(int reserveCount)
: fGLEffects(reserveCount) : fGLEffects(reserveCount)
, fSamplers(reserveCount) { , fSamplers(reserveCount) {

Просмотреть файл

@ -35,33 +35,42 @@ bool GrGLProgramDesc::setRandom(SkRandom* random,
int numStages = numColorStages + numCoverageStages; int numStages = numColorStages + numCoverageStages;
fKey.reset(); fKey.reset();
GR_STATIC_ASSERT(0 == kEffectKeyOffsetsAndLengthOffset % sizeof(uint32_t)); GR_STATIC_ASSERT(0 == kEffectKeyLengthsOffset % sizeof(uint32_t));
// Make room for everything up to and including the array of offsets to effect keys. // Make room for everything up to and including the array of offsets to effect keys.
fKey.push_back_n(kEffectKeyOffsetsAndLengthOffset + 2 * sizeof(uint16_t) * numStages); fKey.push_back_n(kEffectKeyLengthsOffset + sizeof(uint32_t) * numStages);
size_t offset = fKey.count();
int offsetIndex = 0;
bool dstRead = false; bool dstRead = false;
bool fragPos = false; bool fragPos = false;
bool vertexCode = false; bool vertexCode = false;
for (int s = 0; s < numStages; ++s) { for (int s = 0; s < numStages; ++s) {
uint16_t* offsetAndSize = reinterpret_cast<uint16_t*>(fKey.begin() + uint32_t* offsetLocation = reinterpret_cast<uint32_t*>(fKey.begin() +
kEffectKeyOffsetsAndLengthOffset + kEffectKeyLengthsOffset +
s * 2 * sizeof(uint16_t)); offsetIndex * sizeof(uint32_t));
uint32_t effectKeyOffset = fKey.count(); *offsetLocation = offset;
if (effectKeyOffset > SK_MaxU16) { ++offsetIndex;
fKey.reset();
return false; const GrBackendEffectFactory& factory = stages[s]->getEffect()->getFactory();
}
GrDrawEffect drawEffect(*stages[s], useLocalCoords); GrDrawEffect drawEffect(*stages[s], useLocalCoords);
GrEffectKeyBuilder b(&fKey); GrEffectKeyBuilder b(&fKey);
uint16_t effectKeySize; if (!factory.getGLEffectKey(drawEffect, gpu->glCaps(), &b)) {
if (!GetEffectKeyAndUpdateStats(*stages[s], gpu->glCaps(), useLocalCoords, &b,
&effectKeySize, &dstRead, &fragPos, &vertexCode)) {
fKey.reset(); fKey.reset();
return false; return false;
} }
offsetAndSize[0] = effectKeyOffset; if (stages[s]->getEffect()->willReadDstColor()) {
offsetAndSize[1] = effectKeySize; 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();