Upstream version 9.38.198.0
[platform/framework/web/crosswalk.git] / src / third_party / skia / src / core / SkBitmapProcState.cpp
1
2 /*
3  * Copyright 2011 Google Inc.
4  *
5  * Use of this source code is governed by a BSD-style license that can be
6  * found in the LICENSE file.
7  */
8 #include "SkBitmapProcState.h"
9 #include "SkColorPriv.h"
10 #include "SkFilterProc.h"
11 #include "SkPaint.h"
12 #include "SkShader.h"   // for tilemodes
13 #include "SkUtilsArm.h"
14 #include "SkBitmapScaler.h"
15 #include "SkMipMap.h"
16 #include "SkPixelRef.h"
17 #include "SkScaledImageCache.h"
18 #include "SkImageEncoder.h"
19
20 #if !SK_ARM_NEON_IS_NONE
21 // These are defined in src/opts/SkBitmapProcState_arm_neon.cpp
22 extern const SkBitmapProcState::SampleProc16 gSkBitmapProcStateSample16_neon[];
23 extern const SkBitmapProcState::SampleProc32 gSkBitmapProcStateSample32_neon[];
24 extern void  S16_D16_filter_DX_neon(const SkBitmapProcState&, const uint32_t*, int, uint16_t*);
25 extern void  Clamp_S16_D16_filter_DX_shaderproc_neon(const SkBitmapProcState&, int, int, uint16_t*, int);
26 extern void  Repeat_S16_D16_filter_DX_shaderproc_neon(const SkBitmapProcState&, int, int, uint16_t*, int);
27 extern void  SI8_opaque_D32_filter_DX_neon(const SkBitmapProcState&, const uint32_t*, int, SkPMColor*);
28 extern void  SI8_opaque_D32_filter_DX_shaderproc_neon(const SkBitmapProcState&, int, int, uint32_t*, int);
29 extern void  Clamp_SI8_opaque_D32_filter_DX_shaderproc_neon(const SkBitmapProcState&, int, int, uint32_t*, int);
30 #endif
31
32 #define   NAME_WRAP(x)  x
33 #include "SkBitmapProcState_filter.h"
34 #include "SkBitmapProcState_procs.h"
35
36 ///////////////////////////////////////////////////////////////////////////////
37
38 // true iff the matrix contains, at most, scale and translate elements
39 static bool matrix_only_scale_translate(const SkMatrix& m) {
40     return m.getType() <= (SkMatrix::kScale_Mask | SkMatrix::kTranslate_Mask);
41 }
42
43 /**
44  *  For the purposes of drawing bitmaps, if a matrix is "almost" translate
45  *  go ahead and treat it as if it were, so that subsequent code can go fast.
46  */
47 static bool just_trans_clamp(const SkMatrix& matrix, const SkBitmap& bitmap) {
48     SkASSERT(matrix_only_scale_translate(matrix));
49
50     if (matrix.getType() & SkMatrix::kScale_Mask) {
51         SkRect src, dst;
52         bitmap.getBounds(&src);
53
54         // Can't call mapRect(), since that will fix up inverted rectangles,
55         // e.g. when scale is negative, and we don't want to return true for
56         // those.
57         matrix.mapPoints(SkTCast<SkPoint*>(&dst),
58                          SkTCast<const SkPoint*>(&src),
59                          2);
60
61         // Now round all 4 edges to device space, and then compare the device
62         // width/height to the original. Note: we must map all 4 and subtract
63         // rather than map the "width" and compare, since we care about the
64         // phase (in pixel space) that any translate in the matrix might impart.
65         SkIRect idst;
66         dst.round(&idst);
67         return idst.width() == bitmap.width() && idst.height() == bitmap.height();
68     }
69     // if we got here, we're either kTranslate_Mask or identity
70     return true;
71 }
72
73 static bool just_trans_general(const SkMatrix& matrix) {
74     SkASSERT(matrix_only_scale_translate(matrix));
75
76     if (matrix.getType() & SkMatrix::kScale_Mask) {
77         const SkScalar tol = SK_Scalar1 / 32768;
78
79         if (!SkScalarNearlyZero(matrix[SkMatrix::kMScaleX] - SK_Scalar1, tol)) {
80             return false;
81         }
82         if (!SkScalarNearlyZero(matrix[SkMatrix::kMScaleY] - SK_Scalar1, tol)) {
83             return false;
84         }
85     }
86     // if we got here, treat us as either kTranslate_Mask or identity
87     return true;
88 }
89
90 ///////////////////////////////////////////////////////////////////////////////
91
92 static bool valid_for_filtering(unsigned dimension) {
93     // for filtering, width and height must fit in 14bits, since we use steal
94     // 2 bits from each to store our 4bit subpixel data
95     return (dimension & ~0x3FFF) == 0;
96 }
97
98 static SkScalar effective_matrix_scale_sqrd(const SkMatrix& mat) {
99     SkPoint v1, v2;
100
101     v1.fX = mat.getScaleX();
102     v1.fY = mat.getSkewY();
103
104     v2.fX = mat.getSkewX();
105     v2.fY = mat.getScaleY();
106
107     return SkMaxScalar(v1.lengthSqd(), v2.lengthSqd());
108 }
109
110 class AutoScaledCacheUnlocker {
111 public:
112     AutoScaledCacheUnlocker(SkScaledImageCache::ID** idPtr) : fIDPtr(idPtr) {}
113     ~AutoScaledCacheUnlocker() {
114         if (fIDPtr && *fIDPtr) {
115             SkScaledImageCache::Unlock(*fIDPtr);
116             *fIDPtr = NULL;
117         }
118     }
119
120     // forgets the ID, so it won't call Unlock
121     void release() {
122         fIDPtr = NULL;
123     }
124
125 private:
126     SkScaledImageCache::ID** fIDPtr;
127 };
128 #define AutoScaledCacheUnlocker(...) SK_REQUIRE_LOCAL_VAR(AutoScaledCacheUnlocker)
129
130 // Check to see that the size of the bitmap that would be produced by
131 // scaling by the given inverted matrix is less than the maximum allowed.
132 static inline bool cache_size_okay(const SkBitmap& bm, const SkMatrix& invMat) {
133     size_t maximumAllocation
134         = SkScaledImageCache::GetSingleAllocationByteLimit();
135     if (0 == maximumAllocation) {
136         return true;
137     }
138     // float matrixScaleFactor = 1.0 / (invMat.scaleX * invMat.scaleY);
139     // return ((origBitmapSize * matrixScaleFactor) < maximumAllocationSize);
140     // Skip the division step:
141     return bm.info().getSafeSize(bm.info().minRowBytes())
142         < (maximumAllocation * invMat.getScaleX() * invMat.getScaleY());
143 }
144
145 // TODO -- we may want to pass the clip into this function so we only scale
146 // the portion of the image that we're going to need.  This will complicate
147 // the interface to the cache, but might be well worth it.
148
149 bool SkBitmapProcState::possiblyScaleImage() {
150     AutoScaledCacheUnlocker unlocker(&fScaledCacheID);
151
152     SkASSERT(NULL == fBitmap);
153     SkASSERT(NULL == fScaledCacheID);
154
155     if (fFilterLevel <= SkPaint::kLow_FilterLevel) {
156         return false;
157     }
158     // Check to see if the transformation matrix is simple, and if we're
159     // doing high quality scaling.  If so, do the bitmap scale here and
160     // remove the scaling component from the matrix.
161
162     if (SkPaint::kHigh_FilterLevel == fFilterLevel &&
163         fInvMatrix.getType() <= (SkMatrix::kScale_Mask | SkMatrix::kTranslate_Mask) &&
164         kN32_SkColorType == fOrigBitmap.colorType() &&
165         cache_size_okay(fOrigBitmap, fInvMatrix)) {
166
167         SkScalar invScaleX = fInvMatrix.getScaleX();
168         SkScalar invScaleY = fInvMatrix.getScaleY();
169
170         if (SkScalarNearlyEqual(invScaleX,1.0f) &&
171             SkScalarNearlyEqual(invScaleY,1.0f)) {
172             // short-circuit identity scaling; the output is supposed to
173             // be the same as the input, so we might as well go fast.
174
175             // Note(humper): We could also probably do this if the scales
176             // are close to -1 as well, since the flip doesn't require
177             // any fancy re-sampling...
178
179             // Set our filter level to low -- the only post-filtering this
180             // image might require is some interpolation if the translation
181             // is fractional.
182             fFilterLevel = SkPaint::kLow_FilterLevel;
183             return false;
184         }
185
186         fScaledCacheID = SkScaledImageCache::FindAndLock(fOrigBitmap,
187                                                          invScaleX, invScaleY,
188                                                          &fScaledBitmap);
189         if (fScaledCacheID) {
190             fScaledBitmap.lockPixels();
191             if (!fScaledBitmap.getPixels()) {
192                 fScaledBitmap.unlockPixels();
193                 // found a purged entry (discardablememory?), release it
194                 SkScaledImageCache::Unlock(fScaledCacheID);
195                 fScaledCacheID = NULL;
196                 // fall through to rebuild
197             }
198         }
199
200         if (NULL == fScaledCacheID) {
201             float dest_width  = fOrigBitmap.width() / invScaleX;
202             float dest_height = fOrigBitmap.height() / invScaleY;
203
204             // All the criteria are met; let's make a new bitmap.
205
206             if (!SkBitmapScaler::Resize(&fScaledBitmap,
207                                         fOrigBitmap,
208                                         SkBitmapScaler::RESIZE_BEST,
209                                         dest_width,
210                                         dest_height,
211                                         SkScaledImageCache::GetAllocator())) {
212                 // we failed to create fScaledBitmap, so just return and let
213                 // the scanline proc handle it.
214                 return false;
215
216             }
217
218             SkASSERT(NULL != fScaledBitmap.getPixels());
219             fScaledCacheID = SkScaledImageCache::AddAndLock(fOrigBitmap,
220                                                             invScaleX,
221                                                             invScaleY,
222                                                             fScaledBitmap);
223             if (!fScaledCacheID) {
224                 fScaledBitmap.reset();
225                 return false;
226             }
227             SkASSERT(NULL != fScaledBitmap.getPixels());
228         }
229
230         SkASSERT(NULL != fScaledBitmap.getPixels());
231         fBitmap = &fScaledBitmap;
232
233         // set the inv matrix type to translate-only;
234         fInvMatrix.setTranslate(fInvMatrix.getTranslateX() / fInvMatrix.getScaleX(),
235                                 fInvMatrix.getTranslateY() / fInvMatrix.getScaleY());
236
237         // Set our filter level to low -- the only post-filtering this
238         // image might require is some interpolation if the translation
239         // is fractional.
240         fFilterLevel = SkPaint::kLow_FilterLevel;
241         unlocker.release();
242         return true;
243     }
244
245     /*
246      *  If High, then our special-case for scale-only did not take, and so we
247      *  have to make a choice:
248      *      1. fall back on mipmaps + bilerp
249      *      2. fall back on scanline bicubic filter
250      *  For now, we compute the "scale" value from the matrix, and have a
251      *  threshold to decide when bicubic is better, and when mips are better.
252      *  No doubt a fancier decision tree could be used uere.
253      *
254      *  If Medium, then we just try to build a mipmap and select a level,
255      *  setting the filter-level to kLow to signal that we just need bilerp
256      *  to process the selected level.
257      */
258
259     SkScalar scaleSqd = effective_matrix_scale_sqrd(fInvMatrix);
260
261     if (SkPaint::kHigh_FilterLevel == fFilterLevel) {
262         // Set the limit at 0.25 for the CTM... if the CTM is scaling smaller
263         // than this, then the mipmaps quality may be greater (certainly faster)
264         // so we only keep High quality if the scale is greater than this.
265         //
266         // Since we're dealing with the inverse, we compare against its inverse.
267         const SkScalar bicubicLimit = 4.0f;
268         const SkScalar bicubicLimitSqd = bicubicLimit * bicubicLimit;
269         if (scaleSqd < bicubicLimitSqd) {  // use bicubic scanline
270             return false;
271         }
272
273         // else set the filter-level to Medium, since we're scaling down and
274         // want to reqeust mipmaps
275         fFilterLevel = SkPaint::kMedium_FilterLevel;
276     }
277
278     SkASSERT(SkPaint::kMedium_FilterLevel == fFilterLevel);
279
280     /**
281      *  Medium quality means use a mipmap for down-scaling, and just bilper
282      *  for upscaling. Since we're examining the inverse matrix, we look for
283      *  a scale > 1 to indicate down scaling by the CTM.
284      */
285     if (scaleSqd > SK_Scalar1) {
286         const SkMipMap* mip = NULL;
287
288         SkASSERT(NULL == fScaledCacheID);
289         fScaledCacheID = SkScaledImageCache::FindAndLockMip(fOrigBitmap, &mip);
290         if (!fScaledCacheID) {
291             SkASSERT(NULL == mip);
292             mip = SkMipMap::Build(fOrigBitmap);
293             if (mip) {
294                 fScaledCacheID = SkScaledImageCache::AddAndLockMip(fOrigBitmap,
295                                                                    mip);
296                 SkASSERT(mip->getRefCnt() > 1);
297                 mip->unref();   // the cache took a ref
298                 SkASSERT(fScaledCacheID);
299             }
300         } else {
301             SkASSERT(mip);
302         }
303
304         if (mip) {
305             SkScalar levelScale = SkScalarInvert(SkScalarSqrt(scaleSqd));
306             SkMipMap::Level level;
307             if (mip->extractLevel(levelScale, &level)) {
308                 SkScalar invScaleFixup = level.fScale;
309                 fInvMatrix.postScale(invScaleFixup, invScaleFixup);
310
311                 SkImageInfo info = fOrigBitmap.info();
312                 info.fWidth = level.fWidth;
313                 info.fHeight = level.fHeight;
314                 fScaledBitmap.installPixels(info, level.fPixels, level.fRowBytes);
315                 fBitmap = &fScaledBitmap;
316                 fFilterLevel = SkPaint::kLow_FilterLevel;
317                 unlocker.release();
318                 return true;
319             }
320         }
321     }
322
323     return false;
324 }
325
326 static bool get_locked_pixels(const SkBitmap& src, int pow2, SkBitmap* dst) {
327     SkPixelRef* pr = src.pixelRef();
328     if (pr && pr->decodeInto(pow2, dst)) {
329         return true;
330     }
331
332     /*
333      *  If decodeInto() fails, it is possibe that we have an old subclass that
334      *  does not, or cannot, implement that. In that case we fall back to the
335      *  older protocol of having the pixelRef handle the caching for us.
336      */
337     *dst = src;
338     dst->lockPixels();
339     return SkToBool(dst->getPixels());
340 }
341
342 bool SkBitmapProcState::lockBaseBitmap() {
343     AutoScaledCacheUnlocker unlocker(&fScaledCacheID);
344
345     SkPixelRef* pr = fOrigBitmap.pixelRef();
346
347     SkASSERT(NULL == fScaledCacheID);
348
349     if (pr->isLocked() || !pr->implementsDecodeInto()) {
350         // fast-case, no need to look in our cache
351         fScaledBitmap = fOrigBitmap;
352         fScaledBitmap.lockPixels();
353         if (NULL == fScaledBitmap.getPixels()) {
354             return false;
355         }
356     } else {
357         fScaledCacheID = SkScaledImageCache::FindAndLock(fOrigBitmap,
358                                                          SK_Scalar1, SK_Scalar1,
359                                                          &fScaledBitmap);
360         if (fScaledCacheID) {
361             fScaledBitmap.lockPixels();
362             if (!fScaledBitmap.getPixels()) {
363                 fScaledBitmap.unlockPixels();
364                 // found a purged entry (discardablememory?), release it
365                 SkScaledImageCache::Unlock(fScaledCacheID);
366                 fScaledCacheID = NULL;
367                 // fall through to rebuild
368             }
369         }
370
371         if (NULL == fScaledCacheID) {
372             if (!get_locked_pixels(fOrigBitmap, 0, &fScaledBitmap)) {
373                 return false;
374             }
375
376             // TODO: if fScaled comes back at a different width/height than fOrig,
377             // we need to update the matrix we are using to sample from this guy.
378
379             fScaledCacheID = SkScaledImageCache::AddAndLock(fOrigBitmap,
380                                                             SK_Scalar1, SK_Scalar1,
381                                                             fScaledBitmap);
382             if (!fScaledCacheID) {
383                 fScaledBitmap.reset();
384                 return false;
385             }
386         }
387     }
388     fBitmap = &fScaledBitmap;
389     unlocker.release();
390     return true;
391 }
392
393 SkBitmapProcState::~SkBitmapProcState() {
394     if (fScaledCacheID) {
395         SkScaledImageCache::Unlock(fScaledCacheID);
396     }
397     SkDELETE(fBitmapFilter);
398 }
399
400 bool SkBitmapProcState::chooseProcs(const SkMatrix& inv, const SkPaint& paint) {
401     SkASSERT(fOrigBitmap.width() && fOrigBitmap.height());
402
403     fBitmap = NULL;
404     fInvMatrix = inv;
405     fFilterLevel = paint.getFilterLevel();
406
407     SkASSERT(NULL == fScaledCacheID);
408
409     // possiblyScaleImage will look to see if it can rescale the image as a
410     // preprocess; either by scaling up to the target size, or by selecting
411     // a nearby mipmap level.  If it does, it will adjust the working
412     // matrix as well as the working bitmap.  It may also adjust the filter
413     // quality to avoid re-filtering an already perfectly scaled image.
414     if (!this->possiblyScaleImage()) {
415         if (!this->lockBaseBitmap()) {
416             return false;
417         }
418     }
419     // The above logic should have always assigned fBitmap, but in case it
420     // didn't, we check for that now...
421     // TODO(dominikg): Ask humper@ if we can just use an SkASSERT(fBitmap)?
422     if (NULL == fBitmap) {
423         return false;
424     }
425
426     // If we are "still" kMedium_FilterLevel, then the request was not fulfilled by possiblyScale,
427     // so we downgrade to kLow (so the rest of the sniffing code can assume that)
428     if (SkPaint::kMedium_FilterLevel == fFilterLevel) {
429         fFilterLevel = SkPaint::kLow_FilterLevel;
430     }
431
432     bool trivialMatrix = (fInvMatrix.getType() & ~SkMatrix::kTranslate_Mask) == 0;
433     bool clampClamp = SkShader::kClamp_TileMode == fTileModeX &&
434                       SkShader::kClamp_TileMode == fTileModeY;
435
436     if (!(clampClamp || trivialMatrix)) {
437         fInvMatrix.postIDiv(fOrigBitmap.width(), fOrigBitmap.height());
438     }
439
440     // Now that all possible changes to the matrix have taken place, check
441     // to see if we're really close to a no-scale matrix.  If so, explicitly
442     // set it to be so.  Subsequent code may inspect this matrix to choose
443     // a faster path in this case.
444
445     // This code will only execute if the matrix has some scale component;
446     // if it's already pure translate then we won't do this inversion.
447
448     if (matrix_only_scale_translate(fInvMatrix)) {
449         SkMatrix forward;
450         if (fInvMatrix.invert(&forward)) {
451             if (clampClamp ? just_trans_clamp(forward, *fBitmap)
452                             : just_trans_general(forward)) {
453                 SkScalar tx = -SkScalarRoundToScalar(forward.getTranslateX());
454                 SkScalar ty = -SkScalarRoundToScalar(forward.getTranslateY());
455                 fInvMatrix.setTranslate(tx, ty);
456             }
457         }
458     }
459
460     fInvProc        = fInvMatrix.getMapXYProc();
461     fInvType        = fInvMatrix.getType();
462     fInvSx          = SkScalarToFixed(fInvMatrix.getScaleX());
463     fInvSxFractionalInt = SkScalarToFractionalInt(fInvMatrix.getScaleX());
464     fInvKy          = SkScalarToFixed(fInvMatrix.getSkewY());
465     fInvKyFractionalInt = SkScalarToFractionalInt(fInvMatrix.getSkewY());
466
467     fAlphaScale = SkAlpha255To256(paint.getAlpha());
468
469     fShaderProc32 = NULL;
470     fShaderProc16 = NULL;
471     fSampleProc32 = NULL;
472     fSampleProc16 = NULL;
473
474     // recompute the triviality of the matrix here because we may have
475     // changed it!
476
477     trivialMatrix = (fInvMatrix.getType() & ~SkMatrix::kTranslate_Mask) == 0;
478
479     if (SkPaint::kHigh_FilterLevel == fFilterLevel) {
480         // If this is still set, that means we wanted HQ sampling
481         // but couldn't do it as a preprocess.  Let's try to install
482         // the scanline version of the HQ sampler.  If that process fails,
483         // downgrade to bilerp.
484
485         // NOTE: Might need to be careful here in the future when we want
486         // to have the platform proc have a shot at this; it's possible that
487         // the chooseBitmapFilterProc will fail to install a shader but a
488         // platform-specific one might succeed, so it might be premature here
489         // to fall back to bilerp.  This needs thought.
490
491         if (!this->setBitmapFilterProcs()) {
492             fFilterLevel = SkPaint::kLow_FilterLevel;
493         }
494     }
495
496     if (SkPaint::kLow_FilterLevel == fFilterLevel) {
497         // Only try bilerp if the matrix is "interesting" and
498         // the image has a suitable size.
499
500         if (fInvType <= SkMatrix::kTranslate_Mask ||
501                 !valid_for_filtering(fBitmap->width() | fBitmap->height())) {
502             fFilterLevel = SkPaint::kNone_FilterLevel;
503         }
504     }
505
506     // At this point, we know exactly what kind of sampling the per-scanline
507     // shader will perform.
508
509     fMatrixProc = this->chooseMatrixProc(trivialMatrix);
510     // TODO(dominikg): SkASSERT(fMatrixProc) instead? chooseMatrixProc never returns NULL.
511     if (NULL == fMatrixProc) {
512         return false;
513     }
514
515     ///////////////////////////////////////////////////////////////////////
516
517     const SkAlphaType at = fBitmap->alphaType();
518
519     // No need to do this if we're doing HQ sampling; if filter quality is
520     // still set to HQ by the time we get here, then we must have installed
521     // the shader procs above and can skip all this.
522
523     if (fFilterLevel < SkPaint::kHigh_FilterLevel) {
524
525         int index = 0;
526         if (fAlphaScale < 256) {  // note: this distinction is not used for D16
527             index |= 1;
528         }
529         if (fInvType <= (SkMatrix::kTranslate_Mask | SkMatrix::kScale_Mask)) {
530             index |= 2;
531         }
532         if (fFilterLevel > SkPaint::kNone_FilterLevel) {
533             index |= 4;
534         }
535         // bits 3,4,5 encoding the source bitmap format
536         switch (fBitmap->colorType()) {
537             case kN32_SkColorType:
538                 if (kPremul_SkAlphaType != at && kOpaque_SkAlphaType != at) {
539                     return false;
540                 }
541                 index |= 0;
542                 break;
543             case kRGB_565_SkColorType:
544                 index |= 8;
545                 break;
546             case kIndex_8_SkColorType:
547                 if (kPremul_SkAlphaType != at && kOpaque_SkAlphaType != at) {
548                     return false;
549                 }
550                 index |= 16;
551                 break;
552             case kARGB_4444_SkColorType:
553                 if (kPremul_SkAlphaType != at && kOpaque_SkAlphaType != at) {
554                     return false;
555                 }
556                 index |= 24;
557                 break;
558             case kAlpha_8_SkColorType:
559                 index |= 32;
560                 fPaintPMColor = SkPreMultiplyColor(paint.getColor());
561                 break;
562             default:
563                 // TODO(dominikg): Should we ever get here? SkASSERT(false) instead?
564                 return false;
565         }
566
567     #if !SK_ARM_NEON_IS_ALWAYS
568         static const SampleProc32 gSkBitmapProcStateSample32[] = {
569             S32_opaque_D32_nofilter_DXDY,
570             S32_alpha_D32_nofilter_DXDY,
571             S32_opaque_D32_nofilter_DX,
572             S32_alpha_D32_nofilter_DX,
573             S32_opaque_D32_filter_DXDY,
574             S32_alpha_D32_filter_DXDY,
575             S32_opaque_D32_filter_DX,
576             S32_alpha_D32_filter_DX,
577
578             S16_opaque_D32_nofilter_DXDY,
579             S16_alpha_D32_nofilter_DXDY,
580             S16_opaque_D32_nofilter_DX,
581             S16_alpha_D32_nofilter_DX,
582             S16_opaque_D32_filter_DXDY,
583             S16_alpha_D32_filter_DXDY,
584             S16_opaque_D32_filter_DX,
585             S16_alpha_D32_filter_DX,
586
587             SI8_opaque_D32_nofilter_DXDY,
588             SI8_alpha_D32_nofilter_DXDY,
589             SI8_opaque_D32_nofilter_DX,
590             SI8_alpha_D32_nofilter_DX,
591             SI8_opaque_D32_filter_DXDY,
592             SI8_alpha_D32_filter_DXDY,
593             SI8_opaque_D32_filter_DX,
594             SI8_alpha_D32_filter_DX,
595
596             S4444_opaque_D32_nofilter_DXDY,
597             S4444_alpha_D32_nofilter_DXDY,
598             S4444_opaque_D32_nofilter_DX,
599             S4444_alpha_D32_nofilter_DX,
600             S4444_opaque_D32_filter_DXDY,
601             S4444_alpha_D32_filter_DXDY,
602             S4444_opaque_D32_filter_DX,
603             S4444_alpha_D32_filter_DX,
604
605             // A8 treats alpha/opaque the same (equally efficient)
606             SA8_alpha_D32_nofilter_DXDY,
607             SA8_alpha_D32_nofilter_DXDY,
608             SA8_alpha_D32_nofilter_DX,
609             SA8_alpha_D32_nofilter_DX,
610             SA8_alpha_D32_filter_DXDY,
611             SA8_alpha_D32_filter_DXDY,
612             SA8_alpha_D32_filter_DX,
613             SA8_alpha_D32_filter_DX
614         };
615
616         static const SampleProc16 gSkBitmapProcStateSample16[] = {
617             S32_D16_nofilter_DXDY,
618             S32_D16_nofilter_DX,
619             S32_D16_filter_DXDY,
620             S32_D16_filter_DX,
621
622             S16_D16_nofilter_DXDY,
623             S16_D16_nofilter_DX,
624             S16_D16_filter_DXDY,
625             S16_D16_filter_DX,
626
627             SI8_D16_nofilter_DXDY,
628             SI8_D16_nofilter_DX,
629             SI8_D16_filter_DXDY,
630             SI8_D16_filter_DX,
631
632             // Don't support 4444 -> 565
633             NULL, NULL, NULL, NULL,
634             // Don't support A8 -> 565
635             NULL, NULL, NULL, NULL
636         };
637     #endif
638
639         fSampleProc32 = SK_ARM_NEON_WRAP(gSkBitmapProcStateSample32)[index];
640         index >>= 1;    // shift away any opaque/alpha distinction
641         fSampleProc16 = SK_ARM_NEON_WRAP(gSkBitmapProcStateSample16)[index];
642
643         // our special-case shaderprocs
644         if (SK_ARM_NEON_WRAP(S16_D16_filter_DX) == fSampleProc16) {
645             if (clampClamp) {
646                 fShaderProc16 = SK_ARM_NEON_WRAP(Clamp_S16_D16_filter_DX_shaderproc);
647             } else if (SkShader::kRepeat_TileMode == fTileModeX &&
648                        SkShader::kRepeat_TileMode == fTileModeY) {
649                 fShaderProc16 = SK_ARM_NEON_WRAP(Repeat_S16_D16_filter_DX_shaderproc);
650             }
651         } else if (SK_ARM_NEON_WRAP(SI8_opaque_D32_filter_DX) == fSampleProc32 && clampClamp) {
652             fShaderProc32 = SK_ARM_NEON_WRAP(Clamp_SI8_opaque_D32_filter_DX_shaderproc);
653         }
654
655         if (NULL == fShaderProc32) {
656             fShaderProc32 = this->chooseShaderProc32();
657         }
658     }
659
660     // see if our platform has any accelerated overrides
661     this->platformProcs();
662
663     return true;
664 }
665
666 static void Clamp_S32_D32_nofilter_trans_shaderproc(const SkBitmapProcState& s,
667                                                     int x, int y,
668                                                     SkPMColor* SK_RESTRICT colors,
669                                                     int count) {
670     SkASSERT(((s.fInvType & ~SkMatrix::kTranslate_Mask)) == 0);
671     SkASSERT(s.fInvKy == 0);
672     SkASSERT(count > 0 && colors != NULL);
673     SkASSERT(SkPaint::kNone_FilterLevel == s.fFilterLevel);
674
675     const int maxX = s.fBitmap->width() - 1;
676     const int maxY = s.fBitmap->height() - 1;
677     int ix = s.fFilterOneX + x;
678     int iy = SkClampMax(s.fFilterOneY + y, maxY);
679 #ifdef SK_DEBUG
680     {
681         SkPoint pt;
682         s.fInvProc(s.fInvMatrix, SkIntToScalar(x) + SK_ScalarHalf,
683                    SkIntToScalar(y) + SK_ScalarHalf, &pt);
684         int iy2 = SkClampMax(SkScalarFloorToInt(pt.fY), maxY);
685         int ix2 = SkScalarFloorToInt(pt.fX);
686
687         SkASSERT(iy == iy2);
688         SkASSERT(ix == ix2);
689     }
690 #endif
691     const SkPMColor* row = s.fBitmap->getAddr32(0, iy);
692
693     // clamp to the left
694     if (ix < 0) {
695         int n = SkMin32(-ix, count);
696         sk_memset32(colors, row[0], n);
697         count -= n;
698         if (0 == count) {
699             return;
700         }
701         colors += n;
702         SkASSERT(-ix == n);
703         ix = 0;
704     }
705     // copy the middle
706     if (ix <= maxX) {
707         int n = SkMin32(maxX - ix + 1, count);
708         memcpy(colors, row + ix, n * sizeof(SkPMColor));
709         count -= n;
710         if (0 == count) {
711             return;
712         }
713         colors += n;
714     }
715     SkASSERT(count > 0);
716     // clamp to the right
717     sk_memset32(colors, row[maxX], count);
718 }
719
720 static inline int sk_int_mod(int x, int n) {
721     SkASSERT(n > 0);
722     if ((unsigned)x >= (unsigned)n) {
723         if (x < 0) {
724             x = n + ~(~x % n);
725         } else {
726             x = x % n;
727         }
728     }
729     return x;
730 }
731
732 static inline int sk_int_mirror(int x, int n) {
733     x = sk_int_mod(x, 2 * n);
734     if (x >= n) {
735         x = n + ~(x - n);
736     }
737     return x;
738 }
739
740 static void Repeat_S32_D32_nofilter_trans_shaderproc(const SkBitmapProcState& s,
741                                                      int x, int y,
742                                                      SkPMColor* SK_RESTRICT colors,
743                                                      int count) {
744     SkASSERT(((s.fInvType & ~SkMatrix::kTranslate_Mask)) == 0);
745     SkASSERT(s.fInvKy == 0);
746     SkASSERT(count > 0 && colors != NULL);
747     SkASSERT(SkPaint::kNone_FilterLevel == s.fFilterLevel);
748
749     const int stopX = s.fBitmap->width();
750     const int stopY = s.fBitmap->height();
751     int ix = s.fFilterOneX + x;
752     int iy = sk_int_mod(s.fFilterOneY + y, stopY);
753 #ifdef SK_DEBUG
754     {
755         SkPoint pt;
756         s.fInvProc(s.fInvMatrix, SkIntToScalar(x) + SK_ScalarHalf,
757                    SkIntToScalar(y) + SK_ScalarHalf, &pt);
758         int iy2 = sk_int_mod(SkScalarFloorToInt(pt.fY), stopY);
759         int ix2 = SkScalarFloorToInt(pt.fX);
760
761         SkASSERT(iy == iy2);
762         SkASSERT(ix == ix2);
763     }
764 #endif
765     const SkPMColor* row = s.fBitmap->getAddr32(0, iy);
766
767     ix = sk_int_mod(ix, stopX);
768     for (;;) {
769         int n = SkMin32(stopX - ix, count);
770         memcpy(colors, row + ix, n * sizeof(SkPMColor));
771         count -= n;
772         if (0 == count) {
773             return;
774         }
775         colors += n;
776         ix = 0;
777     }
778 }
779
780 static void S32_D32_constX_shaderproc(const SkBitmapProcState& s,
781                                       int x, int y,
782                                       SkPMColor* SK_RESTRICT colors,
783                                       int count) {
784     SkASSERT((s.fInvType & ~(SkMatrix::kTranslate_Mask | SkMatrix::kScale_Mask)) == 0);
785     SkASSERT(s.fInvKy == 0);
786     SkASSERT(count > 0 && colors != NULL);
787     SkASSERT(1 == s.fBitmap->width());
788
789     int iY0;
790     int iY1   SK_INIT_TO_AVOID_WARNING;
791     int iSubY SK_INIT_TO_AVOID_WARNING;
792
793     if (SkPaint::kNone_FilterLevel != s.fFilterLevel) {
794         SkBitmapProcState::MatrixProc mproc = s.getMatrixProc();
795         uint32_t xy[2];
796
797         mproc(s, xy, 1, x, y);
798
799         iY0 = xy[0] >> 18;
800         iY1 = xy[0] & 0x3FFF;
801         iSubY = (xy[0] >> 14) & 0xF;
802     } else {
803         int yTemp;
804
805         if (s.fInvType > SkMatrix::kTranslate_Mask) {
806             SkPoint pt;
807             s.fInvProc(s.fInvMatrix,
808                        SkIntToScalar(x) + SK_ScalarHalf,
809                        SkIntToScalar(y) + SK_ScalarHalf,
810                        &pt);
811             // When the matrix has a scale component the setup code in
812             // chooseProcs multiples the inverse matrix by the inverse of the
813             // bitmap's width and height. Since this method is going to do
814             // its own tiling and sampling we need to undo that here.
815             if (SkShader::kClamp_TileMode != s.fTileModeX ||
816                 SkShader::kClamp_TileMode != s.fTileModeY) {
817                 yTemp = SkScalarFloorToInt(pt.fY * s.fBitmap->height());
818             } else {
819                 yTemp = SkScalarFloorToInt(pt.fY);
820             }
821         } else {
822             yTemp = s.fFilterOneY + y;
823         }
824
825         const int stopY = s.fBitmap->height();
826         switch (s.fTileModeY) {
827             case SkShader::kClamp_TileMode:
828                 iY0 = SkClampMax(yTemp, stopY-1);
829                 break;
830             case SkShader::kRepeat_TileMode:
831                 iY0 = sk_int_mod(yTemp, stopY);
832                 break;
833             case SkShader::kMirror_TileMode:
834             default:
835                 iY0 = sk_int_mirror(yTemp, stopY);
836                 break;
837         }
838
839 #ifdef SK_DEBUG
840         {
841             SkPoint pt;
842             s.fInvProc(s.fInvMatrix,
843                        SkIntToScalar(x) + SK_ScalarHalf,
844                        SkIntToScalar(y) + SK_ScalarHalf,
845                        &pt);
846             if (s.fInvType > SkMatrix::kTranslate_Mask &&
847                 (SkShader::kClamp_TileMode != s.fTileModeX ||
848                  SkShader::kClamp_TileMode != s.fTileModeY)) {
849                 pt.fY *= s.fBitmap->height();
850             }
851             int iY2;
852
853             switch (s.fTileModeY) {
854             case SkShader::kClamp_TileMode:
855                 iY2 = SkClampMax(SkScalarFloorToInt(pt.fY), stopY-1);
856                 break;
857             case SkShader::kRepeat_TileMode:
858                 iY2 = sk_int_mod(SkScalarFloorToInt(pt.fY), stopY);
859                 break;
860             case SkShader::kMirror_TileMode:
861             default:
862                 iY2 = sk_int_mirror(SkScalarFloorToInt(pt.fY), stopY);
863                 break;
864             }
865
866             SkASSERT(iY0 == iY2);
867         }
868 #endif
869     }
870
871     const SkPMColor* row0 = s.fBitmap->getAddr32(0, iY0);
872     SkPMColor color;
873
874     if (SkPaint::kNone_FilterLevel != s.fFilterLevel) {
875         const SkPMColor* row1 = s.fBitmap->getAddr32(0, iY1);
876
877         if (s.fAlphaScale < 256) {
878             Filter_32_alpha(iSubY, *row0, *row1, &color, s.fAlphaScale);
879         } else {
880             Filter_32_opaque(iSubY, *row0, *row1, &color);
881         }
882     } else {
883         if (s.fAlphaScale < 256) {
884             color = SkAlphaMulQ(*row0, s.fAlphaScale);
885         } else {
886             color = *row0;
887         }
888     }
889
890     sk_memset32(colors, color, count);
891 }
892
893 static void DoNothing_shaderproc(const SkBitmapProcState&, int x, int y,
894                                  SkPMColor* SK_RESTRICT colors, int count) {
895     // if we get called, the matrix is too tricky, so we just draw nothing
896     sk_memset32(colors, 0, count);
897 }
898
899 bool SkBitmapProcState::setupForTranslate() {
900     SkPoint pt;
901     fInvProc(fInvMatrix, SK_ScalarHalf, SK_ScalarHalf, &pt);
902
903     /*
904      *  if the translate is larger than our ints, we can get random results, or
905      *  worse, we might get 0x80000000, which wreaks havoc on us, since we can't
906      *  negate it.
907      */
908     const SkScalar too_big = SkIntToScalar(1 << 30);
909     if (SkScalarAbs(pt.fX) > too_big || SkScalarAbs(pt.fY) > too_big) {
910         return false;
911     }
912
913     // Since we know we're not filtered, we re-purpose these fields allow
914     // us to go from device -> src coordinates w/ just an integer add,
915     // rather than running through the inverse-matrix
916     fFilterOneX = SkScalarFloorToInt(pt.fX);
917     fFilterOneY = SkScalarFloorToInt(pt.fY);
918     return true;
919 }
920
921 SkBitmapProcState::ShaderProc32 SkBitmapProcState::chooseShaderProc32() {
922
923     if (kN32_SkColorType != fBitmap->colorType()) {
924         return NULL;
925     }
926
927     static const unsigned kMask = SkMatrix::kTranslate_Mask | SkMatrix::kScale_Mask;
928
929     if (1 == fBitmap->width() && 0 == (fInvType & ~kMask)) {
930         if (SkPaint::kNone_FilterLevel == fFilterLevel &&
931             fInvType <= SkMatrix::kTranslate_Mask &&
932             !this->setupForTranslate()) {
933             return DoNothing_shaderproc;
934         }
935         return S32_D32_constX_shaderproc;
936     }
937
938     if (fAlphaScale < 256) {
939         return NULL;
940     }
941     if (fInvType > SkMatrix::kTranslate_Mask) {
942         return NULL;
943     }
944     if (SkPaint::kNone_FilterLevel != fFilterLevel) {
945         return NULL;
946     }
947
948     SkShader::TileMode tx = (SkShader::TileMode)fTileModeX;
949     SkShader::TileMode ty = (SkShader::TileMode)fTileModeY;
950
951     if (SkShader::kClamp_TileMode == tx && SkShader::kClamp_TileMode == ty) {
952         if (this->setupForTranslate()) {
953             return Clamp_S32_D32_nofilter_trans_shaderproc;
954         }
955         return DoNothing_shaderproc;
956     }
957     if (SkShader::kRepeat_TileMode == tx && SkShader::kRepeat_TileMode == ty) {
958         if (this->setupForTranslate()) {
959             return Repeat_S32_D32_nofilter_trans_shaderproc;
960         }
961         return DoNothing_shaderproc;
962     }
963     return NULL;
964 }
965
966 ///////////////////////////////////////////////////////////////////////////////
967
968 #ifdef SK_DEBUG
969
970 static void check_scale_nofilter(uint32_t bitmapXY[], int count,
971                                  unsigned mx, unsigned my) {
972     unsigned y = *bitmapXY++;
973     SkASSERT(y < my);
974
975     const uint16_t* xptr = reinterpret_cast<const uint16_t*>(bitmapXY);
976     for (int i = 0; i < count; ++i) {
977         SkASSERT(xptr[i] < mx);
978     }
979 }
980
981 static void check_scale_filter(uint32_t bitmapXY[], int count,
982                                  unsigned mx, unsigned my) {
983     uint32_t YY = *bitmapXY++;
984     unsigned y0 = YY >> 18;
985     unsigned y1 = YY & 0x3FFF;
986     SkASSERT(y0 < my);
987     SkASSERT(y1 < my);
988
989     for (int i = 0; i < count; ++i) {
990         uint32_t XX = bitmapXY[i];
991         unsigned x0 = XX >> 18;
992         unsigned x1 = XX & 0x3FFF;
993         SkASSERT(x0 < mx);
994         SkASSERT(x1 < mx);
995     }
996 }
997
998 static void check_affine_nofilter(uint32_t bitmapXY[], int count,
999                                  unsigned mx, unsigned my) {
1000     for (int i = 0; i < count; ++i) {
1001         uint32_t XY = bitmapXY[i];
1002         unsigned x = XY & 0xFFFF;
1003         unsigned y = XY >> 16;
1004         SkASSERT(x < mx);
1005         SkASSERT(y < my);
1006     }
1007 }
1008
1009 static void check_affine_filter(uint32_t bitmapXY[], int count,
1010                                  unsigned mx, unsigned my) {
1011     for (int i = 0; i < count; ++i) {
1012         uint32_t YY = *bitmapXY++;
1013         unsigned y0 = YY >> 18;
1014         unsigned y1 = YY & 0x3FFF;
1015         SkASSERT(y0 < my);
1016         SkASSERT(y1 < my);
1017
1018         uint32_t XX = *bitmapXY++;
1019         unsigned x0 = XX >> 18;
1020         unsigned x1 = XX & 0x3FFF;
1021         SkASSERT(x0 < mx);
1022         SkASSERT(x1 < mx);
1023     }
1024 }
1025
1026 void SkBitmapProcState::DebugMatrixProc(const SkBitmapProcState& state,
1027                                         uint32_t bitmapXY[], int count,
1028                                         int x, int y) {
1029     SkASSERT(bitmapXY);
1030     SkASSERT(count > 0);
1031
1032     state.fMatrixProc(state, bitmapXY, count, x, y);
1033
1034     void (*proc)(uint32_t bitmapXY[], int count, unsigned mx, unsigned my);
1035
1036     // There are four formats possible:
1037     //  scale -vs- affine
1038     //  filter -vs- nofilter
1039     if (state.fInvType <= (SkMatrix::kTranslate_Mask | SkMatrix::kScale_Mask)) {
1040         proc = state.fFilterLevel != SkPaint::kNone_FilterLevel ? check_scale_filter : check_scale_nofilter;
1041     } else {
1042         proc = state.fFilterLevel != SkPaint::kNone_FilterLevel ? check_affine_filter : check_affine_nofilter;
1043     }
1044     proc(bitmapXY, count, state.fBitmap->width(), state.fBitmap->height());
1045 }
1046
1047 SkBitmapProcState::MatrixProc SkBitmapProcState::getMatrixProc() const {
1048     return DebugMatrixProc;
1049 }
1050
1051 #endif
1052
1053 ///////////////////////////////////////////////////////////////////////////////
1054 /*
1055     The storage requirements for the different matrix procs are as follows,
1056     where each X or Y is 2 bytes, and N is the number of pixels/elements:
1057
1058     scale/translate     nofilter      Y(4bytes) + N * X
1059     affine/perspective  nofilter      N * (X Y)
1060     scale/translate     filter        Y Y + N * (X X)
1061     affine/perspective  filter        N * (Y Y X X)
1062  */
1063 int SkBitmapProcState::maxCountForBufferSize(size_t bufferSize) const {
1064     int32_t size = static_cast<int32_t>(bufferSize);
1065
1066     size &= ~3; // only care about 4-byte aligned chunks
1067     if (fInvType <= (SkMatrix::kTranslate_Mask | SkMatrix::kScale_Mask)) {
1068         size -= 4;   // the shared Y (or YY) coordinate
1069         if (size < 0) {
1070             size = 0;
1071         }
1072         size >>= 1;
1073     } else {
1074         size >>= 2;
1075     }
1076
1077     if (fFilterLevel != SkPaint::kNone_FilterLevel) {
1078         size >>= 1;
1079     }
1080
1081     return size;
1082 }