nkeynes@94: /** nkeynes@108: * $Id: video_x11.c,v 1.3 2006-03-15 13:16:46 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@103: #include "video.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@103: 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@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: }