mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2026-01-08 21:30:23 +01:00
1221 lines
No EOL
34 KiB
C++
1221 lines
No EOL
34 KiB
C++
|
||
/* Copyright (c) Mark J. Kilgard, 1994, 1997. */
|
||
|
||
/* This program is freely distributable without licensing fees
|
||
and is provided without guarantee or warrantee expressed or
|
||
implied. This program is -not- in the public domain. */
|
||
|
||
#ifdef __VMS
|
||
#include <GL/vms_x_fix.h>
|
||
#endif
|
||
|
||
#include <stdlib.h>
|
||
#include <stdio.h>
|
||
#include <string.h>
|
||
#include <assert.h>
|
||
#if defined(__OS2__)
|
||
#define POKA 0
|
||
#include "WarpGL.h"
|
||
#include "glutos2.h"
|
||
#include "glutint.h"
|
||
|
||
#include "gl\os2mesa.h"
|
||
|
||
//
|
||
//define for resource id for main GLUT window, in samples it is defined in GL_TEST.h
|
||
#define ID_WINDOW 256
|
||
|
||
int evglSetPixelFormat(int iPixelFormat);
|
||
HPS hpsCurrent;
|
||
|
||
#elif !defined(_WIN32)
|
||
|
||
#include <X11/Xlib.h>
|
||
#include <X11/Xatom.h>
|
||
#endif
|
||
|
||
#include "glutint.h"
|
||
|
||
GLUTwindow *__glutCurrentWindow = NULL;
|
||
GLUTwindow **__glutWindowList = NULL;
|
||
int __glutWindowListSize = 0;
|
||
#if !defined(_WIN32) && !defined(__OS2__)
|
||
GLUTstale *__glutStaleWindowList = NULL;
|
||
#endif
|
||
GLUTwindow *__glutMenuWindow = NULL;
|
||
|
||
void (*__glutFreeOverlayFunc) (GLUToverlay *);
|
||
XVisualInfo *(*__glutDetermineVisualFromString) (char *string, Bool * treatAsSingle,
|
||
Criterion * requiredCriteria, int nRequired, int requiredMask, void** fbc) = NULL;
|
||
|
||
static Criterion requiredWindowCriteria[] =
|
||
{
|
||
{LEVEL, EQ, 0},
|
||
{TRANSPARENT, EQ, 0}
|
||
};
|
||
static int numRequiredWindowCriteria = sizeof(requiredWindowCriteria) / sizeof(Criterion);
|
||
static int requiredWindowCriteriaMask = (1 << LEVEL) | (1 << TRANSPARENT);
|
||
|
||
static void
|
||
cleanWindowWorkList(GLUTwindow * window)
|
||
{
|
||
GLUTwindow **pEntry = &__glutWindowWorkList;
|
||
GLUTwindow *entry = __glutWindowWorkList;
|
||
|
||
/* Tranverse singly-linked window work list look for the
|
||
window. */
|
||
while (entry) {
|
||
if (entry == window) {
|
||
/* Found it; delete it. */
|
||
*pEntry = entry->prevWorkWin;
|
||
return;
|
||
} else {
|
||
pEntry = &entry->prevWorkWin;
|
||
entry = *pEntry;
|
||
}
|
||
}
|
||
}
|
||
|
||
#if !defined(_WIN32) && !defined(__OS2PM__)
|
||
|
||
static void
|
||
cleanStaleWindowList(GLUTwindow * window)
|
||
{
|
||
GLUTstale **pEntry = &__glutStaleWindowList;
|
||
GLUTstale *entry = __glutStaleWindowList;
|
||
|
||
/* Tranverse singly-linked stale window list look for the
|
||
window ID. */
|
||
while (entry) {
|
||
if (entry->window == window) {
|
||
/* Found it; delete it. */
|
||
*pEntry = entry->next;
|
||
free(entry);
|
||
return;
|
||
} else {
|
||
pEntry = &entry->next;
|
||
entry = *pEntry;
|
||
}
|
||
}
|
||
}
|
||
|
||
#endif
|
||
|
||
static GLUTwindow *__glutWindowCache = NULL;
|
||
|
||
GLUTwindow *
|
||
__glutGetWindow(Window win)
|
||
{
|
||
int i;
|
||
|
||
/* Does win belong to the last window ID looked up? */
|
||
if (__glutWindowCache && (win == __glutWindowCache->win ||
|
||
(__glutWindowCache->overlay && win ==
|
||
__glutWindowCache->overlay->win))) {
|
||
return
|
||
__glutWindowCache;
|
||
}
|
||
/* Otherwise scan the window list looking for the window ID. */
|
||
for (i = 0; i < __glutWindowListSize; i++) {
|
||
if (__glutWindowList[i]) {
|
||
if (win == __glutWindowList[i]->win) {
|
||
__glutWindowCache = __glutWindowList[i];
|
||
return __glutWindowCache;
|
||
}
|
||
if (__glutWindowList[i]->overlay) {
|
||
if (win == __glutWindowList[i]->overlay->win) {
|
||
__glutWindowCache = __glutWindowList[i];
|
||
return __glutWindowCache;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
#if !defined(_WIN32) && !defined(__OS2PM__)
|
||
{
|
||
GLUTstale *entry;
|
||
|
||
/* Scan through destroyed overlay window IDs for which no
|
||
DestroyNotify has yet been received. */
|
||
for (entry = __glutStaleWindowList; entry; entry = entry->next) {
|
||
if (entry->win == win)
|
||
return entry->window;
|
||
}
|
||
}
|
||
#endif
|
||
return NULL;
|
||
}
|
||
|
||
/* CENTRY */
|
||
int GLUTAPIENTRY
|
||
glutGetWindow(void)
|
||
{
|
||
if (__glutCurrentWindow) {
|
||
return __glutCurrentWindow->num + 1;
|
||
} else {
|
||
return 0;
|
||
}
|
||
}
|
||
/* ENDCENTRY */
|
||
|
||
void
|
||
__glutSetWindow(GLUTwindow * window)
|
||
{
|
||
/* It is tempting to try to short-circuit the call to
|
||
glXMakeCurrent if we "know" we are going to make current
|
||
to a window we are already current to. In fact, this
|
||
assumption breaks when GLUT is expected to integrated with
|
||
other OpenGL windowing APIs that also make current to
|
||
OpenGL contexts. Since glXMakeCurrent short-circuits the
|
||
"already bound" case, GLUT avoids the temptation to do so
|
||
too. */
|
||
__glutCurrentWindow = window;
|
||
|
||
MAKE_CURRENT_LAYER(__glutCurrentWindow);
|
||
|
||
#if !defined(_WIN32) && !defined(__OS2__)
|
||
/* We should be careful to force a finish between each
|
||
iteration through the GLUT main loop if indirect OpenGL
|
||
contexts are in use; indirect contexts tend to have much
|
||
longer latency because lots of OpenGL extension requests
|
||
can queue up in the X protocol stream. We accomplish this
|
||
by posting GLUT_FINISH_WORK to be done. */
|
||
if (!__glutCurrentWindow->isDirect)
|
||
__glutPutOnWorkList(__glutCurrentWindow, GLUT_FINISH_WORK);
|
||
#endif
|
||
|
||
/* If debugging is enabled, we'll want to check this window
|
||
for any OpenGL errors every iteration through the GLUT
|
||
main loop. To accomplish this, we post the
|
||
GLUT_DEBUG_WORK to be done on this window. */
|
||
if (__glutDebug) {
|
||
__glutPutOnWorkList(__glutCurrentWindow, GLUT_DEBUG_WORK);
|
||
}
|
||
}
|
||
|
||
/* CENTRY */
|
||
void GLUTAPIENTRY
|
||
glutSetWindow(int win)
|
||
{
|
||
GLUTwindow *window;
|
||
|
||
if (win < 1 || win > __glutWindowListSize) {
|
||
__glutWarning("glutSetWindow attempted on bogus window.");
|
||
return;
|
||
}
|
||
window = __glutWindowList[win - 1];
|
||
if (!window) {
|
||
__glutWarning("glutSetWindow attempted on bogus window.");
|
||
return;
|
||
}
|
||
__glutSetWindow(window);
|
||
}
|
||
/* ENDCENTRY */
|
||
|
||
static int
|
||
getUnusedWindowSlot(void)
|
||
{
|
||
int i;
|
||
|
||
/* Look for allocated, unused slot. */
|
||
for (i = 0; i < __glutWindowListSize; i++) {
|
||
if (!__glutWindowList[i]) {
|
||
return i;
|
||
}
|
||
}
|
||
/* Allocate a new slot. */
|
||
__glutWindowListSize++;
|
||
if (__glutWindowList) {
|
||
__glutWindowList = (GLUTwindow **)
|
||
realloc(__glutWindowList,
|
||
__glutWindowListSize * sizeof(GLUTwindow *));
|
||
} else {
|
||
/* XXX Some realloc's do not correctly perform a malloc
|
||
when asked to perform a realloc on a NULL pointer,
|
||
though the ANSI C library spec requires this. */
|
||
__glutWindowList = (GLUTwindow **)
|
||
malloc(sizeof(GLUTwindow *));
|
||
}
|
||
if (!__glutWindowList)
|
||
__glutFatalError("out of memory.");
|
||
__glutWindowList[__glutWindowListSize - 1] = NULL;
|
||
return __glutWindowListSize - 1;
|
||
}
|
||
|
||
static XVisualInfo *
|
||
getVisualInfoCI(unsigned int mode)
|
||
{
|
||
#if POKA
|
||
static int bufSizeList[] =
|
||
{16, 12, 8, 4, 2, 1, 0};
|
||
XVisualInfo *vi;
|
||
int list[32];
|
||
int i, n = 0;
|
||
|
||
/* Should not be looking at display mode mask if
|
||
__glutDisplayString is non-NULL. */
|
||
assert(!__glutDisplayString);
|
||
|
||
list[n++] = GLX_BUFFER_SIZE;
|
||
list[n++] = 1;
|
||
if (GLUT_WIND_IS_DOUBLE(mode)) {
|
||
list[n++] = GLX_DOUBLEBUFFER;
|
||
}
|
||
if (GLUT_WIND_IS_STEREO(mode)) {
|
||
list[n++] = GLX_STEREO;
|
||
}
|
||
if (GLUT_WIND_HAS_DEPTH(mode)) {
|
||
list[n++] = GLX_DEPTH_SIZE;
|
||
list[n++] = 1;
|
||
}
|
||
if (GLUT_WIND_HAS_STENCIL(mode)) {
|
||
list[n++] = GLX_STENCIL_SIZE;
|
||
list[n++] = 1;
|
||
}
|
||
list[n] = (int) None; /* terminate list */
|
||
|
||
/* glXChooseVisual specify GLX_BUFFER_SIZE prefers the
|
||
"smallest index buffer of at least the specified size".
|
||
This would be reasonable if GLUT allowed the user to
|
||
specify the required buffe size, but GLUT's display mode
|
||
is too simplistic (easy to use?). GLUT should try to find
|
||
the "largest". So start with a large buffer size and
|
||
shrink until we find a matching one that exists. */
|
||
|
||
for (i = 0; bufSizeList[i]; i++) {
|
||
/* XXX Assumes list[1] is where GLX_BUFFER_SIZE parameter
|
||
is. */
|
||
list[1] = bufSizeList[i];
|
||
vi = glXChooseVisual(__glutDisplay,
|
||
__glutScreen, list);
|
||
if (vi)
|
||
return vi;
|
||
}
|
||
return NULL;
|
||
#else
|
||
return
|
||
glXChooseVisual(mode);
|
||
|
||
#endif
|
||
}
|
||
|
||
static XVisualInfo *
|
||
getVisualInfoRGB(unsigned int mode)
|
||
{
|
||
#if POKA
|
||
int list[32];
|
||
int n = 0;
|
||
|
||
/* Should not be looking at display mode mask if
|
||
__glutDisplayString is non-NULL. */
|
||
assert(!__glutDisplayString);
|
||
|
||
/* XXX Would a caching mechanism to minize the calls to
|
||
glXChooseVisual? You'd have to reference count
|
||
XVisualInfo* pointers. Would also have to properly
|
||
interact with glutInitDisplayString. */
|
||
|
||
list[n++] = GLX_RGBA;
|
||
list[n++] = GLX_RED_SIZE;
|
||
list[n++] = 1;
|
||
list[n++] = GLX_GREEN_SIZE;
|
||
list[n++] = 1;
|
||
list[n++] = GLX_BLUE_SIZE;
|
||
list[n++] = 1;
|
||
if (GLUT_WIND_HAS_ALPHA(mode)) {
|
||
list[n++] = GLX_ALPHA_SIZE;
|
||
list[n++] = 1;
|
||
}
|
||
if (GLUT_WIND_IS_DOUBLE(mode)) {
|
||
list[n++] = GLX_DOUBLEBUFFER;
|
||
}
|
||
if (GLUT_WIND_IS_STEREO(mode)) {
|
||
list[n++] = GLX_STEREO;
|
||
}
|
||
if (GLUT_WIND_HAS_DEPTH(mode)) {
|
||
list[n++] = GLX_DEPTH_SIZE;
|
||
list[n++] = 1;
|
||
}
|
||
if (GLUT_WIND_HAS_STENCIL(mode)) {
|
||
list[n++] = GLX_STENCIL_SIZE;
|
||
list[n++] = 1;
|
||
}
|
||
if (GLUT_WIND_HAS_ACCUM(mode)) {
|
||
list[n++] = GLX_ACCUM_RED_SIZE;
|
||
list[n++] = 1;
|
||
list[n++] = GLX_ACCUM_GREEN_SIZE;
|
||
list[n++] = 1;
|
||
list[n++] = GLX_ACCUM_BLUE_SIZE;
|
||
list[n++] = 1;
|
||
if (GLUT_WIND_HAS_ALPHA(mode)) {
|
||
list[n++] = GLX_ACCUM_ALPHA_SIZE;
|
||
list[n++] = 1;
|
||
}
|
||
}
|
||
#if defined(GLX_VERSION_1_1) && (defined(GLX_SGIS_multisample) || defined(GLX_ARB_multisample))
|
||
if (GLUT_WIND_IS_MULTISAMPLE(mode)) {
|
||
if (!__glutIsSupportedByGLX("GLX_SGIS_multisample") &&
|
||
!__glutIsSupportedByGLX("GLX_ARB_multisample"))
|
||
return NULL;
|
||
#if defined(GLX_ARB_multisample)
|
||
list[n++] = GLX_SAMPLES_ARB;
|
||
#elif defined(GLX_SGIS_multisample)
|
||
list[n++] = GLX_SAMPLES_SGIS;
|
||
#endif
|
||
/* XXX Is 4 a reasonable minimum acceptable number of
|
||
samples? */
|
||
list[n++] = 4;
|
||
}
|
||
#endif
|
||
list[n] = (int) None; /* terminate list */
|
||
|
||
return glXChooseVisual(__glutDisplay,
|
||
__glutScreen, list);
|
||
#else /* POKA */
|
||
|
||
return
|
||
glXChooseVisual(mode);
|
||
|
||
#endif
|
||
}
|
||
|
||
XVisualInfo *
|
||
__glutGetVisualInfo(unsigned int mode)
|
||
{
|
||
/* XXX GLUT_LUMINANCE not implemented for GLUT 3.0. */
|
||
if (GLUT_WIND_IS_LUMINANCE(mode))
|
||
return NULL;
|
||
|
||
if (GLUT_WIND_IS_RGB(mode))
|
||
return getVisualInfoRGB(mode);
|
||
else
|
||
return getVisualInfoCI(mode);
|
||
}
|
||
|
||
XVisualInfo *
|
||
__glutDetermineVisual(
|
||
unsigned int displayMode,
|
||
Bool * treatAsSingle,
|
||
XVisualInfo * (getVisualInfo) (unsigned int))
|
||
{
|
||
XVisualInfo *vis;
|
||
|
||
/* Should not be looking at display mode mask if
|
||
__glutDisplayString is non-NULL. */
|
||
assert(!__glutDisplayString);
|
||
|
||
*treatAsSingle = GLUT_WIND_IS_SINGLE(displayMode);
|
||
vis = getVisualInfo(displayMode);
|
||
if (!vis) {
|
||
/* Fallback cases when can't get exactly what was asked
|
||
for... */
|
||
if (GLUT_WIND_IS_SINGLE(displayMode)) {
|
||
/* If we can't find a single buffered visual, try looking
|
||
for a double buffered visual. We can treat a double
|
||
buffered visual as a single buffer visual by changing
|
||
the draw buffer to GL_FRONT and treating any swap
|
||
buffers as no-ops. */
|
||
displayMode |= GLUT_DOUBLE;
|
||
vis = getVisualInfo(displayMode);
|
||
*treatAsSingle = True;
|
||
}
|
||
if (!vis && GLUT_WIND_IS_MULTISAMPLE(displayMode)) {
|
||
/* If we can't seem to get multisampling (ie, not Reality
|
||
Engine class graphics!), go without multisampling. It
|
||
is up to the application to query how many multisamples
|
||
were allocated (0 equals no multisampling) if the
|
||
application is going to use multisampling for more than
|
||
just antialiasing. */
|
||
displayMode &= ~GLUT_MULTISAMPLE;
|
||
vis = getVisualInfo(displayMode);
|
||
}
|
||
}
|
||
return vis;
|
||
}
|
||
|
||
static void GLUTCALLBACK
|
||
__glutDefaultDisplay(void)
|
||
{
|
||
/* XXX Remove the warning after GLUT 3.0. */
|
||
__glutWarning("The following is a new check for GLUT 3.0; update your code.");
|
||
__glutFatalError(
|
||
"redisplay needed for window %d, but no display callback.",
|
||
__glutCurrentWindow->num + 1);
|
||
}
|
||
|
||
void GLUTCALLBACK
|
||
__glutDefaultReshape(int width, int height)
|
||
{
|
||
GLUToverlay *overlay;
|
||
|
||
/* Adjust the viewport of the window (and overlay if one
|
||
exists). */
|
||
MAKE_CURRENT_WINDOW(__glutCurrentWindow);
|
||
glViewport(0, 0, (GLsizei) width, (GLsizei) height);
|
||
overlay = __glutCurrentWindow->overlay;
|
||
if (overlay) {
|
||
MAKE_CURRENT_OVERLAY(overlay);
|
||
glViewport(0, 0, (GLsizei) width, (GLsizei) height);
|
||
}
|
||
/* Make sure we are current to the current layer (application
|
||
should be able to count on the current layer not changing
|
||
unless the application explicitly calls glutUseLayer). */
|
||
MAKE_CURRENT_LAYER(__glutCurrentWindow);
|
||
}
|
||
|
||
XVisualInfo *
|
||
__glutDetermineWindowVisual(Bool * treatAsSingle, Bool * visAlloced, void **fbc)
|
||
{
|
||
if (__glutDisplayString) {
|
||
|
||
/* __glutDisplayString should be NULL except if
|
||
glutInitDisplayString has been called to register a
|
||
different display string. Calling glutInitDisplayString
|
||
means using a string instead of an integer mask determine
|
||
the visual to use. Using the function pointer variable
|
||
__glutDetermineVisualFromString below avoids linking in
|
||
the code for implementing glutInitDisplayString (ie,
|
||
glut_dstr.o) unless glutInitDisplayString gets called by
|
||
the application. */
|
||
|
||
assert(__glutDetermineVisualFromString);
|
||
*visAlloced = False;
|
||
*fbc = NULL;
|
||
return __glutDetermineVisualFromString(__glutDisplayString, treatAsSingle,
|
||
requiredWindowCriteria, numRequiredWindowCriteria, requiredWindowCriteriaMask, fbc);
|
||
} else {
|
||
*visAlloced = True;
|
||
*fbc = NULL;
|
||
return __glutDetermineVisual(__glutDisplayMode,
|
||
treatAsSingle, __glutGetVisualInfo);
|
||
}
|
||
}
|
||
|
||
/* ARGSUSED5 */ /* Only Win32 uses gameMode parameter. */
|
||
GLUTwindow *
|
||
__glutCreateWindow(GLUTwindow * parent,
|
||
int x, int y, int width, int height, int gameMode)
|
||
{
|
||
GLUTwindow *window;
|
||
XSetWindowAttributes wa;
|
||
unsigned long attribMask;
|
||
int winnum;
|
||
int i;
|
||
#if defined(GLX_VERSION_1_1) && defined(GLX_SGIX_fbconfig)
|
||
GLXFBConfigSGIX fbc;
|
||
#else
|
||
void *fbc;
|
||
#endif
|
||
|
||
#if defined(__OS2PM__)
|
||
{
|
||
extern HAB hab; /* PM anchor block handle */
|
||
CLASSINFO classinfo;
|
||
|
||
if(!WinQueryClassInfo(hab,"GLUT", &classinfo) )
|
||
__glutOpenOS2Connection(NULL);
|
||
}
|
||
#elif defined(_WIN32)
|
||
WNDCLASS wc;
|
||
int style;
|
||
|
||
if (!GetClassInfo(GetModuleHandle(NULL), "GLUT", &wc)) {
|
||
__glutOpenWin32Connection(NULL);
|
||
}
|
||
#else
|
||
if (!__glutDisplay) {
|
||
__glutOpenXConnection(NULL);
|
||
}
|
||
#endif
|
||
|
||
#ifndef __OS2PM__
|
||
if (__glutGameModeWindow) {
|
||
__glutFatalError("cannot create windows in game mode.");
|
||
}
|
||
#endif
|
||
|
||
winnum = getUnusedWindowSlot();
|
||
window = (GLUTwindow *) malloc(sizeof(GLUTwindow));
|
||
if (!window) {
|
||
__glutFatalError("out of memory.");
|
||
}
|
||
window->num = winnum;
|
||
|
||
#if defined(__OS2PM__)
|
||
/* Add this new window to the window list. */
|
||
__glutWindowList[winnum] = window;
|
||
window->shownState = -1;
|
||
#endif
|
||
|
||
#if !defined(_WIN32) && !defined(__OS2PM__)
|
||
window->vis = __glutDetermineWindowVisual(&window->treatAsSingle,
|
||
&window->visAlloced, (void**) &fbc);
|
||
if (!window->vis) {
|
||
__glutFatalError(
|
||
"visual with necessary capabilities not found.");
|
||
}
|
||
__glutSetupColormap(window->vis, &window->colormap, &window->cmap);
|
||
#endif
|
||
window->eventMask = StructureNotifyMask | ExposureMask;
|
||
|
||
attribMask = CWBackPixmap | CWBorderPixel | CWColormap | CWEventMask;
|
||
wa.background_pixmap = None;
|
||
wa.border_pixel = 0;
|
||
wa.colormap = window->cmap;
|
||
wa.event_mask = window->eventMask;
|
||
if (parent) {
|
||
if (parent->eventMask & GLUT_HACK_STOP_PROPAGATE_MASK)
|
||
wa.event_mask |= GLUT_HACK_STOP_PROPAGATE_MASK;
|
||
attribMask |= CWDontPropagate;
|
||
wa.do_not_propagate_mask = parent->eventMask & GLUT_DONT_PROPAGATE_FILTER_MASK;
|
||
} else {
|
||
wa.do_not_propagate_mask = 0;
|
||
}
|
||
|
||
/* Stash width and height before Win32's __glutAdjustCoords
|
||
possibly overwrites the values. */
|
||
window->width = width;
|
||
window->height = height;
|
||
window->forceReshape = True;
|
||
window->ignoreKeyRepeat = False;
|
||
|
||
#if defined(__OS2PM__)
|
||
|
||
{ ULONG flStyle=0;
|
||
int ii;
|
||
ERRORID erridErrorCode;/* last error id code */
|
||
extern HAB hab; /* PM anchor block handle */
|
||
|
||
if (parent) {
|
||
flStyle = WS_CLIPCHILDREN|WS_VISIBLE;
|
||
} else {
|
||
if (gameMode) {
|
||
/* Game mode window should be a WS_POPUP window to
|
||
ensure that the taskbar is hidden by it. A standard
|
||
WS_OVERLAPPEDWINDOW does not hide the task bar. */
|
||
flStyle = FCF_STANDARD | WS_MAXIMIZED;
|
||
} else {
|
||
/* A standard toplevel window with borders and such. */
|
||
flStyle = FCF_STANDARD | WS_CLIPCHILDREN;
|
||
// flStyle = WS_OVERLAPPEDWINDOW;
|
||
}
|
||
}
|
||
{
|
||
HWND hwnd; /* Window */
|
||
ULONG ListBoxId; /* Window id */
|
||
/* (supplied by application) */
|
||
|
||
|
||
HWND hwndClient; /* handle to the client */
|
||
HWND hwndFrame; /* handle to the frame */
|
||
PFNWP GenericWndProc;
|
||
FRAMECDATA fcd;
|
||
RECTL rect; /* Boundary rectangle */
|
||
|
||
|
||
|
||
/************************************************/
|
||
// flCreate = (FCF_STANDARD) & ~FCF_TASKLIST;
|
||
/**********************************/
|
||
if (parent)
|
||
{ window->frame = NULL;
|
||
|
||
hwnd = WinCreateWindow(parent->win, /* Parent window */
|
||
"GLUTCHILD", /* Class name */
|
||
"", /* Window text */
|
||
flStyle, /* Window style */
|
||
x, y, /* Position (x,y) */
|
||
width, height, /* Size (width,height) */
|
||
parent->win, /* Owner window */
|
||
HWND_TOP, /* Sibling window */
|
||
0, /* Window id */
|
||
NULL, /* Control data */
|
||
NULL); /* Pres parameters */
|
||
|
||
erridErrorCode = WinGetLastError(hab);
|
||
window->win = hwnd;
|
||
|
||
window->hdc = WinOpenWindowDC(window->win);
|
||
window->hpsBuffer = hpsCurrent;
|
||
|
||
|
||
rect.xLeft = x;
|
||
rect.xRight = x+width;
|
||
rect.yBottom = y;
|
||
rect.yTop = y + height;
|
||
|
||
/***** else parent *****************************/
|
||
} else {
|
||
hwnd = WinCreateStdWindow(HWND_DESKTOP,
|
||
0, /* WS_VISIBLE frame-window style */
|
||
&flStyle, /* window style */
|
||
"GLUT", /* class name */
|
||
"GLUT",/* window title */
|
||
0L, /* default client style */
|
||
NULLHANDLE, /* resource in executable file */
|
||
ID_WINDOW, /* resource id */
|
||
&hwndClient); /* receives client window handle */
|
||
|
||
erridErrorCode = WinGetLastError(hab);
|
||
window->win = hwndClient;
|
||
window->frame = hwnd;
|
||
window->hdc = WinOpenWindowDC(window->win);
|
||
|
||
window->hpsBuffer = hpsCurrent;
|
||
|
||
|
||
/* converts a client window's boundaries into an equivalent frame rectangle */
|
||
rect.xLeft = x;
|
||
rect.xRight = x+width;
|
||
rect.yBottom = y;
|
||
rect.yTop = y + height;
|
||
|
||
/* calculate equivalent frame boundary from boundary data */
|
||
WinCalcFrameRect(window->frame, &rect, FALSE);
|
||
}
|
||
/***** endof if(parent) *****************************/
|
||
|
||
/* Must set the XHDC for fake glXChooseVisual & fake
|
||
glXCreateContext & fake XAllocColorCells. */
|
||
XHDC = window->hdc;
|
||
XHWND = window->win;
|
||
window->vis = __glutDetermineWindowVisual(&window->treatAsSingle,
|
||
&window->visAlloced, &fbc);
|
||
if (!window->vis)
|
||
{ __glutFatalError(
|
||
"pixel format with necessary capabilities not found.");
|
||
}
|
||
{ int rc;
|
||
rc = wglChoosePixelFormat(window->hdc, window->vis),
|
||
|
||
// evglSetPixelFormat(2); /* int iPixelFormat 1 - doublebuffer/2 - single buffer ??*/
|
||
wglSetPixelFormat(window->hdc,rc,window->vis);
|
||
}
|
||
__glutSetupColormap(window->vis, &window->colormap, &window->cmap);
|
||
|
||
window->ctx = glXCreateContext(window->hpsBuffer, window->vis,
|
||
None, __glutTryDirect);
|
||
|
||
WinSetWindowPos(hwnd,
|
||
HWND_TOP,rect.xLeft,rect.yBottom,
|
||
rect.xRight-rect.xLeft, rect.yTop-rect.yBottom,
|
||
SWP_ACTIVATE | SWP_MOVE | SWP_SIZE | SWP_SHOW|SWP_ZORDER); /* flags*/
|
||
|
||
/* Make sure subwindows get a windowStatus callback. */
|
||
if (parent)
|
||
WinPostMsg(parent->win, WM_ACTIVATE, 0, 0);
|
||
|
||
}
|
||
}
|
||
|
||
#elif defined(_WIN32)
|
||
|
||
__glutAdjustCoords(parent ? parent->win : NULL,
|
||
&x, &y, &width, &height);
|
||
if (parent) {
|
||
style = WS_CHILD;
|
||
} else {
|
||
if (gameMode) {
|
||
/* Game mode window should be a WS_POPUP window to
|
||
ensure that the taskbar is hidden by it. A standard
|
||
WS_OVERLAPPEDWINDOW does not hide the task bar. */
|
||
style = WS_POPUP | WS_MAXIMIZE;
|
||
} else {
|
||
/* A standard toplevel window with borders and such. */
|
||
style = WS_OVERLAPPEDWINDOW;
|
||
}
|
||
}
|
||
window->win = CreateWindow("GLUT", "GLUT",
|
||
WS_CLIPSIBLINGS | WS_CLIPCHILDREN | style,
|
||
x, y, width, height, parent ? parent->win : __glutRoot,
|
||
NULL, GetModuleHandle(NULL), 0);
|
||
window->hdc = GetDC(window->win);
|
||
/* Must set the XHDC for fake glXChooseVisual & fake
|
||
glXCreateContext & fake XAllocColorCells. */
|
||
XHDC = window->hdc;
|
||
window->vis = __glutDetermineWindowVisual(&window->treatAsSingle,
|
||
&window->visAlloced, &fbc);
|
||
if (!window->vis) {
|
||
__glutFatalError(
|
||
"pixel format with necessary capabilities not found.");
|
||
}
|
||
if (!SetPixelFormat(window->hdc,
|
||
ChoosePixelFormat(window->hdc, window->vis),
|
||
window->vis)) {
|
||
__glutFatalError("SetPixelFormat failed during window create.");
|
||
}
|
||
__glutSetupColormap(window->vis, &window->colormap, &window->cmap);
|
||
/* Make sure subwindows get a windowStatus callback. */
|
||
if (parent) {
|
||
PostMessage(parent->win, WM_ACTIVATE, 0, 0);
|
||
}
|
||
window->renderDc = window->hdc;
|
||
#else
|
||
window->win = XCreateWindow(__glutDisplay,
|
||
parent == NULL ? __glutRoot : parent->win,
|
||
x, y, width, height, 0,
|
||
window->vis->depth, InputOutput, window->vis->visual,
|
||
attribMask, &wa);
|
||
#endif
|
||
window->renderWin = window->win;
|
||
#if defined(GLX_VERSION_1_1) && defined(GLX_SGIX_fbconfig)
|
||
if (fbc) {
|
||
window->ctx = __glut_glXCreateContextWithConfigSGIX(__glutDisplay, fbc,
|
||
GLX_RGBA_TYPE_SGIX, None, __glutTryDirect);
|
||
} else
|
||
#endif
|
||
#if defined(__OS2PM__)
|
||
// window->ctx = glXCreateContext(window->hpsBuffer, window->vis,
|
||
// None, __glutTryDirect);
|
||
#else
|
||
window->ctx = glXCreateContext(__glutDisplay, window->vis,
|
||
None, __glutTryDirect);
|
||
#endif
|
||
if (!window->ctx) {
|
||
__glutFatalError(
|
||
"failed to create OpenGL rendering context.");
|
||
}
|
||
window->renderCtx = window->ctx;
|
||
#if !defined(_WIN32) && !defined(__OS2PM__)
|
||
window->isDirect = glXIsDirect(__glutDisplay, window->ctx);
|
||
if (__glutForceDirect) {
|
||
if (!window->isDirect)
|
||
__glutFatalError("direct rendering not possible.");
|
||
}
|
||
#endif
|
||
|
||
window->parent = parent;
|
||
if (parent) {
|
||
window->siblings = parent->children;
|
||
parent->children = window;
|
||
} else {
|
||
window->siblings = NULL;
|
||
}
|
||
window->overlay = NULL;
|
||
window->children = NULL;
|
||
window->display = __glutDefaultDisplay;
|
||
window->reshape = __glutDefaultReshape;
|
||
window->mouse = NULL;
|
||
window->motion = NULL;
|
||
window->passive = NULL;
|
||
window->entry = NULL;
|
||
window->keyboard = NULL;
|
||
window->keyboardUp = NULL;
|
||
window->windowStatus = NULL;
|
||
window->visibility = NULL;
|
||
window->special = NULL;
|
||
window->specialUp = NULL;
|
||
window->buttonBox = NULL;
|
||
window->dials = NULL;
|
||
window->spaceMotion = NULL;
|
||
window->spaceRotate = NULL;
|
||
window->spaceButton = NULL;
|
||
window->tabletMotion = NULL;
|
||
window->tabletButton = NULL;
|
||
#ifdef _WIN32
|
||
window->joystick = NULL;
|
||
window->joyPollInterval = 0;
|
||
#endif
|
||
|
||
#if defined(__OS2PM__)
|
||
window->wm_command = NULL;
|
||
#endif
|
||
|
||
window->tabletPos[0] = -1;
|
||
window->tabletPos[1] = -1;
|
||
#if defined(__OS2PM__)
|
||
if(window->shownState == -1)
|
||
window->shownState = 0;
|
||
window->visState = window->shownState;
|
||
#else
|
||
window->shownState = 0;
|
||
window->visState = -1; /* not VisibilityUnobscured,
|
||
VisibilityPartiallyObscured, or
|
||
VisibilityFullyObscured */
|
||
#endif
|
||
window->entryState = -1; /* not EnterNotify or LeaveNotify */
|
||
|
||
window->desiredConfMask = 0;
|
||
window->buttonUses = 0;
|
||
window->cursor = GLUT_CURSOR_INHERIT;
|
||
|
||
/* Setup window to be mapped when glutMainLoop starts. */
|
||
window->workMask = GLUT_MAP_WORK;
|
||
#ifdef _WIN32
|
||
if (gameMode) {
|
||
/* When mapping a game mode window, just show
|
||
the window. We have already created the game
|
||
mode window with a maximize flag at creation
|
||
time. Doing a ShowWindow(window->win, SW_SHOWNORMAL)
|
||
would be wrong for a game mode window since it
|
||
would unmaximize the window. */
|
||
window->desiredMapState = GameModeState;
|
||
} else {
|
||
window->desiredMapState = NormalState;
|
||
}
|
||
#else
|
||
window->desiredMapState = NormalState;
|
||
#endif
|
||
window->prevWorkWin = __glutWindowWorkList;
|
||
__glutWindowWorkList = window;
|
||
|
||
/* Initially, no menus attached. */
|
||
for (i = 0; i < GLUT_MAX_MENUS; i++) {
|
||
window->menu[i] = 0;
|
||
}
|
||
|
||
/* Add this new window to the window list. */
|
||
__glutWindowList[winnum] = window;
|
||
|
||
/* Make the new window the current window. */
|
||
__glutSetWindow(window);
|
||
|
||
__glutDetermineMesaSwapHackSupport();
|
||
|
||
if (window->treatAsSingle) {
|
||
/* We do this because either the window really is single
|
||
buffered (in which case this is redundant, but harmless,
|
||
because this is the initial single-buffered context
|
||
state); or we are treating a double buffered window as a
|
||
single-buffered window because the system does not appear
|
||
to export any suitable single- buffered visuals (in which
|
||
the following are necessary). */
|
||
glDrawBuffer(GL_FRONT);
|
||
glReadBuffer(GL_FRONT);
|
||
}
|
||
return window;
|
||
}
|
||
|
||
/* CENTRY */
|
||
int GLUTAPIENTRY
|
||
glutCreateWindow(const char *title)
|
||
{
|
||
static int firstWindow = 1;
|
||
GLUTwindow *window;
|
||
#if !defined(_WIN32) && !defined(__OS2__)
|
||
XWMHints *wmHints;
|
||
#endif
|
||
Window win;
|
||
XTextProperty textprop;
|
||
|
||
if (__glutGameModeWindow) {
|
||
__glutFatalError("cannot create windows in game mode.");
|
||
}
|
||
window = __glutCreateWindow(NULL,
|
||
__glutSizeHints.x, __glutSizeHints.y,
|
||
__glutInitWidth, __glutInitHeight,
|
||
/* not game mode */ 0);
|
||
win = window->win;
|
||
/* Setup ICCCM properties. */
|
||
textprop.value = (unsigned char *) title;
|
||
textprop.encoding = XA_STRING;
|
||
textprop.format = 8;
|
||
textprop.nitems = strlen(title);
|
||
#if defined(__OS2__)
|
||
WinSetWindowText(window->frame, (PCSZ)title);
|
||
if (__glutIconic) {
|
||
window->desiredMapState = IconicState;
|
||
}
|
||
#elif defined(_WIN32)
|
||
SetWindowText(win, title);
|
||
if (__glutIconic) {
|
||
window->desiredMapState = IconicState;
|
||
}
|
||
#else
|
||
wmHints = XAllocWMHints();
|
||
wmHints->initial_state =
|
||
__glutIconic ? IconicState : NormalState;
|
||
wmHints->flags = StateHint;
|
||
XSetWMProperties(__glutDisplay, win, &textprop, &textprop,
|
||
/* Only put WM_COMMAND property on first window. */
|
||
firstWindow ? __glutArgv : NULL,
|
||
firstWindow ? __glutArgc : 0,
|
||
&__glutSizeHints, wmHints, NULL);
|
||
XFree(wmHints);
|
||
XSetWMProtocols(__glutDisplay, win, &__glutWMDeleteWindow, 1);
|
||
#endif
|
||
firstWindow = 0;
|
||
return window->num + 1;
|
||
}
|
||
|
||
#ifdef _WIN32
|
||
int GLUTAPIENTRY
|
||
__glutCreateWindowWithExit(const char *title, void (__cdecl *exitfunc)(int))
|
||
{
|
||
__glutExitFunc = exitfunc;
|
||
return glutCreateWindow(title);
|
||
}
|
||
#endif
|
||
|
||
int GLUTAPIENTRY
|
||
glutCreateSubWindow(int win, int x, int y, int width, int height)
|
||
{
|
||
GLUTwindow *window;
|
||
|
||
window = __glutCreateWindow(__glutWindowList[win - 1],
|
||
x, y, width, height, /* not game mode */ 0);
|
||
#if !defined(_WIN32) && !defined(__OS2__)
|
||
{
|
||
GLUTwindow *toplevel;
|
||
|
||
toplevel = __glutToplevelOf(window);
|
||
if (toplevel->cmap != window->cmap) {
|
||
__glutPutOnWorkList(toplevel, GLUT_COLORMAP_WORK);
|
||
}
|
||
}
|
||
#endif
|
||
return window->num + 1;
|
||
}
|
||
/* ENDCENTRY */
|
||
|
||
void
|
||
__glutDestroyWindow(GLUTwindow * window,
|
||
GLUTwindow * initialWindow)
|
||
{
|
||
GLUTwindow **prev, *cur, *parent, *siblings;
|
||
|
||
/* Recursively destroy any children. */
|
||
cur = window->children;
|
||
while (cur) {
|
||
siblings = cur->siblings;
|
||
__glutDestroyWindow(cur, initialWindow);
|
||
cur = siblings;
|
||
}
|
||
/* Remove from parent's children list (only necessary for
|
||
non-initial windows and subwindows!). */
|
||
parent = window->parent;
|
||
if (parent && parent == initialWindow->parent) {
|
||
prev = &parent->children;
|
||
cur = parent->children;
|
||
while (cur) {
|
||
if (cur == window) {
|
||
*prev = cur->siblings;
|
||
break;
|
||
}
|
||
prev = &(cur->siblings);
|
||
cur = cur->siblings;
|
||
}
|
||
}
|
||
/* Unbind if bound to this window. */
|
||
if (window == __glutCurrentWindow) {
|
||
UNMAKE_CURRENT();
|
||
__glutCurrentWindow = NULL;
|
||
}
|
||
/* Begin tearing down window itself. */
|
||
if (window->overlay) {
|
||
__glutFreeOverlayFunc(window->overlay);
|
||
}
|
||
XDestroyWindow(__glutDisplay, window->win);
|
||
glXDestroyContext(__glutDisplay, window->ctx);
|
||
if (window->colormap) {
|
||
/* Only color index windows have colormap data structure. */
|
||
__glutFreeColormap(window->colormap);
|
||
}
|
||
/* NULLing the __glutWindowList helps detect is a window
|
||
instance has been destroyed, given a window number. */
|
||
__glutWindowList[window->num] = NULL;
|
||
|
||
/* Cleanup data structures that might contain window. */
|
||
cleanWindowWorkList(window);
|
||
#if !defined(_WIN32) && !defined(__OS2__)
|
||
cleanStaleWindowList(window);
|
||
#endif
|
||
/* Remove window from the "get window cache" if it is there. */
|
||
if (__glutWindowCache == window)
|
||
__glutWindowCache = NULL;
|
||
|
||
if (window->visAlloced) {
|
||
/* Only free XVisualInfo* gotten from glXChooseVisual. */
|
||
XFree(window->vis);
|
||
}
|
||
|
||
if (window == __glutGameModeWindow) {
|
||
/* Destroying the game mode window should implicitly
|
||
have GLUT leave game mode. */
|
||
__glutCloseDownGameMode();
|
||
}
|
||
|
||
free(window);
|
||
}
|
||
|
||
/* CENTRY */
|
||
void GLUTAPIENTRY
|
||
glutDestroyWindow(int win)
|
||
{
|
||
GLUTwindow *window = __glutWindowList[win - 1];
|
||
|
||
if (__glutMappedMenu && __glutMenuWindow == window) {
|
||
__glutFatalUsage("destroying menu window not allowed while menus in use");
|
||
}
|
||
#if !defined(_WIN32) && !defined(__OS2__)
|
||
/* If not a toplevel window... */
|
||
if (window->parent) {
|
||
/* Destroying subwindows may change colormap requirements;
|
||
recalculate toplevel window's WM_COLORMAP_WINDOWS
|
||
property. */
|
||
__glutPutOnWorkList(__glutToplevelOf(window->parent),
|
||
GLUT_COLORMAP_WORK);
|
||
}
|
||
#endif
|
||
__glutDestroyWindow(window, window);
|
||
XFlush(__glutDisplay);
|
||
}
|
||
/* ENDCENTRY */
|
||
|
||
void
|
||
__glutChangeWindowEventMask(long eventMask, Bool add)
|
||
{
|
||
if (add) {
|
||
/* Add eventMask to window's event mask. */
|
||
if ((__glutCurrentWindow->eventMask & eventMask) !=
|
||
eventMask) {
|
||
__glutCurrentWindow->eventMask |= eventMask;
|
||
__glutPutOnWorkList(__glutCurrentWindow,
|
||
GLUT_EVENT_MASK_WORK);
|
||
}
|
||
} else {
|
||
/* Remove eventMask from window's event mask. */
|
||
if (__glutCurrentWindow->eventMask & eventMask) {
|
||
__glutCurrentWindow->eventMask &= ~eventMask;
|
||
__glutPutOnWorkList(__glutCurrentWindow,
|
||
GLUT_EVENT_MASK_WORK);
|
||
}
|
||
}
|
||
}
|
||
|
||
void GLUTAPIENTRY
|
||
glutDisplayFunc(GLUTdisplayCB displayFunc)
|
||
{
|
||
/* XXX Remove the warning after GLUT 3.0. */
|
||
if (!displayFunc)
|
||
__glutFatalError("NULL display callback not allowed in GLUT 3.0; update your code.");
|
||
__glutCurrentWindow->display = displayFunc;
|
||
}
|
||
|
||
void GLUTAPIENTRY
|
||
glutMouseFunc(GLUTmouseCB mouseFunc)
|
||
{
|
||
if (__glutCurrentWindow->mouse) {
|
||
if (!mouseFunc) {
|
||
/* Previous mouseFunc being disabled. */
|
||
__glutCurrentWindow->buttonUses--;
|
||
__glutChangeWindowEventMask(
|
||
ButtonPressMask | ButtonReleaseMask,
|
||
__glutCurrentWindow->buttonUses > 0);
|
||
}
|
||
} else {
|
||
if (mouseFunc) {
|
||
/* Previously no mouseFunc, new one being installed. */
|
||
__glutCurrentWindow->buttonUses++;
|
||
__glutChangeWindowEventMask(
|
||
ButtonPressMask | ButtonReleaseMask, True);
|
||
}
|
||
}
|
||
__glutCurrentWindow->mouse = mouseFunc;
|
||
}
|
||
|
||
void GLUTAPIENTRY
|
||
glutMotionFunc(GLUTmotionCB motionFunc)
|
||
{
|
||
/* Hack. Some window managers (4Dwm by default) will mask
|
||
motion events if the client is not selecting for button
|
||
press and release events. So we select for press and
|
||
release events too (being careful to use reference
|
||
counting). */
|
||
if (__glutCurrentWindow->motion) {
|
||
if (!motionFunc) {
|
||
/* previous mouseFunc being disabled */
|
||
__glutCurrentWindow->buttonUses--;
|
||
__glutChangeWindowEventMask(
|
||
ButtonPressMask | ButtonReleaseMask,
|
||
__glutCurrentWindow->buttonUses > 0);
|
||
}
|
||
} else {
|
||
if (motionFunc) {
|
||
/* Previously no mouseFunc, new one being installed. */
|
||
__glutCurrentWindow->buttonUses++;
|
||
__glutChangeWindowEventMask(
|
||
ButtonPressMask | ButtonReleaseMask, True);
|
||
}
|
||
}
|
||
/* Real work of selecting for passive mouse motion. */
|
||
__glutChangeWindowEventMask(
|
||
Button1MotionMask | Button2MotionMask | Button3MotionMask,
|
||
motionFunc != NULL);
|
||
__glutCurrentWindow->motion = motionFunc;
|
||
}
|
||
|
||
void GLUTAPIENTRY
|
||
glutPassiveMotionFunc(GLUTpassiveCB passiveMotionFunc)
|
||
{
|
||
__glutChangeWindowEventMask(PointerMotionMask,
|
||
passiveMotionFunc != NULL);
|
||
|
||
/* Passive motion also requires watching enters and leaves so
|
||
that a fake passive motion event can be generated on an
|
||
enter. */
|
||
__glutChangeWindowEventMask(EnterWindowMask | LeaveWindowMask,
|
||
__glutCurrentWindow->entry != NULL || passiveMotionFunc != NULL);
|
||
|
||
__glutCurrentWindow->passive = passiveMotionFunc;
|
||
}
|
||
|
||
void GLUTAPIENTRY
|
||
glutEntryFunc(GLUTentryCB entryFunc)
|
||
{
|
||
__glutChangeWindowEventMask(EnterWindowMask | LeaveWindowMask,
|
||
entryFunc != NULL || __glutCurrentWindow->passive);
|
||
__glutCurrentWindow->entry = entryFunc;
|
||
if (!entryFunc) {
|
||
__glutCurrentWindow->entryState = -1;
|
||
}
|
||
}
|
||
|
||
void GLUTAPIENTRY
|
||
glutWindowStatusFunc(GLUTwindowStatusCB windowStatusFunc)
|
||
{
|
||
__glutChangeWindowEventMask(VisibilityChangeMask,
|
||
windowStatusFunc != NULL);
|
||
__glutCurrentWindow->windowStatus = windowStatusFunc;
|
||
if (!windowStatusFunc) {
|
||
/* Make state invalid. */
|
||
__glutCurrentWindow->visState = -1;
|
||
}
|
||
}
|
||
|
||
static void GLUTCALLBACK
|
||
visibilityHelper(int status)
|
||
{
|
||
if (status == GLUT_HIDDEN || status == GLUT_FULLY_COVERED)
|
||
__glutCurrentWindow->visibility(GLUT_NOT_VISIBLE);
|
||
else
|
||
__glutCurrentWindow->visibility(GLUT_VISIBLE);
|
||
}
|
||
|
||
|
||
void GLUTAPIENTRY
|
||
glutVisibilityFunc(GLUTvisibilityCB visibilityFunc)
|
||
{
|
||
__glutCurrentWindow->visibility = visibilityFunc;
|
||
|
||
if (visibilityFunc)
|
||
{ glutWindowStatusFunc(visibilityHelper);
|
||
#if defined(__OS2PM__)
|
||
if(__glutCurrentWindow->shownState >= 0)
|
||
{ visibilityHelper(__glutCurrentWindow->shownState);
|
||
}
|
||
#endif
|
||
}
|
||
else
|
||
glutWindowStatusFunc(NULL);
|
||
}
|
||
|
||
void GLUTAPIENTRY
|
||
glutReshapeFunc(GLUTreshapeCB reshapeFunc)
|
||
{
|
||
if (reshapeFunc) {
|
||
__glutCurrentWindow->reshape = reshapeFunc;
|
||
} else {
|
||
__glutCurrentWindow->reshape = __glutDefaultReshape;
|
||
}
|
||
}
|
||
|