os/graphics/graphicscomposition/openwfcompositionengine/composition/src/wfccontext.c
Update contrib.
1 /* Copyright (c) 2009 The Khronos Group Inc.
2 * Portions copyright (c) 2009-2010 Nokia Corporation and/or its subsidiary(-ies)
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and/or associated documentation files (the
6 * "Materials"), to deal in the Materials without restriction, including
7 * without limitation the rights to use, copy, modify, merge, publish,
8 * distribute, sublicense, and/or sell copies of the Materials, and to
9 * permit persons to whom the Materials are furnished to do so, subject to
10 * the following conditions:
12 * The above copyright notice and this permission notice shall be included
13 * in all copies or substantial portions of the Materials.
15 * THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
18 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
19 * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
20 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
21 * MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
27 * \brief SI Context handling
39 #include "wfccontext.h"
40 #include "wfcpipeline.h"
42 #include "owfscreen.h"
43 #include "owfdisplaycontextgeneral.h"
44 #include "owfnotifications.h"
47 /*! maximum number of elements per scene */
48 #define MAX_ELEMENTS 512
49 /*! maximum number of scenes per context */
53 #define CONTEXT_SCENE_POOL_SIZE MAX_SCENES
54 #define CONTEXT_ELEMENT_POOL_SIZE MAX_SCENES * MAX_ELEMENTS
55 #define CONTEXT_NODE_POOL_SIZE 2 * CONTEXT_ELEMENT_POOL_SIZE
58 #define MAX_DELAY 2100000000
61 #define AUTO_COMPOSE_DELAY 15000
62 #define FIRST_CONTEXT_HANDLE 2000
68 static WFCHandle nextContextHandle = FIRST_CONTEXT_HANDLE;
76 WFC_MESSAGE_FENCE_1_DISPLAY,
77 WFC_MESSAGE_FENCE_2_SYNCOBJECT,
79 WFC_MESSAGE_DEACTIVATE,
80 WFC_MESSAGE_START_COUNTDOWN,
85 WFC_Context_ComposerThread(void* data);
88 /*---------------------------------------------------------------------------
90 *----------------------------------------------------------------------------*/
91 void WFC_CONTEXT_Ctor(void* self)
96 /*---------------------------------------------------------------------------*/
98 WFC_Context_CreateState(WFC_CONTEXT* context)
99 { /* Must be called late enough that scratch buffers can be mapped and hardware rotation capability queried */
100 OWF_IMAGE_FORMAT fInt,
105 DPRINT(("WFC_Context_CreateContextState"));
107 owfNativeStreamGetHeader(context->stream,
108 NULL, NULL, &stride, &fExt, NULL);
109 /* internal image used as intermediate target */
110 fInt.pixelFormat = OWF_IMAGE_ARGB_INTERNAL;
111 fInt.linear = fExt.linear;
112 fInt.premultiplied = fExt.premultiplied;
115 if (context->type == WFC_CONTEXT_TYPE_ON_SCREEN)
117 /* The unrotated target buffer: Can't get real address without locking for writing! NO STRIDE */
118 context->state.unrotatedTargetImage=OWF_Image_Create(context->targetWidth,context->targetHeight,&fExt,context->scratchBuffer[2],0);
119 /* The rotated version of the target buffer for hardware rotation
120 * or a de-rotated version of the internal buffer into another scratch buffer for software rotation
122 if (OWF_Screen_Rotation_Supported(context->displayContext))
123 { /* The rotated version of the target buffer for hardware rotation */
124 context->state.rotatedTargetImage=OWF_Image_Create(context->targetHeight,context->targetWidth,&fExt,context->scratchBuffer[2],0);
127 { /* a de-rotated version of the internal buffer into another scratch buffer for software rotation */
128 context->state.rotatedTargetImage=OWF_Image_Create(context->targetWidth,context->targetHeight,&fInt,context->scratchBuffer[1],0);
133 /* The unrotated target buffer: Can't get real address without locking for writing! STRIDE HONOURED */
134 context->state.unrotatedTargetImage=OWF_Image_Create(context->targetWidth,context->targetHeight,&fExt,context->scratchBuffer[2],stride);
135 /* a de-rotated version of the internal buffer into another scratch buffer for software rotation */
136 context->state.rotatedTargetImage=OWF_Image_Create(context->targetWidth,context->targetHeight,&fInt,context->scratchBuffer[1],0);
138 /* The internal target buffer composed to for 0 and 180 degree rotation */
139 context->state.unrotatedInternalTargetImage=OWF_Image_Create(context->targetWidth,context->targetHeight,&fInt,context->scratchBuffer[0],stride);
140 /* The internal target buffer composed to for 90 and 270 degree rotation */
141 context->state.rotatedInternalTargetImage=OWF_Image_Create(context->targetHeight,context->targetWidth,&fInt,context->scratchBuffer[0],stride);
143 if (context->state.unrotatedTargetImage && context->state.rotatedTargetImage && context->state.unrotatedInternalTargetImage && context->state.rotatedInternalTargetImage)
152 /*---------------------------------------------------------------------------*/
154 WFC_Context_DestroyState(WFC_CONTEXT* context)
156 /* The unrotated target buffer */
157 OWF_Image_Destroy(context->state.unrotatedTargetImage);
158 /* The rotated version of the target buffer for hardware rotation,
159 * or a de-rotated version of the internal buffer into another scratch buffer for software rotation
161 OWF_Image_Destroy(context->state.rotatedTargetImage);
162 /* The internal target buffer composed to for 0 and 180 degree rotation */
163 OWF_Image_Destroy(context->state.unrotatedInternalTargetImage);
164 /* The internal target buffer composed to for 90 and 270 degree rotation */
165 OWF_Image_Destroy(context->state.rotatedInternalTargetImage);
168 /*---------------------------------------------------------------------------
169 * Should only be accessed indirectly by calls to WFC_Device_DestroyContext or
170 * WFC_Device_DestroyContexts
171 *----------------------------------------------------------------------------*/
172 void WFC_CONTEXT_Dtor(void* self)
175 WFC_CONTEXT* context = NULL;
178 DPRINT(("WFC_CONTEXT_Dtor(%p)", self));
180 context = CONTEXT(self);
184 WFC_Pipeline_DestroyState(context);
185 WFC_Context_DestroyState(context);
187 OWF_MessageQueue_Destroy(&context->composerQueue);
189 /* make the stream destroyable */
190 if (context->stream != OWF_INVALID_HANDLE)
192 owfNativeStreamSetProtectionFlag(context->stream, OWF_FALSE);
193 owfNativeStreamDestroy(context->stream);
195 context->stream = OWF_INVALID_HANDLE;
197 OWF_AttributeList_Destroy(&context->attributes);
199 for (ii = 0; ii < SCRATCH_BUFFER_COUNT; ii++)
201 OWF_Image_FreeData(context->displayContext, &context->scratchBuffer[ii]);
202 context->scratchBuffer[ii] = 0;
205 OWF_DisplayContext_Destroy(context->screenNumber, context->displayContext);
206 context->displayContext = NULL;
208 OWF_Pool_Destroy(context->scenePool);
209 OWF_Pool_Destroy(context->elementPool);
210 OWF_Pool_Destroy(context->nodePool);
212 OWF_Semaphore_Destroy(&context->compositionSemaphore);
213 OWF_Semaphore_Destroy(&context->commitSemaphore);
214 OWF_Mutex_Destroy(&context->updateFlagMutex);
215 OWF_Mutex_Destroy(&context->sceneMutex);
218 /*---------------------------------------------------------------------------
220 *----------------------------------------------------------------------------*/
222 WFC_Context_Shutdown(WFC_CONTEXT* context)
225 DPRINT(("WFC_Context_Shutdown(context = %d)", context->handle));
227 DPRINT(("Waiting for composer thread termination"));
228 if (context->composerThread)
230 OWF_Message_Send(&context->composerQueue, WFC_MESSAGE_QUIT, 0);
231 OWF_Thread_Join(context->composerThread, NULL);
232 OWF_Thread_Destroy(context->composerThread);
235 context->composerThread = NULL;
239 /* #4604: added guard condition */
240 WFC_Device_DestroyContextElements(context->device, context);
241 WFC_Device_DestroyContextImageProviders(context->device, context);
244 WFC_Scene_Destroy(context->workScene);
245 WFC_Scene_Destroy(context->snapshotScene);
246 WFC_Scene_Destroy(context->committedScene);
247 context->workScene = NULL;
248 context->snapshotScene = NULL;
249 context->committedScene = NULL;
252 /*---------------------------------------------------------------------------
253 * Initialize context attributes
254 *----------------------------------------------------------------------------*/
255 OWF_API_CALL OWF_ATTRIBUTE_LIST_STATUS
256 WFC_Context_InitializeAttributes(WFC_CONTEXT* context,
259 OWF_ATTRIBUTE_LIST_STATUS attribError=ATTR_ERROR_NONE;
261 /* initialize attributes/properties */
264 owfNativeStreamGetHeader(context->stream,
265 &context->targetWidth,
266 &context->targetHeight,
269 context->type = type;
270 context->rotation = WFC_ROTATION_0;
271 context->backgroundColor = 0x000000FF;
272 context->lowestElement = WFC_INVALID_HANDLE;
275 OWF_AttributeList_Create(&context->attributes,
277 WFC_CONTEXT_BG_COLOR);
278 attribError=OWF_AttributeList_GetError(&context->attributes);
279 if (attribError!=ATTR_ERROR_NONE)
281 OWF_ASSERT(attribError==ATTR_ERROR_NO_MEMORY);
286 /* The composition code reads the member variables directly,
287 * not via the attribute engine.
289 OWF_Attribute_Initi(&context->attributes,
291 (WFCint*) &context->type,
294 OWF_Attribute_Initi(&context->attributes,
295 WFC_CONTEXT_TARGET_WIDTH,
296 &context->targetWidth,
299 OWF_Attribute_Initi(&context->attributes,
300 WFC_CONTEXT_TARGET_HEIGHT,
301 &context->targetHeight,
304 OWF_Attribute_Initi(&context->attributes,
305 WFC_CONTEXT_ROTATION,
306 (WFCint*) &context->rotation,
309 OWF_Attribute_Initi(&context->attributes,
310 WFC_CONTEXT_BG_COLOR,
311 (WFCint*) &context->backgroundColor,
314 OWF_Attribute_Initi(&context->attributes,
315 WFC_CONTEXT_LOWEST_ELEMENT,
316 (OWFint*) &context->lowestElement,
318 attribError=OWF_AttributeList_GetError(&context->attributes);
320 /* After commit to working, writable attribute abstracted variables
321 must not be written to directly. */
322 OWF_AttributeList_Commit(&context->attributes,
324 WFC_CONTEXT_BG_COLOR,
325 WORKING_ATTR_VALUE_INDEX );
331 /*---------------------------------------------------------------------------
333 *----------------------------------------------------------------------------*/
335 WFC_Context_Initialize(WFC_CONTEXT* context,
337 WFCNativeStreamType stream,
341 void* scratch[SCRATCH_BUFFER_COUNT];
346 OWF_ATTRIBUTE_LIST_STATUS attribStatus = ATTR_ERROR_NONE;
350 DPRINT(("WFC_Context_Initialize(%p,%p,%d,%d)", context, device, type, screenNum));
352 context->type = type;
353 context->device = device;
354 context->handle = nextContextHandle;
355 context->screenNumber = screenNum;
356 context->activationState = WFC_CONTEXT_STATE_PASSIVE;
357 context->sourceUpdateCount = 0;
358 context->clientElementCount = 0;
361 context->displayContext = OWF_DisplayContext_Create(screenNum);
362 if (context->displayContext == NULL)
364 DPRINT(("WFC_Context_Initialize(): Could not create display Context"));
368 context->eglPrivateSignalSync = (TFPtrEglPrivateSignalSyncNok) eglGetProcAddress("egl_Private_SignalSyncNOK");
369 if (! context->eglPrivateSignalSync)
371 DPRINT(("WFC_Context_Initialize(): Missing EGL extension - egl_Private_SignalSyncNOK extension"));
375 err2 =OWF_MessageQueue_Init(&context->composerQueue);
378 DPRINT(("WFC_Context_Initialize(): Cannot initialise the message queue err(%d)", err2));
382 context->composerThread = OWF_Thread_Create(WFC_Context_ComposerThread, context);
383 if (!(context->composerThread))
385 /* must call these to remove references to context */
386 DPRINT(("WFC_Context_Initialize(): Failed to create thread!"));
390 OWF_ComposerThread_RendezvousWait(context->displayContext);
392 /*the following section of the code could be pushed to adaptation in future*/
393 if (type == WFC_CONTEXT_TYPE_ON_SCREEN)
395 OWF_IMAGE_FORMAT imageFormat;
399 WFCint normalSize = 0;
400 WFCint flippedSize = 0;
401 WFCNativeStreamType stream;
403 /* Set up stream for sending data to screen */
405 if (!OWF_Screen_GetHeader(context->displayContext, &screen))
407 DPRINT(("WFC_Context_Initialize(): Could not retrieve the screen parameters"));
408 WFC_Context_Shutdown(context);
412 /* Set on-screen pixel format */
413 imageFormat.pixelFormat = OWF_SURFACE_PIXEL_FORMAT;
414 imageFormat.premultiplied = OWF_SURFACE_PREMULTIPLIED;
415 imageFormat.linear = OWF_SURFACE_LINEAR;
416 imageFormat.rowPadding = OWF_SURFACE_ROWPADDING;
418 width = screen.normal.width;
419 height = screen.normal.height;
421 normalSize = screen.normal.height * screen.normal.stride;
422 flippedSize = screen.flipped.height * screen.flipped.stride;
424 if (flippedSize > normalSize)
426 width = screen.flipped.width;
427 height = screen.flipped.height;
430 stream = owfNativeStreamCreateImageStream(width,
437 WFC_Context_SetTargetStream(context, stream);
439 /* At this point the stream's refcount is 2 - we must decrement
440 * it by one to ensure that the stream is destroyed when the
441 * context (that "owns" it) is destroyed.
443 owfNativeStreamRemoveReference(stream);
447 DPRINT(("WFC_Context_Initialize(): cannot create internal target stream"));
448 WFC_Context_Shutdown(context);
454 WFC_Context_SetTargetStream(context, stream);
457 nbufs = SCRATCH_BUFFER_COUNT-1;
458 for (ii = 0; ii < nbufs; ii++)
460 scratch[ii] = OWF_Image_AllocData(context->displayContext, MAX_SOURCE_WIDTH,
462 OWF_IMAGE_ARGB_INTERNAL);
463 fail = fail || (scratch[ii] == NULL);
467 * allocate one-channel buffer for alpha
468 * obs! this assumes sizeof(OWFsubpixel) is 4.
470 scratch[nbufs] = OWF_Image_AllocData(context->displayContext, MAX_SOURCE_WIDTH,
473 fail = fail || (scratch[nbufs] == NULL);
477 for (ii = 0; ii < SCRATCH_BUFFER_COUNT; ii++)
479 OWF_Image_FreeData(context->displayContext, &scratch[ii]);
481 WFC_Context_Shutdown(context);
485 for (ii = 0; ii < SCRATCH_BUFFER_COUNT; ii++)
487 context->scratchBuffer[ii] = scratch[ii];
490 if ( OWF_Semaphore_Init(&context->compositionSemaphore, 1)
491 || OWF_Semaphore_Init(&context->commitSemaphore, 1)
492 || OWF_Mutex_Init(&context->updateFlagMutex)
493 || OWF_Mutex_Init(&context->sceneMutex)
497 DPRINT(("WFC_Context_Initialize(): Could not create mutexes and semaphores!"));
498 WFC_Context_Shutdown(context);
502 if (!WFC_Pipeline_CreateState(context) || !WFC_Context_CreateState(context))
504 DPRINT(("WFC_Context_Initialize(): Could not create pipeline state object"));
505 WFC_Context_Shutdown(context);
510 attribStatus= WFC_Context_InitializeAttributes(context, type);
512 if (attribStatus!=ATTR_ERROR_NONE)
514 WFC_Context_Shutdown(context);
519 context->scenePool = OWF_Pool_Create(sizeof(WFC_SCENE),
520 CONTEXT_SCENE_POOL_SIZE);
521 context->elementPool = OWF_Pool_Create(sizeof(WFC_ELEMENT),
522 CONTEXT_ELEMENT_POOL_SIZE);
523 context->nodePool = OWF_Pool_Create(sizeof(OWF_NODE),
524 CONTEXT_NODE_POOL_SIZE);
525 if (!( context->scenePool &&
526 context->nodePool && context->elementPool))
528 WFC_Context_Shutdown(context);
532 DPRINT((" Creating scenes"));
533 context->workScene = WFC_Scene_Create(context);
534 context->committedScene = WFC_Scene_Create(context);
535 context->snapshotScene = NULL;
537 /* snapshotScene is initialized in InvokeCommit */
539 /* context's refcount is now 3 */
541 if (!(context->workScene && context->committedScene &&
542 context->nodePool && context->elementPool))
544 WFC_Context_Shutdown(context);
551 /*---------------------------------------------------------------------------
552 * Create new context on device
554 * \param device Device on which the context should be created
555 * \param type Context type (on- or off-screen)
557 * \return New context object or NULL in case of failure
558 *----------------------------------------------------------------------------*/
559 OWF_API_CALL WFC_CONTEXT*
560 WFC_Context_Create(WFC_DEVICE* device,
561 WFCNativeStreamType stream,
565 WFC_CONTEXT* context = NULL;
568 context = CREATE(WFC_CONTEXT);
572 if (!WFC_Context_Initialize(context, device, stream, type, screenNum))
580 /*---------------------------------------------------------------------------
581 * Setup context rendering target
583 * \param context Context
584 * \param stream Target stream to use for rendering
585 *----------------------------------------------------------------------------*/
587 WFC_Context_SetTargetStream(WFC_CONTEXT* context,
588 OWFNativeStreamType stream)
591 context->stream = stream;
593 owfNativeStreamAddReference(stream);
595 owfNativeStreamGetHeader(stream,
596 &context->targetWidth, &context->targetHeight,
601 WFC_FastpathCheckTransparency(WFCbitfield transparencyTypes, WFCfloat globalAlpha, OWF_PIXEL_FORMAT sourceFormat)
603 if ((transparencyTypes & WFC_TRANSPARENCY_ELEMENT_GLOBAL_ALPHA) && (globalAlpha != 255.0f))
605 DPRINT(("=== WFC_FastpathCheckTransparency - Failed global alfa(%f) check", globalAlpha));
609 if ((transparencyTypes & WFC_TRANSPARENCY_SOURCE) && (sourceFormat != OWF_IMAGE_XRGB8888))
611 DPRINT(("=== WFC_FastpathCheckTransparency - Failed transparency check types=0x%x format=0x%x",
612 transparencyTypes, sourceFormat));
621 WFC_FastpathCheckGeometry(WFC_CONTEXT* context, WFC_ELEMENT* element)
623 OWFint sourceWidth = 0;
624 OWFint sourceHeight = 0;
625 OWFint destWidth = 0;
626 OWFint destHeight = 0;
627 OWFint targetWidth = 0;
628 OWFint targetHeight = 0;
633 if ((element->srcRect[0] != 0) || (element->srcRect[1] != 0))
635 DPRINT(("=== WFC_FastpathCheckGeometry(context = %p) - FAILED Source Position Check", context));
639 if ((element->dstRect[0] != 0) || (element->dstRect[1] != 0))
641 DPRINT(("=== WFC_FastpathCheckGeometry(context = %p) - FAILED Destination Position Check", context));
645 if(element->sourceFlip)
647 DPRINT(("=== WFC_FastpathCheckGeometry(context = %p) - FAILED Source Flip Check", context));
651 if(element->sourceRotation == WFC_ROTATION_0)
653 sourceWidth = element->srcRect[2];
654 sourceHeight = element->srcRect[3];
658 DPRINT(("=== WFC_FastpathCheckGeometry(context = %p) - FAILED Source Rotation (0x%x) Check",
659 context, element->sourceRotation));
663 destWidth = element->dstRect[2];
664 destHeight = element->dstRect[3];
666 if ((sourceWidth != destWidth) || (sourceHeight != destHeight))
668 DPRINT(("=== WFC_FastpathCheckGeometry(context = %p) - FAILED Non-scaling Check", context));
672 if (context->rotation == WFC_ROTATION_0 || OWF_Screen_Rotation_Supported(context->displayContext))
674 if (context->rotation == WFC_ROTATION_0 || context->rotation == WFC_ROTATION_180)
676 targetWidth = context->targetWidth;
677 targetHeight = context->targetHeight;
681 targetWidth = context->targetHeight;
682 targetHeight = context->targetWidth;
685 if (destWidth == targetWidth && destHeight == targetHeight)
691 DPRINT(("=== WFC_FastpathCheckGeometry(context = %p) - Failed Dimensions Check", context));
696 DPRINT(("=== WFC_FastpathCheckGeometry(context = %p) - Failed Supported Rotations Check", context));
703 * Check if the current scene is candidate for fastpath optimisation.
704 * Fastpath optimisation means the topmost visible layer will be passed direct to the
705 * lower level for presentation on the display without being composed.
706 * There are two questions:
707 * - Is the scene itself suitable for fastpathing?
708 * - Can the surface selected for fastpathing be presented directly by the display?
709 * This function will check the scene (eg reject if the top stream is non-opaque or smaller than the screen)
711 * @param context context object containing the scene to be checked.
715 * The first time MOpenWFC_RI_Display_Update::SetTopLayerSurface (or SetLayerSurface) is called
716 * with a different stream handle, it can fail indicating the display cannot accept the stream.
717 * The compositor will then have to immediately compose that frame as normal, and should continue
718 * to perform normal composition until the scene changes to present a different stream as fastpath candidate.
720 * There is a middle ground, e.g. can the hardware handle over-sized images, or do scaling or do rotation?
721 * SetTopLayerSurface accepts an optional list of imperfect attributes to be checked by the adaptation.
722 * By WFC_Context_CheckFastpath only listing the attributes that are considered imperfect,
723 * and SetLayerSurface rejecting fastpath for any attribute IDs that it doesn't recognise,
724 * safe independent extensibility is assured.
727 WFC_Context_CheckFastpath(WFC_CONTEXT* context)
729 WFC_ELEMENT* element = NULL;
732 DPRINT(("WFC_Context_CheckFastpath(context = %p) - Check Fastpath", context));
733 if ((context->type != WFC_CONTEXT_TYPE_ON_SCREEN) ||
734 OWF_DisplayContext_FastpathChecked(context->displayContext))
739 // Simple case-fast path top most layer
740 // More complex case, fast-path top most VISIBLE, OPAQUE layer.
741 OWF_DisplayContext_DisableFastpath(context->displayContext);
742 OWF_DisplayContext_SetFastpathChecked(context->displayContext);
744 element = WFC_Scene_TopMostElement(context->committedScene);
745 if (element && element->source && element->skipCompose == WFC_FALSE)
750 DPRINT(("=== WFC_Context_CheckFastpath(context = %p) - FAILED elemenent includes mask", context));
754 OWF_ASSERT(element->source->lockedStream.image);
756 OWF_ASSERT(element->source->streamHandle != OWF_INVALID_HANDLE);
758 if (!WFC_FastpathCheckGeometry(context, element))
763 if (!WFC_FastpathCheckTransparency(element->transparencyTypes,
764 element->globalAlpha,
765 element->source->lockedStream.image->format.pixelFormat))
770 OWF_DisplayContext_EnableFastpath(context->displayContext, element->source->streamHandle);
771 DPRINT(("=== WFC_Context_CheckFastpath(context = %p) - Fastpath Enabled", context));
775 /*---------------------------------------------------------------------------
776 * Checks if the given stream would be valid as an off-screen context target.
778 * Checks that the format can be rendered TO.
779 * Also checks that the image size is acceptable (within the scratch buffers).
780 * This is called before the context is created so is effectively a "static" context method.
782 * \param stream Target stream to use for rendering
783 ---------------------------------------------------------------------------*/
785 OWF_API_CALL WFCboolean
786 WFC_Context_IsValidTargetStream(OWFNativeStreamType stream)
789 OWF_IMAGE_FORMAT format;
790 owfNativeStreamGetHeader(stream,
792 NULL, &format, NULL);
793 if (width>MAX_SOURCE_WIDTH)
797 if (height>MAX_SOURCE_HEIGHT)
801 return (WFCboolean)OWF_Image_IsValidDestinationFormat(&format);
804 /*---------------------------------------------------------------------------
805 * Checks that the image size is acceptable (within the scratch buffers).
806 * This is called before the source is created.
808 * \param stream source stream to use for rendering.
809 ---------------------------------------------------------------------------*/
811 OWF_API_CALL WFCboolean
812 WFC_Context_IsValidSourceStream(OWFNativeStreamType stream)
815 owfNativeStreamGetHeader(stream,
818 if ((width+2) * (height+2) > MAX_SOURCE_WIDTH * MAX_SOURCE_HEIGHT)
825 /*---------------------------------------------------------------------------
826 * Find element from current scene
828 * \param context Context object
829 * \param element Element to find
831 * \return Element object or NULL if element hasn't been inserted
832 * into current scene.
833 *----------------------------------------------------------------------------*/
834 OWF_API_CALL WFC_ELEMENT*
835 WFC_Context_FindElement(WFC_CONTEXT* context,
839 return WFC_Scene_FindElement(context->workScene, element);
842 /*---------------------------------------------------------------------------
843 * Commit context scene graph changes
845 * \param context Context to commit
846 *----------------------------------------------------------------------------*/
848 WFC_Context_DoCommit(WFC_CONTEXT* context)
851 DPRINT(("WFC_Context_DoCommit(context = %p)", context));
853 OWF_ASSERT(context->snapshotScene);
856 DPRINT(("COMMIT: Committing attribute list changes"));
858 DPRINT(("COMMIT: Acquiring mutex"));
859 OWF_Mutex_Lock(&context->sceneMutex);
861 /* comitting scene attribute changes */
862 DPRINT(("COMMIT: Committing scene attribute changes"));
863 OWF_AttributeList_Commit(&context->attributes,
865 WFC_CONTEXT_BG_COLOR,COMMITTED_ATTR_VALUE_INDEX);
868 /* resolve sources and masks */
869 DPRINT(("COMMIT: Committing scene changes"));
870 WFC_Scene_Commit(context->snapshotScene);
871 DPRINT(("COMMIT: Destroying old committed scene"));
872 WFC_Scene_Destroy(context->committedScene);
873 DPRINT(("COMMIT: Setting new snapshot scene as committed one."));
874 context->committedScene = context->snapshotScene;
875 context->snapshotScene = NULL;
877 // reset the visibility flags
878 owfSymDeviceResetVisibilityState(context);
880 DPRINT(("COMMIT: Unlocking mutex"));
881 OWF_Mutex_Unlock(&context->sceneMutex);
883 DPRINT(("COMMIT: Signaling commit semaphore"));
884 /* signal we're ready */
885 OWF_Semaphore_Post(&context->commitSemaphore);
888 /*---------------------------------------------------------------------------
890 *----------------------------------------------------------------------------*/
892 WFC_Context_LockTargetForWriting(WFC_CONTEXT* context)
896 DPRINT(("WFC_Context_LockTargetForWriting"));
898 context->state.targetBuffer =
899 owfNativeStreamAcquireWriteBuffer(context->stream);
901 if (!context->state.targetBuffer)
903 DPRINT(("Failed to WFC_Context_LockTargetForWriting owfNativeStreamAcquireWriteBuffer"));
906 context->state.targetPixels =
907 owfNativeStreamGetBufferPtr(context->stream,
908 context->state.targetBuffer);
910 if ((WFC_ROTATION_0 == context->rotation || WFC_ROTATION_180 == context->rotation) ||
911 !OWF_Screen_Rotation_Supported(context->displayContext))
913 /* final target, in target format */
914 context->state.targetImage =context->state.unrotatedTargetImage;
918 /* final target, in target format */
919 /* fExt stride/padding value is the rotated value */
920 context->state.targetImage = context->state.rotatedTargetImage;
922 OWF_Image_SetPixelBuffer(context->state.targetImage,context->state.targetPixels);
924 if (context->state.targetImage==NULL)
926 OWF_ASSERT(WFC_FALSE);
929 /* take context rotation into account. */
930 if (WFC_ROTATION_0 == context->rotation ||
931 WFC_ROTATION_180 == context->rotation)
933 context->state.internalTargetImage = context->state.unrotatedInternalTargetImage;
937 context->state.internalTargetImage = context->state.rotatedInternalTargetImage;
940 if (context->state.internalTargetImage==NULL)
942 OWF_ASSERT(WFC_FALSE);
947 /*---------------------------------------------------------------------------
949 *----------------------------------------------------------------------------*/
951 WFC_Context_UnlockTarget(WFC_CONTEXT* context,OWFboolean aDoPost)
953 OWF_ROTATION rotation = OWF_ROTATION_0;
956 DPRINT(("WFC_Context_UnlockTarget"));
957 DPRINT((" Unlocking target stream=%d, buffer=%d",
958 context->stream, context->state.targetBuffer));
960 owfNativeStreamReleaseWriteBuffer(context->stream,
961 context->state.targetBuffer,
968 switch (context->rotation)
972 rotation = OWF_ROTATION_0;
975 case WFC_ROTATION_90:
977 rotation = OWF_ROTATION_90;
980 case WFC_ROTATION_180:
982 rotation = OWF_ROTATION_180;
985 case WFC_ROTATION_270:
987 rotation = OWF_ROTATION_270;
996 if (!OWF_Screen_Post_Topmost_Layer(context->displayContext, context->stream, rotation))
997 { //getting a fail here is bad... display did not accept the composition buffer.
998 DPRINT(("WFC_Context_UnlockTarget - OWF_Screen_Post_Topmost_Layer failed for composition stream"));
1004 /*---------------------------------------------------------------------------
1006 *----------------------------------------------------------------------------*/
1008 WFC_Context_PrepareComposition(WFC_CONTEXT* context)
1010 OWFsubpixel r, g, b, a;
1012 OWF_ASSERT(context);
1014 /* the first thing to do is to lock target stream and fetch
1015 write buffer to it. fetching blocks until one is available,
1016 but since only one stream can be target to only one context
1017 at the time, no stalls should occur */
1018 WFC_Context_LockTargetForWriting(context);
1020 /* prepare for composition by "clearing the table" with
1021 background color. */
1023 r = (OWFsubpixel) OWF_RED_MAX_VALUE * ((context->backgroundColor >> 24) &
1024 0xFF) / OWF_BYTE_MAX_VALUE;
1025 g = (OWFsubpixel) OWF_GREEN_MAX_VALUE * ((context->backgroundColor >> 16) &
1026 0xFF) / OWF_BYTE_MAX_VALUE;
1027 b = (OWFsubpixel) OWF_BLUE_MAX_VALUE * ((context->backgroundColor >> 8) &
1028 0xFF) / OWF_BYTE_MAX_VALUE;
1029 a = (OWFsubpixel) OWF_ALPHA_MAX_VALUE * (context->backgroundColor & 0xFF) /
1032 r = r * a / OWF_ALPHA_MAX_VALUE;
1033 g = g * a / OWF_ALPHA_MAX_VALUE;
1034 b = b * a / OWF_ALPHA_MAX_VALUE;
1036 OWF_Image_Clear(context->state.internalTargetImage, r, g, b, a);
1041 /*---------------------------------------------------------------------------
1043 *----------------------------------------------------------------------------*/
1045 WFC_Context_FinishComposition(WFC_CONTEXT* context)
1047 OWF_ROTATION rotation = OWF_ROTATION_0;
1048 OWFboolean screenRotation;
1050 OWF_ASSERT(context);
1052 screenRotation = OWF_Screen_Rotation_Supported(context->displayContext);
1053 /* re-use scratch buffer 1 for context rotation */
1054 if (WFC_ROTATION_0 == context->rotation || screenRotation)
1059 if (WFC_ROTATION_90 == context->rotation || WFC_ROTATION_270 == context->rotation)
1061 owfSetStreamFlipState(context->stream, OWF_TRUE);
1065 owfSetStreamFlipState(context->stream, OWF_FALSE);
1068 OWF_Image_DestinationFormatConversion(context->state.targetImage, context->state.internalTargetImage);
1072 switch (context->rotation)
1074 case WFC_ROTATION_0:
1076 rotation = OWF_ROTATION_0;
1079 case WFC_ROTATION_90:
1081 rotation = OWF_ROTATION_90;
1084 case WFC_ROTATION_180:
1086 rotation = OWF_ROTATION_180;
1089 case WFC_ROTATION_270:
1091 rotation = OWF_ROTATION_270;
1101 OWF_Image_Rotate(context->state.rotatedTargetImage,
1102 context->state.internalTargetImage,
1105 /* Note: support of different target formats can be put here */
1107 OWF_Image_DestinationFormatConversion(context->state.targetImage, context->state.rotatedTargetImage);
1109 WFC_Context_UnlockTarget(context,(context->type==WFC_CONTEXT_TYPE_ON_SCREEN)?OWF_TRUE:OWF_FALSE);
1112 /*!---------------------------------------------------------------------------
1113 * \brief Actual composition routine.
1114 * Mainly just calls other functions that executes different stages of
1115 * the composition pipeline.
1116 * \param context Context to compose.
1117 *----------------------------------------------------------------------------*/
1119 WFC_Context_DoCompose(WFC_CONTEXT* context)
1121 WFC_SCENE* scene = NULL;
1122 OWF_NODE* node = NULL;
1124 OWF_ASSERT(context);
1126 OWF_Mutex_Lock(&context->updateFlagMutex);
1128 OWF_DisplayContext_IncrementSerialNumber(context->displayContext);
1130 OWF_DisplayContext_SetCompositionOngoing(context->displayContext, WFC_TRUE);
1131 context->sourceUpdateCount = 0;
1132 OWF_Mutex_Unlock(&context->updateFlagMutex);
1134 DPRINT(("WFC_Context_Compose"));
1135 /* Composition always uses the committed version
1139 WFC_Scene_LockSourcesAndMasks(context->committedScene);
1141 OWF_Mutex_Lock(&context->sceneMutex);
1143 WFC_Context_CheckFastpath(context);
1144 if (OWF_DisplayContext_FastpathEnabled(context->displayContext))
1146 WFCboolean targetStreamAccessed;
1147 OWFboolean screenRotation;
1148 screenRotation = OWF_Screen_Rotation_Supported(context->displayContext);
1149 if (WFC_Context_Active(context))
1150 { //Full fastpath is only supported for autonomous composition
1151 OWFNativeStreamType stream = OWF_INVALID_HANDLE;
1152 OWF_ROTATION rotation = OWF_ROTATION_0;
1154 DPRINT(("== WFC_Context_DoCompose(context = %p) - Fastpathing", context));
1156 stream = OWF_DisplayContext_FastpathStream(context->displayContext);
1159 switch (context->rotation)
1161 case WFC_ROTATION_0:
1163 rotation = OWF_ROTATION_0;
1166 case WFC_ROTATION_90:
1168 rotation = OWF_ROTATION_90;
1171 case WFC_ROTATION_180:
1173 rotation = OWF_ROTATION_180;
1176 case WFC_ROTATION_270:
1178 rotation = OWF_ROTATION_270;
1184 rotation = OWF_ROTATION_0;
1189 if (!OWF_Screen_Post_Topmost_Layer(context->displayContext, stream, rotation))
1192 DPRINT(("WFC_Context_Compose calls OWF_DisplayContext_DisableFastpath because !OWF_Screen_Post_Topmost_Layer()"));
1193 OWF_DisplayContext_DisableFastpath(context->displayContext);
1194 //If fastpath is disabled here then we need to compose properly this cycle
1197 targetStreamAccessed = OWF_DisplayContext_InternalStreamAccessed(context->displayContext);
1198 if (OWF_DisplayContext_FastpathEnabled(context->displayContext) && ( targetStreamAccessed || !WFC_Context_Active(context) ))
1199 { //Fastpath in non-autonomous composition just does a simple copy and post.
1200 DPRINT(("== WFC_Context_DoCompose(context = %p) - fastpath copy target", context));
1201 if (WFC_Context_LockTargetForWriting(context))
1206 if (WFC_ROTATION_90 == context->rotation || WFC_ROTATION_270 == context->rotation)
1208 owfSetStreamFlipState(context->stream, OWF_TRUE);
1212 owfSetStreamFlipState(context->stream, OWF_FALSE);
1215 copy=OWF_DisplayContext_CopyFastpathedStreamToTargetStream(context);
1216 if (!WFC_Context_Active(context))
1220 DPRINT(("WFC_Context_Compose calls OWF_DisplayContext_DisableFastpath because !OWF_DisplayContext_CopyFastpathedStreamToTargetStream()"));
1221 OWF_DisplayContext_DisableFastpath(context->displayContext);
1222 //If fastpath is disabled here then we need to compose properly this cycle
1230 WFC_Context_UnlockTarget(context,copy);
1234 //If non-autonomous, then the lock target is required.
1235 OWF_ASSERT(WFC_Context_Active(context));
1239 if (OWF_DisplayContext_FastpathEnabled(context->displayContext))
1241 WFC_ELEMENT* topmostElement = NULL;
1242 topmostElement = WFC_Scene_TopMostElement(context->committedScene);
1243 owfSymElementNotifications(context, topmostElement);
1246 if (!OWF_DisplayContext_FastpathEnabled(context->displayContext))
1248 DPRINT(("== WFC_Context_DoCompose(context = %p) - Composing", context));
1249 WFC_Context_PrepareComposition(context);
1251 scene = context->committedScene;
1254 for (node = scene->elements; NULL != node; node = node->next)
1257 WFC_ELEMENT* element = NULL;
1258 WFC_ELEMENT_STATE* elementState = NULL;
1259 element = ELEMENT(node->data);
1261 if (element->skipCompose)
1263 /* this element is somehow degraded, its source is missing or
1264 * something else; skip to next element */
1265 DPRINT((" *** Skipping element %d", element->handle));
1269 DPRINT((" Composing element %d", element->handle));
1271 /* BeginComposition may fail e.g. if the element's destination
1272 * rectangle is something bizarre, i.e. causes overflows or
1275 if ((elementState=WFC_Pipeline_BeginComposition(context, element))!=NULL)
1277 owfSymElementNotifications(context, element);
1279 WFC_Pipeline_ExecuteSourceConversionStage(context, elementState);
1280 WFC_Pipeline_ExecuteCropStage(context, elementState);
1281 WFC_Pipeline_ExecuteFlipStage(context, elementState);
1282 WFC_Pipeline_ExecuteRotationStage(context, elementState);
1283 WFC_Pipeline_ExecuteScalingStage(context, elementState);
1284 WFC_Pipeline_ExecuteBlendingStage(context, elementState);
1286 WFC_Pipeline_EndComposition(context, element,elementState);
1290 WFC_Context_FinishComposition(context);
1291 DPRINT(("=== WFC_Context_DoCompose(context = %p) - Diplayed Composition", context));
1294 WFC_Scene_UnlockSourcesAndMasks(context->committedScene);
1295 owfSymProcessAllNotifications(context);
1296 OWF_Mutex_Unlock(&context->sceneMutex);
1298 OWF_Semaphore_Post(&context->compositionSemaphore);
1301 /*---------------------------------------------------------------------------
1302 * Activate/deactivate auto-composition on context
1304 * \param context Context
1305 * \param act Auto-composition enable/disable
1306 *----------------------------------------------------------------------------*/
1308 WFC_Context_Activate(WFC_CONTEXT* context,
1311 OWF_ASSERT(context);
1313 DPRINT(("WFC_Context_Activate: %s", (act) ? "activate" : "deactivate"));
1315 if (act && !WFC_Context_Active(context))
1317 DPRINT(("WFC_Context_Activate: WFC_CONTEXT_STATE_PASSIVE: activating"));
1318 context->activationState = WFC_CONTEXT_STATE_ACTIVATING;
1320 /* moved from composer loop - updates must be allowed
1321 * immediately after activation
1323 WFC_Device_EnableContentNotifications(context->device,
1327 OWF_Message_Send(&context->composerQueue,
1328 WFC_MESSAGE_ACTIVATE,
1331 else if (!act && WFC_Context_Active(context))
1333 DPRINT(("WFC_Context_Activate: WFC_CONTEXT_STATE_ACTIVE: deactivating"));
1334 context->activationState = WFC_CONTEXT_STATE_DEACTIVATING;
1335 OWF_Message_Send(&context->composerQueue,
1336 WFC_MESSAGE_DEACTIVATE,
1341 /*---------------------------------------------------------------------------
1343 *----------------------------------------------------------------------------*/
1344 OWF_API_CALL WFCboolean
1345 WFC_Context_InvokeComposition(WFC_DEVICE* device,
1346 WFC_CONTEXT* context,
1351 OWF_ASSERT(context);
1354 device = device; /* suppress the compiler warning */
1356 status = OWF_Semaphore_TryWait(&context->compositionSemaphore);
1361 /* busy; processing last request */
1364 /* wait previous frame composition to finish */
1365 OWF_Semaphore_Wait(&context->compositionSemaphore);
1368 /* compositionSemaphore is posted/signaled in WFC_Context_Compose()
1369 after frame has been successfully composed */
1370 OWF_Message_Send(&context->composerQueue, WFC_MESSAGE_COMPOSE, 0);
1375 /*---------------------------------------------------------------------------
1377 *----------------------------------------------------------------------------*/
1378 OWF_API_CALL WFCErrorCode
1379 WFC_Context_InvokeCommit(WFC_DEVICE* device,
1380 WFC_CONTEXT* context,
1385 OWF_ASSERT(context);
1388 device = device; /* suppress the compiler warning */
1390 /* first check if there're inconsistensies in the scene */
1391 if (WFC_Scene_HasConflicts(context->workScene))
1393 DPRINT(("WFC_Context_InvokeCommit: scene has inconsistensies"));
1394 return WFC_ERROR_INCONSISTENCY;
1397 /* then commit - always asynchronously */
1398 status = OWF_Semaphore_TryWait(&context->commitSemaphore);
1399 DPRINT(("COMMIT: Commit semaphore status = %d", status));
1404 DPRINT(("COMMIT: Busy; exiting."));
1405 /* busy; processing last commit */
1406 return WFC_ERROR_BUSY;
1409 DPRINT(("COMMIT: Waiting for previous commit to finish."));
1410 /* wait previous commit to finish */
1411 OWF_Semaphore_Wait(&context->commitSemaphore);
1414 /* comitting scene attribute changes */
1415 DPRINT(("COMMIT: Cloning scene attribute changes"));
1416 OWF_AttributeList_Commit(&context->attributes,
1418 WFC_CONTEXT_BG_COLOR,SNAPSHOT_ATTR_VALUE_INDEX);
1420 DPRINT(("COMMIT: Cloning scene"));
1421 /* take snapshot of the current working copy - it will
1422 * be the new committed scene */
1423 context->snapshotScene = WFC_Scene_Clone(context->workScene);
1425 DPRINT(("COMMIT: Sending commit request"));
1426 /* invoke async commit */
1427 OWF_Message_Send(&context->composerQueue, WFC_MESSAGE_COMMIT, 0);
1428 return WFC_ERROR_NONE;
1431 /*---------------------------------------------------------------------------
1435 *----------------------------------------------------------------------------*/
1437 WFC_Context_InsertFence(WFC_CONTEXT* context,
1441 OWF_ASSERT(context);
1444 DPRINT(("WFC_Context_InsertFence: Sending fence sync: 0x%08x", sync));
1446 OWF_Message_Send(&context->composerQueue, WFC_MESSAGE_FENCE_1_DISPLAY, (void*) dpy);
1447 OWF_Message_Send(&context->composerQueue, WFC_MESSAGE_FENCE_2_SYNCOBJECT, sync);
1450 /*---------------------------------------------------------------------------
1451 * Insert element into context's scene
1455 * \param subordinate
1457 * \return WFCErrorCode
1458 *----------------------------------------------------------------------------*/
1459 OWF_API_CALL WFCErrorCode
1460 WFC_Context_InsertElement(WFC_CONTEXT* context,
1462 WFCElement subordinate)
1464 WFC_ELEMENT* object = NULL;
1465 WFCErrorCode result = WFC_ERROR_BAD_HANDLE;
1467 OWF_ASSERT(context);
1469 object = WFC_Device_FindElement(context->device, element);
1471 if (NULL != object && CONTEXT(object->context) == context)
1473 /* set the sharing flag as the element will be
1474 * shared between the device and working copy scene.
1475 * this is to tell the scene that it must not destroy
1478 object->shared = WFC_TRUE;
1479 result = WFC_Scene_InsertElement(context->workScene,
1483 context->lowestElement = WFC_Scene_LowestElement(context->workScene);
1488 /*---------------------------------------------------------------------------
1489 * Remove element from context's scene
1494 * \return WFCErrorCode
1495 *----------------------------------------------------------------------------*/
1496 OWF_API_CALL WFCErrorCode
1497 WFC_Context_RemoveElement(WFC_CONTEXT* context,
1500 WFC_ELEMENT* elemento = NULL;
1502 OWF_ASSERT(context);
1504 elemento = WFC_Context_FindElement(context, element);
1508 WFC_Scene_RemoveElement(context->workScene, element);
1509 /* the element is no longer shared, as it only resides
1510 * in device from this point on
1512 elemento->shared = WFC_FALSE;
1513 context->lowestElement = WFC_Scene_LowestElement(context->workScene);
1516 return WFC_ERROR_NONE;
1520 * \brief IncreaseClientElementCount
1523 * \return positive increased current element count; negative or zero indicating the count can't be increased
1526 WFC_Context_IncreaseClientElementCount(WFC_CONTEXT* context)
1528 /* This implementation simply caps the number of elements allocated to the client
1529 * to 1/3 of the total elements.
1530 * A cleverer strategy would allow the client to create more elements
1531 * so long as the number added to the scene *2 did not exceed the spare pool size.
1532 * These failure points are also a good place to consider increasing the pool size
1534 if (context->clientElementCount>=MAX_ELEMENTS)
1536 return -context->clientElementCount;
1540 return ++context->clientElementCount;
1545 * \brief DecreaseClientElementCount
1548 * \return positive or zero decreased current element count; negative indicating the count can't be decreased - p0robably already zero
1551 WFC_Context_DecreaseClientElementCount(WFC_CONTEXT* context)
1553 /* note that a negative return indicates that decrements are not matched with increments */
1554 return --context->clientElementCount;
1557 /*---------------------------------------------------------------------------
1559 *----------------------------------------------------------------------------*/
1560 OWF_API_CALL WFCErrorCode
1561 WFC_Context_GetElementAbove(WFC_CONTEXT* context,
1565 WFC_ELEMENT* object = NULL;
1566 WFCErrorCode error = WFC_ERROR_ILLEGAL_ARGUMENT;
1568 OWF_ASSERT(context);
1571 object = WFC_Context_FindElement(context, element);
1577 temp = WFC_Scene_GetNeighbourElement(context->workScene, element, 1);
1579 error = WFC_ERROR_NONE;
1584 /*---------------------------------------------------------------------------
1586 *----------------------------------------------------------------------------*/
1587 OWF_API_CALL WFCErrorCode
1588 WFC_Context_GetElementBelow(WFC_CONTEXT* context,
1592 WFC_ELEMENT* object = NULL;
1593 WFCErrorCode error = WFC_ERROR_ILLEGAL_ARGUMENT;
1595 OWF_ASSERT(context);
1598 object = WFC_Context_FindElement(context, element);
1603 temp = WFC_Scene_GetNeighbourElement(context->workScene, element, -1);
1605 error = WFC_ERROR_NONE;
1610 /*---------------------------------------------------------------------------
1612 *----------------------------------------------------------------------------*/
1613 OWF_API_CALL WFCErrorCode
1614 WFC_Context_GetAttribi(WFC_CONTEXT* context,
1615 WFCContextAttrib attrib,
1619 OWF_ATTRIBUTE_LIST_STATUS err;
1620 WFCErrorCode result = WFC_ERROR_NONE;
1622 OWF_ASSERT(context);
1625 temp = OWF_Attribute_GetValuei(&context->attributes, attrib);
1626 err = OWF_AttributeList_GetError(&context->attributes);
1628 if (err != ATTR_ERROR_NONE)
1630 result = WFC_ERROR_BAD_ATTRIBUTE;
1639 /*---------------------------------------------------------------------------
1641 *----------------------------------------------------------------------------*/
1642 OWF_API_CALL WFCErrorCode
1643 WFC_Context_SetAttribi(WFC_CONTEXT* context,
1644 WFCContextAttrib attrib,
1647 WFCErrorCode result = WFC_ERROR_NONE;
1649 OWF_ASSERT(context);
1654 case WFC_CONTEXT_BG_COLOR:
1659 * Color format is RGBA NOT RGBA.
1661 alpha = value & 0xFF;
1663 if (WFC_CONTEXT_TYPE_ON_SCREEN == context->type)
1665 /* the only allowed value for on-screen context
1666 * background alpha is 255 */
1669 result = WFC_ERROR_ILLEGAL_ARGUMENT;
1675 case WFC_CONTEXT_ROTATION:
1677 if (!(WFC_ROTATION_0 == value ||
1678 WFC_ROTATION_90 == value ||
1679 WFC_ROTATION_180 == value ||
1680 WFC_ROTATION_270 == value))
1682 result = WFC_ERROR_ILLEGAL_ARGUMENT;
1686 OWF_DisplayContext_ResetFastpathCheck(context->displayContext);
1691 case WFC_CONTEXT_TYPE:
1692 case WFC_CONTEXT_TARGET_HEIGHT:
1693 case WFC_CONTEXT_TARGET_WIDTH:
1694 case WFC_CONTEXT_LOWEST_ELEMENT:
1696 result = WFC_ERROR_BAD_ATTRIBUTE;
1700 case WFC_CONTEXT_FORCE_32BIT:
1703 result = WFC_ERROR_BAD_ATTRIBUTE;
1708 if (WFC_ERROR_NONE == result)
1710 OWF_ATTRIBUTE_LIST_STATUS error;
1712 /* try changing the value */
1713 OWF_Attribute_SetValuei(&context->attributes, attrib, value);
1714 error = OWF_AttributeList_GetError(&context->attributes);
1716 /* transform errors */
1718 case ATTR_ERROR_ACCESS_DENIED:
1719 case ATTR_ERROR_INVALID_ATTRIBUTE:
1721 result = WFC_ERROR_BAD_ATTRIBUTE;
1734 /*---------------------------------------------------------------------------
1736 *----------------------------------------------------------------------------*/
1737 OWF_API_CALL WFCErrorCode
1738 WFC_Context_GetAttribfv(WFC_CONTEXT* context,
1739 WFCContextAttrib attrib,
1743 WFCErrorCode result = WFC_ERROR_NONE;
1745 OWF_ASSERT(context);
1750 case WFC_CONTEXT_BG_COLOR:
1754 result = WFC_ERROR_ILLEGAL_ARGUMENT;
1759 OWF_ATTRIBUTE_LIST_STATUS err;
1761 color = OWF_Attribute_GetValuei(&context->attributes, attrib);
1762 err = OWF_AttributeList_GetError(&context->attributes);
1764 if (err != ATTR_ERROR_NONE)
1766 result = WFC_ERROR_BAD_ATTRIBUTE;
1770 /* extract color channels and convert to float */
1771 values[0] = (WFCfloat) (color >> 24) /
1772 (WFCfloat) OWF_BYTE_MAX_VALUE;
1773 values[1] = (WFCfloat) ((color >> 16) & 0xFF) /
1774 (WFCfloat) OWF_BYTE_MAX_VALUE;
1775 values[2] = (WFCfloat) ((color >> 8) & 0xFF) /
1776 (WFCfloat) OWF_BYTE_MAX_VALUE;
1777 values[3] = (WFCfloat) (color & 0xFF) /
1778 (WFCfloat) OWF_BYTE_MAX_VALUE;
1785 result = WFC_ERROR_BAD_ATTRIBUTE;
1793 /*---------------------------------------------------------------------------
1795 *----------------------------------------------------------------------------*/
1796 OWF_API_CALL WFCErrorCode
1797 WFC_Context_SetAttribfv(WFC_CONTEXT* context,
1798 WFCContextAttrib attrib,
1800 const WFCfloat* values)
1802 WFCErrorCode result = WFC_ERROR_NONE;
1804 OWF_ASSERT(context);
1809 case WFC_CONTEXT_BG_COLOR:
1813 result = WFC_ERROR_ILLEGAL_ARGUMENT;
1819 /* Every color component value must fall within range [0, 1] */
1820 if (INRANGE(values[0], 0.0f, 1.0f) &&
1821 INRANGE(values[1], 0.0f, 1.0f) &&
1822 INRANGE(values[2], 0.0f, 1.0f) &&
1823 INRANGE(values[3], 0.0f, 1.0f))
1825 color = (((OWFuint32) floor(values[0] * 255)) << 24) |
1826 (((OWFuint32) floor(values[1] * 255)) << 16) |
1827 (((OWFuint32) floor(values[2] * 255)) << 8) |
1828 ((OWFuint32) floor(values[3] * 255));
1830 /* delegate to integer accessor - it'll check the
1831 * the rest of the value and update it eventually */
1832 result = WFC_Context_SetAttribi(context, attrib, color);
1836 result = WFC_ERROR_ILLEGAL_ARGUMENT;
1844 result = WFC_ERROR_BAD_ATTRIBUTE;
1854 WFC_Context_AutoComposer(WFC_CONTEXT* context)
1856 OWF_Mutex_Lock(&context->updateFlagMutex);
1857 if (context->sourceUpdateCount > 0)
1859 DPRINT(("WFC_Context_ComposerThread: %d sources were updated, "
1860 "invoking composition\n",
1861 context->sourceUpdateCount));
1863 /* reset update counter */
1865 OWF_Mutex_Unlock(&context->updateFlagMutex);
1866 WFC_Context_DoCompose(context);
1870 OWF_Mutex_Unlock(&context->updateFlagMutex);
1874 /*---------------------------------------------------------------------------
1876 *----------------------------------------------------------------------------*/
1878 WFC_Context_ComposerThread(void* data)
1880 WFC_CONTEXT* context = (WFC_CONTEXT*) data;
1881 OWFboolean screenCreated = OWF_TRUE;
1885 OWF_ASSERT(context);
1886 DPRINT(("WFC_Context_ComposerThread starting"));
1888 memset(&msg, 0, sizeof(OWF_MESSAGE));
1890 if (context->type == WFC_CONTEXT_TYPE_ON_SCREEN)
1892 screenCreated = OWF_Screen_Create(context->screenNumber, context->displayContext);
1895 OWF_ComposerThread_Rendezvous(context->displayContext);
1897 OWF_ComposerThread_RendezvousDestroy(context->displayContext);
1899 while (context->device && msg.id != WFC_MESSAGE_QUIT && screenCreated)
1903 if (WFC_CONTEXT_STATE_ACTIVE == context->activationState)
1905 err = OWF_Message_Wait(&context->composerQueue,
1907 AUTO_COMPOSE_DELAY);
1909 WFC_Context_AutoComposer(context);
1913 DPRINT((" ComposerThread waiting for message"));
1914 err = OWF_Message_Wait(&context->composerQueue, &msg, WAIT_FOREVER);
1921 case WFC_MESSAGE_ACTIVATE:
1923 DPRINT(("****** ENABLING AUTO-COMPOSITION ******"));
1924 context->activationState = WFC_CONTEXT_STATE_ACTIVE;
1928 case WFC_MESSAGE_DEACTIVATE:
1930 /* cancel possible countdown so that update won't occur
1931 * after deactivation */
1932 DPRINT(("****** DISABLING AUTO-COMPOSITION ******"));
1933 WFC_Device_EnableContentNotifications(context->device,
1936 context->activationState = WFC_CONTEXT_STATE_PASSIVE;
1937 if (OWF_DisplayContext_FastpathEnabled(context->displayContext))
1939 DPRINT(("COMMIT: Invoking fastpath recomposition after deactivate"));
1940 WFC_Context_DoCompose(context);
1945 case WFC_MESSAGE_COMMIT:
1947 DPRINT(("****** COMMITTING SCENE CHANGES ******"));
1949 DPRINT(("COMMIT: Invoking DoCommit"));
1950 WFC_Context_DoCommit(context);
1951 OWF_DisplayContext_ResetFastpathCheck(context->displayContext);
1952 if (!WFC_Context_Active(context))
1954 DPRINT(("COMMIT: Context is inactive, composition "
1955 "not needed.", context->handle));
1960 /* context is active; compose immediately after
1961 * commit has completed */
1963 DPRINT(("COMMIT: Invoking composition after commit"));
1968 case WFC_MESSAGE_COMPOSE:
1970 DPRINT(("****** COMPOSING SCENE ******"));
1972 WFC_Context_DoCompose(context);
1977 case WFC_MESSAGE_FENCE_1_DISPLAY:
1979 DPRINT(("****** STORING EGLDISPLAY (%p) ******", msg.data));
1981 context->nextSyncObjectDisplay = (WFCEGLDisplay)msg.data;
1985 case WFC_MESSAGE_FENCE_2_SYNCOBJECT:
1987 DPRINT(("****** BREAKING FENCE (%p) ******", msg.data));
1988 OWF_ASSERT(context->eglPrivateSignalSync);
1990 context->eglPrivateSignalSync(context->nextSyncObjectDisplay,
1991 (WFCEGLSync) msg.data,
1999 if (context->type == WFC_CONTEXT_TYPE_ON_SCREEN)
2001 OWF_Screen_Destroy(context->displayContext);
2003 /* Release any use of EGL by this thread. */
2006 DPRINT(("WFC_Context_ComposerThread terminating"));
2007 OWF_Thread_Exit(NULL);
2011 /*---------------------------------------------------------------------------
2013 *----------------------------------------------------------------------------*/
2014 OWF_API_CALL WFCboolean
2015 WFC_Context_Active(WFC_CONTEXT* context)
2017 OWF_ASSERT(context);
2019 return (WFC_CONTEXT_STATE_ACTIVE == context->activationState ||
2020 WFC_CONTEXT_STATE_ACTIVATING == context->activationState) ? WFC_TRUE : WFC_FALSE;