2

我有一个库,它负责渲染来自网络的 opengl 和 primimaet 流。

我在罂粟下写的,但打算在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 中创建它?

4

2 回答 2

2

该线程没有当前的 OpenGL 上下文。即使您确实在程序的早期创建了上下文(在您的代码段中不可见),它也不会在您启动的线程中处于当前状态。

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

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

(可能不是坠机的原因,但......请参阅 datenwolf 的答案以了解坠机的可能原因——但它是错误的)`

于 2012-12-21T14:18:44.807 回答
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变得无效。

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

于 2012-12-21T14:23:22.910 回答