Skip to content

Commit

Permalink
Merge pull request #23322 from ZehMatt/drawing-refactor
Browse files Browse the repository at this point in the history
Refactor some code around the color palette
  • Loading branch information
ZehMatt authored Dec 17, 2024
2 parents a369198 5765bf3 commit 92dac97
Show file tree
Hide file tree
Showing 16 changed files with 130 additions and 163 deletions.
3 changes: 2 additions & 1 deletion src/openrct2-ui/drawing/engines/opengl/TextureCache.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 21,7 @@
#include <vector>

using namespace OpenRCT2::Ui;
using namespace OpenRCT2::Drawing;

constexpr uint32_t kUnusedIndex = 0xFFFFFFFF;

Expand Down Expand Up @@ -206,7 207,7 @@ void TextureCache::CreateTextures()
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
glTexImage2D(
GL_TEXTURE_2D, 0, GL_R8UI, PALETTE_SIZE, PALETTE_SIZE, 0, GL_RED_INTEGER, GL_UNSIGNED_BYTE, blendArray);
GL_TEXTURE_2D, 0, GL_R8UI, kGamePaletteSize, kGamePaletteSize, 0, GL_RED_INTEGER, GL_UNSIGNED_BYTE, blendArray);
}

_initialized = true;
Expand Down
2 changes: 1 addition & 1 deletion src/openrct2/CommandLineSprite.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -214,7 214,7 @@ static bool SpriteImageExport(const G1Element& spriteElement, u8string_view outP
image.Height = dpi.height;
image.Depth = 8;
image.Stride = dpi.LineStride();
image.Palette = std::make_unique<GamePalette>(StandardPalette);
image.Palette = StandardPalette;
image.Pixels = std::vector<uint8_t>(pixels8, pixels8 pixelsLen);
Imaging::WriteToFile(outPath, image, IMAGE_FORMAT::PNG);
return true;
Expand Down
2 changes: 1 addition & 1 deletion src/openrct2/core/Imaging.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -189,7 189,7 @@ namespace OpenRCT2::Imaging

if (image.Depth == 8)
{
if (image.Palette == nullptr)
if (!image.Palette.has_value())
{
throw std::runtime_error("Expected a palette for 8-bit image.");
}
Expand Down
3 changes: 2 additions & 1 deletion src/openrct2/core/Imaging.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 14,7 @@
#include <functional>
#include <istream>
#include <memory>
#include <optional>
#include <string_view>
#include <vector>

Expand All @@ -37,7 38,7 @@ struct Image

// Data
std::vector<uint8_t> Pixels;
std::unique_ptr<GamePalette> Palette;
std::optional<OpenRCT2::Drawing::GamePalette> Palette;
uint32_t Stride{};
};

Expand Down
21 changes: 21 additions & 0 deletions src/openrct2/drawing/ColourPalette.h
Original file line number Diff line number Diff line change
@@ -0,0 1,21 @@
#pragma once

#include <array>
#include <cstdint>

namespace OpenRCT2::Drawing
{

struct PaletteBGRA
{
uint8_t Blue{};
uint8_t Green{};
uint8_t Red{};
uint8_t Alpha{};
};

constexpr auto kGamePaletteSize = 256u;

using GamePalette = std::array<PaletteBGRA, kGamePaletteSize>;

} // namespace OpenRCT2::Drawing
147 changes: 61 additions & 86 deletions src/openrct2/drawing/Drawing.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,78 26,55 @@
#include "../world/Location.hpp"
#include "LightFX.h"

#include <array>
#include <cassert>
#include <cstring>
#include <numeric>

using namespace OpenRCT2;

const PaletteMap& PaletteMap::GetDefault()
{
static bool initialised = false;
static uint8_t data[256];
static PaletteMap defaultMap(data);
if (!initialised)
{
for (size_t i = 0; i < sizeof(data); i )
{
data[i] = static_cast<uint8_t>(i);
}
initialised = true;
}
return defaultMap;
}
static auto _defaultPaletteMapping = []() {
std::array<uint8_t, 256> res;
std::iota(res.begin(), res.end(), 0);
return res;
}();

bool PaletteMap::operator==(const PaletteMap& lhs) const
PaletteMap PaletteMap::GetDefault()
{
return _data == lhs._data && _dataLength == lhs._dataLength && _numMaps == lhs._numMaps && _mapLength == lhs._mapLength;
return PaletteMap(_defaultPaletteMapping);
}

uint8_t& PaletteMap::operator[](size_t index)
{
assert(index < _dataLength);

// Provide safety in release builds
if (index >= _dataLength)
{
static uint8_t dummy;
return dummy;
}

return _data[index];
}

uint8_t PaletteMap::operator[](size_t index) const
{
assert(index < _dataLength);

// Provide safety in release builds
if (index >= _dataLength)
{
return 0;
}

return _data[index];
}

uint8_t PaletteMap::Blend(uint8_t src, uint8_t dst) const
{
#ifdef _DEBUG
// src = 0 would be transparent so there is no blend palette for that, hence (src - 1)
assert(src != 0 && (src - 1) < _numMaps);
assert(dst < _mapLength);
#endif
auto idx = ((src - 1) * 256) dst;
return (*this)[idx];
return _data[idx];
}

void PaletteMap::Copy(size_t dstIndex, const PaletteMap& src, size_t srcIndex, size_t length)
{
auto maxLength = std::min(_mapLength - srcIndex, _mapLength - dstIndex);
auto maxLength = std::min(_data.size() - srcIndex, _data.size() - dstIndex);
assert(length <= maxLength);
auto copyLength = std::min(length, maxLength);
std::memcpy(&_data[dstIndex], &src._data[srcIndex], copyLength);
std::copy(src._data.begin() srcIndex, src._data.begin() srcIndex copyLength, _data.begin() dstIndex);
}

GamePalette gPalette;
uint8_t gGamePalette[256 * 4];
OpenRCT2::Drawing::GamePalette gPalette;
OpenRCT2::Drawing::GamePalette gGamePalette;
uint32_t gPaletteEffectFrame;

ImageId gPickupPeepImage;
Expand Down Expand Up @@ -718,16 695,17 @@ void GfxTransposePalette(int32_t pal, uint8_t product)
{
int32_t width = g1->width;
int32_t x = g1->x_offset;
uint8_t* dest_pointer = &gGamePalette[x * 4];
uint8_t* source_pointer = g1->offset;

for (; width > 0; width--)
{
dest_pointer[0] = (source_pointer[0] * product) >> 8;
dest_pointer[1] = (source_pointer[1] * product) >> 8;
dest_pointer[2] = (source_pointer[2] * product) >> 8;
auto& dest_pointer = gGamePalette[x];
dest_pointer.Blue = (source_pointer[0] * product) >> 8;
dest_pointer.Green = (source_pointer[1] * product) >> 8;
dest_pointer.Red = (source_pointer[2] * product) >> 8;
source_pointer = 3;
dest_pointer = 4;

x ;
}
UpdatePalette(gGamePalette, 10, 236);
}
Expand Down Expand Up @@ -759,14 737,14 @@ void LoadPalette()
int32_t width = g1->width;
int32_t x = g1->x_offset;
uint8_t* src = g1->offset;
uint8_t* dst = &gGamePalette[x * 4];
for (; width > 0; width--)
{
dst[0] = src[0];
dst[1] = src[1];
dst[2] = src[2];
auto& dst = gGamePalette[x];
dst.Blue = src[0];
dst.Green = src[1];
dst.Red = src[2];
src = 3;
dst = 4;
x ;
}
}
UpdatePalette(gGamePalette, 10, 236);
Expand Down Expand Up @@ -911,15 889,14 @@ FilterPaletteID GetGlassPaletteId(colour_t c)
return GlassPaletteIds[c];
}

void UpdatePalette(const uint8_t* colours, int32_t start_index, int32_t num_colours)
void UpdatePalette(std::span<const OpenRCT2::Drawing::PaletteBGRA> palette, int32_t start_index, int32_t num_colours)
{
colours = start_index * 4;

for (int32_t i = start_index; i < num_colours start_index; i )
{
uint8_t r = colours[2];
uint8_t g = colours[1];
uint8_t b = colours[0];
const auto& colour = palette[i];
uint8_t b = colour.Blue;
uint8_t g = colour.Green;
uint8_t r = colour.Red;

if (LightFXIsAvailable())
{
Expand All @@ -936,18 913,17 @@ void UpdatePalette(const uint8_t* colours, int32_t start_index, int32_t num_colo
}
}

gPalette[i].Red = r;
gPalette[i].Green = g;
gPalette[i].Blue = b;
gPalette[i].Green = g;
gPalette[i].Red = r;
gPalette[i].Alpha = 0;
colours = 4;
}

// Fix #1749 and #6535: rainbow path, donut shop and pause button contain black spots that should be white.
gPalette[255].Alpha = 0;
gPalette[255].Red = 255;
gPalette[255].Green = 255;
gPalette[255].Blue = 255;
gPalette[255].Green = 255;
gPalette[255].Red = 255;
gPalette[255].Alpha = 0;

if (!gOpenRCT2Headless)
{
Expand Down Expand Up @@ -990,14 966,15 @@ void UpdatePaletteEffects()
if (g1 != nullptr)
{
int32_t xoffset = g1->x_offset;
xoffset = xoffset * 4;
uint8_t* paletteOffset = gGamePalette xoffset;

for (int32_t i = 0; i < g1->width; i )
{
paletteOffset[(i * 4) 0] = -((0xFF - g1->offset[(i * 3) 0]) / 2) - 1;
paletteOffset[(i * 4) 1] = -((0xFF - g1->offset[(i * 3) 1]) / 2) - 1;
paletteOffset[(i * 4) 2] = -((0xFF - g1->offset[(i * 3) 2]) / 2) - 1;
auto& paletteOffset = gGamePalette[xoffset i];
paletteOffset.Blue = -((0xFF - g1->offset[(i * 3) 0]) / 2) - 1;
paletteOffset.Green = -((0xFF - g1->offset[(i * 3) 1]) / 2) - 1;
paletteOffset.Red = -((0xFF - g1->offset[(i * 3) 2]) / 2) - 1;
}

UpdatePalette(gGamePalette, kPaletteOffsetDynamic, kPaletteLengthDynamic);
}
gClimateLightningFlash ;
Expand All @@ -1018,13 995,13 @@ void UpdatePaletteEffects()
if (g1 != nullptr)
{
int32_t xoffset = g1->x_offset;
xoffset = xoffset * 4;
uint8_t* paletteOffset = gGamePalette xoffset;

for (int32_t i = 0; i < g1->width; i )
{
paletteOffset[(i * 4) 0] = g1->offset[(i * 3) 0];
paletteOffset[(i * 4) 1] = g1->offset[(i * 3) 1];
paletteOffset[(i * 4) 2] = g1->offset[(i * 3) 2];
auto& paletteOffset = gGamePalette[xoffset i];
paletteOffset.Blue = g1->offset[(i * 3) 0];
paletteOffset.Green = g1->offset[(i * 3) 1];
paletteOffset.Red = g1->offset[(i * 3) 2];
}
}
}
Expand Down Expand Up @@ -1054,19 1031,18 @@ void UpdatePaletteEffects()
if (g1 != nullptr)
{
uint8_t* vs = &g1->offset[j * 3];
uint8_t* vd = &gGamePalette[kPaletteOffsetWaterWaves * 4];
int32_t n = kPaletteLengthWaterWaves;
for (int32_t i = 0; i < n; i )
{
vd[0] = vs[0];
vd[1] = vs[1];
vd[2] = vs[2];
auto& vd = gGamePalette[kPaletteOffsetWaterWaves i];
vd.Blue = vs[0];
vd.Green = vs[1];
vd.Red = vs[2];
vs = 9;
if (vs >= &g1->offset[9 * n])
{
vs -= 9 * n;
}
vd = 4;
}
}

Expand All @@ -1075,23 1051,23 @@ void UpdatePaletteEffects()
{
waterId = water_type->palette_index_2;
}

g1 = GfxGetG1Element(shade waterId);
if (g1 != nullptr)
{
uint8_t* vs = &g1->offset[j * 3];
uint8_t* vd = &gGamePalette[kPaletteOffsetWaterSparkles * 4];
int32_t n = kPaletteLengthWaterSparkles;
for (int32_t i = 0; i < n; i )
{
vd[0] = vs[0];
vd[1] = vs[1];
vd[2] = vs[2];
auto& vd = gGamePalette[kPaletteOffsetWaterSparkles];
vd.Blue = vs[0];
vd.Green = vs[1];
vd.Red = vs[2];
vs = 9;
if (vs >= &g1->offset[9 * n])
{
vs -= 9 * n;
}
vd = 4;
}
}

Expand All @@ -1101,19 1077,18 @@ void UpdatePaletteEffects()
if (g1 != nullptr)
{
uint8_t* vs = &g1->offset[j * 3];
uint8_t* vd = &gGamePalette[PALETTE_INDEX_243 * 4];
int32_t n = 3;
for (int32_t i = 0; i < n; i )
{
vd[0] = vs[0];
vd[1] = vs[1];
vd[2] = vs[2];
auto& vd = gGamePalette[PALETTE_INDEX_243 i];
vd.Blue = vs[0];
vd.Green = vs[1];
vd.Red = vs[2];
vs = 3;
if (vs >= &g1->offset[3 * n])
{
vs -= 3 * n;
}
vd = 4;
}
}

Expand Down
Loading

0 comments on commit 92dac97

Please sign in to comment.