--- /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