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