nkeynes@94: /** nkeynes@280: * $Id: video_x11.c,v 1.7 2007-01-14 02:55:06 nkeynes Exp $ nkeynes@94: * nkeynes@103: * Shared functions for all X11-based display drivers. nkeynes@94: * nkeynes@94: * Copyright (c) 2005 Nathan Keynes. nkeynes@94: * nkeynes@94: * This program is free software; you can redistribute it and/or modify nkeynes@94: * it under the terms of the GNU General Public License as published by nkeynes@94: * the Free Software Foundation; either version 2 of the License, or nkeynes@94: * (at your option) any later version. nkeynes@94: * nkeynes@94: * This program is distributed in the hope that it will be useful, nkeynes@94: * but WITHOUT ANY WARRANTY; without even the implied warranty of nkeynes@94: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the nkeynes@94: * GNU General Public License for more details. nkeynes@94: */ nkeynes@94: nkeynes@103: #include nkeynes@103: #include nkeynes@103: #include "dream.h" nkeynes@94: #include "drivers/video_x11.h" nkeynes@94: nkeynes@103: /** nkeynes@103: * General X11 parameters. The front-end driver is expected to set this up nkeynes@103: * by calling video_x11_set_display after initializing itself. nkeynes@103: */ nkeynes@94: Display *video_x11_display = NULL; nkeynes@94: Screen *video_x11_screen = NULL; nkeynes@94: Window video_x11_window = 0; nkeynes@94: nkeynes@103: /** nkeynes@103: * GLX parameters. nkeynes@103: */ nkeynes@103: GLXContext glx_context; nkeynes@103: Window glx_window; nkeynes@103: gboolean glx_open = FALSE; nkeynes@103: nkeynes@94: void video_x11_set_display( Display *display, Screen *screen, Window window ) nkeynes@94: { nkeynes@94: video_x11_display = display; nkeynes@94: video_x11_screen = screen; nkeynes@94: video_x11_window = window; nkeynes@94: } nkeynes@94: nkeynes@103: nkeynes@103: gboolean video_glx_create_window( int x, int y, int width, int height ) nkeynes@103: { nkeynes@103: int major, minor; nkeynes@103: const char *glxExts, *glxServer; nkeynes@103: int visual_attrs[] = { GLX_RGBA, GLX_RED_SIZE, 4, nkeynes@103: GLX_GREEN_SIZE, 4, nkeynes@103: GLX_BLUE_SIZE, 4, nkeynes@103: GLX_ALPHA_SIZE, 4, nkeynes@103: GLX_DEPTH_SIZE, 16, nkeynes@103: GLX_DOUBLEBUFFER, nkeynes@103: None }; nkeynes@103: int screen = XScreenNumberOfScreen(video_x11_screen); nkeynes@103: XSetWindowAttributes win_attrs; nkeynes@103: XVisualInfo *visual; nkeynes@103: nkeynes@103: if( glXQueryVersion( video_x11_display, &major, &minor ) == False ) { nkeynes@103: ERROR( "X Display lacks the GLX nature" ); nkeynes@103: return FALSE; nkeynes@103: } nkeynes@103: if( major < 1 || minor < 2 ) { nkeynes@103: ERROR( "X display supports GLX %d.%d, but we need at least 1.2", major, minor ); nkeynes@103: return FALSE; nkeynes@103: } nkeynes@103: nkeynes@103: glxExts = glXQueryExtensionsString( video_x11_display, screen ); nkeynes@103: glxServer = glXQueryServerString( video_x11_display, screen, GLX_VENDOR ); nkeynes@103: INFO( "GLX version %d.%d, %s. Supported exts: %s", major, minor, nkeynes@103: glxServer, glxExts ); nkeynes@103: nkeynes@103: /* Find ourselves a nice visual */ nkeynes@103: visual = glXChooseVisual( video_x11_display, nkeynes@103: screen, nkeynes@103: visual_attrs ); nkeynes@103: if( visual == NULL ) { nkeynes@103: ERROR( "Unable to obtain a compatible visual" ); nkeynes@103: return FALSE; nkeynes@103: } nkeynes@103: nkeynes@103: /* And a matching gl context */ nkeynes@103: glx_context = glXCreateContext( video_x11_display, visual, None, True ); nkeynes@103: if( glx_context == NULL ) { nkeynes@103: ERROR( "Unable to obtain a GLX Context. Possibly your system is broken in some small, undefineable way" ); nkeynes@103: return FALSE; nkeynes@103: } nkeynes@103: nkeynes@103: nkeynes@103: /* Ok, all good so far. Unfortunately the visual we need to use will nkeynes@103: * almost certainly be different from the one our frame is using. Which nkeynes@103: * means we have to jump through the following hoops to create a nkeynes@103: * child window with the appropriate settings. nkeynes@103: */ nkeynes@103: win_attrs.event_mask = 0; nkeynes@103: win_attrs.colormap = XCreateColormap( video_x11_display, nkeynes@103: RootWindowOfScreen(video_x11_screen), nkeynes@103: visual->visual, AllocNone ); nkeynes@103: glx_window = XCreateWindow( video_x11_display, video_x11_window, nkeynes@103: x, y, width, height, 0, visual->depth, nkeynes@103: InputOutput, visual->visual, nkeynes@103: CWColormap | CWEventMask, nkeynes@103: &win_attrs ); nkeynes@103: if( glx_window == None ) { nkeynes@103: /* Hrm. Aww, no window? */ nkeynes@103: ERROR( "Unable to create GLX window" ); nkeynes@103: glXDestroyContext( video_x11_display, glx_context ); nkeynes@103: if( win_attrs.colormap ) nkeynes@103: XFreeColormap( video_x11_display, win_attrs.colormap ); nkeynes@103: return FALSE; nkeynes@103: } nkeynes@103: XMapRaised( video_x11_display, glx_window ); nkeynes@103: nkeynes@103: /* And finally set the window to be the active drawing area */ nkeynes@103: if( glXMakeCurrent( video_x11_display, glx_window, glx_context ) == False ) { nkeynes@103: /* Ok you have _GOT_ to be kidding me */ nkeynes@103: ERROR( "Unable to prepare GLX window for drawing" ); nkeynes@103: XDestroyWindow( video_x11_display, glx_window ); nkeynes@103: XFreeColormap( video_x11_display, win_attrs.colormap ); nkeynes@103: glXDestroyContext( video_x11_display, glx_context ); nkeynes@103: return FALSE; nkeynes@103: } nkeynes@280: nkeynes@280: hasRequiredGLExtensions(); nkeynes@280: fprintf(stderr, "GLX extensions: %s\n", glxExts ); nkeynes@103: glx_open = TRUE; nkeynes@103: return TRUE; nkeynes@103: } nkeynes@103: nkeynes@108: int video_glx_load_font( const gchar *font_name ) nkeynes@108: { nkeynes@108: int lists; nkeynes@108: XFontStruct *font = XLoadQueryFont(video_x11_display, font_name ); nkeynes@108: if (font == NULL) nkeynes@108: return -1; nkeynes@108: nkeynes@108: lists = glGenLists(96); nkeynes@108: glXUseXFont(font->fid, 32, 96, lists); nkeynes@108: XFreeFont(video_x11_display, font); nkeynes@108: } nkeynes@108: nkeynes@108: nkeynes@108: nkeynes@108: gboolean video_glx_set_render_format( int x, int y, int width, int height ) nkeynes@108: { nkeynes@108: if( glx_open ) nkeynes@108: return TRUE; nkeynes@108: return video_glx_create_window( x, y, width, height ); nkeynes@108: } nkeynes@108: nkeynes@112: gboolean video_glx_display_frame( video_buffer_t frame ) nkeynes@112: { nkeynes@112: GLenum type, format = GL_RGB; nkeynes@112: switch( frame->colour_format ) { nkeynes@112: case COLFMT_RGB565: nkeynes@112: type = GL_UNSIGNED_SHORT_5_6_5; nkeynes@112: break; nkeynes@112: case COLFMT_RGB888: nkeynes@112: type = GL_UNSIGNED_BYTE; nkeynes@112: break; nkeynes@112: case COLFMT_ARGB1555: nkeynes@112: type = GL_UNSIGNED_SHORT_5_5_5_1; nkeynes@112: break; nkeynes@112: case COLFMT_ARGB8888: nkeynes@112: format = GL_BGRA; nkeynes@112: type = GL_UNSIGNED_INT_8_8_8_8_REV; nkeynes@112: break; nkeynes@112: } nkeynes@112: glDrawBuffer( GL_FRONT ); nkeynes@112: glViewport( 0, 0, frame->hres, frame->vres ); nkeynes@112: glMatrixMode(GL_PROJECTION); nkeynes@112: glLoadIdentity(); nkeynes@112: glOrtho( 0, frame->hres, frame->vres, 0, 0, -65535 ); nkeynes@112: glMatrixMode(GL_MODELVIEW); nkeynes@112: glLoadIdentity(); nkeynes@112: glRasterPos2i( 0, 0 ); nkeynes@112: glPixelZoom( 1.0f, -1.0f ); nkeynes@112: glDrawPixels( frame->hres, frame->vres, format, type, nkeynes@112: frame->data ); nkeynes@112: glFlush(); nkeynes@112: return TRUE; nkeynes@112: } nkeynes@112: nkeynes@160: gboolean video_glx_blank( int width, int height, uint32_t colour ) nkeynes@160: { nkeynes@160: glDrawBuffer( GL_FRONT ); nkeynes@160: glViewport( 0, 0, width, height ); nkeynes@160: glMatrixMode( GL_PROJECTION ); nkeynes@160: glLoadIdentity(); nkeynes@160: glOrtho( 0, width, height, 0, 0, -65535 ); nkeynes@160: glMatrixMode(GL_MODELVIEW); nkeynes@160: glLoadIdentity(); nkeynes@160: glColor3b( (colour >> 16) & 0xFF, (colour >> 8) & 0xFF, colour & 0xFF ); nkeynes@160: glRecti(0,0, width, height ); nkeynes@160: glFlush(); nkeynes@160: return TRUE; nkeynes@160: } nkeynes@160: nkeynes@103: void video_glx_swap_buffers( void ) nkeynes@103: { nkeynes@103: glXSwapBuffers( video_x11_display, glx_window ); nkeynes@103: } nkeynes@103: nkeynes@103: void video_glx_create_pixmap( int width, int height ) nkeynes@103: { nkeynes@103: nkeynes@103: }