os/graphics/graphicscomposition/openwfcompositionengine/adaptation/src/Platform/Graphics/owfnativestream.c
author sl
Tue, 10 Jun 2014 14:32:02 +0200
changeset 1 260cb5ec6c19
permissions -rw-r--r--
Update contrib.
sl@0
     1
/* Copyright (c) 2009 The Khronos Group Inc.
sl@0
     2
 * Portions copyright (c) 2009-2010  Nokia Corporation and/or its subsidiary(-ies)
sl@0
     3
 *
sl@0
     4
 * Permission is hereby granted, free of charge, to any person obtaining a
sl@0
     5
 * copy of this software and/or associated documentation files (the
sl@0
     6
 * "Materials"), to deal in the Materials without restriction, including
sl@0
     7
 * without limitation the rights to use, copy, modify, merge, publish,
sl@0
     8
 * distribute, sublicense, and/or sell copies of the Materials, and to
sl@0
     9
 * permit persons to whom the Materials are furnished to do so, subject to
sl@0
    10
 * the following conditions:
sl@0
    11
 *
sl@0
    12
 * The above copyright notice and this permission notice shall be included
sl@0
    13
 * in all copies or substantial portions of the Materials.
sl@0
    14
 *
sl@0
    15
 * THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
sl@0
    16
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
sl@0
    17
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
sl@0
    18
 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
sl@0
    19
 * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
sl@0
    20
 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
sl@0
    21
 * MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
sl@0
    22
 */
sl@0
    23
sl@0
    24
/*!
sl@0
    25
 * Ring buffer based Image Stream implementation for Linux.
sl@0
    26
 */
sl@0
    27
sl@0
    28
sl@0
    29
sl@0
    30
#ifdef __cplusplus
sl@0
    31
extern "C" {
sl@0
    32
#endif
sl@0
    33
sl@0
    34
#define OWF_NATIVESTREAM_HANDLE 0xAB
sl@0
    35
sl@0
    36
#include <stdlib.h>
sl@0
    37
#include <string.h>
sl@0
    38
sl@0
    39
#include "owfnativestream.h"
sl@0
    40
#include "owfscreen.h"
sl@0
    41
#include "owfmemory.h"
sl@0
    42
#include "owfdebug.h"
sl@0
    43
#include "owftypes.h"
sl@0
    44
#include "owfmutex.h"
sl@0
    45
#include "owfhstore.h"
sl@0
    46
sl@0
    47
/*needed for owfNativeStreamFromWFC function */
sl@0
    48
#include "WF/wfcplatform.h"
sl@0
    49
sl@0
    50
/* macro for fetching stream object by handle */
sl@0
    51
#define GET_STREAM(ns, s)       ns = owfNativeStreamGet(s)
sl@0
    52
sl@0
    53
/* stream null checks */
sl@0
    54
#define CHECK_STREAM(v)     if (NULL == ns) { return v;}
sl@0
    55
#define CHECK_STREAM_NR()   if (NULL == ns) { return; }
sl@0
    56
sl@0
    57
#define BUFFER_HANDLE_BASE  0x100
sl@0
    58
#define STREAM_HANDLE_BASE  10000
sl@0
    59
#define STREAM_HASHTABLE_SIZE   0x100
sl@0
    60
sl@0
    61
/* buffer handle sanity checks */
sl@0
    62
#define CHECK_BUFFER_NR(x)  if ((x) < BUFFER_HANDLE_BASE || \
sl@0
    63
                                (x) >= BUFFER_HANDLE_BASE + ns->bufferCount) \
sl@0
    64
                            { \
sl@0
    65
                                return; \
sl@0
    66
                            }
sl@0
    67
sl@0
    68
#define CHECK_BUFFER(x,v)   if ((x) < BUFFER_HANDLE_BASE || \
sl@0
    69
                                (x) >= BUFFER_HANDLE_BASE + ns->bufferCount) \
sl@0
    70
                            { \
sl@0
    71
                            return v; \
sl@0
    72
                            }
sl@0
    73
sl@0
    74
#define BUFFER(x)           ns->bufferList[(x)-BUFFER_HANDLE_BASE]
sl@0
    75
sl@0
    76
#define INDEX_TO_HANDLE(x)  ((OWFNativeStreamBuffer) ((x)+BUFFER_HANDLE_BASE))
sl@0
    77
#define HANDLE_TO_INDEX(x)  ((int) ((x)-BUFFER_HANDLE_BASE))
sl@0
    78
sl@0
    79
typedef struct {
sl@0
    80
    EGLDisplay     dpy;
sl@0
    81
    EGLSyncKHR*    sync;
sl@0
    82
} OWF_SYNC_DESC;
sl@0
    83
sl@0
    84
sl@0
    85
/*!
sl@0
    86
 * Structure for image stream.
sl@0
    87
 */
sl@0
    88
typedef struct {
sl@0
    89
    OWFNativeStreamType     handle;     /* stream handle */
sl@0
    90
    void**                  bufferList;
sl@0
    91
    OWFint*                 bufferRefs;
sl@0
    92
    OWFint                  bufferCount;
sl@0
    93
    OWFint                  lockCount;
sl@0
    94
    OWFint                  screenNumber;
sl@0
    95
    OWFint                  width,      /* frame width (pixels) */
sl@0
    96
                            height,     /* frame height (pixels) */
sl@0
    97
                            stride;     /* size of single row (bytes) */
sl@0
    98
    OWF_IMAGE_FORMAT        colorFormat;
sl@0
    99
    OWFint                  referenceCount;
sl@0
   100
    OWF_MUTEX               mutex;
sl@0
   101
    OWF_SEMAPHORE           writer;
sl@0
   102
    OWFint                  idxFront;
sl@0
   103
    OWFint                  idxNextFree;
sl@0
   104
    OWF_NODE*               observers;
sl@0
   105
    OWFboolean              sendNotifications;
sl@0
   106
    OWFboolean              protected;  /* protection flag to prevent the
sl@0
   107
                                           user from destroying the stream
sl@0
   108
                                           (for onscreen-context use) */
sl@0
   109
sl@0
   110
    OWF_SYNC_DESC*          bufferSyncs; /* sync object to be signalled when
sl@0
   111
                                            buffer is 'consumed' */
sl@0
   112
} OWF_NATIVE_STREAM;
sl@0
   113
sl@0
   114
sl@0
   115
static const OWF_IMAGE_FORMAT   owfOnScreenColorFormat =
sl@0
   116
                                {
sl@0
   117
                                    OWF_IMAGE_ARGB8888,
sl@0
   118
                                    OWF_FALSE,
sl@0
   119
                                    OWF_TRUE,
sl@0
   120
                                    4
sl@0
   121
                                };
sl@0
   122
sl@0
   123
/*============================================================================
sl@0
   124
 * PRIVATE PARTS
sl@0
   125
 *============================================================================*/
sl@0
   126
sl@0
   127
/*!---------------------------------------------------------------------------
sl@0
   128
 * Internal.
sl@0
   129
 *----------------------------------------------------------------------------*/
sl@0
   130
/*
sl@0
   131
sl@0
   132
*/
sl@0
   133
/*!---------------------------------------------------------------------------
sl@0
   134
 *  Add stream to internal stream dictionary
sl@0
   135
 *
sl@0
   136
 *  \param handle           Stream handle
sl@0
   137
 *  \param stream           Stream object associated with the handle
sl@0
   138
 *
sl@0
   139
 *  \return Boolean value indicating whether the addition was succesful
sl@0
   140
 *----------------------------------------------------------------------------*/
sl@0
   141
static OWFHandle
sl@0
   142
owfNativeStreamAddStream(OWF_NATIVE_STREAM* stream)
sl@0
   143
{
sl@0
   144
    OWFHandle handle = OWF_INVALID_HANDLE;
sl@0
   145
sl@0
   146
    handle = OWF_HStore_HandleCreate(OWF_NATIVESTREAM_HANDLE, stream);
sl@0
   147
sl@0
   148
    return handle;
sl@0
   149
}
sl@0
   150
sl@0
   151
/*----------------------------------------------------------------------------
sl@0
   152
 *  Returns the stream object associated to given handle
sl@0
   153
 *
sl@0
   154
 *  \param handle           Stream handle
sl@0
   155
 *
sl@0
   156
 *  \return Stream object or NULL if the handle is invalid
sl@0
   157
 *----------------------------------------------------------------------------*/
sl@0
   158
static OWF_NATIVE_STREAM*
sl@0
   159
owfNativeStreamGet(OWFNativeStreamType handle)
sl@0
   160
{
sl@0
   161
    return (OWF_NATIVE_STREAM*) OWF_HStore_GetObj(handle, OWF_NATIVESTREAM_HANDLE);
sl@0
   162
}
sl@0
   163
sl@0
   164
/*----------------------------------------------------------------------------
sl@0
   165
 *  Remove stream from internal stream dictionary
sl@0
   166
 *
sl@0
   167
 *  \param handle           Stream handle
sl@0
   168
 *
sl@0
   169
 *  \return Boolean value indicating success of the deletion
sl@0
   170
 *----------------------------------------------------------------------------*/
sl@0
   171
static OWFboolean
sl@0
   172
owfNativeStreamRemove(OWFNativeStreamType handle)
sl@0
   173
{
sl@0
   174
    OWF_HStore_HandleDelete(handle);
sl@0
   175
    return OWF_TRUE;
sl@0
   176
}
sl@0
   177
sl@0
   178
/*!---------------------------------------------------------------------------
sl@0
   179
 *  Notify stream's observers about an event
sl@0
   180
 *
sl@0
   181
 *  \param stream           Stream
sl@0
   182
 *  \param event            Event to notify about
sl@0
   183
 *----------------------------------------------------------------------------*/
sl@0
   184
static void owfNativeStreamNotifyObservers(OWFNativeStreamType stream,
sl@0
   185
                                           OWFNativeStreamEvent event)
sl@0
   186
{
sl@0
   187
    OWF_NODE*               iter = NULL;
sl@0
   188
sl@0
   189
    OWF_NATIVE_STREAM* ns;
sl@0
   190
sl@0
   191
    DPRINT(("owfNativeStreamNotifyObservers(%p, %x)",
sl@0
   192
             stream, event));
sl@0
   193
sl@0
   194
    GET_STREAM(ns, stream);
sl@0
   195
    CHECK_STREAM_NR();
sl@0
   196
sl@0
   197
    if (ns->sendNotifications)
sl@0
   198
    {
sl@0
   199
        OWF_Mutex_Lock(&ns->mutex);
sl@0
   200
sl@0
   201
        iter = ns->observers;
sl@0
   202
        while (iter)
sl@0
   203
        {
sl@0
   204
            OWFStreamCallbackData* cbdata = (OWFStreamCallbackData*) iter->data;
sl@0
   205
sl@0
   206
            DPRINT(("Stream callback: (%p)(%p, %x, %p)",
sl@0
   207
                    cbdata->callback, stream, event, cbdata->data));
sl@0
   208
sl@0
   209
            if (cbdata->callback)
sl@0
   210
            {
sl@0
   211
                (cbdata->callback)(stream, event, cbdata->data);
sl@0
   212
            }
sl@0
   213
            iter = iter->next;
sl@0
   214
        }
sl@0
   215
        OWF_Mutex_Unlock(&ns->mutex);
sl@0
   216
    }
sl@0
   217
}
sl@0
   218
sl@0
   219
/*----------------------------------------------------------------------------
sl@0
   220
 *  Observer equality comparison
sl@0
   221
 *----------------------------------------------------------------------------*/
sl@0
   222
static OWFint
sl@0
   223
ObserversEqual(void* arg1, void* arg2)
sl@0
   224
{
sl@0
   225
#define _CALLBACK(x)        ((OWFStreamCallbackData*)(x))
sl@0
   226
sl@0
   227
sl@0
   228
    return (OWFint)(    _CALLBACK(arg1)->callback ==_CALLBACK(arg2)->callback
sl@0
   229
                    &&  _CALLBACK(arg1)->data ==_CALLBACK(arg2)->data
sl@0
   230
                    );
sl@0
   231
sl@0
   232
#undef _CALLBACK
sl@0
   233
}
sl@0
   234
sl@0
   235
static OWFint
sl@0
   236
ObserverFuncsEqual(void* arg1, void* arg2)
sl@0
   237
{
sl@0
   238
#define _CALLBACK(x)        ((OWFStreamCallbackData*)(x))
sl@0
   239
sl@0
   240
sl@0
   241
    return (OWFint)(_CALLBACK(arg1)->callback ==_CALLBACK(arg2)->callback
sl@0
   242
                    );
sl@0
   243
sl@0
   244
#undef _CALLBACK
sl@0
   245
}
sl@0
   246
sl@0
   247
static OWFint
sl@0
   248
ObserverDatasEqual(void* arg1, void* arg2)
sl@0
   249
{
sl@0
   250
#define _CALLBACK(x)        ((OWFStreamCallbackData*)(x))
sl@0
   251
sl@0
   252
sl@0
   253
    return (OWFint)(_CALLBACK(arg1)->data ==_CALLBACK(arg2)->data
sl@0
   254
                    );
sl@0
   255
sl@0
   256
#undef _CALLBACK
sl@0
   257
}
sl@0
   258
sl@0
   259
/*----------------------------------------------------------------------------
sl@0
   260
 *  Destroy native stream (implementation)
sl@0
   261
 *
sl@0
   262
 *  \param ns               Native stream object
sl@0
   263
 *----------------------------------------------------------------------------*/
sl@0
   264
static void
sl@0
   265
owfNativeStreamDoDestroy(OWF_NATIVE_STREAM* ns)
sl@0
   266
{
sl@0
   267
    OWFint                  ii = 0;
sl@0
   268
sl@0
   269
    OWF_ASSERT(ns);
sl@0
   270
sl@0
   271
    /* bail out if the stream is protected (e.g. the user tries to
sl@0
   272
     * free on-screen context's stream) */
sl@0
   273
    OWF_Mutex_Lock(&ns->mutex);
sl@0
   274
    if (ns->protected)
sl@0
   275
    {
sl@0
   276
        OWF_Mutex_Unlock(&ns->mutex);
sl@0
   277
        return;
sl@0
   278
    }
sl@0
   279
sl@0
   280
    /* decrease reference count and check whether it is safe to
sl@0
   281
     * actually destroy the stream */
sl@0
   282
    ns->referenceCount--;
sl@0
   283
sl@0
   284
    if (ns->referenceCount > 0) {
sl@0
   285
        OWF_Mutex_Unlock(&ns->mutex);
sl@0
   286
        return;
sl@0
   287
    }
sl@0
   288
sl@0
   289
    /* remove from internal dictionary */
sl@0
   290
    if (ns->handle != OWF_INVALID_HANDLE)
sl@0
   291
    {
sl@0
   292
        owfNativeStreamRemove(ns->handle);
sl@0
   293
    }
sl@0
   294
sl@0
   295
    OWF_ASSERT(0 == ns->lockCount);
sl@0
   296
sl@0
   297
    /* release resources allocated by the stream. */
sl@0
   298
    for (ii = 0; ii < ns->bufferCount; ii++)
sl@0
   299
    {
sl@0
   300
        OWF_Image_FreeData(&ns->bufferList[ii]);
sl@0
   301
    }
sl@0
   302
    xfree(ns->bufferList);
sl@0
   303
sl@0
   304
    OWF_Semaphore_Destroy(&ns->writer);
sl@0
   305
    OWF_Mutex_Unlock(&ns->mutex);
sl@0
   306
    OWF_Mutex_Destroy(&ns->mutex);
sl@0
   307
sl@0
   308
    ns->mutex = NULL;
sl@0
   309
sl@0
   310
    while (ns->observers)
sl@0
   311
    {
sl@0
   312
        OWF_NODE* next = ns->observers->next;
sl@0
   313
        xfree(ns->observers);
sl@0
   314
        ns->observers = next;
sl@0
   315
    }
sl@0
   316
sl@0
   317
    xfree(ns->bufferSyncs);
sl@0
   318
    xfree(ns->bufferRefs);
sl@0
   319
    xfree(ns);
sl@0
   320
}
sl@0
   321
sl@0
   322
/*============================================================================
sl@0
   323
 * PUBLIC API STARTS HERE
sl@0
   324
 *============================================================================*/
sl@0
   325
sl@0
   326
/*!----------------------------------------------------------------------------
sl@0
   327
 *  Create new native stream.
sl@0
   328
 *
sl@0
   329
 *  \param width            Stream image buffer width
sl@0
   330
 *  \param height           Stream image buffer height
sl@0
   331
 *  \param imageFormat      Stream image buffer format
sl@0
   332
 *  \param nbufs            Number of image buffers to allocate
sl@0
   333
 *
sl@0
   334
 *  \param Handle to newly created stream or OWF_INVALID_HANDLe if no
sl@0
   335
 *  stream could be created.
sl@0
   336
 *----------------------------------------------------------------------------*/
sl@0
   337
OWF_PUBLIC OWFNativeStreamType
sl@0
   338
owfNativeStreamCreateImageStream(OWFint width,
sl@0
   339
                                 OWFint height,
sl@0
   340
                                 const OWF_IMAGE_FORMAT* imageFormat,
sl@0
   341
                                 OWFint nbufs)
sl@0
   342
{
sl@0
   343
    OWF_NATIVE_STREAM*      ns          = NULL;
sl@0
   344
    OWFint                  multiFail   = 0;
sl@0
   345
    void**                  bufferList  = NULL;
sl@0
   346
    OWFint*                 bufferRefs  = NULL;
sl@0
   347
    OWF_SYNC_DESC*          bufferSyncs = NULL;
sl@0
   348
    OWFint                  ii          = 0,
sl@0
   349
                            j           = 0;
sl@0
   350
    OWFint                  ok          = 0;
sl@0
   351
sl@0
   352
    OWF_ASSERT(nbufs >= 1);
sl@0
   353
sl@0
   354
    /* stream must have at least 2 buffers (front & back) */
sl@0
   355
    ns          = NEW0(OWF_NATIVE_STREAM);
sl@0
   356
    bufferList  = xalloc(sizeof(void*), nbufs);
sl@0
   357
    bufferRefs  = xalloc(sizeof(int*), nbufs);
sl@0
   358
sl@0
   359
    bufferSyncs  = xalloc(sizeof(OWF_SYNC_DESC), nbufs);
sl@0
   360
sl@0
   361
sl@0
   362
    /* initialize surface/buffer list */
sl@0
   363
    if (bufferList)
sl@0
   364
    {
sl@0
   365
        for (ii = 0; ii < nbufs; ii++)
sl@0
   366
        {
sl@0
   367
            bufferList[ii] = OWF_Image_AllocData(width, height,
sl@0
   368
                                                 imageFormat->pixelFormat);
sl@0
   369
            if (!bufferList[ii])
sl@0
   370
            {
sl@0
   371
                multiFail++;
sl@0
   372
                break;
sl@0
   373
            }
sl@0
   374
        }
sl@0
   375
    }
sl@0
   376
sl@0
   377
    if (!ns || !bufferList || multiFail || !bufferRefs || !bufferSyncs)
sl@0
   378
    {
sl@0
   379
        xfree(ns);
sl@0
   380
        if (bufferList)
sl@0
   381
        {
sl@0
   382
            for (j = 0; j < ii; j++)
sl@0
   383
            {
sl@0
   384
                OWF_Image_FreeData(&bufferList[j]);
sl@0
   385
            }
sl@0
   386
        }
sl@0
   387
        xfree(bufferList);
sl@0
   388
        xfree(bufferRefs);
sl@0
   389
        xfree(bufferSyncs);
sl@0
   390
sl@0
   391
        return OWF_INVALID_HANDLE;
sl@0
   392
    }
sl@0
   393
sl@0
   394
    ns->bufferList      = bufferList;
sl@0
   395
    ns->bufferRefs      = bufferRefs;
sl@0
   396
    ns->bufferCount     = nbufs;
sl@0
   397
sl@0
   398
    ns->width           = width;
sl@0
   399
    ns->height          = height;
sl@0
   400
sl@0
   401
    ns->idxFront        = 0;
sl@0
   402
    ns->idxNextFree     = 1;
sl@0
   403
    memcpy(&ns->colorFormat, imageFormat, sizeof(ns->colorFormat));
sl@0
   404
    ns->stride          = OWF_Image_GetStride(width, imageFormat);
sl@0
   405
    ns->referenceCount  = 1;
sl@0
   406
    ns->sendNotifications = OWF_TRUE;
sl@0
   407
    ns->protected       = OWF_FALSE;
sl@0
   408
sl@0
   409
    ok = OWF_Semaphore_Init(&ns->writer, nbufs);
sl@0
   410
    if (ok == 0)
sl@0
   411
    {
sl@0
   412
        ok = OWF_Mutex_Init(&ns->mutex);
sl@0
   413
    }
sl@0
   414
sl@0
   415
    ns->bufferSyncs = bufferSyncs;
sl@0
   416
sl@0
   417
    ns->handle = owfNativeStreamAddStream(ns);
sl@0
   418
    if (ns->handle == OWF_INVALID_HANDLE || ok != 0)
sl@0
   419
    {
sl@0
   420
        owfNativeStreamDoDestroy(ns);
sl@0
   421
        ns = NULL;
sl@0
   422
        return OWF_INVALID_HANDLE;
sl@0
   423
    }
sl@0
   424
sl@0
   425
    return ns->handle;
sl@0
   426
}
sl@0
   427
/*!---------------------------------------------------------------------------
sl@0
   428
 * Converts from external WFC native stream handle type to internal OWF native stream handle type.
sl@0
   429
 * The internal handle MUST be persistant. The external handle nmay already be persistant.
sl@0
   430
 * This method may fail, either due to memory, or due to the stream object not being supported by the compositor
sl@0
   431
 * @param publicStream The publicly defined stream handle
sl@0
   432
 * @param error			Pointer to store error code - optionally can be NULL
sl@0
   433
 * @return OWFNativeStreamType an equivalent internal stream handle
sl@0
   434
 *----------------------------------------------------------------------------**/
sl@0
   435
OWF_PUBLIC OWFNativeStreamType owfNativeStreamFromWFC(WFCNativeStreamType publicStream,OWF_STREAM_ERROR* errorReturn)
sl@0
   436
	{
sl@0
   437
	OWFNativeStreamType rv=(OWFNativeStreamType)publicStream;
sl@0
   438
	OWF_IMAGE_FORMAT format;
sl@0
   439
	owfNativeStreamGetHeader(rv,NULL,NULL,NULL,&format,NULL);
sl@0
   440
	if (format.pixelFormat==OWF_IMAGE_NOT_SUPPORTED)
sl@0
   441
		{
sl@0
   442
		if (errorReturn)
sl@0
   443
			{
sl@0
   444
			*errorReturn=OWF_STREAM_ERROR_INVALID_STREAM;
sl@0
   445
			}
sl@0
   446
		return OWF_INVALID_HANDLE; 
sl@0
   447
		}
sl@0
   448
	owfNativeStreamAddReference(rv);
sl@0
   449
	if (errorReturn)
sl@0
   450
		{
sl@0
   451
		*errorReturn=OWF_STREAM_ERROR_NONE;
sl@0
   452
		}
sl@0
   453
	return rv;
sl@0
   454
	}
sl@0
   455
sl@0
   456
/*!---------------------------------------------------------------------------
sl@0
   457
 *  Increase stream's reference count
sl@0
   458
 *
sl@0
   459
 *  \param stream           Stream handle
sl@0
   460
 *----------------------------------------------------------------------------*/
sl@0
   461
OWF_API_CALL void
sl@0
   462
owfNativeStreamAddReference(OWFNativeStreamType stream)
sl@0
   463
{
sl@0
   464
    OWF_NATIVE_STREAM* ns;
sl@0
   465
sl@0
   466
    GET_STREAM(ns, stream);
sl@0
   467
sl@0
   468
    CHECK_STREAM_NR();
sl@0
   469
sl@0
   470
    OWF_Mutex_Lock(&ns->mutex);
sl@0
   471
    ++(ns->referenceCount);
sl@0
   472
    OWF_Mutex_Unlock(&ns->mutex);
sl@0
   473
}
sl@0
   474
sl@0
   475
/*!---------------------------------------------------------------------------
sl@0
   476
 *  Decrease stream's reference count
sl@0
   477
 *
sl@0
   478
 *  \param stream           Stream handle
sl@0
   479
 *----------------------------------------------------------------------------*/
sl@0
   480
OWF_API_CALL void
sl@0
   481
owfNativeStreamRemoveReference(OWFNativeStreamType stream)
sl@0
   482
{
sl@0
   483
    OWF_NATIVE_STREAM* ns;
sl@0
   484
sl@0
   485
    GET_STREAM(ns, stream);
sl@0
   486
sl@0
   487
    CHECK_STREAM_NR();
sl@0
   488
    OWF_Mutex_Lock(&ns->mutex);
sl@0
   489
    --(ns->referenceCount);
sl@0
   490
    OWF_Mutex_Unlock(&ns->mutex);
sl@0
   491
}
sl@0
   492
sl@0
   493
/*!---------------------------------------------------------------------------
sl@0
   494
 *  Destroy stream. The stream isn't necessarily immediately destroyed, but
sl@0
   495
 *  only when it's reference count reaches zero.
sl@0
   496
 *
sl@0
   497
 *  \param stream           Stream handle
sl@0
   498
 *----------------------------------------------------------------------------*/
sl@0
   499
OWF_PUBLIC void
sl@0
   500
owfNativeStreamDestroy(OWFNativeStreamType stream)
sl@0
   501
{
sl@0
   502
    OWF_NATIVE_STREAM* ns;
sl@0
   503
sl@0
   504
    GET_STREAM(ns, stream);
sl@0
   505
    CHECK_STREAM_NR();
sl@0
   506
sl@0
   507
    owfNativeStreamDoDestroy(ns);
sl@0
   508
}
sl@0
   509
sl@0
   510
/*!---------------------------------------------------------------------------
sl@0
   511
 *  Acquire read buffer from stream
sl@0
   512
 *
sl@0
   513
 *  \param stream           Stream handle
sl@0
   514
 *
sl@0
   515
 *  \return Handle to next readable (unread since last write)
sl@0
   516
 *  buffer from the stream or OWF_INVALID_HANDLE if no unread buffers
sl@0
   517
 *  are available.
sl@0
   518
 *----------------------------------------------------------------------------*/
sl@0
   519
OWF_PUBLIC OWFNativeStreamBuffer
sl@0
   520
owfNativeStreamAcquireReadBuffer(OWFNativeStreamType stream)
sl@0
   521
{
sl@0
   522
    OWF_NATIVE_STREAM* ns;
sl@0
   523
    OWFNativeStreamBuffer buffer = OWF_INVALID_HANDLE;
sl@0
   524
sl@0
   525
    GET_STREAM(ns, stream);
sl@0
   526
    CHECK_STREAM(OWF_INVALID_HANDLE);
sl@0
   527
sl@0
   528
    OWF_Mutex_Lock(&ns->mutex);
sl@0
   529
sl@0
   530
    if (ns->bufferCount == 1)
sl@0
   531
    {
sl@0
   532
        /* Single buffered stream.
sl@0
   533
         * A "Write lock" must not block reading */
sl@0
   534
        buffer = INDEX_TO_HANDLE(0);
sl@0
   535
        ++(ns->bufferRefs[0]); /* Increase buffer's reference count */
sl@0
   536
    }
sl@0
   537
    else
sl@0
   538
    {
sl@0
   539
        buffer = INDEX_TO_HANDLE(ns->idxFront);
sl@0
   540
        /* Increase reference count of front buffer */
sl@0
   541
        ++(ns->bufferRefs[ns->idxFront]);
sl@0
   542
    }
sl@0
   543
    OWF_Mutex_Unlock(&ns->mutex);
sl@0
   544
sl@0
   545
    return buffer;
sl@0
   546
}
sl@0
   547
sl@0
   548
/*!---------------------------------------------------------------------------
sl@0
   549
 *  Release read buffer.
sl@0
   550
 *
sl@0
   551
 *  \param stream           Stream handle
sl@0
   552
 *  \param buf              Buffer handle
sl@0
   553
 *----------------------------------------------------------------------------*/
sl@0
   554
OWF_PUBLIC void
sl@0
   555
owfNativeStreamReleaseReadBuffer(OWFNativeStreamType stream,
sl@0
   556
                                 OWFNativeStreamBuffer buf)
sl@0
   557
{
sl@0
   558
    OWFint           i = 0;
sl@0
   559
    OWF_SYNC_DESC*   syncDesc = NULL;
sl@0
   560
sl@0
   561
    OWF_NATIVE_STREAM* ns;
sl@0
   562
sl@0
   563
    GET_STREAM(ns, stream);
sl@0
   564
    CHECK_STREAM_NR();
sl@0
   565
    CHECK_BUFFER_NR(buf);
sl@0
   566
sl@0
   567
    OWF_Mutex_Lock(&ns->mutex);
sl@0
   568
sl@0
   569
    i = HANDLE_TO_INDEX(buf);
sl@0
   570
sl@0
   571
    OWF_ASSERT(ns->bufferRefs[i] > 0);
sl@0
   572
sl@0
   573
    --(ns->bufferRefs[i]);
sl@0
   574
sl@0
   575
    syncDesc = &ns->bufferSyncs[i];
sl@0
   576
    if (syncDesc->sync != NULL)
sl@0
   577
    {
sl@0
   578
        DPRINT(("signalling synched buffer(%p, %x)",
sl@0
   579
                stream, syncDesc->sync));
sl@0
   580
sl@0
   581
        eglSignalSyncKHR(syncDesc->dpy, syncDesc->sync, EGL_SIGNALED_KHR);
sl@0
   582
        syncDesc->dpy = EGL_NO_DISPLAY;
sl@0
   583
        syncDesc->sync = NULL;
sl@0
   584
    }
sl@0
   585
    OWF_Mutex_Unlock(&ns->mutex);
sl@0
   586
}
sl@0
   587
sl@0
   588
/*!---------------------------------------------------------------------------
sl@0
   589
 *  Acquires writable buffer from a stream. The caller has exclusive access
sl@0
   590
 *  to returned buffer until the buffer is commited to stream by
sl@0
   591
 *  calling ReleaseWriteBuffer.
sl@0
   592
 *
sl@0
   593
 *  \param stream           Stream handle
sl@0
   594
 *
sl@0
   595
 *  \return Handle to next writable buffer or OWF_INVALID_HANDLE if no such
sl@0
   596
 *  buffer is available.
sl@0
   597
 *----------------------------------------------------------------------------*/
sl@0
   598
OWF_PUBLIC OWFNativeStreamBuffer
sl@0
   599
owfNativeStreamAcquireWriteBuffer(OWFNativeStreamType stream)
sl@0
   600
{
sl@0
   601
    OWFNativeStreamBuffer   buffer = OWF_INVALID_HANDLE;
sl@0
   602
sl@0
   603
    OWF_NATIVE_STREAM* ns;
sl@0
   604
sl@0
   605
    GET_STREAM(ns, stream);
sl@0
   606
    CHECK_STREAM(OWF_INVALID_HANDLE);
sl@0
   607
sl@0
   608
    OWF_Mutex_Lock(&ns->mutex);
sl@0
   609
sl@0
   610
    /* write always blocks */
sl@0
   611
    OWF_Semaphore_Wait(&ns->writer);
sl@0
   612
sl@0
   613
    if (ns->bufferCount == 1)
sl@0
   614
    {
sl@0
   615
        /* Single buffered stream */
sl@0
   616
        buffer = INDEX_TO_HANDLE(0);
sl@0
   617
        ++(ns->bufferRefs[0]); /* Increase buffer's reference count */
sl@0
   618
    }
sl@0
   619
    else
sl@0
   620
    {
sl@0
   621
        if (ns->idxFront == ns->idxNextFree)
sl@0
   622
        {
sl@0
   623
            buffer = OWF_INVALID_HANDLE;
sl@0
   624
        }
sl@0
   625
        else
sl@0
   626
        {
sl@0
   627
            buffer = INDEX_TO_HANDLE(ns->idxNextFree);
sl@0
   628
sl@0
   629
            ++(ns->bufferRefs[ns->idxNextFree]); /* Increase buffer's
sl@0
   630
                                                    reference count */
sl@0
   631
            ++(ns->idxNextFree); /* Move pointer to next buffer */
sl@0
   632
            if (ns->idxNextFree == ns->bufferCount)
sl@0
   633
            {
sl@0
   634
                ns->idxNextFree = 0;
sl@0
   635
            }
sl@0
   636
        }
sl@0
   637
    }
sl@0
   638
sl@0
   639
    if (buffer != OWF_INVALID_HANDLE)
sl@0
   640
    {
sl@0
   641
        /* Signal associated 'old' sync because
sl@0
   642
         * buffer gets 'dropped', never consumed
sl@0
   643
         */
sl@0
   644
sl@0
   645
        OWFint           bufferIndex;
sl@0
   646
        OWF_SYNC_DESC*   syncDesc;
sl@0
   647
sl@0
   648
        bufferIndex = HANDLE_TO_INDEX(buffer);
sl@0
   649
        syncDesc = &ns->bufferSyncs[bufferIndex];
sl@0
   650
sl@0
   651
        if (syncDesc->sync != NULL)
sl@0
   652
        {
sl@0
   653
            DPRINT(("dropping synched buffer(%p, %x)",
sl@0
   654
                    stream, syncDesc->sync));
sl@0
   655
sl@0
   656
            eglSignalSyncKHR(syncDesc->dpy, syncDesc->sync, EGL_SIGNALED_KHR);
sl@0
   657
            syncDesc->dpy = EGL_NO_DISPLAY;
sl@0
   658
            syncDesc->sync = NULL;
sl@0
   659
        }
sl@0
   660
    }
sl@0
   661
sl@0
   662
    OWF_Mutex_Unlock(&ns->mutex);
sl@0
   663
sl@0
   664
    return buffer;
sl@0
   665
}
sl@0
   666
sl@0
   667
/*!---------------------------------------------------------------------------
sl@0
   668
 *  Commit write buffer to stream.
sl@0
   669
 *
sl@0
   670
 *  \param stream           Stream handle
sl@0
   671
 *  \param buf              Buffer handle
sl@0
   672
 *  \param sync             EGLSync object which is signalled when
sl@0
   673
 *                          release buffer gets consumed or dropped
sl@0
   674
 *----------------------------------------------------------------------------*/
sl@0
   675
OWF_PUBLIC void
sl@0
   676
owfNativeStreamReleaseWriteBuffer(OWFNativeStreamType stream,
sl@0
   677
                                 OWFNativeStreamBuffer buf,
sl@0
   678
                                 EGLDisplay dpy,
sl@0
   679
                                 EGLSyncKHR sync)
sl@0
   680
{
sl@0
   681
    OWFint                  bufferIndex = 0;
sl@0
   682
sl@0
   683
    OWF_NATIVE_STREAM* ns;
sl@0
   684
sl@0
   685
    GET_STREAM(ns, stream);
sl@0
   686
    CHECK_STREAM_NR();
sl@0
   687
sl@0
   688
    CHECK_BUFFER_NR(buf);
sl@0
   689
sl@0
   690
    OWF_Mutex_Lock(&ns->mutex);
sl@0
   691
sl@0
   692
    bufferIndex = HANDLE_TO_INDEX(buf);
sl@0
   693
    OWF_ASSERT(ns->bufferRefs[bufferIndex] > 0);
sl@0
   694
sl@0
   695
    /* Look up correct buffer (naive search) */
sl@0
   696
    --(ns->bufferRefs[bufferIndex]); /* Decrease buffer's reference count */
sl@0
   697
    ns->idxFront = bufferIndex; /* Update front buffer to point to new
sl@0
   698
                                   front buffer */
sl@0
   699
sl@0
   700
    OWF_Semaphore_Post(&ns->writer);
sl@0
   701
sl@0
   702
    /* sync object bookkeeping */
sl@0
   703
    ns->bufferSyncs[bufferIndex].dpy = dpy;
sl@0
   704
    ns->bufferSyncs[bufferIndex].sync = sync;
sl@0
   705
sl@0
   706
    OWF_Mutex_Unlock(&ns->mutex);
sl@0
   707
sl@0
   708
    DPRINT(("Stream updated %p", stream ));
sl@0
   709
sl@0
   710
    owfNativeStreamNotifyObservers(stream, OWF_STREAM_UPDATED);
sl@0
   711
}
sl@0
   712
sl@0
   713
/*!---------------------------------------------------------------------------
sl@0
   714
 *  Register stream content observer. The observer will receive buffer
sl@0
   715
 *  modification event from the stream whenever a buffer is committed.
sl@0
   716
 *
sl@0
   717
 *  \param stream           Stream handle
sl@0
   718
 *  \param observer         Stream observer
sl@0
   719
 *  \param data             Optional data to pass to observer callback
sl@0
   720
 *                          function when event is dispatched.
sl@0
   721
 *----------------------------------------------------------------------------*/
sl@0
   722
OWF_PUBLIC OWF_STREAM_ERROR
sl@0
   723
owfNativeStreamAddObserver(OWFNativeStreamType stream,
sl@0
   724
                           OWFStreamCallback observer,
sl@0
   725
                           void* data)
sl@0
   726
{
sl@0
   727
    OWF_NODE*               node = NULL;
sl@0
   728
    OWFStreamCallbackData* cbdata = NULL;
sl@0
   729
sl@0
   730
    OWF_NATIVE_STREAM* ns;
sl@0
   731
sl@0
   732
    GET_STREAM(ns, stream);
sl@0
   733
    CHECK_STREAM(OWF_STREAM_ERROR_INVALID_STREAM);
sl@0
   734
sl@0
   735
    /* exclusive access only for you my friend. */
sl@0
   736
    OWF_Mutex_Lock(&ns->mutex);
sl@0
   737
sl@0
   738
sl@0
   739
sl@0
   740
    /* new observer. allocate a slot with extra space needed
sl@0
   741
     * to store the callback data. */
sl@0
   742
    node = xalloc(sizeof(OWF_NODE) + sizeof(OWFStreamCallbackData), 1);
sl@0
   743
    if (!node)
sl@0
   744
    {
sl@0
   745
        OWF_Mutex_Unlock(&ns->mutex);
sl@0
   746
        return OWF_STREAM_ERROR_OUT_OF_MEMORY;
sl@0
   747
    }
sl@0
   748
    
sl@0
   749
    /* callback data is directly after node in the memory*/
sl@0
   750
    cbdata = (OWFStreamCallbackData*) &node[1];
sl@0
   751
    cbdata->callback = observer;
sl@0
   752
    cbdata->data = data;
sl@0
   753
    /* for convenience. */
sl@0
   754
    node->data = (void*) cbdata;
sl@0
   755
sl@0
   756
sl@0
   757
    if (node)
sl@0
   758
    {
sl@0
   759
        /* append to callback-chain */
sl@0
   760
        ns->observers = OWF_List_Append(ns->observers, node);
sl@0
   761
    }
sl@0
   762
sl@0
   763
    OWF_Mutex_Unlock(&ns->mutex);
sl@0
   764
sl@0
   765
    return OWF_STREAM_ERROR_NONE;
sl@0
   766
}
sl@0
   767
sl@0
   768
/*!---------------------------------------------------------------------------
sl@0
   769
 *  Remove stream content observer.
sl@0
   770
 *  Observer or Data can be NULL indicating search only checks for other member.
sl@0
   771
 *  Both must not be NULL.
sl@0
   772
 *  \param stream           Stream handle
sl@0
   773
 *  \param observer         Observer to remove
sl@0
   774
 *  \param data             Identifying client data
sl@0
   775
 *
sl@0
   776
 *  \return Zero if the observer was removed successfully, otherwise non-zero
sl@0
   777
 *  (OWF_STREAM_ERROR_INVALID_STREAM if the stream is invalid;
sl@0
   778
 *   OWF_STREAM_ERROR_INVALID_OBSERVER if the observer is invalid.)
sl@0
   779
 *----------------------------------------------------------------------------*/
sl@0
   780
OWF_PUBLIC OWFint
sl@0
   781
owfNativeStreamRemoveObserver(OWFNativeStreamType stream,
sl@0
   782
                              OWFStreamCallback observer,
sl@0
   783
                              void* data)
sl@0
   784
{
sl@0
   785
    OWF_NODE*               node = NULL;
sl@0
   786
    OWFStreamCallbackData   tmp;
sl@0
   787
sl@0
   788
    NODECMPFUNC search=ObserversEqual;
sl@0
   789
sl@0
   790
    OWF_NATIVE_STREAM* ns;
sl@0
   791
sl@0
   792
    GET_STREAM(ns, stream);
sl@0
   793
    CHECK_STREAM(OWF_STREAM_ERROR_INVALID_STREAM);
sl@0
   794
sl@0
   795
    OWF_Mutex_Lock(&ns->mutex);
sl@0
   796
sl@0
   797
    tmp.callback = observer;
sl@0
   798
    tmp.data = data;
sl@0
   799
    if (!observer)
sl@0
   800
    {
sl@0
   801
        if (!data)
sl@0
   802
        {
sl@0
   803
            return OWF_STREAM_ERROR_INVALID_OBSERVER;
sl@0
   804
        }
sl@0
   805
        else
sl@0
   806
        {
sl@0
   807
            search=ObserverDatasEqual;
sl@0
   808
        }
sl@0
   809
    }
sl@0
   810
    else
sl@0
   811
    {
sl@0
   812
        if (!data)
sl@0
   813
        {
sl@0
   814
            search=ObserverFuncsEqual;
sl@0
   815
        }
sl@0
   816
    }
sl@0
   817
    
sl@0
   818
    node = OWF_List_Find(ns->observers, search, &tmp);
sl@0
   819
sl@0
   820
    if (node)
sl@0
   821
    {
sl@0
   822
        /* taketh the observer away */
sl@0
   823
        ns->observers = OWF_List_Remove(ns->observers, node);
sl@0
   824
        /*  to death */
sl@0
   825
        xfree(node);
sl@0
   826
    }
sl@0
   827
sl@0
   828
    OWF_Mutex_Unlock(&ns->mutex);
sl@0
   829
sl@0
   830
    return node ? OWF_STREAM_ERROR_NONE :
sl@0
   831
                  OWF_STREAM_ERROR_INVALID_OBSERVER;
sl@0
   832
}
sl@0
   833
sl@0
   834
/*!---------------------------------------------------------------------------
sl@0
   835
 *  Enable/disable stream content notifications.
sl@0
   836
 *
sl@0
   837
 *  \param stream           Stream handle
sl@0
   838
 *  \param send             Boolean value indicating whether the stream should
sl@0
   839
 *                          send content notifications to its observers.
sl@0
   840
 *----------------------------------------------------------------------------*/
sl@0
   841
OWF_API_CALL void
sl@0
   842
owfNativeStreamEnableUpdateNotifications(OWFNativeStreamType stream,
sl@0
   843
                                         OWFboolean send)
sl@0
   844
{
sl@0
   845
    OWF_NATIVE_STREAM* ns;
sl@0
   846
sl@0
   847
    GET_STREAM(ns, stream);
sl@0
   848
    CHECK_STREAM_NR();
sl@0
   849
sl@0
   850
    OWF_Mutex_Lock(&ns->mutex);
sl@0
   851
sl@0
   852
    ns->sendNotifications = send;
sl@0
   853
sl@0
   854
    OWF_Mutex_Unlock(&ns->mutex);
sl@0
   855
}
sl@0
   856
sl@0
   857
/*!---------------------------------------------------------------------------
sl@0
   858
 *  Return pointer to stream buffer's pixel data. The buffer must be
sl@0
   859
 *  a valid read/write buffer.
sl@0
   860
 *
sl@0
   861
 *  \param stream           Stream handle
sl@0
   862
 *  \param buffer           Buffer handle
sl@0
   863
 *
sl@0
   864
 *  \return Pointer to buffers pixel data.
sl@0
   865
 *----------------------------------------------------------------------------*/
sl@0
   866
OWF_PUBLIC void*
sl@0
   867
owfNativeStreamGetBufferPtr(OWFNativeStreamType stream,
sl@0
   868
                            OWFNativeStreamBuffer buffer)
sl@0
   869
{
sl@0
   870
    void*                   bufferPtr = NULL;
sl@0
   871
sl@0
   872
    OWF_NATIVE_STREAM* ns;
sl@0
   873
sl@0
   874
    GET_STREAM(ns, stream);
sl@0
   875
    CHECK_STREAM(NULL);
sl@0
   876
sl@0
   877
    /* Check that buffer has been locked */
sl@0
   878
    OWF_ASSERT(ns->bufferRefs[HANDLE_TO_INDEX(buffer)] > 0);
sl@0
   879
sl@0
   880
    OWF_Mutex_Lock(&ns->mutex);
sl@0
   881
sl@0
   882
    bufferPtr = ns->bufferList[HANDLE_TO_INDEX(buffer)];
sl@0
   883
sl@0
   884
    OWF_Mutex_Unlock(&ns->mutex);
sl@0
   885
sl@0
   886
    return bufferPtr;
sl@0
   887
}
sl@0
   888
sl@0
   889
/*!---------------------------------------------------------------------------
sl@0
   890
 *  Set/reset stream's protection flag. This flag is used for preventing the
sl@0
   891
 *  user from deleting a stream that s/he doesn't really own or should
sl@0
   892
 *  not twiddle with too much (on-screen context's target stream, for example)
sl@0
   893
 *
sl@0
   894
 *  \param stream           Stream handle
sl@0
   895
 *  \param flag             Protection status
sl@0
   896
 *----------------------------------------------------------------------------*/
sl@0
   897
OWF_API_CALL void
sl@0
   898
owfNativeStreamSetProtectionFlag(OWFNativeStreamType stream, OWFboolean flag)
sl@0
   899
{
sl@0
   900
    OWF_NATIVE_STREAM* ns;
sl@0
   901
sl@0
   902
    GET_STREAM(ns, stream);
sl@0
   903
    CHECK_STREAM_NR();
sl@0
   904
sl@0
   905
    OWF_Mutex_Lock(&ns->mutex);
sl@0
   906
    ns->protected = flag;
sl@0
   907
    OWF_Mutex_Unlock(&ns->mutex);
sl@0
   908
}
sl@0
   909
sl@0
   910
sl@0
   911
/*!---------------------------------------------------------------------------
sl@0
   912
 * Get stream's image header
sl@0
   913
 *
sl@0
   914
 * \param stream            Stream handle
sl@0
   915
 * \param width             Stream width
sl@0
   916
 * \param height            Stream height
sl@0
   917
 * \param stride            Stream stride
sl@0
   918
 * \param format            Stream format
sl@0
   919
 * \param pixelSize         Stream pixelSize
sl@0
   920
 *
sl@0
   921
 * All the parameters above, except stream handle, are pointers to locations
sl@0
   922
 * where the particular value should be written to. Passing in a NULL
sl@0
   923
 * pointer means that the particular values is of no interest to the caller.
sl@0
   924
 *
sl@0
   925
 * E.g. to query only width & height one would call this function with
sl@0
   926
 * parameters (stream_handle, &width, &height, NULL, NULL, NULL);
sl@0
   927
 *
sl@0
   928
 *----------------------------------------------------------------------------*/
sl@0
   929
OWF_PUBLIC void
sl@0
   930
owfNativeStreamGetHeader(OWFNativeStreamType stream,
sl@0
   931
                           OWFint* width,
sl@0
   932
                           OWFint* height,
sl@0
   933
                           OWFint* stride,
sl@0
   934
                           OWF_IMAGE_FORMAT* format,
sl@0
   935
                           OWFint* pixelSize)
sl@0
   936
{
sl@0
   937
    OWF_NATIVE_STREAM* ns;
sl@0
   938
sl@0
   939
    GET_STREAM(ns, stream);
sl@0
   940
sl@0
   941
    CHECK_STREAM_NR();
sl@0
   942
sl@0
   943
    if (width)
sl@0
   944
    {
sl@0
   945
        *width  = ns->width;
sl@0
   946
    }
sl@0
   947
    if (height)
sl@0
   948
    {
sl@0
   949
        *height = ns->height;
sl@0
   950
    }
sl@0
   951
    if (stride)
sl@0
   952
    {
sl@0
   953
        *stride = ns->stride;
sl@0
   954
    }
sl@0
   955
    if (format)
sl@0
   956
    {
sl@0
   957
        memcpy(format, &ns->colorFormat, sizeof(*format));
sl@0
   958
    }
sl@0
   959
sl@0
   960
    if (pixelSize)
sl@0
   961
    {
sl@0
   962
        *pixelSize = OWF_Image_GetFormatPixelSize(ns->colorFormat.pixelFormat);
sl@0
   963
    }
sl@0
   964
}
sl@0
   965
sl@0
   966
#ifdef __cplusplus
sl@0
   967
}
sl@0
   968
sl@0
   969
#endif