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

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: nits from robert 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
« no previous file with comments | « src/core/SkBitmapProcState.h ('k') | src/core/SkBitmapProcState_matrix.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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.
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
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
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
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
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
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
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 }
OLDNEW
« no previous file with comments | « src/core/SkBitmapProcState.h ('k') | src/core/SkBitmapProcState_matrix.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698