comparison 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
comparison
equal deleted inserted replaced
1555:780fd5b61df1 1556:011b633fa0c9
38 #error You must choose your operating system here 38 #error You must choose your operating system here
39 #endif 39 #endif
40 #include <vga.h> 40 #include <vga.h>
41 #include <vgamouse.h> 41 #include <vgamouse.h>
42 #include <vgakeyboard.h> 42 #include <vgakeyboard.h>
43 #include <vgagl.h>
44 43
45 #include "SDL_video.h" 44 #include "SDL_video.h"
46 #include "SDL_mouse.h" 45 #include "SDL_mouse.h"
47 #include "../SDL_sysvideo.h" 46 #include "../SDL_sysvideo.h"
48 #include "../SDL_pixels_c.h" 47 #include "../SDL_pixels_c.h"
49 #include "../../events/SDL_events_c.h" 48 #include "../../events/SDL_events_c.h"
50 #include "SDL_svgavideo.h" 49 #include "SDL_svgavideo.h"
51 #include "SDL_svgaevents_c.h" 50 #include "SDL_svgaevents_c.h"
52 #include "SDL_svgamouse_c.h" 51 #include "SDL_svgamouse_c.h"
53
54 static GraphicsContext *realgc = NULL;
55 static GraphicsContext *virtgc = NULL;
56 52
57 /* Initialization/Query functions */ 53 /* Initialization/Query functions */
58 static int SVGA_VideoInit(_THIS, SDL_PixelFormat *vformat); 54 static int SVGA_VideoInit(_THIS, SDL_PixelFormat *vformat);
59 static SDL_Rect **SVGA_ListModes(_THIS, SDL_PixelFormat *format, Uint32 flags); 55 static SDL_Rect **SVGA_ListModes(_THIS, SDL_PixelFormat *format, Uint32 flags);
60 static SDL_Surface *SVGA_SetVideoMode(_THIS, SDL_Surface *current, int width, int height, int bpp, Uint32 flags); 56 static SDL_Surface *SVGA_SetVideoMode(_THIS, SDL_Surface *current, int width, int height, int bpp, Uint32 flags);
160 VideoBootStrap SVGALIB_bootstrap = { 156 VideoBootStrap SVGALIB_bootstrap = {
161 "svgalib", "SVGAlib", 157 "svgalib", "SVGAlib",
162 SVGA_Available, SVGA_CreateDevice 158 SVGA_Available, SVGA_CreateDevice
163 }; 159 };
164 160
165 static int SVGA_AddMode(_THIS, int mode, int actually_add, int force) 161 static int SVGA_AddMode(_THIS, int mode, int actually_add)
166 { 162 {
163 int i, j;
167 vga_modeinfo *modeinfo; 164 vga_modeinfo *modeinfo;
168 165
169 modeinfo = vga_getmodeinfo(mode); 166 modeinfo = vga_getmodeinfo(mode);
170 if ( force || ( modeinfo->flags & CAPABLE_LINEAR ) ) { 167
171 int i, j; 168 i = modeinfo->bytesperpixel-1;
172 169 if ( i < 0 ) {
173 i = modeinfo->bytesperpixel-1; 170 return 0;
174 if ( i < 0 ) { 171 }
175 return 0; 172 if ( actually_add ) {
176 } 173 SDL_Rect saved_rect[2];
177 if ( actually_add ) { 174 int saved_mode[2];
178 SDL_Rect saved_rect[2]; 175 int b;
179 int saved_mode[2]; 176
180 int b; 177 /* Add the mode, sorted largest to smallest */
181 178 b = 0;
182 /* Add the mode, sorted largest to smallest */ 179 j = 0;
183 b = 0; 180 while ( (SDL_modelist[i][j]->w > modeinfo->width) ||
184 j = 0; 181 (SDL_modelist[i][j]->h > modeinfo->height) ) {
185 while ( (SDL_modelist[i][j]->w > modeinfo->width) || 182 ++j;
186 (SDL_modelist[i][j]->h > modeinfo->height) ) { 183 }
187 ++j; 184 /* Skip modes that are already in our list */
188 } 185 if ( (SDL_modelist[i][j]->w == modeinfo->width) &&
189 /* Skip modes that are already in our list */ 186 (SDL_modelist[i][j]->h == modeinfo->height) ) {
190 if ( (SDL_modelist[i][j]->w == modeinfo->width) && 187 return(0);
191 (SDL_modelist[i][j]->h == modeinfo->height) ) { 188 }
192 return(0); 189 /* Insert the new mode */
193 } 190 saved_rect[b] = *SDL_modelist[i][j];
194 /* Insert the new mode */ 191 saved_mode[b] = SDL_vgamode[i][j];
195 saved_rect[b] = *SDL_modelist[i][j]; 192 SDL_modelist[i][j]->w = modeinfo->width;
196 saved_mode[b] = SDL_vgamode[i][j]; 193 SDL_modelist[i][j]->h = modeinfo->height;
197 SDL_modelist[i][j]->w = modeinfo->width; 194 SDL_vgamode[i][j] = mode;
198 SDL_modelist[i][j]->h = modeinfo->height; 195 /* Everybody scoot down! */
199 SDL_vgamode[i][j] = mode; 196 if ( saved_rect[b].w && saved_rect[b].h ) {
200 /* Everybody scoot down! */ 197 for ( ++j; SDL_modelist[i][j]->w; ++j ) {
201 if ( saved_rect[b].w && saved_rect[b].h ) { 198 saved_rect[!b] = *SDL_modelist[i][j];
202 for ( ++j; SDL_modelist[i][j]->w; ++j ) { 199 saved_mode[!b] = SDL_vgamode[i][j];
203 saved_rect[!b] = *SDL_modelist[i][j]; 200 *SDL_modelist[i][j] = saved_rect[b];
204 saved_mode[!b] = SDL_vgamode[i][j]; 201 SDL_vgamode[i][j] = saved_mode[b];
205 *SDL_modelist[i][j] = saved_rect[b]; 202 b = !b;
206 SDL_vgamode[i][j] = saved_mode[b]; 203 }
207 b = !b; 204 *SDL_modelist[i][j] = saved_rect[b];
208 } 205 SDL_vgamode[i][j] = saved_mode[b];
209 *SDL_modelist[i][j] = saved_rect[b]; 206 }
210 SDL_vgamode[i][j] = saved_mode[b]; 207 } else {
211 } 208 ++SDL_nummodes[i];
212 } else { 209 }
213 ++SDL_nummodes[i]; 210 return(1);
214 }
215 }
216 return( force || ( modeinfo->flags & CAPABLE_LINEAR ) );
217 } 211 }
218 212
219 static void SVGA_UpdateVideoInfo(_THIS) 213 static void SVGA_UpdateVideoInfo(_THIS)
220 { 214 {
221 vga_modeinfo *modeinfo; 215 vga_modeinfo *modeinfo;
222 216
223 this->info.wm_available = 0; 217 this->info.wm_available = 0;
224 this->info.hw_available = (virtgc ? 0 : 1); 218 this->info.hw_available = (banked ? 0 : 1);
225 modeinfo = vga_getmodeinfo(vga_getcurrentmode()); 219 modeinfo = vga_getmodeinfo(vga_getcurrentmode());
226 this->info.video_mem = modeinfo->memory; 220 this->info.video_mem = modeinfo->memory;
227 /* FIXME: Add hardware accelerated blit information */ 221 /* FIXME: Add hardware accelerated blit information */
228 #ifdef SVGALIB_DEBUG 222 #ifdef SVGALIB_DEBUG
229 printf("Hardware accelerated blit: %savailable\n", modeinfo->haveblit ? "" : "not "); 223 printf("Hardware accelerated blit: %savailable\n", modeinfo->haveblit ? "" : "not ");
272 266
273 /* Enumerate the available fullscreen modes */ 267 /* Enumerate the available fullscreen modes */
274 total_modes = 0; 268 total_modes = 0;
275 for ( mode=vga_lastmodenumber(); mode; --mode ) { 269 for ( mode=vga_lastmodenumber(); mode; --mode ) {
276 if ( vga_hasmode(mode) ) { 270 if ( vga_hasmode(mode) ) {
277 if ( SVGA_AddMode(this, mode, 0, 1) ) { 271 if ( SVGA_AddMode(this, mode, 0) ) {
278 ++total_modes; 272 ++total_modes;
279 } 273 }
280 } 274 }
281 } 275 }
282 if ( SVGA_AddMode(this, G320x200x256, 0, 1) ) ++total_modes; 276 if ( SVGA_AddMode(this, G320x200x256, 0) ) ++total_modes;
283 if ( total_modes == 0 ) { 277 if ( total_modes == 0 ) {
284 SDL_SetError("No linear video modes available"); 278 SDL_SetError("No linear video modes available");
285 return(-1); 279 return(-1);
286 } 280 }
287 for ( i=0; i<NUM_MODELISTS; ++i ) { 281 for ( i=0; i<NUM_MODELISTS; ++i ) {
306 } 300 }
307 SDL_modelist[i][j] = NULL; 301 SDL_modelist[i][j] = NULL;
308 } 302 }
309 for ( mode=vga_lastmodenumber(); mode; --mode ) { 303 for ( mode=vga_lastmodenumber(); mode; --mode ) {
310 if ( vga_hasmode(mode) ) { 304 if ( vga_hasmode(mode) ) {
311 SVGA_AddMode(this, mode, 1, 1); 305 SVGA_AddMode(this, mode, 1);
312 } 306 }
313 } 307 }
314 SVGA_AddMode(this, G320x200x256, 1, 1); 308 SVGA_AddMode(this, G320x200x256, 1);
315 309
316 /* Free extra (duplicated) modes */ 310 /* Free extra (duplicated) modes */
317 for ( i=0; i<NUM_MODELISTS; ++i ) { 311 for ( i=0; i<NUM_MODELISTS; ++i ) {
318 j = 0; 312 j = 0;
319 while ( SDL_modelist[i][j] && SDL_modelist[i][j]->w ) { 313 while ( SDL_modelist[i][j] && SDL_modelist[i][j]->w ) {
348 int mode; 342 int mode;
349 int vgamode; 343 int vgamode;
350 vga_modeinfo *modeinfo; 344 vga_modeinfo *modeinfo;
351 int screenpage_len; 345 int screenpage_len;
352 346
353 /* Clean up old video mode data */ 347 /* Free old pixels if we were in banked mode */
354 if ( realgc ) { 348 if ( banked && current->pixels ) {
355 free(realgc); 349 free(current->pixels);
356 realgc = NULL; 350 current->pixels = NULL;
357 }
358 if ( virtgc ) {
359 /* FIXME: Why does this crash?
360 gl_freecontext(virtgc);*/
361 free(virtgc);
362 virtgc = NULL;
363 } 351 }
364 352
365 /* Try to set the requested linear video mode */ 353 /* Try to set the requested linear video mode */
366 bpp = (bpp+7)/8-1; 354 bpp = (bpp+7)/8-1;
367 for ( mode=0; SDL_modelist[bpp][mode]; ++mode ) { 355 for ( mode=0; SDL_modelist[bpp][mode]; ++mode ) {
377 vgamode = SDL_vgamode[bpp][mode]; 365 vgamode = SDL_vgamode[bpp][mode];
378 vga_setmode(vgamode); 366 vga_setmode(vgamode);
379 vga_setpage(0); 367 vga_setpage(0);
380 368
381 if ( (vga_setlinearaddressing() < 0) && (vgamode != G320x200x256) ) { 369 if ( (vga_setlinearaddressing() < 0) && (vgamode != G320x200x256) ) {
382 gl_setcontextvga(vgamode); 370 banked = 1;
383 realgc = gl_allocatecontext(); 371 } else {
384 gl_getcontext(realgc); 372 banked = 0;
385
386 gl_setcontextvgavirtual(vgamode);
387 virtgc = gl_allocatecontext();
388 gl_getcontext(virtgc);
389
390 flags &= ~SDL_DOUBLEBUF;
391 } 373 }
392 374
393 modeinfo = vga_getmodeinfo(SDL_vgamode[bpp][mode]); 375 modeinfo = vga_getmodeinfo(SDL_vgamode[bpp][mode]);
394 376
395 /* Update hardware acceleration info */ 377 /* Update hardware acceleration info */
404 return(NULL); 386 return(NULL);
405 } 387 }
406 388
407 /* Set up the new mode framebuffer */ 389 /* Set up the new mode framebuffer */
408 current->flags = SDL_FULLSCREEN; 390 current->flags = SDL_FULLSCREEN;
409 if ( virtgc ) { 391 if ( !banked ) {
410 current->flags |= SDL_SWSURFACE;
411 } else {
412 current->flags |= SDL_HWSURFACE; 392 current->flags |= SDL_HWSURFACE;
413 } 393 }
414 if ( bpp == 8 ) { 394 if ( bpp == 8 ) {
415 /* FIXME: What about DirectColor? */ 395 /* FIXME: What about DirectColor? */
416 current->flags |= SDL_HWPALETTE; 396 current->flags |= SDL_HWPALETTE;
417 } 397 }
418 current->w = width; 398 current->w = width;
419 current->h = height; 399 current->h = height;
420 current->pitch = modeinfo->linewidth; 400 current->pitch = modeinfo->linewidth;
421 if ( virtgc ) { 401 if ( banked ) {
422 current->pixels = virtgc->vbuf; 402 current->pixels = SDL_malloc(current->h * current->pitch);
403 if ( !current->pixels ) {
404 SDL_OutOfMemory();
405 return(NULL);
406 }
423 } else { 407 } else {
424 current->pixels = vga_getgraphmem(); 408 current->pixels = vga_getgraphmem();
425 } 409 }
426 410
427 /* set double-buffering */ 411 /* set double-buffering */
428 if ( flags & SDL_DOUBLEBUF ) 412 if ( (flags & SDL_DOUBLEBUF) && !banked )
429 { 413 {
430 /* length of one screen page in bytes */ 414 /* length of one screen page in bytes */
431 screenpage_len=current->h*modeinfo->linewidth; 415 screenpage_len=current->h*modeinfo->linewidth;
432 416
433 /* if start address should be aligned */ 417 /* if start address should be aligned */
451 SVGA_FlipHWSurface(this,current); 435 SVGA_FlipHWSurface(this,current);
452 } 436 }
453 } 437 }
454 438
455 /* Set the blit function */ 439 /* Set the blit function */
456 if ( virtgc ) { 440 if ( banked ) {
457 this->UpdateRects = SVGA_BankedUpdate; 441 this->UpdateRects = SVGA_BankedUpdate;
458 } else { 442 } else {
459 this->UpdateRects = SVGA_DirectUpdate; 443 this->UpdateRects = SVGA_DirectUpdate;
460 } 444 }
461 445
487 return; 471 return;
488 } 472 }
489 473
490 static int SVGA_FlipHWSurface(_THIS, SDL_Surface *surface) 474 static int SVGA_FlipHWSurface(_THIS, SDL_Surface *surface)
491 { 475 {
492 if ( !virtgc ) { 476 if ( !banked ) {
493 vga_setdisplaystart(flip_offset[flip_page]); 477 vga_setdisplaystart(flip_offset[flip_page]);
494 flip_page=!flip_page; 478 flip_page=!flip_page;
495 surface->pixels=flip_address[flip_page]; 479 surface->pixels=flip_address[flip_page];
496 vga_waitretrace(); 480 vga_waitretrace();
497 } 481 }
503 return; 487 return;
504 } 488 }
505 489
506 static void SVGA_BankedUpdate(_THIS, int numrects, SDL_Rect *rects) 490 static void SVGA_BankedUpdate(_THIS, int numrects, SDL_Rect *rects)
507 { 491 {
508 int i; 492 int i, j;
509 SDL_Rect *rect; 493 SDL_Rect *rect;
510 494 int page, vp;
495 int x, y, w, h;
496 unsigned char *src;
497 unsigned char *dst;
498 int bpp = this->screen->format->BytesPerPixel;
499 int pitch = this->screen->pitch;
500
501 dst = vga_getgraphmem();
511 for ( i=0; i < numrects; ++i ) { 502 for ( i=0; i < numrects; ++i ) {
512 rect = &rects[i]; 503 rect = &rects[i];
513 gl_copyboxtocontext(rect->x, rect->y, rect->w, rect->h, realgc, rect->x, rect->y); 504 x = rect->x;
514 } 505 y = rect->y;
515 return; 506 w = rect->w * bpp;
507 h = rect->h;
508
509 vp = y * pitch + x * bpp;
510 src = (unsigned char *)this->screen->pixels + vp;
511 page = vp >> 16;
512 vp &= 0xffff;
513 vga_setpage(page);
514 for (j = 0; j < h; j++) {
515 if (vp + w > 0x10000) {
516 if (vp >= 0x10000) {
517 page++;
518 vga_setpage(page);
519 vp &= 0xffff;
520 } else {
521 SDL_memcpy(dst + vp, src, 0x10000 - vp);
522 page++;
523 vga_setpage(page);
524 SDL_memcpy(dst, src + 0x10000 - vp,
525 (vp + w) & 0xffff);
526 vp = (vp + pitch) & 0xffff;
527 src += pitch;
528 continue;
529 }
530 }
531 SDL_memcpy(dst + vp, src, w);
532 src += pitch;
533 vp += pitch;
534 }
535 }
516 } 536 }
517 537
518 int SVGA_SetColors(_THIS, int firstcolor, int ncolors, SDL_Color *colors) 538 int SVGA_SetColors(_THIS, int firstcolor, int ncolors, SDL_Color *colors)
519 { 539 {
520 int i; 540 int i;
535 { 555 {
536 int i, j; 556 int i, j;
537 557
538 /* Reset the console video mode */ 558 /* Reset the console video mode */
539 if ( this->screen && (this->screen->w && this->screen->h) ) { 559 if ( this->screen && (this->screen->w && this->screen->h) ) {
540 if ( realgc ) {
541 free(realgc);
542 realgc = NULL;
543 }
544 if ( virtgc ) {
545 /* FIXME: Why does this crash?
546 gl_freecontext(virtgc);*/
547 free(virtgc);
548 virtgc = NULL;
549 }
550 vga_setmode(TEXT); 560 vga_setmode(TEXT);
551 } 561 }
552 keyboard_close(); 562 keyboard_close();
553 563
554 /* Free video mode lists */ 564 /* Free video mode lists */
562 if ( SDL_vgamode[i] != NULL ) { 572 if ( SDL_vgamode[i] != NULL ) {
563 SDL_free(SDL_vgamode[i]); 573 SDL_free(SDL_vgamode[i]);
564 SDL_vgamode[i] = NULL; 574 SDL_vgamode[i] = NULL;
565 } 575 }
566 } 576 }
567 if ( this->screen && (this->screen->flags & SDL_HWSURFACE) ) { 577 if ( this->screen ) {
568 /* Direct screen access, no memory buffer */ 578 if ( banked && this->screen->pixels ) {
579 SDL_free(this->screen->pixels);
580 }
569 this->screen->pixels = NULL; 581 this->screen->pixels = NULL;
570 } 582 }
571 } 583 }
572 584