mirror of
https://github.com/moonlight-stream/moonlight-qt
synced 2025-01-23 16:15:02 +00:00
Refactor EGLImage creation into a separate shared class
This commit is contained in:
parent
e143293e91
commit
b01dfea343
7 changed files with 436 additions and 385 deletions
|
@ -314,8 +314,11 @@ config_EGL {
|
|||
DEFINES += HAVE_EGL
|
||||
SOURCES += \
|
||||
streaming/video/ffmpeg-renderers/eglvid.cpp \
|
||||
streaming/video/ffmpeg-renderers/egl_extensions.cpp
|
||||
HEADERS += streaming/video/ffmpeg-renderers/eglvid.h
|
||||
streaming/video/ffmpeg-renderers/egl_extensions.cpp \
|
||||
streaming/video/ffmpeg-renderers/eglimagefactory.cpp
|
||||
HEADERS += \
|
||||
streaming/video/ffmpeg-renderers/eglvid.h \
|
||||
streaming/video/ffmpeg-renderers/eglimagefactory.h
|
||||
}
|
||||
config_SL {
|
||||
message(Steam Link build configuration selected)
|
||||
|
|
|
@ -83,15 +83,10 @@ DrmRenderer::DrmRenderer(bool hwaccel, IFFmpegRenderer *backendRenderer)
|
|||
m_HdrOutputMetadataBlobId(0),
|
||||
m_SwFrameMapper(this),
|
||||
m_CurrentSwFrameIdx(0)
|
||||
{
|
||||
#ifdef HAVE_EGL
|
||||
m_EGLExtDmaBuf = false;
|
||||
m_eglCreateImage = nullptr;
|
||||
m_eglCreateImageKHR = nullptr;
|
||||
m_eglDestroyImage = nullptr;
|
||||
m_eglDestroyImageKHR = nullptr;
|
||||
, m_EglImageFactory(this)
|
||||
#endif
|
||||
|
||||
{
|
||||
SDL_zero(m_SwFrame);
|
||||
}
|
||||
|
||||
|
@ -1153,223 +1148,20 @@ AVPixelFormat DrmRenderer::getEGLImagePixelFormat() {
|
|||
return AV_PIX_FMT_DRM_PRIME;
|
||||
}
|
||||
|
||||
bool DrmRenderer::initializeEGL(EGLDisplay,
|
||||
bool DrmRenderer::initializeEGL(EGLDisplay display,
|
||||
const EGLExtensions &ext) {
|
||||
if (!ext.isSupported("EGL_EXT_image_dma_buf_import")) {
|
||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
|
||||
"DRM-EGL: DMABUF unsupported");
|
||||
return false;
|
||||
}
|
||||
|
||||
m_EGLExtDmaBuf = ext.isSupported("EGL_EXT_image_dma_buf_import_modifiers");
|
||||
|
||||
// NB: eglCreateImage() and eglCreateImageKHR() have slightly different definitions
|
||||
m_eglCreateImage = (typeof(m_eglCreateImage))eglGetProcAddress("eglCreateImage");
|
||||
m_eglCreateImageKHR = (typeof(m_eglCreateImageKHR))eglGetProcAddress("eglCreateImageKHR");
|
||||
m_eglDestroyImage = (typeof(m_eglDestroyImage))eglGetProcAddress("eglDestroyImage");
|
||||
m_eglDestroyImageKHR = (typeof(m_eglDestroyImageKHR))eglGetProcAddress("eglDestroyImageKHR");
|
||||
|
||||
if (!(m_eglCreateImage && m_eglDestroyImage) &&
|
||||
!(m_eglCreateImageKHR && m_eglDestroyImageKHR)) {
|
||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
|
||||
"Missing eglCreateImage()/eglDestroyImage() in EGL driver");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
return m_EglImageFactory.initializeEGL(display, ext);
|
||||
}
|
||||
|
||||
ssize_t DrmRenderer::exportEGLImages(AVFrame *frame, EGLDisplay dpy,
|
||||
EGLImage images[EGL_MAX_PLANES]) {
|
||||
AVDRMFrameDescriptor* drmFrame = (AVDRMFrameDescriptor*)frame->data[0];
|
||||
|
||||
memset(images, 0, sizeof(EGLImage) * EGL_MAX_PLANES);
|
||||
|
||||
// DRM requires composed layers rather than separate layers per plane
|
||||
SDL_assert(drmFrame->nb_layers == 1);
|
||||
|
||||
// Max 33 attributes (1 key + 1 value for each)
|
||||
const int MAX_ATTRIB_COUNT = 33 * 2;
|
||||
EGLAttrib attribs[MAX_ATTRIB_COUNT] = {
|
||||
EGL_LINUX_DRM_FOURCC_EXT, (EGLAttrib)drmFrame->layers[0].format,
|
||||
EGL_WIDTH, frame->width,
|
||||
EGL_HEIGHT, frame->height,
|
||||
EGL_IMAGE_PRESERVED_KHR, EGL_TRUE,
|
||||
};
|
||||
int attribIndex = 8;
|
||||
|
||||
for (int i = 0; i < drmFrame->layers[0].nb_planes; ++i) {
|
||||
const auto &plane = drmFrame->layers[0].planes[i];
|
||||
const auto &object = drmFrame->objects[plane.object_index];
|
||||
|
||||
switch (i) {
|
||||
case 0:
|
||||
attribs[attribIndex++] = EGL_DMA_BUF_PLANE0_FD_EXT;
|
||||
attribs[attribIndex++] = object.fd;
|
||||
attribs[attribIndex++] = EGL_DMA_BUF_PLANE0_OFFSET_EXT;
|
||||
attribs[attribIndex++] = plane.offset;
|
||||
attribs[attribIndex++] = EGL_DMA_BUF_PLANE0_PITCH_EXT;
|
||||
attribs[attribIndex++] = plane.pitch;
|
||||
if (m_EGLExtDmaBuf && object.format_modifier != DRM_FORMAT_MOD_INVALID) {
|
||||
attribs[attribIndex++] = EGL_DMA_BUF_PLANE0_MODIFIER_LO_EXT;
|
||||
attribs[attribIndex++] = (EGLint)(object.format_modifier & 0xFFFFFFFF);
|
||||
attribs[attribIndex++] = EGL_DMA_BUF_PLANE0_MODIFIER_HI_EXT;
|
||||
attribs[attribIndex++] = (EGLint)(object.format_modifier >> 32);
|
||||
}
|
||||
break;
|
||||
|
||||
case 1:
|
||||
attribs[attribIndex++] = EGL_DMA_BUF_PLANE1_FD_EXT;
|
||||
attribs[attribIndex++] = object.fd;
|
||||
attribs[attribIndex++] = EGL_DMA_BUF_PLANE1_OFFSET_EXT;
|
||||
attribs[attribIndex++] = plane.offset;
|
||||
attribs[attribIndex++] = EGL_DMA_BUF_PLANE1_PITCH_EXT;
|
||||
attribs[attribIndex++] = plane.pitch;
|
||||
if (m_EGLExtDmaBuf && object.format_modifier != DRM_FORMAT_MOD_INVALID) {
|
||||
attribs[attribIndex++] = EGL_DMA_BUF_PLANE1_MODIFIER_LO_EXT;
|
||||
attribs[attribIndex++] = (EGLint)(object.format_modifier & 0xFFFFFFFF);
|
||||
attribs[attribIndex++] = EGL_DMA_BUF_PLANE1_MODIFIER_HI_EXT;
|
||||
attribs[attribIndex++] = (EGLint)(object.format_modifier >> 32);
|
||||
}
|
||||
break;
|
||||
|
||||
case 2:
|
||||
attribs[attribIndex++] = EGL_DMA_BUF_PLANE2_FD_EXT;
|
||||
attribs[attribIndex++] = object.fd;
|
||||
attribs[attribIndex++] = EGL_DMA_BUF_PLANE2_OFFSET_EXT;
|
||||
attribs[attribIndex++] = plane.offset;
|
||||
attribs[attribIndex++] = EGL_DMA_BUF_PLANE2_PITCH_EXT;
|
||||
attribs[attribIndex++] = plane.pitch;
|
||||
if (m_EGLExtDmaBuf && object.format_modifier != DRM_FORMAT_MOD_INVALID) {
|
||||
attribs[attribIndex++] = EGL_DMA_BUF_PLANE2_MODIFIER_LO_EXT;
|
||||
attribs[attribIndex++] = (EGLint)(object.format_modifier & 0xFFFFFFFF);
|
||||
attribs[attribIndex++] = EGL_DMA_BUF_PLANE2_MODIFIER_HI_EXT;
|
||||
attribs[attribIndex++] = (EGLint)(object.format_modifier >> 32);
|
||||
}
|
||||
break;
|
||||
|
||||
case 3:
|
||||
attribs[attribIndex++] = EGL_DMA_BUF_PLANE3_FD_EXT;
|
||||
attribs[attribIndex++] = object.fd;
|
||||
attribs[attribIndex++] = EGL_DMA_BUF_PLANE3_OFFSET_EXT;
|
||||
attribs[attribIndex++] = plane.offset;
|
||||
attribs[attribIndex++] = EGL_DMA_BUF_PLANE3_PITCH_EXT;
|
||||
attribs[attribIndex++] = plane.pitch;
|
||||
if (m_EGLExtDmaBuf && object.format_modifier != DRM_FORMAT_MOD_INVALID) {
|
||||
attribs[attribIndex++] = EGL_DMA_BUF_PLANE3_MODIFIER_LO_EXT;
|
||||
attribs[attribIndex++] = (EGLint)(object.format_modifier & 0xFFFFFFFF);
|
||||
attribs[attribIndex++] = EGL_DMA_BUF_PLANE3_MODIFIER_HI_EXT;
|
||||
attribs[attribIndex++] = (EGLint)(object.format_modifier >> 32);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
Q_UNREACHABLE();
|
||||
}
|
||||
}
|
||||
|
||||
// Add colorspace metadata
|
||||
switch (getFrameColorspace(frame)) {
|
||||
case COLORSPACE_REC_601:
|
||||
attribs[attribIndex++] = EGL_YUV_COLOR_SPACE_HINT_EXT;
|
||||
attribs[attribIndex++] = EGL_ITU_REC601_EXT;
|
||||
break;
|
||||
case COLORSPACE_REC_709:
|
||||
attribs[attribIndex++] = EGL_YUV_COLOR_SPACE_HINT_EXT;
|
||||
attribs[attribIndex++] = EGL_ITU_REC709_EXT;
|
||||
break;
|
||||
case COLORSPACE_REC_2020:
|
||||
attribs[attribIndex++] = EGL_YUV_COLOR_SPACE_HINT_EXT;
|
||||
attribs[attribIndex++] = EGL_ITU_REC2020_EXT;
|
||||
break;
|
||||
}
|
||||
|
||||
// Add color range metadata
|
||||
attribs[attribIndex++] = EGL_SAMPLE_RANGE_HINT_EXT;
|
||||
attribs[attribIndex++] = isFrameFullRange(frame) ? EGL_YUV_FULL_RANGE_EXT : EGL_YUV_NARROW_RANGE_EXT;
|
||||
|
||||
// Add chroma siting metadata
|
||||
switch (frame->chroma_location) {
|
||||
case AVCHROMA_LOC_LEFT:
|
||||
case AVCHROMA_LOC_TOPLEFT:
|
||||
attribs[attribIndex++] = EGL_YUV_CHROMA_HORIZONTAL_SITING_HINT_EXT;
|
||||
attribs[attribIndex++] = EGL_YUV_CHROMA_SITING_0_EXT;
|
||||
break;
|
||||
|
||||
case AVCHROMA_LOC_CENTER:
|
||||
case AVCHROMA_LOC_TOP:
|
||||
attribs[attribIndex++] = EGL_YUV_CHROMA_HORIZONTAL_SITING_HINT_EXT;
|
||||
attribs[attribIndex++] = EGL_YUV_CHROMA_SITING_0_5_EXT;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
switch (frame->chroma_location) {
|
||||
case AVCHROMA_LOC_TOPLEFT:
|
||||
case AVCHROMA_LOC_TOP:
|
||||
attribs[attribIndex++] = EGL_YUV_CHROMA_VERTICAL_SITING_HINT_EXT;
|
||||
attribs[attribIndex++] = EGL_YUV_CHROMA_SITING_0_EXT;
|
||||
break;
|
||||
|
||||
case AVCHROMA_LOC_LEFT:
|
||||
case AVCHROMA_LOC_CENTER:
|
||||
attribs[attribIndex++] = EGL_YUV_CHROMA_VERTICAL_SITING_HINT_EXT;
|
||||
attribs[attribIndex++] = EGL_YUV_CHROMA_SITING_0_5_EXT;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
// Terminate the attribute list
|
||||
attribs[attribIndex++] = EGL_NONE;
|
||||
SDL_assert(attribIndex <= MAX_ATTRIB_COUNT);
|
||||
|
||||
// Our EGLImages are non-planar, so we only populate the first entry
|
||||
if (m_eglCreateImage) {
|
||||
images[0] = m_eglCreateImage(dpy, EGL_NO_CONTEXT,
|
||||
EGL_LINUX_DMA_BUF_EXT,
|
||||
nullptr, attribs);
|
||||
if (!images[0]) {
|
||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
|
||||
"eglCreateImage() Failed: %d", eglGetError());
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
else {
|
||||
// Cast the EGLAttrib array elements to EGLint for the KHR extension
|
||||
EGLint intAttribs[MAX_ATTRIB_COUNT];
|
||||
for (int i = 0; i < MAX_ATTRIB_COUNT; i++) {
|
||||
intAttribs[i] = (EGLint)attribs[i];
|
||||
}
|
||||
|
||||
images[0] = m_eglCreateImageKHR(dpy, EGL_NO_CONTEXT,
|
||||
EGL_LINUX_DMA_BUF_EXT,
|
||||
nullptr, intAttribs);
|
||||
if (!images[0]) {
|
||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
|
||||
"eglCreateImageKHR() Failed: %d", eglGetError());
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
|
||||
fail:
|
||||
freeEGLImages(dpy, images);
|
||||
return -1;
|
||||
return m_EglImageFactory.exportDRMImages(frame, drmFrame, dpy, images);
|
||||
}
|
||||
|
||||
void DrmRenderer::freeEGLImages(EGLDisplay dpy, EGLImage images[EGL_MAX_PLANES]) {
|
||||
if (m_eglDestroyImage) {
|
||||
m_eglDestroyImage(dpy, images[0]);
|
||||
}
|
||||
else {
|
||||
m_eglDestroyImageKHR(dpy, images[0]);
|
||||
}
|
||||
|
||||
// Our EGLImages are non-planar
|
||||
SDL_assert(images[1] == 0);
|
||||
SDL_assert(images[2] == 0);
|
||||
m_EglImageFactory.freeEGLImages(dpy, images);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -3,6 +3,10 @@
|
|||
#include "renderer.h"
|
||||
#include "swframemapper.h"
|
||||
|
||||
#ifdef HAVE_EGL
|
||||
#include "eglimagefactory.h"
|
||||
#endif
|
||||
|
||||
#include <xf86drm.h>
|
||||
#include <xf86drmMode.h>
|
||||
|
||||
|
@ -105,11 +109,7 @@ private:
|
|||
} m_SwFrame[k_SwFrameCount];
|
||||
|
||||
#ifdef HAVE_EGL
|
||||
bool m_EGLExtDmaBuf;
|
||||
PFNEGLCREATEIMAGEPROC m_eglCreateImage;
|
||||
PFNEGLDESTROYIMAGEPROC m_eglDestroyImage;
|
||||
PFNEGLCREATEIMAGEKHRPROC m_eglCreateImageKHR;
|
||||
PFNEGLDESTROYIMAGEKHRPROC m_eglDestroyImageKHR;
|
||||
EglImageFactory m_EglImageFactory;
|
||||
#endif
|
||||
};
|
||||
|
||||
|
|
364
app/streaming/video/ffmpeg-renderers/eglimagefactory.cpp
Normal file
364
app/streaming/video/ffmpeg-renderers/eglimagefactory.cpp
Normal file
|
@ -0,0 +1,364 @@
|
|||
#include "eglimagefactory.h"
|
||||
|
||||
// Don't take a dependency on libdrm just for this constant
|
||||
#ifndef DRM_FORMAT_MOD_INVALID
|
||||
#define DRM_FORMAT_MOD_INVALID ((1ULL << 56) - 1)
|
||||
#endif
|
||||
|
||||
EglImageFactory::EglImageFactory(IFFmpegRenderer* renderer) :
|
||||
m_Renderer(renderer),
|
||||
m_EGLExtDmaBuf(false),
|
||||
m_eglCreateImage(nullptr),
|
||||
m_eglDestroyImage(nullptr),
|
||||
m_eglCreateImageKHR(nullptr),
|
||||
m_eglDestroyImageKHR(nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
bool EglImageFactory::initializeEGL(EGLDisplay,
|
||||
const EGLExtensions &ext)
|
||||
{
|
||||
if (!ext.isSupported("EGL_EXT_image_dma_buf_import")) {
|
||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
|
||||
"DRM-EGL: DMABUF unsupported");
|
||||
return false;
|
||||
}
|
||||
|
||||
m_EGLExtDmaBuf = ext.isSupported("EGL_EXT_image_dma_buf_import_modifiers");
|
||||
|
||||
// NB: eglCreateImage() and eglCreateImageKHR() have slightly different definitions
|
||||
m_eglCreateImage = (typeof(m_eglCreateImage))eglGetProcAddress("eglCreateImage");
|
||||
m_eglCreateImageKHR = (typeof(m_eglCreateImageKHR))eglGetProcAddress("eglCreateImageKHR");
|
||||
m_eglDestroyImage = (typeof(m_eglDestroyImage))eglGetProcAddress("eglDestroyImage");
|
||||
m_eglDestroyImageKHR = (typeof(m_eglDestroyImageKHR))eglGetProcAddress("eglDestroyImageKHR");
|
||||
|
||||
if (!(m_eglCreateImage && m_eglDestroyImage) &&
|
||||
!(m_eglCreateImageKHR && m_eglDestroyImageKHR)) {
|
||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
|
||||
"Missing eglCreateImage()/eglDestroyImage() in EGL driver");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
ssize_t EglImageFactory::exportDRMImages(AVFrame* frame, AVDRMFrameDescriptor* drmFrame, EGLDisplay dpy, EGLImage images[EGL_MAX_PLANES])
|
||||
{
|
||||
memset(images, 0, sizeof(EGLImage) * EGL_MAX_PLANES);
|
||||
|
||||
// DRM requires composed layers rather than separate layers per plane
|
||||
SDL_assert(drmFrame->nb_layers == 1);
|
||||
|
||||
// Max 33 attributes (1 key + 1 value for each)
|
||||
const int MAX_ATTRIB_COUNT = 33 * 2;
|
||||
EGLAttrib attribs[MAX_ATTRIB_COUNT] = {
|
||||
EGL_LINUX_DRM_FOURCC_EXT, (EGLAttrib)drmFrame->layers[0].format,
|
||||
EGL_WIDTH, frame->width,
|
||||
EGL_HEIGHT, frame->height,
|
||||
EGL_IMAGE_PRESERVED_KHR, EGL_TRUE,
|
||||
};
|
||||
int attribIndex = 8;
|
||||
|
||||
for (int i = 0; i < drmFrame->layers[0].nb_planes; ++i) {
|
||||
const auto &plane = drmFrame->layers[0].planes[i];
|
||||
const auto &object = drmFrame->objects[plane.object_index];
|
||||
|
||||
switch (i) {
|
||||
case 0:
|
||||
attribs[attribIndex++] = EGL_DMA_BUF_PLANE0_FD_EXT;
|
||||
attribs[attribIndex++] = object.fd;
|
||||
attribs[attribIndex++] = EGL_DMA_BUF_PLANE0_OFFSET_EXT;
|
||||
attribs[attribIndex++] = plane.offset;
|
||||
attribs[attribIndex++] = EGL_DMA_BUF_PLANE0_PITCH_EXT;
|
||||
attribs[attribIndex++] = plane.pitch;
|
||||
if (m_EGLExtDmaBuf && object.format_modifier != DRM_FORMAT_MOD_INVALID) {
|
||||
attribs[attribIndex++] = EGL_DMA_BUF_PLANE0_MODIFIER_LO_EXT;
|
||||
attribs[attribIndex++] = (EGLint)(object.format_modifier & 0xFFFFFFFF);
|
||||
attribs[attribIndex++] = EGL_DMA_BUF_PLANE0_MODIFIER_HI_EXT;
|
||||
attribs[attribIndex++] = (EGLint)(object.format_modifier >> 32);
|
||||
}
|
||||
break;
|
||||
|
||||
case 1:
|
||||
attribs[attribIndex++] = EGL_DMA_BUF_PLANE1_FD_EXT;
|
||||
attribs[attribIndex++] = object.fd;
|
||||
attribs[attribIndex++] = EGL_DMA_BUF_PLANE1_OFFSET_EXT;
|
||||
attribs[attribIndex++] = plane.offset;
|
||||
attribs[attribIndex++] = EGL_DMA_BUF_PLANE1_PITCH_EXT;
|
||||
attribs[attribIndex++] = plane.pitch;
|
||||
if (m_EGLExtDmaBuf && object.format_modifier != DRM_FORMAT_MOD_INVALID) {
|
||||
attribs[attribIndex++] = EGL_DMA_BUF_PLANE1_MODIFIER_LO_EXT;
|
||||
attribs[attribIndex++] = (EGLint)(object.format_modifier & 0xFFFFFFFF);
|
||||
attribs[attribIndex++] = EGL_DMA_BUF_PLANE1_MODIFIER_HI_EXT;
|
||||
attribs[attribIndex++] = (EGLint)(object.format_modifier >> 32);
|
||||
}
|
||||
break;
|
||||
|
||||
case 2:
|
||||
attribs[attribIndex++] = EGL_DMA_BUF_PLANE2_FD_EXT;
|
||||
attribs[attribIndex++] = object.fd;
|
||||
attribs[attribIndex++] = EGL_DMA_BUF_PLANE2_OFFSET_EXT;
|
||||
attribs[attribIndex++] = plane.offset;
|
||||
attribs[attribIndex++] = EGL_DMA_BUF_PLANE2_PITCH_EXT;
|
||||
attribs[attribIndex++] = plane.pitch;
|
||||
if (m_EGLExtDmaBuf && object.format_modifier != DRM_FORMAT_MOD_INVALID) {
|
||||
attribs[attribIndex++] = EGL_DMA_BUF_PLANE2_MODIFIER_LO_EXT;
|
||||
attribs[attribIndex++] = (EGLint)(object.format_modifier & 0xFFFFFFFF);
|
||||
attribs[attribIndex++] = EGL_DMA_BUF_PLANE2_MODIFIER_HI_EXT;
|
||||
attribs[attribIndex++] = (EGLint)(object.format_modifier >> 32);
|
||||
}
|
||||
break;
|
||||
|
||||
case 3:
|
||||
attribs[attribIndex++] = EGL_DMA_BUF_PLANE3_FD_EXT;
|
||||
attribs[attribIndex++] = object.fd;
|
||||
attribs[attribIndex++] = EGL_DMA_BUF_PLANE3_OFFSET_EXT;
|
||||
attribs[attribIndex++] = plane.offset;
|
||||
attribs[attribIndex++] = EGL_DMA_BUF_PLANE3_PITCH_EXT;
|
||||
attribs[attribIndex++] = plane.pitch;
|
||||
if (m_EGLExtDmaBuf && object.format_modifier != DRM_FORMAT_MOD_INVALID) {
|
||||
attribs[attribIndex++] = EGL_DMA_BUF_PLANE3_MODIFIER_LO_EXT;
|
||||
attribs[attribIndex++] = (EGLint)(object.format_modifier & 0xFFFFFFFF);
|
||||
attribs[attribIndex++] = EGL_DMA_BUF_PLANE3_MODIFIER_HI_EXT;
|
||||
attribs[attribIndex++] = (EGLint)(object.format_modifier >> 32);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
Q_UNREACHABLE();
|
||||
}
|
||||
}
|
||||
|
||||
// Add colorspace metadata
|
||||
switch (m_Renderer->getFrameColorspace(frame)) {
|
||||
case COLORSPACE_REC_601:
|
||||
attribs[attribIndex++] = EGL_YUV_COLOR_SPACE_HINT_EXT;
|
||||
attribs[attribIndex++] = EGL_ITU_REC601_EXT;
|
||||
break;
|
||||
case COLORSPACE_REC_709:
|
||||
attribs[attribIndex++] = EGL_YUV_COLOR_SPACE_HINT_EXT;
|
||||
attribs[attribIndex++] = EGL_ITU_REC709_EXT;
|
||||
break;
|
||||
case COLORSPACE_REC_2020:
|
||||
attribs[attribIndex++] = EGL_YUV_COLOR_SPACE_HINT_EXT;
|
||||
attribs[attribIndex++] = EGL_ITU_REC2020_EXT;
|
||||
break;
|
||||
}
|
||||
|
||||
// Add color range metadata
|
||||
attribs[attribIndex++] = EGL_SAMPLE_RANGE_HINT_EXT;
|
||||
attribs[attribIndex++] = m_Renderer->isFrameFullRange(frame) ? EGL_YUV_FULL_RANGE_EXT : EGL_YUV_NARROW_RANGE_EXT;
|
||||
|
||||
// Add chroma siting metadata
|
||||
switch (frame->chroma_location) {
|
||||
case AVCHROMA_LOC_LEFT:
|
||||
case AVCHROMA_LOC_TOPLEFT:
|
||||
attribs[attribIndex++] = EGL_YUV_CHROMA_HORIZONTAL_SITING_HINT_EXT;
|
||||
attribs[attribIndex++] = EGL_YUV_CHROMA_SITING_0_EXT;
|
||||
break;
|
||||
|
||||
case AVCHROMA_LOC_CENTER:
|
||||
case AVCHROMA_LOC_TOP:
|
||||
attribs[attribIndex++] = EGL_YUV_CHROMA_HORIZONTAL_SITING_HINT_EXT;
|
||||
attribs[attribIndex++] = EGL_YUV_CHROMA_SITING_0_5_EXT;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
switch (frame->chroma_location) {
|
||||
case AVCHROMA_LOC_TOPLEFT:
|
||||
case AVCHROMA_LOC_TOP:
|
||||
attribs[attribIndex++] = EGL_YUV_CHROMA_VERTICAL_SITING_HINT_EXT;
|
||||
attribs[attribIndex++] = EGL_YUV_CHROMA_SITING_0_EXT;
|
||||
break;
|
||||
|
||||
case AVCHROMA_LOC_LEFT:
|
||||
case AVCHROMA_LOC_CENTER:
|
||||
attribs[attribIndex++] = EGL_YUV_CHROMA_VERTICAL_SITING_HINT_EXT;
|
||||
attribs[attribIndex++] = EGL_YUV_CHROMA_SITING_0_5_EXT;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
// Terminate the attribute list
|
||||
attribs[attribIndex++] = EGL_NONE;
|
||||
SDL_assert(attribIndex <= MAX_ATTRIB_COUNT);
|
||||
|
||||
// Our EGLImages are non-planar, so we only populate the first entry
|
||||
if (m_eglCreateImage) {
|
||||
images[0] = m_eglCreateImage(dpy, EGL_NO_CONTEXT,
|
||||
EGL_LINUX_DMA_BUF_EXT,
|
||||
nullptr, attribs);
|
||||
if (!images[0]) {
|
||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
|
||||
"eglCreateImage() Failed: %d", eglGetError());
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
else {
|
||||
// Cast the EGLAttrib array elements to EGLint for the KHR extension
|
||||
EGLint intAttribs[MAX_ATTRIB_COUNT];
|
||||
for (int i = 0; i < MAX_ATTRIB_COUNT; i++) {
|
||||
intAttribs[i] = (EGLint)attribs[i];
|
||||
}
|
||||
|
||||
images[0] = m_eglCreateImageKHR(dpy, EGL_NO_CONTEXT,
|
||||
EGL_LINUX_DMA_BUF_EXT,
|
||||
nullptr, intAttribs);
|
||||
if (!images[0]) {
|
||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
|
||||
"eglCreateImageKHR() Failed: %d", eglGetError());
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
#ifdef HAVE_LIBVA
|
||||
|
||||
ssize_t EglImageFactory::exportVAImages(AVFrame *frame, VADRMPRIMESurfaceDescriptor *vaFrame, EGLDisplay dpy, EGLImage images[])
|
||||
{
|
||||
ssize_t count = 0;
|
||||
|
||||
memset(images, 0, sizeof(EGLImage) * EGL_MAX_PLANES);
|
||||
|
||||
SDL_assert(vaFrame->num_layers <= EGL_MAX_PLANES);
|
||||
|
||||
for (size_t i = 0; i < vaFrame->num_layers; ++i) {
|
||||
const auto &layer = vaFrame->layers[i];
|
||||
|
||||
// Max 31 attributes (1 key + 1 value for each)
|
||||
const int EGL_ATTRIB_COUNT = 31 * 2;
|
||||
EGLAttrib attribs[EGL_ATTRIB_COUNT] = {
|
||||
EGL_LINUX_DRM_FOURCC_EXT, layer.drm_format,
|
||||
EGL_WIDTH, i == 0 ? frame->width : frame->width / 2,
|
||||
EGL_HEIGHT, i == 0 ? frame->height : frame->height / 2,
|
||||
EGL_IMAGE_PRESERVED_KHR, EGL_TRUE,
|
||||
};
|
||||
|
||||
int attribIndex = 8;
|
||||
for (size_t j = 0; j < layer.num_planes; j++) {
|
||||
const auto &object = vaFrame->objects[layer.object_index[j]];
|
||||
|
||||
switch (j) {
|
||||
case 0:
|
||||
attribs[attribIndex++] = EGL_DMA_BUF_PLANE0_FD_EXT;
|
||||
attribs[attribIndex++] = object.fd;
|
||||
attribs[attribIndex++] = EGL_DMA_BUF_PLANE0_OFFSET_EXT;
|
||||
attribs[attribIndex++] = layer.offset[0];
|
||||
attribs[attribIndex++] = EGL_DMA_BUF_PLANE0_PITCH_EXT;
|
||||
attribs[attribIndex++] = layer.pitch[0];
|
||||
if (m_EGLExtDmaBuf) {
|
||||
attribs[attribIndex++] = EGL_DMA_BUF_PLANE0_MODIFIER_LO_EXT;
|
||||
attribs[attribIndex++] = (EGLint)(object.drm_format_modifier & 0xFFFFFFFF);
|
||||
attribs[attribIndex++] = EGL_DMA_BUF_PLANE0_MODIFIER_HI_EXT;
|
||||
attribs[attribIndex++] = (EGLint)(object.drm_format_modifier >> 32);
|
||||
}
|
||||
break;
|
||||
|
||||
case 1:
|
||||
attribs[attribIndex++] = EGL_DMA_BUF_PLANE1_FD_EXT;
|
||||
attribs[attribIndex++] = object.fd;
|
||||
attribs[attribIndex++] = EGL_DMA_BUF_PLANE1_OFFSET_EXT;
|
||||
attribs[attribIndex++] = layer.offset[1];
|
||||
attribs[attribIndex++] = EGL_DMA_BUF_PLANE1_PITCH_EXT;
|
||||
attribs[attribIndex++] = layer.pitch[1];
|
||||
if (m_EGLExtDmaBuf) {
|
||||
attribs[attribIndex++] = EGL_DMA_BUF_PLANE1_MODIFIER_LO_EXT;
|
||||
attribs[attribIndex++] = (EGLint)(object.drm_format_modifier & 0xFFFFFFFF);
|
||||
attribs[attribIndex++] = EGL_DMA_BUF_PLANE1_MODIFIER_HI_EXT;
|
||||
attribs[attribIndex++] = (EGLint)(object.drm_format_modifier >> 32);
|
||||
}
|
||||
break;
|
||||
|
||||
case 2:
|
||||
attribs[attribIndex++] = EGL_DMA_BUF_PLANE2_FD_EXT;
|
||||
attribs[attribIndex++] = object.fd;
|
||||
attribs[attribIndex++] = EGL_DMA_BUF_PLANE2_OFFSET_EXT;
|
||||
attribs[attribIndex++] = layer.offset[2];
|
||||
attribs[attribIndex++] = EGL_DMA_BUF_PLANE2_PITCH_EXT;
|
||||
attribs[attribIndex++] = layer.pitch[2];
|
||||
if (m_EGLExtDmaBuf) {
|
||||
attribs[attribIndex++] = EGL_DMA_BUF_PLANE2_MODIFIER_LO_EXT;
|
||||
attribs[attribIndex++] = (EGLint)(object.drm_format_modifier & 0xFFFFFFFF);
|
||||
attribs[attribIndex++] = EGL_DMA_BUF_PLANE2_MODIFIER_HI_EXT;
|
||||
attribs[attribIndex++] = (EGLint)(object.drm_format_modifier >> 32);
|
||||
}
|
||||
break;
|
||||
|
||||
case 3:
|
||||
attribs[attribIndex++] = EGL_DMA_BUF_PLANE3_FD_EXT;
|
||||
attribs[attribIndex++] = object.fd;
|
||||
attribs[attribIndex++] = EGL_DMA_BUF_PLANE3_OFFSET_EXT;
|
||||
attribs[attribIndex++] = layer.offset[3];
|
||||
attribs[attribIndex++] = EGL_DMA_BUF_PLANE3_PITCH_EXT;
|
||||
attribs[attribIndex++] = layer.pitch[3];
|
||||
if (m_EGLExtDmaBuf) {
|
||||
attribs[attribIndex++] = EGL_DMA_BUF_PLANE3_MODIFIER_LO_EXT;
|
||||
attribs[attribIndex++] = (EGLint)(object.drm_format_modifier & 0xFFFFFFFF);
|
||||
attribs[attribIndex++] = EGL_DMA_BUF_PLANE3_MODIFIER_HI_EXT;
|
||||
attribs[attribIndex++] = (EGLint)(object.drm_format_modifier >> 32);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
Q_UNREACHABLE();
|
||||
}
|
||||
}
|
||||
|
||||
// Terminate the attribute list
|
||||
attribs[attribIndex++] = EGL_NONE;
|
||||
SDL_assert(attribIndex <= EGL_ATTRIB_COUNT);
|
||||
|
||||
if (m_eglCreateImage) {
|
||||
images[i] = m_eglCreateImage(dpy, EGL_NO_CONTEXT,
|
||||
EGL_LINUX_DMA_BUF_EXT,
|
||||
nullptr, attribs);
|
||||
if (!images[i]) {
|
||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
|
||||
"eglCreateImage() Failed: %d", eglGetError());
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
else {
|
||||
// Cast the EGLAttrib array elements to EGLint for the KHR extension
|
||||
EGLint intAttribs[EGL_ATTRIB_COUNT];
|
||||
for (int i = 0; i < attribIndex; i++) {
|
||||
intAttribs[i] = (EGLint)attribs[i];
|
||||
}
|
||||
|
||||
images[i] = m_eglCreateImageKHR(dpy, EGL_NO_CONTEXT,
|
||||
EGL_LINUX_DMA_BUF_EXT,
|
||||
nullptr, intAttribs);
|
||||
if (!images[i]) {
|
||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
|
||||
"eglCreateImageKHR() Failed: %d", eglGetError());
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
|
||||
++count;
|
||||
}
|
||||
return count;
|
||||
|
||||
fail:
|
||||
freeEGLImages(dpy, images);
|
||||
return -1;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
void EglImageFactory::freeEGLImages(EGLDisplay dpy, EGLImage images[EGL_MAX_PLANES]) {
|
||||
for (size_t i = 0; i < EGL_MAX_PLANES; ++i) {
|
||||
if (images[i] != nullptr) {
|
||||
if (m_eglDestroyImage) {
|
||||
m_eglDestroyImage(dpy, images[i]);
|
||||
}
|
||||
else {
|
||||
m_eglDestroyImageKHR(dpy, images[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
32
app/streaming/video/ffmpeg-renderers/eglimagefactory.h
Normal file
32
app/streaming/video/ffmpeg-renderers/eglimagefactory.h
Normal file
|
@ -0,0 +1,32 @@
|
|||
#pragma once
|
||||
|
||||
#include "renderer.h"
|
||||
|
||||
#define SDL_USE_BUILTIN_OPENGL_DEFINITIONS 1
|
||||
#include <SDL_egl.h>
|
||||
|
||||
#ifdef HAVE_LIBVA
|
||||
#include <va/va_drmcommon.h>
|
||||
#endif
|
||||
|
||||
class EglImageFactory
|
||||
{
|
||||
public:
|
||||
EglImageFactory(IFFmpegRenderer* renderer);
|
||||
bool initializeEGL(EGLDisplay, const EGLExtensions &ext);
|
||||
ssize_t exportDRMImages(AVFrame* frame, AVDRMFrameDescriptor* drmFrame, EGLDisplay dpy, EGLImage images[EGL_MAX_PLANES]);
|
||||
|
||||
#ifdef HAVE_LIBVA
|
||||
ssize_t exportVAImages(AVFrame* frame, VADRMPRIMESurfaceDescriptor* vaFrame, EGLDisplay dpy, EGLImage images[EGL_MAX_PLANES]);
|
||||
#endif
|
||||
|
||||
void freeEGLImages(EGLDisplay dpy, EGLImage images[EGL_MAX_PLANES]);
|
||||
|
||||
private:
|
||||
IFFmpegRenderer* m_Renderer;
|
||||
bool m_EGLExtDmaBuf;
|
||||
PFNEGLCREATEIMAGEPROC m_eglCreateImage;
|
||||
PFNEGLDESTROYIMAGEPROC m_eglDestroyImage;
|
||||
PFNEGLCREATEIMAGEKHRPROC m_eglCreateImageKHR;
|
||||
PFNEGLDESTROYIMAGEKHRPROC m_eglDestroyImageKHR;
|
||||
};
|
|
@ -17,16 +17,13 @@ VAAPIRenderer::VAAPIRenderer(int decoderSelectionPass)
|
|||
m_HwContext(nullptr),
|
||||
m_BlacklistedForDirectRendering(false),
|
||||
m_OverlayMutex(nullptr)
|
||||
#ifdef HAVE_EGL
|
||||
, m_EglImageFactory(this)
|
||||
#endif
|
||||
{
|
||||
#ifdef HAVE_EGL
|
||||
m_PrimeDescriptor.num_layers = 0;
|
||||
m_PrimeDescriptor.num_objects = 0;
|
||||
m_EGLExtDmaBuf = false;
|
||||
|
||||
m_eglCreateImage = nullptr;
|
||||
m_eglCreateImageKHR = nullptr;
|
||||
m_eglDestroyImage = nullptr;
|
||||
m_eglDestroyImageKHR = nullptr;
|
||||
#endif
|
||||
|
||||
SDL_zero(m_OverlayImage);
|
||||
|
@ -887,35 +884,15 @@ AVPixelFormat VAAPIRenderer::getEGLImagePixelFormat() {
|
|||
}
|
||||
|
||||
bool
|
||||
VAAPIRenderer::initializeEGL(EGLDisplay,
|
||||
VAAPIRenderer::initializeEGL(EGLDisplay dpy,
|
||||
const EGLExtensions &ext) {
|
||||
if (!ext.isSupported("EGL_EXT_image_dma_buf_import")) {
|
||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
|
||||
"VAAPI-EGL: DMABUF unsupported");
|
||||
return false;
|
||||
}
|
||||
m_EGLExtDmaBuf = ext.isSupported("EGL_EXT_image_dma_buf_import_modifiers");
|
||||
|
||||
// NB: eglCreateImage() and eglCreateImageKHR() have slightly different definitions
|
||||
m_eglCreateImage = (typeof(m_eglCreateImage))eglGetProcAddress("eglCreateImage");
|
||||
m_eglCreateImageKHR = (typeof(m_eglCreateImageKHR))eglGetProcAddress("eglCreateImageKHR");
|
||||
m_eglDestroyImage = (typeof(m_eglDestroyImage))eglGetProcAddress("eglDestroyImage");
|
||||
m_eglDestroyImageKHR = (typeof(m_eglDestroyImageKHR))eglGetProcAddress("eglDestroyImageKHR");
|
||||
|
||||
if (!(m_eglCreateImage && m_eglDestroyImage) &&
|
||||
!(m_eglCreateImageKHR && m_eglDestroyImageKHR)) {
|
||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
|
||||
"Missing eglCreateImage()/eglDestroyImage() in EGL driver");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
return m_EglImageFactory.initializeEGL(dpy, ext);
|
||||
}
|
||||
|
||||
ssize_t
|
||||
VAAPIRenderer::exportEGLImages(AVFrame *frame, EGLDisplay dpy,
|
||||
EGLImage images[EGL_MAX_PLANES]) {
|
||||
ssize_t count = 0;
|
||||
ssize_t count;
|
||||
auto hwFrameCtx = (AVHWFramesContext*)frame->hw_frames_ctx->data;
|
||||
AVVAAPIDeviceContext* vaDeviceContext = (AVVAAPIDeviceContext*)hwFrameCtx->device_ctx->hwctx;
|
||||
|
||||
|
@ -931,149 +908,32 @@ VAAPIRenderer::exportEGLImages(AVFrame *frame, EGLDisplay dpy,
|
|||
return -1;
|
||||
}
|
||||
|
||||
SDL_assert(m_PrimeDescriptor.num_layers <= EGL_MAX_PLANES);
|
||||
|
||||
st = vaSyncSurface(vaDeviceContext->display, surface_id);
|
||||
if (st != VA_STATUS_SUCCESS) {
|
||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
|
||||
"vaSyncSurface failed: %d", st);
|
||||
goto sync_fail;
|
||||
"vaSyncSurface() failed: %d", st);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < m_PrimeDescriptor.num_layers; ++i) {
|
||||
const auto &layer = m_PrimeDescriptor.layers[i];
|
||||
|
||||
// Max 31 attributes (1 key + 1 value for each)
|
||||
const int EGL_ATTRIB_COUNT = 31 * 2;
|
||||
EGLAttrib attribs[EGL_ATTRIB_COUNT] = {
|
||||
EGL_LINUX_DRM_FOURCC_EXT, layer.drm_format,
|
||||
EGL_WIDTH, i == 0 ? frame->width : frame->width / 2,
|
||||
EGL_HEIGHT, i == 0 ? frame->height : frame->height / 2,
|
||||
EGL_IMAGE_PRESERVED_KHR, EGL_TRUE,
|
||||
};
|
||||
|
||||
int attribIndex = 8;
|
||||
for (size_t j = 0; j < layer.num_planes; j++) {
|
||||
const auto &object = m_PrimeDescriptor.objects[layer.object_index[j]];
|
||||
|
||||
switch (j) {
|
||||
case 0:
|
||||
attribs[attribIndex++] = EGL_DMA_BUF_PLANE0_FD_EXT;
|
||||
attribs[attribIndex++] = object.fd;
|
||||
attribs[attribIndex++] = EGL_DMA_BUF_PLANE0_OFFSET_EXT;
|
||||
attribs[attribIndex++] = layer.offset[0];
|
||||
attribs[attribIndex++] = EGL_DMA_BUF_PLANE0_PITCH_EXT;
|
||||
attribs[attribIndex++] = layer.pitch[0];
|
||||
if (m_EGLExtDmaBuf) {
|
||||
attribs[attribIndex++] = EGL_DMA_BUF_PLANE0_MODIFIER_LO_EXT;
|
||||
attribs[attribIndex++] = (EGLint)(object.drm_format_modifier & 0xFFFFFFFF);
|
||||
attribs[attribIndex++] = EGL_DMA_BUF_PLANE0_MODIFIER_HI_EXT;
|
||||
attribs[attribIndex++] = (EGLint)(object.drm_format_modifier >> 32);
|
||||
}
|
||||
break;
|
||||
|
||||
case 1:
|
||||
attribs[attribIndex++] = EGL_DMA_BUF_PLANE1_FD_EXT;
|
||||
attribs[attribIndex++] = object.fd;
|
||||
attribs[attribIndex++] = EGL_DMA_BUF_PLANE1_OFFSET_EXT;
|
||||
attribs[attribIndex++] = layer.offset[1];
|
||||
attribs[attribIndex++] = EGL_DMA_BUF_PLANE1_PITCH_EXT;
|
||||
attribs[attribIndex++] = layer.pitch[1];
|
||||
if (m_EGLExtDmaBuf) {
|
||||
attribs[attribIndex++] = EGL_DMA_BUF_PLANE1_MODIFIER_LO_EXT;
|
||||
attribs[attribIndex++] = (EGLint)(object.drm_format_modifier & 0xFFFFFFFF);
|
||||
attribs[attribIndex++] = EGL_DMA_BUF_PLANE1_MODIFIER_HI_EXT;
|
||||
attribs[attribIndex++] = (EGLint)(object.drm_format_modifier >> 32);
|
||||
}
|
||||
break;
|
||||
|
||||
case 2:
|
||||
attribs[attribIndex++] = EGL_DMA_BUF_PLANE2_FD_EXT;
|
||||
attribs[attribIndex++] = object.fd;
|
||||
attribs[attribIndex++] = EGL_DMA_BUF_PLANE2_OFFSET_EXT;
|
||||
attribs[attribIndex++] = layer.offset[2];
|
||||
attribs[attribIndex++] = EGL_DMA_BUF_PLANE2_PITCH_EXT;
|
||||
attribs[attribIndex++] = layer.pitch[2];
|
||||
if (m_EGLExtDmaBuf) {
|
||||
attribs[attribIndex++] = EGL_DMA_BUF_PLANE2_MODIFIER_LO_EXT;
|
||||
attribs[attribIndex++] = (EGLint)(object.drm_format_modifier & 0xFFFFFFFF);
|
||||
attribs[attribIndex++] = EGL_DMA_BUF_PLANE2_MODIFIER_HI_EXT;
|
||||
attribs[attribIndex++] = (EGLint)(object.drm_format_modifier >> 32);
|
||||
}
|
||||
break;
|
||||
|
||||
case 3:
|
||||
attribs[attribIndex++] = EGL_DMA_BUF_PLANE3_FD_EXT;
|
||||
attribs[attribIndex++] = object.fd;
|
||||
attribs[attribIndex++] = EGL_DMA_BUF_PLANE3_OFFSET_EXT;
|
||||
attribs[attribIndex++] = layer.offset[3];
|
||||
attribs[attribIndex++] = EGL_DMA_BUF_PLANE3_PITCH_EXT;
|
||||
attribs[attribIndex++] = layer.pitch[3];
|
||||
if (m_EGLExtDmaBuf) {
|
||||
attribs[attribIndex++] = EGL_DMA_BUF_PLANE3_MODIFIER_LO_EXT;
|
||||
attribs[attribIndex++] = (EGLint)(object.drm_format_modifier & 0xFFFFFFFF);
|
||||
attribs[attribIndex++] = EGL_DMA_BUF_PLANE3_MODIFIER_HI_EXT;
|
||||
attribs[attribIndex++] = (EGLint)(object.drm_format_modifier >> 32);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
Q_UNREACHABLE();
|
||||
}
|
||||
}
|
||||
|
||||
// Terminate the attribute list
|
||||
attribs[attribIndex++] = EGL_NONE;
|
||||
SDL_assert(attribIndex <= EGL_ATTRIB_COUNT);
|
||||
|
||||
if (m_eglCreateImage) {
|
||||
images[i] = m_eglCreateImage(dpy, EGL_NO_CONTEXT,
|
||||
EGL_LINUX_DMA_BUF_EXT,
|
||||
nullptr, attribs);
|
||||
if (!images[i]) {
|
||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
|
||||
"eglCreateImage() Failed: %d", eglGetError());
|
||||
goto create_image_fail;
|
||||
}
|
||||
}
|
||||
else {
|
||||
// Cast the EGLAttrib array elements to EGLint for the KHR extension
|
||||
EGLint intAttribs[EGL_ATTRIB_COUNT];
|
||||
for (int i = 0; i < attribIndex; i++) {
|
||||
intAttribs[i] = (EGLint)attribs[i];
|
||||
}
|
||||
|
||||
images[i] = m_eglCreateImageKHR(dpy, EGL_NO_CONTEXT,
|
||||
EGL_LINUX_DMA_BUF_EXT,
|
||||
nullptr, intAttribs);
|
||||
if (!images[i]) {
|
||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
|
||||
"eglCreateImageKHR() Failed: %d", eglGetError());
|
||||
goto create_image_fail;
|
||||
}
|
||||
}
|
||||
|
||||
++count;
|
||||
count = m_EglImageFactory.exportVAImages(frame, &m_PrimeDescriptor, dpy, images);
|
||||
if (count < 0) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
return count;
|
||||
|
||||
create_image_fail:
|
||||
m_PrimeDescriptor.num_layers = count;
|
||||
sync_fail:
|
||||
freeEGLImages(dpy, images);
|
||||
fail:
|
||||
for (size_t i = 0; i < m_PrimeDescriptor.num_objects; ++i) {
|
||||
close(m_PrimeDescriptor.objects[i].fd);
|
||||
}
|
||||
m_PrimeDescriptor.num_layers = 0;
|
||||
m_PrimeDescriptor.num_objects = 0;
|
||||
return -1;
|
||||
}
|
||||
|
||||
void
|
||||
VAAPIRenderer::freeEGLImages(EGLDisplay dpy, EGLImage images[EGL_MAX_PLANES]) {
|
||||
for (size_t i = 0; i < m_PrimeDescriptor.num_layers; ++i) {
|
||||
if (m_eglDestroyImage) {
|
||||
m_eglDestroyImage(dpy, images[i]);
|
||||
}
|
||||
else {
|
||||
m_eglDestroyImageKHR(dpy, images[i]);
|
||||
}
|
||||
}
|
||||
m_EglImageFactory.freeEGLImages(dpy, images);
|
||||
for (size_t i = 0; i < m_PrimeDescriptor.num_objects; ++i) {
|
||||
close(m_PrimeDescriptor.objects[i].fd);
|
||||
}
|
||||
|
|
|
@ -14,6 +14,10 @@
|
|||
#undef HAVE_LIBVA_WAYLAND
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_EGL
|
||||
#include "eglimagefactory.h"
|
||||
#endif
|
||||
|
||||
extern "C" {
|
||||
#include <va/va.h>
|
||||
#ifdef HAVE_LIBVA_X11
|
||||
|
@ -93,10 +97,6 @@ private:
|
|||
|
||||
#ifdef HAVE_EGL
|
||||
VADRMPRIMESurfaceDescriptor m_PrimeDescriptor;
|
||||
bool m_EGLExtDmaBuf;
|
||||
PFNEGLCREATEIMAGEPROC m_eglCreateImage;
|
||||
PFNEGLDESTROYIMAGEPROC m_eglDestroyImage;
|
||||
PFNEGLCREATEIMAGEKHRPROC m_eglCreateImageKHR;
|
||||
PFNEGLDESTROYIMAGEKHRPROC m_eglDestroyImageKHR;
|
||||
EglImageFactory m_EglImageFactory;
|
||||
#endif
|
||||
};
|
||||
|
|
Loading…
Reference in a new issue