symbian-qemu-0.9.1-12/libsdl-trunk/src/video/photon/SDL_phyuv.c
changeset 1 2fb8b9db1c86
equal deleted inserted replaced
0:ffa851df0825 1:2fb8b9db1c86
       
     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 /* 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 {
       
    41     ph_LockYUVOverlay,
       
    42     ph_UnlockYUVOverlay,
       
    43     ph_DisplayYUVOverlay,
       
    44     ph_FreeYUVOverlay
       
    45 };
       
    46 
       
    47 int 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* ph_CreateYUVOverlay(_THIS, int width, int height, Uint32 format, SDL_Surface* display)
       
    72 {
       
    73     SDL_Overlay* overlay;
       
    74     struct private_yuvhwdata* hwdata;
       
    75     int vidport;
       
    76     int rtncode;
       
    77     int planes;
       
    78     int i=0;
       
    79     PhPoint_t pos;
       
    80 
       
    81     /* Create the overlay structure */
       
    82     overlay = SDL_calloc(1, sizeof(SDL_Overlay));
       
    83 
       
    84     if (overlay == NULL)
       
    85     {
       
    86         SDL_OutOfMemory();
       
    87         return NULL;
       
    88     }
       
    89 
       
    90     /* Fill in the basic members */
       
    91     overlay->format = format;
       
    92     overlay->w = width;
       
    93     overlay->h = height;
       
    94     overlay->hwdata = NULL;
       
    95 	
       
    96     /* Set up the YUV surface function structure */
       
    97     overlay->hwfuncs = &ph_yuvfuncs;
       
    98 
       
    99     /* Create the pixel data and lookup tables */
       
   100     hwdata = SDL_calloc(1, sizeof(struct private_yuvhwdata));
       
   101 
       
   102     if (hwdata == NULL)
       
   103     {
       
   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     {
       
   114         if ((overlay->hwdata->channel = PgCreateVideoChannel(Pg_VIDEO_CHANNEL_SCALER, 0)) == NULL)
       
   115         {
       
   116             SDL_SetError("ph_CreateYUVOverlay(): Create channel failed: %s\n", strerror(errno));
       
   117             SDL_FreeYUVOverlay(overlay);
       
   118             return NULL;
       
   119 
       
   120         }
       
   121     }
       
   122 
       
   123     overlay->hwdata->forcedredraw=0;
       
   124 
       
   125     PtGetAbsPosition(window, &pos.x, &pos.y);
       
   126     overlay->hwdata->CurrentWindowPos.x = pos.x;
       
   127     overlay->hwdata->CurrentWindowPos.y = pos.y;
       
   128     overlay->hwdata->CurrentViewPort.pos.x = 0;
       
   129     overlay->hwdata->CurrentViewPort.pos.y = 0;
       
   130     overlay->hwdata->CurrentViewPort.size.w = width;
       
   131     overlay->hwdata->CurrentViewPort.size.h = height;
       
   132     overlay->hwdata->State = OVERLAY_STATE_UNINIT;
       
   133     overlay->hwdata->FrameData0 = (FRAMEDATA *) SDL_calloc(1, sizeof(FRAMEDATA));
       
   134     overlay->hwdata->FrameData1 = (FRAMEDATA *) SDL_calloc(1, sizeof(FRAMEDATA));
       
   135 
       
   136     vidport = -1;
       
   137     i=0;
       
   138     
       
   139     overlay->hwdata->ischromakey=0;
       
   140 
       
   141     do {
       
   142         SDL_memset(&overlay->hwdata->caps, 0x00, sizeof(PgScalerCaps_t));
       
   143         overlay->hwdata->caps.size = sizeof(PgScalerCaps_t);
       
   144         rtncode = PgGetScalerCapabilities(overlay->hwdata->channel, i, &overlay->hwdata->caps);
       
   145         if (rtncode==0)
       
   146         { 
       
   147             if (overlay->hwdata->caps.format==format)
       
   148             {
       
   149                if ((overlay->hwdata->caps.flags & Pg_SCALER_CAP_DST_CHROMA_KEY) == Pg_SCALER_CAP_DST_CHROMA_KEY)
       
   150                {
       
   151                    overlay->hwdata->ischromakey=1;
       
   152                }
       
   153                vidport=1;
       
   154                break;
       
   155             }
       
   156         }
       
   157         else
       
   158         {
       
   159            break;
       
   160         }
       
   161         i++;
       
   162     } while(1);
       
   163 
       
   164 
       
   165     if (vidport == -1)
       
   166     {
       
   167         SDL_SetError("No available video ports for requested format\n");
       
   168         SDL_FreeYUVOverlay(overlay);
       
   169         return NULL;
       
   170     }
       
   171 
       
   172     overlay->hwdata->format = format;
       
   173     overlay->hwdata->props.format = format;
       
   174     overlay->hwdata->props.size = sizeof(PgScalerProps_t);
       
   175     overlay->hwdata->props.src_dim.w = width;
       
   176     overlay->hwdata->props.src_dim.h = height;
       
   177 
       
   178     /* overlay->hwdata->chromakey = PgGetOverlayChromaColor(); */
       
   179     overlay->hwdata->chromakey = PgRGB(12, 6, 12); /* very dark pink color */
       
   180     overlay->hwdata->props.color_key = overlay->hwdata->chromakey;
       
   181 
       
   182     PhAreaToRect(&overlay->hwdata->CurrentViewPort, &overlay->hwdata->props.viewport);
       
   183 
       
   184     overlay->hwdata->props.flags = Pg_SCALER_PROP_DOUBLE_BUFFER;
       
   185 
       
   186     if ((overlay->hwdata->ischromakey)&&(overlay->hwdata->chromakey))
       
   187     {
       
   188         overlay->hwdata->props.flags |= Pg_SCALER_PROP_CHROMA_ENABLE;
       
   189         overlay->hwdata->props.flags |= Pg_SCALER_PROP_CHROMA_SPECIFY_KEY_MASK;
       
   190     } 
       
   191     else
       
   192     {
       
   193         overlay->hwdata->props.flags &= ~Pg_SCALER_PROP_CHROMA_ENABLE;
       
   194     }
       
   195 
       
   196     rtncode = PgConfigScalerChannel(overlay->hwdata->channel, &overlay->hwdata->props);
       
   197 
       
   198     switch(rtncode)
       
   199     {
       
   200         case -1: SDL_SetError("PgConfigScalerChannel failed\n");
       
   201                  SDL_FreeYUVOverlay(overlay);
       
   202                  return NULL;
       
   203         case 1:
       
   204         case 0:
       
   205         default:
       
   206                  break;
       
   207     }
       
   208 
       
   209     planes = grab_ptrs2(overlay->hwdata->channel, overlay->hwdata->FrameData0, overlay->hwdata->FrameData1);
       
   210 
       
   211     if(overlay->hwdata->channel->yplane1 != NULL)
       
   212         overlay->hwdata->YStride = overlay->hwdata->channel->yplane1->pitch;
       
   213     if(overlay->hwdata->channel->vplane1 != NULL)
       
   214         overlay->hwdata->UStride = overlay->hwdata->channel->vplane1->pitch;
       
   215     if(overlay->hwdata->channel->uplane1 != NULL)
       
   216         overlay->hwdata->VStride = overlay->hwdata->channel->uplane1->pitch;
       
   217 
       
   218     /* check for the validness of all planes */
       
   219     if ((overlay->hwdata->channel->yplane1 == NULL) &&
       
   220         (overlay->hwdata->channel->uplane1 == NULL) &&
       
   221         (overlay->hwdata->channel->vplane1 == NULL))
       
   222     {
       
   223        SDL_FreeYUVOverlay(overlay);
       
   224        SDL_SetError("PgConfigScaler() returns all planes equal NULL\n");
       
   225        return NULL;
       
   226     }
       
   227 /*
       
   228     overlay->hwdata->current = PgNextVideoFrame(overlay->hwdata->channel);
       
   229 
       
   230     if (overlay->hwdata->current==0)
       
   231     {
       
   232         overlay->hwdata->CurrentFrameData = overlay->hwdata->FrameData0;
       
   233     }
       
   234     else
       
   235     {
       
   236         overlay->hwdata->CurrentFrameData = overlay->hwdata->FrameData1;
       
   237     }
       
   238 */
       
   239     overlay->hwdata->CurrentFrameData = overlay->hwdata->FrameData0;
       
   240 
       
   241 /*
       
   242     overlay->hwdata->locked = 1;
       
   243 */
       
   244 
       
   245     /* Find the pitch and offset values for the overlay */
       
   246     overlay->planes = planes;
       
   247     overlay->pitches = SDL_calloc(overlay->planes, sizeof(Uint16));
       
   248     overlay->pixels  = SDL_calloc(overlay->planes, sizeof(Uint8*));
       
   249     if (!overlay->pitches || !overlay->pixels)
       
   250     {
       
   251         SDL_OutOfMemory();
       
   252         SDL_FreeYUVOverlay(overlay);
       
   253         return(NULL);
       
   254     }
       
   255 
       
   256     if (overlay->planes > 0)
       
   257     {
       
   258         overlay->pitches[0] = overlay->hwdata->channel->yplane1->pitch;
       
   259         overlay->pixels[0]  = overlay->hwdata->CurrentFrameData->Y;
       
   260     }
       
   261     if (overlay->planes > 1)
       
   262     {
       
   263         overlay->pitches[1] = overlay->hwdata->channel->vplane1->pitch;
       
   264         overlay->pixels[1]  = overlay->hwdata->CurrentFrameData->U;
       
   265     }
       
   266     if (overlay->planes > 2)
       
   267     {
       
   268         overlay->pitches[2] = overlay->hwdata->channel->uplane1->pitch;
       
   269         overlay->pixels[2]  = overlay->hwdata->CurrentFrameData->V;
       
   270     }
       
   271 
       
   272     overlay->hwdata->State = OVERLAY_STATE_ACTIVE;
       
   273     overlay->hwdata->scaler_on = 0;
       
   274     overlay->hw_overlay = 1;
       
   275 
       
   276     current_overlay=overlay;
       
   277 
       
   278     return overlay;
       
   279 }
       
   280 
       
   281 int ph_LockYUVOverlay(_THIS, SDL_Overlay* overlay)
       
   282 {
       
   283     if (overlay == NULL)
       
   284     {
       
   285         return -1;
       
   286     }
       
   287 
       
   288     overlay->hwdata->locked = 1;
       
   289 
       
   290 /*  overlay->hwdata->current = PgNextVideoFrame(overlay->hwdata->channel);
       
   291     if (overlay->hwdata->current == -1)
       
   292     {
       
   293         SDL_SetError("ph_LockYUVOverlay: PgNextFrame() failed, bailing out\n");
       
   294         SDL_FreeYUVOverlay(overlay);
       
   295         return 0;
       
   296     }
       
   297 
       
   298     if (overlay->hwdata->current == 0)
       
   299     {
       
   300         overlay->hwdata->CurrentFrameData = overlay->hwdata->FrameData0;
       
   301     }
       
   302     else
       
   303     {
       
   304         overlay->hwdata->CurrentFrameData = overlay->hwdata->FrameData1;
       
   305     }
       
   306 
       
   307     if (overlay->planes > 0)
       
   308     {
       
   309         overlay->pitches[0] = overlay->hwdata->channel->yplane1->pitch;
       
   310         overlay->pixels[0]  = overlay->hwdata->CurrentFrameData->Y;
       
   311     }
       
   312     if (overlay->planes > 1)
       
   313     {
       
   314         overlay->pitches[1] = overlay->hwdata->channel->uplane1->pitch;
       
   315         overlay->pixels[1]  = overlay->hwdata->CurrentFrameData->U;
       
   316     }
       
   317     if (overlay->planes > 2)
       
   318     {
       
   319         overlay->pitches[2] = overlay->hwdata->channel->vplane1->pitch;
       
   320         overlay->pixels[2]  = overlay->hwdata->CurrentFrameData->V;
       
   321     }
       
   322 */
       
   323 
       
   324     return(0);
       
   325 }
       
   326 
       
   327 void ph_UnlockYUVOverlay(_THIS, SDL_Overlay* overlay)
       
   328 {
       
   329     if (overlay == NULL)
       
   330     {
       
   331         return;
       
   332     }
       
   333 
       
   334     overlay->hwdata->locked = 0;
       
   335 }
       
   336 
       
   337 int ph_DisplayYUVOverlay(_THIS, SDL_Overlay* overlay, SDL_Rect* src, SDL_Rect* dst)
       
   338 {
       
   339     int rtncode;
       
   340     PhPoint_t pos;
       
   341     SDL_Rect backrect;
       
   342     PhRect_t windowextent;
       
   343     int winchanged=0;
       
   344 
       
   345     if ((overlay == NULL) || (overlay->hwdata==NULL))
       
   346     {
       
   347         return -1;
       
   348     }
       
   349 
       
   350     if (overlay->hwdata->State == OVERLAY_STATE_UNINIT)
       
   351     {
       
   352         return -1;
       
   353     }
       
   354 
       
   355     PtGetAbsPosition(window, &pos.x, &pos.y);
       
   356     if ((pos.x!=overlay->hwdata->CurrentWindowPos.x) ||
       
   357         (pos.y!=overlay->hwdata->CurrentWindowPos.y))
       
   358     {
       
   359        winchanged=1;
       
   360        overlay->hwdata->CurrentWindowPos.x=pos.x;
       
   361        overlay->hwdata->CurrentWindowPos.y=pos.y;
       
   362     }
       
   363 
       
   364     /* If CurrentViewPort position/size has been changed, then move/resize the viewport */
       
   365     if ((overlay->hwdata->CurrentViewPort.pos.x != dst->x) ||
       
   366         (overlay->hwdata->CurrentViewPort.pos.y != dst->y) ||
       
   367         (overlay->hwdata->CurrentViewPort.size.w != dst->w) ||
       
   368         (overlay->hwdata->CurrentViewPort.size.h != dst->h) ||
       
   369         (overlay->hwdata->scaler_on==0) || (winchanged==1) ||
       
   370         (overlay->hwdata->forcedredraw==1))
       
   371     {
       
   372 
       
   373         if (overlay->hwdata->ischromakey==1)
       
   374         {
       
   375             /* restore screen behind the overlay/chroma color. */
       
   376             backrect.x=overlay->hwdata->CurrentViewPort.pos.x;
       
   377             backrect.y=overlay->hwdata->CurrentViewPort.pos.y;
       
   378             backrect.w=overlay->hwdata->CurrentViewPort.size.w;
       
   379             backrect.h=overlay->hwdata->CurrentViewPort.size.h;
       
   380             this->UpdateRects(this, 1, &backrect);
       
   381 
       
   382             /* Draw the new rectangle of the chroma color at the viewport position */
       
   383             PgSetFillColor(overlay->hwdata->chromakey);
       
   384             PgDrawIRect(dst->x, dst->y, dst->x+dst->w-1, dst->y+dst->h-1, Pg_DRAW_FILL);
       
   385             PgFlush();
       
   386         }
       
   387 
       
   388         overlay->hwdata->props.flags |= Pg_SCALER_PROP_SCALER_ENABLE;
       
   389         overlay->hwdata->scaler_on = 1;
       
   390 
       
   391         PhWindowQueryVisible(Ph_QUERY_CONSOLE, 0, PtWidgetRid(window), &windowextent);
       
   392         overlay->hwdata->CurrentViewPort.pos.x = pos.x-windowextent.ul.x+dst->x;
       
   393         overlay->hwdata->CurrentViewPort.pos.y = 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, &overlay->hwdata->props.viewport);
       
   397         overlay->hwdata->CurrentViewPort.pos.x = dst->x;
       
   398         overlay->hwdata->CurrentViewPort.pos.y = dst->y;
       
   399 
       
   400         rtncode = PgConfigScalerChannel(overlay->hwdata->channel, &(overlay->hwdata->props));
       
   401 
       
   402         switch(rtncode)
       
   403         {
       
   404             case -1:
       
   405                      SDL_SetError("PgConfigScalerChannel() function failed\n");
       
   406                      SDL_FreeYUVOverlay(overlay);
       
   407                      return -1;
       
   408             case 1:
       
   409                      grab_ptrs2(overlay->hwdata->channel, overlay->hwdata->FrameData0, overlay->hwdata->FrameData1);
       
   410                      break;
       
   411             case 0:
       
   412             default:
       
   413                      break;
       
   414         }
       
   415     }
       
   416 
       
   417 
       
   418 /*
       
   419     if (overlay->hwdata->locked==0)
       
   420     {
       
   421         overlay->hwdata->current = PgNextVideoFrame(overlay->hwdata->channel);
       
   422         if (overlay->hwdata->current == -1)
       
   423         {
       
   424             SDL_SetError("ph_LockYUVOverlay: PgNextFrame() failed, bailing out\n");
       
   425             SDL_FreeYUVOverlay(overlay);
       
   426             return 0;
       
   427         }
       
   428 
       
   429         if (overlay->hwdata->current == 0)
       
   430         {
       
   431             overlay->hwdata->CurrentFrameData = overlay->hwdata->FrameData0;
       
   432         }
       
   433         else
       
   434         {
       
   435             overlay->hwdata->CurrentFrameData = overlay->hwdata->FrameData1;
       
   436         }
       
   437 
       
   438         if (overlay->planes > 0)
       
   439         {
       
   440             overlay->pitches[0] = overlay->hwdata->channel->yplane1->pitch;
       
   441             overlay->pixels[0]  = overlay->hwdata->CurrentFrameData->Y;
       
   442         }
       
   443         if (overlay->planes > 1)
       
   444         {
       
   445             overlay->pitches[1] = overlay->hwdata->channel->uplane1->pitch;
       
   446             overlay->pixels[1]  = overlay->hwdata->CurrentFrameData->U;
       
   447         }
       
   448         if (overlay->planes > 2)
       
   449         {
       
   450             overlay->pitches[2] = overlay->hwdata->channel->vplane1->pitch;
       
   451             overlay->pixels[2]  = overlay->hwdata->CurrentFrameData->V;
       
   452         }
       
   453     }
       
   454 */
       
   455         
       
   456     return 0;
       
   457 }
       
   458 
       
   459 void ph_FreeYUVOverlay(_THIS, SDL_Overlay *overlay)
       
   460 {
       
   461     SDL_Rect backrect;
       
   462 
       
   463     if (overlay == NULL)
       
   464     {
       
   465         return;
       
   466     }
       
   467 
       
   468     if (overlay->hwdata == NULL)
       
   469     {
       
   470         return;
       
   471     }
       
   472 
       
   473     current_overlay=NULL;
       
   474 
       
   475     /* restore screen behind the overlay/chroma color. */
       
   476     backrect.x=overlay->hwdata->CurrentViewPort.pos.x;
       
   477     backrect.y=overlay->hwdata->CurrentViewPort.pos.y;
       
   478     backrect.w=overlay->hwdata->CurrentViewPort.size.w;
       
   479     backrect.h=overlay->hwdata->CurrentViewPort.size.h;
       
   480     this->UpdateRects(this, 1, &backrect);
       
   481 
       
   482     /* it is need for some buggy drivers, that can't hide overlay before */
       
   483     /* freeing buffer, so we got trash on the srceen                     */
       
   484     overlay->hwdata->props.flags &= ~Pg_SCALER_PROP_SCALER_ENABLE;
       
   485     PgConfigScalerChannel(overlay->hwdata->channel, &(overlay->hwdata->props));
       
   486 
       
   487     overlay->hwdata->scaler_on = 0;
       
   488     overlay->hwdata->State = OVERLAY_STATE_UNINIT;
       
   489 
       
   490     if (overlay->hwdata->channel != NULL)
       
   491     {
       
   492         PgDestroyVideoChannel(overlay->hwdata->channel);
       
   493         overlay->hwdata->channel = NULL;
       
   494         return;
       
   495     }	
       
   496 
       
   497     overlay->hwdata->CurrentFrameData = NULL;  
       
   498 	
       
   499     SDL_free(overlay->hwdata->FrameData0);
       
   500     SDL_free(overlay->hwdata->FrameData1);
       
   501     overlay->hwdata->FrameData0 = NULL;
       
   502     overlay->hwdata->FrameData1 = NULL;
       
   503     SDL_free(overlay->hwdata);
       
   504 }