1 /******************************************************************************/ 2 /* Mednafen - Multi-system Emulator */ 3 /******************************************************************************/ 4 /* surface.h: 5 ** Copyright (C) 2009-2016 Mednafen Team 6 ** 7 ** This program is free software; you can redistribute it and/or 8 ** modify it under the terms of the GNU General Public License 9 ** as published by the Free Software Foundation; either version 2 10 ** of the License, or (at your option) any later version. 11 ** 12 ** This program is distributed in the hope that it will be useful, 13 ** but WITHOUT ANY WARRANTY; without even the implied warranty of 14 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 ** GNU General Public License for more details. 16 ** 17 ** You should have received a copy of the GNU General Public License 18 ** along with this program; if not, write to the Free Software Foundation, Inc., 19 ** 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 20 */ 21 22 #ifndef __MDFN_SURFACE_H 23 #define __MDFN_SURFACE_H 24 25 namespace Mednafen 26 { 27 28 struct MDFN_Rect 29 { 30 int32 x, y, w, h; 31 }; 32 33 enum 34 { 35 MDFN_COLORSPACE_RGB = 0, 36 MDFN_COLORSPACE_YCbCr = 1 37 }; 38 39 struct MDFN_PaletteEntry 40 { 41 uint8 r, g, b; 42 }; 43 44 class MDFN_PixelFormat 45 { 46 public: 47 48 MDFN_PixelFormat(); 49 MDFN_PixelFormat(const unsigned int p_colorspace, const uint8 p_rs, const uint8 p_gs, const uint8 p_bs, const uint8 p_as); 50 51 bool operator==(const MDFN_PixelFormat& a) 52 { 53 return 54 bpp == a.bpp && 55 colorspace == a.colorspace && 56 Rshift == a.Rshift && 57 Gshift == a.Gshift && 58 Bshift == a.Bshift && 59 Ashift == a.Ashift && 60 Rprec == a.Rprec && 61 Gprec == a.Gprec && 62 Bprec == a.Bprec && 63 Aprec == a.Aprec; 64 } 65 66 bool operator!=(const MDFN_PixelFormat& a) 67 { 68 return !(*this == a); 69 } 70 71 unsigned int bpp; // 32 only for now(16 and 8 wip) 72 unsigned int colorspace; 73 74 union 75 { 76 uint8 Rshift; // Bit position of the lowest bit of the red component 77 uint8 Yshift; 78 }; 79 80 union 81 { 82 uint8 Gshift; // [...] green component 83 uint8 Cbshift; 84 }; 85 86 union 87 { 88 uint8 Bshift; // [...] blue component 89 uint8 Crshift; 90 }; 91 92 uint8 Ashift; // [...] alpha component. 93 94 // For 16bpp, WIP 95 uint8 Rprec; 96 uint8 Gprec; 97 uint8 Bprec; 98 uint8 Aprec; 99 100 // Creates a color value for the surface corresponding to the 8-bit R/G/B/A color passed. 101 INLINE uint32 MakeColor(uint8 r, uint8 g, uint8 b, uint8 a = 0) const 102 { 103 if(colorspace == MDFN_COLORSPACE_YCbCr) 104 { 105 uint32 y, u, v; 106 107 y = 16 + ((r * 16842 + g * 33030 + b * 6422) >> 16); 108 u = 128 + ((r * -9699 + g * -19071 + b * 28770) >> 16); 109 v = 128 + ((r * 28770 + g * -24117 + b * -4653) >> 16); 110 111 return((y << Yshift) | (u << Cbshift) | (v << Crshift) | (a << Ashift)); 112 } 113 else 114 { 115 if(bpp == 16) 116 { 117 uint32 ret = 0; 118 /* 119 ret |= std::min(((r * ((1 << Rprec) - 1) + 127) / 255), 255) << Rshift; 120 ret |= std::min(((g * ((1 << Gprec) - 1) + 127) / 255), 255) << Gshift; 121 ret |= std::min(((b * ((1 << Bprec) - 1) + 127) / 255), 255) << Bshift; 122 ret |= std::min(((a * ((1 << Aprec) - 1) + 127) / 255), 255) << Ashift; 123 */ 124 ret |= ((r * ((1 << Rprec) - 1) + 127) / 255) << Rshift; 125 ret |= ((g * ((1 << Gprec) - 1) + 127) / 255) << Gshift; 126 ret |= ((b * ((1 << Bprec) - 1) + 127) / 255) << Bshift; 127 ret |= ((a * ((1 << Aprec) - 1) + 127) / 255) << Ashift; 128 return(ret); 129 } 130 else 131 return((r << Rshift) | (g << Gshift) | (b << Bshift) | (a << Ashift)); 132 } 133 } 134 MakePColor(uint8 r,uint8 g,uint8 b)135 INLINE MDFN_PaletteEntry MakePColor(uint8 r, uint8 g, uint8 b) const 136 { 137 MDFN_PaletteEntry ret; 138 139 ret.r = ((r * ((1 << Rprec) - 1) + 127) / 255) << Rshift; 140 ret.g = ((g * ((1 << Gprec) - 1) + 127) / 255) << Gshift; 141 ret.b = ((b * ((1 << Bprec) - 1) + 127) / 255) << Bshift; 142 143 return ret; 144 } 145 DecodePColor(const MDFN_PaletteEntry & pe,uint8 & r,uint8 & g,uint8 & b)146 INLINE void DecodePColor(const MDFN_PaletteEntry& pe, uint8 &r, uint8 &g, uint8 &b) const 147 { 148 r = ((pe.r >> Rshift) & ((1 << Rprec) - 1)) * 255 / ((1 << Rprec) - 1); 149 g = ((pe.g >> Gshift) & ((1 << Gprec) - 1)) * 255 / ((1 << Gprec) - 1); 150 b = ((pe.b >> Bshift) & ((1 << Bprec) - 1)) * 255 / ((1 << Bprec) - 1); 151 } 152 153 // Gets the R/G/B/A values for the passed 32-bit surface pixel value DecodeColor(uint32 value,int & r,int & g,int & b,int & a)154 INLINE void DecodeColor(uint32 value, int &r, int &g, int &b, int &a) const 155 { 156 if(colorspace == MDFN_COLORSPACE_YCbCr) 157 { 158 int32 y = (value >> Yshift) & 0xFF; 159 int32 cb = (value >> Cbshift) & 0xFF; 160 int32 cr = (value >> Crshift) & 0xFF; 161 162 int32 r_tmp, g_tmp, b_tmp; 163 164 r_tmp = g_tmp = b_tmp = 76284 * (y - 16); 165 166 r_tmp = r_tmp + 104595 * (cr - 128); 167 g_tmp = g_tmp - 53281 * (cr - 128) - 25690 * (cb - 128); 168 b_tmp = b_tmp + 132186 * (cb - 128); 169 170 r_tmp >>= 16; 171 g_tmp >>= 16; 172 b_tmp >>= 16; 173 174 if(r_tmp < 0) r_tmp = 0; 175 if(r_tmp > 255) r_tmp = 255; 176 177 if(g_tmp < 0) g_tmp = 0; 178 if(g_tmp > 255) g_tmp = 255; 179 180 if(b_tmp < 0) b_tmp = 0; 181 if(b_tmp > 255) b_tmp = 255; 182 183 r = r_tmp; 184 g = g_tmp; 185 b = b_tmp; 186 187 a = (value >> Ashift) & 0xFF; 188 } 189 else 190 { 191 if(bpp == 16) 192 { 193 r = ((value >> Rshift) & ((1 << Rprec) - 1)) * 255 / ((1 << Rprec) - 1); 194 g = ((value >> Gshift) & ((1 << Gprec) - 1)) * 255 / ((1 << Gprec) - 1); 195 b = ((value >> Bshift) & ((1 << Bprec) - 1)) * 255 / ((1 << Bprec) - 1); 196 a = ((value >> Ashift) & ((1 << Aprec) - 1)) * 255 / ((1 << Aprec) - 1); 197 } 198 else 199 { 200 r = (value >> Rshift) & 0xFF; 201 g = (value >> Gshift) & 0xFF; 202 b = (value >> Bshift) & 0xFF; 203 a = (value >> Ashift) & 0xFF; 204 } 205 } 206 } 207 DecodeColor(uint32 value,int & r,int & g,int & b)208 INLINE void DecodeColor(uint32 value, int &r, int &g, int &b) const 209 { 210 int dummy_a; 211 212 DecodeColor(value, r, g, b, dummy_a); 213 } 214 }; // MDFN_PixelFormat; 215 216 // Supports 32-bit RGBA 217 // 16-bit is WIP 218 // 8-bit is even WIPier. 219 class MDFN_Surface //typedef struct 220 { 221 public: 222 223 MDFN_Surface(); 224 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); 225 226 ~MDFN_Surface(); 227 228 uint8* pixels8; 229 uint16* pixels16; 230 uint32* pixels; 231 232 private: pix_(uint8 * & z)233 INLINE void pix_(uint8*& z) const { z = pixels8; } pix_(uint16 * & z)234 INLINE void pix_(uint16*& z) const { z = pixels16; } pix_(uint32 * & z)235 INLINE void pix_(uint32*& z) const { z = pixels; } 236 public: 237 238 template<typename T> pix(void)239 INLINE const T* pix(void) const 240 { 241 T* ret; 242 pix_(ret); 243 return (const T*)ret; 244 } 245 246 template<typename T> pix(void)247 INLINE T* pix(void) 248 { 249 T* ret; 250 pix_(ret); 251 return ret; 252 } 253 254 MDFN_PaletteEntry *palette; 255 256 bool pixels_is_external; 257 258 // w, h, and pitch32 should always be > 0 259 int32 w; 260 int32 h; 261 262 union 263 { 264 int32 pitch32; // In pixels, not in bytes. 265 int32 pitchinpix; // New name, new code should use this. 266 }; 267 268 MDFN_PixelFormat format; 269 270 void Fill(uint8 r, uint8 g, uint8 b, uint8 a); 271 //void FillOutside( 272 void SetFormat(const MDFN_PixelFormat &new_format, bool convert); 273 274 // Creates a 32-bit value for the surface corresponding to the R/G/B/A color passed. 275 INLINE uint32 MakeColor(uint8 r, uint8 g, uint8 b, uint8 a = 0) const 276 { 277 return(format.MakeColor(r, g, b, a)); 278 } 279 280 // Gets the R/G/B/A values for the passed 32-bit surface pixel value DecodeColor(uint32 value,int & r,int & g,int & b,int & a)281 INLINE void DecodeColor(uint32 value, int &r, int &g, int &b, int &a) const 282 { 283 format.DecodeColor(value, r, g, b, a); 284 } 285 DecodeColor(uint32 value,int & r,int & g,int & b)286 INLINE void DecodeColor(uint32 value, int &r, int &g, int &b) const 287 { 288 int dummy_a; 289 290 DecodeColor(value, r, g, b, dummy_a); 291 } 292 private: 293 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); 294 }; 295 296 } 297 #endif 298