mirror of
https://github.com/moonlight-stream/moonlight-qt
synced 2024-12-14 05:12:27 +00:00
Allow DRMRenderer to be used for indirect rendering
This commit is contained in:
parent
1e31f6fe77
commit
6a66b462ce
2 changed files with 57 additions and 23 deletions
|
@ -24,6 +24,7 @@ DrmRenderer::DrmRenderer()
|
||||||
: m_HwContext(nullptr),
|
: m_HwContext(nullptr),
|
||||||
m_DrmFd(-1),
|
m_DrmFd(-1),
|
||||||
m_SdlOwnsDrmFd(false),
|
m_SdlOwnsDrmFd(false),
|
||||||
|
m_SupportsDirectRendering(false),
|
||||||
m_CrtcId(0),
|
m_CrtcId(0),
|
||||||
m_PlaneId(0),
|
m_PlaneId(0),
|
||||||
m_CurrentFbId(0)
|
m_CurrentFbId(0)
|
||||||
|
@ -101,12 +102,43 @@ bool DrmRenderer::initialize(PDECODER_PARAMETERS params)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Create the device context first because it is needed whether we can
|
||||||
|
// actually use direct rendering or not.
|
||||||
|
m_HwContext = av_hwdevice_ctx_alloc(AV_HWDEVICE_TYPE_DRM);
|
||||||
|
if (m_HwContext == nullptr) {
|
||||||
|
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
|
||||||
|
"av_hwdevice_ctx_alloc(DRM) failed");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
AVHWDeviceContext* deviceContext = (AVHWDeviceContext*)m_HwContext->data;
|
||||||
|
AVDRMDeviceContext* drmDeviceContext = (AVDRMDeviceContext*)deviceContext->hwctx;
|
||||||
|
|
||||||
|
drmDeviceContext->fd = m_DrmFd;
|
||||||
|
|
||||||
|
int err = av_hwdevice_ctx_init(m_HwContext);
|
||||||
|
if (err < 0) {
|
||||||
|
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
|
||||||
|
"av_hwdevice_ctx_init(DRM) failed: %d",
|
||||||
|
err);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef HAVE_EGL
|
||||||
|
// Still return true if we fail to initialize DRM direct rendering
|
||||||
|
// stuff, since we have EGL that we can use for indirect rendering.
|
||||||
|
const bool DIRECT_RENDERING_INIT_FAILED = true;
|
||||||
|
#else
|
||||||
|
// Fail if we can't initialize direct rendering and we don't have EGL.
|
||||||
|
const bool DIRECT_RENDERING_INIT_FAILED = false;
|
||||||
|
#endif
|
||||||
|
|
||||||
drmModeRes* resources = drmModeGetResources(m_DrmFd);
|
drmModeRes* resources = drmModeGetResources(m_DrmFd);
|
||||||
if (resources == nullptr) {
|
if (resources == nullptr) {
|
||||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
|
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
|
||||||
"drmModeGetResources() failed: %d",
|
"drmModeGetResources() failed: %d",
|
||||||
errno);
|
errno);
|
||||||
return false;
|
return DIRECT_RENDERING_INIT_FAILED;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Look for a connected connector and get the associated encoder
|
// Look for a connected connector and get the associated encoder
|
||||||
|
@ -126,7 +158,7 @@ bool DrmRenderer::initialize(PDECODER_PARAMETERS params)
|
||||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
|
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
|
||||||
"No connected displays found!");
|
"No connected displays found!");
|
||||||
drmModeFreeResources(resources);
|
drmModeFreeResources(resources);
|
||||||
return false;
|
return DIRECT_RENDERING_INIT_FAILED;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Now find the CRTC from the encoder
|
// Now find the CRTC from the encoder
|
||||||
|
@ -146,7 +178,7 @@ bool DrmRenderer::initialize(PDECODER_PARAMETERS params)
|
||||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
|
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
|
||||||
"DRM encoder not found!");
|
"DRM encoder not found!");
|
||||||
drmModeFreeResources(resources);
|
drmModeFreeResources(resources);
|
||||||
return false;
|
return DIRECT_RENDERING_INIT_FAILED;
|
||||||
}
|
}
|
||||||
|
|
||||||
int crtcIndex = -1;
|
int crtcIndex = -1;
|
||||||
|
@ -167,7 +199,7 @@ bool DrmRenderer::initialize(PDECODER_PARAMETERS params)
|
||||||
if (crtcIndex == -1) {
|
if (crtcIndex == -1) {
|
||||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
|
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
|
||||||
"Failed to get CRTC!");
|
"Failed to get CRTC!");
|
||||||
return false;
|
return DIRECT_RENDERING_INIT_FAILED;
|
||||||
}
|
}
|
||||||
|
|
||||||
drmSetClientCap(m_DrmFd, DRM_CLIENT_CAP_UNIVERSAL_PLANES, 1);
|
drmSetClientCap(m_DrmFd, DRM_CLIENT_CAP_UNIVERSAL_PLANES, 1);
|
||||||
|
@ -177,7 +209,7 @@ bool DrmRenderer::initialize(PDECODER_PARAMETERS params)
|
||||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
|
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
|
||||||
"drmGetPlaneResources() failed: %d",
|
"drmGetPlaneResources() failed: %d",
|
||||||
errno);
|
errno);
|
||||||
return false;
|
return DIRECT_RENDERING_INIT_FAILED;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Find an NV12 overlay plane to render on
|
// Find an NV12 overlay plane to render on
|
||||||
|
@ -222,25 +254,14 @@ bool DrmRenderer::initialize(PDECODER_PARAMETERS params)
|
||||||
|
|
||||||
drmModeFreePlaneResources(planeRes);
|
drmModeFreePlaneResources(planeRes);
|
||||||
|
|
||||||
m_HwContext = av_hwdevice_ctx_alloc(AV_HWDEVICE_TYPE_DRM);
|
if (m_PlaneId == 0) {
|
||||||
if (m_HwContext == nullptr) {
|
|
||||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
|
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
|
||||||
"av_hwdevice_ctx_alloc(DRM) failed");
|
"Failed to find suitable NV12 overlay plane!");
|
||||||
return false;
|
return DIRECT_RENDERING_INIT_FAILED;
|
||||||
}
|
}
|
||||||
|
|
||||||
AVHWDeviceContext* deviceContext = (AVHWDeviceContext*)m_HwContext->data;
|
// If we got this far, we can do direct rendering via the DRM FD.
|
||||||
AVDRMDeviceContext* drmDeviceContext = (AVDRMDeviceContext*)deviceContext->hwctx;
|
m_SupportsDirectRendering = true;
|
||||||
|
|
||||||
drmDeviceContext->fd = m_DrmFd;
|
|
||||||
|
|
||||||
int err = av_hwdevice_ctx_init(m_HwContext);
|
|
||||||
if (err < 0) {
|
|
||||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
|
|
||||||
"av_hwdevice_ctx_init(DRM) failed: %d",
|
|
||||||
err);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -335,6 +356,16 @@ void DrmRenderer::renderFrame(AVFrame* frame)
|
||||||
drmModeRmFB(m_DrmFd, lastFbId);
|
drmModeRmFB(m_DrmFd, lastFbId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool DrmRenderer::needsTestFrame()
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool DrmRenderer::isDirectRenderingSupported()
|
||||||
|
{
|
||||||
|
return m_SupportsDirectRendering;
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef HAVE_EGL
|
#ifdef HAVE_EGL
|
||||||
|
|
||||||
bool DrmRenderer::canExportEGL() {
|
bool DrmRenderer::canExportEGL() {
|
||||||
|
|
|
@ -14,6 +14,8 @@ public:
|
||||||
virtual void renderFrame(AVFrame* frame) override;
|
virtual void renderFrame(AVFrame* frame) override;
|
||||||
virtual enum AVPixelFormat getPreferredPixelFormat(int videoFormat) override;
|
virtual enum AVPixelFormat getPreferredPixelFormat(int videoFormat) override;
|
||||||
virtual int getRendererAttributes() override;
|
virtual int getRendererAttributes() override;
|
||||||
|
virtual bool needsTestFrame() override;
|
||||||
|
virtual bool isDirectRenderingSupported() override;
|
||||||
#ifdef HAVE_EGL
|
#ifdef HAVE_EGL
|
||||||
virtual bool canExportEGL() override;
|
virtual bool canExportEGL() override;
|
||||||
virtual bool initializeEGL(EGLDisplay dpy, const EGLExtensions &ext) override;
|
virtual bool initializeEGL(EGLDisplay dpy, const EGLExtensions &ext) override;
|
||||||
|
@ -25,6 +27,7 @@ private:
|
||||||
AVBufferRef* m_HwContext;
|
AVBufferRef* m_HwContext;
|
||||||
int m_DrmFd;
|
int m_DrmFd;
|
||||||
bool m_SdlOwnsDrmFd;
|
bool m_SdlOwnsDrmFd;
|
||||||
|
bool m_SupportsDirectRendering;
|
||||||
uint32_t m_CrtcId;
|
uint32_t m_CrtcId;
|
||||||
uint32_t m_PlaneId;
|
uint32_t m_PlaneId;
|
||||||
uint32_t m_CurrentFbId;
|
uint32_t m_CurrentFbId;
|
||||||
|
|
Loading…
Reference in a new issue