From d3fb52c5a0b06ba89e03f6cbd2d1c33da324b65b Mon Sep 17 00:00:00 2001 From: Cameron Gutman Date: Sat, 3 Jan 2026 02:36:33 -0600 Subject: [PATCH] Check modifiers support in IN_FORMATS property As it turns out, there *are* in fact hardware vendors dumb enough to ship V4L2 decoders that output buffers which are unsupported by any plane on their display hardware. By checking modifiers, we can still fall back to GLES on GL_IS_SLOW=1 builds in this case. --- app/streaming/video/ffmpeg-renderers/drm.cpp | 131 ++++++++++++------- 1 file changed, 85 insertions(+), 46 deletions(-) diff --git a/app/streaming/video/ffmpeg-renderers/drm.cpp b/app/streaming/video/ffmpeg-renderers/drm.cpp index 1bb1acfc..b8d69ca4 100644 --- a/app/streaming/video/ffmpeg-renderers/drm.cpp +++ b/app/streaming/video/ffmpeg-renderers/drm.cpp @@ -1192,6 +1192,89 @@ bool DrmRenderer::addFbForFrame(AVFrame *frame, uint32_t* newFbId, bool testMode drmFrame = (AVDRMFrameDescriptor*)frame->data[0]; } + if (testMode) { + // Check if plane can actually be imported + bool formatMatch = false; + + // If we have an IN_FORMATS property, use that since it supports modifiers too + if (auto prop = m_VideoPlane.property("IN_FORMATS")) { + drmModePropertyBlobPtr blob = drmModeGetPropertyBlob(m_DrmFd, prop->initialValue()); + if (blob) { + auto *header = (struct drm_format_modifier_blob *)blob->data; + auto *modifiers = (struct drm_format_modifier *)((char *)header + header->modifiers_offset); + uint32_t *formats = (uint32_t *)((char *)header + header->formats_offset); + + for (uint32_t i = 0; i < header->count_modifiers; i++) { + if (modifiers[i].modifier == drmFrame->objects[0].format_modifier) { + for (uint32_t j = 0; j < header->count_formats && j < sizeof(modifiers[i].formats) * 8; j++) { + if (modifiers[i].formats & (1ULL << j)) { + if (formats[modifiers[i].offset + j] == drmFrame->layers[0].format) { + formatMatch = true; + break; + } + } + } + + if (formatMatch) { + break; + } + else { + // Do not break for this case even though we got a modifier + // match that did not appear to have our format in it. + // To handle greater than 64 formats, the same modifier may + // appear in the list more than once. + } + } + } + + drmModeFreePropertyBlob(blob); + } + else { + // This should never happen since IN_FORMATS is an immutable property + SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, + "drmModeGetPropertyBlob(IN_FORMATS) failed: %d", + errno); + } + } + else { + drmModePlanePtr videoPlane = drmModeGetPlane(m_DrmFd, m_VideoPlane.objectId()); + if (videoPlane) { + for (uint32_t i = 0; i < videoPlane->count_formats; i++) { + if (drmFrame->layers[0].format == videoPlane->formats[i]) { + formatMatch = true; + break; + } + } + + drmModeFreePlane(videoPlane); + } + else { + SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, + "drmModeGetPlane() failed: %d", + errno); + } + } + + if (formatMatch) { + SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, + "Selected DRM plane supports chosen decoding format and modifier: " FOURCC_FMT " %016" PRIx64, + FOURCC_FMT_ARGS(drmFrame->layers[0].format), + drmFrame->objects[0].format_modifier); + } + else { + SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, + "Selected DRM plane doesn't support chosen decoding format and modifier: " FOURCC_FMT " %016" PRIx64, + FOURCC_FMT_ARGS(drmFrame->layers[0].format), + drmFrame->objects[0].format_modifier); + + if (m_DrmPrimeBackend) { + SDL_assert(drmFrame == &mappedFrame); + m_BackendRenderer->unmapDrmPrimeFrame(drmFrame); + } + return false; + } + } + uint32_t handles[4] = {}; uint32_t pitches[4] = {}; uint32_t offsets[4] = {}; @@ -1243,55 +1326,11 @@ bool DrmRenderer::addFbForFrame(AVFrame *frame, uint32_t* newFbId, bool testMode if (err < 0) { SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, - "drmModeAddFB2[WithModifiers]() failed: %d (format: " FOURCC_FMT ")", - errno, - FOURCC_FMT_ARGS(drmFrame->layers[0].format)); + "drmModeAddFB2[WithModifiers]() failed: %d", + errno); return false; } - if (testMode) { - drmModePlanePtr videoPlane = drmModeGetPlane(m_DrmFd, m_VideoPlane.objectId()); - if (!videoPlane) { - SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, - "drmModeGetPlane() failed: %d", - errno); - drmModeRmFB(m_DrmFd, *newFbId); - return false; - } - - // Check if plane can actually be imported - bool formatMatch = false; - for (uint32_t i = 0; i < videoPlane->count_formats; i++) { - if (drmFrame->layers[0].format == videoPlane->formats[i]) { - formatMatch = true; - break; - } - } - - drmModeFreePlane(videoPlane); - - if (!formatMatch) { - SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, - "Selected DRM plane doesn't support chosen decoding format: " FOURCC_FMT, - FOURCC_FMT_ARGS(drmFrame->layers[0].format)); - drmModeRmFB(m_DrmFd, *newFbId); - return false; - } - - SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, - "Selected DRM plane supports chosen decoding format: " FOURCC_FMT, - FOURCC_FMT_ARGS(drmFrame->layers[0].format)); - - // TODO: We can also check the modifier support using the IN_FORMATS property, - // but checking format alone is probably enough for real world cases since we're - // either getting linear buffers from software mapping or DMA-BUFs from the - // hardware decoder. - // - // Hopefully no actual hardware vendors are dumb enough to ship display hardware - // or drivers that lack support for the format modifiers required by their own - // video decoders. - } - return true; }