зеркало из https://github.com/mozilla/moz-skia.git
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:
Родитель
e9d2d09ea5
Коммит
7940100fae
|
@ -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();
|
||||||
|
|
Загрузка…
Ссылка в новой задаче