Search
lxdream.org :: lxdream :: r352:f0df7a6d4703
lxdream 0.9.1
released Jun 29
Download Now
changeset352:f0df7a6d4703
parent351:41b7e55ee10f
child353:b8569afb53fc
authornkeynes
dateSun Feb 11 10:09:32 2007 +0000 (17 years ago)
Bug 27: Implement opengl framebuffer objects
Rewrite much of the final video output stage. Now uses generic "render
buffers", implemented on GL using framebuffer objects + textures.
src/Makefile.am
src/Makefile.in
src/display.c
src/display.h
src/drivers/gl_common.c
src/drivers/gl_common.h
src/drivers/gl_fbo.c
src/drivers/video_gl.c
src/drivers/video_gl.h
src/drivers/video_gtk.c
src/drivers/video_null.c
src/drivers/video_x11.c
src/drivers/video_x11.h
src/pvr2/pvr2.c
src/pvr2/pvr2.h
src/pvr2/pvr2mem.c
src/pvr2/rendcore.c
src/pvr2/render.c
src/pvr2/texcache.c
1.1 --- a/src/Makefile.am Tue Feb 06 07:59:06 2007 +0000
1.2 +++ b/src/Makefile.am Sun Feb 11 10:09:32 2007 +0000
1.3 @@ -36,7 +36,7 @@
1.4 drivers/audio_null.c drivers/audio_esd.c \
1.5 drivers/video_null.c drivers/video_gtk.c drivers/video_gtk.h \
1.6 drivers/video_x11.c drivers/video_x11.h \
1.7 - drivers/video_gl.c drivers/video_gl.h
1.8 + drivers/gl_common.c drivers/gl_common.h drivers/gl_fbo.c
1.9
1.10 lxdream_LDADD = @PACKAGE_LIBS@ $(INTLLIBS) -lesd
1.11
2.1 --- a/src/Makefile.in Tue Feb 06 07:59:06 2007 +0000
2.2 +++ b/src/Makefile.in Sun Feb 11 10:09:32 2007 +0000
2.3 @@ -170,7 +170,7 @@
2.4 drivers/audio_null.c drivers/audio_esd.c \
2.5 drivers/video_null.c drivers/video_gtk.c drivers/video_gtk.h \
2.6 drivers/video_x11.c drivers/video_x11.h \
2.7 - drivers/video_gl.c drivers/video_gl.h
2.8 + drivers/gl_common.c drivers/gl_common.h drivers/gl_fbo.c
2.9
2.10
2.11 lxdream_LDADD = @PACKAGE_LIBS@ $(INTLLIBS) -lesd
2.12 @@ -202,7 +202,7 @@
2.13 loader.$(OBJEXT) bootstrap.$(OBJEXT) util.$(OBJEXT) \
2.14 display.$(OBJEXT) audio_null.$(OBJEXT) audio_esd.$(OBJEXT) \
2.15 video_null.$(OBJEXT) video_gtk.$(OBJEXT) video_x11.$(OBJEXT) \
2.16 - video_gl.$(OBJEXT)
2.17 + gl_common.$(OBJEXT) gl_fbo.$(OBJEXT)
2.18 lxdream_OBJECTS = $(am_lxdream_OBJECTS)
2.19 lxdream_DEPENDENCIES =
2.20 lxdream_LDFLAGS =
2.21 @@ -221,6 +221,7 @@
2.22 @AMDEP_TRUE@ ./$(DEPDIR)/dmac.Po ./$(DEPDIR)/dreamcast.Po \
2.23 @AMDEP_TRUE@ ./$(DEPDIR)/dump_win.Po ./$(DEPDIR)/eventq.Po \
2.24 @AMDEP_TRUE@ ./$(DEPDIR)/gdimage.Po ./$(DEPDIR)/gdrom.Po \
2.25 +@AMDEP_TRUE@ ./$(DEPDIR)/gl_common.Po ./$(DEPDIR)/gl_fbo.Po \
2.26 @AMDEP_TRUE@ ./$(DEPDIR)/gui.Po ./$(DEPDIR)/ide.Po \
2.27 @AMDEP_TRUE@ ./$(DEPDIR)/intc.Po ./$(DEPDIR)/interface.Po \
2.28 @AMDEP_TRUE@ ./$(DEPDIR)/linux.Po ./$(DEPDIR)/loader.Po \
2.29 @@ -235,10 +236,9 @@
2.30 @AMDEP_TRUE@ ./$(DEPDIR)/sh4mmio.Po ./$(DEPDIR)/support.Po \
2.31 @AMDEP_TRUE@ ./$(DEPDIR)/syscall.Po ./$(DEPDIR)/tacore.Po \
2.32 @AMDEP_TRUE@ ./$(DEPDIR)/texcache.Po ./$(DEPDIR)/timer.Po \
2.33 -@AMDEP_TRUE@ ./$(DEPDIR)/util.Po ./$(DEPDIR)/video_gl.Po \
2.34 -@AMDEP_TRUE@ ./$(DEPDIR)/video_gtk.Po ./$(DEPDIR)/video_null.Po \
2.35 -@AMDEP_TRUE@ ./$(DEPDIR)/video_x11.Po ./$(DEPDIR)/watch.Po \
2.36 -@AMDEP_TRUE@ ./$(DEPDIR)/yuv.Po
2.37 +@AMDEP_TRUE@ ./$(DEPDIR)/util.Po ./$(DEPDIR)/video_gtk.Po \
2.38 +@AMDEP_TRUE@ ./$(DEPDIR)/video_null.Po ./$(DEPDIR)/video_x11.Po \
2.39 +@AMDEP_TRUE@ ./$(DEPDIR)/watch.Po ./$(DEPDIR)/yuv.Po
2.40 COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
2.41 $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
2.42 CCLD = $(CC)
2.43 @@ -312,6 +312,8 @@
2.44 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eventq.Po@am__quote@
2.45 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gdimage.Po@am__quote@
2.46 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gdrom.Po@am__quote@
2.47 +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gl_common.Po@am__quote@
2.48 +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gl_fbo.Po@am__quote@
2.49 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gui.Po@am__quote@
2.50 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ide.Po@am__quote@
2.51 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/intc.Po@am__quote@
2.52 @@ -341,7 +343,6 @@
2.53 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/texcache.Po@am__quote@
2.54 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/timer.Po@am__quote@
2.55 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/util.Po@am__quote@
2.56 -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/video_gl.Po@am__quote@
2.57 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/video_gtk.Po@am__quote@
2.58 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/video_null.Po@am__quote@
2.59 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/video_x11.Po@am__quote@
2.60 @@ -1316,27 +1317,49 @@
2.61 @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
2.62 @am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o video_x11.obj `if test -f 'drivers/video_x11.c'; then $(CYGPATH_W) 'drivers/video_x11.c'; else $(CYGPATH_W) '$(srcdir)/drivers/video_x11.c'; fi`
2.63
2.64 -video_gl.o: drivers/video_gl.c
2.65 -@am__fastdepCC_TRUE@ if $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT video_gl.o -MD -MP -MF "$(DEPDIR)/video_gl.Tpo" \
2.66 -@am__fastdepCC_TRUE@ -c -o video_gl.o `test -f 'drivers/video_gl.c' || echo '$(srcdir)/'`drivers/video_gl.c; \
2.67 -@am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/video_gl.Tpo" "$(DEPDIR)/video_gl.Po"; \
2.68 -@am__fastdepCC_TRUE@ else rm -f "$(DEPDIR)/video_gl.Tpo"; exit 1; \
2.69 +gl_common.o: drivers/gl_common.c
2.70 +@am__fastdepCC_TRUE@ if $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT gl_common.o -MD -MP -MF "$(DEPDIR)/gl_common.Tpo" \
2.71 +@am__fastdepCC_TRUE@ -c -o gl_common.o `test -f 'drivers/gl_common.c' || echo '$(srcdir)/'`drivers/gl_common.c; \
2.72 +@am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/gl_common.Tpo" "$(DEPDIR)/gl_common.Po"; \
2.73 +@am__fastdepCC_TRUE@ else rm -f "$(DEPDIR)/gl_common.Tpo"; exit 1; \
2.74 @am__fastdepCC_TRUE@ fi
2.75 -@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='drivers/video_gl.c' object='video_gl.o' libtool=no @AMDEPBACKSLASH@
2.76 -@AMDEP_TRUE@@am__fastdepCC_FALSE@ depfile='$(DEPDIR)/video_gl.Po' tmpdepfile='$(DEPDIR)/video_gl.TPo' @AMDEPBACKSLASH@
2.77 +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='drivers/gl_common.c' object='gl_common.o' libtool=no @AMDEPBACKSLASH@
2.78 +@AMDEP_TRUE@@am__fastdepCC_FALSE@ depfile='$(DEPDIR)/gl_common.Po' tmpdepfile='$(DEPDIR)/gl_common.TPo' @AMDEPBACKSLASH@
2.79 @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
2.80 -@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o video_gl.o `test -f 'drivers/video_gl.c' || echo '$(srcdir)/'`drivers/video_gl.c
2.81 +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o gl_common.o `test -f 'drivers/gl_common.c' || echo '$(srcdir)/'`drivers/gl_common.c
2.82
2.83 -video_gl.obj: drivers/video_gl.c
2.84 -@am__fastdepCC_TRUE@ if $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT video_gl.obj -MD -MP -MF "$(DEPDIR)/video_gl.Tpo" \
2.85 -@am__fastdepCC_TRUE@ -c -o video_gl.obj `if test -f 'drivers/video_gl.c'; then $(CYGPATH_W) 'drivers/video_gl.c'; else $(CYGPATH_W) '$(srcdir)/drivers/video_gl.c'; fi`; \
2.86 -@am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/video_gl.Tpo" "$(DEPDIR)/video_gl.Po"; \
2.87 -@am__fastdepCC_TRUE@ else rm -f "$(DEPDIR)/video_gl.Tpo"; exit 1; \
2.88 +gl_common.obj: drivers/gl_common.c
2.89 +@am__fastdepCC_TRUE@ if $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT gl_common.obj -MD -MP -MF "$(DEPDIR)/gl_common.Tpo" \
2.90 +@am__fastdepCC_TRUE@ -c -o gl_common.obj `if test -f 'drivers/gl_common.c'; then $(CYGPATH_W) 'drivers/gl_common.c'; else $(CYGPATH_W) '$(srcdir)/drivers/gl_common.c'; fi`; \
2.91 +@am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/gl_common.Tpo" "$(DEPDIR)/gl_common.Po"; \
2.92 +@am__fastdepCC_TRUE@ else rm -f "$(DEPDIR)/gl_common.Tpo"; exit 1; \
2.93 @am__fastdepCC_TRUE@ fi
2.94 -@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='drivers/video_gl.c' object='video_gl.obj' libtool=no @AMDEPBACKSLASH@
2.95 -@AMDEP_TRUE@@am__fastdepCC_FALSE@ depfile='$(DEPDIR)/video_gl.Po' tmpdepfile='$(DEPDIR)/video_gl.TPo' @AMDEPBACKSLASH@
2.96 +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='drivers/gl_common.c' object='gl_common.obj' libtool=no @AMDEPBACKSLASH@
2.97 +@AMDEP_TRUE@@am__fastdepCC_FALSE@ depfile='$(DEPDIR)/gl_common.Po' tmpdepfile='$(DEPDIR)/gl_common.TPo' @AMDEPBACKSLASH@
2.98 @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
2.99 -@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o video_gl.obj `if test -f 'drivers/video_gl.c'; then $(CYGPATH_W) 'drivers/video_gl.c'; else $(CYGPATH_W) '$(srcdir)/drivers/video_gl.c'; fi`
2.100 +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o gl_common.obj `if test -f 'drivers/gl_common.c'; then $(CYGPATH_W) 'drivers/gl_common.c'; else $(CYGPATH_W) '$(srcdir)/drivers/gl_common.c'; fi`
2.101 +
2.102 +gl_fbo.o: drivers/gl_fbo.c
2.103 +@am__fastdepCC_TRUE@ if $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT gl_fbo.o -MD -MP -MF "$(DEPDIR)/gl_fbo.Tpo" \
2.104 +@am__fastdepCC_TRUE@ -c -o gl_fbo.o `test -f 'drivers/gl_fbo.c' || echo '$(srcdir)/'`drivers/gl_fbo.c; \
2.105 +@am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/gl_fbo.Tpo" "$(DEPDIR)/gl_fbo.Po"; \
2.106 +@am__fastdepCC_TRUE@ else rm -f "$(DEPDIR)/gl_fbo.Tpo"; exit 1; \
2.107 +@am__fastdepCC_TRUE@ fi
2.108 +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='drivers/gl_fbo.c' object='gl_fbo.o' libtool=no @AMDEPBACKSLASH@
2.109 +@AMDEP_TRUE@@am__fastdepCC_FALSE@ depfile='$(DEPDIR)/gl_fbo.Po' tmpdepfile='$(DEPDIR)/gl_fbo.TPo' @AMDEPBACKSLASH@
2.110 +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
2.111 +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o gl_fbo.o `test -f 'drivers/gl_fbo.c' || echo '$(srcdir)/'`drivers/gl_fbo.c
2.112 +
2.113 +gl_fbo.obj: drivers/gl_fbo.c
2.114 +@am__fastdepCC_TRUE@ if $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT gl_fbo.obj -MD -MP -MF "$(DEPDIR)/gl_fbo.Tpo" \
2.115 +@am__fastdepCC_TRUE@ -c -o gl_fbo.obj `if test -f 'drivers/gl_fbo.c'; then $(CYGPATH_W) 'drivers/gl_fbo.c'; else $(CYGPATH_W) '$(srcdir)/drivers/gl_fbo.c'; fi`; \
2.116 +@am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/gl_fbo.Tpo" "$(DEPDIR)/gl_fbo.Po"; \
2.117 +@am__fastdepCC_TRUE@ else rm -f "$(DEPDIR)/gl_fbo.Tpo"; exit 1; \
2.118 +@am__fastdepCC_TRUE@ fi
2.119 +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='drivers/gl_fbo.c' object='gl_fbo.obj' libtool=no @AMDEPBACKSLASH@
2.120 +@AMDEP_TRUE@@am__fastdepCC_FALSE@ depfile='$(DEPDIR)/gl_fbo.Po' tmpdepfile='$(DEPDIR)/gl_fbo.TPo' @AMDEPBACKSLASH@
2.121 +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
2.122 +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o gl_fbo.obj `if test -f 'drivers/gl_fbo.c'; then $(CYGPATH_W) 'drivers/gl_fbo.c'; else $(CYGPATH_W) '$(srcdir)/drivers/gl_fbo.c'; fi`
2.123 uninstall-info-am:
2.124
2.125 ETAGS = etags
3.1 --- a/src/display.c Tue Feb 06 07:59:06 2007 +0000
3.2 +++ b/src/display.c Sun Feb 11 10:09:32 2007 +0000
3.3 @@ -1,5 +1,5 @@
3.4 /**
3.5 - * $Id: display.c,v 1.5 2007-01-25 13:03:23 nkeynes Exp $
3.6 + * $Id: display.c,v 1.6 2007-02-11 10:09:32 nkeynes Exp $
3.7 *
3.8 * Generic support for keyboard and other input sources. The active display
3.9 * driver is expected to deliver events here, where they're translated and
3.10 @@ -39,7 +39,8 @@
3.11 { GL_UNSIGNED_SHORT_4_4_4_4_REV, GL_BGRA, GL_RGBA4, 2 },
3.12 { GL_UNSIGNED_INT_8_8_8_8_REV, GL_BGRA, GL_RGBA8, 4 }, /* YUV decoded to ARGB8888 */
3.13 { GL_UNSIGNED_BYTE, GL_BGR, GL_RGB, 3 },
3.14 - { GL_UNSIGNED_INT_8_8_8_8_REV, GL_BGRA, GL_RGBA8, 4 }
3.15 + { GL_UNSIGNED_INT_8_8_8_8_REV, GL_BGRA, GL_RGBA8, 4 },
3.16 +
3.17 };
3.18
3.19 /**
3.20 @@ -151,7 +152,5 @@
3.21 display_driver = driver;
3.22 if( driver->init_driver != NULL )
3.23 driver->init_driver();
3.24 - driver->set_display_format( 640, 480, COLFMT_ARGB8888 );
3.25 - driver->set_render_format( 640, 480, COLFMT_ARGB8888, FALSE );
3.26 texcache_gl_init();
3.27 }
4.1 --- a/src/display.h Tue Feb 06 07:59:06 2007 +0000
4.2 +++ b/src/display.h Sun Feb 11 10:09:32 2007 +0000
4.3 @@ -1,5 +1,5 @@
4.4 /**
4.5 - * $Id: display.h,v 1.4 2007-01-27 12:03:53 nkeynes Exp $
4.6 + * $Id: display.h,v 1.5 2007-02-11 10:09:32 nkeynes Exp $
4.7 *
4.8 * The PC side of the video support (responsible for actually displaying /
4.9 * rendering frames)
4.10 @@ -20,6 +20,7 @@
4.11 #ifndef dream_video_H
4.12 #define dream_video_H
4.13
4.14 +#include "mem.h"
4.15 #include <stdint.h>
4.16 #include <glib.h>
4.17 #include <GL/gl.h>
4.18 @@ -50,17 +51,38 @@
4.19
4.20 extern int colour_format_bytes[];
4.21
4.22 -typedef struct video_buffer {
4.23 - uint32_t hres;
4.24 - uint32_t vres;
4.25 +/**
4.26 + * Structure to hold pixel data held in GL buffers.
4.27 + */
4.28 +typedef struct render_buffer {
4.29 + uint32_t width;
4.30 + uint32_t height;
4.31 uint32_t rowstride;
4.32 int colour_format;
4.33 - gboolean line_double;
4.34 - char *data;
4.35 -} *video_buffer_t;
4.36 + sh4addr_t address; /* Address buffer was rendered to, or -1 for unrendered */
4.37 + uint32_t size; /* Size of buffer in bytes, must be width*height*bpp */
4.38 + int scale;
4.39 + int buf_id; /* driver-specific buffer id, if applicable */
4.40 + gboolean flushed; /* True if the buffer has been flushed to vram */
4.41 +} *render_buffer_t;
4.42
4.43 /**
4.44 - * Core video driver - expected to directly support an OpenGL context
4.45 + * Structure to hold pixel data stored in pvr2 vram, as opposed to data in
4.46 + * GL buffers.
4.47 + */
4.48 +typedef struct frame_buffer {
4.49 + uint32_t width;
4.50 + uint32_t height;
4.51 + uint32_t rowstride;
4.52 + int colour_format;
4.53 + sh4addr_t address;
4.54 + uint32_t size; /* Size of buffer in bytes, must be width*height*bpp */
4.55 + char *data;
4.56 +} * frame_buffer_t;
4.57 +
4.58 +/**
4.59 + * Core video driver - exports function to setup a GL context, as well as handle
4.60 + * keyboard input and display resultant output.
4.61 */
4.62 typedef struct display_driver {
4.63 char *name;
4.64 @@ -87,47 +109,44 @@
4.65 uint16_t (*resolve_keysym)( const gchar *keysym );
4.66
4.67 /**
4.68 - * Set the current display format to the specified values. This is
4.69 - * called immediately prior to any display frame call where the
4.70 - * parameters have changed from the previous frame
4.71 + * Create a render target with the given width and height.
4.72 */
4.73 - gboolean (*set_display_format)( uint32_t hres, uint32_t vres,
4.74 - int colour_fmt );
4.75 + render_buffer_t (*create_render_buffer)( uint32_t width, uint32_t height );
4.76
4.77 /**
4.78 - * Set the current rendering format to the specified values. This is
4.79 - * called immediately prior to starting rendering of a frame where the
4.80 - * parameters have changed from the previous frame. Note that the driver
4.81 - * is not required to precisely support the requested colour format.
4.82 - *
4.83 - * This method is also responsible for setting up an appropriate GL
4.84 - * context for the main engine to render into.
4.85 - *
4.86 - * @param hres The horizontal resolution (ie 640)
4.87 - * @param vres The vertical resolution (ie 480)
4.88 - * @param colour_fmt The colour format of the buffer (ie COLFMT_ARGB4444)
4.89 - * @param texture Flag indicating that the frame being rendered is a
4.90 - * texture, rather than a display frame.
4.91 + * Destroy the specified render buffer and release any associated
4.92 + * resources.
4.93 */
4.94 - gboolean (*set_render_format)( uint32_t hres, uint32_t vres,
4.95 - int colour_fmt, gboolean texture );
4.96 + void (*destroy_render_buffer)( render_buffer_t buffer );
4.97 +
4.98 /**
4.99 - * Display a single frame using the supplied pixmap data. Is assumed to
4.100 - * invalidate the current GL front buffer (but not the back buffer).
4.101 + * Set the current rendering target to the specified buffer.
4.102 */
4.103 - gboolean (*display_frame)( video_buffer_t buffer );
4.104 + gboolean (*set_render_target)( render_buffer_t buffer );
4.105 +
4.106 + /**
4.107 + * Display a single frame using the supplied pixmap data.
4.108 + */
4.109 + gboolean (*display_frame_buffer)( frame_buffer_t buffer );
4.110 +
4.111 + /**
4.112 + * Display a single frame using a previously rendered GL buffer.
4.113 + */
4.114 + gboolean (*display_render_buffer)( render_buffer_t buffer );
4.115
4.116 /**
4.117 * Display a single blanked frame using a fixed colour for the
4.118 - * entire frame (specified in RGB888 format). Is assumed to invalidate
4.119 - * the current GL front buffer (but not the back buffer).
4.120 + * entire frame (specified in RGB888 format).
4.121 */
4.122 - gboolean (*display_blank_frame)( uint32_t rgb );
4.123 + gboolean (*display_blank)( uint32_t rgb );
4.124
4.125 /**
4.126 - * Promote the current render back buffer to the front buffer
4.127 + * Copy the image data from the GL buffer to the target memory buffer,
4.128 + * using the format etc from the buffer. This may force a glFinish()
4.129 + * but does not invalidate the buffer.
4.130 */
4.131 - void (*display_back_buffer)( void );
4.132 + gboolean (*read_render_buffer)( render_buffer_t buffer, char *target );
4.133 +
4.134 } *display_driver_t;
4.135
4.136 void video_open( void );
5.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
5.2 +++ b/src/drivers/gl_common.c Sun Feb 11 10:09:32 2007 +0000
5.3 @@ -0,0 +1,160 @@
5.4 +/**
5.5 + * $Id: gl_common.c,v 1.1 2007-02-11 10:09:32 nkeynes Exp $
5.6 + *
5.7 + * Common GL code that doesn't depend on a specific implementation
5.8 + *
5.9 + * Copyright (c) 2005 Nathan Keynes.
5.10 + *
5.11 + * This program is free software; you can redistribute it and/or modify
5.12 + * it under the terms of the GNU General Public License as published by
5.13 + * the Free Software Foundation; either version 2 of the License, or
5.14 + * (at your option) any later version.
5.15 + *
5.16 + * This program is distributed in the hope that it will be useful,
5.17 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
5.18 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
5.19 + * GNU General Public License for more details.
5.20 + */
5.21 +
5.22 +#include <GL/gl.h>
5.23 +#include "dream.h"
5.24 +#include "drivers/gl_common.h"
5.25 +
5.26 +extern uint32_t video_width, video_height;
5.27 +
5.28 +char *required_extensions[] = { "GL_EXT_framebuffer_object", NULL };
5.29 +
5.30 +/**
5.31 + * Test if a specific extension is supported. From opengl.org
5.32 + * @param extension extension name to check for
5.33 + * @return TRUE if supported, otherwise FALSE.
5.34 + */
5.35 +gboolean isGLExtensionSupported( const char *extension )
5.36 +{
5.37 + const GLubyte *extensions = NULL;
5.38 + const GLubyte *start;
5.39 + GLubyte *where, *terminator;
5.40 +
5.41 + /* Extension names should not have spaces. */
5.42 + where = (GLubyte *) strchr(extension, ' ');
5.43 + if (where || *extension == '\0')
5.44 + return 0;
5.45 + extensions = glGetString(GL_EXTENSIONS);
5.46 + /* It takes a bit of care to be fool-proof about parsing the
5.47 + OpenGL extensions string. Don't be fooled by sub-strings,
5.48 + etc. */
5.49 + start = extensions;
5.50 + for (;;) {
5.51 + where = (GLubyte *) strstr((const char *) start, extension);
5.52 + if (!where)
5.53 + break;
5.54 + terminator = where + strlen(extension);
5.55 + if (where == start || *(where - 1) == ' ')
5.56 + if (*terminator == ' ' || *terminator == '\0')
5.57 + return TRUE;
5.58 + start = terminator;
5.59 + }
5.60 + return FALSE;
5.61 +}
5.62 +
5.63 +gboolean hasRequiredGLExtensions( )
5.64 +{
5.65 + int i;
5.66 + gboolean isOK = TRUE;
5.67 +
5.68 + for( i=0; required_extensions[i] != NULL; i++ ) {
5.69 + if( !isGLExtensionSupported(required_extensions[i]) ) {
5.70 + ERROR( "Required OpenGL extension not supported: %s", required_extensions[i] );
5.71 + isOK = FALSE;
5.72 + }
5.73 + }
5.74 + return isOK;
5.75 +}
5.76 +
5.77 +
5.78 +gboolean gl_display_frame_buffer( frame_buffer_t frame )
5.79 +{
5.80 + GLenum type = colour_formats[frame->colour_format].type;
5.81 + GLenum format = colour_formats[frame->colour_format].format;
5.82 + int bpp = colour_formats[frame->colour_format].bpp;
5.83 + GLint texid;
5.84 +
5.85 + glViewport( 0, 0, video_width, video_height );
5.86 + glMatrixMode(GL_PROJECTION);
5.87 + glLoadIdentity();
5.88 + glOrtho( 0, video_width, video_height, 0, 0, -65535 );
5.89 + glMatrixMode(GL_MODELVIEW);
5.90 + glLoadIdentity();
5.91 +
5.92 + /* Disable everything */
5.93 + glDisable( GL_TEXTURE_2D );
5.94 + glDisable( GL_ALPHA_TEST );
5.95 + glDisable( GL_DEPTH_TEST );
5.96 + glDisable( GL_SCISSOR_TEST );
5.97 + glDisable( GL_CULL_FACE );
5.98 +
5.99 + float scale = ((float)video_height) / frame->height;
5.100 + int rowstride = (frame->rowstride / bpp) - frame->width;
5.101 +
5.102 +
5.103 + /*
5.104 + glGenTextures( 1, &texid );
5.105 + glBindTexture( GL_TEXTURE_2D, texid );
5.106 + glTexImage2D( GL_TEXTURE_2D, 0, colour_formats[frame->colour_format].int_format,
5.107 + frame->width, frame->height, 0, format, type, frame->data );
5.108 + glBegin( GL_QUADS );
5.109 + glTexCoord2i( 0, 1.0 );
5.110 + glVertex2f( 0.0, 0.0 );
5.111 + glTexCoord2i( 1.0, 1.0 );
5.112 + glVertex2f( frame->width, 0.0 );
5.113 + glTexCoord2i( 1.0, 0.0 );
5.114 + glVertex2f( frame->width, frame->height );
5.115 + glTexCoord2i( 0, 0.0 );
5.116 + glVertex2f( 0.0, frame->height );
5.117 + glEnd();
5.118 + glDeleteTextures( 1, &texid );
5.119 + */
5.120 + glRasterPos2i( 0, 0 );
5.121 + glPixelZoom( 1.0f, -scale );
5.122 + glPixelStorei( GL_UNPACK_ROW_LENGTH, rowstride );
5.123 + glDrawPixels( frame->width, frame->height, format, type,
5.124 + frame->data );
5.125 +
5.126 + glFlush();
5.127 + return TRUE;
5.128 +}
5.129 +
5.130 +gboolean gl_display_blank( uint32_t colour )
5.131 +{
5.132 + glViewport( 0, 0, video_width, video_height );
5.133 + glMatrixMode( GL_PROJECTION );
5.134 + glLoadIdentity();
5.135 + glOrtho( 0, video_width, video_height, 0, 0, -65535 );
5.136 + glMatrixMode(GL_MODELVIEW);
5.137 + glLoadIdentity();
5.138 + glColor3b( (colour >> 16) & 0xFF, (colour >> 8) & 0xFF, colour & 0xFF );
5.139 + glRecti(0,0, video_width, video_height );
5.140 + glFlush();
5.141 + return TRUE;
5.142 +}
5.143 +
5.144 +/**
5.145 + * Generic GL read_render_buffer. This function assumes that the caller
5.146 + * has already set the appropriate glReadBuffer(); in other words, unless
5.147 + * there's only one buffer this needs to be wrapped.
5.148 + */
5.149 +gboolean gl_read_render_buffer( render_buffer_t buffer, char *target )
5.150 +{
5.151 + if( buffer->address == -1 )
5.152 + return FALSE;
5.153 + glFinish();
5.154 + GLenum type = colour_formats[buffer->colour_format].type;
5.155 + GLenum format = colour_formats[buffer->colour_format].format;
5.156 + int line_size = buffer->width * colour_formats[buffer->colour_format].bpp;
5.157 + int size = line_size * buffer->height;
5.158 + int rowstride = (buffer->rowstride / colour_formats[buffer->colour_format].bpp) - buffer->width;
5.159 + // glPixelStorei( GL_PACK_ROW_LENGTH, rowstride );
5.160 +
5.161 + glReadPixels( 0, 0, buffer->width, buffer->height, format, type, target );
5.162 + return TRUE;
5.163 +}
6.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
6.2 +++ b/src/drivers/gl_common.h Sun Feb 11 10:09:32 2007 +0000
6.3 @@ -0,0 +1,57 @@
6.4 +/**
6.5 + * $Id: gl_common.h,v 1.1 2007-02-11 10:09:32 nkeynes Exp $
6.6 + *
6.7 + * Parent for all X11 display drivers.
6.8 + *
6.9 + * Copyright (c) 2005 Nathan Keynes.
6.10 + *
6.11 + * This program is free software; you can redistribute it and/or modify
6.12 + * it under the terms of the GNU General Public License as published by
6.13 + * the Free Software Foundation; either version 2 of the License, or
6.14 + * (at your option) any later version.
6.15 + *
6.16 + * This program is distributed in the hope that it will be useful,
6.17 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
6.18 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
6.19 + * GNU General Public License for more details.
6.20 + */
6.21 +
6.22 +#ifndef video_gl_common_H
6.23 +#define video_gl_common_H
6.24 +
6.25 +#include "display.h"
6.26 +
6.27 +/**
6.28 + * Test if a specific extension is supported. From opengl.org
6.29 + * @param extension extension name to check for
6.30 + * @return TRUE if supported, otherwise FALSE.
6.31 + */
6.32 +gboolean isGLExtensionSupported( const char *extension );
6.33 +
6.34 +gboolean hasRequiredGLExtensions();
6.35 +
6.36 +/**
6.37 + * Generic GL routine to draw the given frame buffer in the display view.
6.38 + */
6.39 +gboolean gl_display_frame_buffer( frame_buffer_t frame );
6.40 +
6.41 +/**
6.42 + * Generic GL routine to blank the display view with the specified colour.
6.43 + */
6.44 +gboolean gl_display_blank( uint32_t colour );
6.45 +
6.46 +
6.47 +/**
6.48 + * Generic GL read_render_buffer. This function assumes that the caller
6.49 + * has already set the appropriate glReadBuffer(); in other words, unless
6.50 + * there's only one buffer this needs to be wrapped.
6.51 + */
6.52 +gboolean gl_read_render_buffer( render_buffer_t buffer, char *target );
6.53 +
6.54 +
6.55 +/****** FBO handling (gl_fbo.c) ******/
6.56 +gboolean gl_fbo_is_supported();
6.57 +void gl_fbo_shutdown();
6.58 +void gl_fbo_init( display_driver_t driver );
6.59 +
6.60 +#endif /* !video_gl_common_H */
7.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
7.2 +++ b/src/drivers/gl_fbo.c Sun Feb 11 10:09:32 2007 +0000
7.3 @@ -0,0 +1,299 @@
7.4 +/**
7.5 + * $Id: gl_fbo.c,v 1.1 2007-02-11 10:09:32 nkeynes Exp $
7.6 + *
7.7 + * GL framebuffer-based driver shell. This requires the EXT_framebuffer_object
7.8 + * extension, but is much nicer/faster/etc than pbuffers when it's available.
7.9 + * This is (optionally) used indirectly by the top-level GLX driver.
7.10 + *
7.11 + * Strategy-wise, we maintain 2 framebuffers with up to 4 target colour
7.12 + * buffers a piece. Effectively this reserves one fb for display output,
7.13 + * and the other for texture output (each fb has a single size).
7.14 + *
7.15 + * Copyright (c) 2005 Nathan Keynes.
7.16 + *
7.17 + * This program is free software; you can redistribute it and/or modify
7.18 + * it under the terms of the GNU General Public License as published by
7.19 + * the Free Software Foundation; either version 2 of the License, or
7.20 + * (at your option) any later version.
7.21 + *
7.22 + * This program is distributed in the hope that it will be useful,
7.23 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
7.24 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
7.25 + * GNU General Public License for more details.
7.26 + */
7.27 +
7.28 +#include <GL/gl.h>
7.29 +#include "display.h"
7.30 +
7.31 +#define MAX_FRAMEBUFFERS 2
7.32 +#define MAX_TEXTURES_PER_FB 4
7.33 +
7.34 +static render_buffer_t gl_fbo_create_render_buffer( uint32_t width, uint32_t height );
7.35 +static void gl_fbo_destroy_render_buffer( render_buffer_t buffer );
7.36 +static gboolean gl_fbo_set_render_target( render_buffer_t buffer );
7.37 +static gboolean gl_fbo_display_render_buffer( render_buffer_t buffer );
7.38 +static gboolean gl_fbo_display_frame_buffer( frame_buffer_t buffer );
7.39 +static gboolean gl_fbo_display_blank( uint32_t colour );
7.40 +static gboolean gl_fbo_read_render_buffer( render_buffer_t buffer, char *target );
7.41 +
7.42 +extern uint32_t video_width, video_height;
7.43 +
7.44 +/**
7.45 + * Framebuffer info structure
7.46 + */
7.47 +struct gl_fbo_info {
7.48 + GLuint fb_id;
7.49 + GLuint depth_id;
7.50 + GLuint stencil_id;
7.51 + GLuint tex_ids[MAX_TEXTURES_PER_FB];
7.52 + int width, height;
7.53 +};
7.54 +
7.55 +static struct gl_fbo_info fbo[MAX_FRAMEBUFFERS];
7.56 +const static int ATTACHMENT_POINTS[MAX_TEXTURES_PER_FB] = {
7.57 + GL_COLOR_ATTACHMENT0_EXT, GL_COLOR_ATTACHMENT1_EXT,
7.58 + GL_COLOR_ATTACHMENT2_EXT, GL_COLOR_ATTACHMENT3_EXT };
7.59 +static int last_used_fbo;
7.60 +
7.61 +gboolean gl_fbo_is_supported()
7.62 +{
7.63 + return isGLExtensionSupported("GL_EXT_framebuffer_object");
7.64 +}
7.65 +
7.66 +/**
7.67 + * Construct the initial frame buffers and allocate ids for everything.
7.68 + * The render handling driver methods are set to the fbo versions.
7.69 + */
7.70 +void gl_fbo_init( display_driver_t driver )
7.71 +{
7.72 + int i,j;
7.73 + int fbids[MAX_FRAMEBUFFERS];
7.74 + int rbids[MAX_FRAMEBUFFERS*2]; /* depth buffer, stencil buffer per fb */
7.75 +
7.76 + glGenFramebuffersEXT( MAX_FRAMEBUFFERS, &fbids );
7.77 + glGenRenderbuffersEXT( MAX_FRAMEBUFFERS*2, &rbids );
7.78 + for( i=0; i<MAX_FRAMEBUFFERS; i++ ) {
7.79 + fbo[i].fb_id = fbids[i];
7.80 + fbo[i].depth_id = rbids[i*2];
7.81 + fbo[i].stencil_id = rbids[i*2+1];
7.82 + fbo[i].width = -1;
7.83 + fbo[i].height = -1;
7.84 + for( j=0; j<MAX_TEXTURES_PER_FB; j++ ) {
7.85 + fbo[i].tex_ids[j] = -1;
7.86 + }
7.87 + }
7.88 + last_used_fbo = 0;
7.89 +
7.90 + driver->create_render_buffer = gl_fbo_create_render_buffer;
7.91 + driver->destroy_render_buffer = gl_fbo_destroy_render_buffer;
7.92 + driver->set_render_target = gl_fbo_set_render_target;
7.93 + driver->display_render_buffer = gl_fbo_display_render_buffer;
7.94 + driver->display_frame_buffer = gl_fbo_display_frame_buffer;
7.95 + driver->display_blank = gl_fbo_display_blank;
7.96 + driver->read_render_buffer = gl_fbo_read_render_buffer;
7.97 +}
7.98 +
7.99 +void gl_fbo_shutdown()
7.100 +{
7.101 + int i;
7.102 + glBindFramebufferEXT( GL_FRAMEBUFFER_EXT, 0 );
7.103 + for( i=0; i<MAX_FRAMEBUFFERS; i++ ) {
7.104 + glDeleteFramebuffersEXT( 1, &fbo[i].fb_id );
7.105 + glDeleteRenderbuffersEXT( 2, &fbo[i].depth_id );
7.106 + }
7.107 +}
7.108 +
7.109 +void gl_fbo_setup_framebuffer( int bufno, int width, int height )
7.110 +{
7.111 + glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbo[bufno].fb_id);
7.112 + glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, fbo[bufno].depth_id);
7.113 + glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT24, width, height);
7.114 + glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT,
7.115 + GL_RENDERBUFFER_EXT, fbo[bufno].depth_id);
7.116 + /* Stencil doesn't work on ATI, and we're not using it at the moment anyway, so...
7.117 + glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, fbo[bufno].stencil_id);
7.118 + glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_STENCIL_INDEX, width, height);
7.119 + glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_STENCIL_ATTACHMENT_EXT,
7.120 + GL_RENDERBUFFER_EXT, fbo[bufno].stencil_id);
7.121 + */
7.122 + fbo[bufno].width = width;
7.123 + fbo[bufno].height = height;
7.124 +}
7.125 +
7.126 +int gl_fbo_get_framebuffer( int width, int height )
7.127 +{
7.128 + int bufno = -1, i;
7.129 + /* find a compatible framebuffer context */
7.130 + for( i=0; i<MAX_FRAMEBUFFERS; i++ ) {
7.131 + if( fbo[i].width == -1 && bufno == -1 ) {
7.132 + bufno = i;
7.133 + } else if( fbo[i].width == width && fbo[i].height == height ) {
7.134 + bufno = i;
7.135 + break;
7.136 + }
7.137 + }
7.138 + if( bufno == -1 ) {
7.139 + bufno = last_used_fbo + 1;
7.140 + if( bufno > MAX_FRAMEBUFFERS ) {
7.141 + bufno = 0;
7.142 + }
7.143 + last_used_fbo = bufno;
7.144 + }
7.145 + if( fbo[bufno].width == width && fbo[bufno].height == height ) {
7.146 + glBindFramebufferEXT( GL_FRAMEBUFFER_EXT, fbo[bufno].fb_id );
7.147 + } else {
7.148 + gl_fbo_setup_framebuffer( bufno, width, height );
7.149 + }
7.150 + return bufno;
7.151 +}
7.152 +
7.153 +/**
7.154 + * Attach a texture to the framebuffer. The texture must already be initialized
7.155 + * to the correct dimensions etc.
7.156 + */
7.157 +static GLint gl_fbo_attach_texture( int fbo_no, GLint tex_id ) {
7.158 + int attach = -1, i;
7.159 + for( i=0; i<MAX_TEXTURES_PER_FB; i++ ) {
7.160 + if( fbo[fbo_no].tex_ids[i] == tex_id ) {
7.161 + glDrawBuffer(ATTACHMENT_POINTS[i]);
7.162 + glReadBuffer(ATTACHMENT_POINTS[i]);
7.163 + return ATTACHMENT_POINTS[i]; // already attached
7.164 + } else if( fbo[fbo_no].tex_ids[i] == -1 && attach == -1 ) {
7.165 + attach = i;
7.166 + }
7.167 + }
7.168 + if( attach == -1 ) {
7.169 + /* should never happen */
7.170 + attach = 0;
7.171 + }
7.172 + fbo[fbo_no].tex_ids[attach] = tex_id;
7.173 + glBindTexture( GL_TEXTURE_RECTANGLE_ARB, 0 ); // Ensure the output texture is unbound
7.174 + glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, ATTACHMENT_POINTS[attach],
7.175 + GL_TEXTURE_RECTANGLE_ARB, tex_id, 0 );
7.176 + /* Set draw/read buffers by default */
7.177 + glDrawBuffer(ATTACHMENT_POINTS[attach]);
7.178 + glReadBuffer(ATTACHMENT_POINTS[attach]);
7.179 +
7.180 +
7.181 + GLint status = glGetError();
7.182 + if( status != GL_NO_ERROR ) {
7.183 + ERROR( "GL error setting render target (%x)!", status );
7.184 + }
7.185 + status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);
7.186 + if( status != GL_FRAMEBUFFER_COMPLETE_EXT ) {
7.187 + ERROR( "Framebuffer failure: %x", status );
7.188 + exit(1);
7.189 + }
7.190 +
7.191 + return ATTACHMENT_POINTS[attach];
7.192 +}
7.193 +
7.194 +static render_buffer_t gl_fbo_create_render_buffer( uint32_t width, uint32_t height )
7.195 +{
7.196 + render_buffer_t buffer = calloc( sizeof(struct render_buffer), 1 );
7.197 + buffer->width = width;
7.198 + buffer->height = height;
7.199 + glGenTextures( 1, &buffer->buf_id );
7.200 + glBindTexture( GL_TEXTURE_RECTANGLE_ARB, buffer->buf_id );
7.201 + glTexParameteri( GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_S, GL_CLAMP );
7.202 + glTexParameteri( GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_T, GL_CLAMP );
7.203 + glTexParameteri( GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, GL_NEAREST );
7.204 + glTexParameteri( GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, GL_NEAREST );
7.205 + glTexImage2D( GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL );
7.206 + return buffer;
7.207 +}
7.208 +
7.209 +static void gl_fbo_destroy_render_buffer( render_buffer_t buffer )
7.210 +{
7.211 + int i,j;
7.212 + for( i=0; i<MAX_FRAMEBUFFERS; i++ ) {
7.213 + for( j=0; j < MAX_TEXTURES_PER_FB; j++ ) {
7.214 + if( fbo[i].tex_ids[j] == buffer->buf_id ) {
7.215 + glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, ATTACHMENT_POINTS[j],
7.216 + GL_TEXTURE_RECTANGLE_ARB, GL_NONE, 0 );
7.217 + fbo[i].tex_ids[j] = -1;
7.218 + }
7.219 + }
7.220 + }
7.221 +
7.222 + glDeleteTextures( 1, &buffer->buf_id );
7.223 + buffer->buf_id = 0;
7.224 + free( buffer );
7.225 +}
7.226 +
7.227 +static gboolean gl_fbo_set_render_target( render_buffer_t buffer )
7.228 +{
7.229 + glGetError();
7.230 + int fb = gl_fbo_get_framebuffer( buffer->width, buffer->height );
7.231 + GLint attach = gl_fbo_attach_texture( fb, buffer->buf_id );
7.232 + /* setup the gl context */
7.233 + glViewport( 0, 0, buffer->width, buffer->height );
7.234 +
7.235 + return TRUE;
7.236 +}
7.237 +
7.238 +/**
7.239 + * Render the texture holding the given buffer to the front window
7.240 + * buffer.
7.241 + */
7.242 +static gboolean gl_fbo_display_render_buffer( render_buffer_t buffer )
7.243 +{
7.244 + glFinish();
7.245 + glBindFramebufferEXT( GL_FRAMEBUFFER_EXT, 0 ); // real window
7.246 + glViewport( 0, 0, video_width, video_height );
7.247 + glEnable( GL_TEXTURE_RECTANGLE_ARB );
7.248 + glBindTexture( GL_TEXTURE_RECTANGLE_ARB, buffer->buf_id );
7.249 + glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE );
7.250 + glDrawBuffer( GL_FRONT );
7.251 + glReadBuffer( GL_FRONT );
7.252 + glDisable( GL_ALPHA_TEST );
7.253 + glDisable( GL_DEPTH_TEST );
7.254 + glDisable( GL_SCISSOR_TEST );
7.255 + glDisable( GL_CULL_FACE );
7.256 +
7.257 + glMatrixMode(GL_PROJECTION);
7.258 + glLoadIdentity();
7.259 + glOrtho( 0, buffer->width, buffer->height, 0, 0, -65535 );
7.260 + glMatrixMode(GL_MODELVIEW);
7.261 + glLoadIdentity();
7.262 + glEnable( GL_BLEND );
7.263 + glBlendFunc( GL_ONE, GL_ZERO );
7.264 + glDisable( GL_DEPTH_TEST );
7.265 + glBegin( GL_QUADS );
7.266 + glTexCoord2i( 0, buffer->height );
7.267 + glVertex2f( 0.0, 0.0 );
7.268 + glTexCoord2i( buffer->width, buffer->height );
7.269 + glVertex2f( buffer->width, 0.0 );
7.270 + glTexCoord2i( buffer->width, 0 );
7.271 + glVertex2f( buffer->width, buffer->height );
7.272 + glTexCoord2i( 0, 0 );
7.273 + glVertex2f( 0.0, buffer->height );
7.274 + glEnd();
7.275 + glDisable( GL_TEXTURE_RECTANGLE_ARB );
7.276 + glFlush();
7.277 + return TRUE;
7.278 +}
7.279 +
7.280 +static gboolean gl_fbo_display_frame_buffer( frame_buffer_t buffer )
7.281 +{
7.282 + glBindFramebufferEXT( GL_FRAMEBUFFER_EXT, 0 );
7.283 + glDrawBuffer( GL_FRONT );
7.284 + glReadBuffer( GL_FRONT );
7.285 + return gl_display_frame_buffer( buffer );
7.286 +}
7.287 +
7.288 +static gboolean gl_fbo_display_blank( uint32_t colour )
7.289 +{
7.290 + glBindFramebufferEXT( GL_FRAMEBUFFER_EXT, 0 );
7.291 + glDrawBuffer( GL_FRONT );
7.292 + glReadBuffer( GL_FRONT );
7.293 + return gl_display_blank( colour );
7.294 +}
7.295 +
7.296 +static gboolean gl_fbo_read_render_buffer( render_buffer_t buffer, char *target )
7.297 +{
7.298 + int fb = gl_fbo_get_framebuffer( buffer->width, buffer->height );
7.299 + GLint attach = gl_fbo_attach_texture( fb, buffer->buf_id );
7.300 + return gl_read_render_buffer( buffer, target );
7.301 +}
7.302 +
8.1 --- a/src/drivers/video_gl.c Tue Feb 06 07:59:06 2007 +0000
8.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
8.3 @@ -1,70 +0,0 @@
8.4 -/**
8.5 - * $Id: video_gl.c,v 1.2 2007-01-15 12:57:12 nkeynes Exp $
8.6 - *
8.7 - * Common GL code that doesn't depend on a specific implementation
8.8 - *
8.9 - * Copyright (c) 2005 Nathan Keynes.
8.10 - *
8.11 - * This program is free software; you can redistribute it and/or modify
8.12 - * it under the terms of the GNU General Public License as published by
8.13 - * the Free Software Foundation; either version 2 of the License, or
8.14 - * (at your option) any later version.
8.15 - *
8.16 - * This program is distributed in the hope that it will be useful,
8.17 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
8.18 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
8.19 - * GNU General Public License for more details.
8.20 - */
8.21 -
8.22 -#include "dream.h"
8.23 -#include "drivers/video_gl.h"
8.24 -#include <GL/gl.h>
8.25 -
8.26 -char *required_extensions[] = { "GL_EXT_framebuffer_object", NULL };
8.27 -
8.28 -/**
8.29 - * Test if a specific extension is supported. From opengl.org
8.30 - * @param extension extension name to check for
8.31 - * @return TRUE if supported, otherwise FALSE.
8.32 - */
8.33 -gboolean isGLExtensionSupported( const char *extension )
8.34 -{
8.35 - const GLubyte *extensions = NULL;
8.36 - const GLubyte *start;
8.37 - GLubyte *where, *terminator;
8.38 -
8.39 - /* Extension names should not have spaces. */
8.40 - where = (GLubyte *) strchr(extension, ' ');
8.41 - if (where || *extension == '\0')
8.42 - return 0;
8.43 - extensions = glGetString(GL_EXTENSIONS);
8.44 - /* It takes a bit of care to be fool-proof about parsing the
8.45 - OpenGL extensions string. Don't be fooled by sub-strings,
8.46 - etc. */
8.47 - start = extensions;
8.48 - for (;;) {
8.49 - where = (GLubyte *) strstr((const char *) start, extension);
8.50 - if (!where)
8.51 - break;
8.52 - terminator = where + strlen(extension);
8.53 - if (where == start || *(where - 1) == ' ')
8.54 - if (*terminator == ' ' || *terminator == '\0')
8.55 - return TRUE;
8.56 - start = terminator;
8.57 - }
8.58 - return FALSE;
8.59 -}
8.60 -
8.61 -gboolean hasRequiredGLExtensions( )
8.62 -{
8.63 - int i;
8.64 - gboolean isOK = TRUE;
8.65 -
8.66 - for( i=0; required_extensions[i] != NULL; i++ ) {
8.67 - if( !isGLExtensionSupported(required_extensions[i]) ) {
8.68 - ERROR( "Required OpenGL extension not supported: %s", required_extensions[i] );
8.69 - isOK = FALSE;
8.70 - }
8.71 - }
8.72 - return isOK;
8.73 -}
9.1 --- a/src/drivers/video_gl.h Tue Feb 06 07:59:06 2007 +0000
9.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
9.3 @@ -1,32 +0,0 @@
9.4 -/**
9.5 - * $Id: video_gl.h,v 1.1 2007-01-14 02:55:06 nkeynes Exp $
9.6 - *
9.7 - * Parent for all X11 display drivers.
9.8 - *
9.9 - * Copyright (c) 2005 Nathan Keynes.
9.10 - *
9.11 - * This program is free software; you can redistribute it and/or modify
9.12 - * it under the terms of the GNU General Public License as published by
9.13 - * the Free Software Foundation; either version 2 of the License, or
9.14 - * (at your option) any later version.
9.15 - *
9.16 - * This program is distributed in the hope that it will be useful,
9.17 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
9.18 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
9.19 - * GNU General Public License for more details.
9.20 - */
9.21 -
9.22 -#ifndef video_gl_common_H
9.23 -#define video_gl_common_H
9.24 -
9.25 -
9.26 -/**
9.27 - * Test if a specific extension is supported. From opengl.org
9.28 - * @param extension extension name to check for
9.29 - * @return TRUE if supported, otherwise FALSE.
9.30 - */
9.31 -gboolean isGLExtensionSupported( const char *extension );
9.32 -
9.33 -gboolean hasRequiredGLExtensions();
9.34 -
9.35 -#endif /* !video_gl_common_H */
10.1 --- a/src/drivers/video_gtk.c Tue Feb 06 07:59:06 2007 +0000
10.2 +++ b/src/drivers/video_gtk.c Sun Feb 11 10:09:32 2007 +0000
10.3 @@ -1,5 +1,5 @@
10.4 /**
10.5 - * $Id: video_gtk.c,v 1.9 2007-01-27 12:03:53 nkeynes Exp $
10.6 + * $Id: video_gtk.c,v 1.10 2007-02-11 10:09:32 nkeynes Exp $
10.7 *
10.8 * The PC side of the video support (responsible for actually displaying /
10.9 * rendering frames)
10.10 @@ -29,25 +29,15 @@
10.11 GtkWidget *video_area = NULL;
10.12 uint32_t video_width = 640;
10.13 uint32_t video_height = 480;
10.14 -uint32_t video_frame_count = 0;
10.15
10.16 +gboolean video_gtk_init();
10.17 +void video_gtk_shutdown();
10.18 uint16_t video_gtk_resolve_keysym( const gchar *keysym );
10.19 -gboolean video_gtk_set_output_format( uint32_t width, uint32_t height,
10.20 - int colour_format );
10.21 -gboolean video_gtk_set_render_format( uint32_t width, uint32_t height,
10.22 - int colour_format, gboolean texture );
10.23 -gboolean video_gtk_display_frame( video_buffer_t frame );
10.24 -gboolean video_gtk_blank( uint32_t rgb );
10.25
10.26 -struct display_driver display_gtk_driver = { "gtk",
10.27 - NULL,
10.28 - NULL,
10.29 - video_gtk_resolve_keysym,
10.30 - video_gtk_set_output_format,
10.31 - video_gtk_set_render_format,
10.32 - video_gtk_display_frame,
10.33 - video_gtk_blank,
10.34 - video_glx_swap_buffers };
10.35 +struct display_driver display_gtk_driver = { "gtk", video_gtk_init, NULL,
10.36 + video_gtk_resolve_keysym,
10.37 + NULL, NULL, NULL, NULL, NULL, NULL, NULL };
10.38 +
10.39
10.40 gboolean video_gtk_keydown_callback(GtkWidget *widget,
10.41 GdkEventKey *event,
10.42 @@ -71,115 +61,39 @@
10.43 input_event_keyup( event->keyval );
10.44 }
10.45
10.46 -gboolean video_gtk_set_output_format( uint32_t width, uint32_t height,
10.47 - int colour_format )
10.48 +gboolean video_gtk_init()
10.49 {
10.50 - if( video_win == NULL ) {
10.51 - video_win = GTK_WINDOW(gtk_window_new( GTK_WINDOW_TOPLEVEL ));
10.52 - gtk_window_set_title( video_win, APP_NAME " - Emulation Window" );
10.53 - gtk_window_set_policy( video_win, FALSE, FALSE, FALSE );
10.54 - gtk_window_set_default_size( video_win, video_width, video_height );
10.55 + video_win = GTK_WINDOW(gtk_window_new( GTK_WINDOW_TOPLEVEL ));
10.56 + gtk_window_set_title( video_win, APP_NAME " - Emulation Window" );
10.57 + gtk_window_set_policy( video_win, FALSE, FALSE, FALSE );
10.58
10.59 - g_signal_connect( video_win, "key_press_event",
10.60 - G_CALLBACK(video_gtk_keydown_callback), NULL );
10.61 - g_signal_connect( video_win, "key_release_event",
10.62 - G_CALLBACK(video_gtk_keyup_callback), NULL );
10.63 - gtk_widget_add_events( GTK_WIDGET(video_win),
10.64 - GDK_KEY_PRESS_MASK | GDK_KEY_RELEASE_MASK |
10.65 - GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK );
10.66 - video_area = gtk_image_new();
10.67 - gtk_widget_show( GTK_WIDGET(video_area) );
10.68 - gtk_container_add( GTK_CONTAINER(video_win), GTK_WIDGET(video_area) );
10.69 - gtk_widget_show( GTK_WIDGET(video_win) );
10.70 - video_x11_set_display( gdk_x11_display_get_xdisplay( gtk_widget_get_display(video_area)),
10.71 - gdk_x11_screen_get_xscreen( gtk_widget_get_screen(video_area)),
10.72 - GDK_WINDOW_XWINDOW( GTK_WIDGET(video_win)->window ) );
10.73 -
10.74 - }
10.75 + g_signal_connect( video_win, "key_press_event",
10.76 + G_CALLBACK(video_gtk_keydown_callback), NULL );
10.77 + g_signal_connect( video_win, "key_release_event",
10.78 + G_CALLBACK(video_gtk_keyup_callback), NULL );
10.79 + gtk_widget_add_events( GTK_WIDGET(video_win),
10.80 + GDK_KEY_PRESS_MASK | GDK_KEY_RELEASE_MASK |
10.81 + GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK );
10.82 + video_area = gtk_image_new();
10.83 + gtk_widget_show( GTK_WIDGET(video_area) );
10.84 + gtk_container_add( GTK_CONTAINER(video_win), GTK_WIDGET(video_area) );
10.85 + gtk_widget_show( GTK_WIDGET(video_win) );
10.86 + video_img = gdk_image_new( GDK_IMAGE_FASTEST, gdk_visual_get_system(),
10.87 + video_width, video_height );
10.88 + gtk_image_set_from_image( GTK_IMAGE(video_area), video_img, NULL );
10.89 +
10.90 gtk_window_set_default_size( video_win, video_width, video_height );
10.91 - video_img = gdk_image_new( GDK_IMAGE_FASTEST, gdk_visual_get_system(),
10.92 - video_width, video_height );
10.93 - gtk_image_set_from_image( GTK_IMAGE(video_area), video_img, NULL );
10.94 - /* Note old image is auto de-refed */
10.95 +
10.96 + video_glx_init( gdk_x11_display_get_xdisplay( gtk_widget_get_display(GTK_WIDGET(video_win))),
10.97 + gdk_x11_screen_get_xscreen( gtk_widget_get_screen(GTK_WIDGET(video_win))),
10.98 + GDK_WINDOW_XWINDOW( GTK_WIDGET(video_win)->window ),
10.99 + video_width, video_height, &display_gtk_driver );
10.100 return TRUE;
10.101 }
10.102
10.103 +void video_gtk_shutdown()
10.104 +{
10.105
10.106 -/**
10.107 - * Fill the entire frame with the specified colour (00RRGGBB)
10.108 - */
10.109 -gboolean video_gtk_blank( uint32_t colour )
10.110 -{
10.111 - video_glx_blank( video_width, video_height, colour );
10.112 +
10.113 }
10.114
10.115 -gboolean video_gtk_display_frame( video_buffer_t frame )
10.116 -{
10.117 - uint32_t bytes_per_line, x, y;
10.118 - char *src = frame->data;
10.119 - char *dest = video_img->mem;
10.120 -
10.121 - return video_glx_display_frame( frame );
10.122 -
10.123 - switch( frame->colour_format ) {
10.124 - case COLFMT_ARGB1555:
10.125 - for( y=0; y < frame->vres; y++ ) {
10.126 - uint16_t *p = (uint16_t *)src;
10.127 - for( x=0; x < frame->hres; x++ ) {
10.128 - uint16_t pixel = *p++;
10.129 - *dest++ = (pixel & 0x1F) << 3;
10.130 - *dest++ = (pixel & 0x3E0) >> 2;
10.131 - *dest++ = (pixel & 0x7C00) >> 7;
10.132 - *dest++ = 0;
10.133 - }
10.134 - src += frame->rowstride;
10.135 - }
10.136 - break;
10.137 - case COLFMT_RGB565:
10.138 - for( y=0; y < frame->vres; y++ ) {
10.139 - uint16_t *p = (uint16_t *)src;
10.140 - for( x=0; x < frame->hres; x++ ) {
10.141 - uint16_t pixel = *p++;
10.142 - *dest++ = (pixel & 0x1F) << 3;
10.143 - *dest++ = (pixel & 0x7E0) >> 3;
10.144 - *dest++ = (pixel & 0xF800) >> 8;
10.145 - *dest++ = 0;
10.146 - }
10.147 - src += frame->rowstride;
10.148 - }
10.149 - break;
10.150 - case COLFMT_RGB888:
10.151 - for( y=0; y< frame->vres; y++ ) {
10.152 - char *p = src;
10.153 - for( x=0; x < frame->hres; x++ ) {
10.154 - *dest++ = *p++;
10.155 - *dest++ = *p++;
10.156 - *dest++ = *p++;
10.157 - *dest++ = 0;
10.158 - }
10.159 - src += frame->rowstride;
10.160 - }
10.161 - break;
10.162 - case COLFMT_ARGB8888:
10.163 - bytes_per_line = frame->hres << 2;
10.164 - if( bytes_per_line == frame->rowstride ) {
10.165 - /* A little bit faster */
10.166 - memcpy( dest, src, bytes_per_line * frame->vres );
10.167 - } else {
10.168 - for( y=0; y< frame->vres; y++ ) {
10.169 - memcpy( dest, src, bytes_per_line );
10.170 - src += frame->rowstride;
10.171 - dest += bytes_per_line;
10.172 - }
10.173 - }
10.174 - break;
10.175 - }
10.176 - gtk_widget_queue_draw( video_area );
10.177 - return TRUE;
10.178 -}
10.179 -
10.180 -gboolean video_gtk_set_render_format( uint32_t width, uint32_t height,
10.181 - int colour_format, gboolean texture )
10.182 -{
10.183 - return video_glx_set_render_format( 0, 0, width, height );
10.184 -}
11.1 --- a/src/drivers/video_null.c Tue Feb 06 07:59:06 2007 +0000
11.2 +++ b/src/drivers/video_null.c Sun Feb 11 10:09:32 2007 +0000
11.3 @@ -1,5 +1,5 @@
11.4 /**
11.5 - * $Id: video_null.c,v 1.2 2006-05-15 08:28:52 nkeynes Exp $
11.6 + * $Id: video_null.c,v 1.3 2007-02-11 10:09:32 nkeynes Exp $
11.7 *
11.8 * Null video output driver (ie no video output whatsoever)
11.9 *
11.10 @@ -18,24 +18,37 @@
11.11
11.12 #include "display.h"
11.13
11.14 -gboolean video_null_set_output_format( uint32_t hres, uint32_t vres,
11.15 - int colour_format )
11.16 +render_buffer_t video_null_create_render_buffer( uint32_t hres, uint32_t vres )
11.17 +{
11.18 + return NULL;
11.19 +}
11.20 +
11.21 +void video_null_destroy_render_buffer( render_buffer_t buffer )
11.22 {
11.23 return TRUE;
11.24 }
11.25
11.26 -gboolean video_null_set_render_format( uint32_t hres, uint32_t vres,
11.27 - int colour_format, gboolean tex )
11.28 +gboolean video_null_set_render_target( render_buffer_t buffer )
11.29 {
11.30 return TRUE;
11.31 }
11.32
11.33 -gboolean video_null_display_frame( video_buffer_t buffer )
11.34 +gboolean video_null_display_render_buffer( render_buffer_t buffer )
11.35 {
11.36 return TRUE;
11.37 }
11.38
11.39 -gboolean video_null_blank( uint32_t colour )
11.40 +gboolean video_null_read_render_buffer( render_buffer_t buffer, char *target )
11.41 +{
11.42 + return TRUE;
11.43 +}
11.44 +
11.45 +gboolean video_null_display_frame_buffer( frame_buffer_t buffer )
11.46 +{
11.47 + return TRUE;
11.48 +}
11.49 +
11.50 +gboolean video_null_display_blank( uint32_t colour )
11.51 {
11.52 return TRUE;
11.53 }
11.54 @@ -46,10 +59,13 @@
11.55
11.56
11.57 struct display_driver display_null_driver = { "null",
11.58 - NULL,
11.59 - NULL,
11.60 - video_null_set_output_format,
11.61 - video_null_set_render_format,
11.62 - video_null_display_frame,
11.63 - video_null_blank,
11.64 - video_null_display_back_buffer };
11.65 + NULL,
11.66 + NULL,
11.67 + NULL,
11.68 + video_null_create_render_buffer,
11.69 + video_null_destroy_render_buffer,
11.70 + video_null_set_render_target,
11.71 + video_null_display_render_buffer,
11.72 + video_null_display_frame_buffer,
11.73 + video_null_display_blank,
11.74 + video_null_read_render_buffer };
12.1 --- a/src/drivers/video_x11.c Tue Feb 06 07:59:06 2007 +0000
12.2 +++ b/src/drivers/video_x11.c Sun Feb 11 10:09:32 2007 +0000
12.3 @@ -1,5 +1,5 @@
12.4 /**
12.5 - * $Id: video_x11.c,v 1.11 2007-01-27 12:03:53 nkeynes Exp $
12.6 + * $Id: video_x11.c,v 1.12 2007-02-11 10:09:32 nkeynes Exp $
12.7 *
12.8 * Shared functions for all X11-based display drivers.
12.9 *
12.10 @@ -21,30 +21,46 @@
12.11 #include "dream.h"
12.12 #include "drivers/video_x11.h"
12.13
12.14 +extern uint32_t video_width, video_height;
12.15 +
12.16 /**
12.17 * General X11 parameters. The front-end driver is expected to set this up
12.18 - * by calling video_x11_set_display after initializing itself.
12.19 + * by calling video_glx_init after initializing itself.
12.20 */
12.21 -Display *video_x11_display = NULL;
12.22 -Screen *video_x11_screen = NULL;
12.23 -Window video_x11_window = 0;
12.24 -extern uint32_t video_width, video_height;
12.25 +static Display *video_x11_display = NULL;
12.26 +static Screen *video_x11_screen = NULL;
12.27 +static Window video_x11_window = 0;
12.28 +
12.29 /**
12.30 * GLX parameters.
12.31 */
12.32 -GLXContext glx_context;
12.33 -Window glx_window;
12.34 -gboolean glx_open = FALSE;
12.35 +static GLXContext glx_context;
12.36 +static Window glx_window;
12.37 +static XSetWindowAttributes win_attrs;
12.38
12.39 -void video_x11_set_display( Display *display, Screen *screen, Window window )
12.40 +gboolean video_glx_init( Display *display, Screen *screen, Window window,
12.41 + int width, int height, display_driver_t driver )
12.42 {
12.43 video_x11_display = display;
12.44 video_x11_screen = screen;
12.45 video_x11_window = window;
12.46 +
12.47 + if( !video_glx_create_window(width,height) ) {
12.48 + return FALSE;
12.49 + }
12.50 +
12.51 + if( gl_fbo_is_supported() ) {
12.52 + gl_fbo_init(driver);
12.53 + return TRUE;
12.54 + } else {
12.55 + /* Pbuffers? */
12.56 + ERROR( "Framebuffer objects not supported (required in this version)" );
12.57 + video_glx_shutdown();
12.58 + return FALSE;
12.59 + }
12.60 }
12.61
12.62 -
12.63 -gboolean video_glx_create_window( int x, int y, int width, int height )
12.64 +gboolean video_glx_create_window( int width, int height )
12.65 {
12.66 int major, minor;
12.67 const char *glxExts, *glxServer;
12.68 @@ -56,7 +72,6 @@
12.69 GLX_DOUBLEBUFFER,
12.70 None };
12.71 int screen = XScreenNumberOfScreen(video_x11_screen);
12.72 - XSetWindowAttributes win_attrs;
12.73 XVisualInfo *visual;
12.74
12.75 if( glXQueryVersion( video_x11_display, &major, &minor ) == False ) {
12.76 @@ -68,11 +83,6 @@
12.77 return FALSE;
12.78 }
12.79
12.80 - glxExts = glXQueryExtensionsString( video_x11_display, screen );
12.81 - glxServer = glXQueryServerString( video_x11_display, screen, GLX_VENDOR );
12.82 - INFO( "GLX version %d.%d, %s. Supported exts: %s", major, minor,
12.83 - glxServer, glxExts );
12.84 -
12.85 /* Find ourselves a nice visual */
12.86 visual = glXChooseVisual( video_x11_display,
12.87 screen,
12.88 @@ -100,7 +110,7 @@
12.89 RootWindowOfScreen(video_x11_screen),
12.90 visual->visual, AllocNone );
12.91 glx_window = XCreateWindow( video_x11_display, video_x11_window,
12.92 - x, y, width, height, 0, visual->depth,
12.93 + 0, 0, width, height, 0, visual->depth,
12.94 InputOutput, visual->visual,
12.95 CWColormap | CWEventMask,
12.96 &win_attrs );
12.97 @@ -123,11 +133,15 @@
12.98 glXDestroyContext( video_x11_display, glx_context );
12.99 return FALSE;
12.100 }
12.101 -
12.102 - hasRequiredGLExtensions();
12.103 - glx_open = TRUE;
12.104 return TRUE;
12.105 }
12.106 +void video_glx_shutdown()
12.107 +{
12.108 + XDestroyWindow( video_x11_display, glx_window );
12.109 + XFreeColormap( video_x11_display, win_attrs.colormap );
12.110 + glXDestroyContext( video_x11_display, glx_context );
12.111 +}
12.112 +
12.113
12.114 int video_glx_load_font( const gchar *font_name )
12.115 {
12.116 @@ -142,61 +156,8 @@
12.117 }
12.118
12.119
12.120 -
12.121 -gboolean video_glx_set_render_format( int x, int y, int width, int height )
12.122 -{
12.123 - if( glx_open )
12.124 - return TRUE;
12.125 - return video_glx_create_window( x, y, width, height );
12.126 -}
12.127 -
12.128 -gboolean video_glx_display_frame( video_buffer_t frame )
12.129 -{
12.130 - GLenum type = colour_formats[frame->colour_format].type;
12.131 - GLenum format = colour_formats[frame->colour_format].format;
12.132 - int bpp = colour_formats[frame->colour_format].bpp;
12.133 -
12.134 - glDrawBuffer( GL_FRONT );
12.135 - glViewport( 0, 0, video_width, video_height );
12.136 - glMatrixMode(GL_PROJECTION);
12.137 - glLoadIdentity();
12.138 - glOrtho( 0, frame->hres, frame->vres, 0, 0, -65535 );
12.139 - glMatrixMode(GL_MODELVIEW);
12.140 - glLoadIdentity();
12.141 - glRasterPos2i( 0, 0 );
12.142 - glPushClientAttrib( GL_CLIENT_PIXEL_STORE_BIT );
12.143 - float scale = 480.0 / frame->vres;
12.144 - glPixelZoom( 1.0f, -scale );
12.145 - int rowstride = (frame->rowstride / bpp) - frame->hres;
12.146 - glPixelStorei( GL_PACK_ROW_LENGTH, rowstride );
12.147 - glDrawPixels( frame->hres, frame->vres, format, type,
12.148 - frame->data );
12.149 - glPopClientAttrib();
12.150 - glFlush();
12.151 - return TRUE;
12.152 -}
12.153 -
12.154 -gboolean video_glx_blank( int width, int height, uint32_t colour )
12.155 -{
12.156 - glDrawBuffer( GL_FRONT );
12.157 - glViewport( 0, 0, width, height );
12.158 - glMatrixMode( GL_PROJECTION );
12.159 - glLoadIdentity();
12.160 - glOrtho( 0, width, height, 0, 0, -65535 );
12.161 - glMatrixMode(GL_MODELVIEW);
12.162 - glLoadIdentity();
12.163 - glColor3b( (colour >> 16) & 0xFF, (colour >> 8) & 0xFF, colour & 0xFF );
12.164 - glRecti(0,0, width, height );
12.165 - glFlush();
12.166 - return TRUE;
12.167 -}
12.168 -
12.169 void video_glx_swap_buffers( void )
12.170 {
12.171 glXSwapBuffers( video_x11_display, glx_window );
12.172 }
12.173
12.174 -void video_glx_create_pixmap( int width, int height )
12.175 -{
12.176 -
12.177 -}
13.1 --- a/src/drivers/video_x11.h Tue Feb 06 07:59:06 2007 +0000
13.2 +++ b/src/drivers/video_x11.h Sun Feb 11 10:09:32 2007 +0000
13.3 @@ -1,5 +1,5 @@
13.4 /**
13.5 - * $Id: video_x11.h,v 1.3 2006-05-15 08:28:52 nkeynes Exp $
13.6 + * $Id: video_x11.h,v 1.4 2007-02-11 10:09:32 nkeynes Exp $
13.7 *
13.8 * Parent for all X11 display drivers.
13.9 *
13.10 @@ -22,14 +22,7 @@
13.11 #include "X11/Xlib.h"
13.12 #include "display.h"
13.13
13.14 -void video_x11_set_display( Display *display, Screen *screen, Window window );
13.15 -
13.16 -extern Display *video_x11_display;
13.17 -extern Screen *video_x11_screen;
13.18 -extern Window video_x11_window;
13.19 -
13.20 -
13.21 -gboolean video_glx_set_render_format( int x, int y, int width, int height );
13.22 -void video_glx_swap_buffers();
13.23 +gboolean video_glx_init( Display *display, Screen *screen, Window window,
13.24 + int width, int height, display_driver_t driver );
13.25
13.26 #endif
14.1 --- a/src/pvr2/pvr2.c Tue Feb 06 07:59:06 2007 +0000
14.2 +++ b/src/pvr2/pvr2.c Sun Feb 11 10:09:32 2007 +0000
14.3 @@ -1,5 +1,5 @@
14.4 /**
14.5 - * $Id: pvr2.c,v 1.43 2007-01-28 11:36:00 nkeynes Exp $
14.6 + * $Id: pvr2.c,v 1.44 2007-02-11 10:09:32 nkeynes Exp $
14.7 *
14.8 * PVR2 (Video) Core module implementation and MMIO registers.
14.9 *
14.10 @@ -30,6 +30,8 @@
14.11
14.12 char *video_base;
14.13
14.14 +#define MAX_RENDER_BUFFERS 4
14.15 +
14.16 #define HPOS_PER_FRAME 0
14.17 #define HPOS_PER_LINECOUNT 1
14.18
14.19 @@ -40,11 +42,13 @@
14.20 static int pvr2_load_state( FILE *f );
14.21 static void pvr2_update_raster_posn( uint32_t nanosecs );
14.22 static void pvr2_schedule_scanline_event( int eventid, int line, int minimum_lines, int line_time_ns );
14.23 +static render_buffer_t pvr2_get_render_buffer( frame_buffer_t frame );
14.24 +static render_buffer_t pvr2_next_render_buffer( );
14.25 uint32_t pvr2_get_sync_status();
14.26
14.27 void pvr2_display_frame( void );
14.28
14.29 -int colour_format_bytes[] = { 2, 2, 2, 1, 3, 4, 1, 1 };
14.30 +static int output_colour_formats[] = { COLFMT_ARGB1555, COLFMT_RGB565, COLFMT_RGB888, COLFMT_ARGB8888 };
14.31
14.32 struct dreamcast_module pvr2_module = { "PVR2", pvr2_init, pvr2_reset, NULL,
14.33 pvr2_run_slice, NULL,
14.34 @@ -53,16 +57,6 @@
14.35
14.36 display_driver_t display_driver = NULL;
14.37
14.38 -struct video_timing {
14.39 - int fields_per_second;
14.40 - int total_lines;
14.41 - int retrace_lines;
14.42 - int line_time_ns;
14.43 -};
14.44 -
14.45 -struct video_timing pal_timing = { 50, 625, 65, 31945 };
14.46 -struct video_timing ntsc_timing= { 60, 525, 65, 31746 };
14.47 -
14.48 struct pvr2_state {
14.49 uint32_t frame_count;
14.50 uint32_t line_count;
14.51 @@ -89,11 +83,10 @@
14.52 uint32_t retrace_start_line;
14.53 uint32_t retrace_end_line;
14.54 gboolean interlaced;
14.55 - struct video_timing timing;
14.56 } pvr2_state;
14.57
14.58 -struct video_buffer video_buffer[2];
14.59 -int video_buffer_idx = 0;
14.60 +render_buffer_t render_buffers[MAX_RENDER_BUFFERS];
14.61 +int render_buffer_count = 0;
14.62
14.63 /**
14.64 * Event handler for the hpos callback
14.65 @@ -127,6 +120,7 @@
14.66
14.67 static void pvr2_init( void )
14.68 {
14.69 + int i;
14.70 register_io_region( &mmio_region_PVR2 );
14.71 register_io_region( &mmio_region_PVR2PAL );
14.72 register_io_region( &mmio_region_PVR2TA );
14.73 @@ -138,6 +132,10 @@
14.74 pvr2_reset();
14.75 pvr2_ta_reset();
14.76 pvr2_state.save_next_render_filename = NULL;
14.77 + for( i=0; i<MAX_RENDER_BUFFERS; i++ ) {
14.78 + render_buffers[i] = NULL;
14.79 + }
14.80 + render_buffer_count = 0;
14.81 }
14.82
14.83 static void pvr2_reset( void )
14.84 @@ -147,7 +145,6 @@
14.85 pvr2_state.cycles_run = 0;
14.86 pvr2_state.irq_vpos1 = 0;
14.87 pvr2_state.irq_vpos2 = 0;
14.88 - pvr2_state.timing = ntsc_timing;
14.89 pvr2_state.dot_clock = PVR2_DOT_CLOCK;
14.90 pvr2_state.back_porch_ns = 4000;
14.91 pvr2_state.palette_changed = FALSE;
14.92 @@ -155,10 +152,8 @@
14.93 mmio_region_PVR2_write( DISP_SYNCTIME, 0x07D6A53F );
14.94 mmio_region_PVR2_write( YUV_ADDR, 0 );
14.95 mmio_region_PVR2_write( YUV_CFG, 0 );
14.96 - video_buffer_idx = 0;
14.97
14.98 pvr2_ta_init();
14.99 - pvr2_render_init();
14.100 texcache_flush();
14.101 }
14.102
14.103 @@ -241,82 +236,64 @@
14.104 */
14.105 void pvr2_display_frame( void )
14.106 {
14.107 - uint32_t display_addr;
14.108 - int dispsize = MMIO_READ( PVR2, DISP_SIZE );
14.109 int dispmode = MMIO_READ( PVR2, DISP_MODE );
14.110 int vidcfg = MMIO_READ( PVR2, DISP_SYNCCFG );
14.111 - int vid_stride = (((dispsize & DISPSIZE_MODULO) >> 20) - 1);
14.112 - int vid_lpf = ((dispsize & DISPSIZE_LPF) >> 10) + 1;
14.113 - int vid_ppl = ((dispsize & DISPSIZE_PPL)) + 1;
14.114 gboolean bEnabled = (dispmode & DISPMODE_ENABLE) && (vidcfg & DISPCFG_VO ) ? TRUE : FALSE;
14.115 - gboolean interlaced = (vidcfg & DISPCFG_I ? TRUE : FALSE);
14.116 - video_buffer_t buffer = &video_buffer[video_buffer_idx];
14.117 - video_buffer_idx = !video_buffer_idx;
14.118 - video_buffer_t last = &video_buffer[video_buffer_idx];
14.119 - buffer->rowstride = (vid_ppl + vid_stride) << 2;
14.120 - buffer->data = video_base + MMIO_READ( PVR2, DISP_ADDR1 );
14.121 - buffer->line_double = (dispmode & DISPMODE_LINEDOUBLE) ? TRUE : FALSE;
14.122 - buffer->vres = vid_lpf;
14.123 - if( interlaced ) {
14.124 - if( vid_ppl == vid_stride ) { /* Magic deinterlace */
14.125 - buffer->vres <<= 1;
14.126 - buffer->rowstride = vid_ppl << 2;
14.127 - display_addr = MMIO_READ( PVR2, DISP_ADDR1 );
14.128 - } else {
14.129 - /* Just display the field as is, folks. This is slightly tricky -
14.130 - * we pick the field based on which frame is about to come through,
14.131 - * which may not be the same as the odd_even_field.
14.132 - */
14.133 - gboolean oddfield = pvr2_state.odd_even_field;
14.134 - if( pvr2_state.line_count >= pvr2_state.retrace_start_line ) {
14.135 - oddfield = !oddfield;
14.136 +
14.137 + if( display_driver == NULL ) {
14.138 + return; /* can't really do anything much */
14.139 + } else if( !bEnabled ) {
14.140 + /* Output disabled == black */
14.141 + display_driver->display_blank( 0 );
14.142 + } else if( MMIO_READ( PVR2, DISP_CFG2 ) & 0x08 ) {
14.143 + /* Enabled but blanked - border colour */
14.144 + uint32_t colour = MMIO_READ( PVR2, DISP_BORDER );
14.145 + display_driver->display_blank( colour );
14.146 + } else {
14.147 + /* Real output - determine dimensions etc */
14.148 + struct frame_buffer fbuf;
14.149 + uint32_t dispsize = MMIO_READ( PVR2, DISP_SIZE );
14.150 + int vid_stride = (((dispsize & DISPSIZE_MODULO) >> 20) - 1);
14.151 + int vid_ppl = ((dispsize & DISPSIZE_PPL)) + 1;
14.152 +
14.153 + fbuf.colour_format = output_colour_formats[(dispmode & DISPMODE_COLFMT) >> 2];
14.154 + fbuf.width = vid_ppl << 2 / colour_formats[fbuf.colour_format].bpp;
14.155 + fbuf.height = ((dispsize & DISPSIZE_LPF) >> 10) + 1;
14.156 + fbuf.size = vid_ppl << 2 * fbuf.height;
14.157 + fbuf.rowstride = (vid_ppl + vid_stride) << 2;
14.158 +
14.159 + /* Determine the field to display, and deinterlace if possible */
14.160 + if( pvr2_state.interlaced ) {
14.161 + if( vid_ppl == vid_stride ) { /* Magic deinterlace */
14.162 + fbuf.height = fbuf.height << 1;
14.163 + fbuf.rowstride = vid_ppl << 2;
14.164 + fbuf.address = MMIO_READ( PVR2, DISP_ADDR1 );
14.165 + } else {
14.166 + /* Just display the field as is, folks. This is slightly tricky -
14.167 + * we pick the field based on which frame is about to come through,
14.168 + * which may not be the same as the odd_even_field.
14.169 + */
14.170 + gboolean oddfield = pvr2_state.odd_even_field;
14.171 + if( pvr2_state.line_count >= pvr2_state.retrace_start_line ) {
14.172 + oddfield = !oddfield;
14.173 + }
14.174 + if( oddfield ) {
14.175 + fbuf.address = MMIO_READ( PVR2, DISP_ADDR1 );
14.176 + } else {
14.177 + fbuf.address = MMIO_READ( PVR2, DISP_ADDR2 );
14.178 + }
14.179 }
14.180 - if( oddfield ) {
14.181 - display_addr = MMIO_READ( PVR2, DISP_ADDR1 );
14.182 - } else {
14.183 - display_addr = MMIO_READ( PVR2, DISP_ADDR2 );
14.184 - }
14.185 + } else {
14.186 + fbuf.address = MMIO_READ( PVR2, DISP_ADDR1 );
14.187 }
14.188 - } else {
14.189 - display_addr = MMIO_READ( PVR2, DISP_ADDR1 );
14.190 - }
14.191 - switch( (dispmode & DISPMODE_COLFMT) >> 2 ) {
14.192 - case 0:
14.193 - buffer->colour_format = COLFMT_ARGB1555;
14.194 - buffer->hres = vid_ppl << 1;
14.195 - break;
14.196 - case 1:
14.197 - buffer->colour_format = COLFMT_RGB565;
14.198 - buffer->hres = vid_ppl << 1;
14.199 - break;
14.200 - case 2:
14.201 - buffer->colour_format = COLFMT_RGB888;
14.202 - buffer->hres = (vid_ppl << 2) / 3;
14.203 - break;
14.204 - case 3:
14.205 - buffer->colour_format = COLFMT_ARGB8888;
14.206 - buffer->hres = vid_ppl;
14.207 - break;
14.208 - }
14.209 -
14.210 - if( buffer->hres <=8 )
14.211 - buffer->hres = 640;
14.212 - if( buffer->vres <=8 )
14.213 - buffer->vres = 480;
14.214 - if( display_driver != NULL ) {
14.215 - if( buffer->hres != last->hres ||
14.216 - buffer->vres != last->vres ||
14.217 - buffer->colour_format != last->colour_format) {
14.218 - display_driver->set_display_format( buffer->hres, buffer->vres,
14.219 - buffer->colour_format );
14.220 - }
14.221 - if( !bEnabled ) {
14.222 - display_driver->display_blank_frame( 0 );
14.223 - } else if( MMIO_READ( PVR2, DISP_CFG2 ) & 0x08 ) { /* Blanked */
14.224 - uint32_t colour = MMIO_READ( PVR2, DISP_BORDER );
14.225 - display_driver->display_blank_frame( colour );
14.226 - } else if( !pvr2_render_display_frame( PVR2_RAM_BASE + display_addr ) ) {
14.227 - display_driver->display_frame( buffer );
14.228 + fbuf.address = (fbuf.address & 0x00FFFFFF) + PVR2_RAM_BASE;
14.229 +
14.230 + render_buffer_t rbuf = pvr2_get_render_buffer( &fbuf );
14.231 + if( rbuf != NULL ) {
14.232 + display_driver->display_render_buffer( rbuf );
14.233 + } else {
14.234 + fbuf.data = video_base + (fbuf.address&0x00FFFFFF);
14.235 + display_driver->display_frame_buffer( &fbuf );
14.236 }
14.237 }
14.238 }
14.239 @@ -349,7 +326,9 @@
14.240 g_free( pvr2_state.save_next_render_filename );
14.241 pvr2_state.save_next_render_filename = NULL;
14.242 }
14.243 - pvr2_render_scene();
14.244 + render_buffer_t buffer = pvr2_next_render_buffer();
14.245 + pvr2_render_scene( buffer );
14.246 + asic_event( EVENT_PVR_RENDER_DONE );
14.247 break;
14.248 case RENDER_POLYBASE:
14.249 MMIO_WRITE( PVR2, reg, val&0x00F00000 );
14.250 @@ -372,23 +351,11 @@
14.251 case DISP_ADDR1:
14.252 val &= 0x00FFFFFC;
14.253 MMIO_WRITE( PVR2, reg, val );
14.254 - /*
14.255 pvr2_update_raster_posn(sh4r.slice_cycle);
14.256 - fprintf( stderr, "Set Field 1 addr: %08X\n", val );
14.257 - if( (pvr2_state.line_count >= pvr2_state.retrace_start_line && !pvr2_state.odd_even_field) ||
14.258 - (pvr2_state.line_count < pvr2_state.retrace_end_line && pvr2_state.odd_even_field) ) {
14.259 - pvr2_display_frame();
14.260 - }
14.261 - */
14.262 break;
14.263 case DISP_ADDR2:
14.264 MMIO_WRITE( PVR2, reg, val&0x00FFFFFC );
14.265 pvr2_update_raster_posn(sh4r.slice_cycle);
14.266 - /*
14.267 - if( (pvr2_state.line_count >= pvr2_state.retrace_start_line && pvr2_state.odd_even_field) ||
14.268 - (pvr2_state.line_count < pvr2_state.retrace_end_line && !pvr2_state.odd_even_field) ) {
14.269 - pvr2_display_frame();
14.270 - }*/
14.271 break;
14.272 case DISP_SIZE:
14.273 MMIO_WRITE( PVR2, reg, val&0x3FFFFFFF );
14.274 @@ -722,3 +689,139 @@
14.275 pvr2_ta_write( (char *)&val, sizeof(uint32_t) );
14.276 }
14.277
14.278 +/**
14.279 + * Find the render buffer corresponding to the requested output frame
14.280 + * (does not consider texture renders).
14.281 + * @return the render_buffer if found, or null if no such buffer.
14.282 + *
14.283 + * Note: Currently does not consider "partial matches", ie partial
14.284 + * frame overlap - it probably needs to do this.
14.285 + */
14.286 +render_buffer_t pvr2_get_render_buffer( frame_buffer_t frame )
14.287 +{
14.288 + int i;
14.289 + for( i=0; i<render_buffer_count; i++ ) {
14.290 + if( render_buffers[i] != NULL && render_buffers[i]->address == frame->address ) {
14.291 + return render_buffers[i];
14.292 + }
14.293 + }
14.294 + return NULL;
14.295 +}
14.296 +
14.297 +/**
14.298 + * Determine the next render buffer to write into. The order of preference is:
14.299 + * 1. An existing buffer with the same address. (not flushed unless the new
14.300 + * size is smaller than the old one).
14.301 + * 2. An existing buffer with the same size chosen by LRU order. Old buffer
14.302 + * is flushed to vram.
14.303 + * 3. A new buffer if one can be created.
14.304 + * 4. The current display buff
14.305 + * Note: The current display field(s) will never be overwritten except as a last
14.306 + * resort.
14.307 + */
14.308 +render_buffer_t pvr2_next_render_buffer()
14.309 +{
14.310 + render_buffer_t result = NULL;
14.311 + uint32_t render_addr = MMIO_READ( PVR2, RENDER_ADDR1 );
14.312 + uint32_t render_mode = MMIO_READ( PVR2, RENDER_MODE );
14.313 + uint32_t render_scale = MMIO_READ( PVR2, RENDER_SCALER );
14.314 + uint32_t render_stride = MMIO_READ( PVR2, RENDER_SIZE ) << 3;
14.315 + gboolean render_to_tex;
14.316 + if( render_addr & 0x01000000 ) { /* vram64 */
14.317 + render_addr = (render_addr & 0x00FFFFFF) + PVR2_RAM_BASE_INT;
14.318 + } else { /* vram32 */
14.319 + render_addr = (render_addr & 0x00FFFFFF) + PVR2_RAM_BASE;
14.320 + }
14.321 +
14.322 + int width, height, i;
14.323 + int colour_format = pvr2_render_colour_format[render_mode&0x07];
14.324 + pvr2_render_getsize( &width, &height );
14.325 +
14.326 + /* Check existing buffers for an available buffer */
14.327 + for( i=0; i<render_buffer_count; i++ ) {
14.328 + if( render_buffers[i]->width == width && render_buffers[i]->height == height ) {
14.329 + /* needs to be the right dimensions */
14.330 + if( render_buffers[i]->address == render_addr ) {
14.331 + /* perfect */
14.332 + result = render_buffers[i];
14.333 + break;
14.334 + } else if( render_buffers[i]->address == -1 && result == NULL ) {
14.335 + result = render_buffers[i];
14.336 + }
14.337 + } else if( render_buffers[i]->address == render_addr ) {
14.338 + /* right address, wrong size - if it's larger, flush it, otherwise
14.339 + * nuke it quietly */
14.340 + if( render_buffers[i]->width * render_buffers[i]->height >
14.341 + width*height ) {
14.342 + pvr2_render_buffer_copy_to_sh4( render_buffers[i] );
14.343 + }
14.344 + render_buffers[i]->address == -1;
14.345 + }
14.346 + }
14.347 +
14.348 + /* Nothing available - make one */
14.349 + if( result == NULL ) {
14.350 + if( render_buffer_count == MAX_RENDER_BUFFERS ) {
14.351 + /* maximum buffers reached - need to throw one away */
14.352 + uint32_t field1_addr = MMIO_READ( PVR2, DISP_ADDR1 );
14.353 + uint32_t field2_addr = MMIO_READ( PVR2, DISP_ADDR2 );
14.354 + for( i=0; i<render_buffer_count; i++ ) {
14.355 + if( render_buffers[i]->address != field1_addr &&
14.356 + render_buffers[i]->address != field2_addr ) {
14.357 + /* Never throw away the current "front buffer(s)" */
14.358 + result = render_buffers[i];
14.359 + pvr2_render_buffer_copy_to_sh4( result );
14.360 + if( result->width != width || result->height != height ) {
14.361 + display_driver->destroy_render_buffer(render_buffers[i]);
14.362 + result = display_driver->create_render_buffer(width,height);
14.363 + render_buffers[i] = result;
14.364 + }
14.365 + break;
14.366 + }
14.367 + }
14.368 + } else {
14.369 + result = display_driver->create_render_buffer(width,height);
14.370 + if( result != NULL ) {
14.371 + render_buffers[render_buffer_count++] = result;
14.372 + } else {
14.373 + ERROR( "Failed to obtain a render buffer!" );
14.374 + return NULL;
14.375 + }
14.376 + }
14.377 + }
14.378 +
14.379 + /* Setup the buffer */
14.380 + result->rowstride = render_stride;
14.381 + result->colour_format = colour_format;
14.382 + result->scale = render_scale;
14.383 + result->size = width * height * colour_formats[colour_format].bpp;
14.384 + result->address = render_addr;
14.385 + result->flushed = FALSE;
14.386 + return result;
14.387 +}
14.388 +
14.389 +/**
14.390 + * Invalidate any caching on the supplied address. Specifically, if it falls
14.391 + * within any of the render buffers, flush the buffer back to PVR2 ram.
14.392 + */
14.393 +gboolean pvr2_render_buffer_invalidate( sh4addr_t address, gboolean isWrite )
14.394 +{
14.395 + int i;
14.396 + address = address & 0x1FFFFFFF;
14.397 + for( i=0; i<render_buffer_count; i++ ) {
14.398 + uint32_t bufaddr = render_buffers[i]->address;
14.399 + uint32_t size = render_buffers[i]->size;
14.400 + if( bufaddr != -1 && bufaddr <= address &&
14.401 + (bufaddr + render_buffers[i]->size) > address ) {
14.402 + if( !render_buffers[i]->flushed ) {
14.403 + pvr2_render_buffer_copy_to_sh4( render_buffers[i] );
14.404 + render_buffers[i]->flushed = TRUE;
14.405 + }
14.406 + if( isWrite ) {
14.407 + render_buffers[i]->address = -1; /* Invalid */
14.408 + }
14.409 + return TRUE; /* should never have overlapping buffers */
14.410 + }
14.411 + }
14.412 + return FALSE;
14.413 +}
15.1 --- a/src/pvr2/pvr2.h Tue Feb 06 07:59:06 2007 +0000
15.2 +++ b/src/pvr2/pvr2.h Sun Feb 11 10:09:32 2007 +0000
15.3 @@ -1,5 +1,5 @@
15.4 /**
15.5 - * $Id: pvr2.h,v 1.34 2007-02-05 08:51:34 nkeynes Exp $
15.6 + * $Id: pvr2.h,v 1.35 2007-02-11 10:09:32 nkeynes Exp $
15.7 *
15.8 * PVR2 (video chip) functions and macros.
15.9 *
15.10 @@ -175,19 +175,6 @@
15.11 */
15.12 void pvr2_vram64_dump( sh4addr_t addr, uint32_t length, FILE *f );
15.13
15.14 -
15.15 -/**
15.16 - * Describes a rendering buffer that's actually held in GL, for when we need
15.17 - * to fetch the bits back to vram.
15.18 - */
15.19 -typedef struct pvr2_render_buffer {
15.20 - sh4addr_t render_addr; /* The actual address rendered to in pvr ram */
15.21 - uint32_t size; /* Length of rendering region in bytes */
15.22 - int width, height;
15.23 - int colour_format;
15.24 - int scale;
15.25 -} *pvr2_render_buffer_t;
15.26 -
15.27 /**
15.28 * Flush the indicated render buffer back to PVR. Caller is responsible for
15.29 * tracking whether there is actually anything in the buffer.
15.30 @@ -197,25 +184,12 @@
15.31 * @param backBuffer TRUE to flush the back buffer, FALSE for
15.32 * the front buffer.
15.33 */
15.34 -void pvr2_render_buffer_copy_to_sh4( pvr2_render_buffer_t buffer,
15.35 - gboolean backBuffer );
15.36 -
15.37 -/**
15.38 - * Copy data from PVR ram into the GL render buffer.
15.39 - *
15.40 - * @param buffer A render buffer indicating the address to read from, and the
15.41 - * format the data is in.
15.42 - * @param backBuffer TRUE to write the back buffer, FALSE for
15.43 - * the front buffer.
15.44 - */
15.45 -void pvr2_render_buffer_copy_from_sh4( pvr2_render_buffer_t buffer,
15.46 - gboolean backBuffer );
15.47 -
15.48 +void pvr2_render_buffer_copy_to_sh4( render_buffer_t buffer );
15.49
15.50 /**
15.51 * Invalidate any caching on the supplied SH4 address
15.52 */
15.53 -gboolean pvr2_render_buffer_invalidate( sh4addr_t addr );
15.54 +gboolean pvr2_render_buffer_invalidate( sh4addr_t addr, gboolean isWrite );
15.55
15.56
15.57 /**************************** Tile Accelerator ***************************/
15.58 @@ -250,15 +224,9 @@
15.59 /********************************* Renderer ******************************/
15.60
15.61 /**
15.62 - * Initialize the rendering pipeline.
15.63 - * @return TRUE on success, FALSE on failure.
15.64 - */
15.65 -gboolean pvr2_render_init( void );
15.66 -
15.67 -/**
15.68 * Render the current scene stored in PVR ram to the GL back buffer.
15.69 */
15.70 -void pvr2_render_scene( void );
15.71 +void pvr2_render_scene( render_buffer_t buffer );
15.72
15.73 /**
15.74 * Display the scene rendered to the supplied address.
16.1 --- a/src/pvr2/pvr2mem.c Tue Feb 06 07:59:06 2007 +0000
16.2 +++ b/src/pvr2/pvr2mem.c Sun Feb 11 10:09:32 2007 +0000
16.3 @@ -1,5 +1,5 @@
16.4 /**
16.5 - * $Id: pvr2mem.c,v 1.8 2007-01-27 06:21:35 nkeynes Exp $
16.6 + * $Id: pvr2mem.c,v 1.9 2007-02-11 10:09:32 nkeynes Exp $
16.7 *
16.8 * PVR2 (Video) VRAM handling routines (mainly for the 64-bit region)
16.9 *
16.10 @@ -484,7 +484,7 @@
16.11 ERROR( "Unable to write to dump file '%s' (%s)", filename, strerror(errno) );
16.12 return;
16.13 }
16.14 - pvr2_vram64_read( tmp, addr, length );
16.15 + pvr2_vram64_read( (char *)tmp, addr, length );
16.16 fprintf( f, "%08X\n", addr );
16.17 for( i =0; i<length>>2; i+=8 ) {
16.18 for( j=i; j<i+8; j++ ) {
16.19 @@ -516,77 +516,23 @@
16.20 * @param backBuffer TRUE to flush the back buffer, FALSE for
16.21 * the front buffer.
16.22 */
16.23 -void pvr2_render_buffer_copy_to_sh4( pvr2_render_buffer_t buffer,
16.24 - gboolean backBuffer )
16.25 +void pvr2_render_buffer_copy_to_sh4( render_buffer_t buffer )
16.26 {
16.27 - if( buffer->render_addr == -1 )
16.28 - return;
16.29 - GLenum type = colour_formats[buffer->colour_format].type;
16.30 - GLenum format = colour_formats[buffer->colour_format].format;
16.31 - int line_size = buffer->width * colour_formats[buffer->colour_format].bpp;
16.32 - int size = line_size * buffer->height;
16.33 -
16.34 - if( backBuffer ) {
16.35 - glFinish();
16.36 - glReadBuffer( GL_BACK );
16.37 - } else {
16.38 - glReadBuffer( GL_FRONT );
16.39 - }
16.40 -
16.41 - if( buffer->render_addr & 0xFF000000 == 0x04000000 ) {
16.42 + if( buffer->address & 0xFF000000 == 0x04000000 ) {
16.43 /* Interlaced buffer. Go the double copy... :( */
16.44 - char target[size];
16.45 - glReadPixels( 0, 0, buffer->width, buffer->height, format, type, target );
16.46 - pvr2_vram64_write( buffer->render_addr, target, size );
16.47 + char target[buffer->size];
16.48 + display_driver->read_render_buffer( buffer, target );
16.49 + pvr2_vram64_write( buffer->address, target, buffer->size );
16.50 } else {
16.51 /* Regular buffer */
16.52 - char target[size];
16.53 - glReadPixels( 0, 0, buffer->width, buffer->height, format, type, target );
16.54 - if( (buffer->scale & 0xFFFF) == 0x0800 ) {
16.55 - pvr2_vram_write_invert( buffer->render_addr, target, size, line_size, line_size << 1 );
16.56 - } else {
16.57 - pvr2_vram_write_invert( buffer->render_addr, target, size, line_size, line_size );
16.58 - }
16.59 + char target[buffer->size];
16.60 + int line_size = buffer->width * colour_formats[buffer->colour_format].bpp;
16.61 + display_driver->read_render_buffer( buffer, target );
16.62 + if( (buffer->scale & 0xFFFF) == 0x0800 ) {
16.63 + pvr2_vram_write_invert( buffer->address, target, buffer->size, line_size, line_size << 1 );
16.64 + } else {
16.65 + pvr2_vram_write_invert( buffer->address, target, buffer->size, line_size, line_size );
16.66 + }
16.67 }
16.68 }
16.69
16.70 -
16.71 -/**
16.72 - * Copy data from PVR ram into the GL render buffer.
16.73 - *
16.74 - * @param buffer A render buffer indicating the address to read from, and the
16.75 - * format the data is in.
16.76 - * @param backBuffer TRUE to write the back buffer, FALSE for
16.77 - * the front buffer.
16.78 - */
16.79 -void pvr2_render_buffer_copy_from_sh4( pvr2_render_buffer_t buffer,
16.80 - gboolean backBuffer )
16.81 -{
16.82 - if( buffer->render_addr == -1 )
16.83 - return;
16.84 -
16.85 - GLenum type = colour_formats[buffer->colour_format].type;
16.86 - GLenum format = colour_formats[buffer->colour_format].format;
16.87 - int line_size = buffer->width * colour_formats[buffer->colour_format].bpp;
16.88 - int size = line_size * buffer->height;
16.89 -
16.90 - if( backBuffer ) {
16.91 - glDrawBuffer( GL_BACK );
16.92 - } else {
16.93 - glDrawBuffer( GL_FRONT );
16.94 - }
16.95 -
16.96 - glRasterPos2i( 0, 0 );
16.97 - if( buffer->render_addr & 0xFF000000 == 0x04000000 ) {
16.98 - /* Interlaced buffer. Go the double copy... :( */
16.99 - char target[size];
16.100 - pvr2_vram64_read( target, buffer->render_addr, size );
16.101 - glDrawPixels( buffer->width, buffer->height,
16.102 - format, type, target );
16.103 - } else {
16.104 - /* Regular buffer - go direct */
16.105 - char *target = mem_get_region( buffer->render_addr );
16.106 - glDrawPixels( buffer->width, buffer->height,
16.107 - format, type, target );
16.108 - }
16.109 -}
17.1 --- a/src/pvr2/rendcore.c Tue Feb 06 07:59:06 2007 +0000
17.2 +++ b/src/pvr2/rendcore.c Sun Feb 11 10:09:32 2007 +0000
17.3 @@ -1,5 +1,5 @@
17.4 /**
17.5 - * $Id: rendcore.c,v 1.18 2007-02-06 07:59:06 nkeynes Exp $
17.6 + * $Id: rendcore.c,v 1.19 2007-02-11 10:09:32 nkeynes Exp $
17.7 *
17.8 * PVR2 renderer core.
17.9 *
17.10 @@ -159,7 +159,7 @@
17.11 glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );
17.12 break;
17.13 }
17.14 - glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, POLY2_TEX_BLEND(poly2) );
17.15 +
17.16 if( POLY2_TEX_CLAMP_U(poly2) ) {
17.17 glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP );
17.18 } else {
18.1 --- a/src/pvr2/render.c Tue Feb 06 07:59:06 2007 +0000
18.2 +++ b/src/pvr2/render.c Sun Feb 11 10:09:32 2007 +0000
18.3 @@ -1,5 +1,5 @@
18.4 /**
18.5 - * $Id: render.c,v 1.23 2007-01-29 11:24:44 nkeynes Exp $
18.6 + * $Id: render.c,v 1.24 2007-02-11 10:09:32 nkeynes Exp $
18.7 *
18.8 * PVR2 Renderer support. This part is primarily
18.9 *
18.10 @@ -20,20 +20,6 @@
18.11 #include "asic.h"
18.12
18.13
18.14 -struct pvr2_render_buffer front_buffer;
18.15 -struct pvr2_render_buffer back_buffer;
18.16 -
18.17 -typedef struct pvr2_bgplane_packed {
18.18 - uint32_t poly_cfg, poly_mode;
18.19 - uint32_t texture_mode;
18.20 - float x1, y1, z1;
18.21 - uint32_t colour1;
18.22 - float x2, y2, z2;
18.23 - uint32_t colour2;
18.24 - float x3, y3, z3;
18.25 - uint32_t colour3;
18.26 -} *pvr2_bgplane_packed_t;
18.27 -
18.28 int pvr2_render_font_list = -1;
18.29 int pvr2_render_trace = 0;
18.30
18.31 @@ -85,111 +71,27 @@
18.32
18.33 }
18.34
18.35 -
18.36 -gboolean pvr2_render_init( void )
18.37 -{
18.38 - front_buffer.render_addr = -1;
18.39 - back_buffer.render_addr = -1;
18.40 -}
18.41 -
18.42 -/**
18.43 - * Invalidate any caching on the supplied address. Specifically, if it falls
18.44 - * within either the front buffer or back buffer, flush the buffer back to
18.45 - * PVR2 ram (note that front buffer flush may be corrupt under some
18.46 - * circumstances).
18.47 - */
18.48 -gboolean pvr2_render_buffer_invalidate( sh4addr_t address )
18.49 -{
18.50 - address = address & 0x1FFFFFFF;
18.51 - if( front_buffer.render_addr != -1 &&
18.52 - front_buffer.render_addr <= address &&
18.53 - (front_buffer.render_addr + front_buffer.size) > address ) {
18.54 - pvr2_render_buffer_copy_to_sh4( &front_buffer, FALSE );
18.55 - front_buffer.render_addr = -1;
18.56 - return TRUE;
18.57 - } else if( back_buffer.render_addr != -1 &&
18.58 - back_buffer.render_addr <= address &&
18.59 - (back_buffer.render_addr + back_buffer.size) > address ) {
18.60 - pvr2_render_buffer_copy_to_sh4( &back_buffer, TRUE );
18.61 - back_buffer.render_addr = -1;
18.62 - return TRUE;
18.63 - }
18.64 - return FALSE;
18.65 -}
18.66 -
18.67 -/**
18.68 - * Display a rendered frame if one is available.
18.69 - * @param address An address in PVR ram (0500000 range).
18.70 - * @return TRUE if a frame was available to be displayed, otherwise false.
18.71 - */
18.72 -gboolean pvr2_render_display_frame( uint32_t address )
18.73 -{
18.74 - if( front_buffer.render_addr == address ) {
18.75 - /* Current front buffer is already displayed, so do nothing
18.76 - * and tell the caller that all is well.
18.77 - */
18.78 - return TRUE;
18.79 - }
18.80 - if( back_buffer.render_addr == address ) {
18.81 - /* The more useful case - back buffer is to be displayed. Swap
18.82 - * the buffers
18.83 - */
18.84 - display_driver->display_back_buffer();
18.85 - front_buffer = back_buffer;
18.86 - back_buffer.render_addr = -1;
18.87 - return TRUE;
18.88 - }
18.89 - return FALSE;
18.90 -}
18.91 -
18.92 /**
18.93 * Prepare the OpenGL context to receive instructions for a new frame.
18.94 */
18.95 -static void pvr2_render_prepare_context( sh4addr_t render_addr,
18.96 - uint32_t width, uint32_t height,
18.97 - uint32_t colour_format,
18.98 - float bgplanez, float nearz,
18.99 - gboolean texture_target )
18.100 +static void pvr2_render_prepare_context( render_buffer_t buffer,
18.101 + float bgplanez, float nearz )
18.102 {
18.103 /* Select and initialize the render context */
18.104 - display_driver->set_render_format( width, height, colour_format, texture_target );
18.105 + display_driver->set_render_target(buffer);
18.106
18.107 if( pvr2_render_font_list == -1 ) {
18.108 pvr2_render_font_list = video_glx_load_font( "-*-helvetica-*-r-normal--16-*-*-*-p-*-iso8859-1");
18.109 }
18.110
18.111 - if( back_buffer.render_addr != -1 &&
18.112 - back_buffer.render_addr != render_addr ) {
18.113 - /* There's a current back buffer, and we're rendering somewhere else -
18.114 - * flush the back buffer back to vram and start a new back buffer
18.115 - */
18.116 - pvr2_render_buffer_copy_to_sh4( &back_buffer, TRUE );
18.117 - }
18.118 -
18.119 - if( front_buffer.render_addr == render_addr ) {
18.120 - /* In case we've been asked to render to the current front buffer -
18.121 - * invalidate the front buffer and render to the back buffer, ensuring
18.122 - * we swap at the next frame display.
18.123 - */
18.124 - front_buffer.render_addr = -1;
18.125 - }
18.126 - back_buffer.render_addr = render_addr;
18.127 - back_buffer.width = width;
18.128 - back_buffer.height = height;
18.129 - back_buffer.colour_format = colour_format;
18.130 - back_buffer.scale = MMIO_READ( PVR2, RENDER_SCALER );
18.131 - back_buffer.size = width * height * colour_format_bytes[colour_format];
18.132 -
18.133 pvr2_check_palette_changed();
18.134
18.135 /* Setup the display model */
18.136 - glDrawBuffer(GL_BACK);
18.137 glShadeModel(GL_SMOOTH);
18.138 glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
18.139 - glViewport( 0, 0, width, height );
18.140 glMatrixMode(GL_PROJECTION);
18.141 glLoadIdentity();
18.142 - glOrtho( 0, width, height, 0, -bgplanez, -nearz );
18.143 + glOrtho( 0, buffer->width, buffer->height, 0, -bgplanez, -nearz );
18.144 glMatrixMode(GL_MODELVIEW);
18.145 glLoadIdentity();
18.146 glCullFace( GL_BACK );
18.147 @@ -200,7 +102,6 @@
18.148 glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
18.149 glClearDepth(0);
18.150 glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
18.151 -
18.152 }
18.153
18.154 /**
18.155 @@ -208,58 +109,32 @@
18.156 * Note: this will probably need to be broken up eventually once timings are
18.157 * determined.
18.158 */
18.159 -void pvr2_render_scene( )
18.160 +void pvr2_render_scene( render_buffer_t buffer )
18.161 {
18.162 struct tile_descriptor *tile_desc =
18.163 (struct tile_descriptor *)mem_get_region(PVR2_RAM_BASE + MMIO_READ( PVR2, RENDER_TILEBASE ));
18.164
18.165 - uint32_t render_addr = MMIO_READ( PVR2, RENDER_ADDR1 );
18.166 - gboolean render_to_tex;
18.167 - if( render_addr & 0x01000000 ) {
18.168 - render_addr = (render_addr & 0x00FFFFFF) + PVR2_RAM_BASE_INT;
18.169 - /* Heuristic - if we're rendering to the interlaced region we're
18.170 - * probably creating a texture rather than rendering actual output.
18.171 - * We can optimise for this case a little
18.172 - */
18.173 - render_to_tex = TRUE;
18.174 - WARN( "Render to texture not supported properly yet" );
18.175 - } else {
18.176 - render_addr = (render_addr & 0x00FFFFFF) + PVR2_RAM_BASE;
18.177 - render_to_tex = FALSE;
18.178 - }
18.179 -
18.180 float bgplanez = 1/MMIO_READF( PVR2, RENDER_FARCLIP );
18.181 - uint32_t render_mode = MMIO_READ( PVR2, RENDER_MODE );
18.182 - int width, height;
18.183 - pvr2_render_getsize( &width, &height );
18.184 - int colour_format = pvr2_render_colour_format[render_mode&0x07];
18.185 - pvr2_render_prepare_context( render_addr, width, height, colour_format,
18.186 - bgplanez, 0, render_to_tex );
18.187 + pvr2_render_prepare_context( buffer, bgplanez, 0 );
18.188
18.189 int clip_x = MMIO_READ( PVR2, RENDER_HCLIP ) & 0x03FF;
18.190 int clip_y = MMIO_READ( PVR2, RENDER_VCLIP ) & 0x03FF;
18.191 int clip_width = ((MMIO_READ( PVR2, RENDER_HCLIP ) >> 16) & 0x03FF) - clip_x + 1;
18.192 int clip_height= ((MMIO_READ( PVR2, RENDER_VCLIP ) >> 16) & 0x03FF) - clip_y + 1;
18.193
18.194 - /* Fog setup goes here */
18.195 + /* Fog setup goes here? */
18.196
18.197 /* Render the background plane */
18.198 +
18.199 uint32_t bgplane_mode = MMIO_READ(PVR2, RENDER_BGPLANE);
18.200 uint32_t *display_list =
18.201 (uint32_t *)mem_get_region(PVR2_RAM_BASE + MMIO_READ( PVR2, RENDER_POLYBASE ));
18.202
18.203 uint32_t *bgplane = display_list + (((bgplane_mode & 0x00FFFFFF)) >> 3) ;
18.204 - render_backplane( bgplane, width, height, bgplane_mode );
18.205 -
18.206 - pvr2_render_tilebuffer( width, height, clip_x, clip_y,
18.207 + render_backplane( bgplane, buffer->width, buffer->height, bgplane_mode );
18.208 +
18.209 + pvr2_render_tilebuffer( buffer->width, buffer->height, clip_x, clip_y,
18.210 clip_x + clip_width, clip_y + clip_height );
18.211 -
18.212 - /* Post-render cleanup and update */
18.213 -
18.214 - /* Add frame, fps, etc data */
18.215 - //glDrawGrid( width, height );
18.216 - glPrintf( 4, 16, "Frame %d", pvr2_get_frame_count() );
18.217 - /* Generate end of render event */
18.218 - asic_event( EVENT_PVR_RENDER_DONE );
18.219 - DEBUG( "Rendered frame %d to %08X", pvr2_get_frame_count(), render_addr );
18.220 +
18.221 + DEBUG( "Rendered frame %d to %08X", pvr2_get_frame_count(), buffer->address );
18.222 }
19.1 --- a/src/pvr2/texcache.c Tue Feb 06 07:59:06 2007 +0000
19.2 +++ b/src/pvr2/texcache.c Sun Feb 11 10:09:32 2007 +0000
19.3 @@ -1,5 +1,5 @@
19.4 /**
19.5 - * $Id: texcache.c,v 1.25 2007-02-05 08:52:59 nkeynes Exp $
19.6 + * $Id: texcache.c,v 1.26 2007-02-11 10:09:32 nkeynes Exp $
19.7 *
19.8 * Texture cache. Responsible for maintaining a working set of OpenGL
19.9 * textures.
19.10 @@ -326,6 +326,7 @@
19.11 struct vq_codebook codebook;
19.12 GLint filter = GL_LINEAR;
19.13
19.14 + glPixelStorei( GL_UNPACK_ROW_LENGTH, 0 );
19.15 /* Decode the format parameters */
19.16 switch( tex_format ) {
19.17 case PVR2_TEX_FORMAT_IDX4:
.