1 //
2 //------------------------------------------------------------
3 // Copyright(c) 2009-2010 by Digital Media Professionals Inc.
4 // All rights reserved.
5 //------------------------------------------------------------
6 // This source code is the confidential and proprietary
7 // of Digital Media Professionals Inc.
8 //------------------------------------------------------------
9 //
10 
11 #include "string.h"
12 
13 #include "demo/Utility/demo_TextureConverter.h"
14 
15 namespace demo
16 {
17     /*
18      *  Definitions
19      */
20     const u32 TEXTURE_BLOCK_SIZE = 8;
21     const u32 TEXTURE_PIXELS_IN_BLOCK = TEXTURE_BLOCK_SIZE * TEXTURE_BLOCK_SIZE;
22     #define SWAP(A, B)		tmp = (A); (A) = (B); (B) = tmp
23 
24     /*
25      *  Type definitions
26      */
27 
28     enum TextureMode
29     {
30 	    TEXTURE_LINE_TO_BLOCK_MODE = 0,
31 	    TEXTURE_BLOCK_TO_LINE_MODE = 1
32     };
33 
34     typedef struct
35     {
36         GLenum format;
37 	    s32 blocksInRow;
38 	    s32	blocksInCol;
39 	    u8*	src;
40 	    u8*	dst;
41 	    u32	width;
42 	    u32	height;
43 	    u32	yflip;
44 	    u32	mode;
45     } TextureInformation;
46 
47     typedef s32 (*textureConvertFunction)(TextureInformation* textureInformation);
48 
49     /*
50      *  Local Function Declaration
51      */
52     static s32 GetPixelByte(const GLenum format);
53 
54     static s32 ReadBlock(u32 no, u8* buf, TextureInformation* textureInformation);
55     static s32 WriteBlock(u32 no, const u8* pSrc, TextureInformation* textureInformation);
56     static s32 DeBlock(const u8* pSrc, u8* pDst, s32 blocksize, TextureInformation* textureInformation);
57     static s32 EnBlock(const u8* pSrc, u8* pDst, s32 blocksize, TextureInformation* textureInformation);
58     static s32 SwapColorComponents(TextureInformation* textureInformation);
59 
60     static s32 ConvertFormat8888Function(TextureInformation* textureInformation);
61     static s32 ConvertFormat888Function(TextureInformation* textureInformation);
62     static s32 ConvertFormat88Function(TextureInformation* textureInformation);
63     static s32 ConvertFormatXXXXFunction(TextureInformation* textureInformation);
64 
65     static textureConvertFunction convertFunctionArray[] =
66     {
67 	    ConvertFormat8888Function,  /* GL_RGBA_NATIVE_DMP R8G8B8A8 */
68 	    ConvertFormat888Function,   /* GL_RGB_NATIVE_DMP R8G8B8 */
69         ConvertFormat88Function,    /* GL_LUMINANCE_ALPHA_NATIVE_DMP L8A8 */
70         ConvertFormatXXXXFunction,  /* else     */
71 	    ConvertFormatXXXXFunction,  /* R5G6B5   */
72 	    ConvertFormatXXXXFunction,  /* R5G5B5A1 */
73 	    ConvertFormatXXXXFunction,  /* R4G4B4A4 */
74 	    ConvertFormatXXXXFunction,  /* L8       */
75 	    ConvertFormatXXXXFunction   /* A8       */
76     };
77 
78     /*
79      *	Export functions
80      */
81 
82     /* Block <--> Linear conversion */
ConvertGLTextureToNative(const GLenum format,const u32 width,const u32 height,void * glData,void * dmpData)83     bool ConvertGLTextureToNative(const GLenum format, const u32 width, const u32 height,
84         void* glData, void* dmpData)
85     {
86         bool yflip = true;
87         TextureMode mode = TEXTURE_LINE_TO_BLOCK_MODE;
88 
89 	    u8 blockBuf[TEXTURE_PIXELS_IN_BLOCK * 4];
90 	    TextureInformation textureInformation;
91 
92 	    if (width & 0x00000003 || height & 0x00000003)
93 	    {
94 		    return false;
95 	    }
96 
97 	    textureInformation.format = format;
98 	    textureInformation.width = width;
99 	    textureInformation.height = height;
100 	    textureInformation.blocksInRow = (textureInformation.width / TEXTURE_BLOCK_SIZE);
101 	    textureInformation.blocksInCol = (textureInformation.height / TEXTURE_BLOCK_SIZE);
102 	    textureInformation.src = (u8*)glData;
103 	    textureInformation.dst = (u8*)dmpData;
104         if ( yflip )
105         {
106 	        textureInformation.yflip = 1;
107         }
108         else
109         {
110             textureInformation.yflip = 0;
111         }
112         textureInformation.mode = mode;
113 
114 	    /* Convert color format */
115 	    SwapColorComponents(&textureInformation);
116 	    /* for each row */
117 	    for (s32 row = 0; row < textureInformation.blocksInCol; row++)
118 	    {
119 		    /* for each column */
120 		    for (s32 col = 0; col < textureInformation.blocksInRow; col++)
121 		    {
122 			    /* Read one unit from source buffer. Read in source addressing and color format */
123 			    ReadBlock(row * textureInformation.blocksInRow + col, blockBuf, &textureInformation);
124 			    /* Write one unit to destination buffer. written with converting addressing format */
125 			    WriteBlock(row * textureInformation.blocksInRow + col, blockBuf, &textureInformation);
126 		    }
127 	    }
128 
129 	    return true;
130     }
131 
132     /*
133      *	Local functions
134      */
GetPixelByte(const GLenum format)135     static s32 GetPixelByte(const GLenum format)
136     {
137         /* GL_RGBA_NATIVE_DMP R8G8B8A8 */
138         if ( format == GL_RGBA_NATIVE_DMP )
139         {
140             return 4;
141         }
142         /* GL_RGB_NATIVE_DMP R8G8B8 */
143         else if ( format == GL_RGB_NATIVE_DMP )
144         {
145 	        return 3;
146         }
147         /* GL_LUMINANCE_ALPHA_NATIVE_DMP L8A8 */
148         else if ( format == GL_LUMINANCE_ALPHA_NATIVE_DMP )
149         {
150             return 2;
151         }
152         else
153         {
154             NN_TLOG_("Unsupported texture format.");
155             NN_TASSERT_(0);
156 
157             return 1;
158         }
159     }
160 
ReadBlock(u32 no,u8 * buf,TextureInformation * textureInformation)161     static s32 ReadBlock(u32 no, u8* buf, TextureInformation* textureInformation)
162     {
163         u32 row = (no / textureInformation->blocksInRow);
164         u32 column = (no % textureInformation->blocksInRow);
165         u32 pixelByte = GetPixelByte(textureInformation->format);
166 
167 	    /* Read src us32 */
168 	    if (textureInformation->mode == TEXTURE_BLOCK_TO_LINE_MODE)
169 	    {
170 		    /* Get source buffer pointer */
171 		    const u8* pSrc = textureInformation->src +
172                 no * pixelByte * TEXTURE_PIXELS_IN_BLOCK;
173 
174 		    /* read uint image from block format buffer */
175 		    memcpy(buf, pSrc, (TEXTURE_PIXELS_IN_BLOCK * pixelByte) );
176 	    }
177 	    else // if (mode == L2B)
178 	    {
179 		    /* Get source buffer pointer */
180 		    const u8* pSrc = textureInformation->src +
181                 (row * TEXTURE_PIXELS_IN_BLOCK * pixelByte * textureInformation->blocksInRow) +
182                 (column * pixelByte * TEXTURE_BLOCK_SIZE);
183 
184 		    /* read uint image from linear format buffer */
185 		    for (s32 i = 0; i < TEXTURE_BLOCK_SIZE; i++)
186 		    {
187 			    memcpy(buf, pSrc, pixelByte * TEXTURE_BLOCK_SIZE);
188 			    buf += pixelByte * TEXTURE_BLOCK_SIZE;
189 			    pSrc += pixelByte * textureInformation->width;
190 		    }
191         }
192 
193         return 1;
194     }
195 
WriteBlock(u32 no,const u8 * pSrc,TextureInformation * textureInformation)196     static s32 WriteBlock(u32 no, const u8* pSrc, TextureInformation* textureInformation)
197     {
198         u32 row = (no / textureInformation->blocksInRow);
199         u32 column = (no % textureInformation->blocksInRow);
200         u32 pixelByte = GetPixelByte(textureInformation->format);
201 
202 	    /* Read src uint */
203 	    if (textureInformation->mode == TEXTURE_BLOCK_TO_LINE_MODE)
204 	    {
205 		    /* Get destination buffer pointer */
206 		    u8*	pDst;
207 
208 		    /* Get destination pointer */
209 		    if (textureInformation->yflip)
210             {
211 			    pDst = textureInformation->dst +
212                     ((textureInformation->blocksInCol - row - 1) * TEXTURE_PIXELS_IN_BLOCK * pixelByte *
213                     textureInformation->blocksInRow) + column * pixelByte * TEXTURE_BLOCK_SIZE;
214             }
215 		    else
216             {
217 			    pDst = textureInformation->dst +
218                     (row * TEXTURE_PIXELS_IN_BLOCK * pixelByte * textureInformation->blocksInRow) +
219                     column * pixelByte * TEXTURE_BLOCK_SIZE;
220             }
221 
222 		    /* write uint image to linear format buffer */
223 		    DeBlock(pSrc, pDst, TEXTURE_BLOCK_SIZE, textureInformation);
224 	    }
225 	    else // if (mode == L2B)
226 	    {
227 		    /* Get destination buffer pointer */
228 		    u8* pDst;
229 
230 		    if (textureInformation->yflip)
231             {
232 			    pDst = textureInformation->dst +
233                     ((textureInformation->blocksInCol - row - 1) * textureInformation->blocksInRow + column) *
234                     TEXTURE_PIXELS_IN_BLOCK * pixelByte;
235             }
236 		    else
237             {
238 			    pDst = textureInformation->dst +
239                     no * TEXTURE_PIXELS_IN_BLOCK * pixelByte;
240             }
241 
242 		    /* write uint image to block format buffer */
243 		    EnBlock(pSrc, pDst, TEXTURE_BLOCK_SIZE, textureInformation);
244 	    }
245 
246         return 1;
247     }
248 
DeBlock(const u8 * pSrc,u8 * pDst,s32 blocksize,TextureInformation * textureInformation)249     static s32 DeBlock(const u8* pSrc, u8* pDst, s32 blocksize, TextureInformation* textureInformation)
250     {
251         u32 pixelByte = GetPixelByte(textureInformation->format);
252 
253 	    if (blocksize != 1)
254 	    {
255 		    s32 pixels;
256 		    blocksize >>= 1;
257 		    pixels = blocksize * blocksize;
258 		    //s32 dstWidth = textureInformation->width;
259 
260 		    if (!textureInformation->yflip)
261 		    {
262 			    DeBlock(pSrc + (pixelByte * pixels * 0),
263                     pDst, blocksize, textureInformation);
264 
265                 DeBlock(pSrc + (pixelByte * pixels * 1),
266                     pDst + (pixelByte * blocksize),
267                     blocksize, textureInformation);
268 
269 			    DeBlock(pSrc + (pixelByte * pixels * 2),
270                     pDst + (pixelByte * textureInformation->width * blocksize),
271                     blocksize, textureInformation);
272 
273                 DeBlock(pSrc + (pixelByte * pixels * 3),
274                     pDst + (pixelByte * (blocksize + (textureInformation->width * blocksize))),
275                     blocksize, textureInformation);
276 		    }
277 		    else
278 		    {
279 			    DeBlock(pSrc + (pixelByte * pixels * 0),
280                     pDst + (pixelByte * textureInformation->width*blocksize),
281                     blocksize, textureInformation);
282 
283 			    DeBlock(pSrc + (pixelByte * pixels * 1),
284                     pDst + (pixelByte * (blocksize + (textureInformation->width * blocksize))),
285                     blocksize, textureInformation);
286 
287 			    DeBlock(pSrc + (pixelByte * pixels * 2), pDst,
288                     blocksize, textureInformation);
289 
290 			    DeBlock(pSrc + (pixelByte * pixels * 3),
291                     pDst+(pixelByte * blocksize),
292                     blocksize, textureInformation);
293 		    }
294 	    }
295 	    else
296 		    memcpy((void*)pDst, pSrc, pixelByte);
297 
298 	    return 1;
299     }
300 
EnBlock(const u8 * pSrc,u8 * pDst,s32 blocksize,TextureInformation * textureInformation)301     static s32 EnBlock(const u8* pSrc, u8* pDst, s32 blocksize, TextureInformation* textureInformation)
302     {
303         u32 pixelByte = GetPixelByte(textureInformation->format);
304 
305 	    if (blocksize != 1)
306 	    {
307 		    s32 pixels;
308 		    blocksize >>= 1;
309 		    pixels = blocksize * blocksize;
310 
311 		    if (! textureInformation->yflip )
312 		    {
313 			    EnBlock(pSrc,
314                     pDst + (pixelByte * pixels * 0),
315                     blocksize, textureInformation);
316 
317 			    EnBlock(pSrc + (pixelByte * blocksize),
318                     pDst + (pixelByte * pixels * 1),
319                     blocksize, textureInformation);
320 
321 			    EnBlock(pSrc + (pixelByte * blocksize * TEXTURE_BLOCK_SIZE),
322                     pDst + (pixelByte * pixels * 2),
323                     blocksize, textureInformation);
324 
325 			    EnBlock(pSrc + (pixelByte * blocksize * (TEXTURE_BLOCK_SIZE + 1)),
326                     pDst + (pixelByte * pixels * 3),
327                     blocksize, textureInformation);
328 		    }
329 		    else
330 		    {
331 			    EnBlock(pSrc,
332                     pDst + (pixelByte * pixels * 2),
333                     blocksize, textureInformation);
334 
335 			    EnBlock(pSrc + (pixelByte * blocksize),
336                     pDst + (pixelByte * pixels * 3),
337                     blocksize, textureInformation);
338 
339 			    EnBlock(pSrc + (pixelByte * blocksize * TEXTURE_BLOCK_SIZE),
340                     pDst + (pixelByte * pixels * 0),
341                     blocksize, textureInformation);
342 
343 			    EnBlock(pSrc + (pixelByte * blocksize * (TEXTURE_BLOCK_SIZE + 1)),
344                     pDst + (pixelByte * pixels * 1),
345                     blocksize, textureInformation);
346 		    }
347 
348 	    }
349 	    else
350         {
351 		    memcpy((void*)pDst, pSrc, pixelByte);
352         }
353 
354 	    return 1;
355     }
356 
SwapColorComponents(TextureInformation * textureInformation)357     static s32 SwapColorComponents(TextureInformation* textureInformation)
358     {
359         if ( textureInformation->format == GL_RGBA_NATIVE_DMP )
360         {
361 	        return convertFunctionArray[0](textureInformation);
362         }
363         else if ( textureInformation->format == GL_RGB_NATIVE_DMP )
364         {
365             return convertFunctionArray[1](textureInformation);
366         }
367         else if ( textureInformation->format == GL_LUMINANCE_ALPHA_NATIVE_DMP )
368         {
369             return convertFunctionArray[2](textureInformation);
370         }
371         else
372         {
373             return convertFunctionArray[3](textureInformation);
374         }
375     }
376 
ConvertFormat8888Function(TextureInformation * textureInformation)377     static s32 ConvertFormat8888Function(TextureInformation* textureInformation)
378     {
379     	u8 tmp;
380         u32 pixelByte = GetPixelByte(textureInformation->format);
381         s32 total = static_cast<s32>(textureInformation->width * textureInformation->height * pixelByte);
382 
383 	    for (s32 i = 0; i< total; i+= pixelByte)
384 	    {
385 		    SWAP(textureInformation->src[i + 0], textureInformation->src[i + 3]);
386 		    SWAP(textureInformation->src[i + 1], textureInformation->src[i + 2]);
387 	    }
388 
389 	    return 1;
390     }
391 
ConvertFormat888Function(TextureInformation * textureInformation)392     static s32 ConvertFormat888Function(TextureInformation* textureInformation)
393     {
394 	    u8 tmp;
395         u32 pixelByte = GetPixelByte(textureInformation->format);
396         s32 total = static_cast<s32>(textureInformation->width * textureInformation->height * pixelByte);
397 
398 	    for (s32 i = 0; i < total; i += pixelByte)
399 	    {
400 		    SWAP(textureInformation->src[i + 0], textureInformation->src[i + 2]);
401         }
402 
403 	    return 1;
404     }
405 
ConvertFormat88Function(TextureInformation * textureInformation)406     static s32 ConvertFormat88Function(TextureInformation* textureInformation)
407     {
408 	    u8 tmp;
409         u32 pixelByte = GetPixelByte(textureInformation->format);
410         s32 total = static_cast<s32>(textureInformation->width * textureInformation->height * pixelByte);
411 
412 	    for (s32 i = 0; i < total; i += pixelByte)
413 	    {
414 		    SWAP(textureInformation->src[i+0], textureInformation->src[i+1]);
415 	    }
416 
417 	    return 1;
418     }
419 
ConvertFormatXXXXFunction(TextureInformation * textureInformation)420     static s32 ConvertFormatXXXXFunction(TextureInformation* textureInformation)
421     {
422         (void)textureInformation;
423         NN_TLOG_("Unsupported texture format.");
424         NN_TASSERT_(0);
425 
426 	    return 1;
427     }
428 
429 }
430