• Announcements

    • khawk

      Download the Game Design and Indie Game Marketing Freebook   07/19/17

      GameDev.net and CRC Press have teamed up to bring a free ebook of content curated from top titles published by CRC Press. The freebook, Practices of Game Design & Indie Game Marketing, includes chapters from The Art of Game Design: A Book of Lenses, A Practical Guide to Indie Game Marketing, and An Architectural Approach to Level Design. The GameDev.net FreeBook is relevant to game designers, developers, and those interested in learning more about the challenges in game development. We know game development can be a tough discipline and business, so we picked several chapters from CRC Press titles that we thought would be of interest to you, the GameDev.net audience, in your journey to design, develop, and market your next game. The free ebook is available through CRC Press by clicking here. The Curated Books The Art of Game Design: A Book of Lenses, Second Edition, by Jesse Schell Presents 100+ sets of questions, or different lenses, for viewing a game’s design, encompassing diverse fields such as psychology, architecture, music, film, software engineering, theme park design, mathematics, anthropology, and more. Written by one of the world's top game designers, this book describes the deepest and most fundamental principles of game design, demonstrating how tactics used in board, card, and athletic games also work in video games. It provides practical instruction on creating world-class games that will be played again and again. View it here. A Practical Guide to Indie Game Marketing, by Joel Dreskin Marketing is an essential but too frequently overlooked or minimized component of the release plan for indie games. A Practical Guide to Indie Game Marketing provides you with the tools needed to build visibility and sell your indie games. With special focus on those developers with small budgets and limited staff and resources, this book is packed with tangible recommendations and techniques that you can put to use immediately. As a seasoned professional of the indie game arena, author Joel Dreskin gives you insight into practical, real-world experiences of marketing numerous successful games and also provides stories of the failures. View it here. An Architectural Approach to Level Design This is one of the first books to integrate architectural and spatial design theory with the field of level design. The book presents architectural techniques and theories for level designers to use in their own work. It connects architecture and level design in different ways that address the practical elements of how designers construct space and the experiential elements of how and why humans interact with this space. Throughout the text, readers learn skills for spatial layout, evoking emotion through gamespaces, and creating better levels through architectural theory. View it here. Learn more and download the ebook by clicking here. Did you know? GameDev.net and CRC Press also recently teamed up to bring GDNet+ Members up to a 20% discount on all CRC Press books. Learn more about this and other benefits here.
Sign in to follow this  
Followers 0
Alex Melbourne

Sluggish OpenGL performance using Win32

14 posts in this topic

Just to simplify everything here is a copy of the source file in question:
[source lang="cpp"]
/*
** main.cpp
*/

# include <stdlib.h>
# include <time.h>

# include <windows.h>
# if defined(_WINDOWS_)
# include <gl\gl.h>
# endif /* defined(_WINDOWS_) */

LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);

HDC hdc;
PIXELFORMATDESCRIPTOR pfd;
int format;
HGLRC hglrc;

/*
** entry point
*/
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd)
{
WNDCLASS WndClass;
HWND hWnd;
MSG msg;

WndClass.style = CS_OWNDC | CS_HREDRAW | CS_VREDRAW;
WndClass.lpfnWndProc = WndProc;
WndClass.cbClsExtra = 0;
WndClass.cbWndExtra = 0;
WndClass.hInstance = hInstance;
WndClass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
WndClass.hCursor = LoadCursor(NULL, IDC_ARROW);
WndClass.hbrBackground = NULL;
WndClass.lpszMenuName = NULL;
WndClass.lpszClassName = "greyscale";

if(RegisterClass(&WndClass) == 0)
{
MessageBox(NULL, "Unable to register the window's class.", "", MB_OK | MB_ICONERROR);
return 0;
}

hWnd = CreateWindow("greyscale", "greyscale", WS_OVERLAPPEDWINDOW | WS_VISIBLE,
100, 100, 800, 600, NULL, NULL, hInstance, NULL);
if(!hWnd)
{
MessageBox(NULL, "Failed to create window.", "", MB_OK | MB_ICONERROR);
return 0;
}

hdc = GetDC(hWnd);

ZeroMemory(&pfd, sizeof(PIXELFORMATDESCRIPTOR));
pfd.nSize = sizeof(PIXELFORMATDESCRIPTOR);
pfd.nVersion = 1;
pfd.dwFlags = PFD_SUPPORT_OPENGL | PFD_DRAW_TO_WINDOW;
pfd.iPixelType = PFD_TYPE_RGBA;
pfd.cColorBits = 24;

format = ChoosePixelFormat(hdc, &pfd);
SetPixelFormat(hdc, format, &pfd);

hglrc = wglCreateContext(hdc);
if(!hglrc)
{
MessageBox(NULL, "Failed to create context for OpenGL.", "", MB_OK | MB_ICONERROR);
return 0;
}

if(wglMakeCurrent(hdc, hglrc) == FALSE)
{
MessageBox(NULL, "Unable to change the current context.", "", MB_OK | MB_ICONERROR);
return 0;
}

ReleaseDC(hWnd, hdc);

ShowWindow(hWnd, nShowCmd);
UpdateWindow(hWnd);

glClearColor(0.0f, 1.0f, 0.0f, 0.0f);

for(;;)
{
if(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
{
if(msg.message == WM_QUIT)
break;

TranslateMessage(&msg);
DispatchMessage(&msg);
}

glClear(GL_COLOR_BUFFER_BIT);
glFlush();
}

wglMakeCurrent(NULL, NULL);
wglDeleteContext(hglrc);

return msg.wParam;
}

/*
** message handler
*/
LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch(msg)
{
case WM_NULL:
{
return 0;
}

case WM_DESTROY:
{
PostQuitMessage(0);
return 0;
}

case WM_CLOSE:
{
if(MessageBox(hWnd, "Are you sure you want to exit?", "", MB_YESNO | MB_ICONQUESTION) == IDYES)
DestroyWindow(hWnd);

return 0;
}
}

return DefWindowProc(hWnd, msg, wParam, lParam);
}

[/source]

This has been bugging me for a while so I thought I might as well see if it's happened to anyone else or see if someone can tell me how badly I'm going wrong.

I've finally managed to get OpenGL rendering within Win32 (and not through the other third party libraries like GLUT).

My issue though is that when I actually include rendering commands in the main loop the window [b]appears to become unresponsive[/b]. I say appears because I can drag it around occasionally and it takes ages to respond.

The issue disappears with I remove the Clear and Flush commands in the loop.

I've added a timer (not shown above) to limit the speed at when the rendering runs and the issue then goes away. The only conclusion I can come to is that the OpenGL commands take to long and cause PeekMessage to miss messages in the queue (that was all I had, I only started Win32 yesterday so I'm probably wrong).

The code compiles correctly and produces no errors in Visual Studio. What exactly is causing this behaviour? Edited by BinaryPhysics
0

Share this post


Link to post
Share on other sites
Well, you don't want to use 'glFlush', that's for certain. While that can flush commands to be executed you are basically telling the driver 'clear the same bit of memory over and over' - you need to call the 'swapbuffers' function (I can't recall the Win32 function for it) to make anything really happen.

The other consideration is do you even get a hardware context? If this is executing in software you are basically running a tight loop clearly memory over and over again and the OpenGL1.1 Software implementation is basically a bit load of rubbish so might explain things.

In short;
- check you aren't in software
- don't call glFlush EVER (until you know when you should call it in the future of course)
- even if in hardware your test case is broken so drawing conclusions from it aren't valid - GL calls don't take a long time to execute as most just push commands into a command queue and do work 'later' (generally a few frames later)
2

Share this post


Link to post
Share on other sites
[quote name='phantom' timestamp='1341789341' post='4957067']Well, you don't want to use 'glFlush', that's for certain.[/quote]

But this is a single buffered program. What exactly would I end up swapping too?

[quote name='phantom' timestamp='1341789341' post='4957067']The other consideration is do you even get a hardware context? [...] the OpenGL1.1 Software implementation is basically a bit load of rubbish so might explain things.[/quote]

Is that not anything to do with the CreateContext command? I found a copy of the OpenGL Programming Guide (Release 1) so everything I've learnt is from there.

[quote name='phantom' timestamp='1341789341' post='4957067']even if in hardware your test case is broken so drawing conclusions from it aren't valid - GL calls don't take a long time to execute as most just push commands into a command queue and do work 'later' (generally a few frames later)[/quote]

I figured I was probably wrong (otherwise you wouldn't have the 'remove' choice when calling PeekMessage) but I'm honestly confused why it seems to crawl to a standstill when it isn't regulated. Edited by BinaryPhysics
0

Share this post


Link to post
Share on other sites
Oh, i missed the single buffered bit.... chances are between that, the 24bit color restriction and just grabbing the first context you might well be running on a slow software path.

Any reason you DONT want double buffering anyway?
0

Share this post


Link to post
Share on other sites
[quote name='BinaryPhysics' timestamp='1341788244' post='4957061']
Just to simplify everything here is a copy of the source file in question:
[source lang="cpp"]
/*
** main.cpp
*/

# include <stdlib.h>
# include <time.h>

# include <windows.h>
# if defined(_WINDOWS_)
# include <gl\gl.h>
# endif /* defined(_WINDOWS_) */

LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);

HDC hdc;
PIXELFORMATDESCRIPTOR pfd;
int format;
HGLRC hglrc;

/*
** entry point
*/
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd)
{
WNDCLASS WndClass;
HWND hWnd;
MSG msg;

WndClass.style = CS_OWNDC | CS_HREDRAW | CS_VREDRAW;
WndClass.lpfnWndProc = WndProc;
WndClass.cbClsExtra = 0;
WndClass.cbWndExtra = 0;
WndClass.hInstance = hInstance;
WndClass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
WndClass.hCursor = LoadCursor(NULL, IDC_ARROW);
WndClass.hbrBackground = NULL;
WndClass.lpszMenuName = NULL;
WndClass.lpszClassName = "greyscale";

if(RegisterClass(&WndClass) == 0)
{
MessageBox(NULL, "Unable to register the window's class.", "", MB_OK | MB_ICONERROR);
return 0;
}

hWnd = CreateWindow("greyscale", "greyscale", WS_OVERLAPPEDWINDOW | WS_VISIBLE,
100, 100, 800, 600, NULL, NULL, hInstance, NULL);
if(!hWnd)
{
MessageBox(NULL, "Failed to create window.", "", MB_OK | MB_ICONERROR);
return 0;
}

hdc = GetDC(hWnd);

ZeroMemory(&pfd, sizeof(PIXELFORMATDESCRIPTOR));
pfd.nSize = sizeof(PIXELFORMATDESCRIPTOR);
pfd.nVersion = 1;
pfd.dwFlags = PFD_SUPPORT_OPENGL | PFD_DRAW_TO_WINDOW;
pfd.iPixelType = PFD_TYPE_RGBA;
pfd.cColorBits = 24;

format = ChoosePixelFormat(hdc, &pfd);
SetPixelFormat(hdc, format, &pfd);

hglrc = wglCreateContext(hdc);
if(!hglrc)
{
MessageBox(NULL, "Failed to create context for OpenGL.", "", MB_OK | MB_ICONERROR);
return 0;
}

if(wglMakeCurrent(hdc, hglrc) == FALSE)
{
MessageBox(NULL, "Unable to change the current context.", "", MB_OK | MB_ICONERROR);
return 0;
}

ReleaseDC(hWnd, hdc);

ShowWindow(hWnd, nShowCmd);
UpdateWindow(hWnd);

glClearColor(0.0f, 1.0f, 0.0f, 0.0f);

for(;;)
{
if(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
{
if(msg.message == WM_QUIT)
break;

TranslateMessage(&msg);
DispatchMessage(&msg);
}

glClear(GL_COLOR_BUFFER_BIT);
glFlush();
}

wglMakeCurrent(NULL, NULL);
wglDeleteContext(hglrc);

return msg.wParam;
}

/*
** message handler
*/
LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch(msg)
{
case WM_NULL:
{
return 0;
}

case WM_DESTROY:
{
PostQuitMessage(0);
return 0;
}

case WM_CLOSE:
{
if(MessageBox(hWnd, "Are you sure you want to exit?", "", MB_YESNO | MB_ICONQUESTION) == IDYES)
DestroyWindow(hWnd);

return 0;
}
}

return DefWindowProc(hWnd, msg, wParam, lParam);
}

[/source]

This has been bugging me for a while so I thought I might as well see if it's happened to anyone else or see if someone can tell me how badly I'm going wrong.

I've finally managed to get OpenGL rendering within Win32 (and not through the other third party libraries like GLUT).

My issue though is that when I actually include rendering commands in the main loop the window [b]appears to become unresponsive[/b]. I say appears because I can drag it around occasionally and it takes ages to respond.

The issue disappears with I remove the Clear and Flush commands in the loop.

I've added a timer (not shown above) to limit the speed at when the rendering runs and the issue then goes away. The only conclusion I can come to is that the OpenGL commands take to long and cause PeekMessage to miss messages in the queue (that was all I had, I only started Win32 yesterday so I'm probably wrong).

The code compiles correctly and produces no errors in Visual Studio. What exactly is causing this behaviour?
[/quote]

The big killer is this:

[code]
if(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
{
if(msg.message == WM_QUIT)
break;

TranslateMessage(&msg);
DispatchMessage(&msg);
}

glClear(GL_COLOR_BUFFER_BIT);
glFlush();
[/code]

change that if to a while, otherwise you only process 1 window message per frame and the message queue will get flooded if you do anything that generates alot of messages (such as moving the window)
2

Share this post


Link to post
Share on other sites
[quote name='phantom' timestamp='1341791443' post='4957078']Any reason you DONT want double buffering anyway?[/quote]

Not in the slightest. When learning stuff in the past, I've had a tendency to move far to fast and begin stumbling over further topics that I lack any grounding in. I've got the first copy of OpenGL 1.0 and I've done the first 6 chapters (I need to go back over lighting though). The only reason I'm ignore any use of buffers is that I simply haven't learnt it yet.

[quote name='SimonForsman' timestamp='1341792608' post='4957083'][...] change that if to a while, otherwise you only process 1 window message per frame...[/quote]

When I read this I actually wanted to slap myself. I can't believe I missed something so theoretically simple. Thank-you so much.

Although that didn't actually solve the problem... Now I'm running with a while loop to process all the built up messages and I removed call to Flush. The program now slows down my entire laptop.
0

Share this post


Link to post
Share on other sites
Post the code...

and add this.

[CODE]
pfd.nSize = sizeof( PIXELFORMATDESCRIPTOR );
pfd.nVersion = 1;
pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER;
pfd.iPixelType = PFD_TYPE_RGBA;
pfd.cColorBits = 32;
pfd.cDepthBits = 24;
pfd.cStencilBits = 0;
[/CODE] Edited by mark ds
0

Share this post


Link to post
Share on other sites
[quote name='BinaryPhysics' timestamp='1341795310' post='4957090']
[quote name='phantom' timestamp='1341791443' post='4957078']Any reason you DONT want double buffering anyway?[/quote]

Not in the slightest. When learning stuff in the past, I've had a tendency to move far to fast and begin stumbling over further topics that I lack any grounding in. I've got the first copy of OpenGL 1.0 and I've done the first 6 chapters (I need to go back over lighting though). The only reason I'm ignore any use of buffers is that I simply haven't learnt it yet.

[quote name='SimonForsman' timestamp='1341792608' post='4957083'][...] change that if to a while, otherwise you only process 1 window message per frame...[/quote]

When I read this I actually wanted to slap myself. I can't believe I missed something so theoretically simple. Thank-you so much.

Although that didn't actually solve the problem... Now I'm running with a while loop to process all the built up messages and I removed call to Flush. The program now slows down my entire laptop.
[/quote]

That seems to be as expected aswell, without the flush and no double buffering your application should do its best to occupy a full core on your cpu. (If you only got one then the rest of the system will slow down considerably (Which is fine if its a fullscreen game), you could post your modified code again so we can see if you're doing something else thats wierd.

Since you're only using one buffer i'd highly recommend using glFinish instead of glFlush aswell, Flush only tells the driver to send any buffered commands to the GPU (the opengl driver is free to buffer and batch the commands you give it), glFinish will actually wait for the GPU to finish its job (just like a buffer swap would)
2

Share this post


Link to post
Share on other sites
[source lang=cpp"]
/*
** main.cpp
*/

# include <stdlib.h>
# include <time.h>

# include <windows.h>
# if defined(_WINDOWS_)
# include <gl\gl.h>
# endif /* defined(_WINDOWS_) */

LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);

HDC hdc;
PIXELFORMATDESCRIPTOR pfd;
int format;
HGLRC hglrc;

/*
** entry point
*/
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd)
{
WNDCLASS WndClass;
HWND hWnd;
MSG msg;

WndClass.style = CS_OWNDC | CS_HREDRAW | CS_VREDRAW;
WndClass.lpfnWndProc = WndProc;
WndClass.cbClsExtra = 0;
WndClass.cbWndExtra = 0;
WndClass.hInstance = hInstance;
WndClass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
WndClass.hCursor = LoadCursor(NULL, IDC_ARROW);
WndClass.hbrBackground = NULL;
WndClass.lpszMenuName = NULL;
WndClass.lpszClassName = "greyscale";

if(RegisterClass(&WndClass) == 0)
{
MessageBox(NULL, "Unable to register the window's class.", "", MB_OK | MB_ICONERROR);
return 0;
}

hWnd = CreateWindow("greyscale", "greyscale", WS_OVERLAPPEDWINDOW | WS_VISIBLE,
100, 100, 800, 600, NULL, NULL, hInstance, NULL);
if(!hWnd)
{
MessageBox(NULL, "Failed to create window.", "", MB_OK | MB_ICONERROR);
return 0;
}

hdc = GetDC(hWnd);

ZeroMemory(&pfd, sizeof(PIXELFORMATDESCRIPTOR));
pfd.nSize = sizeof(PIXELFORMATDESCRIPTOR);
pfd.nVersion = 1;
pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER;
pfd.iPixelType = PFD_TYPE_RGBA;
pfd.cColorBits = 32;
pfd.cDepthBits = 24;
pfd.cStencilBits = 0;

format = ChoosePixelFormat(hdc, &pfd);
SetPixelFormat(hdc, format, &pfd);

hglrc = wglCreateContext(hdc);
if(!hglrc)
{
MessageBox(NULL, "Failed to create context for OpenGL.", "", MB_OK | MB_ICONERROR);
return 0;
}

if(wglMakeCurrent(hdc, hglrc) == FALSE)
{
MessageBox(NULL, "Unable to change the current context.", "", MB_OK | MB_ICONERROR);
return 0;
}

ShowWindow(hWnd, nShowCmd);
UpdateWindow(hWnd);

glClearColor(0.0f, 1.0f, 0.0f, 0.0f);

for(;;)
{
while(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
{
if(msg.message == WM_QUIT)
break;

TranslateMessage(&msg);
DispatchMessage(&msg);
}

glClear(GL_COLOR_BUFFER_BIT);

glColor3f(0.0f, 0.0f, 0.0f);
glBegin(GL_TRIANGLES);
glVertex2f( 0.5f, 0.5f );
glVertex2f(-0.5f, 0.75f);
glVertex2f(-0.35f, -0.4f);
glEnd();

glViewport(0, 0, 800, 600);

SwapBuffers(hdc);
}

wglMakeCurrent(NULL, NULL);
wglDeleteContext(hglrc);

ReleaseDC(hWnd, hdc);

return msg.wParam;
}

/*
** message handler
*/
LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch(msg)
{
case WM_NULL:
{
return 0;
}

case WM_DESTROY:
{
PostQuitMessage(0);
return 0;
}

case WM_CLOSE:
{
if(MessageBox(hWnd, "Are you sure you want to exit?", "", MB_YESNO | MB_ICONQUESTION) == IDYES)
DestroyWindow(hWnd);

return 0;
}
}

return DefWindowProc(hWnd, msg, wParam, lParam);
}

[/source]


[quote name='mark ds' timestamp='1341796248' post='4957092']and add this.[/quote]

See that addition makes the program run. I think I'm missing something about Window's behaviour and a single OpenGL buffer?

[quote name='SimonForsman' timestamp='1341796353' post='4957093']Since you're only using one buffer i'd highly recommend using glFinish instead of glFlush aswell[/quote]

I had been using that but I thought it might have been the cause so I took it out. Edited by BinaryPhysics
0

Share this post


Link to post
Share on other sites
Just out of curiosity I did two things:[list]
[*]Leave the call to ReleaseDC at the bottom of WinMain after it had been moved; and
[*]Took the program back to a single buffer with no information about the stencil or depth buffer (I left the increased colour bits).
[/list]
[source lang="cpp"]

/*
** main.cpp
*/

# include <stdlib.h>
# include <time.h>

# include <windows.h>
# if defined(_WINDOWS_)
# include <gl\gl.h>
# endif /* defined(_WINDOWS_) */

LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);

HDC hdc;
PIXELFORMATDESCRIPTOR pfd;
int format;
HGLRC hglrc;

/*
** entry point
*/
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd)
{
WNDCLASS WndClass;
HWND hWnd;
MSG msg;

WndClass.style = CS_OWNDC | CS_HREDRAW | CS_VREDRAW;
WndClass.lpfnWndProc = WndProc;
WndClass.cbClsExtra = 0;
WndClass.cbWndExtra = 0;
WndClass.hInstance = hInstance;
WndClass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
WndClass.hCursor = LoadCursor(NULL, IDC_ARROW);
WndClass.hbrBackground = NULL;
WndClass.lpszMenuName = NULL;
WndClass.lpszClassName = "greyscale";

if(RegisterClass(&WndClass) == 0)
{
MessageBox(NULL, "Unable to register the window's class.", "", MB_OK | MB_ICONERROR);
return 0;
}

hWnd = CreateWindow("greyscale", "greyscale", WS_OVERLAPPEDWINDOW | WS_VISIBLE,
100, 100, 800, 600, NULL, NULL, hInstance, NULL);
if(!hWnd)
{
MessageBox(NULL, "Failed to create window.", "", MB_OK | MB_ICONERROR);
return 0;
}

hdc = GetDC(hWnd);

ZeroMemory(&pfd, sizeof(PIXELFORMATDESCRIPTOR));
pfd.nSize = sizeof(PIXELFORMATDESCRIPTOR);
pfd.nVersion = 1;
pfd.dwFlags = PFD_SUPPORT_OPENGL | PFD_DRAW_TO_WINDOW;
pfd.iPixelType = PFD_TYPE_RGBA;
pfd.cColorBits = 32;

format = ChoosePixelFormat(hdc, &pfd);
SetPixelFormat(hdc, format, &pfd);

hglrc = wglCreateContext(hdc);
if(!hglrc)
{
MessageBox(NULL, "Failed to create context for OpenGL.", "", MB_OK | MB_ICONERROR);
return 0;
}

if(wglMakeCurrent(hdc, hglrc) == FALSE)
{
MessageBox(NULL, "Unable to change the current context.", "", MB_OK | MB_ICONERROR);
return 0;
}

ShowWindow(hWnd, nShowCmd);
UpdateWindow(hWnd);

glClearColor(0.0f, 1.0f, 0.0f, 0.0f);

for(;;)
{
while(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
{
if(msg.message == WM_QUIT)
break;

TranslateMessage(&msg);
DispatchMessage(&msg);
}

glClear(GL_COLOR_BUFFER_BIT);

glColor3f(0.0f, 0.0f, 0.0f);
glBegin(GL_TRIANGLES);
glVertex2f( 0.5f, 0.5f );
glVertex2f(-0.5f, 0.75f);
glVertex2f(-0.35f, -0.4f );
glEnd();

glViewport(0, 0, 800, 600);

glFinish();
}

wglMakeCurrent(NULL, NULL);
wglDeleteContext(hglrc);

ReleaseDC(hWnd, hdc);

return msg.wParam;
}

/*
** message handler
*/
LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch(msg)
{
case WM_NULL:
{
return 0;
}

case WM_DESTROY:
{
PostQuitMessage(0);
return 0;
}

case WM_CLOSE:
{
if(MessageBox(hWnd, "Are you sure you want to exit?", "", MB_YESNO | MB_ICONQUESTION) == IDYES)
DestroyWindow(hWnd);

return 0;
}
}

return DefWindowProc(hWnd, msg, wParam, lParam);
}

[/source]

The program now runs smoothly; but only if the Finish command is used (instead of Flush).

I think the issue was identified in these places:

[quote name='phantom' timestamp='1341791443' post='4957078'][...] the 24bit color restriction...[/quote]
[quote name='mark ds' timestamp='1341796248' post='4957092'][source lang="cpp"]pfd.cColorBits = 32;[/source][/quote]

It doesn't quit properly; but that's a separate issue I can work on.

Thanks a lot for your help. Edited by BinaryPhysics
0

Share this post


Link to post
Share on other sites
easy fix for the exit problem...

[CODE]
for(;;)
{
if(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
{
if(msg.message == WM_QUIT)
break;

TranslateMessage(&msg);
DispatchMessage(&msg);
}
else
{

glClear(GL_COLOR_BUFFER_BIT);

glColor3f(0.0f, 0.0f, 0.0f);
glBegin(GL_TRIANGLES);
glVertex2f( 0.5f, 0.5f );
glVertex2f(-0.5f, 0.75f);
glVertex2f(-0.35f, -0.4f );
glEnd();

glViewport(0, 0, 800, 600);

glFinish();
}
}
[/CODE]
0

Share this post


Link to post
Share on other sites
Just to add... you won't get a lot of help with single buffering or glFinish, simply because nobody ever uses it!
0

Share this post


Link to post
Share on other sites
[quote name='BinaryPhysics' timestamp='1341795310' post='4957090']
[quote name='phantom' timestamp='1341791443' post='4957078']Any reason you DONT want double buffering anyway?[/quote]

Not in the slightest. When learning stuff in the past, I've had a tendency to move far to fast and begin stumbling over further topics that I lack any grounding in. I've got the first copy of OpenGL 1.0 and I've done the first 6 chapters (I need to go back over lighting though). The only reason I'm ignore any use of buffers is that I simply haven't learnt it yet.
[/quote]

I have to comment on this because there's actually nothing to learn with double-buffering. Just make sure that you set PFD_DOUBLEBUFFER and call SwapBuffers at the end of the frame - that's it. OpenGL tutorials that create single buffered contexts may give you the misguided impression that a double-buffered context is somehow more complex or needs more work; it's not.
1

Share this post


Link to post
Share on other sites
[quote name='mark ds' timestamp='1341798321' post='4957109']
Just to add... you won't get a lot of help with single buffering or glFinish, simply because nobody ever uses it!
[/quote]
Not exactly. It is used quite often in multi-threaded rendering setups to signal that resources are no longer being used by the GPU (among other things).


L. Spiro Edited by L. Spiro
0

Share this post


Link to post
Share on other sites
[quote name='mark ds' timestamp='1341797911' post='4957106']easy fix for the exit problem...[/quote]

Yeah, it occurred to me that the break statement suddenly becomes an exit from the message loop by not the containing loop.
0

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!


Register a new account

Sign in

Already have an account? Sign in here.


Sign In Now
Sign in to follow this  
Followers 0