1 /******************************************************************************
2 * Arachnoid Graphics Plugin for Mupen64Plus
3 * http://bitbucket.org/wahrhaft/mupen64plus-video-arachnoid/
5 * Copyright (C) 2007 Kristofer Karlsson, Rickard Niklasson
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.
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.
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 *****************************************************************************/
22 //*****************************************************************************
24 // NOTE THAT THIS FILE IS BASED ON MATERIAL FROM glN64.
25 // http://gln64.emulation64.com/
27 //*****************************************************************************
29 #include "ImageFormatSelector.h"
30 #include "CachedTexture.h"
31 #include "assembler.h"
37 #ifndef GL_EXT_packed_pixels
38 #define GL_EXT_packed_pixels 1
39 #define GL_UNSIGNED_BYTE_3_3_2_EXT 0x8032
40 #define GL_UNSIGNED_SHORT_4_4_4_4_EXT 0x8033
41 #define GL_UNSIGNED_SHORT_5_5_5_1_EXT 0x8034
42 #define GL_UNSIGNED_INT_8_8_8_8_EXT 0x8035
43 #define GL_UNSIGNED_INT_10_10_10_2_EXT 0x8036
44 #endif /* GL_EXT_packed_pixels */
46 unsigned long long* TMEM = Memory::getTextureMemory();
49 inline unsigned int GetNone( unsigned long long *src, unsigned short x, unsigned short i, unsigned char palette )
54 inline unsigned int GetCI4IA_RGBA4444( unsigned long long *src, unsigned short x, unsigned short i, unsigned char palette )
56 unsigned char color4B;
58 color4B = ((unsigned char*)src)[(x>>1)^(i<<1)];
61 return IA88_RGBA4444( *(unsigned short*)&TMEM[256 + (palette << 4) + (color4B & 0x0F)] );
63 return IA88_RGBA4444( *(unsigned short*)&TMEM[256 + (palette << 4) + (color4B >> 4)] );
66 inline unsigned int GetCI4IA_RGBA8888( unsigned long long *src, unsigned short x, unsigned short i, unsigned char palette )
68 unsigned char color4B;
70 color4B = ((unsigned char*)src)[(x>>1)^(i<<1)];
73 return IA88_RGBA8888( *(unsigned short*)&TMEM[256 + (palette << 4) + (color4B & 0x0F)] );
75 return IA88_RGBA8888( *(unsigned short*)&TMEM[256 + (palette << 4) + (color4B >> 4)] );
78 inline unsigned int GetCI4RGBA_RGBA5551( unsigned long long *src, unsigned short x, unsigned short i, unsigned char palette )
80 unsigned char color4B;
82 color4B = ((unsigned char*)src)[(x>>1)^(i<<1)];
85 return RGBA5551_RGBA5551( *(unsigned short*)&TMEM[256 + (palette << 4) + (color4B & 0x0F)] );
87 return RGBA5551_RGBA5551( *(unsigned short*)&TMEM[256 + (palette << 4) + (color4B >> 4)] );
90 inline unsigned int GetCI4RGBA_RGBA8888( unsigned long long *src, unsigned short x, unsigned short i, unsigned char palette )
92 unsigned char color4B;
94 color4B = ((unsigned char*)src)[(x>>1)^(i<<1)];
97 return RGBA5551_RGBA8888( *(unsigned short*)&TMEM[256 + (palette << 4) + (color4B & 0x0F)] );
99 return RGBA5551_RGBA8888( *(unsigned short*)&TMEM[256 + (palette << 4) + (color4B >> 4)] );
102 inline unsigned int GetIA31_RGBA8888( unsigned long long *src, unsigned short x, unsigned short i, unsigned char palette )
104 unsigned char color4B;
106 color4B = ((unsigned char*)src)[(x>>1)^(i<<1)];
108 return IA31_RGBA8888( (x & 1) ? (color4B & 0x0F) : (color4B >> 4) );
111 inline unsigned int GetIA31_RGBA4444( unsigned long long *src, unsigned short x, unsigned short i, unsigned char palette )
113 unsigned char color4B;
115 color4B = ((unsigned char*)src)[(x>>1)^(i<<1)];
117 return IA31_RGBA4444( (x & 1) ? (color4B & 0x0F) : (color4B >> 4) );
120 inline unsigned int GetI4_RGBA8888( unsigned long long *src, unsigned short x, unsigned short i, unsigned char palette )
122 unsigned char color4B;
124 color4B = ((unsigned char*)src)[(x>>1)^(i<<1)];
126 return I4_RGBA8888( (x & 1) ? (color4B & 0x0F) : (color4B >> 4) );
129 inline unsigned int GetI4_RGBA4444( unsigned long long *src, unsigned short x, unsigned short i, unsigned char palette )
131 unsigned char color4B;
133 color4B = ((unsigned char*)src)[(x>>1)^(i<<1)];
135 return I4_RGBA4444( (x & 1) ? (color4B & 0x0F) : (color4B >> 4) );
138 inline unsigned int GetCI8IA_RGBA4444( unsigned long long *src, unsigned short x, unsigned short i, unsigned char palette )
140 return IA88_RGBA4444( *(unsigned short*)&TMEM[256 + ((unsigned char*)src)[x^(i<<1)]] );
143 inline unsigned int GetCI8IA_RGBA8888( unsigned long long *src, unsigned short x, unsigned short i, unsigned char palette )
145 return IA88_RGBA8888( *(unsigned short*)&TMEM[256 + ((unsigned char*)src)[x^(i<<1)]] );
148 inline unsigned int GetCI8RGBA_RGBA5551( unsigned long long *src, unsigned short x, unsigned short i, unsigned char palette )
150 return RGBA5551_RGBA5551( *(unsigned short*)&TMEM[256 + ((unsigned char*)src)[x^(i<<1)]] );
153 inline unsigned int GetCI8RGBA_RGBA8888( unsigned long long *src, unsigned short x, unsigned short i, unsigned char palette )
155 return RGBA5551_RGBA8888( *(unsigned short*)&TMEM[256 + ((unsigned char*)src)[x^(i<<1)]] );
158 inline unsigned int GetIA44_RGBA8888( unsigned long long *src, unsigned short x, unsigned short i, unsigned char palette )
160 return IA44_RGBA8888(((unsigned char*)src)[x^(i<<1)]);
163 inline unsigned int GetIA44_RGBA4444( unsigned long long *src, unsigned short x, unsigned short i, unsigned char palette )
165 return IA44_RGBA4444(((unsigned char*)src)[x^(i<<1)]);
168 inline unsigned int GetI8_RGBA8888( unsigned long long *src, unsigned short x, unsigned short i, unsigned char palette )
170 return I8_RGBA8888(((unsigned char*)src)[x^(i<<1)]);
173 inline unsigned int GetI8_RGBA4444( unsigned long long *src, unsigned short x, unsigned short i, unsigned char palette )
175 return I8_RGBA4444(((unsigned char*)src)[x^(i<<1)]);
178 inline unsigned int GetRGBA5551_RGBA8888( unsigned long long *src, unsigned short x, unsigned short i, unsigned char palette )
180 return RGBA5551_RGBA8888( ((unsigned short*)src)[x^i] );
183 inline unsigned int GetRGBA5551_RGBA5551( unsigned long long *src, unsigned short x, unsigned short i, unsigned char palette )
185 return RGBA5551_RGBA5551( ((unsigned short*)src)[x^i] );
188 inline unsigned int GetIA88_RGBA8888( unsigned long long *src, unsigned short x, unsigned short i, unsigned char palette )
190 return IA88_RGBA8888(((unsigned short*)src)[x^i]);
193 inline unsigned int GetIA88_RGBA4444( unsigned long long *src, unsigned short x, unsigned short i, unsigned char palette )
195 return IA88_RGBA4444(((unsigned short*)src)[x^i]);
198 inline unsigned int GetRGBA8888_RGBA8888( unsigned long long *src, unsigned short x, unsigned short i, unsigned char palette )
200 return ((unsigned int*)src)[x^i];
203 inline unsigned int GetRGBA8888_RGBA4444( unsigned long long *src, unsigned short x, unsigned short i, unsigned char palette )
205 return RGBA8888_RGBA4444(((unsigned int*)src)[x^i]);
212 unsigned int glType16;
213 int glInternalFormat16;
215 unsigned int glType32;
216 int glInternalFormat32;
217 unsigned int autoFormat, lineShift, maxTexels;
220 ImageFormat ImageFormatSelector::imageFormats[4][5] =
221 { // Get16 glType16 glInternalFormat16 Get32 glType32 glInternalFormat32 autoFormat
223 { GetCI4RGBA_RGBA5551, GL_UNSIGNED_SHORT_5_5_5_1_EXT, GL_RGB5_A1, GetCI4RGBA_RGBA8888, GL_UNSIGNED_BYTE, GL_RGBA8, GL_RGB5_A1, 4, 4096 }, // CI (Banjo-Kazooie uses this, doesn't make sense, but it works...)
224 { GetNone, GL_UNSIGNED_SHORT_4_4_4_4_EXT, GL_RGBA4, GetNone, GL_UNSIGNED_BYTE, GL_RGBA8, GL_RGBA4, 4, 8192 }, // YUV
225 { GetCI4RGBA_RGBA5551, GL_UNSIGNED_SHORT_5_5_5_1_EXT, GL_RGB5_A1, GetCI4RGBA_RGBA8888, GL_UNSIGNED_BYTE, GL_RGBA8, GL_RGB5_A1, 4, 4096 }, // CI
226 { GetIA31_RGBA4444, GL_UNSIGNED_SHORT_4_4_4_4_EXT, GL_RGBA4, GetIA31_RGBA8888, GL_UNSIGNED_BYTE, GL_RGBA8, GL_RGBA4, 4, 8192 }, // IA
227 { GetI4_RGBA4444, GL_UNSIGNED_SHORT_4_4_4_4_EXT, GL_RGBA4, GetI4_RGBA8888, GL_UNSIGNED_BYTE, GL_RGBA8, GL_RGBA4, 4, 8192 }, // I
230 { GetCI8RGBA_RGBA5551, GL_UNSIGNED_SHORT_5_5_5_1_EXT, GL_RGB5_A1, GetCI8RGBA_RGBA8888, GL_UNSIGNED_BYTE, GL_RGBA8, GL_RGB5_A1, 3, 2048 }, // RGBA
231 { GetNone, GL_UNSIGNED_SHORT_4_4_4_4_EXT, GL_RGBA4, GetNone, GL_UNSIGNED_BYTE, GL_RGBA8, GL_RGBA4, 0, 4096 }, // YUV
232 { GetCI8RGBA_RGBA5551, GL_UNSIGNED_SHORT_5_5_5_1_EXT, GL_RGB5_A1, GetCI8RGBA_RGBA8888, GL_UNSIGNED_BYTE, GL_RGBA8, GL_RGB5_A1, 3, 2048 }, // CI
233 { GetIA44_RGBA4444, GL_UNSIGNED_SHORT_4_4_4_4_EXT, GL_RGBA4, GetIA44_RGBA8888, GL_UNSIGNED_BYTE, GL_RGBA8, GL_RGBA4, 3, 4096 }, // IA
234 { GetI8_RGBA4444, GL_UNSIGNED_SHORT_4_4_4_4_EXT, GL_RGBA4, GetI8_RGBA8888, GL_UNSIGNED_BYTE, GL_RGBA8, GL_RGBA8, 3, 4096 }, // I
237 { GetRGBA5551_RGBA5551, GL_UNSIGNED_SHORT_5_5_5_1_EXT, GL_RGB5_A1, GetRGBA5551_RGBA8888, GL_UNSIGNED_BYTE, GL_RGBA8, GL_RGB5_A1, 2, 2048 }, // RGBA
238 { GetNone, GL_UNSIGNED_SHORT_4_4_4_4_EXT, GL_RGBA4, GetNone, GL_UNSIGNED_BYTE, GL_RGBA8, GL_RGBA4, 2, 2048 }, // YUV
239 { GetNone, GL_UNSIGNED_SHORT_4_4_4_4_EXT, GL_RGBA4, GetNone, GL_UNSIGNED_BYTE, GL_RGBA8, GL_RGBA4, 0, 2048 }, // CI
240 { GetIA88_RGBA4444, GL_UNSIGNED_SHORT_4_4_4_4_EXT, GL_RGBA4, GetIA88_RGBA8888, GL_UNSIGNED_BYTE, GL_RGBA8, GL_RGBA8, 2, 2048 }, // IA
241 { GetNone, GL_UNSIGNED_SHORT_4_4_4_4_EXT, GL_RGBA4, GetNone, GL_UNSIGNED_BYTE, GL_RGBA8, GL_RGBA4, 0, 2048 }, // I
244 { GetRGBA8888_RGBA4444, GL_UNSIGNED_SHORT_4_4_4_4_EXT, GL_RGBA4, GetRGBA8888_RGBA8888, GL_UNSIGNED_BYTE, GL_RGBA8, GL_RGBA8, 2, 1024 }, // RGBA
245 { GetNone, GL_UNSIGNED_SHORT_4_4_4_4_EXT, GL_RGBA4, GetNone, GL_UNSIGNED_BYTE, GL_RGBA8, GL_RGBA4, 0, 1024 }, // YUV
246 { GetNone, GL_UNSIGNED_SHORT_4_4_4_4_EXT, GL_RGBA4, GetNone, GL_UNSIGNED_BYTE, GL_RGBA8, GL_RGBA4, 0, 1024 }, // CI
247 { GetNone, GL_UNSIGNED_SHORT_4_4_4_4_EXT, GL_RGBA4, GetNone, GL_UNSIGNED_BYTE, GL_RGBA8, GL_RGBA4, 0, 1024 }, // IA
248 { GetNone, GL_UNSIGNED_SHORT_4_4_4_4_EXT, GL_RGBA4, GetNone, GL_UNSIGNED_BYTE, GL_RGBA8, GL_RGBA4, 0, 1024 }, // I
252 //-----------------------------------------------------------------------------
254 //-----------------------------------------------------------------------------
255 ImageFormatSelector::ImageFormatSelector()
259 //-----------------------------------------------------------------------------
261 //-----------------------------------------------------------------------------
262 ImageFormatSelector::~ImageFormatSelector()
267 //-----------------------------------------------------------------------------
268 // Detect Image Format
269 //-----------------------------------------------------------------------------
270 void ImageFormatSelector::detectImageFormat(CachedTexture* texture, unsigned int textureBitDepth, GetTexelFunc& getTexelFunc, unsigned int& internalFormat, int& imageType, unsigned int textureLUT)
272 if (((imageFormats[texture->size][texture->format].autoFormat == GL_RGBA8) ||
273 ((texture->format == G_IM_FMT_CI) && (textureLUT == G_TT_IA16)) ||
274 (textureBitDepth == 2)) && (textureBitDepth != 0))
276 texture->m_textureSize = (texture->realWidth * texture->realHeight) << 2;
277 if ((texture->format == G_IM_FMT_CI) && (textureLUT == G_TT_IA16))
279 if (texture->size == G_IM_SIZ_4b)
280 getTexelFunc = GetCI4IA_RGBA8888;
282 getTexelFunc = GetCI8IA_RGBA8888;
284 internalFormat = GL_RGBA8;
285 imageType = GL_UNSIGNED_BYTE;
289 getTexelFunc = imageFormats[texture->size][texture->format].Get32;
290 internalFormat = imageFormats[texture->size][texture->format].glInternalFormat32;
291 imageType = imageFormats[texture->size][texture->format].glType32;
296 texture->m_textureSize = (texture->realWidth * texture->realHeight) << 1;
297 if ((texture->format == G_IM_FMT_CI) && (textureLUT == G_TT_IA16))
299 if (texture->size == G_IM_SIZ_4b)
300 getTexelFunc = GetCI4IA_RGBA4444;
302 getTexelFunc = GetCI8IA_RGBA4444;
304 internalFormat = GL_RGBA4;
305 imageType = GL_UNSIGNED_SHORT_4_4_4_4_EXT;
309 getTexelFunc = imageFormats[texture->size][texture->format].Get16;
310 internalFormat = imageFormats[texture->size][texture->format].glInternalFormat16;
311 imageType = imageFormats[texture->size][texture->format].glType16;