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