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