nkeynes@352: /** nkeynes@586: * $Id$ nkeynes@352: * nkeynes@352: * Common GL code that doesn't depend on a specific implementation nkeynes@352: * nkeynes@352: * Copyright (c) 2005 Nathan Keynes. nkeynes@352: * nkeynes@352: * This program is free software; you can redistribute it and/or modify nkeynes@352: * it under the terms of the GNU General Public License as published by nkeynes@352: * the Free Software Foundation; either version 2 of the License, or nkeynes@352: * (at your option) any later version. nkeynes@352: * nkeynes@352: * This program is distributed in the hope that it will be useful, nkeynes@352: * but WITHOUT ANY WARRANTY; without even the implied warranty of nkeynes@352: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the nkeynes@352: * GNU General Public License for more details. nkeynes@352: */ nkeynes@352: nkeynes@443: #include nkeynes@443: nkeynes@540: #include "display.h" nkeynes@481: #include "pvr2/pvr2.h" nkeynes@352: #include "drivers/gl_common.h" nkeynes@352: nkeynes@352: extern uint32_t video_width, video_height; nkeynes@352: nkeynes@352: char *required_extensions[] = { "GL_EXT_framebuffer_object", NULL }; nkeynes@352: nkeynes@352: /** nkeynes@352: * Test if a specific extension is supported. From opengl.org nkeynes@352: * @param extension extension name to check for nkeynes@352: * @return TRUE if supported, otherwise FALSE. nkeynes@352: */ nkeynes@352: gboolean isGLExtensionSupported( const char *extension ) nkeynes@352: { nkeynes@352: const GLubyte *extensions = NULL; nkeynes@352: const GLubyte *start; nkeynes@352: GLubyte *where, *terminator; nkeynes@352: nkeynes@352: /* Extension names should not have spaces. */ nkeynes@352: where = (GLubyte *) strchr(extension, ' '); nkeynes@352: if (where || *extension == '\0') nkeynes@352: return 0; nkeynes@352: extensions = glGetString(GL_EXTENSIONS); nkeynes@352: /* It takes a bit of care to be fool-proof about parsing the nkeynes@352: OpenGL extensions string. Don't be fooled by sub-strings, nkeynes@352: etc. */ nkeynes@352: start = extensions; nkeynes@352: for (;;) { nkeynes@352: where = (GLubyte *) strstr((const char *) start, extension); nkeynes@352: if (!where) nkeynes@352: break; nkeynes@352: terminator = where + strlen(extension); nkeynes@352: if (where == start || *(where - 1) == ' ') nkeynes@352: if (*terminator == ' ' || *terminator == '\0') nkeynes@352: return TRUE; nkeynes@352: start = terminator; nkeynes@352: } nkeynes@352: return FALSE; nkeynes@352: } nkeynes@352: nkeynes@352: gboolean hasRequiredGLExtensions( ) nkeynes@352: { nkeynes@352: int i; nkeynes@352: gboolean isOK = TRUE; nkeynes@352: nkeynes@352: for( i=0; required_extensions[i] != NULL; i++ ) { nkeynes@352: if( !isGLExtensionSupported(required_extensions[i]) ) { nkeynes@352: ERROR( "Required OpenGL extension not supported: %s", required_extensions[i] ); nkeynes@352: isOK = FALSE; nkeynes@352: } nkeynes@352: } nkeynes@352: return isOK; nkeynes@352: } nkeynes@352: nkeynes@545: /** nkeynes@545: * Reset the gl state to simple orthographic projection with nkeynes@545: * texturing, alpha/depth/scissor/cull tests disabled. nkeynes@545: */ nkeynes@545: void gl_reset_state() nkeynes@443: { nkeynes@352: glViewport( 0, 0, video_width, video_height ); nkeynes@352: glMatrixMode(GL_PROJECTION); nkeynes@352: glLoadIdentity(); nkeynes@352: glOrtho( 0, video_width, video_height, 0, 0, -65535 ); nkeynes@352: glMatrixMode(GL_MODELVIEW); nkeynes@352: glLoadIdentity(); nkeynes@352: glDisable( GL_TEXTURE_2D ); nkeynes@352: glDisable( GL_ALPHA_TEST ); nkeynes@352: glDisable( GL_DEPTH_TEST ); nkeynes@352: glDisable( GL_SCISSOR_TEST ); nkeynes@352: glDisable( GL_CULL_FACE ); nkeynes@545: glDrawBuffer( GL_FRONT ); nkeynes@545: } nkeynes@545: nkeynes@545: void gl_display_render_buffer( render_buffer_t buffer ) nkeynes@545: { nkeynes@545: gl_texture_window( buffer->width, buffer->height, buffer->buf_id, buffer->inverted ); nkeynes@545: } nkeynes@545: nkeynes@545: void gl_texture_window( int width, int height, int tex_id, gboolean inverted ) nkeynes@545: { nkeynes@545: float top, bottom; nkeynes@545: if( inverted ) { nkeynes@586: top = ((float)height); nkeynes@586: bottom = 0; nkeynes@545: } else { nkeynes@586: top = 0; nkeynes@586: bottom = ((float)height); nkeynes@545: } nkeynes@545: nkeynes@545: /* Reset display parameters */ nkeynes@545: gl_reset_state(); nkeynes@545: glColor3f( 0,0,0 ); nkeynes@444: nkeynes@444: int x1=0,y1=0,x2=video_width,y2=video_height; nkeynes@444: nkeynes@444: int ah = video_width * 0.75; nkeynes@444: nkeynes@444: if( ah > video_height ) { nkeynes@444: int w = (video_height/0.75); nkeynes@444: x1 = (video_width - w)/2; nkeynes@444: x2 -= x1; nkeynes@444: nkeynes@444: glBegin( GL_QUADS ); nkeynes@444: glVertex2f( 0, 0 ); nkeynes@444: glVertex2f( x1, 0 ); nkeynes@444: glVertex2f( x1, video_height ); nkeynes@444: glVertex2f( 0, video_height); nkeynes@444: glVertex2f( x2, 0 ); nkeynes@444: glVertex2f( video_width, 0 ); nkeynes@444: glVertex2f( video_width, video_height ); nkeynes@444: glVertex2f( x2, video_height); nkeynes@444: glEnd(); nkeynes@444: } else if( ah < video_height ) { nkeynes@444: y1 = (video_height - ah)/2; nkeynes@444: y2 -= y1; nkeynes@444: glBegin( GL_QUADS ); nkeynes@444: glVertex2f( 0, 0 ); nkeynes@444: glVertex2f( video_width, 0 ); nkeynes@444: glVertex2f( video_width, y1 ); nkeynes@444: glVertex2f( 0, y1 ); nkeynes@444: glVertex2f( 0, y2 ); nkeynes@444: glVertex2f( video_width, y2 ); nkeynes@444: glVertex2f( video_width, video_height ); nkeynes@444: glVertex2f( 0, video_height ); nkeynes@444: glEnd(); nkeynes@444: } nkeynes@352: nkeynes@443: /* Render the textured rectangle */ nkeynes@443: glEnable( GL_TEXTURE_RECTANGLE_ARB ); nkeynes@545: glBindTexture( GL_TEXTURE_RECTANGLE_ARB, tex_id ); nkeynes@443: glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE ); nkeynes@443: glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, GL_LINEAR); nkeynes@443: glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, GL_LINEAR); nkeynes@443: glEnable( GL_BLEND ); nkeynes@443: glBlendFunc( GL_ONE, GL_ZERO ); nkeynes@352: glBegin( GL_QUADS ); nkeynes@586: glTexCoord2f( 0, top ); nkeynes@444: glVertex2f( x1, y1 ); nkeynes@586: glTexCoord2f( ((float)width), top ); nkeynes@444: glVertex2f( x2, y1 ); nkeynes@586: glTexCoord2f( ((float)width), bottom ); nkeynes@444: glVertex2f( x2, y2 ); nkeynes@586: glTexCoord2f( 0, bottom ); nkeynes@444: glVertex2f( x1, y2 ); nkeynes@352: glEnd(); nkeynes@443: glDisable( GL_TEXTURE_RECTANGLE_ARB ); nkeynes@352: glFlush(); nkeynes@443: } nkeynes@443: nkeynes@545: gboolean gl_load_frame_buffer( frame_buffer_t frame, int tex_id ) nkeynes@443: { nkeynes@477: GLenum type = colour_formats[frame->colour_format].type; nkeynes@477: GLenum format = colour_formats[frame->colour_format].format; nkeynes@477: int bpp = colour_formats[frame->colour_format].bpp; nkeynes@477: int rowstride = (frame->rowstride / bpp) - frame->width; nkeynes@477: nkeynes@477: glPixelStorei( GL_UNPACK_ROW_LENGTH, rowstride ); nkeynes@545: glBindTexture( GL_TEXTURE_RECTANGLE_ARB, tex_id ); nkeynes@477: glTexSubImage2D( GL_TEXTURE_RECTANGLE_ARB, 0, 0,0, nkeynes@481: frame->width, frame->height, format, type, frame->data ); nkeynes@481: return TRUE; nkeynes@352: } nkeynes@352: nkeynes@352: gboolean gl_display_blank( uint32_t colour ) nkeynes@352: { nkeynes@545: gl_reset_state(); nkeynes@545: glColor3ub( (colour >> 16) & 0xFF, (colour >> 8) & 0xFF, colour & 0xFF ); nkeynes@352: glRecti(0,0, video_width, video_height ); nkeynes@352: glFlush(); nkeynes@352: return TRUE; nkeynes@352: } nkeynes@352: nkeynes@352: /** nkeynes@352: * Generic GL read_render_buffer. This function assumes that the caller nkeynes@352: * has already set the appropriate glReadBuffer(); in other words, unless nkeynes@352: * there's only one buffer this needs to be wrapped. nkeynes@352: */ nkeynes@477: gboolean gl_read_render_buffer( unsigned char *target, render_buffer_t buffer, nkeynes@477: int rowstride, int colour_format ) nkeynes@352: { nkeynes@352: glFinish(); nkeynes@477: GLenum type = colour_formats[colour_format].type; nkeynes@477: GLenum format = colour_formats[colour_format].format; nkeynes@477: // int line_size = buffer->width * colour_formats[colour_format].bpp; nkeynes@424: // int size = line_size * buffer->height; nkeynes@477: int glrowstride = (rowstride / colour_formats[colour_format].bpp) - buffer->width; nkeynes@477: glPixelStorei( GL_PACK_ROW_LENGTH, glrowstride ); nkeynes@352: nkeynes@352: glReadPixels( 0, 0, buffer->width, buffer->height, format, type, target ); nkeynes@352: return TRUE; nkeynes@352: }