modesetting: Add CTM RandR property
When the "CTM" (color transform matrix) modesetting property is available, create a corresponding RandR property. To match the format of the property available in the amdgpu driver, expose it as an array of 18 32-bit XA_INTEGERs representing a 3x3 matrix in row-major order, where each entry is a S31.32 sign-magnitude fixed-point number with the fractional part listed first. Signed-off-by: Aaron Plattner <aplattner@nvidia.com> Acked-by: Michel Dänzer <mdaenzer@redhat.com> Reviewed-by: James Jones <jajones@nvidia.com>
This commit is contained in:
parent
245b9db03a
commit
4e670f1281
|
@ -60,6 +60,32 @@ static PixmapPtr drmmode_create_pixmap_header(ScreenPtr pScreen, int width, int
|
||||||
int depth, int bitsPerPixel, int devKind,
|
int depth, int bitsPerPixel, int devKind,
|
||||||
void *pPixData);
|
void *pPixData);
|
||||||
|
|
||||||
|
static const struct drm_color_ctm ctm_identity = { {
|
||||||
|
1UL << 32, 0, 0,
|
||||||
|
0, 1UL << 32, 0,
|
||||||
|
0, 0, 1UL << 32
|
||||||
|
} };
|
||||||
|
|
||||||
|
static Bool ctm_is_identity(const struct drm_color_ctm *ctm)
|
||||||
|
{
|
||||||
|
const size_t matrix_len = sizeof(ctm->matrix) / sizeof(ctm->matrix[0]);
|
||||||
|
const uint64_t one = 1ULL << 32;
|
||||||
|
const uint64_t neg_zero = 1ULL << 63;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < matrix_len; i++) {
|
||||||
|
const Bool diagonal = i / 3 == i % 3;
|
||||||
|
const uint64_t val = ctm->matrix[i];
|
||||||
|
|
||||||
|
if ((diagonal && val != one) ||
|
||||||
|
(!diagonal && val != 0 && val != neg_zero)) {
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
static inline uint32_t *
|
static inline uint32_t *
|
||||||
formats_ptr(struct drm_format_modifier_blob *blob)
|
formats_ptr(struct drm_format_modifier_blob *blob)
|
||||||
{
|
{
|
||||||
|
@ -750,6 +776,39 @@ drmmode_crtc_disable(xf86CrtcPtr crtc)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
drmmode_set_ctm(xf86CrtcPtr crtc, const struct drm_color_ctm *ctm)
|
||||||
|
{
|
||||||
|
drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
|
||||||
|
drmmode_ptr drmmode = drmmode_crtc->drmmode;
|
||||||
|
drmmode_prop_info_ptr ctm_info =
|
||||||
|
&drmmode_crtc->props[DRMMODE_CRTC_CTM];
|
||||||
|
int ret;
|
||||||
|
uint32_t blob_id = 0;
|
||||||
|
|
||||||
|
if (ctm_info->prop_id == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (ctm && drmmode_crtc->use_gamma_lut && !ctm_is_identity(ctm)) {
|
||||||
|
ret = drmModeCreatePropertyBlob(drmmode->fd, ctm, sizeof(*ctm), &blob_id);
|
||||||
|
if (ret != 0) {
|
||||||
|
xf86DrvMsg(crtc->scrn->scrnIndex, X_ERROR,
|
||||||
|
"Failed to create CTM property blob: %d\n", ret);
|
||||||
|
blob_id = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = drmModeObjectSetProperty(drmmode->fd,
|
||||||
|
drmmode_crtc->mode_crtc->crtc_id,
|
||||||
|
DRM_MODE_OBJECT_CRTC, ctm_info->prop_id,
|
||||||
|
blob_id);
|
||||||
|
if (ret != 0)
|
||||||
|
xf86DrvMsg(crtc->scrn->scrnIndex, X_ERROR,
|
||||||
|
"Failed to set CTM property: %d\n", ret);
|
||||||
|
|
||||||
|
drmModeDestroyPropertyBlob(drmmode->fd, blob_id);
|
||||||
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
drmmode_crtc_set_mode(xf86CrtcPtr crtc, Bool test_only)
|
drmmode_crtc_set_mode(xf86CrtcPtr crtc, Bool test_only)
|
||||||
{
|
{
|
||||||
|
@ -763,6 +822,7 @@ drmmode_crtc_set_mode(xf86CrtcPtr crtc, Bool test_only)
|
||||||
uint32_t fb_id;
|
uint32_t fb_id;
|
||||||
int x, y;
|
int x, y;
|
||||||
int i, ret = 0;
|
int i, ret = 0;
|
||||||
|
const struct drm_color_ctm *ctm = NULL;
|
||||||
|
|
||||||
if (!drmmode_crtc_get_fb_id(crtc, &fb_id, &x, &y))
|
if (!drmmode_crtc_get_fb_id(crtc, &fb_id, &x, &y))
|
||||||
return 1;
|
return 1;
|
||||||
|
@ -853,12 +913,16 @@ drmmode_crtc_set_mode(xf86CrtcPtr crtc, Bool test_only)
|
||||||
continue;
|
continue;
|
||||||
output_ids[output_count] = drmmode_output->output_id;
|
output_ids[output_count] = drmmode_output->output_id;
|
||||||
output_count++;
|
output_count++;
|
||||||
|
|
||||||
|
ctm = &drmmode_output->ctm;
|
||||||
}
|
}
|
||||||
|
|
||||||
drmmode_ConvertToKMode(crtc->scrn, &kmode, &crtc->mode);
|
drmmode_ConvertToKMode(crtc->scrn, &kmode, &crtc->mode);
|
||||||
ret = drmModeSetCrtc(drmmode->fd, drmmode_crtc->mode_crtc->crtc_id,
|
ret = drmModeSetCrtc(drmmode->fd, drmmode_crtc->mode_crtc->crtc_id,
|
||||||
fb_id, x, y, output_ids, output_count, &kmode);
|
fb_id, x, y, output_ids, output_count, &kmode);
|
||||||
|
|
||||||
|
drmmode_set_ctm(crtc, ctm);
|
||||||
|
|
||||||
free(output_ids);
|
free(output_ids);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@ -2301,6 +2365,7 @@ drmmode_crtc_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode, drmModeResPtr mode_res
|
||||||
[DRMMODE_CRTC_MODE_ID] = { .name = "MODE_ID" },
|
[DRMMODE_CRTC_MODE_ID] = { .name = "MODE_ID" },
|
||||||
[DRMMODE_CRTC_GAMMA_LUT] = { .name = "GAMMA_LUT" },
|
[DRMMODE_CRTC_GAMMA_LUT] = { .name = "GAMMA_LUT" },
|
||||||
[DRMMODE_CRTC_GAMMA_LUT_SIZE] = { .name = "GAMMA_LUT_SIZE" },
|
[DRMMODE_CRTC_GAMMA_LUT_SIZE] = { .name = "GAMMA_LUT_SIZE" },
|
||||||
|
[DRMMODE_CRTC_CTM] = { .name = "CTM" },
|
||||||
};
|
};
|
||||||
|
|
||||||
crtc = xf86CrtcCreate(pScrn, &drmmode_crtc_funcs);
|
crtc = xf86CrtcCreate(pScrn, &drmmode_crtc_funcs);
|
||||||
|
@ -2370,6 +2435,11 @@ drmmode_crtc_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode, drmModeResPtr mode_res
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (drmmode_crtc->use_gamma_lut &&
|
||||||
|
drmmode_crtc->props[DRMMODE_CRTC_CTM].prop_id) {
|
||||||
|
drmmode->use_ctm = TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2432,6 +2502,20 @@ drmmode_output_update_properties(xf86OutputPtr output)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Update the CTM property */
|
||||||
|
if (drmmode_output->ctm_atom) {
|
||||||
|
err = RRChangeOutputProperty(output->randr_output,
|
||||||
|
drmmode_output->ctm_atom,
|
||||||
|
XA_INTEGER, 32, PropModeReplace, 18,
|
||||||
|
&drmmode_output->ctm,
|
||||||
|
FALSE, TRUE);
|
||||||
|
if (err != 0) {
|
||||||
|
xf86DrvMsg(output->scrn->scrnIndex, X_ERROR,
|
||||||
|
"RRChangeOutputProperty error, %d\n", err);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static xf86OutputStatus
|
static xf86OutputStatus
|
||||||
|
@ -2784,6 +2868,31 @@ drmmode_output_create_resources(xf86OutputPtr output)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (drmmode->use_ctm) {
|
||||||
|
Atom name = MakeAtom("CTM", 3, TRUE);
|
||||||
|
|
||||||
|
if (name != BAD_RESOURCE) {
|
||||||
|
drmmode_output->ctm_atom = name;
|
||||||
|
|
||||||
|
err = RRConfigureOutputProperty(output->randr_output, name,
|
||||||
|
FALSE, FALSE, TRUE, 0, NULL);
|
||||||
|
if (err != 0) {
|
||||||
|
xf86DrvMsg(output->scrn->scrnIndex, X_ERROR,
|
||||||
|
"RRConfigureOutputProperty error, %d\n", err);
|
||||||
|
}
|
||||||
|
|
||||||
|
err = RRChangeOutputProperty(output->randr_output, name,
|
||||||
|
XA_INTEGER, 32, PropModeReplace, 18,
|
||||||
|
&ctm_identity, FALSE, FALSE);
|
||||||
|
if (err != 0) {
|
||||||
|
xf86DrvMsg(output->scrn->scrnIndex, X_ERROR,
|
||||||
|
"RRChangeOutputProperty error, %d\n", err);
|
||||||
|
}
|
||||||
|
|
||||||
|
drmmode_output->ctm = ctm_identity;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for (i = 0; i < drmmode_output->num_props; i++) {
|
for (i = 0; i < drmmode_output->num_props; i++) {
|
||||||
drmmode_prop_ptr p = &drmmode_output->props[i];
|
drmmode_prop_ptr p = &drmmode_output->props[i];
|
||||||
|
|
||||||
|
@ -2906,6 +3015,21 @@ drmmode_output_set_property(xf86OutputPtr output, Atom property,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (property == drmmode_output->ctm_atom) {
|
||||||
|
const size_t matrix_size = sizeof(drmmode_output->ctm);
|
||||||
|
|
||||||
|
if (value->type != XA_INTEGER || value->format != 32 ||
|
||||||
|
value->size * 4 != matrix_size)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
memcpy(&drmmode_output->ctm, value->data, matrix_size);
|
||||||
|
|
||||||
|
// Update the CRTC if there is one bound to this output.
|
||||||
|
if (output->crtc) {
|
||||||
|
drmmode_set_ctm(output->crtc, &drmmode_output->ctm);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -69,6 +69,7 @@ enum drmmode_crtc_property {
|
||||||
DRMMODE_CRTC_MODE_ID,
|
DRMMODE_CRTC_MODE_ID,
|
||||||
DRMMODE_CRTC_GAMMA_LUT,
|
DRMMODE_CRTC_GAMMA_LUT,
|
||||||
DRMMODE_CRTC_GAMMA_LUT_SIZE,
|
DRMMODE_CRTC_GAMMA_LUT_SIZE,
|
||||||
|
DRMMODE_CRTC_CTM,
|
||||||
DRMMODE_CRTC__COUNT
|
DRMMODE_CRTC__COUNT
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -132,6 +133,7 @@ typedef struct {
|
||||||
Bool present_enable;
|
Bool present_enable;
|
||||||
|
|
||||||
uint32_t vrr_prop_id;
|
uint32_t vrr_prop_id;
|
||||||
|
Bool use_ctm;
|
||||||
} drmmode_rec, *drmmode_ptr;
|
} drmmode_rec, *drmmode_ptr;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
|
@ -226,6 +228,8 @@ typedef struct {
|
||||||
int enc_mask;
|
int enc_mask;
|
||||||
int enc_clone_mask;
|
int enc_clone_mask;
|
||||||
xf86CrtcPtr current_crtc;
|
xf86CrtcPtr current_crtc;
|
||||||
|
Atom ctm_atom;
|
||||||
|
struct drm_color_ctm ctm;
|
||||||
} drmmode_output_private_rec, *drmmode_output_private_ptr;
|
} drmmode_output_private_rec, *drmmode_output_private_ptr;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
|
|
Loading…
Reference in New Issue