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