85 QVideoFrameFormat::PixelFormat qtFormat, QSize frameSize,
86 std::shared_ptr<
void> parentKeepAlive)
88 Qt::HANDLE eglDisplay = eglContext.eglDisplay();
89 QOpenGLContext *glContext = eglContext.glContext();
91 QOpenGLFunctions functions(glContext);
92 const auto &elgImageFunctions = QEglImageFunctions::instance();
94 auto *desc = QVideoTextureHelper::textureDescription(qtFormat);
95 int nPlanes = desc->nplanes;
96 Q_ASSERT(planes.size() == nPlanes);
98 rhi.makeThreadLocalNativeContextCurrent();
100 std::array<EGLImageHandle, 4> images;
101 std::array<GLuint, 4> rawGlTextures{};
102 functions.glGenTextures(nPlanes, rawGlTextures.data());
104 std::array<GlTextureHandle, 4> glTextures;
105 for (
int i = 0; i < nPlanes; ++i)
106 glTextures[i] = GlTextureHandle(rawGlTextures[i], GlTextureDeleter(glContext));
108 for (
int i = 0; i < nPlanes; ++i) {
109 const DmaBufPlane &plane = planes[i];
111 QSize planeSize = desc->rhiPlaneSize(frameSize, i, &rhi);
112 constexpr uint32_t maxAttrCount = 18;
113 EGLAttrib img_attr[maxAttrCount] = {
114 EGL_LINUX_DRM_FOURCC_EXT,
115 (EGLint)qToUnderlying(plane.drmFormat),
120 EGL_DMA_BUF_PLANE0_FD_EXT,
122 EGL_DMA_BUF_PLANE0_OFFSET_EXT,
123 (EGLint)plane.offset,
124 EGL_DMA_BUF_PLANE0_PITCH_EXT,
127 uint32_t img_attr_idx = 12;
128 if (plane.modifier != DmaBufFormatModifierInvalid) {
129 const auto modifier = qToUnderlying(plane.modifier);
130 img_attr[img_attr_idx++] = EGL_DMA_BUF_PLANE0_MODIFIER_LO_EXT;
131 img_attr[img_attr_idx++] = EGLAttrib(modifier & 0xFFFFFFFF);
132 img_attr[img_attr_idx++] = EGL_DMA_BUF_PLANE0_MODIFIER_HI_EXT;
133 img_attr[img_attr_idx++] = EGLAttrib(modifier >> 32);
135 img_attr[img_attr_idx++] = EGL_NONE;
136 Q_ASSERT(img_attr_idx <= maxAttrCount);
137 images[i] = elgImageFunctions.eglCreateImage(
138 eglDisplay, EGL_NO_CONTEXT, EGL_LINUX_DMA_BUF_EXT,
nullptr,
139 QSpan<
const EGLAttrib>(img_attr, img_attr_idx));
141 const EGLError error = EGLError(eglGetError());
143 case EGLError::Success: {
146 case EGLError::BadMatch: {
147 qWarning() <<
"eglCreateImage failed for plane" << i <<
"with" << error
148 <<
", disabling hardware acceleration. "
149 "This could indicate an EGL implementation issue."
151 << eglQueryString(eglDisplay, EGL_VENDOR);
153 return q23::unexpected{ FailureSeverity::unrecoverable };
155 case EGLError::BadParameter: {
156 bool dmaModifierNotSupported =
157 dmaModifierIsNotSupportedByDisplay(plane, eglDisplay);
158 if (dmaModifierNotSupported) {
159 qWarning() <<
"eglCreateImage failed for plane" << i <<
"with" << error
160 <<
", disabling hardware acceleration. "
161 "This could indicate an EGL implementation issue."
163 << eglQueryString(eglDisplay, EGL_VENDOR);
165 return q23::unexpected{ FailureSeverity::unrecoverable };
170 qWarning() <<
"eglCreateImage failed for plane" << i <<
"with" << error;
171 return q23::unexpected{ FailureSeverity::recoverable };
175 functions.glActiveTexture(GL_TEXTURE0 + i);
176 functions.glBindTexture(GL_TEXTURE_2D, glTextures[i].get());
178 elgImageFunctions.glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, images[i].get());
179 const GLError error = GLError(glGetError());
180 if (error != GLError::NoError) {
181 qWarning() <<
"eglImageTargetTexture2D failed for plane" << i <<
"with" << error
182 <<
"(the driver may not support importing this dma-buf as a GL texture)";
183 return q23::unexpected{ FailureSeverity::recoverable };
187 for (
int i = 0; i < nPlanes; ++i) {
188 functions.glActiveTexture(GL_TEXTURE0 + i);
189 functions.glBindTexture(GL_TEXTURE_2D, 0);
192 return std::make_unique<DmaBufTextureHandles>(rhi,
std::move(glTextures),
193 std::move(parentKeepAlive));