如果已经存在给定`HDC`(设备上下文)的DirectX上下文,`wglCreateContext`会安全失败

时间:2017-06-30 06:48:24

标签: windows opengl directx wgl

我正在尝试为一个跨平台,内存安全的API做出贡献,以便在Rust中创建和使用名为glutin的OpenGL上下文。我们努力以一种允许用户为预先存在的窗口创建GL上下文的方式重新设计API。

提出的一个问题是,如果用户尝试为具有预先存在的DirectX上下文的窗口创建GL上下文,则这可能不是内存安全的。

wglCreateContext的文档表明它会在失败时返回NULL,但是它没有详细说明可能导致此问题的条件。

如果给定的wglCreateContext(设备上下文)已存在DirectX上下文,NULL会安全失败(通过返回HDC)吗?或者这种情况下的行为是否未定义?

我无法访问支持OpenGL的Windows机器,我无法直接自行测试。

1 个答案:

答案 0 :(得分:0)

我在这里看到的真正问题是wglCreateContext可能因任何原因失败,你必须能够解决这个问题。

话虽如此,你提出问题的方式充满了对OpenGL上下文,设备上下文和窗口之间关系的根本误解。用三个简单的词来表达:没有!

好的,这需要澄清。这是什么交易?如果这些参数与HDC不相关,为什么会有wglCreateContext参数?

这一切都归结为像素格式(或帧缓冲配置)。您可以在屏幕上看到的窗口是一块内存块的直接1:1表示。该存储器块具有某种像素格式。然而,只要使用抽象绘图方法(如GDI),使用的精确像素格式无关紧要,图形系统可以按照其认为合适的方式静默切换像素格式。在很长一段时间内,当图形内存不足时,这可能意味着巨大的节省。

然而,OpenGL假设使用特定的,不变的像素格式来操作帧缓冲区。因此,为了支持添加新API,可以确定给定窗口的内部像素格式。然而,由于实际上与帧缓冲格式有关的图形系统的唯一部分是绘制内容的部分,即GDI,因此帧缓冲配置通过该部分发生。 HWND与传递消息,将输入事件与应用程序和所有爵士乐相关联有关。但是HDC与所有图形有关。这就是为什么你通过HDC设置像素格式。

创建OpenGL上下文时,必须为要使用的图形设备配置该上下文。这再次通过HDC句柄处理的GDI和数据结构。但是一旦创建了OpenGL上下文,它就可以与任何 HDC一起使用,这些 HDC指的是一个帧缓冲区,其配置的像素格式与HDC OpenGL兼容上下文最初是用。创建的。它可以是同一窗口的不同HDC,也可以是完全不同窗口的HDC。从OpenGL-3.3核心开始,OpenGL上下文可以在没有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); } 的情况下成为最新的,完全自包含,在自我管理的帧缓冲区上运行。最后但并非最不重要的是,可以随时更改绑定。

每当人们对此没有清楚的理解,实施一些OpenGL绑定或抽象包装时,他们往往会错误地创建这个部分并创建不必要的紧身直夹克,然后像我这样的其他人必须以他们的方式战斗因为抽象的工作方式是错误的。 Qt家伙犯了这个错误,GTK +这样做了,现在看来你显然也是如此。您的Github项目页面上有这段代码:

make_current

Arrrrggggh。为什么与窗口关联的方法get_proc_address#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 是什么?为什么?!谁想出了这个?不要这样做,它会使那些不得不使用这种悲惨和痛苦的人的生活。

你想知道这导致了什么吗?可怕的,乱糟糟的不安全的代码,做恶心和肮脏的事情强制和直接禁用一些保护措施,只是为了它可以去工作。就像我必须做的这件可怕的事情一样,让Qt4对OpenGL的工作方式做出错误的假设。

.translate {
  float: right;
  margin: 0 1.5rem;
}

.translate-icon {
  position: relative;
  cursor: pointer;
  font-size: 1.5rem;
}

.translate-icon:hover .translate-tooltip {
  display: block;
} 

.translate-tooltip {
  display: none;
  position: absolute;
  bottom: -1.75rem;
  right: -0.35rem;
  width: 13rem;
  text-align: center;
  font-size: 1rem;
  border: 1px solid gray;
}

.translate-tooltip::before,
.translate-tooltip::after {
  content: '';
  position: absolute;
  bottom: 100%;
  right: 0.25rem;
  width: 0;
  height: 0;
  border: solid transparent;
}
.translate-tooltip::before {
  border-bottom-color: gray;
  border-width: 9px;
}
.translate-tooltip::after {
  border-bottom-color: white;
  border-width: 8px;
  right: calc( 0.25rem + 1px );
}