void EGLDisplayOpenVG::removeSurface(const EGLSurface& surface, bool destroySurface) { ASSERT(surface != EGL_NO_SURFACE); #if PLATFORM(OLYMPIA) if (destroySurface) { // Work around a bug in our EGL implementation where the VGImage // referenced by eglCreatePbufferFromClientBuffer is not released // when destroying the context, RIM Bug #1591. // The context that created the VGImage needs to be current for // it to be released. sharedPlatformSurface()->makeResourceCreationContextCurrent(); } else #endif if (eglGetCurrentSurface(EGL_DRAW) == surface) { eglMakeCurrent(m_display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); ASSERT_EGL_NO_ERROR(); } // Destroy the context associated to the surface, if we already created one. if (m_surfaceConfigIds.contains(surface)) { EGLint surfaceConfigId = m_surfaceConfigIds.take(surface); // take = get and remove bool isContextReferenced = false; if (m_compatibleConfigIds.contains(surfaceConfigId)) surfaceConfigId = m_compatibleConfigIds.get(surfaceConfigId); HashMap<EGLSurface, EGLint>::iterator end = m_surfaceConfigIds.end(); // ...but only if there's no other surfaces associated to that context. for (HashMap<EGLSurface, EGLint>::iterator it = m_surfaceConfigIds.begin(); it != end; ++it) { if ((*it).second == surfaceConfigId) { isContextReferenced = true; break; } } if (!isContextReferenced && m_contexts.contains(surfaceConfigId)) { EGLContext context = m_contexts.take(surfaceConfigId); eglDestroyContext(m_display, context); ASSERT_EGL_NO_ERROR(); } } m_platformSurfaces.remove(surface); HashMap<EGLNativeWindowType, EGLSurface>::iterator end = m_windowSurfaces.end(); for (HashMap<EGLNativeWindowType, EGLSurface>::iterator it = m_windowSurfaces.begin(); it != end; ++it) { if ((*it).second == surface) { m_windowSurfaces.remove(it); break; } } if (destroySurface) { eglDestroySurface(m_display, surface); ASSERT_EGL_NO_ERROR(); } }
EGLContext EGLDisplayOpenVG::contextForSurface(const EGLSurface& surface) { ASSERT(surface != EGL_NO_SURFACE); if (m_platformSurfaces.contains(surface)) return m_platformSurfaces.get(surface)->eglContext(); eglBindAPI(EGL_OPENVG_API); ASSERT_EGL_NO_ERROR(); EGLint surfaceConfigId; if (m_surfaceConfigIds.contains(surface)) surfaceConfigId = m_surfaceConfigIds.get(surface); else { // Retrieve the same EGL config for context creation that was used to // create the the EGL surface. EGLBoolean success = eglQuerySurface(m_display, surface, EGL_CONFIG_ID, &surfaceConfigId); ASSERT(success == EGL_TRUE); ASSERT(surfaceConfigId != EGL_BAD_ATTRIBUTE); m_surfaceConfigIds.set(surface, surfaceConfigId); } if (m_compatibleConfigIds.contains(surfaceConfigId)) surfaceConfigId = m_compatibleConfigIds.get(surfaceConfigId); if (m_contexts.contains(surfaceConfigId)) return m_contexts.get(surfaceConfigId); if (!m_sharedPlatformSurface) // shared context has not been created yet sharedPlatformSurface(); // creates the shared surface & context EGLDisplay currentDisplay = eglGetCurrentDisplay(); EGLSurface currentReadSurface = eglGetCurrentSurface(EGL_READ); EGLSurface currentDrawSurface = eglGetCurrentSurface(EGL_DRAW); EGLContext currentContext = eglGetCurrentContext(); // Before creating a new context, let's try whether an existing one // is compatible with the surface. EGL doesn't give us a different way // to check context/surface compatibility than trying it out, so let's // do just that. HashMap<EGLint, EGLContext>::iterator end = m_contexts.end(); for (HashMap<EGLint, EGLContext>::iterator it = m_contexts.begin(); it != end; ++it) { eglMakeCurrent(m_display, surface, surface, (*it).second); if (eglGetError() == EGL_SUCCESS) { // Restore previous surface/context. if (currentContext != EGL_NO_CONTEXT) { eglMakeCurrent(currentDisplay, currentReadSurface, currentDrawSurface, currentContext); ASSERT_EGL_NO_ERROR(); } // Cool, surface is compatible to one of our existing contexts. m_compatibleConfigIds.set(surfaceConfigId, (*it).first); return (*it).second; } } // Restore previous surface/context. if (currentContext != EGL_NO_CONTEXT) { eglMakeCurrent(currentDisplay, currentReadSurface, currentDrawSurface, currentContext); ASSERT_EGL_NO_ERROR(); } EGLConfig config; EGLint numConfigs; const EGLint configAttribs[] = { EGL_CONFIG_ID, surfaceConfigId, EGL_NONE }; eglChooseConfig(m_display, configAttribs, &config, 1, &numConfigs); ASSERT_EGL_NO_ERROR(); ASSERT(numConfigs == 1); // We share all of the images and paths amongst the different contexts, // so that they can be used in all of them. Resources that are created // while m_sharedPlatformSurface->context() is current will be // accessible from all other contexts, but are not restricted to the // lifetime of those contexts. EGLContext context = eglCreateContext(m_display, config, m_sharedPlatformSurface->eglContext(), 0); ASSERT_EGL_NO_ERROR(); ASSERT(!m_contexts.contains(surfaceConfigId)); m_contexts.set(surfaceConfigId, context); return context; }