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