From: Sergi Granell <xerpi.g...@gmail.com>

The per-plane IN_FORMATS property adds information about format
modifiers; we can use these to both feed GBM with the set of modifiers
we want to use for rendering, and also as an early-out test when we're
trying to see if a FB will go on a particular plane.

Signed-off-by: Sergi Granell <xerpi.g...@gmail.com>
Reviewed-by: Daniel Stone <dani...@collabora.com>
Signed-off-by: Daniel Stone <dani...@collabora.com>
---
 libweston/compositor-drm.c | 126 ++++++++++++++++++++++++++++++++++++++++++---
 1 file changed, 118 insertions(+), 8 deletions(-)

diff --git a/libweston/compositor-drm.c b/libweston/compositor-drm.c
index 111cb9e3..811adbbd 100644
--- a/libweston/compositor-drm.c
+++ b/libweston/compositor-drm.c
@@ -83,6 +83,20 @@
 #define GBM_BO_USE_CURSOR GBM_BO_USE_CURSOR_64X64
 #endif
 
+#ifdef HAVE_DRM_ATOMIC
+static inline uint32_t *
+formats_ptr(struct drm_format_modifier_blob *blob)
+{
+       return (uint32_t *)(((char *)blob) + blob->formats_offset);
+}
+
+static inline struct drm_format_modifier *
+modifiers_ptr(struct drm_format_modifier_blob *blob)
+{
+       return (struct drm_format_modifier *)(((char *)blob) + 
blob->modifiers_offset);
+}
+#endif
+
 /**
  * Represents the values of an enum-type KMS property
  */
@@ -127,6 +141,7 @@ enum wdrm_plane_property {
        WDRM_PLANE_CRTC_H,
        WDRM_PLANE_FB_ID,
        WDRM_PLANE_CRTC_ID,
+       WDRM_PLANE_IN_FORMATS,
        WDRM_PLANE__COUNT
 };
 
@@ -168,6 +183,7 @@ static const struct drm_property_info plane_props[] = {
        [WDRM_PLANE_CRTC_H] = { .name = "CRTC_H", },
        [WDRM_PLANE_FB_ID] = { .name = "FB_ID", },
        [WDRM_PLANE_CRTC_ID] = { .name = "CRTC_ID", },
+       [WDRM_PLANE_IN_FORMATS] = { .name = "IN_FORMATS" },
 };
 
 /**
@@ -397,7 +413,11 @@ struct drm_plane {
 
        struct wl_list link;
 
-       uint32_t formats[];
+       struct {
+               uint32_t format;
+               uint32_t count_modifiers;
+               uint64_t *modifiers;
+       } formats[];
 };
 
 struct drm_output {
@@ -2811,7 +2831,19 @@ drm_output_prepare_overlay_view(struct drm_output_state 
*output_state,
 
                /* Check whether the format is supported */
                for (i = 0; i < p->count_formats; i++) {
-                       if (p->formats[i] == fb->format->format)
+                       unsigned int j;
+
+                       if (p->formats[i].format != fb->format->format)
+                               continue;
+
+                       if (fb->modifier == DRM_FORMAT_MOD_INVALID)
+                               break;
+
+                       for (j = 0; j < p->formats[i].count_modifiers; j++) {
+                               if (p->formats[i].modifiers[j] == fb->modifier)
+                                       break;
+                       }
+                       if (j != p->formats[i].count_modifiers)
                                break;
                }
                if (i == p->count_formats)
@@ -3578,6 +3610,61 @@ init_pixman(struct drm_backend *b)
        return pixman_renderer_init(b->compositor);
 }
 
+/**
+ * Populates the formats array, and the modifiers of each format for a 
drm_plane.
+ */
+#ifdef HAVE_DRM_ATOMIC
+static bool
+populate_format_modifiers(struct drm_plane *plane, const drmModePlane *kplane,
+                         uint32_t blob_id)
+{
+       unsigned i, j;
+       drmModePropertyBlobRes *blob;
+       struct drm_format_modifier_blob *fmt_mod_blob;
+       uint32_t *blob_formats;
+       struct drm_format_modifier *blob_modifiers;
+
+       blob = drmModeGetPropertyBlob(plane->backend->drm.fd, blob_id);
+       if (!blob)
+               return false;
+
+       fmt_mod_blob = blob->data;
+       blob_formats = formats_ptr(fmt_mod_blob);
+       blob_modifiers = modifiers_ptr(fmt_mod_blob);
+
+       assert(plane->count_formats == fmt_mod_blob->count_formats);
+
+       for (i = 0; i < fmt_mod_blob->count_formats; i++) {
+               uint32_t count_modifiers = 0;
+               uint64_t *modifiers = NULL;
+
+               for (j = 0; j < fmt_mod_blob->count_modifiers; j++) {
+                       struct drm_format_modifier *mod = &blob_modifiers[j];
+
+                       if ((i < mod->offset) || (i > mod->offset + 63))
+                               continue;
+                       if (!(mod->formats & (1 << (i - mod->offset))))
+                               continue;
+
+                       modifiers = realloc(modifiers, (count_modifiers + 1) * 
sizeof(modifiers[0]));
+                       if (!modifiers) {
+                               drmModeFreePropertyBlob(blob);
+                               return false;
+                       }
+                       modifiers[count_modifiers++] = mod->modifier;
+               }
+
+               plane->formats[i].format = blob_formats[i];
+               plane->formats[i].modifiers = modifiers;
+               plane->formats[i].count_modifiers = count_modifiers;
+       }
+
+       drmModeFreePropertyBlob(blob);
+
+       return true;
+}
+#endif
+
 /**
  * Create a drm_plane for a hardware plane
  *
@@ -3607,25 +3694,27 @@ drm_plane_create(struct drm_backend *b, const 
drmModePlane *kplane,
 {
        struct drm_plane *plane;
        drmModeObjectProperties *props;
-       int num_formats = (kplane) ? kplane->count_formats : 1;
+       uint32_t num_formats = (kplane) ? kplane->count_formats : 1;
 
        plane = zalloc(sizeof(*plane) +
-                      (sizeof(uint32_t) * num_formats));
+                      (sizeof(plane->formats[0]) * num_formats));
        if (!plane) {
                weston_log("%s: out of memory\n", __func__);
                return NULL;
        }
 
        plane->backend = b;
+       plane->count_formats = num_formats;
        plane->state_cur = drm_plane_state_alloc(NULL, plane);
        plane->state_cur->complete = true;
 
        if (kplane) {
+#ifdef HAVE_DRM_ATOMIC
+               uint32_t blob_id;
+#endif
+
                plane->possible_crtcs = kplane->possible_crtcs;
                plane->plane_id = kplane->plane_id;
-               plane->count_formats = kplane->count_formats;
-               memcpy(plane->formats, kplane->formats,
-                      kplane->count_formats * sizeof(kplane->formats[0]));
 
                props = drmModeObjectGetProperties(b->drm.fd, kplane->plane_id,
                                                   DRM_MODE_OBJECT_PLANE);
@@ -3640,13 +3729,34 @@ drm_plane_create(struct drm_backend *b, const 
drmModePlane *kplane,
                        drm_property_get_value(&plane->props[WDRM_PLANE_TYPE],
                                               props,
                                               WDRM_PLANE_TYPE__COUNT);
+
+#ifdef HAVE_DRM_ATOMIC
+               blob_id = 
drm_property_get_value(&plane->props[WDRM_PLANE_IN_FORMATS],
+                                                props,
+                                                0);
+               if (blob_id) {
+                       if (!populate_format_modifiers(plane, kplane, blob_id)) 
{
+                               weston_log("%s: out of memory\n", __func__);
+                               drm_property_info_free(plane->props, 
WDRM_PLANE__COUNT);
+                               drmModeFreeObjectProperties(props);
+                               free(plane);
+                               return NULL;
+                       }
+               } else
+#endif
+               {
+                       uint32_t i;
+                       for (i = 0; i < kplane->count_formats; i++)
+                               plane->formats[i].format = kplane->formats[i];
+               }
+
                drmModeFreeObjectProperties(props);
        }
        else {
                plane->possible_crtcs = (1 << output->pipe);
                plane->plane_id = 0;
                plane->count_formats = 1;
-               plane->formats[0] = format;
+               plane->formats[0].format = format;
                plane->type = type;
        }
 
-- 
2.14.1

_______________________________________________
wayland-devel mailing list
wayland-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/wayland-devel

Reply via email to