2020-10-20 23:19:55 +02:00
|
|
|
#define _POSIX_C_SOURCE 200112L
|
2019-10-30 21:08:31 +01:00
|
|
|
#include <assert.h>
|
|
|
|
#include <libliftoff.h>
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <time.h>
|
|
|
|
#include <unistd.h>
|
|
|
|
#include "libdrm_mock.h"
|
|
|
|
#include "log.h"
|
|
|
|
|
|
|
|
#define MAX_PLANES 128
|
|
|
|
#define MAX_LAYERS 128
|
|
|
|
|
2021-08-13 22:02:33 +02:00
|
|
|
static struct liftoff_layer *
|
2023-02-22 10:45:05 +01:00
|
|
|
add_layer(struct liftoff_output *output, int x, int y, uint32_t width, uint32_t height)
|
2019-10-30 21:08:31 +01:00
|
|
|
{
|
|
|
|
uint32_t fb_id;
|
|
|
|
struct liftoff_layer *layer;
|
|
|
|
|
|
|
|
layer = liftoff_layer_create(output);
|
|
|
|
fb_id = liftoff_mock_drm_create_fb(layer);
|
|
|
|
liftoff_layer_set_property(layer, "FB_ID", fb_id);
|
2023-02-16 21:33:36 +01:00
|
|
|
liftoff_layer_set_property(layer, "CRTC_X", (uint64_t)x);
|
|
|
|
liftoff_layer_set_property(layer, "CRTC_Y", (uint64_t)y);
|
|
|
|
liftoff_layer_set_property(layer, "CRTC_W", (uint64_t)width);
|
|
|
|
liftoff_layer_set_property(layer, "CRTC_H", (uint64_t)height);
|
2019-10-30 21:08:31 +01:00
|
|
|
liftoff_layer_set_property(layer, "SRC_X", 0);
|
|
|
|
liftoff_layer_set_property(layer, "SRC_Y", 0);
|
2023-02-16 21:33:36 +01:00
|
|
|
liftoff_layer_set_property(layer, "SRC_W", (uint64_t)width << 16);
|
|
|
|
liftoff_layer_set_property(layer, "SRC_H", (uint64_t)height << 16);
|
2019-10-30 21:08:31 +01:00
|
|
|
|
|
|
|
return layer;
|
|
|
|
}
|
|
|
|
|
2021-08-13 22:02:33 +02:00
|
|
|
int
|
|
|
|
main(int argc, char *argv[])
|
2019-10-30 21:08:31 +01:00
|
|
|
{
|
|
|
|
int opt;
|
|
|
|
size_t planes_len, layers_len;
|
|
|
|
struct timespec start, end;
|
|
|
|
struct liftoff_mock_plane *mock_planes[MAX_PLANES];
|
|
|
|
size_t i, j;
|
2023-02-16 21:33:36 +01:00
|
|
|
uint64_t plane_type;
|
2019-10-30 21:08:31 +01:00
|
|
|
int drm_fd;
|
2019-11-24 13:07:12 +01:00
|
|
|
struct liftoff_device *device;
|
2019-10-30 21:08:31 +01:00
|
|
|
struct liftoff_output *output;
|
|
|
|
struct liftoff_layer *layers[MAX_LAYERS];
|
|
|
|
drmModeAtomicReq *req;
|
2021-07-27 12:28:00 +02:00
|
|
|
int ret;
|
2023-02-16 20:03:42 +01:00
|
|
|
double dur_ms;
|
2019-10-30 21:08:31 +01:00
|
|
|
|
|
|
|
planes_len = 5;
|
|
|
|
layers_len = 10;
|
|
|
|
while ((opt = getopt(argc, argv, "p:l:")) != -1) {
|
|
|
|
switch (opt) {
|
|
|
|
case 'p':
|
2023-02-16 21:33:36 +01:00
|
|
|
planes_len = (size_t)atoi(optarg);
|
2019-10-30 21:08:31 +01:00
|
|
|
break;
|
|
|
|
case 'l':
|
2023-02-16 21:33:36 +01:00
|
|
|
layers_len = (size_t)atoi(optarg);
|
2019-10-30 21:08:31 +01:00
|
|
|
break;
|
|
|
|
default:
|
|
|
|
fprintf(stderr, "usage: %s [-p planes] [-l layers]\n",
|
|
|
|
argv[0]);
|
|
|
|
exit(EXIT_FAILURE);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-03-31 12:44:24 +02:00
|
|
|
liftoff_log_set_priority(LIFTOFF_SILENT);
|
2024-05-21 10:24:40 +02:00
|
|
|
liftoff_mock_verbose = false;
|
2019-10-30 21:08:31 +01:00
|
|
|
|
|
|
|
for (i = 0; i < planes_len; i++) {
|
|
|
|
plane_type = i == 0 ? DRM_PLANE_TYPE_PRIMARY :
|
|
|
|
DRM_PLANE_TYPE_OVERLAY;
|
|
|
|
mock_planes[i] = liftoff_mock_drm_create_plane(plane_type);
|
|
|
|
}
|
|
|
|
|
|
|
|
drm_fd = liftoff_mock_drm_open();
|
2019-11-24 13:07:12 +01:00
|
|
|
device = liftoff_device_create(drm_fd);
|
|
|
|
assert(device != NULL);
|
2019-10-30 21:08:31 +01:00
|
|
|
|
2021-02-23 18:01:38 +01:00
|
|
|
liftoff_device_register_all_planes(device);
|
|
|
|
|
2019-11-24 13:07:12 +01:00
|
|
|
output = liftoff_output_create(device, liftoff_mock_drm_crtc_id);
|
2019-10-30 21:08:31 +01:00
|
|
|
|
|
|
|
for (i = 0; i < layers_len; i++) {
|
|
|
|
/* Planes don't intersect, so the library can arrange them in
|
|
|
|
* any order. Testing all combinations takes more time. */
|
2023-02-22 10:45:05 +01:00
|
|
|
layers[i] = add_layer(output, (int)i * 100, (int)i * 100, 100, 100);
|
2019-10-30 21:08:31 +01:00
|
|
|
for (j = 0; j < planes_len; j++) {
|
|
|
|
if (j == 1) {
|
|
|
|
/* Make the lowest plane above the primary plane
|
|
|
|
* incompatible with all layers. A solution
|
|
|
|
* using all planes won't be reached, so the
|
|
|
|
* library will keep trying more combinations.
|
|
|
|
*/
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
liftoff_mock_plane_add_compatible_layer(mock_planes[j],
|
|
|
|
layers[i]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
clock_gettime(CLOCK_MONOTONIC, &start);
|
|
|
|
|
|
|
|
req = drmModeAtomicAlloc();
|
2024-05-14 13:59:39 +02:00
|
|
|
ret = liftoff_output_apply(output, req, 0, NULL);
|
2021-07-27 12:28:00 +02:00
|
|
|
assert(ret == 0);
|
2019-10-30 21:08:31 +01:00
|
|
|
drmModeAtomicFree(req);
|
|
|
|
|
|
|
|
clock_gettime(CLOCK_MONOTONIC, &end);
|
|
|
|
|
2023-02-16 20:03:42 +01:00
|
|
|
dur_ms = ((double)end.tv_sec - (double)start.tv_sec) * 1000 +
|
|
|
|
((double)end.tv_nsec - (double)start.tv_nsec) / 1000000;
|
2019-10-30 21:08:31 +01:00
|
|
|
printf("Plane allocation took %fms\n", dur_ms);
|
|
|
|
printf("Plane allocation performed %zu atomic test commits\n",
|
|
|
|
liftoff_mock_commit_count);
|
|
|
|
/* TODO: the mock libdrm library takes time to check atomic requests.
|
|
|
|
* This benchmark doesn't account for time spent in the mock library. */
|
|
|
|
printf("With 20µs per atomic test commit, plane allocation would take "
|
|
|
|
"%fms\n", dur_ms + liftoff_mock_commit_count * 0.02);
|
|
|
|
|
2019-11-24 13:07:12 +01:00
|
|
|
liftoff_device_destroy(device);
|
2019-10-30 21:08:31 +01:00
|
|
|
close(drm_fd);
|
|
|
|
}
|