crtc/kms: Use MetaKmsPlane to check supported rotations and formats
Instead of manually retrieving supported transforms and formats from the primary plane of the CRTC, use the MetaKmsPlane abstraction to find the primary plane of the CRTC and check compatibility using the MetaKmsPlane API. This removes the last user of direct KMS API usage except for applying configuration. https://gitlab.gnome.org/GNOME/mutter/issues/548 https://gitlab.gnome.org/GNOME/mutter/merge_requests/525
This commit is contained in:
parent
aba689312f
commit
d84c7269b2
@ -29,6 +29,8 @@
|
||||
|
||||
#include "backends/meta-backend-private.h"
|
||||
#include "backends/native/meta-gpu-kms.h"
|
||||
#include "backends/native/meta-kms-device.h"
|
||||
#include "backends/native/meta-kms-plane.h"
|
||||
|
||||
/* added in libdrm 2.4.95 */
|
||||
#ifndef DRM_FORMAT_INVALID
|
||||
@ -41,17 +43,10 @@ typedef struct _MetaCrtcKms
|
||||
{
|
||||
MetaKmsCrtc *kms_crtc;
|
||||
|
||||
uint32_t primary_plane_id;
|
||||
uint32_t rotation_prop_id;
|
||||
uint32_t rotation_map[META_MONITOR_N_TRANSFORMS];
|
||||
uint32_t all_hw_transforms;
|
||||
|
||||
/*
|
||||
* primary plane's supported formats and maybe modifiers
|
||||
* key: GUINT_TO_POINTER (format)
|
||||
* value: owned GArray* (uint64_t modifier), or NULL
|
||||
*/
|
||||
GHashTable *formats_modifiers;
|
||||
MetaKmsPlane *primary_plane;
|
||||
} MetaCrtcKms;
|
||||
|
||||
/**
|
||||
@ -93,10 +88,11 @@ meta_crtc_kms_is_transform_handled (MetaCrtc *crtc,
|
||||
{
|
||||
MetaCrtcKms *crtc_kms = crtc->driver_private;
|
||||
|
||||
if ((1 << transform) & crtc_kms->all_hw_transforms)
|
||||
return TRUE;
|
||||
else
|
||||
if (!crtc_kms->primary_plane)
|
||||
return FALSE;
|
||||
|
||||
return meta_kms_plane_is_transform_handled (crtc_kms->primary_plane,
|
||||
transform);
|
||||
}
|
||||
|
||||
void
|
||||
@ -110,28 +106,18 @@ meta_crtc_kms_apply_transform (MetaCrtc *crtc)
|
||||
|
||||
kms_fd = meta_gpu_kms_get_fd (gpu_kms);
|
||||
|
||||
if (crtc_kms->all_hw_transforms & (1 << crtc->transform))
|
||||
hw_transform = crtc->transform;
|
||||
else
|
||||
hw_transform = crtc->transform;
|
||||
if (!meta_crtc_kms_is_transform_handled (crtc, hw_transform))
|
||||
hw_transform = META_MONITOR_TRANSFORM_NORMAL;
|
||||
|
||||
if (!meta_crtc_kms_is_transform_handled (crtc, META_MONITOR_TRANSFORM_NORMAL))
|
||||
if (!meta_crtc_kms_is_transform_handled (crtc, hw_transform))
|
||||
return;
|
||||
|
||||
if (drmModeObjectSetProperty (kms_fd,
|
||||
crtc_kms->primary_plane_id,
|
||||
meta_kms_plane_get_id (crtc_kms->primary_plane),
|
||||
DRM_MODE_OBJECT_PLANE,
|
||||
crtc_kms->rotation_prop_id,
|
||||
crtc_kms->rotation_map[hw_transform]) != 0)
|
||||
{
|
||||
g_warning ("Failed to apply DRM plane transform %d: %m", hw_transform);
|
||||
|
||||
/*
|
||||
* Blacklist this HW transform, we want to fallback to our
|
||||
* fallbacks in this case.
|
||||
*/
|
||||
crtc_kms->all_hw_transforms &= ~(1 << hw_transform);
|
||||
}
|
||||
g_warning ("Failed to apply DRM plane transform %d: %m", hw_transform);
|
||||
}
|
||||
|
||||
static int
|
||||
@ -194,8 +180,8 @@ meta_crtc_kms_get_modifiers (MetaCrtc *crtc,
|
||||
{
|
||||
MetaCrtcKms *crtc_kms = crtc->driver_private;
|
||||
|
||||
return g_hash_table_lookup (crtc_kms->formats_modifiers,
|
||||
GUINT_TO_POINTER (format));
|
||||
return meta_kms_plane_get_modifiers_for_format (crtc_kms->primary_plane,
|
||||
format);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -210,24 +196,8 @@ GArray *
|
||||
meta_crtc_kms_copy_drm_format_list (MetaCrtc *crtc)
|
||||
{
|
||||
MetaCrtcKms *crtc_kms = crtc->driver_private;
|
||||
GArray *formats;
|
||||
GHashTableIter it;
|
||||
gpointer key;
|
||||
unsigned int n_formats_modifiers;
|
||||
|
||||
n_formats_modifiers = g_hash_table_size (crtc_kms->formats_modifiers);
|
||||
formats = g_array_sized_new (FALSE,
|
||||
FALSE,
|
||||
sizeof (uint32_t),
|
||||
n_formats_modifiers);
|
||||
g_hash_table_iter_init (&it, crtc_kms->formats_modifiers);
|
||||
while (g_hash_table_iter_next (&it, &key, NULL))
|
||||
{
|
||||
uint32_t drm_format = GPOINTER_TO_UINT (key);
|
||||
g_array_append_val (formats, drm_format);
|
||||
}
|
||||
|
||||
return formats;
|
||||
return meta_kms_plane_copy_drm_format_list (crtc_kms->primary_plane);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -243,124 +213,8 @@ meta_crtc_kms_supports_format (MetaCrtc *crtc,
|
||||
{
|
||||
MetaCrtcKms *crtc_kms = crtc->driver_private;
|
||||
|
||||
return g_hash_table_lookup_extended (crtc_kms->formats_modifiers,
|
||||
GUINT_TO_POINTER (drm_format),
|
||||
NULL,
|
||||
NULL);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
static void
|
||||
free_modifier_array (GArray *array)
|
||||
{
|
||||
if (!array)
|
||||
return;
|
||||
|
||||
g_array_free (array, TRUE);
|
||||
}
|
||||
|
||||
/*
|
||||
* In case the DRM driver does not expose a format list for the
|
||||
* primary plane (does not support universal planes nor
|
||||
* IN_FORMATS property), hardcode something that is probably supported.
|
||||
*/
|
||||
static const uint32_t drm_default_formats[] =
|
||||
{
|
||||
DRM_FORMAT_XRGB8888 /* The format everything should always support by convention */,
|
||||
#if G_BYTE_ORDER == G_LITTLE_ENDIAN
|
||||
DRM_FORMAT_XBGR8888 /* OpenGL GL_RGBA, GL_UNSIGNED_BYTE format, hopefully supported */
|
||||
#endif
|
||||
};
|
||||
|
||||
static void
|
||||
set_formats_from_array (MetaCrtc *crtc,
|
||||
const uint32_t *formats,
|
||||
size_t n_formats)
|
||||
{
|
||||
MetaCrtcKms *crtc_kms = crtc->driver_private;
|
||||
size_t i;
|
||||
|
||||
for (i = 0; i < n_formats; i++)
|
||||
{
|
||||
g_hash_table_insert (crtc_kms->formats_modifiers,
|
||||
GUINT_TO_POINTER (formats[i]), NULL);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
parse_formats (MetaCrtc *crtc,
|
||||
int kms_fd,
|
||||
uint32_t blob_id)
|
||||
{
|
||||
MetaCrtcKms *crtc_kms = crtc->driver_private;
|
||||
drmModePropertyBlobPtr blob;
|
||||
struct drm_format_modifier_blob *blob_fmt;
|
||||
uint32_t *formats;
|
||||
struct drm_format_modifier *modifiers;
|
||||
unsigned int fmt_i, mod_i;
|
||||
|
||||
g_return_if_fail (g_hash_table_size (crtc_kms->formats_modifiers) == 0);
|
||||
|
||||
if (blob_id == 0)
|
||||
return;
|
||||
|
||||
blob = drmModeGetPropertyBlob (kms_fd, blob_id);
|
||||
if (!blob)
|
||||
return;
|
||||
|
||||
if (blob->length < sizeof (struct drm_format_modifier_blob))
|
||||
{
|
||||
drmModeFreePropertyBlob (blob);
|
||||
return;
|
||||
}
|
||||
|
||||
blob_fmt = blob->data;
|
||||
|
||||
formats = formats_ptr (blob_fmt);
|
||||
modifiers = modifiers_ptr (blob_fmt);
|
||||
|
||||
for (fmt_i = 0; fmt_i < blob_fmt->count_formats; fmt_i++)
|
||||
{
|
||||
GArray *mod_tmp = g_array_new (FALSE, FALSE, sizeof (uint64_t));
|
||||
|
||||
for (mod_i = 0; mod_i < blob_fmt->count_modifiers; mod_i++)
|
||||
{
|
||||
struct drm_format_modifier *modifier = &modifiers[mod_i];
|
||||
|
||||
/* The modifier advertisement blob is partitioned into groups of
|
||||
* 64 formats. */
|
||||
if (fmt_i < modifier->offset || fmt_i > modifier->offset + 63)
|
||||
continue;
|
||||
|
||||
if (!(modifier->formats & (1 << (fmt_i - modifier->offset))))
|
||||
continue;
|
||||
|
||||
g_array_append_val (mod_tmp, modifier->modifier);
|
||||
}
|
||||
|
||||
if (mod_tmp->len == 0)
|
||||
{
|
||||
free_modifier_array (mod_tmp);
|
||||
mod_tmp = NULL;
|
||||
}
|
||||
|
||||
g_hash_table_insert (crtc_kms->formats_modifiers,
|
||||
GUINT_TO_POINTER (formats[fmt_i]), mod_tmp);
|
||||
}
|
||||
|
||||
drmModeFreePropertyBlob (blob);
|
||||
return meta_kms_plane_is_format_supported (crtc_kms->primary_plane,
|
||||
drm_format);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -384,28 +238,10 @@ parse_transforms (MetaCrtc *crtc,
|
||||
transform = META_MONITOR_TRANSFORM_270;
|
||||
|
||||
if (transform != -1)
|
||||
{
|
||||
crtc_kms->all_hw_transforms |= 1 << transform;
|
||||
crtc_kms->rotation_map[transform] = 1 << prop->enums[i].value;
|
||||
}
|
||||
crtc_kms->rotation_map[transform] = 1 << prop->enums[i].value;
|
||||
}
|
||||
}
|
||||
|
||||
static gboolean
|
||||
is_primary_plane (MetaGpu *gpu,
|
||||
drmModeObjectPropertiesPtr props)
|
||||
{
|
||||
drmModePropertyPtr prop;
|
||||
int idx;
|
||||
|
||||
idx = find_property_index (gpu, props, "type", &prop);
|
||||
if (idx < 0)
|
||||
return FALSE;
|
||||
|
||||
drmModeFreeProperty (prop);
|
||||
return props->prop_values[idx] == DRM_PLANE_TYPE_PRIMARY;
|
||||
}
|
||||
|
||||
static void
|
||||
init_crtc_rotations (MetaCrtc *crtc,
|
||||
MetaGpu *gpu)
|
||||
@ -413,91 +249,35 @@ init_crtc_rotations (MetaCrtc *crtc,
|
||||
MetaCrtcKms *crtc_kms = crtc->driver_private;
|
||||
MetaGpuKms *gpu_kms = META_GPU_KMS (gpu);
|
||||
int kms_fd;
|
||||
drmModeObjectPropertiesPtr props;
|
||||
drmModePlaneRes *planes;
|
||||
uint32_t primary_plane_id;
|
||||
drmModePlane *drm_plane;
|
||||
unsigned int i;
|
||||
int crtc_idx;
|
||||
drmModeObjectPropertiesPtr props;
|
||||
drmModePropertyPtr prop;
|
||||
int rotation_idx;
|
||||
|
||||
kms_fd = meta_gpu_kms_get_fd (gpu_kms);
|
||||
primary_plane_id = meta_kms_plane_get_id (crtc_kms->primary_plane);
|
||||
drm_plane = drmModeGetPlane (kms_fd, primary_plane_id);
|
||||
props = drmModeObjectGetProperties (kms_fd,
|
||||
primary_plane_id,
|
||||
DRM_MODE_OBJECT_PLANE);
|
||||
|
||||
planes = drmModeGetPlaneResources (kms_fd);
|
||||
if (planes == NULL)
|
||||
return;
|
||||
|
||||
crtc_idx = meta_kms_crtc_get_idx (crtc_kms->kms_crtc);
|
||||
for (i = 0; i < planes->count_planes; i++)
|
||||
rotation_idx = find_property_index (gpu, props,
|
||||
"rotation", &prop);
|
||||
if (rotation_idx >= 0)
|
||||
{
|
||||
drmModePropertyPtr prop;
|
||||
|
||||
drm_plane = drmModeGetPlane (kms_fd, planes->planes[i]);
|
||||
|
||||
if (!drm_plane)
|
||||
continue;
|
||||
|
||||
if ((drm_plane->possible_crtcs & (1 << crtc_idx)))
|
||||
{
|
||||
props = drmModeObjectGetProperties (kms_fd,
|
||||
drm_plane->plane_id,
|
||||
DRM_MODE_OBJECT_PLANE);
|
||||
|
||||
if (props && is_primary_plane (gpu, props))
|
||||
{
|
||||
int rotation_idx, fmts_idx;
|
||||
|
||||
crtc_kms->primary_plane_id = drm_plane->plane_id;
|
||||
rotation_idx = find_property_index (gpu, props,
|
||||
"rotation", &prop);
|
||||
if (rotation_idx >= 0)
|
||||
{
|
||||
crtc_kms->rotation_prop_id = props->props[rotation_idx];
|
||||
parse_transforms (crtc, prop);
|
||||
drmModeFreeProperty (prop);
|
||||
}
|
||||
|
||||
fmts_idx = find_property_index (gpu, props,
|
||||
"IN_FORMATS", &prop);
|
||||
if (fmts_idx >= 0)
|
||||
{
|
||||
parse_formats (crtc, kms_fd, props->prop_values[fmts_idx]);
|
||||
drmModeFreeProperty (prop);
|
||||
}
|
||||
|
||||
/* fall back to universal plane formats without modifiers */
|
||||
if (g_hash_table_size (crtc_kms->formats_modifiers) == 0)
|
||||
{
|
||||
set_formats_from_array (crtc,
|
||||
drm_plane->formats,
|
||||
drm_plane->count_formats);
|
||||
}
|
||||
}
|
||||
|
||||
if (props)
|
||||
drmModeFreeObjectProperties (props);
|
||||
}
|
||||
|
||||
drmModeFreePlane (drm_plane);
|
||||
crtc_kms->rotation_prop_id = props->props[rotation_idx];
|
||||
parse_transforms (crtc, prop);
|
||||
drmModeFreeProperty (prop);
|
||||
}
|
||||
|
||||
crtc->all_transforms |= crtc_kms->all_hw_transforms;
|
||||
|
||||
drmModeFreePlaneResources (planes);
|
||||
|
||||
/* final formats fallback to something hardcoded */
|
||||
if (g_hash_table_size (crtc_kms->formats_modifiers) == 0)
|
||||
{
|
||||
set_formats_from_array (crtc,
|
||||
drm_default_formats,
|
||||
G_N_ELEMENTS (drm_default_formats));
|
||||
}
|
||||
drmModeFreeObjectProperties (props);
|
||||
drmModeFreePlane (drm_plane);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_crtc_destroy_notify (MetaCrtc *crtc)
|
||||
{
|
||||
MetaCrtcKms *crtc_kms = crtc->driver_private;
|
||||
|
||||
g_hash_table_destroy (crtc_kms->formats_modifiers);
|
||||
g_free (crtc->driver_private);
|
||||
}
|
||||
|
||||
@ -506,10 +286,15 @@ meta_create_kms_crtc (MetaGpuKms *gpu_kms,
|
||||
MetaKmsCrtc *kms_crtc)
|
||||
{
|
||||
MetaGpu *gpu = META_GPU (gpu_kms);
|
||||
MetaKmsDevice *kms_device;
|
||||
MetaCrtc *crtc;
|
||||
MetaCrtcKms *crtc_kms;
|
||||
MetaKmsPlane *primary_plane;
|
||||
const MetaKmsCrtcState *crtc_state;
|
||||
|
||||
kms_device = meta_gpu_kms_get_kms_device (gpu_kms);
|
||||
primary_plane = meta_kms_device_get_primary_plane_for (kms_device,
|
||||
kms_crtc);
|
||||
crtc_state = meta_kms_crtc_get_current_state (kms_crtc);
|
||||
|
||||
crtc = g_object_new (META_TYPE_CRTC, NULL);
|
||||
@ -538,12 +323,7 @@ meta_create_kms_crtc (MetaGpuKms *gpu_kms,
|
||||
|
||||
crtc_kms = g_new0 (MetaCrtcKms, 1);
|
||||
crtc_kms->kms_crtc = kms_crtc;
|
||||
|
||||
crtc_kms->formats_modifiers =
|
||||
g_hash_table_new_full (g_direct_hash,
|
||||
g_direct_equal,
|
||||
NULL,
|
||||
(GDestroyNotify) free_modifier_array);
|
||||
crtc_kms->primary_plane = primary_plane;
|
||||
|
||||
crtc->driver_private = crtc_kms;
|
||||
crtc->driver_notify = (GDestroyNotify) meta_crtc_destroy_notify;
|
||||
|
@ -381,6 +381,12 @@ meta_gpu_kms_wait_for_flip (MetaGpuKms *gpu_kms,
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
MetaKmsDevice *
|
||||
meta_gpu_kms_get_kms_device (MetaGpuKms *gpu_kms)
|
||||
{
|
||||
return gpu_kms->kms_device;
|
||||
}
|
||||
|
||||
int
|
||||
meta_gpu_kms_get_fd (MetaGpuKms *gpu_kms)
|
||||
{
|
||||
|
@ -64,6 +64,8 @@ gboolean meta_gpu_kms_flip_crtc (MetaGpuKms *gpu_kms,
|
||||
gboolean meta_gpu_kms_wait_for_flip (MetaGpuKms *gpu_kms,
|
||||
GError **error);
|
||||
|
||||
MetaKmsDevice * meta_gpu_kms_get_kms_device (MetaGpuKms *gpu_kms);
|
||||
|
||||
int meta_gpu_kms_get_fd (MetaGpuKms *gpu_kms);
|
||||
|
||||
uint32_t meta_gpu_kms_get_id (MetaGpuKms *gpu_kms);
|
||||
|
@ -25,6 +25,7 @@
|
||||
#include "backends/native/meta-backend-native.h"
|
||||
#include "backends/native/meta-kms-impl-device.h"
|
||||
#include "backends/native/meta-kms-impl.h"
|
||||
#include "backends/native/meta-kms-plane.h"
|
||||
#include "backends/native/meta-kms-private.h"
|
||||
|
||||
struct _MetaKmsDevice
|
||||
@ -81,6 +82,32 @@ meta_kms_device_get_crtcs (MetaKmsDevice *device)
|
||||
return device->crtcs;
|
||||
}
|
||||
|
||||
static GList *
|
||||
meta_kms_device_get_planes (MetaKmsDevice *device)
|
||||
{
|
||||
return device->planes;
|
||||
}
|
||||
|
||||
MetaKmsPlane *
|
||||
meta_kms_device_get_primary_plane_for (MetaKmsDevice *device,
|
||||
MetaKmsCrtc *crtc)
|
||||
{
|
||||
GList *l;
|
||||
|
||||
for (l = meta_kms_device_get_planes (device); l; l = l->next)
|
||||
{
|
||||
MetaKmsPlane *plane = l->data;
|
||||
|
||||
if (meta_kms_plane_get_plane_type (plane) != META_KMS_PLANE_TYPE_PRIMARY)
|
||||
continue;
|
||||
|
||||
if (meta_kms_plane_is_usable_with (plane, crtc))
|
||||
return plane;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
typedef struct _CreateImplDeviceData
|
||||
{
|
||||
MetaKmsDevice *device;
|
||||
|
@ -39,6 +39,9 @@ GList * meta_kms_device_get_connectors (MetaKmsDevice *device);
|
||||
|
||||
GList * meta_kms_device_get_crtcs (MetaKmsDevice *device);
|
||||
|
||||
MetaKmsPlane * meta_kms_device_get_primary_plane_for (MetaKmsDevice *device,
|
||||
MetaKmsCrtc *crtc);
|
||||
|
||||
MetaKmsDevice * meta_kms_device_new (MetaKms *kms,
|
||||
const char *path,
|
||||
MetaKmsDeviceFlag flags,
|
||||
|
@ -41,11 +41,24 @@ struct _MetaKmsPlane
|
||||
uint32_t rotation_map[META_MONITOR_N_TRANSFORMS];
|
||||
uint32_t all_hw_transforms;
|
||||
|
||||
/*
|
||||
* primary plane's supported formats and maybe modifiers
|
||||
* key: GUINT_TO_POINTER (format)
|
||||
* value: owned GArray* (uint64_t modifier), or NULL
|
||||
*/
|
||||
GHashTable *formats_modifiers;
|
||||
|
||||
MetaKmsDevice *device;
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE (MetaKmsPlane, meta_kms_plane, G_TYPE_OBJECT)
|
||||
|
||||
uint32_t
|
||||
meta_kms_plane_get_id (MetaKmsPlane *plane)
|
||||
{
|
||||
return plane->id;
|
||||
}
|
||||
|
||||
MetaKmsPlaneType
|
||||
meta_kms_plane_get_plane_type (MetaKmsPlane *plane)
|
||||
{
|
||||
@ -75,10 +88,49 @@ meta_kms_plane_is_transform_handled (MetaKmsPlane *plane,
|
||||
*/
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return plane->all_hw_transforms & (1 << transform);
|
||||
}
|
||||
|
||||
GArray *
|
||||
meta_kms_plane_get_modifiers_for_format (MetaKmsPlane *plane,
|
||||
uint32_t format)
|
||||
{
|
||||
return g_hash_table_lookup (plane->formats_modifiers,
|
||||
GUINT_TO_POINTER (format));
|
||||
}
|
||||
|
||||
GArray *
|
||||
meta_kms_plane_copy_drm_format_list (MetaKmsPlane *plane)
|
||||
{
|
||||
GArray *formats;
|
||||
GHashTableIter it;
|
||||
gpointer key;
|
||||
unsigned int n_formats_modifiers;
|
||||
|
||||
n_formats_modifiers = g_hash_table_size (plane->formats_modifiers);
|
||||
formats = g_array_sized_new (FALSE, FALSE,
|
||||
sizeof (uint32_t),
|
||||
n_formats_modifiers);
|
||||
g_hash_table_iter_init (&it, plane->formats_modifiers);
|
||||
while (g_hash_table_iter_next (&it, &key, NULL))
|
||||
{
|
||||
uint32_t drm_format = GPOINTER_TO_UINT (key);
|
||||
|
||||
g_array_append_val (formats, drm_format);
|
||||
}
|
||||
|
||||
return formats;
|
||||
}
|
||||
|
||||
gboolean
|
||||
meta_kms_plane_is_format_supported (MetaKmsPlane *plane,
|
||||
uint32_t drm_format)
|
||||
{
|
||||
return g_hash_table_lookup_extended (plane->formats_modifiers,
|
||||
GUINT_TO_POINTER (drm_format),
|
||||
NULL, NULL);
|
||||
}
|
||||
|
||||
gboolean
|
||||
meta_kms_plane_is_usable_with (MetaKmsPlane *plane,
|
||||
MetaKmsCrtc *crtc)
|
||||
@ -132,6 +184,122 @@ init_rotations (MetaKmsPlane *plane,
|
||||
}
|
||||
}
|
||||
|
||||
static inline uint32_t *
|
||||
drm_formats_ptr (struct drm_format_modifier_blob *blob)
|
||||
{
|
||||
return (uint32_t *) (((char *) blob) + blob->formats_offset);
|
||||
}
|
||||
|
||||
static inline struct drm_format_modifier *
|
||||
drm_modifiers_ptr (struct drm_format_modifier_blob *blob)
|
||||
{
|
||||
return (struct drm_format_modifier *) (((char *) blob) +
|
||||
blob->modifiers_offset);
|
||||
}
|
||||
|
||||
static void
|
||||
free_modifier_array (GArray *array)
|
||||
{
|
||||
if (!array)
|
||||
return;
|
||||
|
||||
g_array_free (array, TRUE);
|
||||
}
|
||||
|
||||
static void
|
||||
parse_formats (MetaKmsPlane *plane,
|
||||
MetaKmsImplDevice *impl_device,
|
||||
uint32_t blob_id)
|
||||
{
|
||||
int fd;
|
||||
drmModePropertyBlobPtr blob;
|
||||
struct drm_format_modifier_blob *blob_fmt;
|
||||
uint32_t *formats;
|
||||
struct drm_format_modifier *drm_modifiers;
|
||||
unsigned int fmt_i, mod_i;
|
||||
|
||||
g_return_if_fail (g_hash_table_size (plane->formats_modifiers) == 0);
|
||||
|
||||
if (blob_id == 0)
|
||||
return;
|
||||
|
||||
fd = meta_kms_impl_device_get_fd (impl_device);
|
||||
blob = drmModeGetPropertyBlob (fd, blob_id);
|
||||
if (!blob)
|
||||
return;
|
||||
|
||||
if (blob->length < sizeof (struct drm_format_modifier_blob))
|
||||
{
|
||||
drmModeFreePropertyBlob (blob);
|
||||
return;
|
||||
}
|
||||
|
||||
blob_fmt = blob->data;
|
||||
|
||||
formats = drm_formats_ptr (blob_fmt);
|
||||
drm_modifiers = drm_modifiers_ptr (blob_fmt);
|
||||
|
||||
for (fmt_i = 0; fmt_i < blob_fmt->count_formats; fmt_i++)
|
||||
{
|
||||
GArray *modifiers = g_array_new (FALSE, FALSE, sizeof (uint64_t));
|
||||
|
||||
for (mod_i = 0; mod_i < blob_fmt->count_modifiers; mod_i++)
|
||||
{
|
||||
struct drm_format_modifier *drm_modifier = &drm_modifiers[mod_i];
|
||||
|
||||
/*
|
||||
* The modifier advertisement blob is partitioned into groups of
|
||||
* 64 formats.
|
||||
*/
|
||||
if (fmt_i < drm_modifier->offset || fmt_i > drm_modifier->offset + 63)
|
||||
continue;
|
||||
|
||||
if (!(drm_modifier->formats & (1 << (fmt_i - drm_modifier->offset))))
|
||||
continue;
|
||||
|
||||
g_array_append_val (modifiers, drm_modifier->modifier);
|
||||
}
|
||||
|
||||
if (modifiers->len == 0)
|
||||
{
|
||||
free_modifier_array (modifiers);
|
||||
modifiers = NULL;
|
||||
}
|
||||
|
||||
g_hash_table_insert (plane->formats_modifiers,
|
||||
GUINT_TO_POINTER (formats[fmt_i]),
|
||||
modifiers);
|
||||
}
|
||||
|
||||
drmModeFreePropertyBlob (blob);
|
||||
}
|
||||
|
||||
static void
|
||||
init_formats (MetaKmsPlane *plane,
|
||||
MetaKmsImplDevice *impl_device,
|
||||
drmModeObjectProperties *drm_plane_props)
|
||||
{
|
||||
drmModePropertyPtr prop;
|
||||
int idx;
|
||||
|
||||
plane->formats_modifiers =
|
||||
g_hash_table_new_full (g_direct_hash,
|
||||
g_direct_equal,
|
||||
NULL,
|
||||
(GDestroyNotify) free_modifier_array);
|
||||
|
||||
prop = meta_kms_impl_device_find_property (impl_device, drm_plane_props,
|
||||
"IN_FORMATS", &idx);
|
||||
if (prop)
|
||||
{
|
||||
uint32_t blob_id;
|
||||
|
||||
blob_id = drm_plane_props->prop_values[idx];
|
||||
parse_formats (plane, impl_device, blob_id);
|
||||
drmModeFreeProperty (prop);
|
||||
}
|
||||
}
|
||||
|
||||
MetaKmsPlane *
|
||||
meta_kms_plane_new (MetaKmsPlaneType type,
|
||||
MetaKmsImplDevice *impl_device,
|
||||
@ -147,10 +315,21 @@ meta_kms_plane_new (MetaKmsPlaneType type,
|
||||
plane->device = meta_kms_impl_device_get_device (impl_device);
|
||||
|
||||
init_rotations (plane, impl_device, drm_plane_props);
|
||||
init_formats (plane, impl_device, drm_plane_props);
|
||||
|
||||
return plane;
|
||||
}
|
||||
|
||||
static void
|
||||
meta_kms_plane_finalize (GObject *object)
|
||||
{
|
||||
MetaKmsPlane *plane = META_KMS_PLANE (object);
|
||||
|
||||
g_hash_table_destroy (plane->formats_modifiers);
|
||||
|
||||
G_OBJECT_CLASS (meta_kms_plane_parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_kms_plane_init (MetaKmsPlane *plane)
|
||||
{
|
||||
@ -159,4 +338,7 @@ meta_kms_plane_init (MetaKmsPlane *plane)
|
||||
static void
|
||||
meta_kms_plane_class_init (MetaKmsPlaneClass *klass)
|
||||
{
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||
|
||||
object_class->finalize = meta_kms_plane_finalize;
|
||||
}
|
||||
|
@ -43,11 +43,21 @@ MetaKmsPlane * meta_kms_plane_new (MetaKmsPlaneType type,
|
||||
drmModePlane *drm_plane,
|
||||
drmModeObjectProperties *drm_plane_props);
|
||||
|
||||
uint32_t meta_kms_plane_get_id (MetaKmsPlane *plane);
|
||||
|
||||
MetaKmsPlaneType meta_kms_plane_get_plane_type (MetaKmsPlane *plane);
|
||||
|
||||
gboolean meta_kms_plane_is_transform_handled (MetaKmsPlane *plane,
|
||||
MetaMonitorTransform transform);
|
||||
|
||||
GArray * meta_kms_plane_get_modifiers_for_format (MetaKmsPlane *plane,
|
||||
uint32_t format);
|
||||
|
||||
GArray * meta_kms_plane_copy_drm_format_list (MetaKmsPlane *plane);
|
||||
|
||||
gboolean meta_kms_plane_is_format_supported (MetaKmsPlane *plane,
|
||||
uint32_t format);
|
||||
|
||||
gboolean meta_kms_plane_is_usable_with (MetaKmsPlane *plane,
|
||||
MetaKmsCrtc *crtc);
|
||||
|
||||
|
@ -23,6 +23,7 @@
|
||||
typedef struct _MetaKms MetaKms;
|
||||
typedef struct _MetaKmsDevice MetaKmsDevice;
|
||||
|
||||
typedef struct _MetaKmsPlane MetaKmsPlane;
|
||||
typedef struct _MetaKmsCrtc MetaKmsCrtc;
|
||||
typedef struct _MetaKmsConnector MetaKmsConnector;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user