32 #include <string.h> |
32 #include <string.h> |
33 #include <math.h> |
33 #include <math.h> |
34 |
34 |
35 #include "owfattributes.h" |
35 #include "owfattributes.h" |
36 #include "owfmemory.h" |
36 #include "owfmemory.h" |
|
37 #include "owfdebug.h" |
37 |
38 |
38 #define OWF_ATTRIB_RANGE_START (0) |
39 #define OWF_ATTRIB_RANGE_START (0) |
39 #define OWF_ATTRIB_RANGE_UNINITIALIZED (-1) |
40 #define OWF_ATTRIB_RANGE_UNINITIALIZED (-1) |
40 |
41 |
41 static OWFint OWF_Attribute_Commit(OWF_ATTRIBUTE* aAttr, OWFint aDirtyFlag, OWFint aCopyTo,OWFint aCopyFrom); |
42 static OWFint OWF_Attribute_Commit(OWF_ATTRIBUTE* aAttr, OWFint aDirtyFlag, OWFint aCopyTo,OWFint aCopyFrom); |
42 |
43 |
43 /* |
44 /* |
44 This attribute class is currently only used for context attributes. |
45 This attribute class is not used for WFC element attributes because elements are |
45 Why isn't it used for element attributes? |
46 completely cloned in the committed scene. |
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 |
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.] |
48 structure with simple data members, and the whole structure copied each commit.] |
49 Normal attribute values have three pointers indexed via an array: |
49 Normal attribute values have three pointers indexed via an array: |
50 COMMITTED_ATTR_VALUE_INDEX: |
50 COMMITTED_ATTR_VALUE_INDEX: |
51 Attribute values used by the scene |
51 Attribute values used by the scene |
52 - points to named variables directly used by the compositor |
52 - points to named variables directly used by the compositor |
53 WORKING_ATTR_VALUE_INDEX: |
53 WORKING_ATTR_VALUE_INDEX: |
54 Attribute values that may be set by the client, if they are not read-only. |
54 Attribute values that may be set by the client, if they are not read-only. |
55 SNAPSHOT_ATTR_VALUE_INDEX |
55 SNAPSHOT_ATTR_VALUE_INDEX |
56 A copy of the client-set attribute values following a client call to wfcCommit |
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 |
57 The copy is then protected against further modification by the client until |
58 the committed scene is updated and displayed. |
58 the committed scene is updated and displayed. |
59 The Working and Snapshot writable attributes require additional cache storage, |
59 The Working and Snapshot writable attributes require additional cache storage, |
60 which is managed by the lifetime of the attribute list. |
60 which is managed by the lifetime of the attribute list. |
61 Read-only attributes point all three pointers at the named compositor variables. |
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 |
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 |
63 to individually dynamically allocate each cache. It would be better to allocate |
64 a single block sized after the attributes have been registered. |
64 a single block sized after the attributes have been registered. |
65 |
|
66 Internal code is expected to read or write to member variables that are abstracted |
|
67 by read-only attributes. However they must not write directly to member variables |
|
68 masked by writable attributes after the initial "commit" to working. The code does |
|
69 not currently use const instances to enforce this behavior. |
65 */ |
70 */ |
66 #define COND_FAIL_NR(ctx, condition, error) \ |
71 #define COND_FAIL_NR(ctx, condition, error) \ |
67 if (!(condition)) { \ |
72 if (!(condition)) { \ |
68 if (ctx) { \ |
73 if (ctx) { \ |
69 (ctx)->last_error = error; \ |
74 (ctx)->last_error = error; \ |
227 OWF_ATTRIBUTE* attr = NULL; |
246 OWF_ATTRIBUTE* attr = NULL; |
228 void* cache = NULL; |
247 void* cache = NULL; |
229 OWFint itemSize; |
248 OWFint itemSize; |
230 OWFint arraySize; |
249 OWFint arraySize; |
231 OWFint copy; |
250 OWFint copy; |
232 OWFint index = aName - aContext->range_start; |
251 OWFint index; |
233 |
252 |
234 COND_FAIL_NR(aContext, aContext, ATTR_ERROR_INVALID_ARGUMENT); |
253 COND_FAIL_NR_NS(aContext); |
235 CHECK_INDEX_NR(aContext, aName, ATTR_ERROR_INVALID_ATTRIBUTE); |
254 CHECK_INDEX_NR(aContext, aName, ATTR_ERROR_INVALID_ATTRIBUTE); |
236 COND_FAIL_NR(aContext, aContext->attributes, ATTR_ERROR_INVALID_CONTEXT); |
255 COND_FAIL_NR(aContext, aContext->attributes, ATTR_ERROR_INVALID_CONTEXT); |
237 COND_FAIL_NR(aContext, aLength < MAX_ATTR_LENGTH, ATTR_ERROR_CANT_HANDLE); |
256 COND_FAIL_NR(aContext, aLength < MAX_ATTR_LENGTH, ATTR_ERROR_CANT_HANDLE); |
238 COND_FAIL_NR(aContext, aType != AT_UNDEFINED, ATTR_ERROR_INVALID_ARGUMENT); |
257 COND_FAIL_NR(aContext, aType != AT_UNDEFINED, ATTR_ERROR_INVALID_ARGUMENT); |
|
258 |
|
259 index = aName - aContext->range_start; |
239 |
260 |
240 attr = &aContext->attributes[index]; |
261 attr = &aContext->attributes[index]; |
241 |
262 |
242 memset(attr, 0, sizeof(OWF_ATTRIBUTE)); |
263 memset(attr, 0, sizeof(OWF_ATTRIBUTE)); |
243 |
264 |
244 /* when allocin', size DOES matter */ |
265 /* when allocin', size DOES matter */ |
245 |
|
246 if (aType == AT_INTEGER || aType == AT_BOOLEAN) { |
266 if (aType == AT_INTEGER || aType == AT_BOOLEAN) { |
247 itemSize = sizeof(OWFint); |
267 itemSize = sizeof(OWFint); |
248 } else { |
268 } else { |
249 itemSize = sizeof(OWFfloat); |
269 itemSize = sizeof(OWFfloat); |
250 } |
270 } |
251 arraySize=itemSize*aLength; |
271 arraySize=itemSize*aLength; |
252 |
272 |
253 /* don't allocate cache for read-only 'butes */ |
273 /* don't allocate cache for read-only 'butes */ |
254 attr->attr_info.type = aType; |
274 attr->attr_info.type = aType; |
255 attr->attr_info.length = aLength; |
275 attr->attr_info.length = aLength; |
256 attr->attr_info.readonly = aRdOnly; |
276 attr->attr_info.readonly = aRdOnly; |
257 attr->attr_info.size = itemSize; |
277 attr->attr_info.size = itemSize; |
420 { |
434 { |
421 OWFint index = 0; |
435 OWFint index = 0; |
422 OWF_ATTRIBUTE* attr = 0; |
436 OWF_ATTRIBUTE* attr = 0; |
423 OWFint result = 0; |
437 OWFint result = 0; |
424 |
438 |
425 COND_FAIL(aContext, aContext, ATTR_ERROR_INVALID_ARGUMENT, 0); |
439 COND_FAIL_NS(aContext, 0); |
|
440 COND_FAIL(aContext, |
|
441 aContext->attributes, |
|
442 ATTR_ERROR_INVALID_CONTEXT, |
|
443 0); |
426 CHECK_BAD(aContext, aName, 0); |
444 CHECK_BAD(aContext, aName, 0); |
|
445 |
|
446 |
|
447 index = aName - aContext->range_start; |
|
448 attr = &aContext->attributes[index]; |
|
449 |
|
450 COND_FAIL(aContext, |
|
451 1 == attr->attr_info.length, |
|
452 ATTR_ERROR_INVALID_TYPE, |
|
453 0); |
|
454 |
|
455 SET_ERROR(aContext, ATTR_ERROR_NONE); |
|
456 |
|
457 switch (attr->attr_info.type) { |
|
458 case AT_FLOAT: { |
|
459 result = floor(attr->attr_value[WORKING_ATTR_VALUE_INDEX].float_value[0]); |
|
460 break; |
|
461 } |
|
462 |
|
463 case AT_INTEGER: |
|
464 case AT_BOOLEAN: { |
|
465 result = attr->attr_value[WORKING_ATTR_VALUE_INDEX].int_value[0]; |
|
466 break; |
|
467 } |
|
468 |
|
469 default: { |
|
470 SET_ERROR(aContext, ATTR_ERROR_INVALID_TYPE); |
|
471 break; |
|
472 } |
|
473 } |
|
474 return result; |
|
475 } |
|
476 |
|
477 /* |
|
478 * \brief Return boolean attribute value |
|
479 * |
|
480 * \param aContext Attribute context |
|
481 * \param aName Attribute name |
|
482 * |
|
483 * \return Attribute value |
|
484 * ATTR_ERROR_INVALID_ATTRIBUTE |
|
485 * ATTR_ERROR_INVALID_TYPE |
|
486 */ |
|
487 OWF_API_CALL OWFboolean |
|
488 OWF_Attribute_GetValueb(OWF_ATTRIBUTE_LIST* aContext, |
|
489 OWFint aName) |
|
490 { |
|
491 /* boolean is stored as int, must cast */ |
|
492 return (OWFboolean) OWF_Attribute_GetValuei(aContext, aName); |
|
493 } |
|
494 |
|
495 /* |
|
496 * \brief Get attribute float value |
|
497 * |
|
498 * \param aContext |
|
499 * \param aName |
|
500 * \param aValue |
|
501 * |
|
502 * \return Attribute |
|
503 */ |
|
504 OWF_API_CALL OWFfloat |
|
505 OWF_Attribute_GetValuef(OWF_ATTRIBUTE_LIST* aContext, |
|
506 OWFint aName) |
|
507 { |
|
508 OWFint index = 0; |
|
509 OWF_ATTRIBUTE* attr = NULL; |
|
510 OWFfloat result = 0.f; |
|
511 |
|
512 COND_FAIL_NS(aContext, 0); |
427 COND_FAIL(aContext, |
513 COND_FAIL(aContext, |
428 aContext->attributes, |
514 aContext->attributes, |
429 ATTR_ERROR_INVALID_CONTEXT, |
515 ATTR_ERROR_INVALID_CONTEXT, |
430 0); |
516 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); |
517 CHECK_BAD(aContext, aName, 0); |
499 COND_FAIL(aContext, |
518 |
500 aContext->attributes, |
|
501 ATTR_ERROR_INVALID_CONTEXT, |
|
502 0); |
|
503 |
519 |
504 index = aName - aContext->range_start; |
520 index = aName - aContext->range_start; |
505 attr = &aContext->attributes[index]; |
521 attr = &aContext->attributes[index]; |
506 |
522 |
507 COND_FAIL(aContext, |
523 COND_FAIL(aContext, |
959 { |
983 { |
960 return aDirtyFlag; |
984 return aDirtyFlag; |
961 } |
985 } |
962 } |
986 } |
963 |
987 |
|
988 |
964 OWF_API_CALL void |
989 OWF_API_CALL void |
965 OWF_AttributeList_Commit(OWF_ATTRIBUTE_LIST* aContext, |
990 OWF_AttributeList_Commit(OWF_ATTRIBUTE_LIST* aContext, |
966 OWFint aStart, |
991 OWFint aStart, |
967 OWFint aEnd, |
992 OWFint aEnd, |
968 OWFint aCopyTo ) |
993 OWFint aCopyTo ) |
969 { |
994 { |
970 OWFint index = 0; |
995 OWFint index = 0; |
971 /* Attribute commit works like the element list commit |
996 /* Attribute commit works like the element list commit |
972 * by forward-copying the "working" attributes to the snapshot |
997 * by forward-copying the "working" attributes to the snapshot |
973 * during client invoked commit, |
998 * during client invoked commit, |
974 * then copying the snapshot to the commited scene during the docommit job. |
999 * 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. |
1000 * 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, |
1001 * 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, |
1002 * in which case the index of the working attribute set would switch after each invoked commit, |
978 * instead of being a constant. |
1003 * instead of being a constant. |
|
1004 * |
979 * The same number of copies would still need to take place |
1005 * The same number of copies would still need to take place |
980 * but would not need exclusive access to the list. |
1006 * but would not need exclusive access to the list. |
981 */ |
1007 */ |
982 COND_FAIL_NR(aContext, aContext, ATTR_ERROR_INVALID_ARGUMENT); |
1008 |
|
1009 COND_FAIL_NR_NS(aContext); |
983 COND_FAIL_NR(aContext, aStart <= aEnd, ATTR_ERROR_INVALID_ARGUMENT); |
1010 COND_FAIL_NR(aContext, aStart <= aEnd, ATTR_ERROR_INVALID_ARGUMENT); |
984 COND_FAIL_NR(aContext, aContext->attributes, ATTR_ERROR_INVALID_CONTEXT); |
1011 COND_FAIL_NR(aContext, aContext->attributes, ATTR_ERROR_INVALID_CONTEXT); |
985 CHECK_BAD_NR(aContext, aStart); |
1012 CHECK_BAD_NR(aContext, aStart); |
986 CHECK_BAD_NR(aContext, aEnd); |
1013 CHECK_BAD_NR(aContext, aEnd); |
987 |
1014 |
988 |
|
989 switch (aCopyTo) |
1015 switch (aCopyTo) |
990 { |
1016 { |
991 case COMMITTED_ATTR_VALUE_INDEX: //Used in composition thread to set displayed scene attributes |
1017 case COMMITTED_ATTR_VALUE_INDEX: /* Used in composition thread to set displayed scene attributes */ |
992 for (index = aStart; index <= aEnd; index++) |
1018 for (index = aStart; index <= aEnd; index++) |
993 { |
1019 { |
994 OWF_ATTRIBUTE* attr = &aContext->attributes[index - aContext->range_start]; |
1020 OWF_ATTRIBUTE* attr = &aContext->attributes[index - aContext->range_start]; |
995 attr->attr_info.dirtysnapshot= |
1021 attr->attr_info.dirtysnapshot= |
996 OWF_Attribute_Commit(attr,attr->attr_info.dirtysnapshot, |
1022 OWF_Attribute_Commit(attr,attr->attr_info.dirtysnapshot, |
997 COMMITTED_ATTR_VALUE_INDEX,SNAPSHOT_ATTR_VALUE_INDEX); |
1023 COMMITTED_ATTR_VALUE_INDEX,SNAPSHOT_ATTR_VALUE_INDEX); |
998 } |
1024 } |
999 break; |
1025 break; |
1000 case SNAPSHOT_ATTR_VALUE_INDEX: //Used in API threads to make a snapshot of the client attributes |
1026 case SNAPSHOT_ATTR_VALUE_INDEX: /* Used in API threads to make a snapshot of the client attributes */ |
1001 for (index = aStart; index <= aEnd; index++) |
1027 for (index = aStart; index <= aEnd; index++) |
1002 { |
1028 { |
1003 OWF_ATTRIBUTE* attr = &aContext->attributes[index - aContext->range_start]; |
1029 OWF_ATTRIBUTE* attr = &aContext->attributes[index - aContext->range_start]; |
1004 OWFuint oldDirty=attr->attr_info.dirty; |
1030 OWFuint oldDirty=attr->attr_info.dirty; |
1005 attr->attr_info.dirtysnapshot=oldDirty; |
1031 attr->attr_info.dirtysnapshot=oldDirty; |
1006 attr->attr_info.dirty= |
1032 attr->attr_info.dirty= |
1007 OWF_Attribute_Commit(attr,oldDirty, |
1033 OWF_Attribute_Commit(attr,oldDirty, |
1008 SNAPSHOT_ATTR_VALUE_INDEX,WORKING_ATTR_VALUE_INDEX); |
1034 SNAPSHOT_ATTR_VALUE_INDEX,WORKING_ATTR_VALUE_INDEX); |
1009 } |
1035 } |
1010 break; |
1036 break; |
1011 case WORKING_ATTR_VALUE_INDEX: //Used in initialisation to copy displayed attributes to client copies |
1037 case WORKING_ATTR_VALUE_INDEX: /* Used in initialisation to copy displayed attributes to client copies */ |
1012 for (index = aStart; index <= aEnd; index++) |
1038 for (index = aStart; index <= aEnd; index++) |
1013 { |
1039 { |
1014 OWF_ATTRIBUTE* attr = &aContext->attributes[index - aContext->range_start]; |
1040 OWF_ATTRIBUTE* attr = &aContext->attributes[index - aContext->range_start]; |
1015 OWF_Attribute_Commit(attr,!attr->attr_info.readonly, |
1041 OWF_Attribute_Commit(attr,!attr->attr_info.readonly, |
1016 WORKING_ATTR_VALUE_INDEX,COMMITTED_ATTR_VALUE_INDEX); |
1042 WORKING_ATTR_VALUE_INDEX,COMMITTED_ATTR_VALUE_INDEX); |
1017 } |
1043 } |
1018 break; |
1044 break; |
1019 |
1045 case COMMIT_ATTR_DIRECT_FROM_WORKING: /* Used in WFD to commit new working values directly in 1 step. */ |
1020 } |
1046 for (index = aStart; index <= aEnd; index++) |
|
1047 { |
|
1048 OWF_ATTRIBUTE* attr = &aContext->attributes[index - aContext->range_start]; |
|
1049 attr->attr_info.dirty= |
|
1050 OWF_Attribute_Commit(attr,attr->attr_info.dirty, |
|
1051 COMMITTED_ATTR_VALUE_INDEX,WORKING_ATTR_VALUE_INDEX); |
|
1052 } |
|
1053 break; |
|
1054 default: |
|
1055 COND_FAIL_NR(aContext, 0, ATTR_ERROR_INVALID_ARGUMENT); |
|
1056 } |
1021 |
1057 |
1022 SET_ERROR(aContext, ATTR_ERROR_NONE); |
1058 SET_ERROR(aContext, ATTR_ERROR_NONE); |
1023 } |
1059 } |
1024 |
1060 |
1025 #ifdef __cplusplus |
1061 #ifdef __cplusplus |