|
|
1.1 root 1: /*
2: Hatari - hostscreen.c
3:
4: This file is distributed under the GNU Public License, version 2 or at
5: your option any later version. Read the file gpl.txt for details.
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:
13: #include "main.h"
14: #include "configuration.h"
1.1.1.2 root 15: #include "control.h"
1.1 root 16: #include "sysdeps.h"
17: #include "stMemory.h"
18: #include "ioMem.h"
19: #include "hostscreen.h"
20: #include "screen.h"
1.1.1.2 root 21: #include "statusbar.h"
1.1 root 22:
23: #define VIDEL_DEBUG 0
24:
25: #if VIDEL_DEBUG
26: #define Dprintf(a) printf a
27: #else
28: #define Dprintf(a)
29: #endif
30:
31:
32: #define RGB_BLACK 0x00000000
33: #define RGB_BLUE 0x000000ff
34: #define RGB_GREEN 0x00ff0000
35: #define RGB_CYAN 0x00ff00ff
36: #define RGB_RED 0xff000000
37: #define RGB_MAGENTA 0xff0000ff
38: #define RGB_LTGRAY 0xbbbb00bb
39: #define RGB_GRAY 0x88880088
40: #define RGB_LTBLUE 0x000000aa
41: #define RGB_LTGREEN 0x00aa0000
42: #define RGB_LTCYAN 0x00aa00aa
43: #define RGB_LTRED 0xaa000000
44: #define RGB_LTMAGENTA 0xaa0000aa
45: #define RGB_YELLOW 0xffff0000
46: #define RGB_LTYELLOW 0xaaaa0000
47: #define RGB_WHITE 0xffff00ff
48:
49:
50: static SDL_Surface *mainSurface; // The main window surface
51: static SDL_Surface *surf; // pointer to actual surface
52:
53:
1.1.1.2 root 54: static Uint32 sdl_videoparams;
55: static Uint32 hs_width, hs_height, hs_bpp;
56: static bool doUpdate; // the HW surface is available -> the SDL need not to update the surface after ->pixel access
1.1 root 57:
58: static struct { // TOS palette (bpp < 16) to SDL color mapping
59: SDL_Color standard[256];
1.1.1.2 root 60: Uint32 native[256];
1.1 root 61: } palette;
62:
63:
64: static const unsigned long default_palette[] = {
65: RGB_WHITE, RGB_RED, RGB_GREEN, RGB_YELLOW,
66: RGB_BLUE, RGB_MAGENTA, RGB_CYAN, RGB_LTGRAY,
67: RGB_GRAY, RGB_LTRED, RGB_LTGREEN, RGB_LTYELLOW,
68: RGB_LTBLUE, RGB_LTMAGENTA, RGB_LTCYAN, RGB_BLACK
69: };
70:
1.1.1.2 root 71: static int HostScreen_selectVideoMode(SDL_Rect **modes, Uint32 *width, Uint32 *height);
72: static void HostScreen_searchVideoMode( Uint32 *width, Uint32 *height, Uint32 *bpp );
1.1 root 73:
74:
1.1.1.4 ! root 75: void HostScreen_Init(void)
! 76: {
1.1 root 77: int i;
78: for(i=0; i<256; i++) {
79: unsigned long color = default_palette[i%16];
80: palette.standard[i].r = color >> 24;
81: palette.standard[i].g = (color >> 16) & 0xff;
82: palette.standard[i].b = color & 0xff;
83: }
84:
85: mainSurface=NULL;
86: }
87:
1.1.1.4 ! root 88: void HostScreen_UnInit(void)
! 89: {
1.1 root 90: }
91:
92:
93: void HostScreen_toggleFullScreen(void)
94: {
95: sdl_videoparams ^= SDL_FULLSCREEN;
1.1.1.2 root 96: if (sdl_videoparams & SDL_FULLSCREEN) {
97: /* un-embed the Hatari WM window for fullscreen */
1.1.1.4 ! root 98: Control_ReparentWindow(hs_width, hs_height, true);
1.1.1.2 root 99: }
1.1 root 100: if(SDL_WM_ToggleFullScreen(mainSurface) == 0) {
101: // SDL_WM_ToggleFullScreen() did not work.
102: // We have to change video mode "by hand".
103: SDL_Surface *temp = SDL_ConvertSurface(mainSurface, mainSurface->format,
104: mainSurface->flags);
105: Dprintf(("toggleFullScreen: SDL_WM_ToggleFullScreen() not supported"
106: " -> using SDL_SetVideoMode()"));
107: if (temp == NULL)
1.1.1.4 ! root 108: Dprintf(("toggleFullScreen: Unable to save screen content."));
1.1 root 109:
110: #if 1
111: HostScreen_setWindowSize(hs_width, hs_height, hs_bpp);
112: #else
113: mainSurface = SDL_SetVideoMode(width, height, bpp, sdl_videoparams);
114: if (mainSurface == NULL)
1.1.1.4 ! root 115: Dprintf(("toggleFullScreen: Unable to set new video mode."));
1.1 root 116: if (mainSurface->format->BitsPerPixel <= 8)
117: SDL_SetColors(mainSurface, temp->format->palette->colors, 0,
118: temp->format->palette->ncolors);
119: #endif
120:
121: if (SDL_BlitSurface(temp, NULL, mainSurface, NULL) != 0)
1.1.1.4 ! root 122: Dprintf(("toggleFullScreen: Unable to restore screen content."));
1.1 root 123: SDL_FreeSurface(temp);
124:
125: /* refresh the screen */
1.1.1.4 ! root 126: HostScreen_update1(true);
1.1.1.2 root 127: } else {
128: if (!(sdl_videoparams & SDL_FULLSCREEN)) {
129: /* re-embed the new Hatari SDL window */
1.1.1.4 ! root 130: Control_ReparentWindow(hs_width, hs_height, false);
1.1.1.2 root 131: }
1.1 root 132: }
133: }
134:
1.1.1.2 root 135: static int HostScreen_selectVideoMode(SDL_Rect **modes, Uint32 *width, Uint32 *height)
1.1 root 136: {
137: int i, bestw, besth;
138:
139: /* Search the smallest nearest mode */
140: bestw = modes[0]->w;
141: besth = modes[0]->h;
142: for (i=0;modes[i]; ++i) {
143: if ((modes[i]->w >= *width) && (modes[i]->h >= *height)) {
144: if ((modes[i]->w < bestw) || (modes[i]->h < besth)) {
145: bestw = modes[i]->w;
146: besth = modes[i]->h;
147: }
148: }
149: }
150:
151: *width = bestw;
152: *height = besth;
153: Dprintf(("hostscreen: video mode found: %dx%d\n",*width,*height));
154:
155: return 1;
156: }
157:
1.1.1.2 root 158: static void HostScreen_searchVideoMode( Uint32 *width, Uint32 *height, Uint32 *bpp )
1.1 root 159: {
160: SDL_Rect **modes;
161: SDL_PixelFormat pixelformat;
162: int modeflags;
163:
164: /* Search in available modes the best suited */
165: Dprintf(("hostscreen: video mode asked: %dx%dx%d\n",*width,*height,*bpp));
166:
167: if ((*width == 0) || (*height == 0)) {
168: *width = 640;
169: *height = 480;
170: }
171:
172: /* Read available video modes */
173: modeflags = 0 /*SDL_HWSURFACE | SDL_HWPALETTE*/;
174: if (bInFullScreen)
175: modeflags |= SDL_FULLSCREEN;
176:
177: /*--- Search a video mode with asked bpp ---*/
178: if (*bpp != 0) {
179: pixelformat.BitsPerPixel = *bpp;
180: modes = SDL_ListModes(&pixelformat, modeflags);
181: if ((modes != (SDL_Rect **) 0) && (modes != (SDL_Rect **) -1)) {
182: Dprintf(("hostscreen: searching a good video mode (any bpp)\n"));
183: if (HostScreen_selectVideoMode(modes,width,height)) {
184: Dprintf(("hostscreen: video mode selected: %dx%dx%d\n",*width,*height,*bpp));
185: return;
186: }
187: }
188: }
189:
190: /*--- Search a video mode with any bpp ---*/
191: modes = SDL_ListModes(NULL, modeflags);
192: if ((modes != (SDL_Rect **) 0) && (modes != (SDL_Rect **) -1)) {
193: Dprintf(("hostscreen: searching a good video mode\n"));
194: if (HostScreen_selectVideoMode(modes,width,height)) {
195: Dprintf(("hostscreen: video mode selected: %dx%dx%d\n",*width,*height,*bpp));
196: return;
197: }
198: }
199:
200: if (modes == (SDL_Rect **) 0) {
201: Dprintf(("hostscreen: No modes available\n"));
202: }
203:
204: if (modes == (SDL_Rect **) -1) {
205: /* Any mode available */
206: Dprintf(("hostscreen: Any modes available\n"));
207: }
208:
209: Dprintf(("hostscreen: video mode selected: %dx%dx%d\n",*width,*height,*bpp));
210: }
211:
1.1.1.2 root 212: void HostScreen_setWindowSize( Uint32 width, Uint32 height, Uint32 bpp )
1.1 root 213: {
1.1.1.2 root 214: Uint32 screenheight;
1.1.1.4 ! root 215:
! 216: if (bpp == 24)
! 217: bpp = 32;
! 218:
1.1 root 219: nScreenZoomX = 1;
220: nScreenZoomY = 1;
221: if (ConfigureParams.Screen.bZoomLowRes)
222: {
223: /* Ugly: 400x300 threshold is currently hard-coded. */
224: /* Should rather be selectable by the user! */
1.1.1.4 ! root 225: if (width && width <= 400)
1.1 root 226: {
227: nScreenZoomX = (800/width);
228: width *= nScreenZoomX;
229: }
1.1.1.4 ! root 230: if (height && height <= 300)
1.1 root 231: {
232: nScreenZoomY = (550/height);
233: height *= nScreenZoomY;
234: }
235: }
1.1.1.2 root 236: screenheight = height + Statusbar_SetHeight(width, height);
1.1 root 237:
238: // Select a correct video mode
1.1.1.2 root 239: HostScreen_searchVideoMode(&width, &screenheight, &bpp);
1.1 root 240:
1.1.1.2 root 241: hs_width = width;
1.1 root 242: hs_height = height;
243: hs_bpp = bpp;
244:
245: // SelectVideoMode();
1.1.1.2 root 246: if (bInFullScreen) {
247: /* un-embed the Hatari WM window for fullscreen */
248: Control_ReparentWindow(width, screenheight, bInFullScreen);
249:
1.1 root 250: sdl_videoparams = SDL_SWSURFACE|SDL_HWPALETTE|SDL_FULLSCREEN;
1.1.1.2 root 251: } else {
1.1 root 252: sdl_videoparams = SDL_SWSURFACE|SDL_HWPALETTE;
1.1.1.2 root 253: }
254: mainSurface = SDL_SetVideoMode(width, screenheight, bpp, sdl_videoparams);
255: if (!bInFullScreen) {
256: /* re-embed the new Hatari SDL window */
257: Control_ReparentWindow(width, screenheight, bInFullScreen);
258: }
1.1 root 259: sdlscrn = surf = mainSurface;
260:
261: // update the surface's palette
262: HostScreen_updatePalette( 256 );
263:
1.1.1.2 root 264: Statusbar_Init(mainSurface);
265:
1.1 root 266: Dprintf(("Surface Pitch = %d, width = %d, height = %d\n", surf->pitch, surf->w, surf->h));
267: Dprintf(("Must Lock? %s\n", SDL_MUSTLOCK(surf) ? "YES" : "NO"));
268:
269: // is the SDL_update needed?
270: doUpdate = ( surf->flags & SDL_HWSURFACE ) == 0;
271:
272: HostScreen_renderBegin();
273:
274: // VideoRAMBaseHost = (uint8 *) surf->pixels;
275: // InitVMEMBaseDiff(VideoRAMBaseHost, VideoRAMBase);
276: // Dprintf(("VideoRAM starts at %p (%08x)\n", VideoRAMBaseHost, VideoRAMBase));
277: Dprintf(("surf->pixels = %p, getVideoSurface() = %p\n",
278: surf->pixels, SDL_GetVideoSurface()->pixels));
279:
280: HostScreen_renderEnd();
281:
282: Dprintf(("Pixel format:bitspp=%d, tmasks r=%04x g=%04x b=%04x"
283: ", tshifts r=%d g=%d b=%d"
284: ", tlosses r=%d g=%d b=%d\n",
285: surf->format->BitsPerPixel,
286: surf->format->Rmask, surf->format->Gmask, surf->format->Bmask,
287: surf->format->Rshift, surf->format->Gshift, surf->format->Bshift,
288: surf->format->Rloss, surf->format->Gloss, surf->format->Bloss));
289: }
290:
291:
1.1.1.2 root 292: static void HostScreen_update5(Sint32 x, Sint32 y, Sint32 w, Sint32 h, bool forced)
1.1 root 293: {
294: if ( !forced && !doUpdate ) // the HW surface is available
295: return;
296:
297: SDL_UpdateRect(mainSurface, x, y, w, h);
298: }
299:
1.1.1.2 root 300: void HostScreen_update1(bool forced)
1.1 root 301: {
302: HostScreen_update5( 0, 0, hs_width, hs_height, forced );
303: }
304:
305:
1.1.1.4 ! root 306: Uint32 HostScreen_getBpp(void)
1.1 root 307: {
308: return surf->format->BytesPerPixel;
309: }
310:
1.1.1.4 ! root 311: Uint32 HostScreen_getPitch(void)
! 312: {
1.1 root 313: return surf->pitch;
314: }
315:
1.1.1.4 ! root 316: Uint32 HostScreen_getWidth(void)
! 317: {
1.1 root 318: return hs_width;
319: }
320:
1.1.1.4 ! root 321: Uint32 HostScreen_getHeight(void)
! 322: {
1.1 root 323: return hs_height;
324: }
325:
1.1.1.4 ! root 326: Uint8 *HostScreen_getVideoramAddress(void)
! 327: {
1.1 root 328: return surf->pixels; /* FIXME maybe this should be mainSurface? */
329: }
330:
1.1.1.4 ! root 331: void HostScreen_setPaletteColor(Uint8 idx, Uint32 red, Uint32 green, Uint32 blue)
! 332: {
1.1 root 333: // set the SDL standard RGB palette settings
334: palette.standard[idx].r = red;
335: palette.standard[idx].g = green;
336: palette.standard[idx].b = blue;
337: // convert the color to native
338: palette.native[idx] = SDL_MapRGB( surf->format, red, green, blue );
339: }
340:
1.1.1.4 ! root 341: Uint32 HostScreen_getPaletteColor(Uint8 idx)
! 342: {
1.1 root 343: return palette.native[idx];
344: }
345:
1.1.1.4 ! root 346: void HostScreen_updatePalette(Uint16 colorCount)
! 347: {
1.1 root 348: SDL_SetColors( surf, palette.standard, 0, colorCount );
349: }
350:
1.1.1.4 ! root 351: Uint32 HostScreen_getColor(Uint32 red, Uint32 green, Uint32 blue)
! 352: {
1.1 root 353: return SDL_MapRGB( surf->format, red, green, blue );
354: }
355:
356:
1.1.1.2 root 357: bool HostScreen_renderBegin(void)
358: {
1.1 root 359: if (SDL_MUSTLOCK(surf))
360: if (SDL_LockSurface(surf) < 0) {
361: printf("Couldn't lock surface to refresh!\n");
1.1.1.4 ! root 362: return false;
1.1 root 363: }
364:
1.1.1.4 ! root 365: return true;
1.1 root 366: }
367:
1.1.1.4 ! root 368: void HostScreen_renderEnd(void)
! 369: {
1.1 root 370: if (SDL_MUSTLOCK(surf))
371: SDL_UnlockSurface(surf);
1.1.1.2 root 372: Statusbar_Update(surf);
1.1 root 373: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.