25#include <ossia/detail/dylib_loader.hpp>
27#include <QOpenGLContext>
28#include <QtGui/qpa/qplatformnativeinterface.h>
30#if __has_include(<QtGui/qopenglextrafunctions.h>)
31#include <QOpenGLExtraFunctions>
34#include <private/qrhi_p.h>
46struct EglDmaBufImporter
49 static constexpr uint32_t EGL_NONE_ = 0x3038;
50 static constexpr uint32_t EGL_WIDTH_ = 0x3057;
51 static constexpr uint32_t EGL_HEIGHT_ = 0x3056;
52 static constexpr uint32_t EGL_EXTENSIONS_ = 0x3055;
53 static constexpr uint32_t EGL_LINUX_DMA_BUF_EXT_ = 0x3270;
54 static constexpr uint32_t EGL_LINUX_DRM_FOURCC_EXT_ = 0x3271;
55 static constexpr uint32_t EGL_DMA_BUF_PLANE0_FD_EXT_ = 0x3272;
56 static constexpr uint32_t EGL_DMA_BUF_PLANE0_OFFSET_EXT_ = 0x3273;
57 static constexpr uint32_t EGL_DMA_BUF_PLANE0_PITCH_EXT_ = 0x3274;
58 static constexpr uint32_t EGL_DMA_BUF_PLANE0_MODIFIER_LO_EXT_ = 0x3443;
59 static constexpr uint32_t EGL_DMA_BUF_PLANE0_MODIFIER_HI_EXT_ = 0x3444;
61 static constexpr uint32_t EGL_DMA_BUF_PLANE1_FD_EXT_ = 0x3275;
62 static constexpr uint32_t EGL_DMA_BUF_PLANE1_OFFSET_EXT_ = 0x3276;
63 static constexpr uint32_t EGL_DMA_BUF_PLANE1_PITCH_EXT_ = 0x3277;
64 static constexpr uint32_t EGL_DMA_BUF_PLANE1_MODIFIER_LO_EXT_ = 0x3445;
65 static constexpr uint32_t EGL_DMA_BUF_PLANE1_MODIFIER_HI_EXT_ = 0x3446;
67 static constexpr uint32_t EGL_DMA_BUF_PLANE2_FD_EXT_ = 0x3278;
68 static constexpr uint32_t EGL_DMA_BUF_PLANE2_OFFSET_EXT_ = 0x3279;
69 static constexpr uint32_t EGL_DMA_BUF_PLANE2_PITCH_EXT_ = 0x327A;
70 static constexpr uint32_t EGL_DMA_BUF_PLANE2_MODIFIER_LO_EXT_ = 0x3447;
71 static constexpr uint32_t EGL_DMA_BUF_PLANE2_MODIFIER_HI_EXT_ = 0x3448;
76 using FN_eglGetCurrentDisplay =
void* (*)(
void);
77 using FN_eglGetCurrentContext =
void* (*)(
void);
78 using FN_eglQueryString =
const char* (*)(
void* dpy,
int name);
79 using FN_eglCreateImage
80 =
void* (*)(
void* dpy,
void* ctx, uint32_t target,
81 void* clientBuffer,
const intptr_t* attribs);
82 using FN_eglCreateImageKHR
83 =
void* (*)(
void* dpy,
void* ctx, uint32_t target,
84 void* clientBuffer,
const int32_t* attribs);
85 using FN_eglDestroyImage =
unsigned int (*)(
void* dpy,
void* image);
86 using FN_eglDestroyImageKHR =
unsigned int (*)(
void* dpy,
void* image);
88 using FN_glEGLImageTargetTexture2DOES
89 = void (*)(
unsigned int target,
void* image);
93 std::optional<ossia::dylib_loader> m_lib;
94 void* m_display{
nullptr};
95 bool m_useKhrEntry{
false};
97 FN_eglGetCurrentDisplay m_getCurrentDisplay{};
98 FN_eglQueryString m_queryString{};
99 FN_eglCreateImage m_createImage{};
100 FN_eglCreateImageKHR m_createImageKHR{};
101 FN_eglDestroyImage m_destroyImage{};
102 FN_eglDestroyImageKHR m_destroyImageKHR{};
103 FN_glEGLImageTargetTexture2DOES m_eglImageTargetTexture{};
110 void* image{
nullptr};
116 static bool isAvailable(QRhi& rhi)
noexcept
118 if(rhi.backend() != QRhi::OpenGLES2)
121 auto* ctx = QOpenGLContext::currentContext();
130 if(!ctx->nativeInterface<QNativeInterface::QEGLContext>())
135 auto getCurDpy =
reinterpret_cast<FN_eglGetCurrentDisplay
>(
136 ctx->getProcAddress(
"eglGetCurrentDisplay"));
140 void* dpy = getCurDpy();
144 auto queryString =
reinterpret_cast<FN_eglQueryString
>(
145 ctx->getProcAddress(
"eglQueryString"));
148 const char* exts = queryString(dpy,
int(EGL_EXTENSIONS_));
156 if(!std::strstr(exts,
"EGL_EXT_image_dma_buf_import_modifiers"))
162 if(!ctx->hasExtension(QByteArrayLiteral(
"GL_OES_EGL_image")))
170 bool init(QRhi& rhi)
noexcept
172 auto* ctx = QOpenGLContext::currentContext();
178 m_lib.emplace(std::vector<std::string_view>{
179 "libEGL.so.1",
"libEGL.so"});
187 = m_lib->symbol<FN_eglGetCurrentDisplay>(
"eglGetCurrentDisplay");
188 m_queryString = m_lib->symbol<FN_eglQueryString>(
"eglQueryString");
193 m_createImage = m_lib->symbol<FN_eglCreateImage>(
"eglCreateImage");
194 m_destroyImage = m_lib->symbol<FN_eglDestroyImage>(
"eglDestroyImage");
195 if(!m_createImage || !m_destroyImage)
198 = m_lib->symbol<FN_eglCreateImageKHR>(
"eglCreateImageKHR");
200 = m_lib->symbol<FN_eglDestroyImageKHR>(
"eglDestroyImageKHR");
201 m_useKhrEntry = m_createImageKHR && m_destroyImageKHR;
209 m_eglImageTargetTexture
210 =
reinterpret_cast<FN_glEGLImageTargetTexture2DOES
>(
211 ctx->getProcAddress(
"glEGLImageTargetTexture2DOES"));
212 if(!m_eglImageTargetTexture)
215 m_display = m_getCurrentDisplay ? m_getCurrentDisplay() : nullptr;
226 void cleanupPlane(PlaneImport& p)
noexcept
232 if(m_destroyImageKHR && m_display)
233 m_destroyImageKHR(m_display, p.image);
237 if(m_destroyImage && m_display)
238 m_destroyImage(m_display, p.image);
249 bool bindPlane(
unsigned int glTexture,
const PlaneImport& p)
noexcept
251 if(!p.image || !m_eglImageTargetTexture || glTexture == 0)
253 auto* ctx = QOpenGLContext::currentContext();
256 auto* funcs = ctx->extraFunctions();
259 constexpr unsigned int GL_TEXTURE_2D_v = 0x0DE1;
260 funcs->glBindTexture(GL_TEXTURE_2D_v, glTexture);
261 while(funcs->glGetError() != 0u)
263 m_eglImageTargetTexture(GL_TEXTURE_2D_v, p.image);
268 if(
const unsigned int err = funcs->glGetError(); err != 0u)
270 qWarning() <<
"EglDmaBufImporter: glEGLImageTargetTexture2DOES(GL_TEXTURE_2D)"
271 "failed with GL error"
273 <<
"- the buffer is likely samplable only as "
274 "GL_TEXTURE_EXTERNAL_OES";
286 PlaneImport& out,
unsigned int glTexture,
int fd, uint64_t modifier,
287 ptrdiff_t offset, ptrdiff_t pitch, uint32_t drm_fourcc,
int w,
int h)
290 if(!m_display || !m_eglImageTargetTexture || fd < 0)
297 const uint32_t mod_lo = uint32_t(modifier & 0xFFFFFFFFu);
298 const uint32_t mod_hi = uint32_t((modifier >> 32) & 0xFFFFFFFFu);
303 = {(intptr_t)EGL_WIDTH_,
305 (intptr_t)EGL_HEIGHT_,
307 (intptr_t)EGL_LINUX_DRM_FOURCC_EXT_,
308 intptr_t(drm_fourcc),
309 (intptr_t)EGL_DMA_BUF_PLANE0_FD_EXT_,
311 (intptr_t)EGL_DMA_BUF_PLANE0_OFFSET_EXT_,
313 (intptr_t)EGL_DMA_BUF_PLANE0_PITCH_EXT_,
315 (intptr_t)EGL_DMA_BUF_PLANE0_MODIFIER_LO_EXT_,
317 (intptr_t)EGL_DMA_BUF_PLANE0_MODIFIER_HI_EXT_,
319 (intptr_t)EGL_NONE_};
325 int khrAttribs[
sizeof(attribs) /
sizeof(attribs[0])];
326 for(std::size_t i = 0; i <
sizeof(attribs) /
sizeof(attribs[0]); ++i)
327 khrAttribs[i] =
int(attribs[i]);
328 img = m_createImageKHR(
330 EGL_LINUX_DMA_BUF_EXT_,
nullptr,
337 EGL_LINUX_DMA_BUF_EXT_,
nullptr, attribs);
346 bindPlane(glTexture, out);
362 PlaneImport& out,
unsigned int glTexture,
int fd, uint64_t modifier,
363 const std::uint32_t* offsets,
const std::uint32_t* pitches,
364 std::uint32_t planeCount, uint32_t drm_fourcc,
int w,
int h)
367 if(!m_display || !m_eglImageTargetTexture || fd < 0 || planeCount == 0
371 const uint32_t mod_lo = uint32_t(modifier & 0xFFFFFFFFu);
372 const uint32_t mod_hi = uint32_t((modifier >> 32) & 0xFFFFFFFFu);
374 static constexpr uint32_t planeFd[3]
375 = {EGL_DMA_BUF_PLANE0_FD_EXT_, EGL_DMA_BUF_PLANE1_FD_EXT_,
376 EGL_DMA_BUF_PLANE2_FD_EXT_};
377 static constexpr uint32_t planeOff[3]
378 = {EGL_DMA_BUF_PLANE0_OFFSET_EXT_, EGL_DMA_BUF_PLANE1_OFFSET_EXT_,
379 EGL_DMA_BUF_PLANE2_OFFSET_EXT_};
380 static constexpr uint32_t planePitch[3]
381 = {EGL_DMA_BUF_PLANE0_PITCH_EXT_, EGL_DMA_BUF_PLANE1_PITCH_EXT_,
382 EGL_DMA_BUF_PLANE2_PITCH_EXT_};
383 static constexpr uint32_t planeModLo[3]
384 = {EGL_DMA_BUF_PLANE0_MODIFIER_LO_EXT_,
385 EGL_DMA_BUF_PLANE1_MODIFIER_LO_EXT_,
386 EGL_DMA_BUF_PLANE2_MODIFIER_LO_EXT_};
387 static constexpr uint32_t planeModHi[3]
388 = {EGL_DMA_BUF_PLANE0_MODIFIER_HI_EXT_,
389 EGL_DMA_BUF_PLANE1_MODIFIER_HI_EXT_,
390 EGL_DMA_BUF_PLANE2_MODIFIER_HI_EXT_};
392 intptr_t attribs[6 + 3 * 10 + 1];
394 attribs[n++] = (intptr_t)EGL_WIDTH_;
396 attribs[n++] = (intptr_t)EGL_HEIGHT_;
398 attribs[n++] = (intptr_t)EGL_LINUX_DRM_FOURCC_EXT_;
399 attribs[n++] = intptr_t(drm_fourcc);
400 for(std::uint32_t i = 0; i < planeCount; ++i)
402 attribs[n++] = (intptr_t)planeFd[i];
403 attribs[n++] = intptr_t(fd);
404 attribs[n++] = (intptr_t)planeOff[i];
405 attribs[n++] = intptr_t(offsets[i]);
406 attribs[n++] = (intptr_t)planePitch[i];
407 attribs[n++] = intptr_t(pitches[i]);
408 attribs[n++] = (intptr_t)planeModLo[i];
409 attribs[n++] = intptr_t(mod_lo);
410 attribs[n++] = (intptr_t)planeModHi[i];
411 attribs[n++] = intptr_t(mod_hi);
413 attribs[n++] = (intptr_t)EGL_NONE_;
418 int khrAttribs[
sizeof(attribs) /
sizeof(attribs[0])];
419 for(std::size_t i = 0; i < n; ++i)
420 khrAttribs[i] =
int(attribs[i]);
421 img = m_createImageKHR(
422 m_display,
nullptr, EGL_LINUX_DMA_BUF_EXT_,
nullptr, khrAttribs);
427 m_display,
nullptr, EGL_LINUX_DMA_BUF_EXT_,
nullptr, attribs);
433 return bindExternal(glTexture, out);
437 bool bindExternal(
unsigned int glTexture,
const PlaneImport& p)
noexcept
439 if(!p.image || !m_eglImageTargetTexture || glTexture == 0)
441 auto* ctx = QOpenGLContext::currentContext();
444 auto* funcs = ctx->extraFunctions();
447 funcs->glBindTexture(GL_TEXTURE_EXTERNAL_OES_, glTexture);
448 while(funcs->glGetError() != 0u)
450 m_eglImageTargetTexture(GL_TEXTURE_EXTERNAL_OES_, p.image);
451 if(
const unsigned int err = funcs->glGetError(); err != 0u)
453 qDebug() <<
"EglDmaBufImporter: external image target failed, GL error"
460 static constexpr unsigned int GL_TEXTURE_EXTERNAL_OES_ = 0x8D65;
464 static unsigned int createExternalTexture() noexcept
466 auto* ctx = QOpenGLContext::currentContext();
469 auto* f = ctx->extraFunctions();
472 constexpr unsigned int GL_TEXTURE_MIN_FILTER_v = 0x2801;
473 constexpr unsigned int GL_TEXTURE_MAG_FILTER_v = 0x2800;
474 constexpr unsigned int GL_TEXTURE_WRAP_S_v = 0x2802;
475 constexpr unsigned int GL_TEXTURE_WRAP_T_v = 0x2803;
476 constexpr int GL_LINEAR_v = 0x2601;
477 constexpr int GL_CLAMP_TO_EDGE_v = 0x812F;
478 unsigned int tex = 0;
479 f->glGenTextures(1, &tex);
482 f->glBindTexture(GL_TEXTURE_EXTERNAL_OES_, tex);
483 f->glTexParameteri(GL_TEXTURE_EXTERNAL_OES_, GL_TEXTURE_MIN_FILTER_v, GL_LINEAR_v);
484 f->glTexParameteri(GL_TEXTURE_EXTERNAL_OES_, GL_TEXTURE_MAG_FILTER_v, GL_LINEAR_v);
485 f->glTexParameteri(GL_TEXTURE_EXTERNAL_OES_, GL_TEXTURE_WRAP_S_v, GL_CLAMP_TO_EDGE_v);
486 f->glTexParameteri(GL_TEXTURE_EXTERNAL_OES_, GL_TEXTURE_WRAP_T_v, GL_CLAMP_TO_EDGE_v);
491 bool hasExternalImage() const noexcept
493 auto* ctx = QOpenGLContext::currentContext();
496 return ctx->hasExtension(
"GL_OES_EGL_image_external")
497 || ctx->hasExtension(
"GL_OES_EGL_image_external_essl3");
509 std::vector<std::uint64_t>
510 supportedModifiers(std::uint32_t drm_fourcc)
noexcept
512 std::vector<std::uint64_t> result;
516 auto* ctx = QOpenGLContext::currentContext();
520 using FN_eglQueryDmaBufModifiersEXT =
unsigned int (*)(
521 void* dpy,
int format,
int max_modifiers, std::uint64_t* modifiers,
522 unsigned int* external_only,
int* num_modifiers);
523 auto query =
reinterpret_cast<FN_eglQueryDmaBufModifiersEXT
>(
524 ctx->getProcAddress(
"eglQueryDmaBufModifiersEXT"));
534 if(!query(m_display,
int(drm_fourcc), 0,
nullptr,
nullptr, &count)
541 result.resize(
static_cast<std::size_t
>(count));
542 std::vector<unsigned int> external_only(count);
544 m_display,
int(drm_fourcc), count, result.data(),
545 external_only.data(), &count))
551 result.resize(
static_cast<std::size_t
>(count));
556 for(std::size_t i = 0; i < result.size(); ++i)
557 if(external_only[i] == 0)
558 result[w++] = result[i];
563 bool has_linear =
false;
588 bool canImportModifier(
589 std::uint32_t drm_fourcc, std::uint64_t modifier)
noexcept
591 auto* ctx = QOpenGLContext::currentContext();
592 if(!m_display || !ctx)
595 using FN_eglQueryDmaBufModifiersEXT =
unsigned int (*)(
596 void* dpy,
int format,
int max_modifiers, std::uint64_t* modifiers,
597 unsigned int* external_only,
int* num_modifiers);
598 auto query =
reinterpret_cast<FN_eglQueryDmaBufModifiersEXT
>(
599 ctx->getProcAddress(
"eglQueryDmaBufModifiersEXT"));
604 if(!query(m_display,
int(drm_fourcc), 0,
nullptr,
nullptr, &count)
608 const auto n =
static_cast<std::size_t
>(count);
609 std::vector<std::uint64_t> mods(n);
610 std::vector<unsigned int> external_only(n);
612 m_display,
int(drm_fourcc), count, mods.data(), external_only.data(),
616 for(
int i = 0; i < count; ++i)
617 if(mods[std::size_t(i)] == modifier && external_only[std::size_t(i)] == 0)
629inline unsigned int createLinearClampGlTexture2D() noexcept
631 auto* ctx = QOpenGLContext::currentContext();
634 auto* gl = ctx->extraFunctions();
635 unsigned int tex = 0;
636 gl->glGenTextures(1, &tex);
639 constexpr unsigned int GL_TEXTURE_2D_v = 0x0DE1;
640 constexpr unsigned int GL_TEXTURE_MIN_FILTER_v = 0x2801;
641 constexpr unsigned int GL_TEXTURE_MAG_FILTER_v = 0x2800;
642 constexpr unsigned int GL_TEXTURE_WRAP_S_v = 0x2802;
643 constexpr unsigned int GL_TEXTURE_WRAP_T_v = 0x2803;
644 constexpr unsigned int GL_LINEAR_v = 0x2601;
645 constexpr unsigned int GL_CLAMP_TO_EDGE_v = 0x812F;
646 gl->glBindTexture(GL_TEXTURE_2D_v, tex);
647 gl->glTexParameteri(GL_TEXTURE_2D_v, GL_TEXTURE_MIN_FILTER_v, GL_LINEAR_v);
648 gl->glTexParameteri(GL_TEXTURE_2D_v, GL_TEXTURE_MAG_FILTER_v, GL_LINEAR_v);
650 GL_TEXTURE_2D_v, GL_TEXTURE_WRAP_S_v, GL_CLAMP_TO_EDGE_v);
652 GL_TEXTURE_2D_v, GL_TEXTURE_WRAP_T_v, GL_CLAMP_TO_EDGE_v);
Graphics rendering pipeline for ossia score.
Definition Filter/PreviewWidget.hpp:11