--- /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;
+}