MacOS X:glGenFramebuffers()的意外行为

时间:2014-01-20 17:08:29

标签: c macos opengl

我正在进行涉及使用glGenFramebuffers()的OpenGL学习练习。但是,当我调用该函数时,似乎没有任何反应。我创建了以下简单程序来重现问题:

#define GL_GLEXT_PROTOTYPES
#include <stdio.h>
#include <GL/gl.h>
#include <GL/glext.h>

static GLuint fb[2];

int main(void)
{
    glGenFramebuffers(2, fb);
    printf("result: %u %u\n", fb[0], fb[1]);
    return 0;
}

$ gcc -std=c99 -I/usr/X11/include test.c -o test -L/usr/X11/lib -lGL -lOSMesa

$ ./test

输出为result: 0 0

根据http://www.opengl.org/wiki/GLAPI/glGenFramebuffers glGenFramebuffers()应设置fb [0]和fb [1]。我找不到在我的例子中解释实际结果的参考文献。我的真实代码的行为方式相同,所以我认为这不是一些初始化的问题。

我做错了什么或是某种错误?


编辑:即使我有上下文,也会发生同样的事情。这是一个更完整的代码版本。

#define GL_GLEXT_PROTOTYPES

#include <GL/gl.h>
#include <GL/glx.h>
#include <GL/glext.h>
#include <xcb/xcb.h>
#include <X11/Xlib-xcb.h>
#include <stdio.h>

static Display *display;
static xcb_connection_t *connection;
static xcb_window_t window;
static GLXDrawable drawable;
static GLXContext context;

static GLuint fb[2];

int main(void)
{
    display = XOpenDisplay(0);
    if (!display) return 0;

    int default_screen = XDefaultScreen(display);

    connection = XGetXCBConnection(display);
    if (!connection) goto error;

    int visualID = 0;

    XSetEventQueueOwner(display, XCBOwnsEventQueue);

    // find XCB screen
    xcb_screen_iterator_t screen_iter = xcb_setup_roots_iterator(xcb_get_setup(connection));
    int screen_num = default_screen;
    while (screen_iter.rem && screen_num > 0)
    {
        screen_num -= 1;
        xcb_screen_next(&screen_iter);
    }
    xcb_screen_t *screen = screen_iter.data;

    // query framebuffer configurations
    GLXFBConfig *fb_configs = 0;
    int num_fb_configs = 0;
    fb_configs = glXGetFBConfigs(display, default_screen, &num_fb_configs);
    if (!fb_configs || num_fb_configs == 0) goto error;

    // select first framebuffer config and query visualID
    GLXFBConfig fb_config = fb_configs[0];
    glXGetFBConfigAttrib(display, fb_config, GLX_VISUAL_ID , &visualID);

    // create OpenGL context
    context = glXCreateNewContext(display, fb_config, GLX_RGBA_TYPE, 0, True);
    if (!context) goto error;

    // create XID's for colormap and window
    xcb_colormap_t colormap = xcb_generate_id(connection);
    window = xcb_generate_id(connection);

    xcb_create_colormap(connection, XCB_COLORMAP_ALLOC_NONE, colormap, screen->root, visualID);

    uint32_t eventmask = XCB_EVENT_MASK_EXPOSURE | XCB_EVENT_MASK_KEY_PRESS | XCB_EVENT_MASK_KEY_RELEASE | XCB_EVENT_MASK_BUTTON_PRESS | XCB_EVENT_MASK_BUTTON_RELEASE;
    uint32_t valuelist[] = {eventmask, colormap, 0};
    uint32_t valuemask = XCB_CW_EVENT_MASK | XCB_CW_COLORMAP;

    // TODO set window parameters
    xcb_create_window(connection, XCB_COPY_FROM_PARENT, window, screen->root, 100, 0, 400, 300, 0, XCB_WINDOW_CLASS_INPUT_OUTPUT, visualID, valuemask, valuelist);

    // NOTE: window must be mapped before glXMakeContextCurrent
    xcb_map_window(connection, window); 

    drawable = glXCreateWindow(display, fb_config, window, 0);

    if (!window)
    {
        xcb_destroy_window(connection, window);
        glXDestroyContext(display, context);
        goto error;
    }

    // make OpenGL context current
    if (!glXMakeContextCurrent(display, drawable, drawable, context))
    {
        xcb_destroy_window(connection, window);
        glXDestroyContext(display, context);
        goto error;
    }

    glGenFramebuffers(2, fb);

    printf("%s\n", glGetString(GL_VERSION));
    printf("%d %d\n", fb[0], fb[1]);

    return 0;

error:
    XCloseDisplay(display);
}

输出:

2.1 NVIDIA-7.32.12
0 0

MacOS X 10.7.5

NVIDIA GeForce 320M 256 MB

$ gcc --version
i686-apple-darwin11-llvm-gcc-4.2 (GCC) 4.2.1 (Based on Apple Inc. build 5658) (LLVM build 2336.1.00)

glGetString(GL_VERSION):2.1 NVIDIA-7.32.12

3 个答案:

答案 0 :(得分:3)

FBO只是OpenGL 3.0+的核心。你获得了2.1背景。

Check支持EXT_framebuffer_object并使用glGenFramebuffersEXT()代替。

答案 1 :(得分:3)

调用该函数后检查glGetError (...)的值。 2.1环境中很可能GL_INVALID_OPERATION。您可以在OS X上从GL 2.1上下文中调用GL 3.x函数,但它们将始终生成GL_INVALID_OPERATION

这种情况与大多数其他平台完全不同,其中函数指针是在运行时设置的。在OS X上,无论您是GL 2.1上下文还是GL 3.2+核心,都链接到同一个库,其中包含Apple实现的每个GL版本的功能。这允许您调用上下文版本中未实现的函数。但是,除了设置GL_INVALID_OPERATION之外,任何调用这些函数的尝试都不会在运行时产生任何影响。

要解决此问题,您需要使用EXT形式的FBO,或获得3.2+核心上下文。由于在OS X上无法使用X11进行后续操作,因此您可能必须使用该扩展。我应该澄清一下,当我说使用FBO的扩展形式时,所有这些实际上在OS X上的invovles正在用glGenFramebuffers (...)替换glGenFramebuffersEXT (...)。您无需调用任何*GetProcAddress (...)函数。

或者你可以使用像SDL或GLFW3这样的框架,或者从X11 / GLX转移到NSOpenGL(Obj-C)或CGL(C / C ++)。在OS X上使用本机接口而不是AGL或X11 / GLX等弃用的东西是获得3.2核心上下文的唯一方法。

答案 2 :(得分:1)

您需要一个OpenGL上下文,但不创建一个。