我试图在Android原生进程中使用EGL_KHR_image_base来替换glReadPixels,因为它要慢(1280x800 RGBA为220ms)。
这是我到目前为止所做的,但是它产生了一个空缓冲区(只有零)
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();
我做错了什么?
答案 0 :(得分:5)
您正在创建一个空缓冲区,然后从中读取内容。浏览代码:
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);
这将创建一个新的GraphicBuffer
(有时称为“gralloc缓冲区”),具有指定的尺寸和像素格式。使用标志允许它用作纹理或从软件中读取,这是你想要的。
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);
这将获取ANativeWindow
对象(引擎盖下的缓冲区队列)并附加EGLImage
“句柄”。
glGenTextures(1, &mTexture);
glBindTexture(GL_TEXTURE_2D, mTexture);
glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, image);
这会创建一个新的纹理对象,并将EGLImage
附加到它上面。所以现在ANativeWindow
可以用作纹理对象。
window->lock(GraphicBuffer::USAGE_SW_READ_OFTEN, (void**)&ptr);
memcpy(texture, ptr, width * height * 4);
window->unlock();
这将锁定缓冲区以进行读取,从中复制数据并解锁。由于你没有画任何东西,所以没有什么可读的。
为了做一些有用的事情,你必须在纹理中渲染一些东西。您可以通过创建FBO并将纹理作为颜色缓冲区附加到其上,或者使用glCopyTexImage2D()
将帧缓冲区中的像素复制到纹理来完成此操作。
我可以在调用grallocBuffer->lock()
之前添加以下内容让您的示例正常工作:
glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 0, 0, width, height, 0);
glFinish();
在我们尝试查看像素之前,glFinish()
是确保GL完成复制像素所必需的。
修改:我的办公室伙伴建议GL_TEXTURE_2D
需要GL_TEXTURE_EXTERNAL_OES
。尚未尝试过。
修改:另请参阅this question。
答案 1 :(得分:0)
GraphicBuffer
是Android源代码的一部分,而不是NDK。
看到这个供你参考:
https://github.com/fuyufjh/GraphicBuffer