os/graphics/graphicscomposition/openwfcompositionengine/composition/src/wfcscene.c
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/os/graphics/graphicscomposition/openwfcompositionengine/composition/src/wfcscene.c Fri Jun 15 03:10:57 2012 +0200
1.3 @@ -0,0 +1,467 @@
1.4 +/* Copyright (c) 2009-2010 The Khronos Group Inc.
1.5 + * Portions copyright (c) 2009-2010 Nokia Corporation and/or its subsidiary(-ies)
1.6 + *
1.7 + * Permission is hereby granted, free of charge, to any person obtaining a
1.8 + * copy of this software and/or associated documentation files (the
1.9 + * "Materials"), to deal in the Materials without restriction, including
1.10 + * without limitation the rights to use, copy, modify, merge, publish,
1.11 + * distribute, sublicense, and/or sell copies of the Materials, and to
1.12 + * permit persons to whom the Materials are furnished to do so, subject to
1.13 + * the following conditions:
1.14 + *
1.15 + * The above copyright notice and this permission notice shall be included
1.16 + * in all copies or substantial portions of the Materials.
1.17 + *
1.18 + * THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
1.19 + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
1.20 + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
1.21 + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
1.22 + * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
1.23 + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
1.24 + * MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
1.25 + */
1.26 +
1.27 +/*! \ingroup wfc
1.28 + * \file wfcscene.c
1.29 + *
1.30 + * \brief SI Scene graph management functions.
1.31 + */
1.32 +
1.33 +#include "WF/wfc.h"
1.34 +#include "wfcstructs.h"
1.35 +#include "wfcscene.h"
1.36 +#include "wfcelement.h"
1.37 +#include "wfcimageprovider.h"
1.38 +
1.39 +#include "owfmemory.h"
1.40 +#include "owfarray.h"
1.41 +#include "owflinkedlist.h"
1.42 +#include "owfobject.h"
1.43 +
1.44 +#include "owfdebug.h"
1.45 +
1.46 +/*!
1.47 + * \brief Destroy an element. In case the element is marked as shared,
1.48 + * this function does nothing. An element is marked as shared, when it is
1.49 + * inserted into working copy scene. The marked flag is reset when the element
1.50 + * is removed from the context (i.e. it only resides in the device's
1.51 + * list of created elements)
1.52 + *
1.53 + * \param element Element to destroy
1.54 + */
1.55 +static void WFC_Scene_DestroyElement(WFC_ELEMENT* element)
1.56 +{
1.57 + /* elements in the working copy are "read only" because
1.58 + * they're shared between the device & the working copy
1.59 + */
1.60 + if (!element->shared)
1.61 + {
1.62 + WFC_Element_Destroy(element);
1.63 + }
1.64 +}
1.65 +
1.66 +OWF_API_CALL void
1.67 +WFC_Scene_Destroy(WFC_SCENE* scene)
1.68 +{
1.69 + OWF_NODE* node;
1.70 +
1.71 + DPRINT(("WFC_Scene_Destroy(%p)", scene));
1.72 + if (scene)
1.73 + {
1.74 + for (node = scene->elements; NULL != node; node = node->next)
1.75 + {
1.76 + WFC_Scene_DestroyElement((WFC_ELEMENT*)node->data);
1.77 + }
1.78 +
1.79 + scene->elements = OWF_List_Clear(scene->elements);
1.80 +
1.81 + DESTROY(scene->context);
1.82 +
1.83 + OWF_Pool_PutObject(scene);
1.84 + }
1.85 +}
1.86 +
1.87 +/*!
1.88 + * \brief Append element into scene
1.89 + *
1.90 + * \param scene Scene
1.91 + * \param element Element to add
1.92 + */
1.93 +static void
1.94 +WFC_Scene_AppendElement(WFC_SCENE* scene,
1.95 + WFC_ELEMENT* element)
1.96 +{
1.97 + OWF_NODE* node;
1.98 +
1.99 + /* OBS! No duplicate check here! Use with caution*/
1.100 +
1.101 + node = OWF_Node_Create(CONTEXT(scene->context)->nodePool, element);
1.102 + scene->elements = OWF_List_Append(scene->elements, node);
1.103 + return ;
1.104 +}
1.105 +
1.106 +/*----------------------------------------------------------------------------*/
1.107 +OWF_API_CALL WFC_SCENE*
1.108 +WFC_Scene_Clone(WFC_SCENE* scene)
1.109 +{
1.110 + WFC_SCENE* cloneScene;
1.111 + OWF_NODE* node;
1.112 +
1.113 + cloneScene = WFC_Scene_Create(CONTEXT(scene->context));
1.114 +
1.115 + for (node = scene->elements; NULL != node; node = node->next)
1.116 + {
1.117 + WFC_ELEMENT* original;
1.118 + WFC_ELEMENT* cloneElem;
1.119 +
1.120 + original = ELEMENT(node->data);
1.121 + if (WFC_Element_AffectsCompositionResults(original))
1.122 + {
1.123 + cloneElem = WFC_Element_Clone(original);
1.124 + WFC_Scene_AppendElement(cloneScene, cloneElem);
1.125 + }
1.126 + }
1.127 +
1.128 + return cloneScene;
1.129 +}
1.130 +
1.131 +/*----------------------------------------------------------------------------*/
1.132 +OWF_API_CALL WFC_SCENE*
1.133 +WFC_Scene_Create(WFC_CONTEXT* context)
1.134 +{
1.135 + WFC_SCENE* scene;
1.136 +
1.137 + DPRINT(("WFC_Scene_Create"));
1.138 +
1.139 + OWF_ASSERT(context);
1.140 +
1.141 + scene = SCENE(OWF_Pool_GetObject(context->scenePool));
1.142 +
1.143 + OWF_ASSERT(scene);
1.144 +
1.145 + ADDREF(scene->context, context);
1.146 +
1.147 + return scene;
1.148 +}
1.149 +
1.150 + /*----------------------------------------------------------------------------*/
1.151 +OWF_API_CALL WFCErrorCode
1.152 +WFC_Scene_InsertElement(WFC_SCENE* scene,
1.153 + WFC_ELEMENT* element,
1.154 + WFCElement elementBelow)
1.155 +{
1.156 + WFCErrorCode result = WFC_ERROR_NONE;
1.157 + OWF_NODE* iter = NULL;
1.158 + OWF_NODE* newPos = NULL;
1.159 + OWF_NODE* oldPos = NULL;
1.160 +
1.161 + if (!scene || !element)
1.162 + {
1.163 + return WFC_ERROR_ILLEGAL_ARGUMENT;
1.164 + }
1.165 +
1.166 + if (element->handle == (WFCHandle)element)
1.167 + {
1.168 + /* nothing to do */
1.169 + return WFC_ERROR_NONE;
1.170 + }
1.171 +
1.172 + newPos = NULL; /*scene->elements;*/
1.173 + for (iter = scene->elements; NULL != iter; iter = iter->next)
1.174 + {
1.175 + WFC_ELEMENT* temp = NULL;
1.176 +
1.177 + temp = ELEMENT(iter->data);
1.178 +
1.179 + if (temp->handle == elementBelow)
1.180 + {
1.181 + /* insertion point found */
1.182 + newPos = iter;
1.183 + }
1.184 + if (temp->handle == element->handle)
1.185 + {
1.186 + /* already in the scene; relocate */
1.187 + oldPos = iter;
1.188 + }
1.189 + }
1.190 +
1.191 + if (newPos && newPos == oldPos) {
1.192 + /* inserting element above self is a no-op */
1.193 + return WFC_ERROR_NONE;
1.194 + }
1.195 +
1.196 + if (!newPos && WFC_INVALID_HANDLE != elementBelow)
1.197 + {
1.198 + /* could not find elementBelow from the scene */
1.199 + result = WFC_ERROR_ILLEGAL_ARGUMENT;
1.200 + }
1.201 + else
1.202 + {
1.203 + OWF_NODE* newNode = NULL;
1.204 +
1.205 + /* first remove element from its old slot, if already
1.206 + * on the list
1.207 + */
1.208 + if (NULL != oldPos)
1.209 + {
1.210 + scene->elements = OWF_List_Remove(scene->elements, oldPos);
1.211 + OWF_Node_Destroy(oldPos);
1.212 + }
1.213 +
1.214 + /* allocate new node to insert */
1.215 + newNode = OWF_Node_Create(CONTEXT(scene->context)->nodePool, element);
1.216 + if (NULL != newPos)
1.217 + {
1.218 + /* insert into new position, above elementBelow */
1.219 + OWF_List_InsertAfter(newPos, newNode);
1.220 + }
1.221 + else
1.222 + {
1.223 + /* insert on bottom */
1.224 + scene->elements = OWF_List_Insert(scene->elements, newNode);
1.225 + }
1.226 + }
1.227 +
1.228 + DPRINT((" Order of the elements (bottom to top): "));
1.229 + for (iter = scene->elements; NULL != iter; iter = iter->next)
1.230 + {
1.231 + DPRINT((" %d", ELEMENT(iter->data)->handle));
1.232 + }
1.233 + return result;
1.234 +
1.235 +}
1.236 +
1.237 +/*----------------------------------------------------------------------------*/
1.238 +OWF_API_CALL void
1.239 +WFC_Scene_RemoveElement(WFC_SCENE* scene,
1.240 + WFCElement element)
1.241 +{
1.242 + OWF_NODE* node = NULL;
1.243 +
1.244 + for (node = scene->elements; NULL != node; node = node->next)
1.245 + {
1.246 + WFC_ELEMENT* etemp;
1.247 +
1.248 + etemp = ELEMENT(node->data);
1.249 + if (etemp->handle == element)
1.250 + {
1.251 + scene->elements = OWF_List_Remove(scene->elements, node);
1.252 + OWF_Node_Destroy(node);
1.253 + WFC_Scene_DestroyElement(etemp);
1.254 + break;
1.255 +
1.256 + }
1.257 + }
1.258 + DPRINT((" Order of the elements (bottom to top): "));
1.259 + for (node = scene->elements; NULL != node; node = node->next)
1.260 + {
1.261 + DPRINT((" %d", ELEMENT(node->data)->handle));
1.262 + }
1.263 +}
1.264 +
1.265 +/*----------------------------------------------------------------------------*/
1.266 +OWF_API_CALL WFC_ELEMENT*
1.267 +WFC_Scene_FindElement(WFC_SCENE* scene,
1.268 + WFCElement element)
1.269 +{
1.270 + OWF_NODE* node = NULL;
1.271 + WFC_ELEMENT* result = NULL;
1.272 +
1.273 + for (node = scene->elements; NULL != node; node = node->next)
1.274 + {
1.275 + WFC_ELEMENT* etemp;
1.276 +
1.277 + etemp = ELEMENT(node->data);
1.278 + if (etemp->handle == element)
1.279 + {
1.280 + result = etemp;
1.281 + break;
1.282 + }
1.283 + }
1.284 + return result;
1.285 +}
1.286 +
1.287 +/*----------------------------------------------------------------------------*/
1.288 +OWF_API_CALL void
1.289 +WFC_Scene_LockSourcesAndMasks(WFC_SCENE* scene)
1.290 +{
1.291 + OWF_NODE* node = NULL;
1.292 +
1.293 + DPRINT(("WFC_Scene_LockSourcesAndMasks(scene = %p)", scene));
1.294 +
1.295 + for (node = scene->elements; NULL != node; node = node->next)
1.296 + {
1.297 + WFC_ELEMENT* element;
1.298 +
1.299 + element = ELEMENT(node->data);
1.300 +
1.301 + DPRINT((" Element source handle = %d", element->sourceHandle));
1.302 + DPRINT((" Element source = %p", element->source));
1.303 + DPRINT((" Element dest size = %.2fx%.2f",
1.304 + element->dstRect[2], element->dstRect[3]));
1.305 + DPRINT((" Element src size = %.2fx%.2f",
1.306 + element->srcRect[2], element->srcRect[3]));
1.307 +
1.308 + if (WFC_Element_AffectsCompositionResults(element))
1.309 + {
1.310 + DPRINT((" Locking element %p", element));
1.311 + WFC_ImageProvider_LockForReading(element->source);
1.312 + /* set the flag so that composition knows to include the
1.313 + element into composition */
1.314 + element->skipCompose =
1.315 + (element->source->lockedStream.image->data == NULL) ?
1.316 + WFC_TRUE : WFC_FALSE;
1.317 + }
1.318 + else
1.319 + {
1.320 + element->skipCompose = WFC_TRUE;
1.321 + }
1.322 +
1.323 + if (!element->skipCompose &&
1.324 + WFC_INVALID_HANDLE != element->maskHandle &&
1.325 + NULL != element->mask)
1.326 + {
1.327 + WFC_ImageProvider_LockForReading(element->mask);
1.328 + element->maskComposed = WFC_TRUE;
1.329 +
1.330 + OWF_ASSERT(element->mask);
1.331 + OWF_ASSERT(element->mask->streamHandle);
1.332 + OWF_ASSERT(element->mask->lockedStream.image);
1.333 +
1.334 + if(element->mask->lockedStream.image->data == NULL)
1.335 + {
1.336 + WFC_ImageProvider_Unlock(element->source);
1.337 + element->skipCompose = WFC_TRUE;
1.338 + }
1.339 + }
1.340 + else
1.341 + {
1.342 + element->maskComposed = WFC_FALSE;
1.343 + }
1.344 + }
1.345 +}
1.346 +
1.347 +/*----------------------------------------------------------------------------*/
1.348 +OWF_API_CALL void
1.349 +WFC_Scene_UnlockSourcesAndMasks(WFC_SCENE* scene)
1.350 +{
1.351 + OWF_NODE* node = NULL;
1.352 +
1.353 + DPRINT(("WFC_Scene_UnlockSourcesAndMasks(scene = %p)", scene));
1.354 +
1.355 + for (node = scene->elements; NULL != node; node = node->next)
1.356 + {
1.357 + WFC_ELEMENT* element;
1.358 +
1.359 + element = ELEMENT(node->data);
1.360 +
1.361 + DPRINT((" Unlocking element %p", element));
1.362 + if (element->source && !element->skipCompose)
1.363 + {
1.364 + WFC_ImageProvider_Unlock(element->source);
1.365 + }
1.366 +
1.367 + if (element->mask && !element->skipCompose)
1.368 + {
1.369 + WFC_ImageProvider_Unlock(element->mask);
1.370 + }
1.371 + }
1.372 +}
1.373 +
1.374 +/*----------------------------------------------------------------------------*/
1.375 +OWF_API_CALL WFCElement
1.376 +WFC_Scene_GetNeighbourElement(WFC_SCENE* scene, WFCElement element, WFCint n)
1.377 +{
1.378 + WFCElement result = WFC_INVALID_HANDLE;
1.379 + OWF_NODE* node = NULL;
1.380 + OWF_NODE* prev = NULL;
1.381 +
1.382 + for (node = scene->elements; NULL != node; node = node->next)
1.383 + {
1.384 + WFC_ELEMENT* etemp;
1.385 +
1.386 + etemp = ELEMENT(node->data);
1.387 + if (etemp->handle == element)
1.388 + {
1.389 + if (n < 0)
1.390 + {
1.391 + result = prev ? ELEMENT(prev->data)->handle
1.392 + : WFC_INVALID_HANDLE;
1.393 + }
1.394 + else
1.395 + {
1.396 + result = node->next ? ELEMENT(node->next->data)->handle
1.397 + : WFC_INVALID_HANDLE;
1.398 +
1.399 + }
1.400 + break;
1.401 + }
1.402 + prev = node;
1.403 + }
1.404 + return result;
1.405 +}
1.406 +
1.407 +/*----------------------------------------------------------------------------*/
1.408 +OWF_API_CALL WFCboolean
1.409 +WFC_Scene_HasConflicts(WFC_SCENE* scene)
1.410 +{
1.411 + WFCboolean result = WFC_FALSE;
1.412 + OWF_NODE* node = NULL;
1.413 +
1.414 + for (node = scene->elements; NULL != node; node = node->next)
1.415 + {
1.416 + WFC_ELEMENT* element;
1.417 +
1.418 + element = ELEMENT(node->data);
1.419 +
1.420 + result = result || WFC_Element_HasConflicts(element) ? WFC_TRUE : WFC_FALSE;
1.421 + if (result)
1.422 + {
1.423 + /* conflict found */
1.424 + break;
1.425 + }
1.426 + }
1.427 + return result;
1.428 +}
1.429 +
1.430 +/*----------------------------------------------------------------------------*/
1.431 +OWF_API_CALL void
1.432 +WFC_Scene_Commit(WFC_SCENE* scene)
1.433 +{
1.434 + OWF_NODE* node;
1.435 +
1.436 + for (node = scene->elements; NULL != node; node = node->next)
1.437 + {
1.438 + WFC_ELEMENT* element;
1.439 +
1.440 + element = ELEMENT(node->data);
1.441 + WFC_Element_Commit(element);
1.442 + }
1.443 +}
1.444 +
1.445 +/*----------------------------------------------------------------------------*/
1.446 +OWF_API_CALL WFCElement
1.447 +WFC_Scene_LowestElement(WFC_SCENE* scene)
1.448 +{
1.449 + WFCElement element = WFC_INVALID_HANDLE;
1.450 +
1.451 + if (scene && scene->elements)
1.452 + {
1.453 + element = ELEMENT(scene->elements->data)->handle;
1.454 + }
1.455 + return element;
1.456 +}
1.457 +
1.458 +/*----------------------------------------------------------------------------*/
1.459 +OWF_API_CALL WFC_ELEMENT*
1.460 +WFC_Scene_TopMostElement(WFC_SCENE* scene)
1.461 +{
1.462 + OWF_NODE* node = NULL;
1.463 +
1.464 + for (node = scene->elements; node && node->next; node = node->next)
1.465 + {
1.466 + /* All work done in the for statement, so no body */
1.467 + }
1.468 +
1.469 + return node ? ELEMENT(node->data) : NULL;
1.470 +}