diff options
author | Arne Morten Kvarving <spiff@kodi.tv> | 2019-06-17 08:45:46 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2019-06-17 08:45:46 +0200 |
commit | 79dcf62e412bc0c5904dd73f5983ba77311f0c4d (patch) | |
tree | abbea77999d8d7acaed9b72b09598bee11d3f684 | |
parent | 2ebf43de424d2e8834e4851c4bbe822e8252687f (diff) | |
parent | b992f859e732ab7e4970c1b6ee2f5f0927b75bb6 (diff) |
Merge pull request #16274 from Kwiboo/backport-gbm-drmprime
Backport fixes and improvements for GBM and DRM PRIME
21 files changed, 667 insertions, 265 deletions
diff --git a/cmake/treedata/optional/common/gbm.txt b/cmake/treedata/optional/common/gbm.txt index 196b32357f..d6e6e9ebdc 100644 --- a/cmake/treedata/optional/common/gbm.txt +++ b/cmake/treedata/optional/common/gbm.txt @@ -1,2 +1,3 @@ xbmc/cores/RetroPlayer/process/gbm cores/RetroPlayer/process/gbm # GBM +xbmc/cores/VideoPlayer/Process/gbm cores/VideoPlayer/Process/gbm # GBM xbmc/windowing/gbm windowing/gbm # GBM
\ No newline at end of file diff --git a/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecDRMPRIME.cpp b/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecDRMPRIME.cpp index 382b163a71..48796e944b 100644 --- a/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecDRMPRIME.cpp +++ b/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecDRMPRIME.cpp @@ -10,6 +10,7 @@ #include "ServiceBroker.h" #include "cores/VideoPlayer/DVDCodecs/DVDFactoryCodec.h" +#include "cores/VideoPlayer/Process/gbm/VideoBufferDRMPRIME.h" #include "settings/Settings.h" #include "settings/SettingsComponent.h" #include "settings/lib/Setting.h" @@ -24,137 +25,6 @@ extern "C" { using namespace KODI::WINDOWING::GBM; -//------------------------------------------------------------------------------ -// Video Buffers -//------------------------------------------------------------------------------ - -CVideoBufferDRMPRIME::CVideoBufferDRMPRIME(IVideoBufferPool& pool, int id) - : CVideoBuffer(id) -{ - m_pFrame = av_frame_alloc(); -} - -CVideoBufferDRMPRIME::~CVideoBufferDRMPRIME() -{ - Unref(); - av_frame_free(&m_pFrame); -} - -void CVideoBufferDRMPRIME::SetRef(AVFrame* frame) -{ - av_frame_move_ref(m_pFrame, frame); -} - -void CVideoBufferDRMPRIME::Unref() -{ - av_frame_unref(m_pFrame); -} - -int CVideoBufferDRMPRIME::GetColorEncoding() const -{ - switch (m_pFrame->colorspace) - { - case AVCOL_SPC_BT2020_CL: - case AVCOL_SPC_BT2020_NCL: - return DRM_COLOR_YCBCR_BT2020; - case AVCOL_SPC_SMPTE170M: - case AVCOL_SPC_BT470BG: - case AVCOL_SPC_FCC: - return DRM_COLOR_YCBCR_BT601; - case AVCOL_SPC_BT709: - return DRM_COLOR_YCBCR_BT709; - case AVCOL_SPC_RESERVED: - case AVCOL_SPC_UNSPECIFIED: - default: - if (m_pFrame->width > 1024 || m_pFrame->height >= 600) - return DRM_COLOR_YCBCR_BT709; - else - return DRM_COLOR_YCBCR_BT601; - } -} - -int CVideoBufferDRMPRIME::GetColorRange() const -{ - switch (m_pFrame->color_range) - { - case AVCOL_RANGE_JPEG: - return DRM_COLOR_YCBCR_FULL_RANGE; - case AVCOL_RANGE_MPEG: - default: - return DRM_COLOR_YCBCR_LIMITED_RANGE; - } -} - -//------------------------------------------------------------------------------ - -class CVideoBufferPoolDRMPRIME - : public IVideoBufferPool -{ -public: - ~CVideoBufferPoolDRMPRIME(); - void Return(int id) override; - CVideoBuffer* Get() override; - -protected: - CCriticalSection m_critSection; - std::vector<CVideoBufferDRMPRIME*> m_all; - std::deque<int> m_used; - std::deque<int> m_free; -}; - -CVideoBufferPoolDRMPRIME::~CVideoBufferPoolDRMPRIME() -{ - for (auto buf : m_all) - delete buf; -} - -CVideoBuffer* CVideoBufferPoolDRMPRIME::Get() -{ - CSingleLock lock(m_critSection); - - CVideoBufferDRMPRIME* buf = nullptr; - if (!m_free.empty()) - { - int idx = m_free.front(); - m_free.pop_front(); - m_used.push_back(idx); - buf = m_all[idx]; - } - else - { - int id = m_all.size(); - buf = new CVideoBufferDRMPRIME(*this, id); - m_all.push_back(buf); - m_used.push_back(id); - } - - buf->Acquire(GetPtr()); - return buf; -} - -void CVideoBufferPoolDRMPRIME::Return(int id) -{ - CSingleLock lock(m_critSection); - - m_all[id]->Unref(); - auto it = m_used.begin(); - while (it != m_used.end()) - { - if (*it == id) - { - m_used.erase(it); - break; - } - else - ++it; - } - m_free.push_back(id); -} - -//------------------------------------------------------------------------------ -// main class -//------------------------------------------------------------------------------ - CDVDVideoCodecDRMPRIME::CDVDVideoCodecDRMPRIME(CProcessInfo& processInfo) : CDVDVideoCodec(processInfo) { @@ -220,11 +90,17 @@ static const AVCodec* FindDecoder(CDVDStreamInfo& hints) return nullptr; } -static enum AVPixelFormat GetFormat(struct AVCodecContext* avctx, const enum AVPixelFormat* fmt) +enum AVPixelFormat CDVDVideoCodecDRMPRIME::GetFormat(struct AVCodecContext* avctx, const enum AVPixelFormat* fmt) { for (int n = 0; fmt[n] != AV_PIX_FMT_NONE; n++) + { if (fmt[n] == AV_PIX_FMT_DRM_PRIME) + { + CDVDVideoCodecDRMPRIME* ctx = static_cast<CDVDVideoCodecDRMPRIME*>(avctx->opaque); + ctx->UpdateProcessInfo(avctx, fmt[n]); return fmt[n]; + } + } return AV_PIX_FMT_NONE; } @@ -259,6 +135,7 @@ bool CDVDVideoCodecDRMPRIME::Open(CDVDStreamInfo& hints, CDVDCodecOptions& optio } m_pCodecContext->pix_fmt = AV_PIX_FMT_DRM_PRIME; + m_pCodecContext->opaque = static_cast<void*>(this); m_pCodecContext->get_format = GetFormat; m_pCodecContext->codec_tag = hints.codec_tag; m_pCodecContext->coded_width = hints.width; @@ -281,27 +158,25 @@ bool CDVDVideoCodecDRMPRIME::Open(CDVDStreamInfo& hints, CDVDCodecOptions& optio return false; } - if (m_pCodecContext->pix_fmt != AV_PIX_FMT_DRM_PRIME) - { - CLog::Log(LOGNOTICE, "CDVDVideoCodecDRMPRIME::%s - unexpected pix fmt %s", __FUNCTION__, av_get_pix_fmt_name(m_pCodecContext->pix_fmt)); - avcodec_free_context(&m_pCodecContext); - return false; - } - - const char* pixFmtName = av_get_pix_fmt_name(m_pCodecContext->pix_fmt); - m_processInfo.SetVideoPixelFormat(pixFmtName ? pixFmtName : ""); - m_processInfo.SetVideoDimensions(hints.width, hints.height); + UpdateProcessInfo(m_pCodecContext, m_pCodecContext->pix_fmt); m_processInfo.SetVideoDeintMethod("none"); m_processInfo.SetVideoDAR(hints.aspect); - if (pCodec->name) - m_name = std::string("ff-") + pCodec->name; + return true; +} + +void CDVDVideoCodecDRMPRIME::UpdateProcessInfo(struct AVCodecContext* avctx, const enum AVPixelFormat pix_fmt) +{ + const char* pixFmtName = av_get_pix_fmt_name(pix_fmt); + m_processInfo.SetVideoPixelFormat(pixFmtName ? pixFmtName : ""); + m_processInfo.SetVideoDimensions(avctx->coded_width, avctx->coded_height); + + if (avctx->codec && avctx->codec->name) + m_name = std::string("ff-") + avctx->codec->name; else m_name = "ffmpeg"; - m_processInfo.SetVideoDecoderName(m_name, true); - - return true; + m_processInfo.SetVideoDecoderName(m_name, pix_fmt == AV_PIX_FMT_DRM_PRIME); } bool CDVDVideoCodecDRMPRIME::AddData(const DemuxPacket& packet) @@ -412,9 +287,18 @@ CDVDVideoCodec::VCReturn CDVDVideoCodecDRMPRIME::GetPicture(VideoPicture* pVideo SetPictureParams(pVideoPicture); - CVideoBufferDRMPRIME* buffer = dynamic_cast<CVideoBufferDRMPRIME*>(m_videoBufferPool->Get()); - buffer->SetRef(m_pFrame); - pVideoPicture->videoBuffer = buffer; + if (m_pFrame->format == AV_PIX_FMT_DRM_PRIME) + { + CVideoBufferDRMPRIME* buffer = dynamic_cast<CVideoBufferDRMPRIME*>(m_videoBufferPool->Get()); + buffer->SetRef(m_pFrame); + pVideoPicture->videoBuffer = buffer; + } + + if (!pVideoPicture->videoBuffer) + { + CLog::Log(LOGERROR, "CDVDVideoCodecDRMPRIME::{} - videoBuffer:nullptr format:{}", __FUNCTION__, av_get_pix_fmt_name(static_cast<AVPixelFormat>(m_pFrame->format))); + return VC_ERROR; + } return VC_PICTURE; } diff --git a/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecDRMPRIME.h b/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecDRMPRIME.h index cb2929e545..8d399eb5bc 100644 --- a/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecDRMPRIME.h +++ b/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecDRMPRIME.h @@ -13,45 +13,6 @@ #include "cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodec.h" #include "cores/VideoPlayer/Process/VideoBuffer.h" -extern "C" { -#include <libavutil/frame.h> -#include <libavutil/hwcontext_drm.h> -} - -// Color enums is copied from linux include/drm/drm_color_mgmt.h (strangely not part of uapi) -enum drm_color_encoding { - DRM_COLOR_YCBCR_BT601, - DRM_COLOR_YCBCR_BT709, - DRM_COLOR_YCBCR_BT2020, -}; -enum drm_color_range { - DRM_COLOR_YCBCR_LIMITED_RANGE, - DRM_COLOR_YCBCR_FULL_RANGE, -}; - -class CVideoBufferPoolDRMPRIME; - -class CVideoBufferDRMPRIME - : public CVideoBuffer -{ -public: - CVideoBufferDRMPRIME(IVideoBufferPool& pool, int id); - ~CVideoBufferDRMPRIME(); - void SetRef(AVFrame* frame); - void Unref(); - - uint32_t m_fb_id = 0; - uint32_t m_handles[AV_DRM_MAX_PLANES] = {0}; - - AVDRMFrameDescriptor* GetDescriptor() const { return reinterpret_cast<AVDRMFrameDescriptor*>(m_pFrame->data[0]); } - uint32_t GetWidth() const { return m_pFrame->width; } - uint32_t GetHeight() const { return m_pFrame->height; } - int GetColorEncoding() const; - int GetColorRange() const; -protected: - AVFrame* m_pFrame = nullptr; -}; - class CDVDVideoCodecDRMPRIME : public CDVDVideoCodec { @@ -73,10 +34,12 @@ public: protected: void Drain(); void SetPictureParams(VideoPicture* pVideoPicture); + void UpdateProcessInfo(struct AVCodecContext* avctx, const enum AVPixelFormat fmt); + static enum AVPixelFormat GetFormat(struct AVCodecContext* avctx, const enum AVPixelFormat* fmt); std::string m_name; int m_codecControlFlags = 0; AVCodecContext* m_pCodecContext = nullptr; AVFrame* m_pFrame = nullptr; - std::shared_ptr<CVideoBufferPoolDRMPRIME> m_videoBufferPool; + std::shared_ptr<IVideoBufferPool> m_videoBufferPool; }; diff --git a/xbmc/cores/VideoPlayer/Process/gbm/CMakeLists.txt b/xbmc/cores/VideoPlayer/Process/gbm/CMakeLists.txt new file mode 100644 index 0000000000..d1398d77a3 --- /dev/null +++ b/xbmc/cores/VideoPlayer/Process/gbm/CMakeLists.txt @@ -0,0 +1,7 @@ +set(SOURCES ProcessInfoGBM.cpp + VideoBufferDRMPRIME.cpp) + +set(HEADERS ProcessInfoGBM.h + VideoBufferDRMPRIME.h) + +core_add_library(processGBM) diff --git a/xbmc/cores/VideoPlayer/Process/gbm/ProcessInfoGBM.cpp b/xbmc/cores/VideoPlayer/Process/gbm/ProcessInfoGBM.cpp new file mode 100644 index 0000000000..0228319397 --- /dev/null +++ b/xbmc/cores/VideoPlayer/Process/gbm/ProcessInfoGBM.cpp @@ -0,0 +1,34 @@ +/* + * Copyright (C) 2019 Team Kodi + * This file is part of Kodi - https://kodi.tv + * + * SPDX-License-Identifier: GPL-2.0-or-later + * See LICENSES/README.md for more information. + */ + +#include "ProcessInfoGBM.h" + +using namespace VIDEOPLAYER; + +CProcessInfo* CProcessInfoGBM::Create() +{ + return new CProcessInfoGBM(); +} + +void CProcessInfoGBM::Register() +{ + CProcessInfo::RegisterProcessControl("gbm", CProcessInfoGBM::Create); +} + +CProcessInfoGBM::CProcessInfoGBM() +{ +} + +EINTERLACEMETHOD CProcessInfoGBM::GetFallbackDeintMethod() +{ +#if defined(__arm__) + return EINTERLACEMETHOD::VS_INTERLACEMETHOD_DEINTERLACE_HALF; +#else + return CProcessInfo::GetFallbackDeintMethod(); +#endif +} diff --git a/xbmc/cores/VideoPlayer/Process/gbm/ProcessInfoGBM.h b/xbmc/cores/VideoPlayer/Process/gbm/ProcessInfoGBM.h new file mode 100644 index 0000000000..479e4fde4c --- /dev/null +++ b/xbmc/cores/VideoPlayer/Process/gbm/ProcessInfoGBM.h @@ -0,0 +1,26 @@ +/* + * Copyright (C) 2019 Team Kodi + * This file is part of Kodi - https://kodi.tv + * + * SPDX-License-Identifier: GPL-2.0-or-later + * See LICENSES/README.md for more information. + */ + +#pragma once + +#include "cores/IPlayer.h" +#include "cores/VideoPlayer/Process/ProcessInfo.h" + +namespace VIDEOPLAYER +{ + +class CProcessInfoGBM : public CProcessInfo +{ +public: + CProcessInfoGBM(); + static CProcessInfo* Create(); + static void Register(); + EINTERLACEMETHOD GetFallbackDeintMethod() override; +}; + +} // namespace VIDEOPLAYER diff --git a/xbmc/cores/VideoPlayer/Process/gbm/VideoBufferDRMPRIME.cpp b/xbmc/cores/VideoPlayer/Process/gbm/VideoBufferDRMPRIME.cpp new file mode 100644 index 0000000000..719f0185bc --- /dev/null +++ b/xbmc/cores/VideoPlayer/Process/gbm/VideoBufferDRMPRIME.cpp @@ -0,0 +1,134 @@ +/* + * Copyright (C) 2017-2018 Team Kodi + * This file is part of Kodi - https://kodi.tv + * + * SPDX-License-Identifier: GPL-2.0-or-later + * See LICENSES/README.md for more information. + */ + +#include "VideoBufferDRMPRIME.h" + +#include "threads/SingleLock.h" + +extern "C" +{ +#include <libavcodec/avcodec.h> +#include <libavutil/pixdesc.h> +} + +IVideoBufferDRMPRIME::IVideoBufferDRMPRIME(int id) + : CVideoBuffer(id) +{ +} + +CVideoBufferDRMPRIME::CVideoBufferDRMPRIME(IVideoBufferPool& pool, int id) + : IVideoBufferDRMPRIME(id) +{ + m_pFrame = av_frame_alloc(); +} + +CVideoBufferDRMPRIME::~CVideoBufferDRMPRIME() +{ + Unref(); + av_frame_free(&m_pFrame); +} + +void CVideoBufferDRMPRIME::SetRef(AVFrame* frame) +{ + av_frame_move_ref(m_pFrame, frame); +} + +void CVideoBufferDRMPRIME::Unref() +{ + av_frame_unref(m_pFrame); +} + +int CVideoBufferDRMPRIME::GetColorEncoding() const +{ + switch (m_pFrame->colorspace) + { + case AVCOL_SPC_BT2020_CL: + case AVCOL_SPC_BT2020_NCL: + return DRM_COLOR_YCBCR_BT2020; + case AVCOL_SPC_SMPTE170M: + case AVCOL_SPC_BT470BG: + case AVCOL_SPC_FCC: + return DRM_COLOR_YCBCR_BT601; + case AVCOL_SPC_BT709: + return DRM_COLOR_YCBCR_BT709; + case AVCOL_SPC_RESERVED: + case AVCOL_SPC_UNSPECIFIED: + default: + if (m_pFrame->width > 1024 || m_pFrame->height >= 600) + return DRM_COLOR_YCBCR_BT709; + else + return DRM_COLOR_YCBCR_BT601; + } +} + +int CVideoBufferDRMPRIME::GetColorRange() const +{ + switch (m_pFrame->color_range) + { + case AVCOL_RANGE_JPEG: + return DRM_COLOR_YCBCR_FULL_RANGE; + case AVCOL_RANGE_MPEG: + default: + return DRM_COLOR_YCBCR_LIMITED_RANGE; + } +} + +bool CVideoBufferDRMPRIME::IsValid() const +{ + AVDRMFrameDescriptor* descriptor = GetDescriptor(); + return descriptor && descriptor->nb_layers; +} + +CVideoBufferPoolDRMPRIME::~CVideoBufferPoolDRMPRIME() +{ + for (auto buf : m_all) + delete buf; +} + +CVideoBuffer* CVideoBufferPoolDRMPRIME::Get() +{ + CSingleLock lock(m_critSection); + + CVideoBufferDRMPRIME* buf = nullptr; + if (!m_free.empty()) + { + int idx = m_free.front(); + m_free.pop_front(); + m_used.push_back(idx); + buf = m_all[idx]; + } + else + { + int id = m_all.size(); + buf = new CVideoBufferDRMPRIME(*this, id); + m_all.push_back(buf); + m_used.push_back(id); + } + + buf->Acquire(GetPtr()); + return buf; +} + +void CVideoBufferPoolDRMPRIME::Return(int id) +{ + CSingleLock lock(m_critSection); + + m_all[id]->Unref(); + auto it = m_used.begin(); + while (it != m_used.end()) + { + if (*it == id) + { + m_used.erase(it); + break; + } + else + ++it; + } + m_free.push_back(id); +} diff --git a/xbmc/cores/VideoPlayer/Process/gbm/VideoBufferDRMPRIME.h b/xbmc/cores/VideoPlayer/Process/gbm/VideoBufferDRMPRIME.h new file mode 100644 index 0000000000..643395a681 --- /dev/null +++ b/xbmc/cores/VideoPlayer/Process/gbm/VideoBufferDRMPRIME.h @@ -0,0 +1,108 @@ +/* + * Copyright (C) 2017-2018 Team Kodi + * This file is part of Kodi - https://kodi.tv + * + * SPDX-License-Identifier: GPL-2.0-or-later + * See LICENSES/README.md for more information. + */ + +#pragma once + +#include "cores/VideoPlayer/Process/VideoBuffer.h" + +extern "C" +{ +#include <libavutil/frame.h> +#include <libavutil/hwcontext_drm.h> +} + +// Color enums is copied from linux include/drm/drm_color_mgmt.h (strangely not part of uapi) +enum drm_color_encoding +{ + DRM_COLOR_YCBCR_BT601, + DRM_COLOR_YCBCR_BT709, + DRM_COLOR_YCBCR_BT2020, +}; +enum drm_color_range +{ + DRM_COLOR_YCBCR_LIMITED_RANGE, + DRM_COLOR_YCBCR_FULL_RANGE, +}; + +class IVideoBufferDRMPRIME : public CVideoBuffer +{ +public: + IVideoBufferDRMPRIME() = delete; + virtual ~IVideoBufferDRMPRIME() = default; + + virtual AVDRMFrameDescriptor* GetDescriptor() const = 0; + virtual uint32_t GetWidth() const = 0; + virtual uint32_t GetHeight() const = 0; + virtual int GetColorEncoding() const + { + return DRM_COLOR_YCBCR_BT709; + }; + virtual int GetColorRange() const + { + return DRM_COLOR_YCBCR_LIMITED_RANGE; + }; + + virtual bool IsValid() const + { + return true; + }; + virtual bool Map() + { + return true; + }; + virtual void Unmap() {}; + + uint32_t m_fb_id = 0; + uint32_t m_handles[AV_DRM_MAX_PLANES] = {}; + +protected: + explicit IVideoBufferDRMPRIME(int id); +}; + +class CVideoBufferDRMPRIME : public IVideoBufferDRMPRIME +{ +public: + CVideoBufferDRMPRIME(IVideoBufferPool& pool, int id); + ~CVideoBufferDRMPRIME(); + void SetRef(AVFrame* frame); + void Unref(); + + AVDRMFrameDescriptor* GetDescriptor() const override + { + return reinterpret_cast<AVDRMFrameDescriptor*>(m_pFrame->data[0]); + } + uint32_t GetWidth() const override + { + return m_pFrame->width; + } + uint32_t GetHeight() const override + { + return m_pFrame->height; + } + int GetColorEncoding() const override; + int GetColorRange() const override; + + bool IsValid() const override; + +protected: + AVFrame* m_pFrame = nullptr; +}; + +class CVideoBufferPoolDRMPRIME : public IVideoBufferPool +{ +public: + ~CVideoBufferPoolDRMPRIME(); + void Return(int id) override; + CVideoBuffer* Get() override; + +protected: + CCriticalSection m_critSection; + std::vector<CVideoBufferDRMPRIME*> m_all; + std::deque<int> m_used; + std::deque<int> m_free; +}; diff --git a/xbmc/cores/VideoPlayer/VideoRenderers/HwDecRender/DRMPRIMEEGL.cpp b/xbmc/cores/VideoPlayer/VideoRenderers/HwDecRender/DRMPRIMEEGL.cpp index 91809f8ebe..17dd7e1e19 100644 --- a/xbmc/cores/VideoPlayer/VideoRenderers/HwDecRender/DRMPRIMEEGL.cpp +++ b/xbmc/cores/VideoPlayer/VideoRenderers/HwDecRender/DRMPRIMEEGL.cpp @@ -15,11 +15,14 @@ void CDRMPRIMETexture::Init(EGLDisplay eglDisplay) m_eglImage.reset(new CEGLImage(eglDisplay)); } -bool CDRMPRIMETexture::Map(CVideoBufferDRMPRIME *buffer) +bool CDRMPRIMETexture::Map(IVideoBufferDRMPRIME* buffer) { if (m_primebuffer) return true; + if (!buffer->Map()) + return false; + m_texWidth = buffer->GetWidth(); m_texHeight = buffer->GetHeight(); @@ -74,6 +77,8 @@ void CDRMPRIMETexture::Unmap() glDeleteTextures(1, &m_texture); + m_primebuffer->Unmap(); + m_primebuffer->Release(); m_primebuffer = nullptr; } diff --git a/xbmc/cores/VideoPlayer/VideoRenderers/HwDecRender/DRMPRIMEEGL.h b/xbmc/cores/VideoPlayer/VideoRenderers/HwDecRender/DRMPRIMEEGL.h index abc4890acb..55cb2be330 100644 --- a/xbmc/cores/VideoPlayer/VideoRenderers/HwDecRender/DRMPRIMEEGL.h +++ b/xbmc/cores/VideoPlayer/VideoRenderers/HwDecRender/DRMPRIMEEGL.h @@ -8,15 +8,16 @@ #pragma once -#include "cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecDRMPRIME.h" +#include "cores/VideoPlayer/Process/gbm/VideoBufferDRMPRIME.h" #include "utils/EGLImage.h" +#include "utils/Geometry.h" #include "system_gl.h" class CDRMPRIMETexture { public: - bool Map(CVideoBufferDRMPRIME *buffer); + bool Map(IVideoBufferDRMPRIME* buffer); void Unmap(); void Init(EGLDisplay eglDisplay); @@ -24,7 +25,7 @@ public: CSizeInt GetTextureSize() { return { m_texWidth, m_texHeight }; } protected: - CVideoBufferDRMPRIME *m_primebuffer{nullptr}; + IVideoBufferDRMPRIME* m_primebuffer{nullptr}; std::unique_ptr<CEGLImage> m_eglImage; const GLenum m_textureTarget{GL_TEXTURE_EXTERNAL_OES}; diff --git a/xbmc/cores/VideoPlayer/VideoRenderers/HwDecRender/RendererDRMPRIME.cpp b/xbmc/cores/VideoPlayer/VideoRenderers/HwDecRender/RendererDRMPRIME.cpp index 295b269c82..df0fb6fd9c 100644 --- a/xbmc/cores/VideoPlayer/VideoRenderers/HwDecRender/RendererDRMPRIME.cpp +++ b/xbmc/cores/VideoPlayer/VideoRenderers/HwDecRender/RendererDRMPRIME.cpp @@ -8,20 +8,21 @@ #include "RendererDRMPRIME.h" -#include "cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecDRMPRIME.h" +#include "ServiceBroker.h" +#include "cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodec.h" +#include "cores/VideoPlayer/Process/gbm/VideoBufferDRMPRIME.h" #include "cores/VideoPlayer/VideoRenderers/HwDecRender/VideoLayerBridgeDRMPRIME.h" #include "cores/VideoPlayer/VideoRenderers/RenderCapture.h" #include "cores/VideoPlayer/VideoRenderers/RenderFactory.h" #include "cores/VideoPlayer/VideoRenderers/RenderFlags.h" -#include "settings/lib/Setting.h" #include "settings/DisplaySettings.h" #include "settings/Settings.h" #include "settings/SettingsComponent.h" +#include "settings/lib/Setting.h" #include "utils/log.h" +#include "windowing/GraphicContext.h" #include "windowing/gbm/DRMAtomic.h" #include "windowing/gbm/WinSystemGbm.h" -#include "windowing/GraphicContext.h" -#include "ServiceBroker.h" using namespace KODI::WINDOWING::GBM; @@ -34,7 +35,7 @@ CRendererDRMPRIME::~CRendererDRMPRIME() CBaseRenderer* CRendererDRMPRIME::Create(CVideoBuffer* buffer) { - if (buffer && dynamic_cast<CVideoBufferDRMPRIME*>(buffer) && + if (buffer && dynamic_cast<IVideoBufferDRMPRIME*>(buffer) && CServiceBroker::GetSettingsComponent()->GetSettings()->GetInt(SETTING_VIDEOPLAYER_USEPRIMERENDERER) == 0) { CWinSystemGbm* winSystem = dynamic_cast<CWinSystemGbm*>(CServiceBroker::GetWinSystem()); @@ -132,7 +133,7 @@ bool CRendererDRMPRIME::NeedBuffer(int index) if (m_iLastRenderBuffer == index) return true; - CVideoBufferDRMPRIME* buffer = dynamic_cast<CVideoBufferDRMPRIME*>(m_buffers[index].videoBuffer); + IVideoBufferDRMPRIME* buffer = dynamic_cast<IVideoBufferDRMPRIME*>(m_buffers[index].videoBuffer); if (buffer && buffer->m_fb_id) return true; @@ -162,12 +163,8 @@ void CRendererDRMPRIME::RenderUpdate(int index, int index2, bool clear, unsigned return; } - CVideoBufferDRMPRIME* buffer = dynamic_cast<CVideoBufferDRMPRIME*>(m_buffers[index].videoBuffer); - if (!buffer) - return; - - AVDRMFrameDescriptor* descriptor = buffer->GetDescriptor(); - if (!descriptor || !descriptor->nb_layers) + IVideoBufferDRMPRIME* buffer = dynamic_cast<IVideoBufferDRMPRIME*>(m_buffers[index].videoBuffer); + if (!buffer || !buffer->IsValid()) return; if (!m_videoLayerBridge) diff --git a/xbmc/cores/VideoPlayer/VideoRenderers/HwDecRender/RendererDRMPRIMEGLES.cpp b/xbmc/cores/VideoPlayer/VideoRenderers/HwDecRender/RendererDRMPRIMEGLES.cpp index 330823196f..bbe8409cba 100644 --- a/xbmc/cores/VideoPlayer/VideoRenderers/HwDecRender/RendererDRMPRIMEGLES.cpp +++ b/xbmc/cores/VideoPlayer/VideoRenderers/HwDecRender/RendererDRMPRIMEGLES.cpp @@ -10,10 +10,12 @@ #include "cores/VideoPlayer/VideoRenderers/RenderFactory.h" #include "ServiceBroker.h" +#include "utils/EGLFence.h" #include "utils/log.h" #include "windowing/gbm/WinSystemGbmGLESContext.h" using namespace KODI::WINDOWING::GBM; +using namespace KODI::UTILS::EGL; CRendererDRMPRIMEGLES::~CRendererDRMPRIMEGLES() { @@ -23,7 +25,7 @@ CRendererDRMPRIMEGLES::~CRendererDRMPRIMEGLES() CBaseRenderer* CRendererDRMPRIMEGLES::Create(CVideoBuffer* buffer) { - if (buffer && dynamic_cast<CVideoBufferDRMPRIME*>(buffer)) + if (buffer && dynamic_cast<IVideoBufferDRMPRIME*>(buffer)) return new CRendererDRMPRIMEGLES(); return nullptr; @@ -43,15 +45,27 @@ bool CRendererDRMPRIMEGLES::Configure(const VideoPicture &picture, float fps, un for (auto &texture : m_DRMPRIMETextures) texture.Init(winSystem->GetEGLDisplay()); + for (auto& fence : m_fences) + { + fence.reset(new CEGLFence(winSystem->GetEGLDisplay())); + } + return CLinuxRendererGLES::Configure(picture, fps, orientation); } void CRendererDRMPRIMEGLES::ReleaseBuffer(int index) { + m_fences[index]->DestroyFence(); + m_DRMPRIMETextures[index].Unmap(); CLinuxRendererGLES::ReleaseBuffer(index); } +bool CRendererDRMPRIMEGLES::NeedBuffer(int index) +{ + return !m_fences[index]->IsSignaled(); +} + bool CRendererDRMPRIMEGLES::CreateTexture(int index) { CPictureBuffer &buf = m_buffers[index]; @@ -85,9 +99,9 @@ bool CRendererDRMPRIMEGLES::UploadTexture(int index) { CPictureBuffer &buf = m_buffers[index]; - CVideoBufferDRMPRIME *buffer = dynamic_cast<CVideoBufferDRMPRIME*>(buf.videoBuffer); + IVideoBufferDRMPRIME* buffer = dynamic_cast<IVideoBufferDRMPRIME*>(buf.videoBuffer); - if (!buffer) + if (!buffer || !buffer->IsValid()) { CLog::Log(LOGNOTICE, "CRendererDRMPRIMEGLES::%s - no buffer", __FUNCTION__); return false; @@ -139,28 +153,44 @@ bool CRendererDRMPRIMEGLES::RenderHook(int index) { float x, y, z; float u1, v1; - } vertex[4]; + }; + + std::array<PackedVertex, 4> vertex; GLint vertLoc = renderSystem->GUIShaderGetPos(); GLint loc = renderSystem->GUIShaderGetCoord0(); - for (unsigned int i = 0; i < 4; i++) - { - // Setup vertex position values - vertex[i].x = m_rotatedDestCoords[i].x; - vertex[i].y = m_rotatedDestCoords[i].y; - vertex[i].z = 0.0f; - } - - // Setup texture coordinates - vertex[0].u1 = vertex[3].u1 = plane.rect.x1; - vertex[0].v1 = vertex[1].v1 = plane.rect.y1; - vertex[1].u1 = vertex[2].u1 = plane.rect.x2; - vertex[2].v1 = vertex[3].v1 = plane.rect.y2; + // top left + vertex[0].x = m_rotatedDestCoords[0].x; + vertex[0].y = m_rotatedDestCoords[0].y; + vertex[0].z = 0.0f; + vertex[0].u1 = plane.rect.x1; + vertex[0].v1 = plane.rect.y1; + + // top right + vertex[1].x = m_rotatedDestCoords[1].x; + vertex[1].y = m_rotatedDestCoords[1].y; + vertex[1].z = 0.0f; + vertex[1].u1 = plane.rect.x2; + vertex[1].v1 = plane.rect.y1; + + // bottom right + vertex[2].x = m_rotatedDestCoords[2].x; + vertex[2].y = m_rotatedDestCoords[2].y; + vertex[2].z = 0.0f; + vertex[2].u1 = plane.rect.x2; + vertex[2].v1 = plane.rect.y2; + + // bottom left + vertex[3].x = m_rotatedDestCoords[3].x; + vertex[3].y = m_rotatedDestCoords[3].y; + vertex[3].z = 0.0f; + vertex[3].u1 = plane.rect.x1; + vertex[3].v1 = plane.rect.y2;; glGenBuffers(1, &vertexVBO); glBindBuffer(GL_ARRAY_BUFFER, vertexVBO); - glBufferData(GL_ARRAY_BUFFER, sizeof(PackedVertex)*4, &vertex[0], GL_STATIC_DRAW); + glBufferData(GL_ARRAY_BUFFER, sizeof(PackedVertex) * vertex.size(), vertex.data(), GL_STATIC_DRAW); glVertexAttribPointer(vertLoc, 3, GL_FLOAT, 0, sizeof(PackedVertex), reinterpret_cast<const GLvoid*>(offsetof(PackedVertex, x))); glVertexAttribPointer(loc, 2, GL_FLOAT, 0, sizeof(PackedVertex), reinterpret_cast<const GLvoid*>(offsetof(PackedVertex, u1))); @@ -170,7 +200,7 @@ bool CRendererDRMPRIMEGLES::RenderHook(int index) glGenBuffers(1, &indexVBO); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexVBO); - glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(GLubyte)*4, idx, GL_STATIC_DRAW); + glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(GLubyte) * 4, idx, GL_STATIC_DRAW); glDrawElements(GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_BYTE, 0); @@ -188,3 +218,34 @@ bool CRendererDRMPRIMEGLES::RenderHook(int index) return true; } + +void CRendererDRMPRIMEGLES::AfterRenderHook(int index) +{ + m_fences[index]->CreateFence(); +} + +bool CRendererDRMPRIMEGLES::Supports(ERENDERFEATURE feature) +{ + switch (feature) + { + case RENDERFEATURE_STRETCH: + case RENDERFEATURE_ZOOM: + case RENDERFEATURE_VERTICAL_SHIFT: + case RENDERFEATURE_PIXEL_RATIO: + case RENDERFEATURE_ROTATION: + return true; + default: + return false; + } +} + +bool CRendererDRMPRIMEGLES::Supports(ESCALINGMETHOD method) +{ + switch (method) + { + case VS_SCALINGMETHOD_LINEAR: + return true; + default: + return false; + } +} diff --git a/xbmc/cores/VideoPlayer/VideoRenderers/HwDecRender/RendererDRMPRIMEGLES.h b/xbmc/cores/VideoPlayer/VideoRenderers/HwDecRender/RendererDRMPRIMEGLES.h index f879b6cf5a..e6ef033982 100644 --- a/xbmc/cores/VideoPlayer/VideoRenderers/HwDecRender/RendererDRMPRIMEGLES.h +++ b/xbmc/cores/VideoPlayer/VideoRenderers/HwDecRender/RendererDRMPRIMEGLES.h @@ -11,6 +11,20 @@ #include "cores/VideoPlayer/VideoRenderers/LinuxRendererGLES.h" #include "DRMPRIMEEGL.h" +#include <array> +#include <memory> + +namespace KODI +{ +namespace UTILS +{ +namespace EGL +{ +class CEGLFence; +} +} +} + class CRendererDRMPRIMEGLES : public CLinuxRendererGLES { public: @@ -24,14 +38,20 @@ public: // CLinuxRendererGLES overrides bool Configure(const VideoPicture &picture, float fps, unsigned int orientation) override; void ReleaseBuffer(int index) override; + bool NeedBuffer(int index) override; + + bool Supports(ERENDERFEATURE feature) override; + bool Supports(ESCALINGMETHOD method) override; protected: // CLinuxRendererGLES overrides bool LoadShadersHook() override; bool RenderHook(int index) override; + void AfterRenderHook(int index) override; bool UploadTexture(int index) override; void DeleteTexture(int index) override; bool CreateTexture(int index) override; + std::array<std::unique_ptr<KODI::UTILS::EGL::CEGLFence>, NUM_BUFFERS> m_fences; CDRMPRIMETexture m_DRMPRIMETextures[NUM_BUFFERS]; }; diff --git a/xbmc/cores/VideoPlayer/VideoRenderers/HwDecRender/VideoLayerBridgeDRMPRIME.cpp b/xbmc/cores/VideoPlayer/VideoRenderers/HwDecRender/VideoLayerBridgeDRMPRIME.cpp index 1e7acae2c1..3277d3667c 100644 --- a/xbmc/cores/VideoPlayer/VideoRenderers/HwDecRender/VideoLayerBridgeDRMPRIME.cpp +++ b/xbmc/cores/VideoPlayer/VideoRenderers/HwDecRender/VideoLayerBridgeDRMPRIME.cpp @@ -8,7 +8,7 @@ #include "VideoLayerBridgeDRMPRIME.h" -#include "cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecDRMPRIME.h" +#include "cores/VideoPlayer/Process/gbm/VideoBufferDRMPRIME.h" #include "utils/log.h" #include "windowing/gbm/DRMUtils.h" @@ -33,7 +33,7 @@ void CVideoLayerBridgeDRMPRIME::Disable() m_DRM->AddProperty(plane, "CRTC_ID", 0); } -void CVideoLayerBridgeDRMPRIME::Acquire(CVideoBufferDRMPRIME* buffer) +void CVideoLayerBridgeDRMPRIME::Acquire(IVideoBufferDRMPRIME* buffer) { // release the buffer that is no longer presented on screen Release(m_prev_buffer); @@ -46,7 +46,7 @@ void CVideoLayerBridgeDRMPRIME::Acquire(CVideoBufferDRMPRIME* buffer) m_buffer->Acquire(); } -void CVideoLayerBridgeDRMPRIME::Release(CVideoBufferDRMPRIME* buffer) +void CVideoLayerBridgeDRMPRIME::Release(IVideoBufferDRMPRIME* buffer) { if (!buffer) return; @@ -55,11 +55,14 @@ void CVideoLayerBridgeDRMPRIME::Release(CVideoBufferDRMPRIME* buffer) buffer->Release(); } -bool CVideoLayerBridgeDRMPRIME::Map(CVideoBufferDRMPRIME* buffer) +bool CVideoLayerBridgeDRMPRIME::Map(IVideoBufferDRMPRIME* buffer) { if (buffer->m_fb_id) return true; + if (!buffer->Map()) + return false; + AVDRMFrameDescriptor* descriptor = buffer->GetDescriptor(); uint32_t handles[4] = {0}, pitches[4] = {0}, offsets[4] = {0}, flags = 0; uint64_t modifier[4] = {0}; @@ -108,7 +111,7 @@ bool CVideoLayerBridgeDRMPRIME::Map(CVideoBufferDRMPRIME* buffer) return true; } -void CVideoLayerBridgeDRMPRIME::Unmap(CVideoBufferDRMPRIME* buffer) +void CVideoLayerBridgeDRMPRIME::Unmap(IVideoBufferDRMPRIME* buffer) { if (buffer->m_fb_id) { @@ -125,9 +128,11 @@ void CVideoLayerBridgeDRMPRIME::Unmap(CVideoBufferDRMPRIME* buffer) buffer->m_handles[i] = 0; } } + + buffer->Unmap(); } -void CVideoLayerBridgeDRMPRIME::Configure(CVideoBufferDRMPRIME* buffer) +void CVideoLayerBridgeDRMPRIME::Configure(IVideoBufferDRMPRIME* buffer) { struct plane* plane = m_DRM->GetVideoPlane(); if (m_DRM->SupportsProperty(plane, "COLOR_ENCODING") && @@ -138,7 +143,7 @@ void CVideoLayerBridgeDRMPRIME::Configure(CVideoBufferDRMPRIME* buffer) } } -void CVideoLayerBridgeDRMPRIME::SetVideoPlane(CVideoBufferDRMPRIME* buffer, const CRect& destRect) +void CVideoLayerBridgeDRMPRIME::SetVideoPlane(IVideoBufferDRMPRIME* buffer, const CRect& destRect) { if (!Map(buffer)) { diff --git a/xbmc/cores/VideoPlayer/VideoRenderers/HwDecRender/VideoLayerBridgeDRMPRIME.h b/xbmc/cores/VideoPlayer/VideoRenderers/HwDecRender/VideoLayerBridgeDRMPRIME.h index b29488b1a3..ade17ac0c3 100644 --- a/xbmc/cores/VideoPlayer/VideoRenderers/HwDecRender/VideoLayerBridgeDRMPRIME.h +++ b/xbmc/cores/VideoPlayer/VideoRenderers/HwDecRender/VideoLayerBridgeDRMPRIME.h @@ -24,7 +24,7 @@ namespace GBM } } -class CVideoBufferDRMPRIME; +class IVideoBufferDRMPRIME; class CVideoLayerBridgeDRMPRIME : public KODI::WINDOWING::GBM::CVideoLayerBridge @@ -34,19 +34,19 @@ public: ~CVideoLayerBridgeDRMPRIME(); void Disable() override; - virtual void Configure(CVideoBufferDRMPRIME* buffer); - virtual void SetVideoPlane(CVideoBufferDRMPRIME* buffer, const CRect& destRect); + virtual void Configure(IVideoBufferDRMPRIME* buffer); + virtual void SetVideoPlane(IVideoBufferDRMPRIME* buffer, const CRect& destRect); virtual void UpdateVideoPlane(); protected: std::shared_ptr<KODI::WINDOWING::GBM::CDRMUtils> m_DRM; private: - void Acquire(CVideoBufferDRMPRIME* buffer); - void Release(CVideoBufferDRMPRIME* buffer); - bool Map(CVideoBufferDRMPRIME* buffer); - void Unmap(CVideoBufferDRMPRIME* buffer); + void Acquire(IVideoBufferDRMPRIME* buffer); + void Release(IVideoBufferDRMPRIME* buffer); + bool Map(IVideoBufferDRMPRIME* buffer); + void Unmap(IVideoBufferDRMPRIME* buffer); - CVideoBufferDRMPRIME* m_buffer = nullptr; - CVideoBufferDRMPRIME* m_prev_buffer = nullptr; + IVideoBufferDRMPRIME* m_buffer = nullptr; + IVideoBufferDRMPRIME* m_prev_buffer = nullptr; }; diff --git a/xbmc/utils/CMakeLists.txt b/xbmc/utils/CMakeLists.txt index f0ce99014b..6dbee35a1a 100644 --- a/xbmc/utils/CMakeLists.txt +++ b/xbmc/utils/CMakeLists.txt @@ -169,8 +169,10 @@ if(XSLT_FOUND) list(APPEND HEADERS XSLTUtils.h) endif() if(EGL_FOUND) - list(APPEND SOURCES EGLUtils.cpp) - list(APPEND HEADERS EGLUtils.h) + list(APPEND SOURCES EGLUtils.cpp + EGLFence.cpp) + list(APPEND HEADERS EGLUtils.h + EGLFence.h) endif() # The large map trips the clang optimizer diff --git a/xbmc/utils/EGLFence.cpp b/xbmc/utils/EGLFence.cpp new file mode 100644 index 0000000000..bc9f35e173 --- /dev/null +++ b/xbmc/utils/EGLFence.cpp @@ -0,0 +1,69 @@ +/* + * Copyright (C) 2017-2018 Team Kodi + * This file is part of Kodi - https://kodi.tv + * + * SPDX-License-Identifier: GPL-2.0-or-later + * See LICENSES/README.md for more information. + */ + +#include "EGLFence.h" + +#include "EGLUtils.h" + +using namespace KODI::UTILS::EGL; + +CEGLFence::CEGLFence(EGLDisplay display) : + m_display(display) +{ + m_eglCreateSyncKHR = CEGLUtils::GetRequiredProcAddress<PFNEGLCREATESYNCKHRPROC>("eglCreateSyncKHR"); + m_eglDestroySyncKHR = CEGLUtils::GetRequiredProcAddress<PFNEGLDESTROYSYNCKHRPROC>("eglDestroySyncKHR"); + m_eglGetSyncAttribKHR = CEGLUtils::GetRequiredProcAddress<PFNEGLGETSYNCATTRIBKHRPROC>("eglGetSyncAttribKHR"); +} + +void CEGLFence::CreateFence() +{ + m_fence = m_eglCreateSyncKHR(m_display, EGL_SYNC_FENCE_KHR, nullptr); + if (m_fence == EGL_NO_SYNC_KHR) + { + CEGLUtils::LogError("failed to create egl sync fence"); + throw std::runtime_error("failed to create egl sync fence"); + } +} + +void CEGLFence::DestroyFence() +{ + if (m_fence == EGL_NO_SYNC_KHR) + { + return; + } + + if (m_eglDestroySyncKHR(m_display, m_fence) != EGL_TRUE) + { + CEGLUtils::LogError("failed to destroy egl sync fence"); + } + + m_fence = EGL_NO_SYNC_KHR; +} + +bool CEGLFence::IsSignaled() +{ + // fence has been destroyed so return true immediately so buffer can be used + if (m_fence == EGL_NO_SYNC_KHR) + { + return true; + } + + EGLint status = EGL_UNSIGNALED_KHR; + if (m_eglGetSyncAttribKHR(m_display, m_fence, EGL_SYNC_STATUS_KHR, &status) != EGL_TRUE) + { + CEGLUtils::LogError("failed to query egl sync fence"); + return false; + } + + if (status == EGL_SIGNALED_KHR) + { + return true; + } + + return false; +} diff --git a/xbmc/utils/EGLFence.h b/xbmc/utils/EGLFence.h new file mode 100644 index 0000000000..1664772ef0 --- /dev/null +++ b/xbmc/utils/EGLFence.h @@ -0,0 +1,43 @@ +/* + * Copyright (C) 2017-2018 Team Kodi + * This file is part of Kodi - https://kodi.tv + * + * SPDX-License-Identifier: GPL-2.0-or-later + * See LICENSES/README.md for more information. + */ + +#pragma once + +#include <EGL/egl.h> +#include <EGL/eglext.h> + +namespace KODI +{ +namespace UTILS +{ +namespace EGL +{ + +class CEGLFence +{ +public: + explicit CEGLFence(EGLDisplay display); + CEGLFence(CEGLFence const& other) = delete; + CEGLFence& operator=(CEGLFence const& other) = delete; + + void CreateFence(); + void DestroyFence(); + bool IsSignaled(); + +private: + EGLDisplay m_display{nullptr}; + EGLSyncKHR m_fence{nullptr}; + + PFNEGLCREATESYNCKHRPROC m_eglCreateSyncKHR{nullptr}; + PFNEGLDESTROYSYNCKHRPROC m_eglDestroySyncKHR{nullptr}; + PFNEGLGETSYNCATTRIBKHRPROC m_eglGetSyncAttribKHR{nullptr}; +}; + +} +} +} diff --git a/xbmc/windowing/gbm/DRMUtils.cpp b/xbmc/windowing/gbm/DRMUtils.cpp index df46ad4bdc..48f0bc40bc 100644 --- a/xbmc/windowing/gbm/DRMUtils.cpp +++ b/xbmc/windowing/gbm/DRMUtils.cpp @@ -109,27 +109,43 @@ drm_fb * CDRMUtils::DrmFbGetFromBo(struct gbm_bo *bo) memset(offsets, 0, 16); #endif - if (modifiers[0] == DRM_FORMAT_MOD_INVALID) - modifiers[0] = DRM_FORMAT_MOD_LINEAR; - - CLog::Log(LOGDEBUG, "CDRMUtils::%s - using modifier: %lli", __FUNCTION__, modifiers[0]); - - auto ret = drmModeAddFB2WithModifiers(m_fd, - width, - height, - fb->format, - handles, - strides, - offsets, - modifiers, - &fb->fb_id, - (modifiers[0] > 0) ? DRM_MODE_FB_MODIFIERS : 0); + uint32_t flags = 0; - if(ret) + if (modifiers[0] && modifiers[0] != DRM_FORMAT_MOD_INVALID) + { + flags |= DRM_MODE_FB_MODIFIERS; + CLog::Log(LOGDEBUG, "CDRMUtils::{} - using modifier: {:#x}", __FUNCTION__, modifiers[0]); + } + + int ret = drmModeAddFB2WithModifiers(m_fd, + width, + height, + fb->format, + handles, + strides, + offsets, + modifiers, + &fb->fb_id, + flags); + + if(ret < 0) { - delete (fb); - CLog::Log(LOGDEBUG, "CDRMUtils::%s - failed to add framebuffer", __FUNCTION__); - return nullptr; + ret = drmModeAddFB2(m_fd, + width, + height, + fb->format, + handles, + strides, + offsets, + &fb->fb_id, + flags); + + if (ret < 0) + { + delete (fb); + CLog::Log(LOGDEBUG, "CDRMUtils::{} - failed to add framebuffer: {} ({})", __FUNCTION__, strerror(errno), errno); + return nullptr; + } } gbm_bo_set_user_data(bo, fb, DrmFbDestroyCallback); @@ -579,9 +595,25 @@ bool CDRMUtils::InitDrm() auto ret = drmSetClientCap(m_fd, DRM_CLIENT_CAP_UNIVERSAL_PLANES, 1); if (ret) { - CLog::Log(LOGERROR, "CDRMUtils::%s - failed to set Universal planes capability: %s", __FUNCTION__, strerror(errno)); + CLog::Log(LOGERROR, "CDRMUtils::{} - failed to set universal planes capability: {}", __FUNCTION__, strerror(errno)); + return false; + } + + ret = drmSetClientCap(m_fd, DRM_CLIENT_CAP_STEREO_3D, 1); + if (ret) + { + CLog::Log(LOGERROR, "CDRMUtils::{} - failed to set stereo 3d capability: {}", __FUNCTION__, strerror(errno)); + return false; + } + +#if defined(DRM_CLIENT_CAP_ASPECT_RATIO) + ret = drmSetClientCap(m_fd, DRM_CLIENT_CAP_ASPECT_RATIO, 0); + if (ret) + { + CLog::Log(LOGERROR, "CDRMUtils::{} - failed to unset aspect ratio capability: {}", __FUNCTION__, strerror(errno)); return false; } +#endif if(!GetResources()) { diff --git a/xbmc/windowing/gbm/WinSystemGbm.cpp b/xbmc/windowing/gbm/WinSystemGbm.cpp index 4a3291a550..5cee802be2 100644 --- a/xbmc/windowing/gbm/WinSystemGbm.cpp +++ b/xbmc/windowing/gbm/WinSystemGbm.cpp @@ -207,11 +207,19 @@ void CWinSystemGbm::FlipPage(bool rendered, bool videoLayer) m_videoLayerBridge->Disable(); } - struct gbm_bo *bo = m_GBM->LockFrontBuffer(); + struct gbm_bo *bo = nullptr; + + if (rendered) + { + bo = m_GBM->LockFrontBuffer(); + } m_DRM->FlipPage(bo, rendered, videoLayer); - m_GBM->ReleaseBuffer(); + if (rendered) + { + m_GBM->ReleaseBuffer(); + } if (m_videoLayerBridge && !videoLayer) { diff --git a/xbmc/windowing/gbm/WinSystemGbmGLESContext.cpp b/xbmc/windowing/gbm/WinSystemGbmGLESContext.cpp index c24cb919ae..f763577117 100644 --- a/xbmc/windowing/gbm/WinSystemGbmGLESContext.cpp +++ b/xbmc/windowing/gbm/WinSystemGbmGLESContext.cpp @@ -14,6 +14,7 @@ #include "cores/RetroPlayer/rendering/VideoRenderers/RPRendererGBM.h" #include "cores/RetroPlayer/rendering/VideoRenderers/RPRendererOpenGLES.h" #include "cores/VideoPlayer/DVDCodecs/DVDFactoryCodec.h" +#include "cores/VideoPlayer/Process/gbm/ProcessInfoGBM.h" #include "cores/VideoPlayer/VideoRenderers/LinuxRendererGLES.h" #include "cores/VideoPlayer/VideoRenderers/RenderFactory.h" @@ -65,6 +66,7 @@ bool CWinSystemGbmGLESContext::InitWindowSystem() CRendererDRMPRIMEGLES::Register(); CRendererDRMPRIME::Register(); CDVDVideoCodecDRMPRIME::Register(); + VIDEOPLAYER::CProcessInfoGBM::Register(); return true; } |