Search
lxdream.org :: lxdream/src/drivers/video_gl.c
lxdream 0.9.1
released Jun 29
Download Now
filename src/drivers/video_gl.c
changeset 1262:4baa34eee6fc
prev1260:8207695d908c
next1282:9f445c5e252b
author nkeynes
date Mon Mar 05 22:20:33 2012 +1000 (12 years ago)
permissions -rw-r--r--
last change Fix boundary of the first vertical gap in view
view annotate diff log raw
     1 /**
     2  * $Id$
     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 "display.h"
    22 #include "pvr2/pvr2.h"
    23 #include "pvr2/glutil.h"
    24 #include "pvr2/shaders.h"
    25 #include "drivers/video_gl.h"
    27 /* FIXME: Need to actually handle this case */
    28 #ifndef GL_PACK_ROW_LENGTH
    29 #define glPixelStorei(key,val)
    30 #endif
    32 uint32_t video_width, video_height;
    33 struct video_vertex {
    34     float x,y;
    35     float u,v;
    36     float r,g,b,a;
    37 };
    39 static struct video_box_t {
    40     float viewMatrix[16];
    41     struct video_vertex gap1[4];
    42     struct video_vertex gap2[4];
    43     struct video_vertex video_view[4];
    44     struct video_vertex invert_view[4];
    45 } video_box;
    47 void gl_set_video_size( uint32_t width, uint32_t height, int flipped )
    48 {
    49     video_width = width;
    50     video_height = height;
    52     int x1=0,y1=0,x2=video_width,y2=video_height;
    53     int top = 0, bottom = 1;
    55     if( flipped ) {
    56         top = 1;
    57         bottom = 0;
    58     }
    60     int ah = video_width * 0.75;
    62     if( ah > video_height ) {
    63         int w = (video_height/0.75);
    64         x1 = (video_width - w)/2;
    65         x2 -= x1;
    66         video_box.gap1[0].x = 0; video_box.gap1[0].y = 0;
    67         video_box.gap1[1].x = x1; video_box.gap1[1].y = 0;
    68         video_box.gap1[2].x = x1; video_box.gap1[2].y = video_height;
    69         video_box.gap1[3].x = 0; video_box.gap1[3].y = video_height;
    70         video_box.gap2[0].x = x2; video_box.gap2[0].y = 0;
    71         video_box.gap2[1].x = video_width; video_box.gap2[1].y = 0;
    72         video_box.gap2[2].x = video_width; video_box.gap2[2].y = video_height;
    73         video_box.gap2[3].x = x2; video_box.gap2[3].y = video_height;
    74     } else if( ah < video_height ) {
    75         y1 = (video_height - ah)/2;
    76         y2 -= y1;
    78         video_box.gap1[0].x = 0; video_box.gap1[0].y = 0;
    79         video_box.gap1[1].x = video_width; video_box.gap1[1].y = 0;
    80         video_box.gap1[2].x = video_width; video_box.gap1[2].y = y1;
    81         video_box.gap1[3].x = 0; video_box.gap1[3].y = y1;
    82         video_box.gap2[0].x = 0; video_box.gap2[0].y = y2;
    83         video_box.gap2[1].x = video_width; video_box.gap2[1].y = y2;
    84         video_box.gap2[2].x = video_width; video_box.gap2[2].y = video_height;
    85         video_box.gap2[3].x = 0; video_box.gap2[3].y = video_height;
    86     }
    88     video_box.video_view[0].x = x1; video_box.video_view[0].y = y1;
    89     video_box.video_view[0].u = 0; video_box.video_view[0].v = top;
    90     video_box.video_view[1].x = x2; video_box.video_view[1].y = y1;
    91     video_box.video_view[1].u = 1; video_box.video_view[1].v = top;
    92     video_box.video_view[2].x = x2; video_box.video_view[2].y = y2;
    93     video_box.video_view[2].u = 1; video_box.video_view[2].v = bottom;
    94     video_box.video_view[3].x = x1; video_box.video_view[3].y = y2;
    95     video_box.video_view[3].u = 0; video_box.video_view[3].v = bottom;
    97     memcpy( &video_box.invert_view, &video_box.video_view, sizeof(video_box.video_view) );
    98     video_box.invert_view[0].v = bottom; video_box.invert_view[1].v = bottom;
    99     video_box.invert_view[2].v = top; video_box.invert_view[3].v = top;
   101     defineOrthoMatrix(video_box.viewMatrix, video_width, video_height, 0, 65535);
   102 }
   104 #ifdef HAVE_OPENGL_FIXEDFUNC
   105 /**
   106  * Setup the gl context for writes to the display output.
   107  */
   108 void gl_framebuffer_setup()
   109 {
   110     glViewport( 0, 0, video_width, video_height );
   111     glLoadMatrixf(video_box.viewMatrix);
   112     glBlendFunc( GL_ONE, GL_ZERO );
   113     glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE );
   114     glVertexPointer(2, GL_FLOAT, sizeof(struct video_vertex), &video_box.gap1[0].x);
   115     glColorPointer(3, GL_FLOAT, sizeof(struct video_vertex), &video_box.gap1[0].r);
   116     glTexCoordPointer(2, GL_FLOAT, sizeof(struct video_vertex), &video_box.gap1[0].u);
   117     glEnableClientState( GL_VERTEX_ARRAY );
   118     glEnableClientState( GL_COLOR_ARRAY );
   119     glEnableClientState( GL_TEXTURE_COORD_ARRAY );
   120 }
   122 void gl_framebuffer_cleanup()
   123 {
   124     glDisableClientState( GL_VERTEX_ARRAY );
   125     glDisableClientState( GL_COLOR_ARRAY );
   126     glDisableClientState( GL_TEXTURE_COORD_ARRAY );
   127 }
   128 #else
   129 void gl_framebuffer_setup()
   130 {
   131     glViewport( 0, 0, video_width, video_height );
   132     glBlendFunc( GL_ONE, GL_ZERO );
   133     glsl_use_basic_shader();
   134     glsl_set_basic_shader_view_matrix(video_box.viewMatrix);
   135     glsl_set_basic_shader_in_vertex_pointer(&video_box.gap1[0].x, sizeof(struct video_vertex));
   136     glsl_set_basic_shader_in_colour_pointer(&video_box.gap1[0].r, sizeof(struct video_vertex));
   137     glsl_set_basic_shader_in_texcoord_pointer(&video_box.gap1[0].u, sizeof(struct video_vertex));
   138     glsl_set_basic_shader_primary_texture(0);
   139 }
   141 void gl_framebuffer_cleanup()
   142 {
   143     glsl_clear_shader();
   144 }
   145 #endif
   147 void gl_display_render_buffer( render_buffer_t buffer )
   148 {
   149     gl_texture_window( buffer->width, buffer->height, buffer->buf_id, buffer->inverted );
   150 }
   152 /**
   153  * Convert window coordinates to dreamcast device coords (640x480) using the 
   154  * same viewable area as gl_texture_window.
   155  * If the coordinates are outside the viewable area, the result is -1,-1.
   156  */ 
   157 void gl_window_to_system_coords( int *x, int *y )
   158 {
   159     int x1=0,y1=0,x2=video_width,y2=video_height;
   161     int ah = video_width * 0.75;
   163     if( ah > video_height ) {
   164         int w = (video_height/0.75);
   165         x1 = (video_width - w)/2;
   166         x2 -= x1;
   167     } else if( ah < video_height ) {
   168         y1 = (video_height - ah)/2;
   169         y2 -= y1;
   170     }
   171     if( *x < x1 || *x >= x2 || *y < y1 || *y >= y2 ) {
   172         *x = -1;
   173         *y = -1;
   174     } else {
   175         *x = (*x - x1) * DISPLAY_WIDTH / (x2-x1);
   176         *y = (*y - y1) * DISPLAY_HEIGHT / (y2-y1);
   177     }
   178 }
   180 /**
   181  * Use quads if we have them, otherwise tri-fans.
   182  */
   183 #ifndef GL_QUADS
   184 #define GL_QUADS GL_TRIANGLE_FAN
   185 #endif
   187 void gl_texture_window( int width, int height, int tex_id, gboolean inverted )
   188 {
   189     /* Set video box tex alpha to 1 */
   190     video_box.video_view[0].a = video_box.video_view[1].a = video_box.video_view[2].a = video_box.video_view[3].a = 1;
   191     video_box.invert_view[0].a = video_box.invert_view[1].a = video_box.invert_view[2].a = video_box.invert_view[3].a = 1;
   193     /* Reset display parameters */
   194     gl_framebuffer_setup();
   195     glDrawArrays(GL_QUADS, 0, 4);
   196     glDrawArrays(GL_QUADS, 4, 4);
   197     glEnable(GL_TEXTURE_2D);
   198     glBindTexture(GL_TEXTURE_2D,tex_id);
   199     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
   200     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
   201     glDrawArrays(GL_QUADS, inverted ? 12 : 8, 4);
   202     glDisable(GL_TEXTURE_2D);
   203     gl_framebuffer_cleanup();
   204     glFlush();
   205 }
   207 gboolean gl_load_frame_buffer( frame_buffer_t frame, int tex_id )
   208 {
   209     GLenum type = colour_formats[frame->colour_format].type;
   210     GLenum format = colour_formats[frame->colour_format].format;
   211     int bpp = colour_formats[frame->colour_format].bpp;
   212     int rowstride = (frame->rowstride / bpp) - frame->width;
   214     glPixelStorei( GL_UNPACK_ROW_LENGTH, rowstride );
   215     glBindTexture( GL_TEXTURE_2D, tex_id );
   216     glTexSubImage2D( GL_TEXTURE_2D, 0, 0,0,
   217                      frame->width, frame->height, format, type, frame->data );
   218     glPixelStorei( GL_UNPACK_ROW_LENGTH, 0 );
   219     return TRUE;
   220 }
   222 void gl_display_blank( uint32_t colour )
   223 {
   224     /* Set the video_box background colour */
   225     video_box.video_view[0].r = ((float)(((colour >> 16) & 0xFF) + 1)) / 256.0;
   226     video_box.video_view[0].g = ((float)(((colour >> 8) & 0xFF) + 1)) / 256.0;
   227     video_box.video_view[0].b = ((float)((colour & 0xFF) + 1)) / 256.0;
   228     video_box.video_view[0].a = 0;
   229     memcpy( &video_box.video_view[1].r, &video_box.video_view[0].r, sizeof(float)*3 );
   230     memcpy( &video_box.video_view[2].r, &video_box.video_view[0].r, sizeof(float)*3 );
   231     memcpy( &video_box.video_view[3].r, &video_box.video_view[0].r, sizeof(float)*3 );
   233     /* And render */
   234     gl_framebuffer_setup();
   235     glDrawArrays(GL_QUADS, 0, 4);
   236     glDrawArrays(GL_QUADS, 4, 4);
   237     glDrawArrays(GL_QUADS, 8, 4);
   238     gl_framebuffer_cleanup();
   239     glFlush();
   240 }
   242 /**
   243  * Generic GL read_render_buffer. This function assumes that the caller
   244  * has already set the appropriate glReadBuffer(); in other words, unless
   245  * there's only one buffer this needs to be wrapped.
   246  */
   247 gboolean gl_read_render_buffer( unsigned char *target, render_buffer_t buffer, 
   248                                 int rowstride, int colour_format ) 
   249 {
   250     glFinish();
   251     GLenum type = colour_formats[colour_format].type;
   252     GLenum format = colour_formats[colour_format].format;
   253     // int line_size = buffer->width * colour_formats[colour_format].bpp;
   254     // int size = line_size * buffer->height;
   255     int glrowstride = (rowstride / colour_formats[colour_format].bpp) - buffer->width;
   256     glPixelStorei( GL_PACK_ROW_LENGTH, glrowstride );
   257     glReadPixels( 0, 0, buffer->width, buffer->height, format, type, target );
   258     glPixelStorei( GL_PACK_ROW_LENGTH, 0 );
   259     return TRUE;
   260 }
   262 gboolean gl_init_driver( display_driver_t driver, gboolean need_fbo )
   263 {
   264     /* Use framebuffer objects if available */
   265     if( gl_fbo_is_supported() ) {
   266         gl_fbo_init(driver);
   267     } else if( need_fbo ) {
   268         ERROR( "Framebuffer objects not supported - unable to construct an off-screen buffer" );
   269         return FALSE;
   270     }
   272     /* Use SL shaders if available */
   273     gboolean have_shaders = glsl_init(driver);
   274 #ifndef HAVE_OPENGL_FIXEDFUNC
   275     if( !have_shaders ) { /* Shaders are required if we don't have fixed-functionality */
   276         gl_fbo_shutdown();
   277         return FALSE;
   278     }
   279 #endif
   281     /* Use vertex arrays, VBOs, etc, if we have them */
   282     gl_vbo_init(driver);
   284     driver->capabilities.has_gl = TRUE;
   285     return TRUE;
   286 }
   288 static gboolean video_gl_init();
   290 /**
   291  * Minimal GL driver (assuming that the GL context is already set up externally)
   292  * This requires FBO support (since otherwise we have no way to get a render buffer)
   293  */
   294 struct display_driver display_gl_driver = {
   295         "gl", N_("OpenGL driver"), video_gl_init, NULL,
   296         NULL, NULL, NULL,
   297         NULL, NULL, NULL, NULL,
   298         gl_load_frame_buffer, gl_display_render_buffer, gl_display_blank,
   299         NULL, gl_read_render_buffer, NULL, NULL
   300 };
   302 static gboolean video_gl_init()
   303 {
   304     return gl_init_driver(&display_gl_driver, TRUE);
   305 }
.