1 /* ScummVM - Graphic Adventure Engine
2  *
3  * ScummVM is the legal property of its developers, whose names
4  * are too numerous to list here. Please refer to the COPYRIGHT
5  * file distributed with this source distribution.
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
19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20  *
21  */
22 
23 #ifndef GRAPHICS_COLORMASKS_H
24 #define GRAPHICS_COLORMASKS_H
25 
26 #include "graphics/pixelformat.h"
27 
28 namespace Graphics {
29 
30 template<int bitFormat>
31 struct ColorMasks {
32 };
33 
34 /*
35 The ColorMasks template can be used to map bit format values
36 (like 555, 565, 1555, 4444) to corresponding bit masks and shift values.
37 Currently this is only meant for
38 
39 The meaning of these is masks is the following:
40  kBytesPerPixel
41     -> how many bytes per pixel for that format
42 
43  kRedMask, kGreenMask, kBlueMask
44     -> bitmask, and this with the color to select only the bits of the corresponding color
45 
46  The k*Bits and k*Shift values can be used to extract R,G,B. I.e. to get
47  the red color component of a pixel, as a 8-bit value, you would write
48 
49  R = ((color & kRedMask) >> kRedShift) << (8-kRedBits)
50 
51  Actually, instead of the simple left shift, one might want to use somewhat
52  more sophisticated code (which fills up the least significant bits with
53  appropriate data).
54 
55 
56  The kHighBitsMask / kLowBitsMask / qhighBits / qlowBits are special values that are
57  used in the super-optimized interpolation functions in scaler/intern.h
58  and scaler/aspect.cpp. Currently they are only available in 555 and 565 mode.
59  To be specific: They pack the masks for two 16 bit pixels at once. The pixels
60  are split into "high" and "low" bits, which are then separately interpolated
61  and finally re-composed. That way, 2x2 pixels or even 4x2 pixels can
62  be interpolated in one go. They are also included in 888 and 8888 to make
63  the same functions compatible when interpolating 2 32-bit pixels.
64 */
65 
66 
67 template<>
68 struct ColorMasks<565> {
69 	enum {
70 		kHighBitsMask    = 0xF7DEF7DE,
71 		kLowBitsMask     = 0x08210821,
72 		qhighBits   = 0xE79CE79C,
73 		qlowBits    = 0x18631863,
74 
75 
76 		kBytesPerPixel = 2,
77 
78 		kAlphaBits  = 0,
79 		kRedBits    = 5,
80 		kGreenBits  = 6,
81 		kBlueBits   = 5,
82 
83 		kAlphaShift = 0,
84 		kRedShift   = kGreenBits+kBlueBits,
85 		kGreenShift = kBlueBits,
86 		kBlueShift  = 0,
87 
88 		kAlphaMask  = ((1 << kAlphaBits) - 1) << kAlphaShift,
89 		kRedMask    = ((1 << kRedBits) - 1) << kRedShift,
90 		kGreenMask  = ((1 << kGreenBits) - 1) << kGreenShift,
91 		kBlueMask   = ((1 << kBlueBits) - 1) << kBlueShift,
92 
93 		kRedBlueMask = kRedMask | kBlueMask,
94 
95 		kLowBits    = (1 << kRedShift) | (1 << kGreenShift) | (1 << kBlueShift),
96 		kLow2Bits   = (3 << kRedShift) | (3 << kGreenShift) | (3 << kBlueShift),
97 		kLow3Bits   = (7 << kRedShift) | (7 << kGreenShift) | (7 << kBlueShift)
98 	};
99 
100 	typedef uint16 PixelType;
101 };
102 
103 template<>
104 struct ColorMasks<555> {
105 	enum {
106 		kHighBitsMask    = 0x7BDE7BDE,
107 		kLowBitsMask     = 0x04210421,
108 		qhighBits   = 0x739C739C,
109 		qlowBits    = 0x0C630C63,
110 
111 
112 		kBytesPerPixel = 2,
113 
114 		kAlphaBits  = 0,
115 		kRedBits    = 5,
116 		kGreenBits  = 5,
117 		kBlueBits   = 5,
118 
119 #ifdef __N64__
120 		/* Nintendo 64 uses a BGR555 color format for 16bit display */
121 		kAlphaShift = 0,
122 		kRedShift   = kBlueBits+kGreenBits+1,
123 		kGreenShift = kBlueBits + 1,
124 		kBlueShift  = 1,
125 #else   /* RGB555 */
126 		kAlphaShift = 0,
127 		kRedShift   = kGreenBits+kBlueBits,
128 		kGreenShift = kBlueBits,
129 		kBlueShift  = 0,
130 #endif
131 
132 		kAlphaMask = ((1 << kAlphaBits) - 1) << kAlphaShift,
133 		kRedMask   = ((1 << kRedBits) - 1) << kRedShift,
134 		kGreenMask = ((1 << kGreenBits) - 1) << kGreenShift,
135 		kBlueMask  = ((1 << kBlueBits) - 1) << kBlueShift,
136 
137 		kRedBlueMask = kRedMask | kBlueMask,
138 
139 		kLowBits    = (1 << kRedShift) | (1 << kGreenShift) | (1 << kBlueShift),
140 		kLow2Bits   = (3 << kRedShift) | (3 << kGreenShift) | (3 << kBlueShift),
141 		kLow3Bits   = (7 << kRedShift) | (7 << kGreenShift) | (7 << kBlueShift)
142 	};
143 
144 	typedef uint16 PixelType;
145 };
146 
147 template<>
148 struct ColorMasks<1555> {
149 	enum {
150 		kBytesPerPixel = 2,
151 
152 		kAlphaBits  = 1,
153 		kRedBits    = 5,
154 		kGreenBits  = 5,
155 		kBlueBits   = 5,
156 
157 		kAlphaShift = kRedBits+kGreenBits+kBlueBits,
158 		kRedShift   = 0,
159 		kGreenShift = kBlueBits,
160 		kBlueShift  = kGreenBits+kBlueBits,
161 
162 		kAlphaMask = ((1 << kAlphaBits) - 1) << kAlphaShift,
163 		kRedMask   = ((1 << kRedBits) - 1) << kRedShift,
164 		kGreenMask = ((1 << kGreenBits) - 1) << kGreenShift,
165 		kBlueMask  = ((1 << kBlueBits) - 1) << kBlueShift,
166 
167 		kRedBlueMask = kRedMask | kBlueMask
168 	};
169 
170 	typedef uint16 PixelType;
171 };
172 
173 template<>
174 struct ColorMasks<5551> {
175 	enum {
176 		kBytesPerPixel = 2,
177 
178 		kAlphaBits  = 1,
179 		kRedBits    = 5,
180 		kGreenBits  = 5,
181 		kBlueBits   = 5,
182 
183 		kAlphaShift = 0,
184 		kRedShift   = kGreenBits+kBlueBits+kAlphaBits,
185 		kGreenShift = kBlueBits+kAlphaBits,
186 		kBlueShift  = kAlphaBits,
187 
188 		kAlphaMask = ((1 << kAlphaBits) - 1) << kAlphaShift,
189 		kRedMask   = ((1 << kRedBits) - 1) << kRedShift,
190 		kGreenMask = ((1 << kGreenBits) - 1) << kGreenShift,
191 		kBlueMask  = ((1 << kBlueBits) - 1) << kBlueShift,
192 
193 		kRedBlueMask = kRedMask | kBlueMask
194 	};
195 
196 	typedef uint16 PixelType;
197 };
198 
199 template<>
200 struct ColorMasks<4444> {
201 	enum {
202 		kBytesPerPixel = 2,
203 
204 		kAlphaBits  = 4,
205 		kRedBits    = 4,
206 		kGreenBits  = 4,
207 		kBlueBits   = 4,
208 
209 #ifdef __PSP__	//PSP uses ABGR
210 		kAlphaShift = kRedBits+kGreenBits+kBlueBits,
211 		kRedShift   = 0,
212 		kGreenShift = kRedBits,
213 		kBlueShift  = kRedBits+kGreenBits,
214 #else		//ARGB
215 		kAlphaShift = kRedBits+kGreenBits+kBlueBits,
216 		kRedShift   = kGreenBits+kBlueBits,
217 		kGreenShift = kBlueBits,
218 		kBlueShift  = 0,
219 #endif
220 
221 		kAlphaMask = ((1 << kAlphaBits) - 1) << kAlphaShift,
222 		kRedMask   = ((1 << kRedBits) - 1) << kRedShift,
223 		kGreenMask = ((1 << kGreenBits) - 1) << kGreenShift,
224 		kBlueMask  = ((1 << kBlueBits) - 1) << kBlueShift,
225 
226 		kRedBlueMask = kRedMask | kBlueMask
227 	};
228 
229 	typedef uint16 PixelType;
230 };
231 
232 template<>
233 struct ColorMasks<888> {
234 	enum {
235 		kBytesPerPixel = 4,
236 
237 		kAlphaBits  = 0,
238 		kRedBits    = 8,
239 		kGreenBits  = 8,
240 		kBlueBits   = 8,
241 
242 		kAlphaShift = 0,
243 		kRedShift   = kGreenBits+kBlueBits,
244 		kGreenShift = kBlueBits,
245 		kBlueShift  = 0,
246 
247 		kAlphaMask = ((1 << kAlphaBits) - 1) << kAlphaShift,
248 		kRedMask   = ((1 << kRedBits) - 1) << kRedShift,
249 		kGreenMask = ((1 << kGreenBits) - 1) << kGreenShift,
250 		kBlueMask  = ((1 << kBlueBits) - 1) << kBlueShift,
251 
252 		kRedBlueMask = kRedMask | kBlueMask,
253 
254 		kLowBits    = (1 << kRedShift) | (1 << kGreenShift) | (1 << kBlueShift),
255 		kLow2Bits   = (3 << kRedShift) | (3 << kGreenShift) | (3 << kBlueShift),
256 		kLow3Bits   = (7 << kRedShift) | (7 << kGreenShift) | (7 << kBlueShift),
257 		kLow4Bits   = (15 << kRedShift) | (15 << kGreenShift) | (15 << kBlueShift),
258 
259 		kLowBitsMask = kLowBits,
260 		// Prevent mask from including padding byte
261 		kHighBitsMask = (~kLowBits) & (kRedMask | kBlueMask | kGreenMask),
262 		qlowBits = kLow2Bits,
263 		qhighBits = (~kLowBits) & (kRedMask | kBlueMask | kGreenMask)
264 	};
265 
266 	typedef uint32 PixelType;
267 };
268 
269 template<>
270 struct ColorMasks<8888> {
271 	enum {
272 		kBytesPerPixel = 4,
273 
274 		kAlphaBits  = 8,
275 		kRedBits    = 8,
276 		kGreenBits  = 8,
277 		kBlueBits   = 8,
278 
279 		kAlphaShift = kRedBits+kGreenBits+kBlueBits,
280 		kRedShift   = kGreenBits+kBlueBits,
281 		kGreenShift = kBlueBits,
282 		kBlueShift  = 0,
283 
284 		kAlphaMask = ((1 << kAlphaBits) - 1) << kAlphaShift,
285 		kRedMask   = ((1 << kRedBits) - 1) << kRedShift,
286 		kGreenMask = ((1 << kGreenBits) - 1) << kGreenShift,
287 		kBlueMask  = ((1 << kBlueBits) - 1) << kBlueShift,
288 
289 		kRedBlueMask = kRedMask | kBlueMask,
290 
291 		kLowBits    = (1 << kRedShift) | (1 << kGreenShift) | (1 << kBlueShift) | (1 << kAlphaShift),
292 		kLow2Bits   = (3 << kRedShift) | (3 << kGreenShift) | (3 << kBlueShift) | (3 << kAlphaShift),
293 		kLow3Bits   = (7 << kRedShift) | (7 << kGreenShift) | (7 << kBlueShift) | (7 << kAlphaShift),
294 		kLow4Bits   = (15 << kRedShift) | (15 << kGreenShift) | (15 << kBlueShift) | (15 << kAlphaShift),
295 
296 		kLowBitsMask = kLowBits,
297 		kHighBitsMask = ~kLowBits,
298 		qlowBits = kLow2Bits,
299 		qhighBits = ~kLow2Bits
300 	};
301 
302 	typedef uint32 PixelType;
303 };
304 
305 #ifdef __WII__
306 /* Gamecube/Wii specific ColorMask ARGB3444 */
307 template<>
308 struct ColorMasks<3444> {
309 	enum {
310 		kBytesPerPixel = 2,
311 
312 		kAlphaBits  = 3,
313 		kRedBits    = 4,
314 		kGreenBits  = 4,
315 		kBlueBits   = 4,
316 
317 		kBlueShift  = 0,
318 		kGreenShift = kBlueBits,
319 		kRedShift   = kGreenBits+kBlueBits,
320 		kAlphaShift = kGreenBits+kBlueBits+kRedBits,
321 
322 		kAlphaMask = ((1 << kAlphaBits) - 1) << kAlphaShift,
323 		kRedMask   = ((1 << kRedBits) - 1) << kRedShift,
324 		kGreenMask = ((1 << kGreenBits) - 1) << kGreenShift,
325 		kBlueMask  = ((1 << kBlueBits) - 1) << kBlueShift,
326 
327 		kRedBlueMask = kRedMask | kBlueMask
328 	};
329 
330 	typedef uint16 PixelType;
331 };
332 #endif
333 
334 template<class T>
335 uint32 RGBToColor(uint8 r, uint8 g, uint8 b) {
336 	return T::kAlphaMask |
337 	       (((r << T::kRedShift) >> (8 - T::kRedBits)) & T::kRedMask) |
338 	       (((g << T::kGreenShift) >> (8 - T::kGreenBits)) & T::kGreenMask) |
339 	       (((b << T::kBlueShift) >> (8 - T::kBlueBits)) & T::kBlueMask);
340 }
341 
342 template<class T>
343 uint32 ARGBToColor(uint8 a, uint8 r, uint8 g, uint8 b) {
344 	return (((a << T::kAlphaShift) >> (8 - T::kAlphaBits)) & T::kAlphaMask) |
345 	       (((r << T::kRedShift) >> (8 - T::kRedBits)) & T::kRedMask) |
346 	       (((g << T::kGreenShift) >> (8 - T::kGreenBits)) & T::kGreenMask) |
347 	       (((b << T::kBlueShift) >> (8 - T::kBlueBits)) & T::kBlueMask);
348 }
349 
350 template<class T>
351 void colorToRGB(uint32 color, uint8 &r, uint8 &g, uint8 &b) {
352 	r = ((color & T::kRedMask) >> T::kRedShift) << (8 - T::kRedBits);
353 	g = ((color & T::kGreenMask) >> T::kGreenShift) << (8 - T::kGreenBits);
354 	b = ((color & T::kBlueMask) >> T::kBlueShift) << (8 - T::kBlueBits);
355 }
356 
357 template<class T>
358 void colorToARGB(uint32 color, uint8 &a, uint8 &r, uint8 &g, uint8 &b) {
359 	a = ((color & T::kAlphaMask) >> T::kAlphaShift) << (8 - T::kAlphaBits);
360 	r = ((color & T::kRedMask) >> T::kRedShift) << (8 - T::kRedBits);
361 	g = ((color & T::kGreenMask) >> T::kGreenShift) << (8 - T::kGreenBits);
362 	b = ((color & T::kBlueMask) >> T::kBlueShift) << (8 - T::kBlueBits);
363 }
364 
365 
366 
367 /**
368  * Convert a 'bitFormat' as defined by one of the ColorMasks
369  * into a PixelFormat.
370  */
371 template<int bitFormat>
372 PixelFormat createPixelFormat() {
373 	PixelFormat format;
374 
375 	format.bytesPerPixel = ColorMasks<bitFormat>::kBytesPerPixel;
376 
377 	format.rLoss = 8 - ColorMasks<bitFormat>::kRedBits;
378 	format.gLoss = 8 - ColorMasks<bitFormat>::kGreenBits;
379 	format.bLoss = 8 - ColorMasks<bitFormat>::kBlueBits;
380 	format.aLoss = 8 - ColorMasks<bitFormat>::kAlphaBits;
381 
382 	format.rShift = ColorMasks<bitFormat>::kRedShift;
383 	format.gShift = ColorMasks<bitFormat>::kGreenShift;
384 	format.bShift = ColorMasks<bitFormat>::kBlueShift;
385 	format.aShift = ColorMasks<bitFormat>::kAlphaShift;
386 
387 	return format;
388 }
389 
390 
391 } // End of namespace Graphics
392 
393 #endif
394