2013-08-30 10 views
6

Chcę przetwarzać obrazy poza ekranem na Androidzie w natywnym kodzie, więc potrzebuję utworzyć kontekst OpenGL w natywnym kodzie za pomocą EGL.Android inicjuje kontekst openGL2.0 za pomocą EGL

Przez EGL, możemy stworzyć EGLSurface widzę, istnieją trzy możliwości wyboru tam: * EGL_WINDOW_BIT * EGL_PIXMAP_BIT * EGL_BUFFER_BIT

Pierwszym z nich jest do przetwarzania na ekranie, drugi jest na off -screen, więc używam EGL_PIXMAP_BIT tak:

// 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); 

Kod zawiodły w punkcie 5, wydaje Android nie obsługuje wyłączyć przetwarzanie ekranu? Typ EGL_PIXMAP_BIT nie jest obsługiwany.!

Odpowiedz

12

Próbujesz użyć opcji EGL, które po prostu nie działają na Androidzie, a bufory działają tylko na niektórych procesorach graficznych - nie na Nvidii Tegra. pi32ConfigAttribs[] powinien wyglądać tak niezależnie od tego, czy będzie to na ekranie lub off-screen:

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 jest bardzo nieelastyczny w jaki wspierają one off ekranie EGLSurfaces. Zdefiniowali własny typ mapy pików o nazwie EGL_NATIVE_BUFFER_ANDROID.

Aby utworzyć powierzchnię EGL, która jest poza ekranem na Androidzie, należy skonstruować SurfaceTexture i przekazać ją do eglCreateWindowSurface(). Należy również spojrzeć na użyciu EGL Obraz Rozszerzenie i EGL_NATIVE_BUFFER_ANDROID, jak omówiono tutaj:

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: Oto przykładowy kod, który tworzy powierzchnię off-screen:

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

Jak utworzyć teksturę SurfaceTexture bez utworzonego kontekstu? Nie można ustawić kontekstu jako bieżącego kontekstu bez powierzchni ... – jjxtra

+0

Użyj EGLContext.getEGL(), aby uzyskać kontekst. – ClayMontgomery

+0

EGLContext.getEGL() nie istnieje. –