Reland r6233 with fix.
git-svn-id: http://skia.googlecode.com/svn/trunk@6241 2bbb7eff-a529-9590-31e7-b0007b416f81
This commit is contained in:
parent
6e7251669c
commit
d8b5faca04
@ -114,7 +114,7 @@ protected:
|
||||
tm = vm;
|
||||
tm.postIDiv(2*S, 2*S);
|
||||
paint.colorStage(0)->setEffect(SkNEW_ARGS(GrSingleTextureEffect,
|
||||
(texture)), tm)->unref();
|
||||
(texture, tm)))->unref();
|
||||
|
||||
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/GrGLEffect.cpp',
|
||||
'<(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.h',
|
||||
'<(skia_src_path)/gpu/gl/GrGLInterface.cpp',
|
||||
|
@ -928,8 +928,14 @@ private:
|
||||
// for use with textures released from an GrAutoScratchTexture.
|
||||
void addExistingTextureToCache(GrTexture* texture);
|
||||
|
||||
GrEffect* createPMToUPMEffect(GrTexture* texture, bool swapRAndB);
|
||||
GrEffect* createUPMToPMEffect(GrTexture* texture, bool swapRAndB);
|
||||
bool installPMToUPMEffect(GrTexture* texture,
|
||||
bool swapRAndB,
|
||||
const GrMatrix& matrix,
|
||||
GrEffectStage* stage);
|
||||
bool installUPMToPMEffect(GrTexture* texture,
|
||||
bool swapRAndB,
|
||||
const GrMatrix& matrix,
|
||||
GrEffectStage* stage);
|
||||
|
||||
typedef GrRefCnt INHERITED;
|
||||
};
|
||||
|
@ -12,12 +12,20 @@
|
||||
#include "GrNoncopyable.h"
|
||||
#include "SkTArray.h"
|
||||
|
||||
class SkMatrix;
|
||||
|
||||
namespace GrEffectUnitTest {
|
||||
// Used to access the dummy textures in TestCreate procs.
|
||||
enum {
|
||||
kSkiaPMTextureIdx = 0,
|
||||
kAlphaTextureIdx = 1,
|
||||
};
|
||||
|
||||
/**
|
||||
* A helper for use in GrEffect::TestCreate functions.
|
||||
*/
|
||||
const SkMatrix& TestMatrix(SkRandom*);
|
||||
|
||||
}
|
||||
|
||||
#if SK_ALLOW_STATIC_GLOBAL_INITIALIZERS
|
||||
@ -56,12 +64,13 @@ private:
|
||||
static GrEffectTestFactory gTestFactory; \
|
||||
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:
|
||||
* GrEffect* TestCreate(SkRandom*, GrContext*, GrTexture* dummyTextures[2]);
|
||||
* dummyTextures[] are valied textures that they can optionally use for their texture accesses. The
|
||||
* first texture has config kSkia8888_PM_GrPixelConfig and the second has kAlpha_8_GrPixelConfig.
|
||||
* TestCreate functions are also free to create additional textures using the GrContext.
|
||||
* dummyTextures[] are valid textures that can optionally be used to construct GrTextureAccesses.
|
||||
* The first texture has config kSkia8888_PM_GrPixelConfig and the second has
|
||||
* kAlpha_8_GrPixelConfig. TestCreate functions are also free to create additional textures using
|
||||
* the GrContext.
|
||||
*/
|
||||
#define GR_DEFINE_EFFECT_TEST(Effect) \
|
||||
GrEffectTestFactory Effect :: gTestFactory(Effect :: TestCreate)
|
||||
|
@ -13,6 +13,7 @@
|
||||
#include "SkGr.h"
|
||||
#include "SkGrPixelRef.h"
|
||||
#include "gl/GrGLEffect.h"
|
||||
#include "gl/GrGLEffectMatrix.h"
|
||||
#include "GrTBackendEffectFactory.h"
|
||||
#endif
|
||||
|
||||
@ -127,16 +128,19 @@ public:
|
||||
|
||||
static inline EffectKey GenKey(const GrEffectStage&, const GrGLCaps&);
|
||||
|
||||
virtual void setData(const GrGLUniformManager&, const GrEffectStage&);
|
||||
|
||||
private:
|
||||
typedef GrGLEffect INHERITED;
|
||||
SkBlendImageFilter::Mode fMode;
|
||||
GrGLEffectMatrix fEffectMatrix;
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
class GrBlendEffect : public GrSingleTextureEffect {
|
||||
public:
|
||||
GrBlendEffect(SkBlendImageFilter::Mode mode, GrTexture* foreground);
|
||||
GrBlendEffect(SkBlendImageFilter::Mode mode, GrTexture* foreground, const SkMatrix&);
|
||||
virtual ~GrBlendEffect();
|
||||
|
||||
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());
|
||||
GrPaint paint;
|
||||
paint.colorStage(0)->setEffect(
|
||||
SkNEW_ARGS(GrSingleTextureEffect, (background.get())), backgroundTexMatrix)->unref();
|
||||
SkNEW_ARGS(GrSingleTextureEffect, (background.get(), backgroundTexMatrix)))->unref();
|
||||
paint.colorStage(1)->setEffect(
|
||||
SkNEW_ARGS(GrBlendEffect, (fMode, foreground.get())), foregroundTexMatrix)->unref();
|
||||
SkNEW_ARGS(GrBlendEffect, (fMode, foreground.get(), foregroundTexMatrix)))->unref();
|
||||
context->drawRect(paint, rect);
|
||||
return dst;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
GrBlendEffect::GrBlendEffect(SkBlendImageFilter::Mode mode, GrTexture* foreground)
|
||||
: INHERITED(foreground), fMode(mode) {
|
||||
GrBlendEffect::GrBlendEffect(SkBlendImageFilter::Mode mode,
|
||||
GrTexture* foreground,
|
||||
const SkMatrix& matrix)
|
||||
: INHERITED(foreground, matrix), fMode(mode) {
|
||||
}
|
||||
|
||||
GrBlendEffect::~GrBlendEffect() {
|
||||
@ -227,8 +233,7 @@ GrBlendEffect::~GrBlendEffect() {
|
||||
|
||||
bool GrBlendEffect::isEqual(const GrEffect& sBase) const {
|
||||
const GrBlendEffect& s = static_cast<const GrBlendEffect&>(sBase);
|
||||
return INHERITED::isEqual(sBase) &&
|
||||
fMode == s.fMode;
|
||||
return INHERITED::isEqual(sBase) && fMode == s.fMode;
|
||||
}
|
||||
|
||||
const GrBackendEffectFactory& GrBlendEffect::getFactory() const {
|
||||
@ -241,6 +246,7 @@ GrGLBlendEffect::GrGLBlendEffect(const GrBackendEffectFactory& factory,
|
||||
const GrEffect& effect)
|
||||
: INHERITED(factory),
|
||||
fMode(static_cast<const GrBlendEffect&>(effect).mode()) {
|
||||
fRequiresTextureMatrix = false;
|
||||
}
|
||||
|
||||
GrGLBlendEffect::~GrGLBlendEffect() {
|
||||
@ -248,16 +254,19 @@ GrGLBlendEffect::~GrGLBlendEffect() {
|
||||
|
||||
void GrGLBlendEffect::emitCode(GrGLShaderBuilder* builder,
|
||||
const GrEffectStage&,
|
||||
EffectKey,
|
||||
EffectKey key,
|
||||
const char* vertexCoords,
|
||||
const char* outputColor,
|
||||
const char* inputColor,
|
||||
const TextureSamplerArray& samplers) {
|
||||
const char* coords;
|
||||
GrSLType coordsType = fEffectMatrix.emitCode(builder, key, vertexCoords, &coords);
|
||||
|
||||
SkString* code = &builder->fFSCode;
|
||||
const char* bgColor = inputColor;
|
||||
const char* fgColor = "fgColor";
|
||||
code->appendf("\t\tvec4 %s = ", fgColor);
|
||||
builder->appendTextureLookup(code, samplers[0]);
|
||||
builder->appendTextureLookup(code, samplers[0], coords, coordsType);
|
||||
code->append(";\n");
|
||||
code->appendf("\t\t%s.a = 1.0 - (1.0 - %s.a) * (1.0 - %s.b);\n", outputColor, bgColor, fgColor);
|
||||
switch (fMode) {
|
||||
@ -279,7 +288,16 @@ void GrGLBlendEffect::emitCode(GrGLShaderBuilder* builder,
|
||||
}
|
||||
}
|
||||
|
||||
GrGLEffect::EffectKey GrGLBlendEffect::GenKey(const GrEffectStage& s, const GrGLCaps&) {
|
||||
return static_cast<const GrBlendEffect&>(*s.getEffect()).mode();
|
||||
void GrGLBlendEffect::setData(const GrGLUniformManager& uman, const GrEffectStage& stage) {
|
||||
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
|
||||
|
@ -350,6 +350,8 @@ public:
|
||||
: INHERITED(factory)
|
||||
, fMatrixHandle(GrGLUniformManager::kInvalidUniformHandle)
|
||||
, fVectorHandle(GrGLUniformManager::kInvalidUniformHandle) {
|
||||
// no texture
|
||||
fRequiresTextureMatrix = false;
|
||||
}
|
||||
|
||||
virtual void emitCode(GrGLShaderBuilder* builder,
|
||||
|
@ -678,7 +678,9 @@ SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_END
|
||||
GrGLGradientEffect::GrGLGradientEffect(const GrBackendEffectFactory& factory)
|
||||
: INHERITED(factory)
|
||||
, fCachedYCoord(GR_ScalarMax)
|
||||
, fFSYUni(GrGLUniformManager::kInvalidUniformHandle) { }
|
||||
, fFSYUni(GrGLUniformManager::kInvalidUniformHandle) {
|
||||
fRequiresTextureMatrix = false;
|
||||
}
|
||||
|
||||
GrGLGradientEffect::~GrGLGradientEffect() { }
|
||||
|
||||
@ -688,13 +690,37 @@ void GrGLGradientEffect::emitYCoordUniform(GrGLShaderBuilder* builder) {
|
||||
}
|
||||
|
||||
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) {
|
||||
uman.set1f(fFSYUni, 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,
|
||||
const char* gradientTValue,
|
||||
const char* outputColor,
|
||||
@ -714,6 +740,7 @@ void GrGLGradientEffect::emitColorLookup(GrGLShaderBuilder* builder,
|
||||
|
||||
GrGradientEffect::GrGradientEffect(GrContext* ctx,
|
||||
const SkGradientShaderBase& shader,
|
||||
const SkMatrix& matrix,
|
||||
SkShader::TileMode tileMode)
|
||||
: INHERITED(1) {
|
||||
// TODO: check for simple cases where we don't need a texture:
|
||||
@ -721,6 +748,8 @@ GrGradientEffect::GrGradientEffect(GrContext* ctx,
|
||||
//shader.asAGradient(&info);
|
||||
//if (info.fColorCount == 2) { ...
|
||||
|
||||
fMatrix = matrix;
|
||||
|
||||
SkBitmap bitmap;
|
||||
shader.getGradientTableBitmap(&bitmap);
|
||||
|
||||
|
@ -193,12 +193,13 @@ private:
|
||||
#if SK_SUPPORT_GPU
|
||||
|
||||
#include "gl/GrGLEffect.h"
|
||||
#include "gl/GrGLEffectMatrix.h"
|
||||
|
||||
class GrEffectStage;
|
||||
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
|
||||
* and when vertex positions are used as texture coordinates. In the latter
|
||||
* case the texture matrix is applied to the pre-view-matrix position
|
||||
@ -228,6 +229,7 @@ public:
|
||||
|
||||
GrGradientEffect(GrContext* ctx,
|
||||
const SkGradientShaderBase& shader,
|
||||
const SkMatrix& matrix,
|
||||
SkShader::TileMode tileMode);
|
||||
|
||||
virtual ~GrGradientEffect();
|
||||
@ -236,11 +238,12 @@ public:
|
||||
|
||||
bool useAtlas() const { return SkToBool(-1 != fRow); }
|
||||
GrScalar getYCoord() const { return fYCoord; };
|
||||
const SkMatrix& getMatrix() const { return fMatrix;}
|
||||
|
||||
virtual bool isEqual(const GrEffect& effect) const SK_OVERRIDE {
|
||||
const GrGradientEffect& s = static_cast<const GrGradientEffect&>(effect);
|
||||
return INHERITED::isEqual(effect) && this->useAtlas() == s.useAtlas() &&
|
||||
fYCoord == s.getYCoord();
|
||||
fYCoord == s.getYCoord() && fMatrix.cheapEqualTo(s.getMatrix());
|
||||
}
|
||||
|
||||
protected:
|
||||
@ -263,6 +266,7 @@ private:
|
||||
GrScalar fYCoord;
|
||||
GrTextureStripAtlas* fAtlas;
|
||||
int fRow;
|
||||
SkMatrix fMatrix;
|
||||
|
||||
typedef GrEffect INHERITED;
|
||||
|
||||
@ -279,6 +283,36 @@ public:
|
||||
virtual void setData(const GrGLUniformManager&, const GrEffectStage&) SK_OVERRIDE;
|
||||
|
||||
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
|
||||
// should call this method from their emitCode().
|
||||
void emitYCoordUniform(GrGLShaderBuilder* builder);
|
||||
@ -295,6 +329,7 @@ protected:
|
||||
private:
|
||||
GrScalar fCachedYCoord;
|
||||
GrGLUniformManager::UniformHandle fFSYUni;
|
||||
GrGLEffectMatrix fEffectMatrix;
|
||||
|
||||
typedef GrGLEffect INHERITED;
|
||||
};
|
||||
|
@ -495,7 +495,9 @@ public:
|
||||
const char* inputColor,
|
||||
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:
|
||||
|
||||
@ -507,8 +509,11 @@ private:
|
||||
class GrLinearGradient : public GrGradientEffect {
|
||||
public:
|
||||
|
||||
GrLinearGradient(GrContext* ctx, const SkLinearGradient& shader, SkShader::TileMode tm)
|
||||
: INHERITED(ctx, shader, tm) { }
|
||||
GrLinearGradient(GrContext* ctx,
|
||||
const SkLinearGradient& shader,
|
||||
const SkMatrix& matrix,
|
||||
SkShader::TileMode tm)
|
||||
: INHERITED(ctx, shader, matrix, tm) { }
|
||||
virtual ~GrLinearGradient() { }
|
||||
|
||||
static const char* Name() { return "Linear Gradient"; }
|
||||
@ -553,15 +558,18 @@ GrEffect* GrLinearGradient::TestCreate(SkRandom* random,
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
|
||||
void GrGLLinearGradient::emitCode(GrGLShaderBuilder* builder,
|
||||
const GrEffectStage&,
|
||||
EffectKey,
|
||||
const GrEffectStage& stage,
|
||||
EffectKey key,
|
||||
const char* vertexCoords,
|
||||
const char* outputColor,
|
||||
const char* inputColor,
|
||||
const TextureSamplerArray& samplers) {
|
||||
this->emitYCoordUniform(builder);
|
||||
const char* coords;
|
||||
this->setupMatrix(builder, key, vertexCoords, &coords);
|
||||
SkString t;
|
||||
t.printf("%s.x", builder->defaultTexCoordsName());
|
||||
t.append(coords);
|
||||
t.append(".x");
|
||||
this->emitColorLookup(builder, t.c_str(), outputColor, inputColor, samplers[0]);
|
||||
}
|
||||
|
||||
@ -574,7 +582,7 @@ bool SkLinearGradient::asNewEffect(GrContext* context, GrEffectStage* stage) con
|
||||
return false;
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -490,7 +490,9 @@ public:
|
||||
const char* inputColor,
|
||||
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:
|
||||
|
||||
@ -503,8 +505,11 @@ private:
|
||||
class GrRadialGradient : public GrGradientEffect {
|
||||
public:
|
||||
|
||||
GrRadialGradient(GrContext* ctx, const SkRadialGradient& shader, SkShader::TileMode tm)
|
||||
: INHERITED(ctx, shader, tm) {
|
||||
GrRadialGradient(GrContext* ctx,
|
||||
const SkRadialGradient& shader,
|
||||
const SkMatrix& matrix,
|
||||
SkShader::TileMode tm)
|
||||
: INHERITED(ctx, shader, matrix, tm) {
|
||||
}
|
||||
|
||||
virtual ~GrRadialGradient() { }
|
||||
@ -551,15 +556,18 @@ GrEffect* GrRadialGradient::TestCreate(SkRandom* random,
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
|
||||
void GrGLRadialGradient::emitCode(GrGLShaderBuilder* builder,
|
||||
const GrEffectStage&,
|
||||
EffectKey,
|
||||
const GrEffectStage& stage,
|
||||
EffectKey key,
|
||||
const char* vertexCoords,
|
||||
const char* outputColor,
|
||||
const char* inputColor,
|
||||
const TextureSamplerArray& samplers) {
|
||||
this->emitYCoordUniform(builder);
|
||||
SkString t;
|
||||
t.printf("length(%s.xy)", builder->defaultTexCoordsName());
|
||||
const char* coords;
|
||||
this->setupMatrix(builder, key, vertexCoords, &coords);
|
||||
SkString t("length(");
|
||||
t.append(coords);
|
||||
t.append(")");
|
||||
this->emitColorLookup(builder, t.c_str(), outputColor, inputColor, samplers[0]);
|
||||
}
|
||||
|
||||
@ -573,7 +581,7 @@ bool SkRadialGradient::asNewEffect(GrContext* context, GrEffectStage* stage) con
|
||||
return false;
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -399,7 +399,9 @@ public:
|
||||
const char* inputColor,
|
||||
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:
|
||||
|
||||
@ -413,8 +415,9 @@ class GrSweepGradient : public GrGradientEffect {
|
||||
public:
|
||||
|
||||
GrSweepGradient(GrContext* ctx,
|
||||
const SkSweepGradient& shader)
|
||||
: INHERITED(ctx, shader, SkShader::kClamp_TileMode) { }
|
||||
const SkSweepGradient& shader,
|
||||
const SkMatrix& matrix)
|
||||
: INHERITED(ctx, shader, matrix, SkShader::kClamp_TileMode) { }
|
||||
virtual ~GrSweepGradient() { }
|
||||
|
||||
static const char* Name() { return "Sweep Gradient"; }
|
||||
@ -457,16 +460,17 @@ GrEffect* GrSweepGradient::TestCreate(SkRandom* random,
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
|
||||
void GrGLSweepGradient::emitCode(GrGLShaderBuilder* builder,
|
||||
const GrEffectStage&,
|
||||
EffectKey,
|
||||
const GrEffectStage& stage,
|
||||
EffectKey key,
|
||||
const char* vertexCoords,
|
||||
const char* outputColor,
|
||||
const char* inputColor,
|
||||
const TextureSamplerArray& samplers) {
|
||||
this->emitYCoordUniform(builder);
|
||||
const char* coords;
|
||||
this->setupMatrix(builder, key, vertexCoords, &coords);
|
||||
SkString t;
|
||||
t.printf("atan(- %s.y, - %s.x) * 0.1591549430918 + 0.5",
|
||||
builder->defaultTexCoordsName(), builder->defaultTexCoordsName());
|
||||
t.printf("atan(- %s.y, - %s.x) * 0.1591549430918 + 0.5", coords, coords);
|
||||
this->emitColorLookup(builder, t.c_str(), outputColor, inputColor, samplers[0]);
|
||||
}
|
||||
|
||||
@ -478,7 +482,7 @@ bool SkSweepGradient::asNewEffect(GrContext* context, GrEffectStage* stage) cons
|
||||
return false;
|
||||
}
|
||||
matrix.postConcat(fPtsToUnit);
|
||||
stage->setEffect(SkNEW_ARGS(GrSweepGradient, (context, *this)), matrix)->unref();
|
||||
stage->setEffect(SkNEW_ARGS(GrSweepGradient, (context, *this, matrix)))->unref();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -371,8 +371,9 @@ public:
|
||||
|
||||
GrConical2Gradient(GrContext* ctx,
|
||||
const SkTwoPointConicalGradient& shader,
|
||||
const SkMatrix& matrix,
|
||||
SkShader::TileMode tm)
|
||||
: INHERITED(ctx, shader, tm)
|
||||
: INHERITED(ctx, shader, matrix, tm)
|
||||
, fCenterX1(shader.getCenterX1())
|
||||
, fRadius0(shader.getStartRadius())
|
||||
, fDiffRadius(shader.getDiffRadius()) { }
|
||||
@ -468,12 +469,17 @@ GrGLConical2Gradient::GrGLConical2Gradient(
|
||||
}
|
||||
|
||||
void GrGLConical2Gradient::emitCode(GrGLShaderBuilder* builder,
|
||||
const GrEffectStage&,
|
||||
EffectKey,
|
||||
const GrEffectStage& stage,
|
||||
EffectKey key,
|
||||
const char* vertexCoords,
|
||||
const char* outputColor,
|
||||
const char* inputColor,
|
||||
const TextureSamplerArray& samplers) {
|
||||
const char* fsCoords;
|
||||
const char* vsCoordsVarying;
|
||||
GrSLType coordsVaryingType;
|
||||
this->setupMatrix(builder, key, vertexCoords, &fsCoords, &vsCoordsVarying, &coordsVaryingType);
|
||||
|
||||
this->emitYCoordUniform(builder);
|
||||
// 2 copies of uniform array, 1 for each of vertex & fragment shader,
|
||||
// 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
|
||||
// part of the quadratic as a varying.
|
||||
if (!builder->defaultTextureMatrixIsPerspective()) {
|
||||
if (kVec2f_GrSLType == coordsVaryingType) {
|
||||
builder->addVarying(kFloat_GrSLType, "Conical2BCoeff",
|
||||
&fVSVaryingName, &fFSVaryingName);
|
||||
}
|
||||
@ -502,11 +508,11 @@ void GrGLConical2Gradient::emitCode(GrGLShaderBuilder* builder,
|
||||
|
||||
// For radial gradients without perspective we can pass the linear
|
||||
// part of the quadratic as a varying.
|
||||
if (!builder->defaultTextureMatrixIsPerspective()) {
|
||||
if (kVec2f_GrSLType == coordsVaryingType) {
|
||||
// r2Var = -2 * (r2Parm[2] * varCoord.x - r2Param[3] * r2Param[5])
|
||||
code->appendf("\t%s = -2.0 * (%s * %s.x + %s * %s);\n",
|
||||
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,
|
||||
// bVar is the varying; otherwise compute it
|
||||
SkString bVar;
|
||||
if (!builder->defaultTextureMatrixIsPerspective()) {
|
||||
if (kVec2f_GrSLType == coordsVaryingType) {
|
||||
bVar = fFSVaryingName;
|
||||
} else {
|
||||
bVar = "b";
|
||||
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());
|
||||
}
|
||||
|
||||
@ -553,7 +559,7 @@ void GrGLConical2Gradient::emitCode(GrGLShaderBuilder* builder,
|
||||
|
||||
// c = (x^2)+(y^2) - params[4]
|
||||
code->appendf("\tfloat %s = dot(%s, %s) - %s;\n", cName.c_str(),
|
||||
builder->defaultTexCoordsName(), builder->defaultTexCoordsName(),
|
||||
fsCoords, fsCoords,
|
||||
p4.c_str());
|
||||
|
||||
// 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&) {
|
||||
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);
|
||||
}
|
||||
|
||||
stage->setEffect(SkNEW_ARGS(GrConical2Gradient, (context, *this, fTileMode)), matrix)->unref();
|
||||
stage->setEffect(SkNEW_ARGS(GrConical2Gradient, (context, *this, matrix, fTileMode)))->unref();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -404,8 +404,11 @@ private:
|
||||
class GrRadial2Gradient : public GrGradientEffect {
|
||||
public:
|
||||
|
||||
GrRadial2Gradient(GrContext* ctx, const SkTwoPointRadialGradient& shader, SkShader::TileMode tm)
|
||||
: INHERITED(ctx, shader, tm)
|
||||
GrRadial2Gradient(GrContext* ctx,
|
||||
const SkTwoPointRadialGradient& shader,
|
||||
const SkMatrix& matrix,
|
||||
SkShader::TileMode tm)
|
||||
: INHERITED(ctx, shader, matrix, tm)
|
||||
, fCenterX1(shader.getCenterX1())
|
||||
, fRadius0(shader.getStartRadius())
|
||||
, fPosRoot(shader.getDiffRadius() < 0) { }
|
||||
@ -501,14 +504,19 @@ GrGLRadial2Gradient::GrGLRadial2Gradient(
|
||||
}
|
||||
|
||||
void GrGLRadial2Gradient::emitCode(GrGLShaderBuilder* builder,
|
||||
const GrEffectStage&,
|
||||
EffectKey,
|
||||
const GrEffectStage& stage,
|
||||
EffectKey key,
|
||||
const char* vertexCoords,
|
||||
const char* outputColor,
|
||||
const char* inputColor,
|
||||
const TextureSamplerArray& samplers) {
|
||||
|
||||
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,
|
||||
// to work around Xoom bug. Doesn't seem to cause performance decrease
|
||||
// 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
|
||||
// part of the quadratic as a varying.
|
||||
if (!builder->defaultTextureMatrixIsPerspective()) {
|
||||
builder->addVarying(kFloat_GrSLType, "Radial2BCoeff",
|
||||
&fVSVaryingName, &fFSVaryingName);
|
||||
if (kVec2f_GrSLType == coordsVaryingType) {
|
||||
builder->addVarying(kFloat_GrSLType, "Radial2BCoeff", &fVSVaryingName, &fFSVaryingName);
|
||||
}
|
||||
|
||||
// VS
|
||||
@ -534,11 +541,11 @@ void GrGLRadial2Gradient::emitCode(GrGLShaderBuilder* builder,
|
||||
|
||||
// For radial gradients without perspective we can pass the linear
|
||||
// part of the quadratic as a varying.
|
||||
if (!builder->defaultTextureMatrixIsPerspective()) {
|
||||
if (kVec2f_GrSLType == coordsVaryingType) {
|
||||
// r2Var = 2 * (r2Parm[2] * varCoord.x - r2Param[3])
|
||||
code->appendf("\t%s = 2.0 *(%s * %s.x - %s);\n",
|
||||
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,
|
||||
// bVar is the varying; otherwise compute it
|
||||
SkString bVar;
|
||||
if (!builder->defaultTextureMatrixIsPerspective()) {
|
||||
if (kVec2f_GrSLType == coordsVaryingType) {
|
||||
bVar = fFSVaryingName;
|
||||
} else {
|
||||
bVar = "b";
|
||||
code->appendf("\tfloat %s = 2.0 * (%s * %s.x - %s);\n",
|
||||
bVar.c_str(), p2.c_str(),
|
||||
builder->defaultTexCoordsName(), p3.c_str());
|
||||
bVar.c_str(), p2.c_str(), fsCoords, p3.c_str());
|
||||
}
|
||||
|
||||
// c = (x^2)+(y^2) - params[4]
|
||||
code->appendf("\tfloat %s = dot(%s, %s) - %s;\n",
|
||||
cName.c_str(),
|
||||
builder->defaultTexCoordsName(),
|
||||
builder->defaultTexCoordsName(),
|
||||
fsCoords,
|
||||
fsCoords,
|
||||
p4.c_str());
|
||||
|
||||
// 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&) {
|
||||
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);
|
||||
}
|
||||
|
||||
stage->setEffect(SkNEW_ARGS(GrRadial2Gradient, (context, *this, fTileMode)), matrix)->unref();
|
||||
stage->setEffect(SkNEW_ARGS(GrRadial2Gradient, (context, *this, matrix, fTileMode)))->unref();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -1307,35 +1307,44 @@ bool GrContext::readRenderTargetPixels(GrRenderTarget* target,
|
||||
ast.set(this, desc, match);
|
||||
GrTexture* texture = ast.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) {
|
||||
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
|
||||
// there is no longer any point to using the scratch.
|
||||
if (NULL != effect || flipY || swapRAndB) {
|
||||
if (NULL == effect) {
|
||||
effect.reset(GrConfigConversionEffect::Create(src, swapRAndB));
|
||||
GrAssert(NULL != effect);
|
||||
} else {
|
||||
unpremul = false; // we will handle the UPM conversion in the draw
|
||||
if (effectInstalled || flipY || swapRAndB) {
|
||||
if (!effectInstalled) {
|
||||
SkAssertResult(GrConfigConversionEffect::InstallEffect(
|
||||
src,
|
||||
swapRAndB,
|
||||
GrConfigConversionEffect::kNone_PMConversion,
|
||||
textureMatrix,
|
||||
&stage));
|
||||
}
|
||||
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);
|
||||
GrDrawState* drawState = fGpu->drawState();
|
||||
*drawState->stage(0) = stage;
|
||||
|
||||
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));
|
||||
fGpu->drawSimpleRect(rect, NULL);
|
||||
// we want to read back from the scratch's origin
|
||||
@ -1350,7 +1359,7 @@ bool GrContext::readRenderTargetPixels(GrRenderTarget* target,
|
||||
readConfig, buffer, rowBytes, readUpsideDown)) {
|
||||
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) {
|
||||
// These are initialized to suppress a warning
|
||||
SkCanvas::Config8888 srcC8888 = SkCanvas::kNative_Premul_Config8888;
|
||||
@ -1480,7 +1489,7 @@ void GrContext::writeRenderTargetPixels(GrRenderTarget* target,
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
SkAutoTUnref<GrEffect> effect;
|
||||
|
||||
bool swapRAndB = (fGpu->preferredReadPixelsConfig(config) == GrPixelConfigSwapRAndB(config));
|
||||
|
||||
GrPixelConfig textureConfig;
|
||||
@ -1499,15 +1508,24 @@ void GrContext::writeRenderTargetPixels(GrRenderTarget* target,
|
||||
if (NULL == texture) {
|
||||
return;
|
||||
}
|
||||
|
||||
GrEffectStage stage;
|
||||
GrMatrix textureMatrix;
|
||||
textureMatrix.setIDiv(texture->width(), texture->height());
|
||||
|
||||
// allocate a tmp buffer and sw convert the pixels to premul
|
||||
SkAutoSTMalloc<128 * 128, uint32_t> tmpPixels(0);
|
||||
|
||||
bool effectInstalled = false;
|
||||
if (kUnpremul_PixelOpsFlag & flags) {
|
||||
if (kRGBA_8888_GrPixelConfig != config && kBGRA_8888_GrPixelConfig != config) {
|
||||
return;
|
||||
}
|
||||
effect.reset(this->createUPMToPMEffect(texture, swapRAndB));
|
||||
if (NULL == effect) {
|
||||
effectInstalled = this->installUPMToPMEffect(texture,
|
||||
swapRAndB,
|
||||
textureMatrix,
|
||||
&stage);
|
||||
if (!effectInstalled) {
|
||||
SkCanvas::Config8888 srcConfig8888, dstConfig8888;
|
||||
GR_DEBUGCODE(bool success = )
|
||||
grconfig_to_config8888(config, true, &srcConfig8888);
|
||||
@ -1524,9 +1542,13 @@ void GrContext::writeRenderTargetPixels(GrRenderTarget* target,
|
||||
rowBytes = 4 * width;
|
||||
}
|
||||
}
|
||||
if (NULL == effect) {
|
||||
effect.reset(GrConfigConversionEffect::Create(texture, swapRAndB));
|
||||
GrAssert(NULL != effect);
|
||||
if (!effectInstalled) {
|
||||
SkAssertResult(GrConfigConversionEffect::InstallEffect(
|
||||
texture,
|
||||
swapRAndB,
|
||||
GrConfigConversionEffect::kNone_PMConversion,
|
||||
textureMatrix,
|
||||
&stage));
|
||||
}
|
||||
|
||||
this->writeTexturePixels(texture,
|
||||
@ -1536,15 +1558,13 @@ void GrContext::writeRenderTargetPixels(GrRenderTarget* target,
|
||||
|
||||
GrDrawTarget::AutoStateRestore asr(fGpu, GrDrawTarget::kReset_ASRInit);
|
||||
GrDrawState* drawState = fGpu->drawState();
|
||||
*drawState->stage(0) = stage;
|
||||
|
||||
GrMatrix matrix;
|
||||
matrix.setTranslate(GrIntToScalar(left), GrIntToScalar(top));
|
||||
drawState->setViewMatrix(matrix);
|
||||
drawState->setRenderTarget(target);
|
||||
|
||||
matrix.setIDiv(texture->width(), texture->height());
|
||||
drawState->stage(0)->setEffect(effect, matrix);
|
||||
|
||||
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) {
|
||||
test_pm_conversions(this, &fPMToUPMConversion, &fUPMToPMConversion);
|
||||
fDidTestPMConversions = true;
|
||||
@ -1734,13 +1757,17 @@ GrEffect* GrContext::createPMToUPMEffect(GrTexture* texture, bool swapRAndB) {
|
||||
GrConfigConversionEffect::PMConversion pmToUPM =
|
||||
static_cast<GrConfigConversionEffect::PMConversion>(fPMToUPMConversion);
|
||||
if (GrConfigConversionEffect::kNone_PMConversion != pmToUPM) {
|
||||
return GrConfigConversionEffect::Create(texture, swapRAndB, pmToUPM);
|
||||
GrConfigConversionEffect::InstallEffect(texture, swapRAndB, pmToUPM, matrix, stage);
|
||||
return true;
|
||||
} 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) {
|
||||
test_pm_conversions(this, &fPMToUPMConversion, &fUPMToPMConversion);
|
||||
fDidTestPMConversions = true;
|
||||
@ -1748,9 +1775,10 @@ GrEffect* GrContext::createUPMToPMEffect(GrTexture* texture, bool swapRAndB) {
|
||||
GrConfigConversionEffect::PMConversion upmToPM =
|
||||
static_cast<GrConfigConversionEffect::PMConversion>(fUPMToPMConversion);
|
||||
if (GrConfigConversionEffect::kNone_PMConversion != upmToPM) {
|
||||
return GrConfigConversionEffect::Create(texture, swapRAndB, upmToPM);
|
||||
GrConfigConversionEffect::InstallEffect(texture, swapRAndB, upmToPM, matrix, stage);
|
||||
return true;
|
||||
} else {
|
||||
return NULL;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1808,7 +1836,7 @@ GrTexture* GrContext::gaussianBlur(GrTexture* srcTexture,
|
||||
i < scaleFactorY ? 0.5f : 1.0f);
|
||||
|
||||
paint.colorStage(0)->setEffect(SkNEW_ARGS(GrSingleTextureEffect,
|
||||
(srcTexture, true)), matrix)->unref();
|
||||
(srcTexture, matrix, true)))->unref();
|
||||
this->drawRectToRect(paint, dstRect, srcRect);
|
||||
srcRect = dstRect;
|
||||
srcTexture = dstTexture;
|
||||
@ -1865,8 +1893,8 @@ GrTexture* GrContext::gaussianBlur(GrTexture* srcTexture,
|
||||
// FIXME: This should be mitchell, not bilinear.
|
||||
matrix.setIDiv(srcTexture->width(), srcTexture->height());
|
||||
this->setRenderTarget(dstTexture->asRenderTarget());
|
||||
paint.colorStage(0)->setEffect(SkNEW_ARGS(GrSingleTextureEffect,(srcTexture, true)),
|
||||
matrix)->unref();
|
||||
paint.colorStage(0)->setEffect(SkNEW_ARGS(GrSingleTextureEffect,(srcTexture,
|
||||
matrix, true)))->unref();
|
||||
SkRect dstRect(srcRect);
|
||||
scale_rect(&dstRect, (float) scaleFactorX, (float) scaleFactorY);
|
||||
this->drawRectToRect(paint, dstRect, srcRect);
|
||||
|
@ -198,16 +198,16 @@ public:
|
||||
}
|
||||
void createTextureEffect(int stageIdx, GrTexture* texture, const GrMatrix& matrix) {
|
||||
GrAssert(!this->getStage(stageIdx).getEffect());
|
||||
GrEffect* effect = SkNEW_ARGS(GrSingleTextureEffect, (texture));
|
||||
this->stage(stageIdx)->setEffect(effect, matrix)->unref();
|
||||
GrEffect* effect = SkNEW_ARGS(GrSingleTextureEffect, (texture, matrix));
|
||||
this->stage(stageIdx)->setEffect(effect)->unref();
|
||||
}
|
||||
void createTextureEffect(int stageIdx,
|
||||
GrTexture* texture,
|
||||
const GrMatrix& matrix,
|
||||
const GrTextureParams& params) {
|
||||
GrAssert(!this->getStage(stageIdx).getEffect());
|
||||
GrEffect* effect = SkNEW_ARGS(GrSingleTextureEffect, (texture, params));
|
||||
this->stage(stageIdx)->setEffect(effect, matrix)->unref();
|
||||
GrEffect* effect = SkNEW_ARGS(GrSingleTextureEffect, (texture, matrix, params));
|
||||
this->stage(stageIdx)->setEffect(effect)->unref();
|
||||
}
|
||||
|
||||
|
||||
|
@ -20,6 +20,26 @@ SkTArray<GrEffectTestFactory*, true>* GrEffectTestFactory::GetFactories() {
|
||||
}
|
||||
#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 {
|
||||
public:
|
||||
static GrMemoryPool* GetTLS() {
|
||||
|
@ -608,7 +608,7 @@ inline bool skPaint2GrPaintShader(SkGpuDevice* dev,
|
||||
GrScalar sy = SkFloatToScalar(1.f / bitmap.height());
|
||||
matrix.postScale(sx, sy);
|
||||
}
|
||||
stage->setEffect(SkNEW_ARGS(GrSingleTextureEffect, (texture, params)), matrix)->unref();
|
||||
stage->setEffect(SkNEW_ARGS(GrSingleTextureEffect, (texture, matrix, params)))->unref();
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -875,7 +875,7 @@ bool drawWithGPUMaskFilter(GrContext* context, const SkPath& devPath,
|
||||
matrix.setIDiv(pathTexture->width(), pathTexture->height());
|
||||
// Blend pathTexture over blurTexture.
|
||||
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) {
|
||||
// inner: dst = dst * src
|
||||
paint.setBlendFunc(kDC_GrBlendCoeff, kZero_GrBlendCoeff);
|
||||
@ -906,7 +906,7 @@ bool drawWithGPUMaskFilter(GrContext* context, const SkPath& devPath,
|
||||
matrix.postIDiv(blurTexture->width(), blurTexture->height());
|
||||
|
||||
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);
|
||||
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.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;
|
||||
d.setLTRB(GrIntToScalar(dstM.fBounds.fLeft),
|
||||
GrIntToScalar(dstM.fBounds.fTop),
|
||||
|
@ -218,21 +218,27 @@ void GrConfigConversionEffect::TestForPreservingPMConversions(GrContext* context
|
||||
}
|
||||
}
|
||||
|
||||
GrEffect* GrConfigConversionEffect::Create(GrTexture* texture,
|
||||
bool swapRedAndBlue,
|
||||
PMConversion pmConversion) {
|
||||
bool GrConfigConversionEffect::InstallEffect(GrTexture* texture,
|
||||
bool swapRedAndBlue,
|
||||
PMConversion pmConversion,
|
||||
const GrMatrix& matrix,
|
||||
GrEffectStage* stage) {
|
||||
if (!swapRedAndBlue && kNone_PMConversion == pmConversion) {
|
||||
// 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
|
||||
// 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 {
|
||||
if (kRGBA_8888_GrPixelConfig != texture->config() &&
|
||||
kBGRA_8888_GrPixelConfig != texture->config() &&
|
||||
kNone_PMConversion != pmConversion) {
|
||||
// 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
|
||||
};
|
||||
|
||||
// This will fail if the config is not 8888 and a PM conversion is requested.
|
||||
static GrEffect* Create(GrTexture*,
|
||||
bool swapRedAndBlue,
|
||||
PMConversion pmConversion = kNone_PMConversion);
|
||||
// Installs an effect in the GrEffectStage to perform a config conversion.
|
||||
static bool InstallEffect(GrTexture*,
|
||||
bool swapRedAndBlue,
|
||||
PMConversion pmConversion,
|
||||
const GrMatrix& matrix,
|
||||
GrEffectStage* stage);
|
||||
|
||||
static const char* Name() { return "Config Conversion"; }
|
||||
typedef GrGLConfigConversionEffect GLEffect;
|
||||
|
@ -7,6 +7,7 @@
|
||||
|
||||
#include "effects/GrSingleTextureEffect.h"
|
||||
#include "gl/GrGLEffect.h"
|
||||
#include "gl/GrGLEffectMatrix.h"
|
||||
#include "gl/GrGLSL.h"
|
||||
#include "gl/GrGLTexture.h"
|
||||
#include "GrTBackendEffectFactory.h"
|
||||
@ -16,25 +17,43 @@ class GrGLSingleTextureEffect : public GrGLEffect {
|
||||
public:
|
||||
GrGLSingleTextureEffect(const GrBackendEffectFactory& factory, const GrEffect&)
|
||||
: INHERITED (factory) {
|
||||
fRequiresTextureMatrix = false;
|
||||
}
|
||||
|
||||
virtual void emitCode(GrGLShaderBuilder* builder,
|
||||
const GrEffectStage&,
|
||||
EffectKey,
|
||||
EffectKey key,
|
||||
const char* vertexCoords,
|
||||
const char* outputColor,
|
||||
const char* inputColor,
|
||||
const TextureSamplerArray& samplers) SK_OVERRIDE {
|
||||
|
||||
const char* coordName;
|
||||
GrSLType coordType = fEffectMatrix.emitCode(builder, key, vertexCoords, &coordName);
|
||||
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");
|
||||
}
|
||||
|
||||
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:
|
||||
|
||||
GrGLEffectMatrix fEffectMatrix;
|
||||
typedef GrGLEffect INHERITED;
|
||||
};
|
||||
|
||||
@ -43,16 +62,39 @@ private:
|
||||
GrSingleTextureEffect::GrSingleTextureEffect(GrTexture* texture)
|
||||
: INHERITED(1)
|
||||
, fTextureAccess(texture) {
|
||||
fMatrix.reset();
|
||||
}
|
||||
|
||||
GrSingleTextureEffect::GrSingleTextureEffect(GrTexture* texture, bool bilerp)
|
||||
: INHERITED(1)
|
||||
, fTextureAccess(texture, bilerp) {
|
||||
fMatrix.reset();
|
||||
}
|
||||
|
||||
GrSingleTextureEffect::GrSingleTextureEffect(GrTexture* texture, const GrTextureParams& params)
|
||||
: INHERITED(1)
|
||||
, 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() {
|
||||
@ -76,5 +118,6 @@ GrEffect* GrSingleTextureEffect::TestCreate(SkRandom* random,
|
||||
GrTexture* textures[]) {
|
||||
int texIdx = random->nextBool() ? GrEffectUnitTest::kSkiaPMTextureIdx :
|
||||
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
|
||||
|
||||
#include "GrEffect.h"
|
||||
#include "GrMatrix.h"
|
||||
|
||||
class GrGLSingleTextureEffect;
|
||||
|
||||
@ -18,28 +19,37 @@ class GrGLSingleTextureEffect;
|
||||
class GrSingleTextureEffect : public GrEffect {
|
||||
|
||||
public:
|
||||
/** Uses default texture params (unfiltered, clamp) */
|
||||
GrSingleTextureEffect(GrTexture* texture);
|
||||
|
||||
/** Uses default tile mode (clamp) */
|
||||
GrSingleTextureEffect(GrTexture* texture, bool bilerp);
|
||||
|
||||
/** These three constructors assume an identity matrix */
|
||||
GrSingleTextureEffect(GrTexture* texture); /* unfiltered, clamp mode */
|
||||
GrSingleTextureEffect(GrTexture* texture, bool bilerp); /* clamp mode */
|
||||
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 const GrTextureAccess& textureAccess(int index) const SK_OVERRIDE;
|
||||
|
||||
static const char* Name() { return "Single Texture"; }
|
||||
|
||||
const GrMatrix& getMatrix() const { return fMatrix; }
|
||||
|
||||
typedef GrGLSingleTextureEffect GLEffect;
|
||||
|
||||
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:
|
||||
GR_DECLARE_EFFECT_TEST;
|
||||
|
||||
GrTextureAccess fTextureAccess;
|
||||
GrMatrix fMatrix;
|
||||
|
||||
typedef GrEffect INHERITED;
|
||||
};
|
||||
|
@ -10,6 +10,8 @@
|
||||
|
||||
GrGLEffect::GrGLEffect(const GrBackendEffectFactory& factory)
|
||||
: fFactory(factory) {
|
||||
|
||||
fRequiresTextureMatrix = true;
|
||||
}
|
||||
|
||||
GrGLEffect::~GrGLEffect() {
|
||||
|
@ -51,7 +51,9 @@ public:
|
||||
|
||||
@param builder Interface used to emit code in the shaders.
|
||||
@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
|
||||
be removed soon and stages will be responsible for computing their own
|
||||
coords.
|
||||
@ -85,7 +87,14 @@ public:
|
||||
|
||||
static EffectKey GenTextureKey(const GrEffect&, const GrGLCaps&);
|
||||
|
||||
bool requiresTextureMatrix() const { return fRequiresTextureMatrix; }
|
||||
|
||||
|
||||
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;
|
||||
};
|
||||
|
213
src/gpu/gl/GrGLEffectMatrix.cpp
Normal file
213
src/gpu/gl/GrGLEffectMatrix.cpp
Normal file
@ -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.");
|
||||
}
|
||||
}
|
97
src/gpu/gl/GrGLEffectMatrix.h
Normal file
97
src/gpu/gl/GrGLEffectMatrix.h
Normal file
@ -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,57 +909,64 @@ GrGLEffect* GrGLProgram::GenStageCode(const GrEffectStage& stage,
|
||||
|
||||
/// Vertex Shader Stuff
|
||||
|
||||
// decide whether we need a matrix to transform texture coords and whether the varying needs a
|
||||
// perspective coord.
|
||||
const char* matName = NULL;
|
||||
GrSLType texCoordVaryingType;
|
||||
if (desc.fOptFlags & StageDesc::kIdentityMatrix_OptFlagBit) {
|
||||
texCoordVaryingType = kVec2f_GrSLType;
|
||||
} else {
|
||||
uniforms->fTextureMatrixUni = builder->addUniform(GrGLShaderBuilder::kVertex_ShaderType,
|
||||
kMat33f_GrSLType, "TexM", &matName);
|
||||
builder->getUniformVariable(uniforms->fTextureMatrixUni);
|
||||
const char* vertexCoords;
|
||||
|
||||
if (desc.fOptFlags & StageDesc::kNoPerspective_OptFlagBit) {
|
||||
// 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;
|
||||
GrSLType texCoordVaryingType;
|
||||
if (desc.fOptFlags & StageDesc::kIdentityMatrix_OptFlagBit) {
|
||||
texCoordVaryingType = kVec2f_GrSLType;
|
||||
} else {
|
||||
texCoordVaryingType = kVec3f_GrSLType;
|
||||
}
|
||||
}
|
||||
const char *varyingVSName, *varyingFSName;
|
||||
builder->addVarying(texCoordVaryingType,
|
||||
"Stage",
|
||||
&varyingVSName,
|
||||
&varyingFSName);
|
||||
builder->setupTextureAccess(varyingFSName, texCoordVaryingType);
|
||||
uniforms->fTextureMatrixUni = builder->addUniform(GrGLShaderBuilder::kVertex_ShaderType,
|
||||
kMat33f_GrSLType, "TexM", &matName);
|
||||
builder->getUniformVariable(uniforms->fTextureMatrixUni);
|
||||
|
||||
if (desc.fOptFlags & StageDesc::kNoPerspective_OptFlagBit) {
|
||||
texCoordVaryingType = kVec2f_GrSLType;
|
||||
} else {
|
||||
texCoordVaryingType = kVec3f_GrSLType;
|
||||
}
|
||||
}
|
||||
const char *varyingVSName, *varyingFSName;
|
||||
builder->addVarying(texCoordVaryingType,
|
||||
"Stage",
|
||||
&varyingVSName,
|
||||
&varyingFSName);
|
||||
builder->setupTextureAccess(varyingFSName, texCoordVaryingType);
|
||||
|
||||
if (!matName) {
|
||||
GrAssert(kVec2f_GrSLType == texCoordVaryingType);
|
||||
builder->fVSCode.appendf("\t%s = %s;\n", varyingVSName, vsInCoord);
|
||||
} else {
|
||||
// varying = texMatrix * texCoord
|
||||
builder->fVSCode.appendf("\t%s = (%s * vec3(%s, 1))%s;\n",
|
||||
varyingVSName, matName, vsInCoord,
|
||||
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);
|
||||
}
|
||||
|
||||
if (!matName) {
|
||||
GrAssert(kVec2f_GrSLType == texCoordVaryingType);
|
||||
builder->fVSCode.appendf("\t%s = %s;\n", varyingVSName, vsInCoord);
|
||||
} else {
|
||||
// varying = texMatrix * texCoord
|
||||
builder->fVSCode.appendf("\t%s = (%s * vec3(%s, 1))%s;\n",
|
||||
varyingVSName, matName, vsInCoord,
|
||||
vector_all_coords(GrSLTypeToVecLength(texCoordVaryingType)));
|
||||
}
|
||||
|
||||
// Enclose custom code in a block to avoid namespace conflicts
|
||||
builder->fVSCode.appendf("\t{ // %s\n", glEffect->name());
|
||||
builder->fFSCode.appendf("\t{ // %s \n", glEffect->name());
|
||||
glEffect->emitCode(builder,
|
||||
stage,
|
||||
desc.fEffectKey,
|
||||
varyingVSName,
|
||||
vertexCoords,
|
||||
fsOutColor,
|
||||
fsInColor,
|
||||
textureSamplers);
|
||||
|
@ -8,6 +8,7 @@
|
||||
#include "gl/GrGLShaderBuilder.h"
|
||||
#include "gl/GrGLProgram.h"
|
||||
#include "gl/GrGLUniformHandle.h"
|
||||
#include "SkMatrix.h"
|
||||
|
||||
#define ASSERT_ARRAY_UPLOAD_IN_BOUNDS(UNI, OFFSET, COUNT) \
|
||||
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) {
|
||||
GrAssert(uniforms.count() == fUniforms.count());
|
||||
int count = fUniforms.count();
|
||||
|
@ -15,6 +15,7 @@
|
||||
#include "SkTArray.h"
|
||||
|
||||
class GrGLContextInfo;
|
||||
class SkMatrix;
|
||||
|
||||
/** Manages a program's uniforms.
|
||||
*/
|
||||
@ -47,6 +48,9 @@ public:
|
||||
void setMatrix3fv(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 {
|
||||
GrGLShaderVar fVariable;
|
||||
uint32_t fVisibility;
|
||||
|
@ -184,7 +184,12 @@ void forceLinking();
|
||||
void forceLinking() {
|
||||
SkLightingImageFilter::CreateDistantLitDiffuse(SkPoint3(0,0,0), 0, 0, 0);
|
||||
SkMagnifierImageFilter mag(SkRect::MakeWH(SK_Scalar1, SK_Scalar1), SK_Scalar1);
|
||||
GrConfigConversionEffect::Create(NULL, false);
|
||||
GrEffectStage dummyStage;
|
||||
GrConfigConversionEffect::InstallEffect(NULL,
|
||||
false,
|
||||
GrConfigConversionEffect::kNone_PMConversion,
|
||||
GrMatrix::I(),
|
||||
&dummyStage);
|
||||
SkScalar matrix[20];
|
||||
SkColorMatrixFilter cmf(matrix);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user