diff options
24 files changed, 1610 insertions, 1146 deletions
diff --git a/Makefile.in b/Makefile.in index c85825260d..dfd7861250 100644 --- a/Makefile.in +++ b/Makefile.in @@ -37,6 +37,7 @@ DIRECTORY_ARCHIVES=$(DVDPLAYER_ARCHIVES) \ xbmc/cores/ExternalPlayer/ExternalPlayer.a \ xbmc/cores/VideoRenderers/VideoRenderer.a \ xbmc/cores/VideoRenderers/VideoShaders/VideoShaders.a \ + xbmc/cores/VideoRenderers/HwDecRender/HwDecRender.a \ xbmc/cores/cores.a \ xbmc/cores/paplayer/paplayer.a \ xbmc/cores/playercorefactory/playercorefactory.a \ diff --git a/configure.ac b/configure.ac index 53e662a3a0..3f5ddc78e8 100644 --- a/configure.ac +++ b/configure.ac @@ -2356,6 +2356,7 @@ OUTPUT_FILES="Makefile \ xbmc/cdrip/Makefile \ xbmc/cores/Makefile \ xbmc/cores/VideoRenderers/Makefile \ + xbmc/cores/VideoRenderers/HwDecRender/Makefile \ xbmc/cores/dvdplayer/Makefile \ lib/libdvd/Makefile \ xbmc/cores/DllLoader/Makefile \ diff --git a/xbmc/Application.cpp b/xbmc/Application.cpp index e5787b9ded..32848b0e02 100644 --- a/xbmc/Application.cpp +++ b/xbmc/Application.cpp @@ -3554,7 +3554,7 @@ PlayBackRet CApplication::PlayFile(const CFileItem& item, bool bRestart) else if(m_pPlayer->IsPlayingVideo()) { // if player didn't manange to switch to fullscreen by itself do it here - if (options.fullscreen && g_renderManager.IsStarted() && + if (options.fullscreen && g_renderManager.IsConfigured() && g_windowManager.GetActiveWindow() != WINDOW_FULLSCREEN_VIDEO ) SwitchToFullScreen(true); } diff --git a/xbmc/cores/VideoRenderers/BaseRenderer.h b/xbmc/cores/VideoRenderers/BaseRenderer.h index 6c69b80146..81384a1ee5 100644 --- a/xbmc/cores/VideoRenderers/BaseRenderer.h +++ b/xbmc/cores/VideoRenderers/BaseRenderer.h @@ -85,9 +85,9 @@ public: virtual int GetImage(YV12Image *image, int source = -1, bool readonly = false) = 0; virtual void ReleaseImage(int source, bool preserve = false) = 0; virtual bool AddVideoPicture(DVDVideoPicture* picture, int index) { return false; } - virtual void AddVideoPictureHW(DVDVideoPicture &picture, int index) = 0; + virtual void AddVideoPictureHW(DVDVideoPicture &picture, int index) {}; virtual void FlipPage(int source) = 0; - virtual unsigned int PreInit() = 0; + virtual void PreInit() = 0; virtual void UnInit() = 0; virtual void Reset() = 0; virtual void Flush() {}; @@ -110,6 +110,8 @@ public: virtual bool Supports(EINTERLACEMETHOD method) = 0; virtual bool Supports(ESCALINGMETHOD method) = 0; + ERenderFormat GetRenderFormat() { return m_format; } + void SetViewMode(int viewMode); RESOLUTION GetResolution() const; diff --git a/xbmc/cores/VideoRenderers/DXVAHD.cpp b/xbmc/cores/VideoRenderers/HwDecRender/DXVAHD.cpp index c8fd6717ee..c8fd6717ee 100644 --- a/xbmc/cores/VideoRenderers/DXVAHD.cpp +++ b/xbmc/cores/VideoRenderers/HwDecRender/DXVAHD.cpp diff --git a/xbmc/cores/VideoRenderers/DXVAHD.h b/xbmc/cores/VideoRenderers/HwDecRender/DXVAHD.h index 154668f12b..154668f12b 100644 --- a/xbmc/cores/VideoRenderers/DXVAHD.h +++ b/xbmc/cores/VideoRenderers/HwDecRender/DXVAHD.h diff --git a/xbmc/cores/VideoRenderers/MMALRenderer.cpp b/xbmc/cores/VideoRenderers/HwDecRender/MMALRenderer.cpp index 466f44cfc3..466f44cfc3 100644 --- a/xbmc/cores/VideoRenderers/MMALRenderer.cpp +++ b/xbmc/cores/VideoRenderers/HwDecRender/MMALRenderer.cpp diff --git a/xbmc/cores/VideoRenderers/MMALRenderer.h b/xbmc/cores/VideoRenderers/HwDecRender/MMALRenderer.h index d3e5129314..d3e5129314 100644 --- a/xbmc/cores/VideoRenderers/MMALRenderer.h +++ b/xbmc/cores/VideoRenderers/HwDecRender/MMALRenderer.h diff --git a/xbmc/cores/VideoRenderers/HwDecRender/Makefile.in b/xbmc/cores/VideoRenderers/HwDecRender/Makefile.in new file mode 100644 index 0000000000..a302e28efb --- /dev/null +++ b/xbmc/cores/VideoRenderers/HwDecRender/Makefile.in @@ -0,0 +1,15 @@ +SRCS= + +ifeq (@USE_OPENGL@,1) +SRCS += RendererVAAPI.cpp +SRCS += RendererVDPAU.cpp +endif + +ifeq (@USE_MMAL@,1) +SRCS += MMALRenderer.cpp +endif + +LIB=HwDecRender.a + +include ../../../../Makefile.include +-include $(patsubst %.cpp,%.P,$(patsubst %.c,%.P,$(SRCS)))
\ No newline at end of file diff --git a/xbmc/cores/VideoRenderers/HwDecRender/RendererVAAPI.cpp b/xbmc/cores/VideoRenderers/HwDecRender/RendererVAAPI.cpp new file mode 100644 index 0000000000..2744a5ac51 --- /dev/null +++ b/xbmc/cores/VideoRenderers/HwDecRender/RendererVAAPI.cpp @@ -0,0 +1,264 @@ +/* + * Copyright (C) 2007-2015 Team XBMC + * http://xbmc.org + * + * This Program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This Program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with XBMC; see the file COPYING. If not, see + * <http://www.gnu.org/licenses/>. + * + */ + +#include "RendererVAAPI.h" + +#ifdef HAVE_LIBVA + +#include "cores/dvdplayer/DVDCodecs/Video/VAAPI.h" +#include "cores/dvdplayer/DVDCodecs/DVDCodecUtils.h" +#include "settings/Settings.h" +#include "settings/AdvancedSettings.h" +#include "utils/log.h" + +CRendererVAAPI::CRendererVAAPI() +{ + +} + +CRendererVAAPI::~CRendererVAAPI() +{ + for (int i = 0; i < NUM_BUFFERS; ++i) + { + DeleteTexture(i); + } +} + +void CRendererVAAPI::AddVideoPictureHW(DVDVideoPicture &picture, int index) +{ + VAAPI::CVaapiRenderPicture *vaapi = picture.vaapi; + YUVBUFFER &buf = m_buffers[index]; + VAAPI::CVaapiRenderPicture *pic = vaapi->Acquire(); + if (buf.hwDec) + ((VAAPI::CVaapiRenderPicture*)buf.hwDec)->Release(); + buf.hwDec = pic; + + if (m_format == RENDER_FMT_VAAPINV12) + { + YV12Image &im = m_buffers[index].image; + CDVDCodecUtils::CopyNV12Picture(&im, &vaapi->DVDPic); + } +} + +void CRendererVAAPI::ReleaseBuffer(int idx) +{ + YUVBUFFER &buf = m_buffers[idx]; + if (buf.hwDec) + ((VAAPI::CVaapiRenderPicture*)buf.hwDec)->Release(); + buf.hwDec = NULL; +} + +CRenderInfo CRendererVAAPI::GetRenderInfo() +{ + CRenderInfo info; + info.formats = m_formats; + info.max_buffer_size = NUM_BUFFERS; + if (m_format == RENDER_FMT_VAAPINV12) + info.optimal_buffer_size = 3; + else + info.optimal_buffer_size = 5; + return info; +} + +bool CRendererVAAPI::Supports(ERENDERFEATURE feature) +{ + if (m_format == RENDER_FMT_VAAPINV12) + return CLinuxRendererGL::Supports(feature); + + if (feature == RENDERFEATURE_STRETCH || + feature == RENDERFEATURE_ZOOM || + feature == RENDERFEATURE_VERTICAL_SHIFT || + feature == RENDERFEATURE_PIXEL_RATIO || + feature == RENDERFEATURE_POSTPROCESS || + feature == RENDERFEATURE_ROTATION || + feature == RENDERFEATURE_NONLINSTRETCH) + return true; + + return false; +} + +bool CRendererVAAPI::Supports(EINTERLACEMETHOD method) +{ + VAAPI::CVaapiRenderPicture *vaapiPic = (VAAPI::CVaapiRenderPicture*)m_buffers[m_iYV12RenderBuffer].hwDec; + if(vaapiPic && vaapiPic->vaapi) + return vaapiPic->vaapi->Supports(method); + return false; +} + +bool CRendererVAAPI::Supports(ESCALINGMETHOD method) +{ + if (m_format == RENDER_FMT_VAAPINV12) + return CLinuxRendererGL::Supports(method); + + //nearest neighbor doesn't work on YUY2 and UYVY + if (method == VS_SCALINGMETHOD_NEAREST && + m_format != RENDER_FMT_YUYV422 && + m_format != RENDER_FMT_UYVY422) + return true; + + if(method == VS_SCALINGMETHOD_LINEAR + || method == VS_SCALINGMETHOD_AUTO) + return true; + + if(method == VS_SCALINGMETHOD_CUBIC + || method == VS_SCALINGMETHOD_LANCZOS2 + || method == VS_SCALINGMETHOD_SPLINE36_FAST + || method == VS_SCALINGMETHOD_LANCZOS3_FAST + || method == VS_SCALINGMETHOD_SPLINE36 + || method == VS_SCALINGMETHOD_LANCZOS3) + { + // if scaling is below level, avoid hq scaling + float scaleX = fabs(((float)m_sourceWidth - m_destRect.Width())/m_sourceWidth)*100; + float scaleY = fabs(((float)m_sourceHeight - m_destRect.Height())/m_sourceHeight)*100; + int minScale = CSettings::Get().GetInt("videoplayer.hqscalers"); + if (scaleX < minScale && scaleY < minScale) + return false; + + // spline36 and lanczos3 are only allowed through advancedsettings.xml + if(method != VS_SCALINGMETHOD_SPLINE36 + && method != VS_SCALINGMETHOD_LANCZOS3) + return true; + else + return g_advancedSettings.m_videoEnableHighQualityHwScalers; + } + + return false; +} + +bool CRendererVAAPI::LoadShadersHook() +{ + if (m_format == RENDER_FMT_VAAPINV12) + return false; + + CLog::Log(LOGNOTICE, "GL: Using VAAPI render method"); + m_renderMethod = RENDER_VAAPI; + return true; +} + +bool CRendererVAAPI::RenderHook(int idx) +{ + if (m_format == RENDER_FMT_VAAPINV12) + return false; + + UpdateVideoFilter(); + RenderRGB(idx, m_currentField); + YUVBUFFER &buf = m_buffers[idx]; + if (buf.hwDec) + { + ((VAAPI::CVaapiRenderPicture*)buf.hwDec)->Sync(); + } + return true; +} + +bool CRendererVAAPI::CreateTexture(int index) +{ + if (m_format == RENDER_FMT_VAAPINV12) + { + return CreateNV12Texture(index); + } + + YV12Image &im = m_buffers[index].image; + YUVFIELDS &fields = m_buffers[index].fields; + YUVPLANE &plane = fields[0][0]; + + DeleteTexture(index); + + memset(&im , 0, sizeof(im)); + memset(&fields, 0, sizeof(fields)); + im.height = m_sourceHeight; + im.width = m_sourceWidth; + + plane.texwidth = im.width; + plane.texheight = im.height; + + plane.pixpertex_x = 1; + plane.pixpertex_y = 1; + + plane.id = 1; + + return true; +} + +void CRendererVAAPI::DeleteTexture(int index) +{ + if (m_format == RENDER_FMT_VAAPINV12) + { + DeleteNV12Texture(index); + return; + } + + YUVPLANE &plane = m_buffers[index].fields[FIELD_FULL][0]; + if (m_buffers[index].hwDec) + ((VAAPI::CVaapiRenderPicture*)m_buffers[index].hwDec)->Release(); + m_buffers[index].hwDec = NULL; + plane.id = 0; +} + +bool CRendererVAAPI::UploadTexture(int index) +{ + if (m_format == RENDER_FMT_VAAPINV12) + { + return UploadNV12Texture(index); + } + + VAAPI::CVaapiRenderPicture *vaapi = (VAAPI::CVaapiRenderPicture*)m_buffers[index].hwDec; + + YUVFIELDS &fields = m_buffers[index].fields; + YUVPLANE &plane = fields[FIELD_FULL][0]; + + if (!vaapi || !vaapi->valid) + { + return false; + } + + if (!vaapi->CopyGlx()) + return false; + + plane.id = vaapi->texture; + + // in stereoscopic mode sourceRect may only + // be a part of the source video surface + plane.rect = m_sourceRect; + + // clip rect + if (vaapi->crop.x1 > plane.rect.x1) + plane.rect.x1 = vaapi->crop.x1; + if (vaapi->crop.x2 < plane.rect.x2) + plane.rect.x2 = vaapi->crop.x2; + if (vaapi->crop.y1 > plane.rect.y1) + plane.rect.y1 = vaapi->crop.y1; + if (vaapi->crop.y2 < plane.rect.y2) + plane.rect.y2 = vaapi->crop.y2; + + plane.texheight = vaapi->texHeight; + plane.texwidth = vaapi->texWidth; + + if (m_textureTarget == GL_TEXTURE_2D) + { + plane.rect.y1 /= plane.texheight; + plane.rect.y2 /= plane.texheight; + plane.rect.x1 /= plane.texwidth; + plane.rect.x2 /= plane.texwidth; + } + return true; +} + + +#endif diff --git a/xbmc/cores/VideoRenderers/HwDecRender/RendererVAAPI.h b/xbmc/cores/VideoRenderers/HwDecRender/RendererVAAPI.h new file mode 100644 index 0000000000..c6d0615ae7 --- /dev/null +++ b/xbmc/cores/VideoRenderers/HwDecRender/RendererVAAPI.h @@ -0,0 +1,56 @@ +/* + * Copyright (C) 2007-2015 Team XBMC + * http://xbmc.org + * + * This Program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This Program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with XBMC; see the file COPYING. If not, see + * <http://www.gnu.org/licenses/>. + * + */ + +#pragma once + +#include "system.h" + +#ifdef HAVE_LIBVA + +#include "cores/VideoRenderers/LinuxRendererGL.h" + +class CRendererVAAPI : public CLinuxRendererGL +{ +public: + CRendererVAAPI(); + virtual ~CRendererVAAPI(); + + // Player functions + virtual void AddVideoPictureHW(DVDVideoPicture &picture, int index); + virtual void ReleaseBuffer(int idx); + virtual CRenderInfo GetRenderInfo(); + + // Feature support + virtual bool Supports(ERENDERFEATURE feature); + virtual bool Supports(EINTERLACEMETHOD method); + virtual bool Supports(ESCALINGMETHOD method); + +protected: + virtual bool LoadShadersHook(); + virtual bool RenderHook(int idx); + + // textures + virtual bool UploadTexture(int index); + virtual void DeleteTexture(int index); + virtual bool CreateTexture(int index); +}; + +#endif + diff --git a/xbmc/cores/VideoRenderers/HwDecRender/RendererVDA.cpp b/xbmc/cores/VideoRenderers/HwDecRender/RendererVDA.cpp new file mode 100644 index 0000000000..41c9add383 --- /dev/null +++ b/xbmc/cores/VideoRenderers/HwDecRender/RendererVDA.cpp @@ -0,0 +1,174 @@ +/* + * Copyright (C) 2007-2015 Team XBMC + * http://xbmc.org + * + * This Program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This Program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with XBMC; see the file COPYING. If not, see + * <http://www.gnu.org/licenses/>. + * + */ + +#include "RendererVDA.h" + +#if defined(TARGET_DARWIN_OSX) + +#include "settings/Settings.h" +#include "settings/AdvancedSettings.h" +#include "cores/dvdplayer/DVDCodecs/Video/DVDVideoCodec.h" +#include "utils/log.h" +#include "osx/CocoaInterface.h" +#include <CoreVideo/CoreVideo.h> +#include <OpenGL/CGLIOSurface.h> +#include "windowing/WindowingFactory.h" + +CRendererVDA::CRendererVDA() +{ + +} + +CRendererVDA::~CRendererVDA() +{ + +} + +void CRendererVDA::AddVideoPictureHW(DVDVideoPicture &picture, int index) +{ + YUVBUFFER &buf = m_buffers[index]; + if (buf.hwDec) + CVBufferRelease((struct __CVBuffer *)buf.hwDec); + buf.hwDec = picture.cvBufferRef; + // retain another reference, this way dvdplayer and renderer can issue releases. + CVBufferRetain(picture.cvBufferRef); +} + +void CRendererVDA::ReleaseBuffer(int idx) +{ + YUVBUFFER &buf = m_buffers[idx]; + if (buf.hwDec) + CVBufferRelease((struct __CVBuffer *)buf.hwDec); + buf.hwDec = NULL; +} + + +bool CRendererVDA::Supports(EINTERLACEMETHOD method) +{ + return false; +} + +bool CRendererVDA::Supports(EDEINTERLACEMODE mode) +{ + return false; +} + +EINTERLACEMETHOD CRendererVDA::AutoInterlaceMethod() +{ + return VS_INTERLACEMETHOD_NONE; +} + +bool CRendererVDA::LoadShadersHook() +{ + CLog::Log(LOGNOTICE, "GL: Using CVBREF render method"); + // m_renderMethod = RENDER_CVREF; + m_textureTarget = GL_TEXTURE_RECTANGLE_ARB; + return false; +} + +bool CRendererVDA::CreateTexture(int index) +{ + YV12Image &im = m_buffers[index].image; + YUVFIELDS &fields = m_buffers[index].fields; + YUVPLANE &plane = fields[0][0]; + + DeleteTexture(index); + + memset(&im , 0, sizeof(im)); + memset(&fields, 0, sizeof(fields)); + + im.bpp = 1; + im.width = m_sourceWidth; + im.height = m_sourceHeight; + im.cshift_x = 0; + im.cshift_y = 0; + + plane.pixpertex_x = 2; + plane.pixpertex_y = 1; + plane.texwidth = im.width / plane.pixpertex_x; + plane.texheight = im.height / plane.pixpertex_y; + + if(m_renderMethod & RENDER_POT) + { + plane.texwidth = NP2(plane.texwidth); + plane.texheight = NP2(plane.texheight); + } + + glEnable(m_textureTarget); + glGenTextures(1, &plane.id); + glDisable(m_textureTarget); + + return true; +} + +void CRendererVDA::DeleteTexture(int index) +{ + YUVPLANE &plane = m_buffers[index].fields[0][0]; + + if (m_buffers[index].hwDec) + CVBufferRelease((struct __CVBuffer *)m_buffers[index].hwDec); + m_buffers[index].hwDec = NULL; + + if (plane.id && glIsTexture(plane.id)) + glDeleteTextures(1, &plane.id), plane.id = 0; +} + +bool CRendererVDA::UploadTexture(int index) +{ + YUVBUFFER &buf = m_buffers[index]; + YUVFIELDS &fields = buf.fields; + + CVBufferRef cvBufferRef = (struct __CVBuffer *)m_buffers[index].hwDec; + + glEnable(m_textureTarget); + + if (cvBufferRef && fields[m_currentField][0].flipindex != buf.flipindex) + { + + // It is the fastest way to render a CVPixelBuffer backed + // with an IOSurface as there is no CPU -> GPU upload. + CGLContextObj cgl_ctx = (CGLContextObj)g_Windowing.GetCGLContextObj(); + IOSurfaceRef surface = CVPixelBufferGetIOSurface(cvBufferRef); + GLsizei texWidth = IOSurfaceGetWidth(surface); + GLsizei texHeight= IOSurfaceGetHeight(surface); + OSType format_type = IOSurfaceGetPixelFormat(surface); + + glBindTexture(m_textureTarget, fields[FIELD_FULL][0].id); + + if (format_type == kCVPixelFormatType_422YpCbCr8) + CGLTexImageIOSurface2D(cgl_ctx, m_textureTarget, GL_RGBA8, + texWidth / 2, texHeight, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, surface, 0); + else if (format_type == kCVPixelFormatType_32BGRA) + CGLTexImageIOSurface2D(cgl_ctx, m_textureTarget, GL_RGBA8, + texWidth, texHeight, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, surface, 0); + + glBindTexture(m_textureTarget, 0); + fields[FIELD_FULL][0].flipindex = buf.flipindex; + + } + + + CalculateTextureSourceRects(index, 3); + glDisable(m_textureTarget); + + return true; +} + +#endif
\ No newline at end of file diff --git a/xbmc/cores/VideoRenderers/HwDecRender/RendererVDA.h b/xbmc/cores/VideoRenderers/HwDecRender/RendererVDA.h new file mode 100644 index 0000000000..a170dd66a2 --- /dev/null +++ b/xbmc/cores/VideoRenderers/HwDecRender/RendererVDA.h @@ -0,0 +1,54 @@ +/* + * Copyright (C) 2007-2015 Team XBMC + * http://xbmc.org + * + * This Program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This Program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with XBMC; see the file COPYING. If not, see + * <http://www.gnu.org/licenses/>. + * + */ + +#pragma once + +#include "system.h" + +#if defined(TARGET_DARWIN_OSX) + +#include "cores/VideoRenderers/LinuxRendererGL.h" + +class CRendererVDA : public CLinuxRendererGL +{ +public: + CRendererVDA(); + virtual ~CRendererVDA(); + + // Player functions + virtual void AddVideoPictureHW(DVDVideoPicture &picture, int index); + virtual void ReleaseBuffer(int idx); + + // Feature support + virtual bool Supports(EINTERLACEMETHOD method); + virtual bool Supports(EDEINTERLACEMODE mode); + + virtual EINTERLACEMETHOD AutoInterlaceMethod(); + +protected: + virtual bool LoadShadersHook(); + + // textures + virtual bool UploadTexture(int index); + virtual void DeleteTexture(int index); + virtual bool CreateTexture(int index); +}; + +#endif diff --git a/xbmc/cores/VideoRenderers/HwDecRender/RendererVDPAU.cpp b/xbmc/cores/VideoRenderers/HwDecRender/RendererVDPAU.cpp new file mode 100644 index 0000000000..13378989a7 --- /dev/null +++ b/xbmc/cores/VideoRenderers/HwDecRender/RendererVDPAU.cpp @@ -0,0 +1,418 @@ +/* + * Copyright (C) 2007-2015 Team XBMC + * http://xbmc.org + * + * This Program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This Program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with XBMC; see the file COPYING. If not, see + * <http://www.gnu.org/licenses/>. + * + */ + +#include "RendererVDPAU.h" + +#ifdef HAVE_LIBVDPAU + +#include "cores/dvdplayer/DVDCodecs/Video/VDPAU.h" +#include "settings/Settings.h" +#include "settings/AdvancedSettings.h" +#include "utils/log.h" +#include "utils/GLUtils.h" + +CRendererVDPAU::CRendererVDPAU() +{ + +} + +CRendererVDPAU::~CRendererVDPAU() +{ + for (int i = 0; i < NUM_BUFFERS; ++i) + { + DeleteTexture(i); + } +} + +void CRendererVDPAU::AddVideoPictureHW(DVDVideoPicture &picture, int index) +{ + VDPAU::CVdpauRenderPicture *vdpau = picture.vdpau; + YUVBUFFER &buf = m_buffers[index]; + VDPAU::CVdpauRenderPicture *pic = vdpau->Acquire(); + if (buf.hwDec) + ((VDPAU::CVdpauRenderPicture*)buf.hwDec)->Release(); + buf.hwDec = pic; +} + +void CRendererVDPAU::ReleaseBuffer(int idx) +{ + YUVBUFFER &buf = m_buffers[idx]; + if (buf.hwDec) + ((VDPAU::CVdpauRenderPicture*)buf.hwDec)->Release(); + buf.hwDec = NULL; +} + +CRenderInfo CRendererVDPAU::GetRenderInfo() +{ + CRenderInfo info; + info.formats = m_formats; + info.max_buffer_size = NUM_BUFFERS; + info.optimal_buffer_size = 5; + return info; +} + +bool CRendererVDPAU::Supports(ERENDERFEATURE feature) +{ + if(feature == RENDERFEATURE_BRIGHTNESS || + feature == RENDERFEATURE_CONTRAST) + { + if ((m_renderMethod & RENDER_VDPAU) && !CSettings::GetInstance().GetBool(CSettings::SETTING_VIDEOSCREEN_LIMITEDRANGE)) + return true; + + return (m_renderMethod & RENDER_GLSL) + || (m_renderMethod & RENDER_ARB) + || ((m_renderMethod & RENDER_SW) && glewIsSupported("GL_ARB_imaging") == GL_TRUE); + } + else if (feature == RENDERFEATURE_NOISE || + feature == RENDERFEATURE_SHARPNESS) + { + if (m_format == RENDER_FMT_VDPAU) + return true; + } + else if (feature == RENDERFEATURE_STRETCH || + feature == RENDERFEATURE_ZOOM || + feature == RENDERFEATURE_VERTICAL_SHIFT || + feature == RENDERFEATURE_PIXEL_RATIO || + feature == RENDERFEATURE_POSTPROCESS || + feature == RENDERFEATURE_ROTATION || + feature == RENDERFEATURE_NONLINSTRETCH) + return true; + + return false; +} + +bool CRendererVDPAU::Supports(EINTERLACEMETHOD method) +{ + VDPAU::CVdpauRenderPicture *VDPAUPic = (VDPAU::CVdpauRenderPicture*)m_buffers[m_iYV12RenderBuffer].hwDec; + if(VDPAUPic && VDPAUPic->vdpau) + return VDPAUPic->vdpau->Supports(method); + return false; +} + +bool CRendererVDPAU::Supports(ESCALINGMETHOD method) +{ + if (m_format == RENDER_FMT_VDPAU_420) + return CLinuxRendererGL::Supports(method); + + //nearest neighbor doesn't work on YUY2 and UYVY + if (method == VS_SCALINGMETHOD_NEAREST && + m_format != RENDER_FMT_YUYV422 && + m_format != RENDER_FMT_UYVY422) + return true; + + if(method == VS_SCALINGMETHOD_LINEAR + || method == VS_SCALINGMETHOD_AUTO) + return true; + + if(method == VS_SCALINGMETHOD_CUBIC + || method == VS_SCALINGMETHOD_LANCZOS2 + || method == VS_SCALINGMETHOD_SPLINE36_FAST + || method == VS_SCALINGMETHOD_LANCZOS3_FAST + || method == VS_SCALINGMETHOD_SPLINE36 + || method == VS_SCALINGMETHOD_LANCZOS3) + { + // if scaling is below level, avoid hq scaling + float scaleX = fabs(((float)m_sourceWidth - m_destRect.Width())/m_sourceWidth)*100; + float scaleY = fabs(((float)m_sourceHeight - m_destRect.Height())/m_sourceHeight)*100; + int minScale = CSettings::GetInstance().GetInt("videoplayer.hqscalers"); + if (scaleX < minScale && scaleY < minScale) + return false; + + // spline36 and lanczos3 are only allowed through advancedsettings.xml + if(method != VS_SCALINGMETHOD_SPLINE36 + && method != VS_SCALINGMETHOD_LANCZOS3) + return true; + else + return g_advancedSettings.m_videoEnableHighQualityHwScalers; + } + + return false; +} + +bool CRendererVDPAU::LoadShadersHook() +{ + if (m_format == RENDER_FMT_VDPAU) + { + CLog::Log(LOGNOTICE, "GL: Using VDPAU render method"); + m_renderMethod = RENDER_VDPAU; + return true; + } + return false; +} + +bool CRendererVDPAU::RenderHook(int idx) +{ + UpdateVideoFilter(); + + if (m_format == RENDER_FMT_VDPAU_420) + { + switch(m_renderQuality) + { + case RQ_LOW: + case RQ_SINGLEPASS: + if (m_currentField == FIELD_FULL) + RenderProgressiveWeave(idx, m_currentField); + else + RenderSinglePass(idx, m_currentField); + VerifyGLState(); + break; + + case RQ_MULTIPASS: + if (m_currentField == FIELD_FULL) + RenderProgressiveWeave(idx, m_currentField); + else + { + RenderToFBO(idx, m_currentField); + RenderFromFBO(); + } + VerifyGLState(); + break; + } + } + else + { + RenderRGB(idx, m_currentField); + } + + YUVBUFFER &buf = m_buffers[idx]; + if (buf.hwDec) + { + ((VDPAU::CVdpauRenderPicture*)buf.hwDec)->Sync(); + } + return true; +} + +bool CRendererVDPAU::CreateTexture(int index) +{ + if (m_format == RENDER_FMT_VDPAU) + return CreateVDPAUTexture(index); + else if (m_format == RENDER_FMT_VDPAU_420) + return CreateVDPAUTexture420(index); + else + return false; +} + +void CRendererVDPAU::DeleteTexture(int index) +{ + if (m_format == RENDER_FMT_VDPAU) + DeleteVDPAUTexture(index); + else if (m_format == RENDER_FMT_VDPAU_420) + DeleteVDPAUTexture420(index); +} + +bool CRendererVDPAU::UploadTexture(int index) +{ + if (m_format == RENDER_FMT_VDPAU) + return UploadVDPAUTexture(index); + else if (m_format == RENDER_FMT_VDPAU_420) + return UploadVDPAUTexture420(index); + else + return false; +} + +bool CRendererVDPAU::CreateVDPAUTexture(int index) +{ + YV12Image &im = m_buffers[index].image; + YUVFIELDS &fields = m_buffers[index].fields; + YUVPLANE &plane = fields[FIELD_FULL][0]; + + DeleteVDPAUTexture(index); + + memset(&im , 0, sizeof(im)); + memset(&fields, 0, sizeof(fields)); + im.height = m_sourceHeight; + im.width = m_sourceWidth; + + plane.texwidth = im.width; + plane.texheight = im.height; + + plane.pixpertex_x = 1; + plane.pixpertex_y = 1; + + plane.id = 1; + return true; +} + +void CRendererVDPAU::DeleteVDPAUTexture(int index) +{ + YUVPLANE &plane = m_buffers[index].fields[FIELD_FULL][0]; + + if (m_buffers[index].hwDec) + ((VDPAU::CVdpauRenderPicture*)m_buffers[index].hwDec)->Release(); + m_buffers[index].hwDec = NULL; + + plane.id = 0; +} + +bool CRendererVDPAU::UploadVDPAUTexture(int index) +{ + VDPAU::CVdpauRenderPicture *vdpau = (VDPAU::CVdpauRenderPicture*)m_buffers[index].hwDec; + + YUVFIELDS &fields = m_buffers[index].fields; + YUVPLANE &plane = fields[FIELD_FULL][0]; + + if (!vdpau || !vdpau->valid) + { + return false; + } + + plane.id = vdpau->texture[0]; + + // in stereoscopic mode sourceRect may only + // be a part of the source video surface + plane.rect = m_sourceRect; + + // clip rect + if (vdpau->crop.x1 > plane.rect.x1) + plane.rect.x1 = vdpau->crop.x1; + if (vdpau->crop.x2 < plane.rect.x2) + plane.rect.x2 = vdpau->crop.x2; + if (vdpau->crop.y1 > plane.rect.y1) + plane.rect.y1 = vdpau->crop.y1; + if (vdpau->crop.y2 < plane.rect.y2) + plane.rect.y2 = vdpau->crop.y2; + + plane.texheight = vdpau->texHeight; + plane.texwidth = vdpau->texWidth; + + if (m_textureTarget == GL_TEXTURE_2D) + { + plane.rect.y1 /= plane.texheight; + plane.rect.y2 /= plane.texheight; + plane.rect.x1 /= plane.texwidth; + plane.rect.x2 /= plane.texwidth; + } + + return true; +} + +bool CRendererVDPAU::CreateVDPAUTexture420(int index) +{ + YV12Image &im = m_buffers[index].image; + YUVFIELDS &fields = m_buffers[index].fields; + YUVPLANE &plane = fields[0][0]; + GLuint *pbo = m_buffers[index].pbo; + + DeleteVDPAUTexture420(index); + + memset(&im , 0, sizeof(im)); + memset(&fields, 0, sizeof(fields)); + + im.cshift_x = 1; + im.cshift_y = 1; + + im.plane[0] = NULL; + im.plane[1] = NULL; + im.plane[2] = NULL; + + for(int p=0; p<3; p++) + { + pbo[p] = None; + } + + plane.id = 1; + + return true; +} + +void CRendererVDPAU::DeleteVDPAUTexture420(int index) +{ + YUVFIELDS &fields = m_buffers[index].fields; + + if (m_buffers[index].hwDec) + ((VDPAU::CVdpauRenderPicture*)m_buffers[index].hwDec)->Release(); + m_buffers[index].hwDec = NULL; + + fields[0][0].id = 0; + fields[1][0].id = 0; + fields[1][1].id = 0; + fields[2][0].id = 0; + fields[2][1].id = 0; +} + +bool CRendererVDPAU::UploadVDPAUTexture420(int index) +{ + VDPAU::CVdpauRenderPicture *vdpau = (VDPAU::CVdpauRenderPicture*)m_buffers[index].hwDec; + YV12Image &im = m_buffers[index].image; + + YUVFIELDS &fields = m_buffers[index].fields; + + if (!vdpau || !vdpau->valid) + { + return false; + } + + im.height = vdpau->texHeight; + im.width = vdpau->texWidth; + + // YUV + for (int f = FIELD_TOP; f<=FIELD_BOT ; f++) + { + YUVPLANES &planes = fields[f]; + + planes[0].texwidth = im.width; + planes[0].texheight = im.height >> 1; + + planes[1].texwidth = planes[0].texwidth >> im.cshift_x; + planes[1].texheight = planes[0].texheight >> im.cshift_y; + planes[2].texwidth = planes[1].texwidth; + planes[2].texheight = planes[1].texheight; + + for (int p = 0; p < 3; p++) + { + planes[p].pixpertex_x = 1; + planes[p].pixpertex_y = 1; + } + } + // crop +// m_sourceRect.x1 += vdpau->crop.x1; +// m_sourceRect.x2 -= vdpau->crop.x2; +// m_sourceRect.y1 += vdpau->crop.y1; +// m_sourceRect.y2 -= vdpau->crop.y2; + + // set textures + fields[1][0].id = vdpau->texture[0]; + fields[1][1].id = vdpau->texture[2]; + fields[1][2].id = vdpau->texture[2]; + fields[2][0].id = vdpau->texture[1]; + fields[2][1].id = vdpau->texture[3]; + fields[2][2].id = vdpau->texture[3]; + + glEnable(m_textureTarget); + for (int f = FIELD_TOP; f <= FIELD_BOT; f++) + { + for (int p=0; p<2; p++) + { + glBindTexture(m_textureTarget,fields[f][p].id); + glTexParameteri(m_textureTarget, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(m_textureTarget, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(m_textureTarget, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(m_textureTarget, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + + glBindTexture(m_textureTarget,0); + VerifyGLState(); + } + } + CalculateTextureSourceRects(index, 3); + glDisable(m_textureTarget); + return true; +} + +#endif diff --git a/xbmc/cores/VideoRenderers/HwDecRender/RendererVDPAU.h b/xbmc/cores/VideoRenderers/HwDecRender/RendererVDPAU.h new file mode 100644 index 0000000000..55ab570993 --- /dev/null +++ b/xbmc/cores/VideoRenderers/HwDecRender/RendererVDPAU.h @@ -0,0 +1,64 @@ +/* + * Copyright (C) 2007-2015 Team XBMC + * http://xbmc.org + * + * This Program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This Program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with XBMC; see the file COPYING. If not, see + * <http://www.gnu.org/licenses/>. + * + */ + +#pragma once + +#include "system.h" + +#ifdef HAVE_LIBVDPAU + +#include "cores/VideoRenderers/LinuxRendererGL.h" + +class CRendererVDPAU : public CLinuxRendererGL +{ +public: + CRendererVDPAU(); + virtual ~CRendererVDPAU(); + + // Player functions + virtual void AddVideoPictureHW(DVDVideoPicture &picture, int index); + virtual void ReleaseBuffer(int idx); + virtual CRenderInfo GetRenderInfo(); + + // Feature support + virtual bool Supports(ERENDERFEATURE feature); + virtual bool Supports(EINTERLACEMETHOD method); + virtual bool Supports(ESCALINGMETHOD method); + +protected: + virtual bool LoadShadersHook(); + virtual bool RenderHook(int idx); + + // textures + virtual bool UploadTexture(int index); + virtual void DeleteTexture(int index); + virtual bool CreateTexture(int index); + + bool CreateVDPAUTexture(int index); + void DeleteVDPAUTexture(int index); + bool UploadVDPAUTexture(int index); + + bool CreateVDPAUTexture420(int index); + void DeleteVDPAUTexture420(int index); + bool UploadVDPAUTexture420(int index); +}; + +#endif + diff --git a/xbmc/cores/VideoRenderers/LinuxRendererGL.cpp b/xbmc/cores/VideoRenderers/LinuxRendererGL.cpp index cec75eb863..0ba50fabe7 100644 --- a/xbmc/cores/VideoRenderers/LinuxRendererGL.cpp +++ b/xbmc/cores/VideoRenderers/LinuxRendererGL.cpp @@ -54,20 +54,11 @@ extern "C" { #include "libswscale/swscale.h" } -#ifdef HAVE_LIBVDPAU -#include "cores/dvdplayer/DVDCodecs/Video/VDPAU.h" -#endif -#ifdef HAVE_LIBVA -#include "cores/dvdplayer/DVDCodecs/Video/VAAPI.h" -#endif - -#ifdef TARGET_DARWIN - #include "osx/CocoaInterface.h" - #include <CoreVideo/CoreVideo.h> - #include <OpenGL/CGLIOSurface.h> - #ifdef TARGET_DARWIN_OSX - #include "osx/DarwinUtils.h" - #endif +#ifdef TARGET_DARWIN_OSX +#include "osx/CocoaInterface.h" +#include <CoreVideo/CoreVideo.h> +#include <OpenGL/CGLIOSurface.h> +#include "osx/DarwinUtils.h" #endif //due to a bug on osx nvidia, using gltexsubimage2d with a pbo bound and a null pointer @@ -119,23 +110,12 @@ CLinuxRendererGL::YUVBUFFER::YUVBUFFER() memset(&image , 0, sizeof(image)); memset(&pbo , 0, sizeof(pbo)); flipindex = 0; -#ifdef HAVE_LIBVDPAU - vdpau = NULL; -#endif -#ifdef HAVE_LIBVA - vaapi = NULL; -#endif -#ifdef TARGET_DARWIN_OSX - cvBufferRef = NULL; -#endif + hwDec = NULL; } CLinuxRendererGL::YUVBUFFER::~YUVBUFFER() { -#ifdef TARGET_DARWIN_OSX - if (cvBufferRef) - CVBufferRelease(cvBufferRef); -#endif + } CLinuxRendererGL::CLinuxRendererGL() @@ -156,11 +136,6 @@ CLinuxRendererGL::CLinuxRendererGL() m_scalingMethod = VS_SCALINGMETHOD_LINEAR; m_scalingMethodGui = (ESCALINGMETHOD)-1; - // default texture handlers to YUV - m_textureUpload = &CLinuxRendererGL::UploadYV12Texture; - m_textureCreate = &CLinuxRendererGL::CreateYV12Texture; - m_textureDelete = &CLinuxRendererGL::DeleteYV12Texture; - m_rgbBuffer = NULL; m_rgbBufferSize = 0; m_context = NULL; @@ -224,7 +199,7 @@ bool CLinuxRendererGL::ValidateRenderer() return false; int index = m_iYV12RenderBuffer; - YUVBUFFER& buf = m_buffers[index]; + YUVBUFFER& buf = m_buffers[index]; if (!buf.fields[FIELD_FULL][0].id) return false; @@ -239,20 +214,16 @@ bool CLinuxRendererGL::ValidateRenderTarget() { if (!m_bValidated) { - if ((m_format == RENDER_FMT_CVBREF) || - (!glewIsSupported("GL_ARB_texture_non_power_of_two") && glewIsSupported("GL_ARB_texture_rectangle"))) + if (!glewIsSupported("GL_ARB_texture_non_power_of_two") && glewIsSupported("GL_ARB_texture_rectangle")) { - CLog::Log(LOGNOTICE,"Using GL_TEXTURE_RECTANGLE_ARB"); m_textureTarget = GL_TEXTURE_RECTANGLE_ARB; } - else - CLog::Log(LOGNOTICE,"Using GL_TEXTURE_2D"); // function pointer for texture might change in // call to LoadShaders glFinish(); for (int i = 0 ; i < NUM_BUFFERS ; i++) - (this->*m_textureDelete)(i); + DeleteTexture(i); // trigger update of video filters m_scalingMethodGui = (ESCALINGMETHOD)-1; @@ -260,8 +231,13 @@ bool CLinuxRendererGL::ValidateRenderTarget() // create the yuv textures LoadShaders(); + if (m_textureTarget == GL_TEXTURE_RECTANGLE_ARB) + CLog::Log(LOGNOTICE,"Using GL_TEXTURE_RECTANGLE_ARB"); + else + CLog::Log(LOGNOTICE,"Using GL_TEXTURE_2D"); + for (int i = 0 ; i < m_NumYV12Buffers ; i++) - (this->*m_textureCreate)(i); + CreateTexture(i); m_bValidated = true; return true; @@ -328,8 +304,11 @@ int CLinuxRendererGL::NextYV12Texture() int CLinuxRendererGL::GetImage(YV12Image *image, int source, bool readonly) { - if (!image) return -1; - if (!m_bValidated) return -1; + if (!image) + return -1; + + if (!m_bValidated) + return -1; /* take next available buffer */ if( source == AUTOSOURCE ) @@ -539,7 +518,7 @@ void CLinuxRendererGL::Flush() glFinish(); for (int i = 0 ; i < m_NumYV12Buffers ; i++) - (this->*m_textureDelete)(i); + DeleteTexture(i); glFinish(); m_bValidated = false; @@ -547,24 +526,6 @@ void CLinuxRendererGL::Flush() m_iYV12RenderBuffer = 0; } -void CLinuxRendererGL::ReleaseBuffer(int idx) -{ -#if defined(HAVE_LIBVDPAU) || defined(HAVE_LIBVA) || defined(TARGET_DARWIN) - YUVBUFFER &buf = m_buffers[idx]; -#endif -#ifdef HAVE_LIBVDPAU - SAFE_RELEASE(buf.vdpau); -#endif -#ifdef HAVE_LIBVA - SAFE_RELEASE(buf.vaapi); -#endif -#ifdef TARGET_DARWIN - if (buf.cvBufferRef) - CVBufferRelease(buf.cvBufferRef); - buf.cvBufferRef = NULL; -#endif -} - void CLinuxRendererGL::Update() { if (!m_bConfigured) return; @@ -713,7 +674,7 @@ void CLinuxRendererGL::FlipPage(int source) return; } -unsigned int CLinuxRendererGL::PreInit() +void CLinuxRendererGL::PreInit() { CSingleLock lock(g_graphicsContext); m_bConfigured = false; @@ -755,14 +716,9 @@ unsigned int CLinuxRendererGL::PreInit() m_formats.push_back(RENDER_FMT_NV12); m_formats.push_back(RENDER_FMT_YUYV422); m_formats.push_back(RENDER_FMT_UYVY422); -#ifdef TARGET_DARWIN - m_formats.push_back(RENDER_FMT_CVBREF); -#endif // setup the background colour m_clearColour = (float)(g_advancedSettings.m_videoBlackBarColour & 0xff) / 0xff; - - return true; } void CLinuxRendererGL::UpdateVideoFilter() @@ -834,7 +790,7 @@ void CLinuxRendererGL::UpdateVideoFilter() case VS_SCALINGMETHOD_LINEAR: SetTextureFilter(m_scalingMethod == VS_SCALINGMETHOD_NEAREST ? GL_NEAREST : GL_LINEAR); m_renderQuality = RQ_SINGLEPASS; - if (((m_renderMethod & RENDER_VDPAU) || (m_renderMethod & RENDER_VAAPI)) && m_nonLinStretch) + if (Supports(RENDERFEATURE_NONLINSTRETCH) && m_nonLinStretch) { m_pVideoFilterShader = new StretchFilterShader(); if (!m_pVideoFilterShader->CompileAndLink()) @@ -913,17 +869,7 @@ void CLinuxRendererGL::UpdateVideoFilter() void CLinuxRendererGL::LoadShaders(int field) { - if (m_format == RENDER_FMT_VDPAU) - { - CLog::Log(LOGNOTICE, "GL: Using VDPAU render method"); - m_renderMethod = RENDER_VDPAU; - } - else if (m_format == RENDER_FMT_VAAPI) - { - CLog::Log(LOGNOTICE, "GL: Using VAAPI render method"); - m_renderMethod = RENDER_VAAPI; - } - else + if (!LoadShadersHook()) { int requestedMethod = CSettings::GetInstance().GetInt(CSettings::SETTING_VIDEOPLAYER_RENDERMETHOD); CLog::Log(LOGDEBUG, "GL: Requested render method: %d", requestedMethod); @@ -1007,13 +953,6 @@ void CLinuxRendererGL::LoadShaders(int field) } } - /* cvbref format piggy back on normal glsl */ - if (m_format == RENDER_FMT_CVBREF) - { - CLog::Log(LOGNOTICE, "GL: Using CVBREF render method"); - m_renderMethod |= RENDER_CVREF; - } - // determine whether GPU supports NPOT textures if (!glewIsSupported("GL_ARB_texture_non_power_of_two")) { @@ -1039,57 +978,6 @@ void CLinuxRendererGL::LoadShaders(int field) } else m_pboUsed = false; - - // Now that we now the render method, setup texture function handlers - if (m_format == RENDER_FMT_NV12 || - m_format == RENDER_FMT_VAAPINV12) - { - m_textureUpload = &CLinuxRendererGL::UploadNV12Texture; - m_textureCreate = &CLinuxRendererGL::CreateNV12Texture; - m_textureDelete = &CLinuxRendererGL::DeleteNV12Texture; - } - else if (m_format == RENDER_FMT_YUYV422 || - m_format == RENDER_FMT_UYVY422) - { - m_textureUpload = &CLinuxRendererGL::UploadYUV422PackedTexture; - m_textureCreate = &CLinuxRendererGL::CreateYUV422PackedTexture; - m_textureDelete = &CLinuxRendererGL::DeleteYUV422PackedTexture; - } - else if (m_format == RENDER_FMT_VDPAU) - { - m_textureUpload = &CLinuxRendererGL::UploadVDPAUTexture; - m_textureCreate = &CLinuxRendererGL::CreateVDPAUTexture; - m_textureDelete = &CLinuxRendererGL::DeleteVDPAUTexture; - } - else if (m_format == RENDER_FMT_VDPAU_420) - { - m_textureUpload = &CLinuxRendererGL::UploadVDPAUTexture420; - m_textureCreate = &CLinuxRendererGL::CreateVDPAUTexture420; - m_textureDelete = &CLinuxRendererGL::DeleteVDPAUTexture420; - } - else if (m_format == RENDER_FMT_VAAPI) - { - m_textureUpload = &CLinuxRendererGL::UploadVAAPITexture; - m_textureCreate = &CLinuxRendererGL::CreateVAAPITexture; - m_textureDelete = &CLinuxRendererGL::DeleteVAAPITexture; - } - else if (m_format == RENDER_FMT_CVBREF) - { - m_textureUpload = &CLinuxRendererGL::UploadCVRefTexture; - m_textureCreate = &CLinuxRendererGL::CreateCVRefTexture; - m_textureDelete = &CLinuxRendererGL::DeleteCVRefTexture; - } - else - { - // setup default YV12 texture handlers - m_textureUpload = &CLinuxRendererGL::UploadYV12Texture; - m_textureCreate = &CLinuxRendererGL::CreateYV12Texture; - m_textureDelete = &CLinuxRendererGL::DeleteYV12Texture; - } - - //in case of software colorspace conversion, all formats are handled by the same method - if (m_renderMethod & RENDER_SW) - m_textureUpload = &CLinuxRendererGL::UploadRGBTexture; } void CLinuxRendererGL::UnInit() @@ -1121,8 +1009,7 @@ void CLinuxRendererGL::UnInit() // YV12 textures for (int i = 0; i < NUM_BUFFERS; ++i) { - (this->*m_textureDelete)(i); - DeleteVAAPITexture(i); + DeleteTexture(i); } // cleanup framebuffer object if it was in use @@ -1145,31 +1032,25 @@ void CLinuxRendererGL::Render(DWORD flags, int renderBuffer) m_currentField = FIELD_FULL; // call texture load function - if (!(this->*m_textureUpload)(renderBuffer)) + if (!UploadTexture(renderBuffer)) return; - if (m_renderMethod & RENDER_GLSL) + if (RenderHook(renderBuffer)) + ; + else if (m_renderMethod & RENDER_GLSL) { UpdateVideoFilter(); switch(m_renderQuality) { case RQ_LOW: case RQ_SINGLEPASS: - if (m_format == RENDER_FMT_VDPAU_420 && m_currentField == FIELD_FULL) - RenderProgressiveWeave(renderBuffer, m_currentField); - else - RenderSinglePass(renderBuffer, m_currentField); + RenderSinglePass(renderBuffer, m_currentField); VerifyGLState(); break; case RQ_MULTIPASS: - if (m_format == RENDER_FMT_VDPAU_420 && m_currentField == FIELD_FULL) - RenderProgressiveWeave(renderBuffer, m_currentField); - else - { - RenderToFBO(renderBuffer, m_currentField); - RenderFromFBO(); - } + RenderToFBO(renderBuffer, m_currentField); + RenderFromFBO(); VerifyGLState(); break; } @@ -1178,46 +1059,11 @@ void CLinuxRendererGL::Render(DWORD flags, int renderBuffer) { RenderSinglePass(renderBuffer, m_currentField); } -#ifdef HAVE_LIBVDPAU - else if (m_renderMethod & RENDER_VDPAU) - { - UpdateVideoFilter(); - RenderRGB(renderBuffer, m_currentField); - } -#endif -#ifdef HAVE_LIBVA - else if (m_renderMethod & RENDER_VAAPI) - { - UpdateVideoFilter(); - RenderRGB(renderBuffer, m_currentField); - } -#endif else { RenderSoftware(renderBuffer, m_currentField); VerifyGLState(); } - -#ifdef HAVE_LIBVDPAU - if (m_format == RENDER_FMT_VDPAU || m_format == RENDER_FMT_VDPAU_420) - { - YUVBUFFER &buf = m_buffers[renderBuffer]; - if (buf.vdpau) - { - buf.vdpau->Sync(); - } - } -#endif -#ifdef HAVE_LIBVA - if (m_format == RENDER_FMT_VAAPI) - { - YUVBUFFER &buf = m_buffers[renderBuffer]; - if (buf.vaapi) - { - buf.vaapi->Sync(); - } - } -#endif } void CLinuxRendererGL::RenderSinglePass(int index, int field) @@ -1557,7 +1403,6 @@ void CLinuxRendererGL::RenderProgressiveWeave(int index, int field) void CLinuxRendererGL::RenderRGB(int index, int field) { -#if defined(HAVE_LIBVDPAU) || defined(HAVE_LIBVA) YUVPLANE &plane = m_buffers[index].fields[FIELD_FULL][0]; glEnable(m_textureTarget); @@ -1626,7 +1471,6 @@ void CLinuxRendererGL::RenderRGB(int index, int field) glBindTexture (m_textureTarget, 0); glDisable(m_textureTarget); -#endif } void CLinuxRendererGL::RenderSoftware(int index, int field) @@ -1705,132 +1549,6 @@ bool CLinuxRendererGL::RenderCapture(CRenderCapture* capture) return true; } -//******************************************************************************************************** -// YV12 Texture creation, deletion, copying + clearing -//******************************************************************************************************** -bool CLinuxRendererGL::UploadYV12Texture(int source) -{ - YUVBUFFER& buf = m_buffers[source]; - YV12Image* im = &buf.image; - YUVFIELDS& fields = buf.fields; - - if (!(im->flags&IMAGE_FLAG_READY)) - return false; - bool deinterlacing; - if (m_currentField == FIELD_FULL) - deinterlacing = false; - else - deinterlacing = true; - - glEnable(m_textureTarget); - VerifyGLState(); - - glPixelStorei(GL_UNPACK_ALIGNMENT,1); - - if (deinterlacing) - { - // Load Even Y Field - LoadPlane( fields[FIELD_TOP][0] , GL_LUMINANCE, buf.flipindex - , im->width, im->height >> 1 - , im->stride[0]*2, im->bpp, im->plane[0] ); - - //load Odd Y Field - LoadPlane( fields[FIELD_BOT][0], GL_LUMINANCE, buf.flipindex - , im->width, im->height >> 1 - , im->stride[0]*2, im->bpp, im->plane[0] + im->stride[0]) ; - - // Load Even U & V Fields - LoadPlane( fields[FIELD_TOP][1], GL_LUMINANCE, buf.flipindex - , im->width >> im->cshift_x, im->height >> (im->cshift_y + 1) - , im->stride[1]*2, im->bpp, im->plane[1] ); - - LoadPlane( fields[FIELD_TOP][2], GL_ALPHA, buf.flipindex - , im->width >> im->cshift_x, im->height >> (im->cshift_y + 1) - , im->stride[2]*2, im->bpp, im->plane[2] ); - - // Load Odd U & V Fields - LoadPlane( fields[FIELD_BOT][1], GL_LUMINANCE, buf.flipindex - , im->width >> im->cshift_x, im->height >> (im->cshift_y + 1) - , im->stride[1]*2, im->bpp, im->plane[1] + im->stride[1] ); - - LoadPlane( fields[FIELD_BOT][2], GL_ALPHA, buf.flipindex - , im->width >> im->cshift_x, im->height >> (im->cshift_y + 1) - , im->stride[2]*2, im->bpp, im->plane[2] + im->stride[2] ); - } - else - { - //Load Y plane - LoadPlane( fields[FIELD_FULL][0], GL_LUMINANCE, buf.flipindex - , im->width, im->height - , im->stride[0], im->bpp, im->plane[0] ); - - //load U plane - LoadPlane( fields[FIELD_FULL][1], GL_LUMINANCE, buf.flipindex - , im->width >> im->cshift_x, im->height >> im->cshift_y - , im->stride[1], im->bpp, im->plane[1] ); - - //load V plane - LoadPlane( fields[FIELD_FULL][2], GL_ALPHA, buf.flipindex - , im->width >> im->cshift_x, im->height >> im->cshift_y - , im->stride[2], im->bpp, im->plane[2] ); - } - - VerifyGLState(); - - CalculateTextureSourceRects(source, 3); - - glDisable(m_textureTarget); - return true; -} - -void CLinuxRendererGL::DeleteYV12Texture(int index) -{ - YV12Image &im = m_buffers[index].image; - YUVFIELDS &fields = m_buffers[index].fields; - GLuint *pbo = m_buffers[index].pbo; - - if( fields[FIELD_FULL][0].id == 0 ) return; - - /* finish up all textures, and delete them */ - g_graphicsContext.BeginPaint(); //FIXME - for(int f = 0;f<MAX_FIELDS;f++) - { - for(int p = 0;p<MAX_PLANES;p++) - { - if( fields[f][p].id ) - { - if (glIsTexture(fields[f][p].id)) - glDeleteTextures(1, &fields[f][p].id); - fields[f][p].id = 0; - } - } - } - g_graphicsContext.EndPaint(); - - for(int p = 0;p<MAX_PLANES;p++) - { - if (pbo[p]) - { - if (im.plane[p]) - { - glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, pbo[p]); - glUnmapBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB); - im.plane[p] = NULL; - glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, 0); - } - glDeleteBuffersARB(1, pbo + p); - pbo[p] = 0; - } - else - { - if (im.plane[p]) - { - delete[] im.plane[p]; - im.plane[p] = NULL; - } - } - } -} static GLint GetInternalFormat(GLint format, int bpp) { @@ -1851,6 +1569,52 @@ static GLint GetInternalFormat(GLint format, int bpp) return format; } +//----------------------------------------------------------------------------- +// Textures +//----------------------------------------------------------------------------- + +bool CLinuxRendererGL::CreateTexture(int index) +{ + if (m_format == RENDER_FMT_NV12) + return CreateNV12Texture(index); + else if (m_format == RENDER_FMT_YUYV422 || + m_format == RENDER_FMT_UYVY422) + return CreateYUV422PackedTexture(index); + else + return CreateYV12Texture(index); +} + +void CLinuxRendererGL::DeleteTexture(int index) +{ + if (m_format == RENDER_FMT_NV12) + DeleteNV12Texture(index); + else if (m_format == RENDER_FMT_YUYV422 || + m_format == RENDER_FMT_UYVY422) + DeleteYUV422PackedTexture(index); + else + DeleteYV12Texture(index); +} + +bool CLinuxRendererGL::UploadTexture(int index) +{ + if (m_format == RENDER_FMT_NV12) + return UploadNV12Texture(index); + else if (m_format == RENDER_FMT_YUYV422 || + m_format == RENDER_FMT_UYVY422) + return UploadYUV422PackedTexture(index); + //in case of software colorspace conversion, all formats are handled by the same method + else if (m_renderMethod & RENDER_SW) + return UploadRGBTexture(index); + else + return UploadYV12Texture(index); + + return false; +} + +//******************************************************************************************************** +// YV12 Texture creation, deletion, copying + clearing +//******************************************************************************************************** + bool CLinuxRendererGL::CreateYV12Texture(int index) { /* since we also want the field textures, pitch must be texture aligned */ @@ -2014,6 +1778,130 @@ bool CLinuxRendererGL::CreateYV12Texture(int index) return true; } +bool CLinuxRendererGL::UploadYV12Texture(int source) +{ + YUVBUFFER& buf = m_buffers[source]; + YV12Image* im = &buf.image; + YUVFIELDS& fields = buf.fields; + + if (!(im->flags&IMAGE_FLAG_READY)) + return false; + bool deinterlacing; + if (m_currentField == FIELD_FULL) + deinterlacing = false; + else + deinterlacing = true; + + glEnable(m_textureTarget); + VerifyGLState(); + + glPixelStorei(GL_UNPACK_ALIGNMENT,1); + + if (deinterlacing) + { + // Load Even Y Field + LoadPlane( fields[FIELD_TOP][0] , GL_LUMINANCE, buf.flipindex + , im->width, im->height >> 1 + , im->stride[0]*2, im->bpp, im->plane[0] ); + + //load Odd Y Field + LoadPlane( fields[FIELD_BOT][0], GL_LUMINANCE, buf.flipindex + , im->width, im->height >> 1 + , im->stride[0]*2, im->bpp, im->plane[0] + im->stride[0]) ; + + // Load Even U & V Fields + LoadPlane( fields[FIELD_TOP][1], GL_LUMINANCE, buf.flipindex + , im->width >> im->cshift_x, im->height >> (im->cshift_y + 1) + , im->stride[1]*2, im->bpp, im->plane[1] ); + + LoadPlane( fields[FIELD_TOP][2], GL_ALPHA, buf.flipindex + , im->width >> im->cshift_x, im->height >> (im->cshift_y + 1) + , im->stride[2]*2, im->bpp, im->plane[2] ); + + // Load Odd U & V Fields + LoadPlane( fields[FIELD_BOT][1], GL_LUMINANCE, buf.flipindex + , im->width >> im->cshift_x, im->height >> (im->cshift_y + 1) + , im->stride[1]*2, im->bpp, im->plane[1] + im->stride[1] ); + + LoadPlane( fields[FIELD_BOT][2], GL_ALPHA, buf.flipindex + , im->width >> im->cshift_x, im->height >> (im->cshift_y + 1) + , im->stride[2]*2, im->bpp, im->plane[2] + im->stride[2] ); + } + else + { + //Load Y plane + LoadPlane( fields[FIELD_FULL][0], GL_LUMINANCE, buf.flipindex + , im->width, im->height + , im->stride[0], im->bpp, im->plane[0] ); + + //load U plane + LoadPlane( fields[FIELD_FULL][1], GL_LUMINANCE, buf.flipindex + , im->width >> im->cshift_x, im->height >> im->cshift_y + , im->stride[1], im->bpp, im->plane[1] ); + + //load V plane + LoadPlane( fields[FIELD_FULL][2], GL_ALPHA, buf.flipindex + , im->width >> im->cshift_x, im->height >> im->cshift_y + , im->stride[2], im->bpp, im->plane[2] ); + } + + VerifyGLState(); + + CalculateTextureSourceRects(source, 3); + + glDisable(m_textureTarget); + return true; +} + +void CLinuxRendererGL::DeleteYV12Texture(int index) +{ + YV12Image &im = m_buffers[index].image; + YUVFIELDS &fields = m_buffers[index].fields; + GLuint *pbo = m_buffers[index].pbo; + + if( fields[FIELD_FULL][0].id == 0 ) return; + + /* finish up all textures, and delete them */ + g_graphicsContext.BeginPaint(); //FIXME + for(int f = 0;f<MAX_FIELDS;f++) + { + for(int p = 0;p<MAX_PLANES;p++) + { + if( fields[f][p].id ) + { + if (glIsTexture(fields[f][p].id)) + glDeleteTextures(1, &fields[f][p].id); + fields[f][p].id = 0; + } + } + } + g_graphicsContext.EndPaint(); + + for(int p = 0;p<MAX_PLANES;p++) + { + if (pbo[p]) + { + if (im.plane[p]) + { + glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, pbo[p]); + glUnmapBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB); + im.plane[p] = NULL; + glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, 0); + } + glDeleteBuffersARB(1, pbo + p); + pbo[p] = 0; + } + else + { + if (im.plane[p]) + { + delete[] im.plane[p]; + im.plane[p] = NULL; + } + } + } +} + //******************************************************************************************************** // NV12 Texture loading, creation and deletion //******************************************************************************************************** @@ -2291,384 +2179,6 @@ void CLinuxRendererGL::DeleteNV12Texture(int index) } } -void CLinuxRendererGL::DeleteVDPAUTexture(int index) -{ -#ifdef HAVE_LIBVDPAU - YUVPLANE &plane = m_buffers[index].fields[FIELD_FULL][0]; - - SAFE_RELEASE(m_buffers[index].vdpau); - - plane.id = 0; -#endif -} - -bool CLinuxRendererGL::CreateVDPAUTexture(int index) -{ -#ifdef HAVE_LIBVDPAU - YV12Image &im = m_buffers[index].image; - YUVFIELDS &fields = m_buffers[index].fields; - YUVPLANE &plane = fields[FIELD_FULL][0]; - - DeleteVDPAUTexture(index); - - memset(&im , 0, sizeof(im)); - memset(&fields, 0, sizeof(fields)); - im.height = m_sourceHeight; - im.width = m_sourceWidth; - - plane.texwidth = im.width; - plane.texheight = im.height; - - plane.pixpertex_x = 1; - plane.pixpertex_y = 1; - - plane.id = 1; - -#endif - return true; -} - -bool CLinuxRendererGL::UploadVDPAUTexture(int index) -{ -#ifdef HAVE_LIBVDPAU - VDPAU::CVdpauRenderPicture *vdpau = m_buffers[index].vdpau; - - YUVFIELDS &fields = m_buffers[index].fields; - YUVPLANE &plane = fields[FIELD_FULL][0]; - - if (!vdpau || !vdpau->valid) - { - return false; - } - - plane.id = vdpau->texture[0]; - - // in stereoscopic mode sourceRect may only - // be a part of the source video surface - plane.rect = m_sourceRect; - - // clip rect - if (vdpau->crop.x1 > plane.rect.x1) - plane.rect.x1 = vdpau->crop.x1; - if (vdpau->crop.x2 < plane.rect.x2) - plane.rect.x2 = vdpau->crop.x2; - if (vdpau->crop.y1 > plane.rect.y1) - plane.rect.y1 = vdpau->crop.y1; - if (vdpau->crop.y2 < plane.rect.y2) - plane.rect.y2 = vdpau->crop.y2; - - plane.texheight = vdpau->texHeight; - plane.texwidth = vdpau->texWidth; - - if (m_textureTarget == GL_TEXTURE_2D) - { - plane.rect.y1 /= plane.texheight; - plane.rect.y2 /= plane.texheight; - plane.rect.x1 /= plane.texwidth; - plane.rect.x2 /= plane.texwidth; - } - -#endif - return true; -} - -void CLinuxRendererGL::DeleteVDPAUTexture420(int index) -{ -#ifdef HAVE_LIBVDPAU - YUVFIELDS &fields = m_buffers[index].fields; - - SAFE_RELEASE(m_buffers[index].vdpau); - - fields[0][0].id = 0; - fields[1][0].id = 0; - fields[1][1].id = 0; - fields[2][0].id = 0; - fields[2][1].id = 0; - -#endif -} - -bool CLinuxRendererGL::CreateVDPAUTexture420(int index) -{ -#ifdef HAVE_LIBVDPAU - YV12Image &im = m_buffers[index].image; - YUVFIELDS &fields = m_buffers[index].fields; - YUVPLANE &plane = fields[0][0]; - GLuint *pbo = m_buffers[index].pbo; - - DeleteVDPAUTexture420(index); - - memset(&im , 0, sizeof(im)); - memset(&fields, 0, sizeof(fields)); - - im.cshift_x = 1; - im.cshift_y = 1; - - im.plane[0] = NULL; - im.plane[1] = NULL; - im.plane[2] = NULL; - - for(int p=0; p<3; p++) - { - pbo[p] = None; - } - - plane.id = 1; - -#endif - return true; -} - -bool CLinuxRendererGL::UploadVDPAUTexture420(int index) -{ -#ifdef HAVE_LIBVDPAU - VDPAU::CVdpauRenderPicture *vdpau = m_buffers[index].vdpau; - YV12Image &im = m_buffers[index].image; - - YUVFIELDS &fields = m_buffers[index].fields; - - if (!vdpau || !vdpau->valid) - { - return false; - } - - im.height = vdpau->texHeight; - im.width = vdpau->texWidth; - - // YUV - for (int f = FIELD_TOP; f<=FIELD_BOT ; f++) - { - YUVPLANES &planes = fields[f]; - - planes[0].texwidth = im.width; - planes[0].texheight = im.height >> 1; - - planes[1].texwidth = planes[0].texwidth >> im.cshift_x; - planes[1].texheight = planes[0].texheight >> im.cshift_y; - planes[2].texwidth = planes[1].texwidth; - planes[2].texheight = planes[1].texheight; - - for (int p = 0; p < 3; p++) - { - planes[p].pixpertex_x = 1; - planes[p].pixpertex_y = 1; - } - } - // crop -// m_sourceRect.x1 += vdpau->crop.x1; -// m_sourceRect.x2 -= vdpau->crop.x2; -// m_sourceRect.y1 += vdpau->crop.y1; -// m_sourceRect.y2 -= vdpau->crop.y2; - - // set textures - fields[1][0].id = vdpau->texture[0]; - fields[1][1].id = vdpau->texture[2]; - fields[1][2].id = vdpau->texture[2]; - fields[2][0].id = vdpau->texture[1]; - fields[2][1].id = vdpau->texture[3]; - fields[2][2].id = vdpau->texture[3]; - - glEnable(m_textureTarget); - for (int f = FIELD_TOP; f <= FIELD_BOT; f++) - { - for (int p=0; p<2; p++) - { - glBindTexture(m_textureTarget,fields[f][p].id); - glTexParameteri(m_textureTarget, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameteri(m_textureTarget, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glTexParameteri(m_textureTarget, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameteri(m_textureTarget, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - - glBindTexture(m_textureTarget,0); - VerifyGLState(); - } - } - CalculateTextureSourceRects(index, 3); - glDisable(m_textureTarget); - -#endif - return true; -} - -void CLinuxRendererGL::DeleteVAAPITexture(int index) -{ -#ifdef HAVE_LIBVA - YUVPLANE &plane = m_buffers[index].fields[FIELD_FULL][0]; - SAFE_RELEASE(m_buffers[index].vaapi); - plane.id = 0; -#endif -} - -bool CLinuxRendererGL::CreateVAAPITexture(int index) -{ -#ifdef HAVE_LIBVA - YV12Image &im = m_buffers[index].image; - YUVFIELDS &fields = m_buffers[index].fields; - YUVPLANE &plane = fields[0][0]; - - DeleteVAAPITexture(index); - - memset(&im , 0, sizeof(im)); - memset(&fields, 0, sizeof(fields)); - im.height = m_sourceHeight; - im.width = m_sourceWidth; - - plane.texwidth = im.width; - plane.texheight = im.height; - - plane.pixpertex_x = 1; - plane.pixpertex_y = 1; - - plane.id = 1; - -#endif - return true; -} - -bool CLinuxRendererGL::UploadVAAPITexture(int index) -{ -#ifdef HAVE_LIBVA - VAAPI::CVaapiRenderPicture *vaapi = m_buffers[index].vaapi; - - YUVFIELDS &fields = m_buffers[index].fields; - YUVPLANE &plane = fields[FIELD_FULL][0]; - - if (!vaapi || !vaapi->valid) - { - return false; - } - - if (!vaapi->CopyGlx()) - return false; - - plane.id = vaapi->texture; - - // in stereoscopic mode sourceRect may only - // be a part of the source video surface - plane.rect = m_sourceRect; - - // clip rect - if (vaapi->crop.x1 > plane.rect.x1) - plane.rect.x1 = vaapi->crop.x1; - if (vaapi->crop.x2 < plane.rect.x2) - plane.rect.x2 = vaapi->crop.x2; - if (vaapi->crop.y1 > plane.rect.y1) - plane.rect.y1 = vaapi->crop.y1; - if (vaapi->crop.y2 < plane.rect.y2) - plane.rect.y2 = vaapi->crop.y2; - - plane.texheight = vaapi->texHeight; - plane.texwidth = vaapi->texWidth; - - if (m_textureTarget == GL_TEXTURE_2D) - { - plane.rect.y1 /= plane.texheight; - plane.rect.y2 /= plane.texheight; - plane.rect.x1 /= plane.texwidth; - plane.rect.x2 /= plane.texwidth; - } - -#endif - return true; -} - -//******************************************************************************************************** -// CoreVideoRef Texture creation, deletion, copying + clearing -//******************************************************************************************************** -bool CLinuxRendererGL::UploadCVRefTexture(int index) -{ -#ifdef TARGET_DARWIN - YUVBUFFER &buf = m_buffers[index]; - YUVFIELDS &fields = buf.fields; - - CVBufferRef cvBufferRef = m_buffers[index].cvBufferRef; - - glEnable(m_textureTarget); - - if (cvBufferRef && fields[m_currentField][0].flipindex != buf.flipindex) - { - - // It is the fastest way to render a CVPixelBuffer backed - // with an IOSurface as there is no CPU -> GPU upload. - CGLContextObj cgl_ctx = (CGLContextObj)g_Windowing.GetCGLContextObj(); - IOSurfaceRef surface = CVPixelBufferGetIOSurface(cvBufferRef); - GLsizei texWidth = IOSurfaceGetWidth(surface); - GLsizei texHeight= IOSurfaceGetHeight(surface); - OSType format_type = IOSurfaceGetPixelFormat(surface); - - glBindTexture(m_textureTarget, fields[FIELD_FULL][0].id); - - if (format_type == kCVPixelFormatType_422YpCbCr8) - CGLTexImageIOSurface2D(cgl_ctx, m_textureTarget, GL_RGBA8, - texWidth / 2, texHeight, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, surface, 0); - else if (format_type == kCVPixelFormatType_32BGRA) - CGLTexImageIOSurface2D(cgl_ctx, m_textureTarget, GL_RGBA8, - texWidth, texHeight, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, surface, 0); - - glBindTexture(m_textureTarget, 0); - fields[FIELD_FULL][0].flipindex = buf.flipindex; - - } - - - CalculateTextureSourceRects(index, 3); - glDisable(m_textureTarget); - -#endif - return true; -} - -void CLinuxRendererGL::DeleteCVRefTexture(int index) -{ -#ifdef TARGET_DARWIN - YUVPLANE &plane = m_buffers[index].fields[0][0]; - - if (m_buffers[index].cvBufferRef) - CVBufferRelease(m_buffers[index].cvBufferRef); - m_buffers[index].cvBufferRef = NULL; - - if (plane.id && glIsTexture(plane.id)) - glDeleteTextures(1, &plane.id), plane.id = 0; -#endif -} - -bool CLinuxRendererGL::CreateCVRefTexture(int index) -{ -#ifdef TARGET_DARWIN - YV12Image &im = m_buffers[index].image; - YUVFIELDS &fields = m_buffers[index].fields; - YUVPLANE &plane = fields[0][0]; - - DeleteCVRefTexture(index); - - memset(&im , 0, sizeof(im)); - memset(&fields, 0, sizeof(fields)); - - im.bpp = 1; - im.width = m_sourceWidth; - im.height = m_sourceHeight; - im.cshift_x = 0; - im.cshift_y = 0; - - plane.pixpertex_x = 2; - plane.pixpertex_y = 1; - plane.texwidth = im.width / plane.pixpertex_x; - plane.texheight = im.height / plane.pixpertex_y; - - if(m_renderMethod & RENDER_POT) - { - plane.texwidth = NP2(plane.texwidth); - plane.texheight = NP2(plane.texheight); - } - - glEnable(m_textureTarget); - glGenTextures(1, &plane.id); - glDisable(m_textureTarget); - -#endif - return true; -} - bool CLinuxRendererGL::UploadYUV422PackedTexture(int source) { YUVBUFFER& buf = m_buffers[source]; @@ -3240,12 +2750,6 @@ bool CLinuxRendererGL::Supports(ERENDERFEATURE feature) { if(feature == RENDERFEATURE_BRIGHTNESS) { - if ((m_renderMethod & RENDER_VDPAU) && !CSettings::GetInstance().GetBool(CSettings::SETTING_VIDEOSCREEN_LIMITEDRANGE)) - return true; - - if (m_renderMethod & RENDER_VAAPI) - return false; - return (m_renderMethod & RENDER_GLSL) || (m_renderMethod & RENDER_ARB) || ((m_renderMethod & RENDER_SW) && glewIsSupported("GL_ARB_imaging") == GL_TRUE); @@ -3253,12 +2757,6 @@ bool CLinuxRendererGL::Supports(ERENDERFEATURE feature) if(feature == RENDERFEATURE_CONTRAST) { - if ((m_renderMethod & RENDER_VDPAU) && !CSettings::GetInstance().GetBool(CSettings::SETTING_VIDEOSCREEN_LIMITEDRANGE)) - return true; - - if (m_renderMethod & RENDER_VAAPI) - return false; - return (m_renderMethod & RENDER_GLSL) || (m_renderMethod & RENDER_ARB) || ((m_renderMethod & RENDER_SW) && glewIsSupported("GL_ARB_imaging") == GL_TRUE); @@ -3268,21 +2766,16 @@ bool CLinuxRendererGL::Supports(ERENDERFEATURE feature) return false; if(feature == RENDERFEATURE_NOISE) - { - if(m_renderMethod & RENDER_VDPAU) - return true; - } + return false; if(feature == RENDERFEATURE_SHARPNESS) { - if(m_renderMethod & RENDER_VDPAU) - return true; + return false; } if (feature == RENDERFEATURE_NONLINSTRETCH) { - if (((m_renderMethod & RENDER_GLSL) && !(m_renderMethod & RENDER_POT)) || - (m_renderMethod & RENDER_VDPAU) || (m_renderMethod & RENDER_VAAPI)) + if ((m_renderMethod & RENDER_GLSL) && !(m_renderMethod & RENDER_POT)) return true; } @@ -3322,34 +2815,6 @@ bool CLinuxRendererGL::Supports(EINTERLACEMETHOD method) if(method == VS_INTERLACEMETHOD_AUTO) return true; - - if(m_renderMethod & RENDER_VDPAU || - m_format == RENDER_FMT_VDPAU_420) - { -#ifdef HAVE_LIBVDPAU - VDPAU::CVdpauRenderPicture *vdpauPic = m_buffers[m_iYV12RenderBuffer].vdpau; - if(vdpauPic && vdpauPic->vdpau) - return vdpauPic->vdpau->Supports(method); -#endif - return false; - } - - if(m_format == RENDER_FMT_VAAPI || - m_format == RENDER_FMT_VAAPINV12) - { -#ifdef HAVE_LIBVA - VAAPI::CVaapiRenderPicture *vaapiPic = m_buffers[m_iYV12RenderBuffer].vaapi; - if(vaapiPic && vaapiPic->vaapi) - return vaapiPic->vaapi->Supports(method); -#endif - return false; - } - -#ifdef TARGET_DARWIN_IOS - // iOS does not have the ponies for YADIF - if(method == VS_INTERLACEMETHOD_DEINTERLACE) - return false; -#endif if(method == VS_INTERLACEMETHOD_DEINTERLACE || method == VS_INTERLACEMETHOD_DEINTERLACE_HALF @@ -3392,8 +2857,7 @@ bool CLinuxRendererGL::Supports(ESCALINGMETHOD method) if (scaleX < minScale && scaleY < minScale) return false; - if ((glewIsSupported("GL_EXT_framebuffer_object") && (m_renderMethod & RENDER_GLSL)) || - (m_renderMethod & RENDER_VDPAU) || (m_renderMethod & RENDER_VAAPI)) + if (glewIsSupported("GL_EXT_framebuffer_object") && (m_renderMethod & RENDER_GLSL)) { // spline36 and lanczos3 are only allowed through advancedsettings.xml if(method != VS_SCALINGMETHOD_SPLINE36 @@ -3409,12 +2873,6 @@ bool CLinuxRendererGL::Supports(ESCALINGMETHOD method) EINTERLACEMETHOD CLinuxRendererGL::AutoInterlaceMethod() { - if(m_renderMethod & RENDER_CVREF) - return VS_INTERLACEMETHOD_NONE; - - if(m_renderMethod & RENDER_VDPAU) - return VS_INTERLACEMETHOD_NONE; - if(Supports(VS_INTERLACEMETHOD_RENDER_BOB)) return VS_INTERLACEMETHOD_RENDER_BOB; @@ -3460,54 +2918,8 @@ CRenderInfo CLinuxRendererGL::GetRenderInfo() CRenderInfo info; info.formats = m_formats; info.max_buffer_size = NUM_BUFFERS; - if(m_format == RENDER_FMT_CVBREF) - info.optimal_buffer_size = 2; - else if (m_format == RENDER_FMT_VAAPI || - m_format == RENDER_FMT_VAAPINV12 || - m_format == RENDER_FMT_VDPAU || - m_format == RENDER_FMT_VDPAU_420) - info.optimal_buffer_size = 5; - else - info.optimal_buffer_size = 3; + info.optimal_buffer_size = 3; return info; } -void CLinuxRendererGL::AddVideoPictureHW(DVDVideoPicture &picture, int index) -{ - if (picture.format == RENDER_FMT_VDPAU || - picture.format == RENDER_FMT_VDPAU_420) - { -#ifdef HAVE_LIBVDPAU - VDPAU::CVdpauRenderPicture *vdpau = picture.vdpau; - YUVBUFFER &buf = m_buffers[index]; - VDPAU::CVdpauRenderPicture *pic = vdpau->Acquire(); - SAFE_RELEASE(buf.vdpau); - buf.vdpau = pic; -#endif - } - else if (picture.format == RENDER_FMT_VAAPI || - picture.format == RENDER_FMT_VAAPINV12) - { -#ifdef HAVE_LIBVA - VAAPI::CVaapiRenderPicture *vaapi = picture.vaapi; - YUVBUFFER &buf = m_buffers[index]; - VAAPI::CVaapiRenderPicture *pic = vaapi->Acquire(); - SAFE_RELEASE(buf.vaapi); - buf.vaapi = pic; -#endif - } - else if (picture.format == RENDER_FMT_CVBREF) - { -#ifdef TARGET_DARWIN - struct __CVBuffer *cvBufferRef = picture.cvBufferRef; - YUVBUFFER &buf = m_buffers[index]; - if (buf.cvBufferRef) - CVBufferRelease(buf.cvBufferRef); - buf.cvBufferRef = cvBufferRef; - // retain another reference, this way dvdplayer and renderer can issue releases. - CVBufferRetain(buf.cvBufferRef); -#endif - } -} - #endif diff --git a/xbmc/cores/VideoRenderers/LinuxRendererGL.h b/xbmc/cores/VideoRenderers/LinuxRendererGL.h index 2ae7ad6024..249b82da7a 100644 --- a/xbmc/cores/VideoRenderers/LinuxRendererGL.h +++ b/xbmc/cores/VideoRenderers/LinuxRendererGL.h @@ -40,8 +40,6 @@ class CRenderCapture; class CBaseTexture; namespace Shaders { class BaseYUV2RGBShader; } namespace Shaders { class BaseVideoFilterShader; } -namespace VAAPI { class CVaapiRenderPicture; } -namespace VDPAU { class CVdpauRenderPicture; } #undef ALIGN #define ALIGN(value, alignment) (((value)+((alignment)-1))&~((alignment)-1)) @@ -122,13 +120,11 @@ public: virtual bool IsConfigured() { return m_bConfigured; } virtual int GetImage(YV12Image *image, int source = AUTOSOURCE, bool readonly = false); virtual void ReleaseImage(int source, bool preserve = false); - virtual void AddVideoPictureHW(DVDVideoPicture &picture, int index); virtual void FlipPage(int source); - virtual unsigned int PreInit(); + virtual void PreInit(); virtual void UnInit(); virtual void Reset(); /* resets renderer after seek for example */ virtual void Flush(); - virtual void ReleaseBuffer(int idx); virtual void SetBufferSize(int numBuffers) { m_NumYV12Buffers = numBuffers; } virtual void RenderUpdate(bool clear, DWORD flags = 0, DWORD alpha = 255); virtual void Update(); @@ -146,8 +142,8 @@ public: protected: virtual void Render(DWORD flags, int renderBuffer); - void ClearBackBuffer(); - void DrawBlackBars(); + void ClearBackBuffer(); + void DrawBlackBars(); bool ValidateRenderer(); int NextYV12Texture(); @@ -157,9 +153,9 @@ protected: void UpdateVideoFilter(); // textures - bool (CLinuxRendererGL::*m_textureUpload)(int index); - void (CLinuxRendererGL::*m_textureDelete)(int index); - bool (CLinuxRendererGL::*m_textureCreate)(int index); + virtual bool UploadTexture(int index); + virtual void DeleteTexture(int index); + virtual bool CreateTexture(int index); bool UploadYV12Texture(int index); void DeleteYV12Texture(int index); @@ -168,22 +164,6 @@ protected: bool UploadNV12Texture(int index); void DeleteNV12Texture(int index); bool CreateNV12Texture(int index); - - bool UploadVDPAUTexture(int index); - void DeleteVDPAUTexture(int index); - bool CreateVDPAUTexture(int index); - - bool UploadVDPAUTexture420(int index); - void DeleteVDPAUTexture420(int index); - bool CreateVDPAUTexture420(int index); - - bool UploadVAAPITexture(int index); - void DeleteVAAPITexture(int index); - bool CreateVAAPITexture(int index); - - bool UploadCVRefTexture(int index); - void DeleteCVRefTexture(int index); - bool CreateCVRefTexture(int index); bool UploadYUV422PackedTexture(int index); void DeleteYUV422PackedTexture(int index); @@ -204,6 +184,10 @@ protected: void RenderRGB(int renderBuffer, int field); // render using vdpau/vaapi hardware void RenderProgressiveWeave(int renderBuffer, int field); // render using vdpau hardware + // hooks for HwDec Renderered + virtual bool LoadShadersHook() { return false; }; + virtual bool RenderHook(int idx) { return false; }; + struct { CFrameBufferObject fbo; @@ -260,15 +244,7 @@ protected: unsigned flipindex; /* used to decide if this has been uploaded */ GLuint pbo[MAX_PLANES]; -#ifdef HAVE_LIBVDPAU - VDPAU::CVdpauRenderPicture *vdpau; -#endif -#ifdef HAVE_LIBVA - VAAPI::CVaapiRenderPicture *vaapi; -#endif -#ifdef TARGET_DARWIN_OSX - struct __CVBuffer *cvBufferRef; -#endif + void *hwDec; }; typedef YUVBUFFER YUVBUFFERS[NUM_BUFFERS]; diff --git a/xbmc/cores/VideoRenderers/Makefile.in b/xbmc/cores/VideoRenderers/Makefile.in index 7fcc322618..d964285020 100644 --- a/xbmc/cores/VideoRenderers/Makefile.in +++ b/xbmc/cores/VideoRenderers/Makefile.in @@ -20,10 +20,6 @@ SRCS += LinuxRendererGLES.cpp SRCS += OverlayRendererGL.cpp endif -ifeq (@USE_MMAL@,1) -SRCS += MMALRenderer.cpp -endif - LIB = VideoRenderer.a include @abs_top_srcdir@/Makefile.include diff --git a/xbmc/cores/VideoRenderers/RenderManager.cpp b/xbmc/cores/VideoRenderers/RenderManager.cpp index 8146a727b1..d9949d2ed0 100644 --- a/xbmc/cores/VideoRenderers/RenderManager.cpp +++ b/xbmc/cores/VideoRenderers/RenderManager.cpp @@ -19,9 +19,6 @@ */ #include "system.h" -#if defined(HAS_GL) - #include "system_gl.h" -#endif #include "RenderManager.h" #include "RenderFlags.h" #include "threads/CriticalSection.h" @@ -40,7 +37,12 @@ #include "cores/DataCacheCore.h" #if defined(HAS_GL) - #include "LinuxRendererGL.h" +#include "LinuxRendererGL.h" +#include "HwDecRender/RendererVAAPI.h" +#include "HwDecRender/RendererVDPAU.h" +#if defined(TARGET_DARWIN_OSX) +#include "HwDecRender/RendererVDA.h" +#endif #elif defined(HAS_MMAL) #include "MMALRenderer.h" #elif HAS_GLES == 2 @@ -58,10 +60,6 @@ #include "../dvdplayer/DVDCodecs/Video/DVDVideoCodec.h" #include "../dvdplayer/DVDCodecs/DVDCodecUtils.h" -#ifdef HAVE_LIBVA - #include "../dvdplayer/DVDCodecs/Video/VAAPI.h" -#endif - using namespace KODI::MESSAGING; #define MAXPRESENTDELAY 0.500 @@ -104,10 +102,37 @@ static void requeue(std::deque<int> &trg, std::deque<int> &src) src.pop_front(); } +static std::string GetRenderFormatName(ERenderFormat format) +{ + switch(format) + { + case RENDER_FMT_YUV420P: return "YV12"; + case RENDER_FMT_YUV420P16: return "YV12P16"; + case RENDER_FMT_YUV420P10: return "YV12P10"; + case RENDER_FMT_NV12: return "NV12"; + case RENDER_FMT_UYVY422: return "UYVY"; + case RENDER_FMT_YUYV422: return "YUY2"; + case RENDER_FMT_VDPAU: return "VDPAU"; + case RENDER_FMT_VDPAU_420: return "VDPAU_420"; + case RENDER_FMT_DXVA: return "DXVA"; + case RENDER_FMT_VAAPI: return "VAAPI"; + case RENDER_FMT_VAAPINV12: return "VAAPI_NV12"; + case RENDER_FMT_OMXEGL: return "OMXEGL"; + case RENDER_FMT_CVBREF: return "BGRA"; + case RENDER_FMT_EGLIMG: return "EGLIMG"; + case RENDER_FMT_BYPASS: return "BYPASS"; + case RENDER_FMT_MEDIACODEC:return "MEDIACODEC"; + case RENDER_FMT_IMXMAP: return "IMXMAP"; + case RENDER_FMT_MMAL: return "MMAL"; + case RENDER_FMT_NONE: return "NONE"; + } + return "UNKNOWN"; +} + CXBMCRenderManager::CXBMCRenderManager() { m_pRenderer = NULL; - m_bIsStarted = false; + m_renderState = STATE_UNCONFIGURED; m_presentstep = PRESENT_IDLE; m_rendermethod = 0; @@ -128,7 +153,6 @@ CXBMCRenderManager::CXBMCRenderManager() CXBMCRenderManager::~CXBMCRenderManager() { delete m_pRenderer; - m_pRenderer = NULL; } void CXBMCRenderManager::GetVideoRect(CRect &source, CRect &dest, CRect &view) @@ -214,14 +238,11 @@ void CXBMCRenderManager::WaitPresentTime(double presenttime) avgerror /= ERRORBUFFSIZE; - //we change the clock speed slightly //to make every frame's presenttime end up in the middle of two vblanks //integral correction, clamp to -0.5:0.5 range m_presentcorr = std::max(std::min(m_presentcorr + avgerror * 0.01, 0.1), -0.1); g_VideoReferenceClock.SetFineAdjust(1.0 - avgerror * 0.01 - m_presentcorr * 0.01); - - //printf("%f %f % 2.0f%% % f % f\n", presenttime, clock, m_presentcorr * 100, error, error_org); } std::string CXBMCRenderManager::GetVSyncState() @@ -238,56 +259,118 @@ std::string CXBMCRenderManager::GetVSyncState() return state; } -bool CXBMCRenderManager::Configure(unsigned int width, unsigned int height, unsigned int d_width, unsigned int d_height, float fps, unsigned flags, ERenderFormat format, unsigned extended_format, unsigned int orientation, int buffers) +bool CXBMCRenderManager::Configure(DVDVideoPicture& picture, float fps, unsigned flags, unsigned int orientation, int buffers) { - CSingleLock lock2(m_presentlock); + // check if something has changed + { + float config_framerate = fps; + float render_framerate = g_graphicsContext.GetFPS(); + if (CSettings::GetInstance().GetInt(CSettings::SETTING_VIDEOPLAYER_ADJUSTREFRESHRATE) == ADJUST_REFRESHRATE_OFF) + render_framerate = config_framerate; + bool changerefresh = (fps != 0) && + (m_fps == 0.0 || fmod(m_fps, fps) != 0.0) && + (render_framerate != config_framerate); + + CSharedLock lock(m_sharedSection); + if (m_width == picture.iWidth && + m_height == picture.iHeight && + m_dwidth == picture.iDisplayWidth && + m_dheight == picture.iDisplayHeight && + !changerefresh && + (m_flags & ~CONF_FLAGS_FULLSCREEN) == (flags & ~CONF_FLAGS_FULLSCREEN) && + m_format == picture.format && + m_extended_format == picture.extended_format && + m_orientation == orientation && + m_NumberBuffers == buffers && + m_pRenderer != NULL) + return true; + } + + std::string formatstr = GetRenderFormatName(picture.format); + CLog::Log(LOGDEBUG, "CXBMCRenderManager::Configure - change configuration. %dx%d. display: %dx%d. framerate: %4.2f. format: %s", picture.iWidth, picture.iHeight, picture.iDisplayWidth, picture.iDisplayHeight, fps, formatstr.c_str()); - /* make sure any queued frame was fully presented */ - XbmcThreads::EndTime endtime(5000); - while(m_presentstep != PRESENT_IDLE && m_presentstep != PRESENT_READY) + // make sure any queued frame was fully presented { - if(endtime.IsTimePast()) + CSingleLock lock(m_presentlock); + XbmcThreads::EndTime endtime(5000); + while(m_presentstep != PRESENT_IDLE && m_presentstep != PRESENT_READY) { - CLog::Log(LOGWARNING, "CRenderManager::Configure - timeout waiting for state"); - return false; + if(endtime.IsTimePast()) + { + CLog::Log(LOGWARNING, "CRenderManager::Configure - timeout waiting for state"); + return false; + } + m_presentevent.wait(lock, endtime.MillisLeft()); } - m_presentevent.wait(lock2, endtime.MillisLeft()); - }; - lock2.Leave(); + } - CExclusiveLock lock(m_sharedSection); - if(!m_pRenderer) { - CLog::Log(LOGERROR, "%s called without a valid Renderer object", __FUNCTION__); + CExclusiveLock lock(m_sharedSection); + m_width = picture.iWidth; + m_height = picture.iHeight, + m_dwidth = picture.iDisplayWidth; + m_dheight = picture.iDisplayHeight; + m_fps = fps; + m_flags = flags; + m_format = picture.format; + m_extended_format = picture.extended_format; + m_orientation = orientation; + m_NumberBuffers = buffers; + m_renderState = STATE_CONFIGURING; + m_stateEvent.Reset(); + } + + if (!m_stateEvent.WaitMSec(1000)) + { + CLog::Log(LOGWARNING, "CRenderManager::Configure - timeout waiting for configure"); + return false; + } + + CSharedLock lock(m_sharedSection); + if (m_renderState != STATE_CONFIGURED) + { + CLog::Log(LOGWARNING, "CRenderManager::Configure - failed to configure"); return false; } + return true; +} + +bool CXBMCRenderManager::Configure() +{ + CExclusiveLock lock(m_sharedSection); + CSingleLock lock2(m_presentlock); - bool result = m_pRenderer->Configure(width, height, d_width, d_height, fps, flags, format, extended_format, orientation); - if(result) + if (m_pRenderer && m_pRenderer->GetRenderFormat() != m_format) { - if( flags & CONF_FLAGS_FULLSCREEN ) - { - lock.Leave(); - CApplicationMessenger::GetInstance().PostMsg(TMSG_SWITCHTOFULLSCREEN); - lock.Enter(); - } - lock2.Enter(); - m_format = format; + DeleteRenderer(); + } + + if(!m_pRenderer) + { + CreateRenderer(); + if (!m_pRenderer) + return false; + else + m_pRenderer->PreInit(); + } + bool result = m_pRenderer->Configure(m_width, m_height, m_dwidth, m_dheight, m_fps, m_flags, m_format, m_extended_format, m_orientation); + if (result) + { CRenderInfo info = m_pRenderer->GetRenderInfo(); int renderbuffers = info.optimal_buffer_size; m_QueueSize = renderbuffers; - if (buffers > 0) - m_QueueSize = std::min(buffers, renderbuffers); + if (m_NumberBuffers > 0) + m_QueueSize = std::min(m_NumberBuffers, renderbuffers); m_QueueSize = std::min(m_QueueSize, (int)info.max_buffer_size); m_QueueSize = std::min(m_QueueSize, NUM_BUFFERS); if(m_QueueSize < 2) { m_QueueSize = 2; - CLog::Log(LOGWARNING, "CXBMCRenderManager::Configure - queue size too small (%d, %d, %d)", m_QueueSize, renderbuffers, buffers); + CLog::Log(LOGWARNING, "CXBMCRenderManager::Configure - queue size too small (%d, %d, %d)", m_QueueSize, renderbuffers, m_NumberBuffers); } m_pRenderer->SetBufferSize(m_QueueSize); @@ -300,7 +383,6 @@ bool CXBMCRenderManager::Configure(unsigned int width, unsigned int height, unsi for (int i=1; i < m_QueueSize; i++) m_free.push_back(i); - m_bIsStarted = true; m_bRenderGUI = true; m_waitForBufferCount = 0; m_bReconfigured = true; @@ -310,17 +392,24 @@ bool CXBMCRenderManager::Configure(unsigned int width, unsigned int height, unsi m_presentevent.notifyAll(); m_renderedOverlay = false; + m_renderState = STATE_CONFIGURED; + CLog::Log(LOGDEBUG, "CXBMCRenderManager::Configure - %d", m_QueueSize); } + else + m_renderState = STATE_UNCONFIGURED; + m_stateEvent.Set(); return result; } bool CXBMCRenderManager::IsConfigured() const { - if (!m_pRenderer) + CSharedLock lock(m_sharedSection); + if (m_renderState == STATE_CONFIGURED) + return true; + else return false; - return m_pRenderer->IsConfigured(); } void CXBMCRenderManager::Update() @@ -350,54 +439,66 @@ bool CXBMCRenderManager::HasFrame() void CXBMCRenderManager::FrameMove() { - { CSharedLock lock(m_sharedSection); - CSingleLock lock2(m_presentlock); + CSharedLock lock(m_sharedSection); - if (!m_pRenderer) + if (m_renderState == STATE_UNCONFIGURED) + return; + else if (m_renderState == STATE_CONFIGURING) + { + lock.Leave(); + if (!Configure()) return; - if (m_presentstep == PRESENT_FRAME2) + if (m_flags & CONF_FLAGS_FULLSCREEN) { - if(!m_queued.empty()) - { - double timestamp = GetPresentTime(); - SPresent& m = m_Queue[m_presentsource]; - SPresent& q = m_Queue[m_queued.front()]; - if(timestamp > m.timestamp + (q.timestamp - m.timestamp) * 0.5) - { - m_presentstep = PRESENT_READY; - m_presentevent.notifyAll(); - } - } + CApplicationMessenger::GetInstance().PostMsg(TMSG_SWITCHTOFULLSCREEN); } + lock.Enter(); + } - if (m_presentstep == PRESENT_READY) - PrepareNextRender(); - - if(m_presentstep == PRESENT_FLIP) - { - m_pRenderer->FlipPage(m_presentsource); - m_presentstep = PRESENT_FRAME; - m_presentevent.notifyAll(); - } + CSingleLock lock2(m_presentlock); - /* release all previous */ - for(std::deque<int>::iterator it = m_discard.begin(); it != m_discard.end(); ) + if (m_presentstep == PRESENT_FRAME2) + { + if (!m_queued.empty()) { - // renderer may want to keep the frame for postprocessing - if (!m_pRenderer->NeedBufferForRef(*it) || !m_bRenderGUI) + double timestamp = GetPresentTime(); + SPresent& m = m_Queue[m_presentsource]; + SPresent& q = m_Queue[m_queued.front()]; + if(timestamp > m.timestamp + (q.timestamp - m.timestamp) * 0.5) { - m_pRenderer->ReleaseBuffer(*it); - m_overlays.Release(*it); - m_free.push_back(*it); - it = m_discard.erase(it); + m_presentstep = PRESENT_READY; + m_presentevent.notifyAll(); } - else - ++it; } + } - m_bRenderGUI = true; + if (m_presentstep == PRESENT_READY) + PrepareNextRender(); + + if(m_presentstep == PRESENT_FLIP) + { + m_pRenderer->FlipPage(m_presentsource); + m_presentstep = PRESENT_FRAME; + m_presentevent.notifyAll(); } + + /* release all previous */ + for (std::deque<int>::iterator it = m_discard.begin(); it != m_discard.end(); ) + { + // renderer may want to keep the frame for postprocessing + if (!m_pRenderer->NeedBufferForRef(*it) || !m_bRenderGUI) + { + m_pRenderer->ReleaseBuffer(*it); + m_overlays.Release(*it); + m_free.push_back(*it); + it = m_discard.erase(it); + } + else + ++it; + } + + m_bRenderGUI = true; } void CXBMCRenderManager::FrameFinish() @@ -437,8 +538,14 @@ void CXBMCRenderManager::FrameFinish() } } -unsigned int CXBMCRenderManager::PreInit() +void CXBMCRenderManager::PreInit() { + if (!g_application.IsCurrentThread()) + { + CLog::Log(LOGERROR, "CXBMCRenderManager::UnInit - not called from render thread"); + return; + } + CRetakeLock<CExclusiveLock> lock(m_sharedSection); m_presentcorr = 0.0; @@ -446,44 +553,35 @@ unsigned int CXBMCRenderManager::PreInit() m_errorindex = 0; memset(m_errorbuff, 0, sizeof(m_errorbuff)); - m_bIsStarted = false; if (!m_pRenderer) { -#if defined(HAS_GL) - m_pRenderer = new CLinuxRendererGL(); -#elif defined(HAS_MMAL) - m_pRenderer = new CMMALRenderer(); -#elif HAS_GLES == 2 - m_pRenderer = new CLinuxRendererGLES(); -#elif defined(HAS_DX) - m_pRenderer = new CWinRenderer(); -#elif defined(HAS_SDL) - m_pRenderer = new CLinuxRenderer(); -#endif + m_format = RENDER_FMT_NONE; + CreateRenderer(); } UpdateDisplayLatency(); m_QueueSize = 2; m_QueueSkip = 0; - - return m_pRenderer->PreInit(); } void CXBMCRenderManager::UnInit() { - CRetakeLock<CExclusiveLock> lock(m_sharedSection); + if (!g_application.IsCurrentThread()) + { + CLog::Log(LOGERROR, "CXBMCRenderManager::UnInit - not called from render thread"); + return; + } - m_bIsStarted = false; + CRetakeLock<CExclusiveLock> lock(m_sharedSection); m_overlays.Flush(); g_fontManager.Unload("__subtitle__"); g_fontManager.Unload("__subtitleborder__"); - // free renderer resources. - // TODO: we may also want to release the renderer here. - if (m_pRenderer) - m_pRenderer->UnInit(); + DeleteRenderer(); + + m_renderState = STATE_UNCONFIGURED; } bool CXBMCRenderManager::Flush() @@ -496,9 +594,13 @@ bool CXBMCRenderManager::Flush() CLog::Log(LOGDEBUG, "%s - flushing renderer", __FUNCTION__); CRetakeLock<CExclusiveLock> lock(m_sharedSection); - m_pRenderer->Flush(); - m_overlays.Flush(); - m_flushEvent.Set(); + + if (m_pRenderer) + { + m_pRenderer->Flush(); + m_overlays.Flush(); + m_flushEvent.Set(); + } } else { @@ -513,6 +615,7 @@ bool CXBMCRenderManager::Flush() return true; } + CSingleLock lock(m_presentlock); m_queued.clear(); m_discard.clear(); m_free.clear(); @@ -522,6 +625,56 @@ bool CXBMCRenderManager::Flush() return true; } +void CXBMCRenderManager::CreateRenderer() +{ + if (!m_pRenderer) + { +#if defined(HAS_MMAL) + m_pRenderer = new CMMALRenderer(); +#elif HAS_GLES == 2 + m_pRenderer = new CLinuxRendererGLES(); +#elif defined(HAS_DX) + m_pRenderer = new CWinRenderer(); +#endif +#if defined(HAS_GL) + if (m_format == RENDER_FMT_VAAPI || m_format == RENDER_FMT_VAAPINV12) + { +#if defined(HAVE_LIBVA) + m_pRenderer = new CRendererVAAPI; +#endif + } + else if (m_format == RENDER_FMT_VDPAU || m_format == RENDER_FMT_VDPAU_420) + { +#if defined(HAVE_LIBVDPAU) + m_pRenderer = new CRendererVDPAU; +#endif + } + else if (m_format == RENDER_FMT_CVBREF) + { +#if defined(TARGET_DARWIN_OSX) + m_pRenderer = new CRendererVDA; +#endif + } + else if (m_format != RENDER_FMT_NONE) + { + m_pRenderer = new CLinuxRendererGL; + } +#endif + if (m_pRenderer) + m_pRenderer->PreInit(); + } +} + +void CXBMCRenderManager::DeleteRenderer() +{ + CLog::Log(LOGDEBUG, "%s - deleting renderer", __FUNCTION__); + + if (m_pRenderer) + { + delete m_pRenderer; + m_pRenderer = NULL; + } +} void CXBMCRenderManager::SetupScreenshot() { @@ -756,13 +909,6 @@ void CXBMCRenderManager::FlipPage(volatile bool& bStop, double timestamp /* = 0L } } -void CXBMCRenderManager::Reset() -{ - CSharedLock lock(m_sharedSection); - if (m_pRenderer) - m_pRenderer->Reset(); -} - RESOLUTION CXBMCRenderManager::GetResolution() { CSharedLock lock(m_sharedSection); @@ -803,6 +949,9 @@ void CXBMCRenderManager::Render(bool clear, DWORD flags, DWORD alpha, bool gui) { CSharedLock lock(m_sharedSection); + if (m_renderState != STATE_CONFIGURED) + return; + if (!gui && m_pRenderer->IsGuiLayer()) return; @@ -911,10 +1060,6 @@ void CXBMCRenderManager::PresentBlend(bool clear, DWORD flags, DWORD alpha) void CXBMCRenderManager::Recover() { -#if defined(HAS_GL) && !defined(TARGET_DARWIN) - glFlush(); // attempt to have gpu done with pixmap and vdpau -#endif - UpdateDisplayLatency(); } @@ -949,8 +1094,8 @@ CRenderInfo CXBMCRenderManager::GetRenderInfo() CRenderInfo info; if (!m_pRenderer) { - CLog::Log(LOGERROR, "%s - renderer is NULL", __FUNCTION__); - return CRenderInfo(); + info.max_buffer_size = NUM_BUFFERS; + return info;; } return m_pRenderer->GetRenderInfo(); } @@ -997,16 +1142,12 @@ int CXBMCRenderManager::AddVideoPicture(DVDVideoPicture& pic) || pic.format == RENDER_FMT_OMXEGL || pic.format == RENDER_FMT_CVBREF || pic.format == RENDER_FMT_VAAPI + || pic.format == RENDER_FMT_VAAPINV12 || pic.format == RENDER_FMT_EGLIMG || pic.format == RENDER_FMT_MEDIACODEC || pic.format == RENDER_FMT_IMXMAP || pic.format == RENDER_FMT_MMAL) m_pRenderer->AddVideoPictureHW(pic, index); - else if(pic.format == RENDER_FMT_VAAPINV12) - { - m_pRenderer->AddVideoPictureHW(pic, index); - CDVDCodecUtils::CopyNV12Picture(&image, &pic.vaapi->DVDPic); - } m_pRenderer->ReleaseImage(index, false); @@ -1071,7 +1212,7 @@ EINTERLACEMETHOD CXBMCRenderManager::AutoInterlaceMethodInternal(EINTERLACEMETHO int CXBMCRenderManager::WaitForBuffer(volatile bool& bStop, int timeout) { - CSingleLock lock2(m_presentlock); + CSingleLock lock(m_presentlock); // check if gui is active and discard buffer if not // this keeps videoplayer going @@ -1092,7 +1233,7 @@ int CXBMCRenderManager::WaitForBuffer(volatile bool& bStop, int timeout) if (sleeptime < 0) sleeptime = 0; sleeptime = std::min(sleeptime, 20); - m_presentevent.wait(lock2, sleeptime); + m_presentevent.wait(lock, sleeptime); DiscardBuffer(); return 0; } @@ -1100,7 +1241,7 @@ int CXBMCRenderManager::WaitForBuffer(volatile bool& bStop, int timeout) XbmcThreads::EndTime endtime(timeout); while(m_free.empty()) { - m_presentevent.wait(lock2, std::min(50, timeout)); + m_presentevent.wait(lock, std::min(50, timeout)); if(endtime.IsTimePast() || bStop) { if (timeout != 0 && !bStop) diff --git a/xbmc/cores/VideoRenderers/RenderManager.h b/xbmc/cores/VideoRenderers/RenderManager.h index 5d0c3a4c72..e0ec3e6fbf 100644 --- a/xbmc/cores/VideoRenderers/RenderManager.h +++ b/xbmc/cores/VideoRenderers/RenderManager.h @@ -53,7 +53,7 @@ public: CXBMCRenderManager(); ~CXBMCRenderManager(); - // Functions called from the GUI + // Functions called from render thread void GetVideoRect(CRect &source, CRect &dest, CRect &view); float GetAspectRatio(); void Update(); @@ -64,31 +64,43 @@ public: void Render(bool clear, DWORD flags = 0, DWORD alpha = 255, bool gui = true); bool IsGuiLayer(); bool IsVideoLayer(); - void SetupScreenshot(); + RESOLUTION GetResolution(); + void UpdateResolution(); + void SetViewMode(int iViewMode); + void Recover(); // called after resolution switch if something special is needed + void PreInit(); + void UnInit(); + bool Flush(); + bool IsConfigured() const; + void SetupScreenshot(); CRenderCapture* AllocRenderCapture(); void ReleaseRenderCapture(CRenderCapture* capture); void Capture(CRenderCapture *capture, unsigned int width, unsigned int height, int flags); void ManageCaptures(); - void SetViewMode(int iViewMode); + // Functions called from GUI + bool Supports(ERENDERFEATURE feature); + bool Supports(EDEINTERLACEMODE method); + bool Supports(EINTERLACEMETHOD method); + bool Supports(ESCALINGMETHOD method); + EINTERLACEMETHOD AutoInterlaceMethod(EINTERLACEMETHOD mInt); + + static float GetMaximumFPS(); + double GetDisplayLatency() { return m_displayLatency; } + int GetSkippedFrames() { return m_QueueSkip; } + std::string GetVSyncState(); // Functions called from mplayer /** * Called by video player to configure renderer - * @param width width of decoded frame - * @param height height of decoded frame - * @param d_width displayed width of frame (aspect ratio) - * @param d_height displayed height of frame + * @param picture * @param fps frames per second of video * @param flags see RenderFlags.h - * @param format see RenderFormats.h - * @param extended_format used by DXVA * @param orientation * @param numbers of kept buffer references */ - bool Configure(unsigned int width, unsigned int height, unsigned int d_width, unsigned int d_height, float fps, unsigned flags, ERenderFormat format, unsigned extended_format, unsigned int orientation, int buffers = 0); - bool IsConfigured() const; + bool Configure(DVDVideoPicture& picture, float fps, unsigned flags, unsigned int orientation, int buffers = 0); int AddVideoPicture(DVDVideoPicture& picture); @@ -107,9 +119,6 @@ public: * @param sync signals frame, top, or bottom field */ void FlipPage(volatile bool& bStop, double timestamp = 0.0, double pts = 0.0, int source = -1, EFIELDSYNC sync = FS_NONE); - unsigned int PreInit(); - void UnInit(); - bool Flush(); void AddOverlay(CDVDOverlay* o, double pts) { @@ -127,41 +136,9 @@ public: m_overlays.AddCleanup(o); } - void Reset(); - - RESOLUTION GetResolution(); - - static float GetMaximumFPS(); - inline bool IsStarted() { return m_bIsStarted;} - double GetDisplayLatency() { return m_displayLatency; } - int GetSkippedFrames() { return m_QueueSkip; } - - bool Supports(ERENDERFEATURE feature); - bool Supports(EDEINTERLACEMODE method); - bool Supports(EINTERLACEMETHOD method); - bool Supports(ESCALINGMETHOD method); - - EINTERLACEMETHOD AutoInterlaceMethod(EINTERLACEMETHOD mInt); - - static double GetPresentTime(); - void WaitPresentTime(double presenttime); - - std::string GetVSyncState(); - - void UpdateResolution(); - - CBaseRenderer *m_pRenderer; - // Get renderer info, can be called before configure CRenderInfo GetRenderInfo(); - void Recover(); // called after resolution switch if something special is needed - - CSharedSection& GetSection() { return m_sharedSection; }; - - void RegisterRenderUpdateCallBack(const void *ctx, RenderUpdateCallBackFn fn); - void RegisterRenderFeaturesCallBack(const void *ctx, RenderFeaturesCallBackFn fn); - /** * If player uses buffering it has to wait for a buffer before it calls * AddVideoPicture and AddOverlay. It waits for max 50 ms before it returns -1 @@ -183,6 +160,10 @@ public: */ void DiscardBuffer(); + // TODO: trash those + void RegisterRenderUpdateCallBack(const void *ctx, RenderUpdateCallBackFn fn); + void RegisterRenderFeaturesCallBack(const void *ctx, RenderFeaturesCallBackFn fn); + protected: void PresentSingle(bool clear, DWORD flags, DWORD alpha); @@ -190,17 +171,22 @@ protected: void PresentBlend(bool clear, DWORD flags, DWORD alpha); void PrepareNextRender(); + static double GetPresentTime(); + void WaitPresentTime(double presenttime); EINTERLACEMETHOD AutoInterlaceMethodInternal(EINTERLACEMETHOD mInt); + bool Configure(); + void CreateRenderer(); + void DeleteRenderer(); + CBaseRenderer *m_pRenderer; + OVERLAY::CRenderer m_overlays; CSharedSection m_sharedSection; - - bool m_bIsStarted; bool m_bReconfigured; bool m_bRenderGUI; int m_waitForBufferCount; - int m_rendermethod; + bool m_renderedOverlay; enum EPRESENTSTEP { @@ -219,6 +205,15 @@ protected: PRESENT_METHOD_BOB, }; + enum ERENDERSTATE + { + STATE_UNCONFIGURED = 0, + STATE_CONFIGURING, + STATE_CONFIGURED, + }; + ERENDERSTATE m_renderState; + CEvent m_stateEvent; + double m_displayLatency; void UpdateDisplayLatency(); @@ -238,6 +233,12 @@ protected: std::deque<int> m_discard; ERenderFormat m_format; + unsigned int m_width, m_height, m_dwidth, m_dheight; + unsigned int m_flags; + float m_fps; + unsigned int m_extended_format; + unsigned int m_orientation; + int m_NumberBuffers; double m_sleeptime; double m_presentpts; @@ -252,9 +253,6 @@ protected: CEvent m_flushEvent; double m_clock_framefinish; - OVERLAY::CRenderer m_overlays; - bool m_renderedOverlay; - void RenderCapture(CRenderCapture* capture); void RemoveCapture(CRenderCapture* capture); CCriticalSection m_captCritSect; diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/VAAPI.cpp b/xbmc/cores/dvdplayer/DVDCodecs/Video/VAAPI.cpp index f8050b646a..24ccfd03ff 100644 --- a/xbmc/cores/dvdplayer/DVDCodecs/Video/VAAPI.cpp +++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/VAAPI.cpp @@ -1098,7 +1098,6 @@ bool CDecoder::ConfigVAAPI() return false; } - m_hwContext.config_id = m_vaapiConfig.configId; m_hwContext.context_id = m_vaapiConfig.contextId; m_hwContext.display = m_vaapiConfig.dpy; diff --git a/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp b/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp index 379c54153c..4ab81af84c 100644 --- a/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp +++ b/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp @@ -152,7 +152,6 @@ CDVDPlayerVideo::CDVDPlayerVideo( CDVDClock* pClock m_iFrameRateLength = 0; m_bFpsInvalid = false; m_bAllowFullscreen = false; - memset(&m_output, 0, sizeof(m_output)); } CDVDPlayerVideo::~CDVDPlayerVideo() @@ -908,34 +907,6 @@ void CDVDPlayerVideo::ProcessOverlays(DVDVideoPicture* pSource, double pts) } #endif -static std::string GetRenderFormatName(ERenderFormat format) -{ - switch(format) - { - case RENDER_FMT_YUV420P: return "YV12"; - case RENDER_FMT_YUV420P16: return "YV12P16"; - case RENDER_FMT_YUV420P10: return "YV12P10"; - case RENDER_FMT_NV12: return "NV12"; - case RENDER_FMT_UYVY422: return "UYVY"; - case RENDER_FMT_YUYV422: return "YUY2"; - case RENDER_FMT_VDPAU: return "VDPAU"; - case RENDER_FMT_VDPAU_420: return "VDPAU_420"; - case RENDER_FMT_DXVA: return "DXVA"; - case RENDER_FMT_VAAPI: return "VAAPI"; - case RENDER_FMT_VAAPINV12: return "VAAPI_NV12"; - case RENDER_FMT_OMXEGL: return "OMXEGL"; - case RENDER_FMT_CVBREF: return "BGRA"; - case RENDER_FMT_EGLIMG: return "EGLIMG"; - case RENDER_FMT_BYPASS: return "BYPASS"; - case RENDER_FMT_MEDIACODEC:return "MEDIACODEC"; - case RENDER_FMT_MEDIACODECSURFACE:return "MEDIACODECSURFACE"; - case RENDER_FMT_IMXMAP: return "IMXMAP"; - case RENDER_FMT_MMAL: return "MMAL"; - case RENDER_FMT_NONE: return "NONE"; - } - return "UNKNOWN"; -} - std::string CDVDPlayerVideo::GetStereoMode() { std::string stereo_mode; @@ -965,97 +936,40 @@ int CDVDPlayerVideo::OutputPicture(const DVDVideoPicture* src, double pts) /* figure out steremode expected based on user settings and hints */ unsigned int stereo_flags = GetStereoModeFlags(GetStereoMode()); -#ifdef HAS_VIDEO_PLAYBACK double config_framerate = m_bFpsInvalid ? 0.0 : m_fFrameRate; - double render_framerate = g_graphicsContext.GetFPS(); - if (CSettings::GetInstance().GetInt(CSettings::SETTING_VIDEOPLAYER_ADJUSTREFRESHRATE) == ADJUST_REFRESHRATE_OFF) - render_framerate = config_framerate; - bool changerefresh = !m_bFpsInvalid && - (m_output.framerate == 0.0 || fmod(m_output.framerate, config_framerate) != 0.0) && - (render_framerate != config_framerate); - - /* check so that our format or aspect has changed. if it has, reconfigure renderer */ - if (!g_renderManager.IsConfigured() - || ( m_output.width != pPicture->iWidth ) - || ( m_output.height != pPicture->iHeight ) - || ( m_output.dwidth != pPicture->iDisplayWidth ) - || ( m_output.dheight != pPicture->iDisplayHeight ) - || changerefresh - || ( m_output.color_format != (unsigned int)pPicture->format ) - || ( m_output.extended_format != pPicture->extended_format ) - || ( m_output.color_matrix != pPicture->color_matrix && pPicture->color_matrix != 0 ) // don't reconfigure on unspecified - || ( m_output.chroma_position != pPicture->chroma_position && pPicture->chroma_position != 0 ) - || ( m_output.color_primaries != pPicture->color_primaries && pPicture->color_primaries != 0 ) - || ( m_output.color_transfer != pPicture->color_transfer && pPicture->color_transfer != 0 ) - || ( m_output.color_range != pPicture->color_range ) - || ( m_output.stereo_flags != stereo_flags)) - { - CLog::Log(LOGNOTICE, " fps: %f, pwidth: %i, pheight: %i, dwidth: %i, dheight: %i" - , config_framerate - , pPicture->iWidth - , pPicture->iHeight - , pPicture->iDisplayWidth - , pPicture->iDisplayHeight); - - unsigned flags = 0; - if(pPicture->color_range == 1) - flags |= CONF_FLAGS_YUV_FULLRANGE; - flags |= GetFlagsChromaPosition(pPicture->chroma_position) - | GetFlagsColorMatrix(pPicture->color_matrix, pPicture->iWidth, pPicture->iHeight) - | GetFlagsColorPrimaries(pPicture->color_primaries) - | GetFlagsColorTransfer(pPicture->color_transfer); + unsigned flags = 0; + if(pPicture->color_range == 1) + flags |= CONF_FLAGS_YUV_FULLRANGE; - std::string formatstr = GetRenderFormatName(pPicture->format); - - if(m_bAllowFullscreen) - { - flags |= CONF_FLAGS_FULLSCREEN; - m_bAllowFullscreen = false; // only allow on first configure - } + flags |= GetFlagsChromaPosition(pPicture->chroma_position) + | GetFlagsColorMatrix(pPicture->color_matrix, pPicture->iWidth, pPicture->iHeight) + | GetFlagsColorPrimaries(pPicture->color_primaries) + | GetFlagsColorTransfer(pPicture->color_transfer); - flags |= stereo_flags; - - CLog::Log(LOGDEBUG,"%s - change configuration. %dx%d. framerate: %4.2f. format: %s",__FUNCTION__,pPicture->iWidth, pPicture->iHeight, config_framerate, formatstr.c_str()); - if(!g_renderManager.Configure(pPicture->iWidth - , pPicture->iHeight - , pPicture->iDisplayWidth - , pPicture->iDisplayHeight - , config_framerate - , flags - , pPicture->format - , pPicture->extended_format - , m_hints.orientation - , m_pVideoCodec->GetAllowedReferences())) - { - CLog::Log(LOGERROR, "%s - failed to configure renderer", __FUNCTION__); - return EOS_ABORT; - } - m_output.width = pPicture->iWidth; - m_output.height = pPicture->iHeight; - m_output.dwidth = pPicture->iDisplayWidth; - m_output.dheight = pPicture->iDisplayHeight; - m_output.framerate = config_framerate; - m_output.color_format = pPicture->format; - m_output.extended_format = pPicture->extended_format; - m_output.color_matrix = pPicture->color_matrix; - m_output.chroma_position = pPicture->chroma_position; - m_output.color_primaries = pPicture->color_primaries; - m_output.color_transfer = pPicture->color_transfer; - m_output.color_range = pPicture->color_range; - m_output.stereo_flags = stereo_flags; + if(m_bAllowFullscreen) + { + flags |= CONF_FLAGS_FULLSCREEN; + m_bAllowFullscreen = false; // only allow on first configure } - int result = 0; + flags |= stereo_flags; - if (!g_renderManager.IsStarted()) { - CLog::Log(LOGERROR, "%s - renderer not started", __FUNCTION__); + if(!g_renderManager.Configure(picture, + config_framerate, + flags, + m_hints.orientation, + m_pVideoCodec->GetAllowedReferences())) + { + CLog::Log(LOGERROR, "%s - failed to configure renderer", __FUNCTION__); return EOS_ABORT; } + int result = 0; + //correct any pattern in the timestamps - if (m_output.color_format != RENDER_FMT_BYPASS) + if (picture.format != RENDER_FMT_BYPASS) { m_pullupCorrection.Add(pts); pts += m_pullupCorrection.GetCorrection(); @@ -1076,7 +990,7 @@ int CDVDPlayerVideo::OutputPicture(const DVDVideoPicture* src, double pts) pts -= DVD_TIME_BASE * interval; } - if (m_output.color_format != RENDER_FMT_BYPASS) + if (picture.format != RENDER_FMT_BYPASS) { // Correct pts by user set delay and rendering delay pts += m_iVideoDelay - DVD_SEC_TO_TIME(g_renderManager.GetDisplayLatency()); @@ -1210,10 +1124,6 @@ int CDVDPlayerVideo::OutputPicture(const DVDVideoPicture* src, double pts) g_renderManager.FlipPage(CThread::m_bStop, (iCurrentClock + iSleepTime) / DVD_TIME_BASE, pts_org, -1, mDisplayField); return result; -#else - // no video renderer, let's mark it as dropped - return EOS_DROPPED; -#endif } std::string CDVDPlayerVideo::GetPlayerInfo() diff --git a/xbmc/cores/dvdplayer/DVDPlayerVideo.h b/xbmc/cores/dvdplayer/DVDPlayerVideo.h index 3e0d065ca2..b1caceea70 100644 --- a/xbmc/cores/dvdplayer/DVDPlayerVideo.h +++ b/xbmc/cores/dvdplayer/DVDPlayerVideo.h @@ -161,23 +161,6 @@ protected: bool m_bFpsInvalid; // needed to ignore fps (e.g. dvd stills) - struct SOutputConfiguration - { - unsigned int width; - unsigned int height; - unsigned int dwidth; - unsigned int dheight; - unsigned int color_format; - unsigned int extended_format; - unsigned int color_matrix : 4; - unsigned int color_range : 1; - unsigned int chroma_position; - unsigned int color_primaries; - unsigned int color_transfer; - unsigned int stereo_flags; - double framerate; - } m_output; //holds currently configured output - bool m_bAllowFullscreen; bool m_bRenderSubs; diff --git a/xbmc/guilib/GUIVideoControl.cpp b/xbmc/guilib/GUIVideoControl.cpp index 27efb6401f..a844725ebb 100644 --- a/xbmc/guilib/GUIVideoControl.cpp +++ b/xbmc/guilib/GUIVideoControl.cpp @@ -55,7 +55,7 @@ void CGUIVideoControl::Render() // don't render if we aren't playing video, or if the renderer isn't started // (otherwise the lock we have from CApplication::Render() may clash with the startup // locks in the RenderManager.) - if (g_application.m_pPlayer->IsPlayingVideo() && g_renderManager.IsStarted()) + if (g_application.m_pPlayer->IsPlayingVideo() && g_renderManager.IsConfigured()) { #else if (g_application.m_pPlayer->IsPlayingVideo()) @@ -101,7 +101,7 @@ void CGUIVideoControl::Render() void CGUIVideoControl::RenderEx() { #ifdef HAS_VIDEO_PLAYBACK - if (g_application.m_pPlayer->IsPlayingVideo() && g_renderManager.IsStarted()) + if (g_application.m_pPlayer->IsPlayingVideo() && g_renderManager.IsConfigured()) g_renderManager.Render(false, 0, 255, false); g_renderManager.FrameFinish(); #endif |