Unrendered area on Intel OpenGL Win7 (with sample code & screenshots)

Hi,

I wrote an OpenGL program which includes a caption at the top of each view. This is achieved by overriding OnNcPaint() and OnNcCalcSize() in the view. This works on my machine, but one user (and probably many others) has a problem under Windows 7 on a laptop with Intel on-board graphics. The OpenGL area isn’t being shifted down by the caption. The geometry in the view is higher than it would be (making things difficult to select with the mouse), and leaves an unrendered section at the bottom of the view (the section is the same height as the caption above). See screenshots.

I adapted the MSDN Cube sample OpenGL program to demonstrate this effect. Code attached. To find my changes, look for “NEW_CODE” in CubeView.cpp. I left a deliberately unrendered area to the right of the caption, to see whether the OpenGL area would fill there since it was shifted up, but interestingly it doesn’t. Ignore that and look at the gap at the bottom in the screenshot from the buggy machine (I include one correct screenshot from my machine, and a bad one from the user’s machine).

Am I doing this the wrong way? Maybe since it works on other machines I’m doing the right thing, and Intel’s OpenGL is buggy (again), but is there a way to work around this?

Any ideas appreciated,
Thanks,
Rob.

[ATTACH=CONFIG]170[/ATTACH]

[ATTACH=CONFIG]171[/ATTACH]

I posted this almost a month ago. Has no one come across this before? Any ideas about how to work around it?

In case you’re wondering why I want a caption at the top of the view, it’s because I am using a splitter window, with several views, and need a caption above each one. But whether in a splitter or a single view, Intel refuses to acknowledge OnNcCalcSize() when deciding where to put OpenGL.

Is there even a way to find out where the OpenGL area actually ended up on the screen so I can recognise when this problem occurs?

Thanks,
Rob.

Can you post the code section where you set the viewport?

Edit: BTW, this is MFC right? :slight_smile:

Yes MFC. The only place the viewport is set is in OnSize (has not changed from the standard sample program).

void CCubeView::OnSize(UINT nType, int cx, int cy)
{
	CView::OnSize(nType, cx, cy);

	if(cy > 0)
	{
		glViewport(0, 0, cx, cy);

		if((m_oldRect.right > cx) || (m_oldRect.bottom > cy))
			RedrawWindow();

		m_oldRect.right = cx;
		m_oldRect.bottom = cy;

		glMatrixMode(GL_PROJECTION);
		glLoadIdentity();
		gluPerspective(45.0f, (GLdouble)cx/cy, 3.0f, 7.0f);
		glMatrixMode(GL_MODELVIEW);
	}
}

And here’s the new code to alter the client area:


void
CCubeView::OnNcCalcSize(BOOL bCalcValidRects, NCCALCSIZE_PARAMS *lpncsp)
{
	lpncsp->rgrc[0].top += GetSystemMetrics(SM_CYCAPTION);
	CView::OnNcCalcSize(bCalcValidRects, lpncsp);
}

All I’m doing is cropping a bit off the top of the view’s client area, and expecting OpenGL to fill the whole client area after that adjustment.

I don’t think there’s a bug, as it works find on most platforms. But there’s a lot of el-cheapo on-board Intel cards around unfortunately.

I should also mention that I probably confused things by leaving that unrendered half of the caption itself. Ignore that, it’s the unrendered part at the bottom that highlights the problem, which is that the whole view is shifted up from where it should be. Intel seem to have the height right, but they’ve positioned it at the normal client area’s top left corner, instead of my modified one. This also makes my GL selection not work as I am picking in the correct place, but it’s rendered in the wrong place.

Thanks,
Rob.

Do you actually call

void CCubeView::OnSize(UINT nType, int cx, int cy);

after recalculating the client area?

Are you absolutely sure that the values are correct?

I’d be very surprised if Intel got the viewport part wrong. On the other hand, it could also be that the device context isn’t setup correctly to reflect the new size so the viewport could be correct but would still not be able to cover the whole area. Not sure how this is handled by MFC. I’ve never had such troubles with GLUT or Qt - Intel or not.

I don’t explicitly call OnSize() or manually send a message, but actually this simple demo program is quite different in structure from the main program which I’m trying to fix. In my program glViewport() is called every frame in the draw routine, not in OnSize(), so there’s no chance it isn’t getting called or doesn’t have a GL context at the time. In both cases, the top left corner given is (0, 0).

You said you haven’t had problems before, but have you ever adjusted the top of the client area like this and seen it work on on-board Intel under Win7?

I don’t use GLUT. I wonder if their internals do a better job of things like this. How much work would be involved do you think for me to try setting up with GLUT instead? After a quick glance, my main concern would be the glutMainLoop() call. Seems that would restructure my code too much. Can I avoid their message handling loop? Can I use it within an MFC splitter view and still share GL contexts?

Thanks,
Rob.

Let me get this straight: You simply want to display some caption on top of the OpenGL viewport, right?

Basically yes, although my captions also have an icon to the left, various buttons that come and go overlaid on the right, and respond to mouse clicks in a few ways.

I think you’re thinking along the same lines as me, which is that I’ll probably have to do away with OnNcCalcSize() and set the viewport myself to skip the top section. Then it is a matter of how to render that caption.

If I render the caption in OpenGL then I might need an extra font loaded to match Windows, plus drawing the icon and buttons in the appropriate style for the Windows theme. And need to handle the mouse interaction differently too for the buttons. It’s all a bit of a pain for this one annoying glitch.

Maybe another option is to create a separate win32 window to place over the OpenGL view and contain the caption. Probably also a pain, but might work.

I was really just hoping for a simpler way to get my original method to work.

Thoughts?
Rob.

Here’s what I’d do in Qt:

[ul]
[li]Create a main window [/li][li]Create a widget which will simply be used as a container for the caption label, buttons and so on - this will have a fixed height, say 40 pixels [/li][li]Create a GL widget [/li][li]Add the caption widget and add it to the central widget and then add the GL widget to the central widget [/li][/ul]

This way Qt will handle the resizing of the client area the GL widget will occupy automatically and all I’d need to do is have the GL widget call its resize() function which will in turn set the viewport.

I don’t know how this can be done in MFC but trying to it your way seems quite complicated and like an overkill to me.

The easiest solution would be to create two child windows - one for you’re caption bar, and one to render opengl into. That way you just need to resize/reposition the child windows in response to WM_SIZE/WM_MOVE messages in the app window, and set the viewport accordingly.

I have a test case working now, by overlaying a child window with the caption in it.

I did it this way to avoid messing with the CSplitterWnd…CView relationship and to avoid moving GL out of the CView.

Now I just resize the caption when the view changes size, and adjust the top of the GL viewport down accordingly.

Seems to work. Is there likely to be a performance hit on any platform due to the caption window always partially obscuring the GL window? Even then it’s not obscuring the GL viewport, so should be fine.

All feels a bit dodgy though. Pity I have to do this! It’s not the first Intel-only GL bug I’ve had to work around.

Thanks,
Rob.

This topic was automatically closed 183 days after the last reply. New replies are no longer allowed.