expand SkShader's flag kConstInY to 16 and 32 variants, allowing a shader
(like gradients) to support predithering. If they do, then they would suppress kConstInY16, since they no longer are const. The blitters now check for each flag separately, so we don't have to give up const-in-Y in the 32bit case, since in that mode we don't care about dithering. git-svn-id: http://skia.googlecode.com/svn/trunk@339 2bbb7eff-a529-9590-31e7-b0007b416f81
This commit is contained in:
parent
2a4d1ff189
commit
3c9b2a4a0e
@ -76,9 +76,17 @@ public:
|
|||||||
|
|
||||||
/** set (after setContext) if the spans only vary in X (const in Y).
|
/** 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
|
e.g. an Nx1 bitmap that is being tiled in Y, or a linear-gradient
|
||||||
that varies from left-to-right
|
that varies from left-to-right. This flag specifies this for
|
||||||
|
shadeSpan().
|
||||||
*/
|
*/
|
||||||
kConstInY_Flag = 0x08
|
kConstInY32_Flag = 0x08,
|
||||||
|
|
||||||
|
/** same as kConstInY32_Flag, but is set if this is true for shadeSpan16
|
||||||
|
which may not always be the case, since shadeSpan16 may be
|
||||||
|
predithered, which would mean it was not const in Y, even though
|
||||||
|
the 32bit shadeSpan() would be const.
|
||||||
|
*/
|
||||||
|
kConstInY16_Flag = 0x10
|
||||||
};
|
};
|
||||||
|
|
||||||
/** Called sometimes before drawing with this shader.
|
/** Called sometimes before drawing with this shader.
|
||||||
@ -99,8 +107,7 @@ public:
|
|||||||
parameters, or false if not. If false is returned, nothing
|
parameters, or false if not. If false is returned, nothing
|
||||||
will be drawn.
|
will be drawn.
|
||||||
*/
|
*/
|
||||||
virtual bool setContext( const SkBitmap& device,
|
virtual bool setContext(const SkBitmap& device, const SkPaint& paint,
|
||||||
const SkPaint& paint,
|
|
||||||
const SkMatrix& matrix);
|
const SkMatrix& matrix);
|
||||||
|
|
||||||
/** Called for each span of the object being drawn. Your subclass
|
/** Called for each span of the object being drawn. Your subclass
|
||||||
@ -108,7 +115,8 @@ public:
|
|||||||
correspond to the specified device coordinates.
|
correspond to the specified device coordinates.
|
||||||
*/
|
*/
|
||||||
virtual void shadeSpan(int x, int y, SkPMColor[], int count) = 0;
|
virtual void shadeSpan(int x, int y, SkPMColor[], int count) = 0;
|
||||||
/** Called only for 16bit devices when getFlags() returns kOpaqueAlphaFlag | kHasSpan16_Flag
|
/** Called only for 16bit devices when getFlags() returns
|
||||||
|
kOpaqueAlphaFlag | kHasSpan16_Flag
|
||||||
*/
|
*/
|
||||||
virtual void shadeSpan16(int x, int y, uint16_t[], int count);
|
virtual void shadeSpan16(int x, int y, uint16_t[], int count);
|
||||||
/** Similar to shadeSpan, but only returns the alpha-channel for a span.
|
/** Similar to shadeSpan, but only returns the alpha-channel for a span.
|
||||||
@ -120,8 +128,7 @@ public:
|
|||||||
/** Helper function that returns true if this shader's shadeSpan16() method can
|
/** Helper function that returns true if this shader's shadeSpan16() method can
|
||||||
be called.
|
be called.
|
||||||
*/
|
*/
|
||||||
bool canCallShadeSpan16()
|
bool canCallShadeSpan16() {
|
||||||
{
|
|
||||||
return SkShader::CanCallShadeSpan16(this->getFlags());
|
return SkShader::CanCallShadeSpan16(this->getFlags());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,9 +1,35 @@
|
|||||||
#include "SampleCode.h"
|
#include "SampleCode.h"
|
||||||
#include "SkColorPriv.h"
|
#include "SkColorPriv.h"
|
||||||
|
#include "SkGradientShader.h"
|
||||||
#include "SkView.h"
|
#include "SkView.h"
|
||||||
#include "SkCanvas.h"
|
#include "SkCanvas.h"
|
||||||
#include "SkUtils.h"
|
#include "SkUtils.h"
|
||||||
|
|
||||||
|
static void draw_rect(SkCanvas* canvas, const SkRect& r, const SkPaint& p) {
|
||||||
|
canvas->drawRect(r, p);
|
||||||
|
|
||||||
|
SkPaint frame(p);
|
||||||
|
frame.setShader(NULL);
|
||||||
|
frame.setStyle(SkPaint::kStroke_Style);
|
||||||
|
canvas->drawRect(r, frame);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void draw_gradient(SkCanvas* canvas) {
|
||||||
|
SkRect r = { 0, 0, SkIntToScalar(256), SkIntToScalar(32) };
|
||||||
|
SkPoint pts[] = { r.fLeft, r.fTop, r.fRight, r.fTop };
|
||||||
|
SkColor colors[] = { 0xFF000000, 0xFFFF0000 };
|
||||||
|
SkShader* s = SkGradientShader::CreateLinear(pts, colors, NULL, 2,
|
||||||
|
SkShader::kClamp_TileMode);
|
||||||
|
|
||||||
|
SkPaint p;
|
||||||
|
p.setShader(s)->unref();
|
||||||
|
draw_rect(canvas, r, p);
|
||||||
|
|
||||||
|
canvas->translate(0, SkIntToScalar(40));
|
||||||
|
p.setDither(true);
|
||||||
|
draw_rect(canvas, r, p);
|
||||||
|
}
|
||||||
|
|
||||||
static void test_pathregion() {
|
static void test_pathregion() {
|
||||||
SkPath path;
|
SkPath path;
|
||||||
SkRegion region;
|
SkRegion region;
|
||||||
@ -103,6 +129,9 @@ protected:
|
|||||||
draw2(canvas, fBM8);
|
draw2(canvas, fBM8);
|
||||||
canvas->translate(0, SkIntToScalar(fBM8.height() *3));
|
canvas->translate(0, SkIntToScalar(fBM8.height() *3));
|
||||||
draw2(canvas, fBM32);
|
draw2(canvas, fBM32);
|
||||||
|
|
||||||
|
canvas->translate(0, SkIntToScalar(fBM8.height() *3));
|
||||||
|
draw_gradient(canvas);
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -132,7 +132,10 @@ bool SkBitmapProcShader::setContext(const SkBitmap& device,
|
|||||||
// if we're only 1-pixel heigh, and we don't rotate, then we can claim this
|
// if we're only 1-pixel heigh, and we don't rotate, then we can claim this
|
||||||
if (1 == fState.fBitmap->height() &&
|
if (1 == fState.fBitmap->height() &&
|
||||||
only_scale_and_translate(this->getTotalInverse())) {
|
only_scale_and_translate(this->getTotalInverse())) {
|
||||||
flags |= kConstInY_Flag;
|
flags |= kConstInY32_Flag;
|
||||||
|
if (flags & kHasSpan16_Flag) {
|
||||||
|
flags |= kConstInY16_Flag;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fFlags = flags;
|
fFlags = flags;
|
||||||
|
@ -528,7 +528,7 @@ void SkRGB16_Shader16_Blitter::blitRect(int x, int y, int width, int height) {
|
|||||||
int alpha = shader->getSpan16Alpha();
|
int alpha = shader->getSpan16Alpha();
|
||||||
|
|
||||||
if (0xFF == alpha) {
|
if (0xFF == alpha) {
|
||||||
if (fShaderFlags & SkShader::kConstInY_Flag) {
|
if (fShaderFlags & SkShader::kConstInY16_Flag) {
|
||||||
// have the shader blit directly into the device the first time
|
// have the shader blit directly into the device the first time
|
||||||
shader->shadeSpan16(x, y, dst, width);
|
shader->shadeSpan16(x, y, dst, width);
|
||||||
// and now just memcpy that line on the subsequent lines
|
// and now just memcpy that line on the subsequent lines
|
||||||
@ -549,7 +549,7 @@ void SkRGB16_Shader16_Blitter::blitRect(int x, int y, int width, int height) {
|
|||||||
} else {
|
} else {
|
||||||
int scale = SkAlpha255To256(alpha);
|
int scale = SkAlpha255To256(alpha);
|
||||||
uint16_t* span16 = (uint16_t*)fBuffer;
|
uint16_t* span16 = (uint16_t*)fBuffer;
|
||||||
if (fShaderFlags & SkShader::kConstInY_Flag) {
|
if (fShaderFlags & SkShader::kConstInY16_Flag) {
|
||||||
shader->shadeSpan16(x, y, span16, width);
|
shader->shadeSpan16(x, y, span16, width);
|
||||||
do {
|
do {
|
||||||
SkBlendRGB16(span16, dst, scale, width);
|
SkBlendRGB16(span16, dst, scale, width);
|
||||||
@ -668,7 +668,7 @@ void SkRGB16_Shader_Blitter::blitRect(int x, int y, int width, int height) {
|
|||||||
uint16_t* dst = fDevice.getAddr16(x, y);
|
uint16_t* dst = fDevice.getAddr16(x, y);
|
||||||
size_t dstRB = fDevice.rowBytes();
|
size_t dstRB = fDevice.rowBytes();
|
||||||
|
|
||||||
if (fShaderFlags & SkShader::kConstInY_Flag) {
|
if (fShaderFlags & SkShader::kConstInY32_Flag) {
|
||||||
shader->shadeSpan(x, y, buffer, width);
|
shader->shadeSpan(x, y, buffer, width);
|
||||||
do {
|
do {
|
||||||
proc(dst, buffer, width, 0xFF, x, y);
|
proc(dst, buffer, width, 0xFF, x, y);
|
||||||
|
@ -263,7 +263,7 @@ bool SkColorShader::setContext(const SkBitmap& device, const SkPaint& paint,
|
|||||||
}
|
}
|
||||||
fPMColor = SkPackARGB32(a, r, g, b);
|
fPMColor = SkPackARGB32(a, r, g, b);
|
||||||
|
|
||||||
fFlags = kHasSpan16_Flag | kConstInY_Flag;
|
fFlags = kHasSpan16_Flag | kConstInY32_Flag;
|
||||||
if (SkGetPackedA32(fPMColor) == 255) {
|
if (SkGetPackedA32(fPMColor) == 255) {
|
||||||
fFlags |= kOpaqueAlpha_Flag;
|
fFlags |= kOpaqueAlpha_Flag;
|
||||||
}
|
}
|
||||||
|
@ -20,18 +20,6 @@
|
|||||||
#include "SkUnitMapper.h"
|
#include "SkUnitMapper.h"
|
||||||
#include "SkUtils.h"
|
#include "SkUtils.h"
|
||||||
|
|
||||||
/*
|
|
||||||
ToDo
|
|
||||||
|
|
||||||
- not sure we still need the full Rec struct, now that we're using a cache
|
|
||||||
- detect const-alpha (but not opaque) in getFlags()
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* dither seems to look better, but not stuningly yet, and it slows us down a little
|
|
||||||
so its not on by default yet.
|
|
||||||
*/
|
|
||||||
#define TEST_GRADIENT_DITHER
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
typedef SkFixed (*TileProc)(SkFixed);
|
typedef SkFixed (*TileProc)(SkFixed);
|
||||||
@ -503,12 +491,9 @@ static inline U16CPU dot6to16(unsigned x) {
|
|||||||
|
|
||||||
const uint16_t* Gradient_Shader::getCache16() {
|
const uint16_t* Gradient_Shader::getCache16() {
|
||||||
if (fCache16 == NULL) {
|
if (fCache16 == NULL) {
|
||||||
if (fCache16Storage == NULL) // set the storage and our working ptr
|
if (fCache16Storage == NULL) { // set the storage and our working ptr
|
||||||
#ifdef TEST_GRADIENT_DITHER
|
|
||||||
fCache16Storage = (uint16_t*)sk_malloc_throw(sizeof(uint16_t) * kCache16Count * 2);
|
fCache16Storage = (uint16_t*)sk_malloc_throw(sizeof(uint16_t) * kCache16Count * 2);
|
||||||
#else
|
}
|
||||||
fCache16Storage = (uint16_t*)sk_malloc_throw(sizeof(uint16_t) * kCache16Count);
|
|
||||||
#endif
|
|
||||||
fCache16 = fCache16Storage;
|
fCache16 = fCache16Storage;
|
||||||
if (fColorCount == 2) {
|
if (fColorCount == 2) {
|
||||||
build_16bit_cache(fCache16, fOrigColors[0], fOrigColors[1], kCache16Count);
|
build_16bit_cache(fCache16, fOrigColors[0], fOrigColors[1], kCache16Count);
|
||||||
@ -527,20 +512,14 @@ const uint16_t* Gradient_Shader::getCache16() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (fMapper) {
|
if (fMapper) {
|
||||||
#ifdef TEST_GRADIENT_DITHER
|
|
||||||
fCache16Storage = (uint16_t*)sk_malloc_throw(sizeof(uint16_t) * kCache16Count * 2);
|
fCache16Storage = (uint16_t*)sk_malloc_throw(sizeof(uint16_t) * kCache16Count * 2);
|
||||||
#else
|
|
||||||
fCache16Storage = (uint16_t*)sk_malloc_throw(sizeof(uint16_t) * kCache16Count);
|
|
||||||
#endif
|
|
||||||
uint16_t* linear = fCache16; // just computed linear data
|
uint16_t* linear = fCache16; // just computed linear data
|
||||||
uint16_t* mapped = fCache16Storage; // storage for mapped data
|
uint16_t* mapped = fCache16Storage; // storage for mapped data
|
||||||
SkUnitMapper* map = fMapper;
|
SkUnitMapper* map = fMapper;
|
||||||
for (int i = 0; i < 64; i++) {
|
for (int i = 0; i < 64; i++) {
|
||||||
int index = map->mapUnit16(dot6to16(i)) >> 10;
|
int index = map->mapUnit16(dot6to16(i)) >> 10;
|
||||||
mapped[i] = linear[index];
|
mapped[i] = linear[index];
|
||||||
#ifdef TEST_GRADIENT_DITHER
|
|
||||||
mapped[i + 64] = linear[index + 64];
|
mapped[i + 64] = linear[index + 64];
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
sk_free(fCache16);
|
sk_free(fCache16);
|
||||||
fCache16 = fCache16Storage;
|
fCache16 = fCache16Storage;
|
||||||
@ -655,7 +634,13 @@ bool Linear_Gradient::setContext(const SkBitmap& device, const SkPaint& paint,
|
|||||||
|
|
||||||
unsigned mask = SkMatrix::kTranslate_Mask | SkMatrix::kScale_Mask;
|
unsigned mask = SkMatrix::kTranslate_Mask | SkMatrix::kScale_Mask;
|
||||||
if ((fDstToIndex.getType() & ~mask) == 0) {
|
if ((fDstToIndex.getType() & ~mask) == 0) {
|
||||||
fFlags |= SkShader::kConstInY_Flag;
|
fFlags |= SkShader::kConstInY32_Flag;
|
||||||
|
if ((fFlags & SkShader::kHasSpan16_Flag) && !paint.isDither()) {
|
||||||
|
// only claim this if we do have a 16bit mode (i.e. none of our
|
||||||
|
// colors have alpha), and if we are not dithering (which obviously
|
||||||
|
// is not const in Y).
|
||||||
|
fFlags |= SkShader::kConstInY16_Flag;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -779,11 +764,9 @@ bool Linear_Gradient::asABitmap(SkBitmap* bitmap, SkMatrix* matrix,
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef TEST_GRADIENT_DITHER
|
static void dither_memset16(uint16_t dst[], uint16_t value, uint16_t other,
|
||||||
static void dither_memset16(uint16_t dst[], uint16_t value, uint16_t other, int count)
|
int count) {
|
||||||
{
|
if (reinterpret_cast<uintptr_t>(dst) & 2) {
|
||||||
if (reinterpret_cast<uintptr_t>(dst) & 2)
|
|
||||||
{
|
|
||||||
*dst++ = value;
|
*dst++ = value;
|
||||||
count -= 1;
|
count -= 1;
|
||||||
SkTSwap(value, other);
|
SkTSwap(value, other);
|
||||||
@ -791,10 +774,10 @@ static void dither_memset16(uint16_t dst[], uint16_t value, uint16_t other, int
|
|||||||
|
|
||||||
sk_memset32((uint32_t*)dst, (value << 16) | other, count >> 1);
|
sk_memset32((uint32_t*)dst, (value << 16) | other, count >> 1);
|
||||||
|
|
||||||
if (count & 1)
|
if (count & 1) {
|
||||||
dst[count - 1] = value;
|
dst[count - 1] = value;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
void Linear_Gradient::shadeSpan16(int x, int y, uint16_t dstC[], int count)
|
void Linear_Gradient::shadeSpan16(int x, int y, uint16_t dstC[], int count)
|
||||||
{
|
{
|
||||||
@ -804,9 +787,7 @@ void Linear_Gradient::shadeSpan16(int x, int y, uint16_t dstC[], int count)
|
|||||||
SkMatrix::MapXYProc dstProc = fDstToIndexProc;
|
SkMatrix::MapXYProc dstProc = fDstToIndexProc;
|
||||||
TileProc proc = fTileProc;
|
TileProc proc = fTileProc;
|
||||||
const uint16_t* cache = this->getCache16();
|
const uint16_t* cache = this->getCache16();
|
||||||
#ifdef TEST_GRADIENT_DITHER
|
|
||||||
int toggle = ((x ^ y) & 1) << kCache16Bits;
|
int toggle = ((x ^ y) & 1) << kCache16Bits;
|
||||||
#endif
|
|
||||||
|
|
||||||
if (fDstToIndexClass != kPerspective_MatrixClass) {
|
if (fDstToIndexClass != kPerspective_MatrixClass) {
|
||||||
dstProc(fDstToIndex, SkIntToScalar(x), SkIntToScalar(y), &srcPt);
|
dstProc(fDstToIndex, SkIntToScalar(x), SkIntToScalar(y), &srcPt);
|
||||||
@ -827,34 +808,22 @@ void Linear_Gradient::shadeSpan16(int x, int y, uint16_t dstC[], int count)
|
|||||||
// we're a vertical gradient, so no change in a span
|
// we're a vertical gradient, so no change in a span
|
||||||
unsigned fi = proc(fx) >> 10;
|
unsigned fi = proc(fx) >> 10;
|
||||||
SkASSERT(fi <= 63);
|
SkASSERT(fi <= 63);
|
||||||
#ifdef TEST_GRADIENT_DITHER
|
|
||||||
dither_memset16(dstC, cache[toggle + fi], cache[(toggle ^ (1 << kCache16Bits)) + fi], count);
|
dither_memset16(dstC, cache[toggle + fi], cache[(toggle ^ (1 << kCache16Bits)) + fi], count);
|
||||||
#else
|
|
||||||
sk_memset16(dstC, cache[fi], count);
|
|
||||||
#endif
|
|
||||||
} else if (proc == clamp_tileproc) {
|
} else if (proc == clamp_tileproc) {
|
||||||
do {
|
do {
|
||||||
unsigned fi = SkClampMax(fx >> 10, 63);
|
unsigned fi = SkClampMax(fx >> 10, 63);
|
||||||
SkASSERT(fi <= 63);
|
SkASSERT(fi <= 63);
|
||||||
fx += dx;
|
fx += dx;
|
||||||
#ifdef TEST_GRADIENT_DITHER
|
|
||||||
*dstC++ = cache[toggle + fi];
|
*dstC++ = cache[toggle + fi];
|
||||||
toggle ^= (1 << kCache16Bits);
|
toggle ^= (1 << kCache16Bits);
|
||||||
#else
|
|
||||||
*dstC++ = cache[fi];
|
|
||||||
#endif
|
|
||||||
} while (--count != 0);
|
} while (--count != 0);
|
||||||
} else if (proc == mirror_tileproc) {
|
} else if (proc == mirror_tileproc) {
|
||||||
do {
|
do {
|
||||||
unsigned fi = mirror_6bits(fx >> 10);
|
unsigned fi = mirror_6bits(fx >> 10);
|
||||||
SkASSERT(fi <= 0x3F);
|
SkASSERT(fi <= 0x3F);
|
||||||
fx += dx;
|
fx += dx;
|
||||||
#ifdef TEST_GRADIENT_DITHER
|
|
||||||
*dstC++ = cache[toggle + fi];
|
*dstC++ = cache[toggle + fi];
|
||||||
toggle ^= (1 << kCache16Bits);
|
toggle ^= (1 << kCache16Bits);
|
||||||
#else
|
|
||||||
*dstC++ = cache[fi];
|
|
||||||
#endif
|
|
||||||
} while (--count != 0);
|
} while (--count != 0);
|
||||||
} else {
|
} else {
|
||||||
SkASSERT(proc == repeat_tileproc);
|
SkASSERT(proc == repeat_tileproc);
|
||||||
@ -862,12 +831,8 @@ void Linear_Gradient::shadeSpan16(int x, int y, uint16_t dstC[], int count)
|
|||||||
unsigned fi = repeat_6bits(fx >> 10);
|
unsigned fi = repeat_6bits(fx >> 10);
|
||||||
SkASSERT(fi <= 0x3F);
|
SkASSERT(fi <= 0x3F);
|
||||||
fx += dx;
|
fx += dx;
|
||||||
#ifdef TEST_GRADIENT_DITHER
|
|
||||||
*dstC++ = cache[toggle + fi];
|
*dstC++ = cache[toggle + fi];
|
||||||
toggle ^= (1 << kCache16Bits);
|
toggle ^= (1 << kCache16Bits);
|
||||||
#else
|
|
||||||
*dstC++ = cache[fi];
|
|
||||||
#endif
|
|
||||||
} while (--count != 0);
|
} while (--count != 0);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -879,12 +844,8 @@ void Linear_Gradient::shadeSpan16(int x, int y, uint16_t dstC[], int count)
|
|||||||
SkASSERT(fi <= 0xFFFF);
|
SkASSERT(fi <= 0xFFFF);
|
||||||
|
|
||||||
int index = fi >> (16 - kCache16Bits);
|
int index = fi >> (16 - kCache16Bits);
|
||||||
#ifdef TEST_GRADIENT_DITHER
|
|
||||||
*dstC++ = cache[toggle + index];
|
*dstC++ = cache[toggle + index];
|
||||||
toggle ^= (1 << kCache16Bits);
|
toggle ^= (1 << kCache16Bits);
|
||||||
#else
|
|
||||||
*dstC++ = cache[index];
|
|
||||||
#endif
|
|
||||||
|
|
||||||
dstX += SK_Scalar1;
|
dstX += SK_Scalar1;
|
||||||
} while (--count != 0);
|
} while (--count != 0);
|
||||||
@ -1033,40 +994,33 @@ public:
|
|||||||
} while (--count != 0);
|
} while (--count != 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
virtual void shadeSpan16(int x, int y, uint16_t dstC[], int count)
|
|
||||||
{
|
virtual void shadeSpan16(int x, int y, uint16_t dstC[], int count) {
|
||||||
SkASSERT(count > 0);
|
SkASSERT(count > 0);
|
||||||
|
|
||||||
SkPoint srcPt;
|
SkPoint srcPt;
|
||||||
SkMatrix::MapXYProc dstProc = fDstToIndexProc;
|
SkMatrix::MapXYProc dstProc = fDstToIndexProc;
|
||||||
TileProc proc = fTileProc;
|
TileProc proc = fTileProc;
|
||||||
const uint16_t* cache = this->getCache16();
|
const uint16_t* cache = this->getCache16();
|
||||||
#ifdef TEST_GRADIENT_DITHER
|
|
||||||
int toggle = ((x ^ y) & 1) << kCache16Bits;
|
int toggle = ((x ^ y) & 1) << kCache16Bits;
|
||||||
#endif
|
|
||||||
|
|
||||||
if (fDstToIndexClass != kPerspective_MatrixClass)
|
if (fDstToIndexClass != kPerspective_MatrixClass) {
|
||||||
{
|
|
||||||
dstProc(fDstToIndex, SkIntToScalar(x), SkIntToScalar(y), &srcPt);
|
dstProc(fDstToIndex, SkIntToScalar(x), SkIntToScalar(y), &srcPt);
|
||||||
SkFixed dx, fx = SkScalarToFixed(srcPt.fX);
|
SkFixed dx, fx = SkScalarToFixed(srcPt.fX);
|
||||||
SkFixed dy, fy = SkScalarToFixed(srcPt.fY);
|
SkFixed dy, fy = SkScalarToFixed(srcPt.fY);
|
||||||
|
|
||||||
if (fDstToIndexClass == kFixedStepInX_MatrixClass)
|
if (fDstToIndexClass == kFixedStepInX_MatrixClass) {
|
||||||
{
|
|
||||||
SkFixed storage[2];
|
SkFixed storage[2];
|
||||||
(void)fDstToIndex.fixedStepInX(SkIntToScalar(y), &storage[0], &storage[1]);
|
(void)fDstToIndex.fixedStepInX(SkIntToScalar(y), &storage[0], &storage[1]);
|
||||||
dx = storage[0];
|
dx = storage[0];
|
||||||
dy = storage[1];
|
dy = storage[1];
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
SkASSERT(fDstToIndexClass == kLinear_MatrixClass);
|
SkASSERT(fDstToIndexClass == kLinear_MatrixClass);
|
||||||
dx = SkScalarToFixed(fDstToIndex.getScaleX());
|
dx = SkScalarToFixed(fDstToIndex.getScaleX());
|
||||||
dy = SkScalarToFixed(fDstToIndex.getSkewY());
|
dy = SkScalarToFixed(fDstToIndex.getSkewY());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (proc == clamp_tileproc)
|
if (proc == clamp_tileproc) {
|
||||||
{
|
|
||||||
const uint8_t* sqrt_table = gSqrt8Table;
|
const uint8_t* sqrt_table = gSqrt8Table;
|
||||||
|
|
||||||
/* knock these down so we can pin against +- 0x7FFF, which is an immediate load,
|
/* knock these down so we can pin against +- 0x7FFF, which is an immediate load,
|
||||||
@ -1079,8 +1033,7 @@ public:
|
|||||||
dx >>= 1;
|
dx >>= 1;
|
||||||
fy >>= 1;
|
fy >>= 1;
|
||||||
dy >>= 1;
|
dy >>= 1;
|
||||||
if (dy == 0) // might perform this check for the other modes, but the win will be a smaller % of the total
|
if (dy == 0) { // might perform this check for the other modes, but the win will be a smaller % of the total
|
||||||
{
|
|
||||||
fy = SkPin32(fy, -0xFFFF >> 1, 0xFFFF >> 1);
|
fy = SkPin32(fy, -0xFFFF >> 1, 0xFFFF >> 1);
|
||||||
fy *= fy;
|
fy *= fy;
|
||||||
do {
|
do {
|
||||||
@ -1088,16 +1041,10 @@ public:
|
|||||||
unsigned fi = (xx * xx + fy) >> (14 + 16 - kSQRT_TABLE_BITS);
|
unsigned fi = (xx * xx + fy) >> (14 + 16 - kSQRT_TABLE_BITS);
|
||||||
fi = SkFastMin32(fi, 0xFFFF >> (16 - kSQRT_TABLE_BITS));
|
fi = SkFastMin32(fi, 0xFFFF >> (16 - kSQRT_TABLE_BITS));
|
||||||
fx += dx;
|
fx += dx;
|
||||||
#ifdef TEST_GRADIENT_DITHER
|
|
||||||
*dstC++ = cache[toggle + (sqrt_table[fi] >> (8 - kCache16Bits))];
|
*dstC++ = cache[toggle + (sqrt_table[fi] >> (8 - kCache16Bits))];
|
||||||
toggle ^= (1 << kCache16Bits);
|
toggle ^= (1 << kCache16Bits);
|
||||||
#else
|
|
||||||
*dstC++ = cache[sqrt_table[fi] >> (8 - kCache16Bits)];
|
|
||||||
#endif
|
|
||||||
} while (--count != 0);
|
} while (--count != 0);
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
do {
|
do {
|
||||||
unsigned xx = SkPin32(fx, -0xFFFF >> 1, 0xFFFF >> 1);
|
unsigned xx = SkPin32(fx, -0xFFFF >> 1, 0xFFFF >> 1);
|
||||||
unsigned fi = SkPin32(fy, -0xFFFF >> 1, 0xFFFF >> 1);
|
unsigned fi = SkPin32(fy, -0xFFFF >> 1, 0xFFFF >> 1);
|
||||||
@ -1105,33 +1052,21 @@ public:
|
|||||||
fi = SkFastMin32(fi, 0xFFFF >> (16 - kSQRT_TABLE_BITS));
|
fi = SkFastMin32(fi, 0xFFFF >> (16 - kSQRT_TABLE_BITS));
|
||||||
fx += dx;
|
fx += dx;
|
||||||
fy += dy;
|
fy += dy;
|
||||||
#ifdef TEST_GRADIENT_DITHER
|
|
||||||
*dstC++ = cache[toggle + (sqrt_table[fi] >> (8 - kCache16Bits))];
|
*dstC++ = cache[toggle + (sqrt_table[fi] >> (8 - kCache16Bits))];
|
||||||
toggle ^= (1 << kCache16Bits);
|
toggle ^= (1 << kCache16Bits);
|
||||||
#else
|
|
||||||
*dstC++ = cache[sqrt_table[fi] >> (8 - kCache16Bits)];
|
|
||||||
#endif
|
|
||||||
} while (--count != 0);
|
} while (--count != 0);
|
||||||
}
|
}
|
||||||
}
|
} else if (proc == mirror_tileproc) {
|
||||||
else if (proc == mirror_tileproc)
|
|
||||||
{
|
|
||||||
do {
|
do {
|
||||||
SkFixed dist = SkFixedSqrt(SkFixedSquare(fx) + SkFixedSquare(fy));
|
SkFixed dist = SkFixedSqrt(SkFixedSquare(fx) + SkFixedSquare(fy));
|
||||||
unsigned fi = mirror_tileproc(dist);
|
unsigned fi = mirror_tileproc(dist);
|
||||||
SkASSERT(fi <= 0xFFFF);
|
SkASSERT(fi <= 0xFFFF);
|
||||||
fx += dx;
|
fx += dx;
|
||||||
fy += dy;
|
fy += dy;
|
||||||
#ifdef TEST_GRADIENT_DITHER
|
|
||||||
*dstC++ = cache[toggle + (fi >> (16 - kCache16Bits))];
|
*dstC++ = cache[toggle + (fi >> (16 - kCache16Bits))];
|
||||||
toggle ^= (1 << kCache16Bits);
|
toggle ^= (1 << kCache16Bits);
|
||||||
#else
|
|
||||||
*dstC++ = cache[fi >> (16 - kCache16Bits)];
|
|
||||||
#endif
|
|
||||||
} while (--count != 0);
|
} while (--count != 0);
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
SkASSERT(proc == repeat_tileproc);
|
SkASSERT(proc == repeat_tileproc);
|
||||||
do {
|
do {
|
||||||
SkFixed dist = SkFixedSqrt(SkFixedSquare(fx) + SkFixedSquare(fy));
|
SkFixed dist = SkFixedSqrt(SkFixedSquare(fx) + SkFixedSquare(fy));
|
||||||
@ -1139,17 +1074,11 @@ public:
|
|||||||
SkASSERT(fi <= 0xFFFF);
|
SkASSERT(fi <= 0xFFFF);
|
||||||
fx += dx;
|
fx += dx;
|
||||||
fy += dy;
|
fy += dy;
|
||||||
#ifdef TEST_GRADIENT_DITHER
|
|
||||||
*dstC++ = cache[toggle + (fi >> (16 - kCache16Bits))];
|
*dstC++ = cache[toggle + (fi >> (16 - kCache16Bits))];
|
||||||
toggle ^= (1 << kCache16Bits);
|
toggle ^= (1 << kCache16Bits);
|
||||||
#else
|
|
||||||
*dstC++ = cache[fi >> (16 - kCache16Bits)];
|
|
||||||
#endif
|
|
||||||
} while (--count != 0);
|
} while (--count != 0);
|
||||||
}
|
}
|
||||||
}
|
} else { // perspective case
|
||||||
else // perspective case
|
|
||||||
{
|
|
||||||
SkScalar dstX = SkIntToScalar(x);
|
SkScalar dstX = SkIntToScalar(x);
|
||||||
SkScalar dstY = SkIntToScalar(y);
|
SkScalar dstY = SkIntToScalar(y);
|
||||||
do {
|
do {
|
||||||
@ -1158,12 +1087,8 @@ public:
|
|||||||
SkASSERT(fi <= 0xFFFF);
|
SkASSERT(fi <= 0xFFFF);
|
||||||
|
|
||||||
int index = fi >> (16 - kCache16Bits);
|
int index = fi >> (16 - kCache16Bits);
|
||||||
#ifdef TEST_GRADIENT_DITHER
|
|
||||||
*dstC++ = cache[toggle + index];
|
*dstC++ = cache[toggle + index];
|
||||||
toggle ^= (1 << kCache16Bits);
|
toggle ^= (1 << kCache16Bits);
|
||||||
#else
|
|
||||||
*dstC++ = cache[index];
|
|
||||||
#endif
|
|
||||||
|
|
||||||
dstX += SK_Scalar1;
|
dstX += SK_Scalar1;
|
||||||
} while (--count != 0);
|
} while (--count != 0);
|
||||||
|
Loading…
Reference in New Issue
Block a user