Bug Summary

File:root/firefox-clang/gfx/skia/skia/src/core/SkBitmapProcState.cpp
Warning:line 632, column 23
Dereference of null pointer

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-pc-linux-gnu -O3 -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name SkBitmapProcState.cpp -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=cplusplus -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -analyzer-config-compatibility-mode=true -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -mframe-pointer=all -relaxed-aliasing -ffp-contract=off -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fdebug-compilation-dir=/root/firefox-clang/obj-x86_64-pc-linux-gnu/gfx/skia -fcoverage-compilation-dir=/root/firefox-clang/obj-x86_64-pc-linux-gnu/gfx/skia -resource-dir /usr/lib/llvm-23/lib/clang/23 -include /root/firefox-clang/config/gcc_hidden.h -include /root/firefox-clang/obj-x86_64-pc-linux-gnu/mozilla-config.h -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/stl_wrappers -D _GLIBCXX_ASSERTIONS=1 -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/system_wrappers -U _FORTIFY_SOURCE -D _FORTIFY_SOURCE=2 -D DEBUG=1 -D MOZ_SKIA -D SKIA_IMPLEMENTATION=1 -D SK_PDF_USE_HARFBUZZ_SUBSET=1 -D MOZ_HAS_MOZGLUE -D MOZILLA_INTERNAL_API -D IMPL_LIBXUL -D MOZ_SUPPORT_LEAKCHECKING -D STATIC_EXPORTABLE_JS_API -I /root/firefox-clang/gfx/skia -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/gfx/skia -I /root/firefox-clang/gfx/skia/skia -I /root/firefox-clang/gfx/harfbuzz/src -I /root/firefox-clang/gfx/cairo/cairo/src -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/include -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/include/nspr -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/include/nss -D MOZILLA_CLIENT -I /usr/include/freetype2 -I /usr/include/libpng16 -I /usr/include/freetype2 -I /usr/include/libpng16 -I /usr/include/pango-1.0 -I /usr/include/harfbuzz -I /usr/include/glib-2.0 -I /usr/lib/x86_64-linux-gnu/glib-2.0/include -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/fribidi -I /usr/include/cairo -I /usr/include/freetype2 -I /usr/include/libpng16 -I /usr/include/pixman-1 -I /usr/include/sysprof-6 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/16/../../../../include/c++/16 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/16/../../../../include/x86_64-linux-gnu/c++/16 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/16/../../../../include/c++/16/backward -internal-isystem /usr/lib/llvm-23/lib/clang/23/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/16/../../../../x86_64-linux-gnu/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -Wno-error=pessimizing-move -Wno-error=large-by-value-copy=128 -Wno-error=implicit-int-float-conversion -Wno-error=thread-safety-analysis -Wno-error=tautological-type-limit-compare -Wno-invalid-offsetof -Wno-range-loop-analysis -Wno-deprecated-anon-enum-enum-conversion -Wno-deprecated-enum-enum-conversion -Wno-inline-new-delete -Wno-error=deprecated-declarations -Wno-error=array-bounds -Wno-error=free-nonheap-object -Wno-error=atomic-alignment -Wno-error=deprecated-builtins -Wno-psabi -Wno-error=builtin-macro-redefined -Wno-vla-cxx-extension -Wno-unknown-warning-option -Wno-character-conversion -Wno-deprecated-declarations -Wno-overloaded-virtual -Wno-sign-compare -Wno-unreachable-code -Wno-unused-function -Wno-implicit-fallthrough -Wno-inconsistent-missing-override -Wno-macro-redefined -Wno-unused-private-field -std=gnu++20 -fdeprecated-macro -ferror-limit 19 -fstrict-flex-arrays=1 -stack-protector 2 -fstack-clash-protection -ftrivial-auto-var-init=pattern -fno-rtti -fgnuc-version=4.2.1 -fno-implicit-modules -fskip-odr-check-in-gmf -fno-sized-deallocation -fno-aligned-allocation -fdiagnostics-absolute-paths -vectorize-loops -vectorize-slp -analyzer-checker optin.performance.Padding -analyzer-output=html -analyzer-config stable-report-filename=true -mllvm -dwarf-linkage-names=Abstract -faddrsig -fdwarf2-cfi-asm -o /tmp/scan-build-2026-09-01-224014-2642839-1 -x c++ /root/firefox-clang/gfx/skia/skia/src/core/SkBitmapProcState.cpp
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
25class SkImage;
26class 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_).
34static 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
84static 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
128static 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
148SkBitmapProcState::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.
155static 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 */
163static 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 */
176static 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
184static 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
190bool 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 */
263bool 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
303static 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
345static 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
357static 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
365static 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
393static 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
418static 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
520static 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
526bool 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
549SkBitmapProcState::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
592static 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
603static 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
620static 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
630static void check_affine_filter(uint32_t bitmapXY[], int count, unsigned mx, unsigned my) {
631 for (int i = 0; i
8.1
'i' is < 'count'
< count; ++i) {
9
Loop condition is true. Entering loop body
632 uint32_t YY = *bitmapXY++;
10
Null pointer value stored to 'bitmapXY'
11
Dereference of null pointer
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
646void 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); }() )
;
1
Assuming the condition is false
2
'?' condition is 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); }() )
;
3
Assuming 'count' is > 0
4
'?' condition is true
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;
5
Taking false branch
6
Assuming field 'fBilerp' is true
7
'?' condition is true
660 }
661
662 proc(bitmapXY, count, state.fPixmap.width(), state.fPixmap.height());
8
Calling 'check_affine_filter'
663}
664
665SkBitmapProcState::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 */
680int 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