3

In my OpenGLES 2 application (on an SGX535 on Android 2.3, not that it matters), I've got a large texture that I need to make frequent small updates to. I set this up as a pair of FBOs, where I render updates to the back buffer, then render the entire back buffer as a texture to the front buffer to "swap" them. The front buffer is then used elsewhere in the scene as a texture.

The updates are sometimes solid color sub-rectangles, but most of the time, the updates are raw image data, in the same format as the texture, e.g., new image data is coming in as RGB565, and the framebuffer objects are backed by RGB565 textures.

Using glTexSubImage2D() is slow, as you might expect, particularly on a deferred renderer like the SGX. Not only that, using glTexSubImage2D on the back FBO eventually causes the app to crash somewhere in the SGX driver.

I tried creating new texture objects for each sub-rectangle, calling glTexImage2D to initialize them, then render them to the back buffer as textured quads. I preserved the texture objects for two FBO buffer swaps before deleting them, but apparently that wasn't long enough, because when the texture IDs were re-used, they retained the dimensions of the old texture.

Instead, I'm currently taking the entire buffer of raw image data and converting it to an array of structs of vertices and colors, like this:

struct rawPoint {
    GLfloat x;
    GLfloat y;
    GLclampf r;
    GLclampf g;
    GLclampf b;
};

I can then render this array to the back buffer using GL_POINTS. For a buffer of RGB565 data, this means allocating a buffer literally 10x bigger than the original data, but it's actually faster than using glTexSubImage2D()!

I can't keep the vertices or the colors in their native unsigned short format, because OpenGL ES 2 only takes floats in vertex attributes and shader uniforms. I have to submit every pixel as a separate set of coordinates, because I don't have geometry shaders. Finally, I can't use the EGL_KHR_gl_texture_2D_image extension, since my platform doesn't support it!

There must be a better way to do this! I'm burning tons of CPU cycles just to convert image data into a wasteful floating point color format just so the GPU can convert it back into the format it started with.

Would I be better off using EGL Pbuffers? I'm not excited by that prospect, since it requires context switching, and I'm not even sure it would let me write directly to the image buffer.

LightStruk
  • 1,451
  • 14
  • 17

1 Answers1

1

I'm kind of new to graphics, so take this with a big grain of salt.

Create a native buffer (see ) the size of your texture Use the native buffer to create an EGL image

eglCreateImageKHR(eglGetCurrentDisplay(), 
                  eglGetCurrentContext(),
                  EGL_GL_TEXTURE_2D_KHR, 
                  buffer, 
                  attr);

I know this uses EGL_GL_TEXTURE_2D_KHR. Are you sure your platform doesn't support this? I am developing on a platform that uses SGX535 as well, and mine seems to support it.

After that, bind the texture as usual. You can memcpy into your native buffer to update sub rectangles very quickly I believe.

I realize I'm answering a month old question, but if you need to see some more code or something, let me know.

Josh A.
  • 374
  • 3
  • 15
  • Yes, I'm sure that the EGL_KHR_gl_texture_2D_image extension is unavailable on Android Gingerbread with the SGX. Here's what eglQueryString(eglGetCurrentDisplay(), EGL_EXTENSIONS) returns: "EGL_KHR_image EGL_KHR_image_base EGL_KHR_image_pixmap EGL_ANDROID_image_native_buffer EGL_ANDROID_swap_rectangle". By the way, despite being in the list, EGL_KHR_image_pixmap is broken and does not work; I've filed a bug with Google asking them to not advertise a broken extension. – LightStruk Oct 23 '11 at 18:25