123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399 |
- From dbf265558ceb9688f5ffd626ab8969bd836ca60f Mon Sep 17 00:00:00 2001
- From: Luigi Santivetti <luigi.santivetti@imgtec.com>
- Date: Thu, 26 Sep 2019 13:32:15 +0100
- Subject: [PATCH] egl/null: add support for DRM image format modifiers
- This change introduces support for image modifiers to platform_null. In
- order for it to create an image with modifiers, it relies on libdrm to
- iterate all formats with associated modifiers supported by the display
- for the primary drm plane in use.
- drmModeFormatModifierBlobIterNext() is added to the DRM api in a different
- change and it is not upstream at present.
- Internal notes:
- [1] IN_FORMATS blobs are available since kernel 4.14:
- - db1689aa61bd1efb5ce9b896e7aa860a85b7f1b6
- - https://patchwork.freedesktop.org/patch/168543
- [2] the dri image->base.version threshold is 14.
- - Unlike for platform_wayland, where no details were found regarding
- why it's using 15
- - dri_interface.h makes createImageWithModifiers available since
- version 14
- - dri/gbm_dri.c as an example checks for minimum version 14.
- Change-Id: I0f7b030f6e1943690692674bf18daabfc153208a
- Signed-off-by: Luigi Santivetti <luigi.santivetti@imgtec.com>
- ---
- meson.build | 5 +
- src/egl/drivers/dri2/egl_dri2.h | 3 +
- src/egl/drivers/dri2/platform_null.c | 221 +++++++++++++++++++++++----
- 3 files changed, 203 insertions(+), 26 deletions(-)
- diff --git a/meson.build b/meson.build
- index 21d93d3..ca89b8a 100644
- --- a/meson.build
- +++ b/meson.build
- @@ -1581,6 +1581,11 @@ if with_gallium_etnaviv
- _drm_ver = '2.4.89'
- endif
-
- +# platform_null relies on DRM format-modifier iterators available since 2.4.108
- +if with_platform_null
- + _drm_ver = '2.4.108'
- +endif
- +
- # Loop over the enables versions and get the highest libdrm requirement for all
- # active drivers.
- _drm_blame = ''
- diff --git a/src/egl/drivers/dri2/egl_dri2.h b/src/egl/drivers/dri2/egl_dri2.h
- index eb6e455..32ad720 100644
- --- a/src/egl/drivers/dri2/egl_dri2.h
- +++ b/src/egl/drivers/dri2/egl_dri2.h
- @@ -117,6 +117,8 @@ struct display_output {
- uint32_t mode_blob_id;
- unsigned formats;
- drmModeAtomicReq *atomic_state;
- + uint32_t in_formats_id;
- + struct u_vector modifiers;
- };
- #endif
-
- @@ -280,6 +282,7 @@ struct dri2_egl_display
-
- #ifdef HAVE_NULL_PLATFORM
- bool atomic_enabled;
- + bool in_formats_enabled;
- struct display_output output;
- #endif
-
- diff --git a/src/egl/drivers/dri2/platform_null.c b/src/egl/drivers/dri2/platform_null.c
- index d36dc0c..2c79199 100644
- --- a/src/egl/drivers/dri2/platform_null.c
- +++ b/src/egl/drivers/dri2/platform_null.c
- @@ -40,6 +40,7 @@
- #include <sys/types.h>
- #include <sys/stat.h>
- #include <unistd.h>
- +#include <util/u_vector.h>
- #include <xf86drm.h>
-
- #include "egl_dri2.h"
- @@ -156,6 +157,18 @@ format_idx_get_from_drm_format(uint32_t drm_format)
- return -1;
- }
-
- +static inline uint32_t
- +blob_id_from_property_value(uint64_t prop_value)
- +{
- + /* The KMS properties documetation, 01.org/linuxgraphics, says:
- + *
- + * For all property types except blob properties the value is a 64-bit
- + * unsigned integer.
- + */
- + assert(!(prop_value >> 32));
- + return (uint32_t) prop_value;
- +}
- +
- static int
- atomic_state_add_object_properties(drmModeAtomicReq *atomic_state,
- const struct object_property *props,
- @@ -645,7 +658,66 @@ drm_event_process(int fd)
- }
-
- static bool
- -display_output_init(int fd, struct display_output *output, bool use_atomic)
- +plane_init_in_formats(int fd, drmModePlane *plane, struct u_vector *modifiers,
- + uint32_t *in_formats_id_out, unsigned *formats_out)
- +{
- + uint32_t blob_id, prev_fmt = DRM_FORMAT_INVALID, count_formats = 0;
- + drmModeFormatModifierIterator drm_iter = {0};
- + drmModePropertyBlobRes *blob;
- + uint64_t prop_value;
- + int idx, err;
- +
- + assert(plane && in_formats_id_out && formats_out);
- +
- + err = !object_property_value_for_name(fd, plane->plane_id,
- + DRM_MODE_OBJECT_PLANE,
- + "IN_FORMATS", &prop_value);
- + if (err)
- + return false;
- +
- + blob_id = blob_id_from_property_value(prop_value);
- + blob = drmModeGetPropertyBlob(fd, blob_id);
- +
- + while (drmModeFormatModifierBlobIterNext(blob, &drm_iter)) {
- + if (drm_iter.fmt != prev_fmt) {
- + prev_fmt = drm_iter.fmt;
- + count_formats++;
- +
- + idx = format_idx_get_from_drm_format(drm_iter.fmt);
- + if (idx < 0)
- + continue;
- +
- + *formats_out |= (1 << idx);
- + }
- + }
- +
- + drmModeFreePropertyBlob(blob);
- +
- + if (!count_formats) {
- + /* None of the formats in the IN_FORMATS blob has associated modifiers */
- + _eglLog(_EGL_WARNING, "no format-modifiers found in IN_FORMATS");
- + return false;
- + }
- +
- + if (plane->count_formats != count_formats)
- + /* Only some of the formats in the IN_FORMATS blob have associated modifiers,
- + * try to use this subset.
- + */
- + _eglLog(_EGL_WARNING, "discarding formats without modifiers");
- +
- + /* Allocate space for modifiers, if ENOMEM fallback to plane formats */
- + if (!u_vector_init(modifiers, sizeof(uint64_t), 64)) {
- + _eglLog(_EGL_WARNING, "failed to allocate modifiers");
- + return false;
- + }
- +
- + *in_formats_id_out = blob_id;
- + return true;
- +}
- +
- +static bool
- +display_output_init(int fd, struct display_output *output, bool use_atomic,
- + bool prefer_in_formats, bool *in_formats_enabled_out)
- {
- drmModeRes *resources;
- drmModeConnector *connector;
- @@ -674,16 +746,34 @@ display_output_init(int fd, struct display_output *output, bool use_atomic)
- goto err_free_plane;
- output->mode = connector->modes[mode_idx];
-
- - /* Record the display supported formats */
- - for (unsigned i = 0; i < plane->count_formats; i++) {
- - int format_idx;
- + assert(in_formats_enabled_out && !(*in_formats_enabled_out));
-
- - format_idx = format_idx_get_from_drm_format(plane->formats[i]);
- - if (format_idx == -1)
- - continue;
- + /* Track display supported formats. Look them up from IN_FORMATS blobs
- + * if they are available, otherwise use plane formats.
- + */
- + if (prefer_in_formats)
- + *in_formats_enabled_out = plane_init_in_formats(fd, plane,
- + &output->modifiers,
- + &output->in_formats_id,
- + &output->formats);
-
- - output->formats |= (1 << format_idx);
- + if (!*in_formats_enabled_out) {
- + _eglLog(_EGL_WARNING, "fallback to plane formats");
- +
- + for (unsigned i = 0; i < plane->count_formats; i++) {
- + int format_idx;
- +
- + format_idx = format_idx_get_from_drm_format(plane->formats[i]);
- + if (format_idx == -1)
- + continue;
- +
- + output->formats |= (1 << format_idx);
- + }
- }
- +
- + /* At this point we can only shut down if the look up failed and
- + * it is safe to pass NULL to drmModeFreeFormats().
- + */
- if (!output->formats)
- goto err_free_plane;
-
- @@ -983,10 +1073,12 @@ static bool
- add_fb_for_dri_image(struct dri2_egl_display *dri2_dpy, __DRIimage *image,
- uint32_t *fb_id_out)
- {
- + uint64_t modifiers[4] = {0};
- uint32_t handles[4] = {0};
- uint32_t pitches[4] = {0};
- uint32_t offsets[4] = {0};
- - int handle, stride, width, height, format;
- + uint32_t flags = 0;
- + int handle, stride, width, height, format, l_mod, h_mod;
- int format_idx;
-
- dri2_dpy->image->queryImage(image, __DRI_IMAGE_ATTRIB_HANDLE, &handle);
- @@ -1001,9 +1093,47 @@ add_fb_for_dri_image(struct dri2_egl_display *dri2_dpy, __DRIimage *image,
- format_idx = format_idx_get_from_dri_image_format(format);
- assert(format_idx != -1);
-
- - return !drmModeAddFB2(dri2_dpy->fd, width, height,
- - dri2_null_formats[format_idx].drm_format,
- - handles, pitches, offsets, fb_id_out, 0);
- + if (dri2_dpy->in_formats_enabled) {
- + dri2_dpy->image->queryImage(image, __DRI_IMAGE_ATTRIB_MODIFIER_UPPER, &h_mod);
- + dri2_dpy->image->queryImage(image, __DRI_IMAGE_ATTRIB_MODIFIER_LOWER, &l_mod);
- +
- + modifiers[0] = combine_u32_into_u64((uint32_t) h_mod, (uint32_t) l_mod);
- + flags |= DRM_MODE_FB_MODIFIERS;
- + }
- +
- + return !drmModeAddFB2WithModifiers(dri2_dpy->fd, width, height,
- + dri2_null_formats[format_idx].drm_format,
- + handles, pitches, offsets, modifiers,
- + fb_id_out, flags);
- +}
- +
- +static __DRIimage *
- +create_image(struct dri2_egl_surface *dri2_surf, uint32_t flags)
- +{
- + struct dri2_egl_display *dri2_dpy =
- + dri2_egl_display(dri2_surf->base.Resource.Display);
- + uint32_t count_modifiers;
- + uint64_t *modifiers;
- +
- + if (dri2_dpy->in_formats_enabled) {
- + count_modifiers = u_vector_length(&dri2_dpy->output.modifiers);
- + modifiers = u_vector_tail(&dri2_dpy->output.modifiers);
- +
- + return dri2_dpy->image->createImageWithModifiers(dri2_dpy->dri_screen,
- + dri2_surf->base.Width,
- + dri2_surf->base.Height,
- + dri2_surf->format,
- + modifiers,
- + count_modifiers,
- + NULL);
- + }
- +
- + return dri2_dpy->image->createImage(dri2_dpy->dri_screen,
- + dri2_surf->base.Width,
- + dri2_surf->base.Height,
- + dri2_surf->format,
- + flags,
- + NULL);
- }
-
- static bool
- @@ -1016,12 +1146,7 @@ get_front_bo(struct dri2_egl_surface *dri2_surf)
- if (dri2_surf->base.Type == EGL_WINDOW_BIT)
- use |= __DRI_IMAGE_USE_SCANOUT;
-
- - dri2_surf->front = dri2_dpy->image->createImage(dri2_dpy->dri_screen,
- - dri2_surf->base.Width,
- - dri2_surf->base.Height,
- - dri2_surf->format,
- - use,
- - NULL);
- + dri2_surf->front = create_image(dri2_surf, use);
- if (!dri2_surf->front)
- return false;
-
- @@ -1058,13 +1183,8 @@ get_back_bo(struct dri2_egl_surface *dri2_surf)
- }
-
- if (!dri2_surf->back->dri_image) {
- - dri2_surf->back->dri_image =
- - dri2_dpy->image->createImage(dri2_dpy->dri_screen,
- - dri2_surf->base.Width,
- - dri2_surf->base.Height,
- - dri2_surf->format,
- - __DRI_IMAGE_USE_SCANOUT,
- - NULL);
- + dri2_surf->back->dri_image = create_image(dri2_surf,
- + __DRI_IMAGE_USE_SCANOUT);
- if (!dri2_surf->back->dri_image)
- goto err_unlock;
- }
- @@ -1094,6 +1214,30 @@ static void surface_swap_queue_init(struct dri2_egl_surface *dri2_surf)
- swap_queue[i].kms_in_fence_fd = -1;
- }
-
- +static bool
- +in_formats_get_modifiers(const int fd, const uint32_t in_formats_id,
- + const int drm_format, struct u_vector *modifiers)
- +{
- + drmModeFormatModifierIterator drm_iter = {0};
- + drmModePropertyBlobRes *blob;
- + uint64_t *mod = NULL;
- +
- + blob = drmModeGetPropertyBlob(fd, in_formats_id);
- +
- + while (drmModeFormatModifierBlobIterNext(blob, &drm_iter)) {
- + if (drm_iter.fmt == drm_format) {
- + assert(drm_iter.mod != DRM_FORMAT_MOD_INVALID);
- +
- + mod = u_vector_add(modifiers);
- + *mod = drm_iter.mod;
- + }
- + }
- +
- + drmModeFreePropertyBlob(blob);
- +
- + return mod != NULL;
- +}
- +
- static _EGLSurface *
- create_surface(_EGLDisplay *disp, _EGLConfig *config, EGLint type,
- const EGLint *attrib_list)
- @@ -1105,6 +1249,7 @@ create_surface(_EGLDisplay *disp, _EGLConfig *config, EGLint type,
- const __DRIconfig *dri_config;
- _EGLSurface *surf;
- int format_idx;
- + bool ret;
-
- dri2_surf = calloc(1, sizeof(*dri2_surf));
- if (!dri2_surf) {
- @@ -1137,6 +1282,15 @@ create_surface(_EGLDisplay *disp, _EGLConfig *config, EGLint type,
-
- dri2_surf->format = dri2_null_formats[format_idx].dri_image_format;
-
- + if (dri2_dpy->in_formats_enabled) {
- + ret = in_formats_get_modifiers(dri2_dpy->fd,
- + dri2_dpy->output.in_formats_id,
- + dri2_null_formats[format_idx].drm_format,
- + &dri2_dpy->output.modifiers);
- + if (!ret)
- + goto err_free_surface;
- + }
- +
- surface_swap_queue_init(dri2_surf);
-
- return surf;
- @@ -1536,6 +1690,8 @@ EGLBoolean
- dri2_initialize_null(_EGLDisplay *disp)
- {
- struct dri2_egl_display *dri2_dpy;
- + bool prefer_in_formats = false;
- + uint64_t value;
- int err;
-
- dri2_dpy = calloc(1, sizeof(*dri2_dpy));
- @@ -1589,8 +1745,19 @@ dri2_initialize_null(_EGLDisplay *disp)
- goto cleanup;
- }
-
- + err = drmGetCap(dri2_dpy->fd_dpy, DRM_CAP_ADDFB2_MODIFIERS, &value);
- + if (!err && value) {
- + /* in_formats could be supported by the platform, however not being
- + * actually enabled, i.e. in_formats init can still fail.
- + */
- + prefer_in_formats = dri2_dpy->image->base.version >= 14 &&
- + dri2_dpy->image->createImageWithModifiers;
- + }
- +
- if (!display_output_init(dri2_dpy->fd, &dri2_dpy->output,
- - dri2_dpy->atomic_enabled)) {
- + dri2_dpy->atomic_enabled,
- + prefer_in_formats,
- + &dri2_dpy->in_formats_enabled)) {
- _eglError(EGL_NOT_INITIALIZED, "failed to create output");
- goto cleanup;
- }
- @@ -1640,4 +1807,6 @@ dri2_teardown_null(struct dri2_egl_display *dri2_dpy)
- drmModeFreeProperty(dri2_dpy->output.connector_prop_res[i]);
- free(dri2_dpy->output.connector_prop_res);
- }
- +
- + u_vector_finish(&dri2_dpy->output.modifiers);
- }
|