我目前的实施适用于除Mobile Intel GM45之外的所有视频卡。不幸的是,当我试图在所述视频卡上呼叫wglMakeCurrent(sDC, sRC);
时,它完全崩溃了。我没有物理访问此视频卡。
在我的方法中,我在第一个sRC
的基础上重复使用相同的sDC
。
现在,我已经读过"如果两个窗口都使用相同的像素格式,则对两个窗口使用1个GL上下文" (http://www.opengl.org/wiki/Platform_specifics:_Windows#Multiple_Windows)您可以使用单个上下文和多个窗口(DC)执行此操作,并且如上所述,我的实现在所有其他视频卡上都能正常工作。
static HDC sDC = NULL;
static HGLRC sRC = NULL;
static HWND sOldWindow = NULL;
void GfxReset(HWND newWindow) {
if (sCurrentWindow != newWindow) {
if (sDC) {
AssertWGL(wglMakeCurrent(sDC, NULL));
AssertWGL(ReleaseDC(sCurrentWindow, sDC));
}
sDC = GetDC(newWindow);
Assert(sDC);
PrepareDC(sDC);
//Create the render context.
if (!sRC) {
sRC = wglCreateContext(sDC);
Assert(sRC);
}
AssertWGL(wglMakeCurrent(sDC, sRC)); // CRASH (not assertion)
sCurrentWindow = newWindow;
}
}
static void PrepareDC(HDC hDC) {
PIXELFORMATDESCRIPTOR pfd;
ZeroMemory(&pfd, sizeof(pfd));
pfd.nSize = sizeof(pfd);
pfd.nVersion = 1;
pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER;
pfd.iPixelType = PFD_TYPE_RGBA;
pfd.cColorBits = 32;
pfd.cDepthBits = 16;
pfd.cStencilBits = 8;
pfd.iLayerType = PFD_MAIN_PLANE;
int format = ChoosePixelFormat(hDC, &pfd);
Assert(format);
Assert(SetPixelFormat(hDC, format, &pfd));
}
我知道我可以使用多个上下文并使用wglShareLists
来实现此功能。我不想采取这种方式,因为必须在资产加载和诸如此类的方面重构很多代码。
有没有办法在OpenGL中使用单个上下文实现多个窗口,从而大大简化了纹理创建。否则,我必须知道我的应用程序中的所有窗口,并在开始加载纹理之前预先应用wglShareLists
,对吗?
编辑:我还尝试通过以下方式实现wglCreateContextAttribsARB
:http://www.opengl.org/wiki/Tutorial%3a_OpenGL_3.1_The_First_Triangle_%28C%2B%2B/Win%29但是,驱动程序在调用本身崩溃。
答案 0 :(得分:1)
首先,让我告诉你它是多么伟大,你的目标是上下文重用。但是,如果您需要解决驱动程序错误(这就是您正在遇到的问题,您所做的事情必须永远不会使程序崩溃。最坏的情况只会产生错误),然后使用wglShareLists解决它。
只要没有对象ID冲突,合并两个上下文的命名空间就完全没问题了。这意味着,您的主要上下文已经可以加载纹理和资源,只要您将命名空间合并到的上下文是" virgin"。那么"年龄较大的现有资产"上下文也会出现在新的上下文中。
我注意到你的代码:你写道:wglMakeCurrent(sDC, NULL)
表明你有一个概念,一个OpenGL RC以某种方式"绑定"一个可绘制的DC。这不是发生的事情。该关联实际上是在上下文和线程之间。建议的来电是wglMakeCurrent(NULL, NULL)
,坦率地说,我甚至不知道wglMakeCurrent(<someDC not NULL>, NULL)
的结果是否实际定义了。也许这实际上是你麻烦的原因。