gl lists and wglMakeCurrent

Hi all,
I have the following problem:

after the call to wglMakeCurrent I “loose” my display lists:

BOOL result = ::glIsList(pArrDisplayListsNumbers[0]);
//result == true
BOOL l = wglMakeCurrent(hDC,m_hGLContext);
BOOL result = ::glIsList(pArrDisplayListsNumbers[0]);
//result == false

any ideas ?
thanks in advance.

Are you doing this:-

wglMakeCurrent(hDC2, m_hGLContext);
MakeDisplayLists();

BOOL result = ::glIsList(pArrDisplayListsNumbers[0]);
//result == true
BOOL l = wglMakeCurrent(hDC,m_hGLContext);
BOOL result = ::glIsList(pArrDisplayListsNumbers[0]);
//result == false

???
If you are, then I can’t see a problem.

what I am doing is:
at start :
//get the hdc of this ocx
HWND hWnd = GetSafeHwnd();
HDC hDC = ::GetDC(hWnd);
wglMakeCurrent(hDC,m_hGLContext);
MakeDisplayLists();

and then inside the OnPaint function
(because there are sevral opengl users ocx)

BOOL result = ::glIsList(pArrDisplayListsNumbers[0]);
//result == true
BOOL l = wglMakeCurrent(hDC,m_hGLContext);
BOOL result = ::glIsList(pArrDisplayListsNumbers[0]);
//result == false

why don’t you see a problem ?
why is it natural that the display lists I prepared will vanish ? is it because other ocx’s are using the opengl engine and it can’t store more then one hdc related lists ?

p.s
the hdc in the OnPaint function is beeing received the same way:
HWND hWnd = GetSafeHwnd();
HDC hDC = ::GetDC(hWnd);

p.p.s
how are you knackered ? long time no see…

Not bad, snowmaster.
When I said I didn’t see a problem, I meant I can’t figure out why you’re losing your display lists.

Is it something to do with threads? OnPaint is called from the MFC window message processing thread, so if you’re not creating the context in an equivalent callback (OnInitDialog or something) then you’ll have invalid contexts…dunno.
BTW, what hardware are you running it on? Driver version?

Just to clear something up - your wglMakeCurrent is returning TRUE, isn’t it? Both of them? It’s just that if you make your render context current to a dc, but then don’t release the context from that dc, then call makecurrent again on another dc, it will fail.

Is there more than one context going on? If so, you may need to use wglShareLists().

If not, perhaps there’s a threading thing going on; the same GLRC can only be used from a single thread if I remember correctly.

there are no threads, just the main ocx thread.
The wglMakeCurrent returns true.
the hardware is an ATI card Rage Fury with 5.13.1.3279 driver version.(I will check it on another computer to make sure it’s not a driver problem)
though, I am using double buffering, that is two dc…
the complete code is:
OnCreate of the ocx:
//get the hdc of this control
HWND hWnd = GetSafeHwnd();
HDC hDC = ::GetDC(hWnd);

//create the pixel format
if(!createPixelFormat(hDC))
return -1;
//create the opengl view render context
m_hGLContext = wglCreateContext(hDC);

if(m_hGLContext==NULL)
return -1;

wglMakeCurrent(hDC,m_hGLContext);::ReleaseDC(hWnd, hDC);
//init the opengl scene.
CRect rect;
GetClientRect(&rect);
m_renderingCanvas->initScene(rect);

OnPaint:
CPaintDC dc(this); // device context for painting

HWND hWnd = GetSafeHwnd();
HDC hDC = ::GetDC(hWnd);

if(m_iNumberOf3DObjects > 0)
BOOL p = glIsList(m_pArrDisplayListsNumbers[0]);
BOOL l = wglMakeCurrent(hDC,m_hGLContext);
if(numberOf3DObjects > 0)
BOOL ret = ::glIsList(pArrDisplayListsNumbers[0]);

glClear (GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
glLoadIdentity (); /* clear the matrix */

// viewing transformation
gluLookAt (m_eyeX, m_eyeY, m_eyeZ, m_centerX, m_centerY, m_centerZ, m_upX, m_upY, m_upZ);
setLightPosition();
::glPushMatrix();
if(m_bMulSceneByMatrix)
::glMultMatrixf(m_MultMatrix);
//translate the object on the y axis.
::glTranslatef(0.0f, m_fYTranslationDelta, 0.0f);
//translate the object on the x axis.
::glTranslatef(m_fXTranslationDelta, 0.0f, 0.0f);
//do a uniform scale on the object
::glScalef(m_fScaleFactor, m_fScaleFactor, m_fScaleFactor);
//rotate the object
::glRotatef(m_fYAxisRotationAngle, 0.0f, 1.0f, 0.0f);
::glRotatef(m_fXAxisRotationAngle, 1.0f, 0.0f, 0.0f);

//call all the 3d controller display lists
for(int i =0 ; i < numberOf3DObjects ; i++)
{
if(::glIsList(pArrDisplayListsNumbers[i]) == GL_TRUE)
{
::glCallList(pArrDisplayListsNumbers[i]);
}
}
::glPopMatrix();//swap the buffers and flush.
SwapBuffers(dc.m_ps.hdc);
glFlush();
::ReleaseDC(hWnd,hDC);

I want to add another piece to the puzzle:
when the ocx is placed ALONE on a dialog everything works fine.
when another opengl ocx is added to the dialog the problem occurs…
p.s
checked on another computer with different hardware, same results.

No idea if that helps, but I find this suspicious (// comments in caps, no shouting. ) :

wglMakeCurrent(hDC,m_hGLContext);
::ReleaseDC(hWnd, hDC); // WHY HERE?
//init the opengl scene.
CRect rect;
GetClientRect(&rect);
m_renderingCanvas->initScene(rect);

I would do this:

wglMakeCurrent(hDC,m_hGLContext);
//init the opengl scene.
CRect rect;
GetClientRect(&rect);
m_renderingCanvas->initScene(rect);
wglMakeCurrent(hDC, NULL); // ADDED
::ReleaseDC(hWnd, hDC); // MOVED

OnPaint:
CPaintDC dc(this); // device context for painting

HWND hWnd = GetSafeHwnd();
HDC hDC = ::GetDC(hWnd);
BOOL l = wglMakeCurrent(hDC,m_hGLContext); // MOVED

… // MATRIX STUFF

//call all the 3d controller display lists
for(int i =0 ; i < numberOf3DObjects ; i++)
{
if(::glIsList(pArrDisplayListsNumbers[i]) == GL_TRUE) // Actually this may be expensive and glCallList needs to check this anyway. You could replace this with one glCallLists() call.
{
::glCallList(pArrDisplayListsNumbers[i]);
}
}
::glPopMatrix();//swap the buffers and flush.
SwapBuffers(dc.m_ps.hdc); // Isn’t this hDC?
// glFlush(); // OBSOLETE

BOOL l = wglMakeCurrent(hDC, NULL); // ADDED
::ReleaseDC(hWnd,hDC);

And if you’re able to keep the context always current to one HDC per window, you only need to call one wglMakeCurrent(hDC,m_hGLContext) in WM_CREATE and one other wglMakeCurrent(hDC, NULL) in WM_DESTROY.

[This message has been edited by Relic (edited 06-18-2002).]

Relic:
>>I would do this:

>>wglMakeCurrent(hDC,m_hGLContext);
>>//init the opengl scene.
>>CRect rect;
>>GetClientRect(&rect);
>>m_renderingCanvas->initScene(rect);
>>wglMakeCurrent(hDC, NULL); // ADDED
>>::ReleaseDC(hWnd, hDC); // MOVED

if i add to the init the:
wglMakeCurrent(hDC, NULL);
then the ::glGenLists command fails.

i don’t see the logic of issue the wglMakeCurrent(hDC, NULL); command at init since the doc of wglMakeCurrent regarding NULL as hglrc is:
If hglrc is NULL, the function makes the calling thread’s current rendering context no longer current(!!!), and releases the device context that is used by the rendering context. In this case, hdc is ignored.

…and i think this is not what we want at init…

Hey there,

I dont know if this will solve the problem. Try calling wglMakeCurrent(NULL,NULL) right before wglMakeCurrent(dc,rc);

I have had many problems with the multiple rc thing, I had it working perfectly on my geforce2 but as soon as i moved to an ati rage pro, the rcs wouldnt work. The above solution didnt work either so ???

::ReleaseDC(hWnd, hDC);

I’m feeling a little slow this evening, but why are you releasing the windows dc?
This looks dodgy to me…

knackered,
I get and release the dc every call because there is a limited number of dc’s that the windows system can provide and it seems more wise to release it when I am not using it (that is when the ocx thread had been contexed out), but any how I tried getting it once an init and “never let go”, but the same thing…the ocx is working great on the dialog until the second opengl ocx is inserted to the dialog…
the strange thing is that the opengl for some reason does appear in the second ocx, and if I add some “non list included” opengl code it also appears, but the dam lists just disappear…

>>if i add to the init the:
>>wglMakeCurrent(hDC, NULL);
>>then the ::glGenLists command fails.

How should I know? There was no glGenLists in the code you posted.
I assumed you do all OpenGL init stuff including glGenLists in the initScene.

That said, only call OpenGL when a context is current, of course.

>>…and i think this is not what we want at init…<<

My proposed changes made it current around the places where OpenGL is used and not-current anywhere else. If you want to keep the context current all the time (my second suggestion), you need to keep the hDC, too!
HDCs you get from BeginPaint() can change and therefore may differ from the one you used in wglMakeCurrent (unless your window class style contains CS_OWN_DC).

On Win 3.1 there were only 5 HDCs for the whole system, this has completely changed with Win32. Many OpenGL apps grab the HDC at WM_CREATE and only let go on WM_DESTROY.

Note, if you have multiple contexts and want to share display lists, you need to use wglShareLists. It should work for identical pixelformats in multiple windows spawned by one process.

BTW, the HDC in wglMakeCurrent is ignored if the GL render context is NULL. wglMakeCurrent(hDC, NULL) and (NULL, NULL) has the same effect.

[This message has been edited by Relic (edited 06-19-2002).]

If your ocx is in-process, make sure you are not using singletons or anything like that.

Also, I was under the impression you could only have one opengl context per thread, not two. Perhaps this is the source of your problem?

you can have several contexts per thread, but only one thread per context.

do you share the list? wglSharesomething?

Relic,
I tried saving the dc from the init and use it all the time, but I get the same results

regarding the wglShareLists, I don’t need it since only one gl context is using the list in my ocx.
there are other ocx that are using open gl, but they create there own gl context and are using there own hdc.

Robbo: I am not using singletons, though I don’t understand why it would hurt anything (unless you meant putting the gl context as a singleton, and then they all use the same context…)

the thing that drives me crazy, is why the other ocx’s that are drawing not with display lists, and even in my own ocx when I am drawing not with display lists, the images appear !!
why does the ****ing display lists disappear ???

“regarding the wglShareLists, I don’t need it since only one gl context is using the list in my ocx.”

The questioin is if you’re trying to use the same display list anywhere else, i.e. in another ocx with another hdc and another OGL context.

If yes, you must use wglShareLists and those rendercontexts need to run on the same pixelformats and the windows must have been created by the same process.
Or you need to generate the lists in both contexts.

If no, well, I don’t know enough of ocx, and would try that with a standalone program opening two windows.

>>The questioin is if you’re trying to use >>the same display list anywhere else, i.e. >>in another ocx with another hdc and >>another OGL context.

No, the display list is only beeing used in this ocx.