Android12 opengles3.0 glTexImage2D 0x502 error - android

I have 5 textures, such as diffuse specular normal roughness ao, roughness and ao are 8bit jpg.
I got glError 0x502 while loading rouggness/ao texture after call glTexImage2D, but other three texture is OK.
And this issue just occured with android 12, android 11/10/9/8 is no error. How I can fix this issue?
code:
GLuint textureID;
glGenTextures(1, &textureID);
int width, height, nrComponents;
unsigned char *data = stbi_load(path, &width, &height, &nrComponents, 0);
GLenum format;
if (nrComponents == 1) {
format = GL_RED;
} else if (nrComponents == 3) {
format = GL_RGB;
} else {
format = GL_RGBA;
}
glTexImage2D(GL_TEXTURE_2D, 0, format, width, height, 0, format, GL_UNSIGNED_BYTE, data);
glGenerateMipmap(GL_TEXTURE_2D);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);

According to https://www.khronos.org/registry/OpenGL-Refpages/es3.0/html/glTexImage2D.xhtml, GL_RED is not an acceptable value for internalFormat (parameter 3 in glTexImage2D).
I think you need internalFormat=GL_R8 and format=GL_RED. Or you could use GL_LUMINANCE for both.

Related

creating a framebuffer to take an image from external oes

I am trying to do multi pass rendering with framebuffer the issue is that the source is the camera so the texInput is not of type GL_TEXTURE_2D it is of type GL_TEXTURE_EXTERNAL_OES tho, if I use the function glTexImage2D it gives a black screen when I use that texture in the future after rendering to it without any errors glErros.
On the other hand if I don't use it(because it does not support GL_TEXTURE_EXTERNAL_OES) it gives me framebuffer status of NOT_COMPLETE
here is my code for creating the framebuffer and the texture that I want to associate to it.
fun prepareFBO() {
val intArray = IntArray(1)
glGenFramebuffers(1, intArray, 0)
fboId = intArray.first()
glGenTextures(1, intArray, 0)
texId = intArray.first()
glBindTexture(GL_TEXTURE_2D, texId)
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA,1080, 1920, 0, GL_RGBA, GL_UNSIGNED_BYTE, null)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST)
glBindFramebuffer(GL_FRAMEBUFFER, fboId)
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texId, 0)
val status = glCheckFramebufferStatus(GL_FRAMEBUFFER)
Log.e(TAG, "prepareFBO: ${status == GL_FRAMEBUFFER_COMPLETE}")
glBindFramebuffer(GL_FRAMEBUFFER, 0)
glBindTexture(GL_TEXTURE_2D, 0)
}
the rest is just normal glDrawArrays and glActiveTexture that already works fine when I draw directly to the default framebuffer, if needed please let me know and I will share them.
Thanks for help!
UPDATE:
I found that I need instead of using glTexImage2d I can use eglBindTexImage instead so the final code is:
fun prepareFBO() {
val intArray = IntArray(1)
glGenFramebuffers(1, intArray, 0)
fboId = intArray.first()
glBindFramebuffer(GL_FRAMEBUFFER, fboId)
glGenTextures(1, intArray, 0)
texId = intArray.first()
glBindTexture(GL_TEXTURE_EXTERNAL_OES, texId)
checkGlError("Error 1")
eglBindTexImage(eglGetCurrentDisplay(), windowSurface!!.eglSurface, EGL_BACK_BUFFER)
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_EXTERNAL_OES, texId, 0)
val status = glCheckFramebufferStatus(GL_FRAMEBUFFER)
Log.e(TAG, "prepareFBO: is status complete? => ${status == GL_FRAMEBUFFER_COMPLETE}")
}
while this looks like it makes sense, still I am getting the status of the framebuffer as not complete :/

opengl es 3 glBlitFramebuffer - copying one texture into another

I'm trying to copy a texture into another using 'glBlitFramebuffer', I'm working on the classic open gl example hello-gl2 from android ndk-samples. I changed the shaders to support texture and i can correctly render a textured triangle. I also changed the opengl es version requested on the java side so to request opengl-es3 and i updated the Cmakelists file to link the right library. After calling glBlitFramebuffer(0,0,tw, th, 0, 0, tw, th, GL_COLOR_BUFFER_BIT, GL_LINEAR); i get the after blitTexture glBlitFramebuffer() glError (0x502) error. What is the root cause for that?
Code I use:
To generate the textures:
void createTexture(GLuint &tex, int width, int height, int r){
int rowlen = width * 3;
unsigned char buf[width*3*height];
for (int i=0; i<rowlen; i+=3)
for (int j=0; j<height; j++) {
int col = ((int (i/(3*r))) + (int (j/r)))%2;
buf[i+j*rowlen] = buf[i+1+j*rowlen] = buf[i+2+j*rowlen] = col * 255;
}
glGenTextures(1, &tex);
glBindTexture(GL_TEXTURE_2D, tex);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, buf);
// set the texture wrapping/filtering options (on the currently bound texture object)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
LOGI("DEBUG C++ Texture created [%d]", tex);
}
to setup the framebuffer:
bool SetupFramebuffer(GLuint tex, int width, int height)
{
if (fb == 0)
{
glGenFramebuffers(1, &fb);
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fb);
glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
GL_TEXTURE_2D, tex, 0);
GLenum status = glCheckFramebufferStatus(GL_DRAW_FRAMEBUFFER);
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
if (status != GL_FRAMEBUFFER_COMPLETE)
{
LOGE("Incomplete frame buffer object!");
return false;
}
LOGI("Created FBO %d for texture %d.",
fb, tex);
}
return true;
}
to build the array of textures inside the setupGraphics function:
createTexture(tex, tw, th, 6);
for (int i = 0; i<25; i++) createTexture(aniTex[i], tw, th, 3+i);
SetupFramebuffer(tex, tw, th);
and finally to blit the framebuffer:
const GLenum attachment[1] = { GL_COLOR_ATTACHMENT0 };
void blitTexture() {
static int time = 0;
glBindFramebuffer(GL_FRAMEBUFFER, fb);
checkGlError("blitTexture glBindFramebuffer");
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1,
GL_TEXTURE_2D, aniTex[time], 0);
checkGlError("blitTexture glFramebufferTexture2D");
glReadBuffer(GL_COLOR_ATTACHMENT1);
checkGlError("blitTexture glReadBuffer");
glDrawBuffers(1, attachment);
checkGlError("blitTexture glDrawBuffers");
GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
if (status != GL_FRAMEBUFFER_COMPLETE) LOGE("Incomplete frame buffer object!");
glBlitFramebuffer(0,0,tw, th, 0, 0, tw, th, GL_COLOR_BUFFER_BIT, GL_LINEAR);
checkGlError("blitTexture glBlitFramebuffer");
int samples;
glGetFramebufferParameteriv(GL_READ_FRAMEBUFFER, GL_FRAMEBUFFER_DEFAULT_SAMPLES, &samples);
LOGI("SAMPLES draw buffer %d", samples);
time = ++time%25;
}
full project can be found here: https://github.com/AndrewBloom/BlitFramebufferExample

Render to texture attached to Frame Buffer Object (texture appears black)

I have generated a frame buffer object(FBO), bind it, attached a texture to its GL_COLOR_ATTACHMENT0. Then ensure that I get its status as GL_FRAMEBUFFER_COMPLETE. I have another texture(which is displaying on display), let's call it workingTexture. Now I want to render this workingTexture onto FBO, so I bind this FBO and then render workingTexture.
Then I bind default frame buffer(reserved for display) and try to render the texture attached to FBO, thinking that I will get my texture onto display, but I get black texture.
Relevant code
code to generate workingTexture...
int[] workingTexture = new int[1];
glGenTextures(1, workingTexture, 0); // generate workingTexture
glActiveTexture(GL_TEXTURE0); // attach it to TEXTURE_UNIT0
glBindTexture(GL_TEXTURE_2D, workingTexture[0]);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_MIRRORED_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_MIRRORED_REPEAT);
code to generate fbo
int[] fboName = new int[1];
int[] fboTextureName = new int[1];
final int fboTextureUnit = 1; // attach this texture to texture unit GL_TEXTURE1
glGenFramebuffers(1, fboName, 0);
int generatedTextureNameForFBO =
generateTextureForFBO(fboTextureUnit,
width, height);
fboTextureName[0] = generatedTextureNameForFBO;
glBindFramebuffer(GL_FRAMEBUFFER, fboName[0]);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
GL_TEXTURE_2D, generatedTextureNameForFBO, 0);
if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) {
// created FBO is not complete
throw new RuntimeException("FBO status INCOMPLETE 😔😔");
}
method used to generate texture attached to fbo
private int generateTextureForFBO(#IntRange(from = 0) final int textureUnit,
#IntRange(from = 1) final int width,
#IntRange(from = 1) final int height) {
int[] textureName = new int[1];
glGenTextures(1, textureName, 0);
glActiveTexture(GL_TEXTURE0 + textureUnit);
glBindTexture(GL_TEXTURE_2D, textureName[0]);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, null);
// glBindTexture(GL_TEXTURE_2D, 0);
// glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
// glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
// glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_MIRRORED_REPEAT);
// glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_MIRRORED_REPEAT);
// glBindTexture(GL_TEXTURE_2D, 0);
return textureName[0];
}
Now coming to drawing part...
#Override
public void onDrawFrame(GL10 unused) {
glClear(GL_COLOR_BUFFER_BIT);
//renderTex(mViewMatrix, 0, texProgram); // this texture is drawing on screen
glBindFramebuffer(GL_FRAMEBUFFER, fboName[0]);
renderTex(mViewMatrix, 0, texProgram); // rendering workingTexture onto FBO
glBindFramebuffer(GL_FRAMEBUFFER, 0);
renderTex(mViewMatrix, fboTextureUnit[0], texProgram); // texture appears black
}
renderTex is a simple method to render texture. It is working fine.
Also I have checked for GL_ERROR but there is no error.
My understanding of application created FBO is that every read and write glCall will happen on currently bound FBO, so is my understanding of FBO incorrect, or is there some error in my code.
Platform OpenGL|es 20 on Android
The texture which is generated in generateTextureForFBO is mipmap incomplete.
If you do not generate mipmaps (by glGenerateMipmap), then setting the GL_TEXTURE_MIN_FILTER is important. Since the default filter is GL_NEAREST_MIPMAP_LINEAR the texture would be mipmap incomplete, if you don not change the minifying function to GL_NEAREST or GL_LINEAR.
Set the texture minifying function (GL_TEXTURE_MIN_FILTER) by glTexParameter:
glBindTexture(GL_TEXTURE_2D, textureName[0]);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, null);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);

Failed to initialize FBO on Android SDK emulator device

So this is how FBO is initialized:
/**
* Initializes Renderbuffer.
*/
static GLuint init_renderbuffer(GLuint width, GLuint height, GLenum format) {
GLuint renderbuffer;
glGenRenderbuffers(1, &renderbuffer);
checkGlError("init_renderbuffer: glGenRenderbuffers");
glBindRenderbuffer(GL_RENDERBUFFER, renderbuffer);
checkGlError("init_renderbuffer: glBindRenderbuffer");
glRenderbufferStorage(GL_RENDERBUFFER, format, width, height);
checkGlError("init_renderbuffer: glRenderbufferStorage");
glBindRenderbuffer(GL_RENDERBUFFER, 0);
checkGlError("init_renderbuffer: glBindRenderbuffer");
return renderbuffer;
}
/**
* Initializes FBO.
*/
static void engine_init_fbo(struct engine* engine, GLuint width, GLuint height) {
// create renderable texture
glGenTextures(1, &engine->renderableTexture);
checkGlError("engine_init_fbo: glGenTextures");
glBindTexture(GL_TEXTURE_2D, engine->renderableTexture);
checkGlError("engine_init_fbo: glBindTexture");
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, 0);
checkGlError("engine_init_fbo: glTexImage2D");
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
checkGlError("engine_init_fbo: glTexParameteri");
// create render buffers
engine->depthRenderBuffer = init_renderbuffer(width, height, GL_DEPTH_COMPONENT16);
engine->stencilRenderBuffer = init_renderbuffer(width, height, GL_STENCIL_INDEX8);
LOGI("****************************** FBO: T: %d, D: %d, S: %d", engine->renderableTexture,
engine->depthRenderBuffer, engine->stencilRenderBuffer);
// create framebuffer object
glGenFramebuffers(1, &engine->framebufferObject);
checkGlError("engine_init_fbo: glGenFramebuffers");
glBindFramebuffer(GL_FRAMEBUFFER, engine->framebufferObject);
checkGlError("engine_init_fbo: glBindFramebuffer");
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, engine->renderableTexture, 0);
checkGlError("engine_init_fbo: glFramebufferTexture2D");
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, engine->depthRenderBuffer);
checkGlError("engine_init_fbo: glFramebufferRenderbuffer");
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, engine->stencilRenderBuffer);
checkGlError("engine_init_fbo: glFramebufferRenderbuffer");
GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
checkGlError("engine_init_fbo: glCheckFramebufferStatus");
if(status != GL_FRAMEBUFFER_COMPLETE) {
switch(status) {
case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT:
LOGI("****************************** engine_init_fbo: FBO error: FRAMEBUFFER_INCOMPLETE_ATTACHMENT");
break;
case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT:
LOGI("****************************** engine_init_fbo: FBO error: FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT");
break;
case GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS:
LOGI("****************************** engine_init_fbo: FBO error: FRAMEBUFFER_INCOMPLETE_DIMENSIONS");
break;
case GL_FRAMEBUFFER_UNSUPPORTED:
LOGI("****************************** engine_init_fbo: FBO error: FRAMEBUFFER_UNSUPPORTED");
break;
default:
LOGI("****************************** engine_init_fbo: Unknown FBO error");
}
}
else {
LOGI("****************************** engine_init_fbo: FBO has been successfully initialized");
}
glBindTexture(GL_TEXTURE_2D, 0);
checkGlError("engine_init_fbo: glBindTexture");
glBindFramebuffer(GL_FRAMEBUFFER, 0);
checkGlError("engine_init_fbo: glBindFramebuffer");
}
As you can see, everything here is done according to OpenGL ES standard: 2D texture with RGB565 internal format is used as color; 2 renderbuffers are used as depth and stencil surfaces; dimensions are 32x32.
It works fine on real device (Alcatel OT 918D, prints "FBO has been successfully initialized" in adb logcat), but fails with FRAMEBUFFER_UNSUPPORTED on virtual device.
My virtual device's CPU is atom, GPU emulation is enabled, OpenGL ES 2.0 works fine - checked with another applications (which do not use FBOs).
Entire project (based on native-activity sample from NDK), which can be compiled with ndk-build, is here:
https://docs.google.com/file/d/0Byy41LxMuTKUZVJxSUtBZDVDXzA/edit?usp=sharing
My question is: Is this a bug in android-sdk emulator? Because everything seems to meet the minimum requerements to the OpenGL ES 2.0 implementation.
Thank you!
EDIT:
Found the solution. It appears, that AVD does not support this configuration of attached objects. I had to remove stencil attachment to make it work.
EDIT2:
It appears to be the context creation problem. I did not require stencil bits, so probably AVD created context without stencil support, and Alcatel phone - with stencil.
Anyway, this is not a bug, but my mistake.

Fastest 2D frame rate possible with android NDK, my try included, better options available?

Fastest 2D frame rate possible with android NDK, my try included, better options available?
I used the NDK and OpenGL ES 2.0 to display a frame as a texture on a GL_TRIANGLE_STRIP.
This was done on a HTC Desire, same hardware as Nexus One.
I tried to load multiple GL_RGBA textures and switch between the textures, because the normal fill rate with a single texture was disappointingly low:
1 texture: 4.78 fps
2 textures: 19.68 fps
3 textures: 20.18 fps
4 textures: 28.52 fps
5 textures: 29.01 fps
6 textures: 30.32 fps
I think even 30.32 fps RGBA is still too slow.
So is this the way to go to achieve the fastest 2D frame rate (with same quality)?
Any suggestions to speed it up?
Here is the relevant code, it is based on the hello-gl2 NDK example:
=== GL2JNIView.java :
init(false, 0, 0);
ConfigChooser(5, 6, 5, 0, depth, stencil);
=== gl_code.cpp :
#include <GLES2/gl2.h>
#include <GLES2/gl2ext.h>
#include <android/log.h>
#include <stdlib.h>
#include <time.h>
typedef unsigned char byte;
static int view_width, view_height;
static byte* framebuffer;
static int framebuffer_size;
static GLuint texture_id[6];
static const char* vertexSrc =
"precision highp float;\n"
"precision highp int;\n"
"attribute vec4 vertexCoords;\n"
"attribute vec2 textureCoords;\n"
"varying vec2 f_textureCoords;\n"
"void main() {\n"
" f_textureCoords = textureCoords;\n"
" gl_Position = vertexCoords;\n"
"}\n";
static const char* fragmentSrc =
"precision highp float;\n"
"precision highp int;\n"
"uniform sampler2D texture;\n"
"varying vec2 f_textureCoords;\n"
"void main() {\n"
" gl_FragColor = texture2D(texture, f_textureCoords);\n"
"}\n";
static GLuint shaderProgram;
static GLint attrib_vertexCoords;
static GLint attrib_textureCoords;
static GLint uniform_texture;
static const GLfloat vertexCoords[] = {-1.0, 1.0, -1.0, -1.0, 1.0, 1.0, 1.0, -1.0};
static const GLfloat textureCoords[] = {0.0, 0.0, 0.0, 1.0, 1.0, 0.0, 1.0, 1.0};
JNIEXPORT void JNICALL Java_com_android_gl2jni_GL2JNILib_init(JNIEnv * env, jobject obj, jint width, jint height) {
view_width = width;
view_height = height;
framebuffer_size = 4*view_width*view_height;
framebuffer = (byte*)calloc(framebuffer_size, sizeof(byte));
for (int i = 0; i < framebuffer_size; i++) framebuffer[i] = 0;
glViewport(0, 0, view_width, view_height);
glGenTextures(6, &texture_id[0]);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, texture_id[0]);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, view_width, view_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, framebuffer);
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, texture_id[1]);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, view_width, view_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, framebuffer);
glActiveTexture(GL_TEXTURE2);
glBindTexture(GL_TEXTURE_2D, texture_id[2]);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, view_width, view_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, framebuffer);
glActiveTexture(GL_TEXTURE3);
glBindTexture(GL_TEXTURE_2D, texture_id[3]);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, view_width, view_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, framebuffer);
glActiveTexture(GL_TEXTURE4);
glBindTexture(GL_TEXTURE_2D, texture_id[4]);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, view_width, view_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, framebuffer);
glActiveTexture(GL_TEXTURE5);
glBindTexture(GL_TEXTURE_2D, texture_id[5]);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, view_width, view_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, framebuffer);
shaderProgram = glCreateProgram();
GLuint vertexShader = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vertexShader, 1, &vertexSrc, NULL);
glCompileShader(vertexShader);
glAttachShader(shaderProgram, vertexShader);
GLuint fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragmentShader, 1, &fragmentSrc, NULL);
glCompileShader(fragmentShader);
glAttachShader(shaderProgram, fragmentShader);
glLinkProgram(shaderProgram);
glUseProgram(shaderProgram);
uniform_texture = glGetUniformLocation(shaderProgram, "texture");
glUniform1i(uniform_texture, 0);
attrib_vertexCoords = glGetAttribLocation(shaderProgram, "vertexCoords");
glEnableVertexAttribArray(attrib_vertexCoords);
glVertexAttribPointer(attrib_vertexCoords, 2, GL_FLOAT, GL_FALSE, 0, vertexCoords);
attrib_textureCoords = glGetAttribLocation(shaderProgram, "textureCoords");
glEnableVertexAttribArray(attrib_textureCoords);
glVertexAttribPointer(attrib_textureCoords, 2, GL_FLOAT, GL_FALSE, 0, textureCoords);
}
JNIEXPORT void JNICALL Java_com_android_gl2jni_GL2JNILib_step(JNIEnv * env, jobject obj) {
static int frame_count = 0;
static clock_t last_time = clock();
static int last_frame_count = 0;
frame_count++;
if (clock()-last_time > 1e7) {
__android_log_print(ANDROID_LOG_INFO, "libgl2jni", "fps: %f", ((float)frame_count-last_frame_count)/(clock()-last_time)*1e6);
last_time = clock();
last_frame_count = frame_count;
}
static byte val = 0;
val++;
if (val == 256) val = 0;
for (int i = 0; i < framebuffer_size; i++) framebuffer[i] = val;
int tst = frame_count%6;
if (tst == 0) {
glActiveTexture(GL_TEXTURE0);
} else if (tst == 1) {
glActiveTexture(GL_TEXTURE1);
} else if (tst == 2) {
glActiveTexture(GL_TEXTURE2);
} else if (tst == 3) {
glActiveTexture(GL_TEXTURE3);
} else if (tst == 4) {
glActiveTexture(GL_TEXTURE4);
} else if (tst == 5) {
glActiveTexture(GL_TEXTURE5);
}
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, view_width, view_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, framebuffer);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
}
I realize your question is rather old, and you've likely either solved it or moved onto something else, but I'll give a suggestion in case if anyone else comes across this.
First of all, glTexImage2D requires the graphics subsystem to perform a memory free and reallocation of the texture object every time you call it, since the texture parameters can change between calls. An optimized driver might look at the width, height and format, and if they are all the same then the reallocation could be skipped, but it's not likely that the Android driver implementers are actually doing this.
To avoid the texture reallocation completely, you can use glTexSubImage2D to replace the complete bitmap, or just a portion of it. If you combine this with your above texture buffering scheme, you should see a fairly large speed increase. You could even extend this to detect the modified areas of your display and only update the rectangular portions that have changed between frames.
To summarize, change your texture initialization code to call glTexImage2D with a NULL bitmap pointer, so OpenGL only allocates the memory for the texture and doesn't actually copy any data into it like so:
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, view_width, view_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
Then update every frame in your game loop with:
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, view_width, view_height, GL_RGBA, GL_UNSIGNED_BYTE, framebuffer);
Fastest possible onscreen frame rate is effectively capped by screen refresh rate, which is vendor-specific. My guess would be at least 60 Hz (60 frames per second).
Off-screen rendering is not capped by refresh-rate and depends on the intensity of computing you are performing. Endless loop with some gl code may run significantly faster than 60 Hz, or, for that matter, slower.

Categories

Resources