[WIP] Implement DPMS get/setValue (Screen Off/On for KMS)
I added kms drm property set function. The code is dirty, but it works. Any suggestions for improvement?
It allows turn off/on screen.
For my case I use HDMI-0.
kmsprint -p
show:
Connector 0 (33) HDMI-A-1 (connected)
EDID (1) = blob-id 678 len 256 (immutable)
DPMS (2) = 0 (On) [On=0|Standby=1|Suspend=2|Off=3]
TILE (4) = blob-id 0 (immutable)
link-status (5) = 0 (Good) [Good=0|Bad=1]
Screen ON:
if (kmsDrmService.isAvailable()) {
// DPMS (2) = 3 (Off) [On=0|Standby=1|Suspend=2|Off=3]
kmsDrmService.setProperty(2, 0);
}
Screen OFF:
if (kmsDrmService.isAvailable()) {
// DPMS (2) = 0 (On) [On=0|Standby=1|Suspend=2|Off=3]
kmsDrmService.setProperty(2, 3);
}
Service:
static final KmsDrmService kmsDrmService = KmsDrmService();
/*
uint32_t KMS_DRM_isAvailable();
void KMS_DRM_setProperty(uint32_t propId, uint64_t value) ;
uint64_t KMS_DRM_getProperty(uint32_t propId);
*/
typedef KMS_DRM_setPropertyFuncType = ffi.Void Function(ffi.Uint32 propId, ffi.Uint64 value);
typedef KMS_DRM_setPropertyType = void Function(int propId, int value);
typedef KMS_DRM_isAvailableFuncType = ffi.Uint32 Function();
typedef KMS_DRM_isAvailableType = int Function();
class KmsDrmService {
final _KmsDrmService _service = _KmsDrmService.instance;
bool isAvailable() {
if (_service.KMS_DRM_isAvailable == null || _service.KMS_DRM_isAvailable!() == 0) {
return false;
}
return true;
}
void setProperty(int propId, int value) {
if (_service.KMS_DRM_setProperty == null) {
return;
}
_service.KMS_DRM_setProperty!(propId, value);
}
}
class _KmsDrmService {
final KMS_DRM_setPropertyType? KMS_DRM_setProperty;
final KMS_DRM_isAvailableType? KMS_DRM_isAvailable;
_KmsDrmService._constructor({required this.KMS_DRM_setProperty, required this.KMS_DRM_isAvailable});
factory _KmsDrmService._() {
final lib = ffi.DynamicLibrary.process();
try {
final KMS_DRM_setPropertyLFunc = lib.lookupFunction<KMS_DRM_setPropertyFuncType, KMS_DRM_setPropertyType>("KMS_DRM_setProperty");
final KMS_DRM_isAvailableLFunc = lib.lookupFunction<KMS_DRM_isAvailableFuncType, KMS_DRM_isAvailableType>("KMS_DRM_isAvailable");
return _KmsDrmService._constructor(
KMS_DRM_setProperty: KMS_DRM_setPropertyLFunc,
KMS_DRM_isAvailable: KMS_DRM_isAvailableLFunc,
);
} on ArgumentError {
return _KmsDrmService._constructor(
KMS_DRM_setProperty: null,
KMS_DRM_isAvailable: null,
);
}
}
static _KmsDrmService? _instance;
static _KmsDrmService get instance {
if (_instance == null) {
_instance = _KmsDrmService._();
}
return _instance!;
}
}
I used this example https://github.com/tomba/kmsxx/blob/master/utils/kmsblank.cpp#L77
Thanks for the contribution @DisDis !
I think providing support for DPMS & backlight is definitely useful, but a generic way to set KMS properties might be a bit too powerful. It's very easy to shoot yourself in the foot with that and it can easily conflict with flutter-pi's modesetting.
Might be better to provide an abstraction specifically for DPMS (and/or backlight). Just a package where you can do something like:
void main() async {
final dpms = await DPMS.getInstance(); // optionally allow passing the view id here, for multi-view
await dpms.setMode(PowerMode.on);
await Future.delayed(Duration(seconds: 5));
await dpms.setMode(PowerMode.standby);
// ...
}
For backlight, one could implement a platform interface for: https://github.com/aaassseee/screen_brightness/
Weston has its own little sub-library to help with backlight: https://gitlab.freedesktop.org/wayland/weston/-/blob/main/libweston/backend-drm/libbacklight.c, that could just be added to the flutter-pi source tree under third_party/libbacklight.
Hi @ardera. I implemented get/setDPMSValue. When this MR merge, I will start implement DPMS package in "flutter_packages"