Index: src/opts/SkXfermode_opts.h |
diff --git a/src/opts/SkXfermode_opts.h b/src/opts/SkXfermode_opts.h |
index f15094c98bfa5fff4cfc12c0109324252cbc8b36..31817f5f618769387afe64b65785e7bbb55e7756 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]); |