Annotation of hatari/src/falcon/hostscreen.c, revision 1.1.1.9

1.1       root        1: /*
                      2:   Hatari - hostscreen.c
                      3: 
1.1.1.7   root        4:   This file is distributed under the GNU General Public License, version 2
                      5:   or at your option any later version. Read the file gpl.txt for details.
1.1       root        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: */
1.1.1.4   root       11: const char HostScreen_fileid[] = "Hatari hostscreen.c : " __DATE__ " " __TIME__;
1.1       root       12: 
1.1.1.6   root       13: #include <SDL.h>
1.1       root       14: #include "main.h"
                     15: #include "configuration.h"
1.1.1.2   root       16: #include "control.h"
1.1       root       17: #include "sysdeps.h"
                     18: #include "stMemory.h"
                     19: #include "ioMem.h"
                     20: #include "hostscreen.h"
1.1.1.5   root       21: #include "resolution.h"
1.1       root       22: #include "screen.h"
1.1.1.2   root       23: #include "statusbar.h"
1.1       root       24: 
                     25: #define VIDEL_DEBUG 0
                     26: 
                     27: #if VIDEL_DEBUG
                     28: #define Dprintf(a) printf a
                     29: #else
                     30: #define Dprintf(a)
                     31: #endif
                     32: 
                     33: 
                     34: #define RGB_BLACK     0x00000000
                     35: #define RGB_BLUE      0x000000ff
                     36: #define RGB_GREEN     0x00ff0000
                     37: #define RGB_CYAN      0x00ff00ff
                     38: #define RGB_RED       0xff000000
                     39: #define RGB_MAGENTA   0xff0000ff
                     40: #define RGB_LTGRAY    0xbbbb00bb
                     41: #define RGB_GRAY      0x88880088
                     42: #define RGB_LTBLUE    0x000000aa
                     43: #define RGB_LTGREEN   0x00aa0000
                     44: #define RGB_LTCYAN    0x00aa00aa
                     45: #define RGB_LTRED     0xaa000000
                     46: #define RGB_LTMAGENTA 0xaa0000aa
                     47: #define RGB_YELLOW    0xffff0000
                     48: #define RGB_LTYELLOW  0xaaaa0000
                     49: #define RGB_WHITE     0xffff00ff
                     50: 
                     51: 
1.1.1.5   root       52: /* TODO: put these hostscreen globals to some struct */
1.1.1.8   root       53: static SDL_Rect hs_rect;
                     54: static int hs_width_req, hs_height_req, hs_bpp;
1.1.1.2   root       55: static bool   doUpdate; // the HW surface is available -> the SDL need not to update the surface after ->pixel access
1.1       root       56: 
1.1.1.6   root       57: static void HostScreen_remapPalette(void);
                     58: 
1.1       root       59: static struct { // TOS palette (bpp < 16) to SDL color mapping
                     60:        SDL_Color       standard[256];
1.1.1.2   root       61:        Uint32          native[256];
1.1       root       62: } palette;
                     63: 
                     64: 
1.1.1.6   root       65: static const Uint32 default_palette[] = {
1.1       root       66:     RGB_WHITE, RGB_RED, RGB_GREEN, RGB_YELLOW,
                     67:     RGB_BLUE, RGB_MAGENTA, RGB_CYAN, RGB_LTGRAY,
                     68:     RGB_GRAY, RGB_LTRED, RGB_LTGREEN, RGB_LTYELLOW,
                     69:     RGB_LTBLUE, RGB_LTMAGENTA, RGB_LTCYAN, RGB_BLACK
                     70: };
                     71: 
                     72: 
1.1.1.4   root       73: void HostScreen_Init(void)
                     74: {
1.1       root       75:        int i;
1.1.1.6   root       76:        for(i = 0; i < 256; i++) {
                     77:                Uint32 color = default_palette[i%16];
1.1       root       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: 
1.1.1.4   root       84: void HostScreen_UnInit(void)
                     85: {
1.1       root       86: }
                     87: 
                     88: 
                     89: void HostScreen_toggleFullScreen(void)
                     90: {
1.1.1.9 ! root       91:        HostScreen_setWindowSize(hs_width_req, hs_height_req, hs_bpp, true);
1.1.1.6   root       92:        /* force screen redraw */
1.1.1.8   root       93:        HostScreen_update1(NULL, true);
1.1       root       94: }
                     95: 
                     96: 
1.1.1.9 ! root       97: void HostScreen_setWindowSize(int width, int height, int bpp, bool bForceChange)
1.1       root       98: {
1.1.1.8   root       99:        const bool keep = ConfigureParams.Screen.bKeepResolution;
1.1.1.5   root      100:        int screenwidth, screenheight, maxw, maxh;
                    101:        int scalex, scaley, sbarheight;
1.1       root      102: 
1.1.1.5   root      103:        if (bpp == 24)
                    104:                bpp = 32;
1.1       root      105: 
1.1.1.6   root      106:        /* constrain size request to user's desktop size */
                    107:        Resolution_GetDesktopSize(&maxw, &maxh);
                    108:        scalex = scaley = 1;
                    109:        while (width > maxw*scalex) {
                    110:                scalex *= 2;
                    111:        }
1.1.1.9 ! root      112:        while (height > maxh*scaley) {
        !           113:                scaley *= 2;
1.1.1.6   root      114:        }
                    115:        if (scalex * scaley > 1) {
                    116:                fprintf(stderr, "WARNING: too large screen size %dx%d -> divided by %dx%d!\n",
                    117:                        width, height, scalex, scaley);
                    118:                width /= scalex;
                    119:                height /= scaley;
                    120:        }
1.1       root      121: 
1.1.1.8   root      122:        Resolution_GetLimits(&maxw, &maxh, &bpp, keep);
1.1.1.5   root      123:        nScreenZoomX = nScreenZoomY = 1;
                    124:        
                    125:        if (ConfigureParams.Screen.bAspectCorrect) {
                    126:                /* Falcon (and TT) pixel scaling factors seem to 2^x
                    127:                 * (quarter/half pixel, interlace/double line), so
                    128:                 * do aspect correction as 2's exponent.
                    129:                 */
                    130:                while (nScreenZoomX*width < height &&
                    131:                       2*nScreenZoomX*width < maxw) {
                    132:                        nScreenZoomX *= 2;
1.1       root      133:                }
1.1.1.5   root      134:                while (2*nScreenZoomY*height < width &&
                    135:                       2*nScreenZoomY*height < maxh) {
                    136:                        nScreenZoomY *= 2;
                    137:                }
                    138:                if (nScreenZoomX*nScreenZoomY > 2) {
                    139:                        fprintf(stderr, "WARNING: strange screen size %dx%d -> aspect corrected by %dx%d!\n",
                    140:                                width, height, nScreenZoomX, nScreenZoomY);
1.1       root      141:                }
                    142:        }
                    143: 
1.1.1.5   root      144:        /* then select scale as close to target size as possible
                    145:         * without having larger size than it
                    146:         */
                    147:        scalex = maxw/(nScreenZoomX*width);
                    148:        scaley = maxh/(nScreenZoomY*height);
                    149:        if (scalex > 1 && scaley > 1) {
                    150:                /* keep aspect ratio */
                    151:                if (scalex < scaley) {
                    152:                        nScreenZoomX *= scalex;
                    153:                        nScreenZoomY *= scalex;
                    154:                } else {
                    155:                        nScreenZoomX *= scaley;
                    156:                        nScreenZoomY *= scaley;
                    157:                }
1.1       root      158:        }
                    159: 
1.1.1.5   root      160:        hs_width_req = width;
                    161:        hs_height_req = height;
                    162:        width *= nScreenZoomX;
                    163:        height *= nScreenZoomY;
                    164: 
1.1.1.6   root      165:        /* get statusbar size for this screen size */
1.1.1.5   root      166:        sbarheight = Statusbar_GetHeightForSize(width, height);
                    167:        screenheight = height + sbarheight;
                    168:        screenwidth = width;
1.1.1.4   root      169: 
1.1.1.6   root      170:        /* get resolution corresponding to these */
1.1.1.8   root      171:        Resolution_Search(&screenwidth, &screenheight, &bpp, keep);
1.1.1.6   root      172:        /* re-calculate statusbar height for this resolution */
1.1.1.5   root      173:        sbarheight = Statusbar_SetHeight(screenwidth, screenheight-sbarheight);
1.1.1.4   root      174: 
1.1.1.5   root      175:        hs_bpp = bpp;
                    176:        /* videl.c might scale things differently in fullscreen than
                    177:         * in windowed mode because this uses screensize instead of using
                    178:         * the aspect scaled sizes directly, but it works better this way.
                    179:         */
1.1.1.8   root      180:        hs_rect.x = 0;
                    181:        hs_rect.y = 0;
                    182:        hs_rect.w = screenwidth;
                    183:        hs_rect.h = screenheight - sbarheight;
1.1.1.5   root      184: 
1.1.1.9 ! root      185:        if (!Screen_SetSDLVideoSize(screenwidth, screenheight, bpp, bForceChange))
1.1       root      186:        {
1.1.1.6   root      187:                /* same host screen size despite Atari resolution change,
                    188:                 * -> no time consuming host video mode change needed
                    189:                 */
1.1.1.5   root      190:                if (screenwidth > width || screenheight > height+sbarheight) {
                    191:                        /* Atari screen smaller than host -> clear screen */
                    192:                        SDL_Rect rect;
                    193:                        rect.x = 0;
                    194:                        rect.y = 0;
                    195:                        rect.w = sdlscrn->w;
                    196:                        rect.h = sdlscrn->h - sbarheight;
                    197:                        SDL_FillRect(sdlscrn, &rect, SDL_MapRGB(sdlscrn->format, 0, 0, 0));
1.1.1.6   root      198:                        /* re-calculate variables in case height + statusbar height
                    199:                         * don't anymore match SDL surface size (there's an assert
                    200:                         * for that)
                    201:                         */
                    202:                        Statusbar_Init(sdlscrn);
1.1       root      203:                }
1.1.1.9 ! root      204: #if WITH_SDL2
        !           205:                doUpdate = true;
        !           206: #else
1.1.1.6   root      207:                // check in case switched from VDI to Hostscreen
                    208:                doUpdate = ( sdlscrn->flags & SDL_HWSURFACE ) == 0;
1.1.1.5   root      209: #endif
1.1.1.9 ! root      210:                return;
1.1.1.2   root      211:        }
1.1       root      212: 
1.1.1.6   root      213:        // In case surface format changed, update SDL palette & remap the native palette
                    214:        HostScreen_updatePalette(256);
                    215:        HostScreen_remapPalette();
1.1       root      216: 
1.1.1.5   root      217:        // redraw statusbar
1.1.1.6   root      218:        Statusbar_Init(sdlscrn);
1.1.1.2   root      219: 
1.1.1.6   root      220:        Dprintf(("Surface Pitch = %d, width = %d, height = %d\n", sdlscrn->pitch, sdlscrn->w, sdlscrn->h));
                    221:        Dprintf(("Must Lock? %s\n", SDL_MUSTLOCK(sdlscrn) ? "YES" : "NO"));
1.1       root      222: 
1.1.1.9 ! root      223: #if WITH_SDL2
        !           224:        doUpdate = true;
        !           225: #else
1.1       root      226:        // is the SDL_update needed?
1.1.1.6   root      227:        doUpdate = ( sdlscrn->flags & SDL_HWSURFACE ) == 0;
1.1.1.9 ! root      228: #endif
1.1       root      229: 
                    230:        Dprintf(("Pixel format:bitspp=%d, tmasks r=%04x g=%04x b=%04x"
                    231:                        ", tshifts r=%d g=%d b=%d"
                    232:                        ", tlosses r=%d g=%d b=%d\n",
1.1.1.6   root      233:                        sdlscrn->format->BitsPerPixel,
                    234:                        sdlscrn->format->Rmask, sdlscrn->format->Gmask, sdlscrn->format->Bmask,
                    235:                        sdlscrn->format->Rshift, sdlscrn->format->Gshift, sdlscrn->format->Bshift,
                    236:                        sdlscrn->format->Rloss, sdlscrn->format->Gloss, sdlscrn->format->Bloss));
1.1.1.5   root      237: 
1.1.1.9 ! root      238:        Main_WarpMouse(sdlscrn->w/2,sdlscrn->h/2, false);
1.1       root      239: }
                    240: 
                    241: 
1.1.1.8   root      242: void HostScreen_update1(SDL_Rect *extra, bool forced)
1.1       root      243: {
1.1.1.8   root      244:        SDL_Rect rects[2];
                    245:        int count = 1;
                    246: 
1.1       root      247:        if ( !forced && !doUpdate ) // the HW surface is available
                    248:                return;
                    249: 
1.1.1.8   root      250:        rects[0] = hs_rect;
                    251:        if (extra) {
                    252:                rects[1] = *extra;
                    253:                count = 2;
                    254:        }
                    255:        SDL_UpdateRects(sdlscrn, count, rects);
1.1       root      256: }
                    257: 
                    258: 
1.1.1.4   root      259: Uint32 HostScreen_getBpp(void)
1.1       root      260: {
1.1.1.6   root      261:        return sdlscrn->format->BytesPerPixel;
1.1       root      262: }
                    263: 
1.1.1.4   root      264: Uint32 HostScreen_getPitch(void)
                    265: {
1.1.1.6   root      266:        return sdlscrn->pitch;
1.1       root      267: }
                    268: 
1.1.1.4   root      269: Uint32 HostScreen_getWidth(void)
                    270: {
1.1.1.8   root      271:        return hs_rect.w;
1.1       root      272: }
                    273: 
1.1.1.4   root      274: Uint32 HostScreen_getHeight(void)
                    275: {
1.1.1.8   root      276:        return hs_rect.h;
1.1       root      277: }
                    278: 
1.1.1.4   root      279: Uint8 *HostScreen_getVideoramAddress(void)
                    280: {
1.1.1.6   root      281:        return sdlscrn->pixels;
                    282: }
                    283: 
                    284: SDL_PixelFormat *HostScreen_getFormat(void)
                    285: {
                    286:        return sdlscrn->format;
1.1       root      287: }
                    288: 
1.1.1.6   root      289: void HostScreen_setPaletteColor(Uint8 idx, Uint8 red, Uint8 green, Uint8 blue)
1.1.1.4   root      290: {
1.1       root      291:        // set the SDL standard RGB palette settings
                    292:        palette.standard[idx].r = red;
                    293:        palette.standard[idx].g = green;
                    294:        palette.standard[idx].b = blue;
                    295:        // convert the color to native
1.1.1.6   root      296:        palette.native[idx] = SDL_MapRGB( sdlscrn->format, red, green, blue );
1.1       root      297: }
                    298: 
1.1.1.4   root      299: Uint32 HostScreen_getPaletteColor(Uint8 idx)
                    300: {
1.1       root      301:        return palette.native[idx];
                    302: }
                    303: 
1.1.1.6   root      304: void HostScreen_updatePalette(int colorCount)
1.1.1.4   root      305: {
1.1.1.6   root      306:        SDL_SetColors( sdlscrn, palette.standard, 0, colorCount );
1.1       root      307: }
                    308: 
1.1.1.6   root      309: static void HostScreen_remapPalette(void)
1.1.1.4   root      310: {
1.1.1.6   root      311:        int i;
                    312:        Uint32 *native = palette.native;
                    313:        SDL_Color *standard = palette.standard;
                    314:        SDL_PixelFormat *fmt = sdlscrn->format;
1.1       root      315: 
1.1.1.6   root      316:        for(i = 0; i < 256; i++, native++, standard++) {
                    317:                *native = SDL_MapRGB(fmt, standard->r, standard->g, standard->b);
                    318:        }
                    319: }
1.1       root      320: 
1.1.1.2   root      321: bool HostScreen_renderBegin(void)
                    322: {
1.1.1.6   root      323:        if (SDL_MUSTLOCK(sdlscrn))
                    324:                if (SDL_LockSurface(sdlscrn) < 0) {
1.1       root      325:                        printf("Couldn't lock surface to refresh!\n");
1.1.1.4   root      326:                        return false;
1.1       root      327:                }
                    328: 
1.1.1.4   root      329:        return true;
1.1       root      330: }
                    331: 
1.1.1.8   root      332: /**
                    333:  * Direct surface writes done, so unlock screen,
                    334:  * check for statusbar updates and if there were such,
                    335:  * return which area needs update.
                    336:  */
                    337: SDL_Rect* HostScreen_renderEnd(void)
1.1.1.4   root      338: {
1.1.1.6   root      339:        if (SDL_MUSTLOCK(sdlscrn))
                    340:                SDL_UnlockSurface(sdlscrn);
1.1.1.8   root      341:        return Statusbar_Update(sdlscrn, false);
1.1       root      342: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.