filename | src/drivers/video_x11.c |
changeset | 370:3131ba1440fc |
prev | 352:f0df7a6d4703 |
next | 405:570d93abb5b7 |
author | nkeynes |
date | Sat Sep 08 04:05:35 2007 +0000 (15 years ago) |
permissions | -rw-r--r-- |
last change | Handle video driver init failure cleanly (fallback to headless) Hookup shutdown for the GTK driver |
view | annotate | diff | log | raw |
1 /**
2 * $Id: video_x11.c,v 1.13 2007-09-08 04:05:35 nkeynes Exp $
3 *
4 * Shared functions for all X11-based display drivers.
5 *
6 * Copyright (c) 2005 Nathan Keynes.
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 */
19 #include <X11/Xlib.h>
20 #include <GL/glx.h>
21 #include "dream.h"
22 #include "drivers/video_x11.h"
24 extern uint32_t video_width, video_height;
26 /**
27 * General X11 parameters. The front-end driver is expected to set this up
28 * by calling video_glx_init after initializing itself.
29 */
30 static Display *video_x11_display = NULL;
31 static Screen *video_x11_screen = NULL;
32 static Window video_x11_window = 0;
34 /**
35 * GLX parameters.
36 */
37 static GLXContext glx_context;
38 static Window glx_window;
39 static XSetWindowAttributes win_attrs;
41 gboolean video_glx_init( Display *display, Screen *screen, Window window,
42 int width, int height, display_driver_t driver )
43 {
44 video_x11_display = display;
45 video_x11_screen = screen;
46 video_x11_window = window;
48 if( !video_glx_create_window(width,height) ) {
49 return FALSE;
50 }
52 if( gl_fbo_is_supported() ) {
53 gl_fbo_init(driver);
54 return TRUE;
55 } else {
56 /* Pbuffers? */
57 ERROR( "Framebuffer objects not supported (required in this version)" );
58 video_glx_shutdown();
59 return FALSE;
60 }
61 }
63 gboolean video_glx_create_window( int width, int height )
64 {
65 int major, minor;
66 const char *glxExts, *glxServer;
67 int visual_attrs[] = { GLX_RGBA, GLX_RED_SIZE, 4,
68 GLX_GREEN_SIZE, 4,
69 GLX_BLUE_SIZE, 4,
70 GLX_ALPHA_SIZE, 4,
71 GLX_DEPTH_SIZE, 24,
72 GLX_DOUBLEBUFFER,
73 None };
74 int screen = XScreenNumberOfScreen(video_x11_screen);
75 XVisualInfo *visual;
77 if( glXQueryVersion( video_x11_display, &major, &minor ) == False ) {
78 ERROR( "X Display lacks the GLX nature" );
79 return FALSE;
80 }
81 if( major < 1 || minor < 2 ) {
82 ERROR( "X display supports GLX %d.%d, but we need at least 1.2", major, minor );
83 return FALSE;
84 }
86 /* Find ourselves a nice visual */
87 visual = glXChooseVisual( video_x11_display,
88 screen,
89 visual_attrs );
90 if( visual == NULL ) {
91 ERROR( "Unable to obtain a compatible visual" );
92 return FALSE;
93 }
95 /* And a matching gl context */
96 glx_context = glXCreateContext( video_x11_display, visual, None, True );
97 if( glx_context == NULL ) {
98 ERROR( "Unable to obtain a GLX Context. Possibly your system is broken in some small, undefineable way" );
99 return FALSE;
100 }
103 /* Ok, all good so far. Unfortunately the visual we need to use will
104 * almost certainly be different from the one our frame is using. Which
105 * means we have to jump through the following hoops to create a
106 * child window with the appropriate settings.
107 */
108 win_attrs.event_mask = 0;
109 win_attrs.colormap = XCreateColormap( video_x11_display,
110 RootWindowOfScreen(video_x11_screen),
111 visual->visual, AllocNone );
112 glx_window = XCreateWindow( video_x11_display, video_x11_window,
113 0, 0, width, height, 0, visual->depth,
114 InputOutput, visual->visual,
115 CWColormap | CWEventMask,
116 &win_attrs );
117 if( glx_window == None ) {
118 /* Hrm. Aww, no window? */
119 ERROR( "Unable to create GLX window" );
120 glXDestroyContext( video_x11_display, glx_context );
121 if( win_attrs.colormap )
122 XFreeColormap( video_x11_display, win_attrs.colormap );
123 return FALSE;
124 }
125 XMapRaised( video_x11_display, glx_window );
127 /* And finally set the window to be the active drawing area */
128 if( glXMakeCurrent( video_x11_display, glx_window, glx_context ) == False ) {
129 /* Ok you have _GOT_ to be kidding me */
130 ERROR( "Unable to prepare GLX window for drawing" );
131 XDestroyWindow( video_x11_display, glx_window );
132 XFreeColormap( video_x11_display, win_attrs.colormap );
133 glXDestroyContext( video_x11_display, glx_context );
134 return FALSE;
135 }
136 return TRUE;
137 }
139 void video_glx_shutdown()
140 {
141 if( glx_window != None ) {
142 XDestroyWindow( video_x11_display, glx_window );
143 XFreeColormap( video_x11_display, win_attrs.colormap );
144 glx_window = None;
145 }
146 if( glx_context != NULL ) {
147 glXDestroyContext( video_x11_display, glx_context );
148 glx_context = NULL;
149 }
150 }
153 int video_glx_load_font( const gchar *font_name )
154 {
155 int lists;
156 XFontStruct *font = XLoadQueryFont(video_x11_display, font_name );
157 if (font == NULL)
158 return -1;
160 lists = glGenLists(96);
161 glXUseXFont(font->fid, 32, 96, lists);
162 XFreeFont(video_x11_display, font);
163 }
166 void video_glx_swap_buffers( void )
167 {
168 glXSwapBuffers( video_x11_display, glx_window );
169 }
.