static PFNGLEGLIMAGETARGETTEXTURE2DOESPROC eglImageTargetTexture2DOES = 0;
static PFNEGLLOCKSURFACEKHRPROC eglLockSurfaceKHR = 0;
static PFNEGLUNLOCKSURFACEKHRPROC eglUnlockSurfaceKHR = 0;
+#if PLATFORM(WAYLAND)
+static PFNEGLQUERYWAYLANDBUFFERWL eglQueryWaylandBufferWL = 0;
+#endif
struct EGLDisplayConnection {
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)
}
#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")) {
, 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);
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)
m_state |= Mapped;
m_useLinearFilter = useLinearFilter;
- if (!m_textureId)
+ if (!m_textureIds[0])
m_state |= PendingUpdate;
}
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)
{
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;
}
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;