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