1
0
mirror of https://github.com/OpenRCT2/OpenRCT2 synced 2026-01-29 17:54:50 +01:00

Refactor bitmap drawing, one arg struct

This commit is contained in:
Ted John
2020-05-31 13:55:47 +01:00
parent 1b6899a954
commit d0b1bfbe87
4 changed files with 136 additions and 106 deletions

View File

@@ -227,9 +227,10 @@ static bool sprite_file_export(rct_g1_element* spriteHeader, const char* outPath
}
else
{
gfx_bmp_sprite_to_buffer(
PaletteMap::GetDefault(), spriteHeader->offset, pixels, spriteHeader, &dpi, spriteHeader->height,
spriteHeader->width, ImageId());
DrawSpriteArgs args(
&dpi, ImageId(), PaletteMap::GetDefault(), *spriteHeader, spriteHeader->width, spriteHeader->height,
spriteHeader->offset, pixels);
gfx_bmp_sprite_to_buffer(args);
}
auto const pixels8 = dpi.bits;

View File

@@ -9,16 +9,19 @@
#include "Drawing.h"
static void FASTCALL gfx_bmp_sprite_to_buffer_magnify(
const PaletteMap& paletteMap, uint8_t* source_pointer, uint8_t* dest_pointer, const rct_g1_element* source_image,
rct_drawpixelinfo* dest_dpi, int32_t height, int32_t width, ImageId imageId)
static void FASTCALL gfx_bmp_sprite_to_buffer_magnify(DrawSpriteArgs& args)
{
auto zoom_level = dest_dpi->zoom_level;
auto dpi = args.DPI;
auto zoom_level = dpi->zoom_level;
uint8_t zoom_amount = 1 * zoom_level;
uint32_t dest_line_width = (dest_dpi->width / zoom_level) + dest_dpi->pitch;
uint32_t source_line_width = source_image->width * zoom_level;
uint32_t dest_line_width = (dpi->width / zoom_level) + dpi->pitch;
uint32_t source_line_width = args.SourceImage.width * zoom_level;
// Basic bitmap with no draw pixels
auto source_pointer = args.SourceBits;
auto dest_pointer = args.DestinationBits;
auto width = args.Width;
auto height = args.Height;
for (; height > 0; height -= zoom_amount)
{
auto next_source_pointer = source_pointer + source_line_width;
@@ -37,116 +40,94 @@ static void FASTCALL gfx_bmp_sprite_to_buffer_magnify(
}
}
template<DrawBlendOp TBlendOp> static void FASTCALL gfx_bmp_sprite_to_buffer_x(DrawSpriteArgs& args)
{
auto src = args.SourceBits;
auto dst = args.DestinationBits;
auto& paletteMap = args.PalMap;
auto width = args.Width;
auto height = args.Height;
auto dpi = args.DPI;
auto zoomLevel = dpi->zoom_level;
size_t srcLineWidth = args.SourceImage.width * zoomLevel;
size_t dstLineWidth = (static_cast<size_t>(dpi->width) / zoomLevel) + dpi->pitch;
uint8_t zoom = 1 * zoomLevel;
for (; height > 0; height -= zoom)
{
auto nextSrc = src + srcLineWidth;
auto nextDst = dst + dstLineWidth;
for (int32_t widthRemaining = width; widthRemaining > 0; widthRemaining -= zoom, src += zoom, dst++)
{
if constexpr (TBlendOp & BLEND_TRANSPARENT)
{
// Ignore transparent pixels
if (*src == 0)
{
continue;
}
}
if constexpr (((TBlendOp & BLEND_SRC) != 0) && ((TBlendOp & BLEND_DST) != 0))
{
*dst = paletteMap.Blend(*src, *dst);
}
else if constexpr ((TBlendOp & BLEND_SRC) != 0)
{
*dst = paletteMap[*src];
}
else if constexpr ((TBlendOp & BLEND_DST) != 0)
{
*dst = paletteMap[*dst];
}
else
{
*dst = *src;
}
}
src = nextSrc;
dst = nextDst;
}
}
/**
* Copies a sprite onto the buffer. There is no compression used on the sprite
* image.
* rct2: 0x0067A690
* @param imageId Only flags are used.
*/
void FASTCALL gfx_bmp_sprite_to_buffer(
const PaletteMap& paletteMap, uint8_t* source_pointer, uint8_t* dest_pointer, const rct_g1_element* source_image,
rct_drawpixelinfo* dest_dpi, int32_t height, int32_t width, ImageId imageId)
void FASTCALL gfx_bmp_sprite_to_buffer(DrawSpriteArgs& args)
{
auto zoom_level = dest_dpi->zoom_level;
auto dpi = args.DPI;
auto zoom_level = dpi->zoom_level;
if (zoom_level < 0)
{
gfx_bmp_sprite_to_buffer_magnify(
paletteMap, source_pointer, dest_pointer, source_image, dest_dpi, height, width, imageId);
gfx_bmp_sprite_to_buffer_magnify(args);
return;
}
uint8_t zoom_amount = 1 * zoom_level;
uint32_t dest_line_width = (dest_dpi->width / zoom_level) + dest_dpi->pitch;
uint32_t source_line_width = source_image->width * zoom_level;
auto imageId = args.Image;
// Image uses the palette pointer to remap the colours of the image
if (imageId.HasPrimary())
{
// Image with remaps
for (; height > 0; height -= zoom_amount)
{
uint8_t* next_source_pointer = source_pointer + source_line_width;
uint8_t* next_dest_pointer = dest_pointer + dest_line_width;
for (int32_t no_pixels = width; no_pixels > 0;
no_pixels -= zoom_amount, source_pointer += zoom_amount, dest_pointer++)
{
uint8_t pixel = *source_pointer;
pixel = paletteMap[pixel];
if (pixel)
{
*dest_pointer = pixel;
}
}
source_pointer = next_source_pointer;
dest_pointer = next_dest_pointer;
}
return;
// Copy non-transparent bitmap data but re-colour using the palette map.
gfx_bmp_sprite_to_buffer_x<BLEND_TRANSPARENT | BLEND_SRC>(args);
}
// Image is transparent. It only uses source pointer for
// telling if it needs to be drawn not for colour. Colour provided
// by the palette pointer.
if (imageId.IsBlended())
{ // Not tested
for (; height > 0; height -= zoom_amount)
{
uint8_t* next_source_pointer = source_pointer + source_line_width;
uint8_t* next_dest_pointer = dest_pointer + dest_line_width;
for (int32_t no_pixels = width; no_pixels > 0;
no_pixels -= zoom_amount, source_pointer += zoom_amount, dest_pointer++)
{
uint8_t pixel = *source_pointer;
if (pixel)
{
pixel = *dest_pointer;
pixel = paletteMap[pixel];
*dest_pointer = pixel;
}
}
source_pointer = next_source_pointer;
dest_pointer = next_dest_pointer;
}
return;
}
// Basic bitmap no fancy stuff
if (!(source_image->flags & G1_FLAG_BMP))
{ // Not tested
for (; height > 0; height -= zoom_amount)
{
uint8_t* next_source_pointer = source_pointer + source_line_width;
uint8_t* next_dest_pointer = dest_pointer + dest_line_width;
for (int32_t no_pixels = width; no_pixels > 0;
no_pixels -= zoom_amount, dest_pointer++, source_pointer += zoom_amount)
{
*dest_pointer = *source_pointer;
}
dest_pointer = next_dest_pointer;
source_pointer = next_source_pointer;
}
return;
}
// Basic bitmap with no draw pixels
for (; height > 0; height -= zoom_amount)
else if (imageId.IsBlended())
{
uint8_t* next_source_pointer = source_pointer + source_line_width;
uint8_t* next_dest_pointer = dest_pointer + dest_line_width;
for (int32_t no_pixels = width; no_pixels > 0; no_pixels -= zoom_amount, dest_pointer++, source_pointer += zoom_amount)
{
uint8_t pixel = *source_pointer;
if (pixel)
{
*dest_pointer = pixel;
}
}
dest_pointer = next_dest_pointer;
source_pointer = next_source_pointer;
// Image is only a transparency mask. Just colour the pixels using the palette map.
// Used for glass.
gfx_bmp_sprite_to_buffer_x<BLEND_TRANSPARENT | BLEND_DST>(args);
return;
}
else if (!(args.SourceImage.flags & G1_FLAG_BMP))
{
// Copy raw bitmap data to target
gfx_bmp_sprite_to_buffer_x<BLEND_NONE>(args);
}
else
{
// Copy raw bitmap data to target but exclude transparent pixels
gfx_bmp_sprite_to_buffer_x<BLEND_TRANSPARENT>(args);
}
}

View File

@@ -580,7 +580,9 @@ void FASTCALL gfx_draw_sprite_palette_set_software(
{
// Move the pointer to the start point of the source
auto source_pointer = g1->offset + ((static_cast<size_t>(g1->width) * source_start_y) + source_start_x);
gfx_bmp_sprite_to_buffer(paletteMap, source_pointer, dest_pointer, g1, dpi, height, width, imageId);
DrawSpriteArgs args(dpi, imageId, paletteMap, *g1, width, height, source_pointer, dest_pointer);
gfx_bmp_sprite_to_buffer(args);
}
}

View File

@@ -142,6 +142,28 @@ enum : uint32_t
// REMAP_2_PLUS = REMAP 3
};
using DrawBlendOp = uint8_t;
constexpr DrawBlendOp BLEND_NONE = 0;
/**
* Only supported by BITMAP. RLE images always encode transparency via the encoding.
* Pixel value of 0 represents transparent.
*/
constexpr DrawBlendOp BLEND_TRANSPARENT = 1 << 0;
/**
* Whether to use the pixel value from the source image.
* This is usually only unset for glass images where there the src is only a transparency mask.
*/
constexpr DrawBlendOp BLEND_SRC = 1 << 1;
/**
* Whether to use the pixel value of the destination image for blending.
* This is used for any image that filters the target image, e.g. glass or water.
*/
constexpr DrawBlendOp BLEND_DST = 2 << 2;
enum
{
INSET_RECT_FLAG_FILL_GREY = (1 << 2), // 0x04
@@ -492,6 +514,32 @@ public:
void Copy(size_t dstIndex, const PaletteMap& src, size_t srcIndex, size_t length);
};
struct DrawSpriteArgs
{
rct_drawpixelinfo* DPI;
ImageId Image;
const PaletteMap& PalMap;
const rct_g1_element& SourceImage;
int32_t Width;
int32_t Height;
const uint8_t* SourceBits;
uint8_t* DestinationBits;
DrawSpriteArgs(
rct_drawpixelinfo* dpi, ImageId image, const PaletteMap& palMap, const rct_g1_element& sourceImage, int32_t width,
int32_t height, const uint8_t* sourceBits, uint8_t* destinationBits)
: DPI(dpi)
, Image(image)
, PalMap(palMap)
, SourceImage(sourceImage)
, Width(width)
, Height(height)
, SourceBits(sourceBits)
, DestinationBits(destinationBits)
{
}
};
#define SPRITE_ID_PALETTE_COLOUR_1(colourId) (IMAGE_TYPE_REMAP | ((colourId) << 19))
#define SPRITE_ID_PALETTE_COLOUR_2(primaryId, secondaryId) \
(IMAGE_TYPE_REMAP_2_PLUS | IMAGE_TYPE_REMAP | (((primaryId) << 19) | ((secondaryId) << 24)))
@@ -576,9 +624,7 @@ void gfx_object_free_images(uint32_t baseImageId, uint32_t count);
void gfx_object_check_all_images_freed();
size_t ImageListGetUsedCount();
size_t ImageListGetMaximum();
void FASTCALL gfx_bmp_sprite_to_buffer(
const PaletteMap& paletteMap, uint8_t* source_pointer, uint8_t* dest_pointer, const rct_g1_element* source_image,
rct_drawpixelinfo* dest_dpi, int32_t height, int32_t width, ImageId imageId);
void FASTCALL gfx_bmp_sprite_to_buffer(DrawSpriteArgs& args);
void FASTCALL gfx_rle_sprite_to_buffer(
const uint8_t* RESTRICT source_bits_pointer, uint8_t* RESTRICT dest_bits_pointer, const PaletteMap& RESTRICT paletteMap,
const rct_drawpixelinfo* RESTRICT dpi, ImageId imageId, int32_t source_y_start, int32_t height, int32_t source_x_start,