diff -r 000000000000 -r 5d03bc08d59c graphicscomposition/openwfcompositionengine/composition/src/wfcdevice.c --- /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 +#include +#include + +#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