--- /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 <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <math.h>
+
+#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;cache<NUM_ATTR_VALUE_COPIES;cache++)
+ {
+ if (cache!=COMMITTED_ATTR_VALUE_INDEX)
+ {
+ xfree(attr->attr_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;copy<NUM_ATTR_VALUE_COPIES;copy++)
+ {
+ attr->attr_value[copy].gen_ptr = aValue;
+ }
+ }
+ else
+ {
+ for (copy=0;copy<NUM_ATTR_VALUE_COPIES;copy++)
+ {
+ if (copy==COMMITTED_ATTR_VALUE_INDEX)
+ {
+ attr->attr_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