src/video/gapi/SDL_gapivideo.c
author Sam Lantinga <slouken@libsdl.org>
Tue, 15 Dec 2009 08:11:06 +0000
changeset 3565 f43c8f688f77
parent 2985 4e4d814884aa
permissions -rw-r--r--
Fixed bug #906

Added better error reporting for OpenGL context creation failing.
     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 /* Pocket PC GAPI SDL video driver implementation;
    25 Implemented by Dmitry Yakimov - support@activekitten.com
    26 Inspired by http://arisme.free.fr/ports/SDL.php
    27 */
    28 
    29 // TODO: copy surface on window when lost focus
    30 // TODO: test buttons rotation
    31 // TODO: test on be300 and HPC ( check WinDib fullscreen keys catching )
    32 // TODO: test on smartphones
    33 // TODO: windib on SH3 PPC2000 landscape test
    34 // TODO: optimize 8bpp landscape mode
    35 
    36 // there is some problems in runnings apps from a device landscape mode
    37 // due to WinCE bugs. Some works and some - does not.
    38 // TODO: finish Axim Dell X30 and user landscape mode, device landscape mode
    39 // TODO: finish Axim Dell X30 user portrait, device landscape stylus conversion
    40 // TODO: fix running GAPI apps from landscape mode - 
    41 //       wince goes to portrait mode, but does not update video memory
    42 
    43 
    44 #include "SDL_error.h"
    45 #include "SDL_video.h"
    46 #include "SDL_mouse.h"
    47 #include "../SDL_sysvideo.h"
    48 #include "../SDL_pixels_c.h"
    49 #include "../../events/SDL_events_c.h"
    50 #include "../wincommon/SDL_syswm_c.h"
    51 #include "../wincommon/SDL_sysmouse_c.h"
    52 #include "../windib/SDL_dibevents_c.h"
    53 
    54 #include "SDL_gapivideo.h"
    55 
    56 #define GAPIVID_DRIVER_NAME "gapi"
    57 
    58 #if defined(DEBUG) || defined (_DEBUG) || defined(NDEBUG)
    59 #define REPORT_VIDEO_INFO 1
    60 #else
    61 #define REPORT_VIDEO_INFO 0
    62 #endif
    63 
    64 // for testing with GapiEmu
    65 #define USE_GAPI_EMU 0
    66 #define EMULATE_AXIM_X30 0
    67 #define WITHOUT_GAPI 0
    68 
    69 #if USE_GAPI_EMU && !REPORT_VIDEO_INFO
    70 #pragma message("Warning: Using GapiEmu in release build. I assume you'd like to set USE_GAPI_EMU to zero.")
    71 #endif
    72 
    73 // defined and used in SDL_sysevents.c
    74 extern HINSTANCE aygshell;
    75 extern void SDL_UnregisterApp();
    76 extern int DIB_AddMode(_THIS, int bpp, int w, int h);
    77 
    78 /* Initialization/Query functions */
    79 static int GAPI_VideoInit(_THIS, SDL_PixelFormat * vformat);
    80 static SDL_Rect **GAPI_ListModes(_THIS, SDL_PixelFormat * format,
    81                                  Uint32 flags);
    82 static SDL_Surface *GAPI_SetVideoMode(_THIS, SDL_Surface * current,
    83                                       int width, int height, int bpp,
    84                                       Uint32 flags);
    85 static int GAPI_SetColors(_THIS, int firstcolor, int ncolors,
    86                           SDL_Color * colors);
    87 static void GAPI_VideoQuit(_THIS);
    88 
    89 /* Hardware surface functions */
    90 static int GAPI_AllocHWSurface(_THIS, SDL_Surface * surface);
    91 static int GAPI_LockHWSurface(_THIS, SDL_Surface * surface);
    92 static void GAPI_UnlockHWSurface(_THIS, SDL_Surface * surface);
    93 static void GAPI_FreeHWSurface(_THIS, SDL_Surface * surface);
    94 
    95 /* Windows message handling functions, will not be processed */
    96 static void GAPI_RealizePalette(_THIS);
    97 static void GAPI_PaletteChanged(_THIS, HWND window);
    98 static void GAPI_WinPAINT(_THIS, HDC hdc);
    99 
   100 /* etc. */
   101 static void GAPI_UpdateRects(_THIS, int numrects, SDL_Rect * rects);
   102 
   103 static HMODULE g_hGapiLib = 0;
   104 #define LINK(type,name,import) \
   105 	if( g_hGapiLib ) \
   106 		name = (PFN##type)GetProcAddress( g_hGapiLib, _T(import) );
   107 
   108 static char g_bRawBufferAvailable = 0;
   109 
   110 /* GAPI driver bootstrap functions */
   111 
   112 /* hi res definitions */
   113 typedef struct _RawFrameBufferInfo
   114 {
   115     WORD wFormat;
   116     WORD wBPP;
   117     VOID *pFramePointer;
   118     int cxStride;
   119     int cyStride;
   120     int cxPixels;
   121     int cyPixels;
   122 } RawFrameBufferInfo;
   123 
   124 static struct _RawFrameBufferInfo g_RawFrameBufferInfo = { 0 };
   125 
   126 #define GETRAWFRAMEBUFFER   0x00020001
   127 
   128 #define FORMAT_565 1
   129 #define FORMAT_555 2
   130 #define FORMAT_OTHER 3
   131 
   132 /* Dell Axim x30 hangs when we use GAPI from landscape,
   133    so lets avoid using GxOpenDisplay there via GETGXINFO trick 
   134    It seems that GAPI subsystem use the same ExtEscape code.
   135 */
   136 #define GETGXINFO 0x00020000
   137 
   138 typedef struct GXDeviceInfo
   139 {
   140     long Version;               //00 (should filled with 100 before calling ExtEscape)
   141     void *pvFrameBuffer;        //04
   142     unsigned long cbStride;     //08
   143     unsigned long cxWidth;      //0c
   144     unsigned long cyHeight;     //10
   145     unsigned long cBPP;         //14
   146     unsigned long ffFormat;     //18
   147     char Unused[0x84 - 7 * 4];
   148 } GXDeviceInfo;
   149 
   150 static int
   151 GAPI_Available(void)
   152 {
   153     // try to use VGA display, even on emulator
   154     HDC hdc = GetDC(NULL);
   155     int result = ExtEscape(hdc, GETRAWFRAMEBUFFER, 0, NULL,
   156                            sizeof(RawFrameBufferInfo),
   157                            (char *) &g_RawFrameBufferInfo);
   158     ReleaseDC(NULL, hdc);
   159     g_bRawBufferAvailable = result > 0;
   160 
   161 #if WITHOUT_GAPI
   162     return g_bRawBufferAvailable;
   163 #endif
   164 
   165 #if USE_GAPI_EMU
   166     g_hGapiLib = LoadLibrary(_T("GAPI_Emu.dll"));
   167     if (!g_hGapiLib) {
   168         SDL_SetError("Gapi Emu not found!");
   169     }
   170     return g_hGapiLib != 0;
   171 #endif
   172 
   173     // try to find gx.dll
   174     g_hGapiLib = LoadLibrary(_T("\\Windows\\gx.dll"));
   175     if (!g_hGapiLib) {
   176         g_hGapiLib = LoadLibrary(_T("gx.dll"));
   177         if (!g_hGapiLib)
   178             return g_bRawBufferAvailable;
   179     }
   180 
   181     return (1);
   182 }
   183 
   184 static int
   185 cmpmodes(const void *va, const void *vb)
   186 {
   187     SDL_Rect *a = *(SDL_Rect **) va;
   188     SDL_Rect *b = *(SDL_Rect **) vb;
   189     if (a->w == b->w)
   190         return b->h - a->h;
   191     else
   192         return b->w - a->w;
   193 }
   194 
   195 static int
   196 GAPI_AddMode(_THIS, int bpp, int w, int h)
   197 {
   198     SDL_Rect *mode;
   199     int i, index;
   200     int next_mode;
   201 
   202     /* Check to see if we already have this mode */
   203     if (bpp < 8) {              /* Not supported */
   204         return (0);
   205     }
   206     index = ((bpp + 7) / 8) - 1;
   207     for (i = 0; i < gapi->SDL_nummodes[index]; ++i) {
   208         mode = gapi->SDL_modelist[index][i];
   209         if ((mode->w == w) && (mode->h == h)) {
   210             return (0);
   211         }
   212     }
   213 
   214     /* Set up the new video mode rectangle */
   215     mode = (SDL_Rect *) SDL_malloc(sizeof *mode);
   216     if (mode == NULL) {
   217         SDL_OutOfMemory();
   218         return (-1);
   219     }
   220     mode->x = 0;
   221     mode->y = 0;
   222     mode->w = w;
   223     mode->h = h;
   224 
   225     /* Allocate the new list of modes, and fill in the new mode */
   226     next_mode = gapi->SDL_nummodes[index];
   227     gapi->SDL_modelist[index] = (SDL_Rect **)
   228         SDL_realloc(gapi->SDL_modelist[index],
   229                     (1 + next_mode + 1) * sizeof(SDL_Rect *));
   230     if (gapi->SDL_modelist[index] == NULL) {
   231         SDL_OutOfMemory();
   232         gapi->SDL_nummodes[index] = 0;
   233         SDL_free(mode);
   234         return (-1);
   235     }
   236     gapi->SDL_modelist[index][next_mode] = mode;
   237     gapi->SDL_modelist[index][next_mode + 1] = NULL;
   238     gapi->SDL_nummodes[index]++;
   239 
   240     return (0);
   241 }
   242 
   243 static void
   244 GAPI_DeleteDevice(SDL_VideoDevice * device)
   245 {
   246     if (g_hGapiLib) {
   247         FreeLibrary(g_hGapiLib);
   248         g_hGapiLib = 0;
   249     }
   250     SDL_free(device->hidden);
   251     SDL_free(device);
   252 }
   253 
   254 static SDL_VideoDevice *
   255 GAPI_CreateDevice(int devindex)
   256 {
   257     SDL_VideoDevice *device;
   258 
   259     if (!g_hGapiLib && !g_bRawBufferAvailable) {
   260         if (!GAPI_Available()) {
   261             SDL_SetError
   262                 ("GAPI dll is not found and VGA mode is not available!");
   263             return 0;
   264         }
   265     }
   266 
   267     /* Initialize all variables that we clean on shutdown */
   268     device = (SDL_VideoDevice *) SDL_malloc(sizeof(SDL_VideoDevice));
   269     if (device) {
   270         SDL_memset(device, 0, (sizeof *device));
   271         device->hidden = (struct SDL_PrivateVideoData *)
   272             SDL_malloc((sizeof *device->hidden));
   273     }
   274     if ((device == NULL) || (device->hidden == NULL)) {
   275         SDL_OutOfMemory();
   276         if (device) {
   277             SDL_free(device);
   278         }
   279         return (0);
   280     }
   281     SDL_memset(device->hidden, 0, (sizeof *device->hidden));
   282 
   283     /* Set the function pointers */
   284     device->VideoInit = GAPI_VideoInit;
   285     device->ListModes = GAPI_ListModes;
   286     device->SetVideoMode = GAPI_SetVideoMode;
   287     device->UpdateMouse = WIN_UpdateMouse;
   288     device->CreateYUVOverlay = NULL;
   289     device->SetColors = GAPI_SetColors;
   290     device->UpdateRects = GAPI_UpdateRects;
   291     device->VideoQuit = GAPI_VideoQuit;
   292     device->AllocHWSurface = GAPI_AllocHWSurface;
   293     device->CheckHWBlit = NULL;
   294     device->FillHWRect = NULL;
   295     device->SetHWColorKey = NULL;
   296     device->SetHWAlpha = NULL;
   297     device->LockHWSurface = GAPI_LockHWSurface;
   298     device->UnlockHWSurface = GAPI_UnlockHWSurface;
   299     device->FlipHWSurface = NULL;
   300     device->FreeHWSurface = GAPI_FreeHWSurface;
   301     device->SetCaption = WIN_SetWMCaption;
   302     device->SetIcon = WIN_SetWMIcon;
   303     device->IconifyWindow = WIN_IconifyWindow;
   304     device->GrabInput = WIN_GrabInput;
   305     device->GetWMInfo = WIN_GetWMInfo;
   306     device->FreeWMCursor = WIN_FreeWMCursor;
   307     device->CreateWMCursor = WIN_CreateWMCursor;
   308     device->ShowWMCursor = WIN_ShowWMCursor;
   309     device->WarpWMCursor = WIN_WarpWMCursor;
   310     device->CheckMouseMode = WIN_CheckMouseMode;
   311     device->InitOSKeymap = DIB_InitOSKeymap;
   312     device->PumpEvents = DIB_PumpEvents;
   313 
   314     /* Set up the windows message handling functions */
   315     WIN_RealizePalette = GAPI_RealizePalette;
   316     WIN_PaletteChanged = GAPI_PaletteChanged;
   317     WIN_WinPAINT = GAPI_WinPAINT;
   318     HandleMessage = DIB_HandleMessage;
   319 
   320     device->free = GAPI_DeleteDevice;
   321 
   322     /* Load gapi library */
   323 #define gx device->hidden->gxFunc
   324 
   325     LINK(GXOpenDisplay, gx.GXOpenDisplay,
   326          "?GXOpenDisplay@@YAHPAUHWND__@@K@Z") LINK(GXCloseDisplay,
   327                                                    gx.GXCloseDisplay,
   328                                                    "?GXCloseDisplay@@YAHXZ")
   329         LINK(GXBeginDraw, gx.GXBeginDraw,
   330              "?GXBeginDraw@@YAPAXXZ") LINK(GXEndDraw, gx.GXEndDraw,
   331                                            "?GXEndDraw@@YAHXZ")
   332         LINK(GXOpenInput, gx.GXOpenInput,
   333              "?GXOpenInput@@YAHXZ") LINK(GXCloseInput, gx.GXCloseInput,
   334                                          "?GXCloseInput@@YAHXZ")
   335         LINK(GXGetDisplayProperties, gx.GXGetDisplayProperties,
   336              "?GXGetDisplayProperties@@YA?AUGXDisplayProperties@@XZ")
   337         LINK(GXGetDefaultKeys, gx.GXGetDefaultKeys,
   338              "?GXGetDefaultKeys@@YA?AUGXKeyList@@H@Z") LINK(GXSuspend,
   339                                                             gx.GXSuspend,
   340                                                             "?GXSuspend@@YAHXZ")
   341         LINK(GXResume, gx.GXResume, "?GXResume@@YAHXZ") LINK(GXSetViewport,
   342                                                              gx.GXSetViewport,
   343                                                              "?GXSetViewport@@YAHKKKK@Z")
   344         LINK(GXIsDisplayDRAMBuffer, gx.GXIsDisplayDRAMBuffer,
   345              "?GXIsDisplayDRAMBuffer@@YAHXZ")
   346         /* wrong gapi.dll */
   347         if (!gx.GXOpenDisplay) {
   348         if (g_hGapiLib) {
   349             FreeLibrary(g_hGapiLib);
   350             g_hGapiLib = 0;
   351         }
   352     }
   353 
   354     if (!gx.GXOpenDisplay && !g_bRawBufferAvailable) {
   355         SDL_SetError("Error: damaged or unknown gapi.dll!\n");
   356         GAPI_DeleteDevice(device);
   357         return 0;
   358     }
   359 
   360     return device;
   361 }
   362 
   363 VideoBootStrap GAPI_bootstrap = {
   364     GAPIVID_DRIVER_NAME, "WinCE GAPI video driver",
   365     GAPI_Available, GAPI_CreateDevice
   366 };
   367 
   368 static void
   369 FillStructs(_THIS, BOOL useVga)
   370 {
   371 #ifdef _ARM_
   372     WCHAR oemstr[100];
   373 #endif
   374     /* fill a device properties */
   375 
   376     if (!useVga) {
   377         this->hidden->gxProperties =
   378             this->hidden->gxFunc.GXGetDisplayProperties();
   379         this->hidden->needUpdate = 1;
   380         this->hidden->hiresFix = 0;
   381         this->hidden->useVga = 0;
   382         this->hidden->useGXOpenDisplay = 1;
   383 
   384 #ifdef _ARM_
   385         /* check some devices and extract addition info */
   386         SystemParametersInfo(SPI_GETOEMINFO, sizeof(oemstr), oemstr, 0);
   387 
   388         // buggy iPaq38xx
   389         if ((oemstr[12] == 'H') && (oemstr[13] == '3')
   390             && (oemstr[14] == '8')
   391             && (this->hidden->gxProperties.cbxPitch > 0)) {
   392             this->hidden->videoMem = (PIXEL *) 0xac0755a0;
   393             this->hidden->gxProperties.cbxPitch = -640;
   394             this->hidden->gxProperties.cbyPitch = 2;
   395             this->hidden->needUpdate = 0;
   396         }
   397 #if (EMULATE_AXIM_X30 == 0)
   398         // buggy Dell Axim X30
   399         if (_tcsncmp(oemstr, L"Dell Axim X30", 13) == 0)
   400 #endif
   401         {
   402             GXDeviceInfo gxInfo = { 0 };
   403             HDC hdc = GetDC(NULL);
   404             int result;
   405 
   406             gxInfo.Version = 100;
   407             result =
   408                 ExtEscape(hdc, GETGXINFO, 0, NULL, sizeof(gxInfo),
   409                           (char *) &gxInfo);
   410             if (result > 0) {
   411                 this->hidden->useGXOpenDisplay = 0;
   412                 this->hidden->videoMem = gxInfo.pvFrameBuffer;
   413                 this->hidden->needUpdate = 0;
   414                 this->hidden->gxProperties.cbxPitch = 2;
   415                 this->hidden->gxProperties.cbyPitch = 480;
   416                 this->hidden->gxProperties.cxWidth = gxInfo.cxWidth;
   417                 this->hidden->gxProperties.cyHeight = gxInfo.cyHeight;
   418                 this->hidden->gxProperties.ffFormat = gxInfo.ffFormat;
   419             }
   420         }
   421 #endif
   422     } else {
   423         this->hidden->needUpdate = 0;
   424         this->hidden->hiresFix = 0;
   425         this->hidden->gxProperties.cBPP = g_RawFrameBufferInfo.wBPP;
   426         this->hidden->gxProperties.cbxPitch = g_RawFrameBufferInfo.cxStride;
   427         this->hidden->gxProperties.cbyPitch = g_RawFrameBufferInfo.cyStride;
   428         this->hidden->gxProperties.cxWidth = g_RawFrameBufferInfo.cxPixels;
   429         this->hidden->gxProperties.cyHeight = g_RawFrameBufferInfo.cyPixels;
   430         this->hidden->videoMem = g_RawFrameBufferInfo.pFramePointer;
   431         this->hidden->useVga = 1;
   432 
   433         switch (g_RawFrameBufferInfo.wFormat) {
   434         case FORMAT_565:
   435             this->hidden->gxProperties.ffFormat = kfDirect565;
   436             break;
   437         case FORMAT_555:
   438             this->hidden->gxProperties.ffFormat = kfDirect555;
   439             break;
   440         default:
   441             /* unknown pixel format, try define by BPP! */
   442             switch (g_RawFrameBufferInfo.wBPP) {
   443             case 4:
   444             case 8:
   445                 this->hidden->gxProperties.ffFormat = kfDirect;
   446             case 16:
   447                 this->hidden->gxProperties.ffFormat = kfDirect565;
   448             default:
   449                 this->hidden->gxProperties.ffFormat = kfDirect;
   450                 break;
   451             }
   452         }
   453     }
   454 
   455     if (this->hidden->gxProperties.cBPP != 16) {
   456         this->hidden->gapiOrientation = SDL_ORIENTATION_UP;
   457     } else if ((this->hidden->gxProperties.cbxPitch > 0)
   458                && (this->hidden->gxProperties.cbyPitch > 0)) {
   459         this->hidden->gapiOrientation = SDL_ORIENTATION_UP;
   460     } else if ((this->hidden->gxProperties.cbxPitch > 0)
   461                && (this->hidden->gxProperties.cbyPitch < 0)) {
   462         this->hidden->gapiOrientation = SDL_ORIENTATION_RIGHT;  // ipaq 3660
   463     } else if ((this->hidden->gxProperties.cbxPitch < 0)
   464                && (this->hidden->gxProperties.cbyPitch > 0)) {
   465         this->hidden->gapiOrientation = SDL_ORIENTATION_LEFT;   // ipaq 3800
   466     }
   467 }
   468 
   469 static void
   470 GAPI_CreatePalette(int ncolors, SDL_Color * colors)
   471 {
   472     // Setup a custom color palette
   473     BYTE buffer[sizeof(LOGPALETTE) + 255 * sizeof(PALETTEENTRY)];
   474     int i;
   475     LOGPALETTE *pLogical = (LOGPALETTE *) buffer;
   476     PALETTEENTRY *entries = pLogical->palPalEntry;
   477     HPALETTE hPalette;
   478     HDC hdc;
   479 
   480     for (i = 0; i < ncolors; ++i) {
   481         // Find intensity by replicating the bit patterns over a byte
   482         entries[i].peRed = colors[i].r;
   483         entries[i].peGreen = colors[i].g;
   484         entries[i].peBlue = colors[i].b;
   485         entries[i].peFlags = 0;
   486     }
   487 
   488     // Create the GDI palette object
   489     pLogical->palVersion = 0x0300;
   490     pLogical->palNumEntries = ncolors;
   491 
   492     hPalette = CreatePalette(pLogical);
   493     ASSERT(hPalette);
   494 
   495 
   496     // Realize the palette
   497     hdc = GetDC(0);
   498 
   499     SelectPalette(hdc, hPalette, FALSE);
   500     RealizePalette(hdc);
   501 
   502     ReleaseDC(0, hdc);
   503     DeleteObject(hPalette);
   504 }
   505 
   506 int
   507 GAPI_VideoInit(_THIS, SDL_PixelFormat * vformat)
   508 {
   509     int i, bpp;
   510 
   511     /* Create the window */
   512     if (DIB_CreateWindow(this) < 0) {
   513         return (-1);
   514     }
   515 
   516     if (g_hGapiLib) {
   517         FillStructs(this, 0);
   518 
   519         // SDL does not supports 2/4bpp mode, so use 16 bpp
   520         bpp = gapi->gxProperties.cBPP < 8 ? 16 : gapi->gxProperties.cBPP;
   521 
   522         /* set up normal and landscape mode */
   523         GAPI_AddMode(this, bpp, gapi->gxProperties.cyHeight,
   524                      gapi->gxProperties.cxWidth);
   525         GAPI_AddMode(this, bpp, gapi->gxProperties.cxWidth,
   526                      gapi->gxProperties.cyHeight);
   527     }
   528 
   529     /* add hi-res mode */
   530     if (g_bRawBufferAvailable &&
   531         !((gapi->gxProperties.cxWidth ==
   532            (unsigned) g_RawFrameBufferInfo.cxPixels)
   533           && (gapi->gxProperties.cyHeight ==
   534               (unsigned) g_RawFrameBufferInfo.cyPixels))) {
   535         FillStructs(this, 1);
   536 
   537         // SDL does not supports 2/4bpp mode, so use 16 bpp
   538         bpp = gapi->gxProperties.cBPP < 8 ? 16 : gapi->gxProperties.cBPP;
   539 
   540         /* set up normal and landscape mode */
   541         GAPI_AddMode(this, bpp, gapi->gxProperties.cyHeight,
   542                      gapi->gxProperties.cxWidth);
   543         GAPI_AddMode(this, bpp, gapi->gxProperties.cxWidth,
   544                      gapi->gxProperties.cyHeight);
   545     }
   546 
   547     /* Determine the current screen size */
   548     this->info.current_w = gapi->gxProperties.cxWidth;
   549     this->info.current_h = gapi->gxProperties.cyHeight;
   550 
   551     /* Sort the mode lists */
   552     for (i = 0; i < NUM_MODELISTS; ++i) {
   553         if (gapi->SDL_nummodes[i] > 0) {
   554             SDL_qsort(gapi->SDL_modelist[i], gapi->SDL_nummodes[i],
   555                       sizeof *gapi->SDL_modelist[i], cmpmodes);
   556         }
   557     }
   558 
   559     vformat->BitsPerPixel =
   560         this->hidden->gxProperties.cBPP <
   561         8 ? 16 : (unsigned char) this->hidden->gxProperties.cBPP;
   562 
   563     // Get color mask
   564     if (this->hidden->gxProperties.ffFormat & kfDirect565) {
   565         vformat->BitsPerPixel = 16;
   566         vformat->Rmask = 0x0000f800;
   567         vformat->Gmask = 0x000007e0;
   568         vformat->Bmask = 0x0000001f;
   569         this->hidden->videoMode = GAPI_DIRECT_565;
   570     } else if (this->hidden->gxProperties.ffFormat & kfDirect555) {
   571         vformat->BitsPerPixel = 16;
   572         vformat->Rmask = 0x00007c00;
   573         vformat->Gmask = 0x000003e0;
   574         vformat->Bmask = 0x0000001f;
   575         this->hidden->videoMode = GAPI_DIRECT_555;
   576     } else if ((this->hidden->gxProperties.ffFormat & kfDirect)
   577                && (this->hidden->gxProperties.cBPP < 8)) {
   578         // We'll perform the conversion
   579         vformat->BitsPerPixel = 16;
   580         vformat->Rmask = 0x0000f800;    // 16 bit 565
   581         vformat->Gmask = 0x000007e0;
   582         vformat->Bmask = 0x0000001f;
   583         if (this->hidden->gxProperties.ffFormat & kfDirectInverted)
   584             this->hidden->invert = (1 << this->hidden->gxProperties.cBPP) - 1;
   585         this->hidden->colorscale =
   586             this->hidden->gxProperties.cBPP <
   587             8 ? 8 - this->hidden->gxProperties.cBPP : 0;
   588         this->hidden->videoMode = GAPI_MONO;
   589     } else if (this->hidden->gxProperties.ffFormat & kfPalette) {
   590         this->hidden->videoMode = GAPI_PALETTE;
   591     }
   592 
   593     /* We're done! */
   594     return (0);
   595 }
   596 
   597 SDL_Rect **
   598 GAPI_ListModes(_THIS, SDL_PixelFormat * format, Uint32 flags)
   599 {
   600     return (this->hidden->SDL_modelist[((format->BitsPerPixel + 7) / 8) - 1]);
   601 //       return (SDL_Rect **) -1;
   602 }
   603 
   604 SDL_Surface *
   605 GAPI_SetVideoMode(_THIS, SDL_Surface * current,
   606                   int width, int height, int bpp, Uint32 flags)
   607 {
   608     SDL_Surface *video;
   609     Uint32 Rmask, Gmask, Bmask;
   610     DWORD style;
   611     SDL_Rect allScreen;
   612 
   613     if (bpp < 4) {
   614         SDL_SetError("1 bpp and 2 bpp modes is not implemented yet!");
   615         return 0;
   616     }
   617 
   618     /* Recalculate bitmasks if necessary */
   619     if (bpp == current->format->BitsPerPixel) {
   620         video = current;
   621     } else {
   622         switch (bpp) {
   623         case 8:
   624             Rmask = 0;
   625             Gmask = 0;
   626             Bmask = 0;
   627             break;
   628         case 15:
   629         case 16:
   630             /* Default is 565 unless the display is specifically 555 */
   631             if (this->hidden->gxProperties.ffFormat & kfDirect555) {
   632                 Rmask = 0x00007c00;
   633                 Gmask = 0x000003e0;
   634                 Bmask = 0x0000001f;
   635             } else {
   636                 Rmask = 0x0000f800;
   637                 Gmask = 0x000007e0;
   638                 Bmask = 0x0000001f;
   639             }
   640             break;
   641         case 24:
   642         case 32:
   643             Rmask = 0x00ff0000;
   644             Gmask = 0x0000ff00;
   645             Bmask = 0x000000ff;
   646             break;
   647         default:
   648             SDL_SetError("Unsupported Bits Per Pixel format requested");
   649             return NULL;
   650         }
   651         video = SDL_CreateRGBSurface(SDL_SWSURFACE,
   652                                      0, 0, bpp, Rmask, Gmask, Bmask, 0);
   653         if (video == NULL) {
   654             SDL_OutOfMemory();
   655             return (NULL);
   656         }
   657     }
   658 
   659     gapi->userOrientation = SDL_ORIENTATION_UP;
   660     video->flags = SDL_FULLSCREEN;      /* Clear flags, GAPI supports fullscreen only */
   661 
   662     /* GAPI or VGA? */
   663     if (g_hGapiLib) {
   664         FillStructs(this, 0);
   665         if ((((unsigned) width != gapi->gxProperties.cxWidth)
   666              || ((unsigned) height != gapi->gxProperties.cyHeight))
   667             && (((unsigned) width != gapi->gxProperties.cyHeight)
   668                 || ((unsigned) height != gapi->gxProperties.cxWidth)))
   669             FillStructs(this, 1);       // gapi is found but we use VGA resolution                        
   670     } else
   671         FillStructs(this, 1);
   672 
   673     if (!this->hidden->needUpdate && !this->hidden->videoMem) {
   674         SDL_SetError
   675             ("Couldn't get address of video memory, may be unsupported device or bug");
   676         return (NULL);
   677     }
   678 
   679     /* detect user landscape mode */
   680     if ((width > height)
   681         && (GetSystemMetrics(SM_CXSCREEN) < GetSystemMetrics(SM_CYSCREEN)))
   682         gapi->userOrientation = SDL_ORIENTATION_RIGHT;
   683 
   684     /* shall we apply hires fix? for example when we do not use hires resource */
   685     gapi->hiresFix = 0;
   686     if (gapi->userOrientation == SDL_ORIENTATION_RIGHT) {
   687         if ((width > GetSystemMetrics(SM_CYSCREEN))
   688             || (height > GetSystemMetrics(SM_CXSCREEN)))
   689             gapi->hiresFix = 1;
   690     } else if ((width > GetSystemMetrics(SM_CXSCREEN))
   691                || (height > GetSystemMetrics(SM_CYSCREEN)))
   692         if (!((width == GetSystemMetrics(SM_CYSCREEN)) && (height == GetSystemMetrics(SM_CXSCREEN))))   // user portrait, device landscape
   693             gapi->hiresFix = 1;
   694 
   695     switch (gapi->userOrientation) {
   696     case SDL_ORIENTATION_UP:
   697         gapi->startOffset = 0;
   698         gapi->dstLineStep = gapi->gxProperties.cbyPitch;
   699         gapi->dstPixelStep = gapi->gxProperties.cbxPitch;
   700         break;
   701     case SDL_ORIENTATION_RIGHT:
   702         switch (gapi->gapiOrientation) {
   703         case SDL_ORIENTATION_UP:
   704         case SDL_ORIENTATION_RIGHT:
   705         case SDL_ORIENTATION_LEFT:
   706             if ((this->hidden->videoMode == GAPI_MONO))
   707                 gapi->startOffset = -gapi->gxProperties.cbxPitch + 1;   // monochrome mode
   708             else
   709                 gapi->startOffset =
   710                     gapi->gxProperties.cbyPitch *
   711                     (gapi->gxProperties.cyHeight - 1);
   712 
   713             gapi->dstLineStep = gapi->gxProperties.cbxPitch;
   714             gapi->dstPixelStep = -gapi->gxProperties.cbyPitch;
   715             break;
   716         }
   717     }
   718 
   719     video->w = this->hidden->w = width;
   720     video->h = this->hidden->h = height;
   721     video->pitch = SDL_CalculatePitch(video);
   722 
   723     /* Small fix for WinCE/Win32 - when activating window
   724        SDL_VideoSurface is equal to zero, so activating code
   725        is not called properly for fullscreen windows because
   726        macros WINDIB_FULLSCREEN uses SDL_VideoSurface
   727      */
   728     SDL_VideoSurface = video;
   729 
   730     /* GAPI is always fullscreen, title bar is useless */
   731     style = 0;
   732 
   733     if (!SDL_windowid)
   734         SetWindowLong(SDL_Window, GWL_STYLE, style);
   735 
   736     /* Allocate bitmap */
   737     if (gapiBuffer) {
   738         SDL_free(gapiBuffer);
   739         gapiBuffer = NULL;
   740     }
   741     gapiBuffer = SDL_malloc(video->h * video->pitch);
   742     video->pixels = gapiBuffer;
   743 
   744     if (!this->hidden->buffer) {
   745         SDL_SetError("Couldn't allocate buffer for requested mode");
   746         return (NULL);
   747     }
   748 
   749     SDL_memset(gapiBuffer, 255, video->h * video->pitch);
   750     MoveWindow(SDL_Window, 0, 0, GetSystemMetrics(SM_CXSCREEN),
   751                GetSystemMetrics(SM_CYSCREEN), FALSE);
   752     ShowWindow(SDL_Window, SW_SHOW);
   753     SetForegroundWindow(SDL_Window);
   754 
   755     /* JC 14 Mar 2006
   756        Flush the message loop or this can cause big problems later
   757        Especially if the user decides to use dialog boxes or assert()!
   758      */
   759     WIN_FlushMessageQueue();
   760 
   761     /* Open GAPI display */
   762     if (!gapi->useVga && this->hidden->useGXOpenDisplay)
   763         if (!gapi->gxFunc.GXOpenDisplay(SDL_Window, GX_FULLSCREEN)) {
   764             SDL_SetError("Couldn't initialize GAPI");
   765             return (NULL);
   766         }
   767 #if REPORT_VIDEO_INFO
   768     printf("Video properties:\n");
   769     printf("display bpp: %d\n", gapi->gxProperties.cBPP);
   770     printf("display width: %d\n", gapi->gxProperties.cxWidth);
   771     printf("display height: %d\n", gapi->gxProperties.cyHeight);
   772     printf("x pitch: %d\n", gapi->gxProperties.cbxPitch);
   773     printf("y pitch: %d\n", gapi->gxProperties.cbyPitch);
   774     printf("gapi flags: 0x%x\n", gapi->gxProperties.ffFormat);
   775 
   776     if (!gapi->useVga && this->hidden->useGXOpenDisplay && gapi->needUpdate) {
   777         gapi->videoMem = gapi->gxFunc.GXBeginDraw();
   778         gapi->gxFunc.GXEndDraw();
   779     }
   780 
   781     printf("video memory: 0x%x\n", gapi->videoMem);
   782     printf("need update: %d\n", gapi->needUpdate);
   783     printf("hi-res fix: %d\n", gapi->hiresFix);
   784     printf("VGA is available on the device: %d\n", g_bRawBufferAvailable);
   785     printf("use raw framebuffer: %d\n", gapi->useVga);
   786     printf("video surface bpp: %d\n", video->format->BitsPerPixel);
   787     printf("video surface width: %d\n", video->w);
   788     printf("video surface height: %d\n", video->h);
   789 #endif
   790 
   791 
   792     /* Blank screen */
   793     allScreen.x = allScreen.y = 0;
   794     allScreen.w = video->w - 1;
   795     allScreen.h = video->h - 1;
   796     GAPI_UpdateRects(this, 1, &allScreen);
   797 
   798     /* We're done */
   799     return (video);
   800 }
   801 
   802 /* We don't actually allow hardware surfaces other than the main one */
   803 static int
   804 GAPI_AllocHWSurface(_THIS, SDL_Surface * surface)
   805 {
   806     return (-1);
   807 }
   808 
   809 static void
   810 GAPI_FreeHWSurface(_THIS, SDL_Surface * surface)
   811 {
   812     return;
   813 }
   814 
   815 /* We need to wait for vertical retrace on page flipped displays */
   816 static int
   817 GAPI_LockHWSurface(_THIS, SDL_Surface * surface)
   818 {
   819     return (0);
   820 }
   821 
   822 static void
   823 GAPI_UnlockHWSurface(_THIS, SDL_Surface * surface)
   824 {
   825     return;
   826 }
   827 
   828 static int
   829 updateLine8to8(_THIS, unsigned char *srcPointer, unsigned char *destPointer,
   830                int width, int height, int lines)
   831 {
   832     if (gapi->dstPixelStep == 1) {      /* optimized blitting on most devices */
   833         SDL_memcpy(destPointer, srcPointer, width);
   834         return 1;
   835     } else {
   836         // TODO: read 4 pixels, write DWORD
   837         int step = gapi->dstPixelStep;
   838         while (width--) {
   839             *destPointer = *srcPointer++;
   840             destPointer += step;
   841         }
   842     }
   843     return 1;
   844 }
   845 
   846 /* Video memory is very slow so lets optimize as much as possible */
   847 static int
   848 updateLine16to16(_THIS, PIXEL * srcPointer, PIXEL * destPointer, int width,
   849                  int height, int lines)
   850 {
   851     PIXEL *line1, *line2;
   852     int step = gapi->dstPixelStep / 2;
   853 
   854     if (step == 1) {            /* optimized blitting on most devices */
   855         SDL_memcpy(destPointer, srcPointer, width * sizeof(PIXEL));
   856         return 1;
   857     } else {
   858         if ((gapi->gapiOrientation != SDL_ORIENTATION_UP) && (gapi->userOrientation == SDL_ORIENTATION_UP))     // iPaq 3660/3800 and user orientation up
   859         {
   860             // to prevent data misalignment copy only one line
   861             if (((((unsigned) destPointer & 3) != 0)
   862                  && (gapi->gapiOrientation == SDL_ORIENTATION_LEFT))
   863                 || ((((unsigned) destPointer & 3) == 0)
   864                     && (gapi->gapiOrientation != SDL_ORIENTATION_LEFT))
   865                 || (lines == 1)) {
   866                 while (width--) {
   867                     *destPointer = *srcPointer++;
   868                     destPointer += step;
   869                 }
   870                 return 1;
   871             }
   872 
   873             /* read two lines at the same time, write DWORD */
   874             line1 = srcPointer;
   875             line2 = srcPointer + SDL_VideoSurface->pitch / 2;
   876 
   877             if (gapi->gapiOrientation == SDL_ORIENTATION_LEFT)
   878                 while (width--) // iPaq 3800
   879                 {
   880                     *(DWORD *) destPointer = (*line2++ << 16) | *line1++;
   881                     destPointer += step;
   882             } else {
   883                 destPointer += gapi->gxProperties.cbyPitch / 2;
   884 
   885                 while (width--) // iPaq 3660
   886                 {
   887                     *(DWORD *) destPointer = (*line1++ << 16) | *line2++;
   888                     destPointer += step;
   889                 }
   890             }
   891             return 2;
   892         } else {
   893             // iPaq 3800 and user orientation landscape
   894             if (gapi->gapiOrientation == SDL_ORIENTATION_LEFT) {
   895                 int w1;
   896 
   897                 // to prevent data misalignment copy only one pixel
   898                 if ((((unsigned) destPointer & 3) == 0) && (width > 0)) {
   899                     *destPointer-- = *srcPointer++;
   900                     width--;
   901                 }
   902 
   903                 destPointer--;
   904 
   905                 w1 = width / 2;
   906 
   907                 while (w1--) {
   908                     DWORD p = *(DWORD *) srcPointer;
   909                     *((DWORD *) destPointer) = (p << 16) | (p >> 16);
   910                     destPointer -= 2;
   911                     srcPointer += 2;
   912                 }
   913 
   914                 if (width & 1)  // copy the last pixel
   915                 {
   916                     destPointer++;
   917                     *destPointer = *srcPointer;
   918                 }
   919 
   920                 return 1;
   921             }
   922             // modern iPaqs and user orientation landscape
   923             // read two pixels, write DWORD
   924 
   925             line1 = srcPointer;
   926             line2 = srcPointer + SDL_VideoSurface->pitch / 2;
   927 
   928             if ((((unsigned) destPointer & 3) != 0) || (lines == 1)) {
   929                 while (width--) {
   930                     *destPointer = *srcPointer++;
   931                     destPointer += step;
   932                 }
   933                 return 1;
   934             }
   935 
   936             while (width--) {
   937                 *(DWORD *) destPointer = (*line2++ << 16) | *line1++;
   938                 destPointer -= gapi->gxProperties.cbyPitch / 2;
   939             }
   940             return 2;
   941         }
   942     }
   943 }
   944 
   945 // Color component masks for 565
   946 #define REDMASK (31<<11)
   947 #define GREENMASK (63<<5)
   948 #define BLUEMASK (31)
   949 
   950 
   951 static int
   952 updateLine16to4(_THIS, PIXEL * srcPointer, unsigned char *destPointer,
   953                 int width, int height, int lines, int yNibble, int xNibble)
   954 {
   955     PIXEL *line1, *line2;
   956     int step = gapi->dstPixelStep;
   957 
   958     if (gapi->userOrientation == SDL_ORIENTATION_UP) {
   959         if (yNibble)            // copy bottom half of a line
   960         {
   961             while (width--) {
   962                 PIXEL c1 = *srcPointer++;
   963                 c1 = ((c1 & REDMASK) >> 11) + ((c1 & GREENMASK) >> 5) +
   964                     (c1 & BLUEMASK);
   965                 *destPointer = (*destPointer & 0x0F) | ((~(c1 >> 3) << 4));
   966                 destPointer += step;
   967             }
   968             return 1;
   969         }
   970         // either 1 pixel picture or tail, anyway this is the last line
   971         if (lines == 1) {
   972             while (width--) {
   973                 PIXEL c1 = *srcPointer++;
   974                 c1 = ((c1 & REDMASK) >> 11) + ((c1 & GREENMASK) >> 5) +
   975                     (c1 & BLUEMASK);
   976                 *destPointer = (*destPointer & 0xF0) | ((~(c1 >> 3) & 0xF));
   977                 destPointer += step;
   978             }
   979             return 1;
   980         }
   981 
   982         line1 = srcPointer;
   983         line2 = srcPointer + SDL_VideoSurface->pitch / 2;
   984 
   985         while (width--) {
   986             PIXEL c1 = *line1++;
   987             PIXEL c2 = *line2++;
   988             c1 = ((c1 & REDMASK) >> 11) + ((c1 & GREENMASK) >> 5) +
   989                 (c1 & BLUEMASK);
   990             c2 = ((c2 & REDMASK) >> 11) + ((c2 & GREENMASK) >> 5) +
   991                 (c2 & BLUEMASK);
   992             *destPointer = ~((c1 >> 3) + ((c2 >> 3) << 4));
   993             destPointer += step;
   994         }
   995         return 2;
   996     } else {
   997         int w1;
   998         w1 = width / 2;
   999 
  1000         if (xNibble) {
  1001             // copy one pixel
  1002             PIXEL c1 = *srcPointer++;
  1003             c1 = ((c1 & REDMASK) >> 11) + ((c1 & GREENMASK) >> 5) +
  1004                 (c1 & BLUEMASK);
  1005             *destPointer = (*destPointer & 0xF0) | ((~(c1 >> 3) & 0xF));
  1006             destPointer++;
  1007         }
  1008 
  1009         while (w1--) {
  1010             PIXEL c1 = *srcPointer;
  1011             PIXEL c2 = *(srcPointer + 1);
  1012             c1 = ((c1 & REDMASK) >> 11) + ((c1 & GREENMASK) >> 5) +
  1013                 (c1 & BLUEMASK);
  1014             c2 = ((c2 & REDMASK) >> 11) + ((c2 & GREENMASK) >> 5) +
  1015                 (c2 & BLUEMASK);
  1016             *destPointer++ = ~((c2 >> 3) + ((c1 >> 3) << 4));
  1017             srcPointer += 2;
  1018         }
  1019 
  1020         // copy tail
  1021         if ((width & 1) && !xNibble) {
  1022             PIXEL c1 = *srcPointer;
  1023             c1 = ((c1 & REDMASK) >> 11) + ((c1 & GREENMASK) >> 5) +
  1024                 (c1 & BLUEMASK);
  1025             *destPointer = (*destPointer & 0x0F) | ((~(c1 >> 3) << 4));
  1026         }
  1027 
  1028         return 1;
  1029     }
  1030 }
  1031 
  1032 static void
  1033 GAPI_UpdateRectsMono(_THIS, int numrects, SDL_Rect * rects)
  1034 {
  1035     int i, height;
  1036     int linesProcessed;
  1037     int xNibble, yNibble;
  1038 
  1039     for (i = 0; i < numrects; i++) {
  1040         unsigned char *destPointer;
  1041         unsigned char *srcPointer;
  1042 
  1043         if (gapi->userOrientation == SDL_ORIENTATION_UP)
  1044             destPointer =
  1045                 (unsigned char *) gapi->videoMem + gapi->startOffset -
  1046                 rects[i].y * gapi->gxProperties.cBPP / 8 +
  1047                 rects[i].x * gapi->dstPixelStep;
  1048         else
  1049             destPointer =
  1050                 (unsigned char *) gapi->videoMem + gapi->startOffset +
  1051                 rects[i].x * gapi->gxProperties.cBPP / 8 +
  1052                 rects[i].y * gapi->dstLineStep;
  1053 
  1054         srcPointer =
  1055             ((unsigned char *) SDL_VideoSurface->pixels) +
  1056             rects[i].y * SDL_VideoSurface->pitch + rects[i].x * 2;
  1057         yNibble = rects[i].y & 1;       // TODO: only for 4 bpp
  1058         xNibble = rects[i].x & 1;
  1059         height = rects[i].h;
  1060         while (height > 0) {
  1061             switch (gapi->gxProperties.cBPP) {
  1062             case 2:            // TODO
  1063             case 4:
  1064                 linesProcessed =
  1065                     updateLine16to4(this, (PIXEL *) srcPointer,
  1066                                     destPointer, rects[i].w,
  1067                                     rects[i].h, height, yNibble, xNibble);
  1068                 yNibble = 0;
  1069             }
  1070             height -= linesProcessed;
  1071             if (gapi->userOrientation == SDL_ORIENTATION_UP)
  1072                 destPointer--;  // always fill 1 byte
  1073             else
  1074                 destPointer += gapi->dstLineStep;
  1075             srcPointer += SDL_VideoSurface->pitch * linesProcessed;     // pitch in bytes
  1076         }
  1077     }
  1078 }
  1079 
  1080 static void
  1081 GAPI_UpdateRectsColor(_THIS, int numrects, SDL_Rect * rects)
  1082 {
  1083     int i, height;
  1084     int bytesPerPixel = (gapi->gxProperties.cBPP + 1) / 8;
  1085     int linesProcessed;
  1086     for (i = 0; i < numrects; i++) {
  1087         unsigned char *destPointer =
  1088             (unsigned char *) gapi->videoMem + gapi->startOffset +
  1089             rects[i].y * gapi->dstLineStep + rects[i].x * gapi->dstPixelStep;
  1090         unsigned char *srcPointer =
  1091             ((unsigned char *) SDL_VideoSurface->pixels) +
  1092             rects[i].y * SDL_VideoSurface->pitch + rects[i].x * bytesPerPixel;
  1093         height = rects[i].h;
  1094 
  1095 //              fprintf(stderr, "Starting rect %dx%d, dst=0x%x, w = %d, h = %d\n", rects[i].w, rects[i].h,destPointer,rects[i].w,rects[i].h);
  1096 //              fflush(stderr);
  1097         linesProcessed = height;
  1098 
  1099         while (height > 0) {
  1100             switch (bytesPerPixel) {
  1101             case 1:
  1102                 linesProcessed =
  1103                     updateLine8to8(this, srcPointer,
  1104                                    (unsigned char *) destPointer,
  1105                                    rects[i].w, rects[i].h, height);
  1106                 break;
  1107             case 2:
  1108 #pragma warning(disable: 4133)
  1109                 linesProcessed =
  1110                     updateLine16to16(this, (PIXEL *) srcPointer,
  1111                                      destPointer, rects[i].w,
  1112                                      rects[i].h, height);
  1113                 break;
  1114             }
  1115             height -= linesProcessed;
  1116             destPointer += gapi->dstLineStep * linesProcessed;
  1117             srcPointer += SDL_VideoSurface->pitch * linesProcessed;     // pitch in bytes
  1118         }
  1119 //              fprintf(stderr, "End of rect\n");
  1120 //              fflush(stderr);
  1121     }
  1122 }
  1123 
  1124 
  1125 static void
  1126 GAPI_UpdateRects(_THIS, int numrects, SDL_Rect * rects)
  1127 {
  1128     // we do not want to corrupt video memory
  1129     if (gapi->suspended)
  1130         return;
  1131 
  1132     if (gapi->needUpdate)
  1133         gapi->videoMem = gapi->gxFunc.GXBeginDraw();
  1134 
  1135     if (gapi->gxProperties.cBPP < 8)
  1136         GAPI_UpdateRectsMono(this, numrects, rects);
  1137     else
  1138         GAPI_UpdateRectsColor(this, numrects, rects);
  1139 
  1140     if (gapi->needUpdate)
  1141         gapi->gxFunc.GXEndDraw();
  1142 }
  1143 
  1144 /* Note:  If we are terminated, this could be called in the middle of
  1145    another SDL video routine -- notably UpdateRects.
  1146 */
  1147 void
  1148 GAPI_VideoQuit(_THIS)
  1149 {
  1150     int i, j;
  1151     /* Destroy the window and everything associated with it */
  1152     if (SDL_Window) {
  1153         if ((g_hGapiLib != 0) && this && this->hidden
  1154             && this->hidden->gxFunc.GXCloseDisplay && !this->hidden->useVga)
  1155             this->hidden->gxFunc.GXCloseDisplay();
  1156 
  1157         if (this->screen->pixels != NULL) {
  1158             SDL_free(this->screen->pixels);
  1159             this->screen->pixels = NULL;
  1160         }
  1161         if (screen_icn) {
  1162             DestroyIcon(screen_icn);
  1163             screen_icn = NULL;
  1164         }
  1165 
  1166         DIB_DestroyWindow(this);
  1167         SDL_UnregisterApp();
  1168 
  1169         SDL_Window = NULL;
  1170 #if defined(_WIN32_WCE)
  1171 
  1172 // Unload wince aygshell library to prevent leak
  1173         if (aygshell) {
  1174             FreeLibrary(aygshell);
  1175             aygshell = NULL;
  1176         }
  1177 #endif
  1178 
  1179         /* Free video mode lists */
  1180         for (i = 0; i < NUM_MODELISTS; ++i) {
  1181             if (gapi->SDL_modelist[i] != NULL) {
  1182                 for (j = 0; gapi->SDL_modelist[i][j]; ++j)
  1183                     SDL_free(gapi->SDL_modelist[i][j]);
  1184                 SDL_free(gapi->SDL_modelist[i]);
  1185                 gapi->SDL_modelist[i] = NULL;
  1186             }
  1187         }
  1188 
  1189     }
  1190 
  1191 }
  1192 
  1193 static void
  1194 GAPI_RealizePalette(_THIS)
  1195 {
  1196     OutputDebugString(TEXT("GAPI_RealizePalette NOT IMPLEMENTED !\r\n"));
  1197 }
  1198 
  1199 static void
  1200 GAPI_PaletteChanged(_THIS, HWND window)
  1201 {
  1202     OutputDebugString(TEXT("GAPI_PaletteChanged NOT IMPLEMENTED !\r\n"));
  1203 }
  1204 
  1205 static void
  1206 GAPI_WinPAINT(_THIS, HDC hdc)
  1207 {
  1208     // draw current offscreen buffer on hdc
  1209 
  1210     int bpp = 16;               // we always use either 8 or 16 bpp internally
  1211 
  1212     unsigned short *bitmapData;
  1213     HBITMAP hb;
  1214     HDC srcDC;
  1215 
  1216     // Create a DIB
  1217     BYTE buffer[sizeof(BITMAPINFOHEADER) + 3 * sizeof(RGBQUAD)] = { 0 };
  1218     BITMAPINFO *pBMI = (BITMAPINFO *) buffer;
  1219     BITMAPINFOHEADER *pHeader = &pBMI->bmiHeader;
  1220     DWORD *pColors = (DWORD *) & pBMI->bmiColors;
  1221 
  1222     // CreateDIBSection does not support 332 pixel format on wce
  1223     if (gapi->gxProperties.cBPP == 8)
  1224         return;
  1225 
  1226     // DIB Header
  1227     pHeader->biSize = sizeof(BITMAPINFOHEADER);
  1228     pHeader->biWidth = this->hidden->w;
  1229     pHeader->biHeight = -this->hidden->h;
  1230     pHeader->biPlanes = 1;
  1231     pHeader->biBitCount = bpp;
  1232     pHeader->biCompression = BI_RGB;
  1233     pHeader->biSizeImage = (this->hidden->w * this->hidden->h * bpp) / 8;
  1234 
  1235     // Color masks
  1236     if (bpp == 16) {
  1237         pColors[0] = REDMASK;
  1238         pColors[1] = GREENMASK;
  1239         pColors[2] = BLUEMASK;
  1240         pHeader->biCompression = BI_BITFIELDS;
  1241     }
  1242     // Create the DIB
  1243     hb = CreateDIBSection(0, pBMI, DIB_RGB_COLORS, (void **) &bitmapData, 0,
  1244                           0);
  1245 
  1246     // copy data
  1247     // FIXME: prevent misalignment, but I've never seen non aligned width of screen
  1248     memcpy(bitmapData, this->hidden->buffer, pHeader->biSizeImage);
  1249     srcDC = CreateCompatibleDC(hdc);
  1250     SelectObject(srcDC, hb);
  1251 
  1252     BitBlt(hdc, 0, 0, this->hidden->w, this->hidden->h, srcDC, 0, 0, SRCCOPY);
  1253 
  1254     DeleteObject(hb);
  1255     DeleteDC(srcDC);
  1256 }
  1257 
  1258 int
  1259 GAPI_SetColors(_THIS, int firstcolor, int ncolors, SDL_Color * colors)
  1260 {
  1261     GAPI_CreatePalette(ncolors, colors);
  1262     return 1;
  1263 }
  1264 
  1265 /* vi: set ts=4 sw=4 expandtab: */