sl@0: /* Copyright (c) 2009 The Khronos Group Inc. sl@0: * Portions copyright (c) 2009-2010 Nokia Corporation and/or its subsidiary(-ies) sl@0: * sl@0: * Permission is hereby granted, free of charge, to any person obtaining a sl@0: * copy of this software and/or associated documentation files (the sl@0: * "Materials"), to deal in the Materials without restriction, including sl@0: * without limitation the rights to use, copy, modify, merge, publish, sl@0: * distribute, sublicense, and/or sell copies of the Materials, and to sl@0: * permit persons to whom the Materials are furnished to do so, subject to sl@0: * the following conditions: sl@0: * sl@0: * The above copyright notice and this permission notice shall be included sl@0: * in all copies or substantial portions of the Materials. sl@0: * sl@0: * THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, sl@0: * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF sl@0: * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. sl@0: * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY sl@0: * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, sl@0: * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE sl@0: * MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS. sl@0: */ sl@0: sl@0: /*! \ingroup wfc sl@0: * \file wfccontext.c sl@0: * sl@0: * \brief SI Context handling sl@0: */ sl@0: sl@0: #include sl@0: #include sl@0: #include sl@0: #include sl@0: #include sl@0: sl@0: #include sl@0: #include sl@0: sl@0: #include "wfccontext.h" sl@0: #include "wfcpipeline.h" sl@0: sl@0: #include "owfscreen.h" sl@0: #include "owfdisplaycontextgeneral.h" sl@0: #include "owfnotifications.h" sl@0: sl@0: sl@0: /*! maximum number of elements per scene */ sl@0: #define MAX_ELEMENTS 512 sl@0: /*! maximum number of scenes per context */ sl@0: #define MAX_SCENES 3 sl@0: sl@0: sl@0: #define CONTEXT_SCENE_POOL_SIZE MAX_SCENES sl@0: #define CONTEXT_ELEMENT_POOL_SIZE MAX_SCENES * MAX_ELEMENTS sl@0: #define CONTEXT_NODE_POOL_SIZE 2 * CONTEXT_ELEMENT_POOL_SIZE sl@0: sl@0: /*! almost 2^31 */ sl@0: #define MAX_DELAY 2100000000 sl@0: sl@0: /*! 15ms */ sl@0: #define AUTO_COMPOSE_DELAY 15000 sl@0: #define FIRST_CONTEXT_HANDLE 2000 sl@0: sl@0: #ifdef __cplusplus sl@0: extern "C" { sl@0: #endif sl@0: sl@0: static WFCHandle nextContextHandle = FIRST_CONTEXT_HANDLE; sl@0: sl@0: typedef enum sl@0: { sl@0: WFC_MESSAGE_NONE, sl@0: WFC_MESSAGE_QUIT, sl@0: WFC_MESSAGE_COMPOSE, sl@0: WFC_MESSAGE_COMMIT, sl@0: WFC_MESSAGE_FENCE_1_DISPLAY, sl@0: WFC_MESSAGE_FENCE_2_SYNCOBJECT, sl@0: WFC_MESSAGE_ACTIVATE, sl@0: WFC_MESSAGE_DEACTIVATE, sl@0: WFC_MESSAGE_START_COUNTDOWN, sl@0: WFC_MESSAGE_CANCEL sl@0: } WFC_MESSAGES; sl@0: sl@0: static void* sl@0: WFC_Context_ComposerThread(void* data); sl@0: sl@0: sl@0: /*--------------------------------------------------------------------------- sl@0: * sl@0: *----------------------------------------------------------------------------*/ sl@0: void WFC_CONTEXT_Ctor(void* self) sl@0: { sl@0: self = self; sl@0: } sl@0: sl@0: /*---------------------------------------------------------------------------*/ sl@0: static WFCboolean sl@0: WFC_Context_CreateState(WFC_CONTEXT* context) sl@0: { /* Must be called late enough that scratch buffers can be mapped and hardware rotation capability queried */ sl@0: OWF_IMAGE_FORMAT fInt, sl@0: fExt; sl@0: WFCint stride = 0; sl@0: OWF_ASSERT(context); sl@0: sl@0: DPRINT(("WFC_Context_CreateContextState")); sl@0: sl@0: owfNativeStreamGetHeader(context->stream, sl@0: NULL, NULL, &stride, &fExt, NULL); sl@0: /* internal image used as intermediate target */ sl@0: fInt.pixelFormat = OWF_IMAGE_ARGB_INTERNAL; sl@0: fInt.linear = fExt.linear; sl@0: fInt.premultiplied = fExt.premultiplied; sl@0: fInt.rowPadding = 1; sl@0: sl@0: if (context->type == WFC_CONTEXT_TYPE_ON_SCREEN) sl@0: { sl@0: /* The unrotated target buffer: Can't get real address without locking for writing! NO STRIDE */ sl@0: context->state.unrotatedTargetImage=OWF_Image_Create(context->targetWidth,context->targetHeight,&fExt,context->scratchBuffer[2],0); sl@0: /* The rotated version of the target buffer for hardware rotation sl@0: * or a de-rotated version of the internal buffer into another scratch buffer for software rotation sl@0: */ sl@0: if (OWF_Screen_Rotation_Supported(context->displayContext)) sl@0: { /* The rotated version of the target buffer for hardware rotation */ sl@0: context->state.rotatedTargetImage=OWF_Image_Create(context->targetHeight,context->targetWidth,&fExt,context->scratchBuffer[2],0); sl@0: } sl@0: else sl@0: { /* a de-rotated version of the internal buffer into another scratch buffer for software rotation */ sl@0: context->state.rotatedTargetImage=OWF_Image_Create(context->targetWidth,context->targetHeight,&fInt,context->scratchBuffer[1],0); sl@0: } sl@0: } sl@0: else sl@0: { sl@0: /* The unrotated target buffer: Can't get real address without locking for writing! STRIDE HONOURED */ sl@0: context->state.unrotatedTargetImage=OWF_Image_Create(context->targetWidth,context->targetHeight,&fExt,context->scratchBuffer[2],stride); sl@0: /* a de-rotated version of the internal buffer into another scratch buffer for software rotation */ sl@0: context->state.rotatedTargetImage=OWF_Image_Create(context->targetWidth,context->targetHeight,&fInt,context->scratchBuffer[1],0); sl@0: } sl@0: /* The internal target buffer composed to for 0 and 180 degree rotation */ sl@0: context->state.unrotatedInternalTargetImage=OWF_Image_Create(context->targetWidth,context->targetHeight,&fInt,context->scratchBuffer[0],stride); sl@0: /* The internal target buffer composed to for 90 and 270 degree rotation */ sl@0: context->state.rotatedInternalTargetImage=OWF_Image_Create(context->targetHeight,context->targetWidth,&fInt,context->scratchBuffer[0],stride); sl@0: sl@0: if (context->state.unrotatedTargetImage && context->state.rotatedTargetImage && context->state.unrotatedInternalTargetImage && context->state.rotatedInternalTargetImage) sl@0: { sl@0: return WFC_TRUE; sl@0: } sl@0: else sl@0: { sl@0: return WFC_FALSE; sl@0: } sl@0: } sl@0: /*---------------------------------------------------------------------------*/ sl@0: static void sl@0: WFC_Context_DestroyState(WFC_CONTEXT* context) sl@0: { sl@0: /* The unrotated target buffer */ sl@0: OWF_Image_Destroy(context->state.unrotatedTargetImage); sl@0: /* The rotated version of the target buffer for hardware rotation, sl@0: * or a de-rotated version of the internal buffer into another scratch buffer for software rotation sl@0: */ sl@0: OWF_Image_Destroy(context->state.rotatedTargetImage); sl@0: /* The internal target buffer composed to for 0 and 180 degree rotation */ sl@0: OWF_Image_Destroy(context->state.unrotatedInternalTargetImage); sl@0: /* The internal target buffer composed to for 90 and 270 degree rotation */ sl@0: OWF_Image_Destroy(context->state.rotatedInternalTargetImage); sl@0: sl@0: } sl@0: /*--------------------------------------------------------------------------- sl@0: * Should only be accessed indirectly by calls to WFC_Device_DestroyContext or sl@0: * WFC_Device_DestroyContexts sl@0: *----------------------------------------------------------------------------*/ sl@0: void WFC_CONTEXT_Dtor(void* self) sl@0: { sl@0: OWFint ii = 0; sl@0: WFC_CONTEXT* context = NULL; sl@0: sl@0: OWF_ASSERT(self); sl@0: DPRINT(("WFC_CONTEXT_Dtor(%p)", self)); sl@0: sl@0: context = CONTEXT(self); sl@0: sl@0: OWF_ASSERT(context); sl@0: sl@0: WFC_Pipeline_DestroyState(context); sl@0: WFC_Context_DestroyState(context); sl@0: sl@0: OWF_MessageQueue_Destroy(&context->composerQueue); sl@0: sl@0: /* make the stream destroyable */ sl@0: if (context->stream != OWF_INVALID_HANDLE) sl@0: { sl@0: owfNativeStreamSetProtectionFlag(context->stream, OWF_FALSE); sl@0: owfNativeStreamDestroy(context->stream); sl@0: } sl@0: context->stream = OWF_INVALID_HANDLE; sl@0: sl@0: OWF_AttributeList_Destroy(&context->attributes); sl@0: sl@0: for (ii = 0; ii < SCRATCH_BUFFER_COUNT; ii++) sl@0: { sl@0: OWF_Image_FreeData(context->displayContext, &context->scratchBuffer[ii]); sl@0: context->scratchBuffer[ii] = 0; sl@0: } sl@0: sl@0: OWF_DisplayContext_Destroy(context->screenNumber, context->displayContext); sl@0: context->displayContext = NULL; sl@0: sl@0: OWF_Pool_Destroy(context->scenePool); sl@0: OWF_Pool_Destroy(context->elementPool); sl@0: OWF_Pool_Destroy(context->nodePool); sl@0: sl@0: OWF_Semaphore_Destroy(&context->compositionSemaphore); sl@0: OWF_Semaphore_Destroy(&context->commitSemaphore); sl@0: OWF_Mutex_Destroy(&context->updateFlagMutex); sl@0: OWF_Mutex_Destroy(&context->sceneMutex); sl@0: } sl@0: sl@0: /*--------------------------------------------------------------------------- sl@0: * sl@0: *----------------------------------------------------------------------------*/ sl@0: OWF_API_CALL void sl@0: WFC_Context_Shutdown(WFC_CONTEXT* context) sl@0: { sl@0: OWF_ASSERT(context); sl@0: DPRINT(("WFC_Context_Shutdown(context = %d)", context->handle)); sl@0: sl@0: DPRINT(("Waiting for composer thread termination")); sl@0: if (context->composerThread) sl@0: { sl@0: OWF_Message_Send(&context->composerQueue, WFC_MESSAGE_QUIT, 0); sl@0: OWF_Thread_Join(context->composerThread, NULL); sl@0: OWF_Thread_Destroy(context->composerThread); sl@0: } sl@0: sl@0: context->composerThread = NULL; sl@0: sl@0: if (context->device) sl@0: { sl@0: /* #4604: added guard condition */ sl@0: WFC_Device_DestroyContextElements(context->device, context); sl@0: WFC_Device_DestroyContextImageProviders(context->device, context); sl@0: } sl@0: sl@0: WFC_Scene_Destroy(context->workScene); sl@0: WFC_Scene_Destroy(context->snapshotScene); sl@0: WFC_Scene_Destroy(context->committedScene); sl@0: context->workScene = NULL; sl@0: context->snapshotScene = NULL; sl@0: context->committedScene = NULL; sl@0: } sl@0: sl@0: /*--------------------------------------------------------------------------- sl@0: * Initialize context attributes sl@0: *----------------------------------------------------------------------------*/ sl@0: OWF_API_CALL OWF_ATTRIBUTE_LIST_STATUS sl@0: WFC_Context_InitializeAttributes(WFC_CONTEXT* context, sl@0: WFCContextType type) sl@0: { sl@0: OWF_ATTRIBUTE_LIST_STATUS attribError=ATTR_ERROR_NONE; sl@0: OWF_ASSERT(context); sl@0: /* initialize attributes/properties */ sl@0: if (context->stream) sl@0: { sl@0: owfNativeStreamGetHeader(context->stream, sl@0: &context->targetWidth, sl@0: &context->targetHeight, sl@0: NULL, NULL, NULL); sl@0: } sl@0: context->type = type; sl@0: context->rotation = WFC_ROTATION_0; sl@0: context->backgroundColor = 0x000000FF; sl@0: context->lowestElement = WFC_INVALID_HANDLE; sl@0: sl@0: sl@0: OWF_AttributeList_Create(&context->attributes, sl@0: WFC_CONTEXT_TYPE, sl@0: WFC_CONTEXT_BG_COLOR); sl@0: attribError=OWF_AttributeList_GetError(&context->attributes); sl@0: if (attribError!=ATTR_ERROR_NONE) sl@0: { sl@0: OWF_ASSERT(attribError==ATTR_ERROR_NO_MEMORY); sl@0: return attribError; sl@0: } sl@0: sl@0: sl@0: /* The composition code reads the member variables directly, sl@0: * not via the attribute engine. sl@0: */ sl@0: OWF_Attribute_Initi(&context->attributes, sl@0: WFC_CONTEXT_TYPE, sl@0: (WFCint*) &context->type, sl@0: OWF_TRUE); sl@0: sl@0: OWF_Attribute_Initi(&context->attributes, sl@0: WFC_CONTEXT_TARGET_WIDTH, sl@0: &context->targetWidth, sl@0: OWF_TRUE); sl@0: sl@0: OWF_Attribute_Initi(&context->attributes, sl@0: WFC_CONTEXT_TARGET_HEIGHT, sl@0: &context->targetHeight, sl@0: OWF_TRUE); sl@0: sl@0: OWF_Attribute_Initi(&context->attributes, sl@0: WFC_CONTEXT_ROTATION, sl@0: (WFCint*) &context->rotation, sl@0: OWF_FALSE); sl@0: sl@0: OWF_Attribute_Initi(&context->attributes, sl@0: WFC_CONTEXT_BG_COLOR, sl@0: (WFCint*) &context->backgroundColor, sl@0: OWF_FALSE); sl@0: sl@0: OWF_Attribute_Initi(&context->attributes, sl@0: WFC_CONTEXT_LOWEST_ELEMENT, sl@0: (OWFint*) &context->lowestElement, sl@0: OWF_TRUE); sl@0: attribError=OWF_AttributeList_GetError(&context->attributes); sl@0: sl@0: /* After commit to working, writable attribute abstracted variables sl@0: must not be written to directly. */ sl@0: OWF_AttributeList_Commit(&context->attributes, sl@0: WFC_CONTEXT_TYPE, sl@0: WFC_CONTEXT_BG_COLOR, sl@0: WORKING_ATTR_VALUE_INDEX ); sl@0: sl@0: return attribError; sl@0: } sl@0: sl@0: sl@0: /*--------------------------------------------------------------------------- sl@0: * sl@0: *----------------------------------------------------------------------------*/ sl@0: static WFC_CONTEXT* sl@0: WFC_Context_Initialize(WFC_CONTEXT* context, sl@0: WFC_DEVICE* device, sl@0: WFCNativeStreamType stream, sl@0: WFCContextType type, sl@0: WFCint screenNum) sl@0: { sl@0: void* scratch[SCRATCH_BUFFER_COUNT]; sl@0: OWFint err2 = 0; sl@0: OWFint ii = 0, sl@0: nbufs = 0; sl@0: OWFint fail = 0; sl@0: OWF_ATTRIBUTE_LIST_STATUS attribStatus = ATTR_ERROR_NONE; sl@0: OWF_ASSERT(context); sl@0: OWF_ASSERT(device); sl@0: sl@0: DPRINT(("WFC_Context_Initialize(%p,%p,%d,%d)", context, device, type, screenNum)); sl@0: sl@0: context->type = type; sl@0: context->device = device; sl@0: context->handle = nextContextHandle; sl@0: context->screenNumber = screenNum; sl@0: context->activationState = WFC_CONTEXT_STATE_PASSIVE; sl@0: context->sourceUpdateCount = 0; sl@0: context->clientElementCount = 0; sl@0: ++nextContextHandle; sl@0: sl@0: context->displayContext = OWF_DisplayContext_Create(screenNum); sl@0: if (context->displayContext == NULL) sl@0: { sl@0: DPRINT(("WFC_Context_Initialize(): Could not create display Context")); sl@0: return NULL; sl@0: } sl@0: sl@0: context->eglPrivateSignalSync = (TFPtrEglPrivateSignalSyncNok) eglGetProcAddress("egl_Private_SignalSyncNOK"); sl@0: if (! context->eglPrivateSignalSync) sl@0: { sl@0: DPRINT(("WFC_Context_Initialize(): Missing EGL extension - egl_Private_SignalSyncNOK extension")); sl@0: return NULL; sl@0: } sl@0: sl@0: err2 =OWF_MessageQueue_Init(&context->composerQueue); sl@0: if (err2 != 0) sl@0: { sl@0: DPRINT(("WFC_Context_Initialize(): Cannot initialise the message queue err(%d)", err2)); sl@0: return NULL; sl@0: } sl@0: sl@0: context->composerThread = OWF_Thread_Create(WFC_Context_ComposerThread, context); sl@0: if (!(context->composerThread)) sl@0: { sl@0: /* must call these to remove references to context */ sl@0: DPRINT(("WFC_Context_Initialize(): Failed to create thread!")); sl@0: return NULL; sl@0: } sl@0: sl@0: OWF_ComposerThread_RendezvousWait(context->displayContext); sl@0: sl@0: /*the following section of the code could be pushed to adaptation in future*/ sl@0: if (type == WFC_CONTEXT_TYPE_ON_SCREEN) sl@0: { sl@0: OWF_IMAGE_FORMAT imageFormat; sl@0: OWF_SCREEN screen; sl@0: WFCint width = 0; sl@0: WFCint height = 0; sl@0: WFCint normalSize = 0; sl@0: WFCint flippedSize = 0; sl@0: WFCNativeStreamType stream; sl@0: sl@0: /* Set up stream for sending data to screen */ sl@0: sl@0: if (!OWF_Screen_GetHeader(context->displayContext, &screen)) sl@0: { sl@0: DPRINT(("WFC_Context_Initialize(): Could not retrieve the screen parameters")); sl@0: WFC_Context_Shutdown(context); sl@0: return NULL; sl@0: } sl@0: sl@0: /* Set on-screen pixel format */ sl@0: imageFormat.pixelFormat = OWF_SURFACE_PIXEL_FORMAT; sl@0: imageFormat.premultiplied = OWF_SURFACE_PREMULTIPLIED; sl@0: imageFormat.linear = OWF_SURFACE_LINEAR; sl@0: imageFormat.rowPadding = OWF_SURFACE_ROWPADDING; sl@0: sl@0: width = screen.normal.width; sl@0: height = screen.normal.height; sl@0: sl@0: normalSize = screen.normal.height * screen.normal.stride; sl@0: flippedSize = screen.flipped.height * screen.flipped.stride; sl@0: sl@0: if (flippedSize > normalSize) sl@0: { sl@0: width = screen.flipped.width; sl@0: height = screen.flipped.height; sl@0: } sl@0: sl@0: stream = owfNativeStreamCreateImageStream(width, sl@0: height, sl@0: &imageFormat, sl@0: 1); sl@0: sl@0: if (stream) sl@0: { sl@0: WFC_Context_SetTargetStream(context, stream); sl@0: sl@0: /* At this point the stream's refcount is 2 - we must decrement sl@0: * it by one to ensure that the stream is destroyed when the sl@0: * context (that "owns" it) is destroyed. sl@0: */ sl@0: owfNativeStreamRemoveReference(stream); sl@0: } sl@0: else sl@0: { sl@0: DPRINT(("WFC_Context_Initialize(): cannot create internal target stream")); sl@0: WFC_Context_Shutdown(context); sl@0: return NULL; sl@0: } sl@0: } sl@0: else sl@0: { sl@0: WFC_Context_SetTargetStream(context, stream); sl@0: } sl@0: sl@0: nbufs = SCRATCH_BUFFER_COUNT-1; sl@0: for (ii = 0; ii < nbufs; ii++) sl@0: { sl@0: scratch[ii] = OWF_Image_AllocData(context->displayContext, MAX_SOURCE_WIDTH, sl@0: MAX_SOURCE_HEIGHT, sl@0: OWF_IMAGE_ARGB_INTERNAL); sl@0: fail = fail || (scratch[ii] == NULL); sl@0: } sl@0: sl@0: /* sl@0: * allocate one-channel buffer for alpha sl@0: * obs! this assumes sizeof(OWFsubpixel) is 4. sl@0: */ sl@0: scratch[nbufs] = OWF_Image_AllocData(context->displayContext, MAX_SOURCE_WIDTH, sl@0: MAX_SOURCE_HEIGHT, sl@0: OWF_IMAGE_L32); sl@0: fail = fail || (scratch[nbufs] == NULL); sl@0: sl@0: if (fail) sl@0: { sl@0: for (ii = 0; ii < SCRATCH_BUFFER_COUNT; ii++) sl@0: { sl@0: OWF_Image_FreeData(context->displayContext, &scratch[ii]); sl@0: } sl@0: WFC_Context_Shutdown(context); sl@0: return NULL; sl@0: } sl@0: sl@0: for (ii = 0; ii < SCRATCH_BUFFER_COUNT; ii++) sl@0: { sl@0: context->scratchBuffer[ii] = scratch[ii]; sl@0: } sl@0: sl@0: if ( OWF_Semaphore_Init(&context->compositionSemaphore, 1) sl@0: || OWF_Semaphore_Init(&context->commitSemaphore, 1) sl@0: || OWF_Mutex_Init(&context->updateFlagMutex) sl@0: || OWF_Mutex_Init(&context->sceneMutex) sl@0: sl@0: ) sl@0: { sl@0: DPRINT(("WFC_Context_Initialize(): Could not create mutexes and semaphores!")); sl@0: WFC_Context_Shutdown(context); sl@0: return NULL; sl@0: } sl@0: sl@0: if (!WFC_Pipeline_CreateState(context) || !WFC_Context_CreateState(context)) sl@0: { sl@0: DPRINT(("WFC_Context_Initialize(): Could not create pipeline state object")); sl@0: WFC_Context_Shutdown(context); sl@0: return NULL; sl@0: } sl@0: sl@0: sl@0: attribStatus= WFC_Context_InitializeAttributes(context, type); sl@0: sl@0: if (attribStatus!=ATTR_ERROR_NONE) sl@0: { sl@0: WFC_Context_Shutdown(context); sl@0: return NULL; sl@0: } sl@0: sl@0: sl@0: context->scenePool = OWF_Pool_Create(sizeof(WFC_SCENE), sl@0: CONTEXT_SCENE_POOL_SIZE); sl@0: context->elementPool = OWF_Pool_Create(sizeof(WFC_ELEMENT), sl@0: CONTEXT_ELEMENT_POOL_SIZE); sl@0: context->nodePool = OWF_Pool_Create(sizeof(OWF_NODE), sl@0: CONTEXT_NODE_POOL_SIZE); sl@0: if (!( context->scenePool && sl@0: context->nodePool && context->elementPool)) sl@0: { sl@0: WFC_Context_Shutdown(context); sl@0: return NULL; sl@0: } sl@0: sl@0: DPRINT((" Creating scenes")); sl@0: context->workScene = WFC_Scene_Create(context); sl@0: context->committedScene = WFC_Scene_Create(context); sl@0: context->snapshotScene = NULL; sl@0: sl@0: /* snapshotScene is initialized in InvokeCommit */ sl@0: sl@0: /* context's refcount is now 3 */ sl@0: sl@0: if (!(context->workScene && context->committedScene && sl@0: context->nodePool && context->elementPool)) sl@0: { sl@0: WFC_Context_Shutdown(context); sl@0: return NULL; sl@0: } sl@0: sl@0: return context; sl@0: } sl@0: sl@0: /*--------------------------------------------------------------------------- sl@0: * Create new context on device sl@0: * sl@0: * \param device Device on which the context should be created sl@0: * \param type Context type (on- or off-screen) sl@0: * sl@0: * \return New context object or NULL in case of failure sl@0: *----------------------------------------------------------------------------*/ sl@0: OWF_API_CALL WFC_CONTEXT* sl@0: WFC_Context_Create(WFC_DEVICE* device, sl@0: WFCNativeStreamType stream, sl@0: WFCContextType type, sl@0: WFCint screenNum) sl@0: { sl@0: WFC_CONTEXT* context = NULL; sl@0: sl@0: OWF_ASSERT(device); sl@0: context = CREATE(WFC_CONTEXT); sl@0: sl@0: if (context) sl@0: { sl@0: if (!WFC_Context_Initialize(context, device, stream, type, screenNum)) sl@0: { sl@0: DESTROY(context); sl@0: } sl@0: } sl@0: return context; sl@0: } sl@0: sl@0: /*--------------------------------------------------------------------------- sl@0: * Setup context rendering target sl@0: * sl@0: * \param context Context sl@0: * \param stream Target stream to use for rendering sl@0: *----------------------------------------------------------------------------*/ sl@0: OWF_API_CALL void sl@0: WFC_Context_SetTargetStream(WFC_CONTEXT* context, sl@0: OWFNativeStreamType stream) sl@0: { sl@0: OWF_ASSERT(context); sl@0: context->stream = stream; sl@0: sl@0: owfNativeStreamAddReference(stream); sl@0: sl@0: owfNativeStreamGetHeader(stream, sl@0: &context->targetWidth, &context->targetHeight, sl@0: NULL, NULL, NULL); sl@0: } sl@0: sl@0: static OWFboolean sl@0: WFC_FastpathCheckTransparency(WFCbitfield transparencyTypes, WFCfloat globalAlpha, OWF_PIXEL_FORMAT sourceFormat) sl@0: { sl@0: if ((transparencyTypes & WFC_TRANSPARENCY_ELEMENT_GLOBAL_ALPHA) && (globalAlpha != 255.0f)) sl@0: { sl@0: DPRINT(("=== WFC_FastpathCheckTransparency - Failed global alfa(%f) check", globalAlpha)); sl@0: return OWF_FALSE; sl@0: } sl@0: sl@0: if ((transparencyTypes & WFC_TRANSPARENCY_SOURCE) && (sourceFormat != OWF_IMAGE_XRGB8888)) sl@0: { sl@0: DPRINT(("=== WFC_FastpathCheckTransparency - Failed transparency check types=0x%x format=0x%x", sl@0: transparencyTypes, sourceFormat)); sl@0: return OWF_FALSE; sl@0: } sl@0: sl@0: sl@0: return OWF_TRUE; sl@0: } sl@0: sl@0: static OWFboolean sl@0: WFC_FastpathCheckGeometry(WFC_CONTEXT* context, WFC_ELEMENT* element) sl@0: { sl@0: OWFint sourceWidth = 0; sl@0: OWFint sourceHeight = 0; sl@0: OWFint destWidth = 0; sl@0: OWFint destHeight = 0; sl@0: OWFint targetWidth = 0; sl@0: OWFint targetHeight = 0; sl@0: sl@0: OWF_ASSERT(context); sl@0: OWF_ASSERT(element); sl@0: sl@0: if ((element->srcRect[0] != 0) || (element->srcRect[1] != 0)) sl@0: { sl@0: DPRINT(("=== WFC_FastpathCheckGeometry(context = %p) - FAILED Source Position Check", context)); sl@0: return OWF_FALSE; sl@0: } sl@0: sl@0: if ((element->dstRect[0] != 0) || (element->dstRect[1] != 0)) sl@0: { sl@0: DPRINT(("=== WFC_FastpathCheckGeometry(context = %p) - FAILED Destination Position Check", context)); sl@0: return OWF_FALSE; sl@0: } sl@0: sl@0: if(element->sourceFlip) sl@0: { sl@0: DPRINT(("=== WFC_FastpathCheckGeometry(context = %p) - FAILED Source Flip Check", context)); sl@0: return OWF_FALSE; sl@0: } sl@0: sl@0: if(element->sourceRotation == WFC_ROTATION_0) sl@0: { sl@0: sourceWidth = element->srcRect[2]; sl@0: sourceHeight = element->srcRect[3]; sl@0: } sl@0: else sl@0: { sl@0: DPRINT(("=== WFC_FastpathCheckGeometry(context = %p) - FAILED Source Rotation (0x%x) Check", sl@0: context, element->sourceRotation)); sl@0: return OWF_FALSE; sl@0: } sl@0: sl@0: destWidth = element->dstRect[2]; sl@0: destHeight = element->dstRect[3]; sl@0: sl@0: if ((sourceWidth != destWidth) || (sourceHeight != destHeight)) sl@0: { sl@0: DPRINT(("=== WFC_FastpathCheckGeometry(context = %p) - FAILED Non-scaling Check", context)); sl@0: return OWF_FALSE; sl@0: } sl@0: sl@0: if (context->rotation == WFC_ROTATION_0 || OWF_Screen_Rotation_Supported(context->displayContext)) sl@0: { sl@0: if (context->rotation == WFC_ROTATION_0 || context->rotation == WFC_ROTATION_180) sl@0: { sl@0: targetWidth = context->targetWidth; sl@0: targetHeight = context->targetHeight; sl@0: } sl@0: else sl@0: { sl@0: targetWidth = context->targetHeight; sl@0: targetHeight = context->targetWidth; sl@0: } sl@0: sl@0: if (destWidth == targetWidth && destHeight == targetHeight) sl@0: { sl@0: return OWF_TRUE; sl@0: } sl@0: else sl@0: { sl@0: DPRINT(("=== WFC_FastpathCheckGeometry(context = %p) - Failed Dimensions Check", context)); sl@0: } sl@0: } sl@0: else sl@0: { sl@0: DPRINT(("=== WFC_FastpathCheckGeometry(context = %p) - Failed Supported Rotations Check", context)); sl@0: } sl@0: sl@0: return OWF_FALSE; sl@0: } sl@0: sl@0: /** sl@0: * Check if the current scene is candidate for fastpath optimisation. sl@0: * Fastpath optimisation means the topmost visible layer will be passed direct to the sl@0: * lower level for presentation on the display without being composed. sl@0: * There are two questions: sl@0: * - Is the scene itself suitable for fastpathing? sl@0: * - Can the surface selected for fastpathing be presented directly by the display? sl@0: * This function will check the scene (eg reject if the top stream is non-opaque or smaller than the screen) sl@0: * sl@0: * @param context context object containing the scene to be checked. sl@0: **/ sl@0: sl@0: /* [Not in doxygen] sl@0: * The first time MOpenWFC_RI_Display_Update::SetTopLayerSurface (or SetLayerSurface) is called sl@0: * with a different stream handle, it can fail indicating the display cannot accept the stream. sl@0: * The compositor will then have to immediately compose that frame as normal, and should continue sl@0: * to perform normal composition until the scene changes to present a different stream as fastpath candidate. sl@0: * sl@0: * There is a middle ground, e.g. can the hardware handle over-sized images, or do scaling or do rotation? sl@0: * SetTopLayerSurface accepts an optional list of imperfect attributes to be checked by the adaptation. sl@0: * By WFC_Context_CheckFastpath only listing the attributes that are considered imperfect, sl@0: * and SetLayerSurface rejecting fastpath for any attribute IDs that it doesn't recognise, sl@0: * safe independent extensibility is assured. sl@0: */ sl@0: static void sl@0: WFC_Context_CheckFastpath(WFC_CONTEXT* context) sl@0: { sl@0: WFC_ELEMENT* element = NULL; sl@0: OWF_ASSERT(context); sl@0: sl@0: DPRINT(("WFC_Context_CheckFastpath(context = %p) - Check Fastpath", context)); sl@0: if ((context->type != WFC_CONTEXT_TYPE_ON_SCREEN) || sl@0: OWF_DisplayContext_FastpathChecked(context->displayContext)) sl@0: { sl@0: return; sl@0: } sl@0: sl@0: // Simple case-fast path top most layer sl@0: // More complex case, fast-path top most VISIBLE, OPAQUE layer. sl@0: OWF_DisplayContext_DisableFastpath(context->displayContext); sl@0: OWF_DisplayContext_SetFastpathChecked(context->displayContext); sl@0: // Find top layer sl@0: element = WFC_Scene_TopMostElement(context->committedScene); sl@0: if (element && element->source && element->skipCompose == WFC_FALSE) sl@0: { sl@0: sl@0: if (element->mask) sl@0: { sl@0: DPRINT(("=== WFC_Context_CheckFastpath(context = %p) - FAILED elemenent includes mask", context)); sl@0: return; sl@0: } sl@0: sl@0: OWF_ASSERT(element->source->lockedStream.image); sl@0: sl@0: OWF_ASSERT(element->source->streamHandle != OWF_INVALID_HANDLE); sl@0: sl@0: if (!WFC_FastpathCheckGeometry(context, element)) sl@0: { sl@0: return; sl@0: } sl@0: sl@0: if (!WFC_FastpathCheckTransparency(element->transparencyTypes, sl@0: element->globalAlpha, sl@0: element->source->lockedStream.image->format.pixelFormat)) sl@0: { sl@0: return; sl@0: } sl@0: sl@0: OWF_DisplayContext_EnableFastpath(context->displayContext, element->source->streamHandle); sl@0: DPRINT(("=== WFC_Context_CheckFastpath(context = %p) - Fastpath Enabled", context)); sl@0: } sl@0: } sl@0: sl@0: /*--------------------------------------------------------------------------- sl@0: * Checks if the given stream would be valid as an off-screen context target. sl@0: * sl@0: * Checks that the format can be rendered TO. sl@0: * Also checks that the image size is acceptable (within the scratch buffers). sl@0: * This is called before the context is created so is effectively a "static" context method. sl@0: * sl@0: * \param stream Target stream to use for rendering sl@0: ---------------------------------------------------------------------------*/ sl@0: sl@0: OWF_API_CALL WFCboolean sl@0: WFC_Context_IsValidTargetStream(OWFNativeStreamType stream) sl@0: { sl@0: OWFint width,height; sl@0: OWF_IMAGE_FORMAT format; sl@0: owfNativeStreamGetHeader(stream, sl@0: &width, &height, sl@0: NULL, &format, NULL); sl@0: if (width>MAX_SOURCE_WIDTH) sl@0: { sl@0: return WFC_FALSE; sl@0: } sl@0: if (height>MAX_SOURCE_HEIGHT) sl@0: { sl@0: return WFC_FALSE; sl@0: } sl@0: return (WFCboolean)OWF_Image_IsValidDestinationFormat(&format); sl@0: } sl@0: sl@0: /*--------------------------------------------------------------------------- sl@0: * Checks that the image size is acceptable (within the scratch buffers). sl@0: * This is called before the source is created. sl@0: * sl@0: * \param stream source stream to use for rendering. sl@0: ---------------------------------------------------------------------------*/ sl@0: sl@0: OWF_API_CALL WFCboolean sl@0: WFC_Context_IsValidSourceStream(OWFNativeStreamType stream) sl@0: { sl@0: OWFint width,height; sl@0: owfNativeStreamGetHeader(stream, sl@0: &width, &height, sl@0: NULL, NULL, NULL); sl@0: if ((width+2) * (height+2) > MAX_SOURCE_WIDTH * MAX_SOURCE_HEIGHT) sl@0: { sl@0: return WFC_FALSE; sl@0: } sl@0: return WFC_TRUE; sl@0: } sl@0: sl@0: /*--------------------------------------------------------------------------- sl@0: * Find element from current scene sl@0: * sl@0: * \param context Context object sl@0: * \param element Element to find sl@0: * sl@0: * \return Element object or NULL if element hasn't been inserted sl@0: * into current scene. sl@0: *----------------------------------------------------------------------------*/ sl@0: OWF_API_CALL WFC_ELEMENT* sl@0: WFC_Context_FindElement(WFC_CONTEXT* context, sl@0: WFCElement element) sl@0: { sl@0: OWF_ASSERT(context); sl@0: return WFC_Scene_FindElement(context->workScene, element); sl@0: } sl@0: sl@0: /*--------------------------------------------------------------------------- sl@0: * Commit context scene graph changes sl@0: * sl@0: * \param context Context to commit sl@0: *----------------------------------------------------------------------------*/ sl@0: static void sl@0: WFC_Context_DoCommit(WFC_CONTEXT* context) sl@0: { sl@0: OWF_ASSERT(context); sl@0: DPRINT(("WFC_Context_DoCommit(context = %p)", context)); sl@0: sl@0: OWF_ASSERT(context->snapshotScene); sl@0: sl@0: sl@0: DPRINT(("COMMIT: Committing attribute list changes")); sl@0: sl@0: DPRINT(("COMMIT: Acquiring mutex")); sl@0: OWF_Mutex_Lock(&context->sceneMutex); sl@0: sl@0: /* comitting scene attribute changes */ sl@0: DPRINT(("COMMIT: Committing scene attribute changes")); sl@0: OWF_AttributeList_Commit(&context->attributes, sl@0: WFC_CONTEXT_TYPE, sl@0: WFC_CONTEXT_BG_COLOR,COMMITTED_ATTR_VALUE_INDEX); sl@0: sl@0: sl@0: /* resolve sources and masks */ sl@0: DPRINT(("COMMIT: Committing scene changes")); sl@0: WFC_Scene_Commit(context->snapshotScene); sl@0: DPRINT(("COMMIT: Destroying old committed scene")); sl@0: WFC_Scene_Destroy(context->committedScene); sl@0: DPRINT(("COMMIT: Setting new snapshot scene as committed one.")); sl@0: context->committedScene = context->snapshotScene; sl@0: context->snapshotScene = NULL; sl@0: sl@0: // reset the visibility flags sl@0: owfSymDeviceResetVisibilityState(context); sl@0: sl@0: DPRINT(("COMMIT: Unlocking mutex")); sl@0: OWF_Mutex_Unlock(&context->sceneMutex); sl@0: sl@0: DPRINT(("COMMIT: Signaling commit semaphore")); sl@0: /* signal we're ready */ sl@0: OWF_Semaphore_Post(&context->commitSemaphore); sl@0: } sl@0: sl@0: /*--------------------------------------------------------------------------- sl@0: * sl@0: *----------------------------------------------------------------------------*/ sl@0: static OWFboolean sl@0: WFC_Context_LockTargetForWriting(WFC_CONTEXT* context) sl@0: { sl@0: OWF_ASSERT(context); sl@0: sl@0: DPRINT(("WFC_Context_LockTargetForWriting")); sl@0: sl@0: context->state.targetBuffer = sl@0: owfNativeStreamAcquireWriteBuffer(context->stream); sl@0: sl@0: if (!context->state.targetBuffer) sl@0: { sl@0: DPRINT(("Failed to WFC_Context_LockTargetForWriting owfNativeStreamAcquireWriteBuffer")); sl@0: return OWF_FALSE; sl@0: } sl@0: context->state.targetPixels = sl@0: owfNativeStreamGetBufferPtr(context->stream, sl@0: context->state.targetBuffer); sl@0: sl@0: if ((WFC_ROTATION_0 == context->rotation || WFC_ROTATION_180 == context->rotation) || sl@0: !OWF_Screen_Rotation_Supported(context->displayContext)) sl@0: { sl@0: /* final target, in target format */ sl@0: context->state.targetImage =context->state.unrotatedTargetImage; sl@0: } sl@0: else sl@0: { sl@0: /* final target, in target format */ sl@0: /* fExt stride/padding value is the rotated value */ sl@0: context->state.targetImage = context->state.rotatedTargetImage; sl@0: } sl@0: OWF_Image_SetPixelBuffer(context->state.targetImage,context->state.targetPixels); sl@0: sl@0: if (context->state.targetImage==NULL) sl@0: { sl@0: OWF_ASSERT(WFC_FALSE); sl@0: } sl@0: sl@0: /* take context rotation into account. */ sl@0: if (WFC_ROTATION_0 == context->rotation || sl@0: WFC_ROTATION_180 == context->rotation) sl@0: { sl@0: context->state.internalTargetImage = context->state.unrotatedInternalTargetImage; sl@0: } sl@0: else sl@0: { sl@0: context->state.internalTargetImage = context->state.rotatedInternalTargetImage; sl@0: } sl@0: sl@0: if (context->state.internalTargetImage==NULL) sl@0: { sl@0: OWF_ASSERT(WFC_FALSE); sl@0: } sl@0: return OWF_TRUE; sl@0: } sl@0: sl@0: /*--------------------------------------------------------------------------- sl@0: * sl@0: *----------------------------------------------------------------------------*/ sl@0: static void sl@0: WFC_Context_UnlockTarget(WFC_CONTEXT* context,OWFboolean aDoPost) sl@0: { sl@0: OWF_ROTATION rotation = OWF_ROTATION_0; sl@0: sl@0: OWF_ASSERT(context); sl@0: DPRINT(("WFC_Context_UnlockTarget")); sl@0: DPRINT((" Unlocking target stream=%d, buffer=%d", sl@0: context->stream, context->state.targetBuffer)); sl@0: sl@0: owfNativeStreamReleaseWriteBuffer(context->stream, sl@0: context->state.targetBuffer, sl@0: EGL_NO_DISPLAY, sl@0: NULL); sl@0: sl@0: sl@0: if (aDoPost) sl@0: { sl@0: switch (context->rotation) sl@0: { sl@0: case WFC_ROTATION_0: sl@0: { sl@0: rotation = OWF_ROTATION_0; sl@0: break; sl@0: } sl@0: case WFC_ROTATION_90: sl@0: { sl@0: rotation = OWF_ROTATION_90; sl@0: break; sl@0: } sl@0: case WFC_ROTATION_180: sl@0: { sl@0: rotation = OWF_ROTATION_180; sl@0: break; sl@0: } sl@0: case WFC_ROTATION_270: sl@0: { sl@0: rotation = OWF_ROTATION_270; sl@0: break; sl@0: } sl@0: default: sl@0: { sl@0: OWF_ASSERT(0); sl@0: } sl@0: } sl@0: sl@0: if (!OWF_Screen_Post_Topmost_Layer(context->displayContext, context->stream, rotation)) sl@0: { //getting a fail here is bad... display did not accept the composition buffer. sl@0: DPRINT(("WFC_Context_UnlockTarget - OWF_Screen_Post_Topmost_Layer failed for composition stream")); sl@0: OWF_ASSERT(0); sl@0: } sl@0: } sl@0: } sl@0: sl@0: /*--------------------------------------------------------------------------- sl@0: * sl@0: *----------------------------------------------------------------------------*/ sl@0: static void sl@0: WFC_Context_PrepareComposition(WFC_CONTEXT* context) sl@0: { sl@0: OWFsubpixel r, g, b, a; sl@0: sl@0: OWF_ASSERT(context); sl@0: sl@0: /* the first thing to do is to lock target stream and fetch sl@0: write buffer to it. fetching blocks until one is available, sl@0: but since only one stream can be target to only one context sl@0: at the time, no stalls should occur */ sl@0: WFC_Context_LockTargetForWriting(context); sl@0: sl@0: /* prepare for composition by "clearing the table" with sl@0: background color. */ sl@0: sl@0: r = (OWFsubpixel) OWF_RED_MAX_VALUE * ((context->backgroundColor >> 24) & sl@0: 0xFF) / OWF_BYTE_MAX_VALUE; sl@0: g = (OWFsubpixel) OWF_GREEN_MAX_VALUE * ((context->backgroundColor >> 16) & sl@0: 0xFF) / OWF_BYTE_MAX_VALUE; sl@0: b = (OWFsubpixel) OWF_BLUE_MAX_VALUE * ((context->backgroundColor >> 8) & sl@0: 0xFF) / OWF_BYTE_MAX_VALUE; sl@0: a = (OWFsubpixel) OWF_ALPHA_MAX_VALUE * (context->backgroundColor & 0xFF) / sl@0: OWF_BYTE_MAX_VALUE; sl@0: sl@0: r = r * a / OWF_ALPHA_MAX_VALUE; sl@0: g = g * a / OWF_ALPHA_MAX_VALUE; sl@0: b = b * a / OWF_ALPHA_MAX_VALUE; sl@0: sl@0: OWF_Image_Clear(context->state.internalTargetImage, r, g, b, a); sl@0: } sl@0: sl@0: sl@0: sl@0: /*--------------------------------------------------------------------------- sl@0: * sl@0: *----------------------------------------------------------------------------*/ sl@0: static void sl@0: WFC_Context_FinishComposition(WFC_CONTEXT* context) sl@0: { sl@0: OWF_ROTATION rotation = OWF_ROTATION_0; sl@0: OWFboolean screenRotation; sl@0: sl@0: OWF_ASSERT(context); sl@0: sl@0: screenRotation = OWF_Screen_Rotation_Supported(context->displayContext); sl@0: /* re-use scratch buffer 1 for context rotation */ sl@0: if (WFC_ROTATION_0 == context->rotation || screenRotation) sl@0: { sl@0: sl@0: if (screenRotation) sl@0: { sl@0: if (WFC_ROTATION_90 == context->rotation || WFC_ROTATION_270 == context->rotation) sl@0: { sl@0: owfSetStreamFlipState(context->stream, OWF_TRUE); sl@0: } sl@0: else sl@0: { sl@0: owfSetStreamFlipState(context->stream, OWF_FALSE); sl@0: } sl@0: } sl@0: OWF_Image_DestinationFormatConversion(context->state.targetImage, context->state.internalTargetImage); sl@0: } sl@0: else sl@0: { sl@0: switch (context->rotation) sl@0: { sl@0: case WFC_ROTATION_0: sl@0: { sl@0: rotation = OWF_ROTATION_0; sl@0: break; sl@0: } sl@0: case WFC_ROTATION_90: sl@0: { sl@0: rotation = OWF_ROTATION_90; sl@0: break; sl@0: } sl@0: case WFC_ROTATION_180: sl@0: { sl@0: rotation = OWF_ROTATION_180; sl@0: break; sl@0: } sl@0: case WFC_ROTATION_270: sl@0: { sl@0: rotation = OWF_ROTATION_270; sl@0: break; sl@0: } sl@0: default: sl@0: { sl@0: OWF_ASSERT(0); sl@0: } sl@0: } sl@0: sl@0: /* rotate */ sl@0: OWF_Image_Rotate(context->state.rotatedTargetImage, sl@0: context->state.internalTargetImage, sl@0: rotation); sl@0: sl@0: /* Note: support of different target formats can be put here */ sl@0: sl@0: OWF_Image_DestinationFormatConversion(context->state.targetImage, context->state.rotatedTargetImage); sl@0: } sl@0: WFC_Context_UnlockTarget(context,(context->type==WFC_CONTEXT_TYPE_ON_SCREEN)?OWF_TRUE:OWF_FALSE); sl@0: } sl@0: sl@0: /*!--------------------------------------------------------------------------- sl@0: * \brief Actual composition routine. sl@0: * Mainly just calls other functions that executes different stages of sl@0: * the composition pipeline. sl@0: * \param context Context to compose. sl@0: *----------------------------------------------------------------------------*/ sl@0: static void sl@0: WFC_Context_DoCompose(WFC_CONTEXT* context) sl@0: { sl@0: WFC_SCENE* scene = NULL; sl@0: OWF_NODE* node = NULL; sl@0: sl@0: OWF_ASSERT(context); sl@0: sl@0: OWF_Mutex_Lock(&context->updateFlagMutex); sl@0: sl@0: OWF_DisplayContext_IncrementSerialNumber(context->displayContext); sl@0: sl@0: OWF_DisplayContext_SetCompositionOngoing(context->displayContext, WFC_TRUE); sl@0: context->sourceUpdateCount = 0; sl@0: OWF_Mutex_Unlock(&context->updateFlagMutex); sl@0: sl@0: DPRINT(("WFC_Context_Compose")); sl@0: /* Composition always uses the committed version sl@0: * of the scene. sl@0: */ sl@0: sl@0: WFC_Scene_LockSourcesAndMasks(context->committedScene); sl@0: sl@0: OWF_Mutex_Lock(&context->sceneMutex); sl@0: sl@0: WFC_Context_CheckFastpath(context); sl@0: if (OWF_DisplayContext_FastpathEnabled(context->displayContext)) sl@0: { sl@0: WFCboolean targetStreamAccessed; sl@0: OWFboolean screenRotation; sl@0: screenRotation = OWF_Screen_Rotation_Supported(context->displayContext); sl@0: if (WFC_Context_Active(context)) sl@0: { //Full fastpath is only supported for autonomous composition sl@0: OWFNativeStreamType stream = OWF_INVALID_HANDLE; sl@0: OWF_ROTATION rotation = OWF_ROTATION_0; sl@0: sl@0: DPRINT(("== WFC_Context_DoCompose(context = %p) - Fastpathing", context)); sl@0: sl@0: stream = OWF_DisplayContext_FastpathStream(context->displayContext); sl@0: if (screenRotation) sl@0: { sl@0: switch (context->rotation) sl@0: { sl@0: case WFC_ROTATION_0: sl@0: { sl@0: rotation = OWF_ROTATION_0; sl@0: break; sl@0: } sl@0: case WFC_ROTATION_90: sl@0: { sl@0: rotation = OWF_ROTATION_90; sl@0: break; sl@0: } sl@0: case WFC_ROTATION_180: sl@0: { sl@0: rotation = OWF_ROTATION_180; sl@0: break; sl@0: } sl@0: case WFC_ROTATION_270: sl@0: { sl@0: rotation = OWF_ROTATION_270; sl@0: break; sl@0: } sl@0: default: sl@0: { sl@0: OWF_ASSERT(0); sl@0: rotation = OWF_ROTATION_0; sl@0: } sl@0: } sl@0: } sl@0: sl@0: if (!OWF_Screen_Post_Topmost_Layer(context->displayContext, stream, rotation)) sl@0: { sl@0: sl@0: DPRINT(("WFC_Context_Compose calls OWF_DisplayContext_DisableFastpath because !OWF_Screen_Post_Topmost_Layer()")); sl@0: OWF_DisplayContext_DisableFastpath(context->displayContext); sl@0: //If fastpath is disabled here then we need to compose properly this cycle sl@0: } sl@0: } sl@0: targetStreamAccessed = OWF_DisplayContext_InternalStreamAccessed(context->displayContext); sl@0: if (OWF_DisplayContext_FastpathEnabled(context->displayContext) && ( targetStreamAccessed || !WFC_Context_Active(context) )) sl@0: { //Fastpath in non-autonomous composition just does a simple copy and post. sl@0: DPRINT(("== WFC_Context_DoCompose(context = %p) - fastpath copy target", context)); sl@0: if (WFC_Context_LockTargetForWriting(context)) sl@0: { sl@0: OWFboolean copy; sl@0: if (screenRotation) sl@0: { sl@0: if (WFC_ROTATION_90 == context->rotation || WFC_ROTATION_270 == context->rotation) sl@0: { sl@0: owfSetStreamFlipState(context->stream, OWF_TRUE); sl@0: } sl@0: else sl@0: { sl@0: owfSetStreamFlipState(context->stream, OWF_FALSE); sl@0: } sl@0: } sl@0: copy=OWF_DisplayContext_CopyFastpathedStreamToTargetStream(context); sl@0: if (!WFC_Context_Active(context)) sl@0: { sl@0: if (!copy) sl@0: { sl@0: DPRINT(("WFC_Context_Compose calls OWF_DisplayContext_DisableFastpath because !OWF_DisplayContext_CopyFastpathedStreamToTargetStream()")); sl@0: OWF_DisplayContext_DisableFastpath(context->displayContext); sl@0: //If fastpath is disabled here then we need to compose properly this cycle sl@0: } sl@0: } sl@0: else sl@0: { sl@0: copy=OWF_FALSE; sl@0: } sl@0: sl@0: WFC_Context_UnlockTarget(context,copy); sl@0: } sl@0: else sl@0: { sl@0: //If non-autonomous, then the lock target is required. sl@0: OWF_ASSERT(WFC_Context_Active(context)); sl@0: } sl@0: sl@0: } sl@0: if (OWF_DisplayContext_FastpathEnabled(context->displayContext)) sl@0: { sl@0: WFC_ELEMENT* topmostElement = NULL; sl@0: topmostElement = WFC_Scene_TopMostElement(context->committedScene); sl@0: owfSymElementNotifications(context, topmostElement); sl@0: } sl@0: } sl@0: if (!OWF_DisplayContext_FastpathEnabled(context->displayContext)) sl@0: { sl@0: DPRINT(("== WFC_Context_DoCompose(context = %p) - Composing", context)); sl@0: WFC_Context_PrepareComposition(context); sl@0: sl@0: scene = context->committedScene; sl@0: OWF_ASSERT(scene); sl@0: sl@0: for (node = scene->elements; NULL != node; node = node->next) sl@0: { sl@0: sl@0: WFC_ELEMENT* element = NULL; sl@0: WFC_ELEMENT_STATE* elementState = NULL; sl@0: element = ELEMENT(node->data); sl@0: sl@0: if (element->skipCompose) sl@0: { sl@0: /* this element is somehow degraded, its source is missing or sl@0: * something else; skip to next element */ sl@0: DPRINT((" *** Skipping element %d", element->handle)); sl@0: continue; sl@0: } sl@0: sl@0: DPRINT((" Composing element %d", element->handle)); sl@0: sl@0: /* BeginComposition may fail e.g. if the element's destination sl@0: * rectangle is something bizarre, i.e. causes overflows or sl@0: * something. sl@0: */ sl@0: if ((elementState=WFC_Pipeline_BeginComposition(context, element))!=NULL) sl@0: { sl@0: owfSymElementNotifications(context, element); sl@0: sl@0: WFC_Pipeline_ExecuteSourceConversionStage(context, elementState); sl@0: WFC_Pipeline_ExecuteCropStage(context, elementState); sl@0: WFC_Pipeline_ExecuteFlipStage(context, elementState); sl@0: WFC_Pipeline_ExecuteRotationStage(context, elementState); sl@0: WFC_Pipeline_ExecuteScalingStage(context, elementState); sl@0: WFC_Pipeline_ExecuteBlendingStage(context, elementState); sl@0: sl@0: WFC_Pipeline_EndComposition(context, element,elementState); sl@0: } sl@0: } sl@0: sl@0: WFC_Context_FinishComposition(context); sl@0: DPRINT(("=== WFC_Context_DoCompose(context = %p) - Diplayed Composition", context)); sl@0: } sl@0: sl@0: WFC_Scene_UnlockSourcesAndMasks(context->committedScene); sl@0: owfSymProcessAllNotifications(context); sl@0: OWF_Mutex_Unlock(&context->sceneMutex); sl@0: sl@0: OWF_Semaphore_Post(&context->compositionSemaphore); sl@0: } sl@0: sl@0: /*--------------------------------------------------------------------------- sl@0: * Activate/deactivate auto-composition on context sl@0: * sl@0: * \param context Context sl@0: * \param act Auto-composition enable/disable sl@0: *----------------------------------------------------------------------------*/ sl@0: OWF_API_CALL void sl@0: WFC_Context_Activate(WFC_CONTEXT* context, sl@0: WFCboolean act) sl@0: { sl@0: OWF_ASSERT(context); sl@0: sl@0: DPRINT(("WFC_Context_Activate: %s", (act) ? "activate" : "deactivate")); sl@0: sl@0: if (act && !WFC_Context_Active(context)) sl@0: { sl@0: DPRINT(("WFC_Context_Activate: WFC_CONTEXT_STATE_PASSIVE: activating")); sl@0: context->activationState = WFC_CONTEXT_STATE_ACTIVATING; sl@0: sl@0: /* moved from composer loop - updates must be allowed sl@0: * immediately after activation sl@0: */ sl@0: WFC_Device_EnableContentNotifications(context->device, sl@0: context, sl@0: WFC_TRUE); sl@0: sl@0: OWF_Message_Send(&context->composerQueue, sl@0: WFC_MESSAGE_ACTIVATE, sl@0: 0); sl@0: } sl@0: else if (!act && WFC_Context_Active(context)) sl@0: { sl@0: DPRINT(("WFC_Context_Activate: WFC_CONTEXT_STATE_ACTIVE: deactivating")); sl@0: context->activationState = WFC_CONTEXT_STATE_DEACTIVATING; sl@0: OWF_Message_Send(&context->composerQueue, sl@0: WFC_MESSAGE_DEACTIVATE, sl@0: 0); sl@0: } sl@0: } sl@0: sl@0: /*--------------------------------------------------------------------------- sl@0: * sl@0: *----------------------------------------------------------------------------*/ sl@0: OWF_API_CALL WFCboolean sl@0: WFC_Context_InvokeComposition(WFC_DEVICE* device, sl@0: WFC_CONTEXT* context, sl@0: WFCboolean wait) sl@0: { sl@0: WFCint status = 0; sl@0: sl@0: OWF_ASSERT(context); sl@0: OWF_ASSERT(device); sl@0: sl@0: device = device; /* suppress the compiler warning */ sl@0: sl@0: status = OWF_Semaphore_TryWait(&context->compositionSemaphore); sl@0: if (status) sl@0: { sl@0: if (!wait) sl@0: { sl@0: /* busy; processing last request */ sl@0: return WFC_FALSE; sl@0: } sl@0: /* wait previous frame composition to finish */ sl@0: OWF_Semaphore_Wait(&context->compositionSemaphore); sl@0: } sl@0: sl@0: /* compositionSemaphore is posted/signaled in WFC_Context_Compose() sl@0: after frame has been successfully composed */ sl@0: OWF_Message_Send(&context->composerQueue, WFC_MESSAGE_COMPOSE, 0); sl@0: sl@0: return WFC_TRUE; sl@0: } sl@0: sl@0: /*--------------------------------------------------------------------------- sl@0: * sl@0: *----------------------------------------------------------------------------*/ sl@0: OWF_API_CALL WFCErrorCode sl@0: WFC_Context_InvokeCommit(WFC_DEVICE* device, sl@0: WFC_CONTEXT* context, sl@0: WFCboolean wait) sl@0: { sl@0: WFCint status = 0; sl@0: sl@0: OWF_ASSERT(context); sl@0: OWF_ASSERT(device); sl@0: sl@0: device = device; /* suppress the compiler warning */ sl@0: sl@0: /* first check if there're inconsistensies in the scene */ sl@0: if (WFC_Scene_HasConflicts(context->workScene)) sl@0: { sl@0: DPRINT(("WFC_Context_InvokeCommit: scene has inconsistensies")); sl@0: return WFC_ERROR_INCONSISTENCY; sl@0: } sl@0: sl@0: /* then commit - always asynchronously */ sl@0: status = OWF_Semaphore_TryWait(&context->commitSemaphore); sl@0: DPRINT(("COMMIT: Commit semaphore status = %d", status)); sl@0: if (status) sl@0: { sl@0: if (!wait) sl@0: { sl@0: DPRINT(("COMMIT: Busy; exiting.")); sl@0: /* busy; processing last commit */ sl@0: return WFC_ERROR_BUSY; sl@0: } sl@0: sl@0: DPRINT(("COMMIT: Waiting for previous commit to finish.")); sl@0: /* wait previous commit to finish */ sl@0: OWF_Semaphore_Wait(&context->commitSemaphore); sl@0: } sl@0: sl@0: /* comitting scene attribute changes */ sl@0: DPRINT(("COMMIT: Cloning scene attribute changes")); sl@0: OWF_AttributeList_Commit(&context->attributes, sl@0: WFC_CONTEXT_TYPE, sl@0: WFC_CONTEXT_BG_COLOR,SNAPSHOT_ATTR_VALUE_INDEX); sl@0: sl@0: DPRINT(("COMMIT: Cloning scene")); sl@0: /* take snapshot of the current working copy - it will sl@0: * be the new committed scene */ sl@0: context->snapshotScene = WFC_Scene_Clone(context->workScene); sl@0: sl@0: DPRINT(("COMMIT: Sending commit request")); sl@0: /* invoke async commit */ sl@0: OWF_Message_Send(&context->composerQueue, WFC_MESSAGE_COMMIT, 0); sl@0: return WFC_ERROR_NONE; sl@0: } sl@0: sl@0: /*--------------------------------------------------------------------------- sl@0: * \param context sl@0: * \param dpy sl@0: * \param sync sl@0: *----------------------------------------------------------------------------*/ sl@0: OWF_API_CALL void sl@0: WFC_Context_InsertFence(WFC_CONTEXT* context, sl@0: WFCEGLDisplay dpy, sl@0: WFCEGLSync sync) sl@0: { sl@0: OWF_ASSERT(context); sl@0: OWF_ASSERT(sync); sl@0: sl@0: DPRINT(("WFC_Context_InsertFence: Sending fence sync: 0x%08x", sync)); sl@0: sl@0: OWF_Message_Send(&context->composerQueue, WFC_MESSAGE_FENCE_1_DISPLAY, (void*) dpy); sl@0: OWF_Message_Send(&context->composerQueue, WFC_MESSAGE_FENCE_2_SYNCOBJECT, sync); sl@0: } sl@0: sl@0: /*--------------------------------------------------------------------------- sl@0: * Insert element into context's scene sl@0: * sl@0: * \param context sl@0: * \param element sl@0: * \param subordinate sl@0: * sl@0: * \return WFCErrorCode sl@0: *----------------------------------------------------------------------------*/ sl@0: OWF_API_CALL WFCErrorCode sl@0: WFC_Context_InsertElement(WFC_CONTEXT* context, sl@0: WFCElement element, sl@0: WFCElement subordinate) sl@0: { sl@0: WFC_ELEMENT* object = NULL; sl@0: WFCErrorCode result = WFC_ERROR_BAD_HANDLE; sl@0: sl@0: OWF_ASSERT(context); sl@0: sl@0: object = WFC_Device_FindElement(context->device, element); sl@0: sl@0: if (NULL != object && CONTEXT(object->context) == context) sl@0: { sl@0: /* set the sharing flag as the element will be sl@0: * shared between the device and working copy scene. sl@0: * this is to tell the scene that it must not destroy sl@0: * this element. sl@0: */ sl@0: object->shared = WFC_TRUE; sl@0: result = WFC_Scene_InsertElement(context->workScene, sl@0: object, sl@0: subordinate); sl@0: sl@0: context->lowestElement = WFC_Scene_LowestElement(context->workScene); sl@0: } sl@0: return result; sl@0: } sl@0: sl@0: /*--------------------------------------------------------------------------- sl@0: * Remove element from context's scene sl@0: * sl@0: * \param context sl@0: * \param element sl@0: * sl@0: * \return WFCErrorCode sl@0: *----------------------------------------------------------------------------*/ sl@0: OWF_API_CALL WFCErrorCode sl@0: WFC_Context_RemoveElement(WFC_CONTEXT* context, sl@0: WFCElement element) sl@0: { sl@0: WFC_ELEMENT* elemento = NULL; sl@0: sl@0: OWF_ASSERT(context); sl@0: sl@0: elemento = WFC_Context_FindElement(context, element); sl@0: sl@0: if (elemento) sl@0: { sl@0: WFC_Scene_RemoveElement(context->workScene, element); sl@0: /* the element is no longer shared, as it only resides sl@0: * in device from this point on sl@0: */ sl@0: elemento->shared = WFC_FALSE; sl@0: context->lowestElement = WFC_Scene_LowestElement(context->workScene); sl@0: } sl@0: sl@0: return WFC_ERROR_NONE; sl@0: } sl@0: sl@0: /*! sl@0: * \brief IncreaseClientElementCount sl@0: * sl@0: * \param context sl@0: * \return positive increased current element count; negative or zero indicating the count can't be increased sl@0: */ sl@0: OWF_API_CALL WFCint sl@0: WFC_Context_IncreaseClientElementCount(WFC_CONTEXT* context) sl@0: { sl@0: /* This implementation simply caps the number of elements allocated to the client sl@0: * to 1/3 of the total elements. sl@0: * A cleverer strategy would allow the client to create more elements sl@0: * so long as the number added to the scene *2 did not exceed the spare pool size. sl@0: * These failure points are also a good place to consider increasing the pool size sl@0: */ sl@0: if (context->clientElementCount>=MAX_ELEMENTS) sl@0: { sl@0: return -context->clientElementCount; sl@0: } sl@0: else sl@0: { sl@0: return ++context->clientElementCount; sl@0: } sl@0: } sl@0: sl@0: /*! sl@0: * \brief DecreaseClientElementCount sl@0: * sl@0: * \param context sl@0: * \return positive or zero decreased current element count; negative indicating the count can't be decreased - p0robably already zero sl@0: */ sl@0: OWF_API_CALL WFCint sl@0: WFC_Context_DecreaseClientElementCount(WFC_CONTEXT* context) sl@0: { sl@0: /* note that a negative return indicates that decrements are not matched with increments */ sl@0: return --context->clientElementCount; sl@0: } sl@0: sl@0: /*--------------------------------------------------------------------------- sl@0: * sl@0: *----------------------------------------------------------------------------*/ sl@0: OWF_API_CALL WFCErrorCode sl@0: WFC_Context_GetElementAbove(WFC_CONTEXT* context, sl@0: WFCElement element, sl@0: WFCElement* result) sl@0: { sl@0: WFC_ELEMENT* object = NULL; sl@0: WFCErrorCode error = WFC_ERROR_ILLEGAL_ARGUMENT; sl@0: sl@0: OWF_ASSERT(context); sl@0: OWF_ASSERT(result); sl@0: sl@0: object = WFC_Context_FindElement(context, element); sl@0: sl@0: if (object) sl@0: { sl@0: WFCElement temp; sl@0: sl@0: temp = WFC_Scene_GetNeighbourElement(context->workScene, element, 1); sl@0: *result = temp; sl@0: error = WFC_ERROR_NONE; sl@0: } sl@0: return error; sl@0: } sl@0: sl@0: /*--------------------------------------------------------------------------- sl@0: * sl@0: *----------------------------------------------------------------------------*/ sl@0: OWF_API_CALL WFCErrorCode sl@0: WFC_Context_GetElementBelow(WFC_CONTEXT* context, sl@0: WFCElement element, sl@0: WFCElement* result) sl@0: { sl@0: WFC_ELEMENT* object = NULL; sl@0: WFCErrorCode error = WFC_ERROR_ILLEGAL_ARGUMENT; sl@0: sl@0: OWF_ASSERT(context); sl@0: OWF_ASSERT(result); sl@0: sl@0: object = WFC_Context_FindElement(context, element); sl@0: if (object) sl@0: { sl@0: WFCElement temp; sl@0: sl@0: temp = WFC_Scene_GetNeighbourElement(context->workScene, element, -1); sl@0: *result = temp; sl@0: error = WFC_ERROR_NONE; sl@0: } sl@0: return error; sl@0: } sl@0: sl@0: /*--------------------------------------------------------------------------- sl@0: * sl@0: *----------------------------------------------------------------------------*/ sl@0: OWF_API_CALL WFCErrorCode sl@0: WFC_Context_GetAttribi(WFC_CONTEXT* context, sl@0: WFCContextAttrib attrib, sl@0: WFCint* value) sl@0: { sl@0: WFCint temp = 0; sl@0: OWF_ATTRIBUTE_LIST_STATUS err; sl@0: WFCErrorCode result = WFC_ERROR_NONE; sl@0: sl@0: OWF_ASSERT(context); sl@0: OWF_ASSERT(value); sl@0: sl@0: temp = OWF_Attribute_GetValuei(&context->attributes, attrib); sl@0: err = OWF_AttributeList_GetError(&context->attributes); sl@0: sl@0: if (err != ATTR_ERROR_NONE) sl@0: { sl@0: result = WFC_ERROR_BAD_ATTRIBUTE; sl@0: } sl@0: else sl@0: { sl@0: *value = temp; sl@0: } sl@0: return result; sl@0: } sl@0: sl@0: /*--------------------------------------------------------------------------- sl@0: * sl@0: *----------------------------------------------------------------------------*/ sl@0: OWF_API_CALL WFCErrorCode sl@0: WFC_Context_SetAttribi(WFC_CONTEXT* context, sl@0: WFCContextAttrib attrib, sl@0: WFCint value) sl@0: { sl@0: WFCErrorCode result = WFC_ERROR_NONE; sl@0: sl@0: OWF_ASSERT(context); sl@0: sl@0: /* check value */ sl@0: switch (attrib) sl@0: { sl@0: case WFC_CONTEXT_BG_COLOR: sl@0: { sl@0: OWFint alpha; sl@0: sl@0: /* sl@0: * Color format is RGBA NOT RGBA. sl@0: */ sl@0: alpha = value & 0xFF; sl@0: sl@0: if (WFC_CONTEXT_TYPE_ON_SCREEN == context->type) sl@0: { sl@0: /* the only allowed value for on-screen context sl@0: * background alpha is 255 */ sl@0: if (alpha != 255) sl@0: { sl@0: result = WFC_ERROR_ILLEGAL_ARGUMENT; sl@0: } sl@0: } sl@0: break; sl@0: } sl@0: sl@0: case WFC_CONTEXT_ROTATION: sl@0: { sl@0: if (!(WFC_ROTATION_0 == value || sl@0: WFC_ROTATION_90 == value || sl@0: WFC_ROTATION_180 == value || sl@0: WFC_ROTATION_270 == value)) sl@0: { sl@0: result = WFC_ERROR_ILLEGAL_ARGUMENT; sl@0: } sl@0: else sl@0: { sl@0: OWF_DisplayContext_ResetFastpathCheck(context->displayContext); sl@0: } sl@0: break; sl@0: } sl@0: sl@0: case WFC_CONTEXT_TYPE: sl@0: case WFC_CONTEXT_TARGET_HEIGHT: sl@0: case WFC_CONTEXT_TARGET_WIDTH: sl@0: case WFC_CONTEXT_LOWEST_ELEMENT: sl@0: { sl@0: result = WFC_ERROR_BAD_ATTRIBUTE; sl@0: break; sl@0: } sl@0: sl@0: case WFC_CONTEXT_FORCE_32BIT: sl@0: default: sl@0: { sl@0: result = WFC_ERROR_BAD_ATTRIBUTE; sl@0: break; sl@0: } sl@0: } sl@0: sl@0: if (WFC_ERROR_NONE == result) sl@0: { sl@0: OWF_ATTRIBUTE_LIST_STATUS error; sl@0: sl@0: /* try changing the value */ sl@0: OWF_Attribute_SetValuei(&context->attributes, attrib, value); sl@0: error = OWF_AttributeList_GetError(&context->attributes); sl@0: sl@0: /* transform errors */ sl@0: switch (error) { sl@0: case ATTR_ERROR_ACCESS_DENIED: sl@0: case ATTR_ERROR_INVALID_ATTRIBUTE: sl@0: { sl@0: result = WFC_ERROR_BAD_ATTRIBUTE; sl@0: break; sl@0: } sl@0: default: sl@0: { sl@0: break; sl@0: } sl@0: } sl@0: } sl@0: sl@0: return result; sl@0: } sl@0: sl@0: /*--------------------------------------------------------------------------- sl@0: * sl@0: *----------------------------------------------------------------------------*/ sl@0: OWF_API_CALL WFCErrorCode sl@0: WFC_Context_GetAttribfv(WFC_CONTEXT* context, sl@0: WFCContextAttrib attrib, sl@0: WFCint count, sl@0: WFCfloat* values) sl@0: { sl@0: WFCErrorCode result = WFC_ERROR_NONE; sl@0: sl@0: OWF_ASSERT(context); sl@0: OWF_ASSERT(values); sl@0: sl@0: switch (attrib) sl@0: { sl@0: case WFC_CONTEXT_BG_COLOR: sl@0: { sl@0: if (4 != count) sl@0: { sl@0: result = WFC_ERROR_ILLEGAL_ARGUMENT; sl@0: } sl@0: else sl@0: { sl@0: OWFuint32 color; sl@0: OWF_ATTRIBUTE_LIST_STATUS err; sl@0: sl@0: color = OWF_Attribute_GetValuei(&context->attributes, attrib); sl@0: err = OWF_AttributeList_GetError(&context->attributes); sl@0: sl@0: if (err != ATTR_ERROR_NONE) sl@0: { sl@0: result = WFC_ERROR_BAD_ATTRIBUTE; sl@0: break; sl@0: } sl@0: sl@0: /* extract color channels and convert to float */ sl@0: values[0] = (WFCfloat) (color >> 24) / sl@0: (WFCfloat) OWF_BYTE_MAX_VALUE; sl@0: values[1] = (WFCfloat) ((color >> 16) & 0xFF) / sl@0: (WFCfloat) OWF_BYTE_MAX_VALUE; sl@0: values[2] = (WFCfloat) ((color >> 8) & 0xFF) / sl@0: (WFCfloat) OWF_BYTE_MAX_VALUE; sl@0: values[3] = (WFCfloat) (color & 0xFF) / sl@0: (WFCfloat) OWF_BYTE_MAX_VALUE; sl@0: } sl@0: break; sl@0: } sl@0: sl@0: default: sl@0: { sl@0: result = WFC_ERROR_BAD_ATTRIBUTE; sl@0: break; sl@0: } sl@0: } sl@0: sl@0: return result; sl@0: } sl@0: sl@0: /*--------------------------------------------------------------------------- sl@0: * sl@0: *----------------------------------------------------------------------------*/ sl@0: OWF_API_CALL WFCErrorCode sl@0: WFC_Context_SetAttribfv(WFC_CONTEXT* context, sl@0: WFCContextAttrib attrib, sl@0: WFCint count, sl@0: const WFCfloat* values) sl@0: { sl@0: WFCErrorCode result = WFC_ERROR_NONE; sl@0: sl@0: OWF_ASSERT(context); sl@0: OWF_ASSERT(values); sl@0: sl@0: switch (attrib) sl@0: { sl@0: case WFC_CONTEXT_BG_COLOR: sl@0: { sl@0: if (4 != count) sl@0: { sl@0: result = WFC_ERROR_ILLEGAL_ARGUMENT; sl@0: } sl@0: else sl@0: { sl@0: OWFuint32 color; sl@0: sl@0: /* Every color component value must fall within range [0, 1] */ sl@0: if (INRANGE(values[0], 0.0f, 1.0f) && sl@0: INRANGE(values[1], 0.0f, 1.0f) && sl@0: INRANGE(values[2], 0.0f, 1.0f) && sl@0: INRANGE(values[3], 0.0f, 1.0f)) sl@0: { sl@0: color = (((OWFuint32) floor(values[0] * 255)) << 24) | sl@0: (((OWFuint32) floor(values[1] * 255)) << 16) | sl@0: (((OWFuint32) floor(values[2] * 255)) << 8) | sl@0: ((OWFuint32) floor(values[3] * 255)); sl@0: sl@0: /* delegate to integer accessor - it'll check the sl@0: * the rest of the value and update it eventually */ sl@0: result = WFC_Context_SetAttribi(context, attrib, color); sl@0: } sl@0: else sl@0: { sl@0: result = WFC_ERROR_ILLEGAL_ARGUMENT; sl@0: } sl@0: } sl@0: break; sl@0: } sl@0: sl@0: default: sl@0: { sl@0: result = WFC_ERROR_BAD_ATTRIBUTE; sl@0: break; sl@0: } sl@0: } sl@0: sl@0: return result; sl@0: } sl@0: sl@0: sl@0: static void sl@0: WFC_Context_AutoComposer(WFC_CONTEXT* context) sl@0: { sl@0: OWF_Mutex_Lock(&context->updateFlagMutex); sl@0: if (context->sourceUpdateCount > 0) sl@0: { sl@0: DPRINT(("WFC_Context_ComposerThread: %d sources were updated, " sl@0: "invoking composition\n", sl@0: context->sourceUpdateCount)); sl@0: sl@0: /* reset update counter */ sl@0: sl@0: OWF_Mutex_Unlock(&context->updateFlagMutex); sl@0: WFC_Context_DoCompose(context); sl@0: } sl@0: else sl@0: { sl@0: OWF_Mutex_Unlock(&context->updateFlagMutex); sl@0: } sl@0: } sl@0: sl@0: /*--------------------------------------------------------------------------- sl@0: * sl@0: *----------------------------------------------------------------------------*/ sl@0: static void* sl@0: WFC_Context_ComposerThread(void* data) sl@0: { sl@0: WFC_CONTEXT* context = (WFC_CONTEXT*) data; sl@0: OWFboolean screenCreated = OWF_TRUE; sl@0: OWF_MESSAGE msg; sl@0: sl@0: sl@0: OWF_ASSERT(context); sl@0: DPRINT(("WFC_Context_ComposerThread starting")); sl@0: sl@0: memset(&msg, 0, sizeof(OWF_MESSAGE)); sl@0: sl@0: if (context->type == WFC_CONTEXT_TYPE_ON_SCREEN) sl@0: { sl@0: screenCreated = OWF_Screen_Create(context->screenNumber, context->displayContext); sl@0: } sl@0: sl@0: OWF_ComposerThread_Rendezvous(context->displayContext); sl@0: sl@0: OWF_ComposerThread_RendezvousDestroy(context->displayContext); sl@0: sl@0: while (context->device && msg.id != WFC_MESSAGE_QUIT && screenCreated) sl@0: { sl@0: OWFint err = -1; sl@0: sl@0: if (WFC_CONTEXT_STATE_ACTIVE == context->activationState) sl@0: { sl@0: err = OWF_Message_Wait(&context->composerQueue, sl@0: &msg, sl@0: AUTO_COMPOSE_DELAY); sl@0: sl@0: WFC_Context_AutoComposer(context); sl@0: } sl@0: else sl@0: { sl@0: DPRINT((" ComposerThread waiting for message")); sl@0: err = OWF_Message_Wait(&context->composerQueue, &msg, WAIT_FOREVER); sl@0: } sl@0: sl@0: if (0 == err) sl@0: { sl@0: switch (msg.id) sl@0: { sl@0: case WFC_MESSAGE_ACTIVATE: sl@0: { sl@0: DPRINT(("****** ENABLING AUTO-COMPOSITION ******")); sl@0: context->activationState = WFC_CONTEXT_STATE_ACTIVE; sl@0: break; sl@0: } sl@0: sl@0: case WFC_MESSAGE_DEACTIVATE: sl@0: { sl@0: /* cancel possible countdown so that update won't occur sl@0: * after deactivation */ sl@0: DPRINT(("****** DISABLING AUTO-COMPOSITION ******")); sl@0: WFC_Device_EnableContentNotifications(context->device, sl@0: context, sl@0: WFC_FALSE); sl@0: context->activationState = WFC_CONTEXT_STATE_PASSIVE; sl@0: if (OWF_DisplayContext_FastpathEnabled(context->displayContext)) sl@0: { sl@0: DPRINT(("COMMIT: Invoking fastpath recomposition after deactivate")); sl@0: WFC_Context_DoCompose(context); sl@0: } sl@0: break; sl@0: } sl@0: sl@0: case WFC_MESSAGE_COMMIT: sl@0: { sl@0: DPRINT(("****** COMMITTING SCENE CHANGES ******")); sl@0: sl@0: DPRINT(("COMMIT: Invoking DoCommit")); sl@0: WFC_Context_DoCommit(context); sl@0: OWF_DisplayContext_ResetFastpathCheck(context->displayContext); sl@0: if (!WFC_Context_Active(context)) sl@0: { sl@0: DPRINT(("COMMIT: Context is inactive, composition " sl@0: "not needed.", context->handle)); sl@0: break; sl@0: } sl@0: else sl@0: { sl@0: /* context is active; compose immediately after sl@0: * commit has completed */ sl@0: sl@0: DPRINT(("COMMIT: Invoking composition after commit")); sl@0: } sl@0: /* FLOW THROUGH */ sl@0: } sl@0: sl@0: case WFC_MESSAGE_COMPOSE: sl@0: { sl@0: DPRINT(("****** COMPOSING SCENE ******")); sl@0: sl@0: WFC_Context_DoCompose(context); sl@0: sl@0: break; sl@0: } sl@0: sl@0: case WFC_MESSAGE_FENCE_1_DISPLAY: sl@0: { sl@0: DPRINT(("****** STORING EGLDISPLAY (%p) ******", msg.data)); sl@0: sl@0: context->nextSyncObjectDisplay = (WFCEGLDisplay)msg.data; sl@0: break; sl@0: } sl@0: sl@0: case WFC_MESSAGE_FENCE_2_SYNCOBJECT: sl@0: { sl@0: DPRINT(("****** BREAKING FENCE (%p) ******", msg.data)); sl@0: OWF_ASSERT(context->eglPrivateSignalSync); sl@0: sl@0: context->eglPrivateSignalSync(context->nextSyncObjectDisplay, sl@0: (WFCEGLSync) msg.data, sl@0: EGL_SIGNALED_KHR); sl@0: break; sl@0: } sl@0: } sl@0: } sl@0: } sl@0: sl@0: if (context->type == WFC_CONTEXT_TYPE_ON_SCREEN) sl@0: { sl@0: OWF_Screen_Destroy(context->displayContext); sl@0: } sl@0: /* Release any use of EGL by this thread. */ sl@0: eglReleaseThread(); sl@0: sl@0: DPRINT(("WFC_Context_ComposerThread terminating")); sl@0: OWF_Thread_Exit(NULL); sl@0: return NULL; sl@0: } sl@0: sl@0: /*--------------------------------------------------------------------------- sl@0: * sl@0: *----------------------------------------------------------------------------*/ sl@0: OWF_API_CALL WFCboolean sl@0: WFC_Context_Active(WFC_CONTEXT* context) sl@0: { sl@0: OWF_ASSERT(context); sl@0: sl@0: return (WFC_CONTEXT_STATE_ACTIVE == context->activationState || sl@0: WFC_CONTEXT_STATE_ACTIVATING == context->activationState) ? WFC_TRUE : WFC_FALSE; sl@0: } sl@0: sl@0: #ifdef __cplusplus sl@0: } sl@0: #endif sl@0: