2013-08-30 29 views
6

Tôi muốn thực hiện xử lý hình ảnh ngoài màn hình trên Android bằng mã gốc, vì vậy tôi cần tạo ngữ cảnh openGL trong mã gốc bằng EGL.Android initialise openGL2.0 context with EGL

By EGL, chúng ta có thể tạo EGLSurface, tôi có thể thấy có ba sự lựa chọn đó: * EGL_WINDOW_BIT * EGL_PIXMAP_BIT * EGL_BUFFER_BIT

Người đầu tiên là xử lý trên màn hình, điều thứ hai là cho off -screen, vì vậy tôi sử dụng EGL_PIXMAP_BIT như thế này:

// Step 1 - Get the default display. 
EGLDisplay eglDisplay = eglGetDisplay((EGLNativeDisplayType) 0); 
if ((eglDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY)) == EGL_NO_DISPLAY) { 
    LOGH("eglGetDisplay() returned error %d", eglGetError()); 
    exit(-1); 
} 

// Step 2 - Initialize EGL. 
if (!eglInitialize(eglDisplay, 0, 0)) { 
    LOGH("eglInitialize() returned error %d", eglGetError()); 
    exit(-1); 
} 

// Step 3 - Make OpenGL ES the current API. 
eglBindAPI(EGL_OPENGL_ES_API); 

// Step 4 - Specify the required configuration attributes. 
EGLint pi32ConfigAttribs[] = { EGL_SURFACE_TYPE, EGL_PIXMAP_BIT, 
     EGL_BLUE_SIZE, 8, EGL_GREEN_SIZE, 8, EGL_RED_SIZE, 8, EGL_NONE, 
     EGL_BIND_TO_TEXTURE_RGBA, EGL_TRUE }; 

// Step 5 - Find a config that matches all requirements. 
int iConfigs; 
EGLConfig eglConfig; 
eglChooseConfig(eglDisplay, pi32ConfigAttribs, &eglConfig, 1, &iConfigs); 
if (iConfigs != 1) { 
    LOGH(
      "Error: eglChooseConfig(): config not found %d - %d.\n", eglGetError(), iConfigs); 
    exit(-1); 
} 

// Step 6 - Create a surface to draw to. 
EGLSurface eglSurface = eglCreatePbufferSurface(eglDisplay, eglConfig, 
     NULL); 

// Step 7 - Create a context. 
EGLContext eglContext = eglCreateContext(eglDisplay, eglConfig, NULL, 
     ai32ContextAttribs); 

// Step 8 - Bind the context to the current thread 
eglMakeCurrent(eglDisplay, eglSurface, eglSurface, eglContext); 

Mã không thành công ở bước 5, có vẻ như Android không hỗ trợ xử lý màn hình? Loại EGL_PIXMAP_BIT không được hỗ trợ.!

Trả lời

12

Bạn đang cố gắng sử dụng các tùy chọn EGL không hoạt động trên Android và pbuffers chỉ hoạt động trên một số GPU - không phải Nvidia Tegra. pi32ConfigAttribs[] sẽ trông như thế này cho dù nó sẽ được trên màn hình hoặc tắt màn hình:

EGLint pi32ConfigAttribs[] = 
{ 
    EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, 
    EGL_RED_SIZE, 8, 
    EGL_GREEN_SIZE, 8, 
    EGL_BLUE_SIZE, 8, 
    EGL_ALPHA_SIZE, 8, 
    EGL_DEPTH_SIZE, 0, 
    EGL_STENCIL_SIZE, 0, 
    EGL_NONE 
}; 

Android là rất linh hoạt trong cách họ hỗ trợ EGLSurfaces tắt màn hình. Họ đã xác định loại hình bản đồ của riêng mình có tên là EGL_NATIVE_BUFFER_ANDROID.

Để tạo bề mặt EGL bị tắt trên màn hình trên Android, hãy tạo SurfaceTexture và chuyển cho eglCreateWindowSurface(). Bạn cũng nên xem xét sử dụng các hình ảnh mở rộng EGL và EGL_NATIVE_BUFFER_ANDROID, như đã thảo luận ở đây:

http://software.intel.com/en-us/articles/using-opengl-es-to-accelerate-apps-with-legacy-2d-guis

http://software.intel.com/en-us/articles/porting-opengl-games-to-android-on-intel-atom-processors-part-1

UPDATE: Dưới đây là một số mẫu mã mà tạo ra một bề mặt off-màn hình:

private EGL10 mEgl; 
private EGLConfig[] maEGLconfigs; 
private EGLDisplay mEglDisplay = null; 
private EGLContext mEglContext = null; 
private EGLSurface mEglSurface = null; 
private EGLSurface[] maEglSurfaces = new EGLSurface[MAX_SURFACES]; 

@Override 
public void onSurfaceTextureAvailable(SurfaceTexture surfaceTexture, int width, int height) 
{ 
    InitializeEGL(); 
    CreateSurfaceEGL(surfaceTexture, width, height); 
} 

private void InitializeEGL() 
{ 
    mEgl = (EGL10)EGLContext.getEGL(); 

    mEglDisplay = mEgl.eglGetDisplay(EGL10.EGL_DEFAULT_DISPLAY); 

    if (mEglDisplay == EGL10.EGL_NO_DISPLAY) 
     throw new RuntimeException("Error: eglGetDisplay() Failed " + GLUtils.getEGLErrorString(mEgl.eglGetError())); 

    int[] version = new int[2]; 

    if (!mEgl.eglInitialize(mEglDisplay, version)) 
     throw new RuntimeException("Error: eglInitialize() Failed " + GLUtils.getEGLErrorString(mEgl.eglGetError())); 

    maEGLconfigs = new EGLConfig[1]; 

    int[] configsCount = new int[1]; 
    int[] configSpec = new int[] 
    { 
     EGL10.EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, 
     EGL10.EGL_RED_SIZE, 8, 
     EGL10.EGL_GREEN_SIZE, 8, 
     EGL10.EGL_BLUE_SIZE, 8, 
     EGL10.EGL_ALPHA_SIZE, 8, 
     EGL10.EGL_DEPTH_SIZE, 0, 
     EGL10.EGL_STENCIL_SIZE, 0, 
     EGL10.EGL_NONE 
    }; 
    if ((!mEgl.eglChooseConfig(mEglDisplay, configSpec, maEGLconfigs, 1, configsCount)) || (configsCount[0] == 0)) 
     throw new IllegalArgumentException("Error: eglChooseConfig() Failed " + GLUtils.getEGLErrorString(mEgl.eglGetError())); 

    if (maEGLconfigs[0] == null) 
     throw new RuntimeException("Error: eglConfig() not Initialized"); 

    int[] attrib_list = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL10.EGL_NONE }; 

    mEglContext = mEgl.eglCreateContext(mEglDisplay, maEGLconfigs[0], EGL10.EGL_NO_CONTEXT, attrib_list); 
} 

private void CreateSurfaceEGL(SurfaceTexture surfaceTexture, int width, int height) 
{ 
    surfaceTexture.setDefaultBufferSize(width, height); 

    mEglSurface = mEgl.eglCreateWindowSurface(mEglDisplay, maEGLconfigs[0], surfaceTexture, null); 

    if (mEglSurface == null || mEglSurface == EGL10.EGL_NO_SURFACE) 
    { 
     int error = mEgl.eglGetError(); 

     if (error == EGL10.EGL_BAD_NATIVE_WINDOW) 
     { 
      Log.e(LOG_TAG, "Error: createWindowSurface() Returned EGL_BAD_NATIVE_WINDOW."); 
      return; 
     } 
     throw new RuntimeException("Error: createWindowSurface() Failed " + GLUtils.getEGLErrorString(error)); 
    } 
    if (!mEgl.eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface, mEglContext)) 
     throw new RuntimeException("Error: eglMakeCurrent() Failed " + GLUtils.getEGLErrorString(mEgl.eglGetError())); 

    int[] widthResult = new int[1]; 
    int[] heightResult = new int[1]; 

    mEgl.eglQuerySurface(mEglDisplay, mEglSurface, EGL10.EGL_WIDTH, widthResult); 
    mEgl.eglQuerySurface(mEglDisplay, mEglSurface, EGL10.EGL_HEIGHT, heightResult); 
    Log.i(LOG_TAG, "EGL Surface Dimensions:" + widthResult[0] + " " + heightResult[0]); 
} 

private void DeleteSurfaceEGL(EGLSurface eglSurface) 
{ 
    if (eglSurface != EGL10.EGL_NO_SURFACE) 
     mEgl.eglDestroySurface(mEglDisplay, eglSurface); 
} 
+0

Làm cách nào để tạo SurfaceTexture mà không có ngữ cảnh được tạo? Không thể đặt ngữ cảnh làm ngữ cảnh hiện tại mà không có bề mặt ... – jjxtra

+0

Sử dụng EGLContext.getEGL() để lấy ngữ cảnh. – ClayMontgomery

+0

EGLContext.getEGL() không tồn tại. –

Các vấn đề liên quan