Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 /* | 1 /* |
| 2 * Copyright 2011 Google Inc. | 2 * Copyright 2011 Google Inc. |
| 3 * | 3 * |
| 4 * Use of this source code is governed by a BSD-style license that can be | 4 * Use of this source code is governed by a BSD-style license that can be |
| 5 * found in the LICENSE file. | 5 * found in the LICENSE file. |
| 6 */ | 6 */ |
| 7 | 7 |
| 8 #include "SkBitmapCache.h" | 8 #include "SkBitmapCache.h" |
| 9 #include "SkBitmapController.h" | 9 #include "SkBitmapController.h" |
| 10 #include "SkBitmapProcState.h" | 10 #include "SkBitmapProcState.h" |
| (...skipping 18 matching lines...) Expand all Loading... | |
| 29 extern void SI8_opaque_D32_filter_DX_shaderproc_neon(const void *, int, int, ui nt32_t*, int); | 29 extern void SI8_opaque_D32_filter_DX_shaderproc_neon(const void *, int, int, ui nt32_t*, int); |
| 30 extern void Clamp_SI8_opaque_D32_filter_DX_shaderproc_neon(const void*, int, in t, uint32_t*, int); | 30 extern void Clamp_SI8_opaque_D32_filter_DX_shaderproc_neon(const void*, int, in t, uint32_t*, int); |
| 31 #endif | 31 #endif |
| 32 | 32 |
| 33 extern void Clamp_S32_opaque_D32_nofilter_DX_shaderproc(const void*, int, int, u int32_t*, int); | 33 extern void Clamp_S32_opaque_D32_nofilter_DX_shaderproc(const void*, int, int, u int32_t*, int); |
| 34 | 34 |
| 35 #define NAME_WRAP(x) x | 35 #define NAME_WRAP(x) x |
| 36 #include "SkBitmapProcState_filter.h" | 36 #include "SkBitmapProcState_filter.h" |
| 37 #include "SkBitmapProcState_procs.h" | 37 #include "SkBitmapProcState_procs.h" |
| 38 | 38 |
| 39 SkBitmapProcState::SkBitmapProcState(const SkBitmapProvider& provider, | 39 SkBitmapProcInfo::SkBitmapProcInfo(const SkBitmapProvider& provider, |
|
herb_g
2016/03/02 16:00:18
Line up params and below.
reed1
2016/03/02 16:28:27
Done.
| |
| 40 SkShader::TileMode tmx, SkShader::TileMode tmy) | 40 SkShader::TileMode tmx, SkShader::TileMode tmy) |
| 41 : fProvider(provider) | 41 : fProvider(provider) |
| 42 , fBMState(nullptr) | 42 , fBMState(nullptr) |
| 43 { | 43 { |
| 44 fTileModeX = tmx; | 44 fTileModeX = tmx; |
| 45 fTileModeY = tmy; | 45 fTileModeY = tmy; |
| 46 } | 46 } |
| 47 | 47 |
| 48 SkBitmapProcState::SkBitmapProcState(const SkBitmap& bm, | 48 SkBitmapProcInfo::SkBitmapProcInfo(const SkBitmap& bm, |
| 49 SkShader::TileMode tmx, SkShader::TileMode tmy) | 49 SkShader::TileMode tmx, SkShader::TileMode tmy) |
| 50 : fProvider(SkBitmapProvider(bm)) | 50 : fProvider(SkBitmapProvider(bm)) |
| 51 , fBMState(nullptr) | 51 , fBMState(nullptr) |
| 52 { | 52 { |
| 53 fTileModeX = tmx; | 53 fTileModeX = tmx; |
| 54 fTileModeY = tmy; | 54 fTileModeY = tmy; |
| 55 } | 55 } |
| 56 | 56 |
| 57 SkBitmapProcState::~SkBitmapProcState() { | 57 SkBitmapProcInfo::~SkBitmapProcInfo() { |
| 58 SkInPlaceDeleteCheck(fBMState, fBMStateStorage.get()); | 58 SkInPlaceDeleteCheck(fBMState, fBMStateStorage.get()); |
| 59 } | 59 } |
| 60 | 60 |
| 61 /////////////////////////////////////////////////////////////////////////////// | 61 /////////////////////////////////////////////////////////////////////////////// |
| 62 | 62 |
| 63 // true iff the matrix contains, at most, scale and translate elements | 63 // true iff the matrix contains, at most, scale and translate elements |
| 64 static bool matrix_only_scale_translate(const SkMatrix& m) { | 64 static bool matrix_only_scale_translate(const SkMatrix& m) { |
| 65 return m.getType() <= (SkMatrix::kScale_Mask | SkMatrix::kTranslate_Mask); | 65 return m.getType() <= (SkMatrix::kScale_Mask | SkMatrix::kTranslate_Mask); |
| 66 } | 66 } |
| 67 | 67 |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 111 // if we got here, treat us as either kTranslate_Mask or identity | 111 // if we got here, treat us as either kTranslate_Mask or identity |
| 112 return true; | 112 return true; |
| 113 } | 113 } |
| 114 | 114 |
| 115 static bool valid_for_filtering(unsigned dimension) { | 115 static bool valid_for_filtering(unsigned dimension) { |
| 116 // for filtering, width and height must fit in 14bits, since we use steal | 116 // for filtering, width and height must fit in 14bits, since we use steal |
| 117 // 2 bits from each to store our 4bit subpixel data | 117 // 2 bits from each to store our 4bit subpixel data |
| 118 return (dimension & ~0x3FFF) == 0; | 118 return (dimension & ~0x3FFF) == 0; |
| 119 } | 119 } |
| 120 | 120 |
| 121 /* | 121 bool SkBitmapProcInfo::init(const SkMatrix& inv, const SkPaint& paint) { |
| 122 * Analyze filter-quality and matrix, and decide how to implement that. | 122 const int origW = fProvider.info().width(); |
| 123 * | 123 const int origH = fProvider.info().height(); |
| 124 * In general, we cascade down the request level [ High ... None ] | 124 |
| 125 * - for a given level, if we can fulfill it, fine, else | |
| 126 * - else we downgrade to the next lower level and try again. | |
| 127 * We can always fulfill requests for Low and None | |
| 128 * - sometimes we will "ignore" Low and give None, but this is likely a legacy perf hack | |
| 129 * and may be removed. | |
| 130 */ | |
| 131 bool SkBitmapProcState::chooseProcs(const SkMatrix& inv, const SkPaint& paint) { | |
| 132 fPixmap.reset(); | 125 fPixmap.reset(); |
| 133 fInvMatrix = inv; | 126 fInvMatrix = inv; |
| 134 fFilterLevel = paint.getFilterQuality(); | 127 fFilterLevel = paint.getFilterQuality(); |
| 135 | 128 |
| 136 const int origW = fProvider.info().width(); | |
| 137 const int origH = fProvider.info().height(); | |
| 138 bool allow_ignore_fractional_translate = true; // historical default | 129 bool allow_ignore_fractional_translate = true; // historical default |
| 139 if (kMedium_SkFilterQuality == fFilterLevel) { | 130 if (kMedium_SkFilterQuality == fFilterLevel) { |
| 140 allow_ignore_fractional_translate = false; | 131 allow_ignore_fractional_translate = false; |
| 141 } | 132 } |
| 142 | 133 |
| 143 SkDefaultBitmapController controller; | 134 SkDefaultBitmapController controller; |
| 144 fBMState = controller.requestBitmap(fProvider, inv, paint.getFilterQuality() , | 135 fBMState = controller.requestBitmap(fProvider, inv, paint.getFilterQuality() , |
| 145 fBMStateStorage.get(), fBMStateStorage.s ize()); | 136 fBMStateStorage.get(), fBMStateStorage.s ize()); |
| 146 // Note : we allow the controller to return an empty (zero-dimension) result . Should we? | 137 // Note : we allow the controller to return an empty (zero-dimension) result . Should we? |
| 147 if (nullptr == fBMState || fBMState->pixmap().info().isEmpty()) { | 138 if (nullptr == fBMState || fBMState->pixmap().info().isEmpty()) { |
| 148 return false; | 139 return false; |
| 149 } | 140 } |
| 150 fPixmap = fBMState->pixmap(); | 141 fPixmap = fBMState->pixmap(); |
| 151 fInvMatrix = fBMState->invMatrix(); | 142 fInvMatrix = fBMState->invMatrix(); |
| 143 fPaintColor = paint.getColor(); | |
| 152 fFilterLevel = fBMState->quality(); | 144 fFilterLevel = fBMState->quality(); |
| 153 SkASSERT(fPixmap.addr()); | 145 SkASSERT(fPixmap.addr()); |
| 154 | 146 |
| 155 bool trivialMatrix = (fInvMatrix.getType() & ~SkMatrix::kTranslate_Mask) == 0; | 147 bool trivialMatrix = (fInvMatrix.getType() & ~SkMatrix::kTranslate_Mask) == 0; |
| 156 bool clampClamp = SkShader::kClamp_TileMode == fTileModeX && | 148 bool clampClamp = SkShader::kClamp_TileMode == fTileModeX && |
| 157 SkShader::kClamp_TileMode == fTileModeY; | 149 SkShader::kClamp_TileMode == fTileModeY; |
| 158 | 150 |
| 159 // Most of the scanline procs deal with "unit" texture coordinates, as this | 151 // Most of the scanline procs deal with "unit" texture coordinates, as this |
| 160 // makes it easy to perform tiling modes (repeat = (x & 0xFFFF)). To generat e | 152 // makes it easy to perform tiling modes (repeat = (x & 0xFFFF)). To generat e |
| 161 // those, we divide the matrix by its dimensions here. | 153 // those, we divide the matrix by its dimensions here. |
| 162 // | 154 // |
| 163 // We don't do this if we're either trivial (can ignore the matrix) or clamp ing | 155 // We don't do this if we're either trivial (can ignore the matrix) or clamp ing |
| 164 // in both X and Y since clamping to width,height is just as easy as to 0xFF FF. | 156 // in both X and Y since clamping to width,height is just as easy as to 0xFF FF. |
| 165 | 157 |
| 166 if (!(clampClamp || trivialMatrix)) { | 158 if (!(clampClamp || trivialMatrix)) { |
| 167 fInvMatrix.postIDiv(fPixmap.width(), fPixmap.height()); | 159 fInvMatrix.postIDiv(fPixmap.width(), fPixmap.height()); |
| 168 } | 160 } |
| 169 | 161 |
| 170 // Now that all possible changes to the matrix have taken place, check | 162 // Now that all possible changes to the matrix have taken place, check |
| 171 // to see if we're really close to a no-scale matrix. If so, explicitly | 163 // to see if we're really close to a no-scale matrix. If so, explicitly |
| 172 // set it to be so. Subsequent code may inspect this matrix to choose | 164 // set it to be so. Subsequent code may inspect this matrix to choose |
| 173 // a faster path in this case. | 165 // a faster path in this case. |
| 174 | 166 |
| 175 // This code will only execute if the matrix has some scale component; | 167 // This code will only execute if the matrix has some scale component; |
| 176 // if it's already pure translate then we won't do this inversion. | 168 // if it's already pure translate then we won't do this inversion. |
| 177 | 169 |
| 178 if (matrix_only_scale_translate(fInvMatrix)) { | 170 if (matrix_only_scale_translate(fInvMatrix)) { |
| 179 SkMatrix forward; | 171 SkMatrix forward; |
| 180 if (fInvMatrix.invert(&forward)) { | 172 if (fInvMatrix.invert(&forward)) { |
| 181 if ((clampClamp && allow_ignore_fractional_translate) | 173 if ((clampClamp && allow_ignore_fractional_translate) |
| 182 ? just_trans_clamp(forward, fPixmap) | 174 ? just_trans_clamp(forward, fPixmap) |
| 183 : just_trans_general(forward)) { | 175 : just_trans_general(forward)) { |
| 184 fInvMatrix.setTranslate(-forward.getTranslateX(), -forward.getTr anslateY()); | 176 fInvMatrix.setTranslate(-forward.getTranslateX(), -forward.getTr anslateY()); |
| 185 } | 177 } |
| 186 } | 178 } |
| 187 } | 179 } |
| 188 | 180 |
| 189 fInvProc = fInvMatrix.getMapXYProc(); | 181 fInvType = fInvMatrix.getType(); |
| 190 fInvType = fInvMatrix.getType(); | |
| 191 fInvSx = SkScalarToFixed(fInvMatrix.getScaleX()); | |
| 192 fInvSxFractionalInt = SkScalarToFractionalInt(fInvMatrix.getScaleX()); | |
| 193 fInvKy = SkScalarToFixed(fInvMatrix.getSkewY()); | |
| 194 fInvKyFractionalInt = SkScalarToFractionalInt(fInvMatrix.getSkewY()); | |
| 195 | |
| 196 fAlphaScale = SkAlpha255To256(paint.getAlpha()); | |
| 197 | |
| 198 fShaderProc32 = nullptr; | |
| 199 fShaderProc16 = nullptr; | |
| 200 fSampleProc32 = nullptr; | |
| 201 | |
| 202 // recompute the triviality of the matrix here because we may have | |
| 203 // changed it! | |
| 204 | |
| 205 trivialMatrix = (fInvMatrix.getType() & ~SkMatrix::kTranslate_Mask) == 0; | |
| 206 | 182 |
| 207 // If our target pixmap is the same as the original, then we revert back to legacy behavior | 183 // If our target pixmap is the same as the original, then we revert back to legacy behavior |
| 208 // and allow the code to ignore fractional translate. | 184 // and allow the code to ignore fractional translate. |
| 209 // | 185 // |
| 210 // The width/height check allows allow_ignore_fractional_translate to stay f alse if we | 186 // The width/height check allows allow_ignore_fractional_translate to stay f alse if we |
| 211 // previously set it that way (e.g. we started in kMedium). | 187 // previously set it that way (e.g. we started in kMedium). |
| 212 // | 188 // |
| 213 if (fPixmap.width() == origW && fPixmap.height() == origH) { | 189 if (fPixmap.width() == origW && fPixmap.height() == origH) { |
| 214 allow_ignore_fractional_translate = true; | 190 allow_ignore_fractional_translate = true; |
| 215 } | 191 } |
| 216 | 192 |
| 217 if (kLow_SkFilterQuality == fFilterLevel && allow_ignore_fractional_translat e) { | 193 if (kLow_SkFilterQuality == fFilterLevel && allow_ignore_fractional_translat e) { |
| 218 // Only try bilerp if the matrix is "interesting" and | 194 // Only try bilerp if the matrix is "interesting" and |
| 219 // the image has a suitable size. | 195 // the image has a suitable size. |
| 220 | 196 |
| 221 if (fInvType <= SkMatrix::kTranslate_Mask || | 197 if (fInvType <= SkMatrix::kTranslate_Mask || |
| 222 !valid_for_filtering(fPixmap.width() | fPixmap.height())) | 198 !valid_for_filtering(fPixmap.width() | fPixmap.height())) |
| 223 { | 199 { |
| 224 fFilterLevel = kNone_SkFilterQuality; | 200 fFilterLevel = kNone_SkFilterQuality; |
| 225 } | 201 } |
| 226 } | 202 } |
| 227 | 203 |
| 228 return this->chooseScanlineProcs(trivialMatrix, clampClamp, paint); | 204 return true; |
| 229 } | 205 } |
| 230 | 206 |
| 231 bool SkBitmapProcState::chooseScanlineProcs(bool trivialMatrix, bool clampClamp, | 207 /* |
| 232 const SkPaint& paint) { | 208 * Analyze filter-quality and matrix, and decide how to implement that. |
| 209 * | |
| 210 * In general, we cascade down the request level [ High ... None ] | |
| 211 * - for a given level, if we can fulfill it, fine, else | |
| 212 * - else we downgrade to the next lower level and try again. | |
| 213 * We can always fulfill requests for Low and None | |
| 214 * - sometimes we will "ignore" Low and give None, but this is likely a legacy perf hack | |
| 215 * and may be removed. | |
| 216 */ | |
| 217 bool SkBitmapProcState::chooseProcs() { | |
| 218 fInvProc = fInvMatrix.getMapXYProc(); | |
| 219 fInvSx = SkScalarToFixed(fInvMatrix.getScaleX()); | |
|
herb_g
2016/03/02 16:00:18
Align =?
reed1
2016/03/02 16:28:27
Done.
| |
| 220 fInvSxFractionalInt = SkScalarToFractionalInt(fInvMatrix.getScaleX()); | |
| 221 fInvKy = SkScalarToFixed(fInvMatrix.getSkewY()); | |
| 222 fInvKyFractionalInt = SkScalarToFractionalInt(fInvMatrix.getSkewY()); | |
| 223 | |
| 224 fAlphaScale = SkAlpha255To256(SkColorGetA(fPaintColor)); | |
| 225 | |
| 226 fShaderProc32 = nullptr; | |
| 227 fShaderProc16 = nullptr; | |
| 228 fSampleProc32 = nullptr; | |
| 229 | |
| 230 const bool trivialMatrix = (fInvMatrix.getType() & ~SkMatrix::kTranslate_Mas k) == 0; | |
| 231 const bool clampClamp = SkShader::kClamp_TileMode == fTileModeX && | |
| 232 SkShader::kClamp_TileMode == fTileModeY; | |
| 233 | |
| 234 return this->chooseScanlineProcs(trivialMatrix, clampClamp); | |
| 235 } | |
| 236 | |
| 237 bool SkBitmapProcState::chooseScanlineProcs(bool trivialMatrix, bool clampClamp) { | |
| 233 fMatrixProc = this->chooseMatrixProc(trivialMatrix); | 238 fMatrixProc = this->chooseMatrixProc(trivialMatrix); |
| 234 // TODO(dominikg): SkASSERT(fMatrixProc) instead? chooseMatrixProc never ret urns nullptr. | 239 // TODO(dominikg): SkASSERT(fMatrixProc) instead? chooseMatrixProc never ret urns nullptr. |
| 235 if (nullptr == fMatrixProc) { | 240 if (nullptr == fMatrixProc) { |
| 236 return false; | 241 return false; |
| 237 } | 242 } |
| 238 | 243 |
| 239 /////////////////////////////////////////////////////////////////////// | 244 /////////////////////////////////////////////////////////////////////// |
| 240 | 245 |
| 241 const SkAlphaType at = fPixmap.alphaType(); | 246 const SkAlphaType at = fPixmap.alphaType(); |
| 242 | 247 |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 274 index |= 16; | 279 index |= 16; |
| 275 break; | 280 break; |
| 276 case kARGB_4444_SkColorType: | 281 case kARGB_4444_SkColorType: |
| 277 if (kPremul_SkAlphaType != at && kOpaque_SkAlphaType != at) { | 282 if (kPremul_SkAlphaType != at && kOpaque_SkAlphaType != at) { |
| 278 return false; | 283 return false; |
| 279 } | 284 } |
| 280 index |= 24; | 285 index |= 24; |
| 281 break; | 286 break; |
| 282 case kAlpha_8_SkColorType: | 287 case kAlpha_8_SkColorType: |
| 283 index |= 32; | 288 index |= 32; |
| 284 fPaintPMColor = SkPreMultiplyColor(paint.getColor()); | 289 fPaintPMColor = SkPreMultiplyColor(fPaintColor); |
| 285 break; | 290 break; |
| 286 case kGray_8_SkColorType: | 291 case kGray_8_SkColorType: |
| 287 index |= 40; | 292 index |= 40; |
| 288 fPaintPMColor = SkPreMultiplyColor(paint.getColor()); | 293 fPaintPMColor = SkPreMultiplyColor(fPaintColor); |
| 289 break; | 294 break; |
| 290 default: | 295 default: |
| 291 // TODO(dominikg): Should we ever get here? SkASSERT(false) inst ead? | 296 // TODO(dominikg): Should we ever get here? SkASSERT(false) inst ead? |
| 292 return false; | 297 return false; |
| 293 } | 298 } |
| 294 | 299 |
| 295 #if !SK_ARM_NEON_IS_ALWAYS | 300 #if !SK_ARM_NEON_IS_ALWAYS |
| 296 static const SampleProc32 gSkBitmapProcStateSample32[] = { | 301 static const SampleProc32 gSkBitmapProcStateSample32[] = { |
| 297 S32_opaque_D32_nofilter_DXDY, | 302 S32_opaque_D32_nofilter_DXDY, |
| 298 S32_alpha_D32_nofilter_DXDY, | 303 S32_alpha_D32_nofilter_DXDY, |
| (...skipping 513 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 812 fx += dx; | 817 fx += dx; |
| 813 } | 818 } |
| 814 } else { | 819 } else { |
| 815 for (int i = 0; i < count; ++i) { | 820 for (int i = 0; i < count; ++i) { |
| 816 dst[i] = src[SkClampMax(SkFractionalIntToInt(fx), maxX)]; | 821 dst[i] = src[SkClampMax(SkFractionalIntToInt(fx), maxX)]; |
| 817 fx += dx; | 822 fx += dx; |
| 818 } | 823 } |
| 819 } | 824 } |
| 820 } | 825 } |
| 821 | 826 |
| OLD | NEW |