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