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