1/*
2    SDL - Simple DirectMedia Layer
3    Copyright (C) 1997-2006 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
35int 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
111int 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
183int 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
299int 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
327void 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
406int 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
482int 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
522int 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
574void 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
615int 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
656PgColor_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
719int 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
752int 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
782int 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
816void 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
836int 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
926int 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
946int 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
959void ph_OpenGLUpdate(_THIS, int numrects, SDL_Rect* rects)
960{
961   this->GL_SwapBuffers(this);
962
963   return;
964}
965#endif /* SDL_VIDEO_OPENGL */
966
967void 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
1005void 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
1051void 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}
1060