filename | src/drivers/gl_common.c |
changeset | 443:1163eb5c0590 |
prev | 429:e581b90c3fb3 |
next | 444: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 }
.