SDL-1.2.14
[sdl_omap.git] / src / video / photon / SDL_ph_image.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 <Ph.h>
25 #include <photon/Pg.h>
26
27 #include "SDL_endian.h"
28 #include "SDL_video.h"
29 #include "../SDL_pixels_c.h"
30 #include "SDL_ph_video.h"
31 #include "SDL_ph_image_c.h"
32 #include "SDL_ph_modes_c.h"
33 #include "SDL_ph_gl.h"
34
35 int ph_SetupImage(_THIS, SDL_Surface *screen)
36 {
37     PgColor_t* palette=NULL;
38     int type=0;
39     int bpp;
40     
41     bpp=screen->format->BitsPerPixel;
42
43     /* Determine image type */
44     switch(bpp)
45     {
46         case 8:{
47             type = Pg_IMAGE_PALETTE_BYTE;
48         }
49         break;
50         case 15:{
51             type = Pg_IMAGE_DIRECT_555; 
52         }
53         break;
54         case 16:{
55             type = Pg_IMAGE_DIRECT_565; 
56         }
57         break;
58         case 24:{
59             type = Pg_IMAGE_DIRECT_888;
60         }
61         break;
62         case 32:{
63             type = Pg_IMAGE_DIRECT_8888;
64         }
65         break;
66         default:{
67             SDL_SetError("ph_SetupImage(): unsupported bpp=%d !\n", bpp);
68             return -1;
69         }
70         break;
71     }
72
73     /* palette emulation code */
74     if ((bpp==8) && (desktoppal==SDLPH_PAL_EMULATE))
75     {
76         /* creating image palette */
77         palette=SDL_malloc(_Pg_MAX_PALETTE*sizeof(PgColor_t));
78         if (palette==NULL)
79         {
80             SDL_SetError("ph_SetupImage(): can't allocate memory for palette !\n");
81             return -1;
82         }
83         PgGetPalette(palette);
84
85         /* using shared memory for speed (set last param to 1) */
86         if ((SDL_Image = PhCreateImage(NULL, screen->w, screen->h, type, palette, _Pg_MAX_PALETTE, 1)) == NULL)
87         {
88             SDL_SetError("ph_SetupImage(): PhCreateImage() failed for bpp=8 !\n");
89             SDL_free(palette);
90             return -1;
91         }
92     }
93     else
94     {
95         /* using shared memory for speed (set last param to 1) */
96         if ((SDL_Image = PhCreateImage(NULL, screen->w, screen->h, type, NULL, 0, 1)) == NULL)
97         {
98             SDL_SetError("ph_SetupImage(): PhCreateImage() failed for bpp=%d !\n", bpp);
99             return -1;
100         }
101     }
102
103     screen->pixels = SDL_Image->image;
104     screen->pitch = SDL_Image->bpl;
105
106     this->UpdateRects = ph_NormalUpdate;
107
108     return 0;
109 }
110
111 int ph_SetupOCImage(_THIS, SDL_Surface *screen)
112 {
113     int type = 0;
114     int bpp;
115
116     OCImage.flags = screen->flags;
117     
118     bpp=screen->format->BitsPerPixel;
119
120     /* Determine image type */
121     switch(bpp)
122     {
123         case 8: {
124                     type = Pg_IMAGE_PALETTE_BYTE;
125                 }
126                 break;
127         case 15:{
128                     type = Pg_IMAGE_DIRECT_555; 
129                 }
130                 break;
131         case 16:{
132                     type = Pg_IMAGE_DIRECT_565; 
133                 }
134                 break;
135         case 24:{
136                     type = Pg_IMAGE_DIRECT_888;
137                 }
138                 break;
139         case 32:{
140                     type = Pg_IMAGE_DIRECT_8888;
141                 }
142                 break;
143         default:{
144                     SDL_SetError("ph_SetupOCImage(): unsupported bpp=%d !\n", bpp);
145                     return -1;
146                 }
147                 break;
148     }
149
150     /* Currently offscreen contexts with the same bit depth as display bpp only can be created */
151     OCImage.offscreen_context = PdCreateOffscreenContext(0, screen->w, screen->h, Pg_OSC_MEM_PAGE_ALIGN);
152
153     if (OCImage.offscreen_context == NULL)
154     {
155         SDL_SetError("ph_SetupOCImage(): PdCreateOffscreenContext() function failed !\n");
156         return -1;
157     }
158
159     screen->pitch = OCImage.offscreen_context->pitch;
160
161     OCImage.dc_ptr = (unsigned char *)PdGetOffscreenContextPtr(OCImage.offscreen_context);
162
163     if (OCImage.dc_ptr == NULL)
164     {
165         SDL_SetError("ph_SetupOCImage(): PdGetOffscreenContextPtr function failed !\n");
166         PhDCRelease(OCImage.offscreen_context);
167         return -1;
168     }
169
170     OCImage.FrameData0 = OCImage.dc_ptr;
171     OCImage.CurrentFrameData = OCImage.FrameData0;
172     OCImage.current = 0;
173
174     PhDCSetCurrent(OCImage.offscreen_context);
175
176     screen->pixels = OCImage.CurrentFrameData;
177
178     this->UpdateRects = ph_OCUpdate;
179
180     return 0;
181 }
182
183 int ph_SetupFullScreenImage(_THIS, SDL_Surface* screen)
184 {
185     OCImage.flags = screen->flags;
186
187     /* Begin direct and fullscreen mode */
188     if (!ph_EnterFullScreen(this, screen, PH_ENTER_DIRECTMODE))
189     {
190         return -1;
191     }
192
193     /* store palette for fullscreen */
194     if ((screen->format->BitsPerPixel==8) && (desktopbpp!=8))
195     {
196         PgGetPalette(savedpal);
197         PgGetPalette(syspalph);
198     }
199
200     OCImage.offscreen_context = PdCreateOffscreenContext(0, 0, 0, Pg_OSC_MAIN_DISPLAY | Pg_OSC_MEM_PAGE_ALIGN | Pg_OSC_CRTC_SAFE);
201     if (OCImage.offscreen_context == NULL)
202     {
203         SDL_SetError("ph_SetupFullScreenImage(): PdCreateOffscreenContext() function failed !\n");
204         return -1;
205     }
206     
207     if ((screen->flags & SDL_DOUBLEBUF) == SDL_DOUBLEBUF)
208     {
209         OCImage.offscreen_backcontext = PdDupOffscreenContext(OCImage.offscreen_context, Pg_OSC_MEM_PAGE_ALIGN | Pg_OSC_CRTC_SAFE);
210         if (OCImage.offscreen_backcontext == NULL)
211         {
212             SDL_SetError("ph_SetupFullScreenImage(): PdCreateOffscreenContext(back) function failed !\n");
213             return -1;
214         }
215     }
216
217     OCImage.FrameData0 = (unsigned char *)PdGetOffscreenContextPtr(OCImage.offscreen_context);
218     if (OCImage.FrameData0 == NULL)
219     {
220         SDL_SetError("ph_SetupFullScreenImage(): PdGetOffscreenContextPtr() function failed !\n");
221         ph_DestroyImage(this, screen);
222         return -1;
223     }
224
225     if ((screen->flags & SDL_DOUBLEBUF) == SDL_DOUBLEBUF)
226     {
227         OCImage.FrameData1 = (unsigned char *)PdGetOffscreenContextPtr(OCImage.offscreen_backcontext);
228         if (OCImage.FrameData1 == NULL)
229         {
230             SDL_SetError("ph_SetupFullScreenImage(back): PdGetOffscreenContextPtr() function failed !\n");
231             ph_DestroyImage(this, screen);
232             return -1;
233         }
234     }
235
236     /* wait for the hardware */
237     PgFlush();
238     PgWaitHWIdle();
239
240     if ((screen->flags & SDL_DOUBLEBUF) == SDL_DOUBLEBUF)
241     {
242         OCImage.current = 0;
243         PhDCSetCurrent(OCImage.offscreen_context);
244         screen->pitch = OCImage.offscreen_context->pitch;
245         screen->pixels = OCImage.FrameData0;
246         
247         /* emulate 640x400 videomode */
248         if (videomode_emulatemode==1)
249         {
250            int i;
251            
252            for (i=0; i<40; i++)
253            {
254               SDL_memset(screen->pixels+screen->pitch*i, 0x00, screen->pitch);
255            }
256            for (i=440; i<480; i++)
257            {
258               SDL_memset(screen->pixels+screen->pitch*i, 0x00, screen->pitch);
259            }
260            screen->pixels+=screen->pitch*40;
261         }
262         PgSwapDisplay(OCImage.offscreen_backcontext, 0);
263     }
264     else
265     {
266         OCImage.current = 0;
267         PhDCSetCurrent(OCImage.offscreen_context);
268         screen->pitch = OCImage.offscreen_context->pitch;
269         screen->pixels = OCImage.FrameData0;
270
271         /* emulate 640x400 videomode */
272         if (videomode_emulatemode==1)
273         {
274            int i;
275            
276            for (i=0; i<40; i++)
277            {
278               SDL_memset(screen->pixels+screen->pitch*i, 0x00, screen->pitch);
279            }
280            for (i=440; i<480; i++)
281            {
282               SDL_memset(screen->pixels+screen->pitch*i, 0x00, screen->pitch);
283            }
284            screen->pixels+=screen->pitch*40;
285         }
286     }
287
288     this->UpdateRects = ph_OCDCUpdate;
289
290     /* wait for the hardware */
291     PgFlush();
292     PgWaitHWIdle();
293
294     return 0;
295 }
296
297 #if SDL_VIDEO_OPENGL
298
299 int ph_SetupOpenGLImage(_THIS, SDL_Surface* screen)
300 {
301     this->UpdateRects = ph_OpenGLUpdate;
302     screen->pixels=NULL;
303     screen->pitch=NULL;
304
305     #if (_NTO_VERSION >= 630)
306         if ((screen->flags & SDL_FULLSCREEN) == SDL_FULLSCREEN)
307         {
308             if (!ph_EnterFullScreen(this, screen, PH_IGNORE_DIRECTMODE))
309             {
310                 screen->flags &= ~SDL_FULLSCREEN;
311                 return -1;
312             }
313         }
314     #endif /* 6.3.0 */
315
316     if (ph_SetupOpenGLContext(this, screen->w, screen->h, screen->format->BitsPerPixel, screen->flags)!=0)
317     {
318         screen->flags &= ~SDL_OPENGL;
319         return -1;
320     }
321    
322     return 0;
323 }
324
325 #endif /* SDL_VIDEO_OPENGL */
326
327 void ph_DestroyImage(_THIS, SDL_Surface* screen)
328 {
329
330 #if SDL_VIDEO_OPENGL
331     if ((screen->flags & SDL_OPENGL)==SDL_OPENGL)
332     {
333         if (oglctx)
334         {
335             #if (_NTO_VERSION < 630)
336                 PhDCSetCurrent(NULL);
337                 PhDCRelease(oglctx);
338             #else
339                 qnxgl_context_destroy(oglctx);
340                 qnxgl_buffers_destroy(oglbuffers);
341                 qnxgl_finish();
342             #endif /* 6.3.0 */
343             oglctx=NULL;
344             oglbuffers=NULL;
345             oglflags=0;
346             oglbpp=0;
347         }
348
349         #if (_NTO_VERSION >= 630)
350             if (currently_fullscreen)
351             {
352                 ph_LeaveFullScreen(this);
353             }
354         #endif /* 6.3.0 */
355
356         return;
357     }
358 #endif /* SDL_VIDEO_OPENGL */
359
360     if (currently_fullscreen)
361     {
362         /* if we right now in 8bpp fullscreen we must release palette */
363         if ((screen->format->BitsPerPixel==8) && (desktopbpp!=8))
364         {
365             PgSetPalette(syspalph, 0, -1, 0, 0, 0);
366             PgSetPalette(savedpal, 0, 0, _Pg_MAX_PALETTE, Pg_PALSET_GLOBAL | Pg_PALSET_FORCE_EXPOSE, 0);
367             PgFlush();
368         }
369         ph_LeaveFullScreen(this);
370     }
371
372     if (OCImage.offscreen_context != NULL)
373     {
374         PhDCRelease(OCImage.offscreen_context);
375         OCImage.offscreen_context = NULL;
376         OCImage.FrameData0 = NULL;
377     }
378     if (OCImage.offscreen_backcontext != NULL)
379     {
380         PhDCRelease(OCImage.offscreen_backcontext);
381         OCImage.offscreen_backcontext = NULL;
382         OCImage.FrameData1 = NULL;
383     }
384     OCImage.CurrentFrameData = NULL;
385
386     if (SDL_Image)
387     {
388         /* if palette allocated, free it */
389         if (SDL_Image->palette)
390         {
391             SDL_free(SDL_Image->palette);
392         }
393         PgShmemDestroy(SDL_Image->image);
394         SDL_free(SDL_Image);
395     }
396
397     /* Must be zeroed everytime */
398     SDL_Image = NULL;
399
400     if (screen)
401     {
402         screen->pixels = NULL;
403     }
404 }
405
406 int ph_UpdateHWInfo(_THIS)
407 {
408     PgVideoModeInfo_t vmode;
409     PgHWCaps_t hwcaps;
410
411     /* Update video ram amount */
412     if (PgGetGraphicsHWCaps(&hwcaps) < 0)
413     {
414         SDL_SetError("ph_UpdateHWInfo(): GetGraphicsHWCaps() function failed !\n");
415         return -1;
416     }
417     this->info.video_mem=hwcaps.currently_available_video_ram/1024;
418
419     /* obtain current mode capabilities */
420     if (PgGetVideoModeInfo(hwcaps.current_video_mode, &vmode) < 0)
421     {
422         SDL_SetError("ph_UpdateHWInfo(): GetVideoModeInfo() function failed !\n");
423         return -1;
424     }
425
426     if ((vmode.mode_capabilities1 & PgVM_MODE_CAP1_OFFSCREEN) == PgVM_MODE_CAP1_OFFSCREEN)
427     {
428         /* this is a special test for drivers which tries to lie about offscreen capability */
429         if (hwcaps.currently_available_video_ram!=0)
430         {
431            this->info.hw_available = 1;
432         }
433         else
434         {
435            this->info.hw_available = 0;
436         }
437     }
438     else
439     {
440         this->info.hw_available = 0;
441     }
442
443     if ((vmode.mode_capabilities2 & PgVM_MODE_CAP2_RECTANGLE) == PgVM_MODE_CAP2_RECTANGLE)
444     {
445         this->info.blit_fill = 1;
446     }
447     else
448     {
449         this->info.blit_fill = 0;
450     }
451
452     if ((vmode.mode_capabilities2 & PgVM_MODE_CAP2_BITBLT) == PgVM_MODE_CAP2_BITBLT)
453     {
454         this->info.blit_hw = 1;
455     }
456     else
457     {
458         this->info.blit_hw = 0;
459     }
460
461     if ((vmode.mode_capabilities2 & PgVM_MODE_CAP2_ALPHA_BLEND) == PgVM_MODE_CAP2_ALPHA_BLEND)
462     {
463         this->info.blit_hw_A = 1;
464     }
465     else
466     {
467         this->info.blit_hw_A = 0;
468     }
469     
470     if ((vmode.mode_capabilities2 & PgVM_MODE_CAP2_CHROMA) == PgVM_MODE_CAP2_CHROMA)
471     {
472         this->info.blit_hw_CC = 1;
473     }
474     else
475     {
476         this->info.blit_hw_CC = 0;
477     }
478     
479     return 0;
480 }
481
482 int ph_SetupUpdateFunction(_THIS, SDL_Surface* screen, Uint32 flags)
483 {
484     int setupresult=-1;
485
486     ph_DestroyImage(this, screen);
487     
488 #if SDL_VIDEO_OPENGL
489     if ((flags & SDL_OPENGL)==SDL_OPENGL)
490     {
491         setupresult=ph_SetupOpenGLImage(this, screen);
492     }
493     else
494     {
495 #endif
496        if ((flags & SDL_FULLSCREEN)==SDL_FULLSCREEN)
497        {
498            setupresult=ph_SetupFullScreenImage(this, screen);
499        }
500        else
501        {
502           if ((flags & SDL_HWSURFACE)==SDL_HWSURFACE)
503           {
504               setupresult=ph_SetupOCImage(this, screen);
505           }
506           else
507           {
508               setupresult=ph_SetupImage(this, screen);
509           }
510        }
511 #if SDL_VIDEO_OPENGL
512     }
513 #endif
514     if (setupresult!=-1)
515     {
516        ph_UpdateHWInfo(this);
517     }
518     
519     return setupresult;
520 }
521
522 int ph_AllocHWSurface(_THIS, SDL_Surface* surface)
523 {
524     PgHWCaps_t hwcaps;
525
526     if (surface->hwdata!=NULL)
527     {
528        SDL_SetError("ph_AllocHWSurface(): hwdata already exists!\n");
529        return -1;
530     }
531     surface->hwdata=SDL_malloc(sizeof(struct private_hwdata));
532     SDL_memset(surface->hwdata, 0x00, sizeof(struct private_hwdata));
533     surface->hwdata->offscreenctx=PdCreateOffscreenContext(0, surface->w, surface->h, Pg_OSC_MEM_PAGE_ALIGN);
534     if (surface->hwdata->offscreenctx == NULL)
535     {
536         SDL_SetError("ph_AllocHWSurface(): PdCreateOffscreenContext() function failed !\n");
537         return -1;
538     }
539     surface->pixels=PdGetOffscreenContextPtr(surface->hwdata->offscreenctx);
540     if (surface->pixels==NULL)
541     {
542         PhDCRelease(surface->hwdata->offscreenctx);
543         SDL_SetError("ph_AllocHWSurface(): PdGetOffscreenContextPtr() function failed !\n");
544         return -1;
545     }
546     surface->pitch=surface->hwdata->offscreenctx->pitch;
547     surface->flags|=SDL_HWSURFACE;
548     surface->flags|=SDL_PREALLOC;
549     
550 #if 0 /* FIXME */
551     /* create simple offscreen lock */
552     surface->hwdata->crlockparam.flags=0;
553     if (PdCreateOffscreenLock(surface->hwdata->offscreenctx, &surface->hwdata->crlockparam)!=EOK)
554     {
555         PhDCRelease(surface->hwdata->offscreenctx);
556         SDL_SetError("ph_AllocHWSurface(): Can't create offscreen lock !\n");
557         return -1;
558     }
559 #endif /* 0 */
560
561     /* Update video ram amount */
562     if (PgGetGraphicsHWCaps(&hwcaps) < 0)
563     {
564         PdDestroyOffscreenLock(surface->hwdata->offscreenctx);
565         PhDCRelease(surface->hwdata->offscreenctx);
566         SDL_SetError("ph_AllocHWSurface(): GetGraphicsHWCaps() function failed !\n");
567         return -1;
568     }
569     this->info.video_mem=hwcaps.currently_available_video_ram/1024;
570
571     return 0;
572 }
573
574 void ph_FreeHWSurface(_THIS, SDL_Surface* surface)
575 {
576     PgHWCaps_t hwcaps;
577
578     if (surface->hwdata==NULL)
579     {
580        SDL_SetError("ph_FreeHWSurface(): no hwdata!\n");
581        return;
582     }
583     if (surface->hwdata->offscreenctx == NULL)
584     {
585        SDL_SetError("ph_FreeHWSurface(): no offscreen context to delete!\n");
586        return;
587     }
588
589 #if 0 /* FIXME */
590     /* unlock the offscreen context if it has been locked before destroy it */
591     if (PdIsOffscreenLocked(surface->hwdata->offscreenctx)==Pg_OSC_LOCKED)
592     {
593        PdUnlockOffscreen(surface->hwdata->offscreenctx);
594     }
595
596     PdDestroyOffscreenLock(surface->hwdata->offscreenctx);
597 #endif /* 0 */
598
599     PhDCRelease(surface->hwdata->offscreenctx);
600     
601     SDL_free(surface->hwdata);
602     surface->hwdata=NULL;
603
604     /* Update video ram amount */
605     if (PgGetGraphicsHWCaps(&hwcaps) < 0)
606     {
607         SDL_SetError("ph_FreeHWSurface(): GetGraphicsHWCaps() function failed !\n");
608         return;
609     }
610     this->info.video_mem=hwcaps.currently_available_video_ram/1024;
611
612     return;
613 }
614
615 int ph_CheckHWBlit(_THIS, SDL_Surface *src, SDL_Surface *dst)
616 {
617    if ((src->hwdata==NULL) && (src != this->screen))
618    {
619       SDL_SetError("ph_CheckHWBlit(): Source surface haven't hardware specific data.\n");
620       src->flags&=~SDL_HWACCEL;
621       return -1;
622    }
623    if ((src->flags & SDL_HWSURFACE) != SDL_HWSURFACE)
624    {
625       SDL_SetError("ph_CheckHWBlit(): Source surface isn't a hardware surface.\n");
626       src->flags&=~SDL_HWACCEL;
627       return -1;
628    }
629
630    if ((src->flags & SDL_SRCCOLORKEY) == SDL_SRCCOLORKEY)
631    {
632        if (this->info.blit_hw_CC!=1)
633        {
634            src->flags&=~SDL_HWACCEL;
635            src->map->hw_blit=NULL;
636            return -1;
637        }
638    }
639
640    if ((src->flags & SDL_SRCALPHA) == SDL_SRCALPHA)
641    {
642        if (this->info.blit_hw_A!=1)
643        {
644            src->flags&=~SDL_HWACCEL;
645            src->map->hw_blit=NULL;
646            return -1;
647        }
648    }
649
650    src->flags|=SDL_HWACCEL;
651    src->map->hw_blit = ph_HWAccelBlit;
652
653    return 1;
654 }
655
656 PgColor_t ph_ExpandColor(_THIS, SDL_Surface* surface, Uint32 color)
657 {
658     Uint32 truecolor;
659
660     /* Photon API accepts true colors only during hw filling operations */
661     switch(surface->format->BitsPerPixel)
662     {
663        case 8:
664             {
665                 if ((surface->format->palette) && (color<=surface->format->palette->ncolors))
666                 {
667                     truecolor=PgRGB(surface->format->palette->colors[color].r,
668                                     surface->format->palette->colors[color].g,
669                                     surface->format->palette->colors[color].b);
670                 }
671                 else
672                 {
673                     SDL_SetError("ph_ExpandColor(): Color out of range for the 8bpp mode !\n");
674                     return 0xFFFFFFFFUL;
675                 }
676             }
677             break;
678        case 15: 
679             {
680                 truecolor = ((color & 0x00007C00UL) << 9) |   /* R */
681                             ((color & 0x000003E0UL) << 6) |   /* G */
682                             ((color & 0x0000001FUL) << 3) |   /* B */
683                             ((color & 0x00007000UL) << 4) |   /* R compensation */
684                             ((color & 0x00000380UL) << 1) |   /* G compensation */
685                             ((color & 0x0000001CUL) >> 2);    /* B compensation */
686             }
687             break;
688        case 16: 
689             {
690                 truecolor = ((color & 0x0000F800UL) << 8) |   /* R */
691                             ((color & 0x000007E0UL) << 5) |   /* G */
692                             ((color & 0x0000001FUL) << 3) |   /* B */
693                             ((color & 0x0000E000UL) << 3) |   /* R compensation */
694                             ((color & 0x00000600UL) >> 1) |   /* G compensation */
695                             ((color & 0x0000001CUL) >> 2);    /* B compensation */
696
697             }
698             break;
699        case 24: 
700             {
701                 truecolor=color & 0x00FFFFFFUL;
702             }
703             break;
704        case 32: 
705             {
706                 truecolor=color;
707             }
708             break;
709        default:
710             {
711                 SDL_SetError("ph_ExpandColor(): Unsupported depth for the hardware operations !\n");
712                 return 0xFFFFFFFFUL;
713             }
714     }
715
716     return truecolor;
717 }
718
719 int ph_FillHWRect(_THIS, SDL_Surface* surface, SDL_Rect* rect, Uint32 color)
720 {
721     PgColor_t oldcolor;
722     Uint32 truecolor;
723     int ydisp=0;
724
725     if (this->info.blit_fill!=1)
726     {
727        return -1;
728     }
729
730     truecolor=ph_ExpandColor(this, surface, color);
731     if (truecolor==0xFFFFFFFFUL)
732     {
733         return -1;
734     }
735
736     oldcolor=PgSetFillColor(truecolor);
737
738     /* 640x400 videomode emulation */
739     if (videomode_emulatemode==1)
740     {
741         ydisp+=40;
742     }
743
744     PgDrawIRect(rect->x, rect->y+ydisp, rect->w+rect->x-1, rect->h+rect->y+ydisp-1, Pg_DRAW_FILL);
745     PgSetFillColor(oldcolor);
746     PgFlush();
747     PgWaitHWIdle();
748
749     return 0;
750 }
751
752 int ph_FlipHWSurface(_THIS, SDL_Surface* screen)
753 {
754     PhArea_t farea;
755
756     if ((screen->flags & SDL_FULLSCREEN) == SDL_FULLSCREEN)
757     {
758         /* flush all drawing ops before blitting */
759         PgFlush();
760         PgWaitHWIdle();
761
762         farea.pos.x=0;
763         farea.pos.y=0;
764         farea.size.w=screen->w;
765         farea.size.h=screen->h;
766
767         /* emulate 640x400 videomode */
768         if (videomode_emulatemode==1)
769         {
770             farea.pos.y+=40;
771         }
772
773         PgContextBlitArea(OCImage.offscreen_context, &farea, OCImage.offscreen_backcontext, &farea);
774
775         /* flush the blitting */
776         PgFlush();
777         PgWaitHWIdle();
778     }
779     return 0;
780 }
781
782 int ph_LockHWSurface(_THIS, SDL_Surface* surface)
783 {
784
785 #if 0 /* FIXME */
786     int lockresult;
787
788     if (surface->hwdata == NULL)
789     {
790         return;
791     }
792
793     surface->hwdata->lockparam.flags=0;
794     surface->hwdata->lockparam.time_out=NULL;
795     lockresult=PdLockOffscreen(surface->hwdata->offscreenctx, &surface->hwdata->lockparam);
796
797     switch (lockresult)
798     {
799        case EOK:
800                  break;
801        case Pg_OSC_LOCK_DEADLOCK: 
802                  SDL_SetError("ph_LockHWSurface(): Deadlock detected !\n");
803                  return -1;
804        case Pg_OSC_LOCK_INVALID:
805                  SDL_SetError("ph_LockHWSurface(): Lock invalid !\n");
806                  return -1;
807        default:
808                  SDL_SetError("ph_LockHWSurface(): Can't lock the surface !\n");
809                  return -1;
810     }
811 #endif /* 0 */
812
813     return 0;
814 }
815
816 void ph_UnlockHWSurface(_THIS, SDL_Surface* surface)
817 {
818
819 #if 0 /* FIXME */
820     int unlockresult;
821
822     if ((surface == NULL) || (surface->hwdata == NULL))
823     {
824         return;
825     }
826
827     if (PdIsOffscreenLocked(surface->hwdata->offscreenctx)==Pg_OSC_LOCKED)
828     {
829         unlockresult=PdUnlockOffscreen(surface->hwdata->offscreenctx);
830     }
831 #endif /* 0 */
832
833     return;
834 }
835
836 int ph_HWAccelBlit(SDL_Surface* src, SDL_Rect* srcrect, SDL_Surface* dst, SDL_Rect* dstrect)
837 {
838     SDL_VideoDevice* this=current_video;
839     PhArea_t srcarea;
840     PhArea_t dstarea;
841     int ydisp=0;
842
843     /* 640x400 videomode emulation */
844     if (videomode_emulatemode==1)
845     {
846        ydisp+=40;
847     }
848
849     srcarea.pos.x=srcrect->x;
850     srcarea.pos.y=srcrect->y;
851     srcarea.size.w=srcrect->w;
852     srcarea.size.h=srcrect->h;
853
854     dstarea.pos.x=dstrect->x;
855     dstarea.pos.y=dstrect->y;
856     dstarea.size.w=dstrect->w;
857     dstarea.size.h=dstrect->h;
858
859     if (((src == this->screen) || (src->hwdata!=NULL)) && ((dst == this->screen) || (dst->hwdata!=NULL)))
860     {
861         if ((src->flags & SDL_SRCCOLORKEY) == SDL_SRCCOLORKEY)
862         {
863             ph_SetHWColorKey(this, src, src->format->colorkey);
864             PgChromaOn();
865         }
866
867         if ((src->flags & SDL_SRCALPHA) == SDL_SRCALPHA)
868         {
869             ph_SetHWAlpha(this, src, src->format->alpha);
870             PgAlphaOn();
871         }
872
873         if (dst == this->screen)
874         {
875             if (src == this->screen)
876             {
877                 /* blitting from main screen to main screen */
878                 dstarea.pos.y+=ydisp;
879                 srcarea.pos.y+=ydisp;
880                 PgContextBlitArea(OCImage.offscreen_context, &srcarea, OCImage.offscreen_context, &dstarea);
881             }
882             else
883             {
884                 /* blitting from offscreen to main screen */
885                 dstarea.pos.y+=ydisp;
886                 PgContextBlitArea(src->hwdata->offscreenctx, &srcarea, OCImage.offscreen_context, &dstarea);
887             }
888         }
889         else
890         {
891             if (src == this->screen)
892             {
893                 /* blitting from main screen to offscreen */
894                 srcarea.pos.y+=ydisp;
895                 PgContextBlitArea(OCImage.offscreen_context, &srcarea, dst->hwdata->offscreenctx, &dstarea);
896             }
897             else
898             {
899                 /* blitting offscreen to offscreen */
900                 PgContextBlitArea(src->hwdata->offscreenctx, &srcarea, dst->hwdata->offscreenctx, &dstarea);
901             }
902         }
903
904         if ((src->flags & SDL_SRCALPHA) == SDL_SRCALPHA)
905         {
906             PgAlphaOff();
907         }
908
909         if ((src->flags & SDL_SRCCOLORKEY) == SDL_SRCCOLORKEY)
910         {
911             PgChromaOff();
912         }
913     }
914     else
915     {
916         SDL_SetError("ph_HWAccelBlit(): Source or target surface is not a hardware surface !\n");
917         return -1;
918     }
919
920     PgFlush();
921     PgWaitHWIdle();
922
923     return 0;
924 }
925
926 int ph_SetHWColorKey(_THIS, SDL_Surface *surface, Uint32 key)
927 {
928     if (this->info.blit_hw_CC!=1)
929     {
930        return -1;
931     }
932
933     if (surface->hwdata!=NULL)
934     {
935         surface->hwdata->colorkey=ph_ExpandColor(this, surface, key);
936         if (surface->hwdata->colorkey==0xFFFFFFFFUL)
937         {
938             return -1;
939         }
940     }
941     PgSetChroma(surface->hwdata->colorkey, Pg_CHROMA_SRC_MATCH | Pg_CHROMA_NODRAW);
942
943     return 0;
944 }
945
946 int ph_SetHWAlpha(_THIS, SDL_Surface* surface, Uint8 alpha)
947 {
948     if (this->info.blit_hw_A!=1)
949     {
950        return -1;
951     }
952
953     PgSetAlphaBlend(NULL, alpha);
954
955     return 0;
956 }
957
958 #if SDL_VIDEO_OPENGL
959 void ph_OpenGLUpdate(_THIS, int numrects, SDL_Rect* rects)
960 {
961    this->GL_SwapBuffers(this);
962    
963    return;
964 }
965 #endif /* SDL_VIDEO_OPENGL */
966
967 void ph_NormalUpdate(_THIS, int numrects, SDL_Rect *rects)
968 {
969     PhPoint_t ph_pos;
970     PhRect_t ph_rect;
971     int i;
972
973     for (i=0; i<numrects; ++i) 
974     {
975         if (rects[i].w==0) /* Clipped? dunno why but this occurs sometime. */
976         { 
977             continue;
978         }
979
980         if (rects[i].h==0) /* Clipped? dunno why but this occurs sometime. */
981         { 
982             continue;
983         }
984
985         ph_pos.x = rects[i].x;
986         ph_pos.y = rects[i].y;
987         ph_rect.ul.x = rects[i].x;
988         ph_rect.ul.y = rects[i].y;
989         ph_rect.lr.x = rects[i].x + rects[i].w;
990         ph_rect.lr.y = rects[i].y + rects[i].h;
991
992         if (PgDrawPhImageRectmx(&ph_pos, SDL_Image, &ph_rect, 0) < 0)
993         {
994             SDL_SetError("ph_NormalUpdate(): PgDrawPhImageRectmx failed!\n");
995             return;
996         }
997     }
998
999     if (PgFlush() < 0)
1000     {
1001         SDL_SetError("ph_NormalUpdate(): PgFlush() function failed!\n");
1002     }
1003 }
1004
1005 void ph_OCUpdate(_THIS, int numrects, SDL_Rect *rects)
1006 {
1007     int i;
1008
1009     PhPoint_t zero = {0, 0};
1010     PhArea_t src_rect;
1011     PhArea_t dest_rect;
1012
1013     PgSetTranslation(&zero, 0);
1014     PgSetRegion(PtWidgetRid(window));
1015     PgSetClipping(0, NULL);
1016
1017     PgFlush();
1018     PgWaitHWIdle();
1019
1020     for (i=0; i<numrects; ++i)
1021     {
1022         if (rects[i].w == 0)  /* Clipped? */
1023         {
1024             continue;
1025         }
1026
1027         if (rects[i].h == 0)  /* Clipped? */
1028         {
1029             continue;
1030         }
1031         
1032         src_rect.pos.x=rects[i].x;
1033         src_rect.pos.y=rects[i].y;
1034         dest_rect.pos.x=rects[i].x;
1035         dest_rect.pos.y=rects[i].y;
1036
1037         src_rect.size.w=rects[i].w;
1038         src_rect.size.h=rects[i].h;
1039         dest_rect.size.w=rects[i].w;
1040         dest_rect.size.h=rects[i].h;
1041         
1042         PgContextBlitArea(OCImage.offscreen_context, &src_rect, NULL, &dest_rect);
1043     }
1044
1045     if (PgFlush() < 0)
1046     {
1047         SDL_SetError("ph_OCUpdate(): PgFlush failed.\n");
1048     }
1049 }
1050
1051 void ph_OCDCUpdate(_THIS, int numrects, SDL_Rect *rects)
1052 {
1053     PgWaitHWIdle();
1054
1055     if (PgFlush() < 0)
1056     {
1057         SDL_SetError("ph_OCDCUpdate(): PgFlush failed.\n");
1058     }
1059 }