diff --git a/libweston/backend-drm/drm-gbm.c b/libweston/backend-drm/drm-gbm.c index 30609e3e..4920b050 100644 --- a/libweston/backend-drm/drm-gbm.c +++ b/libweston/backend-drm/drm-gbm.c @@ -181,6 +181,10 @@ err: int drm_output_init_egl(struct drm_output *output, struct drm_backend *b) { + struct weston_drm_format *fmt; + const uint64_t *modifiers; + unsigned int num_modifiers; + uint32_t format[2] = { output->gbm_format, fallback_format_for(output->gbm_format), @@ -191,30 +195,26 @@ drm_output_init_egl(struct drm_output *output, struct drm_backend *b) }; struct weston_mode *mode = output->base.current_mode; struct drm_plane *plane = output->scanout_plane; - unsigned int i; assert(output->gbm_surface == NULL); - for (i = 0; i < plane->count_formats; i++) { - if (plane->formats[i].format == output->gbm_format) - break; - } - - if (i == plane->count_formats) { + fmt = weston_drm_format_array_find_format(&plane->formats, output->gbm_format); + if (!fmt) { weston_log("format 0x%x not supported by output %s\n", output->gbm_format, output->base.name); return -1; } #ifdef HAVE_GBM_MODIFIERS - if (plane->formats[i].count_modifiers > 0) { + modifiers = weston_drm_format_get_modifiers(fmt, &num_modifiers); + if (num_modifiers > 0) { output->gbm_surface = gbm_surface_create_with_modifiers(b->gbm, mode->width, mode->height, output->gbm_format, - plane->formats[i].modifiers, - plane->formats[i].count_modifiers); + modifiers, + num_modifiers); } /* If allocating with modifiers fails, try again without. This can diff --git a/libweston/backend-drm/drm-internal.h b/libweston/backend-drm/drm-internal.h index 74d6c7fb..3e20c781 100644 --- a/libweston/backend-drm/drm-internal.h +++ b/libweston/backend-drm/drm-internal.h @@ -435,7 +435,6 @@ struct drm_plane { uint32_t possible_crtcs; uint32_t plane_id; - uint32_t count_formats; struct drm_property_info props[WDRM_PLANE__COUNT]; @@ -447,11 +446,7 @@ struct drm_plane { struct wl_list link; - struct { - uint32_t format; - uint32_t count_modifiers; - uint64_t *modifiers; - } formats[]; + struct weston_drm_format_array formats; }; struct drm_connector { diff --git a/libweston/backend-drm/drm-virtual.c b/libweston/backend-drm/drm-virtual.c index 5ef5f8a7..d016d6ba 100644 --- a/libweston/backend-drm/drm-virtual.c +++ b/libweston/backend-drm/drm-virtual.c @@ -93,9 +93,10 @@ static struct drm_plane * drm_virtual_plane_create(struct drm_backend *b, struct drm_output *output) { struct drm_plane *plane; + struct weston_drm_format *fmt; + int ret; - /* num of formats is one */ - plane = zalloc(sizeof(*plane) + sizeof(plane->formats[0])); + plane = zalloc(sizeof(*plane)); if (!plane) { weston_log("%s: out of memory\n", __func__); return NULL; @@ -105,21 +106,28 @@ drm_virtual_plane_create(struct drm_backend *b, struct drm_output *output) plane->backend = b; plane->state_cur = drm_plane_state_alloc(NULL, plane); plane->state_cur->complete = true; - plane->formats[0].format = output->gbm_format; - plane->count_formats = 1; + + weston_drm_format_array_init(&plane->formats); + fmt = weston_drm_format_array_add_format(&plane->formats, output->gbm_format); + if (!fmt) + goto err; + if ((output->gbm_bo_flags & GBM_BO_USE_LINEAR) && b->fb_modifiers) { - uint64_t *modifiers = zalloc(sizeof *modifiers); - if (modifiers) { - *modifiers = DRM_FORMAT_MOD_LINEAR; - plane->formats[0].modifiers = modifiers; - plane->formats[0].count_modifiers = 1; - } + ret = weston_drm_format_add_modifier(fmt, DRM_FORMAT_MOD_LINEAR); + if (ret < 0) + goto err; } weston_plane_init(&plane->base, b->compositor, 0, 0); wl_list_insert(&b->plane_list, &plane->link); return plane; + +err: + drm_plane_state_free(plane->state_cur, true); + weston_drm_format_array_fini(&plane->formats); + free(plane); + return NULL; } /** @@ -133,8 +141,7 @@ drm_virtual_plane_destroy(struct drm_plane *plane) drm_plane_state_free(plane->state_cur, true); weston_plane_release(&plane->base); wl_list_remove(&plane->link); - if (plane->formats[0].modifiers) - free(plane->formats[0].modifiers); + weston_drm_format_array_fini(&plane->formats); free(plane); } diff --git a/libweston/backend-drm/drm.c b/libweston/backend-drm/drm.c index 82f6ee29..d3c178bf 100644 --- a/libweston/backend-drm/drm.c +++ b/libweston/backend-drm/drm.c @@ -760,20 +760,19 @@ drm_plane_create(struct drm_backend *b, const drmModePlane *kplane, struct drm_plane *plane; drmModeObjectProperties *props; uint64_t *zpos_range_values; - uint32_t num_formats = (kplane) ? kplane->count_formats : 1; - plane = zalloc(sizeof(*plane) + - (sizeof(plane->formats[0]) * num_formats)); + plane = zalloc(sizeof(*plane)); 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; + weston_drm_format_array_init(&plane->formats); + if (kplane) { plane->possible_crtcs = kplane->possible_crtcs; plane->plane_id = kplane->plane_id; @@ -814,11 +813,11 @@ drm_plane_create(struct drm_backend *b, const drmModePlane *kplane, else { plane->possible_crtcs = (1 << output->crtc->pipe); plane->plane_id = 0; - plane->count_formats = 1; - plane->formats[0].format = format; plane->type = type; plane->zpos_max = DRM_PLANE_ZPOS_INVALID_PLANE; plane->zpos_min = DRM_PLANE_ZPOS_INVALID_PLANE; + if (!weston_drm_format_array_add_format(&plane->formats, format)) + goto err; } if (plane->type == WDRM_PLANE_TYPE__COUNT) @@ -845,6 +844,7 @@ drm_plane_create(struct drm_backend *b, const drmModePlane *kplane, err_props: drm_property_info_free(plane->props, WDRM_PLANE__COUNT); err: + weston_drm_format_array_fini(&plane->formats); drm_plane_state_free(plane->state_cur, true); free(plane); return NULL; @@ -945,6 +945,7 @@ drm_plane_destroy(struct drm_plane *plane) drm_plane_state_free(plane->state_cur, true); drm_property_info_free(plane->props, WDRM_PLANE__COUNT); weston_plane_release(&plane->base); + weston_drm_format_array_fini(&plane->formats); wl_list_remove(&plane->link); free(plane); } diff --git a/libweston/backend-drm/kms.c b/libweston/backend-drm/kms.c index f0f85266..75730ffe 100644 --- a/libweston/backend-drm/kms.c +++ b/libweston/backend-drm/kms.c @@ -433,12 +433,14 @@ drm_plane_populate_formats(struct drm_plane *plane, const drmModePlane *kplane, const drmModeObjectProperties *props, const bool use_modifiers) { - unsigned i; - drmModePropertyBlobRes *blob; + unsigned i, j; + drmModePropertyBlobRes *blob = NULL; struct drm_format_modifier_blob *fmt_mod_blob; struct drm_format_modifier *blob_modifiers; uint32_t *blob_formats; uint32_t blob_id; + struct weston_drm_format *fmt; + int ret = 0; if (!use_modifiers) goto fallback; @@ -457,20 +459,15 @@ drm_plane_populate_formats(struct drm_plane *plane, const drmModePlane *kplane, blob_formats = formats_ptr(fmt_mod_blob); blob_modifiers = modifiers_ptr(fmt_mod_blob); - if (plane->count_formats != fmt_mod_blob->count_formats) { - weston_log("DRM backend: format count differs between " - "plane (%d) and IN_FORMATS (%d)\n", - plane->count_formats, - fmt_mod_blob->count_formats); - weston_log("This represents a kernel bug; Weston is " - "unable to continue.\n"); - abort(); - } + assert(kplane->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; - unsigned j; + fmt = weston_drm_format_array_add_format(&plane->formats, + blob_formats[i]); + if (!fmt) { + ret = -1; + goto out; + } for (j = 0; j < fmt_mod_blob->count_modifiers; j++) { struct drm_format_modifier *mod = &blob_modifiers[j]; @@ -480,38 +477,33 @@ drm_plane_populate_formats(struct drm_plane *plane, const drmModePlane *kplane, if (!(mod->formats & (1 << (i - mod->offset)))) continue; - modifiers = realloc(modifiers, - (count_modifiers + 1) * - sizeof(modifiers[0])); - assert(modifiers); - modifiers[count_modifiers++] = mod->modifier; + ret = weston_drm_format_add_modifier(fmt, mod->modifier); + if (ret < 0) + goto out; } - if (count_modifiers == 0) { - modifiers = malloc(sizeof(*modifiers)); - *modifiers = DRM_FORMAT_MOD_LINEAR; - count_modifiers = 1; + if (fmt->modifiers.size == 0) { + ret = weston_drm_format_add_modifier(fmt, DRM_FORMAT_MOD_LINEAR); + if (ret < 0) + goto out; } - - plane->formats[i].format = blob_formats[i]; - plane->formats[i].modifiers = modifiers; - plane->formats[i].count_modifiers = count_modifiers; } +out: drmModeFreePropertyBlob(blob); - - return 0; + return ret; fallback: /* No IN_FORMATS blob available, so just use the old. */ - assert(plane->count_formats == kplane->count_formats); for (i = 0; i < kplane->count_formats; i++) { - plane->formats[i].format = kplane->formats[i]; - plane->formats[i].modifiers = malloc(sizeof(uint64_t)); - plane->formats[i].modifiers[0] = DRM_FORMAT_MOD_LINEAR; - plane->formats[i].count_modifiers = 1; + fmt = weston_drm_format_array_add_format(&plane->formats, + kplane->formats[i]); + if (!fmt) + return -1; + ret = weston_drm_format_add_modifier(fmt, DRM_FORMAT_MOD_LINEAR); + if (ret < 0) + return -1; } - return 0; } diff --git a/libweston/backend-drm/state-propose.c b/libweston/backend-drm/state-propose.c index 5eda8648..cafc0d9e 100644 --- a/libweston/backend-drm/state-propose.c +++ b/libweston/backend-drm/state-propose.c @@ -129,25 +129,19 @@ drm_output_plane_has_valid_format(struct drm_plane *plane, struct drm_fb *fb) { struct drm_backend *b = plane->backend; - unsigned int i; + struct weston_drm_format *fmt; if (!fb) return false; /* Check whether the format is supported */ - for (i = 0; i < plane->count_formats; i++) { - unsigned int j; - - if (plane->formats[i].format != fb->format->format) - continue; - + fmt = weston_drm_format_array_find_format(&plane->formats, + fb->format->format); + if (fmt) { if (fb->modifier == DRM_FORMAT_MOD_INVALID) return true; - - for (j = 0; j < plane->formats[i].count_modifiers; j++) { - if (plane->formats[i].modifiers[j] == fb->modifier) - return true; - } + if (weston_drm_format_has_modifier(fmt, fb->modifier)) + return true; } drm_debug(b, "\t\t\t\t[%s] not placing view on %s: "