Reland r6233 with fix for config conversion texture matrices.

git-svn-id: http://skia.googlecode.com/svn/trunk@6238 2bbb7eff-a529-9590-31e7-b0007b416f81
This commit is contained in:
bsalomon@google.com 2012-11-01 15:40:47 +00:00
Родитель 66e534da8e
Коммит c3a58f345d
29 изменённых файлов: 787 добавлений и 175 удалений

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

@ -114,7 +114,7 @@ protected:
tm = vm; tm = vm;
tm.postIDiv(2*S, 2*S); tm.postIDiv(2*S, 2*S);
paint.colorStage(0)->setEffect(SkNEW_ARGS(GrSingleTextureEffect, paint.colorStage(0)->setEffect(SkNEW_ARGS(GrSingleTextureEffect,
(texture)), tm)->unref(); (texture, tm)))->unref();
ctx->drawRect(paint, GrRect::MakeWH(2*S, 2*S)); ctx->drawRect(paint, GrRect::MakeWH(2*S, 2*S));

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

@ -147,6 +147,8 @@
'<(skia_src_path)/gpu/gl/GrGLDefines.h', '<(skia_src_path)/gpu/gl/GrGLDefines.h',
'<(skia_src_path)/gpu/gl/GrGLEffect.cpp', '<(skia_src_path)/gpu/gl/GrGLEffect.cpp',
'<(skia_src_path)/gpu/gl/GrGLEffect.h', '<(skia_src_path)/gpu/gl/GrGLEffect.h',
'<(skia_src_path)/gpu/gl/GrGLEffectMatrix.cpp',
'<(skia_src_path)/gpu/gl/GrGLEffectMatrix.h',
'<(skia_src_path)/gpu/gl/GrGLIndexBuffer.cpp', '<(skia_src_path)/gpu/gl/GrGLIndexBuffer.cpp',
'<(skia_src_path)/gpu/gl/GrGLIndexBuffer.h', '<(skia_src_path)/gpu/gl/GrGLIndexBuffer.h',
'<(skia_src_path)/gpu/gl/GrGLInterface.cpp', '<(skia_src_path)/gpu/gl/GrGLInterface.cpp',

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

@ -928,8 +928,14 @@ private:
// for use with textures released from an GrAutoScratchTexture. // for use with textures released from an GrAutoScratchTexture.
void addExistingTextureToCache(GrTexture* texture); void addExistingTextureToCache(GrTexture* texture);
GrEffect* createPMToUPMEffect(GrTexture* texture, bool swapRAndB); bool installPMToUPMEffect(GrTexture* texture,
GrEffect* createUPMToPMEffect(GrTexture* texture, bool swapRAndB); bool swapRAndB,
const GrMatrix& matrix,
GrEffectStage* stage);
bool installUPMToPMEffect(GrTexture* texture,
bool swapRAndB,
const GrMatrix& matrix,
GrEffectStage* stage);
typedef GrRefCnt INHERITED; typedef GrRefCnt INHERITED;
}; };

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

@ -12,12 +12,20 @@
#include "GrNoncopyable.h" #include "GrNoncopyable.h"
#include "SkTArray.h" #include "SkTArray.h"
class SkMatrix;
namespace GrEffectUnitTest { namespace GrEffectUnitTest {
// Used to access the dummy textures in TestCreate procs. // Used to access the dummy textures in TestCreate procs.
enum { enum {
kSkiaPMTextureIdx = 0, kSkiaPMTextureIdx = 0,
kAlphaTextureIdx = 1, kAlphaTextureIdx = 1,
}; };
/**
* A helper for use in GrEffect::TestCreate functions.
*/
const SkMatrix& TestMatrix(SkRandom*);
} }
#if SK_ALLOW_STATIC_GLOBAL_INITIALIZERS #if SK_ALLOW_STATIC_GLOBAL_INITIALIZERS
@ -56,12 +64,13 @@ private:
static GrEffectTestFactory gTestFactory; \ static GrEffectTestFactory gTestFactory; \
static GrEffect* TestCreate(SkRandom*, GrContext*, GrTexture* dummyTextures[2]) static GrEffect* TestCreate(SkRandom*, GrContext*, GrTexture* dummyTextures[2])
/** GrEffect subclasses should insert this macro in their implemenation file. They must then /** GrEffect subclasses should insert this macro in their implementation file. They must then
* also implement this static function: * also implement this static function:
* GrEffect* TestCreate(SkRandom*, GrContext*, GrTexture* dummyTextures[2]); * GrEffect* TestCreate(SkRandom*, GrContext*, GrTexture* dummyTextures[2]);
* dummyTextures[] are valied textures that they can optionally use for their texture accesses. The * dummyTextures[] are valid textures that can optionally be used to construct GrTextureAccesses.
* first texture has config kSkia8888_PM_GrPixelConfig and the second has kAlpha_8_GrPixelConfig. * The first texture has config kSkia8888_PM_GrPixelConfig and the second has
* TestCreate functions are also free to create additional textures using the GrContext. * kAlpha_8_GrPixelConfig. TestCreate functions are also free to create additional textures using
* the GrContext.
*/ */
#define GR_DEFINE_EFFECT_TEST(Effect) \ #define GR_DEFINE_EFFECT_TEST(Effect) \
GrEffectTestFactory Effect :: gTestFactory(Effect :: TestCreate) GrEffectTestFactory Effect :: gTestFactory(Effect :: TestCreate)

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

@ -13,6 +13,7 @@
#include "SkGr.h" #include "SkGr.h"
#include "SkGrPixelRef.h" #include "SkGrPixelRef.h"
#include "gl/GrGLEffect.h" #include "gl/GrGLEffect.h"
#include "gl/GrGLEffectMatrix.h"
#include "GrTBackendEffectFactory.h" #include "GrTBackendEffectFactory.h"
#endif #endif
@ -127,16 +128,19 @@ public:
static inline EffectKey GenKey(const GrEffectStage&, const GrGLCaps&); static inline EffectKey GenKey(const GrEffectStage&, const GrGLCaps&);
virtual void setData(const GrGLUniformManager&, const GrEffectStage&);
private: private:
typedef GrGLEffect INHERITED; typedef GrGLEffect INHERITED;
SkBlendImageFilter::Mode fMode; SkBlendImageFilter::Mode fMode;
GrGLEffectMatrix fEffectMatrix;
}; };
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
class GrBlendEffect : public GrSingleTextureEffect { class GrBlendEffect : public GrSingleTextureEffect {
public: public:
GrBlendEffect(SkBlendImageFilter::Mode mode, GrTexture* foreground); GrBlendEffect(SkBlendImageFilter::Mode mode, GrTexture* foreground, const SkMatrix&);
virtual ~GrBlendEffect(); virtual ~GrBlendEffect();
virtual bool isEqual(const GrEffect&) const SK_OVERRIDE; virtual bool isEqual(const GrEffect&) const SK_OVERRIDE;
@ -209,17 +213,19 @@ GrTexture* SkBlendImageFilter::onFilterImageGPU(Proxy* proxy, GrTexture* src, co
foregroundTexMatrix.setIDiv(foreground->width(), foreground->height()); foregroundTexMatrix.setIDiv(foreground->width(), foreground->height());
GrPaint paint; GrPaint paint;
paint.colorStage(0)->setEffect( paint.colorStage(0)->setEffect(
SkNEW_ARGS(GrSingleTextureEffect, (background.get())), backgroundTexMatrix)->unref(); SkNEW_ARGS(GrSingleTextureEffect, (background.get(), backgroundTexMatrix)))->unref();
paint.colorStage(1)->setEffect( paint.colorStage(1)->setEffect(
SkNEW_ARGS(GrBlendEffect, (fMode, foreground.get())), foregroundTexMatrix)->unref(); SkNEW_ARGS(GrBlendEffect, (fMode, foreground.get(), foregroundTexMatrix)))->unref();
context->drawRect(paint, rect); context->drawRect(paint, rect);
return dst; return dst;
} }
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
GrBlendEffect::GrBlendEffect(SkBlendImageFilter::Mode mode, GrTexture* foreground) GrBlendEffect::GrBlendEffect(SkBlendImageFilter::Mode mode,
: INHERITED(foreground), fMode(mode) { GrTexture* foreground,
const SkMatrix& matrix)
: INHERITED(foreground, matrix), fMode(mode) {
} }
GrBlendEffect::~GrBlendEffect() { GrBlendEffect::~GrBlendEffect() {
@ -227,8 +233,7 @@ GrBlendEffect::~GrBlendEffect() {
bool GrBlendEffect::isEqual(const GrEffect& sBase) const { bool GrBlendEffect::isEqual(const GrEffect& sBase) const {
const GrBlendEffect& s = static_cast<const GrBlendEffect&>(sBase); const GrBlendEffect& s = static_cast<const GrBlendEffect&>(sBase);
return INHERITED::isEqual(sBase) && return INHERITED::isEqual(sBase) && fMode == s.fMode;
fMode == s.fMode;
} }
const GrBackendEffectFactory& GrBlendEffect::getFactory() const { const GrBackendEffectFactory& GrBlendEffect::getFactory() const {
@ -241,6 +246,7 @@ GrGLBlendEffect::GrGLBlendEffect(const GrBackendEffectFactory& factory,
const GrEffect& effect) const GrEffect& effect)
: INHERITED(factory), : INHERITED(factory),
fMode(static_cast<const GrBlendEffect&>(effect).mode()) { fMode(static_cast<const GrBlendEffect&>(effect).mode()) {
fRequiresTextureMatrix = false;
} }
GrGLBlendEffect::~GrGLBlendEffect() { GrGLBlendEffect::~GrGLBlendEffect() {
@ -248,16 +254,19 @@ GrGLBlendEffect::~GrGLBlendEffect() {
void GrGLBlendEffect::emitCode(GrGLShaderBuilder* builder, void GrGLBlendEffect::emitCode(GrGLShaderBuilder* builder,
const GrEffectStage&, const GrEffectStage&,
EffectKey, EffectKey key,
const char* vertexCoords, const char* vertexCoords,
const char* outputColor, const char* outputColor,
const char* inputColor, const char* inputColor,
const TextureSamplerArray& samplers) { const TextureSamplerArray& samplers) {
const char* coords;
GrSLType coordsType = fEffectMatrix.emitCode(builder, key, vertexCoords, &coords);
SkString* code = &builder->fFSCode; SkString* code = &builder->fFSCode;
const char* bgColor = inputColor; const char* bgColor = inputColor;
const char* fgColor = "fgColor"; const char* fgColor = "fgColor";
code->appendf("\t\tvec4 %s = ", fgColor); code->appendf("\t\tvec4 %s = ", fgColor);
builder->appendTextureLookup(code, samplers[0]); builder->appendTextureLookup(code, samplers[0], coords, coordsType);
code->append(";\n"); code->append(";\n");
code->appendf("\t\t%s.a = 1.0 - (1.0 - %s.a) * (1.0 - %s.b);\n", outputColor, bgColor, fgColor); code->appendf("\t\t%s.a = 1.0 - (1.0 - %s.a) * (1.0 - %s.b);\n", outputColor, bgColor, fgColor);
switch (fMode) { switch (fMode) {
@ -279,7 +288,16 @@ void GrGLBlendEffect::emitCode(GrGLShaderBuilder* builder,
} }
} }
GrGLEffect::EffectKey GrGLBlendEffect::GenKey(const GrEffectStage& s, const GrGLCaps&) { void GrGLBlendEffect::setData(const GrGLUniformManager& uman, const GrEffectStage& stage) {
return static_cast<const GrBlendEffect&>(*s.getEffect()).mode(); const GrBlendEffect& blend = static_cast<const GrBlendEffect&>(*stage.getEffect());
fEffectMatrix.setData(uman, blend.getMatrix(), stage.getCoordChangeMatrix(), blend.texture(0));
}
GrGLEffect::EffectKey GrGLBlendEffect::GenKey(const GrEffectStage& stage, const GrGLCaps&) {
const GrBlendEffect& blend = static_cast<const GrBlendEffect&>(*stage.getEffect());
EffectKey key =
GrGLEffectMatrix::GenKey(blend.getMatrix(), stage.getCoordChangeMatrix(), blend.texture(0));
key |= (blend.mode() << GrGLEffectMatrix::kKeyBits);
return key;
} }
#endif #endif

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

@ -350,6 +350,8 @@ public:
: INHERITED(factory) : INHERITED(factory)
, fMatrixHandle(GrGLUniformManager::kInvalidUniformHandle) , fMatrixHandle(GrGLUniformManager::kInvalidUniformHandle)
, fVectorHandle(GrGLUniformManager::kInvalidUniformHandle) { , fVectorHandle(GrGLUniformManager::kInvalidUniformHandle) {
// no texture
fRequiresTextureMatrix = false;
} }
virtual void emitCode(GrGLShaderBuilder* builder, virtual void emitCode(GrGLShaderBuilder* builder,

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

@ -678,7 +678,9 @@ SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_END
GrGLGradientEffect::GrGLGradientEffect(const GrBackendEffectFactory& factory) GrGLGradientEffect::GrGLGradientEffect(const GrBackendEffectFactory& factory)
: INHERITED(factory) : INHERITED(factory)
, fCachedYCoord(GR_ScalarMax) , fCachedYCoord(GR_ScalarMax)
, fFSYUni(GrGLUniformManager::kInvalidUniformHandle) { } , fFSYUni(GrGLUniformManager::kInvalidUniformHandle) {
fRequiresTextureMatrix = false;
}
GrGLGradientEffect::~GrGLGradientEffect() { } GrGLGradientEffect::~GrGLGradientEffect() { }
@ -688,13 +690,37 @@ void GrGLGradientEffect::emitYCoordUniform(GrGLShaderBuilder* builder) {
} }
void GrGLGradientEffect::setData(const GrGLUniformManager& uman, const GrEffectStage& stage) { void GrGLGradientEffect::setData(const GrGLUniformManager& uman, const GrEffectStage& stage) {
GrScalar yCoord = static_cast<const GrGradientEffect&>(*stage.getEffect()).getYCoord(); const GrGradientEffect& e = static_cast<const GrGradientEffect&>(*stage.getEffect());
const GrTexture* texture = e.texture(0);
fEffectMatrix.setData(uman, e.getMatrix(), stage.getCoordChangeMatrix(), texture);
GrScalar yCoord = e.getYCoord();
if (yCoord != fCachedYCoord) { if (yCoord != fCachedYCoord) {
uman.set1f(fFSYUni, yCoord); uman.set1f(fFSYUni, yCoord);
fCachedYCoord = yCoord; fCachedYCoord = yCoord;
} }
} }
GrGLEffect::EffectKey GrGLGradientEffect::GenMatrixKey(const GrEffectStage& s) {
const GrGradientEffect& e = static_cast<const GrGradientEffect&>(*s.getEffect());
const GrTexture* texture = e.texture(0);
return GrGLEffectMatrix::GenKey(e.getMatrix(), s.getCoordChangeMatrix(), texture);
}
void GrGLGradientEffect::setupMatrix(GrGLShaderBuilder* builder,
EffectKey key,
const char* vertexCoords,
const char** fsCoordName,
const char** vsVaryingName,
GrSLType* vsVaryingType) {
fEffectMatrix.emitCodeMakeFSCoords2D(builder,
key & kMatrixKeyMask,
vertexCoords,
fsCoordName,
vsVaryingName,
vsVaryingType);
}
void GrGLGradientEffect::emitColorLookup(GrGLShaderBuilder* builder, void GrGLGradientEffect::emitColorLookup(GrGLShaderBuilder* builder,
const char* gradientTValue, const char* gradientTValue,
const char* outputColor, const char* outputColor,
@ -714,6 +740,7 @@ void GrGLGradientEffect::emitColorLookup(GrGLShaderBuilder* builder,
GrGradientEffect::GrGradientEffect(GrContext* ctx, GrGradientEffect::GrGradientEffect(GrContext* ctx,
const SkGradientShaderBase& shader, const SkGradientShaderBase& shader,
const SkMatrix& matrix,
SkShader::TileMode tileMode) SkShader::TileMode tileMode)
: INHERITED(1) { : INHERITED(1) {
// TODO: check for simple cases where we don't need a texture: // TODO: check for simple cases where we don't need a texture:
@ -721,6 +748,8 @@ GrGradientEffect::GrGradientEffect(GrContext* ctx,
//shader.asAGradient(&info); //shader.asAGradient(&info);
//if (info.fColorCount == 2) { ... //if (info.fColorCount == 2) { ...
fMatrix = matrix;
SkBitmap bitmap; SkBitmap bitmap;
shader.getGradientTableBitmap(&bitmap); shader.getGradientTableBitmap(&bitmap);

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

@ -193,12 +193,13 @@ private:
#if SK_SUPPORT_GPU #if SK_SUPPORT_GPU
#include "gl/GrGLEffect.h" #include "gl/GrGLEffect.h"
#include "gl/GrGLEffectMatrix.h"
class GrEffectStage; class GrEffectStage;
class GrBackendEffectFactory; class GrBackendEffectFactory;
/* /*
* The intepretation of the texture matrix depends on the sample mode. The * The interpretation of the texture matrix depends on the sample mode. The
* texture matrix is applied both when the texture coordinates are explicit * texture matrix is applied both when the texture coordinates are explicit
* and when vertex positions are used as texture coordinates. In the latter * and when vertex positions are used as texture coordinates. In the latter
* case the texture matrix is applied to the pre-view-matrix position * case the texture matrix is applied to the pre-view-matrix position
@ -228,6 +229,7 @@ public:
GrGradientEffect(GrContext* ctx, GrGradientEffect(GrContext* ctx,
const SkGradientShaderBase& shader, const SkGradientShaderBase& shader,
const SkMatrix& matrix,
SkShader::TileMode tileMode); SkShader::TileMode tileMode);
virtual ~GrGradientEffect(); virtual ~GrGradientEffect();
@ -236,11 +238,12 @@ public:
bool useAtlas() const { return SkToBool(-1 != fRow); } bool useAtlas() const { return SkToBool(-1 != fRow); }
GrScalar getYCoord() const { return fYCoord; }; GrScalar getYCoord() const { return fYCoord; };
const SkMatrix& getMatrix() const { return fMatrix;}
virtual bool isEqual(const GrEffect& effect) const SK_OVERRIDE { virtual bool isEqual(const GrEffect& effect) const SK_OVERRIDE {
const GrGradientEffect& s = static_cast<const GrGradientEffect&>(effect); const GrGradientEffect& s = static_cast<const GrGradientEffect&>(effect);
return INHERITED::isEqual(effect) && this->useAtlas() == s.useAtlas() && return INHERITED::isEqual(effect) && this->useAtlas() == s.useAtlas() &&
fYCoord == s.getYCoord(); fYCoord == s.getYCoord() && fMatrix.cheapEqualTo(s.getMatrix());
} }
protected: protected:
@ -263,6 +266,7 @@ private:
GrScalar fYCoord; GrScalar fYCoord;
GrTextureStripAtlas* fAtlas; GrTextureStripAtlas* fAtlas;
int fRow; int fRow;
SkMatrix fMatrix;
typedef GrEffect INHERITED; typedef GrEffect INHERITED;
@ -279,6 +283,36 @@ public:
virtual void setData(const GrGLUniformManager&, const GrEffectStage&) SK_OVERRIDE; virtual void setData(const GrGLUniformManager&, const GrEffectStage&) SK_OVERRIDE;
protected: protected:
/**
* Subclasses must reserve the lower kMatrixKeyBitCnt of their key for use by
* GrGLGradientEffect.
*/
enum {
kMatrixKeyBitCnt = GrGLEffectMatrix::kKeyBits,
kMatrixKeyMask = (1 << kMatrixKeyBitCnt) - 1,
};
/**
* Subclasses must call this. It will return a value restricted to the lower kMatrixKeyBitCnt
* bits.
*/
static EffectKey GenMatrixKey(const GrEffectStage& s);
/**
* Inserts code to implement the GrGradientEffect's matrix. This should be called before a
* subclass emits its own code. The name of the 2D coords is output via fsCoordName and already
* incorporates any perspective division. The caller can also optionally retrieve the name of
* the varying inserted in the VS and its type, which may be either vec2f or vec3f depending
* upon whether the matrix has perspective or not. It is not necessary to mask the key before
* calling.
*/
void setupMatrix(GrGLShaderBuilder* builder,
EffectKey key,
const char* vertexCoords,
const char** fsCoordName,
const char** vsVaryingName = NULL,
GrSLType* vsVaryingType = NULL);
// Emits the uniform used as the y-coord to texture samples in derived classes. Subclasses // Emits the uniform used as the y-coord to texture samples in derived classes. Subclasses
// should call this method from their emitCode(). // should call this method from their emitCode().
void emitYCoordUniform(GrGLShaderBuilder* builder); void emitYCoordUniform(GrGLShaderBuilder* builder);
@ -295,6 +329,7 @@ protected:
private: private:
GrScalar fCachedYCoord; GrScalar fCachedYCoord;
GrGLUniformManager::UniformHandle fFSYUni; GrGLUniformManager::UniformHandle fFSYUni;
GrGLEffectMatrix fEffectMatrix;
typedef GrGLEffect INHERITED; typedef GrGLEffect INHERITED;
}; };

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

@ -495,7 +495,9 @@ public:
const char* inputColor, const char* inputColor,
const TextureSamplerArray&) SK_OVERRIDE; const TextureSamplerArray&) SK_OVERRIDE;
static EffectKey GenKey(const GrEffectStage&, const GrGLCaps& caps) { return 0; } static EffectKey GenKey(const GrEffectStage& stage, const GrGLCaps&) {
return GenMatrixKey(stage);
}
private: private:
@ -507,8 +509,11 @@ private:
class GrLinearGradient : public GrGradientEffect { class GrLinearGradient : public GrGradientEffect {
public: public:
GrLinearGradient(GrContext* ctx, const SkLinearGradient& shader, SkShader::TileMode tm) GrLinearGradient(GrContext* ctx,
: INHERITED(ctx, shader, tm) { } const SkLinearGradient& shader,
const SkMatrix& matrix,
SkShader::TileMode tm)
: INHERITED(ctx, shader, matrix, tm) { }
virtual ~GrLinearGradient() { } virtual ~GrLinearGradient() { }
static const char* Name() { return "Linear Gradient"; } static const char* Name() { return "Linear Gradient"; }
@ -553,15 +558,18 @@ GrEffect* GrLinearGradient::TestCreate(SkRandom* random,
///////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////
void GrGLLinearGradient::emitCode(GrGLShaderBuilder* builder, void GrGLLinearGradient::emitCode(GrGLShaderBuilder* builder,
const GrEffectStage&, const GrEffectStage& stage,
EffectKey, EffectKey key,
const char* vertexCoords, const char* vertexCoords,
const char* outputColor, const char* outputColor,
const char* inputColor, const char* inputColor,
const TextureSamplerArray& samplers) { const TextureSamplerArray& samplers) {
this->emitYCoordUniform(builder); this->emitYCoordUniform(builder);
const char* coords;
this->setupMatrix(builder, key, vertexCoords, &coords);
SkString t; SkString t;
t.printf("%s.x", builder->defaultTexCoordsName()); t.append(coords);
t.append(".x");
this->emitColorLookup(builder, t.c_str(), outputColor, inputColor, samplers[0]); this->emitColorLookup(builder, t.c_str(), outputColor, inputColor, samplers[0]);
} }
@ -574,7 +582,7 @@ bool SkLinearGradient::asNewEffect(GrContext* context, GrEffectStage* stage) con
return false; return false;
} }
matrix.postConcat(fPtsToUnit); matrix.postConcat(fPtsToUnit);
stage->setEffect(SkNEW_ARGS(GrLinearGradient, (context, *this, fTileMode)), matrix)->unref(); stage->setEffect(SkNEW_ARGS(GrLinearGradient, (context, *this, matrix, fTileMode)))->unref();
return true; return true;
} }

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

@ -490,7 +490,9 @@ public:
const char* inputColor, const char* inputColor,
const TextureSamplerArray&) SK_OVERRIDE; const TextureSamplerArray&) SK_OVERRIDE;
static EffectKey GenKey(const GrEffectStage&, const GrGLCaps& caps) { return 0; } static EffectKey GenKey(const GrEffectStage& stage, const GrGLCaps&) {
return GenMatrixKey(stage);
}
private: private:
@ -503,8 +505,11 @@ private:
class GrRadialGradient : public GrGradientEffect { class GrRadialGradient : public GrGradientEffect {
public: public:
GrRadialGradient(GrContext* ctx, const SkRadialGradient& shader, SkShader::TileMode tm) GrRadialGradient(GrContext* ctx,
: INHERITED(ctx, shader, tm) { const SkRadialGradient& shader,
const SkMatrix& matrix,
SkShader::TileMode tm)
: INHERITED(ctx, shader, matrix, tm) {
} }
virtual ~GrRadialGradient() { } virtual ~GrRadialGradient() { }
@ -551,15 +556,18 @@ GrEffect* GrRadialGradient::TestCreate(SkRandom* random,
///////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////
void GrGLRadialGradient::emitCode(GrGLShaderBuilder* builder, void GrGLRadialGradient::emitCode(GrGLShaderBuilder* builder,
const GrEffectStage&, const GrEffectStage& stage,
EffectKey, EffectKey key,
const char* vertexCoords, const char* vertexCoords,
const char* outputColor, const char* outputColor,
const char* inputColor, const char* inputColor,
const TextureSamplerArray& samplers) { const TextureSamplerArray& samplers) {
this->emitYCoordUniform(builder); this->emitYCoordUniform(builder);
SkString t; const char* coords;
t.printf("length(%s.xy)", builder->defaultTexCoordsName()); this->setupMatrix(builder, key, vertexCoords, &coords);
SkString t("length(");
t.append(coords);
t.append(")");
this->emitColorLookup(builder, t.c_str(), outputColor, inputColor, samplers[0]); this->emitColorLookup(builder, t.c_str(), outputColor, inputColor, samplers[0]);
} }
@ -573,7 +581,7 @@ bool SkRadialGradient::asNewEffect(GrContext* context, GrEffectStage* stage) con
return false; return false;
} }
matrix.postConcat(fPtsToUnit); matrix.postConcat(fPtsToUnit);
stage->setEffect(SkNEW_ARGS(GrRadialGradient, (context, *this, fTileMode)), matrix)->unref(); stage->setEffect(SkNEW_ARGS(GrRadialGradient, (context, *this, matrix, fTileMode)))->unref();
return true; return true;
} }

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

@ -399,7 +399,9 @@ public:
const char* inputColor, const char* inputColor,
const TextureSamplerArray&) SK_OVERRIDE; const TextureSamplerArray&) SK_OVERRIDE;
static EffectKey GenKey(const GrEffectStage&, const GrGLCaps& caps) { return 0; } static EffectKey GenKey(const GrEffectStage& stage, const GrGLCaps&) {
return GenMatrixKey(stage);
}
private: private:
@ -413,8 +415,9 @@ class GrSweepGradient : public GrGradientEffect {
public: public:
GrSweepGradient(GrContext* ctx, GrSweepGradient(GrContext* ctx,
const SkSweepGradient& shader) const SkSweepGradient& shader,
: INHERITED(ctx, shader, SkShader::kClamp_TileMode) { } const SkMatrix& matrix)
: INHERITED(ctx, shader, matrix, SkShader::kClamp_TileMode) { }
virtual ~GrSweepGradient() { } virtual ~GrSweepGradient() { }
static const char* Name() { return "Sweep Gradient"; } static const char* Name() { return "Sweep Gradient"; }
@ -457,16 +460,17 @@ GrEffect* GrSweepGradient::TestCreate(SkRandom* random,
///////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////
void GrGLSweepGradient::emitCode(GrGLShaderBuilder* builder, void GrGLSweepGradient::emitCode(GrGLShaderBuilder* builder,
const GrEffectStage&, const GrEffectStage& stage,
EffectKey, EffectKey key,
const char* vertexCoords, const char* vertexCoords,
const char* outputColor, const char* outputColor,
const char* inputColor, const char* inputColor,
const TextureSamplerArray& samplers) { const TextureSamplerArray& samplers) {
this->emitYCoordUniform(builder); this->emitYCoordUniform(builder);
const char* coords;
this->setupMatrix(builder, key, vertexCoords, &coords);
SkString t; SkString t;
t.printf("atan(- %s.y, - %s.x) * 0.1591549430918 + 0.5", t.printf("atan(- %s.y, - %s.x) * 0.1591549430918 + 0.5", coords, coords);
builder->defaultTexCoordsName(), builder->defaultTexCoordsName());
this->emitColorLookup(builder, t.c_str(), outputColor, inputColor, samplers[0]); this->emitColorLookup(builder, t.c_str(), outputColor, inputColor, samplers[0]);
} }
@ -478,7 +482,7 @@ bool SkSweepGradient::asNewEffect(GrContext* context, GrEffectStage* stage) cons
return false; return false;
} }
matrix.postConcat(fPtsToUnit); matrix.postConcat(fPtsToUnit);
stage->setEffect(SkNEW_ARGS(GrSweepGradient, (context, *this)), matrix)->unref(); stage->setEffect(SkNEW_ARGS(GrSweepGradient, (context, *this, matrix)))->unref();
return true; return true;
} }

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

@ -371,8 +371,9 @@ public:
GrConical2Gradient(GrContext* ctx, GrConical2Gradient(GrContext* ctx,
const SkTwoPointConicalGradient& shader, const SkTwoPointConicalGradient& shader,
const SkMatrix& matrix,
SkShader::TileMode tm) SkShader::TileMode tm)
: INHERITED(ctx, shader, tm) : INHERITED(ctx, shader, matrix, tm)
, fCenterX1(shader.getCenterX1()) , fCenterX1(shader.getCenterX1())
, fRadius0(shader.getStartRadius()) , fRadius0(shader.getStartRadius())
, fDiffRadius(shader.getDiffRadius()) { } , fDiffRadius(shader.getDiffRadius()) { }
@ -468,12 +469,17 @@ GrGLConical2Gradient::GrGLConical2Gradient(
} }
void GrGLConical2Gradient::emitCode(GrGLShaderBuilder* builder, void GrGLConical2Gradient::emitCode(GrGLShaderBuilder* builder,
const GrEffectStage&, const GrEffectStage& stage,
EffectKey, EffectKey key,
const char* vertexCoords, const char* vertexCoords,
const char* outputColor, const char* outputColor,
const char* inputColor, const char* inputColor,
const TextureSamplerArray& samplers) { const TextureSamplerArray& samplers) {
const char* fsCoords;
const char* vsCoordsVarying;
GrSLType coordsVaryingType;
this->setupMatrix(builder, key, vertexCoords, &fsCoords, &vsCoordsVarying, &coordsVaryingType);
this->emitYCoordUniform(builder); this->emitYCoordUniform(builder);
// 2 copies of uniform array, 1 for each of vertex & fragment shader, // 2 copies of uniform array, 1 for each of vertex & fragment shader,
// to work around Xoom bug. Doesn't seem to cause performance decrease // to work around Xoom bug. Doesn't seem to cause performance decrease
@ -485,7 +491,7 @@ void GrGLConical2Gradient::emitCode(GrGLShaderBuilder* builder,
// For radial gradients without perspective we can pass the linear // For radial gradients without perspective we can pass the linear
// part of the quadratic as a varying. // part of the quadratic as a varying.
if (!builder->defaultTextureMatrixIsPerspective()) { if (kVec2f_GrSLType == coordsVaryingType) {
builder->addVarying(kFloat_GrSLType, "Conical2BCoeff", builder->addVarying(kFloat_GrSLType, "Conical2BCoeff",
&fVSVaryingName, &fFSVaryingName); &fVSVaryingName, &fFSVaryingName);
} }
@ -502,11 +508,11 @@ void GrGLConical2Gradient::emitCode(GrGLShaderBuilder* builder,
// For radial gradients without perspective we can pass the linear // For radial gradients without perspective we can pass the linear
// part of the quadratic as a varying. // part of the quadratic as a varying.
if (!builder->defaultTextureMatrixIsPerspective()) { if (kVec2f_GrSLType == coordsVaryingType) {
// r2Var = -2 * (r2Parm[2] * varCoord.x - r2Param[3] * r2Param[5]) // r2Var = -2 * (r2Parm[2] * varCoord.x - r2Param[3] * r2Param[5])
code->appendf("\t%s = -2.0 * (%s * %s.x + %s * %s);\n", code->appendf("\t%s = -2.0 * (%s * %s.x + %s * %s);\n",
fVSVaryingName, p2.c_str(), fVSVaryingName, p2.c_str(),
vertexCoords, p3.c_str(), p5.c_str()); vsCoordsVarying, p3.c_str(), p5.c_str());
} }
} }
@ -538,12 +544,12 @@ void GrGLConical2Gradient::emitCode(GrGLShaderBuilder* builder,
// If we we're able to interpolate the linear component, // If we we're able to interpolate the linear component,
// bVar is the varying; otherwise compute it // bVar is the varying; otherwise compute it
SkString bVar; SkString bVar;
if (!builder->defaultTextureMatrixIsPerspective()) { if (kVec2f_GrSLType == coordsVaryingType) {
bVar = fFSVaryingName; bVar = fFSVaryingName;
} else { } else {
bVar = "b"; bVar = "b";
code->appendf("\tfloat %s = -2.0 * (%s * %s.x + %s * %s);\n", code->appendf("\tfloat %s = -2.0 * (%s * %s.x + %s * %s);\n",
bVar.c_str(), p2.c_str(), builder->defaultTexCoordsName(), bVar.c_str(), p2.c_str(), fsCoords,
p3.c_str(), p5.c_str()); p3.c_str(), p5.c_str());
} }
@ -553,7 +559,7 @@ void GrGLConical2Gradient::emitCode(GrGLShaderBuilder* builder,
// c = (x^2)+(y^2) - params[4] // c = (x^2)+(y^2) - params[4]
code->appendf("\tfloat %s = dot(%s, %s) - %s;\n", cName.c_str(), code->appendf("\tfloat %s = dot(%s, %s) - %s;\n", cName.c_str(),
builder->defaultTexCoordsName(), builder->defaultTexCoordsName(), fsCoords, fsCoords,
p4.c_str()); p4.c_str());
// Non-degenerate case (quadratic) // Non-degenerate case (quadratic)
@ -669,7 +675,15 @@ void GrGLConical2Gradient::setData(const GrGLUniformManager& uman, const GrEffec
} }
GrGLEffect::EffectKey GrGLConical2Gradient::GenKey(const GrEffectStage& s, const GrGLCaps&) { GrGLEffect::EffectKey GrGLConical2Gradient::GenKey(const GrEffectStage& s, const GrGLCaps&) {
return (static_cast<const GrConical2Gradient&>(*s.getEffect()).isDegenerate()); enum {
kIsDegenerate = 1 << kMatrixKeyBitCnt,
};
EffectKey key = GenMatrixKey(s);
if (static_cast<const GrConical2Gradient&>(*s.getEffect()).isDegenerate()) {
key |= kIsDegenerate;
}
return key;
} }
///////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////
@ -695,7 +709,7 @@ bool SkTwoPointConicalGradient::asNewEffect(GrContext* context,
matrix.postConcat(rot); matrix.postConcat(rot);
} }
stage->setEffect(SkNEW_ARGS(GrConical2Gradient, (context, *this, fTileMode)), matrix)->unref(); stage->setEffect(SkNEW_ARGS(GrConical2Gradient, (context, *this, matrix, fTileMode)))->unref();
return true; return true;
} }

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

@ -404,8 +404,11 @@ private:
class GrRadial2Gradient : public GrGradientEffect { class GrRadial2Gradient : public GrGradientEffect {
public: public:
GrRadial2Gradient(GrContext* ctx, const SkTwoPointRadialGradient& shader, SkShader::TileMode tm) GrRadial2Gradient(GrContext* ctx,
: INHERITED(ctx, shader, tm) const SkTwoPointRadialGradient& shader,
const SkMatrix& matrix,
SkShader::TileMode tm)
: INHERITED(ctx, shader, matrix, tm)
, fCenterX1(shader.getCenterX1()) , fCenterX1(shader.getCenterX1())
, fRadius0(shader.getStartRadius()) , fRadius0(shader.getStartRadius())
, fPosRoot(shader.getDiffRadius() < 0) { } , fPosRoot(shader.getDiffRadius() < 0) { }
@ -501,14 +504,19 @@ GrGLRadial2Gradient::GrGLRadial2Gradient(
} }
void GrGLRadial2Gradient::emitCode(GrGLShaderBuilder* builder, void GrGLRadial2Gradient::emitCode(GrGLShaderBuilder* builder,
const GrEffectStage&, const GrEffectStage& stage,
EffectKey, EffectKey key,
const char* vertexCoords, const char* vertexCoords,
const char* outputColor, const char* outputColor,
const char* inputColor, const char* inputColor,
const TextureSamplerArray& samplers) { const TextureSamplerArray& samplers) {
this->emitYCoordUniform(builder); this->emitYCoordUniform(builder);
const char* fsCoords;
const char* vsCoordsVarying;
GrSLType coordsVaryingType;
this->setupMatrix(builder, key, vertexCoords, &fsCoords, &vsCoordsVarying, &coordsVaryingType);
// 2 copies of uniform array, 1 for each of vertex & fragment shader, // 2 copies of uniform array, 1 for each of vertex & fragment shader,
// to work around Xoom bug. Doesn't seem to cause performance decrease // to work around Xoom bug. Doesn't seem to cause performance decrease
// in test apps, but need to keep an eye on it. // in test apps, but need to keep an eye on it.
@ -519,9 +527,8 @@ void GrGLRadial2Gradient::emitCode(GrGLShaderBuilder* builder,
// For radial gradients without perspective we can pass the linear // For radial gradients without perspective we can pass the linear
// part of the quadratic as a varying. // part of the quadratic as a varying.
if (!builder->defaultTextureMatrixIsPerspective()) { if (kVec2f_GrSLType == coordsVaryingType) {
builder->addVarying(kFloat_GrSLType, "Radial2BCoeff", builder->addVarying(kFloat_GrSLType, "Radial2BCoeff", &fVSVaryingName, &fFSVaryingName);
&fVSVaryingName, &fFSVaryingName);
} }
// VS // VS
@ -534,11 +541,11 @@ void GrGLRadial2Gradient::emitCode(GrGLShaderBuilder* builder,
// For radial gradients without perspective we can pass the linear // For radial gradients without perspective we can pass the linear
// part of the quadratic as a varying. // part of the quadratic as a varying.
if (!builder->defaultTextureMatrixIsPerspective()) { if (kVec2f_GrSLType == coordsVaryingType) {
// r2Var = 2 * (r2Parm[2] * varCoord.x - r2Param[3]) // r2Var = 2 * (r2Parm[2] * varCoord.x - r2Param[3])
code->appendf("\t%s = 2.0 *(%s * %s.x - %s);\n", code->appendf("\t%s = 2.0 *(%s * %s.x - %s);\n",
fVSVaryingName, p2.c_str(), fVSVaryingName, p2.c_str(),
vertexCoords, p3.c_str()); vsCoordsVarying, p3.c_str());
} }
} }
@ -565,20 +572,19 @@ void GrGLRadial2Gradient::emitCode(GrGLShaderBuilder* builder,
// If we we're able to interpolate the linear component, // If we we're able to interpolate the linear component,
// bVar is the varying; otherwise compute it // bVar is the varying; otherwise compute it
SkString bVar; SkString bVar;
if (!builder->defaultTextureMatrixIsPerspective()) { if (kVec2f_GrSLType == coordsVaryingType) {
bVar = fFSVaryingName; bVar = fFSVaryingName;
} else { } else {
bVar = "b"; bVar = "b";
code->appendf("\tfloat %s = 2.0 * (%s * %s.x - %s);\n", code->appendf("\tfloat %s = 2.0 * (%s * %s.x - %s);\n",
bVar.c_str(), p2.c_str(), bVar.c_str(), p2.c_str(), fsCoords, p3.c_str());
builder->defaultTexCoordsName(), p3.c_str());
} }
// c = (x^2)+(y^2) - params[4] // c = (x^2)+(y^2) - params[4]
code->appendf("\tfloat %s = dot(%s, %s) - %s;\n", code->appendf("\tfloat %s = dot(%s, %s) - %s;\n",
cName.c_str(), cName.c_str(),
builder->defaultTexCoordsName(), fsCoords,
builder->defaultTexCoordsName(), fsCoords,
p4.c_str()); p4.c_str());
// If we aren't degenerate, emit some extra code, and accept a slightly // If we aren't degenerate, emit some extra code, and accept a slightly
@ -643,7 +649,15 @@ void GrGLRadial2Gradient::setData(const GrGLUniformManager& uman, const GrEffect
} }
GrGLEffect::EffectKey GrGLRadial2Gradient::GenKey(const GrEffectStage& s, const GrGLCaps&) { GrGLEffect::EffectKey GrGLRadial2Gradient::GenKey(const GrEffectStage& s, const GrGLCaps&) {
return (static_cast<const GrRadial2Gradient&>(*s.getEffect()).isDegenerate()); enum {
kIsDegenerate = 1 << kMatrixKeyBitCnt,
};
EffectKey key = GenMatrixKey(s);
if (static_cast<const GrRadial2Gradient&>(*s.getEffect()).isDegenerate()) {
key |= kIsDegenerate;
}
return key;
} }
///////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////
@ -667,7 +681,7 @@ bool SkTwoPointRadialGradient::asNewEffect(GrContext* context,
matrix.postConcat(rot); matrix.postConcat(rot);
} }
stage->setEffect(SkNEW_ARGS(GrRadial2Gradient, (context, *this, fTileMode)), matrix)->unref(); stage->setEffect(SkNEW_ARGS(GrRadial2Gradient, (context, *this, matrix, fTileMode)))->unref();
return true; return true;
} }

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

@ -1307,35 +1307,44 @@ bool GrContext::readRenderTargetPixels(GrRenderTarget* target,
ast.set(this, desc, match); ast.set(this, desc, match);
GrTexture* texture = ast.texture(); GrTexture* texture = ast.texture();
if (texture) { if (texture) {
SkAutoTUnref<GrEffect> effect; GrEffectStage stage;
// compute a matrix to perform the draw
GrMatrix textureMatrix;
if (flipY) {
textureMatrix.setTranslate(SK_Scalar1 * left,
SK_Scalar1 * (top + height));
textureMatrix.set(GrMatrix::kMScaleY, -GR_Scalar1);
} else {
textureMatrix.setTranslate(SK_Scalar1 *left, SK_Scalar1 *top);
}
textureMatrix.postIDiv(src->width(), src->height());
bool effectInstalled = false;
if (unpremul) { if (unpremul) {
effect.reset(this->createPMToUPMEffect(src, swapRAndB)); if (this->installPMToUPMEffect(src, swapRAndB, textureMatrix, &stage)) {
effectInstalled = true;
unpremul = false; // we no longer need to do this on CPU after the readback.
}
} }
// If we failed to create a PM->UPM effect and have no other conversions to perform then // If we failed to create a PM->UPM effect and have no other conversions to perform then
// there is no longer any point to using the scratch. // there is no longer any point to using the scratch.
if (NULL != effect || flipY || swapRAndB) { if (effectInstalled || flipY || swapRAndB) {
if (NULL == effect) { if (!effectInstalled) {
effect.reset(GrConfigConversionEffect::Create(src, swapRAndB)); SkAssertResult(GrConfigConversionEffect::InstallEffect(
GrAssert(NULL != effect); src,
} else { swapRAndB,
unpremul = false; // we will handle the UPM conversion in the draw GrConfigConversionEffect::kNone_PMConversion,
textureMatrix,
&stage));
} }
swapRAndB = false; // we will handle the swap in the draw. swapRAndB = false; // we will handle the swap in the draw.
flipY = false; // we already incorporated the y flip in the matrix
GrDrawTarget::AutoStateRestore asr(fGpu, GrDrawTarget::kReset_ASRInit); GrDrawTarget::AutoStateRestore asr(fGpu, GrDrawTarget::kReset_ASRInit);
GrDrawState* drawState = fGpu->drawState(); GrDrawState* drawState = fGpu->drawState();
*drawState->stage(0) = stage;
drawState->setRenderTarget(texture->asRenderTarget()); drawState->setRenderTarget(texture->asRenderTarget());
GrMatrix matrix;
if (flipY) {
matrix.setTranslate(SK_Scalar1 * left,
SK_Scalar1 * (top + height));
matrix.set(GrMatrix::kMScaleY, -GR_Scalar1);
flipY = false; // the y flip will be handled in the draw
} else {
matrix.setTranslate(SK_Scalar1 *left, SK_Scalar1 *top);
}
matrix.postIDiv(src->width(), src->height());
drawState->stage(0)->setEffect(effect, matrix);
GrRect rect = GrRect::MakeWH(GrIntToScalar(width), GrIntToScalar(height)); GrRect rect = GrRect::MakeWH(GrIntToScalar(width), GrIntToScalar(height));
fGpu->drawSimpleRect(rect, NULL); fGpu->drawSimpleRect(rect, NULL);
// we want to read back from the scratch's origin // we want to read back from the scratch's origin
@ -1350,7 +1359,7 @@ bool GrContext::readRenderTargetPixels(GrRenderTarget* target,
readConfig, buffer, rowBytes, readUpsideDown)) { readConfig, buffer, rowBytes, readUpsideDown)) {
return false; return false;
} }
// Perform any conversions we weren't able to perfom using a scratch texture. // Perform any conversions we weren't able to perform using a scratch texture.
if (unpremul || swapRAndB || flipY) { if (unpremul || swapRAndB || flipY) {
// These are initialized to suppress a warning // These are initialized to suppress a warning
SkCanvas::Config8888 srcC8888 = SkCanvas::kNative_Premul_Config8888; SkCanvas::Config8888 srcC8888 = SkCanvas::kNative_Premul_Config8888;
@ -1480,7 +1489,7 @@ void GrContext::writeRenderTargetPixels(GrRenderTarget* target,
return; return;
} }
#endif #endif
SkAutoTUnref<GrEffect> effect;
bool swapRAndB = (fGpu->preferredReadPixelsConfig(config) == GrPixelConfigSwapRAndB(config)); bool swapRAndB = (fGpu->preferredReadPixelsConfig(config) == GrPixelConfigSwapRAndB(config));
GrPixelConfig textureConfig; GrPixelConfig textureConfig;
@ -1499,15 +1508,24 @@ void GrContext::writeRenderTargetPixels(GrRenderTarget* target,
if (NULL == texture) { if (NULL == texture) {
return; return;
} }
GrEffectStage stage;
GrMatrix textureMatrix;
textureMatrix.setIDiv(texture->width(), texture->height());
// allocate a tmp buffer and sw convert the pixels to premul // allocate a tmp buffer and sw convert the pixels to premul
SkAutoSTMalloc<128 * 128, uint32_t> tmpPixels(0); SkAutoSTMalloc<128 * 128, uint32_t> tmpPixels(0);
bool effectInstalled = false;
if (kUnpremul_PixelOpsFlag & flags) { if (kUnpremul_PixelOpsFlag & flags) {
if (kRGBA_8888_GrPixelConfig != config && kBGRA_8888_GrPixelConfig != config) { if (kRGBA_8888_GrPixelConfig != config && kBGRA_8888_GrPixelConfig != config) {
return; return;
} }
effect.reset(this->createUPMToPMEffect(texture, swapRAndB)); effectInstalled = this->installUPMToPMEffect(texture,
if (NULL == effect) { swapRAndB,
textureMatrix,
&stage);
if (!effectInstalled) {
SkCanvas::Config8888 srcConfig8888, dstConfig8888; SkCanvas::Config8888 srcConfig8888, dstConfig8888;
GR_DEBUGCODE(bool success = ) GR_DEBUGCODE(bool success = )
grconfig_to_config8888(config, true, &srcConfig8888); grconfig_to_config8888(config, true, &srcConfig8888);
@ -1524,9 +1542,13 @@ void GrContext::writeRenderTargetPixels(GrRenderTarget* target,
rowBytes = 4 * width; rowBytes = 4 * width;
} }
} }
if (NULL == effect) { if (!effectInstalled) {
effect.reset(GrConfigConversionEffect::Create(texture, swapRAndB)); SkAssertResult(GrConfigConversionEffect::InstallEffect(
GrAssert(NULL != effect); texture,
swapRAndB,
GrConfigConversionEffect::kNone_PMConversion,
textureMatrix,
&stage));
} }
this->writeTexturePixels(texture, this->writeTexturePixels(texture,
@ -1536,15 +1558,13 @@ void GrContext::writeRenderTargetPixels(GrRenderTarget* target,
GrDrawTarget::AutoStateRestore asr(fGpu, GrDrawTarget::kReset_ASRInit); GrDrawTarget::AutoStateRestore asr(fGpu, GrDrawTarget::kReset_ASRInit);
GrDrawState* drawState = fGpu->drawState(); GrDrawState* drawState = fGpu->drawState();
*drawState->stage(0) = stage;
GrMatrix matrix; GrMatrix matrix;
matrix.setTranslate(GrIntToScalar(left), GrIntToScalar(top)); matrix.setTranslate(GrIntToScalar(left), GrIntToScalar(top));
drawState->setViewMatrix(matrix); drawState->setViewMatrix(matrix);
drawState->setRenderTarget(target); drawState->setRenderTarget(target);
matrix.setIDiv(texture->width(), texture->height());
drawState->stage(0)->setEffect(effect, matrix);
fGpu->drawSimpleRect(GrRect::MakeWH(SkIntToScalar(width), SkIntToScalar(height)), NULL); fGpu->drawSimpleRect(GrRect::MakeWH(SkIntToScalar(width), SkIntToScalar(height)), NULL);
} }
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
@ -1726,7 +1746,10 @@ void test_pm_conversions(GrContext* ctx, int* pmToUPMValue, int* upmToPMValue) {
} }
} }
GrEffect* GrContext::createPMToUPMEffect(GrTexture* texture, bool swapRAndB) { bool GrContext::installPMToUPMEffect(GrTexture* texture,
bool swapRAndB,
const GrMatrix& matrix,
GrEffectStage* stage) {
if (!fDidTestPMConversions) { if (!fDidTestPMConversions) {
test_pm_conversions(this, &fPMToUPMConversion, &fUPMToPMConversion); test_pm_conversions(this, &fPMToUPMConversion, &fUPMToPMConversion);
fDidTestPMConversions = true; fDidTestPMConversions = true;
@ -1734,13 +1757,17 @@ GrEffect* GrContext::createPMToUPMEffect(GrTexture* texture, bool swapRAndB) {
GrConfigConversionEffect::PMConversion pmToUPM = GrConfigConversionEffect::PMConversion pmToUPM =
static_cast<GrConfigConversionEffect::PMConversion>(fPMToUPMConversion); static_cast<GrConfigConversionEffect::PMConversion>(fPMToUPMConversion);
if (GrConfigConversionEffect::kNone_PMConversion != pmToUPM) { if (GrConfigConversionEffect::kNone_PMConversion != pmToUPM) {
return GrConfigConversionEffect::Create(texture, swapRAndB, pmToUPM); GrConfigConversionEffect::InstallEffect(texture, swapRAndB, pmToUPM, matrix, stage);
return true;
} else { } else {
return NULL; return false;
} }
} }
GrEffect* GrContext::createUPMToPMEffect(GrTexture* texture, bool swapRAndB) { bool GrContext::installUPMToPMEffect(GrTexture* texture,
bool swapRAndB,
const GrMatrix& matrix,
GrEffectStage* stage) {
if (!fDidTestPMConversions) { if (!fDidTestPMConversions) {
test_pm_conversions(this, &fPMToUPMConversion, &fUPMToPMConversion); test_pm_conversions(this, &fPMToUPMConversion, &fUPMToPMConversion);
fDidTestPMConversions = true; fDidTestPMConversions = true;
@ -1748,9 +1775,10 @@ GrEffect* GrContext::createUPMToPMEffect(GrTexture* texture, bool swapRAndB) {
GrConfigConversionEffect::PMConversion upmToPM = GrConfigConversionEffect::PMConversion upmToPM =
static_cast<GrConfigConversionEffect::PMConversion>(fUPMToPMConversion); static_cast<GrConfigConversionEffect::PMConversion>(fUPMToPMConversion);
if (GrConfigConversionEffect::kNone_PMConversion != upmToPM) { if (GrConfigConversionEffect::kNone_PMConversion != upmToPM) {
return GrConfigConversionEffect::Create(texture, swapRAndB, upmToPM); GrConfigConversionEffect::InstallEffect(texture, swapRAndB, upmToPM, matrix, stage);
return true;
} else { } else {
return NULL; return false;
} }
} }
@ -1808,7 +1836,7 @@ GrTexture* GrContext::gaussianBlur(GrTexture* srcTexture,
i < scaleFactorY ? 0.5f : 1.0f); i < scaleFactorY ? 0.5f : 1.0f);
paint.colorStage(0)->setEffect(SkNEW_ARGS(GrSingleTextureEffect, paint.colorStage(0)->setEffect(SkNEW_ARGS(GrSingleTextureEffect,
(srcTexture, true)), matrix)->unref(); (srcTexture, matrix, true)))->unref();
this->drawRectToRect(paint, dstRect, srcRect); this->drawRectToRect(paint, dstRect, srcRect);
srcRect = dstRect; srcRect = dstRect;
srcTexture = dstTexture; srcTexture = dstTexture;
@ -1865,8 +1893,8 @@ GrTexture* GrContext::gaussianBlur(GrTexture* srcTexture,
// FIXME: This should be mitchell, not bilinear. // FIXME: This should be mitchell, not bilinear.
matrix.setIDiv(srcTexture->width(), srcTexture->height()); matrix.setIDiv(srcTexture->width(), srcTexture->height());
this->setRenderTarget(dstTexture->asRenderTarget()); this->setRenderTarget(dstTexture->asRenderTarget());
paint.colorStage(0)->setEffect(SkNEW_ARGS(GrSingleTextureEffect,(srcTexture, true)), paint.colorStage(0)->setEffect(SkNEW_ARGS(GrSingleTextureEffect,(srcTexture,
matrix)->unref(); matrix, true)))->unref();
SkRect dstRect(srcRect); SkRect dstRect(srcRect);
scale_rect(&dstRect, (float) scaleFactorX, (float) scaleFactorY); scale_rect(&dstRect, (float) scaleFactorX, (float) scaleFactorY);
this->drawRectToRect(paint, dstRect, srcRect); this->drawRectToRect(paint, dstRect, srcRect);

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

@ -198,16 +198,16 @@ public:
} }
void createTextureEffect(int stageIdx, GrTexture* texture, const GrMatrix& matrix) { void createTextureEffect(int stageIdx, GrTexture* texture, const GrMatrix& matrix) {
GrAssert(!this->getStage(stageIdx).getEffect()); GrAssert(!this->getStage(stageIdx).getEffect());
GrEffect* effect = SkNEW_ARGS(GrSingleTextureEffect, (texture)); GrEffect* effect = SkNEW_ARGS(GrSingleTextureEffect, (texture, matrix));
this->stage(stageIdx)->setEffect(effect, matrix)->unref(); this->stage(stageIdx)->setEffect(effect)->unref();
} }
void createTextureEffect(int stageIdx, void createTextureEffect(int stageIdx,
GrTexture* texture, GrTexture* texture,
const GrMatrix& matrix, const GrMatrix& matrix,
const GrTextureParams& params) { const GrTextureParams& params) {
GrAssert(!this->getStage(stageIdx).getEffect()); GrAssert(!this->getStage(stageIdx).getEffect());
GrEffect* effect = SkNEW_ARGS(GrSingleTextureEffect, (texture, params)); GrEffect* effect = SkNEW_ARGS(GrSingleTextureEffect, (texture, matrix, params));
this->stage(stageIdx)->setEffect(effect, matrix)->unref(); this->stage(stageIdx)->setEffect(effect)->unref();
} }

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

@ -20,6 +20,26 @@ SkTArray<GrEffectTestFactory*, true>* GrEffectTestFactory::GetFactories() {
} }
#endif #endif
namespace GrEffectUnitTest {
const SkMatrix& TestMatrix(SkRandom* random) {
static SkMatrix gMatrices[5];
static bool gOnce;
if (!gOnce) {
gMatrices[0].reset();
gMatrices[1].setTranslate(SkIntToScalar(-100), SkIntToScalar(100));
gMatrices[2].setRotate(SkIntToScalar(17));
gMatrices[3].setRotate(SkIntToScalar(185));
gMatrices[3].postTranslate(SkIntToScalar(66), SkIntToScalar(-33));
gMatrices[3].postScale(SkIntToScalar(2), SK_ScalarHalf);
gMatrices[4].setRotate(SkIntToScalar(215));
gMatrices[4].set(SkMatrix::kMPersp0, SkFloatToScalar(0.00013f));
gMatrices[4].set(SkMatrix::kMPersp1, SkFloatToScalar(-0.000039f));
gOnce = true;
}
return gMatrices[random->nextULessThan(static_cast<uint32_t>(SK_ARRAY_COUNT(gMatrices)))];
}
}
class GrEffect_Globals { class GrEffect_Globals {
public: public:
static GrMemoryPool* GetTLS() { static GrMemoryPool* GetTLS() {

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

@ -608,7 +608,7 @@ inline bool skPaint2GrPaintShader(SkGpuDevice* dev,
GrScalar sy = SkFloatToScalar(1.f / bitmap.height()); GrScalar sy = SkFloatToScalar(1.f / bitmap.height());
matrix.postScale(sx, sy); matrix.postScale(sx, sy);
} }
stage->setEffect(SkNEW_ARGS(GrSingleTextureEffect, (texture, params)), matrix)->unref(); stage->setEffect(SkNEW_ARGS(GrSingleTextureEffect, (texture, matrix, params)))->unref();
return true; return true;
} }
@ -875,7 +875,7 @@ bool drawWithGPUMaskFilter(GrContext* context, const SkPath& devPath,
matrix.setIDiv(pathTexture->width(), pathTexture->height()); matrix.setIDiv(pathTexture->width(), pathTexture->height());
// Blend pathTexture over blurTexture. // Blend pathTexture over blurTexture.
context->setRenderTarget(blurTexture->asRenderTarget()); context->setRenderTarget(blurTexture->asRenderTarget());
paint.colorStage(0)->setEffect(SkNEW_ARGS(GrSingleTextureEffect, (pathTexture)), matrix)->unref(); paint.colorStage(0)->setEffect(SkNEW_ARGS(GrSingleTextureEffect, (pathTexture, matrix)))->unref();
if (SkMaskFilter::kInner_BlurType == blurType) { if (SkMaskFilter::kInner_BlurType == blurType) {
// inner: dst = dst * src // inner: dst = dst * src
paint.setBlendFunc(kDC_GrBlendCoeff, kZero_GrBlendCoeff); paint.setBlendFunc(kDC_GrBlendCoeff, kZero_GrBlendCoeff);
@ -906,7 +906,7 @@ bool drawWithGPUMaskFilter(GrContext* context, const SkPath& devPath,
matrix.postIDiv(blurTexture->width(), blurTexture->height()); matrix.postIDiv(blurTexture->width(), blurTexture->height());
grp->coverageStage(MASK_IDX)->reset(); grp->coverageStage(MASK_IDX)->reset();
grp->coverageStage(MASK_IDX)->setEffect(SkNEW_ARGS(GrSingleTextureEffect, (blurTexture)), matrix)->unref(); grp->coverageStage(MASK_IDX)->setEffect(SkNEW_ARGS(GrSingleTextureEffect, (blurTexture, matrix)))->unref();
context->drawRect(*grp, finalRect); context->drawRect(*grp, finalRect);
return true; return true;
} }
@ -962,7 +962,7 @@ bool drawWithMaskFilter(GrContext* context, const SkPath& devPath,
m.setTranslate(-dstM.fBounds.fLeft*SK_Scalar1, -dstM.fBounds.fTop*SK_Scalar1); m.setTranslate(-dstM.fBounds.fLeft*SK_Scalar1, -dstM.fBounds.fTop*SK_Scalar1);
m.postIDiv(texture->width(), texture->height()); m.postIDiv(texture->width(), texture->height());
grp->coverageStage(MASK_IDX)->setEffect(SkNEW_ARGS(GrSingleTextureEffect, (texture)), m)->unref(); grp->coverageStage(MASK_IDX)->setEffect(SkNEW_ARGS(GrSingleTextureEffect, (texture, m)))->unref();
GrRect d; GrRect d;
d.setLTRB(GrIntToScalar(dstM.fBounds.fLeft), d.setLTRB(GrIntToScalar(dstM.fBounds.fLeft),
GrIntToScalar(dstM.fBounds.fTop), GrIntToScalar(dstM.fBounds.fTop),

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

@ -218,21 +218,27 @@ void GrConfigConversionEffect::TestForPreservingPMConversions(GrContext* context
} }
} }
GrEffect* GrConfigConversionEffect::Create(GrTexture* texture, bool GrConfigConversionEffect::InstallEffect(GrTexture* texture,
bool swapRedAndBlue, bool swapRedAndBlue,
PMConversion pmConversion) { PMConversion pmConversion,
const GrMatrix& matrix,
GrEffectStage* stage) {
if (!swapRedAndBlue && kNone_PMConversion == pmConversion) { if (!swapRedAndBlue && kNone_PMConversion == pmConversion) {
// If we returned a GrConfigConversionEffect that was equivalent to a GrSingleTextureEffect // If we returned a GrConfigConversionEffect that was equivalent to a GrSingleTextureEffect
// then we may pollute our texture cache with redundant shaders. So in the case that no // then we may pollute our texture cache with redundant shaders. So in the case that no
// conversions were requested we instead return a GrSingleTextureEffect. // conversions were requested we instead return a GrSingleTextureEffect.
return SkNEW_ARGS(GrSingleTextureEffect, (texture)); stage->setEffect(SkNEW_ARGS(GrSingleTextureEffect, (texture, matrix)), matrix)->unref();
return true;
} else { } else {
if (kRGBA_8888_GrPixelConfig != texture->config() && if (kRGBA_8888_GrPixelConfig != texture->config() &&
kBGRA_8888_GrPixelConfig != texture->config() && kBGRA_8888_GrPixelConfig != texture->config() &&
kNone_PMConversion != pmConversion) { kNone_PMConversion != pmConversion) {
// The PM conversions assume colors are 0..255 // The PM conversions assume colors are 0..255
return NULL; return false;
} }
return SkNEW_ARGS(GrConfigConversionEffect, (texture, swapRedAndBlue, pmConversion)); stage->setEffect(SkNEW_ARGS(GrConfigConversionEffect, (texture,
swapRedAndBlue,
pmConversion)), matrix)->unref();
return true;
} }
} }

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

@ -33,10 +33,12 @@ public:
kPMConversionCnt kPMConversionCnt
}; };
// This will fail if the config is not 8888 and a PM conversion is requested. // Installs an effect in the GrEffectStage to perform a config conversion.
static GrEffect* Create(GrTexture*, static bool InstallEffect(GrTexture*,
bool swapRedAndBlue, bool swapRedAndBlue,
PMConversion pmConversion = kNone_PMConversion); PMConversion pmConversion,
const GrMatrix& matrix,
GrEffectStage* stage);
static const char* Name() { return "Config Conversion"; } static const char* Name() { return "Config Conversion"; }
typedef GrGLConfigConversionEffect GLEffect; typedef GrGLConfigConversionEffect GLEffect;

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

@ -7,6 +7,7 @@
#include "effects/GrSingleTextureEffect.h" #include "effects/GrSingleTextureEffect.h"
#include "gl/GrGLEffect.h" #include "gl/GrGLEffect.h"
#include "gl/GrGLEffectMatrix.h"
#include "gl/GrGLSL.h" #include "gl/GrGLSL.h"
#include "gl/GrGLTexture.h" #include "gl/GrGLTexture.h"
#include "GrTBackendEffectFactory.h" #include "GrTBackendEffectFactory.h"
@ -16,25 +17,43 @@ class GrGLSingleTextureEffect : public GrGLEffect {
public: public:
GrGLSingleTextureEffect(const GrBackendEffectFactory& factory, const GrEffect&) GrGLSingleTextureEffect(const GrBackendEffectFactory& factory, const GrEffect&)
: INHERITED (factory) { : INHERITED (factory) {
fRequiresTextureMatrix = false;
} }
virtual void emitCode(GrGLShaderBuilder* builder, virtual void emitCode(GrGLShaderBuilder* builder,
const GrEffectStage&, const GrEffectStage&,
EffectKey, EffectKey key,
const char* vertexCoords, const char* vertexCoords,
const char* outputColor, const char* outputColor,
const char* inputColor, const char* inputColor,
const TextureSamplerArray& samplers) SK_OVERRIDE { const TextureSamplerArray& samplers) SK_OVERRIDE {
const char* coordName;
GrSLType coordType = fEffectMatrix.emitCode(builder, key, vertexCoords, &coordName);
builder->fFSCode.appendf("\t%s = ", outputColor); builder->fFSCode.appendf("\t%s = ", outputColor);
builder->appendTextureLookupAndModulate(&builder->fFSCode, inputColor, samplers[0]); builder->appendTextureLookupAndModulate(&builder->fFSCode,
inputColor,
samplers[0],
coordName,
coordType);
builder->fFSCode.append(";\n"); builder->fFSCode.append(";\n");
} }
static inline EffectKey GenKey(const GrEffectStage&, const GrGLCaps&) { return 0; } static inline EffectKey GenKey(const GrEffectStage& stage, const GrGLCaps&) {
const GrSingleTextureEffect& ste =
static_cast<const GrSingleTextureEffect&>(*stage.getEffect());
return GrGLEffectMatrix::GenKey(ste.getMatrix(),
stage.getCoordChangeMatrix(),
ste.texture(0));
}
virtual void setData(const GrGLUniformManager& uman, const GrEffectStage& stage) SK_OVERRIDE {
const GrSingleTextureEffect& ste =
static_cast<const GrSingleTextureEffect&>(*stage.getEffect());
fEffectMatrix.setData(uman, ste.getMatrix(), stage.getCoordChangeMatrix(), ste.texture(0));
}
private: private:
GrGLEffectMatrix fEffectMatrix;
typedef GrGLEffect INHERITED; typedef GrGLEffect INHERITED;
}; };
@ -43,16 +62,39 @@ private:
GrSingleTextureEffect::GrSingleTextureEffect(GrTexture* texture) GrSingleTextureEffect::GrSingleTextureEffect(GrTexture* texture)
: INHERITED(1) : INHERITED(1)
, fTextureAccess(texture) { , fTextureAccess(texture) {
fMatrix.reset();
} }
GrSingleTextureEffect::GrSingleTextureEffect(GrTexture* texture, bool bilerp) GrSingleTextureEffect::GrSingleTextureEffect(GrTexture* texture, bool bilerp)
: INHERITED(1) : INHERITED(1)
, fTextureAccess(texture, bilerp) { , fTextureAccess(texture, bilerp) {
fMatrix.reset();
} }
GrSingleTextureEffect::GrSingleTextureEffect(GrTexture* texture, const GrTextureParams& params) GrSingleTextureEffect::GrSingleTextureEffect(GrTexture* texture, const GrTextureParams& params)
: INHERITED(1) : INHERITED(1)
, fTextureAccess(texture, params) { , fTextureAccess(texture, params) {
fMatrix.reset();
}
GrSingleTextureEffect::GrSingleTextureEffect(GrTexture* texture, const GrMatrix& m)
: INHERITED(1)
, fTextureAccess(texture)
, fMatrix(m) {
}
GrSingleTextureEffect::GrSingleTextureEffect(GrTexture* texture, const GrMatrix& m, bool bilerp)
: INHERITED(1)
, fTextureAccess(texture, bilerp)
, fMatrix(m) {
}
GrSingleTextureEffect::GrSingleTextureEffect(GrTexture* texture,
const GrMatrix& m,
const GrTextureParams& params)
: INHERITED(1)
, fTextureAccess(texture, params)
, fMatrix(m) {
} }
GrSingleTextureEffect::~GrSingleTextureEffect() { GrSingleTextureEffect::~GrSingleTextureEffect() {
@ -76,5 +118,6 @@ GrEffect* GrSingleTextureEffect::TestCreate(SkRandom* random,
GrTexture* textures[]) { GrTexture* textures[]) {
int texIdx = random->nextBool() ? GrEffectUnitTest::kSkiaPMTextureIdx : int texIdx = random->nextBool() ? GrEffectUnitTest::kSkiaPMTextureIdx :
GrEffectUnitTest::kAlphaTextureIdx; GrEffectUnitTest::kAlphaTextureIdx;
return SkNEW_ARGS(GrSingleTextureEffect, (textures[texIdx])); const SkMatrix& matrix = GrEffectUnitTest::TestMatrix(random);
return SkNEW_ARGS(GrSingleTextureEffect, (textures[texIdx], matrix));
} }

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

@ -9,6 +9,7 @@
#define GrSingleTextureEffect_DEFINED #define GrSingleTextureEffect_DEFINED
#include "GrEffect.h" #include "GrEffect.h"
#include "GrMatrix.h"
class GrGLSingleTextureEffect; class GrGLSingleTextureEffect;
@ -18,28 +19,37 @@ class GrGLSingleTextureEffect;
class GrSingleTextureEffect : public GrEffect { class GrSingleTextureEffect : public GrEffect {
public: public:
/** Uses default texture params (unfiltered, clamp) */ /** These three constructors assume an identity matrix */
GrSingleTextureEffect(GrTexture* texture); GrSingleTextureEffect(GrTexture* texture); /* unfiltered, clamp mode */
GrSingleTextureEffect(GrTexture* texture, bool bilerp); /* clamp mode */
/** Uses default tile mode (clamp) */
GrSingleTextureEffect(GrTexture* texture, bool bilerp);
GrSingleTextureEffect(GrTexture* texture, const GrTextureParams&); GrSingleTextureEffect(GrTexture* texture, const GrTextureParams&);
/** These three constructors take an explicit matrix */
GrSingleTextureEffect(GrTexture*, const GrMatrix&); /* unfiltered, clamp mode */
GrSingleTextureEffect(GrTexture*, const GrMatrix&, bool bilerp); /* clamp mode */
GrSingleTextureEffect(GrTexture*, const GrMatrix&, const GrTextureParams&);
virtual ~GrSingleTextureEffect(); virtual ~GrSingleTextureEffect();
virtual const GrTextureAccess& textureAccess(int index) const SK_OVERRIDE; virtual const GrTextureAccess& textureAccess(int index) const SK_OVERRIDE;
static const char* Name() { return "Single Texture"; } static const char* Name() { return "Single Texture"; }
const GrMatrix& getMatrix() const { return fMatrix; }
typedef GrGLSingleTextureEffect GLEffect; typedef GrGLSingleTextureEffect GLEffect;
virtual const GrBackendEffectFactory& getFactory() const SK_OVERRIDE; virtual const GrBackendEffectFactory& getFactory() const SK_OVERRIDE;
virtual bool isEqual(const GrEffect& effect) const SK_OVERRIDE {
const GrSingleTextureEffect& ste = static_cast<const GrSingleTextureEffect&>(effect);
return INHERITED::isEqual(effect) && fMatrix.cheapEqualTo(ste.getMatrix());
}
private: private:
GR_DECLARE_EFFECT_TEST; GR_DECLARE_EFFECT_TEST;
GrTextureAccess fTextureAccess; GrTextureAccess fTextureAccess;
GrMatrix fMatrix;
typedef GrEffect INHERITED; typedef GrEffect INHERITED;
}; };

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

@ -10,6 +10,8 @@
GrGLEffect::GrGLEffect(const GrBackendEffectFactory& factory) GrGLEffect::GrGLEffect(const GrBackendEffectFactory& factory)
: fFactory(factory) { : fFactory(factory) {
fRequiresTextureMatrix = true;
} }
GrGLEffect::~GrGLEffect() { GrGLEffect::~GrGLEffect() {

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

@ -51,7 +51,9 @@ public:
@param builder Interface used to emit code in the shaders. @param builder Interface used to emit code in the shaders.
@param stage The effect stage that generated this program stage. @param stage The effect stage that generated this program stage.
@param key The key that was computed by EffectKey() from the generating GrEffect. @param key The key that was computed by GenKey() from the generating GrEffect.
Only the bits indicated by GrBackendEffectFactory::kEffectKeyBits are
guaranteed to match the value produced by GenKey();
@param vertexCoords A vec2 of texture coordinates in the VS, which may be altered. This will @param vertexCoords A vec2 of texture coordinates in the VS, which may be altered. This will
be removed soon and stages will be responsible for computing their own be removed soon and stages will be responsible for computing their own
coords. coords.
@ -85,7 +87,14 @@ public:
static EffectKey GenTextureKey(const GrEffect&, const GrGLCaps&); static EffectKey GenTextureKey(const GrEffect&, const GrGLCaps&);
bool requiresTextureMatrix() const { return fRequiresTextureMatrix; }
protected: protected:
// HACK: This is a temporary field that allows GrGLEffect subclasses to opt into the new
// shader gen where a texture matrix is not automatically inserted. It defaults to true and is
// set to false in a subclass to opt into the new behavior.
bool fRequiresTextureMatrix;
const GrBackendEffectFactory& fFactory; const GrBackendEffectFactory& fFactory;
}; };

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

@ -0,0 +1,213 @@
/*
* Copyright 2012 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#include "GrGLEffectMatrix.h"
#include "GrTexture.h"
GrGLEffect::EffectKey GrGLEffectMatrix::GenKey(const SkMatrix& effectMatrix,
const SkMatrix& coordChangeMatrix,
const GrTexture* texture) {
SkMatrix::TypeMask type0 = effectMatrix.getType();
SkMatrix::TypeMask type1 = coordChangeMatrix.getType();
static const int kNonTransMask = SkMatrix::kAffine_Mask |
SkMatrix::kScale_Mask |
SkMatrix::kPerspective_Mask;
int combinedTypes = type0 | type1;
bool reverseY = (NULL != texture) && GrSurface::kBottomLeft_Origin == texture->origin();
if (SkMatrix::kPerspective_Mask & combinedTypes) {
return kGeneral_Key;
} else if ((kNonTransMask & combinedTypes) || reverseY) {
return kNoPersp_Key;
} else if (kTrans_Key & combinedTypes) {
return kTrans_Key;
} else {
GrAssert(effectMatrix.isIdentity() && coordChangeMatrix.isIdentity());
return kIdentity_Key;
}
}
GrSLType GrGLEffectMatrix::emitCode(GrGLShaderBuilder* builder,
EffectKey key,
const char* vertexCoords,
const char** fsCoordName,
const char** vsCoordName,
const char* suffix) {
GrSLType varyingType;
const char* uniName;
key &= kKeyMask;
switch (key) {
case kIdentity_Key:
fUniType = kVoid_GrSLType;
varyingType = kVec2f_GrSLType;
break;
case kTrans_Key:
fUniType = kVec2f_GrSLType;
uniName = "StageTranslate";
varyingType = kVec2f_GrSLType;
break;
case kNoPersp_Key:
fUniType = kMat33f_GrSLType;
uniName = "StageMatrix";
varyingType = kVec2f_GrSLType;
break;
case kGeneral_Key:
fUniType = kMat33f_GrSLType;
uniName = "StageMatrix";
varyingType = kVec3f_GrSLType;
break;
default:
GrCrash("Unexpected key.");
}
SkString suffixedUniName;
if (NULL != suffix) {
suffixedUniName.append(uniName);
suffixedUniName.append(suffix);
uniName = suffixedUniName.c_str();
}
if (kVoid_GrSLType != fUniType) {
fUni = builder->addUniform(GrGLShaderBuilder::kVertex_ShaderType,
fUniType,
uniName,
&uniName);
}
const char* varyingName = "StageCoord";
SkString suffixedVaryingName;
if (NULL != suffix) {
suffixedVaryingName.append(varyingName);
suffixedVaryingName.append(suffix);
varyingName = suffixedVaryingName.c_str();
}
const char* vsVaryingName;
const char* fsVaryingName;
builder->addVarying(varyingType, varyingName, &vsVaryingName, &fsVaryingName);
// varying = matrix * vertex-coords (logically)
switch (fUniType) {
case kVoid_GrSLType:
GrAssert(kVec2f_GrSLType == varyingType);
builder->fVSCode.appendf("\t%s = %s;\n", vsVaryingName, vertexCoords);
break;
case kVec2f_GrSLType:
GrAssert(kVec2f_GrSLType == varyingType);
builder->fVSCode.appendf("\t%s = %s + %s;\n", vsVaryingName, uniName, vertexCoords);
break;
case kMat33f_GrSLType: {
GrAssert(kVec2f_GrSLType == varyingType || kVec3f_GrSLType == varyingType);
if (kVec2f_GrSLType == varyingType) {
builder->fVSCode.appendf("\t%s = (%s * vec3(%s, 1)).xy;\n",
vsVaryingName, uniName, vertexCoords);
} else {
builder->fVSCode.appendf("\t%s = %s * vec3(%s, 1);\n",
vsVaryingName, uniName, vertexCoords);
}
break;
}
default:
GrCrash("Unexpected uniform type.");
}
if (NULL != vsCoordName) {
*vsCoordName = vsVaryingName;
}
if (NULL != fsCoordName) {
*fsCoordName = fsVaryingName;
}
return varyingType;
}
/**
* This is similar to emitCode except that it performs perspective division in the FS if the
* texture coordinates have a w coordinate. The fsCoordName always refers to a vec2f.
*/
void GrGLEffectMatrix::emitCodeMakeFSCoords2D(GrGLShaderBuilder* builder,
EffectKey key,
const char* vertexCoords,
const char** fsCoordName,
const char** vsVaryingName,
GrSLType* vsVaryingType,
const char* suffix) {
const char* fsVaryingName;
GrSLType varyingType = this->emitCode(builder,
key,
vertexCoords,
&fsVaryingName,
vsVaryingName,
suffix);
if (kVec3f_GrSLType == varyingType) {
const char* coordName = "coords2D";
SkString suffixedCoordName;
if (NULL != suffix) {
suffixedCoordName.append(coordName);
suffixedCoordName.append(suffix);
coordName = suffixedCoordName.c_str();
}
builder->fFSCode.appendf("\tvec2 %s = %s.xy / %s.z;",
coordName, fsVaryingName, fsVaryingName);
if (NULL != fsCoordName) {
*fsCoordName = coordName;
}
} else if(NULL != fsCoordName) {
*fsCoordName = fsVaryingName;
}
if (NULL != vsVaryingType) {
*vsVaryingType = varyingType;
}
}
void GrGLEffectMatrix::setData(const GrGLUniformManager& uniformManager,
const SkMatrix& matrix,
const SkMatrix& coordChangeMatrix,
const GrTexture* texture) {
GrAssert((GrGLUniformManager::kInvalidUniformHandle == fUni) ==
(kVoid_GrSLType == fUniType));
switch (fUniType) {
case kVoid_GrSLType:
GrAssert(matrix.isIdentity());
GrAssert(coordChangeMatrix.isIdentity());
GrAssert(NULL == texture || GrSurface::kTopLeft_Origin == texture->origin());
return;
case kVec2f_GrSLType: {
GrAssert(SkMatrix::kTranslate_Mask == (matrix.getType() | coordChangeMatrix.getType()));
GrAssert(NULL == texture || GrSurface::kTopLeft_Origin == texture->origin());
SkScalar tx = matrix[SkMatrix::kMTransX] + coordChangeMatrix[SkMatrix::kMTransX];
SkScalar ty = matrix[SkMatrix::kMTransY] + coordChangeMatrix[SkMatrix::kMTransY];
if (fPrevMatrix.get(SkMatrix::kMTransX) != tx ||
fPrevMatrix.get(SkMatrix::kMTransY) != ty) {
uniformManager.set2f(fUni, tx, ty);
fPrevMatrix.set(SkMatrix::kMTransX, tx);
fPrevMatrix.set(SkMatrix::kMTransY, ty);
}
break;
}
case kMat33f_GrSLType: {
SkMatrix combined;
combined.setConcat(matrix, coordChangeMatrix);
if (NULL != texture && GrSurface::kBottomLeft_Origin == texture->origin()) {
// combined.postScale(1,-1);
// combined.postTranslate(0,1);
combined.set(SkMatrix::kMSkewY,
combined[SkMatrix::kMPersp0] - combined[SkMatrix::kMSkewY]);
combined.set(SkMatrix::kMScaleY,
combined[SkMatrix::kMPersp1] - combined[SkMatrix::kMScaleY]);
combined.set(SkMatrix::kMTransY,
combined[SkMatrix::kMPersp2] - combined[SkMatrix::kMTransY]);
}
if (!fPrevMatrix.cheapEqualTo(combined)) {
uniformManager.setSkMatrix(fUni, combined);
fPrevMatrix = combined;
}
break;
}
default:
GrCrash("Unexpected uniform type.");
}
}

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

@ -0,0 +1,97 @@
/*
* Copyright 2012 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#ifndef GrGLEffectMatrix_DEFINED
#define GrGLEffectMatrix_DEFINED
#include "GrGLEffect.h"
#include "SkMatrix.h"
class GrTexture;
class SkRandom;
/**
* This is a helper to implement a texture matrix in a GrGLEffect.
*/
class GrGLEffectMatrix {
public:
typedef GrGLEffect::EffectKey EffectKey;
/**
* The matrix uses kKeyBits of the effect's EffectKey. A GrGLEffect may place these bits at an
* arbitrary shift in its final key. However, when GrGLEffectMatrix::emitCode*() code is called
* the relevant bits must be in the lower kKeyBits of the key parameter.
*/
enum {
kKeyBits = 2,
kKeyMask = (1 << kKeyBits) - 1,
};
GrGLEffectMatrix() : fUni(GrGLUniformManager::kInvalidUniformHandle) {
fPrevMatrix = SkMatrix::InvalidMatrix();
}
/**
* Generates the key for the portion of the code emitted by this class's emitCode() function.
* Pass a texture to make GrGLEffectMatrix automatically adjust for the texture's origin. Pass
* NULL when not using the EffectMatrix for a texture lookups, or if the GrGLEffect subclass
* wants to handle origin adjustments in some other manner. coordChangeMatrix is the matrix
* from GrEffectStage.
*/
static EffectKey GenKey(const SkMatrix& effectMatrix,
const SkMatrix& coordChangeMatrix,
const GrTexture*);
/**
* Emits code to implement the matrix in the VS. A varying is added as an output of the VS and
* input to the FS. The varying may be either a vec2f or vec3f depending upon whether
* perspective interpolation is required or not. The names of the varying in the VS and FS are
* are returned as output parameters and the type of the varying is the return value. The suffix
* is an optional parameter that can be used to make all variables emitted by the object
* unique within a stage. It is only necessary if multiple GrGLEffectMatrix objects are used by
* a GrGLEffect.
*/
GrSLType emitCode(GrGLShaderBuilder*,
EffectKey,
const char* vertexCoords,
const char** fsCoordName, /* optional */
const char** vsCoordName = NULL,
const char* suffix = NULL);
/**
* This is similar to emitCode except that it performs perspective division in the FS if the
* texture coordinates have a w coordinate. The fsCoordName always refers to a vec2f.
*/
void emitCodeMakeFSCoords2D(GrGLShaderBuilder*,
EffectKey,
const char* vertexCoords,
const char** fsCoordName, /* optional */
const char** vsVaryingName = NULL,
GrSLType* vsVaryingType = NULL,
const char* suffix = NULL);
/**
* Call from a GrGLEffect's subclass to update the texture matrix. The matrix,
* coordChangeMatrix, and texture params should match those used with GenKey.
*/
void setData(const GrGLUniformManager& uniformManager,
const SkMatrix& effectMatrix,
const SkMatrix& coordChangeMatrix,
const GrTexture*);
private:
enum {
kIdentity_Key = 0,
kTrans_Key = 1,
kNoPersp_Key = 2,
kGeneral_Key = 3,
};
GrGLUniformManager::UniformHandle fUni;
GrSLType fUniType;
SkMatrix fPrevMatrix;
};
#endif

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

@ -909,8 +909,12 @@ GrGLEffect* GrGLProgram::GenStageCode(const GrEffectStage& stage,
/// Vertex Shader Stuff /// Vertex Shader Stuff
// decide whether we need a matrix to transform texture coords and whether the varying needs a const char* vertexCoords;
// perspective coord.
// Has the effect not yet been updated to insert its own texture matrix if necessary.
if (glEffect->requiresTextureMatrix()) {
// Decide whether we need a matrix to transform texture coords and whether the varying needs
// a perspective coord.
const char* matName = NULL; const char* matName = NULL;
GrSLType texCoordVaryingType; GrSLType texCoordVaryingType;
if (desc.fOptFlags & StageDesc::kIdentityMatrix_OptFlagBit) { if (desc.fOptFlags & StageDesc::kIdentityMatrix_OptFlagBit) {
@ -933,16 +937,6 @@ GrGLEffect* GrGLProgram::GenStageCode(const GrEffectStage& stage,
&varyingFSName); &varyingFSName);
builder->setupTextureAccess(varyingFSName, texCoordVaryingType); builder->setupTextureAccess(varyingFSName, texCoordVaryingType);
int numTextures = effect->numTextures();
SkSTArray<8, GrGLShaderBuilder::TextureSampler> textureSamplers;
textureSamplers.push_back_n(numTextures);
for (int i = 0; i < numTextures; ++i) {
textureSamplers[i].init(builder, &effect->textureAccess(i));
uniforms->fSamplerUniforms.push_back(textureSamplers[i].fSamplerUniform);
}
if (!matName) { if (!matName) {
GrAssert(kVec2f_GrSLType == texCoordVaryingType); GrAssert(kVec2f_GrSLType == texCoordVaryingType);
builder->fVSCode.appendf("\t%s = %s;\n", varyingVSName, vsInCoord); builder->fVSCode.appendf("\t%s = %s;\n", varyingVSName, vsInCoord);
@ -952,6 +946,19 @@ GrGLEffect* GrGLProgram::GenStageCode(const GrEffectStage& stage,
varyingVSName, matName, vsInCoord, varyingVSName, matName, vsInCoord,
vector_all_coords(GrSLTypeToVecLength(texCoordVaryingType))); vector_all_coords(GrSLTypeToVecLength(texCoordVaryingType)));
} }
vertexCoords = varyingVSName;
} else {
vertexCoords = vsInCoord;
}
// setup texture samplers for gl effect
int numTextures = effect->numTextures();
SkSTArray<8, GrGLShaderBuilder::TextureSampler> textureSamplers;
textureSamplers.push_back_n(numTextures);
for (int i = 0; i < numTextures; ++i) {
textureSamplers[i].init(builder, &effect->textureAccess(i));
uniforms->fSamplerUniforms.push_back(textureSamplers[i].fSamplerUniform);
}
// Enclose custom code in a block to avoid namespace conflicts // Enclose custom code in a block to avoid namespace conflicts
builder->fVSCode.appendf("\t{ // %s\n", glEffect->name()); builder->fVSCode.appendf("\t{ // %s\n", glEffect->name());
@ -959,7 +966,7 @@ GrGLEffect* GrGLProgram::GenStageCode(const GrEffectStage& stage,
glEffect->emitCode(builder, glEffect->emitCode(builder,
stage, stage,
desc.fEffectKey, desc.fEffectKey,
varyingVSName, vertexCoords,
fsOutColor, fsOutColor,
fsInColor, fsInColor,
textureSamplers); textureSamplers);

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

@ -8,6 +8,7 @@
#include "gl/GrGLShaderBuilder.h" #include "gl/GrGLShaderBuilder.h"
#include "gl/GrGLProgram.h" #include "gl/GrGLProgram.h"
#include "gl/GrGLUniformHandle.h" #include "gl/GrGLUniformHandle.h"
#include "SkMatrix.h"
#define ASSERT_ARRAY_UPLOAD_IN_BOUNDS(UNI, OFFSET, COUNT) \ #define ASSERT_ARRAY_UPLOAD_IN_BOUNDS(UNI, OFFSET, COUNT) \
GrAssert(offset + arrayCount <= uni.fArrayCount || \ GrAssert(offset + arrayCount <= uni.fArrayCount || \
@ -231,6 +232,23 @@ void GrGLUniformManager::setMatrix4fv(UniformHandle u,
} }
} }
void GrGLUniformManager::setSkMatrix(UniformHandle u, const SkMatrix& matrix) const {
GR_STATIC_ASSERT(SK_SCALAR_IS_FLOAT);
GrGLfloat mt[] = {
matrix.get(SkMatrix::kMScaleX),
matrix.get(SkMatrix::kMSkewY),
matrix.get(SkMatrix::kMPersp0),
matrix.get(SkMatrix::kMSkewX),
matrix.get(SkMatrix::kMScaleY),
matrix.get(SkMatrix::kMPersp1),
matrix.get(SkMatrix::kMTransX),
matrix.get(SkMatrix::kMTransY),
matrix.get(SkMatrix::kMPersp2),
};
this->setMatrix3f(u, mt);
}
void GrGLUniformManager::getUniformLocations(GrGLuint programID, const BuilderUniformArray& uniforms) { void GrGLUniformManager::getUniformLocations(GrGLuint programID, const BuilderUniformArray& uniforms) {
GrAssert(uniforms.count() == fUniforms.count()); GrAssert(uniforms.count() == fUniforms.count());
int count = fUniforms.count(); int count = fUniforms.count();

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

@ -15,6 +15,7 @@
#include "SkTArray.h" #include "SkTArray.h"
class GrGLContextInfo; class GrGLContextInfo;
class SkMatrix;
/** Manages a program's uniforms. /** Manages a program's uniforms.
*/ */
@ -47,6 +48,9 @@ public:
void setMatrix3fv(UniformHandle, int offset, int arrayCount, const GrGLfloat matrices[]) const; void setMatrix3fv(UniformHandle, int offset, int arrayCount, const GrGLfloat matrices[]) const;
void setMatrix4fv(UniformHandle, int offset, int arrayCount, const GrGLfloat matrices[]) const; void setMatrix4fv(UniformHandle, int offset, int arrayCount, const GrGLfloat matrices[]) const;
// convenience method for uploading a SkMatrix to a 3x3 matrix uniform
void setSkMatrix(UniformHandle, const SkMatrix&) const;
struct BuilderUniform { struct BuilderUniform {
GrGLShaderVar fVariable; GrGLShaderVar fVariable;
uint32_t fVisibility; uint32_t fVisibility;

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

@ -184,7 +184,11 @@ void forceLinking();
void forceLinking() { void forceLinking() {
SkLightingImageFilter::CreateDistantLitDiffuse(SkPoint3(0,0,0), 0, 0, 0); SkLightingImageFilter::CreateDistantLitDiffuse(SkPoint3(0,0,0), 0, 0, 0);
SkMagnifierImageFilter mag(SkRect::MakeWH(SK_Scalar1, SK_Scalar1), SK_Scalar1); SkMagnifierImageFilter mag(SkRect::MakeWH(SK_Scalar1, SK_Scalar1), SK_Scalar1);
GrConfigConversionEffect::Create(NULL, false); GrConfigConversionEffect::InstallEffect(NULL,
false,
GrConfigConversionEffect::kNone_PMConversion,
GrMatrix::I(),
&GrEffectStage());
SkScalar matrix[20]; SkScalar matrix[20];
SkColorMatrixFilter cmf(matrix); SkColorMatrixFilter cmf(matrix);
} }