aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--backend/drm/atomic.c39
-rw-r--r--backend/drm/drm.c4
-rw-r--r--include/backend/drm/drm.h2
3 files changed, 40 insertions, 5 deletions
diff --git a/backend/drm/atomic.c b/backend/drm/atomic.c
index c69d6abd..0dacff23 100644
--- a/backend/drm/atomic.c
+++ b/backend/drm/atomic.c
@@ -1,4 +1,5 @@
#define _POSIX_C_SOURCE 200809L
+#include <drm_fourcc.h>
#include <stdlib.h>
#include <stdio.h>
#include <wlr/util/log.h>
@@ -142,6 +143,40 @@ static bool create_gamma_lut_blob(struct wlr_drm_backend *drm,
return true;
}
+static uint64_t max_bpc_for_format(uint32_t format) {
+ switch (format) {
+ case DRM_FORMAT_XRGB2101010:
+ case DRM_FORMAT_ARGB2101010:
+ case DRM_FORMAT_XBGR2101010:
+ case DRM_FORMAT_ABGR2101010:
+ return 10;
+ case DRM_FORMAT_XBGR16161616F:
+ case DRM_FORMAT_ABGR16161616F:
+ case DRM_FORMAT_XBGR16161616:
+ case DRM_FORMAT_ABGR16161616:
+ return 16;
+ default:
+ return 8;
+ }
+}
+
+static uint64_t pick_max_bpc(struct wlr_drm_connector *conn, struct wlr_drm_fb *fb) {
+ uint32_t format = DRM_FORMAT_INVALID;
+ struct wlr_dmabuf_attributes attribs = {0};
+ if (wlr_buffer_get_dmabuf(fb->wlr_buf, &attribs)) {
+ format = attribs.format;
+ }
+
+ uint64_t target_bpc = max_bpc_for_format(format);
+ if (target_bpc < conn->max_bpc_bounds[0]) {
+ target_bpc = conn->max_bpc_bounds[0];
+ }
+ if (target_bpc > conn->max_bpc_bounds[1]) {
+ target_bpc = conn->max_bpc_bounds[1];
+ }
+ return target_bpc;
+}
+
static void commit_blob(struct wlr_drm_backend *drm,
uint32_t *current, uint32_t next) {
if (*current == next) {
@@ -282,8 +317,8 @@ static bool atomic_crtc_commit(struct wlr_drm_connector *conn,
atomic_add(&atom, conn->id, conn->props.content_type,
DRM_MODE_CONTENT_TYPE_GRAPHICS);
}
- if (modeset && active && conn->props.max_bpc != 0 && conn->max_bpc > 0) {
- atomic_add(&atom, conn->id, conn->props.max_bpc, conn->max_bpc);
+ if (modeset && active && conn->props.max_bpc != 0 && conn->max_bpc_bounds[1] != 0) {
+ atomic_add(&atom, conn->id, conn->props.max_bpc, pick_max_bpc(conn, state->primary_fb));
}
atomic_add(&atom, crtc->id, crtc->props.mode_id, mode_id);
atomic_add(&atom, crtc->id, crtc->props.active, active);
diff --git a/backend/drm/drm.c b/backend/drm/drm.c
index 24bb1088..004124b8 100644
--- a/backend/drm/drm.c
+++ b/backend/drm/drm.c
@@ -1279,10 +1279,10 @@ static bool connect_drm_connector(struct wlr_drm_connector *wlr_conn,
wlr_conn->output.non_desktop = non_desktop;
}
- wlr_conn->max_bpc = 0;
+ memset(wlr_conn->max_bpc_bounds, 0, sizeof(wlr_conn->max_bpc_bounds));
if (wlr_conn->props.max_bpc != 0) {
if (!introspect_drm_prop_range(drm->fd, wlr_conn->props.max_bpc,
- NULL, &wlr_conn->max_bpc)) {
+ &wlr_conn->max_bpc_bounds[0], &wlr_conn->max_bpc_bounds[1])) {
wlr_log(WLR_ERROR, "Failed to introspect 'max bpc' property");
}
}
diff --git a/include/backend/drm/drm.h b/include/backend/drm/drm.h
index e93b5eaf..01971e52 100644
--- a/include/backend/drm/drm.h
+++ b/include/backend/drm/drm.h
@@ -107,7 +107,7 @@ struct wlr_drm_connector {
char name[24];
drmModeConnection status;
uint32_t id;
- uint64_t max_bpc;
+ uint64_t max_bpc_bounds[2];
struct wlr_drm_lease *lease;
struct wlr_drm_crtc *crtc;