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