| File: | root/firefox-clang/gfx/skia/skia/src/core/SkBitmapProcState.cpp |
| Warning: | line 632, column 23 Dereference of null pointer |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
| 1 | /* | |||
| 2 | * Copyright 2011 Google Inc. | |||
| 3 | * | |||
| 4 | * Use of this source code is governed by a BSD-style license that can be | |||
| 5 | * found in the LICENSE file. | |||
| 6 | */ | |||
| 7 | ||||
| 8 | #include "src/core/SkBitmapProcState.h" | |||
| 9 | ||||
| 10 | #include "include/core/SkAlphaType.h" | |||
| 11 | #include "include/core/SkColorType.h" | |||
| 12 | #include "include/core/SkImageInfo.h" | |||
| 13 | #include "include/core/SkTileMode.h" | |||
| 14 | #include "include/private/base/SkMacros.h" | |||
| 15 | #include "include/private/base/SkTPin.h" | |||
| 16 | #include "src/core/SkColorPriv.h" | |||
| 17 | #include "src/core/SkMatrixPriv.h" | |||
| 18 | #include "src/core/SkMemset.h" | |||
| 19 | #include "src/core/SkMipmapAccessor.h" | |||
| 20 | ||||
| 21 | #include <algorithm> | |||
| 22 | #include <cstring> | |||
| 23 | #include <tuple> | |||
| 24 | ||||
| 25 | class SkImage; | |||
| 26 | class SkImage_Base; | |||
| 27 | ||||
| 28 | // One-stop-shop shader for, | |||
| 29 | // - nearest-neighbor sampling (_nofilter_), | |||
| 30 | // - clamp tiling in X and Y both (Clamp_), | |||
| 31 | // - with at most a scale and translate matrix (_DX_), | |||
| 32 | // - and no extra alpha applied (_opaque_), | |||
| 33 | // - sampling from 8888 (_S32_) and drawing to 8888 (_S32_). | |||
| 34 | static void Clamp_S32_opaque_D32_nofilter_DX_shaderproc(const void* sIn, int x, int y, | |||
| 35 | SkPMColor* dst, int count) { | |||
| 36 | const SkBitmapProcState& s = *static_cast<const SkBitmapProcState*>(sIn); | |||
| 37 | SkASSERT(s.fInvMatrix.isScaleTranslate())static_cast<void>( __builtin_expect(static_cast<bool >(s.fInvMatrix.isScaleTranslate()), 1) ? static_cast<void >(0) : []{ do { if (sk_abort_is_enabled()) { do { SkDebugf ("%s:%d" ": fatal error: \"" "check(%s)" "\"\n", "/root/firefox-clang/gfx/skia/skia/src/core/SkBitmapProcState.cpp" , 37, "s.fInvMatrix.isScaleTranslate()"); ; sk_abort_no_print (); } while (false); } } while(false); }() ); | |||
| 38 | SkASSERT(s.fAlphaScale == 256)static_cast<void>( __builtin_expect(static_cast<bool >(s.fAlphaScale == 256), 1) ? static_cast<void>(0) : []{ do { if (sk_abort_is_enabled()) { do { SkDebugf("%s:%d" ": fatal error: \"" "check(%s)" "\"\n", "/root/firefox-clang/gfx/skia/skia/src/core/SkBitmapProcState.cpp" , 38, "s.fAlphaScale == 256"); ; sk_abort_no_print(); } while (false); } } while(false); }() ); | |||
| 39 | ||||
| 40 | const unsigned maxX = s.fPixmap.width() - 1; | |||
| 41 | SkFixed3232 fx; | |||
| 42 | int dstY; | |||
| 43 | { | |||
| 44 | const SkBitmapProcStateAutoMapper mapper(s, x, y); | |||
| 45 | const unsigned maxY = s.fPixmap.height() - 1; | |||
| 46 | dstY = SkTPin<int>(mapper.intY(), 0, maxY); | |||
| 47 | fx = mapper.fixed3232X(); | |||
| 48 | } | |||
| 49 | ||||
| 50 | const SkPMColor* src = s.fPixmap.addr32(0, dstY); | |||
| 51 | const SkFixed3232 dx = s.fInvSx; | |||
| 52 | ||||
| 53 | // Check if we're safely inside [0...maxX] so no need to clamp each computed index. | |||
| 54 | // | |||
| 55 | if ((uint64_t)SkFixed3232ToInt(fx)((int)((fx) >> 32)) <= maxX && | |||
| 56 | (uint64_t)SkFixed3232ToInt(fx + dx * (count - 1))((int)((fx + dx * (count - 1)) >> 32)) <= maxX) | |||
| 57 | { | |||
| 58 | int count4 = count >> 2; | |||
| 59 | for (int i = 0; i < count4; ++i) { | |||
| 60 | SkPMColor src0 = src[SkFixed3232ToInt(fx)((int)((fx) >> 32))]; fx += dx; | |||
| 61 | SkPMColor src1 = src[SkFixed3232ToInt(fx)((int)((fx) >> 32))]; fx += dx; | |||
| 62 | SkPMColor src2 = src[SkFixed3232ToInt(fx)((int)((fx) >> 32))]; fx += dx; | |||
| 63 | SkPMColor src3 = src[SkFixed3232ToInt(fx)((int)((fx) >> 32))]; fx += dx; | |||
| 64 | dst[0] = src0; | |||
| 65 | dst[1] = src1; | |||
| 66 | dst[2] = src2; | |||
| 67 | dst[3] = src3; | |||
| 68 | dst += 4; | |||
| 69 | } | |||
| 70 | for (int i = (count4 << 2); i < count; ++i) { | |||
| 71 | unsigned index = SkFixed3232ToInt(fx)((int)((fx) >> 32)); | |||
| 72 | SkASSERT(index <= maxX)static_cast<void>( __builtin_expect(static_cast<bool >(index <= maxX), 1) ? static_cast<void>(0) : []{ do { if (sk_abort_is_enabled()) { do { SkDebugf("%s:%d" ": fatal error: \"" "check(%s)" "\"\n", "/root/firefox-clang/gfx/skia/skia/src/core/SkBitmapProcState.cpp" , 72, "index <= maxX"); ; sk_abort_no_print(); } while (false ); } } while(false); }() ); | |||
| 73 | *dst++ = src[index]; | |||
| 74 | fx += dx; | |||
| 75 | } | |||
| 76 | } else { | |||
| 77 | for (int i = 0; i < count; ++i) { | |||
| 78 | dst[i] = src[SkTPin<int>(SkFixed3232ToInt(fx)((int)((fx) >> 32)), 0, maxX)]; | |||
| 79 | fx += dx; | |||
| 80 | } | |||
| 81 | } | |||
| 82 | } | |||
| 83 | ||||
| 84 | static void S32_alpha_D32_nofilter_DX(const SkBitmapProcState& s, | |||
| 85 | const uint32_t* xy, int count, SkPMColor* colors) { | |||
| 86 | SkASSERT(count > 0 && colors != nullptr)static_cast<void>( __builtin_expect(static_cast<bool >(count > 0 && colors != nullptr), 1) ? static_cast <void>(0) : []{ do { if (sk_abort_is_enabled()) { do { SkDebugf ("%s:%d" ": fatal error: \"" "check(%s)" "\"\n", "/root/firefox-clang/gfx/skia/skia/src/core/SkBitmapProcState.cpp" , 86, "count > 0 && colors != nullptr"); ; sk_abort_no_print (); } while (false); } } while(false); }() ); | |||
| 87 | SkASSERT(s.fInvMatrix.isScaleTranslate())static_cast<void>( __builtin_expect(static_cast<bool >(s.fInvMatrix.isScaleTranslate()), 1) ? static_cast<void >(0) : []{ do { if (sk_abort_is_enabled()) { do { SkDebugf ("%s:%d" ": fatal error: \"" "check(%s)" "\"\n", "/root/firefox-clang/gfx/skia/skia/src/core/SkBitmapProcState.cpp" , 87, "s.fInvMatrix.isScaleTranslate()"); ; sk_abort_no_print (); } while (false); } } while(false); }() ); | |||
| 88 | SkASSERT(!s.fBilerp)static_cast<void>( __builtin_expect(static_cast<bool >(!s.fBilerp), 1) ? static_cast<void>(0) : []{ do { if (sk_abort_is_enabled()) { do { SkDebugf("%s:%d" ": fatal error: \"" "check(%s)" "\"\n", "/root/firefox-clang/gfx/skia/skia/src/core/SkBitmapProcState.cpp" , 88, "!s.fBilerp"); ; sk_abort_no_print(); } while (false); } } while(false); }() ); | |||
| 89 | SkASSERT(4 == s.fPixmap.info().bytesPerPixel())static_cast<void>( __builtin_expect(static_cast<bool >(4 == s.fPixmap.info().bytesPerPixel()), 1) ? static_cast <void>(0) : []{ do { if (sk_abort_is_enabled()) { do { SkDebugf ("%s:%d" ": fatal error: \"" "check(%s)" "\"\n", "/root/firefox-clang/gfx/skia/skia/src/core/SkBitmapProcState.cpp" , 89, "4 == s.fPixmap.info().bytesPerPixel()"); ; sk_abort_no_print (); } while (false); } } while(false); }() ); | |||
| 90 | SkASSERT(s.fAlphaScale <= 256)static_cast<void>( __builtin_expect(static_cast<bool >(s.fAlphaScale <= 256), 1) ? static_cast<void>(0 ) : []{ do { if (sk_abort_is_enabled()) { do { SkDebugf("%s:%d" ": fatal error: \"" "check(%s)" "\"\n", "/root/firefox-clang/gfx/skia/skia/src/core/SkBitmapProcState.cpp" , 90, "s.fAlphaScale <= 256"); ; sk_abort_no_print(); } while (false); } } while(false); }() ); | |||
| 91 | ||||
| 92 | // xy is a 32-bit y-coordinate, followed by 16-bit x-coordinates. | |||
| 93 | unsigned y = *xy++; | |||
| 94 | SkASSERT(y < (unsigned)s.fPixmap.height())static_cast<void>( __builtin_expect(static_cast<bool >(y < (unsigned)s.fPixmap.height()), 1) ? static_cast< void>(0) : []{ do { if (sk_abort_is_enabled()) { do { SkDebugf ("%s:%d" ": fatal error: \"" "check(%s)" "\"\n", "/root/firefox-clang/gfx/skia/skia/src/core/SkBitmapProcState.cpp" , 94, "y < (unsigned)s.fPixmap.height()"); ; sk_abort_no_print (); } while (false); } } while(false); }() ); | |||
| 95 | ||||
| 96 | auto row = (const SkPMColor*)( (const char*)s.fPixmap.addr() + y * s.fPixmap.rowBytes() ); | |||
| 97 | ||||
| 98 | if (1 == s.fPixmap.width()) { | |||
| 99 | SkOpts::memset32(colors, SkAlphaMulQ(row[0], s.fAlphaScale), count); | |||
| 100 | return; | |||
| 101 | } | |||
| 102 | ||||
| 103 | // Step 4 xs == 2 uint32_t at a time. | |||
| 104 | while (count >= 4) { | |||
| 105 | uint32_t x01 = *xy++, | |||
| 106 | x23 = *xy++; | |||
| 107 | ||||
| 108 | SkPMColor p0 = row[UNPACK_PRIMARY_SHORT (x01)((x01) & 0xFFFF)]; | |||
| 109 | SkPMColor p1 = row[UNPACK_SECONDARY_SHORT(x01)((uint32_t)(x01) >> 16)]; | |||
| 110 | SkPMColor p2 = row[UNPACK_PRIMARY_SHORT (x23)((x23) & 0xFFFF)]; | |||
| 111 | SkPMColor p3 = row[UNPACK_SECONDARY_SHORT(x23)((uint32_t)(x23) >> 16)]; | |||
| 112 | ||||
| 113 | *colors++ = SkAlphaMulQ(p0, s.fAlphaScale); | |||
| 114 | *colors++ = SkAlphaMulQ(p1, s.fAlphaScale); | |||
| 115 | *colors++ = SkAlphaMulQ(p2, s.fAlphaScale); | |||
| 116 | *colors++ = SkAlphaMulQ(p3, s.fAlphaScale); | |||
| 117 | ||||
| 118 | count -= 4; | |||
| 119 | } | |||
| 120 | ||||
| 121 | // Step 1 x == 1 uint16_t at a time. | |||
| 122 | auto x = (const uint16_t*)xy; | |||
| 123 | while (count --> 0) { | |||
| 124 | *colors++ = SkAlphaMulQ(row[*x++], s.fAlphaScale); | |||
| 125 | } | |||
| 126 | } | |||
| 127 | ||||
| 128 | static void S32_alpha_D32_nofilter_DXDY(const SkBitmapProcState& s, | |||
| 129 | const uint32_t* xy, int count, SkPMColor* colors) { | |||
| 130 | SkASSERT(count > 0 && colors != nullptr)static_cast<void>( __builtin_expect(static_cast<bool >(count > 0 && colors != nullptr), 1) ? static_cast <void>(0) : []{ do { if (sk_abort_is_enabled()) { do { SkDebugf ("%s:%d" ": fatal error: \"" "check(%s)" "\"\n", "/root/firefox-clang/gfx/skia/skia/src/core/SkBitmapProcState.cpp" , 130, "count > 0 && colors != nullptr"); ; sk_abort_no_print (); } while (false); } } while(false); }() ); | |||
| 131 | SkASSERT(!s.fBilerp)static_cast<void>( __builtin_expect(static_cast<bool >(!s.fBilerp), 1) ? static_cast<void>(0) : []{ do { if (sk_abort_is_enabled()) { do { SkDebugf("%s:%d" ": fatal error: \"" "check(%s)" "\"\n", "/root/firefox-clang/gfx/skia/skia/src/core/SkBitmapProcState.cpp" , 131, "!s.fBilerp"); ; sk_abort_no_print(); } while (false); } } while(false); }() ); | |||
| 132 | SkASSERT(4 == s.fPixmap.info().bytesPerPixel())static_cast<void>( __builtin_expect(static_cast<bool >(4 == s.fPixmap.info().bytesPerPixel()), 1) ? static_cast <void>(0) : []{ do { if (sk_abort_is_enabled()) { do { SkDebugf ("%s:%d" ": fatal error: \"" "check(%s)" "\"\n", "/root/firefox-clang/gfx/skia/skia/src/core/SkBitmapProcState.cpp" , 132, "4 == s.fPixmap.info().bytesPerPixel()"); ; sk_abort_no_print (); } while (false); } } while(false); }() ); | |||
| 133 | SkASSERT(s.fAlphaScale <= 256)static_cast<void>( __builtin_expect(static_cast<bool >(s.fAlphaScale <= 256), 1) ? static_cast<void>(0 ) : []{ do { if (sk_abort_is_enabled()) { do { SkDebugf("%s:%d" ": fatal error: \"" "check(%s)" "\"\n", "/root/firefox-clang/gfx/skia/skia/src/core/SkBitmapProcState.cpp" , 133, "s.fAlphaScale <= 256"); ; sk_abort_no_print(); } while (false); } } while(false); }() ); | |||
| 134 | ||||
| 135 | auto src = (const char*)s.fPixmap.addr(); | |||
| 136 | size_t rb = s.fPixmap.rowBytes(); | |||
| 137 | ||||
| 138 | while (count --> 0) { | |||
| 139 | uint32_t XY = *xy++, | |||
| 140 | x = XY & 0xffff, | |||
| 141 | y = XY >> 16; | |||
| 142 | SkASSERT(x < (unsigned)s.fPixmap.width ())static_cast<void>( __builtin_expect(static_cast<bool >(x < (unsigned)s.fPixmap.width ()), 1) ? static_cast< void>(0) : []{ do { if (sk_abort_is_enabled()) { do { SkDebugf ("%s:%d" ": fatal error: \"" "check(%s)" "\"\n", "/root/firefox-clang/gfx/skia/skia/src/core/SkBitmapProcState.cpp" , 142, "x < (unsigned)s.fPixmap.width ()"); ; sk_abort_no_print (); } while (false); } } while(false); }() ); | |||
| 143 | SkASSERT(y < (unsigned)s.fPixmap.height())static_cast<void>( __builtin_expect(static_cast<bool >(y < (unsigned)s.fPixmap.height()), 1) ? static_cast< void>(0) : []{ do { if (sk_abort_is_enabled()) { do { SkDebugf ("%s:%d" ": fatal error: \"" "check(%s)" "\"\n", "/root/firefox-clang/gfx/skia/skia/src/core/SkBitmapProcState.cpp" , 143, "y < (unsigned)s.fPixmap.height()"); ; sk_abort_no_print (); } while (false); } } while(false); }() ); | |||
| 144 | *colors++ = SkAlphaMulQ(((const SkPMColor*)(src + y*rb))[x], s.fAlphaScale); | |||
| 145 | } | |||
| 146 | } | |||
| 147 | ||||
| 148 | SkBitmapProcState::SkBitmapProcState(const SkImage_Base* image, SkTileMode tmx, SkTileMode tmy) | |||
| 149 | : fImage(image) | |||
| 150 | , fTileModeX(tmx) | |||
| 151 | , fTileModeY(tmy) | |||
| 152 | {} | |||
| 153 | ||||
| 154 | // true iff the matrix has a scale and no more than an optional translate. | |||
| 155 | static bool matrix_only_scale_translate(const SkMatrix& m) { | |||
| 156 | return (m.getType() & ~SkMatrix::kTranslate_Mask) == SkMatrix::kScale_Mask; | |||
| 157 | } | |||
| 158 | ||||
| 159 | /** | |||
| 160 | * For the purposes of drawing bitmaps, if a matrix is "almost" translate | |||
| 161 | * go ahead and treat it as if it were, so that subsequent code can go fast. | |||
| 162 | */ | |||
| 163 | static bool just_trans_general(const SkMatrix& matrix) { | |||
| 164 | SkASSERT(matrix_only_scale_translate(matrix))static_cast<void>( __builtin_expect(static_cast<bool >(matrix_only_scale_translate(matrix)), 1) ? static_cast< void>(0) : []{ do { if (sk_abort_is_enabled()) { do { SkDebugf ("%s:%d" ": fatal error: \"" "check(%s)" "\"\n", "/root/firefox-clang/gfx/skia/skia/src/core/SkBitmapProcState.cpp" , 164, "matrix_only_scale_translate(matrix)"); ; sk_abort_no_print (); } while (false); } } while(false); }() ); | |||
| 165 | ||||
| 166 | const SkScalar tol = SK_Scalar11.0f / 32768; | |||
| 167 | ||||
| 168 | return SkScalarNearlyZero(matrix[SkMatrix::kMScaleX] - SK_Scalar11.0f, tol) | |||
| 169 | && SkScalarNearlyZero(matrix[SkMatrix::kMScaleY] - SK_Scalar11.0f, tol); | |||
| 170 | } | |||
| 171 | ||||
| 172 | /** | |||
| 173 | * Determine if the matrix can be treated as integral-only-translate, | |||
| 174 | * for the purpose of filtering. | |||
| 175 | */ | |||
| 176 | static bool just_trans_integral(const SkMatrix& m) { | |||
| 177 | static constexpr SkScalar tol = SK_Scalar11.0f / 256; | |||
| 178 | ||||
| 179 | return m.getType() <= SkMatrix::kTranslate_Mask | |||
| 180 | && SkScalarNearlyEqual(m.getTranslateX(), SkScalarRoundToScalar(m.getTranslateX())(float)(std::floor(((double)(m.getTranslateX())) + 0.5)), tol) | |||
| 181 | && SkScalarNearlyEqual(m.getTranslateY(), SkScalarRoundToScalar(m.getTranslateY())(float)(std::floor(((double)(m.getTranslateY())) + 0.5)), tol); | |||
| 182 | } | |||
| 183 | ||||
| 184 | static bool valid_for_filtering(unsigned dimension) { | |||
| 185 | // for filtering, width and height must fit in 14bits, since we use steal | |||
| 186 | // 2 bits from each to store our 4bit subpixel data | |||
| 187 | return (dimension & ~0x3FFF) == 0; | |||
| 188 | } | |||
| 189 | ||||
| 190 | bool SkBitmapProcState::init(const SkMatrix& inv, SkAlpha paintAlpha, | |||
| 191 | const SkSamplingOptions& sampling) { | |||
| 192 | SkASSERT(!inv.hasPerspective())static_cast<void>( __builtin_expect(static_cast<bool >(!inv.hasPerspective()), 1) ? static_cast<void>(0) : []{ do { if (sk_abort_is_enabled()) { do { SkDebugf("%s:%d" ": fatal error: \"" "check(%s)" "\"\n", "/root/firefox-clang/gfx/skia/skia/src/core/SkBitmapProcState.cpp" , 192, "!inv.hasPerspective()"); ; sk_abort_no_print(); } while (false); } } while(false); }() ); | |||
| 193 | SkASSERT(SkOpts::S32_alpha_D32_filter_DXDY || inv.isScaleTranslate())static_cast<void>( __builtin_expect(static_cast<bool >(SkOpts::S32_alpha_D32_filter_DXDY || inv.isScaleTranslate ()), 1) ? static_cast<void>(0) : []{ do { if (sk_abort_is_enabled ()) { do { SkDebugf("%s:%d" ": fatal error: \"" "check(%s)" "\"\n" , "/root/firefox-clang/gfx/skia/skia/src/core/SkBitmapProcState.cpp" , 193, "SkOpts::S32_alpha_D32_filter_DXDY || inv.isScaleTranslate()" ); ; sk_abort_no_print(); } while (false); } } while(false); } () ); | |||
| 194 | SkASSERT(!sampling.isAniso())static_cast<void>( __builtin_expect(static_cast<bool >(!sampling.isAniso()), 1) ? static_cast<void>(0) : [ ]{ do { if (sk_abort_is_enabled()) { do { SkDebugf("%s:%d" ": fatal error: \"" "check(%s)" "\"\n", "/root/firefox-clang/gfx/skia/skia/src/core/SkBitmapProcState.cpp" , 194, "!sampling.isAniso()"); ; sk_abort_no_print(); } while (false); } } while(false); }() ); | |||
| 195 | SkASSERT(!sampling.useCubic)static_cast<void>( __builtin_expect(static_cast<bool >(!sampling.useCubic), 1) ? static_cast<void>(0) : [ ]{ do { if (sk_abort_is_enabled()) { do { SkDebugf("%s:%d" ": fatal error: \"" "check(%s)" "\"\n", "/root/firefox-clang/gfx/skia/skia/src/core/SkBitmapProcState.cpp" , 195, "!sampling.useCubic"); ; sk_abort_no_print(); } while ( false); } } while(false); }() ); | |||
| 196 | SkASSERT(sampling.mipmap != SkMipmapMode::kLinear)static_cast<void>( __builtin_expect(static_cast<bool >(sampling.mipmap != SkMipmapMode::kLinear), 1) ? static_cast <void>(0) : []{ do { if (sk_abort_is_enabled()) { do { SkDebugf ("%s:%d" ": fatal error: \"" "check(%s)" "\"\n", "/root/firefox-clang/gfx/skia/skia/src/core/SkBitmapProcState.cpp" , 196, "sampling.mipmap != SkMipmapMode::kLinear"); ; sk_abort_no_print (); } while (false); } } while(false); }() ); | |||
| 197 | ||||
| 198 | fPixmap.reset(); | |||
| 199 | fBilerp = false; | |||
| 200 | ||||
| 201 | auto* access = SkMipmapAccessor::Make(&fAlloc, (const SkImage*)fImage, inv, sampling.mipmap); | |||
| 202 | if (!access) { | |||
| 203 | return false; | |||
| 204 | } | |||
| 205 | std::tie(fPixmap, fInvMatrix) = access->level(); | |||
| 206 | fInvMatrix.preConcat(inv); | |||
| 207 | ||||
| 208 | fPaintAlpha = paintAlpha; | |||
| 209 | fBilerp = sampling.filter == SkFilterMode::kLinear; | |||
| 210 | SkASSERT(fPixmap.addr())static_cast<void>( __builtin_expect(static_cast<bool >(fPixmap.addr()), 1) ? static_cast<void>(0) : []{ do { if (sk_abort_is_enabled()) { do { SkDebugf("%s:%d" ": fatal error: \"" "check(%s)" "\"\n", "/root/firefox-clang/gfx/skia/skia/src/core/SkBitmapProcState.cpp" , 210, "fPixmap.addr()"); ; sk_abort_no_print(); } while (false ); } } while(false); }() ); | |||
| 211 | ||||
| 212 | bool integral_translate_only = just_trans_integral(fInvMatrix); | |||
| 213 | if (!integral_translate_only) { | |||
| 214 | // Most of the scanline procs deal with "unit" texture coordinates, as this | |||
| 215 | // makes it easy to perform tiling modes (repeat = (x & 0xFFFF)). To generate | |||
| 216 | // those, we divide the matrix by its dimensions here. | |||
| 217 | // | |||
| 218 | // We don't do this if we're either trivial (can ignore the matrix) or clamping | |||
| 219 | // in both X and Y since clamping to width,height is just as easy as to 0xFFFF. | |||
| 220 | ||||
| 221 | if (fTileModeX != SkTileMode::kClamp || fTileModeY != SkTileMode::kClamp) { | |||
| 222 | SkMatrixPriv::PostIDiv(&fInvMatrix, fPixmap.width(), fPixmap.height()); | |||
| 223 | } | |||
| 224 | ||||
| 225 | // Now that all possible changes to the matrix have taken place, check | |||
| 226 | // to see if we're really close to a no-scale matrix. If so, explicitly | |||
| 227 | // set it to be so. Subsequent code may inspect this matrix to choose | |||
| 228 | // a faster path in this case. | |||
| 229 | ||||
| 230 | // This code will only execute if the matrix has some scale component; | |||
| 231 | // if it's already pure translate then we won't do this inversion. | |||
| 232 | ||||
| 233 | if (matrix_only_scale_translate(fInvMatrix)) { | |||
| 234 | if (auto forward = fInvMatrix.invert()) { | |||
| 235 | if (just_trans_general(*forward)) { | |||
| 236 | fInvMatrix.setTranslate(-forward->getTranslateX(), -forward->getTranslateY()); | |||
| 237 | } | |||
| 238 | } | |||
| 239 | } | |||
| 240 | ||||
| 241 | // Recompute the flag after matrix adjustments. | |||
| 242 | integral_translate_only = just_trans_integral(fInvMatrix); | |||
| 243 | } | |||
| 244 | ||||
| 245 | if (fBilerp && | |||
| 246 | (!valid_for_filtering(fPixmap.width() | fPixmap.height()) || integral_translate_only)) { | |||
| 247 | fBilerp = false; | |||
| 248 | } | |||
| 249 | ||||
| 250 | return true; | |||
| 251 | } | |||
| 252 | ||||
| 253 | /* | |||
| 254 | * Analyze filter-quality and matrix, and decide how to implement that. | |||
| 255 | * | |||
| 256 | * In general, we cascade down the request level [ High ... None ] | |||
| 257 | * - for a given level, if we can fulfill it, fine, else | |||
| 258 | * - else we downgrade to the next lower level and try again. | |||
| 259 | * We can always fulfill requests for Low and None | |||
| 260 | * - sometimes we will "ignore" Low and give None, but this is likely a legacy perf hack | |||
| 261 | * and may be removed. | |||
| 262 | */ | |||
| 263 | bool SkBitmapProcState::chooseProcs() { | |||
| 264 | SkASSERT(!fInvMatrix.hasPerspective())static_cast<void>( __builtin_expect(static_cast<bool >(!fInvMatrix.hasPerspective()), 1) ? static_cast<void> (0) : []{ do { if (sk_abort_is_enabled()) { do { SkDebugf("%s:%d" ": fatal error: \"" "check(%s)" "\"\n", "/root/firefox-clang/gfx/skia/skia/src/core/SkBitmapProcState.cpp" , 264, "!fInvMatrix.hasPerspective()"); ; sk_abort_no_print() ; } while (false); } } while(false); }() ); | |||
| 265 | SkASSERT(SkOpts::S32_alpha_D32_filter_DXDY || fInvMatrix.isScaleTranslate())static_cast<void>( __builtin_expect(static_cast<bool >(SkOpts::S32_alpha_D32_filter_DXDY || fInvMatrix.isScaleTranslate ()), 1) ? static_cast<void>(0) : []{ do { if (sk_abort_is_enabled ()) { do { SkDebugf("%s:%d" ": fatal error: \"" "check(%s)" "\"\n" , "/root/firefox-clang/gfx/skia/skia/src/core/SkBitmapProcState.cpp" , 265, "SkOpts::S32_alpha_D32_filter_DXDY || fInvMatrix.isScaleTranslate()" ); ; sk_abort_no_print(); } while (false); } } while(false); } () ); | |||
| 266 | SkASSERT(fPixmap.colorType() == kN32_SkColorType)static_cast<void>( __builtin_expect(static_cast<bool >(fPixmap.colorType() == kN32_SkColorType), 1) ? static_cast <void>(0) : []{ do { if (sk_abort_is_enabled()) { do { SkDebugf ("%s:%d" ": fatal error: \"" "check(%s)" "\"\n", "/root/firefox-clang/gfx/skia/skia/src/core/SkBitmapProcState.cpp" , 266, "fPixmap.colorType() == kN32_SkColorType"); ; sk_abort_no_print (); } while (false); } } while(false); }() ); | |||
| 267 | SkASSERT(fPixmap.alphaType() == kPremul_SkAlphaType ||static_cast<void>( __builtin_expect(static_cast<bool >(fPixmap.alphaType() == kPremul_SkAlphaType || fPixmap.alphaType () == kOpaque_SkAlphaType), 1) ? static_cast<void>(0) : []{ do { if (sk_abort_is_enabled()) { do { SkDebugf("%s:%d" ": fatal error: \"" "check(%s)" "\"\n", "/root/firefox-clang/gfx/skia/skia/src/core/SkBitmapProcState.cpp" , 268, "fPixmap.alphaType() == kPremul_SkAlphaType || fPixmap.alphaType() == kOpaque_SkAlphaType" ); ; sk_abort_no_print(); } while (false); } } while(false); } () ) | |||
| 268 | fPixmap.alphaType() == kOpaque_SkAlphaType)static_cast<void>( __builtin_expect(static_cast<bool >(fPixmap.alphaType() == kPremul_SkAlphaType || fPixmap.alphaType () == kOpaque_SkAlphaType), 1) ? static_cast<void>(0) : []{ do { if (sk_abort_is_enabled()) { do { SkDebugf("%s:%d" ": fatal error: \"" "check(%s)" "\"\n", "/root/firefox-clang/gfx/skia/skia/src/core/SkBitmapProcState.cpp" , 268, "fPixmap.alphaType() == kPremul_SkAlphaType || fPixmap.alphaType() == kOpaque_SkAlphaType" ); ; sk_abort_no_print(); } while (false); } } while(false); } () ); | |||
| 269 | ||||
| 270 | SkASSERT(fTileModeX != SkTileMode::kDecal)static_cast<void>( __builtin_expect(static_cast<bool >(fTileModeX != SkTileMode::kDecal), 1) ? static_cast<void >(0) : []{ do { if (sk_abort_is_enabled()) { do { SkDebugf ("%s:%d" ": fatal error: \"" "check(%s)" "\"\n", "/root/firefox-clang/gfx/skia/skia/src/core/SkBitmapProcState.cpp" , 270, "fTileModeX != SkTileMode::kDecal"); ; sk_abort_no_print (); } while (false); } } while(false); }() ); | |||
| 271 | ||||
| 272 | fInvSx = SkScalarToFixed3232(fInvMatrix.getScaleX())sk_float_saturate2int64((fInvMatrix.getScaleX()) * (65536.0f * 65536.0f)); | |||
| 273 | fInvKy = SkScalarToFixed3232(fInvMatrix.getSkewY ())sk_float_saturate2int64((fInvMatrix.getSkewY ()) * (65536.0f * 65536.0f)); | |||
| 274 | ||||
| 275 | fAlphaScale = SkAlpha255To256(fPaintAlpha); | |||
| 276 | ||||
| 277 | bool translate_only = (fInvMatrix.getType() & ~SkMatrix::kTranslate_Mask) == 0; | |||
| 278 | fMatrixProc = this->chooseMatrixProc(translate_only); | |||
| 279 | SkASSERT(fMatrixProc)static_cast<void>( __builtin_expect(static_cast<bool >(fMatrixProc), 1) ? static_cast<void>(0) : []{ do { if (sk_abort_is_enabled()) { do { SkDebugf("%s:%d" ": fatal error: \"" "check(%s)" "\"\n", "/root/firefox-clang/gfx/skia/skia/src/core/SkBitmapProcState.cpp" , 279, "fMatrixProc"); ; sk_abort_no_print(); } while (false) ; } } while(false); }() ); | |||
| 280 | ||||
| 281 | if (fInvMatrix.isScaleTranslate()) { | |||
| 282 | fSampleProc32 = fBilerp ? SkOpts::S32_alpha_D32_filter_DX : S32_alpha_D32_nofilter_DX ; | |||
| 283 | } else { | |||
| 284 | fSampleProc32 = fBilerp ? SkOpts::S32_alpha_D32_filter_DXDY : S32_alpha_D32_nofilter_DXDY; | |||
| 285 | } | |||
| 286 | SkASSERT(fSampleProc32)static_cast<void>( __builtin_expect(static_cast<bool >(fSampleProc32), 1) ? static_cast<void>(0) : []{ do { if (sk_abort_is_enabled()) { do { SkDebugf("%s:%d" ": fatal error: \"" "check(%s)" "\"\n", "/root/firefox-clang/gfx/skia/skia/src/core/SkBitmapProcState.cpp" , 286, "fSampleProc32"); ; sk_abort_no_print(); } while (false ); } } while(false); }() ); | |||
| 287 | ||||
| 288 | // our special-case shaderprocs | |||
| 289 | // TODO: move this one into chooseShaderProc32() or pull all that in here. | |||
| 290 | if (fAlphaScale == 256 | |||
| 291 | && !fBilerp | |||
| 292 | && SkTileMode::kClamp == fTileModeX | |||
| 293 | && SkTileMode::kClamp == fTileModeY | |||
| 294 | && fInvMatrix.isScaleTranslate()) { | |||
| 295 | fShaderProc32 = Clamp_S32_opaque_D32_nofilter_DX_shaderproc; | |||
| 296 | } else { | |||
| 297 | fShaderProc32 = this->chooseShaderProc32(); | |||
| 298 | } | |||
| 299 | ||||
| 300 | return true; | |||
| 301 | } | |||
| 302 | ||||
| 303 | static void Clamp_S32_D32_nofilter_trans_shaderproc(const void* sIn, | |||
| 304 | int x, int y, | |||
| 305 | SkPMColor* colors, | |||
| 306 | int count) { | |||
| 307 | const SkBitmapProcState& s = *static_cast<const SkBitmapProcState*>(sIn); | |||
| 308 | SkASSERT(s.fInvMatrix.isTranslate())static_cast<void>( __builtin_expect(static_cast<bool >(s.fInvMatrix.isTranslate()), 1) ? static_cast<void> (0) : []{ do { if (sk_abort_is_enabled()) { do { SkDebugf("%s:%d" ": fatal error: \"" "check(%s)" "\"\n", "/root/firefox-clang/gfx/skia/skia/src/core/SkBitmapProcState.cpp" , 308, "s.fInvMatrix.isTranslate()"); ; sk_abort_no_print(); } while (false); } } while(false); }() ); | |||
| 309 | SkASSERT(count > 0 && colors != nullptr)static_cast<void>( __builtin_expect(static_cast<bool >(count > 0 && colors != nullptr), 1) ? static_cast <void>(0) : []{ do { if (sk_abort_is_enabled()) { do { SkDebugf ("%s:%d" ": fatal error: \"" "check(%s)" "\"\n", "/root/firefox-clang/gfx/skia/skia/src/core/SkBitmapProcState.cpp" , 309, "count > 0 && colors != nullptr"); ; sk_abort_no_print (); } while (false); } } while(false); }() ); | |||
| 310 | SkASSERT(!s.fBilerp)static_cast<void>( __builtin_expect(static_cast<bool >(!s.fBilerp), 1) ? static_cast<void>(0) : []{ do { if (sk_abort_is_enabled()) { do { SkDebugf("%s:%d" ": fatal error: \"" "check(%s)" "\"\n", "/root/firefox-clang/gfx/skia/skia/src/core/SkBitmapProcState.cpp" , 310, "!s.fBilerp"); ; sk_abort_no_print(); } while (false); } } while(false); }() ); | |||
| 311 | ||||
| 312 | const int maxX = s.fPixmap.width() - 1; | |||
| 313 | const int maxY = s.fPixmap.height() - 1; | |||
| 314 | int ix = s.fFilterOneX + x; | |||
| 315 | int iy = SkTPin(s.fFilterOneY + y, 0, maxY); | |||
| 316 | const SkPMColor* row = s.fPixmap.addr32(0, iy); | |||
| 317 | ||||
| 318 | // clamp to the left | |||
| 319 | if (ix < 0) { | |||
| 320 | int n = std::min(-ix, count); | |||
| 321 | SkOpts::memset32(colors, row[0], n); | |||
| 322 | count -= n; | |||
| 323 | if (0 == count) { | |||
| 324 | return; | |||
| 325 | } | |||
| 326 | colors += n; | |||
| 327 | SkASSERT(-ix == n)static_cast<void>( __builtin_expect(static_cast<bool >(-ix == n), 1) ? static_cast<void>(0) : []{ do { if (sk_abort_is_enabled()) { do { SkDebugf("%s:%d" ": fatal error: \"" "check(%s)" "\"\n", "/root/firefox-clang/gfx/skia/skia/src/core/SkBitmapProcState.cpp" , 327, "-ix == n"); ; sk_abort_no_print(); } while (false); } } while(false); }() ); | |||
| 328 | ix = 0; | |||
| 329 | } | |||
| 330 | // copy the middle | |||
| 331 | if (ix <= maxX) { | |||
| 332 | int n = std::min(maxX - ix + 1, count); | |||
| 333 | memcpy(colors, row + ix, n * sizeof(SkPMColor)); | |||
| 334 | count -= n; | |||
| 335 | if (0 == count) { | |||
| 336 | return; | |||
| 337 | } | |||
| 338 | colors += n; | |||
| 339 | } | |||
| 340 | SkASSERT(count > 0)static_cast<void>( __builtin_expect(static_cast<bool >(count > 0), 1) ? static_cast<void>(0) : []{ do { if (sk_abort_is_enabled()) { do { SkDebugf("%s:%d" ": fatal error: \"" "check(%s)" "\"\n", "/root/firefox-clang/gfx/skia/skia/src/core/SkBitmapProcState.cpp" , 340, "count > 0"); ; sk_abort_no_print(); } while (false ); } } while(false); }() ); | |||
| 341 | // clamp to the right | |||
| 342 | SkOpts::memset32(colors, row[maxX], count); | |||
| 343 | } | |||
| 344 | ||||
| 345 | static inline int sk_int_mod(int x, int n) { | |||
| 346 | SkASSERT(n > 0)static_cast<void>( __builtin_expect(static_cast<bool >(n > 0), 1) ? static_cast<void>(0) : []{ do { if (sk_abort_is_enabled()) { do { SkDebugf("%s:%d" ": fatal error: \"" "check(%s)" "\"\n", "/root/firefox-clang/gfx/skia/skia/src/core/SkBitmapProcState.cpp" , 346, "n > 0"); ; sk_abort_no_print(); } while (false); } } while(false); }() ); | |||
| 347 | if ((unsigned)x >= (unsigned)n) { | |||
| 348 | if (x < 0) { | |||
| 349 | x = n + ~(~x % n); | |||
| 350 | } else { | |||
| 351 | x = x % n; | |||
| 352 | } | |||
| 353 | } | |||
| 354 | return x; | |||
| 355 | } | |||
| 356 | ||||
| 357 | static inline int sk_int_mirror(int x, int n) { | |||
| 358 | x = sk_int_mod(x, 2 * n); | |||
| 359 | if (x >= n) { | |||
| 360 | x = n + ~(x - n); | |||
| 361 | } | |||
| 362 | return x; | |||
| 363 | } | |||
| 364 | ||||
| 365 | static void Repeat_S32_D32_nofilter_trans_shaderproc(const void* sIn, | |||
| 366 | int x, int y, | |||
| 367 | SkPMColor* colors, | |||
| 368 | int count) { | |||
| 369 | const SkBitmapProcState& s = *static_cast<const SkBitmapProcState*>(sIn); | |||
| 370 | SkASSERT(s.fInvMatrix.isTranslate())static_cast<void>( __builtin_expect(static_cast<bool >(s.fInvMatrix.isTranslate()), 1) ? static_cast<void> (0) : []{ do { if (sk_abort_is_enabled()) { do { SkDebugf("%s:%d" ": fatal error: \"" "check(%s)" "\"\n", "/root/firefox-clang/gfx/skia/skia/src/core/SkBitmapProcState.cpp" , 370, "s.fInvMatrix.isTranslate()"); ; sk_abort_no_print(); } while (false); } } while(false); }() ); | |||
| 371 | SkASSERT(count > 0 && colors != nullptr)static_cast<void>( __builtin_expect(static_cast<bool >(count > 0 && colors != nullptr), 1) ? static_cast <void>(0) : []{ do { if (sk_abort_is_enabled()) { do { SkDebugf ("%s:%d" ": fatal error: \"" "check(%s)" "\"\n", "/root/firefox-clang/gfx/skia/skia/src/core/SkBitmapProcState.cpp" , 371, "count > 0 && colors != nullptr"); ; sk_abort_no_print (); } while (false); } } while(false); }() ); | |||
| 372 | SkASSERT(!s.fBilerp)static_cast<void>( __builtin_expect(static_cast<bool >(!s.fBilerp), 1) ? static_cast<void>(0) : []{ do { if (sk_abort_is_enabled()) { do { SkDebugf("%s:%d" ": fatal error: \"" "check(%s)" "\"\n", "/root/firefox-clang/gfx/skia/skia/src/core/SkBitmapProcState.cpp" , 372, "!s.fBilerp"); ; sk_abort_no_print(); } while (false); } } while(false); }() ); | |||
| 373 | ||||
| 374 | const int stopX = s.fPixmap.width(); | |||
| 375 | const int stopY = s.fPixmap.height(); | |||
| 376 | int ix = s.fFilterOneX + x; | |||
| 377 | int iy = sk_int_mod(s.fFilterOneY + y, stopY); | |||
| 378 | const SkPMColor* row = s.fPixmap.addr32(0, iy); | |||
| 379 | ||||
| 380 | ix = sk_int_mod(ix, stopX); | |||
| 381 | for (;;) { | |||
| 382 | int n = std::min(stopX - ix, count); | |||
| 383 | memcpy(colors, row + ix, n * sizeof(SkPMColor)); | |||
| 384 | count -= n; | |||
| 385 | if (0 == count) { | |||
| 386 | return; | |||
| 387 | } | |||
| 388 | colors += n; | |||
| 389 | ix = 0; | |||
| 390 | } | |||
| 391 | } | |||
| 392 | ||||
| 393 | static inline void filter_32_alpha(unsigned t, | |||
| 394 | SkPMColor color0, | |||
| 395 | SkPMColor color1, | |||
| 396 | SkPMColor* dstColor, | |||
| 397 | unsigned alphaScale) { | |||
| 398 | SkASSERT((unsigned)t <= 0xF)static_cast<void>( __builtin_expect(static_cast<bool >((unsigned)t <= 0xF), 1) ? static_cast<void>(0) : []{ do { if (sk_abort_is_enabled()) { do { SkDebugf("%s:%d" ": fatal error: \"" "check(%s)" "\"\n", "/root/firefox-clang/gfx/skia/skia/src/core/SkBitmapProcState.cpp" , 398, "(unsigned)t <= 0xF"); ; sk_abort_no_print(); } while (false); } } while(false); }() ); | |||
| 399 | SkASSERT(alphaScale <= 256)static_cast<void>( __builtin_expect(static_cast<bool >(alphaScale <= 256), 1) ? static_cast<void>(0) : []{ do { if (sk_abort_is_enabled()) { do { SkDebugf("%s:%d" ": fatal error: \"" "check(%s)" "\"\n", "/root/firefox-clang/gfx/skia/skia/src/core/SkBitmapProcState.cpp" , 399, "alphaScale <= 256"); ; sk_abort_no_print(); } while (false); } } while(false); }() ); | |||
| 400 | ||||
| 401 | const uint32_t mask = 0xFF00FF; | |||
| 402 | ||||
| 403 | int scale = 256 - 16*t; | |||
| 404 | uint32_t lo = (color0 & mask) * scale; | |||
| 405 | uint32_t hi = ((color0 >> 8) & mask) * scale; | |||
| 406 | ||||
| 407 | scale = 16*t; | |||
| 408 | lo += (color1 & mask) * scale; | |||
| 409 | hi += ((color1 >> 8) & mask) * scale; | |||
| 410 | ||||
| 411 | // TODO: if (alphaScale < 256) ... | |||
| 412 | lo = ((lo >> 8) & mask) * alphaScale; | |||
| 413 | hi = ((hi >> 8) & mask) * alphaScale; | |||
| 414 | ||||
| 415 | *dstColor = ((lo >> 8) & mask) | (hi & ~mask); | |||
| 416 | } | |||
| 417 | ||||
| 418 | static void S32_D32_constX_shaderproc(const void* sIn, | |||
| 419 | int x, int y, | |||
| 420 | SkPMColor* colors, | |||
| 421 | int count) { | |||
| 422 | const SkBitmapProcState& s = *static_cast<const SkBitmapProcState*>(sIn); | |||
| 423 | SkASSERT(s.fInvMatrix.isScaleTranslate())static_cast<void>( __builtin_expect(static_cast<bool >(s.fInvMatrix.isScaleTranslate()), 1) ? static_cast<void >(0) : []{ do { if (sk_abort_is_enabled()) { do { SkDebugf ("%s:%d" ": fatal error: \"" "check(%s)" "\"\n", "/root/firefox-clang/gfx/skia/skia/src/core/SkBitmapProcState.cpp" , 423, "s.fInvMatrix.isScaleTranslate()"); ; sk_abort_no_print (); } while (false); } } while(false); }() ); | |||
| 424 | SkASSERT(count > 0 && colors != nullptr)static_cast<void>( __builtin_expect(static_cast<bool >(count > 0 && colors != nullptr), 1) ? static_cast <void>(0) : []{ do { if (sk_abort_is_enabled()) { do { SkDebugf ("%s:%d" ": fatal error: \"" "check(%s)" "\"\n", "/root/firefox-clang/gfx/skia/skia/src/core/SkBitmapProcState.cpp" , 424, "count > 0 && colors != nullptr"); ; sk_abort_no_print (); } while (false); } } while(false); }() ); | |||
| 425 | SkASSERT(1 == s.fPixmap.width())static_cast<void>( __builtin_expect(static_cast<bool >(1 == s.fPixmap.width()), 1) ? static_cast<void>(0) : []{ do { if (sk_abort_is_enabled()) { do { SkDebugf("%s:%d" ": fatal error: \"" "check(%s)" "\"\n", "/root/firefox-clang/gfx/skia/skia/src/core/SkBitmapProcState.cpp" , 425, "1 == s.fPixmap.width()"); ; sk_abort_no_print(); } while (false); } } while(false); }() ); | |||
| 426 | ||||
| 427 | int iY0; | |||
| 428 | int iY1 SK_INIT_TO_AVOID_WARNING= 0; | |||
| 429 | int iSubY SK_INIT_TO_AVOID_WARNING= 0; | |||
| 430 | ||||
| 431 | if (s.fBilerp) { | |||
| 432 | SkBitmapProcState::MatrixProc mproc = s.getMatrixProc(); | |||
| 433 | uint32_t xy[2]; | |||
| 434 | ||||
| 435 | mproc(s, xy, 1, x, y); | |||
| 436 | ||||
| 437 | iY0 = xy[0] >> 18; | |||
| 438 | iY1 = xy[0] & 0x3FFF; | |||
| 439 | iSubY = (xy[0] >> 14) & 0xF; | |||
| 440 | } else { | |||
| 441 | int yTemp; | |||
| 442 | ||||
| 443 | if (s.fInvMatrix.isTranslate()) { | |||
| 444 | yTemp = s.fFilterOneY + y; | |||
| 445 | } else{ | |||
| 446 | const SkBitmapProcStateAutoMapper mapper(s, x, y); | |||
| 447 | ||||
| 448 | // When the matrix has a scale component the setup code in | |||
| 449 | // chooseProcs multiples the inverse matrix by the inverse of the | |||
| 450 | // bitmap's width and height. Since this method is going to do | |||
| 451 | // its own tiling and sampling we need to undo that here. | |||
| 452 | if (SkTileMode::kClamp != s.fTileModeX || SkTileMode::kClamp != s.fTileModeY) { | |||
| 453 | yTemp = SkFixed3232ToInt(mapper.fixed3232Y() * s.fPixmap.height())((int)((mapper.fixed3232Y() * s.fPixmap.height()) >> 32 )); | |||
| 454 | } else { | |||
| 455 | yTemp = mapper.intY(); | |||
| 456 | } | |||
| 457 | } | |||
| 458 | ||||
| 459 | const int stopY = s.fPixmap.height(); | |||
| 460 | switch (s.fTileModeY) { | |||
| 461 | case SkTileMode::kClamp: | |||
| 462 | iY0 = SkTPin(yTemp, 0, stopY-1); | |||
| 463 | break; | |||
| 464 | case SkTileMode::kRepeat: | |||
| 465 | iY0 = sk_int_mod(yTemp, stopY); | |||
| 466 | break; | |||
| 467 | case SkTileMode::kMirror: | |||
| 468 | default: | |||
| 469 | iY0 = sk_int_mirror(yTemp, stopY); | |||
| 470 | break; | |||
| 471 | } | |||
| 472 | ||||
| 473 | #ifdef SK_DEBUG | |||
| 474 | { | |||
| 475 | const SkBitmapProcStateAutoMapper mapper(s, x, y); | |||
| 476 | int iY2; | |||
| 477 | ||||
| 478 | if (!s.fInvMatrix.isTranslate() && | |||
| 479 | (SkTileMode::kClamp != s.fTileModeX || SkTileMode::kClamp != s.fTileModeY)) { | |||
| 480 | iY2 = SkFixed3232ToInt(mapper.fixed3232Y() * s.fPixmap.height())((int)((mapper.fixed3232Y() * s.fPixmap.height()) >> 32 )); | |||
| 481 | } else { | |||
| 482 | iY2 = mapper.intY(); | |||
| 483 | } | |||
| 484 | ||||
| 485 | switch (s.fTileModeY) { | |||
| 486 | case SkTileMode::kClamp: | |||
| 487 | iY2 = SkTPin(iY2, 0, stopY-1); | |||
| 488 | break; | |||
| 489 | case SkTileMode::kRepeat: | |||
| 490 | iY2 = sk_int_mod(iY2, stopY); | |||
| 491 | break; | |||
| 492 | case SkTileMode::kMirror: | |||
| 493 | default: | |||
| 494 | iY2 = sk_int_mirror(iY2, stopY); | |||
| 495 | break; | |||
| 496 | } | |||
| 497 | ||||
| 498 | SkASSERT(iY0 == iY2)static_cast<void>( __builtin_expect(static_cast<bool >(iY0 == iY2), 1) ? static_cast<void>(0) : []{ do { if (sk_abort_is_enabled()) { do { SkDebugf("%s:%d" ": fatal error: \"" "check(%s)" "\"\n", "/root/firefox-clang/gfx/skia/skia/src/core/SkBitmapProcState.cpp" , 498, "iY0 == iY2"); ; sk_abort_no_print(); } while (false); } } while(false); }() ); | |||
| 499 | } | |||
| 500 | #endif | |||
| 501 | } | |||
| 502 | ||||
| 503 | const SkPMColor* row0 = s.fPixmap.addr32(0, iY0); | |||
| 504 | SkPMColor color; | |||
| 505 | ||||
| 506 | if (s.fBilerp) { | |||
| 507 | const SkPMColor* row1 = s.fPixmap.addr32(0, iY1); | |||
| 508 | filter_32_alpha(iSubY, *row0, *row1, &color, s.fAlphaScale); | |||
| 509 | } else { | |||
| 510 | if (s.fAlphaScale < 256) { | |||
| 511 | color = SkAlphaMulQ(*row0, s.fAlphaScale); | |||
| 512 | } else { | |||
| 513 | color = *row0; | |||
| 514 | } | |||
| 515 | } | |||
| 516 | ||||
| 517 | SkOpts::memset32(colors, color, count); | |||
| 518 | } | |||
| 519 | ||||
| 520 | static void DoNothing_shaderproc(const void*, int x, int y, | |||
| 521 | SkPMColor* colors, int count) { | |||
| 522 | // if we get called, the matrix is too tricky, so we just draw nothing | |||
| 523 | SkOpts::memset32(colors, 0, count); | |||
| 524 | } | |||
| 525 | ||||
| 526 | bool SkBitmapProcState::setupForTranslate() { | |||
| 527 | SkPoint pt; | |||
| 528 | const SkBitmapProcStateAutoMapper mapper(*this, 0, 0, &pt); | |||
| 529 | ||||
| 530 | /* | |||
| 531 | * if the translate is larger than our ints, we can get random results, or | |||
| 532 | * worse, we might get 0x80000000, which wreaks havoc on us, since we can't | |||
| 533 | * negate it. | |||
| 534 | */ | |||
| 535 | const SkScalar too_big = SkIntToScalar(1 << 30)static_cast<SkScalar>(1 << 30); | |||
| 536 | if (SkScalarAbs(pt.fX)std::fabs(pt.fX) > too_big || SkScalarAbs(pt.fY)std::fabs(pt.fY) > too_big) { | |||
| 537 | return false; | |||
| 538 | } | |||
| 539 | ||||
| 540 | // Since we know we're not filtered, we re-purpose these fields allow | |||
| 541 | // us to go from device -> src coordinates w/ just an integer add, | |||
| 542 | // rather than running through the inverse-matrix | |||
| 543 | fFilterOneX = mapper.intX(); | |||
| 544 | fFilterOneY = mapper.intY(); | |||
| 545 | ||||
| 546 | return true; | |||
| 547 | } | |||
| 548 | ||||
| 549 | SkBitmapProcState::ShaderProc32 SkBitmapProcState::chooseShaderProc32() { | |||
| 550 | ||||
| 551 | if (kN32_SkColorType != fPixmap.colorType()) { | |||
| 552 | return nullptr; | |||
| 553 | } | |||
| 554 | ||||
| 555 | if (1 == fPixmap.width() && fInvMatrix.isScaleTranslate()) { | |||
| 556 | if (!fBilerp && fInvMatrix.isTranslate() && !this->setupForTranslate()) { | |||
| 557 | return DoNothing_shaderproc; | |||
| 558 | } | |||
| 559 | return S32_D32_constX_shaderproc; | |||
| 560 | } | |||
| 561 | ||||
| 562 | if (fAlphaScale < 256) { | |||
| 563 | return nullptr; | |||
| 564 | } | |||
| 565 | if (!fInvMatrix.isTranslate()) { | |||
| 566 | return nullptr; | |||
| 567 | } | |||
| 568 | if (fBilerp) { | |||
| 569 | return nullptr; | |||
| 570 | } | |||
| 571 | ||||
| 572 | SkTileMode tx = fTileModeX; | |||
| 573 | SkTileMode ty = fTileModeY; | |||
| 574 | ||||
| 575 | if (SkTileMode::kClamp == tx && SkTileMode::kClamp == ty) { | |||
| 576 | if (this->setupForTranslate()) { | |||
| 577 | return Clamp_S32_D32_nofilter_trans_shaderproc; | |||
| 578 | } | |||
| 579 | return DoNothing_shaderproc; | |||
| 580 | } | |||
| 581 | if (SkTileMode::kRepeat == tx && SkTileMode::kRepeat == ty) { | |||
| 582 | if (this->setupForTranslate()) { | |||
| 583 | return Repeat_S32_D32_nofilter_trans_shaderproc; | |||
| 584 | } | |||
| 585 | return DoNothing_shaderproc; | |||
| 586 | } | |||
| 587 | return nullptr; | |||
| 588 | } | |||
| 589 | ||||
| 590 | #ifdef SK_DEBUG | |||
| 591 | ||||
| 592 | static void check_scale_nofilter(uint32_t bitmapXY[], int count, | |||
| 593 | unsigned mx, unsigned my) { | |||
| 594 | unsigned y = *bitmapXY++; | |||
| 595 | SkASSERT(y < my)static_cast<void>( __builtin_expect(static_cast<bool >(y < my), 1) ? static_cast<void>(0) : []{ do { if (sk_abort_is_enabled()) { do { SkDebugf("%s:%d" ": fatal error: \"" "check(%s)" "\"\n", "/root/firefox-clang/gfx/skia/skia/src/core/SkBitmapProcState.cpp" , 595, "y < my"); ; sk_abort_no_print(); } while (false); } } while(false); }() ); | |||
| 596 | ||||
| 597 | const uint16_t* xptr = reinterpret_cast<const uint16_t*>(bitmapXY); | |||
| 598 | for (int i = 0; i < count; ++i) { | |||
| 599 | SkASSERT(xptr[i] < mx)static_cast<void>( __builtin_expect(static_cast<bool >(xptr[i] < mx), 1) ? static_cast<void>(0) : []{ do { if (sk_abort_is_enabled()) { do { SkDebugf("%s:%d" ": fatal error: \"" "check(%s)" "\"\n", "/root/firefox-clang/gfx/skia/skia/src/core/SkBitmapProcState.cpp" , 599, "xptr[i] < mx"); ; sk_abort_no_print(); } while (false ); } } while(false); }() ); | |||
| 600 | } | |||
| 601 | } | |||
| 602 | ||||
| 603 | static void check_scale_filter(uint32_t bitmapXY[], int count, | |||
| 604 | unsigned mx, unsigned my) { | |||
| 605 | uint32_t YY = *bitmapXY++; | |||
| 606 | unsigned y0 = YY >> 18; | |||
| 607 | unsigned y1 = YY & 0x3FFF; | |||
| 608 | SkASSERT(y0 < my)static_cast<void>( __builtin_expect(static_cast<bool >(y0 < my), 1) ? static_cast<void>(0) : []{ do { if (sk_abort_is_enabled()) { do { SkDebugf("%s:%d" ": fatal error: \"" "check(%s)" "\"\n", "/root/firefox-clang/gfx/skia/skia/src/core/SkBitmapProcState.cpp" , 608, "y0 < my"); ; sk_abort_no_print(); } while (false); } } while(false); }() ); | |||
| 609 | SkASSERT(y1 < my)static_cast<void>( __builtin_expect(static_cast<bool >(y1 < my), 1) ? static_cast<void>(0) : []{ do { if (sk_abort_is_enabled()) { do { SkDebugf("%s:%d" ": fatal error: \"" "check(%s)" "\"\n", "/root/firefox-clang/gfx/skia/skia/src/core/SkBitmapProcState.cpp" , 609, "y1 < my"); ; sk_abort_no_print(); } while (false); } } while(false); }() ); | |||
| 610 | ||||
| 611 | for (int i = 0; i < count; ++i) { | |||
| 612 | uint32_t XX = bitmapXY[i]; | |||
| 613 | unsigned x0 = XX >> 18; | |||
| 614 | unsigned x1 = XX & 0x3FFF; | |||
| 615 | SkASSERT(x0 < mx)static_cast<void>( __builtin_expect(static_cast<bool >(x0 < mx), 1) ? static_cast<void>(0) : []{ do { if (sk_abort_is_enabled()) { do { SkDebugf("%s:%d" ": fatal error: \"" "check(%s)" "\"\n", "/root/firefox-clang/gfx/skia/skia/src/core/SkBitmapProcState.cpp" , 615, "x0 < mx"); ; sk_abort_no_print(); } while (false); } } while(false); }() ); | |||
| 616 | SkASSERT(x1 < mx)static_cast<void>( __builtin_expect(static_cast<bool >(x1 < mx), 1) ? static_cast<void>(0) : []{ do { if (sk_abort_is_enabled()) { do { SkDebugf("%s:%d" ": fatal error: \"" "check(%s)" "\"\n", "/root/firefox-clang/gfx/skia/skia/src/core/SkBitmapProcState.cpp" , 616, "x1 < mx"); ; sk_abort_no_print(); } while (false); } } while(false); }() ); | |||
| 617 | } | |||
| 618 | } | |||
| 619 | ||||
| 620 | static void check_affine_nofilter(uint32_t bitmapXY[], int count, unsigned mx, unsigned my) { | |||
| 621 | for (int i = 0; i < count; ++i) { | |||
| 622 | uint32_t XY = bitmapXY[i]; | |||
| 623 | unsigned x = XY & 0xFFFF; | |||
| 624 | unsigned y = XY >> 16; | |||
| 625 | SkASSERT(x < mx)static_cast<void>( __builtin_expect(static_cast<bool >(x < mx), 1) ? static_cast<void>(0) : []{ do { if (sk_abort_is_enabled()) { do { SkDebugf("%s:%d" ": fatal error: \"" "check(%s)" "\"\n", "/root/firefox-clang/gfx/skia/skia/src/core/SkBitmapProcState.cpp" , 625, "x < mx"); ; sk_abort_no_print(); } while (false); } } while(false); }() ); | |||
| 626 | SkASSERT(y < my)static_cast<void>( __builtin_expect(static_cast<bool >(y < my), 1) ? static_cast<void>(0) : []{ do { if (sk_abort_is_enabled()) { do { SkDebugf("%s:%d" ": fatal error: \"" "check(%s)" "\"\n", "/root/firefox-clang/gfx/skia/skia/src/core/SkBitmapProcState.cpp" , 626, "y < my"); ; sk_abort_no_print(); } while (false); } } while(false); }() ); | |||
| 627 | } | |||
| 628 | } | |||
| 629 | ||||
| 630 | static void check_affine_filter(uint32_t bitmapXY[], int count, unsigned mx, unsigned my) { | |||
| 631 | for (int i = 0; i
| |||
| 632 | uint32_t YY = *bitmapXY++; | |||
| ||||
| 633 | unsigned y0 = YY >> 18; | |||
| 634 | unsigned y1 = YY & 0x3FFF; | |||
| 635 | SkASSERT(y0 < my)static_cast<void>( __builtin_expect(static_cast<bool >(y0 < my), 1) ? static_cast<void>(0) : []{ do { if (sk_abort_is_enabled()) { do { SkDebugf("%s:%d" ": fatal error: \"" "check(%s)" "\"\n", "/root/firefox-clang/gfx/skia/skia/src/core/SkBitmapProcState.cpp" , 635, "y0 < my"); ; sk_abort_no_print(); } while (false); } } while(false); }() ); | |||
| 636 | SkASSERT(y1 < my)static_cast<void>( __builtin_expect(static_cast<bool >(y1 < my), 1) ? static_cast<void>(0) : []{ do { if (sk_abort_is_enabled()) { do { SkDebugf("%s:%d" ": fatal error: \"" "check(%s)" "\"\n", "/root/firefox-clang/gfx/skia/skia/src/core/SkBitmapProcState.cpp" , 636, "y1 < my"); ; sk_abort_no_print(); } while (false); } } while(false); }() ); | |||
| 637 | ||||
| 638 | uint32_t XX = *bitmapXY++; | |||
| 639 | unsigned x0 = XX >> 18; | |||
| 640 | unsigned x1 = XX & 0x3FFF; | |||
| 641 | SkASSERT(x0 < mx)static_cast<void>( __builtin_expect(static_cast<bool >(x0 < mx), 1) ? static_cast<void>(0) : []{ do { if (sk_abort_is_enabled()) { do { SkDebugf("%s:%d" ": fatal error: \"" "check(%s)" "\"\n", "/root/firefox-clang/gfx/skia/skia/src/core/SkBitmapProcState.cpp" , 641, "x0 < mx"); ; sk_abort_no_print(); } while (false); } } while(false); }() ); | |||
| 642 | SkASSERT(x1 < mx)static_cast<void>( __builtin_expect(static_cast<bool >(x1 < mx), 1) ? static_cast<void>(0) : []{ do { if (sk_abort_is_enabled()) { do { SkDebugf("%s:%d" ": fatal error: \"" "check(%s)" "\"\n", "/root/firefox-clang/gfx/skia/skia/src/core/SkBitmapProcState.cpp" , 642, "x1 < mx"); ; sk_abort_no_print(); } while (false); } } while(false); }() ); | |||
| 643 | } | |||
| 644 | } | |||
| 645 | ||||
| 646 | void SkBitmapProcState::DebugMatrixProc(const SkBitmapProcState& state, | |||
| 647 | uint32_t bitmapXY[], int count, | |||
| 648 | int x, int y) { | |||
| 649 | SkASSERT(bitmapXY)static_cast<void>( __builtin_expect(static_cast<bool >(bitmapXY), 1) ? static_cast<void>(0) : []{ do { if (sk_abort_is_enabled()) { do { SkDebugf("%s:%d" ": fatal error: \"" "check(%s)" "\"\n", "/root/firefox-clang/gfx/skia/skia/src/core/SkBitmapProcState.cpp" , 649, "bitmapXY"); ; sk_abort_no_print(); } while (false); } } while(false); }() ); | |||
| ||||
| 650 | SkASSERT(count > 0)static_cast<void>( __builtin_expect(static_cast<bool >(count > 0), 1) ? static_cast<void>(0) : []{ do { if (sk_abort_is_enabled()) { do { SkDebugf("%s:%d" ": fatal error: \"" "check(%s)" "\"\n", "/root/firefox-clang/gfx/skia/skia/src/core/SkBitmapProcState.cpp" , 650, "count > 0"); ; sk_abort_no_print(); } while (false ); } } while(false); }() ); | |||
| 651 | ||||
| 652 | state.fMatrixProc(state, bitmapXY, count, x, y); | |||
| 653 | ||||
| 654 | void (*proc)(uint32_t bitmapXY[], int count, unsigned mx, unsigned my); | |||
| 655 | ||||
| 656 | if (state.fInvMatrix.isScaleTranslate()) { | |||
| 657 | proc = state.fBilerp ? check_scale_filter : check_scale_nofilter; | |||
| 658 | } else { | |||
| 659 | proc = state.fBilerp ? check_affine_filter : check_affine_nofilter; | |||
| 660 | } | |||
| 661 | ||||
| 662 | proc(bitmapXY, count, state.fPixmap.width(), state.fPixmap.height()); | |||
| 663 | } | |||
| 664 | ||||
| 665 | SkBitmapProcState::MatrixProc SkBitmapProcState::getMatrixProc() const { | |||
| 666 | return DebugMatrixProc; | |||
| 667 | } | |||
| 668 | ||||
| 669 | #endif | |||
| 670 | ||||
| 671 | /* | |||
| 672 | The storage requirements for the different matrix procs are as follows, | |||
| 673 | where each X or Y is 2 bytes, and N is the number of pixels/elements: | |||
| 674 | ||||
| 675 | scale/translate nofilter Y(4bytes) + N * X | |||
| 676 | affine/perspective nofilter N * (X Y) | |||
| 677 | scale/translate filter Y Y + N * (X X) | |||
| 678 | affine filter N * (Y Y X X) | |||
| 679 | */ | |||
| 680 | int SkBitmapProcState::maxCountForBufferSize(size_t bufferSize) const { | |||
| 681 | int32_t size = static_cast<int32_t>(bufferSize); | |||
| 682 | ||||
| 683 | size &= ~3; // only care about 4-byte aligned chunks | |||
| 684 | if (fInvMatrix.isScaleTranslate()) { | |||
| 685 | size -= 4; // the shared Y (or YY) coordinate | |||
| 686 | if (size < 0) { | |||
| 687 | size = 0; | |||
| 688 | } | |||
| 689 | size >>= 1; | |||
| 690 | } else { | |||
| 691 | size >>= 2; | |||
| 692 | } | |||
| 693 | ||||
| 694 | if (fBilerp) { | |||
| 695 | size >>= 1; | |||
| 696 | } | |||
| 697 | ||||
| 698 | return size; | |||
| 699 | } | |||
| 700 |