246 lines
5.8 KiB
C++
246 lines
5.8 KiB
C++
#ifndef __MDFN_SURFACE_H
|
|
#define __MDFN_SURFACE_H
|
|
|
|
struct MDFN_Rect
|
|
{
|
|
int32 x, y, w, h;
|
|
};
|
|
|
|
enum
|
|
{
|
|
MDFN_COLORSPACE_RGB = 0,
|
|
MDFN_COLORSPACE_YCbCr = 1,
|
|
//MDFN_COLORSPACE_YUV = 2, // TODO, maybe.
|
|
};
|
|
|
|
struct MDFN_PaletteEntry
|
|
{
|
|
uint8 r, g, b;
|
|
};
|
|
|
|
class MDFN_PixelFormat
|
|
{
|
|
public:
|
|
|
|
MDFN_PixelFormat();
|
|
MDFN_PixelFormat(const unsigned int p_colorspace, const uint8 p_rs, const uint8 p_gs, const uint8 p_bs, const uint8 p_as);
|
|
|
|
unsigned int bpp; // 32 only for now(16 and 8 wip)
|
|
unsigned int colorspace;
|
|
|
|
union
|
|
{
|
|
uint8 Rshift; // Bit position of the lowest bit of the red component
|
|
uint8 Yshift;
|
|
};
|
|
|
|
union
|
|
{
|
|
uint8 Gshift; // [...] green component
|
|
uint8 Ushift;
|
|
uint8 Cbshift;
|
|
};
|
|
|
|
union
|
|
{
|
|
uint8 Bshift; // [...] blue component
|
|
uint8 Vshift;
|
|
uint8 Crshift;
|
|
};
|
|
|
|
uint8 Ashift; // [...] alpha component.
|
|
|
|
// For 16bpp, WIP
|
|
uint8 Rprec;
|
|
uint8 Gprec;
|
|
uint8 Bprec;
|
|
uint8 Aprec;
|
|
|
|
// Creates a color value for the surface corresponding to the 8-bit R/G/B/A color passed.
|
|
INLINE uint32 MakeColor(uint8 r, uint8 g, uint8 b, uint8 a = 0) const
|
|
{
|
|
if(colorspace == MDFN_COLORSPACE_YCbCr)
|
|
{
|
|
uint32 y, u, v;
|
|
|
|
y = 16 + ((r * 16842 + g * 33030 + b * 6422) >> 16);
|
|
u = 128 + ((r * -9699 + g * -19071 + b * 28770) >> 16);
|
|
v = 128 + ((r * 28770 + g * -24117 + b * -4653) >> 16);
|
|
|
|
return((y << Yshift) | (u << Ushift) | (v << Vshift) | (a << Ashift));
|
|
}
|
|
else
|
|
{
|
|
if(bpp == 16)
|
|
{
|
|
uint32 ret = 0;
|
|
/*
|
|
ret |= std::min(((r * ((1 << Rprec) - 1) + 127) / 255), 255) << Rshift;
|
|
ret |= std::min(((g * ((1 << Gprec) - 1) + 127) / 255), 255) << Gshift;
|
|
ret |= std::min(((b * ((1 << Bprec) - 1) + 127) / 255), 255) << Bshift;
|
|
ret |= std::min(((a * ((1 << Aprec) - 1) + 127) / 255), 255) << Ashift;
|
|
*/
|
|
ret |= ((r * ((1 << Rprec) - 1) + 127) / 255) << Rshift;
|
|
ret |= ((g * ((1 << Gprec) - 1) + 127) / 255) << Gshift;
|
|
ret |= ((b * ((1 << Bprec) - 1) + 127) / 255) << Bshift;
|
|
ret |= ((a * ((1 << Aprec) - 1) + 127) / 255) << Ashift;
|
|
return(ret);
|
|
}
|
|
else
|
|
return((r << Rshift) | (g << Gshift) | (b << Bshift) | (a << Ashift));
|
|
}
|
|
}
|
|
|
|
INLINE MDFN_PaletteEntry MakePColor(uint8 r, uint8 g, uint8 b) const
|
|
{
|
|
MDFN_PaletteEntry ret;
|
|
|
|
ret.r = ((r * ((1 << Rprec) - 1) + 127) / 255) << Rshift;
|
|
ret.g = ((g * ((1 << Gprec) - 1) + 127) / 255) << Gshift;
|
|
ret.b = ((b * ((1 << Bprec) - 1) + 127) / 255) << Bshift;
|
|
|
|
return ret;
|
|
}
|
|
|
|
INLINE void DecodePColor(const MDFN_PaletteEntry& pe, uint8 &r, uint8 &g, uint8 &b) const
|
|
{
|
|
r = ((pe.r >> Rshift) & ((1 << Rprec) - 1)) * 255 / ((1 << Rprec) - 1);
|
|
g = ((pe.g >> Gshift) & ((1 << Gprec) - 1)) * 255 / ((1 << Gprec) - 1);
|
|
b = ((pe.b >> Bshift) & ((1 << Bprec) - 1)) * 255 / ((1 << Bprec) - 1);
|
|
}
|
|
|
|
// Gets the R/G/B/A values for the passed 32-bit surface pixel value
|
|
INLINE void DecodeColor(uint32 value, int &r, int &g, int &b, int &a) const
|
|
{
|
|
if(colorspace == MDFN_COLORSPACE_YCbCr)
|
|
{
|
|
int32 y = (value >> Yshift) & 0xFF;
|
|
int32 cb = (value >> Cbshift) & 0xFF;
|
|
int32 cr = (value >> Crshift) & 0xFF;
|
|
|
|
int32 r_tmp, g_tmp, b_tmp;
|
|
|
|
r_tmp = g_tmp = b_tmp = 76284 * (y - 16);
|
|
|
|
r_tmp = r_tmp + 104595 * (cr - 128);
|
|
g_tmp = g_tmp - 53281 * (cr - 128) - 25690 * (cb - 128);
|
|
b_tmp = b_tmp + 132186 * (cb - 128);
|
|
|
|
r_tmp >>= 16;
|
|
g_tmp >>= 16;
|
|
b_tmp >>= 16;
|
|
|
|
if(r_tmp < 0) r_tmp = 0;
|
|
if(r_tmp > 255) r_tmp = 255;
|
|
|
|
if(g_tmp < 0) g_tmp = 0;
|
|
if(g_tmp > 255) g_tmp = 255;
|
|
|
|
if(b_tmp < 0) b_tmp = 0;
|
|
if(b_tmp > 255) b_tmp = 255;
|
|
|
|
r = r_tmp;
|
|
g = g_tmp;
|
|
b = b_tmp;
|
|
|
|
a = (value >> Ashift) & 0xFF;
|
|
}
|
|
else
|
|
{
|
|
if(bpp == 16)
|
|
{
|
|
r = ((value >> Rshift) & ((1 << Rprec) - 1)) * 255 / ((1 << Rprec) - 1);
|
|
g = ((value >> Gshift) & ((1 << Gprec) - 1)) * 255 / ((1 << Gprec) - 1);
|
|
b = ((value >> Bshift) & ((1 << Bprec) - 1)) * 255 / ((1 << Bprec) - 1);
|
|
a = ((value >> Ashift) & ((1 << Aprec) - 1)) * 255 / ((1 << Aprec) - 1);
|
|
}
|
|
else
|
|
{
|
|
r = (value >> Rshift) & 0xFF;
|
|
g = (value >> Gshift) & 0xFF;
|
|
b = (value >> Bshift) & 0xFF;
|
|
a = (value >> Ashift) & 0xFF;
|
|
}
|
|
}
|
|
}
|
|
|
|
INLINE void DecodeColor(uint32 value, int &r, int &g, int &b) const
|
|
{
|
|
int dummy_a;
|
|
|
|
DecodeColor(value, r, g, b, dummy_a);
|
|
}
|
|
}; // MDFN_PixelFormat;
|
|
|
|
// Supports 32-bit RGBA
|
|
// 16-bit is WIP
|
|
// 8-bit is even WIPier.
|
|
class MDFN_Surface //typedef struct
|
|
{
|
|
public:
|
|
|
|
MDFN_Surface();
|
|
MDFN_Surface(void *const p_pixels, const uint32 p_width, const uint32 p_height, const uint32 p_pitchinpix, const MDFN_PixelFormat &nf, const bool alloc_init_pixels = true);
|
|
|
|
~MDFN_Surface();
|
|
|
|
uint8 *pixels8;
|
|
uint16 *pixels16;
|
|
uint32 *pixels;
|
|
|
|
template<typename T>
|
|
T* pix(void)
|
|
{
|
|
if(sizeof(T) == 1)
|
|
return (T*)pixels8;
|
|
else if(sizeof(T) == 2)
|
|
return (T*)pixels16;
|
|
else if(sizeof(T) == 4)
|
|
return (T*)pixels;
|
|
else
|
|
return NULL;
|
|
}
|
|
|
|
MDFN_PaletteEntry *palette;
|
|
|
|
bool pixels_is_external;
|
|
|
|
// w, h, and pitch32 should always be > 0
|
|
int32 w;
|
|
int32 h;
|
|
|
|
union
|
|
{
|
|
int32 pitch32; // In pixels, not in bytes.
|
|
int32 pitchinpix; // New name, new code should use this.
|
|
};
|
|
|
|
MDFN_PixelFormat format;
|
|
|
|
void Fill(uint8 r, uint8 g, uint8 b, uint8 a);
|
|
void SetFormat(const MDFN_PixelFormat &new_format, bool convert);
|
|
|
|
// Creates a 32-bit value for the surface corresponding to the R/G/B/A color passed.
|
|
INLINE uint32 MakeColor(uint8 r, uint8 g, uint8 b, uint8 a = 0) const
|
|
{
|
|
return(format.MakeColor(r, g, b, a));
|
|
}
|
|
|
|
// Gets the R/G/B/A values for the passed 32-bit surface pixel value
|
|
INLINE void DecodeColor(uint32 value, int &r, int &g, int &b, int &a) const
|
|
{
|
|
format.DecodeColor(value, r, g, b, a);
|
|
}
|
|
|
|
INLINE void DecodeColor(uint32 value, int &r, int &g, int &b) const
|
|
{
|
|
int dummy_a;
|
|
|
|
DecodeColor(value, r, g, b, dummy_a);
|
|
}
|
|
private:
|
|
void Init(void *const p_pixels, const uint32 p_width, const uint32 p_height, const uint32 p_pitchinpix, const MDFN_PixelFormat &nf, const bool alloc_init_pixels);
|
|
};
|
|
|
|
#endif
|