OpenGL ES SDK for Android ARM Developer Center
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
ETCUncompressedAlpha.cpp
Go to the documentation of this file.
1 /* Copyright (c) 2013-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 
35 #include <GLES2/gl2.h>
36 #include <GLES2/gl2ext.h>
37 
38 #include <string>
39 #include <sstream>
40 
41 #include <jni.h>
42 #include <android/log.h>
43 
44 #include "ETCUncompressedAlpha.h"
45 #include "Shader.h"
46 #include "Texture.h"
47 #include "AndroidPlatform.h"
48 
49 using std::stringstream;
50 using std::string;
51 using namespace MaliSDK;
52 
53 string resourceDirectory = "/data/data/com.arm.malideveloper.openglessdk.etcuncompressedalpha/";
54 string textureFilename = "good_uncompressed_mip_";
55 string imageExtension = ".pkm";
56 string alphaExtension = "_alpha.pgm";
57 
58 string vertexShaderFilename = "ETCUncompressedAlpha_dualtex.vert";
59 string fragmentShaderFilename = "ETCUncompressedAlpha_dualtex.frag";
60 
61 /* Texture variables. */
64 
65 /* Shader variables. */
67 GLint iLocPosition = -1;
68 GLint iLocTexCoord = -1;
69 GLint iLocSampler = -1;
70 GLint iLocAlphaSampler = -1;
71 
72 /*
73  * Load uncompressed single channel alpha file.
74  *
75  * The Mali Texture Compression Tool saves uncompressed alpha in PGM format.
76  * This function reads the alpha of the original image (mipmap level 0)
77  * and then uses OpenGL ES to generate the remaining mipmap levels.
78  */
79 int loadUncompressedAlpha(const char *filename, GLuint *textureID)
80 {
81  FILE *file = fopen(filename, "rb");
82  /*
83  * Read the header. The header is text. Fields are width, height, maximum gray value.
84  * See http://netpbm.sourceforge.net/doc/pgm.html for format details.
85  */
86  unsigned int width = 0;
87  unsigned int height = 0;
88  unsigned int range = 0;
89  int readCount = fscanf(file, "P5 %d %d %d", &width, &height, &range);
90  if(readCount != 3)
91  {
92  LOGE("Error reading file header of %s", filename);
93  exit(1);
94  }
95 
96  /*
97  * We can only handle a maximum gray/alpha value of 255, as generated by
98  * the Texture Compression Tool.
99  */
100  if(range != 255)
101  {
102 
103  LOGE("Alpha file %s has wrong maximum gray value, must be 255", filename);
104  exit(1);
105  }
106 
107  /* Read and thow away the single header terminating character. */
108  fgetc(file);
109 
110  unsigned char *textureData = (unsigned char *)calloc(width * height, sizeof(unsigned char));
111  size_t result = fread(textureData, sizeof(unsigned char), width * height, file);
112  if (result != width * height)
113  {
114  LOGE("Error reading %s", filename);
115  exit(1);
116  }
117  GL_CHECK(glGenTextures(1, textureID));
118  GL_CHECK(glBindTexture(GL_TEXTURE_2D, *textureID));
119  GL_CHECK(glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, width, height, 0,GL_LUMINANCE,GL_UNSIGNED_BYTE, textureData));
120  GL_CHECK(glGenerateMipmap(GL_TEXTURE_2D));
121  free(textureData);
122 
123  return 0;
124 }
125 
126 bool setupGraphics(int w, int h)
127 {
128  LOGD("setupGraphics(%d, %d)", w, h);
129 
130  /* Full paths to the shader and texture files */
131  string texturePath = resourceDirectory + textureFilename;
132  string vertexShaderPath = resourceDirectory + vertexShaderFilename;
133  string fragmentShaderPath = resourceDirectory + fragmentShaderFilename;
134 
135  /* Initialize OpenGL ES. */
136  /* Check which formats are supported. */
137  if (!Texture::isETCSupported(true))
138  {
139  LOGE("ETC1 not supported");
140  return false;
141  };
142 
143  /* Enable alpha blending. */
144  GL_CHECK(glEnable(GL_BLEND));
145  /* Should do src * (src alpha) + dest * (1-src alpha). */
146  GL_CHECK(glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA));
147 
148  /* Initialize textures using separate files. */
149  Texture::loadCompressedMipmaps(texturePath.c_str(), imageExtension.c_str(), &textureID);
150  GL_CHECK(glActiveTexture(GL_TEXTURE1));
151  /* Use only the level 0 mipmap of the uncompressed alpha image, use OpenGL ES to generate the remaining levels */
152  loadUncompressedAlpha((texturePath + "0" + alphaExtension).c_str(), &alphaTextureID);
153 
154  /* Process shaders. */
157  Shader::processShader(&vertexShaderID, vertexShaderPath.c_str(), GL_VERTEX_SHADER);
158  LOGD("vertexShaderID = %d", vertexShaderID);
159  Shader::processShader(&fragmentShaderID, fragmentShaderPath.c_str(), GL_FRAGMENT_SHADER);
160  LOGD("fragmentShaderID = %d", fragmentShaderID);
161 
162  programID = GL_CHECK(glCreateProgram());
163  if (!programID)
164  {
165  LOGE("Could not create program.");
166  return false;
167  }
168  GL_CHECK(glAttachShader(programID, vertexShaderID));
169  GL_CHECK(glAttachShader(programID, fragmentShaderID));
170  GL_CHECK(glLinkProgram(programID));
171  GL_CHECK(glUseProgram(programID));
172 
173  /* Vertex positions. */
174  iLocPosition = GL_CHECK(glGetAttribLocation(programID, "a_v4Position"));
175  if(iLocPosition == -1)
176  {
177  LOGE("Attribute not found: \"a_v4Position\"");
178  exit(1);
179  }
180  GL_CHECK(glEnableVertexAttribArray(iLocPosition));
181 
182  /* Texture coordinates. */
183  iLocTexCoord = GL_CHECK(glGetAttribLocation(programID, "a_v2TexCoord"));
184  if(iLocTexCoord == -1)
185  {
186  LOGD("Warning: Attribute not found: \"a_v2TexCoord\"");
187  }
188  else
189  {
190  GL_CHECK(glEnableVertexAttribArray(iLocTexCoord));
191  }
192 
193  /* Set the sampler to point at the 0th texture unit. */
194  iLocSampler = GL_CHECK(glGetUniformLocation(programID, "u_s2dTexture"));
195  if(iLocSampler == -1)
196  {
197  LOGD("Warning: Uniform not found: \"u_s2dTexture\"");
198  }
199  else
200  {
201  GL_CHECK(glUniform1i(iLocSampler, 0));
202  }
203 
204  /* Set the alpha sampler to point at the 1st texture unit. */
205  iLocAlphaSampler = GL_CHECK(glGetUniformLocation(programID, "u_s2dAlpha"));
206  if(iLocAlphaSampler == -1)
207  {
208  LOGE("Uniform not found at line %i\n", __LINE__);
209  exit(1);
210  }
211  GL_CHECK(glUniform1i(iLocAlphaSampler,1));
212 
213  /* Set clear screen color. */
214  GL_CHECK(glClearColor(0.125f, 0.25f, 0.5f, 1.0));
215 
216  return true;
217 }
218 
219 void renderFrame(void)
220 {
221  GL_CHECK(glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT));
222 
223  GL_CHECK(glUseProgram(programID));
224 
225  /* Pass the plane vertices to the shader. */
226  GL_CHECK(glVertexAttribPointer(iLocPosition, 3, GL_FLOAT, GL_FALSE, 0, vertices));
227  GL_CHECK(glEnableVertexAttribArray(iLocPosition));
228 
229  if(iLocTexCoord != -1)
230  {
231  /* Pass the texture coordinates to the shader. */
232  GL_CHECK(glVertexAttribPointer(iLocTexCoord, 2, GL_FLOAT, GL_FALSE, 0, textureCoordinates));
233  GL_CHECK(glEnableVertexAttribArray(iLocTexCoord));
234  }
235 
236  /* Draw the plane. */
237  GL_CHECK(glDrawElements(GL_TRIANGLE_STRIP, sizeof(indices) / sizeof(GLubyte), GL_UNSIGNED_BYTE, indices));
238 }
239 
240 extern "C"
241 {
243  (JNIEnv *env, jclass jcls, jint width, jint height)
244  {
245  /* Make sure that all resource files are in place. */
248 
249  /* Load all image assets from 0 to 8 */
250  string texturePathFull = textureFilename + "0" + imageExtension;
251  int numberOfImages = 9;
252  for(int allImages = 0; allImages < numberOfImages; allImages++)
253  {
254  stringstream imageNumber;
255  imageNumber << allImages;
256  texturePathFull.replace(textureFilename.length(), 1, imageNumber.str());
257  AndroidPlatform::getAndroidAsset(env, resourceDirectory.c_str(), texturePathFull.c_str());
258  }
259  /* Load the uncompressed alpha image. */
260  AndroidPlatform::getAndroidAsset(env, resourceDirectory.c_str(), (textureFilename + "0_alpha.pgm").c_str());
261 
262  setupGraphics(width, height);
263  }
264 
266  (JNIEnv *env, jclass jcls)
267  {
268  renderFrame();
269  }
270 
272  (JNIEnv *, jclass)
273  {
274 
275  }
276 }
GLint iLocTexCoord
int loadUncompressedAlpha(const char *filename, GLuint *textureID)
GLsizei range
Definition: gl2ext.h:2467
string fragmentShaderFilename
GLint GLsizei GLsizei height
Definition: gl2ext.h:179
const float vertices[]
Definition: Cube.h:30
string textureFilename
void renderFrame(void)
GLuint fragmentShaderID
bool setupGraphics(int w, int h)
GLuint alphaTextureID
#define LOGD(...)
Definition: AstcTextures.h:28
JNIEXPORT void JNICALL Java_com_arm_malideveloper_openglessdk_etcuncompressedalpha_ETCUncompressedAlpha_step(JNIEnv *env, jclass jcls)
JNIEXPORT void JNICALL Java_com_arm_malideveloper_openglessdk_etcuncompressedalpha_ETCUncompressedAlpha_uninit(JNIEnv *, jclass)
GLuint programID
string resourceDirectory
string vertexShaderFilename
GLfloat GLfloat GLfloat w
Definition: gl2ext.h:2701
GLsizei GLenum const void * indices
Definition: gl2ext.h:322
JNIEXPORT void JNICALL Java_com_arm_malideveloper_openglessdk_etcuncompressedalpha_ETCUncompressedAlpha_init(JNIEnv *env, jclass jcls, jint width, jint height)
static void loadCompressedMipmaps(const char *filenameBase, const char *filenameSuffix, GLuint *textureID)
Load compressed mipmaps into memory.
Definition: Texture.cpp:232
GLfloat GLfloat f
Definition: gl2ext.h:2707
GLfloat GLfloat GLfloat GLfloat h
Definition: gl2ext.h:2701
GLint iLocPosition
#define GL_CHECK(x)
Definition: AstcTextures.h:59
unsigned char * textureData
Definition: ThreadSync.cpp:109
static bool getAndroidAsset(JNIEnv *JNIEnvironment, const char destinationDirectory[], const char filename[])
Extract an asset file from the APK.
GLint iLocSampler
GLuint vertexShaderID
#define LOGE(...)
Definition: AstcTextures.h:30
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
static void processShader(GLuint *shader, const char *filename, GLint shaderType)
Create shader, load in source, compile, and dump debug as necessary.
Definition: Shader.cpp:29
typedef GLuint(GL_APIENTRYP PFNGLGETDEBUGMESSAGELOGKHRPROC)(GLuint count
GLuint textureID
static const GLfloat textureCoordinates[]
Definition: ETCAtlasAlpha.h:97
string imageExtension
GLint iLocAlphaSampler
string alphaExtension