mirror of https://github.com/tongzx/nt5src
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
910 lines
21 KiB
910 lines
21 KiB
#include "precomp.h"
|
|
#pragma hdrstop
|
|
|
|
#include <stdio.h>
|
|
|
|
#include "glwinint.h"
|
|
|
|
// Window class
|
|
static char *pszClass = "glWindow";
|
|
|
|
// Structure to pass window creation data
|
|
#pragma pack(1)
|
|
typedef struct _GLWINCREATESTRUCT
|
|
{
|
|
WORD wSize;
|
|
GLWINDOW gw;
|
|
} GLWINCREATESTRUCT;
|
|
#pragma pack()
|
|
|
|
/******************************Public*Routine******************************\
|
|
*
|
|
* glwinWndProc
|
|
*
|
|
* Window procedure for glwin windows
|
|
*
|
|
* History:
|
|
* Fri Aug 30 13:00:23 1996 -by- Drew Bliss [drewb]
|
|
* Created
|
|
*
|
|
\**************************************************************************/
|
|
|
|
LRESULT glwinWndProc(HWND hwnd, UINT uiMsg, WPARAM wpm, LPARAM lpm)
|
|
{
|
|
PAINTSTRUCT ps;
|
|
LRESULT lr;
|
|
GLWINDOW gw;
|
|
GLWINCREATESTRUCT *pgcs;
|
|
|
|
// Set up the window-related data immediately on WM_CREATE so that
|
|
// a callback can be made for it as well as after it
|
|
if (uiMsg == WM_CREATE)
|
|
{
|
|
pgcs = (GLWINCREATESTRUCT *)((CREATESTRUCT *)lpm)->lpCreateParams;
|
|
SetWindowLong(hwnd, GWL_USERDATA, (LONG)pgcs->gw);
|
|
}
|
|
|
|
gw = (GLWINDOW)GetWindowLong(hwnd, GWL_USERDATA);
|
|
|
|
// Pass off window messages if requested
|
|
if (gw != NULL && gw->cbMessage != NULL)
|
|
{
|
|
if (gw->cbMessage(gw, hwnd, uiMsg, wpm, lpm, &lr))
|
|
{
|
|
return lr;
|
|
}
|
|
}
|
|
|
|
switch(uiMsg)
|
|
{
|
|
case WM_PAINT:
|
|
// Validate paint region. The assumption is that the app will either
|
|
// interpose and catch the WM_PAINT itself or it's dynamic so
|
|
// the screen will be repainted shortly anyway. Either way,
|
|
// there's nothing for the library to do.
|
|
BeginPaint(hwnd, &ps);
|
|
EndPaint(hwnd, &ps);
|
|
break;
|
|
|
|
case WM_CLOSE:
|
|
gw->bClosing = TRUE;
|
|
DestroyWindow(hwnd);
|
|
break;
|
|
|
|
case WM_DESTROY:
|
|
if (gw->bClosing)
|
|
{
|
|
PostQuitMessage(1);
|
|
}
|
|
break;
|
|
|
|
default:
|
|
return DefWindowProc(hwnd, uiMsg, wpm, lpm);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
// Default palette entry flags
|
|
#define PALETTE_FLAGS PC_NOCOLLAPSE
|
|
|
|
// Maximum color distance with 8-bit components
|
|
#define MAX_COL_DIST (3*256*256L)
|
|
|
|
// Number of static colors
|
|
#define STATIC_COLORS 20
|
|
|
|
// Flags used when matching colors
|
|
#define EXACT_MATCH 1
|
|
#define COLOR_USED 1
|
|
|
|
// Tables to convert color components between bit sizes
|
|
// These tables are corrected for a gamma of 1.4
|
|
static unsigned char abThreeToEight[8] =
|
|
{
|
|
0, 63, 104, 139, 171, 200, 229, 255
|
|
};
|
|
static unsigned char abTwoToEight[4] =
|
|
{
|
|
0, 116, 191, 255
|
|
};
|
|
static unsigned char abOneToEight[2] =
|
|
{
|
|
0, 255
|
|
};
|
|
|
|
// Table which indicates which colors in a 3-3-2 palette should be
|
|
// replaced with the system default colors
|
|
static int aiDefaultOverride[STATIC_COLORS] =
|
|
{
|
|
0, 3, 24, 27, 64, 67, 88, 173, 181, 236,
|
|
247, 164, 91, 7, 56, 63, 192, 199, 248, 255
|
|
};
|
|
|
|
/******************************Public*Routine******************************\
|
|
*
|
|
* glwinComponentFromIndex
|
|
*
|
|
* Converts a color index to a color component
|
|
*
|
|
* History:
|
|
* Fri Aug 30 14:04:45 1996 -by- Drew Bliss [drewb]
|
|
* Created
|
|
*
|
|
\**************************************************************************/
|
|
|
|
unsigned char glwinComponentFromIndex(int i, int nbits, int shift)
|
|
{
|
|
unsigned char val;
|
|
|
|
val = i >> shift;
|
|
switch (nbits)
|
|
{
|
|
case 1:
|
|
return abOneToEight[val & 1];
|
|
|
|
case 2:
|
|
return abTwoToEight[val & 3];
|
|
|
|
case 3:
|
|
return abThreeToEight[val & 7];
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
// System default colors
|
|
static PALETTEENTRY apeDefaultPalEntry[STATIC_COLORS] =
|
|
{
|
|
{ 0, 0, 0, 0 },
|
|
{ 0x80,0, 0, 0 },
|
|
{ 0, 0x80,0, 0 },
|
|
{ 0x80,0x80,0, 0 },
|
|
{ 0, 0, 0x80, 0 },
|
|
{ 0x80,0, 0x80, 0 },
|
|
{ 0, 0x80,0x80, 0 },
|
|
{ 0xC0,0xC0,0xC0, 0 },
|
|
|
|
{ 192, 220, 192, 0 },
|
|
{ 166, 202, 240, 0 },
|
|
{ 255, 251, 240, 0 },
|
|
{ 160, 160, 164, 0 },
|
|
|
|
{ 0x80,0x80,0x80, 0 },
|
|
{ 0xFF,0, 0, 0 },
|
|
{ 0, 0xFF,0, 0 },
|
|
{ 0xFF,0xFF,0, 0 },
|
|
{ 0, 0, 0xFF, 0 },
|
|
{ 0xFF,0, 0xFF, 0 },
|
|
{ 0, 0xFF,0xFF, 0 },
|
|
{ 0xFF,0xFF,0xFF, 0 }
|
|
};
|
|
|
|
/******************************Public*Routine******************************\
|
|
*
|
|
* glwinUpdateStaticMapping
|
|
*
|
|
* Computes the best match between the current system static colors
|
|
* and a 3-3-2 palette
|
|
*
|
|
* History:
|
|
* Tue Aug 01 18:18:12 1995 -by- Drew Bliss [drewb]
|
|
* Created
|
|
*
|
|
\**************************************************************************/
|
|
|
|
void glwinUpdateStaticMapping(PALETTEENTRY *pe332Palette)
|
|
{
|
|
HPALETTE hpalStock;
|
|
int iStatic, i332;
|
|
int iMinDist, iDist;
|
|
int iDelta;
|
|
int iMinEntry;
|
|
PALETTEENTRY *peStatic, *pe332;
|
|
|
|
hpalStock = (HPALETTE)GetStockObject(DEFAULT_PALETTE);
|
|
|
|
// Get the current static colors
|
|
GetPaletteEntries(hpalStock, 0, STATIC_COLORS, apeDefaultPalEntry);
|
|
|
|
// Zero the flags in the static colors because they are used later
|
|
peStatic = apeDefaultPalEntry;
|
|
for (iStatic = 0; iStatic < STATIC_COLORS; iStatic++)
|
|
{
|
|
peStatic->peFlags = 0;
|
|
peStatic++;
|
|
}
|
|
|
|
// Zero the flags in the incoming palette because they are used later
|
|
pe332 = pe332Palette;
|
|
for (i332 = 0; i332 < 256; i332++)
|
|
{
|
|
pe332->peFlags = 0;
|
|
pe332++;
|
|
}
|
|
|
|
// Try to match each static color exactly
|
|
// This saves time by avoiding the least-squares match for each
|
|
// exact match
|
|
peStatic = apeDefaultPalEntry;
|
|
for (iStatic = 0; iStatic < STATIC_COLORS; iStatic++)
|
|
{
|
|
pe332 = pe332Palette;
|
|
for (i332 = 0; i332 < 256; i332++)
|
|
{
|
|
if (peStatic->peRed == pe332->peRed &&
|
|
peStatic->peGreen == pe332->peGreen &&
|
|
peStatic->peBlue == pe332->peBlue)
|
|
{
|
|
peStatic->peFlags = EXACT_MATCH;
|
|
pe332->peFlags = COLOR_USED;
|
|
aiDefaultOverride[iStatic] = i332;
|
|
|
|
break;
|
|
}
|
|
|
|
pe332++;
|
|
}
|
|
|
|
peStatic++;
|
|
}
|
|
|
|
// Match each static color as closely as possible to an entry
|
|
// in the 332 palette by minimized the square of the distance
|
|
peStatic = apeDefaultPalEntry;
|
|
for (iStatic = 0; iStatic < STATIC_COLORS; iStatic++)
|
|
{
|
|
// Skip colors already matched exactly
|
|
if (peStatic->peFlags == EXACT_MATCH)
|
|
{
|
|
peStatic++;
|
|
continue;
|
|
}
|
|
|
|
iMinDist = MAX_COL_DIST+1;
|
|
#if DBG
|
|
iMinEntry = -1;
|
|
#endif
|
|
|
|
pe332 = pe332Palette;
|
|
for (i332 = 0; i332 < 256; i332++)
|
|
{
|
|
// Skip colors already used
|
|
if (pe332->peFlags == COLOR_USED)
|
|
{
|
|
pe332++;
|
|
continue;
|
|
}
|
|
|
|
// Compute Euclidean distance squared
|
|
iDelta = pe332->peRed-peStatic->peRed;
|
|
iDist = iDelta*iDelta;
|
|
iDelta = pe332->peGreen-peStatic->peGreen;
|
|
iDist += iDelta*iDelta;
|
|
iDelta = pe332->peBlue-peStatic->peBlue;
|
|
iDist += iDelta*iDelta;
|
|
|
|
if (iDist < iMinDist)
|
|
{
|
|
iMinDist = iDist;
|
|
iMinEntry = i332;
|
|
}
|
|
|
|
pe332++;
|
|
}
|
|
|
|
// Remember the best match
|
|
aiDefaultOverride[iStatic] = iMinEntry;
|
|
pe332Palette[iMinEntry].peFlags = COLOR_USED;
|
|
|
|
peStatic++;
|
|
}
|
|
|
|
// Zero the flags in the static colors because they may have been
|
|
// set. We want them to be zero so the colors can be remapped
|
|
peStatic = apeDefaultPalEntry;
|
|
for (iStatic = 0; iStatic < STATIC_COLORS; iStatic++)
|
|
{
|
|
peStatic->peFlags = 0;
|
|
peStatic++;
|
|
}
|
|
|
|
// Reset the 332 flags because we may have set them
|
|
pe332 = pe332Palette;
|
|
for (i332 = 0; i332 < 256; i332++)
|
|
{
|
|
pe332->peFlags = PALETTE_FLAGS;
|
|
pe332++;
|
|
}
|
|
}
|
|
|
|
PALETTEENTRY *glwinFillRgbPaletteEntries(PIXELFORMATDESCRIPTOR *ppfd,
|
|
PALETTEENTRY *ppeEntries,
|
|
UINT cColors)
|
|
{
|
|
PALETTEENTRY *ppeEntry;
|
|
UINT i;
|
|
|
|
for (i = 0, ppeEntry = ppeEntries ; i < cColors ; i++, ppeEntry++)
|
|
{
|
|
ppeEntry->peRed = glwinComponentFromIndex(i, ppfd->cRedBits,
|
|
ppfd->cRedShift);
|
|
ppeEntry->peGreen = glwinComponentFromIndex(i, ppfd->cGreenBits,
|
|
ppfd->cGreenShift);
|
|
ppeEntry->peBlue = glwinComponentFromIndex(i, ppfd->cBlueBits,
|
|
ppfd->cBlueShift);
|
|
ppeEntry->peFlags = PALETTE_FLAGS;
|
|
}
|
|
|
|
if (cColors == 256)
|
|
{
|
|
// If app set static system color usage for fixed palette support,
|
|
// setup to take over the static colors. Otherwise, fixup the
|
|
// static system colors.
|
|
|
|
// The defaultOverride array is computed assuming a 332
|
|
// palette where red has zero shift, etc.
|
|
|
|
if ( (3 == ppfd->cRedBits) && (0 == ppfd->cRedShift) &&
|
|
(3 == ppfd->cGreenBits) && (3 == ppfd->cGreenShift) &&
|
|
(2 == ppfd->cBlueBits) && (6 == ppfd->cBlueShift) )
|
|
{
|
|
glwinUpdateStaticMapping(ppeEntries);
|
|
|
|
for ( i = 0 ; i < STATIC_COLORS ; i++)
|
|
{
|
|
ppeEntries[aiDefaultOverride[i]] = apeDefaultPalEntry[i];
|
|
}
|
|
}
|
|
}
|
|
|
|
return ppeEntries;
|
|
}
|
|
|
|
void glwinFlushPalette(HDC hdc, int cColors)
|
|
{
|
|
LOGPALETTE *plpal;
|
|
HPALETTE hpal, hpalOld;
|
|
int i;
|
|
|
|
if (cColors == 256)
|
|
{
|
|
plpal = (LOGPALETTE *)calloc(1, sizeof(LOGPALETTE)+
|
|
cColors*sizeof(PALETTEENTRY));
|
|
if (plpal != NULL)
|
|
{
|
|
plpal->palVersion = 0x300;
|
|
plpal->palNumEntries = cColors;
|
|
|
|
// Mark everything PC_NOCOLLAPSE and PC_RESERVED to force
|
|
// every thing into the palette. Colors are already black
|
|
// because we zero initialized during memory allocation.
|
|
|
|
for (i = 0; i < cColors; i++)
|
|
{
|
|
plpal->palPalEntry[i].peFlags = PC_NOCOLLAPSE | PC_RESERVED;
|
|
}
|
|
|
|
hpal = CreatePalette(plpal);
|
|
free(plpal);
|
|
|
|
hpalOld = SelectPalette(hdc, hpal, FALSE);
|
|
RealizePalette(hdc);
|
|
|
|
SelectPalette(hdc, hpalOld, FALSE);
|
|
DeleteObject(hpal);
|
|
}
|
|
}
|
|
}
|
|
|
|
LONG glwinRealizePaletteNow(HDC hdc, HPALETTE hpal, BOOL bForceBackground)
|
|
{
|
|
LONG lRet = -1;
|
|
BOOL bHaveSysPal = TRUE;
|
|
|
|
if (SelectPalette(hdc, hpal, FALSE) != NULL)
|
|
{
|
|
lRet = RealizePalette(hdc);
|
|
}
|
|
|
|
return lRet;
|
|
}
|
|
|
|
BOOL glwinCreateRgbPalette(HDC hdc, PIXELFORMATDESCRIPTOR *ppfd,
|
|
HPALETTE *phpal)
|
|
{
|
|
LOGPALETTE *plpal;
|
|
UINT cColors;
|
|
HPALETTE hpal = NULL;
|
|
BOOL bRet = TRUE;
|
|
|
|
if (ppfd->iPixelType == PFD_TYPE_RGBA &&
|
|
(ppfd->dwFlags & PFD_NEED_PALETTE))
|
|
{
|
|
cColors = 1 << ppfd->cColorBits;
|
|
plpal = (LOGPALETTE *)malloc(sizeof(LOGPALETTE)+
|
|
cColors*sizeof(PALETTEENTRY));
|
|
if (plpal != NULL)
|
|
{
|
|
plpal->palVersion = 0x300;
|
|
plpal->palNumEntries = cColors;
|
|
|
|
glwinFillRgbPaletteEntries(ppfd, &plpal->palPalEntry[0], cColors);
|
|
hpal = CreatePalette(plpal);
|
|
free(plpal);
|
|
|
|
glwinFlushPalette(hdc, cColors);
|
|
glwinRealizePaletteNow(hdc, hpal, FALSE);
|
|
}
|
|
else
|
|
{
|
|
bRet = FALSE;
|
|
}
|
|
}
|
|
|
|
*phpal = hpal;
|
|
|
|
return bRet;
|
|
}
|
|
|
|
/******************************Public*Routine******************************\
|
|
*
|
|
* glwinRegisterClass
|
|
*
|
|
* Register a window class if necessary
|
|
*
|
|
* History:
|
|
* Fri Aug 30 14:37:49 1996 -by- Drew Bliss [drewb]
|
|
* Created
|
|
*
|
|
\**************************************************************************/
|
|
|
|
BOOL glwinRegisterClass(void)
|
|
{
|
|
static ATOM aClass = 0;
|
|
WNDCLASS wc;
|
|
|
|
if (aClass == 0)
|
|
{
|
|
wc.style = CS_HREDRAW | CS_VREDRAW;
|
|
wc.lpfnWndProc = glwinWndProc;
|
|
wc.cbClsExtra = 0;
|
|
wc.cbWndExtra = 0;
|
|
wc.hInstance = (HINSTANCE)GetModuleHandle(NULL);
|
|
wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
|
|
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
|
|
wc.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);
|
|
wc.lpszMenuName = NULL;
|
|
wc.lpszClassName = pszClass;
|
|
aClass = RegisterClass(&wc);
|
|
if (aClass == 0)
|
|
{
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
/******************************Public*Routine******************************\
|
|
*
|
|
* glwinCreateWindow
|
|
*
|
|
* Create a new rendering window
|
|
*
|
|
* History:
|
|
* Fri Aug 30 14:38:49 1996 -by- Drew Bliss [drewb]
|
|
* Created
|
|
*
|
|
\**************************************************************************/
|
|
|
|
GLWINDOW glwinCreateWindow(HWND hwndParent,
|
|
char *pszTitle, int x, int y,
|
|
int iWidth, int iHeight,
|
|
DWORD dwFlags)
|
|
{
|
|
GLWINDOW gw;
|
|
RECT rct;
|
|
PIXELFORMATDESCRIPTOR pfd;
|
|
GLWINCREATESTRUCT gcs;
|
|
int ipfd;
|
|
DWORD dwStyle;
|
|
|
|
if (!glwinRegisterClass())
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
gw = (GLWINDOW)malloc(sizeof(_GLWINDOW));
|
|
if (gw == NULL)
|
|
{
|
|
return NULL;
|
|
}
|
|
memset(gw, 0, sizeof(*gw));
|
|
|
|
if (hwndParent != NULL)
|
|
{
|
|
dwStyle = WS_CHILDWINDOW;
|
|
}
|
|
else
|
|
{
|
|
dwStyle = WS_OVERLAPPEDWINDOW;
|
|
}
|
|
dwStyle |= WS_CLIPCHILDREN | WS_CLIPSIBLINGS;
|
|
|
|
// Create base window
|
|
rct.left = x;
|
|
rct.top = y;
|
|
rct.right = x+iWidth;
|
|
rct.bottom = y+iHeight;
|
|
AdjustWindowRect(&rct, dwStyle, FALSE);
|
|
|
|
gcs.wSize = sizeof(gcs);
|
|
gcs.gw = gw;
|
|
gw->hwnd = CreateWindow(pszClass, pszTitle, dwStyle,
|
|
rct.left, rct.top,
|
|
rct.right-rct.left, rct.bottom-rct.top,
|
|
hwndParent, NULL, GetModuleHandle(NULL), &gcs);
|
|
if (gw->hwnd == NULL)
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
ShowWindow(gw->hwnd, SW_SHOWDEFAULT);
|
|
UpdateWindow(gw->hwnd);
|
|
|
|
gw->hdc = GetDC(gw->hwnd);
|
|
if (gw->hdc == NULL)
|
|
{
|
|
goto DestroyWin;
|
|
}
|
|
|
|
// Create an OpenGL rendering context
|
|
memset(&pfd, 0, sizeof(pfd));
|
|
pfd.nSize = sizeof(pfd);
|
|
pfd.nVersion = 1;
|
|
pfd.dwFlags = PFD_GENERIC_FORMAT;
|
|
if (dwFlags & GLWIN_GENERIC_ACCELERATED)
|
|
{
|
|
pfd.dwFlags |= PFD_GENERIC_ACCELERATED;
|
|
}
|
|
if (dwFlags & GLWIN_BACK_BUFFER)
|
|
{
|
|
pfd.dwFlags |= PFD_DOUBLEBUFFER;
|
|
}
|
|
pfd.iPixelType = PFD_TYPE_RGBA;
|
|
if (dwFlags & GLWIN_ACCUM_BUFFER)
|
|
{
|
|
pfd.cAccumBits = 64;
|
|
}
|
|
if (dwFlags & GLWIN_STENCIL_BUFFER)
|
|
{
|
|
pfd.cStencilBits = 8;
|
|
}
|
|
if (dwFlags & GLWIN_Z_BUFFER_16)
|
|
{
|
|
pfd.cDepthBits = 16;
|
|
}
|
|
else if (dwFlags & GLWIN_Z_BUFFER_32)
|
|
{
|
|
pfd.cDepthBits = 32;
|
|
}
|
|
ipfd = ChoosePixelFormat(gw->hdc, &pfd);
|
|
if (ipfd <= 0)
|
|
{
|
|
goto DestroyWin;
|
|
}
|
|
if (DescribePixelFormat(gw->hdc, ipfd, sizeof(pfd), &pfd) <= 0)
|
|
{
|
|
goto DestroyWin;
|
|
}
|
|
if (!SetPixelFormat(gw->hdc, ipfd, &pfd))
|
|
{
|
|
goto DestroyWin;
|
|
}
|
|
|
|
if (!glwinCreateRgbPalette(gw->hdc, &pfd, &gw->hpal))
|
|
{
|
|
goto DestroyWin;
|
|
}
|
|
|
|
gw->hrc = wglCreateContext(gw->hdc);
|
|
if (gw->hrc == NULL)
|
|
{
|
|
goto DestroyWin;
|
|
}
|
|
|
|
gw->iWidth = iWidth;
|
|
gw->iHeight = iHeight;
|
|
gw->dwFlags = dwFlags;
|
|
|
|
return gw;
|
|
|
|
DestroyWin:
|
|
glwinDestroyWindow(gw);
|
|
return NULL;
|
|
}
|
|
|
|
/******************************Public*Routine******************************\
|
|
*
|
|
* glwinDestroyWindow
|
|
*
|
|
* Clean up a rendering window
|
|
*
|
|
* History:
|
|
* Fri Aug 30 14:39:20 1996 -by- Drew Bliss [drewb]
|
|
* Created
|
|
*
|
|
\**************************************************************************/
|
|
|
|
void glwinDestroyWindow(GLWINDOW gw)
|
|
{
|
|
if (gw->hrc != NULL)
|
|
{
|
|
if (wglGetCurrentContext() == gw->hrc)
|
|
{
|
|
wglMakeCurrent(NULL, NULL);
|
|
}
|
|
wglDeleteContext(gw->hrc);
|
|
}
|
|
|
|
if (gw->hdc != NULL)
|
|
{
|
|
ReleaseDC(gw->hwnd, gw->hdc);
|
|
}
|
|
|
|
if (gw->hpal != NULL)
|
|
{
|
|
DeleteObject(gw->hpal);
|
|
}
|
|
|
|
if (gw->hwnd != NULL)
|
|
{
|
|
DestroyWindow(gw->hwnd);
|
|
}
|
|
}
|
|
|
|
/******************************Public*Routine******************************\
|
|
*
|
|
* glwinGetGlrc
|
|
*
|
|
* Return a rendering window's OpenGL rendering context
|
|
*
|
|
* History:
|
|
* Fri Aug 30 14:39:29 1996 -by- Drew Bliss [drewb]
|
|
* Created
|
|
*
|
|
\**************************************************************************/
|
|
|
|
HGLRC glwinGetGlrc(GLWINDOW gw)
|
|
{
|
|
return gw->hrc;
|
|
}
|
|
|
|
/******************************Public*Routine******************************\
|
|
*
|
|
* glwinGetHwnd
|
|
*
|
|
* Returns a rendering window's window system window
|
|
*
|
|
* History:
|
|
* Mon Oct 21 18:10:23 1996 -by- Drew Bliss [drewb]
|
|
* Created
|
|
*
|
|
\**************************************************************************/
|
|
|
|
HWND glwinGetHwnd(GLWINDOW gw)
|
|
{
|
|
return gw->hwnd;
|
|
}
|
|
|
|
/******************************Public*Routine******************************\
|
|
*
|
|
* glwinGetHdc
|
|
*
|
|
* Returns a renderin window's HDC
|
|
*
|
|
* History:
|
|
* Tue Oct 22 11:01:35 1996 -by- Drew Bliss [drewb]
|
|
* Created
|
|
*
|
|
\**************************************************************************/
|
|
|
|
HDC glwinGetHdc(GLWINDOW gw)
|
|
{
|
|
return gw->hdc;
|
|
}
|
|
|
|
/******************************Public*Routine******************************\
|
|
*
|
|
* glwinGetFlags
|
|
*
|
|
* Returns creation flags
|
|
*
|
|
* History:
|
|
* Mon Oct 21 18:28:24 1996 -by- Drew Bliss [drewb]
|
|
* Created
|
|
*
|
|
\**************************************************************************/
|
|
|
|
DWORD glwinGetFlags(GLWINDOW gw)
|
|
{
|
|
return gw->dwFlags;
|
|
}
|
|
|
|
/******************************Public*Routine******************************\
|
|
*
|
|
* glwinGetLastError
|
|
*
|
|
* Returns the last error recorded by the library
|
|
*
|
|
* History:
|
|
* Fri Aug 30 14:39:39 1996 -by- Drew Bliss [drewb]
|
|
* Created
|
|
*
|
|
\**************************************************************************/
|
|
|
|
LONG glwinGetLastError(void)
|
|
{
|
|
#if DBG
|
|
char pszMsg[80];
|
|
|
|
if (GetLastError() != ERROR_SUCCESS)
|
|
{
|
|
sprintf(pszMsg, "glwinGetLastError returning %d (0x%08lX)\n",
|
|
GetLastError(), GetLastError());
|
|
OutputDebugString(pszMsg);
|
|
}
|
|
#endif
|
|
return GetLastError();
|
|
}
|
|
|
|
/******************************Public*Routine******************************\
|
|
*
|
|
* glwinMakeCurrent
|
|
*
|
|
* Makes the given rendering window's OpenGL rendering context current
|
|
*
|
|
* History:
|
|
* Fri Aug 30 14:39:47 1996 -by- Drew Bliss [drewb]
|
|
* Created
|
|
*
|
|
\**************************************************************************/
|
|
|
|
BOOL glwinMakeCurrent(GLWINDOW gw)
|
|
{
|
|
return wglMakeCurrent(gw->hdc, gw->hrc);
|
|
}
|
|
|
|
/******************************Public*Routine******************************\
|
|
*
|
|
* glwinSwapBuffers
|
|
*
|
|
* Performs double-buffer swapping through blt or flip
|
|
*
|
|
* History:
|
|
* Fri Aug 30 14:40:49 1996 -by- Drew Bliss [drewb]
|
|
* Created
|
|
*
|
|
\**************************************************************************/
|
|
|
|
BOOL glwinSwapBuffers(GLWINDOW gw)
|
|
{
|
|
return SwapBuffers(gw->hdc);
|
|
}
|
|
|
|
/******************************Public*Routine******************************\
|
|
*
|
|
* glwinIdleCallback
|
|
*
|
|
* Set the idle-time callback
|
|
*
|
|
* History:
|
|
* Fri Aug 30 14:41:28 1996 -by- Drew Bliss [drewb]
|
|
* Created
|
|
*
|
|
\**************************************************************************/
|
|
|
|
void glwinIdleCallback(GLWINDOW gw, GLWINIDLECALLBACK cb)
|
|
{
|
|
gw->cbIdle = cb;
|
|
}
|
|
|
|
/******************************Public*Routine******************************\
|
|
*
|
|
* glwinMessageCallback
|
|
*
|
|
* Set the message interposition callback
|
|
*
|
|
* History:
|
|
* Fri Aug 30 14:41:40 1996 -by- Drew Bliss [drewb]
|
|
* Created
|
|
*
|
|
\**************************************************************************/
|
|
|
|
void glwinMessageCallback(GLWINDOW gw, GLWINMESSAGECALLBACK cb)
|
|
{
|
|
gw->cbMessage = cb;
|
|
}
|
|
|
|
/******************************Public*Routine******************************\
|
|
*
|
|
* glwinRunWindow
|
|
*
|
|
* Run the message loop for a single window
|
|
*
|
|
* History:
|
|
* Fri Aug 30 14:41:58 1996 -by- Drew Bliss [drewb]
|
|
* Created
|
|
*
|
|
\**************************************************************************/
|
|
|
|
void glwinRunWindow(GLWINDOW gw)
|
|
{
|
|
MSG msg;
|
|
BOOL bQuit;
|
|
|
|
bQuit = FALSE;
|
|
while (!bQuit)
|
|
{
|
|
while (!bQuit && PeekMessage(&msg, gw->hwnd, 0, 0, PM_NOREMOVE))
|
|
{
|
|
if (GetMessage(&msg, gw->hwnd, 0, 0))
|
|
{
|
|
TranslateMessage(&msg);
|
|
DispatchMessage(&msg);
|
|
}
|
|
else
|
|
{
|
|
bQuit = TRUE;
|
|
}
|
|
}
|
|
|
|
// Call the idle callback if one exists
|
|
if (gw->cbIdle != NULL)
|
|
{
|
|
gw->cbIdle(gw);
|
|
}
|
|
}
|
|
}
|
|
|
|
/******************************Public*Routine******************************\
|
|
*
|
|
* glwinRun
|
|
*
|
|
* Run a message loop for all windows
|
|
*
|
|
* History:
|
|
* Tue Oct 22 11:13:48 1996 -by- Drew Bliss [drewb]
|
|
* Created
|
|
*
|
|
\**************************************************************************/
|
|
|
|
void glwinRun(GLWINIDLECALLBACK cb)
|
|
{
|
|
MSG msg;
|
|
BOOL bQuit;
|
|
|
|
bQuit = FALSE;
|
|
while (!bQuit)
|
|
{
|
|
while (!bQuit && PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE))
|
|
{
|
|
if (GetMessage(&msg, NULL, 0, 0))
|
|
{
|
|
TranslateMessage(&msg);
|
|
DispatchMessage(&msg);
|
|
}
|
|
else
|
|
{
|
|
bQuit = TRUE;
|
|
}
|
|
}
|
|
|
|
// Call the idle callback if one exists
|
|
if (cb != NULL)
|
|
{
|
|
cb(NULL);
|
|
}
|
|
}
|
|
}
|