add shader flag kConstInY_Flag
this signals blitters that the shader will return the same results for a given x value, independent of y. Useful inside blitRect(), where it can cache the first call to shadeSpan() and reuse it on all subsequent scans. Works with (non-rotated) linear-gradients, and Nx1 bitmaps. git-svn-id: http://skia.googlecode.com/svn/trunk@214 2bbb7eff-a529-9590-31e7-b0007b416f81
This commit is contained in:
parent
b2c5f2d260
commit
5119bdb952
@ -29,14 +29,15 @@ public:
|
||||
/** Create a ColorShader that will inherit its color from the Paint
|
||||
at draw time.
|
||||
*/
|
||||
SkColorShader() : fInheritColor(true) {}
|
||||
SkColorShader() : fFlags(0), fInheritColor(true) {}
|
||||
|
||||
/** Create a ColorShader that ignores the color in the paint, and uses the
|
||||
specified color. Note: like all shaders, at draw time the paint's alpha
|
||||
will be respected, and is applied to the specified color.
|
||||
*/
|
||||
SkColorShader(SkColor c) : fColor(c), fInheritColor(false) {}
|
||||
SkColorShader(SkColor c) : fColor(c), fFlags(0), fInheritColor(false) {}
|
||||
|
||||
virtual uint32_t getFlags();
|
||||
virtual uint32_t getFlags() { return fFlags; }
|
||||
virtual uint8_t getSpan16Alpha() const;
|
||||
virtual bool setContext(const SkBitmap& device, const SkPaint& paint,
|
||||
const SkMatrix& matrix);
|
||||
@ -54,6 +55,7 @@ private:
|
||||
}
|
||||
SkColor fColor; // ignored if fInheritColor is true
|
||||
SkPMColor fPMColor; // cached after setContext()
|
||||
uint32_t fFlags; // cached after setContext()
|
||||
uint16_t fColor16; // cached after setContext()
|
||||
SkBool8 fInheritColor;
|
||||
|
||||
|
@ -63,14 +63,22 @@ public:
|
||||
enum Flags {
|
||||
//!< set if all of the colors will be opaque
|
||||
kOpaqueAlpha_Flag = 0x01,
|
||||
|
||||
//! set if this shader's shadeSpan16() method can be called
|
||||
kHasSpan16_Flag = 0x02,
|
||||
|
||||
/** Set this bit if the shader's native data type is instrinsically 16
|
||||
bit, meaning that calling the 32bit shadeSpan() entry point will
|
||||
mean the the impl has to up-sample 16bit data into 32bit. Used as a
|
||||
a means of clearing a dither request if the it will have no effect
|
||||
*/
|
||||
kIntrinsicly16_Flag = 0x04
|
||||
kIntrinsicly16_Flag = 0x04,
|
||||
|
||||
/** set (after setContext) if the spans only vary in X (const in Y).
|
||||
e.g. an Nx1 bitmap that is being tiled in Y, or a linear-gradient
|
||||
that varies from left-to-right
|
||||
*/
|
||||
kConstInY_Flag = 0x08
|
||||
};
|
||||
|
||||
/** Called sometimes before drawing with this shader.
|
||||
|
@ -9,6 +9,19 @@
|
||||
#include "SkShader.h"
|
||||
#include "SkUtils.h"
|
||||
|
||||
static void show_ramp(SkCanvas* canvas, const SkRect& r) {
|
||||
SkPoint pts[] = { r.fLeft, 0, r.fRight, 0 };
|
||||
SkColor colors[] = { SK_ColorRED, SK_ColorBLUE };
|
||||
SkShader* s = SkGradientShader::CreateLinear(pts, colors, NULL, 2,
|
||||
SkShader::kRepeat_TileMode);
|
||||
SkPaint p;
|
||||
p.setShader(s)->unref();
|
||||
canvas->drawRect(r, p);
|
||||
canvas->translate(r.width() + SkIntToScalar(8), 0);
|
||||
p.setDither(true);
|
||||
canvas->drawRect(r, p);
|
||||
}
|
||||
|
||||
class TestGLView : public SkView {
|
||||
public:
|
||||
TestGLView() {
|
||||
@ -49,6 +62,9 @@ protected:
|
||||
canvas->translate(r.width() + SkIntToScalar(20), 0);
|
||||
paint.setStrokeWidth(SkIntToScalar(5));
|
||||
canvas->drawRect(r, paint);
|
||||
|
||||
canvas->translate(r.width() * 10/9, 0);
|
||||
show_ramp(canvas, r);
|
||||
}
|
||||
|
||||
private:
|
||||
|
@ -67,6 +67,11 @@ void SkBitmapProcShader::flatten(SkFlattenableWriteBuffer& buffer) {
|
||||
buffer.write8(fState.fTileModeY);
|
||||
}
|
||||
|
||||
static bool only_scale_and_translate(const SkMatrix& matrix) {
|
||||
unsigned mask = SkMatrix::kTranslate_Mask | SkMatrix::kScale_Mask;
|
||||
return (matrix.getType() & ~mask) == 0;
|
||||
}
|
||||
|
||||
bool SkBitmapProcShader::setContext(const SkBitmap& device,
|
||||
const SkPaint& paint,
|
||||
const SkMatrix& matrix) {
|
||||
@ -117,6 +122,12 @@ bool SkBitmapProcShader::setContext(const SkBitmap& device,
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
// if we're only 1-pixel heigh, and we don't rotate, then we can claim this
|
||||
if (1 == fState.fBitmap->height() &&
|
||||
only_scale_and_translate(this->getTotalInverse())) {
|
||||
fFlags |= kConstInY_Flag;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -977,17 +977,16 @@ const uint32_t gMask_00FF00FF = 0xFF00FF;
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
SkShaderBlitter::SkShaderBlitter(const SkBitmap& device, const SkPaint& paint)
|
||||
: INHERITED(device)
|
||||
{
|
||||
: INHERITED(device) {
|
||||
fShader = paint.getShader();
|
||||
SkASSERT(fShader);
|
||||
|
||||
fShader->ref();
|
||||
fShader->beginSession();
|
||||
fShaderFlags = fShader->getFlags();
|
||||
}
|
||||
|
||||
SkShaderBlitter::~SkShaderBlitter()
|
||||
{
|
||||
SkShaderBlitter::~SkShaderBlitter() {
|
||||
fShader->endSession();
|
||||
fShader->unref();
|
||||
}
|
||||
|
@ -483,7 +483,7 @@ void SkRGB16_Blitter::blitRect(int x, int y, int width, int height) {
|
||||
SkRGB16_Shader16_Blitter::SkRGB16_Shader16_Blitter(const SkBitmap& device,
|
||||
const SkPaint& paint)
|
||||
: SkRGB16_Shader_Blitter(device, paint) {
|
||||
SkASSERT(SkShader::CanCallShadeSpan16(fShader->getFlags()));
|
||||
SkASSERT(SkShader::CanCallShadeSpan16(fShaderFlags));
|
||||
}
|
||||
|
||||
void SkRGB16_Shader16_Blitter::blitH(int x, int y, int width) SK_RESTRICT {
|
||||
@ -569,7 +569,7 @@ SkRGB16_Shader_Blitter::SkRGB16_Shader_Blitter(const SkBitmap& device,
|
||||
// compute SkBlitRow::Procs
|
||||
unsigned flags = 0;
|
||||
|
||||
uint32_t shaderFlags = fShader->getFlags();
|
||||
uint32_t shaderFlags = fShaderFlags;
|
||||
// shaders take care of global alpha, so we never set it in SkBlitRow
|
||||
if (!(shaderFlags & SkShader::kOpaqueAlpha_Flag)) {
|
||||
flags |= SkBlitRow::kSrcPixelAlpha_Flag;
|
||||
@ -597,6 +597,30 @@ void SkRGB16_Shader_Blitter::blitH(int x, int y, int width) {
|
||||
fOpaqueProc(fDevice.getAddr16(x, y), fBuffer, width, 0xFF, x, y);
|
||||
}
|
||||
|
||||
void SkRGB16_Shader_Blitter::blitRect(int x, int y, int width, int height) {
|
||||
SkShader* shader = fShader;
|
||||
SkBlitRow::Proc proc = fOpaqueProc;
|
||||
SkPMColor* buffer = fBuffer;
|
||||
uint16_t* dst = fDevice.getAddr16(x, y);
|
||||
size_t dstRB = fDevice.rowBytes();
|
||||
|
||||
if (fShaderFlags & SkShader::kConstInY_Flag) {
|
||||
shader->shadeSpan(x, y, buffer, width);
|
||||
do {
|
||||
proc(dst, buffer, width, 0xFF, x, y);
|
||||
y += 1;
|
||||
dst = (uint16_t*)((char*)dst + dstRB);
|
||||
} while (--height);
|
||||
} else {
|
||||
do {
|
||||
shader->shadeSpan(x, y, buffer, width);
|
||||
proc(dst, buffer, width, 0xFF, x, y);
|
||||
y += 1;
|
||||
dst = (uint16_t*)((char*)dst + dstRB);
|
||||
} while (--height);
|
||||
}
|
||||
}
|
||||
|
||||
static inline int count_nonzero_span(const int16_t runs[], const SkAlpha aa[]) {
|
||||
int count = 0;
|
||||
for (;;) {
|
||||
|
@ -38,7 +38,8 @@ public:
|
||||
virtual ~SkShaderBlitter();
|
||||
|
||||
protected:
|
||||
SkShader* fShader;
|
||||
uint32_t fShaderFlags;
|
||||
SkShader* fShader;
|
||||
|
||||
private:
|
||||
// illegal
|
||||
@ -192,7 +193,8 @@ public:
|
||||
virtual ~SkRGB16_Shader_Blitter();
|
||||
virtual void blitH(int x, int y, int width);
|
||||
virtual void blitAntiH(int x, int y, const SkAlpha antialias[], const int16_t runs[]);
|
||||
|
||||
virtual void blitRect(int x, int y, int width, int height);
|
||||
|
||||
protected:
|
||||
SkPMColor* fBuffer;
|
||||
SkBlitRow::Proc fOpaqueProc;
|
||||
|
@ -210,6 +210,7 @@ SkShader* SkShader::CreateBitmapShader(const SkBitmap& src,
|
||||
#include "SkUtils.h"
|
||||
|
||||
SkColorShader::SkColorShader(SkFlattenableReadBuffer& b) : INHERITED(b) {
|
||||
fFlags = 0; // computed in setContext
|
||||
fInheritColor = b.readU8();
|
||||
if (fInheritColor) {
|
||||
return;
|
||||
@ -226,11 +227,6 @@ void SkColorShader::flatten(SkFlattenableWriteBuffer& buffer) {
|
||||
buffer.write32(fColor);
|
||||
}
|
||||
|
||||
uint32_t SkColorShader::getFlags() {
|
||||
return (SkGetPackedA32(fPMColor) == 255 ? kOpaqueAlpha_Flag : 0) |
|
||||
kHasSpan16_Flag;
|
||||
}
|
||||
|
||||
uint8_t SkColorShader::getSpan16Alpha() const {
|
||||
return SkGetPackedA32(fPMColor);
|
||||
}
|
||||
@ -267,6 +263,11 @@ bool SkColorShader::setContext(const SkBitmap& device, const SkPaint& paint,
|
||||
}
|
||||
fPMColor = SkPackARGB32(a, r, g, b);
|
||||
|
||||
fFlags = kHasSpan16_Flag | kConstInY_Flag;
|
||||
if (SkGetPackedA32(fPMColor) == 255) {
|
||||
fFlags |= kOpaqueAlpha_Flag;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -620,6 +620,7 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
virtual bool setContext(const SkBitmap&, const SkPaint&, const SkMatrix&);
|
||||
virtual void shadeSpan(int x, int y, SkPMColor dstC[], int count);
|
||||
virtual void shadeSpan16(int x, int y, uint16_t dstC[], int count);
|
||||
virtual bool asABitmap(SkBitmap*, SkMatrix*, TileMode*);
|
||||
@ -646,6 +647,19 @@ private:
|
||||
typedef Gradient_Shader INHERITED;
|
||||
};
|
||||
|
||||
bool Linear_Gradient::setContext(const SkBitmap& device, const SkPaint& paint,
|
||||
const SkMatrix& matrix) {
|
||||
if (!this->INHERITED::setContext(device, paint, matrix)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
unsigned mask = SkMatrix::kTranslate_Mask | SkMatrix::kScale_Mask;
|
||||
if ((fDstToIndex.getType() & ~mask) == 0) {
|
||||
fFlags |= SkShader::kConstInY_Flag;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// Return true if fx, fx+dx, fx+2*dx, ... is always in range
|
||||
static inline bool no_need_for_clamp(int fx, int dx, int count)
|
||||
{
|
||||
|
@ -71,7 +71,7 @@
|
||||
00A728270FD43D0400D5051F /* SampleMovie.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2762F6760FCCCB01002BD8B4 /* SampleMovie.cpp */; };
|
||||
00A7282F0FD43D3700D5051F /* SkMovie.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 00A7282D0FD43D3700D5051F /* SkMovie.cpp */; };
|
||||
00A7295D0FD8397600D5051F /* SampleAll.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2762F6740FCCCB01002BD8B4 /* SampleAll.cpp */; };
|
||||
00A729650FD93ED600D5051F /* SampleTestGL.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 00A729630FD93ED600D5051F /* SampleTestGL.cpp */; };
|
||||
00AF77B00FE2EA2D007F9650 /* SampleTestGL.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 00A729630FD93ED600D5051F /* SampleTestGL.cpp */; };
|
||||
00C55DA10F8552DC000CAC09 /* SampleGradients.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 00C55DA00F8552DC000CAC09 /* SampleGradients.cpp */; };
|
||||
00FF39140FC6ED2C00915187 /* SampleEffects.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 00FF39130FC6ED2C00915187 /* SampleEffects.cpp */; };
|
||||
0156F80407C56A3000C6122B /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0156F80307C56A3000C6122B /* Foundation.framework */; };
|
||||
@ -569,8 +569,8 @@
|
||||
00A728270FD43D0400D5051F /* SampleMovie.cpp in Sources */,
|
||||
00A7282F0FD43D3700D5051F /* SkMovie.cpp in Sources */,
|
||||
00A7295D0FD8397600D5051F /* SampleAll.cpp in Sources */,
|
||||
00A729650FD93ED600D5051F /* SampleTestGL.cpp in Sources */,
|
||||
000A99820FD97526007E45BD /* SampleArc.cpp in Sources */,
|
||||
00AF77B00FE2EA2D007F9650 /* SampleTestGL.cpp in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user