OLD | NEW |
1 | 1 |
2 /* | 2 /* |
3 * Copyright 2011 Google Inc. | 3 * Copyright 2011 Google Inc. |
4 * | 4 * |
5 * Use of this source code is governed by a BSD-style license that can be | 5 * Use of this source code is governed by a BSD-style license that can be |
6 * found in the LICENSE file. | 6 * found in the LICENSE file. |
7 */ | 7 */ |
8 #include "SkBitmapProcState.h" | 8 #include "SkBitmapProcState.h" |
9 #include "SkColorPriv.h" | 9 #include "SkColorPriv.h" |
10 #include "SkFilterProc.h" | 10 #include "SkFilterProc.h" |
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
83 } | 83 } |
84 | 84 |
85 /////////////////////////////////////////////////////////////////////////////// | 85 /////////////////////////////////////////////////////////////////////////////// |
86 | 86 |
87 static bool valid_for_filtering(unsigned dimension) { | 87 static bool valid_for_filtering(unsigned dimension) { |
88 // for filtering, width and height must fit in 14bits, since we use steal | 88 // for filtering, width and height must fit in 14bits, since we use steal |
89 // 2 bits from each to store our 4bit subpixel data | 89 // 2 bits from each to store our 4bit subpixel data |
90 return (dimension & ~0x3FFF) == 0; | 90 return (dimension & ~0x3FFF) == 0; |
91 } | 91 } |
92 | 92 |
| 93 // TODO -- we may want to pass the clip into this function so we only scale |
| 94 // the portion of the image that we're going to need. This will complicate |
| 95 // the interface to the cache, but might be well worth it. |
| 96 |
| 97 void SkBitmapProcState::possiblyScaleImage() { |
| 98 |
| 99 if (fFilterQuality != kHQ_BitmapFilter) { |
| 100 return; |
| 101 } |
| 102 |
| 103 // STEP 1: UPSAMPLE? |
| 104 |
| 105 // Check to see if the transformation matrix is scaling up, and if |
| 106 // the matrix is simple, and if we're doing high quality scaling. |
| 107 // If so, do the bitmap scale here and remove the scaling component from the
matrix. |
| 108 |
| 109 if (fInvMatrix.getType() <= (SkMatrix::kScale_Mask | SkMatrix::kTranslate_Ma
sk) && |
| 110 (fInvMatrix.getScaleX() < 1 || fInvMatrix.getScaleY() < 1) && |
| 111 fOrigBitmap.config() == SkBitmap::kARGB_8888_Config) { |
| 112 |
| 113 // All the criteria are met; let's make a new bitmap. |
| 114 fScaledBitmap.setConfig(SkBitmap::kARGB_8888_Config, |
| 115 (int)(fOrigBitmap.width() / fInvMatrix.getScaleX
()), |
| 116 (int)(fOrigBitmap.height() / fInvMatrix.getScale
Y())); |
| 117 fScaledBitmap.allocPixels(); |
| 118 fOrigBitmap.scale(&fScaledBitmap); |
| 119 fBitmap = &fScaledBitmap; |
| 120 |
| 121 // set the inv matrix type to translate-only; |
| 122 |
| 123 fInvMatrix.setTranslate( 1/fInvMatrix.getScaleX() * fInvMatrix.getTransl
ateX(), |
| 124 1/fInvMatrix.getScaleY() * fInvMatrix.getTransl
ateY() ); |
| 125 |
| 126 // no need for any further filtering; we just did it! |
| 127 |
| 128 fFilterQuality = kNone_BitmapFilter; |
| 129 |
| 130 return; |
| 131 } |
| 132 |
| 133 if (!fOrigBitmap.hasMipMap()) { |
| 134 |
| 135 // STEP 2: DOWNSAMPLE |
| 136 |
| 137 // Check to see if the transformation matrix is scaling *down*. |
| 138 // If so, automatically build mipmaps. |
| 139 |
| 140 SkPoint v1, v2; |
| 141 |
| 142 // conservatively estimate if the matrix is scaling down by seeing |
| 143 // what its upper left 2x2 portion does to two unit vectors. |
| 144 |
| 145 v1.fX = fInvMatrix.getScaleX(); |
| 146 v1.fY = fInvMatrix.getSkewY(); |
| 147 |
| 148 v2.fX = fInvMatrix.getSkewX(); |
| 149 v2.fY = fInvMatrix.getScaleY(); |
| 150 |
| 151 if (v1.fX * v1.fX + v1.fY * v1.fY > 1 || |
| 152 v2.fX * v2.fX + v2.fY * v2.fY > 1) { |
| 153 fOrigBitmap.buildMipMap(); |
| 154 |
| 155 // Now that we've built the mipmaps and we know we're downsampling, |
| 156 // downgrade to bilinear interpolation for the mip level. |
| 157 |
| 158 fFilterQuality = kBilerp_BitmapFilter; |
| 159 } |
| 160 } |
| 161 |
| 162 if (fOrigBitmap.hasMipMap()) { |
| 163 |
| 164 // STEP 3: We've got mipmaps, let's choose the closest level as our rend
er |
| 165 // source and adjust the matrix accordingly. |
| 166 |
| 167 int shift = fOrigBitmap.extractMipLevel(&fScaledBitmap, |
| 168 SkScalarToFixed(fInvMatrix.getSc
aleX()), |
| 169 SkScalarToFixed(fInvMatrix.getSk
ewY())); |
| 170 |
| 171 if (shift > 0) { |
| 172 SkScalar scale = SkFixedToScalar(SK_Fixed1 >> shift); |
| 173 fInvMatrix.postScale(scale, scale); |
| 174 fBitmap = &fScaledBitmap; |
| 175 } |
| 176 } |
| 177 } |
| 178 |
| 179 void SkBitmapProcState::endContext() { |
| 180 SkDELETE(fBitmapFilter); |
| 181 fBitmapFilter = NULL; |
| 182 fScaledBitmap.reset(); |
| 183 } |
| 184 |
93 bool SkBitmapProcState::chooseProcs(const SkMatrix& inv, const SkPaint& paint) { | 185 bool SkBitmapProcState::chooseProcs(const SkMatrix& inv, const SkPaint& paint) { |
94 if (fOrigBitmap.width() == 0 || fOrigBitmap.height() == 0) { | 186 if (fOrigBitmap.width() == 0 || fOrigBitmap.height() == 0) { |
95 return false; | 187 return false; |
96 } | 188 } |
97 | 189 |
98 const SkMatrix* m; | 190 bool trivialMatrix = (inv.getType() & ~SkMatrix::kTranslate_Mask) == 0; |
99 bool trivial_matrix = (inv.getType() & ~SkMatrix::kTranslate_Mask) == 0; | 191 bool clampClamp = SkShader::kClamp_TileMode == fTileModeX && |
100 bool clamp_clamp = SkShader::kClamp_TileMode == fTileModeX && | |
101 SkShader::kClamp_TileMode == fTileModeY; | 192 SkShader::kClamp_TileMode == fTileModeY; |
102 | 193 |
103 if (clamp_clamp || trivial_matrix) { | 194 fInvMatrix = inv; |
104 m = &inv; | 195 if (!(clampClamp || trivialMatrix)) { |
105 } else { | 196 fInvMatrix.postIDiv(fOrigBitmap.width(), fOrigBitmap.height()); |
106 fUnitInvMatrix = inv; | |
107 fUnitInvMatrix.postIDiv(fOrigBitmap.width(), fOrigBitmap.height()); | |
108 m = &fUnitInvMatrix; | |
109 } | 197 } |
110 | 198 |
111 fBitmap = &fOrigBitmap; | 199 fBitmap = &fOrigBitmap; |
112 if (fOrigBitmap.hasMipMap()) { | 200 |
113 int shift = fOrigBitmap.extractMipLevel(&fMipBitmap, | 201 // initialize our filter quality to the one requested by the caller. |
114 SkScalarToFixed(m->getScaleX()), | 202 // We may downgrade it later if we determine that we either don't need |
115 SkScalarToFixed(m->getSkewY())); | 203 // or can't provide as high a quality filtering as the user requested. |
116 | 204 |
117 if (shift > 0) { | 205 fFilterQuality = kNone_BitmapFilter; |
118 if (m != &fUnitInvMatrix) { | 206 if (paint.isFilterBitmap()) { |
119 fUnitInvMatrix = *m; | 207 if (paint.getFlags() & SkPaint::kHighQualityFilterBitmap_Flag) { |
120 m = &fUnitInvMatrix; | 208 fFilterQuality = kHQ_BitmapFilter; |
121 } | 209 } else { |
122 | 210 fFilterQuality = kBilerp_BitmapFilter; |
123 SkScalar scale = SkFixedToScalar(SK_Fixed1 >> shift); | 211 } |
124 fUnitInvMatrix.postScale(scale, scale); | 212 } |
125 | 213 |
126 // now point here instead of fOrigBitmap | 214 #ifndef SK_IGNORE_IMAGE_PRESCALE |
127 fBitmap = &fMipBitmap; | 215 // possiblyScaleImage will look to see if it can rescale the image as a |
128 } | 216 // preprocess; either by scaling up to the target size, or by selecting |
129 } | 217 // a nearby mipmap level. If it does, it will adjust the working |
130 | 218 // matrix as well as the working bitmap. It may also adjust the filter |
131 // wack our matrix to exactly no-scale, if we're really close to begin with | 219 // quality to avoid re-filtering an already perfectly scaled image. |
132 if (matrix_only_scale_translate(*m)) { | 220 |
| 221 this->possiblyScaleImage(); |
| 222 #endif |
| 223 |
| 224 // Now that all possible changes to the matrix have taken place, check |
| 225 // to see if we're really close to a no-scale matrix. If so, explicitly |
| 226 // set it to be so. Subsequent code may inspect this matrix to choose |
| 227 // a faster path in this case. |
| 228 |
| 229 // This code will only execute if the matrix has some scale component; |
| 230 // if it's already pure translate then we won't do this inversion. |
| 231 |
| 232 if (matrix_only_scale_translate(fInvMatrix)) { |
133 SkMatrix forward; | 233 SkMatrix forward; |
134 if (m->invert(&forward)) { | 234 if (fInvMatrix.invert(&forward)) { |
135 if (clamp_clamp ? just_trans_clamp(forward, *fBitmap) | 235 if (clampClamp ? just_trans_clamp(forward, *fBitmap) |
136 : just_trans_general(forward)) { | 236 : just_trans_general(forward)) { |
137 SkScalar tx = -SkScalarRoundToScalar(forward.getTranslateX()); | 237 SkScalar tx = -SkScalarRoundToScalar(forward.getTranslateX()); |
138 SkScalar ty = -SkScalarRoundToScalar(forward.getTranslateY()); | 238 SkScalar ty = -SkScalarRoundToScalar(forward.getTranslateY()); |
139 fUnitInvMatrix.setTranslate(tx, ty); | 239 fInvMatrix.setTranslate(tx, ty); |
140 m = &fUnitInvMatrix; | 240 |
141 // now the following code will sniff m, and decide to take the | |
142 // fast case (since m is purely translate). | |
143 } | 241 } |
144 } | 242 } |
145 } | 243 } |
146 | 244 |
147 // Below this point, we should never refer to the inv parameter, since we | 245 fInvProc = fInvMatrix.getMapXYProc(); |
148 // may be using a munged version for "our" inverse. | 246 fInvType = fInvMatrix.getType(); |
149 | 247 fInvSx = SkScalarToFixed(fInvMatrix.getScaleX()); |
150 fInvMatrix = m; | 248 fInvSxFractionalInt = SkScalarToFractionalInt(fInvMatrix.getScaleX()); |
151 fInvProc = m->getMapXYProc(); | 249 fInvKy = SkScalarToFixed(fInvMatrix.getSkewY()); |
152 fInvType = m->getType(); | 250 fInvKyFractionalInt = SkScalarToFractionalInt(fInvMatrix.getSkewY()); |
153 fInvSx = SkScalarToFixed(m->getScaleX()); | |
154 fInvSxFractionalInt = SkScalarToFractionalInt(m->getScaleX()); | |
155 fInvKy = SkScalarToFixed(m->getSkewY()); | |
156 fInvKyFractionalInt = SkScalarToFractionalInt(m->getSkewY()); | |
157 | 251 |
158 fAlphaScale = SkAlpha255To256(paint.getAlpha()); | 252 fAlphaScale = SkAlpha255To256(paint.getAlpha()); |
159 | 253 |
160 // pick-up filtering from the paint, but only if the matrix is | |
161 // more complex than identity/translate (i.e. no need to pay the cost | |
162 // of filtering if we're not scaled etc.). | |
163 // note: we explicitly check inv, since m might be scaled due to unitinv | |
164 // trickery, but we don't want to see that for this test | |
165 fDoFilter = paint.isFilterBitmap() && | |
166 (fInvType > SkMatrix::kTranslate_Mask && | |
167 valid_for_filtering(fBitmap->width() | fBitmap->height())); | |
168 | |
169 fShaderProc32 = NULL; | 254 fShaderProc32 = NULL; |
170 fShaderProc16 = NULL; | 255 fShaderProc16 = NULL; |
171 fSampleProc32 = NULL; | 256 fSampleProc32 = NULL; |
172 fSampleProc16 = NULL; | 257 fSampleProc16 = NULL; |
173 | 258 |
174 fMatrixProc = this->chooseMatrixProc(trivial_matrix); | 259 // recompute the triviality of the matrix here because we may have |
| 260 // changed it! |
| 261 |
| 262 trivialMatrix = (fInvMatrix.getType() & ~SkMatrix::kTranslate_Mask) == 0; |
| 263 |
| 264 if (kHQ_BitmapFilter == fFilterQuality) { |
| 265 // If this is still set, that means we wanted HQ sampling |
| 266 // but couldn't do it as a preprocess. Let's try to install |
| 267 // the scanline version of the HQ sampler. If that process fails, |
| 268 // downgrade to bilerp. |
| 269 |
| 270 // NOTE: Might need to be careful here in the future when we want |
| 271 // to have the platform proc have a shot at this; it's possible that |
| 272 // the chooseBitmapFilterProc will fail to install a shader but a |
| 273 // platform-specific one might succeed, so it might be premature here |
| 274 // to fall back to bilerp. This needs thought. |
| 275 |
| 276 SkASSERT(fInvType > SkMatrix::kTranslate_Mask); |
| 277 |
| 278 fShaderProc32 = this->chooseBitmapFilterProc(); |
| 279 if (!fShaderProc32) { |
| 280 fFilterQuality = kBilerp_BitmapFilter; |
| 281 } |
| 282 } |
| 283 |
| 284 if (kBilerp_BitmapFilter == fFilterQuality) { |
| 285 // Only try bilerp if the matrix is "interesting" and |
| 286 // the image has a suitable size. |
| 287 |
| 288 if (fInvType < SkMatrix::kTranslate_Mask || |
| 289 !valid_for_filtering(fBitmap->width() | fBitmap->height())) { |
| 290 fFilterQuality = kNone_BitmapFilter; |
| 291 } |
| 292 } |
| 293 |
| 294 // At this point, we know exactly what kind of sampling the per-scanline |
| 295 // shader will perform. |
| 296 |
| 297 fMatrixProc = this->chooseMatrixProc(trivialMatrix); |
175 if (NULL == fMatrixProc) { | 298 if (NULL == fMatrixProc) { |
176 return false; | 299 return false; |
177 } | 300 } |
178 | 301 |
179 /////////////////////////////////////////////////////////////////////// | 302 /////////////////////////////////////////////////////////////////////// |
180 | 303 |
181 int index = 0; | 304 // No need to do this if we're doing HQ sampling; if filter quality is |
182 if (fAlphaScale < 256) { // note: this distinction is not used for D16 | 305 // still set to HQ by the time we get here, then we must have installed |
183 index |= 1; | 306 // the shader proc above and can skip all this. |
184 } | 307 |
185 if (fInvType <= (SkMatrix::kTranslate_Mask | SkMatrix::kScale_Mask)) { | 308 if (fFilterQuality < kHQ_BitmapFilter) { |
186 index |= 2; | 309 |
187 } | 310 int index = 0; |
188 if (fDoFilter) { | 311 if (fAlphaScale < 256) { // note: this distinction is not used for D16 |
189 index |= 4; | 312 index |= 1; |
190 } | 313 } |
191 // bits 3,4,5 encoding the source bitmap format | 314 if (fInvType <= (SkMatrix::kTranslate_Mask | SkMatrix::kScale_Mask)) { |
192 switch (fBitmap->config()) { | 315 index |= 2; |
193 case SkBitmap::kARGB_8888_Config: | 316 } |
194 index |= 0; | 317 if (fFilterQuality != kNone_BitmapFilter) { |
195 break; | 318 index |= 4; |
196 case SkBitmap::kRGB_565_Config: | 319 } |
197 index |= 8; | 320 // bits 3,4,5 encoding the source bitmap format |
198 break; | 321 switch (fBitmap->config()) { |
199 case SkBitmap::kIndex8_Config: | 322 case SkBitmap::kARGB_8888_Config: |
200 index |= 16; | 323 index |= 0; |
201 break; | 324 break; |
202 case SkBitmap::kARGB_4444_Config: | 325 case SkBitmap::kRGB_565_Config: |
203 index |= 24; | 326 index |= 8; |
204 break; | 327 break; |
205 case SkBitmap::kA8_Config: | 328 case SkBitmap::kIndex8_Config: |
206 index |= 32; | 329 index |= 16; |
207 fPaintPMColor = SkPreMultiplyColor(paint.getColor()); | 330 break; |
208 break; | 331 case SkBitmap::kARGB_4444_Config: |
209 default: | 332 index |= 24; |
210 return false; | 333 break; |
211 } | 334 case SkBitmap::kA8_Config: |
212 | 335 index |= 32; |
213 #if !SK_ARM_NEON_IS_ALWAYS | 336 fPaintPMColor = SkPreMultiplyColor(paint.getColor()); |
214 static const SampleProc32 gSkBitmapProcStateSample32[] = { | 337 break; |
215 S32_opaque_D32_nofilter_DXDY, | 338 default: |
216 S32_alpha_D32_nofilter_DXDY, | 339 return false; |
217 S32_opaque_D32_nofilter_DX, | 340 } |
218 S32_alpha_D32_nofilter_DX, | 341 |
219 S32_opaque_D32_filter_DXDY, | 342 #if !SK_ARM_NEON_IS_ALWAYS |
220 S32_alpha_D32_filter_DXDY, | 343 static const SampleProc32 gSkBitmapProcStateSample32[] = { |
221 S32_opaque_D32_filter_DX, | 344 S32_opaque_D32_nofilter_DXDY, |
222 S32_alpha_D32_filter_DX, | 345 S32_alpha_D32_nofilter_DXDY, |
223 | 346 S32_opaque_D32_nofilter_DX, |
224 S16_opaque_D32_nofilter_DXDY, | 347 S32_alpha_D32_nofilter_DX, |
225 S16_alpha_D32_nofilter_DXDY, | 348 S32_opaque_D32_filter_DXDY, |
226 S16_opaque_D32_nofilter_DX, | 349 S32_alpha_D32_filter_DXDY, |
227 S16_alpha_D32_nofilter_DX, | 350 S32_opaque_D32_filter_DX, |
228 S16_opaque_D32_filter_DXDY, | 351 S32_alpha_D32_filter_DX, |
229 S16_alpha_D32_filter_DXDY, | 352 |
230 S16_opaque_D32_filter_DX, | 353 S16_opaque_D32_nofilter_DXDY, |
231 S16_alpha_D32_filter_DX, | 354 S16_alpha_D32_nofilter_DXDY, |
232 | 355 S16_opaque_D32_nofilter_DX, |
233 SI8_opaque_D32_nofilter_DXDY, | 356 S16_alpha_D32_nofilter_DX, |
234 SI8_alpha_D32_nofilter_DXDY, | 357 S16_opaque_D32_filter_DXDY, |
235 SI8_opaque_D32_nofilter_DX, | 358 S16_alpha_D32_filter_DXDY, |
236 SI8_alpha_D32_nofilter_DX, | 359 S16_opaque_D32_filter_DX, |
237 SI8_opaque_D32_filter_DXDY, | 360 S16_alpha_D32_filter_DX, |
238 SI8_alpha_D32_filter_DXDY, | 361 |
239 SI8_opaque_D32_filter_DX, | 362 SI8_opaque_D32_nofilter_DXDY, |
240 SI8_alpha_D32_filter_DX, | 363 SI8_alpha_D32_nofilter_DXDY, |
241 | 364 SI8_opaque_D32_nofilter_DX, |
242 S4444_opaque_D32_nofilter_DXDY, | 365 SI8_alpha_D32_nofilter_DX, |
243 S4444_alpha_D32_nofilter_DXDY, | 366 SI8_opaque_D32_filter_DXDY, |
244 S4444_opaque_D32_nofilter_DX, | 367 SI8_alpha_D32_filter_DXDY, |
245 S4444_alpha_D32_nofilter_DX, | 368 SI8_opaque_D32_filter_DX, |
246 S4444_opaque_D32_filter_DXDY, | 369 SI8_alpha_D32_filter_DX, |
247 S4444_alpha_D32_filter_DXDY, | 370 |
248 S4444_opaque_D32_filter_DX, | 371 S4444_opaque_D32_nofilter_DXDY, |
249 S4444_alpha_D32_filter_DX, | 372 S4444_alpha_D32_nofilter_DXDY, |
250 | 373 S4444_opaque_D32_nofilter_DX, |
251 // A8 treats alpha/opaque the same (equally efficient) | 374 S4444_alpha_D32_nofilter_DX, |
252 SA8_alpha_D32_nofilter_DXDY, | 375 S4444_opaque_D32_filter_DXDY, |
253 SA8_alpha_D32_nofilter_DXDY, | 376 S4444_alpha_D32_filter_DXDY, |
254 SA8_alpha_D32_nofilter_DX, | 377 S4444_opaque_D32_filter_DX, |
255 SA8_alpha_D32_nofilter_DX, | 378 S4444_alpha_D32_filter_DX, |
256 SA8_alpha_D32_filter_DXDY, | 379 |
257 SA8_alpha_D32_filter_DXDY, | 380 // A8 treats alpha/opaque the same (equally efficient) |
258 SA8_alpha_D32_filter_DX, | 381 SA8_alpha_D32_nofilter_DXDY, |
259 SA8_alpha_D32_filter_DX | 382 SA8_alpha_D32_nofilter_DXDY, |
260 }; | 383 SA8_alpha_D32_nofilter_DX, |
261 | 384 SA8_alpha_D32_nofilter_DX, |
262 static const SampleProc16 gSkBitmapProcStateSample16[] = { | 385 SA8_alpha_D32_filter_DXDY, |
263 S32_D16_nofilter_DXDY, | 386 SA8_alpha_D32_filter_DXDY, |
264 S32_D16_nofilter_DX, | 387 SA8_alpha_D32_filter_DX, |
265 S32_D16_filter_DXDY, | 388 SA8_alpha_D32_filter_DX |
266 S32_D16_filter_DX, | 389 }; |
267 | 390 |
268 S16_D16_nofilter_DXDY, | 391 static const SampleProc16 gSkBitmapProcStateSample16[] = { |
269 S16_D16_nofilter_DX, | 392 S32_D16_nofilter_DXDY, |
270 S16_D16_filter_DXDY, | 393 S32_D16_nofilter_DX, |
271 S16_D16_filter_DX, | 394 S32_D16_filter_DXDY, |
272 | 395 S32_D16_filter_DX, |
273 SI8_D16_nofilter_DXDY, | 396 |
274 SI8_D16_nofilter_DX, | 397 S16_D16_nofilter_DXDY, |
275 SI8_D16_filter_DXDY, | 398 S16_D16_nofilter_DX, |
276 SI8_D16_filter_DX, | 399 S16_D16_filter_DXDY, |
277 | 400 S16_D16_filter_DX, |
278 // Don't support 4444 -> 565 | 401 |
279 NULL, NULL, NULL, NULL, | 402 SI8_D16_nofilter_DXDY, |
280 // Don't support A8 -> 565 | 403 SI8_D16_nofilter_DX, |
281 NULL, NULL, NULL, NULL | 404 SI8_D16_filter_DXDY, |
282 }; | 405 SI8_D16_filter_DX, |
283 #endif | 406 |
284 | 407 // Don't support 4444 -> 565 |
285 fSampleProc32 = SK_ARM_NEON_WRAP(gSkBitmapProcStateSample32)[index]; | 408 NULL, NULL, NULL, NULL, |
286 index >>= 1; // shift away any opaque/alpha distinction | 409 // Don't support A8 -> 565 |
287 fSampleProc16 = SK_ARM_NEON_WRAP(gSkBitmapProcStateSample16)[index]; | 410 NULL, NULL, NULL, NULL |
288 | 411 }; |
289 // our special-case shaderprocs | 412 #endif |
290 if (SK_ARM_NEON_WRAP(S16_D16_filter_DX) == fSampleProc16) { | 413 |
291 if (clamp_clamp) { | 414 fSampleProc32 = SK_ARM_NEON_WRAP(gSkBitmapProcStateSample32)[index]; |
292 fShaderProc16 = SK_ARM_NEON_WRAP(Clamp_S16_D16_filter_DX_shaderproc)
; | 415 index >>= 1; // shift away any opaque/alpha distinction |
293 } else if (SkShader::kRepeat_TileMode == fTileModeX && | 416 fSampleProc16 = SK_ARM_NEON_WRAP(gSkBitmapProcStateSample16)[index]; |
294 SkShader::kRepeat_TileMode == fTileModeY) { | 417 |
295 fShaderProc16 = SK_ARM_NEON_WRAP(Repeat_S16_D16_filter_DX_shaderproc
); | 418 // our special-case shaderprocs |
296 } | 419 if (SK_ARM_NEON_WRAP(S16_D16_filter_DX) == fSampleProc16) { |
297 } else if (SK_ARM_NEON_WRAP(SI8_opaque_D32_filter_DX) == fSampleProc32 && cl
amp_clamp) { | 420 if (clampClamp) { |
298 fShaderProc32 = SK_ARM_NEON_WRAP(Clamp_SI8_opaque_D32_filter_DX_shaderpr
oc); | 421 fShaderProc16 = SK_ARM_NEON_WRAP(Clamp_S16_D16_filter_DX_shaderp
roc); |
299 } | 422 } else if (SkShader::kRepeat_TileMode == fTileModeX && |
300 | 423 SkShader::kRepeat_TileMode == fTileModeY) { |
301 if (NULL == fShaderProc32) { | 424 fShaderProc16 = SK_ARM_NEON_WRAP(Repeat_S16_D16_filter_DX_shader
proc); |
302 fShaderProc32 = this->chooseShaderProc32(); | 425 } |
303 } | 426 } else if (SK_ARM_NEON_WRAP(SI8_opaque_D32_filter_DX) == fSampleProc32 &
& clampClamp) { |
304 | 427 fShaderProc32 = SK_ARM_NEON_WRAP(Clamp_SI8_opaque_D32_filter_DX_shad
erproc); |
305 if (NULL == fShaderProc32) { | 428 } |
306 fShaderProc32 = this->chooseBitmapFilterProc(paint); | 429 |
| 430 if (NULL == fShaderProc32) { |
| 431 fShaderProc32 = this->chooseShaderProc32(); |
| 432 } |
307 } | 433 } |
308 | 434 |
309 // see if our platform has any accelerated overrides | 435 // see if our platform has any accelerated overrides |
310 this->platformProcs(); | 436 this->platformProcs(); |
311 | 437 |
312 return true; | 438 return true; |
313 } | 439 } |
314 | 440 |
315 static void Clamp_S32_D32_nofilter_trans_shaderproc(const SkBitmapProcState& s, | 441 static void Clamp_S32_D32_nofilter_trans_shaderproc(const SkBitmapProcState& s, |
316 int x, int y, | 442 int x, int y, |
317 SkPMColor* SK_RESTRICT color
s, | 443 SkPMColor* SK_RESTRICT color
s, |
318 int count) { | 444 int count) { |
319 SkASSERT(((s.fInvType & ~SkMatrix::kTranslate_Mask)) == 0); | 445 SkASSERT(((s.fInvType & ~SkMatrix::kTranslate_Mask)) == 0); |
320 SkASSERT(s.fInvKy == 0); | 446 SkASSERT(s.fInvKy == 0); |
321 SkASSERT(count > 0 && colors != NULL); | 447 SkASSERT(count > 0 && colors != NULL); |
322 SkASSERT(!s.fDoFilter); | 448 SkASSERT(SkBitmapProcState::kNone_BitmapFilter == s.fFilterQuality); |
323 | 449 |
324 const int maxX = s.fBitmap->width() - 1; | 450 const int maxX = s.fBitmap->width() - 1; |
325 const int maxY = s.fBitmap->height() - 1; | 451 const int maxY = s.fBitmap->height() - 1; |
326 int ix = s.fFilterOneX + x; | 452 int ix = s.fFilterOneX + x; |
327 int iy = SkClampMax(s.fFilterOneY + y, maxY); | 453 int iy = SkClampMax(s.fFilterOneY + y, maxY); |
328 #ifdef SK_DEBUG | 454 #ifdef SK_DEBUG |
329 { | 455 { |
330 SkPoint pt; | 456 SkPoint pt; |
331 s.fInvProc(*s.fInvMatrix, SkIntToScalar(x) + SK_ScalarHalf, | 457 s.fInvProc(s.fInvMatrix, SkIntToScalar(x) + SK_ScalarHalf, |
332 SkIntToScalar(y) + SK_ScalarHalf, &pt); | 458 SkIntToScalar(y) + SK_ScalarHalf, &pt); |
333 int iy2 = SkClampMax(SkScalarFloorToInt(pt.fY), maxY); | 459 int iy2 = SkClampMax(SkScalarFloorToInt(pt.fY), maxY); |
334 int ix2 = SkScalarFloorToInt(pt.fX); | 460 int ix2 = SkScalarFloorToInt(pt.fX); |
335 | 461 |
336 SkASSERT(iy == iy2); | 462 SkASSERT(iy == iy2); |
337 SkASSERT(ix == ix2); | 463 SkASSERT(ix == ix2); |
338 } | 464 } |
339 #endif | 465 #endif |
340 const SkPMColor* row = s.fBitmap->getAddr32(0, iy); | 466 const SkPMColor* row = s.fBitmap->getAddr32(0, iy); |
341 | 467 |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
386 return x; | 512 return x; |
387 } | 513 } |
388 | 514 |
389 static void Repeat_S32_D32_nofilter_trans_shaderproc(const SkBitmapProcState& s, | 515 static void Repeat_S32_D32_nofilter_trans_shaderproc(const SkBitmapProcState& s, |
390 int x, int y, | 516 int x, int y, |
391 SkPMColor* SK_RESTRICT colo
rs, | 517 SkPMColor* SK_RESTRICT colo
rs, |
392 int count) { | 518 int count) { |
393 SkASSERT(((s.fInvType & ~SkMatrix::kTranslate_Mask)) == 0); | 519 SkASSERT(((s.fInvType & ~SkMatrix::kTranslate_Mask)) == 0); |
394 SkASSERT(s.fInvKy == 0); | 520 SkASSERT(s.fInvKy == 0); |
395 SkASSERT(count > 0 && colors != NULL); | 521 SkASSERT(count > 0 && colors != NULL); |
396 SkASSERT(!s.fDoFilter); | 522 SkASSERT(SkBitmapProcState::kNone_BitmapFilter == s.fFilterQuality); |
397 | 523 |
398 const int stopX = s.fBitmap->width(); | 524 const int stopX = s.fBitmap->width(); |
399 const int stopY = s.fBitmap->height(); | 525 const int stopY = s.fBitmap->height(); |
400 int ix = s.fFilterOneX + x; | 526 int ix = s.fFilterOneX + x; |
401 int iy = sk_int_mod(s.fFilterOneY + y, stopY); | 527 int iy = sk_int_mod(s.fFilterOneY + y, stopY); |
402 #ifdef SK_DEBUG | 528 #ifdef SK_DEBUG |
403 { | 529 { |
404 SkPoint pt; | 530 SkPoint pt; |
405 s.fInvProc(*s.fInvMatrix, SkIntToScalar(x) + SK_ScalarHalf, | 531 s.fInvProc(s.fInvMatrix, SkIntToScalar(x) + SK_ScalarHalf, |
406 SkIntToScalar(y) + SK_ScalarHalf, &pt); | 532 SkIntToScalar(y) + SK_ScalarHalf, &pt); |
407 int iy2 = sk_int_mod(SkScalarFloorToInt(pt.fY), stopY); | 533 int iy2 = sk_int_mod(SkScalarFloorToInt(pt.fY), stopY); |
408 int ix2 = SkScalarFloorToInt(pt.fX); | 534 int ix2 = SkScalarFloorToInt(pt.fX); |
409 | 535 |
410 SkASSERT(iy == iy2); | 536 SkASSERT(iy == iy2); |
411 SkASSERT(ix == ix2); | 537 SkASSERT(ix == ix2); |
412 } | 538 } |
413 #endif | 539 #endif |
414 const SkPMColor* row = s.fBitmap->getAddr32(0, iy); | 540 const SkPMColor* row = s.fBitmap->getAddr32(0, iy); |
415 | 541 |
(...skipping 16 matching lines...) Expand all Loading... |
432 int count) { | 558 int count) { |
433 SkASSERT((s.fInvType & ~(SkMatrix::kTranslate_Mask | SkMatrix::kScale_Mask))
== 0); | 559 SkASSERT((s.fInvType & ~(SkMatrix::kTranslate_Mask | SkMatrix::kScale_Mask))
== 0); |
434 SkASSERT(s.fInvKy == 0); | 560 SkASSERT(s.fInvKy == 0); |
435 SkASSERT(count > 0 && colors != NULL); | 561 SkASSERT(count > 0 && colors != NULL); |
436 SkASSERT(1 == s.fBitmap->width()); | 562 SkASSERT(1 == s.fBitmap->width()); |
437 | 563 |
438 int iY0; | 564 int iY0; |
439 int iY1 SK_INIT_TO_AVOID_WARNING; | 565 int iY1 SK_INIT_TO_AVOID_WARNING; |
440 int iSubY SK_INIT_TO_AVOID_WARNING; | 566 int iSubY SK_INIT_TO_AVOID_WARNING; |
441 | 567 |
442 if (s.fDoFilter) { | 568 if (s.fFilterQuality != SkBitmapProcState::kNone_BitmapFilter) { |
443 SkBitmapProcState::MatrixProc mproc = s.getMatrixProc(); | 569 SkBitmapProcState::MatrixProc mproc = s.getMatrixProc(); |
444 uint32_t xy[2]; | 570 uint32_t xy[2]; |
445 | 571 |
446 mproc(s, xy, 1, x, y); | 572 mproc(s, xy, 1, x, y); |
447 | 573 |
448 iY0 = xy[0] >> 18; | 574 iY0 = xy[0] >> 18; |
449 iY1 = xy[0] & 0x3FFF; | 575 iY1 = xy[0] & 0x3FFF; |
450 iSubY = (xy[0] >> 14) & 0xF; | 576 iSubY = (xy[0] >> 14) & 0xF; |
451 } else { | 577 } else { |
452 int yTemp; | 578 int yTemp; |
453 | 579 |
454 if (s.fInvType > SkMatrix::kTranslate_Mask) { | 580 if (s.fInvType > SkMatrix::kTranslate_Mask) { |
455 SkPoint pt; | 581 SkPoint pt; |
456 s.fInvProc(*s.fInvMatrix, | 582 s.fInvProc(s.fInvMatrix, |
457 SkIntToScalar(x) + SK_ScalarHalf, | 583 SkIntToScalar(x) + SK_ScalarHalf, |
458 SkIntToScalar(y) + SK_ScalarHalf, | 584 SkIntToScalar(y) + SK_ScalarHalf, |
459 &pt); | 585 &pt); |
460 // When the matrix has a scale component the setup code in | 586 // When the matrix has a scale component the setup code in |
461 // chooseProcs multiples the inverse matrix by the inverse of the | 587 // chooseProcs multiples the inverse matrix by the inverse of the |
462 // bitmap's width and height. Since this method is going to do | 588 // bitmap's width and height. Since this method is going to do |
463 // its own tiling and sampling we need to undo that here. | 589 // its own tiling and sampling we need to undo that here. |
464 if (SkShader::kClamp_TileMode != s.fTileModeX || | 590 if (SkShader::kClamp_TileMode != s.fTileModeX || |
465 SkShader::kClamp_TileMode != s.fTileModeY) { | 591 SkShader::kClamp_TileMode != s.fTileModeY) { |
466 yTemp = SkScalarFloorToInt(pt.fY * s.fBitmap->height()); | 592 yTemp = SkScalarFloorToInt(pt.fY * s.fBitmap->height()); |
(...skipping 14 matching lines...) Expand all Loading... |
481 break; | 607 break; |
482 case SkShader::kMirror_TileMode: | 608 case SkShader::kMirror_TileMode: |
483 default: | 609 default: |
484 iY0 = sk_int_mirror(yTemp, stopY); | 610 iY0 = sk_int_mirror(yTemp, stopY); |
485 break; | 611 break; |
486 } | 612 } |
487 | 613 |
488 #ifdef SK_DEBUG | 614 #ifdef SK_DEBUG |
489 { | 615 { |
490 SkPoint pt; | 616 SkPoint pt; |
491 s.fInvProc(*s.fInvMatrix, | 617 s.fInvProc(s.fInvMatrix, |
492 SkIntToScalar(x) + SK_ScalarHalf, | 618 SkIntToScalar(x) + SK_ScalarHalf, |
493 SkIntToScalar(y) + SK_ScalarHalf, | 619 SkIntToScalar(y) + SK_ScalarHalf, |
494 &pt); | 620 &pt); |
495 if (s.fInvType > SkMatrix::kTranslate_Mask && | 621 if (s.fInvType > SkMatrix::kTranslate_Mask && |
496 (SkShader::kClamp_TileMode != s.fTileModeX || | 622 (SkShader::kClamp_TileMode != s.fTileModeX || |
497 SkShader::kClamp_TileMode != s.fTileModeY)) { | 623 SkShader::kClamp_TileMode != s.fTileModeY)) { |
498 pt.fY *= s.fBitmap->height(); | 624 pt.fY *= s.fBitmap->height(); |
499 } | 625 } |
500 int iY2; | 626 int iY2; |
501 | 627 |
(...skipping 11 matching lines...) Expand all Loading... |
513 } | 639 } |
514 | 640 |
515 SkASSERT(iY0 == iY2); | 641 SkASSERT(iY0 == iY2); |
516 } | 642 } |
517 #endif | 643 #endif |
518 } | 644 } |
519 | 645 |
520 const SkPMColor* row0 = s.fBitmap->getAddr32(0, iY0); | 646 const SkPMColor* row0 = s.fBitmap->getAddr32(0, iY0); |
521 SkPMColor color; | 647 SkPMColor color; |
522 | 648 |
523 if (s.fDoFilter) { | 649 if (s.fFilterQuality != SkBitmapProcState::kNone_BitmapFilter) { |
524 const SkPMColor* row1 = s.fBitmap->getAddr32(0, iY1); | 650 const SkPMColor* row1 = s.fBitmap->getAddr32(0, iY1); |
525 | 651 |
526 if (s.fAlphaScale < 256) { | 652 if (s.fAlphaScale < 256) { |
527 Filter_32_alpha(iSubY, *row0, *row1, &color, s.fAlphaScale); | 653 Filter_32_alpha(iSubY, *row0, *row1, &color, s.fAlphaScale); |
528 } else { | 654 } else { |
529 Filter_32_opaque(iSubY, *row0, *row1, &color); | 655 Filter_32_opaque(iSubY, *row0, *row1, &color); |
530 } | 656 } |
531 } else { | 657 } else { |
532 if (s.fAlphaScale < 256) { | 658 if (s.fAlphaScale < 256) { |
533 color = SkAlphaMulQ(*row0, s.fAlphaScale); | 659 color = SkAlphaMulQ(*row0, s.fAlphaScale); |
534 } else { | 660 } else { |
535 color = *row0; | 661 color = *row0; |
536 } | 662 } |
537 } | 663 } |
538 | 664 |
539 sk_memset32(colors, color, count); | 665 sk_memset32(colors, color, count); |
540 } | 666 } |
541 | 667 |
542 static void DoNothing_shaderproc(const SkBitmapProcState&, int x, int y, | 668 static void DoNothing_shaderproc(const SkBitmapProcState&, int x, int y, |
543 SkPMColor* SK_RESTRICT colors, int count) { | 669 SkPMColor* SK_RESTRICT colors, int count) { |
544 // if we get called, the matrix is too tricky, so we just draw nothing | 670 // if we get called, the matrix is too tricky, so we just draw nothing |
545 sk_memset32(colors, 0, count); | 671 sk_memset32(colors, 0, count); |
546 } | 672 } |
547 | 673 |
548 bool SkBitmapProcState::setupForTranslate() { | 674 bool SkBitmapProcState::setupForTranslate() { |
549 SkPoint pt; | 675 SkPoint pt; |
550 fInvProc(*fInvMatrix, SK_ScalarHalf, SK_ScalarHalf, &pt); | 676 fInvProc(fInvMatrix, SK_ScalarHalf, SK_ScalarHalf, &pt); |
551 | 677 |
552 /* | 678 /* |
553 * if the translate is larger than our ints, we can get random results, or | 679 * if the translate is larger than our ints, we can get random results, or |
554 * worse, we might get 0x80000000, which wreaks havoc on us, since we can't | 680 * worse, we might get 0x80000000, which wreaks havoc on us, since we can't |
555 * negate it. | 681 * negate it. |
556 */ | 682 */ |
557 const SkScalar too_big = SkIntToScalar(1 << 30); | 683 const SkScalar too_big = SkIntToScalar(1 << 30); |
558 if (SkScalarAbs(pt.fX) > too_big || SkScalarAbs(pt.fY) > too_big) { | 684 if (SkScalarAbs(pt.fX) > too_big || SkScalarAbs(pt.fY) > too_big) { |
559 return false; | 685 return false; |
560 } | 686 } |
561 | 687 |
562 // Since we know we're not filtered, we re-purpose these fields allow | 688 // Since we know we're not filtered, we re-purpose these fields allow |
563 // us to go from device -> src coordinates w/ just an integer add, | 689 // us to go from device -> src coordinates w/ just an integer add, |
564 // rather than running through the inverse-matrix | 690 // rather than running through the inverse-matrix |
565 fFilterOneX = SkScalarFloorToInt(pt.fX); | 691 fFilterOneX = SkScalarFloorToInt(pt.fX); |
566 fFilterOneY = SkScalarFloorToInt(pt.fY); | 692 fFilterOneY = SkScalarFloorToInt(pt.fY); |
567 return true; | 693 return true; |
568 } | 694 } |
569 | 695 |
570 SkBitmapProcState::ShaderProc32 SkBitmapProcState::chooseShaderProc32() { | 696 SkBitmapProcState::ShaderProc32 SkBitmapProcState::chooseShaderProc32() { |
571 | 697 |
572 if (SkBitmap::kARGB_8888_Config != fBitmap->config()) { | 698 if (SkBitmap::kARGB_8888_Config != fBitmap->config()) { |
573 return NULL; | 699 return NULL; |
574 } | 700 } |
575 | 701 |
576 static const unsigned kMask = SkMatrix::kTranslate_Mask | SkMatrix::kScale_M
ask; | 702 static const unsigned kMask = SkMatrix::kTranslate_Mask | SkMatrix::kScale_M
ask; |
577 | 703 |
578 if (1 == fBitmap->width() && 0 == (fInvType & ~kMask)) { | 704 if (1 == fBitmap->width() && 0 == (fInvType & ~kMask)) { |
579 if (!fDoFilter && fInvType <= SkMatrix::kTranslate_Mask && !this->setupF
orTranslate()) { | 705 if (kNone_BitmapFilter == fFilterQuality && |
| 706 fInvType <= SkMatrix::kTranslate_Mask && |
| 707 !this->setupForTranslate()) { |
580 return DoNothing_shaderproc; | 708 return DoNothing_shaderproc; |
581 } | 709 } |
582 return S32_D32_constX_shaderproc; | 710 return S32_D32_constX_shaderproc; |
583 } | 711 } |
584 | 712 |
585 if (fAlphaScale < 256) { | 713 if (fAlphaScale < 256) { |
586 return NULL; | 714 return NULL; |
587 } | 715 } |
588 if (fInvType > SkMatrix::kTranslate_Mask) { | 716 if (fInvType > SkMatrix::kTranslate_Mask) { |
589 return NULL; | 717 return NULL; |
590 } | 718 } |
591 if (fDoFilter) { | 719 if (fFilterQuality != kNone_BitmapFilter) { |
592 return NULL; | 720 return NULL; |
593 } | 721 } |
594 | 722 |
595 SkShader::TileMode tx = (SkShader::TileMode)fTileModeX; | 723 SkShader::TileMode tx = (SkShader::TileMode)fTileModeX; |
596 SkShader::TileMode ty = (SkShader::TileMode)fTileModeY; | 724 SkShader::TileMode ty = (SkShader::TileMode)fTileModeY; |
597 | 725 |
598 if (SkShader::kClamp_TileMode == tx && SkShader::kClamp_TileMode == ty) { | 726 if (SkShader::kClamp_TileMode == tx && SkShader::kClamp_TileMode == ty) { |
599 if (this->setupForTranslate()) { | 727 if (this->setupForTranslate()) { |
600 return Clamp_S32_D32_nofilter_trans_shaderproc; | 728 return Clamp_S32_D32_nofilter_trans_shaderproc; |
601 } | 729 } |
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
677 SkASSERT(count > 0); | 805 SkASSERT(count > 0); |
678 | 806 |
679 state.fMatrixProc(state, bitmapXY, count, x, y); | 807 state.fMatrixProc(state, bitmapXY, count, x, y); |
680 | 808 |
681 void (*proc)(uint32_t bitmapXY[], int count, unsigned mx, unsigned my); | 809 void (*proc)(uint32_t bitmapXY[], int count, unsigned mx, unsigned my); |
682 | 810 |
683 // There are four formats possible: | 811 // There are four formats possible: |
684 // scale -vs- affine | 812 // scale -vs- affine |
685 // filter -vs- nofilter | 813 // filter -vs- nofilter |
686 if (state.fInvType <= (SkMatrix::kTranslate_Mask | SkMatrix::kScale_Mask)) { | 814 if (state.fInvType <= (SkMatrix::kTranslate_Mask | SkMatrix::kScale_Mask)) { |
687 proc = state.fDoFilter ? check_scale_filter : check_scale_nofilter; | 815 proc = state.fFilterQuality != kNone_BitmapFilter ? check_scale_filter :
check_scale_nofilter; |
688 } else { | 816 } else { |
689 proc = state.fDoFilter ? check_affine_filter : check_affine_nofilter; | 817 proc = state.fFilterQuality != kNone_BitmapFilter ? check_affine_filter
: check_affine_nofilter; |
690 } | 818 } |
691 proc(bitmapXY, count, state.fBitmap->width(), state.fBitmap->height()); | 819 proc(bitmapXY, count, state.fBitmap->width(), state.fBitmap->height()); |
692 } | 820 } |
693 | 821 |
694 SkBitmapProcState::MatrixProc SkBitmapProcState::getMatrixProc() const { | 822 SkBitmapProcState::MatrixProc SkBitmapProcState::getMatrixProc() const { |
695 return DebugMatrixProc; | 823 return DebugMatrixProc; |
696 } | 824 } |
697 | 825 |
698 #endif | 826 #endif |
699 | 827 |
(...skipping 14 matching lines...) Expand all Loading... |
714 if (fInvType <= (SkMatrix::kTranslate_Mask | SkMatrix::kScale_Mask)) { | 842 if (fInvType <= (SkMatrix::kTranslate_Mask | SkMatrix::kScale_Mask)) { |
715 size -= 4; // the shared Y (or YY) coordinate | 843 size -= 4; // the shared Y (or YY) coordinate |
716 if (size < 0) { | 844 if (size < 0) { |
717 size = 0; | 845 size = 0; |
718 } | 846 } |
719 size >>= 1; | 847 size >>= 1; |
720 } else { | 848 } else { |
721 size >>= 2; | 849 size >>= 2; |
722 } | 850 } |
723 | 851 |
724 if (fDoFilter) { | 852 if (fFilterQuality != kNone_BitmapFilter) { |
725 size >>= 1; | 853 size >>= 1; |
726 } | 854 } |
727 | 855 |
728 return size; | 856 return size; |
729 } | 857 } |
OLD | NEW |