1.1 --- a/src/video/fbcon/SDL_fbvideo.c Sun Sep 27 23:22:57 2009 +0000
1.2 +++ b/src/video/fbcon/SDL_fbvideo.c Mon Sep 28 06:23:22 2009 +0000
1.3 @@ -126,6 +126,14 @@
1.4 { 1600, 1200,/*?*/0, 272, 48, 32, 5, 152, 5, 0, 0 }, /* 60 Hz */
1.5 #endif
1.6 };
1.7 +enum {
1.8 + FBCON_ROTATE_NONE = 0,
1.9 + FBCON_ROTATE_CCW = 90,
1.10 + FBCON_ROTATE_UD = 180,
1.11 + FBCON_ROTATE_CW = 270
1.12 +};
1.13 +
1.14 +#define min(a,b) ((a)<(b)?(a):(b))
1.15
1.16 /* Initialization/Query functions */
1.17 static int FB_VideoInit(_THIS, SDL_PixelFormat *vformat);
1.18 @@ -153,6 +161,10 @@
1.19 struct fb_var_screeninfo *vinfo);
1.20 static void FB_RestorePalette(_THIS);
1.21
1.22 +/* Shadow buffer functions */
1.23 +static FB_bitBlit FB_blit16;
1.24 +static FB_bitBlit FB_blit16blocked;
1.25 +
1.26 static int SDL_getpagesize(void)
1.27 {
1.28 #ifdef HAVE_GETPAGESIZE
1.29 @@ -491,6 +503,7 @@
1.30 unsigned int current_w;
1.31 unsigned int current_h;
1.32 const char *SDL_fbdev;
1.33 + const char *rotation;
1.34 FILE *modesdb;
1.35
1.36 /* Initialize the library */
1.37 @@ -619,9 +632,55 @@
1.38 }
1.39 }
1.40
1.41 + rotate = FBCON_ROTATE_NONE;
1.42 + rotation = SDL_getenv("SDL_VIDEO_FBCON_ROTATION");
1.43 + if (rotation != NULL) {
1.44 + if (SDL_strlen(rotation) == 0) {
1.45 + shadow_fb = 0;
1.46 + rotate = FBCON_ROTATE_NONE;
1.47 +#ifdef FBCON_DEBUG
1.48 + printf("Not rotating, no shadow\n");
1.49 +#endif
1.50 + } else if (!SDL_strcmp(rotation, "NONE")) {
1.51 + shadow_fb = 1;
1.52 + rotate = FBCON_ROTATE_NONE;
1.53 +#ifdef FBCON_DEBUG
1.54 + printf("Not rotating, but still using shadow\n");
1.55 +#endif
1.56 + } else if (!SDL_strcmp(rotation, "CW")) {
1.57 + shadow_fb = 1;
1.58 + rotate = FBCON_ROTATE_CW;
1.59 +#ifdef FBCON_DEBUG
1.60 + printf("Rotating screen clockwise\n");
1.61 +#endif
1.62 + } else if (!SDL_strcmp(rotation, "CCW")) {
1.63 + shadow_fb = 1;
1.64 + rotate = FBCON_ROTATE_CCW;
1.65 +#ifdef FBCON_DEBUG
1.66 + printf("Rotating screen counter clockwise\n");
1.67 +#endif
1.68 + } else if (!SDL_strcmp(rotation, "UD")) {
1.69 + shadow_fb = 1;
1.70 + rotate = FBCON_ROTATE_UD;
1.71 +#ifdef FBCON_DEBUG
1.72 + printf("Rotating screen upside down\n");
1.73 +#endif
1.74 + } else {
1.75 + SDL_SetError("\"%s\" is not a valid value for "
1.76 + "SDL_VIDEO_FBCON_ROTATION", rotation);
1.77 + return(-1);
1.78 + }
1.79 + }
1.80 +
1.81 + if (rotate == FBCON_ROTATE_CW || rotate == FBCON_ROTATE_CCW) {
1.82 + current_w = vinfo.yres;
1.83 + current_h = vinfo.xres;
1.84 + } else {
1.85 + current_w = vinfo.xres;
1.86 + current_h = vinfo.yres;
1.87 + }
1.88 +
1.89 /* Query for the list of available video modes */
1.90 - current_w = vinfo.xres;
1.91 - current_h = vinfo.yres;
1.92 current_index = ((vinfo.bits_per_pixel+7)/8)-1;
1.93 modesdb = fopen(FB_MODES_DB, "r");
1.94 for ( i=0; i<NUM_MODELISTS; ++i ) {
1.95 @@ -635,9 +694,14 @@
1.96 for ( i=0; i<NUM_MODELISTS; ++i ) {
1.97 unsigned int w, h;
1.98
1.99 + if (rotate == FBCON_ROTATE_CW || rotate == FBCON_ROTATE_CCW) {
1.100 + w = vinfo.yres;
1.101 + h = vinfo.xres;
1.102 + } else {
1.103 + w = vinfo.xres;
1.104 + h = vinfo.yres;
1.105 + }
1.106 /* See if we are querying for the current mode */
1.107 - w = vinfo.xres;
1.108 - h = vinfo.yres;
1.109 if ( i == current_index ) {
1.110 if ( (current_w > w) || (current_h > h) ) {
1.111 /* Only check once */
1.112 @@ -657,9 +721,14 @@
1.113 for ( j=0; j<(sizeof(checkres)/sizeof(checkres[0])); ++j ) {
1.114 unsigned int w, h;
1.115
1.116 + if (rotate == FBCON_ROTATE_CW || rotate == FBCON_ROTATE_CCW) {
1.117 + w = checkres[j].h;
1.118 + h = checkres[j].w;
1.119 + } else {
1.120 + w = checkres[j].w;
1.121 + h = checkres[j].h;
1.122 + }
1.123 /* See if we are querying for the current mode */
1.124 - w = checkres[j].w;
1.125 - h = checkres[j].h;
1.126 if ( i == current_index ) {
1.127 if ( (current_w > w) || (current_h > h) ) {
1.128 /* Only check once */
1.129 @@ -674,12 +743,12 @@
1.130 }
1.131 }
1.132
1.133 - /* Fill in our hardware acceleration capabilities */
1.134 this->info.current_w = current_w;
1.135 this->info.current_h = current_h;
1.136 this->info.wm_available = 0;
1.137 - this->info.hw_available = 1;
1.138 - this->info.video_mem = finfo.smem_len/1024;
1.139 + this->info.hw_available = !shadow_fb;
1.140 + this->info.video_mem = shadow_fb ? 0 : finfo.smem_len/1024;
1.141 + /* Fill in our hardware acceleration capabilities */
1.142 if ( mapped_io ) {
1.143 switch (finfo.accel) {
1.144 case FB_ACCEL_MATROX_MGA2064W:
1.145 @@ -715,6 +784,14 @@
1.146 }
1.147 }
1.148
1.149 + if (shadow_fb) {
1.150 + shadow_mem = (char *)SDL_malloc(mapped_memlen);
1.151 + if (shadow_mem == NULL) {
1.152 + SDL_SetError("No memory for shadow");
1.153 + return (-1);
1.154 + }
1.155 + }
1.156 +
1.157 /* Enable mouse and keyboard support */
1.158 if ( FB_OpenKeyboard(this) < 0 ) {
1.159 FB_VideoQuit(this);
1.160 @@ -947,6 +1024,11 @@
1.161 fprintf(stderr, "Printing original vinfo:\n");
1.162 print_vinfo(&vinfo);
1.163 #endif
1.164 + /* Do not use double buffering with shadow buffer */
1.165 + if (shadow_fb) {
1.166 + flags &= ~SDL_DOUBLEBUF;
1.167 + }
1.168 +
1.169 if ( (vinfo.xres != width) || (vinfo.yres != height) ||
1.170 (vinfo.bits_per_pixel != bpp) || (flags & SDL_DOUBLEBUF) ) {
1.171 vinfo.activate = FB_ACTIVATE_NOW;
1.172 @@ -973,7 +1055,8 @@
1.173 fprintf(stderr, "Printing wanted vinfo:\n");
1.174 print_vinfo(&vinfo);
1.175 #endif
1.176 - if ( ioctl(console_fd, FBIOPUT_VSCREENINFO, &vinfo) < 0 ) {
1.177 + if ( !shadow_fb &&
1.178 + ioctl(console_fd, FBIOPUT_VSCREENINFO, &vinfo) < 0 ) {
1.179 vinfo.yres_virtual = height;
1.180 if ( ioctl(console_fd, FBIOPUT_VSCREENINFO, &vinfo) < 0 ) {
1.181 SDL_SetError("Couldn't set console screen info");
1.182 @@ -1029,26 +1112,54 @@
1.183 /* Save hardware palette, if needed */
1.184 FB_SavePalette(this, &finfo, &vinfo);
1.185
1.186 + if (shadow_fb) {
1.187 + if (vinfo.bits_per_pixel == 16) {
1.188 + blitFunc = (rotate == FBCON_ROTATE_NONE ||
1.189 + rotate == FBCON_ROTATE_UD) ?
1.190 + FB_blit16 : FB_blit16blocked;
1.191 + } else {
1.192 + fprintf(stderr, "Init vinfo:\n");
1.193 + print_vinfo(&vinfo);
1.194 + SDL_SetError("Using software buffer, but no blitter "
1.195 + "function is available for %d bpp.",
1.196 + vinfo.bits_per_pixel);
1.197 + return(NULL);
1.198 + }
1.199 + }
1.200 +
1.201 /* Set up the new mode framebuffer */
1.202 - current->flags = (SDL_FULLSCREEN|SDL_HWSURFACE);
1.203 + current->flags &= SDL_FULLSCREEN;
1.204 + if (shadow_fb) {
1.205 + current->flags |= SDL_SWSURFACE;
1.206 + } else {
1.207 + current->flags |= SDL_HWSURFACE;
1.208 + }
1.209 current->w = vinfo.xres;
1.210 current->h = vinfo.yres;
1.211 - current->pitch = finfo.line_length;
1.212 - current->pixels = mapped_mem+mapped_offset;
1.213 + if (shadow_fb) {
1.214 + current->pitch = current->w * ((vinfo.bits_per_pixel + 7) / 8);
1.215 + current->pixels = shadow_mem;
1.216 + physlinebytes = finfo.line_length;
1.217 + } else {
1.218 + current->pitch = finfo.line_length;
1.219 + current->pixels = mapped_mem+mapped_offset;
1.220 + }
1.221
1.222 /* Set up the information for hardware surfaces */
1.223 surfaces_mem = (char *)current->pixels +
1.224 - vinfo.yres_virtual*current->pitch;
1.225 - surfaces_len = (mapped_memlen-(surfaces_mem-mapped_mem));
1.226 + vinfo.yres_virtual*current->pitch;
1.227 + surfaces_len = (shadow_fb) ?
1.228 + 0 : (mapped_memlen-(surfaces_mem-mapped_mem));
1.229 +
1.230 FB_FreeHWSurfaces(this);
1.231 FB_InitHWSurfaces(this, current, surfaces_mem, surfaces_len);
1.232
1.233 /* Let the application know we have a hardware palette */
1.234 switch (finfo.visual) {
1.235 - case FB_VISUAL_PSEUDOCOLOR:
1.236 + case FB_VISUAL_PSEUDOCOLOR:
1.237 current->flags |= SDL_HWPALETTE;
1.238 break;
1.239 - default:
1.240 + default:
1.241 break;
1.242 }
1.243
1.244 @@ -1059,7 +1170,7 @@
1.245 flip_page = 0;
1.246 flip_address[0] = (char *)current->pixels;
1.247 flip_address[1] = (char *)current->pixels+
1.248 - current->h*current->pitch;
1.249 + current->h*current->pitch;
1.250 this->screen = current;
1.251 FB_FlipHWSurface(this, current);
1.252 this->screen = NULL;
1.253 @@ -1329,10 +1440,169 @@
1.254 return(0);
1.255 }
1.256
1.257 +static void FB_blit16(Uint8 *byte_src_pos, int src_right_delta, int src_down_delta,
1.258 + Uint8 *byte_dst_pos, int dst_linebytes, int width, int height)
1.259 +{
1.260 + int w;
1.261 + Uint16 *src_pos = (Uint16 *)byte_src_pos;
1.262 + Uint16 *dst_pos = (Uint16 *)byte_dst_pos;
1.263 +
1.264 + while (height) {
1.265 + Uint16 *src = src_pos;
1.266 + Uint16 *dst = dst_pos;
1.267 + for (w = width; w != 0; w--) {
1.268 + *dst = *src;
1.269 + src += src_right_delta;
1.270 + dst++;
1.271 + }
1.272 + dst_pos = (Uint16 *)((Uint8 *)dst_pos + dst_linebytes);
1.273 + src_pos += src_down_delta;
1.274 + height--;
1.275 + }
1.276 +}
1.277 +
1.278 +#define BLOCKSIZE_W 32
1.279 +#define BLOCKSIZE_H 32
1.280 +
1.281 +static void FB_blit16blocked(Uint8 *byte_src_pos, int src_right_delta, int src_down_delta,
1.282 + Uint8 *byte_dst_pos, int dst_linebytes, int width, int height)
1.283 +{
1.284 + int w;
1.285 + Uint16 *src_pos = (Uint16 *)byte_src_pos;
1.286 + Uint16 *dst_pos = (Uint16 *)byte_dst_pos;
1.287 +
1.288 + while (height > 0) {
1.289 + Uint16 *src = src_pos;
1.290 + Uint16 *dst = dst_pos;
1.291 + for (w = width; w > 0; w -= BLOCKSIZE_W) {
1.292 + FB_blit16((Uint8 *)src,
1.293 + src_right_delta,
1.294 + src_down_delta,
1.295 + (Uint8 *)dst,
1.296 + dst_linebytes,
1.297 + min(w, BLOCKSIZE_W),
1.298 + min(height, BLOCKSIZE_H));
1.299 + src += src_right_delta * BLOCKSIZE_W;
1.300 + dst += BLOCKSIZE_W;
1.301 + }
1.302 + dst_pos = (Uint16 *)((Uint8 *)dst_pos + dst_linebytes * BLOCKSIZE_H);
1.303 + src_pos += src_down_delta * BLOCKSIZE_H;
1.304 + height -= BLOCKSIZE_H;
1.305 + }
1.306 +}
1.307 +
1.308 static void FB_DirectUpdate(_THIS, int numrects, SDL_Rect *rects)
1.309 {
1.310 - /* The application is already updating the visible video memory */
1.311 - return;
1.312 + int width = cache_vinfo.xres;
1.313 + int height = cache_vinfo.yres;
1.314 + int bytes_per_pixel = (cache_vinfo.bits_per_pixel + 7) / 8;
1.315 + int i;
1.316 +
1.317 + if (!shadow_fb) {
1.318 + /* The application is already updating the visible video memory */
1.319 + return;
1.320 + }
1.321 +
1.322 + if (cache_vinfo.bits_per_pixel != 16) {
1.323 + SDL_SetError("Shadow copy only implemented for 16 bpp");
1.324 + return;
1.325 + }
1.326 +
1.327 + for (i = 0; i < numrects; i++) {
1.328 + int x1, y1, x2, y2;
1.329 + int scr_x1, scr_y1, scr_x2, scr_y2;
1.330 + int sha_x1, sha_y1;
1.331 + int shadow_right_delta; /* Address change when moving right in dest */
1.332 + int shadow_down_delta; /* Address change when moving down in dest */
1.333 + char *src_start;
1.334 + char *dst_start;
1.335 +
1.336 + x1 = rects[i].x;
1.337 + y1 = rects[i].y;
1.338 + x2 = x1 + rects[i].w;
1.339 + y2 = y1 + rects[i].h;
1.340 +
1.341 + if (x1 < 0) {
1.342 + x1 = 0;
1.343 + } else if (x1 > width) {
1.344 + x1 = width;
1.345 + }
1.346 + if (x2 < 0) {
1.347 + x2 = 0;
1.348 + } else if (x2 > width) {
1.349 + x2 = width;
1.350 + }
1.351 + if (y1 < 0) {
1.352 + y1 = 0;
1.353 + } else if (y1 > height) {
1.354 + y1 = height;
1.355 + }
1.356 + if (y2 < 0) {
1.357 + y2 = 0;
1.358 + } else if (y2 > height) {
1.359 + y2 = height;
1.360 + }
1.361 + if (x2 <= x1 || y2 <= y1) {
1.362 + continue;
1.363 + }
1.364 +
1.365 + switch (rotate) {
1.366 + case FBCON_ROTATE_NONE:
1.367 + sha_x1 = scr_x1 = x1;
1.368 + sha_y1 = scr_y1 = y1;
1.369 + scr_x2 = x2;
1.370 + scr_y2 = y2;
1.371 + shadow_right_delta = 1;
1.372 + shadow_down_delta = width;
1.373 + break;
1.374 + case FBCON_ROTATE_CCW:
1.375 + scr_x1 = y1;
1.376 + scr_y1 = width - x2;
1.377 + scr_x2 = y2;
1.378 + scr_y2 = width - x1;
1.379 + sha_x1 = x2 - 1;
1.380 + sha_y1 = y1;
1.381 + shadow_right_delta = width;
1.382 + shadow_down_delta = -1;
1.383 + break;
1.384 + case FBCON_ROTATE_UD:
1.385 + scr_x1 = width - x2;
1.386 + scr_y1 = height - y2;
1.387 + scr_x2 = width - x1;
1.388 + scr_y2 = height - y1;
1.389 + sha_x1 = x2 - 1;
1.390 + sha_y1 = y2 - 1;
1.391 + shadow_right_delta = -1;
1.392 + shadow_down_delta = -width;
1.393 + break;
1.394 + case FBCON_ROTATE_CW:
1.395 + scr_x1 = height - y2;
1.396 + scr_y1 = x1;
1.397 + scr_x2 = height - y1;
1.398 + scr_y2 = x2;
1.399 + sha_x1 = x1;
1.400 + sha_y1 = y2 - 1;
1.401 + shadow_right_delta = -width;
1.402 + shadow_down_delta = 1;
1.403 + break;
1.404 + default:
1.405 + SDL_SetError("Unknown rotation");
1.406 + return;
1.407 + }
1.408 +
1.409 + src_start = shadow_mem +
1.410 + (sha_y1 * width + sha_x1) * bytes_per_pixel;
1.411 + dst_start = mapped_mem + mapped_offset + scr_y1 * physlinebytes +
1.412 + scr_x1 * bytes_per_pixel;
1.413 +
1.414 + blitFunc((Uint8 *) src_start,
1.415 + shadow_right_delta,
1.416 + shadow_down_delta,
1.417 + (Uint8 *) dst_start,
1.418 + physlinebytes,
1.419 + scr_x2 - scr_x1,
1.420 + scr_y2 - scr_y1);
1.421 + }
1.422 }
1.423
1.424 #ifdef VGA16_FBCON_SUPPORT
2.1 --- a/src/video/fbcon/SDL_fbvideo.h Sun Sep 27 23:22:57 2009 +0000
2.2 +++ b/src/video/fbcon/SDL_fbvideo.h Mon Sep 28 06:23:22 2009 +0000
2.3 @@ -38,6 +38,14 @@
2.4 /* Hidden "this" pointer for the video functions */
2.5 #define _THIS SDL_VideoDevice *this
2.6
2.7 +typedef void FB_bitBlit(
2.8 + Uint8 *src_pos,
2.9 + int src_right_delta, /* pixels, not bytes */
2.10 + int src_down_delta, /* pixels, not bytes */
2.11 + Uint8 *dst_pos,
2.12 + int dst_linebytes,
2.13 + int width,
2.14 + int height);
2.15
2.16 /* This is the structure we use to keep track of video memory */
2.17 typedef struct vidmem_bucket {
2.18 @@ -69,12 +77,17 @@
2.19 #endif
2.20
2.21 char *mapped_mem;
2.22 + char *shadow_mem;
2.23 int mapped_memlen;
2.24 int mapped_offset;
2.25 char *mapped_io;
2.26 long mapped_iolen;
2.27 int flip_page;
2.28 char *flip_address[2];
2.29 + int rotate;
2.30 + int shadow_fb; /* Tells whether a shadow is being used. */
2.31 + FB_bitBlit *blitFunc;
2.32 + int physlinebytes; /* Length of a line in bytes in physical fb */
2.33
2.34 #define NUM_MODELISTS 4 /* 8, 16, 24, and 32 bits-per-pixel */
2.35 int SDL_nummodes[NUM_MODELISTS];
2.36 @@ -110,12 +123,17 @@
2.37 #define saved_cmaplen (this->hidden->saved_cmaplen)
2.38 #define saved_cmap (this->hidden->saved_cmap)
2.39 #define mapped_mem (this->hidden->mapped_mem)
2.40 +#define shadow_mem (this->hidden->shadow_mem)
2.41 #define mapped_memlen (this->hidden->mapped_memlen)
2.42 #define mapped_offset (this->hidden->mapped_offset)
2.43 #define mapped_io (this->hidden->mapped_io)
2.44 #define mapped_iolen (this->hidden->mapped_iolen)
2.45 #define flip_page (this->hidden->flip_page)
2.46 #define flip_address (this->hidden->flip_address)
2.47 +#define rotate (this->hidden->rotate)
2.48 +#define shadow_fb (this->hidden->shadow_fb)
2.49 +#define blitFunc (this->hidden->blitFunc)
2.50 +#define physlinebytes (this->hidden->physlinebytes)
2.51 #define SDL_nummodes (this->hidden->SDL_nummodes)
2.52 #define SDL_modelist (this->hidden->SDL_modelist)
2.53 #define surfaces (this->hidden->surfaces)