DALi Version 1.3.0
[platform/core/uifw/dali-demo.git] / examples / rendering-basic-pbr / ktx-loader.cpp
1 /*
2  * Copyright (c) 2017 Samsung Electronics Co., Ltd.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  *
16  */
17
18 // FILE HEADER
19 #include "ktx-loader.h"
20
21 // EXTERNAL INCLUDES
22 #include <memory.h>
23 #include <stdio.h>
24 #include <stdint.h>
25
26 namespace PbrDemo
27 {
28
29 struct KtxFileHeader
30 {
31   char   identifier[12];
32   uint32_t  endianness;
33   uint32_t  glType;    //(UNSIGNED_BYTE, UNSIGNED_SHORT_5_6_5, etc.)
34   uint32_t  glTypeSize;
35   uint32_t  glFormat;  //(RGB, RGBA, BGRA, etc.)
36   uint32_t  glInternalFormat; //For uncompressed textures, specifies the internalformat parameter passed to glTexStorage*D or glTexImage*D
37   uint32_t  glBaseInternalFormat;
38   uint32_t  pixelWidth;
39   uint32_t  pixelHeight;
40   uint32_t  pixelDepth;
41   uint32_t  numberOfArrayElements;
42   uint32_t  numberOfFaces; //Cube map faces are stored in the order: +X, -X, +Y, -Y, +Z, -Z.
43   uint32_t  numberOfMipmapLevels;
44   uint32_t  bytesOfKeyValueData;
45 };
46
47 /**
48  * Convert KTX format to Dali::Pixel::Format
49  */
50 bool ConvertPixelFormat(const uint32_t ktxPixelFormat, Dali::Pixel::Format& format)
51 {
52   switch( ktxPixelFormat )
53   {
54     case 0x93B0: // GL_COMPRESSED_RGBA_ASTC_4x4_KHR
55     {
56       format = Dali::Pixel::COMPRESSED_RGBA_ASTC_4x4_KHR;
57       break;
58     }
59     case 0x881B:// GL_RGB16F
60     {
61       format = Dali::Pixel::RGB16F;
62       break;
63     }
64     case 0x8815: // GL_RGB32F
65     {
66       format = Dali::Pixel::RGB32F;
67       break;
68     }
69     case 0x8C3A: // GL_R11F_G11F_B10F
70     {
71       format = Dali::Pixel::RGB32F;
72       break;
73     }
74     case 0x8D7C: // GL_RGBA8UI
75     {
76       format = Dali::Pixel::RGBA8888;
77       break;
78     }
79     case 0x8D7D: // GL_RGB8UI
80     {
81       format = Dali::Pixel::RGB888;
82       break;
83     }
84     default:
85     {
86       return false;
87     }
88   }
89
90   return true;
91 }
92
93 bool LoadCubeMapFromKtxFile( const std::string& path, CubeData& cubedata )
94 {
95   FILE* fp = fopen(path.c_str(),"rb");
96
97   if( NULL == fp )
98   {
99     return false;
100   }
101
102   KtxFileHeader header;
103
104   int result = fread(&header,1,sizeof(KtxFileHeader),fp);
105   if( 0 == result )
106   {
107     return false;
108   }
109
110   long lSize = 0;
111
112   // Skip the key-values:
113   const long int imageSizeOffset = sizeof(KtxFileHeader) + header.bytesOfKeyValueData;
114
115   fseek(fp, imageSizeOffset, SEEK_END);
116   lSize = ftell(fp);
117   rewind(fp);
118
119   if(fseek(fp, imageSizeOffset, SEEK_SET))
120   {
121     return false;
122   }
123   cubedata.img.resize(header.numberOfFaces);
124
125   for(unsigned int face=0; face < header.numberOfFaces; ++face) //array_element must be 0 or 1
126   {
127     cubedata.img[face].resize(header.numberOfMipmapLevels);
128   }
129
130   unsigned char* buffer= reinterpret_cast<unsigned char*>( malloc( lSize ) );
131
132   unsigned char* img[6];
133   unsigned int imgSize[6];
134   unsigned char* imgPointer = buffer;
135   result = fread(buffer,1,lSize,fp);
136   if( 0 == result )
137   {
138     return false;
139   }
140
141   fclose(fp);
142
143   if( 0 == header.numberOfMipmapLevels )
144   {
145     header.numberOfMipmapLevels = 1u;
146   }
147
148   if( 0 == header.numberOfArrayElements )
149   {
150     header.numberOfArrayElements = 1u;
151   }
152
153   if( 0 == header.pixelDepth )
154   {
155     header.pixelDepth = 1u;
156   }
157
158   if( 0 == header.pixelHeight )
159   {
160     header.pixelHeight = 1u;
161   }
162
163   Dali::Pixel::Format daliformat = Pixel::RGB888;
164
165   ConvertPixelFormat(header.glInternalFormat, daliformat);
166
167   for( unsigned int mipmapLevel = 0; mipmapLevel < header.numberOfMipmapLevels; ++mipmapLevel )
168   {
169     long int byteSize = 0;
170     int imageSize;
171     memcpy(&imageSize,imgPointer,sizeof(unsigned int));
172     imgPointer += 4u;
173     for(unsigned int arrayElement=0; arrayElement < header.numberOfArrayElements; ++arrayElement) //arrayElement must be 0 or 1
174     {
175       for(unsigned int face=0; face < header.numberOfFaces; ++face)
176       {
177         byteSize = imageSize;
178         if(byteSize % 4u)
179         {
180           byteSize += 4u - byteSize % 4u;
181         }
182         img[face] = reinterpret_cast<unsigned char*>( malloc( byteSize ) ); // resources will be freed when the PixelData is destroyed.
183         memcpy(img[face],imgPointer,byteSize);
184         imgSize[face] = byteSize;
185         imgPointer += byteSize;
186         cubedata.img[face][mipmapLevel] = PixelData::New( img[face], imgSize[face], header.pixelWidth , header.pixelHeight , daliformat, PixelData::FREE );
187       }
188     }
189     header.pixelHeight/=2u;
190     header.pixelWidth/=2u;
191   }
192
193   free(buffer);
194   return true;
195 }
196
197 } // namespace PbrDemo