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