[Reland] Repeating SkBitmapProcState rounding bias
1) observe the bias in repeat matrix procs also. 2) add utility for device space -> bitmap space mapping. 3) remove unneeded filter bias This is a reland of https://codereview.chromium.org/1529833003/. The main difference (and the fix) vs. the prev version is increased precision: the mapper now operates with SkFractionalInts. R=reed@google.com BUG=skia:4680, skia:4649 GOLD_TRYBOT_URL= https://gold.skia.org/search2?unt=true&query=source_type%3Dgm&master=false&issue=1539083002 Review URL: https://codereview.chromium.org/1539083002
This commit is contained in:
parent
0152cc3819
commit
b3a835891c
@ -824,15 +824,10 @@ void Clamp_S32_opaque_D32_nofilter_DX_shaderproc(const void* sIn, int x, int y,
|
||||
SkFractionalInt fx;
|
||||
int dstY;
|
||||
{
|
||||
SkPoint pt;
|
||||
s.fInvProc(s.fInvMatrix, SkIntToScalar(x) + SK_ScalarHalf, SkIntToScalar(y) + SK_ScalarHalf,
|
||||
&pt);
|
||||
fx = SkScalarToFractionalInt(pt.fY)
|
||||
+ bitmap_sampler_inv_bias(s.fInvMatrix.getScaleY());
|
||||
const SkBitmapProcStateAutoMapper mapper(s, x, y);
|
||||
const unsigned maxY = s.fPixmap.height() - 1;
|
||||
dstY = SkClampMax(SkFractionalIntToInt(fx), maxY);
|
||||
fx = SkScalarToFractionalInt(pt.fX)
|
||||
+ bitmap_sampler_inv_bias(s.fInvMatrix.getScaleX());
|
||||
dstY = SkClampMax(SkFractionalIntToInt(mapper.y()), maxY);
|
||||
fx = mapper.x();
|
||||
}
|
||||
|
||||
const SkPMColor* SK_RESTRICT src = s.fPixmap.addr32(0, dstY);
|
||||
|
@ -25,17 +25,6 @@ typedef SkFixed3232 SkFractionalInt;
|
||||
#define SkFixedToFractionalInt(x) SkFixedToFixed3232(x)
|
||||
#define SkFractionalIntToInt(x) SkFixed3232ToInt(x)
|
||||
|
||||
// Applying a fixed point (SkFixed, SkFractionalInt) epsilon bias ensures that the inverse-mapped
|
||||
// bitmap coordinates are rounded consistently WRT geometry. Note that we only have to do this
|
||||
// when the scale is positive - for negative scales we're already rounding in the right direction.
|
||||
static inline int bitmap_sampler_inv_bias(SkScalar scale) {
|
||||
#ifndef SK_SUPPORT_LEGACY_BITMAP_SAMPLER_BIAS
|
||||
return -(scale > 0);
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
class SkPaint;
|
||||
|
||||
struct SkBitmapProcState {
|
||||
@ -210,4 +199,34 @@ void S32_D16_filter_DX(const SkBitmapProcState& s,
|
||||
void S32_D16_filter_DXDY(const SkBitmapProcState& s,
|
||||
const uint32_t* xy, int count, uint16_t* colors);
|
||||
|
||||
// Helper class for mapping the middle of pixel (x, y) into SkFractionalInt bitmap space.
|
||||
// TODO: filtered version which applies a fFilterOne{X,Y}/2 bias instead of epsilon?
|
||||
class SkBitmapProcStateAutoMapper {
|
||||
public:
|
||||
SkBitmapProcStateAutoMapper(const SkBitmapProcState& s, int x, int y) {
|
||||
SkPoint pt;
|
||||
s.fInvProc(s.fInvMatrix,
|
||||
SkIntToScalar(x) + SK_ScalarHalf,
|
||||
SkIntToScalar(y) + SK_ScalarHalf, &pt);
|
||||
|
||||
#ifndef SK_SUPPORT_LEGACY_BITMAP_SAMPLER_BIAS
|
||||
// SkFixed epsilon bias to ensure inverse-mapped bitmap coordinates are rounded
|
||||
// consistently WRT geometry. Note that we only need the bias for positive scales:
|
||||
// for negative scales, the rounding is intrinsically correct.
|
||||
// We scale it to persist SkFractionalInt -> SkFixed conversions.
|
||||
fX = SkScalarToFractionalInt(pt.x()) - SkFixedToFractionalInt(s.fInvMatrix.getScaleX() > 0);
|
||||
fY = SkScalarToFractionalInt(pt.y()) - SkFixedToFractionalInt(s.fInvMatrix.getScaleY() > 0);
|
||||
#else
|
||||
fX = SkScalarToFractionalInt(pt.x());
|
||||
fY = SkScalarToFractionalInt(pt.y());
|
||||
#endif
|
||||
}
|
||||
|
||||
SkFractionalInt x() const { return fX; }
|
||||
SkFractionalInt y() const { return fY; }
|
||||
|
||||
private:
|
||||
SkFractionalInt fX, fY;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -64,14 +64,12 @@ void SCALE_FILTER_NAME(const SkBitmapProcState& s,
|
||||
SkPoint pt;
|
||||
s.fInvProc(s.fInvMatrix, SkIntToScalar(x) + SK_ScalarHalf,
|
||||
SkIntToScalar(y) + SK_ScalarHalf, &pt);
|
||||
const SkFixed fy = SkScalarToFixed(pt.fY) - (s.fFilterOneY >> 1)
|
||||
+ bitmap_sampler_inv_bias(s.fInvMatrix.getScaleY());
|
||||
const SkFixed fy = SkScalarToFixed(pt.fY) - (s.fFilterOneY >> 1);
|
||||
const unsigned maxY = s.fPixmap.height() - 1;
|
||||
// compute our two Y values up front
|
||||
*xy++ = PACK_FILTER_Y_NAME(fy, maxY, s.fFilterOneY PREAMBLE_ARG_Y);
|
||||
// now initialize fx
|
||||
fx = SkScalarToFractionalInt(pt.fX) - (SkFixedToFractionalInt(one) >> 1)
|
||||
+ bitmap_sampler_inv_bias(s.fInvMatrix.getScaleX());
|
||||
fx = SkScalarToFractionalInt(pt.fX) - (SkFixedToFractionalInt(one) >> 1);
|
||||
}
|
||||
|
||||
#ifdef CHECK_FOR_DECAL
|
||||
@ -104,10 +102,8 @@ void AFFINE_FILTER_NAME(const SkBitmapProcState& s,
|
||||
|
||||
SkFixed oneX = s.fFilterOneX;
|
||||
SkFixed oneY = s.fFilterOneY;
|
||||
SkFixed fx = SkScalarToFixed(srcPt.fX) - (oneX >> 1)
|
||||
+ bitmap_sampler_inv_bias(s.fInvMatrix.getScaleX());
|
||||
SkFixed fy = SkScalarToFixed(srcPt.fY) - (oneY >> 1)
|
||||
+ bitmap_sampler_inv_bias(s.fInvMatrix.getScaleY());
|
||||
SkFixed fx = SkScalarToFixed(srcPt.fX) - (oneX >> 1);
|
||||
SkFixed fy = SkScalarToFixed(srcPt.fY) - (oneY >> 1);
|
||||
SkFixed dx = s.fInvSx;
|
||||
SkFixed dy = s.fInvKy;
|
||||
unsigned maxX = s.fPixmap.width() - 1;
|
||||
|
@ -22,13 +22,10 @@ void NoFilterProc_Scale(const SkBitmapProcState& s, uint32_t xy[],
|
||||
const unsigned maxX = s.fPixmap.width() - 1;
|
||||
SkFractionalInt fx;
|
||||
{
|
||||
SkPoint pt;
|
||||
s.fInvProc(s.fInvMatrix, SkIntToScalar(x) + SK_ScalarHalf,
|
||||
SkIntToScalar(y) + SK_ScalarHalf, &pt);
|
||||
fx = SkScalarToFractionalInt(pt.fY);
|
||||
const SkBitmapProcStateAutoMapper mapper(s, x, y);
|
||||
const unsigned maxY = s.fPixmap.height() - 1;
|
||||
*xy++ = TileProc::Y(s, SkFractionalIntToFixed(fx), maxY);
|
||||
fx = SkScalarToFractionalInt(pt.fX);
|
||||
*xy++ = TileProc::Y(s, SkFractionalIntToFixed(mapper.y()), maxY);
|
||||
fx = mapper.x();
|
||||
}
|
||||
|
||||
if (0 == maxX) {
|
||||
@ -80,13 +77,10 @@ void NoFilterProc_Affine(const SkBitmapProcState& s, uint32_t xy[],
|
||||
SkMatrix::kScale_Mask |
|
||||
SkMatrix::kAffine_Mask)) == 0);
|
||||
|
||||
SkPoint srcPt;
|
||||
s.fInvProc(s.fInvMatrix,
|
||||
SkIntToScalar(x) + SK_ScalarHalf,
|
||||
SkIntToScalar(y) + SK_ScalarHalf, &srcPt);
|
||||
const SkBitmapProcStateAutoMapper mapper(s, x, y);
|
||||
|
||||
SkFractionalInt fx = SkScalarToFractionalInt(srcPt.fX);
|
||||
SkFractionalInt fy = SkScalarToFractionalInt(srcPt.fY);
|
||||
SkFractionalInt fx = mapper.x();
|
||||
SkFractionalInt fy = mapper.y();
|
||||
SkFractionalInt dx = s.fInvSxFractionalInt;
|
||||
SkFractionalInt dy = s.fInvKyFractionalInt;
|
||||
int maxX = s.fPixmap.width() - 1;
|
||||
|
Loading…
Reference in New Issue
Block a user