blob: f87b9b4e10111485e865dd0a935ed92563e38723 [file] [log] [blame]
/*
* Copyright 2010 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#ifndef GrSamplerState_DEFINED
#define GrSamplerState_DEFINED
#include "GrCustomStage.h"
#include "GrMatrix.h"
#include "GrTypes.h"
#include "SkShader.h"
class GrTextureParams {
public:
GrTextureParams() {
this->reset();
}
GrTextureParams(const GrTextureParams& params) {
*this = params;
}
GrTextureParams& operator =(const GrTextureParams& params) {
fTileModes[0] = params.fTileModes[0];
fTileModes[1] = params.fTileModes[1];
fBilerp = params.fBilerp;
return *this;
}
void reset() {
this->reset(SkShader::kClamp_TileMode, false);
}
void reset(SkShader::TileMode tileXAndY, bool filter) {
fTileModes[0] = fTileModes[1] = tileXAndY;
fBilerp = filter;
}
void reset(SkShader::TileMode tileModes[2], bool filter) {
fTileModes[0] = tileModes[0];
fTileModes[1] = tileModes[1];
fBilerp = filter;
}
void setClampNoFilter() {
fTileModes[0] = fTileModes[1] = SkShader::kClamp_TileMode;
fBilerp = false;
}
void setClamp() {
fTileModes[0] = fTileModes[1] = SkShader::kClamp_TileMode;
}
void setBilerp(bool bilerp) { fBilerp = bilerp; }
void setTileModeX(const SkShader::TileMode tm) { fTileModes[0] = tm; }
void setTileModeY(const SkShader::TileMode tm) { fTileModes[1] = tm; }
void setTileModeXAndY(const SkShader::TileMode tm) { fTileModes[0] = fTileModes[1] = tm; }
SkShader::TileMode getTileModeX() const { return fTileModes[0]; }
SkShader::TileMode getTileModeY() const { return fTileModes[1]; }
bool isTiled() const {
return SkShader::kClamp_TileMode != fTileModes[0] ||
SkShader::kClamp_TileMode != fTileModes[1];
}
bool isBilerp() const { return fBilerp; }
private:
SkShader::TileMode fTileModes[2];
bool fBilerp;
};
class GrSamplerState {
public:
static const bool kBilerpDefault = false;
static const SkShader::TileMode kTileModeDefault = SkShader::kClamp_TileMode;
/**
* Default sampler state is set to clamp, use normal sampling mode, be
* unfiltered, and use identity matrix.
*/
GrSamplerState()
: fCustomStage (NULL) {
memset(this, 0, sizeof(GrSamplerState));
this->reset();
}
~GrSamplerState() {
GrSafeUnref(fCustomStage);
}
bool operator ==(const GrSamplerState& s) const {
/* We must be bit-identical as far as the CustomStage;
there may be multiple CustomStages that will produce
the same shader code and so are equivalent.
Can't take the address of fWrapX because it's :8 */
int bitwiseRegion = (intptr_t) &fCustomStage - (intptr_t) this;
GrAssert(sizeof(GrSamplerState) ==
bitwiseRegion + sizeof(fCustomStage));
return !memcmp(this, &s, bitwiseRegion) &&
((fCustomStage == s.fCustomStage) ||
(fCustomStage && s.fCustomStage &&
(fCustomStage->getFactory() ==
s.fCustomStage->getFactory()) &&
fCustomStage->isEqual(*s.fCustomStage)));
}
bool operator !=(const GrSamplerState& s) const { return !(*this == s); }
GrSamplerState& operator =(const GrSamplerState& s) {
// memcpy() breaks refcounting
fTextureParams = s.fTextureParams;
fMatrix = s.fMatrix;
fSwapRAndB = s.fSwapRAndB;
GrSafeAssign(fCustomStage, s.fCustomStage);
return *this;
}
const GrMatrix& getMatrix() const { return fMatrix; }
bool swapsRAndB() const { return fSwapRAndB; }
bool premultiply() const { return fPremultiply; }
GrTextureParams* textureParams() { return &fTextureParams; }
const GrTextureParams& getTextureParams() const { return fTextureParams; }
/**
* Access the sampler's matrix. See SampleMode for explanation of
* relationship between the matrix and sample mode.
*/
GrMatrix* matrix() { return &fMatrix; }
/**
* Swaps the R and B components when reading from the texture. Has no effect
* if the texture is alpha only.
*/
void setRAndBSwap(bool swap) { fSwapRAndB = swap; }
/**
* If the texture is RGBA/BGRA 8888 config then its rgb components will be
* multiplied by its a component after the texture read.
**/
void setPremultiply(bool premul) { fPremultiply = premul; }
/**
* Multiplies the current sampler matrix a matrix
*
* After this call M' = M*m where M is the old matrix, m is the parameter
* to this function, and M' is the new matrix. (We consider points to
* be column vectors so tex cood vector t is transformed by matrix X as
* t' = X*t.)
*
* @param matrix the matrix used to modify the matrix.
*/
void preConcatMatrix(const GrMatrix& matrix) { fMatrix.preConcat(matrix); }
void reset(SkShader::TileMode tileXAndY,
bool filter,
const GrMatrix& matrix) {
fTextureParams.reset(tileXAndY, filter);
fMatrix = matrix;
fSwapRAndB = false;
fPremultiply = false;
GrSafeSetNull(fCustomStage);
}
void reset(SkShader::TileMode wrapXAndY, bool filter) {
this->reset(wrapXAndY, filter, GrMatrix::I());
}
void reset(const GrMatrix& matrix) {
this->reset(kTileModeDefault, kBilerpDefault, matrix);
}
void reset() {
this->reset(kTileModeDefault, kBilerpDefault, GrMatrix::I());
}
GrCustomStage* setCustomStage(GrCustomStage* stage) {
GrSafeAssign(fCustomStage, stage);
return stage;
}
const GrCustomStage* getCustomStage() const { return fCustomStage; }
private:
GrTextureParams fTextureParams;
bool fSwapRAndB;
bool fPremultiply; // temporary, will be replaced soon by a custom stage.
GrMatrix fMatrix;
GrCustomStage* fCustomStage;
};
#endif