2024-11-20 21:26:35 -05:00
|
|
|
#pragma once
|
|
|
|
|
|
|
|
#include <cstdint>
|
2024-11-23 10:55:52 -05:00
|
|
|
#include <cstring>
|
|
|
|
#include <memory>
|
2024-11-20 21:26:35 -05:00
|
|
|
|
|
|
|
// common types
|
|
|
|
using u8 = std::uint8_t;
|
|
|
|
using i8 = std::int8_t;
|
|
|
|
using u16 = std::uint16_t;
|
|
|
|
using i16 = std::int16_t;
|
|
|
|
using u32 = std::uint32_t;
|
|
|
|
using i32 = std::int32_t;
|
|
|
|
using u64 = std::uint64_t;
|
|
|
|
using i64 = std::int64_t;
|
|
|
|
using usize = std::size_t;
|
|
|
|
using f32 = float;
|
|
|
|
using f64 = double;
|
|
|
|
|
2024-11-23 10:55:52 -05:00
|
|
|
struct tSize {
|
|
|
|
u32 width;
|
|
|
|
u32 height;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct tRect {
|
|
|
|
u32 x;
|
|
|
|
u32 y;
|
|
|
|
u32 width;
|
|
|
|
u32 height;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct cSurface {
|
|
|
|
private:
|
|
|
|
u32* pBuffer;
|
|
|
|
tSize size;
|
|
|
|
u32 stride;
|
|
|
|
bool owned { false };
|
|
|
|
|
|
|
|
struct OwnedTag {};
|
|
|
|
|
|
|
|
public:
|
|
|
|
cSurface(u32* pBuffer, const tSize& size, u32 stride = -1) {
|
|
|
|
if(stride == -1) {
|
|
|
|
this->stride = size.width;
|
|
|
|
} else {
|
|
|
|
this->stride = stride;
|
|
|
|
}
|
|
|
|
|
|
|
|
this->size = size;
|
|
|
|
this->pBuffer = pBuffer;
|
|
|
|
this->owned = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
cSurface(u32* pBuffer, const tSize& size, OwnedTag) {
|
|
|
|
this->pBuffer = pBuffer;
|
|
|
|
this->size = size;
|
|
|
|
owned = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
~cSurface() {
|
|
|
|
if(owned) {
|
|
|
|
delete[] pBuffer;
|
|
|
|
this->pBuffer = nullptr;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
cSurface(const cSurface&) = delete;
|
|
|
|
cSurface(cSurface&& move) {
|
|
|
|
this->pBuffer = move.pBuffer;
|
|
|
|
move.pBuffer = nullptr;
|
|
|
|
this->size = {};
|
|
|
|
this->stride = -1;
|
|
|
|
this->owned = move.owned;
|
|
|
|
move.owned = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
u32 Stride() const { return stride; }
|
|
|
|
u32 StrideBytes() const { return stride * sizeof(u32); }
|
|
|
|
|
|
|
|
const tSize& Size() const { return size; }
|
|
|
|
|
|
|
|
u32* Memory() { return &this->pBuffer[0]; }
|
|
|
|
|
|
|
|
// creates a new owned cSurface which owns this memory
|
|
|
|
std::unique_ptr<cSurface> ClonePiece(const tRect& rect) {
|
|
|
|
auto* pSurfaceMemory = new u32[rect.width * rect.height * sizeof(u32)];
|
|
|
|
|
|
|
|
for(u32 y = 0; y < rect.height; ++y) {
|
|
|
|
auto* pTileLineStart = &pBuffer[(rect.y + y) * this->stride + rect.x];
|
|
|
|
memcpy(&pSurfaceMemory[y * rect.width], pTileLineStart, rect.width * sizeof(u32));
|
|
|
|
}
|
|
|
|
|
|
|
|
return std::unique_ptr<cSurface>(new cSurface(pSurfaceMemory, { rect.width, rect.height }, OwnedTag {}));
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2024-11-20 21:26:35 -05:00
|
|
|
/// like vector<T> but doesn't grow on its own
|
2024-11-20 21:29:22 -05:00
|
|
|
template <class T>
|
2024-11-20 21:26:35 -05:00
|
|
|
struct unique_buffer {
|
|
|
|
T* m_buffer;
|
|
|
|
size_t size;
|
2024-11-20 21:29:22 -05:00
|
|
|
|
|
|
|
public:
|
2024-11-20 21:26:35 -05:00
|
|
|
unique_buffer() {
|
|
|
|
m_buffer = nullptr;
|
|
|
|
size = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
// forbid copying or movement for now
|
|
|
|
unique_buffer(const unique_buffer&) = delete;
|
|
|
|
unique_buffer(unique_buffer&&) = delete;
|
|
|
|
|
2024-11-20 21:29:22 -05:00
|
|
|
~unique_buffer() { resize(0); }
|
2024-11-20 21:26:35 -05:00
|
|
|
|
|
|
|
size_t get_size() const { return this->size; }
|
|
|
|
|
|
|
|
void resize(size_t new_size) {
|
2024-11-20 21:29:22 -05:00
|
|
|
if(m_buffer) {
|
2024-11-20 21:26:35 -05:00
|
|
|
delete[] m_buffer;
|
|
|
|
m_buffer = nullptr;
|
|
|
|
size = 0;
|
|
|
|
}
|
|
|
|
|
2024-11-20 21:29:22 -05:00
|
|
|
if(new_size) {
|
2024-11-20 21:26:35 -05:00
|
|
|
m_buffer = new T[new_size];
|
|
|
|
size = new_size;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
T* data() { return &m_buffer[0]; }
|
|
|
|
|
|
|
|
const T* data() const { return &m_buffer[0]; }
|
|
|
|
};
|