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 352:f0df7a6d4703
prev335:fb890e1814c0
next370:3131ba1440fc
author nkeynes
date Sun Feb 11 10:09:32 2007 +0000 (12 years ago)
permissions -rw-r--r--
last change Bug 27: Implement opengl framebuffer objects
Rewrite much of the final video output stage. Now uses generic "render
buffers", implemented on GL using framebuffer objects + textures.
file annotate diff log raw
nkeynes@94
     1
/**
nkeynes@352
     2
 * $Id: video_x11.c,v 1.12 2007-02-11 10:09:32 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@94
    22
#include "drivers/video_x11.h"
nkeynes@94
    23
nkeynes@352
    24
extern uint32_t video_width, video_height;
nkeynes@352
    25
nkeynes@103
    26
/**
nkeynes@103
    27
 * General X11 parameters. The front-end driver is expected to set this up
nkeynes@352
    28
 * by calling video_glx_init after initializing itself.
nkeynes@103
    29
 */
nkeynes@352
    30
static Display *video_x11_display = NULL;
nkeynes@352
    31
static Screen *video_x11_screen = NULL;
nkeynes@352
    32
static Window video_x11_window = 0;
nkeynes@352
    33
nkeynes@103
    34
/**
nkeynes@103
    35
 * GLX parameters.
nkeynes@103
    36
 */
nkeynes@352
    37
static GLXContext glx_context;
nkeynes@352
    38
static Window glx_window;
nkeynes@352
    39
static XSetWindowAttributes win_attrs;
nkeynes@103
    40
nkeynes@352
    41
gboolean video_glx_init( Display *display, Screen *screen, Window window,
nkeynes@352
    42
			 int width, int height, display_driver_t driver )
nkeynes@94
    43
{
nkeynes@94
    44
    video_x11_display = display;
nkeynes@94
    45
    video_x11_screen = screen;
nkeynes@94
    46
    video_x11_window = window;
nkeynes@352
    47
nkeynes@352
    48
    if( !video_glx_create_window(width,height) ) {
nkeynes@352
    49
	return FALSE;
nkeynes@352
    50
    }
nkeynes@352
    51
nkeynes@352
    52
    if( gl_fbo_is_supported() ) {
nkeynes@352
    53
	gl_fbo_init(driver);
nkeynes@352
    54
	return TRUE;
nkeynes@352
    55
    } else {
nkeynes@352
    56
	/* Pbuffers? */
nkeynes@352
    57
	ERROR( "Framebuffer objects not supported (required in this version)" );
nkeynes@352
    58
	video_glx_shutdown();
nkeynes@352
    59
	return FALSE;
nkeynes@352
    60
    }
nkeynes@94
    61
}
nkeynes@94
    62
nkeynes@352
    63
gboolean video_glx_create_window( int width, int height )
nkeynes@103
    64
{
nkeynes@103
    65
    int major, minor;
nkeynes@103
    66
    const char *glxExts, *glxServer;
nkeynes@103
    67
    int visual_attrs[] = { GLX_RGBA, GLX_RED_SIZE, 4, 
nkeynes@103
    68
			   GLX_GREEN_SIZE, 4, 
nkeynes@103
    69
			   GLX_BLUE_SIZE, 4,
nkeynes@103
    70
			   GLX_ALPHA_SIZE, 4,
nkeynes@335
    71
			   GLX_DEPTH_SIZE, 24,
nkeynes@103
    72
			   GLX_DOUBLEBUFFER, 
nkeynes@103
    73
			   None };
nkeynes@103
    74
    int screen = XScreenNumberOfScreen(video_x11_screen);
nkeynes@103
    75
    XVisualInfo *visual;
nkeynes@103
    76
nkeynes@103
    77
    if( glXQueryVersion( video_x11_display, &major, &minor ) == False ) {
nkeynes@103
    78
	ERROR( "X Display lacks the GLX nature" );
nkeynes@103
    79
	return FALSE;
nkeynes@103
    80
    }
nkeynes@103
    81
    if( major < 1 || minor < 2 ) {
nkeynes@103
    82
	ERROR( "X display supports GLX %d.%d, but we need at least 1.2", major, minor );
nkeynes@103
    83
	return FALSE;
nkeynes@103
    84
    }
nkeynes@103
    85
nkeynes@103
    86
    /* Find ourselves a nice visual */
nkeynes@103
    87
    visual = glXChooseVisual( video_x11_display, 
nkeynes@103
    88
			      screen,
nkeynes@103
    89
			      visual_attrs );
nkeynes@103
    90
    if( visual == NULL ) {
nkeynes@103
    91
	ERROR( "Unable to obtain a compatible visual" );
nkeynes@103
    92
	return FALSE;
nkeynes@103
    93
    }
nkeynes@103
    94
nkeynes@103
    95
    /* And a matching gl context */
nkeynes@103
    96
    glx_context = glXCreateContext( video_x11_display, visual, None, True );
nkeynes@103
    97
    if( glx_context == NULL ) {
nkeynes@103
    98
	ERROR( "Unable to obtain a GLX Context. Possibly your system is broken in some small, undefineable way" );
nkeynes@103
    99
	return FALSE;
nkeynes@103
   100
    }
nkeynes@103
   101
    
nkeynes@103
   102
nkeynes@103
   103
    /* Ok, all good so far. Unfortunately the visual we need to use will 
nkeynes@103
   104
     * almost certainly be different from the one our frame is using. Which 
nkeynes@103
   105
     * means we have to jump through the following hoops to create a 
nkeynes@103
   106
     * child window with the appropriate settings.
nkeynes@103
   107
     */
nkeynes@103
   108
    win_attrs.event_mask = 0;
nkeynes@103
   109
    win_attrs.colormap = XCreateColormap( video_x11_display, 
nkeynes@103
   110
					  RootWindowOfScreen(video_x11_screen),
nkeynes@103
   111
					  visual->visual, AllocNone );
nkeynes@103
   112
    glx_window = XCreateWindow( video_x11_display, video_x11_window, 
nkeynes@352
   113
				0, 0, width, height, 0, visual->depth, 
nkeynes@103
   114
				InputOutput, visual->visual, 
nkeynes@103
   115
				CWColormap | CWEventMask, 
nkeynes@103
   116
				&win_attrs );
nkeynes@103
   117
    if( glx_window == None ) {
nkeynes@103
   118
	/* Hrm. Aww, no window? */
nkeynes@103
   119
	ERROR( "Unable to create GLX window" );
nkeynes@103
   120
	glXDestroyContext( video_x11_display, glx_context );
nkeynes@103
   121
	if( win_attrs.colormap ) 
nkeynes@103
   122
	    XFreeColormap( video_x11_display, win_attrs.colormap );
nkeynes@103
   123
	return FALSE;
nkeynes@103
   124
    }
nkeynes@103
   125
    XMapRaised( video_x11_display, glx_window );
nkeynes@103
   126
nkeynes@103
   127
    /* And finally set the window to be the active drawing area */
nkeynes@103
   128
    if( glXMakeCurrent( video_x11_display, glx_window, glx_context ) == False ) {
nkeynes@103
   129
	/* Ok you have _GOT_ to be kidding me */
nkeynes@103
   130
	ERROR( "Unable to prepare GLX window for drawing" );
nkeynes@103
   131
	XDestroyWindow( video_x11_display, glx_window );
nkeynes@103
   132
	XFreeColormap( video_x11_display, win_attrs.colormap );
nkeynes@103
   133
	glXDestroyContext( video_x11_display, glx_context );
nkeynes@103
   134
	return FALSE;
nkeynes@103
   135
    }
nkeynes@103
   136
    return TRUE;
nkeynes@103
   137
}
nkeynes@352
   138
void video_glx_shutdown()
nkeynes@352
   139
{
nkeynes@352
   140
    XDestroyWindow( video_x11_display, glx_window );
nkeynes@352
   141
    XFreeColormap( video_x11_display, win_attrs.colormap );
nkeynes@352
   142
    glXDestroyContext( video_x11_display, glx_context );
nkeynes@352
   143
}
nkeynes@352
   144
nkeynes@103
   145
nkeynes@108
   146
int video_glx_load_font( const gchar *font_name )
nkeynes@108
   147
{
nkeynes@108
   148
    int lists;
nkeynes@108
   149
    XFontStruct *font = XLoadQueryFont(video_x11_display, font_name );
nkeynes@108
   150
    if (font == NULL)
nkeynes@108
   151
	return -1;
nkeynes@108
   152
    
nkeynes@108
   153
    lists = glGenLists(96);
nkeynes@108
   154
    glXUseXFont(font->fid, 32, 96, lists);
nkeynes@108
   155
    XFreeFont(video_x11_display, font);
nkeynes@108
   156
}
nkeynes@108
   157
nkeynes@108
   158
nkeynes@103
   159
void video_glx_swap_buffers( void )
nkeynes@103
   160
{
nkeynes@103
   161
    glXSwapBuffers( video_x11_display, glx_window );
nkeynes@103
   162
}
nkeynes@103
   163
.