diff options
author | Drew DeVault <sir@cmpwn.com> | 2018-02-10 09:51:09 -0500 |
---|---|---|
committer | GitHub <noreply@github.com> | 2018-02-10 09:51:09 -0500 |
commit | 664d7bfe4eb55556be491bb87f8f1c0135d8cac5 (patch) | |
tree | 07510f38d5176e978fb612f55511a747e32714d0 /backend/drm | |
parent | 8fc7edd636ce827dc147edc890e483bc3e3e9b09 (diff) | |
parent | 7cb828ac70c0c41005a761d9011f8b0ca8904688 (diff) |
Merge pull request #618 from VincentVanlaer/atomic-gamma
Add atomic gamma control
Diffstat (limited to 'backend/drm')
-rw-r--r-- | backend/drm/atomic.c | 53 | ||||
-rw-r--r-- | backend/drm/drm.c | 24 | ||||
-rw-r--r-- | backend/drm/legacy.c | 13 | ||||
-rw-r--r-- | backend/drm/properties.c | 10 |
4 files changed, 93 insertions, 7 deletions
diff --git a/backend/drm/atomic.c b/backend/drm/atomic.c index 54024d86..526b2731 100644 --- a/backend/drm/atomic.c +++ b/backend/drm/atomic.c @@ -1,3 +1,4 @@ +#include <stdlib.h> #include <gbm.h> #include <xf86drm.h> #include <xf86drmMode.h> @@ -195,9 +196,61 @@ static bool atomic_crtc_move_cursor(struct wlr_drm_backend *drm, return atomic_end(drm->fd, &atom); } +static bool atomic_crtc_set_gamma(struct wlr_drm_backend *drm, + struct wlr_drm_crtc *crtc, uint16_t *r, uint16_t *g, uint16_t *b, + uint32_t size) { + struct drm_color_lut gamma[size]; + + // Fallback to legacy gamma interface when gamma properties are not available + // (can happen on older intel gpu's that support gamma but not degamma) + if (crtc->props.gamma_lut == 0) { + return legacy_iface.crtc_set_gamma(drm, crtc, r, g, b, size); + } + + for (uint32_t i = 0; i < size; i++) { + gamma[i].red = r[i]; + gamma[i].green = g[i]; + gamma[i].blue = b[i]; + } + + if (crtc->gamma_lut != 0) { + drmModeDestroyPropertyBlob(drm->fd, crtc->gamma_lut); + } + + if (drmModeCreatePropertyBlob(drm->fd, gamma, + sizeof(struct drm_color_lut) * size, &crtc->gamma_lut)) { + wlr_log_errno(L_ERROR, "Unable to create property blob"); + return false; + } + + struct atomic atom; + atomic_begin(crtc, &atom); + atomic_add(&atom, crtc->id, crtc->props.gamma_lut, crtc->gamma_lut); + return atomic_end(drm->fd, &atom); +} + +static uint32_t atomic_crtc_get_gamma_size(struct wlr_drm_backend *drm, + struct wlr_drm_crtc *crtc) { + uint64_t gamma_lut_size; + + if (crtc->props.gamma_lut_size == 0) { + return legacy_iface.crtc_get_gamma_size(drm, crtc); + } + + if (!wlr_drm_get_prop(drm->fd, crtc->id, crtc->props.gamma_lut_size, + &gamma_lut_size)) { + wlr_log(L_ERROR, "Unable to get gamma lut size"); + return 0; + } + + return (uint32_t)gamma_lut_size; +} + const struct wlr_drm_interface atomic_iface = { .conn_enable = atomic_conn_enable, .crtc_pageflip = atomic_crtc_pageflip, .crtc_set_cursor = atomic_crtc_set_cursor, .crtc_move_cursor = atomic_crtc_move_cursor, + .crtc_set_gamma = atomic_crtc_set_gamma, + .crtc_get_gamma_size = atomic_crtc_get_gamma_size, }; diff --git a/backend/drm/drm.c b/backend/drm/drm.c index e1bf63db..56a78851 100644 --- a/backend/drm/drm.c +++ b/backend/drm/drm.c @@ -140,6 +140,7 @@ bool wlr_drm_resources_init(struct wlr_drm_backend *drm) { for (size_t i = 0; i < drm->num_crtcs; ++i) { struct wlr_drm_crtc *crtc = &drm->crtcs[i]; crtc->id = res->crtcs[i]; + crtc->legacy_crtc = drmModeGetCrtc(drm->fd, crtc->id); wlr_drm_get_crtc_props(drm->fd, crtc->id, &crtc->props); } @@ -166,9 +167,13 @@ void wlr_drm_resources_free(struct wlr_drm_backend *drm) { for (size_t i = 0; i < drm->num_crtcs; ++i) { struct wlr_drm_crtc *crtc = &drm->crtcs[i]; drmModeAtomicFree(crtc->atomic); + drmModeFreeCrtc(crtc->legacy_crtc); if (crtc->mode_id) { drmModeDestroyPropertyBlob(drm->fd, crtc->mode_id); } + if (crtc->gamma_lut) { + drmModeDestroyPropertyBlob(drm->fd, crtc->gamma_lut); + } } for (size_t i = 0; i < drm->num_planes; ++i) { struct wlr_drm_plane *plane = &drm->planes[i]; @@ -228,13 +233,26 @@ static void wlr_drm_connector_set_gamma(struct wlr_output *output, uint32_t size, uint16_t *r, uint16_t *g, uint16_t *b) { struct wlr_drm_connector *conn = (struct wlr_drm_connector *)output; struct wlr_drm_backend *drm = (struct wlr_drm_backend *)output->backend; - drmModeCrtcSetGamma(drm->fd, conn->crtc->id, size, r, g, b); + bool ok; + + if (conn->crtc) { + ok = drm->iface->crtc_set_gamma(drm, conn->crtc, r, g, b, size); + if (ok) { + wlr_output_update_needs_swap(output); + } + } + } static uint32_t wlr_drm_connector_get_gamma_size(struct wlr_output *output) { struct wlr_drm_connector *conn = (struct wlr_drm_connector *)output; - drmModeCrtc *crtc = conn->old_crtc; - return crtc ? crtc->gamma_size : 0; + struct wlr_drm_backend *drm = (struct wlr_drm_backend *)output->backend; + + if (conn->crtc) { + return drm->iface->crtc_get_gamma_size(drm, conn->crtc); + } + + return 0; } void wlr_drm_connector_start_renderer(struct wlr_drm_connector *conn) { diff --git a/backend/drm/legacy.c b/backend/drm/legacy.c index 61140cec..eec8c642 100644 --- a/backend/drm/legacy.c +++ b/backend/drm/legacy.c @@ -59,9 +59,22 @@ bool legacy_crtc_move_cursor(struct wlr_drm_backend *drm, return !drmModeMoveCursor(drm->fd, crtc->id, x, y); } +bool legacy_crtc_set_gamma(struct wlr_drm_backend *drm, + struct wlr_drm_crtc *crtc, uint16_t *r, uint16_t *g, uint16_t *b, + uint32_t size) { + return !drmModeCrtcSetGamma(drm->fd, crtc->id, size, r, g, b); +} + +uint32_t legacy_crtc_get_gamma_size(struct wlr_drm_backend *drm, + struct wlr_drm_crtc *crtc) { + return crtc->legacy_crtc->gamma_size; +} + const struct wlr_drm_interface legacy_iface = { .conn_enable = legacy_conn_enable, .crtc_pageflip = legacy_crtc_pageflip, .crtc_set_cursor = legacy_crtc_set_cursor, .crtc_move_cursor = legacy_crtc_move_cursor, + .crtc_set_gamma = legacy_crtc_set_gamma, + .crtc_get_gamma_size = legacy_crtc_get_gamma_size, }; diff --git a/backend/drm/properties.c b/backend/drm/properties.c index 5bec3243..153e845e 100644 --- a/backend/drm/properties.c +++ b/backend/drm/properties.c @@ -27,10 +27,12 @@ static const struct prop_info connector_info[] = { static const struct prop_info crtc_info[] = { #define INDEX(name) (offsetof(union wlr_drm_crtc_props, name) / sizeof(uint32_t)) - { "ACTIVE", INDEX(active) }, - { "MODE_ID", INDEX(mode_id) }, - { "rotation", INDEX(rotation) }, - { "scaling mode", INDEX(scaling_mode) }, + { "ACTIVE", INDEX(active) }, + { "GAMMA_LUT", INDEX(gamma_lut) }, + { "GAMMA_LUT_SIZE", INDEX(gamma_lut_size) }, + { "MODE_ID", INDEX(mode_id) }, + { "rotation", INDEX(rotation) }, + { "scaling mode", INDEX(scaling_mode) }, #undef INDEX }; |