Search
lxdream.org :: lxdream/src/drivers/video_gl.c :: diff
lxdream 0.9.1
released Jun 29
Download Now
filename src/drivers/video_gl.c
changeset 1282:9f445c5e252b
prev1262:4baa34eee6fc
next1298:d0eb2307b847
author nkeynes
date Tue Mar 27 08:23:52 2012 +1000 (8 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 +1000
1.2 +++ b/src/drivers/video_gl.c Tue Mar 27 08:23:52 2012 +1000
1.3 @@ -16,6 +16,7 @@
1.4 * GNU General Public License for more details.
1.5 */
1.6
1.7 +#include <assert.h>
1.8 #include <sys/time.h>
1.9
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.14
1.15 -/* FIXME: Need to actually handle this case */
1.16 -#ifndef GL_PACK_ROW_LENGTH
1.17 -#define glPixelStorei(key,val)
1.18 -#endif
1.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.26
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.48
1.49 +
1.50 +#ifdef HAVE_GLES2
1.51 +/* Note: OpenGL ES only officialy supports glReadPixels for the RGBA32 format
1.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 where
1.58 + * necessary. Target may == source.
1.59 + * @param target destination buffer
1.60 + * @param Source buffer, which must be in 8-bit-per-component RGBA format, fully packed.
1.61 + * @param width width of image in pixels
1.62 + * @param height height of image in pixels
1.63 + * @param target_stride Stride of target buffer, in bytes
1.64 + * @param colour_format
1.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 +#else
1.275 /**
1.276 * Generic GL read_render_buffer. This function assumes that the caller
1.277 * has already set the appropriate glReadBuffer(); in other words, unless
1.278 @@ -259,6 +466,23 @@
1.279 return TRUE;
1.280 }
1.281
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 +#endif
1.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.304
1.305 driver->capabilities.has_gl = TRUE;
1.306 + driver->capabilities.has_bgra = isGLBGRATextureSupported();
1.307 return TRUE;
1.308 }
1.309
.