--- hatari/src/falcon/hostscreen.c 2019/04/01 07:15:34 1.1.1.3 +++ hatari/src/falcon/hostscreen.c 2019/04/09 08:48:46 1.1.1.5 @@ -8,7 +8,7 @@ has been thoroughly reworked for Hatari. However, integration with the rest of the Hatari source code is still bad and needs a lot of improvement... */ -const char HostScreen_rcsid[] = "Hatari $Id: hostscreen.c,v 1.1.1.3 2019/04/01 07:15:34 root Exp $"; +const char HostScreen_fileid[] = "Hatari hostscreen.c : " __DATE__ " " __TIME__; #include "main.h" #include "configuration.h" @@ -17,6 +17,7 @@ const char HostScreen_rcsid[] = "Hatari #include "stMemory.h" #include "ioMem.h" #include "hostscreen.h" +#include "resolution.h" #include "screen.h" #include "statusbar.h" @@ -50,10 +51,9 @@ const char HostScreen_rcsid[] = "Hatari static SDL_Surface *mainSurface; // The main window surface static SDL_Surface *surf; // pointer to actual surface - -static SDL_mutex *screenLock; +/* TODO: put these hostscreen globals to some struct */ static Uint32 sdl_videoparams; -static Uint32 hs_width, hs_height, hs_bpp; +static int hs_width, hs_height, hs_width_req, hs_height_req, hs_bpp; static bool doUpdate; // the HW surface is available -> the SDL need not to update the surface after ->pixel access static struct { // TOS palette (bpp < 16) to SDL color mapping @@ -69,11 +69,9 @@ static const unsigned long default_palet RGB_LTBLUE, RGB_LTMAGENTA, RGB_LTCYAN, RGB_BLACK }; -static int HostScreen_selectVideoMode(SDL_Rect **modes, Uint32 *width, Uint32 *height); -static void HostScreen_searchVideoMode( Uint32 *width, Uint32 *height, Uint32 *bpp ); - -void HostScreen_Init(void) { +void HostScreen_Init(void) +{ int i; for(i=0; i<256; i++) { unsigned long color = default_palette[i%16]; @@ -82,184 +80,136 @@ void HostScreen_Init(void) { palette.standard[i].b = color & 0xff; } - screenLock = SDL_CreateMutex(); - mainSurface=NULL; } -void HostScreen_UnInit(void) { - SDL_DestroyMutex(screenLock); +void HostScreen_UnInit(void) +{ } void HostScreen_toggleFullScreen(void) { sdl_videoparams ^= SDL_FULLSCREEN; - if (sdl_videoparams & SDL_FULLSCREEN) { - /* un-embed the Hatari WM window for fullscreen */ - Control_ReparentWindow(hs_width, hs_height, TRUE); - } - if(SDL_WM_ToggleFullScreen(mainSurface) == 0) { - // SDL_WM_ToggleFullScreen() did not work. - // We have to change video mode "by hand". - SDL_Surface *temp = SDL_ConvertSurface(mainSurface, mainSurface->format, - mainSurface->flags); - Dprintf(("toggleFullScreen: SDL_WM_ToggleFullScreen() not supported" - " -> using SDL_SetVideoMode()")); - if (temp == NULL) - bug("toggleFullScreen: Unable to save screen content."); - -#if 1 - HostScreen_setWindowSize(hs_width, hs_height, hs_bpp); -#else - mainSurface = SDL_SetVideoMode(width, height, bpp, sdl_videoparams); - if (mainSurface == NULL) - bug("toggleFullScreen: Unable to set new video mode."); - if (mainSurface->format->BitsPerPixel <= 8) - SDL_SetColors(mainSurface, temp->format->palette->colors, 0, - temp->format->palette->ncolors); -#endif - - if (SDL_BlitSurface(temp, NULL, mainSurface, NULL) != 0) - bug("toggleFullScreen: Unable to restore screen content."); - SDL_FreeSurface(temp); - /* refresh the screen */ - HostScreen_update1(TRUE); - } else { - if (!(sdl_videoparams & SDL_FULLSCREEN)) { - /* re-embed the new Hatari SDL window */ - Control_ReparentWindow(hs_width, hs_height, FALSE); - } - } + HostScreen_setWindowSize(hs_width_req, hs_height_req, hs_bpp); + /* refresh the screen */ + HostScreen_update1(true); } -static int HostScreen_selectVideoMode(SDL_Rect **modes, Uint32 *width, Uint32 *height) -{ - int i, bestw, besth; - - /* Search the smallest nearest mode */ - bestw = modes[0]->w; - besth = modes[0]->h; - for (i=0;modes[i]; ++i) { - if ((modes[i]->w >= *width) && (modes[i]->h >= *height)) { - if ((modes[i]->w < bestw) || (modes[i]->h < besth)) { - bestw = modes[i]->w; - besth = modes[i]->h; - } - } - } - *width = bestw; - *height = besth; - Dprintf(("hostscreen: video mode found: %dx%d\n",*width,*height)); - - return 1; -} - -static void HostScreen_searchVideoMode( Uint32 *width, Uint32 *height, Uint32 *bpp ) +void HostScreen_setWindowSize(int width, int height, int bpp) { - SDL_Rect **modes; - SDL_PixelFormat pixelformat; - int modeflags; + int screenwidth, screenheight, maxw, maxh; + int scalex, scaley, sbarheight; - /* Search in available modes the best suited */ - Dprintf(("hostscreen: video mode asked: %dx%dx%d\n",*width,*height,*bpp)); + if (bpp == 24) + bpp = 32; - if ((*width == 0) || (*height == 0)) { - *width = 640; - *height = 480; - } + Resolution_GetLimits(&maxw, &maxh, &bpp); - /* Read available video modes */ - modeflags = 0 /*SDL_HWSURFACE | SDL_HWPALETTE*/; - if (bInFullScreen) - modeflags |= SDL_FULLSCREEN; - - /*--- Search a video mode with asked bpp ---*/ - if (*bpp != 0) { - pixelformat.BitsPerPixel = *bpp; - modes = SDL_ListModes(&pixelformat, modeflags); - if ((modes != (SDL_Rect **) 0) && (modes != (SDL_Rect **) -1)) { - Dprintf(("hostscreen: searching a good video mode (any bpp)\n")); - if (HostScreen_selectVideoMode(modes,width,height)) { - Dprintf(("hostscreen: video mode selected: %dx%dx%d\n",*width,*height,*bpp)); - return; - } + nScreenZoomX = nScreenZoomY = 1; + + if (ConfigureParams.Screen.bAspectCorrect) { + /* Falcon (and TT) pixel scaling factors seem to 2^x + * (quarter/half pixel, interlace/double line), so + * do aspect correction as 2's exponent. + */ + while (nScreenZoomX*width < height && + 2*nScreenZoomX*width < maxw) { + nScreenZoomX *= 2; + } + while (2*nScreenZoomY*height < width && + 2*nScreenZoomY*height < maxh) { + nScreenZoomY *= 2; + } + if (nScreenZoomX*nScreenZoomY > 2) { + fprintf(stderr, "WARNING: strange screen size %dx%d -> aspect corrected by %dx%d!\n", + width, height, nScreenZoomX, nScreenZoomY); } } - /*--- Search a video mode with any bpp ---*/ - modes = SDL_ListModes(NULL, modeflags); - if ((modes != (SDL_Rect **) 0) && (modes != (SDL_Rect **) -1)) { - Dprintf(("hostscreen: searching a good video mode\n")); - if (HostScreen_selectVideoMode(modes,width,height)) { - Dprintf(("hostscreen: video mode selected: %dx%dx%d\n",*width,*height,*bpp)); - return; + /* then select scale as close to target size as possible + * without having larger size than it + */ + scalex = maxw/(nScreenZoomX*width); + scaley = maxh/(nScreenZoomY*height); + if (scalex > 1 && scaley > 1) { + /* keep aspect ratio */ + if (scalex < scaley) { + nScreenZoomX *= scalex; + nScreenZoomY *= scalex; + } else { + nScreenZoomX *= scaley; + nScreenZoomY *= scaley; } } - if (modes == (SDL_Rect **) 0) { - Dprintf(("hostscreen: No modes available\n")); - } + hs_width_req = width; + hs_height_req = height; + width *= nScreenZoomX; + height *= nScreenZoomY; + + sbarheight = Statusbar_GetHeightForSize(width, height); + screenheight = height + sbarheight; + screenwidth = width; - if (modes == (SDL_Rect **) -1) { - /* Any mode available */ - Dprintf(("hostscreen: Any modes available\n")); - } + // Select a correct video mode + Resolution_Search(&screenwidth, &screenheight, &bpp); + sbarheight = Statusbar_SetHeight(screenwidth, screenheight-sbarheight); - Dprintf(("hostscreen: video mode selected: %dx%dx%d\n",*width,*height,*bpp)); -} + hs_bpp = bpp; + /* videl.c might scale things differently in fullscreen than + * in windowed mode because this uses screensize instead of using + * the aspect scaled sizes directly, but it works better this way. + */ + hs_width = screenwidth; + hs_height = screenheight - sbarheight; -void HostScreen_setWindowSize( Uint32 width, Uint32 height, Uint32 bpp ) -{ - Uint32 screenheight; - - nScreenZoomX = 1; - nScreenZoomY = 1; - if (ConfigureParams.Screen.bZoomLowRes) + if (sdlscrn && (!bpp || sdlscrn->format->BitsPerPixel == bpp) && + sdlscrn->w == (signed)screenwidth && sdlscrn->h == (signed)screenheight && + (sdlscrn->flags&SDL_FULLSCREEN) == (sdl_videoparams&SDL_FULLSCREEN)) { - /* Ugly: 400x300 threshold is currently hard-coded. */ - /* Should rather be selectable by the user! */ - if (width <= 400) - { - nScreenZoomX = (800/width); - width *= nScreenZoomX; - } - if (height <= 300) - { - nScreenZoomY = (550/height); - height *= nScreenZoomY; + /* no time consuming host video mode change needed */ + if (screenwidth > width || screenheight > height+sbarheight) { + /* Atari screen smaller than host -> clear screen */ + SDL_Rect rect; + rect.x = 0; + rect.y = 0; + rect.w = sdlscrn->w; + rect.h = sdlscrn->h - sbarheight; + SDL_FillRect(sdlscrn, &rect, SDL_MapRGB(sdlscrn->format, 0, 0, 0)); } + return; } - screenheight = height + Statusbar_SetHeight(width, height); - - // Select a correct video mode - HostScreen_searchVideoMode(&width, &screenheight, &bpp); - - hs_width = width; - hs_height = height; - hs_bpp = bpp; - // SelectVideoMode(); if (bInFullScreen) { /* un-embed the Hatari WM window for fullscreen */ - Control_ReparentWindow(width, screenheight, bInFullScreen); + Control_ReparentWindow(screenwidth, screenheight, bInFullScreen); sdl_videoparams = SDL_SWSURFACE|SDL_HWPALETTE|SDL_FULLSCREEN; } else { sdl_videoparams = SDL_SWSURFACE|SDL_HWPALETTE; } - mainSurface = SDL_SetVideoMode(width, screenheight, bpp, sdl_videoparams); +#ifdef _MUDFLAP + if (sdlscrn) { + __mf_unregister(sdlscrn->pixels, sdlscrn->pitch*sdlscrn->h, __MF_TYPE_GUESS); + } +#endif + mainSurface = SDL_SetVideoMode(screenwidth, screenheight, bpp, sdl_videoparams); + sdlscrn = surf = mainSurface; +#ifdef _MUDFLAP + __mf_register(sdlscrn->pixels, sdlscrn->pitch*sdlscrn->h, __MF_TYPE_GUESS, "SDL pixels"); +#endif if (!bInFullScreen) { /* re-embed the new Hatari SDL window */ - Control_ReparentWindow(width, screenheight, bInFullScreen); + Control_ReparentWindow(screenwidth, screenheight, bInFullScreen); } - sdlscrn = surf = mainSurface; // update the surface's palette HostScreen_updatePalette( 256 ); + // redraw statusbar Statusbar_Init(mainSurface); Dprintf(("Surface Pitch = %d, width = %d, height = %d\n", surf->pitch, surf->w, surf->h)); @@ -268,16 +218,6 @@ void HostScreen_setWindowSize( Uint32 wi // is the SDL_update needed? doUpdate = ( surf->flags & SDL_HWSURFACE ) == 0; - HostScreen_renderBegin(); - -// VideoRAMBaseHost = (uint8 *) surf->pixels; -// InitVMEMBaseDiff(VideoRAMBaseHost, VideoRAMBase); -// Dprintf(("VideoRAM starts at %p (%08x)\n", VideoRAMBaseHost, VideoRAMBase)); - Dprintf(("surf->pixels = %p, getVideoSurface() = %p\n", - surf->pixels, SDL_GetVideoSurface()->pixels)); - - HostScreen_renderEnd(); - Dprintf(("Pixel format:bitspp=%d, tmasks r=%04x g=%04x b=%04x" ", tshifts r=%d g=%d b=%d" ", tlosses r=%d g=%d b=%d\n", @@ -285,6 +225,8 @@ void HostScreen_setWindowSize( Uint32 wi surf->format->Rmask, surf->format->Gmask, surf->format->Bmask, surf->format->Rshift, surf->format->Gshift, surf->format->Bshift, surf->format->Rloss, surf->format->Gloss, surf->format->Bloss)); + + Main_WarpMouse(sdlscrn->w/2,sdlscrn->h/2); } @@ -293,8 +235,6 @@ static void HostScreen_update5(Sint32 x, if ( !forced && !doUpdate ) // the HW surface is available return; - // SDL_UpdateRect(SDL_GetVideoSurface(), 0, 0, width, height); - // SDL_UpdateRect(surf, x, y, w, h); SDL_UpdateRect(mainSurface, x, y, w, h); } @@ -303,40 +243,34 @@ void HostScreen_update1(bool forced) HostScreen_update5( 0, 0, hs_width, hs_height, forced ); } -void HostScreen_update0() -{ - HostScreen_update5( 0, 0, hs_width, hs_height, FALSE ); -} - - -Uint32 HostScreen_getBitsPerPixel(void) -{ - return surf->format->BitsPerPixel; -} - -Uint32 HostScreen_getBpp() +Uint32 HostScreen_getBpp(void) { return surf->format->BytesPerPixel; } -Uint32 HostScreen_getPitch() { +Uint32 HostScreen_getPitch(void) +{ return surf->pitch; } -Uint32 HostScreen_getWidth() { +Uint32 HostScreen_getWidth(void) +{ return hs_width; } -Uint32 HostScreen_getHeight() { +Uint32 HostScreen_getHeight(void) +{ return hs_height; } -Uint8 *HostScreen_getVideoramAddress() { +Uint8 *HostScreen_getVideoramAddress(void) +{ return surf->pixels; /* FIXME maybe this should be mainSurface? */ } -void HostScreen_setPaletteColor(Uint8 idx, Uint32 red, Uint32 green, Uint32 blue ) { +void HostScreen_setPaletteColor(Uint8 idx, Uint32 red, Uint32 green, Uint32 blue) +{ // set the SDL standard RGB palette settings palette.standard[idx].r = red; palette.standard[idx].g = green; @@ -345,179 +279,36 @@ void HostScreen_setPaletteColor(Uint8 id palette.native[idx] = SDL_MapRGB( surf->format, red, green, blue ); } -Uint32 HostScreen_getPaletteColor(Uint8 idx) { +Uint32 HostScreen_getPaletteColor(Uint8 idx) +{ return palette.native[idx]; } -void HostScreen_updatePalette( Uint16 colorCount ) { +void HostScreen_updatePalette(Uint16 colorCount) +{ SDL_SetColors( surf, palette.standard, 0, colorCount ); } -Uint32 HostScreen_getColor( Uint32 red, Uint32 green, Uint32 blue ) { +Uint32 HostScreen_getColor(Uint32 red, Uint32 green, Uint32 blue) +{ return SDL_MapRGB( surf->format, red, green, blue ); } -#if 0 -void HostScreen_lock(void) { - while (SDL_mutexP(screenLock)==-1) { - SDL_Delay(20); - fprintf(stderr, "Couldn't lock mutex\n"); - } -} - -void HostScreen_unlock(void) { - while (SDL_mutexV(screenLock)==-1) { - SDL_Delay(20); - fprintf(stderr, "Couldn't unlock mutex\n"); - } -} -#endif bool HostScreen_renderBegin(void) { if (SDL_MUSTLOCK(surf)) if (SDL_LockSurface(surf) < 0) { printf("Couldn't lock surface to refresh!\n"); - return FALSE; + return false; } - return TRUE; + return true; } -void HostScreen_renderEnd() { +void HostScreen_renderEnd(void) +{ if (SDL_MUSTLOCK(surf)) SDL_UnlockSurface(surf); Statusbar_Update(surf); } - - - -/** - * Performs conversion from the TOS's bitplane word order (big endian) data - * into the native chunky color index. - */ -void HostScreen_bitplaneToChunky(Uint16 *atariBitplaneData, Uint16 bpp, Uint8 colorValues[16] ) -{ - Uint32 a, b, c, d, x; - - /* Obviously the different cases can be broken out in various - * ways to lessen the amount of work needed for <8 bit modes. - * It's doubtful if the usage of those modes warrants it, though. - * The branches below should be ~100% correctly predicted and - * thus be more or less for free. - * Getting the palette values inline does not seem to help - * enough to worry about. The palette lookup is much slower than - * this code, though, so it would be nice to do something about it. - */ - if (bpp >= 4) { - d = *(Uint32 *)&atariBitplaneData[0]; - c = *(Uint32 *)&atariBitplaneData[2]; - if (bpp == 4) { - a = b = 0; - } else { - b = *(Uint32 *)&atariBitplaneData[4]; - a = *(Uint32 *)&atariBitplaneData[6]; - } - } else { - a = b = c = 0; - if (bpp == 2) { - d = *(Uint32 *)&atariBitplaneData[0]; - } else { -#if SDL_BYTEORDER == SDL_BIG_ENDIAN - d = atariBitplaneData[0]<<16; -#else - d = atariBitplaneData[0]; -#endif - } - } - - x = a; - a = (a & 0xf0f0f0f0) | ((c & 0xf0f0f0f0) >> 4); - c = ((x & 0x0f0f0f0f) << 4) | (c & 0x0f0f0f0f); - x = b; - b = (b & 0xf0f0f0f0) | ((d & 0xf0f0f0f0) >> 4); - d = ((x & 0x0f0f0f0f) << 4) | (d & 0x0f0f0f0f); - - x = a; - a = (a & 0xcccccccc) | ((b & 0xcccccccc) >> 2); - b = ((x & 0x33333333) << 2) | (b & 0x33333333); - x = c; - c = (c & 0xcccccccc) | ((d & 0xcccccccc) >> 2); - d = ((x & 0x33333333) << 2) | (d & 0x33333333); - -#if SDL_BYTEORDER == SDL_BIG_ENDIAN - a = (a & 0x5555aaaa) | ((a & 0x00005555) << 17) | ((a & 0xaaaa0000) >> 17); - b = (b & 0x5555aaaa) | ((b & 0x00005555) << 17) | ((b & 0xaaaa0000) >> 17); - c = (c & 0x5555aaaa) | ((c & 0x00005555) << 17) | ((c & 0xaaaa0000) >> 17); - d = (d & 0x5555aaaa) | ((d & 0x00005555) << 17) | ((d & 0xaaaa0000) >> 17); - - colorValues[ 8] = a; - a >>= 8; - colorValues[ 0] = a; - a >>= 8; - colorValues[ 9] = a; - a >>= 8; - colorValues[ 1] = a; - - colorValues[10] = b; - b >>= 8; - colorValues[ 2] = b; - b >>= 8; - colorValues[11] = b; - b >>= 8; - colorValues[ 3] = b; - - colorValues[12] = c; - c >>= 8; - colorValues[ 4] = c; - c >>= 8; - colorValues[13] = c; - c >>= 8; - colorValues[ 5] = c; - - colorValues[14] = d; - d >>= 8; - colorValues[ 6] = d; - d >>= 8; - colorValues[15] = d; - d >>= 8; - colorValues[ 7] = d; -#else - a = (a & 0xaaaa5555) | ((a & 0x0000aaaa) << 15) | ((a & 0x55550000) >> 15); - b = (b & 0xaaaa5555) | ((b & 0x0000aaaa) << 15) | ((b & 0x55550000) >> 15); - c = (c & 0xaaaa5555) | ((c & 0x0000aaaa) << 15) | ((c & 0x55550000) >> 15); - d = (d & 0xaaaa5555) | ((d & 0x0000aaaa) << 15) | ((d & 0x55550000) >> 15); - - colorValues[ 1] = a; - a >>= 8; - colorValues[ 9] = a; - a >>= 8; - colorValues[ 0] = a; - a >>= 8; - colorValues[ 8] = a; - - colorValues[ 3] = b; - b >>= 8; - colorValues[11] = b; - b >>= 8; - colorValues[ 2] = b; - b >>= 8; - colorValues[10] = b; - - colorValues[ 5] = c; - c >>= 8; - colorValues[13] = c; - c >>= 8; - colorValues[ 4] = c; - c >>= 8; - colorValues[12] = c; - - colorValues[ 7] = d; - d >>= 8; - colorValues[15] = d; - d >>= 8; - colorValues[ 6] = d; - d >>= 8; - colorValues[14] = d; -#endif -}