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)
- Qué superficie utilizar para eglMakeCurrent para el contexto que sólo se convierte en FBOs
- ¿Cómo acceder a EGL Image directamente desde Android Surface para su uso en el decodificador de video MediaCodec?
- Android: cómo averiguar la relación de aspecto exacta de píxeles de los dispositivos mediante programación?
- Rendimiento lento de glTexSubImage2D en Nexus 10 / Android 4.2.2 (Samsung Exynos 5 con Mali-T604)
- Cómo utilizar GraphicBuffer en android ndk
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 ?
- Android inicializa el contexto openGL2.0 con EGL
- EGL trabajando en Linux pero no en Android
- GLES2.0: Usar GL_TEXTURE_EXTERNAL_OES a través de glEGLImageTargetTexture2DOES
- Android EGL / OpenGL ES Frecuencia de fotogramas tartamudeando
- Tipo 'EGL_DEFAULT_DISPLAY' no se pudo resolver el error mientras que la constante está claramente definida
- ¿Qué sustituye a GraphicBuffer en Android 7.0?
- EglSwapBuffers es errático / lento
- Preservar el contenido del búfer tras eglSwapBuffers
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