Ви не можете вибрати більше 25 тем Теми мають розпочинатися з літери або цифри, можуть містити дефіси (-) і не повинні перевищувати 35 символів.

18 роки тому
18 роки тому
18 роки тому
18 роки тому
18 роки тому
18 роки тому
18 роки тому
18 роки тому
18 роки тому
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632
  1. /*
  2. * libcaca Colour ASCII-Art library
  3. * Copyright (c) 2002-2006 Sam Hocevar <sam@zoy.org>
  4. * All Rights Reserved
  5. *
  6. * $Id$
  7. *
  8. * This library is free software; you can redistribute it and/or
  9. * modify it under the terms of the Do What The Fuck You Want To
  10. * Public License, Version 2, as published by Sam Hocevar. See
  11. * http://sam.zoy.org/wtfpl/COPYING for more details.
  12. */
  13. /*
  14. * This file contains the libcaca OpenGL input and output driver
  15. */
  16. #include "config.h"
  17. #include "common.h"
  18. #if defined(USE_GL)
  19. #ifdef HAVE_OPENGL_GL_H
  20. # include <OpenGL/gl.h>
  21. # include <GLUT/glut.h>
  22. #else
  23. # include <GL/gl.h>
  24. # include <GL/glut.h>
  25. # include <GL/freeglut_ext.h>
  26. #endif
  27. #include <string.h>
  28. #include <stdlib.h>
  29. #include <stdio.h>
  30. #include "caca.h"
  31. #include "caca_internals.h"
  32. #include "cucul.h"
  33. #include "cucul_internals.h"
  34. /*
  35. * Global variables
  36. */
  37. static caca_display_t *gl_d; /* FIXME: we ought to get rid of this */
  38. /*
  39. * Local functions
  40. */
  41. static void gl_handle_keyboard(unsigned char, int, int);
  42. static void gl_handle_special_key(int, int, int);
  43. static void gl_handle_reshape(int, int);
  44. static void gl_handle_mouse(int, int, int, int);
  45. static void gl_handle_mouse_motion(int, int);
  46. #ifdef HAVE_GLUTCLOSEFUNC
  47. static void gl_handle_close(void);
  48. #endif
  49. static void _display(void);
  50. struct driver_private
  51. {
  52. int window;
  53. unsigned int width, height;
  54. unsigned int new_width, new_height;
  55. float font_width, font_height;
  56. float incx, incy;
  57. int id[(128 - 32)];
  58. int id_uni[8]; /* Hack, FIXME */
  59. unsigned char close;
  60. unsigned char bit;
  61. unsigned char mouse_changed, mouse_clicked;
  62. unsigned int mouse_x, mouse_y;
  63. unsigned int mouse_button, mouse_state;
  64. unsigned char key;
  65. int special_key;
  66. float sw, sh;
  67. };
  68. static int gl_init_graphics(caca_display_t *dp)
  69. {
  70. char *empty_texture;
  71. char const *geometry;
  72. char *argv[2] = { "", NULL };
  73. unsigned int width = 0, height = 0;
  74. int argc = 1;
  75. int i;
  76. dp->drv.p = malloc(sizeof(struct driver_private));
  77. gl_d = dp;
  78. #if defined(HAVE_GETENV)
  79. geometry = getenv("CACA_GEOMETRY");
  80. if(geometry && *geometry)
  81. sscanf(geometry, "%ux%u", &width, &height);
  82. #endif
  83. if(width && height)
  84. _cucul_set_canvas_size(dp->cv, width, height);
  85. dp->drv.p->font_width = 9;
  86. dp->drv.p->font_height = 15;
  87. dp->drv.p->width = dp->cv->width * dp->drv.p->font_width;
  88. dp->drv.p->height = dp->cv->height * dp->drv.p->font_height;
  89. #ifdef HAVE_GLUTCLOSEFUNC
  90. dp->drv.p->close = 0;
  91. #endif
  92. dp->drv.p->bit = 0;
  93. dp->drv.p->mouse_changed = dp->drv.p->mouse_clicked = 0;
  94. dp->drv.p->mouse_button = dp->drv.p->mouse_state = 0;
  95. dp->drv.p->key = 0;
  96. dp->drv.p->special_key = 0;
  97. dp->drv.p->sw = 9.0f / 16.0f;
  98. dp->drv.p->sh = 15.0f / 16.0f;
  99. glutInit(&argc, argv);
  100. glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE);
  101. glutInitWindowSize(dp->drv.p->width, dp->drv.p->height);
  102. dp->drv.p->window = glutCreateWindow("caca for GL");
  103. gluOrtho2D(0, dp->drv.p->width, dp->drv.p->height, 0);
  104. glDisable(GL_CULL_FACE);
  105. glDisable(GL_DEPTH_TEST);
  106. glutKeyboardFunc(gl_handle_keyboard);
  107. glutSpecialFunc(gl_handle_special_key);
  108. glutReshapeFunc(gl_handle_reshape);
  109. glutDisplayFunc(_display);
  110. #ifdef HAVE_GLUTCLOSEFUNC
  111. glutCloseFunc(gl_handle_close);
  112. #endif
  113. glutMouseFunc(gl_handle_mouse);
  114. glutMotionFunc(gl_handle_mouse_motion);
  115. glutPassiveMotionFunc(gl_handle_mouse_motion);
  116. glLoadIdentity();
  117. glMatrixMode(GL_PROJECTION);
  118. glPushMatrix();
  119. glLoadIdentity();
  120. gluOrtho2D(0, dp->drv.p->width, dp->drv.p->height, 0);
  121. glMatrixMode(GL_MODELVIEW);
  122. glClear(GL_COLOR_BUFFER_BIT);
  123. empty_texture = malloc(16 * 16 * 4);
  124. if(empty_texture == NULL)
  125. return -1;
  126. memset(empty_texture, 0xff, 16 * 16 * 4);
  127. glEnable(GL_TEXTURE_2D);
  128. for(i = 32; i < 128; i++)
  129. {
  130. glGenTextures(1, (GLuint*)&dp->drv.p->id[i - 32]);
  131. glBindTexture(GL_TEXTURE_2D, dp->drv.p->id[i - 32]);
  132. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
  133. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
  134. glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB8,
  135. 16, 16, 0, GL_RGB, GL_UNSIGNED_BYTE, empty_texture);
  136. }
  137. for(i = 0; i < 8; i++)
  138. {
  139. glGenTextures(1, (GLuint*)&dp->drv.p->id_uni[i]);
  140. glBindTexture(GL_TEXTURE_2D, dp->drv.p->id_uni[i]);
  141. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
  142. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
  143. glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB8,
  144. 16, 16, 0, GL_RGB, GL_UNSIGNED_BYTE, empty_texture);
  145. }
  146. for(i = 32; i < 128; i++)
  147. {
  148. glDisable(GL_TEXTURE_2D);
  149. glClear(GL_COLOR_BUFFER_BIT);
  150. glColor3f(1, 1, 1);
  151. glRasterPos2f(0, 15);
  152. glutBitmapCharacter(GLUT_BITMAP_9_BY_15, i);
  153. glEnable(GL_TEXTURE_2D);
  154. glBindTexture(GL_TEXTURE_2D, dp->drv.p->id[i - 32]);
  155. glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGB,
  156. 0, dp->drv.p->height - 16, 16, 16, 0);
  157. #ifdef HAVE_GLUTCHECKLOOP
  158. glutCheckLoop();
  159. #else
  160. glutMainLoopEvent();
  161. #endif
  162. glutSwapBuffers();
  163. }
  164. /* CP437 hack */
  165. for(i = 0; i < 8; i++)
  166. {
  167. glDisable(GL_TEXTURE_2D);
  168. glClear(GL_COLOR_BUFFER_BIT);
  169. glColor3f(1, 1, 1);
  170. glTranslatef(0.5,0.5,0);
  171. switch(i)
  172. {
  173. case 0: /* 0x00002580 */
  174. glBegin(GL_QUADS);
  175. glVertex2f(0,0); glVertex2f(9,0); glVertex2f(9,7); glVertex2f(0,7);
  176. glEnd();
  177. break;
  178. case 1: /* 0x00002584 */
  179. glBegin(GL_QUADS);
  180. glVertex2f(0,7); glVertex2f(9,7); glVertex2f(9,15); glVertex2f(0,15);
  181. glEnd();
  182. break;
  183. case 2: /* 0x00002588 */
  184. glBegin(GL_QUADS);
  185. glVertex2f(0,0); glVertex2f(9,0); glVertex2f(9,15); glVertex2f(0,15);
  186. glEnd();
  187. break;
  188. case 3: /* 0x0000258c */
  189. glBegin(GL_QUADS);
  190. glVertex2f(0,0); glVertex2f(4,0); glVertex2f(4,15); glVertex2f(0,15);
  191. glEnd();
  192. break;
  193. case 4: /* 0x00002590 */
  194. glBegin(GL_QUADS);
  195. glVertex2f(4,0); glVertex2f(9,0); glVertex2f(9,15); glVertex2f(4,15);
  196. glEnd();
  197. break;
  198. default: /* 0x0000259[123] */
  199. {
  200. int a, j, k = i - 5;
  201. for(j = dp->drv.p->font_height; j--; )
  202. for(a = dp->drv.p->font_width; a--; )
  203. {
  204. if(((a + 2 * (j & 1)) & 3) > k)
  205. continue;
  206. glBegin(GL_POINTS);
  207. glVertex2f(a, j);
  208. glEnd();
  209. }
  210. }
  211. }
  212. glEnable(GL_TEXTURE_2D);
  213. glBindTexture(GL_TEXTURE_2D, dp->drv.p->id_uni[i]);
  214. glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGB,
  215. 0, dp->drv.p->height - 16, 16, 16, 0);
  216. #ifdef HAVE_GLUTCHECKLOOP
  217. glutCheckLoop();
  218. #else
  219. glutMainLoopEvent();
  220. #endif
  221. glutSwapBuffers();
  222. glutPostRedisplay();
  223. }
  224. return 0;
  225. }
  226. static int gl_end_graphics(caca_display_t *dp)
  227. {
  228. glutDestroyWindow(dp->drv.p->window);
  229. free(dp->drv.p);
  230. return 0;
  231. }
  232. static int gl_set_display_title(caca_display_t *dp, char const *title)
  233. {
  234. glutSetWindowTitle(title);
  235. return 0;
  236. }
  237. static unsigned int gl_get_display_width(caca_display_t *dp)
  238. {
  239. return dp->drv.p->width;
  240. }
  241. static unsigned int gl_get_display_height(caca_display_t *dp)
  242. {
  243. return dp->drv.p->height;
  244. }
  245. static void gl_display(caca_display_t *dp)
  246. {
  247. unsigned int x, y, line;
  248. glClear(GL_COLOR_BUFFER_BIT);
  249. line = 0;
  250. for(y = 0; y < dp->drv.p->height; y += dp->drv.p->font_height)
  251. {
  252. uint32_t *attr = dp->cv->attr + line * dp->cv->width;
  253. for(x = 0; x < dp->drv.p->width; x += dp->drv.p->font_width)
  254. {
  255. uint16_t bg = _cucul_argb32_to_rgb12bg(*attr++);
  256. glDisable(GL_TEXTURE_2D);
  257. glColor3b(((bg & 0xf00) >> 8) * 8,
  258. ((bg & 0x0f0) >> 4) * 8,
  259. (bg & 0x00f) * 8);
  260. glBegin(GL_QUADS);
  261. glVertex2f(x, y);
  262. glVertex2f(x + dp->drv.p->font_width, y);
  263. glVertex2f(x + dp->drv.p->font_width,
  264. y + dp->drv.p->font_height);
  265. glVertex2f(x, y + dp->drv.p->font_height);
  266. glEnd();
  267. }
  268. line++;
  269. }
  270. /* 2nd pass, avoids changing render state too much */
  271. glEnable(GL_BLEND);
  272. glEnable(GL_TEXTURE_2D);
  273. glBlendFunc(GL_ONE, GL_ONE);
  274. line = 0;
  275. for(y = 0; y < dp->drv.p->height; y += dp->drv.p->font_height)
  276. {
  277. uint32_t *attr = dp->cv->attr + line * dp->cv->width;
  278. uint32_t *chars = dp->cv->chars + line * dp->cv->width;
  279. for(x = 0; x < dp->drv.p->width; x += dp->drv.p->font_width)
  280. {
  281. uint32_t cv = *chars++;
  282. if(cv > 0x00000020 && cv < 0x00000080)
  283. {
  284. uint16_t fg = _cucul_argb32_to_rgb12fg(*attr);
  285. glBindTexture(GL_TEXTURE_2D, dp->drv.p->id[cv - 32]);
  286. glColor3b(((fg & 0xf00) >> 8) * 8,
  287. ((fg & 0x0f0) >> 4) * 8,
  288. (fg & 0x00f) * 8);
  289. glBegin(GL_QUADS);
  290. glTexCoord2f(0, dp->drv.p->sh);
  291. glVertex2f(x, y);
  292. glTexCoord2f(dp->drv.p->sw, dp->drv.p->sh);
  293. glVertex2f(x + dp->drv.p->font_width, y);
  294. glTexCoord2f(dp->drv.p->sw, 0);
  295. glVertex2f(x + dp->drv.p->font_width,
  296. y + dp->drv.p->font_height);
  297. glTexCoord2f(0, 0);
  298. glVertex2f(x, y + dp->drv.p->font_height);
  299. glEnd();
  300. }
  301. else if(cv!=' ')
  302. {
  303. switch(cv)
  304. {
  305. case 0x00002580: glBindTexture(GL_TEXTURE_2D, dp->drv.p->id_uni[0]); break;
  306. case 0x00002584: glBindTexture(GL_TEXTURE_2D, dp->drv.p->id_uni[1]); break;
  307. case 0x00002588: glBindTexture(GL_TEXTURE_2D, dp->drv.p->id_uni[2]); break;
  308. case 0x0000258c: glBindTexture(GL_TEXTURE_2D, dp->drv.p->id_uni[3]); break;
  309. case 0x00002590: glBindTexture(GL_TEXTURE_2D, dp->drv.p->id_uni[4]); break;
  310. case 0x00002591: glBindTexture(GL_TEXTURE_2D, dp->drv.p->id_uni[5]); break;
  311. case 0x00002592: glBindTexture(GL_TEXTURE_2D, dp->drv.p->id_uni[6]); break;
  312. case 0x00002593: glBindTexture(GL_TEXTURE_2D, dp->drv.p->id_uni[7]); break;
  313. default: glBindTexture(GL_TEXTURE_2D, dp->drv.p->id['?' - 32]); break;
  314. }
  315. uint16_t fg = _cucul_argb32_to_rgb12fg(*attr);
  316. glColor3b(((fg & 0xf00) >> 8) * 8,
  317. ((fg & 0x0f0) >> 4) * 8,
  318. (fg & 0x00f) * 8);
  319. glBegin(GL_QUADS);
  320. glTexCoord2f(0, dp->drv.p->sh);
  321. glVertex2f(x, y);
  322. glTexCoord2f(dp->drv.p->sw, dp->drv.p->sh);
  323. glVertex2f(x + dp->drv.p->font_width, y);
  324. glTexCoord2f(dp->drv.p->sw, 0);
  325. glVertex2f(x + dp->drv.p->font_width,
  326. y + dp->drv.p->font_height);
  327. glTexCoord2f(0, 0);
  328. glVertex2f(x, y + dp->drv.p->font_height);
  329. glEnd();
  330. }
  331. attr++;
  332. }
  333. line++;
  334. }
  335. glDisable(GL_BLEND);
  336. glDisable(GL_TEXTURE_2D);
  337. #ifdef HAVE_GLUTCHECKLOOP
  338. glutCheckLoop();
  339. #else
  340. glutMainLoopEvent();
  341. #endif
  342. glutSwapBuffers();
  343. glutPostRedisplay();
  344. }
  345. static void gl_handle_resize(caca_display_t *dp)
  346. {
  347. dp->drv.p->width = dp->drv.p->new_width;
  348. dp->drv.p->height = dp->drv.p->new_height;
  349. glMatrixMode(GL_PROJECTION);
  350. glPushMatrix();
  351. glLoadIdentity();
  352. glViewport(0, 0, dp->drv.p->width, dp->drv.p->height);
  353. gluOrtho2D(0, dp->drv.p->width, dp->drv.p->height, 0);
  354. glMatrixMode(GL_MODELVIEW);
  355. }
  356. static int gl_get_event(caca_display_t *dp, caca_event_t *ev)
  357. {
  358. #ifdef HAVE_GLUTCHECKLOOP
  359. glutCheckLoop();
  360. #else
  361. glutMainLoopEvent();
  362. #endif
  363. #ifdef HAVE_GLUTCLOSEFUNC
  364. if(dp->drv.p->close)
  365. {
  366. dp->drv.p->close = 0;
  367. ev->type = CACA_EVENT_QUIT;
  368. return 1;
  369. }
  370. #endif
  371. if(dp->resize.resized)
  372. {
  373. ev->type = CACA_EVENT_RESIZE;
  374. ev->data.resize.w = dp->cv->width;
  375. ev->data.resize.h = dp->cv->height;
  376. return 1;
  377. }
  378. if(dp->drv.p->mouse_changed)
  379. {
  380. ev->type = CACA_EVENT_MOUSE_MOTION;
  381. ev->data.mouse.x = dp->mouse.x;
  382. ev->data.mouse.y = dp->mouse.y;
  383. dp->drv.p->mouse_changed = 0;
  384. if(dp->drv.p->mouse_clicked)
  385. {
  386. _push_event(dp, ev);
  387. ev->type = CACA_EVENT_MOUSE_PRESS;
  388. ev->data.mouse.button = dp->drv.p->mouse_button;
  389. dp->drv.p->mouse_clicked = 0;
  390. }
  391. return 1;
  392. }
  393. if(dp->drv.p->key != 0)
  394. {
  395. ev->type = CACA_EVENT_KEY_PRESS;
  396. ev->data.key.ch = dp->drv.p->key;
  397. ev->data.key.utf32 = (uint32_t)dp->drv.p->key;
  398. ev->data.key.utf8[0] = dp->drv.p->key;
  399. ev->data.key.utf8[1] = '\0';
  400. dp->drv.p->key = 0;
  401. return 1;
  402. }
  403. if(dp->drv.p->special_key != 0)
  404. {
  405. switch(dp->drv.p->special_key)
  406. {
  407. case GLUT_KEY_F1 : ev->data.key.ch = CACA_KEY_F1; break;
  408. case GLUT_KEY_F2 : ev->data.key.ch = CACA_KEY_F2; break;
  409. case GLUT_KEY_F3 : ev->data.key.ch = CACA_KEY_F3; break;
  410. case GLUT_KEY_F4 : ev->data.key.ch = CACA_KEY_F4; break;
  411. case GLUT_KEY_F5 : ev->data.key.ch = CACA_KEY_F5; break;
  412. case GLUT_KEY_F6 : ev->data.key.ch = CACA_KEY_F6; break;
  413. case GLUT_KEY_F7 : ev->data.key.ch = CACA_KEY_F7; break;
  414. case GLUT_KEY_F8 : ev->data.key.ch = CACA_KEY_F8; break;
  415. case GLUT_KEY_F9 : ev->data.key.ch = CACA_KEY_F9; break;
  416. case GLUT_KEY_F10: ev->data.key.ch = CACA_KEY_F10; break;
  417. case GLUT_KEY_F11: ev->data.key.ch = CACA_KEY_F11; break;
  418. case GLUT_KEY_F12: ev->data.key.ch = CACA_KEY_F12; break;
  419. case GLUT_KEY_LEFT : ev->data.key.ch = CACA_KEY_LEFT; break;
  420. case GLUT_KEY_RIGHT: ev->data.key.ch = CACA_KEY_RIGHT; break;
  421. case GLUT_KEY_UP : ev->data.key.ch = CACA_KEY_UP; break;
  422. case GLUT_KEY_DOWN : ev->data.key.ch = CACA_KEY_DOWN; break;
  423. case GLUT_KEY_PAGE_UP : ev->data.key.ch = CACA_KEY_PAGEUP; break;
  424. case GLUT_KEY_PAGE_DOWN : ev->data.key.ch = CACA_KEY_PAGEDOWN;
  425. break;
  426. case GLUT_KEY_HOME : ev->data.key.ch = CACA_KEY_HOME; break;
  427. case GLUT_KEY_END : ev->data.key.ch = CACA_KEY_END; break;
  428. case GLUT_KEY_INSERT : ev->data.key.ch = CACA_KEY_INSERT; break;
  429. default: ev->type = CACA_EVENT_NONE; return 0;
  430. }
  431. ev->type = CACA_EVENT_KEY_PRESS;
  432. ev->data.key.utf32 = 0;
  433. ev->data.key.utf8[0] = '\0';
  434. dp->drv.p->special_key = 0;
  435. return 1;
  436. }
  437. ev->type = CACA_EVENT_NONE;
  438. return 0;
  439. }
  440. static void gl_set_mouse(caca_display_t *dp, int flag)
  441. {
  442. if(flag)
  443. glutSetCursor(GLUT_CURSOR_RIGHT_ARROW);
  444. else
  445. glutSetCursor(GLUT_CURSOR_NONE);
  446. }
  447. /*
  448. * XXX: following functions are local
  449. */
  450. static void gl_handle_keyboard(unsigned char key, int x, int y)
  451. {
  452. caca_display_t *dp = gl_d;
  453. dp->drv.p->key = key;
  454. }
  455. static void gl_handle_special_key(int key, int x, int y)
  456. {
  457. caca_display_t *dp = gl_d;
  458. dp->drv.p->special_key = key;
  459. }
  460. static void gl_handle_reshape(int w, int h)
  461. {
  462. caca_display_t *dp = gl_d;
  463. if(dp->drv.p->bit) /* Do not handle reshaping at the first time */
  464. {
  465. dp->drv.p->new_width = w;
  466. dp->drv.p->new_height = h;
  467. dp->resize.w = w / dp->drv.p->font_width;
  468. dp->resize.h = (h / dp->drv.p->font_height) + 1;
  469. dp->resize.resized = 1;
  470. }
  471. else
  472. dp->drv.p->bit = 1;
  473. }
  474. static void gl_handle_mouse(int button, int state, int x, int y)
  475. {
  476. caca_display_t *dp = gl_d;
  477. dp->drv.p->mouse_clicked = 1;
  478. dp->drv.p->mouse_button = button;
  479. dp->drv.p->mouse_state = state;
  480. dp->drv.p->mouse_x = x / dp->drv.p->font_width;
  481. dp->drv.p->mouse_y = y / dp->drv.p->font_height;
  482. dp->mouse.x = dp->drv.p->mouse_x;
  483. dp->mouse.y = dp->drv.p->mouse_y;
  484. dp->drv.p->mouse_changed = 1;
  485. }
  486. static void gl_handle_mouse_motion(int x, int y)
  487. {
  488. caca_display_t *dp = gl_d;
  489. dp->drv.p->mouse_x = x / dp->drv.p->font_width;
  490. dp->drv.p->mouse_y = y / dp->drv.p->font_height;
  491. dp->mouse.x = dp->drv.p->mouse_x;
  492. dp->mouse.y = dp->drv.p->mouse_y;
  493. dp->drv.p->mouse_changed = 1;
  494. }
  495. #ifdef HAVE_GLUTCLOSEFUNC
  496. static void gl_handle_close(void)
  497. {
  498. caca_display_t *dp = gl_d;
  499. dp->drv.p->close = 1;
  500. }
  501. #endif
  502. static void _display(void)
  503. {
  504. caca_display_t *dp = gl_d;
  505. gl_display(dp);
  506. }
  507. /*
  508. * Driver initialisation
  509. */
  510. int gl_install(caca_display_t *dp)
  511. {
  512. #if defined(HAVE_GETENV) && defined(GLUT_XLIB_IMPLEMENTATION)
  513. if(!getenv("DISPLAY") || !*(getenv("DISPLAY")))
  514. return -1;
  515. #endif
  516. dp->drv.driver = CACA_DRIVER_GL;
  517. dp->drv.init_graphics = gl_init_graphics;
  518. dp->drv.end_graphics = gl_end_graphics;
  519. dp->drv.set_display_title = gl_set_display_title;
  520. dp->drv.get_display_width = gl_get_display_width;
  521. dp->drv.get_display_height = gl_get_display_height;
  522. dp->drv.display = gl_display;
  523. dp->drv.handle_resize = gl_handle_resize;
  524. dp->drv.get_event = gl_get_event;
  525. dp->drv.set_mouse = gl_set_mouse;
  526. return 0;
  527. }
  528. #endif /* USE_GL */