Search
lxdream.org :: lxdream :: r477:9a373f2ff009
lxdream 0.9.1
released Jun 29
Download Now
changeset477:9a373f2ff009
parent476:75eb00fc191d
child478:57f73576c974
authornkeynes
dateWed 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
src/display.c
src/display.h
src/dream.h
src/dreamcast.c
src/dreamcast.h
src/drivers/gl_common.c
src/drivers/gl_common.h
src/drivers/gl_fbo.c
src/drivers/gl_sl.c
src/drivers/video_gtk.c
src/drivers/video_null.c
src/gui/gtkcb.c
src/gui/gtkui.c
src/gui/gtkui.h
src/lxdream.h
src/mem.c
src/mem.h
src/pvr2/pvr2.c
src/pvr2/pvr2mem.c
src/pvr2/rendcore.c
src/pvr2/render.c
src/pvr2/texcache.c
src/util.c
1.1 --- a/src/display.c Wed Oct 31 09:07:25 2007 +0000
1.2 +++ b/src/display.c Wed Oct 31 09:10:23 2007 +0000
1.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 display
1.9 * driver is expected to deliver events here, where they're translated and
1.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.18
1.19 };
1.20
2.1 --- a/src/display.h Wed Oct 31 09:07:25 2007 +0000
2.2 +++ b/src/display.h Wed Oct 31 09:10:23 2007 +0000
2.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.16
2.17 #ifdef __cplusplus
2.18 extern "C" {
2.19 #endif
2.20
2.21 /**
2.22 - * Supported colour formats. Note that ARGB4444 is only ever used for texture
2.23 + * Supported colour formats. Note that BGRA4444 is only ever used for texture
2.24 * rendering (it's not valid for display purposes).
2.25 */
2.26 -#define COLFMT_ARGB1555 0
2.27 +#define COLFMT_BGRA1555 0
2.28 #define COLFMT_RGB565 1
2.29 -#define COLFMT_ARGB4444 2
2.30 +#define COLFMT_BGRA4444 2
2.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 5
2.34 +#define COLFMT_BGR888 4 /* 24-bit BGR */
2.35 +#define COLFMT_BGRA8888 5
2.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.41
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.62
2.63 /**
2.64 * Structure to hold pixel data stored in pvr2 vram, as opposed to data in
2.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.79
2.80 /**
2.81 * Core video driver - exports function to setup a GL context, as well as handle
2.82 @@ -125,9 +128,10 @@
2.83 gboolean (*set_render_target)( render_buffer_t buffer );
2.84
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.92
2.93 /**
2.94 * Display a single frame using a previously rendered GL buffer.
2.95 @@ -136,7 +140,7 @@
2.96
2.97 /**
2.98 * Display a single blanked frame using a fixed colour for the
2.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.103
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 enough
2.109 + * to accomodate the image.
2.110 + * @param buffer Render buffer to read from.
2.111 + * @param rowstride rowstride of the target data
2.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.117
2.118 } *display_driver_t;
2.119
3.1 --- a/src/dream.h Wed Oct 31 09:07:25 2007 +0000
3.2 +++ b/src/dream.h Wed Oct 31 09:10:23 2007 +0000
3.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.16
3.17 #ifdef __cplusplus
3.18 extern "C" {
3.19 #endif
3.20
3.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 all
3.27 @@ -90,39 +87,16 @@
3.28 extern struct dreamcast_module eventq_module;
3.29 extern struct dreamcast_module unknown_module;
3.30
3.31 -/*************************** Logging **************************/
3.32 -
3.33 -#define EMIT_FATAL 0
3.34 -#define EMIT_ERR 1
3.35 -#define EMIT_WARN 2
3.36 -#define EMIT_INFO 3
3.37 -#define EMIT_DEBUG 4
3.38 -#define EMIT_TRACE 5
3.39 -
3.40 -#ifndef MODULE
3.41 -#define MODULE unknown_module
3.42 -#endif
3.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.60
3.61 -typedef uint32_t sh4addr_t;
3.62 -
3.63 -#ifndef max
3.64 -#define max(a,b) ( (a) > (b) ? (a) : (b) )
3.65 -#endif
3.66 +gboolean write_png_to_stream( FILE *f, frame_buffer_t );
3.67 +frame_buffer_t read_png_from_stream( FILE *f );
3.68
3.69 #ifdef __cplusplus
3.70 }
4.1 --- a/src/dreamcast.c Wed Oct 31 09:07:25 2007 +0000
4.2 +++ b/src/dreamcast.c Wed Oct 31 09:10:23 2007 +0000
4.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 modules
4.8 * together into some kind of coherent structure. This is also where you'd
4.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.13
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, supported
4.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.107
4.108 - f = fopen( filename, "r" );
4.109 + FILE *f = fopen( filename, "r" );
4.110 if( f == NULL ) return errno;
4.111
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.132
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.149
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 +0000
5.2 +++ b/src/dreamcast.h Wed Oct 31 09:10:23 2007 +0000
5.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 modules
5.10 @@ -23,7 +23,7 @@
5.11 #define dreamcast_H 1
5.12
5.13 #include <stdio.h>
5.14 -#include <glib/gtypes.h>
5.15 +#include "lxdream.h"
5.16
5.17 #ifdef __cplusplus
5.18 extern "C" {
5.19 @@ -31,9 +31,6 @@
5.20
5.21 #define DEFAULT_TIMESLICE_LENGTH 1000000 /* nanoseconds */
5.22
5.23 -#define MB *1024*1024
5.24 -#define KB *1024
5.25 -
5.26 #define XLAT_NEW_CACHE_SIZE 32 MB
5.27 #define XLAT_TEMP_CACHE_SIZE 2 MB
5.28 #define XLAT_OLD_CACHE_SIZE 8 MB
5.29 @@ -55,6 +52,15 @@
5.30 int dreamcast_save_state( const gchar *filename );
5.31 int dreamcast_load_state( const gchar *filename );
5.32
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 freed
5.37 + * by the caller. (The data buffer is contained within the
5.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
5.44
6.1 --- a/src/drivers/gl_common.c Wed Oct 31 09:07:25 2007 +0000
6.2 +++ b/src/drivers/gl_common.c Wed Oct 31 09:10:23 2007 +0000
6.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 implementation
6.9 *
6.10 @@ -23,13 +23,7 @@
6.11 #include "drivers/gl_common.h"
6.12
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.21
6.22 char *required_extensions[] = { "GL_EXT_framebuffer_object", NULL };
6.23
6.24 @@ -80,28 +74,15 @@
6.25 return isOK;
6.26 }
6.27
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.55
6.56 /* Reset display parameters */
6.57 @@ -155,7 +136,7 @@
6.58
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.86
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.106
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.115
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.127
6.128 @@ -219,17 +199,16 @@
6.129 * has already set the appropriate glReadBuffer(); in other words, unless
6.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.150
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 +0000
7.2 +++ b/src/drivers/gl_common.h Wed Oct 31 09:10:23 2007 +0000
7.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.12
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 buffer
7.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.19
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.24
7.25 /**
7.26 - * Copy the frame buffer contents to the specified texture id
7.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 frame
7.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.35
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, unless
7.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.45
7.46
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.52
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 +0000
8.2 +++ b/src/drivers/gl_fbo.c Wed Oct 31 09:10:23 2007 +0000
8.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_object
8.9 * extension, but is much nicer/faster/etc than pbuffers when it's available.
8.10 @@ -26,6 +26,8 @@
8.11
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.28
8.29 extern uint32_t video_width, video_height;
8.30
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.39
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.49
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 window
8.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.101
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.125
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 }
8.143
9.1 --- a/src/drivers/gl_sl.c Wed Oct 31 09:07:25 2007 +0000
9.2 +++ b/src/drivers/gl_sl.c Wed Oct 31 09:10:23 2007 +0000
9.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 exactly
9.9 * 1 shader program that's used globally. This may turn out not to be the
9.10 @@ -22,6 +22,7 @@
9.11
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"
9.17
10.1 --- a/src/drivers/video_gtk.c Wed Oct 31 09:07:25 2007 +0000
10.2 +++ b/src/drivers/video_gtk.c Wed Oct 31 09:10:23 2007 +0000
10.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.11
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 +0000
11.2 +++ b/src/drivers/video_null.c Wed Oct 31 09:10:23 2007 +0000
11.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.13
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 +0000
12.2 +++ b/src/gui/gtkcb.c Wed Oct 31 09:10:23 2007 +0000
12.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 window
12.9 *
12.10 @@ -46,21 +46,6 @@
12.11 }
12.12
12.13
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.57
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.83
12.84 void mount_action_callback( GtkAction *action, gpointer user_data)
12.85 @@ -133,11 +122,62 @@
12.86 dreamcast_run();
12.87 }
12.88
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 +0000
13.2 +++ b/src/gui/gtkui.c Wed Oct 31 09:10:23 2007 +0000
13.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 interface
13.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.17
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 +0000
14.2 +++ b/src/gui/gtkui.h Wed Oct 31 09:10:23 2007 +0000
14.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 interface
14.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.13
14.14 +/**
14.15 + * Construct a new pixbuf that takes ownership of the frame buffer
14.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();
14.21
15.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
15.2 +++ b/src/lxdream.h Wed Oct 31 09:10:23 2007 +0000
15.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 declarations
15.8 + *
15.9 + * Copyright (c) 2005 Nathan Keynes.
15.10 + *
15.11 + * This program is free software; you can redistribute it and/or modify
15.12 + * it under the terms of the GNU General Public License as published by
15.13 + * the Free Software Foundation; either version 2 of the License, or
15.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 of
15.18 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15.19 + * GNU General Public License for more details.
15.20 + */
15.21 +
15.22 +#ifndef lxdream_common_H
15.23 +#define lxdream_common_H 1
15.24 +
15.25 +#include <stdint.h>
15.26 +#include <glib/gtypes.h>
15.27 +
15.28 +#ifdef __cplusplus
15.29 +extern "C" {
15.30 +#endif
15.31 +
15.32 +#define APP_NAME "lxDream"
15.33 +#define APP_VERSION "0.8"
15.34 +
15.35 +#define MB *1024*1024
15.36 +#define KB *1024
15.37 +
15.38 +#ifndef max
15.39 +#define max(a,b) ( (a) > (b) ? (a) : (b) )
15.40 +#endif
15.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 0
15.53 +#define EMIT_ERR 1
15.54 +#define EMIT_WARN 2
15.55 +#define EMIT_INFO 3
15.56 +#define EMIT_DEBUG 4
15.57 +#define EMIT_TRACE 5
15.58 +
15.59 +#ifdef MODULE
15.60 +#define MODULE_NAME MODULE.name
15.61 +#else
15.62 +#define MODULE_NAME "*****"
15.63 +#endif
15.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 __cplusplus
15.77 +}
15.78 +#endif
15.79 +
15.80 +#endif /* !lxdream_common_H */
16.1 --- a/src/mem.c Wed Oct 31 09:07:25 2007 +0000
16.2 +++ b/src/mem.c Wed Oct 31 09:10:23 2007 +0000
16.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 memory
16.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.17
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.27
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.35
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 +0000
17.2 +++ b/src/mem.h Wed Oct 31 09:10:23 2007 +0000
17.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 memory
17.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_H
17.12
17.13 #include <stdint.h>
17.14 -#include "dream.h"
17.15 +#include "lxdream.h"
17.16
17.17 #ifdef __cplusplus
17.18 extern "C" {
18.1 --- a/src/pvr2/pvr2.c Wed Oct 31 09:07:25 2007 +0000
18.2 +++ b/src/pvr2/pvr2.c Wed Oct 31 09:10:23 2007 +0000
18.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_module
18.13
18.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.24
18.25 void pvr2_display_frame( void );
18.26
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.29
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.33
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.41
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.53
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.155
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.166
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.181
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.197
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 new
18.203 * size is smaller than the old one).
18.204 * 2. An existing buffer with the same size chosen by LRU order. Old buffer
18.205 @@ -726,23 +842,10 @@
18.206 * Note: The current display field(s) will never be overwritten except as a last
18.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.228
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 the
18.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.260
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.273
18.274 /**
18.275 + * Allocate a render buffer based on the current rendering settings
18.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 normally
18.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 falls
18.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 +0000
19.2 +++ b/src/pvr2/pvr2mem.c Wed Oct 31 09:10:23 2007 +0000
19.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 +0000
20.2 +++ b/src/pvr2/rendcore.c Wed Oct 31 09:10:23 2007 +0000
20.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_MODULATE
20.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.18
20.19
20.20 #define CULL_NONE 0
20.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.49
20.50 struct tile_segment *segment = (struct tile_segment *)(video_base + segmentbase);
20.51
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.65
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 +0000
21.2 +++ b/src/pvr2/render.c Wed Oct 31 09:10:23 2007 +0000
21.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 primarily
21.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.17
21.18 /**
22.1 --- a/src/pvr2/texcache.c Wed Oct 31 09:07:25 2007 +0000
22.2 +++ b/src/pvr2/texcache.c Wed Oct 31 09:10:23 2007 +0000
22.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 OpenGL
22.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 +0000
23.2 +++ b/src/util.c Wed Oct 31 09:10:23 2007 +0000
23.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.13
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.26
23.27 char *msg_levels[] = { "FATAL", "ERROR", "WARN", "INFO", "DEBUG", "TRACE" };
23.28 @@ -49,6 +54,38 @@
23.29 return len;
23.30 }
23.31
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.70
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.194
23.195 void log_message( void *ptr, int level, const gchar *source, const char *msg, ... )
23.196 {
.