Windows NT 4.0 source code leak
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.
 
 
 
 
 
 

508 lines
12 KiB

/************************************************************************/
/* */
/* Nano toolkit for OpenGL for the X Window System */
/* */
/************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/keysym.h>
#include <GL/glx.h>
#include "ctk.h"
#if defined(__cplusplus) || defined(c_plusplus)
#define class c_class
#endif
/******************************************************************************/
static Display *display = 0;
static int screen = 0;
static XVisualInfo *visual = 0;
static Colormap colorMap;
static Window window = 0;
static GLXContext context = 0;
static int windType;
static TK_EventRec event;
/******************************************************************************/
static long DisplayInit(void)
{
int erb, evb;
if (!display) {
display = XOpenDisplay(0);
if (!display) {
fprintf(stderr, "Can't connect to display!\n");
return 0;
}
if (!glXQueryExtension(display, &erb, &evb)) {
fprintf(stderr, "No glx extension!\n");
return 0;
}
screen = DefaultScreen(display);
}
return 1;
}
static XVisualInfo *FindVisual(long type)
{
long list[32];
int i;
i = 0;
list[i++] = GLX_LEVEL;
list[i++] = 0;
if (TK_WIND_IS_DB(type)) {
list[i++] = GLX_DOUBLEBUFFER;
}
if (TK_WIND_IS_RGB(type)) {
list[i++] = GLX_RGBA;
list[i++] = GLX_RED_SIZE;
list[i++] = 1;
list[i++] = GLX_GREEN_SIZE;
list[i++] = 1;
list[i++] = GLX_BLUE_SIZE;
list[i++] = 1;
/*
list[i++] = GLX_ALPHA_SIZE;
list[i++] = 1;
list[i++] = GLX_ACCUM_RED_SIZE;
list[i++] = 1;
list[i++] = GLX_ACCUM_GREEN_SIZE;
list[i++] = 1;
list[i++] = GLX_ACCUM_BLUE_SIZE;
list[i++] = 1;
list[i++] = GLX_ACCUM_ALPHA_SIZE;
list[i++] = 1;
*/
} else {
list[i++] = GLX_BUFFER_SIZE;
list[i++] = 1;
}
list[i++] = GLX_DEPTH_SIZE;
list[i++] = 1;
list[i++] = GLX_STENCIL_SIZE;
list[i++] = 1;
list[i] = (int)None;
return glXChooseVisual(display, screen, (int *)list);
}
static long MakeVisualType(XVisualInfo *vi)
{
int rgba, doubleBuffer, stencilSize, depthSize;
int accumRed, accumGreen, accumBlue, auxBuffers;
long mask;
mask = 0;
glXGetConfig(display, vi, GLX_RGBA, &rgba);
if (rgba) {
mask |= TK_WIND_RGB;
} else {
mask |= TK_WIND_CI;
}
glXGetConfig(display, vi, GLX_DOUBLEBUFFER, &doubleBuffer);
if (doubleBuffer) {
mask |= TK_WIND_DB;
} else {
mask |= TK_WIND_SB;
}
glXGetConfig(display, vi, GLX_ACCUM_RED_SIZE, &accumRed);
glXGetConfig(display, vi, GLX_ACCUM_GREEN_SIZE, &accumGreen);
glXGetConfig(display, vi, GLX_ACCUM_BLUE_SIZE, &accumBlue);
if ((accumRed > 0) && (accumGreen > 0) && (accumBlue > 0)) {
mask |= TK_WIND_ACCUM;
}
glXGetConfig(display, vi, GLX_STENCIL_SIZE, &stencilSize);
if (stencilSize > 0) {
mask |= TK_WIND_STENCIL;
}
glXGetConfig(display, vi, GLX_DEPTH_SIZE, &depthSize);
if (depthSize > 0) {
mask |= TK_WIND_Z;
}
return mask;
}
static Bool WaitForMapNotify(Display *d, XEvent *e, char *arg)
{
if (e->type == MapNotify && e->xmap.window == window) {
return GL_TRUE;
}
return GL_FALSE;
}
long tkNewWindow(TK_WindowRec *wind)
{
XSetWindowAttributes wa;
XTextProperty tp;
XSizeHints sh;
XEvent e;
char *ptr;
if (!DisplayInit()) {
return 0;
}
if (wind->type == TK_WIND_REQUEST) {
int useGL;
visual = FindVisual(wind->info);
if (visual == 0) {
return 0;
}
glXGetConfig(display, visual, GLX_USE_GL, &useGL);
if (!useGL) {
return 0;
}
} else {
XVisualInfo temp;
int useGL, count;
temp.visualid = wind->info;
visual = XGetVisualInfo(display, VisualIDMask, &temp, &count);
if (visual == 0) {
return 0;
}
glXGetConfig(display, visual, GLX_USE_GL, &useGL);
if (!useGL) {
return 0;
}
}
wind->type = TK_WIND_REQUEST;
wind->info = MakeVisualType(visual);
windType = wind->info;
context = glXCreateContext(display, visual, None,
(wind->render==TK_WIND_DIRECT)?GL_TRUE:GL_FALSE);
if (!context) {
fprintf(stderr, "Can't create a context!\n");
}
if (glXIsDirect(display, context)) {
wind->render = TK_WIND_DIRECT;
} else {
wind->render = TK_WIND_INDIRECT;
}
colorMap = XCreateColormap(display, RootWindow(display, screen),
visual->visual, AllocNone);
wa.colormap = colorMap;
wa.background_pixmap = None;
wa.border_pixel = 0;
wa.event_mask = StructureNotifyMask | ExposureMask;
window = XCreateWindow(display, RootWindow(display, screen), (int)wind->x,
(int)wind->y, (unsigned int)wind->width,
(unsigned int)wind->height, 0, visual->depth,
InputOutput, visual->visual,
CWBackPixmap|CWBorderPixel|CWEventMask|CWColormap,
&wa);
/*
** Set up window hints.
*/
ptr = &wind->name[0];
XStringListToTextProperty(&ptr, 1, &tp);
sh.flags = USPosition | USSize;
XSetWMProperties(display, window, &tp, &tp, 0, 0, &sh, 0, 0);
/*
** Map window and then wait for the window system to get around to it.
*/
XMapWindow(display, window);
XIfEvent(display, &e, WaitForMapNotify, 0);
XSetWMColormapWindows(display, window, &window, 1);
if (!glXMakeCurrent(display, window, context)) {
return 0;
}
XFlush(display);
return 1;
}
void tkCloseWindow(void)
{
glFinish();
XDestroyWindow(display, window);
glXDestroyContext(display, context);
XFreeColormap(display, colorMap);
XFree((char *)visual);
}
void tkSwapBuffers(void)
{
glXSwapBuffers(display, window);
}
void tkQuit(void)
{
exit(0);
}
static void GetNextEvent(void)
{
XEvent current, ahead;
event.event = 0;
event.data[0] = 0;
event.data[1] = 0;
event.data[2] = 0;
event.data[3] = 0;
XNextEvent(display, &current);
switch (current.type) {
case MappingNotify:
XRefreshKeyboardMapping((XMappingEvent *)&current);
break;
case Expose:
while (XEventsQueued(current.xexpose.display, QueuedAfterReading) > 0) {
XPeekEvent(current.xexpose.display, &ahead);
if (ahead.type != Expose) {
break;
}
if (ahead.xexpose.window != current.xexpose.window) {
break;
}
XNextEvent(display, &current);
}
if (current.xexpose.count == 0) {
event.event = TK_EVENT_EXPOSE;
event.data[TK_WINDOWX] = current.xexpose.width;
event.data[TK_WINDOWY] = current.xexpose.height;
}
break;
}
}
void tkExec(long (*Func)(TK_EventRec *ptr))
{
while (1) {
if (XPending(display)) {
GetNextEvent();
if (event.event == TK_EVENT_EXPOSE) {
if ((*Func)(&event) == 0) {
break;
}
}
}
}
}
static void ScreenImage(TK_ScreenImageRec *ptr)
{
XImage *image;
float *destPtr, *tmpBuf;
unsigned long *srcPtr, c, mask;
long rShift = 0, gShift = 0, bShift = 0;
GLint rBits, gBits, bBits;
float rFactor, gFactor, bFactor;
long indices_per_word, words_per_line, lines;
int i, j;
float *tmpPtr;
glXWaitGL();
image = XGetImage(display, window, (int)ptr->x, (int)ptr->y,
(unsigned int)ptr->width, (unsigned int)ptr->height, ~0, ZPixmap);
srcPtr = (unsigned long *)image->data;
destPtr = ptr->data;
mask = (1 << image->depth) - 1;
indices_per_word = 32 / image->bits_per_pixel;
words_per_line = image->bytes_per_line / 4;
lines = ptr->width * ptr->height / (words_per_line * indices_per_word);
if (ptr->colorMode == TK_WIND_RGB) {
mask = image->red_mask;
while ((mask & 0x1) == 0) {
rShift++;
mask = mask >> 1;
}
mask = image->green_mask;
while ((mask & 0x1) == 0) {
gShift++;
mask = mask >> 1;
}
mask = image->blue_mask;
while ((mask & 0x1) == 0) {
bShift++;
mask = mask >> 1;
}
mask = (1 << image->depth) - 1;
glGetIntegerv(GL_RED_BITS, &rBits);
glGetIntegerv(GL_GREEN_BITS, &gBits);
glGetIntegerv(GL_BLUE_BITS, &bBits);
rFactor = (1 << rBits) - 1;
gFactor = (1 << gBits) - 1;
bFactor = (1 << bBits) - 1;
tmpBuf = (float *)malloc(ptr->width*ptr->height*3*sizeof(float));
tmpPtr = tmpBuf;
for ( j = 0; j < ptr->height; j++) {
for (i = 0; i < ptr->width; i++) {
c = XGetPixel(image, i, j);
*tmpPtr++ = ((float)((c & image->red_mask) >> rShift)) / rFactor;
*tmpPtr++ = ((float)((c & image->green_mask) >> gShift)) / gFactor;
*tmpPtr++ = ((float)((c & image->blue_mask) >> bShift)) / bFactor;
}
}
/*
** X reads top to bottom, so reverse the line ordering to match
** GL's bottom to top ordering.
*/
tmpPtr = tmpBuf;
for (i = ptr->height - 1; i >= 0; i--) {
for (j = 0; j < ptr->width * 3; j++) {
destPtr[i*ptr->width*3 + j] = *tmpPtr++;
}
}
free(tmpBuf);
} else {
for ( j = 0; j < ptr->height; j++) {
for (i = 0; i < ptr->width; i++) {
destPtr[(ptr->height-j-1)*ptr->width + i] = (float) XGetPixel(image, i, j);
}
}
}
XDestroyImage(image);
}
static void GetVisuals(TK_VisualIDsRec *ptr)
{
XVisualInfo vInfoTmp, *vInfoList;
int total, useGL, i;
ptr->count = 0;
if (!DisplayInit()) {
return;
}
vInfoTmp.screen = screen;
vInfoList = XGetVisualInfo(display, VisualScreenMask, &vInfoTmp, &total);
for (i = 0; i < total; i++) {
glXGetConfig(display, &vInfoList[i], GLX_USE_GL, &useGL);
if (useGL) {
ptr->IDs[ptr->count++] = vInfoList[i].visualid;
}
}
XFree((char *)vInfoList);
}
void tkGet(long item, void *data)
{
if (item == TK_SCREENIMAGE) {
ScreenImage((TK_ScreenImageRec *)data);
} else if (item == TK_VISUALIDS) {
GetVisuals((TK_VisualIDsRec *)data);
}
}
long tkLoadFont(char *fontName, long *width, long *height)
{
XFontStruct *fontInfo;
Font id;
int first, last;
GLuint base;
fontInfo = XLoadQueryFont(display, fontName);
if (fontInfo == NULL) {
return 0;
}
id = fontInfo->fid;
first = (int)fontInfo->min_char_or_byte2;
last = (int)fontInfo->max_char_or_byte2;
base = glGenLists(last+1);
if (base == 0) {
return 0;
}
glXUseXFont(id, first, last-first+1, base+first);
*height = fontInfo->ascent + fontInfo->descent;
*width = fontInfo->max_bounds.width;
return base;
}
long tkDrawFont(char *fontName, long x, long y, char *string, long len)
{
static char pattern1[] = "-adobe-courier-bold-o-normal--14-*-*-*-*-*-*-*";
static char pattern2[] = "-*-*-*-*-*-*-14-*-*-*-*-*-*-*";
static char size[] = "456781";
XFontStruct *fontInfo;
GC gc;
XGCValues values;
XColor exact, green;
char **fontList;
unsigned long mask;
long count, i;
glXWaitGL();
/*
** Look for a common font first, then look for any font in
** a range of point sizes from 11 to 18.
*/
fontList = XListFonts(display, pattern1, 1, (int *)&count);
if (count == 0) {
for (i = 0; i < 6; i++) {
pattern2[14] = size[i];
fontList = XListFonts(display, pattern2, 1, (int *)&count);
if (count > 0) {
break;
}
}
}
if (count == 0) {
return 0;
}
strcpy(fontName, fontList[0]);
fontInfo = XLoadQueryFont(display, fontList[0]);
if (fontInfo == NULL) {
return 0;
}
mask = GCForeground | GCFont;
values.font = fontInfo->fid;
if (TK_WIND_IS_RGB(windType)) {
XAllocNamedColor(display, colorMap, "Green", &exact, &green);
values.foreground = green.pixel;
} else {
values.foreground = 2; /* 2 = GREEN. */
}
gc = XCreateGC(display, window, mask, &values);
XDrawString(display, window, gc, (int)x, (int)y, string, (int)len);
XFreeFontNames(fontList);
glXWaitX();
return 1;
}