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