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