A question about GLEW Windows setup

Started by
24 comments, last by NicoG 12 years, 8 months ago

This is the definition of
BOOL SetPixelFormat( HDC hdc, int iPixelFormat, CONST PIXELFORMATDESCRIPTOR * ppfd );

so SetPixelFormat won't modify ppfd. You must set it up and provide it to SetPixelFormat. Also, check MSDN if you want to see how the function works.


It is not necessary to provide relevant pfd to SetPixelFormat. It'll still either set or fail to set the pixel format you specify via iPixelFormat.
WBW, capricorn
Advertisement

[quote name='V-man' timestamp='1311418907' post='4839248']
This is the definition of
BOOL SetPixelFormat( HDC hdc, int iPixelFormat, CONST PIXELFORMATDESCRIPTOR * ppfd );

so SetPixelFormat won't modify ppfd. You must set it up and provide it to SetPixelFormat. Also, check MSDN if you want to see how the function works.


It is not necessary to provide relevant pfd to SetPixelFormat. It'll still either set or fail to set the pixel format you specify via iPixelFormat.
[/quote]



The MSDN documentation says something about the metafile component using the pfd argument for recording information, probably if someone wanted to access it later, or something.

And I understand about the dummy pixel format now, I think. It seems I got lucky with the '1' format, lol. I thought it was the index to some "default" index before, but now I know that isn't correct. I am a little confused at one part though: what exactly do I have to initialize in the pfd in order for the ARB functions to work? So far what I've done is made it as close as possible to my attribs array... I suppose that's good enough though. The code still works with that anyway.

I've actually made a lot of improvements to the code, including giving it an object-oriented interface which I mentioned earlier. This time I'm just going to post the whole entire program just for entirety, but keep in mind that I've been using the "GL Tools" library from the OGL Superbible as I'm still learning the low-level functions. Here it is:

#ifndef GLEW_STATIC
#define GLEW_STATIC
#endif

#include <GL\glew.h>
#include <GL\wglew.h>

#include "GLTools.h"
#include "GLShaderManager.h"

class Application
{
public:
void Start(int width = 800, int height = 600);
void End();

void MainLoop();

bool running;
const TCHAR *name;
} app;

class WindowManager
{
HINSTANCE hInstance;

WNDPROC wndProc;

WNDCLASS wndClass;

DWORD wndStyle;
DWORD extStyle;

RECT dimensions;
bool fullScreen;

public:
HWND hWnd;

void CoreInit(int width, int height);
void Start(int width, int height);
void End();

void FullStart(int width, int height)
{
CoreInit(width, height),
Start(width, height);
}

void Restart()
{
// Destroy the window
if(hWnd)
{
DestroyWindow(hWnd);
hWnd = NULL;
}

// Recreate Window
Start(
dimensions.right - dimensions.left,
dimensions.bottom - dimensions.top);
}

void Show()
{
ShowWindow( hWnd, SW_SHOW ),
SetForegroundWindow( hWnd ),
SetFocus( hWnd );
}
} windowManager;

class GraphicsManager
{
HGLRC renderingContext;
HDC deviceContext;

GLBatch triangleBatch;
GLShaderManager shaderManager;

bool sceneReady;

public:
void Start(int width, int height);
void End();

void SetupScene();
void RenderScene();

void ChangeSize(int width, int height);

void CheckErrors(GLuint progName = 0);
} graphicsManager;

///////////////////////////////////////////////////////////////////////////////
// Main program function, called on startup
// First setup the window and OGL state, then enter rendering loop
int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,
PSTR szCmdLine, int iCmdShow)
{
app.Start();

graphicsManager.SetupScene();
app.MainLoop();

app.End();
return 0;
}

///////////////////////////////////////////////////////////////////////////////
// Callback functions to handle all window functions this app cares about.
// Once complete, pass message on to next app in the hook chain.
LRESULT CALLBACK WndProc( HWND hWnd, // Handle For This Window
UINT uMsg, // Message For This Window
WPARAM wParam, // Additional Message Information
LPARAM lParam) // Additional Message Information
{
// Handle relevant messages individually
switch(uMsg)
{
case WM_SIZE:
graphicsManager.ChangeSize(LOWORD(lParam),HIWORD(lParam));
graphicsManager.RenderScene();
break;
case WM_CLOSE:
app.running = false;
PostQuitMessage(0);
return 0;
default:
// Nothing to do now
break;
}

// Pass All Unhandled Messages To DefWindowProc
return DefWindowProc(hWnd,uMsg,wParam,lParam);
}

void Application::Start(int width, int height)
{
running = true;
name = TEXT("Triangle");

windowManager.FullStart(width, height);
graphicsManager.Start(width, height);
}

void Application::End()
{
graphicsManager.End();
windowManager.End();
}

void Application::MainLoop()
{
while(running)
{
MSG msg;

// Check for waiting mssgs
if (PeekMessage(&msg,NULL,0,0,PM_REMOVE))
{
if (msg.message==WM_QUIT)
{
running = false;
}
else
{
// Deal with mssgs
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
else
{
graphicsManager.RenderScene();
}

Sleep(0);
}
}

void WindowManager::CoreInit(int width, int height)
{
hInstance = GetModuleHandle(NULL);
wndProc = (WNDPROC)WndProc;

extStyle = WS_EX_APPWINDOW | WS_EX_WINDOWEDGE;
wndStyle = WS_OVERLAPPEDWINDOW;

if(MessageBox(NULL, TEXT("Would you like to run in Fullscreen Mode?"), app.name, MB_YESNO|MB_ICONEXCLAMATION)==IDYES)
{
// Prepare for a mode set to the requested resolution
DEVMODE dm;
memset (&dm, 0, sizeof(dm));

dm.dmSize = sizeof(dm);
dm.dmPelsWidth = width;
dm.dmPelsHeight = height;
dm.dmBitsPerPel = 32;
dm.dmFields = DM_BITSPERPEL|DM_PELSWIDTH|DM_PELSHEIGHT;

long error = ChangeDisplaySettings(&dm, CDS_FULLSCREEN);

if (error != DISP_CHANGE_SUCCESSFUL)
{
// Oops, something went wrong, let the user know.
if (MessageBox(NULL, TEXT("Could not set fullscreen mode.\n\
Your video card may not support the requested mode.\n\
Use windowed mode instead?"),
app.name, MB_YESNO|MB_ICONEXCLAMATION) == IDYES)
{
fullScreen = false;
extStyle = WS_EX_APPWINDOW | WS_EX_WINDOWEDGE;
wndStyle = WS_OVERLAPPEDWINDOW;
}
else
{
MessageBox(NULL, TEXT("Program will exit."), TEXT("ERROR"), MB_OK|MB_ICONSTOP);
app.running = false;
}
}
else
{
// Mode set passed, setup the styles for fullscreen
fullScreen = true;
extStyle = WS_EX_APPWINDOW;
wndStyle = WS_POPUP;
ShowCursor(FALSE);
}
}

// Setup window width and height
dimensions.left = 0;
dimensions.right = width;
dimensions.top = 0;
dimensions.bottom = height;

AdjustWindowRectEx(&dimensions, wndStyle, FALSE, extStyle);

//Adjust for adornments
width = dimensions.right - dimensions.left;
height = dimensions.bottom - dimensions.top;

// setup window class
wndClass.lpszClassName = TEXT("OGL_WINCLASS"); // Set the name of the Class
wndClass.lpfnWndProc = wndProc; // Set pointer to WndProc
wndClass.hInstance = hInstance; // Use this module for the module handle
wndClass.hCursor = LoadCursor(NULL, IDC_ARROW); // Pick the default mouse cursor
wndClass.hIcon = LoadIcon(NULL, IDI_WINLOGO); // Pick the default windows icons
wndClass.hbrBackground = NULL; // No Background
wndClass.lpszMenuName = NULL; // No menu for this window
wndClass.style = CS_HREDRAW | CS_OWNDC | // set styles for this class, specifically to catch
CS_VREDRAW; // window redraws, unique DC, and resize
wndClass.cbClsExtra = 0; // Extra class memory
wndClass.cbWndExtra = 0; // Extra window memory

// Register the newly defined class
if(!RegisterClass( &wndClass ))
{
app.running = false;
MessageBox(NULL,
TEXT("!!! An error occured creating an OpenGL window. (wndClass registration failure)\n"),
TEXT("ERROR"),
MB_OK|MB_ICONEXCLAMATION);
}
}

void WindowManager::Start(int width, int height)
{
// Create window
hWnd = CreateWindowEx( extStyle, // Extended style
TEXT("OGL_WINCLASS"), // class name
app.name, // window name
wndStyle |
WS_CLIPSIBLINGS |
WS_CLIPCHILDREN, // window stlye
0, // window position, x
0, // window position, y
width, // height
height, // width
NULL, // Parent window
NULL, // menu
hInstance, // instance
NULL); // pass this to WM_CREATE

}

void WindowManager::End()
{
// Disable fullscreen
if (fullScreen)
{
ChangeDisplaySettings(NULL,0);
ShowCursor(TRUE);
}

// Destroy the window
if(hWnd)
{
DestroyWindow(hWnd);
hWnd = NULL;
}

// Delete the window class
UnregisterClass(TEXT("OGL_WINCLASS"), hInstance);
hInstance = NULL;
ShowCursor(TRUE);
}

void GraphicsManager::Start(int width, int height)
{
sceneReady = false;

int nPixelFormat = NULL;
PIXELFORMATDESCRIPTOR pfd;

// now that we have a window, setup the pixel format descriptor
deviceContext = GetDC(windowManager.hWnd);

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

nPixelFormat = ChoosePixelFormat(deviceContext, &pfd);

// Set a dummy pixel format so that we can get access to wgl functions
SetPixelFormat( deviceContext, nPixelFormat, &pfd);

// Create OGL context and make it current
renderingContext = wglCreateContext( deviceContext );
wglMakeCurrent( deviceContext, renderingContext );

if (deviceContext == 0 ||
renderingContext == 0)
{
app.running = false;
MessageBox(NULL,
TEXT("!!! An error occured creating an OpenGL window. (Context failure)\n"),
TEXT("ERROR"),
MB_OK|MB_ICONEXCLAMATION);
}

// Setup GLEW which loads OGL function pointers
if (GLEW_OK != glewInit())
{
app.running = false;
MessageBox(NULL,
TEXT("!!! An error occured creating an OpenGL window. (GLEW failure)\n"),
TEXT("ERROR"),
MB_OK|MB_ICONEXCLAMATION);
}

// Now that extensions are setup, delete window and start over picking a real format.
wglMakeCurrent(NULL, NULL);
wglDeleteContext(renderingContext);
ReleaseDC(windowManager.hWnd, deviceContext);
windowManager.Restart();

deviceContext = GetDC(windowManager.hWnd);

UINT nPixCount = 0;

// Specify the important attributes we care about
int pixAttribs[] = { WGL_SUPPORT_OPENGL_ARB, 1, // Must support OGL rendering
WGL_DRAW_TO_WINDOW_ARB, 1, // pf that can run a window
WGL_ACCELERATION_ARB, WGL_FULL_ACCELERATION_ARB, // must be HW accelerated
WGL_COLOR_BITS_ARB, 24, // 8 bits of each R, G and B
WGL_DEPTH_BITS_ARB, 16, // 16 bits of depth precision for window
WGL_DOUBLE_BUFFER_ARB, GL_TRUE, // Double buffered context
WGL_SAMPLE_BUFFERS_ARB, GL_TRUE, // MSAA on
WGL_SAMPLES_ARB, 8, // 8x MSAA
WGL_PIXEL_TYPE_ARB, WGL_TYPE_RGBA_ARB, // pf should be RGBA type
0}; // NULL termination

// Ask OpenGL to find the most relevant format matching our attribs
// Only get one format back.
wglChoosePixelFormatARB(deviceContext, pixAttribs, NULL, 1, &nPixelFormat, &nPixCount);

if(nPixelFormat == NULL)
{
MessageBox(NULL,
TEXT("!!! An error occurred trying to find a MSAA pixel format with the requested attribs.\n"),
TEXT("ERROR"),
MB_OK|MB_ICONEXCLAMATION);

// Try again without MSAA
pixAttribs[15] = 1;
wglChoosePixelFormatARB(deviceContext, pixAttribs, NULL, 1, &nPixelFormat, &nPixCount);

if(nPixelFormat == NULL)
{
// Couldn't find a format, perhaps no 3D HW or drivers are installed
deviceContext = 0;
renderingContext = 0;
app.running = false;
MessageBox(NULL,
TEXT("!!! An error occurred trying to find a pixel format with the requested attribs.\n"),
TEXT("ERROR"),
MB_OK|MB_ICONEXCLAMATION);
}
}

if(nPixelFormat != NULL)
{
// Got a format, now set it as the current one
memset(&pfd, 0, sizeof(pfd));
DescribePixelFormat(deviceContext, nPixelFormat, sizeof(PIXELFORMATDESCRIPTOR), &pfd);
SetPixelFormat( deviceContext, nPixelFormat, &pfd );

GLint attribs[] = {WGL_CONTEXT_MAJOR_VERSION_ARB, 3,
WGL_CONTEXT_MINOR_VERSION_ARB, 3,
0 };

renderingContext = wglCreateContextAttribsARB(deviceContext, 0, attribs);
if (renderingContext == NULL)
{
MessageBox(NULL,
TEXT("!!! Could not create an OpenGL 3.3 context.\n"),
TEXT("ERROR"),
MB_OK|MB_ICONEXCLAMATION);

attribs[3] = 2;
renderingContext = wglCreateContextAttribsARB(deviceContext, 0, attribs);

if (renderingContext == NULL)
{
MessageBox(NULL,
TEXT("!!! Could not create an OpenGL 3.2 context.\n"),
TEXT("ERROR"),
MB_OK|MB_ICONEXCLAMATION);

attribs[3] = 1;
renderingContext = wglCreateContextAttribsARB(deviceContext, 0, attribs);

if (renderingContext == NULL)
{
MessageBox(NULL,
TEXT("!!! Could not create an OpenGL 3.1 context.\n"),
TEXT("ERROR"),
MB_OK|MB_ICONEXCLAMATION);

attribs[3] = 0;
renderingContext = wglCreateContextAttribsARB(deviceContext, 0, attribs);

if (renderingContext == NULL)
{
MessageBox(NULL,
TEXT("!!! Could not create an OpenGL 3.0 context.\n!!! OpenGL 3.0 and higher are not supported on this system.\n"),
TEXT("ERROR"),
MB_OK|MB_ICONEXCLAMATION);
}
}
}
}

wglMakeCurrent( deviceContext, renderingContext );
}

if (deviceContext == 0 ||
renderingContext == 0)
{
app.running = false;
MessageBox(NULL,
TEXT("!!! An error occured creating an OpenGL window. (Context failure)"),
TEXT("ERROR"),
MB_OK|MB_ICONEXCLAMATION);
}

// If everything went as planned, display the window
if( app.running )
windowManager.Show();

ChangeSize(width, height);
}

void GraphicsManager::End()
{
//Cleanup OGL RC
if(renderingContext)
{
wglMakeCurrent(NULL, NULL);
wglDeleteContext(renderingContext);
renderingContext = NULL;
}

// release the DC
if(deviceContext)
{
ReleaseDC(windowManager.hWnd, deviceContext);
deviceContext = NULL;
}
}

void GraphicsManager::SetupScene()
{
if(app.running == false) return;

// Blue background
glClearColor(0.0f, 0.0f, 1.0f, 1.0f );

shaderManager.InitializeStockShaders();

// Load up a triangle
GLfloat vVerts[] = { -0.5f, 0.0f, 0.0f,
0.5f, 0.0f, 0.0f,
0.0f, 0.5f, 0.0f };

triangleBatch.Begin(GL_TRIANGLES, 3);
triangleBatch.CopyVertexData3f(vVerts);
triangleBatch.End();

sceneReady = true;
}

void GraphicsManager::RenderScene()
{
if(app.running == false || sceneReady == false) return;

// Clear the window with current clearing color
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);

GLfloat vRed[] = { 1.0f, 0.0f, 0.0f, 1.0f };
shaderManager.UseStockShader(GLT_SHADER_IDENTITY, vRed);
triangleBatch.Draw();

// Do the buffer Swap
SwapBuffers(deviceContext);

CheckErrors();
}

void GraphicsManager::ChangeSize(int width, int height)
{
glViewport(0, 0, width, height);
}

void GraphicsManager::CheckErrors(GLuint progName)
{
GLenum error = glGetError();

if (error != GL_NO_ERROR)
{
fprintf(stderr, "A GL Error has occured\n");
}

GLenum fboStatus = glCheckFramebufferStatus(GL_DRAW_FRAMEBUFFER);

if(fboStatus != GL_FRAMEBUFFER_COMPLETE)
{
switch (fboStatus)
{
case GL_FRAMEBUFFER_UNDEFINED:
// Oops, no window exists?
MessageBox(NULL, TEXT("GL_FRAMEBUFFER_UNDEFINED"), app.name, MB_OK|MB_ICONEXCLAMATION);
break;
case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT:
// Check the status of each attachment
MessageBox(NULL, TEXT("GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT"), app.name, MB_OK|MB_ICONEXCLAMATION);
break;
case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT:
// Attach at least one buffer to the FBO
MessageBox(NULL, TEXT("GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT"), app.name, MB_OK|MB_ICONEXCLAMATION);
break;
case GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER:
// Check that all attachments enabled via
// glDrawBuffers exist in FBO
MessageBox(NULL, TEXT("GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER"), app.name, MB_OK|MB_ICONEXCLAMATION);
case GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER:
// Check that the buffer specified via
// glReadBuffer exists in FBO
MessageBox(NULL, TEXT("GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER"), app.name, MB_OK|MB_ICONEXCLAMATION);
break;
case GL_FRAMEBUFFER_UNSUPPORTED:
// Reconsider formats used for attached buffers
MessageBox(NULL, TEXT("GL_FRAMEBUFFER_UNSUPPORTED"), app.name, MB_OK|MB_ICONEXCLAMATION);
break;
case GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE:
// Make sure the number of samples for each
// attachment is the same
MessageBox(NULL, TEXT("GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE"), app.name, MB_OK|MB_ICONEXCLAMATION);
break;
//case GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS:
// Make sure the number of layers for each
// attachment is the same
//break;
}
fprintf(stderr,"The framebuffer is not complete\n");
}

if (progName != 0)
{
glValidateProgram(progName);
int iIsProgValid = 0;
glGetProgramiv(progName, GL_VALIDATE_STATUS, &iIsProgValid);
if(iIsProgValid == 0)
{
MessageBox(NULL, TEXT("The current program is not valid\n"), app.name, MB_YESNO|MB_ICONEXCLAMATION);
fprintf(stderr,"The current program is not valid\n");
}
}
}



This is hopefully the start of a game engine subsystem layout, and of course its only a start at the moment. It still makes the code a lot more readable in my opinion, not to mention easier to use. Any opinions on it? (Sorry if the indentations look all screwed up, it looks a lot better in my IDE for some reason)

Tons of thanks to capricorn, V-man, and Brother Bob for helping me out with this, I definitely know a lot more than before. I'm not sure if there's much more to worry about now, I'm satisfied with how the program's turned out for the most part. Any further suggestions are still welcome, of course. Thanks again!

And I understand about the dummy pixel format now, I think. It seems I got lucky with the '1' format, lol. I thought it was the index to some "default" index before, but now I know that isn't correct. I am a little confused at one part though: what exactly do I have to initialize in the pfd in order for the ARB functions to work? So far what I've done is made it as close as possible to my attribs array... I suppose that's good enough though. The code still works with that anyway.

Theoretically, you should match them exactly. Any difference in the final pixel formats may result in different contexts, and the function pointers won't work. But in practice, as close as possible is typically good enough. As long as the dummy context is created is a hardware accelerated context, you should be fine. Just be aware that having small differences may tip the scale different ways when choosing between what contexts are created (hardware vs. software implementation), but any reasonable pixel format usually tips it towards the hardware context.

The MSDN documentation says something about the metafile component using the pfd argument for recording information, probably if someone wanted to access it later, or something.

Almost. It's for recording metafiles. As long as you don't do that, it does not matter at all what pfd you pass to SetPixelFormat().


I am a little confused at one part though: what exactly do I have to initialize in the pfd in order for the ARB functions to work? So far what I've done is made it as close as possible to my attribs array... I suppose that's good enough though. The code still works with that anyway.
[/quote]
Yeah, I'd say that's good enough... almost :) Actually, it'd be better if you removed that PFD_GENERIC_ACCELERATED flag. It's only meaningful to have it for the software GDI pixel formats.


This is hopefully the start of a game engine subsystem layout, and of course its only a start at the moment. It still makes the code a lot more readable in my opinion, not to mention easier to use. Any opinions on it? (Sorry if the indentations look all screwed up, it looks a lot better in my IDE for some reason)
[/quote]
Regarding GL, I'd only encourage you to heed Brother Bob's advice and load GL functions after your real context creation. But I can't say for sure if GLEW is currently capable of properly doing that, and it's quite a work to implement it by hand. So you may consider this for the future work at least.


Tons of thanks to capricorn, V-man, and Brother Bob for helping me out with this, I definitely know a lot more than before. I'm not sure if there's much more to worry about now, I'm satisfied with how the program's turned out for the most part. Any further suggestions are still welcome, of course. Thanks again!
[/quote]
You're welcome.
WBW, capricorn

Regarding GL, I'd only encourage you to heed Brother Bob's advice and load GL functions after your real context creation. But I can't say for sure if GLEW is currently capable of properly doing that, and it's quite a work to implement it by hand. So you may consider this for the future work at least.

Quite a work? I showed how to do it in my first post; it is one line of code for every function you need, and at the moment he only needs two function.

[quote name='capricorn' timestamp='1311505255' post='4839549']
Regarding GL, I'd only encourage you to heed Brother Bob's advice and load GL functions after your real context creation. But I can't say for sure if GLEW is currently capable of properly doing that, and it's quite a work to implement it by hand. So you may consider this for the future work at least.

Quite a work? I showed how to do it in my first post; it is one line of code for every function you need, and at the moment he only needs two function.
[/quote]

Quite a work doing this by hand ("...load GL functions after your real context creation"). I mentioned this because I'm not sure if GLEW is consistent with GL's deprecation/removal model (e.g. strict interface for core GL3.3 profile does not include all functions from previous GL versions, but GLEW loader might try and load them anyway, and, what's most frustrating, even succeed if the driver's not conformant). Maybe it's worth asking the authors, it's hard to tell from GLEW code at a glance.

I myself load all GL function pointers by hand (i'm currently working in D so I don't have the luxury of GLEW. Could use Derelict instead, but it doesn't work entirely well, and I don't think this is the proper place to explain why wink.gif ), and I'm already considering splitting GL interface into different sections consistent with deprecation model.

EDIT: writing that, I remembered I've read in GL specs that "calling removed functions would result in an INVALID_OPERATION", so I've gone and rechecked that. It seems that conformant driver should still provide removed functions, but they just simply operate as the docs state. Well, maybe it is better to have that than calling a function via null pointer (e.g. if functions were totally absent).
WBW, capricorn

Regarding GL, I'd only encourage you to heed Brother Bob's advice and load GL functions after your real context creation. But I can't say for sure if GLEW is currently capable of properly doing that, and it's quite a work to implement it by hand. So you may consider this for the future work at least.


Yeah, that is a good thing to be aware of just in case GLEW doesn't do the job, though you have to admit it is pretty nice if you want immediate access to GL functions :D

[quote name='AutoBot' timestamp='1311473147' post='4839439']
And I understand about the dummy pixel format now, I think. It seems I got lucky with the '1' format, lol. I thought it was the index to some "default" index before, but now I know that isn't correct. I am a little confused at one part though: what exactly do I have to initialize in the pfd in order for the ARB functions to work? So far what I've done is made it as close as possible to my attribs array... I suppose that's good enough though. The code still works with that anyway.

Theoretically, you should match them exactly. Any difference in the final pixel formats may result in different contexts, and the function pointers won't work. But in practice, as close as possible is typically good enough. As long as the dummy context is created is a hardware accelerated context, you should be fine. Just be aware that having small differences may tip the scale different ways when choosing between what contexts are created (hardware vs. software implementation), but any reasonable pixel format usually tips it towards the hardware context.
[/quote]

From what I understand, you either get the GL driver, from which you can get your tons of GL function pointers or #2, you get Microsoft GDI which is GL 1.1

What is there to worry about? Your graphics driver is not going to give you some other set of pointers.
Has anyone ever seen a case where you had a different set of pointers for a hw accelerated context GL 1.2 or 1.3 or 1.3 or 1.4 or 1.5 or 2.0......?

If you read the MSDN documentation, different pixel formats can give you a different set of pointers but I think in practice, you just have 2 cases.
Sig: http://glhlib.sourceforge.net
an open source GLU replacement library. Much more modern than GLU.
float matrix[16], inverse_matrix[16];
glhLoadIdentityf2(matrix);
glhTranslatef2(matrix, 0.0, 0.0, 5.0);
glhRotateAboutXf2(matrix, angleInRadians);
glhScalef2(matrix, 1.0, 1.0, -1.0);
glhQuickInvertMatrixf2(matrix, inverse_matrix);
glUniformMatrix4fv(uniformLocation1, 1, FALSE, matrix);
glUniformMatrix4fv(uniformLocation2, 1, FALSE, inverse_matrix);
What you should worry about is not getting a software context when creating the dummy context. Not sure what you're getting at though; you seems to agree with what I say, but present it in a way that you seem to disagree with me.


From what I understand, you either get the GL driver, from which you can get your tons of GL function pointers or #2, you get Microsoft GDI which is GL 1.1
If you read the MSDN documentation, different pixel formats can give you a different set of pointers but I think in practice, you just have 2 cases.



In practice, it's implementation-specific. As I mentioned above, specifications for modern GL versions state that calling removed functions should result in GL_INVALID_OPERATION error. It means that GL implementations (i.e. drivers) will provide different functionality for different GL versions. Alas, while it is determined what functionality is available for a specific GL version, it is not clearly specified at what level it is controlled. Function behavior may be controlled on a context level (i.e. function call is forwarded to implementation-specific context object, thus, same function pointer but different behavior on different GL versions), or at function acquisition level (i.e. when you fetch function pointer from the driver via e.g. wglGetProcAddress, thus, different function pointers for different GL versions). The latter approach may introduce very unpleasant (and platform/driver-specific) bugs to your programs, but since it is not explicitly covered by specification, one should not act on assumption that no implementation would ever do this. So to be completely safe, it's better to tie your own function pointers to a specific GL version and load them while a context of that specific version is active. This does no harm (save some programming effort) but deals with both possible cases equally well. Perhaps at some point, the specs will become explicit in this regard, but for now this is the safest route to take.
WBW, capricorn

This topic is closed to new replies.

Advertisement