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

5 years ago
  1. /************************************************************************/
  2. /* */
  3. /* Nano toolkit for OpenGL for the X Window System */
  4. /* */
  5. /************************************************************************/
  6. #include <stdio.h>
  7. #include <stdlib.h>
  8. #include <string.h>
  9. #include <X11/Xlib.h>
  10. #include <X11/Xutil.h>
  11. #include <X11/keysym.h>
  12. #include <GL/glx.h>
  13. #include "ctk.h"
  14. #if defined(__cplusplus) || defined(c_plusplus)
  15. #define class c_class
  16. #endif
  17. /******************************************************************************/
  18. static Display *display = 0;
  19. static int screen = 0;
  20. static XVisualInfo *visual = 0;
  21. static Colormap colorMap;
  22. static Window window = 0;
  23. static GLXContext context = 0;
  24. static int windType;
  25. static TK_EventRec event;
  26. /******************************************************************************/
  27. static long DisplayInit(void)
  28. {
  29. int erb, evb;
  30. if (!display) {
  31. display = XOpenDisplay(0);
  32. if (!display) {
  33. fprintf(stderr, "Can't connect to display!\n");
  34. return 0;
  35. }
  36. if (!glXQueryExtension(display, &erb, &evb)) {
  37. fprintf(stderr, "No glx extension!\n");
  38. return 0;
  39. }
  40. screen = DefaultScreen(display);
  41. }
  42. return 1;
  43. }
  44. static XVisualInfo *FindVisual(long type)
  45. {
  46. long list[32];
  47. int i;
  48. i = 0;
  49. list[i++] = GLX_LEVEL;
  50. list[i++] = 0;
  51. if (TK_WIND_IS_DB(type)) {
  52. list[i++] = GLX_DOUBLEBUFFER;
  53. }
  54. if (TK_WIND_IS_RGB(type)) {
  55. list[i++] = GLX_RGBA;
  56. list[i++] = GLX_RED_SIZE;
  57. list[i++] = 1;
  58. list[i++] = GLX_GREEN_SIZE;
  59. list[i++] = 1;
  60. list[i++] = GLX_BLUE_SIZE;
  61. list[i++] = 1;
  62. /*
  63. list[i++] = GLX_ALPHA_SIZE;
  64. list[i++] = 1;
  65. list[i++] = GLX_ACCUM_RED_SIZE;
  66. list[i++] = 1;
  67. list[i++] = GLX_ACCUM_GREEN_SIZE;
  68. list[i++] = 1;
  69. list[i++] = GLX_ACCUM_BLUE_SIZE;
  70. list[i++] = 1;
  71. list[i++] = GLX_ACCUM_ALPHA_SIZE;
  72. list[i++] = 1;
  73. */
  74. } else {
  75. list[i++] = GLX_BUFFER_SIZE;
  76. list[i++] = 1;
  77. }
  78. list[i++] = GLX_DEPTH_SIZE;
  79. list[i++] = 1;
  80. list[i++] = GLX_STENCIL_SIZE;
  81. list[i++] = 1;
  82. list[i] = (int)None;
  83. return glXChooseVisual(display, screen, (int *)list);
  84. }
  85. static long MakeVisualType(XVisualInfo *vi)
  86. {
  87. int rgba, doubleBuffer, stencilSize, depthSize;
  88. int accumRed, accumGreen, accumBlue, auxBuffers;
  89. long mask;
  90. mask = 0;
  91. glXGetConfig(display, vi, GLX_RGBA, &rgba);
  92. if (rgba) {
  93. mask |= TK_WIND_RGB;
  94. } else {
  95. mask |= TK_WIND_CI;
  96. }
  97. glXGetConfig(display, vi, GLX_DOUBLEBUFFER, &doubleBuffer);
  98. if (doubleBuffer) {
  99. mask |= TK_WIND_DB;
  100. } else {
  101. mask |= TK_WIND_SB;
  102. }
  103. glXGetConfig(display, vi, GLX_ACCUM_RED_SIZE, &accumRed);
  104. glXGetConfig(display, vi, GLX_ACCUM_GREEN_SIZE, &accumGreen);
  105. glXGetConfig(display, vi, GLX_ACCUM_BLUE_SIZE, &accumBlue);
  106. if ((accumRed > 0) && (accumGreen > 0) && (accumBlue > 0)) {
  107. mask |= TK_WIND_ACCUM;
  108. }
  109. glXGetConfig(display, vi, GLX_STENCIL_SIZE, &stencilSize);
  110. if (stencilSize > 0) {
  111. mask |= TK_WIND_STENCIL;
  112. }
  113. glXGetConfig(display, vi, GLX_DEPTH_SIZE, &depthSize);
  114. if (depthSize > 0) {
  115. mask |= TK_WIND_Z;
  116. }
  117. return mask;
  118. }
  119. static Bool WaitForMapNotify(Display *d, XEvent *e, char *arg)
  120. {
  121. if (e->type == MapNotify && e->xmap.window == window) {
  122. return GL_TRUE;
  123. }
  124. return GL_FALSE;
  125. }
  126. long tkNewWindow(TK_WindowRec *wind)
  127. {
  128. XSetWindowAttributes wa;
  129. XTextProperty tp;
  130. XSizeHints sh;
  131. XEvent e;
  132. char *ptr;
  133. if (!DisplayInit()) {
  134. return 0;
  135. }
  136. if (wind->type == TK_WIND_REQUEST) {
  137. int useGL;
  138. visual = FindVisual(wind->info);
  139. if (visual == 0) {
  140. return 0;
  141. }
  142. glXGetConfig(display, visual, GLX_USE_GL, &useGL);
  143. if (!useGL) {
  144. return 0;
  145. }
  146. } else {
  147. XVisualInfo temp;
  148. int useGL, count;
  149. temp.visualid = wind->info;
  150. visual = XGetVisualInfo(display, VisualIDMask, &temp, &count);
  151. if (visual == 0) {
  152. return 0;
  153. }
  154. glXGetConfig(display, visual, GLX_USE_GL, &useGL);
  155. if (!useGL) {
  156. return 0;
  157. }
  158. }
  159. wind->type = TK_WIND_REQUEST;
  160. wind->info = MakeVisualType(visual);
  161. windType = wind->info;
  162. context = glXCreateContext(display, visual, None,
  163. (wind->render==TK_WIND_DIRECT)?GL_TRUE:GL_FALSE);
  164. if (!context) {
  165. fprintf(stderr, "Can't create a context!\n");
  166. }
  167. if (glXIsDirect(display, context)) {
  168. wind->render = TK_WIND_DIRECT;
  169. } else {
  170. wind->render = TK_WIND_INDIRECT;
  171. }
  172. colorMap = XCreateColormap(display, RootWindow(display, screen),
  173. visual->visual, AllocNone);
  174. wa.colormap = colorMap;
  175. wa.background_pixmap = None;
  176. wa.border_pixel = 0;
  177. wa.event_mask = StructureNotifyMask | ExposureMask;
  178. window = XCreateWindow(display, RootWindow(display, screen), (int)wind->x,
  179. (int)wind->y, (unsigned int)wind->width,
  180. (unsigned int)wind->height, 0, visual->depth,
  181. InputOutput, visual->visual,
  182. CWBackPixmap|CWBorderPixel|CWEventMask|CWColormap,
  183. &wa);
  184. /*
  185. ** Set up window hints.
  186. */
  187. ptr = &wind->name[0];
  188. XStringListToTextProperty(&ptr, 1, &tp);
  189. sh.flags = USPosition | USSize;
  190. XSetWMProperties(display, window, &tp, &tp, 0, 0, &sh, 0, 0);
  191. /*
  192. ** Map window and then wait for the window system to get around to it.
  193. */
  194. XMapWindow(display, window);
  195. XIfEvent(display, &e, WaitForMapNotify, 0);
  196. XSetWMColormapWindows(display, window, &window, 1);
  197. if (!glXMakeCurrent(display, window, context)) {
  198. return 0;
  199. }
  200. XFlush(display);
  201. return 1;
  202. }
  203. void tkCloseWindow(void)
  204. {
  205. glFinish();
  206. XDestroyWindow(display, window);
  207. glXDestroyContext(display, context);
  208. XFreeColormap(display, colorMap);
  209. XFree((char *)visual);
  210. }
  211. void tkSwapBuffers(void)
  212. {
  213. glXSwapBuffers(display, window);
  214. }
  215. void tkQuit(void)
  216. {
  217. exit(0);
  218. }
  219. static void GetNextEvent(void)
  220. {
  221. XEvent current, ahead;
  222. event.event = 0;
  223. event.data[0] = 0;
  224. event.data[1] = 0;
  225. event.data[2] = 0;
  226. event.data[3] = 0;
  227. XNextEvent(display, &current);
  228. switch (current.type) {
  229. case MappingNotify:
  230. XRefreshKeyboardMapping((XMappingEvent *)&current);
  231. break;
  232. case Expose:
  233. while (XEventsQueued(current.xexpose.display, QueuedAfterReading) > 0) {
  234. XPeekEvent(current.xexpose.display, &ahead);
  235. if (ahead.type != Expose) {
  236. break;
  237. }
  238. if (ahead.xexpose.window != current.xexpose.window) {
  239. break;
  240. }
  241. XNextEvent(display, &current);
  242. }
  243. if (current.xexpose.count == 0) {
  244. event.event = TK_EVENT_EXPOSE;
  245. event.data[TK_WINDOWX] = current.xexpose.width;
  246. event.data[TK_WINDOWY] = current.xexpose.height;
  247. }
  248. break;
  249. }
  250. }
  251. void tkExec(long (*Func)(TK_EventRec *ptr))
  252. {
  253. while (1) {
  254. if (XPending(display)) {
  255. GetNextEvent();
  256. if (event.event == TK_EVENT_EXPOSE) {
  257. if ((*Func)(&event) == 0) {
  258. break;
  259. }
  260. }
  261. }
  262. }
  263. }
  264. static void ScreenImage(TK_ScreenImageRec *ptr)
  265. {
  266. XImage *image;
  267. float *destPtr, *tmpBuf;
  268. unsigned long *srcPtr, c, mask;
  269. long rShift = 0, gShift = 0, bShift = 0;
  270. GLint rBits, gBits, bBits;
  271. float rFactor, gFactor, bFactor;
  272. long indices_per_word, words_per_line, lines;
  273. int i, j;
  274. float *tmpPtr;
  275. glXWaitGL();
  276. image = XGetImage(display, window, (int)ptr->x, (int)ptr->y,
  277. (unsigned int)ptr->width, (unsigned int)ptr->height, ~0, ZPixmap);
  278. srcPtr = (unsigned long *)image->data;
  279. destPtr = ptr->data;
  280. mask = (1 << image->depth) - 1;
  281. indices_per_word = 32 / image->bits_per_pixel;
  282. words_per_line = image->bytes_per_line / 4;
  283. lines = ptr->width * ptr->height / (words_per_line * indices_per_word);
  284. if (ptr->colorMode == TK_WIND_RGB) {
  285. mask = image->red_mask;
  286. while ((mask & 0x1) == 0) {
  287. rShift++;
  288. mask = mask >> 1;
  289. }
  290. mask = image->green_mask;
  291. while ((mask & 0x1) == 0) {
  292. gShift++;
  293. mask = mask >> 1;
  294. }
  295. mask = image->blue_mask;
  296. while ((mask & 0x1) == 0) {
  297. bShift++;
  298. mask = mask >> 1;
  299. }
  300. mask = (1 << image->depth) - 1;
  301. glGetIntegerv(GL_RED_BITS, &rBits);
  302. glGetIntegerv(GL_GREEN_BITS, &gBits);
  303. glGetIntegerv(GL_BLUE_BITS, &bBits);
  304. rFactor = (1 << rBits) - 1;
  305. gFactor = (1 << gBits) - 1;
  306. bFactor = (1 << bBits) - 1;
  307. tmpBuf = (float *)malloc(ptr->width*ptr->height*3*sizeof(float));
  308. tmpPtr = tmpBuf;
  309. for ( j = 0; j < ptr->height; j++) {
  310. for (i = 0; i < ptr->width; i++) {
  311. c = XGetPixel(image, i, j);
  312. *tmpPtr++ = ((float)((c & image->red_mask) >> rShift)) / rFactor;
  313. *tmpPtr++ = ((float)((c & image->green_mask) >> gShift)) / gFactor;
  314. *tmpPtr++ = ((float)((c & image->blue_mask) >> bShift)) / bFactor;
  315. }
  316. }
  317. /*
  318. ** X reads top to bottom, so reverse the line ordering to match
  319. ** GL's bottom to top ordering.
  320. */
  321. tmpPtr = tmpBuf;
  322. for (i = ptr->height - 1; i >= 0; i--) {
  323. for (j = 0; j < ptr->width * 3; j++) {
  324. destPtr[i*ptr->width*3 + j] = *tmpPtr++;
  325. }
  326. }
  327. free(tmpBuf);
  328. } else {
  329. for ( j = 0; j < ptr->height; j++) {
  330. for (i = 0; i < ptr->width; i++) {
  331. destPtr[(ptr->height-j-1)*ptr->width + i] = (float) XGetPixel(image, i, j);
  332. }
  333. }
  334. }
  335. XDestroyImage(image);
  336. }
  337. static void GetVisuals(TK_VisualIDsRec *ptr)
  338. {
  339. XVisualInfo vInfoTmp, *vInfoList;
  340. int total, useGL, i;
  341. ptr->count = 0;
  342. if (!DisplayInit()) {
  343. return;
  344. }
  345. vInfoTmp.screen = screen;
  346. vInfoList = XGetVisualInfo(display, VisualScreenMask, &vInfoTmp, &total);
  347. for (i = 0; i < total; i++) {
  348. glXGetConfig(display, &vInfoList[i], GLX_USE_GL, &useGL);
  349. if (useGL) {
  350. ptr->IDs[ptr->count++] = vInfoList[i].visualid;
  351. }
  352. }
  353. XFree((char *)vInfoList);
  354. }
  355. void tkGet(long item, void *data)
  356. {
  357. if (item == TK_SCREENIMAGE) {
  358. ScreenImage((TK_ScreenImageRec *)data);
  359. } else if (item == TK_VISUALIDS) {
  360. GetVisuals((TK_VisualIDsRec *)data);
  361. }
  362. }
  363. long tkLoadFont(char *fontName, long *width, long *height)
  364. {
  365. XFontStruct *fontInfo;
  366. Font id;
  367. int first, last;
  368. GLuint base;
  369. fontInfo = XLoadQueryFont(display, fontName);
  370. if (fontInfo == NULL) {
  371. return 0;
  372. }
  373. id = fontInfo->fid;
  374. first = (int)fontInfo->min_char_or_byte2;
  375. last = (int)fontInfo->max_char_or_byte2;
  376. base = glGenLists(last+1);
  377. if (base == 0) {
  378. return 0;
  379. }
  380. glXUseXFont(id, first, last-first+1, base+first);
  381. *height = fontInfo->ascent + fontInfo->descent;
  382. *width = fontInfo->max_bounds.width;
  383. return base;
  384. }
  385. long tkDrawFont(char *fontName, long x, long y, char *string, long len)
  386. {
  387. static char pattern1[] = "-adobe-courier-bold-o-normal--14-*-*-*-*-*-*-*";
  388. static char pattern2[] = "-*-*-*-*-*-*-14-*-*-*-*-*-*-*";
  389. static char size[] = "456781";
  390. XFontStruct *fontInfo;
  391. GC gc;
  392. XGCValues values;
  393. XColor exact, green;
  394. char **fontList;
  395. unsigned long mask;
  396. long count, i;
  397. glXWaitGL();
  398. /*
  399. ** Look for a common font first, then look for any font in
  400. ** a range of point sizes from 11 to 18.
  401. */
  402. fontList = XListFonts(display, pattern1, 1, (int *)&count);
  403. if (count == 0) {
  404. for (i = 0; i < 6; i++) {
  405. pattern2[14] = size[i];
  406. fontList = XListFonts(display, pattern2, 1, (int *)&count);
  407. if (count > 0) {
  408. break;
  409. }
  410. }
  411. }
  412. if (count == 0) {
  413. return 0;
  414. }
  415. strcpy(fontName, fontList[0]);
  416. fontInfo = XLoadQueryFont(display, fontList[0]);
  417. if (fontInfo == NULL) {
  418. return 0;
  419. }
  420. mask = GCForeground | GCFont;
  421. values.font = fontInfo->fid;
  422. if (TK_WIND_IS_RGB(windType)) {
  423. XAllocNamedColor(display, colorMap, "Green", &exact, &green);
  424. values.foreground = green.pixel;
  425. } else {
  426. values.foreground = 2; /* 2 = GREEN. */
  427. }
  428. gc = XCreateGC(display, window, mask, &values);
  429. XDrawString(display, window, gc, (int)x, (int)y, string, (int)len);
  430. XFreeFontNames(fontList);
  431. glXWaitX();
  432. return 1;
  433. }