|
|
1.1 ! root 1: /* ! 2: Hatari - hostscreen.c ! 3: ! 4: This file is distributed under the GNU Public License, version 2 or at ! 5: your option any later version. Read the file gpl.txt for details. ! 6: ! 7: Host video routines. This file originally came from the Aranym project but ! 8: has been thoroughly reworked for Hatari. However, integration with the rest ! 9: of the Hatari source code is still bad and needs a lot of improvement... ! 10: */ ! 11: const char HostScreen_rcsid[] = "Hatari $Id: hostscreen.c,v 1.13 2007/04/04 15:23:58 thothy Exp $"; ! 12: ! 13: #include "main.h" ! 14: #include "configuration.h" ! 15: #include "sysdeps.h" ! 16: #include "stMemory.h" ! 17: #include "ioMem.h" ! 18: #include "hostscreen.h" ! 19: #include "screen.h" ! 20: ! 21: #define VIDEL_DEBUG 0 ! 22: ! 23: #if VIDEL_DEBUG ! 24: #define Dprintf(a) printf a ! 25: #else ! 26: #define Dprintf(a) ! 27: #endif ! 28: ! 29: ! 30: #define RGB_BLACK 0x00000000 ! 31: #define RGB_BLUE 0x000000ff ! 32: #define RGB_GREEN 0x00ff0000 ! 33: #define RGB_CYAN 0x00ff00ff ! 34: #define RGB_RED 0xff000000 ! 35: #define RGB_MAGENTA 0xff0000ff ! 36: #define RGB_LTGRAY 0xbbbb00bb ! 37: #define RGB_GRAY 0x88880088 ! 38: #define RGB_LTBLUE 0x000000aa ! 39: #define RGB_LTGREEN 0x00aa0000 ! 40: #define RGB_LTCYAN 0x00aa00aa ! 41: #define RGB_LTRED 0xaa000000 ! 42: #define RGB_LTMAGENTA 0xaa0000aa ! 43: #define RGB_YELLOW 0xffff0000 ! 44: #define RGB_LTYELLOW 0xaaaa0000 ! 45: #define RGB_WHITE 0xffff00ff ! 46: ! 47: ! 48: static SDL_Surface *mainSurface; // The main window surface ! 49: static SDL_Surface *surf; // pointer to actual surface ! 50: ! 51: ! 52: static SDL_mutex *screenLock; ! 53: static uint32 sdl_videoparams; ! 54: static uint32 hs_width, hs_height, hs_bpp; ! 55: static BOOL doUpdate; // the HW surface is available -> the SDL need not to update the surface after ->pixel access ! 56: ! 57: static struct { // TOS palette (bpp < 16) to SDL color mapping ! 58: SDL_Color standard[256]; ! 59: uint32 native[256]; ! 60: } palette; ! 61: ! 62: ! 63: static const unsigned long default_palette[] = { ! 64: RGB_WHITE, RGB_RED, RGB_GREEN, RGB_YELLOW, ! 65: RGB_BLUE, RGB_MAGENTA, RGB_CYAN, RGB_LTGRAY, ! 66: RGB_GRAY, RGB_LTRED, RGB_LTGREEN, RGB_LTYELLOW, ! 67: RGB_LTBLUE, RGB_LTMAGENTA, RGB_LTCYAN, RGB_BLACK ! 68: }; ! 69: ! 70: static int HostScreen_selectVideoMode(SDL_Rect **modes, uint32 *width, uint32 *height); ! 71: static void HostScreen_searchVideoMode( uint32 *width, uint32 *height, uint32 *bpp ); ! 72: ! 73: ! 74: void HostScreen_Init(void) { ! 75: int i; ! 76: for(i=0; i<256; i++) { ! 77: unsigned long color = default_palette[i%16]; ! 78: palette.standard[i].r = color >> 24; ! 79: palette.standard[i].g = (color >> 16) & 0xff; ! 80: palette.standard[i].b = color & 0xff; ! 81: } ! 82: ! 83: screenLock = SDL_CreateMutex(); ! 84: ! 85: mainSurface=NULL; ! 86: } ! 87: ! 88: void HostScreen_UnInit(void) { ! 89: SDL_DestroyMutex(screenLock); ! 90: } ! 91: ! 92: ! 93: void HostScreen_toggleFullScreen(void) ! 94: { ! 95: sdl_videoparams ^= SDL_FULLSCREEN; ! 96: if(SDL_WM_ToggleFullScreen(mainSurface) == 0) { ! 97: // SDL_WM_ToggleFullScreen() did not work. ! 98: // We have to change video mode "by hand". ! 99: SDL_Surface *temp = SDL_ConvertSurface(mainSurface, mainSurface->format, ! 100: mainSurface->flags); ! 101: Dprintf(("toggleFullScreen: SDL_WM_ToggleFullScreen() not supported" ! 102: " -> using SDL_SetVideoMode()")); ! 103: if (temp == NULL) ! 104: bug("toggleFullScreen: Unable to save screen content."); ! 105: ! 106: #if 1 ! 107: HostScreen_setWindowSize(hs_width, hs_height, hs_bpp); ! 108: #else ! 109: mainSurface = SDL_SetVideoMode(width, height, bpp, sdl_videoparams); ! 110: if (mainSurface == NULL) ! 111: bug("toggleFullScreen: Unable to set new video mode."); ! 112: if (mainSurface->format->BitsPerPixel <= 8) ! 113: SDL_SetColors(mainSurface, temp->format->palette->colors, 0, ! 114: temp->format->palette->ncolors); ! 115: #endif ! 116: ! 117: if (SDL_BlitSurface(temp, NULL, mainSurface, NULL) != 0) ! 118: bug("toggleFullScreen: Unable to restore screen content."); ! 119: SDL_FreeSurface(temp); ! 120: ! 121: /* refresh the screen */ ! 122: HostScreen_update1(TRUE); ! 123: } ! 124: } ! 125: ! 126: static int HostScreen_selectVideoMode(SDL_Rect **modes, uint32 *width, uint32 *height) ! 127: { ! 128: int i, bestw, besth; ! 129: ! 130: /* Search the smallest nearest mode */ ! 131: bestw = modes[0]->w; ! 132: besth = modes[0]->h; ! 133: for (i=0;modes[i]; ++i) { ! 134: if ((modes[i]->w >= *width) && (modes[i]->h >= *height)) { ! 135: if ((modes[i]->w < bestw) || (modes[i]->h < besth)) { ! 136: bestw = modes[i]->w; ! 137: besth = modes[i]->h; ! 138: } ! 139: } ! 140: } ! 141: ! 142: *width = bestw; ! 143: *height = besth; ! 144: Dprintf(("hostscreen: video mode found: %dx%d\n",*width,*height)); ! 145: ! 146: return 1; ! 147: } ! 148: ! 149: static void HostScreen_searchVideoMode( uint32 *width, uint32 *height, uint32 *bpp ) ! 150: { ! 151: SDL_Rect **modes; ! 152: SDL_PixelFormat pixelformat; ! 153: int modeflags; ! 154: ! 155: /* Search in available modes the best suited */ ! 156: Dprintf(("hostscreen: video mode asked: %dx%dx%d\n",*width,*height,*bpp)); ! 157: ! 158: if ((*width == 0) || (*height == 0)) { ! 159: *width = 640; ! 160: *height = 480; ! 161: } ! 162: ! 163: /* Read available video modes */ ! 164: modeflags = 0 /*SDL_HWSURFACE | SDL_HWPALETTE*/; ! 165: if (bInFullScreen) ! 166: modeflags |= SDL_FULLSCREEN; ! 167: ! 168: /*--- Search a video mode with asked bpp ---*/ ! 169: if (*bpp != 0) { ! 170: pixelformat.BitsPerPixel = *bpp; ! 171: modes = SDL_ListModes(&pixelformat, modeflags); ! 172: if ((modes != (SDL_Rect **) 0) && (modes != (SDL_Rect **) -1)) { ! 173: Dprintf(("hostscreen: searching a good video mode (any bpp)\n")); ! 174: if (HostScreen_selectVideoMode(modes,width,height)) { ! 175: Dprintf(("hostscreen: video mode selected: %dx%dx%d\n",*width,*height,*bpp)); ! 176: return; ! 177: } ! 178: } ! 179: } ! 180: ! 181: /*--- Search a video mode with any bpp ---*/ ! 182: modes = SDL_ListModes(NULL, modeflags); ! 183: if ((modes != (SDL_Rect **) 0) && (modes != (SDL_Rect **) -1)) { ! 184: Dprintf(("hostscreen: searching a good video mode\n")); ! 185: if (HostScreen_selectVideoMode(modes,width,height)) { ! 186: Dprintf(("hostscreen: video mode selected: %dx%dx%d\n",*width,*height,*bpp)); ! 187: return; ! 188: } ! 189: } ! 190: ! 191: if (modes == (SDL_Rect **) 0) { ! 192: Dprintf(("hostscreen: No modes available\n")); ! 193: } ! 194: ! 195: if (modes == (SDL_Rect **) -1) { ! 196: /* Any mode available */ ! 197: Dprintf(("hostscreen: Any modes available\n")); ! 198: } ! 199: ! 200: Dprintf(("hostscreen: video mode selected: %dx%dx%d\n",*width,*height,*bpp)); ! 201: } ! 202: ! 203: void HostScreen_setWindowSize( uint32 width, uint32 height, uint32 bpp ) ! 204: { ! 205: nScreenZoomX = 1; ! 206: nScreenZoomY = 1; ! 207: if (ConfigureParams.Screen.bZoomLowRes) ! 208: { ! 209: /* Ugly: 400x300 threshold is currently hard-coded. */ ! 210: /* Should rather be selectable by the user! */ ! 211: if (width <= 400) ! 212: { ! 213: nScreenZoomX = (800/width); ! 214: width *= nScreenZoomX; ! 215: } ! 216: if (height <= 300) ! 217: { ! 218: nScreenZoomY = (550/height); ! 219: height *= nScreenZoomY; ! 220: } ! 221: } ! 222: ! 223: // Select a correct video mode ! 224: HostScreen_searchVideoMode(&width, &height, &bpp); ! 225: ! 226: hs_width = width; ! 227: hs_height = height; ! 228: hs_bpp = bpp; ! 229: ! 230: // SelectVideoMode(); ! 231: if (bInFullScreen) ! 232: sdl_videoparams = SDL_SWSURFACE|SDL_HWPALETTE|SDL_FULLSCREEN; ! 233: else ! 234: sdl_videoparams = SDL_SWSURFACE|SDL_HWPALETTE; ! 235: ! 236: mainSurface = SDL_SetVideoMode(width, height, bpp, sdl_videoparams); ! 237: ! 238: sdlscrn = surf = mainSurface; ! 239: ! 240: // update the surface's palette ! 241: HostScreen_updatePalette( 256 ); ! 242: ! 243: Dprintf(("Surface Pitch = %d, width = %d, height = %d\n", surf->pitch, surf->w, surf->h)); ! 244: Dprintf(("Must Lock? %s\n", SDL_MUSTLOCK(surf) ? "YES" : "NO")); ! 245: ! 246: // is the SDL_update needed? ! 247: doUpdate = ( surf->flags & SDL_HWSURFACE ) == 0; ! 248: ! 249: HostScreen_renderBegin(); ! 250: ! 251: // VideoRAMBaseHost = (uint8 *) surf->pixels; ! 252: // InitVMEMBaseDiff(VideoRAMBaseHost, VideoRAMBase); ! 253: // Dprintf(("VideoRAM starts at %p (%08x)\n", VideoRAMBaseHost, VideoRAMBase)); ! 254: Dprintf(("surf->pixels = %p, getVideoSurface() = %p\n", ! 255: surf->pixels, SDL_GetVideoSurface()->pixels)); ! 256: ! 257: HostScreen_renderEnd(); ! 258: ! 259: Dprintf(("Pixel format:bitspp=%d, tmasks r=%04x g=%04x b=%04x" ! 260: ", tshifts r=%d g=%d b=%d" ! 261: ", tlosses r=%d g=%d b=%d\n", ! 262: surf->format->BitsPerPixel, ! 263: surf->format->Rmask, surf->format->Gmask, surf->format->Bmask, ! 264: surf->format->Rshift, surf->format->Gshift, surf->format->Bshift, ! 265: surf->format->Rloss, surf->format->Gloss, surf->format->Bloss)); ! 266: } ! 267: ! 268: ! 269: static void HostScreen_update5( int32 x, int32 y, int32 w, int32 h, BOOL forced ) ! 270: { ! 271: if ( !forced && !doUpdate ) // the HW surface is available ! 272: return; ! 273: ! 274: // SDL_UpdateRect(SDL_GetVideoSurface(), 0, 0, width, height); ! 275: // SDL_UpdateRect(surf, x, y, w, h); ! 276: SDL_UpdateRect(mainSurface, x, y, w, h); ! 277: } ! 278: ! 279: void HostScreen_update1( BOOL forced ) ! 280: { ! 281: HostScreen_update5( 0, 0, hs_width, hs_height, forced ); ! 282: } ! 283: ! 284: void HostScreen_update0() ! 285: { ! 286: HostScreen_update5( 0, 0, hs_width, hs_height, FALSE ); ! 287: } ! 288: ! 289: ! 290: uint32 HostScreen_getBitsPerPixel(void) ! 291: { ! 292: return surf->format->BitsPerPixel; ! 293: } ! 294: ! 295: ! 296: #if 0 ! 297: void HostScreen_gfxFastPixelColorNolock(int16 x, int16 y, uint32 color) ! 298: { ! 299: int bpp; ! 300: uint8 *p; ! 301: ! 302: /* Get destination format */ ! 303: bpp = surf->format->BytesPerPixel; ! 304: p = (uint8 *)surf->pixels + y * surf->pitch + x * bpp; ! 305: switch(bpp) { ! 306: case 1: ! 307: *p = color; ! 308: break; ! 309: case 2: ! 310: *(uint16 *)p = color; ! 311: break; ! 312: case 3: ! 313: putBpp24Pixel( p, color ); ! 314: break; ! 315: case 4: ! 316: *(uint32 *)p = color; ! 317: break; ! 318: } /* switch */ ! 319: } ! 320: #endif ! 321: ! 322: #if 0 ! 323: uint32 HostScreen_gfxGetPixel( int16 x, int16 y ) ! 324: { ! 325: int bpp; ! 326: uint8 *p; ! 327: ! 328: /* Get destination format */ ! 329: bpp = surf->format->BytesPerPixel; ! 330: p = (uint8 *)surf->pixels + y * surf->pitch + x * bpp; ! 331: switch(bpp) { ! 332: case 1: ! 333: return (uint32)(*(uint8 *)p); ! 334: case 2: ! 335: return (uint32)(*(uint16 *)p); ! 336: case 3: ! 337: // FIXME maybe some & problems? and endian ! 338: return getBpp24Pixel( p ); ! 339: case 4: ! 340: return *(uint32 *)p; ! 341: } /* switch */ ! 342: return 0; // should never happen ! 343: } ! 344: #endif ! 345: ! 346: uint32 HostScreen_getBpp() ! 347: { ! 348: return surf->format->BytesPerPixel; ! 349: } ! 350: ! 351: uint32 HostScreen_getPitch() { ! 352: return surf->pitch; ! 353: } ! 354: ! 355: uint32 HostScreen_getWidth() { ! 356: return hs_width; ! 357: } ! 358: ! 359: uint32 HostScreen_getHeight() { ! 360: return hs_height; ! 361: } ! 362: ! 363: uint8 *HostScreen_getVideoramAddress() { ! 364: return surf->pixels; /* FIXME maybe this should be mainSurface? */ ! 365: } ! 366: ! 367: void HostScreen_setPaletteColor( uint8 idx, uint32 red, uint32 green, uint32 blue ) { ! 368: // set the SDL standard RGB palette settings ! 369: palette.standard[idx].r = red; ! 370: palette.standard[idx].g = green; ! 371: palette.standard[idx].b = blue; ! 372: // convert the color to native ! 373: palette.native[idx] = SDL_MapRGB( surf->format, red, green, blue ); ! 374: } ! 375: ! 376: uint32 HostScreen_getPaletteColor( uint8 idx ) { ! 377: return palette.native[idx]; ! 378: } ! 379: ! 380: void HostScreen_updatePalette( uint16 colorCount ) { ! 381: SDL_SetColors( surf, palette.standard, 0, colorCount ); ! 382: } ! 383: ! 384: uint32 HostScreen_getColor( uint32 red, uint32 green, uint32 blue ) { ! 385: return SDL_MapRGB( surf->format, red, green, blue ); ! 386: } ! 387: ! 388: #if 0 ! 389: void HostScreen_lock(void) { ! 390: while (SDL_mutexP(screenLock)==-1) { ! 391: SDL_Delay(20); ! 392: fprintf(stderr, "Couldn't lock mutex\n"); ! 393: } ! 394: } ! 395: ! 396: void HostScreen_unlock(void) { ! 397: while (SDL_mutexV(screenLock)==-1) { ! 398: SDL_Delay(20); ! 399: fprintf(stderr, "Couldn't unlock mutex\n"); ! 400: } ! 401: } ! 402: #endif ! 403: ! 404: BOOL HostScreen_renderBegin(void) { ! 405: if (SDL_MUSTLOCK(surf)) ! 406: if (SDL_LockSurface(surf) < 0) { ! 407: printf("Couldn't lock surface to refresh!\n"); ! 408: return FALSE; ! 409: } ! 410: ! 411: return TRUE; ! 412: } ! 413: ! 414: void HostScreen_renderEnd() { ! 415: if (SDL_MUSTLOCK(surf)) ! 416: SDL_UnlockSurface(surf); ! 417: } ! 418: ! 419: ! 420: ! 421: /** ! 422: * Performs conversion from the TOS's bitplane word order (big endian) data ! 423: * into the native chunky color index. ! 424: */ ! 425: void HostScreen_bitplaneToChunky( uint16 *atariBitplaneData, uint16 bpp, uint8 colorValues[16] ) ! 426: { ! 427: uint32 a, b, c, d, x; ! 428: ! 429: /* Obviously the different cases can be broken out in various ! 430: * ways to lessen the amount of work needed for <8 bit modes. ! 431: * It's doubtful if the usage of those modes warrants it, though. ! 432: * The branches below should be ~100% correctly predicted and ! 433: * thus be more or less for free. ! 434: * Getting the palette values inline does not seem to help ! 435: * enough to worry about. The palette lookup is much slower than ! 436: * this code, though, so it would be nice to do something about it. ! 437: */ ! 438: if (bpp >= 4) { ! 439: d = *(uint32 *)&atariBitplaneData[0]; ! 440: c = *(uint32 *)&atariBitplaneData[2]; ! 441: if (bpp == 4) { ! 442: a = b = 0; ! 443: } else { ! 444: b = *(uint32 *)&atariBitplaneData[4]; ! 445: a = *(uint32 *)&atariBitplaneData[6]; ! 446: } ! 447: } else { ! 448: a = b = c = 0; ! 449: if (bpp == 2) { ! 450: d = *(uint32 *)&atariBitplaneData[0]; ! 451: } else { ! 452: #if SDL_BYTEORDER == SDL_BIG_ENDIAN ! 453: d = atariBitplaneData[0]<<16; ! 454: #else ! 455: d = atariBitplaneData[0]; ! 456: #endif ! 457: } ! 458: } ! 459: ! 460: x = a; ! 461: a = (a & 0xf0f0f0f0) | ((c & 0xf0f0f0f0) >> 4); ! 462: c = ((x & 0x0f0f0f0f) << 4) | (c & 0x0f0f0f0f); ! 463: x = b; ! 464: b = (b & 0xf0f0f0f0) | ((d & 0xf0f0f0f0) >> 4); ! 465: d = ((x & 0x0f0f0f0f) << 4) | (d & 0x0f0f0f0f); ! 466: ! 467: x = a; ! 468: a = (a & 0xcccccccc) | ((b & 0xcccccccc) >> 2); ! 469: b = ((x & 0x33333333) << 2) | (b & 0x33333333); ! 470: x = c; ! 471: c = (c & 0xcccccccc) | ((d & 0xcccccccc) >> 2); ! 472: d = ((x & 0x33333333) << 2) | (d & 0x33333333); ! 473: ! 474: #if SDL_BYTEORDER == SDL_BIG_ENDIAN ! 475: a = (a & 0x5555aaaa) | ((a & 0x00005555) << 17) | ((a & 0xaaaa0000) >> 17); ! 476: b = (b & 0x5555aaaa) | ((b & 0x00005555) << 17) | ((b & 0xaaaa0000) >> 17); ! 477: c = (c & 0x5555aaaa) | ((c & 0x00005555) << 17) | ((c & 0xaaaa0000) >> 17); ! 478: d = (d & 0x5555aaaa) | ((d & 0x00005555) << 17) | ((d & 0xaaaa0000) >> 17); ! 479: ! 480: colorValues[ 8] = a; ! 481: a >>= 8; ! 482: colorValues[ 0] = a; ! 483: a >>= 8; ! 484: colorValues[ 9] = a; ! 485: a >>= 8; ! 486: colorValues[ 1] = a; ! 487: ! 488: colorValues[10] = b; ! 489: b >>= 8; ! 490: colorValues[ 2] = b; ! 491: b >>= 8; ! 492: colorValues[11] = b; ! 493: b >>= 8; ! 494: colorValues[ 3] = b; ! 495: ! 496: colorValues[12] = c; ! 497: c >>= 8; ! 498: colorValues[ 4] = c; ! 499: c >>= 8; ! 500: colorValues[13] = c; ! 501: c >>= 8; ! 502: colorValues[ 5] = c; ! 503: ! 504: colorValues[14] = d; ! 505: d >>= 8; ! 506: colorValues[ 6] = d; ! 507: d >>= 8; ! 508: colorValues[15] = d; ! 509: d >>= 8; ! 510: colorValues[ 7] = d; ! 511: #else ! 512: a = (a & 0xaaaa5555) | ((a & 0x0000aaaa) << 15) | ((a & 0x55550000) >> 15); ! 513: b = (b & 0xaaaa5555) | ((b & 0x0000aaaa) << 15) | ((b & 0x55550000) >> 15); ! 514: c = (c & 0xaaaa5555) | ((c & 0x0000aaaa) << 15) | ((c & 0x55550000) >> 15); ! 515: d = (d & 0xaaaa5555) | ((d & 0x0000aaaa) << 15) | ((d & 0x55550000) >> 15); ! 516: ! 517: colorValues[ 1] = a; ! 518: a >>= 8; ! 519: colorValues[ 9] = a; ! 520: a >>= 8; ! 521: colorValues[ 0] = a; ! 522: a >>= 8; ! 523: colorValues[ 8] = a; ! 524: ! 525: colorValues[ 3] = b; ! 526: b >>= 8; ! 527: colorValues[11] = b; ! 528: b >>= 8; ! 529: colorValues[ 2] = b; ! 530: b >>= 8; ! 531: colorValues[10] = b; ! 532: ! 533: colorValues[ 5] = c; ! 534: c >>= 8; ! 535: colorValues[13] = c; ! 536: c >>= 8; ! 537: colorValues[ 4] = c; ! 538: c >>= 8; ! 539: colorValues[12] = c; ! 540: ! 541: colorValues[ 7] = d; ! 542: d >>= 8; ! 543: colorValues[15] = d; ! 544: d >>= 8; ! 545: colorValues[ 6] = d; ! 546: d >>= 8; ! 547: colorValues[14] = d; ! 548: #endif ! 549: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.