PDA

View Full Version : gl lists and wglMakeCurrent



snow_master
06-17-2002, 09:23 AM
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.

knackered
06-17-2002, 09:37 AM
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.

snow_master
06-17-2002, 10:22 AM
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 ?

snow_master
06-17-2002, 10:24 AM
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...

knackered
06-17-2002, 12:45 PM
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?

knackered
06-17-2002, 12:49 PM
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.

jwatte
06-17-2002, 06:07 PM
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.

snow_master
06-17-2002, 10:35 PM
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);

snow_master
06-17-2002, 11:50 PM
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.

Relic
06-18-2002, 01:31 AM
No idea if that helps, but I find this suspicious (// comments in caps, no shouting. http://www.opengl.org/discussion_boards/ubb/smile.gif) :

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).]

snow_master
06-18-2002, 05:10 AM
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...

Jeeeez
06-18-2002, 06:09 AM
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 ???

knackered
06-18-2002, 01:29 PM
::ReleaseDC(hWnd, hDC);


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

snow_master
06-18-2002, 10:27 PM
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.....

Relic
06-19-2002, 01:33 AM
>>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. http://www.opengl.org/discussion_boards/ubb/smile.gif
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).]

Robbo
06-19-2002, 02:32 AM
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?

davepermen
06-19-2002, 02:40 AM
you can have several contexts per thread, but only one thread per context.

do you share the list? wglSharesomething?

snow_master
06-19-2002, 03:46 AM
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 ???

Relic
06-19-2002, 05:50 AM
"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.

snow_master
06-19-2002, 02:43 PM
>>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.

snow_master
06-28-2002, 01:36 AM
help...???...

Eric
06-28-2002, 01:49 AM
Could you try the following in your OnPaint function:





HGLRC hglrcOld=wglGetCurrentContext();
HDC hdcOld=wglGetCurrentDC();
BOOL result = ::glIsList(pArrDisplayListsNumbers[0]);
//result == true
BOOL l = wglMakeCurrent(hDC,m_hGLContext);
BOOL result = ::glIsList(pArrDisplayListsNumbers[0]);
//result == false


And tell us how hdcOld compares to hDC and how hglrcOld compares to m_hGLContext.

BTW, this snippet should produce an error at compilation time as you define result twice...

Regards.

Eric


[This message has been edited by Eric (edited 06-28-2002).]

Thaellin
06-28-2002, 03:49 AM
Originally posted by snow_master:
>>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.



Hi,

Display lists are context-specific unless you explicitly share them (using wglShareLists). The number of controls is not the issue, but the number of contexts is. Just try to use the call and see if your problem goes away.

Also, on an unrelated note, as a "heads-up": since you're using the shared DC pool to create your contexts, attempting to display more than a few contexts at a time will cause 'unexpected' results (most apparent under Win9x). If you run into this, modify the window class (not style, /class/) to use the CS_OWNDC flag (giving a unique private DC for the lifetime of the window).

Have fun,
-- Jeff

snow_master
07-01-2002, 03:57 AM
Eric,
I think you are on to something:
on the first call to onPaint, the list is still there, and the HDC hdcOld=wglGetCurrentDC(), returns a reference that differs from the one passed to wglMakeCurrent(hDC,m_hGLContext);
now, the hDC that is passed to wglMakeCurrent, is from:

HWND hWnd = GetSafeHwnd();
m_hDC = ::GetDC(hWnd);

on the second call to onPaint the list isn't there anymore and then the references are the same....
how could that be ?

snow_master
07-03-2002, 02:48 AM
Eric ?

Eric
07-03-2002, 07:23 AM
Originally posted by snow_master:
Eric ?

Sorry, I am trying to see how this can make sense !

Have you tried putting the CS_OWNDC flag in the window class as some people suggested ?

Regards.

Eric

snow_master
07-10-2002, 03:35 AM
Eric,
I inserted the CS_OWNDC flag, same result.
I will try to explain it again to make all of you maybe see it more clearer and organized:
I wrote an opengl using ocx.
Everything works fine when this ocx is ALONE on a dialog.
When I insert another opengl using ocx (a different one) I loose the display lists that I created, furthermore as Eric led me to find both the hdc and the glcontex values changes,
That is the wglGetCurrentDC(); isn’t the same dc as returned from ::GetDC(hWnd);, and the gl rendering context returned from the wglGetCurrentContext(); isn’t the same as the context member that was retrieved at create.
This is ONLY on the first iteration of the on paint function call, after they are ALWAYS the same.(but when I call the wglMakeCurrent on the first iteration I loose the display list from obvious reasons…)
If the ocx is ALONE on the dialog, from the start (including first call to on paint) the dc and rendering context are not changed and therefore the display lists are ok too.
I think this code will cover all possible question regarding creation and use of the dc and rendering context:

Creation code:
int D3Controller::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
if (COleControl::OnCreate(lpCreateStruct) == -1)
return -1;

//get the dc of this control
m_pDC = GetDC();

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

wglMakeCurrent(m_pDC->m_hDC, m_hGLContext);
//init the opengl scene.
CRect rect;
GetClientRect(&rect);
m_renderingCanvas->initScene(rect);
return 0;
}

///////////////////////////////////////////////
//
// Create the Pixel Format of the DC.
//
///////////////////////////////////////////////
BOOL D3Controller::createPixelFormat(HDC hdc)
{
//the pixel type
int nPixelType;
//define the pixel descriptor.
PIXELFORMATDESCRIPTOR pfd =
{
sizeof(PIXELFORMATDESCRIPTOR),
1,//version
PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER,//flags
PFD_TYPE_RGBA, //pixel type
24, //pixel size
0, 0, 0, 0, 0, 0,
0,
0,
0,
0, 0, 0, 0,
32,
0,
0,
PFD_MAIN_PLANE,
0,
0, 0, 0
};
//choose this pixel format
nPixelType = ChoosePixelFormat(hdc, &pfd);
return SetPixelFormat(hdc, nPixelType, &pfd);
}


the pre create window where I state the CS_OWNDC flag

BOOL D3Controller::PreCreateWindow(CREATESTRUCT& cs)
{
cs.lpszClass = ::AfxRegisterWndClass(CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS | CS_OWNDC,
::LoadCursor(NULL, IDC_ARROW), NULL, NULL);
cs.style |= WS_CLIPSIBLINGS | WS_CLIPCHILDREN;

return COleControl::PreCreateWindow(cs);
}

drawing code:

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

//get the hdc of this control
HWND hWnd = GetSafeHwnd();
HDC hDC = ::GetDC(hWnd);

//preform the uniform scale of the scene
m_renderingCanvas->setUniformScale(m_fScaleFactor);
//rotate the scene to the curent display c-arm angles
m_renderingCanvas->rotateOnXAxis((float)(m_thetaAngle));
m_renderingCanvas->rotateOnYAxis((float)(m_phiAngle));
//pan the scene
m_renderingCanvas->setXAndYTranslation(m_fXPanDelta, m_fYPanDelta);
//call the canvas paint function.
m_renderingCanvas->OnPaint(m_iNumberOf3DObjects, m_pArrDisplayListsNumbers, hDC);

//swap the buffers and flush.
glFlush();
SwapBuffers(m_pDC->m_hDC);
}


/////////////////////////////////////////////////////////////////
//
// the main paint function of the canvas
//
/////////////////////////////////////////////////////////////////
void RenderingCanvas::OnPaint(int numberOf3DObjects, unsigned int * pArrDisplayListsNumbers, HDC hDC)
{
if(numberOf3DObjects > 0)
BOOL ret = ::glIsList(pArrDisplayListsNumbers[0]);
//!!!!!!!!!**********these differ on the first iteration from hDC and from m_hGLContext !!!!!*********
HDC hdcOld=wglGetCurrentDC();
HGLRC hglrcOld=wglGetCurrentContext();

BOOL l = wglMakeCurrent(hDC,m_hGLContext);
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();
}


please help.......(-:

snow_master
07-11-2002, 08:38 AM
someone ????

snow_master
07-15-2002, 05:22 AM
you all gave up ???
to big of a challenge ??? (-: (trying to insert some motivation.....)

snow_master
07-26-2002, 05:44 AM
can any one direct me to a good ocx-opengl example ?