filename | src/drivers/video_gl.c |
changeset | 1282:9f445c5e252b |
prev | 1262:4baa34eee6fc |
next | 1298:d0eb2307b847 |
author | nkeynes |
date | Tue Mar 27 08:23:52 2012 +1000 (11 years ago) |
permissions | -rw-r--r-- |
last change | 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. |
file | annotate | diff | log | raw |
1.1 --- a/src/drivers/video_gl.c Mon Mar 05 22:20:33 2012 +10001.2 +++ b/src/drivers/video_gl.c Tue Mar 27 08:23:52 2012 +10001.3 @@ -16,6 +16,7 @@1.4 * GNU General Public License for more details.1.5 */1.7 +#include <assert.h>1.8 #include <sys/time.h>1.10 #include "display.h"1.11 @@ -24,11 +25,6 @@1.12 #include "pvr2/shaders.h"1.13 #include "drivers/video_gl.h"1.15 -/* FIXME: Need to actually handle this case */1.16 -#ifndef GL_PACK_ROW_LENGTH1.17 -#define glPixelStorei(key,val)1.18 -#endif1.19 -1.20 uint32_t video_width, video_height;1.21 struct video_vertex {1.22 float x,y;1.23 @@ -204,21 +200,6 @@1.24 glFlush();1.25 }1.27 -gboolean gl_load_frame_buffer( frame_buffer_t frame, int tex_id )1.28 -{1.29 - GLenum type = colour_formats[frame->colour_format].type;1.30 - GLenum format = colour_formats[frame->colour_format].format;1.31 - int bpp = colour_formats[frame->colour_format].bpp;1.32 - int rowstride = (frame->rowstride / bpp) - frame->width;1.33 -1.34 - glPixelStorei( GL_UNPACK_ROW_LENGTH, rowstride );1.35 - glBindTexture( GL_TEXTURE_2D, tex_id );1.36 - glTexSubImage2D( GL_TEXTURE_2D, 0, 0,0,1.37 - frame->width, frame->height, format, type, frame->data );1.38 - glPixelStorei( GL_UNPACK_ROW_LENGTH, 0 );1.39 - return TRUE;1.40 -}1.41 -1.42 void gl_display_blank( uint32_t colour )1.43 {1.44 /* Set the video_box background colour */1.45 @@ -239,6 +220,232 @@1.46 glFlush();1.47 }1.49 +1.50 +#ifdef HAVE_GLES21.51 +/* Note: OpenGL ES only officialy supports glReadPixels for the RGBA32 format1.52 + * (and doesn't necessarily support glPixelStore(GL_PACK_ROW_LENGTH) either.1.53 + * As a result, we end up needed to do the format conversion ourselves.1.54 + */1.55 +1.56 +/**1.57 + * Swizzle 32-bit RGBA to specified target format, truncating components where1.58 + * necessary. Target may == source.1.59 + * @param target destination buffer1.60 + * @param Source buffer, which must be in 8-bit-per-component RGBA format, fully packed.1.61 + * @param width width of image in pixels1.62 + * @param height height of image in pixels1.63 + * @param target_stride Stride of target buffer, in bytes1.64 + * @param colour_format1.65 + */1.66 +static void rgba32_to_target( unsigned char *target, const uint32_t *source, int width, int height, int target_stride, int colour_format )1.67 +{1.68 + int x,y;1.69 +1.70 + if( target_stride == 0 )1.71 + target_stride = width * colour_formats[colour_format].bpp;1.72 +1.73 + switch( colour_format ) {1.74 + case COLFMT_BGRA1555:1.75 + for( y=0; y<height; y++ ) {1.76 + uint16_t *d = (uint16_t *)target;1.77 + for( x=0; x<width; x++ ) {1.78 + uint32_t v = *source++;1.79 + *d++ = (uint16_t)( ((v & 0x80000000) >> 16) | ((v & 0x00F80000) >> 19) |1.80 + ((v & 0x0000F800)>>6) | ((v & 0x000000F8) << 7) );1.81 + }1.82 + target += target_stride;1.83 + }1.84 + break;1.85 + case COLFMT_RGB565:1.86 + for( y=0; y<height; y++ ) {1.87 + uint16_t *d = (uint16_t *)target;1.88 + for( x=0; x<width; x++ ) {1.89 + uint32_t v = *source++;1.90 + *d++ = (uint16_t)( ((v & 0x00F80000) >> 19) | ((v & 0x0000FC00) >> 5) | ((v & 0x000000F8)<<8) );1.91 + }1.92 + target += target_stride;1.93 + }1.94 + break;1.95 + case COLFMT_BGRA4444:1.96 + for( y=0; y<height; y++ ) {1.97 + uint16_t *d = (uint16_t *)target;1.98 + for( x=0; x<width; x++ ) {1.99 + uint32_t v = *source++;1.100 + *d++ = (uint16_t)( ((v & 0xF0000000) >> 16) | ((v & 0x00F00000) >> 20) |1.101 + ((v & 0x0000F000) >> 8) | ((v & 0x000000F0)<<4) );1.102 + }1.103 + target += target_stride;1.104 + }1.105 + break;1.106 + case COLFMT_BGRA8888:1.107 + for( y=0; y<height; y++ ) {1.108 + uint32_t *d = (uint32_t *)target;1.109 + for( x=0; x<width; x++ ) {1.110 + uint32_t v = *source++;1.111 + *d++ = (v & 0xFF00FF00) | ((v & 0x00FF0000) >> 16) | ((v & 0x000000FF)<<16);1.112 + }1.113 + target += target_stride;1.114 + }1.115 + break;1.116 + case COLFMT_BGR0888:1.117 + for( y=0; y<height; y++ ) {1.118 + uint32_t *d = (uint32_t *)target;1.119 + for( x=0; x<width; x++ ) {1.120 + uint32_t v = *source++;1.121 + *d++ = ((v & 0x00FF0000) >> 16) | (v & 0x0000FF00) | ((v & 0x000000FF)<<16);1.122 + }1.123 + target += target_stride;1.124 + }1.125 + break;1.126 + case COLFMT_BGR888:1.127 + for( y=0; y<height; y++ ) {1.128 + uint8_t *d = (uint8_t *)target;1.129 + for( x=0; x<width; x++ ) {1.130 + uint32_t v = *source++;1.131 + *d++ = (uint8_t)(v >> 16);1.132 + *d++ = (uint8_t)(v >> 8);1.133 + *d++ = (uint8_t)(v);1.134 + }1.135 + target += target_stride;1.136 + }1.137 + break;1.138 + case COLFMT_RGB888:1.139 + for( y=0; y<height; y++ ) {1.140 + uint8_t *d = (uint8_t *)target;1.141 + for( x=0; x<width; x++ ) {1.142 + uint32_t v = *source++;1.143 + *d++ = (uint8_t)(v);1.144 + *d++ = (uint8_t)(v >> 8);1.145 + *d++ = (uint8_t)(v >> 16);1.146 + }1.147 + target += target_stride;1.148 + }1.149 + break;1.150 + default:1.151 + assert( 0 && "Unsupported colour format" );1.152 + }1.153 +}1.154 +1.155 +/**1.156 + * Convert data into an acceptable form for loading into an RGBA texture.1.157 + */1.158 +static int target_to_rgba( uint32_t *target, const unsigned char *source, int width, int height, int source_stride, int colour_format )1.159 +{1.160 + int x,y;1.161 + uint16_t *d;1.162 + switch( colour_format ) {1.163 + case COLFMT_BGRA1555:1.164 + d = (uint16_t *)target;1.165 + for( y=0; y<height; y++ ) {1.166 + uint16_t *s = (uint16_t *)source;1.167 + for( x=0; x<width; x++ ) {1.168 + uint16_t v = *s++;1.169 + *d++ = (v >> 15) | (v<<1);1.170 + }1.171 + source += source_stride;1.172 + }1.173 + return GL_UNSIGNED_SHORT_5_5_5_1;1.174 + break;1.175 + case COLFMT_RGB565:1.176 + /* Need to expand to RGBA32 in order to have room for an alpha component */1.177 + for( y=0; y<height; y++ ) {1.178 + uint16_t *s = (uint16_t *)source;1.179 + for( x=0; x<width; x++ ) {1.180 + uint32_t v = (uint32_t)*s++;1.181 + *target++ = ((v & 0xF800)>>8) | ((v & 0x07E0) <<5) | ((v & 0x001F) << 19) |1.182 + ((v & 0xE000) >> 13) | ((v &0x0600) >> 1) | ((v & 0x001C) << 14);1.183 + }1.184 + source += source_stride;1.185 + }1.186 + return GL_UNSIGNED_BYTE;1.187 + case COLFMT_BGRA4444:1.188 + d = (uint16_t *)target;1.189 + for( y=0; y<height; y++ ) {1.190 + uint16_t *s = (uint16_t *)source;1.191 + for( x=0; x<width; x++ ) {1.192 + uint16_t v = *s++;1.193 + *d++ = (v >> 12) | (v<<4);1.194 + }1.195 + source += source_stride;1.196 + }1.197 + return GL_UNSIGNED_SHORT_4_4_4_4;1.198 + case COLFMT_RGB888:1.199 + for( y=0; y<height; y++ ) {1.200 + uint8_t *s = (uint8_t *)source;1.201 + for( x=0; x<width; x++ ) {1.202 + *target++ = s[0] | (s[1]<<8) | (s[2]<<16);1.203 + s += 3;1.204 + }1.205 + source += source_stride;1.206 + }1.207 + return GL_UNSIGNED_BYTE;1.208 + case COLFMT_BGRA8888:1.209 + for( y=0; y<height; y++ ) {1.210 + uint32_t *s = (uint32_t *)source;1.211 + for( x=0; x<width; x++ ) {1.212 + uint32_t v = (uint32_t)*s++;1.213 + *target++ = (v & 0xFF00FF00) | ((v & 0x00FF0000) >> 16) | ((v & 0x000000FF) << 16);1.214 + }1.215 + source += source_stride;1.216 + }1.217 + return GL_UNSIGNED_BYTE;1.218 + case COLFMT_BGR0888:1.219 + for( y=0; y<height; y++ ) {1.220 + uint32_t *s = (uint32_t *)source;1.221 + for( x=0; x<width; x++ ) {1.222 + uint32_t v = (uint32_t)*s++;1.223 + *target++ = (v & 0x0000FF00) | ((v & 0x00FF0000) >> 16) | ((v & 0x000000FF) << 16);1.224 + }1.225 + source += source_stride;1.226 + }1.227 + return GL_UNSIGNED_BYTE;1.228 + case COLFMT_BGR888:1.229 + for( y=0; y<height; y++ ) {1.230 + uint8_t *s = (uint8_t *)source;1.231 + for( x=0; x<width; x++ ) {1.232 + *target++ = s[2] | (s[1]<<8) | (s[0]<<16);1.233 + s += 3;1.234 + }1.235 + source += source_stride;1.236 + }1.237 + return GL_UNSIGNED_BYTE;1.238 + default:1.239 + assert( 0 && "Unsupported colour format" );1.240 + }1.241 +1.242 +1.243 +}1.244 +1.245 +1.246 +gboolean gl_read_render_buffer( unsigned char *target, render_buffer_t buffer,1.247 + int rowstride, int colour_format )1.248 +{1.249 + if( colour_formats[colour_format].bpp == 4 && (rowstride == 0 || rowstride == buffer->width*4) ) {1.250 + glReadPixels( 0, 0, buffer->width, buffer->height, GL_RGBA, GL_UNSIGNED_BYTE, target );1.251 + rgba32_to_target( target, (uint32_t *)target, buffer->width, buffer->height, rowstride, colour_format );1.252 + } else {1.253 + int size = buffer->width * buffer->height;1.254 + uint32_t tmp[size];1.255 +1.256 + glReadPixels( 0, 0, buffer->width, buffer->height, GL_RGBA, GL_UNSIGNED_BYTE, tmp );1.257 + rgba32_to_target( target, tmp, buffer->width, buffer->height, rowstride, colour_format );1.258 + }1.259 + return TRUE;1.260 +}1.261 +1.262 +gboolean gl_load_frame_buffer( frame_buffer_t frame, int tex_id )1.263 +{1.264 + int size = frame->width * frame->height;1.265 + uint32_t tmp[size];1.266 +1.267 + GLenum type = target_to_rgba( tmp, frame->data, frame->width, frame->height, frame->rowstride, frame->colour_format );1.268 + glBindTexture( GL_TEXTURE_2D, tex_id );1.269 + glTexSubImage2D( GL_TEXTURE_2D, 0, 0,0, frame->width, frame->height, GL_RGBA, type, tmp );1.270 + gl_check_error("gl_load_frame_buffer:glTexSubImage2DBGRA");1.271 + return TRUE;1.272 +}1.273 +1.274 +#else1.275 /**1.276 * Generic GL read_render_buffer. This function assumes that the caller1.277 * has already set the appropriate glReadBuffer(); in other words, unless1.278 @@ -259,6 +466,23 @@1.279 return TRUE;1.280 }1.282 +gboolean gl_load_frame_buffer( frame_buffer_t frame, int tex_id )1.283 +{1.284 + GLenum type = colour_formats[frame->colour_format].type;1.285 + GLenum format = colour_formats[frame->colour_format].format;1.286 + int bpp = colour_formats[frame->colour_format].bpp;1.287 + int rowstride = (frame->rowstride / bpp) - frame->width;1.288 +1.289 + glPixelStorei( GL_UNPACK_ROW_LENGTH, rowstride );1.290 + glBindTexture( GL_TEXTURE_2D, tex_id );1.291 + glTexSubImage2DBGRA( 0, 0,0,1.292 + frame->width, frame->height, format, type, frame->data, FALSE );1.293 + glPixelStorei( GL_UNPACK_ROW_LENGTH, 0 );1.294 + return TRUE;1.295 +}1.296 +#endif1.297 +1.298 +1.299 gboolean gl_init_driver( display_driver_t driver, gboolean need_fbo )1.300 {1.301 /* Use framebuffer objects if available */1.302 @@ -282,6 +506,7 @@1.303 gl_vbo_init(driver);1.305 driver->capabilities.has_gl = TRUE;1.306 + driver->capabilities.has_bgra = isGLBGRATextureSupported();1.307 return TRUE;1.308 }
.