EGLDisplayOpenVG.cpp [plain text]
#include "config.h"
#include "EGLDisplayOpenVG.h"
#include "EGLUtils.h"
#include "IntSize.h"
#include "SurfaceOpenVG.h"
#include <wtf/Assertions.h>
#include <wtf/StdLibExtras.h>
namespace WebCore {
typedef HashMap<EGLDisplay, EGLDisplayOpenVG*> EGLDisplayManagerMap;
static EGLDisplayManagerMap& displayManagers()
{
DEFINE_STATIC_LOCAL(EGLDisplayManagerMap, managers, ());
return managers;
}
static EGLDisplayOpenVG* s_current = 0;
SurfaceOpenVG* EGLDisplayOpenVG::currentSurface()
{
EGLDisplayManagerMap& managers = displayManagers();
EGLDisplay currentDisplay = eglGetCurrentDisplay();
if (currentDisplay == EGL_NO_DISPLAY || !managers.contains(currentDisplay))
return 0;
EGLDisplayOpenVG* displayManager = managers.get(currentDisplay);
EGLSurface currentSurface = eglGetCurrentSurface(EGL_DRAW);
if (currentSurface == EGL_NO_SURFACE || !displayManager->m_platformSurfaces.contains(currentSurface))
return 0;
return displayManager->m_platformSurfaces.get(currentSurface);
}
void EGLDisplayOpenVG::registerPlatformSurface(SurfaceOpenVG* platformSurface)
{
EGLDisplayOpenVG* displayManager = EGLDisplayOpenVG::forDisplay(platformSurface->eglDisplay());
displayManager->m_platformSurfaces.set(platformSurface->eglSurface(), platformSurface);
}
void EGLDisplayOpenVG::unregisterPlatformSurface(SurfaceOpenVG* platformSurface)
{
EGLDisplayOpenVG* displayManager = EGLDisplayOpenVG::forDisplay(platformSurface->eglDisplay());
displayManager->m_platformSurfaces.remove(platformSurface->eglSurface());
}
void EGLDisplayOpenVG::setCurrentDisplay(const EGLDisplay& display)
{
s_current = EGLDisplayOpenVG::forDisplay(display);
}
EGLDisplayOpenVG* EGLDisplayOpenVG::current()
{
if (!s_current) {
EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
eglInitialize(display, 0, 0);
ASSERT_EGL_NO_ERROR();
s_current = EGLDisplayOpenVG::forDisplay(display);
}
return s_current;
}
EGLDisplayOpenVG* EGLDisplayOpenVG::forDisplay(const EGLDisplay& display)
{
EGLDisplayManagerMap& managers = displayManagers();
if (!managers.contains(display))
managers.set(display, new EGLDisplayOpenVG(display));
return managers.get(display);
}
EGLDisplayOpenVG::EGLDisplayOpenVG(const EGLDisplay& display)
: m_display(display)
, m_sharedPlatformSurface(0)
, m_pbufferConfigId(0)
, m_windowConfigId(0)
{
eglBindAPI(EGL_OPENVG_API);
ASSERT_EGL_NO_ERROR();
}
EGLDisplayOpenVG::~EGLDisplayOpenVG()
{
eglMakeCurrent(m_display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
ASSERT_EGL_NO_ERROR();
delete m_sharedPlatformSurface;
HashMap<EGLSurface, EGLint>::const_iterator end = m_surfaceConfigIds.end();
for (HashMap<EGLSurface, EGLint>::const_iterator it = m_surfaceConfigIds.begin(); it != end; ++it)
destroySurface((*it).first);
eglTerminate(m_display);
ASSERT_EGL_NO_ERROR();
}
void EGLDisplayOpenVG::setDefaultPbufferConfig(const EGLConfig& config)
{
EGLint configId;
EGLBoolean success = eglGetConfigAttrib(m_display, config, EGL_CONFIG_ID, &configId);
ASSERT(success == EGL_TRUE);
ASSERT(configId != EGL_BAD_ATTRIBUTE);
m_pbufferConfigId = configId;
}
EGLConfig EGLDisplayOpenVG::defaultPbufferConfig()
{
EGLConfig config;
EGLint numConfigs;
if (!m_pbufferConfigId) {
static const EGLint configAttribs[] = {
EGL_RED_SIZE, 8,
EGL_GREEN_SIZE, 8,
EGL_BLUE_SIZE, 8,
EGL_ALPHA_SIZE, 8,
EGL_ALPHA_MASK_SIZE, 1,
EGL_LUMINANCE_SIZE, EGL_DONT_CARE,
EGL_SURFACE_TYPE, EGL_PBUFFER_BIT,
EGL_RENDERABLE_TYPE, EGL_OPENVG_BIT,
EGL_NONE
};
eglChooseConfig(m_display, configAttribs, &config, 1, &numConfigs);
} else {
const EGLint configAttribs[] = {
EGL_CONFIG_ID, m_pbufferConfigId,
EGL_NONE
};
eglChooseConfig(m_display, configAttribs, &config, 1, &numConfigs);
}
ASSERT_EGL_NO_ERROR();
ASSERT(numConfigs == 1);
return config;
}
void EGLDisplayOpenVG::setDefaultWindowConfig(const EGLConfig& config)
{
EGLint configId;
EGLBoolean success = eglGetConfigAttrib(m_display, config, EGL_CONFIG_ID, &configId);
ASSERT(success == EGL_TRUE);
ASSERT(configId != EGL_BAD_ATTRIBUTE);
m_windowConfigId = configId;
}
EGLConfig EGLDisplayOpenVG::defaultWindowConfig()
{
EGLConfig config;
EGLint numConfigs;
if (!m_windowConfigId) {
static const EGLint configAttribs[] = {
EGL_RED_SIZE, 8,
EGL_GREEN_SIZE, 8,
EGL_BLUE_SIZE, 8,
EGL_ALPHA_SIZE, 8,
EGL_ALPHA_MASK_SIZE, 1,
EGL_LUMINANCE_SIZE, EGL_DONT_CARE,
EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
EGL_RENDERABLE_TYPE, EGL_OPENVG_BIT,
EGL_NONE
};
eglChooseConfig(m_display, configAttribs, &config, 1, &numConfigs);
} else {
const EGLint configAttribs[] = {
EGL_CONFIG_ID, m_windowConfigId,
EGL_NONE
};
eglChooseConfig(m_display, configAttribs, &config, 1, &numConfigs);
}
ASSERT_EGL_NO_ERROR();
ASSERT(numConfigs == 1);
return config;
}
SurfaceOpenVG* EGLDisplayOpenVG::sharedPlatformSurface()
{
if (!m_sharedPlatformSurface) {
EGLConfig config = defaultPbufferConfig();
EGLSurface surface = createPbufferSurface(IntSize(1, 1), config);
EGLContext context = eglCreateContext(m_display, config, EGL_NO_CONTEXT, 0);
ASSERT_EGL_NO_ERROR();
m_contexts.set(m_surfaceConfigIds.get(surface), context);
m_sharedPlatformSurface = new SurfaceOpenVG;
m_sharedPlatformSurface->m_eglDisplay = m_display;
m_sharedPlatformSurface->m_eglSurface = surface;
m_sharedPlatformSurface->m_eglContext = context;
m_platformSurfaces.set(surface, m_sharedPlatformSurface); }
return m_sharedPlatformSurface;
}
EGLSurface EGLDisplayOpenVG::createPbufferSurface(const IntSize& size, const EGLConfig& config, EGLint* errorCode)
{
const EGLint attribList[] = {
EGL_WIDTH, size.width(),
EGL_HEIGHT, size.height(),
EGL_NONE
};
EGLSurface surface = eglCreatePbufferSurface(m_display, config, attribList);
if (errorCode)
*errorCode = eglGetError();
else
ASSERT_EGL_NO_ERROR();
if (surface == EGL_NO_SURFACE)
return EGL_NO_SURFACE;
EGLint surfaceConfigId;
EGLBoolean success = eglGetConfigAttrib(m_display, config, EGL_CONFIG_ID, &surfaceConfigId);
ASSERT(success == EGL_TRUE);
ASSERT(surfaceConfigId != EGL_BAD_ATTRIBUTE);
ASSERT(!m_surfaceConfigIds.contains(surface));
m_surfaceConfigIds.set(surface, surfaceConfigId);
return surface;
}
EGLSurface EGLDisplayOpenVG::createPbufferFromClientBuffer(
EGLClientBuffer clientBuffer, EGLenum bufferType, const EGLConfig& config, EGLint* errorCode)
{
EGLSurface surface = eglCreatePbufferFromClientBuffer(m_display,
bufferType, clientBuffer, config, 0 );
if (errorCode)
*errorCode = eglGetError();
else
ASSERT_EGL_NO_ERROR();
if (surface == EGL_NO_SURFACE)
return EGL_NO_SURFACE;
EGLint surfaceConfigId;
EGLBoolean success = eglGetConfigAttrib(m_display, config, EGL_CONFIG_ID, &surfaceConfigId);
ASSERT(success == EGL_TRUE);
ASSERT(surfaceConfigId != EGL_BAD_ATTRIBUTE);
ASSERT(!m_surfaceConfigIds.contains(surface));
m_surfaceConfigIds.set(surface, surfaceConfigId);
return surface;
}
EGLSurface EGLDisplayOpenVG::surfaceForWindow(EGLNativeWindowType wId, const EGLConfig& config)
{
if (m_windowSurfaces.contains(wId))
return m_windowSurfaces.get(wId);
EGLSurface surface = eglCreateWindowSurface(m_display, config, wId, 0);
ASSERT_EGL_NO_ERROR();
EGLint surfaceConfigId;
EGLBoolean success = eglGetConfigAttrib(m_display, config, EGL_CONFIG_ID, &surfaceConfigId);
ASSERT(success == EGL_TRUE);
ASSERT(surfaceConfigId != EGL_BAD_ATTRIBUTE);
ASSERT(!m_surfaceConfigIds.contains(surface));
m_surfaceConfigIds.set(surface, surfaceConfigId);
return surface;
}
bool EGLDisplayOpenVG::surfacesCompatible(const EGLSurface& surface, const EGLSurface& otherSurface)
{
if (surface == EGL_NO_SURFACE || otherSurface == EGL_NO_SURFACE)
return false;
return m_surfaceConfigIds.contains(surface) && m_surfaceConfigIds.contains(otherSurface);
}
void EGLDisplayOpenVG::destroySurface(const EGLSurface& surface)
{
ASSERT(surface != EGL_NO_SURFACE);
if (eglGetCurrentSurface(EGL_DRAW) == surface) {
eglMakeCurrent(m_display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
ASSERT_EGL_NO_ERROR();
}
if (m_surfaceConfigIds.contains(surface)) {
EGLint surfaceConfigId = m_surfaceConfigIds.take(surface); bool isContextReferenced = false;
if (m_compatibleConfigIds.contains(surfaceConfigId))
surfaceConfigId = m_compatibleConfigIds.get(surfaceConfigId);
HashMap<EGLSurface, EGLint>::iterator end = m_surfaceConfigIds.end();
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;
}
}
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 {
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) sharedPlatformSurface();
EGLDisplay currentDisplay = eglGetCurrentDisplay();
EGLSurface currentReadSurface = eglGetCurrentSurface(EGL_READ);
EGLSurface currentDrawSurface = eglGetCurrentSurface(EGL_DRAW);
EGLContext currentContext = eglGetCurrentContext();
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) {
if (currentContext != EGL_NO_CONTEXT) {
eglMakeCurrent(currentDisplay, currentReadSurface, currentDrawSurface, currentContext);
ASSERT_EGL_NO_ERROR();
}
m_compatibleConfigIds.set(surfaceConfigId, (*it).first);
return (*it).second;
}
}
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);
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;
}
}