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@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
45static int  ph_VideoInit(_THIS, SDL_PixelFormat *vformat);
46static SDL_Surface *ph_SetVideoMode(_THIS, SDL_Surface *current, int width, int height, int bpp, Uint32 flags);
47static int  ph_SetColors(_THIS, int firstcolor, int ncolors, SDL_Color *colors);
48static void ph_VideoQuit(_THIS);
49static void ph_DeleteDevice(SDL_VideoDevice *device);
50
51static int phstatus=-1;
52
53static 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
70static 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
140VideoBootStrap ph_bootstrap = {
141    "photon", "QNX Photon video output",
142    ph_Available, ph_CreateDevice
143};
144
145static 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
164static PtWidget_t *ph_CreateWindow(_THIS)
165{
166    PtWidget_t *widget;
167
168    widget = PtCreateWidget(PtWindow, NULL, 0, NULL);
169
170    return widget;
171}
172
173static 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
320static 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
347static 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
448static 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
568static 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
594static 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