我们可以使用Open GL GLES20 API渲染图像并在Android上的小部件中显示结果吗?

时间:2014-04-15 14:10:07

标签: opengl-es android-widget

我们的Android应用程序使用Open GL渲染出漂亮的图像。 现在我们想要重新使用相同代码库的桌面应用小部件。 我们不需要实时。 静态图片没问题。

不幸的是,不可能将Open GL图形直接呈现给小部件。 Widget API受限于远程视图组件。

但是,如果我们只能将Open GL图形渲染到屏幕外缓冲区,然后将其导出为图像。然后我们可以创建一个ImageView并将图像添加到小部件。

我知道,可以创建一个Open GL曲面,同时拥有一个View。 但是在Android Widget的情况下没有View。 这是死路一条吗?

有没有办法在没有View的情况下创建一个屏幕外的Open GL曲面? 我们可以使用Open GL渲染图像并在Android上的小部件中显示结果吗?

[UPDATE] 我们的应用程序完全使用GLES20 API呈现内容。 有一个解决方案适用于旧的GL10 API - egl库。但它不适合我们的项目。

1 个答案:

答案 0 :(得分:1)

您几乎可以在所有情况下使用egl创建Opengl上下文。

编辑(放一个小例子egl + GLES2):

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

const EGLint attribs[] = { 
                EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
                EGL_BLUE_SIZE, 8,
                EGL_GREEN_SIZE, 8,
                EGL_RED_SIZE, 8,
                EGL_NONE
};

static const EGLint context_attribute_list[] = {
    EGL_CONTEXT_CLIENT_VERSION, 2,
    EGL_NONE
};

int main(int argc, char** argv) 
{
    EGLDisplay dpy;
    EGLContext ctx;
    EGLConfig config;
    EGLSurface surface;
    EGLint major, minor, n;
    ANativeWindow *window;
    GLint width, height;

    dpy = eglGetDisplay(EGL_DEFAULT_DISPLAY);

    if (dpy == EGL_NO_DISPLAY) {
      fprintf(stderr, "eglGetDisplay() failed\n");
      return -1;    
    }

    eglInitialize(dpy, &major, &minor);
    printf("GL Version: %d.%d\n", major, minor);

    if (!eglChooseConfig(dpy, attribs, &config, 1, &n))
    {
      printf("eglChooseConfig failed\n");
      printf("Error code: %x\n", eglGetError());
    }

     /* create an EGL rendering context */
    ctx = eglCreateContext(dpy, config, EGL_NO_CONTEXT, context_attribute_list);

    if (ctx == EGL_NO_CONTEXT) {
        printf("Error: eglCreateContext failed: %d\n", eglGetError());
        return -1;
    }

    window = android_createDisplaySurface();

    if (window == EGL_NO_SURFACE) {
        printf("Error: android_createDisplaySurface failed: %x\n", eglGetError());
        return -1;
    }

    surface = eglCreateWindowSurface(dpy, config, window, NULL);

    if (surface == EGL_NO_SURFACE) {
        printf("Error: eglCreateWindowSurface failed: %d\n", eglGetError());
        return -1;
    }

    if (!eglQuerySurface(dpy, surface, EGL_WIDTH, &width) ||
        !eglQuerySurface(dpy, surface, EGL_HEIGHT, &height)) {
        printf("Error: eglQuerySurface failed: %d\n", eglGetError());
        return -1;
    }

    printf("PBuffer: %dx%d\n", width, height);

    /* connect the context to the surface */
    if (!eglMakeCurrent(dpy, surface, surface, ctx)) {
        printf("Error: eglMakeCurrent() failed: %d\n", eglGetError());
        return -1;
    }

    glViewport(0, 0, width, height);
    /* clear the color buffer */
    glClearColor(1.0, 0.0, 0.0, 1.0);

    glClear(GL_COLOR_BUFFER_BIT);

    glFlush();

    eglSwapBuffers(dpy, surface);
    usleep(1000000);        

    return 0;
}

编译:

arm-linux-androideabi-gcc hello.c -o hello -lEGL -lGLESv2 -lui

在Android上

setEGLContextClientVersion(2);

seems启用GLES20。 (但我没有自己测试过)

注意:在linux上,通过cairo api,我用FBO进行了屏幕外渲染,(egl context)