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();
    }
}
Exemplo n.º 2
0
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;
}