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