prepare multiple texture for wayland buffer 33/9033/1
authorZhao Halley <halley.zhao@intel.com>
Wed, 21 Aug 2013 01:44:20 +0000 (09:44 +0800)
committerZhao Halley <halley.zhao@intel.com>
Mon, 2 Sep 2013 02:39:13 +0000 (10:39 +0800)
Change-Id: I5130904e09f962c81b0b1ccd240869de150c38cf

Source/WebCore/platform/graphics/surfaces/egl/EGLHelper.cpp
Source/WebCore/platform/graphics/surfaces/egl/EGLHelper.h
Source/WebCore/platform/graphics/surfaces/wayland/GraphicsSurfaceWayland.cpp
Source/WebCore/platform/graphics/surfaces/wayland/PlatformTextureWayland.cpp
Source/WebCore/platform/graphics/surfaces/wayland/PlatformTextureWayland.h
Source/WebCore/platform/graphics/surfaces/wayland/WaylandSurface.cpp
Source/WebCore/platform/graphics/surfaces/wayland/WaylandSurface.h

index 8d493a4..8f3fd2f 100644 (file)
@@ -49,6 +49,9 @@ static PFNEGLDESTROYIMAGEKHRPROC eglDestroyImageKHR = 0;
 static PFNGLEGLIMAGETARGETTEXTURE2DOESPROC eglImageTargetTexture2DOES = 0;
 static PFNEGLLOCKSURFACEKHRPROC eglLockSurfaceKHR = 0;
 static PFNEGLUNLOCKSURFACEKHRPROC eglUnlockSurfaceKHR = 0;
+#if PLATFORM(WAYLAND)
+static PFNEGLQUERYWAYLANDBUFFERWL eglQueryWaylandBufferWL = 0;
+#endif
 
 struct EGLDisplayConnection {
 
@@ -146,6 +149,23 @@ PlatformDisplay EGLHelper::compositorEGLDisplay(NativeSharedDisplay* display)
     static EGLDisplayConnection displayConnection(display);
     return displayConnection.display();
 }
+
+GLint EGLHelper::queryWaylandBufferWLFormat(void *buffer, EGLDisplay eglDisplay)
+{
+    EGLDisplay display = eglDisplay;
+    if (display == EGL_NO_DISPLAY)
+        display = currentDisplay();
+
+    if (display == EGL_NO_DISPLAY)
+        return -1;
+
+    EGLint format = -1;
+    if (eglQueryWaylandBufferWL) {
+        eglQueryWaylandBufferWL(display, (struct wl_buffer*)buffer, EGL_TEXTURE_FORMAT, &format);
+    }
+
+    return format;
+}
 #endif
 
 void EGLHelper::resolveEGLBindings(EGLDisplay eglDisplay)
@@ -170,6 +190,10 @@ void EGLHelper::resolveEGLBindings(EGLDisplay eglDisplay)
     }
 
 #if PLATFORM(WAYLAND)
+    eglQueryWaylandBufferWL = (PFNEGLQUERYWAYLANDBUFFERWL) eglGetProcAddress("eglQueryWaylandBufferWL");
+#endif
+
+#if PLATFORM(WAYLAND)
     if (GLPlatformContext::supportsEGLExtension(display, "EGL_KHR_image_base") && GLPlatformContext::supportsEGLExtension(display, "EGL_WL_bind_wayland_display")) {
 #else
     if (GLPlatformContext::supportsEGLExtension(display, "EGL_KHR_image") && GLPlatformContext::supportsEGLExtension(display, "EGL_KHR_image_pixmap")) {
index 85c39bf..96e9527 100644 (file)
@@ -61,6 +61,9 @@ public:
     static bool lockSurface(EGLSurface, EGLint[], EGLDisplay = EGL_NO_DISPLAY);
     static bool unlockSurface(EGLSurface, EGLDisplay = EGL_NO_DISPLAY);
     static bool querySurface(EGLSurface, EGLint, EGLint*, EGLDisplay = EGL_NO_DISPLAY);
+#if PLATFORM(WAYLAND)
+    static GLint queryWaylandBufferWLFormat(void *buffer, EGLDisplay eglDisplay);
+#endif
 };
 
 }
index 44191bf..2f60717 100644 (file)
@@ -61,6 +61,31 @@ public:
         return textureId;
     }
 
+    uint32_t totalPlanes()
+    {
+        return m_platformTexture ? m_platformTexture->totalPlanes() : 0;
+    }
+
+    uint32_t textureFormat()
+    {
+        return m_platformTexture ? m_platformTexture->textureFormat() : 0;
+    }
+
+    uint32_t* textureIds()
+    {
+        uint32_t* ids = NULL;
+        if (m_platformTexture) {
+            ids = m_platformTexture->textureIds();
+
+            if (!ids) {
+                m_platformTexture->initialize(m_useLinearFilter);
+                ids = m_platformTexture->textureIds();
+            }
+        }
+
+        return ids;
+    }
+
 private:
     bool m_useLinearFilter : 1;
     OwnPtr<PlatformTextureWayland> m_platformTexture;
index 1bd6051..d7e69e7 100644 (file)
@@ -74,6 +74,21 @@ uint32_t PlatformTextureWayland::id() const
     return m_buffer ? m_buffer->textureId() :0;
 }
 
+uint32_t PlatformTextureWayland::totalPlanes()
+{
+    return m_buffer ? m_buffer->totalPlanes() : 0;
+}
+
+uint32_t PlatformTextureWayland::textureFormat()
+{
+    return m_buffer ? m_buffer->textureFormat() : 0;
+}
+
+uint32_t* PlatformTextureWayland::textureIds()
+{
+    return m_buffer ? m_buffer->textureIds() : NULL;
+}
+
 void PlatformTextureWayland::bufferDestroyed()
 {
     m_buffer = 0;
index 4a111c1..172525f 100644 (file)
@@ -35,6 +35,9 @@ public:
     ~PlatformTextureWayland();
     bool initialize(bool useLinearFilter);
     virtual uint32_t id() const OVERRIDE;
+    uint32_t totalPlanes();
+    uint32_t textureFormat();
+    uint32_t* textureIds();
     virtual int platformSurfaceId() const OVERRIDE { return m_platformSurfaceID; }
     virtual void updateTexture() OVERRIDE { }
     virtual void setUsed(bool used) OVERRIDE { m_used = used; }
index 45e5735..61fefaf 100644 (file)
@@ -150,11 +150,18 @@ WaylandBuffer::WaylandBuffer(wl_client* client, uint32_t id)
     , m_useLinearFilter(false)
     , m_state(Default)
     , m_id(0)
-    , m_textureId(0)
+    , m_format(0)
+    , m_numPlanes(0)
 {
     static WaylandSurfaceId bufferHandleId = 0;
+    int i;
+
     bufferHandleId++;
     m_id = bufferHandleId;
+
+    for (i=0; i<s_maxPlaneCount; i++) {
+        m_textureIds[i] = 0;
+    }
     wl_resource* resource = wl_resource_create(client, &wl_surface_interface, 1, id);
     wl_resource_set_implementation(resource, &surfaceInterface, this, WaylandBuffer::destroySurface);
     wl_list_init(&m_callbackList);
@@ -166,22 +173,22 @@ WaylandBuffer::~WaylandBuffer()
     m_id = 0;
 }
 
-uint WaylandBuffer::textureId()
+uint32_t WaylandBuffer::textureId()
 {
     if (m_state & PendingUpdate)
-        bindTextureToImage();
+        bindTextureToImage(true);
 
-    if (!m_textureId) {
+    if (!m_textureIds[0]) {
         WaylandDisplay::instance()->lock();
         WaylandDisplay::instance()->handlePendingEvents();
-        if (!m_textureId)
+        if (!m_textureIds[0])
             handleSurfaceCommit();
 
-        bindTextureToImage();
+        bindTextureToImage(true);
         WaylandDisplay::instance()->unlock();
     }
 
-    return m_textureId;
+    return m_textureIds[0];
 }
 
 void WaylandBuffer::mapSurface(bool useLinearFilter)
@@ -191,7 +198,7 @@ void WaylandBuffer::mapSurface(bool useLinearFilter)
 
     m_state |= Mapped;
     m_useLinearFilter = useLinearFilter;
-    if (!m_textureId)
+    if (!m_textureIds[0])
         m_state |= PendingUpdate;
 }
 
@@ -203,11 +210,18 @@ void WaylandBuffer::unmapSurface()
 
 void WaylandBuffer::release()
 {
-    if (m_textureId) {
+    int i;
+    for (i=0; i<m_numPlanes; i++) {
+        glActiveTexture(GL_TEXTURE0 + i);
         glBindTexture(GL_TEXTURE_2D, 0);
-        glDeleteTextures(1, &m_textureId);
-        m_textureId = 0;
+        if (m_textureIds[i])
+            glDeleteTextures(1, &m_textureIds[i]);
+        m_textureIds[i] = 0;
     }
+
+    glActiveTexture(GL_TEXTURE0);
+    m_numPlanes = 0;
+    m_format    = 0;
 }
 
 void WaylandBuffer::attach(wl_resource* bufferResource)
@@ -225,31 +239,59 @@ void WaylandBuffer::handleSurfaceCommit()
 {
     m_commitedResource = m_bufferResource;
 
-    if (m_commitedResource)
+    if (m_commitedResource) {
         m_state |= PendingUpdate;
+        m_format = 0;
+        m_numPlanes = 0;
+    }
 }
 
-void WaylandBuffer::bindTextureToImage()
+void WaylandBuffer::bindTextureToImage(bool bindFirstTextureOnly)
 {
+    EGLDisplay display;
+    EGLint attribs[3];
+    EGLImageKHR eglImage = EGL_NO_IMAGE_KHR;
+    int bindTextureCount;
+    int i;
+
     if (!m_commitedResource || (m_state & Destroyed))
         return;
 
-    m_state &= ~PendingUpdate;
-    EGLDisplay display = WaylandCompositor::getInstance()->m_eglDisplay;
-    EGLImageKHR image;
-    EGLHelper::createEGLImage(&image, EGL_WAYLAND_BUFFER_WL, wl_resource_get_user_data(m_commitedResource), 0, display);
-    if (image == EGL_NO_IMAGE_KHR) {
-        LOG_ERROR("Failed to create EGLImage.");
-        return;
+    if (bindFirstTextureOnly) {
+        bindTextureCount = 1;
+        m_numPlanes = bindTextureCount;
+
+        if (!m_textureIds[0])
+            glGenTextures(1, &m_textureIds[0]);
     }
+    else {
+        if (!m_numPlanes)
+            queryBufferInformation();
 
-    if (!m_textureId)
-        glGenTextures(1, &m_textureId);
+        bindTextureCount = m_numPlanes;
+    }
+
+    display = WaylandCompositor::getInstance()->m_eglDisplay;
+    m_state &= ~PendingUpdate;
+
+    for (i = 0; i < bindTextureCount; i++) {
+        attribs[0] = EGL_WAYLAND_PLANE_WL;
+        attribs[1] = i;
+        attribs[2] = EGL_NONE;
+        EGLHelper::createEGLImage(&eglImage, EGL_WAYLAND_BUFFER_WL, wl_resource_get_user_data(m_commitedResource), attribs, display);
+        if (eglImage == EGL_NO_IMAGE_KHR) {
+            LOG_ERROR("failed to create img for plane %d\n", i);
+            continue;
+        }
+
+        glActiveTexture(GL_TEXTURE0 + i);
+        glBindTexture(GL_TEXTURE_2D, m_textureIds[i]);
+        EGLHelper::imageTargetTexture2DOES(eglImage);
+        updateFilter();
+        EGLHelper::destroyEGLImage(eglImage, display);
+        eglImage = EGL_NO_IMAGE_KHR;
+    }
 
-    glBindTexture(GL_TEXTURE_2D, m_textureId);
-    EGLHelper::imageTargetTexture2DOES(image);
-    updateFilter();
-    EGLHelper::destroyEGLImage(image, display);
     m_commitedResource = 0;
 }
 
@@ -264,6 +306,87 @@ void WaylandBuffer::updateFilter()
     glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
 }
 
+uint32_t WaylandBuffer::textureFormat()
+{
+    if (!m_format)
+        queryBufferInformation();
+
+    return m_format;
+}
+
+uint32_t WaylandBuffer::totalPlanes()
+{
+    if (!m_numPlanes)
+        queryBufferInformation();
+
+    return m_numPlanes;
+}
+
+uint32_t* WaylandBuffer::textureIds()
+{
+    if (m_state & PendingUpdate)
+        bindTextureToImage();
+
+    if (!m_textureIds[0]) {
+        WaylandDisplay::instance()->lock();
+        WaylandDisplay::instance()->handlePendingEvents();
+        if (!m_textureIds[0])
+            handleSurfaceCommit();
+
+        bindTextureToImage();
+        WaylandDisplay::instance()->unlock();
+    }
+
+    return m_textureIds;
+}
+
+void WaylandBuffer::queryBufferInformation()
+{
+    int numPlanes = 0;
+
+    if (!m_commitedResource || (m_state & Destroyed))
+        return;
+
+    EGLDisplay display = WaylandCompositor::getInstance()->m_eglDisplay;
+    if (display == EGL_NO_DISPLAY) {
+        LOG_ERROR("No Valid EGLDisplay connection.");
+        return;
+    }
+
+    m_format = EGLHelper::queryWaylandBufferWLFormat(wl_resource_get_user_data(m_commitedResource), display);
+    switch (m_format) {
+    case EGL_TEXTURE_Y_UV_WL:
+        numPlanes = 2;
+        break;
+    case EGL_TEXTURE_Y_U_V_WL:
+        numPlanes = 3;
+        break;
+    case EGL_TEXTURE_Y_XUXV_WL:
+        numPlanes = 2;
+        break;
+    case EGL_TEXTURE_RGB:
+    case EGL_TEXTURE_RGBA:
+    default:
+        numPlanes = 1;
+        break;
+    }
+
+    if (numPlanes > m_numPlanes) {
+        glGenTextures(numPlanes - m_numPlanes, &m_textureIds[m_numPlanes]);
+    } else if (numPlanes < m_numPlanes) {
+        int i;
+        for (i=numPlanes; i<m_numPlanes; i++) {
+            glActiveTexture(GL_TEXTURE0 + i);
+            glBindTexture(GL_TEXTURE_2D, 0);
+            if (m_textureIds[i])
+                glDeleteTextures(1, &m_textureIds[i]);
+            m_textureIds[i] = 0;
+        }
+    }
+
+    m_numPlanes = numPlanes;
+}
+
 void WaylandBuffer::surfaceCommitCallBack()
 {
     struct frameCallback* frameCallback;
index 22bebdd..797503c 100644 (file)
@@ -93,7 +93,11 @@ public:
     uint handle() const { return m_id; }
 
     // texture.
-    uint textureId();
+    uint32_t textureId();
+    uint32_t* textureIds();
+    uint32_t textureFormat();
+    uint32_t totalPlanes();
+
     WaylandBufferState state() const { return m_state; }
 
     static WaylandBuffer* getBuffer(wl_resource*);
@@ -117,14 +121,18 @@ private:
     void handleSurfaceCommit();
     void release();
     void updateFilter();
-    void bindTextureToImage();
+    void bindTextureToImage(bool = false);
+    void queryBufferInformation();
+    static const uint32_t s_maxPlaneCount = 3;
     struct wl_resource* m_bufferResource;
     struct wl_resource* m_commitedResource;
     struct wl_list m_callbackList;
+    uint32_t m_textureIds[s_maxPlaneCount];
+    uint32_t m_format;
+    uint32_t m_numPlanes;
     bool m_useLinearFilter :1;
     WaylandBufferState m_state :6;
     uint m_id;
-    uint32_t m_textureId;
     friend class WaylandCompositor;
 };