SkBitmapProcState.cpp revision 6bb92bc0b52d31f3ded38927cdefbeb13a3df87a
1ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com 2ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com/* 3ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Copyright 2011 Google Inc. 4ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * 5ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Use of this source code is governed by a BSD-style license that can be 6ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * found in the LICENSE file. 7ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com */ 88a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkBitmapProcState.h" 98a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkColorPriv.h" 108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkFilterProc.h" 118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkPaint.h" 128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkShader.h" // for tilemodes 133ada0efdc8de8316df8113ec54ffd1a3f33ecd21digit@google.com#include "SkUtilsArm.h" 143ada0efdc8de8316df8113ec54ffd1a3f33ecd21digit@google.com 153ada0efdc8de8316df8113ec54ffd1a3f33ecd21digit@google.com#if !SK_ARM_NEON_IS_NONE 163ada0efdc8de8316df8113ec54ffd1a3f33ecd21digit@google.com// These are defined in src/opts/SkBitmapProcState_arm_neon.cpp 173ada0efdc8de8316df8113ec54ffd1a3f33ecd21digit@google.comextern const SkBitmapProcState::SampleProc16 gSkBitmapProcStateSample16_neon[]; 183ada0efdc8de8316df8113ec54ffd1a3f33ecd21digit@google.comextern const SkBitmapProcState::SampleProc32 gSkBitmapProcStateSample32_neon[]; 193ada0efdc8de8316df8113ec54ffd1a3f33ecd21digit@google.comextern void S16_D16_filter_DX_neon(const SkBitmapProcState&, const uint32_t*, int, uint16_t*); 203ada0efdc8de8316df8113ec54ffd1a3f33ecd21digit@google.comextern void Clamp_S16_D16_filter_DX_shaderproc_neon(const SkBitmapProcState&, int, int, uint16_t*, int); 213ada0efdc8de8316df8113ec54ffd1a3f33ecd21digit@google.comextern void Repeat_S16_D16_filter_DX_shaderproc_neon(const SkBitmapProcState&, int, int, uint16_t*, int); 223ada0efdc8de8316df8113ec54ffd1a3f33ecd21digit@google.comextern void SI8_opaque_D32_filter_DX_neon(const SkBitmapProcState&, const uint32_t*, int, SkPMColor*); 233ada0efdc8de8316df8113ec54ffd1a3f33ecd21digit@google.comextern void SI8_opaque_D32_filter_DX_shaderproc_neon(const SkBitmapProcState&, int, int, uint32_t*, int); 243ada0efdc8de8316df8113ec54ffd1a3f33ecd21digit@google.comextern void Clamp_SI8_opaque_D32_filter_DX_shaderproc_neon(const SkBitmapProcState&, int, int, uint32_t*, int); 253ada0efdc8de8316df8113ec54ffd1a3f33ecd21digit@google.com#endif 263ada0efdc8de8316df8113ec54ffd1a3f33ecd21digit@google.com 273ada0efdc8de8316df8113ec54ffd1a3f33ecd21digit@google.com#if !SK_ARM_NEON_IS_ALWAYS 283ada0efdc8de8316df8113ec54ffd1a3f33ecd21digit@google.com#define NAME_WRAP(x) x 293ada0efdc8de8316df8113ec54ffd1a3f33ecd21digit@google.com#include "SkBitmapProcState_filter.h" 303ada0efdc8de8316df8113ec54ffd1a3f33ecd21digit@google.com#include "SkBitmapProcState_procs.h" 313ada0efdc8de8316df8113ec54ffd1a3f33ecd21digit@google.com#endif 32b577b41c8ec26c21ae599e80a2707d42f03eaa60reed@android.com 33a44b4cc7976b06caf3a3f6b7913c2af92eb32217reed@android.com/////////////////////////////////////////////////////////////////////////////// 34a44b4cc7976b06caf3a3f6b7913c2af92eb32217reed@android.com 35c0e88e0d5d1260f81e7f6b66eeabfb25e6b95a4dreed@google.com/** 36c0e88e0d5d1260f81e7f6b66eeabfb25e6b95a4dreed@google.com * For the purposes of drawing bitmaps, if a matrix is "almost" translate 37c0e88e0d5d1260f81e7f6b66eeabfb25e6b95a4dreed@google.com * go ahead and treat it as if it were, so that subsequent code can go fast. 38c0e88e0d5d1260f81e7f6b66eeabfb25e6b95a4dreed@google.com */ 39c0e88e0d5d1260f81e7f6b66eeabfb25e6b95a4dreed@google.comstatic bool just_trans_clamp(const SkMatrix& matrix, const SkBitmap& bitmap) { 40c0e88e0d5d1260f81e7f6b66eeabfb25e6b95a4dreed@google.com SkMatrix::TypeMask mask = matrix.getType(); 41c0e88e0d5d1260f81e7f6b66eeabfb25e6b95a4dreed@google.com 42c0e88e0d5d1260f81e7f6b66eeabfb25e6b95a4dreed@google.com if (mask & (SkMatrix::kAffine_Mask | SkMatrix::kPerspective_Mask)) { 43c0e88e0d5d1260f81e7f6b66eeabfb25e6b95a4dreed@google.com return false; 44c0e88e0d5d1260f81e7f6b66eeabfb25e6b95a4dreed@google.com } 45c0e88e0d5d1260f81e7f6b66eeabfb25e6b95a4dreed@google.com if (mask & SkMatrix::kScale_Mask) { 46c0e88e0d5d1260f81e7f6b66eeabfb25e6b95a4dreed@google.com SkScalar sx = matrix[SkMatrix::kMScaleX]; 47c0e88e0d5d1260f81e7f6b66eeabfb25e6b95a4dreed@google.com SkScalar sy = matrix[SkMatrix::kMScaleY]; 48c0e88e0d5d1260f81e7f6b66eeabfb25e6b95a4dreed@google.com int w = bitmap.width(); 49c0e88e0d5d1260f81e7f6b66eeabfb25e6b95a4dreed@google.com int h = bitmap.height(); 50c0e88e0d5d1260f81e7f6b66eeabfb25e6b95a4dreed@google.com int sw = SkScalarRound(SkScalarMul(sx, SkIntToScalar(w))); 51c0e88e0d5d1260f81e7f6b66eeabfb25e6b95a4dreed@google.com int sh = SkScalarRound(SkScalarMul(sy, SkIntToScalar(h))); 52c0e88e0d5d1260f81e7f6b66eeabfb25e6b95a4dreed@google.com return sw == w && sh == h; 53c0e88e0d5d1260f81e7f6b66eeabfb25e6b95a4dreed@google.com } 54c0e88e0d5d1260f81e7f6b66eeabfb25e6b95a4dreed@google.com // if we got here, we're either kTranslate_Mask or identity 55c0e88e0d5d1260f81e7f6b66eeabfb25e6b95a4dreed@google.com return true; 56c0e88e0d5d1260f81e7f6b66eeabfb25e6b95a4dreed@google.com} 57c0e88e0d5d1260f81e7f6b66eeabfb25e6b95a4dreed@google.com 58c0e88e0d5d1260f81e7f6b66eeabfb25e6b95a4dreed@google.comstatic bool just_trans_general(const SkMatrix& matrix) { 59c0e88e0d5d1260f81e7f6b66eeabfb25e6b95a4dreed@google.com SkMatrix::TypeMask mask = matrix.getType(); 60c0e88e0d5d1260f81e7f6b66eeabfb25e6b95a4dreed@google.com 61c0e88e0d5d1260f81e7f6b66eeabfb25e6b95a4dreed@google.com if (mask & (SkMatrix::kAffine_Mask | SkMatrix::kPerspective_Mask)) { 62c0e88e0d5d1260f81e7f6b66eeabfb25e6b95a4dreed@google.com return false; 63c0e88e0d5d1260f81e7f6b66eeabfb25e6b95a4dreed@google.com } 64c0e88e0d5d1260f81e7f6b66eeabfb25e6b95a4dreed@google.com if (mask & SkMatrix::kScale_Mask) { 65c0e88e0d5d1260f81e7f6b66eeabfb25e6b95a4dreed@google.com const SkScalar tol = SK_Scalar1 / 32768; 66989a95ea77230e8347da18876e1bd5f39a78ebb5skia.committer@gmail.com 67c0e88e0d5d1260f81e7f6b66eeabfb25e6b95a4dreed@google.com if (!SkScalarNearlyZero(matrix[SkMatrix::kMScaleX] - SK_Scalar1, tol)) { 68c0e88e0d5d1260f81e7f6b66eeabfb25e6b95a4dreed@google.com return false; 69c0e88e0d5d1260f81e7f6b66eeabfb25e6b95a4dreed@google.com } 70c0e88e0d5d1260f81e7f6b66eeabfb25e6b95a4dreed@google.com if (!SkScalarNearlyZero(matrix[SkMatrix::kMScaleY] - SK_Scalar1, tol)) { 71c0e88e0d5d1260f81e7f6b66eeabfb25e6b95a4dreed@google.com return false; 72c0e88e0d5d1260f81e7f6b66eeabfb25e6b95a4dreed@google.com } 73c0e88e0d5d1260f81e7f6b66eeabfb25e6b95a4dreed@google.com } 74c0e88e0d5d1260f81e7f6b66eeabfb25e6b95a4dreed@google.com // if we got here, treat us as either kTranslate_Mask or identity 75c0e88e0d5d1260f81e7f6b66eeabfb25e6b95a4dreed@google.com return true; 76c0e88e0d5d1260f81e7f6b66eeabfb25e6b95a4dreed@google.com} 77c0e88e0d5d1260f81e7f6b66eeabfb25e6b95a4dreed@google.com 78c0e88e0d5d1260f81e7f6b66eeabfb25e6b95a4dreed@google.com/////////////////////////////////////////////////////////////////////////////// 79c0e88e0d5d1260f81e7f6b66eeabfb25e6b95a4dreed@google.com 808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic bool valid_for_filtering(unsigned dimension) { 818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // for filtering, width and height must fit in 14bits, since we use steal 828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // 2 bits from each to store our 4bit subpixel data 838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return (dimension & ~0x3FFF) == 0; 848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.combool SkBitmapProcState::chooseProcs(const SkMatrix& inv, const SkPaint& paint) { 878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (fOrigBitmap.width() == 0 || fOrigBitmap.height() == 0) { 888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return false; 898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 9007d1f008b365e94ef7c7347be19a03d00bd36805reed@android.com 918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkMatrix* m; 9207d1f008b365e94ef7c7347be19a03d00bd36805reed@android.com bool trivial_matrix = (inv.getType() & ~SkMatrix::kTranslate_Mask) == 0; 9307d1f008b365e94ef7c7347be19a03d00bd36805reed@android.com bool clamp_clamp = SkShader::kClamp_TileMode == fTileModeX && 94c0e88e0d5d1260f81e7f6b66eeabfb25e6b95a4dreed@google.com SkShader::kClamp_TileMode == fTileModeY; 95a44b4cc7976b06caf3a3f6b7913c2af92eb32217reed@android.com 9607d1f008b365e94ef7c7347be19a03d00bd36805reed@android.com if (clamp_clamp || trivial_matrix) { 978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com m = &inv; 988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } else { 998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fUnitInvMatrix = inv; 1008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fUnitInvMatrix.postIDiv(fOrigBitmap.width(), fOrigBitmap.height()); 1018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com m = &fUnitInvMatrix; 1028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 10307d1f008b365e94ef7c7347be19a03d00bd36805reed@android.com 1048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fBitmap = &fOrigBitmap; 1058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (fOrigBitmap.hasMipMap()) { 1068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int shift = fOrigBitmap.extractMipLevel(&fMipBitmap, 1078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkScalarToFixed(m->getScaleX()), 1088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkScalarToFixed(m->getSkewY())); 109989a95ea77230e8347da18876e1bd5f39a78ebb5skia.committer@gmail.com 1108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (shift > 0) { 1118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (m != &fUnitInvMatrix) { 1128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fUnitInvMatrix = *m; 1138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com m = &fUnitInvMatrix; 1148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 1158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkScalar scale = SkFixedToScalar(SK_Fixed1 >> shift); 1178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fUnitInvMatrix.postScale(scale, scale); 118fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 1198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // now point here instead of fOrigBitmap 1208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fBitmap = &fMipBitmap; 1218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 1228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 1238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 124c0e88e0d5d1260f81e7f6b66eeabfb25e6b95a4dreed@google.com // wack our matrix to exactly no-scale, if we're really close to begin with 125c0e88e0d5d1260f81e7f6b66eeabfb25e6b95a4dreed@google.com { 126c0e88e0d5d1260f81e7f6b66eeabfb25e6b95a4dreed@google.com bool fixupMatrix = clamp_clamp ? 127c0e88e0d5d1260f81e7f6b66eeabfb25e6b95a4dreed@google.com just_trans_clamp(*m, *fBitmap) : just_trans_general(*m); 128c0e88e0d5d1260f81e7f6b66eeabfb25e6b95a4dreed@google.com if (fixupMatrix) { 129c0e88e0d5d1260f81e7f6b66eeabfb25e6b95a4dreed@google.com if (m != &fUnitInvMatrix) { // can't mutate the original 130c0e88e0d5d1260f81e7f6b66eeabfb25e6b95a4dreed@google.com fUnitInvMatrix = inv; 131c0e88e0d5d1260f81e7f6b66eeabfb25e6b95a4dreed@google.com m = &fUnitInvMatrix; 132c0e88e0d5d1260f81e7f6b66eeabfb25e6b95a4dreed@google.com } 133c0e88e0d5d1260f81e7f6b66eeabfb25e6b95a4dreed@google.com fUnitInvMatrix.set(SkMatrix::kMScaleX, SK_Scalar1); 134c0e88e0d5d1260f81e7f6b66eeabfb25e6b95a4dreed@google.com fUnitInvMatrix.set(SkMatrix::kMScaleY, SK_Scalar1); 135c0e88e0d5d1260f81e7f6b66eeabfb25e6b95a4dreed@google.com } 136c0e88e0d5d1260f81e7f6b66eeabfb25e6b95a4dreed@google.com } 137c0e88e0d5d1260f81e7f6b66eeabfb25e6b95a4dreed@google.com 138c0e88e0d5d1260f81e7f6b66eeabfb25e6b95a4dreed@google.com // Below this point, we should never refer to the inv parameter, since we 139c0e88e0d5d1260f81e7f6b66eeabfb25e6b95a4dreed@google.com // may be using a munged version for "our" inverse. 140989a95ea77230e8347da18876e1bd5f39a78ebb5skia.committer@gmail.com 1418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fInvMatrix = m; 1428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fInvProc = m->getMapXYProc(); 1438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fInvType = m->getType(); 1448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fInvSx = SkScalarToFixed(m->getScaleX()); 1454bc0a9db18d58698057b8f38a6f21537aca4ddcfreed@google.com fInvSxFractionalInt = SkScalarToFractionalInt(m->getScaleX()); 1468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fInvKy = SkScalarToFixed(m->getSkewY()); 147411215ae2b9a36ff6e262f77d7fb5071cc084f00reed@google.com fInvKyFractionalInt = SkScalarToFractionalInt(m->getSkewY()); 1488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fAlphaScale = SkAlpha255To256(paint.getAlpha()); 1508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // pick-up filtering from the paint, but only if the matrix is 1528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // more complex than identity/translate (i.e. no need to pay the cost 1538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // of filtering if we're not scaled etc.). 1548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // note: we explicitly check inv, since m might be scaled due to unitinv 1558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // trickery, but we don't want to see that for this test 1568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fDoFilter = paint.isFilterBitmap() && 157c0e88e0d5d1260f81e7f6b66eeabfb25e6b95a4dreed@google.com (fInvType > SkMatrix::kTranslate_Mask && 1588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com valid_for_filtering(fBitmap->width() | fBitmap->height())); 1598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1607a99eb1c63d4327d352af09ea59f039f014e4028reed@android.com fShaderProc32 = NULL; 1617a99eb1c63d4327d352af09ea59f039f014e4028reed@android.com fShaderProc16 = NULL; 1627a99eb1c63d4327d352af09ea59f039f014e4028reed@android.com fSampleProc32 = NULL; 1637a99eb1c63d4327d352af09ea59f039f014e4028reed@android.com fSampleProc16 = NULL; 16448534f96b9ccb747cecbdf3818bfbd3523a4d034reed@android.com 16507d1f008b365e94ef7c7347be19a03d00bd36805reed@android.com fMatrixProc = this->chooseMatrixProc(trivial_matrix); 1668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (NULL == fMatrixProc) { 1678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return false; 1688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 1698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com /////////////////////////////////////////////////////////////////////// 171fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 1728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int index = 0; 1738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (fAlphaScale < 256) { // note: this distinction is not used for D16 1748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com index |= 1; 1758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 1768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (fInvType <= (SkMatrix::kTranslate_Mask | SkMatrix::kScale_Mask)) { 1778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com index |= 2; 1788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 1798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (fDoFilter) { 1808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com index |= 4; 1818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 1828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // bits 3,4,5 encoding the source bitmap format 1838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com switch (fBitmap->config()) { 1848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com case SkBitmap::kARGB_8888_Config: 1858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com index |= 0; 1868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com break; 1878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com case SkBitmap::kRGB_565_Config: 1888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com index |= 8; 1898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com break; 1908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com case SkBitmap::kIndex8_Config: 1918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com index |= 16; 1928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com break; 1938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com case SkBitmap::kARGB_4444_Config: 1948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com index |= 24; 1958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com break; 1968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com case SkBitmap::kA8_Config: 1978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com index |= 32; 1988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fPaintPMColor = SkPreMultiplyColor(paint.getColor()); 1993469c76c40790b409621fd7eff34f56240718549reed@android.com break; 2008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com default: 2018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return false; 2028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 2038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 2043ada0efdc8de8316df8113ec54ffd1a3f33ecd21digit@google.com#if !SK_ARM_NEON_IS_ALWAYS 2053ada0efdc8de8316df8113ec54ffd1a3f33ecd21digit@google.com static const SampleProc32 gSkBitmapProcStateSample32[] = { 2068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com S32_opaque_D32_nofilter_DXDY, 2078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com S32_alpha_D32_nofilter_DXDY, 2088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com S32_opaque_D32_nofilter_DX, 2098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com S32_alpha_D32_nofilter_DX, 2108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com S32_opaque_D32_filter_DXDY, 2118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com S32_alpha_D32_filter_DXDY, 2128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com S32_opaque_D32_filter_DX, 2138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com S32_alpha_D32_filter_DX, 214fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 2158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com S16_opaque_D32_nofilter_DXDY, 2168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com S16_alpha_D32_nofilter_DXDY, 2178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com S16_opaque_D32_nofilter_DX, 2188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com S16_alpha_D32_nofilter_DX, 2198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com S16_opaque_D32_filter_DXDY, 2208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com S16_alpha_D32_filter_DXDY, 2218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com S16_opaque_D32_filter_DX, 2228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com S16_alpha_D32_filter_DX, 223fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 2248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SI8_opaque_D32_nofilter_DXDY, 2258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SI8_alpha_D32_nofilter_DXDY, 2268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SI8_opaque_D32_nofilter_DX, 2278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SI8_alpha_D32_nofilter_DX, 2288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SI8_opaque_D32_filter_DXDY, 2298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SI8_alpha_D32_filter_DXDY, 2308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SI8_opaque_D32_filter_DX, 2318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SI8_alpha_D32_filter_DX, 232fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 2338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com S4444_opaque_D32_nofilter_DXDY, 2348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com S4444_alpha_D32_nofilter_DXDY, 2358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com S4444_opaque_D32_nofilter_DX, 2368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com S4444_alpha_D32_nofilter_DX, 2378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com S4444_opaque_D32_filter_DXDY, 2388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com S4444_alpha_D32_filter_DXDY, 2398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com S4444_opaque_D32_filter_DX, 2408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com S4444_alpha_D32_filter_DX, 241fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 2428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // A8 treats alpha/opauqe the same (equally efficient) 2438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SA8_alpha_D32_nofilter_DXDY, 2448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SA8_alpha_D32_nofilter_DXDY, 2458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SA8_alpha_D32_nofilter_DX, 2468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SA8_alpha_D32_nofilter_DX, 2478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SA8_alpha_D32_filter_DXDY, 2488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SA8_alpha_D32_filter_DXDY, 2498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SA8_alpha_D32_filter_DX, 2508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SA8_alpha_D32_filter_DX 2518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com }; 252fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 2533ada0efdc8de8316df8113ec54ffd1a3f33ecd21digit@google.com static const SampleProc16 gSkBitmapProcStateSample16[] = { 2548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com S32_D16_nofilter_DXDY, 2558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com S32_D16_nofilter_DX, 2568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com S32_D16_filter_DXDY, 2578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com S32_D16_filter_DX, 258fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 2598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com S16_D16_nofilter_DXDY, 2608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com S16_D16_nofilter_DX, 2618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com S16_D16_filter_DXDY, 2628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com S16_D16_filter_DX, 263fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 2648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SI8_D16_nofilter_DXDY, 2658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SI8_D16_nofilter_DX, 2668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SI8_D16_filter_DXDY, 2678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SI8_D16_filter_DX, 268fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 2698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // Don't support 4444 -> 565 2708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com NULL, NULL, NULL, NULL, 2718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // Don't support A8 -> 565 2728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com NULL, NULL, NULL, NULL 2738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com }; 2743ada0efdc8de8316df8113ec54ffd1a3f33ecd21digit@google.com#endif 27548534f96b9ccb747cecbdf3818bfbd3523a4d034reed@android.com 2763ada0efdc8de8316df8113ec54ffd1a3f33ecd21digit@google.com fSampleProc32 = SK_ARM_NEON_WRAP(gSkBitmapProcStateSample32)[index]; 2778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com index >>= 1; // shift away any opaque/alpha distinction 2783ada0efdc8de8316df8113ec54ffd1a3f33ecd21digit@google.com fSampleProc16 = SK_ARM_NEON_WRAP(gSkBitmapProcStateSample16)[index]; 2798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 280a44b4cc7976b06caf3a3f6b7913c2af92eb32217reed@android.com // our special-case shaderprocs 2813ada0efdc8de8316df8113ec54ffd1a3f33ecd21digit@google.com if (SK_ARM_NEON_WRAP(S16_D16_filter_DX) == fSampleProc16) { 282aa9152abbca3a958a9379f4e5067a1c37486d677reed@android.com if (clamp_clamp) { 2833ada0efdc8de8316df8113ec54ffd1a3f33ecd21digit@google.com fShaderProc16 = SK_ARM_NEON_WRAP(Clamp_S16_D16_filter_DX_shaderproc); 284aa9152abbca3a958a9379f4e5067a1c37486d677reed@android.com } else if (SkShader::kRepeat_TileMode == fTileModeX && 285aa9152abbca3a958a9379f4e5067a1c37486d677reed@android.com SkShader::kRepeat_TileMode == fTileModeY) { 2863ada0efdc8de8316df8113ec54ffd1a3f33ecd21digit@google.com fShaderProc16 = SK_ARM_NEON_WRAP(Repeat_S16_D16_filter_DX_shaderproc); 287aa9152abbca3a958a9379f4e5067a1c37486d677reed@android.com } 2883ada0efdc8de8316df8113ec54ffd1a3f33ecd21digit@google.com } else if (SK_ARM_NEON_WRAP(SI8_opaque_D32_filter_DX) == fSampleProc32 && clamp_clamp) { 2893ada0efdc8de8316df8113ec54ffd1a3f33ecd21digit@google.com fShaderProc32 = SK_ARM_NEON_WRAP(Clamp_SI8_opaque_D32_filter_DX_shaderproc); 290a44b4cc7976b06caf3a3f6b7913c2af92eb32217reed@android.com } 291c9a1d4b519c2db8e43e54fef068c46462d2f8a4breed@android.com 2929a4c746a1f0f91a5be2708a4c2018dfe14f62e48reed@google.com if (NULL == fShaderProc32) { 2939a4c746a1f0f91a5be2708a4c2018dfe14f62e48reed@google.com fShaderProc32 = this->chooseShaderProc32(); 2949a4c746a1f0f91a5be2708a4c2018dfe14f62e48reed@google.com } 2959a4c746a1f0f91a5be2708a4c2018dfe14f62e48reed@google.com 296c9a1d4b519c2db8e43e54fef068c46462d2f8a4breed@android.com // see if our platform has any accelerated overrides 297c9a1d4b519c2db8e43e54fef068c46462d2f8a4breed@android.com this->platformProcs(); 2988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return true; 2998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 3008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 3019a4c746a1f0f91a5be2708a4c2018dfe14f62e48reed@google.comstatic void Clamp_S32_D32_nofilter_trans_shaderproc(const SkBitmapProcState& s, 3029a4c746a1f0f91a5be2708a4c2018dfe14f62e48reed@google.com int x, int y, 3039a4c746a1f0f91a5be2708a4c2018dfe14f62e48reed@google.com SkPMColor* SK_RESTRICT colors, 3049a4c746a1f0f91a5be2708a4c2018dfe14f62e48reed@google.com int count) { 3059a4c746a1f0f91a5be2708a4c2018dfe14f62e48reed@google.com SkASSERT(((s.fInvType & ~SkMatrix::kTranslate_Mask)) == 0); 3069a4c746a1f0f91a5be2708a4c2018dfe14f62e48reed@google.com SkASSERT(s.fInvKy == 0); 3079a4c746a1f0f91a5be2708a4c2018dfe14f62e48reed@google.com SkASSERT(count > 0 && colors != NULL); 3089a4c746a1f0f91a5be2708a4c2018dfe14f62e48reed@google.com SkASSERT(!s.fDoFilter); 30920c301bd1aa4578c6d0abb23ac2c72b5fbb436dbskia.committer@gmail.com 3109a4c746a1f0f91a5be2708a4c2018dfe14f62e48reed@google.com const int maxX = s.fBitmap->width() - 1; 311f7698de60e2cfecf84cb84f957e6fe69325fe67freed@google.com const int maxY = s.fBitmap->height() - 1; 312f7698de60e2cfecf84cb84f957e6fe69325fe67freed@google.com int ix = s.fFilterOneX + x; 313f7698de60e2cfecf84cb84f957e6fe69325fe67freed@google.com int iy = SkClampMax(s.fFilterOneY + y, maxY); 314f7698de60e2cfecf84cb84f957e6fe69325fe67freed@google.com#ifdef SK_DEBUG 3159a4c746a1f0f91a5be2708a4c2018dfe14f62e48reed@google.com { 3169a4c746a1f0f91a5be2708a4c2018dfe14f62e48reed@google.com SkPoint pt; 3179a4c746a1f0f91a5be2708a4c2018dfe14f62e48reed@google.com s.fInvProc(*s.fInvMatrix, SkIntToScalar(x) + SK_ScalarHalf, 3189a4c746a1f0f91a5be2708a4c2018dfe14f62e48reed@google.com SkIntToScalar(y) + SK_ScalarHalf, &pt); 319f7698de60e2cfecf84cb84f957e6fe69325fe67freed@google.com int iy2 = SkClampMax(SkScalarFloorToInt(pt.fY), maxY); 320f7698de60e2cfecf84cb84f957e6fe69325fe67freed@google.com int ix2 = SkScalarFloorToInt(pt.fX); 32120c301bd1aa4578c6d0abb23ac2c72b5fbb436dbskia.committer@gmail.com 322f7698de60e2cfecf84cb84f957e6fe69325fe67freed@google.com SkASSERT(iy == iy2); 323f7698de60e2cfecf84cb84f957e6fe69325fe67freed@google.com SkASSERT(ix == ix2); 3249a4c746a1f0f91a5be2708a4c2018dfe14f62e48reed@google.com } 325f7698de60e2cfecf84cb84f957e6fe69325fe67freed@google.com#endif 326f7698de60e2cfecf84cb84f957e6fe69325fe67freed@google.com const SkPMColor* row = s.fBitmap->getAddr32(0, iy); 32720c301bd1aa4578c6d0abb23ac2c72b5fbb436dbskia.committer@gmail.com 3289a4c746a1f0f91a5be2708a4c2018dfe14f62e48reed@google.com // clamp to the left 3299a4c746a1f0f91a5be2708a4c2018dfe14f62e48reed@google.com if (ix < 0) { 3309a4c746a1f0f91a5be2708a4c2018dfe14f62e48reed@google.com int n = SkMin32(-ix, count); 3319a4c746a1f0f91a5be2708a4c2018dfe14f62e48reed@google.com sk_memset32(colors, row[0], n); 3329a4c746a1f0f91a5be2708a4c2018dfe14f62e48reed@google.com count -= n; 3339a4c746a1f0f91a5be2708a4c2018dfe14f62e48reed@google.com if (0 == count) { 3349a4c746a1f0f91a5be2708a4c2018dfe14f62e48reed@google.com return; 3359a4c746a1f0f91a5be2708a4c2018dfe14f62e48reed@google.com } 3369a4c746a1f0f91a5be2708a4c2018dfe14f62e48reed@google.com colors += n; 3379a4c746a1f0f91a5be2708a4c2018dfe14f62e48reed@google.com SkASSERT(-ix == n); 3389a4c746a1f0f91a5be2708a4c2018dfe14f62e48reed@google.com ix = 0; 3399a4c746a1f0f91a5be2708a4c2018dfe14f62e48reed@google.com } 3409a4c746a1f0f91a5be2708a4c2018dfe14f62e48reed@google.com // copy the middle 3419a4c746a1f0f91a5be2708a4c2018dfe14f62e48reed@google.com if (ix <= maxX) { 3429a4c746a1f0f91a5be2708a4c2018dfe14f62e48reed@google.com int n = SkMin32(maxX - ix + 1, count); 3439a4c746a1f0f91a5be2708a4c2018dfe14f62e48reed@google.com memcpy(colors, row + ix, n * sizeof(SkPMColor)); 3449a4c746a1f0f91a5be2708a4c2018dfe14f62e48reed@google.com count -= n; 3459a4c746a1f0f91a5be2708a4c2018dfe14f62e48reed@google.com if (0 == count) { 3469a4c746a1f0f91a5be2708a4c2018dfe14f62e48reed@google.com return; 3479a4c746a1f0f91a5be2708a4c2018dfe14f62e48reed@google.com } 3489a4c746a1f0f91a5be2708a4c2018dfe14f62e48reed@google.com colors += n; 3499a4c746a1f0f91a5be2708a4c2018dfe14f62e48reed@google.com } 3509a4c746a1f0f91a5be2708a4c2018dfe14f62e48reed@google.com SkASSERT(count > 0); 3519a4c746a1f0f91a5be2708a4c2018dfe14f62e48reed@google.com // clamp to the right 3529a4c746a1f0f91a5be2708a4c2018dfe14f62e48reed@google.com sk_memset32(colors, row[maxX], count); 3539a4c746a1f0f91a5be2708a4c2018dfe14f62e48reed@google.com} 3549a4c746a1f0f91a5be2708a4c2018dfe14f62e48reed@google.com 355a8d99307717c5fe02043969db0566c236a08c313reed@google.comstatic inline int sk_int_mod(int x, int n) { 356a8d99307717c5fe02043969db0566c236a08c313reed@google.com SkASSERT(n > 0); 357a8d99307717c5fe02043969db0566c236a08c313reed@google.com if ((unsigned)x >= (unsigned)n) { 358a8d99307717c5fe02043969db0566c236a08c313reed@google.com if (x < 0) { 359a8d99307717c5fe02043969db0566c236a08c313reed@google.com x = n + ~(~x % n); 360a8d99307717c5fe02043969db0566c236a08c313reed@google.com } else { 361a8d99307717c5fe02043969db0566c236a08c313reed@google.com x = x % n; 362a8d99307717c5fe02043969db0566c236a08c313reed@google.com } 363a8d99307717c5fe02043969db0566c236a08c313reed@google.com } 364a8d99307717c5fe02043969db0566c236a08c313reed@google.com return x; 365a8d99307717c5fe02043969db0566c236a08c313reed@google.com} 366a8d99307717c5fe02043969db0566c236a08c313reed@google.com 367a8d99307717c5fe02043969db0566c236a08c313reed@google.comstatic void Repeat_S32_D32_nofilter_trans_shaderproc(const SkBitmapProcState& s, 368a8d99307717c5fe02043969db0566c236a08c313reed@google.com int x, int y, 369a8d99307717c5fe02043969db0566c236a08c313reed@google.com SkPMColor* SK_RESTRICT colors, 370a8d99307717c5fe02043969db0566c236a08c313reed@google.com int count) { 371a8d99307717c5fe02043969db0566c236a08c313reed@google.com SkASSERT(((s.fInvType & ~SkMatrix::kTranslate_Mask)) == 0); 372a8d99307717c5fe02043969db0566c236a08c313reed@google.com SkASSERT(s.fInvKy == 0); 373a8d99307717c5fe02043969db0566c236a08c313reed@google.com SkASSERT(count > 0 && colors != NULL); 374a8d99307717c5fe02043969db0566c236a08c313reed@google.com SkASSERT(!s.fDoFilter); 37520c301bd1aa4578c6d0abb23ac2c72b5fbb436dbskia.committer@gmail.com 376a8d99307717c5fe02043969db0566c236a08c313reed@google.com const int stopX = s.fBitmap->width(); 377a8d99307717c5fe02043969db0566c236a08c313reed@google.com const int stopY = s.fBitmap->height(); 378a8d99307717c5fe02043969db0566c236a08c313reed@google.com int ix = s.fFilterOneX + x; 379a8d99307717c5fe02043969db0566c236a08c313reed@google.com int iy = sk_int_mod(s.fFilterOneY + y, stopY); 380a8d99307717c5fe02043969db0566c236a08c313reed@google.com#ifdef SK_DEBUG 381a8d99307717c5fe02043969db0566c236a08c313reed@google.com { 382a8d99307717c5fe02043969db0566c236a08c313reed@google.com SkPoint pt; 383a8d99307717c5fe02043969db0566c236a08c313reed@google.com s.fInvProc(*s.fInvMatrix, SkIntToScalar(x) + SK_ScalarHalf, 384a8d99307717c5fe02043969db0566c236a08c313reed@google.com SkIntToScalar(y) + SK_ScalarHalf, &pt); 385a8d99307717c5fe02043969db0566c236a08c313reed@google.com int iy2 = sk_int_mod(SkScalarFloorToInt(pt.fY), stopY); 386a8d99307717c5fe02043969db0566c236a08c313reed@google.com int ix2 = SkScalarFloorToInt(pt.fX); 38720c301bd1aa4578c6d0abb23ac2c72b5fbb436dbskia.committer@gmail.com 388a8d99307717c5fe02043969db0566c236a08c313reed@google.com SkASSERT(iy == iy2); 389a8d99307717c5fe02043969db0566c236a08c313reed@google.com SkASSERT(ix == ix2); 390a8d99307717c5fe02043969db0566c236a08c313reed@google.com } 391a8d99307717c5fe02043969db0566c236a08c313reed@google.com#endif 392a8d99307717c5fe02043969db0566c236a08c313reed@google.com const SkPMColor* row = s.fBitmap->getAddr32(0, iy); 393a8d99307717c5fe02043969db0566c236a08c313reed@google.com 394a8d99307717c5fe02043969db0566c236a08c313reed@google.com ix = sk_int_mod(ix, stopX); 395a8d99307717c5fe02043969db0566c236a08c313reed@google.com for (;;) { 396a8d99307717c5fe02043969db0566c236a08c313reed@google.com int n = SkMin32(stopX - ix, count); 397a8d99307717c5fe02043969db0566c236a08c313reed@google.com memcpy(colors, row + ix, n * sizeof(SkPMColor)); 398a8d99307717c5fe02043969db0566c236a08c313reed@google.com count -= n; 399a8d99307717c5fe02043969db0566c236a08c313reed@google.com if (0 == count) { 400a8d99307717c5fe02043969db0566c236a08c313reed@google.com return; 401a8d99307717c5fe02043969db0566c236a08c313reed@google.com } 402a8d99307717c5fe02043969db0566c236a08c313reed@google.com colors += n; 403a8d99307717c5fe02043969db0566c236a08c313reed@google.com ix = 0; 404a8d99307717c5fe02043969db0566c236a08c313reed@google.com } 405a8d99307717c5fe02043969db0566c236a08c313reed@google.com} 406a8d99307717c5fe02043969db0566c236a08c313reed@google.com 4076bb92bc0b52d31f3ded38927cdefbeb13a3df87areed@google.comstatic void DoNothing_shaderproc(const SkBitmapProcState&, int x, int y, 4086bb92bc0b52d31f3ded38927cdefbeb13a3df87areed@google.com SkPMColor* SK_RESTRICT colors, int count) { 4096bb92bc0b52d31f3ded38927cdefbeb13a3df87areed@google.com // if we get called, the matrix is too tricky, so we just draw nothing 4106bb92bc0b52d31f3ded38927cdefbeb13a3df87areed@google.com sk_memset32(colors, 0, count); 4116bb92bc0b52d31f3ded38927cdefbeb13a3df87areed@google.com} 4126bb92bc0b52d31f3ded38927cdefbeb13a3df87areed@google.com 4136bb92bc0b52d31f3ded38927cdefbeb13a3df87areed@google.combool SkBitmapProcState::setupForTranslate() { 414a8d99307717c5fe02043969db0566c236a08c313reed@google.com SkPoint pt; 415a8d99307717c5fe02043969db0566c236a08c313reed@google.com fInvProc(*fInvMatrix, SK_ScalarHalf, SK_ScalarHalf, &pt); 4166bb92bc0b52d31f3ded38927cdefbeb13a3df87areed@google.com 4176bb92bc0b52d31f3ded38927cdefbeb13a3df87areed@google.com /* 4186bb92bc0b52d31f3ded38927cdefbeb13a3df87areed@google.com * if the translate is larger than our ints, we can get random results, or 4196bb92bc0b52d31f3ded38927cdefbeb13a3df87areed@google.com * worse, we might get 0x80000000, which wreaks havoc on us, since we can't 4206bb92bc0b52d31f3ded38927cdefbeb13a3df87areed@google.com * negate it. 4216bb92bc0b52d31f3ded38927cdefbeb13a3df87areed@google.com */ 4226bb92bc0b52d31f3ded38927cdefbeb13a3df87areed@google.com const SkScalar too_big = SkIntToScalar(1 << 30); 4236bb92bc0b52d31f3ded38927cdefbeb13a3df87areed@google.com if (SkScalarAbs(pt.fX) > too_big || SkScalarAbs(pt.fY) > too_big) { 4246bb92bc0b52d31f3ded38927cdefbeb13a3df87areed@google.com return false; 4256bb92bc0b52d31f3ded38927cdefbeb13a3df87areed@google.com } 4266bb92bc0b52d31f3ded38927cdefbeb13a3df87areed@google.com 427a8d99307717c5fe02043969db0566c236a08c313reed@google.com // Since we know we're not filtered, we re-purpose these fields allow 428a8d99307717c5fe02043969db0566c236a08c313reed@google.com // us to go from device -> src coordinates w/ just an integer add, 429a8d99307717c5fe02043969db0566c236a08c313reed@google.com // rather than running through the inverse-matrix 430a8d99307717c5fe02043969db0566c236a08c313reed@google.com fFilterOneX = SkScalarFloorToInt(pt.fX); 431a8d99307717c5fe02043969db0566c236a08c313reed@google.com fFilterOneY = SkScalarFloorToInt(pt.fY); 4326bb92bc0b52d31f3ded38927cdefbeb13a3df87areed@google.com return true; 433a8d99307717c5fe02043969db0566c236a08c313reed@google.com} 434a8d99307717c5fe02043969db0566c236a08c313reed@google.com 4359a4c746a1f0f91a5be2708a4c2018dfe14f62e48reed@google.comSkBitmapProcState::ShaderProc32 SkBitmapProcState::chooseShaderProc32() { 4369a4c746a1f0f91a5be2708a4c2018dfe14f62e48reed@google.com if (fAlphaScale < 256) { 4379a4c746a1f0f91a5be2708a4c2018dfe14f62e48reed@google.com return NULL; 4389a4c746a1f0f91a5be2708a4c2018dfe14f62e48reed@google.com } 4399a4c746a1f0f91a5be2708a4c2018dfe14f62e48reed@google.com if (fInvType > SkMatrix::kTranslate_Mask) { 4409a4c746a1f0f91a5be2708a4c2018dfe14f62e48reed@google.com return NULL; 4419a4c746a1f0f91a5be2708a4c2018dfe14f62e48reed@google.com } 4429a4c746a1f0f91a5be2708a4c2018dfe14f62e48reed@google.com if (fDoFilter) { 4439a4c746a1f0f91a5be2708a4c2018dfe14f62e48reed@google.com return NULL; 4449a4c746a1f0f91a5be2708a4c2018dfe14f62e48reed@google.com } 4459a4c746a1f0f91a5be2708a4c2018dfe14f62e48reed@google.com if (SkBitmap::kARGB_8888_Config != fBitmap->config()) { 4469a4c746a1f0f91a5be2708a4c2018dfe14f62e48reed@google.com return NULL; 4479a4c746a1f0f91a5be2708a4c2018dfe14f62e48reed@google.com } 4489a4c746a1f0f91a5be2708a4c2018dfe14f62e48reed@google.com 449a8d99307717c5fe02043969db0566c236a08c313reed@google.com SkShader::TileMode tx = (SkShader::TileMode)fTileModeX; 450a8d99307717c5fe02043969db0566c236a08c313reed@google.com SkShader::TileMode ty = (SkShader::TileMode)fTileModeY; 451a8d99307717c5fe02043969db0566c236a08c313reed@google.com 452a8d99307717c5fe02043969db0566c236a08c313reed@google.com if (SkShader::kClamp_TileMode == tx && SkShader::kClamp_TileMode == ty) { 4536bb92bc0b52d31f3ded38927cdefbeb13a3df87areed@google.com if (this->setupForTranslate()) { 4546bb92bc0b52d31f3ded38927cdefbeb13a3df87areed@google.com return Clamp_S32_D32_nofilter_trans_shaderproc; 4556bb92bc0b52d31f3ded38927cdefbeb13a3df87areed@google.com } 4566bb92bc0b52d31f3ded38927cdefbeb13a3df87areed@google.com return DoNothing_shaderproc; 4579a4c746a1f0f91a5be2708a4c2018dfe14f62e48reed@google.com } 458a8d99307717c5fe02043969db0566c236a08c313reed@google.com if (SkShader::kRepeat_TileMode == tx && SkShader::kRepeat_TileMode == ty) { 4596bb92bc0b52d31f3ded38927cdefbeb13a3df87areed@google.com if (this->setupForTranslate()) { 4606bb92bc0b52d31f3ded38927cdefbeb13a3df87areed@google.com return Repeat_S32_D32_nofilter_trans_shaderproc; 4616bb92bc0b52d31f3ded38927cdefbeb13a3df87areed@google.com } 4626bb92bc0b52d31f3ded38927cdefbeb13a3df87areed@google.com return DoNothing_shaderproc; 463a8d99307717c5fe02043969db0566c236a08c313reed@google.com } 4649a4c746a1f0f91a5be2708a4c2018dfe14f62e48reed@google.com return NULL; 4659a4c746a1f0f91a5be2708a4c2018dfe14f62e48reed@google.com} 4669a4c746a1f0f91a5be2708a4c2018dfe14f62e48reed@google.com 4674c128c4917acf25c2cc5d1bd22282a4e1bb53d96reed@android.com/////////////////////////////////////////////////////////////////////////////// 4689fe287bd07baa6d9e890b627c102bba562954f7dreed@google.com 4699fe287bd07baa6d9e890b627c102bba562954f7dreed@google.com#ifdef SK_DEBUG 4709fe287bd07baa6d9e890b627c102bba562954f7dreed@google.com 4719fe287bd07baa6d9e890b627c102bba562954f7dreed@google.comstatic void check_scale_nofilter(uint32_t bitmapXY[], int count, 4729fe287bd07baa6d9e890b627c102bba562954f7dreed@google.com unsigned mx, unsigned my) { 4739fe287bd07baa6d9e890b627c102bba562954f7dreed@google.com unsigned y = *bitmapXY++; 4749fe287bd07baa6d9e890b627c102bba562954f7dreed@google.com SkASSERT(y < my); 475fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 4769fe287bd07baa6d9e890b627c102bba562954f7dreed@google.com const uint16_t* xptr = reinterpret_cast<const uint16_t*>(bitmapXY); 4779fe287bd07baa6d9e890b627c102bba562954f7dreed@google.com for (int i = 0; i < count; ++i) { 4789fe287bd07baa6d9e890b627c102bba562954f7dreed@google.com SkASSERT(xptr[i] < mx); 4799fe287bd07baa6d9e890b627c102bba562954f7dreed@google.com } 4809fe287bd07baa6d9e890b627c102bba562954f7dreed@google.com} 4819fe287bd07baa6d9e890b627c102bba562954f7dreed@google.com 4829fe287bd07baa6d9e890b627c102bba562954f7dreed@google.comstatic void check_scale_filter(uint32_t bitmapXY[], int count, 4839fe287bd07baa6d9e890b627c102bba562954f7dreed@google.com unsigned mx, unsigned my) { 4849fe287bd07baa6d9e890b627c102bba562954f7dreed@google.com uint32_t YY = *bitmapXY++; 4859fe287bd07baa6d9e890b627c102bba562954f7dreed@google.com unsigned y0 = YY >> 18; 486fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com unsigned y1 = YY & 0x3FFF; 4879fe287bd07baa6d9e890b627c102bba562954f7dreed@google.com SkASSERT(y0 < my); 4889fe287bd07baa6d9e890b627c102bba562954f7dreed@google.com SkASSERT(y1 < my); 489fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 4909fe287bd07baa6d9e890b627c102bba562954f7dreed@google.com for (int i = 0; i < count; ++i) { 4919fe287bd07baa6d9e890b627c102bba562954f7dreed@google.com uint32_t XX = bitmapXY[i]; 4929fe287bd07baa6d9e890b627c102bba562954f7dreed@google.com unsigned x0 = XX >> 18; 4939fe287bd07baa6d9e890b627c102bba562954f7dreed@google.com unsigned x1 = XX & 0x3FFF; 4949fe287bd07baa6d9e890b627c102bba562954f7dreed@google.com SkASSERT(x0 < mx); 4959fe287bd07baa6d9e890b627c102bba562954f7dreed@google.com SkASSERT(x1 < mx); 4969fe287bd07baa6d9e890b627c102bba562954f7dreed@google.com } 4979fe287bd07baa6d9e890b627c102bba562954f7dreed@google.com} 4989fe287bd07baa6d9e890b627c102bba562954f7dreed@google.com 4999fe287bd07baa6d9e890b627c102bba562954f7dreed@google.comstatic void check_affine_nofilter(uint32_t bitmapXY[], int count, 5009fe287bd07baa6d9e890b627c102bba562954f7dreed@google.com unsigned mx, unsigned my) { 5019fe287bd07baa6d9e890b627c102bba562954f7dreed@google.com for (int i = 0; i < count; ++i) { 5029fe287bd07baa6d9e890b627c102bba562954f7dreed@google.com uint32_t XY = bitmapXY[i]; 5039fe287bd07baa6d9e890b627c102bba562954f7dreed@google.com unsigned x = XY & 0xFFFF; 5049fe287bd07baa6d9e890b627c102bba562954f7dreed@google.com unsigned y = XY >> 16; 5059fe287bd07baa6d9e890b627c102bba562954f7dreed@google.com SkASSERT(x < mx); 5069fe287bd07baa6d9e890b627c102bba562954f7dreed@google.com SkASSERT(y < my); 5079fe287bd07baa6d9e890b627c102bba562954f7dreed@google.com } 5089fe287bd07baa6d9e890b627c102bba562954f7dreed@google.com} 5099fe287bd07baa6d9e890b627c102bba562954f7dreed@google.com 5109fe287bd07baa6d9e890b627c102bba562954f7dreed@google.comstatic void check_affine_filter(uint32_t bitmapXY[], int count, 5119fe287bd07baa6d9e890b627c102bba562954f7dreed@google.com unsigned mx, unsigned my) { 5129fe287bd07baa6d9e890b627c102bba562954f7dreed@google.com for (int i = 0; i < count; ++i) { 5139fe287bd07baa6d9e890b627c102bba562954f7dreed@google.com uint32_t YY = *bitmapXY++; 5149fe287bd07baa6d9e890b627c102bba562954f7dreed@google.com unsigned y0 = YY >> 18; 5159fe287bd07baa6d9e890b627c102bba562954f7dreed@google.com unsigned y1 = YY & 0x3FFF; 5169fe287bd07baa6d9e890b627c102bba562954f7dreed@google.com SkASSERT(y0 < my); 5179fe287bd07baa6d9e890b627c102bba562954f7dreed@google.com SkASSERT(y1 < my); 5189fe287bd07baa6d9e890b627c102bba562954f7dreed@google.com 5199fe287bd07baa6d9e890b627c102bba562954f7dreed@google.com uint32_t XX = *bitmapXY++; 5209fe287bd07baa6d9e890b627c102bba562954f7dreed@google.com unsigned x0 = XX >> 18; 5219fe287bd07baa6d9e890b627c102bba562954f7dreed@google.com unsigned x1 = XX & 0x3FFF; 5229fe287bd07baa6d9e890b627c102bba562954f7dreed@google.com SkASSERT(x0 < mx); 5239fe287bd07baa6d9e890b627c102bba562954f7dreed@google.com SkASSERT(x1 < mx); 5249fe287bd07baa6d9e890b627c102bba562954f7dreed@google.com } 5259fe287bd07baa6d9e890b627c102bba562954f7dreed@google.com} 5269fe287bd07baa6d9e890b627c102bba562954f7dreed@google.com 5279fe287bd07baa6d9e890b627c102bba562954f7dreed@google.comvoid SkBitmapProcState::DebugMatrixProc(const SkBitmapProcState& state, 5289fe287bd07baa6d9e890b627c102bba562954f7dreed@google.com uint32_t bitmapXY[], int count, 5299fe287bd07baa6d9e890b627c102bba562954f7dreed@google.com int x, int y) { 5309fe287bd07baa6d9e890b627c102bba562954f7dreed@google.com SkASSERT(bitmapXY); 5319fe287bd07baa6d9e890b627c102bba562954f7dreed@google.com SkASSERT(count > 0); 5329fe287bd07baa6d9e890b627c102bba562954f7dreed@google.com 5339fe287bd07baa6d9e890b627c102bba562954f7dreed@google.com state.fMatrixProc(state, bitmapXY, count, x, y); 5349fe287bd07baa6d9e890b627c102bba562954f7dreed@google.com 5359fe287bd07baa6d9e890b627c102bba562954f7dreed@google.com void (*proc)(uint32_t bitmapXY[], int count, unsigned mx, unsigned my); 5369fe287bd07baa6d9e890b627c102bba562954f7dreed@google.com 5379fe287bd07baa6d9e890b627c102bba562954f7dreed@google.com // There are four formats possible: 5389fe287bd07baa6d9e890b627c102bba562954f7dreed@google.com // scale -vs- affine 5399fe287bd07baa6d9e890b627c102bba562954f7dreed@google.com // filter -vs- nofilter 5409fe287bd07baa6d9e890b627c102bba562954f7dreed@google.com if (state.fInvType <= (SkMatrix::kTranslate_Mask | SkMatrix::kScale_Mask)) { 5419fe287bd07baa6d9e890b627c102bba562954f7dreed@google.com proc = state.fDoFilter ? check_scale_filter : check_scale_nofilter; 5429fe287bd07baa6d9e890b627c102bba562954f7dreed@google.com } else { 5439fe287bd07baa6d9e890b627c102bba562954f7dreed@google.com proc = state.fDoFilter ? check_affine_filter : check_affine_nofilter; 5449fe287bd07baa6d9e890b627c102bba562954f7dreed@google.com } 5459fe287bd07baa6d9e890b627c102bba562954f7dreed@google.com proc(bitmapXY, count, state.fBitmap->width(), state.fBitmap->height()); 5469fe287bd07baa6d9e890b627c102bba562954f7dreed@google.com} 5479fe287bd07baa6d9e890b627c102bba562954f7dreed@google.com 5489fe287bd07baa6d9e890b627c102bba562954f7dreed@google.comSkBitmapProcState::MatrixProc SkBitmapProcState::getMatrixProc() const { 5499fe287bd07baa6d9e890b627c102bba562954f7dreed@google.com return DebugMatrixProc; 5509fe287bd07baa6d9e890b627c102bba562954f7dreed@google.com} 5519fe287bd07baa6d9e890b627c102bba562954f7dreed@google.com 5529fe287bd07baa6d9e890b627c102bba562954f7dreed@google.com#endif 5539fe287bd07baa6d9e890b627c102bba562954f7dreed@google.com 5549fe287bd07baa6d9e890b627c102bba562954f7dreed@google.com/////////////////////////////////////////////////////////////////////////////// 5554c128c4917acf25c2cc5d1bd22282a4e1bb53d96reed@android.com/* 5564c128c4917acf25c2cc5d1bd22282a4e1bb53d96reed@android.com The storage requirements for the different matrix procs are as follows, 5574c128c4917acf25c2cc5d1bd22282a4e1bb53d96reed@android.com where each X or Y is 2 bytes, and N is the number of pixels/elements: 558fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 5594c128c4917acf25c2cc5d1bd22282a4e1bb53d96reed@android.com scale/translate nofilter Y(4bytes) + N * X 5604c128c4917acf25c2cc5d1bd22282a4e1bb53d96reed@android.com affine/perspective nofilter N * (X Y) 5614c128c4917acf25c2cc5d1bd22282a4e1bb53d96reed@android.com scale/translate filter Y Y + N * (X X) 5624c128c4917acf25c2cc5d1bd22282a4e1bb53d96reed@android.com affine/perspective filter N * (Y Y X X) 5634c128c4917acf25c2cc5d1bd22282a4e1bb53d96reed@android.com */ 5644c128c4917acf25c2cc5d1bd22282a4e1bb53d96reed@android.comint SkBitmapProcState::maxCountForBufferSize(size_t bufferSize) const { 5654c128c4917acf25c2cc5d1bd22282a4e1bb53d96reed@android.com int32_t size = static_cast<int32_t>(bufferSize); 5664c128c4917acf25c2cc5d1bd22282a4e1bb53d96reed@android.com 5674c128c4917acf25c2cc5d1bd22282a4e1bb53d96reed@android.com size &= ~3; // only care about 4-byte aligned chunks 5684c128c4917acf25c2cc5d1bd22282a4e1bb53d96reed@android.com if (fInvType <= (SkMatrix::kTranslate_Mask | SkMatrix::kScale_Mask)) { 5694c128c4917acf25c2cc5d1bd22282a4e1bb53d96reed@android.com size -= 4; // the shared Y (or YY) coordinate 5704c128c4917acf25c2cc5d1bd22282a4e1bb53d96reed@android.com if (size < 0) { 5714c128c4917acf25c2cc5d1bd22282a4e1bb53d96reed@android.com size = 0; 5724c128c4917acf25c2cc5d1bd22282a4e1bb53d96reed@android.com } 573258cb228c636282a3e4f4ce87b1017498e207f33reed@android.com size >>= 1; 5744c128c4917acf25c2cc5d1bd22282a4e1bb53d96reed@android.com } else { 575258cb228c636282a3e4f4ce87b1017498e207f33reed@android.com size >>= 2; 5764c128c4917acf25c2cc5d1bd22282a4e1bb53d96reed@android.com } 5774c128c4917acf25c2cc5d1bd22282a4e1bb53d96reed@android.com 578258cb228c636282a3e4f4ce87b1017498e207f33reed@android.com if (fDoFilter) { 579258cb228c636282a3e4f4ce87b1017498e207f33reed@android.com size >>= 1; 580258cb228c636282a3e4f4ce87b1017498e207f33reed@android.com } 581258cb228c636282a3e4f4ce87b1017498e207f33reed@android.com 582258cb228c636282a3e4f4ce87b1017498e207f33reed@android.com return size; 5834c128c4917acf25c2cc5d1bd22282a4e1bb53d96reed@android.com} 5844c128c4917acf25c2cc5d1bd22282a4e1bb53d96reed@android.com 585