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 444:74c38d57eb11
prev443:1163eb5c0590
next477:9a373f2ff009
author nkeynes
date Sun Oct 14 09:30:16 2007 +0000 (14 years ago)
permissions -rw-r--r--
last change Maintain aspect ratio when resizing (draw black-bars to the sides when needed)
file annotate diff log raw
nkeynes@352
     1
/**
nkeynes@444
     2
 * $Id: gl_common.c,v 1.5 2007-10-14 09:30:16 nkeynes Exp $
nkeynes@352
     3
 *
nkeynes@352
     4
 * Common GL code that doesn't depend on a specific implementation
nkeynes@352
     5
 *
nkeynes@352
     6
 * Copyright (c) 2005 Nathan Keynes.
nkeynes@352
     7
 *
nkeynes@352
     8
 * This program is free software; you can redistribute it and/or modify
nkeynes@352
     9
 * it under the terms of the GNU General Public License as published by
nkeynes@352
    10
 * the Free Software Foundation; either version 2 of the License, or
nkeynes@352
    11
 * (at your option) any later version.
nkeynes@352
    12
 *
nkeynes@352
    13
 * This program is distributed in the hope that it will be useful,
nkeynes@352
    14
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
nkeynes@352
    15
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
nkeynes@352
    16
 * GNU General Public License for more details.
nkeynes@352
    17
 */
nkeynes@352
    18
nkeynes@443
    19
#include <sys/time.h>
nkeynes@443
    20
nkeynes@352
    21
#include <GL/gl.h>
nkeynes@352
    22
#include "dream.h"
nkeynes@352
    23
#include "drivers/gl_common.h"
nkeynes@352
    24
nkeynes@352
    25
extern uint32_t video_width, video_height;
nkeynes@443
    26
static GLuint frame_last_texid = 0, fbuf_id = 0;
nkeynes@443
    27
static uint32_t frame_width = 0;
nkeynes@443
    28
static uint32_t frame_height = 0;
nkeynes@443
    29
static uint32_t frame_colour = 0;
nkeynes@443
    30
static gboolean frame_inverted = FALSE;
nkeynes@443
    31
nkeynes@443
    32
nkeynes@352
    33
nkeynes@352
    34
char *required_extensions[] = { "GL_EXT_framebuffer_object", NULL };
nkeynes@352
    35
nkeynes@352
    36
/**
nkeynes@352
    37
 * Test if a specific extension is supported. From opengl.org
nkeynes@352
    38
 * @param extension extension name to check for
nkeynes@352
    39
 * @return TRUE if supported, otherwise FALSE.
nkeynes@352
    40
 */
nkeynes@352
    41
gboolean isGLExtensionSupported( const char *extension )
nkeynes@352
    42
{
nkeynes@352
    43
    const GLubyte *extensions = NULL;
nkeynes@352
    44
    const GLubyte *start;
nkeynes@352
    45
    GLubyte *where, *terminator;
nkeynes@352
    46
nkeynes@352
    47
    /* Extension names should not have spaces. */
nkeynes@352
    48
    where = (GLubyte *) strchr(extension, ' ');
nkeynes@352
    49
    if (where || *extension == '\0')
nkeynes@352
    50
	return 0;
nkeynes@352
    51
    extensions = glGetString(GL_EXTENSIONS);
nkeynes@352
    52
    /* It takes a bit of care to be fool-proof about parsing the
nkeynes@352
    53
       OpenGL extensions string. Don't be fooled by sub-strings,
nkeynes@352
    54
       etc. */
nkeynes@352
    55
    start = extensions;
nkeynes@352
    56
    for (;;) {
nkeynes@352
    57
	where = (GLubyte *) strstr((const char *) start, extension);
nkeynes@352
    58
	if (!where)
nkeynes@352
    59
	    break;
nkeynes@352
    60
	terminator = where + strlen(extension);
nkeynes@352
    61
	if (where == start || *(where - 1) == ' ')
nkeynes@352
    62
	    if (*terminator == ' ' || *terminator == '\0')
nkeynes@352
    63
		return TRUE;
nkeynes@352
    64
	start = terminator;
nkeynes@352
    65
    }
nkeynes@352
    66
    return FALSE;
nkeynes@352
    67
}
nkeynes@352
    68
nkeynes@352
    69
gboolean hasRequiredGLExtensions( ) 
nkeynes@352
    70
{
nkeynes@352
    71
    int i;
nkeynes@352
    72
    gboolean isOK = TRUE;
nkeynes@352
    73
nkeynes@352
    74
    for( i=0; required_extensions[i] != NULL; i++ ) {
nkeynes@352
    75
	if( !isGLExtensionSupported(required_extensions[i]) ) {
nkeynes@352
    76
	    ERROR( "Required OpenGL extension not supported: %s", required_extensions[i] );
nkeynes@352
    77
	    isOK = FALSE;
nkeynes@352
    78
	}
nkeynes@352
    79
    }
nkeynes@352
    80
    return isOK;
nkeynes@352
    81
}
nkeynes@352
    82
nkeynes@443
    83
void gl_frame_buffer_to_tex_rectangle( frame_buffer_t frame, GLuint texid )
nkeynes@352
    84
{
nkeynes@352
    85
    GLenum type = colour_formats[frame->colour_format].type;
nkeynes@352
    86
    GLenum format = colour_formats[frame->colour_format].format;
nkeynes@352
    87
    int bpp = colour_formats[frame->colour_format].bpp;
nkeynes@443
    88
    int rowstride = (frame->rowstride / bpp) - frame->width;
nkeynes@443
    89
    
nkeynes@443
    90
    glPixelStorei( GL_UNPACK_ROW_LENGTH, rowstride );
nkeynes@443
    91
    glBindTexture( GL_TEXTURE_RECTANGLE_ARB, texid );
nkeynes@443
    92
    glTexImage2D( GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGB,
nkeynes@443
    93
		  frame->width, frame->height, 0, format, type, frame->data );
nkeynes@443
    94
}
nkeynes@352
    95
nkeynes@443
    96
void gl_display_tex_rectangle( GLuint texid, uint32_t tex_width, uint32_t tex_height, gboolean invert )
nkeynes@443
    97
{
nkeynes@443
    98
    float top, bottom;
nkeynes@443
    99
    if( invert ) {
nkeynes@443
   100
	top = ((float)tex_height) - 0.5;
nkeynes@443
   101
	bottom = 0.5;
nkeynes@443
   102
    } else {
nkeynes@443
   103
	top = 0.5;
nkeynes@443
   104
	bottom = ((float)tex_height) - 0.5;
nkeynes@443
   105
    }
nkeynes@443
   106
nkeynes@443
   107
    /* Reset display parameters */
nkeynes@352
   108
    glViewport( 0, 0, video_width, video_height );
nkeynes@352
   109
    glMatrixMode(GL_PROJECTION);
nkeynes@352
   110
    glLoadIdentity();
nkeynes@352
   111
    glOrtho( 0, video_width, video_height, 0, 0, -65535 );
nkeynes@352
   112
    glMatrixMode(GL_MODELVIEW);
nkeynes@352
   113
    glLoadIdentity();
nkeynes@352
   114
    glDisable( GL_TEXTURE_2D );
nkeynes@352
   115
    glDisable( GL_ALPHA_TEST );
nkeynes@352
   116
    glDisable( GL_DEPTH_TEST );
nkeynes@352
   117
    glDisable( GL_SCISSOR_TEST );
nkeynes@352
   118
    glDisable( GL_CULL_FACE );
nkeynes@444
   119
    glColor3f( 0,0,0 );
nkeynes@444
   120
    
nkeynes@444
   121
nkeynes@444
   122
    int x1=0,y1=0,x2=video_width,y2=video_height;
nkeynes@444
   123
nkeynes@444
   124
    int ah = video_width * 0.75;
nkeynes@444
   125
nkeynes@444
   126
    if( ah > video_height ) {
nkeynes@444
   127
	int w = (video_height/0.75);
nkeynes@444
   128
	x1 = (video_width - w)/2;
nkeynes@444
   129
	x2 -= x1;
nkeynes@444
   130
nkeynes@444
   131
	glBegin( GL_QUADS );
nkeynes@444
   132
	glVertex2f( 0, 0 );
nkeynes@444
   133
	glVertex2f( x1, 0 );
nkeynes@444
   134
	glVertex2f( x1, video_height );
nkeynes@444
   135
	glVertex2f( 0, video_height);
nkeynes@444
   136
	glVertex2f( x2, 0 );
nkeynes@444
   137
	glVertex2f( video_width, 0 );
nkeynes@444
   138
	glVertex2f( video_width, video_height );
nkeynes@444
   139
	glVertex2f( x2, video_height);
nkeynes@444
   140
	glEnd();
nkeynes@444
   141
    } else if( ah < video_height ) {
nkeynes@444
   142
	y1 = (video_height - ah)/2;
nkeynes@444
   143
	y2 -= y1;
nkeynes@444
   144
	glBegin( GL_QUADS );
nkeynes@444
   145
	glVertex2f( 0, 0 );
nkeynes@444
   146
	glVertex2f( video_width, 0 );
nkeynes@444
   147
	glVertex2f( video_width, y1 );
nkeynes@444
   148
	glVertex2f( 0, y1 );
nkeynes@444
   149
	glVertex2f( 0, y2 );
nkeynes@444
   150
	glVertex2f( video_width, y2 );
nkeynes@444
   151
	glVertex2f( video_width, video_height );
nkeynes@444
   152
	glVertex2f( 0, video_height );
nkeynes@444
   153
	glEnd();
nkeynes@444
   154
    }
nkeynes@352
   155
nkeynes@443
   156
    /* Render the textured rectangle */
nkeynes@443
   157
    glEnable( GL_TEXTURE_RECTANGLE_ARB );
nkeynes@443
   158
    glBindTexture( GL_TEXTURE_RECTANGLE_ARB, texid );
nkeynes@443
   159
    glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE );
nkeynes@443
   160
    glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
nkeynes@443
   161
    glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
nkeynes@443
   162
    glEnable( GL_BLEND );
nkeynes@443
   163
    glBlendFunc( GL_ONE, GL_ZERO );
nkeynes@352
   164
    glBegin( GL_QUADS );
nkeynes@443
   165
    glTexCoord2f( 0.5, top );
nkeynes@444
   166
    glVertex2f( x1, y1 );
nkeynes@443
   167
    glTexCoord2f( ((float)tex_width)-0.5, top );
nkeynes@444
   168
    glVertex2f( x2, y1 );
nkeynes@443
   169
    glTexCoord2f( ((float)tex_width)-0.5, bottom );
nkeynes@444
   170
    glVertex2f( x2, y2 );
nkeynes@443
   171
    glTexCoord2f( 0.5, bottom );
nkeynes@444
   172
    glVertex2f( x1, y2 );
nkeynes@352
   173
    glEnd();
nkeynes@443
   174
    glDisable( GL_TEXTURE_RECTANGLE_ARB );
nkeynes@352
   175
    glFlush();
nkeynes@443
   176
    frame_last_texid = texid;
nkeynes@443
   177
    frame_width = tex_width;
nkeynes@443
   178
    frame_height = tex_height;
nkeynes@443
   179
    frame_inverted = invert;
nkeynes@443
   180
}
nkeynes@443
   181
nkeynes@443
   182
gboolean gl_display_frame_buffer( frame_buffer_t frame )
nkeynes@443
   183
{
nkeynes@443
   184
    if( fbuf_id == 0 ) {
nkeynes@443
   185
	glGenTextures( 1, &fbuf_id );
nkeynes@443
   186
    }
nkeynes@443
   187
    gl_frame_buffer_to_tex_rectangle( frame, fbuf_id );
nkeynes@443
   188
    gl_display_tex_rectangle( fbuf_id, frame->width, frame->height, FALSE );
nkeynes@352
   189
    return TRUE;
nkeynes@352
   190
}
nkeynes@352
   191
nkeynes@352
   192
gboolean gl_display_blank( uint32_t colour )
nkeynes@352
   193
{
nkeynes@352
   194
    glViewport( 0, 0, video_width, video_height );
nkeynes@352
   195
    glMatrixMode( GL_PROJECTION );
nkeynes@352
   196
    glLoadIdentity();
nkeynes@352
   197
    glOrtho( 0, video_width, video_height, 0, 0, -65535 );
nkeynes@352
   198
    glMatrixMode(GL_MODELVIEW);
nkeynes@352
   199
    glLoadIdentity();
nkeynes@352
   200
    glColor3b( (colour >> 16) & 0xFF, (colour >> 8) & 0xFF, colour & 0xFF );
nkeynes@352
   201
    glRecti(0,0, video_width, video_height );
nkeynes@352
   202
    glFlush();
nkeynes@443
   203
    frame_colour = colour;
nkeynes@443
   204
    frame_last_texid = 0;
nkeynes@352
   205
    return TRUE;
nkeynes@352
   206
}
nkeynes@352
   207
nkeynes@443
   208
void gl_redisplay_last()
nkeynes@443
   209
{
nkeynes@443
   210
    if( frame_last_texid == 0 ) {
nkeynes@443
   211
	gl_display_blank( frame_colour );
nkeynes@443
   212
    } else {
nkeynes@443
   213
	gl_display_tex_rectangle( frame_last_texid, frame_width, frame_height, frame_inverted );
nkeynes@443
   214
    }
nkeynes@443
   215
}
nkeynes@443
   216
nkeynes@352
   217
/**
nkeynes@352
   218
 * Generic GL read_render_buffer. This function assumes that the caller
nkeynes@352
   219
 * has already set the appropriate glReadBuffer(); in other words, unless
nkeynes@352
   220
 * there's only one buffer this needs to be wrapped.
nkeynes@352
   221
 */
nkeynes@429
   222
gboolean gl_read_render_buffer( render_buffer_t buffer, unsigned char *target ) 
nkeynes@352
   223
{
nkeynes@352
   224
    if( buffer->address == -1 )
nkeynes@352
   225
	return FALSE;
nkeynes@352
   226
    glFinish();
nkeynes@352
   227
    GLenum type = colour_formats[buffer->colour_format].type;
nkeynes@352
   228
    GLenum format = colour_formats[buffer->colour_format].format;
nkeynes@424
   229
    // int line_size = buffer->width * colour_formats[buffer->colour_format].bpp;
nkeynes@424
   230
    // int size = line_size * buffer->height;
nkeynes@424
   231
    // int rowstride = (buffer->rowstride / colour_formats[buffer->colour_format].bpp) - buffer->width;
nkeynes@352
   232
    // glPixelStorei( GL_PACK_ROW_LENGTH, rowstride );
nkeynes@352
   233
    
nkeynes@352
   234
    glReadPixels( 0, 0, buffer->width, buffer->height, format, type, target );
nkeynes@352
   235
    return TRUE;
nkeynes@352
   236
}
.