[Mesa-dev] [PATCH kmscube 3/4] Automatically select modifiers

Thierry Reding thierry.reding at gmail.com
Thu Apr 5 13:44:53 UTC 2018


From: Thierry Reding <treding at nvidia.com>

If available, use the formats/modifiers blob from a DRM/KMS device to
automatically detect which modifiers to use. In the absence of the blob,
leave it up to the implementation to choose an appropriate format.

Based on work by Lucas Stach <l.stach at pengutronix.de>.

Signed-off-by: Thierry Reding <treding at nvidia.com>
---
 common.c     | 10 +++++----
 common.h     |  2 +-
 drm-atomic.c | 70 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
 drm-common.h |  5 ++++-
 kmscube.c    |  8 +++++--
 5 files changed, 86 insertions(+), 9 deletions(-)

diff --git a/common.c b/common.c
index 3dcd9bd3d8f4..a886962ea7b1 100644
--- a/common.c
+++ b/common.c
@@ -41,17 +41,19 @@ gbm_surface_create_with_modifiers(struct gbm_device *gbm,
                                   const uint64_t *modifiers,
                                   const unsigned int count);
 
-const struct gbm * init_gbm(const struct drm *drm, uint64_t modifier)
+const struct gbm * init_gbm(const struct drm *drm)
 {
 	gbm.dev = gbm_create_device(drm->fd);
 	gbm.format = GBM_FORMAT_XRGB8888;
 
-	if (gbm_surface_create_with_modifiers) {
+	if (gbm_surface_create_with_modifiers && drm->num_modifiers > 0) {
 		gbm.surface = gbm_surface_create_with_modifiers(gbm.dev,
 				drm->mode->hdisplay, drm->mode->vdisplay,
-				gbm.format, &modifier, 1);
+				gbm.format, drm->modifiers,
+				drm->num_modifiers);
 	} else {
-		if (modifier != DRM_FORMAT_MOD_LINEAR) {
+		if (drm->num_modifiers > 0 &&
+		    drm->modifiers[0] != DRM_FORMAT_MOD_LINEAR) {
 			fprintf(stderr, "Modifiers requested but support isn't available\n");
 			return NULL;
 		}
diff --git a/common.h b/common.h
index 8ff1ed3a6aa3..bed316786557 100644
--- a/common.h
+++ b/common.h
@@ -84,7 +84,7 @@ struct gbm {
 };
 
 struct drm;
-const struct gbm *init_gbm(const struct drm *drm, uint64_t modifier);
+const struct gbm *init_gbm(const struct drm *drm);
 
 struct egl {
 	EGLDisplay display;
diff --git a/drm-atomic.c b/drm-atomic.c
index 99ac33d6a686..a68f036a9aab 100644
--- a/drm-atomic.c
+++ b/drm-atomic.c
@@ -337,7 +337,66 @@ static int get_plane_id(void)
 	return ret;
 }
 
-const struct drm * init_drm_atomic(const char *device)
+static unsigned int
+get_modifiers(drmModePropertyBlobPtr blob, struct drm_format_modifier **modsp)
+{
+	struct drm_format_modifier_blob *data = blob->data;
+
+	*modsp = blob->data + data->modifiers_offset;
+
+	return data->count_modifiers;
+}
+
+static int
+drm_atomic_get_modifiers(struct drm *drm)
+{
+	unsigned int i, j, format_index = 0;
+
+	for (i = 0; i < drm->plane->plane->count_formats; i++) {
+		if (drm->plane->plane->formats[i] == DRM_FORMAT_XRGB8888)
+			format_index = i;
+	}
+
+	for (i = 0; i < drm->plane->props->count_props; i++) {
+		if (!strcmp(drm->plane->props_info[i]->name, "IN_FORMATS")) {
+			struct drm_format_modifier *mods;
+			drmModePropertyBlobPtr blob;
+			unsigned int count;
+
+			blob = drmModeGetPropertyBlob(drm->fd,
+						      drm->plane->props->prop_values[i]);
+			if (!blob) {
+				printf("failed to get blob for property %s\n",
+				       drm->plane->props_info[i]->name);
+				return -ENOMEM;
+			}
+
+			count = get_modifiers(blob, &mods);
+
+			for (j = 0; j < count; j++) {
+				if (mods[j].formats & (1ULL << format_index))
+					drm->num_modifiers++;
+			}
+
+			drm->modifiers = calloc(drm->num_modifiers,
+					        sizeof(uint64_t));
+			if (!drm->modifiers) {
+				printf("failed to allocate modifiers\n");
+				return -ENOMEM;
+			}
+
+			for (j = 0; j < count; j++) {
+				if (mods[j].formats & (1ULL << format_index))
+					drm->modifiers[j] = mods[j].modifier;
+			}
+		}
+	}
+
+	return 0;
+}
+
+const struct drm *init_drm_atomic(const char *device, uint64_t *modifiers,
+				  unsigned int num_modifiers)
 {
 	uint32_t plane_id;
 	int ret;
@@ -346,6 +405,9 @@ const struct drm * init_drm_atomic(const char *device)
 	if (ret)
 		return NULL;
 
+	drm.num_modifiers = num_modifiers;
+	drm.modifiers = modifiers;
+
 	ret = drmSetClientCap(drm.fd, DRM_CLIENT_CAP_ATOMIC, 1);
 	if (ret) {
 		printf("no atomic modesetting support: %s\n", strerror(errno));
@@ -402,6 +464,12 @@ const struct drm * init_drm_atomic(const char *device)
 	get_properties(crtc, CRTC, drm.crtc_id);
 	get_properties(connector, CONNECTOR, drm.connector_id);
 
+	if (num_modifiers == 0) {
+		ret = drm_atomic_get_modifiers(&drm);
+		if (ret < 0)
+			return NULL;
+	}
+
 	drm.run = atomic_run;
 
 	return &drm;
diff --git a/drm-common.h b/drm-common.h
index 53af2cfee4a9..2ab753a3db2a 100644
--- a/drm-common.h
+++ b/drm-common.h
@@ -58,6 +58,8 @@ struct drm {
 	int crtc_index;
 	int kms_in_fence_fd;
 	int kms_out_fence_fd;
+	unsigned int num_modifiers;
+	uint64_t *modifiers;
 
 	drmModeModeInfo *mode;
 	uint32_t crtc_id;
@@ -75,6 +77,7 @@ struct drm_fb * drm_fb_get_from_bo(struct gbm_bo *bo);
 
 int init_drm(struct drm *drm, const char *device);
 const struct drm * init_drm_legacy(const char *device);
-const struct drm * init_drm_atomic(const char *device);
+const struct drm * init_drm_atomic(const char *device, uint64_t *modifiers,
+				   unsigned int num_modifiers);
 
 #endif /* _DRM_COMMON_H */
diff --git a/kmscube.c b/kmscube.c
index b05e57df7faf..1b3245b2b9cd 100644
--- a/kmscube.c
+++ b/kmscube.c
@@ -77,6 +77,8 @@ int main(int argc, char *argv[])
 	const char *video = NULL;
 	enum mode mode = SMOOTH;
 	uint64_t modifier = DRM_FORMAT_MOD_LINEAR;
+	unsigned int num_modifiers = 0;
+	uint64_t *modifiers = NULL;
 	int atomic = 0;
 	int opt;
 
@@ -110,6 +112,8 @@ int main(int argc, char *argv[])
 			break;
 		case 'm':
 			modifier = strtoull(optarg, NULL, 0);
+			modifiers = &modifier;
+			num_modifiers = 1;
 			break;
 		case 'V':
 			mode = VIDEO;
@@ -122,7 +126,7 @@ int main(int argc, char *argv[])
 	}
 
 	if (atomic)
-		drm = init_drm_atomic(device);
+		drm = init_drm_atomic(device, modifiers, num_modifiers);
 	else
 		drm = init_drm_legacy(device);
 	if (!drm) {
@@ -130,7 +134,7 @@ int main(int argc, char *argv[])
 		return -1;
 	}
 
-	gbm = init_gbm(drm, modifier);
+	gbm = init_gbm(drm);
 	if (!gbm) {
 		printf("failed to initialize GBM\n");
 		return -1;
-- 
2.16.3



More information about the mesa-dev mailing list