nvkms: Implement CRTC_X/Y for primary planes

This is used by Gamescope for centring the game's buffer.

Adds a check to see if the `supportsWindowMode` cap is supported
for the main plane (EVO3+) and implements CRTC_X/Y for
NVKMS_MAIN_LAYER if it is supported.

This was not checked before, so CRTC_X could be specified on the main
layer, and the atomic commit would succeed, resulting in incorrect
output.
This commit is contained in:
Joshua Ashton 2022-05-18 03:27:43 +00:00
parent d8f3bcff92
commit c32515c11a
3 changed files with 21 additions and 0 deletions

View File

@ -71,6 +71,8 @@ struct NvKmsKapiDevice {
/* Device capabilities */
struct {
NvBool mainLayerSupportsWindowMode;
struct NvKmsCompositionCapabilities cursorCompositionCaps;
struct NvKmsCompositionCapabilities overlayCompositionCaps;

View File

@ -339,6 +339,9 @@ static NvBool KmsAllocateDevice(struct NvKmsKapiDevice *device)
device->hKmsDevice = paramsAlloc->reply.deviceHandle;
device->caps.mainLayerSupportsWindowMode =
paramsAlloc->reply.layerCaps[NVKMS_MAIN_LAYER].supportsWindowMode;
device->caps.cursorCompositionCaps =
paramsAlloc->reply.cursorCompositionCaps;
@ -2432,6 +2435,18 @@ static NvBool NvKmsKapiPrimaryLayerConfigToKms(
changed = TRUE;
}
if (layerRequestedConfig->flags.dstXYChanged || bFromKmsSetMode) {
/* If the main layer doesn't support window mode,
* then return false here to fail the commit/test. */
if (!device->caps.mainLayerSupportsWindowMode &&
(layerConfig->dstX != 0 || layerConfig->dstY != 0))
return NV_FALSE;
params->layer[NVKMS_MAIN_LAYER].outputPosition.val.x = layerConfig->dstX;
params->layer[NVKMS_MAIN_LAYER].outputPosition.val.y = layerConfig->dstY;
params->layer[NVKMS_MAIN_LAYER].outputPosition.specified = TRUE;
}
if (layerRequestedConfig->flags.srcXYChanged || bFromKmsSetMode) {
params->viewPortIn.point.x = layerConfig->srcX;
params->viewPortIn.point.y = layerConfig->srcY;

View File

@ -232,6 +232,10 @@ static NvBool InitModeOneHeadRequest(
pFlip->layer[NVKMS_MAIN_LAYER].sizeOut.val =
pFlip->layer[NVKMS_MAIN_LAYER].sizeIn.val;
pFlip->layer[NVKMS_MAIN_LAYER].outputPosition.specified = TRUE;
pFlip->layer[NVKMS_MAIN_LAYER].outputPosition.val.x = 0;
pFlip->layer[NVKMS_MAIN_LAYER].outputPosition.val.y = 0;
/* Disable other layers except Main */
for (layer = 0; layer < pDevEvo->head[head].numLayers; layer++) {