src/video/photon/SDL_ph_image.c
author Sam Lantinga <slouken@libsdl.org>
Sun, 28 May 2006 13:04:16 +0000
branchSDL-1.3
changeset 1662 782fd950bd46
parent 1658 e49147870aac
child 1668 4da1ee79c9af
permissions -rw-r--r--
Revamp of the video system in progress - adding support for multiple displays, multiple windows, and a full video mode selection API.

WARNING: None of the video drivers have been updated for the new API yet! The API is still under design and very fluid.

The code is now run through a consistent indent format:
indent -i4 -nut -nsc -br -ce

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