Mercurial > sdl-ios-xcode
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 |