Home | History | Annotate | Download | only in photon
      1 /*
      2     SDL - Simple DirectMedia Layer
      3     Copyright (C) 1997-2012 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 (at) libsdl.org
     21 */
     22 #include "SDL_config.h"
     23 
     24 #include <unistd.h>
     25 #include <sys/ioctl.h>
     26 
     27 #include "SDL_endian.h"
     28 #include "SDL_timer.h"
     29 #include "SDL_thread.h"
     30 #include "SDL_video.h"
     31 #include "SDL_mouse.h"
     32 #include "../SDL_sysvideo.h"
     33 #include "../SDL_pixels_c.h"
     34 #include "../../events/SDL_events_c.h"
     35 #include "SDL_ph_video.h"
     36 #include "SDL_ph_modes_c.h"
     37 #include "SDL_ph_image_c.h"
     38 #include "SDL_ph_events_c.h"
     39 #include "SDL_ph_mouse_c.h"
     40 #include "SDL_ph_wm_c.h"
     41 #include "SDL_ph_gl.h"
     42 #include "SDL_phyuv_c.h"
     43 #include "../blank_cursor.h"
     44 
     45 static int  ph_VideoInit(_THIS, SDL_PixelFormat *vformat);
     46 static SDL_Surface *ph_SetVideoMode(_THIS, SDL_Surface *current, int width, int height, int bpp, Uint32 flags);
     47 static int  ph_SetColors(_THIS, int firstcolor, int ncolors, SDL_Color *colors);
     48 static void ph_VideoQuit(_THIS);
     49 static void ph_DeleteDevice(SDL_VideoDevice *device);
     50 
     51 static int phstatus=-1;
     52 
     53 static int ph_Available(void)
     54 {
     55     if (phstatus!=0)
     56     {
     57         phstatus=PtInit(NULL);
     58         if (phstatus==0)
     59         {
     60            return 1;
     61         }
     62         else
     63         {
     64            return 0;
     65         }
     66     }
     67     return 1;
     68 }
     69 
     70 static SDL_VideoDevice* ph_CreateDevice(int devindex)
     71 {
     72     SDL_VideoDevice* device;
     73 
     74     /* Initialize all variables that we clean on shutdown */
     75     device = (SDL_VideoDevice *)SDL_malloc(sizeof(SDL_VideoDevice));
     76     if (device)
     77     {
     78         SDL_memset(device, 0, (sizeof *device));
     79         device->hidden = (struct SDL_PrivateVideoData*)SDL_malloc((sizeof *device->hidden));
     80         device->gl_data = NULL;
     81     }
     82     if ((device == NULL) || (device->hidden == NULL))
     83     {
     84         SDL_OutOfMemory();
     85         ph_DeleteDevice(device);
     86         return NULL;
     87     }
     88     SDL_memset(device->hidden, 0, (sizeof *device->hidden));
     89 
     90     /* Set the driver flags */
     91     device->handles_any_size = 1;
     92 
     93     /* Set the function pointers */
     94     device->CreateYUVOverlay = ph_CreateYUVOverlay;
     95     device->VideoInit = ph_VideoInit;
     96     device->ListModes = ph_ListModes;
     97     device->SetVideoMode = ph_SetVideoMode;
     98     device->ToggleFullScreen = ph_ToggleFullScreen;
     99     device->UpdateMouse = ph_UpdateMouse;
    100     device->SetColors = ph_SetColors;
    101     device->UpdateRects = NULL;                        /* set up in ph_SetupUpdateFunction */
    102     device->VideoQuit = ph_VideoQuit;
    103     device->AllocHWSurface = ph_AllocHWSurface;
    104     device->CheckHWBlit = ph_CheckHWBlit;
    105     device->FillHWRect = ph_FillHWRect;
    106     device->SetHWColorKey = ph_SetHWColorKey;
    107     device->SetHWAlpha = ph_SetHWAlpha;
    108     device->LockHWSurface = ph_LockHWSurface;
    109     device->UnlockHWSurface = ph_UnlockHWSurface;
    110     device->FlipHWSurface = ph_FlipHWSurface;
    111     device->FreeHWSurface = ph_FreeHWSurface;
    112     device->SetCaption = ph_SetCaption;
    113     device->SetIcon = NULL;
    114     device->IconifyWindow = ph_IconifyWindow;
    115     device->GrabInput = ph_GrabInput;
    116     device->GetWMInfo = ph_GetWMInfo;
    117     device->FreeWMCursor = ph_FreeWMCursor;
    118     device->CreateWMCursor = ph_CreateWMCursor;
    119     device->ShowWMCursor = ph_ShowWMCursor;
    120     device->WarpWMCursor = ph_WarpWMCursor;
    121     device->MoveWMCursor = NULL;
    122     device->CheckMouseMode = ph_CheckMouseMode;
    123     device->InitOSKeymap = ph_InitOSKeymap;
    124     device->PumpEvents = ph_PumpEvents;
    125 
    126     /* OpenGL support. */
    127 #if SDL_VIDEO_OPENGL
    128     device->GL_MakeCurrent = ph_GL_MakeCurrent;
    129     device->GL_SwapBuffers = ph_GL_SwapBuffers;
    130     device->GL_GetAttribute = ph_GL_GetAttribute;
    131     device->GL_LoadLibrary = ph_GL_LoadLibrary;
    132     device->GL_GetProcAddress = ph_GL_GetProcAddress;
    133 #endif /* SDL_VIDEO_OPENGL */
    134 
    135     device->free = ph_DeleteDevice;
    136 
    137     return device;
    138 }
    139 
    140 VideoBootStrap ph_bootstrap = {
    141     "photon", "QNX Photon video output",
    142     ph_Available, ph_CreateDevice
    143 };
    144 
    145 static void ph_DeleteDevice(SDL_VideoDevice *device)
    146 {
    147     if (device)
    148     {
    149         if (device->hidden)
    150         {
    151             SDL_free(device->hidden);
    152             device->hidden = NULL;
    153         }
    154         if (device->gl_data)
    155         {
    156             SDL_free(device->gl_data);
    157             device->gl_data = NULL;
    158         }
    159         SDL_free(device);
    160         device = NULL;
    161     }
    162 }
    163 
    164 static PtWidget_t *ph_CreateWindow(_THIS)
    165 {
    166     PtWidget_t *widget;
    167 
    168     widget = PtCreateWidget(PtWindow, NULL, 0, NULL);
    169 
    170     return widget;
    171 }
    172 
    173 static int ph_SetupWindow(_THIS, int w, int h, int flags)
    174 {
    175     PtArg_t     args[32];
    176     PhPoint_t   pos = {0, 0};
    177     PhDim_t*    olddim;
    178     PhDim_t     dim = {w, h};
    179     PhRect_t    desktopextent;
    180     int         nargs = 0;
    181     const char* windowpos;
    182     const char* iscentered;
    183     int         x, y;
    184 
    185     /* check if window size has been changed by Window Manager */
    186     PtGetResource(window, Pt_ARG_DIM, &olddim, 0);
    187     if ((olddim->w!=w) || (olddim->h!=h))
    188     {
    189        PtSetArg(&args[nargs++], Pt_ARG_DIM, &dim, 0);
    190     }
    191 
    192     if ((flags & SDL_RESIZABLE) == SDL_RESIZABLE)
    193     {
    194         PtSetArg(&args[nargs++], Pt_ARG_WINDOW_MANAGED_FLAGS, Pt_FALSE, Ph_WM_CLOSE);
    195         PtSetArg(&args[nargs++], Pt_ARG_WINDOW_MANAGED_FLAGS, Pt_TRUE, Ph_WM_MAX | Ph_WM_RESTORE | Ph_WM_RESIZE);
    196         PtSetArg(&args[nargs++], Pt_ARG_WINDOW_NOTIFY_FLAGS, Pt_TRUE, Ph_WM_RESIZE | Ph_WM_MOVE | Ph_WM_CLOSE | Ph_WM_MAX | Ph_WM_RESTORE);
    197         PtSetArg(&args[nargs++], Pt_ARG_WINDOW_RENDER_FLAGS, Pt_TRUE, Ph_WM_RENDER_RESIZE | Ph_WM_RENDER_MAX | Ph_WM_RENDER_COLLAPSE | Ph_WM_RENDER_RETURN);
    198         PtSetArg(&args[nargs++], Pt_ARG_RESIZE_FLAGS, Pt_TRUE, Pt_RESIZE_XY_AS_REQUIRED);
    199     }
    200     else
    201     {
    202         PtSetArg(&args[nargs++], Pt_ARG_WINDOW_MANAGED_FLAGS, Pt_FALSE, Ph_WM_RESIZE | Ph_WM_MAX | Ph_WM_RESTORE | Ph_WM_CLOSE);
    203         PtSetArg(&args[nargs++], Pt_ARG_WINDOW_NOTIFY_FLAGS, Pt_FALSE, Ph_WM_RESIZE | Ph_WM_MAX | Ph_WM_RESTORE);
    204         PtSetArg(&args[nargs++], Pt_ARG_WINDOW_NOTIFY_FLAGS, Pt_TRUE, Ph_WM_MOVE | Ph_WM_CLOSE);
    205         PtSetArg(&args[nargs++], Pt_ARG_WINDOW_RENDER_FLAGS, Pt_FALSE, Ph_WM_RENDER_RESIZE | Ph_WM_RENDER_MAX | Ph_WM_RENDER_COLLAPSE | Ph_WM_RENDER_RETURN);
    206         PtSetArg(&args[nargs++], Pt_ARG_RESIZE_FLAGS, Pt_FALSE, Pt_RESIZE_XY_AS_REQUIRED);
    207     }
    208 
    209     if (((flags & SDL_NOFRAME)==SDL_NOFRAME) || ((flags & SDL_FULLSCREEN)==SDL_FULLSCREEN))
    210     {
    211        if ((flags & SDL_RESIZABLE) != SDL_RESIZABLE)
    212        {
    213            PtSetArg(&args[nargs++], Pt_ARG_WINDOW_RENDER_FLAGS, Pt_FALSE, Pt_TRUE);
    214        }
    215        else
    216        {
    217            PtSetArg(&args[nargs++], Pt_ARG_WINDOW_RENDER_FLAGS, Pt_FALSE, Pt_TRUE);
    218            PtSetArg(&args[nargs++], Pt_ARG_WINDOW_RENDER_FLAGS, Pt_TRUE, Ph_WM_RENDER_RESIZE | Ph_WM_RENDER_BORDER);
    219        }
    220     }
    221     else
    222     {
    223         PtSetArg(&args[nargs++], Pt_ARG_WINDOW_RENDER_FLAGS, Pt_TRUE, Ph_WM_RENDER_BORDER | Ph_WM_RENDER_TITLE |
    224                                  Ph_WM_RENDER_CLOSE | Ph_WM_RENDER_MENU | Ph_WM_RENDER_MIN);
    225     }
    226 
    227     if ((flags & SDL_FULLSCREEN) == SDL_FULLSCREEN)
    228     {
    229         PtSetArg(&args[nargs++], Pt_ARG_POS, &pos, 0);
    230         PtSetArg(&args[nargs++], Pt_ARG_BASIC_FLAGS, Pt_TRUE, Pt_BASIC_PREVENT_FILL);
    231         PtSetArg(&args[nargs++], Pt_ARG_WINDOW_MANAGED_FLAGS, Pt_TRUE, Ph_WM_FFRONT | Ph_WM_MAX | Ph_WM_TOFRONT | Ph_WM_CONSWITCH);
    232         PtSetArg(&args[nargs++], Pt_ARG_WINDOW_STATE, Pt_TRUE, Ph_WM_STATE_ISFRONT | Ph_WM_STATE_ISFOCUS | Ph_WM_STATE_ISALTKEY);
    233     }
    234     else
    235     {
    236         PtSetArg(&args[nargs++], Pt_ARG_WINDOW_MANAGED_FLAGS, Pt_FALSE, Ph_WM_FFRONT | Ph_WM_CONSWITCH);
    237         PtSetArg(&args[nargs++], Pt_ARG_WINDOW_STATE, Pt_FALSE, Ph_WM_STATE_ISFRONT);
    238         PtSetArg(&args[nargs++], Pt_ARG_WINDOW_STATE, Pt_TRUE, Ph_WM_STATE_ISALTKEY);
    239 
    240         if ((flags & SDL_HWSURFACE) == SDL_HWSURFACE)
    241         {
    242             PtSetArg(&args[nargs++], Pt_ARG_BASIC_FLAGS, Pt_TRUE, Pt_BASIC_PREVENT_FILL);
    243         }
    244         else
    245         {
    246             PtSetArg(&args[nargs++], Pt_ARG_FILL_COLOR, Pg_BLACK, 0);
    247         }
    248         if (!currently_maximized)
    249         {
    250             windowpos = SDL_getenv("SDL_VIDEO_WINDOW_POS");
    251             iscentered = SDL_getenv("SDL_VIDEO_CENTERED");
    252 
    253             if ((iscentered) || ((windowpos) && (SDL_strcmp(windowpos, "center")==0)))
    254             {
    255                 PhWindowQueryVisible(Ph_QUERY_CONSOLE, 0, 0, &desktopextent);
    256                 if (desktop_mode.width>w)
    257                 {
    258                     pos.x = (desktop_mode.width - w)/2;
    259                 }
    260                 if (desktop_mode.height>h)
    261                 {
    262                     pos.y = (desktop_mode.height - h)/2;
    263                 }
    264 
    265                 pos.x+=desktopextent.ul.x;
    266                 pos.y+=desktopextent.ul.y;
    267                 PtSetArg(&args[nargs++], Pt_ARG_POS, &pos, 0);
    268             }
    269             else
    270             {
    271                 if (windowpos)
    272                 {
    273                     if (SDL_sscanf(windowpos, "%d,%d", &x, &y) == 2)
    274                     {
    275                         if ((x<desktop_mode.width) && (y<desktop_mode.height))
    276                         {
    277                             PhWindowQueryVisible(Ph_QUERY_CONSOLE, 0, 0, &desktopextent);
    278                             pos.x=x+desktopextent.ul.x;
    279                             pos.y=y+desktopextent.ul.y;
    280                         }
    281                         PtSetArg(&args[nargs++], Pt_ARG_POS, &pos, 0);
    282                     }
    283                 }
    284             }
    285         }
    286 
    287         /* if window is maximized render it as maximized */
    288         if (currently_maximized)
    289         {
    290            PtSetArg(&args[nargs++], Pt_ARG_WINDOW_STATE, Pt_TRUE, Ph_WM_STATE_ISMAX);
    291         }
    292         else
    293         {
    294            PtSetArg(&args[nargs++], Pt_ARG_WINDOW_STATE, Pt_FALSE, Ph_WM_STATE_ISMAX);
    295         }
    296 
    297         /* do not grab the keyboard by default */
    298         PtSetArg(&args[nargs++], Pt_ARG_WINDOW_STATE, Pt_FALSE, Ph_WM_STATE_ISALTKEY);
    299 
    300         /* bring the focus to the window */
    301         PtSetArg(&args[nargs++], Pt_ARG_WINDOW_STATE, Pt_TRUE, Ph_WM_STATE_ISFOCUS);
    302 
    303         /* allow to catch hide event */
    304         PtSetArg(&args[nargs++], Pt_ARG_WINDOW_MANAGED_FLAGS, Pt_TRUE, Ph_WM_HIDE);
    305         PtSetArg(&args[nargs++], Pt_ARG_WINDOW_NOTIFY_FLAGS, Pt_TRUE, Ph_WM_HIDE);
    306     }
    307 
    308     PtSetResources(window, nargs, args);
    309     PtRealizeWidget(window);
    310     PtWindowToFront(window);
    311 
    312 #if 0 /* FIXME */
    313     PtGetResource(window, Pt_ARG_POS, &olddim, 0);
    314     fprintf(stderr, "POSITION: %d, %d\n", olddim->w, olddim->h);
    315 #endif
    316 
    317     return 0;
    318 }
    319 
    320 static const struct ColourMasks* ph_GetColourMasks(int bpp)
    321 {
    322     /* The alpha mask doesn't appears to be needed */
    323     static const struct ColourMasks phColorMasks[5] = {
    324         /*  8 bit      */  {0, 0, 0, 0, 8},
    325         /* 15 bit ARGB */  {0x7C00, 0x03E0, 0x001F, 0x8000, 15},
    326         /* 16 bit  RGB */  {0xF800, 0x07E0, 0x001F, 0x0000, 16},
    327         /* 24 bit  RGB */  {0xFF0000, 0x00FF00, 0x0000FF, 0x000000, 24},
    328         /* 32 bit ARGB */  {0x00FF0000, 0x0000FF00, 0x000000FF, 0xFF000000, 32},
    329     };
    330 
    331     switch (bpp)
    332     {
    333         case 8:
    334              return &phColorMasks[0];
    335         case 15:
    336              return &phColorMasks[1];
    337         case 16:
    338              return &phColorMasks[2];
    339         case 24:
    340              return &phColorMasks[3];
    341         case 32:
    342              return &phColorMasks[4];
    343     }
    344     return NULL;
    345 }
    346 
    347 static int ph_VideoInit(_THIS, SDL_PixelFormat* vformat)
    348 {
    349     PgHWCaps_t hwcaps;
    350     int i;
    351 
    352     window=NULL;
    353     desktoppal=SDLPH_PAL_NONE;
    354 
    355 #if SDL_VIDEO_OPENGL
    356     oglctx=NULL;
    357     oglbuffers=NULL;
    358     oglflags=0;
    359     oglbpp=0;
    360 #endif
    361 
    362     old_video_mode=-1;
    363     old_refresh_rate=-1;
    364 
    365     if (NULL == (phevent = SDL_malloc(EVENT_SIZE)))
    366     {
    367         SDL_OutOfMemory();
    368         return -1;
    369     }
    370     SDL_memset(phevent, 0x00, EVENT_SIZE);
    371 
    372     window = ph_CreateWindow(this);
    373     if (window == NULL)
    374     {
    375         SDL_SetError("ph_VideoInit(): Couldn't create video window !\n");
    376         return -1;
    377     }
    378 
    379     /* Create the blank cursor */
    380     SDL_BlankCursor = this->CreateWMCursor(this, blank_cdata, blank_cmask,
    381                                           (int)BLANK_CWIDTH, (int)BLANK_CHEIGHT,
    382                                           (int)BLANK_CHOTX, (int)BLANK_CHOTY);
    383 
    384     if (SDL_BlankCursor == NULL)
    385     {
    386         return -1;
    387     }
    388 
    389     if (PgGetGraphicsHWCaps(&hwcaps) < 0)
    390     {
    391         SDL_SetError("ph_VideoInit(): GetGraphicsHWCaps function failed !\n");
    392         this->FreeWMCursor(this, SDL_BlankCursor);
    393         return -1;
    394     }
    395 
    396     if (PgGetVideoModeInfo(hwcaps.current_video_mode, &desktop_mode) < 0)
    397     {
    398         SDL_SetError("ph_VideoInit(): PgGetVideoModeInfo function failed !\n");
    399         this->FreeWMCursor(this, SDL_BlankCursor);
    400         return -1;
    401     }
    402 
    403    /* Determine the current screen size */
    404    this->info.current_w = desktop_mode.width;
    405    this->info.current_h = desktop_mode.height;
    406 
    407     /* We need to return BytesPerPixel as it in used by CreateRGBsurface */
    408     vformat->BitsPerPixel = desktop_mode.bits_per_pixel;
    409     vformat->BytesPerPixel = desktop_mode.bytes_per_scanline/desktop_mode.width;
    410     desktopbpp = desktop_mode.bits_per_pixel;
    411 
    412     /* save current palette */
    413     if (desktopbpp==8)
    414     {
    415         PgGetPalette(savedpal);
    416         PgGetPalette(syspalph);
    417     }
    418     else
    419     {
    420         for(i=0; i<_Pg_MAX_PALETTE; i++)
    421         {
    422             savedpal[i]=PgRGB(0, 0, 0);
    423             syspalph[i]=PgRGB(0, 0, 0);
    424         }
    425     }
    426 
    427     currently_fullscreen = 0;
    428     currently_hided = 0;
    429     currently_maximized = 0;
    430     current_overlay = NULL;
    431 
    432     OCImage.direct_context = NULL;
    433     OCImage.offscreen_context = NULL;
    434     OCImage.offscreen_backcontext = NULL;
    435     OCImage.oldDC = NULL;
    436     OCImage.CurrentFrameData = NULL;
    437     OCImage.FrameData0 = NULL;
    438     OCImage.FrameData1 = NULL;
    439     videomode_emulatemode = 0;
    440 
    441     this->info.wm_available = 1;
    442 
    443     ph_UpdateHWInfo(this);
    444 
    445     return 0;
    446 }
    447 
    448 static SDL_Surface* ph_SetVideoMode(_THIS, SDL_Surface *current, int width, int height, int bpp, Uint32 flags)
    449 {
    450     const struct ColourMasks* mask;
    451 
    452     /* Lock the event thread, in multi-threading environments */
    453     SDL_Lock_EventThread();
    454 
    455     current->flags = flags;
    456 
    457     /* if we do not have desired fullscreen mode, then fallback into window mode */
    458     if (((current->flags & SDL_FULLSCREEN) == SDL_FULLSCREEN) && (ph_GetVideoMode(width, height, bpp)==0))
    459     {
    460        current->flags &= ~SDL_FULLSCREEN;
    461        current->flags &= ~SDL_NOFRAME;
    462        current->flags &= ~SDL_RESIZABLE;
    463     }
    464 
    465     ph_SetupWindow(this, width, height, current->flags);
    466 
    467     mask = ph_GetColourMasks(bpp);
    468     if (mask != NULL)
    469     {
    470         SDL_ReallocFormat(current, mask->bpp, mask->red, mask->green, mask->blue, 0);
    471     }
    472     else
    473     {
    474         SDL_SetError("ph_SetVideoMode(): desired bpp is not supported by photon !\n");
    475         return NULL;
    476     }
    477 
    478     if ((current->flags & SDL_OPENGL)==SDL_OPENGL)
    479     {
    480 #if !SDL_VIDEO_OPENGL
    481         /* if no built-in OpenGL support */
    482         SDL_SetError("ph_SetVideoMode(): no OpenGL support, you need to recompile SDL.\n");
    483         current->flags &= ~SDL_OPENGL;
    484         return NULL;
    485 #endif /* SDL_VIDEO_OPENGL */
    486     }
    487     else
    488     {
    489         /* Initialize internal variables */
    490         if ((current->flags & SDL_FULLSCREEN) == SDL_FULLSCREEN)
    491         {
    492             if (bpp==8)
    493             {
    494                desktoppal=SDLPH_PAL_SYSTEM;
    495             }
    496 
    497             current->flags &= ~SDL_RESIZABLE; /* no resize for Direct Context */
    498             current->flags |= SDL_HWSURFACE;
    499         }
    500         else
    501         {
    502             /* remove this if we'll have support for the non-fullscreen sw/hw+doublebuf one day */
    503             current->flags &= ~SDL_DOUBLEBUF;
    504 
    505             /* Use offscreen memory if SDL_HWSURFACE flag is set */
    506             if ((current->flags & SDL_HWSURFACE) == SDL_HWSURFACE)
    507             {
    508                 if (desktopbpp!=bpp)
    509                 {
    510                    current->flags &= ~SDL_HWSURFACE;
    511                 }
    512             }
    513 
    514             /* using palette emulation code in window mode */
    515             if (bpp==8)
    516             {
    517                 if (desktopbpp>=15)
    518                 {
    519                     desktoppal = SDLPH_PAL_EMULATE;
    520                 }
    521                 else
    522                 {
    523                     desktoppal = SDLPH_PAL_SYSTEM;
    524                 }
    525             }
    526             else
    527             {
    528                desktoppal = SDLPH_PAL_NONE;
    529             }
    530         }
    531     }
    532 
    533     current->w = width;
    534     current->h = height;
    535 
    536     if (desktoppal==SDLPH_PAL_SYSTEM)
    537     {
    538        current->flags|=SDL_HWPALETTE;
    539     }
    540 
    541     /* Must call at least once for setup image planes */
    542     if (ph_SetupUpdateFunction(this, current, current->flags)==-1)
    543     {
    544         /* Error string was filled in the ph_SetupUpdateFunction() */
    545         return NULL;
    546     }
    547 
    548     /* finish window drawing, if we are not in fullscreen, of course */
    549     if ((current->flags & SDL_FULLSCREEN) != SDL_FULLSCREEN)
    550     {
    551        PtFlush();
    552     }
    553     else
    554     {
    555        PgFlush();
    556     }
    557 
    558     visualbpp=bpp;
    559 
    560     ph_UpdateHWInfo(this);
    561 
    562     SDL_Unlock_EventThread();
    563 
    564     /* We've done! */
    565     return (current);
    566 }
    567 
    568 static void ph_VideoQuit(_THIS)
    569 {
    570     /* restore palette */
    571     if (desktopbpp==8)
    572     {
    573         PgSetPalette(syspalph, 0, -1, 0, 0, 0);
    574         PgSetPalette(savedpal, 0, 0, _Pg_MAX_PALETTE, Pg_PALSET_GLOBAL | Pg_PALSET_FORCE_EXPOSE, 0);
    575         PgFlush();
    576     }
    577 
    578     ph_DestroyImage(this, SDL_VideoSurface);
    579 
    580     if (window)
    581     {
    582         PtUnrealizeWidget(window);
    583         PtDestroyWidget(window);
    584         window=NULL;
    585     }
    586 
    587     if (phevent!=NULL)
    588     {
    589         SDL_free(phevent);
    590         phevent=NULL;
    591     }
    592 }
    593 
    594 static int ph_SetColors(_THIS, int firstcolor, int ncolors, SDL_Color *colors)
    595 {
    596     int i;
    597     SDL_Rect updaterect;
    598 
    599     updaterect.x = updaterect.y = 0;
    600     updaterect.w = this->screen->w;
    601     updaterect.h = this->screen->h;
    602 
    603     /* palette emulation code, using palette of the PhImage_t struct */
    604     if (desktoppal==SDLPH_PAL_EMULATE)
    605     {
    606         if ((SDL_Image) && (SDL_Image->palette))
    607         {
    608             for (i=firstcolor; i<firstcolor+ncolors; i++)
    609             {
    610                 syspalph[i] = PgRGB(colors[i-firstcolor].r, colors[i-firstcolor].g, colors[i-firstcolor].b);
    611                 SDL_Image->palette[i] = syspalph[i];
    612             }
    613 
    614             /* image needs to be redrawn */
    615             this->UpdateRects(this, 1, &updaterect);
    616         }
    617     }
    618     else
    619     {
    620         if (desktoppal==SDLPH_PAL_SYSTEM)
    621         {
    622             for (i=firstcolor; i<firstcolor+ncolors; i++)
    623             {
    624                 syspalph[i] = PgRGB(colors[i-firstcolor].r, colors[i-firstcolor].g, colors[i-firstcolor].b);
    625             }
    626 
    627             if ((this->screen->flags & SDL_FULLSCREEN) != SDL_FULLSCREEN)
    628             {
    629                  /* window mode must use soft palette */
    630                 PgSetPalette(&syspalph[firstcolor], 0, firstcolor, ncolors, Pg_PALSET_GLOBAL, 0);
    631                 /* image needs to be redrawn */
    632                 this->UpdateRects(this, 1, &updaterect);
    633             }
    634             else
    635             {
    636                 /* fullscreen mode must use hardware palette */
    637                 PgSetPalette(&syspalph[firstcolor], 0, firstcolor, ncolors, Pg_PALSET_GLOBAL, 0);
    638             }
    639         }
    640         else
    641         {
    642             /* SDLPH_PAL_NONE do nothing */
    643         }
    644     }
    645 
    646     return 1;
    647 }
    648 
    649