7#error "Configuration error"
14#include "private/qvideotexturehelper_p.h"
19#include <qpa/qplatformnativeinterface.h>
25#if __has_include("drm/drm_fourcc.h")
26#include <drm/drm_fourcc.h>
27#elif __has_include("libdrm/drm_fourcc.h")
28#include <libdrm/drm_fourcc.h>
31#define fourcc_code(a, b, c, d) ((uint32_t)(a) | ((uint32_t)(b) << 8) | \
32 ((uint32_t)(c) << 16) | ((uint32_t)(d) << 24))
34#define DRM_FORMAT_RGBA8888 fourcc_code('R', 'A', '2', '4')
35#define DRM_FORMAT_RGB888 fourcc_code('R', 'G', '2', '4')
36#define DRM_FORMAT_RG88 fourcc_code('R', 'G', '8', '8')
37#define DRM_FORMAT_ABGR8888 fourcc_code('A', 'B', '2', '4')
38#define DRM_FORMAT_BGR888 fourcc_code('B', 'G', '2', '4')
39#define DRM_FORMAT_GR88 fourcc_code('G', 'R', '8', '8')
40#define DRM_FORMAT_R8 fourcc_code('R', '8', ' ', ' ')
41#define DRM_FORMAT_R16 fourcc_code('R', '1', '6', ' ')
42#define DRM_FORMAT_RGB565 fourcc_code('R', 'G', '1', '6')
43#define DRM_FORMAT_RG1616 fourcc_code('R', 'G', '3', '2')
44#define DRM_FORMAT_GR1616 fourcc_code('G', 'R', '3', '2')
45#define DRM_FORMAT_BGRA1010102 fourcc_code('B', 'A', '3', '0')
49#include <libavutil/hwcontext_vaapi.h>
53#include <va/va_drmcommon.h>
56#include <EGL/eglext.h>
70#if G_BYTE_ORDER == G_LITTLE_ENDIAN
108 static constexpr quint32 format[] = { rgba_fourcc, 0, 0, 0 };
168VAAPITextureConverter::VAAPITextureConverter(
QRhi *rhi)
169 : TextureConverterBackend(
nullptr)
171 qCDebug(qLHWAccelVAAPI) <<
">>>> Creating VAAPI HW accelerator";
174 qWarning() <<
"VAAPITextureConverter: No rhi or non openGL based RHI";
182 qCDebug(qLHWAccelVAAPI) <<
" no GL context, disabling";
187 eglDisplay = pni->nativeResourceForIntegration(
"egldisplay");
191 qCDebug(qLHWAccelVAAPI) <<
" no egl display, disabling";
194 eglImageTargetTexture2D = eglGetProcAddress(
"glEGLImageTargetTexture2DOES");
196 qCDebug(qLHWAccelVAAPI) <<
" no eglImageTargetTexture2D, disabling";
204VAAPITextureConverter::~VAAPITextureConverter()
209TextureSet *VAAPITextureConverter::getTextures(AVFrame *
frame)
212 if (
frame->format != AV_PIX_FMT_VAAPI || !eglDisplay) {
213 qCDebug(qLHWAccelVAAPI) <<
"format/egl error" <<
frame->format << eglDisplay;
217 if (!
frame->hw_frames_ctx)
220 auto *fCtx = (AVHWFramesContext *)
frame->hw_frames_ctx->data;
221 auto *
ctx = fCtx->device_ctx;
225 auto *vaCtx = (AVVAAPIDeviceContext *)
ctx->hwctx;
226 auto vaDisplay = vaCtx->display;
228 qCDebug(qLHWAccelVAAPI) <<
" no VADisplay, disabling";
232 VASurfaceID vaSurface = (uintptr_t)
frame->data[3];
234 VADRMPRIMESurfaceDescriptor prime = {};
235 if (vaExportSurfaceHandle(vaDisplay, vaSurface,
236 VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME_2,
237 VA_EXPORT_SURFACE_READ_ONLY |
238#ifdef VA_EXPORT_USE_LAYERS
239 VA_EXPORT_SURFACE_SEPARATE_LAYERS,
241 VA_EXPORT_SURFACE_COMPOSED_LAYERS,
243 &prime) != VA_STATUS_SUCCESS)
245 qWarning() <<
"vaExportSurfaceHandle failed";
251 for (uint32_t
i = 0;
i < prime.num_objects; ++
i)
252 close(prime.objects[
i].fd);
256 vaSyncSurface(vaDisplay, vaSurface);
264 bool needsConversion;
267 if (!drm_formats || needsConversion) {
268 qWarning() <<
"can't use DMA transfer for pixel format" <<
fmt << qtFormat;
274 for (; nPlanes < 5; ++nPlanes) {
275 if (drm_formats[nPlanes] == 0)
279 nPlanes =
desc->nplanes;
285 GLuint glTextures[4] = {};
286 functions.glGenTextures(nPlanes, glTextures);
287 for (
int i = 0;
i < nPlanes; ++
i) {
288#ifdef VA_EXPORT_USE_LAYERS
291 if (prime.layers[
i].drm_format != drm_formats[
i]) {
292 qWarning() <<
"expected DRM format check failed expected"
293 <<
Qt::hex << drm_formats[
i] <<
"got" << prime.layers[
i].drm_format;
301 EGL_LINUX_DRM_FOURCC_EXT, (EGLint)drm_formats[
i],
304 EGL_DMA_BUF_PLANE0_FD_EXT, prime.objects[prime.layers[
LAYER].object_index[
PLANE]].fd,
305 EGL_DMA_BUF_PLANE0_OFFSET_EXT, (EGLint)prime.layers[
LAYER].offset[
PLANE],
306 EGL_DMA_BUF_PLANE0_PITCH_EXT, (EGLint)prime.layers[
LAYER].pitch[
PLANE],
309 images[
i] = eglCreateImage(eglDisplay, EGL_NO_CONTEXT, EGL_LINUX_DMA_BUF_EXT,
nullptr, img_attr);
312 if (
error == EGL_BAD_MATCH) {
313 qWarning() <<
"eglCreateImage failed for plane" <<
i <<
"with error code EGL_BAD_MATCH, "
314 "disabling hardware acceleration. This could indicate an EGL implementation issue."
315 "\nVAAPI driver: " << vaQueryVendorString(vaDisplay)
316 <<
"\nEGL vendor:" << eglQueryString(eglDisplay, EGL_VENDOR);
321 qWarning() <<
"eglCreateImage failed for plane" <<
i <<
"with error code" <<
error;
326 functions.glBindTexture(GL_TEXTURE_2D, glTextures[
i]);
328 PFNGLEGLIMAGETARGETTEXTURE2DOESPROC eglImageTargetTexture2D = (PFNGLEGLIMAGETARGETTEXTURE2DOESPROC)this->eglImageTargetTexture2D;
329 eglImageTargetTexture2D(GL_TEXTURE_2D,
images[
i]);
332 qWarning() <<
"eglImageTargetTexture2D failed with error code" <<
error;
335 for (
int i = 0;
i < nPlanes; ++
i) {
337 functions.glBindTexture(GL_TEXTURE_2D, 0);
338 eglDestroyImage(eglDisplay,
images[
i]);
341 VAAPITextureSet *textureSet =
new VAAPITextureSet;
342 textureSet->nPlanes = nPlanes;
343 textureSet->rhi = rhi;
344 textureSet->glContext = glContext;
346 for (
int i = 0;
i < 4; ++
i)
347 textureSet->textures[
i] = glTextures[
i];
static QVideoFrameFormat::PixelFormat toQtPixelFormat(AVPixelFormat avPixelFormat, bool *needsConversion=nullptr)
static AVPixelFormat format(AVFrame *frame)
QOpenGLContext * glContext
qint64 textureHandle(QRhi *, int plane) override
static QPlatformNativeInterface * platformNativeInterface()
QString platformName
The name of the underlying platform plugin.
The QOpenGLFunctions class provides cross-platform access to the OpenGL ES 2.0 API.
void glDeleteTextures(GLsizei n, const GLuint *textures)
Convenience function that calls glDeleteTextures(n, textures).
\variable QRhiGles2InitParams::format
\inmodule QtGuiPrivate \inheaderfile rhi/qrhi.h
bool makeThreadLocalNativeContextCurrent()
With OpenGL this makes the OpenGL context current on the current thread.
Implementation backend() const
const QRhiNativeHandles * nativeHandles()
\macro QT_RESTRICTED_CAST_FROM_ASCII
static const quint32 * fourccFromPixelFormat(const QVideoFrameFormat::PixelFormat format)
Combined button and popup list for selecting options.
const TextureDescription * textureDescription(QVideoFrameFormat::PixelFormat format)
QTextStream & hex(QTextStream &stream)
Calls QTextStream::setIntegerBase(16) on stream and returns stream.
DBusConnection const char DBusError * error
#define DRM_FORMAT_ABGR8888
#define DRM_FORMAT_GR1616
#define DRM_FORMAT_RGBA8888
#define DRM_FORMAT_RG1616
#define Q_LOGGING_CATEGORY(name,...)
#define qCDebug(category,...)
GLuint const GLuint GLuint const GLuint * textures
typedef GLenum(GL_APIENTRYP PFNGLGETGRAPHICSRESETSTATUSKHRPROC)(void)
GLint GLsizei GLsizei GLenum format
QVideoFrameFormat::PixelFormat fmt
QList< QImage > images
[6]