diff src/video/svga/SDL_svgavideo.c @ 1556:011b633fa0c9

Fixed bug #84 Actually implemented banked update for SVGAlib
author Sam Lantinga <slouken@libsdl.org>
date Sun, 19 Mar 2006 19:03:40 +0000
parents 0ca607a5d173
children 782fd950bd46 c121d94672cb a1b03ba2fcd0
line wrap: on
line diff
--- a/src/video/svga/SDL_svgavideo.c	Sun Mar 19 12:05:16 2006 +0000
+++ b/src/video/svga/SDL_svgavideo.c	Sun Mar 19 19:03:40 2006 +0000
@@ -40,7 +40,6 @@
 #include <vga.h>
 #include <vgamouse.h>
 #include <vgakeyboard.h>
-#include <vgagl.h>
 
 #include "SDL_video.h"
 #include "SDL_mouse.h"
@@ -51,9 +50,6 @@
 #include "SDL_svgaevents_c.h"
 #include "SDL_svgamouse_c.h"
 
-static GraphicsContext *realgc = NULL;
-static GraphicsContext *virtgc = NULL;
-
 /* Initialization/Query functions */
 static int SVGA_VideoInit(_THIS, SDL_PixelFormat *vformat);
 static SDL_Rect **SVGA_ListModes(_THIS, SDL_PixelFormat *format, Uint32 flags);
@@ -162,58 +158,56 @@
 	SVGA_Available, SVGA_CreateDevice
 };
 
-static int SVGA_AddMode(_THIS, int mode, int actually_add, int force)
+static int SVGA_AddMode(_THIS, int mode, int actually_add)
 {
+	int i, j;
 	vga_modeinfo *modeinfo;
 
 	modeinfo = vga_getmodeinfo(mode);
-	if ( force || ( modeinfo->flags & CAPABLE_LINEAR ) ) {
-		int i, j;
 
-		i = modeinfo->bytesperpixel-1;
-		if ( i < 0 ) {
-			return 0;
-		}
-		if ( actually_add ) {
-			SDL_Rect saved_rect[2];
-			int      saved_mode[2];
-			int b;
+	i = modeinfo->bytesperpixel-1;
+	if ( i < 0 ) {
+		return 0;
+	}
+	if ( actually_add ) {
+		SDL_Rect saved_rect[2];
+		int      saved_mode[2];
+		int b;
 
-			/* Add the mode, sorted largest to smallest */
-			b = 0;
-			j = 0;
-			while ( (SDL_modelist[i][j]->w > modeinfo->width) ||
-			        (SDL_modelist[i][j]->h > modeinfo->height) ) {
-				++j;
-			}
-			/* Skip modes that are already in our list */
-			if ( (SDL_modelist[i][j]->w == modeinfo->width) &&
-			     (SDL_modelist[i][j]->h == modeinfo->height) ) {
-				return(0);
-			}
-			/* Insert the new mode */
-			saved_rect[b] = *SDL_modelist[i][j];
-			saved_mode[b] = SDL_vgamode[i][j];
-			SDL_modelist[i][j]->w = modeinfo->width;
-			SDL_modelist[i][j]->h = modeinfo->height;
-			SDL_vgamode[i][j] = mode;
-			/* Everybody scoot down! */
-			if ( saved_rect[b].w && saved_rect[b].h ) {
-			    for ( ++j; SDL_modelist[i][j]->w; ++j ) {
-				saved_rect[!b] = *SDL_modelist[i][j];
-				saved_mode[!b] = SDL_vgamode[i][j];
-				*SDL_modelist[i][j] = saved_rect[b];
-				SDL_vgamode[i][j] = saved_mode[b];
-				b = !b;
-			    }
-			    *SDL_modelist[i][j] = saved_rect[b];
-			    SDL_vgamode[i][j] = saved_mode[b];
-			}
-		} else {
-			++SDL_nummodes[i];
+		/* Add the mode, sorted largest to smallest */
+		b = 0;
+		j = 0;
+		while ( (SDL_modelist[i][j]->w > modeinfo->width) ||
+			(SDL_modelist[i][j]->h > modeinfo->height) ) {
+			++j;
+		}
+		/* Skip modes that are already in our list */
+		if ( (SDL_modelist[i][j]->w == modeinfo->width) &&
+		     (SDL_modelist[i][j]->h == modeinfo->height) ) {
+			return(0);
 		}
+		/* Insert the new mode */
+		saved_rect[b] = *SDL_modelist[i][j];
+		saved_mode[b] = SDL_vgamode[i][j];
+		SDL_modelist[i][j]->w = modeinfo->width;
+		SDL_modelist[i][j]->h = modeinfo->height;
+		SDL_vgamode[i][j] = mode;
+		/* Everybody scoot down! */
+		if ( saved_rect[b].w && saved_rect[b].h ) {
+		    for ( ++j; SDL_modelist[i][j]->w; ++j ) {
+			saved_rect[!b] = *SDL_modelist[i][j];
+			saved_mode[!b] = SDL_vgamode[i][j];
+			*SDL_modelist[i][j] = saved_rect[b];
+			SDL_vgamode[i][j] = saved_mode[b];
+			b = !b;
+		    }
+		    *SDL_modelist[i][j] = saved_rect[b];
+		    SDL_vgamode[i][j] = saved_mode[b];
+		}
+	} else {
+		++SDL_nummodes[i];
 	}
-	return( force || ( modeinfo->flags & CAPABLE_LINEAR ) );
+	return(1);
 }
 
 static void SVGA_UpdateVideoInfo(_THIS)
@@ -221,7 +215,7 @@
 	vga_modeinfo *modeinfo;
 
 	this->info.wm_available = 0;
-	this->info.hw_available = (virtgc ? 0 : 1);
+	this->info.hw_available = (banked ? 0 : 1);
 	modeinfo = vga_getmodeinfo(vga_getcurrentmode());
 	this->info.video_mem = modeinfo->memory;
 	/* FIXME: Add hardware accelerated blit information */
@@ -274,12 +268,12 @@
 	total_modes = 0;
 	for ( mode=vga_lastmodenumber(); mode; --mode ) {
 		if ( vga_hasmode(mode) ) {
-			if ( SVGA_AddMode(this, mode, 0, 1) ) {
+			if ( SVGA_AddMode(this, mode, 0) ) {
 				++total_modes;
 			}
 		}
 	}
-	if ( SVGA_AddMode(this, G320x200x256, 0, 1) ) ++total_modes;
+	if ( SVGA_AddMode(this, G320x200x256, 0) ) ++total_modes;
 	if ( total_modes == 0 ) {
 		SDL_SetError("No linear video modes available");
 		return(-1);
@@ -308,10 +302,10 @@
 	}
 	for ( mode=vga_lastmodenumber(); mode; --mode ) {
 		if ( vga_hasmode(mode) ) {
-			SVGA_AddMode(this, mode, 1, 1);
+			SVGA_AddMode(this, mode, 1);
 		}
 	}
-	SVGA_AddMode(this, G320x200x256, 1, 1);
+	SVGA_AddMode(this, G320x200x256, 1);
 
 	/* Free extra (duplicated) modes */
 	for ( i=0; i<NUM_MODELISTS; ++i ) {
@@ -350,16 +344,10 @@
 	vga_modeinfo *modeinfo;
 	int screenpage_len;
 
-	/* Clean up old video mode data */
-	if ( realgc ) {
-		free(realgc);
-		realgc = NULL;
-	}
-	if ( virtgc ) {
-		/* FIXME: Why does this crash?
-		gl_freecontext(virtgc);*/
-		free(virtgc);
-		virtgc = NULL;
+	/* Free old pixels if we were in banked mode */
+	if ( banked && current->pixels ) {
+		free(current->pixels);
+		current->pixels = NULL;
 	}
 
 	/* Try to set the requested linear video mode */
@@ -379,15 +367,9 @@
 	vga_setpage(0);
 
 	if ( (vga_setlinearaddressing() < 0) && (vgamode != G320x200x256) ) {
-		gl_setcontextvga(vgamode);
-		realgc = gl_allocatecontext();
-		gl_getcontext(realgc);
-    
-		gl_setcontextvgavirtual(vgamode);
-		virtgc = gl_allocatecontext();
-		gl_getcontext(virtgc);
-    
-		flags &= ~SDL_DOUBLEBUF;
+		banked = 1;
+	} else {
+		banked = 0;
 	}
     
 	modeinfo = vga_getmodeinfo(SDL_vgamode[bpp][mode]);
@@ -406,9 +388,7 @@
 
 	/* Set up the new mode framebuffer */
 	current->flags = SDL_FULLSCREEN;
-	if ( virtgc ) {
-		current->flags |= SDL_SWSURFACE;
-	} else {
+	if ( !banked ) {
 		current->flags |= SDL_HWSURFACE;
 	}
 	if ( bpp == 8 ) {
@@ -418,14 +398,18 @@
 	current->w = width;
 	current->h = height;
 	current->pitch = modeinfo->linewidth;
-	if ( virtgc ) {
-		current->pixels = virtgc->vbuf;
+	if ( banked ) {
+		current->pixels = SDL_malloc(current->h * current->pitch);
+		if ( !current->pixels ) {
+			SDL_OutOfMemory();
+			return(NULL);
+		}
 	} else {
 		current->pixels = vga_getgraphmem();
 	}
 
 	/* set double-buffering */
-	if ( flags & SDL_DOUBLEBUF )
+	if ( (flags & SDL_DOUBLEBUF) && !banked )
 	{
 	    /* length of one screen page in bytes */
 	    screenpage_len=current->h*modeinfo->linewidth;
@@ -453,7 +437,7 @@
 	} 
 
 	/* Set the blit function */
-	if ( virtgc ) {
+	if ( banked ) {
 		this->UpdateRects = SVGA_BankedUpdate;
 	} else {
 		this->UpdateRects = SVGA_DirectUpdate;
@@ -489,7 +473,7 @@
 
 static int SVGA_FlipHWSurface(_THIS, SDL_Surface *surface)
 {
-	if ( !virtgc ) {
+	if ( !banked ) {
 		vga_setdisplaystart(flip_offset[flip_page]);
 		flip_page=!flip_page;
 		surface->pixels=flip_address[flip_page];
@@ -505,14 +489,50 @@
 
 static void SVGA_BankedUpdate(_THIS, int numrects, SDL_Rect *rects)
 {
-	int i;
+	int i, j;
 	SDL_Rect *rect;
+	int page, vp;
+	int x, y, w, h;
+	unsigned char *src;
+	unsigned char *dst;
+	int bpp = this->screen->format->BytesPerPixel;
+	int pitch = this->screen->pitch;
 
+	dst = vga_getgraphmem();
 	for ( i=0; i < numrects; ++i ) {
 		rect = &rects[i];
-		gl_copyboxtocontext(rect->x, rect->y, rect->w, rect->h, realgc, rect->x, rect->y);
+		x = rect->x;
+		y = rect->y;
+		w = rect->w * bpp;
+		h = rect->h;
+
+		vp = y * pitch + x * bpp;
+		src = (unsigned char *)this->screen->pixels + vp;
+		page = vp >> 16;
+		vp &= 0xffff;
+		vga_setpage(page);
+		for (j = 0; j < h; j++) {
+			if (vp + w > 0x10000) {
+				if (vp >= 0x10000) {
+					page++;
+					vga_setpage(page);
+					vp &= 0xffff;
+				} else {
+					SDL_memcpy(dst + vp, src, 0x10000 - vp);
+					page++;
+					vga_setpage(page);
+					SDL_memcpy(dst, src + 0x10000 - vp,
+						 (vp + w) & 0xffff);
+					vp = (vp + pitch) & 0xffff;
+					src += pitch;
+					continue;
+				}
+			}
+			SDL_memcpy(dst + vp, src, w);
+			src += pitch;
+			vp += pitch;
+		}
 	}
-	return;
 }
 
 int SVGA_SetColors(_THIS, int firstcolor, int ncolors, SDL_Color *colors)
@@ -537,16 +557,6 @@
 
 	/* Reset the console video mode */
 	if ( this->screen && (this->screen->w && this->screen->h) ) {
-		if ( realgc ) {
-			free(realgc);
-			realgc = NULL;
-		}
-		if ( virtgc ) {
-			/* FIXME: Why does this crash?
-			gl_freecontext(virtgc);*/
-			free(virtgc);
-			virtgc = NULL;
-		}
 		vga_setmode(TEXT);
 	}
 	keyboard_close();
@@ -564,8 +574,10 @@
 			SDL_vgamode[i] = NULL;
 		}
 	}
-	if ( this->screen && (this->screen->flags & SDL_HWSURFACE) ) {
-		/* Direct screen access, no memory buffer */
+	if ( this->screen ) {
+		if ( banked && this->screen->pixels ) {
+			SDL_free(this->screen->pixels);
+		}
 		this->screen->pixels = NULL;
 	}
 }