diff -r 000000000000 -r 5d03bc08d59c graphicscomposition/openwfcompositionengine/composition/src/wfcscene.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graphicscomposition/openwfcompositionengine/composition/src/wfcscene.c Tue Feb 02 01:47:50 2010 +0200 @@ -0,0 +1,449 @@ +/* Copyright (c) 2009 The Khronos Group Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and/or associated documentation files (the + * "Materials"), to deal in the Materials without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Materials, and to + * permit persons to whom the Materials are furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Materials. + * + * THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY + * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS. + */ + +/*! \ingroup wfc + * \file wfcscene.c + * + * \brief SI Scene graph management functions. + */ + +#include "WF/wfc.h" +#include "wfcstructs.h" +#include "wfcscene.h" +#include "wfcelement.h" +#include "wfcimageprovider.h" + +#include "owfmemory.h" +#include "owfarray.h" +#include "owflinkedlist.h" +#include "owfobject.h" + +#include "owfdebug.h" + +/*! + * \brief Destroy an element. In case the element is marked as shared, + * this function does nothing. An element is marked as shared, when it is + * inserted into working copy scene. The marked flag is reset when the element + * is removed from the context (i.e. it only resides in the device's + * list of created elements) + * + * \param element Element to destroy + */ +static void WFC_Scene_DestroyElement(WFC_ELEMENT* element) +{ + /* elements in the working copy are "read only" because + * they're shared between the device & the working copy + */ + if (!element->shared) + { + WFC_Element_Destroy(element); + } +} + +OWF_API_CALL void +WFC_Scene_Destroy(WFC_SCENE* scene) +{ + OWF_NODE* node; + + DPRINT(("WFC_Scene_Destroy(%p)", scene)); + if (scene) + { + for (node = scene->elements; NULL != node; node = node->next) + { + WFC_Scene_DestroyElement((WFC_ELEMENT*)node->data); + } + + scene->elements = OWF_List_Clear(scene->elements); + + DESTROY(scene->context); + + OWF_Pool_PutObject(scene); + } +} + +/*! + * \brief Append element into scene + * + * \param scene Scene + * \param element Element to add + */ +static void +WFC_Scene_AppendElement(WFC_SCENE* scene, + WFC_ELEMENT* element) +{ + OWF_NODE* node; + + /* OBS! No duplicate check here! Use with caution*/ + + node = OWF_Node_Create(CONTEXT(scene->context)->nodePool, element); + scene->elements = OWF_List_Append(scene->elements, node); + return ; +} + +/*----------------------------------------------------------------------------*/ +OWF_API_CALL WFC_SCENE* +WFC_Scene_Clone(WFC_SCENE* scene) +{ + WFC_SCENE* cloneScene; + OWF_NODE* node; + + cloneScene = WFC_Scene_Create(CONTEXT(scene->context)); + + for (node = scene->elements; NULL != node; node = node->next) + { + WFC_ELEMENT* original; + WFC_ELEMENT* cloneElem; + + original = ELEMENT(node->data); + if (WFC_Element_AffectsCompositionResults(original)) + { + cloneElem = WFC_Element_Clone(original); + WFC_Scene_AppendElement(cloneScene, cloneElem); + } + } + + return cloneScene; +} + +/*----------------------------------------------------------------------------*/ +OWF_API_CALL WFC_SCENE* +WFC_Scene_Create(WFC_CONTEXT* context) +{ + WFC_SCENE* scene; + + DPRINT(("WFC_Scene_Create")); + scene = SCENE(OWF_Pool_GetObject(context->scenePool)); + + OWF_ASSERT(scene); + + ADDREF(scene->context, context); + + return scene; +} + + /*----------------------------------------------------------------------------*/ +OWF_API_CALL WFCErrorCode +WFC_Scene_InsertElement(WFC_SCENE* scene, + WFC_ELEMENT* element, + WFCElement elementBelow) +{ + WFCErrorCode result = WFC_ERROR_NONE; + OWF_NODE* iter = NULL; + OWF_NODE* newPos = NULL; + OWF_NODE* oldPos = NULL; + + if (!scene || !element) + { + return WFC_ERROR_ILLEGAL_ARGUMENT; + } + + if (element->handle == (WFCHandle)element) + { + /* nothing to do */ + return WFC_ERROR_NONE; + } + + newPos = NULL; /*scene->elements;*/ + for (iter = scene->elements; NULL != iter; iter = iter->next) + { + WFC_ELEMENT* temp = NULL; + + temp = ELEMENT(iter->data); + + if (temp->handle == elementBelow) + { + /* insertion point found */ + newPos = iter; + } + if (temp->handle == element->handle) + { + /* already in the scene; relocate */ + oldPos = iter; + } + } + + if (newPos && newPos == oldPos) { + /* inserting element above self is a no-op */ + return WFC_ERROR_NONE; + } + + if (!newPos && WFC_INVALID_HANDLE != elementBelow) + { + /* could not find elementBelow from the scene */ + result = WFC_ERROR_ILLEGAL_ARGUMENT; + } + else + { + OWF_NODE* newNode = NULL; + + /* first remove element from its old slot, if already + * on the list + */ + if (NULL != oldPos) + { + scene->elements = OWF_List_Remove(scene->elements, oldPos); + OWF_Node_Destroy(oldPos); + } + + /* allocate new node to insert */ + newNode = OWF_Node_Create(CONTEXT(scene->context)->nodePool, element); + if (NULL != newPos) + { + /* insert into new position, above elementBelow */ + OWF_List_InsertAfter(newPos, newNode); + } + else + { + /* insert on bottom */ + scene->elements = OWF_List_Insert(scene->elements, newNode); + } + } + + DPRINT((" Order of the elements (bottom to top): ")); + for (iter = scene->elements; NULL != iter; iter = iter->next) + { + DPRINT((" %d", ELEMENT(iter->data)->handle)); + } + return result; + +} + +/*----------------------------------------------------------------------------*/ +OWF_API_CALL void +WFC_Scene_RemoveElement(WFC_SCENE* scene, + WFCElement element) +{ + OWF_NODE* node = NULL; + + for (node = scene->elements; NULL != node; node = node->next) + { + WFC_ELEMENT* etemp; + + etemp = ELEMENT(node->data); + if (etemp->handle == element) + { + scene->elements = OWF_List_Remove(scene->elements, node); + OWF_Node_Destroy(node); + WFC_Scene_DestroyElement(etemp); + break; + + } + } + DPRINT((" Order of the elements (bottom to top): ")); + for (node = scene->elements; NULL != node; node = node->next) + { + DPRINT((" %d", ELEMENT(node->data)->handle)); + } +} + +/*----------------------------------------------------------------------------*/ +OWF_API_CALL WFC_ELEMENT* +WFC_Scene_FindElement(WFC_SCENE* scene, + WFCElement element) +{ + OWF_NODE* node = NULL; + WFC_ELEMENT* result = NULL; + + for (node = scene->elements; NULL != node; node = node->next) + { + WFC_ELEMENT* etemp; + + etemp = ELEMENT(node->data); + if (etemp->handle == element) + { + result = etemp; + break; + } + } + return result; +} + +/*----------------------------------------------------------------------------*/ +OWF_API_CALL void +WFC_Scene_LockSourcesAndMasks(WFC_SCENE* scene) +{ + OWF_NODE* node = NULL; + + DPRINT(("WFC_Scene_LockSourcesAndMasks(scene = %p)", scene)); + + for (node = scene->elements; NULL != node; node = node->next) + { + WFC_ELEMENT* element; + + element = ELEMENT(node->data); + + DPRINT((" Element source handle = %d", element->sourceHandle)); + DPRINT((" Element source = %p", element->source)); + DPRINT((" Element dest size = %.2fx%.2f", + element->dstRect[2], element->dstRect[3])); + DPRINT((" Element src size = %.2fx%.2f", + element->srcRect[2], element->srcRect[3])); + + if (WFC_Element_AffectsCompositionResults(element)) + { + DPRINT((" Locking element %p", element)); + WFC_ImageProvider_LockForReading(element->source); + /* set the flag so that composition knows to include the + element into composition */ + element->skipCompose = + (element->source->lockedStream.image->data == NULL) ? + WFC_TRUE : WFC_FALSE; + } + else + { + element->skipCompose = WFC_TRUE; + } + + if (!element->skipCompose && + WFC_INVALID_HANDLE != element->maskHandle && + NULL != element->mask) + { + WFC_ImageProvider_LockForReading(element->mask); + element->maskComposed = WFC_TRUE; + + OWF_ASSERT(element->mask); + OWF_ASSERT(element->mask->streamHandle); + OWF_ASSERT(element->mask->lockedStream.image); + + if(element->mask->lockedStream.image->data == NULL) + { + WFC_ImageProvider_Unlock(element->source); + element->skipCompose = WFC_TRUE; + } + } + else + { + element->maskComposed = WFC_FALSE; + } + } +} + +/*----------------------------------------------------------------------------*/ +OWF_API_CALL void +WFC_Scene_UnlockSourcesAndMasks(WFC_SCENE* scene) +{ + OWF_NODE* node = NULL; + + DPRINT(("WFC_Scene_UnlockSourcesAndMasks(scene = %p)", scene)); + + for (node = scene->elements; NULL != node; node = node->next) + { + WFC_ELEMENT* element; + + element = ELEMENT(node->data); + + DPRINT((" Unlocking element %p", element)); + if (element->source && !element->skipCompose) + { + WFC_ImageProvider_Unlock(element->source); + } + + if (element->mask && !element->skipCompose) + { + WFC_ImageProvider_Unlock(element->mask); + } + } +} + +/*----------------------------------------------------------------------------*/ +OWF_API_CALL WFCElement +WFC_Scene_GetNeighbourElement(WFC_SCENE* scene, WFCElement element, WFCint n) +{ + WFCElement result = WFC_INVALID_HANDLE; + OWF_NODE* node = NULL; + OWF_NODE* prev = NULL; + + for (node = scene->elements; NULL != node; node = node->next) + { + WFC_ELEMENT* etemp; + + etemp = ELEMENT(node->data); + if (etemp->handle == element) + { + if (n < 0) + { + result = prev ? ELEMENT(prev->data)->handle + : WFC_INVALID_HANDLE; + } + else + { + result = node->next ? ELEMENT(node->next->data)->handle + : WFC_INVALID_HANDLE; + + } + break; + } + prev = node; + } + return result; +} + +/*----------------------------------------------------------------------------*/ +OWF_API_CALL WFCboolean +WFC_Scene_HasConflicts(WFC_SCENE* scene) +{ + WFCboolean result = WFC_FALSE; + OWF_NODE* node = NULL; + + for (node = scene->elements; NULL != node; node = node->next) + { + WFC_ELEMENT* element; + + element = ELEMENT(node->data); + + result = result || WFC_Element_HasConflicts(element) ? WFC_TRUE : WFC_FALSE; + if (result) + { + /* conflict found */ + break; + } + } + return result; +} + +/*----------------------------------------------------------------------------*/ +OWF_API_CALL void +WFC_Scene_Commit(WFC_SCENE* scene) +{ + OWF_NODE* node; + + for (node = scene->elements; NULL != node; node = node->next) + { + WFC_ELEMENT* element; + + element = ELEMENT(node->data); + WFC_Element_Commit(element); + } +} + +/*----------------------------------------------------------------------------*/ +OWF_API_CALL WFCElement +WFC_Scene_LowestElement(WFC_SCENE* scene) +{ + WFCElement element = WFC_INVALID_HANDLE; + + if (scene && scene->elements) + { + element = ELEMENT(scene->elements->data)->handle; + } + return element; +}