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

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

unix.superglobalmegacorp.com

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