|
From: James W. <ja...@fr...> - 2007-12-12 21:37:38
|
Jose' Cruanyes wrote:
> Il giorno 12/dic/07, alle ore 01:17, James Walker ha scritto:
>
>> The extra complication is mostly due to Windows. On Windows, in order
>> to get an appropriate function pointer, you must first get a function
>> pointer to wglChoosePixelFormatARB, and in order to get that, you must
>> already have an OpenGL context set up. So the typical routine would
>> involve creating a dummy window, getting the function pointer,
>> destroying the dummy window, and then proceeding to set up the window
>> you really want to use. I didn't want Quesa to get into the
>> business of
>> creating and destroying windows.
>
>
> can you please post a code snippet of this, (mostly for documentation
> purposes)
OK... I'm not an expert Windows programmer, so I might be doing more
work than necessary.
static const char* kWindowClassName = "dummy";
static HDC theDC = NULL;
static PFNWGLGETPIXELFORMATATTRIBIVARBPROC wglGetPixelFormatAttribivARB
= NULL;
static PFNWGLCHOOSEPIXELFORMATARBPROC wglChoosePixelFormatARB = NULL;
static void RegisterWindowClass( HINSTANCE inInstance )
{
WNDCLASSEX wcex;
wcex.cbSize = sizeof(WNDCLASSEX);
wcex.style = CS_OWNDC;
wcex.lpfnWndProc = (WNDPROC) DefWindowProc;
wcex.cbClsExtra = 0;
wcex.cbWndExtra = 0;
wcex.hInstance = inInstance;
wcex.hIcon = LoadIcon(NULL, IDI_WINLOGO);
wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
wcex.hbrBackground = NULL;
wcex.lpszMenuName = NULL;
wcex.lpszClassName = kWindowClassName;
wcex.hIconSm = NULL;
RegisterClassEx(&wcex);
}
void SetDummyGLContext()
{
static HGLRC glContext = NULL;
if (glContext == NULL)
{
HINSTANCE theInstance = GetModuleHandle( NULL );
RegisterWindowClass( theInstance );
HWND theWindow = CreateWindow( kWindowClassName, "XDummy",
WS_OVERLAPPEDWINDOW |
WS_CLIPCHILDREN |
WS_CLIPSIBLINGS,
400, 30, 40, 40,
NULL, NULL, theInstance, NULL );
theDC = GetDC((HWND) theWindow);
PIXELFORMATDESCRIPTOR pixelFormatDesc;
pixelFormatDesc.nSize = sizeof(pixelFormatDesc);
pixelFormatDesc.nVersion = 1;
pixelFormatDesc.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL |
PFD_DOUBLEBUFFER;
pixelFormatDesc.cColorBits = 0;
pixelFormatDesc.cDepthBits = 24;
pixelFormatDesc.cStencilBits = 8;
pixelFormatDesc.iPixelType = PFD_TYPE_RGBA;
int pixelFormat = ChoosePixelFormat( theDC, &pixelFormatDesc );
if (pixelFormat != NULL)
{
if (SetPixelFormat( theDC, pixelFormat, &pixelFormatDesc))
{
glContext = wglCreateContext( theDC );
}
}
}
if (glContext != NULL)
{
wglMakeCurrent( theDC, glContext );
}
}
static bool HasMultisample()
{
std::string theExts(" ");
theExts += (const char*) glGetString( GL_EXTENSIONS );
theExts += ' ';
bool hasExt = theExts.find( " GL_ARB_multisample " ) != std::string::npos;
if (not hasExt)
{
// OpenGL 1.3 incorporates multisampling.
std::string theVers( (const char*) glGetString( GL_VERSION ) );
if ( (theVers[0] > '1') or (theVers[2] >= '3') )
{
hasExt = true;
}
}
return hasExt;
}
static bool IsMultisampleFormat( HDC inDC, int inPixelFormat )
{
bool isMulti = false;
int atts[2] = {
WGL_SAMPLE_BUFFERS_ARB,
WGL_SAMPLES_ARB
};
int values[2];
if (wglGetPixelFormatAttribivARB( inDC, inPixelFormat, 0, 2,
atts, values ))
{
isMulti = (values[0] > 0) and (values[1] > 0);
}
return isMulti;
}
static int ChoosePixelFormatARB( HDC hdc, const int *piAttribIList )
{
UINT numFormats = -1;
int theFormat = 0;
if (wglChoosePixelFormatARB( hdc, piAttribIList, NULL, 1, &theFormat,
&numFormats ))
{
if (numFormats == 0)
{
theFormat = 0;
//DebugMsg("No multisample formats available");
}
else
{
if (not IsMultisampleFormat( hdc, theFormat ))
{
theFormat = 0; // not sure if this can happen
}
}
}
else
{
DWORD err = GetLastError();
char xmsg[100];
std::sprintf( xmsg, "wglChoosePixelFormatARB failed with error %X.",
err );
DebugMsg(xmsg);
}
return theFormat;
}
static int ChooseWinMultisampleFormat()
{
int theFormat = 0;
SetDummyGLContext();
if (not HasMultisample())
{
return theFormat;
}
PFNWGLGETEXTENSIONSSTRINGARBPROC wglGetExtensionsStringARB =
(PFNWGLGETEXTENSIONSSTRINGARBPROC)
wglGetProcAddress("wglGetExtensionsStringARB");
if (wglGetExtensionsStringARB != NULL)
{
HDC theDC = GetDummyDC();
std::string extStr(" ");
extStr += (char*)wglGetExtensionsStringARB( theDC );
extStr += ' ';
if (extStr.find( " WGL_ARB_pixel_format " ) != std::string::npos)
{
wglChoosePixelFormatARB =
(PFNWGLCHOOSEPIXELFORMATARBPROC)
wglGetProcAddress( "wglChoosePixelFormatARB" );
wglGetPixelFormatAttribivARB =
(PFNWGLGETPIXELFORMATATTRIBIVARBPROC)
wglGetProcAddress( "wglGetPixelFormatAttribivARB" );
int atts[] =
{
WGL_SAMPLES_ARB, 4, // keep this first!
WGL_DOUBLE_BUFFER_ARB, GL_TRUE,
WGL_DRAW_TO_WINDOW_ARB, GL_TRUE,
WGL_SUPPORT_OPENGL_ARB, GL_TRUE,
WGL_ACCELERATION_ARB, WGL_FULL_ACCELERATION_ARB,
WGL_SAMPLE_BUFFERS_ARB, 1,
WGL_DEPTH_BITS_ARB, 24,
WGL_STENCIL_BITS_ARB, 8,
0, 0
};
theFormat = ChoosePixelFormatARB( theDC, atts );
if ( theFormat == 0 )
{
atts[1] = 2; // WGL_SAMPLES_ARB value
theFormat = ChoosePixelFormatARB( theDC, atts );
}
}
}
return theFormat;
}
--
James W. Walker, Innoventive Software LLC
<http://www.frameforge3d.com/>
|