diff --git a/include/libweston/libweston.h b/include/libweston/libweston.h index 5cb5c60a..4be9f8d4 100644 --- a/include/libweston/libweston.h +++ b/include/libweston/libweston.h @@ -1193,6 +1193,9 @@ struct weston_buffer { uint32_t busy_count; int y_inverted; void *backend_private; + + const struct pixel_format_info *pixel_format; + uint64_t format_modifier; }; struct weston_buffer_reference { diff --git a/libweston/compositor.c b/libweston/compositor.c index b2ecaa89..4e276b4e 100644 --- a/libweston/compositor.c +++ b/libweston/compositor.c @@ -52,6 +52,7 @@ #include #include #include +#include #include "timeline.h" @@ -2415,11 +2416,25 @@ weston_buffer_from_resource(struct weston_compositor *ec, buffer->width = wl_shm_buffer_get_width(shm); buffer->height = wl_shm_buffer_get_height(shm); buffer->y_inverted = true; + /* wl_shm might create a buffer with an unknown format, so check + * and reject */ + buffer->pixel_format = + pixel_format_get_info_shm(wl_shm_buffer_get_format(shm)); + buffer->format_modifier = DRM_FORMAT_MOD_LINEAR; + + if (!buffer->pixel_format) + goto fail; } else if ((dmabuf = linux_dmabuf_buffer_get(buffer->resource))) { buffer->type = WESTON_BUFFER_DMABUF; buffer->dmabuf = dmabuf; buffer->width = dmabuf->attributes.width; buffer->height = dmabuf->attributes.height; + buffer->pixel_format = + pixel_format_get_info(dmabuf->attributes.format); + /* dmabuf import should assure we don't create a buffer with an + * unknown format */ + assert(buffer->pixel_format); + buffer->format_modifier = dmabuf->attributes.modifier[0]; buffer->y_inverted = !(dmabuf->attributes.flags & ZWP_LINUX_BUFFER_PARAMS_V1_FLAGS_Y_INVERT); } else { @@ -2431,6 +2446,10 @@ weston_buffer_from_resource(struct weston_compositor *ec, buffer->type = WESTON_BUFFER_RENDERER_OPAQUE; } + /* Don't accept any formats we can't reason about: the importer should + * make sure this never happens */ + assert(buffer->pixel_format); + return buffer; fail: diff --git a/libweston/renderer-gl/gl-renderer.c b/libweston/renderer-gl/gl-renderer.c index 2b9c11d9..a87ac466 100644 --- a/libweston/renderer-gl/gl-renderer.c +++ b/libweston/renderer-gl/gl-renderer.c @@ -2158,6 +2158,8 @@ gl_renderer_fill_buffer_info(struct weston_compositor *ec, struct weston_buffer *buffer) { struct gl_renderer *gr = get_renderer(ec); + EGLint format; + uint32_t fourcc; bool ret = true; buffer->legacy_buffer = (struct wl_buffer *)buffer->resource; @@ -2165,6 +2167,37 @@ gl_renderer_fill_buffer_info(struct weston_compositor *ec, EGL_WIDTH, &buffer->width); ret &= gr->query_buffer(gr->egl_display, buffer->legacy_buffer, EGL_HEIGHT, &buffer->height); + ret &= gr->query_buffer(gr->egl_display, buffer->legacy_buffer, + EGL_TEXTURE_FORMAT, &format); + if (!ret) + return false; + + /* The legacy EGL buffer interface only describes the channels we can + * sample from; not their depths or order. Take a stab at something + * which might be representative. Pessimise extremely hard for + * TEXTURE_EXTERNAL_OES. */ + switch (format) { + case EGL_TEXTURE_RGB: + fourcc = DRM_FORMAT_XRGB8888; + break; + case EGL_TEXTURE_EXTERNAL_WL: + case EGL_TEXTURE_RGBA: + fourcc = DRM_FORMAT_ARGB8888; + break; + case EGL_TEXTURE_Y_XUXV_WL: + fourcc = DRM_FORMAT_YUYV; + break; + case EGL_TEXTURE_Y_UV_WL: + fourcc = DRM_FORMAT_NV12; + break; + case EGL_TEXTURE_Y_U_V_WL: + fourcc = DRM_FORMAT_YUV420; + break; + } + + buffer->pixel_format = pixel_format_get_info(fourcc); + assert(buffer->pixel_format); + buffer->format_modifier = DRM_FORMAT_MOD_INVALID; /* Assume scanout co-ordinate space i.e. (0,0) is top-left * if the query fails */ @@ -2172,7 +2205,7 @@ gl_renderer_fill_buffer_info(struct weston_compositor *ec, gr->query_buffer(gr->egl_display, buffer->legacy_buffer, EGL_WAYLAND_Y_INVERTED_WL, &buffer->y_inverted); - return ret; + return true; } static void