os/graphics/graphicscomposition/openwfcompositionengine/composition/src/wfcscene.c
author sl
Tue, 10 Jun 2014 14:32:02 +0200
changeset 1 260cb5ec6c19
permissions -rw-r--r--
Update contrib.
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 wfcscene.c
sl@0
    26
 *
sl@0
    27
 *  \brief SI Scene graph management functions.
sl@0
    28
 */
sl@0
    29
sl@0
    30
#include "WF/wfc.h"
sl@0
    31
#include "wfcstructs.h"
sl@0
    32
#include "wfcscene.h"
sl@0
    33
#include "wfcelement.h"
sl@0
    34
#include "wfcimageprovider.h"
sl@0
    35
sl@0
    36
#include "owfmemory.h"
sl@0
    37
#include "owfarray.h"
sl@0
    38
#include "owflinkedlist.h"
sl@0
    39
#include "owfobject.h"
sl@0
    40
sl@0
    41
#include "owfdebug.h"
sl@0
    42
sl@0
    43
/*!
sl@0
    44
 *  \brief Destroy an element. In case the element is marked as shared,
sl@0
    45
 *  this function does nothing. An element is marked as shared, when it is
sl@0
    46
 *  inserted into working copy scene. The marked flag is reset when the element
sl@0
    47
 *  is removed from the context (i.e. it only resides in the device's
sl@0
    48
 *  list of created elements)
sl@0
    49
 *
sl@0
    50
 *  \param element          Element to destroy
sl@0
    51
 */
sl@0
    52
static void WFC_Scene_DestroyElement(WFC_ELEMENT* element)
sl@0
    53
{
sl@0
    54
    /* elements in the working copy are "read only" because
sl@0
    55
     * they're shared between the device & the working copy
sl@0
    56
     */
sl@0
    57
    if (!element->shared)
sl@0
    58
    {
sl@0
    59
        WFC_Element_Destroy(element);
sl@0
    60
    }
sl@0
    61
}
sl@0
    62
sl@0
    63
OWF_API_CALL void
sl@0
    64
WFC_Scene_Destroy(WFC_SCENE* scene)
sl@0
    65
{
sl@0
    66
    OWF_NODE*               node;
sl@0
    67
sl@0
    68
    DPRINT(("WFC_Scene_Destroy(%p)", scene));
sl@0
    69
    if (scene)
sl@0
    70
    {
sl@0
    71
        for (node = scene->elements; NULL != node; node = node->next)
sl@0
    72
        {
sl@0
    73
            WFC_Scene_DestroyElement((WFC_ELEMENT*)node->data);
sl@0
    74
        }
sl@0
    75
sl@0
    76
        scene->elements = OWF_List_Clear(scene->elements);
sl@0
    77
sl@0
    78
        DESTROY(scene->context);
sl@0
    79
sl@0
    80
        OWF_Pool_PutObject(scene);
sl@0
    81
    }
sl@0
    82
}
sl@0
    83
sl@0
    84
/*!
sl@0
    85
 *  \brief Append element into scene
sl@0
    86
 *
sl@0
    87
 *  \param scene            Scene
sl@0
    88
 *  \param element          Element to add
sl@0
    89
 */
sl@0
    90
static void
sl@0
    91
WFC_Scene_AppendElement(WFC_SCENE* scene,
sl@0
    92
                        WFC_ELEMENT* element)
sl@0
    93
{
sl@0
    94
    OWF_NODE*               node;
sl@0
    95
sl@0
    96
    /* OBS! No duplicate check here! Use with caution*/
sl@0
    97
sl@0
    98
    node = OWF_Node_Create(CONTEXT(scene->context)->nodePool, element);
sl@0
    99
    scene->elements = OWF_List_Append(scene->elements, node);
sl@0
   100
    return ;
sl@0
   101
}
sl@0
   102
sl@0
   103
/*----------------------------------------------------------------------------*/
sl@0
   104
OWF_API_CALL WFC_SCENE*
sl@0
   105
WFC_Scene_Clone(WFC_SCENE* scene)
sl@0
   106
{
sl@0
   107
    WFC_SCENE*              cloneScene;
sl@0
   108
    OWF_NODE*               node;
sl@0
   109
sl@0
   110
    cloneScene = WFC_Scene_Create(CONTEXT(scene->context));
sl@0
   111
sl@0
   112
    for (node = scene->elements; NULL != node; node = node->next)
sl@0
   113
    {
sl@0
   114
        WFC_ELEMENT* original;
sl@0
   115
        WFC_ELEMENT* cloneElem;
sl@0
   116
sl@0
   117
        original = ELEMENT(node->data);
sl@0
   118
        if (WFC_Element_AffectsCompositionResults(original))
sl@0
   119
            {
sl@0
   120
            cloneElem = WFC_Element_Clone(original);
sl@0
   121
            WFC_Scene_AppendElement(cloneScene, cloneElem);
sl@0
   122
            }
sl@0
   123
    }
sl@0
   124
sl@0
   125
    return cloneScene;
sl@0
   126
}
sl@0
   127
sl@0
   128
/*----------------------------------------------------------------------------*/
sl@0
   129
OWF_API_CALL WFC_SCENE*
sl@0
   130
WFC_Scene_Create(WFC_CONTEXT* context)
sl@0
   131
{
sl@0
   132
    WFC_SCENE*              scene;
sl@0
   133
	
sl@0
   134
	DPRINT(("WFC_Scene_Create"));
sl@0
   135
	
sl@0
   136
	OWF_ASSERT(context);
sl@0
   137
	
sl@0
   138
    scene = SCENE(OWF_Pool_GetObject(context->scenePool));
sl@0
   139
sl@0
   140
    OWF_ASSERT(scene);
sl@0
   141
sl@0
   142
    ADDREF(scene->context, context);
sl@0
   143
sl@0
   144
    return scene;
sl@0
   145
}
sl@0
   146
sl@0
   147
 /*----------------------------------------------------------------------------*/
sl@0
   148
OWF_API_CALL WFCErrorCode
sl@0
   149
WFC_Scene_InsertElement(WFC_SCENE* scene,
sl@0
   150
                        WFC_ELEMENT* element,
sl@0
   151
                        WFCElement elementBelow)
sl@0
   152
{
sl@0
   153
    WFCErrorCode            result = WFC_ERROR_NONE;
sl@0
   154
    OWF_NODE*               iter = NULL;
sl@0
   155
    OWF_NODE*               newPos = NULL;
sl@0
   156
    OWF_NODE*               oldPos = NULL;
sl@0
   157
sl@0
   158
    if (!scene || !element)
sl@0
   159
    {
sl@0
   160
        return WFC_ERROR_ILLEGAL_ARGUMENT;
sl@0
   161
    }
sl@0
   162
sl@0
   163
    if (element->handle == (WFCHandle)element)
sl@0
   164
    {
sl@0
   165
        /* nothing to do */
sl@0
   166
        return WFC_ERROR_NONE;
sl@0
   167
    }
sl@0
   168
sl@0
   169
    newPos = NULL; /*scene->elements;*/
sl@0
   170
    for (iter = scene->elements; NULL != iter; iter = iter->next)
sl@0
   171
    {
sl@0
   172
        WFC_ELEMENT*        temp = NULL;
sl@0
   173
sl@0
   174
        temp = ELEMENT(iter->data);
sl@0
   175
sl@0
   176
        if (temp->handle == elementBelow)
sl@0
   177
        {
sl@0
   178
            /* insertion point found */
sl@0
   179
            newPos = iter;
sl@0
   180
        }
sl@0
   181
        if (temp->handle == element->handle)
sl@0
   182
        {
sl@0
   183
            /* already in the scene; relocate */
sl@0
   184
            oldPos = iter;
sl@0
   185
        }
sl@0
   186
    }
sl@0
   187
sl@0
   188
    if (newPos && newPos == oldPos) {
sl@0
   189
        /* inserting element above self is a no-op */
sl@0
   190
        return WFC_ERROR_NONE;
sl@0
   191
    }
sl@0
   192
sl@0
   193
    if (!newPos && WFC_INVALID_HANDLE != elementBelow)
sl@0
   194
    {
sl@0
   195
        /* could not find elementBelow from the scene */
sl@0
   196
        result = WFC_ERROR_ILLEGAL_ARGUMENT;
sl@0
   197
    }
sl@0
   198
    else
sl@0
   199
    {
sl@0
   200
        OWF_NODE*           newNode = NULL;
sl@0
   201
sl@0
   202
        /* first remove element from its old slot, if already
sl@0
   203
         * on the list
sl@0
   204
         */
sl@0
   205
        if (NULL != oldPos)
sl@0
   206
        {
sl@0
   207
            scene->elements = OWF_List_Remove(scene->elements, oldPos);
sl@0
   208
            OWF_Node_Destroy(oldPos);
sl@0
   209
        }
sl@0
   210
sl@0
   211
        /* allocate new node to insert */
sl@0
   212
        newNode = OWF_Node_Create(CONTEXT(scene->context)->nodePool, element);
sl@0
   213
        if (NULL != newPos)
sl@0
   214
        {
sl@0
   215
            /* insert into new position, above elementBelow */
sl@0
   216
            OWF_List_InsertAfter(newPos, newNode);
sl@0
   217
        }
sl@0
   218
        else
sl@0
   219
        {
sl@0
   220
            /* insert on bottom */
sl@0
   221
            scene->elements = OWF_List_Insert(scene->elements, newNode);
sl@0
   222
        }
sl@0
   223
    }
sl@0
   224
sl@0
   225
    DPRINT(("  Order of the elements (bottom to top): "));
sl@0
   226
    for (iter = scene->elements; NULL != iter; iter = iter->next)
sl@0
   227
    {
sl@0
   228
        DPRINT(("    %d", ELEMENT(iter->data)->handle));
sl@0
   229
    }
sl@0
   230
    return result;
sl@0
   231
sl@0
   232
}
sl@0
   233
sl@0
   234
/*----------------------------------------------------------------------------*/
sl@0
   235
OWF_API_CALL void
sl@0
   236
WFC_Scene_RemoveElement(WFC_SCENE* scene,
sl@0
   237
                        WFCElement element)
sl@0
   238
{
sl@0
   239
    OWF_NODE*               node = NULL;
sl@0
   240
sl@0
   241
    for (node = scene->elements; NULL != node; node = node->next)
sl@0
   242
    {
sl@0
   243
        WFC_ELEMENT*        etemp;
sl@0
   244
sl@0
   245
        etemp = ELEMENT(node->data);
sl@0
   246
        if (etemp->handle == element)
sl@0
   247
        {
sl@0
   248
            scene->elements = OWF_List_Remove(scene->elements, node);
sl@0
   249
            OWF_Node_Destroy(node);
sl@0
   250
            WFC_Scene_DestroyElement(etemp);
sl@0
   251
            break;
sl@0
   252
sl@0
   253
        }
sl@0
   254
    }
sl@0
   255
    DPRINT(("  Order of the elements (bottom to top): "));
sl@0
   256
    for (node = scene->elements; NULL != node; node = node->next)
sl@0
   257
    {
sl@0
   258
        DPRINT(("    %d", ELEMENT(node->data)->handle));
sl@0
   259
    }
sl@0
   260
}
sl@0
   261
sl@0
   262
/*----------------------------------------------------------------------------*/
sl@0
   263
OWF_API_CALL WFC_ELEMENT*
sl@0
   264
WFC_Scene_FindElement(WFC_SCENE* scene,
sl@0
   265
                      WFCElement element)
sl@0
   266
{
sl@0
   267
    OWF_NODE*               node = NULL;
sl@0
   268
    WFC_ELEMENT*            result = NULL;
sl@0
   269
sl@0
   270
    for (node = scene->elements; NULL != node; node = node->next)
sl@0
   271
    {
sl@0
   272
        WFC_ELEMENT*        etemp;
sl@0
   273
sl@0
   274
        etemp = ELEMENT(node->data);
sl@0
   275
        if (etemp->handle == element)
sl@0
   276
        {
sl@0
   277
            result = etemp;
sl@0
   278
            break;
sl@0
   279
        }
sl@0
   280
    }
sl@0
   281
    return result;
sl@0
   282
}
sl@0
   283
sl@0
   284
/*----------------------------------------------------------------------------*/
sl@0
   285
OWF_API_CALL void
sl@0
   286
WFC_Scene_LockSourcesAndMasks(WFC_SCENE* scene)
sl@0
   287
{
sl@0
   288
    OWF_NODE*               node = NULL;
sl@0
   289
sl@0
   290
    DPRINT(("WFC_Scene_LockSourcesAndMasks(scene = %p)", scene));
sl@0
   291
sl@0
   292
    for (node = scene->elements; NULL != node; node = node->next)
sl@0
   293
    {
sl@0
   294
        WFC_ELEMENT*        element;
sl@0
   295
        
sl@0
   296
        element = ELEMENT(node->data);
sl@0
   297
sl@0
   298
        DPRINT(("  Element source handle = %d", element->sourceHandle));
sl@0
   299
        DPRINT(("  Element source = %p", element->source));
sl@0
   300
        DPRINT(("  Element dest size = %.2fx%.2f",
sl@0
   301
                element->dstRect[2], element->dstRect[3]));
sl@0
   302
        DPRINT(("  Element src size = %.2fx%.2f",
sl@0
   303
                element->srcRect[2], element->srcRect[3]));
sl@0
   304
sl@0
   305
        if (WFC_Element_AffectsCompositionResults(element))
sl@0
   306
         {
sl@0
   307
            DPRINT(("  Locking element %p", element));
sl@0
   308
            WFC_ImageProvider_LockForReading(element->source);
sl@0
   309
            /* set the flag so that composition knows to include the
sl@0
   310
               element into composition */
sl@0
   311
            element->skipCompose =
sl@0
   312
                (element->source->lockedStream.image->data == NULL) ?
sl@0
   313
                        WFC_TRUE : WFC_FALSE;
sl@0
   314
        }
sl@0
   315
        else
sl@0
   316
        {
sl@0
   317
            element->skipCompose = WFC_TRUE;
sl@0
   318
        }
sl@0
   319
sl@0
   320
        if (!element->skipCompose &&
sl@0
   321
            WFC_INVALID_HANDLE != element->maskHandle &&
sl@0
   322
            NULL != element->mask)
sl@0
   323
        {
sl@0
   324
            WFC_ImageProvider_LockForReading(element->mask);
sl@0
   325
            element->maskComposed = WFC_TRUE;
sl@0
   326
sl@0
   327
            OWF_ASSERT(element->mask);
sl@0
   328
            OWF_ASSERT(element->mask->streamHandle);
sl@0
   329
            OWF_ASSERT(element->mask->lockedStream.image);
sl@0
   330
sl@0
   331
             if(element->mask->lockedStream.image->data == NULL)
sl@0
   332
             {
sl@0
   333
                    WFC_ImageProvider_Unlock(element->source);
sl@0
   334
                    element->skipCompose = WFC_TRUE;
sl@0
   335
             }
sl@0
   336
        }
sl@0
   337
        else
sl@0
   338
        {
sl@0
   339
            element->maskComposed = WFC_FALSE;
sl@0
   340
        }
sl@0
   341
    }
sl@0
   342
}
sl@0
   343
sl@0
   344
/*----------------------------------------------------------------------------*/
sl@0
   345
OWF_API_CALL void
sl@0
   346
WFC_Scene_UnlockSourcesAndMasks(WFC_SCENE* scene)
sl@0
   347
{
sl@0
   348
    OWF_NODE*               node = NULL;
sl@0
   349
sl@0
   350
    DPRINT(("WFC_Scene_UnlockSourcesAndMasks(scene = %p)", scene));
sl@0
   351
sl@0
   352
    for (node = scene->elements; NULL != node; node = node->next)
sl@0
   353
    {
sl@0
   354
        WFC_ELEMENT*        element;
sl@0
   355
sl@0
   356
        element = ELEMENT(node->data);
sl@0
   357
sl@0
   358
        DPRINT(("  Unlocking element %p", element));
sl@0
   359
        if (element->source && !element->skipCompose)
sl@0
   360
        {
sl@0
   361
            WFC_ImageProvider_Unlock(element->source);
sl@0
   362
        }
sl@0
   363
sl@0
   364
        if (element->mask && !element->skipCompose)
sl@0
   365
        {
sl@0
   366
            WFC_ImageProvider_Unlock(element->mask);
sl@0
   367
        }
sl@0
   368
    }
sl@0
   369
}
sl@0
   370
sl@0
   371
/*----------------------------------------------------------------------------*/
sl@0
   372
OWF_API_CALL WFCElement
sl@0
   373
WFC_Scene_GetNeighbourElement(WFC_SCENE* scene, WFCElement element, WFCint n)
sl@0
   374
{
sl@0
   375
    WFCElement              result = WFC_INVALID_HANDLE;
sl@0
   376
    OWF_NODE*               node = NULL;
sl@0
   377
    OWF_NODE*               prev = NULL;
sl@0
   378
sl@0
   379
    for (node = scene->elements; NULL != node; node = node->next)
sl@0
   380
    {
sl@0
   381
        WFC_ELEMENT*        etemp;
sl@0
   382
sl@0
   383
        etemp = ELEMENT(node->data);
sl@0
   384
        if (etemp->handle == element)
sl@0
   385
        {
sl@0
   386
            if (n < 0)
sl@0
   387
            {
sl@0
   388
                result = prev ? ELEMENT(prev->data)->handle
sl@0
   389
                              : WFC_INVALID_HANDLE;
sl@0
   390
            }
sl@0
   391
            else
sl@0
   392
            {
sl@0
   393
                result = node->next ? ELEMENT(node->next->data)->handle
sl@0
   394
                                    : WFC_INVALID_HANDLE;
sl@0
   395
sl@0
   396
            }
sl@0
   397
            break;
sl@0
   398
        }
sl@0
   399
        prev = node;
sl@0
   400
    }
sl@0
   401
    return result;
sl@0
   402
}
sl@0
   403
sl@0
   404
/*----------------------------------------------------------------------------*/
sl@0
   405
OWF_API_CALL WFCboolean
sl@0
   406
WFC_Scene_HasConflicts(WFC_SCENE* scene)
sl@0
   407
{
sl@0
   408
    WFCboolean              result = WFC_FALSE;
sl@0
   409
    OWF_NODE*               node = NULL;
sl@0
   410
sl@0
   411
    for (node = scene->elements; NULL != node; node = node->next)
sl@0
   412
    {
sl@0
   413
        WFC_ELEMENT*        element;
sl@0
   414
sl@0
   415
        element = ELEMENT(node->data);
sl@0
   416
sl@0
   417
        result = result || WFC_Element_HasConflicts(element) ? WFC_TRUE : WFC_FALSE;
sl@0
   418
        if (result)
sl@0
   419
        {
sl@0
   420
            /* conflict found */
sl@0
   421
            break;
sl@0
   422
        }
sl@0
   423
    }
sl@0
   424
    return result;
sl@0
   425
}
sl@0
   426
sl@0
   427
/*----------------------------------------------------------------------------*/
sl@0
   428
OWF_API_CALL void
sl@0
   429
WFC_Scene_Commit(WFC_SCENE* scene)
sl@0
   430
{
sl@0
   431
    OWF_NODE*               node;
sl@0
   432
sl@0
   433
    for (node = scene->elements; NULL != node; node = node->next)
sl@0
   434
    {
sl@0
   435
        WFC_ELEMENT*        element;
sl@0
   436
sl@0
   437
        element = ELEMENT(node->data);
sl@0
   438
        WFC_Element_Commit(element);
sl@0
   439
    }
sl@0
   440
}
sl@0
   441
sl@0
   442
/*----------------------------------------------------------------------------*/
sl@0
   443
OWF_API_CALL WFCElement
sl@0
   444
WFC_Scene_LowestElement(WFC_SCENE* scene)
sl@0
   445
{
sl@0
   446
    WFCElement              element = WFC_INVALID_HANDLE;
sl@0
   447
sl@0
   448
    if (scene && scene->elements)
sl@0
   449
    {
sl@0
   450
        element = ELEMENT(scene->elements->data)->handle;
sl@0
   451
    }
sl@0
   452
    return element;
sl@0
   453
}
sl@0
   454
sl@0
   455
/*----------------------------------------------------------------------------*/
sl@0
   456
OWF_API_CALL WFC_ELEMENT*
sl@0
   457
WFC_Scene_TopMostElement(WFC_SCENE* scene)
sl@0
   458
{
sl@0
   459
    OWF_NODE*               node = NULL;
sl@0
   460
sl@0
   461
    for (node = scene->elements; node && node->next; node = node->next)
sl@0
   462
    {
sl@0
   463
        /* All work done in the for statement, so no body */
sl@0
   464
    }
sl@0
   465
    
sl@0
   466
    return node ? ELEMENT(node->data) : NULL;
sl@0
   467
}