SDL-1.2.14
[sdl_omap.git] / src / video / photon / SDL_ph_video.c
1 /*
2     SDL - Simple DirectMedia Layer
3     Copyright (C) 1997-2009 Sam Lantinga
4
5     This library is free software; you can redistribute it and/or
6     modify it under the terms of the GNU Lesser General Public
7     License as published by the Free Software Foundation; either
8     version 2.1 of the License, or (at your option) any later version.
9
10     This library is distributed in the hope that it will be useful,
11     but WITHOUT ANY WARRANTY; without even the implied warranty of
12     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13     Lesser General Public License for more details.
14
15     You should have received a copy of the GNU Lesser General Public
16     License along with this library; if not, write to the Free Software
17     Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
18
19     Sam Lantinga
20     slouken@libsdl.org
21 */
22 #include "SDL_config.h"
23
24 #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