From 56f482a4c54057ba7dc2eb0ff44075003944c6a4 Mon Sep 17 00:00:00 2001 From: Hannes Winkler Date: Tue, 8 Sep 2020 23:24:11 +0200 Subject: [PATCH 1/3] log page flip timing --- include/flutter-pi.h | 19 +++++++++++++ src/flutter-pi.c | 66 ++++++++++++++++++++++++++++++++++++++------ src/plugins/gpiod.c | 1 + 3 files changed, 78 insertions(+), 8 deletions(-) diff --git a/include/flutter-pi.h b/include/flutter-pi.h index 018dbd45..60f8b212 100644 --- a/include/flutter-pi.h +++ b/include/flutter-pi.h @@ -464,6 +464,25 @@ int flutterpi_fill_view_properties( int rotation ); +int flutterpi_post_platform_task( + int (*callback)(void *userdata), + void *userdata +); + +int flutterpi_post_platform_task_with_time( + int (*callback)(void *userdata), + void *userdata, + uint64_t target_time_usec +); + +int flutterpi_sd_event_add_io( + sd_event_source **source_out, + int fd, + uint32_t events, + sd_event_io_handler_t callback, + void *userdata +); + int flutterpi_send_platform_message( const char *channel, const uint8_t *restrict message, diff --git a/src/flutter-pi.c b/src/flutter-pi.c index 70af7ee8..dc8e2202 100644 --- a/src/flutter-pi.c +++ b/src/flutter-pi.c @@ -132,10 +132,10 @@ SEE ALSO:\n\ struct flutterpi flutterpi; -static int post_platform_task( +/*static int flutterpi_post_platform_task( int (*callback)(void *userdata), void *userdata -); +);*/ static bool runs_platform_tasks_on_current_thread(void *userdata); @@ -442,7 +442,7 @@ static void on_frame_request( } if (reply_instantly) { - post_platform_task( + flutterpi_post_platform_task( on_execute_frame_request, NULL ); @@ -480,7 +480,7 @@ static int on_execute_platform_task( return 0; } -static int post_platform_task( +int flutterpi_post_platform_task( int (*callback)(void *userdata), void *userdata ) { @@ -558,7 +558,7 @@ static int on_execute_platform_task_with_time( return 0; } -static int post_platform_task_with_time( +int flutterpi_post_platform_task_with_time( int (*callback)(void *userdata), void *userdata, uint64_t target_time_usec @@ -621,6 +621,54 @@ static int post_platform_task_with_time( return ok; } +int flutterpi_sd_event_add_io( + sd_event_source **source_out, + int fd, + uint32_t events, + sd_event_io_handler_t callback, + void *userdata +) { + int ok; + + if (pthread_self() != flutterpi.event_loop_thread) { + pthread_mutex_lock(&flutterpi.event_loop_mutex); + } + + ok = sd_event_add_io( + flutterpi.event_loop, + source_out, + fd, + events, + callback, + userdata + ); + if (ok < 0) { + fprintf(stderr, "[flutter-pi] Could not add IO callback to event loop. sd_event_add_io: %s\n", strerror(-ok)); + return -ok; + } + + if (pthread_self() != flutterpi.event_loop_thread) { + ok = write(flutterpi.wakeup_event_loop_fd, (uint8_t[8]) {0, 0, 0, 0, 0, 0, 0, 1}, 8); + if (ok < 0) { + perror("[flutter-pi] Error arming main loop for io callback. write"); + ok = errno; + goto fail_unlock_event_loop; + } + } + + if (pthread_self() != flutterpi.event_loop_thread) { + pthread_mutex_unlock(&flutterpi.event_loop_mutex); + } + + return 0; + + + fail_unlock_event_loop: + if (pthread_self() != flutterpi.event_loop_thread) { + pthread_mutex_unlock(&flutterpi.event_loop_mutex); + } +} + /// flutter tasks static int on_execute_flutter_task( void *userdata @@ -658,7 +706,7 @@ static void on_post_flutter_task( *dup_task = task; - ok = post_platform_task_with_time( + ok = flutterpi_post_platform_task_with_time( on_execute_flutter_task, dup_task, target_time / 1000 @@ -762,7 +810,7 @@ int flutterpi_send_platform_message( msg->message_size = 0; } - ok = post_platform_task( + ok = flutterpi_post_platform_task( on_send_platform_message, msg ); @@ -819,7 +867,7 @@ int flutterpi_respond_to_platform_message( msg->message = 0; } - ok = post_platform_task( + ok = flutterpi_post_platform_task( on_send_platform_message, msg ); @@ -987,6 +1035,8 @@ static void on_pageflip_event( flutterpi.flutter.libflutter_engine.FlutterEngineTraceEventInstant("pageflip"); + printf("[%12.6f] pageflip ocurred at %12.6f\n", flutterpi.flutter.libflutter_engine.FlutterEngineGetCurrentTime() / 1000000000.0, sec + usec / 1000000.0); + cqueue_lock(&flutterpi.frame_queue); ok = cqueue_try_dequeue_locked(&flutterpi.frame_queue, &presented_frame); diff --git a/src/plugins/gpiod.c b/src/plugins/gpiod.c index 9b5f87c2..d67876b3 100644 --- a/src/plugins/gpiod.c +++ b/src/plugins/gpiod.c @@ -5,6 +5,7 @@ #include #include +#include #include #include From 1a49227c8166fc52d431f6b49c4ac646fb569fb8 Mon Sep 17 00:00:00 2001 From: Hannes Winkler Date: Sat, 12 Sep 2020 18:20:20 +0200 Subject: [PATCH 2/3] debugging - make sure DRM properties are supported before requesting them - verbose atomic commits and pageflips --- include/modesetting.h | 14 ++++ src/compositor.c | 75 ++++++++++++++++++-- src/modesetting.c | 158 ++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 241 insertions(+), 6 deletions(-) diff --git a/include/modesetting.h b/include/modesetting.h index 1c022c75..0be49a11 100644 --- a/include/modesetting.h +++ b/include/modesetting.h @@ -86,6 +86,20 @@ int drmdev_configure( const drmModeModeInfo *mode ); +int drmdev_plane_supports_rotation_value( + struct drmdev *drmdev, + uint32_t plane_id, + int drm_rotation, + bool *result +); + +int drmdev_plane_supports_zpos_value( + struct drmdev *drmdev, + uint32_t plane_id, + int zpos, + bool *result +); + int drmdev_new_atomic_req( struct drmdev *drmdev, struct drmdev_atomic_req **req_out diff --git a/src/compositor.c b/src/compositor.c index 72cdad38..27f5327a 100644 --- a/src/compositor.c +++ b/src/compositor.c @@ -351,6 +351,7 @@ static int rendertarget_gbm_present( struct rendertarget_gbm *gbm_target; struct gbm_bo *next_front_bo; uint32_t next_front_fb_id; + bool supported; int ok; gbm_target = &target->gbm; @@ -368,8 +369,41 @@ static int rendertarget_gbm_present( drmdev_atomic_req_put_plane_property(atomic_req, drm_plane_id, "CRTC_Y", 0); drmdev_atomic_req_put_plane_property(atomic_req, drm_plane_id, "CRTC_W", flutterpi.display.width); drmdev_atomic_req_put_plane_property(atomic_req, drm_plane_id, "CRTC_H", flutterpi.display.height); - drmdev_atomic_req_put_plane_property(atomic_req, drm_plane_id, "rotation", DRM_MODE_ROTATE_0); - drmdev_atomic_req_put_plane_property(atomic_req, drm_plane_id, "zpos", zpos); + + ok = drmdev_plane_supports_rotation_value(atomic_req->drmdev, drm_plane_id, DRM_MODE_ROTATE_0, &supported); + if (ok != 0) return ok; + + if (supported) { + drmdev_atomic_req_put_plane_property(atomic_req, drm_plane_id, "rotation", DRM_MODE_ROTATE_0); + } else { + static bool printed = false; + + if (!printed) { + fprintf(stderr, + "[compositor] GPU does not support reflecting the screen in Y-direction.\n" + " This is required for rendering into hardware overlay planes though.\n" + " Any UI that is drawn in overlay planes will look upside down.\n" + ); + printed = true; + } + } + + ok = drmdev_plane_supports_zpos_value(atomic_req->drmdev, drm_plane_id, zpos, &supported); + if (ok != 0) return ok; + + if (supported) { + drmdev_atomic_req_put_plane_property(atomic_req, drm_plane_id, "zpos", zpos); + } else { + static bool printed = false; + + if (!printed) { + fprintf(stderr, + "[compositor] GPU does not supported the desired HW plane order.\n" + " Some UI layers may be invisible.\n" + ); + printed = true; + } + } // TODO: move this to the page flip handler. // We can only be sure the buffer can be released when the buffer swap @@ -438,6 +472,7 @@ static int rendertarget_nogbm_present( int zpos ) { struct rendertarget_nogbm *nogbm_target; + bool supported; int ok; nogbm_target = &target->nogbm; @@ -456,8 +491,38 @@ static int rendertarget_nogbm_present( drmdev_atomic_req_put_plane_property(req, drm_plane_id, "CRTC_Y", 0); drmdev_atomic_req_put_plane_property(req, drm_plane_id, "CRTC_W", flutterpi.display.width); drmdev_atomic_req_put_plane_property(req, drm_plane_id, "CRTC_H", flutterpi.display.height); - drmdev_atomic_req_put_plane_property(req, drm_plane_id, "rotation", DRM_MODE_ROTATE_0 | DRM_MODE_REFLECT_Y); - drmdev_atomic_req_put_plane_property(req, drm_plane_id, "zpos", zpos); + + ok = drmdev_plane_supports_rotation_value(req->drmdev, drm_plane_id, DRM_MODE_ROTATE_0 | DRM_MODE_REFLECT_Y, &supported); + if (ok != 0) return ok; + + if (supported) { + drmdev_atomic_req_put_plane_property(req, drm_plane_id, "rotation", DRM_MODE_ROTATE_0 | DRM_MODE_REFLECT_Y); + } else { + static bool printed = false; + + if (!printed) { + fprintf(stderr, + "[compositor] GPU does not support reflecting the screen in Y-direction.\n" + " This is required for rendering into hardware overlay planes though.\n" + " Any UI that is drawn in overlay planes will look upside down.\n" + ); + printed = true; + } + } + + if (supported) { + drmdev_atomic_req_put_plane_property(req, drm_plane_id, "zpos", zpos); + } else { + static bool printed = false; + + if (!printed) { + fprintf(stderr, + "[compositor] GPU does not supported the desired HW plane order.\n" + " Some UI layers may be invisible.\n" + ); + printed = true; + } + } return 0; } @@ -1003,8 +1068,6 @@ int compositor_remove_view_callbacks(int64_t view_id) { return 0; } -/// DRM HARDWARE PLANE RESERVATION - /// COMPOSITOR INITIALIZATION int compositor_initialize(struct drmdev *drmdev) { compositor.drmdev = drmdev; diff --git a/src/modesetting.c b/src/modesetting.c index 1118e013..f2b3ac5a 100644 --- a/src/modesetting.c +++ b/src/modesetting.c @@ -559,6 +559,159 @@ int drmdev_configure( return 0; } +int drmdev_plane_supports_rotation_value( + struct drmdev *drmdev, + uint32_t plane_id, + int drm_rotation, + bool *result +) { + struct drm_plane *plane; + + plane = NULL; + for (int i = 0; i < drmdev->n_planes; i++) { + if (drmdev->planes[i].plane->plane_id == plane_id) { + plane = drmdev->planes + i; + break; + } + } + + if (plane == NULL) { + return EINVAL; + } + + int prop_index = -1; + for (int i = 0; i < plane->props->count_props; i++) { + if (strcmp(plane->props_info[i]->name, "rotation") == 0) { + prop_index = i; + break; + } + } + + if (prop_index == -1) { + *result = false; + return 0; + } + + if (plane->props_info[prop_index]->flags & DRM_MODE_PROP_IMMUTABLE) { + *result = false; + return 0; + } + + if (!(plane->props_info[prop_index]->flags & DRM_MODE_PROP_BITMASK)) { + *result = false; + return 0; + } + + static bool printed = false; + uint64_t value = drm_rotation; + + if (!printed) { + printf("supported \"rotation\" bits: "); + } + + for (int i = 0; i < plane->props_info[prop_index]->count_enums; i++) { + value &= ~plane->props_info[prop_index]->enums[i].value; + + if (!printed) { + printf("%s, ", plane->props_info[prop_index]->enums[i].name); + } + } + + if (!printed) { + printf("\n"); + printed = true; + } + + + *result = !value; + return 0; +} + +int drmdev_plane_supports_zpos_value( + struct drmdev *drmdev, + uint32_t plane_id, + int zpos, + bool *result +) { + struct drm_plane *plane; + + plane = NULL; + for (int i = 0; i < drmdev->n_planes; i++) { + if (drmdev->planes[i].plane->plane_id == plane_id) { + plane = drmdev->planes + i; + break; + } + } + + if (plane == NULL) { + return EINVAL; + } + + int prop_index = -1; + for (int i = 0; i < plane->props->count_props; i++) { + if (strcmp(plane->props_info[i]->name, "zpos") == 0) { + prop_index = i; + break; + } + } + + if (prop_index == -1) { + *result = false; + return 0; + } + + if (plane->props_info[prop_index]->flags & DRM_MODE_PROP_IMMUTABLE) { + *result = false; + return 0; + } + + if (plane->props_info[prop_index]->count_values != 2) { + *result = false; + return 0; + } + + static bool printed = false; + + if (plane->props_info[prop_index]->flags & DRM_MODE_PROP_SIGNED_RANGE) { + int64_t min = *((int64_t*) (plane->props_info[prop_index]->values + 0)); + int64_t max = *((int64_t*) (plane->props_info[prop_index]->values + 1)); + + if ((min <= zpos) && (max >= zpos)) { + *result = true; + return 0; + } else { + *result = false; + return 0; + } + + if (!printed) { + printf("zpos range: %lld <= zpos <= %lld\n", min, max); + printed = true; + } + } else if (plane->props_info[prop_index]->flags & DRM_MODE_PROP_RANGE) { + uint64_t min = plane->props_info[prop_index]->values[0]; + uint64_t max = plane->props_info[prop_index]->values[1]; + + if (!printed) { + printf("zpos range: %llu <= zpos <= %llu\n", min, max); + printed = true; + } + + if ((min <= zpos) && (max >= zpos)) { + *result = true; + return 0; + } else { + *result = false; + return 0; + } + } else { + *result = false; + return 0; + } + + return 0; +} + int drmdev_new_atomic_req( struct drmdev *drmdev, struct drmdev_atomic_req **req_out @@ -610,6 +763,7 @@ int drmdev_atomic_req_put_connector_property( for (int i = 0; i < req->drmdev->selected_connector->props->count_props; i++) { drmModePropertyRes *prop = req->drmdev->selected_connector->props_info[i]; if (strcmp(prop->name, name) == 0) { + printf("atomic_request %p: conn %3d: [\"%s\"] = %llu\n", req->atomic_req, req->drmdev->selected_connector->connector->connector_id, name, value); ok = drmModeAtomicAddProperty( req->atomic_req, req->drmdev->selected_connector->connector->connector_id, @@ -643,6 +797,7 @@ int drmdev_atomic_req_put_crtc_property( for (int i = 0; i < req->drmdev->selected_crtc->props->count_props; i++) { drmModePropertyRes *prop = req->drmdev->selected_crtc->props_info[i]; if (strcmp(prop->name, name) == 0) { + printf("atomic_request %p: crtc %3d: [\"%s\"] = %llu\n", req->atomic_req, req->drmdev->selected_crtc->crtc->crtc_id, name, value); ok = drmModeAtomicAddProperty( req->atomic_req, req->drmdev->selected_crtc->crtc->crtc_id, @@ -695,6 +850,7 @@ int drmdev_atomic_req_put_plane_property( prop = plane->props_info[i]; if (strcmp(prop->name, name) == 0) { + printf("atomic_request %p: plane %3d: [\"%s\"] = %llu\n", req->atomic_req, plane_id, name, value); ok = drmModeAtomicAddProperty( req->atomic_req, plane_id, @@ -773,6 +929,8 @@ int drmdev_atomic_req_commit( drmdev_lock(req->drmdev); + printf("committing %p%s\n", req->atomic_req, flags & DRM_MODE_ATOMIC_NONBLOCK ? " nonblocking" : ""); + ok = drmModeAtomicCommit(req->drmdev->fd, req->atomic_req, flags, userdata); if (ok < 0) { ok = errno; From 35dcb4d09ab7fa7900f44769584abeaf99227cbb Mon Sep 17 00:00:00 2001 From: Hannes Winkler Date: Sun, 13 Sep 2020 20:32:53 +0200 Subject: [PATCH 3/3] - more rebust DRM interfacing - fix "Error handling platform message." --- Makefile | 2 - include/modesetting.h | 24 ++++- src/compositor.c | 48 ++++++++-- src/flutter-pi.c | 1 - src/modesetting.c | 199 +++++++++++++++++++++++++++++------------- src/platformchannel.c | 3 +- 6 files changed, 204 insertions(+), 73 deletions(-) diff --git a/Makefile b/Makefile index 8c563bf2..9a569e0e 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,5 @@ REAL_CFLAGS = -I./include $(shell pkg-config --cflags gbm libdrm glesv2 egl libsystemd libinput libudev) \ -DBUILD_TEXT_INPUT_PLUGIN \ - -DBUILD_GPIOD_PLUGIN \ - -DBUILD_SPIDEV_PLUGIN \ -DBUILD_TEST_PLUGIN \ -DBUILD_OMXPLAYER_VIDEO_PLAYER_PLUGIN \ -O0 -ggdb \ diff --git a/include/modesetting.h b/include/modesetting.h index 0be49a11..eba5db1e 100644 --- a/include/modesetting.h +++ b/include/modesetting.h @@ -86,17 +86,35 @@ int drmdev_configure( const drmModeModeInfo *mode ); -int drmdev_plane_supports_rotation_value( +int drmdev_plane_supports_setting_rotation_value( struct drmdev *drmdev, uint32_t plane_id, int drm_rotation, bool *result ); -int drmdev_plane_supports_zpos_value( +int drmdev_plane_get_min_zpos_value( struct drmdev *drmdev, uint32_t plane_id, - int zpos, + int64_t *min_zpos_out +); + +int drmdev_plane_get_max_zpos_value( + struct drmdev *drmdev, + uint32_t plane_id, + int64_t *max_zpos_out +); + +int drmdev_plane_supports_setting_zpos( + struct drmdev *drmdev, + uint32_t plane_id, + bool *result +); + +int drmdev_plane_supports_setting_zpos_value( + struct drmdev *drmdev, + uint32_t plane_id, + int64_t zpos, bool *result ); diff --git a/src/compositor.c b/src/compositor.c index 27f5327a..859361b3 100644 --- a/src/compositor.c +++ b/src/compositor.c @@ -370,7 +370,7 @@ static int rendertarget_gbm_present( drmdev_atomic_req_put_plane_property(atomic_req, drm_plane_id, "CRTC_W", flutterpi.display.width); drmdev_atomic_req_put_plane_property(atomic_req, drm_plane_id, "CRTC_H", flutterpi.display.height); - ok = drmdev_plane_supports_rotation_value(atomic_req->drmdev, drm_plane_id, DRM_MODE_ROTATE_0, &supported); + ok = drmdev_plane_supports_setting_rotation_value(atomic_req->drmdev, drm_plane_id, DRM_MODE_ROTATE_0, &supported); if (ok != 0) return ok; if (supported) { @@ -388,7 +388,7 @@ static int rendertarget_gbm_present( } } - ok = drmdev_plane_supports_zpos_value(atomic_req->drmdev, drm_plane_id, zpos, &supported); + ok = drmdev_plane_supports_setting_zpos_value(atomic_req->drmdev, drm_plane_id, zpos, &supported); if (ok != 0) return ok; if (supported) { @@ -492,7 +492,7 @@ static int rendertarget_nogbm_present( drmdev_atomic_req_put_plane_property(req, drm_plane_id, "CRTC_W", flutterpi.display.width); drmdev_atomic_req_put_plane_property(req, drm_plane_id, "CRTC_H", flutterpi.display.height); - ok = drmdev_plane_supports_rotation_value(req->drmdev, drm_plane_id, DRM_MODE_ROTATE_0 | DRM_MODE_REFLECT_Y, &supported); + ok = drmdev_plane_supports_setting_rotation_value(req->drmdev, drm_plane_id, DRM_MODE_ROTATE_0 | DRM_MODE_REFLECT_Y, &supported); if (ok != 0) return ok; if (supported) { @@ -509,6 +509,9 @@ static int rendertarget_nogbm_present( printed = true; } } + + ok = drmdev_plane_supports_setting_zpos_value(req->drmdev, drm_plane_id, zpos, &supported); + if (ok != 0) return ok; if (supported) { drmdev_atomic_req_put_plane_property(req, drm_plane_id, "zpos", zpos); @@ -774,10 +777,32 @@ static bool on_present_layers( ok = drmdev_atomic_req_put_modeset_props(req, &req_flags); if (ok != 0) return false; + int64_t max_zpos = 0; + for_each_unreserved_plane_in_atomic_req(req, plane) { if (plane->type == DRM_PLANE_TYPE_CURSOR) { // make sure the cursor is in front of everything - drmdev_atomic_req_put_plane_property(req, plane->plane->plane_id, "zpos", 2); + int64_t max_zpos; + bool supported; + + ok = drmdev_plane_get_max_zpos_value(req->drmdev, plane->plane->plane_id, &max_zpos); + if (ok != 0) { + printf("[compositor] Could not move cursor to front. Mouse cursor may be invisible. drmdev_plane_get_max_zpos_value: %s\n", strerror(ok)); + continue; + } + + ok = drmdev_plane_supports_setting_zpos_value(req->drmdev, plane->plane->plane_id, max_zpos, &supported); + if (ok != 0) { + printf("[compositor] Could not move cursor to front. Mouse cursor may be invisible. drmdev_plane_supports_setting_zpos_value: %s\n", strerror(ok)); + continue; + } + + if (supported) { + drmdev_atomic_req_put_plane_property(req, plane->plane->plane_id, "zpos", max_zpos); + } else { + printf("[compositor] Could not move cursor to front. Mouse cursor may be invisible. drmdev_plane_supports_setting_zpos_value: %s\n", strerror(ok)); + continue; + } } } @@ -930,6 +955,17 @@ static bool on_present_layers( } } } + + int64_t min_zpos; + for_each_unreserved_plane_in_atomic_req(req, plane) { + if (plane->type == DRM_PLANE_TYPE_PRIMARY) { + ok = drmdev_plane_get_min_zpos_value(req->drmdev, plane->plane->plane_id, &min_zpos); + if (ok != 0) { + min_zpos = 0; + } + break; + } + } for (int i = 0; i < layers_count; i++) { if (layers[i]->type == kFlutterLayerContentTypeBackingStore) { @@ -964,7 +1000,7 @@ static bool on_present_layers( 0, compositor->drmdev->selected_mode->hdisplay, compositor->drmdev->selected_mode->vdisplay, - plane->type == DRM_PLANE_TYPE_PRIMARY ? 0 : 1 + i + min_zpos ); if (ok != 0) { fprintf(stderr, "[compositor] Could not present backing store. rendertarget->present: %s\n", strerror(ok)); @@ -982,7 +1018,7 @@ static bool on_present_layers( (int) round(layers[i]->offset.y), (int) round(layers[i]->size.width), (int) round(layers[i]->size.height), - i, + i + min_zpos, cb_data->userdata ); if (ok != 0) { diff --git a/src/flutter-pi.c b/src/flutter-pi.c index dc8e2202..438bd012 100644 --- a/src/flutter-pi.c +++ b/src/flutter-pi.c @@ -1035,7 +1035,6 @@ static void on_pageflip_event( flutterpi.flutter.libflutter_engine.FlutterEngineTraceEventInstant("pageflip"); - printf("[%12.6f] pageflip ocurred at %12.6f\n", flutterpi.flutter.libflutter_engine.FlutterEngineGetCurrentTime() / 1000000000.0, sec + usec / 1000000.0); cqueue_lock(&flutterpi.frame_queue); diff --git a/src/modesetting.c b/src/modesetting.c index f2b3ac5a..226d6c56 100644 --- a/src/modesetting.c +++ b/src/modesetting.c @@ -559,11 +559,9 @@ int drmdev_configure( return 0; } -int drmdev_plane_supports_rotation_value( +static struct drm_plane *get_plane_by_id( struct drmdev *drmdev, - uint32_t plane_id, - int drm_rotation, - bool *result + uint32_t plane_id ) { struct drm_plane *plane; @@ -575,18 +573,40 @@ int drmdev_plane_supports_rotation_value( } } + return plane; +} + +static int get_plane_property_index_by_name( + struct drm_plane *plane, + const char *property_name +) { if (plane == NULL) { - return EINVAL; + return -1; } - + int prop_index = -1; for (int i = 0; i < plane->props->count_props; i++) { - if (strcmp(plane->props_info[i]->name, "rotation") == 0) { + if (strcmp(plane->props_info[i]->name, property_name) == 0) { prop_index = i; break; } } + return prop_index; +} + +int drmdev_plane_supports_setting_rotation_value( + struct drmdev *drmdev, + uint32_t plane_id, + int drm_rotation, + bool *result +) { + struct drm_plane *plane = get_plane_by_id(drmdev, plane_id); + if (plane == NULL) { + return EINVAL; + } + + int prop_index = get_plane_property_index_by_name(plane, "rotation"); if (prop_index == -1) { *result = false; return 0; @@ -602,59 +622,28 @@ int drmdev_plane_supports_rotation_value( return 0; } - static bool printed = false; uint64_t value = drm_rotation; - if (!printed) { - printf("supported \"rotation\" bits: "); - } - for (int i = 0; i < plane->props_info[prop_index]->count_enums; i++) { - value &= ~plane->props_info[prop_index]->enums[i].value; - - if (!printed) { - printf("%s, ", plane->props_info[prop_index]->enums[i].name); - } - } - - if (!printed) { - printf("\n"); - printed = true; + value &= ~(1 << plane->props_info[prop_index]->enums[i].value); } - *result = !value; return 0; } -int drmdev_plane_supports_zpos_value( +int drmdev_plane_supports_setting_zpos_value( struct drmdev *drmdev, uint32_t plane_id, - int zpos, + int64_t zpos, bool *result ) { - struct drm_plane *plane; - - plane = NULL; - for (int i = 0; i < drmdev->n_planes; i++) { - if (drmdev->planes[i].plane->plane_id == plane_id) { - plane = drmdev->planes + i; - break; - } - } - + struct drm_plane *plane = get_plane_by_id(drmdev, plane_id); if (plane == NULL) { return EINVAL; } - int prop_index = -1; - for (int i = 0; i < plane->props->count_props; i++) { - if (strcmp(plane->props_info[i]->name, "zpos") == 0) { - prop_index = i; - break; - } - } - + int prop_index = get_plane_property_index_by_name(plane, "zpos"); if (prop_index == -1) { *result = false; return 0; @@ -670,8 +659,6 @@ int drmdev_plane_supports_zpos_value( return 0; } - static bool printed = false; - if (plane->props_info[prop_index]->flags & DRM_MODE_PROP_SIGNED_RANGE) { int64_t min = *((int64_t*) (plane->props_info[prop_index]->values + 0)); int64_t max = *((int64_t*) (plane->props_info[prop_index]->values + 1)); @@ -683,20 +670,10 @@ int drmdev_plane_supports_zpos_value( *result = false; return 0; } - - if (!printed) { - printf("zpos range: %lld <= zpos <= %lld\n", min, max); - printed = true; - } } else if (plane->props_info[prop_index]->flags & DRM_MODE_PROP_RANGE) { uint64_t min = plane->props_info[prop_index]->values[0]; uint64_t max = plane->props_info[prop_index]->values[1]; - if (!printed) { - printf("zpos range: %llu <= zpos <= %llu\n", min, max); - printed = true; - } - if ((min <= zpos) && (max >= zpos)) { *result = true; return 0; @@ -712,6 +689,113 @@ int drmdev_plane_supports_zpos_value( return 0; } +int drmdev_plane_get_min_zpos_value( + struct drmdev *drmdev, + uint32_t plane_id, + int64_t *min_zpos_out +) { + struct drm_plane *plane = get_plane_by_id(drmdev, plane_id); + if (plane == NULL) { + return EINVAL; + } + + int prop_index = get_plane_property_index_by_name(plane, "zpos"); + if (prop_index == -1) { + return EINVAL; + } + + if (plane->props_info[prop_index]->count_values != 2) { + return EINVAL; + } + + if (plane->props_info[prop_index]->flags & DRM_MODE_PROP_SIGNED_RANGE) { + int64_t min = *((int64_t*) (plane->props_info[prop_index]->values + 0)); + + *min_zpos_out = min; + return 0; + } else if (plane->props_info[prop_index]->flags & DRM_MODE_PROP_RANGE) { + uint64_t min = plane->props_info[prop_index]->values[0]; + + *min_zpos_out = (int64_t) min; + return 0; + } else { + return EINVAL; + } + + return EINVAL; +} + +int drmdev_plane_get_max_zpos_value( + struct drmdev *drmdev, + uint32_t plane_id, + int64_t *max_zpos_out +) { + struct drm_plane *plane = get_plane_by_id(drmdev, plane_id); + if (plane == NULL) { + return EINVAL; + } + + int prop_index = get_plane_property_index_by_name(plane, "zpos"); + if (prop_index == -1) { + return EINVAL; + } + + if (plane->props_info[prop_index]->count_values != 2) { + return EINVAL; + } + + if (plane->props_info[prop_index]->flags & DRM_MODE_PROP_SIGNED_RANGE) { + int64_t max = *((int64_t*) (plane->props_info[prop_index]->values + 1)); + + *max_zpos_out = max; + return 0; + } else if (plane->props_info[prop_index]->flags & DRM_MODE_PROP_RANGE) { + uint64_t max = plane->props_info[prop_index]->values[1]; + + *max_zpos_out = (int64_t) max; + return 0; + } else { + return EINVAL; + } + + return EINVAL; +} + +int drmdev_plane_supports_setting_zpos( + struct drmdev *drmdev, + uint32_t plane_id, + bool *result +) { + struct drm_plane *plane = get_plane_by_id(drmdev, plane_id); + if (plane == NULL) { + return EINVAL; + } + + int prop_index = get_plane_property_index_by_name(plane, "zpos"); + if (prop_index == -1) { + *result = false; + return 0; + } + + if (plane->props_info[prop_index]->count_values != 2) { + *result = false; + return 0; + } + + if (plane->props_info[prop_index]->flags & DRM_MODE_PROP_IMMUTABLE) { + *result = false; + return 0; + } + + if (!(plane->props_info[prop_index]->flags & (DRM_MODE_PROP_RANGE | DRM_MODE_PROP_SIGNED_RANGE))) { + *result = false; + return 0; + } + + *result = true; + return 0; +} + int drmdev_new_atomic_req( struct drmdev *drmdev, struct drmdev_atomic_req **req_out @@ -763,7 +847,6 @@ int drmdev_atomic_req_put_connector_property( for (int i = 0; i < req->drmdev->selected_connector->props->count_props; i++) { drmModePropertyRes *prop = req->drmdev->selected_connector->props_info[i]; if (strcmp(prop->name, name) == 0) { - printf("atomic_request %p: conn %3d: [\"%s\"] = %llu\n", req->atomic_req, req->drmdev->selected_connector->connector->connector_id, name, value); ok = drmModeAtomicAddProperty( req->atomic_req, req->drmdev->selected_connector->connector->connector_id, @@ -797,7 +880,6 @@ int drmdev_atomic_req_put_crtc_property( for (int i = 0; i < req->drmdev->selected_crtc->props->count_props; i++) { drmModePropertyRes *prop = req->drmdev->selected_crtc->props_info[i]; if (strcmp(prop->name, name) == 0) { - printf("atomic_request %p: crtc %3d: [\"%s\"] = %llu\n", req->atomic_req, req->drmdev->selected_crtc->crtc->crtc_id, name, value); ok = drmModeAtomicAddProperty( req->atomic_req, req->drmdev->selected_crtc->crtc->crtc_id, @@ -850,7 +932,6 @@ int drmdev_atomic_req_put_plane_property( prop = plane->props_info[i]; if (strcmp(prop->name, name) == 0) { - printf("atomic_request %p: plane %3d: [\"%s\"] = %llu\n", req->atomic_req, plane_id, name, value); ok = drmModeAtomicAddProperty( req->atomic_req, plane_id, @@ -929,8 +1010,6 @@ int drmdev_atomic_req_commit( drmdev_lock(req->drmdev); - printf("committing %p%s\n", req->atomic_req, flags & DRM_MODE_ATOMIC_NONBLOCK ? " nonblocking" : ""); - ok = drmModeAtomicCommit(req->drmdev->fd, req->atomic_req, flags, userdata); if (ok < 0) { ok = errno; diff --git a/src/platformchannel.c b/src/platformchannel.c index 59ec0d73..774be991 100644 --- a/src/platformchannel.c +++ b/src/platformchannel.c @@ -959,7 +959,8 @@ int platch_encode(struct platch_obj *object, uint8_t **buffer_out, size_t *size_ ok = platch_write_value_to_buffer_json(&(object->json_value), &buffer_cursor); if (ok != 0) goto free_buffer_and_return_ok; break; - case kJSONMethodCall: ; + case kJSONMethodCall: + case kJSONMethodCallResponse: ; size -= 1; ok = platch_write_value_to_buffer_json(&jsroot, &buffer_cursor); if (ok != 0) goto free_buffer_and_return_ok;