revision 477:9a373f2ff009
summary |
tree |
shortlog |
changelog |
graph |
changeset |
raw | bz2 | zip | gz changeset | 477:9a373f2ff009 |
parent | 476:75eb00fc191d |
child | 478:57f73576c974 |
author | nkeynes |
date | Wed Oct 31 09:10:23 2007 +0000 (16 years ago) |
Add save/restore of render buffers in save states
Gzip memory blocks in save states
Move front-buffer management back to pvr2
Add screenshot preview when loading save states
Various minor fixes and cleanups
Gzip memory blocks in save states
Move front-buffer management back to pvr2
Add screenshot preview when loading save states
Various minor fixes and cleanups
1.1 --- a/src/display.c Wed Oct 31 09:07:25 2007 +00001.2 +++ b/src/display.c Wed Oct 31 09:10:23 2007 +00001.3 @@ -1,5 +1,5 @@1.4 /**1.5 - * $Id: display.c,v 1.11 2007-10-21 05:15:56 nkeynes Exp $1.6 + * $Id: display.c,v 1.12 2007-10-31 09:10:23 nkeynes Exp $1.7 *1.8 * Generic support for keyboard and other input sources. The active display1.9 * driver is expected to deliver events here, where they're translated and1.10 @@ -41,6 +41,10 @@1.11 { GL_UNSIGNED_BYTE, GL_BGRA, GL_RGBA8, 4 }, /* YUV decoded to ARGB8888 */1.12 { GL_UNSIGNED_BYTE, GL_BGR, GL_RGB, 3 },1.13 { GL_UNSIGNED_BYTE, GL_BGRA, GL_RGBA8, 4 },1.14 + { GL_UNSIGNED_BYTE, GL_BGRA, GL_RGBA8, 4 }, /* Index4 decoded */1.15 + { GL_UNSIGNED_BYTE, GL_BGRA, GL_RGBA8, 4 }, /* Index8 decoded */1.16 + { GL_UNSIGNED_BYTE, GL_BGRA, GL_RGBA8, 4 },1.17 + { GL_UNSIGNED_BYTE, GL_RGB, GL_RGB, 3 },1.19 };
2.1 --- a/src/display.h Wed Oct 31 09:07:25 2007 +00002.2 +++ b/src/display.h Wed Oct 31 09:10:23 2007 +00002.3 @@ -1,5 +1,5 @@2.4 /**2.5 - * $Id: display.h,v 1.10 2007-10-21 05:15:56 nkeynes Exp $2.6 + * $Id: display.h,v 1.11 2007-10-31 09:10:23 nkeynes Exp $2.7 *2.8 * The PC side of the video support (responsible for actually displaying /2.9 * rendering frames)2.10 @@ -23,25 +23,26 @@2.11 #include <stdint.h>2.12 #include <glib.h>2.13 #include <GL/gl.h>2.14 -#include "dream.h"2.15 +#include "lxdream.h"2.17 #ifdef __cplusplus2.18 extern "C" {2.19 #endif2.21 /**2.22 - * Supported colour formats. Note that ARGB4444 is only ever used for texture2.23 + * Supported colour formats. Note that BGRA4444 is only ever used for texture2.24 * rendering (it's not valid for display purposes).2.25 */2.26 -#define COLFMT_ARGB1555 02.27 +#define COLFMT_BGRA1555 02.28 #define COLFMT_RGB565 12.29 -#define COLFMT_ARGB4444 22.30 +#define COLFMT_BGRA4444 22.31 #define COLFMT_YUV422 3 /* 8-bit YUV (texture source only) */2.32 -#define COLFMT_RGB888 4 /* 24-bit RGB */2.33 -#define COLFMT_ARGB8888 52.34 +#define COLFMT_BGR888 4 /* 24-bit BGR */2.35 +#define COLFMT_BGRA8888 52.36 #define COLFMT_INDEX4 6 /* 4 bit indexed colour (texture source only) */2.37 #define COLFMT_INDEX8 7 /* 8-bit indexed colour (texture source only) */2.38 -#define COLFMT_RGB0888 8 /* 32-bit RGB */2.39 +#define COLFMT_BGR0888 8 /* 32-bit BGR */2.40 +#define COLFMT_RGB888 9 /* 24-bit RGB (ie GL native) */2.42 struct colour_format {2.43 GLint type, format, int_format;2.44 @@ -54,31 +55,33 @@2.45 /**2.46 * Structure to hold pixel data held in GL buffers.2.47 */2.48 -typedef struct render_buffer {2.49 +struct render_buffer {2.50 uint32_t width;2.51 uint32_t height;2.52 uint32_t rowstride;2.53 int colour_format;2.54 sh4addr_t address; /* Address buffer was rendered to, or -1 for unrendered */2.55 uint32_t size; /* Size of buffer in bytes, must be width*height*bpp */2.56 + gboolean inverted;/* True if the buffer is upside down */2.57 int scale;2.58 unsigned int buf_id; /* driver-specific buffer id, if applicable */2.59 gboolean flushed; /* True if the buffer has been flushed to vram */2.60 -} *render_buffer_t;2.61 +};2.63 /**2.64 * Structure to hold pixel data stored in pvr2 vram, as opposed to data in2.65 * GL buffers.2.66 */2.67 -typedef struct frame_buffer {2.68 +struct frame_buffer {2.69 uint32_t width;2.70 uint32_t height;2.71 uint32_t rowstride;2.72 int colour_format;2.73 sh4addr_t address;2.74 uint32_t size; /* Size of buffer in bytes, must be width*height*bpp */2.75 + gboolean inverted;/* True if the buffer is upside down */2.76 char *data;2.77 -} * frame_buffer_t;2.78 +};2.80 /**2.81 * Core video driver - exports function to setup a GL context, as well as handle2.82 @@ -125,9 +128,10 @@2.83 gboolean (*set_render_target)( render_buffer_t buffer );2.85 /**2.86 - * Display a single frame using the supplied pixmap data.2.87 + * Load the supplied frame buffer into the given render buffer.2.88 + * Included here to allow driver-specific optimizations.2.89 */2.90 - gboolean (*display_frame_buffer)( frame_buffer_t buffer );2.91 + void (*load_frame_buffer)( frame_buffer_t frame, render_buffer_t render );2.93 /**2.94 * Display a single frame using a previously rendered GL buffer.2.95 @@ -136,7 +140,7 @@2.97 /**2.98 * Display a single blanked frame using a fixed colour for the2.99 - * entire frame (specified in RGB888 format).2.100 + * entire frame (specified in BGR888 format).2.101 */2.102 gboolean (*display_blank)( uint32_t rgb );2.104 @@ -144,8 +148,14 @@2.105 * Copy the image data from the GL buffer to the target memory buffer,2.106 * using the format etc from the buffer. This may force a glFinish()2.107 * but does not invalidate the buffer.2.108 + * @param target buffer to fill with image data, which must be large enough2.109 + * to accomodate the image.2.110 + * @param buffer Render buffer to read from.2.111 + * @param rowstride rowstride of the target data2.112 + * @param format colour format to output the data in.2.113 */2.114 - gboolean (*read_render_buffer)( render_buffer_t buffer, unsigned char *target );2.115 + gboolean (*read_render_buffer)( unsigned char *target, render_buffer_t buffer,2.116 + int rowstride, int format );2.118 } *display_driver_t;
3.1 --- a/src/dream.h Wed Oct 31 09:07:25 2007 +00003.2 +++ b/src/dream.h Wed Oct 31 09:10:23 2007 +00003.3 @@ -1,5 +1,5 @@3.4 /**3.5 - * $Id: dream.h,v 1.15 2007-10-11 08:22:03 nkeynes Exp $3.6 + * $Id: dream.h,v 1.16 2007-10-31 09:10:23 nkeynes Exp $3.7 *3.8 * Miscellaneous application-wide declarations (mainly logging atm)3.9 *3.10 @@ -23,15 +23,12 @@3.11 #include <stdlib.h>3.12 #include <stdint.h>3.13 #include <string.h>3.14 -#include <glib/gtypes.h>3.15 +#include "lxdream.h"3.17 #ifdef __cplusplus3.18 extern "C" {3.19 #endif3.21 -#define APP_NAME "lxDream"3.22 -#define APP_VERSION "0.8"3.23 -3.24 /************************ Modules ********************************/3.25 /**3.26 * Basic module structure defining the common operations across all3.27 @@ -90,39 +87,16 @@3.28 extern struct dreamcast_module eventq_module;3.29 extern struct dreamcast_module unknown_module;3.31 -/*************************** Logging **************************/3.32 -3.33 -#define EMIT_FATAL 03.34 -#define EMIT_ERR 13.35 -#define EMIT_WARN 23.36 -#define EMIT_INFO 33.37 -#define EMIT_DEBUG 43.38 -#define EMIT_TRACE 53.39 -3.40 -#ifndef MODULE3.41 -#define MODULE unknown_module3.42 -#endif3.43 -3.44 -void log_message( void *, int level, const char *source, const char *msg, ... );3.45 -3.46 -#define FATAL( ... ) log_message( NULL, EMIT_FATAL, MODULE.name, __VA_ARGS__ )3.47 -#define ERROR( ... ) log_message( NULL, EMIT_ERR, MODULE.name, __VA_ARGS__ )3.48 -#define WARN( ... ) log_message( NULL, EMIT_WARN, MODULE.name, __VA_ARGS__ )3.49 -#define INFO( ... ) log_message( NULL, EMIT_INFO, MODULE.name, __VA_ARGS__ )3.50 -#define DEBUG( ... ) log_message( NULL, EMIT_DEBUG, MODULE.name, __VA_ARGS__ )3.51 -#define TRACE( ... ) log_message( NULL, EMIT_TRACE, MODULE.name, __VA_ARGS__ )3.52 -3.53 void fwrite_string( const char *s, FILE *f );3.54 int fread_string( char *s, int maxlen, FILE *f );3.55 +void fwrite_gzip( void *p, size_t size, size_t num, FILE *f );3.56 +int fread_gzip( void *p, size_t size, size_t num, FILE *f );3.57 void fwrite_dump( unsigned char *buf, unsigned int length, FILE *f );3.58 void fwrite_dump32( unsigned int *buf, unsigned int length, FILE *f );3.59 void fwrite_dump32v( unsigned int *buf, unsigned int length, int wordsPerLine, FILE *f );3.61 -typedef uint32_t sh4addr_t;3.62 -3.63 -#ifndef max3.64 -#define max(a,b) ( (a) > (b) ? (a) : (b) )3.65 -#endif3.66 +gboolean write_png_to_stream( FILE *f, frame_buffer_t );3.67 +frame_buffer_t read_png_from_stream( FILE *f );3.69 #ifdef __cplusplus3.70 }
4.1 --- a/src/dreamcast.c Wed Oct 31 09:07:25 2007 +00004.2 +++ b/src/dreamcast.c Wed Oct 31 09:10:23 2007 +00004.3 @@ -1,5 +1,5 @@4.4 /**4.5 - * $Id: dreamcast.c,v 1.26 2007-10-27 05:47:55 nkeynes Exp $4.6 + * $Id: dreamcast.c,v 1.27 2007-10-31 09:10:23 nkeynes Exp $4.7 * Central switchboard for the system. This pulls all the individual modules4.8 * together into some kind of coherent structure. This is also where you'd4.9 * add Naomi support, if I ever get a board to play with...4.10 @@ -220,62 +220,137 @@4.11 uint32_t module_count;4.12 };4.14 +struct chunk_header {4.15 + char marker[4]; /* Always BLCK */4.16 + char name[8]; /* Block (module) name */4.17 + uint32_t block_length;4.18 +};4.19 +4.20 +/**4.21 + * Check the save state header to ensure that it is a valid, supported4.22 + * file.4.23 + * @return the number of blocks following, or 0 if the file is invalid.4.24 + */4.25 +int dreamcast_read_save_state_header( FILE *f )4.26 +{4.27 + struct save_state_header header;4.28 + if( fread( &header, sizeof(header), 1, f ) != 1 ) {4.29 + return 0;4.30 + }4.31 + if( strncmp( header.magic, DREAMCAST_SAVE_MAGIC, 16 ) != 0 ) {4.32 + ERROR( "Not a %s save state file", APP_NAME );4.33 + return 0;4.34 + }4.35 + if( header.version != DREAMCAST_SAVE_VERSION ) {4.36 + ERROR( "%s save state version not supported", APP_NAME );4.37 + return 0;4.38 + }4.39 + if( header.module_count > MAX_MODULES ) {4.40 + ERROR( "%s save state is corrupted (bad module count)", APP_NAME );4.41 + return 0;4.42 + }4.43 + return header.module_count;4.44 +}4.45 +4.46 +int dreamcast_write_chunk_header( const gchar *name, uint32_t length, FILE *f )4.47 +{4.48 + struct chunk_header head;4.49 +4.50 + memcpy( head.marker, "BLCK", 4 );4.51 + memset( head.name, 0, 8 );4.52 + memcpy( head.name, name, strlen(name) );4.53 + head.block_length = length;4.54 + return fwrite( &head, sizeof(head), 1, f );4.55 +}4.56 +4.57 +4.58 +frame_buffer_t dreamcast_load_preview( const gchar *filename )4.59 +{4.60 + int i;4.61 + FILE *f = fopen( filename, "r" );4.62 + if( f == NULL ) return NULL;4.63 +4.64 + int module_count = dreamcast_read_save_state_header(f);4.65 + if( module_count <= 0 ) {4.66 + fclose(f);4.67 + return NULL;4.68 + }4.69 + for( i=0; i<module_count; i++ ) {4.70 + struct chunk_header head;4.71 + if( fread( &head, sizeof(head), 1, f ) != 1 ) {4.72 + fclose(f);4.73 + return NULL;4.74 + }4.75 + if( memcmp("BLCK", head.marker, 4) != 0 ) {4.76 + fclose(f);4.77 + return NULL;4.78 + }4.79 +4.80 + if( strcmp("PVR2", head.name) == 0 ) {4.81 + uint32_t buf_count;4.82 + int has_front;4.83 + fread( &buf_count, sizeof(buf_count), 1, f );4.84 + fread( &has_front, sizeof(has_front), 1, f );4.85 + if( buf_count != 0 && has_front ) {4.86 + frame_buffer_t result = read_png_from_stream(f);4.87 + fclose(f);4.88 + return result;4.89 + }4.90 + break;4.91 + } else {4.92 + fseek( f, head.block_length, SEEK_CUR );4.93 + }4.94 + }4.95 + return NULL;4.96 +}4.97 +4.98 int dreamcast_load_state( const gchar *filename )4.99 {4.100 int i,j;4.101 uint32_t len;4.102 + int module_count;4.103 int have_read[MAX_MODULES];4.104 - char tmp[64];4.105 - struct save_state_header header;4.106 - FILE *f;4.108 - f = fopen( filename, "r" );4.109 + FILE *f = fopen( filename, "r" );4.110 if( f == NULL ) return errno;4.112 - fread( &header, sizeof(header), 1, f );4.113 - if( strncmp( header.magic, DREAMCAST_SAVE_MAGIC, 16 ) != 0 ) {4.114 - ERROR( "Not a %s save state file", APP_NAME );4.115 + module_count = dreamcast_read_save_state_header(f);4.116 + if( module_count <= 0 ) {4.117 + fclose(f);4.118 return 1;4.119 }4.120 - if( header.version != DREAMCAST_SAVE_VERSION ) {4.121 - ERROR( "%s save state version not supported", APP_NAME );4.122 - return 1;4.123 - }4.124 - if( header.module_count > MAX_MODULES ) {4.125 - ERROR( "%s save state is corrupted (bad module count)", APP_NAME );4.126 - return 1;4.127 - }4.128 +4.129 for( i=0; i<MAX_MODULES; i++ ) {4.130 have_read[i] = 0;4.131 }4.133 - for( i=0; i<header.module_count; i++ ) {4.134 - fread(tmp, 4, 1, f );4.135 - if( strncmp(tmp, "BLCK", 4) != 0 ) {4.136 + for( i=0; i<module_count; i++ ) {4.137 + struct chunk_header chunk;4.138 + fread( &chunk, sizeof(chunk), 1, f );4.139 + if( strncmp(chunk.marker, "BLCK", 4) != 0 ) {4.140 ERROR( "%s save state is corrupted (missing block header %d)", APP_NAME, i );4.141 - return 2;4.142 - }4.143 - len = fread_string(tmp, sizeof(tmp), f );4.144 - if( len > 64 || len < 1 ) {4.145 - ERROR( "%s save state is corrupted (bad string)", APP_NAME );4.146 + fclose(f);4.147 return 2;4.148 }4.150 /* Find the matching module by name */4.151 for( j=0; j<num_modules; j++ ) {4.152 - if( strcmp(modules[j]->name,tmp) == 0 ) {4.153 + if( strcmp(modules[j]->name,chunk.name) == 0 ) {4.154 have_read[j] = 1;4.155 if( modules[j]->load == NULL ) {4.156 ERROR( "%s save state is corrupted (no loader for %s)", APP_NAME, modules[j]->name );4.157 + fclose(f);4.158 return 2;4.159 } else if( modules[j]->load(f) != 0 ) {4.160 ERROR( "%s save state is corrupted (%s failed)", APP_NAME, modules[j]->name );4.161 + fclose(f);4.162 return 2;4.163 }4.164 break;4.165 }4.166 }4.167 if( j == num_modules ) {4.168 + fclose(f);4.169 ERROR( "%s save state contains unrecognized section", APP_NAME );4.170 return 2;4.171 }4.172 @@ -315,9 +390,15 @@4.173 fwrite( &header, sizeof(header), 1, f );4.174 for( i=0; i<num_modules; i++ ) {4.175 if( modules[i]->save != NULL ) {4.176 - fwrite( "BLCK", 4, 1, f );4.177 - fwrite_string( modules[i]->name, f );4.178 + uint32_t blocklen, posn1, posn2;4.179 + dreamcast_write_chunk_header( modules[i]->name, 0, f );4.180 + posn1 = ftell(f);4.181 modules[i]->save(f);4.182 + posn2 = ftell(f);4.183 + blocklen = posn2 - posn1;4.184 + fseek( f, posn1-4, SEEK_SET );4.185 + fwrite( &blocklen, sizeof(blocklen), 1, f );4.186 + fseek( f, posn2, SEEK_SET );4.187 }4.188 }4.189 fclose( f );
5.1 --- a/src/dreamcast.h Wed Oct 31 09:07:25 2007 +00005.2 +++ b/src/dreamcast.h Wed Oct 31 09:10:23 2007 +00005.3 @@ -1,5 +1,5 @@5.4 /**5.5 - * $Id: dreamcast.h,v 1.20 2007-10-27 05:48:22 nkeynes Exp $5.6 + * $Id: dreamcast.h,v 1.21 2007-10-31 09:10:23 nkeynes Exp $5.7 *5.8 * Public interface for dreamcast.c -5.9 * Central switchboard for the system. This pulls all the individual modules5.10 @@ -23,7 +23,7 @@5.11 #define dreamcast_H 15.13 #include <stdio.h>5.14 -#include <glib/gtypes.h>5.15 +#include "lxdream.h"5.17 #ifdef __cplusplus5.18 extern "C" {5.19 @@ -31,9 +31,6 @@5.21 #define DEFAULT_TIMESLICE_LENGTH 1000000 /* nanoseconds */5.23 -#define MB *1024*10245.24 -#define KB *10245.25 -5.26 #define XLAT_NEW_CACHE_SIZE 32 MB5.27 #define XLAT_TEMP_CACHE_SIZE 2 MB5.28 #define XLAT_OLD_CACHE_SIZE 8 MB5.29 @@ -55,6 +52,15 @@5.30 int dreamcast_save_state( const gchar *filename );5.31 int dreamcast_load_state( const gchar *filename );5.33 +/**5.34 + * Load the front-buffer image from the specified file.5.35 + * If the file is not a valid save state, returns NULL. Otherwise,5.36 + * returns a newly allocated frame_buffer that should be freed5.37 + * by the caller. (The data buffer is contained within the5.38 + * allocation and does not need to be freed separately)5.39 + */5.40 +frame_buffer_t dreamcast_load_preview( const gchar *filename );5.41 +5.42 #define SCENE_SAVE_MAGIC "%!-lxDream!Scene"5.43 #define SCENE_SAVE_VERSION 0x00010000
6.1 --- a/src/drivers/gl_common.c Wed Oct 31 09:07:25 2007 +00006.2 +++ b/src/drivers/gl_common.c Wed Oct 31 09:10:23 2007 +00006.3 @@ -1,5 +1,5 @@6.4 /**6.5 - * $Id: gl_common.c,v 1.5 2007-10-14 09:30:16 nkeynes Exp $6.6 + * $Id: gl_common.c,v 1.6 2007-10-31 09:10:23 nkeynes Exp $6.7 *6.8 * Common GL code that doesn't depend on a specific implementation6.9 *6.10 @@ -23,13 +23,7 @@6.11 #include "drivers/gl_common.h"6.13 extern uint32_t video_width, video_height;6.14 -static GLuint frame_last_texid = 0, fbuf_id = 0;6.15 -static uint32_t frame_width = 0;6.16 -static uint32_t frame_height = 0;6.17 static uint32_t frame_colour = 0;6.18 -static gboolean frame_inverted = FALSE;6.19 -6.20 -6.22 char *required_extensions[] = { "GL_EXT_framebuffer_object", NULL };6.24 @@ -80,28 +74,15 @@6.25 return isOK;6.26 }6.28 -void gl_frame_buffer_to_tex_rectangle( frame_buffer_t frame, GLuint texid )6.29 -{6.30 - GLenum type = colour_formats[frame->colour_format].type;6.31 - GLenum format = colour_formats[frame->colour_format].format;6.32 - int bpp = colour_formats[frame->colour_format].bpp;6.33 - int rowstride = (frame->rowstride / bpp) - frame->width;6.34 -6.35 - glPixelStorei( GL_UNPACK_ROW_LENGTH, rowstride );6.36 - glBindTexture( GL_TEXTURE_RECTANGLE_ARB, texid );6.37 - glTexImage2D( GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGB,6.38 - frame->width, frame->height, 0, format, type, frame->data );6.39 -}6.40 -6.41 -void gl_display_tex_rectangle( GLuint texid, uint32_t tex_width, uint32_t tex_height, gboolean invert )6.42 +void gl_display_render_buffer( render_buffer_t buffer )6.43 {6.44 float top, bottom;6.45 - if( invert ) {6.46 - top = ((float)tex_height) - 0.5;6.47 + if( buffer->inverted ) {6.48 + top = ((float)buffer->height) - 0.5;6.49 bottom = 0.5;6.50 } else {6.51 top = 0.5;6.52 - bottom = ((float)tex_height) - 0.5;6.53 + bottom = ((float)buffer->height) - 0.5;6.54 }6.56 /* Reset display parameters */6.57 @@ -155,7 +136,7 @@6.59 /* Render the textured rectangle */6.60 glEnable( GL_TEXTURE_RECTANGLE_ARB );6.61 - glBindTexture( GL_TEXTURE_RECTANGLE_ARB, texid );6.62 + glBindTexture( GL_TEXTURE_RECTANGLE_ARB, buffer->buf_id );6.63 glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE );6.64 glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, GL_LINEAR);6.65 glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, GL_LINEAR);6.66 @@ -164,29 +145,28 @@6.67 glBegin( GL_QUADS );6.68 glTexCoord2f( 0.5, top );6.69 glVertex2f( x1, y1 );6.70 - glTexCoord2f( ((float)tex_width)-0.5, top );6.71 + glTexCoord2f( ((float)buffer->width)-0.5, top );6.72 glVertex2f( x2, y1 );6.73 - glTexCoord2f( ((float)tex_width)-0.5, bottom );6.74 + glTexCoord2f( ((float)buffer->width)-0.5, bottom );6.75 glVertex2f( x2, y2 );6.76 glTexCoord2f( 0.5, bottom );6.77 glVertex2f( x1, y2 );6.78 glEnd();6.79 glDisable( GL_TEXTURE_RECTANGLE_ARB );6.80 glFlush();6.81 - frame_last_texid = texid;6.82 - frame_width = tex_width;6.83 - frame_height = tex_height;6.84 - frame_inverted = invert;6.85 }6.87 -gboolean gl_display_frame_buffer( frame_buffer_t frame )6.88 +gboolean gl_load_frame_buffer( frame_buffer_t frame, render_buffer_t render )6.89 {6.90 - if( fbuf_id == 0 ) {6.91 - glGenTextures( 1, &fbuf_id );6.92 - }6.93 - gl_frame_buffer_to_tex_rectangle( frame, fbuf_id );6.94 - gl_display_tex_rectangle( fbuf_id, frame->width, frame->height, FALSE );6.95 - return TRUE;6.96 + GLenum type = colour_formats[frame->colour_format].type;6.97 + GLenum format = colour_formats[frame->colour_format].format;6.98 + int bpp = colour_formats[frame->colour_format].bpp;6.99 + int rowstride = (frame->rowstride / bpp) - frame->width;6.100 +6.101 + glPixelStorei( GL_UNPACK_ROW_LENGTH, rowstride );6.102 + glBindTexture( GL_TEXTURE_RECTANGLE_ARB, render->buf_id );6.103 + glTexSubImage2D( GL_TEXTURE_RECTANGLE_ARB, 0, 0,0,6.104 + frame->width, frame->height, format, type, frame->data );6.105 }6.107 gboolean gl_display_blank( uint32_t colour )6.108 @@ -201,16 +181,16 @@6.109 glRecti(0,0, video_width, video_height );6.110 glFlush();6.111 frame_colour = colour;6.112 - frame_last_texid = 0;6.113 return TRUE;6.114 }6.116 void gl_redisplay_last()6.117 {6.118 - if( frame_last_texid == 0 ) {6.119 + render_buffer_t buffer = pvr2_get_front_buffer();6.120 + if( buffer == NULL ) {6.121 gl_display_blank( frame_colour );6.122 } else {6.123 - gl_display_tex_rectangle( frame_last_texid, frame_width, frame_height, frame_inverted );6.124 + gl_display_render_buffer( buffer );6.125 }6.126 }6.128 @@ -219,17 +199,16 @@6.129 * has already set the appropriate glReadBuffer(); in other words, unless6.130 * there's only one buffer this needs to be wrapped.6.131 */6.132 -gboolean gl_read_render_buffer( render_buffer_t buffer, unsigned char *target )6.133 +gboolean gl_read_render_buffer( unsigned char *target, render_buffer_t buffer,6.134 + int rowstride, int colour_format )6.135 {6.136 - if( buffer->address == -1 )6.137 - return FALSE;6.138 glFinish();6.139 - GLenum type = colour_formats[buffer->colour_format].type;6.140 - GLenum format = colour_formats[buffer->colour_format].format;6.141 - // int line_size = buffer->width * colour_formats[buffer->colour_format].bpp;6.142 + GLenum type = colour_formats[colour_format].type;6.143 + GLenum format = colour_formats[colour_format].format;6.144 + // int line_size = buffer->width * colour_formats[colour_format].bpp;6.145 // int size = line_size * buffer->height;6.146 - // int rowstride = (buffer->rowstride / colour_formats[buffer->colour_format].bpp) - buffer->width;6.147 - // glPixelStorei( GL_PACK_ROW_LENGTH, rowstride );6.148 + int glrowstride = (rowstride / colour_formats[colour_format].bpp) - buffer->width;6.149 + glPixelStorei( GL_PACK_ROW_LENGTH, glrowstride );6.151 glReadPixels( 0, 0, buffer->width, buffer->height, format, type, target );6.152 return TRUE;
7.1 --- a/src/drivers/gl_common.h Wed Oct 31 09:07:25 2007 +00007.2 +++ b/src/drivers/gl_common.h Wed Oct 31 09:10:23 2007 +00007.3 @@ -1,5 +1,5 @@7.4 /**7.5 - * $Id: gl_common.h,v 1.4 2007-10-13 04:01:02 nkeynes Exp $7.6 + * $Id: gl_common.h,v 1.5 2007-10-31 09:10:23 nkeynes Exp $7.7 *7.8 * Parent for all X11 display drivers.7.9 *7.10 @@ -31,9 +31,9 @@7.11 gboolean hasRequiredGLExtensions();7.13 /**7.14 - * Generic GL routine to draw the given frame buffer in the display view.7.15 + * Generic GL routine to draw the given frame buffer into a render buffer7.16 */7.17 -gboolean gl_display_frame_buffer( frame_buffer_t frame );7.18 +gboolean gl_load_frame_buffer( frame_buffer_t frame, render_buffer_t buffer );7.20 /**7.21 * Generic GL routine to blank the display view with the specified colour.7.22 @@ -41,14 +41,9 @@7.23 gboolean gl_display_blank( uint32_t colour );7.25 /**7.26 - * Copy the frame buffer contents to the specified texture id7.27 - */7.28 -void gl_frame_buffer_to_tex_rectangle( frame_buffer_t frame, GLuint texid );7.29 -7.30 -/**7.31 * Write a rectangular texture (GL_TEXTURE_RECTANGLE_ARB) to the display frame7.32 */7.33 -void gl_display_tex_rectangle( GLuint texid, uint32_t texwidth, uint32_t texheight, gboolean invert );7.34 +void gl_display_render_buffer( render_buffer_t buffer );7.36 /**7.37 * Redisplay the last frame.7.38 @@ -60,13 +55,15 @@7.39 * has already set the appropriate glReadBuffer(); in other words, unless7.40 * there's only one buffer this needs to be wrapped.7.41 */7.42 -gboolean gl_read_render_buffer( render_buffer_t buffer, unsigned char *target );7.43 +gboolean gl_read_render_buffer( unsigned char *target, render_buffer_t buffer,7.44 + int rowstride, int colour_format );7.47 /****** FBO handling (gl_fbo.c) ******/7.48 gboolean gl_fbo_is_supported();7.49 void gl_fbo_shutdown();7.50 void gl_fbo_init( display_driver_t driver );7.51 +void gl_fbo_detach();7.53 /****** Shader handling (gl_sl.c) *****/7.54 gboolean glsl_is_supported(void);
8.1 --- a/src/drivers/gl_fbo.c Wed Oct 31 09:07:25 2007 +00008.2 +++ b/src/drivers/gl_fbo.c Wed Oct 31 09:10:23 2007 +00008.3 @@ -1,5 +1,5 @@8.4 /**8.5 - * $Id: gl_fbo.c,v 1.6 2007-10-16 12:27:28 nkeynes Exp $8.6 + * $Id: gl_fbo.c,v 1.7 2007-10-31 09:10:23 nkeynes Exp $8.7 *8.8 * GL framebuffer-based driver shell. This requires the EXT_framebuffer_object8.9 * extension, but is much nicer/faster/etc than pbuffers when it's available.8.10 @@ -26,6 +26,8 @@8.12 #include <GL/gl.h>8.13 #include <GL/glext.h>8.14 +#include <stdlib.h>8.15 +#include "lxdream.h"8.16 #include "display.h"8.17 #include "drivers/video_x11.h"8.18 #include "drivers/gl_common.h"8.19 @@ -37,9 +39,9 @@8.20 static void gl_fbo_destroy_render_buffer( render_buffer_t buffer );8.21 static gboolean gl_fbo_set_render_target( render_buffer_t buffer );8.22 static gboolean gl_fbo_display_render_buffer( render_buffer_t buffer );8.23 -static gboolean gl_fbo_display_frame_buffer( frame_buffer_t buffer );8.24 +static void gl_fbo_load_frame_buffer( frame_buffer_t frame, render_buffer_t buffer );8.25 static gboolean gl_fbo_display_blank( uint32_t colour );8.26 -static gboolean gl_fbo_read_render_buffer( render_buffer_t buffer, unsigned char *target );8.27 +static gboolean gl_fbo_read_render_buffer( unsigned char *target, render_buffer_t buffer, int rowstride, int format );8.29 extern uint32_t video_width, video_height;8.31 @@ -93,7 +95,7 @@8.32 driver->destroy_render_buffer = gl_fbo_destroy_render_buffer;8.33 driver->set_render_target = gl_fbo_set_render_target;8.34 driver->display_render_buffer = gl_fbo_display_render_buffer;8.35 - driver->display_frame_buffer = gl_fbo_display_frame_buffer;8.36 + driver->load_frame_buffer = gl_fbo_load_frame_buffer;8.37 driver->display_blank = gl_fbo_display_blank;8.38 driver->read_render_buffer = gl_fbo_read_render_buffer;8.40 @@ -218,6 +220,7 @@8.41 for( i=0; i<MAX_FRAMEBUFFERS; i++ ) {8.42 for( j=0; j < MAX_TEXTURES_PER_FB; j++ ) {8.43 if( fbo[i].tex_ids[j] == buffer->buf_id ) {8.44 + glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbo[i].fb_id);8.45 glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, ATTACHMENT_POINTS[j],8.46 GL_TEXTURE_RECTANGLE_ARB, GL_NONE, 0 );8.47 fbo[i].tex_ids[j] = -1;8.48 @@ -232,6 +235,7 @@8.50 static gboolean gl_fbo_set_render_target( render_buffer_t buffer )8.51 {8.52 + glFinish();8.53 glGetError();8.54 int fb = gl_fbo_get_framebuffer( buffer->width, buffer->height );8.55 gl_fbo_attach_texture( fb, buffer->buf_id );8.56 @@ -248,66 +252,37 @@8.57 static gboolean gl_fbo_display_render_buffer( render_buffer_t buffer )8.58 {8.59 glFinish();8.60 - glBindFramebufferEXT( GL_FRAMEBUFFER_EXT, 0 ); // real window8.61 - glDrawBuffer( GL_FRONT );8.62 - glReadBuffer( GL_FRONT );8.63 - gl_display_tex_rectangle( buffer->buf_id, buffer->width, buffer->height, TRUE );8.64 - /*8.65 - glViewport( 0, 0, video_width, video_height );8.66 - glEnable( GL_TEXTURE_RECTANGLE_ARB );8.67 - glBindTexture( GL_TEXTURE_RECTANGLE_ARB, buffer->buf_id );8.68 - glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE );8.69 - glTexParameteri( GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, GL_LINEAR );8.70 - glTexParameteri( GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, GL_LINEAR );8.71 - glDisable( GL_ALPHA_TEST );8.72 - glDisable( GL_DEPTH_TEST );8.73 - glDisable( GL_SCISSOR_TEST );8.74 - glDisable( GL_CULL_FACE );8.75 -8.76 - glMatrixMode(GL_PROJECTION);8.77 - glLoadIdentity();8.78 - glOrtho( 0, buffer->width, buffer->height, 0, 0, -65535 );8.79 - glMatrixMode(GL_MODELVIEW);8.80 - glLoadIdentity();8.81 - glEnable( GL_BLEND );8.82 - glBlendFunc( GL_ONE, GL_ZERO );8.83 - glDisable( GL_DEPTH_TEST );8.84 - glBegin( GL_QUADS );8.85 - glTexCoord2i( 0.5, buffer->height-0.5 );8.86 - glVertex2f( 0.0, 0.0 );8.87 - glTexCoord2i( buffer->width-0.5, buffer->height-0.5 );8.88 - glVertex2f( buffer->width, 0.0 );8.89 - glTexCoord2i( buffer->width-0.5, 0 );8.90 - glVertex2f( buffer->width, buffer->height );8.91 - glTexCoord2i( 0.5, 0.5 );8.92 - glVertex2f( 0.0, buffer->height );8.93 - glEnd();8.94 - glDisable( GL_TEXTURE_RECTANGLE_ARB );8.95 - glFlush();8.96 - */8.97 + gl_fbo_detach();8.98 + gl_display_render_buffer( buffer );8.99 return TRUE;8.100 }8.102 -static gboolean gl_fbo_display_frame_buffer( frame_buffer_t buffer )8.103 +static void gl_fbo_load_frame_buffer( frame_buffer_t frame, render_buffer_t buffer )8.104 +{8.105 + glFinish();8.106 + gl_fbo_detach();8.107 + gl_load_frame_buffer( frame, buffer );8.108 +}8.109 +8.110 +static gboolean gl_fbo_display_blank( uint32_t colour )8.111 +{8.112 + glFinish();8.113 + gl_fbo_detach();8.114 + return gl_display_blank( colour );8.115 +}8.116 +8.117 +void gl_fbo_detach()8.118 {8.119 glBindFramebufferEXT( GL_FRAMEBUFFER_EXT, 0 );8.120 glDrawBuffer( GL_FRONT );8.121 glReadBuffer( GL_FRONT );8.122 - return gl_display_frame_buffer( buffer );8.123 -}8.124 +}8.126 -static gboolean gl_fbo_display_blank( uint32_t colour )8.127 -{8.128 - glBindFramebufferEXT( GL_FRAMEBUFFER_EXT, 0 );8.129 - glDrawBuffer( GL_FRONT );8.130 - glReadBuffer( GL_FRONT );8.131 - return gl_display_blank( colour );8.132 -}8.133 -8.134 -static gboolean gl_fbo_read_render_buffer( render_buffer_t buffer, unsigned char *target )8.135 +static gboolean gl_fbo_read_render_buffer( unsigned char *target, render_buffer_t buffer,8.136 + int rowstride, int format )8.137 {8.138 int fb = gl_fbo_get_framebuffer( buffer->width, buffer->height );8.139 gl_fbo_attach_texture( fb, buffer->buf_id );8.140 - return gl_read_render_buffer( buffer, target );8.141 + return gl_read_render_buffer( target, buffer, rowstride, format );8.142 }
9.1 --- a/src/drivers/gl_sl.c Wed Oct 31 09:07:25 2007 +00009.2 +++ b/src/drivers/gl_sl.c Wed Oct 31 09:10:23 2007 +00009.3 @@ -1,5 +1,5 @@9.4 /**9.5 - * $Id: gl_sl.c,v 1.2 2007-10-07 05:42:25 nkeynes Exp $9.6 + * $Id: gl_sl.c,v 1.3 2007-10-31 09:10:23 nkeynes Exp $9.7 *9.8 * GLSL shader loader/unloader. Current version assumes there's exactly9.9 * 1 shader program that's used globally. This may turn out not to be the9.10 @@ -22,6 +22,7 @@9.12 #include <GL/gl.h>9.13 #include <GL/glext.h>9.14 +#include "lxdream.h"9.15 #include "drivers/gl_common.h"9.16 #include "display.h"
10.1 --- a/src/drivers/video_gtk.c Wed Oct 31 09:07:25 2007 +000010.2 +++ b/src/drivers/video_gtk.c Wed Oct 31 09:10:23 2007 +000010.3 @@ -1,5 +1,5 @@10.4 /**10.5 - * $Id: video_gtk.c,v 1.16 2007-10-16 12:38:01 nkeynes Exp $10.6 + * $Id: video_gtk.c,v 1.17 2007-10-31 09:10:23 nkeynes Exp $10.7 *10.8 * The PC side of the video support (responsible for actually displaying /10.9 * rendering frames)10.10 @@ -79,6 +79,7 @@10.12 gboolean video_gtk_expose_callback(GtkWidget *widget, GdkEventExpose *event, gpointer data )10.13 {10.14 + gl_fbo_detach();10.15 gl_redisplay_last();10.16 return TRUE;10.17 }10.18 @@ -87,6 +88,7 @@10.19 {10.20 video_width = event->width;10.21 video_height = event->height;10.22 + gl_fbo_detach();10.23 gl_redisplay_last();10.24 return TRUE;10.25 }
11.1 --- a/src/drivers/video_null.c Wed Oct 31 09:07:25 2007 +000011.2 +++ b/src/drivers/video_null.c Wed Oct 31 09:10:23 2007 +000011.3 @@ -1,5 +1,5 @@11.4 /**11.5 - * $Id: video_null.c,v 1.5 2007-10-08 11:49:35 nkeynes Exp $11.6 + * $Id: video_null.c,v 1.6 2007-10-31 09:10:23 nkeynes Exp $11.7 *11.8 * Null video output driver (ie no video output whatsoever)11.9 *11.10 @@ -37,7 +37,7 @@11.11 return TRUE;11.12 }11.14 -gboolean video_null_read_render_buffer( render_buffer_t buffer, unsigned char *target )11.15 +gboolean video_null_read_render_buffer( unsigned char *target, render_buffer_t buffer, int format )11.16 {11.17 return TRUE;11.18 }
12.1 --- a/src/gui/gtkcb.c Wed Oct 31 09:07:25 2007 +000012.2 +++ b/src/gui/gtkcb.c Wed Oct 31 09:10:23 2007 +000012.3 @@ -1,5 +1,5 @@12.4 /**12.5 - * $Id: gtkcb.c,v 1.5 2007-10-21 05:21:35 nkeynes Exp $12.6 + * $Id: gtkcb.c,v 1.6 2007-10-31 09:10:23 nkeynes Exp $12.7 *12.8 * Action callbacks from the main window12.9 *12.10 @@ -46,21 +46,6 @@12.11 }12.14 -void open_file_callback(GtkWidget *btn, gint result, gpointer user_data) {12.15 - GtkFileChooser *file = GTK_FILE_CHOOSER(user_data);12.16 - if( result == GTK_RESPONSE_ACCEPT ) {12.17 - gchar *filename =gtk_file_chooser_get_filename(12.18 - GTK_FILE_CHOOSER(file) );12.19 - file_callback_t action = (file_callback_t)gtk_object_get_data( GTK_OBJECT(file), "file_action" );12.20 - gtk_widget_destroy(GTK_WIDGET(file));12.21 - action( filename );12.22 - g_free(filename);12.23 - } else {12.24 - gtk_widget_destroy(GTK_WIDGET(file));12.25 - }12.26 - dreamcast_unpause();12.27 -}12.28 -12.29 static void add_file_pattern( GtkFileChooser *chooser, char *pattern, char *patname )12.30 {12.31 if( pattern != NULL ) {12.32 @@ -79,38 +64,42 @@12.33 gchar const *initial_dir )12.34 {12.35 GtkWidget *file;12.36 - dreamcast_pause();12.37 file = gtk_file_chooser_dialog_new( title, NULL,12.38 GTK_FILE_CHOOSER_ACTION_OPEN,12.39 GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,12.40 GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT,12.41 NULL );12.42 add_file_pattern( GTK_FILE_CHOOSER(file), pattern, patname );12.43 - g_signal_connect( GTK_OBJECT(file), "response",12.44 - GTK_SIGNAL_FUNC(open_file_callback), file );12.45 - gtk_object_set_data( GTK_OBJECT(file), "file_action", action );12.46 gtk_file_chooser_set_current_folder( GTK_FILE_CHOOSER(file), initial_dir );12.47 gtk_window_set_modal( GTK_WINDOW(file), TRUE );12.48 - gtk_widget_show( file );12.49 + gtk_dialog_set_default_response( GTK_DIALOG(file), GTK_RESPONSE_ACCEPT );12.50 + int result = gtk_dialog_run( GTK_DIALOG(file) );12.51 + if( result == GTK_RESPONSE_ACCEPT ) {12.52 + gchar *filename = gtk_file_chooser_get_filename( GTK_FILE_CHOOSER(file) );12.53 + action( filename );12.54 + }12.55 + gtk_widget_destroy(file);12.56 }12.58 void save_file_dialog( char *title, file_callback_t action, char *pattern, char *patname,12.59 gchar const *initial_dir )12.60 {12.61 GtkWidget *file;12.62 - dreamcast_pause();12.63 file = gtk_file_chooser_dialog_new( title, NULL,12.64 GTK_FILE_CHOOSER_ACTION_SAVE,12.65 GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,12.66 GTK_STOCK_SAVE, GTK_RESPONSE_ACCEPT,12.67 NULL );12.68 add_file_pattern( GTK_FILE_CHOOSER(file), pattern, patname );12.69 - g_signal_connect( GTK_OBJECT(file), "response",12.70 - GTK_SIGNAL_FUNC(open_file_callback), file );12.71 - gtk_object_set_data( GTK_OBJECT(file), "file_action", action );12.72 gtk_file_chooser_set_current_folder( GTK_FILE_CHOOSER(file), initial_dir );12.73 gtk_window_set_modal( GTK_WINDOW(file), TRUE );12.74 - gtk_widget_show( file );12.75 + gtk_dialog_set_default_response( GTK_DIALOG(file), GTK_RESPONSE_ACCEPT );12.76 + int result = gtk_dialog_run( GTK_DIALOG(file) );12.77 + if( result == GTK_RESPONSE_ACCEPT ) {12.78 + gchar *filename = gtk_file_chooser_get_filename( GTK_FILE_CHOOSER(file) );12.79 + action( filename );12.80 + }12.81 + gtk_widget_destroy(file);12.82 }12.84 void mount_action_callback( GtkAction *action, gpointer user_data)12.85 @@ -133,11 +122,62 @@12.86 dreamcast_run();12.87 }12.89 +void load_state_preview_callback( GtkFileChooser *chooser, gpointer user_data )12.90 +{12.91 + GtkWidget *preview = GTK_WIDGET(user_data);12.92 + gchar *filename = gtk_file_chooser_get_preview_filename(chooser);12.93 +12.94 + frame_buffer_t data = dreamcast_load_preview(filename);12.95 + if( data != NULL ) {12.96 + GdkPixbuf *pixbuf = gdk_pixbuf_new_from_frame_buffer(data);12.97 + GdkPixbuf *scaled = gdk_pixbuf_scale_simple(pixbuf, 320, 240,12.98 + GDK_INTERP_BILINEAR);12.99 + g_object_unref(pixbuf);12.100 + gtk_image_set_from_pixbuf( GTK_IMAGE(preview), scaled );12.101 + g_object_unref(scaled);12.102 + gtk_widget_show(preview);12.103 + } else {12.104 + gtk_widget_hide(preview);12.105 + }12.106 +}12.107 +12.108 void load_state_action_callback( GtkAction *action, gpointer user_data)12.109 {12.110 + GtkWidget *file, *preview, *frame, *align;12.111 + GtkRequisition size;12.112 const gchar *dir = lxdream_get_config_value(CONFIG_SAVE_PATH);12.113 - open_file_dialog( "Load state...", dreamcast_load_state, "*.dst", "lxDream Save State (*.dst)", dir );12.114 + file = gtk_file_chooser_dialog_new( "Load state...", NULL,12.115 + GTK_FILE_CHOOSER_ACTION_OPEN,12.116 + GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,12.117 + GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT,12.118 + NULL );12.119 + add_file_pattern( GTK_FILE_CHOOSER(file), "*.dst", "lxDream Save State (*.dst)" );12.120 + gtk_object_set_data( GTK_OBJECT(file), "file_action", action );12.121 +12.122 + preview = gtk_image_new( );12.123 +12.124 + frame = gtk_frame_new(NULL);12.125 + gtk_frame_set_shadow_type( GTK_FRAME(frame), GTK_SHADOW_IN );12.126 + gtk_container_add( GTK_CONTAINER(frame), preview );12.127 + gtk_widget_show(frame);12.128 + gtk_widget_size_request(frame, &size);12.129 + gtk_widget_set_size_request(frame, size.width + 320, size.height + 240);12.130 + align = gtk_alignment_new(0.5, 0.5, 0, 0 );12.131 + gtk_container_add( GTK_CONTAINER(align), frame );12.132 + gtk_widget_show( align );12.133 + gtk_file_chooser_set_preview_widget(GTK_FILE_CHOOSER(file), align);12.134 + g_signal_connect( file, "update-preview", G_CALLBACK(load_state_preview_callback),12.135 + preview );12.136 + gtk_file_chooser_set_current_folder( GTK_FILE_CHOOSER(file), dir );12.137 + gtk_window_set_modal( GTK_WINDOW(file), TRUE );12.138 + int result = gtk_dialog_run( GTK_DIALOG(file) );12.139 + if( result == GTK_RESPONSE_ACCEPT ) {12.140 + gchar *filename = gtk_file_chooser_get_filename( GTK_FILE_CHOOSER(file) );12.141 + dreamcast_load_state( filename );12.142 + }12.143 + gtk_widget_destroy(file);12.144 }12.145 +12.146 void save_state_action_callback( GtkAction *action, gpointer user_data)12.147 {12.148 const gchar *dir = lxdream_get_config_value(CONFIG_SAVE_PATH);
13.1 --- a/src/gui/gtkui.c Wed Oct 31 09:07:25 2007 +000013.2 +++ b/src/gui/gtkui.c Wed Oct 31 09:10:23 2007 +000013.3 @@ -1,5 +1,5 @@13.4 /**13.5 - * $Id: gtkui.c,v 1.8 2007-10-28 08:29:29 nkeynes Exp $13.6 + * $Id: gtkui.c,v 1.9 2007-10-31 09:10:23 nkeynes Exp $13.7 *13.8 * Core GTK-based user interface13.9 *13.10 @@ -20,6 +20,7 @@13.11 #include <time.h>13.12 #include "dream.h"13.13 #include "dreamcast.h"13.14 +#include "display.h"13.15 #include "gdrom/gdrom.h"13.16 #include "gui/gtkui.h"13.18 @@ -134,7 +135,7 @@13.19 " </toolbar>"13.20 " <menubar name='DebugMenu'>"13.21 " <menu action='FileMenu'>"13.22 - " <menuitem action='GdromMount'/>"13.23 + " <menuitem action='GdromSettings'/>"13.24 " <separator/>"13.25 " <menuitem action='Reset'/>"13.26 " <separator/>"13.27 @@ -263,6 +264,9 @@13.28 GtkAccelGroup *accel_group = gtk_ui_manager_get_accel_group (global_ui_manager);13.29 GtkWidget *menubar = gtk_ui_manager_get_widget(global_ui_manager, "/DebugMenu");13.30 GtkWidget *toolbar = gtk_ui_manager_get_widget(global_ui_manager, "/DebugToolbar");13.31 + GtkWidget *gdrommenuitem = gtk_ui_manager_get_widget(global_ui_manager, "/DebugMenu/FileMenu/GdromSettings");13.32 + GtkWidget *gdrommenu = gdrom_menu_new();13.33 + gtk_menu_item_set_submenu( GTK_MENU_ITEM(gdrommenuitem), gdrommenu );13.34 debug_win = debug_window_new( APP_NAME " " APP_VERSION " :: Debugger", menubar, toolbar, accel_group );13.35 }13.36 }13.37 @@ -423,3 +427,23 @@13.38 {13.39 gtk_action_set_sensitive( gtk_action_group_get_action( global_action_group, action), enable);13.40 }13.41 +13.42 +static void delete_frame_buffer( guchar *pixels, gpointer buffer )13.43 +{13.44 + if( buffer != NULL ) {13.45 + g_free(buffer);13.46 + }13.47 +}13.48 +13.49 +GdkPixbuf *gdk_pixbuf_new_from_frame_buffer( frame_buffer_t buffer )13.50 +{13.51 + return gdk_pixbuf_new_from_data( buffer->data,13.52 + GDK_COLORSPACE_RGB,13.53 + (buffer->colour_format == COLFMT_BGRA8888),13.54 + 8,13.55 + buffer->width,13.56 + buffer->height,13.57 + buffer->rowstride,13.58 + delete_frame_buffer,13.59 + buffer );13.60 +}
14.1 --- a/src/gui/gtkui.h Wed Oct 31 09:07:25 2007 +000014.2 +++ b/src/gui/gtkui.h Wed Oct 31 09:10:23 2007 +000014.3 @@ -1,5 +1,5 @@14.4 /**14.5 - * $Id: gtkui.h,v 1.8 2007-10-28 08:29:29 nkeynes Exp $14.6 + * $Id: gtkui.h,v 1.9 2007-10-31 09:10:23 nkeynes Exp $14.7 *14.8 * Core GTK-based user interface14.9 *14.10 @@ -71,6 +71,11 @@14.11 void gtk_gui_enable_action( const gchar *action, gboolean enabled );14.12 gint gtk_gui_run_property_dialog( const gchar *title, GtkWidget *panel, gtk_dialog_done_fn fn );14.14 +/**14.15 + * Construct a new pixbuf that takes ownership of the frame buffer14.16 + */14.17 +GdkPixbuf *gdk_pixbuf_new_from_frame_buffer( frame_buffer_t );14.18 +14.19 void gdrom_menu_init();14.20 GtkWidget *gdrom_menu_new();
15.1 --- /dev/null Thu Jan 01 00:00:00 1970 +000015.2 +++ b/src/lxdream.h Wed Oct 31 09:10:23 2007 +000015.3 @@ -0,0 +1,77 @@15.4 +/**15.5 + * $Id: lxdream.h,v 1.1 2007-10-31 09:10:23 nkeynes Exp $15.6 + *15.7 + * Common type definitions and forward declarations15.8 + *15.9 + * Copyright (c) 2005 Nathan Keynes.15.10 + *15.11 + * This program is free software; you can redistribute it and/or modify15.12 + * it under the terms of the GNU General Public License as published by15.13 + * the Free Software Foundation; either version 2 of the License, or15.14 + * (at your option) any later version.15.15 + *15.16 + * This program is distributed in the hope that it will be useful,15.17 + * but WITHOUT ANY WARRANTY; without even the implied warranty of15.18 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the15.19 + * GNU General Public License for more details.15.20 + */15.21 +15.22 +#ifndef lxdream_common_H15.23 +#define lxdream_common_H 115.24 +15.25 +#include <stdint.h>15.26 +#include <glib/gtypes.h>15.27 +15.28 +#ifdef __cplusplus15.29 +extern "C" {15.30 +#endif15.31 +15.32 +#define APP_NAME "lxDream"15.33 +#define APP_VERSION "0.8"15.34 +15.35 +#define MB *1024*102415.36 +#define KB *102415.37 +15.38 +#ifndef max15.39 +#define max(a,b) ( (a) > (b) ? (a) : (b) )15.40 +#endif15.41 +15.42 +15.43 +typedef uint32_t sh4addr_t;15.44 +15.45 +/******************* Forward type declarations ******************/15.46 +15.47 +typedef struct render_buffer *render_buffer_t;15.48 +typedef struct frame_buffer *frame_buffer_t;15.49 +15.50 +/*************************** Logging ****************************/15.51 +15.52 +#define EMIT_FATAL 015.53 +#define EMIT_ERR 115.54 +#define EMIT_WARN 215.55 +#define EMIT_INFO 315.56 +#define EMIT_DEBUG 415.57 +#define EMIT_TRACE 515.58 +15.59 +#ifdef MODULE15.60 +#define MODULE_NAME MODULE.name15.61 +#else15.62 +#define MODULE_NAME "*****"15.63 +#endif15.64 +15.65 +void log_message( void *, int level, const char *source, const char *msg, ... );15.66 +15.67 +#define FATAL( ... ) log_message( NULL, EMIT_FATAL, MODULE_NAME, __VA_ARGS__ )15.68 +#define ERROR( ... ) log_message( NULL, EMIT_ERR, MODULE_NAME, __VA_ARGS__ )15.69 +#define WARN( ... ) log_message( NULL, EMIT_WARN, MODULE_NAME, __VA_ARGS__ )15.70 +#define INFO( ... ) log_message( NULL, EMIT_INFO, MODULE_NAME, __VA_ARGS__ )15.71 +#define DEBUG( ... ) log_message( NULL, EMIT_DEBUG, MODULE_NAME, __VA_ARGS__ )15.72 +#define TRACE( ... ) log_message( NULL, EMIT_TRACE, MODULE_NAME, __VA_ARGS__ )15.73 +15.74 +15.75 +15.76 +#ifdef __cplusplus15.77 +}15.78 +#endif15.79 +15.80 +#endif /* !lxdream_common_H */
16.1 --- a/src/mem.c Wed Oct 31 09:07:25 2007 +000016.2 +++ b/src/mem.c Wed Oct 31 09:10:23 2007 +000016.3 @@ -1,5 +1,5 @@16.4 /**16.5 - * $Id: mem.c,v 1.17 2007-10-27 05:47:55 nkeynes Exp $16.6 + * $Id: mem.c,v 1.18 2007-10-31 09:10:23 nkeynes Exp $16.7 * mem.c is responsible for creating and maintaining the overall system memory16.8 * map, as visible from the SH4 processor.16.9 *16.10 @@ -99,7 +99,7 @@16.11 fwrite( &mem_rgn[i].flags, sizeof(int), 1, f );16.12 fwrite( &mem_rgn[i].size, sizeof(uint32_t), 1, f );16.13 if( mem_rgn[i].flags != MEM_FLAG_ROM )16.14 - fwrite( mem_rgn[i].mem, mem_rgn[i].size, 1, f );16.15 + fwrite_gzip( mem_rgn[i].mem, mem_rgn[i].size, 1, f );16.16 }16.18 /* All MMIO regions */16.19 @@ -109,7 +109,7 @@16.20 fwrite( &io_rgn[i]->base, sizeof( uint32_t ), 1, f );16.21 len = 4096;16.22 fwrite( &len, sizeof(len), 1, f );16.23 - fwrite( io_rgn[i]->mem, len, 1, f );16.24 + fwrite_gzip( io_rgn[i]->mem, len, 1, f );16.25 }16.26 }16.28 @@ -138,7 +138,7 @@16.29 return -1;16.30 }16.31 if( flags != MEM_FLAG_ROM )16.32 - fread( mem_rgn[i].mem, size, 1, f );16.33 + fread_gzip( mem_rgn[i].mem, size, 1, f );16.34 }16.36 /* All MMIO regions */16.37 @@ -155,7 +155,7 @@16.38 ERROR( "Bad MMIO region %d %s", i, tmp );16.39 return -1;16.40 }16.41 - fread( io_rgn[i]->mem, size, 1, f );16.42 + fread_gzip( io_rgn[i]->mem, size, 1, f );16.43 }16.44 return 0;16.45 }
17.1 --- a/src/mem.h Wed Oct 31 09:07:25 2007 +000017.2 +++ b/src/mem.h Wed Oct 31 09:10:23 2007 +000017.3 @@ -1,5 +1,5 @@17.4 /**17.5 - * $Id: mem.h,v 1.14 2007-10-27 05:47:55 nkeynes Exp $17.6 + * $Id: mem.h,v 1.15 2007-10-31 09:10:23 nkeynes Exp $17.7 *17.8 * mem is responsible for creating and maintaining the overall system memory17.9 * map, as visible from the SH4 processor. (Note the ARM has a different map)17.10 @@ -21,7 +21,7 @@17.11 #define dream_mem_H17.13 #include <stdint.h>17.14 -#include "dream.h"17.15 +#include "lxdream.h"17.17 #ifdef __cplusplus17.18 extern "C" {
18.1 --- a/src/pvr2/pvr2.c Wed Oct 31 09:07:25 2007 +000018.2 +++ b/src/pvr2/pvr2.c Wed Oct 31 09:10:23 2007 +000018.3 @@ -1,5 +1,5 @@18.4 /**18.5 - * $Id: pvr2.c,v 1.47 2007-10-13 03:59:32 nkeynes Exp $18.6 + * $Id: pvr2.c,v 1.48 2007-10-31 09:10:23 nkeynes Exp $18.7 *18.8 * PVR2 (Video) Core module implementation and MMIO registers.18.9 *18.10 @@ -17,6 +17,7 @@18.11 */18.12 #define MODULE pvr2_module18.14 +#include <assert.h>18.15 #include "dream.h"18.16 #include "eventq.h"18.17 #include "display.h"18.18 @@ -44,11 +45,12 @@18.19 static void pvr2_schedule_scanline_event( int eventid, int line, int minimum_lines, int line_time_ns );18.20 static render_buffer_t pvr2_get_render_buffer( frame_buffer_t frame );18.21 static render_buffer_t pvr2_next_render_buffer( );18.22 +static render_buffer_t pvr2_frame_buffer_to_render_buffer( frame_buffer_t frame );18.23 uint32_t pvr2_get_sync_status();18.25 void pvr2_display_frame( void );18.27 -static int output_colour_formats[] = { COLFMT_ARGB1555, COLFMT_RGB565, COLFMT_RGB888, COLFMT_ARGB8888 };18.28 +static int output_colour_formats[] = { COLFMT_BGRA1555, COLFMT_RGB565, COLFMT_BGR888, COLFMT_BGRA8888 };18.30 struct dreamcast_module pvr2_module = { "PVR2", pvr2_init, pvr2_reset, NULL,18.31 pvr2_run_slice, NULL,18.32 @@ -142,6 +144,7 @@18.34 static void pvr2_reset( void )18.35 {18.36 + int i;18.37 pvr2_state.line_count = 0;18.38 pvr2_state.line_remainder = 0;18.39 pvr2_state.cycles_run = 0;18.40 @@ -157,10 +160,113 @@18.42 pvr2_ta_init();18.43 texcache_flush();18.44 + if( display_driver ) {18.45 + display_driver->display_blank(0);18.46 + for( i=0; i<render_buffer_count; i++ ) {18.47 + display_driver->destroy_render_buffer(render_buffers[i]);18.48 + render_buffers[i] = NULL;18.49 + }18.50 + render_buffer_count = 0;18.51 + }18.52 }18.54 +void pvr2_save_render_buffer( FILE *f, render_buffer_t buffer )18.55 +{18.56 + struct frame_buffer fbuf;18.57 +18.58 + fbuf.width = buffer->width;18.59 + fbuf.height = buffer->height;18.60 + fbuf.rowstride = fbuf.width*3;18.61 + fbuf.colour_format = COLFMT_BGR888;18.62 + fbuf.inverted = buffer->inverted;18.63 + fbuf.data = g_malloc0( buffer->width * buffer->height * 3 );18.64 +18.65 + display_driver->read_render_buffer( fbuf.data, buffer, fbuf.rowstride, COLFMT_BGR888 );18.66 + write_png_to_stream( f, &fbuf );18.67 + g_free( fbuf.data );18.68 +18.69 + fwrite( &buffer->rowstride, sizeof(buffer->rowstride), 1, f );18.70 + fwrite( &buffer->colour_format, sizeof(buffer->colour_format), 1, f );18.71 + fwrite( &buffer->address, sizeof(buffer->address), 1, f );18.72 + fwrite( &buffer->scale, sizeof(buffer->scale), 1, f );18.73 + fwrite( &buffer->flushed, sizeof(buffer->flushed), 1, f );18.74 +18.75 +}18.76 +18.77 +render_buffer_t pvr2_load_render_buffer( FILE *f )18.78 +{18.79 + frame_buffer_t frame = read_png_from_stream( f );18.80 + if( frame == NULL ) {18.81 + return NULL;18.82 + }18.83 +18.84 + render_buffer_t buffer = pvr2_frame_buffer_to_render_buffer(frame);18.85 + assert( buffer != NULL );18.86 + fread( &buffer->rowstride, sizeof(buffer->rowstride), 1, f );18.87 + fread( &buffer->colour_format, sizeof(buffer->colour_format), 1, f );18.88 + fread( &buffer->address, sizeof(buffer->address), 1, f );18.89 + fread( &buffer->scale, sizeof(buffer->scale), 1, f );18.90 + fread( &buffer->flushed, sizeof(buffer->flushed), 1, f );18.91 + return buffer;18.92 +}18.93 +18.94 +18.95 +18.96 +18.97 +void pvr2_save_render_buffers( FILE *f )18.98 +{18.99 + int i;18.100 + fwrite( &render_buffer_count, sizeof(render_buffer_count), 1, f );18.101 + if( displayed_render_buffer != NULL ) {18.102 + i = 1;18.103 + fwrite( &i, sizeof(i), 1, f );18.104 + pvr2_save_render_buffer( f, displayed_render_buffer );18.105 + } else {18.106 + i = 0;18.107 + fwrite( &i, sizeof(i), 1, f );18.108 + }18.109 +18.110 + for( i=0; i<render_buffer_count; i++ ) {18.111 + if( render_buffers[i] != displayed_render_buffer && render_buffers[i] != NULL ) {18.112 + pvr2_save_render_buffer( f, render_buffers[i] );18.113 + }18.114 + }18.115 +}18.116 +18.117 +gboolean pvr2_load_render_buffers( FILE *f )18.118 +{18.119 + uint32_t count;18.120 + int i, has_frontbuffer;18.121 +18.122 + fread( &count, sizeof(count), 1, f );18.123 + if( count >= MAX_RENDER_BUFFERS ) {18.124 + return FALSE;18.125 + }18.126 + fread( &has_frontbuffer, sizeof(has_frontbuffer), 1, f );18.127 + for( i=0; i<render_buffer_count; i++ ) {18.128 + display_driver->destroy_render_buffer(render_buffers[i]);18.129 + render_buffers[i] = NULL;18.130 + }18.131 + render_buffer_count = 0;18.132 +18.133 + if( has_frontbuffer ) {18.134 + displayed_render_buffer = pvr2_load_render_buffer(f);18.135 + display_driver->display_render_buffer( displayed_render_buffer );18.136 + count--;18.137 + }18.138 +18.139 + for( i=0; i<count; i++ ) {18.140 + if( pvr2_load_render_buffer( f ) == NULL ) {18.141 + return FALSE;18.142 + }18.143 + }18.144 + return TRUE;18.145 +}18.146 +18.147 +18.148 static void pvr2_save_state( FILE *f )18.149 {18.150 + pvr2_save_render_buffers( f );18.151 fwrite( &pvr2_state, sizeof(pvr2_state), 1, f );18.152 pvr2_ta_save_state( f );18.153 pvr2_yuv_save_state( f );18.154 @@ -168,6 +274,8 @@18.156 static int pvr2_load_state( FILE *f )18.157 {18.158 + if( !pvr2_load_render_buffers(f) )18.159 + return 1;18.160 if( fread( &pvr2_state, sizeof(pvr2_state), 1, f ) != 1 )18.161 return 1;18.162 if( pvr2_ta_load_state(f) ) {18.163 @@ -220,6 +328,11 @@18.164 return pvr2_state.frame_count;18.165 }18.167 +render_buffer_t pvr2_get_front_buffer()18.168 +{18.169 + return displayed_render_buffer;18.170 +}18.171 +18.172 gboolean pvr2_save_next_scene( const gchar *filename )18.173 {18.174 if( pvr2_state.save_next_render_filename != NULL ) {18.175 @@ -291,14 +404,16 @@18.176 fbuf.address = MMIO_READ( PVR2, DISP_ADDR1 );18.177 }18.178 fbuf.address = (fbuf.address & 0x00FFFFFF) + PVR2_RAM_BASE;18.179 + fbuf.inverted = FALSE;18.180 + fbuf.data = video_base + (fbuf.address&0x00FFFFFF);18.182 render_buffer_t rbuf = pvr2_get_render_buffer( &fbuf );18.183 + if( rbuf == NULL ) {18.184 + rbuf = pvr2_frame_buffer_to_render_buffer( &fbuf );18.185 + }18.186 displayed_render_buffer = rbuf;18.187 if( rbuf != NULL ) {18.188 display_driver->display_render_buffer( rbuf );18.189 - } else {18.190 - fbuf.data = video_base + (fbuf.address&0x00FFFFFF);18.191 - display_driver->display_frame_buffer( &fbuf );18.192 }18.193 }18.194 }18.195 @@ -716,7 +831,8 @@18.196 }18.198 /**18.199 - * Determine the next render buffer to write into. The order of preference is:18.200 + * Allocate a render buffer with the requested parameters.18.201 + * The order of preference is:18.202 * 1. An existing buffer with the same address. (not flushed unless the new18.203 * size is smaller than the old one).18.204 * 2. An existing buffer with the same size chosen by LRU order. Old buffer18.205 @@ -726,23 +842,10 @@18.206 * Note: The current display field(s) will never be overwritten except as a last18.207 * resort.18.208 */18.209 -render_buffer_t pvr2_next_render_buffer()18.210 +render_buffer_t pvr2_alloc_render_buffer( sh4addr_t render_addr, int width, int height )18.211 {18.212 + int i;18.213 render_buffer_t result = NULL;18.214 - uint32_t render_addr = MMIO_READ( PVR2, RENDER_ADDR1 );18.215 - uint32_t render_mode = MMIO_READ( PVR2, RENDER_MODE );18.216 - uint32_t render_scale = MMIO_READ( PVR2, RENDER_SCALER );18.217 - uint32_t render_stride = MMIO_READ( PVR2, RENDER_SIZE ) << 3;18.218 -18.219 - if( render_addr & 0x01000000 ) { /* vram64 */18.220 - render_addr = (render_addr & 0x00FFFFFF) + PVR2_RAM_BASE_INT;18.221 - } else { /* vram32 */18.222 - render_addr = (render_addr & 0x00FFFFFF) + PVR2_RAM_BASE;18.223 - }18.224 -18.225 - int width, height, i;18.226 - int colour_format = pvr2_render_colour_format[render_mode&0x07];18.227 - pvr2_render_getsize( &width, &height );18.229 /* Check existing buffers for an available buffer */18.230 for( i=0; i<render_buffer_count; i++ ) {18.231 @@ -752,6 +855,7 @@18.232 if( displayed_render_buffer == render_buffers[i] ) {18.233 /* Same address, but we can't use it because the18.234 * display has it. Mark it as unaddressed for later.18.235 + */18.236 render_buffers[i]->address = -1;18.237 } else {18.238 /* perfect */18.239 @@ -786,7 +890,9 @@18.240 render_buffers[i] != displayed_render_buffer ) {18.241 /* Never throw away the current "front buffer(s)" */18.242 result = render_buffers[i];18.243 - pvr2_render_buffer_copy_to_sh4( result );18.244 + if( !result->flushed ) {18.245 + pvr2_render_buffer_copy_to_sh4( result );18.246 + }18.247 if( result->width != width || result->height != height ) {18.248 display_driver->destroy_render_buffer(render_buffers[i]);18.249 result = display_driver->create_render_buffer(width,height);18.250 @@ -799,24 +905,68 @@18.251 result = display_driver->create_render_buffer(width,height);18.252 if( result != NULL ) {18.253 render_buffers[render_buffer_count++] = result;18.254 - } else {18.255 - // ERROR( "Failed to obtain a render buffer!" );18.256 - return NULL;18.257 }18.258 }18.259 }18.261 - /* Setup the buffer */18.262 - result->rowstride = render_stride;18.263 - result->colour_format = colour_format;18.264 - result->scale = render_scale;18.265 - result->size = width * height * colour_formats[colour_format].bpp;18.266 - result->address = render_addr;18.267 - result->flushed = FALSE;18.268 + if( result != NULL ) {18.269 + result->address = render_addr;18.270 + }18.271 return result;18.272 }18.274 /**18.275 + * Allocate a render buffer based on the current rendering settings18.276 + */18.277 +render_buffer_t pvr2_next_render_buffer()18.278 +{18.279 + render_buffer_t result = NULL;18.280 + uint32_t render_addr = MMIO_READ( PVR2, RENDER_ADDR1 );18.281 + uint32_t render_mode = MMIO_READ( PVR2, RENDER_MODE );18.282 + uint32_t render_scale = MMIO_READ( PVR2, RENDER_SCALER );18.283 + uint32_t render_stride = MMIO_READ( PVR2, RENDER_SIZE ) << 3;18.284 +18.285 + if( render_addr & 0x01000000 ) { /* vram64 */18.286 + render_addr = (render_addr & 0x00FFFFFF) + PVR2_RAM_BASE_INT;18.287 + } else { /* vram32 */18.288 + render_addr = (render_addr & 0x00FFFFFF) + PVR2_RAM_BASE;18.289 + }18.290 +18.291 + int width, height;18.292 + int colour_format = pvr2_render_colour_format[render_mode&0x07];18.293 + pvr2_render_getsize( &width, &height );18.294 +18.295 + result = pvr2_alloc_render_buffer( render_addr, width, height );18.296 + /* Setup the buffer */18.297 + if( result != NULL ) {18.298 + result->rowstride = render_stride;18.299 + result->colour_format = colour_format;18.300 + result->scale = render_scale;18.301 + result->size = width * height * colour_formats[colour_format].bpp;18.302 + result->flushed = FALSE;18.303 + result->inverted = TRUE; // render buffers are inverted normally18.304 + }18.305 + return result;18.306 +}18.307 +18.308 +static render_buffer_t pvr2_frame_buffer_to_render_buffer( frame_buffer_t frame )18.309 +{18.310 + render_buffer_t result = pvr2_alloc_render_buffer( frame->address, frame->width, frame->height );18.311 + if( result != NULL ) {18.312 + int bpp = colour_formats[frame->colour_format].bpp;18.313 + result->rowstride = frame->rowstride;18.314 + result->colour_format = frame->colour_format;18.315 + result->scale = 0x400;18.316 + result->size = frame->width * frame->height * bpp;18.317 + result->flushed = TRUE;18.318 + result->inverted = frame->inverted;18.319 + display_driver->load_frame_buffer( frame, result );18.320 + }18.321 + return result;18.322 +}18.323 +18.324 +18.325 +/**18.326 * Invalidate any caching on the supplied address. Specifically, if it falls18.327 * within any of the render buffers, flush the buffer back to PVR2 ram.18.328 */
19.1 --- a/src/pvr2/pvr2mem.c Wed Oct 31 09:07:25 2007 +000019.2 +++ b/src/pvr2/pvr2mem.c Wed Oct 31 09:10:23 2007 +000019.3 @@ -1,5 +1,5 @@19.4 /**19.5 - * $Id: pvr2mem.c,v 1.10 2007-10-08 11:52:13 nkeynes Exp $19.6 + * $Id: pvr2mem.c,v 1.11 2007-10-31 09:10:23 nkeynes Exp $19.7 *19.8 * PVR2 (Video) VRAM handling routines (mainly for the 64-bit region)19.9 *19.10 @@ -521,13 +521,13 @@19.11 if( (buffer->address & 0xFF000000) == 0x04000000 ) {19.12 /* Interlaced buffer. Go the double copy... :( */19.13 unsigned char target[buffer->size];19.14 - display_driver->read_render_buffer( buffer, target );19.15 + display_driver->read_render_buffer( target, buffer, buffer->rowstride, buffer->colour_format );19.16 pvr2_vram64_write( buffer->address, target, buffer->size );19.17 } else {19.18 /* Regular buffer */19.19 unsigned char target[buffer->size];19.20 int line_size = buffer->width * colour_formats[buffer->colour_format].bpp;19.21 - display_driver->read_render_buffer( buffer, target );19.22 + display_driver->read_render_buffer( target, buffer, buffer->rowstride, buffer->colour_format );19.23 if( (buffer->scale & 0xFFFF) == 0x0800 ) {19.24 pvr2_vram_write_invert( buffer->address, target, buffer->size, line_size, line_size << 1 );19.25 } else {
20.1 --- a/src/pvr2/rendcore.c Wed Oct 31 09:07:25 2007 +000020.2 +++ b/src/pvr2/rendcore.c Wed Oct 31 09:10:23 2007 +000020.3 @@ -1,5 +1,5 @@20.4 /**20.5 - * $Id: rendcore.c,v 1.20 2007-10-08 11:52:13 nkeynes Exp $20.6 + * $Id: rendcore.c,v 1.21 2007-10-31 09:10:23 nkeynes Exp $20.7 *20.8 * PVR2 renderer core.20.9 *20.10 @@ -41,8 +41,8 @@20.11 GL_MODULATE20.12 };20.13 int pvr2_render_colour_format[8] = {20.14 - COLFMT_ARGB1555, COLFMT_RGB565, COLFMT_ARGB4444, COLFMT_ARGB1555,20.15 - COLFMT_RGB888, COLFMT_ARGB8888, COLFMT_ARGB8888, COLFMT_ARGB4444 };20.16 + COLFMT_BGRA1555, COLFMT_RGB565, COLFMT_BGRA4444, COLFMT_BGRA1555,20.17 + COLFMT_BGR888, COLFMT_BGRA8888, COLFMT_BGRA8888, COLFMT_BGRA4444 };20.20 #define CULL_NONE 020.21 @@ -428,7 +428,7 @@20.22 for( i=0; i<strip_count; i++ ) {20.23 render_set_context( polygon, render_mode );20.24 render_vertexes( *polygon, polygon+context_length, 3, vertex_length,20.25 - render_mode );20.26 + render_mode );20.27 polygon += polygon_length;20.28 }20.29 } else if( (entry & 0xE0000000) == 0xA0000000 ) {20.30 @@ -439,7 +439,7 @@20.31 for( i=0; i<strip_count; i++ ) {20.32 render_set_context( polygon, render_mode );20.33 render_quad_vertexes( *polygon, polygon+context_length, vertex_length,20.34 - render_mode );20.35 + render_mode );20.36 polygon += polygon_length;20.37 }20.38 } else {20.39 @@ -455,7 +455,7 @@20.40 first = 0;20.41 render_set_context(polygon, render_mode);20.42 render_vertexes( *polygon, polygon+context_length + (first*vertex_length),20.43 - (last-first+3), vertex_length, render_mode );20.44 + (last-first+3), vertex_length, render_mode );20.45 }20.46 }20.47 }20.48 @@ -487,8 +487,6 @@20.50 struct tile_segment *segment = (struct tile_segment *)(video_base + segmentbase);20.52 - struct timeval tv_start, tv_end;20.53 - gettimeofday(&tv_start, NULL);20.54 glEnable( GL_SCISSOR_TEST );20.55 do {20.56 // fwrite_dump32v( (uint32_t *)segment, sizeof(struct tile_segment), 6, stderr );20.57 @@ -548,9 +546,6 @@20.58 }20.59 } while( ((segment++)->control & SEGMENT_END) == 0 );20.60 glDisable( GL_SCISSOR_TEST );20.61 -20.62 - gettimeofday(&tv_end, NULL);20.63 - timersub(&tv_end,&tv_start, &tv_start);20.64 }20.66 static float render_find_maximum_tile_z( pvraddr_t tile_entry, float inputz )
21.1 --- a/src/pvr2/render.c Wed Oct 31 09:07:25 2007 +000021.2 +++ b/src/pvr2/render.c Wed Oct 31 09:10:23 2007 +000021.3 @@ -1,5 +1,5 @@21.4 /**21.5 - * $Id: render.c,v 1.25 2007-10-08 11:52:13 nkeynes Exp $21.6 + * $Id: render.c,v 1.26 2007-10-31 09:10:23 nkeynes Exp $21.7 *21.8 * PVR2 Renderer support. This part is primarily21.9 *21.10 @@ -106,6 +106,8 @@21.11 glClearColor(0.0f, 0.0f, 0.0f, 0.0f);21.12 glClearDepth(0);21.13 glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );21.14 + glEnableClientState( GL_COLOR_ARRAY );21.15 + glEnableClientState( GL_VERTEX_ARRAY );21.16 }21.18 /**
22.1 --- a/src/pvr2/texcache.c Wed Oct 31 09:07:25 2007 +000022.2 +++ b/src/pvr2/texcache.c Wed Oct 31 09:10:23 2007 +000022.3 @@ -1,5 +1,5 @@22.4 /**22.5 - * $Id: texcache.c,v 1.28 2007-10-24 21:23:22 nkeynes Exp $22.6 + * $Id: texcache.c,v 1.29 2007-10-31 09:10:23 nkeynes Exp $22.7 *22.8 * Texture cache. Responsible for maintaining a working set of OpenGL22.9 * textures.22.10 @@ -354,7 +354,7 @@22.11 break;22.12 case 3: /* ARGB8888 */22.13 format = GL_BGRA;22.14 - type = GL_UNSIGNED_INT_8_8_8_8_REV;22.15 + type = GL_UNSIGNED_BYTE;22.16 bpp_shift = 2;22.17 break;22.18 default:22.19 @@ -381,7 +381,7 @@22.20 */22.21 bpp_shift = 2;22.22 format = GL_BGRA;22.23 - type = GL_UNSIGNED_INT_8_8_8_8_REV;22.24 + type = GL_UNSIGNED_BYTE;22.25 break;22.26 case PVR2_TEX_FORMAT_BUMPMAP:22.27 ERROR( "Bumpmap not supported" );
23.1 --- a/src/util.c Wed Oct 31 09:07:25 2007 +000023.2 +++ b/src/util.c Wed Oct 31 09:10:23 2007 +000023.3 @@ -1,5 +1,5 @@23.4 /**23.5 - * $Id: util.c,v 1.10 2007-10-16 12:36:29 nkeynes Exp $23.6 + * $Id: util.c,v 1.11 2007-10-31 09:10:23 nkeynes Exp $23.7 *23.8 * Miscellaneous utility functions.23.9 *23.10 @@ -16,12 +16,17 @@23.11 * GNU General Public License for more details.23.12 */23.14 +#include <assert.h>23.15 #include <ctype.h>23.16 #include <stdarg.h>23.17 #include <stdio.h>23.18 #include <stdlib.h>23.19 #include <time.h>23.20 +#include <zlib.h>23.21 +#include <glib.h>23.22 +#include <png.h>23.23 #include "dream.h"23.24 +#include "display.h"23.25 #include "sh4/sh4core.h"23.27 char *msg_levels[] = { "FATAL", "ERROR", "WARN", "INFO", "DEBUG", "TRACE" };23.28 @@ -49,6 +54,38 @@23.29 return len;23.30 }23.32 +void fwrite_gzip( void *p, size_t sz, size_t count, FILE *f )23.33 +{23.34 + uLongf size = sz*count;23.35 + uLongf csize = ((int)(size*1.001))+13;23.36 + unsigned char *tmp = g_malloc0( csize );23.37 + int status = compress( tmp, &csize, p, size );23.38 + assert( status == Z_OK );23.39 + fwrite( &csize, sizeof(csize), 1, f );23.40 + fwrite( tmp, csize, 1, f );23.41 + g_free(tmp);23.42 +}23.43 +23.44 +int fread_gzip( void *p, size_t sz, size_t count, FILE *f )23.45 +{23.46 + uLongf size = sz*count;23.47 + uLongf csize;23.48 + unsigned char *tmp;23.49 +23.50 + fread( &csize, sizeof(csize), 1, f );23.51 + assert( csize <= (size*2) );23.52 + tmp = g_malloc0( csize );23.53 + fread( tmp, csize, 1, f );23.54 + int status = uncompress( p, &size, tmp, csize );23.55 + g_free(tmp);23.56 + if( status == Z_OK ) {23.57 + return count;23.58 + } else {23.59 + fprintf( stderr, "Error reading compressed data\n" );23.60 + return 0;23.61 + }23.62 +}23.63 +23.64 void fwrite_dump( unsigned char *data, unsigned int length, FILE *f )23.65 {23.66 unsigned int i, j;23.67 @@ -90,6 +127,129 @@23.68 }23.69 }23.71 +gboolean write_png_to_stream( FILE *f, frame_buffer_t buffer )23.72 +{23.73 + int coltype, i;23.74 + png_bytep p;23.75 + png_structp png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);23.76 + if (!png_ptr) {23.77 + return FALSE;23.78 + }23.79 +23.80 + png_infop info_ptr = png_create_info_struct(png_ptr);23.81 + if (!info_ptr) {23.82 + png_destroy_write_struct(&png_ptr, NULL);23.83 + return FALSE;23.84 + }23.85 +23.86 + if( setjmp(png_jmpbuf(png_ptr)) ) {23.87 + png_destroy_write_struct(&png_ptr, &info_ptr);23.88 + return FALSE;23.89 + }23.90 + png_init_io( png_ptr, f );23.91 + switch( buffer->colour_format ) {23.92 + case COLFMT_BGR888:23.93 + coltype = PNG_COLOR_TYPE_RGB;23.94 + break;23.95 + case COLFMT_BGRA8888:23.96 + coltype = PNG_COLOR_TYPE_RGB_ALPHA;23.97 + break;23.98 + case COLFMT_BGR0888:23.99 + coltype = PNG_COLOR_TYPE_RGB;23.100 + break;23.101 + default:23.102 + coltype = PNG_COLOR_TYPE_RGB;23.103 + }23.104 + png_set_IHDR(png_ptr, info_ptr, buffer->width, buffer->height,23.105 + 8, coltype, PNG_INTERLACE_NONE,23.106 + PNG_COMPRESSION_TYPE_DEFAULT,23.107 + PNG_FILTER_TYPE_DEFAULT );23.108 + png_write_info(png_ptr, info_ptr);23.109 + if( buffer->colour_format == COLFMT_BGR0888 ) {23.110 + png_set_filler(png_ptr, 0, PNG_FILLER_AFTER);23.111 + }23.112 + png_set_bgr(png_ptr);23.113 + if( buffer->inverted ) {23.114 + p = buffer->data + (buffer->height*buffer->rowstride) - buffer->rowstride;23.115 + for(i=0; i<buffer->height; i++ ) {23.116 + png_write_row(png_ptr, p);23.117 + p-=buffer->rowstride;23.118 + }23.119 + } else {23.120 + p = buffer->data;23.121 + for(i=0; i<buffer->height; i++ ) {23.122 + png_write_row(png_ptr, p);23.123 + p+=buffer->rowstride;23.124 + }23.125 + }23.126 + png_write_end(png_ptr, info_ptr);23.127 + png_destroy_write_struct(&png_ptr, &info_ptr);23.128 + return TRUE;23.129 +}23.130 +23.131 +frame_buffer_t read_png_from_stream( FILE *f )23.132 +{23.133 + png_bytep p;23.134 + int i;23.135 + png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING,23.136 + NULL, NULL, NULL);23.137 + if (!png_ptr) {23.138 + return NULL;23.139 + }23.140 +23.141 + png_infop info_ptr = png_create_info_struct(png_ptr);23.142 + if (!info_ptr) {23.143 + png_destroy_read_struct(&png_ptr, NULL, NULL);23.144 + return NULL;23.145 + }23.146 +23.147 + png_infop end_info = png_create_info_struct(png_ptr);23.148 + if (!end_info) {23.149 + png_destroy_read_struct(&png_ptr, &info_ptr, NULL );23.150 + return NULL;23.151 + }23.152 +23.153 + if( setjmp(png_jmpbuf(png_ptr)) ) {23.154 + png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);23.155 + return NULL;23.156 + }23.157 +23.158 + png_init_io(png_ptr, f);23.159 + png_read_info(png_ptr, info_ptr);23.160 +23.161 + png_uint_32 width, height;23.162 + int bit_depth, color_type, interlace_type,23.163 + compression_type, filter_method;23.164 + png_get_IHDR(png_ptr, info_ptr, &width, &height,23.165 + &bit_depth, &color_type, &interlace_type,23.166 + &compression_type, &filter_method);23.167 + assert( interlace_type == PNG_INTERLACE_NONE );23.168 + int rowbytes = png_get_rowbytes(png_ptr, info_ptr);23.169 + int channels = png_get_channels(png_ptr, info_ptr);23.170 + frame_buffer_t buffer = g_malloc( sizeof(struct frame_buffer) + rowbytes*height );23.171 + buffer->data = (char *)(buffer+1);23.172 + buffer->width = width;23.173 + buffer->height = height;23.174 + buffer->rowstride = rowbytes;23.175 + buffer->address = -1;23.176 + buffer->size = rowbytes*height;23.177 + buffer->inverted = FALSE;23.178 + if( channels == 4 ) {23.179 + buffer->colour_format = COLFMT_BGRA8888;23.180 + } else if( channels == 3 ) {23.181 + buffer->colour_format = COLFMT_RGB888;23.182 + }23.183 +23.184 + p = buffer->data;23.185 + for( i=0; i<height; i++ ) {23.186 + png_read_row(png_ptr, p, NULL );23.187 + p += rowbytes;23.188 + }23.189 +23.190 + png_read_end(png_ptr, end_info);23.191 + png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);23.192 + return buffer;23.193 +}23.195 void log_message( void *ptr, int level, const gchar *source, const char *msg, ... )23.196 {
.