Skip to content

Commit

Permalink
extend the API to export frame buffers using DRM PRIME file descriptors
Browse files Browse the repository at this point in the history
Export frame buffers, providing applications like those based on libegt
with DRM PRIME file descriptors. Hence applications can next pass these
DRM PRIME file descriptors down to libm2d, which finally use them to
import the frame buffers created by libplanes so the GPU can ultimately
render into these frame buffers.

Signed-off-by: Cyrille Pitchen <[email protected]>
Signed-off-by: Ludovic Desroches <[email protected]>
  • Loading branch information
CyrillePitchen authored and ldesroches committed Feb 6, 2025
1 parent c7bcfd5 commit cc92dcd
Show file tree
Hide file tree
Showing 5 changed files with 81 additions and 1 deletion.
2 changes: 2 additions & 0 deletions include/planes/kms.h
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,8 @@ struct kms_framebuffer {
uint32_t handle;
uint32_t id;

int prime_fd;

void *ptr;
};

Expand Down
19 changes: 19 additions & 0 deletions include/planes/plane.h
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,8 @@ struct plane_data
struct kms_framebuffer** fbs;
/** The framebuffer. Must call plane_map() to allocate this. */
void** bufs;
/** The DRM PRIME file descriptor. Must call plane_fb_export() to set this. */
int* prime_fds;
unsigned int front_buf;
/** The number of framebuffers. */
uint32_t buffer_count;
Expand Down Expand Up @@ -376,6 +378,23 @@ int plane_fb_map(struct plane_data* plane);
*/
void plane_fb_unmap(struct plane_data* plane);

/**
* Export the framebuffer using a DRM PRIME file descriptor.
*
* @param plane The plane.
*/
int plane_fb_export(struct plane_data* plane);

/**
* Opposite of plane_fb_export().
*
* @param plane The plane.
*
* @note Like plane_fb_unmap(), plane_fb_unexport() is automatically called from
* plane_free() through plane_fb_free().
*/
void plane_fb_unexport(struct plane_data* plane);

/**
* Reallocate the framebuffer to the specified height, width, and format.
*
Expand Down
24 changes: 24 additions & 0 deletions src/kms-framebuffer.c
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ struct kms_framebuffer *kms_framebuffer_create(struct kms_device *device,
fb->width = width;
fb->height = height;
fb->format = format;
fb->prime_fd = -1;

memset(&args, 0, sizeof(args));
args.width = width;
Expand Down Expand Up @@ -244,3 +245,26 @@ void kms_framebuffer_unmap(struct kms_framebuffer *fb)
fb->ptr = NULL;
}
}

int kms_framebuffer_export(struct kms_framebuffer *fb, int *prime_fd)
{
struct kms_device *device = fb->device;
struct drm_prime_handle args;
int err;

if (fb->prime_fd != -1) {
*prime_fd = fb->prime_fd;
return 0;
}

memset(&args, 0, sizeof(args));
args.handle = fb->handle;

err = drmIoctl(device->fd, DRM_IOCTL_PRIME_HANDLE_TO_FD, &args);
if (err < 0)
return -errno;

*prime_fd = fb->prime_fd = args.fd;

return 0;
}
1 change: 1 addition & 0 deletions src/p_kms.h
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ struct kms_framebuffer *kms_framebuffer_create(struct kms_device *device,
void kms_framebuffer_free(struct kms_framebuffer *fb);
int kms_framebuffer_map(struct kms_framebuffer *fb, void **ptrp);
void kms_framebuffer_unmap(struct kms_framebuffer *fb);
int kms_framebuffer_export(struct kms_framebuffer *fb, int *prime_fd);

struct kms_screen *kms_screen_create(struct kms_device *device, uint32_t id);
void kms_screen_free(struct kms_screen *screen);
Expand Down
36 changes: 35 additions & 1 deletion src/plane.c
Original file line number Diff line number Diff line change
Expand Up @@ -90,9 +90,10 @@ struct plane_data* plane_create_buffered(struct kms_device* device, int type,

plane->fbs = calloc(buffer_count, sizeof(struct kms_framebuffer*));
plane->bufs = calloc(buffer_count, sizeof(void*));
plane->prime_fds = calloc(buffer_count, sizeof(int));
plane->gem_names = calloc(buffer_count, sizeof(uint32_t*));

if (!plane->fbs || !plane->bufs || !plane->gem_names) {
if (!plane->fbs || !plane->bufs || !plane->prime_fds || !plane->gem_names) {
LOG("error: failed to allocate plane\n");
goto abort;
}
Expand Down Expand Up @@ -137,6 +138,7 @@ struct plane_data* plane_create_buffered(struct kms_device* device, int type,
goto abort;
}
}
plane->prime_fds[fb] = -1;
}

plane->index = index;
Expand Down Expand Up @@ -168,6 +170,7 @@ static void plane_fb_free(struct plane_data* plane)
uint32_t fb;

plane_fb_unmap(plane);
plane_fb_unexport(plane);

for (fb = 0; fb < plane->buffer_count; fb++) {
if (plane->fbs[fb]) {
Expand All @@ -186,6 +189,8 @@ void plane_free(struct plane_data* plane)
free(plane->fbs);
if (plane->bufs)
free(plane->bufs);
if (plane->prime_fds)
free(plane->prime_fds);
if (plane->gem_names)
free(plane->gem_names);
free(plane);
Expand Down Expand Up @@ -465,6 +470,35 @@ void plane_fb_unmap(struct plane_data* plane)
}
}

int plane_fb_export(struct plane_data* plane)
{
uint32_t fb;

for (fb = 0; fb < plane->buffer_count; fb++) {
if (plane->prime_fds[fb] == -1) {
int err;

err = kms_framebuffer_export(plane->fbs[fb], &plane->prime_fds[fb]);
if (err < 0)
{
LOG("error: kms_framebuffer_export() failed: %s\n",
strerror(-err));
return err;
}
}
}

return 0;
}

void plane_fb_unexport(struct plane_data* plane)
{
uint32_t fb;

for (fb = 0; fb < plane->buffer_count; fb++)
plane->prime_fds[fb] = -1;
}

int plane_flip(struct plane_data* plane, uint32_t target)
{
plane->front_buf = target;
Expand Down

0 comments on commit cc92dcd

Please sign in to comment.