--- hatari/src/falcon/hostscreen.c 2019/04/09 08:48:46 1.1.1.5 +++ hatari/src/falcon/hostscreen.c 2019/04/09 08:55:47 1.1.1.9 @@ -1,8 +1,8 @@ /* Hatari - hostscreen.c - This file is distributed under the GNU Public License, version 2 or at - your option any later version. Read the file gpl.txt for details. + This file is distributed under the GNU General Public License, version 2 + or at your option any later version. Read the file gpl.txt for details. Host video routines. This file originally came from the Aranym project but has been thoroughly reworked for Hatari. However, integration with the rest @@ -10,6 +10,7 @@ */ const char HostScreen_fileid[] = "Hatari hostscreen.c : " __DATE__ " " __TIME__; +#include #include "main.h" #include "configuration.h" #include "control.h" @@ -48,21 +49,20 @@ const char HostScreen_fileid[] = "Hatari #define RGB_WHITE 0xffff00ff -static SDL_Surface *mainSurface; // The main window surface -static SDL_Surface *surf; // pointer to actual surface - /* TODO: put these hostscreen globals to some struct */ -static Uint32 sdl_videoparams; -static int hs_width, hs_height, hs_width_req, hs_height_req, hs_bpp; +static SDL_Rect hs_rect; +static int 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 void HostScreen_remapPalette(void); + static struct { // TOS palette (bpp < 16) to SDL color mapping SDL_Color standard[256]; Uint32 native[256]; } palette; -static const unsigned long default_palette[] = { +static const Uint32 default_palette[] = { RGB_WHITE, RGB_RED, RGB_GREEN, RGB_YELLOW, RGB_BLUE, RGB_MAGENTA, RGB_CYAN, RGB_LTGRAY, RGB_GRAY, RGB_LTRED, RGB_LTGREEN, RGB_LTYELLOW, @@ -73,14 +73,12 @@ static const unsigned long default_palet void HostScreen_Init(void) { int i; - for(i=0; i<256; i++) { - unsigned long color = default_palette[i%16]; + for(i = 0; i < 256; i++) { + Uint32 color = default_palette[i%16]; palette.standard[i].r = color >> 24; palette.standard[i].g = (color >> 16) & 0xff; palette.standard[i].b = color & 0xff; } - - mainSurface=NULL; } void HostScreen_UnInit(void) @@ -90,24 +88,38 @@ void HostScreen_UnInit(void) void HostScreen_toggleFullScreen(void) { - sdl_videoparams ^= SDL_FULLSCREEN; - - HostScreen_setWindowSize(hs_width_req, hs_height_req, hs_bpp); - /* refresh the screen */ - HostScreen_update1(true); + HostScreen_setWindowSize(hs_width_req, hs_height_req, hs_bpp, true); + /* force screen redraw */ + HostScreen_update1(NULL, true); } -void HostScreen_setWindowSize(int width, int height, int bpp) +void HostScreen_setWindowSize(int width, int height, int bpp, bool bForceChange) { + const bool keep = ConfigureParams.Screen.bKeepResolution; int screenwidth, screenheight, maxw, maxh; int scalex, scaley, sbarheight; if (bpp == 24) bpp = 32; - Resolution_GetLimits(&maxw, &maxh, &bpp); + /* constrain size request to user's desktop size */ + Resolution_GetDesktopSize(&maxw, &maxh); + scalex = scaley = 1; + while (width > maxw*scalex) { + scalex *= 2; + } + while (height > maxh*scaley) { + scaley *= 2; + } + if (scalex * scaley > 1) { + fprintf(stderr, "WARNING: too large screen size %dx%d -> divided by %dx%d!\n", + width, height, scalex, scaley); + width /= scalex; + height /= scaley; + } + Resolution_GetLimits(&maxw, &maxh, &bpp, keep); nScreenZoomX = nScreenZoomY = 1; if (ConfigureParams.Screen.bAspectCorrect) { @@ -150,12 +162,14 @@ void HostScreen_setWindowSize(int width, width *= nScreenZoomX; height *= nScreenZoomY; + /* get statusbar size for this screen size */ sbarheight = Statusbar_GetHeightForSize(width, height); screenheight = height + sbarheight; screenwidth = width; - // Select a correct video mode - Resolution_Search(&screenwidth, &screenheight, &bpp); + /* get resolution corresponding to these */ + Resolution_Search(&screenwidth, &screenheight, &bpp, keep); + /* re-calculate statusbar height for this resolution */ sbarheight = Statusbar_SetHeight(screenwidth, screenheight-sbarheight); hs_bpp = bpp; @@ -163,14 +177,16 @@ void HostScreen_setWindowSize(int width, * 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; + hs_rect.x = 0; + hs_rect.y = 0; + hs_rect.w = screenwidth; + hs_rect.h = screenheight - sbarheight; - if (sdlscrn && (!bpp || sdlscrn->format->BitsPerPixel == bpp) && - sdlscrn->w == (signed)screenwidth && sdlscrn->h == (signed)screenheight && - (sdlscrn->flags&SDL_FULLSCREEN) == (sdl_videoparams&SDL_FULLSCREEN)) + if (!Screen_SetSDLVideoSize(screenwidth, screenheight, bpp, bForceChange)) { - /* no time consuming host video mode change needed */ + /* same host screen size despite Atari resolution change, + * -> no time consuming host video mode change needed + */ if (screenwidth > width || screenheight > height+sbarheight) { /* Atari screen smaller than host -> clear screen */ SDL_Rect rect; @@ -179,104 +195,105 @@ void HostScreen_setWindowSize(int width, rect.w = sdlscrn->w; rect.h = sdlscrn->h - sbarheight; SDL_FillRect(sdlscrn, &rect, SDL_MapRGB(sdlscrn->format, 0, 0, 0)); + /* re-calculate variables in case height + statusbar height + * don't anymore match SDL surface size (there's an assert + * for that) + */ + Statusbar_Init(sdlscrn); } - return; - } - - if (bInFullScreen) { - /* un-embed the Hatari WM window for fullscreen */ - Control_ReparentWindow(screenwidth, screenheight, bInFullScreen); - - sdl_videoparams = SDL_SWSURFACE|SDL_HWPALETTE|SDL_FULLSCREEN; - } else { - sdl_videoparams = SDL_SWSURFACE|SDL_HWPALETTE; - } -#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"); +#if WITH_SDL2 + doUpdate = true; +#else + // check in case switched from VDI to Hostscreen + doUpdate = ( sdlscrn->flags & SDL_HWSURFACE ) == 0; #endif - if (!bInFullScreen) { - /* re-embed the new Hatari SDL window */ - Control_ReparentWindow(screenwidth, screenheight, bInFullScreen); + return; } - // update the surface's palette - HostScreen_updatePalette( 256 ); + // In case surface format changed, update SDL palette & remap the native palette + HostScreen_updatePalette(256); + HostScreen_remapPalette(); // redraw statusbar - Statusbar_Init(mainSurface); + Statusbar_Init(sdlscrn); - Dprintf(("Surface Pitch = %d, width = %d, height = %d\n", surf->pitch, surf->w, surf->h)); - Dprintf(("Must Lock? %s\n", SDL_MUSTLOCK(surf) ? "YES" : "NO")); + Dprintf(("Surface Pitch = %d, width = %d, height = %d\n", sdlscrn->pitch, sdlscrn->w, sdlscrn->h)); + Dprintf(("Must Lock? %s\n", SDL_MUSTLOCK(sdlscrn) ? "YES" : "NO")); +#if WITH_SDL2 + doUpdate = true; +#else // is the SDL_update needed? - doUpdate = ( surf->flags & SDL_HWSURFACE ) == 0; + doUpdate = ( sdlscrn->flags & SDL_HWSURFACE ) == 0; +#endif 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", - surf->format->BitsPerPixel, - 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)); + sdlscrn->format->BitsPerPixel, + sdlscrn->format->Rmask, sdlscrn->format->Gmask, sdlscrn->format->Bmask, + sdlscrn->format->Rshift, sdlscrn->format->Gshift, sdlscrn->format->Bshift, + sdlscrn->format->Rloss, sdlscrn->format->Gloss, sdlscrn->format->Bloss)); - Main_WarpMouse(sdlscrn->w/2,sdlscrn->h/2); + Main_WarpMouse(sdlscrn->w/2,sdlscrn->h/2, false); } -static void HostScreen_update5(Sint32 x, Sint32 y, Sint32 w, Sint32 h, bool forced) +void HostScreen_update1(SDL_Rect *extra, bool forced) { + SDL_Rect rects[2]; + int count = 1; + if ( !forced && !doUpdate ) // the HW surface is available return; - SDL_UpdateRect(mainSurface, x, y, w, h); -} - -void HostScreen_update1(bool forced) -{ - HostScreen_update5( 0, 0, hs_width, hs_height, forced ); + rects[0] = hs_rect; + if (extra) { + rects[1] = *extra; + count = 2; + } + SDL_UpdateRects(sdlscrn, count, rects); } Uint32 HostScreen_getBpp(void) { - return surf->format->BytesPerPixel; + return sdlscrn->format->BytesPerPixel; } Uint32 HostScreen_getPitch(void) { - return surf->pitch; + return sdlscrn->pitch; } Uint32 HostScreen_getWidth(void) { - return hs_width; + return hs_rect.w; } Uint32 HostScreen_getHeight(void) { - return hs_height; + return hs_rect.h; } Uint8 *HostScreen_getVideoramAddress(void) { - return surf->pixels; /* FIXME maybe this should be mainSurface? */ + return sdlscrn->pixels; } -void HostScreen_setPaletteColor(Uint8 idx, Uint32 red, Uint32 green, Uint32 blue) +SDL_PixelFormat *HostScreen_getFormat(void) +{ + return sdlscrn->format; +} + +void HostScreen_setPaletteColor(Uint8 idx, Uint8 red, Uint8 green, Uint8 blue) { // set the SDL standard RGB palette settings palette.standard[idx].r = red; palette.standard[idx].g = green; palette.standard[idx].b = blue; // convert the color to native - palette.native[idx] = SDL_MapRGB( surf->format, red, green, blue ); + palette.native[idx] = SDL_MapRGB( sdlscrn->format, red, green, blue ); } Uint32 HostScreen_getPaletteColor(Uint8 idx) @@ -284,21 +301,27 @@ Uint32 HostScreen_getPaletteColor(Uint8 return palette.native[idx]; } -void HostScreen_updatePalette(Uint16 colorCount) +void HostScreen_updatePalette(int colorCount) { - SDL_SetColors( surf, palette.standard, 0, colorCount ); + SDL_SetColors( sdlscrn, palette.standard, 0, colorCount ); } -Uint32 HostScreen_getColor(Uint32 red, Uint32 green, Uint32 blue) +static void HostScreen_remapPalette(void) { - return SDL_MapRGB( surf->format, red, green, blue ); -} + int i; + Uint32 *native = palette.native; + SDL_Color *standard = palette.standard; + SDL_PixelFormat *fmt = sdlscrn->format; + for(i = 0; i < 256; i++, native++, standard++) { + *native = SDL_MapRGB(fmt, standard->r, standard->g, standard->b); + } +} bool HostScreen_renderBegin(void) { - if (SDL_MUSTLOCK(surf)) - if (SDL_LockSurface(surf) < 0) { + if (SDL_MUSTLOCK(sdlscrn)) + if (SDL_LockSurface(sdlscrn) < 0) { printf("Couldn't lock surface to refresh!\n"); return false; } @@ -306,9 +329,14 @@ bool HostScreen_renderBegin(void) return true; } -void HostScreen_renderEnd(void) -{ - if (SDL_MUSTLOCK(surf)) - SDL_UnlockSurface(surf); - Statusbar_Update(surf); +/** + * Direct surface writes done, so unlock screen, + * check for statusbar updates and if there were such, + * return which area needs update. + */ +SDL_Rect* HostScreen_renderEnd(void) +{ + if (SDL_MUSTLOCK(sdlscrn)) + SDL_UnlockSurface(sdlscrn); + return Statusbar_Update(sdlscrn, false); }