sl@0: /* Copyright (c) 2009-2010 The Khronos Group Inc. sl@0: * Portions copyright (c) 2009-2010 Nokia Corporation and/or its subsidiary(-ies) sl@0: * sl@0: * Permission is hereby granted, free of charge, to any person obtaining a sl@0: * copy of this software and/or associated documentation files (the sl@0: * "Materials"), to deal in the Materials without restriction, including sl@0: * without limitation the rights to use, copy, modify, merge, publish, sl@0: * distribute, sublicense, and/or sell copies of the Materials, and to sl@0: * permit persons to whom the Materials are furnished to do so, subject to sl@0: * the following conditions: sl@0: * sl@0: * The above copyright notice and this permission notice shall be included sl@0: * in all copies or substantial portions of the Materials. sl@0: * sl@0: * THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, sl@0: * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF sl@0: * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. sl@0: * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY sl@0: * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, sl@0: * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE sl@0: * MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS. sl@0: */ sl@0: sl@0: sl@0: sl@0: #ifdef __cplusplus sl@0: extern "C" { sl@0: #endif sl@0: sl@0: sl@0: #include sl@0: #include sl@0: #include sl@0: #include sl@0: sl@0: #include "owfattributes.h" sl@0: #include "owfmemory.h" sl@0: #include "owfdebug.h" sl@0: sl@0: #define OWF_ATTRIB_RANGE_START (0) sl@0: #define OWF_ATTRIB_RANGE_UNINITIALIZED (-1) sl@0: sl@0: static OWFint OWF_Attribute_Commit(OWF_ATTRIBUTE* aAttr, OWFint aDirtyFlag, OWFint aCopyTo,OWFint aCopyFrom); sl@0: sl@0: /* sl@0: This attribute class is not used for WFC element attributes because elements are sl@0: completely cloned in the committed scene. sl@0: [This class could be replaced with 3 copies of a much simpler writable attributes raw sl@0: structure with simple data members, and the whole structure copied each commit.] sl@0: Normal attribute values have three pointers indexed via an array: sl@0: COMMITTED_ATTR_VALUE_INDEX: sl@0: Attribute values used by the scene sl@0: - points to named variables directly used by the compositor sl@0: WORKING_ATTR_VALUE_INDEX: sl@0: Attribute values that may be set by the client, if they are not read-only. sl@0: SNAPSHOT_ATTR_VALUE_INDEX sl@0: A copy of the client-set attribute values following a client call to wfcCommit sl@0: The copy is then protected against further modification by the client until sl@0: the committed scene is updated and displayed. sl@0: The Working and Snapshot writable attributes require additional cache storage, sl@0: which is managed by the lifetime of the attribute list. sl@0: Read-only attributes point all three pointers at the named compositor variables. sl@0: Currently, there are relatively few writable attributes so it is reasonable sl@0: to individually dynamically allocate each cache. It would be better to allocate sl@0: a single block sized after the attributes have been registered. sl@0: sl@0: Internal code is expected to read or write to member variables that are abstracted sl@0: by read-only attributes. However they must not write directly to member variables sl@0: masked by writable attributes after the initial "commit" to working. The code does sl@0: not currently use const instances to enforce this behavior. sl@0: */ sl@0: #define COND_FAIL_NR(ctx, condition, error) \ sl@0: if (!(condition)) { \ sl@0: if (ctx) { \ sl@0: (ctx)->last_error = error; \ sl@0: } \ sl@0: return; \ sl@0: } sl@0: sl@0: #define COND_FAIL(ctx, condition, error, r) \ sl@0: if (!(condition)) { \ sl@0: if (ctx) { \ sl@0: (ctx)->last_error = error; \ sl@0: } \ sl@0: return r; \ sl@0: } sl@0: sl@0: // NS here means No Set as we are not setting the last_error member of the context. sl@0: // These are used when we are testing the context itself so setting the last_error sl@0: // member is itself is an error sl@0: #define COND_FAIL_NR_NS(condition) \ sl@0: if (!(condition)) { \ sl@0: return; \ sl@0: } sl@0: sl@0: #define COND_FAIL_NS(condition, r) \ sl@0: if (!(condition)) { \ sl@0: return r; \ sl@0: } sl@0: sl@0: #define CHECK_INDEX_NR(ctx, index, error) \ sl@0: if (index < (ctx)->range_start || index > (ctx)->range_end) { \ sl@0: (ctx)->last_error = error; \ sl@0: return; \ sl@0: } sl@0: sl@0: #define CHECK_INDEX(ctx, index, error, r) \ sl@0: if (index < (ctx)->range_start || index > (ctx)->range_end) { \ sl@0: (ctx)->last_error = error; \ sl@0: return r; \ sl@0: } sl@0: sl@0: #define CHECK_BAD_NR(ctx, index) \ sl@0: CHECK_INDEX_NR(ctx, index, ATTR_ERROR_INVALID_ATTRIBUTE); \ sl@0: if ((ctx)->attributes[index-(ctx)->range_start].attr_info.type == AT_UNDEFINED) { \ sl@0: (ctx)->last_error = ATTR_ERROR_INVALID_ATTRIBUTE; \ sl@0: return; \ sl@0: } sl@0: sl@0: #define CHECK_BAD(ctx, index, r) \ sl@0: CHECK_INDEX(ctx, index, ATTR_ERROR_INVALID_ATTRIBUTE, r); \ sl@0: if ((ctx)->attributes[index-(ctx)->range_start].attr_info.type == AT_UNDEFINED) { \ sl@0: (ctx)->last_error = ATTR_ERROR_INVALID_ATTRIBUTE; \ sl@0: return r; \ sl@0: } sl@0: sl@0: #define SET_ERROR(ctx, err) \ sl@0: if ((ctx)->last_error == ATTR_ERROR_NONE) { \ sl@0: (ctx)->last_error = err; \ sl@0: } sl@0: sl@0: sl@0: /* sl@0: ============================================================================= sl@0: ATTRIBUTE CONTEXT MANAGEMENT FUNCTIONS sl@0: ============================================================================= sl@0: */ sl@0: sl@0: /*! sl@0: * \brief Initializes attribute context sl@0: * sl@0: * \param aContext Attribute context to initialize sl@0: * \param aStart Attribute range start sl@0: * \param aEnd Attribute range end. Must be greater than range start. sl@0: * sl@0: * \return ATTR_ERROR_INVALID_ARGUMENT sl@0: * ATTR_ERROR_NO_MEMORY sl@0: */ sl@0: OWF_API_CALL void sl@0: OWF_AttributeList_Create(OWF_ATTRIBUTE_LIST* aContext, sl@0: OWFint aStart, sl@0: OWFint aEnd) sl@0: { sl@0: OWF_ATTRIBUTE* temp = NULL; sl@0: sl@0: COND_FAIL_NR_NS(aContext); sl@0: COND_FAIL_NR(aContext, aEnd >= 0, ATTR_ERROR_INVALID_ARGUMENT); sl@0: COND_FAIL_NR(aContext, aEnd >= aStart, ATTR_ERROR_INVALID_ARGUMENT); sl@0: sl@0: aContext->range_start = OWF_ATTRIB_RANGE_START; sl@0: aContext->range_end = OWF_ATTRIB_RANGE_UNINITIALIZED; sl@0: sl@0: temp = (OWF_ATTRIBUTE*) xalloc(aEnd - aStart + 1, sizeof(OWF_ATTRIBUTE)); sl@0: COND_FAIL_NR(aContext, temp, ATTR_ERROR_NO_MEMORY); sl@0: sl@0: memset(aContext, 0, sizeof(OWF_ATTRIBUTE_LIST)); sl@0: sl@0: aContext->range_start = aStart; sl@0: aContext->range_end = aEnd; sl@0: aContext->attributes = temp; sl@0: sl@0: SET_ERROR(aContext, ATTR_ERROR_NONE); sl@0: return; sl@0: } sl@0: sl@0: /*! sl@0: * \brief Destroy attribute context and free any resources (memory sl@0: * blocks) allocated to it. All attributes are destroyed. sl@0: * sl@0: * \param aContext Attribute context to destroy sl@0: * sl@0: * \return ATTR_ERROR_INVALID_ARGUMENT sl@0: * ATTR_ERROR_INVALID_CONTEXT sl@0: */ sl@0: OWF_API_CALL void sl@0: OWF_AttributeList_Destroy(OWF_ATTRIBUTE_LIST* aContext) sl@0: { sl@0: OWFint count = 0; sl@0: OWFint at = 0; sl@0: OWFint cache = 0; sl@0: sl@0: COND_FAIL_NR_NS(aContext); sl@0: COND_FAIL_NR(aContext, aContext->attributes, ATTR_ERROR_INVALID_CONTEXT); sl@0: sl@0: count = aContext->range_end - aContext->range_start; sl@0: for (at = 0; at <= count; at++) { sl@0: sl@0: OWF_ATTRIBUTE* attr = &aContext->attributes[at]; sl@0: if (!attr->attr_info.readonly) sl@0: { sl@0: for (cache=0;cacheattr_value[cache].gen_ptr); sl@0: } sl@0: } sl@0: } sl@0: } sl@0: sl@0: xfree(aContext->attributes); sl@0: memset(aContext, 0, sizeof(OWF_ATTRIBUTE_LIST)); sl@0: SET_ERROR(aContext, ATTR_ERROR_NONE); sl@0: return; sl@0: } sl@0: sl@0: /* sl@0: sl@0: sl@0: */ sl@0: OWF_API_CALL OWF_ATTRIBUTE_LIST_STATUS sl@0: OWF_AttributeList_GetError(OWF_ATTRIBUTE_LIST* aContext) sl@0: { sl@0: OWF_ATTRIBUTE_LIST_STATUS error; sl@0: sl@0: if (!aContext) { sl@0: return ATTR_ERROR_INVALID_ARGUMENT; sl@0: } sl@0: error = aContext->last_error; sl@0: aContext->last_error = ATTR_ERROR_NONE; sl@0: return error; sl@0: } sl@0: sl@0: /* sl@0: ============================================================================= sl@0: INITIALIZATION FUNCTIONS sl@0: ============================================================================= sl@0: */ sl@0: sl@0: static void OWF_Attribute_Init(OWF_ATTRIBUTE_LIST* aContext, sl@0: OWFint aName, sl@0: OWF_ATTRIBUTE_TYPE aType, sl@0: OWFint aLength, sl@0: void* aValue, sl@0: OWFboolean aRdOnly) sl@0: { sl@0: OWF_ATTRIBUTE* attr = NULL; sl@0: void* cache = NULL; sl@0: OWFint itemSize; sl@0: OWFint arraySize; sl@0: OWFint copy; sl@0: OWFint index; sl@0: sl@0: COND_FAIL_NR_NS(aContext); sl@0: CHECK_INDEX_NR(aContext, aName, ATTR_ERROR_INVALID_ATTRIBUTE); sl@0: COND_FAIL_NR(aContext, aContext->attributes, ATTR_ERROR_INVALID_CONTEXT); sl@0: COND_FAIL_NR(aContext, aLength < MAX_ATTR_LENGTH, ATTR_ERROR_CANT_HANDLE); sl@0: COND_FAIL_NR(aContext, aType != AT_UNDEFINED, ATTR_ERROR_INVALID_ARGUMENT); sl@0: sl@0: index = aName - aContext->range_start; sl@0: sl@0: attr = &aContext->attributes[index]; sl@0: sl@0: memset(attr, 0, sizeof(OWF_ATTRIBUTE)); sl@0: sl@0: /* when allocin', size DOES matter */ sl@0: if (aType == AT_INTEGER || aType == AT_BOOLEAN) { sl@0: itemSize = sizeof(OWFint); sl@0: } else { sl@0: itemSize = sizeof(OWFfloat); sl@0: } sl@0: arraySize=itemSize*aLength; sl@0: sl@0: /* don't allocate cache for read-only 'butes */ sl@0: attr->attr_info.type = aType; sl@0: attr->attr_info.length = aLength; sl@0: attr->attr_info.readonly = aRdOnly; sl@0: attr->attr_info.size = itemSize; sl@0: if (aRdOnly) sl@0: { sl@0: for (copy=0;copyattr_value[copy].gen_ptr = aValue; sl@0: } sl@0: } sl@0: else sl@0: { sl@0: for (copy=0;copyattr_value[COMMITTED_ATTR_VALUE_INDEX].gen_ptr = aValue; sl@0: } sl@0: else sl@0: { sl@0: cache = xalloc(arraySize,1); sl@0: COND_FAIL_NR(aContext, NULL != cache, ATTR_ERROR_NO_MEMORY); sl@0: attr->attr_value[copy].gen_ptr = cache; sl@0: } sl@0: } sl@0: } sl@0: sl@0: SET_ERROR(aContext, ATTR_ERROR_NONE); sl@0: sl@0: } sl@0: sl@0: /* sl@0: * \brief Intialize integer attribute sl@0: * sl@0: * \param aContext Attibute context sl@0: * \param aName Attribute name sl@0: * \param aValue Attribute initial value sl@0: * \param aRdOnly Read-only flag sl@0: * sl@0: * \return ATTR_ERROR_INVALID_ARGUMENT sl@0: * ATTR_ERROR_INVALID_ATTRIBUTE sl@0: * ATTR_ERROR_INVALID_CONTEXT sl@0: */ sl@0: OWF_API_CALL void sl@0: OWF_Attribute_Initi(OWF_ATTRIBUTE_LIST* aContext, sl@0: OWFint aName, sl@0: OWF_INT_REF aValue, sl@0: OWFboolean aRdOnly) sl@0: { sl@0: OWF_Attribute_Init(aContext, aName, AT_INTEGER, 1, aValue, aRdOnly); sl@0: } sl@0: sl@0: /* sl@0: * \brief Initialize float attribute sl@0: * sl@0: * \param aContext Attribute context sl@0: * \param aName Attribute name sl@0: * \param aValue Initial value for attribute sl@0: * \param aRdOnly Read-only flag sl@0: * sl@0: * \return ATTR_ERROR_INVALID_ARGUMENT sl@0: * ATTR_ERROR_INVALID_ATTRIBUTE sl@0: * ATTR_ERROR_INVALID_CONTEXT sl@0: */ sl@0: OWF_API_CALL void sl@0: OWF_Attribute_Initf(OWF_ATTRIBUTE_LIST* aContext, sl@0: OWFint aName, sl@0: OWF_FLOAT_REF aValue, sl@0: OWFboolean aRdOnly) sl@0: { sl@0: OWF_Attribute_Init(aContext, aName, AT_FLOAT, 1, aValue, aRdOnly); sl@0: } sl@0: sl@0: /* sl@0: * \brief Initialize boolean attribute sl@0: * sl@0: * \param aContext Attribute context sl@0: * \param aName Attribute name sl@0: * \param aValue Initial value for attribute sl@0: * \param aRdOnly Read-only flag sl@0: * sl@0: * \return ATTR_ERROR_INVALID_ARGUMENT sl@0: * ATTR_ERROR_INVALID_ATTRIBUTE sl@0: * ATTR_ERROR_INVALID_CONTEXT sl@0: */ sl@0: OWF_API_CALL void sl@0: OWF_Attribute_Initb(OWF_ATTRIBUTE_LIST* aContext, sl@0: OWFint aName, sl@0: OWF_BOOL_REF aValue, sl@0: OWFboolean aRdOnly) sl@0: { sl@0: OWF_Attribute_Init(aContext, aName, AT_BOOLEAN, 1, aValue, aRdOnly); sl@0: } sl@0: sl@0: /* sl@0: * \brief Initialize vector attribute sl@0: * sl@0: * \param aContext Attribute context sl@0: * \param aName Attribute name sl@0: * \param aLength Attribute (vector) length sl@0: * \param aValues Initial value(s) for attribute sl@0: * \param aRdOnly Read-only flag sl@0: * sl@0: * \return ATTR_ERROR_INVALID_ARGUMENT sl@0: * ATTR_ERROR_INVALID_ATTRIBUTE sl@0: * ATTR_ERROR_INVALID_CONTEXT sl@0: * ATTR_ERROR_CANT_HANDLE sl@0: */ sl@0: OWF_API_CALL void sl@0: OWF_Attribute_Initiv(OWF_ATTRIBUTE_LIST* aContext, sl@0: OWFint aName, sl@0: OWFint aLength, sl@0: OWF_INT_VECTOR_REF aValues, sl@0: OWFboolean aRdOnly) sl@0: { sl@0: OWF_Attribute_Init(aContext, aName, AT_INTEGER, aLength, aValues, aRdOnly); sl@0: } sl@0: sl@0: /* sl@0: * \brief Initialize vector attribute sl@0: * sl@0: * \param aContext Attribute context sl@0: * \param aName Attribute name sl@0: * \param aLength Attribute (vector) length sl@0: * \param aValues Initial value(s) for attributes sl@0: * \param aRdOnly Read-only flag sl@0: * sl@0: * \return sl@0: */ sl@0: OWF_API_CALL void sl@0: OWF_Attribute_Initfv(OWF_ATTRIBUTE_LIST* aContext, sl@0: OWFint aName, sl@0: OWFint aLength, sl@0: OWF_FLOAT_VECTOR_REF aValues, sl@0: OWFboolean aRdOnly) sl@0: { sl@0: OWF_Attribute_Init(aContext, aName, AT_FLOAT, aLength, aValues, aRdOnly); sl@0: } sl@0: sl@0: /* sl@0: ============================================================================= sl@0: GETTER FUNCTIONS sl@0: ============================================================================= sl@0: */ sl@0: sl@0: /* sl@0: * \brief Get attribute integer value. sl@0: * sl@0: * \param aContext Attribute context sl@0: * \param aName Attribute name sl@0: * sl@0: * \return Attribute integer value (floats are floor()ed). For vector sl@0: * attributes the return value will be error ATTR_ERROR_INVALID_TYPE. sl@0: * ATTR_ERROR_INVALID_ATTRIBUTE sl@0: * ATTR_ERROR_INVALID_CONTEXT sl@0: */ sl@0: OWF_API_CALL OWFint sl@0: OWF_Attribute_GetValuei(OWF_ATTRIBUTE_LIST* aContext, sl@0: OWFint aName) sl@0: { sl@0: OWFint index = 0; sl@0: OWF_ATTRIBUTE* attr = 0; sl@0: OWFint result = 0; sl@0: sl@0: COND_FAIL_NS(aContext, 0); sl@0: COND_FAIL(aContext, sl@0: aContext->attributes, sl@0: ATTR_ERROR_INVALID_CONTEXT, sl@0: 0); sl@0: CHECK_BAD(aContext, aName, 0); sl@0: sl@0: sl@0: index = aName - aContext->range_start; sl@0: attr = &aContext->attributes[index]; sl@0: sl@0: COND_FAIL(aContext, sl@0: 1 == attr->attr_info.length, sl@0: ATTR_ERROR_INVALID_TYPE, sl@0: 0); sl@0: sl@0: SET_ERROR(aContext, ATTR_ERROR_NONE); sl@0: sl@0: switch (attr->attr_info.type) { sl@0: case AT_FLOAT: { sl@0: result = floor(attr->attr_value[WORKING_ATTR_VALUE_INDEX].float_value[0]); sl@0: break; sl@0: } sl@0: sl@0: case AT_INTEGER: sl@0: case AT_BOOLEAN: { sl@0: result = attr->attr_value[WORKING_ATTR_VALUE_INDEX].int_value[0]; sl@0: break; sl@0: } sl@0: sl@0: default: { sl@0: SET_ERROR(aContext, ATTR_ERROR_INVALID_TYPE); sl@0: break; sl@0: } sl@0: } sl@0: return result; sl@0: } sl@0: sl@0: /* sl@0: * \brief Return boolean attribute value sl@0: * sl@0: * \param aContext Attribute context sl@0: * \param aName Attribute name sl@0: * sl@0: * \return Attribute value sl@0: * ATTR_ERROR_INVALID_ATTRIBUTE sl@0: * ATTR_ERROR_INVALID_TYPE sl@0: */ sl@0: OWF_API_CALL OWFboolean sl@0: OWF_Attribute_GetValueb(OWF_ATTRIBUTE_LIST* aContext, sl@0: OWFint aName) sl@0: { sl@0: /* boolean is stored as int, must cast */ sl@0: return (OWFboolean) OWF_Attribute_GetValuei(aContext, aName); sl@0: } sl@0: sl@0: /* sl@0: * \brief Get attribute float value sl@0: * sl@0: * \param aContext sl@0: * \param aName sl@0: * \param aValue sl@0: * sl@0: * \return Attribute sl@0: */ sl@0: OWF_API_CALL OWFfloat sl@0: OWF_Attribute_GetValuef(OWF_ATTRIBUTE_LIST* aContext, sl@0: OWFint aName) sl@0: { sl@0: OWFint index = 0; sl@0: OWF_ATTRIBUTE* attr = NULL; sl@0: OWFfloat result = 0.f; sl@0: sl@0: COND_FAIL_NS(aContext, 0); sl@0: COND_FAIL(aContext, sl@0: aContext->attributes, sl@0: ATTR_ERROR_INVALID_CONTEXT, sl@0: 0); sl@0: CHECK_BAD(aContext, aName, 0); sl@0: sl@0: sl@0: index = aName - aContext->range_start; sl@0: attr = &aContext->attributes[index]; sl@0: sl@0: COND_FAIL(aContext, sl@0: 1 == attr->attr_info.length, sl@0: ATTR_ERROR_INVALID_TYPE, sl@0: 0); sl@0: sl@0: SET_ERROR(aContext, ATTR_ERROR_NONE); sl@0: result = 0.f; sl@0: sl@0: switch (attr->attr_info.type) { sl@0: case AT_FLOAT: { sl@0: result = attr->attr_value[WORKING_ATTR_VALUE_INDEX].float_value[0]; sl@0: break; sl@0: } sl@0: sl@0: case AT_INTEGER: sl@0: case AT_BOOLEAN: { sl@0: result = (OWFfloat) attr->attr_value[WORKING_ATTR_VALUE_INDEX].int_value[0]; sl@0: break; sl@0: } sl@0: sl@0: default: { sl@0: SET_ERROR(aContext, ATTR_ERROR_INVALID_TYPE); sl@0: break; sl@0: } sl@0: } sl@0: return result; sl@0: } sl@0: sl@0: /* sl@0: * \brief sl@0: * sl@0: * \param aContext sl@0: * \param aName sl@0: * \param aSize sl@0: * \param aValue sl@0: * sl@0: * \return sl@0: */ sl@0: OWF_API_CALL OWFint sl@0: OWF_Attribute_GetValueiv(OWF_ATTRIBUTE_LIST* aContext, sl@0: OWFint aName, sl@0: OWFint aLength, sl@0: OWFint* aValue) sl@0: { sl@0: OWFint index = 0; sl@0: OWF_ATTRIBUTE* attr = NULL; sl@0: OWFint count = 0; sl@0: sl@0: COND_FAIL_NS(aContext, 0); sl@0: COND_FAIL(aContext, sl@0: aContext->attributes, sl@0: ATTR_ERROR_INVALID_CONTEXT, sl@0: 0); sl@0: CHECK_BAD(aContext, aName, 0); sl@0: sl@0: sl@0: index = aName - aContext->range_start; sl@0: attr = &aContext->attributes[index]; sl@0: sl@0: COND_FAIL(aContext, sl@0: attr->attr_info.length >= 1, sl@0: ATTR_ERROR_INVALID_TYPE, sl@0: 0); sl@0: sl@0: if (!aValue) { sl@0: /* fetch size only */ sl@0: return attr->attr_info.length; sl@0: } sl@0: sl@0: count = min(aLength, attr->attr_info.length); sl@0: sl@0: SET_ERROR(aContext, ATTR_ERROR_NONE); sl@0: sl@0: switch (attr->attr_info.type) { sl@0: case AT_FLOAT: { sl@0: OWFint i; sl@0: OWFfloat* v = attr->attr_value[WORKING_ATTR_VALUE_INDEX].float_value; sl@0: for (i = 0; i < count; i++) { sl@0: aValue[i] = floor(v[i]); sl@0: } sl@0: break; sl@0: } sl@0: sl@0: case AT_BOOLEAN: sl@0: case AT_INTEGER: { sl@0: memcpy(aValue, sl@0: attr->attr_value[WORKING_ATTR_VALUE_INDEX].int_value, sl@0: count * attr->attr_info.size); sl@0: break; sl@0: } sl@0: sl@0: default: { sl@0: SET_ERROR(aContext, ATTR_ERROR_INVALID_TYPE); sl@0: break; sl@0: } sl@0: } sl@0: return count; sl@0: } sl@0: sl@0: /* sl@0: * \brief sl@0: * sl@0: * \param aContext sl@0: * \param aName sl@0: * \param aSize sl@0: * \param aValue sl@0: * sl@0: * \return sl@0: */ sl@0: OWF_API_CALL OWFint sl@0: OWF_Attribute_GetValuefv(OWF_ATTRIBUTE_LIST* aContext, sl@0: OWFint aName, sl@0: OWFint aLength, sl@0: OWFfloat* aValue) sl@0: { sl@0: OWFint index = 0; sl@0: OWF_ATTRIBUTE* attr = NULL; sl@0: OWFint count = 0; sl@0: sl@0: COND_FAIL_NS(aContext, 0); sl@0: COND_FAIL(aContext, sl@0: aContext->attributes, sl@0: ATTR_ERROR_INVALID_CONTEXT, sl@0: 0); sl@0: CHECK_BAD(aContext, aName, 0); sl@0: sl@0: sl@0: index = aName - aContext->range_start; sl@0: attr = &aContext->attributes[index]; sl@0: sl@0: COND_FAIL(aContext, sl@0: attr->attr_info.length >= 1, sl@0: ATTR_ERROR_INVALID_TYPE, 0); sl@0: sl@0: if (!aValue) { sl@0: /* fetch size only */ sl@0: return attr->attr_info.length; sl@0: } sl@0: sl@0: count = min(aLength, attr->attr_info.length); sl@0: sl@0: SET_ERROR(aContext, ATTR_ERROR_NONE); sl@0: sl@0: switch (attr->attr_info.type) { sl@0: case AT_FLOAT: { sl@0: memcpy(aValue, sl@0: attr->attr_value[WORKING_ATTR_VALUE_INDEX].float_value, sl@0: count * attr->attr_info.size); sl@0: break; sl@0: } sl@0: sl@0: case AT_BOOLEAN: sl@0: case AT_INTEGER: { sl@0: OWFint i; sl@0: OWFint* v = attr->attr_value[WORKING_ATTR_VALUE_INDEX].int_value; sl@0: for (i = 0; i < count; i++) { sl@0: aValue[i] = (OWFfloat) v[i]; sl@0: } sl@0: break; sl@0: } sl@0: sl@0: default: { sl@0: SET_ERROR(aContext, ATTR_ERROR_INVALID_TYPE); sl@0: break; sl@0: } sl@0: } sl@0: return count; sl@0: } sl@0: sl@0: /* sl@0: ============================================================================= sl@0: SETTER FUNCTIONS sl@0: ============================================================================= sl@0: */ sl@0: sl@0: /* sl@0: * \brief sl@0: * sl@0: * \param aContext sl@0: * \param aName sl@0: * \param aValue sl@0: * sl@0: * \return sl@0: */ sl@0: OWF_API_CALL void sl@0: OWF_Attribute_SetValuei(OWF_ATTRIBUTE_LIST* aContext, sl@0: OWFint aName, sl@0: OWFint aValue) sl@0: { sl@0: OWFint index = 0; sl@0: OWF_ATTRIBUTE* attr = NULL; sl@0: sl@0: COND_FAIL_NR_NS(aContext); sl@0: COND_FAIL_NR(aContext, aContext->attributes, ATTR_ERROR_INVALID_CONTEXT); sl@0: CHECK_BAD_NR(aContext, aName); sl@0: sl@0: sl@0: index = aName - aContext->range_start; sl@0: attr = &aContext->attributes[index]; sl@0: sl@0: COND_FAIL_NR(aContext, sl@0: 1 == attr->attr_info.length, sl@0: ATTR_ERROR_INVALID_TYPE); sl@0: COND_FAIL_NR(aContext, !attr->attr_info.readonly, ATTR_ERROR_ACCESS_DENIED); sl@0: sl@0: SET_ERROR(aContext, ATTR_ERROR_NONE); sl@0: sl@0: attr->attr_info.dirty = 1; sl@0: sl@0: switch (attr->attr_info.type) { sl@0: case AT_FLOAT: { sl@0: attr->attr_value[WORKING_ATTR_VALUE_INDEX].float_value[0] = aValue; sl@0: break; sl@0: } sl@0: sl@0: case AT_INTEGER: sl@0: case AT_BOOLEAN: { sl@0: attr->attr_value[WORKING_ATTR_VALUE_INDEX].int_value[0] = aValue; sl@0: break; sl@0: } sl@0: sl@0: default: { sl@0: SET_ERROR(aContext, ATTR_ERROR_INVALID_TYPE); sl@0: break; sl@0: } sl@0: } sl@0: } sl@0: sl@0: /* sl@0: * \brief sl@0: * sl@0: * \param aContext sl@0: * \param aName sl@0: * \param aValue sl@0: * sl@0: * \return sl@0: */ sl@0: OWF_API_CALL void sl@0: OWF_Attribute_SetValuef(OWF_ATTRIBUTE_LIST* aContext, sl@0: OWFint aName, sl@0: OWFfloat aValue) sl@0: { sl@0: OWFint index = 0; sl@0: OWF_ATTRIBUTE* attr = NULL; sl@0: sl@0: COND_FAIL_NR_NS(aContext); sl@0: COND_FAIL_NR(aContext, aContext->attributes, ATTR_ERROR_INVALID_CONTEXT); sl@0: CHECK_BAD_NR(aContext, aName); sl@0: sl@0: sl@0: index = aName - aContext->range_start; sl@0: attr = &aContext->attributes[index]; sl@0: sl@0: COND_FAIL_NR(aContext, sl@0: 1 == attr->attr_info.length, sl@0: ATTR_ERROR_INVALID_TYPE); sl@0: COND_FAIL_NR(aContext, sl@0: !attr->attr_info.readonly, sl@0: ATTR_ERROR_ACCESS_DENIED); sl@0: sl@0: SET_ERROR(aContext, ATTR_ERROR_NONE); sl@0: sl@0: attr->attr_info.dirty = 1; sl@0: sl@0: switch (attr->attr_info.type) { sl@0: case AT_FLOAT: { sl@0: attr->attr_value[WORKING_ATTR_VALUE_INDEX].float_value[0] = aValue; sl@0: break; sl@0: } sl@0: sl@0: case AT_INTEGER: sl@0: case AT_BOOLEAN: { sl@0: attr->attr_value[WORKING_ATTR_VALUE_INDEX].int_value[0] = floor(aValue); sl@0: break; sl@0: } sl@0: sl@0: default: { sl@0: SET_ERROR(aContext, ATTR_ERROR_INVALID_TYPE); sl@0: break; sl@0: } sl@0: } sl@0: } sl@0: sl@0: /* sl@0: * \brief sl@0: * sl@0: * \param sl@0: * \param sl@0: * \param sl@0: * sl@0: * \return sl@0: */ sl@0: OWF_API_CALL void sl@0: OWF_Attribute_SetValueb(OWF_ATTRIBUTE_LIST* aContext, sl@0: OWFint aName, sl@0: OWFboolean aValue) sl@0: { sl@0: OWF_Attribute_SetValuei(aContext, aName, (OWFint) aValue); sl@0: } sl@0: sl@0: /* sl@0: * \brief sl@0: * sl@0: * \param sl@0: * \param sl@0: * \param sl@0: * sl@0: * \return sl@0: */ sl@0: OWF_API_CALL void sl@0: OWF_Attribute_SetValueiv(OWF_ATTRIBUTE_LIST* aContext, sl@0: OWFint aName, sl@0: OWFint aLength, sl@0: const OWFint* aValue) sl@0: { sl@0: OWFint index = 0; sl@0: OWF_ATTRIBUTE* attr = NULL; sl@0: OWFint count = 0; sl@0: sl@0: COND_FAIL_NR_NS(aContext); sl@0: COND_FAIL_NR(aContext, aValue, ATTR_ERROR_INVALID_ARGUMENT); sl@0: COND_FAIL_NR(aContext, aContext->attributes, ATTR_ERROR_INVALID_CONTEXT); sl@0: CHECK_BAD_NR(aContext, aName); sl@0: sl@0: index = aName - aContext->range_start; sl@0: attr = &aContext->attributes[index]; sl@0: /* sl@0: COND_FAIL_NR(aContext, sl@0: attr->attr_info.length >= 1, sl@0: ATTR_ERROR_INVALID_TYPE); sl@0: */ sl@0: COND_FAIL_NR(aContext, sl@0: aLength > 0 && aLength <= attr->attr_info.length, sl@0: ATTR_ERROR_INVALID_ARGUMENT); sl@0: sl@0: COND_FAIL_NR(aContext, sl@0: !attr->attr_info.readonly, sl@0: ATTR_ERROR_ACCESS_DENIED); sl@0: sl@0: count = min(aLength, attr->attr_info.length); sl@0: sl@0: SET_ERROR(aContext, ATTR_ERROR_NONE); sl@0: sl@0: switch (attr->attr_info.type) { sl@0: case AT_FLOAT: { sl@0: OWFint i = 0; sl@0: OWFfloat* v = attr->attr_value[1].float_value; sl@0: for (i = 0; i < count; i++) { sl@0: v[i] = floor(aValue[i]); sl@0: } sl@0: break; sl@0: } sl@0: sl@0: case AT_BOOLEAN: sl@0: case AT_INTEGER: { sl@0: memcpy(attr->attr_value[1].int_value, sl@0: aValue, sl@0: count * attr->attr_info.size); sl@0: break; sl@0: } sl@0: sl@0: default: { sl@0: SET_ERROR(aContext, ATTR_ERROR_INVALID_TYPE); sl@0: break; sl@0: } sl@0: } sl@0: aContext->attributes[index].attr_info.dirty = 1; sl@0: } sl@0: sl@0: /* sl@0: * \brief sl@0: * sl@0: * \param sl@0: * \param sl@0: * \param sl@0: * sl@0: * \return sl@0: */ sl@0: OWF_API_CALL void sl@0: OWF_Attribute_SetValuefv(OWF_ATTRIBUTE_LIST* aContext, sl@0: OWFint aName, sl@0: OWFint aLength, sl@0: const OWFfloat* aValue) sl@0: { sl@0: OWFint index = 0; sl@0: OWF_ATTRIBUTE* attr = NULL; sl@0: OWFint count = 0; sl@0: sl@0: COND_FAIL_NR_NS(aContext); sl@0: COND_FAIL_NR(aContext, aValue, ATTR_ERROR_INVALID_ARGUMENT); sl@0: COND_FAIL_NR(aContext, aContext->attributes, ATTR_ERROR_INVALID_CONTEXT); sl@0: CHECK_BAD_NR(aContext, aName); sl@0: sl@0: index = aName - aContext->range_start; sl@0: attr = &aContext->attributes[index]; sl@0: sl@0: /* sl@0: COND_FAIL_NR(aContext, sl@0: attr->attr_info.length >= 1, sl@0: ATTR_ERROR_INVALID_TYPE); sl@0: */ sl@0: sl@0: COND_FAIL_NR(aContext, sl@0: aLength > 0 && aLength <= attr->attr_info.length, sl@0: ATTR_ERROR_INVALID_ARGUMENT); sl@0: sl@0: COND_FAIL_NR(aContext, sl@0: !attr->attr_info.readonly, sl@0: ATTR_ERROR_ACCESS_DENIED); sl@0: sl@0: count = min(aLength, attr->attr_info.length); sl@0: sl@0: SET_ERROR(aContext, ATTR_ERROR_NONE); sl@0: sl@0: switch (attr->attr_info.type) { sl@0: case AT_FLOAT: { sl@0: memcpy(attr->attr_value[1].float_value, sl@0: aValue, sl@0: count * attr->attr_info.size); sl@0: break; sl@0: } sl@0: sl@0: case AT_BOOLEAN: sl@0: case AT_INTEGER: { sl@0: OWFint i; sl@0: OWFint* v = attr->attr_value[1].int_value; sl@0: for (i = 0; i < count; i++) { sl@0: v[i] = floor(aValue[i]); sl@0: } sl@0: break; sl@0: } sl@0: sl@0: default: { sl@0: SET_ERROR(aContext, ATTR_ERROR_INVALID_TYPE); sl@0: break; sl@0: } sl@0: } sl@0: aContext->attributes[index].attr_info.dirty = 1; sl@0: } sl@0: sl@0: static OWFint OWF_Attribute_Commit(OWF_ATTRIBUTE* aAttr, sl@0: OWFint aDirtyFlag, sl@0: OWFint aCopyTo, sl@0: OWFint aCopyFrom ) sl@0: { sl@0: OWF_ASSERT(aCopyTo >= 0); sl@0: OWF_ASSERT(aCopyTo < NUM_ATTR_VALUE_COPIES); sl@0: OWF_ASSERT(aCopyFrom >= 0); sl@0: OWF_ASSERT(aCopyFrom < NUM_ATTR_VALUE_COPIES); sl@0: /* if type is undefined, it means there're gaps in the attribute sl@0: range (e.g. reservations for future use and such.) ignore them. */ sl@0: if (aAttr->attr_info.type != AT_UNDEFINED && aDirtyFlag) sl@0: { sl@0: /* poor-man's commit */ sl@0: memcpy(aAttr->attr_value[aCopyTo].gen_ptr, sl@0: aAttr->attr_value[aCopyFrom].gen_ptr, sl@0: aAttr->attr_info.size * aAttr->attr_info.length); sl@0: return 0; sl@0: } sl@0: else sl@0: { sl@0: return aDirtyFlag; sl@0: } sl@0: } sl@0: sl@0: sl@0: OWF_API_CALL void sl@0: OWF_AttributeList_Commit(OWF_ATTRIBUTE_LIST* aContext, sl@0: OWFint aStart, sl@0: OWFint aEnd, sl@0: OWFint aCopyTo ) sl@0: { sl@0: OWFint index = 0; sl@0: /* Attribute commit works like the element list commit sl@0: * by forward-copying the "working" attributes to the snapshot sl@0: * during client invoked commit, sl@0: * then copying the snapshot to the commited scene during the docommit job. sl@0: * This requires the same wait-for-the-previous-commit-job strategy used in the element commit. sl@0: * Could in future use copy-back technique to avoid having to wait substantially, sl@0: * in which case the index of the working attribute set would switch after each invoked commit, sl@0: * instead of being a constant. sl@0: * sl@0: * The same number of copies would still need to take place sl@0: * but would not need exclusive access to the list. sl@0: */ sl@0: sl@0: COND_FAIL_NR_NS(aContext); sl@0: COND_FAIL_NR(aContext, aStart <= aEnd, ATTR_ERROR_INVALID_ARGUMENT); sl@0: COND_FAIL_NR(aContext, aContext->attributes, ATTR_ERROR_INVALID_CONTEXT); sl@0: CHECK_BAD_NR(aContext, aStart); sl@0: CHECK_BAD_NR(aContext, aEnd); sl@0: sl@0: switch (aCopyTo) sl@0: { sl@0: case COMMITTED_ATTR_VALUE_INDEX: /* Used in composition thread to set displayed scene attributes */ sl@0: for (index = aStart; index <= aEnd; index++) sl@0: { sl@0: OWF_ATTRIBUTE* attr = &aContext->attributes[index - aContext->range_start]; sl@0: attr->attr_info.dirtysnapshot= sl@0: OWF_Attribute_Commit(attr,attr->attr_info.dirtysnapshot, sl@0: COMMITTED_ATTR_VALUE_INDEX,SNAPSHOT_ATTR_VALUE_INDEX); sl@0: } sl@0: break; sl@0: case SNAPSHOT_ATTR_VALUE_INDEX: /* Used in API threads to make a snapshot of the client attributes */ sl@0: for (index = aStart; index <= aEnd; index++) sl@0: { sl@0: OWF_ATTRIBUTE* attr = &aContext->attributes[index - aContext->range_start]; sl@0: OWFuint oldDirty=attr->attr_info.dirty; sl@0: attr->attr_info.dirtysnapshot=oldDirty; sl@0: attr->attr_info.dirty= sl@0: OWF_Attribute_Commit(attr,oldDirty, sl@0: SNAPSHOT_ATTR_VALUE_INDEX,WORKING_ATTR_VALUE_INDEX); sl@0: } sl@0: break; sl@0: case WORKING_ATTR_VALUE_INDEX: /* Used in initialisation to copy displayed attributes to client copies */ sl@0: for (index = aStart; index <= aEnd; index++) sl@0: { sl@0: OWF_ATTRIBUTE* attr = &aContext->attributes[index - aContext->range_start]; sl@0: OWF_Attribute_Commit(attr,!attr->attr_info.readonly, sl@0: WORKING_ATTR_VALUE_INDEX,COMMITTED_ATTR_VALUE_INDEX); sl@0: } sl@0: break; sl@0: case COMMIT_ATTR_DIRECT_FROM_WORKING: /* Used in WFD to commit new working values directly in 1 step. */ sl@0: for (index = aStart; index <= aEnd; index++) sl@0: { sl@0: OWF_ATTRIBUTE* attr = &aContext->attributes[index - aContext->range_start]; sl@0: attr->attr_info.dirty= sl@0: OWF_Attribute_Commit(attr,attr->attr_info.dirty, sl@0: COMMITTED_ATTR_VALUE_INDEX,WORKING_ATTR_VALUE_INDEX); sl@0: } sl@0: break; sl@0: default: sl@0: COND_FAIL_NR(aContext, 0, ATTR_ERROR_INVALID_ARGUMENT); sl@0: } sl@0: sl@0: SET_ERROR(aContext, ATTR_ERROR_NONE); sl@0: } sl@0: sl@0: #ifdef __cplusplus sl@0: } sl@0: #endif