Android OpenGL textures: create and delete them on the fly

I am currently implementing a 3D viewer, which basically displays a subset of all the images that the user has on his SD card. The closest matching product I'd think of would be CoolIris:

enter image description here

It simply displays a scroll bar of N tiles on the screen, each of which shows a different image, and new tiles enter the screen and show new images.

Now for my problem: I have a program that works and perfectly displays ATVs. When the quad leaves the screen, it receives recirculation / release. New ATVs continue to be added to the tile before they enter the screen.

Since there can be hundreds of images, textures need to be created and deleted on the fly (so that we don't have enough memory). The problem is that after removing the textures, the newly created textures seem to get some identifiers of the other textures currently in use.

My rendering cycle is as follows:

void render(GL10 gl) {
  0. Move the camera

  // Tile board maintenance
  1. Remove tiles out of screen
  2. Add new tiles which are about to enter screen

  // Texture handling
  3. glDeleteTextures on all unused textures followed by glFlush
  4. For newly used images
     - Create corresponding Bitmap
     - Create the OpenGL texture, followed by glFlush
     - Release the Bitmap

  // Rendering
  5. Render the tile (using a textured quad)

}

To better understand how the data is organized, an overview of the classes is provided:

TileBoard {
  Image[] allImages;
  Tile[] board;
}

Tile {
  Image image;
}

Image {
  String path;
  int textureId;
  int referenceCount;
}

Texture Creation Code:

protected void loadSingleTexture(GL10 gl, long objectId, Bitmap bmp) {
    int[] textures = new int[1];
    gl.glGenTextures(1, textures, 0);
    gl.glBindTexture(GL10.GL_TEXTURE_2D, textures[0]);
    gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER, GL10.GL_LINEAR);
    gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MAG_FILTER, GL10.GL_LINEAR);
    GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, bmp, 0);
    gl.glFlush();

    if (bmp != null) bmp.recycle();

    if (listener != null) listener.onTextureLoaded(gl, objectId, textures[0]);
}

Texture Removal Code:

// pendingTextureUnloads is a Set<Integer>
if (pendingTextureUnloads.size() > 0) {
  int[] textureIds = new int[pendingTextureUnloads.size()];
  int i = 0;
  Iterator<Integer> it = pendingTextureUnloads.iterator();
  while (it.hasNext()) {
    textureIds[i] = it.next();
  }

  gl.glDeleteTextures(textureIds.length, textureIds, 0);
  gl.glFlush();
}
+5
source share
2 answers

I solved the problem: the problem was that you have to save the texture array passed to glGenTextures and reuse it.

Here is a modified overview for those who will have the same problem:

Image {
  String path;
  int[] textureIds;
  int referenceCount;
}

Texture Creation Code:

// Notice that I don't allocate the int[] at the beginning but use the one of the image
protected void loadSingleTexture(GL10 gl, Image img, Bitmap bmp) {
    gl.glGenTextures(1, img.textureIds, 0);
    gl.glBindTexture(GL10.GL_TEXTURE_2D, img.textureIds[0]);
    gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER, GL10.GL_LINEAR);
    gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MAG_FILTER, GL10.GL_LINEAR);
    GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, bmp, 0);
    gl.glFlush();

    if (bmp != null) bmp.recycle();
}

Texture Removal Code:

foreach Image img {
  gl.glDeleteTextures(img.textureIds.length, img.textureIds, 0);
}
gl.glFlush();
+5
source

, , , , . while , , , pendingTextureUnloads, 0 (null), .

, , , , glGenTextures. , , int int . , .

+4

All Articles