blob: 2484153d452d8f620c5cfc1b69e9ba3b74352d20 [file] [log] [blame]
/*
* Copyright (C) 2013 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
* in compliance with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
* or implied. See the License for the specific language governing permissions and limitations under
* the License.
*/
#include "GLUtils.h"
#include <stdlib.h>
#include <sys/time.h>
#define LOG_TAG "PTS_OPENGL"
#define LOG_NDEBUG 0
#include <utils/Log.h>
// Loads the given source code as a shader of the given type.
static GLuint loadShader(GLenum shaderType, const char** source) {
GLuint shader = glCreateShader(shaderType);
if (shader) {
glShaderSource(shader, 1, source, NULL);
glCompileShader(shader);
GLint compiled = 0;
glGetShaderiv(shader, GL_COMPILE_STATUS, &compiled);
if (!compiled) {
GLint infoLen = 0;
glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &infoLen);
if (infoLen > 0) {
char* infoLog = (char*) malloc(sizeof(char) * infoLen);
glGetShaderInfoLog(shader, infoLen, NULL, infoLog);
ALOGE("Error compiling shader:\n%s\n", infoLog);
free(infoLog);
}
glDeleteShader(shader);
shader = 0;
}
}
return shader;
}
GLuint GLUtils::createProgram(const char** vertexSource,
const char** fragmentSource) {
GLuint vertexShader = loadShader(GL_VERTEX_SHADER, vertexSource);
if (!vertexShader) {
return 0;
}
GLuint fragmentShader = loadShader(GL_FRAGMENT_SHADER, fragmentSource);
if (!fragmentShader) {
return 0;
}
GLuint program = glCreateProgram();
if (program) {
glAttachShader(program, vertexShader);
glAttachShader(program, fragmentShader);
GLint linkStatus;
glLinkProgram(program);
glGetProgramiv(program, GL_LINK_STATUS, &linkStatus);
if (!linkStatus) {
GLint infoLen = 0;
glGetProgramiv(program, GL_INFO_LOG_LENGTH, &infoLen);
if (infoLen > 0) {
char* infoLog = (char*) malloc(sizeof(char) * infoLen);
glGetProgramInfoLog(program, infoLen, NULL, infoLog);
ALOGE("Error linking program:\n%s\n", infoLog);
free(infoLog);
}
glDeleteProgram(program);
program = 0;
}
}
return program;
}
double GLUtils::currentTimeMillis() {
struct timeval tv;
gettimeofday(&tv, (struct timezone *) NULL);
return tv.tv_sec * 1000.0 + tv.tv_usec / 1000.0;
}
// Rounds a number up to the smallest power of 2 that is greater than the original number.
int GLUtils::roundUpToSmallestPowerOf2(int x) {
if (x < 0) {
return 0;
}
--x;
x |= x >> 1;
x |= x >> 2;
x |= x >> 4;
x |= x >> 8;
x |= x >> 16;
return x + 1;
}
GLuint GLUtils::genTexture(int texWidth, int texHeight, int fill) {
GLuint textureId = 0;
int w = roundUpToSmallestPowerOf2(texWidth);
int h = roundUpToSmallestPowerOf2(texHeight);
uint32_t* m = new uint32_t[w * h];
if (m != NULL) {
uint32_t* d = m;
for (int y = 0; y < h; y++) {
for (int x = 0; x < w; x++) {
if (fill == RANDOM_FILL) {
*d = 0xff000000 | ((y & 0xff) << 16) | ((x & 0xff) << 8) | ((x + y) & 0xff);
} else {
*d = 0xff000000 | fill;
}
d++;
}
}
glGenTextures(1, &textureId);
glBindTexture(GL_TEXTURE_2D, textureId);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_RGBA,
GL_UNSIGNED_BYTE, m);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
}
delete[] m;
return textureId;
}
bool GLUtils::createFBO(GLuint& fboId, GLuint& rboId, GLuint& cboId, int width, int height) {
glGenFramebuffers(1, &fboId);
glBindFramebuffer(GL_FRAMEBUFFER, fboId);
glGenRenderbuffers(1, &rboId);
glBindRenderbuffer(GL_RENDERBUFFER, rboId);
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, width, height);
glBindRenderbuffer(GL_RENDERBUFFER, 0);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, rboId);
glGenRenderbuffers(1, &cboId);
glBindRenderbuffer(GL_RENDERBUFFER, cboId);
glRenderbufferStorage(GL_RENDERBUFFER, GL_RGB565, width, height);
glBindRenderbuffer(GL_RENDERBUFFER, 0);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, cboId);
GLuint err = glGetError();
if (err != GL_NO_ERROR) {
ALOGE("GLError %d", err);
return false;
}
return glCheckFramebufferStatus(GL_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE;
}