mirror of
https://github.com/OpenRCT2/OpenRCT2
synced 2025-12-23 15:52:55 +01:00
Refactor paint structs to use ImageId and extend size of image list (#16258)
* Move to image ID for paint struct * Move image list to be past the end of legacy limit * Extend image list size * Introduce constants for image list size * Use std::array to store internal paint struct
This commit is contained in:
@@ -18,6 +18,7 @@
|
||||
#include <mutex>
|
||||
#include <openrct2/common.h>
|
||||
#include <openrct2/drawing/Drawing.h>
|
||||
#include <openrct2/sprites.h>
|
||||
#ifndef __MACOSX__
|
||||
# include <shared_mutex>
|
||||
#endif
|
||||
@@ -202,7 +203,7 @@ private:
|
||||
std::vector<Atlas> _atlases;
|
||||
std::unordered_map<GlyphId, AtlasTextureInfo, GlyphId::Hash, GlyphId::Equal> _glyphTextureMap;
|
||||
std::vector<AtlasTextureInfo> _textureCache;
|
||||
std::array<uint32_t, 0x7FFFF> _indexMap;
|
||||
std::array<uint32_t, SPR_IMAGE_LIST_END> _indexMap;
|
||||
|
||||
GLuint _paletteTexture = 0;
|
||||
|
||||
|
||||
@@ -42,14 +42,14 @@ static void fixup_pointers(std::vector<RecordedPaintSession>& s)
|
||||
auto& quadrants = s[i].Session.Quadrants;
|
||||
for (size_t j = 0; j < entries.size(); j++)
|
||||
{
|
||||
if (entries[j].basic.next_quadrant_ps == reinterpret_cast<paint_struct*>(-1))
|
||||
if (entries[j].AsBasic()->next_quadrant_ps == reinterpret_cast<paint_struct*>(-1))
|
||||
{
|
||||
entries[j].basic.next_quadrant_ps = nullptr;
|
||||
entries[j].AsBasic()->next_quadrant_ps = nullptr;
|
||||
}
|
||||
else
|
||||
{
|
||||
auto nextQuadrantPs = reinterpret_cast<size_t>(entries[j].basic.next_quadrant_ps) / sizeof(paint_entry);
|
||||
entries[j].basic.next_quadrant_ps = &s[i].Entries[nextQuadrantPs].basic;
|
||||
auto nextQuadrantPs = reinterpret_cast<size_t>(entries[j].AsBasic()->next_quadrant_ps) / sizeof(paint_entry);
|
||||
entries[j].AsBasic()->next_quadrant_ps = s[i].Entries[nextQuadrantPs].AsBasic();
|
||||
}
|
||||
}
|
||||
for (size_t j = 0; j < std::size(quadrants); j++)
|
||||
@@ -61,7 +61,7 @@ static void fixup_pointers(std::vector<RecordedPaintSession>& s)
|
||||
else
|
||||
{
|
||||
auto ps = reinterpret_cast<size_t>(quadrants[j]) / sizeof(paint_entry);
|
||||
quadrants[j] = &entries[ps].basic;
|
||||
quadrants[j] = entries[ps].AsBasic();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -164,7 +164,7 @@ static int cmdline_for_bench_sprite_sort(int argc, const char** argv)
|
||||
std::vector<RecordedPaintSession> sessions(1);
|
||||
for (auto& ps : sessions[0].Entries)
|
||||
{
|
||||
ps.basic.next_quadrant_ps = reinterpret_cast<paint_struct*>(-1);
|
||||
ps.AsBasic()->next_quadrant_ps = reinterpret_cast<paint_struct*>(-1);
|
||||
}
|
||||
for (auto& quad : sessions[0].Session.Quadrants)
|
||||
{
|
||||
|
||||
@@ -857,7 +857,7 @@ static void record_session(
|
||||
auto& src = chain->PaintStructs[i];
|
||||
auto& dst = recordedSession.Entries[paintIndex++];
|
||||
dst = src;
|
||||
entryRemap[&src.basic] = reinterpret_cast<paint_struct*>(i * sizeof(paint_entry));
|
||||
entryRemap[src.AsBasic()] = reinterpret_cast<paint_struct*>(i * sizeof(paint_entry));
|
||||
}
|
||||
chain = chain->Next;
|
||||
}
|
||||
@@ -866,7 +866,7 @@ static void record_session(
|
||||
// Remap all entries
|
||||
for (auto& ps : recordedSession.Entries)
|
||||
{
|
||||
auto& ptr = ps.basic.next_quadrant_ps;
|
||||
auto& ptr = ps.AsBasic()->next_quadrant_ps;
|
||||
auto it = entryRemap.find(ptr);
|
||||
if (it == entryRemap.end())
|
||||
{
|
||||
@@ -1662,8 +1662,7 @@ InteractionInfo set_interaction_info_from_paint_session(paint_session* session,
|
||||
while (next_ps != nullptr)
|
||||
{
|
||||
ps = next_ps;
|
||||
auto imageId = ImageId::FromUInt32(ps->image_id, ps->tertiary_colour);
|
||||
if (is_sprite_interacted_with(dpi, imageId, { ps->x, ps->y }))
|
||||
if (is_sprite_interacted_with(dpi, ps->image_id, { ps->x, ps->y }))
|
||||
{
|
||||
if (PSSpriteTypeIsInFilter(ps, filter))
|
||||
{
|
||||
@@ -1675,8 +1674,7 @@ InteractionInfo set_interaction_info_from_paint_session(paint_session* session,
|
||||
|
||||
for (attached_paint_struct* attached_ps = ps->attached_ps; attached_ps != nullptr; attached_ps = attached_ps->next)
|
||||
{
|
||||
auto imageId = ImageId::FromUInt32(attached_ps->image_id, attached_ps->tertiary_colour);
|
||||
if (is_sprite_interacted_with(dpi, imageId, { (attached_ps->x + ps->x), (attached_ps->y + ps->y) }))
|
||||
if (is_sprite_interacted_with(dpi, attached_ps->image_id, { (attached_ps->x + ps->x), (attached_ps->y + ps->y) }))
|
||||
{
|
||||
if (PSSpriteTypeIsInFilter(ps, filter))
|
||||
{
|
||||
|
||||
@@ -25,7 +25,7 @@ struct rct_window;
|
||||
struct EntityBase;
|
||||
struct Guest;
|
||||
struct Staff;
|
||||
union paint_entry;
|
||||
struct paint_entry;
|
||||
|
||||
enum
|
||||
{
|
||||
|
||||
@@ -176,8 +176,7 @@ static paint_struct* CreateNormalPaintStruct(
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
ps->image_id = image_id.ToUInt32();
|
||||
ps->tertiary_colour = image_id.GetTertiary();
|
||||
ps->image_id = image_id;
|
||||
ps->x = imagePos.x;
|
||||
ps->y = imagePos.y;
|
||||
ps->bounds.x_end = rotBoundBoxSize.x + rotBoundBoxOffset.x + session->SpritePosition.x;
|
||||
@@ -502,8 +501,7 @@ static void PaintDrawStruct(paint_session* session, paint_struct* ps)
|
||||
}
|
||||
}
|
||||
|
||||
auto imageId = PaintPSColourifyImage(
|
||||
ImageId::FromUInt32(ps->image_id, ps->tertiary_colour), ps->sprite_type, session->ViewFlags);
|
||||
auto imageId = PaintPSColourifyImage(ps->image_id, ps->sprite_type, session->ViewFlags);
|
||||
if (gPaintBoundingBoxes && dpi->zoom_level == ZoomLevel{ 0 })
|
||||
{
|
||||
PaintPSImageWithBoundingBoxes(dpi, ps, imageId, x, y);
|
||||
@@ -551,11 +549,10 @@ static void PaintAttachedPS(rct_drawpixelinfo* dpi, paint_struct* ps, uint32_t v
|
||||
{
|
||||
auto screenCoords = ScreenCoordsXY{ attached_ps->x + ps->x, attached_ps->y + ps->y };
|
||||
|
||||
auto imageId = PaintPSColourifyImage(
|
||||
ImageId::FromUInt32(attached_ps->image_id, ps->tertiary_colour), ps->sprite_type, viewFlags);
|
||||
auto imageId = PaintPSColourifyImage(attached_ps->image_id, ps->sprite_type, viewFlags);
|
||||
if (attached_ps->flags & PAINT_STRUCT_FLAG_IS_MASKED)
|
||||
{
|
||||
gfx_draw_sprite_raw_masked(dpi, screenCoords, imageId, ImageId::FromUInt32(attached_ps->colour_image_id));
|
||||
gfx_draw_sprite_raw_masked(dpi, screenCoords, imageId, attached_ps->colour_image_id);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -654,7 +651,7 @@ static void PaintPSImage(rct_drawpixelinfo* dpi, paint_struct* ps, ImageId image
|
||||
{
|
||||
if (ps->flags & PAINT_STRUCT_FLAG_IS_MASKED)
|
||||
{
|
||||
return gfx_draw_sprite_raw_masked(dpi, { x, y }, imageId, ImageId::FromUInt32(ps->colour_image_id));
|
||||
return gfx_draw_sprite_raw_masked(dpi, { x, y }, imageId, ps->colour_image_id);
|
||||
}
|
||||
|
||||
gfx_draw_sprite(dpi, imageId, { x, y });
|
||||
@@ -882,8 +879,7 @@ bool PaintAttachToPreviousAttach(paint_session* session, ImageId imageId, int32_
|
||||
return false;
|
||||
}
|
||||
|
||||
ps->image_id = imageId.ToUInt32();
|
||||
ps->tertiary_colour = imageId.GetTertiary();
|
||||
ps->image_id = imageId;
|
||||
ps->x = x;
|
||||
ps->y = y;
|
||||
ps->flags = 0;
|
||||
@@ -921,8 +917,7 @@ bool PaintAttachToPreviousPS(paint_session* session, ImageId image_id, int32_t x
|
||||
return false;
|
||||
}
|
||||
|
||||
ps->image_id = image_id.ToUInt32();
|
||||
ps->tertiary_colour = image_id.GetTertiary();
|
||||
ps->image_id = image_id;
|
||||
ps->x = x;
|
||||
ps->y = y;
|
||||
ps->flags = 0;
|
||||
|
||||
@@ -26,13 +26,8 @@ enum class ViewportInteractionItem : uint8_t;
|
||||
struct attached_paint_struct
|
||||
{
|
||||
attached_paint_struct* next;
|
||||
uint32_t image_id;
|
||||
union
|
||||
{
|
||||
uint32_t tertiary_colour;
|
||||
// If masked image_id is masked_id
|
||||
uint32_t colour_image_id;
|
||||
};
|
||||
ImageId image_id;
|
||||
ImageId colour_image_id;
|
||||
int32_t x;
|
||||
int32_t y;
|
||||
uint8_t flags;
|
||||
@@ -55,13 +50,8 @@ struct paint_struct
|
||||
paint_struct* children;
|
||||
paint_struct* next_quadrant_ps;
|
||||
TileElement* tileElement;
|
||||
uint32_t image_id;
|
||||
union
|
||||
{
|
||||
uint32_t tertiary_colour;
|
||||
// If masked image_id is masked_id
|
||||
uint32_t colour_image_id;
|
||||
};
|
||||
ImageId image_id;
|
||||
ImageId colour_image_id;
|
||||
int32_t x;
|
||||
int32_t y;
|
||||
int32_t map_x;
|
||||
@@ -82,12 +72,34 @@ struct paint_string_struct
|
||||
uint8_t* y_offsets;
|
||||
};
|
||||
|
||||
union paint_entry
|
||||
struct paint_entry
|
||||
{
|
||||
paint_struct basic;
|
||||
attached_paint_struct attached;
|
||||
paint_string_struct string;
|
||||
private:
|
||||
std::array<uint8_t, std::max({ sizeof(paint_struct), sizeof(attached_paint_struct), sizeof(paint_string_struct) })> data;
|
||||
|
||||
public:
|
||||
paint_struct* AsBasic()
|
||||
{
|
||||
auto* res = reinterpret_cast<paint_struct*>(data.data());
|
||||
::new (res) paint_struct();
|
||||
return res;
|
||||
}
|
||||
attached_paint_struct* AsAttached()
|
||||
{
|
||||
auto* res = reinterpret_cast<attached_paint_struct*>(data.data());
|
||||
::new (res) attached_paint_struct();
|
||||
return res;
|
||||
}
|
||||
paint_string_struct* AsString()
|
||||
{
|
||||
auto* res = reinterpret_cast<paint_string_struct*>(data.data());
|
||||
::new (res) paint_string_struct();
|
||||
return res;
|
||||
}
|
||||
};
|
||||
static_assert(sizeof(paint_entry) >= sizeof(paint_struct));
|
||||
static_assert(sizeof(paint_entry) >= sizeof(attached_paint_struct));
|
||||
static_assert(sizeof(paint_entry) >= sizeof(paint_string_struct));
|
||||
|
||||
struct sprite_bb
|
||||
{
|
||||
@@ -214,7 +226,7 @@ struct paint_session : public PaintSessionCore
|
||||
auto* entry = PaintEntryChain.Allocate();
|
||||
if (entry != nullptr)
|
||||
{
|
||||
LastPS = &entry->basic;
|
||||
LastPS = entry->AsBasic();
|
||||
return LastPS;
|
||||
}
|
||||
return nullptr;
|
||||
@@ -225,7 +237,7 @@ struct paint_session : public PaintSessionCore
|
||||
auto* entry = PaintEntryChain.Allocate();
|
||||
if (entry != nullptr)
|
||||
{
|
||||
LastAttachedPS = &entry->attached;
|
||||
LastAttachedPS = entry->AsAttached();
|
||||
return LastAttachedPS;
|
||||
}
|
||||
return nullptr;
|
||||
@@ -236,7 +248,7 @@ struct paint_session : public PaintSessionCore
|
||||
auto* entry = PaintEntryChain.Allocate();
|
||||
if (entry != nullptr)
|
||||
{
|
||||
auto* string = &entry->string;
|
||||
auto* string = entry->AsString();
|
||||
if (LastPSString == nullptr)
|
||||
{
|
||||
PSStringHead = string;
|
||||
|
||||
@@ -529,7 +529,7 @@ static void viewport_surface_smoothen_edge(
|
||||
{
|
||||
attached_paint_struct* out = session->LastAttachedPS;
|
||||
// set content and enable masking
|
||||
out->colour_image_id = get_surface_pattern(neighbour.terrain, cl).ToUInt32();
|
||||
out->colour_image_id = get_surface_pattern(neighbour.terrain, cl);
|
||||
out->flags |= PAINT_STRUCT_FLAG_IS_MASKED;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -336,7 +336,7 @@ static void sub_68B3FB(paint_session* session, int32_t x, int32_t y)
|
||||
if (ps != nullptr)
|
||||
{
|
||||
ps->flags &= PAINT_STRUCT_FLAG_IS_MASKED;
|
||||
ps->colour_image_id = COLOUR_BORDEAUX_RED;
|
||||
ps->image_id = ps->image_id.WithTertiary(COLOUR_BORDEAUX_RED);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1118,6 +1118,7 @@ enum
|
||||
SPR_SCROLLING_TEXT_START = SPR_CSG_END,
|
||||
SPR_SCROLLING_TEXT_END = SPR_SCROLLING_TEXT_START + OpenRCT2::MaxScrollingTextEntries,
|
||||
|
||||
SPR_IMAGE_LIST_LENGTH = 1000000,
|
||||
SPR_IMAGE_LIST_BEGIN = SPR_SCROLLING_TEXT_END,
|
||||
SPR_IMAGE_LIST_END = 0x7FFFE
|
||||
SPR_IMAGE_LIST_END = SPR_IMAGE_LIST_BEGIN + SPR_IMAGE_LIST_LENGTH,
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user