Implement highQualityFilter16 so GM doesn't crash when you give it resources.

Testing consisted of:
 1) ninja -C out/Debug gm && gm -i resources --match mandrill_512 -w /tmp/gm
 2) notice that gm didn't segfault
 3) look in /tmp/gm and see a bunch of handsome monkeys

BUG=skia:1517
R=humper@google.com

Review URL: https://codereview.chromium.org/22801016

git-svn-id: http://skia.googlecode.com/svn/trunk@10917 2bbb7eff-a529-9590-31e7-b0007b416f81
This commit is contained in:
mtklein@google.com 2013-08-26 16:21:35 +00:00
parent 62aa8d6148
commit 0dc546c37c
4 changed files with 42 additions and 22 deletions

View File

@ -22,9 +22,10 @@
// the image is rotated or has some other complex transformation applied. // the image is rotated or has some other complex transformation applied.
// Scaled images will usually be rescaled directly before rasterization. // Scaled images will usually be rescaled directly before rasterization.
void highQualityFilter(const SkBitmapProcState& s, int x, int y, namespace {
SkPMColor* SK_RESTRICT colors, int count) {
template <typename Color, typename ColorPacker>
void highQualityFilter(ColorPacker pack, const SkBitmapProcState& s, int x, int y, Color* SK_RESTRICT colors, int count) {
const int maxX = s.fBitmap->width() - 1; const int maxX = s.fBitmap->width() - 1;
const int maxY = s.fBitmap->height() - 1; const int maxY = s.fBitmap->height() - 1;
@ -70,12 +71,27 @@ void highQualityFilter(const SkBitmapProcState& s, int x, int y,
int g = SkClampMax(SkScalarRoundToInt(fg), a); int g = SkClampMax(SkScalarRoundToInt(fg), a);
int b = SkClampMax(SkScalarRoundToInt(fb), a); int b = SkClampMax(SkScalarRoundToInt(fb), a);
*colors++ = SkPackARGB32(a, r, g, b); *colors++ = pack(a, r, g, b);
x++; x++;
} }
} }
uint16_t PackTo565(int /*a*/, int r, int g, int b) {
return SkPack888ToRGB16(r, g, b);
}
} // namespace
void highQualityFilter32(const SkBitmapProcState& s, int x, int y, SkPMColor* SK_RESTRICT colors, int count) {
highQualityFilter(&SkPackARGB32, s, x, y, colors, count);
}
void highQualityFilter16(const SkBitmapProcState& s, int x, int y, uint16_t* SK_RESTRICT colors, int count) {
highQualityFilter(&PackTo565, s, x, y, colors, count);
}
SK_CONF_DECLARE(const char *, c_bitmapFilter, "bitmap.filter", "mitchell", "Which scanline bitmap filter to use [mitchell, lanczos, hamming, gaussian, triangle, box]"); SK_CONF_DECLARE(const char *, c_bitmapFilter, "bitmap.filter", "mitchell", "Which scanline bitmap filter to use [mitchell, lanczos, hamming, gaussian, triangle, box]");
SkBitmapFilter *SkBitmapFilter::Allocate() { SkBitmapFilter *SkBitmapFilter::Allocate() {
@ -98,34 +114,35 @@ SkBitmapFilter *SkBitmapFilter::Allocate() {
return NULL; return NULL;
} }
SkBitmapProcState::ShaderProc32 bool SkBitmapProcState::setBitmapFilterProcs() {
SkBitmapProcState::chooseBitmapFilterProc() {
if (fFilterLevel != SkPaint::kHigh_FilterLevel) { if (fFilterLevel != SkPaint::kHigh_FilterLevel) {
return NULL; return false;
} }
if (fAlphaScale != 256) { if (fAlphaScale != 256) {
return NULL; return false;
} }
// TODO: consider supporting other configs (e.g. 565, A8) // TODO: consider supporting other configs (e.g. 565, A8)
if (fBitmap->config() != SkBitmap::kARGB_8888_Config) { if (fBitmap->config() != SkBitmap::kARGB_8888_Config) {
return NULL; return false;
} }
// TODO: consider supporting repeat and mirror // TODO: consider supporting repeat and mirror
if (SkShader::kClamp_TileMode != fTileModeX || SkShader::kClamp_TileMode != fTileModeY) { if (SkShader::kClamp_TileMode != fTileModeX || SkShader::kClamp_TileMode != fTileModeY) {
return NULL; return false;
} }
// TODO: is this right? do we want fBitmapFilter allocated even if we can't set shader procs?
if (fInvType & (SkMatrix::kAffine_Mask | SkMatrix::kScale_Mask)) { if (fInvType & (SkMatrix::kAffine_Mask | SkMatrix::kScale_Mask)) {
fBitmapFilter = SkBitmapFilter::Allocate(); fBitmapFilter = SkBitmapFilter::Allocate();
} }
if (fInvType & SkMatrix::kScale_Mask) { if (fInvType & SkMatrix::kScale_Mask) {
return highQualityFilter; fShaderProc32 = highQualityFilter32;
fShaderProc16 = highQualityFilter16;
return true;
} else { } else {
return NULL; return false;
} }
} }

View File

@ -376,8 +376,7 @@ bool SkBitmapProcState::chooseProcs(const SkMatrix& inv, const SkPaint& paint) {
SkASSERT(fInvType > SkMatrix::kTranslate_Mask); SkASSERT(fInvType > SkMatrix::kTranslate_Mask);
fShaderProc32 = this->chooseBitmapFilterProc(); if (!this->setBitmapFilterProcs()) {
if (!fShaderProc32) {
fFilterLevel = SkPaint::kLow_FilterLevel; fFilterLevel = SkPaint::kLow_FilterLevel;
} }
} }
@ -404,7 +403,7 @@ bool SkBitmapProcState::chooseProcs(const SkMatrix& inv, const SkPaint& paint) {
// No need to do this if we're doing HQ sampling; if filter quality is // No need to do this if we're doing HQ sampling; if filter quality is
// still set to HQ by the time we get here, then we must have installed // still set to HQ by the time we get here, then we must have installed
// the shader proc above and can skip all this. // the shader procs above and can skip all this.
if (fFilterLevel < SkPaint::kHigh_FilterLevel) { if (fFilterLevel < SkPaint::kHigh_FilterLevel) {

View File

@ -166,7 +166,9 @@ private:
SkBitmapFilter* fBitmapFilter; SkBitmapFilter* fBitmapFilter;
ShaderProc32 chooseBitmapFilterProc(); // If supported, sets fShaderProc32 and fShaderProc16 and returns true,
// otherwise returns false.
bool setBitmapFilterProcs();
// Return false if we failed to setup for fast translate (e.g. overflow) // Return false if we failed to setup for fast translate (e.g. overflow)
bool setupForTranslate(); bool setupForTranslate();
@ -208,9 +210,9 @@ void S32_opaque_D32_filter_DX(const SkBitmapProcState& s, const uint32_t xy[],
void S32_alpha_D32_filter_DX(const SkBitmapProcState& s, const uint32_t xy[], void S32_alpha_D32_filter_DX(const SkBitmapProcState& s, const uint32_t xy[],
int count, SkPMColor colors[]); int count, SkPMColor colors[]);
void S32_opaque_D32_filter_DXDY(const SkBitmapProcState& s, void S32_opaque_D32_filter_DXDY(const SkBitmapProcState& s,
const uint32_t xy[], int count, SkPMColor colors[]); const uint32_t xy[], int count, SkPMColor colors[]);
void S32_alpha_D32_filter_DXDY(const SkBitmapProcState& s, void S32_alpha_D32_filter_DXDY(const SkBitmapProcState& s,
const uint32_t xy[], int count, SkPMColor colors[]); const uint32_t xy[], int count, SkPMColor colors[]);
void ClampX_ClampY_filter_scale(const SkBitmapProcState& s, uint32_t xy[], void ClampX_ClampY_filter_scale(const SkBitmapProcState& s, uint32_t xy[],
int count, int x, int y); int count, int x, int y);
void ClampX_ClampY_nofilter_scale(const SkBitmapProcState& s, uint32_t xy[], void ClampX_ClampY_nofilter_scale(const SkBitmapProcState& s, uint32_t xy[],
@ -220,10 +222,12 @@ void ClampX_ClampY_filter_affine(const SkBitmapProcState& s,
void ClampX_ClampY_nofilter_affine(const SkBitmapProcState& s, void ClampX_ClampY_nofilter_affine(const SkBitmapProcState& s,
uint32_t xy[], int count, int x, int y); uint32_t xy[], int count, int x, int y);
void S32_D16_filter_DX(const SkBitmapProcState& s, void S32_D16_filter_DX(const SkBitmapProcState& s,
const uint32_t* xy, int count, uint16_t* colors); const uint32_t* xy, int count, uint16_t* colors);
void highQualityFilter(const SkBitmapProcState &s, int x, int y, void highQualityFilter32(const SkBitmapProcState &s, int x, int y,
SkPMColor *SK_RESTRICT colors, int count); SkPMColor *SK_RESTRICT colors, int count);
void highQualityFilter16(const SkBitmapProcState &s, int x, int y,
uint16_t *SK_RESTRICT colors, int count);
#endif #endif

View File

@ -155,7 +155,7 @@ void SkBitmapProcState::platformProcs() {
fMatrixProc = ClampX_ClampY_nofilter_affine_SSE2; fMatrixProc = ClampX_ClampY_nofilter_affine_SSE2;
} }
if (c_hqfilter_sse) { if (c_hqfilter_sse) {
if (fShaderProc32 == highQualityFilter) { if (fShaderProc32 == highQualityFilter32) {
fShaderProc32 = highQualityFilter_SSE2; fShaderProc32 = highQualityFilter_SSE2;
} }
} }