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" 16cee9dcb8377e1f85a7a232822a894464ea6ccddcreed@google.com#include "SkPixelRef.h" 17602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com#include "SkScaledImageCache.h" 18f449156bd00815eae1f1daea436f08068ef0f01ccommit-bot@chromium.org#include "SkImageEncoder.h" 193ada0efdc8de8316df8113ec54ffd1a3f33ecd21digit@google.com 203ada0efdc8de8316df8113ec54ffd1a3f33ecd21digit@google.com#if !SK_ARM_NEON_IS_NONE 213ada0efdc8de8316df8113ec54ffd1a3f33ecd21digit@google.com// These are defined in src/opts/SkBitmapProcState_arm_neon.cpp 223ada0efdc8de8316df8113ec54ffd1a3f33ecd21digit@google.comextern const SkBitmapProcState::SampleProc16 gSkBitmapProcStateSample16_neon[]; 233ada0efdc8de8316df8113ec54ffd1a3f33ecd21digit@google.comextern const SkBitmapProcState::SampleProc32 gSkBitmapProcStateSample32_neon[]; 243ada0efdc8de8316df8113ec54ffd1a3f33ecd21digit@google.comextern void S16_D16_filter_DX_neon(const SkBitmapProcState&, const uint32_t*, int, uint16_t*); 253ada0efdc8de8316df8113ec54ffd1a3f33ecd21digit@google.comextern void Clamp_S16_D16_filter_DX_shaderproc_neon(const SkBitmapProcState&, int, int, uint16_t*, int); 263ada0efdc8de8316df8113ec54ffd1a3f33ecd21digit@google.comextern void Repeat_S16_D16_filter_DX_shaderproc_neon(const SkBitmapProcState&, int, int, uint16_t*, int); 273ada0efdc8de8316df8113ec54ffd1a3f33ecd21digit@google.comextern void SI8_opaque_D32_filter_DX_neon(const SkBitmapProcState&, const uint32_t*, int, SkPMColor*); 283ada0efdc8de8316df8113ec54ffd1a3f33ecd21digit@google.comextern void SI8_opaque_D32_filter_DX_shaderproc_neon(const SkBitmapProcState&, int, int, uint32_t*, int); 293ada0efdc8de8316df8113ec54ffd1a3f33ecd21digit@google.comextern void Clamp_SI8_opaque_D32_filter_DX_shaderproc_neon(const SkBitmapProcState&, int, int, uint32_t*, int); 303ada0efdc8de8316df8113ec54ffd1a3f33ecd21digit@google.com#endif 313ada0efdc8de8316df8113ec54ffd1a3f33ecd21digit@google.com 323ada0efdc8de8316df8113ec54ffd1a3f33ecd21digit@google.com#define NAME_WRAP(x) x 333ada0efdc8de8316df8113ec54ffd1a3f33ecd21digit@google.com#include "SkBitmapProcState_filter.h" 343ada0efdc8de8316df8113ec54ffd1a3f33ecd21digit@google.com#include "SkBitmapProcState_procs.h" 35b577b41c8ec26c21ae599e80a2707d42f03eaa60reed@android.com 36a44b4cc7976b06caf3a3f6b7913c2af92eb32217reed@android.com/////////////////////////////////////////////////////////////////////////////// 37a44b4cc7976b06caf3a3f6b7913c2af92eb32217reed@android.com 38ee056a82ae59373cae01ebbb4edcd3297d7c92cereed@google.com// true iff the matrix contains, at most, scale and translate elements 39ee056a82ae59373cae01ebbb4edcd3297d7c92cereed@google.comstatic bool matrix_only_scale_translate(const SkMatrix& m) { 40ee056a82ae59373cae01ebbb4edcd3297d7c92cereed@google.com return m.getType() <= (SkMatrix::kScale_Mask | SkMatrix::kTranslate_Mask); 41ee056a82ae59373cae01ebbb4edcd3297d7c92cereed@google.com} 42ee056a82ae59373cae01ebbb4edcd3297d7c92cereed@google.com 43c0e88e0d5d1260f81e7f6b66eeabfb25e6b95a4dreed@google.com/** 44c0e88e0d5d1260f81e7f6b66eeabfb25e6b95a4dreed@google.com * For the purposes of drawing bitmaps, if a matrix is "almost" translate 45c0e88e0d5d1260f81e7f6b66eeabfb25e6b95a4dreed@google.com * go ahead and treat it as if it were, so that subsequent code can go fast. 46c0e88e0d5d1260f81e7f6b66eeabfb25e6b95a4dreed@google.com */ 47c0e88e0d5d1260f81e7f6b66eeabfb25e6b95a4dreed@google.comstatic bool just_trans_clamp(const SkMatrix& matrix, const SkBitmap& bitmap) { 48ee056a82ae59373cae01ebbb4edcd3297d7c92cereed@google.com SkASSERT(matrix_only_scale_translate(matrix)); 49ee056a82ae59373cae01ebbb4edcd3297d7c92cereed@google.com 50ee056a82ae59373cae01ebbb4edcd3297d7c92cereed@google.com if (matrix.getType() & SkMatrix::kScale_Mask) { 51ee056a82ae59373cae01ebbb4edcd3297d7c92cereed@google.com SkRect src, dst; 52ee056a82ae59373cae01ebbb4edcd3297d7c92cereed@google.com bitmap.getBounds(&src); 53f707adc4f8b22fd1a59a900b64333480de653c5breed@google.com 54f707adc4f8b22fd1a59a900b64333480de653c5breed@google.com // Can't call mapRect(), since that will fix up inverted rectangles, 55f707adc4f8b22fd1a59a900b64333480de653c5breed@google.com // e.g. when scale is negative, and we don't want to return true for 56f707adc4f8b22fd1a59a900b64333480de653c5breed@google.com // those. 57f707adc4f8b22fd1a59a900b64333480de653c5breed@google.com matrix.mapPoints(SkTCast<SkPoint*>(&dst), 58f707adc4f8b22fd1a59a900b64333480de653c5breed@google.com SkTCast<const SkPoint*>(&src), 59f707adc4f8b22fd1a59a900b64333480de653c5breed@google.com 2); 60ee056a82ae59373cae01ebbb4edcd3297d7c92cereed@google.com 61ee056a82ae59373cae01ebbb4edcd3297d7c92cereed@google.com // Now round all 4 edges to device space, and then compare the device 62ee056a82ae59373cae01ebbb4edcd3297d7c92cereed@google.com // width/height to the original. Note: we must map all 4 and subtract 63ee056a82ae59373cae01ebbb4edcd3297d7c92cereed@google.com // rather than map the "width" and compare, since we care about the 64ee056a82ae59373cae01ebbb4edcd3297d7c92cereed@google.com // phase (in pixel space) that any translate in the matrix might impart. 65ee056a82ae59373cae01ebbb4edcd3297d7c92cereed@google.com SkIRect idst; 66ee056a82ae59373cae01ebbb4edcd3297d7c92cereed@google.com dst.round(&idst); 67ee056a82ae59373cae01ebbb4edcd3297d7c92cereed@google.com return idst.width() == bitmap.width() && idst.height() == bitmap.height(); 68c0e88e0d5d1260f81e7f6b66eeabfb25e6b95a4dreed@google.com } 69c0e88e0d5d1260f81e7f6b66eeabfb25e6b95a4dreed@google.com // if we got here, we're either kTranslate_Mask or identity 70c0e88e0d5d1260f81e7f6b66eeabfb25e6b95a4dreed@google.com return true; 71c0e88e0d5d1260f81e7f6b66eeabfb25e6b95a4dreed@google.com} 72c0e88e0d5d1260f81e7f6b66eeabfb25e6b95a4dreed@google.com 73c0e88e0d5d1260f81e7f6b66eeabfb25e6b95a4dreed@google.comstatic bool just_trans_general(const SkMatrix& matrix) { 74ee056a82ae59373cae01ebbb4edcd3297d7c92cereed@google.com SkASSERT(matrix_only_scale_translate(matrix)); 75c0e88e0d5d1260f81e7f6b66eeabfb25e6b95a4dreed@google.com 76ee056a82ae59373cae01ebbb4edcd3297d7c92cereed@google.com if (matrix.getType() & SkMatrix::kScale_Mask) { 77c0e88e0d5d1260f81e7f6b66eeabfb25e6b95a4dreed@google.com const SkScalar tol = SK_Scalar1 / 32768; 78989a95ea77230e8347da18876e1bd5f39a78ebb5skia.committer@gmail.com 79c0e88e0d5d1260f81e7f6b66eeabfb25e6b95a4dreed@google.com if (!SkScalarNearlyZero(matrix[SkMatrix::kMScaleX] - SK_Scalar1, tol)) { 80c0e88e0d5d1260f81e7f6b66eeabfb25e6b95a4dreed@google.com return false; 81c0e88e0d5d1260f81e7f6b66eeabfb25e6b95a4dreed@google.com } 82c0e88e0d5d1260f81e7f6b66eeabfb25e6b95a4dreed@google.com if (!SkScalarNearlyZero(matrix[SkMatrix::kMScaleY] - SK_Scalar1, tol)) { 83c0e88e0d5d1260f81e7f6b66eeabfb25e6b95a4dreed@google.com return false; 84c0e88e0d5d1260f81e7f6b66eeabfb25e6b95a4dreed@google.com } 85c0e88e0d5d1260f81e7f6b66eeabfb25e6b95a4dreed@google.com } 86c0e88e0d5d1260f81e7f6b66eeabfb25e6b95a4dreed@google.com // if we got here, treat us as either kTranslate_Mask or identity 87c0e88e0d5d1260f81e7f6b66eeabfb25e6b95a4dreed@google.com return true; 88c0e88e0d5d1260f81e7f6b66eeabfb25e6b95a4dreed@google.com} 89c0e88e0d5d1260f81e7f6b66eeabfb25e6b95a4dreed@google.com 90c0e88e0d5d1260f81e7f6b66eeabfb25e6b95a4dreed@google.com/////////////////////////////////////////////////////////////////////////////// 91c0e88e0d5d1260f81e7f6b66eeabfb25e6b95a4dreed@google.com 928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic bool valid_for_filtering(unsigned dimension) { 938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // for filtering, width and height must fit in 14bits, since we use steal 948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // 2 bits from each to store our 4bit subpixel data 958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return (dimension & ~0x3FFF) == 0; 968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 98d94697c21ae479df4190a1afbf08d85ce244a4efreed@google.comstatic SkScalar effective_matrix_scale_sqrd(const SkMatrix& mat) { 999cfc83cc8ac2ee50a7ce889e65a707941f48bdeareed@google.com SkPoint v1, v2; 1005c561cb8d8151d38c69128345106cbf225033a1askia.committer@gmail.com 1019cfc83cc8ac2ee50a7ce889e65a707941f48bdeareed@google.com v1.fX = mat.getScaleX(); 1029cfc83cc8ac2ee50a7ce889e65a707941f48bdeareed@google.com v1.fY = mat.getSkewY(); 1035c561cb8d8151d38c69128345106cbf225033a1askia.committer@gmail.com 1049cfc83cc8ac2ee50a7ce889e65a707941f48bdeareed@google.com v2.fX = mat.getSkewX(); 1059cfc83cc8ac2ee50a7ce889e65a707941f48bdeareed@google.com v2.fY = mat.getScaleY(); 1065c561cb8d8151d38c69128345106cbf225033a1askia.committer@gmail.com 1079cfc83cc8ac2ee50a7ce889e65a707941f48bdeareed@google.com return SkMaxScalar(v1.lengthSqd(), v2.lengthSqd()); 1089cfc83cc8ac2ee50a7ce889e65a707941f48bdeareed@google.com} 1099cfc83cc8ac2ee50a7ce889e65a707941f48bdeareed@google.com 110fa7fd80ec36103351c32a7a1f235a6095110c39creed@google.comclass AutoScaledCacheUnlocker { 111fa7fd80ec36103351c32a7a1f235a6095110c39creed@google.compublic: 112fa7fd80ec36103351c32a7a1f235a6095110c39creed@google.com AutoScaledCacheUnlocker(SkScaledImageCache::ID** idPtr) : fIDPtr(idPtr) {} 113fa7fd80ec36103351c32a7a1f235a6095110c39creed@google.com ~AutoScaledCacheUnlocker() { 114fa7fd80ec36103351c32a7a1f235a6095110c39creed@google.com if (fIDPtr && *fIDPtr) { 115fa7fd80ec36103351c32a7a1f235a6095110c39creed@google.com SkScaledImageCache::Unlock(*fIDPtr); 116fa7fd80ec36103351c32a7a1f235a6095110c39creed@google.com *fIDPtr = NULL; 117fa7fd80ec36103351c32a7a1f235a6095110c39creed@google.com } 118fa7fd80ec36103351c32a7a1f235a6095110c39creed@google.com } 119fa7fd80ec36103351c32a7a1f235a6095110c39creed@google.com 120fa7fd80ec36103351c32a7a1f235a6095110c39creed@google.com // forgets the ID, so it won't call Unlock 121fa7fd80ec36103351c32a7a1f235a6095110c39creed@google.com void release() { 122fa7fd80ec36103351c32a7a1f235a6095110c39creed@google.com fIDPtr = NULL; 123fa7fd80ec36103351c32a7a1f235a6095110c39creed@google.com } 124fa7fd80ec36103351c32a7a1f235a6095110c39creed@google.com 125fa7fd80ec36103351c32a7a1f235a6095110c39creed@google.comprivate: 126fa7fd80ec36103351c32a7a1f235a6095110c39creed@google.com SkScaledImageCache::ID** fIDPtr; 127fa7fd80ec36103351c32a7a1f235a6095110c39creed@google.com}; 128fa7fd80ec36103351c32a7a1f235a6095110c39creed@google.com#define AutoScaledCacheUnlocker(...) SK_REQUIRE_LOCAL_VAR(AutoScaledCacheUnlocker) 129fa7fd80ec36103351c32a7a1f235a6095110c39creed@google.com 1304e4a89dab47d74874d6a79c4b34d89ffbfb386afDerek Sollenberger// Check to see that the size of the bitmap that would be produced by 1314e4a89dab47d74874d6a79c4b34d89ffbfb386afDerek Sollenberger// scaling by the given inverted matrix is less than the maximum allowed. 1324e4a89dab47d74874d6a79c4b34d89ffbfb386afDerek Sollenbergerstatic inline bool cache_size_okay(const SkBitmap& bm, const SkMatrix& invMat) { 1334e4a89dab47d74874d6a79c4b34d89ffbfb386afDerek Sollenberger size_t maximumAllocation 1344e4a89dab47d74874d6a79c4b34d89ffbfb386afDerek Sollenberger = SkScaledImageCache::GetSingleAllocationByteLimit(); 1354e4a89dab47d74874d6a79c4b34d89ffbfb386afDerek Sollenberger if (0 == maximumAllocation) { 1364e4a89dab47d74874d6a79c4b34d89ffbfb386afDerek Sollenberger return true; 1374e4a89dab47d74874d6a79c4b34d89ffbfb386afDerek Sollenberger } 1384e4a89dab47d74874d6a79c4b34d89ffbfb386afDerek Sollenberger // float matrixScaleFactor = 1.0 / (invMat.scaleX * invMat.scaleY); 1394e4a89dab47d74874d6a79c4b34d89ffbfb386afDerek Sollenberger // return ((origBitmapSize * matrixScaleFactor) < maximumAllocationSize); 1404e4a89dab47d74874d6a79c4b34d89ffbfb386afDerek Sollenberger // Skip the division step: 1414e4a89dab47d74874d6a79c4b34d89ffbfb386afDerek Sollenberger return bm.info().getSafeSize(bm.info().minRowBytes()) 1424e4a89dab47d74874d6a79c4b34d89ffbfb386afDerek Sollenberger < (maximumAllocation * invMat.getScaleX() * invMat.getScaleY()); 1434e4a89dab47d74874d6a79c4b34d89ffbfb386afDerek Sollenberger} 1444e4a89dab47d74874d6a79c4b34d89ffbfb386afDerek Sollenberger 1459c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com// TODO -- we may want to pass the clip into this function so we only scale 1469c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com// the portion of the image that we're going to need. This will complicate 1479c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com// the interface to the cache, but might be well worth it. 1489c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com 149cee9dcb8377e1f85a7a232822a894464ea6ccddcreed@google.combool SkBitmapProcState::possiblyScaleImage() { 150fa7fd80ec36103351c32a7a1f235a6095110c39creed@google.com AutoScaledCacheUnlocker unlocker(&fScaledCacheID); 151fa7fd80ec36103351c32a7a1f235a6095110c39creed@google.com 152cee9dcb8377e1f85a7a232822a894464ea6ccddcreed@google.com SkASSERT(NULL == fBitmap); 153cee9dcb8377e1f85a7a232822a894464ea6ccddcreed@google.com SkASSERT(NULL == fScaledCacheID); 1549c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com 1559cfc83cc8ac2ee50a7ce889e65a707941f48bdeareed@google.com if (fFilterLevel <= SkPaint::kLow_FilterLevel) { 156cee9dcb8377e1f85a7a232822a894464ea6ccddcreed@google.com return false; 1579c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com } 1581f3c73825b8a1752abc6b74fbce978a430de6473skia.committer@gmail.com // Check to see if the transformation matrix is simple, and if we're 1591f3c73825b8a1752abc6b74fbce978a430de6473skia.committer@gmail.com // doing high quality scaling. If so, do the bitmap scale here and 160138ebc3e4061cf533ea2f7f3717239670fdc6e43humper@google.com // remove the scaling component from the matrix. 161138ebc3e4061cf533ea2f7f3717239670fdc6e43humper@google.com 1629cfc83cc8ac2ee50a7ce889e65a707941f48bdeareed@google.com if (SkPaint::kHigh_FilterLevel == fFilterLevel && 163138ebc3e4061cf533ea2f7f3717239670fdc6e43humper@google.com fInvMatrix.getType() <= (SkMatrix::kScale_Mask | SkMatrix::kTranslate_Mask) && 1644e4a89dab47d74874d6a79c4b34d89ffbfb386afDerek Sollenberger kN32_SkColorType == fOrigBitmap.colorType() && 1654e4a89dab47d74874d6a79c4b34d89ffbfb386afDerek Sollenberger cache_size_okay(fOrigBitmap, fInvMatrix)) { 1661f3c73825b8a1752abc6b74fbce978a430de6473skia.committer@gmail.com 167602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com SkScalar invScaleX = fInvMatrix.getScaleX(); 168602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com SkScalar invScaleY = fInvMatrix.getScaleY(); 1697f1af501f206da48a7ff791af53432c9c1c89d08skia.committer@gmail.com 170602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com fScaledCacheID = SkScaledImageCache::FindAndLock(fOrigBitmap, 171602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com invScaleX, invScaleY, 172602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com &fScaledBitmap); 173fa7fd80ec36103351c32a7a1f235a6095110c39creed@google.com if (fScaledCacheID) { 174fa7fd80ec36103351c32a7a1f235a6095110c39creed@google.com fScaledBitmap.lockPixels(); 175fa7fd80ec36103351c32a7a1f235a6095110c39creed@google.com if (!fScaledBitmap.getPixels()) { 176fa7fd80ec36103351c32a7a1f235a6095110c39creed@google.com fScaledBitmap.unlockPixels(); 177fa7fd80ec36103351c32a7a1f235a6095110c39creed@google.com // found a purged entry (discardablememory?), release it 178fa7fd80ec36103351c32a7a1f235a6095110c39creed@google.com SkScaledImageCache::Unlock(fScaledCacheID); 179fa7fd80ec36103351c32a7a1f235a6095110c39creed@google.com fScaledCacheID = NULL; 180fa7fd80ec36103351c32a7a1f235a6095110c39creed@google.com // fall through to rebuild 181fa7fd80ec36103351c32a7a1f235a6095110c39creed@google.com } 182fa7fd80ec36103351c32a7a1f235a6095110c39creed@google.com } 183fa7fd80ec36103351c32a7a1f235a6095110c39creed@google.com 184602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com if (NULL == fScaledCacheID) { 185f449156bd00815eae1f1daea436f08068ef0f01ccommit-bot@chromium.org float dest_width = fOrigBitmap.width() / invScaleX; 186f449156bd00815eae1f1daea436f08068ef0f01ccommit-bot@chromium.org float dest_height = fOrigBitmap.height() / invScaleY; 187f449156bd00815eae1f1daea436f08068ef0f01ccommit-bot@chromium.org 188602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com // All the criteria are met; let's make a new bitmap. 189602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com 190e15d9ecef8ca7a2818b4dc021f7b0dea8a03cb00reed@google.com SkConvolutionProcs simd; 191e15d9ecef8ca7a2818b4dc021f7b0dea8a03cb00reed@google.com sk_bzero(&simd, sizeof(simd)); 192e15d9ecef8ca7a2818b4dc021f7b0dea8a03cb00reed@google.com this->platformConvolutionProcs(&simd); 193e15d9ecef8ca7a2818b4dc021f7b0dea8a03cb00reed@google.com 1941e182253f8358ad1bc46209e84d2b4058f1f16a6reed@google.com if (!SkBitmapScaler::Resize(&fScaledBitmap, 1951e182253f8358ad1bc46209e84d2b4058f1f16a6reed@google.com fOrigBitmap, 1961e182253f8358ad1bc46209e84d2b4058f1f16a6reed@google.com SkBitmapScaler::RESIZE_BEST, 1971e182253f8358ad1bc46209e84d2b4058f1f16a6reed@google.com dest_width, 1981e182253f8358ad1bc46209e84d2b4058f1f16a6reed@google.com dest_height, 199e4eb122a61d7c29f1dd979a41d90524fd249db3freed@google.com simd, 200e4eb122a61d7c29f1dd979a41d90524fd249db3freed@google.com SkScaledImageCache::GetAllocator())) { 2011e182253f8358ad1bc46209e84d2b4058f1f16a6reed@google.com // we failed to create fScaledBitmap, so just return and let 2021e182253f8358ad1bc46209e84d2b4058f1f16a6reed@google.com // the scanline proc handle it. 20323d0ab724129a517ea1bc6cf60830169b524f3bfreed@google.com return false; 2045c561cb8d8151d38c69128345106cbf225033a1askia.committer@gmail.com 2051e182253f8358ad1bc46209e84d2b4058f1f16a6reed@google.com } 206f449156bd00815eae1f1daea436f08068ef0f01ccommit-bot@chromium.org 207fa7fd80ec36103351c32a7a1f235a6095110c39creed@google.com SkASSERT(NULL != fScaledBitmap.getPixels()); 208602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com fScaledCacheID = SkScaledImageCache::AddAndLock(fOrigBitmap, 209602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com invScaleX, 210602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com invScaleY, 211602a1d70257eb3fcb746d758577f042d8c94f6d9reed@google.com fScaledBitmap); 212fa7fd80ec36103351c32a7a1f235a6095110c39creed@google.com if (!fScaledCacheID) { 213fa7fd80ec36103351c32a7a1f235a6095110c39creed@google.com fScaledBitmap.reset(); 214fa7fd80ec36103351c32a7a1f235a6095110c39creed@google.com return false; 215fa7fd80ec36103351c32a7a1f235a6095110c39creed@google.com } 216fa7fd80ec36103351c32a7a1f235a6095110c39creed@google.com SkASSERT(NULL != fScaledBitmap.getPixels()); 2171ae6c2b0121fd1fcd5b736a810060fc66ed68286reed@google.com } 2181ae6c2b0121fd1fcd5b736a810060fc66ed68286reed@google.com 219fa7fd80ec36103351c32a7a1f235a6095110c39creed@google.com SkASSERT(NULL != fScaledBitmap.getPixels()); 2209c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com fBitmap = &fScaledBitmap; 2219c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com 2229c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com // set the inv matrix type to translate-only; 22340039a350bc7c1d650e1f0ba18f17734c5c3ba3ereed@google.com fInvMatrix.setTranslate(fInvMatrix.getTranslateX() / fInvMatrix.getScaleX(), 22440039a350bc7c1d650e1f0ba18f17734c5c3ba3ereed@google.com fInvMatrix.getTranslateY() / fInvMatrix.getScaleY()); 2259c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com 2269c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com // no need for any further filtering; we just did it! 2279cfc83cc8ac2ee50a7ce889e65a707941f48bdeareed@google.com fFilterLevel = SkPaint::kNone_FilterLevel; 228fa7fd80ec36103351c32a7a1f235a6095110c39creed@google.com unlocker.release(); 229cee9dcb8377e1f85a7a232822a894464ea6ccddcreed@google.com return true; 2309c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com } 2319c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com 2329cfc83cc8ac2ee50a7ce889e65a707941f48bdeareed@google.com /* 2339cfc83cc8ac2ee50a7ce889e65a707941f48bdeareed@google.com * If High, then our special-case for scale-only did not take, and so we 2349cfc83cc8ac2ee50a7ce889e65a707941f48bdeareed@google.com * have to make a choice: 2359cfc83cc8ac2ee50a7ce889e65a707941f48bdeareed@google.com * 1. fall back on mipmaps + bilerp 2369cfc83cc8ac2ee50a7ce889e65a707941f48bdeareed@google.com * 2. fall back on scanline bicubic filter 2379cfc83cc8ac2ee50a7ce889e65a707941f48bdeareed@google.com * For now, we compute the "scale" value from the matrix, and have a 2389cfc83cc8ac2ee50a7ce889e65a707941f48bdeareed@google.com * threshold to decide when bicubic is better, and when mips are better. 2399cfc83cc8ac2ee50a7ce889e65a707941f48bdeareed@google.com * No doubt a fancier decision tree could be used uere. 2409cfc83cc8ac2ee50a7ce889e65a707941f48bdeareed@google.com * 2419cfc83cc8ac2ee50a7ce889e65a707941f48bdeareed@google.com * If Medium, then we just try to build a mipmap and select a level, 2429cfc83cc8ac2ee50a7ce889e65a707941f48bdeareed@google.com * setting the filter-level to kLow to signal that we just need bilerp 2439cfc83cc8ac2ee50a7ce889e65a707941f48bdeareed@google.com * to process the selected level. 2449cfc83cc8ac2ee50a7ce889e65a707941f48bdeareed@google.com */ 2459c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com 2469cfc83cc8ac2ee50a7ce889e65a707941f48bdeareed@google.com SkScalar scaleSqd = effective_matrix_scale_sqrd(fInvMatrix); 2479cfc83cc8ac2ee50a7ce889e65a707941f48bdeareed@google.com 2489cfc83cc8ac2ee50a7ce889e65a707941f48bdeareed@google.com if (SkPaint::kHigh_FilterLevel == fFilterLevel) { 2499cfc83cc8ac2ee50a7ce889e65a707941f48bdeareed@google.com // Set the limit at 0.25 for the CTM... if the CTM is scaling smaller 2509cfc83cc8ac2ee50a7ce889e65a707941f48bdeareed@google.com // than this, then the mipmaps quality may be greater (certainly faster) 2519cfc83cc8ac2ee50a7ce889e65a707941f48bdeareed@google.com // so we only keep High quality if the scale is greater than this. 2529cfc83cc8ac2ee50a7ce889e65a707941f48bdeareed@google.com // 2539cfc83cc8ac2ee50a7ce889e65a707941f48bdeareed@google.com // Since we're dealing with the inverse, we compare against its inverse. 2544b413c8bb123e42ca4b9c7bfa6bc2167283cb84ccommit-bot@chromium.org const SkScalar bicubicLimit = 4.0f; 2559cfc83cc8ac2ee50a7ce889e65a707941f48bdeareed@google.com const SkScalar bicubicLimitSqd = bicubicLimit * bicubicLimit; 2569cfc83cc8ac2ee50a7ce889e65a707941f48bdeareed@google.com if (scaleSqd < bicubicLimitSqd) { // use bicubic scanline 257cee9dcb8377e1f85a7a232822a894464ea6ccddcreed@google.com return false; 2589cfc83cc8ac2ee50a7ce889e65a707941f48bdeareed@google.com } 2599c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com 2609cfc83cc8ac2ee50a7ce889e65a707941f48bdeareed@google.com // else set the filter-level to Medium, since we're scaling down and 2619cfc83cc8ac2ee50a7ce889e65a707941f48bdeareed@google.com // want to reqeust mipmaps 2629cfc83cc8ac2ee50a7ce889e65a707941f48bdeareed@google.com fFilterLevel = SkPaint::kMedium_FilterLevel; 2639cfc83cc8ac2ee50a7ce889e65a707941f48bdeareed@google.com } 2645c561cb8d8151d38c69128345106cbf225033a1askia.committer@gmail.com 2659cfc83cc8ac2ee50a7ce889e65a707941f48bdeareed@google.com SkASSERT(SkPaint::kMedium_FilterLevel == fFilterLevel); 2669c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com 2679cfc83cc8ac2ee50a7ce889e65a707941f48bdeareed@google.com /** 2689cfc83cc8ac2ee50a7ce889e65a707941f48bdeareed@google.com * Medium quality means use a mipmap for down-scaling, and just bilper 2699cfc83cc8ac2ee50a7ce889e65a707941f48bdeareed@google.com * for upscaling. Since we're examining the inverse matrix, we look for 2709cfc83cc8ac2ee50a7ce889e65a707941f48bdeareed@google.com * a scale > 1 to indicate down scaling by the CTM. 2719cfc83cc8ac2ee50a7ce889e65a707941f48bdeareed@google.com */ 2729cfc83cc8ac2ee50a7ce889e65a707941f48bdeareed@google.com if (scaleSqd > SK_Scalar1) { 273d94697c21ae479df4190a1afbf08d85ce244a4efreed@google.com const SkMipMap* mip = NULL; 274d94697c21ae479df4190a1afbf08d85ce244a4efreed@google.com 275d94697c21ae479df4190a1afbf08d85ce244a4efreed@google.com SkASSERT(NULL == fScaledCacheID); 276d94697c21ae479df4190a1afbf08d85ce244a4efreed@google.com fScaledCacheID = SkScaledImageCache::FindAndLockMip(fOrigBitmap, &mip); 277d94697c21ae479df4190a1afbf08d85ce244a4efreed@google.com if (!fScaledCacheID) { 278d94697c21ae479df4190a1afbf08d85ce244a4efreed@google.com SkASSERT(NULL == mip); 279d94697c21ae479df4190a1afbf08d85ce244a4efreed@google.com mip = SkMipMap::Build(fOrigBitmap); 280d94697c21ae479df4190a1afbf08d85ce244a4efreed@google.com if (mip) { 281d94697c21ae479df4190a1afbf08d85ce244a4efreed@google.com fScaledCacheID = SkScaledImageCache::AddAndLockMip(fOrigBitmap, 282d94697c21ae479df4190a1afbf08d85ce244a4efreed@google.com mip); 28384f7a06ff926eeddd2fb753795359f3b39a0c0ebcommit-bot@chromium.org SkASSERT(mip->getRefCnt() > 1); 284d94697c21ae479df4190a1afbf08d85ce244a4efreed@google.com mip->unref(); // the cache took a ref 285d94697c21ae479df4190a1afbf08d85ce244a4efreed@google.com SkASSERT(fScaledCacheID); 286d94697c21ae479df4190a1afbf08d85ce244a4efreed@google.com } 287d94697c21ae479df4190a1afbf08d85ce244a4efreed@google.com } else { 288d94697c21ae479df4190a1afbf08d85ce244a4efreed@google.com SkASSERT(mip); 2899c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com } 2905c561cb8d8151d38c69128345106cbf225033a1askia.committer@gmail.com 291d94697c21ae479df4190a1afbf08d85ce244a4efreed@google.com if (mip) { 292d94697c21ae479df4190a1afbf08d85ce244a4efreed@google.com SkScalar levelScale = SkScalarInvert(SkScalarSqrt(scaleSqd)); 293d94697c21ae479df4190a1afbf08d85ce244a4efreed@google.com SkMipMap::Level level; 294d94697c21ae479df4190a1afbf08d85ce244a4efreed@google.com if (mip->extractLevel(levelScale, &level)) { 295d94697c21ae479df4190a1afbf08d85ce244a4efreed@google.com SkScalar invScaleFixup = level.fScale; 296d94697c21ae479df4190a1afbf08d85ce244a4efreed@google.com fInvMatrix.postScale(invScaleFixup, invScaleFixup); 2975c561cb8d8151d38c69128345106cbf225033a1askia.committer@gmail.com 298cba73780bbd12fd254229517aec04fcbf0b64b52commit-bot@chromium.org SkImageInfo info = fOrigBitmap.info(); 299cba73780bbd12fd254229517aec04fcbf0b64b52commit-bot@chromium.org info.fWidth = level.fWidth; 300cba73780bbd12fd254229517aec04fcbf0b64b52commit-bot@chromium.org info.fHeight = level.fHeight; 301cba73780bbd12fd254229517aec04fcbf0b64b52commit-bot@chromium.org fScaledBitmap.installPixels(info, level.fPixels, level.fRowBytes); 3029cfc83cc8ac2ee50a7ce889e65a707941f48bdeareed@google.com fBitmap = &fScaledBitmap; 303cee9dcb8377e1f85a7a232822a894464ea6ccddcreed@google.com fFilterLevel = SkPaint::kLow_FilterLevel; 304fa7fd80ec36103351c32a7a1f235a6095110c39creed@google.com unlocker.release(); 305cee9dcb8377e1f85a7a232822a894464ea6ccddcreed@google.com return true; 3069cfc83cc8ac2ee50a7ce889e65a707941f48bdeareed@google.com } 3079c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com } 3089c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com } 3099cfc83cc8ac2ee50a7ce889e65a707941f48bdeareed@google.com 310cee9dcb8377e1f85a7a232822a894464ea6ccddcreed@google.com return false; 311cee9dcb8377e1f85a7a232822a894464ea6ccddcreed@google.com} 312cee9dcb8377e1f85a7a232822a894464ea6ccddcreed@google.com 313cee9dcb8377e1f85a7a232822a894464ea6ccddcreed@google.comstatic bool get_locked_pixels(const SkBitmap& src, int pow2, SkBitmap* dst) { 314cee9dcb8377e1f85a7a232822a894464ea6ccddcreed@google.com SkPixelRef* pr = src.pixelRef(); 315cee9dcb8377e1f85a7a232822a894464ea6ccddcreed@google.com if (pr && pr->decodeInto(pow2, dst)) { 316cee9dcb8377e1f85a7a232822a894464ea6ccddcreed@google.com return true; 317cee9dcb8377e1f85a7a232822a894464ea6ccddcreed@google.com } 318cee9dcb8377e1f85a7a232822a894464ea6ccddcreed@google.com 319d94697c21ae479df4190a1afbf08d85ce244a4efreed@google.com /* 320cee9dcb8377e1f85a7a232822a894464ea6ccddcreed@google.com * If decodeInto() fails, it is possibe that we have an old subclass that 321cee9dcb8377e1f85a7a232822a894464ea6ccddcreed@google.com * does not, or cannot, implement that. In that case we fall back to the 322cee9dcb8377e1f85a7a232822a894464ea6ccddcreed@google.com * older protocol of having the pixelRef handle the caching for us. 323d94697c21ae479df4190a1afbf08d85ce244a4efreed@google.com */ 324cee9dcb8377e1f85a7a232822a894464ea6ccddcreed@google.com *dst = src; 325cee9dcb8377e1f85a7a232822a894464ea6ccddcreed@google.com dst->lockPixels(); 326cee9dcb8377e1f85a7a232822a894464ea6ccddcreed@google.com return SkToBool(dst->getPixels()); 327cee9dcb8377e1f85a7a232822a894464ea6ccddcreed@google.com} 328cee9dcb8377e1f85a7a232822a894464ea6ccddcreed@google.com 329cee9dcb8377e1f85a7a232822a894464ea6ccddcreed@google.combool SkBitmapProcState::lockBaseBitmap() { 330fa7fd80ec36103351c32a7a1f235a6095110c39creed@google.com AutoScaledCacheUnlocker unlocker(&fScaledCacheID); 331fa7fd80ec36103351c32a7a1f235a6095110c39creed@google.com 332cee9dcb8377e1f85a7a232822a894464ea6ccddcreed@google.com SkPixelRef* pr = fOrigBitmap.pixelRef(); 333cee9dcb8377e1f85a7a232822a894464ea6ccddcreed@google.com 334fa7fd80ec36103351c32a7a1f235a6095110c39creed@google.com SkASSERT(NULL == fScaledCacheID); 335fa7fd80ec36103351c32a7a1f235a6095110c39creed@google.com 336cee9dcb8377e1f85a7a232822a894464ea6ccddcreed@google.com if (pr->isLocked() || !pr->implementsDecodeInto()) { 337cee9dcb8377e1f85a7a232822a894464ea6ccddcreed@google.com // fast-case, no need to look in our cache 338cee9dcb8377e1f85a7a232822a894464ea6ccddcreed@google.com fScaledBitmap = fOrigBitmap; 339fa7fd80ec36103351c32a7a1f235a6095110c39creed@google.com fScaledBitmap.lockPixels(); 340fa7fd80ec36103351c32a7a1f235a6095110c39creed@google.com if (NULL == fScaledBitmap.getPixels()) { 341fa7fd80ec36103351c32a7a1f235a6095110c39creed@google.com return false; 342fa7fd80ec36103351c32a7a1f235a6095110c39creed@google.com } 343cee9dcb8377e1f85a7a232822a894464ea6ccddcreed@google.com } else { 344cee9dcb8377e1f85a7a232822a894464ea6ccddcreed@google.com fScaledCacheID = SkScaledImageCache::FindAndLock(fOrigBitmap, 345cee9dcb8377e1f85a7a232822a894464ea6ccddcreed@google.com SK_Scalar1, SK_Scalar1, 346cee9dcb8377e1f85a7a232822a894464ea6ccddcreed@google.com &fScaledBitmap); 347fa7fd80ec36103351c32a7a1f235a6095110c39creed@google.com if (fScaledCacheID) { 348fa7fd80ec36103351c32a7a1f235a6095110c39creed@google.com fScaledBitmap.lockPixels(); 349fa7fd80ec36103351c32a7a1f235a6095110c39creed@google.com if (!fScaledBitmap.getPixels()) { 350fa7fd80ec36103351c32a7a1f235a6095110c39creed@google.com fScaledBitmap.unlockPixels(); 351fa7fd80ec36103351c32a7a1f235a6095110c39creed@google.com // found a purged entry (discardablememory?), release it 352fa7fd80ec36103351c32a7a1f235a6095110c39creed@google.com SkScaledImageCache::Unlock(fScaledCacheID); 353fa7fd80ec36103351c32a7a1f235a6095110c39creed@google.com fScaledCacheID = NULL; 354fa7fd80ec36103351c32a7a1f235a6095110c39creed@google.com // fall through to rebuild 355fa7fd80ec36103351c32a7a1f235a6095110c39creed@google.com } 356fa7fd80ec36103351c32a7a1f235a6095110c39creed@google.com } 357fa7fd80ec36103351c32a7a1f235a6095110c39creed@google.com 358cee9dcb8377e1f85a7a232822a894464ea6ccddcreed@google.com if (NULL == fScaledCacheID) { 359cee9dcb8377e1f85a7a232822a894464ea6ccddcreed@google.com if (!get_locked_pixels(fOrigBitmap, 0, &fScaledBitmap)) { 360cee9dcb8377e1f85a7a232822a894464ea6ccddcreed@google.com return false; 361cee9dcb8377e1f85a7a232822a894464ea6ccddcreed@google.com } 362cee9dcb8377e1f85a7a232822a894464ea6ccddcreed@google.com 363cee9dcb8377e1f85a7a232822a894464ea6ccddcreed@google.com // TODO: if fScaled comes back at a different width/height than fOrig, 364cee9dcb8377e1f85a7a232822a894464ea6ccddcreed@google.com // we need to update the matrix we are using to sample from this guy. 365cee9dcb8377e1f85a7a232822a894464ea6ccddcreed@google.com 366cee9dcb8377e1f85a7a232822a894464ea6ccddcreed@google.com fScaledCacheID = SkScaledImageCache::AddAndLock(fOrigBitmap, 367cee9dcb8377e1f85a7a232822a894464ea6ccddcreed@google.com SK_Scalar1, SK_Scalar1, 368cee9dcb8377e1f85a7a232822a894464ea6ccddcreed@google.com fScaledBitmap); 369cee9dcb8377e1f85a7a232822a894464ea6ccddcreed@google.com if (!fScaledCacheID) { 370cee9dcb8377e1f85a7a232822a894464ea6ccddcreed@google.com fScaledBitmap.reset(); 371cee9dcb8377e1f85a7a232822a894464ea6ccddcreed@google.com return false; 372cee9dcb8377e1f85a7a232822a894464ea6ccddcreed@google.com } 373cee9dcb8377e1f85a7a232822a894464ea6ccddcreed@google.com } 374cee9dcb8377e1f85a7a232822a894464ea6ccddcreed@google.com } 375cee9dcb8377e1f85a7a232822a894464ea6ccddcreed@google.com fBitmap = &fScaledBitmap; 376fa7fd80ec36103351c32a7a1f235a6095110c39creed@google.com unlocker.release(); 377cee9dcb8377e1f85a7a232822a894464ea6ccddcreed@google.com return true; 3789c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com} 3799c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com 3801e182253f8358ad1bc46209e84d2b4058f1f16a6reed@google.comSkBitmapProcState::~SkBitmapProcState() { 3811e182253f8358ad1bc46209e84d2b4058f1f16a6reed@google.com if (fScaledCacheID) { 3821e182253f8358ad1bc46209e84d2b4058f1f16a6reed@google.com SkScaledImageCache::Unlock(fScaledCacheID); 3831e182253f8358ad1bc46209e84d2b4058f1f16a6reed@google.com } 3841e182253f8358ad1bc46209e84d2b4058f1f16a6reed@google.com SkDELETE(fBitmapFilter); 3859c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com} 3869c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com 3878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.combool SkBitmapProcState::chooseProcs(const SkMatrix& inv, const SkPaint& paint) { 388cee9dcb8377e1f85a7a232822a894464ea6ccddcreed@google.com SkASSERT(fOrigBitmap.width() && fOrigBitmap.height()); 38907d1f008b365e94ef7c7347be19a03d00bd36805reed@android.com 390cee9dcb8377e1f85a7a232822a894464ea6ccddcreed@google.com fBitmap = NULL; 391ef0e3190d3dd4c4e0652c550ac3dbd73762b5322reed@google.com fInvMatrix = inv; 3929cfc83cc8ac2ee50a7ce889e65a707941f48bdeareed@google.com fFilterLevel = paint.getFilterLevel(); 3938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 394fa7fd80ec36103351c32a7a1f235a6095110c39creed@google.com SkASSERT(NULL == fScaledCacheID); 395fa7fd80ec36103351c32a7a1f235a6095110c39creed@google.com 3969c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com // possiblyScaleImage will look to see if it can rescale the image as a 3979c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com // preprocess; either by scaling up to the target size, or by selecting 3989c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com // a nearby mipmap level. If it does, it will adjust the working 3999c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com // matrix as well as the working bitmap. It may also adjust the filter 4009c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com // quality to avoid re-filtering an already perfectly scaled image. 401cee9dcb8377e1f85a7a232822a894464ea6ccddcreed@google.com if (!this->possiblyScaleImage()) { 402cee9dcb8377e1f85a7a232822a894464ea6ccddcreed@google.com if (!this->lockBaseBitmap()) { 403cee9dcb8377e1f85a7a232822a894464ea6ccddcreed@google.com return false; 404cee9dcb8377e1f85a7a232822a894464ea6ccddcreed@google.com } 405cee9dcb8377e1f85a7a232822a894464ea6ccddcreed@google.com } 406c294a97842d6d24b220e7512a8043b93554ed40ereed@google.com // The above logic should have always assigned fBitmap, but in case it 407c294a97842d6d24b220e7512a8043b93554ed40ereed@google.com // didn't, we check for that now... 40887fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org // TODO(dominikg): Ask humper@ if we can just use an SkASSERT(fBitmap)? 409c294a97842d6d24b220e7512a8043b93554ed40ereed@google.com if (NULL == fBitmap) { 410c294a97842d6d24b220e7512a8043b93554ed40ereed@google.com return false; 411c294a97842d6d24b220e7512a8043b93554ed40ereed@google.com } 4129c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com 41384f7a06ff926eeddd2fb753795359f3b39a0c0ebcommit-bot@chromium.org // If we are "still" kMedium_FilterLevel, then the request was not fulfilled by possiblyScale, 41484f7a06ff926eeddd2fb753795359f3b39a0c0ebcommit-bot@chromium.org // so we downgrade to kLow (so the rest of the sniffing code can assume that) 41584f7a06ff926eeddd2fb753795359f3b39a0c0ebcommit-bot@chromium.org if (SkPaint::kMedium_FilterLevel == fFilterLevel) { 41684f7a06ff926eeddd2fb753795359f3b39a0c0ebcommit-bot@chromium.org fFilterLevel = SkPaint::kLow_FilterLevel; 41784f7a06ff926eeddd2fb753795359f3b39a0c0ebcommit-bot@chromium.org } 41884f7a06ff926eeddd2fb753795359f3b39a0c0ebcommit-bot@chromium.org 419ef0e3190d3dd4c4e0652c550ac3dbd73762b5322reed@google.com bool trivialMatrix = (fInvMatrix.getType() & ~SkMatrix::kTranslate_Mask) == 0; 420ef0e3190d3dd4c4e0652c550ac3dbd73762b5322reed@google.com bool clampClamp = SkShader::kClamp_TileMode == fTileModeX && 421ef0e3190d3dd4c4e0652c550ac3dbd73762b5322reed@google.com SkShader::kClamp_TileMode == fTileModeY; 4229a070f24f1450091dfe25cacec8bd375ec7a0e50skia.committer@gmail.com 423ef0e3190d3dd4c4e0652c550ac3dbd73762b5322reed@google.com if (!(clampClamp || trivialMatrix)) { 424ef0e3190d3dd4c4e0652c550ac3dbd73762b5322reed@google.com fInvMatrix.postIDiv(fOrigBitmap.width(), fOrigBitmap.height()); 425ef0e3190d3dd4c4e0652c550ac3dbd73762b5322reed@google.com } 426ef0e3190d3dd4c4e0652c550ac3dbd73762b5322reed@google.com 4279c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com // Now that all possible changes to the matrix have taken place, check 4289c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com // to see if we're really close to a no-scale matrix. If so, explicitly 4299c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com // set it to be so. Subsequent code may inspect this matrix to choose 4309c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com // a faster path in this case. 4319c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com 4329c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com // This code will only execute if the matrix has some scale component; 4339c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com // if it's already pure translate then we won't do this inversion. 4349c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com 4359c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com if (matrix_only_scale_translate(fInvMatrix)) { 436ee056a82ae59373cae01ebbb4edcd3297d7c92cereed@google.com SkMatrix forward; 4379c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com if (fInvMatrix.invert(&forward)) { 4389c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com if (clampClamp ? just_trans_clamp(forward, *fBitmap) 439ee056a82ae59373cae01ebbb4edcd3297d7c92cereed@google.com : just_trans_general(forward)) { 440ce1f3cc1e22a50caaaaded7b91d9492b3ae5901creed@google.com SkScalar tx = -SkScalarRoundToScalar(forward.getTranslateX()); 441ce1f3cc1e22a50caaaaded7b91d9492b3ae5901creed@google.com SkScalar ty = -SkScalarRoundToScalar(forward.getTranslateY()); 4429c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com fInvMatrix.setTranslate(tx, ty); 443ce1f3cc1e22a50caaaaded7b91d9492b3ae5901creed@google.com } 444c0e88e0d5d1260f81e7f6b66eeabfb25e6b95a4dreed@google.com } 445c0e88e0d5d1260f81e7f6b66eeabfb25e6b95a4dreed@google.com } 446c0e88e0d5d1260f81e7f6b66eeabfb25e6b95a4dreed@google.com 4479c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com fInvProc = fInvMatrix.getMapXYProc(); 4489c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com fInvType = fInvMatrix.getType(); 4499c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com fInvSx = SkScalarToFixed(fInvMatrix.getScaleX()); 4509c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com fInvSxFractionalInt = SkScalarToFractionalInt(fInvMatrix.getScaleX()); 4519c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com fInvKy = SkScalarToFixed(fInvMatrix.getSkewY()); 4529c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com fInvKyFractionalInt = SkScalarToFractionalInt(fInvMatrix.getSkewY()); 4538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 4548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fAlphaScale = SkAlpha255To256(paint.getAlpha()); 455fa1bd5f86ceea6cfa8303594730125ad2853d87bskia.committer@gmail.com 4567a99eb1c63d4327d352af09ea59f039f014e4028reed@android.com fShaderProc32 = NULL; 4577a99eb1c63d4327d352af09ea59f039f014e4028reed@android.com fShaderProc16 = NULL; 4587a99eb1c63d4327d352af09ea59f039f014e4028reed@android.com fSampleProc32 = NULL; 4597a99eb1c63d4327d352af09ea59f039f014e4028reed@android.com fSampleProc16 = NULL; 460fa1bd5f86ceea6cfa8303594730125ad2853d87bskia.committer@gmail.com 4619c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com // recompute the triviality of the matrix here because we may have 4629c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com // changed it! 4639c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com 4649c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com trivialMatrix = (fInvMatrix.getType() & ~SkMatrix::kTranslate_Mask) == 0; 4659c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com 4669cfc83cc8ac2ee50a7ce889e65a707941f48bdeareed@google.com if (SkPaint::kHigh_FilterLevel == fFilterLevel) { 4679c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com // If this is still set, that means we wanted HQ sampling 4689c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com // but couldn't do it as a preprocess. Let's try to install 4699c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com // the scanline version of the HQ sampler. If that process fails, 4709c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com // downgrade to bilerp. 4719c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com 4729c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com // NOTE: Might need to be careful here in the future when we want 4739c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com // to have the platform proc have a shot at this; it's possible that 4749c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com // the chooseBitmapFilterProc will fail to install a shader but a 4759c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com // platform-specific one might succeed, so it might be premature here 4769c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com // to fall back to bilerp. This needs thought. 4779c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com 4780dc546c37c7dff3885188054d191cf852d899e32mtklein@google.com if (!this->setBitmapFilterProcs()) { 4799cfc83cc8ac2ee50a7ce889e65a707941f48bdeareed@google.com fFilterLevel = SkPaint::kLow_FilterLevel; 4809c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com } 4819c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com } 4829c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com 4839cfc83cc8ac2ee50a7ce889e65a707941f48bdeareed@google.com if (SkPaint::kLow_FilterLevel == fFilterLevel) { 4849c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com // Only try bilerp if the matrix is "interesting" and 4859c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com // the image has a suitable size. 4869c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com 4879c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com if (fInvType <= SkMatrix::kTranslate_Mask || 4889cfc83cc8ac2ee50a7ce889e65a707941f48bdeareed@google.com !valid_for_filtering(fBitmap->width() | fBitmap->height())) { 4899cfc83cc8ac2ee50a7ce889e65a707941f48bdeareed@google.com fFilterLevel = SkPaint::kNone_FilterLevel; 4909c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com } 4919c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com } 4929c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com 4939c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com // At this point, we know exactly what kind of sampling the per-scanline 4949c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com // shader will perform. 4959c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com 4969c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com fMatrixProc = this->chooseMatrixProc(trivialMatrix); 49787fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org // TODO(dominikg): SkASSERT(fMatrixProc) instead? chooseMatrixProc never returns NULL. 4988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (NULL == fMatrixProc) { 4998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return false; 5008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 5018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 5028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com /////////////////////////////////////////////////////////////////////// 503fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 5049c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com // No need to do this if we're doing HQ sampling; if filter quality is 5059c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com // still set to HQ by the time we get here, then we must have installed 5060dc546c37c7dff3885188054d191cf852d899e32mtklein@google.com // the shader procs above and can skip all this. 5078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 5089cfc83cc8ac2ee50a7ce889e65a707941f48bdeareed@google.com if (fFilterLevel < SkPaint::kHigh_FilterLevel) { 509fa1bd5f86ceea6cfa8303594730125ad2853d87bskia.committer@gmail.com 5109c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com int index = 0; 5119c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com if (fAlphaScale < 256) { // note: this distinction is not used for D16 5129c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com index |= 1; 5139c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com } 5149c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com if (fInvType <= (SkMatrix::kTranslate_Mask | SkMatrix::kScale_Mask)) { 5159c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com index |= 2; 5169c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com } 5179cfc83cc8ac2ee50a7ce889e65a707941f48bdeareed@google.com if (fFilterLevel > SkPaint::kNone_FilterLevel) { 5189c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com index |= 4; 5199c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com } 5209c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com // bits 3,4,5 encoding the source bitmap format 521cba73780bbd12fd254229517aec04fcbf0b64b52commit-bot@chromium.org switch (fBitmap->colorType()) { 522cba73780bbd12fd254229517aec04fcbf0b64b52commit-bot@chromium.org case kN32_SkColorType: 5239c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com index |= 0; 5249c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com break; 525cba73780bbd12fd254229517aec04fcbf0b64b52commit-bot@chromium.org case kRGB_565_SkColorType: 5269c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com index |= 8; 5279c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com break; 528cba73780bbd12fd254229517aec04fcbf0b64b52commit-bot@chromium.org case kIndex_8_SkColorType: 5299c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com index |= 16; 5309c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com break; 531cba73780bbd12fd254229517aec04fcbf0b64b52commit-bot@chromium.org case kARGB_4444_SkColorType: 5329c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com index |= 24; 5339c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com break; 534cba73780bbd12fd254229517aec04fcbf0b64b52commit-bot@chromium.org case kAlpha_8_SkColorType: 5359c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com index |= 32; 5369c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com fPaintPMColor = SkPreMultiplyColor(paint.getColor()); 5379c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com break; 5389c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com default: 53987fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org // TODO(dominikg): Should we ever get here? SkASSERT(false) instead? 5409c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com return false; 541aa9152abbca3a958a9379f4e5067a1c37486d677reed@android.com } 542c9a1d4b519c2db8e43e54fef068c46462d2f8a4breed@android.com 5439c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com #if !SK_ARM_NEON_IS_ALWAYS 5449c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com static const SampleProc32 gSkBitmapProcStateSample32[] = { 5459c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com S32_opaque_D32_nofilter_DXDY, 5469c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com S32_alpha_D32_nofilter_DXDY, 5479c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com S32_opaque_D32_nofilter_DX, 5489c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com S32_alpha_D32_nofilter_DX, 5499c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com S32_opaque_D32_filter_DXDY, 5509c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com S32_alpha_D32_filter_DXDY, 5519c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com S32_opaque_D32_filter_DX, 5529c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com S32_alpha_D32_filter_DX, 5539c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com 5549c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com S16_opaque_D32_nofilter_DXDY, 5559c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com S16_alpha_D32_nofilter_DXDY, 5569c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com S16_opaque_D32_nofilter_DX, 5579c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com S16_alpha_D32_nofilter_DX, 5589c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com S16_opaque_D32_filter_DXDY, 5599c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com S16_alpha_D32_filter_DXDY, 5609c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com S16_opaque_D32_filter_DX, 5619c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com S16_alpha_D32_filter_DX, 5629c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com 5639c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com SI8_opaque_D32_nofilter_DXDY, 5649c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com SI8_alpha_D32_nofilter_DXDY, 5659c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com SI8_opaque_D32_nofilter_DX, 5669c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com SI8_alpha_D32_nofilter_DX, 5679c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com SI8_opaque_D32_filter_DXDY, 5689c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com SI8_alpha_D32_filter_DXDY, 5699c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com SI8_opaque_D32_filter_DX, 5709c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com SI8_alpha_D32_filter_DX, 5719c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com 5729c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com S4444_opaque_D32_nofilter_DXDY, 5739c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com S4444_alpha_D32_nofilter_DXDY, 5749c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com S4444_opaque_D32_nofilter_DX, 5759c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com S4444_alpha_D32_nofilter_DX, 5769c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com S4444_opaque_D32_filter_DXDY, 5779c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com S4444_alpha_D32_filter_DXDY, 5789c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com S4444_opaque_D32_filter_DX, 5799c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com S4444_alpha_D32_filter_DX, 5809c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com 5819c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com // A8 treats alpha/opaque the same (equally efficient) 5829c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com SA8_alpha_D32_nofilter_DXDY, 5839c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com SA8_alpha_D32_nofilter_DXDY, 5849c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com SA8_alpha_D32_nofilter_DX, 5859c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com SA8_alpha_D32_nofilter_DX, 5869c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com SA8_alpha_D32_filter_DXDY, 5879c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com SA8_alpha_D32_filter_DXDY, 5889c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com SA8_alpha_D32_filter_DX, 5899c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com SA8_alpha_D32_filter_DX 5909c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com }; 5919c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com 5929c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com static const SampleProc16 gSkBitmapProcStateSample16[] = { 5939c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com S32_D16_nofilter_DXDY, 5949c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com S32_D16_nofilter_DX, 5959c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com S32_D16_filter_DXDY, 5969c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com S32_D16_filter_DX, 5979c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com 5989c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com S16_D16_nofilter_DXDY, 5999c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com S16_D16_nofilter_DX, 6009c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com S16_D16_filter_DXDY, 6019c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com S16_D16_filter_DX, 6029c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com 6039c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com SI8_D16_nofilter_DXDY, 6049c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com SI8_D16_nofilter_DX, 6059c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com SI8_D16_filter_DXDY, 6069c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com SI8_D16_filter_DX, 6079c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com 6089c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com // Don't support 4444 -> 565 6099c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com NULL, NULL, NULL, NULL, 6109c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com // Don't support A8 -> 565 6119c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com NULL, NULL, NULL, NULL 6129c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com }; 6139c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com #endif 6149c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com 6159c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com fSampleProc32 = SK_ARM_NEON_WRAP(gSkBitmapProcStateSample32)[index]; 6169c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com index >>= 1; // shift away any opaque/alpha distinction 6179c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com fSampleProc16 = SK_ARM_NEON_WRAP(gSkBitmapProcStateSample16)[index]; 6189c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com 6199c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com // our special-case shaderprocs 6209c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com if (SK_ARM_NEON_WRAP(S16_D16_filter_DX) == fSampleProc16) { 6219c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com if (clampClamp) { 6229c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com fShaderProc16 = SK_ARM_NEON_WRAP(Clamp_S16_D16_filter_DX_shaderproc); 6239c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com } else if (SkShader::kRepeat_TileMode == fTileModeX && 6249c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com SkShader::kRepeat_TileMode == fTileModeY) { 6259c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com fShaderProc16 = SK_ARM_NEON_WRAP(Repeat_S16_D16_filter_DX_shaderproc); 6269c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com } 6279c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com } else if (SK_ARM_NEON_WRAP(SI8_opaque_D32_filter_DX) == fSampleProc32 && clampClamp) { 6289c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com fShaderProc32 = SK_ARM_NEON_WRAP(Clamp_SI8_opaque_D32_filter_DX_shaderproc); 6299c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com } 6303e2345a8d56cb76bc43e4421a3e9e3681ecd9ebaskia.committer@gmail.com 6319c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com if (NULL == fShaderProc32) { 6329c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com fShaderProc32 = this->chooseShaderProc32(); 6339c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com } 6341a8940e558ecc91502767525f69339fd45b71bd4humper@google.com } 6351a8940e558ecc91502767525f69339fd45b71bd4humper@google.com 636b088947f27496a9b9dc48a7cfb170f9d59589825humper@google.com // see if our platform has any accelerated overrides 637b088947f27496a9b9dc48a7cfb170f9d59589825humper@google.com this->platformProcs(); 638b088947f27496a9b9dc48a7cfb170f9d59589825humper@google.com 6398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return true; 6408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 6418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 6429a4c746a1f0f91a5be2708a4c2018dfe14f62e48reed@google.comstatic void Clamp_S32_D32_nofilter_trans_shaderproc(const SkBitmapProcState& s, 6439a4c746a1f0f91a5be2708a4c2018dfe14f62e48reed@google.com int x, int y, 6449a4c746a1f0f91a5be2708a4c2018dfe14f62e48reed@google.com SkPMColor* SK_RESTRICT colors, 6459a4c746a1f0f91a5be2708a4c2018dfe14f62e48reed@google.com int count) { 6469a4c746a1f0f91a5be2708a4c2018dfe14f62e48reed@google.com SkASSERT(((s.fInvType & ~SkMatrix::kTranslate_Mask)) == 0); 6479a4c746a1f0f91a5be2708a4c2018dfe14f62e48reed@google.com SkASSERT(s.fInvKy == 0); 6489a4c746a1f0f91a5be2708a4c2018dfe14f62e48reed@google.com SkASSERT(count > 0 && colors != NULL); 6499cfc83cc8ac2ee50a7ce889e65a707941f48bdeareed@google.com SkASSERT(SkPaint::kNone_FilterLevel == s.fFilterLevel); 65020c301bd1aa4578c6d0abb23ac2c72b5fbb436dbskia.committer@gmail.com 6519a4c746a1f0f91a5be2708a4c2018dfe14f62e48reed@google.com const int maxX = s.fBitmap->width() - 1; 652f7698de60e2cfecf84cb84f957e6fe69325fe67freed@google.com const int maxY = s.fBitmap->height() - 1; 653f7698de60e2cfecf84cb84f957e6fe69325fe67freed@google.com int ix = s.fFilterOneX + x; 654f7698de60e2cfecf84cb84f957e6fe69325fe67freed@google.com int iy = SkClampMax(s.fFilterOneY + y, maxY); 655f7698de60e2cfecf84cb84f957e6fe69325fe67freed@google.com#ifdef SK_DEBUG 6569a4c746a1f0f91a5be2708a4c2018dfe14f62e48reed@google.com { 6579a4c746a1f0f91a5be2708a4c2018dfe14f62e48reed@google.com SkPoint pt; 6589c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com s.fInvProc(s.fInvMatrix, SkIntToScalar(x) + SK_ScalarHalf, 6599a4c746a1f0f91a5be2708a4c2018dfe14f62e48reed@google.com SkIntToScalar(y) + SK_ScalarHalf, &pt); 660f7698de60e2cfecf84cb84f957e6fe69325fe67freed@google.com int iy2 = SkClampMax(SkScalarFloorToInt(pt.fY), maxY); 661f7698de60e2cfecf84cb84f957e6fe69325fe67freed@google.com int ix2 = SkScalarFloorToInt(pt.fX); 66220c301bd1aa4578c6d0abb23ac2c72b5fbb436dbskia.committer@gmail.com 663f7698de60e2cfecf84cb84f957e6fe69325fe67freed@google.com SkASSERT(iy == iy2); 664f7698de60e2cfecf84cb84f957e6fe69325fe67freed@google.com SkASSERT(ix == ix2); 6659a4c746a1f0f91a5be2708a4c2018dfe14f62e48reed@google.com } 666f7698de60e2cfecf84cb84f957e6fe69325fe67freed@google.com#endif 667f7698de60e2cfecf84cb84f957e6fe69325fe67freed@google.com const SkPMColor* row = s.fBitmap->getAddr32(0, iy); 66820c301bd1aa4578c6d0abb23ac2c72b5fbb436dbskia.committer@gmail.com 6699a4c746a1f0f91a5be2708a4c2018dfe14f62e48reed@google.com // clamp to the left 6709a4c746a1f0f91a5be2708a4c2018dfe14f62e48reed@google.com if (ix < 0) { 6719a4c746a1f0f91a5be2708a4c2018dfe14f62e48reed@google.com int n = SkMin32(-ix, count); 6729a4c746a1f0f91a5be2708a4c2018dfe14f62e48reed@google.com sk_memset32(colors, row[0], n); 6739a4c746a1f0f91a5be2708a4c2018dfe14f62e48reed@google.com count -= n; 6749a4c746a1f0f91a5be2708a4c2018dfe14f62e48reed@google.com if (0 == count) { 6759a4c746a1f0f91a5be2708a4c2018dfe14f62e48reed@google.com return; 6769a4c746a1f0f91a5be2708a4c2018dfe14f62e48reed@google.com } 6779a4c746a1f0f91a5be2708a4c2018dfe14f62e48reed@google.com colors += n; 6789a4c746a1f0f91a5be2708a4c2018dfe14f62e48reed@google.com SkASSERT(-ix == n); 6799a4c746a1f0f91a5be2708a4c2018dfe14f62e48reed@google.com ix = 0; 6809a4c746a1f0f91a5be2708a4c2018dfe14f62e48reed@google.com } 6819a4c746a1f0f91a5be2708a4c2018dfe14f62e48reed@google.com // copy the middle 6829a4c746a1f0f91a5be2708a4c2018dfe14f62e48reed@google.com if (ix <= maxX) { 6839a4c746a1f0f91a5be2708a4c2018dfe14f62e48reed@google.com int n = SkMin32(maxX - ix + 1, count); 6849a4c746a1f0f91a5be2708a4c2018dfe14f62e48reed@google.com memcpy(colors, row + ix, n * sizeof(SkPMColor)); 6859a4c746a1f0f91a5be2708a4c2018dfe14f62e48reed@google.com count -= n; 6869a4c746a1f0f91a5be2708a4c2018dfe14f62e48reed@google.com if (0 == count) { 6879a4c746a1f0f91a5be2708a4c2018dfe14f62e48reed@google.com return; 6889a4c746a1f0f91a5be2708a4c2018dfe14f62e48reed@google.com } 6899a4c746a1f0f91a5be2708a4c2018dfe14f62e48reed@google.com colors += n; 6909a4c746a1f0f91a5be2708a4c2018dfe14f62e48reed@google.com } 6919a4c746a1f0f91a5be2708a4c2018dfe14f62e48reed@google.com SkASSERT(count > 0); 6929a4c746a1f0f91a5be2708a4c2018dfe14f62e48reed@google.com // clamp to the right 6939a4c746a1f0f91a5be2708a4c2018dfe14f62e48reed@google.com sk_memset32(colors, row[maxX], count); 6949a4c746a1f0f91a5be2708a4c2018dfe14f62e48reed@google.com} 6959a4c746a1f0f91a5be2708a4c2018dfe14f62e48reed@google.com 696a8d99307717c5fe02043969db0566c236a08c313reed@google.comstatic inline int sk_int_mod(int x, int n) { 697a8d99307717c5fe02043969db0566c236a08c313reed@google.com SkASSERT(n > 0); 698a8d99307717c5fe02043969db0566c236a08c313reed@google.com if ((unsigned)x >= (unsigned)n) { 699a8d99307717c5fe02043969db0566c236a08c313reed@google.com if (x < 0) { 700a8d99307717c5fe02043969db0566c236a08c313reed@google.com x = n + ~(~x % n); 701a8d99307717c5fe02043969db0566c236a08c313reed@google.com } else { 702a8d99307717c5fe02043969db0566c236a08c313reed@google.com x = x % n; 703a8d99307717c5fe02043969db0566c236a08c313reed@google.com } 704a8d99307717c5fe02043969db0566c236a08c313reed@google.com } 705a8d99307717c5fe02043969db0566c236a08c313reed@google.com return x; 706a8d99307717c5fe02043969db0566c236a08c313reed@google.com} 707a8d99307717c5fe02043969db0566c236a08c313reed@google.com 7088b8bf4d12ecf8fb340a1362c91a8a57395dd31a3robertphillips@google.comstatic inline int sk_int_mirror(int x, int n) { 7098b8bf4d12ecf8fb340a1362c91a8a57395dd31a3robertphillips@google.com x = sk_int_mod(x, 2 * n); 7108b8bf4d12ecf8fb340a1362c91a8a57395dd31a3robertphillips@google.com if (x >= n) { 7118b8bf4d12ecf8fb340a1362c91a8a57395dd31a3robertphillips@google.com x = n + ~(x - n); 7128b8bf4d12ecf8fb340a1362c91a8a57395dd31a3robertphillips@google.com } 7138b8bf4d12ecf8fb340a1362c91a8a57395dd31a3robertphillips@google.com return x; 7148b8bf4d12ecf8fb340a1362c91a8a57395dd31a3robertphillips@google.com} 7158b8bf4d12ecf8fb340a1362c91a8a57395dd31a3robertphillips@google.com 716a8d99307717c5fe02043969db0566c236a08c313reed@google.comstatic void Repeat_S32_D32_nofilter_trans_shaderproc(const SkBitmapProcState& s, 717a8d99307717c5fe02043969db0566c236a08c313reed@google.com int x, int y, 718a8d99307717c5fe02043969db0566c236a08c313reed@google.com SkPMColor* SK_RESTRICT colors, 719a8d99307717c5fe02043969db0566c236a08c313reed@google.com int count) { 720a8d99307717c5fe02043969db0566c236a08c313reed@google.com SkASSERT(((s.fInvType & ~SkMatrix::kTranslate_Mask)) == 0); 721a8d99307717c5fe02043969db0566c236a08c313reed@google.com SkASSERT(s.fInvKy == 0); 722a8d99307717c5fe02043969db0566c236a08c313reed@google.com SkASSERT(count > 0 && colors != NULL); 7239cfc83cc8ac2ee50a7ce889e65a707941f48bdeareed@google.com SkASSERT(SkPaint::kNone_FilterLevel == s.fFilterLevel); 72420c301bd1aa4578c6d0abb23ac2c72b5fbb436dbskia.committer@gmail.com 725a8d99307717c5fe02043969db0566c236a08c313reed@google.com const int stopX = s.fBitmap->width(); 726a8d99307717c5fe02043969db0566c236a08c313reed@google.com const int stopY = s.fBitmap->height(); 727a8d99307717c5fe02043969db0566c236a08c313reed@google.com int ix = s.fFilterOneX + x; 728a8d99307717c5fe02043969db0566c236a08c313reed@google.com int iy = sk_int_mod(s.fFilterOneY + y, stopY); 729a8d99307717c5fe02043969db0566c236a08c313reed@google.com#ifdef SK_DEBUG 730a8d99307717c5fe02043969db0566c236a08c313reed@google.com { 731a8d99307717c5fe02043969db0566c236a08c313reed@google.com SkPoint pt; 7329c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com s.fInvProc(s.fInvMatrix, SkIntToScalar(x) + SK_ScalarHalf, 733a8d99307717c5fe02043969db0566c236a08c313reed@google.com SkIntToScalar(y) + SK_ScalarHalf, &pt); 734a8d99307717c5fe02043969db0566c236a08c313reed@google.com int iy2 = sk_int_mod(SkScalarFloorToInt(pt.fY), stopY); 735a8d99307717c5fe02043969db0566c236a08c313reed@google.com int ix2 = SkScalarFloorToInt(pt.fX); 73620c301bd1aa4578c6d0abb23ac2c72b5fbb436dbskia.committer@gmail.com 737a8d99307717c5fe02043969db0566c236a08c313reed@google.com SkASSERT(iy == iy2); 738a8d99307717c5fe02043969db0566c236a08c313reed@google.com SkASSERT(ix == ix2); 739a8d99307717c5fe02043969db0566c236a08c313reed@google.com } 740a8d99307717c5fe02043969db0566c236a08c313reed@google.com#endif 741a8d99307717c5fe02043969db0566c236a08c313reed@google.com const SkPMColor* row = s.fBitmap->getAddr32(0, iy); 742a8d99307717c5fe02043969db0566c236a08c313reed@google.com 743a8d99307717c5fe02043969db0566c236a08c313reed@google.com ix = sk_int_mod(ix, stopX); 744a8d99307717c5fe02043969db0566c236a08c313reed@google.com for (;;) { 745a8d99307717c5fe02043969db0566c236a08c313reed@google.com int n = SkMin32(stopX - ix, count); 746a8d99307717c5fe02043969db0566c236a08c313reed@google.com memcpy(colors, row + ix, n * sizeof(SkPMColor)); 747a8d99307717c5fe02043969db0566c236a08c313reed@google.com count -= n; 748a8d99307717c5fe02043969db0566c236a08c313reed@google.com if (0 == count) { 749a8d99307717c5fe02043969db0566c236a08c313reed@google.com return; 750a8d99307717c5fe02043969db0566c236a08c313reed@google.com } 751a8d99307717c5fe02043969db0566c236a08c313reed@google.com colors += n; 752a8d99307717c5fe02043969db0566c236a08c313reed@google.com ix = 0; 753a8d99307717c5fe02043969db0566c236a08c313reed@google.com } 754a8d99307717c5fe02043969db0566c236a08c313reed@google.com} 755a8d99307717c5fe02043969db0566c236a08c313reed@google.com 7568b8bf4d12ecf8fb340a1362c91a8a57395dd31a3robertphillips@google.comstatic void S32_D32_constX_shaderproc(const SkBitmapProcState& s, 7578b8bf4d12ecf8fb340a1362c91a8a57395dd31a3robertphillips@google.com int x, int y, 7588b8bf4d12ecf8fb340a1362c91a8a57395dd31a3robertphillips@google.com SkPMColor* SK_RESTRICT colors, 7598b8bf4d12ecf8fb340a1362c91a8a57395dd31a3robertphillips@google.com int count) { 7608b8bf4d12ecf8fb340a1362c91a8a57395dd31a3robertphillips@google.com SkASSERT((s.fInvType & ~(SkMatrix::kTranslate_Mask | SkMatrix::kScale_Mask)) == 0); 7618b8bf4d12ecf8fb340a1362c91a8a57395dd31a3robertphillips@google.com SkASSERT(s.fInvKy == 0); 7628b8bf4d12ecf8fb340a1362c91a8a57395dd31a3robertphillips@google.com SkASSERT(count > 0 && colors != NULL); 7638b8bf4d12ecf8fb340a1362c91a8a57395dd31a3robertphillips@google.com SkASSERT(1 == s.fBitmap->width()); 7648b8bf4d12ecf8fb340a1362c91a8a57395dd31a3robertphillips@google.com 765ad51132b1b494e9921c500167adc899e6cfc8684scroggo@google.com int iY0; 766ad51132b1b494e9921c500167adc899e6cfc8684scroggo@google.com int iY1 SK_INIT_TO_AVOID_WARNING; 767ad51132b1b494e9921c500167adc899e6cfc8684scroggo@google.com int iSubY SK_INIT_TO_AVOID_WARNING; 7688b8bf4d12ecf8fb340a1362c91a8a57395dd31a3robertphillips@google.com 7699cfc83cc8ac2ee50a7ce889e65a707941f48bdeareed@google.com if (SkPaint::kNone_FilterLevel != s.fFilterLevel) { 7708b8bf4d12ecf8fb340a1362c91a8a57395dd31a3robertphillips@google.com SkBitmapProcState::MatrixProc mproc = s.getMatrixProc(); 7718b8bf4d12ecf8fb340a1362c91a8a57395dd31a3robertphillips@google.com uint32_t xy[2]; 7728b8bf4d12ecf8fb340a1362c91a8a57395dd31a3robertphillips@google.com 7738b8bf4d12ecf8fb340a1362c91a8a57395dd31a3robertphillips@google.com mproc(s, xy, 1, x, y); 7748b8bf4d12ecf8fb340a1362c91a8a57395dd31a3robertphillips@google.com 7758b8bf4d12ecf8fb340a1362c91a8a57395dd31a3robertphillips@google.com iY0 = xy[0] >> 18; 7768b8bf4d12ecf8fb340a1362c91a8a57395dd31a3robertphillips@google.com iY1 = xy[0] & 0x3FFF; 7778b8bf4d12ecf8fb340a1362c91a8a57395dd31a3robertphillips@google.com iSubY = (xy[0] >> 14) & 0xF; 7788b8bf4d12ecf8fb340a1362c91a8a57395dd31a3robertphillips@google.com } else { 7798b8bf4d12ecf8fb340a1362c91a8a57395dd31a3robertphillips@google.com int yTemp; 7808b8bf4d12ecf8fb340a1362c91a8a57395dd31a3robertphillips@google.com 7818b8bf4d12ecf8fb340a1362c91a8a57395dd31a3robertphillips@google.com if (s.fInvType > SkMatrix::kTranslate_Mask) { 7828b8bf4d12ecf8fb340a1362c91a8a57395dd31a3robertphillips@google.com SkPoint pt; 7839c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com s.fInvProc(s.fInvMatrix, 7848b8bf4d12ecf8fb340a1362c91a8a57395dd31a3robertphillips@google.com SkIntToScalar(x) + SK_ScalarHalf, 78536df7ed46b41ac31cb2205bfd3ae37659d61e2fbskia.committer@gmail.com SkIntToScalar(y) + SK_ScalarHalf, 7868b8bf4d12ecf8fb340a1362c91a8a57395dd31a3robertphillips@google.com &pt); 7871e3052354ac155e3d9418cf7e8c8e009df524e01robertphillips@google.com // When the matrix has a scale component the setup code in 78898ded84b80918ac1e40224c125922941f3b2eb03skia.committer@gmail.com // chooseProcs multiples the inverse matrix by the inverse of the 7891e3052354ac155e3d9418cf7e8c8e009df524e01robertphillips@google.com // bitmap's width and height. Since this method is going to do 7901e3052354ac155e3d9418cf7e8c8e009df524e01robertphillips@google.com // its own tiling and sampling we need to undo that here. 791d507775a8be5eca19c1c6212196bf4e56d29bab5robertphillips@google.com if (SkShader::kClamp_TileMode != s.fTileModeX || 792d507775a8be5eca19c1c6212196bf4e56d29bab5robertphillips@google.com SkShader::kClamp_TileMode != s.fTileModeY) { 793d507775a8be5eca19c1c6212196bf4e56d29bab5robertphillips@google.com yTemp = SkScalarFloorToInt(pt.fY * s.fBitmap->height()); 794d507775a8be5eca19c1c6212196bf4e56d29bab5robertphillips@google.com } else { 795d507775a8be5eca19c1c6212196bf4e56d29bab5robertphillips@google.com yTemp = SkScalarFloorToInt(pt.fY); 796d507775a8be5eca19c1c6212196bf4e56d29bab5robertphillips@google.com } 7978b8bf4d12ecf8fb340a1362c91a8a57395dd31a3robertphillips@google.com } else { 7988b8bf4d12ecf8fb340a1362c91a8a57395dd31a3robertphillips@google.com yTemp = s.fFilterOneY + y; 7998b8bf4d12ecf8fb340a1362c91a8a57395dd31a3robertphillips@google.com } 8008b8bf4d12ecf8fb340a1362c91a8a57395dd31a3robertphillips@google.com 8018b8bf4d12ecf8fb340a1362c91a8a57395dd31a3robertphillips@google.com const int stopY = s.fBitmap->height(); 8028b8bf4d12ecf8fb340a1362c91a8a57395dd31a3robertphillips@google.com switch (s.fTileModeY) { 8038b8bf4d12ecf8fb340a1362c91a8a57395dd31a3robertphillips@google.com case SkShader::kClamp_TileMode: 8048b8bf4d12ecf8fb340a1362c91a8a57395dd31a3robertphillips@google.com iY0 = SkClampMax(yTemp, stopY-1); 8058b8bf4d12ecf8fb340a1362c91a8a57395dd31a3robertphillips@google.com break; 8068b8bf4d12ecf8fb340a1362c91a8a57395dd31a3robertphillips@google.com case SkShader::kRepeat_TileMode: 8078b8bf4d12ecf8fb340a1362c91a8a57395dd31a3robertphillips@google.com iY0 = sk_int_mod(yTemp, stopY); 8088b8bf4d12ecf8fb340a1362c91a8a57395dd31a3robertphillips@google.com break; 8098b8bf4d12ecf8fb340a1362c91a8a57395dd31a3robertphillips@google.com case SkShader::kMirror_TileMode: 8108b8bf4d12ecf8fb340a1362c91a8a57395dd31a3robertphillips@google.com default: 8118b8bf4d12ecf8fb340a1362c91a8a57395dd31a3robertphillips@google.com iY0 = sk_int_mirror(yTemp, stopY); 8128b8bf4d12ecf8fb340a1362c91a8a57395dd31a3robertphillips@google.com break; 8138b8bf4d12ecf8fb340a1362c91a8a57395dd31a3robertphillips@google.com } 8148b8bf4d12ecf8fb340a1362c91a8a57395dd31a3robertphillips@google.com 8158b8bf4d12ecf8fb340a1362c91a8a57395dd31a3robertphillips@google.com#ifdef SK_DEBUG 8168b8bf4d12ecf8fb340a1362c91a8a57395dd31a3robertphillips@google.com { 8178b8bf4d12ecf8fb340a1362c91a8a57395dd31a3robertphillips@google.com SkPoint pt; 8189c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com s.fInvProc(s.fInvMatrix, 8198b8bf4d12ecf8fb340a1362c91a8a57395dd31a3robertphillips@google.com SkIntToScalar(x) + SK_ScalarHalf, 82036df7ed46b41ac31cb2205bfd3ae37659d61e2fbskia.committer@gmail.com SkIntToScalar(y) + SK_ScalarHalf, 8218b8bf4d12ecf8fb340a1362c91a8a57395dd31a3robertphillips@google.com &pt); 822d507775a8be5eca19c1c6212196bf4e56d29bab5robertphillips@google.com if (s.fInvType > SkMatrix::kTranslate_Mask && 823d507775a8be5eca19c1c6212196bf4e56d29bab5robertphillips@google.com (SkShader::kClamp_TileMode != s.fTileModeX || 824d507775a8be5eca19c1c6212196bf4e56d29bab5robertphillips@google.com SkShader::kClamp_TileMode != s.fTileModeY)) { 8251e3052354ac155e3d9418cf7e8c8e009df524e01robertphillips@google.com pt.fY *= s.fBitmap->height(); 8261e3052354ac155e3d9418cf7e8c8e009df524e01robertphillips@google.com } 8278b8bf4d12ecf8fb340a1362c91a8a57395dd31a3robertphillips@google.com int iY2; 8288b8bf4d12ecf8fb340a1362c91a8a57395dd31a3robertphillips@google.com 8298b8bf4d12ecf8fb340a1362c91a8a57395dd31a3robertphillips@google.com switch (s.fTileModeY) { 8308b8bf4d12ecf8fb340a1362c91a8a57395dd31a3robertphillips@google.com case SkShader::kClamp_TileMode: 8318b8bf4d12ecf8fb340a1362c91a8a57395dd31a3robertphillips@google.com iY2 = SkClampMax(SkScalarFloorToInt(pt.fY), stopY-1); 8328b8bf4d12ecf8fb340a1362c91a8a57395dd31a3robertphillips@google.com break; 8338b8bf4d12ecf8fb340a1362c91a8a57395dd31a3robertphillips@google.com case SkShader::kRepeat_TileMode: 8348b8bf4d12ecf8fb340a1362c91a8a57395dd31a3robertphillips@google.com iY2 = sk_int_mod(SkScalarFloorToInt(pt.fY), stopY); 8358b8bf4d12ecf8fb340a1362c91a8a57395dd31a3robertphillips@google.com break; 8368b8bf4d12ecf8fb340a1362c91a8a57395dd31a3robertphillips@google.com case SkShader::kMirror_TileMode: 8378b8bf4d12ecf8fb340a1362c91a8a57395dd31a3robertphillips@google.com default: 8388b8bf4d12ecf8fb340a1362c91a8a57395dd31a3robertphillips@google.com iY2 = sk_int_mirror(SkScalarFloorToInt(pt.fY), stopY); 8398b8bf4d12ecf8fb340a1362c91a8a57395dd31a3robertphillips@google.com break; 8408b8bf4d12ecf8fb340a1362c91a8a57395dd31a3robertphillips@google.com } 8418b8bf4d12ecf8fb340a1362c91a8a57395dd31a3robertphillips@google.com 8428b8bf4d12ecf8fb340a1362c91a8a57395dd31a3robertphillips@google.com SkASSERT(iY0 == iY2); 8438b8bf4d12ecf8fb340a1362c91a8a57395dd31a3robertphillips@google.com } 8448b8bf4d12ecf8fb340a1362c91a8a57395dd31a3robertphillips@google.com#endif 8458b8bf4d12ecf8fb340a1362c91a8a57395dd31a3robertphillips@google.com } 8468b8bf4d12ecf8fb340a1362c91a8a57395dd31a3robertphillips@google.com 8478b8bf4d12ecf8fb340a1362c91a8a57395dd31a3robertphillips@google.com const SkPMColor* row0 = s.fBitmap->getAddr32(0, iY0); 8488b8bf4d12ecf8fb340a1362c91a8a57395dd31a3robertphillips@google.com SkPMColor color; 8498b8bf4d12ecf8fb340a1362c91a8a57395dd31a3robertphillips@google.com 8509cfc83cc8ac2ee50a7ce889e65a707941f48bdeareed@google.com if (SkPaint::kNone_FilterLevel != s.fFilterLevel) { 8518b8bf4d12ecf8fb340a1362c91a8a57395dd31a3robertphillips@google.com const SkPMColor* row1 = s.fBitmap->getAddr32(0, iY1); 8528b8bf4d12ecf8fb340a1362c91a8a57395dd31a3robertphillips@google.com 8538b8bf4d12ecf8fb340a1362c91a8a57395dd31a3robertphillips@google.com if (s.fAlphaScale < 256) { 8548b8bf4d12ecf8fb340a1362c91a8a57395dd31a3robertphillips@google.com Filter_32_alpha(iSubY, *row0, *row1, &color, s.fAlphaScale); 8558b8bf4d12ecf8fb340a1362c91a8a57395dd31a3robertphillips@google.com } else { 8568b8bf4d12ecf8fb340a1362c91a8a57395dd31a3robertphillips@google.com Filter_32_opaque(iSubY, *row0, *row1, &color); 8578b8bf4d12ecf8fb340a1362c91a8a57395dd31a3robertphillips@google.com } 8588b8bf4d12ecf8fb340a1362c91a8a57395dd31a3robertphillips@google.com } else { 8598b8bf4d12ecf8fb340a1362c91a8a57395dd31a3robertphillips@google.com if (s.fAlphaScale < 256) { 8608b8bf4d12ecf8fb340a1362c91a8a57395dd31a3robertphillips@google.com color = SkAlphaMulQ(*row0, s.fAlphaScale); 8618b8bf4d12ecf8fb340a1362c91a8a57395dd31a3robertphillips@google.com } else { 8628b8bf4d12ecf8fb340a1362c91a8a57395dd31a3robertphillips@google.com color = *row0; 8638b8bf4d12ecf8fb340a1362c91a8a57395dd31a3robertphillips@google.com } 8648b8bf4d12ecf8fb340a1362c91a8a57395dd31a3robertphillips@google.com } 8658b8bf4d12ecf8fb340a1362c91a8a57395dd31a3robertphillips@google.com 8668b8bf4d12ecf8fb340a1362c91a8a57395dd31a3robertphillips@google.com sk_memset32(colors, color, count); 8678b8bf4d12ecf8fb340a1362c91a8a57395dd31a3robertphillips@google.com} 8688b8bf4d12ecf8fb340a1362c91a8a57395dd31a3robertphillips@google.com 8696bb92bc0b52d31f3ded38927cdefbeb13a3df87areed@google.comstatic void DoNothing_shaderproc(const SkBitmapProcState&, int x, int y, 8706bb92bc0b52d31f3ded38927cdefbeb13a3df87areed@google.com SkPMColor* SK_RESTRICT colors, int count) { 8716bb92bc0b52d31f3ded38927cdefbeb13a3df87areed@google.com // if we get called, the matrix is too tricky, so we just draw nothing 8726bb92bc0b52d31f3ded38927cdefbeb13a3df87areed@google.com sk_memset32(colors, 0, count); 8736bb92bc0b52d31f3ded38927cdefbeb13a3df87areed@google.com} 8746bb92bc0b52d31f3ded38927cdefbeb13a3df87areed@google.com 8756bb92bc0b52d31f3ded38927cdefbeb13a3df87areed@google.combool SkBitmapProcState::setupForTranslate() { 876a8d99307717c5fe02043969db0566c236a08c313reed@google.com SkPoint pt; 8779c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com fInvProc(fInvMatrix, SK_ScalarHalf, SK_ScalarHalf, &pt); 8786bb92bc0b52d31f3ded38927cdefbeb13a3df87areed@google.com 8796bb92bc0b52d31f3ded38927cdefbeb13a3df87areed@google.com /* 8806bb92bc0b52d31f3ded38927cdefbeb13a3df87areed@google.com * if the translate is larger than our ints, we can get random results, or 8816bb92bc0b52d31f3ded38927cdefbeb13a3df87areed@google.com * worse, we might get 0x80000000, which wreaks havoc on us, since we can't 8826bb92bc0b52d31f3ded38927cdefbeb13a3df87areed@google.com * negate it. 8836bb92bc0b52d31f3ded38927cdefbeb13a3df87areed@google.com */ 8846bb92bc0b52d31f3ded38927cdefbeb13a3df87areed@google.com const SkScalar too_big = SkIntToScalar(1 << 30); 8856bb92bc0b52d31f3ded38927cdefbeb13a3df87areed@google.com if (SkScalarAbs(pt.fX) > too_big || SkScalarAbs(pt.fY) > too_big) { 8866bb92bc0b52d31f3ded38927cdefbeb13a3df87areed@google.com return false; 8876bb92bc0b52d31f3ded38927cdefbeb13a3df87areed@google.com } 8886bb92bc0b52d31f3ded38927cdefbeb13a3df87areed@google.com 889a8d99307717c5fe02043969db0566c236a08c313reed@google.com // Since we know we're not filtered, we re-purpose these fields allow 890a8d99307717c5fe02043969db0566c236a08c313reed@google.com // us to go from device -> src coordinates w/ just an integer add, 891a8d99307717c5fe02043969db0566c236a08c313reed@google.com // rather than running through the inverse-matrix 892a8d99307717c5fe02043969db0566c236a08c313reed@google.com fFilterOneX = SkScalarFloorToInt(pt.fX); 893a8d99307717c5fe02043969db0566c236a08c313reed@google.com fFilterOneY = SkScalarFloorToInt(pt.fY); 8946bb92bc0b52d31f3ded38927cdefbeb13a3df87areed@google.com return true; 895a8d99307717c5fe02043969db0566c236a08c313reed@google.com} 896a8d99307717c5fe02043969db0566c236a08c313reed@google.com 8979a4c746a1f0f91a5be2708a4c2018dfe14f62e48reed@google.comSkBitmapProcState::ShaderProc32 SkBitmapProcState::chooseShaderProc32() { 8988b8bf4d12ecf8fb340a1362c91a8a57395dd31a3robertphillips@google.com 899cba73780bbd12fd254229517aec04fcbf0b64b52commit-bot@chromium.org if (kN32_SkColorType != fBitmap->colorType()) { 9008b8bf4d12ecf8fb340a1362c91a8a57395dd31a3robertphillips@google.com return NULL; 9018b8bf4d12ecf8fb340a1362c91a8a57395dd31a3robertphillips@google.com } 9028b8bf4d12ecf8fb340a1362c91a8a57395dd31a3robertphillips@google.com 9038b8bf4d12ecf8fb340a1362c91a8a57395dd31a3robertphillips@google.com static const unsigned kMask = SkMatrix::kTranslate_Mask | SkMatrix::kScale_Mask; 9048b8bf4d12ecf8fb340a1362c91a8a57395dd31a3robertphillips@google.com 9058b8bf4d12ecf8fb340a1362c91a8a57395dd31a3robertphillips@google.com if (1 == fBitmap->width() && 0 == (fInvType & ~kMask)) { 9069cfc83cc8ac2ee50a7ce889e65a707941f48bdeareed@google.com if (SkPaint::kNone_FilterLevel == fFilterLevel && 9079c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com fInvType <= SkMatrix::kTranslate_Mask && 9089c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com !this->setupForTranslate()) { 9098b8bf4d12ecf8fb340a1362c91a8a57395dd31a3robertphillips@google.com return DoNothing_shaderproc; 9108b8bf4d12ecf8fb340a1362c91a8a57395dd31a3robertphillips@google.com } 9118b8bf4d12ecf8fb340a1362c91a8a57395dd31a3robertphillips@google.com return S32_D32_constX_shaderproc; 9128b8bf4d12ecf8fb340a1362c91a8a57395dd31a3robertphillips@google.com } 9138b8bf4d12ecf8fb340a1362c91a8a57395dd31a3robertphillips@google.com 9149a4c746a1f0f91a5be2708a4c2018dfe14f62e48reed@google.com if (fAlphaScale < 256) { 9159a4c746a1f0f91a5be2708a4c2018dfe14f62e48reed@google.com return NULL; 9169a4c746a1f0f91a5be2708a4c2018dfe14f62e48reed@google.com } 9179a4c746a1f0f91a5be2708a4c2018dfe14f62e48reed@google.com if (fInvType > SkMatrix::kTranslate_Mask) { 9189a4c746a1f0f91a5be2708a4c2018dfe14f62e48reed@google.com return NULL; 9199a4c746a1f0f91a5be2708a4c2018dfe14f62e48reed@google.com } 9209cfc83cc8ac2ee50a7ce889e65a707941f48bdeareed@google.com if (SkPaint::kNone_FilterLevel != fFilterLevel) { 9219a4c746a1f0f91a5be2708a4c2018dfe14f62e48reed@google.com return NULL; 9229a4c746a1f0f91a5be2708a4c2018dfe14f62e48reed@google.com } 9239a4c746a1f0f91a5be2708a4c2018dfe14f62e48reed@google.com 924a8d99307717c5fe02043969db0566c236a08c313reed@google.com SkShader::TileMode tx = (SkShader::TileMode)fTileModeX; 925a8d99307717c5fe02043969db0566c236a08c313reed@google.com SkShader::TileMode ty = (SkShader::TileMode)fTileModeY; 926a8d99307717c5fe02043969db0566c236a08c313reed@google.com 927a8d99307717c5fe02043969db0566c236a08c313reed@google.com if (SkShader::kClamp_TileMode == tx && SkShader::kClamp_TileMode == ty) { 9286bb92bc0b52d31f3ded38927cdefbeb13a3df87areed@google.com if (this->setupForTranslate()) { 9296bb92bc0b52d31f3ded38927cdefbeb13a3df87areed@google.com return Clamp_S32_D32_nofilter_trans_shaderproc; 9306bb92bc0b52d31f3ded38927cdefbeb13a3df87areed@google.com } 9316bb92bc0b52d31f3ded38927cdefbeb13a3df87areed@google.com return DoNothing_shaderproc; 9329a4c746a1f0f91a5be2708a4c2018dfe14f62e48reed@google.com } 933a8d99307717c5fe02043969db0566c236a08c313reed@google.com if (SkShader::kRepeat_TileMode == tx && SkShader::kRepeat_TileMode == ty) { 9346bb92bc0b52d31f3ded38927cdefbeb13a3df87areed@google.com if (this->setupForTranslate()) { 9356bb92bc0b52d31f3ded38927cdefbeb13a3df87areed@google.com return Repeat_S32_D32_nofilter_trans_shaderproc; 9366bb92bc0b52d31f3ded38927cdefbeb13a3df87areed@google.com } 9376bb92bc0b52d31f3ded38927cdefbeb13a3df87areed@google.com return DoNothing_shaderproc; 938a8d99307717c5fe02043969db0566c236a08c313reed@google.com } 9399a4c746a1f0f91a5be2708a4c2018dfe14f62e48reed@google.com return NULL; 9409a4c746a1f0f91a5be2708a4c2018dfe14f62e48reed@google.com} 9419a4c746a1f0f91a5be2708a4c2018dfe14f62e48reed@google.com 9424c128c4917acf25c2cc5d1bd22282a4e1bb53d96reed@android.com/////////////////////////////////////////////////////////////////////////////// 9439fe287bd07baa6d9e890b627c102bba562954f7dreed@google.com 9449fe287bd07baa6d9e890b627c102bba562954f7dreed@google.com#ifdef SK_DEBUG 9459fe287bd07baa6d9e890b627c102bba562954f7dreed@google.com 9469fe287bd07baa6d9e890b627c102bba562954f7dreed@google.comstatic void check_scale_nofilter(uint32_t bitmapXY[], int count, 9479fe287bd07baa6d9e890b627c102bba562954f7dreed@google.com unsigned mx, unsigned my) { 9489fe287bd07baa6d9e890b627c102bba562954f7dreed@google.com unsigned y = *bitmapXY++; 9499fe287bd07baa6d9e890b627c102bba562954f7dreed@google.com SkASSERT(y < my); 950fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 9519fe287bd07baa6d9e890b627c102bba562954f7dreed@google.com const uint16_t* xptr = reinterpret_cast<const uint16_t*>(bitmapXY); 9529fe287bd07baa6d9e890b627c102bba562954f7dreed@google.com for (int i = 0; i < count; ++i) { 9539fe287bd07baa6d9e890b627c102bba562954f7dreed@google.com SkASSERT(xptr[i] < mx); 9549fe287bd07baa6d9e890b627c102bba562954f7dreed@google.com } 9559fe287bd07baa6d9e890b627c102bba562954f7dreed@google.com} 9569fe287bd07baa6d9e890b627c102bba562954f7dreed@google.com 9579fe287bd07baa6d9e890b627c102bba562954f7dreed@google.comstatic void check_scale_filter(uint32_t bitmapXY[], int count, 9589fe287bd07baa6d9e890b627c102bba562954f7dreed@google.com unsigned mx, unsigned my) { 9599fe287bd07baa6d9e890b627c102bba562954f7dreed@google.com uint32_t YY = *bitmapXY++; 9609fe287bd07baa6d9e890b627c102bba562954f7dreed@google.com unsigned y0 = YY >> 18; 961fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com unsigned y1 = YY & 0x3FFF; 9629fe287bd07baa6d9e890b627c102bba562954f7dreed@google.com SkASSERT(y0 < my); 9639fe287bd07baa6d9e890b627c102bba562954f7dreed@google.com SkASSERT(y1 < my); 964fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 9659fe287bd07baa6d9e890b627c102bba562954f7dreed@google.com for (int i = 0; i < count; ++i) { 9669fe287bd07baa6d9e890b627c102bba562954f7dreed@google.com uint32_t XX = bitmapXY[i]; 9679fe287bd07baa6d9e890b627c102bba562954f7dreed@google.com unsigned x0 = XX >> 18; 9689fe287bd07baa6d9e890b627c102bba562954f7dreed@google.com unsigned x1 = XX & 0x3FFF; 9699fe287bd07baa6d9e890b627c102bba562954f7dreed@google.com SkASSERT(x0 < mx); 9709fe287bd07baa6d9e890b627c102bba562954f7dreed@google.com SkASSERT(x1 < mx); 9719fe287bd07baa6d9e890b627c102bba562954f7dreed@google.com } 9729fe287bd07baa6d9e890b627c102bba562954f7dreed@google.com} 9739fe287bd07baa6d9e890b627c102bba562954f7dreed@google.com 9749fe287bd07baa6d9e890b627c102bba562954f7dreed@google.comstatic void check_affine_nofilter(uint32_t bitmapXY[], int count, 9759fe287bd07baa6d9e890b627c102bba562954f7dreed@google.com unsigned mx, unsigned my) { 9769fe287bd07baa6d9e890b627c102bba562954f7dreed@google.com for (int i = 0; i < count; ++i) { 9779fe287bd07baa6d9e890b627c102bba562954f7dreed@google.com uint32_t XY = bitmapXY[i]; 9789fe287bd07baa6d9e890b627c102bba562954f7dreed@google.com unsigned x = XY & 0xFFFF; 9799fe287bd07baa6d9e890b627c102bba562954f7dreed@google.com unsigned y = XY >> 16; 9809fe287bd07baa6d9e890b627c102bba562954f7dreed@google.com SkASSERT(x < mx); 9819fe287bd07baa6d9e890b627c102bba562954f7dreed@google.com SkASSERT(y < my); 9829fe287bd07baa6d9e890b627c102bba562954f7dreed@google.com } 9839fe287bd07baa6d9e890b627c102bba562954f7dreed@google.com} 9849fe287bd07baa6d9e890b627c102bba562954f7dreed@google.com 9859fe287bd07baa6d9e890b627c102bba562954f7dreed@google.comstatic void check_affine_filter(uint32_t bitmapXY[], int count, 9869fe287bd07baa6d9e890b627c102bba562954f7dreed@google.com unsigned mx, unsigned my) { 9879fe287bd07baa6d9e890b627c102bba562954f7dreed@google.com for (int i = 0; i < count; ++i) { 9889fe287bd07baa6d9e890b627c102bba562954f7dreed@google.com uint32_t YY = *bitmapXY++; 9899fe287bd07baa6d9e890b627c102bba562954f7dreed@google.com unsigned y0 = YY >> 18; 9909fe287bd07baa6d9e890b627c102bba562954f7dreed@google.com unsigned y1 = YY & 0x3FFF; 9919fe287bd07baa6d9e890b627c102bba562954f7dreed@google.com SkASSERT(y0 < my); 9929fe287bd07baa6d9e890b627c102bba562954f7dreed@google.com SkASSERT(y1 < my); 9939fe287bd07baa6d9e890b627c102bba562954f7dreed@google.com 9949fe287bd07baa6d9e890b627c102bba562954f7dreed@google.com uint32_t XX = *bitmapXY++; 9959fe287bd07baa6d9e890b627c102bba562954f7dreed@google.com unsigned x0 = XX >> 18; 9969fe287bd07baa6d9e890b627c102bba562954f7dreed@google.com unsigned x1 = XX & 0x3FFF; 9979fe287bd07baa6d9e890b627c102bba562954f7dreed@google.com SkASSERT(x0 < mx); 9989fe287bd07baa6d9e890b627c102bba562954f7dreed@google.com SkASSERT(x1 < mx); 9999fe287bd07baa6d9e890b627c102bba562954f7dreed@google.com } 10009fe287bd07baa6d9e890b627c102bba562954f7dreed@google.com} 10019fe287bd07baa6d9e890b627c102bba562954f7dreed@google.com 10029fe287bd07baa6d9e890b627c102bba562954f7dreed@google.comvoid SkBitmapProcState::DebugMatrixProc(const SkBitmapProcState& state, 10039fe287bd07baa6d9e890b627c102bba562954f7dreed@google.com uint32_t bitmapXY[], int count, 10049fe287bd07baa6d9e890b627c102bba562954f7dreed@google.com int x, int y) { 10059fe287bd07baa6d9e890b627c102bba562954f7dreed@google.com SkASSERT(bitmapXY); 10069fe287bd07baa6d9e890b627c102bba562954f7dreed@google.com SkASSERT(count > 0); 10079fe287bd07baa6d9e890b627c102bba562954f7dreed@google.com 10089fe287bd07baa6d9e890b627c102bba562954f7dreed@google.com state.fMatrixProc(state, bitmapXY, count, x, y); 10099fe287bd07baa6d9e890b627c102bba562954f7dreed@google.com 10109fe287bd07baa6d9e890b627c102bba562954f7dreed@google.com void (*proc)(uint32_t bitmapXY[], int count, unsigned mx, unsigned my); 10119fe287bd07baa6d9e890b627c102bba562954f7dreed@google.com 10129fe287bd07baa6d9e890b627c102bba562954f7dreed@google.com // There are four formats possible: 10139fe287bd07baa6d9e890b627c102bba562954f7dreed@google.com // scale -vs- affine 10149fe287bd07baa6d9e890b627c102bba562954f7dreed@google.com // filter -vs- nofilter 10159fe287bd07baa6d9e890b627c102bba562954f7dreed@google.com if (state.fInvType <= (SkMatrix::kTranslate_Mask | SkMatrix::kScale_Mask)) { 10169cfc83cc8ac2ee50a7ce889e65a707941f48bdeareed@google.com proc = state.fFilterLevel != SkPaint::kNone_FilterLevel ? check_scale_filter : check_scale_nofilter; 10179fe287bd07baa6d9e890b627c102bba562954f7dreed@google.com } else { 10189cfc83cc8ac2ee50a7ce889e65a707941f48bdeareed@google.com proc = state.fFilterLevel != SkPaint::kNone_FilterLevel ? check_affine_filter : check_affine_nofilter; 10199fe287bd07baa6d9e890b627c102bba562954f7dreed@google.com } 10209fe287bd07baa6d9e890b627c102bba562954f7dreed@google.com proc(bitmapXY, count, state.fBitmap->width(), state.fBitmap->height()); 10219fe287bd07baa6d9e890b627c102bba562954f7dreed@google.com} 10229fe287bd07baa6d9e890b627c102bba562954f7dreed@google.com 10239fe287bd07baa6d9e890b627c102bba562954f7dreed@google.comSkBitmapProcState::MatrixProc SkBitmapProcState::getMatrixProc() const { 10249fe287bd07baa6d9e890b627c102bba562954f7dreed@google.com return DebugMatrixProc; 10259fe287bd07baa6d9e890b627c102bba562954f7dreed@google.com} 10269fe287bd07baa6d9e890b627c102bba562954f7dreed@google.com 10279fe287bd07baa6d9e890b627c102bba562954f7dreed@google.com#endif 10289fe287bd07baa6d9e890b627c102bba562954f7dreed@google.com 10299fe287bd07baa6d9e890b627c102bba562954f7dreed@google.com/////////////////////////////////////////////////////////////////////////////// 10304c128c4917acf25c2cc5d1bd22282a4e1bb53d96reed@android.com/* 10314c128c4917acf25c2cc5d1bd22282a4e1bb53d96reed@android.com The storage requirements for the different matrix procs are as follows, 10324c128c4917acf25c2cc5d1bd22282a4e1bb53d96reed@android.com where each X or Y is 2 bytes, and N is the number of pixels/elements: 1033fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 10344c128c4917acf25c2cc5d1bd22282a4e1bb53d96reed@android.com scale/translate nofilter Y(4bytes) + N * X 10354c128c4917acf25c2cc5d1bd22282a4e1bb53d96reed@android.com affine/perspective nofilter N * (X Y) 10364c128c4917acf25c2cc5d1bd22282a4e1bb53d96reed@android.com scale/translate filter Y Y + N * (X X) 10374c128c4917acf25c2cc5d1bd22282a4e1bb53d96reed@android.com affine/perspective filter N * (Y Y X X) 10384c128c4917acf25c2cc5d1bd22282a4e1bb53d96reed@android.com */ 10394c128c4917acf25c2cc5d1bd22282a4e1bb53d96reed@android.comint SkBitmapProcState::maxCountForBufferSize(size_t bufferSize) const { 10404c128c4917acf25c2cc5d1bd22282a4e1bb53d96reed@android.com int32_t size = static_cast<int32_t>(bufferSize); 10414c128c4917acf25c2cc5d1bd22282a4e1bb53d96reed@android.com 10424c128c4917acf25c2cc5d1bd22282a4e1bb53d96reed@android.com size &= ~3; // only care about 4-byte aligned chunks 10434c128c4917acf25c2cc5d1bd22282a4e1bb53d96reed@android.com if (fInvType <= (SkMatrix::kTranslate_Mask | SkMatrix::kScale_Mask)) { 10444c128c4917acf25c2cc5d1bd22282a4e1bb53d96reed@android.com size -= 4; // the shared Y (or YY) coordinate 10454c128c4917acf25c2cc5d1bd22282a4e1bb53d96reed@android.com if (size < 0) { 10464c128c4917acf25c2cc5d1bd22282a4e1bb53d96reed@android.com size = 0; 10474c128c4917acf25c2cc5d1bd22282a4e1bb53d96reed@android.com } 1048258cb228c636282a3e4f4ce87b1017498e207f33reed@android.com size >>= 1; 10494c128c4917acf25c2cc5d1bd22282a4e1bb53d96reed@android.com } else { 1050258cb228c636282a3e4f4ce87b1017498e207f33reed@android.com size >>= 2; 10514c128c4917acf25c2cc5d1bd22282a4e1bb53d96reed@android.com } 10524c128c4917acf25c2cc5d1bd22282a4e1bb53d96reed@android.com 10539cfc83cc8ac2ee50a7ce889e65a707941f48bdeareed@google.com if (fFilterLevel != SkPaint::kNone_FilterLevel) { 1054258cb228c636282a3e4f4ce87b1017498e207f33reed@android.com size >>= 1; 1055258cb228c636282a3e4f4ce87b1017498e207f33reed@android.com } 1056258cb228c636282a3e4f4ce87b1017498e207f33reed@android.com 1057258cb228c636282a3e4f4ce87b1017498e207f33reed@android.com return size; 10584c128c4917acf25c2cc5d1bd22282a4e1bb53d96reed@android.com} 1059