SkBitmapProcState.cpp revision d94697c21ae479df4190a1afbf08d85ce244a4ef
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" 14138ebc3e4061cf533ea2f7f3717239670fdc6e43humper@google.com#include "SkBitmapScaler.h" 15d94697c21ae479df4190a1afbf08d85ce244a4efreed@google.com#include "SkMipMap.h" 16602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com#include "SkScaledImageCache.h" 173ada0efdc8de8316df8113ec54ffd1a3f33ecd21digit@google.com 183ada0efdc8de8316df8113ec54ffd1a3f33ecd21digit@google.com#if !SK_ARM_NEON_IS_NONE 193ada0efdc8de8316df8113ec54ffd1a3f33ecd21digit@google.com// These are defined in src/opts/SkBitmapProcState_arm_neon.cpp 203ada0efdc8de8316df8113ec54ffd1a3f33ecd21digit@google.comextern const SkBitmapProcState::SampleProc16 gSkBitmapProcStateSample16_neon[]; 213ada0efdc8de8316df8113ec54ffd1a3f33ecd21digit@google.comextern const SkBitmapProcState::SampleProc32 gSkBitmapProcStateSample32_neon[]; 223ada0efdc8de8316df8113ec54ffd1a3f33ecd21digit@google.comextern void S16_D16_filter_DX_neon(const SkBitmapProcState&, const uint32_t*, int, uint16_t*); 233ada0efdc8de8316df8113ec54ffd1a3f33ecd21digit@google.comextern void Clamp_S16_D16_filter_DX_shaderproc_neon(const SkBitmapProcState&, int, int, uint16_t*, int); 243ada0efdc8de8316df8113ec54ffd1a3f33ecd21digit@google.comextern void Repeat_S16_D16_filter_DX_shaderproc_neon(const SkBitmapProcState&, int, int, uint16_t*, int); 253ada0efdc8de8316df8113ec54ffd1a3f33ecd21digit@google.comextern void SI8_opaque_D32_filter_DX_neon(const SkBitmapProcState&, const uint32_t*, int, SkPMColor*); 263ada0efdc8de8316df8113ec54ffd1a3f33ecd21digit@google.comextern void SI8_opaque_D32_filter_DX_shaderproc_neon(const SkBitmapProcState&, int, int, uint32_t*, int); 273ada0efdc8de8316df8113ec54ffd1a3f33ecd21digit@google.comextern void Clamp_SI8_opaque_D32_filter_DX_shaderproc_neon(const SkBitmapProcState&, int, int, uint32_t*, int); 283ada0efdc8de8316df8113ec54ffd1a3f33ecd21digit@google.com#endif 293ada0efdc8de8316df8113ec54ffd1a3f33ecd21digit@google.com 303ada0efdc8de8316df8113ec54ffd1a3f33ecd21digit@google.com#define NAME_WRAP(x) x 313ada0efdc8de8316df8113ec54ffd1a3f33ecd21digit@google.com#include "SkBitmapProcState_filter.h" 323ada0efdc8de8316df8113ec54ffd1a3f33ecd21digit@google.com#include "SkBitmapProcState_procs.h" 33b577b41c8ec26c21ae599e80a2707d42f03eaa60reed@android.com 34a44b4cc7976b06caf3a3f6b7913c2af92eb32217reed@android.com/////////////////////////////////////////////////////////////////////////////// 35a44b4cc7976b06caf3a3f6b7913c2af92eb32217reed@android.com 36ee056a82ae59373cae01ebbb4edcd3297d7c92cereed@google.com// true iff the matrix contains, at most, scale and translate elements 37ee056a82ae59373cae01ebbb4edcd3297d7c92cereed@google.comstatic bool matrix_only_scale_translate(const SkMatrix& m) { 38ee056a82ae59373cae01ebbb4edcd3297d7c92cereed@google.com return m.getType() <= (SkMatrix::kScale_Mask | SkMatrix::kTranslate_Mask); 39ee056a82ae59373cae01ebbb4edcd3297d7c92cereed@google.com} 40ee056a82ae59373cae01ebbb4edcd3297d7c92cereed@google.com 41c0e88e0d5d1260f81e7f6b66eeabfb25e6b95a4dreed@google.com/** 42c0e88e0d5d1260f81e7f6b66eeabfb25e6b95a4dreed@google.com * For the purposes of drawing bitmaps, if a matrix is "almost" translate 43c0e88e0d5d1260f81e7f6b66eeabfb25e6b95a4dreed@google.com * go ahead and treat it as if it were, so that subsequent code can go fast. 44c0e88e0d5d1260f81e7f6b66eeabfb25e6b95a4dreed@google.com */ 45c0e88e0d5d1260f81e7f6b66eeabfb25e6b95a4dreed@google.comstatic bool just_trans_clamp(const SkMatrix& matrix, const SkBitmap& bitmap) { 46ee056a82ae59373cae01ebbb4edcd3297d7c92cereed@google.com SkASSERT(matrix_only_scale_translate(matrix)); 47ee056a82ae59373cae01ebbb4edcd3297d7c92cereed@google.com 48ee056a82ae59373cae01ebbb4edcd3297d7c92cereed@google.com if (matrix.getType() & SkMatrix::kScale_Mask) { 49ee056a82ae59373cae01ebbb4edcd3297d7c92cereed@google.com SkRect src, dst; 50ee056a82ae59373cae01ebbb4edcd3297d7c92cereed@google.com bitmap.getBounds(&src); 51f707adc4f8b22fd1a59a900b64333480de653c5breed@google.com 52f707adc4f8b22fd1a59a900b64333480de653c5breed@google.com // Can't call mapRect(), since that will fix up inverted rectangles, 53f707adc4f8b22fd1a59a900b64333480de653c5breed@google.com // e.g. when scale is negative, and we don't want to return true for 54f707adc4f8b22fd1a59a900b64333480de653c5breed@google.com // those. 55f707adc4f8b22fd1a59a900b64333480de653c5breed@google.com matrix.mapPoints(SkTCast<SkPoint*>(&dst), 56f707adc4f8b22fd1a59a900b64333480de653c5breed@google.com SkTCast<const SkPoint*>(&src), 57f707adc4f8b22fd1a59a900b64333480de653c5breed@google.com 2); 58ee056a82ae59373cae01ebbb4edcd3297d7c92cereed@google.com 59ee056a82ae59373cae01ebbb4edcd3297d7c92cereed@google.com // Now round all 4 edges to device space, and then compare the device 60ee056a82ae59373cae01ebbb4edcd3297d7c92cereed@google.com // width/height to the original. Note: we must map all 4 and subtract 61ee056a82ae59373cae01ebbb4edcd3297d7c92cereed@google.com // rather than map the "width" and compare, since we care about the 62ee056a82ae59373cae01ebbb4edcd3297d7c92cereed@google.com // phase (in pixel space) that any translate in the matrix might impart. 63ee056a82ae59373cae01ebbb4edcd3297d7c92cereed@google.com SkIRect idst; 64ee056a82ae59373cae01ebbb4edcd3297d7c92cereed@google.com dst.round(&idst); 65ee056a82ae59373cae01ebbb4edcd3297d7c92cereed@google.com return idst.width() == bitmap.width() && idst.height() == bitmap.height(); 66c0e88e0d5d1260f81e7f6b66eeabfb25e6b95a4dreed@google.com } 67c0e88e0d5d1260f81e7f6b66eeabfb25e6b95a4dreed@google.com // if we got here, we're either kTranslate_Mask or identity 68c0e88e0d5d1260f81e7f6b66eeabfb25e6b95a4dreed@google.com return true; 69c0e88e0d5d1260f81e7f6b66eeabfb25e6b95a4dreed@google.com} 70c0e88e0d5d1260f81e7f6b66eeabfb25e6b95a4dreed@google.com 71c0e88e0d5d1260f81e7f6b66eeabfb25e6b95a4dreed@google.comstatic bool just_trans_general(const SkMatrix& matrix) { 72ee056a82ae59373cae01ebbb4edcd3297d7c92cereed@google.com SkASSERT(matrix_only_scale_translate(matrix)); 73c0e88e0d5d1260f81e7f6b66eeabfb25e6b95a4dreed@google.com 74ee056a82ae59373cae01ebbb4edcd3297d7c92cereed@google.com if (matrix.getType() & SkMatrix::kScale_Mask) { 75c0e88e0d5d1260f81e7f6b66eeabfb25e6b95a4dreed@google.com const SkScalar tol = SK_Scalar1 / 32768; 76989a95ea77230e8347da18876e1bd5f39a78ebb5skia.committer@gmail.com 77c0e88e0d5d1260f81e7f6b66eeabfb25e6b95a4dreed@google.com if (!SkScalarNearlyZero(matrix[SkMatrix::kMScaleX] - SK_Scalar1, tol)) { 78c0e88e0d5d1260f81e7f6b66eeabfb25e6b95a4dreed@google.com return false; 79c0e88e0d5d1260f81e7f6b66eeabfb25e6b95a4dreed@google.com } 80c0e88e0d5d1260f81e7f6b66eeabfb25e6b95a4dreed@google.com if (!SkScalarNearlyZero(matrix[SkMatrix::kMScaleY] - SK_Scalar1, tol)) { 81c0e88e0d5d1260f81e7f6b66eeabfb25e6b95a4dreed@google.com return false; 82c0e88e0d5d1260f81e7f6b66eeabfb25e6b95a4dreed@google.com } 83c0e88e0d5d1260f81e7f6b66eeabfb25e6b95a4dreed@google.com } 84c0e88e0d5d1260f81e7f6b66eeabfb25e6b95a4dreed@google.com // if we got here, treat us as either kTranslate_Mask or identity 85c0e88e0d5d1260f81e7f6b66eeabfb25e6b95a4dreed@google.com return true; 86c0e88e0d5d1260f81e7f6b66eeabfb25e6b95a4dreed@google.com} 87c0e88e0d5d1260f81e7f6b66eeabfb25e6b95a4dreed@google.com 88c0e88e0d5d1260f81e7f6b66eeabfb25e6b95a4dreed@google.com/////////////////////////////////////////////////////////////////////////////// 89c0e88e0d5d1260f81e7f6b66eeabfb25e6b95a4dreed@google.com 908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic bool valid_for_filtering(unsigned dimension) { 918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // for filtering, width and height must fit in 14bits, since we use steal 928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // 2 bits from each to store our 4bit subpixel data 938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return (dimension & ~0x3FFF) == 0; 948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 96d94697c21ae479df4190a1afbf08d85ce244a4efreed@google.comstatic SkScalar effective_matrix_scale_sqrd(const SkMatrix& mat) { 979cfc83cc8ac2ee50a7ce889e65a707941f48bdeareed@google.com SkPoint v1, v2; 9858c856a54a75e703aa3c82a0cd4e1affd9bd8ffcrobertphillips@google.com 999cfc83cc8ac2ee50a7ce889e65a707941f48bdeareed@google.com v1.fX = mat.getScaleX(); 1009cfc83cc8ac2ee50a7ce889e65a707941f48bdeareed@google.com v1.fY = mat.getSkewY(); 10158c856a54a75e703aa3c82a0cd4e1affd9bd8ffcrobertphillips@google.com 1029cfc83cc8ac2ee50a7ce889e65a707941f48bdeareed@google.com v2.fX = mat.getSkewX(); 1039cfc83cc8ac2ee50a7ce889e65a707941f48bdeareed@google.com v2.fY = mat.getScaleY(); 10458c856a54a75e703aa3c82a0cd4e1affd9bd8ffcrobertphillips@google.com 1059cfc83cc8ac2ee50a7ce889e65a707941f48bdeareed@google.com return SkMaxScalar(v1.lengthSqd(), v2.lengthSqd()); 1069cfc83cc8ac2ee50a7ce889e65a707941f48bdeareed@google.com} 1079cfc83cc8ac2ee50a7ce889e65a707941f48bdeareed@google.com 1089c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com// TODO -- we may want to pass the clip into this function so we only scale 1099c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com// the portion of the image that we're going to need. This will complicate 1109c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com// the interface to the cache, but might be well worth it. 1119c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com 1129c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.comvoid SkBitmapProcState::possiblyScaleImage() { 1139c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com 1149cfc83cc8ac2ee50a7ce889e65a707941f48bdeareed@google.com if (fFilterLevel <= SkPaint::kLow_FilterLevel) { 1159cfc83cc8ac2ee50a7ce889e65a707941f48bdeareed@google.com // none or low (bilerp) does not need to look any further 1169c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com return; 1179c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com } 1181f3c73825b8a1752abc6b74fbce978a430de6473skia.committer@gmail.com 119138ebc3e4061cf533ea2f7f3717239670fdc6e43humper@google.com // see if our platform has any specialized convolution code. 1201f3c73825b8a1752abc6b74fbce978a430de6473skia.committer@gmail.com 1211f3c73825b8a1752abc6b74fbce978a430de6473skia.committer@gmail.com 122138ebc3e4061cf533ea2f7f3717239670fdc6e43humper@google.com // Set up a pointer to a local (instead of storing the structure in the 1231f3c73825b8a1752abc6b74fbce978a430de6473skia.committer@gmail.com // proc state) to avoid introducing a header dependency; this makes 124138ebc3e4061cf533ea2f7f3717239670fdc6e43humper@google.com // recompiles a lot less painful. 1251f3c73825b8a1752abc6b74fbce978a430de6473skia.committer@gmail.com 126138ebc3e4061cf533ea2f7f3717239670fdc6e43humper@google.com SkConvolutionProcs simd; 127138ebc3e4061cf533ea2f7f3717239670fdc6e43humper@google.com fConvolutionProcs = &simd; 1281f3c73825b8a1752abc6b74fbce978a430de6473skia.committer@gmail.com 129138ebc3e4061cf533ea2f7f3717239670fdc6e43humper@google.com fConvolutionProcs->fExtraHorizontalReads = 0; 130138ebc3e4061cf533ea2f7f3717239670fdc6e43humper@google.com fConvolutionProcs->fConvolveVertically = NULL; 131138ebc3e4061cf533ea2f7f3717239670fdc6e43humper@google.com fConvolutionProcs->fConvolve4RowsHorizontally = NULL; 132138ebc3e4061cf533ea2f7f3717239670fdc6e43humper@google.com fConvolutionProcs->fConvolveHorizontally = NULL; 133138ebc3e4061cf533ea2f7f3717239670fdc6e43humper@google.com fConvolutionProcs->fApplySIMDPadding = NULL; 1341f3c73825b8a1752abc6b74fbce978a430de6473skia.committer@gmail.com 135138ebc3e4061cf533ea2f7f3717239670fdc6e43humper@google.com this->platformConvolutionProcs(); 136138ebc3e4061cf533ea2f7f3717239670fdc6e43humper@google.com 137138ebc3e4061cf533ea2f7f3717239670fdc6e43humper@google.com // STEP 1: Highest quality direct scale? 138138ebc3e4061cf533ea2f7f3717239670fdc6e43humper@google.com 1391f3c73825b8a1752abc6b74fbce978a430de6473skia.committer@gmail.com // Check to see if the transformation matrix is simple, and if we're 1401f3c73825b8a1752abc6b74fbce978a430de6473skia.committer@gmail.com // doing high quality scaling. If so, do the bitmap scale here and 141138ebc3e4061cf533ea2f7f3717239670fdc6e43humper@google.com // remove the scaling component from the matrix. 142138ebc3e4061cf533ea2f7f3717239670fdc6e43humper@google.com 1439cfc83cc8ac2ee50a7ce889e65a707941f48bdeareed@google.com if (SkPaint::kHigh_FilterLevel == fFilterLevel && 144138ebc3e4061cf533ea2f7f3717239670fdc6e43humper@google.com fInvMatrix.getType() <= (SkMatrix::kScale_Mask | SkMatrix::kTranslate_Mask) && 1459c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com fOrigBitmap.config() == SkBitmap::kARGB_8888_Config) { 1461f3c73825b8a1752abc6b74fbce978a430de6473skia.committer@gmail.com 147602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com SkScalar invScaleX = fInvMatrix.getScaleX(); 148602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com SkScalar invScaleY = fInvMatrix.getScaleY(); 1497f1af501f206da48a7ff791af53432c9c1c89d08skia.committer@gmail.com 150602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com SkASSERT(NULL == fScaledCacheID); 151602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com fScaledCacheID = SkScaledImageCache::FindAndLock(fOrigBitmap, 152602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com invScaleX, invScaleY, 153602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com &fScaledBitmap); 154602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com if (NULL == fScaledCacheID) { 155602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com int dest_width = SkScalarCeilToInt(fOrigBitmap.width() / invScaleX); 156602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com int dest_height = SkScalarCeilToInt(fOrigBitmap.height() / invScaleY); 157602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com 158602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com // All the criteria are met; let's make a new bitmap. 159602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com 160602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com fScaledBitmap = SkBitmapScaler::Resize(fOrigBitmap, 161602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com SkBitmapScaler::RESIZE_BEST, 162602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com dest_width, 163602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com dest_height, 164602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com fConvolutionProcs); 165602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com fScaledCacheID = SkScaledImageCache::AddAndLock(fOrigBitmap, 166602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com invScaleX, 167602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com invScaleY, 168602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com fScaledBitmap); 169602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com } 170138ebc3e4061cf533ea2f7f3717239670fdc6e43humper@google.com fScaledBitmap.lockPixels(); 1711f3c73825b8a1752abc6b74fbce978a430de6473skia.committer@gmail.com 1729c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com fBitmap = &fScaledBitmap; 1739c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com 1749c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com // set the inv matrix type to translate-only; 1759c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com 1769c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com fInvMatrix.setTranslate( 1/fInvMatrix.getScaleX() * fInvMatrix.getTranslateX(), 1779c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com 1/fInvMatrix.getScaleY() * fInvMatrix.getTranslateY() ); 1789c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com 1799c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com // no need for any further filtering; we just did it! 1809c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com 1819cfc83cc8ac2ee50a7ce889e65a707941f48bdeareed@google.com fFilterLevel = SkPaint::kNone_FilterLevel; 1829c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com 1839c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com return; 1849c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com } 1859c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com 1869cfc83cc8ac2ee50a7ce889e65a707941f48bdeareed@google.com /* 1879cfc83cc8ac2ee50a7ce889e65a707941f48bdeareed@google.com * If we get here, the caller has requested either Med or High filter-level 1889cfc83cc8ac2ee50a7ce889e65a707941f48bdeareed@google.com * 1899cfc83cc8ac2ee50a7ce889e65a707941f48bdeareed@google.com * If High, then our special-case for scale-only did not take, and so we 1909cfc83cc8ac2ee50a7ce889e65a707941f48bdeareed@google.com * have to make a choice: 1919cfc83cc8ac2ee50a7ce889e65a707941f48bdeareed@google.com * 1. fall back on mipmaps + bilerp 1929cfc83cc8ac2ee50a7ce889e65a707941f48bdeareed@google.com * 2. fall back on scanline bicubic filter 1939cfc83cc8ac2ee50a7ce889e65a707941f48bdeareed@google.com * For now, we compute the "scale" value from the matrix, and have a 1949cfc83cc8ac2ee50a7ce889e65a707941f48bdeareed@google.com * threshold to decide when bicubic is better, and when mips are better. 1959cfc83cc8ac2ee50a7ce889e65a707941f48bdeareed@google.com * No doubt a fancier decision tree could be used uere. 1969cfc83cc8ac2ee50a7ce889e65a707941f48bdeareed@google.com * 1979cfc83cc8ac2ee50a7ce889e65a707941f48bdeareed@google.com * If Medium, then we just try to build a mipmap and select a level, 1989cfc83cc8ac2ee50a7ce889e65a707941f48bdeareed@google.com * setting the filter-level to kLow to signal that we just need bilerp 1999cfc83cc8ac2ee50a7ce889e65a707941f48bdeareed@google.com * to process the selected level. 2009cfc83cc8ac2ee50a7ce889e65a707941f48bdeareed@google.com */ 2019c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com 2029cfc83cc8ac2ee50a7ce889e65a707941f48bdeareed@google.com SkScalar scaleSqd = effective_matrix_scale_sqrd(fInvMatrix); 2039cfc83cc8ac2ee50a7ce889e65a707941f48bdeareed@google.com 2049cfc83cc8ac2ee50a7ce889e65a707941f48bdeareed@google.com if (SkPaint::kHigh_FilterLevel == fFilterLevel) { 2059cfc83cc8ac2ee50a7ce889e65a707941f48bdeareed@google.com // Set the limit at 0.25 for the CTM... if the CTM is scaling smaller 2069cfc83cc8ac2ee50a7ce889e65a707941f48bdeareed@google.com // than this, then the mipmaps quality may be greater (certainly faster) 2079cfc83cc8ac2ee50a7ce889e65a707941f48bdeareed@google.com // so we only keep High quality if the scale is greater than this. 2089cfc83cc8ac2ee50a7ce889e65a707941f48bdeareed@google.com // 2099cfc83cc8ac2ee50a7ce889e65a707941f48bdeareed@google.com // Since we're dealing with the inverse, we compare against its inverse. 2109cfc83cc8ac2ee50a7ce889e65a707941f48bdeareed@google.com const SkScalar bicubicLimit = SkFloatToScalar(4.0f); 2119cfc83cc8ac2ee50a7ce889e65a707941f48bdeareed@google.com const SkScalar bicubicLimitSqd = bicubicLimit * bicubicLimit; 2129cfc83cc8ac2ee50a7ce889e65a707941f48bdeareed@google.com if (scaleSqd < bicubicLimitSqd) { // use bicubic scanline 2139cfc83cc8ac2ee50a7ce889e65a707941f48bdeareed@google.com return; 2149cfc83cc8ac2ee50a7ce889e65a707941f48bdeareed@google.com } 2159c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com 2169cfc83cc8ac2ee50a7ce889e65a707941f48bdeareed@google.com // else set the filter-level to Medium, since we're scaling down and 2179cfc83cc8ac2ee50a7ce889e65a707941f48bdeareed@google.com // want to reqeust mipmaps 2189cfc83cc8ac2ee50a7ce889e65a707941f48bdeareed@google.com fFilterLevel = SkPaint::kMedium_FilterLevel; 2199cfc83cc8ac2ee50a7ce889e65a707941f48bdeareed@google.com } 22058c856a54a75e703aa3c82a0cd4e1affd9bd8ffcrobertphillips@google.com 2219cfc83cc8ac2ee50a7ce889e65a707941f48bdeareed@google.com SkASSERT(SkPaint::kMedium_FilterLevel == fFilterLevel); 2229c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com 2239cfc83cc8ac2ee50a7ce889e65a707941f48bdeareed@google.com /** 2249cfc83cc8ac2ee50a7ce889e65a707941f48bdeareed@google.com * Medium quality means use a mipmap for down-scaling, and just bilper 2259cfc83cc8ac2ee50a7ce889e65a707941f48bdeareed@google.com * for upscaling. Since we're examining the inverse matrix, we look for 2269cfc83cc8ac2ee50a7ce889e65a707941f48bdeareed@google.com * a scale > 1 to indicate down scaling by the CTM. 2279cfc83cc8ac2ee50a7ce889e65a707941f48bdeareed@google.com */ 2289cfc83cc8ac2ee50a7ce889e65a707941f48bdeareed@google.com if (scaleSqd > SK_Scalar1) { 229d94697c21ae479df4190a1afbf08d85ce244a4efreed@google.com const SkMipMap* mip = NULL; 230d94697c21ae479df4190a1afbf08d85ce244a4efreed@google.com 231d94697c21ae479df4190a1afbf08d85ce244a4efreed@google.com SkASSERT(NULL == fScaledCacheID); 232d94697c21ae479df4190a1afbf08d85ce244a4efreed@google.com fScaledCacheID = SkScaledImageCache::FindAndLockMip(fOrigBitmap, &mip); 233d94697c21ae479df4190a1afbf08d85ce244a4efreed@google.com if (!fScaledCacheID) { 234d94697c21ae479df4190a1afbf08d85ce244a4efreed@google.com SkASSERT(NULL == mip); 235d94697c21ae479df4190a1afbf08d85ce244a4efreed@google.com mip = SkMipMap::Build(fOrigBitmap); 236d94697c21ae479df4190a1afbf08d85ce244a4efreed@google.com if (mip) { 237d94697c21ae479df4190a1afbf08d85ce244a4efreed@google.com fScaledCacheID = SkScaledImageCache::AddAndLockMip(fOrigBitmap, 238d94697c21ae479df4190a1afbf08d85ce244a4efreed@google.com mip); 239d94697c21ae479df4190a1afbf08d85ce244a4efreed@google.com mip->unref(); // the cache took a ref 240d94697c21ae479df4190a1afbf08d85ce244a4efreed@google.com SkASSERT(fScaledCacheID); 241d94697c21ae479df4190a1afbf08d85ce244a4efreed@google.com } 242d94697c21ae479df4190a1afbf08d85ce244a4efreed@google.com } else { 243d94697c21ae479df4190a1afbf08d85ce244a4efreed@google.com SkASSERT(mip); 2449c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com } 245d94697c21ae479df4190a1afbf08d85ce244a4efreed@google.com 246d94697c21ae479df4190a1afbf08d85ce244a4efreed@google.com if (mip) { 247d94697c21ae479df4190a1afbf08d85ce244a4efreed@google.com SkScalar levelScale = SkScalarInvert(SkScalarSqrt(scaleSqd)); 248d94697c21ae479df4190a1afbf08d85ce244a4efreed@google.com SkMipMap::Level level; 249d94697c21ae479df4190a1afbf08d85ce244a4efreed@google.com if (mip->extractLevel(levelScale, &level)) { 250d94697c21ae479df4190a1afbf08d85ce244a4efreed@google.com SkScalar invScaleFixup = level.fScale; 251d94697c21ae479df4190a1afbf08d85ce244a4efreed@google.com fInvMatrix.postScale(invScaleFixup, invScaleFixup); 252d94697c21ae479df4190a1afbf08d85ce244a4efreed@google.com 253d94697c21ae479df4190a1afbf08d85ce244a4efreed@google.com fScaledBitmap.setConfig(fOrigBitmap.config(), 254d94697c21ae479df4190a1afbf08d85ce244a4efreed@google.com level.fWidth, level.fHeight, 255d94697c21ae479df4190a1afbf08d85ce244a4efreed@google.com level.fRowBytes); 256d94697c21ae479df4190a1afbf08d85ce244a4efreed@google.com fScaledBitmap.setPixels(level.fPixels); 2579cfc83cc8ac2ee50a7ce889e65a707941f48bdeareed@google.com fBitmap = &fScaledBitmap; 2589cfc83cc8ac2ee50a7ce889e65a707941f48bdeareed@google.com } 2599c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com } 2609c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com } 2619cfc83cc8ac2ee50a7ce889e65a707941f48bdeareed@google.com 262d94697c21ae479df4190a1afbf08d85ce244a4efreed@google.com /* 263d94697c21ae479df4190a1afbf08d85ce244a4efreed@google.com * At this point, we may or may not have built a mipmap. Regardless, we 264d94697c21ae479df4190a1afbf08d85ce244a4efreed@google.com * now fall back on Low so will bilerp whatever fBitmap now points at. 265d94697c21ae479df4190a1afbf08d85ce244a4efreed@google.com */ 2669cfc83cc8ac2ee50a7ce889e65a707941f48bdeareed@google.com fFilterLevel = SkPaint::kLow_FilterLevel; 2679c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com} 2689c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com 2699c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.comvoid SkBitmapProcState::endContext() { 2709c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com SkDELETE(fBitmapFilter); 2719c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com fBitmapFilter = NULL; 2729c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com fScaledBitmap.reset(); 2737f1af501f206da48a7ff791af53432c9c1c89d08skia.committer@gmail.com 274602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com if (fScaledCacheID) { 275602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com SkScaledImageCache::Unlock(fScaledCacheID); 276602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com fScaledCacheID = NULL; 277602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com } 2789c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com} 2799c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com 2808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.combool SkBitmapProcState::chooseProcs(const SkMatrix& inv, const SkPaint& paint) { 2818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (fOrigBitmap.width() == 0 || fOrigBitmap.height() == 0) { 2828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return false; 2838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 28407d1f008b365e94ef7c7347be19a03d00bd36805reed@android.com 2859c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com bool trivialMatrix = (inv.getType() & ~SkMatrix::kTranslate_Mask) == 0; 2869c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com bool clampClamp = SkShader::kClamp_TileMode == fTileModeX && 2878b8bf4d12ecf8fb340a1362c91a8a57395dd31a3robertphillips@google.com SkShader::kClamp_TileMode == fTileModeY; 288a44b4cc7976b06caf3a3f6b7913c2af92eb32217reed@android.com 2899c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com fInvMatrix = inv; 2909c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com if (!(clampClamp || trivialMatrix)) { 2919c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com fInvMatrix.postIDiv(fOrigBitmap.width(), fOrigBitmap.height()); 2928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 29307d1f008b365e94ef7c7347be19a03d00bd36805reed@android.com 2948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fBitmap = &fOrigBitmap; 295fa1bd5f86ceea6cfa8303594730125ad2853d87bskia.committer@gmail.com 2969c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com // initialize our filter quality to the one requested by the caller. 2979c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com // We may downgrade it later if we determine that we either don't need 2989c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com // or can't provide as high a quality filtering as the user requested. 299fa1bd5f86ceea6cfa8303594730125ad2853d87bskia.committer@gmail.com 3009cfc83cc8ac2ee50a7ce889e65a707941f48bdeareed@google.com fFilterLevel = paint.getFilterLevel(); 3018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 3029c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com#ifndef SK_IGNORE_IMAGE_PRESCALE 3039c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com // possiblyScaleImage will look to see if it can rescale the image as a 3049c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com // preprocess; either by scaling up to the target size, or by selecting 3059c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com // a nearby mipmap level. If it does, it will adjust the working 3069c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com // matrix as well as the working bitmap. It may also adjust the filter 3079c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com // quality to avoid re-filtering an already perfectly scaled image. 3089c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com 3099c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com this->possiblyScaleImage(); 3109c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com#endif 3119c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com 3129c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com // Now that all possible changes to the matrix have taken place, check 3139c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com // to see if we're really close to a no-scale matrix. If so, explicitly 3149c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com // set it to be so. Subsequent code may inspect this matrix to choose 3159c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com // a faster path in this case. 3169c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com 3179c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com // This code will only execute if the matrix has some scale component; 3189c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com // if it's already pure translate then we won't do this inversion. 3199c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com 3209c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com if (matrix_only_scale_translate(fInvMatrix)) { 321ee056a82ae59373cae01ebbb4edcd3297d7c92cereed@google.com SkMatrix forward; 3229c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com if (fInvMatrix.invert(&forward)) { 3239c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com if (clampClamp ? just_trans_clamp(forward, *fBitmap) 324ee056a82ae59373cae01ebbb4edcd3297d7c92cereed@google.com : just_trans_general(forward)) { 325ce1f3cc1e22a50caaaaded7b91d9492b3ae5901creed@google.com SkScalar tx = -SkScalarRoundToScalar(forward.getTranslateX()); 326ce1f3cc1e22a50caaaaded7b91d9492b3ae5901creed@google.com SkScalar ty = -SkScalarRoundToScalar(forward.getTranslateY()); 3279c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com fInvMatrix.setTranslate(tx, ty); 3289c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com 329ce1f3cc1e22a50caaaaded7b91d9492b3ae5901creed@google.com } 330c0e88e0d5d1260f81e7f6b66eeabfb25e6b95a4dreed@google.com } 331c0e88e0d5d1260f81e7f6b66eeabfb25e6b95a4dreed@google.com } 332c0e88e0d5d1260f81e7f6b66eeabfb25e6b95a4dreed@google.com 3339c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com fInvProc = fInvMatrix.getMapXYProc(); 3349c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com fInvType = fInvMatrix.getType(); 3359c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com fInvSx = SkScalarToFixed(fInvMatrix.getScaleX()); 3369c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com fInvSxFractionalInt = SkScalarToFractionalInt(fInvMatrix.getScaleX()); 3379c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com fInvKy = SkScalarToFixed(fInvMatrix.getSkewY()); 3389c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com fInvKyFractionalInt = SkScalarToFractionalInt(fInvMatrix.getSkewY()); 3398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 3408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fAlphaScale = SkAlpha255To256(paint.getAlpha()); 341fa1bd5f86ceea6cfa8303594730125ad2853d87bskia.committer@gmail.com 3427a99eb1c63d4327d352af09ea59f039f014e4028reed@android.com fShaderProc32 = NULL; 3437a99eb1c63d4327d352af09ea59f039f014e4028reed@android.com fShaderProc16 = NULL; 3447a99eb1c63d4327d352af09ea59f039f014e4028reed@android.com fSampleProc32 = NULL; 3457a99eb1c63d4327d352af09ea59f039f014e4028reed@android.com fSampleProc16 = NULL; 346fa1bd5f86ceea6cfa8303594730125ad2853d87bskia.committer@gmail.com 3479c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com // recompute the triviality of the matrix here because we may have 3489c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com // changed it! 3499c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com 3509c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com trivialMatrix = (fInvMatrix.getType() & ~SkMatrix::kTranslate_Mask) == 0; 3519c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com 3529cfc83cc8ac2ee50a7ce889e65a707941f48bdeareed@google.com if (SkPaint::kHigh_FilterLevel == fFilterLevel) { 3539c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com // If this is still set, that means we wanted HQ sampling 3549c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com // but couldn't do it as a preprocess. Let's try to install 3559c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com // the scanline version of the HQ sampler. If that process fails, 3569c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com // downgrade to bilerp. 3579c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com 3589c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com // NOTE: Might need to be careful here in the future when we want 3599c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com // to have the platform proc have a shot at this; it's possible that 3609c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com // the chooseBitmapFilterProc will fail to install a shader but a 3619c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com // platform-specific one might succeed, so it might be premature here 3629c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com // to fall back to bilerp. This needs thought. 3639c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com 3649c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com SkASSERT(fInvType > SkMatrix::kTranslate_Mask); 3659c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com 3669c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com fShaderProc32 = this->chooseBitmapFilterProc(); 3679c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com if (!fShaderProc32) { 3689cfc83cc8ac2ee50a7ce889e65a707941f48bdeareed@google.com fFilterLevel = SkPaint::kLow_FilterLevel; 3699c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com } 3709c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com } 3719c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com 3729cfc83cc8ac2ee50a7ce889e65a707941f48bdeareed@google.com if (SkPaint::kLow_FilterLevel == fFilterLevel) { 3739c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com // Only try bilerp if the matrix is "interesting" and 3749c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com // the image has a suitable size. 3759c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com 3769c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com if (fInvType <= SkMatrix::kTranslate_Mask || 3779cfc83cc8ac2ee50a7ce889e65a707941f48bdeareed@google.com !valid_for_filtering(fBitmap->width() | fBitmap->height())) { 3789cfc83cc8ac2ee50a7ce889e65a707941f48bdeareed@google.com fFilterLevel = SkPaint::kNone_FilterLevel; 3799c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com } 3809c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com } 3819c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com 3829c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com // At this point, we know exactly what kind of sampling the per-scanline 3839c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com // shader will perform. 3849c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com 3859c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com fMatrixProc = this->chooseMatrixProc(trivialMatrix); 3868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (NULL == fMatrixProc) { 3878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return false; 3888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 3898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 3908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com /////////////////////////////////////////////////////////////////////// 391fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 3929c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com // No need to do this if we're doing HQ sampling; if filter quality is 3939c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com // still set to HQ by the time we get here, then we must have installed 3949c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com // the shader proc above and can skip all this. 3958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 3969cfc83cc8ac2ee50a7ce889e65a707941f48bdeareed@google.com if (fFilterLevel < SkPaint::kHigh_FilterLevel) { 397fa1bd5f86ceea6cfa8303594730125ad2853d87bskia.committer@gmail.com 3989c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com int index = 0; 3999c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com if (fAlphaScale < 256) { // note: this distinction is not used for D16 4009c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com index |= 1; 4019c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com } 4029c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com if (fInvType <= (SkMatrix::kTranslate_Mask | SkMatrix::kScale_Mask)) { 4039c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com index |= 2; 4049c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com } 4059cfc83cc8ac2ee50a7ce889e65a707941f48bdeareed@google.com if (fFilterLevel > SkPaint::kNone_FilterLevel) { 4069c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com index |= 4; 4079c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com } 4089c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com // bits 3,4,5 encoding the source bitmap format 4099c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com switch (fBitmap->config()) { 4109c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com case SkBitmap::kARGB_8888_Config: 4119c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com index |= 0; 4129c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com break; 4139c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com case SkBitmap::kRGB_565_Config: 4149c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com index |= 8; 4159c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com break; 4169c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com case SkBitmap::kIndex8_Config: 4179c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com index |= 16; 4189c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com break; 4199c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com case SkBitmap::kARGB_4444_Config: 4209c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com index |= 24; 4219c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com break; 4229c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com case SkBitmap::kA8_Config: 4239c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com index |= 32; 4249c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com fPaintPMColor = SkPreMultiplyColor(paint.getColor()); 4259c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com break; 4269c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com default: 4279c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com return false; 428aa9152abbca3a958a9379f4e5067a1c37486d677reed@android.com } 429c9a1d4b519c2db8e43e54fef068c46462d2f8a4breed@android.com 4309c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com #if !SK_ARM_NEON_IS_ALWAYS 4319c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com static const SampleProc32 gSkBitmapProcStateSample32[] = { 4329c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com S32_opaque_D32_nofilter_DXDY, 4339c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com S32_alpha_D32_nofilter_DXDY, 4349c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com S32_opaque_D32_nofilter_DX, 4359c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com S32_alpha_D32_nofilter_DX, 4369c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com S32_opaque_D32_filter_DXDY, 4379c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com S32_alpha_D32_filter_DXDY, 4389c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com S32_opaque_D32_filter_DX, 4399c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com S32_alpha_D32_filter_DX, 4409c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com 4419c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com S16_opaque_D32_nofilter_DXDY, 4429c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com S16_alpha_D32_nofilter_DXDY, 4439c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com S16_opaque_D32_nofilter_DX, 4449c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com S16_alpha_D32_nofilter_DX, 4459c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com S16_opaque_D32_filter_DXDY, 4469c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com S16_alpha_D32_filter_DXDY, 4479c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com S16_opaque_D32_filter_DX, 4489c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com S16_alpha_D32_filter_DX, 4499c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com 4509c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com SI8_opaque_D32_nofilter_DXDY, 4519c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com SI8_alpha_D32_nofilter_DXDY, 4529c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com SI8_opaque_D32_nofilter_DX, 4539c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com SI8_alpha_D32_nofilter_DX, 4549c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com SI8_opaque_D32_filter_DXDY, 4559c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com SI8_alpha_D32_filter_DXDY, 4569c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com SI8_opaque_D32_filter_DX, 4579c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com SI8_alpha_D32_filter_DX, 4589c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com 4599c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com S4444_opaque_D32_nofilter_DXDY, 4609c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com S4444_alpha_D32_nofilter_DXDY, 4619c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com S4444_opaque_D32_nofilter_DX, 4629c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com S4444_alpha_D32_nofilter_DX, 4639c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com S4444_opaque_D32_filter_DXDY, 4649c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com S4444_alpha_D32_filter_DXDY, 4659c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com S4444_opaque_D32_filter_DX, 4669c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com S4444_alpha_D32_filter_DX, 4679c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com 4689c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com // A8 treats alpha/opaque the same (equally efficient) 4699c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com SA8_alpha_D32_nofilter_DXDY, 4709c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com SA8_alpha_D32_nofilter_DXDY, 4719c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com SA8_alpha_D32_nofilter_DX, 4729c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com SA8_alpha_D32_nofilter_DX, 4739c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com SA8_alpha_D32_filter_DXDY, 4749c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com SA8_alpha_D32_filter_DXDY, 4759c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com SA8_alpha_D32_filter_DX, 4769c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com SA8_alpha_D32_filter_DX 4779c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com }; 4789c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com 4799c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com static const SampleProc16 gSkBitmapProcStateSample16[] = { 4809c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com S32_D16_nofilter_DXDY, 4819c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com S32_D16_nofilter_DX, 4829c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com S32_D16_filter_DXDY, 4839c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com S32_D16_filter_DX, 4849c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com 4859c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com S16_D16_nofilter_DXDY, 4869c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com S16_D16_nofilter_DX, 4879c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com S16_D16_filter_DXDY, 4889c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com S16_D16_filter_DX, 4899c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com 4909c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com SI8_D16_nofilter_DXDY, 4919c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com SI8_D16_nofilter_DX, 4929c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com SI8_D16_filter_DXDY, 4939c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com SI8_D16_filter_DX, 4949c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com 4959c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com // Don't support 4444 -> 565 4969c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com NULL, NULL, NULL, NULL, 4979c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com // Don't support A8 -> 565 4989c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com NULL, NULL, NULL, NULL 4999c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com }; 5009c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com #endif 5019c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com 5029c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com fSampleProc32 = SK_ARM_NEON_WRAP(gSkBitmapProcStateSample32)[index]; 5039c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com index >>= 1; // shift away any opaque/alpha distinction 5049c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com fSampleProc16 = SK_ARM_NEON_WRAP(gSkBitmapProcStateSample16)[index]; 5059c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com 5069c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com // our special-case shaderprocs 5079c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com if (SK_ARM_NEON_WRAP(S16_D16_filter_DX) == fSampleProc16) { 5089c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com if (clampClamp) { 5099c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com fShaderProc16 = SK_ARM_NEON_WRAP(Clamp_S16_D16_filter_DX_shaderproc); 5109c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com } else if (SkShader::kRepeat_TileMode == fTileModeX && 5119c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com SkShader::kRepeat_TileMode == fTileModeY) { 5129c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com fShaderProc16 = SK_ARM_NEON_WRAP(Repeat_S16_D16_filter_DX_shaderproc); 5139c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com } 5149c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com } else if (SK_ARM_NEON_WRAP(SI8_opaque_D32_filter_DX) == fSampleProc32 && clampClamp) { 5159c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com fShaderProc32 = SK_ARM_NEON_WRAP(Clamp_SI8_opaque_D32_filter_DX_shaderproc); 5169c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com } 5173e2345a8d56cb76bc43e4421a3e9e3681ecd9ebaskia.committer@gmail.com 5189c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com if (NULL == fShaderProc32) { 5199c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com fShaderProc32 = this->chooseShaderProc32(); 5209c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com } 5211a8940e558ecc91502767525f69339fd45b71bd4humper@google.com } 5221a8940e558ecc91502767525f69339fd45b71bd4humper@google.com 523b088947f27496a9b9dc48a7cfb170f9d59589825humper@google.com // see if our platform has any accelerated overrides 524b088947f27496a9b9dc48a7cfb170f9d59589825humper@google.com this->platformProcs(); 525b088947f27496a9b9dc48a7cfb170f9d59589825humper@google.com 5268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return true; 5278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 5288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 5299a4c746a1f0f91a5be2708a4c2018dfe14f62e48reed@google.comstatic void Clamp_S32_D32_nofilter_trans_shaderproc(const SkBitmapProcState& s, 5309a4c746a1f0f91a5be2708a4c2018dfe14f62e48reed@google.com int x, int y, 5319a4c746a1f0f91a5be2708a4c2018dfe14f62e48reed@google.com SkPMColor* SK_RESTRICT colors, 5329a4c746a1f0f91a5be2708a4c2018dfe14f62e48reed@google.com int count) { 5339a4c746a1f0f91a5be2708a4c2018dfe14f62e48reed@google.com SkASSERT(((s.fInvType & ~SkMatrix::kTranslate_Mask)) == 0); 5349a4c746a1f0f91a5be2708a4c2018dfe14f62e48reed@google.com SkASSERT(s.fInvKy == 0); 5359a4c746a1f0f91a5be2708a4c2018dfe14f62e48reed@google.com SkASSERT(count > 0 && colors != NULL); 5369cfc83cc8ac2ee50a7ce889e65a707941f48bdeareed@google.com SkASSERT(SkPaint::kNone_FilterLevel == s.fFilterLevel); 53720c301bd1aa4578c6d0abb23ac2c72b5fbb436dbskia.committer@gmail.com 5389a4c746a1f0f91a5be2708a4c2018dfe14f62e48reed@google.com const int maxX = s.fBitmap->width() - 1; 539f7698de60e2cfecf84cb84f957e6fe69325fe67freed@google.com const int maxY = s.fBitmap->height() - 1; 540f7698de60e2cfecf84cb84f957e6fe69325fe67freed@google.com int ix = s.fFilterOneX + x; 541f7698de60e2cfecf84cb84f957e6fe69325fe67freed@google.com int iy = SkClampMax(s.fFilterOneY + y, maxY); 542f7698de60e2cfecf84cb84f957e6fe69325fe67freed@google.com#ifdef SK_DEBUG 5439a4c746a1f0f91a5be2708a4c2018dfe14f62e48reed@google.com { 5449a4c746a1f0f91a5be2708a4c2018dfe14f62e48reed@google.com SkPoint pt; 5459c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com s.fInvProc(s.fInvMatrix, SkIntToScalar(x) + SK_ScalarHalf, 5469a4c746a1f0f91a5be2708a4c2018dfe14f62e48reed@google.com SkIntToScalar(y) + SK_ScalarHalf, &pt); 547f7698de60e2cfecf84cb84f957e6fe69325fe67freed@google.com int iy2 = SkClampMax(SkScalarFloorToInt(pt.fY), maxY); 548f7698de60e2cfecf84cb84f957e6fe69325fe67freed@google.com int ix2 = SkScalarFloorToInt(pt.fX); 54920c301bd1aa4578c6d0abb23ac2c72b5fbb436dbskia.committer@gmail.com 550f7698de60e2cfecf84cb84f957e6fe69325fe67freed@google.com SkASSERT(iy == iy2); 551f7698de60e2cfecf84cb84f957e6fe69325fe67freed@google.com SkASSERT(ix == ix2); 5529a4c746a1f0f91a5be2708a4c2018dfe14f62e48reed@google.com } 553f7698de60e2cfecf84cb84f957e6fe69325fe67freed@google.com#endif 554f7698de60e2cfecf84cb84f957e6fe69325fe67freed@google.com const SkPMColor* row = s.fBitmap->getAddr32(0, iy); 55520c301bd1aa4578c6d0abb23ac2c72b5fbb436dbskia.committer@gmail.com 5569a4c746a1f0f91a5be2708a4c2018dfe14f62e48reed@google.com // clamp to the left 5579a4c746a1f0f91a5be2708a4c2018dfe14f62e48reed@google.com if (ix < 0) { 5589a4c746a1f0f91a5be2708a4c2018dfe14f62e48reed@google.com int n = SkMin32(-ix, count); 5599a4c746a1f0f91a5be2708a4c2018dfe14f62e48reed@google.com sk_memset32(colors, row[0], n); 5609a4c746a1f0f91a5be2708a4c2018dfe14f62e48reed@google.com count -= n; 5619a4c746a1f0f91a5be2708a4c2018dfe14f62e48reed@google.com if (0 == count) { 5629a4c746a1f0f91a5be2708a4c2018dfe14f62e48reed@google.com return; 5639a4c746a1f0f91a5be2708a4c2018dfe14f62e48reed@google.com } 5649a4c746a1f0f91a5be2708a4c2018dfe14f62e48reed@google.com colors += n; 5659a4c746a1f0f91a5be2708a4c2018dfe14f62e48reed@google.com SkASSERT(-ix == n); 5669a4c746a1f0f91a5be2708a4c2018dfe14f62e48reed@google.com ix = 0; 5679a4c746a1f0f91a5be2708a4c2018dfe14f62e48reed@google.com } 5689a4c746a1f0f91a5be2708a4c2018dfe14f62e48reed@google.com // copy the middle 5699a4c746a1f0f91a5be2708a4c2018dfe14f62e48reed@google.com if (ix <= maxX) { 5709a4c746a1f0f91a5be2708a4c2018dfe14f62e48reed@google.com int n = SkMin32(maxX - ix + 1, count); 5719a4c746a1f0f91a5be2708a4c2018dfe14f62e48reed@google.com memcpy(colors, row + ix, n * sizeof(SkPMColor)); 5729a4c746a1f0f91a5be2708a4c2018dfe14f62e48reed@google.com count -= n; 5739a4c746a1f0f91a5be2708a4c2018dfe14f62e48reed@google.com if (0 == count) { 5749a4c746a1f0f91a5be2708a4c2018dfe14f62e48reed@google.com return; 5759a4c746a1f0f91a5be2708a4c2018dfe14f62e48reed@google.com } 5769a4c746a1f0f91a5be2708a4c2018dfe14f62e48reed@google.com colors += n; 5779a4c746a1f0f91a5be2708a4c2018dfe14f62e48reed@google.com } 5789a4c746a1f0f91a5be2708a4c2018dfe14f62e48reed@google.com SkASSERT(count > 0); 5799a4c746a1f0f91a5be2708a4c2018dfe14f62e48reed@google.com // clamp to the right 5809a4c746a1f0f91a5be2708a4c2018dfe14f62e48reed@google.com sk_memset32(colors, row[maxX], count); 5819a4c746a1f0f91a5be2708a4c2018dfe14f62e48reed@google.com} 5829a4c746a1f0f91a5be2708a4c2018dfe14f62e48reed@google.com 583a8d99307717c5fe02043969db0566c236a08c313reed@google.comstatic inline int sk_int_mod(int x, int n) { 584a8d99307717c5fe02043969db0566c236a08c313reed@google.com SkASSERT(n > 0); 585a8d99307717c5fe02043969db0566c236a08c313reed@google.com if ((unsigned)x >= (unsigned)n) { 586a8d99307717c5fe02043969db0566c236a08c313reed@google.com if (x < 0) { 587a8d99307717c5fe02043969db0566c236a08c313reed@google.com x = n + ~(~x % n); 588a8d99307717c5fe02043969db0566c236a08c313reed@google.com } else { 589a8d99307717c5fe02043969db0566c236a08c313reed@google.com x = x % n; 590a8d99307717c5fe02043969db0566c236a08c313reed@google.com } 591a8d99307717c5fe02043969db0566c236a08c313reed@google.com } 592a8d99307717c5fe02043969db0566c236a08c313reed@google.com return x; 593a8d99307717c5fe02043969db0566c236a08c313reed@google.com} 594a8d99307717c5fe02043969db0566c236a08c313reed@google.com 5958b8bf4d12ecf8fb340a1362c91a8a57395dd31a3robertphillips@google.comstatic inline int sk_int_mirror(int x, int n) { 5968b8bf4d12ecf8fb340a1362c91a8a57395dd31a3robertphillips@google.com x = sk_int_mod(x, 2 * n); 5978b8bf4d12ecf8fb340a1362c91a8a57395dd31a3robertphillips@google.com if (x >= n) { 5988b8bf4d12ecf8fb340a1362c91a8a57395dd31a3robertphillips@google.com x = n + ~(x - n); 5998b8bf4d12ecf8fb340a1362c91a8a57395dd31a3robertphillips@google.com } 6008b8bf4d12ecf8fb340a1362c91a8a57395dd31a3robertphillips@google.com return x; 6018b8bf4d12ecf8fb340a1362c91a8a57395dd31a3robertphillips@google.com} 6028b8bf4d12ecf8fb340a1362c91a8a57395dd31a3robertphillips@google.com 603a8d99307717c5fe02043969db0566c236a08c313reed@google.comstatic void Repeat_S32_D32_nofilter_trans_shaderproc(const SkBitmapProcState& s, 604a8d99307717c5fe02043969db0566c236a08c313reed@google.com int x, int y, 605a8d99307717c5fe02043969db0566c236a08c313reed@google.com SkPMColor* SK_RESTRICT colors, 606a8d99307717c5fe02043969db0566c236a08c313reed@google.com int count) { 607a8d99307717c5fe02043969db0566c236a08c313reed@google.com SkASSERT(((s.fInvType & ~SkMatrix::kTranslate_Mask)) == 0); 608a8d99307717c5fe02043969db0566c236a08c313reed@google.com SkASSERT(s.fInvKy == 0); 609a8d99307717c5fe02043969db0566c236a08c313reed@google.com SkASSERT(count > 0 && colors != NULL); 6109cfc83cc8ac2ee50a7ce889e65a707941f48bdeareed@google.com SkASSERT(SkPaint::kNone_FilterLevel == s.fFilterLevel); 61120c301bd1aa4578c6d0abb23ac2c72b5fbb436dbskia.committer@gmail.com 612a8d99307717c5fe02043969db0566c236a08c313reed@google.com const int stopX = s.fBitmap->width(); 613a8d99307717c5fe02043969db0566c236a08c313reed@google.com const int stopY = s.fBitmap->height(); 614a8d99307717c5fe02043969db0566c236a08c313reed@google.com int ix = s.fFilterOneX + x; 615a8d99307717c5fe02043969db0566c236a08c313reed@google.com int iy = sk_int_mod(s.fFilterOneY + y, stopY); 616a8d99307717c5fe02043969db0566c236a08c313reed@google.com#ifdef SK_DEBUG 617a8d99307717c5fe02043969db0566c236a08c313reed@google.com { 618a8d99307717c5fe02043969db0566c236a08c313reed@google.com SkPoint pt; 6199c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com s.fInvProc(s.fInvMatrix, SkIntToScalar(x) + SK_ScalarHalf, 620a8d99307717c5fe02043969db0566c236a08c313reed@google.com SkIntToScalar(y) + SK_ScalarHalf, &pt); 621a8d99307717c5fe02043969db0566c236a08c313reed@google.com int iy2 = sk_int_mod(SkScalarFloorToInt(pt.fY), stopY); 622a8d99307717c5fe02043969db0566c236a08c313reed@google.com int ix2 = SkScalarFloorToInt(pt.fX); 62320c301bd1aa4578c6d0abb23ac2c72b5fbb436dbskia.committer@gmail.com 624a8d99307717c5fe02043969db0566c236a08c313reed@google.com SkASSERT(iy == iy2); 625a8d99307717c5fe02043969db0566c236a08c313reed@google.com SkASSERT(ix == ix2); 626a8d99307717c5fe02043969db0566c236a08c313reed@google.com } 627a8d99307717c5fe02043969db0566c236a08c313reed@google.com#endif 628a8d99307717c5fe02043969db0566c236a08c313reed@google.com const SkPMColor* row = s.fBitmap->getAddr32(0, iy); 629a8d99307717c5fe02043969db0566c236a08c313reed@google.com 630a8d99307717c5fe02043969db0566c236a08c313reed@google.com ix = sk_int_mod(ix, stopX); 631a8d99307717c5fe02043969db0566c236a08c313reed@google.com for (;;) { 632a8d99307717c5fe02043969db0566c236a08c313reed@google.com int n = SkMin32(stopX - ix, count); 633a8d99307717c5fe02043969db0566c236a08c313reed@google.com memcpy(colors, row + ix, n * sizeof(SkPMColor)); 634a8d99307717c5fe02043969db0566c236a08c313reed@google.com count -= n; 635a8d99307717c5fe02043969db0566c236a08c313reed@google.com if (0 == count) { 636a8d99307717c5fe02043969db0566c236a08c313reed@google.com return; 637a8d99307717c5fe02043969db0566c236a08c313reed@google.com } 638a8d99307717c5fe02043969db0566c236a08c313reed@google.com colors += n; 639a8d99307717c5fe02043969db0566c236a08c313reed@google.com ix = 0; 640a8d99307717c5fe02043969db0566c236a08c313reed@google.com } 641a8d99307717c5fe02043969db0566c236a08c313reed@google.com} 642a8d99307717c5fe02043969db0566c236a08c313reed@google.com 6438b8bf4d12ecf8fb340a1362c91a8a57395dd31a3robertphillips@google.comstatic void S32_D32_constX_shaderproc(const SkBitmapProcState& s, 6448b8bf4d12ecf8fb340a1362c91a8a57395dd31a3robertphillips@google.com int x, int y, 6458b8bf4d12ecf8fb340a1362c91a8a57395dd31a3robertphillips@google.com SkPMColor* SK_RESTRICT colors, 6468b8bf4d12ecf8fb340a1362c91a8a57395dd31a3robertphillips@google.com int count) { 6478b8bf4d12ecf8fb340a1362c91a8a57395dd31a3robertphillips@google.com SkASSERT((s.fInvType & ~(SkMatrix::kTranslate_Mask | SkMatrix::kScale_Mask)) == 0); 6488b8bf4d12ecf8fb340a1362c91a8a57395dd31a3robertphillips@google.com SkASSERT(s.fInvKy == 0); 6498b8bf4d12ecf8fb340a1362c91a8a57395dd31a3robertphillips@google.com SkASSERT(count > 0 && colors != NULL); 6508b8bf4d12ecf8fb340a1362c91a8a57395dd31a3robertphillips@google.com SkASSERT(1 == s.fBitmap->width()); 6518b8bf4d12ecf8fb340a1362c91a8a57395dd31a3robertphillips@google.com 652ad51132b1b494e9921c500167adc899e6cfc8684scroggo@google.com int iY0; 653ad51132b1b494e9921c500167adc899e6cfc8684scroggo@google.com int iY1 SK_INIT_TO_AVOID_WARNING; 654ad51132b1b494e9921c500167adc899e6cfc8684scroggo@google.com int iSubY SK_INIT_TO_AVOID_WARNING; 6558b8bf4d12ecf8fb340a1362c91a8a57395dd31a3robertphillips@google.com 6569cfc83cc8ac2ee50a7ce889e65a707941f48bdeareed@google.com if (SkPaint::kNone_FilterLevel != s.fFilterLevel) { 6578b8bf4d12ecf8fb340a1362c91a8a57395dd31a3robertphillips@google.com SkBitmapProcState::MatrixProc mproc = s.getMatrixProc(); 6588b8bf4d12ecf8fb340a1362c91a8a57395dd31a3robertphillips@google.com uint32_t xy[2]; 6598b8bf4d12ecf8fb340a1362c91a8a57395dd31a3robertphillips@google.com 6608b8bf4d12ecf8fb340a1362c91a8a57395dd31a3robertphillips@google.com mproc(s, xy, 1, x, y); 6618b8bf4d12ecf8fb340a1362c91a8a57395dd31a3robertphillips@google.com 6628b8bf4d12ecf8fb340a1362c91a8a57395dd31a3robertphillips@google.com iY0 = xy[0] >> 18; 6638b8bf4d12ecf8fb340a1362c91a8a57395dd31a3robertphillips@google.com iY1 = xy[0] & 0x3FFF; 6648b8bf4d12ecf8fb340a1362c91a8a57395dd31a3robertphillips@google.com iSubY = (xy[0] >> 14) & 0xF; 6658b8bf4d12ecf8fb340a1362c91a8a57395dd31a3robertphillips@google.com } else { 6668b8bf4d12ecf8fb340a1362c91a8a57395dd31a3robertphillips@google.com int yTemp; 6678b8bf4d12ecf8fb340a1362c91a8a57395dd31a3robertphillips@google.com 6688b8bf4d12ecf8fb340a1362c91a8a57395dd31a3robertphillips@google.com if (s.fInvType > SkMatrix::kTranslate_Mask) { 6698b8bf4d12ecf8fb340a1362c91a8a57395dd31a3robertphillips@google.com SkPoint pt; 6709c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com s.fInvProc(s.fInvMatrix, 6718b8bf4d12ecf8fb340a1362c91a8a57395dd31a3robertphillips@google.com SkIntToScalar(x) + SK_ScalarHalf, 67236df7ed46b41ac31cb2205bfd3ae37659d61e2fbskia.committer@gmail.com SkIntToScalar(y) + SK_ScalarHalf, 6738b8bf4d12ecf8fb340a1362c91a8a57395dd31a3robertphillips@google.com &pt); 6741e3052354ac155e3d9418cf7e8c8e009df524e01robertphillips@google.com // When the matrix has a scale component the setup code in 67598ded84b80918ac1e40224c125922941f3b2eb03skia.committer@gmail.com // chooseProcs multiples the inverse matrix by the inverse of the 6761e3052354ac155e3d9418cf7e8c8e009df524e01robertphillips@google.com // bitmap's width and height. Since this method is going to do 6771e3052354ac155e3d9418cf7e8c8e009df524e01robertphillips@google.com // its own tiling and sampling we need to undo that here. 678d507775a8be5eca19c1c6212196bf4e56d29bab5robertphillips@google.com if (SkShader::kClamp_TileMode != s.fTileModeX || 679d507775a8be5eca19c1c6212196bf4e56d29bab5robertphillips@google.com SkShader::kClamp_TileMode != s.fTileModeY) { 680d507775a8be5eca19c1c6212196bf4e56d29bab5robertphillips@google.com yTemp = SkScalarFloorToInt(pt.fY * s.fBitmap->height()); 681d507775a8be5eca19c1c6212196bf4e56d29bab5robertphillips@google.com } else { 682d507775a8be5eca19c1c6212196bf4e56d29bab5robertphillips@google.com yTemp = SkScalarFloorToInt(pt.fY); 683d507775a8be5eca19c1c6212196bf4e56d29bab5robertphillips@google.com } 6848b8bf4d12ecf8fb340a1362c91a8a57395dd31a3robertphillips@google.com } else { 6858b8bf4d12ecf8fb340a1362c91a8a57395dd31a3robertphillips@google.com yTemp = s.fFilterOneY + y; 6868b8bf4d12ecf8fb340a1362c91a8a57395dd31a3robertphillips@google.com } 6878b8bf4d12ecf8fb340a1362c91a8a57395dd31a3robertphillips@google.com 6888b8bf4d12ecf8fb340a1362c91a8a57395dd31a3robertphillips@google.com const int stopY = s.fBitmap->height(); 6898b8bf4d12ecf8fb340a1362c91a8a57395dd31a3robertphillips@google.com switch (s.fTileModeY) { 6908b8bf4d12ecf8fb340a1362c91a8a57395dd31a3robertphillips@google.com case SkShader::kClamp_TileMode: 6918b8bf4d12ecf8fb340a1362c91a8a57395dd31a3robertphillips@google.com iY0 = SkClampMax(yTemp, stopY-1); 6928b8bf4d12ecf8fb340a1362c91a8a57395dd31a3robertphillips@google.com break; 6938b8bf4d12ecf8fb340a1362c91a8a57395dd31a3robertphillips@google.com case SkShader::kRepeat_TileMode: 6948b8bf4d12ecf8fb340a1362c91a8a57395dd31a3robertphillips@google.com iY0 = sk_int_mod(yTemp, stopY); 6958b8bf4d12ecf8fb340a1362c91a8a57395dd31a3robertphillips@google.com break; 6968b8bf4d12ecf8fb340a1362c91a8a57395dd31a3robertphillips@google.com case SkShader::kMirror_TileMode: 6978b8bf4d12ecf8fb340a1362c91a8a57395dd31a3robertphillips@google.com default: 6988b8bf4d12ecf8fb340a1362c91a8a57395dd31a3robertphillips@google.com iY0 = sk_int_mirror(yTemp, stopY); 6998b8bf4d12ecf8fb340a1362c91a8a57395dd31a3robertphillips@google.com break; 7008b8bf4d12ecf8fb340a1362c91a8a57395dd31a3robertphillips@google.com } 7018b8bf4d12ecf8fb340a1362c91a8a57395dd31a3robertphillips@google.com 7028b8bf4d12ecf8fb340a1362c91a8a57395dd31a3robertphillips@google.com#ifdef SK_DEBUG 7038b8bf4d12ecf8fb340a1362c91a8a57395dd31a3robertphillips@google.com { 7048b8bf4d12ecf8fb340a1362c91a8a57395dd31a3robertphillips@google.com SkPoint pt; 7059c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com s.fInvProc(s.fInvMatrix, 7068b8bf4d12ecf8fb340a1362c91a8a57395dd31a3robertphillips@google.com SkIntToScalar(x) + SK_ScalarHalf, 70736df7ed46b41ac31cb2205bfd3ae37659d61e2fbskia.committer@gmail.com SkIntToScalar(y) + SK_ScalarHalf, 7088b8bf4d12ecf8fb340a1362c91a8a57395dd31a3robertphillips@google.com &pt); 709d507775a8be5eca19c1c6212196bf4e56d29bab5robertphillips@google.com if (s.fInvType > SkMatrix::kTranslate_Mask && 710d507775a8be5eca19c1c6212196bf4e56d29bab5robertphillips@google.com (SkShader::kClamp_TileMode != s.fTileModeX || 711d507775a8be5eca19c1c6212196bf4e56d29bab5robertphillips@google.com SkShader::kClamp_TileMode != s.fTileModeY)) { 7121e3052354ac155e3d9418cf7e8c8e009df524e01robertphillips@google.com pt.fY *= s.fBitmap->height(); 7131e3052354ac155e3d9418cf7e8c8e009df524e01robertphillips@google.com } 7148b8bf4d12ecf8fb340a1362c91a8a57395dd31a3robertphillips@google.com int iY2; 7158b8bf4d12ecf8fb340a1362c91a8a57395dd31a3robertphillips@google.com 7168b8bf4d12ecf8fb340a1362c91a8a57395dd31a3robertphillips@google.com switch (s.fTileModeY) { 7178b8bf4d12ecf8fb340a1362c91a8a57395dd31a3robertphillips@google.com case SkShader::kClamp_TileMode: 7188b8bf4d12ecf8fb340a1362c91a8a57395dd31a3robertphillips@google.com iY2 = SkClampMax(SkScalarFloorToInt(pt.fY), stopY-1); 7198b8bf4d12ecf8fb340a1362c91a8a57395dd31a3robertphillips@google.com break; 7208b8bf4d12ecf8fb340a1362c91a8a57395dd31a3robertphillips@google.com case SkShader::kRepeat_TileMode: 7218b8bf4d12ecf8fb340a1362c91a8a57395dd31a3robertphillips@google.com iY2 = sk_int_mod(SkScalarFloorToInt(pt.fY), stopY); 7228b8bf4d12ecf8fb340a1362c91a8a57395dd31a3robertphillips@google.com break; 7238b8bf4d12ecf8fb340a1362c91a8a57395dd31a3robertphillips@google.com case SkShader::kMirror_TileMode: 7248b8bf4d12ecf8fb340a1362c91a8a57395dd31a3robertphillips@google.com default: 7258b8bf4d12ecf8fb340a1362c91a8a57395dd31a3robertphillips@google.com iY2 = sk_int_mirror(SkScalarFloorToInt(pt.fY), stopY); 7268b8bf4d12ecf8fb340a1362c91a8a57395dd31a3robertphillips@google.com break; 7278b8bf4d12ecf8fb340a1362c91a8a57395dd31a3robertphillips@google.com } 7288b8bf4d12ecf8fb340a1362c91a8a57395dd31a3robertphillips@google.com 7298b8bf4d12ecf8fb340a1362c91a8a57395dd31a3robertphillips@google.com SkASSERT(iY0 == iY2); 7308b8bf4d12ecf8fb340a1362c91a8a57395dd31a3robertphillips@google.com } 7318b8bf4d12ecf8fb340a1362c91a8a57395dd31a3robertphillips@google.com#endif 7328b8bf4d12ecf8fb340a1362c91a8a57395dd31a3robertphillips@google.com } 7338b8bf4d12ecf8fb340a1362c91a8a57395dd31a3robertphillips@google.com 7348b8bf4d12ecf8fb340a1362c91a8a57395dd31a3robertphillips@google.com const SkPMColor* row0 = s.fBitmap->getAddr32(0, iY0); 7358b8bf4d12ecf8fb340a1362c91a8a57395dd31a3robertphillips@google.com SkPMColor color; 7368b8bf4d12ecf8fb340a1362c91a8a57395dd31a3robertphillips@google.com 7379cfc83cc8ac2ee50a7ce889e65a707941f48bdeareed@google.com if (SkPaint::kNone_FilterLevel != s.fFilterLevel) { 7388b8bf4d12ecf8fb340a1362c91a8a57395dd31a3robertphillips@google.com const SkPMColor* row1 = s.fBitmap->getAddr32(0, iY1); 7398b8bf4d12ecf8fb340a1362c91a8a57395dd31a3robertphillips@google.com 7408b8bf4d12ecf8fb340a1362c91a8a57395dd31a3robertphillips@google.com if (s.fAlphaScale < 256) { 7418b8bf4d12ecf8fb340a1362c91a8a57395dd31a3robertphillips@google.com Filter_32_alpha(iSubY, *row0, *row1, &color, s.fAlphaScale); 7428b8bf4d12ecf8fb340a1362c91a8a57395dd31a3robertphillips@google.com } else { 7438b8bf4d12ecf8fb340a1362c91a8a57395dd31a3robertphillips@google.com Filter_32_opaque(iSubY, *row0, *row1, &color); 7448b8bf4d12ecf8fb340a1362c91a8a57395dd31a3robertphillips@google.com } 7458b8bf4d12ecf8fb340a1362c91a8a57395dd31a3robertphillips@google.com } else { 7468b8bf4d12ecf8fb340a1362c91a8a57395dd31a3robertphillips@google.com if (s.fAlphaScale < 256) { 7478b8bf4d12ecf8fb340a1362c91a8a57395dd31a3robertphillips@google.com color = SkAlphaMulQ(*row0, s.fAlphaScale); 7488b8bf4d12ecf8fb340a1362c91a8a57395dd31a3robertphillips@google.com } else { 7498b8bf4d12ecf8fb340a1362c91a8a57395dd31a3robertphillips@google.com color = *row0; 7508b8bf4d12ecf8fb340a1362c91a8a57395dd31a3robertphillips@google.com } 7518b8bf4d12ecf8fb340a1362c91a8a57395dd31a3robertphillips@google.com } 7528b8bf4d12ecf8fb340a1362c91a8a57395dd31a3robertphillips@google.com 7538b8bf4d12ecf8fb340a1362c91a8a57395dd31a3robertphillips@google.com sk_memset32(colors, color, count); 7548b8bf4d12ecf8fb340a1362c91a8a57395dd31a3robertphillips@google.com} 7558b8bf4d12ecf8fb340a1362c91a8a57395dd31a3robertphillips@google.com 7566bb92bc0b52d31f3ded38927cdefbeb13a3df87areed@google.comstatic void DoNothing_shaderproc(const SkBitmapProcState&, int x, int y, 7576bb92bc0b52d31f3ded38927cdefbeb13a3df87areed@google.com SkPMColor* SK_RESTRICT colors, int count) { 7586bb92bc0b52d31f3ded38927cdefbeb13a3df87areed@google.com // if we get called, the matrix is too tricky, so we just draw nothing 7596bb92bc0b52d31f3ded38927cdefbeb13a3df87areed@google.com sk_memset32(colors, 0, count); 7606bb92bc0b52d31f3ded38927cdefbeb13a3df87areed@google.com} 7616bb92bc0b52d31f3ded38927cdefbeb13a3df87areed@google.com 7626bb92bc0b52d31f3ded38927cdefbeb13a3df87areed@google.combool SkBitmapProcState::setupForTranslate() { 763a8d99307717c5fe02043969db0566c236a08c313reed@google.com SkPoint pt; 7649c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com fInvProc(fInvMatrix, SK_ScalarHalf, SK_ScalarHalf, &pt); 7656bb92bc0b52d31f3ded38927cdefbeb13a3df87areed@google.com 7666bb92bc0b52d31f3ded38927cdefbeb13a3df87areed@google.com /* 7676bb92bc0b52d31f3ded38927cdefbeb13a3df87areed@google.com * if the translate is larger than our ints, we can get random results, or 7686bb92bc0b52d31f3ded38927cdefbeb13a3df87areed@google.com * worse, we might get 0x80000000, which wreaks havoc on us, since we can't 7696bb92bc0b52d31f3ded38927cdefbeb13a3df87areed@google.com * negate it. 7706bb92bc0b52d31f3ded38927cdefbeb13a3df87areed@google.com */ 7716bb92bc0b52d31f3ded38927cdefbeb13a3df87areed@google.com const SkScalar too_big = SkIntToScalar(1 << 30); 7726bb92bc0b52d31f3ded38927cdefbeb13a3df87areed@google.com if (SkScalarAbs(pt.fX) > too_big || SkScalarAbs(pt.fY) > too_big) { 7736bb92bc0b52d31f3ded38927cdefbeb13a3df87areed@google.com return false; 7746bb92bc0b52d31f3ded38927cdefbeb13a3df87areed@google.com } 7756bb92bc0b52d31f3ded38927cdefbeb13a3df87areed@google.com 776a8d99307717c5fe02043969db0566c236a08c313reed@google.com // Since we know we're not filtered, we re-purpose these fields allow 777a8d99307717c5fe02043969db0566c236a08c313reed@google.com // us to go from device -> src coordinates w/ just an integer add, 778a8d99307717c5fe02043969db0566c236a08c313reed@google.com // rather than running through the inverse-matrix 779a8d99307717c5fe02043969db0566c236a08c313reed@google.com fFilterOneX = SkScalarFloorToInt(pt.fX); 780a8d99307717c5fe02043969db0566c236a08c313reed@google.com fFilterOneY = SkScalarFloorToInt(pt.fY); 7816bb92bc0b52d31f3ded38927cdefbeb13a3df87areed@google.com return true; 782a8d99307717c5fe02043969db0566c236a08c313reed@google.com} 783a8d99307717c5fe02043969db0566c236a08c313reed@google.com 7849a4c746a1f0f91a5be2708a4c2018dfe14f62e48reed@google.comSkBitmapProcState::ShaderProc32 SkBitmapProcState::chooseShaderProc32() { 7858b8bf4d12ecf8fb340a1362c91a8a57395dd31a3robertphillips@google.com 7868b8bf4d12ecf8fb340a1362c91a8a57395dd31a3robertphillips@google.com if (SkBitmap::kARGB_8888_Config != fBitmap->config()) { 7878b8bf4d12ecf8fb340a1362c91a8a57395dd31a3robertphillips@google.com return NULL; 7888b8bf4d12ecf8fb340a1362c91a8a57395dd31a3robertphillips@google.com } 7898b8bf4d12ecf8fb340a1362c91a8a57395dd31a3robertphillips@google.com 7908b8bf4d12ecf8fb340a1362c91a8a57395dd31a3robertphillips@google.com static const unsigned kMask = SkMatrix::kTranslate_Mask | SkMatrix::kScale_Mask; 7918b8bf4d12ecf8fb340a1362c91a8a57395dd31a3robertphillips@google.com 7928b8bf4d12ecf8fb340a1362c91a8a57395dd31a3robertphillips@google.com if (1 == fBitmap->width() && 0 == (fInvType & ~kMask)) { 7939cfc83cc8ac2ee50a7ce889e65a707941f48bdeareed@google.com if (SkPaint::kNone_FilterLevel == fFilterLevel && 7949c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com fInvType <= SkMatrix::kTranslate_Mask && 7959c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com !this->setupForTranslate()) { 7968b8bf4d12ecf8fb340a1362c91a8a57395dd31a3robertphillips@google.com return DoNothing_shaderproc; 7978b8bf4d12ecf8fb340a1362c91a8a57395dd31a3robertphillips@google.com } 7988b8bf4d12ecf8fb340a1362c91a8a57395dd31a3robertphillips@google.com return S32_D32_constX_shaderproc; 7998b8bf4d12ecf8fb340a1362c91a8a57395dd31a3robertphillips@google.com } 8008b8bf4d12ecf8fb340a1362c91a8a57395dd31a3robertphillips@google.com 8019a4c746a1f0f91a5be2708a4c2018dfe14f62e48reed@google.com if (fAlphaScale < 256) { 8029a4c746a1f0f91a5be2708a4c2018dfe14f62e48reed@google.com return NULL; 8039a4c746a1f0f91a5be2708a4c2018dfe14f62e48reed@google.com } 8049a4c746a1f0f91a5be2708a4c2018dfe14f62e48reed@google.com if (fInvType > SkMatrix::kTranslate_Mask) { 8059a4c746a1f0f91a5be2708a4c2018dfe14f62e48reed@google.com return NULL; 8069a4c746a1f0f91a5be2708a4c2018dfe14f62e48reed@google.com } 8079cfc83cc8ac2ee50a7ce889e65a707941f48bdeareed@google.com if (SkPaint::kNone_FilterLevel != fFilterLevel) { 8089a4c746a1f0f91a5be2708a4c2018dfe14f62e48reed@google.com return NULL; 8099a4c746a1f0f91a5be2708a4c2018dfe14f62e48reed@google.com } 8109a4c746a1f0f91a5be2708a4c2018dfe14f62e48reed@google.com 811a8d99307717c5fe02043969db0566c236a08c313reed@google.com SkShader::TileMode tx = (SkShader::TileMode)fTileModeX; 812a8d99307717c5fe02043969db0566c236a08c313reed@google.com SkShader::TileMode ty = (SkShader::TileMode)fTileModeY; 813a8d99307717c5fe02043969db0566c236a08c313reed@google.com 814a8d99307717c5fe02043969db0566c236a08c313reed@google.com if (SkShader::kClamp_TileMode == tx && SkShader::kClamp_TileMode == ty) { 8156bb92bc0b52d31f3ded38927cdefbeb13a3df87areed@google.com if (this->setupForTranslate()) { 8166bb92bc0b52d31f3ded38927cdefbeb13a3df87areed@google.com return Clamp_S32_D32_nofilter_trans_shaderproc; 8176bb92bc0b52d31f3ded38927cdefbeb13a3df87areed@google.com } 8186bb92bc0b52d31f3ded38927cdefbeb13a3df87areed@google.com return DoNothing_shaderproc; 8199a4c746a1f0f91a5be2708a4c2018dfe14f62e48reed@google.com } 820a8d99307717c5fe02043969db0566c236a08c313reed@google.com if (SkShader::kRepeat_TileMode == tx && SkShader::kRepeat_TileMode == ty) { 8216bb92bc0b52d31f3ded38927cdefbeb13a3df87areed@google.com if (this->setupForTranslate()) { 8226bb92bc0b52d31f3ded38927cdefbeb13a3df87areed@google.com return Repeat_S32_D32_nofilter_trans_shaderproc; 8236bb92bc0b52d31f3ded38927cdefbeb13a3df87areed@google.com } 8246bb92bc0b52d31f3ded38927cdefbeb13a3df87areed@google.com return DoNothing_shaderproc; 825a8d99307717c5fe02043969db0566c236a08c313reed@google.com } 8269a4c746a1f0f91a5be2708a4c2018dfe14f62e48reed@google.com return NULL; 8279a4c746a1f0f91a5be2708a4c2018dfe14f62e48reed@google.com} 8289a4c746a1f0f91a5be2708a4c2018dfe14f62e48reed@google.com 8294c128c4917acf25c2cc5d1bd22282a4e1bb53d96reed@android.com/////////////////////////////////////////////////////////////////////////////// 8309fe287bd07baa6d9e890b627c102bba562954f7dreed@google.com 8319fe287bd07baa6d9e890b627c102bba562954f7dreed@google.com#ifdef SK_DEBUG 8329fe287bd07baa6d9e890b627c102bba562954f7dreed@google.com 8339fe287bd07baa6d9e890b627c102bba562954f7dreed@google.comstatic void check_scale_nofilter(uint32_t bitmapXY[], int count, 8349fe287bd07baa6d9e890b627c102bba562954f7dreed@google.com unsigned mx, unsigned my) { 8359fe287bd07baa6d9e890b627c102bba562954f7dreed@google.com unsigned y = *bitmapXY++; 8369fe287bd07baa6d9e890b627c102bba562954f7dreed@google.com SkASSERT(y < my); 837fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 8389fe287bd07baa6d9e890b627c102bba562954f7dreed@google.com const uint16_t* xptr = reinterpret_cast<const uint16_t*>(bitmapXY); 8399fe287bd07baa6d9e890b627c102bba562954f7dreed@google.com for (int i = 0; i < count; ++i) { 8409fe287bd07baa6d9e890b627c102bba562954f7dreed@google.com SkASSERT(xptr[i] < mx); 8419fe287bd07baa6d9e890b627c102bba562954f7dreed@google.com } 8429fe287bd07baa6d9e890b627c102bba562954f7dreed@google.com} 8439fe287bd07baa6d9e890b627c102bba562954f7dreed@google.com 8449fe287bd07baa6d9e890b627c102bba562954f7dreed@google.comstatic void check_scale_filter(uint32_t bitmapXY[], int count, 8459fe287bd07baa6d9e890b627c102bba562954f7dreed@google.com unsigned mx, unsigned my) { 8469fe287bd07baa6d9e890b627c102bba562954f7dreed@google.com uint32_t YY = *bitmapXY++; 8479fe287bd07baa6d9e890b627c102bba562954f7dreed@google.com unsigned y0 = YY >> 18; 848fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com unsigned y1 = YY & 0x3FFF; 8499fe287bd07baa6d9e890b627c102bba562954f7dreed@google.com SkASSERT(y0 < my); 8509fe287bd07baa6d9e890b627c102bba562954f7dreed@google.com SkASSERT(y1 < my); 851fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 8529fe287bd07baa6d9e890b627c102bba562954f7dreed@google.com for (int i = 0; i < count; ++i) { 8539fe287bd07baa6d9e890b627c102bba562954f7dreed@google.com uint32_t XX = bitmapXY[i]; 8549fe287bd07baa6d9e890b627c102bba562954f7dreed@google.com unsigned x0 = XX >> 18; 8559fe287bd07baa6d9e890b627c102bba562954f7dreed@google.com unsigned x1 = XX & 0x3FFF; 8569fe287bd07baa6d9e890b627c102bba562954f7dreed@google.com SkASSERT(x0 < mx); 8579fe287bd07baa6d9e890b627c102bba562954f7dreed@google.com SkASSERT(x1 < mx); 8589fe287bd07baa6d9e890b627c102bba562954f7dreed@google.com } 8599fe287bd07baa6d9e890b627c102bba562954f7dreed@google.com} 8609fe287bd07baa6d9e890b627c102bba562954f7dreed@google.com 8619fe287bd07baa6d9e890b627c102bba562954f7dreed@google.comstatic void check_affine_nofilter(uint32_t bitmapXY[], int count, 8629fe287bd07baa6d9e890b627c102bba562954f7dreed@google.com unsigned mx, unsigned my) { 8639fe287bd07baa6d9e890b627c102bba562954f7dreed@google.com for (int i = 0; i < count; ++i) { 8649fe287bd07baa6d9e890b627c102bba562954f7dreed@google.com uint32_t XY = bitmapXY[i]; 8659fe287bd07baa6d9e890b627c102bba562954f7dreed@google.com unsigned x = XY & 0xFFFF; 8669fe287bd07baa6d9e890b627c102bba562954f7dreed@google.com unsigned y = XY >> 16; 8679fe287bd07baa6d9e890b627c102bba562954f7dreed@google.com SkASSERT(x < mx); 8689fe287bd07baa6d9e890b627c102bba562954f7dreed@google.com SkASSERT(y < my); 8699fe287bd07baa6d9e890b627c102bba562954f7dreed@google.com } 8709fe287bd07baa6d9e890b627c102bba562954f7dreed@google.com} 8719fe287bd07baa6d9e890b627c102bba562954f7dreed@google.com 8729fe287bd07baa6d9e890b627c102bba562954f7dreed@google.comstatic void check_affine_filter(uint32_t bitmapXY[], int count, 8739fe287bd07baa6d9e890b627c102bba562954f7dreed@google.com unsigned mx, unsigned my) { 8749fe287bd07baa6d9e890b627c102bba562954f7dreed@google.com for (int i = 0; i < count; ++i) { 8759fe287bd07baa6d9e890b627c102bba562954f7dreed@google.com uint32_t YY = *bitmapXY++; 8769fe287bd07baa6d9e890b627c102bba562954f7dreed@google.com unsigned y0 = YY >> 18; 8779fe287bd07baa6d9e890b627c102bba562954f7dreed@google.com unsigned y1 = YY & 0x3FFF; 8789fe287bd07baa6d9e890b627c102bba562954f7dreed@google.com SkASSERT(y0 < my); 8799fe287bd07baa6d9e890b627c102bba562954f7dreed@google.com SkASSERT(y1 < my); 8809fe287bd07baa6d9e890b627c102bba562954f7dreed@google.com 8819fe287bd07baa6d9e890b627c102bba562954f7dreed@google.com uint32_t XX = *bitmapXY++; 8829fe287bd07baa6d9e890b627c102bba562954f7dreed@google.com unsigned x0 = XX >> 18; 8839fe287bd07baa6d9e890b627c102bba562954f7dreed@google.com unsigned x1 = XX & 0x3FFF; 8849fe287bd07baa6d9e890b627c102bba562954f7dreed@google.com SkASSERT(x0 < mx); 8859fe287bd07baa6d9e890b627c102bba562954f7dreed@google.com SkASSERT(x1 < mx); 8869fe287bd07baa6d9e890b627c102bba562954f7dreed@google.com } 8879fe287bd07baa6d9e890b627c102bba562954f7dreed@google.com} 8889fe287bd07baa6d9e890b627c102bba562954f7dreed@google.com 8899fe287bd07baa6d9e890b627c102bba562954f7dreed@google.comvoid SkBitmapProcState::DebugMatrixProc(const SkBitmapProcState& state, 8909fe287bd07baa6d9e890b627c102bba562954f7dreed@google.com uint32_t bitmapXY[], int count, 8919fe287bd07baa6d9e890b627c102bba562954f7dreed@google.com int x, int y) { 8929fe287bd07baa6d9e890b627c102bba562954f7dreed@google.com SkASSERT(bitmapXY); 8939fe287bd07baa6d9e890b627c102bba562954f7dreed@google.com SkASSERT(count > 0); 8949fe287bd07baa6d9e890b627c102bba562954f7dreed@google.com 8959fe287bd07baa6d9e890b627c102bba562954f7dreed@google.com state.fMatrixProc(state, bitmapXY, count, x, y); 8969fe287bd07baa6d9e890b627c102bba562954f7dreed@google.com 8979fe287bd07baa6d9e890b627c102bba562954f7dreed@google.com void (*proc)(uint32_t bitmapXY[], int count, unsigned mx, unsigned my); 8989fe287bd07baa6d9e890b627c102bba562954f7dreed@google.com 8999fe287bd07baa6d9e890b627c102bba562954f7dreed@google.com // There are four formats possible: 9009fe287bd07baa6d9e890b627c102bba562954f7dreed@google.com // scale -vs- affine 9019fe287bd07baa6d9e890b627c102bba562954f7dreed@google.com // filter -vs- nofilter 9029fe287bd07baa6d9e890b627c102bba562954f7dreed@google.com if (state.fInvType <= (SkMatrix::kTranslate_Mask | SkMatrix::kScale_Mask)) { 9039cfc83cc8ac2ee50a7ce889e65a707941f48bdeareed@google.com proc = state.fFilterLevel != SkPaint::kNone_FilterLevel ? check_scale_filter : check_scale_nofilter; 9049fe287bd07baa6d9e890b627c102bba562954f7dreed@google.com } else { 9059cfc83cc8ac2ee50a7ce889e65a707941f48bdeareed@google.com proc = state.fFilterLevel != SkPaint::kNone_FilterLevel ? check_affine_filter : check_affine_nofilter; 9069fe287bd07baa6d9e890b627c102bba562954f7dreed@google.com } 9079fe287bd07baa6d9e890b627c102bba562954f7dreed@google.com proc(bitmapXY, count, state.fBitmap->width(), state.fBitmap->height()); 9089fe287bd07baa6d9e890b627c102bba562954f7dreed@google.com} 9099fe287bd07baa6d9e890b627c102bba562954f7dreed@google.com 9109fe287bd07baa6d9e890b627c102bba562954f7dreed@google.comSkBitmapProcState::MatrixProc SkBitmapProcState::getMatrixProc() const { 9119fe287bd07baa6d9e890b627c102bba562954f7dreed@google.com return DebugMatrixProc; 9129fe287bd07baa6d9e890b627c102bba562954f7dreed@google.com} 9139fe287bd07baa6d9e890b627c102bba562954f7dreed@google.com 9149fe287bd07baa6d9e890b627c102bba562954f7dreed@google.com#endif 9159fe287bd07baa6d9e890b627c102bba562954f7dreed@google.com 9169fe287bd07baa6d9e890b627c102bba562954f7dreed@google.com/////////////////////////////////////////////////////////////////////////////// 9174c128c4917acf25c2cc5d1bd22282a4e1bb53d96reed@android.com/* 9184c128c4917acf25c2cc5d1bd22282a4e1bb53d96reed@android.com The storage requirements for the different matrix procs are as follows, 9194c128c4917acf25c2cc5d1bd22282a4e1bb53d96reed@android.com where each X or Y is 2 bytes, and N is the number of pixels/elements: 920fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 9214c128c4917acf25c2cc5d1bd22282a4e1bb53d96reed@android.com scale/translate nofilter Y(4bytes) + N * X 9224c128c4917acf25c2cc5d1bd22282a4e1bb53d96reed@android.com affine/perspective nofilter N * (X Y) 9234c128c4917acf25c2cc5d1bd22282a4e1bb53d96reed@android.com scale/translate filter Y Y + N * (X X) 9244c128c4917acf25c2cc5d1bd22282a4e1bb53d96reed@android.com affine/perspective filter N * (Y Y X X) 9254c128c4917acf25c2cc5d1bd22282a4e1bb53d96reed@android.com */ 9264c128c4917acf25c2cc5d1bd22282a4e1bb53d96reed@android.comint SkBitmapProcState::maxCountForBufferSize(size_t bufferSize) const { 9274c128c4917acf25c2cc5d1bd22282a4e1bb53d96reed@android.com int32_t size = static_cast<int32_t>(bufferSize); 9284c128c4917acf25c2cc5d1bd22282a4e1bb53d96reed@android.com 9294c128c4917acf25c2cc5d1bd22282a4e1bb53d96reed@android.com size &= ~3; // only care about 4-byte aligned chunks 9304c128c4917acf25c2cc5d1bd22282a4e1bb53d96reed@android.com if (fInvType <= (SkMatrix::kTranslate_Mask | SkMatrix::kScale_Mask)) { 9314c128c4917acf25c2cc5d1bd22282a4e1bb53d96reed@android.com size -= 4; // the shared Y (or YY) coordinate 9324c128c4917acf25c2cc5d1bd22282a4e1bb53d96reed@android.com if (size < 0) { 9334c128c4917acf25c2cc5d1bd22282a4e1bb53d96reed@android.com size = 0; 9344c128c4917acf25c2cc5d1bd22282a4e1bb53d96reed@android.com } 935258cb228c636282a3e4f4ce87b1017498e207f33reed@android.com size >>= 1; 9364c128c4917acf25c2cc5d1bd22282a4e1bb53d96reed@android.com } else { 937258cb228c636282a3e4f4ce87b1017498e207f33reed@android.com size >>= 2; 9384c128c4917acf25c2cc5d1bd22282a4e1bb53d96reed@android.com } 9394c128c4917acf25c2cc5d1bd22282a4e1bb53d96reed@android.com 9409cfc83cc8ac2ee50a7ce889e65a707941f48bdeareed@google.com if (fFilterLevel != SkPaint::kNone_FilterLevel) { 941258cb228c636282a3e4f4ce87b1017498e207f33reed@android.com size >>= 1; 942258cb228c636282a3e4f4ce87b1017498e207f33reed@android.com } 943258cb228c636282a3e4f4ce87b1017498e207f33reed@android.com 944258cb228c636282a3e4f4ce87b1017498e207f33reed@android.com return size; 9454c128c4917acf25c2cc5d1bd22282a4e1bb53d96reed@android.com} 946