Search
lxdream.org :: lxdream :: r1282:9f445c5e252b
lxdream 0.9.1
released Jun 29
Download Now
changeset1282:9f445c5e252b
parent1281:a3e763a4c60e
child1283:2cbafe321d6f
authornkeynes
dateTue Mar 27 08:23:52 2012 +1000 (12 years ago)
Android: Preserve render buffers when switching away from app.
- fix gl_read_render_buffer + gl_load_frame_buffer to work in GLES
a) glReadPixels only (guaranteed to) work for GL_RGBA,GL_UNSIGNED_BYTE
b) glTexSubImage2D can only load GL_RGBA into a GL_RGBA render buffer.
src/display.h
src/drivers/video_gl.c
src/gui_android.c
src/pvr2/glutil.c
src/pvr2/glutil.h
src/pvr2/pvr2.c
src/pvr2/pvr2.h
src/pvr2/texcache.c
1.1 --- a/src/display.h Wed Mar 21 20:36:20 2012 +1000
1.2 +++ b/src/display.h Tue Mar 27 08:23:52 2012 +1000
1.3 @@ -101,7 +101,7 @@
1.4 uint32_t width;
1.5 uint32_t height;
1.6 uint32_t rowstride;
1.7 - uint32_t colour_format;
1.8 + uint32_t colour_format; /* Colour format that the dreamcast expects the data to be in */
1.9 sh4addr_t address;
1.10 uint32_t size; /* Size of buffer in bytes, must be width*height*bpp */
1.11 gboolean inverted;/* True if the buffer is upside down */
1.12 @@ -111,6 +111,7 @@
1.13 struct display_capabilities {
1.14 gboolean has_gl;
1.15 gboolean has_sl;
1.16 + gboolean has_bgra;
1.17 int depth_bits;
1.18 int stencil_bits; /* 0 = no stencil buffer */
1.19 };
2.1 --- a/src/drivers/video_gl.c Wed Mar 21 20:36:20 2012 +1000
2.2 +++ b/src/drivers/video_gl.c Tue Mar 27 08:23:52 2012 +1000
2.3 @@ -16,6 +16,7 @@
2.4 * GNU General Public License for more details.
2.5 */
2.6
2.7 +#include <assert.h>
2.8 #include <sys/time.h>
2.9
2.10 #include "display.h"
2.11 @@ -24,11 +25,6 @@
2.12 #include "pvr2/shaders.h"
2.13 #include "drivers/video_gl.h"
2.14
2.15 -/* FIXME: Need to actually handle this case */
2.16 -#ifndef GL_PACK_ROW_LENGTH
2.17 -#define glPixelStorei(key,val)
2.18 -#endif
2.19 -
2.20 uint32_t video_width, video_height;
2.21 struct video_vertex {
2.22 float x,y;
2.23 @@ -204,21 +200,6 @@
2.24 glFlush();
2.25 }
2.26
2.27 -gboolean gl_load_frame_buffer( frame_buffer_t frame, int tex_id )
2.28 -{
2.29 - GLenum type = colour_formats[frame->colour_format].type;
2.30 - GLenum format = colour_formats[frame->colour_format].format;
2.31 - int bpp = colour_formats[frame->colour_format].bpp;
2.32 - int rowstride = (frame->rowstride / bpp) - frame->width;
2.33 -
2.34 - glPixelStorei( GL_UNPACK_ROW_LENGTH, rowstride );
2.35 - glBindTexture( GL_TEXTURE_2D, tex_id );
2.36 - glTexSubImage2D( GL_TEXTURE_2D, 0, 0,0,
2.37 - frame->width, frame->height, format, type, frame->data );
2.38 - glPixelStorei( GL_UNPACK_ROW_LENGTH, 0 );
2.39 - return TRUE;
2.40 -}
2.41 -
2.42 void gl_display_blank( uint32_t colour )
2.43 {
2.44 /* Set the video_box background colour */
2.45 @@ -239,6 +220,232 @@
2.46 glFlush();
2.47 }
2.48
2.49 +
2.50 +#ifdef HAVE_GLES2
2.51 +/* Note: OpenGL ES only officialy supports glReadPixels for the RGBA32 format
2.52 + * (and doesn't necessarily support glPixelStore(GL_PACK_ROW_LENGTH) either.
2.53 + * As a result, we end up needed to do the format conversion ourselves.
2.54 + */
2.55 +
2.56 +/**
2.57 + * Swizzle 32-bit RGBA to specified target format, truncating components where
2.58 + * necessary. Target may == source.
2.59 + * @param target destination buffer
2.60 + * @param Source buffer, which must be in 8-bit-per-component RGBA format, fully packed.
2.61 + * @param width width of image in pixels
2.62 + * @param height height of image in pixels
2.63 + * @param target_stride Stride of target buffer, in bytes
2.64 + * @param colour_format
2.65 + */
2.66 +static void rgba32_to_target( unsigned char *target, const uint32_t *source, int width, int height, int target_stride, int colour_format )
2.67 +{
2.68 + int x,y;
2.69 +
2.70 + if( target_stride == 0 )
2.71 + target_stride = width * colour_formats[colour_format].bpp;
2.72 +
2.73 + switch( colour_format ) {
2.74 + case COLFMT_BGRA1555:
2.75 + for( y=0; y<height; y++ ) {
2.76 + uint16_t *d = (uint16_t *)target;
2.77 + for( x=0; x<width; x++ ) {
2.78 + uint32_t v = *source++;
2.79 + *d++ = (uint16_t)( ((v & 0x80000000) >> 16) | ((v & 0x00F80000) >> 19) |
2.80 + ((v & 0x0000F800)>>6) | ((v & 0x000000F8) << 7) );
2.81 + }
2.82 + target += target_stride;
2.83 + }
2.84 + break;
2.85 + case COLFMT_RGB565:
2.86 + for( y=0; y<height; y++ ) {
2.87 + uint16_t *d = (uint16_t *)target;
2.88 + for( x=0; x<width; x++ ) {
2.89 + uint32_t v = *source++;
2.90 + *d++ = (uint16_t)( ((v & 0x00F80000) >> 19) | ((v & 0x0000FC00) >> 5) | ((v & 0x000000F8)<<8) );
2.91 + }
2.92 + target += target_stride;
2.93 + }
2.94 + break;
2.95 + case COLFMT_BGRA4444:
2.96 + for( y=0; y<height; y++ ) {
2.97 + uint16_t *d = (uint16_t *)target;
2.98 + for( x=0; x<width; x++ ) {
2.99 + uint32_t v = *source++;
2.100 + *d++ = (uint16_t)( ((v & 0xF0000000) >> 16) | ((v & 0x00F00000) >> 20) |
2.101 + ((v & 0x0000F000) >> 8) | ((v & 0x000000F0)<<4) );
2.102 + }
2.103 + target += target_stride;
2.104 + }
2.105 + break;
2.106 + case COLFMT_BGRA8888:
2.107 + for( y=0; y<height; y++ ) {
2.108 + uint32_t *d = (uint32_t *)target;
2.109 + for( x=0; x<width; x++ ) {
2.110 + uint32_t v = *source++;
2.111 + *d++ = (v & 0xFF00FF00) | ((v & 0x00FF0000) >> 16) | ((v & 0x000000FF)<<16);
2.112 + }
2.113 + target += target_stride;
2.114 + }
2.115 + break;
2.116 + case COLFMT_BGR0888:
2.117 + for( y=0; y<height; y++ ) {
2.118 + uint32_t *d = (uint32_t *)target;
2.119 + for( x=0; x<width; x++ ) {
2.120 + uint32_t v = *source++;
2.121 + *d++ = ((v & 0x00FF0000) >> 16) | (v & 0x0000FF00) | ((v & 0x000000FF)<<16);
2.122 + }
2.123 + target += target_stride;
2.124 + }
2.125 + break;
2.126 + case COLFMT_BGR888:
2.127 + for( y=0; y<height; y++ ) {
2.128 + uint8_t *d = (uint8_t *)target;
2.129 + for( x=0; x<width; x++ ) {
2.130 + uint32_t v = *source++;
2.131 + *d++ = (uint8_t)(v >> 16);
2.132 + *d++ = (uint8_t)(v >> 8);
2.133 + *d++ = (uint8_t)(v);
2.134 + }
2.135 + target += target_stride;
2.136 + }
2.137 + break;
2.138 + case COLFMT_RGB888:
2.139 + for( y=0; y<height; y++ ) {
2.140 + uint8_t *d = (uint8_t *)target;
2.141 + for( x=0; x<width; x++ ) {
2.142 + uint32_t v = *source++;
2.143 + *d++ = (uint8_t)(v);
2.144 + *d++ = (uint8_t)(v >> 8);
2.145 + *d++ = (uint8_t)(v >> 16);
2.146 + }
2.147 + target += target_stride;
2.148 + }
2.149 + break;
2.150 + default:
2.151 + assert( 0 && "Unsupported colour format" );
2.152 + }
2.153 +}
2.154 +
2.155 +/**
2.156 + * Convert data into an acceptable form for loading into an RGBA texture.
2.157 + */
2.158 +static int target_to_rgba( uint32_t *target, const unsigned char *source, int width, int height, int source_stride, int colour_format )
2.159 +{
2.160 + int x,y;
2.161 + uint16_t *d;
2.162 + switch( colour_format ) {
2.163 + case COLFMT_BGRA1555:
2.164 + d = (uint16_t *)target;
2.165 + for( y=0; y<height; y++ ) {
2.166 + uint16_t *s = (uint16_t *)source;
2.167 + for( x=0; x<width; x++ ) {
2.168 + uint16_t v = *s++;
2.169 + *d++ = (v >> 15) | (v<<1);
2.170 + }
2.171 + source += source_stride;
2.172 + }
2.173 + return GL_UNSIGNED_SHORT_5_5_5_1;
2.174 + break;
2.175 + case COLFMT_RGB565:
2.176 + /* Need to expand to RGBA32 in order to have room for an alpha component */
2.177 + for( y=0; y<height; y++ ) {
2.178 + uint16_t *s = (uint16_t *)source;
2.179 + for( x=0; x<width; x++ ) {
2.180 + uint32_t v = (uint32_t)*s++;
2.181 + *target++ = ((v & 0xF800)>>8) | ((v & 0x07E0) <<5) | ((v & 0x001F) << 19) |
2.182 + ((v & 0xE000) >> 13) | ((v &0x0600) >> 1) | ((v & 0x001C) << 14);
2.183 + }
2.184 + source += source_stride;
2.185 + }
2.186 + return GL_UNSIGNED_BYTE;
2.187 + case COLFMT_BGRA4444:
2.188 + d = (uint16_t *)target;
2.189 + for( y=0; y<height; y++ ) {
2.190 + uint16_t *s = (uint16_t *)source;
2.191 + for( x=0; x<width; x++ ) {
2.192 + uint16_t v = *s++;
2.193 + *d++ = (v >> 12) | (v<<4);
2.194 + }
2.195 + source += source_stride;
2.196 + }
2.197 + return GL_UNSIGNED_SHORT_4_4_4_4;
2.198 + case COLFMT_RGB888:
2.199 + for( y=0; y<height; y++ ) {
2.200 + uint8_t *s = (uint8_t *)source;
2.201 + for( x=0; x<width; x++ ) {
2.202 + *target++ = s[0] | (s[1]<<8) | (s[2]<<16);
2.203 + s += 3;
2.204 + }
2.205 + source += source_stride;
2.206 + }
2.207 + return GL_UNSIGNED_BYTE;
2.208 + case COLFMT_BGRA8888:
2.209 + for( y=0; y<height; y++ ) {
2.210 + uint32_t *s = (uint32_t *)source;
2.211 + for( x=0; x<width; x++ ) {
2.212 + uint32_t v = (uint32_t)*s++;
2.213 + *target++ = (v & 0xFF00FF00) | ((v & 0x00FF0000) >> 16) | ((v & 0x000000FF) << 16);
2.214 + }
2.215 + source += source_stride;
2.216 + }
2.217 + return GL_UNSIGNED_BYTE;
2.218 + case COLFMT_BGR0888:
2.219 + for( y=0; y<height; y++ ) {
2.220 + uint32_t *s = (uint32_t *)source;
2.221 + for( x=0; x<width; x++ ) {
2.222 + uint32_t v = (uint32_t)*s++;
2.223 + *target++ = (v & 0x0000FF00) | ((v & 0x00FF0000) >> 16) | ((v & 0x000000FF) << 16);
2.224 + }
2.225 + source += source_stride;
2.226 + }
2.227 + return GL_UNSIGNED_BYTE;
2.228 + case COLFMT_BGR888:
2.229 + for( y=0; y<height; y++ ) {
2.230 + uint8_t *s = (uint8_t *)source;
2.231 + for( x=0; x<width; x++ ) {
2.232 + *target++ = s[2] | (s[1]<<8) | (s[0]<<16);
2.233 + s += 3;
2.234 + }
2.235 + source += source_stride;
2.236 + }
2.237 + return GL_UNSIGNED_BYTE;
2.238 + default:
2.239 + assert( 0 && "Unsupported colour format" );
2.240 + }
2.241 +
2.242 +
2.243 +}
2.244 +
2.245 +
2.246 +gboolean gl_read_render_buffer( unsigned char *target, render_buffer_t buffer,
2.247 + int rowstride, int colour_format )
2.248 +{
2.249 + if( colour_formats[colour_format].bpp == 4 && (rowstride == 0 || rowstride == buffer->width*4) ) {
2.250 + glReadPixels( 0, 0, buffer->width, buffer->height, GL_RGBA, GL_UNSIGNED_BYTE, target );
2.251 + rgba32_to_target( target, (uint32_t *)target, buffer->width, buffer->height, rowstride, colour_format );
2.252 + } else {
2.253 + int size = buffer->width * buffer->height;
2.254 + uint32_t tmp[size];
2.255 +
2.256 + glReadPixels( 0, 0, buffer->width, buffer->height, GL_RGBA, GL_UNSIGNED_BYTE, tmp );
2.257 + rgba32_to_target( target, tmp, buffer->width, buffer->height, rowstride, colour_format );
2.258 + }
2.259 + return TRUE;
2.260 +}
2.261 +
2.262 +gboolean gl_load_frame_buffer( frame_buffer_t frame, int tex_id )
2.263 +{
2.264 + int size = frame->width * frame->height;
2.265 + uint32_t tmp[size];
2.266 +
2.267 + GLenum type = target_to_rgba( tmp, frame->data, frame->width, frame->height, frame->rowstride, frame->colour_format );
2.268 + glBindTexture( GL_TEXTURE_2D, tex_id );
2.269 + glTexSubImage2D( GL_TEXTURE_2D, 0, 0,0, frame->width, frame->height, GL_RGBA, type, tmp );
2.270 + gl_check_error("gl_load_frame_buffer:glTexSubImage2DBGRA");
2.271 + return TRUE;
2.272 +}
2.273 +
2.274 +#else
2.275 /**
2.276 * Generic GL read_render_buffer. This function assumes that the caller
2.277 * has already set the appropriate glReadBuffer(); in other words, unless
2.278 @@ -259,6 +466,23 @@
2.279 return TRUE;
2.280 }
2.281
2.282 +gboolean gl_load_frame_buffer( frame_buffer_t frame, int tex_id )
2.283 +{
2.284 + GLenum type = colour_formats[frame->colour_format].type;
2.285 + GLenum format = colour_formats[frame->colour_format].format;
2.286 + int bpp = colour_formats[frame->colour_format].bpp;
2.287 + int rowstride = (frame->rowstride / bpp) - frame->width;
2.288 +
2.289 + glPixelStorei( GL_UNPACK_ROW_LENGTH, rowstride );
2.290 + glBindTexture( GL_TEXTURE_2D, tex_id );
2.291 + glTexSubImage2DBGRA( 0, 0,0,
2.292 + frame->width, frame->height, format, type, frame->data, FALSE );
2.293 + glPixelStorei( GL_UNPACK_ROW_LENGTH, 0 );
2.294 + return TRUE;
2.295 +}
2.296 +#endif
2.297 +
2.298 +
2.299 gboolean gl_init_driver( display_driver_t driver, gboolean need_fbo )
2.300 {
2.301 /* Use framebuffer objects if available */
2.302 @@ -282,6 +506,7 @@
2.303 gl_vbo_init(driver);
2.304
2.305 driver->capabilities.has_gl = TRUE;
2.306 + driver->capabilities.has_bgra = isGLBGRATextureSupported();
2.307 return TRUE;
2.308 }
2.309
3.1 --- a/src/gui_android.c Wed Mar 21 20:36:20 2012 +1000
3.2 +++ b/src/gui_android.c Tue Mar 27 08:23:52 2012 +1000
3.3 @@ -39,6 +39,7 @@
3.4 #include "drivers/video_egl.h"
3.5 #include "maple/maple.h"
3.6 #include "vmu/vmulist.h"
3.7 +#include "pvr2/pvr2.h"
3.8
3.9 struct surface_info {
3.10 ANativeWindow *win;
3.11 @@ -86,6 +87,8 @@
3.12 {
3.13 struct surface_info *surface = (struct surface_info *)data;
3.14 video_egl_set_window(surface->win, surface->width, surface->height, surface->format);
3.15 + pvr2_restore_render_buffers();
3.16 + pvr2_draw_frame();
3.17 INFO( "set_surface" );
3.18 return 0;
3.19 }
3.20 @@ -97,6 +100,7 @@
3.21 if( dreamcast_is_running() ) {
3.22 dreamcast_stop(); /* Should already be stopped, but just in case */
3.23 }
3.24 + pvr2_preserve_render_buffers();
3.25 video_egl_clear_window();
3.26 ANativeWindow_release(surface->win);
3.27 surface->win = NULL;
3.28 @@ -112,6 +116,7 @@
3.29
3.30 pthread_attr_init(&attr);
3.31 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
3.32 + pthread_attr_setstacksize(&attr,2048*1024);
3.33 int status = pthread_create(&dreamcast_thread, &attr, android_thread_main, NULL);
3.34 if( status != 0 ) {
3.35 /* Handle errors */
4.1 --- a/src/pvr2/glutil.c Wed Mar 21 20:36:20 2012 +1000
4.2 +++ b/src/pvr2/glutil.c Tue Mar 27 08:23:52 2012 +1000
4.3 @@ -16,6 +16,7 @@
4.4 * GNU General Public License for more details.
4.5 */
4.6
4.7 +#include <assert.h>
4.8 #include <string.h>
4.9 #include <stdlib.h>
4.10 #include <glib/gstrfuncs.h>
4.11 @@ -58,7 +59,6 @@
4.12 return !isOpenGLES2() && isGLExtensionSupported("GL_EXT_bgra");
4.13 }
4.14
4.15 -
4.16 gboolean isGLShaderSupported()
4.17 {
4.18 return isOpenGLES2() || (isGLExtensionSupported("GL_ARB_fragment_shader") &&
4.19 @@ -255,11 +255,117 @@
4.20 default: s = "Unknown error"; break;
4.21 }
4.22 if( context ) {
4.23 - WARN( "%s: GL error: %x (%s)\n", context, err, s );
4.24 + WARN( "%s: GL error: %x (%s)", context, err, s );
4.25 } else {
4.26 - WARN( "GL error: %x (%s)\n", err, s );
4.27 + WARN( "GL error: %x (%s)", err, s );
4.28 }
4.29 return FALSE;
4.30 }
4.31 return TRUE;
4.32 }
4.33 +
4.34 +static int bgra_to_rgba_type( int glFormatType )
4.35 +{
4.36 + switch( glFormatType ) {
4.37 + case GL_UNSIGNED_SHORT_1_5_5_5_REV:
4.38 + return GL_UNSIGNED_SHORT_5_5_5_1;
4.39 + case GL_UNSIGNED_SHORT_4_4_4_4_REV:
4.40 + return GL_UNSIGNED_SHORT_4_4_4_4;
4.41 + case GL_UNSIGNED_BYTE:
4.42 + return GL_UNSIGNED_BYTE;
4.43 + default:
4.44 + assert( 0 && "Unsupported BGRA format" );
4.45 + return glFormatType;
4.46 + }
4.47 +}
4.48 +
4.49 +/**
4.50 + * Convert BGRA data in buffer to RGBA format in-place (for systems that don't natively
4.51 + * support BGRA).
4.52 + * @return converted format type
4.53 + * @param data BGRA pixel data
4.54 + * @param nPixels total number of pixels (width*height)
4.55 + * @param glFormatType GL format of source data. One of
4.56 + * GL_UNSIGNED_SHORT_1_5_5_5_REV, GL_UNSIGNED_SHORT_4_4_4_4_REV, or GL_UNSIGNED_BYTE
4.57 + */
4.58 +static int bgra_to_rgba( unsigned char *data, unsigned nPixels, int glFormatType )
4.59 +{
4.60 + unsigned i;
4.61 + switch( glFormatType ) {
4.62 + case GL_UNSIGNED_SHORT_1_5_5_5_REV: {
4.63 + uint16_t *p = (uint16_t *)data;
4.64 + uint16_t *end = p + nPixels;
4.65 + while( p != end ) {
4.66 + uint16_t v = *p;
4.67 + *p = (v >> 15) | (v<<1);
4.68 + p++;
4.69 + }
4.70 + return GL_UNSIGNED_SHORT_5_5_5_1;
4.71 + }
4.72 + case GL_UNSIGNED_SHORT_4_4_4_4_REV: { /* ARGB => RGBA */
4.73 + uint16_t *p = (uint16_t *)data;
4.74 + uint16_t *end = p + nPixels;
4.75 + while( p != end ) {
4.76 + uint16_t v = *p;
4.77 + *p = (v >> 12) | (v<<4);
4.78 + p++;
4.79 + }
4.80 + return GL_UNSIGNED_SHORT_4_4_4_4;
4.81 + }
4.82 + case GL_UNSIGNED_BYTE: { /* ARGB => ABGR */
4.83 + uint32_t *p = (uint32_t *)data;
4.84 + uint32_t *end = p + nPixels;
4.85 + while( p != end ) {
4.86 + uint32_t v = *p;
4.87 + *p = (v&0xFF000000) | ((v<<16) & 0x00FF0000) | (v & 0x0000FF00) | ((v>>16) & 0x000000FF);
4.88 + p++;
4.89 + }
4.90 + return GL_UNSIGNED_BYTE;
4.91 + }
4.92 + default:
4.93 + assert( 0 && "Unsupported BGRA format" );
4.94 + return glFormatType;
4.95 + }
4.96 +}
4.97 +
4.98 +void glTexImage2DBGRA( int level, GLint intFormat, int width, int height, GLint format, GLint type, unsigned char *data, int preserveData )
4.99 +{
4.100 + if( format == GL_BGRA && !display_driver->capabilities.has_bgra ) {
4.101 + if( preserveData ) {
4.102 + size_t size = width * height * (type == GL_UNSIGNED_BYTE ? 4 : 2);
4.103 + char buf[size];
4.104 + memcpy(buf, data, size);
4.105 + GLint rgbaType = bgra_to_rgba( buf, width*height, type );
4.106 + glTexImage2D( GL_TEXTURE_2D, level, intFormat, width, height, 0, GL_RGBA, rgbaType,
4.107 + buf );
4.108 + } else {
4.109 + GLint rgbaType = bgra_to_rgba( data, width*height, type );
4.110 + glTexImage2D( GL_TEXTURE_2D, level, intFormat, width, height, 0, GL_RGBA, rgbaType,
4.111 + data );
4.112 + }
4.113 + } else {
4.114 + glTexImage2D( GL_TEXTURE_2D, level, intFormat, width, height, 0, format, type,
4.115 + data );
4.116 + }
4.117 +}
4.118 +
4.119 +void glTexSubImage2DBGRA( int level, int xoff, int yoff, int width, int height, GLint format, GLint type, unsigned char *data, int preserveData )
4.120 +{
4.121 + if( format == GL_BGRA && !display_driver->capabilities.has_bgra ) {
4.122 + if( preserveData ) {
4.123 + size_t size = width * height * (type == GL_UNSIGNED_BYTE ? 4 : 2);
4.124 + char buf[size];
4.125 + memcpy(buf, data, size);
4.126 + GLint rgbaType = bgra_to_rgba( buf, width*height, type );
4.127 + glTexSubImage2D( GL_TEXTURE_2D, level, xoff, yoff, width, height, GL_RGBA, rgbaType,
4.128 + buf );
4.129 + } else {
4.130 + GLint rgbaType = bgra_to_rgba( data, width*height, type );
4.131 + glTexSubImage2D( GL_TEXTURE_2D, level, xoff, yoff, width, height, GL_RGBA, rgbaType,
4.132 + data );
4.133 + }
4.134 + } else {
4.135 + glTexSubImage2D( GL_TEXTURE_2D, level, xoff, yoff, width, height, format, type,
4.136 + data );
4.137 + }
4.138 +}
5.1 --- a/src/pvr2/glutil.h Wed Mar 21 20:36:20 2012 +1000
5.2 +++ b/src/pvr2/glutil.h Tue Mar 27 08:23:52 2012 +1000
5.3 @@ -60,6 +60,15 @@
5.4 gboolean isGLShaderSupported();
5.5 GLint glGetMaxColourAttachments();
5.6
5.7 +/**
5.8 + * Wrapper function for glTexImage2D calls that may have BGRA data - on systems
5.9 + * where this isn't directly supported, swizzle the data into an acceptable RGBA
5.10 + * equivalent. If preserveData is true, data will not be modified - otherwise
5.11 + * the method may swizzle data in-place.
5.12 + */
5.13 +void glTexImage2DBGRA( int level, GLint intFormat, int width, int height, GLint format, GLint type, unsigned char *data, int preserveData );
5.14 +void glTexSubImage2DBGRA( int level, int xoff, int yoff, int width, int height, GLint format, GLint type, unsigned char *data, int preserveData );
5.15 +
5.16 /****** Extension variant wrangling *****/
5.17
5.18 #if defined(GL_MIRRORED_REPEAT_ARB) && !defined(GL_MIRRORED_REPEAT)
5.19 @@ -141,8 +150,6 @@
5.20 #define glCheckFramebufferStatus glCheckFramebufferStatusEXT
5.21 #endif
5.22
5.23 -
5.24 -
5.25 /* Define an orthographic transform matrix, given the bounding box (assuming origin at 0) */
5.26 void defineOrthoMatrix( GLfloat *matrix, GLfloat width, GLfloat height, GLfloat znear, GLfloat zfar );
5.27
6.1 --- a/src/pvr2/pvr2.c Wed Mar 21 20:36:20 2012 +1000
6.2 +++ b/src/pvr2/pvr2.c Tue Mar 27 08:23:52 2012 +1000
6.3 @@ -46,6 +46,7 @@
6.4 static render_buffer_t pvr2_get_render_buffer( frame_buffer_t frame );
6.5 static render_buffer_t pvr2_next_render_buffer( );
6.6 static render_buffer_t pvr2_frame_buffer_to_render_buffer( frame_buffer_t frame );
6.7 +static frame_buffer_t pvr2_render_buffer_to_frame_buffer( render_buffer_t frame );
6.8 uint32_t pvr2_get_sync_status();
6.9 static int output_colour_formats[] = { COLFMT_BGRA1555, COLFMT_RGB565, COLFMT_BGR888, COLFMT_BGRA8888 };
6.10 static int render_colour_formats[8] = {
6.11 @@ -202,7 +203,6 @@
6.12 fwrite( &buffer->scale, sizeof(buffer->scale), 1, f );
6.13 int32_t flushed = (int32_t)buffer->flushed; // Force to 32-bits for save-file consistency
6.14 fwrite( &flushed, sizeof(flushed), 1, f );
6.15 -
6.16 }
6.17
6.18 render_buffer_t pvr2_load_render_buffer( FILE *f, gboolean *status )
6.19 @@ -870,7 +870,7 @@
6.20 int i;
6.21 for( i=0; i<render_buffer_count; i++ ) {
6.22 if( render_buffers[i] != NULL ) {
6.23 - display_driver->destroy_render_buffer(render_buffers[i]);
6.24 + pvr2_destroy_render_buffer(render_buffers[i]);
6.25 render_buffers[i] = NULL;
6.26 }
6.27 }
6.28 @@ -878,6 +878,57 @@
6.29 }
6.30 }
6.31
6.32 +static frame_buffer_t saved_render_buffers[MAX_RENDER_BUFFERS];
6.33 +static frame_buffer_t saved_displayed_render_buffer = NULL;
6.34 +static int saved_render_buffer_count = 0;
6.35 +
6.36 +/*
6.37 + * Copy all render buffers to main RAM to preserve across GL shutdown
6.38 + */
6.39 +void pvr2_preserve_render_buffers( void )
6.40 +{
6.41 + int i, j;
6.42 + /* If we had previous preserved buffers, blow them away now. */
6.43 + for( i=0; i<MAX_RENDER_BUFFERS; i++ ) {
6.44 + if( saved_render_buffers[i] != NULL ) {
6.45 + g_free(saved_render_buffers[i]);
6.46 + saved_render_buffers[i] = NULL;
6.47 + }
6.48 + }
6.49 + saved_displayed_render_buffer = NULL;
6.50 +
6.51 + for( i=0, j=0; i<render_buffer_count; i++ ) {
6.52 + if( render_buffers[i]->address != -1 ) {
6.53 + saved_render_buffers[j] = pvr2_render_buffer_to_frame_buffer(render_buffers[i]);
6.54 + if( render_buffers[i] == displayed_render_buffer )
6.55 + saved_displayed_render_buffer = saved_render_buffers[j];
6.56 + j++;
6.57 + }
6.58 + }
6.59 + saved_render_buffer_count = j;
6.60 +}
6.61 +
6.62 +/**
6.63 + * Restore render buffers that were preserved by a previous call to
6.64 + * pvr2_preserve_render_buffers().
6.65 + */
6.66 +void pvr2_restore_render_buffers( void )
6.67 +{
6.68 + int i;
6.69 + for( i=0; i<saved_render_buffer_count; i++ ) {
6.70 + if( saved_render_buffers[i] != NULL ) {
6.71 + render_buffers[i] = pvr2_frame_buffer_to_render_buffer(saved_render_buffers[i]);
6.72 + if( saved_render_buffers[i] == saved_displayed_render_buffer )
6.73 + displayed_render_buffer = render_buffers[i];
6.74 + g_free(saved_render_buffers[i]);
6.75 + saved_render_buffers[i] = NULL;
6.76 + }
6.77 + }
6.78 + render_buffer_count = saved_render_buffer_count;
6.79 + saved_render_buffer_count = 0;
6.80 + saved_displayed_render_buffer = NULL;
6.81 +}
6.82 +
6.83
6.84 void pvr2_finish_render_buffer( render_buffer_t buffer )
6.85 {
6.86 @@ -930,6 +981,7 @@
6.87 * display has it. Mark it as unaddressed for later.
6.88 */
6.89 render_buffers[i]->address = -1;
6.90 + render_buffers[i]->flushed = TRUE;
6.91 } else {
6.92 /* perfect */
6.93 result = render_buffers[i];
6.94 @@ -948,6 +1000,7 @@
6.95 pvr2_render_buffer_copy_to_sh4( render_buffers[i] );
6.96 }
6.97 render_buffers[i]->address = -1;
6.98 + render_buffers[i]->flushed = TRUE;
6.99 }
6.100 }
6.101
6.102 @@ -1038,6 +1091,23 @@
6.103 return result;
6.104 }
6.105
6.106 +static frame_buffer_t pvr2_render_buffer_to_frame_buffer( render_buffer_t buffer )
6.107 +{
6.108 + int bpp = colour_formats[buffer->colour_format].bpp;
6.109 + size_t size = buffer->width * buffer->height * bpp;
6.110 + frame_buffer_t result = g_malloc0( sizeof(struct frame_buffer) + size );
6.111 + result->data = (unsigned char *)(result+1);
6.112 + result->width = buffer->width;
6.113 + result->height = buffer->height;
6.114 + result->rowstride = buffer->rowstride;
6.115 + result->colour_format = buffer->colour_format;
6.116 + result->address = buffer->address;
6.117 + result->size = buffer->size;
6.118 + result->inverted = buffer->inverted;
6.119 + display_driver->read_render_buffer( result->data, buffer, buffer->width * bpp, buffer->colour_format );
6.120 + return result;
6.121 +}
6.122 +
6.123
6.124 /**
6.125 * Invalidate any caching on the supplied address. Specifically, if it falls
6.126 @@ -1056,6 +1126,7 @@
6.127 }
6.128 if( isWrite ) {
6.129 render_buffers[i]->address = -1; /* Invalid */
6.130 + render_buffers[i]->flushed = TRUE;
6.131 }
6.132 return TRUE; /* should never have overlapping buffers */
6.133 }
7.1 --- a/src/pvr2/pvr2.h Wed Mar 21 20:36:20 2012 +1000
7.2 +++ b/src/pvr2/pvr2.h Tue Mar 27 08:23:52 2012 +1000
7.3 @@ -301,6 +301,15 @@
7.4 */
7.5 void pvr2_destroy_render_buffers( void );
7.6
7.7 +/**
7.8 + * Preserve render buffers in main memory
7.9 + */
7.10 +void pvr2_preserve_render_buffers( void );
7.11 +
7.12 +/**
7.13 + * Restore render buffers from a previous call to pvr2_preserve_render_buffers()
7.14 + */
7.15 +void pvr2_restore_render_buffers( void );
7.16
7.17 /**
7.18 * Structure to hold a complete unpacked vertex (excluding modifier
8.1 --- a/src/pvr2/texcache.c Wed Mar 21 20:36:20 2012 +1000
8.2 +++ b/src/pvr2/texcache.c Tue Mar 27 08:23:52 2012 +1000
8.3 @@ -61,7 +61,6 @@
8.4 static uint32_t texcache_palette_mode;
8.5 static uint32_t texcache_stride_width;
8.6 static gboolean texcache_have_palette_shader;
8.7 -static gboolean texcache_have_bgra;
8.8 static gboolean texcache_palette_valid;
8.9 static GLuint texcache_palette_texid;
8.10
8.11 @@ -142,14 +141,13 @@
8.12 } else {
8.13 texcache_have_palette_shader = FALSE;
8.14 }
8.15 - texcache_have_bgra = isGLBGRATextureSupported();
8.16
8.17 glGenTextures( MAX_TEXTURES, texids );
8.18 for( i=0; i<MAX_TEXTURES; i++ ) {
8.19 texcache_active_list[i].texture_id = texids[i];
8.20 }
8.21 INFO( "Texcache initialized (%s, %s)", (texcache_have_palette_shader ? "Palette shader" : "No palette support"),
8.22 - (texcache_have_bgra ? "BGRA" : "RGBA") );
8.23 + (display_driver->capabilities.has_bgra ? "BGRA" : "RGBA") );
8.24 }
8.25
8.26 /**
8.27 @@ -252,73 +250,6 @@
8.28 }
8.29
8.30 /**
8.31 - * Convert BGRA data in buffer to RGBA format (for systems that don't natively
8.32 - * support BGRA).
8.33 - * @return converted format type
8.34 - * @param data BGRA pixel data
8.35 - * @param nPixels total number of pixels (width*height)
8.36 - * @param glFormatType GL format of source data. One of
8.37 - * GL_UNSIGNED_SHORT_1_5_5_5_REV, GL_UNSIGNED_SHORT_4_4_4_4_REV, or GL_UNSIGNED_BYTE
8.38 - */
8.39 -static int bgra_to_rgba( unsigned char *data, unsigned nPixels, int glFormatType )
8.40 -{
8.41 - unsigned i;
8.42 - switch( glFormatType ) {
8.43 - case GL_UNSIGNED_SHORT_1_5_5_5_REV: {
8.44 - uint16_t *p = (uint16_t *)data;
8.45 - uint16_t *end = p + nPixels;
8.46 - while( p != end ) {
8.47 - uint16_t v = *p;
8.48 - *p = (v >> 15) | (v<<1);
8.49 - p++;
8.50 - }
8.51 - return GL_UNSIGNED_SHORT_5_5_5_1;
8.52 - }
8.53 - case GL_UNSIGNED_SHORT_4_4_4_4_REV: { /* ARGB => RGBA */
8.54 - uint16_t *p = (uint16_t *)data;
8.55 - uint16_t *end = p + nPixels;
8.56 - while( p != end ) {
8.57 - uint16_t v = *p;
8.58 - *p = (v >> 12) | (v<<4);
8.59 - p++;
8.60 - }
8.61 - return GL_UNSIGNED_SHORT_4_4_4_4;
8.62 - }
8.63 - case GL_UNSIGNED_BYTE: { /* ARGB => ABGR */
8.64 - uint32_t *p = (uint32_t *)data;
8.65 - uint32_t *end = p + nPixels;
8.66 - while( p != end ) {
8.67 - uint32_t v = *p;
8.68 - *p = (v&0xFF000000) | ((v<<16) & 0x00FF0000) | (v & 0x0000FF00) | ((v>>16) & 0x000000FF);
8.69 - p++;
8.70 - }
8.71 - return GL_UNSIGNED_BYTE;
8.72 - }
8.73 - default:
8.74 - assert( 0 && "Unsupported BGRA format" );
8.75 - return glFormatType;
8.76 - }
8.77 -}
8.78 -
8.79 -/**
8.80 - * Install the image data in the currently bound 2D texture.
8.81 - * May modify the buffered data if needed to make the texture compatible with
8.82 - * the GL.
8.83 - */
8.84 -static void texcache_load_image_2D( int level, GLint intFormat, int width, int height, GLint format, GLint type, unsigned char *data )
8.85 -{
8.86 - if( format == GL_BGRA && !texcache_have_bgra ) {
8.87 - GLint rgbaType = bgra_to_rgba( data, width*height, type );
8.88 - glTexImage2D( GL_TEXTURE_2D, level, intFormat, width, height, 0, GL_RGBA, rgbaType,
8.89 - data );
8.90 - } else {
8.91 - glTexImage2D( GL_TEXTURE_2D, level, intFormat, width, height, 0, format, type,
8.92 - data );
8.93 - }
8.94 -
8.95 -}
8.96 -
8.97 -/**
8.98 * Load the palette into 4 textures of 256 entries each. This mirrors the
8.99 * banking done by the PVR2 for 8-bit textures, and also ensures that we
8.100 * can use 8-bit paletted textures ourselves.
8.101 @@ -329,7 +260,7 @@
8.102 unsigned i;
8.103 int bpp = 2;
8.104 uint32_t *palette = (uint32_t *)mmio_region_PVR2PAL.mem;
8.105 - char buf[4096];
8.106 + uint16_t packed_palette[1024];
8.107 char *data = (char *)palette;
8.108
8.109 switch( texcache_palette_mode ) {
8.110 @@ -356,27 +287,17 @@
8.111 }
8.112
8.113 if( bpp == 2 ) {
8.114 - data = buf;
8.115 - uint16_t *packed_palette = (uint16_t *)buf;
8.116 for( i=0; i<1024; i++ ) {
8.117 packed_palette[i] = (uint16_t)palette[i];
8.118 }
8.119 - if( !texcache_have_bgra && format == GL_BGRA ) {
8.120 - type = bgra_to_rgba(data, 1024, type);
8.121 - format = GL_RGBA;
8.122 - }
8.123 - } else if( !texcache_have_bgra && format == GL_BGRA ) { /* bpp == 4 */
8.124 - data = buf;
8.125 - memcpy( buf, palette, 4096 );
8.126 - type = bgra_to_rgba(buf, 1024, type);
8.127 - format = GL_RGBA;
8.128 + data = (char *)packed_palette;
8.129 }
8.130
8.131 glActiveTexture(GL_TEXTURE1);
8.132 if( format_changed )
8.133 - glTexImage2D(GL_TEXTURE_2D, 0, intFormat, 1024, 1, 0, format, type, data );
8.134 + glTexImage2DBGRA(0, intFormat, 1024, 1, format, type, data, data == (char *)palette );
8.135 else
8.136 - glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1024, 1, format, type, data);
8.137 + glTexSubImage2DBGRA(0, 0, 0, 1024, 1, format, type, data, data == (char *)palette);
8.138 glActiveTexture(GL_TEXTURE0);
8.139 texcache_palette_valid = TRUE;
8.140 }
8.141 @@ -660,7 +581,7 @@
8.142 } else {
8.143 pvr2_vram64_read_stride( data, width<<bpp_shift, texture_addr, texcache_stride_width<<bpp_shift, height );
8.144 }
8.145 - texcache_load_image_2D( 0, intFormat, width, height, format, type, data );
8.146 + glTexImage2DBGRA( 0, intFormat, width, height, format, type, data, FALSE );
8.147 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, min_filter);
8.148 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, max_filter);
8.149 return;
8.150 @@ -761,10 +682,10 @@
8.151
8.152 /* Pass to GL */
8.153 if( level == last_level && level != 0 ) { /* 1x1 stored within a 2x2 */
8.154 - texcache_load_image_2D( level, intFormat, 1, 1, format, type,
8.155 - data + (3 << bpp_shift) );
8.156 + glTexImage2DBGRA( level, intFormat, 1, 1, format, type,
8.157 + data + (3 << bpp_shift), FALSE );
8.158 } else {
8.159 - texcache_load_image_2D( level, intFormat, mip_width, mip_height, format, type, data );
8.160 + glTexImage2DBGRA( level, intFormat, mip_width, mip_height, format, type, data, FALSE );
8.161 if( mip_width > 2 ) {
8.162 mip_width >>= 1;
8.163 mip_height >>= 1;
.