diff -r 000000000000 -r 5d03bc08d59c graphicscomposition/openwfcompositionengine/common/src/owfattributes.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graphicscomposition/openwfcompositionengine/common/src/owfattributes.c Tue Feb 02 01:47:50 2010 +0200 @@ -0,0 +1,1027 @@ +/* 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. + */ + + + +#ifdef __cplusplus +extern "C" { +#endif + + +#include +#include +#include +#include + +#include "owfattributes.h" +#include "owfmemory.h" + +#define OWF_ATTRIB_RANGE_START (0) +#define OWF_ATTRIB_RANGE_UNINITIALIZED (-1) + +static OWFint OWF_Attribute_Commit(OWF_ATTRIBUTE* aAttr, OWFint aDirtyFlag, OWFint aCopyTo,OWFint aCopyFrom); + +/* + This attribute class is currently only used for context attributes. + Why isn't it used for element attributes? + - Because elements are completely cloned in the committed scene. + [This class could be replaced with 3 copies of a much simpler writable attributes raw + structure with simple data members, and the whole structure copied each commit.] + Normal attribute values have three pointers indexed via an array: + COMMITTED_ATTR_VALUE_INDEX: + Attribute values used by the scene + - points to named variables directly used by the compositor + WORKING_ATTR_VALUE_INDEX: + Attribute values that may be set by the client, if they are not read-only. + SNAPSHOT_ATTR_VALUE_INDEX + A copy of the client-set attribute values following a client call to wfcCommit + The copy is then protected against further modification by the client until + the committed scene is updated and displayed. + The Working and Snapshot writable attributes require additional cache storage, + which is managed by the lifetime of the attribute list. + Read-only attributes point all three pointers at the named compositor variables. + Currently, there are relatively few writable attributes so it is reasonable + to individually dynamically allocate each cache. It would be better to allocate + a single block sized after the attributes have been registered. + */ +#define COND_FAIL_NR(ctx, condition, error) \ + if (!(condition)) { \ + if (ctx) { \ + (ctx)->last_error = error; \ + } \ + return; \ + } + +#define COND_FAIL(ctx, condition, error, r) \ + if (!(condition)) { \ + if (ctx) { \ + (ctx)->last_error = error; \ + } \ + return r; \ + } + +#define CHECK_INDEX_NR(ctx, index, error) \ + if (index < (ctx)->range_start || index > (ctx)->range_end) { \ + (ctx)->last_error = error; \ + return; \ + } + +#define CHECK_INDEX(ctx, index, error, r) \ + if (index < (ctx)->range_start || index > (ctx)->range_end) { \ + (ctx)->last_error = error; \ + return r; \ + } + +#define CHECK_BAD_NR(ctx, index) \ + CHECK_INDEX_NR(ctx, index, ATTR_ERROR_INVALID_ATTRIBUTE); \ + if ((ctx)->attributes[index-(ctx)->range_start].attr_info.type == AT_UNDEFINED) { \ + (ctx)->last_error = ATTR_ERROR_INVALID_ATTRIBUTE; \ + return; \ + } + +#define CHECK_BAD(ctx, index, r) \ + CHECK_INDEX(ctx, index, ATTR_ERROR_INVALID_ATTRIBUTE, r); \ + if ((ctx)->attributes[index-(ctx)->range_start].attr_info.type == AT_UNDEFINED) { \ + (ctx)->last_error = ATTR_ERROR_INVALID_ATTRIBUTE; \ + return r; \ + } + +#define SET_ERROR(ctx, err) \ + if ((ctx)->last_error == ATTR_ERROR_NONE) { \ + (ctx)->last_error = err; \ + } + + +/* +============================================================================= +ATTRIBUTE CONTEXT MANAGEMENT FUNCTIONS +============================================================================= +*/ + +/*! + * \brief Initializes attribute context + * + * \param aContext Attribute context to initialize + * \param aStart Attribute range start + * \param aEnd Attribute range end. Must be greater than range start. + * + * \return ATTR_ERROR_INVALID_ARGUMENT + * ATTR_ERROR_NO_MEMORY + */ +OWF_API_CALL void +OWF_AttributeList_Create(OWF_ATTRIBUTE_LIST* aContext, + OWFint aStart, + OWFint aEnd) +{ + OWF_ATTRIBUTE* temp = NULL; + + COND_FAIL_NR(aContext, aContext, ATTR_ERROR_INVALID_ARGUMENT); + COND_FAIL_NR(aContext, aEnd >= 0, ATTR_ERROR_INVALID_ARGUMENT); + COND_FAIL_NR(aContext, aEnd >= aStart, ATTR_ERROR_INVALID_ARGUMENT); + + aContext->range_start = OWF_ATTRIB_RANGE_START; + aContext->range_end = OWF_ATTRIB_RANGE_UNINITIALIZED; + + temp = (OWF_ATTRIBUTE*) xalloc(aEnd - aStart + 1, sizeof(OWF_ATTRIBUTE)); + COND_FAIL_NR(aContext, temp, ATTR_ERROR_NO_MEMORY); + + memset(aContext, 0, sizeof(OWF_ATTRIBUTE_LIST)); + + aContext->range_start = aStart; + aContext->range_end = aEnd; + aContext->attributes = temp; + + SET_ERROR(aContext, ATTR_ERROR_NONE); + return; +} + +/*! + * \brief Destroy attribute context and free any resources (memory + * blocks) allocated to it. All attributes are destroyed. + * + * \param aContext Attribute context to destroy + * + * \return ATTR_ERROR_INVALID_ARGUMENT + * ATTR_ERROR_INVALID_CONTEXT + */ +OWF_API_CALL void +OWF_AttributeList_Destroy(OWF_ATTRIBUTE_LIST* aContext) +{ + OWFint count = 0; + OWFint at = 0; + OWFint cache = 0; + + COND_FAIL_NR(aContext, aContext, ATTR_ERROR_INVALID_ARGUMENT); + COND_FAIL_NR(aContext, aContext->attributes, ATTR_ERROR_INVALID_CONTEXT); + + count = aContext->range_end - aContext->range_start; + for (at = 0; at <= count; at++) { + OWF_ATTRIBUTE* attr = &aContext->attributes[at]; + if (!attr->attr_info.readonly) + { + for (cache=0;cacheattr_value[cache].gen_ptr); + } + } + } + } + + xfree(aContext->attributes); + memset(aContext, 0, sizeof(OWF_ATTRIBUTE_LIST)); + SET_ERROR(aContext, ATTR_ERROR_NONE); + return; +} + +/* + + + */ +OWF_API_CALL OWF_ATTRIBUTE_LIST_STATUS +OWF_AttributeList_GetError(OWF_ATTRIBUTE_LIST* aContext) +{ + OWF_ATTRIBUTE_LIST_STATUS error; + + if (!aContext) { + return ATTR_ERROR_INVALID_ARGUMENT; + } + error = aContext->last_error; + aContext->last_error = ATTR_ERROR_NONE; + return error; +} + +/* +============================================================================= +INITIALIZATION FUNCTIONS +============================================================================= +*/ + +static void OWF_Attribute_Init(OWF_ATTRIBUTE_LIST* aContext, + OWFint aName, + OWF_ATTRIBUTE_TYPE aType, + OWFint aLength, + void* aValue, + OWFboolean aRdOnly) +{ + OWF_ATTRIBUTE* attr = NULL; + void* cache = NULL; + OWFint itemSize; + OWFint arraySize; + OWFint copy; + OWFint index = aName - aContext->range_start; + + COND_FAIL_NR(aContext, aContext, ATTR_ERROR_INVALID_ARGUMENT); + CHECK_INDEX_NR(aContext, aName, ATTR_ERROR_INVALID_ATTRIBUTE); + COND_FAIL_NR(aContext, aContext->attributes, ATTR_ERROR_INVALID_CONTEXT); + COND_FAIL_NR(aContext, aLength < MAX_ATTR_LENGTH, ATTR_ERROR_CANT_HANDLE); + COND_FAIL_NR(aContext, aType != AT_UNDEFINED, ATTR_ERROR_INVALID_ARGUMENT); + + attr = &aContext->attributes[index]; + + memset(attr, 0, sizeof(OWF_ATTRIBUTE)); + + /* when allocin', size DOES matter */ + + if (aType == AT_INTEGER || aType == AT_BOOLEAN) { + itemSize = sizeof(OWFint); + } else { + itemSize = sizeof(OWFfloat); + } + arraySize=itemSize*aLength; + + /* don't allocate cache for read-only 'butes */ + attr->attr_info.type = aType; + attr->attr_info.length = aLength; + attr->attr_info.readonly = aRdOnly; + attr->attr_info.size = itemSize; + if (aRdOnly) + { + for (copy=0;copyattr_value[copy].gen_ptr = aValue; + } + } + else + { + for (copy=0;copyattr_value[COMMITTED_ATTR_VALUE_INDEX].gen_ptr = aValue; + } + else + { + cache = xalloc(arraySize,1); + COND_FAIL_NR(aContext, NULL != cache, ATTR_ERROR_NO_MEMORY); + attr->attr_value[copy].gen_ptr = cache; + } + } + OWF_Attribute_Commit(attr,1, + WORKING_ATTR_VALUE_INDEX,COMMITTED_ATTR_VALUE_INDEX); + } + + + + + + SET_ERROR(aContext, ATTR_ERROR_NONE); + +} + +/* + * \brief Intialize integer attribute + * + * \param aContext Attibute context + * \param aName Attribute name + * \param aValue Attribute initial value + * \param aRdOnly Read-only flag + * + * \return ATTR_ERROR_INVALID_ARGUMENT + * ATTR_ERROR_INVALID_ATTRIBUTE + * ATTR_ERROR_INVALID_CONTEXT + */ +OWF_API_CALL void +OWF_Attribute_Initi(OWF_ATTRIBUTE_LIST* aContext, + OWFint aName, + OWF_INT_REF aValue, + OWFboolean aRdOnly) +{ + OWF_Attribute_Init(aContext, aName, AT_INTEGER, 1, aValue, aRdOnly); +} + +/* + * \brief Initialize float attribute + * + * \param aContext Attribute context + * \param aName Attribute name + * \param aValue Initial value for attribute + * \param aRdOnly Read-only flag + * + * \return ATTR_ERROR_INVALID_ARGUMENT + * ATTR_ERROR_INVALID_ATTRIBUTE + * ATTR_ERROR_INVALID_CONTEXT + */ +OWF_API_CALL void +OWF_Attribute_Initf(OWF_ATTRIBUTE_LIST* aContext, + OWFint aName, + OWF_FLOAT_REF aValue, + OWFboolean aRdOnly) +{ + OWF_Attribute_Init(aContext, aName, AT_FLOAT, 1, aValue, aRdOnly); +} + +/* + * \brief Initialize boolean attribute + * + * \param aContext Attribute context + * \param aName Attribute name + * \param aValue Initial value for attribute + * \param aRdOnly Read-only flag + * + * \return ATTR_ERROR_INVALID_ARGUMENT + * ATTR_ERROR_INVALID_ATTRIBUTE + * ATTR_ERROR_INVALID_CONTEXT + */ +OWF_API_CALL void +OWF_Attribute_Initb(OWF_ATTRIBUTE_LIST* aContext, + OWFint aName, + OWF_BOOL_REF aValue, + OWFboolean aRdOnly) +{ + OWF_Attribute_Init(aContext, aName, AT_BOOLEAN, 1, aValue, aRdOnly); +} + +/* + * \brief Initialize vector attribute + * + * \param aContext Attribute context + * \param aName Attribute name + * \param aLength Attribute (vector) length + * \param aValues Initial value(s) for attribute + * \param aRdOnly Read-only flag + * + * \return ATTR_ERROR_INVALID_ARGUMENT + * ATTR_ERROR_INVALID_ATTRIBUTE + * ATTR_ERROR_INVALID_CONTEXT + * ATTR_ERROR_CANT_HANDLE + */ +OWF_API_CALL void +OWF_Attribute_Initiv(OWF_ATTRIBUTE_LIST* aContext, + OWFint aName, + OWFint aLength, + OWF_INT_VECTOR_REF aValues, + OWFboolean aRdOnly) +{ + OWF_Attribute_Init(aContext, aName, AT_INTEGER, aLength, aValues, aRdOnly); +} + +/* + * \brief Initialize vector attribute + * + * \param aContext Attribute context + * \param aName Attribute name + * \param aLength Attribute (vector) length + * \param aValues Initial value(s) for attributes + * \param aRdOnly Read-only flag + * + * \return + */ +OWF_API_CALL void +OWF_Attribute_Initfv(OWF_ATTRIBUTE_LIST* aContext, + OWFint aName, + OWFint aLength, + OWF_FLOAT_VECTOR_REF aValues, + OWFboolean aRdOnly) +{ + OWF_Attribute_Init(aContext, aName, AT_FLOAT, aLength, aValues, aRdOnly); +} + +/* +============================================================================= +GETTER FUNCTIONS +============================================================================= +*/ + +/* + * \brief Get attribute integer value. + * + * \param aContext Attribute context + * \param aName Attribute name + * + * \return Attribute integer value (floats are floor()ed). For vector + * attributes the return value will be error ATTR_ERROR_INVALID_TYPE. + * ATTR_ERROR_INVALID_ATTRIBUTE + * ATTR_ERROR_INVALID_CONTEXT + */ +OWF_API_CALL OWFint +OWF_Attribute_GetValuei(OWF_ATTRIBUTE_LIST* aContext, + OWFint aName) +{ + OWFint index = 0; + OWF_ATTRIBUTE* attr = 0; + OWFint result = 0; + + COND_FAIL(aContext, aContext, ATTR_ERROR_INVALID_ARGUMENT, 0); + CHECK_BAD(aContext, aName, 0); + COND_FAIL(aContext, + aContext->attributes, + ATTR_ERROR_INVALID_CONTEXT, + 0); + + index = aName - aContext->range_start; + attr = &aContext->attributes[index]; + + COND_FAIL(aContext, + 1 == attr->attr_info.length, + ATTR_ERROR_INVALID_TYPE, + 0); + + SET_ERROR(aContext, ATTR_ERROR_NONE); + + switch (attr->attr_info.type) { + case AT_FLOAT: { + result = floor(attr->attr_value[WORKING_ATTR_VALUE_INDEX].float_value[0]); + break; + } + + case AT_INTEGER: + case AT_BOOLEAN: { + result = attr->attr_value[WORKING_ATTR_VALUE_INDEX].int_value[0]; + break; + } + + default: { + SET_ERROR(aContext, ATTR_ERROR_INVALID_TYPE); + break; + } + } + return result; +} + +/* + * \brief Return boolean attribute value + * + * \param aContext Attribute context + * \param aName Attribute name + * + * \return Attribute value + * ATTR_ERROR_INVALID_ATTRIBUTE + * ATTR_ERROR_INVALID_TYPE + */ +OWF_API_CALL OWFboolean +OWF_Attribute_GetValueb(OWF_ATTRIBUTE_LIST* aContext, + OWFint aName) +{ + /* boolean is stored as int, must cast */ + return (OWFboolean) OWF_Attribute_GetValuei(aContext, aName); +} + +/* + * \brief Get attribute float value + * + * \param aContext + * \param aName + * \param aValue + * + * \return Attribute + */ +OWF_API_CALL OWFfloat +OWF_Attribute_GetValuef(OWF_ATTRIBUTE_LIST* aContext, + OWFint aName) +{ + OWFint index = 0; + OWF_ATTRIBUTE* attr = NULL; + OWFfloat result = 0.f; + + COND_FAIL(aContext, aContext, ATTR_ERROR_INVALID_ARGUMENT, 0); + CHECK_BAD(aContext, aName, 0); + COND_FAIL(aContext, + aContext->attributes, + ATTR_ERROR_INVALID_CONTEXT, + 0); + + index = aName - aContext->range_start; + attr = &aContext->attributes[index]; + + COND_FAIL(aContext, + 1 == attr->attr_info.length, + ATTR_ERROR_INVALID_TYPE, + 0); + + SET_ERROR(aContext, ATTR_ERROR_NONE); + result = 0.f; + + switch (attr->attr_info.type) { + case AT_FLOAT: { + result = attr->attr_value[WORKING_ATTR_VALUE_INDEX].float_value[0]; + break; + } + + case AT_INTEGER: + case AT_BOOLEAN: { + result = (OWFfloat) attr->attr_value[WORKING_ATTR_VALUE_INDEX].int_value[0]; + break; + } + + default: { + SET_ERROR(aContext, ATTR_ERROR_INVALID_TYPE); + break; + } + } + return result; +} + +/* + * \brief + * + * \param aContext + * \param aName + * \param aSize + * \param aValue + * + * \return + */ +OWF_API_CALL OWFint +OWF_Attribute_GetValueiv(OWF_ATTRIBUTE_LIST* aContext, + OWFint aName, + OWFint aLength, + OWFint* aValue) +{ + OWFint index = 0; + OWF_ATTRIBUTE* attr = NULL; + OWFint count = 0; + + COND_FAIL(aContext, aContext, ATTR_ERROR_INVALID_ARGUMENT, 0); + CHECK_BAD(aContext, aName, 0); + COND_FAIL(aContext, + aContext->attributes, + ATTR_ERROR_INVALID_CONTEXT, + 0); + + index = aName - aContext->range_start; + attr = &aContext->attributes[index]; + + COND_FAIL(aContext, + attr->attr_info.length >= 1, + ATTR_ERROR_INVALID_TYPE, + 0); + + if (!aValue) { + /* fetch size only */ + return attr->attr_info.length; + } + + count = min(aLength, attr->attr_info.length); + + SET_ERROR(aContext, ATTR_ERROR_NONE); + + switch (attr->attr_info.type) { + case AT_FLOAT: { + OWFint i; + OWFfloat* v = attr->attr_value[WORKING_ATTR_VALUE_INDEX].float_value; + for (i = 0; i < count; i++) { + aValue[i] = floor(v[i]); + } + break; + } + + case AT_BOOLEAN: + case AT_INTEGER: { + memcpy(aValue, + attr->attr_value[WORKING_ATTR_VALUE_INDEX].int_value, + count * attr->attr_info.size); + break; + } + + default: { + SET_ERROR(aContext, ATTR_ERROR_INVALID_TYPE); + break; + } + } + return count; +} + +/* + * \brief + * + * \param aContext + * \param aName + * \param aSize + * \param aValue + * + * \return + */ +OWF_API_CALL OWFint +OWF_Attribute_GetValuefv(OWF_ATTRIBUTE_LIST* aContext, + OWFint aName, + OWFint aLength, + OWFfloat* aValue) +{ + OWFint index = 0; + OWF_ATTRIBUTE* attr = NULL; + OWFint count = 0; + + COND_FAIL(aContext, aContext, ATTR_ERROR_INVALID_ARGUMENT, 0); + CHECK_BAD(aContext, aName, 0); + COND_FAIL(aContext, + aContext->attributes, + ATTR_ERROR_INVALID_CONTEXT, + 0); + + index = aName - aContext->range_start; + attr = &aContext->attributes[index]; + + COND_FAIL(aContext, + attr->attr_info.length >= 1, + ATTR_ERROR_INVALID_TYPE, 0); + + if (!aValue) { + /* fetch size only */ + return attr->attr_info.length; + } + + count = min(aLength, attr->attr_info.length); + + SET_ERROR(aContext, ATTR_ERROR_NONE); + + switch (attr->attr_info.type) { + case AT_FLOAT: { + memcpy(aValue, + attr->attr_value[WORKING_ATTR_VALUE_INDEX].float_value, + count * attr->attr_info.size); + break; + } + + case AT_BOOLEAN: + case AT_INTEGER: { + OWFint i; + OWFint* v = attr->attr_value[WORKING_ATTR_VALUE_INDEX].int_value; + for (i = 0; i < count; i++) { + aValue[i] = (OWFfloat) v[i]; + } + break; + } + + default: { + SET_ERROR(aContext, ATTR_ERROR_INVALID_TYPE); + break; + } + } + return count; +} + +/* +============================================================================= +SETTER FUNCTIONS +============================================================================= +*/ + +/* + * \brief + * + * \param aContext + * \param aName + * \param aValue + * + * \return + */ +OWF_API_CALL void +OWF_Attribute_SetValuei(OWF_ATTRIBUTE_LIST* aContext, + OWFint aName, + OWFint aValue) +{ + OWFint index = 0; + OWF_ATTRIBUTE* attr = NULL; + + COND_FAIL_NR(aContext, aContext, ATTR_ERROR_INVALID_ARGUMENT); + CHECK_BAD_NR(aContext, aName); + COND_FAIL_NR(aContext, aContext->attributes, ATTR_ERROR_INVALID_CONTEXT); + + index = aName - aContext->range_start; + attr = &aContext->attributes[index]; + + COND_FAIL_NR(aContext, + 1 == attr->attr_info.length, + ATTR_ERROR_INVALID_TYPE); + COND_FAIL_NR(aContext, !attr->attr_info.readonly, ATTR_ERROR_ACCESS_DENIED); + + SET_ERROR(aContext, ATTR_ERROR_NONE); + + attr->attr_info.dirty = 1; + + switch (attr->attr_info.type) { + case AT_FLOAT: { + attr->attr_value[WORKING_ATTR_VALUE_INDEX].float_value[0] = aValue; + break; + } + + case AT_INTEGER: + case AT_BOOLEAN: { + attr->attr_value[WORKING_ATTR_VALUE_INDEX].int_value[0] = aValue; + break; + } + + default: { + SET_ERROR(aContext, ATTR_ERROR_INVALID_TYPE); + break; + } + } +} + +/* + * \brief + * + * \param aContext + * \param aName + * \param aValue + * + * \return + */ +OWF_API_CALL void +OWF_Attribute_SetValuef(OWF_ATTRIBUTE_LIST* aContext, + OWFint aName, + OWFfloat aValue) +{ + OWFint index = 0; + OWF_ATTRIBUTE* attr = NULL; + + COND_FAIL_NR(aContext, aContext, ATTR_ERROR_INVALID_ARGUMENT); + CHECK_BAD_NR(aContext, aName); + COND_FAIL_NR(aContext, aContext->attributes, ATTR_ERROR_INVALID_CONTEXT); + + index = aName - aContext->range_start; + attr = &aContext->attributes[index]; + + COND_FAIL_NR(aContext, + 1 == attr->attr_info.length, + ATTR_ERROR_INVALID_TYPE); + COND_FAIL_NR(aContext, + !attr->attr_info.readonly, + ATTR_ERROR_ACCESS_DENIED); + + SET_ERROR(aContext, ATTR_ERROR_NONE); + + attr->attr_info.dirty = 1; + + switch (attr->attr_info.type) { + case AT_FLOAT: { + attr->attr_value[WORKING_ATTR_VALUE_INDEX].float_value[0] = aValue; + break; + } + + case AT_INTEGER: + case AT_BOOLEAN: { + attr->attr_value[WORKING_ATTR_VALUE_INDEX].int_value[0] = floor(aValue); + break; + } + + default: { + SET_ERROR(aContext, ATTR_ERROR_INVALID_TYPE); + break; + } + } +} + +/* + * \brief + * + * \param + * \param + * \param + * + * \return + */ +OWF_API_CALL void +OWF_Attribute_SetValueb(OWF_ATTRIBUTE_LIST* aContext, + OWFint aName, + OWFboolean aValue) +{ + OWF_Attribute_SetValuei(aContext, aName, (OWFint) aValue); +} + +/* + * \brief + * + * \param + * \param + * \param + * + * \return + */ +OWF_API_CALL void +OWF_Attribute_SetValueiv(OWF_ATTRIBUTE_LIST* aContext, + OWFint aName, + OWFint aLength, + const OWFint* aValue) +{ + OWFint index = 0; + OWF_ATTRIBUTE* attr = NULL; + OWFint count = 0; + + COND_FAIL_NR(aContext, aContext, ATTR_ERROR_INVALID_ARGUMENT); + COND_FAIL_NR(aContext, aValue, ATTR_ERROR_INVALID_ARGUMENT); + COND_FAIL_NR(aContext, aContext->attributes, ATTR_ERROR_INVALID_CONTEXT); + CHECK_BAD_NR(aContext, aName); + + index = aName - aContext->range_start; + attr = &aContext->attributes[index]; +/* + COND_FAIL_NR(aContext, + attr->attr_info.length >= 1, + ATTR_ERROR_INVALID_TYPE); +*/ + COND_FAIL_NR(aContext, + aLength > 0 && aLength <= attr->attr_info.length, + ATTR_ERROR_INVALID_ARGUMENT); + + COND_FAIL_NR(aContext, + !attr->attr_info.readonly, + ATTR_ERROR_ACCESS_DENIED); + + count = min(aLength, attr->attr_info.length); + + SET_ERROR(aContext, ATTR_ERROR_NONE); + + switch (attr->attr_info.type) { + case AT_FLOAT: { + OWFint i = 0; + OWFfloat* v = attr->attr_value[1].float_value; + for (i = 0; i < count; i++) { + v[i] = floor(aValue[i]); + } + break; + } + + case AT_BOOLEAN: + case AT_INTEGER: { + memcpy(attr->attr_value[1].int_value, + aValue, + count * attr->attr_info.size); + break; + } + + default: { + SET_ERROR(aContext, ATTR_ERROR_INVALID_TYPE); + break; + } + } + aContext->attributes[index].attr_info.dirty = 1; +} + +/* + * \brief + * + * \param + * \param + * \param + * + * \return + */ +OWF_API_CALL void +OWF_Attribute_SetValuefv(OWF_ATTRIBUTE_LIST* aContext, + OWFint aName, + OWFint aLength, + const OWFfloat* aValue) +{ + OWFint index = 0; + OWF_ATTRIBUTE* attr = NULL; + OWFint count = 0; + + COND_FAIL_NR(aContext, aContext, ATTR_ERROR_INVALID_ARGUMENT); + COND_FAIL_NR(aContext, aValue, ATTR_ERROR_INVALID_ARGUMENT); + COND_FAIL_NR(aContext, aContext->attributes, ATTR_ERROR_INVALID_CONTEXT); + CHECK_BAD_NR(aContext, aName); + + index = aName - aContext->range_start; + attr = &aContext->attributes[index]; + +/* + COND_FAIL_NR(aContext, + attr->attr_info.length >= 1, + ATTR_ERROR_INVALID_TYPE); +*/ + + COND_FAIL_NR(aContext, + aLength > 0 && aLength <= attr->attr_info.length, + ATTR_ERROR_INVALID_ARGUMENT); + + COND_FAIL_NR(aContext, + !attr->attr_info.readonly, + ATTR_ERROR_ACCESS_DENIED); + + count = min(aLength, attr->attr_info.length); + + SET_ERROR(aContext, ATTR_ERROR_NONE); + + switch (attr->attr_info.type) { + case AT_FLOAT: { + memcpy(attr->attr_value[1].float_value, + aValue, + count * attr->attr_info.size); + break; + } + + case AT_BOOLEAN: + case AT_INTEGER: { + OWFint i; + OWFint* v = attr->attr_value[1].int_value; + for (i = 0; i < count; i++) { + v[i] = floor(aValue[i]); + } + break; + } + + default: { + SET_ERROR(aContext, ATTR_ERROR_INVALID_TYPE); + break; + } + } + aContext->attributes[index].attr_info.dirty = 1; +} + +static OWFint OWF_Attribute_Commit(OWF_ATTRIBUTE* aAttr, + OWFint aDirtyFlag, + OWFint aCopyTo, + OWFint aCopyFrom ) + { + /* if type is undefined, it means there're gaps in the attribute + range (e.g. reservations for future use and such.) ignore them. */ + if (aAttr->attr_info.type != AT_UNDEFINED && aDirtyFlag) + { + /* poor-man's commit */ + memcpy(aAttr->attr_value[aCopyTo].gen_ptr, + aAttr->attr_value[aCopyFrom].gen_ptr, + aAttr->attr_info.size * aAttr->attr_info.length); + return 0; + } + else + { + return aDirtyFlag; + } + } + +OWF_API_CALL void +OWF_AttributeList_Commit(OWF_ATTRIBUTE_LIST* aContext, + OWFint aStart, + OWFint aEnd, + OWFint aCopyTo ) +{ + OWFint index = 0; + /* Attribute commit works like the element list commit + * by forward-copying the "working" attributes to the snapshot + * during client invoked commit, + * then copying the snapshot to the commited scene during the docommit job. + * This requires the same wait-for-the-previous-commit-job strategy used in the element commit. + * Could in future use copy-back technique to avoid having to wait substantially, + * in which case the index of the working attribute set would switch after each invoked commit, + * instead of being a constant. + * The same number of copies would still need to take place + * but would not need exclusive access to the list. + */ + COND_FAIL_NR(aContext, aContext, ATTR_ERROR_INVALID_ARGUMENT); + COND_FAIL_NR(aContext, aStart <= aEnd, ATTR_ERROR_INVALID_ARGUMENT); + COND_FAIL_NR(aContext, aContext->attributes, ATTR_ERROR_INVALID_CONTEXT); + CHECK_BAD_NR(aContext, aStart); + CHECK_BAD_NR(aContext, aEnd); + + + switch (aCopyTo) + { + case COMMITTED_ATTR_VALUE_INDEX: //Used in composition thread to set displayed scene attributes + for (index = aStart; index <= aEnd; index++) + { + OWF_ATTRIBUTE* attr = &aContext->attributes[index - aContext->range_start]; + attr->attr_info.dirtysnapshot= + OWF_Attribute_Commit(attr,attr->attr_info.dirtysnapshot, + COMMITTED_ATTR_VALUE_INDEX,SNAPSHOT_ATTR_VALUE_INDEX); + } + break; + case SNAPSHOT_ATTR_VALUE_INDEX: //Used in API threads to make a snapshot of the client attributes + for (index = aStart; index <= aEnd; index++) + { + OWF_ATTRIBUTE* attr = &aContext->attributes[index - aContext->range_start]; + OWFuint oldDirty=attr->attr_info.dirty; + attr->attr_info.dirtysnapshot=oldDirty; + attr->attr_info.dirty= + OWF_Attribute_Commit(attr,oldDirty, + SNAPSHOT_ATTR_VALUE_INDEX,WORKING_ATTR_VALUE_INDEX); + } + break; + case WORKING_ATTR_VALUE_INDEX: //Used in initialisation to copy displayed attributes to client copies + for (index = aStart; index <= aEnd; index++) + { + OWF_ATTRIBUTE* attr = &aContext->attributes[index - aContext->range_start]; + OWF_Attribute_Commit(attr,!attr->attr_info.readonly, + WORKING_ATTR_VALUE_INDEX,COMMITTED_ATTR_VALUE_INDEX); + } + break; + + } + + SET_ERROR(aContext, ATTR_ERROR_NONE); +} + +#ifdef __cplusplus +} +#endif