|
|
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: */
11: const char HostScreen_rcsid[] = "Hatari $Id: hostscreen.c,v 1.13 2007/04/04 15:23:58 thothy Exp $";
12:
13: #include "main.h"
14: #include "configuration.h"
15: #include "sysdeps.h"
16: #include "stMemory.h"
17: #include "ioMem.h"
18: #include "hostscreen.h"
19: #include "screen.h"
20:
21: #define VIDEL_DEBUG 0
22:
23: #if VIDEL_DEBUG
24: #define Dprintf(a) printf a
25: #else
26: #define Dprintf(a)
27: #endif
28:
29:
30: #define RGB_BLACK 0x00000000
31: #define RGB_BLUE 0x000000ff
32: #define RGB_GREEN 0x00ff0000
33: #define RGB_CYAN 0x00ff00ff
34: #define RGB_RED 0xff000000
35: #define RGB_MAGENTA 0xff0000ff
36: #define RGB_LTGRAY 0xbbbb00bb
37: #define RGB_GRAY 0x88880088
38: #define RGB_LTBLUE 0x000000aa
39: #define RGB_LTGREEN 0x00aa0000
40: #define RGB_LTCYAN 0x00aa00aa
41: #define RGB_LTRED 0xaa000000
42: #define RGB_LTMAGENTA 0xaa0000aa
43: #define RGB_YELLOW 0xffff0000
44: #define RGB_LTYELLOW 0xaaaa0000
45: #define RGB_WHITE 0xffff00ff
46:
47:
48: static SDL_Surface *mainSurface; // The main window surface
49: static SDL_Surface *surf; // pointer to actual surface
50:
51:
52: static SDL_mutex *screenLock;
53: static uint32 sdl_videoparams;
54: static uint32 hs_width, hs_height, hs_bpp;
55: static BOOL doUpdate; // the HW surface is available -> the SDL need not to update the surface after ->pixel access
56:
57: static struct { // TOS palette (bpp < 16) to SDL color mapping
58: SDL_Color standard[256];
59: uint32 native[256];
60: } palette;
61:
62:
63: static const unsigned long default_palette[] = {
64: RGB_WHITE, RGB_RED, RGB_GREEN, RGB_YELLOW,
65: RGB_BLUE, RGB_MAGENTA, RGB_CYAN, RGB_LTGRAY,
66: RGB_GRAY, RGB_LTRED, RGB_LTGREEN, RGB_LTYELLOW,
67: RGB_LTBLUE, RGB_LTMAGENTA, RGB_LTCYAN, RGB_BLACK
68: };
69:
70: static int HostScreen_selectVideoMode(SDL_Rect **modes, uint32 *width, uint32 *height);
71: static void HostScreen_searchVideoMode( uint32 *width, uint32 *height, uint32 *bpp );
72:
73:
74: void HostScreen_Init(void) {
75: int i;
76: for(i=0; i<256; i++) {
77: unsigned long color = default_palette[i%16];
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: screenLock = SDL_CreateMutex();
84:
85: mainSurface=NULL;
86: }
87:
88: void HostScreen_UnInit(void) {
89: SDL_DestroyMutex(screenLock);
90: }
91:
92:
93: void HostScreen_toggleFullScreen(void)
94: {
95: sdl_videoparams ^= SDL_FULLSCREEN;
96: if(SDL_WM_ToggleFullScreen(mainSurface) == 0) {
97: // SDL_WM_ToggleFullScreen() did not work.
98: // We have to change video mode "by hand".
99: SDL_Surface *temp = SDL_ConvertSurface(mainSurface, mainSurface->format,
100: mainSurface->flags);
101: Dprintf(("toggleFullScreen: SDL_WM_ToggleFullScreen() not supported"
102: " -> using SDL_SetVideoMode()"));
103: if (temp == NULL)
104: bug("toggleFullScreen: Unable to save screen content.");
105:
106: #if 1
107: HostScreen_setWindowSize(hs_width, hs_height, hs_bpp);
108: #else
109: mainSurface = SDL_SetVideoMode(width, height, bpp, sdl_videoparams);
110: if (mainSurface == NULL)
111: bug("toggleFullScreen: Unable to set new video mode.");
112: if (mainSurface->format->BitsPerPixel <= 8)
113: SDL_SetColors(mainSurface, temp->format->palette->colors, 0,
114: temp->format->palette->ncolors);
115: #endif
116:
117: if (SDL_BlitSurface(temp, NULL, mainSurface, NULL) != 0)
118: bug("toggleFullScreen: Unable to restore screen content.");
119: SDL_FreeSurface(temp);
120:
121: /* refresh the screen */
122: HostScreen_update1(TRUE);
123: }
124: }
125:
126: static int HostScreen_selectVideoMode(SDL_Rect **modes, uint32 *width, uint32 *height)
127: {
128: int i, bestw, besth;
129:
130: /* Search the smallest nearest mode */
131: bestw = modes[0]->w;
132: besth = modes[0]->h;
133: for (i=0;modes[i]; ++i) {
134: if ((modes[i]->w >= *width) && (modes[i]->h >= *height)) {
135: if ((modes[i]->w < bestw) || (modes[i]->h < besth)) {
136: bestw = modes[i]->w;
137: besth = modes[i]->h;
138: }
139: }
140: }
141:
142: *width = bestw;
143: *height = besth;
144: Dprintf(("hostscreen: video mode found: %dx%d\n",*width,*height));
145:
146: return 1;
147: }
148:
149: static void HostScreen_searchVideoMode( uint32 *width, uint32 *height, uint32 *bpp )
150: {
151: SDL_Rect **modes;
152: SDL_PixelFormat pixelformat;
153: int modeflags;
154:
155: /* Search in available modes the best suited */
156: Dprintf(("hostscreen: video mode asked: %dx%dx%d\n",*width,*height,*bpp));
157:
158: if ((*width == 0) || (*height == 0)) {
159: *width = 640;
160: *height = 480;
161: }
162:
163: /* Read available video modes */
164: modeflags = 0 /*SDL_HWSURFACE | SDL_HWPALETTE*/;
165: if (bInFullScreen)
166: modeflags |= SDL_FULLSCREEN;
167:
168: /*--- Search a video mode with asked bpp ---*/
169: if (*bpp != 0) {
170: pixelformat.BitsPerPixel = *bpp;
171: modes = SDL_ListModes(&pixelformat, modeflags);
172: if ((modes != (SDL_Rect **) 0) && (modes != (SDL_Rect **) -1)) {
173: Dprintf(("hostscreen: searching a good video mode (any bpp)\n"));
174: if (HostScreen_selectVideoMode(modes,width,height)) {
175: Dprintf(("hostscreen: video mode selected: %dx%dx%d\n",*width,*height,*bpp));
176: return;
177: }
178: }
179: }
180:
181: /*--- Search a video mode with any bpp ---*/
182: modes = SDL_ListModes(NULL, modeflags);
183: if ((modes != (SDL_Rect **) 0) && (modes != (SDL_Rect **) -1)) {
184: Dprintf(("hostscreen: searching a good video mode\n"));
185: if (HostScreen_selectVideoMode(modes,width,height)) {
186: Dprintf(("hostscreen: video mode selected: %dx%dx%d\n",*width,*height,*bpp));
187: return;
188: }
189: }
190:
191: if (modes == (SDL_Rect **) 0) {
192: Dprintf(("hostscreen: No modes available\n"));
193: }
194:
195: if (modes == (SDL_Rect **) -1) {
196: /* Any mode available */
197: Dprintf(("hostscreen: Any modes available\n"));
198: }
199:
200: Dprintf(("hostscreen: video mode selected: %dx%dx%d\n",*width,*height,*bpp));
201: }
202:
203: void HostScreen_setWindowSize( uint32 width, uint32 height, uint32 bpp )
204: {
205: nScreenZoomX = 1;
206: nScreenZoomY = 1;
207: if (ConfigureParams.Screen.bZoomLowRes)
208: {
209: /* Ugly: 400x300 threshold is currently hard-coded. */
210: /* Should rather be selectable by the user! */
211: if (width <= 400)
212: {
213: nScreenZoomX = (800/width);
214: width *= nScreenZoomX;
215: }
216: if (height <= 300)
217: {
218: nScreenZoomY = (550/height);
219: height *= nScreenZoomY;
220: }
221: }
222:
223: // Select a correct video mode
224: HostScreen_searchVideoMode(&width, &height, &bpp);
225:
226: hs_width = width;
227: hs_height = height;
228: hs_bpp = bpp;
229:
230: // SelectVideoMode();
231: if (bInFullScreen)
232: sdl_videoparams = SDL_SWSURFACE|SDL_HWPALETTE|SDL_FULLSCREEN;
233: else
234: sdl_videoparams = SDL_SWSURFACE|SDL_HWPALETTE;
235:
236: mainSurface = SDL_SetVideoMode(width, height, bpp, sdl_videoparams);
237:
238: sdlscrn = surf = mainSurface;
239:
240: // update the surface's palette
241: HostScreen_updatePalette( 256 );
242:
243: Dprintf(("Surface Pitch = %d, width = %d, height = %d\n", surf->pitch, surf->w, surf->h));
244: Dprintf(("Must Lock? %s\n", SDL_MUSTLOCK(surf) ? "YES" : "NO"));
245:
246: // is the SDL_update needed?
247: doUpdate = ( surf->flags & SDL_HWSURFACE ) == 0;
248:
249: HostScreen_renderBegin();
250:
251: // VideoRAMBaseHost = (uint8 *) surf->pixels;
252: // InitVMEMBaseDiff(VideoRAMBaseHost, VideoRAMBase);
253: // Dprintf(("VideoRAM starts at %p (%08x)\n", VideoRAMBaseHost, VideoRAMBase));
254: Dprintf(("surf->pixels = %p, getVideoSurface() = %p\n",
255: surf->pixels, SDL_GetVideoSurface()->pixels));
256:
257: HostScreen_renderEnd();
258:
259: Dprintf(("Pixel format:bitspp=%d, tmasks r=%04x g=%04x b=%04x"
260: ", tshifts r=%d g=%d b=%d"
261: ", tlosses r=%d g=%d b=%d\n",
262: surf->format->BitsPerPixel,
263: surf->format->Rmask, surf->format->Gmask, surf->format->Bmask,
264: surf->format->Rshift, surf->format->Gshift, surf->format->Bshift,
265: surf->format->Rloss, surf->format->Gloss, surf->format->Bloss));
266: }
267:
268:
269: static void HostScreen_update5( int32 x, int32 y, int32 w, int32 h, BOOL forced )
270: {
271: if ( !forced && !doUpdate ) // the HW surface is available
272: return;
273:
274: // SDL_UpdateRect(SDL_GetVideoSurface(), 0, 0, width, height);
275: // SDL_UpdateRect(surf, x, y, w, h);
276: SDL_UpdateRect(mainSurface, x, y, w, h);
277: }
278:
279: void HostScreen_update1( BOOL forced )
280: {
281: HostScreen_update5( 0, 0, hs_width, hs_height, forced );
282: }
283:
284: void HostScreen_update0()
285: {
286: HostScreen_update5( 0, 0, hs_width, hs_height, FALSE );
287: }
288:
289:
290: uint32 HostScreen_getBitsPerPixel(void)
291: {
292: return surf->format->BitsPerPixel;
293: }
294:
295:
296: #if 0
297: void HostScreen_gfxFastPixelColorNolock(int16 x, int16 y, uint32 color)
298: {
299: int bpp;
300: uint8 *p;
301:
302: /* Get destination format */
303: bpp = surf->format->BytesPerPixel;
304: p = (uint8 *)surf->pixels + y * surf->pitch + x * bpp;
305: switch(bpp) {
306: case 1:
307: *p = color;
308: break;
309: case 2:
310: *(uint16 *)p = color;
311: break;
312: case 3:
313: putBpp24Pixel( p, color );
314: break;
315: case 4:
316: *(uint32 *)p = color;
317: break;
318: } /* switch */
319: }
320: #endif
321:
322: #if 0
323: uint32 HostScreen_gfxGetPixel( int16 x, int16 y )
324: {
325: int bpp;
326: uint8 *p;
327:
328: /* Get destination format */
329: bpp = surf->format->BytesPerPixel;
330: p = (uint8 *)surf->pixels + y * surf->pitch + x * bpp;
331: switch(bpp) {
332: case 1:
333: return (uint32)(*(uint8 *)p);
334: case 2:
335: return (uint32)(*(uint16 *)p);
336: case 3:
337: // FIXME maybe some & problems? and endian
338: return getBpp24Pixel( p );
339: case 4:
340: return *(uint32 *)p;
341: } /* switch */
342: return 0; // should never happen
343: }
344: #endif
345:
346: uint32 HostScreen_getBpp()
347: {
348: return surf->format->BytesPerPixel;
349: }
350:
351: uint32 HostScreen_getPitch() {
352: return surf->pitch;
353: }
354:
355: uint32 HostScreen_getWidth() {
356: return hs_width;
357: }
358:
359: uint32 HostScreen_getHeight() {
360: return hs_height;
361: }
362:
363: uint8 *HostScreen_getVideoramAddress() {
364: return surf->pixels; /* FIXME maybe this should be mainSurface? */
365: }
366:
367: void HostScreen_setPaletteColor( uint8 idx, uint32 red, uint32 green, uint32 blue ) {
368: // set the SDL standard RGB palette settings
369: palette.standard[idx].r = red;
370: palette.standard[idx].g = green;
371: palette.standard[idx].b = blue;
372: // convert the color to native
373: palette.native[idx] = SDL_MapRGB( surf->format, red, green, blue );
374: }
375:
376: uint32 HostScreen_getPaletteColor( uint8 idx ) {
377: return palette.native[idx];
378: }
379:
380: void HostScreen_updatePalette( uint16 colorCount ) {
381: SDL_SetColors( surf, palette.standard, 0, colorCount );
382: }
383:
384: uint32 HostScreen_getColor( uint32 red, uint32 green, uint32 blue ) {
385: return SDL_MapRGB( surf->format, red, green, blue );
386: }
387:
388: #if 0
389: void HostScreen_lock(void) {
390: while (SDL_mutexP(screenLock)==-1) {
391: SDL_Delay(20);
392: fprintf(stderr, "Couldn't lock mutex\n");
393: }
394: }
395:
396: void HostScreen_unlock(void) {
397: while (SDL_mutexV(screenLock)==-1) {
398: SDL_Delay(20);
399: fprintf(stderr, "Couldn't unlock mutex\n");
400: }
401: }
402: #endif
403:
404: BOOL HostScreen_renderBegin(void) {
405: if (SDL_MUSTLOCK(surf))
406: if (SDL_LockSurface(surf) < 0) {
407: printf("Couldn't lock surface to refresh!\n");
408: return FALSE;
409: }
410:
411: return TRUE;
412: }
413:
414: void HostScreen_renderEnd() {
415: if (SDL_MUSTLOCK(surf))
416: SDL_UnlockSurface(surf);
417: }
418:
419:
420:
421: /**
422: * Performs conversion from the TOS's bitplane word order (big endian) data
423: * into the native chunky color index.
424: */
425: void HostScreen_bitplaneToChunky( uint16 *atariBitplaneData, uint16 bpp, uint8 colorValues[16] )
426: {
427: uint32 a, b, c, d, x;
428:
429: /* Obviously the different cases can be broken out in various
430: * ways to lessen the amount of work needed for <8 bit modes.
431: * It's doubtful if the usage of those modes warrants it, though.
432: * The branches below should be ~100% correctly predicted and
433: * thus be more or less for free.
434: * Getting the palette values inline does not seem to help
435: * enough to worry about. The palette lookup is much slower than
436: * this code, though, so it would be nice to do something about it.
437: */
438: if (bpp >= 4) {
439: d = *(uint32 *)&atariBitplaneData[0];
440: c = *(uint32 *)&atariBitplaneData[2];
441: if (bpp == 4) {
442: a = b = 0;
443: } else {
444: b = *(uint32 *)&atariBitplaneData[4];
445: a = *(uint32 *)&atariBitplaneData[6];
446: }
447: } else {
448: a = b = c = 0;
449: if (bpp == 2) {
450: d = *(uint32 *)&atariBitplaneData[0];
451: } else {
452: #if SDL_BYTEORDER == SDL_BIG_ENDIAN
453: d = atariBitplaneData[0]<<16;
454: #else
455: d = atariBitplaneData[0];
456: #endif
457: }
458: }
459:
460: x = a;
461: a = (a & 0xf0f0f0f0) | ((c & 0xf0f0f0f0) >> 4);
462: c = ((x & 0x0f0f0f0f) << 4) | (c & 0x0f0f0f0f);
463: x = b;
464: b = (b & 0xf0f0f0f0) | ((d & 0xf0f0f0f0) >> 4);
465: d = ((x & 0x0f0f0f0f) << 4) | (d & 0x0f0f0f0f);
466:
467: x = a;
468: a = (a & 0xcccccccc) | ((b & 0xcccccccc) >> 2);
469: b = ((x & 0x33333333) << 2) | (b & 0x33333333);
470: x = c;
471: c = (c & 0xcccccccc) | ((d & 0xcccccccc) >> 2);
472: d = ((x & 0x33333333) << 2) | (d & 0x33333333);
473:
474: #if SDL_BYTEORDER == SDL_BIG_ENDIAN
475: a = (a & 0x5555aaaa) | ((a & 0x00005555) << 17) | ((a & 0xaaaa0000) >> 17);
476: b = (b & 0x5555aaaa) | ((b & 0x00005555) << 17) | ((b & 0xaaaa0000) >> 17);
477: c = (c & 0x5555aaaa) | ((c & 0x00005555) << 17) | ((c & 0xaaaa0000) >> 17);
478: d = (d & 0x5555aaaa) | ((d & 0x00005555) << 17) | ((d & 0xaaaa0000) >> 17);
479:
480: colorValues[ 8] = a;
481: a >>= 8;
482: colorValues[ 0] = a;
483: a >>= 8;
484: colorValues[ 9] = a;
485: a >>= 8;
486: colorValues[ 1] = a;
487:
488: colorValues[10] = b;
489: b >>= 8;
490: colorValues[ 2] = b;
491: b >>= 8;
492: colorValues[11] = b;
493: b >>= 8;
494: colorValues[ 3] = b;
495:
496: colorValues[12] = c;
497: c >>= 8;
498: colorValues[ 4] = c;
499: c >>= 8;
500: colorValues[13] = c;
501: c >>= 8;
502: colorValues[ 5] = c;
503:
504: colorValues[14] = d;
505: d >>= 8;
506: colorValues[ 6] = d;
507: d >>= 8;
508: colorValues[15] = d;
509: d >>= 8;
510: colorValues[ 7] = d;
511: #else
512: a = (a & 0xaaaa5555) | ((a & 0x0000aaaa) << 15) | ((a & 0x55550000) >> 15);
513: b = (b & 0xaaaa5555) | ((b & 0x0000aaaa) << 15) | ((b & 0x55550000) >> 15);
514: c = (c & 0xaaaa5555) | ((c & 0x0000aaaa) << 15) | ((c & 0x55550000) >> 15);
515: d = (d & 0xaaaa5555) | ((d & 0x0000aaaa) << 15) | ((d & 0x55550000) >> 15);
516:
517: colorValues[ 1] = a;
518: a >>= 8;
519: colorValues[ 9] = a;
520: a >>= 8;
521: colorValues[ 0] = a;
522: a >>= 8;
523: colorValues[ 8] = a;
524:
525: colorValues[ 3] = b;
526: b >>= 8;
527: colorValues[11] = b;
528: b >>= 8;
529: colorValues[ 2] = b;
530: b >>= 8;
531: colorValues[10] = b;
532:
533: colorValues[ 5] = c;
534: c >>= 8;
535: colorValues[13] = c;
536: c >>= 8;
537: colorValues[ 4] = c;
538: c >>= 8;
539: colorValues[12] = c;
540:
541: colorValues[ 7] = d;
542: d >>= 8;
543: colorValues[15] = d;
544: d >>= 8;
545: colorValues[ 6] = d;
546: d >>= 8;
547: colorValues[14] = d;
548: #endif
549: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.