2014-01-16 190 views
4

我想在android本機進程中使用EGL_KHR_image_base以取代glReadPixels,因爲它的速度較慢(22080爲1280x800 RGBA)。用EGL_KHR_image_base代替glReadPixels以獲得更快的像素複製

這是我到目前爲止,但我它會產生一個空的緩衝區(只有零)

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

您的寬度和高度是否非零? – HalR

+0

是的,我檢查了。它1280 * 800 – jacob

回答

4

您正在創建一個空緩衝區,然後從中讀取內容。走過的代碼:

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

+0

謝謝,你的幫助,它爲你工作? 我仍然得到一個空的緩衝區(儘管現在大約需要50ms),即使在添加之後: glCopyTexImage2D(GL_TEXTURE_2D,0,GL_RGBA,0,0,width,height,0); glFinish(); 你可以請看看: https://dl.dropboxusercontent。com/u/36894441/Overlay.cpp https://dl.dropboxusercontent.com/u/36894441/EglWindow.cpp – jacob

+0

我現在看到它不是一個完全空的緩衝區,而是每個4096000的開始處都是數據其餘的都是零。你可以發佈你試過的代碼嗎? – jacob

+0

嗯,我不是把圖像作爲圖像保存下來,只是檢查它是否全部爲零。在你的函數開始時,添加'glClearColor(0.5f,0.5f,0.5f,1.0f); glClear(GL_COLOR_BUFFER_BIT);'。這將填充50%灰度的幀,確保沒有任何字節值爲零。那麼你看到了什麼? (我可以發佈我的實驗前兩天。) – fadden