OpenGL ES SDK for Android ARM Developer Center
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
Texture.cpp
Go to the documentation of this file.
1 /* Copyright (c) 2012-2017, ARM Limited and Contributors
2  *
3  * SPDX-License-Identifier: MIT
4  *
5  * Permission is hereby granted, free of charge,
6  * to any person obtaining a copy of this software and associated documentation files (the "Software"),
7  * to deal in the Software without restriction, including without limitation the rights to
8  * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
9  * and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
10  *
11  * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
12  *
13  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
14  * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
16  * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
17  * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
19  */
20 
21 #include "Texture.h"
22 #include "ETCHeader.h"
23 #include "Platform.h"
24 
25 #if GLES_VERSION == 2
26 #include <GLES2/gl2ext.h>
27 #endif
28 
29 #include <cstdio>
30 #include <cstdlib>
31 #include <cstring>
32 #include <string>
33 
34 using std::string;
35 
36 namespace MaliSDK
37 {
38  void Texture::getCompressedTextureFormats(GLint** textureFormats, int* numberOfTextureFormats)
39  {
40  GL_CHECK(glGetIntegerv(GL_NUM_COMPRESSED_TEXTURE_FORMATS, numberOfTextureFormats));
41 
42  *textureFormats = (GLint *)calloc(*numberOfTextureFormats, sizeof(GLint));
43  if(*textureFormats == NULL)
44  {
45  LOGE("Out of memory at %s:%i\n", __FILE__, __LINE__);
46  exit(1);
47  }
48 
49  GL_CHECK(glGetIntegerv(GL_COMPRESSED_TEXTURE_FORMATS, *textureFormats));
50  }
51 
52 #if GLES_VERSION == 2
53  bool Texture::isETCSupported(bool verbose)
54  {
55  bool supportETC = false;
56  GLint *textureFormat = NULL;
57  GLint numberOfTextureFormats = 0;
58  getCompressedTextureFormats(&textureFormat, &numberOfTextureFormats);
59 
60  if (verbose != 0)
61  {
62  LOGI("Number of texture formats supported: %d\nFormats:\n", numberOfTextureFormats);
63  for(int allTextureFormats = 0; allTextureFormats < numberOfTextureFormats; allTextureFormats++)
64  {
65  LOGI("0x%.8x\t", textureFormat[allTextureFormats]);
66  switch(textureFormat[allTextureFormats])
67  {
68  case GL_ETC1_RGB8_OES:
69  LOGI("GL_ETC1_RGB8_OES\n");
70  break;
71  default:
72  LOGI("UNKNOWN\n");
73  break;
74  }
75  }
76  }
77 
78  for(int allTextureFormats = 0; allTextureFormats < numberOfTextureFormats; allTextureFormats++)
79  {
80  if (textureFormat[allTextureFormats] == GL_ETC1_RGB8_OES)
81  {
82  supportETC = true;
83  }
84  }
85 
86  free(textureFormat);
87  textureFormat = NULL;
88 
89  if(!supportETC)
90  {
91  LOGD("Texture compression format GL_ETC1_RGB8_OES not supported\n");
92  }
93  return supportETC;
94  }
95 #elif GLES_VERSION == 3
96  bool Texture::isETCSupported(bool verbose)
97  {
98  /* TODO */
99  return true;
100  }
101 #endif
102 
103  void Texture::createTexture(unsigned int width, unsigned int height, GLvoid **textureData)
104  {
105  unsigned char *randomTexture = new unsigned char [width * height * 4];
106  if(randomTexture == NULL)
107  {
108  LOGE("Out of memory at %s:%i\n", __FILE__, __LINE__);
109  exit(1);
110  }
111 
112  /* Initialize texture with random shades. */
113  for(unsigned int allTexels = 0; allTexels < width * height; allTexels ++)
114  {
115  /* Use 255 (fully opaque) for the alpha value */
116  randomTexture[allTexels * 4 + 3] = 255;
117  /* Set each colour component (Red, Green, Blue) of the texel to a different random number. */
118  for (int allChannels = 0; allChannels < 3; allChannels++)
119  {
120  /* Generate a random number between 0 and 255 */
121  int randomNumber = (int)(255 * (rand() / (float)RAND_MAX));
122  randomTexture[allTexels * 4 + allChannels] = randomNumber;
123  }
124  }
125 
126  *textureData = randomTexture;
127  }
128 
129  void Texture::createTexture(unsigned int width, unsigned int height, unsigned int red, GLvoid **textureData)
130  {
131  unsigned char* newTexture = new unsigned char [width * height];
132 
133  if(newTexture == NULL)
134  {
135  LOGE("Out of memory at %s:%i\n", __FILE__, __LINE__);
136  exit(1);
137  }
138 
139  for (unsigned int texelIndex = 0; texelIndex < width * height; ++texelIndex)
140  {
141  newTexture[texelIndex] = red;
142  }
143  *textureData = newTexture;
144  }
145 
146  void Texture::createTexture(unsigned int width, unsigned int height, short red, short **textureData)
147  {
148  *textureData = new short [width * height];
149 
150  if (*textureData == NULL)
151  {
152  LOGE("Out of memory at %s:%i\n", __FILE__, __LINE__);
153  exit(1);
154  }
155 
156  for (unsigned int texelIndex = 0; texelIndex < width * height; ++texelIndex)
157  {
158  (*textureData)[texelIndex] = red;
159  }
160  }
161 
163  {
164  delete[] (unsigned char*)*textureData;
165  }
166 
167  void Texture::loadData(const char *filename, unsigned char **textureData)
168  {
169  LOGD("Texture loadData started for %s...\n", filename);
170 
171  FILE *file = fopen(filename, "rb");
172  if(file == NULL)
173  {
174  LOGE("Failed to open '%s'\n", filename);
175  exit(1);
176  }
177  fseek(file, 0, SEEK_END);
178  unsigned int length = ftell(file);
179  unsigned char *loadedTexture = (unsigned char *)calloc(length, sizeof(unsigned char));
180  if(loadedTexture == NULL)
181  {
182  LOGE("Out of memory at %s:%i\n", __FILE__, __LINE__);
183  exit(1);
184  }
185  fseek(file, 0, SEEK_SET);
186  size_t read = fread(loadedTexture, sizeof(unsigned char), length, file);
187  if(read != length)
188  {
189  LOGE("Failed to read in '%s'\n", filename);
190  exit(1);
191  }
192  fclose(file);
193 
194  *textureData = loadedTexture;
195 
196  LOGD("Texture loadData for %s done.\n", filename);
197  }
198 
199  void Texture::loadPKMData(const char *filename, ETCHeader* etcHeader, unsigned char **textureData)
200  {
201  /* PKM file consists of a header with information about image (stored in 16 first bits) and image data. */
202  const int sizeOfETCHeader = 16;
203  unsigned char* tempTextureData = NULL;
204 
205  loadData(filename, &tempTextureData);
206 
207  if (textureData == NULL)
208  {
209  LOGE("textureData is a NULL pointer.");
210  exit(1);
211  }
212  if (etcHeader == NULL)
213  {
214  LOGE("etcHeader is a NULL pointer.");
215  exit(1);
216  }
217 
218  if (tempTextureData != NULL)
219  {
220  ETCHeader tempEtcHeader(tempTextureData);
221 
222  *etcHeader = tempEtcHeader;
223  *textureData = tempTextureData + sizeOfETCHeader;
224  }
225  else
226  {
227  LOGE("Could not load data from file %s.", filename);
228  exit(1);
229  }
230  }
231 
232  void Texture::loadCompressedMipmaps(const char *filenameBase, const char *filenameSuffix, GLuint *textureID)
233  {
234  /* Allocate texture name. */
235  GL_CHECK(glGenTextures(1, textureID));
236  GL_CHECK(glBindTexture(GL_TEXTURE_2D, *textureID));
237 
238  /* Load base level Mipmap. */
239  /* Construct filename, load and tidy up. */
240  string filename = filenameBase + string("0") + filenameSuffix;
241  unsigned char *data = NULL;
242  loadData(filename.c_str(), &data);
243  ETCHeader loadedETCHeader = ETCHeader(data);
244 
245  /* Calculate number of Mipmap levels. */
246  LOGD("Base level Mipmap loaded: (%i, %i) padded to 4x4 blocks, (%i, %i) actual\n", loadedETCHeader.getPaddedWidth(), loadedETCHeader.getPaddedHeight(), loadedETCHeader.getWidth(), loadedETCHeader.getHeight());
247  int width = loadedETCHeader.getWidth();
248  int height = loadedETCHeader.getHeight();
249  int numberOfMipmaps = 1;
250  while((width > 1) || (height > 1))
251  {
252  numberOfMipmaps ++;
253  if(width > 1) width >>= 1;
254  if(height > 1) height >>= 1;
255  }
256  LOGD("Requires %i Mipmap levels in total\n", numberOfMipmaps);
257 
258  /* Load base Mipmap level into level 0 of texture.
259  * Skip the 16 byte header of the PKM file before passing the data to OpenGL ES.
260  * Data size (taken in number of bytes) of the texture is:
261  * Number of pixels = padded width * padded height.
262  * The number of pixels is divided by two as there are 4 bits per pixel in ETC (half a byte)
263  */
264 #if GLES_VERSION == 2
265  GL_CHECK(glCompressedTexImage2D(GL_TEXTURE_2D, 0, GL_ETC1_RGB8_OES, loadedETCHeader.getWidth(), loadedETCHeader.getHeight(), 0, (loadedETCHeader.getPaddedWidth() * loadedETCHeader.getPaddedHeight()) >> 1, data + 16));
266 #elif GLES_VERSION == 3
267  /* TODO */
268 #endif
269  free(data);
270  data = NULL;
271 
272  /* Load other levels. */
273  for(int allMipmaps = 1; allMipmaps < numberOfMipmaps; allMipmaps++)
274  {
275  /* Construct filename, load and tidy up. */
276  char *level = NULL;
277  int input = allMipmaps;
278  int inputLength = 0;
279 
280  /* Calculate the string length of the Mipmap level number (no snprintf in ANSI C). */
281  do
282  {
283  input /= 10;
284  inputLength ++;
285  }
286  while(input != 0);
287 
288  level = (char *)calloc(inputLength + 1, sizeof(char));
289  if(level == NULL)
290  {
291  LOGE("Out of memory at %s:%i\n", __FILE__, __LINE__);
292  exit(1);
293  }
294  sprintf(level, "%i", allMipmaps);
295 
296  filename = filenameBase + string(level) + filenameSuffix;
297  loadData(filename.c_str(), &data);
298  free(level);
299  level = NULL;
300  loadedETCHeader = ETCHeader(data);
301 
302  /* Load Mipmap level into texture.
303  * Skip the 16 byte header of the PKM file before passing the data to OpenGL ES.
304  * Data size (taken in number of bytes) of the texture is:
305  * Number of pixels = padded width * padded height.
306  * The number of pixels is divided by two as there are 4 bits per pixel in ETC (half a byte)
307  */
308 #if GLES_VERSION == 2
309  GL_CHECK(glCompressedTexImage2D(GL_TEXTURE_2D, allMipmaps, GL_ETC1_RGB8_OES, loadedETCHeader.getWidth(), loadedETCHeader.getHeight(), 0, (loadedETCHeader.getPaddedWidth() * loadedETCHeader.getPaddedHeight()) >> 1, data + 16));
310 #elif GLES_VERSION == 3
311  /* TODO */
312 #endif
313  free(data);
314  data = NULL;
315  }
316  }
317 
318  void Texture::reversePixelLine(float* destination, const float* source, int lineWidth)
319  {
320  const int rgbComponentsCount = 3;
321 
322  for (int pixelIndex = 0; pixelIndex < lineWidth; ++pixelIndex)
323  {
324  memcpy(destination + pixelIndex * rgbComponentsCount,
325  source + (lineWidth - pixelIndex - 1) * rgbComponentsCount,
326  rgbComponentsCount * sizeof(float));
327  }
328  }
329 }
static void loadPKMData(const char *filename, ETCHeader *etcHeader, unsigned char **textureData)
Load header and texture data from a pkm file into memory.
Definition: Texture.cpp:199
GLuint textureID
const int rgbComponentsCount
Definition: HDRImage.cpp:40
static void createTexture(unsigned int width, unsigned int height, GLvoid **textureData)
Create a texture using random data.
Definition: Texture.cpp:103
Class to extract information from the ETC headers of compressed textures.
Definition: ETCHeader.h:38
const GLenum textureFormats[]
GLint GLsizei GLsizei height
Definition: gl2ext.h:179
#define LOGI(...)
Definition: Texture.cpp:31
static void getCompressedTextureFormats(GLint **textureFormats, int *numberOfTextureFormats)
Uses glGetIntegerv to get the number of compressed texture formats and the formats themselves...
Definition: Texture.cpp:38
precision highp int
Definition: hiz_cull.cs:38
#define LOGD(...)
Definition: AstcTextures.h:28
GLint GLsizei GLsizei GLenum GLenum GLsizei void * data
Definition: gl2ext.h:179
static void deleteTextureData(GLvoid **textureData)
Deletes previously created texture.
Definition: Texture.cpp:162
GLsizei GLsizei GLchar * source
Definition: gl2ext.h:877
static void loadCompressedMipmaps(const char *filenameBase, const char *filenameSuffix, GLuint *textureID)
Load compressed mipmaps into memory.
Definition: Texture.cpp:232
static void reversePixelLine(float *destination, const float *source, int lineWidth)
Copies float pixel data of one line of the image from source to destination in the reverse direction...
Definition: Texture.cpp:318
#define GL_CHECK(x)
Definition: AstcTextures.h:59
unsigned char * textureData
Definition: ThreadSync.cpp:109
#define LOGE(...)
Definition: Texture.cpp:32
static void loadData(const char *filename, unsigned char **textureData)
Load texture data from a file into memory.
Definition: Texture.cpp:167
#define GL_ETC1_RGB8_OES
Definition: gl2ext.h:257
GLenum GLuint GLenum GLsizei length
Definition: gl2ext.h:134
GLenum GLuint GLint level
Definition: gl2ext.h:385
GLint GLsizei width
Definition: gl2ext.h:179
static bool isETCSupported(bool verbose=false)
Reports whether or not ETC (Ericsson Texture Compression) is supported.
Definition: Texture.cpp:46
typedef GLuint(GL_APIENTRYP PFNGLGETDEBUGMESSAGELOGKHRPROC)(GLuint count