1 /* Copyright (c) 2009 The Khronos Group Inc. |
1 /* Copyright (c) 2009-2010 The Khronos Group Inc. |
|
2 * Portions copyright (c) 2009-2010 Nokia Corporation and/or its subsidiary(-ies) |
2 * |
3 * |
3 * Permission is hereby granted, free of charge, to any person obtaining a |
4 * Permission is hereby granted, free of charge, to any person obtaining a |
4 * copy of this software and/or associated documentation files (the |
5 * copy of this software and/or associated documentation files (the |
5 * "Materials"), to deal in the Materials without restriction, including |
6 * "Materials"), to deal in the Materials without restriction, including |
6 * without limitation the rights to use, copy, modify, merge, publish, |
7 * without limitation the rights to use, copy, modify, merge, publish, |
32 #include <string.h> |
33 #include <string.h> |
33 #include <math.h> |
34 #include <math.h> |
34 |
35 |
35 #include "owfattributes.h" |
36 #include "owfattributes.h" |
36 #include "owfmemory.h" |
37 #include "owfmemory.h" |
|
38 #include "owfdebug.h" |
37 |
39 |
38 #define OWF_ATTRIB_RANGE_START (0) |
40 #define OWF_ATTRIB_RANGE_START (0) |
39 #define OWF_ATTRIB_RANGE_UNINITIALIZED (-1) |
41 #define OWF_ATTRIB_RANGE_UNINITIALIZED (-1) |
40 |
42 |
41 static OWFint OWF_Attribute_Commit(OWF_ATTRIBUTE* aAttr, OWFint aDirtyFlag, OWFint aCopyTo,OWFint aCopyFrom); |
43 static OWFint OWF_Attribute_Commit(OWF_ATTRIBUTE* aAttr, OWFint aDirtyFlag, OWFint aCopyTo,OWFint aCopyFrom); |
42 |
44 |
43 /* |
45 /* |
44 This attribute class is currently only used for context attributes. |
46 This attribute class is not used for WFC element attributes because elements are |
45 Why isn't it used for element attributes? |
47 completely cloned in the committed scene. |
46 - Because elements are completely cloned in the committed scene. |
48 [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 |
49 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.] |
50 Normal attribute values have three pointers indexed via an array: |
49 Normal attribute values have three pointers indexed via an array: |
51 COMMITTED_ATTR_VALUE_INDEX: |
50 COMMITTED_ATTR_VALUE_INDEX: |
52 Attribute values used by the scene |
51 Attribute values used by the scene |
53 - points to named variables directly used by the compositor |
52 - points to named variables directly used by the compositor |
54 WORKING_ATTR_VALUE_INDEX: |
53 WORKING_ATTR_VALUE_INDEX: |
55 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. |
56 SNAPSHOT_ATTR_VALUE_INDEX |
55 SNAPSHOT_ATTR_VALUE_INDEX |
57 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 |
58 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 |
59 the committed scene is updated and displayed. |
58 the committed scene is updated and displayed. |
60 The Working and Snapshot writable attributes require additional cache storage, |
59 The Working and Snapshot writable attributes require additional cache storage, |
61 which is managed by the lifetime of the attribute list. |
60 which is managed by the lifetime of the attribute list. |
62 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. |
63 Currently, there are relatively few writable attributes so it is reasonable |
62 Currently, there are relatively few writable attributes so it is reasonable |
64 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 |
65 a single block sized after the attributes have been registered. |
64 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. |
65 */ |
71 */ |
66 #define COND_FAIL_NR(ctx, condition, error) \ |
72 #define COND_FAIL_NR(ctx, condition, error) \ |
67 if (!(condition)) { \ |
73 if (!(condition)) { \ |
68 if (ctx) { \ |
74 if (ctx) { \ |
69 (ctx)->last_error = error; \ |
75 (ctx)->last_error = error; \ |
227 OWF_ATTRIBUTE* attr = NULL; |
247 OWF_ATTRIBUTE* attr = NULL; |
228 void* cache = NULL; |
248 void* cache = NULL; |
229 OWFint itemSize; |
249 OWFint itemSize; |
230 OWFint arraySize; |
250 OWFint arraySize; |
231 OWFint copy; |
251 OWFint copy; |
232 OWFint index = aName - aContext->range_start; |
252 OWFint index; |
233 |
253 |
234 COND_FAIL_NR(aContext, aContext, ATTR_ERROR_INVALID_ARGUMENT); |
254 COND_FAIL_NR_NS(aContext); |
235 CHECK_INDEX_NR(aContext, aName, ATTR_ERROR_INVALID_ATTRIBUTE); |
255 CHECK_INDEX_NR(aContext, aName, ATTR_ERROR_INVALID_ATTRIBUTE); |
236 COND_FAIL_NR(aContext, aContext->attributes, ATTR_ERROR_INVALID_CONTEXT); |
256 COND_FAIL_NR(aContext, aContext->attributes, ATTR_ERROR_INVALID_CONTEXT); |
237 COND_FAIL_NR(aContext, aLength < MAX_ATTR_LENGTH, ATTR_ERROR_CANT_HANDLE); |
257 COND_FAIL_NR(aContext, aLength < MAX_ATTR_LENGTH, ATTR_ERROR_CANT_HANDLE); |
238 COND_FAIL_NR(aContext, aType != AT_UNDEFINED, ATTR_ERROR_INVALID_ARGUMENT); |
258 COND_FAIL_NR(aContext, aType != AT_UNDEFINED, ATTR_ERROR_INVALID_ARGUMENT); |
|
259 |
|
260 index = aName - aContext->range_start; |
239 |
261 |
240 attr = &aContext->attributes[index]; |
262 attr = &aContext->attributes[index]; |
241 |
263 |
242 memset(attr, 0, sizeof(OWF_ATTRIBUTE)); |
264 memset(attr, 0, sizeof(OWF_ATTRIBUTE)); |
243 |
265 |
244 /* when allocin', size DOES matter */ |
266 /* when allocin', size DOES matter */ |
245 |
|
246 if (aType == AT_INTEGER || aType == AT_BOOLEAN) { |
267 if (aType == AT_INTEGER || aType == AT_BOOLEAN) { |
247 itemSize = sizeof(OWFint); |
268 itemSize = sizeof(OWFint); |
248 } else { |
269 } else { |
249 itemSize = sizeof(OWFfloat); |
270 itemSize = sizeof(OWFfloat); |
250 } |
271 } |
251 arraySize=itemSize*aLength; |
272 arraySize=itemSize*aLength; |
252 |
273 |
253 /* don't allocate cache for read-only 'butes */ |
274 /* don't allocate cache for read-only 'butes */ |
254 attr->attr_info.type = aType; |
275 attr->attr_info.type = aType; |
255 attr->attr_info.length = aLength; |
276 attr->attr_info.length = aLength; |
256 attr->attr_info.readonly = aRdOnly; |
277 attr->attr_info.readonly = aRdOnly; |
257 attr->attr_info.size = itemSize; |
278 attr->attr_info.size = itemSize; |
420 { |
435 { |
421 OWFint index = 0; |
436 OWFint index = 0; |
422 OWF_ATTRIBUTE* attr = 0; |
437 OWF_ATTRIBUTE* attr = 0; |
423 OWFint result = 0; |
438 OWFint result = 0; |
424 |
439 |
425 COND_FAIL(aContext, aContext, ATTR_ERROR_INVALID_ARGUMENT, 0); |
440 COND_FAIL_NS(aContext, 0); |
|
441 COND_FAIL(aContext, |
|
442 aContext->attributes, |
|
443 ATTR_ERROR_INVALID_CONTEXT, |
|
444 0); |
426 CHECK_BAD(aContext, aName, 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); |
427 COND_FAIL(aContext, |
514 COND_FAIL(aContext, |
428 aContext->attributes, |
515 aContext->attributes, |
429 ATTR_ERROR_INVALID_CONTEXT, |
516 ATTR_ERROR_INVALID_CONTEXT, |
430 0); |
517 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); |
518 CHECK_BAD(aContext, aName, 0); |
499 COND_FAIL(aContext, |
519 |
500 aContext->attributes, |
|
501 ATTR_ERROR_INVALID_CONTEXT, |
|
502 0); |
|
503 |
520 |
504 index = aName - aContext->range_start; |
521 index = aName - aContext->range_start; |
505 attr = &aContext->attributes[index]; |
522 attr = &aContext->attributes[index]; |
506 |
523 |
507 COND_FAIL(aContext, |
524 COND_FAIL(aContext, |
959 { |
984 { |
960 return aDirtyFlag; |
985 return aDirtyFlag; |
961 } |
986 } |
962 } |
987 } |
963 |
988 |
|
989 |
964 OWF_API_CALL void |
990 OWF_API_CALL void |
965 OWF_AttributeList_Commit(OWF_ATTRIBUTE_LIST* aContext, |
991 OWF_AttributeList_Commit(OWF_ATTRIBUTE_LIST* aContext, |
966 OWFint aStart, |
992 OWFint aStart, |
967 OWFint aEnd, |
993 OWFint aEnd, |
968 OWFint aCopyTo ) |
994 OWFint aCopyTo ) |
969 { |
995 { |
970 OWFint index = 0; |
996 OWFint index = 0; |
971 /* Attribute commit works like the element list commit |
997 /* Attribute commit works like the element list commit |
972 * by forward-copying the "working" attributes to the snapshot |
998 * by forward-copying the "working" attributes to the snapshot |
973 * during client invoked commit, |
999 * during client invoked commit, |
974 * then copying the snapshot to the commited scene during the docommit job. |
1000 * 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. |
1001 * 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, |
1002 * 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, |
1003 * in which case the index of the working attribute set would switch after each invoked commit, |
978 * instead of being a constant. |
1004 * instead of being a constant. |
|
1005 * |
979 * The same number of copies would still need to take place |
1006 * The same number of copies would still need to take place |
980 * but would not need exclusive access to the list. |
1007 * but would not need exclusive access to the list. |
981 */ |
1008 */ |
982 COND_FAIL_NR(aContext, aContext, ATTR_ERROR_INVALID_ARGUMENT); |
1009 |
|
1010 COND_FAIL_NR_NS(aContext); |
983 COND_FAIL_NR(aContext, aStart <= aEnd, ATTR_ERROR_INVALID_ARGUMENT); |
1011 COND_FAIL_NR(aContext, aStart <= aEnd, ATTR_ERROR_INVALID_ARGUMENT); |
984 COND_FAIL_NR(aContext, aContext->attributes, ATTR_ERROR_INVALID_CONTEXT); |
1012 COND_FAIL_NR(aContext, aContext->attributes, ATTR_ERROR_INVALID_CONTEXT); |
985 CHECK_BAD_NR(aContext, aStart); |
1013 CHECK_BAD_NR(aContext, aStart); |
986 CHECK_BAD_NR(aContext, aEnd); |
1014 CHECK_BAD_NR(aContext, aEnd); |
987 |
1015 |
988 |
|
989 switch (aCopyTo) |
1016 switch (aCopyTo) |
990 { |
1017 { |
991 case COMMITTED_ATTR_VALUE_INDEX: //Used in composition thread to set displayed scene attributes |
1018 case COMMITTED_ATTR_VALUE_INDEX: /* Used in composition thread to set displayed scene attributes */ |
992 for (index = aStart; index <= aEnd; index++) |
1019 for (index = aStart; index <= aEnd; index++) |
993 { |
1020 { |
994 OWF_ATTRIBUTE* attr = &aContext->attributes[index - aContext->range_start]; |
1021 OWF_ATTRIBUTE* attr = &aContext->attributes[index - aContext->range_start]; |
995 attr->attr_info.dirtysnapshot= |
1022 attr->attr_info.dirtysnapshot= |
996 OWF_Attribute_Commit(attr,attr->attr_info.dirtysnapshot, |
1023 OWF_Attribute_Commit(attr,attr->attr_info.dirtysnapshot, |
997 COMMITTED_ATTR_VALUE_INDEX,SNAPSHOT_ATTR_VALUE_INDEX); |
1024 COMMITTED_ATTR_VALUE_INDEX,SNAPSHOT_ATTR_VALUE_INDEX); |
998 } |
1025 } |
999 break; |
1026 break; |
1000 case SNAPSHOT_ATTR_VALUE_INDEX: //Used in API threads to make a snapshot of the client attributes |
1027 case SNAPSHOT_ATTR_VALUE_INDEX: /* Used in API threads to make a snapshot of the client attributes */ |
1001 for (index = aStart; index <= aEnd; index++) |
1028 for (index = aStart; index <= aEnd; index++) |
1002 { |
1029 { |
1003 OWF_ATTRIBUTE* attr = &aContext->attributes[index - aContext->range_start]; |
1030 OWF_ATTRIBUTE* attr = &aContext->attributes[index - aContext->range_start]; |
1004 OWFuint oldDirty=attr->attr_info.dirty; |
1031 OWFuint oldDirty=attr->attr_info.dirty; |
1005 attr->attr_info.dirtysnapshot=oldDirty; |
1032 attr->attr_info.dirtysnapshot=oldDirty; |
1006 attr->attr_info.dirty= |
1033 attr->attr_info.dirty= |
1007 OWF_Attribute_Commit(attr,oldDirty, |
1034 OWF_Attribute_Commit(attr,oldDirty, |
1008 SNAPSHOT_ATTR_VALUE_INDEX,WORKING_ATTR_VALUE_INDEX); |
1035 SNAPSHOT_ATTR_VALUE_INDEX,WORKING_ATTR_VALUE_INDEX); |
1009 } |
1036 } |
1010 break; |
1037 break; |
1011 case WORKING_ATTR_VALUE_INDEX: //Used in initialisation to copy displayed attributes to client copies |
1038 case WORKING_ATTR_VALUE_INDEX: /* Used in initialisation to copy displayed attributes to client copies */ |
1012 for (index = aStart; index <= aEnd; index++) |
1039 for (index = aStart; index <= aEnd; index++) |
1013 { |
1040 { |
1014 OWF_ATTRIBUTE* attr = &aContext->attributes[index - aContext->range_start]; |
1041 OWF_ATTRIBUTE* attr = &aContext->attributes[index - aContext->range_start]; |
1015 OWF_Attribute_Commit(attr,!attr->attr_info.readonly, |
1042 OWF_Attribute_Commit(attr,!attr->attr_info.readonly, |
1016 WORKING_ATTR_VALUE_INDEX,COMMITTED_ATTR_VALUE_INDEX); |
1043 WORKING_ATTR_VALUE_INDEX,COMMITTED_ATTR_VALUE_INDEX); |
1017 } |
1044 } |
1018 break; |
1045 break; |
1019 |
1046 case COMMIT_ATTR_DIRECT_FROM_WORKING: /* Used in WFD to commit new working values directly in 1 step. */ |
1020 } |
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 } |
1021 |
1058 |
1022 SET_ERROR(aContext, ATTR_ERROR_NONE); |
1059 SET_ERROR(aContext, ATTR_ERROR_NONE); |
1023 } |
1060 } |
1024 |
1061 |
1025 #ifdef __cplusplus |
1062 #ifdef __cplusplus |