graphicscomposition/openwfcompositionengine/composition/src/wfcpipeline.c
changeset 0 5d03bc08d59c
child 36 01a6848ebfd7
child 39 a4b63488e0b0
child 163 bbf46f59e123
equal deleted inserted replaced
-1:000000000000 0:5d03bc08d59c
       
     1 /* Copyright (c) 2009 The Khronos Group Inc.
       
     2  *
       
     3  * Permission is hereby granted, free of charge, to any person obtaining a
       
     4  * copy of this software and/or associated documentation files (the
       
     5  * "Materials"), to deal in the Materials without restriction, including
       
     6  * without limitation the rights to use, copy, modify, merge, publish,
       
     7  * distribute, sublicense, and/or sell copies of the Materials, and to
       
     8  * permit persons to whom the Materials are furnished to do so, subject to
       
     9  * the following conditions:
       
    10  *
       
    11  * The above copyright notice and this permission notice shall be included
       
    12  * in all copies or substantial portions of the Materials.
       
    13  *
       
    14  * THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
       
    15  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
       
    16  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
       
    17  * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
       
    18  * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
       
    19  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
       
    20  * MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
       
    21  */
       
    22 
       
    23 /*! \ingroup wfc
       
    24  *  \file wfcpipeline.c
       
    25  *
       
    26  *  \brief SI Composition pipeline stages
       
    27  *
       
    28  *  Each pipeline stage is implemented in their respective functions
       
    29  *  that take context and element as parameter. Composition status is
       
    30  *  stored in elements state variable (struct WFC_ELEMENT_STATE.)
       
    31  *  State has no strict input/output variables, each stage reads/writes
       
    32  *  those variables it needs
       
    33  */
       
    34 #include <string.h>
       
    35 #include <stdlib.h>
       
    36 #include <math.h>
       
    37 
       
    38 #include "WF/wfc.h"
       
    39 #include "wfccontext.h"
       
    40 #include "wfcelement.h"
       
    41 #include "wfcimageprovider.h"
       
    42 #include "wfcstructs.h"
       
    43 #include "wfcscene.h"
       
    44 
       
    45 #include "owfobject.h"
       
    46 
       
    47 #include "owfnativestream.h"
       
    48 #include "owfmemory.h"
       
    49 #include "owfimage.h"
       
    50 #include "owfdebug.h"
       
    51 
       
    52 #define EXTRA_PIXEL_BOUNDARY 2
       
    53 
       
    54 /*!
       
    55  *  \brief Check element destination visibility
       
    56  *
       
    57  *  Check if element's destination rectangle is
       
    58  *  inside context's visible limits.
       
    59  *
       
    60  *  \param context          Context
       
    61  *  \param element          Element
       
    62  *
       
    63  *  \return Boolean value indicating whether element is visible or not
       
    64  */
       
    65 
       
    66 static WFCboolean
       
    67 WFC_Pipeline_ElementIsVisible(WFC_CONTEXT* context, WFC_ELEMENT* element)
       
    68 {
       
    69     OWF_RECTANGLE bounds, rect, drect;
       
    70 
       
    71     if ((context->rotation == WFC_ROTATION_90) || (context->rotation == WFC_ROTATION_270))
       
    72         {
       
    73         OWF_Rect_Set(&bounds, 0, 0, context->targetHeight, context->targetWidth);
       
    74         }
       
    75     else
       
    76         {
       
    77         OWF_Rect_Set(&bounds, 0, 0, context->targetWidth, context->targetHeight);
       
    78         }
       
    79     
       
    80     OWF_Rect_Set(&rect, element->dstRect[0], element->dstRect[1],
       
    81             element->dstRect[2], element->dstRect[3]);
       
    82 
       
    83     /* check destination rectangle against bounds - exit if not visible */
       
    84     if (!OWF_Rect_Clip(&drect, &rect, &bounds))
       
    85     {
       
    86         return WFC_FALSE;
       
    87     }
       
    88 
       
    89     return WFC_TRUE;
       
    90 }
       
    91 
       
    92 static void 
       
    93 WFC_Pipeline_BlendInfo(WFC_CONTEXT* context, WFC_ELEMENT_STATE* state)
       
    94 {
       
    95 
       
    96     OWF_ASSERT(state);    
       
    97     
       
    98     /* setup blending parameters */
       
    99     state->blendInfo.destination.image     = context->state.internalTargetImage;
       
   100     state->blendInfo.destination.rectangle = &state->dstRect;
       
   101     state->blendInfo.source.image          = state->scaledSourceImage;
       
   102     state->blendInfo.source.rectangle      = &state->scaledSrcRect;
       
   103     state->blendInfo.mask                  = state->originalMaskImage ? state->maskImage : NULL;
       
   104     state->blendInfo.globalAlpha           = state->globalAlpha;
       
   105     
       
   106     /* composition does not use these values ever */
       
   107     state->blendInfo.tsColor                = NULL;
       
   108     state->blendInfo.destinationFullyOpaque = OWF_FALSE;    
       
   109     
       
   110     DPRINT(("  globalAplha = %f", state->globalAlpha));
       
   111     /* no need to check with OWF_ALPHA_MIN_VALUE as it is zero */
       
   112     OWF_ASSERT(state->blendInfo.globalAlpha <= OWF_ALPHA_MAX_VALUE);    
       
   113 }
       
   114 
       
   115 /*! Transform the source rectangle to represent the floating point viewport
       
   116     as an offset in the final rotation stage image */
       
   117 static void
       
   118 WFC_Pipeline_TransformSource(WFC_ELEMENT_STATE* state)
       
   119 {
       
   120     OWFfloat                width, height, totalWidth, totalHeight,
       
   121                             leftMargin, rightMargin, 
       
   122                             topMargin, bottomMargin,
       
   123                             temp;
       
   124     OWF_FLIP_DIRECTION      flipping;
       
   125     WFCRotation             rotation;
       
   126     
       
   127     
       
   128     OWF_ASSERT(state);
       
   129     
       
   130     width = state->sourceRect[2];
       
   131     totalWidth = state->sourceRect[0] + state->sourceRect[2];
       
   132     
       
   133     height = state->sourceRect[3];
       
   134     totalHeight = state->sourceRect[1] + state->sourceRect[3];
       
   135     
       
   136     /* X margins - includes 1 pixel border */
       
   137     leftMargin = (state->sourceRect[0] - ((float) floor(state->sourceRect[0]))) + 1.0f;
       
   138     rightMargin = (((float) ceil(totalWidth)) - totalWidth) + 1.0f;
       
   139     
       
   140     /* Y margins - includes 1 pixel border */
       
   141     topMargin = (state->sourceRect[1] - ((float) floor(state->sourceRect[1]))) + 1.0f;    
       
   142     bottomMargin = (((float) ceil(totalHeight)) - totalHeight) + 1.0f;
       
   143     
       
   144     /* flip stages */
       
   145     flipping = state->sourceFlip > 0.0f ? OWF_FLIP_VERTICALLY
       
   146                                       : OWF_FLIP_NONE;
       
   147     
       
   148     /* top margin needs to be the bottom margin */
       
   149     if (flipping & OWF_FLIP_VERTICALLY)
       
   150     {
       
   151         temp = topMargin;
       
   152         topMargin = bottomMargin;
       
   153         bottomMargin = temp; 
       
   154     }
       
   155     
       
   156     /* rotation stages */
       
   157     rotation = state->rotation;
       
   158     
       
   159     switch (rotation)
       
   160     {
       
   161         case WFC_ROTATION_0:
       
   162         {
       
   163             break;
       
   164         }
       
   165 
       
   166         case WFC_ROTATION_90:
       
   167         {
       
   168             /* switch width and height */
       
   169             temp = width;
       
   170             width = height;
       
   171             height = temp;
       
   172             
       
   173             topMargin = leftMargin;
       
   174             leftMargin = bottomMargin;
       
   175             
       
   176             break;
       
   177         }
       
   178 
       
   179         case WFC_ROTATION_180:
       
   180         {
       
   181             leftMargin = rightMargin;
       
   182             topMargin = bottomMargin;
       
   183         
       
   184             break;
       
   185         }
       
   186 
       
   187         case WFC_ROTATION_270:
       
   188         {
       
   189             /* switch width and height */
       
   190             temp = width;
       
   191             width = height;
       
   192             height = temp; 
       
   193             
       
   194             leftMargin = topMargin;
       
   195             topMargin = rightMargin;
       
   196             
       
   197             break;
       
   198         }
       
   199 
       
   200         default:
       
   201         {
       
   202             OWF_ASSERT(0);
       
   203         }
       
   204     }    
       
   205     
       
   206     /* X offset */
       
   207     state->transformedSourceRect[0] = leftMargin;
       
   208     /* Y offset */
       
   209     state->transformedSourceRect[1] = topMargin;
       
   210     /* width */
       
   211     state->transformedSourceRect[2] = width;
       
   212     /* height */
       
   213     state->transformedSourceRect[3] = height;    
       
   214 }
       
   215 
       
   216 /*! Calculate the oversized integer crop region */
       
   217 static void
       
   218 WFC_Pipeline_OversizedViewport(WFC_ELEMENT_STATE* state)
       
   219 {
       
   220     OWFint width, height;
       
   221 
       
   222     state->oversizedCropRect.x = (int) floor(state->sourceRect[0]);
       
   223     state->oversizedCropRect.y = (int) floor(state->sourceRect[1]);
       
   224     
       
   225     width = (int) ceil(state->sourceRect[0] + state->sourceRect[2]);
       
   226     state->oversizedCropRect.width = (width - state->oversizedCropRect.x) + EXTRA_PIXEL_BOUNDARY;
       
   227     
       
   228     height = (int) ceil(state->sourceRect[1] + state->sourceRect[3]);    
       
   229     state->oversizedCropRect.height = (height - state->oversizedCropRect.y) + EXTRA_PIXEL_BOUNDARY;
       
   230 }
       
   231 
       
   232 /*-----------------------------------------------------------*
       
   233  * Initial creation of element state object created just once per context
       
   234  *-----------------------------------------------------------*/
       
   235 OWF_API_CALL void WFC_Pipeline_DestroyState(WFC_CONTEXT* context)
       
   236 {
       
   237     WFC_ELEMENT_STATE*      state;
       
   238     state= &context->prototypeElementState;
       
   239     OWF_Image_Destroy(state->scaledSourceImage);
       
   240     OWF_Image_Destroy(state->croppedSourceImage);
       
   241     OWF_Image_Destroy(state->convertedSourceImage);
       
   242     OWF_Image_Destroy(state->rotatedSourceIntermediateImage);
       
   243     OWF_Image_Destroy(state->flippedSourceImage);
       
   244     OWF_Image_Destroy(state->rotatedSourceImage);    
       
   245     OWF_Image_Destroy(state->maskImage);
       
   246     state->scaledSourceImage=NULL;
       
   247     state->croppedSourceImage=NULL;
       
   248     state->convertedSourceImage=NULL;
       
   249     state->rotatedSourceIntermediateImage=NULL;
       
   250     state->flippedSourceImage=NULL;
       
   251     state->rotatedSourceImage=NULL;    
       
   252     state->maskImage=NULL;
       
   253 }
       
   254 
       
   255 OWF_API_CALL OWFboolean WFC_Pipeline_CreateState(WFC_CONTEXT* context)
       
   256 {
       
   257     WFC_ELEMENT_STATE*      state;
       
   258     OWF_IMAGE_FORMAT        fmt;
       
   259     
       
   260     fmt.pixelFormat    = OWF_IMAGE_ARGB_INTERNAL;
       
   261     fmt.linear         = OWF_FALSE;
       
   262     fmt.premultiplied  = OWF_FALSE;
       
   263     fmt.rowPadding     = 1;
       
   264     state= &context->prototypeElementState;
       
   265     /* All buffers are initially created the full size of the scratch buffers, whicgh records the buffer size in bytes */
       
   266     state->convertedSourceImage=OWF_Image_Create(MAX_SOURCE_WIDTH, MAX_SOURCE_HEIGHT, &fmt, context->scratchBuffer[1], 0);
       
   267     state->croppedSourceImage=OWF_Image_Create(MAX_SOURCE_WIDTH, MAX_SOURCE_HEIGHT, &fmt, context->scratchBuffer[2], 0);
       
   268     state->flippedSourceImage=OWF_Image_Create(MAX_SOURCE_WIDTH, MAX_SOURCE_HEIGHT, &fmt, context->scratchBuffer[2], 0);    
       
   269 
       
   270     state->rotatedSourceIntermediateImage=OWF_Image_Create(MAX_SOURCE_WIDTH, MAX_SOURCE_HEIGHT, &fmt, context->scratchBuffer[1], 0);      
       
   271     state->rotatedSourceImage=OWF_Image_Create(MAX_SOURCE_WIDTH, MAX_SOURCE_HEIGHT, &fmt, context->scratchBuffer[2], 0);  
       
   272     state->scaledSourceImage=OWF_Image_Create(MAX_SOURCE_WIDTH, MAX_SOURCE_HEIGHT, &fmt, context->scratchBuffer[3], 0);
       
   273     fmt.pixelFormat    = OWF_IMAGE_L32;
       
   274     state->maskImage=OWF_Image_Create(MAX_SOURCE_WIDTH, MAX_SOURCE_HEIGHT, &fmt, context->scratchBuffer[4], 0);
       
   275     if (!state->convertedSourceImage||!state->croppedSourceImage||!state->flippedSourceImage
       
   276         ||!state->rotatedSourceIntermediateImage||!state->rotatedSourceImage
       
   277         ||!state->scaledSourceImage||!state->maskImage
       
   278         )
       
   279         {
       
   280         WFC_Pipeline_DestroyState(context);
       
   281         return OWF_FALSE;
       
   282         }
       
   283     return OWF_TRUE;
       
   284 }
       
   285 
       
   286 
       
   287 /*---------------------------------------------------------------------------
       
   288  *  Composition pipeline preparation
       
   289  *
       
   290  *  \param context          Context
       
   291  *  \param element          Element
       
   292  *
       
   293  *  \return Boolean value indicating whether preparation succeeded
       
   294  *----------------------------------------------------------------------------*/
       
   295 #ifdef DEBUG
       
   296 /* reset size to original extent then try to set it to the target size */
       
   297 #define CREATE_WITH_LIMITS(img, imgW, imgH, fmt, maxW, maxH) \
       
   298     { \
       
   299         OWFboolean resized; \
       
   300         OWF_Image_SetSize(img, maxW, maxH); \
       
   301         OWF_Image_SetFlags(img,(fmt)->premultiplied,(fmt)->linear); \
       
   302         resized = OWF_Image_SetSize(img, imgW, imgH); \
       
   303         OWF_ASSERT(resized); \
       
   304     }
       
   305 #else
       
   306 #define CREATE_WITH_LIMITS(img, imgW, imgH, fmt, maxW, maxH) \
       
   307     { \
       
   308         OWF_Image_SetSize(img, maxW, maxH); \
       
   309         OWF_Image_SetFlags(img,(fmt)->premultiplied,(fmt)->linear); \
       
   310         OWF_Image_SetSize(img, imgW, imgH); \
       
   311     }
       
   312 #endif
       
   313 OWF_API_CALL WFC_ELEMENT_STATE*
       
   314 WFC_Pipeline_BeginComposition(WFC_CONTEXT* context, WFC_ELEMENT* element)
       
   315 {
       
   316     WFC_ELEMENT_STATE*      state = &context->prototypeElementState;
       
   317     OWF_IMAGE_FORMAT        imgf;
       
   318     OWFint                  sourceWidth;
       
   319     OWFint                  sourceHeight;
       
   320     OWFint                  x;
       
   321     OWFint                  tempWidth, tempHeight;
       
   322 
       
   323 
       
   324     DPRINT(("WFC_Element_BeginComposition(%x,%x)",
       
   325             context ? context->handle : 0, element ? element->handle : 0));
       
   326 
       
   327     if (!context || !element)
       
   328     {
       
   329         DPRINT(("  context == NULL || element == NULL"));
       
   330         return NULL;
       
   331     }
       
   332 
       
   333     if (!WFC_Pipeline_ElementIsVisible(context, element))
       
   334     {
       
   335         DPRINT(("  element [%x] totally outside of target - skipped",
       
   336                         element ? element->handle : 0));
       
   337         return NULL;
       
   338     }
       
   339 
       
   340     
       
   341     /* setup temporary images used in composition. since the original
       
   342        source data must not be altered, we must copy it to scratch buffer
       
   343        and work it there. another scratch buffer is needed for scaling
       
   344        the image to its final size. same applies for masks; thus a grand total
       
   345        of 4 scratch buffers are needed. */
       
   346     OWF_ASSERT(element->source);
       
   347     OWF_ASSERT(element->source->streamHandle);     
       
   348     
       
   349     state->originalSourceImage = element->source->lockedStream.image;
       
   350     state->rotation = element->sourceRotation;
       
   351     state->sourceFlip = element->sourceFlip;
       
   352     state->globalAlpha = element->globalAlpha;
       
   353     state->sourceScaleFilter = element->sourceScaleFilter;
       
   354     state->transparencyTypes = element->transparencyTypes;
       
   355     /* replicate the source viewport rectangle and target extent rectangle */
       
   356     for (x = 0; x < 4; x++)
       
   357     {
       
   358         state->sourceRect[x] = element->srcRect[x];
       
   359         state->destinationRect[x] = element->dstRect[x];
       
   360     }
       
   361     OWF_Rect_Set(&state->dstRect, element->dstRect[0], element->dstRect[1],
       
   362                  element->dstRect[2], element->dstRect[3]);    
       
   363     
       
   364     /* transform the source rectangle to represent the floating point viewport
       
   365        as an offset in the final rotation stage image */
       
   366     WFC_Pipeline_TransformSource(state);
       
   367     
       
   368     imgf.pixelFormat    = OWF_IMAGE_ARGB_INTERNAL;
       
   369     imgf.linear         = element->source->lockedStream.image->format.linear;
       
   370     imgf.premultiplied  = element->source->lockedStream.image->format.premultiplied;
       
   371     imgf.rowPadding     = 1;
       
   372 
       
   373     /* add a 1 pixel boundary so we can replicate the edges */
       
   374     sourceWidth = element->source->lockedStream.image->width + EXTRA_PIXEL_BOUNDARY;
       
   375     sourceHeight = element->source->lockedStream.image->height + EXTRA_PIXEL_BOUNDARY;
       
   376     
       
   377     CREATE_WITH_LIMITS(state->convertedSourceImage,
       
   378                        sourceWidth,
       
   379                        sourceHeight,
       
   380                        &imgf,
       
   381                        MAX_SOURCE_WIDTH, MAX_SOURCE_HEIGHT);
       
   382     
       
   383     /* calculate the oversized integer crop region (inc. 1 pixel boundary)
       
   384        so edge replication can be performed */
       
   385     WFC_Pipeline_OversizedViewport(state);    
       
   386     
       
   387     /* subsequent temporary renderstage pipeline images need to use the oversized
       
   388        integer crop region */
       
   389     CREATE_WITH_LIMITS(state->croppedSourceImage,
       
   390                        state->oversizedCropRect.width, state->oversizedCropRect.height,
       
   391                        &imgf,
       
   392                        MAX_SOURCE_WIDTH, MAX_SOURCE_HEIGHT);
       
   393     
       
   394     CREATE_WITH_LIMITS(state->flippedSourceImage,
       
   395                        state->oversizedCropRect.width, state->oversizedCropRect.height,
       
   396                        &imgf,
       
   397                        MAX_SOURCE_WIDTH, MAX_SOURCE_HEIGHT);    
       
   398     
       
   399 
       
   400     if (state->rotation == WFC_ROTATION_90 || state->rotation == WFC_ROTATION_270)
       
   401     {
       
   402         tempHeight = state->oversizedCropRect.width;
       
   403         tempWidth = state->oversizedCropRect.height;
       
   404     }
       
   405     else
       
   406     {
       
   407         tempWidth = state->oversizedCropRect.width;
       
   408         tempHeight = state->oversizedCropRect.height;
       
   409     }
       
   410 
       
   411     CREATE_WITH_LIMITS(state->rotatedSourceIntermediateImage,
       
   412                        tempWidth, tempHeight,
       
   413                        &imgf,
       
   414                        MAX_SOURCE_WIDTH, MAX_SOURCE_HEIGHT);      
       
   415     
       
   416 
       
   417      /* no rotation required - just use the previous stages (flip) buffer */
       
   418     CREATE_WITH_LIMITS(state->rotatedSourceImage,
       
   419                        tempWidth, tempHeight,
       
   420                        &imgf,
       
   421                        MAX_SOURCE_WIDTH, MAX_SOURCE_HEIGHT);  
       
   422 
       
   423     /* finally, scaled image uses destination width and height */
       
   424     OWF_Rect_Set(&state->scaledSrcRect, 0, 0, element->dstRect[2], element->dstRect[3]);
       
   425     CREATE_WITH_LIMITS(state->scaledSourceImage,
       
   426                        state->scaledSrcRect.width,
       
   427                        state->scaledSrcRect.height,
       
   428                        &imgf,
       
   429                         MAX_SOURCE_WIDTH, MAX_SOURCE_HEIGHT);
       
   430 
       
   431     if (!(state->convertedSourceImage && state->croppedSourceImage &&
       
   432           state->scaledSourceImage && state->rotatedSourceIntermediateImage &&
       
   433           state->flippedSourceImage && state->rotatedSourceImage))
       
   434     {
       
   435         DPRINT(("  Preparation of intermediate pipeline image buffers failed"
       
   436                 "  (May be caused by overflow or out-of-memory situation)"));
       
   437         DPRINT(("    convertedSourceImage = %p", state->convertedSourceImage));
       
   438         DPRINT(("    croppedSourceImage = %p", state->croppedSourceImage));
       
   439         DPRINT(("    scaledSourceImage = %p", state->scaledSourceImage));
       
   440         DPRINT(("    rotatedSourceIntermediateImage = %p", state->rotatedSourceIntermediateImage));
       
   441         DPRINT(("    flippedSourceImage = %p", state->flippedSourceImage));
       
   442         DPRINT(("    rotatedSourceImage = %p", state->rotatedSourceImage));
       
   443 
       
   444 
       
   445         return (WFC_ELEMENT_STATE*)WFC_FALSE;
       
   446     }
       
   447 
       
   448 #ifdef DEBUG
       
   449         OWF_Image_Clear(state->convertedSourceImage, 0, 0, 0, 0);
       
   450         OWF_Image_Clear(state->croppedSourceImage, 0, 0, 0, 0);
       
   451         OWF_Image_Clear(state->scaledSourceImage, 0, 0, 0, 0);
       
   452         OWF_Image_Clear(state->rotatedSourceIntermediateImage, 0, 0, 0, 0);
       
   453         OWF_Image_Clear(state->flippedSourceImage, 0, 0, 0, 0);
       
   454         OWF_Image_Clear(state->rotatedSourceImage, 0, 0, 0, 0);
       
   455 #endif
       
   456 
       
   457     /* setup mask in case the element has one */
       
   458     if (element->maskComposed)
       
   459     {
       
   460         OWF_IMAGE*          image = NULL;
       
   461         OWFsubpixel*        pix = NULL;
       
   462         WFCint              i = 0;
       
   463 
       
   464         DPRINT(("Processing element mask"));
       
   465         OWF_ASSERT(&element->mask);
       
   466         OWF_ASSERT(&element->mask->streamHandle);
       
   467         image = element->mask->lockedStream.image;
       
   468         OWF_ASSERT(image);
       
   469 
       
   470         state->originalMaskImage = element->mask->lockedStream.image;        
       
   471         
       
   472         imgf.pixelFormat    = OWF_IMAGE_L32;
       
   473         imgf.linear         = image->format.linear;
       
   474         imgf.premultiplied  = image->format.premultiplied;
       
   475 
       
   476         /* mask size is always same as destination rect's */
       
   477         DPRINT(("Binding stream image to scratch buffer"));
       
   478         CREATE_WITH_LIMITS(state->maskImage,
       
   479                            state->scaledSrcRect.width,
       
   480                            state->scaledSrcRect.height,
       
   481                            &imgf,
       
   482                            MAX_SOURCE_WIDTH, MAX_SOURCE_HEIGHT);
       
   483 
       
   484         /* initialize mask */
       
   485         DPRINT(("Initializing mask, size = %dx%d", state->scaledSrcRect.width,
       
   486                 state->scaledSrcRect.height));
       
   487         pix = (OWFsubpixel*) state->maskImage->data;
       
   488         for (i = 0; i < state->scaledSrcRect.width * state->scaledSrcRect.height; i++)
       
   489         {
       
   490             pix[i] = OWF_FULLY_OPAQUE;
       
   491         }
       
   492     }
       
   493     else
       
   494         {
       
   495         state->originalMaskImage=NULL;
       
   496         }
       
   497     
       
   498     WFC_Pipeline_BlendInfo(context, state);
       
   499 
       
   500     DPRINT(("  Cropped source image size is %dx%d",
       
   501            state->croppedSourceImage->width, state->croppedSourceImage->height));
       
   502     DPRINT(("  Scaled source image size is %dx%d",
       
   503             state->scaledSourceImage->width, state->scaledSourceImage->height));
       
   504     DPRINT(("  Mirrored source intermediate image size is %dx%d",
       
   505             state->rotatedSourceIntermediateImage->width, state->rotatedSourceIntermediateImage->height));
       
   506     DPRINT(("  Mirrored source image size is %dx%d",
       
   507             state->flippedSourceImage->width, state->flippedSourceImage->height));
       
   508     DPRINT(("  Rotated source image size is %dx%d",
       
   509             state->rotatedSourceImage->width, state->rotatedSourceImage->height));  
       
   510     
       
   511     return state;
       
   512 }
       
   513 
       
   514 /*---------------------------------------------------------------------------
       
   515  *  Composition pipeline cleanup
       
   516  *
       
   517  *  \param context          Context
       
   518  *  \param element          Element
       
   519  *----------------------------------------------------------------------------*/
       
   520 OWF_API_CALL void
       
   521 WFC_Pipeline_EndComposition(WFC_CONTEXT* context, WFC_ELEMENT* element, WFC_ELEMENT_STATE* state)
       
   522 {
       
   523 
       
   524     if (!context || !element)
       
   525     {
       
   526         DPRINT(("WFC_Element_EndComposition: context == NULL || "
       
   527                 "element == NULL"));
       
   528     }
       
   529 
       
   530 
       
   531     OWF_ASSERT(state);
       
   532     state->originalSourceImage=NULL;
       
   533     state->originalMaskImage=NULL;
       
   534 
       
   535 }
       
   536 
       
   537 /*---------------------------------------------------------------------------
       
   538  *  \brief Source conversion stage
       
   539  *
       
   540  *  \param context          Context
       
   541  *  \param element          Element
       
   542  *----------------------------------------------------------------------------*/
       
   543 OWF_API_CALL void
       
   544 WFC_Pipeline_ExecuteSourceConversionStage(WFC_CONTEXT* context,
       
   545         WFC_ELEMENT_STATE* state)
       
   546 {
       
   547     /* this stage could be embedded in cropping stage */
       
   548 
       
   549 
       
   550     if (NULL == context || NULL == state)
       
   551     {
       
   552         DPRINT(("WFC_Context_ExecuteSourceConversionStage: context = %p, "
       
   553                 "state = %p",
       
   554                 context, state));
       
   555         return;
       
   556     }
       
   557 
       
   558     OWF_ASSERT(state->originalSourceImage);
       
   559 
       
   560     OWF_Image_SourceFormatConversion(state->convertedSourceImage,
       
   561                                      state->originalSourceImage);
       
   562 
       
   563     /* convert mask from stream format to internal format */
       
   564     if (state->originalMaskImage)
       
   565     {
       
   566         if (!OWF_Image_ConvertMask(state->maskImage, state->originalMaskImage))
       
   567         {
       
   568             state->originalMaskImage=NULL;
       
   569         }
       
   570     }
       
   571 }
       
   572 
       
   573 /*---------------------------------------------------------------------------
       
   574  *  \brief Crop stage
       
   575  *
       
   576  *  \param context          Context
       
   577  *  \param element          Element
       
   578  *----------------------------------------------------------------------------*/
       
   579 OWF_API_CALL void
       
   580 WFC_Pipeline_ExecuteCropStage(WFC_CONTEXT* context, WFC_ELEMENT_STATE* state)
       
   581 {
       
   582     OWF_RECTANGLE           sourceRect,
       
   583                             cropRect;
       
   584 
       
   585     DPRINT(("WFC_Pipeline_ExecuteCropStage"));
       
   586 
       
   587     if (NULL == context || NULL == state)
       
   588     {
       
   589         DPRINT(("WFC_Context_ExecuteCropStage: context = %p, state = %p",
       
   590                context, state));
       
   591     }
       
   592     else
       
   593     {
       
   594 
       
   595         /* Source rectangle */
       
   596         OWF_Rect_Set(&sourceRect,
       
   597                      state->oversizedCropRect.x, state->oversizedCropRect.y,
       
   598                      state->oversizedCropRect.width, state->oversizedCropRect.height);
       
   599 
       
   600         /* cropped source size - supports oversized integer and 1 pixel boundary */
       
   601         OWF_Rect_Set(&cropRect,
       
   602                      0, 0,
       
   603                      state->oversizedCropRect.width, state->oversizedCropRect.height);
       
   604 
       
   605         OWF_Image_Blit(state->croppedSourceImage, &cropRect,
       
   606                        state->convertedSourceImage, &sourceRect);
       
   607     }
       
   608 }
       
   609 
       
   610 /*---------------------------------------------------------------------------
       
   611  *  \brief Flip stage
       
   612  *
       
   613  *  \param context          Context
       
   614  *  \param element          Element
       
   615  *----------------------------------------------------------------------------*/
       
   616 OWF_API_CALL void
       
   617 WFC_Pipeline_ExecuteFlipStage(WFC_CONTEXT* context, WFC_ELEMENT_STATE* state)
       
   618 {
       
   619     OWF_FLIP_DIRECTION      flipping;
       
   620     
       
   621     if (NULL == context || NULL == state)
       
   622     {
       
   623         DPRINT(("WFC_Context_ExecuteFlipStage: context = %p, state = %p",
       
   624                context, state));
       
   625     }
       
   626     else
       
   627     {
       
   628         OWF_ASSERT(state);
       
   629         flipping = state->sourceFlip > 0.0f ? OWF_FLIP_VERTICALLY
       
   630                                           : OWF_FLIP_NONE;
       
   631         
       
   632         OWF_Image_Flip(state->flippedSourceImage, flipping);
       
   633     }
       
   634 }
       
   635 
       
   636 /*---------------------------------------------------------------------------
       
   637  *  \brief Rotation stage
       
   638  *
       
   639  *  \param context          Context
       
   640  *  \param element          Element
       
   641  *----------------------------------------------------------------------------*/
       
   642 OWF_API_CALL void
       
   643 WFC_Pipeline_ExecuteRotationStage(WFC_CONTEXT* context, WFC_ELEMENT_STATE* state)
       
   644 {
       
   645     OWF_ROTATION            rot = OWF_ROTATION_0;
       
   646     OWF_RECTANGLE           rect;    
       
   647     WFCRotation             rotation;
       
   648 
       
   649 
       
   650     if (NULL == context || NULL == state)
       
   651     {
       
   652         DPRINT(("WFC_Context_ExecuteRotationStage: context = %p, state = %p",
       
   653                context, state));
       
   654         return;
       
   655     }
       
   656     OWF_ASSERT(state);
       
   657 
       
   658     rotation = state->rotation;
       
   659     DPRINT(("  Element rotation = %d", rotation));
       
   660 
       
   661     switch (rotation)
       
   662     {
       
   663         case WFC_ROTATION_0:
       
   664         {
       
   665             return; /* Rotate copies back into input buffer so just skip */
       
   666         }
       
   667 
       
   668         case WFC_ROTATION_90:
       
   669         {
       
   670             rot = OWF_ROTATION_90;
       
   671             break;
       
   672         }
       
   673 
       
   674         case WFC_ROTATION_180:
       
   675         {
       
   676             rot = OWF_ROTATION_180;
       
   677             break;
       
   678         }
       
   679 
       
   680         case WFC_ROTATION_270:
       
   681         {
       
   682             rot = OWF_ROTATION_270;
       
   683             break;
       
   684         }
       
   685 
       
   686         default:
       
   687         {
       
   688             OWF_ASSERT(0);
       
   689         }
       
   690     }
       
   691 
       
   692     /* rotate the the image using rotatedSourceIntermediateImage */
       
   693     OWF_Image_Rotate(state->rotatedSourceIntermediateImage,
       
   694                      state->flippedSourceImage,
       
   695                      rot);
       
   696 
       
   697     /* blit rotated image back to original image buffer */
       
   698     rect.x      = 0;
       
   699     rect.y      = 0;
       
   700     rect.width  = state->rotatedSourceIntermediateImage->width;
       
   701     rect.height = state->rotatedSourceIntermediateImage->height;
       
   702 
       
   703     DPRINT(("  Source image dimensions after rotation = %dx%d",
       
   704            rect.width, rect.height));
       
   705 
       
   706     OWF_Image_Blit(state->rotatedSourceImage,
       
   707                    &rect,
       
   708                    state->rotatedSourceIntermediateImage,
       
   709                    &rect);
       
   710     
       
   711 }
       
   712 
       
   713 /*---------------------------------------------------------------------------
       
   714  *  \brief Scaling stage
       
   715  *
       
   716  *  \param context          Context
       
   717  *  \param element          Element
       
   718  *----------------------------------------------------------------------------*/
       
   719 OWF_API_CALL void
       
   720 WFC_Pipeline_ExecuteScalingStage(WFC_CONTEXT* context, WFC_ELEMENT_STATE* state)
       
   721 {
       
   722     OWF_RECTANGLE           scaledRect,
       
   723                             cropRect;
       
   724     OWF_FILTERING           filteringMode = OWF_FILTER_POINT_SAMPLING;
       
   725     WFCScaleFilter          filter;
       
   726 
       
   727     DPRINT(("WFC_Context_ExecuteScalingStage(%p,%p)", context, state));
       
   728 
       
   729     if (NULL == context || NULL == state)
       
   730     {
       
   731         DPRINT(("WFC_Context_ExecuteScalingStage: context = %p, state = %p",
       
   732                context, state));
       
   733         return;
       
   734     }
       
   735 
       
   736     OWF_ASSERT(state);
       
   737 
       
   738     filter = state->sourceScaleFilter;
       
   739 
       
   740     switch (filter)
       
   741     {
       
   742         case WFC_SCALE_FILTER_NONE:
       
   743         case WFC_SCALE_FILTER_FASTER:
       
   744         {
       
   745             filteringMode = OWF_FILTER_POINT_SAMPLING;
       
   746             DPRINT(("  Using point-sampling filter"));
       
   747             break;
       
   748         }
       
   749         case WFC_SCALE_FILTER_BETTER:
       
   750         {
       
   751             filteringMode = OWF_FILTER_BILINEAR;
       
   752             DPRINT(("  Using bilinear filter"));
       
   753             break;
       
   754         }
       
   755 
       
   756         case WFC_SCALE_FILTER_FORCE_32BIT:
       
   757         {
       
   758             /* To shut the compiler up -- not a valid filtering mode.
       
   759              * Validity is ensured when the filter attribute value
       
   760              * is set, thus it shouldn't have this value ever. */
       
   761             OWF_ASSERT(0);
       
   762             break;
       
   763         }
       
   764     }
       
   765 
       
   766     OWF_Rect_Set(&cropRect, 1, 1,
       
   767                  state->rotatedSourceImage->width - EXTRA_PIXEL_BOUNDARY,
       
   768                  state->rotatedSourceImage->height - EXTRA_PIXEL_BOUNDARY);
       
   769 
       
   770     OWF_Rect_Set(&scaledRect, 0, 0, state->destinationRect[2], state->destinationRect[3]);
       
   771     
       
   772     if (  scaledRect.width != state->transformedSourceRect[2] 
       
   773       ||  scaledRect.height != state->transformedSourceRect[3]
       
   774       ||  state->sourceRect[0] != floor(state->sourceRect[0])
       
   775       ||  state->sourceRect[1] != floor(state->sourceRect[1])
       
   776     )
       
   777     {
       
   778         /* scale the image */
       
   779         OWF_Image_Stretch(state->scaledSourceImage, &scaledRect,
       
   780                           state->rotatedSourceImage, state->transformedSourceRect,
       
   781                           filteringMode);
       
   782     }
       
   783     else
       
   784     {
       
   785         /* 1:1 copy, no need to scale */
       
   786         OWF_Image_Blit(state->scaledSourceImage, &scaledRect,
       
   787                        state->rotatedSourceImage, &cropRect);
       
   788     }
       
   789     
       
   790 }
       
   791 
       
   792 /*---------------------------------------------------------------------------
       
   793  *  \brief Blending stage
       
   794  *
       
   795  *  \param context          Context
       
   796  *  \param element          Element
       
   797  *----------------------------------------------------------------------------*/
       
   798 OWF_API_CALL void
       
   799 WFC_Pipeline_ExecuteBlendingStage(WFC_CONTEXT* context, WFC_ELEMENT_STATE* state)
       
   800 {
       
   801     OWF_TRANSPARENCY        blendMode = OWF_TRANSPARENCY_NONE;
       
   802     WFCbitfield             transparency = 0;
       
   803 
       
   804     DPRINT(("WFC_Pipeline_ExecuteBlendingStage"));
       
   805 
       
   806     if (NULL == context || NULL == state)
       
   807     {
       
   808         return;
       
   809     }
       
   810 
       
   811     DPRINT(("  context = %d, state = %d",
       
   812            context->handle, state));
       
   813 
       
   814     OWF_ASSERT(state);
       
   815 
       
   816     transparency = state->transparencyTypes;
       
   817     blendMode = OWF_TRANSPARENCY_NONE;
       
   818 
       
   819     if (transparency & WFC_TRANSPARENCY_ELEMENT_GLOBAL_ALPHA)
       
   820     {
       
   821         blendMode = (OWF_TRANSPARENCY)(blendMode|OWF_TRANSPARENCY_GLOBAL_ALPHA);
       
   822     }
       
   823 
       
   824     if (transparency & WFC_TRANSPARENCY_SOURCE)
       
   825     {
       
   826         OWF_Image_PremultiplyAlpha(state->scaledSourceImage);
       
   827         blendMode = (OWF_TRANSPARENCY)(blendMode|OWF_TRANSPARENCY_SOURCE_ALPHA);
       
   828     }
       
   829 
       
   830     if ((transparency & WFC_TRANSPARENCY_MASK) && state->originalMaskImage)
       
   831     {
       
   832         blendMode = (OWF_TRANSPARENCY)(blendMode|OWF_TRANSPARENCY_MASK);
       
   833     }
       
   834 
       
   835     OWF_Image_Blend(&state->blendInfo, blendMode);
       
   836 }