os/graphics/graphicscomposition/openwfcompositionengine/composition/src/wfccontext.c
author sl@SLION-WIN7.fritz.box
Fri, 15 Jun 2012 03:10:57 +0200
changeset 0 bde4ae8d615e
permissions -rw-r--r--
First public contribution.
     1 /* Copyright (c) 2009 The Khronos Group Inc.
     2  * Portions copyright (c) 2009-2010  Nokia Corporation and/or its subsidiary(-ies)
     3  *
     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:
    11  *
    12  * The above copyright notice and this permission notice shall be included
    13  * in all copies or substantial portions of the Materials.
    14  *
    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.
    22  */
    23 
    24 /*! \ingroup wfc
    25  *  \file wfccontext.c
    26  *
    27  *  \brief SI Context handling
    28  */
    29 
    30 #include <string.h>
    31 #include <stdio.h>
    32 #include <time.h>
    33 #include <stdlib.h>
    34 #include <math.h>
    35 
    36 #include <WF/wfc.h>
    37 #include <EGL/egl.h>
    38 
    39 #include "wfccontext.h"
    40 #include "wfcpipeline.h"
    41 
    42 #include "owfscreen.h"
    43 #include "owfdisplaycontextgeneral.h"
    44 #include "owfnotifications.h"
    45 
    46 
    47 /*! maximum number of elements per scene */
    48 #define MAX_ELEMENTS            512
    49 /*! maximum number of scenes per context */
    50 #define MAX_SCENES              3
    51 
    52 
    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
    56 
    57 /*! almost 2^31 */
    58 #define MAX_DELAY               2100000000
    59 
    60 /*! 15ms */
    61 #define AUTO_COMPOSE_DELAY      15000
    62 #define FIRST_CONTEXT_HANDLE    2000
    63 
    64 #ifdef __cplusplus
    65 extern "C" {
    66 #endif
    67 
    68 static WFCHandle                nextContextHandle = FIRST_CONTEXT_HANDLE;
    69 
    70 typedef enum
    71 {
    72     WFC_MESSAGE_NONE,
    73     WFC_MESSAGE_QUIT,
    74     WFC_MESSAGE_COMPOSE,
    75     WFC_MESSAGE_COMMIT,
    76     WFC_MESSAGE_FENCE_1_DISPLAY,
    77     WFC_MESSAGE_FENCE_2_SYNCOBJECT,
    78     WFC_MESSAGE_ACTIVATE,
    79     WFC_MESSAGE_DEACTIVATE,
    80     WFC_MESSAGE_START_COUNTDOWN,
    81     WFC_MESSAGE_CANCEL
    82 } WFC_MESSAGES;
    83 
    84 static void*
    85 WFC_Context_ComposerThread(void* data);
    86 
    87 
    88 /*---------------------------------------------------------------------------
    89  *
    90  *----------------------------------------------------------------------------*/
    91 void WFC_CONTEXT_Ctor(void* self)
    92 {
    93     self = self;
    94 }
    95 
    96 /*---------------------------------------------------------------------------*/
    97 static WFCboolean
    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,
   101                             fExt;
   102     WFCint                  stride = 0;
   103     OWF_ASSERT(context);
   104 
   105     DPRINT(("WFC_Context_CreateContextState"));
   106 
   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;
   113     fInt.rowPadding     = 1;
   114      
   115     if (context->type == WFC_CONTEXT_TYPE_ON_SCREEN)
   116         {
   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
   121          */ 
   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);
   125             }
   126         else
   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);
   129             }
   130         }
   131     else
   132         {
   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);
   137         }
   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);
   142 
   143     if (context->state.unrotatedTargetImage && context->state.rotatedTargetImage && context->state.unrotatedInternalTargetImage && context->state.rotatedInternalTargetImage)
   144         {
   145         return WFC_TRUE;
   146         }
   147     else
   148         {
   149         return WFC_FALSE;
   150         }
   151     }
   152 /*---------------------------------------------------------------------------*/
   153 static void
   154 WFC_Context_DestroyState(WFC_CONTEXT* context)
   155     {
   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
   160      */ 
   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);
   166     
   167     }
   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)
   173 {
   174     OWFint                  ii = 0;
   175     WFC_CONTEXT*            context = NULL;
   176 
   177     OWF_ASSERT(self);
   178     DPRINT(("WFC_CONTEXT_Dtor(%p)", self));
   179 
   180     context = CONTEXT(self);
   181 
   182     OWF_ASSERT(context);
   183     
   184     WFC_Pipeline_DestroyState(context);
   185     WFC_Context_DestroyState(context);
   186     
   187     OWF_MessageQueue_Destroy(&context->composerQueue);
   188 
   189     /* make the stream destroyable */
   190     if (context->stream != OWF_INVALID_HANDLE)
   191         {
   192         owfNativeStreamSetProtectionFlag(context->stream, OWF_FALSE);
   193         owfNativeStreamDestroy(context->stream);
   194         }
   195     context->stream = OWF_INVALID_HANDLE;
   196 
   197     OWF_AttributeList_Destroy(&context->attributes);
   198 
   199     for (ii = 0; ii < SCRATCH_BUFFER_COUNT; ii++)
   200     {
   201         OWF_Image_FreeData(context->displayContext, &context->scratchBuffer[ii]);
   202         context->scratchBuffer[ii] = 0;
   203     }
   204 
   205     OWF_DisplayContext_Destroy(context->screenNumber, context->displayContext);
   206     context->displayContext = NULL;    
   207 
   208     OWF_Pool_Destroy(context->scenePool);
   209     OWF_Pool_Destroy(context->elementPool);
   210     OWF_Pool_Destroy(context->nodePool);
   211 
   212     OWF_Semaphore_Destroy(&context->compositionSemaphore);
   213     OWF_Semaphore_Destroy(&context->commitSemaphore);
   214     OWF_Mutex_Destroy(&context->updateFlagMutex);
   215     OWF_Mutex_Destroy(&context->sceneMutex);
   216 }
   217 
   218 /*---------------------------------------------------------------------------
   219  *
   220  *----------------------------------------------------------------------------*/
   221 OWF_API_CALL void
   222 WFC_Context_Shutdown(WFC_CONTEXT* context)
   223 {
   224     OWF_ASSERT(context);
   225     DPRINT(("WFC_Context_Shutdown(context = %d)", context->handle));
   226 
   227     DPRINT(("Waiting for composer thread termination"));
   228     if (context->composerThread)
   229         {
   230         OWF_Message_Send(&context->composerQueue, WFC_MESSAGE_QUIT, 0);
   231         OWF_Thread_Join(context->composerThread, NULL);
   232         OWF_Thread_Destroy(context->composerThread);
   233         }
   234     
   235     context->composerThread = NULL;
   236 
   237     if (context->device)
   238     {
   239         /* #4604: added guard condition */
   240         WFC_Device_DestroyContextElements(context->device, context);
   241         WFC_Device_DestroyContextImageProviders(context->device, context);
   242     }
   243 
   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;    
   250 }
   251 
   252 /*---------------------------------------------------------------------------
   253  *  Initialize context attributes
   254  *----------------------------------------------------------------------------*/
   255 OWF_API_CALL OWF_ATTRIBUTE_LIST_STATUS
   256 WFC_Context_InitializeAttributes(WFC_CONTEXT* context,
   257                                  WFCContextType type)
   258 {
   259     OWF_ATTRIBUTE_LIST_STATUS attribError=ATTR_ERROR_NONE;
   260     OWF_ASSERT(context);
   261     /* initialize attributes/properties */
   262     if (context->stream)
   263     {
   264         owfNativeStreamGetHeader(context->stream,
   265                                  &context->targetWidth,
   266                                  &context->targetHeight,
   267                                  NULL, NULL, NULL);
   268     }
   269     context->type               = type;
   270     context->rotation           = WFC_ROTATION_0;
   271     context->backgroundColor    = 0x000000FF;
   272     context->lowestElement      = WFC_INVALID_HANDLE;
   273 
   274 
   275     OWF_AttributeList_Create(&context->attributes,
   276                              WFC_CONTEXT_TYPE,
   277                              WFC_CONTEXT_BG_COLOR);
   278     attribError=OWF_AttributeList_GetError(&context->attributes);
   279     if (attribError!=ATTR_ERROR_NONE)
   280         {
   281         OWF_ASSERT(attribError==ATTR_ERROR_NO_MEMORY);
   282         return attribError;
   283         }
   284 
   285   
   286     /* The composition code reads the member variables directly, 
   287      * not via the attribute engine.
   288      */
   289     OWF_Attribute_Initi(&context->attributes,
   290                         WFC_CONTEXT_TYPE,
   291                         (WFCint*) &context->type,
   292                         OWF_TRUE);
   293 
   294     OWF_Attribute_Initi(&context->attributes,
   295                         WFC_CONTEXT_TARGET_WIDTH,
   296                         &context->targetWidth,
   297                         OWF_TRUE);
   298 
   299     OWF_Attribute_Initi(&context->attributes,
   300                         WFC_CONTEXT_TARGET_HEIGHT,
   301                         &context->targetHeight,
   302                         OWF_TRUE);
   303 
   304     OWF_Attribute_Initi(&context->attributes,
   305                         WFC_CONTEXT_ROTATION,
   306                         (WFCint*) &context->rotation,
   307                         OWF_FALSE);
   308 
   309     OWF_Attribute_Initi(&context->attributes,
   310                         WFC_CONTEXT_BG_COLOR,
   311                         (WFCint*) &context->backgroundColor,
   312                         OWF_FALSE);
   313 
   314     OWF_Attribute_Initi(&context->attributes,
   315                         WFC_CONTEXT_LOWEST_ELEMENT,
   316                         (OWFint*) &context->lowestElement,
   317                         OWF_TRUE);
   318     attribError=OWF_AttributeList_GetError(&context->attributes);
   319 	
   320 	/* After commit to working, writable attribute abstracted variables
   321 	must not be written to directly. */
   322     OWF_AttributeList_Commit(&context->attributes,
   323                              WFC_CONTEXT_TYPE,
   324                              WFC_CONTEXT_BG_COLOR,
   325 		             WORKING_ATTR_VALUE_INDEX );
   326 	
   327     return attribError;
   328 }
   329 
   330 
   331 /*---------------------------------------------------------------------------
   332  *
   333  *----------------------------------------------------------------------------*/
   334 static WFC_CONTEXT*
   335 WFC_Context_Initialize(WFC_CONTEXT* context,
   336                        WFC_DEVICE* device,
   337                        WFCNativeStreamType stream,
   338                        WFCContextType type,
   339                        WFCint screenNum)
   340 {
   341     void*                   scratch[SCRATCH_BUFFER_COUNT];
   342     OWFint                  err2    = 0;
   343     OWFint                  ii      = 0,
   344                             nbufs   = 0;
   345     OWFint                  fail    = 0;
   346     OWF_ATTRIBUTE_LIST_STATUS attribStatus = ATTR_ERROR_NONE;
   347     OWF_ASSERT(context);
   348     OWF_ASSERT(device);
   349 
   350     DPRINT(("WFC_Context_Initialize(%p,%p,%d,%d)", context, device, type, screenNum));
   351 
   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;
   359     ++nextContextHandle;
   360 
   361     context->displayContext = OWF_DisplayContext_Create(screenNum);
   362     if (context->displayContext == NULL)
   363         {
   364         DPRINT(("WFC_Context_Initialize(): Could not create display Context"));
   365         return NULL;
   366         }
   367     
   368     context->eglPrivateSignalSync = (TFPtrEglPrivateSignalSyncNok) eglGetProcAddress("egl_Private_SignalSyncNOK");
   369     if (! context->eglPrivateSignalSync)
   370         {
   371         DPRINT(("WFC_Context_Initialize(): Missing EGL extension - egl_Private_SignalSyncNOK extension"));   
   372         return NULL;
   373         }
   374 
   375     err2 =OWF_MessageQueue_Init(&context->composerQueue);
   376     if (err2 != 0)
   377         {
   378         DPRINT(("WFC_Context_Initialize(): Cannot initialise the message queue err(%d)", err2));   
   379         return NULL;
   380         }
   381     
   382     context->composerThread = OWF_Thread_Create(WFC_Context_ComposerThread, context);
   383     if (!(context->composerThread))
   384         {
   385         /* must call these to remove references to context */
   386         DPRINT(("WFC_Context_Initialize(): Failed to create thread!"));
   387         return NULL;
   388         }
   389 
   390     OWF_ComposerThread_RendezvousWait(context->displayContext);
   391     
   392     /*the following section of the code could be pushed to adaptation in future*/
   393     if (type == WFC_CONTEXT_TYPE_ON_SCREEN)
   394     {
   395        OWF_IMAGE_FORMAT        imageFormat;
   396        OWF_SCREEN              screen;
   397        WFCint width = 0;
   398        WFCint height = 0;
   399        WFCint normalSize = 0;
   400        WFCint flippedSize = 0;
   401        WFCNativeStreamType stream;
   402     
   403        /* Set up stream for sending data to screen */
   404        
   405        if (!OWF_Screen_GetHeader(context->displayContext, &screen))
   406        {
   407            DPRINT(("WFC_Context_Initialize(): Could not retrieve the screen parameters"));
   408            WFC_Context_Shutdown(context);
   409            return NULL;
   410        }
   411     
   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;
   417     
   418        width = screen.normal.width;
   419        height = screen.normal.height;
   420        
   421        normalSize = screen.normal.height * screen.normal.stride;
   422        flippedSize = screen.flipped.height * screen.flipped.stride;
   423        
   424        if (flippedSize > normalSize)
   425            {
   426            width = screen.flipped.width;
   427            height = screen.flipped.height;
   428            }
   429        
   430        stream = owfNativeStreamCreateImageStream(width,
   431                                                  height,
   432                                                  &imageFormat,
   433                                                  1);
   434     
   435        if (stream)
   436        {
   437            WFC_Context_SetTargetStream(context, stream);
   438            
   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.
   442             */
   443            owfNativeStreamRemoveReference(stream);
   444        }
   445        else
   446        {
   447            DPRINT(("WFC_Context_Initialize(): cannot create internal target stream"));
   448            WFC_Context_Shutdown(context);
   449            return NULL;
   450        }
   451     }
   452     else
   453     {
   454        WFC_Context_SetTargetStream(context, stream);
   455     }
   456     
   457     nbufs = SCRATCH_BUFFER_COUNT-1;
   458     for (ii = 0; ii < nbufs; ii++)
   459     {
   460         scratch[ii] = OWF_Image_AllocData(context->displayContext, MAX_SOURCE_WIDTH,
   461                 MAX_SOURCE_HEIGHT,
   462                 OWF_IMAGE_ARGB_INTERNAL);
   463         fail = fail || (scratch[ii] == NULL);
   464     }
   465 
   466     /*
   467      * allocate one-channel buffer for alpha
   468      * obs! this assumes sizeof(OWFsubpixel) is 4.
   469      */
   470     scratch[nbufs] = OWF_Image_AllocData(context->displayContext, MAX_SOURCE_WIDTH,
   471                                          MAX_SOURCE_HEIGHT,
   472                                          OWF_IMAGE_L32);
   473     fail = fail || (scratch[nbufs] == NULL);
   474     
   475     if (fail)
   476     {
   477         for (ii = 0; ii < SCRATCH_BUFFER_COUNT; ii++)
   478         {
   479             OWF_Image_FreeData(context->displayContext, &scratch[ii]);
   480         }
   481         WFC_Context_Shutdown(context);
   482         return NULL;
   483     }
   484 
   485     for (ii = 0; ii < SCRATCH_BUFFER_COUNT; ii++)
   486     {
   487         context->scratchBuffer[ii] = scratch[ii];
   488     }
   489     
   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)
   494         
   495         )
   496         {
   497         DPRINT(("WFC_Context_Initialize(): Could not create mutexes and semaphores!"));
   498         WFC_Context_Shutdown(context);
   499         return NULL;
   500         }
   501 
   502     if (!WFC_Pipeline_CreateState(context) || !WFC_Context_CreateState(context))
   503          {
   504          DPRINT(("WFC_Context_Initialize(): Could not create pipeline state object"));
   505          WFC_Context_Shutdown(context);
   506          return NULL;
   507          }
   508     
   509 
   510     attribStatus= WFC_Context_InitializeAttributes(context, type);
   511 
   512     if (attribStatus!=ATTR_ERROR_NONE)
   513         {
   514         WFC_Context_Shutdown(context);
   515         return NULL;
   516         }
   517     
   518     
   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))
   527     {
   528         WFC_Context_Shutdown(context);
   529         return NULL;
   530     }
   531 
   532     DPRINT(("  Creating scenes"));
   533     context->workScene = WFC_Scene_Create(context);
   534     context->committedScene = WFC_Scene_Create(context);
   535     context->snapshotScene = NULL;
   536 
   537     /* snapshotScene is initialized in InvokeCommit */
   538 
   539     /* context's refcount is now 3 */
   540 
   541     if (!(context->workScene && context->committedScene &&
   542           context->nodePool && context->elementPool))
   543     {
   544         WFC_Context_Shutdown(context);
   545         return NULL;
   546     }
   547 
   548     return context;
   549 }
   550 
   551 /*---------------------------------------------------------------------------
   552  *  Create new context on device
   553  *
   554  *  \param device Device on which the context should be created
   555  *  \param type Context type (on- or off-screen)
   556  *
   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,
   562                    WFCContextType type,
   563                    WFCint screenNum)
   564 {
   565     WFC_CONTEXT*            context = NULL;
   566 
   567     OWF_ASSERT(device);
   568     context = CREATE(WFC_CONTEXT);
   569 
   570     if (context)
   571     {
   572         if (!WFC_Context_Initialize(context, device, stream, type, screenNum))
   573         {
   574             DESTROY(context);
   575         }
   576     }
   577     return context;
   578 }
   579 
   580 /*---------------------------------------------------------------------------
   581  *  Setup context rendering target
   582  *
   583  *  \param context Context
   584  *  \param stream Target stream to use for rendering
   585  *----------------------------------------------------------------------------*/
   586 OWF_API_CALL void
   587 WFC_Context_SetTargetStream(WFC_CONTEXT* context,
   588                             OWFNativeStreamType stream)
   589 {
   590     OWF_ASSERT(context);
   591     context->stream = stream;
   592 
   593     owfNativeStreamAddReference(stream);
   594 
   595     owfNativeStreamGetHeader(stream,
   596                              &context->targetWidth, &context->targetHeight,
   597                              NULL, NULL, NULL);
   598 }
   599 
   600 static OWFboolean
   601 WFC_FastpathCheckTransparency(WFCbitfield transparencyTypes, WFCfloat globalAlpha, OWF_PIXEL_FORMAT sourceFormat)
   602     {
   603     if ((transparencyTypes & WFC_TRANSPARENCY_ELEMENT_GLOBAL_ALPHA) && (globalAlpha != 255.0f))
   604         {
   605         DPRINT(("=== WFC_FastpathCheckTransparency - Failed global alfa(%f) check", globalAlpha));
   606         return OWF_FALSE;
   607         }
   608 
   609     if ((transparencyTypes & WFC_TRANSPARENCY_SOURCE) && (sourceFormat != OWF_IMAGE_XRGB8888))
   610         {
   611         DPRINT(("=== WFC_FastpathCheckTransparency - Failed transparency check types=0x%x format=0x%x", 
   612                 transparencyTypes, sourceFormat));
   613         return OWF_FALSE;
   614         }
   615     
   616 
   617     return OWF_TRUE;
   618     }
   619 
   620 static OWFboolean
   621 WFC_FastpathCheckGeometry(WFC_CONTEXT* context, WFC_ELEMENT* element)
   622     {
   623     OWFint sourceWidth = 0;
   624     OWFint sourceHeight = 0;
   625     OWFint destWidth = 0;
   626     OWFint destHeight = 0;
   627     OWFint targetWidth = 0;
   628     OWFint targetHeight = 0;
   629     
   630     OWF_ASSERT(context);
   631     OWF_ASSERT(element);
   632 
   633     if ((element->srcRect[0] != 0) || (element->srcRect[1] != 0))
   634         {
   635         DPRINT(("=== WFC_FastpathCheckGeometry(context = %p) - FAILED Source Position Check", context));
   636         return OWF_FALSE;
   637         }
   638     
   639     if ((element->dstRect[0] != 0) || (element->dstRect[1] != 0))
   640         {
   641         DPRINT(("=== WFC_FastpathCheckGeometry(context = %p) - FAILED Destination Position Check", context));
   642         return OWF_FALSE;
   643         }
   644     
   645     if(element->sourceFlip)
   646         {
   647         DPRINT(("=== WFC_FastpathCheckGeometry(context = %p) - FAILED Source Flip Check", context));
   648         return OWF_FALSE;
   649         }
   650     
   651     if(element->sourceRotation == WFC_ROTATION_0)
   652         {
   653         sourceWidth = element->srcRect[2];
   654         sourceHeight = element->srcRect[3];
   655         }
   656     else
   657         {
   658         DPRINT(("=== WFC_FastpathCheckGeometry(context = %p) - FAILED Source Rotation (0x%x) Check", 
   659                 context, element->sourceRotation));
   660         return OWF_FALSE;
   661         }
   662     
   663     destWidth = element->dstRect[2];
   664     destHeight = element->dstRect[3];
   665     
   666     if ((sourceWidth != destWidth) || (sourceHeight != destHeight))
   667        {
   668        DPRINT(("=== WFC_FastpathCheckGeometry(context = %p) - FAILED Non-scaling Check", context));
   669        return OWF_FALSE;
   670        }
   671 
   672     if (context->rotation == WFC_ROTATION_0 || OWF_Screen_Rotation_Supported(context->displayContext))
   673         {
   674         if (context->rotation == WFC_ROTATION_0 || context->rotation == WFC_ROTATION_180)
   675             {
   676             targetWidth = context->targetWidth;
   677             targetHeight = context->targetHeight;
   678             }
   679         else
   680             {
   681             targetWidth = context->targetHeight;
   682             targetHeight = context->targetWidth;
   683             }
   684         
   685         if (destWidth == targetWidth && destHeight == targetHeight)
   686             {
   687             return OWF_TRUE;
   688             }
   689         else
   690             {
   691             DPRINT(("=== WFC_FastpathCheckGeometry(context = %p) - Failed Dimensions Check", context));
   692             }
   693         }
   694     else
   695         {
   696         DPRINT(("=== WFC_FastpathCheckGeometry(context = %p) - Failed Supported Rotations Check", context));
   697         }
   698     
   699     return OWF_FALSE;
   700     }
   701 
   702 /**
   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)
   710  *
   711  * @param context context object containing the scene to be checked.
   712  **/
   713 
   714 /* [Not in doxygen]
   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.  
   719  * 
   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. 
   725  */
   726 static void
   727 WFC_Context_CheckFastpath(WFC_CONTEXT* context)
   728     {
   729     WFC_ELEMENT* element = NULL;
   730     OWF_ASSERT(context);
   731     
   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))
   735         {
   736         return;
   737         }
   738     
   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);
   743     // Find top layer
   744     element = WFC_Scene_TopMostElement(context->committedScene);
   745     if (element && element->source && element->skipCompose == WFC_FALSE)
   746         {
   747     
   748         if (element->mask)
   749             {
   750             DPRINT(("=== WFC_Context_CheckFastpath(context = %p) - FAILED elemenent includes mask", context));
   751             return;
   752             }
   753         
   754         OWF_ASSERT(element->source->lockedStream.image);
   755         
   756         OWF_ASSERT(element->source->streamHandle != OWF_INVALID_HANDLE);
   757         
   758         if (!WFC_FastpathCheckGeometry(context, element))
   759             {
   760             return;
   761             }
   762         
   763         if (!WFC_FastpathCheckTransparency(element->transparencyTypes, 
   764                                            element->globalAlpha, 
   765                                            element->source->lockedStream.image->format.pixelFormat))
   766             {
   767             return;
   768             }
   769         
   770         OWF_DisplayContext_EnableFastpath(context->displayContext, element->source->streamHandle);
   771         DPRINT(("=== WFC_Context_CheckFastpath(context = %p) - Fastpath Enabled", context));
   772         }
   773     }
   774 
   775 /*---------------------------------------------------------------------------
   776  * Checks if the given stream would be valid as an off-screen context target.
   777  * 
   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.
   781  * 
   782  *  \param stream Target stream to use for rendering
   783  ---------------------------------------------------------------------------*/
   784 
   785 OWF_API_CALL WFCboolean
   786 WFC_Context_IsValidTargetStream(OWFNativeStreamType stream)
   787 {
   788     OWFint      width,height;
   789     OWF_IMAGE_FORMAT    format;
   790     owfNativeStreamGetHeader(stream,
   791                          &width, &height,
   792                          NULL, &format, NULL);
   793     if (width>MAX_SOURCE_WIDTH)
   794         {
   795         return WFC_FALSE;
   796         }
   797     if (height>MAX_SOURCE_HEIGHT)
   798         {
   799         return WFC_FALSE;
   800         }
   801     return (WFCboolean)OWF_Image_IsValidDestinationFormat(&format);
   802 }
   803 
   804 /*---------------------------------------------------------------------------
   805  * Checks that the image size is acceptable (within the scratch buffers).
   806  * This is called before the source is created.
   807  * 
   808  *  \param stream source stream to use for rendering.
   809  ---------------------------------------------------------------------------*/
   810 
   811 OWF_API_CALL WFCboolean
   812 WFC_Context_IsValidSourceStream(OWFNativeStreamType stream)
   813 {
   814     OWFint      width,height;
   815     owfNativeStreamGetHeader(stream,
   816                          &width, &height,
   817                          NULL, NULL, NULL);
   818     if ((width+2) * (height+2) > MAX_SOURCE_WIDTH * MAX_SOURCE_HEIGHT)
   819         {
   820         return WFC_FALSE;
   821         }
   822     return WFC_TRUE;
   823 }
   824 
   825 /*---------------------------------------------------------------------------
   826  *  Find element from current scene
   827  *
   828  *  \param context Context object
   829  *  \param element Element to find
   830  *
   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,
   836                         WFCElement element)
   837 {
   838     OWF_ASSERT(context);
   839     return WFC_Scene_FindElement(context->workScene, element);
   840 }
   841 
   842 /*---------------------------------------------------------------------------
   843  *  Commit context scene graph changes
   844  *
   845  *  \param context Context to commit
   846  *----------------------------------------------------------------------------*/
   847 static void
   848 WFC_Context_DoCommit(WFC_CONTEXT* context)
   849 {
   850     OWF_ASSERT(context);
   851     DPRINT(("WFC_Context_DoCommit(context = %p)", context));
   852 
   853     OWF_ASSERT(context->snapshotScene);
   854 
   855 
   856     DPRINT(("COMMIT: Committing attribute list changes"));
   857 
   858     DPRINT(("COMMIT: Acquiring mutex"));
   859     OWF_Mutex_Lock(&context->sceneMutex);
   860 
   861     /* comitting scene attribute changes */
   862     DPRINT(("COMMIT: Committing scene attribute changes"));
   863     OWF_AttributeList_Commit(&context->attributes,
   864                              WFC_CONTEXT_TYPE,
   865                              WFC_CONTEXT_BG_COLOR,COMMITTED_ATTR_VALUE_INDEX);
   866 
   867 
   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;
   876 
   877     // reset the visibility flags
   878     owfSymDeviceResetVisibilityState(context);
   879     
   880     DPRINT(("COMMIT: Unlocking mutex"));
   881     OWF_Mutex_Unlock(&context->sceneMutex);
   882 
   883     DPRINT(("COMMIT: Signaling commit semaphore"));
   884     /* signal we're ready */
   885     OWF_Semaphore_Post(&context->commitSemaphore);
   886 }
   887 
   888 /*---------------------------------------------------------------------------
   889  *
   890  *----------------------------------------------------------------------------*/
   891 static OWFboolean
   892 WFC_Context_LockTargetForWriting(WFC_CONTEXT* context)
   893 {
   894     OWF_ASSERT(context);
   895 
   896     DPRINT(("WFC_Context_LockTargetForWriting"));
   897 
   898     context->state.targetBuffer =
   899         owfNativeStreamAcquireWriteBuffer(context->stream);
   900     
   901     if (!context->state.targetBuffer)
   902         {
   903         DPRINT(("Failed to WFC_Context_LockTargetForWriting owfNativeStreamAcquireWriteBuffer"));
   904         return OWF_FALSE;
   905         }
   906     context->state.targetPixels =
   907         owfNativeStreamGetBufferPtr(context->stream,
   908                                     context->state.targetBuffer);
   909 
   910     if ((WFC_ROTATION_0   == context->rotation || WFC_ROTATION_180 == context->rotation) ||
   911         !OWF_Screen_Rotation_Supported(context->displayContext))
   912     {
   913         /* final target, in target format */
   914         context->state.targetImage =context->state.unrotatedTargetImage;
   915     }
   916     else
   917     {
   918         /* final target, in target format */
   919         /* fExt stride/padding value is the rotated value */
   920         context->state.targetImage = context->state.rotatedTargetImage;
   921     }
   922     OWF_Image_SetPixelBuffer(context->state.targetImage,context->state.targetPixels);
   923     
   924     if (context->state.targetImage==NULL)
   925         {
   926         OWF_ASSERT(WFC_FALSE);
   927         }
   928 
   929     /* take context rotation into account. */
   930     if (WFC_ROTATION_0   == context->rotation ||
   931         WFC_ROTATION_180 == context->rotation)
   932     {
   933         context->state.internalTargetImage = context->state.unrotatedInternalTargetImage;
   934     }
   935     else
   936     {
   937         context->state.internalTargetImage = context->state.rotatedInternalTargetImage;
   938     }
   939 
   940     if (context->state.internalTargetImage==NULL)
   941         {
   942         OWF_ASSERT(WFC_FALSE);
   943         }
   944     return OWF_TRUE;
   945 }
   946 
   947 /*---------------------------------------------------------------------------
   948  *
   949  *----------------------------------------------------------------------------*/
   950 static void
   951 WFC_Context_UnlockTarget(WFC_CONTEXT* context,OWFboolean aDoPost)
   952 {
   953     OWF_ROTATION rotation = OWF_ROTATION_0;
   954 
   955     OWF_ASSERT(context);
   956     DPRINT(("WFC_Context_UnlockTarget"));
   957     DPRINT(("  Unlocking target stream=%d, buffer=%d",
   958             context->stream, context->state.targetBuffer));
   959 
   960     owfNativeStreamReleaseWriteBuffer(context->stream,
   961                                       context->state.targetBuffer,
   962                                       EGL_NO_DISPLAY,
   963                                       NULL);
   964 
   965     
   966     if (aDoPost)
   967     {
   968         switch (context->rotation)
   969         {
   970             case WFC_ROTATION_0:
   971             {
   972                 rotation = OWF_ROTATION_0;
   973                 break;
   974             }
   975             case WFC_ROTATION_90:
   976             {
   977                 rotation = OWF_ROTATION_90;
   978                 break;
   979             }
   980             case WFC_ROTATION_180:
   981             {
   982                 rotation = OWF_ROTATION_180;
   983                 break;
   984             }
   985             case WFC_ROTATION_270:
   986             {
   987                 rotation = OWF_ROTATION_270;
   988                 break;
   989             }
   990             default:
   991             {
   992                 OWF_ASSERT(0);
   993             }
   994         }
   995         
   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"));
   999            OWF_ASSERT(0);
  1000             }
  1001     }
  1002 }
  1003 
  1004 /*---------------------------------------------------------------------------
  1005  *
  1006  *----------------------------------------------------------------------------*/
  1007 static void
  1008 WFC_Context_PrepareComposition(WFC_CONTEXT* context)
  1009 {
  1010     OWFsubpixel             r, g, b, a;
  1011 
  1012     OWF_ASSERT(context);
  1013 
  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);
  1019 
  1020     /* prepare for composition by "clearing the table" with
  1021        background color.  */
  1022 
  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) /
  1030         OWF_BYTE_MAX_VALUE;
  1031 
  1032     r = r * a / OWF_ALPHA_MAX_VALUE;
  1033     g = g * a / OWF_ALPHA_MAX_VALUE;
  1034     b = b * a / OWF_ALPHA_MAX_VALUE;
  1035 
  1036     OWF_Image_Clear(context->state.internalTargetImage, r, g, b, a);
  1037 }
  1038 
  1039 
  1040 
  1041 /*---------------------------------------------------------------------------
  1042  *
  1043  *----------------------------------------------------------------------------*/
  1044 static void
  1045 WFC_Context_FinishComposition(WFC_CONTEXT* context)
  1046 {
  1047     OWF_ROTATION            rotation = OWF_ROTATION_0;
  1048     OWFboolean              screenRotation;
  1049 
  1050     OWF_ASSERT(context);
  1051 
  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)
  1055     {
  1056  
  1057         if (screenRotation)
  1058         {
  1059             if (WFC_ROTATION_90   == context->rotation || WFC_ROTATION_270   == context->rotation)
  1060                 {
  1061                 owfSetStreamFlipState(context->stream, OWF_TRUE);
  1062                 }
  1063             else
  1064                 {
  1065                 owfSetStreamFlipState(context->stream, OWF_FALSE);
  1066                 }
  1067         }
  1068         OWF_Image_DestinationFormatConversion(context->state.targetImage, context->state.internalTargetImage);
  1069     }
  1070     else
  1071     {
  1072         switch (context->rotation)
  1073         {
  1074             case WFC_ROTATION_0:
  1075             {
  1076                 rotation = OWF_ROTATION_0;
  1077                 break;
  1078             }
  1079             case WFC_ROTATION_90:
  1080             {
  1081                 rotation = OWF_ROTATION_90;
  1082                 break;
  1083             }
  1084             case WFC_ROTATION_180:
  1085             {
  1086                 rotation = OWF_ROTATION_180;
  1087                 break;
  1088             }
  1089             case WFC_ROTATION_270:
  1090             {
  1091                 rotation = OWF_ROTATION_270;
  1092                 break;
  1093             }
  1094             default:
  1095             {
  1096                 OWF_ASSERT(0);
  1097             }
  1098         }
  1099      
  1100         /* rotate */
  1101         OWF_Image_Rotate(context->state.rotatedTargetImage,
  1102                          context->state.internalTargetImage,
  1103                          rotation);
  1104 
  1105         /* Note: support of different target formats  can be put here */
  1106 
  1107         OWF_Image_DestinationFormatConversion(context->state.targetImage, context->state.rotatedTargetImage);
  1108     }
  1109     WFC_Context_UnlockTarget(context,(context->type==WFC_CONTEXT_TYPE_ON_SCREEN)?OWF_TRUE:OWF_FALSE);
  1110 }
  1111 
  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  *----------------------------------------------------------------------------*/
  1118 static void
  1119 WFC_Context_DoCompose(WFC_CONTEXT* context)
  1120 {
  1121     WFC_SCENE*              scene   = NULL;
  1122     OWF_NODE*               node    = NULL;
  1123 
  1124     OWF_ASSERT(context);
  1125 
  1126     OWF_Mutex_Lock(&context->updateFlagMutex);
  1127 
  1128     OWF_DisplayContext_IncrementSerialNumber(context->displayContext);
  1129     
  1130     OWF_DisplayContext_SetCompositionOngoing(context->displayContext, WFC_TRUE);
  1131     context->sourceUpdateCount = 0;
  1132     OWF_Mutex_Unlock(&context->updateFlagMutex);
  1133     
  1134     DPRINT(("WFC_Context_Compose"));
  1135     /* Composition always uses the committed version
  1136      * of the scene.
  1137      */
  1138 
  1139     WFC_Scene_LockSourcesAndMasks(context->committedScene);
  1140     
  1141     OWF_Mutex_Lock(&context->sceneMutex);
  1142     
  1143     WFC_Context_CheckFastpath(context);
  1144     if (OWF_DisplayContext_FastpathEnabled(context->displayContext))
  1145         {
  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;
  1153     
  1154             DPRINT(("== WFC_Context_DoCompose(context = %p) - Fastpathing", context));
  1155     
  1156             stream = OWF_DisplayContext_FastpathStream(context->displayContext);
  1157             if (screenRotation)
  1158                 {
  1159                 switch (context->rotation)
  1160                     {
  1161                     case WFC_ROTATION_0:
  1162                         {
  1163                         rotation = OWF_ROTATION_0;
  1164                         break;
  1165                         }
  1166                     case WFC_ROTATION_90:
  1167                         {
  1168                         rotation = OWF_ROTATION_90;
  1169                         break;
  1170                         }
  1171                     case WFC_ROTATION_180:
  1172                         {
  1173                         rotation = OWF_ROTATION_180;
  1174                         break;
  1175                         }
  1176                     case WFC_ROTATION_270:
  1177                         {
  1178                         rotation = OWF_ROTATION_270;
  1179                         break;
  1180                         }
  1181                     default:
  1182                         {
  1183                         OWF_ASSERT(0);
  1184                         rotation = OWF_ROTATION_0;
  1185                         }
  1186                     }
  1187                 }
  1188     
  1189             if (!OWF_Screen_Post_Topmost_Layer(context->displayContext, stream, rotation))
  1190                 {
  1191             
  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
  1195                 }
  1196             }
  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))
  1202                 {
  1203                 OWFboolean copy;
  1204                 if (screenRotation)
  1205                     {
  1206                     if (WFC_ROTATION_90 == context->rotation || WFC_ROTATION_270 == context->rotation)
  1207                         {
  1208                         owfSetStreamFlipState(context->stream, OWF_TRUE);
  1209                         }
  1210                     else
  1211                         {
  1212                         owfSetStreamFlipState(context->stream, OWF_FALSE);
  1213                         }
  1214                     }
  1215                 copy=OWF_DisplayContext_CopyFastpathedStreamToTargetStream(context);
  1216                 if (!WFC_Context_Active(context))
  1217                     {
  1218                     if (!copy)
  1219                         {
  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
  1223                         }
  1224                     }
  1225                 else
  1226                     {
  1227                     copy=OWF_FALSE;
  1228                     }
  1229               
  1230                 WFC_Context_UnlockTarget(context,copy);
  1231                 }
  1232             else
  1233                 {
  1234                 //If non-autonomous, then the lock target is required.
  1235                 OWF_ASSERT(WFC_Context_Active(context));
  1236                 }
  1237 
  1238             }
  1239         if (OWF_DisplayContext_FastpathEnabled(context->displayContext))
  1240             {
  1241             WFC_ELEMENT* topmostElement = NULL;
  1242             topmostElement = WFC_Scene_TopMostElement(context->committedScene);
  1243             owfSymElementNotifications(context, topmostElement);
  1244             }
  1245         }
  1246     if (!OWF_DisplayContext_FastpathEnabled(context->displayContext))
  1247         {
  1248         DPRINT(("== WFC_Context_DoCompose(context = %p) -   Composing", context));
  1249         WFC_Context_PrepareComposition(context);
  1250 
  1251         scene = context->committedScene;
  1252         OWF_ASSERT(scene);
  1253     
  1254         for (node = scene->elements; NULL != node; node = node->next)
  1255             {
  1256             
  1257             WFC_ELEMENT*            element = NULL;
  1258             WFC_ELEMENT_STATE*      elementState = NULL;
  1259             element = ELEMENT(node->data);
  1260     
  1261             if (element->skipCompose)
  1262                 {
  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));
  1266                 continue;
  1267                 }
  1268     
  1269             DPRINT(("  Composing element %d", element->handle));
  1270     
  1271             /* BeginComposition may fail e.g. if the element's destination
  1272              * rectangle is something bizarre, i.e. causes overflows or
  1273              * something.
  1274              */
  1275             if ((elementState=WFC_Pipeline_BeginComposition(context, element))!=NULL)
  1276                 {
  1277                 owfSymElementNotifications(context, element);
  1278                 
  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);
  1285                     
  1286                 WFC_Pipeline_EndComposition(context, element,elementState);
  1287                 }
  1288             }
  1289     
  1290         WFC_Context_FinishComposition(context);
  1291         DPRINT(("=== WFC_Context_DoCompose(context = %p) - Diplayed Composition", context));
  1292         }
  1293     
  1294     WFC_Scene_UnlockSourcesAndMasks(context->committedScene);
  1295     owfSymProcessAllNotifications(context);
  1296     OWF_Mutex_Unlock(&context->sceneMutex);
  1297     
  1298     OWF_Semaphore_Post(&context->compositionSemaphore);
  1299 }
  1300 
  1301 /*---------------------------------------------------------------------------
  1302  *  Activate/deactivate auto-composition on context
  1303  *
  1304  *  \param context Context
  1305  *  \param act Auto-composition enable/disable
  1306  *----------------------------------------------------------------------------*/
  1307 OWF_API_CALL void
  1308 WFC_Context_Activate(WFC_CONTEXT* context,
  1309                      WFCboolean act)
  1310 {
  1311     OWF_ASSERT(context);
  1312 
  1313     DPRINT(("WFC_Context_Activate: %s", (act) ? "activate" : "deactivate"));
  1314 
  1315     if (act && !WFC_Context_Active(context))
  1316     {
  1317         DPRINT(("WFC_Context_Activate: WFC_CONTEXT_STATE_PASSIVE: activating"));
  1318         context->activationState = WFC_CONTEXT_STATE_ACTIVATING;
  1319 
  1320         /* moved from composer loop - updates must be allowed
  1321          * immediately after activation
  1322          */
  1323         WFC_Device_EnableContentNotifications(context->device,
  1324                                               context,
  1325                                               WFC_TRUE);
  1326 
  1327         OWF_Message_Send(&context->composerQueue,
  1328                          WFC_MESSAGE_ACTIVATE,
  1329                          0);
  1330     }
  1331     else if (!act && WFC_Context_Active(context))
  1332     {
  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,
  1337                          0);
  1338     }
  1339 }
  1340 
  1341 /*---------------------------------------------------------------------------
  1342  *
  1343  *----------------------------------------------------------------------------*/
  1344 OWF_API_CALL WFCboolean
  1345 WFC_Context_InvokeComposition(WFC_DEVICE* device,
  1346                               WFC_CONTEXT* context,
  1347                               WFCboolean wait)
  1348 {
  1349     WFCint              status = 0;
  1350 
  1351     OWF_ASSERT(context);
  1352     OWF_ASSERT(device);
  1353 
  1354     device = device; /* suppress the compiler warning */
  1355 
  1356     status = OWF_Semaphore_TryWait(&context->compositionSemaphore);
  1357     if (status)
  1358     {
  1359         if (!wait)
  1360         {
  1361             /* busy; processing last request */
  1362             return WFC_FALSE;
  1363         }
  1364         /* wait previous frame composition to finish */
  1365         OWF_Semaphore_Wait(&context->compositionSemaphore);
  1366     }
  1367 
  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);
  1371 
  1372     return WFC_TRUE;
  1373 }
  1374 
  1375 /*---------------------------------------------------------------------------
  1376  *
  1377  *----------------------------------------------------------------------------*/
  1378 OWF_API_CALL WFCErrorCode
  1379 WFC_Context_InvokeCommit(WFC_DEVICE* device,
  1380                          WFC_CONTEXT* context,
  1381                          WFCboolean wait)
  1382 {
  1383     WFCint              status = 0;
  1384 
  1385     OWF_ASSERT(context);
  1386     OWF_ASSERT(device);
  1387 
  1388     device = device; /* suppress the compiler warning */
  1389 
  1390     /* first check if there're inconsistensies in the scene */
  1391     if (WFC_Scene_HasConflicts(context->workScene))
  1392     {
  1393         DPRINT(("WFC_Context_InvokeCommit: scene has inconsistensies"));
  1394         return WFC_ERROR_INCONSISTENCY;
  1395     }
  1396 
  1397     /* then commit - always asynchronously */
  1398     status = OWF_Semaphore_TryWait(&context->commitSemaphore);
  1399     DPRINT(("COMMIT: Commit semaphore status = %d", status));
  1400     if (status)
  1401     {
  1402         if (!wait)
  1403         {
  1404             DPRINT(("COMMIT: Busy; exiting."));
  1405             /* busy; processing last commit */
  1406             return WFC_ERROR_BUSY;
  1407         }
  1408 
  1409         DPRINT(("COMMIT: Waiting for previous commit to finish."));
  1410         /* wait previous commit to finish */
  1411         OWF_Semaphore_Wait(&context->commitSemaphore);
  1412     }
  1413 
  1414     /* comitting scene attribute changes */
  1415     DPRINT(("COMMIT: Cloning scene attribute changes"));
  1416     OWF_AttributeList_Commit(&context->attributes,
  1417                              WFC_CONTEXT_TYPE,
  1418                              WFC_CONTEXT_BG_COLOR,SNAPSHOT_ATTR_VALUE_INDEX);
  1419 
  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);
  1424 
  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;
  1429 }
  1430 
  1431 /*---------------------------------------------------------------------------
  1432  *  \param context
  1433  *  \param dpy
  1434  *  \param sync
  1435  *----------------------------------------------------------------------------*/
  1436 OWF_API_CALL void
  1437 WFC_Context_InsertFence(WFC_CONTEXT* context,
  1438                         WFCEGLDisplay dpy,
  1439                         WFCEGLSync sync)
  1440 {
  1441     OWF_ASSERT(context);
  1442     OWF_ASSERT(sync);
  1443 
  1444     DPRINT(("WFC_Context_InsertFence: Sending fence sync: 0x%08x", sync));
  1445     
  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);
  1448 }
  1449 
  1450 /*---------------------------------------------------------------------------
  1451  *  Insert element into context's scene
  1452  *
  1453  *  \param context
  1454  *  \param element
  1455  *  \param subordinate
  1456  *
  1457  *  \return WFCErrorCode
  1458  *----------------------------------------------------------------------------*/
  1459 OWF_API_CALL WFCErrorCode
  1460 WFC_Context_InsertElement(WFC_CONTEXT* context,
  1461                           WFCElement element,
  1462                           WFCElement subordinate)
  1463 {
  1464     WFC_ELEMENT*            object = NULL;
  1465     WFCErrorCode            result = WFC_ERROR_BAD_HANDLE;
  1466 
  1467     OWF_ASSERT(context);
  1468 
  1469     object = WFC_Device_FindElement(context->device, element);
  1470 
  1471     if (NULL != object && CONTEXT(object->context) == context)
  1472     {
  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
  1476          * this element.
  1477          */
  1478         object->shared = WFC_TRUE;
  1479         result = WFC_Scene_InsertElement(context->workScene,
  1480                                          object,
  1481                                          subordinate);
  1482 
  1483         context->lowestElement = WFC_Scene_LowestElement(context->workScene);
  1484     }
  1485     return result;
  1486 }
  1487 
  1488 /*---------------------------------------------------------------------------
  1489  *  Remove element from context's scene
  1490  *
  1491  *  \param context
  1492  *  \param element
  1493  *
  1494  *  \return WFCErrorCode
  1495  *----------------------------------------------------------------------------*/
  1496 OWF_API_CALL WFCErrorCode
  1497 WFC_Context_RemoveElement(WFC_CONTEXT* context,
  1498                           WFCElement element)
  1499 {
  1500     WFC_ELEMENT*            elemento = NULL;
  1501 
  1502     OWF_ASSERT(context);
  1503 
  1504     elemento = WFC_Context_FindElement(context, element);
  1505 
  1506     if (elemento)
  1507     {
  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
  1511          */
  1512         elemento->shared = WFC_FALSE;
  1513         context->lowestElement = WFC_Scene_LowestElement(context->workScene);
  1514     }
  1515 
  1516     return WFC_ERROR_NONE;
  1517 }
  1518 
  1519 /*!
  1520  *  \brief IncreaseClientElementCount
  1521  *
  1522  *  \param context
  1523  *  \return positive increased current element count; negative or zero indicating the count can't be increased
  1524  */
  1525 OWF_API_CALL WFCint
  1526 WFC_Context_IncreaseClientElementCount(WFC_CONTEXT* context)
  1527     {
  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
  1533      */
  1534     if (context->clientElementCount>=MAX_ELEMENTS)
  1535         {
  1536         return -context->clientElementCount;
  1537         }
  1538     else
  1539         {
  1540         return ++context->clientElementCount;
  1541         }
  1542     }
  1543 
  1544 /*!
  1545  *  \brief DecreaseClientElementCount
  1546  *
  1547  *  \param context
  1548  *  \return positive or zero decreased current element count; negative indicating the count can't be decreased - p0robably already zero
  1549  */
  1550 OWF_API_CALL WFCint
  1551 WFC_Context_DecreaseClientElementCount(WFC_CONTEXT* context)
  1552     {
  1553     /* note that a negative return indicates that decrements are not matched with increments */ 
  1554     return --context->clientElementCount;
  1555     }
  1556 
  1557 /*---------------------------------------------------------------------------
  1558  *
  1559  *----------------------------------------------------------------------------*/
  1560 OWF_API_CALL WFCErrorCode
  1561 WFC_Context_GetElementAbove(WFC_CONTEXT* context,
  1562                             WFCElement element,
  1563                             WFCElement* result)
  1564 {
  1565     WFC_ELEMENT*            object = NULL;
  1566     WFCErrorCode            error = WFC_ERROR_ILLEGAL_ARGUMENT;
  1567 
  1568     OWF_ASSERT(context);
  1569     OWF_ASSERT(result);
  1570 
  1571     object = WFC_Context_FindElement(context, element);
  1572 
  1573     if (object)
  1574     {
  1575         WFCElement          temp;
  1576 
  1577         temp = WFC_Scene_GetNeighbourElement(context->workScene, element, 1);
  1578         *result = temp;
  1579         error = WFC_ERROR_NONE;
  1580     }
  1581     return error;
  1582 }
  1583 
  1584 /*---------------------------------------------------------------------------
  1585  *
  1586  *----------------------------------------------------------------------------*/
  1587 OWF_API_CALL WFCErrorCode
  1588 WFC_Context_GetElementBelow(WFC_CONTEXT* context,
  1589                             WFCElement element,
  1590                             WFCElement* result)
  1591 {
  1592     WFC_ELEMENT*            object = NULL;
  1593     WFCErrorCode            error = WFC_ERROR_ILLEGAL_ARGUMENT;
  1594 
  1595     OWF_ASSERT(context);
  1596     OWF_ASSERT(result);
  1597 
  1598     object = WFC_Context_FindElement(context, element);
  1599     if (object)
  1600     {
  1601         WFCElement          temp;
  1602 
  1603         temp = WFC_Scene_GetNeighbourElement(context->workScene, element, -1);
  1604         *result = temp;
  1605         error = WFC_ERROR_NONE;
  1606     }
  1607     return error;
  1608 }
  1609 
  1610 /*---------------------------------------------------------------------------
  1611  *
  1612  *----------------------------------------------------------------------------*/
  1613 OWF_API_CALL WFCErrorCode
  1614 WFC_Context_GetAttribi(WFC_CONTEXT* context,
  1615                        WFCContextAttrib attrib,
  1616                        WFCint* value)
  1617 {
  1618     WFCint                  temp = 0;
  1619     OWF_ATTRIBUTE_LIST_STATUS   err;
  1620     WFCErrorCode            result = WFC_ERROR_NONE;
  1621 
  1622     OWF_ASSERT(context);
  1623     OWF_ASSERT(value);
  1624 
  1625     temp    = OWF_Attribute_GetValuei(&context->attributes, attrib);
  1626     err     = OWF_AttributeList_GetError(&context->attributes);
  1627 
  1628     if (err != ATTR_ERROR_NONE)
  1629     {
  1630         result = WFC_ERROR_BAD_ATTRIBUTE;
  1631     }
  1632     else
  1633     {
  1634         *value = temp;
  1635     }
  1636     return result;
  1637 }
  1638 
  1639 /*---------------------------------------------------------------------------
  1640  *
  1641  *----------------------------------------------------------------------------*/
  1642 OWF_API_CALL WFCErrorCode
  1643 WFC_Context_SetAttribi(WFC_CONTEXT* context,
  1644                        WFCContextAttrib attrib,
  1645                        WFCint value)
  1646 {
  1647     WFCErrorCode                result = WFC_ERROR_NONE;
  1648 
  1649     OWF_ASSERT(context);
  1650 
  1651     /* check value */
  1652     switch (attrib)
  1653     {
  1654         case WFC_CONTEXT_BG_COLOR:
  1655         {
  1656             OWFint              alpha;
  1657 
  1658             /*
  1659              *  Color format is RGBA NOT RGBA.
  1660              */
  1661             alpha = value & 0xFF;
  1662 
  1663             if (WFC_CONTEXT_TYPE_ON_SCREEN == context->type)
  1664             {
  1665                 /* the only allowed value for on-screen context
  1666                  * background alpha is 255 */
  1667                 if (alpha != 255)
  1668                 {
  1669                     result = WFC_ERROR_ILLEGAL_ARGUMENT;
  1670                 }
  1671             }
  1672             break;
  1673         }
  1674 
  1675         case WFC_CONTEXT_ROTATION:
  1676         {
  1677             if (!(WFC_ROTATION_0 == value ||
  1678                   WFC_ROTATION_90 == value ||
  1679                   WFC_ROTATION_180 == value ||
  1680                   WFC_ROTATION_270 == value))
  1681             {
  1682                result = WFC_ERROR_ILLEGAL_ARGUMENT;
  1683             }
  1684             else
  1685             {
  1686                 OWF_DisplayContext_ResetFastpathCheck(context->displayContext);
  1687             }
  1688             break;
  1689         }
  1690 
  1691         case WFC_CONTEXT_TYPE:
  1692         case WFC_CONTEXT_TARGET_HEIGHT:
  1693         case WFC_CONTEXT_TARGET_WIDTH:
  1694         case WFC_CONTEXT_LOWEST_ELEMENT:
  1695         {
  1696             result = WFC_ERROR_BAD_ATTRIBUTE;
  1697             break;
  1698         }
  1699 
  1700         case WFC_CONTEXT_FORCE_32BIT:
  1701         default:
  1702         {
  1703             result = WFC_ERROR_BAD_ATTRIBUTE;
  1704             break;
  1705         }
  1706     }
  1707 
  1708     if (WFC_ERROR_NONE == result)
  1709     {
  1710         OWF_ATTRIBUTE_LIST_STATUS   error;
  1711 
  1712         /* try changing the value */
  1713         OWF_Attribute_SetValuei(&context->attributes, attrib, value);
  1714         error = OWF_AttributeList_GetError(&context->attributes);
  1715 
  1716         /* transform errors */
  1717         switch (error) {
  1718             case ATTR_ERROR_ACCESS_DENIED:
  1719             case ATTR_ERROR_INVALID_ATTRIBUTE:
  1720             {
  1721                 result = WFC_ERROR_BAD_ATTRIBUTE;
  1722                 break;
  1723             }
  1724             default:
  1725             {
  1726                 break;
  1727             }
  1728         }
  1729     }
  1730 
  1731     return result;
  1732 }
  1733 
  1734 /*---------------------------------------------------------------------------
  1735  *
  1736  *----------------------------------------------------------------------------*/
  1737 OWF_API_CALL WFCErrorCode
  1738 WFC_Context_GetAttribfv(WFC_CONTEXT* context,
  1739                         WFCContextAttrib attrib,
  1740                         WFCint count,
  1741                         WFCfloat* values)
  1742 {
  1743     WFCErrorCode            result = WFC_ERROR_NONE;
  1744 
  1745     OWF_ASSERT(context);
  1746     OWF_ASSERT(values);
  1747 
  1748     switch (attrib)
  1749     {
  1750         case WFC_CONTEXT_BG_COLOR:
  1751         {
  1752             if (4 != count)
  1753             {
  1754                 result = WFC_ERROR_ILLEGAL_ARGUMENT;
  1755             }
  1756             else
  1757             {
  1758                 OWFuint32      color;
  1759                 OWF_ATTRIBUTE_LIST_STATUS   err;
  1760 
  1761                 color = OWF_Attribute_GetValuei(&context->attributes, attrib);
  1762                 err = OWF_AttributeList_GetError(&context->attributes);
  1763 
  1764                 if (err != ATTR_ERROR_NONE)
  1765                 {
  1766                     result = WFC_ERROR_BAD_ATTRIBUTE;
  1767                     break;
  1768                 }
  1769 
  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;
  1779             }
  1780             break;
  1781         }
  1782 
  1783         default:
  1784         {
  1785             result = WFC_ERROR_BAD_ATTRIBUTE;
  1786             break;
  1787         }
  1788     }
  1789 
  1790     return result;
  1791 }
  1792 
  1793 /*---------------------------------------------------------------------------
  1794  *
  1795  *----------------------------------------------------------------------------*/
  1796 OWF_API_CALL WFCErrorCode
  1797 WFC_Context_SetAttribfv(WFC_CONTEXT* context,
  1798                         WFCContextAttrib attrib,
  1799                         WFCint count,
  1800                         const WFCfloat* values)
  1801 {
  1802     WFCErrorCode            result = WFC_ERROR_NONE;
  1803 
  1804     OWF_ASSERT(context);
  1805     OWF_ASSERT(values);
  1806 
  1807     switch (attrib)
  1808     {
  1809         case WFC_CONTEXT_BG_COLOR:
  1810         {
  1811             if (4 != count)
  1812             {
  1813                 result = WFC_ERROR_ILLEGAL_ARGUMENT;
  1814             }
  1815             else
  1816             {
  1817                 OWFuint32    color;
  1818 
  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))
  1824                 {
  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));
  1829 
  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);
  1833                 }
  1834                 else
  1835                 {
  1836                     result = WFC_ERROR_ILLEGAL_ARGUMENT;
  1837                 }
  1838             }
  1839             break;
  1840         }
  1841 
  1842         default:
  1843         {
  1844             result = WFC_ERROR_BAD_ATTRIBUTE;
  1845             break;
  1846         }
  1847     }
  1848 
  1849     return result;
  1850 }
  1851 
  1852 
  1853 static void
  1854 WFC_Context_AutoComposer(WFC_CONTEXT* context)
  1855 {
  1856     OWF_Mutex_Lock(&context->updateFlagMutex);
  1857     if (context->sourceUpdateCount > 0)
  1858     {
  1859         DPRINT(("WFC_Context_ComposerThread: %d sources were updated, "
  1860                 "invoking composition\n",
  1861                 context->sourceUpdateCount));
  1862 
  1863         /* reset update counter */
  1864 
  1865         OWF_Mutex_Unlock(&context->updateFlagMutex);
  1866         WFC_Context_DoCompose(context);
  1867     }
  1868     else
  1869     {
  1870         OWF_Mutex_Unlock(&context->updateFlagMutex);
  1871     }
  1872 }
  1873 
  1874 /*---------------------------------------------------------------------------
  1875  *
  1876  *----------------------------------------------------------------------------*/
  1877 static void*
  1878 WFC_Context_ComposerThread(void* data)
  1879 {
  1880     WFC_CONTEXT*            context = (WFC_CONTEXT*) data;
  1881     OWFboolean screenCreated = OWF_TRUE;
  1882     OWF_MESSAGE             msg;
  1883 
  1884 
  1885     OWF_ASSERT(context);
  1886     DPRINT(("WFC_Context_ComposerThread starting"));
  1887 
  1888     memset(&msg, 0, sizeof(OWF_MESSAGE));
  1889     
  1890     if (context->type == WFC_CONTEXT_TYPE_ON_SCREEN)
  1891         {
  1892         screenCreated = OWF_Screen_Create(context->screenNumber, context->displayContext);
  1893         }
  1894     
  1895     OWF_ComposerThread_Rendezvous(context->displayContext);
  1896 
  1897     OWF_ComposerThread_RendezvousDestroy(context->displayContext);
  1898     
  1899     while (context->device && msg.id != WFC_MESSAGE_QUIT && screenCreated)
  1900     {
  1901         OWFint              err = -1;
  1902 
  1903         if (WFC_CONTEXT_STATE_ACTIVE == context->activationState)
  1904         {
  1905             err = OWF_Message_Wait(&context->composerQueue,
  1906                                    &msg,
  1907                                    AUTO_COMPOSE_DELAY);
  1908 
  1909             WFC_Context_AutoComposer(context);
  1910         }
  1911         else
  1912         {
  1913             DPRINT(("  ComposerThread waiting for message"));
  1914             err = OWF_Message_Wait(&context->composerQueue, &msg, WAIT_FOREVER);
  1915         }
  1916 
  1917         if (0 == err)
  1918         {
  1919             switch (msg.id)
  1920             {
  1921                 case WFC_MESSAGE_ACTIVATE:
  1922                 {
  1923                     DPRINT(("****** ENABLING AUTO-COMPOSITION ******"));
  1924                     context->activationState = WFC_CONTEXT_STATE_ACTIVE;
  1925                     break;
  1926                 }
  1927 
  1928                 case WFC_MESSAGE_DEACTIVATE:
  1929                 {
  1930                     /* cancel possible countdown so that update won't occur
  1931                      * after deactivation */
  1932                     DPRINT(("****** DISABLING AUTO-COMPOSITION ******"));
  1933                     WFC_Device_EnableContentNotifications(context->device,
  1934                                                           context,
  1935                                                           WFC_FALSE);
  1936                     context->activationState = WFC_CONTEXT_STATE_PASSIVE;
  1937                     if (OWF_DisplayContext_FastpathEnabled(context->displayContext))
  1938                         {
  1939                         DPRINT(("COMMIT: Invoking fastpath recomposition after deactivate"));
  1940                         WFC_Context_DoCompose(context);
  1941                         }
  1942                     break;
  1943                 }
  1944 
  1945                 case WFC_MESSAGE_COMMIT:
  1946                 {
  1947                     DPRINT(("****** COMMITTING SCENE CHANGES ******"));
  1948 
  1949                     DPRINT(("COMMIT: Invoking DoCommit"));
  1950                     WFC_Context_DoCommit(context);
  1951                     OWF_DisplayContext_ResetFastpathCheck(context->displayContext);
  1952                     if (!WFC_Context_Active(context))
  1953                     {
  1954                         DPRINT(("COMMIT: Context is inactive, composition "
  1955                                 "not needed.", context->handle));
  1956                         break;
  1957                     }
  1958                     else
  1959                     {
  1960                         /* context is active; compose immediately after
  1961                          * commit has completed */
  1962 
  1963                         DPRINT(("COMMIT: Invoking composition after commit"));
  1964                     }
  1965                     /* FLOW THROUGH */
  1966                 }
  1967 
  1968                 case WFC_MESSAGE_COMPOSE:
  1969                 {
  1970                     DPRINT(("****** COMPOSING SCENE ******"));
  1971 
  1972                     WFC_Context_DoCompose(context);
  1973 
  1974                     break;
  1975                 }
  1976                 
  1977                 case WFC_MESSAGE_FENCE_1_DISPLAY:
  1978                 {
  1979                     DPRINT(("****** STORING EGLDISPLAY (%p) ******", msg.data));
  1980 
  1981                     context->nextSyncObjectDisplay = (WFCEGLDisplay)msg.data;
  1982                     break;
  1983                 }
  1984 
  1985                 case WFC_MESSAGE_FENCE_2_SYNCOBJECT:
  1986                 {
  1987                     DPRINT(("****** BREAKING FENCE (%p) ******", msg.data));
  1988                     OWF_ASSERT(context->eglPrivateSignalSync);
  1989 
  1990                     context->eglPrivateSignalSync(context->nextSyncObjectDisplay,
  1991                                      (WFCEGLSync) msg.data,
  1992                                      EGL_SIGNALED_KHR);
  1993                     break;
  1994                 }
  1995             }
  1996         }
  1997     }
  1998 
  1999     if (context->type == WFC_CONTEXT_TYPE_ON_SCREEN)
  2000         {
  2001         OWF_Screen_Destroy(context->displayContext);
  2002         }
  2003     /* Release any use of EGL by this thread. */
  2004     eglReleaseThread();
  2005 
  2006     DPRINT(("WFC_Context_ComposerThread terminating"));
  2007     OWF_Thread_Exit(NULL);
  2008     return NULL;
  2009 }
  2010 
  2011 /*---------------------------------------------------------------------------
  2012  *
  2013  *----------------------------------------------------------------------------*/
  2014 OWF_API_CALL WFCboolean
  2015 WFC_Context_Active(WFC_CONTEXT* context)
  2016 {
  2017     OWF_ASSERT(context);
  2018 
  2019     return (WFC_CONTEXT_STATE_ACTIVE == context->activationState ||
  2020            WFC_CONTEXT_STATE_ACTIVATING == context->activationState) ? WFC_TRUE : WFC_FALSE;
  2021 }
  2022 
  2023 #ifdef __cplusplus
  2024 }
  2025 #endif
  2026