|
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 |