[SCM] WebKit Debian packaging branch, webkit-1.2, updated. upstream/1.1.90-6072-g9a69373

jpetsovits at rim.com jpetsovits at rim.com
Thu Apr 8 01:15:28 UTC 2010


The following commit has been merged in the webkit-1.2 branch:
commit 438d16b5d8a92e31a72192e493c4b8df14995e69
Author: jpetsovits at rim.com <jpetsovits at rim.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Date:   Tue Jan 19 23:09:14 2010 +0000

    2010-01-19  Jakob Petsovits  <jpetsovits at rim.com>
    
            Reviewed by Nikolas Zimmermann.
    
            [OpenVG] Add (EGL) surface/context management
            https://bugs.webkit.org/show_bug.cgi?id=33403
    
            The foundations for a new OpenVG port.
    
            OpenVG is not tied to EGL per se, EGL just happens to be
            the only usable backend for OpenVG state and painting
            at the time of writing.
    
            The purpose of the SurfaceOpenVG class is to provide
            an EGL-independent interface for OpenVG-specific code.
            The EGLDisplayOpenVG class takes care of keeping track
            of EGL displays, surfaces and contexts. It also makes
            sure that all created contexts are interoperable, and
            that different surfaces use a single context if possible.
    
            * platform/graphics/openvg/EGLDisplayOpenVG.cpp: Added.
            (WebCore::displayManagers):
            (WebCore::EGLDisplayOpenVG::currentSurface):
            (WebCore::EGLDisplayOpenVG::registerPlatformSurface):
            (WebCore::EGLDisplayOpenVG::unregisterPlatformSurface):
            (WebCore::EGLDisplayOpenVG::setCurrentDisplay):
            (WebCore::EGLDisplayOpenVG::current):
            (WebCore::EGLDisplayOpenVG::forDisplay):
            (WebCore::EGLDisplayOpenVG::EGLDisplayOpenVG):
            (WebCore::EGLDisplayOpenVG::~EGLDisplayOpenVG):
            (WebCore::EGLDisplayOpenVG::setDefaultPbufferConfig):
            (WebCore::EGLDisplayOpenVG::defaultPbufferConfig):
            (WebCore::EGLDisplayOpenVG::setDefaultWindowConfig):
            (WebCore::EGLDisplayOpenVG::defaultWindowConfig):
            (WebCore::EGLDisplayOpenVG::sharedPlatformSurface):
            (WebCore::EGLDisplayOpenVG::createPbufferSurface):
            (WebCore::EGLDisplayOpenVG::surfaceForWindow):
            (WebCore::EGLDisplayOpenVG::surfacesCompatible):
            (WebCore::EGLDisplayOpenVG::destroySurface):
            (WebCore::EGLDisplayOpenVG::contextForSurface):
            * platform/graphics/openvg/EGLDisplayOpenVG.h: Added.
            (WebCore::EGLDisplayOpenVG::display):
            * platform/graphics/openvg/EGLUtils.h: Added.
            (toEGLErrorConstant):
            * platform/graphics/openvg/SurfaceOpenVG.cpp: Added.
            (WebCore::SurfaceOpenVG::currentSurface):
            (WebCore::SurfaceOpenVG::SurfaceOpenVG):
            (WebCore::SurfaceOpenVG::~SurfaceOpenVG):
            (WebCore::SurfaceOpenVG::isValid):
            (WebCore::SurfaceOpenVG::width):
            (WebCore::SurfaceOpenVG::height):
            (WebCore::SurfaceOpenVG::sharedSurface):
            (WebCore::SurfaceOpenVG::makeCurrent):
            (WebCore::SurfaceOpenVG::makeCompatibleCurrent):
            (WebCore::SurfaceOpenVG::flush):
            * platform/graphics/openvg/SurfaceOpenVG.h: Added.
            (WebCore::SurfaceOpenVG::eglDisplay):
            (WebCore::SurfaceOpenVG::eglSurface):
            (WebCore::SurfaceOpenVG::eglContext):
            * platform/graphics/openvg/VGUtils.h: Added.
            (toVGErrorConstant):
    
    
    git-svn-id: http://svn.webkit.org/repository/webkit/trunk@53499 268f45cc-cd09-0410-ab3c-d52691b4dbfc

diff --git a/WebCore/ChangeLog b/WebCore/ChangeLog
index b2eca20..ef7293a 100644
--- a/WebCore/ChangeLog
+++ b/WebCore/ChangeLog
@@ -1,3 +1,65 @@
+2010-01-19  Jakob Petsovits  <jpetsovits at rim.com>
+
+        Reviewed by Nikolas Zimmermann.
+
+        [OpenVG] Add (EGL) surface/context management
+        https://bugs.webkit.org/show_bug.cgi?id=33403
+
+        The foundations for a new OpenVG port.
+
+        OpenVG is not tied to EGL per se, EGL just happens to be
+        the only usable backend for OpenVG state and painting
+        at the time of writing.
+
+        The purpose of the SurfaceOpenVG class is to provide
+        an EGL-independent interface for OpenVG-specific code.
+        The EGLDisplayOpenVG class takes care of keeping track
+        of EGL displays, surfaces and contexts. It also makes
+        sure that all created contexts are interoperable, and
+        that different surfaces use a single context if possible.
+
+        * platform/graphics/openvg/EGLDisplayOpenVG.cpp: Added.
+        (WebCore::displayManagers):
+        (WebCore::EGLDisplayOpenVG::currentSurface):
+        (WebCore::EGLDisplayOpenVG::registerPlatformSurface):
+        (WebCore::EGLDisplayOpenVG::unregisterPlatformSurface):
+        (WebCore::EGLDisplayOpenVG::setCurrentDisplay):
+        (WebCore::EGLDisplayOpenVG::current):
+        (WebCore::EGLDisplayOpenVG::forDisplay):
+        (WebCore::EGLDisplayOpenVG::EGLDisplayOpenVG):
+        (WebCore::EGLDisplayOpenVG::~EGLDisplayOpenVG):
+        (WebCore::EGLDisplayOpenVG::setDefaultPbufferConfig):
+        (WebCore::EGLDisplayOpenVG::defaultPbufferConfig):
+        (WebCore::EGLDisplayOpenVG::setDefaultWindowConfig):
+        (WebCore::EGLDisplayOpenVG::defaultWindowConfig):
+        (WebCore::EGLDisplayOpenVG::sharedPlatformSurface):
+        (WebCore::EGLDisplayOpenVG::createPbufferSurface):
+        (WebCore::EGLDisplayOpenVG::surfaceForWindow):
+        (WebCore::EGLDisplayOpenVG::surfacesCompatible):
+        (WebCore::EGLDisplayOpenVG::destroySurface):
+        (WebCore::EGLDisplayOpenVG::contextForSurface):
+        * platform/graphics/openvg/EGLDisplayOpenVG.h: Added.
+        (WebCore::EGLDisplayOpenVG::display):
+        * platform/graphics/openvg/EGLUtils.h: Added.
+        (toEGLErrorConstant):
+        * platform/graphics/openvg/SurfaceOpenVG.cpp: Added.
+        (WebCore::SurfaceOpenVG::currentSurface):
+        (WebCore::SurfaceOpenVG::SurfaceOpenVG):
+        (WebCore::SurfaceOpenVG::~SurfaceOpenVG):
+        (WebCore::SurfaceOpenVG::isValid):
+        (WebCore::SurfaceOpenVG::width):
+        (WebCore::SurfaceOpenVG::height):
+        (WebCore::SurfaceOpenVG::sharedSurface):
+        (WebCore::SurfaceOpenVG::makeCurrent):
+        (WebCore::SurfaceOpenVG::makeCompatibleCurrent):
+        (WebCore::SurfaceOpenVG::flush):
+        * platform/graphics/openvg/SurfaceOpenVG.h: Added.
+        (WebCore::SurfaceOpenVG::eglDisplay):
+        (WebCore::SurfaceOpenVG::eglSurface):
+        (WebCore::SurfaceOpenVG::eglContext):
+        * platform/graphics/openvg/VGUtils.h: Added.
+        (toVGErrorConstant):
+
 2010-01-19  Steve Block  <steveblock at google.com>
 
         Reviewed by David Levin.
diff --git a/WebCore/platform/graphics/openvg/EGLDisplayOpenVG.cpp b/WebCore/platform/graphics/openvg/EGLDisplayOpenVG.cpp
new file mode 100644
index 0000000..576dc5b
--- /dev/null
+++ b/WebCore/platform/graphics/openvg/EGLDisplayOpenVG.cpp
@@ -0,0 +1,426 @@
+/*
+ * Copyright (C) Research In Motion Limited 2009-2010. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB.  If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#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 {
+
+// Need to typedef this, otherwise DEFINE_STATIC_LOCAL() doesn't swallow it.
+typedef HashMap<EGLDisplay, EGLDisplayOpenVG*> EGLDisplayManagerMap;
+
+// File-static variables.
+static EGLDisplayManagerMap& displayManagers()
+{
+    DEFINE_STATIC_LOCAL(EGLDisplayManagerMap, managers, ());
+    return managers;
+}
+
+static EGLDisplayOpenVG* s_current = 0;
+
+// Static class members.
+
+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);
+}
+
+
+// Object/instance members.
+
+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;
+
+    // Hopefully the client will have set the pbuffer config of its choice
+    // by now - if not, use a 32-bit generic one as default.
+    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;
+
+    // Hopefully the client will have set the window config of its choice
+    // by now - if not, use a 32-bit generic one as default.
+    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) {
+        // The shared surface doesn't need to be drawn on, it just exists so
+        // that we can always make the shared context current (which in turn is
+        // the owner of long-living resources such as images, paths and fonts).
+        // We'll just make the shared surface as small as possible: 1x1 pixel.
+        EGLConfig config = defaultPbufferConfig();
+        EGLSurface surface = createPbufferSurface(IntSize(1, 1), config);
+        ASSERT_EGL_NO_ERROR();
+
+        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); // a.k.a. registerPlatformSurface()
+    }
+    return m_sharedPlatformSurface;
+}
+
+EGLSurface EGLDisplayOpenVG::createPbufferSurface(const IntSize& size, const EGLConfig& config)
+{
+    const EGLint attribList[] = {
+        EGL_WIDTH, size.width(),
+        EGL_HEIGHT, size.height(),
+        EGL_NONE
+    };
+    EGLSurface surface = eglCreatePbufferSurface(m_display, config, attribList);
+    if (eglGetError() != EGL_SUCCESS)
+        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;
+
+    // Currently, we assume that all surfaces known to this object are
+    // context-compatible to each other (which is reasonable to assume,
+    // otherwise eglCreateContext() would fail with EGL_BAD_MATCH for shared
+    // context compatibility anyways.
+    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();
+    }
+
+    // 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;
+        }
+    }
+
+    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;
+}
+
+}
diff --git a/WebCore/platform/graphics/openvg/EGLDisplayOpenVG.h b/WebCore/platform/graphics/openvg/EGLDisplayOpenVG.h
new file mode 100644
index 0000000..5d367c5
--- /dev/null
+++ b/WebCore/platform/graphics/openvg/EGLDisplayOpenVG.h
@@ -0,0 +1,87 @@
+/*
+ * Copyright (C) Research In Motion Limited 2009-2010. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB.  If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef EGLDisplayOpenVG_h
+#define EGLDisplayOpenVG_h
+
+#include <egl.h>
+#include <wtf/HashMap.h>
+
+namespace WebCore {
+
+class IntSize;
+class SurfaceOpenVG;
+
+class EGLDisplayOpenVG {
+public:
+    friend class SurfaceOpenVG;
+
+    static SurfaceOpenVG* currentSurface();
+    static void setCurrentDisplay(const EGLDisplay&);
+    static EGLDisplayOpenVG* current();
+    static EGLDisplayOpenVG* forDisplay(const EGLDisplay&);
+
+    void setDefaultPbufferConfig(const EGLConfig&);
+    EGLConfig defaultPbufferConfig();
+    void setDefaultWindowConfig(const EGLConfig&);
+    EGLConfig defaultWindowConfig();
+
+    EGLDisplay display() const { return m_display; }
+    SurfaceOpenVG* sharedPlatformSurface();
+
+    /** Creates a pbuffer surface using the given config. If no surface
+     * could be created, EGL_NO_SURFACE is returned and errors can be
+     * caught with eglGetError() (respectively ASSERT_EGL_NO_ERROR()). */
+    EGLSurface createPbufferSurface(const IntSize&, const EGLConfig&);
+
+    EGLSurface surfaceForWindow(EGLNativeWindowType, const EGLConfig&);
+
+    bool surfacesCompatible(const EGLSurface&, const EGLSurface&);
+
+    /** Destroy the surface and its corresponding context (unless another
+     * surface is still using the same context, in which case the context
+     * is not destroyed). */
+    void destroySurface(const EGLSurface&);
+
+    /** Return the context corresponding to the surface.
+     * If no corresponding context exists, one is created automatically. */
+    EGLContext contextForSurface(const EGLSurface&);
+
+private:
+    static void registerPlatformSurface(SurfaceOpenVG*);
+    static void unregisterPlatformSurface(SurfaceOpenVG*);
+
+    EGLDisplayOpenVG(const EGLDisplay& display);
+    ~EGLDisplayOpenVG();
+
+    EGLDisplay m_display;
+    SurfaceOpenVG* m_sharedPlatformSurface;
+    EGLint m_pbufferConfigId;
+    EGLint m_windowConfigId;
+
+    HashMap<EGLSurface, SurfaceOpenVG*> m_platformSurfaces;
+    HashMap<EGLNativeWindowType, EGLSurface> m_windowSurfaces;
+    HashMap<EGLSurface, EGLint> m_surfaceConfigIds;
+    HashMap<EGLint, EGLint> m_compatibleConfigIds;
+    HashMap<EGLint, EGLContext> m_contexts;
+};
+
+}
+
+#endif
diff --git a/WebCore/platform/graphics/openvg/EGLUtils.h b/WebCore/platform/graphics/openvg/EGLUtils.h
new file mode 100644
index 0000000..84e318e
--- /dev/null
+++ b/WebCore/platform/graphics/openvg/EGLUtils.h
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) Research In Motion Limited 2009-2010. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB.  If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef EGLUtils_h
+#define EGLUtils_h
+
+#include <egl.h>
+#include <wtf/Assertions.h>
+
+static inline const char* toEGLErrorConstant(EGLint error)
+{
+    switch (error) {
+    case EGL_NOT_INITIALIZED:
+        return "EGL_NOT_INITIALIZED";
+    case EGL_BAD_ACCESS:
+        return "EGL_BAD_ACCESS";
+    case EGL_BAD_ALLOC:
+        return "EGL_BAD_ALLOC";
+    case EGL_BAD_ATTRIBUTE:
+        return "EGL_BAD_ATTRIBUTE";
+    case EGL_BAD_CONTEXT:
+        return "EGL_BAD_CONTEXT";
+    case EGL_BAD_CONFIG:
+        return "EGL_BAD_CONFIG";
+    case EGL_BAD_CURRENT_SURFACE:
+        return "EGL_BAD_CURRENT_SURFACE";
+    case EGL_BAD_DISPLAY:
+        return "EGL_BAD_DISPLAY";
+    case EGL_BAD_SURFACE:
+        return "EGL_BAD_SURFACE";
+    case EGL_BAD_MATCH:
+        return "EGL_BAD_MATCH";
+    case EGL_BAD_PARAMETER:
+        return "EGL_BAD_PARAMETER";
+    case EGL_BAD_NATIVE_PIXMAP:
+        return "EGL_BAD_NATIVE_PIXMAP";
+    case EGL_BAD_NATIVE_WINDOW:
+        return "EGL_BAD_NATIVE_WINDOW";
+    case EGL_CONTEXT_LOST:
+        return "EGL_CONTEXT_LOST";
+    default:
+        return "UNKNOWN_ERROR";
+    }
+}
+
+#if ASSERT_DISABLED
+#define ASSERT_EGL_NO_ERROR() ((void)0)
+#else
+#define ASSERT_EGL_NO_ERROR() \
+    ASSERT_WITH_MESSAGE(eglGetError() == VG_NO_ERROR, "Found %s", toEGLErrorConstant(eglGetError()))
+#endif
+
+#endif
diff --git a/WebCore/platform/graphics/openvg/SurfaceOpenVG.cpp b/WebCore/platform/graphics/openvg/SurfaceOpenVG.cpp
new file mode 100644
index 0000000..88a8f91
--- /dev/null
+++ b/WebCore/platform/graphics/openvg/SurfaceOpenVG.cpp
@@ -0,0 +1,208 @@
+/*
+ * Copyright (C) Research In Motion Limited 2009-2010. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB.  If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#include "config.h"
+#include "SurfaceOpenVG.h"
+
+#include "IntSize.h"
+#include "PainterOpenVG.h"
+
+#if PLATFORM(EGL)
+#include "EGLDisplayOpenVG.h"
+#include "EGLUtils.h"
+#endif
+
+#include <wtf/Assertions.h>
+#include <wtf/UnusedParam.h>
+
+namespace WebCore {
+
+SurfaceOpenVG* SurfaceOpenVG::currentSurface()
+{
+#if PLATFORM(EGL)
+    return EGLDisplayOpenVG::currentSurface();
+#else
+    ASSERT_NOT_REACHED();
+    return 0;
+#endif
+}
+
+#if PLATFORM(EGL)
+SurfaceOpenVG::SurfaceOpenVG(const IntSize& size, const EGLDisplay& display, EGLConfig* confPtr)
+    : m_eglDisplay(display)
+    , m_eglSurface(EGL_NO_SURFACE)
+    , m_eglContext(EGL_NO_CONTEXT)
+{
+    ASSERT(m_eglDisplay != EGL_NO_DISPLAY);
+
+    EGLDisplayOpenVG* displayManager = EGLDisplayOpenVG::forDisplay(m_eglDisplay);
+    EGLConfig config = confPtr ? (*confPtr) : displayManager->defaultPbufferConfig();
+    m_eglSurface = displayManager->createPbufferSurface(size, config);
+
+    if (m_eglSurface == EGL_NO_SURFACE)
+        return;
+
+    m_eglContext = displayManager->contextForSurface(m_eglSurface);
+    EGLDisplayOpenVG::registerPlatformSurface(this);
+}
+
+SurfaceOpenVG::SurfaceOpenVG(EGLNativeWindowType window, const EGLDisplay& display, EGLConfig* confPtr)
+    : m_eglDisplay(display)
+    , m_eglSurface(EGL_NO_SURFACE)
+    , m_eglContext(EGL_NO_CONTEXT)
+{
+    ASSERT(m_eglDisplay != EGL_NO_DISPLAY);
+
+    EGLDisplayOpenVG* displayManager = EGLDisplayOpenVG::forDisplay(m_eglDisplay);
+    EGLConfig config = confPtr ? (*confPtr) : displayManager->defaultWindowConfig();
+    m_eglSurface = displayManager->surfaceForWindow(window, config);
+
+    if (m_eglSurface == EGL_NO_SURFACE)
+        return;
+
+    m_eglContext = displayManager->contextForSurface(m_eglSurface);
+    EGLDisplayOpenVG::registerPlatformSurface(this);
+}
+
+// Constructor only accessible to EGLDisplayOpenVG for shared context
+// initialization. The parameter types might define to void* like in the
+// window surface constructor, so it can't be overloaded with all the required
+// arguments and EGLDisplayOpenVG basically implements the constructor
+// by itself.
+SurfaceOpenVG::SurfaceOpenVG()
+    : m_eglDisplay(EGL_NO_DISPLAY)
+    , m_eglSurface(EGL_NO_SURFACE)
+    , m_eglContext(EGL_NO_CONTEXT)
+{
+}
+#endif
+
+SurfaceOpenVG::~SurfaceOpenVG()
+{
+    if (!isValid())
+        return;
+
+#if PLATFORM(EGL)
+    EGLDisplayOpenVG::forDisplay(m_eglDisplay)->destroySurface(m_eglSurface);
+    EGLDisplayOpenVG::unregisterPlatformSurface(this);
+#else
+    ASSERT_NOT_REACHED();
+#endif
+}
+
+bool SurfaceOpenVG::isValid() const
+{
+#if PLATFORM(EGL)
+    return (m_eglSurface != EGL_NO_SURFACE);
+#else
+    ASSERT_NOT_REACHED();
+    return false;
+#endif
+}
+
+int SurfaceOpenVG::width() const
+{
+#if PLATFORM(EGL)
+    ASSERT(m_eglSurface != EGL_NO_SURFACE);
+
+    EGLint width;
+    eglQuerySurface(m_eglDisplay, m_eglSurface, EGL_WIDTH, &width);
+    ASSERT_EGL_NO_ERROR();
+    return width;
+#else
+    ASSERT_NOT_REACHED();
+    return 0;
+#endif
+}
+
+int SurfaceOpenVG::height() const
+{
+#if PLATFORM(EGL)
+    ASSERT(m_eglSurface != EGL_NO_SURFACE);
+
+    EGLint height;
+    eglQuerySurface(m_eglDisplay, m_eglSurface, EGL_HEIGHT, &height);
+    ASSERT_EGL_NO_ERROR();
+    return height;
+#else
+    ASSERT_NOT_REACHED();
+    return 0;
+#endif
+}
+
+SurfaceOpenVG* SurfaceOpenVG::sharedSurface() const
+{
+#if PLATFORM(EGL)
+    ASSERT(m_eglSurface != EGL_NO_SURFACE);
+    return EGLDisplayOpenVG::forDisplay(m_eglDisplay)->sharedPlatformSurface();
+#else
+    ASSERT_NOT_REACHED();
+    return 0;
+#endif
+}
+
+void SurfaceOpenVG::makeCurrent(MakeCurrentMode mode)
+{
+#if PLATFORM(EGL)
+    ASSERT(m_eglSurface != EGL_NO_SURFACE);
+
+    eglBindAPI(EGL_OPENVG_API);
+    ASSERT_EGL_NO_ERROR();
+    EGLSurface currentSurface = eglGetCurrentSurface(EGL_DRAW);
+    ASSERT_EGL_NO_ERROR();
+
+    if (currentSurface != m_eglSurface) {
+        eglMakeCurrent(m_eglDisplay, m_eglSurface, m_eglSurface, m_eglContext);
+        ASSERT_EGL_NO_ERROR();
+    }
+#else
+    UNUSED_PARAM(mode);
+#endif
+}
+
+void SurfaceOpenVG::makeCompatibleCurrent()
+{
+#if PLATFORM(EGL)
+    ASSERT(m_eglSurface != EGL_NO_SURFACE);
+
+    eglBindAPI(EGL_OPENVG_API);
+    ASSERT_EGL_NO_ERROR();
+    EGLSurface currentSurface = eglGetCurrentSurface(EGL_DRAW);
+    ASSERT_EGL_NO_ERROR();
+
+    if (currentSurface != m_eglSurface
+        && !EGLDisplayOpenVG::forDisplay(m_eglDisplay)->surfacesCompatible(currentSurface, m_eglSurface)) {
+        eglMakeCurrent(m_eglDisplay, m_eglSurface, m_eglSurface, m_eglContext);
+        ASSERT_EGL_NO_ERROR();
+    }
+    // else: surfaces compatible, no need to switch contexts
+#endif
+}
+
+void SurfaceOpenVG::flush()
+{
+#if PLATFORM(EGL)
+    ASSERT(m_eglSurface != EGL_NO_SURFACE);
+
+    eglSwapBuffers(m_eglDisplay, m_eglSurface);
+    ASSERT_EGL_NO_ERROR();
+#endif
+}
+
+}
diff --git a/WebCore/platform/graphics/openvg/SurfaceOpenVG.h b/WebCore/platform/graphics/openvg/SurfaceOpenVG.h
new file mode 100644
index 0000000..37b17e7
--- /dev/null
+++ b/WebCore/platform/graphics/openvg/SurfaceOpenVG.h
@@ -0,0 +1,129 @@
+/*
+ * Copyright (C) Research In Motion Limited 2009-2010. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB.  If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef SurfaceOpenVG_h
+#define SurfaceOpenVG_h
+
+#if PLATFORM(EGL)
+#include <egl.h>
+#endif
+
+#include <wtf/Noncopyable.h>
+#include <wtf/Platform.h>
+
+namespace WebCore {
+
+#if PLATFORM(EGL)
+class EGLDisplayOpenVG;
+#endif
+class IntSize;
+
+/**
+ * SurfaceOpenVG provides the functionality of surfaces and contexts that are
+ * underlying the OpenVG implementation. In the vast majority of cases, that
+ * underlying technology is EGL, but OpenVG doesn't depend on EGL per se.
+ * Wrapping surface/context functionality into a separate class avoids lots
+ * of #ifdefs and should make it easy to add different surface/context
+ * implementations than EGL.
+ */
+class SurfaceOpenVG : public Noncopyable {
+public:
+    static SurfaceOpenVG* currentSurface();
+
+#if PLATFORM(EGL)
+    friend class EGLDisplayOpenVG;
+
+    /**
+     * Create a new EGL pbuffer surface with the specified size and config on
+     * the given display. If config is not specified, the display's default
+     * pbuffer config is used.
+     *
+     * For reasons of recoverability (e.g. ImageBuffer's "bool success"
+     * return value), this constructor won't assert if creation of the surface
+     * fails. Make sure to check successful surface creation with either
+     * ASSERT_EGL_NO_ERROR() or the surface's isValid() method.
+     */
+    SurfaceOpenVG(const IntSize& size, const EGLDisplay& display, EGLConfig* config = 0);
+
+    /**
+     * Create a new EGL window surface with the specified native window handle
+     * and config on the given display. If config is not specified, the
+     * display's default window config is used.
+     *
+     * For reasons of recoverability, this constructor won't assert if creation
+     * of the surface fails. Make sure to check successful surface creation
+     * with either ASSERT_EGL_NO_ERROR() or the surface's isValid() method.
+     */
+    SurfaceOpenVG(EGLNativeWindowType window, const EGLDisplay& display, EGLConfig* config = 0);
+
+    EGLDisplay eglDisplay() const { return m_eglDisplay; }
+    EGLSurface eglSurface() const { return m_eglSurface; }
+    EGLContext eglContext() const { return m_eglContext; }
+#endif
+
+    ~SurfaceOpenVG();
+
+    /**
+     * If a surface is invalid (could not be created), all method calls will
+     * crash horribly.
+     */
+    bool isValid() const;
+
+    int width() const;
+    int height() const;
+
+    SurfaceOpenVG* sharedSurface() const;
+
+    /**
+     * Make the associated GL/EGL context the current one, so that subsequent
+     * OpenVG commands apply to it.
+     */
+    void makeCurrent();
+
+    /**
+     * Make a surface/context combination current that is "compatible"
+     * (i.e. can access its shared resources) to the given one. If no
+     * surface/context is current, the given one is made current.
+     *
+     * This method is meant to avoid context changes if they're not
+     * necessary, particularly tailored for the case where something
+     * compatible to the shared surface is requested while actual painting
+     * happens on another surface.
+     */
+    void makeCompatibleCurrent();
+
+    /**
+     * Empty the OpenVG pipeline and make sure all the performed paint
+     * operations show up on the surface as actual drawn pixels.
+     */
+    void flush();
+
+private:
+#if PLATFORM(EGL)
+    SurfaceOpenVG(); // for EGLDisplayOpenVG
+
+    EGLDisplay m_eglDisplay;
+    EGLSurface m_eglSurface;
+    EGLContext m_eglContext;
+#endif
+};
+
+}
+
+#endif
diff --git a/WebCore/platform/graphics/openvg/VGUtils.h b/WebCore/platform/graphics/openvg/VGUtils.h
new file mode 100644
index 0000000..f08e06e
--- /dev/null
+++ b/WebCore/platform/graphics/openvg/VGUtils.h
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) Research In Motion Limited 2009-2010. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB.  If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef VGUtils_h
+#define VGUtils_h
+
+#include <openvg.h>
+#include <wtf/Assertions.h>
+
+static inline const char* toVGErrorConstant(VGErrorCode error)
+{
+    switch (error) {
+    case VG_BAD_HANDLE_ERROR:
+        return "VG_BAD_HANDLE_ERROR";
+    case VG_ILLEGAL_ARGUMENT_ERROR:
+        return "VG_ILLEGAL_ARGUMENT_ERROR";
+    case VG_OUT_OF_MEMORY_ERROR:
+        return "VG_OUT_OF_MEMORY_ERROR";
+    case VG_PATH_CAPABILITY_ERROR:
+        return "VG_PATH_CAPABILITY_ERROR";
+    case VG_UNSUPPORTED_IMAGE_FORMAT_ERROR:
+        return "VG_UNSUPPORTED_IMAGE_FORMAT_ERROR";
+    case VG_UNSUPPORTED_PATH_FORMAT_ERROR:
+        return "VG_UNSUPPORTED_PATH_FORMAT_ERROR";
+    case VG_IMAGE_IN_USE_ERROR:
+        return "VG_IMAGE_IN_USE_ERROR";
+    case VG_NO_CONTEXT_ERROR:
+        return "VG_NO_CONTEXT_ERROR";
+    default:
+        return "UNKNOWN_ERROR";
+    }
+}
+
+#if ASSERT_DISABLED
+#define ASSERT_VG_NO_ERROR() ((void)0)
+#else
+#define ASSERT_VG_NO_ERROR() \
+    ASSERT_WITH_MESSAGE(vgGetError() == VG_NO_ERROR, "Found %s", toVGErrorConstant(vgGetError()))
+#endif
+
+#endif

-- 
WebKit Debian packaging



More information about the Pkg-webkit-commits mailing list