mirror of
https://github.com/moonlight-stream/moonlight-embedded.git
synced 2025-07-02 15:56:02 +00:00
Only use atomic API for HDR streams on RK backend
This commit is contained in:
parent
eb46891f4c
commit
b1d111b5f7
133
src/video/rk.c
133
src/video/rk.c
@ -106,6 +106,7 @@ int crtc_height;
|
|||||||
RK_U32 frm_width;
|
RK_U32 frm_width;
|
||||||
RK_U32 frm_height;
|
RK_U32 frm_height;
|
||||||
int fb_x, fb_y, fb_width, fb_height;
|
int fb_x, fb_y, fb_width, fb_height;
|
||||||
|
bool atomic;
|
||||||
|
|
||||||
uint8_t last_colorspace = 0xFF;
|
uint8_t last_colorspace = 0xFF;
|
||||||
bool last_hdr_state = false;
|
bool last_hdr_state = false;
|
||||||
@ -138,21 +139,23 @@ struct {
|
|||||||
uint32_t handle;
|
uint32_t handle;
|
||||||
} frame_to_drm[MAX_FRAMES];
|
} frame_to_drm[MAX_FRAMES];
|
||||||
|
|
||||||
int set_atomic_property(drmModeAtomicReq *request, uint32_t id, drmModePropertyPtr *props, char *name, uint64_t value) {
|
int set_property(uint32_t id, uint32_t type, drmModePropertyPtr *props, char *name, uint64_t value) {
|
||||||
while (*props) {
|
while (*props) {
|
||||||
if (!strcasecmp(name, (*props)->name)) {
|
if (!strcasecmp(name, (*props)->name)) {
|
||||||
return drmModeAtomicAddProperty(request, id, (*props)->prop_id, value);
|
if (atomic)
|
||||||
}
|
return drmModeAtomicAddProperty(drm_request, id, (*props)->prop_id, value);
|
||||||
props++;
|
else
|
||||||
}
|
return drmModeObjectSetProperty(fd, id, type, (*props)->prop_id, value);
|
||||||
|
}
|
||||||
|
props++;
|
||||||
|
}
|
||||||
|
|
||||||
return -EINVAL;
|
fprintf(stderr, "Property '%s' not found\n", name);
|
||||||
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
void *display_thread(void *param) {
|
void *display_thread(void *param) {
|
||||||
|
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
while (!frm_eos) {
|
while (!frm_eos) {
|
||||||
int _fb_id;
|
int _fb_id;
|
||||||
|
|
||||||
@ -173,28 +176,16 @@ void *display_thread(void *param) {
|
|||||||
ret = pthread_mutex_unlock(&mutex);
|
ret = pthread_mutex_unlock(&mutex);
|
||||||
assert(!ret);
|
assert(!ret);
|
||||||
|
|
||||||
uint32_t v4l2_colorspace;
|
if (atomic) {
|
||||||
switch (last_colorspace) {
|
// We may need to modeset to apply colorspace changes when toggling HDR
|
||||||
default:
|
set_property(plane_id, DRM_MODE_OBJECT_PLANE, plane_props, "FB_ID", _fb_id);
|
||||||
fprintf(stderr, "Unknown frame colorspace: %d\n", last_colorspace);
|
ret = drmModeAtomicCommit(fd, drm_request, DRM_MODE_ATOMIC_ALLOW_MODESET, NULL);
|
||||||
/* fall-through */
|
} else {
|
||||||
case COLORSPACE_REC_601:
|
ret = drmModeSetPlane(fd, plane_id, crtc_id, _fb_id, 0,
|
||||||
v4l2_colorspace = V4L2_COLORSPACE_SMPTE170M;
|
fb_x, fb_y, fb_width, fb_height,
|
||||||
break;
|
0, 0, frm_width << 16, frm_height << 16);
|
||||||
case COLORSPACE_REC_709:
|
|
||||||
v4l2_colorspace = V4L2_COLORSPACE_REC709;
|
|
||||||
break;
|
|
||||||
case COLORSPACE_REC_2020:
|
|
||||||
v4l2_colorspace = V4L2_COLORSPACE_BT2020;
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
set_atomic_property(drm_request, plane_id, plane_props, "COLOR_SPACE", v4l2_colorspace);
|
assert(!ret);
|
||||||
set_atomic_property(drm_request, plane_id, plane_props, "EOTF", last_hdr_state ? 2 : 0); // PQ or SDR
|
|
||||||
set_atomic_property(drm_request, plane_id, plane_props, "FB_ID", _fb_id);
|
|
||||||
|
|
||||||
// We may need to modeset to apply colorspace changes when toggling HDR
|
|
||||||
ret = drmModeAtomicCommit(fd, drm_request, DRM_MODE_ATOMIC_NONBLOCK | DRM_MODE_ATOMIC_ALLOW_MODESET, NULL);
|
|
||||||
assert(!ret || errno == EBUSY);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
@ -297,20 +288,22 @@ void *frame_thread(void *param) {
|
|||||||
ret = mpi_api->control(mpi_ctx, MPP_DEC_SET_INFO_CHANGE_READY, NULL);
|
ret = mpi_api->control(mpi_ctx, MPP_DEC_SET_INFO_CHANGE_READY, NULL);
|
||||||
|
|
||||||
// Set atomic properties for the plane prior to the first commit
|
// Set atomic properties for the plane prior to the first commit
|
||||||
set_atomic_property(drm_request, plane_id, plane_props, "CRTC_ID", crtc_id);
|
if (atomic) {
|
||||||
set_atomic_property(drm_request, plane_id, plane_props, "SRC_X", 0 << 16);
|
set_property(plane_id, DRM_MODE_OBJECT_PLANE, plane_props, "CRTC_ID", crtc_id);
|
||||||
set_atomic_property(drm_request, plane_id, plane_props, "SRC_Y", 0 << 16);
|
set_property(plane_id, DRM_MODE_OBJECT_PLANE, plane_props, "SRC_X", 0 << 16);
|
||||||
set_atomic_property(drm_request, plane_id, plane_props, "SRC_W", frm_width << 16);
|
set_property(plane_id, DRM_MODE_OBJECT_PLANE, plane_props, "SRC_Y", 0 << 16);
|
||||||
set_atomic_property(drm_request, plane_id, plane_props, "SRC_H", frm_height << 16);
|
set_property(plane_id, DRM_MODE_OBJECT_PLANE, plane_props, "SRC_W", frm_width << 16);
|
||||||
set_atomic_property(drm_request, plane_id, plane_props, "CRTC_X", fb_x);
|
set_property(plane_id, DRM_MODE_OBJECT_PLANE, plane_props, "SRC_H", frm_height << 16);
|
||||||
set_atomic_property(drm_request, plane_id, plane_props, "CRTC_Y", fb_y);
|
set_property(plane_id, DRM_MODE_OBJECT_PLANE, plane_props, "CRTC_X", fb_x);
|
||||||
set_atomic_property(drm_request, plane_id, plane_props, "CRTC_W", fb_width);
|
set_property(plane_id, DRM_MODE_OBJECT_PLANE, plane_props, "CRTC_Y", fb_y);
|
||||||
set_atomic_property(drm_request, plane_id, plane_props, "CRTC_H", fb_height);
|
set_property(plane_id, DRM_MODE_OBJECT_PLANE, plane_props, "CRTC_W", fb_width);
|
||||||
set_atomic_property(drm_request, plane_id, plane_props, "ZPOS", 0);
|
set_property(plane_id, DRM_MODE_OBJECT_PLANE, plane_props, "CRTC_H", fb_height);
|
||||||
|
set_property(plane_id, DRM_MODE_OBJECT_PLANE, plane_props, "ZPOS", 0);
|
||||||
|
}
|
||||||
|
|
||||||
// Set atomic properties on the connector
|
// Set properties on the connector
|
||||||
set_atomic_property(drm_request, conn_id, conn_props, "allm_enable", 1); // HDMI ALLM (Game Mode)
|
set_property(conn_id, DRM_MODE_OBJECT_CONNECTOR, conn_props, "allm_enable", 1); // HDMI ALLM (Game Mode)
|
||||||
set_atomic_property(drm_request, conn_id, conn_props, "Colorspace", last_hdr_state ? DRM_MODE_COLORIMETRY_BT2020_RGB : DRM_MODE_COLORIMETRY_DEFAULT);
|
set_property(conn_id, DRM_MODE_OBJECT_CONNECTOR, conn_props, "Colorspace", last_hdr_state ? DRM_MODE_COLORIMETRY_BT2020_RGB : DRM_MODE_COLORIMETRY_DEFAULT);
|
||||||
} else {
|
} else {
|
||||||
// regular frame received
|
// regular frame received
|
||||||
|
|
||||||
@ -370,6 +363,11 @@ int rk_setup(int videoFormat, int width, int height, int redrawRate, void* conte
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// We need atomic plane properties for HDR, but atomic seems to perform quite bad
|
||||||
|
// on RK3588 for some reason. The performance of commits seems to go down the longer
|
||||||
|
// the stream runs. We'll use the legacy API for non-HDR streams as a workaround.
|
||||||
|
atomic = !!(videoFormat & VIDEO_FORMAT_MASK_10BIT);
|
||||||
|
|
||||||
MppCodingType mpp_type = (MppCodingType)format;
|
MppCodingType mpp_type = (MppCodingType)format;
|
||||||
ret = mpp_check_support_format(MPP_CTX_DEC, mpp_type);
|
ret = mpp_check_support_format(MPP_CTX_DEC, mpp_type);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
@ -444,10 +442,12 @@ int rk_setup(int videoFormat, int width, int height, int redrawRate, void* conte
|
|||||||
|
|
||||||
ret = drmSetClientCap(fd, DRM_CLIENT_CAP_UNIVERSAL_PLANES, 1);
|
ret = drmSetClientCap(fd, DRM_CLIENT_CAP_UNIVERSAL_PLANES, 1);
|
||||||
assert(!ret);
|
assert(!ret);
|
||||||
ret = drmSetClientCap(fd, DRM_CLIENT_CAP_ATOMIC, 1);
|
if (atomic) {
|
||||||
assert(!ret);
|
ret = drmSetClientCap(fd, DRM_CLIENT_CAP_ATOMIC, 1);
|
||||||
drm_request = drmModeAtomicAlloc();
|
assert(!ret);
|
||||||
assert(drm_request);
|
drm_request = drmModeAtomicAlloc();
|
||||||
|
assert(drm_request);
|
||||||
|
}
|
||||||
plane_resources = drmModeGetPlaneResources(fd);
|
plane_resources = drmModeGetPlaneResources(fd);
|
||||||
assert(plane_resources);
|
assert(plane_resources);
|
||||||
|
|
||||||
@ -598,18 +598,21 @@ void rk_cleanup() {
|
|||||||
free(pkt_buf);
|
free(pkt_buf);
|
||||||
|
|
||||||
// Undo the connector-wide changes we performed
|
// Undo the connector-wide changes we performed
|
||||||
drmModeAtomicSetCursor(drm_request, 0);
|
if (atomic)
|
||||||
set_atomic_property(drm_request, conn_id, conn_props, "HDR_OUTPUT_METADATA", 0);
|
drmModeAtomicSetCursor(drm_request, 0);
|
||||||
set_atomic_property(drm_request, conn_id, conn_props, "allm_enable", 0);
|
set_property(conn_id, DRM_MODE_OBJECT_CONNECTOR, conn_props, "HDR_OUTPUT_METADATA", 0);
|
||||||
set_atomic_property(drm_request, conn_id, conn_props, "Colorspace", DRM_MODE_COLORIMETRY_DEFAULT);
|
set_property(conn_id, DRM_MODE_OBJECT_CONNECTOR, conn_props, "allm_enable", 0);
|
||||||
drmModeAtomicCommit(fd, drm_request, DRM_MODE_ATOMIC_ALLOW_MODESET, NULL);
|
set_property(conn_id, DRM_MODE_OBJECT_CONNECTOR, conn_props, "Colorspace", DRM_MODE_COLORIMETRY_DEFAULT);
|
||||||
|
if (atomic)
|
||||||
|
drmModeAtomicCommit(fd, drm_request, DRM_MODE_ATOMIC_ALLOW_MODESET, NULL);
|
||||||
|
|
||||||
if (hdr_metadata_blob_id) {
|
if (hdr_metadata_blob_id) {
|
||||||
drmModeDestroyPropertyBlob(fd, hdr_metadata_blob_id);
|
drmModeDestroyPropertyBlob(fd, hdr_metadata_blob_id);
|
||||||
hdr_metadata_blob_id = 0;
|
hdr_metadata_blob_id = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
drmModeAtomicFree(drm_request);
|
if (atomic)
|
||||||
|
drmModeAtomicFree(drm_request);
|
||||||
drmModeFreePlane(ovr);
|
drmModeFreePlane(ovr);
|
||||||
drmModeFreePlaneResources(plane_resources);
|
drmModeFreePlaneResources(plane_resources);
|
||||||
drmModeFreeEncoder(encoder);
|
drmModeFreeEncoder(encoder);
|
||||||
@ -689,6 +692,28 @@ int rk_submit_decode_unit(PDECODE_UNIT decodeUnit) {
|
|||||||
} else {
|
} else {
|
||||||
fprintf(stderr, "HDR_OUTPUT_METADATA property is not supported by your display/kernel. Do you have an HDR display connected?\n");
|
fprintf(stderr, "HDR_OUTPUT_METADATA property is not supported by your display/kernel. Do you have an HDR display connected?\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Adjust plane EOTF property
|
||||||
|
set_property(plane_id, DRM_MODE_OBJECT_PLANE, plane_props, "EOTF", decodeUnit->hdrActive ? 2 : 0); // PQ or SDR
|
||||||
|
}
|
||||||
|
|
||||||
|
if (last_colorspace != decodeUnit->colorspace) {
|
||||||
|
uint32_t v4l2_colorspace;
|
||||||
|
switch (decodeUnit->colorspace) {
|
||||||
|
default:
|
||||||
|
fprintf(stderr, "Unknown frame colorspace: %d\n", decodeUnit->colorspace);
|
||||||
|
/* fall-through */
|
||||||
|
case COLORSPACE_REC_601:
|
||||||
|
v4l2_colorspace = V4L2_COLORSPACE_SMPTE170M;
|
||||||
|
break;
|
||||||
|
case COLORSPACE_REC_709:
|
||||||
|
v4l2_colorspace = V4L2_COLORSPACE_REC709;
|
||||||
|
break;
|
||||||
|
case COLORSPACE_REC_2020:
|
||||||
|
v4l2_colorspace = V4L2_COLORSPACE_BT2020;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
set_property(plane_id, DRM_MODE_OBJECT_PLANE, plane_props, "COLOR_SPACE", v4l2_colorspace);
|
||||||
}
|
}
|
||||||
|
|
||||||
last_colorspace = decodeUnit->colorspace;
|
last_colorspace = decodeUnit->colorspace;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user