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