From 5dc72bc0b1662e5806c0f6903c09d7a7e5fbcc53 Mon Sep 17 00:00:00 2001 From: Jean-Yves Lamoureux Date: Tue, 21 Jun 2005 13:28:51 +0000 Subject: [PATCH] OpenGL support. --- configure.ac | 19 ++- src/caca.c | 27 +++- src/caca_internals.h | 9 ++ src/event.c | 64 +++++++++ src/graphics.c | 306 ++++++++++++++++++++++++++++++++++++++++++- 5 files changed, 422 insertions(+), 3 deletions(-) diff --git a/configure.ac b/configure.ac index d87feb6..879af62 100644 --- a/configure.ac +++ b/configure.ac @@ -35,6 +35,8 @@ AC_ARG_ENABLE(conio, [ --enable-conio DOS conio.h graphics support (autodetected)]) AC_ARG_ENABLE(x11, [ --enable-x11 X11 support (autodetected)]) +AC_ARG_ENABLE(gl, + [ --enable-gl OpenGL support (autodetected)]) dnl example programs features AC_ARG_ENABLE(imlib2, @@ -123,6 +125,19 @@ if test "${enable_x11}" != "no"; then fi fi +if test "${enable_gl}" != "no"; then + ac_cv_my_have_gl="no" + AC_CHECK_HEADERS(GL/gl.h GL/glut.h, + [AC_CHECK_LIB(glut, glutMainLoopEvent, + [ac_cv_my_have_gl="yes" + AC_DEFINE(USE_GL, 1, Define to activate the OpenGL backend driver) + CACA_LIBS="${CACA_LIBS} -lGL -lglut" + CACA_DRIVERS="${CACA_DRIVERS} gl"])]) + if test "${ac_cv_my_have_gl}" = "no" -a "${enable_gl}" = "yes"; then + AC_MSG_ERROR([cannot find OpenGL+FreeGLUT development files]) + fi +fi + if test "${enable_ncurses}" != "no"; then ac_cv_my_have_ncurses="no" AC_CHECK_HEADERS(curses.h ncurses.h, @@ -155,7 +170,9 @@ AC_SUBST(CACA_LIBS) # Optimizations CFLAGS="${CFLAGS} -g -O2 -fno-strength-reduce -fomit-frame-pointer" # Code qui fait des warnings == code de porc == deux baffes dans ta gueule -CFLAGS="${CFLAGS} -Wall -Wpointer-arith -Wcast-align -Wcast-qual -Wstrict-prototypes -Wshadow -Waggregate-return -Wmissing-prototypes -Wnested-externs -Wsign-compare" +# [Jylam] Removed -Wshadow in order to avoid ncurses/gl conflict +# (Comme quoi on est pas les seuls porcs) +CFLAGS="${CFLAGS} -Wall -Wpointer-arith -Wcast-align -Wcast-qual -Wstrict-prototypes -Waggregate-return -Wmissing-prototypes -Wnested-externs -Wsign-compare" # Build the PIC library? case "${target_os}" in diff --git a/src/caca.c b/src/caca.c index 613faa9..f0e4a26 100644 --- a/src/caca.c +++ b/src/caca.c @@ -55,7 +55,9 @@ #if defined(USE_WIN32) # include #endif - +#if defined(USE_GL) +# include +#endif #include #include @@ -194,6 +196,13 @@ int caca_init(void) SetConsoleMode(win32_hout, ENABLE_MOUSE_INPUT); } else +#endif +#if defined(USE_GL) + if(_caca_driver == CACA_DRIVER_GL) + { + /* Nothing to do */ + } + else #endif { /* Dummy */ @@ -425,6 +434,13 @@ void caca_end(void) CloseHandle(win32_hout); } else +#endif +#if defined(USE_GL) + if(_caca_driver == CACA_DRIVER_GL) + { + /* Nothing to do */ + } + else #endif { /* Dummy */ @@ -458,6 +474,11 @@ static void caca_init_driver(void) _caca_driver = CACA_DRIVER_X11; else #endif +#if defined(USE_GL) + if(!strcasecmp(var, "gl")) + _caca_driver = CACA_DRIVER_GL; + else +#endif #if defined(USE_SLANG) if(!strcasecmp(var, "slang")) _caca_driver = CACA_DRIVER_SLANG; @@ -491,6 +512,10 @@ static void caca_init_driver(void) return; } #endif +#if defined(USE_GL) + _caca_driver = CACA_DRIVER_GL; + return; +#endif #if defined(USE_SLANG) _caca_driver = CACA_DRIVER_SLANG; return; diff --git a/src/caca_internals.h b/src/caca_internals.h index 1b680b3..132c982 100644 --- a/src/caca_internals.h +++ b/src/caca_internals.h @@ -47,6 +47,9 @@ enum caca_driver #endif #if defined(USE_WIN32) CACA_DRIVER_WIN32 = 5, +#endif +#if defined(USE_GL) + CACA_DRIVER_GL = 6, #endif CACA_DRIVER_NONE = 0 }; @@ -97,4 +100,10 @@ extern unsigned int x11_new_width, x11_new_height; extern HANDLE win32_hin, win32_hout; #endif +#if defined(USE_GL) +#include +extern unsigned int gl_width, gl_height; +#endif + + #endif /* __CACA_INTERNALS_H__ */ diff --git a/src/event.c b/src/event.c index f8b13c4..feb3927 100644 --- a/src/event.c +++ b/src/event.c @@ -54,7 +54,18 @@ #if defined(USE_WIN32) # include #endif +#if defined(USE_GL) +#include +#include +extern int gl_special_key; +extern unsigned char gl_key; +extern unsigned char gl_resized; +extern float gl_font_width; +extern float gl_font_height; +extern int gl_new_width; +extern int gl_new_height; +#endif #include "caca.h" #include "caca_internals.h" @@ -718,6 +729,59 @@ static unsigned int _lowlevel_event(void) return CACA_EVENT_NONE; } else +#endif +#if defined(USE_GL) + if(_caca_driver == CACA_DRIVER_GL) + { + glutMainLoopEvent(); + + if(gl_resized) + { + if(!_caca_resize) + { + + + _caca_resize = 1; + gl_resized=0; + return CACA_EVENT_RESIZE; + } + } + + if(gl_key!=0) + { + event |= CACA_EVENT_KEY_PRESS; + event |= gl_key; + gl_key = 0; + } + + if(gl_special_key != 0) + { + event |= CACA_EVENT_KEY_PRESS; + + switch(gl_special_key) + { + case GLUT_KEY_F1 : gl_special_key = 0; return event | CACA_KEY_F1; + case GLUT_KEY_F2 : gl_special_key = 0; return event | CACA_KEY_F2; + case GLUT_KEY_F3 : gl_special_key = 0; return event | CACA_KEY_F3; + case GLUT_KEY_F4 : gl_special_key = 0; return event | CACA_KEY_F4; + case GLUT_KEY_F5 : gl_special_key = 0; return event | CACA_KEY_F5; + case GLUT_KEY_F6 : gl_special_key = 0; return event | CACA_KEY_F6; + case GLUT_KEY_F7 : gl_special_key = 0; return event | CACA_KEY_F7; + case GLUT_KEY_F8 : gl_special_key = 0; return event | CACA_KEY_F8; + case GLUT_KEY_F9 : gl_special_key = 0; return event | CACA_KEY_F9; + case GLUT_KEY_F10 : gl_special_key = 0; return event | CACA_KEY_F10; + case GLUT_KEY_F11 : gl_special_key = 0; return event | CACA_KEY_F11; + case GLUT_KEY_F12 : gl_special_key = 0; return event | CACA_KEY_F12; + case GLUT_KEY_LEFT : gl_special_key = 0; return event | CACA_KEY_LEFT; + case GLUT_KEY_RIGHT: gl_special_key = 0; return event | CACA_KEY_RIGHT; + case GLUT_KEY_UP : gl_special_key = 0; return event | CACA_KEY_UP; + case GLUT_KEY_DOWN : gl_special_key = 0; return event | CACA_KEY_DOWN; + default: return CACA_EVENT_NONE; + } + } + return event; + } + else #endif { /* Dummy */ diff --git a/src/graphics.c b/src/graphics.c index 23fd987..0b25da6 100644 --- a/src/graphics.c +++ b/src/graphics.c @@ -58,7 +58,10 @@ #if defined(USE_WIN32) # include #endif - +#if defined(USE_GL) +# include +# include +#endif #if defined(HAVE_INTTYPES_H) || defined(_DOXYGEN_SKIP_ME) # include #else @@ -232,6 +235,38 @@ static int const win32_bg_palette[] = BACKGROUND_INTENSITY | BACKGROUND_RED | BACKGROUND_GREEN | BACKGROUND_BLUE }; #endif +#if defined(USE_GL) + +static unsigned int const gl_bg_palette[] = +{ + 0, + 0x0000007F, + 0x00007F00, + 0x00007F7F, + 0x007F0000, + 0x007F007F, + 0x007F7F00, + 0x007F7F7F, + // + intensity + 0x00000000, + 0x000000FF, + 0x0000FF00, + 0x0000FFFF, + 0x00FF0000, + 0x00FF00FF, + 0x00FFFF00, + 0x00FFFFFF, + +}; + +int gl_window; +unsigned int gl_width, gl_height; +float gl_font_width, gl_font_height; +float gl_incx, gl_incy; +int id[94]; +unsigned char gl_resized=0, gl_bit=0; +#endif + static char *_caca_empty_line; static char *_caca_scratch_line; @@ -262,6 +297,39 @@ static RETSIGTYPE sigwinch_handler(int); static int x11_error_handler(Display *, XErrorEvent *); #endif +#if defined(USE_GL) +unsigned char gl_key = 0; +int gl_special_key=0; +int gl_new_width; +int gl_new_height; + + +static void gl_handle_keyboard(unsigned char key, int x, int y) +{ + gl_key = key; +} +static void gl_handle_special_key(int key, int x, int y) +{ + gl_special_key = key; +} +static void gl_handle_reshape (int w, int h) +{ + if(gl_bit) /* Do not handle reshaping at the first time*/ + { + + gl_new_width = w; + gl_new_height = h; + + gl_resized = 1; + } + else + gl_bit=1; + +} +#endif + + + /** \brief Set the default colour pair. * * This function sets the default colour pair. String functions such as @@ -329,6 +397,11 @@ void caca_set_color(enum caca_color fgcolor, enum caca_color bgcolor) case CACA_DRIVER_WIN32: /* Nothing to do */ break; +#endif +#if defined(USE_GL) + case CACA_DRIVER_GL: + /* Nothing to do */ + break; #endif default: break; @@ -414,6 +487,10 @@ void caca_putchar(int x, int y, char c) #if defined(USE_WIN32) case CACA_DRIVER_WIN32: break; +#endif +#if defined(USE_GL) + case CACA_DRIVER_GL: + break; #endif default: break; @@ -509,6 +586,10 @@ void caca_putstr(int x, int y, char const *s) #if defined(USE_WIN32) case CACA_DRIVER_WIN32: break; +#endif +#if defined(USE_GL) + case CACA_DRIVER_GL: + break; #endif default: break; @@ -880,6 +961,89 @@ int _caca_init_graphics(void) } else #endif +#if defined(USE_GL) + if(_caca_driver == CACA_DRIVER_GL) + { + int i; + char *empty; + + if(!_caca_width) + _caca_width = 80; + if(!_caca_height) + _caca_height = 32; + + gl_font_width = 9; + gl_font_height = 15; + + gl_width = _caca_width*gl_font_width; + gl_height = _caca_height*gl_font_height; + + glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE); + glutInitWindowSize(gl_width, gl_height); + gl_window = glutCreateWindow("caca for GL"); + + gluOrtho2D(0,gl_width, gl_height, 0); + + glDisable(GL_CULL_FACE); + glDisable(GL_DEPTH_TEST); + + glutKeyboardFunc(gl_handle_keyboard); + glutSpecialFunc(gl_handle_special_key); + glutReshapeFunc(gl_handle_reshape); + + glLoadIdentity(); + + glMatrixMode(GL_PROJECTION); + glPushMatrix(); + glLoadIdentity(); + gluOrtho2D(0, gl_width, gl_height, 0); + + glMatrixMode(GL_MODELVIEW); + + + glClear(GL_COLOR_BUFFER_BIT); + + + + empty = malloc(16*16*4); + if(empty == NULL) + return -1; + + memset(empty, 255, 16*16*4); + glEnable(GL_TEXTURE_2D); + + for(i=0;i<94;i++) + { + glGenTextures(1,&id[i]); + glBindTexture(GL_TEXTURE_2D, id[i]); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB8, + 16,16, + 0, GL_RGB, GL_UNSIGNED_BYTE, empty); + } + for(i=0;i<94;i++) + { + + glDisable(GL_TEXTURE_2D); + glClear(GL_COLOR_BUFFER_BIT); + + glColor3f(1,1,1); + glRasterPos2f(0,15); + glutBitmapCharacter(GLUT_BITMAP_9_BY_15,i+32); + + + glEnable(GL_TEXTURE_2D); + glBindTexture(GL_TEXTURE_2D,id[i]); + glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 0, gl_height-16, 16,16, 0); + + glutMainLoopEvent(); + glutPostRedisplay(); + } + } + else +#endif + { /* Dummy */ } @@ -953,6 +1117,13 @@ int _caca_end_graphics(void) CloseHandle(win32_front); } else +#endif +#if defined(USE_GL) + if(_caca_driver == CACA_DRIVER_GL) + { + glutDestroyWindow(gl_window); + } + else #endif { /* Dummy */ @@ -987,6 +1158,13 @@ int caca_set_window_title(char const *title) SetConsoleTitle(title); } else +#endif +#if defined(USE_GL) + if(_caca_driver == CACA_DRIVER_GL) + { + glutSetWindowTitle(title); + } + else #endif { /* Not supported */ @@ -1020,6 +1198,13 @@ unsigned int caca_get_window_width(void) /* FIXME */ } else +#endif +#if defined(USE_GL) + if(_caca_driver == CACA_DRIVER_GL) + { + return gl_width; + } + else #endif { /* Dummy */ @@ -1053,6 +1238,13 @@ unsigned int caca_get_window_height(void) /* FIXME */ } else +#endif +#if defined(USE_GL) + if(_caca_driver == CACA_DRIVER_GL) + { + return gl_height; + } + else #endif { /* Dummy */ @@ -1220,6 +1412,98 @@ void caca_refresh(void) WriteConsoleOutput(win32_front, win32_buffer, size, pos, &rect); } else +#endif +#if defined(USE_GL) + if(_caca_driver == CACA_DRIVER_GL) + { + unsigned int x, y, offsetx, offsety; + + + glClear(GL_COLOR_BUFFER_BIT); + + offsety=0; + for(y=0;y>4; + + br = ((gl_bg_palette[offset]&0x00FF0000)>>16)/255.0f; + bg = ((gl_bg_palette[offset]&0x0000FF00)>>8)/255.0f; + bb = ((gl_bg_palette[offset]&0x000000FF))/255.0f; + + glDisable(GL_TEXTURE_2D); + glColor3f(br, bg, bb); + glBegin(GL_QUADS); + glVertex2f(x,y); + glVertex2f(x+gl_font_width,y); + glVertex2f(x+gl_font_width,y+gl_font_height); + glVertex2f(x,y+gl_font_height); + glEnd(); + + + offsetx++; + } + + offsety++; + } + + + + /* 2nd pass, avoids changing render state too much */ + glEnable(GL_BLEND); + glEnable(GL_TEXTURE_2D); + glBlendFunc(GL_ONE, GL_ONE); + + offsety=0; + for(y=0;y>16)/255.0f; + fg = ((gl_bg_palette[attr[0] & 0xf]&0x0000FF00)>>8)/255.0f; + fb = ((gl_bg_palette[attr[0] & 0xf]&0x000000FF))/255.0f; + + if(chr[0] != ' ') + { + glBindTexture(GL_TEXTURE_2D, id[chr[0]-32]); + + glColor3f(fr, fg, fb); + glBegin(GL_QUADS); + glTexCoord2f(0,1); + glVertex2f(x,y); + glTexCoord2f(0.5,1); + glVertex2f(x+gl_font_width,y); + glTexCoord2f(0.5,0); + glVertex2f(x+gl_font_width,y+gl_font_height); + glTexCoord2f(0,0); + glVertex2f(x,y+gl_font_height); + glEnd(); + } + offsetx++; + } + offsety++; + } + glDisable(GL_BLEND); + glDisable(GL_TEXTURE_2D); + + + + glutMainLoopEvent(); + glutSwapBuffers(); + glutPostRedisplay(); + } +else #endif { /* Dummy */ @@ -1321,6 +1605,26 @@ static void caca_handle_resize(void) { } else +#endif +#if defined(USE_GL) + if(_caca_driver == CACA_DRIVER_GL) + { + gl_width = gl_new_width; + gl_height = gl_new_height; + + _caca_width = gl_width/gl_font_width; + _caca_height = (gl_height/gl_font_height)+1; + + glMatrixMode(GL_PROJECTION); + glPushMatrix(); + glLoadIdentity(); + + glViewport(0,0,gl_width, gl_height); + gluOrtho2D(0, gl_width, gl_height, 0); + glMatrixMode(GL_MODELVIEW); + + } + else #endif { /* Dummy */