EglContext::EglContext(EGLNativeContextType context,ContextPtr shared_context, EglConfig* config,GLEScontext* glesCtx,GLESVersion ver,ObjectNameManager* mngr): m_native(context), m_config(config), m_glesContext(glesCtx), m_read(NULL), m_draw(NULL), m_destroy(false), m_version(ver) { m_shareGroup = shared_context.Ptr()? mngr->attachShareGroup(context,shared_context.Ptr()->getShareGroup().Ptr()): mngr->createShareGroup(context); m_hndl = ++s_nextContextHndl; }
EGLAPI EGLSurface EGLAPIENTRY eglGetCurrentSurface(EGLint readdraw) { if (!EglValidate::surfaceTarget(readdraw)) { return EGL_NO_SURFACE; } ThreadInfo* thread = getThreadInfo(); EglDisplay* dpy = static_cast<EglDisplay*>(thread->eglDisplay); ContextPtr ctx = thread->eglContext; if(dpy && ctx.Ptr()) { SurfacePtr surface = readdraw == EGL_READ ? ctx->read() : ctx->draw(); if(surface.Ptr()) { // This double check is required because a surface might still be // current after it is destroyed - in which case its handle should // be invalid, that is EGL_NO_SURFACE should be returned even // though the surface is current. EGLSurface s = (EGLSurface)SafePointerFromUInt(surface->getHndl()); surface = dpy->getSurface(s); if(surface.Ptr()) { return s; } } } return EGL_NO_SURFACE; }
void detachEGLImage(unsigned int imageId) { ThreadInfo* thread = getThreadInfo(); ContextPtr ctx = thread->eglContext; if (ctx.Ptr()) { ctx->detachImage(imageId); } }
EGLContext EglDisplay::addContext(ContextPtr ctx ) { android::Mutex::Autolock mutex(m_lock); unsigned int hndl = ctx.Ptr()->getHndl(); EGLContext ret = reinterpret_cast<EGLContext> (hndl); if(m_contexts.find(hndl) != m_contexts.end()) { return ret; } m_contexts[hndl] = ctx; return ret; }
EGLAPI EGLContext EGLAPIENTRY eglCreateContext(EGLDisplay display, EGLConfig config, EGLContext share_context, const EGLint *attrib_list) { VALIDATE_DISPLAY_RETURN(display,EGL_NO_CONTEXT); VALIDATE_CONFIG_RETURN(config,EGL_NO_CONTEXT); GLESVersion version = GLES_1_1; if(!EglValidate::noAttribs(attrib_list)) { int i = 0; while(attrib_list[i] != EGL_NONE) { switch(attrib_list[i]) { case EGL_CONTEXT_CLIENT_VERSION: if(attrib_list[i+1] == 2) { version = GLES_2_0; } else { version = GLES_1_1; } break; default: RETURN_ERROR(EGL_NO_CONTEXT,EGL_BAD_ATTRIBUTE); } i+=2; } } const GLESiface* iface = g_eglInfo->getIface(version); GLEScontext* glesCtx = NULL; if(iface) { glesCtx = iface->createGLESContext(); } else { // there is no interface for this gles version RETURN_ERROR(EGL_NO_CONTEXT,EGL_BAD_ATTRIBUTE); } ContextPtr sharedCtxPtr; if(share_context != EGL_NO_CONTEXT) { sharedCtxPtr = dpy->getContext(share_context); if(!sharedCtxPtr.Ptr()) { RETURN_ERROR(EGL_NO_CONTEXT,EGL_BAD_CONTEXT); } } EglOS::Context* globalSharedContext = dpy->getGlobalSharedContext(); EglOS::Context* nativeContext = dpy->nativeType()->createContext( cfg->nativeFormat(), globalSharedContext); if(nativeContext) { ContextPtr ctx(new EglContext(dpy, nativeContext,sharedCtxPtr,cfg,glesCtx,version,dpy->getManager(version))); return dpy->addContext(ctx); } else { iface->deleteGLESContext(glesCtx); } return EGL_NO_CONTEXT; }
/************************** KHR IMAGE *************************************************************/ EglImage *attachEGLImage(unsigned int imageId) { ThreadInfo* thread = getThreadInfo(); EglDisplay* dpy = static_cast<EglDisplay*>(thread->eglDisplay); ContextPtr ctx = thread->eglContext; if (ctx.Ptr()) { ImagePtr img = dpy->getImage(reinterpret_cast<EGLImageKHR>(imageId)); if(img.Ptr()) { ctx->attachImage(imageId,img); return img.Ptr(); } } return NULL; }
bool EglDisplay::removeContext(ContextPtr ctx) { android::Mutex::Autolock mutex(m_lock); ContextsHndlMap::iterator it; for(it = m_contexts.begin(); it != m_contexts.end(); it++) { if((*it).second.Ptr() == ctx.Ptr()) { break; } } if(it != m_contexts.end()) { m_contexts.erase(it); return true; } return false; }
EGLAPI EGLContext EGLAPIENTRY eglGetCurrentContext(void) { ThreadInfo* thread = getThreadInfo(); EglDisplay* dpy = static_cast<EglDisplay*>(thread->eglDisplay); ContextPtr ctx = thread->eglContext; if(dpy && ctx.Ptr()){ // This double check is required because a context might still be current after it is destroyed - in which case // its handle should be invalid, that is EGL_NO_CONTEXT should be returned even though the context is current EGLContext c = (EGLContext)SafePointerFromUInt(ctx->getHndl()); if(dpy->getContext(c).Ptr()) { return c; } } return EGL_NO_CONTEXT; }
EGLAPI EGLBoolean EGLAPIENTRY eglSwapBuffers(EGLDisplay display, EGLSurface surface) { VALIDATE_DISPLAY(display); VALIDATE_SURFACE(surface,Srfc); ThreadInfo* thread = getThreadInfo(); ContextPtr currentCtx = thread->eglContext; //if surface not window return if(Srfc->type() != EglSurface::WINDOW){ RETURN_ERROR(EGL_TRUE,EGL_SUCCESS); } if(!currentCtx.Ptr() || !currentCtx->usingSurface(Srfc) || !dpy->nativeType()->isValidNativeWin(Srfc.Ptr()->native())) { RETURN_ERROR(EGL_FALSE,EGL_BAD_SURFACE); } dpy->nativeType()->swapBuffers(Srfc->native()); return EGL_TRUE; }
EGLAPI EGLBoolean EGLAPIENTRY eglMakeCurrent(EGLDisplay display, EGLSurface draw, EGLSurface read, EGLContext context) { VALIDATE_DISPLAY(display); bool releaseContext = EglValidate::releaseContext(context, read, draw); if(!releaseContext && EglValidate::badContextMatch(context, read, draw)) { RETURN_ERROR(EGL_FALSE, EGL_BAD_MATCH); } ThreadInfo* thread = getThreadInfo(); ContextPtr prevCtx = thread->eglContext; if(releaseContext) { //releasing current context if(prevCtx.Ptr()) { g_eglInfo->getIface(prevCtx->version())->flush(); if(!dpy->nativeType()->makeCurrent(NULL,NULL,NULL)) { RETURN_ERROR(EGL_FALSE,EGL_BAD_ACCESS); } thread->updateInfo(ContextPtr(NULL),dpy,NULL,ShareGroupPtr(NULL),dpy->getManager(prevCtx->version())); } } else { //assining new context VALIDATE_CONTEXT(context); VALIDATE_SURFACE(draw,newDrawSrfc); VALIDATE_SURFACE(read,newReadSrfc); EglSurface* newDrawPtr = newDrawSrfc.Ptr(); EglSurface* newReadPtr = newReadSrfc.Ptr(); ContextPtr newCtx = ctx; if (newCtx.Ptr() && prevCtx.Ptr()) { if (newCtx.Ptr() == prevCtx.Ptr()) { if (newDrawPtr == prevCtx->draw().Ptr() && newReadPtr == prevCtx->read().Ptr()) { // nothing to do return EGL_TRUE; } } else { // Make sure previous context is detached from surfaces releaseContext = true; } } //surfaces compatibility check if(!((*ctx->getConfig()).compatibleWith((*newDrawPtr->getConfig()))) || !((*ctx->getConfig()).compatibleWith((*newReadPtr->getConfig())))) { RETURN_ERROR(EGL_FALSE,EGL_BAD_MATCH); } EglOS::Display* nativeDisplay = dpy->nativeType(); EglOS::Surface* nativeRead = newReadPtr->native(); EglOS::Surface* nativeDraw = newDrawPtr->native(); //checking native window validity if(newReadPtr->type() == EglSurface::WINDOW && !nativeDisplay->isValidNativeWin(nativeRead)) { RETURN_ERROR(EGL_FALSE,EGL_BAD_NATIVE_WINDOW); } if(newDrawPtr->type() == EglSurface::WINDOW && !nativeDisplay->isValidNativeWin(nativeDraw)) { RETURN_ERROR(EGL_FALSE,EGL_BAD_NATIVE_WINDOW); } if(prevCtx.Ptr()) { g_eglInfo->getIface(prevCtx->version())->flush(); } if (!dpy->nativeType()->makeCurrent( newReadPtr->native(), newDrawPtr->native(), newCtx->nativeType())) { RETURN_ERROR(EGL_FALSE,EGL_BAD_ACCESS); } //TODO: handle the following errors // EGL_BAD_CURRENT_SURFACE , EGL_CONTEXT_LOST , EGL_BAD_ACCESS thread->updateInfo(newCtx,dpy,newCtx->getGlesContext(),newCtx->getShareGroup(),dpy->getManager(newCtx->version())); newCtx->setSurfaces(newReadSrfc,newDrawSrfc); g_eglInfo->getIface(newCtx->version())->initContext(newCtx->getGlesContext(),newCtx->getShareGroup()); // Initialize the GLES extension function table used in // eglGetProcAddress for the context's GLES version if not // yet initialized. We initialize it here to make sure we call the // GLES getProcAddress after when a context is bound. g_eglInfo->initClientExtFuncTable(newCtx->version()); } // release previous context surface binding if(prevCtx.Ptr() && releaseContext) { prevCtx->setSurfaces(SurfacePtr(NULL),SurfacePtr(NULL)); } return EGL_TRUE; }