Sustituyendo glReadPixels por EGL_KHR_image_base para una copia de píxeles más rápida

Estoy intentando utilizar EGL_KHR_image_base en un proceso androide nativo para reemplazar glReadPixels porque es lento (220ms para RGBX 1280×800).

Esto es lo que tengo hasta ahora, pero mi produce un buffer vacío (sólo ceros)

uint8_t *ptr; GLuint mTexture; status_t error; GraphicBufferAlloc* mGraphicBufferAlloc = new GraphicBufferAlloc(); sp<GraphicBuffer> window = mGraphicBufferAlloc->createGraphicBuffer(width, height, PIXEL_FORMAT_RGBA_8888, GraphicBuffer::USAGE_SW_READ_OFTEN | GraphicBuffer::USAGE_HW_TEXTURE,&error); EGLClientBuffer buffer = (EGLClientBuffer)window->getNativeBuffer(); EGLint eglImageAttributes[] = {EGL_WIDTH, width, EGL_HEIGHT, height, EGL_MATCH_FORMAT_KHR, EGL_FORMAT_RGBA_8888_KHR, EGL_IMAGE_PRESERVED_KHR, EGL_TRUE, EGL_NONE}; EGLImageKHR image = eglCreateImageKHR(eglGetCurrentDisplay(), EGL_NO_CONTEXT, EGL_NATIVE_BUFFER_ANDROID,buffer, eglImageAttributes); glGenTextures(1, &mTexture); glBindTexture(GL_TEXTURE_2D, mTexture); glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, image); window->lock(GraphicBuffer::USAGE_SW_READ_OFTEN, (void**)&ptr); memcpy(texture, ptr, width * height * 4); window->unlock(); 

Qué estoy haciendo mal ?

Estás creando un búfer vacío y luego lee el contenido de él. Caminando a través del código:

 GraphicBufferAlloc* mGraphicBufferAlloc = new GraphicBufferAlloc(); sp<GraphicBuffer> window = mGraphicBufferAlloc->createGraphicBuffer(width, height, PIXEL_FORMAT_RGBA_8888, GraphicBuffer::USAGE_SW_READ_OFTEN | GraphicBuffer::USAGE_HW_TEXTURE,&error); 

Esto crea un nuevo GraphicBuffer (a veces denominado "buffer gralloc"), con las dimensiones especificadas y el formato de píxeles. Los indicadores de uso permiten utilizarlo como textura o leer desde el software, que es lo que quieres.

 EGLClientBuffer buffer = (EGLClientBuffer)window->getNativeBuffer(); EGLint eglImageAttributes[] = {EGL_WIDTH, width, EGL_HEIGHT, height, EGL_MATCH_FORMAT_KHR, EGL_FORMAT_RGBA_8888_KHR, EGL_IMAGE_PRESERVED_KHR, EGL_TRUE, EGL_NONE}; EGLImageKHR image = eglCreateImageKHR(eglGetCurrentDisplay(), EGL_NO_CONTEXT, EGL_NATIVE_BUFFER_ANDROID,buffer, eglImageAttributes); 

Esto toma el objeto ANativeWindow (que es una cola de búferes debajo de la campana) y le asigna un EGLImage "handle".

 glGenTextures(1, &mTexture); glBindTexture(GL_TEXTURE_2D, mTexture); glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, image); 

Esto crea un nuevo objeto de textura y le asigna la EGLImage . Así que ahora el ANativeWindow puede ser utilizado como un objeto de textura.

 window->lock(GraphicBuffer::USAGE_SW_READ_OFTEN, (void**)&ptr); memcpy(texture, ptr, width * height * 4); window->unlock(); 

Esto bloquea el búfer para la lectura, copia los datos de él, y lo desbloquea. Como no has dibujado nada, no hay nada que leer.

Para que esto haga algo útil, usted tiene que hacer algo en la textura. Puede hacerlo creando una FBO y adjuntando la textura a ella como el búfer de color, o usando glCopyTexImage2D() para copiar píxeles de la framebuffer a la textura.

Pude conseguir su ejemplo para trabajar añadiendo lo siguiente antes de la llamada a grallocBuffer->lock() :

 glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 0, 0, width, height, 0); glFinish(); 

El glFinish() es necesario para asegurarse de que GL ha terminado de copiar los píxeles antes de tratar de mirarlos.

Edit: mi compañero de oficina sugirió que el GL_TEXTURE_2D necesita ser GL_TEXTURE_EXTERNAL_OES . No lo he probado todavía.

Editar: véase también esta pregunta .

GraphicBuffer es una parte del código fuente de Android, no en NDK. Consulte esto para su referencia: https://github.com/fuyufjh/GraphicBuffer

  • EGLImages con renderbuffer como hermano de origen y textura como hermano objetivo
  • ¿Por qué eglCreateImageKHR está devolviendo EGL_NO_IMAGE_KHR (en android)?
  • ¿Cómo usar MediaMuxer / MediaCodec InputSurface con GLSurfaceView?
  • E / libEGL: error en el archivo de caché CRC check
  • OPENGL ES no funciona: no Contexto actual
  • Obtener un ANativeWindowBuffer de ANativeWindow_Buffer
  • Confusión entre OPEN GL ES y EGL library
  • Buffer automático al utilizar OpenGL en Android
  • Opengls eglCreateWindowSurface GL Error EGL_BAD_ALLOC
  • Cómo renderizar vídeo a través de openGLES2 con Android NDK
  • Android: ¿Es posible crear una SurfaceTexture sin SurfaceView?
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.