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