revision 1282:9f445c5e252b
summary |
tree |
shortlog |
changelog |
graph |
changeset |
raw | bz2 | zip | gz changeset | 1282:9f445c5e252b |
parent | 1281:a3e763a4c60e |
child | 1283:2cbafe321d6f |
author | nkeynes |
date | Tue 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.
- 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 | view | annotate | diff | log | ||
src/drivers/video_gl.c | view | annotate | diff | log | ||
src/gui_android.c | view | annotate | diff | log | ||
src/pvr2/glutil.c | view | annotate | diff | log | ||
src/pvr2/glutil.h | view | annotate | diff | log | ||
src/pvr2/pvr2.c | view | annotate | diff | log | ||
src/pvr2/pvr2.h | view | annotate | diff | log | ||
src/pvr2/texcache.c | view | annotate | diff | log |
1.1 --- a/src/display.h Wed Mar 21 20:36:20 2012 +10001.2 +++ b/src/display.h Tue Mar 27 08:23:52 2012 +10001.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 +10002.2 +++ b/src/drivers/video_gl.c Tue Mar 27 08:23:52 2012 +10002.3 @@ -16,6 +16,7 @@2.4 * GNU General Public License for more details.2.5 */2.7 +#include <assert.h>2.8 #include <sys/time.h>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.15 -/* FIXME: Need to actually handle this case */2.16 -#ifndef GL_PACK_ROW_LENGTH2.17 -#define glPixelStorei(key,val)2.18 -#endif2.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.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.49 +2.50 +#ifdef HAVE_GLES22.51 +/* Note: OpenGL ES only officialy supports glReadPixels for the RGBA32 format2.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 where2.58 + * necessary. Target may == source.2.59 + * @param target destination buffer2.60 + * @param Source buffer, which must be in 8-bit-per-component RGBA format, fully packed.2.61 + * @param width width of image in pixels2.62 + * @param height height of image in pixels2.63 + * @param target_stride Stride of target buffer, in bytes2.64 + * @param colour_format2.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 +#else2.275 /**2.276 * Generic GL read_render_buffer. This function assumes that the caller2.277 * has already set the appropriate glReadBuffer(); in other words, unless2.278 @@ -259,6 +466,23 @@2.279 return TRUE;2.280 }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 +#endif2.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.305 driver->capabilities.has_gl = TRUE;2.306 + driver->capabilities.has_bgra = isGLBGRATextureSupported();2.307 return TRUE;2.308 }
3.1 --- a/src/gui_android.c Wed Mar 21 20:36:20 2012 +10003.2 +++ b/src/gui_android.c Tue Mar 27 08:23:52 2012 +10003.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.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.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 +10004.2 +++ b/src/pvr2/glutil.c Tue Mar 27 08:23:52 2012 +10004.3 @@ -16,6 +16,7 @@4.4 * GNU General Public License for more details.4.5 */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.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 natively4.51 + * support BGRA).4.52 + * @return converted format type4.53 + * @param data BGRA pixel data4.54 + * @param nPixels total number of pixels (width*height)4.55 + * @param glFormatType GL format of source data. One of4.56 + * GL_UNSIGNED_SHORT_1_5_5_5_REV, GL_UNSIGNED_SHORT_4_4_4_4_REV, or GL_UNSIGNED_BYTE4.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 +10005.2 +++ b/src/pvr2/glutil.h Tue Mar 27 08:23:52 2012 +10005.3 @@ -60,6 +60,15 @@5.4 gboolean isGLShaderSupported();5.5 GLint glGetMaxColourAttachments();5.7 +/**5.8 + * Wrapper function for glTexImage2D calls that may have BGRA data - on systems5.9 + * where this isn't directly supported, swizzle the data into an acceptable RGBA5.10 + * equivalent. If preserveData is true, data will not be modified - otherwise5.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.18 #if defined(GL_MIRRORED_REPEAT_ARB) && !defined(GL_MIRRORED_REPEAT)5.19 @@ -141,8 +150,6 @@5.20 #define glCheckFramebufferStatus glCheckFramebufferStatusEXT5.21 #endif5.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 );
6.1 --- a/src/pvr2/pvr2.c Wed Mar 21 20:36:20 2012 +10006.2 +++ b/src/pvr2/pvr2.c Tue Mar 27 08:23:52 2012 +10006.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 consistency6.14 fwrite( &flushed, sizeof(flushed), 1, f );6.15 -6.16 }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.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 shutdown6.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 to6.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.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.102 @@ -1038,6 +1091,23 @@6.103 return result;6.104 }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.124 /**6.125 * Invalidate any caching on the supplied address. Specifically, if it falls6.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 +10007.2 +++ b/src/pvr2/pvr2.h Tue Mar 27 08:23:52 2012 +10007.3 @@ -301,6 +301,15 @@7.4 */7.5 void pvr2_destroy_render_buffers( void );7.7 +/**7.8 + * Preserve render buffers in main memory7.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.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 +10008.2 +++ b/src/pvr2/texcache.c Tue Mar 27 08:23:52 2012 +10008.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.11 @@ -142,14 +141,13 @@8.12 } else {8.13 texcache_have_palette_shader = FALSE;8.14 }8.15 - texcache_have_bgra = isGLBGRATextureSupported();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.26 /**8.27 @@ -252,73 +250,6 @@8.28 }8.30 /**8.31 - * Convert BGRA data in buffer to RGBA format (for systems that don't natively8.32 - * support BGRA).8.33 - * @return converted format type8.34 - * @param data BGRA pixel data8.35 - * @param nPixels total number of pixels (width*height)8.36 - * @param glFormatType GL format of source data. One of8.37 - * GL_UNSIGNED_SHORT_1_5_5_5_REV, GL_UNSIGNED_SHORT_4_4_4_4_REV, or GL_UNSIGNED_BYTE8.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 with8.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 the8.99 * banking done by the PVR2 for 8-bit textures, and also ensures that we8.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.109 switch( texcache_palette_mode ) {8.110 @@ -356,27 +287,17 @@8.111 }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.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 else8.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.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;
.