summaryrefslogtreecommitdiff
path: root/hw
diff options
context:
space:
mode:
authorLouis-Francis Ratté-Boulianne <lfrb@collabora.com>2017-08-30 00:45:41 -0400
committerJason Ekstrand <jason.ekstrand@intel.com>2017-09-05 12:40:14 -0700
commit19531d012c7208dfbe34cb9d6248133af50bdcb7 (patch)
tree7d03b4ca44f8fc947a9e09ff1b6003f5ce550884 /hw
parent1e172954a26143523b1741d301b69ea749592d37 (diff)
modesetting: Get supported formats/modifiers for scanout
Retrieve IN_FORMATS property from the plane. It gives the allowed formats and modifiers for BO allocation. Signed-off-by: Louis-Francis Ratté-Boulianne <lfrb@collabora.com>
Diffstat (limited to 'hw')
-rw-r--r--hw/xfree86/drivers/modesetting/drmmode_display.c114
-rw-r--r--hw/xfree86/drivers/modesetting/drmmode_display.h9
2 files changed, 119 insertions, 4 deletions
diff --git a/hw/xfree86/drivers/modesetting/drmmode_display.c b/hw/xfree86/drivers/modesetting/drmmode_display.c
index 8aba32d56..95005f4de 100644
--- a/hw/xfree86/drivers/modesetting/drmmode_display.c
+++ b/hw/xfree86/drivers/modesetting/drmmode_display.c
@@ -56,6 +56,23 @@ static Bool drmmode_xf86crtc_resize(ScrnInfoPtr scrn, int width, int height);
static PixmapPtr drmmode_create_pixmap_header(ScreenPtr pScreen, int width, int height,
int depth, int bitsPerPixel, int devKind,
void *pPixData);
+
+#ifdef GLAMOR_HAS_DRM_MODIFIERS
+
+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
+
static Bool
drmmode_zaphod_string_matches(ScrnInfoPtr scrn, const char *s, char *output_name)
{
@@ -1540,15 +1557,76 @@ is_plane_assigned(ScrnInfoPtr scrn, int plane_id)
return FALSE;
}
+#ifdef GLAMOR_HAS_DRM_MODIFIERS
+/**
+ * Populates the formats array, and the modifiers of each format for a drm_plane.
+ */
+static Bool
+populate_format_modifiers(xf86CrtcPtr crtc, const drmModePlane *kplane,
+ uint32_t blob_id)
+{
+ drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
+ drmmode_ptr drmmode = drmmode_crtc->drmmode;
+ 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(drmmode->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(drmmode_crtc->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;
+ uint64_t *tmp;
+
+ 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;
+
+ count_modifiers++;
+ tmp = realloc(modifiers, count_modifiers * sizeof(modifiers[0]));
+ if (!tmp) {
+ free(modifiers);
+ drmModeFreePropertyBlob(blob);
+ return FALSE;
+ }
+ modifiers = tmp;
+ modifiers[count_modifiers - 1] = mod->modifier;
+ }
+
+ drmmode_crtc->formats[i].format = blob_formats[i];
+ drmmode_crtc->formats[i].modifiers = modifiers;
+ drmmode_crtc->formats[i].count_modifiers = count_modifiers;
+ }
+
+ drmModeFreePropertyBlob(blob);
+
+ return TRUE;
+}
+#endif
+
static void
drmmode_crtc_create_planes(xf86CrtcPtr crtc, int num)
{
drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
drmmode_ptr drmmode = drmmode_crtc->drmmode;
drmModePlaneRes *kplane_res;
- drmModePlane *kplane;
+ drmModePlane *kplane, *best_kplane = NULL;
drmModeObjectProperties *props;
- uint32_t i, type;
+ uint32_t i, type, blob_id;
int current_crtc, best_plane = 0;
static drmmode_prop_enum_info_rec plane_type_enums[] = {
@@ -1570,6 +1648,7 @@ drmmode_crtc_create_planes(xf86CrtcPtr crtc, int num)
},
[DRMMODE_PLANE_FB_ID] = { .name = "FB_ID", },
[DRMMODE_PLANE_CRTC_ID] = { .name = "CRTC_ID", },
+ [DRMMODE_PLANE_IN_FORMATS] = { .name = "IN_FORMATS", },
[DRMMODE_PLANE_SRC_X] = { .name = "SRC_X", },
[DRMMODE_PLANE_SRC_Y] = { .name = "SRC_Y", },
};
@@ -1602,13 +1681,13 @@ drmmode_crtc_create_planes(xf86CrtcPtr crtc, int num)
}
plane_id = kplane->plane_id;
- drmModeFreePlane(kplane);
props = drmModeObjectGetProperties(drmmode->fd, plane_id,
DRM_MODE_OBJECT_PLANE);
if (!props) {
xf86DrvMsg(drmmode->scrn->scrnIndex, X_ERROR,
"couldn't get plane properties\n");
+ drmModeFreePlane(kplane);
continue;
}
@@ -1618,6 +1697,7 @@ drmmode_crtc_create_planes(xf86CrtcPtr crtc, int num)
type = drmmode_prop_get_value(&tmp_props[DRMMODE_PLANE_TYPE],
props, DRMMODE_PLANE_TYPE__COUNT);
if (type != DRMMODE_PLANE_TYPE_PRIMARY) {
+ drmModeFreePlane(kplane);
drmModeFreeObjectProperties(props);
continue;
}
@@ -1626,9 +1706,14 @@ drmmode_crtc_create_planes(xf86CrtcPtr crtc, int num)
current_crtc = drmmode_prop_get_value(&tmp_props[DRMMODE_PLANE_CRTC_ID],
props, 0);
if (current_crtc == drmmode_crtc->mode_crtc->crtc_id) {
- if (best_plane)
+ if (best_plane) {
+ drmModeFreePlane(best_kplane);
drmmode_prop_info_free(drmmode_crtc->props_plane, DRMMODE_PLANE__COUNT);
+ }
best_plane = plane_id;
+ best_kplane = kplane;
+ blob_id = drmmode_prop_get_value(&tmp_props[DRMMODE_PLANE_IN_FORMATS],
+ props, 0);
drmmode_prop_info_copy(drmmode_crtc->props_plane, tmp_props,
DRMMODE_PLANE__COUNT, 1);
drmModeFreeObjectProperties(props);
@@ -1637,14 +1722,35 @@ drmmode_crtc_create_planes(xf86CrtcPtr crtc, int num)
if (!best_plane) {
best_plane = plane_id;
+ best_kplane = kplane;
+ blob_id = drmmode_prop_get_value(&tmp_props[DRMMODE_PLANE_IN_FORMATS],
+ props, 0);
drmmode_prop_info_copy(drmmode_crtc->props_plane, tmp_props,
DRMMODE_PLANE__COUNT, 1);
+ } else {
+ drmModeFreePlane(kplane);
}
drmModeFreeObjectProperties(props);
}
drmmode_crtc->plane_id = best_plane;
+ if (best_kplane) {
+ drmmode_crtc->count_formats = best_kplane->count_formats;
+ drmmode_crtc->formats = calloc(sizeof(drmmode_format_rec),
+ best_kplane->count_formats);
+#ifdef GLAMOR_HAS_DRM_MODIFIERS
+ if (blob_id) {
+ populate_format_modifiers(crtc, best_kplane, blob_id);
+ }
+ else
+#endif
+ {
+ for (i = 0; i < best_kplane->count_formats; i++)
+ drmmode_crtc->formats[i].format = best_kplane->formats[i];
+ }
+ drmModeFreePlane(best_kplane);
+ }
drmmode_prop_info_free(tmp_props, DRMMODE_PLANE__COUNT);
drmModeFreePlaneResources(kplane_res);
diff --git a/hw/xfree86/drivers/modesetting/drmmode_display.h b/hw/xfree86/drivers/modesetting/drmmode_display.h
index 3eea0a8d4..24d6b44cb 100644
--- a/hw/xfree86/drivers/modesetting/drmmode_display.h
+++ b/hw/xfree86/drivers/modesetting/drmmode_display.h
@@ -39,6 +39,7 @@ struct gbm_device;
enum drmmode_plane_property {
DRMMODE_PLANE_TYPE = 0,
DRMMODE_PLANE_FB_ID,
+ DRMMODE_PLANE_IN_FORMATS,
DRMMODE_PLANE_CRTC_ID,
DRMMODE_PLANE_SRC_X,
DRMMODE_PLANE_SRC_Y,
@@ -137,6 +138,12 @@ typedef struct {
} drmmode_mode_rec, *drmmode_mode_ptr;
typedef struct {
+ uint32_t format;
+ uint32_t count_modifiers;
+ uint64_t *modifiers;
+} drmmode_format_rec, *drmmode_format_ptr;
+
+typedef struct {
drmmode_ptr drmmode;
drmModeCrtcPtr mode_crtc;
uint32_t vblank_pipe;
@@ -149,6 +156,8 @@ typedef struct {
drmmode_prop_info_rec props_plane[DRMMODE_PLANE__COUNT];
uint32_t plane_id;
drmmode_mode_ptr current_mode;
+ uint32_t count_formats;
+ drmmode_format_rec *formats;
drmmode_bo rotate_bo;
unsigned rotate_fb_id;