graphicscomposition/openwfcompositionengine/composition/src/wfcdevice.c
changeset 0 5d03bc08d59c
child 36 01a6848ebfd7
child 163 bbf46f59e123
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graphicscomposition/openwfcompositionengine/composition/src/wfcdevice.c	Tue Feb 02 01:47:50 2010 +0200
@@ -0,0 +1,1141 @@
+/* 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 wfcdevice.c
+ *
+ *  \brief SI Device handling
+ */
+
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include "wfcdevice.h"
+#include "wfcelement.h"
+#include "wfccontext.h"
+#include "wfcimageprovider.h"
+
+#include "owfarray.h"
+#include "owfmemory.h"
+#include "owfmutex.h"
+#include "owfscreen.h"
+#include "owftypes.h"
+#include "owfobject.h"
+#include "owfnativestream.h"
+#include "owfnotifications.h"
+#include "owfdebug.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define MAX_ATTRIBUTES      32
+
+#define FAIL_IF(c,e)        if (c) { LEAVE(0); return e; }
+
+#define FIRST_DEVICE_HANDLE 1000
+
+PHYSICAL_DEVICE gPhyDevice;
+
+
+/*-------------------------------------------------------------------------*//*!
+ *  \internal
+ *
+ *  Initialize devices with default parameters.
+ *//*-------------------------------------------------------------------------*/
+OWF_API_CALL void
+WFC_Devices_Initialize()
+{
+    static WFCboolean initialised=WFC_FALSE;
+    if (!initialised)
+    {
+        OWF_Array_Initialize(&(gPhyDevice.iDeviceInstanceArray));
+        gPhyDevice.gDeviceHandleID = 0;
+        initialised=WFC_TRUE;
+    }
+}
+
+/*---------------------------------------------------------------------------
+ *
+ *
+ *----------------------------------------------------------------------------*/
+OWF_API_CALL WFCint
+WFC_Devices_GetIds(WFCint* idList,
+                   WFCint listCapacity,
+                   const WFCint* filterList)
+{
+
+/* We assume there is only one physical device and
+ * all screens are supported by this device */
+
+    WFCint                  screenNumber = OWF_RESERVED_BAD_SCREEN_NUMBER,
+                            n = MAX_ATTRIBUTES,
+                            i = 0;
+    WFCboolean              hasFilter;
+
+    hasFilter = (filterList && (*filterList != WFC_NONE)) ?
+                WFC_TRUE :
+                WFC_FALSE;
+
+    /* handle filter list, if given */
+    if (hasFilter)
+    {
+        /* scan filter list (up to 32 attributes) */
+        while (n > 0 && WFC_NONE != filterList[0])
+        {
+            switch (filterList[0])
+            {
+                case WFC_DEVICE_FILTER_SCREEN_NUMBER:
+                    if (screenNumber!=OWF_RESERVED_BAD_SCREEN_NUMBER && screenNumber!=filterList[1])
+                         {
+                         /* invalid repeated filter on screen number */
+                          return 0;
+                         }
+                    screenNumber = filterList[1];
+                    if (!OWF_Screen_Valid(screenNumber))
+                    {
+                        /* invalid screen number */
+                        return 0;
+                    }
+                    break;
+
+                case WFC_NONE:
+                    n = 0;
+                    break;
+
+                default:
+                    /* EARLY EXIT - invalid attribute */
+                    return 0;
+            }
+
+            /* Move pointer to next key-value pair */
+            filterList += 2;
+            n--;
+        }
+    }
+
+    /* Return number of available devices */
+    if (NULL == idList && !hasFilter) {
+        return 1;
+    }
+
+    for (i = 0, n = 0; i < 1 && listCapacity >= 0; i++) {
+        /* idList might be NULL when querying all devices w/
+         * screen number in filter list */
+        if (idList && n < listCapacity)
+        {
+            idList[n] = OWF_SUPPORTED_DEVICE_ID;
+        }
+
+        n++;
+    }
+
+    return n;
+}
+
+
+/*---------------------------------------------------------------------------
+ *  Create instance of a device whose ID
+ *  matches deviceId
+ *
+ *  \param deviceId ID of the device to create. Must be WFC_DEFAULT_DEVICE_ID
+ *  or some other valid device ID (returned by Devices_GetIds)
+ *
+ *  \return Handle to created device or WFC_INVALID_HANDLE
+ *
+ *----------------------------------------------------------------------------*/
+OWF_API_CALL WFCint
+WFC_Device_Create(WFCint deviceId)
+{
+	WFC_DEVICE *dev = NULL;
+	
+    ENTER(WFC_Device_Create);
+    
+    WFC_Devices_Initialize();
+
+    if (deviceId != WFC_DEFAULT_DEVICE_ID && deviceId != OWF_SUPPORTED_DEVICE_ID)
+    {
+        return WFC_INVALID_HANDLE;
+    }
+    
+    dev = DEVICE(xalloc(1,sizeof(WFC_DEVICE)));
+    if (dev == NULL)
+    {
+    	return WFC_INVALID_HANDLE;
+    }
+    
+    dev->handle = FIRST_DEVICE_HANDLE + (gPhyDevice.gDeviceHandleID)++;
+    dev->deviceId = deviceId;
+    dev->latestUnreadError = WFC_ERROR_NONE;
+    dev->mutex = NULL;
+    OWF_Array_Initialize(&dev->contexts);
+    OWF_Array_Initialize(&dev->providers);
+    OWF_Array_Initialize(&dev->elements);
+
+    if (!OWF_Array_AppendItem(&(gPhyDevice.iDeviceInstanceArray), dev))
+        {
+        xfree(dev);
+        return WFC_INVALID_HANDLE;
+        }
+
+    LEAVE(WFC_Device_Create);
+
+    return dev->handle;
+}
+
+/*---------------------------------------------------------------------------
+ *  Set error code for device. Obs! In case the previous
+ *  error code hasn't been read from the device, this function
+ *  does nothing; the new error is set only if "current" error
+ *  is none.
+ *
+ *  \param dev Device object
+ *  \param code Error to set
+ *
+ *----------------------------------------------------------------------------*/
+OWF_API_CALL void OWF_APIENTRY
+WFC_Device_SetError(WFCDevice dev,
+                    WFCErrorCode code)
+{
+#ifdef DEBUG_LOG
+    static char* const      errmsg[] =
+                            {
+                            "WFC_ERROR_NONE",
+                            "WFC_ERROR_OUT_OF_MEMORY",
+                            "WFC_ERROR_ILLEGAL_ARGUMENT",
+                            "WFC_ERROR_UNSUPPORTED",
+                            "WFC_ERROR_BAD_ATTRIBUTE",
+                            "WFC_ERROR_IN_USE",
+                            "WFC_ERROR_BUSY",
+                            "WFC_ERROR_BAD_DEVICE",
+                            "WFC_ERROR_BAD_HANDLE",
+                            "WFC_ERROR_INCONSISTENCY",
+                            };
+#endif
+    
+    WFC_DEVICE* device = WFC_Device_FindByHandle(dev);
+    if (WFC_INVALID_HANDLE == device)
+    {
+        /* Invalid device handle. Nothing we can do about it so return. */
+        return;
+    }
+
+    if (!device->mutex)
+    {
+        OWF_Mutex_Init(&device->mutex);
+    }
+
+    OWF_Mutex_Lock(&device->mutex);
+    if (code == WFC_ERROR_IN_USE)
+        {
+        code=WFC_ERROR_IN_USE;
+        }
+    if (WFC_INVALID_HANDLE != device) {
+        if (WFC_ERROR_NONE == device->latestUnreadError &&
+            code != device->latestUnreadError)
+        {
+#ifdef DEBUG_LOG
+             char* const msg = errmsg[code > WFC_ERROR_NONE ?
+                    code - WFC_ERROR_OUT_OF_MEMORY + 1 : 0];
+             (void)msg; //always reference to avoid warning
+#endif
+
+            DPRINT(("setError(dev = %08x, err = %08x)", dev, code));
+            DPRINT(("  error set to = %04x (%s)", (OWFuint16) code, msg));
+
+            device->latestUnreadError = code;
+        }
+    }
+
+    OWF_Mutex_Unlock(&device->mutex);
+}
+
+/*---------------------------------------------------------------------------
+ *  Read and reset last error code from device.
+ *
+ *  \param device Device object
+ *
+ *  \return WFCErrorCode
+ *----------------------------------------------------------------------------*/
+OWF_API_CALL WFCErrorCode
+WFC_Device_GetError(WFC_DEVICE* device)
+{
+    WFCErrorCode            err;
+
+    OWF_ASSERT(device);
+
+    err = device->latestUnreadError;
+    device->latestUnreadError = WFC_ERROR_NONE;
+    return err;
+}
+
+/*---------------------------------------------------------------------------
+ *  Find device object by handle
+ *
+ *  \param dev Device handle
+ *
+ *  \return Matching device object or NULL
+ *----------------------------------------------------------------------------*/
+OWF_API_CALL WFC_DEVICE*
+WFC_Device_FindByHandle(WFCDevice dev)
+{
+    WFCint i = 0, length = 0;
+    WFC_DEVICE* pDevice = NULL;
+    
+    if (dev == WFC_INVALID_HANDLE)
+    {
+        return NULL;
+    }
+    
+    WFC_Devices_Initialize();
+    
+    length = gPhyDevice.iDeviceInstanceArray.length;
+    for (i = 0; i < length; ++i)
+        {
+        pDevice = DEVICE(OWF_Array_GetItemAt(&(gPhyDevice.iDeviceInstanceArray), i));
+        if (pDevice->handle == dev)
+            {
+            return pDevice;
+            }
+        }
+    return NULL;
+}
+
+/*---------------------------------------------------------------------------
+ *  Get device attribute
+ *
+ *  \param device Device
+ *  \param attrib Attribute name
+ *  \param value Pointer to where the value should be saved
+ *
+ *  \return WFCErrorCode
+ *----------------------------------------------------------------------------*/
+OWF_API_CALL WFCErrorCode
+WFC_Device_GetAttribi(WFC_DEVICE* device,
+                      WFCDeviceAttrib attrib,
+                      WFCint* value)
+{
+    WFCErrorCode            result = WFC_ERROR_NONE;
+
+    OWF_ASSERT(device);
+
+    switch (attrib)
+    {
+        case WFC_DEVICE_CLASS:
+        {
+            *value = WFC_DEVICE_CLASS_FULLY_CAPABLE;
+            break;
+        }
+        case WFC_DEVICE_ID:
+        {
+            *value = device->deviceId;
+            break;
+        }
+        default:
+        {
+            result = WFC_ERROR_BAD_ATTRIBUTE;
+        }
+    }
+    return result;
+}
+
+/*[][][][] CONTEXTS  [][][][][][][][][][][][][][][][][][][][][][][][][][][][]*/
+
+/*---------------------------------------------------------------------------
+ *  Create context on device
+ *
+ *  \param device Device
+ *  \param stream Target stream for context
+ *  \param type Context type
+ *
+ *  \return New context
+ *----------------------------------------------------------------------------*/
+OWF_API_CALL WFC_CONTEXT*
+WFC_Device_CreateContext(WFC_DEVICE* device,
+                         OWFNativeStreamType stream,
+                         WFCContextType type,
+                         WFCint screenNum)
+{
+    WFC_CONTEXT*            context;
+
+    ENTER(WFC_Device_CreateContext);
+
+    OWF_ASSERT(device);
+
+    context = WFC_Context_Create(device, stream, type, screenNum);
+    if (context)
+    {
+        if (!OWF_Array_AppendItem(&device->contexts, context))
+        {
+            DESTROY(context);
+        }
+    }
+    LEAVE(WFC_Device_CreateContext);
+
+    return context;
+}
+
+/*---------------------------------------------------------------------------
+ *  Destroy context from device
+ *----------------------------------------------------------------------------*/
+OWF_API_CALL WFCErrorCode
+WFC_Device_DestroyContext(WFC_DEVICE* device,
+                          WFCContext context)
+{
+    WFCint                  i;
+    WFCErrorCode            result = WFC_ERROR_BAD_HANDLE;
+    ENTER(WFC_Device_DestroyContext);
+
+    OWF_ASSERT(device);
+
+    DPRINT(("WFC_Device_DestroyContext(context = %d)", context));
+
+    for (i = 0; i < device->contexts.length; i++)
+    {
+        WFC_CONTEXT*        ctmp;
+
+        ctmp = (WFC_CONTEXT*) OWF_Array_GetItemAt(&device->contexts, i);
+        if (ctmp->handle == context)
+        {
+            WFC_CONTEXT*    context;
+
+            context = CONTEXT(OWF_Array_RemoveItemAt(&device->contexts, i));
+            DPRINT(("  Shutting down context %d", context->handle));
+            WFC_Context_Shutdown(context);
+            DESTROY(context);
+            result = WFC_ERROR_NONE;
+            break;
+        }
+    }
+
+    DPRINT((""));
+
+    DPRINT(("-------------------------------------------------------"));
+    DPRINT(("Device statistics after context destruction:"));
+    DPRINT(("  Contexts: %d", device->contexts.length));
+    DPRINT(("  Elements: %d", device->elements.length));
+    DPRINT(("  Image providers: %d", device->providers.length));
+     DPRINT(("-------------------------------------------------------"));
+    LEAVE(WFC_Device_DestroyContext);
+
+    return result;
+}
+
+/*---------------------------------------------------------------------------
+ *  Destroy all device's contexts
+ *
+ *  \param device Device object
+ *----------------------------------------------------------------------------*/
+OWF_API_CALL void
+WFC_Device_DestroyContexts(WFC_DEVICE* device)
+{
+    WFCint                  i;
+
+    ENTER(WFC_Device_DestroyContexts);
+
+    for (i = 0; i < device->contexts.length; i++)
+    {
+        WFC_CONTEXT*        context;
+
+        context = CONTEXT(OWF_Array_GetItemAt(&device->contexts, i));
+        WFC_Context_Shutdown(context);
+
+        DESTROY(context);
+    }
+    OWF_Array_Destroy(&device->contexts);
+
+    LEAVE(WFC_Device_DestroyContexts);
+}
+
+/*---------------------------------------------------------------------------
+ *  Find context context object by handle
+ *
+ *  \param device Device
+ *  \param context Context handle
+ *
+ *  \return Corresponding context object or NULL
+ *  if handle is invalid.
+ *----------------------------------------------------------------------------*/
+OWF_API_CALL WFC_CONTEXT*
+WFC_Device_FindContext(WFC_DEVICE* device,
+                       WFCContext context)
+{
+    WFCint                  i;
+    WFC_CONTEXT*            result = NULL;
+
+    ENTER(WFC_Device_FindContext);
+
+    FAIL_IF(NULL == device, NULL);
+
+    for (i = 0; i < device->contexts.length; i++)
+    {
+        WFC_CONTEXT*        ctmp;
+
+        ctmp = CONTEXT(OWF_Array_GetItemAt(&device->contexts, i));
+        if (ctmp->handle == context)
+        {
+            result = ctmp;
+            break;
+        }
+    }
+    LEAVE(WFC_Device_FindContext);
+
+    return result;
+}
+/*[][][][] ELEMENTS  [][][][][][][][][][][][][][][][][][][][][][][][][][][][]*/
+
+/*---------------------------------------------------------------------------
+ *  Create new element
+ *
+ *  \param device
+ *  \param context
+ *
+ *  \return New element or NULL
+ *----------------------------------------------------------------------------*/
+OWF_API_CALL WFC_ELEMENT*
+WFC_Device_CreateElement(WFC_DEVICE* device, WFC_CONTEXT* context)
+{
+    WFC_ELEMENT*        element=NULL;
+
+    ENTER(WFC_Device_CreateElement);
+
+    FAIL_IF(NULL == device || NULL == context, NULL);
+    if (WFC_Context_IncreaseClientElementCount(context)>0)
+    {
+        element = WFC_Element_Create(context);
+        if (!element || !OWF_Array_AppendItem(&device->elements, element))
+        {
+            DPRINT(("WFC_Device_CreateElement: couldn't create element"));
+            WFC_Context_DecreaseClientElementCount(context);
+            if (element)
+                {
+                WFC_Element_Destroy(element);
+                }
+            element = NULL;
+        }
+        else
+        {
+            /* #4585: statement moved to else block */
+            DPRINT(("  Created element; handle = %d", element->handle));
+        }
+    }
+    LEAVE(WFC_Device_CreateElement);
+
+    return element;
+}
+
+/*---------------------------------------------------------------------------
+ *  Destroy element
+ *
+ *  \param device
+ *  \param element
+ *----------------------------------------------------------------------------*/
+OWF_API_CALL WFCErrorCode
+WFC_Device_DestroyElement(WFC_DEVICE* device,
+                          WFCElement element)
+{
+    WFCint                  i;
+    WFCErrorCode            result = WFC_ERROR_BAD_HANDLE;
+
+    ENTER(WFC_Device_DestroyElement);
+
+    FAIL_IF(NULL == device, WFC_ERROR_BAD_HANDLE);
+    DPRINT(("destroying element %d", element));
+
+    for (i = 0; i < device->elements.length; i++)
+    {
+        WFC_ELEMENT*        object;
+
+        object = ELEMENT(OWF_Array_GetItemAt(&device->elements, i));
+        DPRINT(("  element %d = %d", i, object->handle));
+        if (object->handle == element)
+        {
+            WFC_Context_RemoveElement(CONTEXT(object->context), element);
+
+            WFC_Context_DecreaseClientElementCount(object->context);
+            OWF_Array_RemoveItemAt(&device->elements, i);
+            WFC_Element_Destroy(object);
+            result = WFC_ERROR_NONE;
+            break;
+        }
+    }
+    LEAVE(WFC_Device_DestroyElement);
+    return result;
+}
+
+/*---------------------------------------------------------------------------
+ *  Destroy all elements from device
+ *
+ *  \param device Device
+ *----------------------------------------------------------------------------*/
+OWF_API_CALL void
+WFC_Device_DestroyElements(WFC_DEVICE* device)
+{
+    WFCint                  i;
+
+    ENTER(WFC_Device_DestroyElements);
+
+    OWF_ASSERT(device);
+
+    for (i = 0; i < device->elements.length; i++)
+    {
+        WFC_ELEMENT*        etemp;
+
+        etemp = ELEMENT(OWF_Array_GetItemAt(&device->elements, i));
+        WFC_Element_Destroy(etemp);
+    }
+    OWF_Array_Destroy(&device->elements);
+
+    LEAVE(WFC_Device_DestroyElements);
+}
+
+/*---------------------------------------------------------------------------
+ *  Find element by handle
+ *
+ *  \param device Device
+ *  \param el Element handle
+ *
+ *  \return Element object
+ *----------------------------------------------------------------------------*/
+OWF_API_CALL WFC_ELEMENT*
+WFC_Device_FindElement(WFC_DEVICE* device,
+                       WFCElement el)
+{
+    WFC_ELEMENT*            result = WFC_INVALID_HANDLE;
+    WFCint                  i;
+
+    FAIL_IF(NULL == device, NULL);
+
+    for (i = 0; i < device->elements.length; i++)
+    {
+        WFC_ELEMENT*        element;
+        element = ELEMENT(OWF_Array_GetItemAt(&device->elements, i));
+
+        if (element->handle == el)
+        {
+            result = element;
+            break;
+        }
+
+    }
+    return result;
+}
+
+/*---------------------------------------------------------------------------
+ *  Set element integer vector attribute
+ *
+ *  \param device Device
+ *  \param element Element handle
+ *  \param attrib Attribute name
+ *  \param count Attribute value vector length (1 for scalar attribute)
+ *  \param values Pointer to values
+ *
+ *  \return WFCErrorCode: WFC_ERROR_BAD_ATTRIBUTE if attribute name is invalid;
+ *  WFC_ERROR_INVALID_ARGUMENT if values is NULL or if the count doesn't match
+ *  the attribute's size; WFC_ERROR_BAD_HANDLE if element handle is invalid.
+ *----------------------------------------------------------------------------*/
+OWF_API_CALL WFCErrorCode
+WFC_Device_SetElementAttribiv(WFC_DEVICE* device,
+                              WFCElement element,
+                              WFCElementAttrib attrib,
+                              WFCint count,
+                              const WFCint* values)
+{
+    WFC_ELEMENT*            object;
+
+    OWF_ASSERT(device);
+
+    object = WFC_Device_FindElement(device, element);
+    FAIL_IF(NULL == object, WFC_ERROR_BAD_HANDLE);
+    return WFC_Element_SetAttribiv(object, attrib, count, values);
+}
+
+/*---------------------------------------------------------------------------
+ *
+ *
+ *----------------------------------------------------------------------------*/
+OWF_API_CALL WFCErrorCode
+WFC_Device_SetElementAttribfv(WFC_DEVICE* device,
+                              WFCElement element,
+                              WFCElementAttrib attrib,
+                              WFCint count,
+                              const WFCfloat* values)
+{
+    WFC_ELEMENT*            object;
+
+    OWF_ASSERT(device);
+
+    object = WFC_Device_FindElement(device, element);
+    FAIL_IF(NULL == object, WFC_ERROR_BAD_HANDLE);
+    return WFC_Element_SetAttribfv(object, attrib, count, values);
+}
+
+/*---------------------------------------------------------------------------
+ *
+ *
+ *----------------------------------------------------------------------------*/
+OWF_API_CALL WFCErrorCode
+WFC_Device_GetElementAttribiv(WFC_DEVICE* device,
+                              WFCElement element,
+                              WFCElementAttrib attrib,
+                              WFCint count,
+                              WFCint* values)
+{
+    WFC_ELEMENT*            object;
+
+    OWF_ASSERT(device);
+
+    object = WFC_Device_FindElement(device, element);
+    FAIL_IF(NULL == object, WFC_ERROR_BAD_HANDLE);
+    return WFC_Element_GetAttribiv(object, attrib, count, values);
+}
+
+/*---------------------------------------------------------------------------
+ *
+ *
+ *----------------------------------------------------------------------------*/
+OWF_API_CALL WFCErrorCode
+WFC_Device_GetElementAttribfv(WFC_DEVICE* device,
+                              WFCElement element,
+                              WFCElementAttrib attrib,
+                              WFCint count,
+                              WFCfloat* values)
+{
+    WFC_ELEMENT*            object;
+
+    OWF_ASSERT(device);
+
+    object = WFC_Device_FindElement(device, element);
+    FAIL_IF(NULL == object, WFC_ERROR_BAD_HANDLE);
+    return WFC_Element_GetAttribfv(object, attrib, count, values);
+}
+
+
+/*[][][][] IMAGE PROVIDERS [][][][][][][][][][][][][][][][][][][][][][][][][]*/
+
+/*---------------------------------------------------------------------------
+ *
+ *----------------------------------------------------------------------------*/
+OWF_API_CALL void
+WFC_Device_EnableContentNotifications(WFC_DEVICE* device,
+                                      WFC_CONTEXT* context,
+                                      WFCboolean enable)
+{
+    WFCint                  i;
+
+    OWF_ASSERT(device);
+    OWF_ASSERT(context);
+
+    context = context;
+
+    for (i = 0; i < device->providers.length; i++)
+    {
+        WFC_IMAGE_PROVIDER* prov;
+
+        prov = IMAGE_PROVIDER(OWF_Array_GetItemAt(&device->providers, i));
+
+        owfNativeStreamEnableUpdateNotifications(prov->streamHandle,
+                                                 enable ? OWF_TRUE : OWF_FALSE);
+    }
+}
+
+/*---------------------------------------------------------------------------
+ *
+ *----------------------------------------------------------------------------*/
+static WFC_IMAGE_PROVIDER*
+WFC_Device_CreateImageProvider(WFC_DEVICE* device,
+                               WFC_CONTEXT* context,
+                               OWFNativeStreamType stream,
+                               WFC_IMAGE_PROVIDER_TYPE type)
+{
+    WFC_IMAGE_PROVIDER*         provider;
+    WFCint						success;
+
+    OWF_ASSERT(device);
+    OWF_ASSERT(context);
+
+    /* create/fetch stream-wrapper for native stream.  */
+
+    /* create new image provider object associated to
+     * native stream wrapper previously fetched */
+    provider = WFC_ImageProvider_Create(context, stream, type);
+    if (!provider)
+    {
+        return NULL;
+    }   
+
+    success = OWF_TRUE;
+    if (OWF_Array_AppendItem(&device->providers, provider) != OWF_TRUE)
+    {
+        success = OWF_FALSE;
+    }
+
+    if (!success || !owfSymDeviceInitialise(provider))
+    {
+        OWF_Array_RemoveItem(&device->providers, provider);
+        success = OWF_FALSE;
+    }
+    if (!success)
+    {
+        DESTROY(provider);
+        provider = NULL;
+    }
+    return provider;
+}
+
+/*---------------------------------------------------------------------------
+ *
+ *----------------------------------------------------------------------------*/
+static WFCErrorCode
+WFC_Device_DestroyImageProvider(WFC_DEVICE* device,
+                                WFCHandle handle)
+{
+    WFCint                  i;
+    WFCErrorCode            result = WFC_ERROR_BAD_HANDLE;
+
+    ENTER(WFC_Device_DestroyImageProvider);
+
+    OWF_ASSERT(device);
+
+    DPRINT(("  number of providers = %d", device->providers.length));
+
+    for (i = 0; i < device->providers.length; i++)
+    {
+        WFC_IMAGE_PROVIDER* object;
+
+        object = (WFC_IMAGE_PROVIDER*)OWF_Array_GetItemAt(&device->providers, i);
+        if (object->handle == handle)
+        {
+        
+            DPRINT(("  Destroying image provider %d", handle));
+            
+            owfSymDeviceDestroy(device, object, i);
+            OWF_Array_RemoveItemAt(&device->providers, i);
+                        
+            DESTROY(object);
+            result = WFC_ERROR_NONE;
+            break;
+        }
+    }
+
+    /*
+     *  Image provider's source content observer should be removed here,
+     *  but on the other hand, it'll be removed when the image provider's
+     *  source stream gets destroyed.
+     */
+    LEAVE(WFC_Device_DestroyImageProvider);
+    return result;
+}
+
+/*---------------------------------------------------------------------------
+ *  Destroy all image providers from device
+ *
+ *  \param device Device
+ *----------------------------------------------------------------------------*/
+OWF_API_CALL void
+WFC_Device_DestroyImageProviders(WFC_DEVICE* device)
+{
+    WFCint                  i;
+
+    ENTER(WFC_Device_DestroyImageProviders);
+
+    OWF_ASSERT(device);
+
+    DPRINT(("number of providers = %d", device->providers.length));
+
+    for (i = 0; i < device->providers.length; i++)
+    {
+        WFC_IMAGE_PROVIDER* itemp;
+
+        itemp = IMAGE_PROVIDER(OWF_Array_GetItemAt(&device->providers, i));
+        DESTROY(itemp);
+    }
+    OWF_Array_Destroy(&device->providers);
+
+    LEAVE(WFC_Device_DestroyImageProviders);
+}
+
+/*---------------------------------------------------------------------------
+ *
+ *----------------------------------------------------------------------------*/
+OWF_API_CALL WFC_IMAGE_PROVIDER*
+WFC_Device_FindImageProvider(WFC_DEVICE* device,
+                             WFCHandle handle,
+                             WFC_IMAGE_PROVIDER_TYPE type)
+{
+    WFCint                  i;
+    WFC_IMAGE_PROVIDER*     result = WFC_INVALID_HANDLE;
+
+    ENTER(WFC_Device_FindImageProvider);
+
+    OWF_ASSERT(device);
+    DPRINT(("number of providers = %d", device->providers.length));
+
+    for (i = 0; i < device->providers.length; i++)
+    {
+        WFC_IMAGE_PROVIDER* object;
+
+        object = IMAGE_PROVIDER(OWF_Array_GetItemAt(&device->providers, i));
+        if (object->handle == handle && object->type == type)
+        {
+            result = object;
+            break;
+        }
+    }
+
+    LEAVE(WFC_Device_FindImageProvider);
+
+    return result;
+}
+
+/*---------------------------------------------------------------------------
+ *
+ *----------------------------------------------------------------------------*/
+OWF_API_CALL WFC_IMAGE_PROVIDER*
+WFC_Device_CreateSource(WFC_DEVICE* device,
+                        WFC_CONTEXT* context,
+                        WFCNativeStreamType stream)
+{
+    OWF_ASSERT(device);
+    OWF_ASSERT(context);
+    return WFC_Device_CreateImageProvider(device,
+                                          context, stream, WFC_IMAGE_SOURCE);
+}
+
+/*---------------------------------------------------------------------------
+ *
+ *----------------------------------------------------------------------------*/
+OWF_API_CALL WFC_IMAGE_PROVIDER*
+WFC_Device_CreateMask(WFC_DEVICE* device,
+                      WFC_CONTEXT* context,
+                      WFCNativeStreamType stream)
+{
+    OWF_ASSERT(device);
+    OWF_ASSERT(context);
+    return WFC_Device_CreateImageProvider(device,
+                                          context, stream, WFC_IMAGE_MASK);
+}
+
+/*---------------------------------------------------------------------------
+ *
+ *----------------------------------------------------------------------------*/
+OWF_API_CALL WFCErrorCode
+WFC_Device_DestroySource(WFC_DEVICE* device, WFCSource source)
+{
+    OWF_ASSERT(device);
+    return WFC_Device_DestroyImageProvider(device, source);
+}
+
+/*---------------------------------------------------------------------------
+ *
+ *----------------------------------------------------------------------------*/
+OWF_API_CALL WFCErrorCode
+WFC_Device_DestroyMask(WFC_DEVICE* device, WFCMask mask)
+{
+    OWF_ASSERT(device);
+    return WFC_Device_DestroyImageProvider(device, mask);
+}
+
+/*---------------------------------------------------------------------------
+ *
+ *----------------------------------------------------------------------------*/
+OWF_API_CALL WFC_IMAGE_PROVIDER*
+WFC_Device_FindSource(WFC_DEVICE* device, WFCSource source)
+{
+    OWF_ASSERT(device);
+    return WFC_Device_FindImageProvider(device, source, WFC_IMAGE_SOURCE);
+}
+
+/*---------------------------------------------------------------------------
+ *
+ *----------------------------------------------------------------------------*/
+OWF_API_CALL WFC_IMAGE_PROVIDER*
+WFC_Device_FindMask(WFC_DEVICE* device, WFCMask mask)
+{
+    OWF_ASSERT(device);
+    return WFC_Device_FindImageProvider(device, mask, WFC_IMAGE_MASK);
+}
+
+/*---------------------------------------------------------------------------
+ *  Destroy device, or rather queue it for destruction.
+ *
+ *  \param device Device
+ *----------------------------------------------------------------------------*/
+OWF_API_CALL void
+WFC_Device_Destroy(WFC_DEVICE* device)
+{
+    ENTER(WFC_Device_Destroy);
+
+    OWF_ASSERT(device);
+
+    /* release resources */
+    WFC_Device_DestroyElements(device);
+    WFC_Device_DestroyImageProviders(device);
+    WFC_Device_DestroyContexts(device);
+
+    OWF_Mutex_Destroy(&device->mutex);
+    device->mutex = NULL;
+
+    device->latestUnreadError = WFC_ERROR_NONE;
+    device->handle = WFC_INVALID_HANDLE;
+    
+    OWF_Array_RemoveItem(&(gPhyDevice.iDeviceInstanceArray), device);
+    xfree(device);
+    if (gPhyDevice.iDeviceInstanceArray.length == 0)
+        {
+        OWF_Array_Destroy(&(gPhyDevice.iDeviceInstanceArray));
+        }
+    LEAVE(WFC_Device_Destroy);
+}
+
+/*---------------------------------------------------------------------------
+ *
+ *----------------------------------------------------------------------------*/
+OWF_API_CALL WFCboolean
+WFC_Device_StreamIsTarget(WFC_DEVICE* device,
+                          WFCNativeStreamType stream)
+{
+    WFCint                  i;
+    WFCboolean              result = WFC_FALSE;
+
+    OWF_ASSERT(device);
+
+    for (i = 0; i < device->contexts.length; i++)
+    {
+        WFC_CONTEXT*        ctmp;
+
+        ctmp = CONTEXT(OWF_Array_GetItemAt(&device->contexts, i));
+        if (ctmp->stream == stream)
+        {
+            result = WFC_TRUE;
+            break;
+        }
+    }
+    return result;
+}
+
+/*---------------------------------------------------------------------------
+ *
+ *----------------------------------------------------------------------------*/
+OWF_API_CALL WFC_CONTEXT*
+WFC_Device_FindContextByScreen(WFC_DEVICE* device,
+                               WFCint screenNumber)
+{
+    WFCint                  i;
+    WFC_CONTEXT*            result = NULL;
+
+    OWF_ASSERT(device);
+
+    for (i = 0; i < device->contexts.length; i++)
+    {
+        WFC_CONTEXT*        ctmp;
+
+        ctmp = CONTEXT(OWF_Array_GetItemAt(&device->contexts, i));
+        if (ctmp->screenNumber == screenNumber)
+        {
+            result = ctmp;
+            break;
+        }
+    }
+    return result;
+
+}
+
+/*---------------------------------------------------------------------------
+ *  Called from context's destructor to clean up any elements that
+ *  weren't added to any scene at all i.e. they only reside in the
+ *  device's element list. These elements must not stay alive after
+ *  the context has been deleted.
+ *----------------------------------------------------------------------------*/
+OWF_API_CALL void
+WFC_Device_DestroyContextElements(WFC_DEVICE* device,
+                                  WFC_CONTEXT* context)
+{
+    WFCint                  i;
+
+    DPRINT(("WFC_Device_DestroyContextElements(device=%d, context=%d",
+            device ? device->handle : 0,
+            context ? context->handle : 0));
+
+    if (!device || !context)
+    {
+        return;
+    }
+
+    for (i = device->elements.length; i > 0; i--)
+    {
+        WFC_ELEMENT*        element;
+
+        element = ELEMENT(OWF_Array_GetItemAt(&device->elements, i-1));
+        if (element->context == context)
+        {
+            DPRINT(("  Destroying element %d (%p)", element->handle, element));
+
+            /* Improvement idea: This code is partially same as in
+             * WFC_Device_RemoveElement. Maybe the common part should
+             * be isolated into some DoRemoveElement function which then
+             * would be called from here and RemoveElement.
+             */
+            WFC_Context_RemoveElement(CONTEXT(element->context), element->handle);
+            OWF_Array_RemoveItemAt(&device->elements, i-1);
+            WFC_Element_Destroy(element);
+        }
+    }
+}
+
+/*---------------------------------------------------------------------------
+ *
+ *----------------------------------------------------------------------------*/
+OWF_API_CALL void
+WFC_Device_DestroyContextImageProviders(WFC_DEVICE* device,
+                                        WFC_CONTEXT* context)
+{
+    WFCint                  i;
+    
+	DPRINT(("WFC_Device_DestroyContextImageProviders(device=%d, context=%d",
+	device ? device->handle : 0,
+	context ? context->handle : 0));
+
+    if (!device || !context)
+    {
+        return;
+    }
+
+    for (i = device->providers.length; i > 0; i--)
+    {
+        WFC_IMAGE_PROVIDER* provider;
+
+        provider = IMAGE_PROVIDER(OWF_Array_GetItemAt(&device->providers, i-1));
+        if (provider->owner == context)
+        {
+            DPRINT(("  Destroying image provider %d (%p)",
+                    provider->handle, provider));
+
+            WFC_Device_DestroyImageProvider(device, provider->handle);
+        }
+    }
+}
+
+#ifdef __cplusplus
+}
+#endif