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