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