aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/opts/SkXfermode_opts.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/opts/SkXfermode_opts.h')
-rw-r--r--src/opts/SkXfermode_opts.h14
1 files changed, 14 insertions, 0 deletions
diff --git a/src/opts/SkXfermode_opts.h b/src/opts/SkXfermode_opts.h
index f15094c98b..31817f5f61 100644
--- a/src/opts/SkXfermode_opts.h
+++ b/src/opts/SkXfermode_opts.h
@@ -9,6 +9,7 @@
#define Sk4pxXfermode_DEFINED
#include "Sk4px.h"
+#include "SkMSAN.h"
#include "SkNx.h"
#include "SkXfermode_proccoeff.h"
@@ -202,6 +203,17 @@ XFERMODE_AA(Plus) { // [ clamp( (1-AA)D + (AA)(S+D) ) == clamp(D + AA*S) ]
#undef XFERMODE_AA
+// Src and Clear modes are safe to use with unitialized dst buffers,
+// even if the implementation branches based on bytes from dst (e.g. asserts in Debug mode).
+// For those modes, just lie to MSAN that dst is always intialized.
+template <typename Xfermode> static void mark_dst_initialized_if_safe(void*, void*) {}
+template <> void mark_dst_initialized_if_safe<Src>(void* dst, void* end) {
+ sk_msan_mark_initialized(dst, end, "Src doesn't read dst.");
+}
+template <> void mark_dst_initialized_if_safe<Clear>(void* dst, void* end) {
+ sk_msan_mark_initialized(dst, end, "Clear doesn't read dst.");
+}
+
template <typename Xfermode>
class Sk4pxXfermode : public SkProcCoeffXfermode {
public:
@@ -209,6 +221,7 @@ public:
: INHERITED(rec, mode) {}
void xfer32(SkPMColor dst[], const SkPMColor src[], int n, const SkAlpha aa[]) const override {
+ mark_dst_initialized_if_safe<Xfermode>(dst, dst+n);
if (nullptr == aa) {
Sk4px::MapDstSrc(n, dst, src, Xfermode());
} else {
@@ -217,6 +230,7 @@ public:
}
void xfer16(uint16_t dst[], const SkPMColor src[], int n, const SkAlpha aa[]) const override {
+ mark_dst_initialized_if_safe<Xfermode>(dst, dst+n);
SkPMColor dst32[4];
while (n >= 4) {
dst32[0] = SkPixel16ToPixel32(dst[0]);