os/graphics/egl/eglrefimpl/src/session.cpp
author sl@SLION-WIN7.fritz.box
Fri, 15 Jun 2012 03:10:57 +0200
changeset 0 bde4ae8d615e
permissions -rw-r--r--
First public contribution.
sl@0
     1
// Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
sl@0
     2
// All rights reserved.
sl@0
     3
// This component and the accompanying materials are made available
sl@0
     4
// under the terms of "Eclipse Public License v1.0"
sl@0
     5
// which accompanies this distribution, and is available
sl@0
     6
// at the URL "http://www.eclipse.org/legal/epl-v10.html".
sl@0
     7
//
sl@0
     8
// Initial Contributors:
sl@0
     9
// Nokia Corporation - initial contribution.
sl@0
    10
//
sl@0
    11
// Contributors:
sl@0
    12
//
sl@0
    13
// Description:
sl@0
    14
// Reference EGL implementation to support EGL sync objects and OpenWF extensions
sl@0
    15
sl@0
    16
#include "eglprivate.h"
sl@0
    17
sl@0
    18
const TInt KEglMajorVersion = 1;
sl@0
    19
const TInt KEglMinorVersion = 4;
sl@0
    20
sl@0
    21
#define KEglClientApis  ""
sl@0
    22
#define KEglVendor      "Nokia"
sl@0
    23
#define KEglVersion     "1.4 Reference EGL"
sl@0
    24
#define KEglExtensions  "EGL_KHR_reusable_sync" /* additonal extensions should be added beginning with a space */ \
sl@0
    25
                        " EGL_NOK__private__signal_sync"
sl@0
    26
sl@0
    27
// Helper macros for repetitive task
sl@0
    28
//
sl@0
    29
#define CHECK_FOR_NULL_DISPLAY(handle, retval) \
sl@0
    30
    if (handle == EGL_NO_DISPLAY) \
sl@0
    31
        { \
sl@0
    32
        SetError(EGL_BAD_DISPLAY); \
sl@0
    33
        return retval; \
sl@0
    34
        }
sl@0
    35
sl@0
    36
#define CHECK_FOR_NULL_SYNCOBJ(handle, retval) \
sl@0
    37
    if (handle == EGL_NO_SYNC_KHR) \
sl@0
    38
        { \
sl@0
    39
        SetError(EGL_BAD_PARAMETER); \
sl@0
    40
        return retval; \
sl@0
    41
        }
sl@0
    42
sl@0
    43
#define GET_DISPLAY_RETURN_IF_ERR(drv, display, handle, retval) \
sl@0
    44
    CEglDisplay* display = iDriver.FindDisplay(handle); \
sl@0
    45
    if (!display) \
sl@0
    46
        { \
sl@0
    47
        drv.Unlock(); \
sl@0
    48
        SetError(EGL_BAD_DISPLAY); \
sl@0
    49
        return retval; \
sl@0
    50
        } \
sl@0
    51
    if (!display->IsInitialized()) \
sl@0
    52
        { \
sl@0
    53
        drv.Unlock(); \
sl@0
    54
        SetError(EGL_NOT_INITIALIZED); \
sl@0
    55
        return retval; \
sl@0
    56
        }
sl@0
    57
sl@0
    58
#define GET_SYNCOBJ_RETURN_IF_ERR(drv, display, sync, handle, retval) \
sl@0
    59
    CEglSync* sync = display->FindSyncObj(handle); \
sl@0
    60
    if (!sync) \
sl@0
    61
        { \
sl@0
    62
        drv.Unlock(); \
sl@0
    63
        SetError(EGL_BAD_PARAMETER); \
sl@0
    64
        return retval; \
sl@0
    65
        } \
sl@0
    66
    if (sync->IsDestroyed()) /* sync obj has been marked as destroyed */ \
sl@0
    67
        { \
sl@0
    68
        drv.Unlock(); \
sl@0
    69
        SetError(EGL_BAD_PARAMETER); \
sl@0
    70
        return retval; \
sl@0
    71
        }
sl@0
    72
                                                                
sl@0
    73
CEglThreadSession::CEglThreadSession(CEglDriver& aDriver):
sl@0
    74
	iDriver(aDriver),
sl@0
    75
	iError(EGL_SUCCESS)
sl@0
    76
	{
sl@0
    77
	}
sl@0
    78
sl@0
    79
CEglThreadSession::~CEglThreadSession()
sl@0
    80
	{
sl@0
    81
	CEglDriver::Close();
sl@0
    82
	}
sl@0
    83
sl@0
    84
CEglThreadSession* CEglThreadSession::Static()
sl@0
    85
	{
sl@0
    86
	CEglThreadSession* es = reinterpret_cast<CEglThreadSession*>(Dll::Tls());
sl@0
    87
	if (es)
sl@0
    88
		{
sl@0
    89
		return es;
sl@0
    90
		}
sl@0
    91
sl@0
    92
	const TInt err = CEglDriver::Open();
sl@0
    93
	if (err != KErrNone)
sl@0
    94
		{
sl@0
    95
		return NULL;
sl@0
    96
		}
sl@0
    97
sl@0
    98
	// CEglDriver is reference counted. As we successfuly open the driver, pls.iDriver will be non-null
sl@0
    99
	// and it should be safe to cache the pointer inside CEglThreadSession
sl@0
   100
	CEglDriver* drv = CEglDriver::GetDriver();
sl@0
   101
	__ASSERT_DEBUG(drv, User::Panic(KEglPanicCategory, EEglPanicDriverNull));
sl@0
   102
sl@0
   103
	// create session object on default thread's heap
sl@0
   104
	es = new CEglThreadSession(*drv);
sl@0
   105
	if (!es || Dll::SetTls(es)!= KErrNone)
sl@0
   106
		{
sl@0
   107
		delete es;
sl@0
   108
		return NULL;
sl@0
   109
		}
sl@0
   110
	
sl@0
   111
	return es;
sl@0
   112
	}
sl@0
   113
sl@0
   114
void CEglThreadSession::SetError(EGLint aError)
sl@0
   115
	{
sl@0
   116
	// EGL spec section 3.1, GetError will return the status of the most recent EGL function call
sl@0
   117
	// so we will always override the error status
sl@0
   118
	iError = aError;
sl@0
   119
	}
sl@0
   120
sl@0
   121
EGLint CEglThreadSession::EglGetError()
sl@0
   122
	{
sl@0
   123
	// eglGetError always succeed so it will set error state to EGL_SUCCESS
sl@0
   124
	const EGLint lastError = iError;
sl@0
   125
	iError = EGL_SUCCESS;
sl@0
   126
	return lastError;
sl@0
   127
	}
sl@0
   128
sl@0
   129
EGLDisplay CEglThreadSession::EglGetDisplay(NativeDisplayType aDisplayId)
sl@0
   130
    {
sl@0
   131
    // EGL spec section 3.2: we do not need to raise EGL error when GetDisplay fails
sl@0
   132
    SetError(EGL_SUCCESS);
sl@0
   133
sl@0
   134
    if (aDisplayId != EGL_DEFAULT_DISPLAY)
sl@0
   135
        {
sl@0
   136
        return EGL_NO_DISPLAY;
sl@0
   137
        }
sl@0
   138
sl@0
   139
    // default display is created when driver is initialised the first time and will
sl@0
   140
    // be destroyed when all threads within process have called eglReleaseThread
sl@0
   141
sl@0
   142
    return KEglDefaultDisplayHandle;
sl@0
   143
    }
sl@0
   144
sl@0
   145
EGLBoolean CEglThreadSession::EglInitialize(EGLDisplay aDisplay, EGLint* aMajor, EGLint* aMinor)
sl@0
   146
    {
sl@0
   147
    SetError(EGL_SUCCESS);
sl@0
   148
    
sl@0
   149
    CHECK_FOR_NULL_DISPLAY(aDisplay, EGL_FALSE)
sl@0
   150
sl@0
   151
    iDriver.Lock();
sl@0
   152
    CEglDisplay* display = iDriver.FindDisplay(aDisplay);
sl@0
   153
    if (!display)
sl@0
   154
        {
sl@0
   155
        iDriver.Unlock();
sl@0
   156
        SetError(EGL_BAD_DISPLAY);
sl@0
   157
        return EGL_FALSE;
sl@0
   158
        }
sl@0
   159
sl@0
   160
    const TInt err = display->Initialize();
sl@0
   161
    iDriver.Unlock();
sl@0
   162
    
sl@0
   163
    if (err != KErrNone)
sl@0
   164
        {
sl@0
   165
        SetError(EGL_NOT_INITIALIZED);
sl@0
   166
        return EGL_FALSE;
sl@0
   167
        }
sl@0
   168
sl@0
   169
    if (aMajor)
sl@0
   170
        {
sl@0
   171
        *aMajor = KEglMajorVersion;
sl@0
   172
        }
sl@0
   173
    if (aMinor)
sl@0
   174
        {
sl@0
   175
        *aMinor = KEglMinorVersion;
sl@0
   176
        }
sl@0
   177
sl@0
   178
    return EGL_TRUE;
sl@0
   179
    }
sl@0
   180
sl@0
   181
EGLBoolean CEglThreadSession::EglTerminate(EGLDisplay aDisplay)
sl@0
   182
    {
sl@0
   183
    SetError(EGL_SUCCESS);
sl@0
   184
    
sl@0
   185
    CHECK_FOR_NULL_DISPLAY(aDisplay, EGL_FALSE)
sl@0
   186
sl@0
   187
    iDriver.Lock();
sl@0
   188
    CEglDisplay* display = iDriver.FindDisplay(aDisplay);
sl@0
   189
    if (!display)
sl@0
   190
        {
sl@0
   191
        iDriver.Unlock();
sl@0
   192
        SetError(EGL_BAD_DISPLAY);
sl@0
   193
        return EGL_FALSE;
sl@0
   194
        }
sl@0
   195
sl@0
   196
    display->Terminate();
sl@0
   197
    iDriver.Unlock();
sl@0
   198
    
sl@0
   199
    return EGL_TRUE;
sl@0
   200
    }
sl@0
   201
sl@0
   202
TFuncPtrEglProc CEglThreadSession::EglGetProcAddress(const char* aName)
sl@0
   203
    {
sl@0
   204
    SetError(EGL_SUCCESS);
sl@0
   205
        
sl@0
   206
    if(!aName)
sl@0
   207
        {
sl@0
   208
        return NULL;
sl@0
   209
        }
sl@0
   210
    
sl@0
   211
    // EGL spec does not mention about raising error if requested function not found
sl@0
   212
    // This implementation does not set error and leave thread state unmodified
sl@0
   213
    return iDriver.GetProcAddress(aName);
sl@0
   214
    }
sl@0
   215
sl@0
   216
const char* CEglThreadSession::EglQueryString(EGLDisplay aDisplay, EGLint aName)
sl@0
   217
    {
sl@0
   218
    SetError(EGL_SUCCESS);
sl@0
   219
    
sl@0
   220
    const char* str = NULL;
sl@0
   221
sl@0
   222
    CHECK_FOR_NULL_DISPLAY(aDisplay, str)
sl@0
   223
sl@0
   224
    iDriver.Lock();
sl@0
   225
    GET_DISPLAY_RETURN_IF_ERR(iDriver, display, aDisplay, str)
sl@0
   226
    iDriver.Unlock();
sl@0
   227
sl@0
   228
    switch (aName)
sl@0
   229
        {
sl@0
   230
        case EGL_CLIENT_APIS:
sl@0
   231
            str = KEglClientApis;
sl@0
   232
            break;
sl@0
   233
        case EGL_EXTENSIONS:
sl@0
   234
            str = KEglExtensions;
sl@0
   235
            break;
sl@0
   236
        case EGL_VENDOR:
sl@0
   237
            str = KEglVendor;
sl@0
   238
            break;
sl@0
   239
        case EGL_VERSION:
sl@0
   240
            str = KEglVersion;
sl@0
   241
            break;
sl@0
   242
        default:
sl@0
   243
            SetError(EGL_BAD_PARAMETER);
sl@0
   244
            break;
sl@0
   245
        }
sl@0
   246
sl@0
   247
    return str;
sl@0
   248
    }
sl@0
   249
sl@0
   250
EGLSyncKHR CEglThreadSession::EglCreateSyncKhr(EGLDisplay aDisplay, EGLenum aType, const EGLint *aAttribList)
sl@0
   251
    {
sl@0
   252
    SetError(EGL_SUCCESS);
sl@0
   253
    
sl@0
   254
    CHECK_FOR_NULL_DISPLAY(aDisplay, EGL_NO_SYNC_KHR)
sl@0
   255
sl@0
   256
    if (aType != EGL_SYNC_REUSABLE_KHR || (aAttribList && *aAttribList != EGL_NONE))
sl@0
   257
        {
sl@0
   258
        SetError(EGL_BAD_ATTRIBUTE);
sl@0
   259
        return EGL_NO_SYNC_KHR;
sl@0
   260
        }
sl@0
   261
    
sl@0
   262
    iDriver.Lock();
sl@0
   263
    GET_DISPLAY_RETURN_IF_ERR(iDriver, display, aDisplay, EGL_NO_SYNC_KHR)
sl@0
   264
    
sl@0
   265
    CEglSync* syncObj = display->CreateSyncObj();
sl@0
   266
    iDriver.Unlock();
sl@0
   267
    
sl@0
   268
    if (!syncObj)
sl@0
   269
        {
sl@0
   270
        SetError(EGL_BAD_ALLOC);
sl@0
   271
        return EGL_NO_SYNC_KHR;
sl@0
   272
        }
sl@0
   273
sl@0
   274
    return reinterpret_cast<EGLSyncKHR>(syncObj);
sl@0
   275
    }
sl@0
   276
sl@0
   277
EGLBoolean CEglThreadSession::EglDestroySyncKhr(EGLDisplay aDisplay, EGLSyncKHR aSync)
sl@0
   278
    {
sl@0
   279
    SetError(EGL_SUCCESS);
sl@0
   280
    
sl@0
   281
    CHECK_FOR_NULL_DISPLAY(aDisplay, EGL_FALSE)
sl@0
   282
    CHECK_FOR_NULL_SYNCOBJ(aSync, EGL_FALSE)
sl@0
   283
sl@0
   284
    iDriver.Lock();
sl@0
   285
    GET_DISPLAY_RETURN_IF_ERR(iDriver, display, aDisplay, EGL_FALSE)
sl@0
   286
    
sl@0
   287
    const TInt err = display->DestroySyncObj(aSync);
sl@0
   288
    iDriver.Unlock();
sl@0
   289
sl@0
   290
    if (err != KErrNone)
sl@0
   291
        {
sl@0
   292
        SetError(EGL_BAD_PARAMETER);
sl@0
   293
        return EGL_FALSE;
sl@0
   294
        }
sl@0
   295
sl@0
   296
    return EGL_TRUE;
sl@0
   297
    }
sl@0
   298
sl@0
   299
EGLint CEglThreadSession::EglClientWaitSyncKhr(EGLDisplay aDisplay, EGLSyncKHR aSync, EGLint aFlags, EGLTimeKHR aTimeout)
sl@0
   300
    {
sl@0
   301
    SetError(EGL_SUCCESS);
sl@0
   302
    
sl@0
   303
    CHECK_FOR_NULL_DISPLAY(aDisplay, EGL_FALSE)
sl@0
   304
    CHECK_FOR_NULL_SYNCOBJ(aSync, EGL_FALSE)
sl@0
   305
    
sl@0
   306
    const EGLint supportedFlags = EGL_SYNC_FLUSH_COMMANDS_BIT_KHR;
sl@0
   307
    if (aFlags & ~supportedFlags)
sl@0
   308
        {
sl@0
   309
        SetError(EGL_BAD_PARAMETER);
sl@0
   310
        return EGL_FALSE;
sl@0
   311
        }
sl@0
   312
    
sl@0
   313
    iDriver.Lock();
sl@0
   314
    GET_DISPLAY_RETURN_IF_ERR(iDriver, display, aDisplay, EGL_FALSE)
sl@0
   315
    GET_SYNCOBJ_RETURN_IF_ERR(iDriver, display, syncObj, aSync, EGL_FALSE)
sl@0
   316
sl@0
   317
    // increment refcount to mark this sync obj in use and prevent it from being destroyed when other thread calls eglDestroySyncKHR or eglTerminate
sl@0
   318
    syncObj->Open();
sl@0
   319
    
sl@0
   320
    // release display lock as we're going to wait on sync object after this point, not releasing display lock at this 
sl@0
   321
    // point will cause deadlock
sl@0
   322
    // coverity[stale]
sl@0
   323
    iDriver.Unlock();
sl@0
   324
sl@0
   325
    // sync obj refcount has been incremented so it won't get destroyed even if other thread call eglDestroySyncKHR or eglTerminate
sl@0
   326
    // at this point
sl@0
   327
sl@0
   328
    // we do not support client apis, so flushing flags will be ignored in this implementation
sl@0
   329
    EGLint err = syncObj->Wait(aTimeout);
sl@0
   330
sl@0
   331
    // decrement refcount
sl@0
   332
    // sync obj will be destroyted if refcount is 0 e.g. other thread issues eglDestroySyncKHR or eglTerminate while this thread
sl@0
   333
    // is waiting on it
sl@0
   334
    iDriver.Lock();
sl@0
   335
    syncObj->Close();
sl@0
   336
    iDriver.Unlock();
sl@0
   337
sl@0
   338
    // we do not check error here as it is passed back to caller
sl@0
   339
sl@0
   340
    return err;
sl@0
   341
    }
sl@0
   342
sl@0
   343
EGLBoolean CEglThreadSession::EglSignalSyncKhr(EGLDisplay aDisplay, EGLSyncKHR aSync, EGLenum aMode)
sl@0
   344
    {
sl@0
   345
    const EGLint err = EglSignalSyncInternal(aDisplay, aSync, aMode);
sl@0
   346
    SetError(err);
sl@0
   347
    return err == EGL_SUCCESS;
sl@0
   348
    }
sl@0
   349
sl@0
   350
EGLint CEglThreadSession::EglSignalSyncInternal(EGLDisplay aDisplay, EGLSyncKHR aSync, EGLenum aMode)
sl@0
   351
    {
sl@0
   352
    if (aDisplay == EGL_NO_DISPLAY)
sl@0
   353
        {
sl@0
   354
        return EGL_BAD_DISPLAY;
sl@0
   355
        }
sl@0
   356
    if (aSync == EGL_NO_SYNC_KHR)
sl@0
   357
        {
sl@0
   358
        return EGL_BAD_PARAMETER;
sl@0
   359
        }
sl@0
   360
    if (aMode != EGL_SIGNALED_KHR && aMode != EGL_UNSIGNALED_KHR)
sl@0
   361
        {
sl@0
   362
        return EGL_BAD_PARAMETER;
sl@0
   363
        }
sl@0
   364
sl@0
   365
    iDriver.Lock();
sl@0
   366
sl@0
   367
    CEglDisplay* display = iDriver.FindDisplay(aDisplay);
sl@0
   368
    if (!display)
sl@0
   369
        {
sl@0
   370
        iDriver.Unlock();
sl@0
   371
        return EGL_BAD_DISPLAY;
sl@0
   372
        }
sl@0
   373
    if (!display->IsInitialized())
sl@0
   374
        {
sl@0
   375
        iDriver.Unlock();
sl@0
   376
        return EGL_NOT_INITIALIZED;
sl@0
   377
        }
sl@0
   378
sl@0
   379
    CEglSync* syncObj = display->FindSyncObj(aSync);
sl@0
   380
    if (!syncObj)
sl@0
   381
        {
sl@0
   382
        iDriver.Unlock();
sl@0
   383
        return EGL_BAD_PARAMETER;
sl@0
   384
        }
sl@0
   385
    if (syncObj->Type() != EGL_SYNC_REUSABLE_KHR)
sl@0
   386
        {
sl@0
   387
        iDriver.Unlock();
sl@0
   388
        return EGL_BAD_MATCH;
sl@0
   389
        }
sl@0
   390
    if (syncObj->IsDestroyed()) /* sync obj has been marked as destroyed */
sl@0
   391
        {
sl@0
   392
        iDriver.Unlock();
sl@0
   393
        return EGL_BAD_PARAMETER;
sl@0
   394
        }
sl@0
   395
    
sl@0
   396
    syncObj->Signal(aMode);
sl@0
   397
    iDriver.Unlock();
sl@0
   398
    
sl@0
   399
    return EGL_SUCCESS;
sl@0
   400
    }
sl@0
   401
sl@0
   402
EGLBoolean CEglThreadSession::EglGetSyncAttribKhr(EGLDisplay aDisplay, EGLSyncKHR aSync, EGLint aAttribute, EGLint *aValue)
sl@0
   403
    {
sl@0
   404
    SetError(EGL_SUCCESS);
sl@0
   405
    
sl@0
   406
    CHECK_FOR_NULL_DISPLAY(aDisplay, EGL_FALSE)
sl@0
   407
    CHECK_FOR_NULL_SYNCOBJ(aSync, EGL_FALSE)
sl@0
   408
    
sl@0
   409
    if (aAttribute != EGL_SYNC_TYPE_KHR && aAttribute != EGL_SYNC_STATUS_KHR)
sl@0
   410
        {
sl@0
   411
        SetError(EGL_BAD_ATTRIBUTE);
sl@0
   412
        return EGL_FALSE;
sl@0
   413
        }
sl@0
   414
sl@0
   415
    if (!aValue)
sl@0
   416
        {
sl@0
   417
        SetError(EGL_BAD_PARAMETER);
sl@0
   418
        return EGL_FALSE;
sl@0
   419
        }
sl@0
   420
sl@0
   421
    iDriver.Lock();
sl@0
   422
sl@0
   423
    GET_DISPLAY_RETURN_IF_ERR(iDriver, display, aDisplay, EGL_FALSE)
sl@0
   424
    GET_SYNCOBJ_RETURN_IF_ERR(iDriver, display, syncObj, aSync, EGL_FALSE)
sl@0
   425
sl@0
   426
    if (syncObj->Type() != EGL_SYNC_REUSABLE_KHR)
sl@0
   427
        {
sl@0
   428
        iDriver.Unlock();
sl@0
   429
        SetError(EGL_BAD_MATCH);
sl@0
   430
        return EGL_FALSE;
sl@0
   431
        }
sl@0
   432
    
sl@0
   433
    switch (aAttribute)
sl@0
   434
        {
sl@0
   435
        case EGL_SYNC_TYPE_KHR:
sl@0
   436
            *aValue = syncObj->Type();
sl@0
   437
            break;
sl@0
   438
            
sl@0
   439
        case EGL_SYNC_STATUS_KHR:
sl@0
   440
            *aValue = syncObj->Status();
sl@0
   441
            break;
sl@0
   442
        }
sl@0
   443
sl@0
   444
    iDriver.Unlock();
sl@0
   445
    
sl@0
   446
    return EGL_TRUE;
sl@0
   447
    }
sl@0
   448
sl@0
   449
#ifdef _DEBUG
sl@0
   450
void CEglThreadSession::EglHeapMarkStart()
sl@0
   451
    {
sl@0
   452
    iDriver.Lock();
sl@0
   453
    iDriver.Heap().__DbgMarkStart();
sl@0
   454
    iDriver.Unlock();
sl@0
   455
    }
sl@0
   456
sl@0
   457
EGLint CEglThreadSession::EglHeapMarkEnd(EGLint aCount)
sl@0
   458
    {
sl@0
   459
    iDriver.Lock();
sl@0
   460
    const TInt cell = iDriver.Heap().__DbgMarkEnd(aCount);
sl@0
   461
    iDriver.Unlock();
sl@0
   462
    
sl@0
   463
    return cell;
sl@0
   464
    }
sl@0
   465
sl@0
   466
void CEglThreadSession::EglHeapSetBurstAllocFail(EGLenum aType, EGLint aRate, EGLint aBurst)
sl@0
   467
    {
sl@0
   468
    iDriver.Lock();
sl@0
   469
    iDriver.Heap().__DbgSetBurstAllocFail(static_cast<RAllocator::TAllocFail>(aType), aRate, aBurst);
sl@0
   470
    iDriver.Unlock();
sl@0
   471
    }
sl@0
   472
sl@0
   473
#endif //_DEBUG