src/video/photon/SDL_phyuv.c
author Bob Pendleton <bob@pendleton.com>
Fri, 09 Jan 2009 20:43:30 +0000
changeset 3011 8f4ed5ec2b06
parent 2859 99210400e8b9
child 3013 8cc00819c8d6
permissions -rw-r--r--
I ran a global "make indent" it modified the following files.
     1 /*
     2     SDL - Simple DirectMedia Layer
     3     Copyright (C) 1997-2009 Sam Lantinga
     4 
     5     This library is free software; you can redistribute it and/or
     6     modify it under the terms of the GNU Lesser General Public
     7     License as published by the Free Software Foundation; either
     8     version 2.1 of the License, or (at your option) any later version.
     9 
    10     This library is distributed in the hope that it will be useful,
    11     but WITHOUT ANY WARRANTY; without even the implied warranty of
    12     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    13     Lesser General Public License for more details.
    14 
    15     You should have received a copy of the GNU Lesser General Public
    16     License along with this library; if not, write to the Free Software
    17     Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
    18 
    19     Sam Lantinga
    20     slouken@libsdl.org
    21 */
    22 #include "SDL_config.h"
    23 
    24 /* This is the QNX Realtime Platform version of SDL YUV video overlays */
    25 
    26 #include <errno.h>
    27 
    28 #include <Ph.h>
    29 #include <Pt.h>
    30 
    31 #include "SDL_video.h"
    32 #include "SDL_phyuv_c.h"
    33 #include "../SDL_yuvfuncs.h"
    34 
    35 #define OVERLAY_STATE_UNINIT 0
    36 #define OVERLAY_STATE_ACTIVE 1
    37 
    38 /* The functions are used to manipulate software video overlays */
    39 static struct private_yuvhwfuncs ph_yuvfuncs = {
    40     ph_LockYUVOverlay,
    41     ph_UnlockYUVOverlay,
    42     ph_DisplayYUVOverlay,
    43     ph_FreeYUVOverlay
    44 };
    45 
    46 int
    47 grab_ptrs2(PgVideoChannel_t * channel, FRAMEDATA * Frame0, FRAMEDATA * Frame1)
    48 {
    49     int planes = 0;
    50 
    51     /* Buffers have moved; re-obtain the pointers */
    52     Frame0->Y = (unsigned char *) PdGetOffscreenContextPtr(channel->yplane1);
    53     Frame1->Y = (unsigned char *) PdGetOffscreenContextPtr(channel->yplane2);
    54     Frame0->U = (unsigned char *) PdGetOffscreenContextPtr(channel->vplane1);
    55     Frame1->U = (unsigned char *) PdGetOffscreenContextPtr(channel->vplane2);
    56     Frame0->V = (unsigned char *) PdGetOffscreenContextPtr(channel->uplane1);
    57     Frame1->V = (unsigned char *) PdGetOffscreenContextPtr(channel->uplane2);
    58 
    59     if (Frame0->Y)
    60         planes++;
    61 
    62     if (Frame0->U)
    63         planes++;
    64 
    65     if (Frame0->V)
    66         planes++;
    67 
    68     return planes;
    69 }
    70 
    71 SDL_Overlay *
    72 ph_CreateYUVOverlay(_THIS, int width, int height, Uint32 format,
    73                     SDL_Surface * display)
    74 {
    75     SDL_Overlay *overlay;
    76     struct private_yuvhwdata *hwdata;
    77     int vidport;
    78     int rtncode;
    79     int planes;
    80     int i = 0;
    81     PhPoint_t pos;
    82 
    83     /* Create the overlay structure */
    84     overlay = SDL_calloc(1, sizeof(SDL_Overlay));
    85 
    86     if (overlay == NULL) {
    87         SDL_OutOfMemory();
    88         return NULL;
    89     }
    90 
    91     /* Fill in the basic members */
    92     overlay->format = format;
    93     overlay->w = width;
    94     overlay->h = height;
    95     overlay->hwdata = NULL;
    96 
    97     /* Set up the YUV surface function structure */
    98     overlay->hwfuncs = &ph_yuvfuncs;
    99 
   100     /* Create the pixel data and lookup tables */
   101     hwdata = SDL_calloc(1, sizeof(struct private_yuvhwdata));
   102 
   103     if (hwdata == NULL) {
   104         SDL_OutOfMemory();
   105         SDL_FreeYUVOverlay(overlay);
   106         return NULL;
   107     }
   108 
   109     overlay->hwdata = hwdata;
   110 
   111     PhDCSetCurrent(0);
   112     if (overlay->hwdata->channel == NULL) {
   113         if ((overlay->hwdata->channel =
   114              PgCreateVideoChannel(Pg_VIDEO_CHANNEL_SCALER, 0)) == NULL) {
   115             SDL_SetError
   116                 ("ph_CreateYUVOverlay(): Create channel failed: %s\n",
   117                  strerror(errno));
   118             SDL_FreeYUVOverlay(overlay);
   119             return NULL;
   120 
   121         }
   122     }
   123 
   124     overlay->hwdata->forcedredraw = 0;
   125 
   126     PtGetAbsPosition(window, &pos.x, &pos.y);
   127     overlay->hwdata->CurrentWindowPos.x = pos.x;
   128     overlay->hwdata->CurrentWindowPos.y = pos.y;
   129     overlay->hwdata->CurrentViewPort.pos.x = 0;
   130     overlay->hwdata->CurrentViewPort.pos.y = 0;
   131     overlay->hwdata->CurrentViewPort.size.w = width;
   132     overlay->hwdata->CurrentViewPort.size.h = height;
   133     overlay->hwdata->State = OVERLAY_STATE_UNINIT;
   134     overlay->hwdata->FrameData0 =
   135         (FRAMEDATA *) SDL_calloc(1, sizeof(FRAMEDATA));
   136     overlay->hwdata->FrameData1 =
   137         (FRAMEDATA *) SDL_calloc(1, sizeof(FRAMEDATA));
   138 
   139     vidport = -1;
   140     i = 0;
   141 
   142     overlay->hwdata->ischromakey = 0;
   143 
   144     do {
   145         SDL_memset(&overlay->hwdata->caps, 0x00, sizeof(PgScalerCaps_t));
   146         overlay->hwdata->caps.size = sizeof(PgScalerCaps_t);
   147         rtncode =
   148             PgGetScalerCapabilities(overlay->hwdata->channel, i,
   149                                     &overlay->hwdata->caps);
   150         if (rtncode == 0) {
   151             if (overlay->hwdata->caps.format == format) {
   152                 if ((overlay->hwdata->caps.
   153                      flags & Pg_SCALER_CAP_DST_CHROMA_KEY) ==
   154                     Pg_SCALER_CAP_DST_CHROMA_KEY) {
   155                     overlay->hwdata->ischromakey = 1;
   156                 }
   157                 vidport = 1;
   158                 break;
   159             }
   160         } else {
   161             break;
   162         }
   163         i++;
   164     } while (1);
   165 
   166 
   167     if (vidport == -1) {
   168         SDL_SetError("No available video ports for requested format\n");
   169         SDL_FreeYUVOverlay(overlay);
   170         return NULL;
   171     }
   172 
   173     overlay->hwdata->format = format;
   174     overlay->hwdata->props.format = format;
   175     overlay->hwdata->props.size = sizeof(PgScalerProps_t);
   176     overlay->hwdata->props.src_dim.w = width;
   177     overlay->hwdata->props.src_dim.h = height;
   178 
   179     /* overlay->hwdata->chromakey = PgGetOverlayChromaColor(); */
   180     overlay->hwdata->chromakey = PgRGB(12, 6, 12);      /* very dark pink color */
   181     overlay->hwdata->props.color_key = overlay->hwdata->chromakey;
   182 
   183     PhAreaToRect(&overlay->hwdata->CurrentViewPort,
   184                  &overlay->hwdata->props.viewport);
   185 
   186     overlay->hwdata->props.flags = Pg_SCALER_PROP_DOUBLE_BUFFER;
   187 
   188     if ((overlay->hwdata->ischromakey) && (overlay->hwdata->chromakey)) {
   189         overlay->hwdata->props.flags |= Pg_SCALER_PROP_CHROMA_ENABLE;
   190         overlay->hwdata->props.flags |=
   191             Pg_SCALER_PROP_CHROMA_SPECIFY_KEY_MASK;
   192     } else {
   193         overlay->hwdata->props.flags &= ~Pg_SCALER_PROP_CHROMA_ENABLE;
   194     }
   195 
   196     rtncode =
   197         PgConfigScalerChannel(overlay->hwdata->channel,
   198                               &overlay->hwdata->props);
   199 
   200     switch (rtncode) {
   201     case -1:
   202         SDL_SetError("PgConfigScalerChannel failed\n");
   203         SDL_FreeYUVOverlay(overlay);
   204         return NULL;
   205     case 1:
   206     case 0:
   207     default:
   208         break;
   209     }
   210 
   211     planes =
   212         grab_ptrs2(overlay->hwdata->channel, overlay->hwdata->FrameData0,
   213                    overlay->hwdata->FrameData1);
   214 
   215     if (overlay->hwdata->channel->yplane1 != NULL)
   216         overlay->hwdata->YStride = overlay->hwdata->channel->yplane1->pitch;
   217     if (overlay->hwdata->channel->vplane1 != NULL)
   218         overlay->hwdata->UStride = overlay->hwdata->channel->vplane1->pitch;
   219     if (overlay->hwdata->channel->uplane1 != NULL)
   220         overlay->hwdata->VStride = overlay->hwdata->channel->uplane1->pitch;
   221 
   222     /* check for the validness of all planes */
   223     if ((overlay->hwdata->channel->yplane1 == NULL) &&
   224         (overlay->hwdata->channel->uplane1 == NULL) &&
   225         (overlay->hwdata->channel->vplane1 == NULL)) {
   226         SDL_FreeYUVOverlay(overlay);
   227         SDL_SetError("PgConfigScaler() returns all planes equal NULL\n");
   228         return NULL;
   229     }
   230 /*
   231     overlay->hwdata->current = PgNextVideoFrame(overlay->hwdata->channel);
   232 
   233     if (overlay->hwdata->current==0)
   234     {
   235         overlay->hwdata->CurrentFrameData = overlay->hwdata->FrameData0;
   236     }
   237     else
   238     {
   239         overlay->hwdata->CurrentFrameData = overlay->hwdata->FrameData1;
   240     }
   241 */
   242     overlay->hwdata->CurrentFrameData = overlay->hwdata->FrameData0;
   243 
   244 /*
   245     overlay->hwdata->locked = 1;
   246 */
   247 
   248     /* Find the pitch and offset values for the overlay */
   249     overlay->planes = planes;
   250     overlay->pitches = SDL_calloc(overlay->planes, sizeof(Uint16));
   251     overlay->pixels = SDL_calloc(overlay->planes, sizeof(Uint8 *));
   252     if (!overlay->pitches || !overlay->pixels) {
   253         SDL_OutOfMemory();
   254         SDL_FreeYUVOverlay(overlay);
   255         return (NULL);
   256     }
   257 
   258     if (overlay->planes > 0) {
   259         overlay->pitches[0] = overlay->hwdata->channel->yplane1->pitch;
   260         overlay->pixels[0] = overlay->hwdata->CurrentFrameData->Y;
   261     }
   262     if (overlay->planes > 1) {
   263         overlay->pitches[1] = overlay->hwdata->channel->vplane1->pitch;
   264         overlay->pixels[1] = overlay->hwdata->CurrentFrameData->U;
   265     }
   266     if (overlay->planes > 2) {
   267         overlay->pitches[2] = overlay->hwdata->channel->uplane1->pitch;
   268         overlay->pixels[2] = overlay->hwdata->CurrentFrameData->V;
   269     }
   270 
   271     overlay->hwdata->State = OVERLAY_STATE_ACTIVE;
   272     overlay->hwdata->scaler_on = 0;
   273     overlay->hw_overlay = 1;
   274 
   275     current_overlay = overlay;
   276 
   277     return overlay;
   278 }
   279 
   280 int
   281 ph_LockYUVOverlay(_THIS, SDL_Overlay * overlay)
   282 {
   283     if (overlay == NULL) {
   284         return -1;
   285     }
   286 
   287     overlay->hwdata->locked = 1;
   288 
   289 /*  overlay->hwdata->current = PgNextVideoFrame(overlay->hwdata->channel);
   290     if (overlay->hwdata->current == -1)
   291     {
   292         SDL_SetError("ph_LockYUVOverlay: PgNextFrame() failed, bailing out\n");
   293         SDL_FreeYUVOverlay(overlay);
   294         return 0;
   295     }
   296 
   297     if (overlay->hwdata->current == 0)
   298     {
   299         overlay->hwdata->CurrentFrameData = overlay->hwdata->FrameData0;
   300     }
   301     else
   302     {
   303         overlay->hwdata->CurrentFrameData = overlay->hwdata->FrameData1;
   304     }
   305 
   306     if (overlay->planes > 0)
   307     {
   308         overlay->pitches[0] = overlay->hwdata->channel->yplane1->pitch;
   309         overlay->pixels[0]  = overlay->hwdata->CurrentFrameData->Y;
   310     }
   311     if (overlay->planes > 1)
   312     {
   313         overlay->pitches[1] = overlay->hwdata->channel->uplane1->pitch;
   314         overlay->pixels[1]  = overlay->hwdata->CurrentFrameData->U;
   315     }
   316     if (overlay->planes > 2)
   317     {
   318         overlay->pitches[2] = overlay->hwdata->channel->vplane1->pitch;
   319         overlay->pixels[2]  = overlay->hwdata->CurrentFrameData->V;
   320     }
   321 */
   322 
   323     return (0);
   324 }
   325 
   326 void
   327 ph_UnlockYUVOverlay(_THIS, SDL_Overlay * overlay)
   328 {
   329     if (overlay == NULL) {
   330         return;
   331     }
   332 
   333     overlay->hwdata->locked = 0;
   334 }
   335 
   336 int
   337 ph_DisplayYUVOverlay(_THIS, SDL_Overlay * overlay, SDL_Rect * src,
   338                      SDL_Rect * dst)
   339 {
   340     int rtncode;
   341     PhPoint_t pos;
   342     SDL_Rect backrect;
   343     PhRect_t windowextent;
   344     int winchanged = 0;
   345 
   346     if ((overlay == NULL) || (overlay->hwdata == NULL)) {
   347         return -1;
   348     }
   349 
   350     if (overlay->hwdata->State == OVERLAY_STATE_UNINIT) {
   351         return -1;
   352     }
   353 
   354     PtGetAbsPosition(window, &pos.x, &pos.y);
   355     if ((pos.x != overlay->hwdata->CurrentWindowPos.x) ||
   356         (pos.y != overlay->hwdata->CurrentWindowPos.y)) {
   357         winchanged = 1;
   358         overlay->hwdata->CurrentWindowPos.x = pos.x;
   359         overlay->hwdata->CurrentWindowPos.y = pos.y;
   360     }
   361 
   362     /* If CurrentViewPort position/size has been changed, then move/resize the viewport */
   363     if ((overlay->hwdata->CurrentViewPort.pos.x != dst->x) ||
   364         (overlay->hwdata->CurrentViewPort.pos.y != dst->y) ||
   365         (overlay->hwdata->CurrentViewPort.size.w != dst->w) ||
   366         (overlay->hwdata->CurrentViewPort.size.h != dst->h) ||
   367         (overlay->hwdata->scaler_on == 0) || (winchanged == 1) ||
   368         (overlay->hwdata->forcedredraw == 1)) {
   369 
   370         if (overlay->hwdata->ischromakey == 1) {
   371             /* restore screen behind the overlay/chroma color. */
   372             backrect.x = overlay->hwdata->CurrentViewPort.pos.x;
   373             backrect.y = overlay->hwdata->CurrentViewPort.pos.y;
   374             backrect.w = overlay->hwdata->CurrentViewPort.size.w;
   375             backrect.h = overlay->hwdata->CurrentViewPort.size.h;
   376             this->UpdateRects(this, 1, &backrect);
   377 
   378             /* Draw the new rectangle of the chroma color at the viewport position */
   379             PgSetFillColor(overlay->hwdata->chromakey);
   380             PgDrawIRect(dst->x, dst->y, dst->x + dst->w - 1,
   381                         dst->y + dst->h - 1, Pg_DRAW_FILL);
   382             PgFlush();
   383         }
   384 
   385         overlay->hwdata->props.flags |= Pg_SCALER_PROP_SCALER_ENABLE;
   386         overlay->hwdata->scaler_on = 1;
   387 
   388         PhWindowQueryVisible(Ph_QUERY_CONSOLE, 0, PtWidgetRid(window),
   389                              &windowextent);
   390         overlay->hwdata->CurrentViewPort.pos.x =
   391             pos.x - windowextent.ul.x + dst->x;
   392         overlay->hwdata->CurrentViewPort.pos.y =
   393             pos.y - windowextent.ul.y + dst->y;
   394         overlay->hwdata->CurrentViewPort.size.w = dst->w;
   395         overlay->hwdata->CurrentViewPort.size.h = dst->h;
   396         PhAreaToRect(&overlay->hwdata->CurrentViewPort,
   397                      &overlay->hwdata->props.viewport);
   398         overlay->hwdata->CurrentViewPort.pos.x = dst->x;
   399         overlay->hwdata->CurrentViewPort.pos.y = dst->y;
   400 
   401         rtncode =
   402             PgConfigScalerChannel(overlay->hwdata->channel,
   403                                   &(overlay->hwdata->props));
   404 
   405         switch (rtncode) {
   406         case -1:
   407             SDL_SetError("PgConfigScalerChannel() function failed\n");
   408             SDL_FreeYUVOverlay(overlay);
   409             return -1;
   410         case 1:
   411             grab_ptrs2(overlay->hwdata->channel,
   412                        overlay->hwdata->FrameData0,
   413                        overlay->hwdata->FrameData1);
   414             break;
   415         case 0:
   416         default:
   417             break;
   418         }
   419     }
   420 
   421 
   422 /*
   423     if (overlay->hwdata->locked==0)
   424     {
   425         overlay->hwdata->current = PgNextVideoFrame(overlay->hwdata->channel);
   426         if (overlay->hwdata->current == -1)
   427         {
   428             SDL_SetError("ph_LockYUVOverlay: PgNextFrame() failed, bailing out\n");
   429             SDL_FreeYUVOverlay(overlay);
   430             return 0;
   431         }
   432 
   433         if (overlay->hwdata->current == 0)
   434         {
   435             overlay->hwdata->CurrentFrameData = overlay->hwdata->FrameData0;
   436         }
   437         else
   438         {
   439             overlay->hwdata->CurrentFrameData = overlay->hwdata->FrameData1;
   440         }
   441 
   442         if (overlay->planes > 0)
   443         {
   444             overlay->pitches[0] = overlay->hwdata->channel->yplane1->pitch;
   445             overlay->pixels[0]  = overlay->hwdata->CurrentFrameData->Y;
   446         }
   447         if (overlay->planes > 1)
   448         {
   449             overlay->pitches[1] = overlay->hwdata->channel->uplane1->pitch;
   450             overlay->pixels[1]  = overlay->hwdata->CurrentFrameData->U;
   451         }
   452         if (overlay->planes > 2)
   453         {
   454             overlay->pitches[2] = overlay->hwdata->channel->vplane1->pitch;
   455             overlay->pixels[2]  = overlay->hwdata->CurrentFrameData->V;
   456         }
   457     }
   458 */
   459 
   460     return 0;
   461 }
   462 
   463 void
   464 ph_FreeYUVOverlay(_THIS, SDL_Overlay * overlay)
   465 {
   466     SDL_Rect backrect;
   467 
   468     if (overlay == NULL) {
   469         return;
   470     }
   471 
   472     if (overlay->hwdata == NULL) {
   473         return;
   474     }
   475 
   476     current_overlay = NULL;
   477 
   478     /* restore screen behind the overlay/chroma color. */
   479     backrect.x = overlay->hwdata->CurrentViewPort.pos.x;
   480     backrect.y = overlay->hwdata->CurrentViewPort.pos.y;
   481     backrect.w = overlay->hwdata->CurrentViewPort.size.w;
   482     backrect.h = overlay->hwdata->CurrentViewPort.size.h;
   483     this->UpdateRects(this, 1, &backrect);
   484 
   485     /* it is need for some buggy drivers, that can't hide overlay before */
   486     /* freeing buffer, so we got trash on the srceen                     */
   487     overlay->hwdata->props.flags &= ~Pg_SCALER_PROP_SCALER_ENABLE;
   488     PgConfigScalerChannel(overlay->hwdata->channel,
   489                           &(overlay->hwdata->props));
   490 
   491     overlay->hwdata->scaler_on = 0;
   492     overlay->hwdata->State = OVERLAY_STATE_UNINIT;
   493 
   494     if (overlay->hwdata->channel != NULL) {
   495         PgDestroyVideoChannel(overlay->hwdata->channel);
   496         overlay->hwdata->channel = NULL;
   497         return;
   498     }
   499 
   500     overlay->hwdata->CurrentFrameData = NULL;
   501 
   502     SDL_free(overlay->hwdata->FrameData0);
   503     SDL_free(overlay->hwdata->FrameData1);
   504     overlay->hwdata->FrameData0 = NULL;
   505     overlay->hwdata->FrameData1 = NULL;
   506     SDL_free(overlay->hwdata);
   507 }
   508 
   509 /* vi: set ts=4 sw=4 expandtab: */