Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(453)

Side by Side Diff: src/core/SkBitmapProcState.cpp

Issue 18978014: Working plumb of image scaling: (Closed) Base URL: https://skia.googlecode.com/svn/trunk
Patch Set: Added a comment about passing the clip Created 7 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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
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
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
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
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
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
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
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 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698