Search
lxdream.org :: lxdream/src/drivers/video_x11.c
lxdream 0.9.1
released Jun 29
Download Now
filename src/drivers/video_x11.c
changeset 531:f0fee3ba71d1
prev481:3b2d6c5a19ad
author nkeynes
date Thu Nov 22 11:10:15 2007 +0000 (16 years ago)
permissions -rw-r--r--
last change Re-add "Load Binary" menu item (misplaced in GUI rewrite)
Prevent running with no code loaded
file annotate diff log raw
nkeynes@94
     1
/**
nkeynes@481
     2
 * $Id: video_x11.c,v 1.20 2007-10-31 12:05:23 nkeynes Exp $
nkeynes@94
     3
 *
nkeynes@103
     4
 * Shared functions for all X11-based display drivers.
nkeynes@94
     5
 *
nkeynes@94
     6
 * Copyright (c) 2005 Nathan Keynes.
nkeynes@94
     7
 *
nkeynes@94
     8
 * This program is free software; you can redistribute it and/or modify
nkeynes@94
     9
 * it under the terms of the GNU General Public License as published by
nkeynes@94
    10
 * the Free Software Foundation; either version 2 of the License, or
nkeynes@94
    11
 * (at your option) any later version.
nkeynes@94
    12
 *
nkeynes@94
    13
 * This program is distributed in the hope that it will be useful,
nkeynes@94
    14
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
nkeynes@94
    15
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
nkeynes@94
    16
 * GNU General Public License for more details.
nkeynes@94
    17
 */
nkeynes@94
    18
nkeynes@103
    19
#include <X11/Xlib.h>
nkeynes@103
    20
#include <GL/glx.h>
nkeynes@103
    21
#include "dream.h"
nkeynes@531
    22
#include "pvr2/pvr2.h"
nkeynes@94
    23
#include "drivers/video_x11.h"
nkeynes@405
    24
#include "drivers/gl_common.h"
nkeynes@94
    25
nkeynes@352
    26
extern uint32_t video_width, video_height;
nkeynes@352
    27
nkeynes@103
    28
/**
nkeynes@103
    29
 * General X11 parameters. The front-end driver is expected to set this up
nkeynes@352
    30
 * by calling video_glx_init after initializing itself.
nkeynes@103
    31
 */
nkeynes@352
    32
static Display *video_x11_display = NULL;
nkeynes@352
    33
static Screen *video_x11_screen = NULL;
nkeynes@352
    34
static Window video_x11_window = 0;
nkeynes@405
    35
static gboolean glsl_loaded = FALSE;
nkeynes@352
    36
nkeynes@103
    37
/**
nkeynes@103
    38
 * GLX parameters.
nkeynes@103
    39
 */
nkeynes@352
    40
static GLXContext glx_context;
nkeynes@352
    41
static Window glx_window;
nkeynes@352
    42
static XSetWindowAttributes win_attrs;
nkeynes@103
    43
nkeynes@424
    44
gboolean video_glx_create_window( int width, int height );
nkeynes@481
    45
gboolean video_glx_init_context( Window window );
nkeynes@424
    46
nkeynes@352
    47
gboolean video_glx_init( Display *display, Screen *screen, Window window,
nkeynes@352
    48
			 int width, int height, display_driver_t driver )
nkeynes@94
    49
{
nkeynes@94
    50
    video_x11_display = display;
nkeynes@94
    51
    video_x11_screen = screen;
nkeynes@442
    52
    glx_window = video_x11_window = window;
nkeynes@352
    53
nkeynes@442
    54
    if( !video_glx_init_context(glx_window) ) {
nkeynes@352
    55
	return FALSE;
nkeynes@352
    56
    }
nkeynes@352
    57
nkeynes@478
    58
    if( !glXIsDirect(video_x11_display, glx_context) ) {
nkeynes@478
    59
    	WARN( "Not using direct rendering - this is likely to be slow" );
nkeynes@478
    60
    }
nkeynes@478
    61
nkeynes@352
    62
    if( gl_fbo_is_supported() ) {
nkeynes@352
    63
	gl_fbo_init(driver);
nkeynes@405
    64
nkeynes@405
    65
#ifdef USE_GLSL
nkeynes@405
    66
	if( glsl_is_supported() ) {
nkeynes@405
    67
	    glsl_loaded = glsl_load_shaders( glsl_vertex_shader_src, glsl_fragment_shader_src );
nkeynes@405
    68
	    if( !glsl_loaded ) {
nkeynes@405
    69
	        WARN( "Shaders failed to load" );
nkeynes@405
    70
	    }
nkeynes@405
    71
	} else {
nkeynes@405
    72
	    WARN( "Shaders not supported" );
nkeynes@405
    73
	}
nkeynes@405
    74
#endif
nkeynes@352
    75
	return TRUE;
nkeynes@352
    76
    } else {
nkeynes@352
    77
	/* Pbuffers? */
nkeynes@352
    78
	ERROR( "Framebuffer objects not supported (required in this version)" );
nkeynes@352
    79
	video_glx_shutdown();
nkeynes@352
    80
	return FALSE;
nkeynes@352
    81
    }
nkeynes@94
    82
}
nkeynes@94
    83
nkeynes@442
    84
/**
nkeynes@442
    85
 * Create a new window with a custom visual - not used at the moment,
nkeynes@442
    86
 * but retained for future reference.
nkeynes@442
    87
 */
nkeynes@442
    88
gboolean video_x11_create_window( int width, int height )
nkeynes@103
    89
{
nkeynes@103
    90
    int visual_attrs[] = { GLX_RGBA, GLX_RED_SIZE, 4, 
nkeynes@103
    91
			   GLX_GREEN_SIZE, 4, 
nkeynes@103
    92
			   GLX_BLUE_SIZE, 4,
nkeynes@103
    93
			   GLX_ALPHA_SIZE, 4,
nkeynes@335
    94
			   GLX_DEPTH_SIZE, 24,
nkeynes@103
    95
			   GLX_DOUBLEBUFFER, 
nkeynes@103
    96
			   None };
nkeynes@103
    97
    int screen = XScreenNumberOfScreen(video_x11_screen);
nkeynes@103
    98
    XVisualInfo *visual;
nkeynes@442
    99
    /* Find ourselves a nice visual */
nkeynes@442
   100
    visual = glXChooseVisual( video_x11_display, 
nkeynes@442
   101
			      screen,
nkeynes@442
   102
			      visual_attrs );
nkeynes@103
   103
nkeynes@442
   104
    /* Create a child window with the visual in question */
nkeynes@103
   105
    win_attrs.event_mask = 0;
nkeynes@103
   106
    win_attrs.colormap = XCreateColormap( video_x11_display, 
nkeynes@103
   107
					  RootWindowOfScreen(video_x11_screen),
nkeynes@103
   108
					  visual->visual, AllocNone );
nkeynes@103
   109
    glx_window = XCreateWindow( video_x11_display, video_x11_window, 
nkeynes@352
   110
				0, 0, width, height, 0, visual->depth, 
nkeynes@103
   111
				InputOutput, visual->visual, 
nkeynes@103
   112
				CWColormap | CWEventMask, 
nkeynes@103
   113
				&win_attrs );
nkeynes@103
   114
    if( glx_window == None ) {
nkeynes@103
   115
	/* Hrm. Aww, no window? */
nkeynes@103
   116
	ERROR( "Unable to create GLX window" );
nkeynes@103
   117
	if( win_attrs.colormap ) 
nkeynes@103
   118
	    XFreeColormap( video_x11_display, win_attrs.colormap );
nkeynes@442
   119
	XFree(visual);
nkeynes@103
   120
	return FALSE;
nkeynes@103
   121
    }
nkeynes@103
   122
    XMapRaised( video_x11_display, glx_window );
nkeynes@439
   123
nkeynes@442
   124
    XFree(visual);
nkeynes@442
   125
    return TRUE;
nkeynes@442
   126
}
nkeynes@439
   127
nkeynes@442
   128
gboolean video_glx_init_context( Window window )
nkeynes@442
   129
{
nkeynes@442
   130
    XWindowAttributes attr;
nkeynes@442
   131
    XVisualInfo *visual;
nkeynes@442
   132
    XVisualInfo query;
nkeynes@442
   133
    int query_items = 1;
nkeynes@442
   134
nkeynes@442
   135
    XGetWindowAttributes(video_x11_display, window, &attr);
nkeynes@442
   136
    
nkeynes@442
   137
    query.visualid = XVisualIDFromVisual(attr.visual);
nkeynes@442
   138
    visual = XGetVisualInfo(video_x11_display, VisualIDMask, &query, &query_items );
nkeynes@442
   139
    if( visual == NULL ) {
nkeynes@442
   140
	ERROR( "Unable to obtain a compatible visual" );
nkeynes@103
   141
	return FALSE;
nkeynes@103
   142
    }
nkeynes@442
   143
nkeynes@442
   144
    int major, minor;
nkeynes@442
   145
    if( glXQueryVersion( video_x11_display, &major, &minor ) == False ) {
nkeynes@442
   146
	ERROR( "X Display lacks the GLX nature" );
nkeynes@442
   147
	XFree(visual);
nkeynes@442
   148
	return FALSE;
nkeynes@442
   149
    }
nkeynes@442
   150
    if( major < 1 || minor < 2 ) {
nkeynes@442
   151
	ERROR( "X display supports GLX %d.%d, but we need at least 1.2", major, minor );
nkeynes@442
   152
	XFree(visual);
nkeynes@442
   153
	return FALSE;
nkeynes@442
   154
    }
nkeynes@442
   155
nkeynes@442
   156
    /* And a matching gl context */
nkeynes@442
   157
    glx_context = glXCreateContext( video_x11_display, visual, None, True );
nkeynes@442
   158
    if( glx_context == NULL ) {
nkeynes@442
   159
	ERROR( "Unable to obtain a GLX Context. Possibly your system is broken in some small, undefineable way" );
nkeynes@442
   160
	XFree(visual);
nkeynes@442
   161
	return FALSE;
nkeynes@442
   162
    }
nkeynes@442
   163
nkeynes@442
   164
    if( glXMakeCurrent( video_x11_display, window, glx_context ) == False ) {
nkeynes@442
   165
	ERROR( "Unable to prepare GLX context for drawing" );
nkeynes@442
   166
	glXDestroyContext( video_x11_display, glx_context );
nkeynes@442
   167
	XFree(visual);
nkeynes@442
   168
	return FALSE;
nkeynes@442
   169
    }
nkeynes@442
   170
    XFree(visual);
nkeynes@531
   171
nkeynes@531
   172
    texcache_gl_init();
nkeynes@103
   173
    return TRUE;
nkeynes@103
   174
}
nkeynes@370
   175
nkeynes@442
   176
nkeynes@352
   177
void video_glx_shutdown()
nkeynes@352
   178
{
nkeynes@405
   179
    if( glsl_loaded ) {
nkeynes@405
   180
	glsl_unload_shaders();
nkeynes@405
   181
    }
nkeynes@370
   182
    if( glx_window != None ) {
nkeynes@370
   183
	XDestroyWindow( video_x11_display, glx_window );
nkeynes@370
   184
	XFreeColormap( video_x11_display, win_attrs.colormap );
nkeynes@370
   185
	glx_window = None;
nkeynes@370
   186
    }
nkeynes@370
   187
    if( glx_context != NULL ) {
nkeynes@370
   188
	glXDestroyContext( video_x11_display, glx_context );
nkeynes@370
   189
	glx_context = NULL;
nkeynes@370
   190
    }
nkeynes@352
   191
}
nkeynes@352
   192
nkeynes@103
   193
nkeynes@108
   194
int video_glx_load_font( const gchar *font_name )
nkeynes@108
   195
{
nkeynes@108
   196
    int lists;
nkeynes@108
   197
    XFontStruct *font = XLoadQueryFont(video_x11_display, font_name );
nkeynes@108
   198
    if (font == NULL)
nkeynes@108
   199
	return -1;
nkeynes@108
   200
    
nkeynes@108
   201
    lists = glGenLists(96);
nkeynes@108
   202
    glXUseXFont(font->fid, 32, 96, lists);
nkeynes@108
   203
    XFreeFont(video_x11_display, font);
nkeynes@424
   204
    return lists;
nkeynes@108
   205
}
nkeynes@108
   206
nkeynes@108
   207
nkeynes@103
   208
void video_glx_swap_buffers( void )
nkeynes@103
   209
{
nkeynes@103
   210
    glXSwapBuffers( video_x11_display, glx_window );
nkeynes@103
   211
}
nkeynes@103
   212
.