|
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 /*! \ingroup wfc |
|
24 * \file wfccontext.c |
|
25 * |
|
26 * \brief SI Context handling |
|
27 */ |
|
28 |
|
29 #include <string.h> |
|
30 #include <stdio.h> |
|
31 #include <time.h> |
|
32 #include <stdlib.h> |
|
33 #include <math.h> |
|
34 |
|
35 #include <WF/wfc.h> |
|
36 #include <EGL/egl.h> |
|
37 |
|
38 #include "wfccontext.h" |
|
39 #include "wfcpipeline.h" |
|
40 |
|
41 #include "owfscreen.h" |
|
42 #include "owfdisplaycontextgeneral.h" |
|
43 #include "owfnotifications.h" |
|
44 |
|
45 |
|
46 /*! maximum number of elements per scene */ |
|
47 #define MAX_ELEMENTS 512 |
|
48 /*! maximum number of scenes per context */ |
|
49 #define MAX_SCENES 3 |
|
50 |
|
51 |
|
52 #define CONTEXT_SCENE_POOL_SIZE MAX_SCENES |
|
53 #define CONTEXT_ELEMENT_POOL_SIZE MAX_SCENES * MAX_ELEMENTS |
|
54 #define CONTEXT_NODE_POOL_SIZE 2 * CONTEXT_ELEMENT_POOL_SIZE |
|
55 |
|
56 /*! almost 2^31 */ |
|
57 #define MAX_DELAY 2100000000 |
|
58 |
|
59 /*! 15ms */ |
|
60 #define AUTO_COMPOSE_DELAY 15000 |
|
61 #define FIRST_CONTEXT_HANDLE 2000 |
|
62 |
|
63 #define WAIT_FOREVER -1 |
|
64 |
|
65 #ifdef __cplusplus |
|
66 extern "C" { |
|
67 #endif |
|
68 |
|
69 static WFCHandle nextContextHandle = FIRST_CONTEXT_HANDLE; |
|
70 |
|
71 typedef enum |
|
72 { |
|
73 WFC_MESSAGE_NONE, |
|
74 WFC_MESSAGE_QUIT, |
|
75 WFC_MESSAGE_COMPOSE, |
|
76 WFC_MESSAGE_COMMIT, |
|
77 WFC_MESSAGE_FENCE_1_DISPLAY, |
|
78 WFC_MESSAGE_FENCE_2_SYNCOBJECT, |
|
79 WFC_MESSAGE_ACTIVATE, |
|
80 WFC_MESSAGE_DEACTIVATE, |
|
81 WFC_MESSAGE_START_COUNTDOWN, |
|
82 WFC_MESSAGE_CANCEL |
|
83 } WFC_MESSAGES; |
|
84 |
|
85 static void* |
|
86 WFC_Context_ComposerThread(void* data); |
|
87 |
|
88 |
|
89 /*--------------------------------------------------------------------------- |
|
90 * |
|
91 *----------------------------------------------------------------------------*/ |
|
92 void WFC_CONTEXT_Ctor(void* self) |
|
93 { |
|
94 self = self; |
|
95 } |
|
96 |
|
97 /*---------------------------------------------------------------------------*/ |
|
98 static WFCboolean |
|
99 WFC_Context_CreateState(WFC_CONTEXT* context) |
|
100 { /* Must be called late enough that scratch buffers can be mapped and hardware rotation capability queried */ |
|
101 OWF_IMAGE_FORMAT fInt, |
|
102 fExt; |
|
103 WFCint stride = 0; |
|
104 OWF_ASSERT(context); |
|
105 |
|
106 DPRINT(("WFC_Context_CreateContextState")); |
|
107 |
|
108 owfNativeStreamGetHeader(context->stream, |
|
109 NULL, NULL, &stride, &fExt, NULL); |
|
110 /* internal image used as intermediate target */ |
|
111 fInt.pixelFormat = OWF_IMAGE_ARGB_INTERNAL; |
|
112 fInt.linear = fExt.linear; |
|
113 fInt.premultiplied = fExt.premultiplied; |
|
114 fInt.rowPadding = 1; |
|
115 |
|
116 |
|
117 if (context->type == WFC_CONTEXT_TYPE_ON_SCREEN) |
|
118 { |
|
119 /* The unrotated target buffer: Can't get real address without locking for writing! NO STRIDE */ |
|
120 context->state.unrotatedTargetImage=OWF_Image_Create(context->targetWidth,context->targetHeight,&fExt,context->scratchBuffer[2],0); |
|
121 /* The rotated version of the target buffer for hardware rotation |
|
122 * or a de-rotated version of the internal buffer into another scratch buffer for software rotation |
|
123 */ |
|
124 if (OWF_Screen_Rotation_Supported(context->screenNumber)) |
|
125 { /* The rotated version of the target buffer for hardware rotation */ |
|
126 context->state.rotatedTargetImage=OWF_Image_Create(context->targetHeight,context->targetWidth,&fExt,context->scratchBuffer[2],0); |
|
127 } |
|
128 else |
|
129 { /* a de-rotated version of the internal buffer into another scratch buffer for software rotation */ |
|
130 context->state.rotatedTargetImage=OWF_Image_Create(context->targetWidth,context->targetHeight,&fInt,context->scratchBuffer[1],0); |
|
131 } |
|
132 } |
|
133 else |
|
134 { |
|
135 /* The unrotated target buffer: Can't get real address without locking for writing! STRIDE HONOURED */ |
|
136 context->state.unrotatedTargetImage=OWF_Image_Create(context->targetWidth,context->targetHeight,&fExt,context->scratchBuffer[2],stride); |
|
137 /* a de-rotated version of the internal buffer into another scratch buffer for software rotation */ |
|
138 context->state.rotatedTargetImage=OWF_Image_Create(context->targetWidth,context->targetHeight,&fInt,context->scratchBuffer[1],0); |
|
139 } |
|
140 /* The internal target buffer composed to for 0 and 180 degree rotation */ |
|
141 context->state.unrotatedInternalTargetImage=OWF_Image_Create(context->targetWidth,context->targetHeight,&fInt,context->scratchBuffer[0],stride); |
|
142 /* The internal target buffer composed to for 90 and 270 degree rotation */ |
|
143 context->state.rotatedInternalTargetImage=OWF_Image_Create(context->targetHeight,context->targetWidth,&fInt,context->scratchBuffer[0],stride); |
|
144 |
|
145 if (context->state.unrotatedTargetImage && context->state.rotatedTargetImage && context->state.unrotatedInternalTargetImage && context->state.rotatedInternalTargetImage) |
|
146 { |
|
147 return WFC_TRUE; |
|
148 } |
|
149 else |
|
150 { |
|
151 return WFC_FALSE; |
|
152 } |
|
153 } |
|
154 /*---------------------------------------------------------------------------*/ |
|
155 static void |
|
156 WFC_Context_DestroyState(WFC_CONTEXT* context) |
|
157 { |
|
158 /* The unrotated target buffer */ |
|
159 OWF_Image_Destroy(context->state.unrotatedTargetImage); |
|
160 /* The rotated version of the target buffer for hardware rotation, |
|
161 * or a de-rotated version of the internal buffer into another scratch buffer for software rotation |
|
162 */ |
|
163 OWF_Image_Destroy(context->state.rotatedTargetImage); |
|
164 /* The internal target buffer composed to for 0 and 180 degree rotation */ |
|
165 OWF_Image_Destroy(context->state.unrotatedInternalTargetImage); |
|
166 /* The internal target buffer composed to for 90 and 270 degree rotation */ |
|
167 OWF_Image_Destroy(context->state.rotatedInternalTargetImage); |
|
168 |
|
169 } |
|
170 /*--------------------------------------------------------------------------- |
|
171 * Should only be accessed indirectly by calls to WFC_Device_DestroyContext or |
|
172 * WFC_Device_DestroyContexts |
|
173 *----------------------------------------------------------------------------*/ |
|
174 void WFC_CONTEXT_Dtor(void* self) |
|
175 { |
|
176 OWFint ii = 0; |
|
177 WFC_CONTEXT* context = NULL; |
|
178 |
|
179 OWF_ASSERT(self); |
|
180 DPRINT(("WFC_CONTEXT_Dtor(%p)", self)); |
|
181 |
|
182 context = CONTEXT(self); |
|
183 |
|
184 OWF_ASSERT(context); |
|
185 |
|
186 WFC_Pipeline_DestroyState(context); |
|
187 WFC_Context_DestroyState(context); |
|
188 |
|
189 OWF_MessageQueue_Destroy(&context->composerQueue); |
|
190 |
|
191 /* make the stream destroyable */ |
|
192 if (context->stream != OWF_INVALID_HANDLE) |
|
193 { |
|
194 owfNativeStreamSetProtectionFlag(context->stream, OWF_FALSE); |
|
195 owfNativeStreamDestroy(context->stream); |
|
196 } |
|
197 context->stream = OWF_INVALID_HANDLE; |
|
198 |
|
199 OWF_AttributeList_Destroy(&context->attributes); |
|
200 |
|
201 for (ii = 0; ii < SCRATCH_BUFFER_COUNT; ii++) |
|
202 { |
|
203 OWF_Image_FreeData(context->displayContext, &context->scratchBuffer[ii]); |
|
204 context->scratchBuffer[ii] = 0; |
|
205 } |
|
206 |
|
207 OWF_DisplayContext_Destroy(context->screenNumber, context->displayContext); |
|
208 context->displayContext = NULL; |
|
209 |
|
210 OWF_Pool_Destroy(context->scenePool); |
|
211 OWF_Pool_Destroy(context->elementPool); |
|
212 OWF_Pool_Destroy(context->nodePool); |
|
213 |
|
214 OWF_Semaphore_Destroy(&context->compositionSemaphore); |
|
215 OWF_Semaphore_Destroy(&context->commitSemaphore); |
|
216 OWF_Mutex_Destroy(&context->updateFlagMutex); |
|
217 OWF_Mutex_Destroy(&context->sceneMutex); |
|
218 } |
|
219 |
|
220 /*--------------------------------------------------------------------------- |
|
221 * |
|
222 *----------------------------------------------------------------------------*/ |
|
223 OWF_API_CALL void |
|
224 WFC_Context_Shutdown(WFC_CONTEXT* context) |
|
225 { |
|
226 OWF_ASSERT(context); |
|
227 DPRINT(("WFC_Context_Shutdown(context = %d)", context->handle)); |
|
228 |
|
229 DPRINT(("Waiting for composer thread termination")); |
|
230 OWF_Message_Send(&context->composerQueue, WFC_MESSAGE_QUIT, 0); |
|
231 OWF_Thread_Join(context->composerThread, NULL); |
|
232 OWF_Thread_Destroy(context->composerThread); |
|
233 context->composerThread = NULL; |
|
234 |
|
235 if (context->device) |
|
236 { |
|
237 /* #4604: added guard condition */ |
|
238 WFC_Device_DestroyContextElements(context->device, context); |
|
239 WFC_Device_DestroyContextImageProviders(context->device, context); |
|
240 } |
|
241 |
|
242 WFC_Scene_Destroy(context->workScene); |
|
243 WFC_Scene_Destroy(context->snapshotScene); |
|
244 WFC_Scene_Destroy(context->committedScene); |
|
245 context->workScene = NULL; |
|
246 context->snapshotScene = NULL; |
|
247 context->committedScene = NULL; |
|
248 } |
|
249 |
|
250 /*--------------------------------------------------------------------------- |
|
251 * Initialize context attributes |
|
252 *----------------------------------------------------------------------------*/ |
|
253 OWF_API_CALL OWF_ATTRIBUTE_LIST_STATUS |
|
254 WFC_Context_InitializeAttributes(WFC_CONTEXT* context, |
|
255 WFCContextType type) |
|
256 { |
|
257 OWF_ATTRIBUTE_LIST_STATUS attribError=ATTR_ERROR_NONE; |
|
258 OWF_ASSERT(context); |
|
259 /* initialize attributes/properties */ |
|
260 if (context->stream) |
|
261 { |
|
262 owfNativeStreamGetHeader(context->stream, |
|
263 &context->targetWidth, |
|
264 &context->targetHeight, |
|
265 NULL, NULL, NULL); |
|
266 } |
|
267 context->type = type; |
|
268 context->rotation = WFC_ROTATION_0; |
|
269 context->backgroundColor = 0x000000FF; |
|
270 context->lowestElement = WFC_INVALID_HANDLE; |
|
271 |
|
272 |
|
273 OWF_AttributeList_Create(&context->attributes, |
|
274 WFC_CONTEXT_TYPE, |
|
275 WFC_CONTEXT_BG_COLOR); |
|
276 attribError=OWF_AttributeList_GetError(&context->attributes); |
|
277 if (attribError!=ATTR_ERROR_NONE) |
|
278 { |
|
279 OWF_ASSERT(attribError==ATTR_ERROR_NO_MEMORY); |
|
280 return attribError; |
|
281 } |
|
282 |
|
283 /* The composition code uses the member variables directly, |
|
284 * not via the attribute engine. |
|
285 */ |
|
286 OWF_Attribute_Initi(&context->attributes, |
|
287 WFC_CONTEXT_TYPE, |
|
288 (WFCint*) &context->type, |
|
289 OWF_TRUE); |
|
290 |
|
291 OWF_Attribute_Initi(&context->attributes, |
|
292 WFC_CONTEXT_TARGET_WIDTH, |
|
293 &context->targetWidth, |
|
294 OWF_TRUE); |
|
295 |
|
296 OWF_Attribute_Initi(&context->attributes, |
|
297 WFC_CONTEXT_TARGET_HEIGHT, |
|
298 &context->targetHeight, |
|
299 OWF_TRUE); |
|
300 |
|
301 OWF_Attribute_Initi(&context->attributes, |
|
302 WFC_CONTEXT_ROTATION, |
|
303 (WFCint*) &context->rotation, |
|
304 OWF_FALSE); |
|
305 |
|
306 OWF_Attribute_Initi(&context->attributes, |
|
307 WFC_CONTEXT_BG_COLOR, |
|
308 (WFCint*) &context->backgroundColor, |
|
309 OWF_FALSE); |
|
310 |
|
311 OWF_Attribute_Initi(&context->attributes, |
|
312 WFC_CONTEXT_LOWEST_ELEMENT, |
|
313 (OWFint*) &context->lowestElement, |
|
314 OWF_TRUE); |
|
315 attribError=OWF_AttributeList_GetError(&context->attributes); |
|
316 return attribError; |
|
317 } |
|
318 |
|
319 |
|
320 /*--------------------------------------------------------------------------- |
|
321 * |
|
322 *----------------------------------------------------------------------------*/ |
|
323 static WFC_CONTEXT* |
|
324 WFC_Context_Initialize(WFC_CONTEXT* context, |
|
325 WFC_DEVICE* device, |
|
326 WFCNativeStreamType stream, |
|
327 WFCContextType type, |
|
328 WFCint screenNum) |
|
329 { |
|
330 void* scratch[SCRATCH_BUFFER_COUNT]; |
|
331 OWFint err2 = 0; |
|
332 OWFint ii = 0, |
|
333 nbufs = 0; |
|
334 OWFint fail = 0; |
|
335 OWF_ATTRIBUTE_LIST_STATUS attribStatus = ATTR_ERROR_NONE; |
|
336 OWF_ASSERT(context); |
|
337 OWF_ASSERT(device); |
|
338 |
|
339 DPRINT(("WFC_Context_Initialize(%p,%p,%d,%d)", context, device, type, screenNum)); |
|
340 |
|
341 context->type = type; |
|
342 context->device = device; |
|
343 context->handle = nextContextHandle; |
|
344 context->screenNumber = screenNum; |
|
345 context->activationState = WFC_CONTEXT_STATE_PASSIVE; |
|
346 context->sourceUpdateCount = 0; |
|
347 context->clientElementCount = 0; |
|
348 ++nextContextHandle; |
|
349 |
|
350 context->displayContext = OWF_DisplayContext_Create(screenNum); |
|
351 if (context->displayContext == NULL) |
|
352 { |
|
353 DPRINT(("WFC_Context_Initialize(): Could not create display Context")); |
|
354 return NULL; |
|
355 } |
|
356 |
|
357 context->eglPrivateSignalSync = (TFPtrEglPrivateSignalSyncNok) eglGetProcAddress("egl_Private_SignalSyncNOK"); |
|
358 if (! context->eglPrivateSignalSync) |
|
359 { |
|
360 DPRINT(("WFC_Context_Initialize(): Missing EGL extension - egl_Private_SignalSyncNOK extension")); |
|
361 return NULL; |
|
362 } |
|
363 |
|
364 /*the following section of the code could be pushed to adaptation in future*/ |
|
365 if (type == WFC_CONTEXT_TYPE_ON_SCREEN) |
|
366 { |
|
367 OWF_IMAGE_FORMAT imageFormat; |
|
368 OWF_SCREEN screen; |
|
369 WFCint width = 0; |
|
370 WFCint height = 0; |
|
371 WFCint normalSize = 0; |
|
372 WFCint flippedSize = 0; |
|
373 WFCNativeStreamType stream; |
|
374 |
|
375 /* Set up stream for sending data to screen */ |
|
376 |
|
377 if (!OWF_Screen_GetHeader(screenNum, &screen)) |
|
378 { |
|
379 DPRINT(("WFC_Context_Initialize(): Could not retrieve the screen parameters")); |
|
380 return NULL; |
|
381 } |
|
382 |
|
383 /* Set on-screen pixel format */ |
|
384 imageFormat.pixelFormat = OWF_SURFACE_PIXEL_FORMAT; |
|
385 imageFormat.premultiplied = OWF_SURFACE_PREMULTIPLIED; |
|
386 imageFormat.linear = OWF_SURFACE_LINEAR; |
|
387 imageFormat.rowPadding = OWF_SURFACE_ROWPADDING; |
|
388 |
|
389 width = screen.normal.width; |
|
390 height = screen.normal.height; |
|
391 |
|
392 normalSize = screen.normal.height * screen.normal.stride; |
|
393 flippedSize = screen.flipped.height * screen.flipped.stride; |
|
394 |
|
395 if (flippedSize > normalSize) |
|
396 { |
|
397 width = screen.flipped.width; |
|
398 height = screen.flipped.height; |
|
399 } |
|
400 |
|
401 stream = owfNativeStreamCreateImageStream(width, |
|
402 height, |
|
403 &imageFormat, |
|
404 1); |
|
405 |
|
406 if (stream) |
|
407 { |
|
408 WFC_Context_SetTargetStream(context, stream); |
|
409 |
|
410 /* At this point the stream's refcount is 2 - we must decrement |
|
411 * it by one to ensure that the stream is destroyed when the |
|
412 * context (that "owns" it) is destroyed. |
|
413 */ |
|
414 owfNativeStreamRemoveReference(stream); |
|
415 } |
|
416 else |
|
417 { |
|
418 DPRINT(("WFC_Context_Initialize(): cannot create internal target stream")); |
|
419 return NULL; |
|
420 } |
|
421 } |
|
422 else |
|
423 { |
|
424 WFC_Context_SetTargetStream(context, stream); |
|
425 } |
|
426 |
|
427 nbufs = SCRATCH_BUFFER_COUNT-1; |
|
428 for (ii = 0; ii < nbufs; ii++) |
|
429 { |
|
430 scratch[ii] = OWF_Image_AllocData(context->displayContext, MAX_SOURCE_WIDTH, |
|
431 MAX_SOURCE_HEIGHT, |
|
432 OWF_IMAGE_ARGB_INTERNAL); |
|
433 fail = fail || (scratch[ii] == NULL); |
|
434 } |
|
435 |
|
436 /* |
|
437 * allocate one-channel buffer for alpha |
|
438 * obs! this assumes sizeof(OWFsubpixel) is 4. |
|
439 */ |
|
440 scratch[nbufs] = OWF_Image_AllocData(context->displayContext, MAX_SOURCE_WIDTH, |
|
441 MAX_SOURCE_HEIGHT, |
|
442 OWF_IMAGE_L32); |
|
443 fail = fail || (scratch[nbufs] == NULL); |
|
444 |
|
445 err2 = OWF_MessageQueue_Init(&context->composerQueue); |
|
446 fail = fail || (err2 != 0); |
|
447 |
|
448 if (fail) |
|
449 { |
|
450 OWF_MessageQueue_Destroy(&context->composerQueue); |
|
451 |
|
452 for (ii = 0; ii < SCRATCH_BUFFER_COUNT; ii++) |
|
453 { |
|
454 OWF_Image_FreeData(context->displayContext, &scratch[ii]); |
|
455 } |
|
456 return NULL; |
|
457 } |
|
458 |
|
459 for (ii = 0; ii < SCRATCH_BUFFER_COUNT; ii++) |
|
460 { |
|
461 context->scratchBuffer[ii] = scratch[ii]; |
|
462 } |
|
463 |
|
464 if (!WFC_Pipeline_CreateState(context) || !WFC_Context_CreateState(context)) |
|
465 { |
|
466 DPRINT(("WFC_Context_Initialize(): Could not create pipeline state object")); |
|
467 return NULL; |
|
468 } |
|
469 if ( OWF_Semaphore_Init(&context->compositionSemaphore, 1) |
|
470 || OWF_Semaphore_Init(&context->commitSemaphore, 1) |
|
471 || OWF_Mutex_Init(&context->updateFlagMutex) |
|
472 || OWF_Mutex_Init(&context->sceneMutex) |
|
473 |
|
474 ) |
|
475 { |
|
476 DPRINT(("WFC_Context_Initialize(): Could not create mutexes and semaphores!")); |
|
477 return NULL; |
|
478 } |
|
479 |
|
480 attribStatus= WFC_Context_InitializeAttributes(context, type); |
|
481 |
|
482 if (attribStatus!=ATTR_ERROR_NONE) |
|
483 { |
|
484 return NULL; |
|
485 } |
|
486 |
|
487 |
|
488 context->scenePool = OWF_Pool_Create(sizeof(WFC_SCENE), |
|
489 CONTEXT_SCENE_POOL_SIZE); |
|
490 context->elementPool = OWF_Pool_Create(sizeof(WFC_ELEMENT), |
|
491 CONTEXT_ELEMENT_POOL_SIZE); |
|
492 context->nodePool = OWF_Pool_Create(sizeof(OWF_NODE), |
|
493 CONTEXT_NODE_POOL_SIZE); |
|
494 if (!( context->scenePool && |
|
495 context->nodePool && context->elementPool)) |
|
496 { |
|
497 /* must call these to remove references to context */ |
|
498 context->workScene = NULL; |
|
499 context->committedScene = NULL; |
|
500 return NULL; |
|
501 } |
|
502 |
|
503 DPRINT((" Creating scenes")); |
|
504 context->workScene = WFC_Scene_Create(context); |
|
505 context->committedScene = WFC_Scene_Create(context); |
|
506 context->snapshotScene = NULL; |
|
507 |
|
508 /* snapshotScene is initialized in InvokeCommit */ |
|
509 |
|
510 /* context's refcount is now 3 */ |
|
511 |
|
512 if (!(context->workScene && context->committedScene && |
|
513 context->nodePool && context->elementPool)) |
|
514 { |
|
515 /* must call these to remove references to context */ |
|
516 WFC_Scene_Destroy(context->workScene); |
|
517 WFC_Scene_Destroy(context->committedScene); |
|
518 context->workScene = NULL; |
|
519 context->committedScene = NULL; |
|
520 return NULL; |
|
521 } |
|
522 |
|
523 |
|
524 context->composerThread = OWF_Thread_Create(WFC_Context_ComposerThread, |
|
525 context); |
|
526 if (!(context->composerThread)) |
|
527 { |
|
528 /* must call these to remove references to context */ |
|
529 WFC_Scene_Destroy(context->workScene); |
|
530 WFC_Scene_Destroy(context->committedScene); |
|
531 context->workScene = NULL; |
|
532 context->committedScene = NULL; |
|
533 return NULL; |
|
534 } |
|
535 |
|
536 return context; |
|
537 } |
|
538 |
|
539 /*--------------------------------------------------------------------------- |
|
540 * Create new context on device |
|
541 * |
|
542 * \param device Device on which the context should be created |
|
543 * \param type Context type (on- or off-screen) |
|
544 * |
|
545 * \return New context object or NULL in case of failure |
|
546 *----------------------------------------------------------------------------*/ |
|
547 OWF_API_CALL WFC_CONTEXT* |
|
548 WFC_Context_Create(WFC_DEVICE* device, |
|
549 WFCNativeStreamType stream, |
|
550 WFCContextType type, |
|
551 WFCint screenNum) |
|
552 { |
|
553 WFC_CONTEXT* context = NULL; |
|
554 |
|
555 OWF_ASSERT(device); |
|
556 context = CREATE(WFC_CONTEXT); |
|
557 |
|
558 if (context) |
|
559 { |
|
560 if (!WFC_Context_Initialize(context, device, stream, type, screenNum)) |
|
561 { |
|
562 DESTROY(context); |
|
563 } |
|
564 } |
|
565 return context; |
|
566 } |
|
567 |
|
568 /*--------------------------------------------------------------------------- |
|
569 * Setup context rendering target |
|
570 * |
|
571 * \param context Context |
|
572 * \param stream Target stream to use for rendering |
|
573 *----------------------------------------------------------------------------*/ |
|
574 OWF_API_CALL void |
|
575 WFC_Context_SetTargetStream(WFC_CONTEXT* context, |
|
576 OWFNativeStreamType stream) |
|
577 { |
|
578 OWF_ASSERT(context); |
|
579 context->stream = stream; |
|
580 |
|
581 owfNativeStreamAddReference(stream); |
|
582 |
|
583 owfNativeStreamGetHeader(stream, |
|
584 &context->targetWidth, &context->targetHeight, |
|
585 NULL, NULL, NULL); |
|
586 } |
|
587 /*--------------------------------------------------------------------------- |
|
588 * Checks if the given stream would be valid as an off-screen context target. |
|
589 * |
|
590 * Checks that the format can be rendered TO. |
|
591 * Also checks that the image size is acceptable (within the scratch buffers). |
|
592 * This is called before the context is created so is effectively a "static" context method. |
|
593 * |
|
594 * \param stream Target stream to use for rendering |
|
595 ---------------------------------------------------------------------------*/ |
|
596 |
|
597 OWF_API_CALL WFCboolean |
|
598 WFC_Context_IsValidTargetStream(OWFNativeStreamType stream) |
|
599 { |
|
600 OWFint width,height; |
|
601 OWF_IMAGE_FORMAT format; |
|
602 owfNativeStreamGetHeader(stream, |
|
603 &width, &height, |
|
604 NULL, &format, NULL); |
|
605 if (width>MAX_SOURCE_WIDTH) |
|
606 { |
|
607 return WFC_FALSE; |
|
608 } |
|
609 if (height>MAX_SOURCE_HEIGHT) |
|
610 { |
|
611 return WFC_FALSE; |
|
612 } |
|
613 return (WFCboolean)OWF_Image_IsValidDestinationFormat(&format); |
|
614 } |
|
615 |
|
616 /*--------------------------------------------------------------------------- |
|
617 * Checks that the image size is acceptable (within the scratch buffers). |
|
618 * This is called before the source is created. |
|
619 * |
|
620 * \param stream source stream to use for rendering. |
|
621 ---------------------------------------------------------------------------*/ |
|
622 |
|
623 OWF_API_CALL WFCboolean |
|
624 WFC_Context_IsValidSourceStream(OWFNativeStreamType stream) |
|
625 { |
|
626 OWFint width,height; |
|
627 owfNativeStreamGetHeader(stream, |
|
628 &width, &height, |
|
629 NULL, NULL, NULL); |
|
630 if ((width+2) * (height+2) > MAX_SOURCE_WIDTH * MAX_SOURCE_HEIGHT) |
|
631 { |
|
632 return WFC_FALSE; |
|
633 } |
|
634 return WFC_TRUE; |
|
635 } |
|
636 |
|
637 /*--------------------------------------------------------------------------- |
|
638 * Find element from current scene |
|
639 * |
|
640 * \param context Context object |
|
641 * \param element Element to find |
|
642 * |
|
643 * \return Element object or NULL if element hasn't been inserted |
|
644 * into current scene. |
|
645 *----------------------------------------------------------------------------*/ |
|
646 OWF_API_CALL WFC_ELEMENT* |
|
647 WFC_Context_FindElement(WFC_CONTEXT* context, |
|
648 WFCElement element) |
|
649 { |
|
650 OWF_ASSERT(context); |
|
651 return WFC_Scene_FindElement(context->workScene, element); |
|
652 } |
|
653 |
|
654 /*--------------------------------------------------------------------------- |
|
655 * Commit context scene graph changes |
|
656 * |
|
657 * \param context Context to commit |
|
658 *----------------------------------------------------------------------------*/ |
|
659 static void |
|
660 WFC_Context_DoCommit(WFC_CONTEXT* context) |
|
661 { |
|
662 OWF_ASSERT(context); |
|
663 DPRINT(("WFC_Context_DoCommit(context = %p)", context)); |
|
664 |
|
665 OWF_ASSERT(context->snapshotScene); |
|
666 |
|
667 |
|
668 DPRINT(("COMMIT: Committing attribute list changes")); |
|
669 |
|
670 DPRINT(("COMMIT: Acquiring mutex")); |
|
671 OWF_Mutex_Lock(&context->sceneMutex); |
|
672 |
|
673 /* comitting scene attribute changes */ |
|
674 DPRINT(("COMMIT: Committing scene attribute changes")); |
|
675 OWF_AttributeList_Commit(&context->attributes, |
|
676 WFC_CONTEXT_TYPE, |
|
677 WFC_CONTEXT_BG_COLOR,COMMITTED_ATTR_VALUE_INDEX); |
|
678 |
|
679 |
|
680 /* resolve sources and masks */ |
|
681 DPRINT(("COMMIT: Committing scene changes")); |
|
682 WFC_Scene_Commit(context->snapshotScene); |
|
683 DPRINT(("COMMIT: Destroying old committed scene")); |
|
684 WFC_Scene_Destroy(context->committedScene); |
|
685 DPRINT(("COMMIT: Setting new snapshot scene as committed one.")); |
|
686 context->committedScene = context->snapshotScene; |
|
687 context->snapshotScene = NULL; |
|
688 |
|
689 // reset the visibility flags |
|
690 owfSymDeviceResetVisibilityState(context); |
|
691 |
|
692 DPRINT(("COMMIT: Unlocking mutex")); |
|
693 OWF_Mutex_Unlock(&context->sceneMutex); |
|
694 |
|
695 DPRINT(("COMMIT: Signaling commit semaphore")); |
|
696 /* signal we're ready */ |
|
697 OWF_Semaphore_Post(&context->commitSemaphore); |
|
698 } |
|
699 |
|
700 /*--------------------------------------------------------------------------- |
|
701 * |
|
702 *----------------------------------------------------------------------------*/ |
|
703 static void |
|
704 WFC_Context_LockTargetForWriting(WFC_CONTEXT* context) |
|
705 { |
|
706 OWF_ASSERT(context); |
|
707 |
|
708 DPRINT(("WFC_Context_LockTargetForWriting")); |
|
709 |
|
710 context->state.targetBuffer = |
|
711 owfNativeStreamAcquireWriteBuffer(context->stream); |
|
712 context->state.targetPixels = |
|
713 owfNativeStreamGetBufferPtr(context->stream, |
|
714 context->state.targetBuffer); |
|
715 |
|
716 if ((WFC_ROTATION_0 == context->rotation || WFC_ROTATION_180 == context->rotation) || |
|
717 !OWF_Screen_Rotation_Supported(context->screenNumber)) |
|
718 { |
|
719 /* final target, in target format */ |
|
720 context->state.targetImage =context->state.unrotatedTargetImage; |
|
721 } |
|
722 else |
|
723 { |
|
724 /* final target, in target format */ |
|
725 /* fExt stride/padding value is the rotated value */ |
|
726 context->state.targetImage = context->state.rotatedTargetImage; |
|
727 } |
|
728 OWF_Image_SetPixelBuffer(context->state.targetImage,context->state.targetPixels); |
|
729 |
|
730 if (context->state.targetImage==NULL) |
|
731 { |
|
732 OWF_ASSERT(WFC_FALSE); |
|
733 } |
|
734 |
|
735 /* take context rotation into account. */ |
|
736 if (WFC_ROTATION_0 == context->rotation || |
|
737 WFC_ROTATION_180 == context->rotation) |
|
738 { |
|
739 context->state.internalTargetImage = context->state.unrotatedInternalTargetImage; |
|
740 } |
|
741 else |
|
742 { |
|
743 context->state.internalTargetImage = context->state.rotatedInternalTargetImage; |
|
744 } |
|
745 |
|
746 if (context->state.internalTargetImage==NULL) |
|
747 { |
|
748 OWF_ASSERT(WFC_FALSE); |
|
749 } |
|
750 } |
|
751 |
|
752 /*--------------------------------------------------------------------------- |
|
753 * |
|
754 *----------------------------------------------------------------------------*/ |
|
755 static void |
|
756 WFC_Context_UnlockTarget(WFC_CONTEXT* context) |
|
757 { |
|
758 OWFNativeStreamBuffer frontBuffer = OWF_INVALID_HANDLE; |
|
759 void* pixelDataPtr = NULL; |
|
760 OWF_ROTATION rotation = OWF_ROTATION_0; |
|
761 |
|
762 OWF_ASSERT(context); |
|
763 DPRINT(("WFC_Context_UnlockTarget")); |
|
764 DPRINT((" Unlocking target stream=%d, buffer=%d", |
|
765 context->stream, context->state.targetBuffer)); |
|
766 |
|
767 owfNativeStreamReleaseWriteBuffer(context->stream, |
|
768 context->state.targetBuffer, |
|
769 EGL_NO_DISPLAY, |
|
770 NULL); |
|
771 |
|
772 |
|
773 /* Refactor the code that follows so that it is triggered by the above releasewrite */ |
|
774 |
|
775 /* Acquire target stream front buffer and blit to SDL screen */ |
|
776 frontBuffer = owfNativeStreamAcquireReadBuffer(context->stream); |
|
777 DPRINT((" Locking target stream=%d, buffer=%d", |
|
778 context->stream, frontBuffer)); |
|
779 |
|
780 pixelDataPtr = owfNativeStreamGetBufferPtr(context->stream, frontBuffer); |
|
781 |
|
782 switch (context->rotation) |
|
783 { |
|
784 case WFC_ROTATION_0: |
|
785 { |
|
786 rotation = OWF_ROTATION_0; |
|
787 break; |
|
788 } |
|
789 case WFC_ROTATION_90: |
|
790 { |
|
791 rotation = OWF_ROTATION_90; |
|
792 break; |
|
793 } |
|
794 case WFC_ROTATION_180: |
|
795 { |
|
796 rotation = OWF_ROTATION_180; |
|
797 break; |
|
798 } |
|
799 case WFC_ROTATION_270: |
|
800 { |
|
801 rotation = OWF_ROTATION_270; |
|
802 break; |
|
803 } |
|
804 default: |
|
805 { |
|
806 OWF_ASSERT(0); |
|
807 } |
|
808 } |
|
809 |
|
810 OWF_Screen_Blit(context->screenNumber, pixelDataPtr, rotation); |
|
811 |
|
812 owfNativeStreamReleaseReadBuffer(context->stream, frontBuffer); |
|
813 DPRINT((" Releasing target stream=%d, buffer=%d", |
|
814 context->stream, frontBuffer)); |
|
815 |
|
816 } |
|
817 |
|
818 /*--------------------------------------------------------------------------- |
|
819 * |
|
820 *----------------------------------------------------------------------------*/ |
|
821 static void |
|
822 WFC_Context_PrepareComposition(WFC_CONTEXT* context) |
|
823 { |
|
824 OWFsubpixel r, g, b, a; |
|
825 |
|
826 OWF_ASSERT(context); |
|
827 |
|
828 /* the first thing to do is to lock target stream and fetch |
|
829 write buffer to it. fetching blocks until one is available, |
|
830 but since only one stream can be target to only one context |
|
831 at the time, no stalls should occur */ |
|
832 WFC_Context_LockTargetForWriting(context); |
|
833 |
|
834 /* prepare for composition by "clearing the table" with |
|
835 background color. */ |
|
836 |
|
837 r = (OWFsubpixel) OWF_RED_MAX_VALUE * ((context->backgroundColor >> 24) & |
|
838 0xFF) / OWF_BYTE_MAX_VALUE; |
|
839 g = (OWFsubpixel) OWF_GREEN_MAX_VALUE * ((context->backgroundColor >> 16) & |
|
840 0xFF) / OWF_BYTE_MAX_VALUE; |
|
841 b = (OWFsubpixel) OWF_BLUE_MAX_VALUE * ((context->backgroundColor >> 8) & |
|
842 0xFF) / OWF_BYTE_MAX_VALUE; |
|
843 a = (OWFsubpixel) OWF_ALPHA_MAX_VALUE * (context->backgroundColor & 0xFF) / |
|
844 OWF_BYTE_MAX_VALUE; |
|
845 |
|
846 r = r * a / OWF_ALPHA_MAX_VALUE; |
|
847 g = g * a / OWF_ALPHA_MAX_VALUE; |
|
848 b = b * a / OWF_ALPHA_MAX_VALUE; |
|
849 |
|
850 OWF_Image_Clear(context->state.internalTargetImage, r, g, b, a); |
|
851 |
|
852 WFC_Scene_LockSourcesAndMasks(context->committedScene); |
|
853 } |
|
854 |
|
855 |
|
856 |
|
857 /*--------------------------------------------------------------------------- |
|
858 * |
|
859 *----------------------------------------------------------------------------*/ |
|
860 static void |
|
861 WFC_Context_FinishComposition(WFC_CONTEXT* context) |
|
862 { |
|
863 OWF_ROTATION rotation = OWF_ROTATION_0; |
|
864 OWFint screenNumber; |
|
865 OWFboolean screenRotation; |
|
866 |
|
867 OWF_ASSERT(context); |
|
868 |
|
869 screenNumber = context->screenNumber; |
|
870 screenRotation = OWF_Screen_Rotation_Supported(screenNumber); |
|
871 /* re-use scratch buffer 1 for context rotation */ |
|
872 if (WFC_ROTATION_0 == context->rotation || screenRotation) |
|
873 { |
|
874 |
|
875 if (screenRotation) |
|
876 { |
|
877 if (WFC_ROTATION_90 == context->rotation || WFC_ROTATION_270 == context->rotation) |
|
878 { |
|
879 owfSetStreamFlipState(context->stream, OWF_TRUE); |
|
880 } |
|
881 else |
|
882 { |
|
883 owfSetStreamFlipState(context->stream, OWF_FALSE); |
|
884 } |
|
885 } |
|
886 OWF_Image_DestinationFormatConversion(context->state.targetImage, context->state.internalTargetImage); |
|
887 } |
|
888 else |
|
889 { |
|
890 switch (context->rotation) |
|
891 { |
|
892 case WFC_ROTATION_0: |
|
893 { |
|
894 rotation = OWF_ROTATION_0; |
|
895 break; |
|
896 } |
|
897 case WFC_ROTATION_90: |
|
898 { |
|
899 rotation = OWF_ROTATION_90; |
|
900 break; |
|
901 } |
|
902 case WFC_ROTATION_180: |
|
903 { |
|
904 rotation = OWF_ROTATION_180; |
|
905 break; |
|
906 } |
|
907 case WFC_ROTATION_270: |
|
908 { |
|
909 rotation = OWF_ROTATION_270; |
|
910 break; |
|
911 } |
|
912 default: |
|
913 { |
|
914 OWF_ASSERT(0); |
|
915 } |
|
916 } |
|
917 |
|
918 /* rotate */ |
|
919 OWF_Image_Rotate(context->state.rotatedTargetImage, |
|
920 context->state.internalTargetImage, |
|
921 rotation); |
|
922 |
|
923 /* Note: support of different target formats can be put here */ |
|
924 |
|
925 OWF_Image_DestinationFormatConversion(context->state.targetImage, context->state.rotatedTargetImage); |
|
926 } |
|
927 WFC_Context_UnlockTarget(context); |
|
928 WFC_Scene_UnlockSourcesAndMasks(context->committedScene); |
|
929 } |
|
930 |
|
931 /*!--------------------------------------------------------------------------- |
|
932 * \brief Actual composition routine. |
|
933 * Mainly just calls other functions that executes different stages of |
|
934 * the composition pipeline. |
|
935 * \param context Context to compose. |
|
936 *----------------------------------------------------------------------------*/ |
|
937 static void |
|
938 WFC_Context_DoCompose(WFC_CONTEXT* context) |
|
939 { |
|
940 WFC_SCENE* scene = NULL; |
|
941 OWF_NODE* node = NULL; |
|
942 |
|
943 OWF_ASSERT(context); |
|
944 |
|
945 OWF_Mutex_Lock(&context->updateFlagMutex); |
|
946 |
|
947 OWF_DisplayContext_IncrementSerialNumber(context->displayContext); |
|
948 |
|
949 OWF_DisplayContext_SetCompositionOngoing(context->displayContext, WFC_TRUE); |
|
950 context->sourceUpdateCount = 0; |
|
951 OWF_Mutex_Unlock(&context->updateFlagMutex); |
|
952 |
|
953 WFC_Context_PrepareComposition(context); |
|
954 |
|
955 DPRINT(("WFC_Context_Compose")); |
|
956 /* Composition always uses the committed version |
|
957 * of the scene. |
|
958 */ |
|
959 |
|
960 OWF_Mutex_Lock(&context->sceneMutex); |
|
961 |
|
962 scene = context->committedScene; |
|
963 OWF_ASSERT(scene); |
|
964 |
|
965 for (node = scene->elements; NULL != node; node = node->next) |
|
966 { |
|
967 |
|
968 WFC_ELEMENT* element = NULL; |
|
969 WFC_ELEMENT_STATE* elementState = NULL; |
|
970 element = ELEMENT(node->data); |
|
971 |
|
972 if (element->skipCompose) |
|
973 { |
|
974 /* this element is somehow degraded, its source is missing or |
|
975 * something else; skip to next element */ |
|
976 DPRINT((" *** Skipping element %d", element->handle)); |
|
977 continue; |
|
978 } |
|
979 |
|
980 DPRINT((" Composing element %d", element->handle)); |
|
981 |
|
982 /* BeginComposition may fail e.g. if the element's destination |
|
983 * rectangle is something bizarre, i.e. causes overflows or |
|
984 * something. |
|
985 */ |
|
986 if ((elementState=WFC_Pipeline_BeginComposition(context, element))!=NULL) |
|
987 { |
|
988 owfSymElementNotifications(context, element); |
|
989 |
|
990 WFC_Pipeline_ExecuteSourceConversionStage(context, elementState); |
|
991 WFC_Pipeline_ExecuteCropStage(context, elementState); |
|
992 WFC_Pipeline_ExecuteFlipStage(context, elementState); |
|
993 WFC_Pipeline_ExecuteRotationStage(context, elementState); |
|
994 WFC_Pipeline_ExecuteScalingStage(context, elementState); |
|
995 WFC_Pipeline_ExecuteBlendingStage(context, elementState); |
|
996 |
|
997 WFC_Pipeline_EndComposition(context, element,elementState); |
|
998 } |
|
999 } |
|
1000 |
|
1001 WFC_Context_FinishComposition(context); |
|
1002 |
|
1003 owfSymProcessAllNotifications(context); |
|
1004 OWF_Mutex_Unlock(&context->sceneMutex); |
|
1005 |
|
1006 OWF_Semaphore_Post(&context->compositionSemaphore); |
|
1007 } |
|
1008 |
|
1009 /*--------------------------------------------------------------------------- |
|
1010 * Activate/deactivate auto-composition on context |
|
1011 * |
|
1012 * \param context Context |
|
1013 * \param act Auto-composition enable/disable |
|
1014 *----------------------------------------------------------------------------*/ |
|
1015 OWF_API_CALL void |
|
1016 WFC_Context_Activate(WFC_CONTEXT* context, |
|
1017 WFCboolean act) |
|
1018 { |
|
1019 OWF_ASSERT(context); |
|
1020 |
|
1021 DPRINT(("WFC_Context_Activate: %s", (act) ? "activate" : "deactivate")); |
|
1022 |
|
1023 if (act && !WFC_Context_Active(context)) |
|
1024 { |
|
1025 DPRINT(("WFC_Context_Activate: WFC_CONTEXT_STATE_PASSIVE: activating")); |
|
1026 context->activationState = WFC_CONTEXT_STATE_ACTIVATING; |
|
1027 |
|
1028 /* moved from composer loop - updates must be allowed |
|
1029 * immediately after activation |
|
1030 */ |
|
1031 WFC_Device_EnableContentNotifications(context->device, |
|
1032 context, |
|
1033 WFC_TRUE); |
|
1034 |
|
1035 OWF_Message_Send(&context->composerQueue, |
|
1036 WFC_MESSAGE_ACTIVATE, |
|
1037 0); |
|
1038 } |
|
1039 else if (!act && WFC_Context_Active(context)) |
|
1040 { |
|
1041 DPRINT(("WFC_Context_Activate: WFC_CONTEXT_STATE_ACTIVE: deactivating")); |
|
1042 context->activationState = WFC_CONTEXT_STATE_DEACTIVATING; |
|
1043 OWF_Message_Send(&context->composerQueue, |
|
1044 WFC_MESSAGE_DEACTIVATE, |
|
1045 0); |
|
1046 } |
|
1047 } |
|
1048 |
|
1049 /*--------------------------------------------------------------------------- |
|
1050 * |
|
1051 *----------------------------------------------------------------------------*/ |
|
1052 OWF_API_CALL WFCboolean |
|
1053 WFC_Context_InvokeComposition(WFC_DEVICE* device, |
|
1054 WFC_CONTEXT* context, |
|
1055 WFCboolean wait) |
|
1056 { |
|
1057 WFCint status = 0; |
|
1058 |
|
1059 OWF_ASSERT(context); |
|
1060 OWF_ASSERT(device); |
|
1061 |
|
1062 device = device; /* suppress the compiler warning */ |
|
1063 |
|
1064 status = OWF_Semaphore_TryWait(&context->compositionSemaphore); |
|
1065 if (status) |
|
1066 { |
|
1067 if (!wait) |
|
1068 { |
|
1069 /* busy; processing last request */ |
|
1070 return WFC_FALSE; |
|
1071 } |
|
1072 /* wait previous frame composition to finish */ |
|
1073 OWF_Semaphore_Wait(&context->compositionSemaphore); |
|
1074 } |
|
1075 |
|
1076 /* compositionSemaphore is posted/signaled in WFC_Context_Compose() |
|
1077 after frame has been successfully composed */ |
|
1078 OWF_Message_Send(&context->composerQueue, WFC_MESSAGE_COMPOSE, 0); |
|
1079 |
|
1080 return WFC_TRUE; |
|
1081 } |
|
1082 |
|
1083 /*--------------------------------------------------------------------------- |
|
1084 * |
|
1085 *----------------------------------------------------------------------------*/ |
|
1086 OWF_API_CALL WFCErrorCode |
|
1087 WFC_Context_InvokeCommit(WFC_DEVICE* device, |
|
1088 WFC_CONTEXT* context, |
|
1089 WFCboolean wait) |
|
1090 { |
|
1091 WFCint status = 0; |
|
1092 |
|
1093 OWF_ASSERT(context); |
|
1094 OWF_ASSERT(device); |
|
1095 |
|
1096 device = device; /* suppress the compiler warning */ |
|
1097 |
|
1098 /* first check if there're inconsistensies in the scene */ |
|
1099 if (WFC_Scene_HasConflicts(context->workScene)) |
|
1100 { |
|
1101 DPRINT(("WFC_Context_InvokeCommit: scene has inconsistensies")); |
|
1102 return WFC_ERROR_INCONSISTENCY; |
|
1103 } |
|
1104 |
|
1105 /* then commit - always asynchronously */ |
|
1106 status = OWF_Semaphore_TryWait(&context->commitSemaphore); |
|
1107 DPRINT(("COMMIT: Commit semaphore status = %d", status)); |
|
1108 if (status) |
|
1109 { |
|
1110 if (!wait) |
|
1111 { |
|
1112 DPRINT(("COMMIT: Busy; exiting.")); |
|
1113 /* busy; processing last commit */ |
|
1114 return WFC_ERROR_BUSY; |
|
1115 } |
|
1116 |
|
1117 DPRINT(("COMMIT: Waiting for previous commit to finish.")); |
|
1118 /* wait previous commit to finish */ |
|
1119 OWF_Semaphore_Wait(&context->commitSemaphore); |
|
1120 } |
|
1121 |
|
1122 /* comitting scene attribute changes */ |
|
1123 DPRINT(("COMMIT: Cloning scene attribute changes")); |
|
1124 OWF_AttributeList_Commit(&context->attributes, |
|
1125 WFC_CONTEXT_TYPE, |
|
1126 WFC_CONTEXT_BG_COLOR,SNAPSHOT_ATTR_VALUE_INDEX); |
|
1127 |
|
1128 DPRINT(("COMMIT: Cloning scene")); |
|
1129 /* take snapshot of the current working copy - it will |
|
1130 * be the new committed scene */ |
|
1131 context->snapshotScene = WFC_Scene_Clone(context->workScene); |
|
1132 |
|
1133 DPRINT(("COMMIT: Sending commit request")); |
|
1134 /* invoke async commit */ |
|
1135 OWF_Message_Send(&context->composerQueue, WFC_MESSAGE_COMMIT, 0); |
|
1136 return WFC_ERROR_NONE; |
|
1137 } |
|
1138 |
|
1139 /*--------------------------------------------------------------------------- |
|
1140 * \param context |
|
1141 * \param dpy |
|
1142 * \param sync |
|
1143 *----------------------------------------------------------------------------*/ |
|
1144 OWF_API_CALL void |
|
1145 WFC_Context_InsertFence(WFC_CONTEXT* context, |
|
1146 WFCEGLDisplay dpy, |
|
1147 WFCEGLSync sync) |
|
1148 { |
|
1149 OWF_ASSERT(context); |
|
1150 OWF_ASSERT(sync); |
|
1151 |
|
1152 DPRINT(("WFC_Context_InsertFence: Sending fence sync: 0x%08x", sync)); |
|
1153 |
|
1154 OWF_Message_Send(&context->composerQueue, WFC_MESSAGE_FENCE_1_DISPLAY, (void*) dpy); |
|
1155 OWF_Message_Send(&context->composerQueue, WFC_MESSAGE_FENCE_2_SYNCOBJECT, sync); |
|
1156 } |
|
1157 |
|
1158 /*--------------------------------------------------------------------------- |
|
1159 * Insert element into context's scene |
|
1160 * |
|
1161 * \param context |
|
1162 * \param element |
|
1163 * \param subordinate |
|
1164 * |
|
1165 * \return WFCErrorCode |
|
1166 *----------------------------------------------------------------------------*/ |
|
1167 OWF_API_CALL WFCErrorCode |
|
1168 WFC_Context_InsertElement(WFC_CONTEXT* context, |
|
1169 WFCElement element, |
|
1170 WFCElement subordinate) |
|
1171 { |
|
1172 WFC_ELEMENT* object = NULL; |
|
1173 WFCErrorCode result = WFC_ERROR_BAD_HANDLE; |
|
1174 |
|
1175 OWF_ASSERT(context); |
|
1176 |
|
1177 object = WFC_Device_FindElement(context->device, element); |
|
1178 |
|
1179 if (NULL != object && CONTEXT(object->context) == context) |
|
1180 { |
|
1181 /* set the sharing flag as the element will be |
|
1182 * shared between the device and working copy scene. |
|
1183 * this is to tell the scene that it must not destroy |
|
1184 * this element. |
|
1185 */ |
|
1186 object->shared = WFC_TRUE; |
|
1187 result = WFC_Scene_InsertElement(context->workScene, |
|
1188 object, |
|
1189 subordinate); |
|
1190 |
|
1191 context->lowestElement = WFC_Scene_LowestElement(context->workScene); |
|
1192 } |
|
1193 return result; |
|
1194 } |
|
1195 |
|
1196 /*--------------------------------------------------------------------------- |
|
1197 * Remove element from context's scene |
|
1198 * |
|
1199 * \param context |
|
1200 * \param element |
|
1201 * |
|
1202 * \return WFCErrorCode |
|
1203 *----------------------------------------------------------------------------*/ |
|
1204 OWF_API_CALL WFCErrorCode |
|
1205 WFC_Context_RemoveElement(WFC_CONTEXT* context, |
|
1206 WFCElement element) |
|
1207 { |
|
1208 WFCErrorCode err = WFC_ERROR_BAD_HANDLE; |
|
1209 WFC_ELEMENT* elemento = NULL; |
|
1210 |
|
1211 OWF_ASSERT(context); |
|
1212 |
|
1213 elemento = WFC_Context_FindElement(context, element); |
|
1214 |
|
1215 if (elemento) |
|
1216 { |
|
1217 WFC_Scene_RemoveElement(context->workScene, element); |
|
1218 /* the element is no longer shared, as it only resides |
|
1219 * in device from this point on |
|
1220 */ |
|
1221 elemento->shared = WFC_FALSE; |
|
1222 context->lowestElement = WFC_Scene_LowestElement(context->workScene); |
|
1223 |
|
1224 err = WFC_ERROR_NONE; |
|
1225 } |
|
1226 |
|
1227 return err; |
|
1228 } |
|
1229 |
|
1230 /*! |
|
1231 * \brief IncreaseClientElementCount |
|
1232 * |
|
1233 * \param context |
|
1234 * \return positive increased current element count; negative or zero indicating the count can't be increased |
|
1235 */ |
|
1236 OWF_API_CALL WFCint |
|
1237 WFC_Context_IncreaseClientElementCount(WFC_CONTEXT* context) |
|
1238 { |
|
1239 /* This implementation simply caps the number of elements allocated to the client |
|
1240 * to 1/3 of the total elements. |
|
1241 * A cleverer strategy would allow the client to create more elements |
|
1242 * so long as the number added to the scene *2 did not exceed the spare pool size. |
|
1243 * These failure points are also a good place to consider increasing the pool size |
|
1244 */ |
|
1245 if (context->clientElementCount>=MAX_ELEMENTS) |
|
1246 { |
|
1247 return -context->clientElementCount; |
|
1248 } |
|
1249 else |
|
1250 { |
|
1251 return ++context->clientElementCount; |
|
1252 } |
|
1253 } |
|
1254 |
|
1255 /*! |
|
1256 * \brief DecreaseClientElementCount |
|
1257 * |
|
1258 * \param context |
|
1259 * \return positive or zero decreased current element count; negative indicating the count can't be decreased - p0robably already zero |
|
1260 */ |
|
1261 OWF_API_CALL WFCint |
|
1262 WFC_Context_DecreaseClientElementCount(WFC_CONTEXT* context) |
|
1263 { |
|
1264 /* note that a negative return indicates that decrements are not matched with increments */ |
|
1265 return --context->clientElementCount; |
|
1266 } |
|
1267 |
|
1268 /*--------------------------------------------------------------------------- |
|
1269 * |
|
1270 *----------------------------------------------------------------------------*/ |
|
1271 OWF_API_CALL WFCErrorCode |
|
1272 WFC_Context_GetElementAbove(WFC_CONTEXT* context, |
|
1273 WFCElement element, |
|
1274 WFCElement* result) |
|
1275 { |
|
1276 WFC_ELEMENT* object = NULL; |
|
1277 WFCErrorCode error = WFC_ERROR_ILLEGAL_ARGUMENT; |
|
1278 |
|
1279 OWF_ASSERT(context); |
|
1280 OWF_ASSERT(result); |
|
1281 |
|
1282 object = WFC_Context_FindElement(context, element); |
|
1283 |
|
1284 if (object) |
|
1285 { |
|
1286 WFCElement temp; |
|
1287 |
|
1288 temp = WFC_Scene_GetNeighbourElement(context->workScene, element, 1); |
|
1289 *result = temp; |
|
1290 error = WFC_ERROR_NONE; |
|
1291 } |
|
1292 return error; |
|
1293 } |
|
1294 |
|
1295 /*--------------------------------------------------------------------------- |
|
1296 * |
|
1297 *----------------------------------------------------------------------------*/ |
|
1298 OWF_API_CALL WFCErrorCode |
|
1299 WFC_Context_GetElementBelow(WFC_CONTEXT* context, |
|
1300 WFCElement element, |
|
1301 WFCElement* result) |
|
1302 { |
|
1303 WFC_ELEMENT* object = NULL; |
|
1304 WFCErrorCode error = WFC_ERROR_ILLEGAL_ARGUMENT; |
|
1305 |
|
1306 OWF_ASSERT(context); |
|
1307 OWF_ASSERT(result); |
|
1308 |
|
1309 object = WFC_Context_FindElement(context, element); |
|
1310 if (object) |
|
1311 { |
|
1312 WFCElement temp; |
|
1313 |
|
1314 temp = WFC_Scene_GetNeighbourElement(context->workScene, element, -1); |
|
1315 *result = temp; |
|
1316 error = WFC_ERROR_NONE; |
|
1317 } |
|
1318 return error; |
|
1319 } |
|
1320 |
|
1321 /*--------------------------------------------------------------------------- |
|
1322 * |
|
1323 *----------------------------------------------------------------------------*/ |
|
1324 OWF_API_CALL WFCErrorCode |
|
1325 WFC_Context_GetAttribi(WFC_CONTEXT* context, |
|
1326 WFCContextAttrib attrib, |
|
1327 WFCint* value) |
|
1328 { |
|
1329 WFCint temp = 0; |
|
1330 OWF_ATTRIBUTE_LIST_STATUS err; |
|
1331 WFCErrorCode result = WFC_ERROR_NONE; |
|
1332 |
|
1333 OWF_ASSERT(context); |
|
1334 OWF_ASSERT(value); |
|
1335 |
|
1336 temp = OWF_Attribute_GetValuei(&context->attributes, attrib); |
|
1337 err = OWF_AttributeList_GetError(&context->attributes); |
|
1338 |
|
1339 if (err != ATTR_ERROR_NONE) |
|
1340 { |
|
1341 result = WFC_ERROR_BAD_ATTRIBUTE; |
|
1342 } |
|
1343 else |
|
1344 { |
|
1345 *value = temp; |
|
1346 } |
|
1347 return result; |
|
1348 } |
|
1349 |
|
1350 /*--------------------------------------------------------------------------- |
|
1351 * |
|
1352 *----------------------------------------------------------------------------*/ |
|
1353 OWF_API_CALL WFCErrorCode |
|
1354 WFC_Context_SetAttribi(WFC_CONTEXT* context, |
|
1355 WFCContextAttrib attrib, |
|
1356 WFCint value) |
|
1357 { |
|
1358 WFCErrorCode result = WFC_ERROR_NONE; |
|
1359 |
|
1360 OWF_ASSERT(context); |
|
1361 |
|
1362 /* check value */ |
|
1363 switch (attrib) |
|
1364 { |
|
1365 case WFC_CONTEXT_BG_COLOR: |
|
1366 { |
|
1367 OWFint alpha; |
|
1368 |
|
1369 /* |
|
1370 * Color format is RGBA NOT RGBA. |
|
1371 */ |
|
1372 alpha = value & 0xFF; |
|
1373 |
|
1374 if (WFC_CONTEXT_TYPE_ON_SCREEN == context->type) |
|
1375 { |
|
1376 /* the only allowed value for on-screen context |
|
1377 * background alpha is 255 */ |
|
1378 if (alpha != 255) |
|
1379 { |
|
1380 result = WFC_ERROR_ILLEGAL_ARGUMENT; |
|
1381 } |
|
1382 } |
|
1383 break; |
|
1384 } |
|
1385 |
|
1386 case WFC_CONTEXT_ROTATION: |
|
1387 { |
|
1388 if (!(WFC_ROTATION_0 == value || |
|
1389 WFC_ROTATION_90 == value || |
|
1390 WFC_ROTATION_180 == value || |
|
1391 WFC_ROTATION_270 == value)) |
|
1392 { |
|
1393 result = WFC_ERROR_ILLEGAL_ARGUMENT; |
|
1394 } |
|
1395 break; |
|
1396 } |
|
1397 |
|
1398 case WFC_CONTEXT_TYPE: |
|
1399 case WFC_CONTEXT_TARGET_HEIGHT: |
|
1400 case WFC_CONTEXT_TARGET_WIDTH: |
|
1401 case WFC_CONTEXT_LOWEST_ELEMENT: |
|
1402 { |
|
1403 result = WFC_ERROR_BAD_ATTRIBUTE; |
|
1404 break; |
|
1405 } |
|
1406 |
|
1407 case WFC_CONTEXT_FORCE_32BIT: |
|
1408 default: |
|
1409 { |
|
1410 result = WFC_ERROR_BAD_ATTRIBUTE; |
|
1411 break; |
|
1412 } |
|
1413 } |
|
1414 |
|
1415 if (WFC_ERROR_NONE == result) |
|
1416 { |
|
1417 OWF_ATTRIBUTE_LIST_STATUS error; |
|
1418 |
|
1419 /* try changing the value */ |
|
1420 OWF_Attribute_SetValuei(&context->attributes, attrib, value); |
|
1421 error = OWF_AttributeList_GetError(&context->attributes); |
|
1422 |
|
1423 /* transform errors */ |
|
1424 switch (error) { |
|
1425 case ATTR_ERROR_ACCESS_DENIED: |
|
1426 case ATTR_ERROR_INVALID_ATTRIBUTE: |
|
1427 { |
|
1428 result = WFC_ERROR_BAD_ATTRIBUTE; |
|
1429 break; |
|
1430 } |
|
1431 default: |
|
1432 { |
|
1433 break; |
|
1434 } |
|
1435 } |
|
1436 } |
|
1437 |
|
1438 return result; |
|
1439 } |
|
1440 |
|
1441 /*--------------------------------------------------------------------------- |
|
1442 * |
|
1443 *----------------------------------------------------------------------------*/ |
|
1444 OWF_API_CALL WFCErrorCode |
|
1445 WFC_Context_GetAttribfv(WFC_CONTEXT* context, |
|
1446 WFCContextAttrib attrib, |
|
1447 WFCint count, |
|
1448 WFCfloat* values) |
|
1449 { |
|
1450 WFCErrorCode result = WFC_ERROR_NONE; |
|
1451 |
|
1452 OWF_ASSERT(context); |
|
1453 OWF_ASSERT(values); |
|
1454 |
|
1455 switch (attrib) |
|
1456 { |
|
1457 case WFC_CONTEXT_BG_COLOR: |
|
1458 { |
|
1459 if (4 != count) |
|
1460 { |
|
1461 result = WFC_ERROR_ILLEGAL_ARGUMENT; |
|
1462 } |
|
1463 else |
|
1464 { |
|
1465 OWFuint32 color; |
|
1466 OWF_ATTRIBUTE_LIST_STATUS err; |
|
1467 |
|
1468 color = OWF_Attribute_GetValuei(&context->attributes, attrib); |
|
1469 err = OWF_AttributeList_GetError(&context->attributes); |
|
1470 |
|
1471 if (err != ATTR_ERROR_NONE) |
|
1472 { |
|
1473 result = WFC_ERROR_BAD_ATTRIBUTE; |
|
1474 break; |
|
1475 } |
|
1476 |
|
1477 /* extract color channels and convert to float */ |
|
1478 values[0] = (WFCfloat) (color >> 24) / |
|
1479 (WFCfloat) OWF_BYTE_MAX_VALUE; |
|
1480 values[1] = (WFCfloat) ((color >> 16) & 0xFF) / |
|
1481 (WFCfloat) OWF_BYTE_MAX_VALUE; |
|
1482 values[2] = (WFCfloat) ((color >> 8) & 0xFF) / |
|
1483 (WFCfloat) OWF_BYTE_MAX_VALUE; |
|
1484 values[3] = (WFCfloat) (color & 0xFF) / |
|
1485 (WFCfloat) OWF_BYTE_MAX_VALUE; |
|
1486 } |
|
1487 break; |
|
1488 } |
|
1489 |
|
1490 default: |
|
1491 { |
|
1492 result = WFC_ERROR_BAD_ATTRIBUTE; |
|
1493 break; |
|
1494 } |
|
1495 } |
|
1496 |
|
1497 return result; |
|
1498 } |
|
1499 |
|
1500 /*--------------------------------------------------------------------------- |
|
1501 * |
|
1502 *----------------------------------------------------------------------------*/ |
|
1503 OWF_API_CALL WFCErrorCode |
|
1504 WFC_Context_SetAttribfv(WFC_CONTEXT* context, |
|
1505 WFCContextAttrib attrib, |
|
1506 WFCint count, |
|
1507 const WFCfloat* values) |
|
1508 { |
|
1509 WFCErrorCode result = WFC_ERROR_NONE; |
|
1510 |
|
1511 OWF_ASSERT(context); |
|
1512 OWF_ASSERT(values); |
|
1513 |
|
1514 switch (attrib) |
|
1515 { |
|
1516 case WFC_CONTEXT_BG_COLOR: |
|
1517 { |
|
1518 if (4 != count) |
|
1519 { |
|
1520 result = WFC_ERROR_ILLEGAL_ARGUMENT; |
|
1521 } |
|
1522 else |
|
1523 { |
|
1524 OWFuint32 color; |
|
1525 |
|
1526 /* Every color component value must fall within range [0, 1] */ |
|
1527 if (INRANGE(values[0], 0.0f, 1.0f) && |
|
1528 INRANGE(values[1], 0.0f, 1.0f) && |
|
1529 INRANGE(values[2], 0.0f, 1.0f) && |
|
1530 INRANGE(values[3], 0.0f, 1.0f)) |
|
1531 { |
|
1532 color = (((OWFuint32) floor(values[0] * 255)) << 24) | |
|
1533 (((OWFuint32) floor(values[1] * 255)) << 16) | |
|
1534 (((OWFuint32) floor(values[2] * 255)) << 8) | |
|
1535 ((OWFuint32) floor(values[3] * 255)); |
|
1536 |
|
1537 /* delegate to integer accessor - it'll check the |
|
1538 * the rest of the value and update it eventually */ |
|
1539 result = WFC_Context_SetAttribi(context, attrib, color); |
|
1540 } |
|
1541 else |
|
1542 { |
|
1543 result = WFC_ERROR_ILLEGAL_ARGUMENT; |
|
1544 } |
|
1545 } |
|
1546 break; |
|
1547 } |
|
1548 |
|
1549 default: |
|
1550 { |
|
1551 result = WFC_ERROR_BAD_ATTRIBUTE; |
|
1552 break; |
|
1553 } |
|
1554 } |
|
1555 |
|
1556 return result; |
|
1557 } |
|
1558 |
|
1559 |
|
1560 static void |
|
1561 WFC_Context_AutoComposer(WFC_CONTEXT* context) |
|
1562 { |
|
1563 OWF_Mutex_Lock(&context->updateFlagMutex); |
|
1564 if (context->sourceUpdateCount > 0) |
|
1565 { |
|
1566 DPRINT(("WFC_Context_ComposerThread: %d sources were updated, " |
|
1567 "invoking composition\n", |
|
1568 context->sourceUpdateCount)); |
|
1569 |
|
1570 /* reset update counter */ |
|
1571 |
|
1572 OWF_Mutex_Unlock(&context->updateFlagMutex); |
|
1573 WFC_Context_DoCompose(context); |
|
1574 } |
|
1575 else |
|
1576 { |
|
1577 OWF_Mutex_Unlock(&context->updateFlagMutex); |
|
1578 } |
|
1579 } |
|
1580 |
|
1581 /*--------------------------------------------------------------------------- |
|
1582 * |
|
1583 *----------------------------------------------------------------------------*/ |
|
1584 static void* |
|
1585 WFC_Context_ComposerThread(void* data) |
|
1586 { |
|
1587 WFC_CONTEXT* context = (WFC_CONTEXT*) data; |
|
1588 OWF_MESSAGE msg; |
|
1589 |
|
1590 |
|
1591 OWF_ASSERT(context); |
|
1592 DPRINT(("WFC_Context_ComposerThread starting")); |
|
1593 |
|
1594 memset(&msg, 0, sizeof(OWF_MESSAGE)); |
|
1595 |
|
1596 while (context->device && msg.id != WFC_MESSAGE_QUIT) |
|
1597 { |
|
1598 OWFint err = -1; |
|
1599 |
|
1600 if (WFC_CONTEXT_STATE_ACTIVE == context->activationState) |
|
1601 { |
|
1602 err = OWF_Message_Wait(&context->composerQueue, |
|
1603 &msg, |
|
1604 AUTO_COMPOSE_DELAY); |
|
1605 |
|
1606 WFC_Context_AutoComposer(context); |
|
1607 } |
|
1608 else |
|
1609 { |
|
1610 DPRINT((" ComposerThread waiting for message")); |
|
1611 err = OWF_Message_Wait(&context->composerQueue, &msg, WAIT_FOREVER); |
|
1612 } |
|
1613 |
|
1614 if (0 == err) |
|
1615 { |
|
1616 switch (msg.id) |
|
1617 { |
|
1618 case WFC_MESSAGE_ACTIVATE: |
|
1619 { |
|
1620 DPRINT(("****** ENABLING AUTO-COMPOSITION ******")); |
|
1621 context->activationState = WFC_CONTEXT_STATE_ACTIVE; |
|
1622 break; |
|
1623 } |
|
1624 |
|
1625 case WFC_MESSAGE_DEACTIVATE: |
|
1626 { |
|
1627 /* cancel possible countdown so that update won't occur |
|
1628 * after deactivation */ |
|
1629 DPRINT(("****** DISABLING AUTO-COMPOSITION ******")); |
|
1630 WFC_Device_EnableContentNotifications(context->device, |
|
1631 context, |
|
1632 WFC_FALSE); |
|
1633 context->activationState = WFC_CONTEXT_STATE_PASSIVE; |
|
1634 break; |
|
1635 } |
|
1636 |
|
1637 case WFC_MESSAGE_COMMIT: |
|
1638 { |
|
1639 DPRINT(("****** COMMITTING SCENE CHANGES ******")); |
|
1640 |
|
1641 DPRINT(("COMMIT: Invoking DoCommit")); |
|
1642 WFC_Context_DoCommit(context); |
|
1643 |
|
1644 if (!WFC_Context_Active(context)) |
|
1645 { |
|
1646 DPRINT(("COMMIT: Context is inactive, composition " |
|
1647 "not needed.", context->handle)); |
|
1648 break; |
|
1649 } |
|
1650 else |
|
1651 { |
|
1652 /* context is active; compose immediately after |
|
1653 * commit has completed */ |
|
1654 |
|
1655 DPRINT(("COMMIT: Invoking composition after commit")); |
|
1656 } |
|
1657 /* FLOW THROUGH */ |
|
1658 } |
|
1659 |
|
1660 case WFC_MESSAGE_COMPOSE: |
|
1661 { |
|
1662 DPRINT(("****** COMPOSING SCENE ******")); |
|
1663 |
|
1664 WFC_Context_DoCompose(context); |
|
1665 |
|
1666 break; |
|
1667 } |
|
1668 |
|
1669 case WFC_MESSAGE_FENCE_1_DISPLAY: |
|
1670 { |
|
1671 DPRINT(("****** STORING EGLDISPLAY (%p) ******", msg.data)); |
|
1672 |
|
1673 context->nextSyncObjectDisplay = (WFCEGLDisplay)msg.data; |
|
1674 break; |
|
1675 } |
|
1676 |
|
1677 case WFC_MESSAGE_FENCE_2_SYNCOBJECT: |
|
1678 { |
|
1679 DPRINT(("****** BREAKING FENCE (%p) ******", msg.data)); |
|
1680 OWF_ASSERT(context->eglPrivateSignalSync); |
|
1681 |
|
1682 context->eglPrivateSignalSync(context->nextSyncObjectDisplay, |
|
1683 (WFCEGLSync) msg.data, |
|
1684 EGL_SIGNALED_KHR); |
|
1685 break; |
|
1686 } |
|
1687 } |
|
1688 } |
|
1689 } |
|
1690 |
|
1691 /* Release any use of EGL by this thread. */ |
|
1692 eglReleaseThread(); |
|
1693 |
|
1694 DPRINT(("WFC_Context_ComposerThread terminating")); |
|
1695 OWF_Thread_Exit(NULL); |
|
1696 return NULL; |
|
1697 } |
|
1698 |
|
1699 /*--------------------------------------------------------------------------- |
|
1700 * |
|
1701 *----------------------------------------------------------------------------*/ |
|
1702 |
|
1703 OWF_API_CALL void |
|
1704 WFC_Context_SourceStreamUpdated(OWFNativeStreamType stream, |
|
1705 OWFint event, |
|
1706 void* data, |
|
1707 void* returnParam) |
|
1708 { |
|
1709 (void)returnParam; |
|
1710 OWF_ASSERT(data); |
|
1711 |
|
1712 DPRINT(("WFC_Context_SourceStreamUpdated(%p, %x, %p)", |
|
1713 stream, event, data)); |
|
1714 stream = stream; /* suppress compiler warning */ |
|
1715 |
|
1716 switch (event) |
|
1717 { |
|
1718 case OWF_OBSERVER_RETURN_DEFAULT_EVENT: |
|
1719 if (returnParam) |
|
1720 { |
|
1721 OWF_DEFAULT_EVENT_PARAM* parameter = (OWF_DEFAULT_EVENT_PARAM*) returnParam; |
|
1722 if ((parameter->length) == sizeof(OWF_DEFAULT_EVENT_PARAM)) |
|
1723 { |
|
1724 parameter->event = OWF_STREAM_UPDATED; |
|
1725 } |
|
1726 } |
|
1727 break; |
|
1728 |
|
1729 case OWF_STREAM_UPDATED: |
|
1730 { |
|
1731 WFC_CONTEXT* context = NULL; |
|
1732 context = CONTEXT(data); |
|
1733 OWF_ASSERT(context); |
|
1734 OWF_Mutex_Lock(&context->updateFlagMutex); |
|
1735 |
|
1736 if (WFC_Context_Active(context)) |
|
1737 { |
|
1738 ++context->sourceUpdateCount; |
|
1739 } |
|
1740 OWF_Mutex_Unlock(&context->updateFlagMutex); |
|
1741 } |
|
1742 break; |
|
1743 default: |
|
1744 break; |
|
1745 } |
|
1746 } |
|
1747 |
|
1748 /*--------------------------------------------------------------------------- |
|
1749 * |
|
1750 *----------------------------------------------------------------------------*/ |
|
1751 OWF_API_CALL WFCboolean |
|
1752 WFC_Context_Active(WFC_CONTEXT* context) |
|
1753 { |
|
1754 OWF_ASSERT(context); |
|
1755 |
|
1756 return (WFC_CONTEXT_STATE_ACTIVE == context->activationState || |
|
1757 WFC_CONTEXT_STATE_ACTIVATING == context->activationState) ? WFC_TRUE : WFC_FALSE; |
|
1758 } |
|
1759 |
|
1760 #ifdef __cplusplus |
|
1761 } |
|
1762 #endif |
|
1763 |