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

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

unix.superglobalmegacorp.com

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