在线程中使用opengl

时间:2012-12-21 12:11:48

标签: opengl

我有一个库,用于渲染来自网络的opengl和prinimaet流。

我在罂粟下写字,但计划在linux上使用

所以窗口是为目标c创建的 我开始在另一个线程中绘制接收和解码数据。

我在opengl的方法上崩溃了错误(EXT_BAD_ACCESS),即使我只在一个线程中使用它们。

我的代码 主要过剩:

int main(int argc, const char * argv[]){
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DOUBLE|GLUT_RGBA);
int win = glutGetWindow();
glutInitWindowSize(800, 600);
glutCreateWindow("OpenGL lesson 1");
client_init(1280, 720, win, "192.168.0.98", 8000, 2222);
return 0;

}

或目标c

- (id)initWithFrame:(NSRect)frameRect pixelFormat:(NSOpenGLPixelFormat*)format{
self = [super initWithFrame:frameRect];
if (self != nil) {
    NSOpenGLPixelFormatAttribute attributes[] = {

        NSOpenGLPFANoRecovery,
        NSOpenGLPFAFullScreen,
        NSOpenGLPFAScreenMask,
        CGDisplayIDToOpenGLDisplayMask(kCGDirectMainDisplay),
        (NSOpenGLPixelFormatAttribute) 0
    };
    _pixelFormat = [[NSOpenGLPixelFormat alloc] initWithAttributes:attributes];
    if (!_pixelFormat)
    {
        return nil;
    }
    //_pixelFormat   = [format retain];
    [[NSNotificationCenter defaultCenter] addObserver:self
                                             selector:@selector(_surfaceNeedsUpdate:)
                                                 name:NSViewGlobalFrameDidChangeNotification
                                               object:self];
    _openGLContext = [self openGLContext];
    client_init(1280, 720, win, "192.168.0.98", 8000, 2222);
}
return self;

}

client_init代码

    // pthread_create(&posixThreadID, NULL, (void*(*)(void*))ShowThread, dh_tmp);
pthread_create(&posixThreadID, NULL, (void*(*)(void*))ShowThread, NULL);

void* ShowThread(struct drawhandle * dh){

        //glViewport(0, 0, dh->swidth, dh->sheight);//EXT_BAD_ACCESS
        glViewport(0, 0, 1280, 720);//EXT_BAD_ACCESS

        glMatrixMode(GL_PROJECTION);
        glLoadIdentity();
        //gluOrtho2D(0, dh->swidth, 0, dh->sheight);
        gluOrtho2D(0, 1280, 0, 720);

        glMatrixMode(GL_MODELVIEW);
        glLoadIdentity();

    ...
        return 0;
    }

我认为问题是什么?那个未创建的上下文opengl。

如何在macos / linux中创建它?

2 个答案:

答案 0 :(得分:2)

此线程没有当前的OpenGL上下文。即使您之前在程序中创建了一个上下文(在您的代码段中不可见),它也不会是您启动的主题中的最新内容。

OpenGL上下文总是,没有例外,一次只有一个线程的“当前”。默认情况下,这是创建上下文的线程。任何调用OpenGL的线程都必须先“当前”。

必须在此线程中创建上下文,或者调用glXMakeCurrent(Unix / Linux)或aglMakeCurrent(Mac)或wglMakeCurrent(Windows)在ShowThread内(在做与OpenGL相关的任何其他事情之前)。

(可能不是崩溃的原因,但是......看看datenwolf对崩溃可能原因的回答 - 尽管这是错误的)`

答案 1 :(得分:1)

OpenGL和多线程处理困难。它可以做到,但需要一些照顾。首先,OpenGL上下文一次只能在一个线程中处于活动状态。在某些系统上,如Windows扩展函数指针是每个上下文,因此对于不同线程中的不同上下文,您可能最终会得到不同的扩展函数指针,必须为其配置。

所以第一个问题是:你可能在这个线程上没有OpenGL上下文,但这不应该在调用非扩展函数时崩溃,它只会做什么。

如果它确实在您指定的行上崩溃,那么dh指针无效是肯定的。这是唯一的解释。 C中的指针只是一些以特殊方式解释的数字。如果你传递指针 - 特别是如果用作回调或线程函数的参数 - 那么指向指针的对象必须不会无效,直到它确保无法再访问该指针为止。这意味着:您不能在堆栈上创建的内容上使用它,即在C自动存储中。

这会破坏:

void foo(void)
{
    struct drawhandle dh_tmp;

    pthread_create(&posixThreadID, NULL, (void*(*)(void*))ShowThread, &dh_tmp);
}

为什么呢?因为时间foo返回对象dh_tmp无效。但是&dh_tmp(指向它的指针)只是一个数字,当dh_tmp无效时,这个数字不会“神奇地”变为零。

您必须在堆上分配它才能使其正常工作。当然有问题,何时再次释放内存。