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.

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