os/graphics/graphicscomposition/openwfcompositionengine/common/src/owfattributes.c
author sl@SLION-WIN7.fritz.box
Fri, 15 Jun 2012 03:10:57 +0200
changeset 0 bde4ae8d615e
permissions -rw-r--r--
First public contribution.
     1 /* Copyright (c) 2009-2010 The Khronos Group Inc.
     2  * Portions copyright (c) 2009-2010  Nokia Corporation and/or its subsidiary(-ies)
     3  *
     4  * Permission is hereby granted, free of charge, to any person obtaining a
     5  * copy of this software and/or associated documentation files (the
     6  * "Materials"), to deal in the Materials without restriction, including
     7  * without limitation the rights to use, copy, modify, merge, publish,
     8  * distribute, sublicense, and/or sell copies of the Materials, and to
     9  * permit persons to whom the Materials are furnished to do so, subject to
    10  * the following conditions:
    11  *
    12  * The above copyright notice and this permission notice shall be included
    13  * in all copies or substantial portions of the Materials.
    14  *
    15  * THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
    16  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
    17  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
    18  * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
    19  * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
    20  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
    21  * MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
    22  */
    23 
    24 
    25 
    26 #ifdef __cplusplus
    27 extern "C" {
    28 #endif
    29 
    30 
    31 #include <stdio.h>
    32 #include <stdlib.h>
    33 #include <string.h>
    34 #include <math.h>
    35 
    36 #include "owfattributes.h"
    37 #include "owfmemory.h"
    38 #include "owfdebug.h"
    39 
    40 #define OWF_ATTRIB_RANGE_START            (0)
    41 #define OWF_ATTRIB_RANGE_UNINITIALIZED    (-1)
    42 
    43 static OWFint OWF_Attribute_Commit(OWF_ATTRIBUTE* aAttr, OWFint aDirtyFlag, OWFint aCopyTo,OWFint aCopyFrom);
    44  
    45   /*
    46   This attribute class is not used for WFC element attributes because elements are 
    47   completely cloned in the committed scene.
    48   [This class could be replaced with 3 copies of a much simpler writable attributes raw 
    49   structure with simple data members, and the whole structure copied each commit.] 
    50   Normal attribute values have three pointers indexed via an array:
    51      COMMITTED_ATTR_VALUE_INDEX:
    52          Attribute values used by the scene 
    53              - points to named variables directly used by the compositor
    54      WORKING_ATTR_VALUE_INDEX:
    55          Attribute values that may be set by the client, if they are not read-only.
    56      SNAPSHOT_ATTR_VALUE_INDEX
    57          A copy of the client-set attribute values following a client call to wfcCommit
    58          The copy is then protected against further modification by the client until 
    59          the committed scene is updated and displayed.
    60   The Working and Snapshot writable attributes require additional cache storage, 
    61   which is managed by the lifetime of the attribute list.
    62   Read-only attributes point all three pointers at the named compositor variables.
    63   Currently, there are relatively few writable attributes so it is reasonable 
    64   to individually dynamically allocate each cache. It would be better to allocate 
    65   a single block sized after the attributes have been registered.  
    66   
    67   Internal code is expected to read or write to member variables that are abstracted 
    68   by read-only attributes. However they must not write directly to member variables 
    69   masked by writable attributes after the initial "commit" to working. The code does 
    70   not currently use const instances to enforce this behavior.
    71  */
    72 #define COND_FAIL_NR(ctx, condition, error) \
    73     if (!(condition)) { \
    74         if (ctx) { \
    75             (ctx)->last_error = error; \
    76         } \
    77         return; \
    78     }
    79 
    80 #define COND_FAIL(ctx, condition, error, r) \
    81     if (!(condition)) { \
    82         if (ctx) { \
    83             (ctx)->last_error = error; \
    84         } \
    85         return r; \
    86     }
    87 	
    88 // NS here means No Set as we are not setting the last_error member of the context.
    89 // These are used when we are testing the context itself so setting the last_error
    90 // member is itself is an error
    91 #define COND_FAIL_NR_NS(condition) \
    92     if (!(condition)) { \
    93         return; \
    94     }
    95 
    96 #define COND_FAIL_NS(condition, r) \
    97     if (!(condition)) { \
    98         return r; \
    99     }
   100 
   101 #define CHECK_INDEX_NR(ctx, index, error) \
   102     if (index < (ctx)->range_start || index > (ctx)->range_end) { \
   103         (ctx)->last_error = error; \
   104         return; \
   105     }
   106 
   107 #define CHECK_INDEX(ctx, index, error, r) \
   108     if (index < (ctx)->range_start || index > (ctx)->range_end) { \
   109         (ctx)->last_error = error; \
   110         return r; \
   111     }
   112 
   113 #define CHECK_BAD_NR(ctx, index) \
   114     CHECK_INDEX_NR(ctx, index, ATTR_ERROR_INVALID_ATTRIBUTE); \
   115     if ((ctx)->attributes[index-(ctx)->range_start].attr_info.type == AT_UNDEFINED) { \
   116         (ctx)->last_error = ATTR_ERROR_INVALID_ATTRIBUTE; \
   117         return; \
   118     }
   119 
   120 #define CHECK_BAD(ctx, index, r) \
   121     CHECK_INDEX(ctx, index, ATTR_ERROR_INVALID_ATTRIBUTE, r); \
   122     if ((ctx)->attributes[index-(ctx)->range_start].attr_info.type == AT_UNDEFINED) { \
   123         (ctx)->last_error = ATTR_ERROR_INVALID_ATTRIBUTE; \
   124         return r; \
   125     }
   126 
   127 #define SET_ERROR(ctx, err) \
   128     if ((ctx)->last_error == ATTR_ERROR_NONE) { \
   129         (ctx)->last_error = err; \
   130     }
   131 
   132 
   133 /*
   134 =============================================================================
   135 ATTRIBUTE CONTEXT MANAGEMENT FUNCTIONS
   136 =============================================================================
   137 */
   138 
   139 /*!
   140  * \brief Initializes attribute context
   141  *
   142  * \param aContext Attribute context to initialize
   143  * \param aStart Attribute range start
   144  * \param aEnd Attribute range end. Must be greater than range start.
   145  *
   146  * \return ATTR_ERROR_INVALID_ARGUMENT
   147  * ATTR_ERROR_NO_MEMORY
   148  */
   149 OWF_API_CALL void
   150 OWF_AttributeList_Create(OWF_ATTRIBUTE_LIST* aContext,
   151                          OWFint aStart,
   152                          OWFint aEnd)
   153 {
   154     OWF_ATTRIBUTE*          temp = NULL;
   155 
   156     COND_FAIL_NR_NS(aContext);
   157     COND_FAIL_NR(aContext, aEnd >= 0, ATTR_ERROR_INVALID_ARGUMENT);
   158     COND_FAIL_NR(aContext, aEnd >= aStart, ATTR_ERROR_INVALID_ARGUMENT);
   159 
   160     aContext->range_start = OWF_ATTRIB_RANGE_START;
   161     aContext->range_end = OWF_ATTRIB_RANGE_UNINITIALIZED;
   162 
   163     temp = (OWF_ATTRIBUTE*) xalloc(aEnd - aStart + 1, sizeof(OWF_ATTRIBUTE));
   164     COND_FAIL_NR(aContext, temp, ATTR_ERROR_NO_MEMORY);
   165 
   166     memset(aContext, 0, sizeof(OWF_ATTRIBUTE_LIST));
   167 
   168     aContext->range_start = aStart;
   169     aContext->range_end = aEnd;
   170     aContext->attributes = temp;
   171 
   172     SET_ERROR(aContext, ATTR_ERROR_NONE);
   173     return;
   174 }
   175 
   176 /*!
   177  * \brief Destroy attribute context and free any resources (memory
   178  * blocks) allocated to it. All attributes are destroyed.
   179  *
   180  * \param aContext Attribute context to destroy
   181  *
   182  * \return ATTR_ERROR_INVALID_ARGUMENT
   183  * ATTR_ERROR_INVALID_CONTEXT
   184  */
   185 OWF_API_CALL void
   186 OWF_AttributeList_Destroy(OWF_ATTRIBUTE_LIST* aContext)
   187 {
   188     OWFint                 count = 0;
   189     OWFint                 at = 0;
   190     OWFint                 cache = 0;
   191 
   192     COND_FAIL_NR_NS(aContext);
   193     COND_FAIL_NR(aContext, aContext->attributes, ATTR_ERROR_INVALID_CONTEXT);
   194 
   195     count = aContext->range_end - aContext->range_start;
   196     for (at = 0; at <= count; at++) {
   197 
   198         OWF_ATTRIBUTE* attr = &aContext->attributes[at];
   199         if (!attr->attr_info.readonly)
   200             {
   201             for (cache=0;cache<NUM_ATTR_VALUE_COPIES;cache++)
   202                 {
   203                 if (cache!=COMMITTED_ATTR_VALUE_INDEX)
   204                     {
   205                     xfree(attr->attr_value[cache].gen_ptr);
   206                     }
   207                 }
   208             }
   209     }
   210 
   211     xfree(aContext->attributes);
   212     memset(aContext, 0, sizeof(OWF_ATTRIBUTE_LIST));
   213     SET_ERROR(aContext, ATTR_ERROR_NONE);
   214     return;
   215 }
   216 
   217 /*
   218 
   219 
   220  */
   221 OWF_API_CALL OWF_ATTRIBUTE_LIST_STATUS
   222 OWF_AttributeList_GetError(OWF_ATTRIBUTE_LIST* aContext)
   223 {
   224     OWF_ATTRIBUTE_LIST_STATUS   error;
   225 
   226     if (!aContext) {
   227         return ATTR_ERROR_INVALID_ARGUMENT;
   228     }
   229     error = aContext->last_error;
   230     aContext->last_error = ATTR_ERROR_NONE;
   231     return error;
   232 }
   233 
   234 /*
   235 =============================================================================
   236 INITIALIZATION FUNCTIONS
   237 =============================================================================
   238 */
   239 
   240 static void OWF_Attribute_Init(OWF_ATTRIBUTE_LIST* aContext,
   241                                OWFint aName,
   242                                OWF_ATTRIBUTE_TYPE aType,
   243                                OWFint aLength,
   244                                void* aValue,
   245                                OWFboolean aRdOnly)
   246 {
   247     OWF_ATTRIBUTE*          attr = NULL;
   248     void*                   cache = NULL;
   249     OWFint                  itemSize;
   250     OWFint                  arraySize;
   251     OWFint                  copy;
   252     OWFint                  index;
   253 	
   254 	COND_FAIL_NR_NS(aContext);
   255 	CHECK_INDEX_NR(aContext, aName, ATTR_ERROR_INVALID_ATTRIBUTE);
   256     COND_FAIL_NR(aContext, aContext->attributes, ATTR_ERROR_INVALID_CONTEXT);
   257     COND_FAIL_NR(aContext, aLength < MAX_ATTR_LENGTH, ATTR_ERROR_CANT_HANDLE);
   258     COND_FAIL_NR(aContext, aType != AT_UNDEFINED, ATTR_ERROR_INVALID_ARGUMENT);
   259 	
   260 	index = aName - aContext->range_start;
   261 
   262     attr = &aContext->attributes[index];
   263     
   264     memset(attr, 0, sizeof(OWF_ATTRIBUTE));
   265 
   266     /* when allocin', size DOES matter */
   267     if (aType == AT_INTEGER || aType == AT_BOOLEAN) {
   268         itemSize = sizeof(OWFint);
   269     } else {
   270         itemSize = sizeof(OWFfloat);
   271     }
   272     arraySize=itemSize*aLength;
   273 
   274     /* don't allocate cache for read-only 'butes */
   275     attr->attr_info.type        = aType;
   276     attr->attr_info.length      = aLength;
   277     attr->attr_info.readonly    = aRdOnly;
   278     attr->attr_info.size        = itemSize;
   279     if (aRdOnly)
   280         {
   281         for (copy=0;copy<NUM_ATTR_VALUE_COPIES;copy++)
   282             {
   283             attr->attr_value[copy].gen_ptr = aValue;
   284             }
   285         }
   286     else
   287         {
   288         for (copy=0;copy<NUM_ATTR_VALUE_COPIES;copy++)
   289             {
   290             if (copy==COMMITTED_ATTR_VALUE_INDEX)
   291                 {
   292                  attr->attr_value[COMMITTED_ATTR_VALUE_INDEX].gen_ptr = aValue;
   293                 }
   294             else
   295                 {
   296                 cache = xalloc(arraySize,1);
   297                 COND_FAIL_NR(aContext, NULL != cache, ATTR_ERROR_NO_MEMORY);
   298                 attr->attr_value[copy].gen_ptr = cache;
   299                 }
   300              }
   301        }
   302 
   303     SET_ERROR(aContext, ATTR_ERROR_NONE);
   304 
   305 }
   306 
   307 /*
   308  * \brief Intialize integer attribute
   309  *
   310  * \param aContext Attibute context
   311  * \param aName Attribute name
   312  * \param aValue Attribute initial value
   313  * \param aRdOnly Read-only flag
   314  *
   315  * \return ATTR_ERROR_INVALID_ARGUMENT
   316  * ATTR_ERROR_INVALID_ATTRIBUTE
   317  * ATTR_ERROR_INVALID_CONTEXT
   318  */
   319 OWF_API_CALL void
   320 OWF_Attribute_Initi(OWF_ATTRIBUTE_LIST* aContext,
   321                     OWFint aName,
   322                     OWF_INT_REF aValue,
   323                     OWFboolean aRdOnly)
   324 {
   325     OWF_Attribute_Init(aContext, aName, AT_INTEGER, 1, aValue, aRdOnly);
   326 }
   327 
   328 /*
   329  * \brief Initialize float attribute
   330  *
   331  * \param aContext Attribute context
   332  * \param aName Attribute name
   333  * \param aValue Initial value for attribute
   334  * \param aRdOnly Read-only flag
   335  *
   336  * \return ATTR_ERROR_INVALID_ARGUMENT
   337  * ATTR_ERROR_INVALID_ATTRIBUTE
   338  * ATTR_ERROR_INVALID_CONTEXT
   339  */
   340 OWF_API_CALL void
   341 OWF_Attribute_Initf(OWF_ATTRIBUTE_LIST* aContext,
   342                     OWFint aName,
   343                     OWF_FLOAT_REF aValue,
   344                     OWFboolean aRdOnly)
   345 {
   346     OWF_Attribute_Init(aContext, aName, AT_FLOAT, 1, aValue, aRdOnly);
   347 }
   348 
   349 /*
   350  * \brief Initialize boolean attribute
   351  *
   352  * \param aContext Attribute context
   353  * \param aName Attribute name
   354  * \param aValue Initial value for attribute
   355  * \param aRdOnly Read-only flag
   356  *
   357  * \return ATTR_ERROR_INVALID_ARGUMENT
   358  * ATTR_ERROR_INVALID_ATTRIBUTE
   359  * ATTR_ERROR_INVALID_CONTEXT
   360  */
   361 OWF_API_CALL void
   362 OWF_Attribute_Initb(OWF_ATTRIBUTE_LIST* aContext,
   363                     OWFint aName,
   364                     OWF_BOOL_REF aValue,
   365                     OWFboolean aRdOnly)
   366 {
   367     OWF_Attribute_Init(aContext, aName, AT_BOOLEAN, 1, aValue, aRdOnly);
   368 }
   369 
   370 /*
   371  * \brief Initialize vector attribute
   372  *
   373  * \param aContext Attribute context
   374  * \param aName Attribute name
   375  * \param aLength Attribute (vector) length
   376  * \param aValues Initial value(s) for attribute
   377  * \param aRdOnly Read-only flag
   378  *
   379  * \return ATTR_ERROR_INVALID_ARGUMENT
   380  * ATTR_ERROR_INVALID_ATTRIBUTE
   381  * ATTR_ERROR_INVALID_CONTEXT
   382  * ATTR_ERROR_CANT_HANDLE
   383  */
   384 OWF_API_CALL void
   385 OWF_Attribute_Initiv(OWF_ATTRIBUTE_LIST* aContext,
   386                      OWFint aName,
   387                      OWFint aLength,
   388                      OWF_INT_VECTOR_REF aValues,
   389                      OWFboolean aRdOnly)
   390 {
   391     OWF_Attribute_Init(aContext, aName, AT_INTEGER, aLength, aValues, aRdOnly);
   392 }
   393 
   394 /*
   395  * \brief Initialize vector attribute
   396  *
   397  * \param aContext Attribute context
   398  * \param aName Attribute name
   399  * \param aLength Attribute (vector) length
   400  * \param aValues Initial value(s) for attributes
   401  * \param aRdOnly Read-only flag
   402  *
   403  * \return
   404  */
   405 OWF_API_CALL void
   406 OWF_Attribute_Initfv(OWF_ATTRIBUTE_LIST* aContext,
   407                      OWFint aName,
   408                      OWFint aLength,
   409                      OWF_FLOAT_VECTOR_REF aValues,
   410                      OWFboolean aRdOnly)
   411 {
   412     OWF_Attribute_Init(aContext, aName, AT_FLOAT, aLength, aValues, aRdOnly);
   413 }
   414 
   415 /*
   416 =============================================================================
   417 GETTER FUNCTIONS
   418 =============================================================================
   419 */
   420 
   421 /*
   422  * \brief Get attribute integer value.
   423  *
   424  * \param aContext Attribute context
   425  * \param aName Attribute name
   426  *
   427  * \return Attribute integer value (floats are floor()ed). For vector
   428  * attributes the return value will be error ATTR_ERROR_INVALID_TYPE.
   429  * ATTR_ERROR_INVALID_ATTRIBUTE
   430  * ATTR_ERROR_INVALID_CONTEXT
   431  */
   432 OWF_API_CALL OWFint
   433 OWF_Attribute_GetValuei(OWF_ATTRIBUTE_LIST* aContext,
   434                         OWFint aName)
   435 {
   436     OWFint                  index = 0;
   437     OWF_ATTRIBUTE*          attr = 0;
   438     OWFint                  result = 0;
   439 
   440     COND_FAIL_NS(aContext, 0); 
   441 	COND_FAIL(aContext,
   442               aContext->attributes,
   443               ATTR_ERROR_INVALID_CONTEXT,
   444               0);
   445     CHECK_BAD(aContext, aName, 0);
   446 
   447 
   448     index = aName - aContext->range_start;
   449     attr = &aContext->attributes[index];
   450 
   451     COND_FAIL(aContext,
   452               1 == attr->attr_info.length,
   453               ATTR_ERROR_INVALID_TYPE,
   454               0);
   455 
   456     SET_ERROR(aContext, ATTR_ERROR_NONE);
   457 
   458     switch (attr->attr_info.type) {
   459         case AT_FLOAT: {
   460             result = floor(attr->attr_value[WORKING_ATTR_VALUE_INDEX].float_value[0]);
   461             break;
   462         }
   463 
   464         case AT_INTEGER:
   465         case AT_BOOLEAN: {
   466             result = attr->attr_value[WORKING_ATTR_VALUE_INDEX].int_value[0];
   467             break;
   468         }
   469 
   470         default: {
   471             SET_ERROR(aContext, ATTR_ERROR_INVALID_TYPE);
   472             break;
   473         }
   474     }
   475     return result;
   476 }
   477 
   478 /*
   479  * \brief Return boolean attribute value
   480  *
   481  * \param aContext Attribute context
   482  * \param aName Attribute name
   483  *
   484  * \return Attribute value
   485  * ATTR_ERROR_INVALID_ATTRIBUTE
   486  * ATTR_ERROR_INVALID_TYPE
   487  */
   488 OWF_API_CALL OWFboolean
   489 OWF_Attribute_GetValueb(OWF_ATTRIBUTE_LIST* aContext,
   490                         OWFint aName)
   491 {
   492     /* boolean is stored as int, must cast */
   493     return (OWFboolean) OWF_Attribute_GetValuei(aContext, aName);
   494 }
   495 
   496 /*
   497  * \brief Get attribute float value
   498  *
   499  * \param aContext
   500  * \param aName
   501  * \param aValue
   502  *
   503  * \return Attribute
   504  */
   505 OWF_API_CALL OWFfloat
   506 OWF_Attribute_GetValuef(OWF_ATTRIBUTE_LIST* aContext,
   507                         OWFint aName)
   508 {
   509     OWFint                 index = 0;
   510     OWF_ATTRIBUTE*          attr = NULL;
   511     OWFfloat                result = 0.f;
   512 
   513     COND_FAIL_NS(aContext, 0);
   514     COND_FAIL(aContext,
   515               aContext->attributes,
   516               ATTR_ERROR_INVALID_CONTEXT,
   517               0);
   518     CHECK_BAD(aContext, aName, 0);
   519 
   520 
   521     index = aName - aContext->range_start;
   522     attr = &aContext->attributes[index];
   523 
   524     COND_FAIL(aContext,
   525               1 == attr->attr_info.length,
   526               ATTR_ERROR_INVALID_TYPE,
   527               0);
   528 
   529     SET_ERROR(aContext, ATTR_ERROR_NONE);
   530     result = 0.f;
   531 
   532     switch (attr->attr_info.type) {
   533         case AT_FLOAT: {
   534             result = attr->attr_value[WORKING_ATTR_VALUE_INDEX].float_value[0];
   535             break;
   536         }
   537 
   538         case AT_INTEGER:
   539         case AT_BOOLEAN: {
   540             result = (OWFfloat) attr->attr_value[WORKING_ATTR_VALUE_INDEX].int_value[0];
   541             break;
   542         }
   543 
   544         default: {
   545             SET_ERROR(aContext, ATTR_ERROR_INVALID_TYPE);
   546             break;
   547         }
   548     }
   549     return result;
   550 }
   551 
   552 /*
   553  * \brief
   554  *
   555  * \param aContext
   556  * \param aName
   557  * \param aSize
   558  * \param aValue
   559  *
   560  * \return
   561  */
   562 OWF_API_CALL OWFint
   563 OWF_Attribute_GetValueiv(OWF_ATTRIBUTE_LIST* aContext,
   564                          OWFint aName,
   565                          OWFint aLength,
   566                          OWFint* aValue)
   567 {
   568     OWFint                 index = 0;
   569     OWF_ATTRIBUTE*          attr = NULL;
   570     OWFint                 count = 0;
   571 
   572     COND_FAIL_NS(aContext, 0);
   573     COND_FAIL(aContext,
   574               aContext->attributes,
   575               ATTR_ERROR_INVALID_CONTEXT,
   576               0);
   577     CHECK_BAD(aContext, aName, 0);
   578 
   579 
   580     index = aName - aContext->range_start;
   581     attr = &aContext->attributes[index];
   582 
   583     COND_FAIL(aContext,
   584               attr->attr_info.length >= 1,
   585               ATTR_ERROR_INVALID_TYPE,
   586               0);
   587 
   588     if (!aValue) {
   589         /* fetch size only */
   590         return attr->attr_info.length;
   591     }
   592 
   593     count = min(aLength, attr->attr_info.length);
   594 
   595     SET_ERROR(aContext, ATTR_ERROR_NONE);
   596 
   597     switch (attr->attr_info.type) {
   598         case AT_FLOAT: {
   599             OWFint i;
   600             OWFfloat* v = attr->attr_value[WORKING_ATTR_VALUE_INDEX].float_value;
   601             for (i = 0; i < count; i++) {
   602                 aValue[i] = floor(v[i]);
   603             }
   604             break;
   605         }
   606 
   607         case AT_BOOLEAN:
   608         case AT_INTEGER: {
   609             memcpy(aValue,
   610                    attr->attr_value[WORKING_ATTR_VALUE_INDEX].int_value,
   611                    count * attr->attr_info.size);
   612             break;
   613         }
   614 
   615         default: {
   616             SET_ERROR(aContext, ATTR_ERROR_INVALID_TYPE);
   617             break;
   618         }
   619     }
   620     return count;
   621 }
   622 
   623 /*
   624  * \brief
   625  *
   626  * \param aContext
   627  * \param aName
   628  * \param aSize
   629  * \param aValue
   630  *
   631  * \return
   632  */
   633 OWF_API_CALL OWFint
   634 OWF_Attribute_GetValuefv(OWF_ATTRIBUTE_LIST* aContext,
   635                          OWFint aName,
   636                          OWFint aLength,
   637                          OWFfloat* aValue)
   638 {
   639     OWFint                 index = 0;
   640     OWF_ATTRIBUTE*          attr = NULL;
   641     OWFint                 count = 0;
   642 
   643     COND_FAIL_NS(aContext, 0);
   644     COND_FAIL(aContext,
   645               aContext->attributes,
   646               ATTR_ERROR_INVALID_CONTEXT,
   647               0);
   648     CHECK_BAD(aContext, aName, 0);
   649 
   650 
   651     index = aName - aContext->range_start;
   652     attr = &aContext->attributes[index];
   653 
   654     COND_FAIL(aContext,
   655               attr->attr_info.length >= 1,
   656               ATTR_ERROR_INVALID_TYPE, 0);
   657 
   658     if (!aValue) {
   659         /* fetch size only */
   660         return attr->attr_info.length;
   661     }
   662 
   663     count = min(aLength, attr->attr_info.length);
   664 
   665     SET_ERROR(aContext, ATTR_ERROR_NONE);
   666 
   667     switch (attr->attr_info.type) {
   668         case AT_FLOAT: {
   669             memcpy(aValue,
   670                    attr->attr_value[WORKING_ATTR_VALUE_INDEX].float_value,
   671                    count * attr->attr_info.size);
   672             break;
   673         }
   674 
   675         case AT_BOOLEAN:
   676         case AT_INTEGER: {
   677             OWFint i;
   678             OWFint* v = attr->attr_value[WORKING_ATTR_VALUE_INDEX].int_value;
   679             for (i = 0; i < count; i++) {
   680                 aValue[i] = (OWFfloat) v[i];
   681             }
   682             break;
   683         }
   684 
   685         default: {
   686             SET_ERROR(aContext, ATTR_ERROR_INVALID_TYPE);
   687             break;
   688         }
   689     }
   690     return count;
   691 }
   692 
   693 /*
   694 =============================================================================
   695 SETTER FUNCTIONS
   696 =============================================================================
   697 */
   698 
   699 /*
   700  * \brief
   701  *
   702  * \param aContext
   703  * \param aName
   704  * \param aValue
   705  *
   706  * \return
   707  */
   708 OWF_API_CALL void
   709 OWF_Attribute_SetValuei(OWF_ATTRIBUTE_LIST* aContext,
   710                         OWFint aName,
   711                         OWFint aValue)
   712 {
   713     OWFint                 index = 0;
   714     OWF_ATTRIBUTE*          attr = NULL;
   715 
   716     COND_FAIL_NR_NS(aContext);
   717     COND_FAIL_NR(aContext, aContext->attributes, ATTR_ERROR_INVALID_CONTEXT);
   718     CHECK_BAD_NR(aContext, aName);
   719 
   720 
   721     index = aName - aContext->range_start;
   722     attr = &aContext->attributes[index];
   723 
   724     COND_FAIL_NR(aContext,
   725                  1 == attr->attr_info.length,
   726                  ATTR_ERROR_INVALID_TYPE);
   727     COND_FAIL_NR(aContext, !attr->attr_info.readonly, ATTR_ERROR_ACCESS_DENIED);
   728 
   729     SET_ERROR(aContext, ATTR_ERROR_NONE);
   730 
   731     attr->attr_info.dirty = 1;
   732 
   733     switch (attr->attr_info.type) {
   734         case AT_FLOAT: {
   735             attr->attr_value[WORKING_ATTR_VALUE_INDEX].float_value[0] = aValue;
   736             break;
   737         }
   738 
   739         case AT_INTEGER:
   740         case AT_BOOLEAN: {
   741             attr->attr_value[WORKING_ATTR_VALUE_INDEX].int_value[0] = aValue;
   742             break;
   743         }
   744 
   745         default: {
   746             SET_ERROR(aContext, ATTR_ERROR_INVALID_TYPE);
   747             break;
   748         }
   749     }
   750 }
   751 
   752 /*
   753  * \brief
   754  *
   755  * \param aContext
   756  * \param aName
   757  * \param aValue
   758  *
   759  * \return
   760  */
   761 OWF_API_CALL void
   762 OWF_Attribute_SetValuef(OWF_ATTRIBUTE_LIST* aContext,
   763                         OWFint aName,
   764                         OWFfloat aValue)
   765 {
   766     OWFint                 index = 0;
   767     OWF_ATTRIBUTE*          attr = NULL;
   768 
   769     COND_FAIL_NR_NS(aContext);
   770     COND_FAIL_NR(aContext, aContext->attributes, ATTR_ERROR_INVALID_CONTEXT);
   771     CHECK_BAD_NR(aContext, aName);
   772 
   773 
   774     index = aName - aContext->range_start;
   775     attr = &aContext->attributes[index];
   776 
   777     COND_FAIL_NR(aContext,
   778                  1 == attr->attr_info.length,
   779                  ATTR_ERROR_INVALID_TYPE);
   780     COND_FAIL_NR(aContext,
   781                  !attr->attr_info.readonly,
   782                  ATTR_ERROR_ACCESS_DENIED);
   783 
   784     SET_ERROR(aContext, ATTR_ERROR_NONE);
   785 
   786     attr->attr_info.dirty = 1;
   787 
   788     switch (attr->attr_info.type) {
   789         case AT_FLOAT: {
   790             attr->attr_value[WORKING_ATTR_VALUE_INDEX].float_value[0] = aValue;
   791             break;
   792         }
   793 
   794         case AT_INTEGER:
   795         case AT_BOOLEAN: {
   796             attr->attr_value[WORKING_ATTR_VALUE_INDEX].int_value[0] = floor(aValue);
   797             break;
   798         }
   799 
   800         default: {
   801             SET_ERROR(aContext, ATTR_ERROR_INVALID_TYPE);
   802             break;
   803         }
   804     }
   805 }
   806 
   807 /*
   808  * \brief
   809  *
   810  * \param
   811  * \param
   812  * \param
   813  *
   814  * \return
   815  */
   816 OWF_API_CALL void
   817 OWF_Attribute_SetValueb(OWF_ATTRIBUTE_LIST* aContext,
   818                         OWFint aName,
   819                         OWFboolean aValue)
   820 {
   821     OWF_Attribute_SetValuei(aContext, aName, (OWFint) aValue);
   822 }
   823 
   824 /*
   825  * \brief
   826  *
   827  * \param
   828  * \param
   829  * \param
   830  *
   831  * \return
   832  */
   833 OWF_API_CALL void
   834 OWF_Attribute_SetValueiv(OWF_ATTRIBUTE_LIST* aContext,
   835                          OWFint aName,
   836                          OWFint aLength,
   837                          const OWFint* aValue)
   838 {
   839     OWFint                 index = 0;
   840     OWF_ATTRIBUTE*          attr = NULL;
   841     OWFint                 count = 0;
   842 
   843     COND_FAIL_NR_NS(aContext);
   844     COND_FAIL_NR(aContext, aValue, ATTR_ERROR_INVALID_ARGUMENT);
   845     COND_FAIL_NR(aContext, aContext->attributes, ATTR_ERROR_INVALID_CONTEXT);
   846     CHECK_BAD_NR(aContext, aName);
   847 
   848     index = aName - aContext->range_start;
   849     attr = &aContext->attributes[index];
   850 /*
   851     COND_FAIL_NR(aContext,
   852                attr->attr_info.length >= 1,
   853                ATTR_ERROR_INVALID_TYPE);
   854 */
   855     COND_FAIL_NR(aContext,
   856                  aLength > 0 && aLength <= attr->attr_info.length,
   857                  ATTR_ERROR_INVALID_ARGUMENT);
   858 
   859     COND_FAIL_NR(aContext,
   860                  !attr->attr_info.readonly,
   861                  ATTR_ERROR_ACCESS_DENIED);
   862 
   863     count = min(aLength, attr->attr_info.length);
   864 
   865     SET_ERROR(aContext, ATTR_ERROR_NONE);
   866 
   867     switch (attr->attr_info.type) {
   868         case AT_FLOAT: {
   869             OWFint i = 0;
   870             OWFfloat* v = attr->attr_value[1].float_value;
   871             for (i = 0; i < count; i++) {
   872                 v[i] = floor(aValue[i]);
   873             }
   874             break;
   875         }
   876 
   877         case AT_BOOLEAN:
   878         case AT_INTEGER: {
   879             memcpy(attr->attr_value[1].int_value,
   880                    aValue,
   881                    count * attr->attr_info.size);
   882             break;
   883         }
   884 
   885         default: {
   886             SET_ERROR(aContext, ATTR_ERROR_INVALID_TYPE);
   887             break;
   888         }
   889     }
   890     aContext->attributes[index].attr_info.dirty = 1;
   891 }
   892 
   893 /*
   894  * \brief
   895  *
   896  * \param
   897  * \param
   898  * \param
   899  *
   900  * \return
   901  */
   902 OWF_API_CALL void
   903 OWF_Attribute_SetValuefv(OWF_ATTRIBUTE_LIST* aContext,
   904                          OWFint aName,
   905                          OWFint aLength,
   906                          const OWFfloat* aValue)
   907 {
   908     OWFint                 index = 0;
   909     OWF_ATTRIBUTE*          attr = NULL;
   910     OWFint                 count = 0;
   911 
   912     COND_FAIL_NR_NS(aContext);
   913     COND_FAIL_NR(aContext, aValue, ATTR_ERROR_INVALID_ARGUMENT);
   914     COND_FAIL_NR(aContext, aContext->attributes, ATTR_ERROR_INVALID_CONTEXT);
   915     CHECK_BAD_NR(aContext, aName);
   916 
   917     index = aName - aContext->range_start;
   918     attr = &aContext->attributes[index];
   919 
   920 /*
   921     COND_FAIL_NR(aContext,
   922                attr->attr_info.length >= 1,
   923                ATTR_ERROR_INVALID_TYPE);
   924 */
   925 
   926     COND_FAIL_NR(aContext,
   927                  aLength > 0 && aLength <= attr->attr_info.length,
   928                  ATTR_ERROR_INVALID_ARGUMENT);
   929 
   930     COND_FAIL_NR(aContext,
   931                  !attr->attr_info.readonly,
   932                  ATTR_ERROR_ACCESS_DENIED);
   933 
   934     count = min(aLength, attr->attr_info.length);
   935 
   936     SET_ERROR(aContext, ATTR_ERROR_NONE);
   937 
   938     switch (attr->attr_info.type) {
   939         case AT_FLOAT: {
   940             memcpy(attr->attr_value[1].float_value,
   941                    aValue,
   942                    count * attr->attr_info.size);
   943             break;
   944         }
   945 
   946         case AT_BOOLEAN:
   947         case AT_INTEGER: {
   948             OWFint i;
   949             OWFint* v = attr->attr_value[1].int_value;
   950             for (i = 0; i < count; i++) {
   951                  v[i] = floor(aValue[i]);
   952             }
   953             break;
   954         }
   955 
   956         default: {
   957             SET_ERROR(aContext, ATTR_ERROR_INVALID_TYPE);
   958             break;
   959         }
   960     }
   961     aContext->attributes[index].attr_info.dirty = 1;
   962 }
   963 
   964 static OWFint OWF_Attribute_Commit(OWF_ATTRIBUTE* aAttr, 
   965                             OWFint aDirtyFlag, 
   966                             OWFint aCopyTo,
   967                             OWFint aCopyFrom )
   968     {
   969 	OWF_ASSERT(aCopyTo >= 0);
   970 	OWF_ASSERT(aCopyTo < NUM_ATTR_VALUE_COPIES);
   971 	OWF_ASSERT(aCopyFrom >= 0);
   972 	OWF_ASSERT(aCopyFrom < NUM_ATTR_VALUE_COPIES);
   973     /* if type is undefined, it means there're gaps in the attribute
   974        range (e.g. reservations for future use and such.) ignore them. */
   975     if (aAttr->attr_info.type != AT_UNDEFINED && aDirtyFlag) 
   976         {
   977         /* poor-man's commit */
   978         memcpy(aAttr->attr_value[aCopyTo].gen_ptr,
   979                 aAttr->attr_value[aCopyFrom].gen_ptr,
   980                 aAttr->attr_info.size * aAttr->attr_info.length);
   981         return 0;
   982         }
   983     else
   984         {
   985         return aDirtyFlag;
   986         }
   987     }
   988 
   989 
   990 OWF_API_CALL void
   991 OWF_AttributeList_Commit(OWF_ATTRIBUTE_LIST* aContext,
   992                      OWFint aStart,
   993                      OWFint aEnd,
   994 		     OWFint aCopyTo )
   995 {
   996     OWFint                 index = 0;
   997     /* Attribute commit works like the element list commit
   998      * by forward-copying the "working" attributes to the snapshot  
   999      * during client invoked commit,
  1000      * then copying the snapshot to the commited scene during the docommit job.
  1001      * This requires the same wait-for-the-previous-commit-job strategy used in the element commit.
  1002      * Could in future use copy-back technique to avoid having to wait substantially, 
  1003      * in which case the index of the working attribute set would switch after each invoked commit,
  1004      * instead of being a constant.
  1005      *
  1006      * The same number of copies would still need to take place  
  1007      * but would not need exclusive access to the list.
  1008      */
  1009 
  1010     COND_FAIL_NR_NS(aContext);
  1011     COND_FAIL_NR(aContext, aStart <= aEnd, ATTR_ERROR_INVALID_ARGUMENT);
  1012     COND_FAIL_NR(aContext, aContext->attributes, ATTR_ERROR_INVALID_CONTEXT);
  1013     CHECK_BAD_NR(aContext, aStart);
  1014     CHECK_BAD_NR(aContext, aEnd);
  1015 
  1016     switch (aCopyTo)
  1017         {
  1018         case COMMITTED_ATTR_VALUE_INDEX: /* Used in composition thread to set displayed scene attributes */
  1019             for (index = aStart; index <= aEnd; index++) 
  1020                 {
  1021                 OWF_ATTRIBUTE* attr = &aContext->attributes[index - aContext->range_start];
  1022                 attr->attr_info.dirtysnapshot=
  1023                     OWF_Attribute_Commit(attr,attr->attr_info.dirtysnapshot,
  1024                             COMMITTED_ATTR_VALUE_INDEX,SNAPSHOT_ATTR_VALUE_INDEX);
  1025                 }
  1026             break;
  1027         case SNAPSHOT_ATTR_VALUE_INDEX: /* Used in API threads to make a snapshot of the client attributes */
  1028              for (index = aStart; index <= aEnd; index++) 
  1029                  {
  1030                  OWF_ATTRIBUTE* attr = &aContext->attributes[index - aContext->range_start];
  1031                  OWFuint oldDirty=attr->attr_info.dirty;
  1032                  attr->attr_info.dirtysnapshot=oldDirty;
  1033                  attr->attr_info.dirty=
  1034                      OWF_Attribute_Commit(attr,oldDirty,
  1035                              SNAPSHOT_ATTR_VALUE_INDEX,WORKING_ATTR_VALUE_INDEX);
  1036                  }
  1037              break;
  1038         case WORKING_ATTR_VALUE_INDEX:   /* Used in initialisation to copy displayed attributes to client copies */
  1039              for (index = aStart; index <= aEnd; index++) 
  1040                  {
  1041                  OWF_ATTRIBUTE* attr = &aContext->attributes[index - aContext->range_start];
  1042                  OWF_Attribute_Commit(attr,!attr->attr_info.readonly,
  1043                          WORKING_ATTR_VALUE_INDEX,COMMITTED_ATTR_VALUE_INDEX);
  1044                  }
  1045              break;
  1046 	case COMMIT_ATTR_DIRECT_FROM_WORKING: /* Used in WFD to commit new working values directly in 1 step. */
  1047             for (index = aStart; index <= aEnd; index++) 
  1048                 {
  1049                 OWF_ATTRIBUTE* attr = &aContext->attributes[index - aContext->range_start];
  1050                 attr->attr_info.dirty=
  1051                     OWF_Attribute_Commit(attr,attr->attr_info.dirty,
  1052                             COMMITTED_ATTR_VALUE_INDEX,WORKING_ATTR_VALUE_INDEX);
  1053                 }
  1054             break;
  1055 	default:
  1056 			COND_FAIL_NR(aContext, 0, ATTR_ERROR_INVALID_ARGUMENT);
  1057           }
  1058     
  1059     SET_ERROR(aContext, ATTR_ERROR_NONE);
  1060 }
  1061 
  1062 #ifdef __cplusplus
  1063 }
  1064 #endif