PDA

View Full Version : PFD_DOUBLEBUFFER and resize crash



PeaceMaker
04-12-2004, 05:12 AM
Hi All.
Please, help to solve a problem.
I'm setting to a window PixelFormat with PFD_DOUBLEBUFFER flag.
Then in WM_SIZE handler, I'm changing glViewPort and glOrtho. Code is as in the common tutorials.
It works fine for the first time, but after some resizes program crashes WindowsNT with SP6 to blue screen.
It crashes somewhere inside after handling WM_SIZE, and it doesn't enter to the WM_PAINT handler.
On the other computer program crashes on SwapBuffers.
With out PFD_DOUBLEBUFFER same code works stable, but picture flicks on resize.
Also the MSDN example "CUBE" without my changes crashes after a lot of resizes.
I think it is the driver problem, but I need to avoid this problem by any mean. One way is to create memoryDC and use it as double buffer, but I don't want this way.
I'm waiting for help. Even thanx for some links.

plasmonster
04-12-2004, 07:57 AM
For a problem like this, I would begin a process of elimination, beginning with a few sanity checks. First, get rid of all non-essential code. That is, strip your app down to the nub, so that you basically have a "hello world" program, or in gl, a "hello clear screen". The idea is to remove/simplify code until you can isolate the problem, or satisfy yourself that it is not your code that is broken. This is brute force, but I'll assume you have exhausted the debugger's usefulness.

PeaceMaker
04-13-2004, 02:16 AM
Even sample program crashes to blue screen after a lot of resizes:
To get the crash PixelFormat's flag should contain both PFD_DOUBLEBUFFER and PFD_GENERIC_ACELERATED.

#include <windows.h>
#include <windowsx.h>
#include <GL\gl.h>

const char pszGLWNDCLASS[] = "OpenGLTestWindow";

HDC s_hDC = NULL;
HGLRC s_hRC = NULL;

HGLRC CreateRenderContext(HDC hDC)
{
PIXELFORMATDESCRIPTOR pfd;
memset(&amp;pfd,0,sizeof(pfd));
pfd.nSize = sizeof(pfd);
pfd.dwFlags = PFD_DOUBLEBUFFER | PFD_SUPPORT_OPENGL |
PFD_DRAW_TO_WINDOW | PFD_GENERIC_ACCELERATED;
pfd.nVersion = 1;
pfd.iPixelType = PFD_TYPE_RGBA;
pfd.iLayerType = PFD_MAIN_PLANE;
pfd.cColorBits = 32;
pfd.cAccumBits = 32;
pfd.cDepthBits = 32;
pfd.cAlphaBits = 32;
int nPixelFormat = ChoosePixelFormat(hDC,&amp;pfd);
if(!nPixelFormat) return NULL;
int nNumFormats = DescribePixelFormat(hDC,nPixelFormat,sizeof(pfd),&amp; pfd);
if(!(pfd.dwFlags & PFD_GENERIC_ACCELERATED))
for(int j = 1; j < nNumFormats; j++)
{
DescribePixelFormat(hDC,j,sizeof(pfd),&amp;pfd);
if(pfd.dwFlags & PFD_GENERIC_ACCELERATED)
{
nPixelFormat = j;
break;
}
}
if(!(pfd.dwFlags & PFD_GENERIC_ACCELERATED))
{
MessageBox(HWND_DESKTOP,
"Pixel Format flag should contain PFD_GENERIC_ACCELERATED",
"Cannot create window",MB_OK);
return NULL;
}
if(!SetPixelFormat(hDC,nPixelFormat,&amp;pfd)) return NULL;
return wglCreateContext(hDC);
}

void OnSize(HWND hwnd, UINT state, int cx, int cy)
{
if(cy <= 0) cy = 1;
glViewport(0,0,cx,cy);
glMatrixMode(GL_PROJECTION);
float m = (float)max(cx,cy);
float w = cx/m;
float h = cy/m;
glLoadIdentity();
glOrtho(-w,w,-h,h,-1,1);
glMatrixMode(GL_MODELVIEW);
InvalidateRect(hwnd,NULL,TRUE);
}

void OnPaint(HWND hwnd)
{
PAINTSTRUCT ps;
BeginPaint(hwnd,&amp;ps);
glLoadIdentity();
glClearColor(0.7f,0.7f,0.7f,0.7f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glBegin(GL_QUADS);
glColor3f(1,0.6f,0.6f);
glVertex3f(-1,-1,0);
glColor3f(0.6f,1,0.6f);
glVertex3f(-1, 1,0);
glColor3f(0.6f,0.6f,1);
glVertex3f( 1, 1,0);
glColor3f(1,1,0.6f);
glVertex3f( 1,-1,0);
glEnd();
glFlush();
glFinish();
SwapBuffers(wglGetCurrentDC());
EndPaint(hwnd,&amp;ps);
}

void OnDestroy(HWND hwnd)
{
wglMakeCurrent(NULL,NULL);
if(s_hDC) ReleaseDC(hwnd,s_hDC);
if(s_hRC) wglDeleteContext(s_hRC);
s_hDC = NULL;
s_hRC = NULL;
PostQuitMessage(0);
}

BOOL OnCreate(HWND hwnd, LPCREATESTRUCT lpCreateStruct)
{
s_hDC = GetDC(hwnd);
s_hRC = CreateRenderContext(s_hDC);
if(!s_hRC) return FALSE;
wglMakeCurrent(s_hDC,s_hRC);
return TRUE;
}

BOOL OnEraseBkgnd(HWND hwnd, HDC hdc)
{
return TRUE;
}

LRESULT CALLBACK GLWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch(message)
{
HANDLE_MSG(hWnd,WM_PAINT , OnPaint);
HANDLE_MSG(hWnd,WM_CREATE , OnCreate);
HANDLE_MSG(hWnd,WM_SIZE , OnSize);
HANDLE_MSG(hWnd,WM_DESTROY , OnDestroy);
HANDLE_MSG(hWnd,WM_ERASEBKGND, OnEraseBkgnd);
}
return DefWindowProc(hWnd, message, wParam, lParam);
}

int APIENTRY WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow)
{
WNDCLASS wc;
memset(&amp;wc,0,sizeof(wc));
wc.hCursor = LoadCursor(hInstance,IDC_ARROW);
wc.hInstance = hInstance;
wc.lpszClassName = pszGLWNDCLASS;
wc.lpfnWndProc = GLWndProc;
wc.style = CS_OWNDC | CS_DBLCLKS | CS_GLOBALCLASS;
if(!RegisterClass(&amp;wc)) return 0;
HWND hWnd = CreateWindowEx(WS_EX_OVERLAPPEDWINDOW,pszGLWNDCLAS S,"Test",
WS_OVERLAPPEDWINDOW | WS_VISIBLE | WS_CLIPCHILDREN | WS_CLIPSIBLINGS,
100,100,400,300,HWND_DESKTOP,NULL,hInstance,NULL);
if(!hWnd) return 0;
MSG msg;
while(GetMessage(&amp;msg,hWnd,0,0) > 0)
{
TranslateMessage(&amp;msg);
DispatchMessage(&amp;msg);
}
return 0;
}

plasmonster
04-13-2004, 08:39 AM
I had a quick scan of your code, it looked ok except for the paint function, try this:
BeginPaint(...);
EndPaint(...);
// now draw with gl
...

You don't want to mix gdi and gl, very naughty...

Relic
04-14-2004, 03:38 AM
There's no need for BeginPaint EndPaint anyway.
Normally you use it to get an HDC for painting and to reset the invalid paint regions.
But you already have a fixed global HDC, and validation of the paint region can be done with ValidateRect() at the end of the OpenGL drawing.