modesetting: Use GAMMA_LUT when available
If the kernel exposes GAMMA_LUT and GAMMA_LUT_SIZE properties and the size is not what the server has pre-configured for the crtc, free the old gamma ramp memory allocated by the server and replace it with new allocations of the appropriate size. In addition, when GAMMA_LUT is available, use drmModeCreatePropertyBlob() and drmModeObjectSetProperty() to set the gamma ramp rather than using the legacy drmModeCrtcSetGamma() function. Add a new option "UseGammaLUT" to allow disabling this new behavior and falling back to drmModeCrtcSetGamma() unconditionally. Signed-off-by: Aaron Plattner <aplattner@nvidia.com>
This commit is contained in:
parent
b6985d6b3f
commit
245b9db03a
|
@ -140,6 +140,7 @@ static const OptionInfoRec Options[] = {
|
|||
{OPTION_DOUBLE_SHADOW, "DoubleShadow", OPTV_BOOLEAN, {0}, FALSE},
|
||||
{OPTION_ATOMIC, "Atomic", OPTV_BOOLEAN, {0}, FALSE},
|
||||
{OPTION_VARIABLE_REFRESH, "VariableRefresh", OPTV_BOOLEAN, {0}, FALSE},
|
||||
{OPTION_USE_GAMMA_LUT, "UseGammaLUT", OPTV_BOOLEAN, {0}, FALSE},
|
||||
{-1, NULL, OPTV_NONE, {0}, FALSE}
|
||||
};
|
||||
|
||||
|
|
|
@ -57,6 +57,7 @@ typedef enum {
|
|||
OPTION_DOUBLE_SHADOW,
|
||||
OPTION_ATOMIC,
|
||||
OPTION_VARIABLE_REFRESH,
|
||||
OPTION_USE_GAMMA_LUT,
|
||||
} modesettingOpts;
|
||||
|
||||
typedef struct
|
||||
|
|
|
@ -1669,6 +1669,35 @@ drmmode_show_cursor(xf86CrtcPtr crtc)
|
|||
return drmmode_set_cursor(crtc);
|
||||
}
|
||||
|
||||
static void
|
||||
drmmode_set_gamma_lut(drmmode_crtc_private_ptr drmmode_crtc,
|
||||
uint16_t * red, uint16_t * green, uint16_t * blue,
|
||||
int size)
|
||||
{
|
||||
drmmode_ptr drmmode = drmmode_crtc->drmmode;
|
||||
drmmode_prop_info_ptr gamma_lut_info =
|
||||
&drmmode_crtc->props[DRMMODE_CRTC_GAMMA_LUT];
|
||||
const uint32_t crtc_id = drmmode_crtc->mode_crtc->crtc_id;
|
||||
uint32_t blob_id;
|
||||
struct drm_color_lut lut[size];
|
||||
|
||||
assert(gamma_lut_info->prop_id != 0);
|
||||
|
||||
for (int i = 0; i < size; i++) {
|
||||
lut[i].red = red[i];
|
||||
lut[i].green = green[i];
|
||||
lut[i].blue = blue[i];
|
||||
}
|
||||
|
||||
if (drmModeCreatePropertyBlob(drmmode->fd, lut, sizeof(lut), &blob_id))
|
||||
return;
|
||||
|
||||
drmModeObjectSetProperty(drmmode->fd, crtc_id, DRM_MODE_OBJECT_CRTC,
|
||||
gamma_lut_info->prop_id, blob_id);
|
||||
|
||||
drmModeDestroyPropertyBlob(drmmode->fd, blob_id);
|
||||
}
|
||||
|
||||
static void
|
||||
drmmode_crtc_gamma_set(xf86CrtcPtr crtc, uint16_t * red, uint16_t * green,
|
||||
uint16_t * blue, int size)
|
||||
|
@ -1676,8 +1705,12 @@ drmmode_crtc_gamma_set(xf86CrtcPtr crtc, uint16_t * red, uint16_t * green,
|
|||
drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
|
||||
drmmode_ptr drmmode = drmmode_crtc->drmmode;
|
||||
|
||||
drmModeCrtcSetGamma(drmmode->fd, drmmode_crtc->mode_crtc->crtc_id,
|
||||
size, red, green, blue);
|
||||
if (drmmode_crtc->use_gamma_lut) {
|
||||
drmmode_set_gamma_lut(drmmode_crtc, red, green, blue, size);
|
||||
} else {
|
||||
drmModeCrtcSetGamma(drmmode->fd, drmmode_crtc->mode_crtc->crtc_id,
|
||||
size, red, green, blue);
|
||||
}
|
||||
}
|
||||
|
||||
static Bool
|
||||
|
@ -2266,6 +2299,8 @@ drmmode_crtc_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode, drmModeResPtr mode_res
|
|||
static const drmmode_prop_info_rec crtc_props[] = {
|
||||
[DRMMODE_CRTC_ACTIVE] = { .name = "ACTIVE" },
|
||||
[DRMMODE_CRTC_MODE_ID] = { .name = "MODE_ID" },
|
||||
[DRMMODE_CRTC_GAMMA_LUT] = { .name = "GAMMA_LUT" },
|
||||
[DRMMODE_CRTC_GAMMA_LUT_SIZE] = { .name = "GAMMA_LUT_SIZE" },
|
||||
};
|
||||
|
||||
crtc = xf86CrtcCreate(pScrn, &drmmode_crtc_funcs);
|
||||
|
@ -2302,6 +2337,39 @@ drmmode_crtc_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode, drmModeResPtr mode_res
|
|||
xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, MS_LOGLEVEL_DEBUG,
|
||||
"Allocated crtc nr. %d to this screen.\n", num);
|
||||
|
||||
/* If the GAMMA_LUT property is available, replace the server's default
|
||||
* gamma ramps with ones of the appropriate size. */
|
||||
if (drmmode_crtc->props[DRMMODE_CRTC_GAMMA_LUT_SIZE].prop_id) {
|
||||
Bool try_gamma_lut =
|
||||
xf86ReturnOptValBool(drmmode->Options, OPTION_USE_GAMMA_LUT, TRUE);
|
||||
uint64_t size = drmmode_crtc->props[DRMMODE_CRTC_GAMMA_LUT_SIZE].value;
|
||||
|
||||
if (try_gamma_lut && size != crtc->gamma_size) {
|
||||
uint16_t *gamma = malloc(3 * size * sizeof(uint16_t));
|
||||
|
||||
if (gamma) {
|
||||
free(crtc->gamma_red);
|
||||
|
||||
crtc->gamma_size = size;
|
||||
crtc->gamma_red = gamma;
|
||||
crtc->gamma_green = gamma + size;
|
||||
crtc->gamma_blue = gamma + size * 2;
|
||||
|
||||
drmmode_crtc->use_gamma_lut = TRUE;
|
||||
|
||||
xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, MS_LOGLEVEL_DEBUG,
|
||||
"Gamma ramp set to %ld entries on CRTC %d\n",
|
||||
size, num);
|
||||
} else {
|
||||
xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
|
||||
"Failed to allocate memory for %ld gamma ramp "
|
||||
"entries on CRTC %d. Falling back to legacy "
|
||||
"%d-entry mode.\n",
|
||||
size, num, crtc->gamma_size);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
|
|
@ -67,6 +67,8 @@ enum drmmode_connector_property {
|
|||
enum drmmode_crtc_property {
|
||||
DRMMODE_CRTC_ACTIVE,
|
||||
DRMMODE_CRTC_MODE_ID,
|
||||
DRMMODE_CRTC_GAMMA_LUT,
|
||||
DRMMODE_CRTC_GAMMA_LUT_SIZE,
|
||||
DRMMODE_CRTC__COUNT
|
||||
};
|
||||
|
||||
|
@ -199,6 +201,7 @@ typedef struct {
|
|||
Bool flipping_active;
|
||||
|
||||
Bool vrr_enabled;
|
||||
Bool use_gamma_lut;
|
||||
} drmmode_crtc_private_rec, *drmmode_crtc_private_ptr;
|
||||
|
||||
typedef struct {
|
||||
|
|
|
@ -81,6 +81,12 @@ For example:
|
|||
Option \*qZaphodHeads\*q \*qLVDS,VGA-0\*q
|
||||
will assign xrandr outputs LVDS and VGA-0 to this instance of the driver.
|
||||
.TP
|
||||
.BI "Option \*qUseGammaLUT\*q \*q" boolean \*q
|
||||
Enable or disable use of the GAMMA_LUT property, when available.
|
||||
When enabled, this option allows the driver to use gamma ramps with more
|
||||
entries, if supported by the kernel.
|
||||
Default: on.
|
||||
.TP
|
||||
.SH "SEE ALSO"
|
||||
@xservername@(@appmansuffix@), @xconfigfile@(@filemansuffix@), Xserver(@appmansuffix@),
|
||||
X(@miscmansuffix@)
|
||||
|
|
Loading…
Reference in New Issue