1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/os/graphics/egl/eglrefimpl/src/session.cpp Fri Jun 15 03:10:57 2012 +0200
1.3 @@ -0,0 +1,473 @@
1.4 +// Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
1.5 +// All rights reserved.
1.6 +// This component and the accompanying materials are made available
1.7 +// under the terms of "Eclipse Public License v1.0"
1.8 +// which accompanies this distribution, and is available
1.9 +// at the URL "http://www.eclipse.org/legal/epl-v10.html".
1.10 +//
1.11 +// Initial Contributors:
1.12 +// Nokia Corporation - initial contribution.
1.13 +//
1.14 +// Contributors:
1.15 +//
1.16 +// Description:
1.17 +// Reference EGL implementation to support EGL sync objects and OpenWF extensions
1.18 +
1.19 +#include "eglprivate.h"
1.20 +
1.21 +const TInt KEglMajorVersion = 1;
1.22 +const TInt KEglMinorVersion = 4;
1.23 +
1.24 +#define KEglClientApis ""
1.25 +#define KEglVendor "Nokia"
1.26 +#define KEglVersion "1.4 Reference EGL"
1.27 +#define KEglExtensions "EGL_KHR_reusable_sync" /* additonal extensions should be added beginning with a space */ \
1.28 + " EGL_NOK__private__signal_sync"
1.29 +
1.30 +// Helper macros for repetitive task
1.31 +//
1.32 +#define CHECK_FOR_NULL_DISPLAY(handle, retval) \
1.33 + if (handle == EGL_NO_DISPLAY) \
1.34 + { \
1.35 + SetError(EGL_BAD_DISPLAY); \
1.36 + return retval; \
1.37 + }
1.38 +
1.39 +#define CHECK_FOR_NULL_SYNCOBJ(handle, retval) \
1.40 + if (handle == EGL_NO_SYNC_KHR) \
1.41 + { \
1.42 + SetError(EGL_BAD_PARAMETER); \
1.43 + return retval; \
1.44 + }
1.45 +
1.46 +#define GET_DISPLAY_RETURN_IF_ERR(drv, display, handle, retval) \
1.47 + CEglDisplay* display = iDriver.FindDisplay(handle); \
1.48 + if (!display) \
1.49 + { \
1.50 + drv.Unlock(); \
1.51 + SetError(EGL_BAD_DISPLAY); \
1.52 + return retval; \
1.53 + } \
1.54 + if (!display->IsInitialized()) \
1.55 + { \
1.56 + drv.Unlock(); \
1.57 + SetError(EGL_NOT_INITIALIZED); \
1.58 + return retval; \
1.59 + }
1.60 +
1.61 +#define GET_SYNCOBJ_RETURN_IF_ERR(drv, display, sync, handle, retval) \
1.62 + CEglSync* sync = display->FindSyncObj(handle); \
1.63 + if (!sync) \
1.64 + { \
1.65 + drv.Unlock(); \
1.66 + SetError(EGL_BAD_PARAMETER); \
1.67 + return retval; \
1.68 + } \
1.69 + if (sync->IsDestroyed()) /* sync obj has been marked as destroyed */ \
1.70 + { \
1.71 + drv.Unlock(); \
1.72 + SetError(EGL_BAD_PARAMETER); \
1.73 + return retval; \
1.74 + }
1.75 +
1.76 +CEglThreadSession::CEglThreadSession(CEglDriver& aDriver):
1.77 + iDriver(aDriver),
1.78 + iError(EGL_SUCCESS)
1.79 + {
1.80 + }
1.81 +
1.82 +CEglThreadSession::~CEglThreadSession()
1.83 + {
1.84 + CEglDriver::Close();
1.85 + }
1.86 +
1.87 +CEglThreadSession* CEglThreadSession::Static()
1.88 + {
1.89 + CEglThreadSession* es = reinterpret_cast<CEglThreadSession*>(Dll::Tls());
1.90 + if (es)
1.91 + {
1.92 + return es;
1.93 + }
1.94 +
1.95 + const TInt err = CEglDriver::Open();
1.96 + if (err != KErrNone)
1.97 + {
1.98 + return NULL;
1.99 + }
1.100 +
1.101 + // CEglDriver is reference counted. As we successfuly open the driver, pls.iDriver will be non-null
1.102 + // and it should be safe to cache the pointer inside CEglThreadSession
1.103 + CEglDriver* drv = CEglDriver::GetDriver();
1.104 + __ASSERT_DEBUG(drv, User::Panic(KEglPanicCategory, EEglPanicDriverNull));
1.105 +
1.106 + // create session object on default thread's heap
1.107 + es = new CEglThreadSession(*drv);
1.108 + if (!es || Dll::SetTls(es)!= KErrNone)
1.109 + {
1.110 + delete es;
1.111 + return NULL;
1.112 + }
1.113 +
1.114 + return es;
1.115 + }
1.116 +
1.117 +void CEglThreadSession::SetError(EGLint aError)
1.118 + {
1.119 + // EGL spec section 3.1, GetError will return the status of the most recent EGL function call
1.120 + // so we will always override the error status
1.121 + iError = aError;
1.122 + }
1.123 +
1.124 +EGLint CEglThreadSession::EglGetError()
1.125 + {
1.126 + // eglGetError always succeed so it will set error state to EGL_SUCCESS
1.127 + const EGLint lastError = iError;
1.128 + iError = EGL_SUCCESS;
1.129 + return lastError;
1.130 + }
1.131 +
1.132 +EGLDisplay CEglThreadSession::EglGetDisplay(NativeDisplayType aDisplayId)
1.133 + {
1.134 + // EGL spec section 3.2: we do not need to raise EGL error when GetDisplay fails
1.135 + SetError(EGL_SUCCESS);
1.136 +
1.137 + if (aDisplayId != EGL_DEFAULT_DISPLAY)
1.138 + {
1.139 + return EGL_NO_DISPLAY;
1.140 + }
1.141 +
1.142 + // default display is created when driver is initialised the first time and will
1.143 + // be destroyed when all threads within process have called eglReleaseThread
1.144 +
1.145 + return KEglDefaultDisplayHandle;
1.146 + }
1.147 +
1.148 +EGLBoolean CEglThreadSession::EglInitialize(EGLDisplay aDisplay, EGLint* aMajor, EGLint* aMinor)
1.149 + {
1.150 + SetError(EGL_SUCCESS);
1.151 +
1.152 + CHECK_FOR_NULL_DISPLAY(aDisplay, EGL_FALSE)
1.153 +
1.154 + iDriver.Lock();
1.155 + CEglDisplay* display = iDriver.FindDisplay(aDisplay);
1.156 + if (!display)
1.157 + {
1.158 + iDriver.Unlock();
1.159 + SetError(EGL_BAD_DISPLAY);
1.160 + return EGL_FALSE;
1.161 + }
1.162 +
1.163 + const TInt err = display->Initialize();
1.164 + iDriver.Unlock();
1.165 +
1.166 + if (err != KErrNone)
1.167 + {
1.168 + SetError(EGL_NOT_INITIALIZED);
1.169 + return EGL_FALSE;
1.170 + }
1.171 +
1.172 + if (aMajor)
1.173 + {
1.174 + *aMajor = KEglMajorVersion;
1.175 + }
1.176 + if (aMinor)
1.177 + {
1.178 + *aMinor = KEglMinorVersion;
1.179 + }
1.180 +
1.181 + return EGL_TRUE;
1.182 + }
1.183 +
1.184 +EGLBoolean CEglThreadSession::EglTerminate(EGLDisplay aDisplay)
1.185 + {
1.186 + SetError(EGL_SUCCESS);
1.187 +
1.188 + CHECK_FOR_NULL_DISPLAY(aDisplay, EGL_FALSE)
1.189 +
1.190 + iDriver.Lock();
1.191 + CEglDisplay* display = iDriver.FindDisplay(aDisplay);
1.192 + if (!display)
1.193 + {
1.194 + iDriver.Unlock();
1.195 + SetError(EGL_BAD_DISPLAY);
1.196 + return EGL_FALSE;
1.197 + }
1.198 +
1.199 + display->Terminate();
1.200 + iDriver.Unlock();
1.201 +
1.202 + return EGL_TRUE;
1.203 + }
1.204 +
1.205 +TFuncPtrEglProc CEglThreadSession::EglGetProcAddress(const char* aName)
1.206 + {
1.207 + SetError(EGL_SUCCESS);
1.208 +
1.209 + if(!aName)
1.210 + {
1.211 + return NULL;
1.212 + }
1.213 +
1.214 + // EGL spec does not mention about raising error if requested function not found
1.215 + // This implementation does not set error and leave thread state unmodified
1.216 + return iDriver.GetProcAddress(aName);
1.217 + }
1.218 +
1.219 +const char* CEglThreadSession::EglQueryString(EGLDisplay aDisplay, EGLint aName)
1.220 + {
1.221 + SetError(EGL_SUCCESS);
1.222 +
1.223 + const char* str = NULL;
1.224 +
1.225 + CHECK_FOR_NULL_DISPLAY(aDisplay, str)
1.226 +
1.227 + iDriver.Lock();
1.228 + GET_DISPLAY_RETURN_IF_ERR(iDriver, display, aDisplay, str)
1.229 + iDriver.Unlock();
1.230 +
1.231 + switch (aName)
1.232 + {
1.233 + case EGL_CLIENT_APIS:
1.234 + str = KEglClientApis;
1.235 + break;
1.236 + case EGL_EXTENSIONS:
1.237 + str = KEglExtensions;
1.238 + break;
1.239 + case EGL_VENDOR:
1.240 + str = KEglVendor;
1.241 + break;
1.242 + case EGL_VERSION:
1.243 + str = KEglVersion;
1.244 + break;
1.245 + default:
1.246 + SetError(EGL_BAD_PARAMETER);
1.247 + break;
1.248 + }
1.249 +
1.250 + return str;
1.251 + }
1.252 +
1.253 +EGLSyncKHR CEglThreadSession::EglCreateSyncKhr(EGLDisplay aDisplay, EGLenum aType, const EGLint *aAttribList)
1.254 + {
1.255 + SetError(EGL_SUCCESS);
1.256 +
1.257 + CHECK_FOR_NULL_DISPLAY(aDisplay, EGL_NO_SYNC_KHR)
1.258 +
1.259 + if (aType != EGL_SYNC_REUSABLE_KHR || (aAttribList && *aAttribList != EGL_NONE))
1.260 + {
1.261 + SetError(EGL_BAD_ATTRIBUTE);
1.262 + return EGL_NO_SYNC_KHR;
1.263 + }
1.264 +
1.265 + iDriver.Lock();
1.266 + GET_DISPLAY_RETURN_IF_ERR(iDriver, display, aDisplay, EGL_NO_SYNC_KHR)
1.267 +
1.268 + CEglSync* syncObj = display->CreateSyncObj();
1.269 + iDriver.Unlock();
1.270 +
1.271 + if (!syncObj)
1.272 + {
1.273 + SetError(EGL_BAD_ALLOC);
1.274 + return EGL_NO_SYNC_KHR;
1.275 + }
1.276 +
1.277 + return reinterpret_cast<EGLSyncKHR>(syncObj);
1.278 + }
1.279 +
1.280 +EGLBoolean CEglThreadSession::EglDestroySyncKhr(EGLDisplay aDisplay, EGLSyncKHR aSync)
1.281 + {
1.282 + SetError(EGL_SUCCESS);
1.283 +
1.284 + CHECK_FOR_NULL_DISPLAY(aDisplay, EGL_FALSE)
1.285 + CHECK_FOR_NULL_SYNCOBJ(aSync, EGL_FALSE)
1.286 +
1.287 + iDriver.Lock();
1.288 + GET_DISPLAY_RETURN_IF_ERR(iDriver, display, aDisplay, EGL_FALSE)
1.289 +
1.290 + const TInt err = display->DestroySyncObj(aSync);
1.291 + iDriver.Unlock();
1.292 +
1.293 + if (err != KErrNone)
1.294 + {
1.295 + SetError(EGL_BAD_PARAMETER);
1.296 + return EGL_FALSE;
1.297 + }
1.298 +
1.299 + return EGL_TRUE;
1.300 + }
1.301 +
1.302 +EGLint CEglThreadSession::EglClientWaitSyncKhr(EGLDisplay aDisplay, EGLSyncKHR aSync, EGLint aFlags, EGLTimeKHR aTimeout)
1.303 + {
1.304 + SetError(EGL_SUCCESS);
1.305 +
1.306 + CHECK_FOR_NULL_DISPLAY(aDisplay, EGL_FALSE)
1.307 + CHECK_FOR_NULL_SYNCOBJ(aSync, EGL_FALSE)
1.308 +
1.309 + const EGLint supportedFlags = EGL_SYNC_FLUSH_COMMANDS_BIT_KHR;
1.310 + if (aFlags & ~supportedFlags)
1.311 + {
1.312 + SetError(EGL_BAD_PARAMETER);
1.313 + return EGL_FALSE;
1.314 + }
1.315 +
1.316 + iDriver.Lock();
1.317 + GET_DISPLAY_RETURN_IF_ERR(iDriver, display, aDisplay, EGL_FALSE)
1.318 + GET_SYNCOBJ_RETURN_IF_ERR(iDriver, display, syncObj, aSync, EGL_FALSE)
1.319 +
1.320 + // increment refcount to mark this sync obj in use and prevent it from being destroyed when other thread calls eglDestroySyncKHR or eglTerminate
1.321 + syncObj->Open();
1.322 +
1.323 + // release display lock as we're going to wait on sync object after this point, not releasing display lock at this
1.324 + // point will cause deadlock
1.325 + // coverity[stale]
1.326 + iDriver.Unlock();
1.327 +
1.328 + // sync obj refcount has been incremented so it won't get destroyed even if other thread call eglDestroySyncKHR or eglTerminate
1.329 + // at this point
1.330 +
1.331 + // we do not support client apis, so flushing flags will be ignored in this implementation
1.332 + EGLint err = syncObj->Wait(aTimeout);
1.333 +
1.334 + // decrement refcount
1.335 + // sync obj will be destroyted if refcount is 0 e.g. other thread issues eglDestroySyncKHR or eglTerminate while this thread
1.336 + // is waiting on it
1.337 + iDriver.Lock();
1.338 + syncObj->Close();
1.339 + iDriver.Unlock();
1.340 +
1.341 + // we do not check error here as it is passed back to caller
1.342 +
1.343 + return err;
1.344 + }
1.345 +
1.346 +EGLBoolean CEglThreadSession::EglSignalSyncKhr(EGLDisplay aDisplay, EGLSyncKHR aSync, EGLenum aMode)
1.347 + {
1.348 + const EGLint err = EglSignalSyncInternal(aDisplay, aSync, aMode);
1.349 + SetError(err);
1.350 + return err == EGL_SUCCESS;
1.351 + }
1.352 +
1.353 +EGLint CEglThreadSession::EglSignalSyncInternal(EGLDisplay aDisplay, EGLSyncKHR aSync, EGLenum aMode)
1.354 + {
1.355 + if (aDisplay == EGL_NO_DISPLAY)
1.356 + {
1.357 + return EGL_BAD_DISPLAY;
1.358 + }
1.359 + if (aSync == EGL_NO_SYNC_KHR)
1.360 + {
1.361 + return EGL_BAD_PARAMETER;
1.362 + }
1.363 + if (aMode != EGL_SIGNALED_KHR && aMode != EGL_UNSIGNALED_KHR)
1.364 + {
1.365 + return EGL_BAD_PARAMETER;
1.366 + }
1.367 +
1.368 + iDriver.Lock();
1.369 +
1.370 + CEglDisplay* display = iDriver.FindDisplay(aDisplay);
1.371 + if (!display)
1.372 + {
1.373 + iDriver.Unlock();
1.374 + return EGL_BAD_DISPLAY;
1.375 + }
1.376 + if (!display->IsInitialized())
1.377 + {
1.378 + iDriver.Unlock();
1.379 + return EGL_NOT_INITIALIZED;
1.380 + }
1.381 +
1.382 + CEglSync* syncObj = display->FindSyncObj(aSync);
1.383 + if (!syncObj)
1.384 + {
1.385 + iDriver.Unlock();
1.386 + return EGL_BAD_PARAMETER;
1.387 + }
1.388 + if (syncObj->Type() != EGL_SYNC_REUSABLE_KHR)
1.389 + {
1.390 + iDriver.Unlock();
1.391 + return EGL_BAD_MATCH;
1.392 + }
1.393 + if (syncObj->IsDestroyed()) /* sync obj has been marked as destroyed */
1.394 + {
1.395 + iDriver.Unlock();
1.396 + return EGL_BAD_PARAMETER;
1.397 + }
1.398 +
1.399 + syncObj->Signal(aMode);
1.400 + iDriver.Unlock();
1.401 +
1.402 + return EGL_SUCCESS;
1.403 + }
1.404 +
1.405 +EGLBoolean CEglThreadSession::EglGetSyncAttribKhr(EGLDisplay aDisplay, EGLSyncKHR aSync, EGLint aAttribute, EGLint *aValue)
1.406 + {
1.407 + SetError(EGL_SUCCESS);
1.408 +
1.409 + CHECK_FOR_NULL_DISPLAY(aDisplay, EGL_FALSE)
1.410 + CHECK_FOR_NULL_SYNCOBJ(aSync, EGL_FALSE)
1.411 +
1.412 + if (aAttribute != EGL_SYNC_TYPE_KHR && aAttribute != EGL_SYNC_STATUS_KHR)
1.413 + {
1.414 + SetError(EGL_BAD_ATTRIBUTE);
1.415 + return EGL_FALSE;
1.416 + }
1.417 +
1.418 + if (!aValue)
1.419 + {
1.420 + SetError(EGL_BAD_PARAMETER);
1.421 + return EGL_FALSE;
1.422 + }
1.423 +
1.424 + iDriver.Lock();
1.425 +
1.426 + GET_DISPLAY_RETURN_IF_ERR(iDriver, display, aDisplay, EGL_FALSE)
1.427 + GET_SYNCOBJ_RETURN_IF_ERR(iDriver, display, syncObj, aSync, EGL_FALSE)
1.428 +
1.429 + if (syncObj->Type() != EGL_SYNC_REUSABLE_KHR)
1.430 + {
1.431 + iDriver.Unlock();
1.432 + SetError(EGL_BAD_MATCH);
1.433 + return EGL_FALSE;
1.434 + }
1.435 +
1.436 + switch (aAttribute)
1.437 + {
1.438 + case EGL_SYNC_TYPE_KHR:
1.439 + *aValue = syncObj->Type();
1.440 + break;
1.441 +
1.442 + case EGL_SYNC_STATUS_KHR:
1.443 + *aValue = syncObj->Status();
1.444 + break;
1.445 + }
1.446 +
1.447 + iDriver.Unlock();
1.448 +
1.449 + return EGL_TRUE;
1.450 + }
1.451 +
1.452 +#ifdef _DEBUG
1.453 +void CEglThreadSession::EglHeapMarkStart()
1.454 + {
1.455 + iDriver.Lock();
1.456 + iDriver.Heap().__DbgMarkStart();
1.457 + iDriver.Unlock();
1.458 + }
1.459 +
1.460 +EGLint CEglThreadSession::EglHeapMarkEnd(EGLint aCount)
1.461 + {
1.462 + iDriver.Lock();
1.463 + const TInt cell = iDriver.Heap().__DbgMarkEnd(aCount);
1.464 + iDriver.Unlock();
1.465 +
1.466 + return cell;
1.467 + }
1.468 +
1.469 +void CEglThreadSession::EglHeapSetBurstAllocFail(EGLenum aType, EGLint aRate, EGLint aBurst)
1.470 + {
1.471 + iDriver.Lock();
1.472 + iDriver.Heap().__DbgSetBurstAllocFail(static_cast<RAllocator::TAllocFail>(aType), aRate, aBurst);
1.473 + iDriver.Unlock();
1.474 + }
1.475 +
1.476 +#endif //_DEBUG