os/graphics/graphicscomposition/openwfcompositionengine/composition/src/wfcscene.c
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)
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:
12 * The above copyright notice and this permission notice shall be included
13 * in all copies or substantial portions of the Materials.
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.
27 * \brief SI Scene graph management functions.
31 #include "wfcstructs.h"
33 #include "wfcelement.h"
34 #include "wfcimageprovider.h"
36 #include "owfmemory.h"
38 #include "owflinkedlist.h"
39 #include "owfobject.h"
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)
50 * \param element Element to destroy
52 static void WFC_Scene_DestroyElement(WFC_ELEMENT* element)
54 /* elements in the working copy are "read only" because
55 * they're shared between the device & the working copy
59 WFC_Element_Destroy(element);
64 WFC_Scene_Destroy(WFC_SCENE* scene)
68 DPRINT(("WFC_Scene_Destroy(%p)", scene));
71 for (node = scene->elements; NULL != node; node = node->next)
73 WFC_Scene_DestroyElement((WFC_ELEMENT*)node->data);
76 scene->elements = OWF_List_Clear(scene->elements);
78 DESTROY(scene->context);
80 OWF_Pool_PutObject(scene);
85 * \brief Append element into scene
88 * \param element Element to add
91 WFC_Scene_AppendElement(WFC_SCENE* scene,
96 /* OBS! No duplicate check here! Use with caution*/
98 node = OWF_Node_Create(CONTEXT(scene->context)->nodePool, element);
99 scene->elements = OWF_List_Append(scene->elements, node);
103 /*----------------------------------------------------------------------------*/
104 OWF_API_CALL WFC_SCENE*
105 WFC_Scene_Clone(WFC_SCENE* scene)
107 WFC_SCENE* cloneScene;
110 cloneScene = WFC_Scene_Create(CONTEXT(scene->context));
112 for (node = scene->elements; NULL != node; node = node->next)
114 WFC_ELEMENT* original;
115 WFC_ELEMENT* cloneElem;
117 original = ELEMENT(node->data);
118 if (WFC_Element_AffectsCompositionResults(original))
120 cloneElem = WFC_Element_Clone(original);
121 WFC_Scene_AppendElement(cloneScene, cloneElem);
128 /*----------------------------------------------------------------------------*/
129 OWF_API_CALL WFC_SCENE*
130 WFC_Scene_Create(WFC_CONTEXT* context)
134 DPRINT(("WFC_Scene_Create"));
138 scene = SCENE(OWF_Pool_GetObject(context->scenePool));
142 ADDREF(scene->context, context);
147 /*----------------------------------------------------------------------------*/
148 OWF_API_CALL WFCErrorCode
149 WFC_Scene_InsertElement(WFC_SCENE* scene,
150 WFC_ELEMENT* element,
151 WFCElement elementBelow)
153 WFCErrorCode result = WFC_ERROR_NONE;
154 OWF_NODE* iter = NULL;
155 OWF_NODE* newPos = NULL;
156 OWF_NODE* oldPos = NULL;
158 if (!scene || !element)
160 return WFC_ERROR_ILLEGAL_ARGUMENT;
163 if (element->handle == (WFCHandle)element)
166 return WFC_ERROR_NONE;
169 newPos = NULL; /*scene->elements;*/
170 for (iter = scene->elements; NULL != iter; iter = iter->next)
172 WFC_ELEMENT* temp = NULL;
174 temp = ELEMENT(iter->data);
176 if (temp->handle == elementBelow)
178 /* insertion point found */
181 if (temp->handle == element->handle)
183 /* already in the scene; relocate */
188 if (newPos && newPos == oldPos) {
189 /* inserting element above self is a no-op */
190 return WFC_ERROR_NONE;
193 if (!newPos && WFC_INVALID_HANDLE != elementBelow)
195 /* could not find elementBelow from the scene */
196 result = WFC_ERROR_ILLEGAL_ARGUMENT;
200 OWF_NODE* newNode = NULL;
202 /* first remove element from its old slot, if already
207 scene->elements = OWF_List_Remove(scene->elements, oldPos);
208 OWF_Node_Destroy(oldPos);
211 /* allocate new node to insert */
212 newNode = OWF_Node_Create(CONTEXT(scene->context)->nodePool, element);
215 /* insert into new position, above elementBelow */
216 OWF_List_InsertAfter(newPos, newNode);
220 /* insert on bottom */
221 scene->elements = OWF_List_Insert(scene->elements, newNode);
225 DPRINT((" Order of the elements (bottom to top): "));
226 for (iter = scene->elements; NULL != iter; iter = iter->next)
228 DPRINT((" %d", ELEMENT(iter->data)->handle));
234 /*----------------------------------------------------------------------------*/
236 WFC_Scene_RemoveElement(WFC_SCENE* scene,
239 OWF_NODE* node = NULL;
241 for (node = scene->elements; NULL != node; node = node->next)
245 etemp = ELEMENT(node->data);
246 if (etemp->handle == element)
248 scene->elements = OWF_List_Remove(scene->elements, node);
249 OWF_Node_Destroy(node);
250 WFC_Scene_DestroyElement(etemp);
255 DPRINT((" Order of the elements (bottom to top): "));
256 for (node = scene->elements; NULL != node; node = node->next)
258 DPRINT((" %d", ELEMENT(node->data)->handle));
262 /*----------------------------------------------------------------------------*/
263 OWF_API_CALL WFC_ELEMENT*
264 WFC_Scene_FindElement(WFC_SCENE* scene,
267 OWF_NODE* node = NULL;
268 WFC_ELEMENT* result = NULL;
270 for (node = scene->elements; NULL != node; node = node->next)
274 etemp = ELEMENT(node->data);
275 if (etemp->handle == element)
284 /*----------------------------------------------------------------------------*/
286 WFC_Scene_LockSourcesAndMasks(WFC_SCENE* scene)
288 OWF_NODE* node = NULL;
290 DPRINT(("WFC_Scene_LockSourcesAndMasks(scene = %p)", scene));
292 for (node = scene->elements; NULL != node; node = node->next)
294 WFC_ELEMENT* element;
296 element = ELEMENT(node->data);
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]));
305 if (WFC_Element_AffectsCompositionResults(element))
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;
317 element->skipCompose = WFC_TRUE;
320 if (!element->skipCompose &&
321 WFC_INVALID_HANDLE != element->maskHandle &&
322 NULL != element->mask)
324 WFC_ImageProvider_LockForReading(element->mask);
325 element->maskComposed = WFC_TRUE;
327 OWF_ASSERT(element->mask);
328 OWF_ASSERT(element->mask->streamHandle);
329 OWF_ASSERT(element->mask->lockedStream.image);
331 if(element->mask->lockedStream.image->data == NULL)
333 WFC_ImageProvider_Unlock(element->source);
334 element->skipCompose = WFC_TRUE;
339 element->maskComposed = WFC_FALSE;
344 /*----------------------------------------------------------------------------*/
346 WFC_Scene_UnlockSourcesAndMasks(WFC_SCENE* scene)
348 OWF_NODE* node = NULL;
350 DPRINT(("WFC_Scene_UnlockSourcesAndMasks(scene = %p)", scene));
352 for (node = scene->elements; NULL != node; node = node->next)
354 WFC_ELEMENT* element;
356 element = ELEMENT(node->data);
358 DPRINT((" Unlocking element %p", element));
359 if (element->source && !element->skipCompose)
361 WFC_ImageProvider_Unlock(element->source);
364 if (element->mask && !element->skipCompose)
366 WFC_ImageProvider_Unlock(element->mask);
371 /*----------------------------------------------------------------------------*/
372 OWF_API_CALL WFCElement
373 WFC_Scene_GetNeighbourElement(WFC_SCENE* scene, WFCElement element, WFCint n)
375 WFCElement result = WFC_INVALID_HANDLE;
376 OWF_NODE* node = NULL;
377 OWF_NODE* prev = NULL;
379 for (node = scene->elements; NULL != node; node = node->next)
383 etemp = ELEMENT(node->data);
384 if (etemp->handle == element)
388 result = prev ? ELEMENT(prev->data)->handle
389 : WFC_INVALID_HANDLE;
393 result = node->next ? ELEMENT(node->next->data)->handle
394 : WFC_INVALID_HANDLE;
404 /*----------------------------------------------------------------------------*/
405 OWF_API_CALL WFCboolean
406 WFC_Scene_HasConflicts(WFC_SCENE* scene)
408 WFCboolean result = WFC_FALSE;
409 OWF_NODE* node = NULL;
411 for (node = scene->elements; NULL != node; node = node->next)
413 WFC_ELEMENT* element;
415 element = ELEMENT(node->data);
417 result = result || WFC_Element_HasConflicts(element) ? WFC_TRUE : WFC_FALSE;
427 /*----------------------------------------------------------------------------*/
429 WFC_Scene_Commit(WFC_SCENE* scene)
433 for (node = scene->elements; NULL != node; node = node->next)
435 WFC_ELEMENT* element;
437 element = ELEMENT(node->data);
438 WFC_Element_Commit(element);
442 /*----------------------------------------------------------------------------*/
443 OWF_API_CALL WFCElement
444 WFC_Scene_LowestElement(WFC_SCENE* scene)
446 WFCElement element = WFC_INVALID_HANDLE;
448 if (scene && scene->elements)
450 element = ELEMENT(scene->elements->data)->handle;
455 /*----------------------------------------------------------------------------*/
456 OWF_API_CALL WFC_ELEMENT*
457 WFC_Scene_TopMostElement(WFC_SCENE* scene)
459 OWF_NODE* node = NULL;
461 for (node = scene->elements; node && node->next; node = node->next)
463 /* All work done in the for statement, so no body */
466 return node ? ELEMENT(node->data) : NULL;