glTexImage2D is too slow on android with nexus one

when draw YUV frame use opengl 2.0 and shader on nexus one,but the
function glTexImage2D is too slow ,cost 40-60 ms
who can fix it ? the key codes:

int CreateSimpleTexture2D()
{
int err, i;

          for (i=0; i<3;i++)
          {
                  glGenTextures(1, &userData.textureId[i]);
                  if (err = glGetError()) {
                  //      NSLog(@"Error: Could not generate

texture: %d", err);

__android_log_print(ANDROID_LOG_ERROR,“CreateSimpleTexture2D”,“Error:
Could not generate texture: %d”, err);
return 0;
}

                  glBindTexture(GL_TEXTURE_2D, userData.textureId[i]);
                  if (err = glGetError()) {
                  //      NSLog(@"Error: Could not bind texture: %d", err);

__android_log_print(ANDROID_LOG_ERROR,“CreateSimpleTexture2D”,“Error:
Could not bind texture: %d”, err);
return 0;
}
}

          glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
          if (err = glGetError()) {
                  //NSLog(@"Error: Could not set texture

minimization filter: %d", err);

__android_log_print(ANDROID_LOG_ERROR,“CreateSimpleTexture2D”,“Error:
Could not set texture minimization filter: %d”, err);
return 0;
}

          glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
          if (err = glGetError()) {
          //      NSLog(@"Error: Could not set texture

magnification filter: %d", err);
__android_log_print(ANDROID_LOG_ERROR,“CreateSimpleTexture2D”,“Error:
Could not set texture magnification filter: %d”, err);
return 0;
}

          glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S,

GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T,
GL_CLAMP_TO_EDGE);
glGenerateMipmap(GL_TEXTURE_2D);
return 1;
}

---------------------------------------render frame

          glViewport ( 0, 0, g_WindowsWidth, g_WindowsHeight );
          checkGlError("glViewport");
          //glDrawBuffer(GL_COLOR_ATTACHMENT0);
          // Clear the color buffer
          glClear ( GL_COLOR_BUFFER_BIT );
          checkGlError("glClear");
          // Use the program object
          glUseProgram ( userData.programObject );
          checkGlError("glUseProgram");
          // Load the vertex position
          glVertexAttribPointer ( userData.positionLoc, 3, GL_FLOAT,
                                                     GL_FALSE, 5
  • sizeof(GLfloat), vVertices );
    // Load the texture coordinate
    glVertexAttribPointer ( userData.texCoordLoc, 2, GL_FLOAT,
    GL_FALSE, 5

  • sizeof(GLfloat), &vVertices[3] );

            glEnableVertexAttribArray ( userData.positionLoc );
            glEnableVertexAttribArray ( userData.texCoordLoc );
    
            long long  ttttttt=av_gettime();
            // Bind the texture
            glActiveTexture ( GL_TEXTURE1 );
            glBindTexture ( GL_TEXTURE_2D, userData.textureId[1] );
            glUniform1i ( userData.samplerLocU, 1);
            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_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T,
GL_CLAMP_TO_EDGE);
//glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
//glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
//glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);

          //glPixelStorei(GL_UNPACK_ALIGNMENT,1);

          glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, width/2,

height/2, 0,
GL_LUMINANCE, GL_UNSIGNED_BYTE, pict->data[1]);
checkGlError(“glTexImage2D…pict->data[1]”);
//glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, width0.5,
height
0.5, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, pict->data[1]);

          // Bind the texture
          glActiveTexture ( GL_TEXTURE2 );
          glBindTexture ( GL_TEXTURE_2D, userData.textureId[2] );
          glUniform1i ( userData.samplerLocV, 2);
          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_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T,
GL_CLAMP_TO_EDGE);
//glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
//glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
//glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
//glPixelStorei(GL_UNPACK_ALIGNMENT,1);

          glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE,width/2, height/2, 0,

GL_LUMINANCE, GL_UNSIGNED_BYTE, pict->data[2]);

          checkGlError("glTexImage2D....pict->data[2]");
          // Set the sampler texture unit to 0
          glActiveTexture ( GL_TEXTURE0 );
          glBindTexture ( GL_TEXTURE_2D, userData.textureId[0] );
          glUniform1i ( userData.samplerLocY, 0);
          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_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T,
GL_CLAMP_TO_EDGE);
//glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
//glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
//glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
//glPixelStorei(GL_UNPACK_ALIGNMENT,1);

          glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, width, height, 0,

GL_LUMINANCE, GL_UNSIGNED_BYTE, pict->data[0]);
__android_log_print(ANDROID_LOG_ERROR,“GPU”,"%lld",(av_gettime()-ttttttt)/1000);
checkGlError(“glTexImage2D…pict->data[0]”);
glDrawElements ( GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, indices );

who can help me ?

  • are you sure you benchmark correctly ?
  • use smaller texture ?
  • try to benchmark different combinations of parameters for glTexImage2D, to find the fastest paths
  • try to pack 4 YUV 4:1:1 pixels into 3 RGBA8 texels, is that fast ?
  • do you have access to any compressed texture format on your platform ?
  • use PBO for streaming texture data ?

Advice : try to avoid throwing a bunch of code on the forum without any [ code ] blocks, it is very hard to read.

You may also want to try glTexSubImage rather than glTexImage.

Yeah, as a general rule you shouldn’t be calling glTexImage2D at runtime, because - in addition to needing to transfer the data from system memory to GPU - it also fully respecifies the texture, which may or may not include swapping other objects out of video RAM. Both of those are expensive operations.

So you should call glTexImage2D once - during startup - then call glTexSubImage2D at runtime, which will reuse the original texture object but just update it’s data.

Also, make certain that the format and type parameters you choose are optimal for your hardware, otherwise you may be going through software stages in the driver as part of the upload.

We have also met this issue.
with PowerVR GPU has no this issue, but with Adreno200, the upload speed is so so slow.

yep, if we change the format to RGBA, the upload speed will a litter faster, but it is not as fast as PowerVR GPU.

Ignore this, duplicated

What do you mean “benchmark correctly”?
Do you mean the third parameter of the glTexImage2D?

We have tried that GL_RGBA will be faster than GL_LUMINANCE, but there needs a extra time to do parse in the shader.

The compressed texture has only RGBA format, no LUMINANCE format. and it not supports PBO currently.