xref: /aosp_15_r20/cts/tests/openglperf2/jni/graphics/GLUtils.cpp (revision b7c941bb3fa97aba169d73cee0bed2de8ac964bf)
1*b7c941bbSAndroid Build Coastguard Worker /*
2*b7c941bbSAndroid Build Coastguard Worker  * Copyright (C) 2013 The Android Open Source Project
3*b7c941bbSAndroid Build Coastguard Worker  *
4*b7c941bbSAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
5*b7c941bbSAndroid Build Coastguard Worker  * in compliance with the License. You may obtain a copy of the License at
6*b7c941bbSAndroid Build Coastguard Worker  *
7*b7c941bbSAndroid Build Coastguard Worker  * http://www.apache.org/licenses/LICENSE-2.0
8*b7c941bbSAndroid Build Coastguard Worker  *
9*b7c941bbSAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software distributed under the License
10*b7c941bbSAndroid Build Coastguard Worker  * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
11*b7c941bbSAndroid Build Coastguard Worker  * or implied. See the License for the specific language governing permissions and limitations under
12*b7c941bbSAndroid Build Coastguard Worker  * the License.
13*b7c941bbSAndroid Build Coastguard Worker  */
14*b7c941bbSAndroid Build Coastguard Worker 
15*b7c941bbSAndroid Build Coastguard Worker #include "GLUtils.h"
16*b7c941bbSAndroid Build Coastguard Worker #include <stdlib.h>
17*b7c941bbSAndroid Build Coastguard Worker #include <sys/time.h>
18*b7c941bbSAndroid Build Coastguard Worker 
19*b7c941bbSAndroid Build Coastguard Worker #include <android/asset_manager_jni.h>
20*b7c941bbSAndroid Build Coastguard Worker 
21*b7c941bbSAndroid Build Coastguard Worker #define LOG_TAG "CTS_OPENGL"
22*b7c941bbSAndroid Build Coastguard Worker #define LOG_NDEBUG 0
23*b7c941bbSAndroid Build Coastguard Worker #include <android/log.h>
24*b7c941bbSAndroid Build Coastguard Worker 
25*b7c941bbSAndroid Build Coastguard Worker static JNIEnv* sEnv = NULL;
26*b7c941bbSAndroid Build Coastguard Worker static jobject sAssetManager = NULL;
27*b7c941bbSAndroid Build Coastguard Worker 
setEnvAndAssetManager(JNIEnv * env,jobject assetManager)28*b7c941bbSAndroid Build Coastguard Worker void GLUtils::setEnvAndAssetManager(JNIEnv* env, jobject assetManager) {
29*b7c941bbSAndroid Build Coastguard Worker     sEnv = env;
30*b7c941bbSAndroid Build Coastguard Worker     sAssetManager = assetManager;
31*b7c941bbSAndroid Build Coastguard Worker }
32*b7c941bbSAndroid Build Coastguard Worker 
loadAsset(const char * path)33*b7c941bbSAndroid Build Coastguard Worker static AAsset* loadAsset(const char* path) {
34*b7c941bbSAndroid Build Coastguard Worker     AAssetManager* nativeManager = AAssetManager_fromJava(sEnv, sAssetManager);
35*b7c941bbSAndroid Build Coastguard Worker     if (nativeManager == NULL) {
36*b7c941bbSAndroid Build Coastguard Worker         return NULL;
37*b7c941bbSAndroid Build Coastguard Worker     }
38*b7c941bbSAndroid Build Coastguard Worker     return AAssetManager_open(nativeManager, path, AASSET_MODE_UNKNOWN);;
39*b7c941bbSAndroid Build Coastguard Worker }
40*b7c941bbSAndroid Build Coastguard Worker 
openTextFile(const char * path)41*b7c941bbSAndroid Build Coastguard Worker char* GLUtils::openTextFile(const char* path) {
42*b7c941bbSAndroid Build Coastguard Worker     AAsset* asset = loadAsset(path);
43*b7c941bbSAndroid Build Coastguard Worker     if (asset == NULL) {
44*b7c941bbSAndroid Build Coastguard Worker         __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, "Couldn't load %s", path);
45*b7c941bbSAndroid Build Coastguard Worker         return NULL;
46*b7c941bbSAndroid Build Coastguard Worker     }
47*b7c941bbSAndroid Build Coastguard Worker     off_t length = AAsset_getLength(asset);
48*b7c941bbSAndroid Build Coastguard Worker     char* buffer = new char[length + 1];
49*b7c941bbSAndroid Build Coastguard Worker     int num = AAsset_read(asset, buffer, length);
50*b7c941bbSAndroid Build Coastguard Worker     AAsset_close(asset);
51*b7c941bbSAndroid Build Coastguard Worker     if (num != length) {
52*b7c941bbSAndroid Build Coastguard Worker         __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, "Couldn't read %s", path);
53*b7c941bbSAndroid Build Coastguard Worker         delete[] buffer;
54*b7c941bbSAndroid Build Coastguard Worker         return NULL;
55*b7c941bbSAndroid Build Coastguard Worker     }
56*b7c941bbSAndroid Build Coastguard Worker     buffer[length] = '\0';
57*b7c941bbSAndroid Build Coastguard Worker     return buffer;
58*b7c941bbSAndroid Build Coastguard Worker }
59*b7c941bbSAndroid Build Coastguard Worker 
loadTexture(const char * path)60*b7c941bbSAndroid Build Coastguard Worker GLuint GLUtils::loadTexture(const char* path) {
61*b7c941bbSAndroid Build Coastguard Worker     GLuint textureId = 0;
62*b7c941bbSAndroid Build Coastguard Worker     jclass activityClass = sEnv->FindClass("android/opengl2/cts/reference/GLGameActivity");
63*b7c941bbSAndroid Build Coastguard Worker     if (activityClass == NULL) {
64*b7c941bbSAndroid Build Coastguard Worker         __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, "Couldn't find activity class");
65*b7c941bbSAndroid Build Coastguard Worker         return -1;
66*b7c941bbSAndroid Build Coastguard Worker     }
67*b7c941bbSAndroid Build Coastguard Worker     jmethodID loadTexture = sEnv->GetStaticMethodID(activityClass, "loadTexture",
68*b7c941bbSAndroid Build Coastguard Worker             "(Landroid/content/res/AssetManager;Ljava/lang/String;)I");
69*b7c941bbSAndroid Build Coastguard Worker     if (loadTexture == NULL) {
70*b7c941bbSAndroid Build Coastguard Worker         __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, "Couldn't find loadTexture method");
71*b7c941bbSAndroid Build Coastguard Worker         return -1;
72*b7c941bbSAndroid Build Coastguard Worker     }
73*b7c941bbSAndroid Build Coastguard Worker     jstring pathStr = sEnv->NewStringUTF(path);
74*b7c941bbSAndroid Build Coastguard Worker     textureId = sEnv->CallStaticIntMethod(activityClass, loadTexture, sAssetManager, pathStr);
75*b7c941bbSAndroid Build Coastguard Worker     sEnv->DeleteLocalRef(pathStr);
76*b7c941bbSAndroid Build Coastguard Worker     return textureId;
77*b7c941bbSAndroid Build Coastguard Worker }
78*b7c941bbSAndroid Build Coastguard Worker 
readInt(char * b)79*b7c941bbSAndroid Build Coastguard Worker static int readInt(char* b) {
80*b7c941bbSAndroid Build Coastguard Worker     unsigned char* ub = (unsigned char*) b;
81*b7c941bbSAndroid Build Coastguard Worker     return (((int) ub[0]) << 24) | (((int) ub[1]) << 16) | (((int) ub[2]) << 8) | ((int) ub[3]);
82*b7c941bbSAndroid Build Coastguard Worker }
83*b7c941bbSAndroid Build Coastguard Worker 
readFloat(char * b)84*b7c941bbSAndroid Build Coastguard Worker static float readFloat(char* b) {
85*b7c941bbSAndroid Build Coastguard Worker     union {
86*b7c941bbSAndroid Build Coastguard Worker         int input;
87*b7c941bbSAndroid Build Coastguard Worker         float output;
88*b7c941bbSAndroid Build Coastguard Worker     } data;
89*b7c941bbSAndroid Build Coastguard Worker     data.input = readInt(b);
90*b7c941bbSAndroid Build Coastguard Worker     return data.output;
91*b7c941bbSAndroid Build Coastguard Worker }
92*b7c941bbSAndroid Build Coastguard Worker 
loadMesh(const char * path)93*b7c941bbSAndroid Build Coastguard Worker Mesh* GLUtils::loadMesh(const char* path) {
94*b7c941bbSAndroid Build Coastguard Worker     char* buffer = openTextFile(path);
95*b7c941bbSAndroid Build Coastguard Worker     if (buffer == NULL) {
96*b7c941bbSAndroid Build Coastguard Worker         return NULL;
97*b7c941bbSAndroid Build Coastguard Worker     }
98*b7c941bbSAndroid Build Coastguard Worker     int index = 0;
99*b7c941bbSAndroid Build Coastguard Worker     int numVertices = readInt(buffer + index);
100*b7c941bbSAndroid Build Coastguard Worker     index += 4;
101*b7c941bbSAndroid Build Coastguard Worker     float* vertices = new float[numVertices * 3];
102*b7c941bbSAndroid Build Coastguard Worker     float* normals = new float[numVertices * 3];
103*b7c941bbSAndroid Build Coastguard Worker     float* texCoords = new float[numVertices * 2];
104*b7c941bbSAndroid Build Coastguard Worker     for (int i = 0; i < numVertices; i++) {
105*b7c941bbSAndroid Build Coastguard Worker         // Vertices
106*b7c941bbSAndroid Build Coastguard Worker         int vIndex = i * 3;
107*b7c941bbSAndroid Build Coastguard Worker         vertices[vIndex + 0] = readFloat(buffer + index);
108*b7c941bbSAndroid Build Coastguard Worker         index += 4;
109*b7c941bbSAndroid Build Coastguard Worker         vertices[vIndex + 1] = readFloat(buffer + index);
110*b7c941bbSAndroid Build Coastguard Worker         index += 4;
111*b7c941bbSAndroid Build Coastguard Worker         vertices[vIndex + 2] = readFloat(buffer + index);
112*b7c941bbSAndroid Build Coastguard Worker         index += 4;
113*b7c941bbSAndroid Build Coastguard Worker         // Normals
114*b7c941bbSAndroid Build Coastguard Worker         normals[vIndex + 0] = readFloat(buffer + index);
115*b7c941bbSAndroid Build Coastguard Worker         index += 4;
116*b7c941bbSAndroid Build Coastguard Worker         normals[vIndex + 1] = readFloat(buffer + index);
117*b7c941bbSAndroid Build Coastguard Worker         index += 4;
118*b7c941bbSAndroid Build Coastguard Worker         normals[vIndex + 2] = readFloat(buffer + index);
119*b7c941bbSAndroid Build Coastguard Worker         index += 4;
120*b7c941bbSAndroid Build Coastguard Worker         // Texture Coordinates
121*b7c941bbSAndroid Build Coastguard Worker         int tIndex = i * 2;
122*b7c941bbSAndroid Build Coastguard Worker         texCoords[tIndex + 0] = readFloat(buffer + index);
123*b7c941bbSAndroid Build Coastguard Worker         index += 4;
124*b7c941bbSAndroid Build Coastguard Worker         texCoords[tIndex + 1] = readFloat(buffer + index);
125*b7c941bbSAndroid Build Coastguard Worker         index += 4;
126*b7c941bbSAndroid Build Coastguard Worker     }
127*b7c941bbSAndroid Build Coastguard Worker     return new Mesh(vertices, normals, texCoords, numVertices);
128*b7c941bbSAndroid Build Coastguard Worker }
129*b7c941bbSAndroid Build Coastguard Worker 
130*b7c941bbSAndroid Build Coastguard Worker // Loads the given source code as a shader of the given type.
loadShader(GLenum shaderType,const char ** source)131*b7c941bbSAndroid Build Coastguard Worker static GLuint loadShader(GLenum shaderType, const char** source) {
132*b7c941bbSAndroid Build Coastguard Worker     GLuint shader = glCreateShader(shaderType);
133*b7c941bbSAndroid Build Coastguard Worker     if (shader) {
134*b7c941bbSAndroid Build Coastguard Worker         glShaderSource(shader, 1, source, NULL);
135*b7c941bbSAndroid Build Coastguard Worker         glCompileShader(shader);
136*b7c941bbSAndroid Build Coastguard Worker         GLint compiled = 0;
137*b7c941bbSAndroid Build Coastguard Worker         glGetShaderiv(shader, GL_COMPILE_STATUS, &compiled);
138*b7c941bbSAndroid Build Coastguard Worker         if (!compiled) {
139*b7c941bbSAndroid Build Coastguard Worker             GLint infoLen = 0;
140*b7c941bbSAndroid Build Coastguard Worker             glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &infoLen);
141*b7c941bbSAndroid Build Coastguard Worker             if (infoLen > 0) {
142*b7c941bbSAndroid Build Coastguard Worker                 char* infoLog = (char*) malloc(sizeof(char) * infoLen);
143*b7c941bbSAndroid Build Coastguard Worker                 glGetShaderInfoLog(shader, infoLen, NULL, infoLog);
144*b7c941bbSAndroid Build Coastguard Worker                 __android_log_print(ANDROID_LOG_ERROR, LOG_TAG,
145*b7c941bbSAndroid Build Coastguard Worker                                     "Error compiling shader:\n%s\n", infoLog);
146*b7c941bbSAndroid Build Coastguard Worker                 free(infoLog);
147*b7c941bbSAndroid Build Coastguard Worker             }
148*b7c941bbSAndroid Build Coastguard Worker             glDeleteShader(shader);
149*b7c941bbSAndroid Build Coastguard Worker             shader = 0;
150*b7c941bbSAndroid Build Coastguard Worker         }
151*b7c941bbSAndroid Build Coastguard Worker     }
152*b7c941bbSAndroid Build Coastguard Worker     return shader;
153*b7c941bbSAndroid Build Coastguard Worker }
154*b7c941bbSAndroid Build Coastguard Worker 
createProgram(const char ** vertexSource,const char ** fragmentSource)155*b7c941bbSAndroid Build Coastguard Worker GLuint GLUtils::createProgram(const char** vertexSource, const char** fragmentSource) {
156*b7c941bbSAndroid Build Coastguard Worker     GLuint vertexShader = loadShader(GL_VERTEX_SHADER, vertexSource);
157*b7c941bbSAndroid Build Coastguard Worker     if (!vertexShader) {
158*b7c941bbSAndroid Build Coastguard Worker         return 0;
159*b7c941bbSAndroid Build Coastguard Worker     }
160*b7c941bbSAndroid Build Coastguard Worker 
161*b7c941bbSAndroid Build Coastguard Worker     GLuint fragmentShader = loadShader(GL_FRAGMENT_SHADER, fragmentSource);
162*b7c941bbSAndroid Build Coastguard Worker     if (!fragmentShader) {
163*b7c941bbSAndroid Build Coastguard Worker         return 0;
164*b7c941bbSAndroid Build Coastguard Worker     }
165*b7c941bbSAndroid Build Coastguard Worker 
166*b7c941bbSAndroid Build Coastguard Worker     GLuint program = glCreateProgram();
167*b7c941bbSAndroid Build Coastguard Worker     if (program) {
168*b7c941bbSAndroid Build Coastguard Worker         glAttachShader(program, vertexShader);
169*b7c941bbSAndroid Build Coastguard Worker         glAttachShader(program, fragmentShader);
170*b7c941bbSAndroid Build Coastguard Worker 
171*b7c941bbSAndroid Build Coastguard Worker         GLint linkStatus;
172*b7c941bbSAndroid Build Coastguard Worker         glLinkProgram(program);
173*b7c941bbSAndroid Build Coastguard Worker         glGetProgramiv(program, GL_LINK_STATUS, &linkStatus);
174*b7c941bbSAndroid Build Coastguard Worker 
175*b7c941bbSAndroid Build Coastguard Worker         if (!linkStatus) {
176*b7c941bbSAndroid Build Coastguard Worker             GLint infoLen = 0;
177*b7c941bbSAndroid Build Coastguard Worker             glGetProgramiv(program, GL_INFO_LOG_LENGTH, &infoLen);
178*b7c941bbSAndroid Build Coastguard Worker             if (infoLen > 0) {
179*b7c941bbSAndroid Build Coastguard Worker                 char* infoLog = (char*) malloc(sizeof(char) * infoLen);
180*b7c941bbSAndroid Build Coastguard Worker                 glGetProgramInfoLog(program, infoLen, NULL, infoLog);
181*b7c941bbSAndroid Build Coastguard Worker                 __android_log_print(ANDROID_LOG_ERROR, LOG_TAG,
182*b7c941bbSAndroid Build Coastguard Worker                                     "Error linking program:\n%s\n", infoLog);
183*b7c941bbSAndroid Build Coastguard Worker                 free(infoLog);
184*b7c941bbSAndroid Build Coastguard Worker             }
185*b7c941bbSAndroid Build Coastguard Worker             glDeleteProgram(program);
186*b7c941bbSAndroid Build Coastguard Worker             program = 0;
187*b7c941bbSAndroid Build Coastguard Worker         }
188*b7c941bbSAndroid Build Coastguard Worker     }
189*b7c941bbSAndroid Build Coastguard Worker     return program;
190*b7c941bbSAndroid Build Coastguard Worker }
191*b7c941bbSAndroid Build Coastguard Worker 
currentTimeMillis()192*b7c941bbSAndroid Build Coastguard Worker double GLUtils::currentTimeMillis() {
193*b7c941bbSAndroid Build Coastguard Worker     struct timeval tv;
194*b7c941bbSAndroid Build Coastguard Worker     gettimeofday(&tv, (struct timezone *) NULL);
195*b7c941bbSAndroid Build Coastguard Worker     return tv.tv_sec * 1000.0 + tv.tv_usec / 1000.0;
196*b7c941bbSAndroid Build Coastguard Worker }
197*b7c941bbSAndroid Build Coastguard Worker 
198*b7c941bbSAndroid Build Coastguard Worker // Rounds a number up to the smallest power of 2 that is greater than or equal to x.
roundUpToSmallestPowerOf2(int x)199*b7c941bbSAndroid Build Coastguard Worker int GLUtils::roundUpToSmallestPowerOf2(int x) {
200*b7c941bbSAndroid Build Coastguard Worker     if (x < 0) {
201*b7c941bbSAndroid Build Coastguard Worker         return 0;
202*b7c941bbSAndroid Build Coastguard Worker     }
203*b7c941bbSAndroid Build Coastguard Worker     --x;
204*b7c941bbSAndroid Build Coastguard Worker     x |= x >> 1;
205*b7c941bbSAndroid Build Coastguard Worker     x |= x >> 2;
206*b7c941bbSAndroid Build Coastguard Worker     x |= x >> 4;
207*b7c941bbSAndroid Build Coastguard Worker     x |= x >> 8;
208*b7c941bbSAndroid Build Coastguard Worker     x |= x >> 16;
209*b7c941bbSAndroid Build Coastguard Worker     return x + 1;
210*b7c941bbSAndroid Build Coastguard Worker }
211*b7c941bbSAndroid Build Coastguard Worker 
genTexture(int texWidth,int texHeight,int fill)212*b7c941bbSAndroid Build Coastguard Worker GLuint GLUtils::genTexture(int texWidth, int texHeight, int fill) {
213*b7c941bbSAndroid Build Coastguard Worker     GLuint textureId = 0;
214*b7c941bbSAndroid Build Coastguard Worker     int w = roundUpToSmallestPowerOf2(texWidth);
215*b7c941bbSAndroid Build Coastguard Worker     int h = roundUpToSmallestPowerOf2(texHeight);
216*b7c941bbSAndroid Build Coastguard Worker     uint32_t* m = new uint32_t[w * h];
217*b7c941bbSAndroid Build Coastguard Worker     if (m != NULL) {
218*b7c941bbSAndroid Build Coastguard Worker         uint32_t* d = m;
219*b7c941bbSAndroid Build Coastguard Worker         for (int y = 0; y < h; y++) {
220*b7c941bbSAndroid Build Coastguard Worker             for (int x = 0; x < w; x++) {
221*b7c941bbSAndroid Build Coastguard Worker                 if (fill == RANDOM_FILL) {
222*b7c941bbSAndroid Build Coastguard Worker                     *d = 0xff000000 | ((y & 0xff) << 16) | ((x & 0xff) << 8) | ((x + y) & 0xff);
223*b7c941bbSAndroid Build Coastguard Worker                 } else {
224*b7c941bbSAndroid Build Coastguard Worker                     *d = 0xff000000 | fill;
225*b7c941bbSAndroid Build Coastguard Worker                 }
226*b7c941bbSAndroid Build Coastguard Worker                 d++;
227*b7c941bbSAndroid Build Coastguard Worker             }
228*b7c941bbSAndroid Build Coastguard Worker         }
229*b7c941bbSAndroid Build Coastguard Worker         glGenTextures(1, &textureId);
230*b7c941bbSAndroid Build Coastguard Worker         glBindTexture(GL_TEXTURE_2D, textureId);
231*b7c941bbSAndroid Build Coastguard Worker         glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, m);
232*b7c941bbSAndroid Build Coastguard Worker         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
233*b7c941bbSAndroid Build Coastguard Worker         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
234*b7c941bbSAndroid Build Coastguard Worker         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
235*b7c941bbSAndroid Build Coastguard Worker         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
236*b7c941bbSAndroid Build Coastguard Worker     }
237*b7c941bbSAndroid Build Coastguard Worker     delete[] m;
238*b7c941bbSAndroid Build Coastguard Worker     return textureId;
239*b7c941bbSAndroid Build Coastguard Worker }
240