Arachnoid GLESv1.1 plugin. Compile and run (a bit glitchy and no frameskip) on the...
[mupen64plus-pandora.git] / source / mupen64plus-video-arachnoid / src / texture / ImageFormatSelector.cpp
1 /******************************************************************************
2  * Arachnoid Graphics Plugin for Mupen64Plus
3  * http://bitbucket.org/wahrhaft/mupen64plus-video-arachnoid/
4  *
5  * Copyright (C) 2007 Kristofer Karlsson, Rickard Niklasson
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 // 
24 // NOTE THAT THIS FILE IS BASED ON MATERIAL FROM glN64.
25 // http://gln64.emulation64.com/
26 //
27 //*****************************************************************************
28
29 #include "ImageFormatSelector.h"
30 #include "CachedTexture.h"
31 #include "assembler.h"
32 #include "GBIDefs.h"
33 #include "m64p.h"
34 #include "OpenGL.h"
35 #include "Memory.h"
36
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 */
45
46 unsigned long long* TMEM = Memory::getTextureMemory();
47
48
49 inline unsigned int GetNone( unsigned long long *src, unsigned short x, unsigned short i, unsigned char palette )
50 {
51     return 0x00000000;
52 }
53
54 inline unsigned int GetCI4IA_RGBA4444( unsigned long long *src, unsigned short x, unsigned short i, unsigned char palette )
55 {
56     unsigned char color4B;
57
58     color4B = ((unsigned char*)src)[(x>>1)^(i<<1)];
59
60     if (x & 1)
61         return IA88_RGBA4444( *(unsigned short*)&TMEM[256 + (palette << 4) + (color4B & 0x0F)] );
62     else
63         return IA88_RGBA4444( *(unsigned short*)&TMEM[256 + (palette << 4) + (color4B >> 4)] );
64 }
65
66 inline unsigned int GetCI4IA_RGBA8888( unsigned long long *src, unsigned short x, unsigned short i, unsigned char palette )
67 {
68     unsigned char color4B;
69
70     color4B = ((unsigned char*)src)[(x>>1)^(i<<1)];
71
72     if (x & 1)
73         return IA88_RGBA8888( *(unsigned short*)&TMEM[256 + (palette << 4) + (color4B & 0x0F)] );
74     else
75         return IA88_RGBA8888( *(unsigned short*)&TMEM[256 + (palette << 4) + (color4B >> 4)] );
76 }
77
78 inline unsigned int GetCI4RGBA_RGBA5551( unsigned long long *src, unsigned short x, unsigned short i, unsigned char palette )
79 {
80     unsigned char color4B;
81
82     color4B = ((unsigned char*)src)[(x>>1)^(i<<1)];
83
84     if (x & 1)
85         return RGBA5551_RGBA5551( *(unsigned short*)&TMEM[256 + (palette << 4) + (color4B & 0x0F)] );
86     else
87         return RGBA5551_RGBA5551( *(unsigned short*)&TMEM[256 + (palette << 4) + (color4B >> 4)] );
88 }
89
90 inline unsigned int GetCI4RGBA_RGBA8888( unsigned long long *src, unsigned short x, unsigned short i, unsigned char palette )
91 {
92     unsigned char color4B;
93
94     color4B = ((unsigned char*)src)[(x>>1)^(i<<1)];
95
96     if (x & 1)
97         return RGBA5551_RGBA8888( *(unsigned short*)&TMEM[256 + (palette << 4) + (color4B & 0x0F)] );
98     else
99         return RGBA5551_RGBA8888( *(unsigned short*)&TMEM[256 + (palette << 4) + (color4B >> 4)] );
100 }
101
102 inline unsigned int GetIA31_RGBA8888( unsigned long long *src, unsigned short x, unsigned short i, unsigned char palette )
103 {
104     unsigned char color4B;
105
106     color4B = ((unsigned char*)src)[(x>>1)^(i<<1)];
107
108     return IA31_RGBA8888( (x & 1) ? (color4B & 0x0F) : (color4B >> 4) );
109 }
110
111 inline unsigned int GetIA31_RGBA4444( unsigned long long *src, unsigned short x, unsigned short i, unsigned char palette )
112 {
113     unsigned char color4B;
114
115     color4B = ((unsigned char*)src)[(x>>1)^(i<<1)];
116
117     return IA31_RGBA4444( (x & 1) ? (color4B & 0x0F) : (color4B >> 4) );
118 }
119
120 inline unsigned int GetI4_RGBA8888( unsigned long long *src, unsigned short x, unsigned short i, unsigned char palette )
121 {
122     unsigned char color4B;
123
124     color4B = ((unsigned char*)src)[(x>>1)^(i<<1)];
125
126     return I4_RGBA8888( (x & 1) ? (color4B & 0x0F) : (color4B >> 4) );
127 }
128
129 inline unsigned int GetI4_RGBA4444( unsigned long long *src, unsigned short x, unsigned short i, unsigned char palette )
130 {
131     unsigned char color4B;
132
133     color4B = ((unsigned char*)src)[(x>>1)^(i<<1)];
134
135     return I4_RGBA4444( (x & 1) ? (color4B & 0x0F) : (color4B >> 4) );
136 }
137
138 inline unsigned int GetCI8IA_RGBA4444( unsigned long long *src, unsigned short x, unsigned short i, unsigned char palette )
139 {
140     return IA88_RGBA4444( *(unsigned short*)&TMEM[256 + ((unsigned char*)src)[x^(i<<1)]] );
141 }
142
143 inline unsigned int GetCI8IA_RGBA8888( unsigned long long *src, unsigned short x, unsigned short i, unsigned char palette )
144 {
145     return IA88_RGBA8888( *(unsigned short*)&TMEM[256 + ((unsigned char*)src)[x^(i<<1)]] );
146 }
147
148 inline unsigned int GetCI8RGBA_RGBA5551( unsigned long long *src, unsigned short x, unsigned short i, unsigned char palette )
149 {
150     return RGBA5551_RGBA5551( *(unsigned short*)&TMEM[256 + ((unsigned char*)src)[x^(i<<1)]] );
151 }
152
153 inline unsigned int GetCI8RGBA_RGBA8888( unsigned long long *src, unsigned short x, unsigned short i, unsigned char palette )
154 {
155     return RGBA5551_RGBA8888( *(unsigned short*)&TMEM[256 + ((unsigned char*)src)[x^(i<<1)]] );
156 }
157
158 inline unsigned int GetIA44_RGBA8888( unsigned long long *src, unsigned short x, unsigned short i, unsigned char palette )
159 {
160     return IA44_RGBA8888(((unsigned char*)src)[x^(i<<1)]);
161 }
162
163 inline unsigned int GetIA44_RGBA4444( unsigned long long *src, unsigned short x, unsigned short i, unsigned char palette )
164 {
165     return IA44_RGBA4444(((unsigned char*)src)[x^(i<<1)]);
166 }
167
168 inline unsigned int GetI8_RGBA8888( unsigned long long *src, unsigned short x, unsigned short i, unsigned char palette )
169 {
170     return I8_RGBA8888(((unsigned char*)src)[x^(i<<1)]);
171 }
172
173 inline unsigned int GetI8_RGBA4444( unsigned long long *src, unsigned short x, unsigned short i, unsigned char palette )
174 {
175     return I8_RGBA4444(((unsigned char*)src)[x^(i<<1)]);
176 }
177
178 inline unsigned int GetRGBA5551_RGBA8888( unsigned long long *src, unsigned short x, unsigned short i, unsigned char palette )
179 {
180     return RGBA5551_RGBA8888( ((unsigned short*)src)[x^i] );
181 }
182
183 inline unsigned int GetRGBA5551_RGBA5551( unsigned long long *src, unsigned short x, unsigned short i, unsigned char palette )
184 {
185     return RGBA5551_RGBA5551( ((unsigned short*)src)[x^i] );
186 }
187
188 inline unsigned int GetIA88_RGBA8888( unsigned long long *src, unsigned short x, unsigned short i, unsigned char palette )
189 {
190     return IA88_RGBA8888(((unsigned short*)src)[x^i]);
191 }
192
193 inline unsigned int GetIA88_RGBA4444( unsigned long long *src, unsigned short x, unsigned short i, unsigned char palette )
194 {
195     return IA88_RGBA4444(((unsigned short*)src)[x^i]);
196 }
197
198 inline unsigned int GetRGBA8888_RGBA8888( unsigned long long *src, unsigned short x, unsigned short i, unsigned char palette )
199 {
200     return ((unsigned int*)src)[x^i];
201 }
202
203 inline unsigned int GetRGBA8888_RGBA4444( unsigned long long *src, unsigned short x, unsigned short i, unsigned char palette )
204 {
205     return RGBA8888_RGBA4444(((unsigned int*)src)[x^i]);
206 }
207
208 /*
209 const struct
210 {
211     GetTexelFunc    Get16;
212     unsigned int    glType16;
213     int              glInternalFormat16;
214     GetTexelFunc    Get32;
215     unsigned int     glType32;
216     int                glInternalFormat32;
217     unsigned int   autoFormat, lineShift, maxTexels;
218
219 */
220 ImageFormat ImageFormatSelector::imageFormats[4][5]  =
221 { //        Get16                    glType16                        glInternalFormat16    Get32                   glType32             glInternalFormat32   autoFormat
222     { // 4-bit
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
228     },
229     { // 8-bit
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
235     },
236     { // 16-bit
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
242     },
243     { // 32-bit
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
249     }
250 };
251
252 //-----------------------------------------------------------------------------
253 //! Constructor
254 //-----------------------------------------------------------------------------
255 ImageFormatSelector::ImageFormatSelector()
256 {
257 }
258
259 //-----------------------------------------------------------------------------
260 //! Destructor
261 //-----------------------------------------------------------------------------
262 ImageFormatSelector::~ImageFormatSelector()
263 {
264
265 }
266
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)
271 {
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))
275     {
276          texture->m_textureSize = (texture->realWidth * texture->realHeight) << 2;
277         if ((texture->format == G_IM_FMT_CI) && (textureLUT == G_TT_IA16))
278         {
279             if (texture->size == G_IM_SIZ_4b)
280                 getTexelFunc = GetCI4IA_RGBA8888;
281             else
282                 getTexelFunc = GetCI8IA_RGBA8888;
283
284             internalFormat = GL_RGBA8;
285             imageType = GL_UNSIGNED_BYTE;
286         }
287         else
288         {
289             getTexelFunc = imageFormats[texture->size][texture->format].Get32;
290             internalFormat = imageFormats[texture->size][texture->format].glInternalFormat32;
291             imageType = imageFormats[texture->size][texture->format].glType32;
292         }
293     }
294     else
295     {
296         texture->m_textureSize = (texture->realWidth * texture->realHeight) << 1;
297         if ((texture->format == G_IM_FMT_CI) && (textureLUT == G_TT_IA16))
298         {
299             if (texture->size == G_IM_SIZ_4b)
300                 getTexelFunc = GetCI4IA_RGBA4444;
301             else
302                 getTexelFunc = GetCI8IA_RGBA4444;
303
304             internalFormat = GL_RGBA4;
305             imageType = GL_UNSIGNED_SHORT_4_4_4_4_EXT;
306         }
307         else
308         {
309             getTexelFunc = imageFormats[texture->size][texture->format].Get16;
310             internalFormat = imageFormats[texture->size][texture->format].glInternalFormat16;
311             imageType = imageFormats[texture->size][texture->format].glType16;
312         }
313     }
314 }