Search
lxdream.org :: lxdream/src/drivers/gl_common.c
lxdream 0.9.1
released Jun 29
Download Now
filename src/drivers/gl_common.c
changeset 443:1163eb5c0590
prev429:e581b90c3fb3
next444:74c38d57eb11
author nkeynes
date Sat Oct 13 04:01:02 2007 +0000 (16 years ago)
permissions -rw-r--r--
last change Add ability to track the last displayed buffer, and handle expose/resize
events appropriately
view annotate diff log raw
     1 /**
     2  * $Id: gl_common.c,v 1.4 2007-10-13 04:01:02 nkeynes Exp $
     3  *
     4  * Common GL code that doesn't depend on a specific implementation
     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 <sys/time.h>
    21 #include <GL/gl.h>
    22 #include "dream.h"
    23 #include "drivers/gl_common.h"
    25 extern uint32_t video_width, video_height;
    26 static GLuint frame_last_texid = 0, fbuf_id = 0;
    27 static uint32_t frame_width = 0;
    28 static uint32_t frame_height = 0;
    29 static uint32_t frame_colour = 0;
    30 static gboolean frame_inverted = FALSE;
    34 char *required_extensions[] = { "GL_EXT_framebuffer_object", NULL };
    36 /**
    37  * Test if a specific extension is supported. From opengl.org
    38  * @param extension extension name to check for
    39  * @return TRUE if supported, otherwise FALSE.
    40  */
    41 gboolean isGLExtensionSupported( const char *extension )
    42 {
    43     const GLubyte *extensions = NULL;
    44     const GLubyte *start;
    45     GLubyte *where, *terminator;
    47     /* Extension names should not have spaces. */
    48     where = (GLubyte *) strchr(extension, ' ');
    49     if (where || *extension == '\0')
    50 	return 0;
    51     extensions = glGetString(GL_EXTENSIONS);
    52     /* It takes a bit of care to be fool-proof about parsing the
    53        OpenGL extensions string. Don't be fooled by sub-strings,
    54        etc. */
    55     start = extensions;
    56     for (;;) {
    57 	where = (GLubyte *) strstr((const char *) start, extension);
    58 	if (!where)
    59 	    break;
    60 	terminator = where + strlen(extension);
    61 	if (where == start || *(where - 1) == ' ')
    62 	    if (*terminator == ' ' || *terminator == '\0')
    63 		return TRUE;
    64 	start = terminator;
    65     }
    66     return FALSE;
    67 }
    69 gboolean hasRequiredGLExtensions( ) 
    70 {
    71     int i;
    72     gboolean isOK = TRUE;
    74     for( i=0; required_extensions[i] != NULL; i++ ) {
    75 	if( !isGLExtensionSupported(required_extensions[i]) ) {
    76 	    ERROR( "Required OpenGL extension not supported: %s", required_extensions[i] );
    77 	    isOK = FALSE;
    78 	}
    79     }
    80     return isOK;
    81 }
    83 void gl_frame_buffer_to_tex_rectangle( frame_buffer_t frame, GLuint texid )
    84 {
    85     GLenum type = colour_formats[frame->colour_format].type;
    86     GLenum format = colour_formats[frame->colour_format].format;
    87     int bpp = colour_formats[frame->colour_format].bpp;
    88     int rowstride = (frame->rowstride / bpp) - frame->width;
    90     glPixelStorei( GL_UNPACK_ROW_LENGTH, rowstride );
    91     glBindTexture( GL_TEXTURE_RECTANGLE_ARB, texid );
    92     glTexImage2D( GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGB,
    93 		  frame->width, frame->height, 0, format, type, frame->data );
    94 }
    96 void gl_display_tex_rectangle( GLuint texid, uint32_t tex_width, uint32_t tex_height, gboolean invert )
    97 {
    98     float top, bottom;
    99     if( invert ) {
   100 	top = ((float)tex_height) - 0.5;
   101 	bottom = 0.5;
   102     } else {
   103 	top = 0.5;
   104 	bottom = ((float)tex_height) - 0.5;
   105     }
   107     /* Reset display parameters */
   108     glViewport( 0, 0, video_width, video_height );
   109     glMatrixMode(GL_PROJECTION);
   110     glLoadIdentity();
   111     glOrtho( 0, video_width, video_height, 0, 0, -65535 );
   112     glMatrixMode(GL_MODELVIEW);
   113     glLoadIdentity();
   114     glDisable( GL_TEXTURE_2D );
   115     glDisable( GL_ALPHA_TEST );
   116     glDisable( GL_DEPTH_TEST );
   117     glDisable( GL_SCISSOR_TEST );
   118     glDisable( GL_CULL_FACE );
   120     /* Render the textured rectangle */
   121     glEnable( GL_TEXTURE_RECTANGLE_ARB );
   122     glBindTexture( GL_TEXTURE_RECTANGLE_ARB, texid );
   123     glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE );
   124     glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
   125     glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
   126     glEnable( GL_BLEND );
   127     glBlendFunc( GL_ONE, GL_ZERO );
   128     glBegin( GL_QUADS );
   129     glTexCoord2f( 0.5, top );
   130     glVertex2f( 0.0, 0.0 );
   131     glTexCoord2f( ((float)tex_width)-0.5, top );
   132     glVertex2f( video_width, 0.0 );
   133     glTexCoord2f( ((float)tex_width)-0.5, bottom );
   134     glVertex2f( video_width, video_height );
   135     glTexCoord2f( 0.5, bottom );
   136     glVertex2f( 0.0, video_height );
   137     glEnd();
   138     glDisable( GL_TEXTURE_RECTANGLE_ARB );
   139     glFlush();
   140     frame_last_texid = texid;
   141     frame_width = tex_width;
   142     frame_height = tex_height;
   143     frame_inverted = invert;
   144 }
   146 gboolean gl_display_frame_buffer( frame_buffer_t frame )
   147 {
   148     if( fbuf_id == 0 ) {
   149 	glGenTextures( 1, &fbuf_id );
   150     }
   151     gl_frame_buffer_to_tex_rectangle( frame, fbuf_id );
   152     gl_display_tex_rectangle( fbuf_id, frame->width, frame->height, FALSE );
   153     return TRUE;
   154 }
   156 gboolean gl_display_blank( uint32_t colour )
   157 {
   158     glViewport( 0, 0, video_width, video_height );
   159     glMatrixMode( GL_PROJECTION );
   160     glLoadIdentity();
   161     glOrtho( 0, video_width, video_height, 0, 0, -65535 );
   162     glMatrixMode(GL_MODELVIEW);
   163     glLoadIdentity();
   164     glColor3b( (colour >> 16) & 0xFF, (colour >> 8) & 0xFF, colour & 0xFF );
   165     glRecti(0,0, video_width, video_height );
   166     glFlush();
   167     frame_colour = colour;
   168     frame_last_texid = 0;
   169     return TRUE;
   170 }
   172 void gl_redisplay_last()
   173 {
   174     if( frame_last_texid == 0 ) {
   175 	gl_display_blank( frame_colour );
   176     } else {
   177 	gl_display_tex_rectangle( frame_last_texid, frame_width, frame_height, frame_inverted );
   178     }
   179 }
   181 /**
   182  * Generic GL read_render_buffer. This function assumes that the caller
   183  * has already set the appropriate glReadBuffer(); in other words, unless
   184  * there's only one buffer this needs to be wrapped.
   185  */
   186 gboolean gl_read_render_buffer( render_buffer_t buffer, unsigned char *target ) 
   187 {
   188     if( buffer->address == -1 )
   189 	return FALSE;
   190     glFinish();
   191     GLenum type = colour_formats[buffer->colour_format].type;
   192     GLenum format = colour_formats[buffer->colour_format].format;
   193     // int line_size = buffer->width * colour_formats[buffer->colour_format].bpp;
   194     // int size = line_size * buffer->height;
   195     // int rowstride = (buffer->rowstride / colour_formats[buffer->colour_format].bpp) - buffer->width;
   196     // glPixelStorei( GL_PACK_ROW_LENGTH, rowstride );
   198     glReadPixels( 0, 0, buffer->width, buffer->height, format, type, target );
   199     return TRUE;
   200 }
.