drm_prime: fix use of formats with modifiers

Similar to handles the modifiers must be supplied for each plane of the
format or a framebuffer cannot be created.

Use the format_modifier tied to the object used for the plane to fix use
of formats with modifiers.

Also fix the improper use of the DRM_MODE_FB_MODIFIERS-flag for formats
without modifiers.

This fixes playback of videos decoded by e.g. rpivid into a NV12 format
using SAND128 modifer on RPi using the drmprime-overlay interop.

Signed-off-by: Jonas Karlman <jonas@kwiboo.se>
This commit is contained in:
Jonas Karlman 2024-07-09 15:31:45 +00:00 committed by Philip Langdale
parent d06f3d39cb
commit 84c18f6b96
1 changed files with 21 additions and 16 deletions

View File

@ -19,6 +19,7 @@
#include <unistd.h>
#include <xf86drm.h>
#include <xf86drmMode.h>
#include <drm_fourcc.h>
#include <drm_mode.h>
#include "common/common.h"
@ -36,7 +37,8 @@ int drm_prime_create_framebuffer(struct mp_log *log, int fd,
uint32_t offsets[4] = { 0 };
uint32_t handles[4] = { 0 };
uint64_t modifiers[4] = { 0 };
int ret, layer_fd;
uint32_t flags = 0;
int ret;
if (descriptor && descriptor->nb_layers) {
*framebuffer = (struct drm_prime_framebuffer){0};
@ -49,17 +51,17 @@ int drm_prime_create_framebuffer(struct mp_log *log, int fd,
object, descriptor->objects[object].fd);
goto fail;
}
modifiers[object] = descriptor->objects[object].format_modifier;
}
layer = &descriptor->layers[0];
for (int plane = 0; plane < AV_DRM_MAX_PLANES; plane++) {
layer_fd = framebuffer->gem_handles[layer->planes[plane].object_index];
if (layer_fd && layer->planes[plane].pitch) {
if (plane < layer->nb_planes) {
int object = layer->planes[plane].object_index;
pitches[plane] = layer->planes[plane].pitch;
offsets[plane] = layer->planes[plane].offset;
handles[plane] = layer_fd;
handles[plane] = framebuffer->gem_handles[object];
modifiers[plane] = descriptor->objects[object].format_modifier;
} else {
pitches[plane] = 0;
offsets[plane] = 0;
@ -68,23 +70,26 @@ int drm_prime_create_framebuffer(struct mp_log *log, int fd,
}
}
if (modifiers[0] && modifiers[0] != DRM_FORMAT_MOD_INVALID) {
flags = DRM_MODE_FB_MODIFIERS;
}
ret = drmModeAddFB2WithModifiers(fd, width, height, layer->format,
handles, pitches, offsets,
modifiers, &framebuffer->fb_id,
DRM_MODE_FB_MODIFIERS);
if (ret < 0) {
handles, pitches, offsets, modifiers,
&framebuffer->fb_id, flags);
if (ret) {
ret = drmModeAddFB2(fd, width, height, layer->format,
handles, pitches, offsets,
&framebuffer->fb_id, 0);
if (ret < 0) {
mp_err(log, "Failed to create framebuffer with drmModeAddFB2 on layer %d: %s\n",
0, mp_strerror(errno));
goto fail;
}
}
if (ret) {
mp_err(log, "Failed to create framebuffer on layer %d: %s\n",
0, mp_strerror(errno));
goto fail;
}
for (int plane = 0; plane < AV_DRM_MAX_PLANES; plane++) {
drm_prime_add_handle_ref(handle_refs, framebuffer->gem_handles[plane]);
for (int object = 0; object < descriptor->nb_objects; object++) {
drm_prime_add_handle_ref(handle_refs, framebuffer->gem_handles[object]);
}
}