适用于OpenGL离屏渲染上下文的初始化代码

原创
2015/10/15 18:05
阅读数 258

说明

最近做图像算法,需要用到shader对图像进行处理,用glut会有窗口,不适合写成UT测试用例,需要创建一个无窗口的OpenGL上下文。

代码

这部分代码其实是参考 Android的Skia 模块相关代码写的,适用于 Mac、EGL(Android)、X11(Ubuntu等Linux系统)平台。

h文件

#ifndef GL_GLCONTEXT_H
#define GL_GLCONTEXT_H
class GLContext {
public:
    static bool init(int version=2);
    static void destroy();
};
#endif

cpp文件

#include "GL/GLContext.h"
#include <assert.h>

#ifdef GL_BUILD_FOR_ANDROID
//适用于 Android 和其他使用 EGL 标准的平台
#include <EGL/egl.h>
static EGLContext gContext;
static EGLDisplay gDisplay;
static EGLSurface gSurface;
bool GLContext::init(int version)
{
    gDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY);
    EGLint majorVersion;
    EGLint minorVersion;
    eglInitialize(gDisplay, &majorVersion, &minorVersion);
    EGLint numConfigs;
    static const EGLint configAttribs[] = {
        EGL_SURFACE_TYPE, EGL_PBUFFER_BIT,
        EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
        EGL_RED_SIZE, 8,
        EGL_GREEN_SIZE, 8,
        EGL_BLUE_SIZE, 8,
        EGL_ALPHA_SIZE, 8,
        EGL_NONE
    };

    EGLConfig surfaceConfig;
    eglChooseConfig(gDisplay, configAttribs, &surfaceConfig, 1, &numConfigs);

    static const EGLint contextAttribs[] = {
        EGL_CONTEXT_CLIENT_VERSION, version,
        EGL_NONE
    };
    gContext = eglCreateContext(gDisplay, surfaceConfig, NULL, contextAttribs);


    static const EGLint surfaceAttribs[] = {
            EGL_WIDTH, 1,
            EGL_HEIGHT, 1,
            EGL_NONE
        };
    gSurface = eglCreatePbufferSurface(gDisplay, surfaceConfig, surfaceAttribs);
    eglMakeCurrent(gDisplay, gSurface, gSurface, gContext);
    return true;
}

void GLContext::destroy()
{
    eglMakeCurrent(gDisplay, EGL_NO_SURFACE , EGL_NO_SURFACE , EGL_NO_CONTEXT);
    eglDestroyContext(gDisplay, gContext);
    eglDestroySurface(gDisplay, gSurface);
    eglTerminate(gDisplay);
    gDisplay = EGL_NO_DISPLAY;
}
#else
/*适用于Mac平台*/
#ifdef __APPLE__
#include <OpenGL/OpenGL.h>
CGLContextObj gContext;
bool GLContext::init(int version)
{
    CGLPixelFormatAttribute attributes[] = {
        kCGLPFADoubleBuffer,
        (CGLPixelFormatAttribute)0
    };
    CGLPixelFormatObj pixFormat;
    GLint npix;

    CGLChoosePixelFormat(attributes, &pixFormat, &npix);
    assert(NULL!=pixFormat);

    CGLCreateContext(pixFormat, NULL, &gContext);
    CGLReleasePixelFormat(pixFormat);
    assert(NULL!=gContext);
    CGLSetCurrentContext(gContext);
    return true;
}
void GLContext::destroy()
{
    CGLReleaseContext(gContext);
}
#else
/*这个是以前用在Ubuntu系统中的,使用了glew以打开shader功能,适用于 XDisplay*/
#include <GL/glew.h>
#include <GL/glut.h>
#include <X11/Xlib.h>
#include <GL/glx.h>
static GLXContext gContext;
static Pixmap gPixmap;
static GLXPixmap gGlxPixmap;
static Display* gDisplay = XOpenDisplay(0);
bool GLContext::init(int version)
{
    int fbcount;
    static int visual_attribs[] = {
        GLX_X_RENDERABLE    , True,
        GLX_DRAWABLE_TYPE   , GLX_PIXMAP_BIT,
        None
    };
    GLXFBConfig *fbc = glXChooseFBConfig(gDisplay, DefaultScreen(gDisplay),
            visual_attribs, &fbcount);
    int best_fbc = -1, best_num_samp = -1;

    int i;
    for (i = 0; i < fbcount; ++i) {
        XVisualInfo *vi = glXGetVisualFromFBConfig(gDisplay, fbc[i]);
        if (vi) {
            int samp_buf, samples;
            glXGetFBConfigAttrib(gDisplay, fbc[i], GLX_SAMPLE_BUFFERS, &samp_buf);
            glXGetFBConfigAttrib(gDisplay, fbc[i], GLX_SAMPLES, &samples);
            if (best_fbc < 0 || (samp_buf && samples > best_num_samp))
                best_fbc = i, best_num_samp = samples;
        }
        XFree(vi);
    }
    GLXFBConfig bestFbc = fbc[best_fbc];
    XFree(fbc);
    XVisualInfo *vi = glXGetVisualFromFBConfig(gDisplay, bestFbc);
    gPixmap = XCreatePixmap(gDisplay, RootWindow(gDisplay, vi->screen), 10, 10, vi->depth);
    gGlxPixmap = glXCreateGLXPixmap(gDisplay, vi, gPixmap);
    XFree(vi);
    gContext = glXCreateNewContext(gDisplay, bestFbc, GLX_RGBA_TYPE, 0, True);
    glXMakeCurrent(gDisplay, gGlxPixmap, gContext);
    glewInit();
    return true;
}

void GLContext::destroy()
{
    glXMakeCurrent(gDisplay, 0,0);
    glXDestroyContext(gDisplay, gContext);
    glXDestroyGLXPixmap(gDisplay, gGlxPixmap);
    XFreePixmap(gDisplay, gPixmap);
    gDisplay = NULL;
    XCloseDisplay(gDisplay);
}
#endif
#endif

版权声明:本文为博主原创文章,未经博主允许不得转载。

展开阅读全文
打赏
0
0 收藏
分享
加载中
更多评论
打赏
0 评论
0 收藏
0
分享
返回顶部
顶部