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