add more checks for computing clamp counts, remove dead code
BUG=448299 Review URL: https://codereview.chromium.org/886473003
This commit is contained in:
parent
3bd12efdcf
commit
9d91eb3136
@ -1,4 +1,3 @@
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright 2011 Google Inc.
|
* Copyright 2011 Google Inc.
|
||||||
*
|
*
|
||||||
@ -6,8 +5,33 @@
|
|||||||
* found in the LICENSE file.
|
* found in the LICENSE file.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
#include "SkClampRange.h"
|
#include "SkClampRange.h"
|
||||||
|
#include "SkMath.h"
|
||||||
|
|
||||||
|
static int SkCLZ64(uint64_t value) {
|
||||||
|
int count = 0;
|
||||||
|
if (value >> 32) {
|
||||||
|
value >>= 32;
|
||||||
|
} else {
|
||||||
|
count += 32;
|
||||||
|
}
|
||||||
|
return count + SkCLZ(SkToU32(value));
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool sk_64_smul_check(int64_t a, int64_t b, int64_t* result) {
|
||||||
|
// Do it the slow way until we have some assembly.
|
||||||
|
int64_t ua = SkTAbs(a);
|
||||||
|
int64_t ub = SkTAbs(b);
|
||||||
|
int zeros = SkCLZ64(ua) + SkCLZ64(ub);
|
||||||
|
// this is a conservative check: it may return false when in fact it would not have overflowed.
|
||||||
|
// Hackers Delight uses 34 as its convervative check, but that is for 32x32 multiplies.
|
||||||
|
// Since we are looking at 64x64 muls, we add 32 to the check.
|
||||||
|
if (zeros < (32 + 34)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
*result = a * b;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* returns [0..count] for the number of steps (<= count) for which x0 <= edge
|
* returns [0..count] for the number of steps (<= count) for which x0 <= edge
|
||||||
@ -58,6 +82,14 @@ void SkClampRange::init(SkGradFixed fx0, SkGradFixed dx0, int count, int v0, int
|
|||||||
int64_t dx = dx0;
|
int64_t dx = dx0;
|
||||||
|
|
||||||
// start with ex equal to the last computed value
|
// start with ex equal to the last computed value
|
||||||
|
int64_t count_times_dx;
|
||||||
|
if (!sk_64_smul_check(count - 1, dx, &count_times_dx)) {
|
||||||
|
// we can't represent the computed end in 32.32, so just draw something (first color)
|
||||||
|
fCount1 = fCount2 = 0;
|
||||||
|
fCount0 = count;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
int64_t ex = fx + (count - 1) * dx;
|
int64_t ex = fx + (count - 1) * dx;
|
||||||
|
|
||||||
if ((uint64_t)(fx | ex) <= kFracMax_SkGradFixed) {
|
if ((uint64_t)(fx | ex) <= kFracMax_SkGradFixed) {
|
||||||
@ -77,8 +109,6 @@ void SkClampRange::init(SkGradFixed fx0, SkGradFixed dx0, int count, int v0, int
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
int extraCount = 0;
|
|
||||||
|
|
||||||
// now make ex be 1 past the last computed value
|
// now make ex be 1 past the last computed value
|
||||||
ex += dx;
|
ex += dx;
|
||||||
|
|
||||||
@ -93,11 +123,15 @@ void SkClampRange::init(SkGradFixed fx0, SkGradFixed dx0, int count, int v0, int
|
|||||||
|
|
||||||
|
|
||||||
fCount0 = chop(fx, 0, ex, dx, count);
|
fCount0 = chop(fx, 0, ex, dx, count);
|
||||||
|
SkASSERT(fCount0 >= 0);
|
||||||
|
SkASSERT(fCount0 <= count);
|
||||||
count -= fCount0;
|
count -= fCount0;
|
||||||
fx += fCount0 * dx;
|
fx += fCount0 * dx;
|
||||||
SkASSERT(fx >= 0);
|
SkASSERT(fx >= 0);
|
||||||
SkASSERT(fCount0 == 0 || (fx - dx) < 0);
|
SkASSERT(fCount0 == 0 || (fx - dx) < 0);
|
||||||
fCount1 = chop(fx, kFracMax_SkGradFixed, ex, dx, count);
|
fCount1 = chop(fx, kFracMax_SkGradFixed, ex, dx, count);
|
||||||
|
SkASSERT(fCount1 >= 0);
|
||||||
|
SkASSERT(fCount1 <= count);
|
||||||
count -= fCount1;
|
count -= fCount1;
|
||||||
fCount2 = count;
|
fCount2 = count;
|
||||||
|
|
||||||
@ -121,10 +155,4 @@ void SkClampRange::init(SkGradFixed fx0, SkGradFixed dx0, int count, int v0, int
|
|||||||
if (fCount1 > 0) {
|
if (fCount1 > 0) {
|
||||||
fFx1 = fx0 + fCount0 * dx;
|
fFx1 = fx0 + fCount0 * dx;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dx > 0) {
|
|
||||||
fCount2 += extraCount;
|
|
||||||
} else {
|
|
||||||
fCount0 += extraCount;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -35,6 +35,15 @@ struct SkClampRange {
|
|||||||
|
|
||||||
void init(SkGradFixed fx, SkGradFixed dx, int count, int v0, int v1);
|
void init(SkGradFixed fx, SkGradFixed dx, int count, int v0, int v1);
|
||||||
|
|
||||||
|
void validate(int count) const {
|
||||||
|
#ifdef SK_DEBUG
|
||||||
|
SkASSERT(fCount0 >= 0);
|
||||||
|
SkASSERT(fCount1 >= 0);
|
||||||
|
SkASSERT(fCount2 >= 0);
|
||||||
|
SkASSERT(fCount0 + fCount1 + fCount2 == count);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void initFor1(SkGradFixed fx);
|
void initFor1(SkGradFixed fx);
|
||||||
};
|
};
|
||||||
|
@ -149,6 +149,7 @@ void shadeSpan_linear_clamp(TileProc proc, SkGradFixed dx, SkGradFixed fx,
|
|||||||
int toggle, int count) {
|
int toggle, int count) {
|
||||||
SkClampRange range;
|
SkClampRange range;
|
||||||
range.init(fx, dx, count, 0, SkGradientShaderBase::kCache32Count - 1);
|
range.init(fx, dx, count, 0, SkGradientShaderBase::kCache32Count - 1);
|
||||||
|
range.validate(count);
|
||||||
|
|
||||||
if ((count = range.fCount0) > 0) {
|
if ((count = range.fCount0) > 0) {
|
||||||
sk_memset32_dither(dstC,
|
sk_memset32_dither(dstC,
|
||||||
@ -332,6 +333,7 @@ void shadeSpan16_linear_clamp(TileProc proc, SkGradFixed dx, SkGradFixed fx,
|
|||||||
int toggle, int count) {
|
int toggle, int count) {
|
||||||
SkClampRange range;
|
SkClampRange range;
|
||||||
range.init(fx, dx, count, 0, SkGradientShaderBase::kCache32Count - 1);
|
range.init(fx, dx, count, 0, SkGradientShaderBase::kCache32Count - 1);
|
||||||
|
range.validate(count);
|
||||||
|
|
||||||
if ((count = range.fCount0) > 0) {
|
if ((count = range.fCount0) > 0) {
|
||||||
dither_memset16(dstC,
|
dither_memset16(dstC,
|
||||||
|
@ -12,6 +12,30 @@
|
|||||||
#include "SkTemplates.h"
|
#include "SkTemplates.h"
|
||||||
#include "Test.h"
|
#include "Test.h"
|
||||||
|
|
||||||
|
// https://code.google.com/p/chromium/issues/detail?id=448299
|
||||||
|
// Giant (inverse) matrix causes overflow when converting/computing using 32.32
|
||||||
|
// Before the fix, we would assert (and then crash).
|
||||||
|
static void test_big_grad(skiatest::Reporter* reporter) {
|
||||||
|
const SkColor colors[] = { SK_ColorRED, SK_ColorBLUE };
|
||||||
|
const SkPoint pts[] = {{ 15, 14.7112684f }, { 0.709064007f, 12.6108112f }};
|
||||||
|
SkShader* s = SkGradientShader::CreateLinear(pts, colors, NULL, 2, SkShader::kClamp_TileMode);
|
||||||
|
SkPaint paint;
|
||||||
|
paint.setShader(s)->unref();
|
||||||
|
|
||||||
|
SkBitmap bm;
|
||||||
|
bm.allocN32Pixels(2000, 1);
|
||||||
|
SkCanvas c(bm);
|
||||||
|
|
||||||
|
const SkScalar affine[] = {
|
||||||
|
1.06608627e-06f, 4.26434525e-07f, 6.2855f, 2.6611f, 273.4393f, 244.0046f
|
||||||
|
};
|
||||||
|
SkMatrix matrix;
|
||||||
|
matrix.setAffine(affine);
|
||||||
|
c.concat(matrix);
|
||||||
|
|
||||||
|
c.drawPaint(paint);
|
||||||
|
}
|
||||||
|
|
||||||
struct GradRec {
|
struct GradRec {
|
||||||
int fColorCount;
|
int fColorCount;
|
||||||
const SkColor* fColors;
|
const SkColor* fColors;
|
||||||
@ -192,4 +216,5 @@ static void TestGradientShaders(skiatest::Reporter* reporter) {
|
|||||||
DEF_TEST(Gradient, reporter) {
|
DEF_TEST(Gradient, reporter) {
|
||||||
TestGradientShaders(reporter);
|
TestGradientShaders(reporter);
|
||||||
TestConstantGradient(reporter);
|
TestConstantGradient(reporter);
|
||||||
|
test_big_grad(reporter);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user