我有一个问题,涉及到Intel显卡HD 3000和Toshiba笔记本(操作系统Win7 x32,编程语言C++)。
传统的单一上下文OpenGL应用程序可以正常工作,但在单个应用程序中创建多个OpenGL上下文会产生奇怪的行为:
1. 在我的旧应用程序版本中,Intel驱动程序根本无法创建第二个渲染上下文。 2. 在我基于OpenGL的软件架构进行了重大更改后,行为发生了变化。现在我能够创建第二个渲染上下文,但在释放它之后(使用/关闭窗口后),驱动程序不能再创建任何下一个渲染上下文。这已经在多个应用程序上进行了测试,并且始终表现相同。为了清晰起见,第二个OpenGL渲染上下文用于打开/保存对话框(预览子窗口)。 驱动程序信息:
传统的单一上下文OpenGL应用程序可以正常工作,但在单个应用程序中创建多个OpenGL上下文会产生奇怪的行为:
1. 在我的旧应用程序版本中,Intel驱动程序根本无法创建第二个渲染上下文。 2. 在我基于OpenGL的软件架构进行了重大更改后,行为发生了变化。现在我能够创建第二个渲染上下文,但在释放它之后(使用/关闭窗口后),驱动程序不能再创建任何下一个渲染上下文。这已经在多个应用程序上进行了测试,并且始终表现相同。为了清晰起见,第二个OpenGL渲染上下文用于打开/保存对话框(预览子窗口)。 驱动程序信息:
Intel(R) HD Graphics 3000
OpenGL ver: 3.1.0 - Build 9.17.10.2932
OpenGL 引擎中的 初始化和退出 OpenGL 代码:
//------------------------------------------------------------------------------
int OpenGLscreen::init(void *f,int textures)
{
if (_init) exit();
frm=(formtype*)f;
hdc = GetDC(frm->Handle); // get device context
int i;
if (!_used)
{
int i,_pfid=-1,_zbit=0;
PIXELFORMATDESCRIPTOR _pfd;
#define pfd_test i=ChoosePixelFormat(hdc,&pfd); DescribePixelFormat(hdc,i,sizeof(_pfd),&_pfd); if (_zbit<_pfd.cDepthBits) { _zbit=_pfd.cDepthBits; _pfid=i; }
pfd.cColorBits = 32; pfd.cDepthBits = 32; pfd_test;
pfd.cColorBits = 24; pfd.cDepthBits = 32; pfd_test;
pfd.cColorBits = 16; pfd.cDepthBits = 32; pfd_test;
pfd.cColorBits = 32; pfd.cDepthBits = 24; pfd_test;
pfd.cColorBits = 24; pfd.cDepthBits = 24; pfd_test;
pfd.cColorBits = 16; pfd.cDepthBits = 24; pfd_test;
pfd.cColorBits = 32; pfd.cDepthBits = 16; pfd_test;
pfd.cColorBits = 24; pfd.cDepthBits = 16; pfd_test;
pfd.cColorBits = 16; pfd.cDepthBits = 16; pfd_test;
#undef pfd_test
pfd.cDepthBits = _zbit; // iba koli warningu
DescribePixelFormat(hdc,_pfid,sizeof(pfd),&pfd);
pfid=ChoosePixelFormat(hdc,&pfd);
SetPixelFormat(hdc,pfid,&pfd);
DescribePixelFormat(hdc,pfid,sizeof(pfd),&pfd);
znum=1<<(pfd.cDepthBits-1);
}
// create current rendering context
hrc = wglCreateContext(hdc);
if(hrc == NULL)
{
ShowMessage("Could not initialize OpenGL Rendering context !!!");
_init=0;
return 0;
}
if(wglMakeCurrent(hdc, hrc) == false)
{
ShowMessage("Could not make current OpenGL Rendering context !!!");
wglDeleteContext(hrc); // destroy rendering context
_init=0;
return 0;
}
if (!_used) glewInit();
_init=1;
_used=1;
resize(0,0,128,128);
// glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
// glFrontFace(GL_CCW); // predna strana je proti smeru hod. ruciciek
// glEnable(GL_CULL_FACE); // vynechavaj odvratene steny
// glEnable(GL_TEXTURE_2D); // pouzivaj textury, farbu pouzivaj z textury
// glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL);
// glEnable(GL_BLEND); // priehladnost
// glBlendFunc(GL_SRC_ALPHA,GL_DST_ALPHA);
/*
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
glEnable(GL_COLOR_MATERIAL);
GLdouble MaterialAmbient [] = {0.25, 0.25, 0.25, 1.00};
GLdouble MaterialDiffuse [] = {0.25, 0.25, 0.25, 1.00};
GLdouble MaterialSpecular [] = {0.50, 0.50, 0.50, 1.00};
GLdouble MaterialShininess[] = {15.0}; // 0-ufocused, 128 max focus
glMaterialfv(GL_FRONT, GL_AMBIENT , MaterialAmbient );
glMaterialfv(GL_FRONT, GL_DIFFUSE , MaterialDiffuse );
glMaterialfv(GL_FRONT, GL_SPECULAR , MaterialSpecular );
glMaterialfv(GL_FRONT, GL_SHININESS, MaterialShininess);
glColorMaterial(GL_FRONT, GL_AMBIENT_AND_DIFFUSE);
GLdouble LightPosition [] = {0.00, 0.00, 0.00, 0.0};
GLdouble LightAmbient [] = {0.10, 0.10, 0.10, 1.0};
GLdouble LightDiffuse [] = {0.20, 0.20, 0.20, 1.0};
GLdouble LightSpecular [] = {1.00, 1.00, 1.00, 1.0};
glLightfv(GL_LIGHT0,GL_AMBIENT ,LightAmbient );
glLightfv(GL_LIGHT0,GL_DIFFUSE ,LightDiffuse );
glLightfv(GL_LIGHT0,GL_SPECULAR,LightSpecular);
glLightfv(GL_LIGHT0,GL_POSITION,LightPosition);
glLightModelfv(GL_LIGHT_MODEL_AMBIENT, LightAmbient);
*/
glEnable(GL_DEPTH_TEST); // Zbuf
glShadeModel(GL_SMOOTH); // gourard shading
glClearColor(0.0f, 0.0f, 0.0f, 1.0f); // background color
glDepthFunc(GL_LEQUAL);
const GLubyte *p; char a; // get extensions list
extensions="";
#define ext_add if ((extensions!="")&&(extensions[extensions.Length()]!=' ')) extensions+=' '; for (i=0;;i++) { a=p[i]; if (!a) break; extensions+=a; }
p=glGetString(GL_EXTENSIONS); ext_add;
if (wglGetExtensionsStringARB) p=wglGetExtensionsStringARB(hdc); ext_add;
if (wglGetExtensionsStringEXT) p=wglGetExtensionsStringEXT(); ext_add;
// int hnd=FileCreate("glext.txt"); FileWrite(hnd,scr.extensions.c_str(),scr.extensions.Length()); FileClose(hnd);
OpenGLtexture txr;
txrs.alloc(textures); // allocate textures name space
font_init(txr);
font=txrs.add(txr);
s3dl=txrs.add(txr); txrs.sizes[s3dl]._mode=GL_MODULATE;
s3dr=txrs.add(txr); txrs.sizes[s3dr]._mode=GL_MODULATE;
return 1;
}
//------------------------------------------------------------------------------
void OpenGLscreen::exit()
{
if (!_init) return;
wglMakeCurrent(hdc,hrc); // use this context if multiple OpenGLs are used
txrs.free();
wglMakeCurrent(NULL, NULL); // release current rendering context
wglDeleteContext(hrc); // destroy rendering context
hrc=NULL;
_init=0;
}
//------------------------------------------------------------------------------
现在的问题:
我有什么做错了吗?
引擎完全正常,支持GL,GLSL,VBO,VAO,...并且已经测试了多年。奇怪的行为只在Intel上出现。nVidia的显卡运行良好,ATI/AMD几乎良好(存在一些问题,但这些问题通常与有缺陷的驱动程序相关,尤其是对于使用索引的VBO,其他都工作良好)。
有更好的初始化/退出OpenGL的方法吗?
如何正确地在不同的渲染上下文之间切换?
我目前正在使用
wglMakeCurrent(hdc,hrc)
,但可能我还漏掉了一些东西或者在Intel上有一些解决方法。