mirror of
https://github.com/hyprwm/wlroots-hyprland.git
synced 2024-11-02 11:55:59 +01:00
backend/drm: check format when scanning out DMA-BUF
This commit is contained in:
parent
96d6fde5dc
commit
e516ea4c79
6 changed files with 90 additions and 22 deletions
|
@ -123,6 +123,8 @@ static bool init_planes(struct wlr_drm_backend *drm) {
|
||||||
uint32_t rgb_format = DRM_FORMAT_INVALID;
|
uint32_t rgb_format = DRM_FORMAT_INVALID;
|
||||||
for (size_t j = 0; j < plane->count_formats; ++j) {
|
for (size_t j = 0; j < plane->count_formats; ++j) {
|
||||||
uint32_t fmt = plane->formats[j];
|
uint32_t fmt = plane->formats[j];
|
||||||
|
wlr_drm_format_set_add(&p->formats, fmt, DRM_FORMAT_MOD_INVALID);
|
||||||
|
|
||||||
if (fmt == DRM_FORMAT_ARGB8888) {
|
if (fmt == DRM_FORMAT_ARGB8888) {
|
||||||
// Prefer formats with alpha channel
|
// Prefer formats with alpha channel
|
||||||
rgb_format = fmt;
|
rgb_format = fmt;
|
||||||
|
@ -141,6 +143,38 @@ static bool init_planes(struct wlr_drm_backend *drm) {
|
||||||
}
|
}
|
||||||
p->drm_format = rgb_format;
|
p->drm_format = rgb_format;
|
||||||
|
|
||||||
|
if (p->props.in_formats) {
|
||||||
|
uint64_t blob_id;
|
||||||
|
if (!get_drm_prop(drm->fd, p->id, p->props.in_formats, &blob_id)) {
|
||||||
|
wlr_log(WLR_ERROR, "Failed to read IN_FORMATS property");
|
||||||
|
drmModeFreePlane(plane);
|
||||||
|
goto error_planes;
|
||||||
|
}
|
||||||
|
|
||||||
|
drmModePropertyBlobRes *blob =
|
||||||
|
drmModeGetPropertyBlob(drm->fd, blob_id);
|
||||||
|
if (!blob) {
|
||||||
|
wlr_log(WLR_ERROR, "Failed to read IN_FORMATS blob");
|
||||||
|
drmModeFreePlane(plane);
|
||||||
|
goto error_planes;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct drm_format_modifier_blob *data = blob->data;
|
||||||
|
uint32_t *fmts = (uint32_t *)((char *)data + data->formats_offset);
|
||||||
|
struct drm_format_modifier *mods = (struct drm_format_modifier *)
|
||||||
|
((char *)data + data->modifiers_offset);
|
||||||
|
for (uint32_t i = 0; i < data->count_modifiers; ++i) {
|
||||||
|
for (int j = 0; j < 64; ++j) {
|
||||||
|
if (mods[i].formats & ((uint64_t)1 << j)) {
|
||||||
|
wlr_drm_format_set_add(&p->formats,
|
||||||
|
fmts[j + mods[i].offset], mods[i].modifier);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
drmModeFreePropertyBlob(blob);
|
||||||
|
}
|
||||||
|
|
||||||
drmModeFreePlane(plane);
|
drmModeFreePlane(plane);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -215,6 +249,11 @@ void finish_drm_resources(struct wlr_drm_backend *drm) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (size_t i = 0; i < drm->num_planes; ++i) {
|
||||||
|
struct wlr_drm_plane *p = &drm->planes[i];
|
||||||
|
wlr_drm_format_set_finish(&p->formats);
|
||||||
|
}
|
||||||
|
|
||||||
for (size_t i = 0; i < drm->num_crtcs; ++i) {
|
for (size_t i = 0; i < drm->num_crtcs; ++i) {
|
||||||
struct wlr_drm_crtc *crtc = &drm->crtcs[i];
|
struct wlr_drm_crtc *crtc = &drm->crtcs[i];
|
||||||
drmModeAtomicFree(crtc->atomic);
|
drmModeAtomicFree(crtc->atomic);
|
||||||
|
@ -833,11 +872,13 @@ static bool drm_connector_set_dmabuf(struct wlr_output *output,
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: check plane input formats
|
|
||||||
|
|
||||||
if (attribs->width != output->width || attribs->height != output->height) {
|
if (attribs->width != output->width || attribs->height != output->height) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
if (!wlr_drm_format_set_has(&crtc->primary->formats,
|
||||||
|
attribs->format, attribs->modifier)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
struct gbm_bo *bo = import_gbm_bo(&drm->renderer, attribs);
|
struct gbm_bo *bo = import_gbm_bo(&drm->renderer, attribs);
|
||||||
if (bo == NULL) {
|
if (bo == NULL) {
|
||||||
|
|
|
@ -19,38 +19,39 @@ struct prop_info {
|
||||||
|
|
||||||
static const struct prop_info connector_info[] = {
|
static const struct prop_info connector_info[] = {
|
||||||
#define INDEX(name) (offsetof(union wlr_drm_connector_props, name) / sizeof(uint32_t))
|
#define INDEX(name) (offsetof(union wlr_drm_connector_props, name) / sizeof(uint32_t))
|
||||||
{ "CRTC_ID", INDEX(crtc_id) },
|
{ "CRTC_ID", INDEX(crtc_id) },
|
||||||
{ "DPMS", INDEX(dpms) },
|
{ "DPMS", INDEX(dpms) },
|
||||||
{ "EDID", INDEX(edid) },
|
{ "EDID", INDEX(edid) },
|
||||||
{ "PATH", INDEX(path) },
|
{ "PATH", INDEX(path) },
|
||||||
{ "link-status", INDEX(link_status) },
|
{ "link-status", INDEX(link_status) },
|
||||||
#undef INDEX
|
#undef INDEX
|
||||||
};
|
};
|
||||||
|
|
||||||
static const struct prop_info crtc_info[] = {
|
static const struct prop_info crtc_info[] = {
|
||||||
#define INDEX(name) (offsetof(union wlr_drm_crtc_props, name) / sizeof(uint32_t))
|
#define INDEX(name) (offsetof(union wlr_drm_crtc_props, name) / sizeof(uint32_t))
|
||||||
{ "ACTIVE", INDEX(active) },
|
{ "ACTIVE", INDEX(active) },
|
||||||
{ "GAMMA_LUT", INDEX(gamma_lut) },
|
{ "GAMMA_LUT", INDEX(gamma_lut) },
|
||||||
{ "GAMMA_LUT_SIZE", INDEX(gamma_lut_size) },
|
{ "GAMMA_LUT_SIZE", INDEX(gamma_lut_size) },
|
||||||
{ "MODE_ID", INDEX(mode_id) },
|
{ "MODE_ID", INDEX(mode_id) },
|
||||||
{ "rotation", INDEX(rotation) },
|
{ "rotation", INDEX(rotation) },
|
||||||
{ "scaling mode", INDEX(scaling_mode) },
|
{ "scaling mode", INDEX(scaling_mode) },
|
||||||
#undef INDEX
|
#undef INDEX
|
||||||
};
|
};
|
||||||
|
|
||||||
static const struct prop_info plane_info[] = {
|
static const struct prop_info plane_info[] = {
|
||||||
#define INDEX(name) (offsetof(union wlr_drm_plane_props, name) / sizeof(uint32_t))
|
#define INDEX(name) (offsetof(union wlr_drm_plane_props, name) / sizeof(uint32_t))
|
||||||
{ "CRTC_H", INDEX(crtc_h) },
|
{ "CRTC_H", INDEX(crtc_h) },
|
||||||
{ "CRTC_ID", INDEX(crtc_id) },
|
{ "CRTC_ID", INDEX(crtc_id) },
|
||||||
{ "CRTC_W", INDEX(crtc_w) },
|
{ "CRTC_W", INDEX(crtc_w) },
|
||||||
{ "CRTC_X", INDEX(crtc_x) },
|
{ "CRTC_X", INDEX(crtc_x) },
|
||||||
{ "CRTC_Y", INDEX(crtc_y) },
|
{ "CRTC_Y", INDEX(crtc_y) },
|
||||||
{ "FB_ID", INDEX(fb_id) },
|
{ "FB_ID", INDEX(fb_id) },
|
||||||
{ "SRC_H", INDEX(src_h) },
|
{ "IN_FORMATS", INDEX(in_formats) },
|
||||||
{ "SRC_W", INDEX(src_w) },
|
{ "SRC_H", INDEX(src_h) },
|
||||||
{ "SRC_X", INDEX(src_x) },
|
{ "SRC_W", INDEX(src_w) },
|
||||||
{ "SRC_Y", INDEX(src_y) },
|
{ "SRC_X", INDEX(src_x) },
|
||||||
{ "type", INDEX(type) },
|
{ "SRC_Y", INDEX(src_y) },
|
||||||
|
{ "type", INDEX(type) },
|
||||||
#undef INDEX
|
#undef INDEX
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -11,6 +11,7 @@
|
||||||
#include <wayland-util.h>
|
#include <wayland-util.h>
|
||||||
#include <wlr/backend/drm.h>
|
#include <wlr/backend/drm.h>
|
||||||
#include <wlr/backend/session.h>
|
#include <wlr/backend/session.h>
|
||||||
|
#include <wlr/render/drm_format_set.h>
|
||||||
#include <wlr/render/egl.h>
|
#include <wlr/render/egl.h>
|
||||||
#include <xf86drmMode.h>
|
#include <xf86drmMode.h>
|
||||||
#include "iface.h"
|
#include "iface.h"
|
||||||
|
@ -27,6 +28,7 @@ struct wlr_drm_plane {
|
||||||
struct wlr_drm_surface mgpu_surf;
|
struct wlr_drm_surface mgpu_surf;
|
||||||
|
|
||||||
uint32_t drm_format; // ARGB8888 or XRGB8888
|
uint32_t drm_format; // ARGB8888 or XRGB8888
|
||||||
|
struct wlr_drm_format_set formats;
|
||||||
|
|
||||||
// Only used by cursor
|
// Only used by cursor
|
||||||
float matrix[9];
|
float matrix[9];
|
||||||
|
|
|
@ -44,6 +44,7 @@ union wlr_drm_plane_props {
|
||||||
struct {
|
struct {
|
||||||
uint32_t type;
|
uint32_t type;
|
||||||
uint32_t rotation; // Not guaranteed to exist
|
uint32_t rotation; // Not guaranteed to exist
|
||||||
|
uint32_t in_formats; // Not guaranteed to exist
|
||||||
|
|
||||||
// atomic-modesetting only
|
// atomic-modesetting only
|
||||||
|
|
||||||
|
@ -58,7 +59,7 @@ union wlr_drm_plane_props {
|
||||||
uint32_t fb_id;
|
uint32_t fb_id;
|
||||||
uint32_t crtc_id;
|
uint32_t crtc_id;
|
||||||
};
|
};
|
||||||
uint32_t props[12];
|
uint32_t props[13];
|
||||||
};
|
};
|
||||||
|
|
||||||
bool get_drm_connector_props(int fd, uint32_t id,
|
bool get_drm_connector_props(int fd, uint32_t id,
|
||||||
|
|
|
@ -21,6 +21,9 @@ void wlr_drm_format_set_finish(struct wlr_drm_format_set *set);
|
||||||
const struct wlr_drm_format *wlr_drm_format_set_get(
|
const struct wlr_drm_format *wlr_drm_format_set_get(
|
||||||
const struct wlr_drm_format_set *set, uint32_t format);
|
const struct wlr_drm_format_set *set, uint32_t format);
|
||||||
|
|
||||||
|
bool wlr_drm_format_set_has(const struct wlr_drm_format_set *set,
|
||||||
|
uint32_t format, uint64_t modifier);
|
||||||
|
|
||||||
bool wlr_drm_format_set_add(struct wlr_drm_format_set *set, uint32_t format,
|
bool wlr_drm_format_set_add(struct wlr_drm_format_set *set, uint32_t format,
|
||||||
uint64_t modifier);
|
uint64_t modifier);
|
||||||
|
|
||||||
|
|
|
@ -35,6 +35,26 @@ const struct wlr_drm_format *wlr_drm_format_set_get(
|
||||||
return ptr ? *ptr : NULL;
|
return ptr ? *ptr : NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool wlr_drm_format_set_has(const struct wlr_drm_format_set *set,
|
||||||
|
uint32_t format, uint64_t modifier) {
|
||||||
|
const struct wlr_drm_format *fmt = wlr_drm_format_set_get(set, format);
|
||||||
|
if (!fmt) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (modifier == DRM_FORMAT_MOD_INVALID) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (size_t i = 0; i < fmt->len; ++i) {
|
||||||
|
if (fmt->modifiers[i] == modifier) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
bool wlr_drm_format_set_add(struct wlr_drm_format_set *set, uint32_t format,
|
bool wlr_drm_format_set_add(struct wlr_drm_format_set *set, uint32_t format,
|
||||||
uint64_t modifier) {
|
uint64_t modifier) {
|
||||||
struct wlr_drm_format **ptr = format_set_get_ref(set, format);
|
struct wlr_drm_format **ptr = format_set_get_ref(set, format);
|
||||||
|
|
Loading…
Reference in a new issue