diff --git a/src/wayland/meta-wayland-dma-buf.c b/src/wayland/meta-wayland-dma-buf.c index 535fae10a..209ed878b 100644 --- a/src/wayland/meta-wayland-dma-buf.c +++ b/src/wayland/meta-wayland-dma-buf.c @@ -51,6 +51,7 @@ #include "cogl/cogl-egl.h" #include "cogl/cogl.h" #include "common/meta-cogl-drm-formats.h" +#include "compositor/meta-multi-texture-format-private.h" #include "meta/meta-backend.h" #include "wayland/meta-wayland-buffer.h" #include "wayland/meta-wayland-private.h" @@ -343,12 +344,8 @@ meta_wayland_dma_buf_realize_texture (MetaWaylandBuffer *buffer, CoglContext *cogl_context = clutter_backend_get_cogl_context (clutter_backend); EGLDisplay egl_display = cogl_egl_context_get_egl_display (cogl_context); MetaWaylandDmaBufBuffer *dma_buf = buffer->dma_buf.dma_buf; - uint32_t n_planes; - uint64_t modifiers[META_WAYLAND_DMA_BUF_MAX_FDS]; + MetaMultiTextureFormat multi_format; CoglPixelFormat cogl_format; - EGLImageKHR egl_image; - CoglEglImageFlags flags; - CoglTexture2D *cogl_texture; #ifdef HAVE_NATIVE_BACKEND MetaDrmFormatBuf format_buf; #endif @@ -358,7 +355,7 @@ meta_wayland_dma_buf_realize_texture (MetaWaylandBuffer *buffer, if (!meta_cogl_pixel_format_from_drm_format (dma_buf->drm_format, &cogl_format, - NULL)) + &multi_format)) { g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, @@ -368,49 +365,140 @@ meta_wayland_dma_buf_realize_texture (MetaWaylandBuffer *buffer, #ifdef HAVE_NATIVE_BACKEND meta_topic (META_DEBUG_WAYLAND, - "[dma-buf] wl_buffer@%u DRM format %s -> CoglPixelFormat %s", + "[dma-buf] wl_buffer@%u DRM format %s " + "-> MetaMultiTextureFormat %s / CoglPixelFormat %s", wl_resource_get_id (meta_wayland_buffer_get_resource (buffer)), meta_drm_format_to_string (&format_buf, dma_buf->drm_format), + meta_multi_texture_format_to_string (multi_format), cogl_pixel_format_to_string (cogl_format)); #endif - for (n_planes = 0; n_planes < META_WAYLAND_DMA_BUF_MAX_FDS; n_planes++) + if (multi_format == META_MULTI_TEXTURE_FORMAT_SIMPLE) { - if (dma_buf->fds[n_planes] < 0) - break; + EGLImageKHR egl_image; + CoglEglImageFlags flags; + CoglTexture2D *cogl_texture; + uint64_t modifiers[META_WAYLAND_DMA_BUF_MAX_FDS]; + uint32_t n_planes; - modifiers[n_planes] = dma_buf->drm_modifier; + for (n_planes = 0; n_planes < META_WAYLAND_DMA_BUF_MAX_FDS; n_planes++) + { + if (dma_buf->fds[n_planes] < 0) + break; + + modifiers[n_planes] = dma_buf->drm_modifier; + } + + egl_image = meta_egl_create_dmabuf_image (egl, + egl_display, + dma_buf->width, + dma_buf->height, + dma_buf->drm_format, + n_planes, + dma_buf->fds, + dma_buf->strides, + dma_buf->offsets, + modifiers, + error); + if (egl_image == EGL_NO_IMAGE_KHR) + return FALSE; + + flags = COGL_EGL_IMAGE_FLAG_NO_GET_DATA; + cogl_texture = cogl_egl_texture_2d_new_from_image (cogl_context, + dma_buf->width, + dma_buf->height, + cogl_format, + egl_image, + flags, + error); + + meta_egl_destroy_image (egl, egl_display, egl_image, NULL); + + if (!cogl_texture) + return FALSE; + + buffer->dma_buf.texture = + meta_multi_texture_new_simple (COGL_TEXTURE (cogl_texture)); } + else + { + CoglTexture **textures; + g_autoptr (GPtrArray) planes = NULL; + CoglPixelFormat subformats[META_WAYLAND_DMA_BUF_MAX_FDS]; + uint8_t horizontal_factors[META_WAYLAND_DMA_BUF_MAX_FDS]; + uint8_t vertical_factors[META_WAYLAND_DMA_BUF_MAX_FDS]; + uint8_t plane_indices[META_WAYLAND_DMA_BUF_MAX_FDS]; + int n_planes, i; - egl_image = meta_egl_create_dmabuf_image (egl, - egl_display, - dma_buf->width, - dma_buf->height, - dma_buf->drm_format, - n_planes, - dma_buf->fds, - dma_buf->strides, - dma_buf->offsets, - modifiers, - error); - if (egl_image == EGL_NO_IMAGE_KHR) - return FALSE; + n_planes = meta_multi_texture_format_get_n_planes (multi_format); - flags = COGL_EGL_IMAGE_FLAG_NO_GET_DATA; - cogl_texture = cogl_egl_texture_2d_new_from_image (cogl_context, - dma_buf->width, - dma_buf->height, - cogl_format, - egl_image, - flags, - error); + /* Each EGLImage is a plane in the final CoglMultiPlaneTexture */ + planes = g_ptr_array_new_full (n_planes, cogl_object_unref); + meta_multi_texture_format_get_subformats (multi_format, subformats); + meta_multi_texture_format_get_plane_indices (multi_format, plane_indices); + meta_multi_texture_format_get_subsampling_factors (multi_format, + horizontal_factors, + vertical_factors); - meta_egl_destroy_image (egl, egl_display, egl_image, NULL); + for (i = 0; i < n_planes; i++) + { + EGLImageKHR egl_image; + CoglEglImageFlags flags; + CoglTexture2D *cogl_texture; + uint32_t drm_format = 0; + int plane_index, j; - if (!cogl_texture) - return FALSE; + for (j = 0; j < G_N_ELEMENTS (meta_cogl_drm_format_map); j++) + { + if (meta_cogl_drm_format_map[j].cogl_format == subformats[i]) + { + drm_format = meta_cogl_drm_format_map[j].drm_format; + break; + } + } + g_return_val_if_fail (drm_format != 0, FALSE); - buffer->dma_buf.texture = meta_multi_texture_new_simple (COGL_TEXTURE (cogl_texture)); + plane_index = plane_indices[i]; + + egl_image = meta_egl_create_dmabuf_image (egl, + egl_display, + dma_buf->width / + horizontal_factors[i], + dma_buf->height / + vertical_factors[i], + drm_format, + 1, + &dma_buf->fds[plane_index], + &dma_buf->strides[plane_index], + &dma_buf->offsets[plane_index], + &dma_buf->drm_modifier, + error); + if (egl_image == EGL_NO_IMAGE_KHR) + return FALSE; + + flags = COGL_EGL_IMAGE_FLAG_NO_GET_DATA; + cogl_texture = cogl_egl_texture_2d_new_from_image (cogl_context, + dma_buf->width, + dma_buf->height, + subformats[i], + egl_image, + flags, + error); + + meta_egl_destroy_image (egl, egl_display, egl_image, NULL); + + if (!cogl_texture) + return FALSE; + + g_ptr_array_add (planes, cogl_texture); + } + + textures = (CoglTexture**) g_ptr_array_free (g_steal_pointer (&planes), + FALSE); + buffer->dma_buf.texture = meta_multi_texture_new (multi_format, + textures, + n_planes); + } buffer->is_y_inverted = dma_buf->is_y_inverted; return TRUE;