|
|
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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.