Chromium Code Reviews| 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 void SkBitmapProcState::possiblyScaleImage() { | |
|
reed1
2013/07/12 14:01:06
I think we may need to pass in the clip-bounds, so
humper
2013/07/12 17:18:01
Is it OK to leave this as a TODO comment for now a
| |
| 94 | |
| 95 if (fFilterQuality != kHQ_BitmapFilter) { | |
| 96 return; | |
| 97 } | |
| 98 | |
| 99 // STEP 1: UPSAMPLE? | |
| 100 | |
| 101 // Check to see if the transformation matrix is scaling up, and if | |
| 102 // the matrix is simple, and if we're doing high quality scaling. | |
| 103 // If so, do the bitmap scale here and remove the scaling component from the matrix. | |
| 104 | |
| 105 if (fUnitInvMatrix.getType() <= (SkMatrix::kScale_Mask | SkMatrix::kTranslat e_Mask) && | |
| 106 (fUnitInvMatrix.getScaleX() < 1 || fUnitInvMatrix.getScaleY() < 1) && | |
| 107 fOrigBitmap.config() == SkBitmap::kARGB_8888_Config) { | |
| 108 | |
| 109 // All the criteria are met; let's make a new bitmap. | |
| 110 fScaledBitmap.setConfig(SkBitmap::kARGB_8888_Config, | |
| 111 (int)(fOrigBitmap.width() / fUnitInvMatrix.getSc aleX()), | |
| 112 (int)(fOrigBitmap.height() / fUnitInvMatrix.getS caleY())); | |
| 113 fScaledBitmap.allocPixels(); | |
| 114 fOrigBitmap.scale(&fScaledBitmap); | |
| 115 fBitmap = &fScaledBitmap; | |
| 116 | |
| 117 // set the inv matrix type to translate-only; | |
| 118 | |
| 119 fUnitInvMatrix.setTranslate( 1/fUnitInvMatrix.getScaleX() * fUnitInvMatr ix.getTranslateX(), | |
| 120 1/fUnitInvMatrix.getScaleY() * fUnitInvMatr ix.getTranslateY() ); | |
| 121 | |
| 122 // no need for any further filtering; we just did it! | |
| 123 | |
| 124 fFilterQuality = kNone_BitmapFilter; | |
| 125 | |
| 126 return; | |
| 127 } | |
| 128 | |
| 129 if (!fOrigBitmap.hasMipMap()) { | |
| 130 | |
| 131 // STEP 2: DOWNSAMPLE | |
| 132 | |
| 133 // Check to see if the transformation matrix is scaling *down*. | |
| 134 // If so, automatically build mipmaps. | |
| 135 | |
| 136 SkPoint v1, v2; | |
| 137 | |
| 138 // conservatively estimate if the matrix is scaling down by seeing | |
| 139 // what its upper left 2x2 portion does to two unit vectors. | |
| 140 | |
| 141 v1.fX = fUnitInvMatrix.getScaleX(); | |
| 142 v1.fY = fUnitInvMatrix.getSkewY(); | |
| 143 | |
| 144 v2.fX = fUnitInvMatrix.getSkewX(); | |
| 145 v2.fY = fUnitInvMatrix.getScaleY(); | |
| 146 | |
| 147 if (v1.fX * v1.fX + v1.fY * v1.fY > 1 || | |
| 148 v2.fX * v2.fX + v2.fY * v2.fY > 1) { | |
| 149 fOrigBitmap.buildMipMap(); | |
| 150 | |
| 151 // Now that we've built the mipmaps and we know we're downsampling, | |
| 152 // downgrade to bilinear interpolation for the mip level. | |
| 153 | |
| 154 fFilterQuality = kBilerp_BitmapFilter; | |
| 155 } | |
| 156 } | |
| 157 | |
| 158 if (fOrigBitmap.hasMipMap()) { | |
| 159 | |
| 160 // STEP 3: We've got mipmaps, let's choose the closest level as our rend er | |
| 161 // source and adjust the matrix accordingly. | |
| 162 | |
| 163 int shift = fOrigBitmap.extractMipLevel(&fScaledBitmap, | |
| 164 SkScalarToFixed(fUnitInvMatrix.g etScaleX()), | |
| 165 SkScalarToFixed(fUnitInvMatrix.g etSkewY())); | |
| 166 | |
| 167 if (shift > 0) { | |
| 168 SkScalar scale = SkFixedToScalar(SK_Fixed1 >> shift); | |
| 169 fUnitInvMatrix.postScale(scale, scale); | |
| 170 fBitmap = &fScaledBitmap; | |
| 171 } | |
| 172 } | |
| 173 } | |
| 174 | |
| 175 void SkBitmapProcState::endContext() { | |
| 176 SkDELETE(fBitmapFilter); | |
| 177 } | |
| 178 | |
| 93 bool SkBitmapProcState::chooseProcs(const SkMatrix& inv, const SkPaint& paint) { | 179 bool SkBitmapProcState::chooseProcs(const SkMatrix& inv, const SkPaint& paint) { |
| 94 if (fOrigBitmap.width() == 0 || fOrigBitmap.height() == 0) { | 180 if (fOrigBitmap.width() == 0 || fOrigBitmap.height() == 0) { |
| 95 return false; | 181 return false; |
| 96 } | 182 } |
| 97 | 183 |
| 98 const SkMatrix* m; | |
| 99 bool trivial_matrix = (inv.getType() & ~SkMatrix::kTranslate_Mask) == 0; | 184 bool trivial_matrix = (inv.getType() & ~SkMatrix::kTranslate_Mask) == 0; |
|
reed1
2013/07/12 14:01:06
This is probably too soon to be computing "trivial
humper
2013/07/12 17:18:01
trivial_matrix is used immediately (so we need it
reed1
2013/07/12 18:33:24
Yes, lets recompute it, either when we know we've
| |
| 100 bool clamp_clamp = SkShader::kClamp_TileMode == fTileModeX && | 185 bool clamp_clamp = SkShader::kClamp_TileMode == fTileModeX && |
| 101 SkShader::kClamp_TileMode == fTileModeY; | 186 SkShader::kClamp_TileMode == fTileModeY; |
| 102 | 187 |
| 103 if (clamp_clamp || trivial_matrix) { | 188 fUnitInvMatrix = inv; |
|
reed1
2013/07/12 14:01:06
I see now that your change meas we *always* use fU
humper
2013/07/12 17:18:01
Done.
| |
| 104 m = &inv; | 189 if (!(clamp_clamp || trivial_matrix)) { |
| 105 } else { | |
| 106 fUnitInvMatrix = inv; | |
| 107 fUnitInvMatrix.postIDiv(fOrigBitmap.width(), fOrigBitmap.height()); | 190 fUnitInvMatrix.postIDiv(fOrigBitmap.width(), fOrigBitmap.height()); |
| 108 m = &fUnitInvMatrix; | |
| 109 } | 191 } |
| 110 | 192 |
| 111 fBitmap = &fOrigBitmap; | 193 fBitmap = &fOrigBitmap; |
| 112 if (fOrigBitmap.hasMipMap()) { | 194 |
| 113 int shift = fOrigBitmap.extractMipLevel(&fMipBitmap, | 195 // initialize our filter quality to the one requested by the caller. |
| 114 SkScalarToFixed(m->getScaleX()), | 196 // We may downgrade it later if we determine that we either don't need |
| 115 SkScalarToFixed(m->getSkewY())); | 197 // or can't provide as high a quality filtering as the user requested. |
| 116 | 198 |
| 117 if (shift > 0) { | 199 fFilterQuality = kNone_BitmapFilter; |
| 118 if (m != &fUnitInvMatrix) { | 200 if (paint.isFilterBitmap()) { |
| 119 fUnitInvMatrix = *m; | 201 if (paint.getFlags() & SkPaint::kHighQualityFilterBitmap_Flag) { |
| 120 m = &fUnitInvMatrix; | 202 fFilterQuality = kHQ_BitmapFilter; |
| 121 } | 203 } else { |
| 122 | 204 fFilterQuality = kBilerp_BitmapFilter; |
| 123 SkScalar scale = SkFixedToScalar(SK_Fixed1 >> shift); | |
| 124 fUnitInvMatrix.postScale(scale, scale); | |
| 125 | |
| 126 // now point here instead of fOrigBitmap | |
| 127 fBitmap = &fMipBitmap; | |
| 128 } | 205 } |
| 129 } | 206 } |
| 130 | 207 |
| 131 // wack our matrix to exactly no-scale, if we're really close to begin with | 208 // possiblyScaleImage will look to see if it can rescale the image as a |
| 132 if (matrix_only_scale_translate(*m)) { | 209 // preprocess; either by scaling up to the target size, or by selecting |
| 210 // a nearby mipmap level. If it does, it will adjust the working | |
| 211 // matrix as well as the working bitmap. It may also adjust the filter | |
| 212 // quality to avoid re-filtering an already perfectly scaled image. | |
| 213 | |
| 214 possiblyScaleImage(); | |
|
reed1
2013/07/12 14:01:06
nit: this->possiblyScaleImage();
humper
2013/07/12 17:18:01
Done.
| |
| 215 | |
| 216 // Now that all possible changes to the matrix have taken place, check | |
| 217 // to see if we're really close to a no-scale matrix. If so, explicitly | |
| 218 // set it to be so. Subsequent code may inspect this matrix to choose | |
| 219 // a faster path in this case. | |
| 220 | |
| 221 if (matrix_only_scale_translate(fUnitInvMatrix)) { | |
|
reed1
2013/07/12 14:01:06
unrelated to this CL, but this guy should probably
humper
2013/07/12 17:18:01
Done.
| |
| 133 SkMatrix forward; | 222 SkMatrix forward; |
| 134 if (m->invert(&forward)) { | 223 if (fUnitInvMatrix.invert(&forward)) { |
| 135 if (clamp_clamp ? just_trans_clamp(forward, *fBitmap) | 224 if (clamp_clamp ? just_trans_clamp(forward, *fBitmap) |
| 136 : just_trans_general(forward)) { | 225 : just_trans_general(forward)) { |
| 137 SkScalar tx = -SkScalarRoundToScalar(forward.getTranslateX()); | 226 SkScalar tx = -SkScalarRoundToScalar(forward.getTranslateX()); |
| 138 SkScalar ty = -SkScalarRoundToScalar(forward.getTranslateY()); | 227 SkScalar ty = -SkScalarRoundToScalar(forward.getTranslateY()); |
| 139 fUnitInvMatrix.setTranslate(tx, ty); | 228 fUnitInvMatrix.setTranslate(tx, ty); |
| 140 m = &fUnitInvMatrix; | 229 |
| 141 // now the following code will sniff m, and decide to take the | |
| 142 // fast case (since m is purely translate). | |
| 143 } | 230 } |
| 144 } | 231 } |
| 145 } | 232 } |
| 146 | 233 |
| 147 // Below this point, we should never refer to the inv parameter, since we | 234 // Below this point, we should never refer to the inv parameter, since we |
| 148 // may be using a munged version for "our" inverse. | 235 // may be using a munged version for "our" inverse. |
| 149 | 236 |
| 150 fInvMatrix = m; | 237 fInvMatrix = &fUnitInvMatrix; |
| 151 fInvProc = m->getMapXYProc(); | 238 fInvProc = fInvMatrix->getMapXYProc(); |
|
reed1
2013/07/12 14:01:06
Maybe we no longer need fInvMatrix as a pointer an
humper
2013/07/12 17:18:01
Done.
| |
| 152 fInvType = m->getType(); | 239 fInvType = fInvMatrix->getType(); |
| 153 fInvSx = SkScalarToFixed(m->getScaleX()); | 240 fInvSx = SkScalarToFixed(fInvMatrix->getScaleX()); |
| 154 fInvSxFractionalInt = SkScalarToFractionalInt(m->getScaleX()); | 241 fInvSxFractionalInt = SkScalarToFractionalInt(fInvMatrix->getScaleX()); |
| 155 fInvKy = SkScalarToFixed(m->getSkewY()); | 242 fInvKy = SkScalarToFixed(fInvMatrix->getSkewY()); |
| 156 fInvKyFractionalInt = SkScalarToFractionalInt(m->getSkewY()); | 243 fInvKyFractionalInt = SkScalarToFractionalInt(fInvMatrix->getSkewY()); |
| 157 | 244 |
| 158 fAlphaScale = SkAlpha255To256(paint.getAlpha()); | 245 fAlphaScale = SkAlpha255To256(paint.getAlpha()); |
| 159 | 246 |
| 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; | 247 fShaderProc32 = NULL; |
| 170 fShaderProc16 = NULL; | 248 fShaderProc16 = NULL; |
| 171 fSampleProc32 = NULL; | 249 fSampleProc32 = NULL; |
| 172 fSampleProc16 = NULL; | 250 fSampleProc16 = NULL; |
| 173 | 251 |
| 252 if (kHQ_BitmapFilter == fFilterQuality) { | |
|
reed1
2013/07/12 14:01:06
*maybe* we can add an ASSERT here that claims that
humper
2013/07/12 17:18:01
Done.
| |
| 253 // If this is still set, that means we wanted HQ sampling | |
| 254 // but couldn't do it as a preprocess. Let's try to install | |
| 255 // the scanline version of the HQ sampler. If that process fails, | |
| 256 // downgrade to bilerp. | |
| 257 | |
| 258 // NOTE: Might need to be careful here in the future when we want | |
| 259 // to have the platform proc have a shot at this; it's possible that | |
| 260 // the chooseBitmapFilterProc will fail to install a shader but a | |
| 261 // platform-specific one might succeed, so it might be premature here | |
| 262 // to fall back to bilerp. This needs thought. | |
| 263 | |
| 264 fShaderProc32 = this->chooseBitmapFilterProc(); | |
| 265 if (!fShaderProc32) { | |
| 266 fFilterQuality = kBilerp_BitmapFilter; | |
| 267 } | |
| 268 } | |
| 269 | |
| 270 if (kBilerp_BitmapFilter == fFilterQuality) { | |
| 271 // Only try bilerp if the matrix is "interesting" and | |
| 272 // the image has a suitable size. | |
| 273 | |
| 274 if (fInvType < SkMatrix::kTranslate_Mask || | |
| 275 !valid_for_filtering(fBitmap->width() | fBitmap->height())) { | |
| 276 fFilterQuality = kNone_BitmapFilter; | |
| 277 } | |
| 278 } | |
| 279 | |
| 280 // At this point, we know exactly what kind of sampling the per-scanline | |
| 281 // shader will perform. | |
| 282 | |
| 174 fMatrixProc = this->chooseMatrixProc(trivial_matrix); | 283 fMatrixProc = this->chooseMatrixProc(trivial_matrix); |
| 175 if (NULL == fMatrixProc) { | 284 if (NULL == fMatrixProc) { |
| 176 return false; | 285 return false; |
| 177 } | 286 } |
| 178 | 287 |
| 179 /////////////////////////////////////////////////////////////////////// | 288 /////////////////////////////////////////////////////////////////////// |
| 180 | 289 |
| 181 int index = 0; | 290 // 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 | 291 // still set to HQ by the time we get here, then we must have installed |
| 183 index |= 1; | 292 // 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 | 293 |
| 213 #if !SK_ARM_NEON_IS_ALWAYS | 294 if (fFilterQuality < kHQ_BitmapFilter) { |
| 214 static const SampleProc32 gSkBitmapProcStateSample32[] = { | 295 |
| 215 S32_opaque_D32_nofilter_DXDY, | 296 int index = 0; |
| 216 S32_alpha_D32_nofilter_DXDY, | 297 if (fAlphaScale < 256) { // note: this distinction is not used for D16 |
| 217 S32_opaque_D32_nofilter_DX, | 298 index |= 1; |
| 218 S32_alpha_D32_nofilter_DX, | 299 } |
| 219 S32_opaque_D32_filter_DXDY, | 300 if (fInvType <= (SkMatrix::kTranslate_Mask | SkMatrix::kScale_Mask)) { |
| 220 S32_alpha_D32_filter_DXDY, | 301 index |= 2; |
| 221 S32_opaque_D32_filter_DX, | 302 } |
| 222 S32_alpha_D32_filter_DX, | 303 if (fFilterQuality != kNone_BitmapFilter) { |
| 304 index |= 4; | |
| 305 } | |
| 306 // bits 3,4,5 encoding the source bitmap format | |
| 307 switch (fBitmap->config()) { | |
| 308 case SkBitmap::kARGB_8888_Config: | |
| 309 index |= 0; | |
| 310 break; | |
| 311 case SkBitmap::kRGB_565_Config: | |
| 312 index |= 8; | |
| 313 break; | |
| 314 case SkBitmap::kIndex8_Config: | |
| 315 index |= 16; | |
| 316 break; | |
| 317 case SkBitmap::kARGB_4444_Config: | |
| 318 index |= 24; | |
| 319 break; | |
| 320 case SkBitmap::kA8_Config: | |
| 321 index |= 32; | |
| 322 fPaintPMColor = SkPreMultiplyColor(paint.getColor()); | |
| 323 break; | |
| 324 default: | |
| 325 return false; | |
| 326 } | |
| 223 | 327 |
| 224 S16_opaque_D32_nofilter_DXDY, | 328 #if !SK_ARM_NEON_IS_ALWAYS |
| 225 S16_alpha_D32_nofilter_DXDY, | 329 static const SampleProc32 gSkBitmapProcStateSample32[] = { |
| 226 S16_opaque_D32_nofilter_DX, | 330 S32_opaque_D32_nofilter_DXDY, |
| 227 S16_alpha_D32_nofilter_DX, | 331 S32_alpha_D32_nofilter_DXDY, |
| 228 S16_opaque_D32_filter_DXDY, | 332 S32_opaque_D32_nofilter_DX, |
| 229 S16_alpha_D32_filter_DXDY, | 333 S32_alpha_D32_nofilter_DX, |
| 230 S16_opaque_D32_filter_DX, | 334 S32_opaque_D32_filter_DXDY, |
| 231 S16_alpha_D32_filter_DX, | 335 S32_alpha_D32_filter_DXDY, |
| 336 S32_opaque_D32_filter_DX, | |
| 337 S32_alpha_D32_filter_DX, | |
| 232 | 338 |
| 233 SI8_opaque_D32_nofilter_DXDY, | 339 S16_opaque_D32_nofilter_DXDY, |
| 234 SI8_alpha_D32_nofilter_DXDY, | 340 S16_alpha_D32_nofilter_DXDY, |
| 235 SI8_opaque_D32_nofilter_DX, | 341 S16_opaque_D32_nofilter_DX, |
| 236 SI8_alpha_D32_nofilter_DX, | 342 S16_alpha_D32_nofilter_DX, |
| 237 SI8_opaque_D32_filter_DXDY, | 343 S16_opaque_D32_filter_DXDY, |
| 238 SI8_alpha_D32_filter_DXDY, | 344 S16_alpha_D32_filter_DXDY, |
| 239 SI8_opaque_D32_filter_DX, | 345 S16_opaque_D32_filter_DX, |
| 240 SI8_alpha_D32_filter_DX, | 346 S16_alpha_D32_filter_DX, |
| 241 | 347 |
| 242 S4444_opaque_D32_nofilter_DXDY, | 348 SI8_opaque_D32_nofilter_DXDY, |
| 243 S4444_alpha_D32_nofilter_DXDY, | 349 SI8_alpha_D32_nofilter_DXDY, |
| 244 S4444_opaque_D32_nofilter_DX, | 350 SI8_opaque_D32_nofilter_DX, |
| 245 S4444_alpha_D32_nofilter_DX, | 351 SI8_alpha_D32_nofilter_DX, |
| 246 S4444_opaque_D32_filter_DXDY, | 352 SI8_opaque_D32_filter_DXDY, |
| 247 S4444_alpha_D32_filter_DXDY, | 353 SI8_alpha_D32_filter_DXDY, |
| 248 S4444_opaque_D32_filter_DX, | 354 SI8_opaque_D32_filter_DX, |
| 249 S4444_alpha_D32_filter_DX, | 355 SI8_alpha_D32_filter_DX, |
| 250 | 356 |
| 251 // A8 treats alpha/opaque the same (equally efficient) | 357 S4444_opaque_D32_nofilter_DXDY, |
| 252 SA8_alpha_D32_nofilter_DXDY, | 358 S4444_alpha_D32_nofilter_DXDY, |
| 253 SA8_alpha_D32_nofilter_DXDY, | 359 S4444_opaque_D32_nofilter_DX, |
| 254 SA8_alpha_D32_nofilter_DX, | 360 S4444_alpha_D32_nofilter_DX, |
| 255 SA8_alpha_D32_nofilter_DX, | 361 S4444_opaque_D32_filter_DXDY, |
| 256 SA8_alpha_D32_filter_DXDY, | 362 S4444_alpha_D32_filter_DXDY, |
| 257 SA8_alpha_D32_filter_DXDY, | 363 S4444_opaque_D32_filter_DX, |
| 258 SA8_alpha_D32_filter_DX, | 364 S4444_alpha_D32_filter_DX, |
| 259 SA8_alpha_D32_filter_DX | |
| 260 }; | |
| 261 | 365 |
| 262 static const SampleProc16 gSkBitmapProcStateSample16[] = { | 366 // A8 treats alpha/opaque the same (equally efficient) |
| 263 S32_D16_nofilter_DXDY, | 367 SA8_alpha_D32_nofilter_DXDY, |
| 264 S32_D16_nofilter_DX, | 368 SA8_alpha_D32_nofilter_DXDY, |
| 265 S32_D16_filter_DXDY, | 369 SA8_alpha_D32_nofilter_DX, |
| 266 S32_D16_filter_DX, | 370 SA8_alpha_D32_nofilter_DX, |
| 371 SA8_alpha_D32_filter_DXDY, | |
| 372 SA8_alpha_D32_filter_DXDY, | |
| 373 SA8_alpha_D32_filter_DX, | |
| 374 SA8_alpha_D32_filter_DX | |
| 375 }; | |
| 267 | 376 |
| 268 S16_D16_nofilter_DXDY, | 377 static const SampleProc16 gSkBitmapProcStateSample16[] = { |
| 269 S16_D16_nofilter_DX, | 378 S32_D16_nofilter_DXDY, |
| 270 S16_D16_filter_DXDY, | 379 S32_D16_nofilter_DX, |
| 271 S16_D16_filter_DX, | 380 S32_D16_filter_DXDY, |
| 381 S32_D16_filter_DX, | |
| 272 | 382 |
| 273 SI8_D16_nofilter_DXDY, | 383 S16_D16_nofilter_DXDY, |
| 274 SI8_D16_nofilter_DX, | 384 S16_D16_nofilter_DX, |
| 275 SI8_D16_filter_DXDY, | 385 S16_D16_filter_DXDY, |
| 276 SI8_D16_filter_DX, | 386 S16_D16_filter_DX, |
| 277 | 387 |
| 278 // Don't support 4444 -> 565 | 388 SI8_D16_nofilter_DXDY, |
| 279 NULL, NULL, NULL, NULL, | 389 SI8_D16_nofilter_DX, |
| 280 // Don't support A8 -> 565 | 390 SI8_D16_filter_DXDY, |
| 281 NULL, NULL, NULL, NULL | 391 SI8_D16_filter_DX, |
| 282 }; | |
| 283 #endif | |
| 284 | 392 |
| 285 fSampleProc32 = SK_ARM_NEON_WRAP(gSkBitmapProcStateSample32)[index]; | 393 // Don't support 4444 -> 565 |
| 286 index >>= 1; // shift away any opaque/alpha distinction | 394 NULL, NULL, NULL, NULL, |
| 287 fSampleProc16 = SK_ARM_NEON_WRAP(gSkBitmapProcStateSample16)[index]; | 395 // Don't support A8 -> 565 |
| 396 NULL, NULL, NULL, NULL | |
| 397 }; | |
| 398 #endif | |
| 288 | 399 |
| 289 // our special-case shaderprocs | 400 fSampleProc32 = SK_ARM_NEON_WRAP(gSkBitmapProcStateSample32)[index]; |
| 290 if (SK_ARM_NEON_WRAP(S16_D16_filter_DX) == fSampleProc16) { | 401 index >>= 1; // shift away any opaque/alpha distinction |
| 291 if (clamp_clamp) { | 402 fSampleProc16 = SK_ARM_NEON_WRAP(gSkBitmapProcStateSample16)[index]; |
| 292 fShaderProc16 = SK_ARM_NEON_WRAP(Clamp_S16_D16_filter_DX_shaderproc) ; | 403 |
| 293 } else if (SkShader::kRepeat_TileMode == fTileModeX && | 404 // our special-case shaderprocs |
| 294 SkShader::kRepeat_TileMode == fTileModeY) { | 405 if (SK_ARM_NEON_WRAP(S16_D16_filter_DX) == fSampleProc16) { |
| 295 fShaderProc16 = SK_ARM_NEON_WRAP(Repeat_S16_D16_filter_DX_shaderproc ); | 406 if (clamp_clamp) { |
| 407 fShaderProc16 = SK_ARM_NEON_WRAP(Clamp_S16_D16_filter_DX_shaderp roc); | |
| 408 } else if (SkShader::kRepeat_TileMode == fTileModeX && | |
| 409 SkShader::kRepeat_TileMode == fTileModeY) { | |
| 410 fShaderProc16 = SK_ARM_NEON_WRAP(Repeat_S16_D16_filter_DX_shader proc); | |
| 411 } | |
| 412 } else if (SK_ARM_NEON_WRAP(SI8_opaque_D32_filter_DX) == fSampleProc32 & & clamp_clamp) { | |
| 413 fShaderProc32 = SK_ARM_NEON_WRAP(Clamp_SI8_opaque_D32_filter_DX_shad erproc); | |
| 296 } | 414 } |
| 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 | 415 |
| 301 if (NULL == fShaderProc32) { | 416 if (NULL == fShaderProc32) { |
| 302 fShaderProc32 = this->chooseShaderProc32(); | 417 fShaderProc32 = this->chooseShaderProc32(); |
| 303 } | 418 } |
| 304 | |
| 305 if (NULL == fShaderProc32) { | |
| 306 fShaderProc32 = this->chooseBitmapFilterProc(paint); | |
| 307 } | 419 } |
| 308 | 420 |
| 309 // see if our platform has any accelerated overrides | 421 // see if our platform has any accelerated overrides |
| 310 this->platformProcs(); | 422 this->platformProcs(); |
| 311 | 423 |
| 312 return true; | 424 return true; |
| 313 } | 425 } |
| 314 | 426 |
| 315 static void Clamp_S32_D32_nofilter_trans_shaderproc(const SkBitmapProcState& s, | 427 static void Clamp_S32_D32_nofilter_trans_shaderproc(const SkBitmapProcState& s, |
| 316 int x, int y, | 428 int x, int y, |
| 317 SkPMColor* SK_RESTRICT color s, | 429 SkPMColor* SK_RESTRICT color s, |
| 318 int count) { | 430 int count) { |
| 319 SkASSERT(((s.fInvType & ~SkMatrix::kTranslate_Mask)) == 0); | 431 SkASSERT(((s.fInvType & ~SkMatrix::kTranslate_Mask)) == 0); |
| 320 SkASSERT(s.fInvKy == 0); | 432 SkASSERT(s.fInvKy == 0); |
| 321 SkASSERT(count > 0 && colors != NULL); | 433 SkASSERT(count > 0 && colors != NULL); |
| 322 SkASSERT(!s.fDoFilter); | 434 SkASSERT(SkBitmapProcState::kNone_BitmapFilter == s.fFilterQuality); |
| 323 | 435 |
| 324 const int maxX = s.fBitmap->width() - 1; | 436 const int maxX = s.fBitmap->width() - 1; |
| 325 const int maxY = s.fBitmap->height() - 1; | 437 const int maxY = s.fBitmap->height() - 1; |
| 326 int ix = s.fFilterOneX + x; | 438 int ix = s.fFilterOneX + x; |
| 327 int iy = SkClampMax(s.fFilterOneY + y, maxY); | 439 int iy = SkClampMax(s.fFilterOneY + y, maxY); |
| 328 #ifdef SK_DEBUG | 440 #ifdef SK_DEBUG |
| 329 { | 441 { |
| 330 SkPoint pt; | 442 SkPoint pt; |
| 331 s.fInvProc(*s.fInvMatrix, SkIntToScalar(x) + SK_ScalarHalf, | 443 s.fInvProc(*s.fInvMatrix, SkIntToScalar(x) + SK_ScalarHalf, |
| 332 SkIntToScalar(y) + SK_ScalarHalf, &pt); | 444 SkIntToScalar(y) + SK_ScalarHalf, &pt); |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 386 return x; | 498 return x; |
| 387 } | 499 } |
| 388 | 500 |
| 389 static void Repeat_S32_D32_nofilter_trans_shaderproc(const SkBitmapProcState& s, | 501 static void Repeat_S32_D32_nofilter_trans_shaderproc(const SkBitmapProcState& s, |
| 390 int x, int y, | 502 int x, int y, |
| 391 SkPMColor* SK_RESTRICT colo rs, | 503 SkPMColor* SK_RESTRICT colo rs, |
| 392 int count) { | 504 int count) { |
| 393 SkASSERT(((s.fInvType & ~SkMatrix::kTranslate_Mask)) == 0); | 505 SkASSERT(((s.fInvType & ~SkMatrix::kTranslate_Mask)) == 0); |
| 394 SkASSERT(s.fInvKy == 0); | 506 SkASSERT(s.fInvKy == 0); |
| 395 SkASSERT(count > 0 && colors != NULL); | 507 SkASSERT(count > 0 && colors != NULL); |
| 396 SkASSERT(!s.fDoFilter); | 508 SkASSERT(SkBitmapProcState::kNone_BitmapFilter == s.fFilterQuality); |
| 397 | 509 |
| 398 const int stopX = s.fBitmap->width(); | 510 const int stopX = s.fBitmap->width(); |
| 399 const int stopY = s.fBitmap->height(); | 511 const int stopY = s.fBitmap->height(); |
| 400 int ix = s.fFilterOneX + x; | 512 int ix = s.fFilterOneX + x; |
| 401 int iy = sk_int_mod(s.fFilterOneY + y, stopY); | 513 int iy = sk_int_mod(s.fFilterOneY + y, stopY); |
| 402 #ifdef SK_DEBUG | 514 #ifdef SK_DEBUG |
| 403 { | 515 { |
| 404 SkPoint pt; | 516 SkPoint pt; |
| 405 s.fInvProc(*s.fInvMatrix, SkIntToScalar(x) + SK_ScalarHalf, | 517 s.fInvProc(*s.fInvMatrix, SkIntToScalar(x) + SK_ScalarHalf, |
| 406 SkIntToScalar(y) + SK_ScalarHalf, &pt); | 518 SkIntToScalar(y) + SK_ScalarHalf, &pt); |
| (...skipping 25 matching lines...) Expand all Loading... | |
| 432 int count) { | 544 int count) { |
| 433 SkASSERT((s.fInvType & ~(SkMatrix::kTranslate_Mask | SkMatrix::kScale_Mask)) == 0); | 545 SkASSERT((s.fInvType & ~(SkMatrix::kTranslate_Mask | SkMatrix::kScale_Mask)) == 0); |
| 434 SkASSERT(s.fInvKy == 0); | 546 SkASSERT(s.fInvKy == 0); |
| 435 SkASSERT(count > 0 && colors != NULL); | 547 SkASSERT(count > 0 && colors != NULL); |
| 436 SkASSERT(1 == s.fBitmap->width()); | 548 SkASSERT(1 == s.fBitmap->width()); |
| 437 | 549 |
| 438 int iY0; | 550 int iY0; |
| 439 int iY1 SK_INIT_TO_AVOID_WARNING; | 551 int iY1 SK_INIT_TO_AVOID_WARNING; |
| 440 int iSubY SK_INIT_TO_AVOID_WARNING; | 552 int iSubY SK_INIT_TO_AVOID_WARNING; |
| 441 | 553 |
| 442 if (s.fDoFilter) { | 554 if (s.fFilterQuality != SkBitmapProcState::kNone_BitmapFilter) { |
| 443 SkBitmapProcState::MatrixProc mproc = s.getMatrixProc(); | 555 SkBitmapProcState::MatrixProc mproc = s.getMatrixProc(); |
| 444 uint32_t xy[2]; | 556 uint32_t xy[2]; |
| 445 | 557 |
| 446 mproc(s, xy, 1, x, y); | 558 mproc(s, xy, 1, x, y); |
| 447 | 559 |
| 448 iY0 = xy[0] >> 18; | 560 iY0 = xy[0] >> 18; |
| 449 iY1 = xy[0] & 0x3FFF; | 561 iY1 = xy[0] & 0x3FFF; |
| 450 iSubY = (xy[0] >> 14) & 0xF; | 562 iSubY = (xy[0] >> 14) & 0xF; |
| 451 } else { | 563 } else { |
| 452 int yTemp; | 564 int yTemp; |
| (...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 513 } | 625 } |
| 514 | 626 |
| 515 SkASSERT(iY0 == iY2); | 627 SkASSERT(iY0 == iY2); |
| 516 } | 628 } |
| 517 #endif | 629 #endif |
| 518 } | 630 } |
| 519 | 631 |
| 520 const SkPMColor* row0 = s.fBitmap->getAddr32(0, iY0); | 632 const SkPMColor* row0 = s.fBitmap->getAddr32(0, iY0); |
| 521 SkPMColor color; | 633 SkPMColor color; |
| 522 | 634 |
| 523 if (s.fDoFilter) { | 635 if (s.fFilterQuality != SkBitmapProcState::kNone_BitmapFilter) { |
| 524 const SkPMColor* row1 = s.fBitmap->getAddr32(0, iY1); | 636 const SkPMColor* row1 = s.fBitmap->getAddr32(0, iY1); |
| 525 | 637 |
| 526 if (s.fAlphaScale < 256) { | 638 if (s.fAlphaScale < 256) { |
| 527 Filter_32_alpha(iSubY, *row0, *row1, &color, s.fAlphaScale); | 639 Filter_32_alpha(iSubY, *row0, *row1, &color, s.fAlphaScale); |
| 528 } else { | 640 } else { |
| 529 Filter_32_opaque(iSubY, *row0, *row1, &color); | 641 Filter_32_opaque(iSubY, *row0, *row1, &color); |
| 530 } | 642 } |
| 531 } else { | 643 } else { |
| 532 if (s.fAlphaScale < 256) { | 644 if (s.fAlphaScale < 256) { |
| 533 color = SkAlphaMulQ(*row0, s.fAlphaScale); | 645 color = SkAlphaMulQ(*row0, s.fAlphaScale); |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 569 | 681 |
| 570 SkBitmapProcState::ShaderProc32 SkBitmapProcState::chooseShaderProc32() { | 682 SkBitmapProcState::ShaderProc32 SkBitmapProcState::chooseShaderProc32() { |
| 571 | 683 |
| 572 if (SkBitmap::kARGB_8888_Config != fBitmap->config()) { | 684 if (SkBitmap::kARGB_8888_Config != fBitmap->config()) { |
| 573 return NULL; | 685 return NULL; |
| 574 } | 686 } |
| 575 | 687 |
| 576 static const unsigned kMask = SkMatrix::kTranslate_Mask | SkMatrix::kScale_M ask; | 688 static const unsigned kMask = SkMatrix::kTranslate_Mask | SkMatrix::kScale_M ask; |
| 577 | 689 |
| 578 if (1 == fBitmap->width() && 0 == (fInvType & ~kMask)) { | 690 if (1 == fBitmap->width() && 0 == (fInvType & ~kMask)) { |
| 579 if (!fDoFilter && fInvType <= SkMatrix::kTranslate_Mask && !this->setupF orTranslate()) { | 691 if (kNone_BitmapFilter == fFilterQuality && |
| 692 fInvType <= SkMatrix::kTranslate_Mask && | |
| 693 !this->setupForTranslate()) { | |
| 580 return DoNothing_shaderproc; | 694 return DoNothing_shaderproc; |
| 581 } | 695 } |
| 582 return S32_D32_constX_shaderproc; | 696 return S32_D32_constX_shaderproc; |
| 583 } | 697 } |
| 584 | 698 |
| 585 if (fAlphaScale < 256) { | 699 if (fAlphaScale < 256) { |
| 586 return NULL; | 700 return NULL; |
| 587 } | 701 } |
| 588 if (fInvType > SkMatrix::kTranslate_Mask) { | 702 if (fInvType > SkMatrix::kTranslate_Mask) { |
| 589 return NULL; | 703 return NULL; |
| 590 } | 704 } |
| 591 if (fDoFilter) { | 705 if (fFilterQuality != kNone_BitmapFilter) { |
| 592 return NULL; | 706 return NULL; |
| 593 } | 707 } |
| 594 | 708 |
| 595 SkShader::TileMode tx = (SkShader::TileMode)fTileModeX; | 709 SkShader::TileMode tx = (SkShader::TileMode)fTileModeX; |
| 596 SkShader::TileMode ty = (SkShader::TileMode)fTileModeY; | 710 SkShader::TileMode ty = (SkShader::TileMode)fTileModeY; |
| 597 | 711 |
| 598 if (SkShader::kClamp_TileMode == tx && SkShader::kClamp_TileMode == ty) { | 712 if (SkShader::kClamp_TileMode == tx && SkShader::kClamp_TileMode == ty) { |
| 599 if (this->setupForTranslate()) { | 713 if (this->setupForTranslate()) { |
| 600 return Clamp_S32_D32_nofilter_trans_shaderproc; | 714 return Clamp_S32_D32_nofilter_trans_shaderproc; |
| 601 } | 715 } |
| (...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 677 SkASSERT(count > 0); | 791 SkASSERT(count > 0); |
| 678 | 792 |
| 679 state.fMatrixProc(state, bitmapXY, count, x, y); | 793 state.fMatrixProc(state, bitmapXY, count, x, y); |
| 680 | 794 |
| 681 void (*proc)(uint32_t bitmapXY[], int count, unsigned mx, unsigned my); | 795 void (*proc)(uint32_t bitmapXY[], int count, unsigned mx, unsigned my); |
| 682 | 796 |
| 683 // There are four formats possible: | 797 // There are four formats possible: |
| 684 // scale -vs- affine | 798 // scale -vs- affine |
| 685 // filter -vs- nofilter | 799 // filter -vs- nofilter |
| 686 if (state.fInvType <= (SkMatrix::kTranslate_Mask | SkMatrix::kScale_Mask)) { | 800 if (state.fInvType <= (SkMatrix::kTranslate_Mask | SkMatrix::kScale_Mask)) { |
| 687 proc = state.fDoFilter ? check_scale_filter : check_scale_nofilter; | 801 proc = state.fFilterQuality != kNone_BitmapFilter ? check_scale_filter : check_scale_nofilter; |
| 688 } else { | 802 } else { |
| 689 proc = state.fDoFilter ? check_affine_filter : check_affine_nofilter; | 803 proc = state.fFilterQuality != kNone_BitmapFilter ? check_affine_filter : check_affine_nofilter; |
| 690 } | 804 } |
| 691 proc(bitmapXY, count, state.fBitmap->width(), state.fBitmap->height()); | 805 proc(bitmapXY, count, state.fBitmap->width(), state.fBitmap->height()); |
| 692 } | 806 } |
| 693 | 807 |
| 694 SkBitmapProcState::MatrixProc SkBitmapProcState::getMatrixProc() const { | 808 SkBitmapProcState::MatrixProc SkBitmapProcState::getMatrixProc() const { |
| 695 return DebugMatrixProc; | 809 return DebugMatrixProc; |
| 696 } | 810 } |
| 697 | 811 |
| 698 #endif | 812 #endif |
| 699 | 813 |
| (...skipping 14 matching lines...) Expand all Loading... | |
| 714 if (fInvType <= (SkMatrix::kTranslate_Mask | SkMatrix::kScale_Mask)) { | 828 if (fInvType <= (SkMatrix::kTranslate_Mask | SkMatrix::kScale_Mask)) { |
| 715 size -= 4; // the shared Y (or YY) coordinate | 829 size -= 4; // the shared Y (or YY) coordinate |
| 716 if (size < 0) { | 830 if (size < 0) { |
| 717 size = 0; | 831 size = 0; |
| 718 } | 832 } |
| 719 size >>= 1; | 833 size >>= 1; |
| 720 } else { | 834 } else { |
| 721 size >>= 2; | 835 size >>= 2; |
| 722 } | 836 } |
| 723 | 837 |
| 724 if (fDoFilter) { | 838 if (fFilterQuality != kNone_BitmapFilter) { |
| 725 size >>= 1; | 839 size >>= 1; |
| 726 } | 840 } |
| 727 | 841 |
| 728 return size; | 842 return size; |
| 729 } | 843 } |
| OLD | NEW |