2014-05-21 56 views
0

我想在我的Raspberry上使用OpenGL ES 2繪製一個矩形,其RGB像素值將存儲在內存的緩衝區中,以便通過CPU進一步處理。使用opengl繪製紋理並將紋理映射到系統RAM

換句話說,這是路徑:RAM中的RGB緩衝區 - > GPU上的紋理 - >繪製 - >回到RAM。最終,通過閱讀以下簡單的程序,我想要做的事情應該清楚。

我曾嘗試通過eglCreateImageKHR本質上創建一個EGLImage方面要做到這一點,但該程序失敗,錯誤0x501(從GLCHK宏觀斷言):

#include <bcm_host.h> 

#include <GLES2/gl2.h> 
#include <GLES2/gl2ext.h> 
#include <EGL/egl.h> 

#include <iostream> 
#include <stdexcept> 
#include <cassert> 
#include <system_error> 
#include <memory> 

/* Uncomment to enable extra GL error checking */ 
#define CHECK_GL_ERRORS 
#if defined(CHECK_GL_ERRORS) 
#define GLCHK(X) \ 
do { \ 
    GLenum err = GL_NO_ERROR; \ 
    X; \ 
    while ((err = glGetError())) \ 
    { \ 
     std::cout << "GL error " << err << " in file " << __FILE__<< ", line " << __LINE__ << ' '; \ 
     assert(err == GL_NO_ERROR); \ 
     exit(err); \ 
    } \ 
} \ 
while(0) 
#else 
#define GLCHK(X) X 
#endif /* CHECK_GL_ERRORS */ 

void demo() { 
    EGLDisplay eglDisplay = 0; 
    EGLConfig eglConfigWindow = 0; 
    EGLSurface eglSurfacePbuffer = 0; 
    EGLContext eglContext = 0; 

    const EGLint attribListWindow[] = { 
             EGL_SURFACE_TYPE, EGL_PBUFFER_BIT, 
             EGL_RED_SIZE, 8, 
             EGL_GREEN_SIZE, 8, 
             EGL_BLUE_SIZE, 8, 
             EGL_ALPHA_SIZE, 8, 
             EGL_DEPTH_SIZE, 16, 
             EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, 
             EGL_NONE          
    }; 
    const EGLint srfPbufferAttr[] = { 
            EGL_WIDTH, 640, 
            EGL_HEIGHT, 480, 
            EGL_NONE 
    }; 

    const EGLint context_attribs[] = { 
     EGL_CONTEXT_CLIENT_VERSION, 1, 
     EGL_NONE 
    }; 

    EGLint iMajorVersion, iMinorVersion; 
    int iConfigs; 

    eglDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY); 
    if (eglDisplay == EGL_NO_DISPLAY) 
     throw std::runtime_error {"error eglGetDisaply()"}; 

    auto result = eglInitialize(eglDisplay, &iMajorVersion, &iMinorVersion); 
    if (result == EGL_FALSE) 
     throw std::runtime_error {"error eglInitialize()"}; 

    //result = eglChooseConfig(eglDisplay, attribListPbuffer, &eglConfigWindow, 1, &iConfigs); 
    result = eglChooseConfig(eglDisplay, attribListWindow, &eglConfigWindow, 1, &iConfigs); 
    if (result == EGL_FALSE) 
     throw std::system_error(result, std::generic_category(), "Error setting configuration for the given display: check your settings"); 

    auto context = eglContext = eglCreateContext(eglDisplay, eglConfigWindow, EGL_NO_CONTEXT, context_attribs); 
    if (context == EGL_NO_CONTEXT) 
     throw std::runtime_error{"error eglCreateContext()"};     

    eglSurfacePbuffer = eglCreatePbufferSurface(eglDisplay, eglConfigWindow, srfPbufferAttr); 
    if (eglSurfacePbuffer == EGL_NO_SURFACE) 
     throw std::runtime_error{"error CreatePbufferSurface(). " + std::to_string(eglGetError())};     

    eglMakeCurrent(eglDisplay, eglSurfacePbuffer, eglSurfacePbuffer, eglContext); 

    GLuint texture;       // Name for the preview texture 
    EGLImageKHR egl_image = EGL_NO_IMAGE_KHR; // The current preview EGL image 

    glClearColor(0x11, 0x22, 0x33, 0); // random color 
    glClearDepthf(1); 
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 

    const int bytes_per_pixel = 4; 
    unsigned char buffer[640 * 480 * bytes_per_pixel] = {}; // 0x77 to see if it will be changed somehow 

    GLCHK(glBindTexture(GL_TEXTURE_EXTERNAL_OES, texture)); 
    egl_image = eglCreateImageKHR(eglDisplay, EGL_NO_CONTEXT, EGL_IMAGE_BRCM_MULTIMEDIA, (EGLClientBuffer) buffer, NULL); 
    GLCHK(glEGLImageTargetTexture2DOES(GL_TEXTURE_EXTERNAL_OES, &egl_image)); 

    glReadPixels(0, 0, 640, 480, GL_RGBA, GL_UNSIGNED_BYTE, buffer); 
    if (glGetError() != GL_NO_ERROR) 
     throw std::runtime_error{"error glReadPixels():" + std::to_string(eglGetError())}; 

    eglSwapBuffers(eglDisplay, eglSurfacePbuffer); 

    // print the buffer pixel values, should be different from 0x00 
    for (auto x : buffer) 
     std::cout << std::hex << int(x) << ' '; 

    // Terminate 

    /* Delete OES textures */ 
    glDeleteTextures(1, &texture); 
    eglDestroyImageKHR(eglDisplay, egl_image); 
    egl_image = EGL_NO_IMAGE_KHR; 

    /* Terminate EGL */ 
    eglMakeCurrent(eglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); 
    eglDestroyContext(eglDisplay, context); 
    eglDestroySurface(eglDisplay, eglSurfacePbuffer); 
    eglTerminate(eglDisplay); 
} 

int main() { 
    atexit(bcm_host_deinit); 
    bcm_host_init(); 
    demo(); 
} 

回答

0

夫婦的代碼中的問題。你請求ES 1.0範圍內,而一切都在你的代碼,你的問題一樣,建議您打算使用ES 2.0:

const EGLint context_attribs[] = { 
    EGL_CONTEXT_CLIENT_VERSION, 1, 
    EGL_NONE 
}; 

您需要的客戶端版本2 ES 2.0。

最直接的問題是,你正在使用的texture變量初始化:

GLuint texture;       // Name for the preview texture 
... 
GLCHK(glBindTexture(GL_TEXTURE_EXTERNAL_OES, texture)); 

texture沒有設置這兩個語句之間。你需要一個glGenTextures(1, &texture)來創建一個有效的紋理ID。