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