#pragma once #include #include #include "engine/palette.h" #include "utils/attributes.h" namespace devilution { enum class BlitType : uint8_t { Transparent, Pixels, Fill }; struct BlitCommand { BlitType type; const uint8_t *srcEnd; // Pointer past the end of the command. unsigned length; // Number of pixels this command will write. uint8_t color; // For `BlitType::Pixel` and `BlitType::Fill` only. }; DVL_ALWAYS_INLINE DVL_ATTRIBUTE_HOT void BlitFillDirect(uint8_t *dst, unsigned length, uint8_t color) { std::memset(dst, color, length); } DVL_ALWAYS_INLINE DVL_ATTRIBUTE_HOT void BlitPixelsDirect(uint8_t *DVL_RESTRICT dst, const uint8_t *DVL_RESTRICT src, unsigned length) { std::memcpy(dst, src, length); } struct BlitDirect { DVL_ALWAYS_INLINE DVL_ATTRIBUTE_HOT void operator()(BlitCommand cmd, uint8_t *DVL_RESTRICT dst, const uint8_t *DVL_RESTRICT src) { switch (cmd.type) { case BlitType::Fill: BlitFillDirect(dst, cmd.length, cmd.color); return; case BlitType::Pixels: BlitPixelsDirect(dst, src, cmd.length); return; case BlitType::Transparent: return; } } }; DVL_ALWAYS_INLINE DVL_ATTRIBUTE_HOT void BlitFillWithMap(uint8_t *dst, unsigned length, uint8_t color, const uint8_t *DVL_RESTRICT colorMap) { assert(length != 0); std::memset(dst, colorMap[color], length); } DVL_ALWAYS_INLINE DVL_ATTRIBUTE_HOT void BlitPixelsWithMap(uint8_t *DVL_RESTRICT dst, const uint8_t *DVL_RESTRICT src, unsigned length, const uint8_t *DVL_RESTRICT colorMap) { assert(length != 0); const uint8_t *end = src + length; while (src + 3 < end) { *dst++ = colorMap[*src++]; *dst++ = colorMap[*src++]; *dst++ = colorMap[*src++]; *dst++ = colorMap[*src++]; } while (src < end) { *dst++ = colorMap[*src++]; } } DVL_ALWAYS_INLINE DVL_ATTRIBUTE_HOT void BlitFillBlended(uint8_t *dst, unsigned length, uint8_t color) { assert(length != 0); const uint8_t *end = dst + length; const std::array &tbl = paletteTransparencyLookup[color]; while (dst + 3 < end) { *dst = tbl[*dst]; ++dst; *dst = tbl[*dst]; ++dst; *dst = tbl[*dst]; ++dst; *dst = tbl[*dst]; ++dst; } while (dst < end) { *dst = tbl[*dst]; ++dst; } } DVL_ALWAYS_INLINE DVL_ATTRIBUTE_HOT void BlitPixelsBlended(uint8_t *DVL_RESTRICT dst, const uint8_t *DVL_RESTRICT src, unsigned length) { assert(length != 0); const uint8_t *end = src + length; while (src + 3 < end) { *dst = paletteTransparencyLookup[*dst][*src++]; ++dst; *dst = paletteTransparencyLookup[*dst][*src++]; ++dst; *dst = paletteTransparencyLookup[*dst][*src++]; ++dst; *dst = paletteTransparencyLookup[*dst][*src++]; ++dst; } while (src < end) { *dst = paletteTransparencyLookup[*dst][*src++]; ++dst; } } struct BlitWithMap { const uint8_t *DVL_RESTRICT colorMap; DVL_ALWAYS_INLINE DVL_ATTRIBUTE_HOT void operator()(BlitCommand cmd, uint8_t *DVL_RESTRICT dst, const uint8_t *DVL_RESTRICT src) const { switch (cmd.type) { case BlitType::Fill: BlitFillWithMap(dst, cmd.length, cmd.color, colorMap); return; case BlitType::Pixels: BlitPixelsWithMap(dst, src, cmd.length, colorMap); return; case BlitType::Transparent: return; } } }; DVL_ALWAYS_INLINE DVL_ATTRIBUTE_HOT void BlitPixelsBlendedWithMap(uint8_t *DVL_RESTRICT dst, const uint8_t *DVL_RESTRICT src, unsigned length, const uint8_t *DVL_RESTRICT colorMap) { assert(length != 0); const uint8_t *end = src + length; while (src + 3 < end) { *dst = paletteTransparencyLookup[*dst][colorMap[*src++]]; ++dst; *dst = paletteTransparencyLookup[*dst][colorMap[*src++]]; ++dst; *dst = paletteTransparencyLookup[*dst][colorMap[*src++]]; ++dst; *dst = paletteTransparencyLookup[*dst][colorMap[*src++]]; ++dst; } while (src < end) { *dst = paletteTransparencyLookup[*dst][colorMap[*src++]]; ++dst; } } struct BlitBlendedWithMap { const uint8_t *colorMap; DVL_ALWAYS_INLINE DVL_ATTRIBUTE_HOT void operator()(BlitCommand cmd, uint8_t *DVL_RESTRICT dst, const uint8_t *DVL_RESTRICT src) const { switch (cmd.type) { case BlitType::Fill: BlitFillBlended(dst, cmd.length, colorMap[cmd.color]); return; case BlitType::Pixels: BlitPixelsBlendedWithMap(dst, src, cmd.length, colorMap); return; case BlitType::Transparent: return; } } }; } // namespace devilution