我在这里看到的真正问题是,它wglCreateContext
可能因任何原因而失败,你必须能够处理它。
话虽如此,您提出问题的方式让人觉得 OpenGL 上下文、设备上下文和窗口之间的关系存在根本性的误解。简单地说三个字:没有!
好的,这需要澄清。这是怎么回事?如果这些不相关,为什么会有一个HDC
参数?wglCreateContext
这一切都归结为像素格式(或帧缓冲区配置)。您可以在屏幕上看到的窗口是内存块的直接 1:1 表示。这块内存具有一定的像素格式。然而,只要只使用抽象绘图方法(就像 GDI 一样),所使用的精确像素格式并不重要,并且图形系统可以在它认为合适的时候默默地切换像素格式。在很久以前,当图形内存稀缺时,这可能意味着巨大的节省。
然而,OpenGL 假定使用特定的、不变的像素格式来操作帧缓冲区。因此,为了支持添加了一个新的 API,该 API 允许确定给定窗口的内部像素格式。然而,由于图形系统中唯一真正关心帧缓冲区格式的部分是绘制内容的部分,即 GDI,帧缓冲区配置通过该部分进行。HWND
s 与传递消息、将输入事件与应用程序相关联以及所有爵士乐相关。但它HDC
与所有图形相关。这就是为什么您通过HDC
.
创建 OpenGL 上下文时,必须为打算使用它的图形设备配置该上下文。这再次通过HDC
句柄寻址的 GDI 和数据结构。但是,一旦创建了 OpenGL 上下文,它就可以与任何 HDC
引用帧缓冲区的内容一起使用,该帧缓冲区的像素格式配置与HDC
最初创建的 OpenGL 上下文兼容。它可以是HDC
同一个窗口的不同,也可以是HDC
完全不同的窗口。并且自从 OpenGL-3.3 核心以来,OpenGL 上下文可以完全不HDC
更新,完全自包含,在自我管理的帧缓冲区上运行。最后但并非最不重要的一点是,该绑定可以随时更改。
每当对此没有清晰理解的人实现一些 OpenGL 绑定或抽象包装器时,他们往往会弄错这部分并创建不必要的紧身夹克,然后其他人,比如我,不得不拼命解决,因为抽象的工作方式是错误的。Qt 人犯了这个错误,GTK+ 人也犯了这个错误,现在看来你也犯了。您的 Github 项目页面上有此代码段:
let events_loop = glutin::EventsLoop::new();
let window = glutin::WindowBuilder::new()
.with_title("Hello, world!".to_string())
.with_dimensions(1024, 768)
.with_vsync()
.build(&events_loop)
.unwrap();
unsafe {
window.make_current()
}.unwrap();
unsafe {
gl::load_with(|symbol| window.get_proc_address(symbol) as *const _);
gl::ClearColor(0.0, 1.0, 0.0, 1.0);
}
啊啊啊啊。为什么这些方法make_current
与get_proc_address
窗口相关联?为什么?!这是谁想出来的?不要做这种狗屁事,它会让不得不使用这种东西的人的生活变得悲惨和痛苦。
你想知道这会导致什么吗?可怕的,凌乱的不安全代码,它会做令人作呕和肮脏的事情来强行直截了当地禁用一些现有的保护措施,以便它可以开始工作。就像我不得不做的这件可怕的事情一样,为了让 Qt4 对 OpenGL 如何工作的错误假设不再有影响。
#ifndef _WIN32
#if OCTPROCESSOR_CREATE_GLWIDGET_IN_THREAD
QGLFormat glformat(
QGL::DirectRendering |
QGL::DoubleBuffer |
QGL::Rgba |
QGL::AlphaChannel |
QGL::DepthBuffer,
0 );
glformat.setProfile(QGLFormat::CompatibilityProfile);
gl_hidden_widget = new QGLWidget(glformat);
if( !gl_hidden_widget ) {
qDebug() << "creating woker context failed";
goto fail_init_glcontext;
}
gl_hidden_widget->moveToThread( QThread::currentThread() );
#endif
if( !gl_hidden_widget->isValid() ) {
qDebug() << "worker context invalid";
goto fail_glcontext_valid;
}
gl_hidden_widget->makeCurrent();
#else
if( wglu_create_pbuffer_with_glrc(
3,3,WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB,
&m_hpbuffer,
&m_hdc,
&m_hglrc,
&m_share_hglrc)
){
qDebug() << "failed to create worker PBuffer and OpenGL context";
goto fail_init_glcontext;
}
qDebug()
<< "m_hdc" << m_hdc
<< "m_hglrc" << m_hglrc;
if( !wglMakeCurrent(m_hdc, m_hglrc) ){
qDebug() << "failed making OpenGL context current on PBuffer HDC";
goto fail_glcontext_valid;
}
#endif