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