flycast/core/rend/texconv.h

258 lines
6.3 KiB
C++

/*
This file is part of Flycast.
Flycast is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
Flycast is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Flycast. If not, see <https://www.gnu.org/licenses/>.
*/
#pragma once
#include "types.h"
constexpr int VQ_CODEBOOK_SIZE = 256 * 8;
extern const u8 *vq_codebook;
extern u32 palette_index;
extern u32 palette16_ram[1024];
extern u32 palette32_ram[1024];
extern u32 pal_hash_256[4];
extern u32 pal_hash_16[64];
void palette_update();
template<typename Pixel>
class PixelBuffer
{
Pixel* p_buffer_start = nullptr;
Pixel* p_current_mipmap = nullptr;
Pixel* p_current_line = nullptr;
Pixel* p_current_pixel = nullptr;
u32 pixels_per_line = 0;
public:
~PixelBuffer() {
deinit();
}
void init(u32 width, u32 height, bool mipmapped)
{
deinit();
size_t size = width * height * sizeof(Pixel);
if (mipmapped)
{
do
{
width /= 2;
height /= 2;
size += width * height * sizeof(Pixel);
}
while (width != 0 && height != 0);
}
p_buffer_start = p_current_line = p_current_pixel = p_current_mipmap = (Pixel *)malloc(size);
this->pixels_per_line = 1;
}
void init(u32 width, u32 height)
{
deinit();
p_buffer_start = p_current_line = p_current_pixel = p_current_mipmap = (Pixel *)malloc(width * height * sizeof(Pixel));
this->pixels_per_line = width;
}
void deinit()
{
if (p_buffer_start != nullptr)
{
free(p_buffer_start);
p_buffer_start = p_current_mipmap = p_current_line = p_current_pixel = nullptr;
}
}
void steal_data(PixelBuffer &buffer)
{
deinit();
p_buffer_start = p_current_mipmap = p_current_line = p_current_pixel = buffer.p_buffer_start;
pixels_per_line = buffer.pixels_per_line;
buffer.p_buffer_start = buffer.p_current_mipmap = buffer.p_current_line = buffer.p_current_pixel = nullptr;
}
void set_mipmap(int level)
{
u32 offset = 0;
for (int i = 0; i < level; i++)
offset += (1 << (2 * i));
p_current_mipmap = p_current_line = p_current_pixel = p_buffer_start + offset;
pixels_per_line = 1 << level;
}
Pixel *data(u32 x = 0, u32 y = 0)
{
return p_current_mipmap + pixels_per_line * y + x;
}
void prel(u32 x, Pixel value)
{
p_current_pixel[x] = value;
}
void prel(u32 x, u32 y, Pixel value)
{
p_current_pixel[y * pixels_per_line + x] = value;
}
void rmovex(u32 value)
{
p_current_pixel += value;
}
void rmovey(u32 value)
{
p_current_line += pixels_per_line * value;
p_current_pixel = p_current_line;
}
void amove(u32 x_m, u32 y_m)
{
//p_current_pixel=p_buffer_start;
p_current_line = p_current_mipmap + pixels_per_line * y_m;
p_current_pixel = p_current_line + x_m;
}
};
// OpenGL
struct RGBAPacker {
static u32 pack(u8 r, u8 g, u8 b, u8 a) {
return r | (g << 8) | (b << 16) | (a << 24);
}
};
// DirectX
struct BGRAPacker {
static u32 pack(u8 r, u8 g, u8 b, u8 a) {
return b | (g << 8) | (r << 16) | (a << 24);
}
};
template<typename Pixel>
struct UnpackerNop {
using unpacked_type = Pixel;
static Pixel unpack(Pixel word) {
return word;
}
};
// ARGB1555 to RGBA5551
struct Unpacker1555 {
using unpacked_type = u16;
static u16 unpack(u16 word) {
return ((word >> 15) & 1) | (((word >> 10) & 0x1F) << 11) | (((word >> 5) & 0x1F) << 6) | (((word >> 0) & 0x1F) << 1);
}
};
// ARGB4444 to RGBA4444
struct Unpacker4444 {
using unpacked_type = u16;
static u16 unpack(u16 word) {
return (((word >> 0) & 0xF) << 4) | (((word >> 4) & 0xF) << 8) | (((word >> 8) & 0xF) << 12) | (((word >> 12) & 0xF) << 0);
}
};
template <typename Packer>
struct Unpacker1555_32 {
using unpacked_type = u32;
static u32 unpack(u16 word) {
return Packer::pack(
(((word >> 10) & 0x1F) << 3) | ((word >> 12) & 7),
(((word >> 5) & 0x1F) << 3) | ((word >> 7) & 7),
(((word >> 0) & 0x1F) << 3) | ((word >> 2) & 7),
(word & 0x8000) ? 0xFF : 0);
}
};
template <typename Packer>
struct Unpacker565_32 {
using unpacked_type = u32;
static u32 unpack(u16 word) {
return Packer::pack(
(((word >> 11) & 0x1F) << 3) | ((word >> 13) & 7),
(((word >> 5) & 0x3F) << 2) | ((word >> 9) & 3),
(((word >> 0) & 0x1F) << 3) | ((word >> 2) & 7),
0xFF);
}
};
template <typename Packer>
struct Unpacker4444_32 {
using unpacked_type = u32;
static u32 unpack(u16 word) {
return Packer::pack(
(((word >> 8) & 0xF) << 4) | ((word >> 8) & 0xF),
(((word >> 4) & 0xF) << 4) | ((word >> 4) & 0xF),
(((word >> 0) & 0xF) << 4) | ((word >> 0) & 0xF),
(((word >> 12) & 0xF) << 4) | ((word >> 12) & 0xF));
}
};
// ARGB8888 to whatever
template <typename Packer>
struct Unpacker8888 {
using unpacked_type = u32;
static u32 unpack(u32 word) {
return Packer::pack(
(word >> 16) & 0xFF,
(word >> 8) & 0xFF,
(word >> 0) & 0xFF,
(word >> 24) & 0xFF);
}
};
enum class TextureType { _565, _5551, _4444, _8888, _8 };
typedef void (*TexConvFP)(PixelBuffer<u16> *pb, const u8 *p_in, u32 width, u32 height);
typedef void (*TexConvFP8)(PixelBuffer<u8> *pb, const u8 *p_in, u32 width, u32 height);
typedef void (*TexConvFP32)(PixelBuffer<u32> *pb, const u8 *p_in, u32 width, u32 height);
struct PvrTexInfo
{
const char* name;
int bpp; //4/8 for pal. 16 for yuv, rgb, argb
TextureType type;
// Conversion to 16 bpp
TexConvFP TW;
TexConvFP VQ;
// Conversion to 32 bpp
TexConvFP32 PL32;
TexConvFP32 TW32;
TexConvFP32 VQ32;
TexConvFP32 PLVQ32;
// Conversion to 8 bpp (palette)
TexConvFP8 TW8;
};
namespace opengl
{
extern const TexConvFP32 tex1555_TW32;
extern const TexConvFP32 tex1555_VQ32;
extern const TexConvFP32 tex1555_PL32;
extern const TexConvFP32 tex565_TW32;
extern const TexConvFP32 tex565_VQ32;
extern const TexConvFP32 tex565_PL32;
extern const TexConvFP32 tex4444_TW32;
extern const TexConvFP32 tex4444_VQ32;
extern const TexConvFP32 tex4444_PL32;
extern const PvrTexInfo pvrTexInfo[8];
}
namespace directx
{
extern const PvrTexInfo pvrTexInfo[8];
}
extern const PvrTexInfo *pvrTexInfo;