src/video/gem/SDL_gemvideo.c
author Patrice Mandin
Sun, 08 Jan 2006 17:29:19 +0000
changeset 1239 cbdb2c156aca
parent 1238 1901fea5edac
child 1312 c9b51268668f
permissions -rw-r--r--
Rollback
     1 /*
     2     SDL - Simple DirectMedia Layer
     3     Copyright (C) 1997-2004 Sam Lantinga
     4 
     5     This library is free software; you can redistribute it and/or
     6     modify it under the terms of the GNU Library General Public
     7     License as published by the Free Software Foundation; either
     8     version 2 of the License, or (at your option) any later version.
     9 
    10     This library is distributed in the hope that it will be useful,
    11     but WITHOUT ANY WARRANTY; without even the implied warranty of
    12     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    13     Library General Public License for more details.
    14 
    15     You should have received a copy of the GNU Library General Public
    16     License along with this library; if not, write to the Free
    17     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
    18 
    19     Sam Lantinga
    20     slouken@libsdl.org
    21 */
    22 
    23 #ifdef SAVE_RCSID
    24 static char rcsid =
    25  "@(#) $Id$";
    26 #endif
    27 
    28 /*
    29 	GEM video driver
    30 
    31 	Patrice Mandin
    32 	and work from
    33 	Olivier Landemarre, Johan Klockars, Xavier Joubert, Claude Attard
    34 */
    35 
    36 #include <stdio.h>
    37 #include <stdlib.h>
    38 #include <string.h>
    39 
    40 /* Mint includes */
    41 #include <gem.h>
    42 #include <gemx.h>
    43 #include <mint/osbind.h>
    44 #include <mint/cookie.h>
    45 
    46 #include "SDL.h"
    47 #include "SDL_error.h"
    48 #include "SDL_video.h"
    49 #include "SDL_mouse.h"
    50 #include "SDL_endian.h"
    51 #include "SDL_sysvideo.h"
    52 #include "SDL_pixels_c.h"
    53 #include "SDL_events_c.h"
    54 #include "SDL_cursor_c.h"
    55 
    56 #include "SDL_ataric2p_s.h"
    57 #include "SDL_atarieddi_s.h"
    58 #include "SDL_atarimxalloc_c.h"
    59 #include "SDL_atarigl_c.h"
    60 
    61 #include "SDL_gemvideo.h"
    62 #include "SDL_gemevents_c.h"
    63 #include "SDL_gemmouse_c.h"
    64 #include "SDL_gemwm_c.h"
    65 #include "SDL_xbiosevents_c.h"
    66 
    67 /* Defines */
    68 
    69 /*#define DEBUG_VIDEO_GEM	1*/
    70 
    71 #define GEM_VID_DRIVER_NAME "gem"
    72 
    73 #undef MIN
    74 #define MIN(a,b) (((a)<(b)) ? (a) : (b))
    75 #undef MAX
    76 #define MAX(a,b) (((a)>(b)) ? (a) : (b))
    77 
    78 /* Variables */
    79 
    80 static unsigned char vdi_index[256] = {
    81 	0,  2,  3,  6,  4,  7,  5,   8,
    82 	9, 10, 11, 14, 12, 15, 13, 255
    83 };
    84 
    85 static const unsigned char empty_name[]="";
    86 
    87 /* Initialization/Query functions */
    88 static int GEM_VideoInit(_THIS, SDL_PixelFormat *vformat);
    89 static SDL_Rect **GEM_ListModes(_THIS, SDL_PixelFormat *format, Uint32 flags);
    90 static SDL_Surface *GEM_SetVideoMode(_THIS, SDL_Surface *current, int width, int height, int bpp, Uint32 flags);
    91 static int GEM_SetColors(_THIS, int firstcolor, int ncolors, SDL_Color *colors);
    92 static void GEM_VideoQuit(_THIS);
    93 
    94 /* Hardware surface functions */
    95 static int GEM_AllocHWSurface(_THIS, SDL_Surface *surface);
    96 static int GEM_LockHWSurface(_THIS, SDL_Surface *surface);
    97 static int GEM_FlipHWSurface(_THIS, SDL_Surface *surface);
    98 static void GEM_UnlockHWSurface(_THIS, SDL_Surface *surface);
    99 static void GEM_FreeHWSurface(_THIS, SDL_Surface *surface);
   100 static void GEM_UpdateRects(_THIS, int numrects, SDL_Rect *rects);
   101 #if 0
   102 static int GEM_ToggleFullScreen(_THIS, int on);
   103 #endif
   104 
   105 /* Internal functions */
   106 static void GEM_FreeBuffers(_THIS);
   107 static void GEM_ClearScreen(_THIS);
   108 static void GEM_ClearRect(_THIS, short *rect);
   109 static void GEM_SetNewPalette(_THIS, Uint16 newpal[256][3]);
   110 static void GEM_LockScreen(_THIS);
   111 static void GEM_UnlockScreen(_THIS);
   112 static void refresh_window(_THIS, int winhandle, short *rect);
   113 
   114 #ifdef HAVE_OPENGL
   115 /* OpenGL functions */
   116 static void GEM_GL_SwapBuffers(_THIS);
   117 #endif
   118 
   119 /* GEM driver bootstrap functions */
   120 
   121 static int GEM_Available(void)
   122 {
   123 	/* Test if AES available */
   124 	if (appl_init() == -1)
   125 		return 0;
   126 
   127 	appl_exit();
   128 	return 1;
   129 }
   130 
   131 static void GEM_DeleteDevice(SDL_VideoDevice *device)
   132 {
   133 	free(device->hidden);
   134 	free(device);
   135 }
   136 
   137 static SDL_VideoDevice *GEM_CreateDevice(int devindex)
   138 {
   139 	SDL_VideoDevice *device;
   140 	int vectors_mask;
   141 	unsigned long dummy;
   142 
   143 	/* Initialize all variables that we clean on shutdown */
   144 	device = (SDL_VideoDevice *)malloc(sizeof(SDL_VideoDevice));
   145 	if ( device ) {
   146 		memset(device, 0, (sizeof *device));
   147 		device->hidden = (struct SDL_PrivateVideoData *)
   148 				malloc((sizeof *device->hidden));
   149 		device->gl_data = (struct SDL_PrivateGLData *)
   150 				malloc((sizeof *device->gl_data));
   151 	}
   152 	if ( (device == NULL) || (device->hidden == NULL) ) {
   153 		SDL_OutOfMemory();
   154 		if ( device ) {
   155 			free(device);
   156 		}
   157 		return(0);
   158 	}
   159 	memset(device->hidden, 0, (sizeof *device->hidden));
   160 	memset(device->gl_data, 0, sizeof(*device->gl_data));
   161 
   162 	/* Set the function pointers */
   163 	device->VideoInit = GEM_VideoInit;
   164 	device->ListModes = GEM_ListModes;
   165 	device->SetVideoMode = GEM_SetVideoMode;
   166 	device->SetColors = GEM_SetColors;
   167 	device->UpdateRects = NULL /*GEM_UpdateRects*/;
   168 	device->VideoQuit = GEM_VideoQuit;
   169 	device->AllocHWSurface = GEM_AllocHWSurface;
   170 	device->LockHWSurface = GEM_LockHWSurface;
   171 	device->UnlockHWSurface = GEM_UnlockHWSurface;
   172 	device->FlipHWSurface = GEM_FlipHWSurface;
   173 	device->FreeHWSurface = GEM_FreeHWSurface;
   174 	device->ToggleFullScreen = NULL /*GEM_ToggleFullScreen*/;
   175 
   176 	/* Window manager */
   177 	device->SetCaption = GEM_SetCaption;
   178 	device->SetIcon = GEM_SetIcon;
   179 	device->IconifyWindow = GEM_IconifyWindow;
   180 	device->GrabInput = GEM_GrabInput;
   181 
   182 	/* Events */
   183 	device->InitOSKeymap = GEM_InitOSKeymap;
   184 	device->PumpEvents = GEM_PumpEvents;
   185 
   186 	/* Mouse */
   187 	device->FreeWMCursor = GEM_FreeWMCursor;
   188 	device->CreateWMCursor = GEM_CreateWMCursor;
   189 	device->ShowWMCursor = GEM_ShowWMCursor;
   190 	device->WarpWMCursor = NULL /*GEM_WarpWMCursor*/;
   191 	device->CheckMouseMode = GEM_CheckMouseMode;
   192 
   193 #ifdef HAVE_OPENGL
   194 	/* OpenGL functions */
   195 	device->GL_LoadLibrary = SDL_AtariGL_LoadLibrary;
   196 	device->GL_GetProcAddress = SDL_AtariGL_GetProcAddress;
   197 	device->GL_GetAttribute = SDL_AtariGL_GetAttribute;
   198 	device->GL_MakeCurrent = SDL_AtariGL_MakeCurrent;
   199 	device->GL_SwapBuffers = GEM_GL_SwapBuffers;
   200 #endif
   201 
   202 	/* Joystick + Mouse relative motion */
   203 	vectors_mask = ATARI_XBIOS_MOUSEEVENTS|ATARI_XBIOS_JOYSTICKEVENTS;
   204 	if (Getcookie(C_MiNT, &dummy)==C_FOUND) {
   205 		vectors_mask = 0;
   206 	}
   207 
   208 	SDL_AtariXbios_InstallVectors(vectors_mask);
   209 
   210 	device->free = GEM_DeleteDevice;
   211 
   212 	return device;
   213 }
   214 
   215 VideoBootStrap GEM_bootstrap = {
   216 	GEM_VID_DRIVER_NAME, "Atari GEM video driver",
   217 	GEM_Available, GEM_CreateDevice
   218 };
   219 
   220 static void VDI_ReadExtInfo(_THIS, short *work_out)
   221 {
   222 	unsigned long EdDI_version;
   223 	unsigned long cookie_EdDI;
   224 	Uint32 num_colours;
   225 	Uint16 clut_type, num_bits;
   226 
   227 	/* Read EdDI informations */
   228 	if  (Getcookie(C_EdDI, &cookie_EdDI) == C_NOTFOUND) {
   229 		return;
   230 	}
   231 	
   232 	EdDI_version = Atari_get_EdDI_version( (void *)cookie_EdDI);
   233 
   234 	vq_scrninfo(VDI_handle, work_out);
   235 
   236 	VDI_format = work_out[0];
   237 	clut_type = work_out[1];
   238 	num_bits = work_out[2];
   239 	num_colours = *((Uint32 *) &work_out[3]);
   240 
   241 	/* With EdDI>=1.1, we can have screen pitch, address and format
   242 	 * so we can directly write to screen without using vro_cpyfm
   243 	 */
   244 	if (EdDI_version >= EDDI_11) {
   245 		VDI_pitch = work_out[5];
   246 		VDI_screen = (void *) *((unsigned long *) &work_out[6]);
   247 	}
   248 
   249 	switch(clut_type) {
   250 		case VDI_CLUT_HARDWARE:
   251 			{
   252 				int i;
   253 				Uint16 *tmp_p;
   254 
   255 				tmp_p = (Uint16 *)&work_out[16];
   256 
   257 				for (i=0;i<256;i++) {
   258 					vdi_index[*tmp_p++] = i;
   259 				}
   260 			}
   261 			break;
   262 		case VDI_CLUT_SOFTWARE:
   263 			{
   264 				int component; /* red, green, blue, alpha, overlay */
   265 				int num_bit;
   266 				unsigned short *tmp_p;
   267 
   268 				/* We can build masks with info here */
   269 				tmp_p = (unsigned short *) &work_out[16];
   270 				for (component=0;component<5;component++) {
   271 					for (num_bit=0;num_bit<16;num_bit++) {
   272 						unsigned short valeur;
   273 
   274 						valeur = *tmp_p++;
   275 
   276 						if (valeur == 0xffff) {
   277 							continue;
   278 						}
   279 
   280 						switch(component) {
   281 							case 0:
   282 								VDI_redmask |= 1<< valeur;
   283 								break;
   284 							case 1:
   285 								VDI_greenmask |= 1<< valeur;
   286 								break;
   287 							case 2:
   288 								VDI_bluemask |= 1<< valeur;
   289 								break;
   290 							case 3:
   291 								VDI_alphamask |= 1<< valeur;
   292 								break;
   293 						}
   294 					}
   295 				}
   296 			}
   297 
   298 			/* Remove lower green bits for Intel endian screen */
   299 			if ((VDI_greenmask == ((7<<13)|3)) || (VDI_greenmask == ((7<<13)|7))) {
   300 				VDI_greenmask &= ~(7<<13);
   301 			}
   302 			break;
   303 		case VDI_CLUT_NONE:
   304 			break;
   305 	}
   306 }
   307 
   308 int GEM_VideoInit(_THIS, SDL_PixelFormat *vformat)
   309 {
   310 	int i, menubar_size;
   311 	short work_in[12], work_out[272], dummy;
   312 
   313 	/* Open AES (Application Environment Services) */
   314 	if (appl_init() == -1) {
   315 		fprintf(stderr,"Can not open AES\n");
   316 		return 1;
   317 	}
   318 
   319 	/* Read version and features */
   320 	GEM_version = aes_global[0];
   321 	if (GEM_version >= 0x0410) {
   322 		short ap_gout[4], errorcode;
   323 		
   324 		GEM_wfeatures=0;
   325 		errorcode=appl_getinfo(AES_WINDOW, &ap_gout[0], &ap_gout[1], &ap_gout[2], &ap_gout[3]);
   326 
   327 		if (errorcode==0) {
   328 			GEM_wfeatures=ap_gout[0];			
   329 		}
   330 	}	
   331 
   332 	/* Ask VDI physical workstation handle opened by AES */
   333 	VDI_handle = graf_handle(&dummy, &dummy, &dummy, &dummy);
   334 	if (VDI_handle<1) {
   335 		fprintf(stderr,"Wrong VDI handle %d returned by AES\n",VDI_handle);
   336 		return 1;
   337 	}
   338 
   339 	/* Open virtual VDI workstation */
   340 	work_in[0]=Getrez()+2;
   341 	for(i = 1; i < 10; i++)
   342 		work_in[i] = 1;
   343 	work_in[10] = 2;
   344 
   345 	v_opnvwk(work_in, &VDI_handle, work_out);
   346 	if (VDI_handle == 0) {
   347 		fprintf(stderr,"Can not open VDI virtual workstation\n");
   348 		return 1;
   349 	}
   350 
   351 	/* Read fullscreen size */
   352 	VDI_w = work_out[0] + 1;
   353 	VDI_h = work_out[1] + 1;
   354 
   355 	/* Read desktop size and position */
   356 	if (!wind_get(DESKTOP_HANDLE, WF_WORKXYWH, &GEM_desk_x, &GEM_desk_y, &GEM_desk_w, &GEM_desk_h)) {
   357 		fprintf(stderr,"Can not read desktop properties\n");
   358 		return 1;
   359 	}
   360 
   361 	/* Read bit depth */
   362 	vq_extnd(VDI_handle, 1, work_out);
   363 	VDI_bpp = work_out[4];
   364 	VDI_oldnumcolors=0;
   365 
   366 	switch(VDI_bpp) {
   367 		case 8:
   368 			VDI_pixelsize=1;
   369 			break;
   370 		case 15:
   371 		case 16:
   372 			VDI_pixelsize=2;
   373 			break;
   374 		case 24:
   375 			VDI_pixelsize=3;
   376 			break;
   377 		case 32:
   378 			VDI_pixelsize=4;
   379 			break;
   380 		default:
   381 			fprintf(stderr,"%d bits colour depth not supported\n",VDI_bpp);
   382 			return 1;
   383 	}
   384 
   385 	/* Setup hardware -> VDI palette mapping */
   386 	for(i = 16; i < 255; i++) {
   387 		vdi_index[i] = i;
   388 	}
   389 	vdi_index[255] = 1;
   390 
   391 	/* Save current palette */
   392 	if (VDI_bpp>8) {
   393 		VDI_oldnumcolors=1<<8;
   394 	} else {
   395 		VDI_oldnumcolors=1<<VDI_bpp;
   396 	}
   397 	
   398 	for(i = 0; i < VDI_oldnumcolors; i++) {
   399 		short rgb[3];
   400 
   401 		vq_color(VDI_handle, i, 0, rgb);
   402 
   403 		VDI_oldpalette[i][0] = rgb[0];
   404 		VDI_oldpalette[i][1] = rgb[1];
   405 		VDI_oldpalette[i][2] = rgb[2];
   406 	}
   407 	VDI_setpalette = GEM_SetNewPalette;
   408 	memcpy(VDI_curpalette,VDI_oldpalette,sizeof(VDI_curpalette));
   409 
   410 	/* Setup screen info */
   411 	GEM_title_name = empty_name;
   412 	GEM_icon_name = empty_name;
   413 
   414 	GEM_handle = -1;
   415 	GEM_locked = SDL_FALSE;
   416 	GEM_win_fulled = SDL_FALSE;
   417 	GEM_fullscreen = SDL_FALSE;
   418 	GEM_lock_redraw = SDL_TRUE;	/* Prevent redraw till buffers are setup */
   419 
   420 	VDI_screen = NULL;
   421 	VDI_pitch = VDI_w * VDI_pixelsize;
   422 	VDI_format = ( (VDI_bpp <= 8) ? VDI_FORMAT_INTER : VDI_FORMAT_PACK);
   423 	VDI_redmask = VDI_greenmask = VDI_bluemask = VDI_alphamask = 0;
   424 	VDI_ReadExtInfo(this, work_out);
   425 
   426 #ifdef DEBUG_VIDEO_GEM
   427 	printf("sdl:video:gem: screen: address=0x%08x, pitch=%d\n", VDI_screen, VDI_pitch);
   428 	printf("sdl:video:gem: format=%d\n", VDI_format);
   429 	printf("sdl:video:gem: masks: 0x%08x, 0x%08x, 0x%08x, 0x%08x\n",
   430 		VDI_alphamask, VDI_redmask, VDI_greenmask, VDI_bluemask
   431 	);
   432 #endif
   433 
   434 	/* Setup destination mfdb */
   435 	VDI_dst_mfdb.fd_addr = NULL;
   436 
   437 	/* Update hardware info */
   438 	this->info.hw_available = 0;
   439 	this->info.video_mem = 0;
   440 
   441 	/* Determine the screen depth */
   442 	/* we change this during the SDL_SetVideoMode implementation... */
   443 	vformat->BitsPerPixel = VDI_bpp;
   444 
   445 	/* Set mouse cursor to arrow */
   446 	graf_mouse(ARROW, NULL);
   447 
   448 	/* Init chunky to planar routine */
   449 	SDL_Atari_C2pConvert = SDL_Atari_C2pConvert8;
   450 
   451 	/* Setup VDI fill functions */
   452 	vsf_color(VDI_handle,0);
   453 	vsf_interior(VDI_handle,1);
   454 	vsf_perimeter(VDI_handle,0);
   455 
   456 	/* Menu bar save buffer */
   457 	menubar_size = GEM_desk_w * GEM_desk_y * VDI_pixelsize;
   458 	GEM_menubar=Atari_SysMalloc(menubar_size,MX_PREFTTRAM);
   459 
   460 	/* Fill video modes list */
   461 	SDL_modelist[0] = malloc(sizeof(SDL_Rect));
   462 	SDL_modelist[0]->x = 0;
   463 	SDL_modelist[0]->y = 0;
   464 	SDL_modelist[0]->w = VDI_w;
   465 	SDL_modelist[0]->h = VDI_h;
   466 
   467 	SDL_modelist[1] = NULL;
   468 
   469 #ifdef HAVE_OPENGL
   470 	SDL_AtariGL_InitPointers(this);
   471 #endif
   472 
   473 	/* We're done! */
   474 	return(0);
   475 }
   476 
   477 SDL_Rect **GEM_ListModes(_THIS, SDL_PixelFormat *format, Uint32 flags)
   478 {
   479 	if (format->BitsPerPixel != VDI_bpp) {
   480 		return ((SDL_Rect **)NULL);
   481 	}
   482 
   483 	if (flags & SDL_FULLSCREEN) {
   484 		return (SDL_modelist);
   485 	}
   486 
   487 	return((SDL_Rect **)-1);
   488 }
   489 
   490 static void GEM_FreeBuffers(_THIS)
   491 {
   492 	/* Release buffer */
   493 	if ( GEM_buffer2 ) {
   494 		Mfree( GEM_buffer2 );
   495 		GEM_buffer2=NULL;
   496 	}
   497 
   498 	if ( GEM_buffer1 ) {
   499 		Mfree( GEM_buffer1 );
   500 		GEM_buffer1=NULL;
   501 	}
   502 }
   503 
   504 static void GEM_ClearRect(_THIS, short *rect)
   505 {
   506 	short oldrgb[3], rgb[3]={0,0,0};
   507 
   508 	vq_color(VDI_handle, vdi_index[0], 0, oldrgb);
   509 	vs_color(VDI_handle, vdi_index[0], rgb);
   510 
   511 	vsf_color(VDI_handle,0);
   512 	vsf_interior(VDI_handle,1);
   513 	vsf_perimeter(VDI_handle,0);
   514 	v_bar(VDI_handle, rect);
   515 
   516 	vs_color(VDI_handle, vdi_index[0], oldrgb);
   517 }
   518 
   519 static void GEM_ClearScreen(_THIS)
   520 {
   521 	short pxy[4];
   522 
   523 	v_hide_c(VDI_handle);
   524 
   525 	pxy[0] = pxy[1] = 0;
   526 	pxy[2] = VDI_w - 1;
   527 	pxy[3] = VDI_h - 1;
   528 	GEM_ClearRect(this, pxy);
   529 
   530 	v_show_c(VDI_handle, 1);
   531 }
   532 
   533 static void GEM_SetNewPalette(_THIS, Uint16 newpal[256][3])
   534 {
   535 	int i;
   536 	short rgb[3];
   537 
   538 	if (VDI_oldnumcolors==0)
   539 		return;
   540 
   541 	for(i = 0; i < VDI_oldnumcolors; i++) {
   542 		rgb[0] = newpal[i][0];
   543 		rgb[1] = newpal[i][1];
   544 		rgb[2] = newpal[i][2];
   545 
   546 		vs_color(VDI_handle, i, rgb);
   547 	}
   548 }
   549 
   550 static void GEM_LockScreen(_THIS)
   551 {
   552 	if (!GEM_locked) {
   553 		/* Lock AES */
   554 		wind_update(BEG_UPDATE);
   555 		wind_update(BEG_MCTRL);
   556 		/* Reserve memory space, used to be sure of compatibility */
   557 		form_dial( FMD_START, 0,0,0,0, 0,0,VDI_w,VDI_h);
   558 
   559 		/* Save menu bar */
   560 		if (GEM_menubar) {
   561 			MFDB mfdb_src;
   562 			short blitcoords[8];
   563 
   564 			mfdb_src.fd_addr=GEM_menubar;
   565 			mfdb_src.fd_w=GEM_desk_w;
   566 			mfdb_src.fd_h=GEM_desk_y;
   567 			mfdb_src.fd_wdwidth=GEM_desk_w>>4;
   568 			mfdb_src.fd_nplanes=VDI_bpp;
   569 			mfdb_src.fd_stand=
   570 				mfdb_src.fd_r1=
   571 				mfdb_src.fd_r2=
   572 				mfdb_src.fd_r3= 0;
   573 
   574 			blitcoords[0] = blitcoords[4] = 0;
   575 			blitcoords[1] = blitcoords[5] = 0;
   576 			blitcoords[2] = blitcoords[6] = GEM_desk_w-1;
   577 			blitcoords[3] = blitcoords[7] = GEM_desk_y-1;
   578 
   579 			vro_cpyfm(VDI_handle, S_ONLY, blitcoords, &VDI_dst_mfdb, &mfdb_src);
   580 		}
   581 
   582 		GEM_locked=SDL_TRUE;
   583 	}
   584 }
   585 
   586 static void GEM_UnlockScreen(_THIS)
   587 {
   588 	if (GEM_locked) {
   589 		/* Restore menu bar */
   590 		if (GEM_menubar) {
   591 			MFDB mfdb_src;
   592 			short blitcoords[8];
   593 
   594 			mfdb_src.fd_addr=GEM_menubar;
   595 			mfdb_src.fd_w=GEM_desk_w;
   596 			mfdb_src.fd_h=GEM_desk_y;
   597 			mfdb_src.fd_wdwidth=GEM_desk_w>>4;
   598 			mfdb_src.fd_nplanes=VDI_bpp;
   599 			mfdb_src.fd_stand=
   600 				mfdb_src.fd_r1=
   601 				mfdb_src.fd_r2=
   602 				mfdb_src.fd_r3= 0;
   603 
   604 			blitcoords[0] = blitcoords[4] = 0;
   605 			blitcoords[1] = blitcoords[5] = 0;
   606 			blitcoords[2] = blitcoords[6] = GEM_desk_w-1;
   607 			blitcoords[3] = blitcoords[7] = GEM_desk_y-1;
   608 
   609 			vro_cpyfm(VDI_handle, S_ONLY, blitcoords, &mfdb_src, &VDI_dst_mfdb);
   610 		}
   611 
   612 		/* Restore screen memory, and send REDRAW to all apps */
   613 		form_dial( FMD_FINISH, 0,0,0,0, 0,0,VDI_w,VDI_h);
   614 		/* Unlock AES */
   615 		wind_update(END_MCTRL);
   616 		wind_update(END_UPDATE);
   617 
   618 		GEM_locked=SDL_FALSE;
   619 	}
   620 }
   621 
   622 SDL_Surface *GEM_SetVideoMode(_THIS, SDL_Surface *current,
   623 				int width, int height, int bpp, Uint32 flags)
   624 {
   625 	int maxwidth, maxheight;
   626 	Uint32 modeflags, screensize;
   627 	SDL_bool use_shadow1, use_shadow2;
   628 
   629 	/*--- Verify if asked mode can be used ---*/
   630 	if (flags & SDL_FULLSCREEN) {
   631 		maxwidth=VDI_w;
   632 		maxheight=VDI_h;
   633 	} else {
   634 		/* Windowed mode */
   635 		maxwidth=GEM_desk_w;
   636 		maxheight=GEM_desk_h;
   637 	}
   638 
   639 	/* width must be multiple of 16, for vro_cpyfm() and c2p_convert() */
   640 	if ((width & 15) != 0) {
   641 		width = (width | 15) +1;
   642 	}
   643 
   644 	if ((maxwidth < width) || (maxheight < height) || (VDI_bpp != bpp)) {
   645 		SDL_SetError("Couldn't find requested mode in list");
   646 		return(NULL);
   647 	}
   648 
   649 	/*--- Allocate the new pixel format for the screen ---*/
   650 	if ( ! SDL_ReallocFormat(current, VDI_bpp, VDI_redmask, VDI_greenmask, VDI_bluemask, VDI_alphamask) ) {
   651 		SDL_SetError("Couldn't allocate new pixel format for requested mode");
   652 		return(NULL);
   653 	}
   654 
   655 	screensize = width * height * VDI_pixelsize;
   656 
   657 #ifdef DEBUG_VIDEO_GEM
   658 	printf("sdl:video:gem: setvideomode(): %dx%dx%d = %d\n", width, height, bpp, screensize);
   659 #endif
   660 
   661 	/*--- Allocate shadow buffers if needed, and conversion operations ---*/
   662 	GEM_FreeBuffers(this);
   663 
   664 	GEM_bufops=0;
   665 	use_shadow1=use_shadow2=SDL_FALSE;
   666 	if (VDI_screen && (flags & SDL_FULLSCREEN)) {
   667 		if (VDI_format==VDI_FORMAT_INTER) {
   668 			use_shadow1=SDL_TRUE;
   669 			GEM_bufops = B2S_C2P_1TOS;
   670 		}
   671 	} else {
   672 		use_shadow1=SDL_TRUE;
   673 		if (VDI_format==VDI_FORMAT_PACK) {
   674 			GEM_bufops = B2S_VROCPYFM_1TOS;
   675 		} else {
   676 			use_shadow2=SDL_TRUE;
   677 			GEM_bufops = B2S_C2P_1TO2|B2S_VROCPYFM_2TOS;
   678 		}
   679 	}
   680 
   681 	if (use_shadow1) {
   682 		GEM_buffer1 = Atari_SysMalloc(screensize, MX_PREFTTRAM);
   683 		if (GEM_buffer1==NULL) {
   684 			SDL_SetError("Can not allocate %d KB for frame buffer", screensize>>10);
   685 			return NULL;
   686 		}
   687 		memset(GEM_buffer1, 0, screensize);
   688 #ifdef DEBUG_VIDEO_GEM
   689 		printf("sdl:video:gem: setvideomode(): allocated buffer 1\n");
   690 #endif
   691 	}
   692 
   693 	if (use_shadow2) {
   694 		GEM_buffer2 = Atari_SysMalloc(screensize, MX_PREFTTRAM);
   695 		if (GEM_buffer2==NULL) {
   696 			SDL_SetError("Can not allocate %d KB for shadow buffer", screensize>>10);
   697 			return NULL;
   698 		}
   699 		memset(GEM_buffer2, 0, screensize);
   700 #ifdef DEBUG_VIDEO_GEM
   701 		printf("sdl:video:gem: setvideomode(): allocated buffer 2\n");
   702 #endif
   703 	}
   704 
   705 	/*--- Initialize screen ---*/
   706 	modeflags = SDL_PREALLOC;
   707 	if (VDI_bpp == 8) {
   708 		modeflags |= SDL_HWPALETTE;
   709 	}
   710 
   711 	if (flags & SDL_FULLSCREEN) {
   712 		GEM_LockScreen(this);
   713 
   714 		GEM_ClearScreen(this);
   715 
   716 		modeflags |= SDL_FULLSCREEN;
   717 		if (VDI_screen && (VDI_format==VDI_FORMAT_PACK) && !use_shadow1) {
   718 			modeflags |= SDL_HWSURFACE;
   719 		} else {
   720 			modeflags |= SDL_SWSURFACE;
   721 		}
   722 
   723 		GEM_fullscreen = SDL_TRUE;
   724 	} else {
   725 		int old_win_type;
   726 		short x2,y2,w2,h2;
   727 
   728 		GEM_UnlockScreen(this);
   729 
   730 		/* Set window gadgets */
   731 		old_win_type = GEM_win_type;
   732 		if (!(flags & SDL_NOFRAME)) {
   733 			GEM_win_type=NAME|MOVER|CLOSER|SMALLER;
   734 			if (flags & SDL_RESIZABLE) {
   735 				GEM_win_type |= FULLER|SIZER;
   736 				modeflags |= SDL_RESIZABLE;
   737 			}
   738 		} else {
   739 			GEM_win_type=0;
   740 			modeflags |= SDL_NOFRAME;
   741 		}
   742 		modeflags |= SDL_SWSURFACE;
   743 
   744 		/* Recreate window ? only for different widget or non-created window */
   745 		if ((old_win_type != GEM_win_type) || (GEM_handle < 0)) {
   746 			/* Calculate window size */
   747 			if (!wind_calc(WC_BORDER, GEM_win_type, 0,0,width,height, &x2,&y2,&w2,&h2)) {
   748 				GEM_FreeBuffers(this);
   749 				SDL_SetError("Can not calculate window attributes");
   750 				return NULL;
   751 			}
   752 
   753 			/* Center window */
   754 			x2 = GEM_desk_x+((GEM_desk_w-w2)>>1);
   755 			y2 = GEM_desk_y+((GEM_desk_h-h2)>>1);
   756 
   757 			/* Destroy existing window */
   758 			if (GEM_handle >= 0) {
   759 				wind_close(GEM_handle);
   760 				wind_delete(GEM_handle);
   761 			}
   762 
   763 			/* Create window */
   764 			GEM_handle=wind_create(GEM_win_type, x2,y2,w2,h2);
   765 			if (GEM_handle<0) {
   766 				GEM_FreeBuffers(this);
   767 				SDL_SetError("Can not create window");
   768 				return NULL;
   769 			}
   770 
   771 #ifdef DEBUG_VIDEO_GEM
   772 			printf("sdl:video:gem: handle=%d\n", GEM_handle);
   773 #endif
   774 
   775 			/* Setup window name */
   776 			wind_set(GEM_handle,WF_NAME,(short)(((unsigned long)GEM_title_name)>>16),(short)(((unsigned long)GEM_title_name) & 0xffff),0,0);
   777 			GEM_refresh_name = SDL_FALSE;
   778 
   779 			/* Open the window */
   780 			wind_open(GEM_handle,x2,y2,w2,h2);
   781 		} else {
   782 			/* Resize window if needed, to fit asked video mode */
   783 			if (modeflags & SDL_RESIZABLE) {
   784 				wind_get (GEM_handle, WF_WORKXYWH, &x2,&y2,&w2,&h2);
   785 				if ((w2&15)!=0) {
   786 					w2=(w2|15)+1;
   787 				}
   788 				if ((w2!=width) || (h2!=height)) {
   789 					if (wind_calc(WC_BORDER, GEM_win_type, x2,y2,width,height, &x2,&y2,&w2,&h2)) {
   790 						wind_set (GEM_handle, WF_CURRXYWH, x2,y2,w2,h2);
   791 					}
   792 				}
   793 			}
   794 		}
   795 
   796 		GEM_fullscreen = SDL_FALSE;
   797 	}
   798 
   799 	/* Set up the new mode framebuffer */
   800 	current->w = width;
   801 	current->h = height;
   802 	if (use_shadow1) {
   803 		current->pixels = GEM_buffer1;
   804 		current->pitch = width * VDI_pixelsize;
   805 	} else {
   806 		current->pixels = VDI_screen;
   807 		current->pitch = VDI_pitch;
   808 	}
   809 
   810 #ifdef HAVE_OPENGL
   811 	if (flags & SDL_OPENGL) {
   812 		if (!SDL_AtariGL_Init(this, current)) {
   813 			GEM_FreeBuffers(this);
   814 			SDL_SetError("Can not create OpenGL context");
   815 			return NULL;
   816 		}
   817 
   818 		modeflags |= SDL_OPENGL;
   819 	}
   820 #endif
   821 
   822 	current->flags = modeflags;
   823 
   824 #ifdef DEBUG_VIDEO_GEM
   825 	printf("sdl:video:gem: surface: %dx%d\n", current->w, current->h);
   826 #endif
   827 
   828 	this->UpdateRects = GEM_UpdateRects;
   829 	GEM_lock_redraw = SDL_FALSE;	/* Enable redraw */
   830 
   831 	/* We're done */
   832 	return(current);
   833 }
   834 
   835 static int GEM_AllocHWSurface(_THIS, SDL_Surface *surface)
   836 {
   837 	return -1;
   838 }
   839 
   840 static void GEM_FreeHWSurface(_THIS, SDL_Surface *surface)
   841 {
   842 	return;
   843 }
   844 
   845 static int GEM_LockHWSurface(_THIS, SDL_Surface *surface)
   846 {
   847 	return(0);
   848 }
   849 
   850 static void GEM_UnlockHWSurface(_THIS, SDL_Surface *surface)
   851 {
   852 	return;
   853 }
   854 
   855 static void GEM_UpdateRectsFullscreen(_THIS, int numrects, SDL_Rect *rects)
   856 {
   857 	SDL_Surface *surface;
   858 	int i, surf_width;
   859 
   860 	surface = this->screen;
   861 	/* Need to be a multiple of 16 pixels */
   862 	surf_width=surface->w;
   863 	if ((surf_width & 15) != 0) {
   864 		surf_width = (surf_width | 15) + 1;
   865 	}
   866 
   867 	if (GEM_bufops & (B2S_C2P_1TO2|B2S_C2P_1TOS)) {
   868 		void *destscr;
   869 		int destpitch;
   870 
   871 		if (GEM_bufops & B2S_C2P_1TOS) {
   872 			destscr = VDI_screen;
   873 			destpitch = VDI_pitch;
   874 		} else {
   875 			destscr = GEM_buffer2;
   876 			destpitch = surface->pitch;
   877 		}
   878 
   879 		for (i=0;i<numrects;i++) {
   880 			void *source,*destination;
   881 			int x1,x2;
   882 
   883 			x1 = rects[i].x & ~15;
   884 			x2 = rects[i].x+rects[i].w;
   885 			if (x2 & 15) {
   886 				x2 = (x2 | 15) +1;
   887 			}
   888 
   889 			source = surface->pixels;
   890 			source += surface->pitch * rects[i].y;
   891 			source += x1;
   892 
   893 			destination = destscr;
   894 			destination += destpitch * rects[i].y;
   895 			destination += x1;
   896 
   897 			SDL_Atari_C2pConvert(
   898 				source, destination,
   899 				x2-x1, rects[i].h,
   900 				SDL_FALSE,
   901 				surface->pitch, destpitch
   902 			);
   903 		}
   904 	}
   905 
   906 	if (GEM_bufops & (B2S_VROCPYFM_1TOS|B2S_VROCPYFM_2TOS)) {
   907 		MFDB mfdb_src;
   908 		short blitcoords[8];
   909 
   910 		mfdb_src.fd_addr=surface->pixels;
   911 		mfdb_src.fd_w=surf_width;
   912 		mfdb_src.fd_h=surface->h;
   913 		mfdb_src.fd_wdwidth= (surface->pitch/VDI_pixelsize) >> 4;
   914 		mfdb_src.fd_nplanes=surface->format->BitsPerPixel;
   915 		mfdb_src.fd_stand=
   916 			mfdb_src.fd_r1=
   917 			mfdb_src.fd_r2=
   918 			mfdb_src.fd_r3= 0;
   919 		if (GEM_bufops & B2S_VROCPYFM_2TOS) {
   920 			mfdb_src.fd_addr=GEM_buffer2;
   921 		}
   922 
   923 		for ( i=0; i<numrects; ++i ) {
   924 			blitcoords[0] = blitcoords[4] = rects[i].x;
   925 			blitcoords[1] = blitcoords[5] = rects[i].y;
   926 			blitcoords[2] = blitcoords[6] = rects[i].x + rects[i].w - 1;
   927 			blitcoords[3] = blitcoords[7] = rects[i].y + rects[i].h - 1;
   928 
   929 			vro_cpyfm(VDI_handle, S_ONLY, blitcoords, &mfdb_src, &VDI_dst_mfdb);
   930 		}
   931 	}
   932 }
   933 
   934 static void GEM_UpdateRectsWindowed(_THIS, int numrects, SDL_Rect *rects)
   935 {
   936 	short pxy[4], wind_pxy[4];
   937 	int i;
   938 
   939 	if (wind_get(GEM_handle, WF_WORKXYWH, &wind_pxy[0], &wind_pxy[1], &wind_pxy[2], &wind_pxy[3])==0) {
   940 		return;
   941 	}
   942 
   943 	for ( i=0; i<numrects; ++i ) {
   944 		pxy[0] = wind_pxy[0] + rects[i].x;
   945 		pxy[1] = wind_pxy[1] + rects[i].y;
   946 		pxy[2] = rects[i].w;
   947 		pxy[3] = rects[i].h;
   948 
   949 		GEM_wind_redraw(this, GEM_handle, pxy);
   950 	}
   951 }
   952 
   953 static void GEM_UpdateRects(_THIS, int numrects, SDL_Rect *rects)
   954 {
   955 	SDL_Surface *surface;
   956 
   957 	if (GEM_lock_redraw) {
   958 		return;
   959 	}
   960 
   961 	surface = this->screen;
   962 
   963 	if (surface->flags & SDL_FULLSCREEN) {
   964 		GEM_UpdateRectsFullscreen(this, numrects, rects);
   965 	} else {
   966 		GEM_UpdateRectsWindowed(this, numrects, rects);
   967 	}
   968 }
   969 
   970 static int GEM_FlipHWSurfaceFullscreen(_THIS, SDL_Surface *surface)
   971 {
   972 	int surf_width;
   973 
   974 	/* Need to be a multiple of 16 pixels */
   975 	surf_width=surface->w;
   976 	if ((surf_width & 15) != 0) {
   977 		surf_width = (surf_width | 15) + 1;
   978 	}
   979 
   980 	if (GEM_bufops & (B2S_C2P_1TO2|B2S_C2P_1TOS)) {
   981 		void *destscr;
   982 		int destpitch;
   983 
   984 		if (GEM_bufops & B2S_C2P_1TOS) {
   985 			destscr = VDI_screen;
   986 			destpitch = VDI_pitch;
   987 		} else {
   988 			destscr = GEM_buffer2;
   989 			destpitch = surface->pitch;
   990 		}
   991 
   992 		SDL_Atari_C2pConvert(
   993 			surface->pixels, destscr,
   994 			surf_width, surface->h,
   995 			SDL_FALSE,
   996 			surface->pitch, destpitch
   997 		);
   998 	}
   999 
  1000 	if (GEM_bufops & (B2S_VROCPYFM_1TOS|B2S_VROCPYFM_2TOS)) {
  1001 		MFDB mfdb_src;
  1002 		short blitcoords[8];
  1003 
  1004 		mfdb_src.fd_w=surf_width;
  1005 		mfdb_src.fd_h=surface->h;
  1006 		mfdb_src.fd_wdwidth=mfdb_src.fd_w >> 4;
  1007 		mfdb_src.fd_nplanes=surface->format->BitsPerPixel;
  1008 		mfdb_src.fd_stand=
  1009 			mfdb_src.fd_r1=
  1010 			mfdb_src.fd_r2=
  1011 			mfdb_src.fd_r3= 0;
  1012 		if (GEM_bufops & B2S_VROCPYFM_1TOS) {
  1013 			mfdb_src.fd_addr=surface->pixels;
  1014 		} else {
  1015 			mfdb_src.fd_addr=GEM_buffer2;
  1016 		}
  1017 
  1018 		blitcoords[0] = blitcoords[4] = 0;
  1019 		blitcoords[1] = blitcoords[5] = 0;
  1020 		blitcoords[2] = blitcoords[6] = surface->w - 1;
  1021 		blitcoords[3] = blitcoords[7] = surface->h - 1;
  1022 
  1023 		vro_cpyfm(VDI_handle, S_ONLY, blitcoords, &mfdb_src, &VDI_dst_mfdb);
  1024 	}
  1025 
  1026 	return(0);
  1027 }
  1028 
  1029 static int GEM_FlipHWSurfaceWindowed(_THIS, SDL_Surface *surface)
  1030 {
  1031 	short	pxy[8];
  1032 
  1033 	/* Update the whole window */
  1034 	wind_get(GEM_handle, WF_WORKXYWH, &pxy[0], &pxy[1], &pxy[2], &pxy[3]);
  1035 
  1036 	GEM_wind_redraw(this, GEM_handle, pxy);
  1037 
  1038 	return(0);
  1039 }
  1040 
  1041 static int GEM_FlipHWSurface(_THIS, SDL_Surface *surface)
  1042 {
  1043 	if (GEM_lock_redraw) {
  1044 		return(0);
  1045 	}
  1046 
  1047 	if (surface->flags & SDL_FULLSCREEN) {
  1048 		return GEM_FlipHWSurfaceFullscreen(this, surface);
  1049 	} else {
  1050 		return GEM_FlipHWSurfaceWindowed(this, surface);
  1051 	}
  1052 }
  1053 
  1054 static int GEM_SetColors(_THIS, int firstcolor, int ncolors, SDL_Color *colors)
  1055 {
  1056 	int i;
  1057 	SDL_Surface *surface;
  1058 
  1059 #ifdef DEBUG_VIDEO_GEM
  1060 	printf("sdl:video:gem: setcolors()\n");
  1061 #endif
  1062 
  1063 	/* Do not change palette in True Colour */
  1064 	surface = this->screen;
  1065 	if (surface->format->BitsPerPixel > 8) {
  1066 		return 1;
  1067 	}
  1068 
  1069 	for(i = 0; i < ncolors; i++)
  1070 	{
  1071 		int		r, g, b;
  1072 		short	rgb[3];
  1073 
  1074 		r = colors[i].r;
  1075 		g = colors[i].g;
  1076 		b = colors[i].b;
  1077 
  1078 		rgb[0] = VDI_curpalette[i][0] = (1000 * r) / 255;
  1079 		rgb[1] = VDI_curpalette[i][1] =(1000 * g) / 255;
  1080 		rgb[2] = VDI_curpalette[i][2] =(1000 * b) / 255;
  1081 
  1082 		vs_color(VDI_handle, vdi_index[firstcolor+i], rgb);
  1083 	}
  1084 
  1085 	return(1);
  1086 }
  1087 
  1088 #if 0
  1089 static int GEM_ToggleFullScreen(_THIS, int on)
  1090 {
  1091 	if (on) {
  1092 		GEM_LockScreen(this);
  1093 	} else {
  1094 		GEM_UnlockScreen(this);
  1095 	}
  1096 
  1097 	return(1);
  1098 }
  1099 #endif
  1100 
  1101 /* Note:  If we are terminated, this could be called in the middle of
  1102    another SDL video routine -- notably UpdateRects.
  1103 */
  1104 void GEM_VideoQuit(_THIS)
  1105 {
  1106 	SDL_AtariXbios_RestoreVectors();
  1107 
  1108 	GEM_FreeBuffers(this);
  1109 
  1110 #ifdef HAVE_OPENGL
  1111 	if (gl_active) {
  1112 		SDL_AtariGL_Quit(this, SDL_TRUE);
  1113 	}
  1114 #endif
  1115 
  1116 	/* Destroy window */
  1117 	if (GEM_handle>=0) {
  1118 		wind_close(GEM_handle);
  1119 		wind_delete(GEM_handle);
  1120 		GEM_handle=-1;
  1121 	}
  1122 
  1123 	GEM_UnlockScreen(this);
  1124 	if (GEM_menubar) {
  1125 		Mfree(GEM_menubar);
  1126 		GEM_menubar=NULL;
  1127 	}
  1128 
  1129 	appl_exit();
  1130 
  1131 	GEM_SetNewPalette(this, VDI_oldpalette);
  1132 
  1133 	/* Close VDI workstation */
  1134 	if (VDI_handle) {
  1135 		v_clsvwk(VDI_handle);
  1136 	}
  1137 
  1138 	/* Free mode list */
  1139 	if (SDL_modelist[0]) {
  1140 		free(SDL_modelist[0]);
  1141 		SDL_modelist[0]=NULL;
  1142 	}
  1143 
  1144 	this->screen->pixels = NULL;	
  1145 }
  1146 
  1147 void GEM_wind_redraw(_THIS, int winhandle, short *inside)
  1148 {
  1149 	short todo[4];
  1150 
  1151 	/* Tell AES we are going to update */
  1152 	wind_update(BEG_UPDATE);
  1153 
  1154 	v_hide_c(VDI_handle);
  1155 
  1156 	/* Browse the rectangle list to redraw */
  1157 	if (wind_get(winhandle, WF_FIRSTXYWH, &todo[0], &todo[1], &todo[2], &todo[3])!=0) {
  1158 
  1159 		while (todo[2] && todo[3]) {
  1160 
  1161 			if (rc_intersect((GRECT *)inside,(GRECT *)todo)) {
  1162 				todo[2] += todo[0]-1;
  1163 				todo[3] += todo[1]-1;
  1164 				refresh_window(this, winhandle, todo);
  1165 			}
  1166 
  1167 			if (wind_get(winhandle, WF_NEXTXYWH, &todo[0], &todo[1], &todo[2], &todo[3])==0) {
  1168 				break;
  1169 			}
  1170 		}
  1171 
  1172 	}
  1173 
  1174 	/* Update finished */
  1175 	wind_update(END_UPDATE);
  1176 
  1177 	v_show_c(VDI_handle,1);
  1178 }
  1179 
  1180 static void refresh_window(_THIS, int winhandle, short *rect)
  1181 {
  1182 	MFDB mfdb_src;
  1183 	short pxy[8],wind_pxy[8];
  1184 	SDL_Surface *surface;
  1185 	int iconified;
  1186 
  1187 	/* Is window iconified ? */
  1188 	iconified = 0;
  1189 /*	if (GEM_wfeatures & (1<<WF_ICONIFY))*/ {
  1190 		if (wind_get(winhandle, WF_ICONIFY, &wind_pxy[0], &wind_pxy[1], &wind_pxy[2], &wind_pxy[3])!=0) {
  1191 			iconified = wind_pxy[0];
  1192 		}
  1193 	}
  1194 
  1195 	if (wind_get(winhandle, WF_WORKXYWH, &wind_pxy[0], &wind_pxy[1], &wind_pxy[2], &wind_pxy[3])==0) {
  1196 		return;
  1197 	}
  1198 
  1199 	if (iconified && GEM_icon) {
  1200 		short icon_rect[4], dst_rect[4];
  1201 		short iconx,icony;
  1202 		
  1203 		surface = GEM_icon;
  1204 
  1205 		GEM_ClearRect(this, rect);
  1206 
  1207 		/* Calculate centered icon(x,y,w,h) relative to window */
  1208 		iconx = (wind_pxy[2]-surface->w)>>1;
  1209 		icony = (wind_pxy[3]-surface->h)>>1;
  1210 
  1211 		icon_rect[0] = iconx;
  1212 		icon_rect[1] = icony;
  1213 		icon_rect[2] = surface->w;
  1214 		icon_rect[3] = surface->h;
  1215 
  1216 		/* Calculate redraw rectangle(x,y,w,h) relative to window */
  1217 		dst_rect[0] = rect[0]-wind_pxy[0];
  1218 		dst_rect[1] = rect[1]-wind_pxy[1];
  1219 		dst_rect[2] = rect[2]-rect[0]+1;
  1220 		dst_rect[3] = rect[3]-rect[1]+1;
  1221 
  1222 		/* Does the icon rectangle must be redrawn ? */
  1223 		if (!rc_intersect((GRECT *)icon_rect, (GRECT *)dst_rect)) {
  1224 			return;
  1225 		}
  1226 
  1227 #if DEBUG_VIDEO_GEM
  1228 		printf("sdl:video:gem:  clip(0,0,%d,%d) to (%d,%d,%d,%d)\n",
  1229 			surface->w-1,surface->h-1, dst_rect[0],dst_rect[1],dst_rect[2],dst_rect[3]);
  1230 		printf("sdl:video:gem:  icon(%d,%d,%d,%d)\n",
  1231 			icon_rect[0], icon_rect[1], icon_rect[2], icon_rect[3]);
  1232 		printf("sdl:video:gem: refresh_window(): draw icon\n");
  1233 #endif
  1234 
  1235 		/* Calculate icon(x1,y1,x2,y2) relative to screen */
  1236 		icon_rect[0] += wind_pxy[0];
  1237 		icon_rect[1] += wind_pxy[1];
  1238 		icon_rect[2] += icon_rect[0]-1;
  1239 		icon_rect[3] += icon_rect[1]-1;
  1240 
  1241 		/* Calculate intersection rectangle to redraw */
  1242 		pxy[4]=pxy[0]=MAX(icon_rect[0],rect[0]);
  1243 		pxy[5]=pxy[1]=MAX(icon_rect[1],rect[1]);
  1244  		pxy[6]=pxy[2]=MIN(icon_rect[2],rect[2]);
  1245 	 	pxy[7]=pxy[3]=MIN(icon_rect[3],rect[3]);
  1246 
  1247 		/* Calculate icon source image pos relative to window */
  1248 		pxy[0] -= wind_pxy[0]+iconx;
  1249 		pxy[1] -= wind_pxy[1]+icony;
  1250 		pxy[2] -= wind_pxy[0]+iconx;
  1251 		pxy[3] -= wind_pxy[1]+icony;
  1252 
  1253 	} else {
  1254 		surface = this->screen;
  1255 
  1256 #if DEBUG_VIDEO_GEM
  1257 		printf("sdl:video:gem: refresh_window(): draw frame buffer\n");
  1258 #endif
  1259 
  1260 		/* Redraw all window content */
  1261 		pxy[0] = rect[0]-wind_pxy[0];
  1262 		pxy[1] = rect[1]-wind_pxy[1];
  1263 	 	pxy[2] = rect[2]-wind_pxy[0];   
  1264 	 	pxy[3] = rect[3]-wind_pxy[1];  
  1265 
  1266 		pxy[4] = rect[0];
  1267 		pxy[5] = rect[1];
  1268 		pxy[6] = rect[2];  
  1269 		pxy[7] = rect[3];
  1270 	}
  1271 
  1272 	if (GEM_bufops & B2S_C2P_1TO2) {
  1273 		void *src, *dest;
  1274 		int x1,x2;
  1275 
  1276 		x1 = (rect[0]-wind_pxy[0]) & ~15;
  1277 		x2 = rect[2]-wind_pxy[0];
  1278 		if (x2 & 15) {
  1279 			x2 = (x2 | 15) +1;
  1280 		}
  1281 
  1282 		src = surface->pixels;
  1283 		src += surface->pitch * (rect[1]-wind_pxy[1]);
  1284 		src += x1;
  1285 
  1286 		dest = GEM_buffer2;
  1287 		dest += surface->pitch * (rect[1]-wind_pxy[1]);
  1288 		dest += x1;
  1289 
  1290 		SDL_Atari_C2pConvert(
  1291 			src, dest,
  1292 			x2-x1, rect[3]-rect[1]+1,
  1293 			SDL_FALSE,
  1294 			surface->pitch, surface->pitch
  1295 		);
  1296 	}
  1297 
  1298 	mfdb_src.fd_addr=surface->pixels;
  1299 	{
  1300 		int width;
  1301 
  1302 		/* Need to be a multiple of 16 pixels */
  1303 		width=surface->w;
  1304 		if ((width & 15) != 0) {
  1305 			width = (width | 15) + 1;
  1306 		}
  1307 		mfdb_src.fd_w=width;
  1308 	}
  1309 	mfdb_src.fd_h=surface->h;
  1310   	mfdb_src.fd_nplanes=surface->format->BitsPerPixel;
  1311 	mfdb_src.fd_wdwidth=mfdb_src.fd_w>>4;
  1312 	mfdb_src.fd_stand=
  1313 		mfdb_src.fd_r1=
  1314   		mfdb_src.fd_r2=
  1315 	  	mfdb_src.fd_r3= 0;
  1316 
  1317 	if (GEM_bufops & B2S_VROCPYFM_2TOS) {
  1318 		mfdb_src.fd_addr=GEM_buffer2;
  1319 	}
  1320 
  1321 #if DEBUG_VIDEO_GEM
  1322 	printf("sdl:video:gem: redraw %dx%d: (%d,%d,%d,%d) to (%d,%d,%d,%d)\n",
  1323 		surface->w, surface->h,
  1324 		pxy[0],pxy[1],pxy[2],pxy[3],
  1325 		pxy[4],pxy[5],pxy[6],pxy[7]
  1326 	);
  1327 #endif
  1328 
  1329 	vro_cpyfm( VDI_handle, S_ONLY, pxy, &mfdb_src, &VDI_dst_mfdb);
  1330 }
  1331 
  1332 #ifdef HAVE_OPENGL
  1333 
  1334 static void GEM_GL_SwapBuffers(_THIS)
  1335 {
  1336 	SDL_AtariGL_SwapBuffers(this);
  1337 	GEM_FlipHWSurface(this, this->screen);
  1338 }
  1339 
  1340 #endif