1e8f016305
where feasible, through convenience function on GrDrawState. http://codereview.appspot.com/6425055/ git-svn-id: http://skia.googlecode.com/svn/trunk@4694 2bbb7eff-a529-9590-31e7-b0007b416f81
290 lines
8.1 KiB
C++
290 lines
8.1 KiB
C++
|
|
/*
|
|
* Copyright 2011 Google Inc.
|
|
*
|
|
* Use of this source code is governed by a BSD-style license that can be
|
|
* found in the LICENSE file.
|
|
*/
|
|
|
|
|
|
#ifndef GrPaint_DEFINED
|
|
#define GrPaint_DEFINED
|
|
|
|
#include "GrTexture.h"
|
|
#include "GrColor.h"
|
|
#include "GrSamplerState.h"
|
|
|
|
#include "SkXfermode.h"
|
|
|
|
/**
|
|
* The paint describes how pixels are colored when the context draws to
|
|
* them. TODO: Make this a "real" class with getters and setters, default
|
|
* values, and documentation.
|
|
*/
|
|
class GrPaint {
|
|
public:
|
|
enum {
|
|
kMaxTextures = 2,
|
|
kMaxMasks = 1,
|
|
};
|
|
|
|
// All the paint fields are public except textures/samplers
|
|
GrBlendCoeff fSrcBlendCoeff;
|
|
GrBlendCoeff fDstBlendCoeff;
|
|
bool fAntiAlias;
|
|
bool fDither;
|
|
bool fColorMatrixEnabled;
|
|
|
|
GrColor fColor;
|
|
uint8_t fCoverage;
|
|
|
|
GrColor fColorFilterColor;
|
|
SkXfermode::Mode fColorFilterXfermode;
|
|
float fColorMatrix[20];
|
|
|
|
void setTexture(int i, GrTexture* texture) {
|
|
GrAssert((unsigned)i < kMaxTextures);
|
|
GrSafeRef(texture);
|
|
GrSafeUnref(fTextures[i]);
|
|
fTextures[i] = texture;
|
|
}
|
|
|
|
GrTexture* getTexture(int i) const {
|
|
GrAssert((unsigned)i < kMaxTextures);
|
|
//if (this->getTextureSampler(i).getCustomStage()) {
|
|
//return this->getTextureSampler(i).getCustomStage()->texture(i);
|
|
//}
|
|
return fTextures[i];
|
|
}
|
|
|
|
GrSamplerState* textureSampler(int i) {
|
|
GrAssert((unsigned)i < kMaxTextures);
|
|
return fTextureSamplers + i;
|
|
}
|
|
|
|
const GrSamplerState& getTextureSampler(int i) const {
|
|
GrAssert((unsigned)i < kMaxTextures);
|
|
return fTextureSamplers[i];
|
|
}
|
|
|
|
bool isTextureStageEnabled(int i) const {
|
|
GrAssert((unsigned)i < kMaxTextures);
|
|
return (NULL != fTextures[i]) ||
|
|
(NULL != fTextureSamplers[i].getCustomStage());
|
|
}
|
|
|
|
// The mask can be alpha-only or per channel. It is applied
|
|
// after the colorfilter
|
|
void setMask(int i, GrTexture* mask) {
|
|
GrAssert((unsigned)i < kMaxMasks);
|
|
GrSafeRef(mask);
|
|
GrSafeUnref(fMaskTextures[i]);
|
|
fMaskTextures[i] = mask;
|
|
}
|
|
|
|
GrTexture* getMask(int i) const {
|
|
GrAssert((unsigned)i < kMaxMasks);
|
|
//if (this->getMaskSampler(i).getCustomStage()) {
|
|
//return this->getMaskSampler(i).getCustomStage()->texture(i);
|
|
//}
|
|
return fMaskTextures[i];
|
|
}
|
|
|
|
// mask's sampler matrix is always applied to the positions
|
|
// (i.e. no explicit texture coordinates)
|
|
GrSamplerState* maskSampler(int i) {
|
|
GrAssert((unsigned)i < kMaxMasks);
|
|
return fMaskSamplers + i;
|
|
}
|
|
|
|
const GrSamplerState& getMaskSampler(int i) const {
|
|
GrAssert((unsigned)i < kMaxMasks);
|
|
return fMaskSamplers[i];
|
|
}
|
|
|
|
bool isMaskStageEnabled(int i) const {
|
|
GrAssert((unsigned)i < kMaxTextures);
|
|
return (NULL != fMaskTextures[i]) ||
|
|
(NULL != fMaskSamplers[i].getCustomStage());
|
|
}
|
|
|
|
bool hasMask() const {
|
|
for (int i = 0; i < kMaxMasks; ++i) {
|
|
if (this->isMaskStageEnabled(i)) {
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
bool hasTexture() const {
|
|
for (int i = 0; i < kMaxTextures; ++i) {
|
|
if (this->isTextureStageEnabled(i)) {
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
bool hasTextureOrMask() const { return this->hasTexture() || this->hasMask(); }
|
|
|
|
/**
|
|
* Preconcats the matrix of all samplers in the mask with the inverse of a
|
|
* matrix. If the matrix inverse cannot be computed (and there is at least
|
|
* one enabled stage) then false is returned.
|
|
*/
|
|
bool preConcatSamplerMatricesWithInverse(const GrMatrix& matrix) {
|
|
GrMatrix inv;
|
|
bool computed = false;
|
|
for (int i = 0; i < kMaxTextures; ++i) {
|
|
if (this->isTextureStageEnabled(i)) {
|
|
if (!computed && !matrix.invert(&inv)) {
|
|
return false;
|
|
} else {
|
|
computed = true;
|
|
}
|
|
fTextureSamplers[i].preConcatMatrix(inv);
|
|
}
|
|
}
|
|
for (int i = 0; i < kMaxMasks; ++i) {
|
|
if (this->isMaskStageEnabled(i)) {
|
|
if (!computed && !matrix.invert(&inv)) {
|
|
return false;
|
|
} else {
|
|
computed = true;
|
|
}
|
|
fMaskSamplers[i].preConcatMatrix(inv);
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
// uninitialized
|
|
GrPaint() {
|
|
for (int i = 0; i < kMaxTextures; ++i) {
|
|
fTextures[i] = NULL;
|
|
}
|
|
for (int i = 0; i < kMaxMasks; ++i) {
|
|
fMaskTextures[i] = NULL;
|
|
}
|
|
}
|
|
|
|
GrPaint(const GrPaint& paint) {
|
|
for (int i = 0; i < kMaxTextures; ++i) {
|
|
fTextures[i] = NULL;
|
|
}
|
|
for (int i = 0; i < kMaxMasks; ++i) {
|
|
fMaskTextures[i] = NULL;
|
|
}
|
|
*this = paint;
|
|
}
|
|
|
|
GrPaint& operator=(const GrPaint& paint) {
|
|
fSrcBlendCoeff = paint.fSrcBlendCoeff;
|
|
fDstBlendCoeff = paint.fDstBlendCoeff;
|
|
fAntiAlias = paint.fAntiAlias;
|
|
fDither = paint.fDither;
|
|
|
|
fColor = paint.fColor;
|
|
fCoverage = paint.fCoverage;
|
|
|
|
fColorFilterColor = paint.fColorFilterColor;
|
|
fColorFilterXfermode = paint.fColorFilterXfermode;
|
|
fColorMatrixEnabled = paint.fColorMatrixEnabled;
|
|
if (fColorMatrixEnabled) {
|
|
memcpy(fColorMatrix, paint.fColorMatrix, sizeof(fColorMatrix));
|
|
}
|
|
|
|
for (int i = 0; i < kMaxTextures; ++i) {
|
|
GrSafeAssign(fTextures[i], paint.fTextures[i]);
|
|
if (paint.isTextureStageEnabled(i)) {
|
|
fTextureSamplers[i] = paint.fTextureSamplers[i];
|
|
}
|
|
}
|
|
for (int i = 0; i < kMaxMasks; ++i) {
|
|
GrSafeAssign(fMaskTextures[i], paint.fMaskTextures[i]);
|
|
if (paint.isMaskStageEnabled(i)) {
|
|
fMaskSamplers[i] = paint.fMaskSamplers[i];
|
|
}
|
|
}
|
|
return *this;
|
|
}
|
|
|
|
~GrPaint() {
|
|
for (int i = 0; i < kMaxTextures; ++i) {
|
|
GrSafeUnref(fTextures[i]);
|
|
}
|
|
for (int i = 0; i < kMaxMasks; ++i) {
|
|
GrSafeUnref(fMaskTextures[i]);
|
|
}
|
|
}
|
|
|
|
// sets paint to src-over, solid white, no texture, no mask
|
|
void reset() {
|
|
this->resetBlend();
|
|
this->resetOptions();
|
|
this->resetColor();
|
|
this->resetCoverage();
|
|
this->resetTextures();
|
|
this->resetColorFilter();
|
|
this->resetMasks();
|
|
}
|
|
|
|
void resetColorFilter() {
|
|
fColorFilterXfermode = SkXfermode::kDst_Mode;
|
|
fColorFilterColor = GrColorPackRGBA(0xff, 0xff, 0xff, 0xff);
|
|
fColorMatrixEnabled = false;
|
|
}
|
|
|
|
// internal use
|
|
// GrPaint's textures and masks map to the first N stages
|
|
// of GrDrawTarget in that order (textures followed by masks)
|
|
enum {
|
|
kFirstTextureStage = 0,
|
|
kFirstMaskStage = kMaxTextures,
|
|
kTotalStages = kMaxTextures + kMaxMasks,
|
|
};
|
|
|
|
private:
|
|
|
|
GrSamplerState fTextureSamplers[kMaxTextures];
|
|
GrSamplerState fMaskSamplers[kMaxMasks];
|
|
|
|
GrTexture* fTextures[kMaxTextures];
|
|
GrTexture* fMaskTextures[kMaxMasks];
|
|
|
|
void resetBlend() {
|
|
fSrcBlendCoeff = kOne_GrBlendCoeff;
|
|
fDstBlendCoeff = kZero_GrBlendCoeff;
|
|
}
|
|
|
|
void resetOptions() {
|
|
fAntiAlias = false;
|
|
fDither = false;
|
|
}
|
|
|
|
void resetColor() {
|
|
fColor = GrColorPackRGBA(0xff, 0xff, 0xff, 0xff);
|
|
}
|
|
|
|
void resetCoverage() {
|
|
fCoverage = 0xff;
|
|
}
|
|
|
|
void resetTextures() {
|
|
for (int i = 0; i < kMaxTextures; ++i) {
|
|
this->setTexture(i, NULL);
|
|
fTextureSamplers[i].reset();
|
|
}
|
|
}
|
|
|
|
void resetMasks() {
|
|
for (int i = 0; i < kMaxMasks; ++i) {
|
|
this->setMask(i, NULL);
|
|
fMaskSamplers[i].reset();
|
|
}
|
|
}
|
|
};
|
|
|
|
#endif
|