celestia/src/celestia/win32/wglext.cpp

256 lines
8.6 KiB
C++

// wglext.cpp
//
// Copyright (C) 2001, Chris Laurel <claurel@shatters.net>
//
// Set up pointers for WGL functions.
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
#include <celengine/glsupport.h>
//#define WGL_WGLEXT_PROTOTYPES 1
#include "wglext.h"
#include <windows.h>
#include <cstdio>
#include <vector>
using namespace std;
static vector<string> supportedExtensions;
extern "C"
{
PFNWGLGETEXTENSIONSSTRINGARBPROC wglGetExtensionsStringARB = NULL;
// WGL_ARB_pixel_format functions
PFNWGLGETPIXELFORMATATTRIBIVARBPROC wglGetPixelFormatAttribivARB = NULL;
PFNWGLGETPIXELFORMATATTRIBFVARBPROC wglGetPixelFormatAttribfvARB = NULL;
PFNWGLCHOOSEPIXELFORMATARBPROC wglChoosePixelFormatARB = NULL;
// WGL_ARB_pbuffer functions
PFNWGLCREATEPBUFFERARBPROC wglCreatePbufferARB = NULL;
PFNWGLGETPBUFFERDCARBPROC wglGetPbufferDCARB = NULL;
PFNWGLRELEASEPBUFFERDCARBPROC wglReleasePbufferDCARB = NULL;
PFNWGLDESTROYPBUFFERARBPROC wglDestroyPbufferARB = NULL;
PFNWGLQUERYPBUFFERARBPROC wglQueryPbufferARB = NULL;
};
// Select a floating point pixel format
int FindFormatFloat(HDC hDC)
{
int ifmtList[] = {
WGL_DRAW_TO_PBUFFER_ARB, TRUE,
WGL_SUPPORT_OPENGL_ARB, TRUE,
//WGL_DOUBLE_BUFFER_ARB, TRUE,
WGL_PIXEL_TYPE_ARB, WGL_TYPE_RGBA_FLOAT_ATI,
WGL_DEPTH_BITS_ARB, 24,
WGL_COLOR_BITS_ARB, 0,
WGL_RED_BITS_ARB, 16,
WGL_GREEN_BITS_ARB, 16,
WGL_BLUE_BITS_ARB, 16,
WGL_ALPHA_BITS_ARB, 0,
WGL_ACCUM_BITS_ARB, 0,
WGL_STENCIL_BITS_ARB, 8,
WGL_BIND_TO_TEXTURE_RGB_ARB, TRUE,
0
};
int pixelFormatIndex = -1;
int pixFormats[256];
unsigned int numFormats;
wglChoosePixelFormatARB(hDC, ifmtList, NULL, 256, pixFormats, &numFormats);
if (numFormats != 0)
{
for (unsigned int i = 0; i < numFormats; i++)
{
int results[7];
int query[] = { WGL_COLOR_BITS_ARB,
WGL_DEPTH_BITS_ARB,
WGL_STENCIL_BITS_ARB,
WGL_RED_BITS_ARB,
WGL_GREEN_BITS_ARB,
WGL_BLUE_BITS_ARB,
WGL_ALPHA_BITS_ARB };
wglGetPixelFormatAttribivARB(hDC, pixFormats[i], 0,
7, query, results);
// Select an fp16 format. No existing hardware fully supports
// fp32 render targets (no alpha blending, etc.), and fp16 is
// probably good enough anyway.
if (results[0] == 64 && results[3] == 16)
return pixFormats[i];
}
}
return -1;
}
// Called when dummy window is opened. Its only job is to get hold
// of wgl extensions.
static void WGLCallback(HWND wnd)
{
if (wnd == NULL)
return;
HDC hdc = GetDC(wnd);
if (hdc == NULL)
return;
PIXELFORMATDESCRIPTOR pfd = {
sizeof(PIXELFORMATDESCRIPTOR), // size of this pfd
1, // version number
PFD_DRAW_TO_WINDOW | // support window
PFD_SUPPORT_OPENGL | // support OpenGL
PFD_DOUBLEBUFFER, // double buffered
PFD_TYPE_RGBA, // RGBA type
24, // 24-bit color depth
0, 0, 0, 0, 0, 0, // color bits ignored
0, // no alpha buffer
0, // shift bit ignored
0, // no accumulation buffer
0, 0, 0, 0, // accum bits ignored
24, // 24-bit z-buffer
0, // no stencil buffer
0, // no auxiliary buffer
PFD_MAIN_PLANE, // main layer
0, // reserved
0, 0, 0 // layer masks ignored
};
unsigned int pixelFormat = ChoosePixelFormat(hdc, &pfd);
DescribePixelFormat(hdc, pixelFormat, sizeof(PIXELFORMATDESCRIPTOR), &pfd);
if (!SetPixelFormat(hdc, pixelFormat, &pfd))
return;
HGLRC context = wglCreateContext(hdc);
if (context == NULL)
return;
wglMakeCurrent(hdc, context);
wglGetExtensionsStringARB = (PFNWGLGETEXTENSIONSSTRINGARBPROC) wglGetProcAddress("wglGetExtensionsStringARB");
if (wglGetExtensionsStringARB == NULL)
return;
const char *ext = wglGetExtensionsStringARB(hdc);
char buff[100];
if (ext == NULL)
return;
while (*ext != '\0')
{
// TODO: This is prone to buffer overflows if the driver reports a
// bad extension string.
sscanf(ext, "%s", buff);
// Check for required extension and fill in pointers
if (strcmp(buff, "WGL_ARB_pixel_format") == 0)
{
wglGetPixelFormatAttribivARB = (PFNWGLGETPIXELFORMATATTRIBIVARBPROC) wglGetProcAddress("wglGetPixelFormatAttribivARB");
wglGetPixelFormatAttribfvARB = (PFNWGLGETPIXELFORMATATTRIBFVARBPROC) wglGetProcAddress("wglGetPixelFormatAttribfvARB");
wglChoosePixelFormatARB = (PFNWGLCHOOSEPIXELFORMATARBPROC) wglGetProcAddress("wglChoosePixelFormatARB");
if (wglChoosePixelFormatARB != NULL &&
wglGetPixelFormatAttribivARB != NULL &&
wglGetPixelFormatAttribfvARB != NULL)
{
supportedExtensions.push_back(buff);
}
}
else if (strcmp(buff, "WGL_ARB_pbuffer") == 0)
{
wglCreatePbufferARB = (PFNWGLCREATEPBUFFERARBPROC) wglGetProcAddress("wglCreatePbufferARB");
wglGetPbufferDCARB = (PFNWGLGETPBUFFERDCARBPROC) wglGetProcAddress("wglGetPbufferDCARB");
wglReleasePbufferDCARB = (PFNWGLRELEASEPBUFFERDCARBPROC) wglGetProcAddress("wglReleasePbufferDCARB");
wglDestroyPbufferARB = (PFNWGLDESTROYPBUFFERARBPROC) wglGetProcAddress("wglDestroyPbufferARB");
wglQueryPbufferARB = (PFNWGLQUERYPBUFFERARBPROC) wglGetProcAddress("wglQueryPbufferARB");
if (wglCreatePbufferARB != NULL &&
wglGetPbufferDCARB != NULL &&
wglReleasePbufferDCARB != NULL &&
wglDestroyPbufferARB != NULL &&
wglQueryPbufferARB != NULL)
{
supportedExtensions.push_back(buff);
}
}
else if (strcmp(buff, "WGL_ARB_multisample") == 0)
{
//wglSampleCoverageARB = (PFNWGLSAMPLECOVERAGEARBPROC) wglGetProcAddres("wglSampleCoverageARB");
supportedExtensions.push_back(buff);
}
else if (strcmp(buff, "WGL_ATI_pixel_format_float") == 0)
{
supportedExtensions.push_back(buff);
}
else if (strcmp(buff, "WGL_ARB_render_texture") == 0)
{
}
ext += strlen(buff) + 1;
}
// Close down this context
wglMakeCurrent(NULL, NULL);
wglDeleteContext(context);
ReleaseDC(wnd, hdc);
}
// This window exists only to call WGLCallback when its created
static LRESULT CALLBACK WGLWindProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch (uMsg)
{
case WM_CREATE:
{
CREATESTRUCT *cs = (CREATESTRUCT *) lParam;
WGLCallback(hwnd);
return -1;
}
default:
return DefWindowProc(hwnd, uMsg, wParam, lParam);
}
return 0;
}
// Create a dummy window to initialise WGL extensions.
void InitWGLExtensions(HINSTANCE appInstance)
{
WNDCLASS wglClass = {
0, WGLWindProc, 0, 0, appInstance, NULL, NULL, NULL, NULL, "InitWGL"
};
ATOM classId = RegisterClass(&wglClass);
HWND hwnd = CreateWindow("InitWGL", "",
0, 0, 0, 0, 0,
(HWND) NULL,
(HMENU) NULL,
appInstance,
NULL);
}
bool WGLExtensionSupported(const string& extName)
{
for (unsigned int i = 0; i < supportedExtensions.size(); i++)
{
if (supportedExtensions[i] == extName)
return true;
}
return false;
}