From 12cfeb37a73a3776e350f54a56e92fdbf89bc337 Mon Sep 17 00:00:00 2001 From: Stephan Raue Date: Sun, 10 Mar 2013 18:06:11 +0100 Subject: [PATCH] xbmc: fix XVBA/VDPAU patch Signed-off-by: Stephan Raue --- .../xbmc-995.01-xvba_support-1f1e576.patch | 20535 ++++++---------- 1 file changed, 7611 insertions(+), 12924 deletions(-) diff --git a/packages/mediacenter/xbmc/patches/xbmc-995.01-xvba_support-1f1e576.patch b/packages/mediacenter/xbmc/patches/xbmc-995.01-xvba_support-1f1e576.patch index 45a76f534a..704449ffe0 100644 --- a/packages/mediacenter/xbmc/patches/xbmc-995.01-xvba_support-1f1e576.patch +++ b/packages/mediacenter/xbmc/patches/xbmc-995.01-xvba_support-1f1e576.patch @@ -1,1367 +1,1045 @@ -From 7a1298aa773b8a098ca2589dcccebdda46b4995f Mon Sep 17 00:00:00 2001 -From: xbmc -Date: Mon, 28 May 2012 10:03:31 +0200 -Subject: [PATCH 01/88] VideoRenerers: add buffering - ---- - xbmc/Application.cpp | 3 + - xbmc/cores/IPlayer.h | 2 + - xbmc/cores/VideoRenderers/BaseRenderer.h | 5 +- - xbmc/cores/VideoRenderers/LinuxRendererGL.cpp | 41 ++-- - xbmc/cores/VideoRenderers/LinuxRendererGL.h | 13 +- - xbmc/cores/VideoRenderers/LinuxRendererGLES.cpp | 8 +- - xbmc/cores/VideoRenderers/LinuxRendererGLES.h | 4 +- - xbmc/cores/VideoRenderers/OverlayRenderer.cpp | 24 +- - xbmc/cores/VideoRenderers/OverlayRenderer.h | 9 +- - xbmc/cores/VideoRenderers/RenderManager.cpp | 294 +++++++++++++++++++---- - xbmc/cores/VideoRenderers/RenderManager.h | 63 ++++- - xbmc/cores/VideoRenderers/WinRenderer.cpp | 8 +- - xbmc/cores/VideoRenderers/WinRenderer.h | 2 +- - xbmc/cores/dvdplayer/DVDPlayer.cpp | 5 + - xbmc/cores/dvdplayer/DVDPlayer.h | 2 + - xbmc/cores/dvdplayer/DVDPlayerVideo.cpp | 34 ++- - 16 files changed, 417 insertions(+), 100 deletions(-) - -diff --git a/xbmc/Application.cpp b/xbmc/Application.cpp -index 46b2fde..efb3ac0 100644 ---- a/xbmc/Application.cpp -+++ b/xbmc/Application.cpp -@@ -2371,7 +2371,10 @@ void CApplication::Render() - m_lastFrameTime = XbmcThreads::SystemClockMillis(); - - if (flip) -+ { - g_graphicsContext.Flip(dirtyRegions); -+ g_renderManager.NotifyDisplayFlip(); -+ } - CTimeUtils::UpdateFrameTime(flip); - - g_TextureManager.FreeUnusedTextures(); -diff --git a/xbmc/cores/IPlayer.h b/xbmc/cores/IPlayer.h -index f2aa227..eb654ec 100644 ---- a/xbmc/cores/IPlayer.h -+++ b/xbmc/cores/IPlayer.h -@@ -229,6 +229,8 @@ class IPlayer - */ - virtual void GetSubtitleCapabilities(std::vector &subCaps) { subCaps.assign(1,IPC_SUBS_ALL); }; - -+ virtual double GetClock(double& absolute, bool interpolated = true) {return 0; }; -+ - protected: - IPlayerCallback& m_callback; - }; -diff --git a/xbmc/cores/VideoRenderers/BaseRenderer.h b/xbmc/cores/VideoRenderers/BaseRenderer.h -index 81d21d8..aa1e4ae 100644 ---- a/xbmc/cores/VideoRenderers/BaseRenderer.h -+++ b/xbmc/cores/VideoRenderers/BaseRenderer.h -@@ -80,10 +80,13 @@ class CBaseRenderer - void GetVideoRect(CRect &source, CRect &dest); - float GetAspectRatio() const; - -- virtual bool AddVideoPicture(DVDVideoPicture* picture) { return false; } -+ virtual bool AddVideoPicture(DVDVideoPicture* picture, int index) { return false; } - virtual void Flush() {}; - - virtual unsigned int GetProcessorSize() { return 0; } -+ virtual unsigned int GetMaxBufferSize() { return 0; } -+ virtual void SetBufferSize(int numBuffers) { } -+ virtual void ReleaseBuffer(int idx) { } - - virtual bool Supports(ERENDERFEATURE feature) { return false; } - -diff --git a/xbmc/cores/VideoRenderers/LinuxRendererGL.cpp b/xbmc/cores/VideoRenderers/LinuxRendererGL.cpp -index 1cf52d3..b32a7ea 100644 ---- a/xbmc/cores/VideoRenderers/LinuxRendererGL.cpp -+++ b/xbmc/cores/VideoRenderers/LinuxRendererGL.cpp -@@ -235,14 +235,6 @@ bool CLinuxRendererGL::ValidateRenderer() - return true; - } - -- --void CLinuxRendererGL::ManageTextures() --{ -- m_NumYV12Buffers = 2; -- //m_iYV12RenderBuffer = 0; -- return; --} -- - bool CLinuxRendererGL::ValidateRenderTarget() - { - if (!m_bValidated) -@@ -603,13 +595,28 @@ void CLinuxRendererGL::Flush() - glFinish(); - m_bValidated = false; - m_fbo.fbo.Cleanup(); -+ m_iYV12RenderBuffer = 0; -+} -+ -+void CLinuxRendererGL::ReleaseBuffer(int idx) -+{ -+ YUVBUFFER &buf = m_buffers[idx]; -+#ifdef HAVE_LIBVDPAU -+ SAFE_RELEASE(buf.vdpau); -+#endif -+#ifdef HAVE_LIBVA -+ buf.vaapi.surface.reset(); -+#endif -+#ifdef TARGET_DARWIN -+ if (buf.cvBufferRef) -+ CVBufferRelease(buf.cvBufferRef); -+#endif - } - - void CLinuxRendererGL::Update(bool bPauseDrawing) - { - if (!m_bConfigured) return; - ManageDisplay(); -- ManageTextures(); - } - - void CLinuxRendererGL::RenderUpdate(bool clear, DWORD flags, DWORD alpha) -@@ -625,7 +632,6 @@ void CLinuxRendererGL::RenderUpdate(bool clear, DWORD flags, DWORD alpha) - } - - ManageDisplay(); -- ManageTextures(); - - g_graphicsContext.BeginPaint(); - -@@ -782,7 +788,6 @@ unsigned int CLinuxRendererGL::PreInit() - m_resolution = RES_DESKTOP; - - m_iYV12RenderBuffer = 0; -- m_NumYV12Buffers = 2; - - m_formats.push_back(RENDER_FMT_YUV420P); - GLint size; -@@ -2465,7 +2470,7 @@ void CLinuxRendererGL::UploadVAAPITexture(int index) - || status == VA_STATUS_ERROR_INVALID_DISPLAY) - { - va.display->lost(true); -- for(int i = 0; i < NUM_BUFFERS; i++) -+ for(int i = 0; i < m_NumYV12Buffers; i++) - { - m_buffers[i].vaapi.display.reset(); - m_buffers[i].vaapi.surface.reset(); -@@ -3412,26 +3417,26 @@ void CLinuxRendererGL::UnBindPbo(YUVBUFFER& buff) - } - - #ifdef HAVE_LIBVDPAU --void CLinuxRendererGL::AddProcessor(CVDPAU* vdpau) -+void CLinuxRendererGL::AddProcessor(CVDPAU* vdpau, int index) - { -- YUVBUFFER &buf = m_buffers[NextYV12Texture()]; -+ YUVBUFFER &buf = m_buffers[index]; - SAFE_RELEASE(buf.vdpau); - buf.vdpau = (CVDPAU*)vdpau->Acquire(); - } - #endif - - #ifdef HAVE_LIBVA --void CLinuxRendererGL::AddProcessor(VAAPI::CHolder& holder) -+void CLinuxRendererGL::AddProcessor(VAAPI::CHolder& holder, int index) - { -- YUVBUFFER &buf = m_buffers[NextYV12Texture()]; -+ YUVBUFFER &buf = m_buffers[index]; - buf.vaapi.surface = holder.surface; - } - #endif - - #ifdef TARGET_DARWIN --void CLinuxRendererGL::AddProcessor(struct __CVBuffer *cvBufferRef) -+void CLinuxRendererGL::AddProcessor(struct __CVBuffer *cvBufferRef, int index) - { -- YUVBUFFER &buf = m_buffers[NextYV12Texture()]; -+ YUVBUFFER &buf = m_buffers[index]; - if (buf.cvBufferRef) - CVBufferRelease(buf.cvBufferRef); - buf.cvBufferRef = cvBufferRef; -diff --git a/xbmc/cores/VideoRenderers/LinuxRendererGL.h b/xbmc/cores/VideoRenderers/LinuxRendererGL.h -index acebfe0..7c9fcae 100644 ---- a/xbmc/cores/VideoRenderers/LinuxRendererGL.h -+++ b/xbmc/cores/VideoRenderers/LinuxRendererGL.h -@@ -44,7 +44,7 @@ - namespace Shaders { class BaseVideoFilterShader; } - namespace VAAPI { struct CHolder; } - --#define NUM_BUFFERS 3 -+#define NUM_BUFFERS 10 - - - #undef ALIGN -@@ -138,15 +138,19 @@ class CLinuxRendererGL : public CBaseRenderer - 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 unsigned int GetMaxBufferSize() { return NUM_BUFFERS; } -+ virtual unsigned int GetProcessorSize() { return m_NumYV12Buffers; } - - #ifdef HAVE_LIBVDPAU -- virtual void AddProcessor(CVDPAU* vdpau); -+ virtual void AddProcessor(CVDPAU* vdpau, int index); - #endif - #ifdef HAVE_LIBVA -- virtual void AddProcessor(VAAPI::CHolder& holder); -+ virtual void AddProcessor(VAAPI::CHolder& holder, int index); - #endif - #ifdef TARGET_DARWIN -- virtual void AddProcessor(struct __CVBuffer *cvBufferRef); -+ virtual void AddProcessor(struct __CVBuffer *cvBufferRef, int index); - #endif - - virtual void RenderUpdate(bool clear, DWORD flags = 0, DWORD alpha = 255); -@@ -168,7 +172,6 @@ class CLinuxRendererGL : public CBaseRenderer - void DrawBlackBars(); - - bool ValidateRenderer(); -- virtual void ManageTextures(); - int NextYV12Texture(); - virtual bool ValidateRenderTarget(); - virtual void LoadShaders(int field=FIELD_FULL); -diff --git a/xbmc/cores/VideoRenderers/LinuxRendererGLES.cpp b/xbmc/cores/VideoRenderers/LinuxRendererGLES.cpp -index cb0939f..2a59e2b 100644 ---- a/xbmc/cores/VideoRenderers/LinuxRendererGLES.cpp -+++ b/xbmc/cores/VideoRenderers/LinuxRendererGLES.cpp -@@ -1982,16 +1982,16 @@ EINTERLACEMETHOD CLinuxRendererGLES::AutoInterlaceMethod() - } - - #ifdef HAVE_LIBOPENMAX --void CLinuxRendererGLES::AddProcessor(COpenMax* openMax, DVDVideoPicture *picture) -+void CLinuxRendererGLES::AddProcessor(COpenMax* openMax, DVDVideoPicture *picture, int index) - { -- YUVBUFFER &buf = m_buffers[NextYV12Texture()]; -+ YUVBUFFER &buf = m_buffers[index]; - buf.openMaxBuffer = picture->openMaxBuffer; - } - #endif - #ifdef HAVE_VIDEOTOOLBOXDECODER --void CLinuxRendererGLES::AddProcessor(struct __CVBuffer *cvBufferRef) -+void CLinuxRendererGLES::AddProcessor(struct __CVBuffer *cvBufferRef, int index) - { -- YUVBUFFER &buf = m_buffers[NextYV12Texture()]; -+ YUVBUFFER &buf = m_buffers[index]; - if (buf.cvBufferRef) - CVBufferRelease(buf.cvBufferRef); - buf.cvBufferRef = cvBufferRef; -diff --git a/xbmc/cores/VideoRenderers/LinuxRendererGLES.h b/xbmc/cores/VideoRenderers/LinuxRendererGLES.h -index 76b5437..c6b69db 100644 ---- a/xbmc/cores/VideoRenderers/LinuxRendererGLES.h -+++ b/xbmc/cores/VideoRenderers/LinuxRendererGLES.h -@@ -153,10 +153,10 @@ class CLinuxRendererGLES : public CBaseRenderer - virtual std::vector SupportedFormats() { return m_formats; } - - #ifdef HAVE_LIBOPENMAX -- virtual void AddProcessor(COpenMax* openMax, DVDVideoPicture *picture); -+ virtual void AddProcessor(COpenMax* openMax, DVDVideoPicture *picture, int index); - #endif - #ifdef HAVE_VIDEOTOOLBOXDECODER -- virtual void AddProcessor(struct __CVBuffer *cvBufferRef); -+ virtual void AddProcessor(struct __CVBuffer *cvBufferRef, int index); - #endif - - protected: -diff --git a/xbmc/cores/VideoRenderers/OverlayRenderer.cpp b/xbmc/cores/VideoRenderers/OverlayRenderer.cpp -index 19d2d7d..f7f74ce 100644 ---- a/xbmc/cores/VideoRenderers/OverlayRenderer.cpp -+++ b/xbmc/cores/VideoRenderers/OverlayRenderer.cpp -@@ -89,29 +89,32 @@ long COverlayMainThread::Release() - CRenderer::CRenderer() - { - m_render = 0; -- m_decode = (m_render + 1) % 2; - } - - CRenderer::~CRenderer() - { -- for(int i = 0; i < 2; i++) -+ for(int i = 0; i < 10; i++) - Release(m_buffers[i]); - } - --void CRenderer::AddOverlay(CDVDOverlay* o, double pts) -+void CRenderer::AddOverlay(CDVDOverlay* o, double pts, int index) - { - CSingleLock lock(m_section); - -+ m_decode = index; -+ - SElement e; - e.pts = pts; - e.overlay_dvd = o->Acquire(); - m_buffers[m_decode].push_back(e); - } - --void CRenderer::AddOverlay(COverlay* o, double pts) -+void CRenderer::AddOverlay(COverlay* o, double pts, int index) - { - CSingleLock lock(m_section); - -+ m_decode = index; -+ - SElement e; - e.pts = pts; - e.overlay = o->Acquire(); -@@ -151,20 +154,23 @@ void CRenderer::Flush() - { - CSingleLock lock(m_section); - -- for(int i = 0; i < 2; i++) -+ for(int i = 0; i < m_iNumBuffers; i++) - Release(m_buffers[i]); - -+ m_render = 0; - Release(m_cleanup); - } - - void CRenderer::Flip() - { - CSingleLock lock(m_section); -+ m_render = (m_render + 1) % m_iNumBuffers; -+} - -- m_render = m_decode; -- m_decode =(m_decode + 1) % 2; -- -- Release(m_buffers[m_decode]); -+void CRenderer::ReleaseBuffer(int idx) -+{ -+ CSingleLock lock(m_section); -+ Release(m_buffers[idx]); - } - - void CRenderer::Render() -diff --git a/xbmc/cores/VideoRenderers/OverlayRenderer.h b/xbmc/cores/VideoRenderers/OverlayRenderer.h -index d2175d8..0921fc5 100644 ---- a/xbmc/cores/VideoRenderers/OverlayRenderer.h -+++ b/xbmc/cores/VideoRenderers/OverlayRenderer.h -@@ -92,12 +92,14 @@ - CRenderer(); - ~CRenderer(); - -- void AddOverlay(CDVDOverlay* o, double pts); -- void AddOverlay(COverlay* o, double pts); -+ void AddOverlay(CDVDOverlay* o, double pts, int index); -+ void AddOverlay(COverlay* o, double pts, int index); - void AddCleanup(COverlay* o); - void Flip(); - void Render(); - void Flush(); -+ void SetNumBuffers(int numBuffers) { m_iNumBuffers = numBuffers; } -+ void ReleaseBuffer(int idx); - - protected: - -@@ -124,7 +126,8 @@ - void Release(SElementV& list); - - CCriticalSection m_section; -- SElementV m_buffers[2]; -+ SElementV m_buffers[10]; -+ int m_iNumBuffers; - int m_decode; - int m_render; - -diff --git a/xbmc/cores/VideoRenderers/RenderManager.cpp b/xbmc/cores/VideoRenderers/RenderManager.cpp -index d22287d..c13f83d 100644 ---- a/xbmc/cores/VideoRenderers/RenderManager.cpp -+++ b/xbmc/cores/VideoRenderers/RenderManager.cpp -@@ -28,6 +28,7 @@ - #include "utils/MathUtils.h" - #include "threads/SingleLock.h" - #include "utils/log.h" -+#include "utils/TimeUtils.h" - - #include "Application.h" - #include "ApplicationMessenger.h" -@@ -227,7 +228,7 @@ CStdString 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) -+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, bool buffering) - { - /* make sure any queued frame was fully presented */ - double timeout = m_presenttime + 0.1; -@@ -247,6 +248,9 @@ bool CXBMCRenderManager::Configure(unsigned int width, unsigned int height, unsi - return false; - } - -+ // set buffering -+ m_bCodecSupportsBuffering = buffering; -+ - bool result = m_pRenderer->Configure(width, height, d_width, d_height, fps, flags, format, extended_format, orientation); - if(result) - { -@@ -261,6 +265,7 @@ bool CXBMCRenderManager::Configure(unsigned int width, unsigned int height, unsi - m_bReconfigured = true; - m_presentstep = PRESENT_IDLE; - m_presentevent.Set(); -+ ResetRenderBuffer(); - } - - return result; -@@ -292,8 +297,12 @@ void CXBMCRenderManager::RenderUpdate(bool clear, DWORD flags, DWORD alpha) - if (!m_pRenderer) - return; - -+ if (m_presentstep == PRESENT_IDLE) -+ PrepareNextRender(); -+ - if(m_presentstep == PRESENT_FLIP) - { -+ FlipRenderBuffer(); - m_overlays.Flip(); - m_pRenderer->FlipPage(m_presentsource); - m_presentstep = PRESENT_FRAME; -@@ -338,6 +347,10 @@ unsigned int CXBMCRenderManager::PreInit() - - UpdateDisplayLatency(); - -+ m_bUseBuffering = false; -+ m_bCodecSupportsBuffering = true; -+ ResetRenderBuffer(); -+ - return m_pRenderer->PreInit(); - } - -@@ -366,7 +379,9 @@ bool CXBMCRenderManager::Flush() - - CRetakeLock lock(m_sharedSection); - m_pRenderer->Flush(); -+ m_overlays.Flush(); - m_flushEvent.Set(); -+ ResetRenderBuffer(); - } - else - { -@@ -534,25 +549,21 @@ void CXBMCRenderManager::SetViewMode(int iViewMode) - m_pRenderer->SetViewMode(iViewMode); - } - --void CXBMCRenderManager::FlipPage(volatile bool& bStop, double timestamp /* = 0LL*/, int source /*= -1*/, EFIELDSYNC sync /*= FS_NONE*/) -+void CXBMCRenderManager::FlipPage(volatile bool& bStop, double timestamp /* = 0LL*/, int source /*= -1*/, EFIELDSYNC sync /*= FS_NONE*/, int speed /*= 1000*/) - { -- if(timestamp - GetPresentTime() > MAXPRESENTDELAY) -- timestamp = GetPresentTime() + MAXPRESENTDELAY; -- -- /* can't flip, untill timestamp */ -- if(!g_graphicsContext.IsFullScreenVideo()) -- WaitPresentTime(timestamp); -- -- /* make sure any queued frame was fully presented */ -- double timeout = m_presenttime + 1.0; -- while(m_presentstep != PRESENT_IDLE && !bStop) -+ if (!m_bUseBuffering) - { -- if(!m_presentevent.WaitMSec(100) && GetPresentTime() > timeout && !bStop) -+ /* make sure any queued frame was fully presented */ -+ double timeout = m_presenttime + 1.0; -+ while(m_presentstep != PRESENT_IDLE && !bStop) - { -- CLog::Log(LOGWARNING, "CRenderManager::FlipPage - timeout waiting for previous frame"); -- return; -+ if(!m_presentevent.WaitMSec(100) && GetPresentTime() > timeout && !bStop) -+ { -+ CLog::Log(LOGWARNING, "CRenderManager::FlipPage - timeout waiting for previous frame"); -+ return; -+ } - } -- }; -+ } - - if(bStop) - return; -@@ -560,58 +571,67 @@ void CXBMCRenderManager::FlipPage(volatile bool& bStop, double timestamp /* = 0L - { CRetakeLock lock(m_sharedSection); - if(!m_pRenderer) return; - -- m_presenttime = timestamp; -- m_presentfield = sync; -- m_presentstep = PRESENT_FLIP; -- m_presentsource = source; -+ double presenttime = timestamp; -+ EFIELDSYNC presentfield = sync; -+ EPRESENTMETHOD presentmethod; -+ - EDEINTERLACEMODE deinterlacemode = g_settings.m_currentVideoSettings.m_DeinterlaceMode; - EINTERLACEMETHOD interlacemethod = AutoInterlaceMethodInternal(g_settings.m_currentVideoSettings.m_InterlaceMethod); - - bool invert = false; - - if (deinterlacemode == VS_DEINTERLACEMODE_OFF) -- m_presentmethod = PRESENT_METHOD_SINGLE; -+ presentmethod = PRESENT_METHOD_SINGLE; - else - { -- if (deinterlacemode == VS_DEINTERLACEMODE_AUTO && m_presentfield == FS_NONE) -- m_presentmethod = PRESENT_METHOD_SINGLE; -+ if (deinterlacemode == VS_DEINTERLACEMODE_AUTO && presentfield == FS_NONE) -+ presentmethod = PRESENT_METHOD_SINGLE; - else - { -- if (interlacemethod == VS_INTERLACEMETHOD_RENDER_BLEND) m_presentmethod = PRESENT_METHOD_BLEND; -- else if (interlacemethod == VS_INTERLACEMETHOD_RENDER_WEAVE) m_presentmethod = PRESENT_METHOD_WEAVE; -- else if (interlacemethod == VS_INTERLACEMETHOD_RENDER_WEAVE_INVERTED) { m_presentmethod = PRESENT_METHOD_WEAVE ; invert = true; } -- else if (interlacemethod == VS_INTERLACEMETHOD_RENDER_BOB) m_presentmethod = PRESENT_METHOD_BOB; -- else if (interlacemethod == VS_INTERLACEMETHOD_RENDER_BOB_INVERTED) { m_presentmethod = PRESENT_METHOD_BOB; invert = true; } -- else if (interlacemethod == VS_INTERLACEMETHOD_DXVA_BOB) m_presentmethod = PRESENT_METHOD_BOB; -- else if (interlacemethod == VS_INTERLACEMETHOD_DXVA_BEST) m_presentmethod = PRESENT_METHOD_BOB; -- else m_presentmethod = PRESENT_METHOD_SINGLE; -+ if (interlacemethod == VS_INTERLACEMETHOD_RENDER_BLEND) presentmethod = PRESENT_METHOD_BLEND; -+ else if (interlacemethod == VS_INTERLACEMETHOD_RENDER_WEAVE) presentmethod = PRESENT_METHOD_WEAVE; -+ else if (interlacemethod == VS_INTERLACEMETHOD_RENDER_WEAVE_INVERTED) { presentmethod = PRESENT_METHOD_WEAVE ; invert = true; } -+ else if (interlacemethod == VS_INTERLACEMETHOD_RENDER_BOB) presentmethod = PRESENT_METHOD_BOB; -+ else if (interlacemethod == VS_INTERLACEMETHOD_RENDER_BOB_INVERTED) { presentmethod = PRESENT_METHOD_BOB; invert = true; } -+ else if (interlacemethod == VS_INTERLACEMETHOD_DXVA_BOB) presentmethod = PRESENT_METHOD_BOB; -+ else if (interlacemethod == VS_INTERLACEMETHOD_DXVA_BEST) presentmethod = PRESENT_METHOD_BOB; -+ else presentmethod = PRESENT_METHOD_SINGLE; - - /* default to odd field if we want to deinterlace and don't know better */ -- if (deinterlacemode == VS_DEINTERLACEMODE_FORCE && m_presentfield == FS_NONE) -- m_presentfield = FS_TOP; -+ if (deinterlacemode == VS_DEINTERLACEMODE_FORCE && presentfield == FS_NONE) -+ presentfield = FS_TOP; - - /* invert present field */ - if(invert) - { -- if( m_presentfield == FS_BOT ) -- m_presentfield = FS_TOP; -+ if( presentfield == FS_BOT ) -+ presentfield = FS_TOP; - else -- m_presentfield = FS_BOT; -+ presentfield = FS_BOT; - } - } - } - -+ FlipFreeBuffer(); -+ m_renderBuffers[m_iOutputRenderBuffer].pts = timestamp; -+ m_renderBuffers[m_iOutputRenderBuffer].presentfield = presentfield; -+ m_renderBuffers[m_iOutputRenderBuffer].presentmethod = presentmethod; -+ m_speed = speed; - } - - g_application.NewFrame(); -- /* wait untill render thread have flipped buffers */ -- timeout = m_presenttime + 1.0; -- while(m_presentstep == PRESENT_FLIP && !bStop) -+ -+ if (!m_bUseBuffering) - { -- if(!m_presentevent.WaitMSec(100) && GetPresentTime() > timeout && !bStop) -+ /* wait untill render thread have flipped buffers */ -+ double timeout = m_presenttime + 1.0; -+ while(m_presentstep == PRESENT_FLIP && !bStop) - { -- CLog::Log(LOGWARNING, "CRenderManager::FlipPage - timeout waiting for flip to complete"); -- return; -+ if(!m_presentevent.WaitMSec(100) && GetPresentTime() > timeout && !bStop) -+ { -+ CLog::Log(LOGWARNING, "CRenderManager::FlipPage - timeout waiting for flip to complete"); -+ return; -+ } - } - } - } -@@ -675,8 +695,12 @@ void CXBMCRenderManager::Present() - if (!m_pRenderer) - return; - -+ if (m_presentstep == PRESENT_IDLE) -+ PrepareNextRender(); -+ - if(m_presentstep == PRESENT_FLIP) - { -+ FlipRenderBuffer(); - m_overlays.Flip(); - m_pRenderer->FlipPage(m_presentsource); - m_presentstep = PRESENT_FRAME; -@@ -800,11 +824,11 @@ int CXBMCRenderManager::AddVideoPicture(DVDVideoPicture& pic) - if (!m_pRenderer) - return -1; - -- if(m_pRenderer->AddVideoPicture(&pic)) -+ if(m_pRenderer->AddVideoPicture(&pic, (m_iOutputRenderBuffer + 1) % m_iNumRenderBuffers)) - return 1; - - YV12Image image; -- int index = m_pRenderer->GetImage(&image); -+ int index = m_pRenderer->GetImage(&image, (m_iOutputRenderBuffer + 1) % m_iNumRenderBuffers); - - if(index < 0) - return index; -@@ -830,19 +854,19 @@ int CXBMCRenderManager::AddVideoPicture(DVDVideoPicture& pic) - } - #ifdef HAVE_LIBVDPAU - else if(pic.format == RENDER_FMT_VDPAU) -- m_pRenderer->AddProcessor(pic.vdpau); -+ m_pRenderer->AddProcessor(pic.vdpau, index); - #endif - #ifdef HAVE_LIBOPENMAX - else if(pic.format == RENDER_FMT_OMXEGL) -- m_pRenderer->AddProcessor(pic.openMax, &pic); -+ m_pRenderer->AddProcessor(pic.openMax, &pic, index); - #endif - #ifdef TARGET_DARWIN - else if(pic.format == RENDER_FMT_CVBREF) -- m_pRenderer->AddProcessor(pic.cvBufferRef); -+ m_pRenderer->AddProcessor(pic.cvBufferRef, index); - #endif - #ifdef HAVE_LIBVA - else if(pic.format == RENDER_FMT_VAAPI) -- m_pRenderer->AddProcessor(*pic.vaapi); -+ m_pRenderer->AddProcessor(*pic.vaapi, index); - #endif - m_pRenderer->ReleaseImage(index, false); - -@@ -904,3 +928,177 @@ EINTERLACEMETHOD CXBMCRenderManager::AutoInterlaceMethodInternal(EINTERLACEMETHO - - return mInt; - } -+ -+int CXBMCRenderManager::WaitForBuffer(volatile bool& bStop, int timeout) -+{ -+ CSharedLock lock(m_sharedSection); -+ if (!m_pRenderer) -+ return -1; -+ -+ double maxwait = GetPresentTime() + (float)timeout/1000; -+ while(!HasFreeBuffer() && !bStop) -+ { -+ lock.Leave(); -+ m_flipEvent.WaitMSec(std::min(50, timeout)); -+ if(GetPresentTime() > maxwait && !bStop) -+ { -+ if (timeout != 0) -+ CLog::Log(LOGWARNING, "CRenderManager::WaitForBuffer - timeout waiting for buffer"); -+ return -1; -+ } -+ lock.Enter(); -+ } -+ lock.Leave(); -+ -+ if (bStop) -+ return -1; -+ -+ return 1; -+} -+ -+int CXBMCRenderManager::GetNextRenderBufferIndex() -+{ -+ if (m_iOutputRenderBuffer == m_iCurrentRenderBuffer) -+ return -1; -+ return (m_iCurrentRenderBuffer + 1) % m_iNumRenderBuffers; -+} -+ -+void CXBMCRenderManager::FlipRenderBuffer() -+{ -+ m_iCurrentRenderBuffer = GetNextRenderBufferIndex(); -+} -+ -+int CXBMCRenderManager::FlipFreeBuffer() -+{ -+ // See "Render Buffer State Description" in header for information. -+ if (HasFreeBuffer()) -+ { -+ m_bAllRenderBuffersDisplayed = false; -+ m_iOutputRenderBuffer = (m_iOutputRenderBuffer + 1) % m_iNumRenderBuffers; -+ return m_iOutputRenderBuffer; -+ } -+} -+ -+bool CXBMCRenderManager::HasFreeBuffer() -+{ -+ if (!m_bUseBuffering) -+ { -+ if (m_iOutputRenderBuffer != m_iCurrentRenderBuffer) -+ return false; +diff -Naur xbmc-12.0.4/configure.in xbmc-12.0.4.patch/configure.in +--- xbmc-12.0.4/configure.in 2013-03-08 13:01:45.000000000 +0100 ++++ xbmc-12.0.4.patch/configure.in 2013-03-10 13:00:12.321988177 +0100 +@@ -124,6 +124,8 @@ + vaapi_disabled="== VAAPI support manually disabled. ==" + crystalhd_not_found="== Could not find libcrystalhd. CrystalHD support disabled. ==" + crystalhd_disabled="== CrystalHD support manually disabled. ==" ++xvba_not_found="== Could not find amdxvba.h. XVBA support disabled. ==" ++xvba_disabled="== XVBA support manually disabled. ==" + vdadecoder_enabled="== VDADecoder support enabled. ==" + vdadecoder_disabled="== VDADecoder support manually disabled. ==" + vtbdecoder_enabled="== VTBDecoder support enabled. ==" +@@ -247,6 +249,12 @@ + [enable CrystalHD decoding (default is auto)])], + [use_crystalhd=$enableval], + [use_crystalhd=auto]) ++ ++AC_ARG_ENABLE([xvba], ++ [AS_HELP_STRING([--enable-xvba], ++ [enable XVBA decoding (default is auto)])], ++ [use_xvba=$enableval], ++ [use_xvba=auto]) + + AC_ARG_ENABLE([vdadecoder], + [AS_HELP_STRING([--enable-vdadecoder], +@@ -1751,6 +1759,38 @@ + USE_CRYSTALHD=0 + fi + ++# XVBA ++if test "x$use_xvba" != "xno"; then ++ if test "$host_vendor" = "apple" ; then ++ if test "x$use_xvba" = "xyes"; then ++ AC_MSG_ERROR([XVBA not supported on this platform]) + else -+ return true; -+ } -+ -+ int outputPlus1 = (m_iOutputRenderBuffer + 1) % m_iNumRenderBuffers; -+ if ((m_iOutputRenderBuffer == m_iDisplayedRenderBuffer && !m_bAllRenderBuffersDisplayed) -+ || outputPlus1 == m_iCurrentRenderBuffer) -+ return false; ++ use_xvba="no" ++ AC_MSG_NOTICE($xvba_disabled) ++ fi ++ USE_XVBA=0 + else -+ return true; -+} ++ initial_val=$use_xvba ++ AC_CHECK_HEADER([amd/amdxvba.h],, use_xvba=no, [#include ]) + -+void CXBMCRenderManager::ResetRenderBuffer() -+{ -+ m_iNumRenderBuffers = m_pRenderer->GetMaxBufferSize(); -+ m_iNumRenderBuffers = std::min(5, m_iNumRenderBuffers); -+ m_iNumRenderBuffers = std::max(2, m_iNumRenderBuffers); ++ if test "x$use_xvba" = "xno"; then ++ if test "x$initial_val" = "xyes"; then ++ AC_MSG_ERROR($xvba_not_found) ++ else ++ AC_MSG_RESULT($xvba_not_found) ++ fi ++ USE_XVBA=0 ++ else ++ AC_DEFINE([HAVE_LIBXVBA], [1], [Define to 1 if you have the 'xvba' header (amdxvba.h)]) ++ USE_XVBA=1 ++ fi ++ fi ++else ++ AC_MSG_NOTICE($xvba_disabled) ++ USE_XVBA=0 ++fi + -+ if (!m_bCodecSupportsBuffering) -+ m_iNumRenderBuffers = 2; + -+ CLog::Log(LOGNOTICE,"CXBMCRenderManager::ResetRenderBuffer - using %d render buffers", m_iNumRenderBuffers); -+ m_overlays.SetNumBuffers(m_iNumRenderBuffers); -+ m_pRenderer->SetBufferSize(m_iNumRenderBuffers); + # VDADecoder + if test "x$use_vdadecoder" != "xno"; then + if test "$host_vendor" = "apple" ; then +@@ -1962,6 +2002,12 @@ + final_message="$final_message\n CrystalHD:\tNo" + fi + ++if test "x$use_xvba" != "xno"; then ++ final_message="$final_message\n XVBA:\t\tYes" ++else ++ final_message="$final_message\n XVBA:\t\tNo" ++fi + -+ m_iCurrentRenderBuffer = 0; -+ m_iOutputRenderBuffer = 0; -+ m_iDisplayedRenderBuffer = 0; -+ m_bAllRenderBuffersDisplayed = true; -+ m_sleeptime = 1.0; -+ m_presentPts = DVD_NOPTS_VALUE; -+ m_speed = 0; -+} -+ -+void CXBMCRenderManager::PrepareNextRender() -+{ -+ int idx = GetNextRenderBufferIndex(); -+ if (idx < 0) -+ { -+ if (m_speed >= DVD_PLAYSPEED_NORMAL && g_graphicsContext.IsFullScreenVideo()) -+ CLog::Log(LOGDEBUG,"%s no buffer, out: %d, current: %d, display: %d", -+ __FUNCTION__, m_iOutputRenderBuffer, m_iCurrentRenderBuffer, m_iDisplayedRenderBuffer); -+ return; -+ } -+ -+ double iClockSleep, iPlayingClock, iCurrentClock; -+ if (g_application.m_pPlayer) -+ iPlayingClock = g_application.m_pPlayer->GetClock(iCurrentClock, false); -+ else -+ iPlayingClock = iCurrentClock = 0; -+ -+ iClockSleep = m_renderBuffers[idx].pts - iPlayingClock; -+ -+ if (m_speed) -+ iClockSleep = iClockSleep * DVD_PLAYSPEED_NORMAL / m_speed; -+ -+ double presenttime = (iCurrentClock + iClockSleep) / DVD_TIME_BASE; -+ double clocktime = iCurrentClock / DVD_TIME_BASE; -+ if(presenttime - clocktime > MAXPRESENTDELAY) -+ presenttime = clocktime + MAXPRESENTDELAY; -+ -+ m_sleeptime = presenttime - clocktime; -+ double frametime = 1 / g_graphicsContext.GetFPS(); -+ -+ if (g_graphicsContext.IsFullScreenVideo() || presenttime <= clocktime + frametime) -+ { -+ m_presentPts = m_renderBuffers[idx].pts; -+ m_presenttime = presenttime; -+ m_presentmethod = m_renderBuffers[idx].presentmethod; -+ m_presentfield = m_renderBuffers[idx].presentfield; -+ m_presentstep = PRESENT_FLIP; -+ m_presentsource = idx; -+ } -+} -+ -+void CXBMCRenderManager::EnableBuffering(bool enable) -+{ -+ CRetakeLock lock(m_sharedSection); -+ -+ if (m_iNumRenderBuffers < 3) -+ return; -+ -+ m_bUseBuffering = enable; -+ if (!m_bUseBuffering) -+ m_iOutputRenderBuffer = m_iCurrentRenderBuffer; -+ -+ CLog::Log(LOGDEBUG, "CXBMCRenderManager::EnableBuffering - %d", m_bUseBuffering); -+} -+ -+void CXBMCRenderManager::DiscardBuffer() -+{ -+ CRetakeLock lock(m_sharedSection); -+ m_iOutputRenderBuffer = m_iCurrentRenderBuffer; -+} -+ -+void CXBMCRenderManager::NotifyDisplayFlip() -+{ -+ CRetakeLock lock(m_sharedSection); -+ if (!m_pRenderer) -+ return; -+ -+ if (m_iNumRenderBuffers >= 3) -+ { -+ int last = m_iDisplayedRenderBuffer; -+ m_iDisplayedRenderBuffer = (m_iCurrentRenderBuffer + m_iNumRenderBuffers - 1) % m_iNumRenderBuffers; -+ -+ if (last != m_iDisplayedRenderBuffer -+ && m_iDisplayedRenderBuffer != m_iCurrentRenderBuffer) -+ { -+ m_pRenderer->ReleaseBuffer(m_iDisplayedRenderBuffer); -+ m_overlays.ReleaseBuffer(m_iDisplayedRenderBuffer); -+ } -+ } -+ -+ lock.Leave(); -+ m_flipEvent.Set(); -+} -diff --git a/xbmc/cores/VideoRenderers/RenderManager.h b/xbmc/cores/VideoRenderers/RenderManager.h -index 7fe6bb2..96ab53f 100644 ---- a/xbmc/cores/VideoRenderers/RenderManager.h -+++ b/xbmc/cores/VideoRenderers/RenderManager.h -@@ -31,6 +31,7 @@ - #include "OverlayRenderer.h" + if test "x$use_vdadecoder" != "xno"; then + final_message="$final_message\n VDADecoder:\tYes" + else +@@ -2435,6 +2481,7 @@ + AC_SUBST(USE_VDPAU) + AC_SUBST(USE_VAAPI) + AC_SUBST(USE_CRYSTALHD) ++AC_SUBST(USE_XVBA) + AC_SUBST(USE_LIBSMBCLIENT) + AC_SUBST(USE_LIBNFS) + AC_SUBST(USE_LIBAFPCLIENT) +@@ -2618,6 +2665,7 @@ + `if test "x$use_vdpau" != "xno"; then echo --enable-vdpau; else echo --disable-vdpau; fi` \ + `if test "x$use_vaapi" != "xno"; then echo --enable-vaapi; else echo --disable-vaapi; fi` \ + `if test "$use_optimizations" != "no"; then echo --enable-optimizations; else echo --disable-optimizations; fi` \ ++ `if test "x$use_xvba" != "xno"; then echo --enable-xvba; else echo --disable-xvba; fi` \ + --enable-protocol=http \ + --enable-pthreads \ + --enable-runtime-cpudetect \ +diff -Naur xbmc-12.0.4/language/English/strings.po xbmc-12.0.4.patch/language/English/strings.po +--- xbmc-12.0.4/language/English/strings.po 2013-03-08 13:01:31.000000000 +0100 ++++ xbmc-12.0.4.patch/language/English/strings.po 2013-03-10 13:00:12.322988170 +0100 +@@ -895,7 +895,9 @@ + msgid "Sizing: (%i,%i)->(%i,%i) (Zoom x%2.2f) AR:%2.2f:1 (Pixels: %2.2f:1) (VShift: %2.2f)" + msgstr "" - class CRenderCapture; -+class CDVDClock; +-#empty string with id 246 ++msgctxt "#246" ++msgid "Monitor" ++msgstr "" - namespace DXVA { class CProcessor; } - namespace VAAPI { class CSurfaceHolder; } -@@ -65,12 +66,12 @@ class CXBMCRenderManager - void SetViewMode(int iViewMode); + msgctxt "#247" + msgid "Scripts" +@@ -4369,11 +4371,7 @@ + msgid "VDPAU HQ Upscaling level" + msgstr "" - // Functions called from mplayer -- 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); -+ 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, bool buffering = false); - bool IsConfigured(); - - int AddVideoPicture(DVDVideoPicture& picture); - -- void FlipPage(volatile bool& bStop, double timestamp = 0.0, int source = -1, EFIELDSYNC sync = FS_NONE); -+ void FlipPage(volatile bool& bStop, double timestamp = 0.0, int source = -1, EFIELDSYNC sync = FS_NONE, int speed = 1000); - unsigned int PreInit(); - void UnInit(); - bool Flush(); -@@ -78,7 +79,7 @@ class CXBMCRenderManager - void AddOverlay(CDVDOverlay* o, double pts) - { - CSharedLock lock(m_sharedSection); -- m_overlays.AddOverlay(o, pts); -+ m_overlays.AddOverlay(o, pts, (m_iOutputRenderBuffer + 1) % m_iNumRenderBuffers); - } - - void AddCleanup(OVERLAY::COverlay* o) -@@ -132,6 +133,24 @@ class CXBMCRenderManager - - void RegisterRenderUpdateCallBack(const void *ctx, RenderUpdateCallBackFn 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 -+ * in case no buffer is available. Player may call this in a loop and decides -+ * by itself when it wants to drop a frame. -+ * If no buffering is requested in Configure, player does not need to call this, -+ * because FlipPage will block. -+ */ -+ int WaitForBuffer(volatile bool& bStop, int timeout = 100); -+ -+ /** -+ * Called by application right after flip. The buffer which has been rendered to -+ * display becomes available for player to deliver a new frame. -+ */ -+ void NotifyDisplayFlip(); -+ void EnableBuffering(bool enable); -+ void DiscardBuffer(); -+ - protected: - void Render(bool clear, DWORD flags, DWORD alpha); - -@@ -139,6 +158,13 @@ class CXBMCRenderManager - void PresentFields(bool clear, DWORD flags, DWORD alpha); - void PresentBlend(bool clear, DWORD flags, DWORD alpha); - -+ int GetNextRenderBufferIndex(); -+ void FlipRenderBuffer(); -+ int FlipFreeBuffer(); -+ bool HasFreeBuffer(); -+ void ResetRenderBuffer(); -+ void PrepareNextRender(); -+ - EINTERLACEMETHOD AutoInterlaceMethodInternal(EINTERLACEMETHOD mInt); - - bool m_bPauseDrawing; // true if we should pause rendering -@@ -169,6 +195,37 @@ class CXBMCRenderManager - double m_displayLatency; - void UpdateDisplayLatency(); - -+ // Render Buffer State Description: -+ // -+ // Output: is the buffer about to or having its texture prepared for render (ie from output thread). -+ // Cannot go past the "Displayed" buffer (otherwise we will probably overwrite buffers not yet -+ // displayed or even rendered). -+ // Current: is the current buffer being or having been submitted for render to back buffer. -+ // Cannot go past "Output" buffer (else it would be rendering old output). -+ // Displayed: is the buffer that is now considered to be safely copied from back buffer to front buffer -+ // (we assume that after two swap-buffer flips for the same "Current" render buffer that that -+ // buffer will be safe, but otherwise we consider that only the previous-to-"Current" is guaranteed). -+ -+ int m_iCurrentRenderBuffer; -+ int m_iNumRenderBuffers; -+ int m_iOutputRenderBuffer; -+ int m_iDisplayedRenderBuffer; -+ bool m_bAllRenderBuffersDisplayed; -+ bool m_bUseBuffering; -+ bool m_bCodecSupportsBuffering; -+ int m_speed; -+ CEvent m_flipEvent; -+ -+ struct -+ { -+ double pts; -+ EFIELDSYNC presentfield; -+ EPRESENTMETHOD presentmethod; -+ }m_renderBuffers[5]; -+ -+ double m_sleeptime; -+ double m_presentPts; -+ - double m_presenttime; - double m_presentcorr; - double m_presenterr; -diff --git a/xbmc/cores/VideoRenderers/WinRenderer.cpp b/xbmc/cores/VideoRenderers/WinRenderer.cpp -index f1d0768..f0f5b2d 100644 ---- a/xbmc/cores/VideoRenderers/WinRenderer.cpp -+++ b/xbmc/cores/VideoRenderers/WinRenderer.cpp -@@ -253,12 +253,12 @@ int CWinRenderer::NextYV12Texture() - return -1; - } - --bool CWinRenderer::AddVideoPicture(DVDVideoPicture* picture) -+bool CWinRenderer::AddVideoPicture(DVDVideoPicture* picture, int index) - { - if (m_renderMethod == RENDER_DXVA) - { -- int source = NextYV12Texture(); -- if(source < 0) -+ int source = index; -+ if(source < 0 || NextYV12Texture() < 0) - return false; - - DXVABuffer *buf = (DXVABuffer*)m_VideoBuffers[source]; -@@ -274,7 +274,7 @@ int CWinRenderer::GetImage(YV12Image *image, int source, bool readonly) - if( source == AUTOSOURCE ) - source = NextYV12Texture(); - -- if( source < 0 ) -+ if( source < 0 || NextYV12Texture() < 0) - return -1; - - YUVBuffer *buf = (YUVBuffer*)m_VideoBuffers[source]; -diff --git a/xbmc/cores/VideoRenderers/WinRenderer.h b/xbmc/cores/VideoRenderers/WinRenderer.h -index 2ab5684..f493ba7 100644 ---- a/xbmc/cores/VideoRenderers/WinRenderer.h -+++ b/xbmc/cores/VideoRenderers/WinRenderer.h -@@ -157,7 +157,7 @@ class CWinRenderer : public CBaseRenderer - virtual 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); - virtual int GetImage(YV12Image *image, int source = AUTOSOURCE, bool readonly = false); - virtual void ReleaseImage(int source, bool preserve = false); -- virtual bool AddVideoPicture(DVDVideoPicture* picture); -+ virtual bool AddVideoPicture(DVDVideoPicture* picture, int index); - virtual void FlipPage(int source); - virtual unsigned int PreInit(); - virtual void UnInit(); -diff --git a/xbmc/cores/dvdplayer/DVDPlayer.cpp b/xbmc/cores/dvdplayer/DVDPlayer.cpp -index 0cd2510..dfb317f 100644 ---- a/xbmc/cores/dvdplayer/DVDPlayer.cpp -+++ b/xbmc/cores/dvdplayer/DVDPlayer.cpp -@@ -4075,3 +4075,8 @@ bool CDVDPlayer::CachePVRStream(void) const - !g_PVRManager.IsPlayingRecording() && - g_advancedSettings.m_bPVRCacheInDvdPlayer; - } -+ -+double CDVDPlayer::GetClock(double& absolute, bool interpolated) -+{ -+ return m_clock.GetClock(absolute, interpolated); -+} -diff --git a/xbmc/cores/dvdplayer/DVDPlayer.h b/xbmc/cores/dvdplayer/DVDPlayer.h -index d3c201e..093318e 100644 ---- a/xbmc/cores/dvdplayer/DVDPlayer.h -+++ b/xbmc/cores/dvdplayer/DVDPlayer.h -@@ -252,6 +252,8 @@ class CDVDPlayer : public IPlayer, public CThread, public IDVDPlayer - virtual bool SwitchChannel(const PVR::CPVRChannel &channel); - virtual bool CachePVRStream(void) const; - -+ virtual double GetClock(double& absolute, bool interpolated = true); -+ - enum ECacheState - { CACHESTATE_DONE = 0 - , CACHESTATE_FULL // player is filling up the demux queue -diff --git a/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp b/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp -index 3008c25..19496a7 100644 ---- a/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp -+++ b/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp -@@ -261,6 +261,7 @@ void CDVDPlayerVideo::OpenStream(CDVDStreamInfo &hint, CDVDVideoCodec* codec) - m_stalled = m_messageQueue.GetPacketCount(CDVDMsg::DEMUXER_PACKET) == 0; - m_started = false; - m_codecname = m_pVideoCodec->GetName(); -+ g_renderManager.EnableBuffering(false); - } - - void CDVDPlayerVideo::CloseStream(bool bWaitForBuffers) -@@ -436,6 +437,7 @@ void CDVDPlayerVideo::Process() - picture.iFlags &= ~DVP_FLAG_ALLOCATED; - m_packets.clear(); - m_started = false; -+ g_renderManager.EnableBuffering(false); - } - else if (pMsg->IsType(CDVDMsg::GENERAL_FLUSH)) // private message sent by (CDVDPlayerVideo::Flush()) - { -@@ -448,6 +450,7 @@ void CDVDPlayerVideo::Process() - //we need to recalculate the framerate - //TODO: this needs to be set on a streamchange instead - ResetFrameRateCalc(); -+ g_renderManager.EnableBuffering(false); - - m_stalled = true; - m_started = false; -@@ -586,6 +589,8 @@ void CDVDPlayerVideo::Process() - - m_pVideoCodec->Reset(); - m_packets.clear(); -+ picture.iFlags &= ~DVP_FLAG_ALLOCATED; -+ g_renderManager.DiscardBuffer(); - break; - } - -@@ -700,6 +705,7 @@ void CDVDPlayerVideo::Process() - m_codecname = m_pVideoCodec->GetName(); - m_started = true; - m_messageParent.Put(new CDVDMsgInt(CDVDMsg::PLAYER_STARTED, DVDPLAYER_VIDEO)); -+ g_renderManager.EnableBuffering(true); - } - - // guess next frame pts. iDuration is always valid -@@ -1088,47 +1094,61 @@ int CDVDPlayerVideo::OutputPicture(const DVDVideoPicture* src, double pts) - } - - CStdString formatstr; -+ bool buffering; - - switch(pPicture->format) - { - case RENDER_FMT_YUV420P: - formatstr = "YV12"; -+ buffering = true; - break; - case RENDER_FMT_YUV420P16: - formatstr = "YV12P16"; -+ buffering = true; - break; - case RENDER_FMT_YUV420P10: - formatstr = "YV12P10"; -+ buffering = true; - break; - case RENDER_FMT_NV12: - formatstr = "NV12"; -+ buffering = true; - break; - case RENDER_FMT_UYVY422: - formatstr = "UYVY"; -+ buffering = true; - break; - case RENDER_FMT_YUYV422: - formatstr = "YUY2"; -+ buffering = true; - break; - case RENDER_FMT_VDPAU: - formatstr = "VDPAU"; -+ buffering = true; - break; - case RENDER_FMT_DXVA: - formatstr = "DXVA"; -+ buffering = false; - break; - case RENDER_FMT_VAAPI: - formatstr = "VAAPI"; -+ buffering = false; - break; - case RENDER_FMT_OMXEGL: - formatstr = "OMXEGL"; -+ buffering = false; - break; - case RENDER_FMT_CVBREF: - formatstr = "BGRA"; -+ buffering = false; - break; - case RENDER_FMT_BYPASS: - formatstr = "BYPASS"; -+ buffering = false; - break; - case RENDER_FMT_NONE: - formatstr = "NONE"; -+ buffering = false; - break; - } - -@@ -1139,7 +1159,7 @@ int CDVDPlayerVideo::OutputPicture(const DVDVideoPicture* src, double pts) - } - - 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)) -+ if(!g_renderManager.Configure(pPicture->iWidth, pPicture->iHeight, pPicture->iDisplayWidth, pPicture->iDisplayHeight, config_framerate, flags, pPicture->format, pPicture->extended_format, m_hints.orientation, buffering)) - { - CLog::Log(LOGERROR, "%s - failed to configure renderer", __FUNCTION__); - return EOS_ABORT; -@@ -1317,6 +1337,16 @@ int CDVDPlayerVideo::OutputPicture(const DVDVideoPicture* src, double pts) - mDisplayField = FS_BOT; - } - -+ int buffer = g_renderManager.WaitForBuffer(m_bStop); -+ while (buffer < 0 && !CThread::m_bStop && -+ CDVDClock::GetAbsoluteClock(false) < iCurrentClock + iSleepTime + DVD_MSEC_TO_TIME(500) ) -+ { -+ Sleep(1); -+ buffer = g_renderManager.WaitForBuffer(m_bStop); -+ } -+ if (buffer < 0) -+ return EOS_DROPPED; -+ - ProcessOverlays(pPicture, pts); - AutoCrop(pPicture); - -@@ -1333,7 +1363,7 @@ int CDVDPlayerVideo::OutputPicture(const DVDVideoPicture* src, double pts) - if (index < 0) - return EOS_DROPPED; - -- g_renderManager.FlipPage(CThread::m_bStop, (iCurrentClock + iSleepTime) / DVD_TIME_BASE, -1, mDisplayField); -+ g_renderManager.FlipPage(CThread::m_bStop, pts, -1, mDisplayField, m_speed); - - return result; - #else --- -1.7.10 - - -From 383daa67f101ff6cc75f0fde39c8bca69a7789ae Mon Sep 17 00:00:00 2001 -From: xbmc -Date: Sat, 16 Feb 2013 08:32:18 +0100 -Subject: [PATCH 02/88] add buffering for GLES - ---- - xbmc/cores/VideoRenderers/LinuxRendererGLES.cpp | 10 ---------- - xbmc/cores/VideoRenderers/LinuxRendererGLES.h | 6 ++++-- - 2 files changed, 4 insertions(+), 12 deletions(-) - -diff --git a/xbmc/cores/VideoRenderers/LinuxRendererGLES.cpp b/xbmc/cores/VideoRenderers/LinuxRendererGLES.cpp -index 2a59e2b..1bf2f3b 100644 ---- a/xbmc/cores/VideoRenderers/LinuxRendererGLES.cpp -+++ b/xbmc/cores/VideoRenderers/LinuxRendererGLES.cpp -@@ -135,13 +135,6 @@ - delete m_dllSwScale; - } - --void CLinuxRendererGLES::ManageTextures() --{ -- m_NumYV12Buffers = 2; -- //m_iYV12RenderBuffer = 0; -- return; --} +-msgctxt "#13122" +-msgid "VDPAU Studio level color conversion" +-msgstr "" - - bool CLinuxRendererGLES::ValidateRenderTarget() - { - if (!m_bValidated) -@@ -395,7 +388,6 @@ void CLinuxRendererGLES::Update(bool bPauseDrawing) - { - if (!m_bConfigured) return; - ManageDisplay(); -- ManageTextures(); - } +-#empty strings from id 13123 to 13129 ++#empty strings from id 13122 to 13129 - void CLinuxRendererGLES::RenderUpdate(bool clear, DWORD flags, DWORD alpha) -@@ -409,7 +401,6 @@ void CLinuxRendererGLES::RenderUpdate(bool clear, DWORD flags, DWORD alpha) - if (m_renderMethod & RENDER_BYPASS) - { - ManageDisplay(); -- ManageTextures(); - // if running bypass, then the player might need the src/dst rects - // for sizing video playback on a layer other than the gles layer. - if (m_RenderUpdateCallBackFn) -@@ -449,7 +440,6 @@ void CLinuxRendererGLES::RenderUpdate(bool clear, DWORD flags, DWORD alpha) - return; + msgctxt "#13130" + msgid "Blank other displays" +@@ -5114,7 +5112,19 @@ + msgid "Play only this" + msgstr "" - ManageDisplay(); -- ManageTextures(); - - g_graphicsContext.BeginPaint(); - -diff --git a/xbmc/cores/VideoRenderers/LinuxRendererGLES.h b/xbmc/cores/VideoRenderers/LinuxRendererGLES.h -index c6b69db..5bae10d 100644 ---- a/xbmc/cores/VideoRenderers/LinuxRendererGLES.h -+++ b/xbmc/cores/VideoRenderers/LinuxRendererGLES.h -@@ -41,7 +41,7 @@ - class COpenMaxVideo; - typedef std::vector Features; - --#define NUM_BUFFERS 3 -+#define NUM_BUFFERS 10 - - - #undef ALIGN -@@ -138,6 +138,9 @@ class CLinuxRendererGLES : public CBaseRenderer - virtual void UnInit(); - virtual void Reset(); /* resets renderer after seek for example */ - virtual void ReorderDrawPoints(); -+ virtual void SetBufferSize(int numBuffers) { m_NumYV12Buffers = numBuffers; } -+ virtual unsigned int GetMaxBufferSize() { return NUM_BUFFERS; } -+ virtual unsigned int GetProcessorSize() { return m_NumYV12Buffers; } - - virtual void RenderUpdate(bool clear, DWORD flags = 0, DWORD alpha = 255); - -@@ -162,7 +165,6 @@ class CLinuxRendererGLES : public CBaseRenderer - protected: - virtual void Render(DWORD flags, int index); - -- virtual void ManageTextures(); - int NextYV12Texture(); - virtual bool ValidateRenderTarget(); - virtual void LoadShaders(int field=FIELD_FULL); --- -1.7.10 - - -From 41ee337f40e25843a134c3f1e02d66db733555d0 Mon Sep 17 00:00:00 2001 -From: unknown -Date: Sat, 16 Feb 2013 11:17:02 +0100 -Subject: [PATCH 03/88] WinRenderer: add buffering - ---- - xbmc/cores/VideoRenderers/WinRenderer.cpp | 14 ++++++-------- - xbmc/cores/VideoRenderers/WinRenderer.h | 12 +++++------- - 2 files changed, 11 insertions(+), 15 deletions(-) - -diff --git a/xbmc/cores/VideoRenderers/WinRenderer.cpp b/xbmc/cores/VideoRenderers/WinRenderer.cpp -index f0f5b2d..b6279f2 100644 ---- a/xbmc/cores/VideoRenderers/WinRenderer.cpp -+++ b/xbmc/cores/VideoRenderers/WinRenderer.cpp -@@ -103,21 +103,19 @@ static enum PixelFormat PixelFormatFromFormat(ERenderFormat format) - - void CWinRenderer::ManageTextures() - { -- int neededbuffers = 2; -- -- if( m_NumYV12Buffers < neededbuffers ) -+ if( m_NumYV12Buffers < m_neededBuffers ) - { -- for(int i = m_NumYV12Buffers; i neededbuffers ) -+ else if( m_NumYV12Buffers > m_neededBuffers ) - { -- m_NumYV12Buffers = neededbuffers; -+ m_NumYV12Buffers = m_neededBuffers; - m_iYV12RenderBuffer = m_iYV12RenderBuffer % m_NumYV12Buffers; - -- for(int i = m_NumYV12Buffers-1; i>=neededbuffers;i--) -+ for(int i = m_NumYV12Buffers-1; i>=m_neededBuffers;i--) - DeleteYV12Texture(i); - } - } -diff --git a/xbmc/cores/VideoRenderers/WinRenderer.h b/xbmc/cores/VideoRenderers/WinRenderer.h -index f493ba7..b3448ed 100644 ---- a/xbmc/cores/VideoRenderers/WinRenderer.h -+++ b/xbmc/cores/VideoRenderers/WinRenderer.h -@@ -32,13 +32,7 @@ - #include "cores/VideoRenderers/RenderFlags.h" - #include "cores/VideoRenderers/RenderFormats.h" - --//#define MP_DIRECTRENDERING -- --#ifdef MP_DIRECTRENDERING --#define NUM_BUFFERS 3 --#else --#define NUM_BUFFERS 2 --#endif -+#define NUM_BUFFERS 10 - - #define ALIGN(value, alignment) (((value)+((alignment)-1))&~((alignment)-1)) - #define CLAMP(a, min, max) ((a) > (max) ? (max) : ( (a) < (min) ? (min) : a )) -@@ -176,6 +170,8 @@ class CWinRenderer : public CBaseRenderer - void RenderUpdate(bool clear, DWORD flags = 0, DWORD alpha = 255); - - virtual unsigned int GetProcessorSize() { return m_processor.Size(); } -+ virtual void SetBufferSize(int numBuffers) { m_neededBuffers = numBuffers; } -+ virtual unsigned int GetMaxBufferSize() { return NUM_BUFFERS; } - - protected: - virtual void Render(DWORD flags); -@@ -245,6 +241,8 @@ class CWinRenderer : public CBaseRenderer - // the separable HQ scalers need this info, but could the m_destRect be used instead? - unsigned int m_destWidth; - unsigned int m_destHeight; +-#empty strings from id 13435 to 13499 ++msgctxt "#13435" ++msgid "Allow Vdpau OpenGL interop" ++msgstr "" + -+ int m_neededBuffers; ++msgctxt "#13436" ++msgid "Prefer VDPAU Video Mixer" ++msgstr "" ++ ++msgctxt "#13437" ++msgid "Allow hardware acceleration (XVBA)" ++msgstr "" ++ ++#empty strings from id 13438 to 13499 + + msgctxt "#13500" + msgid "A/V sync method" +@@ -6333,10 +6343,14 @@ + msgstr "" + + msgctxt "#16325" +-msgid "Auto - ION Optimized" ++msgid "VDPAU - Bob" ++msgstr "" ++ ++msgctxt "#16326" ++msgid "XVBA" + msgstr "" + +-#empty strings from id 16326 to 16399 ++#empty strings from id 16327 to 16399 + + msgctxt "#16400" + msgid "Post-processing" +diff -Naur xbmc-12.0.4/lib/DllAvFormat.h xbmc-12.0.4.patch/lib/DllAvFormat.h +--- xbmc-12.0.4/lib/DllAvFormat.h 2013-03-08 13:01:40.000000000 +0100 ++++ xbmc-12.0.4.patch/lib/DllAvFormat.h 2013-03-10 13:00:12.325988148 +0100 +@@ -98,6 +98,7 @@ + virtual int avformat_write_header (AVFormatContext *s, AVDictionary **options)=0; + virtual int av_write_trailer(AVFormatContext *s)=0; + virtual int av_write_frame (AVFormatContext *s, AVPacket *pkt)=0; ++ virtual int av_find_default_stream_index(AVFormatContext *s)=0; }; - #else --- -1.7.10 - - -From b0d133ededb6849b4313a65204ee9716cd0aae9f Mon Sep 17 00:00:00 2001 -From: unknown -Date: Sat, 16 Feb 2013 11:17:32 +0100 -Subject: [PATCH 04/88] DXVA: activate buffering in renderer - ---- - xbmc/cores/dvdplayer/DVDPlayerVideo.cpp | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp b/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp -index 19496a7..3bfe180 100644 ---- a/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp -+++ b/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp -@@ -1128,7 +1128,7 @@ int CDVDPlayerVideo::OutputPicture(const DVDVideoPicture* src, double pts) - break; - case RENDER_FMT_DXVA: - formatstr = "DXVA"; -- buffering = false; -+ buffering = true; - break; - case RENDER_FMT_VAAPI: - formatstr = "VAAPI"; --- -1.7.10 - - -From bcbb88a9c2c822bf40c1f4d862cd10b9baccfd02 Mon Sep 17 00:00:00 2001 -From: xbmc -Date: Tue, 2 Oct 2012 10:49:09 +0200 -Subject: [PATCH 05/88] linuxrenderer: delete all textures on reconfigure - ---- - xbmc/cores/VideoRenderers/LinuxRendererGL.cpp | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/xbmc/cores/VideoRenderers/LinuxRendererGL.cpp b/xbmc/cores/VideoRenderers/LinuxRendererGL.cpp -index b32a7ea..a2dc2be 100644 ---- a/xbmc/cores/VideoRenderers/LinuxRendererGL.cpp -+++ b/xbmc/cores/VideoRenderers/LinuxRendererGL.cpp -@@ -251,7 +251,7 @@ bool CLinuxRendererGL::ValidateRenderTarget() - // function pointer for texture might change in - // call to LoadShaders - glFinish(); -- for (int i = 0 ; i < m_NumYV12Buffers ; i++) -+ for (int i = 0 ; i < NUM_BUFFERS ; i++) - (this->*m_textureDelete)(i); + #if (defined USE_EXTERNAL_FFMPEG) || (defined TARGET_DARWIN) +@@ -153,6 +154,7 @@ + virtual int avformat_write_header (AVFormatContext *s, AVDictionary **options) { return ::avformat_write_header (s, options); } + virtual int av_write_trailer(AVFormatContext *s) { return ::av_write_trailer(s); } + virtual int av_write_frame (AVFormatContext *s, AVPacket *pkt) { return ::av_write_frame(s, pkt); } ++ virtual int av_find_default_stream_index(AVFormatContext *s) { return ::av_find_default_stream_index(s); } - // trigger update of video filters --- -1.7.10 - - -From 3d37fe3c9eca279b4ed2e0977651834b858f3682 Mon Sep 17 00:00:00 2001 -From: xbmc -Date: Mon, 28 May 2012 10:17:33 +0200 -Subject: [PATCH 06/88] drop frame counter in application, ask render manager - instead - ---- - xbmc/Application.cpp | 50 +++++---------------------- - xbmc/Application.h | 6 ++-- - xbmc/cores/VideoRenderers/RenderManager.cpp | 11 ++++++ - xbmc/cores/VideoRenderers/RenderManager.h | 1 + - 4 files changed, 23 insertions(+), 45 deletions(-) - -diff --git a/xbmc/Application.cpp b/xbmc/Application.cpp -index efb3ac0..5c7017c 100644 ---- a/xbmc/Application.cpp -+++ b/xbmc/Application.cpp + // DLL faking. + virtual bool ResolveExports() { return true; } +@@ -209,6 +211,7 @@ + DEFINE_METHOD2(int, avformat_write_header , (AVFormatContext *p1, AVDictionary **p2)) + DEFINE_METHOD1(int, av_write_trailer, (AVFormatContext *p1)) + DEFINE_METHOD2(int, av_write_frame , (AVFormatContext *p1, AVPacket *p2)) ++ DEFINE_METHOD1(int, av_find_default_stream_index, (AVFormatContext *p1)) + BEGIN_METHOD_RESOLVE() + RESOLVE_METHOD_RENAME(av_register_all, av_register_all_dont_call) + RESOLVE_METHOD(av_find_input_format) +@@ -243,6 +246,7 @@ + RESOLVE_METHOD(avformat_write_header) + RESOLVE_METHOD(av_write_trailer) + RESOLVE_METHOD(av_write_frame) ++ RESOLVE_METHOD(av_find_default_stream_index) + END_METHOD_RESOLVE() + + /* dependencies of libavformat */ +diff -Naur xbmc-12.0.4/lib/ffmpeg/configure xbmc-12.0.4.patch/lib/ffmpeg/configure +--- xbmc-12.0.4/lib/ffmpeg/configure 2013-03-08 13:01:41.000000000 +0100 ++++ xbmc-12.0.4.patch/lib/ffmpeg/configure 2013-03-10 13:00:12.318988199 +0100 +@@ -113,6 +113,7 @@ + --enable-vdpau enable VDPAU code [autodetect] + --disable-dxva2 disable DXVA2 code + --disable-vda disable VDA code ++ --disable-xvba disable XVBA code + --enable-runtime-cpudetect detect cpu capabilities at runtime (bigger binary) + --enable-hardcoded-tables use hardcoded tables instead of runtime generation + --disable-safe-bitstream-reader +@@ -1084,6 +1085,7 @@ + vaapi + vda + vdpau ++ xvba + version3 + x11grab + zlib +@@ -1423,6 +1425,7 @@ + h264_vaapi_hwaccel_select="vaapi h264_decoder" + h264_vda_hwaccel_deps="VideoDecodeAcceleration_VDADecoder_h pthreads" + h264_vda_hwaccel_select="vda h264_decoder" ++h264_xvba_hwaccel_select="xvba h264_decoder" + h264_vdpau_decoder_select="vdpau h264_decoder" + imc_decoder_select="fft mdct sinewin" + jpegls_decoder_select="golomb" +@@ -1459,6 +1462,7 @@ + mpeg4_decoder_select="h263_decoder mpeg4video_parser" + mpeg4_encoder_select="h263_encoder" + mpeg4_vaapi_hwaccel_select="vaapi mpeg4_decoder" ++mpeg2_xvba_hwaccel_select="xvba mpeg2video_decoder" + mpeg4_vdpau_decoder_select="vdpau mpeg4_decoder" + msmpeg4_crystalhd_decoder_select="crystalhd" + msmpeg4v1_decoder_select="h263_decoder" +@@ -1501,6 +1505,7 @@ + vc1_dxva2_hwaccel_deps="dxva2api_h" + vc1_dxva2_hwaccel_select="dxva2 vc1_decoder" + vc1_vaapi_hwaccel_select="vaapi vc1_decoder" ++vc1_xvba_hwaccel_select="xvba vc1_decoder" + vc1_vdpau_decoder_select="vdpau vc1_decoder" + vc1image_decoder_select="vc1_decoder" + vorbis_decoder_select="mdct" +@@ -1525,6 +1530,7 @@ + wmv3_vaapi_hwaccel_select="vc1_vaapi_hwaccel" + wmv3_vdpau_decoder_select="vc1_vdpau_decoder" + wmv3image_decoder_select="wmv3_decoder" ++wmv3_xvba_hwaccel_select="vc1_xvba_hwaccel" + zlib_decoder_select="zlib" + zlib_encoder_select="zlib" + zmbv_decoder_select="zlib" +@@ -1533,6 +1539,7 @@ + crystalhd_deps="libcrystalhd_libcrystalhd_if_h" + vaapi_deps="va_va_h" + vda_deps="VideoDecodeAcceleration_VDADecoder_h pthreads" ++xvba_deps="amd_amdxvba_h" + vdpau_deps="vdpau_vdpau_h vdpau_vdpau_x11_h" + + # parsers +@@ -3062,6 +3069,7 @@ + check_header termios.h + check_header vdpau/vdpau.h + check_header vdpau/vdpau_x11.h ++check_header amd/amdxvba.h + check_cpp_condition vdpau/vdpau.h "defined(VDP_DECODER_PROFILE_MPEG4_PART2_SP)" && enable vdpau_mpeg4_support + + check_header X11/extensions/XvMClib.h +diff -Naur xbmc-12.0.4/lib/ffmpeg/libavcodec/allcodecs.c xbmc-12.0.4.patch/lib/ffmpeg/libavcodec/allcodecs.c +--- xbmc-12.0.4/lib/ffmpeg/libavcodec/allcodecs.c 2013-03-08 13:01:45.000000000 +0100 ++++ xbmc-12.0.4.patch/lib/ffmpeg/libavcodec/allcodecs.c 2013-03-10 13:00:12.319988191 +0100 +@@ -59,14 +59,18 @@ + REGISTER_HWACCEL (H264_VAAPI, h264_vaapi); + REGISTER_HWACCEL (H264_VDA, h264_vda); + REGISTER_HWACCEL (MPEG1_VDPAU, mpeg1_vdpau); ++ REGISTER_HWACCEL (H264_XVBA, h264_xvba); + REGISTER_HWACCEL (MPEG2_DXVA2, mpeg2_dxva2); + REGISTER_HWACCEL (MPEG2_VAAPI, mpeg2_vaapi); + REGISTER_HWACCEL (MPEG2_VDPAU, mpeg2_vdpau); + REGISTER_HWACCEL (MPEG4_VAAPI, mpeg4_vaapi); ++ REGISTER_HWACCEL (MPEG2_XVBA, mpeg2_xvba); + REGISTER_HWACCEL (VC1_DXVA2, vc1_dxva2); + REGISTER_HWACCEL (VC1_VAAPI, vc1_vaapi); ++ REGISTER_HWACCEL (VC1_XVBA, vc1_xvba); + REGISTER_HWACCEL (WMV3_DXVA2, wmv3_dxva2); + REGISTER_HWACCEL (WMV3_VAAPI, wmv3_vaapi); ++ REGISTER_HWACCEL (WMV3_XVBA, wmv3_xvba); + + /* video codecs */ + REGISTER_ENCODER (A64MULTI, a64multi); +diff -Naur xbmc-12.0.4/lib/ffmpeg/libavcodec/h264.c xbmc-12.0.4.patch/lib/ffmpeg/libavcodec/h264.c +--- xbmc-12.0.4/lib/ffmpeg/libavcodec/h264.c 2013-03-08 13:01:45.000000000 +0100 ++++ xbmc-12.0.4.patch/lib/ffmpeg/libavcodec/h264.c 2013-03-10 13:00:12.319988191 +0100 +@@ -60,6 +60,7 @@ + PIX_FMT_DXVA2_VLD, + PIX_FMT_VAAPI_VLD, + PIX_FMT_VDA_VLD, ++ PIX_FMT_XVBA_VLD, + PIX_FMT_YUVJ420P, + PIX_FMT_NONE + }; +diff -Naur xbmc-12.0.4/lib/ffmpeg/libavcodec/Makefile xbmc-12.0.4.patch/lib/ffmpeg/libavcodec/Makefile +--- xbmc-12.0.4/lib/ffmpeg/libavcodec/Makefile 2013-03-08 13:01:42.000000000 +0100 ++++ xbmc-12.0.4.patch/lib/ffmpeg/libavcodec/Makefile 2013-03-10 13:00:12.318988199 +0100 +@@ -3,7 +3,7 @@ + NAME = avcodec + FFLIBS = avutil + +-HEADERS = avcodec.h avfft.h dxva2.h opt.h vaapi.h vda.h vdpau.h version.h xvmc.h ++HEADERS = avcodec.h avfft.h dxva2.h opt.h vaapi.h vda.h vdpau.h version.h xvmc.h xvba.h + + OBJS = allcodecs.o \ + audioconvert.o \ +@@ -51,6 +51,7 @@ + OBJS-$(CONFIG_VAAPI) += vaapi.o + OBJS-$(CONFIG_VDA) += vda.o + OBJS-$(CONFIG_VDPAU) += vdpau.o ++OBJS-$(CONFIG_XVBA) += xvba.o + + # decoders/encoders/hardware accelerators + OBJS-$(CONFIG_A64MULTI_ENCODER) += a64multienc.o elbg.o +@@ -201,6 +202,7 @@ + OBJS-$(CONFIG_H264_DXVA2_HWACCEL) += dxva2_h264.o + OBJS-$(CONFIG_H264_VAAPI_HWACCEL) += vaapi_h264.o + OBJS-$(CONFIG_H264_VDA_HWACCEL) += vda_h264.o ++OBJS-$(CONFIG_H264_XVBA_HWACCEL) += xvba_h264.o + OBJS-$(CONFIG_HUFFYUV_DECODER) += huffyuv.o + OBJS-$(CONFIG_HUFFYUV_ENCODER) += huffyuv.o + OBJS-$(CONFIG_IDCIN_DECODER) += idcinvideo.o +@@ -284,6 +286,7 @@ + mpegvideo.o error_resilience.o + OBJS-$(CONFIG_MPEG2_DXVA2_HWACCEL) += dxva2_mpeg2.o + OBJS-$(CONFIG_MPEG2_VAAPI_HWACCEL) += vaapi_mpeg2.o ++OBJS-$(CONFIG_MPEG2_XVBA_HWACCEL) += xvba_mpeg2.o + OBJS-$(CONFIG_MPEG2VIDEO_DECODER) += mpeg12.o mpeg12data.o \ + mpegvideo.o error_resilience.o + OBJS-$(CONFIG_MPEG2VIDEO_ENCODER) += mpeg12enc.o mpegvideo_enc.o \ +@@ -431,6 +434,7 @@ + intrax8.o intrax8dsp.o + OBJS-$(CONFIG_VC1_DXVA2_HWACCEL) += dxva2_vc1.o + OBJS-$(CONFIG_VC1_VAAPI_HWACCEL) += vaapi_vc1.o ++OBJS-$(CONFIG_VC1_XVBA_HWACCEL) += xvba_vc1.o + OBJS-$(CONFIG_VCR1_DECODER) += vcr1.o + OBJS-$(CONFIG_VCR1_ENCODER) += vcr1.o + OBJS-$(CONFIG_VMDAUDIO_DECODER) += vmdav.o +@@ -732,6 +736,7 @@ + SKIPHEADERS-$(CONFIG_LIBSCHROEDINGER) += libschroedinger.h + SKIPHEADERS-$(CONFIG_VAAPI) += vaapi_internal.h + SKIPHEADERS-$(CONFIG_VDA) += vda_internal.h ++SKIPHEADERS-$(CONFIG_XVBA) += xvba_internal.h + SKIPHEADERS-$(CONFIG_VDPAU) += vdpau.h + SKIPHEADERS-$(CONFIG_XVMC) += xvmc.h + SKIPHEADERS-$(HAVE_W32THREADS) += w32pthreads.h +diff -Naur xbmc-12.0.4/lib/ffmpeg/libavcodec/mpegvideo.c xbmc-12.0.4.patch/lib/ffmpeg/libavcodec/mpegvideo.c +--- xbmc-12.0.4/lib/ffmpeg/libavcodec/mpegvideo.c 2013-03-08 13:01:42.000000000 +0100 ++++ xbmc-12.0.4.patch/lib/ffmpeg/libavcodec/mpegvideo.c 2013-03-10 13:00:12.320988184 +0100 +@@ -136,6 +136,7 @@ + PIX_FMT_DXVA2_VLD, + PIX_FMT_VAAPI_VLD, + PIX_FMT_VDA_VLD, ++ PIX_FMT_XVBA_VLD, + PIX_FMT_YUV420P, + PIX_FMT_NONE + }; +diff -Naur xbmc-12.0.4/lib/ffmpeg/libavcodec/xvba.c xbmc-12.0.4.patch/lib/ffmpeg/libavcodec/xvba.c +--- xbmc-12.0.4/lib/ffmpeg/libavcodec/xvba.c 1970-01-01 01:00:00.000000000 +0100 ++++ xbmc-12.0.4.patch/lib/ffmpeg/libavcodec/xvba.c 2013-03-10 13:00:12.320988184 +0100 +@@ -0,0 +1,66 @@ ++/* ++ * HW decode acceleration for MPEG-2, H.264 and VC-1 ++ * ++ * Copyright (C) 2005-2011 Team XBMC ++ * ++ * This file is part of FFmpeg. ++ * ++ * FFmpeg is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU Lesser General Public ++ * License as published by the Free Software Foundation; either ++ * version 2.1 of the License, or (at your option) any later version. ++ * ++ * FFmpeg 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 ++ * Lesser General Public License for more details. ++ * ++ * You should have received a copy of the GNU Lesser General Public ++ * License along with FFmpeg; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA ++ */ ++ ++ ++/** ++ * \addtogroup XVBA_Decoding ++ * ++ * @{ ++ */ ++ ++#include ++#include "xvba.h" ++#include "xvba_internal.h" ++#include "avcodec.h" ++ ++int ff_xvba_translate_profile(int profile) { ++ ++ if (profile == 66) ++ return 1; ++ else if (profile == 77) ++ return 2; ++ else if (profile == 100) ++ return 3; ++ else if (profile == 0) ++ return 4; ++ else if (profile == 1) ++ return 5; ++ else if (profile == 3) ++ return 6; ++ else ++ return -1; ++} ++ ++void ff_xvba_add_slice_data(struct xvba_render_state *render, const uint8_t *buffer, uint32_t size) { ++ ++ render->buffers = av_fast_realloc( ++ render->buffers, ++ &render->buffers_alllocated, ++ sizeof(struct xvba_bitstream_buffers)*(render->num_slices + 1) ++ ); ++ ++ render->buffers[render->num_slices].buffer = buffer; ++ render->buffers[render->num_slices].size = size; ++ ++ render->num_slices++; ++} ++ +diff -Naur xbmc-12.0.4/lib/ffmpeg/libavcodec/xvba.h xbmc-12.0.4.patch/lib/ffmpeg/libavcodec/xvba.h +--- xbmc-12.0.4/lib/ffmpeg/libavcodec/xvba.h 1970-01-01 01:00:00.000000000 +0100 ++++ xbmc-12.0.4.patch/lib/ffmpeg/libavcodec/xvba.h 2013-03-10 13:00:12.320988184 +0100 +@@ -0,0 +1,71 @@ ++/* ++ * HW decode acceleration for MPEG-2, H.264 and VC-1 ++ * ++ * Copyright (C) 2005-2011 Team XBMC ++ * ++ * This file is part of FFmpeg. ++ * ++ * FFmpeg is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU Lesser General Public ++ * License as published by the Free Software Foundation; either ++ * version 2.1 of the License, or (at your option) any later version. ++ * ++ * FFmpeg 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 ++ * Lesser General Public License for more details. ++ * ++ * You should have received a copy of the GNU Lesser General Public ++ * License along with FFmpeg; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA ++ */ ++ ++#ifndef AVCODEC_XVBA_H ++#define AVCODEC_XVBA_H ++ ++#include ++#include ++#include ++ ++ ++/** ++ * \defgroup XVBA_Decoding VA API Decoding ++ * \ingroup Decoder ++ * @{ ++ */ ++ ++/** \brief The videoSurface is used for rendering. */ ++#define FF_XVBA_STATE_USED_FOR_RENDER 1 ++ ++/** ++ * \brief The videoSurface is needed for reference/prediction. ++ * The codec manipulates this. ++ */ ++#define FF_XVBA_STATE_USED_FOR_REFERENCE 2 ++ ++/** ++ * \brief The videoSurface holds a decoded frame. ++ * The codec manipulates this. ++ */ ++#define FF_XVBA_STATE_DECODED 4 ++ ++/* @} */ ++ ++struct xvba_bitstream_buffers ++{ ++ const void *buffer; ++ unsigned int size; ++}; ++ ++struct xvba_render_state { ++ ++ int state; ///< Holds FF_XVBA_STATE_* values. ++ void *surface; ++ XVBAPictureDescriptor *picture_descriptor; ++ XVBAQuantMatrixAvc *iq_matrix; ++ unsigned int num_slices; ++ struct xvba_bitstream_buffers *buffers; ++ uint32_t buffers_alllocated; ++}; ++ ++#endif /* AVCODEC_XVBA_H */ +diff -Naur xbmc-12.0.4/lib/ffmpeg/libavcodec/xvba_h264.c xbmc-12.0.4.patch/lib/ffmpeg/libavcodec/xvba_h264.c +--- xbmc-12.0.4/lib/ffmpeg/libavcodec/xvba_h264.c 1970-01-01 01:00:00.000000000 +0100 ++++ xbmc-12.0.4.patch/lib/ffmpeg/libavcodec/xvba_h264.c 2013-03-10 13:00:12.320988184 +0100 +@@ -0,0 +1,195 @@ ++/* ++ * H.264 HW decode acceleration through XVBA ++ * ++ * Copyright (C) 2005-2011 Team XBMC ++ * ++ * This file is part of FFmpeg. ++ * ++ * FFmpeg is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU Lesser General Public ++ * License as published by the Free Software Foundation; either ++ * version 2.1 of the License, or (at your option) any later version. ++ * ++ * FFmpeg 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 ++ * Lesser General Public License for more details. ++ * ++ * You should have received a copy of the GNU Lesser General Public ++ * License along with FFmpeg; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA ++ */ ++ ++#include "xvba.h" ++#include "xvba_internal.h" ++#include "h264.h" ++#include ++ ++/** @file ++ * This file implements the glue code between FFmpeg's and XvBA API's ++ * structures for H.264 decoding. ++ */ ++ ++ ++/** Initialize and start decoding a frame with XVBA. */ ++static int start_frame(AVCodecContext *avctx, ++ av_unused const uint8_t *buffer, ++ av_unused uint32_t size) ++{ ++ H264Context * const h = avctx->priv_data; ++ MpegEncContext * const s = &h->s; ++ struct xvba_render_state *render; ++ XVBAPictureDescriptor *pic_descriptor; ++ int i; ++ ++ render = (struct xvba_render_state *)s->current_picture_ptr->f.data[0]; ++ assert(render); ++ ++ if (render->picture_descriptor == 0) ++ return -1; ++ ++ pic_descriptor = render->picture_descriptor; ++ ++ for (i = 0; i < 2; ++i) { ++ int foc = s->current_picture_ptr->field_poc[i]; ++ if (foc == INT_MAX) ++ foc = 0; ++ pic_descriptor->avc_curr_field_order_cnt_list[i] = foc; ++ } ++ ++ pic_descriptor->avc_frame_num = h->frame_num; ++ ++ render->num_slices = 0; ++ ++ return 0; ++} ++ ++/** End a hardware decoding based frame. */ ++static int end_frame(AVCodecContext *avctx) ++{ ++ H264Context * const h = avctx->priv_data; ++ MpegEncContext * const s = &h->s; ++ struct xvba_render_state *render; ++ XVBAPictureDescriptor *pic_descriptor; ++ XVBAQuantMatrixAvc *iq_matrix; ++ ++ render = (struct xvba_render_state *)s->current_picture_ptr->f.data[0]; ++ assert(render); ++ ++ if (render->picture_descriptor == 0 || render->iq_matrix == 0) ++ return -1; ++ ++ pic_descriptor = render->picture_descriptor; ++ iq_matrix = render->iq_matrix; ++ ++ av_dlog(avctx, "end_frame()\n"); ++ ++ /* Fill in Picture Parameters*/ ++ pic_descriptor->profile = ff_xvba_translate_profile(avctx->profile); ++ pic_descriptor->level = avctx->level; ++ pic_descriptor->width_in_mb = s->mb_width; ++ pic_descriptor->height_in_mb = s->mb_height; ++ pic_descriptor->picture_structure = s->picture_structure; ++ pic_descriptor->chroma_format = s->chroma_format ? s->chroma_format : 1; ++ pic_descriptor->avc_intra_flag = (h->slice_type == AV_PICTURE_TYPE_I) ? 1 : 0; ++ pic_descriptor->avc_reference = (s->current_picture_ptr->f.reference & 3) ? 1 : 0; ++ ++ pic_descriptor->avc_bit_depth_luma_minus8 = h->sps.bit_depth_luma - 8; ++ pic_descriptor->avc_bit_depth_chroma_minus8 = h->sps.bit_depth_chroma - 8; ++ pic_descriptor->avc_log2_max_frame_num_minus4 = h->sps.log2_max_frame_num -4; ++ pic_descriptor->avc_pic_order_cnt_type = h->sps.poc_type; ++ pic_descriptor->avc_log2_max_pic_order_cnt_lsb_minus4 = h->sps.log2_max_poc_lsb - 4; ++ pic_descriptor->avc_num_ref_frames = h->sps.ref_frame_count; ++ pic_descriptor->avc_reserved_8bit = 0; ++ ++ /* Set a level that can decode stuff in every case without a lookup table ++ xvba seems to have problems only when the number of Reframes goes beyond ++ the max support number of Level4.1@High. So in praxis decoding a Level 3.0 ++ file that in deed has level4.1@High specs does not matter. We use this fact ++ and check if the ref_frames stay in the range Level4.1@high can decode if ++ not, we set Level5.1 */ ++ if (pic_descriptor->avc_num_ref_frames > 4) { ++ const unsigned int mbw = pic_descriptor->width_in_mb; ++ const unsigned int mbh = pic_descriptor->height_in_mb; ++ // this matches Level4.1@High stats to differ between <= 4.1 and 5.1 ++ const unsigned int max_ref_frames = 12288 * 1024 / (mbw * mbh * 384); ++ const unsigned int num_ref_frames = pic_descriptor->avc_num_ref_frames; ++ if (max_ref_frames < num_ref_frames) ++ pic_descriptor->level = 51; ++ } ++ ++ pic_descriptor->avc_num_slice_groups_minus1 = h->pps.slice_group_count - 1; ++ pic_descriptor->avc_num_ref_idx_l0_active_minus1 = h->pps.ref_count[0] - 1; ++ pic_descriptor->avc_num_ref_idx_l1_active_minus1 = h->pps.ref_count[1] - 1; ++ ++ pic_descriptor->avc_pic_init_qp_minus26 = h->pps.init_qp - 26; ++ pic_descriptor->avc_pic_init_qs_minus26 = h->pps.init_qs - 26; ++ pic_descriptor->avc_chroma_qp_index_offset = h->pps.chroma_qp_index_offset[0]; ++ pic_descriptor->avc_second_chroma_qp_index_offset = h->pps.chroma_qp_index_offset[1]; ++ pic_descriptor->avc_slice_group_change_rate_minus1 = 0; // not implemented in ffmpeg ++ pic_descriptor->avc_reserved_16bit = 0; // must be 0 ++ memset(pic_descriptor->avc_field_order_cnt_list,0,sizeof(pic_descriptor->avc_field_order_cnt_list)); // must be 0 ++ memset(pic_descriptor->avc_slice_group_map,0,sizeof(pic_descriptor->avc_slice_group_map)); // must be 0 ++ ++ // sps ++ pic_descriptor->sps_info.avc.delta_pic_always_zero_flag = h->sps.delta_pic_order_always_zero_flag; ++ pic_descriptor->sps_info.avc.direct_8x8_inference_flag = h->sps.direct_8x8_inference_flag; ++ pic_descriptor->sps_info.avc.frame_mbs_only_flag = h->sps.frame_mbs_only_flag; ++ pic_descriptor->sps_info.avc.gaps_in_frame_num_value_allowed_flag = h->sps.gaps_in_frame_num_allowed_flag; ++ pic_descriptor->sps_info.avc.mb_adaptive_frame_field_flag = h->sps.mb_aff; ++ pic_descriptor->sps_info.avc.residual_colour_transform_flag = h->sps.residual_color_transform_flag; ++ pic_descriptor->sps_info.avc.xvba_avc_sps_reserved = 0; ++ ++ // pps ++ pic_descriptor->pps_info.avc.entropy_coding_mode_flag = h->pps.cabac; ++ pic_descriptor->pps_info.avc.pic_order_present_flag = h->pps.pic_order_present; ++ pic_descriptor->pps_info.avc.weighted_pred_flag = h->pps.weighted_pred; ++ pic_descriptor->pps_info.avc.weighted_bipred_idc = h->pps.weighted_bipred_idc; ++ pic_descriptor->pps_info.avc.deblocking_filter_control_present_flag = h->pps.deblocking_filter_parameters_present; ++ pic_descriptor->pps_info.avc.constrained_intra_pred_flag = h->pps.constrained_intra_pred; ++ pic_descriptor->pps_info.avc.redundant_pic_cnt_present_flag = h->pps.redundant_pic_cnt_present; ++ pic_descriptor->pps_info.avc.transform_8x8_mode_flag = h->pps.transform_8x8_mode; ++ pic_descriptor->pps_info.avc.xvba_avc_pps_reserved = 0; // must be 0 ++ ++ memcpy(iq_matrix->bScalingLists4x4, h->pps.scaling_matrix4, sizeof(iq_matrix->bScalingLists4x4)); ++ memcpy(iq_matrix->bScalingLists8x8[0], h->pps.scaling_matrix8[0], sizeof(iq_matrix->bScalingLists8x8[0])); ++ memcpy(iq_matrix->bScalingLists8x8[1], h->pps.scaling_matrix8[3], sizeof(iq_matrix->bScalingLists8x8[0])); ++ ++ // Wait for an I-frame before start decoding. Workaround for ATI UVD and UVD+ GPUs ++ if (!h->got_first_iframe) { ++ if (h->slice_type != AV_PICTURE_TYPE_I && h->slice_type != AV_PICTURE_TYPE_SI) ++ return -1; ++ h->got_first_iframe = 1; ++ } ++ ++ ff_draw_horiz_band(s, 0, s->avctx->height); ++ ++ return 0; ++} ++ ++/** Decode the given H.264 slice with XVBA. */ ++static int decode_slice(AVCodecContext *avctx, ++ const uint8_t *buffer, ++ uint32_t size) ++{ ++ H264Context * const h = avctx->priv_data; ++ MpegEncContext * const s = &h->s; ++ struct xvba_render_state *render; ++ ++ render = (struct xvba_render_state *)s->current_picture_ptr->f.data[0]; ++ assert(render); ++ ++ ff_xvba_add_slice_data(render, buffer, size); ++ ++ return 0; ++} ++ ++AVHWAccel ff_h264_xvba_hwaccel = { ++ .name = "h264_xvba", ++ .type = AVMEDIA_TYPE_VIDEO, ++ .id = CODEC_ID_H264, ++ .pix_fmt = PIX_FMT_XVBA_VLD, ++ .start_frame = start_frame, ++ .end_frame = end_frame, ++ .decode_slice = decode_slice, ++}; +diff -Naur xbmc-12.0.4/lib/ffmpeg/libavcodec/xvba_internal.h xbmc-12.0.4.patch/lib/ffmpeg/libavcodec/xvba_internal.h +--- xbmc-12.0.4/lib/ffmpeg/libavcodec/xvba_internal.h 1970-01-01 01:00:00.000000000 +0100 ++++ xbmc-12.0.4.patch/lib/ffmpeg/libavcodec/xvba_internal.h 2013-03-10 13:00:12.320988184 +0100 +@@ -0,0 +1,24 @@ ++/* ++ * HW decode acceleration for MPEG-2, H.264 and VC-1 ++ * ++ * Copyright (C) 2005-2011 Team XBMC ++ * ++ * This file is part of FFmpeg. ++ * ++ * FFmpeg is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU Lesser General Public ++ * License as published by the Free Software Foundation; either ++ * version 2.1 of the License, or (at your option) any later version. ++ * ++ * FFmpeg 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 ++ * Lesser General Public License for more details. ++ * ++ * You should have received a copy of the GNU Lesser General Public ++ * License along with FFmpeg; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA ++ */ ++ ++int ff_xvba_translate_profile(int profile); ++void ff_xvba_add_slice_data(struct xvba_render_state *render, const uint8_t *buffer, uint32_t size); +diff -Naur xbmc-12.0.4/lib/ffmpeg/libavcodec/xvba_mpeg2.c xbmc-12.0.4.patch/lib/ffmpeg/libavcodec/xvba_mpeg2.c +--- xbmc-12.0.4/lib/ffmpeg/libavcodec/xvba_mpeg2.c 1970-01-01 01:00:00.000000000 +0100 ++++ xbmc-12.0.4.patch/lib/ffmpeg/libavcodec/xvba_mpeg2.c 2013-03-10 13:00:12.320988184 +0100 +@@ -0,0 +1,52 @@ ++/* ++ * MPEG-2 HW decode acceleration through XVBA ++ * ++ * Copyright (C) 2005-2011 Team XBMC ++ * ++ * This file is part of FFmpeg. ++ * ++ * FFmpeg is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU Lesser General Public ++ * License as published by the Free Software Foundation; either ++ * version 2.1 of the License, or (at your option) any later version. ++ * ++ * FFmpeg 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 ++ * Lesser General Public License for more details. ++ * ++ * You should have received a copy of the GNU Lesser General Public ++ * License along with FFmpeg; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA ++ */ ++ ++#include "dsputil.h" ++ ++static int start_frame(AVCodecContext *avctx, av_unused const uint8_t *buffer, av_unused uint32_t size) ++{ ++ struct MpegEncContext * const s = avctx->priv_data; ++ return 0; ++} ++ ++static int end_frame(AVCodecContext *avctx) ++{ ++ return 0; ++} ++ ++static int decode_slice(AVCodecContext *avctx, const uint8_t *buffer, uint32_t size) ++{ ++ struct MpegEncContext * const s = avctx->priv_data; ++ return 0; ++} ++ ++AVHWAccel ff_mpeg2_xvba_hwaccel = { ++ .name = "mpeg2_xvba", ++ .type = AVMEDIA_TYPE_VIDEO, ++ .id = CODEC_ID_MPEG2VIDEO, ++ .pix_fmt = PIX_FMT_XVBA_VLD, ++ .capabilities = 0, ++ .start_frame = start_frame, ++ .end_frame = end_frame, ++ .decode_slice = decode_slice, ++ .priv_data_size = 0, ++}; +diff -Naur xbmc-12.0.4/lib/ffmpeg/libavcodec/xvba_vc1.c xbmc-12.0.4.patch/lib/ffmpeg/libavcodec/xvba_vc1.c +--- xbmc-12.0.4/lib/ffmpeg/libavcodec/xvba_vc1.c 1970-01-01 01:00:00.000000000 +0100 ++++ xbmc-12.0.4.patch/lib/ffmpeg/libavcodec/xvba_vc1.c 2013-03-10 13:00:12.320988184 +0100 +@@ -0,0 +1,190 @@ ++/* ++ * VC-1 HW decode acceleration through XVBA ++ * ++ * Copyright (C) 2005-2011 Team XBMC ++ * ++ * This file is part of FFmpeg. ++ * ++ * FFmpeg is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU Lesser General Public ++ * License as published by the Free Software Foundation; either ++ * version 2.1 of the License, or (at your option) any later version. ++ * ++ * FFmpeg 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 ++ * Lesser General Public License for more details. ++ * ++ * You should have received a copy of the GNU Lesser General Public ++ * License along with FFmpeg; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA ++ */ ++ ++#include "xvba.h" ++#include "xvba_internal.h" ++#include "vc1.h" ++#include "vc1data.h" ++#include ++ ++ ++/** @file ++ * Implement structures of ffmpeg <-> XvBA ++ */ ++ ++/* Initialize and start decoding a frame with XvBA */ ++static int start_frame(AVCodecContext *avctx, ++ av_unused const uint8_t *buffer, ++ av_unused uint32_t size) ++{ ++ VC1Context * const v = avctx->priv_data; ++ MpegEncContext * const s = &v->s; ++ struct xvba_render_state *render; ++ ++ render = (struct xvba_render_state *)s->current_picture_ptr->f.data[0]; ++ assert(render); ++ ++ render->num_slices = 0; ++ return 0; ++} ++ ++/* End a hardware decoding based frame */ ++static int end_frame(AVCodecContext *avctx) ++{ ++ VC1Context* const v = avctx->priv_data; ++ MpegEncContext* const s = &v->s; ++ struct xvba_render_state *render, *last, *next; ++ XVBAPictureDescriptor *pic_descriptor; ++ ++ render = (struct xvba_render_state *)s->current_picture_ptr->f.data[0]; ++ assert(render); ++ ++ if (render->picture_descriptor == 0) ++ return -1; ++ ++ pic_descriptor = render->picture_descriptor; ++ ++ av_dlog(avctx, "xvba_vc1_end_frame()\n"); ++ ++ memset(pic_descriptor, 0, sizeof(*pic_descriptor)); ++ ++ /* Fill in Parameters - for reference see AMD sdk documentation */ ++ pic_descriptor->profile = ff_xvba_translate_profile(v->profile); ++ pic_descriptor->level = v->level; ++ //done like in va-driver and vaapi ++ if (v->profile == PROFILE_ADVANCED) { ++ pic_descriptor->width_in_mb = s->avctx->coded_width; ++ pic_descriptor->height_in_mb = s->avctx->coded_height; ++ } else { ++ pic_descriptor->width_in_mb = s->mb_width; ++ pic_descriptor->height_in_mb = s->mb_height; ++ } ++ pic_descriptor->picture_structure = s->picture_structure; ++ // xvba-video set this to 1 only 4:2:0 supported ++ // doc says: if not set, choose 1 - we try this ++ pic_descriptor->chroma_format = 1; ++ pic_descriptor->avc_intra_flag = s->pict_type == AV_PICTURE_TYPE_I || v->bi_type == 1; ++ pic_descriptor->avc_reference = (s->current_picture_ptr->f.reference & 3) ? 1 : 0; ++ ++ // VC-1 explicit parameters see page 30 of sdk ++ // sps_info ++ pic_descriptor->sps_info.vc1.postprocflag = v->postprocflag; ++ ++ // done as in vaapi ++ pic_descriptor->sps_info.vc1.pulldown = v->broadcast; ++ pic_descriptor->sps_info.vc1.interlace = v->interlace; ++ pic_descriptor->sps_info.vc1.tfcntrflag = v->tfcntrflag; ++ pic_descriptor->sps_info.vc1.finterpflag = v->finterpflag; ++ pic_descriptor->sps_info.vc1.reserved = 1; ++ // eventually check if this makes sense together with interlace ++ pic_descriptor->sps_info.vc1.psf = v->psf; ++ // what about if it is a frame (page 31) ++ // looked at xvba-driver ++ pic_descriptor->sps_info.vc1.second_field = !s->first_field; ++ pic_descriptor->sps_info.vc1.xvba_vc1_sps_reserved = 0; ++ ++ // VC-1 explicit parameters see page 30 of sdk ++ // pps_info ++ pic_descriptor->pps_info.vc1.panscan_flag = v->panscanflag; ++ pic_descriptor->pps_info.vc1.refdist_flag = v->refdist_flag; ++ pic_descriptor->pps_info.vc1.loopfilter = s->loop_filter; ++ pic_descriptor->pps_info.vc1.fastuvmc = v->fastuvmc; ++ pic_descriptor->pps_info.vc1.extended_mv = v->extended_mv; ++ pic_descriptor->pps_info.vc1.dquant = v->dquant; ++ pic_descriptor->pps_info.vc1.vstransform = v->vstransform; ++ pic_descriptor->pps_info.vc1.overlap = v->overlap; ++ pic_descriptor->pps_info.vc1.quantizer = v->quantizer_mode; ++ pic_descriptor->pps_info.vc1.extended_dmv = v->extended_dmv; ++ pic_descriptor->pps_info.vc1.maxbframes = s->avctx->max_b_frames; ++ pic_descriptor->pps_info.vc1.rangered = (pic_descriptor->profile == PROFILE_SIMPLE) ? 0 : v->rangered; ++ pic_descriptor->pps_info.vc1.syncmarker = (pic_descriptor->profile == PROFILE_SIMPLE) ? 0 : s->resync_marker; ++ pic_descriptor->pps_info.vc1.multires = v->multires; ++ pic_descriptor->pps_info.vc1.reserved = 1; ++ pic_descriptor->pps_info.vc1.range_mapy_flag = v->range_mapy_flag; ++ pic_descriptor->pps_info.vc1.range_mapy = v->range_mapy; ++ pic_descriptor->pps_info.vc1.range_mapuv_flag = v->range_mapuv_flag; ++ pic_descriptor->pps_info.vc1.range_mapuv = v->range_mapuv; ++ pic_descriptor->pps_info.vc1.xvba_vc1_pps_reserved = 0; ++ ++ pic_descriptor->past_surface = 0; ++ pic_descriptor->future_surface = 0; ++ switch (s->pict_type) { ++ case AV_PICTURE_TYPE_B: ++ next = (struct xvba_render_state *)s->next_picture.f.data[0]; ++ assert(next); ++ if (next) ++ pic_descriptor->past_surface = next->surface; ++ // fall-through ++ case AV_PICTURE_TYPE_P: ++ last = (struct xvba_render_state *)s->last_picture.f.data[0]; ++ assert(last); ++ if (last) ++ pic_descriptor->future_surface = last->surface; ++ break; ++ } ++ ++ ff_draw_horiz_band(s, 0, s->avctx->height); ++ ++ return 0; ++} ++ ++static int decode_slice(AVCodecContext *avctx, const uint8_t *buffer, uint32_t size) ++{ ++ VC1Context* const v = avctx->priv_data; ++ MpegEncContext* const s = &v->s; ++ struct xvba_render_state *render; ++ ++ render = (struct xvba_render_state *)s->current_picture_ptr->f.data[0]; ++ assert(render); ++ ++ if (avctx->codec_id == CODEC_ID_VC1 && ++ size >= 4 && IS_MARKER(AV_RB32(buffer))) { ++ buffer += 4; ++ size -= 4; ++ } ++ ++ ff_xvba_add_slice_data(render, buffer, size); ++ ++ return 0; ++} ++ ++#if CONFIG_WMV3_XVBA_HWACCEL ++AVHWAccel ff_wmv3_xvba_hwaccel = { ++ .name = "wmv3_xvba", ++ .type = AVMEDIA_TYPE_VIDEO, ++ .id = CODEC_ID_WMV3, ++ .pix_fmt = PIX_FMT_XVBA_VLD, ++ .start_frame = start_frame, ++ .end_frame = end_frame, ++ .decode_slice = decode_slice, ++}; ++#endif ++ ++AVHWAccel ff_vc1_xvba_hwaccel = { ++ .name = "vc1_xvba", ++ .type = AVMEDIA_TYPE_VIDEO, ++ .id = CODEC_ID_VC1, ++ .pix_fmt = PIX_FMT_XVBA_VLD, ++ .start_frame = start_frame, ++ .end_frame = end_frame, ++ .decode_slice = decode_slice, ++}; +diff -Naur xbmc-12.0.4/lib/ffmpeg/libavcodec/xvmc_internal.h xbmc-12.0.4.patch/lib/ffmpeg/libavcodec/xvmc_internal.h +--- xbmc-12.0.4/lib/ffmpeg/libavcodec/xvmc_internal.h 2013-03-08 13:01:44.000000000 +0100 ++++ xbmc-12.0.4.patch/lib/ffmpeg/libavcodec/xvmc_internal.h 2013-03-10 13:00:12.321988177 +0100 +@@ -1,5 +1,7 @@ + /* +- * XVideo Motion Compensation internal functions ++ * HW decode acceleration for MPEG-2, H.264 and VC-1 ++ * ++ * Copyright (C) 2005-2011 Team XBMC + * + * This file is part of FFmpeg. + * +diff -Naur xbmc-12.0.4/lib/ffmpeg/libavutil/pixdesc.c xbmc-12.0.4.patch/lib/ffmpeg/libavutil/pixdesc.c +--- xbmc-12.0.4/lib/ffmpeg/libavutil/pixdesc.c 2013-03-08 13:01:41.000000000 +0100 ++++ xbmc-12.0.4.patch/lib/ffmpeg/libavutil/pixdesc.c 2013-03-10 13:00:12.321988177 +0100 +@@ -874,6 +874,12 @@ + .log2_chroma_h = 1, + .flags = PIX_FMT_HWACCEL, + }, ++ [PIX_FMT_XVBA_VLD] = { ++ .name = "xvba_vld", ++ .log2_chroma_w = 1, ++ .log2_chroma_h = 1, ++ .flags = PIX_FMT_HWACCEL, ++ }, + [PIX_FMT_YUV420P9LE] = { + .name = "yuv420p9le", + .nb_components = 3, +diff -Naur xbmc-12.0.4/lib/ffmpeg/libavutil/pixfmt.h xbmc-12.0.4.patch/lib/ffmpeg/libavutil/pixfmt.h +--- xbmc-12.0.4/lib/ffmpeg/libavutil/pixfmt.h 2013-03-08 13:01:41.000000000 +0100 ++++ xbmc-12.0.4.patch/lib/ffmpeg/libavutil/pixfmt.h 2013-03-10 13:00:12.321988177 +0100 +@@ -129,6 +129,7 @@ + PIX_FMT_YUV444P16BE, ///< planar YUV 4:4:4, 48bpp, (1 Cr & Cb sample per 1x1 Y samples), big-endian + PIX_FMT_VDPAU_MPEG4, ///< MPEG4 HW decoding with VDPAU, data[0] contains a vdpau_render_state struct which contains the bitstream of the slices as well as various fields extracted from headers + PIX_FMT_DXVA2_VLD, ///< HW decoding through DXVA2, Picture.data[3] contains a LPDIRECT3DSURFACE9 pointer ++ PIX_FMT_XVBA_VLD, ///< HW decoding through DXVA2, Picture.data[3] contains a vaapi_render_state struct which contains the bitstream of the slices as well as various fields extracted from headers + + PIX_FMT_RGB444LE, ///< packed RGB 4:4:4, 16bpp, (msb)4A 4R 4G 4B(lsb), little-endian, most significant bits to 0 + PIX_FMT_RGB444BE, ///< packed RGB 4:4:4, 16bpp, (msb)4A 4R 4G 4B(lsb), big-endian, most significant bits to 0 +diff -Naur xbmc-12.0.4/system/shaders/yuv2rgb_basic.glsl xbmc-12.0.4.patch/system/shaders/yuv2rgb_basic.glsl +--- xbmc-12.0.4/system/shaders/yuv2rgb_basic.glsl 2013-03-08 13:01:46.000000000 +0100 ++++ xbmc-12.0.4.patch/system/shaders/yuv2rgb_basic.glsl 2013-03-10 13:00:12.294988371 +0100 +@@ -70,6 +70,18 @@ + rgb.a = gl_Color.a; + gl_FragColor = rgb; + ++#elif defined(XBMC_VDPAU_NV12) ++ ++ vec4 yuv, rgb; ++ yuv.rgba = vec4( texture2D(m_sampY, stretch(m_cordY)).r ++ , texture2D(m_sampU, stretch(m_cordU)).r ++ , texture2D(m_sampV, stretch(m_cordV)).g ++ , 1.0 ); ++ ++ rgb = m_yuvmat * yuv; ++ rgb.a = gl_Color.a; ++ gl_FragColor = rgb; ++ + #elif defined(XBMC_YUY2) || defined(XBMC_UYVY) + + #if(XBMC_texture_rectangle) +diff -Naur xbmc-12.0.4/xbmc/Application.cpp xbmc-12.0.4.patch/xbmc/Application.cpp +--- xbmc-12.0.4/xbmc/Application.cpp 2013-03-08 13:01:28.000000000 +0100 ++++ xbmc-12.0.4.patch/xbmc/Application.cpp 2013-03-10 13:00:12.308988270 +0100 @@ -419,8 +419,6 @@ #endif m_currentStack = new CFileItemList; @@ -1371,7 +1049,16 @@ index efb3ac0..5c7017c 100644 m_bPresentFrame = false; m_bPlatformDirectories = true; -@@ -2231,28 +2229,18 @@ float CApplication::GetDimScreenSaverLevel() const +@@ -796,7 +794,7 @@ + + uint32_t sdlFlags = 0; + +-#if defined(HAS_SDL_OPENGL) || (HAS_GLES == 2) ++#if (defined(HAS_SDL_OPENGL) || (HAS_GLES == 2)) && !defined(HAS_GLX) + sdlFlags |= SDL_INIT_VIDEO; + #endif + +@@ -2231,28 +2229,18 @@ bool CApplication::WaitFrame(unsigned int timeout) { @@ -1405,7 +1092,7 @@ index efb3ac0..5c7017c 100644 } void CApplication::Render() -@@ -2272,7 +2260,6 @@ void CApplication::Render() +@@ -2272,7 +2260,6 @@ int vsync_mode = g_guiSettings.GetInt("videoscreen.vsync"); @@ -1413,7 +1100,7 @@ index efb3ac0..5c7017c 100644 bool hasRendered = false; bool limitFrames = false; unsigned int singleFrameTime = 10; // default limit 100 fps -@@ -2286,13 +2273,10 @@ void CApplication::Render() +@@ -2286,13 +2273,10 @@ m_bPresentFrame = false; if (!extPlayerActive && g_graphicsContext.IsFullScreenVideo() && !IsPaused()) { @@ -1431,7 +1118,7 @@ index efb3ac0..5c7017c 100644 hasRendered = true; } else -@@ -2316,8 +2300,6 @@ void CApplication::Render() +@@ -2316,8 +2300,6 @@ else if (lowfps) singleFrameTime = 200; // 5 fps, <=200 ms latency to wake up } @@ -1440,7 +1127,17 @@ index efb3ac0..5c7017c 100644 } } -@@ -2381,13 +2363,6 @@ void CApplication::Render() +@@ -2371,20 +2353,16 @@ + m_lastFrameTime = XbmcThreads::SystemClockMillis(); + + if (flip) ++ { + g_graphicsContext.Flip(dirtyRegions); ++ g_renderManager.NotifyDisplayFlip(); ++ } + CTimeUtils::UpdateFrameTime(flip); + + g_TextureManager.FreeUnusedTextures(); g_renderManager.UpdateResolution(); g_renderManager.ManageCaptures(); @@ -1454,7 +1151,7 @@ index efb3ac0..5c7017c 100644 } void CApplication::SetStandAlone(bool value) -@@ -5633,12 +5608,6 @@ bool CApplication::SwitchToFullScreen() +@@ -5630,12 +5608,6 @@ // See if we're playing a video, and are in GUI mode if ( IsPlayingVideo() && g_windowManager.GetActiveWindow() != WINDOW_FULLSCREEN_VIDEO) { @@ -1467,7 +1164,7 @@ index efb3ac0..5c7017c 100644 // then switch to fullscreen mode g_windowManager.ActivateWindow(WINDOW_FULLSCREEN_VIDEO); return true; -@@ -5871,7 +5840,6 @@ bool CApplication::IsCurrentThread() const +@@ -5868,7 +5840,6 @@ bool CApplication::IsPresentFrame() { @@ -1475,11 +1172,10 @@ index efb3ac0..5c7017c 100644 bool ret = m_bPresentFrame; return ret; -diff --git a/xbmc/Application.h b/xbmc/Application.h -index 69609fa..6764a60 100644 ---- a/xbmc/Application.h -+++ b/xbmc/Application.h -@@ -422,10 +422,8 @@ class CApplication : public CXBApplicationEx, public IPlayerCallback, public IMs +diff -Naur xbmc-12.0.4/xbmc/Application.h xbmc-12.0.4.patch/xbmc/Application.h +--- xbmc-12.0.4/xbmc/Application.h 2013-03-08 13:01:27.000000000 +0100 ++++ xbmc-12.0.4.patch/xbmc/Application.h 2013-03-10 13:00:12.283988450 +0100 +@@ -422,10 +422,8 @@ bool m_bEnableLegacyRes; bool m_bTestMode; bool m_bSystemScreenSaverEnable; @@ -1492,2786 +1188,35 @@ index 69609fa..6764a60 100644 VIDEO::CVideoInfoScanner *m_videoInfoScanner; MUSIC_INFO::CMusicInfoScanner *m_musicInfoScanner; -diff --git a/xbmc/cores/VideoRenderers/RenderManager.cpp b/xbmc/cores/VideoRenderers/RenderManager.cpp -index c13f83d..35aba7e 100644 ---- a/xbmc/cores/VideoRenderers/RenderManager.cpp -+++ b/xbmc/cores/VideoRenderers/RenderManager.cpp -@@ -1102,3 +1102,14 @@ void CXBMCRenderManager::NotifyDisplayFlip() - lock.Leave(); - m_flipEvent.Set(); - } -+ -+bool CXBMCRenderManager::HasFrame() -+{ -+ CSharedLock lock(m_sharedSection); -+ if (m_presentstep == PRESENT_IDLE && -+ GetNextRenderBufferIndex() < 0 && -+ m_speed > 0) -+ return false; -+ else -+ return true; -+} -diff --git a/xbmc/cores/VideoRenderers/RenderManager.h b/xbmc/cores/VideoRenderers/RenderManager.h -index 96ab53f..1e44233 100644 ---- a/xbmc/cores/VideoRenderers/RenderManager.h -+++ b/xbmc/cores/VideoRenderers/RenderManager.h -@@ -148,6 +148,7 @@ class CXBMCRenderManager - * display becomes available for player to deliver a new frame. - */ - void NotifyDisplayFlip(); -+ bool HasFrame(); - void EnableBuffering(bool enable); - void DiscardBuffer(); - --- -1.7.10 - - -From 61ece20a4691e8d7f6203054bdc1a5fc5e9b84ab Mon Sep 17 00:00:00 2001 -From: xbmc -Date: Mon, 28 May 2012 11:02:29 +0200 -Subject: [PATCH 07/88] vaapi: adopt to buffering in renderer - ---- - xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.cpp | 2 +- - xbmc/cores/dvdplayer/DVDCodecs/Video/VAAPI.cpp | 3 ++- - xbmc/cores/dvdplayer/DVDCodecs/Video/VAAPI.h | 1 + - 3 files changed, 4 insertions(+), 2 deletions(-) - -diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.cpp b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.cpp -index 8f81637..286fd67 100644 ---- a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.cpp -+++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.cpp -@@ -106,7 +106,7 @@ enum PixelFormat CDVDVideoCodecFFmpeg::GetFormat( struct AVCodecContext * avctx - && (avctx->codec_id != CODEC_ID_MPEG4 || g_advancedSettings.m_videoAllowMpeg4VAAPI)) - { - VAAPI::CDecoder* dec = new VAAPI::CDecoder(); -- if(dec->Open(avctx, *cur)) -+ if(dec->Open(avctx, *cur, ctx->m_uSurfacesCount)) - { - ctx->SetHardware(dec); - return *cur; -diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/VAAPI.cpp b/xbmc/cores/dvdplayer/DVDCodecs/Video/VAAPI.cpp -index 9f5a960..a2b9195 100644 ---- a/xbmc/cores/dvdplayer/DVDCodecs/Video/VAAPI.cpp -+++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/VAAPI.cpp -@@ -357,6 +357,7 @@ bool CDecoder::Open(AVCodecContext *avctx, enum PixelFormat fmt, unsigned int su - CHECK(vaCreateConfig(m_display->get(), profile, entrypoint, &attrib, 1, &m_hwaccel->config_id)) - m_config = m_hwaccel->config_id; - -+ m_renderbuffers_count = surfaces; - if (!EnsureContext(avctx)) - return false; - -@@ -388,7 +389,7 @@ bool CDecoder::EnsureContext(AVCodecContext *avctx) - else - m_refs = 2; - } -- return EnsureSurfaces(avctx, m_refs + 3); -+ return EnsureSurfaces(avctx, m_refs + m_renderbuffers_count + 1); - } - - bool CDecoder::EnsureSurfaces(AVCodecContext *avctx, unsigned n_surfaces_count) -diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/VAAPI.h b/xbmc/cores/dvdplayer/DVDCodecs/Video/VAAPI.h -index 863edc4..417cbc0 100644 ---- a/xbmc/cores/dvdplayer/DVDCodecs/Video/VAAPI.h -+++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/VAAPI.h -@@ -122,6 +122,7 @@ class CDecoder - static const unsigned m_surfaces_max = 32; - unsigned m_surfaces_count; - VASurfaceID m_surfaces[m_surfaces_max]; -+ unsigned m_renderbuffers_count; - - int m_refs; - std::list m_surfaces_used; --- -1.7.10 - - -From ab9b5a5d746f712a0d3e5332cc191d129fc3a175 Mon Sep 17 00:00:00 2001 -From: xbmc -Date: Sat, 16 Feb 2013 20:17:29 +0100 -Subject: [PATCH 08/88] add buffering - some documentation - ---- - xbmc/cores/IPlayer.h | 3 +++ - xbmc/cores/VideoRenderers/RenderManager.h | 40 +++++++++++++++++++++++++++++ - 2 files changed, 43 insertions(+) - -diff --git a/xbmc/cores/IPlayer.h b/xbmc/cores/IPlayer.h -index eb654ec..cbf2faa 100644 ---- a/xbmc/cores/IPlayer.h -+++ b/xbmc/cores/IPlayer.h -@@ -229,6 +229,9 @@ class IPlayer - */ - virtual void GetSubtitleCapabilities(std::vector &subCaps) { subCaps.assign(1,IPC_SUBS_ALL); }; - -+ /*! -+ \brief called by RenderManager in order to schedule frames -+ */ - virtual double GetClock(double& absolute, bool interpolated = true) {return 0; }; - - protected: -diff --git a/xbmc/cores/VideoRenderers/RenderManager.h b/xbmc/cores/VideoRenderers/RenderManager.h -index 1e44233..49da2ed 100644 ---- a/xbmc/cores/VideoRenderers/RenderManager.h -+++ b/xbmc/cores/VideoRenderers/RenderManager.h -@@ -66,11 +66,38 @@ class CXBMCRenderManager - void SetViewMode(int iViewMode); - - // 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 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 buffering enable buffering in renderer, defaults to false -+ */ - 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, bool buffering = false); - bool IsConfigured(); - - int AddVideoPicture(DVDVideoPicture& picture); - -+ /** -+ * Called by video player to flip render buffers -+ * If buffering is enabled this method does not block. In case of disabled buffering -+ * this method blocks waiting for the render thread to pass by. -+ * When buffering is used there might be no free buffer available after the call to -+ * this method. Player has to call WaitForBuffer. A free buffer will become -+ * available after the main thread has flipped front / back buffers. -+ * -+ * @param bStop reference to stop flag of calling thread -+ * @param timestamp pts of frame delivered with AddVideoPicture -+ * @param source depreciated -+ * @param sync signals frame, top, or bottom field -+ * @param speed current speed of player, needed for some optimizations like keeping the gui responsive on rewind -+ */ - void FlipPage(volatile bool& bStop, double timestamp = 0.0, int source = -1, EFIELDSYNC sync = FS_NONE, int speed = 1000); - unsigned int PreInit(); - void UnInit(); -@@ -148,8 +175,21 @@ class CXBMCRenderManager - * display becomes available for player to deliver a new frame. - */ - void NotifyDisplayFlip(); -+ -+ /** -+ * Called by application (main thread) to query if there is any frame to render -+ */ - bool HasFrame(); -+ -+ /** -+ * Video player can dynamically enable/disable buffering. In situations like -+ * rewind buffering is not ideal. -+ */ - void EnableBuffering(bool enable); -+ -+ /** -+ * Video player call this on flush in oder to discard any queued frames -+ */ - void DiscardBuffer(); - - protected: --- -1.7.10 - - -From 9d2f1cbcf647826f3449fb58c995a478bfd0697c Mon Sep 17 00:00:00 2001 -From: xbmc -Date: Mon, 18 Feb 2013 10:42:00 +0100 -Subject: [PATCH 09/88] RenderManager: only flip free buffer if player has - added something - ---- - xbmc/cores/VideoRenderers/RenderManager.cpp | 29 +++++++++++++++++++++++---- - xbmc/cores/VideoRenderers/RenderManager.h | 7 ++----- - 2 files changed, 27 insertions(+), 9 deletions(-) - -diff --git a/xbmc/cores/VideoRenderers/RenderManager.cpp b/xbmc/cores/VideoRenderers/RenderManager.cpp -index 35aba7e..f5cc0f6 100644 ---- a/xbmc/cores/VideoRenderers/RenderManager.cpp -+++ b/xbmc/cores/VideoRenderers/RenderManager.cpp -@@ -612,10 +612,12 @@ void CXBMCRenderManager::FlipPage(volatile bool& bStop, double timestamp /* = 0L - } - } - -- FlipFreeBuffer(); -- m_renderBuffers[m_iOutputRenderBuffer].pts = timestamp; -- m_renderBuffers[m_iOutputRenderBuffer].presentfield = presentfield; -- m_renderBuffers[m_iOutputRenderBuffer].presentmethod = presentmethod; -+ if (FlipFreeBuffer() >= 0) -+ { -+ m_renderBuffers[m_iOutputRenderBuffer].pts = timestamp; -+ m_renderBuffers[m_iOutputRenderBuffer].presentfield = presentfield; -+ m_renderBuffers[m_iOutputRenderBuffer].presentmethod = presentmethod; -+ } - m_speed = speed; - } - -@@ -825,7 +827,10 @@ int CXBMCRenderManager::AddVideoPicture(DVDVideoPicture& pic) - return -1; - - if(m_pRenderer->AddVideoPicture(&pic, (m_iOutputRenderBuffer + 1) % m_iNumRenderBuffers)) -+ { -+ m_bRenderBufferUsed = true; - return 1; -+ } - - YV12Image image; - int index = m_pRenderer->GetImage(&image, (m_iOutputRenderBuffer + 1) % m_iNumRenderBuffers); -@@ -870,9 +875,17 @@ int CXBMCRenderManager::AddVideoPicture(DVDVideoPicture& pic) +diff -Naur xbmc-12.0.4/xbmc/cores/dvdplayer/DVDCodecs/DVDFactoryCodec.cpp xbmc-12.0.4.patch/xbmc/cores/dvdplayer/DVDCodecs/DVDFactoryCodec.cpp +--- xbmc-12.0.4/xbmc/cores/dvdplayer/DVDCodecs/DVDFactoryCodec.cpp 2013-03-08 13:01:31.000000000 +0100 ++++ xbmc-12.0.4.patch/xbmc/cores/dvdplayer/DVDCodecs/DVDFactoryCodec.cpp 2013-03-10 13:00:12.325988148 +0100 +@@ -169,6 +169,11 @@ + #elif defined(_LINUX) && !defined(TARGET_DARWIN) + hwSupport += "VAAPI:no "; #endif - m_pRenderer->ReleaseImage(index, false); - -+ m_bRenderBufferUsed = true; - return index; - } - -+void CXBMCRenderManager::AddOverlay(CDVDOverlay* o, double pts) -+{ -+ CSharedLock lock(m_sharedSection); -+ m_overlays.AddOverlay(o, pts, (m_iOutputRenderBuffer + 1) % m_iNumRenderBuffers); -+ m_bRenderBufferUsed = true; -+} -+ - bool CXBMCRenderManager::Supports(ERENDERFEATURE feature) - { - CSharedLock lock(m_sharedSection); -@@ -973,10 +986,17 @@ int CXBMCRenderManager::FlipFreeBuffer() - // See "Render Buffer State Description" in header for information. - if (HasFreeBuffer()) - { -+ if (!m_bRenderBufferUsed) -+ { -+ return -1; -+ } -+ m_bRenderBufferUsed = false; - m_bAllRenderBuffersDisplayed = false; - m_iOutputRenderBuffer = (m_iOutputRenderBuffer + 1) % m_iNumRenderBuffers; - return m_iOutputRenderBuffer; - } -+ else -+ return -1; - } - - bool CXBMCRenderManager::HasFreeBuffer() -@@ -1017,6 +1037,7 @@ void CXBMCRenderManager::ResetRenderBuffer() - m_sleeptime = 1.0; - m_presentPts = DVD_NOPTS_VALUE; - m_speed = 0; -+ m_bRenderBufferUsed = false; - } - - void CXBMCRenderManager::PrepareNextRender() -diff --git a/xbmc/cores/VideoRenderers/RenderManager.h b/xbmc/cores/VideoRenderers/RenderManager.h -index 49da2ed..afb6b1f 100644 ---- a/xbmc/cores/VideoRenderers/RenderManager.h -+++ b/xbmc/cores/VideoRenderers/RenderManager.h -@@ -103,11 +103,7 @@ class CXBMCRenderManager - void UnInit(); - bool Flush(); - -- void AddOverlay(CDVDOverlay* o, double pts) -- { -- CSharedLock lock(m_sharedSection); -- m_overlays.AddOverlay(o, pts, (m_iOutputRenderBuffer + 1) % m_iNumRenderBuffers); -- } -+ void AddOverlay(CDVDOverlay* o, double pts); - - void AddCleanup(OVERLAY::COverlay* o) - { -@@ -255,6 +251,7 @@ class CXBMCRenderManager - bool m_bUseBuffering; - bool m_bCodecSupportsBuffering; - int m_speed; -+ bool m_bRenderBufferUsed; - CEvent m_flipEvent; - - struct --- -1.7.10 - - -From d4d025be1cd04effdc90d6b6103097ce193067a0 Mon Sep 17 00:00:00 2001 -From: xbmc -Date: Tue, 19 Feb 2013 09:06:22 +0100 -Subject: [PATCH 10/88] move NUM_BUFFERS up to BaseRenderer.h - ---- - xbmc/cores/VideoRenderers/BaseRenderer.h | 3 ++- - xbmc/cores/VideoRenderers/LinuxRendererGL.h | 2 -- - xbmc/cores/VideoRenderers/LinuxRendererGLES.h | 2 -- - xbmc/cores/VideoRenderers/OverlayRenderer.cpp | 2 +- - xbmc/cores/VideoRenderers/OverlayRenderer.h | 3 ++- - xbmc/cores/VideoRenderers/WinRenderer.h | 2 -- - 6 files changed, 5 insertions(+), 9 deletions(-) - -diff --git a/xbmc/cores/VideoRenderers/BaseRenderer.h b/xbmc/cores/VideoRenderers/BaseRenderer.h -index aa1e4ae..60b7197 100644 ---- a/xbmc/cores/VideoRenderers/BaseRenderer.h -+++ b/xbmc/cores/VideoRenderers/BaseRenderer.h -@@ -26,10 +26,11 @@ - - #define MAX_PLANES 3 - #define MAX_FIELDS 3 -+#define NUM_BUFFERS 10 - - typedef struct YV12Image - { -- BYTE * plane[MAX_PLANES]; -+ uint8_t* plane[MAX_PLANES]; - int planesize[MAX_PLANES]; - unsigned stride[MAX_PLANES]; - unsigned width; -diff --git a/xbmc/cores/VideoRenderers/LinuxRendererGL.h b/xbmc/cores/VideoRenderers/LinuxRendererGL.h -index 7c9fcae..a7b5886 100644 ---- a/xbmc/cores/VideoRenderers/LinuxRendererGL.h -+++ b/xbmc/cores/VideoRenderers/LinuxRendererGL.h -@@ -44,8 +44,6 @@ - namespace Shaders { class BaseVideoFilterShader; } - namespace VAAPI { struct CHolder; } - --#define NUM_BUFFERS 10 -- - - #undef ALIGN - #define ALIGN(value, alignment) (((value)+((alignment)-1))&~((alignment)-1)) -diff --git a/xbmc/cores/VideoRenderers/LinuxRendererGLES.h b/xbmc/cores/VideoRenderers/LinuxRendererGLES.h -index 5bae10d..fe32eff 100644 ---- a/xbmc/cores/VideoRenderers/LinuxRendererGLES.h -+++ b/xbmc/cores/VideoRenderers/LinuxRendererGLES.h -@@ -41,8 +41,6 @@ - class COpenMaxVideo; - typedef std::vector Features; - --#define NUM_BUFFERS 10 -- - - #undef ALIGN - #define ALIGN(value, alignment) (((value)+((alignment)-1))&~((alignment)-1)) -diff --git a/xbmc/cores/VideoRenderers/OverlayRenderer.cpp b/xbmc/cores/VideoRenderers/OverlayRenderer.cpp -index f7f74ce..5236390 100644 ---- a/xbmc/cores/VideoRenderers/OverlayRenderer.cpp -+++ b/xbmc/cores/VideoRenderers/OverlayRenderer.cpp -@@ -93,7 +93,7 @@ long COverlayMainThread::Release() - - CRenderer::~CRenderer() - { -- for(int i = 0; i < 10; i++) -+ for(int i = 0; i < NUM_BUFFERS; i++) - Release(m_buffers[i]); - } - -diff --git a/xbmc/cores/VideoRenderers/OverlayRenderer.h b/xbmc/cores/VideoRenderers/OverlayRenderer.h -index 0921fc5..66c592a 100644 ---- a/xbmc/cores/VideoRenderers/OverlayRenderer.h -+++ b/xbmc/cores/VideoRenderers/OverlayRenderer.h -@@ -23,6 +23,7 @@ - #pragma once - - #include "threads/CriticalSection.h" -+#include "BaseRenderer.h" - - #include - -@@ -126,7 +127,7 @@ - void Release(SElementV& list); - - CCriticalSection m_section; -- SElementV m_buffers[10]; -+ SElementV m_buffers[NUM_BUFFERS]; - int m_iNumBuffers; - int m_decode; - int m_render; -diff --git a/xbmc/cores/VideoRenderers/WinRenderer.h b/xbmc/cores/VideoRenderers/WinRenderer.h -index b3448ed..b099697 100644 ---- a/xbmc/cores/VideoRenderers/WinRenderer.h -+++ b/xbmc/cores/VideoRenderers/WinRenderer.h -@@ -32,8 +32,6 @@ - #include "cores/VideoRenderers/RenderFlags.h" - #include "cores/VideoRenderers/RenderFormats.h" - --#define NUM_BUFFERS 10 -- - #define ALIGN(value, alignment) (((value)+((alignment)-1))&~((alignment)-1)) - #define CLAMP(a, min, max) ((a) > (max) ? (max) : ( (a) < (min) ? (min) : a )) - --- -1.7.10 - - -From 08665778e71d52fa461150f596dd18de1035915f Mon Sep 17 00:00:00 2001 -From: xbmc -Date: Sun, 24 Feb 2013 09:55:00 +0100 -Subject: [PATCH 11/88] OverlayRenderer: align buffers with index in - renderManager - ---- - xbmc/cores/VideoRenderers/OverlayRenderer.cpp | 26 ++++++++++++++++--------- - xbmc/cores/VideoRenderers/OverlayRenderer.h | 8 ++++---- - xbmc/cores/VideoRenderers/RenderManager.cpp | 11 +++++++---- - xbmc/cores/VideoRenderers/RenderManager.h | 1 + - 4 files changed, 29 insertions(+), 17 deletions(-) - -diff --git a/xbmc/cores/VideoRenderers/OverlayRenderer.cpp b/xbmc/cores/VideoRenderers/OverlayRenderer.cpp -index 5236390..5592eca 100644 ---- a/xbmc/cores/VideoRenderers/OverlayRenderer.cpp -+++ b/xbmc/cores/VideoRenderers/OverlayRenderer.cpp -@@ -127,27 +127,32 @@ void CRenderer::AddCleanup(COverlay* o) - m_cleanup.push_back(o->Acquire()); - } - --void CRenderer::Release(SElementV& list) -+long CRenderer::Release(SElementV& list) - { - SElementV l = list; - list.clear(); - -+ long count = 0; - for(SElementV::iterator it = l.begin(); it != l.end(); it++) - { - if(it->overlay) -- it->overlay->Release(); -+ count += it->overlay->Release(); - if(it->overlay_dvd) -- it->overlay_dvd->Release(); -+ count += it->overlay_dvd->Release(); - } -+ return count; - } - --void CRenderer::Release(COverlayV& list) -+long CRenderer::Release(COverlayV& list) - { - COverlayV l = list; - list.clear(); - -+ long count = 0; - for(COverlayV::iterator it = l.begin(); it != l.end(); it++) -- (*it)->Release(); -+ count += (*it)->Release(); -+ -+ return count; - } - - void CRenderer::Flush() -@@ -161,16 +166,19 @@ void CRenderer::Flush() - Release(m_cleanup); - } - --void CRenderer::Flip() -+void CRenderer::Flip(int source) - { - CSingleLock lock(m_section); -- m_render = (m_render + 1) % m_iNumBuffers; -+ if( source >= 0 && source < m_iNumBuffers ) -+ m_render = source; -+ else -+ m_render = (m_render + 1) % m_iNumBuffers; - } - --void CRenderer::ReleaseBuffer(int idx) -+long CRenderer::ReleaseBuffer(int idx) - { - CSingleLock lock(m_section); -- Release(m_buffers[idx]); -+ return Release(m_buffers[idx]); - } - - void CRenderer::Render() -diff --git a/xbmc/cores/VideoRenderers/OverlayRenderer.h b/xbmc/cores/VideoRenderers/OverlayRenderer.h -index 66c592a..627dd9f 100644 ---- a/xbmc/cores/VideoRenderers/OverlayRenderer.h -+++ b/xbmc/cores/VideoRenderers/OverlayRenderer.h -@@ -96,11 +96,11 @@ - void AddOverlay(CDVDOverlay* o, double pts, int index); - void AddOverlay(COverlay* o, double pts, int index); - void AddCleanup(COverlay* o); -- void Flip(); -+ void Flip(int source); - void Render(); - void Flush(); - void SetNumBuffers(int numBuffers) { m_iNumBuffers = numBuffers; } -- void ReleaseBuffer(int idx); -+ long ReleaseBuffer(int idx); - - protected: - -@@ -123,8 +123,8 @@ - COverlay* Convert(CDVDOverlay* o, double pts); - COverlay* Convert(CDVDOverlaySSA* o, double pts); - -- void Release(COverlayV& list); -- void Release(SElementV& list); -+ long Release(COverlayV& list); -+ long Release(SElementV& list); - - CCriticalSection m_section; - SElementV m_buffers[NUM_BUFFERS]; -diff --git a/xbmc/cores/VideoRenderers/RenderManager.cpp b/xbmc/cores/VideoRenderers/RenderManager.cpp -index f5cc0f6..e887313 100644 ---- a/xbmc/cores/VideoRenderers/RenderManager.cpp -+++ b/xbmc/cores/VideoRenderers/RenderManager.cpp -@@ -303,7 +303,7 @@ void CXBMCRenderManager::RenderUpdate(bool clear, DWORD flags, DWORD alpha) - if(m_presentstep == PRESENT_FLIP) - { - FlipRenderBuffer(); -- m_overlays.Flip(); -+ m_overlays.Flip(m_presentsource); - m_pRenderer->FlipPage(m_presentsource); - m_presentstep = PRESENT_FRAME; - m_presentevent.Set(); -@@ -703,7 +703,7 @@ void CXBMCRenderManager::Present() - if(m_presentstep == PRESENT_FLIP) - { - FlipRenderBuffer(); -- m_overlays.Flip(); -+ m_overlays.Flip(m_presentsource); - m_pRenderer->FlipPage(m_presentsource); - m_presentstep = PRESENT_FRAME; - m_presentevent.Set(); -@@ -986,11 +986,12 @@ int CXBMCRenderManager::FlipFreeBuffer() - // See "Render Buffer State Description" in header for information. - if (HasFreeBuffer()) - { -- if (!m_bRenderBufferUsed) -+ if (!m_bRenderBufferUsed && !m_bOverlayReleased) - { - return -1; - } - m_bRenderBufferUsed = false; -+ m_bOverlayReleased = false; - m_bAllRenderBuffersDisplayed = false; - m_iOutputRenderBuffer = (m_iOutputRenderBuffer + 1) % m_iNumRenderBuffers; - return m_iOutputRenderBuffer; -@@ -1038,6 +1039,7 @@ void CXBMCRenderManager::ResetRenderBuffer() - m_presentPts = DVD_NOPTS_VALUE; - m_speed = 0; - m_bRenderBufferUsed = false; -+ m_bOverlayReleased = false; - } - - void CXBMCRenderManager::PrepareNextRender() -@@ -1116,7 +1118,8 @@ void CXBMCRenderManager::NotifyDisplayFlip() - && m_iDisplayedRenderBuffer != m_iCurrentRenderBuffer) - { - m_pRenderer->ReleaseBuffer(m_iDisplayedRenderBuffer); -- m_overlays.ReleaseBuffer(m_iDisplayedRenderBuffer); -+ if (m_overlays.ReleaseBuffer(m_iDisplayedRenderBuffer) > 0) -+ m_bOverlayReleased = true; - } - } - -diff --git a/xbmc/cores/VideoRenderers/RenderManager.h b/xbmc/cores/VideoRenderers/RenderManager.h -index afb6b1f..3f95793 100644 ---- a/xbmc/cores/VideoRenderers/RenderManager.h -+++ b/xbmc/cores/VideoRenderers/RenderManager.h -@@ -252,6 +252,7 @@ class CXBMCRenderManager - bool m_bCodecSupportsBuffering; - int m_speed; - bool m_bRenderBufferUsed; -+ bool m_bOverlayReleased; - CEvent m_flipEvent; - - struct --- -1.7.10 - - -From a0838293cf956be846f298e4bc5b6211e80f535a Mon Sep 17 00:00:00 2001 -From: xbmc -Date: Tue, 26 Feb 2013 09:00:21 +0100 -Subject: [PATCH 12/88] add buffering - submit absolute time to render buffers - ---- - xbmc/cores/IPlayer.h | 5 ----- - xbmc/cores/VideoRenderers/RenderManager.cpp | 20 +++----------------- - xbmc/cores/VideoRenderers/RenderManager.h | 5 ++--- - xbmc/cores/dvdplayer/DVDPlayer.cpp | 5 ----- - xbmc/cores/dvdplayer/DVDPlayer.h | 2 -- - xbmc/cores/dvdplayer/DVDPlayerVideo.cpp | 2 +- - 6 files changed, 6 insertions(+), 33 deletions(-) - -diff --git a/xbmc/cores/IPlayer.h b/xbmc/cores/IPlayer.h -index cbf2faa..f2aa227 100644 ---- a/xbmc/cores/IPlayer.h -+++ b/xbmc/cores/IPlayer.h -@@ -229,11 +229,6 @@ class IPlayer - */ - virtual void GetSubtitleCapabilities(std::vector &subCaps) { subCaps.assign(1,IPC_SUBS_ALL); }; - -- /*! -- \brief called by RenderManager in order to schedule frames -- */ -- virtual double GetClock(double& absolute, bool interpolated = true) {return 0; }; -- - protected: - IPlayerCallback& m_callback; - }; -diff --git a/xbmc/cores/VideoRenderers/RenderManager.cpp b/xbmc/cores/VideoRenderers/RenderManager.cpp -index e887313..a2001c0 100644 ---- a/xbmc/cores/VideoRenderers/RenderManager.cpp -+++ b/xbmc/cores/VideoRenderers/RenderManager.cpp -@@ -571,7 +571,6 @@ void CXBMCRenderManager::FlipPage(volatile bool& bStop, double timestamp /* = 0L - { CRetakeLock lock(m_sharedSection); - if(!m_pRenderer) return; - -- double presenttime = timestamp; - EFIELDSYNC presentfield = sync; - EPRESENTMETHOD presentmethod; - -@@ -614,7 +613,7 @@ void CXBMCRenderManager::FlipPage(volatile bool& bStop, double timestamp /* = 0L - - if (FlipFreeBuffer() >= 0) - { -- m_renderBuffers[m_iOutputRenderBuffer].pts = timestamp; -+ m_renderBuffers[m_iOutputRenderBuffer].timestamp = timestamp; - m_renderBuffers[m_iOutputRenderBuffer].presentfield = presentfield; - m_renderBuffers[m_iOutputRenderBuffer].presentmethod = presentmethod; - } -@@ -1036,7 +1035,6 @@ void CXBMCRenderManager::ResetRenderBuffer() - m_iDisplayedRenderBuffer = 0; - m_bAllRenderBuffersDisplayed = true; - m_sleeptime = 1.0; -- m_presentPts = DVD_NOPTS_VALUE; - m_speed = 0; - m_bRenderBufferUsed = false; - m_bOverlayReleased = false; -@@ -1053,19 +1051,8 @@ void CXBMCRenderManager::PrepareNextRender() - return; - } - -- double iClockSleep, iPlayingClock, iCurrentClock; -- if (g_application.m_pPlayer) -- iPlayingClock = g_application.m_pPlayer->GetClock(iCurrentClock, false); -- else -- iPlayingClock = iCurrentClock = 0; -- -- iClockSleep = m_renderBuffers[idx].pts - iPlayingClock; -- -- if (m_speed) -- iClockSleep = iClockSleep * DVD_PLAYSPEED_NORMAL / m_speed; -- -- double presenttime = (iCurrentClock + iClockSleep) / DVD_TIME_BASE; -- double clocktime = iCurrentClock / DVD_TIME_BASE; -+ double presenttime = m_renderBuffers[idx].timestamp; -+ double clocktime = GetPresentTime(); - if(presenttime - clocktime > MAXPRESENTDELAY) - presenttime = clocktime + MAXPRESENTDELAY; - -@@ -1074,7 +1061,6 @@ void CXBMCRenderManager::PrepareNextRender() - - if (g_graphicsContext.IsFullScreenVideo() || presenttime <= clocktime + frametime) - { -- m_presentPts = m_renderBuffers[idx].pts; - m_presenttime = presenttime; - m_presentmethod = m_renderBuffers[idx].presentmethod; - m_presentfield = m_renderBuffers[idx].presentfield; -diff --git a/xbmc/cores/VideoRenderers/RenderManager.h b/xbmc/cores/VideoRenderers/RenderManager.h -index 3f95793..858a547 100644 ---- a/xbmc/cores/VideoRenderers/RenderManager.h -+++ b/xbmc/cores/VideoRenderers/RenderManager.h -@@ -93,7 +93,7 @@ class CXBMCRenderManager - * available after the main thread has flipped front / back buffers. - * - * @param bStop reference to stop flag of calling thread -- * @param timestamp pts of frame delivered with AddVideoPicture -+ * @param timestamp of frame delivered with AddVideoPicture - * @param source depreciated - * @param sync signals frame, top, or bottom field - * @param speed current speed of player, needed for some optimizations like keeping the gui responsive on rewind -@@ -257,13 +257,12 @@ class CXBMCRenderManager - - struct - { -- double pts; -+ double timestamp; - EFIELDSYNC presentfield; - EPRESENTMETHOD presentmethod; - }m_renderBuffers[5]; - - double m_sleeptime; -- double m_presentPts; - - double m_presenttime; - double m_presentcorr; -diff --git a/xbmc/cores/dvdplayer/DVDPlayer.cpp b/xbmc/cores/dvdplayer/DVDPlayer.cpp -index dfb317f..0cd2510 100644 ---- a/xbmc/cores/dvdplayer/DVDPlayer.cpp -+++ b/xbmc/cores/dvdplayer/DVDPlayer.cpp -@@ -4075,8 +4075,3 @@ bool CDVDPlayer::CachePVRStream(void) const - !g_PVRManager.IsPlayingRecording() && - g_advancedSettings.m_bPVRCacheInDvdPlayer; - } -- --double CDVDPlayer::GetClock(double& absolute, bool interpolated) --{ -- return m_clock.GetClock(absolute, interpolated); --} -diff --git a/xbmc/cores/dvdplayer/DVDPlayer.h b/xbmc/cores/dvdplayer/DVDPlayer.h -index 093318e..d3c201e 100644 ---- a/xbmc/cores/dvdplayer/DVDPlayer.h -+++ b/xbmc/cores/dvdplayer/DVDPlayer.h -@@ -252,8 +252,6 @@ class CDVDPlayer : public IPlayer, public CThread, public IDVDPlayer - virtual bool SwitchChannel(const PVR::CPVRChannel &channel); - virtual bool CachePVRStream(void) const; - -- virtual double GetClock(double& absolute, bool interpolated = true); -- - enum ECacheState - { CACHESTATE_DONE = 0 - , CACHESTATE_FULL // player is filling up the demux queue -diff --git a/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp b/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp -index 3bfe180..a90c141 100644 ---- a/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp -+++ b/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp -@@ -1363,7 +1363,7 @@ int CDVDPlayerVideo::OutputPicture(const DVDVideoPicture* src, double pts) - if (index < 0) - return EOS_DROPPED; - -- g_renderManager.FlipPage(CThread::m_bStop, pts, -1, mDisplayField, m_speed); -+ g_renderManager.FlipPage(CThread::m_bStop, (iCurrentClock + iSleepTime) / DVD_TIME_BASE, -1, mDisplayField, m_speed); - - return result; - #else --- -1.7.10 - - -From aee70c4018b40358ff2e8a98727ccb55be65da63 Mon Sep 17 00:00:00 2001 -From: xbmc -Date: Fri, 1 Mar 2013 08:05:00 +0100 -Subject: [PATCH 13/88] RenderManager: some rework, squash add buffering - ---- - xbmc/cores/VideoRenderers/RenderManager.cpp | 18 ++++++++++-------- - 1 file changed, 10 insertions(+), 8 deletions(-) - -diff --git a/xbmc/cores/VideoRenderers/RenderManager.cpp b/xbmc/cores/VideoRenderers/RenderManager.cpp -index a2001c0..09daaef 100644 ---- a/xbmc/cores/VideoRenderers/RenderManager.cpp -+++ b/xbmc/cores/VideoRenderers/RenderManager.cpp -@@ -616,6 +616,8 @@ void CXBMCRenderManager::FlipPage(volatile bool& bStop, double timestamp /* = 0L - m_renderBuffers[m_iOutputRenderBuffer].timestamp = timestamp; - m_renderBuffers[m_iOutputRenderBuffer].presentfield = presentfield; - m_renderBuffers[m_iOutputRenderBuffer].presentmethod = presentmethod; -+ if (!m_bUseBuffering) -+ PrepareNextRender(); - } - m_speed = speed; - } -@@ -825,17 +827,17 @@ int CXBMCRenderManager::AddVideoPicture(DVDVideoPicture& pic) - if (!m_pRenderer) - return -1; - -- if(m_pRenderer->AddVideoPicture(&pic, (m_iOutputRenderBuffer + 1) % m_iNumRenderBuffers)) -+ int index = (m_iOutputRenderBuffer + 1) % m_iNumRenderBuffers; -+ -+ if(m_pRenderer->AddVideoPicture(&pic, index)) - { - m_bRenderBufferUsed = true; - return 1; - } - - YV12Image image; -- int index = m_pRenderer->GetImage(&image, (m_iOutputRenderBuffer + 1) % m_iNumRenderBuffers); -- -- if(index < 0) -- return index; -+ if (m_pRenderer->GetImage(&image, index) < 0) -+ return -1; - - if(pic.format == RENDER_FMT_YUV420P - || pic.format == RENDER_FMT_YUV420P10 -@@ -947,14 +949,14 @@ int CXBMCRenderManager::WaitForBuffer(volatile bool& bStop, int timeout) - if (!m_pRenderer) - return -1; - -- double maxwait = GetPresentTime() + (float)timeout/1000; -+ XbmcThreads::EndTime endtime(timeout); - while(!HasFreeBuffer() && !bStop) - { - lock.Leave(); - m_flipEvent.WaitMSec(std::min(50, timeout)); -- if(GetPresentTime() > maxwait && !bStop) -+ if(endtime.IsTimePast()) - { -- if (timeout != 0) -+ if (timeout != 0 && !bStop) - CLog::Log(LOGWARNING, "CRenderManager::WaitForBuffer - timeout waiting for buffer"); - return -1; - } --- -1.7.10 - - -From 927a0787cf8c8eb9d87e1c39f1abc4adc680235a Mon Sep 17 00:00:00 2001 -From: xbmc -Date: Fri, 1 Mar 2013 08:07:07 +0100 -Subject: [PATCH 14/88] dvdplayer: disable buffering unil dropping is improved - ---- - xbmc/cores/dvdplayer/DVDPlayerVideo.cpp | 16 ++++++++-------- - 1 file changed, 8 insertions(+), 8 deletions(-) - -diff --git a/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp b/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp -index a90c141..c02bb96 100644 ---- a/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp -+++ b/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp -@@ -1100,35 +1100,35 @@ int CDVDPlayerVideo::OutputPicture(const DVDVideoPicture* src, double pts) - { - case RENDER_FMT_YUV420P: - formatstr = "YV12"; -- buffering = true; -+ buffering = false; - break; - case RENDER_FMT_YUV420P16: - formatstr = "YV12P16"; -- buffering = true; -+ buffering = false; - break; - case RENDER_FMT_YUV420P10: - formatstr = "YV12P10"; -- buffering = true; -+ buffering = false; - break; - case RENDER_FMT_NV12: - formatstr = "NV12"; -- buffering = true; -+ buffering = false; - break; - case RENDER_FMT_UYVY422: - formatstr = "UYVY"; -- buffering = true; -+ buffering = false; - break; - case RENDER_FMT_YUYV422: - formatstr = "YUY2"; -- buffering = true; -+ buffering = false; - break; - case RENDER_FMT_VDPAU: - formatstr = "VDPAU"; -- buffering = true; -+ buffering = false; - break; - case RENDER_FMT_DXVA: - formatstr = "DXVA"; -- buffering = true; -+ buffering = false; - break; - case RENDER_FMT_VAAPI: - formatstr = "VAAPI"; --- -1.7.10 - - -From b4dba473cb37652a888d8a47cb37d4f489ff8133 Mon Sep 17 00:00:00 2001 -From: xbmc -Date: Sat, 2 Mar 2013 12:00:51 +0100 -Subject: [PATCH 15/88] RenderManager: skip very late frames in render buffer - ---- - xbmc/cores/VideoRenderers/RenderManager.cpp | 21 +++++++++++++++++++-- - 1 file changed, 19 insertions(+), 2 deletions(-) - -diff --git a/xbmc/cores/VideoRenderers/RenderManager.cpp b/xbmc/cores/VideoRenderers/RenderManager.cpp -index 09daaef..9897f1c 100644 ---- a/xbmc/cores/VideoRenderers/RenderManager.cpp -+++ b/xbmc/cores/VideoRenderers/RenderManager.cpp -@@ -1053,13 +1053,30 @@ void CXBMCRenderManager::PrepareNextRender() - return; - } - -- double presenttime = m_renderBuffers[idx].timestamp; - double clocktime = GetPresentTime(); -+ double frametime = 1 / g_graphicsContext.GetFPS(); -+ -+ // look ahead in the queue -+ // if the next frame is already late, skip the one we are about to render -+ while (idx != m_iOutputRenderBuffer) -+ { -+ int idx_next = (idx + 1) % m_iNumRenderBuffers; -+ if (m_renderBuffers[idx_next].timestamp <= clocktime) -+ { -+ FlipRenderBuffer(); -+ idx = GetNextRenderBufferIndex(); -+ CLog::Log(LOGDEBUG,"%s - skip frame at render buffer index: %d", __FUNCTION__, idx); -+ } -+ else -+ break; -+ } -+ -+ double presenttime = m_renderBuffers[idx].timestamp; -+ - if(presenttime - clocktime > MAXPRESENTDELAY) - presenttime = clocktime + MAXPRESENTDELAY; - - m_sleeptime = presenttime - clocktime; -- double frametime = 1 / g_graphicsContext.GetFPS(); - - if (g_graphicsContext.IsFullScreenVideo() || presenttime <= clocktime + frametime) - { --- -1.7.10 - - -From c77b0cded556ed2e5a83df8df37278cc40490123 Mon Sep 17 00:00:00 2001 -From: xbmc -Date: Sat, 2 Mar 2013 12:10:17 +0100 -Subject: [PATCH 16/88] renderbuffers: drop enable/disable in this iteration - ---- - xbmc/cores/VideoRenderers/RenderManager.cpp | 4 ++++ - xbmc/cores/dvdplayer/DVDPlayerVideo.cpp | 4 ---- - 2 files changed, 4 insertions(+), 4 deletions(-) - -diff --git a/xbmc/cores/VideoRenderers/RenderManager.cpp b/xbmc/cores/VideoRenderers/RenderManager.cpp -index 9897f1c..e479adc 100644 ---- a/xbmc/cores/VideoRenderers/RenderManager.cpp -+++ b/xbmc/cores/VideoRenderers/RenderManager.cpp -@@ -266,6 +266,7 @@ bool CXBMCRenderManager::Configure(unsigned int width, unsigned int height, unsi - m_presentstep = PRESENT_IDLE; - m_presentevent.Set(); - ResetRenderBuffer(); -+ EnableBuffering(buffering); - } - - return result; -@@ -1093,7 +1094,10 @@ void CXBMCRenderManager::EnableBuffering(bool enable) - CRetakeLock lock(m_sharedSection); - - if (m_iNumRenderBuffers < 3) -+ { -+ m_bUseBuffering = false; - return; -+ } - - m_bUseBuffering = enable; - if (!m_bUseBuffering) -diff --git a/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp b/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp -index c02bb96..1d3c7e3 100644 ---- a/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp -+++ b/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp -@@ -261,7 +261,6 @@ void CDVDPlayerVideo::OpenStream(CDVDStreamInfo &hint, CDVDVideoCodec* codec) - m_stalled = m_messageQueue.GetPacketCount(CDVDMsg::DEMUXER_PACKET) == 0; - m_started = false; - m_codecname = m_pVideoCodec->GetName(); -- g_renderManager.EnableBuffering(false); - } - - void CDVDPlayerVideo::CloseStream(bool bWaitForBuffers) -@@ -437,7 +436,6 @@ void CDVDPlayerVideo::Process() - picture.iFlags &= ~DVP_FLAG_ALLOCATED; - m_packets.clear(); - m_started = false; -- g_renderManager.EnableBuffering(false); - } - else if (pMsg->IsType(CDVDMsg::GENERAL_FLUSH)) // private message sent by (CDVDPlayerVideo::Flush()) - { -@@ -450,7 +448,6 @@ void CDVDPlayerVideo::Process() - //we need to recalculate the framerate - //TODO: this needs to be set on a streamchange instead - ResetFrameRateCalc(); -- g_renderManager.EnableBuffering(false); - - m_stalled = true; - m_started = false; -@@ -705,7 +702,6 @@ void CDVDPlayerVideo::Process() - m_codecname = m_pVideoCodec->GetName(); - m_started = true; - m_messageParent.Put(new CDVDMsgInt(CDVDMsg::PLAYER_STARTED, DVDPLAYER_VIDEO)); -- g_renderManager.EnableBuffering(true); - } - - // guess next frame pts. iDuration is always valid --- -1.7.10 - - -From 094da266d519fd5385ca99866817f7b51944a0c0 Mon Sep 17 00:00:00 2001 -From: xbmc -Date: Sat, 2 Mar 2013 12:31:11 +0100 -Subject: [PATCH 17/88] RenderManager: add method SetSpeed - ---- - xbmc/cores/VideoRenderers/RenderManager.cpp | 10 +++++++--- - xbmc/cores/VideoRenderers/RenderManager.h | 8 ++++++-- - xbmc/cores/dvdplayer/DVDPlayerVideo.cpp | 3 ++- - 3 files changed, 15 insertions(+), 6 deletions(-) - -diff --git a/xbmc/cores/VideoRenderers/RenderManager.cpp b/xbmc/cores/VideoRenderers/RenderManager.cpp -index e479adc..dc984cf 100644 ---- a/xbmc/cores/VideoRenderers/RenderManager.cpp -+++ b/xbmc/cores/VideoRenderers/RenderManager.cpp -@@ -550,7 +550,7 @@ void CXBMCRenderManager::SetViewMode(int iViewMode) - m_pRenderer->SetViewMode(iViewMode); - } - --void CXBMCRenderManager::FlipPage(volatile bool& bStop, double timestamp /* = 0LL*/, int source /*= -1*/, EFIELDSYNC sync /*= FS_NONE*/, int speed /*= 1000*/) -+void CXBMCRenderManager::FlipPage(volatile bool& bStop, double timestamp /* = 0LL*/, int source /*= -1*/, EFIELDSYNC sync /*= FS_NONE*/) - { - if (!m_bUseBuffering) - { -@@ -620,7 +620,6 @@ void CXBMCRenderManager::FlipPage(volatile bool& bStop, double timestamp /* = 0L - if (!m_bUseBuffering) - PrepareNextRender(); - } -- m_speed = speed; - } - - g_application.NewFrame(); -@@ -1038,7 +1037,7 @@ void CXBMCRenderManager::ResetRenderBuffer() - m_iDisplayedRenderBuffer = 0; - m_bAllRenderBuffersDisplayed = true; - m_sleeptime = 1.0; -- m_speed = 0; -+ m_speed = DVD_PLAYSPEED_NORMAL; - m_bRenderBufferUsed = false; - m_bOverlayReleased = false; - } -@@ -1112,6 +1111,11 @@ void CXBMCRenderManager::DiscardBuffer() - m_iOutputRenderBuffer = m_iCurrentRenderBuffer; - } - -+void CXBMCRenderManager::SetSpeed(int speed) -+{ -+ m_speed = speed; -+} -+ - void CXBMCRenderManager::NotifyDisplayFlip() - { - CRetakeLock lock(m_sharedSection); -diff --git a/xbmc/cores/VideoRenderers/RenderManager.h b/xbmc/cores/VideoRenderers/RenderManager.h -index 858a547..c9edb64 100644 ---- a/xbmc/cores/VideoRenderers/RenderManager.h -+++ b/xbmc/cores/VideoRenderers/RenderManager.h -@@ -96,9 +96,8 @@ class CXBMCRenderManager - * @param timestamp of frame delivered with AddVideoPicture - * @param source depreciated - * @param sync signals frame, top, or bottom field -- * @param speed current speed of player, needed for some optimizations like keeping the gui responsive on rewind - */ -- void FlipPage(volatile bool& bStop, double timestamp = 0.0, int source = -1, EFIELDSYNC sync = FS_NONE, int speed = 1000); -+ void FlipPage(volatile bool& bStop, double timestamp = 0.0, int source = -1, EFIELDSYNC sync = FS_NONE); - unsigned int PreInit(); - void UnInit(); - bool Flush(); -@@ -188,6 +187,11 @@ class CXBMCRenderManager - */ - void DiscardBuffer(); - -+ /** -+ * notify RenderManager about play speed -+ */ -+ void SetSpeed(int speed); -+ - protected: - void Render(bool clear, DWORD flags, DWORD alpha); - -diff --git a/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp b/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp -index 1d3c7e3..db4f7bd 100644 ---- a/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp -+++ b/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp -@@ -465,6 +465,7 @@ void CDVDPlayerVideo::Process() - m_speed = static_cast(pMsg)->m_value; - if(m_speed == DVD_PLAYSPEED_PAUSE) - m_iNrOfPicturesNotToSkip = 0; -+ g_renderManager.SetSpeed(m_speed); - } - else if (pMsg->IsType(CDVDMsg::PLAYER_STARTED)) - { -@@ -1359,7 +1360,7 @@ int CDVDPlayerVideo::OutputPicture(const DVDVideoPicture* src, double pts) - if (index < 0) - return EOS_DROPPED; - -- g_renderManager.FlipPage(CThread::m_bStop, (iCurrentClock + iSleepTime) / DVD_TIME_BASE, -1, mDisplayField, m_speed); -+ g_renderManager.FlipPage(CThread::m_bStop, (iCurrentClock + iSleepTime) / DVD_TIME_BASE, -1, mDisplayField); - - return result; - #else --- -1.7.10 - - -From e46b7cb93cc01827dc03966dd8f0d3cbdbbc8f60 Mon Sep 17 00:00:00 2001 -From: xbmc -Date: Sun, 10 Feb 2013 18:40:30 +0100 -Subject: [PATCH 18/88] OMXPlayer: adapt to buffering - ---- - xbmc/cores/omxplayer/OMXPlayerVideo.cpp | 25 ++++++++----------------- - 1 file changed, 8 insertions(+), 17 deletions(-) - -diff --git a/xbmc/cores/omxplayer/OMXPlayerVideo.cpp b/xbmc/cores/omxplayer/OMXPlayerVideo.cpp -index 4d813db..8b1c06e 100644 ---- a/xbmc/cores/omxplayer/OMXPlayerVideo.cpp -+++ b/xbmc/cores/omxplayer/OMXPlayerVideo.cpp -@@ -359,7 +359,7 @@ void OMXPlayerVideo::Output(int iGroupId, double pts, bool bDropPacket) - - if(!g_renderManager.Configure(m_hints.width, m_hints.height, - iDisplayWidth, iDisplayHeight, m_fps, flags, format, 0, -- m_hints.orientation)) -+ m_hints.orientation, true)) - { - CLog::Log(LOGERROR, "%s - failed to configure renderer", __FUNCTION__); - return; -@@ -453,25 +453,16 @@ void OMXPlayerVideo::Output(int iGroupId, double pts, bool bDropPacket) - m_dropbase = 0.0f; - #endif - -- // DVDPlayer sleeps until m_iSleepEndTime here before calling FlipPage. -- // Video playback in asynchronous in OMXPlayer, so we don't want to do that here, as it prevents the video fifo from being kept full. -- // So, we keep track of when FlipPage would have been called on DVDPlayer and return early if it is not time. -- // m_iSleepEndTime == DVD_NOPTS_VALUE means we are not waiting to call FlipPage, otherwise it is the time we want to call FlipPage -- if (m_iSleepEndTime == DVD_NOPTS_VALUE) { -- m_iSleepEndTime = iCurrentClock + iSleepTime; -- } -- -- if (!CThread::m_bStop && m_av_clock->GetAbsoluteClock(false) < m_iSleepEndTime + DVD_MSEC_TO_TIME(500)) -+ int buffer = g_renderManager.WaitForBuffer(m_bStop, 0); -+ if (buffer < 0) - return; - -- double pts_media = m_av_clock->OMXMediaTime(false, false); -- ProcessOverlays(iGroupId, pts_media); -- -- g_renderManager.FlipPage(CThread::m_bStop, m_iSleepEndTime / DVD_TIME_BASE, -1, FS_NONE); -- -- m_iSleepEndTime = DVD_NOPTS_VALUE; -+ double pts_overlay = m_av_clock->OMXMediaTime(false, false) -+ + 2* (double)DVD_TIME_BASE / g_graphicsContext.GetFPS(); -+ ProcessOverlays(iGroupId, pts_overlay); - -- //m_av_clock->WaitAbsoluteClock((iCurrentClock + iSleepTime)); -+ double timestamp = CDVDClock::GetAbsoluteClock(false) + 2 / g_graphicsContext.GetFPS(); -+ g_renderManager.FlipPage(CThread::m_bStop, timestamp, -1, FS_NONE); - } - - void OMXPlayerVideo::Process() --- -1.7.10 - - -From b4f1ed7fd41c48b9ec199cce6854d6f2e25f53c0 Mon Sep 17 00:00:00 2001 -From: xbmc -Date: Sat, 2 Mar 2013 20:42:10 +0100 -Subject: [PATCH 19/88] overlays: squash to - b0b5c7c825b0265c5e7c888a48a76d11eb719246 - ---- - xbmc/cores/VideoRenderers/OverlayRenderer.cpp | 19 +++++++++---------- - xbmc/cores/VideoRenderers/OverlayRenderer.h | 4 ++-- - xbmc/cores/VideoRenderers/RenderManager.cpp | 4 +++- - 3 files changed, 14 insertions(+), 13 deletions(-) - -diff --git a/xbmc/cores/VideoRenderers/OverlayRenderer.cpp b/xbmc/cores/VideoRenderers/OverlayRenderer.cpp -index 5592eca..8559720 100644 ---- a/xbmc/cores/VideoRenderers/OverlayRenderer.cpp -+++ b/xbmc/cores/VideoRenderers/OverlayRenderer.cpp -@@ -127,32 +127,31 @@ void CRenderer::AddCleanup(COverlay* o) - m_cleanup.push_back(o->Acquire()); - } - --long CRenderer::Release(SElementV& list) -+bool CRenderer::Release(SElementV& list) - { - SElementV l = list; - list.clear(); - -- long count = 0; -+ bool change = false; - for(SElementV::iterator it = l.begin(); it != l.end(); it++) - { - if(it->overlay) -- count += it->overlay->Release(); -+ it->overlay->Release(); - if(it->overlay_dvd) -- count += it->overlay_dvd->Release(); -+ it->overlay_dvd->Release(); -+ -+ change = true; - } -- return count; -+ return change; - } - --long CRenderer::Release(COverlayV& list) -+void CRenderer::Release(COverlayV& list) - { - COverlayV l = list; - list.clear(); - -- long count = 0; - for(COverlayV::iterator it = l.begin(); it != l.end(); it++) -- count += (*it)->Release(); -- -- return count; -+ (*it)->Release(); - } - - void CRenderer::Flush() -diff --git a/xbmc/cores/VideoRenderers/OverlayRenderer.h b/xbmc/cores/VideoRenderers/OverlayRenderer.h -index 627dd9f..e0c497d 100644 ---- a/xbmc/cores/VideoRenderers/OverlayRenderer.h -+++ b/xbmc/cores/VideoRenderers/OverlayRenderer.h -@@ -123,8 +123,8 @@ - COverlay* Convert(CDVDOverlay* o, double pts); - COverlay* Convert(CDVDOverlaySSA* o, double pts); - -- long Release(COverlayV& list); -- long Release(SElementV& list); -+ void Release(COverlayV& list); -+ bool Release(SElementV& list); - - CCriticalSection m_section; - SElementV m_buffers[NUM_BUFFERS]; -diff --git a/xbmc/cores/VideoRenderers/RenderManager.cpp b/xbmc/cores/VideoRenderers/RenderManager.cpp -index dc984cf..1343a71 100644 ---- a/xbmc/cores/VideoRenderers/RenderManager.cpp -+++ b/xbmc/cores/VideoRenderers/RenderManager.cpp -@@ -967,6 +967,8 @@ int CXBMCRenderManager::WaitForBuffer(volatile bool& bStop, int timeout) - if (bStop) - return -1; - -+ // make sure overlay buffer is released, this won't happen on AddOverlay -+ m_overlays.ReleaseBuffer((m_iOutputRenderBuffer + 1) % m_iNumRenderBuffers); - return 1; - } - -@@ -1131,7 +1133,7 @@ void CXBMCRenderManager::NotifyDisplayFlip() - && m_iDisplayedRenderBuffer != m_iCurrentRenderBuffer) - { - m_pRenderer->ReleaseBuffer(m_iDisplayedRenderBuffer); -- if (m_overlays.ReleaseBuffer(m_iDisplayedRenderBuffer) > 0) -+ if (m_overlays.ReleaseBuffer(m_iDisplayedRenderBuffer)) - m_bOverlayReleased = true; - } - } --- -1.7.10 - - -From 652203771888444899ae4b2655224d4022278c56 Mon Sep 17 00:00:00 2001 -From: xbmc -Date: Mon, 28 May 2012 10:34:39 +0200 -Subject: [PATCH 20/88] videoplayer: adapt lateness detection and dropping to - buffering - ---- - xbmc/cores/VideoRenderers/RenderManager.cpp | 17 +- - xbmc/cores/VideoRenderers/RenderManager.h | 11 +- - .../dvdplayer/DVDCodecs/Video/DVDVideoCodec.h | 14 ++ - .../DVDCodecs/Video/DVDVideoCodecFFmpeg.cpp | 31 +++ - .../DVDCodecs/Video/DVDVideoCodecFFmpeg.h | 7 + - xbmc/cores/dvdplayer/DVDPlayerVideo.cpp | 226 ++++++++++++++++---- - xbmc/cores/dvdplayer/DVDPlayerVideo.h | 24 +++ - 7 files changed, 282 insertions(+), 48 deletions(-) - -diff --git a/xbmc/cores/VideoRenderers/RenderManager.cpp b/xbmc/cores/VideoRenderers/RenderManager.cpp -index 1343a71..c4ca57e 100644 ---- a/xbmc/cores/VideoRenderers/RenderManager.cpp -+++ b/xbmc/cores/VideoRenderers/RenderManager.cpp -@@ -550,7 +550,7 @@ void CXBMCRenderManager::SetViewMode(int iViewMode) - m_pRenderer->SetViewMode(iViewMode); - } - --void CXBMCRenderManager::FlipPage(volatile bool& bStop, double timestamp /* = 0LL*/, int source /*= -1*/, EFIELDSYNC sync /*= FS_NONE*/) -+void CXBMCRenderManager::FlipPage(volatile bool& bStop, double timestamp /* = 0LL*/, double pts /* = 0 */, int source /*= -1*/, EFIELDSYNC sync /*= FS_NONE*/) - { - if (!m_bUseBuffering) - { -@@ -614,6 +614,7 @@ void CXBMCRenderManager::FlipPage(volatile bool& bStop, double timestamp /* = 0L - - if (FlipFreeBuffer() >= 0) - { -+ m_renderBuffers[m_iOutputRenderBuffer].pts = pts; - m_renderBuffers[m_iOutputRenderBuffer].timestamp = timestamp; - m_renderBuffers[m_iOutputRenderBuffer].presentfield = presentfield; - m_renderBuffers[m_iOutputRenderBuffer].presentmethod = presentmethod; -@@ -1040,6 +1041,7 @@ void CXBMCRenderManager::ResetRenderBuffer() - m_bAllRenderBuffersDisplayed = true; - m_sleeptime = 1.0; - m_speed = DVD_PLAYSPEED_NORMAL; -+ m_presentPts = DVD_NOPTS_VALUE; - m_bRenderBufferUsed = false; - m_bOverlayReleased = false; - } -@@ -1082,6 +1084,7 @@ void CXBMCRenderManager::PrepareNextRender() - - if (g_graphicsContext.IsFullScreenVideo() || presenttime <= clocktime + frametime) - { -+ m_presentPts = m_renderBuffers[idx].pts; - m_presenttime = presenttime; - m_presentmethod = m_renderBuffers[idx].presentmethod; - m_presentfield = m_renderBuffers[idx].presentfield; -@@ -1142,6 +1145,18 @@ void CXBMCRenderManager::NotifyDisplayFlip() - m_flipEvent.Set(); - } - -+bool CXBMCRenderManager::GetStats(double &sleeptime, double &pts, int &bufferLevel) -+{ -+ CSharedLock lock(m_sharedSection); -+ sleeptime = m_sleeptime; -+ pts = m_presentPts; -+ if (m_iNumRenderBuffers < 3) -+ bufferLevel = -1; -+ else -+ bufferLevel = (m_iOutputRenderBuffer - m_iCurrentRenderBuffer + m_iNumRenderBuffers) % m_iNumRenderBuffers; -+ return true; -+} -+ - bool CXBMCRenderManager::HasFrame() - { - CSharedLock lock(m_sharedSection); -diff --git a/xbmc/cores/VideoRenderers/RenderManager.h b/xbmc/cores/VideoRenderers/RenderManager.h -index c9edb64..b3e6547 100644 ---- a/xbmc/cores/VideoRenderers/RenderManager.h -+++ b/xbmc/cores/VideoRenderers/RenderManager.h -@@ -94,10 +94,11 @@ class CXBMCRenderManager - * - * @param bStop reference to stop flag of calling thread - * @param timestamp of frame delivered with AddVideoPicture -+ * @param pts used for lateness detection - * @param source depreciated - * @param sync signals frame, top, or bottom field - */ -- void FlipPage(volatile bool& bStop, double timestamp = 0.0, int source = -1, EFIELDSYNC sync = FS_NONE); -+ 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(); -@@ -177,6 +178,12 @@ class CXBMCRenderManager - bool HasFrame(); - - /** -+ * Can be called by player for lateness detection. This is done best by -+ * looking at the end of the queue. -+ */ -+ bool GetStats(double &sleeptime, double &pts, int &bufferLevel); -+ -+ /** - * Video player can dynamically enable/disable buffering. In situations like - * rewind buffering is not ideal. - */ -@@ -261,12 +268,14 @@ class CXBMCRenderManager - - struct - { -+ double pts; - double timestamp; - EFIELDSYNC presentfield; - EPRESENTMETHOD presentmethod; - }m_renderBuffers[5]; - - double m_sleeptime; -+ double m_presentPts; - - double m_presenttime; - double m_presentcorr; -diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodec.h b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodec.h -index 1d8bad3..5001aac 100644 ---- a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodec.h -+++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodec.h -@@ -110,6 +110,10 @@ struct DVDVideoUserData - #define DVP_FLAG_NOSKIP 0x00000010 // indicate this picture should never be dropped - #define DVP_FLAG_DROPPED 0x00000020 // indicate that this picture has been dropped in decoder stage, will have no data - -+#define DVP_FLAG_DROPDEINT 0x00000040 // indicate that this picture was requested to have been dropped in deint stage -+#define DVP_FLAG_NO_POSTPROC 0x00000100 -+#define DVP_FLAG_DRAIN 0x00000200 -+ - // DVP_FLAG 0x00000100 - 0x00000f00 is in use by libmpeg2! - - #define DVP_QSCALE_UNKNOWN 0 -@@ -127,6 +131,9 @@ struct DVDVideoUserData - #define VC_PICTURE 0x00000004 // the decoder got a picture, call Decode(NULL, 0) again to parse the rest of the data - #define VC_USERDATA 0x00000008 // the decoder found some userdata, call Decode(NULL, 0) again to parse the rest of the data - #define VC_FLUSHED 0x00000010 // the decoder lost it's state, we need to restart decoding again -+#define VC_DROPPED 0x00000020 // needed to identify if a picture was dropped -+#define VC_HURRY 0x00000040 -+ - class CDVDVideoCodec - { - public: -@@ -237,4 +244,11 @@ class CDVDVideoCodec - { - return 0; - } -+ -+ virtual bool GetPts(double &pts, int &skippedDeint, int &interlaced) -+ { -+ return false; -+ } -+ -+ virtual void SetCodecControl(int flags) {} - }; -diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.cpp b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.cpp -index 286fd67..dae3b8e 100644 ---- a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.cpp -+++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.cpp -@@ -142,6 +142,7 @@ enum PixelFormat CDVDVideoCodecFFmpeg::GetFormat( struct AVCodecContext * avctx - m_iLastKeyframe = 0; - m_dts = DVD_NOPTS_VALUE; - m_started = false; -+ m_decoderPts = DVD_NOPTS_VALUE; - } - - CDVDVideoCodecFFmpeg::~CDVDVideoCodecFFmpeg() -@@ -340,6 +341,14 @@ void CDVDVideoCodecFFmpeg::SetDropState(bool bDrop) - { - if( m_pCodecContext ) - { -+ if (bDrop && m_pHardware && m_pHardware->CanSkipDeint()) -+ { -+ m_requestSkipDeint = true; -+ bDrop = false; -+ } -+ else -+ m_requestSkipDeint = false; -+ - // i don't know exactly how high this should be set - // couldn't find any good docs on it. think it varies - // from codec to codec on what it does -@@ -541,6 +550,7 @@ int CDVDVideoCodecFFmpeg::Decode(BYTE* pData, int iSize, double dts, double pts) - void CDVDVideoCodecFFmpeg::Reset() - { - m_started = false; -+ m_decoderPts = DVD_NOPTS_VALUE; - m_iLastKeyframe = m_pCodecContext->has_b_frames; - m_dllAvCodec.avcodec_flush_buffers(m_pCodecContext); - -@@ -639,6 +649,22 @@ bool CDVDVideoCodecFFmpeg::GetPictureCommon(DVDVideoPicture* pDvdVideoPicture) - else - pDvdVideoPicture->pts = DVD_NOPTS_VALUE; - -+ if (pDvdVideoPicture->pts != DVD_NOPTS_VALUE) -+ m_decoderPts = pDvdVideoPicture->pts; -+ else -+ m_decoderPts = m_dts; -+ -+ if (m_requestSkipDeint) -+ { -+ pDvdVideoPicture->iFlags |= DVP_FLAG_DROPDEINT; -+ m_skippedDeint = 1; -+ } -+ else -+ m_skippedDeint = 0; -+ -+ m_requestSkipDeint = false; -+ pDvdVideoPicture->iFlags |= m_codecControlFlags; -+ - if(!m_started) - pDvdVideoPicture->iFlags |= DVP_FLAG_DROPPED; - -@@ -861,3 +887,8 @@ unsigned CDVDVideoCodecFFmpeg::GetConvergeCount() - else - return 0; - } -+ -+void CDVDVideoCodecFFmpeg::SetCodecControl(int flags) -+{ -+ m_codecControlFlags = flags; -+} -diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.h b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.h -index 61d0305..52e1113 100644 ---- a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.h -+++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.h -@@ -44,6 +44,7 @@ class CDVDVideoCodecFFmpeg : public CDVDVideoCodec - virtual bool GetPicture(AVCodecContext* avctx, AVFrame* frame, DVDVideoPicture* picture) = 0; - virtual int Check (AVCodecContext* avctx) = 0; - virtual void Reset () {} -+ virtual bool CanSkipDeint() {return false; } - virtual const std::string Name() = 0; - virtual CCriticalSection* Section() { return NULL; } - }; -@@ -60,6 +61,8 @@ class CDVDVideoCodecFFmpeg : public CDVDVideoCodec - virtual unsigned int SetFilters(unsigned int filters); - virtual const char* GetName() { return m_name.c_str(); }; // m_name is never changed after open - virtual unsigned GetConvergeCount(); -+ virtual bool GetPts(double &pts, int &skippedDeint, int &interlaced) {pts=m_decoderPts; skippedDeint=m_skippedDeint; if (m_pFrame) interlaced = m_pFrame->interlaced_frame; return true;} -+ virtual void SetCodecControl(int flags); - - bool IsHardwareAllowed() { return !m_bSoftware; } - IHardwareDecoder * GetHardware() { return m_pHardware; }; -@@ -119,4 +122,8 @@ class CDVDVideoCodecFFmpeg : public CDVDVideoCodec - double m_dts; - bool m_started; - std::vector m_formats; -+ double m_decoderPts, m_decoderInterval; -+ int m_skippedDeint; -+ bool m_requestSkipDeint; -+ int m_codecControlFlags; - }; -diff --git a/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp b/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp -index db4f7bd..5484073 100644 ---- a/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp -+++ b/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp -@@ -325,8 +325,10 @@ void CDVDPlayerVideo::Process() - - int iDropped = 0; //frames dropped in a row - bool bRequestDrop = false; -+ int iDropDirective; - - m_videoStats.Start(); -+ m_droppingStats.Reset(); - - while (!m_bStop) - { -@@ -436,6 +438,7 @@ void CDVDPlayerVideo::Process() - picture.iFlags &= ~DVP_FLAG_ALLOCATED; - m_packets.clear(); - m_started = false; -+ m_droppingStats.Reset(); - } - else if (pMsg->IsType(CDVDMsg::GENERAL_FLUSH)) // private message sent by (CDVDPlayerVideo::Flush()) - { -@@ -448,6 +451,7 @@ void CDVDPlayerVideo::Process() - //we need to recalculate the framerate - //TODO: this needs to be set on a streamchange instead - ResetFrameRateCalc(); -+ m_droppingStats.Reset(); - - m_stalled = true; - m_started = false; -@@ -466,6 +470,7 @@ void CDVDPlayerVideo::Process() - if(m_speed == DVD_PLAYSPEED_PAUSE) - m_iNrOfPicturesNotToSkip = 0; - g_renderManager.SetSpeed(m_speed); -+ m_droppingStats.Reset(); - } - else if (pMsg->IsType(CDVDMsg::PLAYER_STARTED)) - { -@@ -500,6 +505,28 @@ void CDVDPlayerVideo::Process() - m_iNrOfPicturesNotToSkip = 1; - } - -+ bRequestDrop = false; -+ iDropDirective = CalcDropRequirement(pts); -+ if (iDropDirective & EOS_VERYLATE) -+ { -+ if (m_bAllowDrop) -+ { -+ m_pullupCorrection.Flush(); -+ bRequestDrop = true; -+ } -+ } -+ int codecControl = 0; -+ if (iDropDirective & EOS_BUFFER_LEVEL) -+ codecControl |= DVP_FLAG_DRAIN; -+ if (m_speed > DVD_PLAYSPEED_NORMAL) -+ codecControl |= DVP_FLAG_NO_POSTPROC; -+ m_pVideoCodec->SetCodecControl(codecControl); -+ if (iDropDirective & EOS_DROPPED) -+ { -+ m_iDroppedFrames++; -+ iDropped++; -+ } -+ - #ifdef PROFILE - bRequestDrop = false; - #else -@@ -509,6 +536,7 @@ void CDVDPlayerVideo::Process() - bRequestDrop = false; - m_iDroppedRequest = 0; - m_iLateFrames = 0; -+ m_droppingStats.m_requestOutputDrop = false; - } - #endif - -@@ -556,15 +584,8 @@ void CDVDPlayerVideo::Process() - } - - m_videoStats.AddSampleBytes(pPacket->iSize); -- // assume decoder dropped a picture if it didn't give us any -- // picture from a demux packet, this should be reasonable -- // for libavformat as a demuxer as it normally packetizes -- // pictures when they come from demuxer -- if(bRequestDrop && !bPacketDrop && (iDecoderState & VC_BUFFER) && !(iDecoderState & VC_PICTURE)) -- { -- m_iDroppedFrames++; -- iDropped++; -- } -+ -+ bRequestDrop = false; - - // loop while no error - while (!m_bStop) -@@ -1255,50 +1276,30 @@ int CDVDPlayerVideo::OutputPicture(const DVDVideoPicture* src, double pts) - m_FlipTimeStamp += max(0.0, iSleepTime); - m_FlipTimeStamp += iFrameDuration; - -- if (iSleepTime <= 0 && m_speed) -- m_iLateFrames++; -- else -- m_iLateFrames = 0; -- -- // ask decoder to drop frames next round, as we are very late -- if(m_iLateFrames > 10) -- { -- if (!(pPicture->iFlags & DVP_FLAG_NOSKIP)) -- { -- //if we're calculating the framerate, -- //don't drop frames until we've calculated a stable framerate -- if (m_bAllowDrop || m_speed != DVD_PLAYSPEED_NORMAL) -- { -- result |= EOS_VERYLATE; -- m_pullupCorrection.Flush(); //dropped frames mess up the pattern, so just flush it -- } -- -- //if we requested 5 drops in a row and we're still late, drop on output -- //this keeps a/v sync if the decoder can't drop, or we're still calculating the framerate -- if (m_iDroppedRequest > 5) -- { -- m_iDroppedRequest--; //decrease so we only drop half the frames -- return result | EOS_DROPPED; -- } -- m_iDroppedRequest++; -- } -- } -- else -+ if ((m_droppingStats.m_requestOutputDrop && !(pPicture->iFlags & DVP_FLAG_NOSKIP)) -+ || (pPicture->iFlags & DVP_FLAG_DROPPED)) - { -- m_iDroppedRequest = 0; -+ m_droppingStats.AddOutputDropGain(pts, 1/m_fFrameRate); -+ m_droppingStats.m_requestOutputDrop = false; -+ CLog::Log(LOGDEBUG,"%s - dropped in output", __FUNCTION__); -+ return result | EOS_DROPPED; - } - - if( m_speed < 0 ) - { -- if( iClockSleep < -DVD_MSEC_TO_TIME(200) -- && !(pPicture->iFlags & DVP_FLAG_NOSKIP) ) -+ double decoderPts = m_droppingStats.m_lastDecoderPts; -+ double renderPts = m_droppingStats.m_lastRenderPts; -+ if (pts > renderPts) -+ { -+ if (decoderPts >= renderPts) -+ { -+ Sleep(200); -+ } - return result | EOS_DROPPED; -+ } - } - -- if( (pPicture->iFlags & DVP_FLAG_DROPPED) ) -- return result | EOS_DROPPED; -- -- if( m_speed != DVD_PLAYSPEED_NORMAL && limited ) -+ if( m_speed != DVD_PLAYSPEED_NORMAL && m_speed >= 0 && limited ) - { - // calculate frame dropping pattern to render at this speed - // we do that by deciding if this or next frame is closest -@@ -1360,7 +1361,7 @@ int CDVDPlayerVideo::OutputPicture(const DVDVideoPicture* src, double pts) - if (index < 0) - return EOS_DROPPED; - -- g_renderManager.FlipPage(CThread::m_bStop, (iCurrentClock + iSleepTime) / DVD_TIME_BASE, -1, mDisplayField); -+ g_renderManager.FlipPage(CThread::m_bStop, (iCurrentClock + iSleepTime) / DVD_TIME_BASE, pts, -1, mDisplayField); - - return result; - #else -@@ -1659,3 +1660,136 @@ void CDVDPlayerVideo::CalcFrameRate() - m_iFrameRateCount = 0; - } - } -+ -+int CDVDPlayerVideo::CalcDropRequirement(double pts) -+{ -+ int result = 0; -+ double iSleepTime; -+ double iDecoderPts, iRenderPts; -+ double iInterval; -+ int interlaced; -+ double iGain; -+ double iLateness; -+ bool bNewFrame; -+ int iSkippedDeint = 0; -+ int iBufferLevel; -+ -+ // get decoder stats -+ if (!m_pVideoCodec->GetPts(iDecoderPts, iSkippedDeint, interlaced)) -+ iDecoderPts = pts; -+ if (iDecoderPts == DVD_NOPTS_VALUE) -+ iDecoderPts = pts; -+ -+ // get render stats -+ g_renderManager.GetStats(iSleepTime, iRenderPts, iBufferLevel); -+ -+ if (iBufferLevel < 0) -+ result |= EOS_BUFFER_LEVEL; -+ else if (iBufferLevel < 2) -+ { -+ result |= EOS_BUFFER_LEVEL; -+ CLog::Log(LOGDEBUG,"CDVDPlayerVideo::CalcDropRequirement - hurry: %d", iBufferLevel); -+ } -+ -+ bNewFrame = iDecoderPts != m_droppingStats.m_lastDecoderPts; -+ -+ if (interlaced) -+ iInterval = 2/m_fFrameRate*(double)DVD_TIME_BASE; -+ else -+ iInterval = 1/m_fFrameRate*(double)DVD_TIME_BASE; -+ -+ if (m_droppingStats.m_lastDecoderPts > 0 -+ && bNewFrame -+ && m_bAllowDrop -+ && m_droppingStats.m_dropRequests > 0) -+ { -+ iGain = (iDecoderPts - m_droppingStats.m_lastDecoderPts - iInterval)/(double)DVD_TIME_BASE; -+ if (iSkippedDeint) -+ { -+ CDroppingStats::CGain gain; -+ gain.gain = 1/m_fFrameRate; -+ gain.pts = iDecoderPts; -+ m_droppingStats.m_gain.push_back(gain); -+ m_droppingStats.m_totalGain += gain.gain; -+ result |= EOS_DROPPED; -+ m_droppingStats.m_dropRequests = 0; -+ CLog::Log(LOGDEBUG,"CDVDPlayerVideo::CalcDropRequirement - dropped de-interlacing cycle, Sleeptime: %f, Bufferlevel: %d", iSleepTime, iBufferLevel); -+ } -+ else if (iGain > 1/m_fFrameRate) -+ { -+ CDroppingStats::CGain gain; -+ gain.gain = iGain; -+ gain.pts = iDecoderPts; -+ m_droppingStats.m_gain.push_back(gain); -+ m_droppingStats.m_totalGain += iGain; -+ result |= EOS_DROPPED; -+ m_droppingStats.m_dropRequests = 0; -+ CLog::Log(LOGDEBUG,"CDVDPlayerVideo::CalcDropRequirement - dropped in decoder, Sleeptime: %f, Bufferlevel: %d, Gain: %f", iSleepTime, iBufferLevel, iGain); -+ } -+ } -+ m_droppingStats.m_lastDecoderPts = iDecoderPts; -+ -+ // subtract gains -+ while (!m_droppingStats.m_gain.empty() && -+ iRenderPts >= m_droppingStats.m_gain.front().pts) -+ { -+ m_droppingStats.m_totalGain -= m_droppingStats.m_gain.front().gain; -+ m_droppingStats.m_gain.pop_front(); -+ } -+ -+ // calculate lateness -+ iLateness = iSleepTime + m_droppingStats.m_totalGain; -+ if (iLateness < 0 && m_speed) -+ { -+ if (bNewFrame) -+ m_droppingStats.m_lateFrames++; -+ -+ // if lateness is smaller than frametime, we observe this state -+ // for 10 cycles -+ if (m_droppingStats.m_lateFrames > 10 || iLateness < -2/m_fFrameRate) -+ { -+ // is frame allowed to skip -+ if (m_iNrOfPicturesNotToSkip <= 0) -+ { -+ result |= EOS_VERYLATE; -+ -+ // drop in output -+ if (m_droppingStats.m_dropRequests > 7 && g_graphicsContext.IsFullScreenVideo()) -+ { -+ m_droppingStats.m_dropRequests--; //decrease so we only drop half the frames -+ m_droppingStats.m_requestOutputDrop = true; -+ } -+ else if (bNewFrame) -+ m_droppingStats.m_dropRequests++; -+ } -+ } -+ } -+ else -+ { -+ m_droppingStats.m_dropRequests = 0; -+ m_droppingStats.m_lateFrames = 0; -+ m_droppingStats.m_requestOutputDrop = false; -+ } -+ m_droppingStats.m_lastRenderPts = iRenderPts; -+ return result; -+} -+ -+void CDroppingStats::Reset() -+{ -+ m_gain.clear(); -+ m_totalGain = 0; -+ m_lastDecoderPts = 0; -+ m_lastRenderPts = 0; -+ m_lateFrames = 0; -+ m_dropRequests = 0; -+ m_requestOutputDrop = false; -+} -+ -+void CDroppingStats::AddOutputDropGain(double pts, double frametime) -+{ -+ CDroppingStats::CGain gain; -+ gain.gain = frametime; -+ gain.pts = pts; -+ m_gain.push_back(gain); -+ m_totalGain += frametime; -+} -diff --git a/xbmc/cores/dvdplayer/DVDPlayerVideo.h b/xbmc/cores/dvdplayer/DVDPlayerVideo.h -index fe7e12c..4913712 100644 ---- a/xbmc/cores/dvdplayer/DVDPlayerVideo.h -+++ b/xbmc/cores/dvdplayer/DVDPlayerVideo.h -@@ -37,6 +37,26 @@ - - #define VIDEO_PICTURE_QUEUE_SIZE 1 - -+class CDroppingStats -+{ -+public: -+ void Reset(); -+ void AddOutputDropGain(double pts, double frametime); -+ struct CGain -+ { -+ double gain; -+ double pts; -+ }; -+ std::deque m_gain; -+ double m_totalGain; -+ double m_lastDecoderPts; -+ double m_lastRenderPts; -+ unsigned int m_lateFrames; -+ unsigned int m_dropRequests; -+ bool m_requestOutputDrop; -+}; -+ -+ - class CDVDPlayerVideo : public CThread - { - public: -@@ -110,6 +130,7 @@ class CDVDPlayerVideo : public CThread - #define EOS_ABORT 1 - #define EOS_DROPPED 2 - #define EOS_VERYLATE 4 -+#define EOS_BUFFER_LEVEL 8 - - void AutoCrop(DVDVideoPicture* pPicture); - void AutoCrop(DVDVideoPicture *pPicture, RECT &crop); -@@ -135,6 +156,7 @@ class CDVDPlayerVideo : public CThread - - void ResetFrameRateCalc(); - void CalcFrameRate(); -+ int CalcDropRequirement(double pts); - - double m_fFrameRate; //framerate of the video currently playing - bool m_bCalcFrameRate; //if we should calculate the framerate from the timestamps -@@ -195,5 +217,7 @@ class CDVDPlayerVideo : public CThread - CPullupCorrection m_pullupCorrection; - - std::list m_packets; -+ -+ CDroppingStats m_droppingStats; - }; - --- -1.7.10 - - -From cf731f6c3d24d7e53ed79402b01666aa6dae0991 Mon Sep 17 00:00:00 2001 -From: xbmc -Date: Sun, 2 Sep 2012 16:05:21 +0200 -Subject: [PATCH 21/88] video player: present correct pts to user for a/v sync - (after buffering in renderer) - ---- - xbmc/cores/dvdplayer/DVDPlayerVideo.cpp | 41 +++++++++++++++++++------------ - xbmc/cores/dvdplayer/DVDPlayerVideo.h | 2 +- - 2 files changed, 26 insertions(+), 17 deletions(-) - -diff --git a/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp b/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp -index 5484073..8ac5a32 100644 ---- a/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp -+++ b/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp -@@ -1260,22 +1260,6 @@ int CDVDPlayerVideo::OutputPicture(const DVDVideoPicture* src, double pts) - else - iSleepTime = iFrameSleep + (iClockSleep - iFrameSleep) / m_autosync; - --#ifdef PROFILE /* during profiling, try to play as fast as possible */ -- iSleepTime = 0; --#endif -- -- // present the current pts of this frame to user, and include the actual -- // presentation delay, to allow him to adjust for it -- if( m_stalled ) -- m_iCurrentPts = DVD_NOPTS_VALUE; -- else -- m_iCurrentPts = pts - max(0.0, iSleepTime); -- -- // timestamp when we think next picture should be displayed based on current duration -- m_FlipTimeStamp = iCurrentClock; -- m_FlipTimeStamp += max(0.0, iSleepTime); -- m_FlipTimeStamp += iFrameDuration; -- - if ((m_droppingStats.m_requestOutputDrop && !(pPicture->iFlags & DVP_FLAG_NOSKIP)) - || (pPicture->iFlags & DVP_FLAG_DROPPED)) - { -@@ -1580,6 +1564,22 @@ void CDVDPlayerVideo::ResetFrameRateCalc() - g_advancedSettings.m_videoFpsDetect == 0; - } - -+double CDVDPlayerVideo::GetCurrentPts() -+{ -+ double iSleepTime, iRenderPts; -+ int iBufferLevel; -+ -+ // get render stats -+ g_renderManager.GetStats(iSleepTime, iRenderPts, iBufferLevel); -+ -+ if( m_stalled ) -+ iRenderPts = DVD_NOPTS_VALUE; -+ else -+ iRenderPts = iRenderPts - max(0.0, iSleepTime); -+ -+ return iRenderPts; -+} -+ - #define MAXFRAMERATEDIFF 0.01 - #define MAXFRAMESERR 1000 - -@@ -1698,6 +1698,15 @@ int CDVDPlayerVideo::CalcDropRequirement(double pts) - else - iInterval = 1/m_fFrameRate*(double)DVD_TIME_BASE; - -+ -+ m_FlipTimeStamp = m_pClock->GetAbsoluteClock() + max(0.0, iSleepTime) + iInterval; -+ -+ if( m_stalled ) -+ m_iCurrentPts = DVD_NOPTS_VALUE; -+ else -+ m_iCurrentPts = iRenderPts - max(0.0, iSleepTime); -+ -+ - if (m_droppingStats.m_lastDecoderPts > 0 - && bNewFrame - && m_bAllowDrop -diff --git a/xbmc/cores/dvdplayer/DVDPlayerVideo.h b/xbmc/cores/dvdplayer/DVDPlayerVideo.h -index 4913712..509d5f7 100644 ---- a/xbmc/cores/dvdplayer/DVDPlayerVideo.h -+++ b/xbmc/cores/dvdplayer/DVDPlayerVideo.h -@@ -108,7 +108,7 @@ class CDVDPlayerVideo : public CThread - - bool InitializedOutputDevice(); - -- double GetCurrentPts() { return m_iCurrentPts; } -+ double GetCurrentPts(); - int GetPullupCorrection() { return m_pullupCorrection.GetPatternLength(); } - - double GetOutputDelay(); /* returns the expected delay, from that a packet is put in queue */ --- -1.7.10 - - -From 5e05def8121969dbf936848e2025e419e68335a5 Mon Sep 17 00:00:00 2001 -From: xbmc -Date: Sat, 16 Feb 2013 18:25:53 +0100 -Subject: [PATCH 22/88] videoplayer: some rework and documentation - ---- - .../dvdplayer/DVDCodecs/Video/DVDVideoCodec.h | 29 ++++++++++++++++++-- - .../DVDCodecs/Video/DVDVideoCodecFFmpeg.cpp | 11 ++++++++ - .../DVDCodecs/Video/DVDVideoCodecFFmpeg.h | 2 +- - xbmc/cores/dvdplayer/DVDPlayerVideo.cpp | 2 +- - 4 files changed, 40 insertions(+), 4 deletions(-) - -diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodec.h b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodec.h -index 5001aac..e84e65f 100644 ---- a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodec.h -+++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodec.h -@@ -132,7 +132,6 @@ struct DVDVideoUserData - #define VC_USERDATA 0x00000008 // the decoder found some userdata, call Decode(NULL, 0) again to parse the rest of the data - #define VC_FLUSHED 0x00000010 // the decoder lost it's state, we need to restart decoding again - #define VC_DROPPED 0x00000020 // needed to identify if a picture was dropped --#define VC_HURRY 0x00000040 - - class CDVDVideoCodec - { -@@ -245,10 +244,36 @@ class CDVDVideoCodec - return 0; - } - -- virtual bool GetPts(double &pts, int &skippedDeint, int &interlaced) -+ /** -+ * For calculation of dropping requirements player asks for some information. -+ * -+ * - pts : right after decoder, used to detect gaps (dropped frames in decoder) -+ * - skippedDeint : indicates if decoder has just skipped a deinterlacing cycle -+ * instead of dropping a full frame -+ * - interlaced : when detecting gaps in pts, player needs to know whether -+ * it's interlaced or not -+ * -+ * If codec does not implement this method, pts of decoded frame at input -+ * video player is used. In case coded does post-proc and de-interlacing there -+ * may be quite some frames queued up between exit decoder and entry player. -+ */ -+ virtual bool GetCodecStats(double &pts, int &skippedDeint, int &interlaced) - { - return false; - } - -+ /** -+ * Codec can be informed by player with the following flags: -+ * -+ * DVP_FLAG_NO_POSTPROC : if speed is not normal the codec can switch off -+ * postprocessing and de-interlacing -+ * -+ * DVP_FLAG_DRAIN : codecs may do postprocessing and de-interlacing. -+ * If video buffers in RenderManager are about to run dry, -+ * this is signaled to codec. Codec can wait for post-proc -+ * to be finished instead of returning empty and getting another -+ * packet. -+ * -+ */ - virtual void SetCodecControl(int flags) {} - }; -diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.cpp b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.cpp -index dae3b8e..2c2353d 100644 ---- a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.cpp -+++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.cpp -@@ -888,6 +888,17 @@ unsigned CDVDVideoCodecFFmpeg::GetConvergeCount() - return 0; - } - -+bool CDVDVideoCodecFFmpeg::GetCodecStats(double &pts, int &skippedDeint, int &interlaced) -+{ -+ pts = m_decoderPts; -+ skippedDeint = m_skippedDeint; -+ if (m_pFrame) -+ interlaced = m_pFrame->interlaced_frame; -+ else -+ interlaced = 0; -+ return true; -+} -+ - void CDVDVideoCodecFFmpeg::SetCodecControl(int flags) - { - m_codecControlFlags = flags; -diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.h b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.h -index 52e1113..3631f7f 100644 ---- a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.h -+++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.h -@@ -61,7 +61,7 @@ class CDVDVideoCodecFFmpeg : public CDVDVideoCodec - virtual unsigned int SetFilters(unsigned int filters); - virtual const char* GetName() { return m_name.c_str(); }; // m_name is never changed after open - virtual unsigned GetConvergeCount(); -- virtual bool GetPts(double &pts, int &skippedDeint, int &interlaced) {pts=m_decoderPts; skippedDeint=m_skippedDeint; if (m_pFrame) interlaced = m_pFrame->interlaced_frame; return true;} -+ virtual bool GetCodecStats(double &pts, int &skippedDeint, int &interlaced); - virtual void SetCodecControl(int flags); - - bool IsHardwareAllowed() { return !m_bSoftware; } -diff --git a/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp b/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp -index 8ac5a32..12b08ac 100644 ---- a/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp -+++ b/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp -@@ -1675,7 +1675,7 @@ int CDVDPlayerVideo::CalcDropRequirement(double pts) - int iBufferLevel; - - // get decoder stats -- if (!m_pVideoCodec->GetPts(iDecoderPts, iSkippedDeint, interlaced)) -+ if (!m_pVideoCodec->GetCodecStats(iDecoderPts, iSkippedDeint, interlaced)) - iDecoderPts = pts; - if (iDecoderPts == DVD_NOPTS_VALUE) - iDecoderPts = pts; --- -1.7.10 - - -From 903e78e4320a8549eccd0a710eac7747032c18eb Mon Sep 17 00:00:00 2001 -From: xbmc -Date: Fri, 1 Mar 2013 09:57:16 +0100 -Subject: [PATCH 23/88] Revert "dvdplayer: disable buffering unit dropping is - improves" - -This reverts commit de1caf5686c1fb53cb7ab11b356e6c22770740db. ---- - xbmc/cores/dvdplayer/DVDPlayerVideo.cpp | 16 ++++++++-------- - 1 file changed, 8 insertions(+), 8 deletions(-) - -diff --git a/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp b/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp -index 12b08ac..3297513 100644 ---- a/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp -+++ b/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp -@@ -1118,35 +1118,35 @@ int CDVDPlayerVideo::OutputPicture(const DVDVideoPicture* src, double pts) - { - case RENDER_FMT_YUV420P: - formatstr = "YV12"; -- buffering = false; -+ buffering = true; - break; - case RENDER_FMT_YUV420P16: - formatstr = "YV12P16"; -- buffering = false; -+ buffering = true; - break; - case RENDER_FMT_YUV420P10: - formatstr = "YV12P10"; -- buffering = false; -+ buffering = true; - break; - case RENDER_FMT_NV12: - formatstr = "NV12"; -- buffering = false; -+ buffering = true; - break; - case RENDER_FMT_UYVY422: - formatstr = "UYVY"; -- buffering = false; -+ buffering = true; - break; - case RENDER_FMT_YUYV422: - formatstr = "YUY2"; -- buffering = false; -+ buffering = true; - break; - case RENDER_FMT_VDPAU: - formatstr = "VDPAU"; -- buffering = false; -+ buffering = true; - break; - case RENDER_FMT_DXVA: - formatstr = "DXVA"; -- buffering = false; -+ buffering = true; - break; - case RENDER_FMT_VAAPI: - formatstr = "VAAPI"; --- -1.7.10 - - -From 82974290389d5caa2692079301b167cb80323491 Mon Sep 17 00:00:00 2001 -From: xbmc -Date: Mon, 28 May 2012 10:41:31 +0200 -Subject: [PATCH 24/88] videoplayer: update frametime, it might change due to - fps detection - ---- - xbmc/cores/dvdplayer/DVDPlayerVideo.cpp | 2 ++ - 1 file changed, 2 insertions(+) - -diff --git a/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp b/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp -index 3297513..8eb2eda 100644 ---- a/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp -+++ b/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp -@@ -719,6 +719,8 @@ void CDVDPlayerVideo::Process() - CDVDCodecUtils::FreePicture(pTempYUVPackedPicture); - #endif - -+ frametime = (double)DVD_TIME_BASE/m_fFrameRate; -+ - if(m_started == false) - { - m_codecname = m_pVideoCodec->GetName(); --- -1.7.10 - - -From 5b62f34f8013302cd10c06944120032ec1f8d555 Mon Sep 17 00:00:00 2001 -From: xbmc -Date: Mon, 28 May 2012 10:43:06 +0200 -Subject: [PATCH 25/88] videoplayer: give streams with invalid fps a chance - for fps detection - ---- - xbmc/cores/dvdplayer/DVDPlayerVideo.cpp | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp b/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp -index 8eb2eda..d004153 100644 ---- a/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp -+++ b/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp -@@ -1606,7 +1606,7 @@ void CDVDPlayerVideo::CalcFrameRate() - double frameduration = m_pullupCorrection.GetFrameDuration(); - - if (frameduration == DVD_NOPTS_VALUE || -- (g_advancedSettings.m_videoFpsDetect == 1 && m_pullupCorrection.GetPatternLength() > 1)) -+ (g_advancedSettings.m_videoFpsDetect == 1 && (m_pullupCorrection.GetPatternLength() > 1 && !m_bFpsInvalid))) - { - //reset the stored framerates if no good framerate was detected - m_fStableFrameRate = 0.0; --- -1.7.10 - - -From 7493aa51685421085be83c56c62267709b22c65f Mon Sep 17 00:00:00 2001 -From: xbmc -Date: Mon, 28 May 2012 10:49:05 +0200 -Subject: [PATCH 26/88] dvdplayer: allow rewinding at end of stream, do a seek - after rewind - ---- - xbmc/cores/dvdplayer/DVDPlayer.cpp | 8 +++++++- - 1 file changed, 7 insertions(+), 1 deletion(-) - -diff --git a/xbmc/cores/dvdplayer/DVDPlayer.cpp b/xbmc/cores/dvdplayer/DVDPlayer.cpp -index 0cd2510..3737419 100644 ---- a/xbmc/cores/dvdplayer/DVDPlayer.cpp -+++ b/xbmc/cores/dvdplayer/DVDPlayer.cpp -@@ -1542,7 +1542,7 @@ void CDVDPlayer::HandlePlaySpeed() - - } - else if (m_CurrentVideo.id >= 0 -- && m_CurrentVideo.inited == true -+ && (m_CurrentVideo.inited == true || GetPlaySpeed() < 0) // allow rewind at end of file - && m_SpeedState.lastpts != m_dvdPlayerVideo.GetCurrentPts() - && m_SpeedState.lasttime != GetTime()) - { -@@ -2183,6 +2183,12 @@ void CDVDPlayer::HandleMessages() - pvrinputstream->Pause( speed == 0 ); - } - -+ // do a seek after rewind, clock is not in sync with current pts -+ if (m_playSpeed < 0 && speed >= 0) -+ { -+ m_messenger.Put(new CDVDMsgPlayerSeek(GetTime(), true, true, true)); -+ } -+ - // if playspeed is different then DVD_PLAYSPEED_NORMAL or DVD_PLAYSPEED_PAUSE - // audioplayer, stops outputing audio to audiorendere, but still tries to - // sleep an correct amount for each packet --- -1.7.10 - - -From 4ae2ba6880415872258c400fae19e58307ed4828 Mon Sep 17 00:00:00 2001 -From: xbmc -Date: Sat, 7 Apr 2012 09:19:00 +0200 -Subject: [PATCH 27/88] vdpau: redesign - ---- - language/English/strings.po | 12 +- - system/shaders/yuv2rgb_basic.glsl | 12 + - xbmc/cores/VideoRenderers/LinuxRendererGL.cpp | 203 +- - xbmc/cores/VideoRenderers/LinuxRendererGL.h | 13 +- - xbmc/cores/VideoRenderers/RenderFormats.h | 1 + - xbmc/cores/VideoRenderers/RenderManager.cpp | 3 +- - xbmc/cores/VideoRenderers/RenderManager.h | 2 +- - .../VideoRenderers/VideoShaders/YUV2RGBShader.cpp | 2 + - .../dvdplayer/DVDCodecs/Video/DVDVideoCodec.h | 4 +- - .../DVDCodecs/Video/DVDVideoCodecFFmpeg.cpp | 23 +- - .../DVDCodecs/Video/DVDVideoCodecFFmpeg.h | 1 - - xbmc/cores/dvdplayer/DVDCodecs/Video/VDPAU.cpp | 3800 +++++++++++++++----- - xbmc/cores/dvdplayer/DVDCodecs/Video/VDPAU.h | 662 +++- - xbmc/cores/dvdplayer/DVDPlayerVideo.cpp | 4 + - xbmc/settings/AdvancedSettings.cpp | 8 +- - xbmc/settings/AdvancedSettings.h | 4 +- - xbmc/settings/GUISettings.cpp | 2 + - xbmc/settings/GUIWindowSettingsCategory.cpp | 34 + - xbmc/utils/ActorProtocol.cpp | 253 ++ - xbmc/utils/ActorProtocol.h | 87 + - xbmc/utils/Makefile | 1 + - xbmc/video/dialogs/GUIDialogVideoSettings.cpp | 2 +- - xbmc/windowing/X11/WinSystemX11.h | 1 + - 23 files changed, 3942 insertions(+), 1192 deletions(-) - create mode 100644 xbmc/utils/ActorProtocol.cpp - create mode 100644 xbmc/utils/ActorProtocol.h - -diff --git a/language/English/strings.po b/language/English/strings.po -index dff2978..88292d3 100644 ---- a/language/English/strings.po -+++ b/language/English/strings.po -@@ -5114,7 +5114,15 @@ msgctxt "#13434" - msgid "Play only this" - msgstr "" - --#empty strings from id 13435 to 13499 -+msgctxt "#13435" -+msgid "Allow Vdpau OpenGL interop" -+msgstr "" -+ -+msgctxt "#13436" -+msgid "Allow Vdpau OpenGL interop YUV" -+msgstr "" -+ -+#empty strings from id 13437 to 13499 - - msgctxt "#13500" - msgid "A/V sync method" -@@ -6333,7 +6341,7 @@ msgid "Software Blend" - msgstr "" - - msgctxt "#16325" --msgid "Auto - ION Optimized" -+msgid "VDPAU - Bob" - msgstr "" - - #empty strings from id 16326 to 16399 -diff --git a/system/shaders/yuv2rgb_basic.glsl b/system/shaders/yuv2rgb_basic.glsl -index 88c33b2..aa26174 100644 ---- a/system/shaders/yuv2rgb_basic.glsl -+++ b/system/shaders/yuv2rgb_basic.glsl -@@ -70,6 +70,18 @@ void main() - rgb.a = gl_Color.a; - gl_FragColor = rgb; - -+#elif defined(XBMC_VDPAU_NV12) -+ -+ vec4 yuv, rgb; -+ yuv.rgba = vec4( texture2D(m_sampY, stretch(m_cordY)).r -+ , texture2D(m_sampU, stretch(m_cordU)).r -+ , texture2D(m_sampV, stretch(m_cordV)).g -+ , 1.0 ); -+ -+ rgb = m_yuvmat * yuv; -+ rgb.a = gl_Color.a; -+ gl_FragColor = rgb; -+ - #elif defined(XBMC_YUY2) || defined(XBMC_UYVY) - - #if(XBMC_texture_rectangle) -diff --git a/xbmc/cores/VideoRenderers/LinuxRendererGL.cpp b/xbmc/cores/VideoRenderers/LinuxRendererGL.cpp -index a2dc2be..4ee50c1 100644 ---- a/xbmc/cores/VideoRenderers/LinuxRendererGL.cpp -+++ b/xbmc/cores/VideoRenderers/LinuxRendererGL.cpp -@@ -689,6 +689,18 @@ void CLinuxRendererGL::RenderUpdate(bool clear, DWORD flags, DWORD alpha) - glDisable(GL_POLYGON_STIPPLE); - - } -+ else if(m_format == RENDER_FMT_VDPAU_420 -+ && !(flags & RENDER_FLAG_BOTH)) -+ { -+ glDisable(GL_BLEND); -+ glColor4f(1.0f, 1.0f, 1.0f, 1.0f); -+ Render(flags | RENDER_FLAG_TOP, index); -+ -+ glEnable(GL_BLEND); -+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); -+ glColor4f(1.0f, 1.0f, 1.0f, 128 / 255.0f); -+ Render(flags | RENDER_FLAG_BOT , index); -+ } - else - Render(flags, index); - -@@ -769,11 +781,6 @@ void CLinuxRendererGL::FlipPage(int source) - - m_buffers[m_iYV12RenderBuffer].flipindex = ++m_flipindex; - --#ifdef HAVE_LIBVDPAU -- if((m_renderMethod & RENDER_VDPAU) && m_buffers[m_iYV12RenderBuffer].vdpau) -- m_buffers[m_iYV12RenderBuffer].vdpau->Present(); --#endif -- - return; - } - -@@ -1100,6 +1107,12 @@ void CLinuxRendererGL::LoadShaders(int field) - 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; -@@ -1175,7 +1188,10 @@ void CLinuxRendererGL::Render(DWORD flags, int renderBuffer) - m_currentField = FIELD_FULL; - - // call texture load function -+ m_skipRender = false; - (this->*m_textureUpload)(renderBuffer); -+ if (m_skipRender) -+ return; - - if (m_renderMethod & RENDER_GLSL) - { -@@ -1541,17 +1557,12 @@ void CLinuxRendererGL::RenderFromFBO() - void CLinuxRendererGL::RenderVDPAU(int index, int field) - { - #ifdef HAVE_LIBVDPAU -- YUVPLANE &plane = m_buffers[index].fields[field][0]; -- CVDPAU *vdpau = m_buffers[m_iYV12RenderBuffer].vdpau; -- -- if (!vdpau) -- return; -+ YUVPLANE &plane = m_buffers[index].fields[0][1]; - - glEnable(m_textureTarget); - glActiveTextureARB(GL_TEXTURE0); -- glBindTexture(m_textureTarget, plane.id); - -- vdpau->BindPixmap(); -+ glBindTexture(m_textureTarget, plane.id); - - // Try some clamping or wrapping - glTexParameteri(m_textureTarget, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); -@@ -1609,8 +1620,6 @@ void CLinuxRendererGL::RenderVDPAU(int index, int field) - if (m_pVideoFilterShader) - m_pVideoFilterShader->Disable(); - -- vdpau->ReleasePixmap(); -- - glBindTexture (m_textureTarget, 0); - glDisable(m_textureTarget); - #endif -@@ -2295,12 +2304,14 @@ void CLinuxRendererGL::DeleteVDPAUTexture(int index) - { - #ifdef HAVE_LIBVDPAU - YUVPLANE &plane = m_buffers[index].fields[0][0]; -+ YUVFIELDS &fields = m_buffers[index].fields; - - SAFE_RELEASE(m_buffers[index].vdpau); - - if(plane.id && glIsTexture(plane.id)) - glDeleteTextures(1, &plane.id); - plane.id = 0; -+ fields[0][1].id = 0; - #endif - } - -@@ -2334,11 +2345,152 @@ bool CLinuxRendererGL::CreateVDPAUTexture(int index) - void CLinuxRendererGL::UploadVDPAUTexture(int index) - { - #ifdef HAVE_LIBVDPAU -+ VDPAU::CVdpauRenderPicture *vdpau = m_buffers[index].vdpau; -+ -+ unsigned int flipindex = m_buffers[index].flipindex; -+ YUVFIELDS &fields = m_buffers[index].fields; -+ YUVPLANE &plane = fields[0][0]; -+ -+ if (!vdpau || !vdpau->valid) -+ { -+ m_eventTexturesDone[index]->Set(); -+ m_skipRender = true; -+ return; -+ } -+ -+ fields[0][1].id = vdpau->texture[0]; -+ -+ m_eventTexturesDone[index]->Set(); ++#if defined(HAVE_LIBXVBA) && defined(TARGET_LINUX) ++ hwSupport += "XVBA:yes "; ++#elif defined(TARGET_LINUX) ++ hwSupport += "XVBA:no "; +#endif -+} -+ -+void CLinuxRendererGL::DeleteVDPAUTexture420(int index) -+{ -+#ifdef HAVE_LIBVDPAU -+ YUVPLANE &plane = m_buffers[index].fields[0][0]; -+ YUVFIELDS &fields = m_buffers[index].fields; -+ -+ SAFE_RELEASE(m_buffers[index].vdpau); -+ -+ if(plane.id && glIsTexture(plane.id)) -+ glDeleteTextures(1, &plane.id); -+ plane.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; -+ } -+ -+ glEnable(m_textureTarget); -+ glGenTextures(1, &plane.id); -+ glDisable(m_textureTarget); -+ - m_eventTexturesDone[index]->Set(); -- glPixelStorei(GL_UNPACK_ALIGNMENT,1); //what's this for? - #endif -+ return true; - } -+void CLinuxRendererGL::UploadVDPAUTexture420(int index) -+{ -+#ifdef HAVE_LIBVDPAU -+ VDPAU::CVdpauRenderPicture *vdpau = m_buffers[index].vdpau; -+ YV12Image &im = m_buffers[index].image; -+ -+ unsigned int flipindex = m_buffers[index].flipindex; -+ YUVFIELDS &fields = m_buffers[index].fields; -+ YUVPLANE &plane = fields[0][0]; -+ -+ if (!vdpau || !vdpau->valid) -+ { -+ m_eventTexturesDone[index]->Set(); -+ m_skipRender = true; -+ return; -+ } -+ -+ im.height = vdpau->texHeight; -+ im.width = vdpau->texWidth; -+ -+ // YUV -+ for (int f = FIELD_FULL; f<=FIELD_BOT ; f++) -+ { -+ int fieldshift = (f==FIELD_FULL) ? 0 : 1; -+ YUVPLANES &planes = fields[f]; -+ -+ planes[0].texwidth = im.width; -+ planes[0].texheight = im.height >> fieldshift; -+ -+ 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[2][0].id = vdpau->texture[1]; -+ fields[2][1].id = vdpau->texture[3]; -+ -+ glEnable(m_textureTarget); -+ for (int f = 1; f < 3; 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(); -+ } -+ fields[f][2].id = fields[f][1].id; -+ } -+ CalculateTextureSourceRects(index, 3); -+ glDisable(m_textureTarget); -+ -+ m_eventTexturesDone[index]->Set(); -+#endif -+} + CLog::Log(LOGDEBUG, "CDVDFactoryCodec: compiled in hardware support: %s", hwSupport.c_str()); - void CLinuxRendererGL::DeleteVAAPITexture(int index) - { -@@ -3276,12 +3428,13 @@ bool CLinuxRendererGL::Supports(EINTERLACEMETHOD method) - if(method == VS_INTERLACEMETHOD_AUTO) - return true; - -- if(m_renderMethod & RENDER_VDPAU) -+ if(m_renderMethod & RENDER_VDPAU || -+ m_format == RENDER_FMT_VDPAU_420) - { - #ifdef HAVE_LIBVDPAU -- CVDPAU *vdpau = m_buffers[m_iYV12RenderBuffer].vdpau; -- if(vdpau) -- return vdpau->Supports(method); -+ VDPAU::CVdpauRenderPicture *vdpauPic = m_buffers[m_iYV12RenderBuffer].vdpau; -+ if(vdpauPic && vdpauPic->vdpau) -+ return vdpauPic->vdpau->Supports(method); - #endif - return false; - } -@@ -3367,14 +3520,7 @@ EINTERLACEMETHOD CLinuxRendererGL::AutoInterlaceMethod() - return VS_INTERLACEMETHOD_NONE; - - if(m_renderMethod & RENDER_VDPAU) -- { --#ifdef HAVE_LIBVDPAU -- CVDPAU *vdpau = m_buffers[m_iYV12RenderBuffer].vdpau; -- if(vdpau) -- return vdpau->AutoInterlaceMethod(); --#endif - return VS_INTERLACEMETHOD_NONE; -- } - - if(Supports(VS_INTERLACEMETHOD_RENDER_BOB)) - return VS_INTERLACEMETHOD_RENDER_BOB; -@@ -3417,11 +3563,12 @@ void CLinuxRendererGL::UnBindPbo(YUVBUFFER& buff) - } - - #ifdef HAVE_LIBVDPAU --void CLinuxRendererGL::AddProcessor(CVDPAU* vdpau, int index) -+void CLinuxRendererGL::AddProcessor(VDPAU::CVdpauRenderPicture *vdpau, int index) - { - YUVBUFFER &buf = m_buffers[index]; -+ VDPAU::CVdpauRenderPicture *pic = vdpau->Acquire(); - SAFE_RELEASE(buf.vdpau); -- buf.vdpau = (CVDPAU*)vdpau->Acquire(); -+ buf.vdpau = pic; - } - #endif - -diff --git a/xbmc/cores/VideoRenderers/LinuxRendererGL.h b/xbmc/cores/VideoRenderers/LinuxRendererGL.h -index a7b5886..329ddee 100644 ---- a/xbmc/cores/VideoRenderers/LinuxRendererGL.h -+++ b/xbmc/cores/VideoRenderers/LinuxRendererGL.h -@@ -38,12 +38,11 @@ - - class CRenderCapture; - --class CVDPAU; - class CBaseTexture; - namespace Shaders { class BaseYUV2RGBShader; } - namespace Shaders { class BaseVideoFilterShader; } - namespace VAAPI { struct CHolder; } -- -+namespace VDPAU { class CVdpauRenderPicture; } - - #undef ALIGN - #define ALIGN(value, alignment) (((value)+((alignment)-1))&~((alignment)-1)) -@@ -142,7 +141,7 @@ class CLinuxRendererGL : public CBaseRenderer - virtual unsigned int GetProcessorSize() { return m_NumYV12Buffers; } - - #ifdef HAVE_LIBVDPAU -- virtual void AddProcessor(CVDPAU* vdpau, int index); -+ virtual void AddProcessor(VDPAU::CVdpauRenderPicture* vdpau, int index); - #endif +diff -Naur xbmc-12.0.4/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.cpp xbmc-12.0.4.patch/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.cpp +--- xbmc-12.0.4/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.cpp 2013-03-08 13:01:31.000000000 +0100 ++++ xbmc-12.0.4.patch/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.cpp 2013-03-10 13:00:12.323988163 +0100 +@@ -56,6 +56,9 @@ #ifdef HAVE_LIBVA - virtual void AddProcessor(VAAPI::CHolder& holder, int index); -@@ -193,6 +192,10 @@ class CLinuxRendererGL : public CBaseRenderer - void DeleteVDPAUTexture(int index); - bool CreateVDPAUTexture(int index); - -+ void UploadVDPAUTexture420(int index); -+ void DeleteVDPAUTexture420(int index); -+ bool CreateVDPAUTexture420(int index); -+ - void UploadVAAPITexture(int index); - void DeleteVAAPITexture(int index); - bool CreateVAAPITexture(int index); -@@ -219,6 +222,7 @@ class CLinuxRendererGL : public CBaseRenderer - void RenderSinglePass(int renderBuffer, int field); // single pass glsl renderer - void RenderSoftware(int renderBuffer, int field); // single pass s/w yuv2rgb renderer - void RenderVDPAU(int renderBuffer, int field); // render using vdpau hardware -+ void RenderVDPAUYV12(int renderBuffer, int field); // render using vdpau hardware - void RenderVAAPI(int renderBuffer, int field); // render using vdpau hardware - - struct -@@ -279,7 +283,7 @@ class CLinuxRendererGL : public CBaseRenderer - GLuint pbo[MAX_PLANES]; - - #ifdef HAVE_LIBVDPAU -- CVDPAU* vdpau; -+ VDPAU::CVdpauRenderPicture *vdpau; + #include "VAAPI.h" #endif - #ifdef HAVE_LIBVA - VAAPI::CHolder& vaapi; -@@ -325,6 +329,7 @@ class CLinuxRendererGL : public CBaseRenderer - bool m_nonLinStretch; - bool m_nonLinStretchGui; - float m_pixelRatio; -+ bool m_skipRender; - }; ++#ifdef HAVE_LIBXVBA ++#include "XVBA.h" ++#endif + using namespace boost; -diff --git a/xbmc/cores/VideoRenderers/RenderFormats.h b/xbmc/cores/VideoRenderers/RenderFormats.h -index 09f8f5d..0262c60 100644 ---- a/xbmc/cores/VideoRenderers/RenderFormats.h -+++ b/xbmc/cores/VideoRenderers/RenderFormats.h -@@ -26,6 +26,7 @@ enum ERenderFormat { - RENDER_FMT_YUV420P10, - RENDER_FMT_YUV420P16, - RENDER_FMT_VDPAU, -+ RENDER_FMT_VDPAU_420, - RENDER_FMT_NV12, - RENDER_FMT_UYVY422, - RENDER_FMT_YUYV422, -diff --git a/xbmc/cores/VideoRenderers/RenderManager.cpp b/xbmc/cores/VideoRenderers/RenderManager.cpp -index c4ca57e..b89ec67 100644 ---- a/xbmc/cores/VideoRenderers/RenderManager.cpp -+++ b/xbmc/cores/VideoRenderers/RenderManager.cpp -@@ -860,7 +860,8 @@ int CXBMCRenderManager::AddVideoPicture(DVDVideoPicture& pic) - CDVDCodecUtils::CopyDXVA2Picture(&image, &pic); - } - #ifdef HAVE_LIBVDPAU -- else if(pic.format == RENDER_FMT_VDPAU) -+ else if(pic.format == RENDER_FMT_VDPAU -+ || pic.format == RENDER_FMT_VDPAU_420) - m_pRenderer->AddProcessor(pic.vdpau, index); - #endif - #ifdef HAVE_LIBOPENMAX -diff --git a/xbmc/cores/VideoRenderers/RenderManager.h b/xbmc/cores/VideoRenderers/RenderManager.h -index b3e6547..e4bd614 100644 ---- a/xbmc/cores/VideoRenderers/RenderManager.h -+++ b/xbmc/cores/VideoRenderers/RenderManager.h -@@ -35,7 +35,7 @@ - - namespace DXVA { class CProcessor; } - namespace VAAPI { class CSurfaceHolder; } --class CVDPAU; -+namespace VDPAU { class CVdpauRenderPicture; } - struct DVDVideoPicture; - - #define ERRORBUFFSIZE 30 -diff --git a/xbmc/cores/VideoRenderers/VideoShaders/YUV2RGBShader.cpp b/xbmc/cores/VideoRenderers/VideoShaders/YUV2RGBShader.cpp -index 58f26b0..50606eb 100644 ---- a/xbmc/cores/VideoRenderers/VideoShaders/YUV2RGBShader.cpp -+++ b/xbmc/cores/VideoRenderers/VideoShaders/YUV2RGBShader.cpp -@@ -201,6 +201,8 @@ static void CalculateYUVMatrixGL(GLfloat res[4][4] - m_defines += "#define XBMC_YUY2\n"; - else if (m_format == RENDER_FMT_UYVY422) - m_defines += "#define XBMC_UYVY\n"; -+ else if (RENDER_FMT_VDPAU_420) -+ m_defines += "#define XBMC_VDPAU_NV12\n"; - else - CLog::Log(LOGERROR, "GL: BaseYUV2RGBGLSLShader - unsupported format %d", m_format); - -diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodec.h b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodec.h -index e84e65f..64c5f5f 100644 ---- a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodec.h -+++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodec.h -@@ -34,7 +34,7 @@ - - namespace DXVA { class CSurfaceContext; } - namespace VAAPI { struct CHolder; } --class CVDPAU; -+namespace VDPAU { class CVdpauRenderPicture; } - class COpenMax; - class COpenMaxVideo; - struct OpenMaxVideoBuffer; -@@ -55,7 +55,7 @@ struct DVDVideoPicture - DXVA::CSurfaceContext* context; - }; - struct { -- CVDPAU* vdpau; -+ VDPAU::CVdpauRenderPicture* vdpau; - }; - struct { - VAAPI::CHolder* vaapi; -diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.cpp b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.cpp -index 2c2353d..e0c0f84 100644 ---- a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.cpp -+++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.cpp -@@ -71,14 +71,14 @@ enum PixelFormat CDVDVideoCodecFFmpeg::GetFormat( struct AVCodecContext * avctx +@@ -71,14 +74,14 @@ while(*cur != PIX_FMT_NONE) { #ifdef HAVE_LIBVDPAU @@ -4289,7 +1234,43 @@ index 2c2353d..e0c0f84 100644 { ctx->SetHardware(vdp); return *cur; -@@ -205,14 +205,27 @@ bool CDVDVideoCodecFFmpeg::Open(CDVDStreamInfo &hints, CDVDCodecOptions &options +@@ -100,13 +103,26 @@ + dec->Release(); + } + #endif ++#ifdef HAVE_LIBXVBA ++ if(*cur == PIX_FMT_XVBA_VLD && g_guiSettings.GetBool("videoplayer.usexvba")) ++ { ++ XVBA::CDecoder* dec = new XVBA::CDecoder(); ++ if(dec->Open(avctx, *cur, ctx->m_uSurfacesCount)) ++ { ++ ctx->SetHardware(dec); ++ return *cur; ++ } ++ else ++ dec->Release(); ++ } ++#endif + #ifdef HAVE_LIBVA + // mpeg4 vaapi decoding is disabled + if(*cur == PIX_FMT_VAAPI_VLD && g_guiSettings.GetBool("videoplayer.usevaapi") + && (avctx->codec_id != CODEC_ID_MPEG4 || g_advancedSettings.m_videoAllowMpeg4VAAPI)) + { + VAAPI::CDecoder* dec = new VAAPI::CDecoder(); +- if(dec->Open(avctx, *cur)) ++ if(dec->Open(avctx, *cur, ctx->m_uSurfacesCount)) + { + ctx->SetHardware(dec); + return *cur; +@@ -142,6 +158,7 @@ + m_iLastKeyframe = 0; + m_dts = DVD_NOPTS_VALUE; + m_started = false; ++ m_decoderPts = DVD_NOPTS_VALUE; + } + + CDVDVideoCodecFFmpeg::~CDVDVideoCodecFFmpeg() +@@ -204,14 +221,27 @@ continue; CLog::Log(LOGNOTICE,"CDVDVideoCodecFFmpeg::Open() Creating VDPAU(%ix%i, %d)",hints.width, hints.height, hints.codec); @@ -4319,10 +1300,75 @@ index 2c2353d..e0c0f84 100644 { m_pHardware = vdp; m_pCodecContext->codec_id = CODEC_ID_NONE; // ffmpeg will complain if this has been set -diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.h b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.h -index 3631f7f..17a12d0 100644 ---- a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.h -+++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.h +@@ -340,6 +370,14 @@ + { + if( m_pCodecContext ) + { ++ if (bDrop && m_pHardware && m_pHardware->CanSkipDeint()) ++ { ++ m_requestSkipDeint = true; ++ bDrop = false; ++ } ++ else ++ m_requestSkipDeint = false; ++ + // i don't know exactly how high this should be set + // couldn't find any good docs on it. think it varies + // from codec to codec on what it does +@@ -541,6 +579,7 @@ + void CDVDVideoCodecFFmpeg::Reset() + { + m_started = false; ++ m_decoderPts = DVD_NOPTS_VALUE; + m_iLastKeyframe = m_pCodecContext->has_b_frames; + m_dllAvCodec.avcodec_flush_buffers(m_pCodecContext); + +@@ -639,6 +678,22 @@ + else + pDvdVideoPicture->pts = DVD_NOPTS_VALUE; + ++ if (pDvdVideoPicture->pts != DVD_NOPTS_VALUE) ++ m_decoderPts = pDvdVideoPicture->pts; ++ else ++ m_decoderPts = m_dts; ++ ++ if (m_requestSkipDeint) ++ { ++ pDvdVideoPicture->iFlags |= DVP_FLAG_DROPDEINT; ++ m_skippedDeint = 1; ++ } ++ else ++ m_skippedDeint = 0; ++ ++ m_requestSkipDeint = false; ++ pDvdVideoPicture->iFlags |= m_codecControlFlags; ++ + if(!m_started) + pDvdVideoPicture->iFlags |= DVP_FLAG_DROPPED; + +@@ -861,3 +916,19 @@ + else + return 0; + } ++ ++bool CDVDVideoCodecFFmpeg::GetCodecStats(double &pts, int &skippedDeint, int &interlaced) ++{ ++ pts = m_decoderPts; ++ skippedDeint = m_skippedDeint; ++ if (m_pFrame) ++ interlaced = m_pFrame->interlaced_frame; ++ else ++ interlaced = 0; ++ return true; ++} ++ ++void CDVDVideoCodecFFmpeg::SetCodecControl(int flags) ++{ ++ m_codecControlFlags = flags; ++} +diff -Naur xbmc-12.0.4/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.h xbmc-12.0.4.patch/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.h +--- xbmc-12.0.4/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.h 2013-03-08 13:01:31.000000000 +0100 ++++ xbmc-12.0.4.patch/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.h 2013-03-10 13:00:12.295988364 +0100 @@ -28,7 +28,6 @@ #include "DllSwScale.h" #include "DllAvFilter.h" @@ -4331,10 +1377,183 @@ index 3631f7f..17a12d0 100644 class CCriticalSection; class CDVDVideoCodecFFmpeg : public CDVDVideoCodec -diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/VDPAU.cpp b/xbmc/cores/dvdplayer/DVDCodecs/Video/VDPAU.cpp -index f70a4f9..07cfc04 100644 ---- a/xbmc/cores/dvdplayer/DVDCodecs/Video/VDPAU.cpp -+++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/VDPAU.cpp +@@ -44,6 +43,7 @@ + virtual bool GetPicture(AVCodecContext* avctx, AVFrame* frame, DVDVideoPicture* picture) = 0; + virtual int Check (AVCodecContext* avctx) = 0; + virtual void Reset () {} ++ virtual bool CanSkipDeint() {return false; } + virtual const std::string Name() = 0; + virtual CCriticalSection* Section() { return NULL; } + }; +@@ -60,6 +60,8 @@ + virtual unsigned int SetFilters(unsigned int filters); + virtual const char* GetName() { return m_name.c_str(); }; // m_name is never changed after open + virtual unsigned GetConvergeCount(); ++ virtual bool GetCodecStats(double &pts, int &skippedDeint, int &interlaced); ++ virtual void SetCodecControl(int flags); + + bool IsHardwareAllowed() { return !m_bSoftware; } + IHardwareDecoder * GetHardware() { return m_pHardware; }; +@@ -119,4 +121,8 @@ + double m_dts; + bool m_started; + std::vector m_formats; ++ double m_decoderPts, m_decoderInterval; ++ int m_skippedDeint; ++ bool m_requestSkipDeint; ++ int m_codecControlFlags; + }; +diff -Naur xbmc-12.0.4/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodec.h xbmc-12.0.4.patch/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodec.h +--- xbmc-12.0.4/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodec.h 2013-03-08 13:01:31.000000000 +0100 ++++ xbmc-12.0.4.patch/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodec.h 2013-03-10 13:00:12.323988163 +0100 +@@ -34,7 +34,8 @@ + + namespace DXVA { class CSurfaceContext; } + namespace VAAPI { struct CHolder; } +-class CVDPAU; ++namespace VDPAU { class CVdpauRenderPicture; } ++namespace XVBA { class CXvbaRenderPicture; } + class COpenMax; + class COpenMaxVideo; + struct OpenMaxVideoBuffer; +@@ -55,11 +56,14 @@ + DXVA::CSurfaceContext* context; + }; + struct { +- CVDPAU* vdpau; ++ VDPAU::CVdpauRenderPicture* vdpau; + }; + struct { + VAAPI::CHolder* vaapi; + }; ++ struct { ++ XVBA::CXvbaRenderPicture* xvba; ++ }; + + struct { + COpenMax *openMax; +@@ -110,6 +114,10 @@ + #define DVP_FLAG_NOSKIP 0x00000010 // indicate this picture should never be dropped + #define DVP_FLAG_DROPPED 0x00000020 // indicate that this picture has been dropped in decoder stage, will have no data + ++#define DVP_FLAG_DROPDEINT 0x00000040 // indicate that this picture was requested to have been dropped in deint stage ++#define DVP_FLAG_NO_POSTPROC 0x00000100 ++#define DVP_FLAG_DRAIN 0x00000200 ++ + // DVP_FLAG 0x00000100 - 0x00000f00 is in use by libmpeg2! + + #define DVP_QSCALE_UNKNOWN 0 +@@ -127,6 +135,8 @@ + #define VC_PICTURE 0x00000004 // the decoder got a picture, call Decode(NULL, 0) again to parse the rest of the data + #define VC_USERDATA 0x00000008 // the decoder found some userdata, call Decode(NULL, 0) again to parse the rest of the data + #define VC_FLUSHED 0x00000010 // the decoder lost it's state, we need to restart decoding again ++#define VC_DROPPED 0x00000020 // needed to identify if a picture was dropped ++ + class CDVDVideoCodec + { + public: +@@ -237,4 +247,37 @@ + { + return 0; + } ++ ++ /** ++ * For calculation of dropping requirements player asks for some information. ++ * ++ * - pts : right after decoder, used to detect gaps (dropped frames in decoder) ++ * - skippedDeint : indicates if decoder has just skipped a deinterlacing cycle ++ * instead of dropping a full frame ++ * - interlaced : when detecting gaps in pts, player needs to know whether ++ * it's interlaced or not ++ * ++ * If codec does not implement this method, pts of decoded frame at input ++ * video player is used. In case coded does post-proc and de-interlacing there ++ * may be quite some frames queued up between exit decoder and entry player. ++ */ ++ virtual bool GetCodecStats(double &pts, int &skippedDeint, int &interlaced) ++ { ++ return false; ++ } ++ ++ /** ++ * Codec can be informed by player with the following flags: ++ * ++ * DVP_FLAG_NO_POSTPROC : if speed is not normal the codec can switch off ++ * postprocessing and de-interlacing ++ * ++ * DVP_FLAG_DRAIN : codecs may do postprocessing and de-interlacing. ++ * If video buffers in RenderManager are about to run dry, ++ * this is signaled to codec. Codec can wait for post-proc ++ * to be finished instead of returning empty and getting another ++ * packet. ++ * ++ */ ++ virtual void SetCodecControl(int flags) {} + }; +diff -Naur xbmc-12.0.4/xbmc/cores/dvdplayer/DVDCodecs/Video/Makefile.in xbmc-12.0.4.patch/xbmc/cores/dvdplayer/DVDCodecs/Video/Makefile.in +--- xbmc-12.0.4/xbmc/cores/dvdplayer/DVDCodecs/Video/Makefile.in 2013-03-08 13:01:31.000000000 +0100 ++++ xbmc-12.0.4.patch/xbmc/cores/dvdplayer/DVDCodecs/Video/Makefile.in 2013-03-10 13:00:12.323988163 +0100 +@@ -14,6 +14,10 @@ + SRCS += CrystalHD.cpp + SRCS += DVDVideoCodecCrystalHD.cpp + endif ++ifeq (@USE_XVBA@,1) ++SRCS+= XVBA.cpp \ ++ ++endif + ifeq (@USE_VDA@,1) + SRCS += DVDVideoCodecVDA.cpp + endif +diff -Naur xbmc-12.0.4/xbmc/cores/dvdplayer/DVDCodecs/Video/VAAPI.cpp xbmc-12.0.4.patch/xbmc/cores/dvdplayer/DVDCodecs/Video/VAAPI.cpp +--- xbmc-12.0.4/xbmc/cores/dvdplayer/DVDCodecs/Video/VAAPI.cpp 2013-03-08 13:01:31.000000000 +0100 ++++ xbmc-12.0.4.patch/xbmc/cores/dvdplayer/DVDCodecs/Video/VAAPI.cpp 2013-03-10 13:00:12.325988148 +0100 +@@ -261,6 +261,15 @@ + + bool CDecoder::Open(AVCodecContext *avctx, enum PixelFormat fmt, unsigned int surfaces) + { ++#ifdef HAVE_LIBXVBA ++ std::string Vendor = g_Windowing.GetRenderVendor(); ++ std::transform(Vendor.begin(), Vendor.end(), Vendor.begin(), ::tolower); ++ if (Vendor.compare(0, 3, "ati") == 0) ++ { ++ return false; ++ } ++#endif ++ + VAEntrypoint entrypoint = VAEntrypointVLD; + VAProfile profile; + +@@ -357,6 +366,7 @@ + CHECK(vaCreateConfig(m_display->get(), profile, entrypoint, &attrib, 1, &m_hwaccel->config_id)) + m_config = m_hwaccel->config_id; + ++ m_renderbuffers_count = surfaces; + if (!EnsureContext(avctx)) + return false; + +@@ -388,7 +398,7 @@ + else + m_refs = 2; + } +- return EnsureSurfaces(avctx, m_refs + 3); ++ return EnsureSurfaces(avctx, m_refs + m_renderbuffers_count + 1); + } + + bool CDecoder::EnsureSurfaces(AVCodecContext *avctx, unsigned n_surfaces_count) +diff -Naur xbmc-12.0.4/xbmc/cores/dvdplayer/DVDCodecs/Video/VAAPI.h xbmc-12.0.4.patch/xbmc/cores/dvdplayer/DVDCodecs/Video/VAAPI.h +--- xbmc-12.0.4/xbmc/cores/dvdplayer/DVDCodecs/Video/VAAPI.h 2013-03-08 13:01:31.000000000 +0100 ++++ xbmc-12.0.4.patch/xbmc/cores/dvdplayer/DVDCodecs/Video/VAAPI.h 2013-03-10 13:00:12.284988442 +0100 +@@ -122,6 +122,7 @@ + static const unsigned m_surfaces_max = 32; + unsigned m_surfaces_count; + VASurfaceID m_surfaces[m_surfaces_max]; ++ unsigned m_renderbuffers_count; + + int m_refs; + std::list m_surfaces_used; +diff -Naur xbmc-12.0.4/xbmc/cores/dvdplayer/DVDCodecs/Video/VDPAU.cpp xbmc-12.0.4.patch/xbmc/cores/dvdplayer/DVDCodecs/Video/VDPAU.cpp +--- xbmc-12.0.4/xbmc/cores/dvdplayer/DVDCodecs/Video/VDPAU.cpp 2013-03-08 13:01:31.000000000 +0100 ++++ xbmc-12.0.4.patch/xbmc/cores/dvdplayer/DVDCodecs/Video/VDPAU.cpp 2013-03-10 13:00:12.333988091 +0100 @@ -32,11 +32,16 @@ #include "settings/AdvancedSettings.h" #include "Application.h" @@ -4353,31 +1572,23 @@ index f70a4f9..07cfc04 100644 {"MPEG1", VDP_DECODER_PROFILE_MPEG1}, {"MPEG2_SIMPLE", VDP_DECODER_PROFILE_MPEG2_SIMPLE}, {"MPEG2_MAIN", VDP_DECODER_PROFILE_MPEG2_MAIN}, -@@ -50,14 +55,16 @@ +@@ -50,14 +55,7 @@ {"MPEG4_PART2_ASP", VDP_DECODER_PROFILE_MPEG4_PART2_ASP}, #endif }; -const size_t decoder_profile_count = sizeof(decoder_profiles)/sizeof(CVDPAU::Desc); -+const size_t decoder_profile_count = sizeof(decoder_profiles)/sizeof(CDecoder::Desc); - +- -static float studioCSC[3][4] = -{ - { 1.0f, 0.0f, 1.57480000f,-0.78740000f}, - { 1.0f,-0.18737736f,-0.46813736f, 0.32775736f}, - { 1.0f, 1.85556000f, 0.0f,-0.92780000f} -}; -+//static float studioCSC[3][4] = -+//{ -+// { 1.0f, 0.0f, 1.57480000f,-0.78740000f}, -+// { 1.0f,-0.18737736f,-0.46813736f, 0.32775736f}, -+// { 1.0f, 1.85556000f, 0.0f,-0.92780000f} -+//}; -+static float studioCSCKCoeffs601[3] = {0.299, 0.587, 0.114}; //BT601 {Kr, Kg, Kb} -+static float studioCSCKCoeffs709[3] = {0.2126, 0.7152, 0.0722}; //BT709 {Kr, Kg, Kb} ++const size_t decoder_profile_count = sizeof(decoder_profiles)/sizeof(CDecoder::Desc); static struct SInterlaceMapping { -@@ -68,88 +75,30 @@ +@@ -68,88 +66,30 @@ , {VS_INTERLACEMETHOD_VDPAU_TEMPORAL_HALF , VDP_VIDEO_MIXER_FEATURE_DEINTERLACE_TEMPORAL} , {VS_INTERLACEMETHOD_VDPAU_TEMPORAL_SPATIAL , VDP_VIDEO_MIXER_FEATURE_DEINTERLACE_TEMPORAL_SPATIAL} , {VS_INTERLACEMETHOD_VDPAU_TEMPORAL_SPATIAL_HALF, VDP_VIDEO_MIXER_FEATURE_DEINTERLACE_TEMPORAL_SPATIAL} @@ -4391,14 +1602,9 @@ index f70a4f9..07cfc04 100644 //so we just keep a static handle to libvdpau around -void* CVDPAU::dl_handle; +void* CDecoder::dl_handle; -+ -+//----------------------------------------------------------------------------- -+// CVDPAU -+//----------------------------------------------------------------------------- -CVDPAU::CVDPAU() -+CDecoder::CDecoder() : m_vdpauOutput(&m_inMsgEvent) - { +-{ - glXBindTexImageEXT = NULL; - glXReleaseTexImageEXT = NULL; - vdp_device = VDP_INVALID_HANDLE; @@ -4408,9 +1614,9 @@ index f70a4f9..07cfc04 100644 - m_DisplayState = VDPAU_OPEN; - m_mixerfield = VDP_VIDEO_MIXER_PICTURE_STRUCTURE_FRAME; - m_mixerstep = 0; -+ m_vdpauConfig.vdpDevice = VDP_INVALID_HANDLE; -+ m_vdpauConfig.videoSurfaces = &m_videoSurfaces; -+ m_vdpauConfig.videoSurfaceSec = &m_videoSurfaceSec; ++//----------------------------------------------------------------------------- ++// CVDPAU ++//----------------------------------------------------------------------------- - m_glPixmap = 0; - m_Pixmap = 0; @@ -4418,9 +1624,11 @@ index f70a4f9..07cfc04 100644 - glXBindTexImageEXT = (PFNGLXBINDTEXIMAGEEXTPROC)glXGetProcAddress((GLubyte *) "glXBindTexImageEXT"); - if (!glXReleaseTexImageEXT) - glXReleaseTexImageEXT = (PFNGLXRELEASETEXIMAGEEXTPROC)glXGetProcAddress((GLubyte *) "glXReleaseTexImageEXT"); -+ m_vdpauConfigured = false; -+ m_DisplayState = VDPAU_OPEN; -+} ++CDecoder::CDecoder() : m_vdpauOutput(&m_inMsgEvent) ++{ ++ m_vdpauConfig.vdpDevice = VDP_INVALID_HANDLE; ++ m_vdpauConfig.videoSurfaces = &m_videoSurfaces; ++ m_vdpauConfig.videoSurfaceSec = &m_videoSurfaceSec; - totalAvailableOutputSurfaces = 0; - outputSurface = presentSurface = VDP_INVALID_HANDLE; @@ -4473,14 +1681,16 @@ index f70a4f9..07cfc04 100644 - dl_vdp_device_create_x11 = NULL; - dl_vdp_get_proc_address = NULL; - dl_vdp_preemption_callback_register = NULL; --} -- ++ m_vdpauConfigured = false; ++ m_DisplayState = VDPAU_OPEN; + } + -bool CVDPAU::Open(AVCodecContext* avctx, const enum PixelFormat, unsigned int surfaces) +bool CDecoder::Open(AVCodecContext* avctx, const enum PixelFormat, unsigned int surfaces) { if(avctx->coded_width == 0 || avctx->coded_height == 0) -@@ -157,6 +106,8 @@ bool CVDPAU::Open(AVCodecContext* avctx, const enum PixelFormat, unsigned int su +@@ -157,6 +97,8 @@ CLog::Log(LOGWARNING,"(VDPAU) no width/height available, can't init"); return false; } @@ -4489,7 +1699,7 @@ index f70a4f9..07cfc04 100644 if (!dl_handle) { -@@ -168,8 +119,6 @@ bool CVDPAU::Open(AVCodecContext* avctx, const enum PixelFormat, unsigned int su +@@ -168,8 +110,6 @@ error = "dlerror() returned NULL"; CLog::Log(LOGNOTICE,"(VDPAU) Unable to get handle to libvdpau: %s", error); @@ -4498,7 +1708,7 @@ index f70a4f9..07cfc04 100644 return false; } } -@@ -178,8 +127,9 @@ bool CVDPAU::Open(AVCodecContext* avctx, const enum PixelFormat, unsigned int su +@@ -178,18 +118,18 @@ return false; InitVDPAUProcs(); @@ -4509,7 +1719,18 @@ index f70a4f9..07cfc04 100644 { SpewHardwareAvailable(); -@@ -197,25 +147,23 @@ bool CVDPAU::Open(AVCodecContext* avctx, const enum PixelFormat, unsigned int su + VdpDecoderProfile profile = 0; + if(avctx->codec_id == CODEC_ID_H264) + profile = VDP_DECODER_PROFILE_H264_HIGH; +-#ifdef VDP_DECODER_PROFILE_MPEG4_PART2_ASP + else if(avctx->codec_id == CODEC_ID_MPEG4) + profile = VDP_DECODER_PROFILE_MPEG4_PART2_ASP; +-#endif ++ + if(profile) + { + if (!CDVDCodecUtils::IsVP3CompatibleWidth(avctx->coded_width)) +@@ -197,25 +137,23 @@ /* attempt to create a decoder with this width/height, some sizes are not supported by hw */ VdpStatus vdp_st; @@ -4541,7 +1762,7 @@ index f70a4f9..07cfc04 100644 avctx->slice_flags=SLICE_FLAG_CODED_ORDER|SLICE_FLAG_ALLOW_FIELD; g_Windowing.Register(this); -@@ -224,17 +172,20 @@ bool CVDPAU::Open(AVCodecContext* avctx, const enum PixelFormat, unsigned int su +@@ -224,17 +162,20 @@ return false; } @@ -4564,7 +1785,7 @@ index f70a4f9..07cfc04 100644 while (!m_videoSurfaces.empty()) { -@@ -250,188 +201,111 @@ void CVDPAU::Close() +@@ -250,188 +191,111 @@ m_dllAvUtil.Unload(); } @@ -4598,20 +1819,22 @@ index f70a4f9..07cfc04 100644 - GLXFBConfig *fbConfigs; - fbConfigs = glXChooseFBConfig(m_Display, DefaultScreen(m_Display), doubleVisAttributes, &num); - if (fbConfigs==NULL) -+ // check if we should do some pre-cleanup here -+ // a second decoder might need resources -+ if (m_vdpauConfigured == true) - { +- { - CLog::Log(LOGERROR, "GLX Error: MakePixmap: No compatible framebuffers found"); - return false; - } - CLog::Log(LOGDEBUG, "Found %d fbconfigs.", num); - fbConfigIndex = 0; - CLog::Log(LOGDEBUG, "Using fbconfig index %d.", fbConfigIndex); +- +- m_glPixmap = glXCreatePixmap(m_Display, fbConfigs[fbConfigIndex], m_Pixmap, pixmapAttribs); ++ // check if we should do some pre-cleanup here ++ // a second decoder might need resources ++ if (m_vdpauConfigured == true) ++ { + CSingleLock lock(m_DecoderSection); + CLog::Log(LOGNOTICE,"CVDPAU::Release pre-cleanup"); - -- m_glPixmap = glXCreatePixmap(m_Display, fbConfigs[fbConfigIndex], m_Pixmap, pixmapAttribs); ++ + Message *reply; + if (m_vdpauOutput.m_controlPort.SendOutMessageSync(COutputControlProtocol::PRECLEANUP, + &reply, @@ -4810,7 +2033,7 @@ index f70a4f9..07cfc04 100644 state = m_DisplayState; } -@@ -445,16 +319,13 @@ int CVDPAU::Check(AVCodecContext* avctx) +@@ -445,16 +309,13 @@ } else { @@ -4829,7 +2052,7 @@ index f70a4f9..07cfc04 100644 FiniVDPAUOutput(); FiniVDPAUProcs(); -@@ -469,7 +340,7 @@ int CVDPAU::Check(AVCodecContext* avctx) +@@ -469,7 +330,7 @@ return 0; } @@ -4838,7 +2061,7 @@ index f70a4f9..07cfc04 100644 { if ((format >= PIX_FMT_VDPAU_H264) && (format <= PIX_FMT_VDPAU_VC1)) return true; #if (defined PIX_FMT_VDPAU_MPEG4_IN_AVUTIL) -@@ -478,91 +349,28 @@ bool CVDPAU::IsVDPAUFormat(PixelFormat format) +@@ -478,255 +339,45 @@ else return false; } @@ -4932,19 +2155,14 @@ index f70a4f9..07cfc04 100644 + || method == VS_INTERLACEMETHOD_AUTO) return true; -+ if (g_guiSettings.GetBool("videoplayer.usevdpauinteropyuv")) -+ { -+ if (method == VS_INTERLACEMETHOD_RENDER_BOB) -+ return true; -+ } -+ - for(SInterlaceMapping* p = g_interlace_mapping; p->method != VS_INTERLACEMETHOD_NONE; p++) - { - if(p->method == method) -@@ -571,162 +379,12 @@ bool CVDPAU::Supports(EINTERLACEMETHOD method) - return false; - } - +- for(SInterlaceMapping* p = g_interlace_mapping; p->method != VS_INTERLACEMETHOD_NONE; p++) +- { +- if(p->method == method) +- return Supports(p->feature); +- } +- return false; +-} +- -EINTERLACEMETHOD CVDPAU::AutoInterlaceMethod() -{ - return VS_INTERLACEMETHOD_VDPAU_TEMPORAL; @@ -4988,12 +2206,15 @@ index f70a4f9..07cfc04 100644 - VdpStatus vdp_st; - - if (!g_settings.m_currentVideoSettings.m_NoiseReduction) -- { ++ if (!m_vdpauConfig.usePixmaps) + { - VdpBool enabled[]= {0}; - vdp_st = vdp_video_mixer_set_feature_enables(videoMixer, ARSIZE(feature), feature, enabled); - CheckStatus(vdp_st, __LINE__); - return; -- } ++ if (method == VS_INTERLACEMETHOD_RENDER_BOB) ++ return true; + } - VdpBool enabled[]={1}; - vdp_st = vdp_video_mixer_set_feature_enables(videoMixer, ARSIZE(feature), feature, enabled); - CheckStatus(vdp_st, __LINE__); @@ -5002,7 +2223,7 @@ index f70a4f9..07cfc04 100644 - vdp_st = vdp_video_mixer_set_attribute_values(videoMixer, ARSIZE(attributes), attributes, nr); - CheckStatus(vdp_st, __LINE__); -} -- + -void CVDPAU::SetSharpness() -{ - if(!Supports(VDP_VIDEO_MIXER_FEATURE_SHARPNESS)) @@ -5011,14 +2232,19 @@ index f70a4f9..07cfc04 100644 - VdpVideoMixerFeature feature[] = { VDP_VIDEO_MIXER_FEATURE_SHARPNESS }; - VdpVideoMixerAttribute attributes[] = { VDP_VIDEO_MIXER_ATTRIBUTE_SHARPNESS_LEVEL }; - VdpStatus vdp_st; -- ++ if (method == VS_INTERLACEMETHOD_VDPAU_INVERSE_TELECINE) ++ return false; + - if (!g_settings.m_currentVideoSettings.m_Sharpness) -- { ++ for(SInterlaceMapping* p = g_interlace_mapping; p->method != VS_INTERLACEMETHOD_NONE; p++) + { - VdpBool enabled[]={0}; - vdp_st = vdp_video_mixer_set_feature_enables(videoMixer, ARSIZE(feature), feature, enabled); - CheckStatus(vdp_st, __LINE__); - return; -- } ++ if(p->method == method) ++ return Supports(p->feature); + } - VdpBool enabled[]={1}; - vdp_st = vdp_video_mixer_set_feature_enables(videoMixer, ARSIZE(feature), feature, enabled); - CheckStatus(vdp_st, __LINE__); @@ -5040,8 +2266,9 @@ index f70a4f9..07cfc04 100644 - vdp_st = vdp_video_mixer_set_feature_enables(videoMixer, ARSIZE(feature), feature, enabled); - CheckStatus(vdp_st, __LINE__); -#endif --} -- ++ return false; + } + -void CVDPAU::SetDeinterlacing() +EINTERLACEMETHOD CDecoder::AutoInterlaceMethod() { @@ -5107,7 +2334,7 @@ index f70a4f9..07cfc04 100644 { char* error; -@@ -736,151 +394,115 @@ void CVDPAU::InitVDPAUProcs() +@@ -736,151 +387,115 @@ if (error) { CLog::Log(LOGERROR,"(VDPAU) - %s in %s",error,__FUNCTION__); @@ -5257,28 +2484,17 @@ index f70a4f9..07cfc04 100644 +void CDecoder::FiniVDPAUProcs() { - if (vdp_device == VDP_INVALID_HANDLE) return; -+ if (m_vdpauConfig.vdpDevice == VDP_INVALID_HANDLE) return; - - VdpStatus vdp_st; +- +- VdpStatus vdp_st; - vdp_st = vdp_device_destroy(vdp_device); -+ vdp_st = m_vdpauConfig.vdpProcs.vdp_device_destroy(m_vdpauConfig.vdpDevice); - CheckStatus(vdp_st, __LINE__); +- CheckStatus(vdp_st, __LINE__); - vdp_device = VDP_INVALID_HANDLE; - vdpauConfigured = false; -+ m_vdpauConfig.vdpDevice = VDP_INVALID_HANDLE; - } +-} ++ if (m_vdpauConfig.vdpDevice == VDP_INVALID_HANDLE) return; -void CVDPAU::InitCSCMatrix(int Height) -+void CDecoder::FiniVDPAUOutput() - { -+ if (m_vdpauConfig.vdpDevice == VDP_INVALID_HANDLE || !m_vdpauConfigured) return; -+ -+ CLog::Log(LOGNOTICE, " (VDPAU) %s", __FUNCTION__); -+ -+ // uninit output -+ m_vdpauOutput.Dispose(); -+ m_vdpauConfigured = false; -+ +-{ VdpStatus vdp_st; - m_Procamp.struct_version = VDP_PROCAMP_VERSION; - m_Procamp.brightness = 0.0; @@ -5288,19 +2504,27 @@ index f70a4f9..07cfc04 100644 - vdp_st = vdp_generate_csc_matrix(&m_Procamp, - (Height < 720)? VDP_COLOR_STANDARD_ITUR_BT_601 : VDP_COLOR_STANDARD_ITUR_BT_709, - &m_CSCMatrix); -- CheckStatus(vdp_st, __LINE__); --} -- --void CVDPAU::FiniVDPAUOutput() --{ -- FiniOutputMethod(); ++ vdp_st = m_vdpauConfig.vdpProcs.vdp_device_destroy(m_vdpauConfig.vdpDevice); + CheckStatus(vdp_st, __LINE__); ++ m_vdpauConfig.vdpDevice = VDP_INVALID_HANDLE; + } +-void CVDPAU::FiniVDPAUOutput() ++void CDecoder::FiniVDPAUOutput() + { +- FiniOutputMethod(); +- - if (vdp_device == VDP_INVALID_HANDLE || !vdpauConfigured) return; -- -- CLog::Log(LOGNOTICE, " (VDPAU) %s", __FUNCTION__); -- -- VdpStatus vdp_st; -- ++ if (m_vdpauConfig.vdpDevice == VDP_INVALID_HANDLE || !m_vdpauConfigured) return; + + CLog::Log(LOGNOTICE, " (VDPAU) %s", __FUNCTION__); + ++ // uninit output ++ m_vdpauOutput.Dispose(); ++ m_vdpauConfigured = false; ++ + VdpStatus vdp_st; + - vdp_st = vdp_decoder_destroy(decoder); + vdp_st = m_vdpauConfig.vdpProcs.vdp_decoder_destroy(m_vdpauConfig.vdpDecoder); if (CheckStatus(vdp_st, __LINE__)) @@ -5322,7 +2546,7 @@ index f70a4f9..07cfc04 100644 render->surface = VDP_INVALID_HANDLE; } if (CheckStatus(vdp_st, __LINE__)) -@@ -888,8 +510,7 @@ void CVDPAU::FiniVDPAUOutput() +@@ -888,8 +503,7 @@ } } @@ -5332,19 +2556,21 @@ index f70a4f9..07cfc04 100644 , VdpDecoderProfile &vdp_decoder_profile , VdpChromaType &vdp_chroma_type) { -@@ -916,9 +537,9 @@ void CVDPAU::ReadFormatOf( PixelFormat fmt +@@ -915,13 +529,10 @@ + vdp_decoder_profile = VDP_DECODER_PROFILE_VC1_ADVANCED; vdp_chroma_type = VDP_CHROMA_TYPE_420; break; - #if (defined PIX_FMT_VDPAU_MPEG4_IN_AVUTIL) && \ +-#if (defined PIX_FMT_VDPAU_MPEG4_IN_AVUTIL) && \ - (defined VDP_DECODER_PROFILE_MPEG4_PART2_ASP) -+ (defined VDP_DECODER_PROFILE_MP) case PIX_FMT_VDPAU_MPEG4: -- vdp_decoder_profile = VDP_DECODER_PROFILE_MPEG4_PART2_ASP; -+ vdp_decoder_profile = VDP_DECOPEG4_PART2_ASP; + vdp_decoder_profile = VDP_DECODER_PROFILE_MPEG4_PART2_ASP; vdp_chroma_type = VDP_CHROMA_TYPE_420; break; - #endif -@@ -929,170 +550,78 @@ void CVDPAU::ReadFormatOf( PixelFormat fmt +-#endif + default: + vdp_decoder_profile = 0; + vdp_chroma_type = 0; +@@ -929,170 +540,78 @@ } } @@ -5360,11 +2586,12 @@ index f70a4f9..07cfc04 100644 - vid_height = avctx->height; - surface_width = avctx->coded_width; - surface_height = avctx->coded_height; - +- - past[1] = past[0] = current = future = NULL; - CLog::Log(LOGNOTICE, " (VDPAU) screenWidth:%i vidWidth:%i surfaceWidth:%i",OutWidth,vid_width,surface_width); - CLog::Log(LOGNOTICE, " (VDPAU) screenHeight:%i vidHeight:%i surfaceHeight:%i",OutHeight,vid_height,surface_height); - ReadFormatOf(avctx->pix_fmt, vdp_decoder_profile, vdp_chroma_type); ++ + m_vdpauConfig.vidWidth = avctx->width; + m_vdpauConfig.vidHeight = avctx->height; + m_vdpauConfig.surfaceWidth = avctx->coded_width; @@ -5563,7 +2790,7 @@ index f70a4f9..07cfc04 100644 { VdpStatus rv; CLog::Log(LOGNOTICE,"VDPAU Decoder capabilities:"); -@@ -1102,7 +631,7 @@ void CVDPAU::SpewHardwareAvailable() //Copyright (c) 2008 Wladimir J. van der L +@@ -1102,7 +621,7 @@ { VdpBool is_supported = false; uint32_t max_level, max_macroblocks, max_width, max_height; @@ -5572,7 +2799,7 @@ index f70a4f9..07cfc04 100644 &is_supported, &max_level, &max_macroblocks, &max_width, &max_height); if(rv == VDP_STATUS_OK && is_supported) { -@@ -1111,13 +640,13 @@ void CVDPAU::SpewHardwareAvailable() //Copyright (c) 2008 Wladimir J. van der L +@@ -1111,13 +630,13 @@ } } CLog::Log(LOGNOTICE,"------------------------------------"); @@ -5589,7 +2816,7 @@ index f70a4f9..07cfc04 100644 } \ } while(false) -@@ -1141,7 +670,7 @@ void CVDPAU::SpewHardwareAvailable() //Copyright (c) 2008 Wladimir J. van der L +@@ -1141,7 +660,7 @@ } @@ -5598,7 +2825,7 @@ index f70a4f9..07cfc04 100644 { // find render state in queue bool found(false); -@@ -1168,34 +697,33 @@ bool CVDPAU::IsSurfaceValid(vdpau_render_state *render) +@@ -1168,34 +687,33 @@ return true; } @@ -5648,7 +2875,7 @@ index f70a4f9..07cfc04 100644 } } -@@ -1204,21 +732,22 @@ int CVDPAU::FFGetBuffer(AVCodecContext *avctx, AVFrame *pic) +@@ -1204,21 +722,22 @@ { // create a new surface VdpDecoderProfile profile; @@ -5674,7 +2901,7 @@ index f70a4f9..07cfc04 100644 avctx->coded_width, avctx->coded_height, &render->surface); -@@ -1239,18 +768,6 @@ int CVDPAU::FFGetBuffer(AVCodecContext *avctx, AVFrame *pic) +@@ -1239,18 +758,6 @@ pic->linesize[0] = pic->linesize[1] = pic->linesize[2] = 0; @@ -5693,7 +2920,7 @@ index f70a4f9..07cfc04 100644 pic->type= FF_BUFFER_TYPE_USER; render->state |= FF_VDPAU_STATE_USED_FOR_REFERENCE; -@@ -1258,15 +775,16 @@ int CVDPAU::FFGetBuffer(AVCodecContext *avctx, AVFrame *pic) +@@ -1258,15 +765,16 @@ return 0; } @@ -5713,7 +2940,7 @@ index f70a4f9..07cfc04 100644 render=(vdpau_render_state*)pic->data[0]; if(!render) -@@ -1275,6 +793,8 @@ void CVDPAU::FFReleaseBuffer(AVCodecContext *avctx, AVFrame *pic) +@@ -1275,6 +783,8 @@ return; } @@ -5722,7 +2949,7 @@ index f70a4f9..07cfc04 100644 for(i=0; i<4; i++) pic->data[i]= NULL; -@@ -1289,21 +809,18 @@ void CVDPAU::FFReleaseBuffer(AVCodecContext *avctx, AVFrame *pic) +@@ -1289,21 +799,18 @@ } @@ -5749,7 +2976,7 @@ index f70a4f9..07cfc04 100644 if(src->linesize[0] || src->linesize[1] || src->linesize[2] || offset[0] || offset[1] || offset[2]) -@@ -1333,59 +850,41 @@ void CVDPAU::FFDrawSlice(struct AVCodecContext *s, +@@ -1333,59 +840,41 @@ if(s->pix_fmt == PIX_FMT_VDPAU_H264) max_refs = render->info.h264.num_ref_frames; @@ -5824,7 +3051,7 @@ index f70a4f9..07cfc04 100644 if(pFrame) { // we have a new frame from decoder -@@ -1393,7 +892,10 @@ int CVDPAU::Decode(AVCodecContext *avctx, AVFrame *pFrame) +@@ -1393,7 +882,10 @@ if(!render) // old style ffmpeg gave data on plane 0 render = (vdpau_render_state*)pFrame->data[0]; if(!render) @@ -5835,59 +3062,63 @@ index f70a4f9..07cfc04 100644 // ffmpeg vc-1 decoder does not flush, make sure the data buffer is still valid if (!IsSurfaceValid(render)) -@@ -1402,258 +904,166 @@ int CVDPAU::Decode(AVCodecContext *avctx, AVFrame *pFrame) +@@ -1402,258 +894,167 @@ return VC_BUFFER; } + CSingleLock lock(m_videoSurfaceSec); render->state |= FF_VDPAU_STATE_USED_FOR_RENDER; + lock.Leave(); ++ ++ // send frame to output for processing ++ CVdpauDecodedPicture pic; ++ memset(&pic.DVDPic, 0, sizeof(pic.DVDPic)); ++ ((CDVDVideoCodecFFmpeg*)avctx->opaque)->GetPictureCommon(&pic.DVDPic); ++ pic.render = render; ++ pic.DVDPic.color_matrix = avctx->colorspace; ++ m_bufferStats.IncDecoded(); ++ m_vdpauOutput.m_dataPort.SendOutMessage(COutputDataProtocol::NEWFRAME, &pic, sizeof(pic)); - ClearUsedForRender(&past[0]); - past[0] = past[1]; - past[1] = current; - current = future; - future = render; -+ // send frame to output for processing -+ CVdpauDecodedPicture pic; -+ memset(&pic.DVDPic, 0, sizeof(pic.DVDPic)); -+ ((CDVDVideoCodecFFmpeg*)avctx->opaque)->GetPictureCommon(&pic.DVDPic); -+ pic.render = render; -+ m_bufferStats.IncDecoded(); -+ m_vdpauOutput.m_dataPort.SendOutMessage(COutputDataProtocol::NEWFRAME, &pic, sizeof(pic)); - +- - DVDVideoPicture DVDPic; - memset(&DVDPic, 0, sizeof(DVDVideoPicture)); - ((CDVDVideoCodecFFmpeg*)avctx->opaque)->GetPictureCommon(&DVDPic); - m_DVDVideoPics.push(DVDPic); -+ m_codecControl = pic.DVDPic.iFlags & (DVP_FLAG_DRAIN | DVP_FLAG_NO_POSTPROC); -+ } - +- - int pics = m_DVDVideoPics.size(); - if (pics < 2) - return VC_BUFFER; - else if (pics > 2) +- { +- // this should not normally happen +- CLog::Log(LOGERROR, "CVDPAU::Decode - invalid number of pictures in queue"); +- while (pics-- != 2) +- m_DVDVideoPics.pop(); ++ m_codecControl = pic.DVDPic.iFlags & (DVP_FLAG_DRAIN | DVP_FLAG_NO_POSTPROC); ++ } ++ + int retval = 0; + uint16_t decoded, processed, render; + Message *msg; + while (m_vdpauOutput.m_controlPort.ReceiveInMessage(&msg)) + { + if (msg->signal == COutputControlProtocol::ERROR) - { -- // this should not normally happen -- CLog::Log(LOGERROR, "CVDPAU::Decode - invalid number of pictures in queue"); -- while (pics-- != 2) -- m_DVDVideoPics.pop(); ++ { + m_DisplayState = VDPAU_ERROR; + retval |= VC_ERROR; } + msg->Release(); + } ++ ++ m_bufferStats.Get(decoded, processed, render); - if (mode == VS_DEINTERLACEMODE_FORCE - || (mode == VS_DEINTERLACEMODE_AUTO && m_DVDVideoPics.front().iFlags & DVP_FLAG_INTERLACED)) -+ m_bufferStats.Get(decoded, processed, render); -+ + uint64_t startTime = CurrentHostCounter(); + while (!retval) + { @@ -5996,19 +3227,16 @@ index f70a4f9..07cfc04 100644 - VdpVideoSurface futu_surfaces[1] = { VDP_INVALID_HANDLE }; - - if(m_mixerfield == VDP_VIDEO_MIXER_PICTURE_STRUCTURE_FRAME) -+ if (!retval) - { +- { - if (past[0]) - past_surfaces[1] = past[0]->surface; - if (past[1]) - past_surfaces[0] = past[1]->surface; - futu_surfaces[0] = future->surface; -+ CLog::Log(LOGERROR, "VDPAU::%s - timed out waiting for output message", __FUNCTION__); -+ m_DisplayState = VDPAU_ERROR; -+ retval |= VC_ERROR; - } +- } - else -- { ++ if (!retval) + { - if(m_mixerstep == 1) - { // first field - if (past[1]) @@ -6025,8 +3253,11 @@ index f70a4f9..07cfc04 100644 - past_surfaces[0] = current->surface; - futu_surfaces[0] = future->surface; - } -- } -- ++ CLog::Log(LOGERROR, "VDPAU::%s - timed out waiting for output message", __FUNCTION__); ++ m_DisplayState = VDPAU_ERROR; ++ retval |= VC_ERROR; + } + - vdp_st = vdp_presentation_queue_block_until_surface_idle(vdp_flip_queue,outputSurface,&time); - - VdpRect sourceRect = {0,0,vid_width, vid_height}; @@ -6047,7 +3278,7 @@ index f70a4f9..07cfc04 100644 - 0, - NULL); - CheckStatus(vdp_st, __LINE__); - +- - surfaceNum++; - if (surfaceNum >= totalAvailableOutputSurfaces) surfaceNum = 0; + return retval; @@ -6105,7 +3336,8 @@ index f70a4f9..07cfc04 100644 +void CDecoder::Reset() { - CSharedLock lock(m_DecoderSection); -- ++ CSingleLock lock(m_DecoderSection); + - { CSharedLock dLock(m_DisplaySection); - if (m_DisplayState != VDPAU_OPEN) - return false; @@ -6116,8 +3348,7 @@ index f70a4f9..07cfc04 100644 - // this same picture for the second field later - if (m_mixerstep != 1) - m_DVDVideoPics.pop(); -+ CSingleLock lock(m_DecoderSection); - +- - picture->format = RENDER_FMT_VDPAU; - picture->iFlags &= DVP_FLAG_DROPPED; - picture->iWidth = OutWidth; @@ -6127,13 +3358,14 @@ index f70a4f9..07cfc04 100644 + return; - if(m_mixerstep) +- { +- picture->iRepeatPicture = -0.5; +- if(m_mixerstep > 1) + Message *reply; + if (m_vdpauOutput.m_controlPort.SendOutMessageSync(COutputControlProtocol::FLUSH, + &reply, + 2000)) - { -- picture->iRepeatPicture = -0.5; -- if(m_mixerstep > 1) ++ { + bool success = reply->signal == COutputControlProtocol::ACC ? true : false; + reply->Release(); + if (!success) @@ -6204,7 +3436,7 @@ index f70a4f9..07cfc04 100644 if(m_DisplayState == VDPAU_OPEN) { -@@ -1671,4 +1081,2424 @@ bool CVDPAU::CheckStatus(VdpStatus vdp_st, int line) +@@ -1671,4 +1072,2423 @@ return false; } @@ -6278,6 +3510,11 @@ index f70a4f9..07cfc04 100644 + m_dataPort.Purge(); +} + ++bool CMixer::IsActive() ++{ ++ return IsRunning(); ++} ++ +void CMixer::OnStartup() +{ + CLog::Log(LOGNOTICE, "CMixer::OnStartup: Output Thread created"); @@ -6646,10 +3883,6 @@ index f70a4f9..07cfc04 100644 + m_Procamp.contrast = 1.0; + m_Procamp.saturation = 1.0; + m_Procamp.hue = 0; -+ vdp_st = m_config.vdpProcs.vdp_generate_csc_matrix(&m_Procamp, -+ (Width < 1000)? VDP_COLOR_STANDARD_ITUR_BT_601 : VDP_COLOR_STANDARD_ITUR_BT_709, -+ &m_CSCMatrix); -+ CheckStatus(vdp_st, __LINE__); +} + +void CMixer::CheckFeatures() @@ -6660,11 +3893,13 @@ index f70a4f9..07cfc04 100644 + m_Upscale = m_config.upscale; + } + if (m_Brightness != g_settings.m_currentVideoSettings.m_Brightness || -+ m_Contrast != g_settings.m_currentVideoSettings.m_Contrast) ++ m_Contrast != g_settings.m_currentVideoSettings.m_Contrast || ++ m_ColorMatrix != m_mixerInput[1].DVDPic.color_matrix) + { + SetColor(); + m_Brightness = g_settings.m_currentVideoSettings.m_Brightness; + m_Contrast = g_settings.m_currentVideoSettings.m_Contrast; ++ m_ColorMatrix = m_mixerInput[1].DVDPic.color_matrix; + } + if (m_NoiseReduction != g_settings.m_currentVideoSettings.m_NoiseReduction) + { @@ -6738,74 +3973,6 @@ index f70a4f9..07cfc04 100644 + DisableHQScaling(); +} + -+ -+bool CMixer::GenerateStudioCSCMatrix(VdpColorStandard colorStandard, VdpCSCMatrix &studioCSCMatrix) -+{ -+ // instead use studioCSCKCoeffs601[3], studioCSCKCoeffs709[3] to generate float[3][4] matrix (float studioCSC[3][4]) -+ // m00 = mRY = red: luma factor (contrast factor) (1.0) -+ // m10 = mGY = green: luma factor (contrast factor) (1.0) -+ // m20 = mBY = blue: luma factor (contrast factor) (1.0) -+ // -+ // m01 = mRB = red: blue color diff coeff (0.0) -+ // m11 = mGB = green: blue color diff coeff (-2Kb(1-Kb)/(Kg)) -+ // m21 = mBB = blue: blue color diff coeff ((1-Kb)/0.5) -+ // -+ // m02 = mRR = red: red color diff coeff ((1-Kr)/0.5) -+ // m12 = mGR = green: red color diff coeff (-2Kr(1-Kr)/(Kg)) -+ // m22 = mBR = blue: red color diff coeff (0.0) -+ // -+ // m03 = mRC = red: colour zero offset (brightness factor) (-(1-Kr)/0.5 * (128/255)) -+ // m13 = mGC = green: colour zero offset (brightness factor) ((256/255) * (Kb(1-Kb) + Kr(1-Kr)) / Kg) -+ // m23 = mBC = blue: colour zero offset (brightness factor) (-(1-Kb)/0.5 * (128/255)) -+ -+ // columns -+ int Y = 0; -+ int Cb = 1; -+ int Cr = 2; -+ int C = 3; -+ // rows -+ int R = 0; -+ int G = 1; -+ int B = 2; -+ // colour standard coefficients for red, geen, blue -+ double Kr, Kg, Kb; -+ // colour diff zero position (use standard 8-bit coding precision) -+ double CDZ = 128; //256*0.5 -+ // range excursion (use standard 8-bit coding precision) -+ double EXC = 255; //256-1 -+ -+ if (colorStandard == VDP_COLOR_STANDARD_ITUR_BT_601) -+ { -+ Kr = studioCSCKCoeffs601[0]; -+ Kg = studioCSCKCoeffs601[1]; -+ Kb = studioCSCKCoeffs601[2]; -+ } -+ else // assume VDP_COLOR_STANDARD_ITUR_BT_709 -+ { -+ Kr = studioCSCKCoeffs709[0]; -+ Kg = studioCSCKCoeffs709[1]; -+ Kb = studioCSCKCoeffs709[2]; -+ } -+ // we keep luma unscaled to retain the levels present in source so that 16-235 luma is converted to RGB 16-235 -+ studioCSCMatrix[R][Y] = 1.0; -+ studioCSCMatrix[G][Y] = 1.0; -+ studioCSCMatrix[B][Y] = 1.0; -+ -+ studioCSCMatrix[R][Cb] = 0.0; -+ studioCSCMatrix[G][Cb] = (double)-2 * Kb * (1 - Kb) / Kg; -+ studioCSCMatrix[B][Cb] = (double)(1 - Kb) / 0.5; -+ -+ studioCSCMatrix[R][Cr] = (double)(1 - Kr) / 0.5; -+ studioCSCMatrix[G][Cr] = (double)-2 * Kr * (1 - Kr) / Kg; -+ studioCSCMatrix[B][Cr] = 0.0; -+ -+ studioCSCMatrix[R][C] = (double)-1 * studioCSCMatrix[R][Cr] * CDZ/EXC; -+ studioCSCMatrix[G][C] = (double)-1 * (studioCSCMatrix[G][Cb] + studioCSCMatrix[G][Cr]) * CDZ/EXC; -+ studioCSCMatrix[B][C] = (double)-1 * studioCSCMatrix[B][Cb] * CDZ/EXC; -+ -+ return true; -+} -+ +void CMixer::SetColor() +{ + VdpStatus vdp_st; @@ -6816,28 +3983,33 @@ index f70a4f9..07cfc04 100644 + m_Procamp.contrast = (float)((g_settings.m_currentVideoSettings.m_Contrast)+50) / 100; + + VdpColorStandard colorStandard; -+// if(vid_height >= 600 || vid_width > 1024) -+ if(m_config.surfaceWidth > 1000) -+ colorStandard = VDP_COLOR_STANDARD_ITUR_BT_709; -+ //vdp_st = vdp_generate_csc_matrix(&m_Procamp, VDP_COLOR_STANDARD_ITUR_BT_709, &m_CSCMatrix); -+ else -+ colorStandard = VDP_COLOR_STANDARD_ITUR_BT_601; -+ //vdp_st = vdp_generate_csc_matrix(&m_Procamp, VDP_COLOR_STANDARD_ITUR_BT_601, &m_CSCMatrix); ++ switch(m_mixerInput[1].DVDPic.color_matrix) ++ { ++ case AVCOL_SPC_BT709: ++ colorStandard = VDP_COLOR_STANDARD_ITUR_BT_709; ++ break; ++ case AVCOL_SPC_BT470BG: ++ case AVCOL_SPC_SMPTE170M: ++ colorStandard = VDP_COLOR_STANDARD_ITUR_BT_601; ++ break; ++ case AVCOL_SPC_SMPTE240M: ++ colorStandard = VDP_COLOR_STANDARD_SMPTE_240M; ++ break; ++ case AVCOL_SPC_FCC: ++ case AVCOL_SPC_UNSPECIFIED: ++ case AVCOL_SPC_RGB: ++ default: ++ if(m_config.surfaceWidth > 1000) ++ colorStandard = VDP_COLOR_STANDARD_ITUR_BT_709; ++ else ++ colorStandard = VDP_COLOR_STANDARD_ITUR_BT_601; ++ } + + VdpVideoMixerAttribute attributes[] = { VDP_VIDEO_MIXER_ATTRIBUTE_CSC_MATRIX }; -+ if (g_guiSettings.GetBool("videoplayer.vdpaustudiolevel")) -+ { -+ float studioCSC[3][4]; -+ GenerateStudioCSCMatrix(colorStandard, studioCSC); -+ void const * pm_CSCMatix[] = { &studioCSC }; -+ vdp_st = m_config.vdpProcs.vdp_video_mixer_set_attribute_values(m_videoMixer, ARSIZE(attributes), attributes, pm_CSCMatix); -+ } -+ else -+ { -+ vdp_st = m_config.vdpProcs.vdp_generate_csc_matrix(&m_Procamp, colorStandard, &m_CSCMatrix); -+ void const * pm_CSCMatix[] = { &m_CSCMatrix }; -+ vdp_st = m_config.vdpProcs.vdp_video_mixer_set_attribute_values(m_videoMixer, ARSIZE(attributes), attributes, pm_CSCMatix); -+ } ++ vdp_st = m_config.vdpProcs.vdp_generate_csc_matrix(&m_Procamp, colorStandard, &m_CSCMatrix); ++ void const * pm_CSCMatix[] = { &m_CSCMatrix }; ++ vdp_st = m_config.vdpProcs.vdp_video_mixer_set_attribute_values(m_videoMixer, ARSIZE(attributes), attributes, pm_CSCMatix); ++ + CheckStatus(vdp_st, __LINE__); +} + @@ -6897,10 +4069,10 @@ index f70a4f9..07cfc04 100644 + if (method == VS_INTERLACEMETHOD_AUTO) + { + int deint = -1; -+// if (m_config.outHeight >= 720) -+// deint = g_advancedSettings.m_videoVDPAUdeintHD; -+// else -+// deint = g_advancedSettings.m_videoVDPAUdeintSD; ++ if (m_config.outHeight >= 720) ++ deint = g_advancedSettings.m_videoVDPAUdeintHD; ++ else ++ deint = g_advancedSettings.m_videoVDPAUdeintSD; + + if (deint != -1) + { @@ -6974,7 +4146,7 @@ index f70a4f9..07cfc04 100644 + + SetDeintSkipChroma(); + -+ m_config.useInteropYuv = g_guiSettings.GetBool("videoplayer.usevdpauinteropyuv"); ++ m_config.useInteropYuv = !g_guiSettings.GetBool("videoplayer.usevdpaumixer"); +} + +void CMixer::SetDeintSkipChroma() @@ -7162,11 +4334,12 @@ index f70a4f9..07cfc04 100644 + m_Sharpness = 0.0; + m_DeintMode = 0; + m_Deint = 0; ++ m_ColorMatrix = 0; + m_PostProc = false; + m_vdpError = false; + + m_config.upscale = g_advancedSettings.m_videoVDPAUScaling; -+ m_config.useInteropYuv = g_guiSettings.GetBool("videoplayer.usevdpauinteropyuv"); ++ m_config.useInteropYuv = !g_guiSettings.GetBool("videoplayer.usevdpaumixer"); + + CreateVdpauMixer(); +} @@ -7239,8 +4412,9 @@ index f70a4f9..07cfc04 100644 + EINTERLACEMETHOD method = GetDeinterlacingMethod(); + bool interlaced = m_mixerInput[1].DVDPic.iFlags & DVP_FLAG_INTERLACED; + -+ if (mode == VS_DEINTERLACEMODE_FORCE || -+ (mode == VS_DEINTERLACEMODE_AUTO && interlaced)) ++ if (!(flags & DVP_FLAG_NO_POSTPROC) && ++ (mode == VS_DEINTERLACEMODE_FORCE || ++ (mode == VS_DEINTERLACEMODE_AUTO && interlaced))) + { + if((method == VS_INTERLACEMETHOD_AUTO && interlaced) + || method == VS_INTERLACEMETHOD_VDPAU_BOB @@ -7276,21 +4450,24 @@ index f70a4f9..07cfc04 100644 + DVP_FLAG_INTERLACED); + m_config.useInteropYuv = false; + } -+ else if (method == VS_INTERLACEMETHOD_RENDER_BOB && m_config.useInteropYuv) ++ else if (method == VS_INTERLACEMETHOD_RENDER_BOB) + { + m_mixersteps = 1; + m_mixerfield = VDP_VIDEO_MIXER_PICTURE_STRUCTURE_FRAME; + m_mixerInput[1].DVDPic.format = RENDER_FMT_VDPAU_420; ++ m_config.useInteropYuv = true; + } + else + { -+ CLog::Log(LOGERROR, "CMixer::%s - interlace method not supported", __FUNCTION__); ++ CLog::Log(LOGERROR, "CMixer::%s - interlace method: %d not supported, setting to AUTO", __FUNCTION__, method); + m_mixersteps = 1; + m_mixerfield = VDP_VIDEO_MIXER_PICTURE_STRUCTURE_FRAME; + m_mixerInput[1].DVDPic.format = RENDER_FMT_VDPAU; + m_mixerInput[1].DVDPic.iFlags &= ~(DVP_FLAG_TOP_FIELD_FIRST | + DVP_FLAG_REPEAT_TOP_FIELD | + DVP_FLAG_INTERLACED); ++ ++ g_settings.m_currentVideoSettings.m_InterlaceMethod = VS_INTERLACEMETHOD_AUTO; + } + } + else @@ -7653,6 +4830,7 @@ index f70a4f9..07cfc04 100644 + return; + case COutputControlProtocol::PRECLEANUP: + Flush(); ++ PreCleanup(); + msg->Reply(COutputControlProtocol::ACC); + return; + default: @@ -7859,15 +5037,18 @@ index f70a4f9..07cfc04 100644 + +void COutput::Flush() +{ -+ Message *reply; -+ if (m_mixer.m_controlPort.SendOutMessageSync(CMixerControlProtocol::FLUSH, ++ if (m_mixer.IsActive()) ++ { ++ Message *reply; ++ if (m_mixer.m_controlPort.SendOutMessageSync(CMixerControlProtocol::FLUSH, + &reply, + 2000)) -+ { -+ reply->Release(); ++ { ++ reply->Release(); ++ } ++ else ++ CLog::Log(LOGERROR, "Coutput::%s - failed to flush mixer", __FUNCTION__); + } -+ else -+ CLog::Log(LOGERROR, "Coutput::%s - failed to flush mixer", __FUNCTION__); + + Message *msg; + while (m_mixer.m_dataPort.ReceiveInMessage(&msg)) @@ -8206,6 +5387,57 @@ index f70a4f9..07cfc04 100644 + } +} + ++void COutput::PreCleanup() ++{ ++ ++ VdpStatus vdp_st; ++ ++ m_mixer.Dispose(); ++ ++ CSingleLock lock(m_bufferPool.renderPicSec); ++ for (unsigned int i = 0; i < m_bufferPool.outputSurfaces.size(); ++i) ++ { ++ if (m_bufferPool.outputSurfaces[i] == VDP_INVALID_HANDLE) ++ continue; ++ ++ // check if output surface is in use ++ bool used = false; ++ std::deque::iterator it; ++ for (it = m_bufferPool.usedRenderPics.begin(); it != m_bufferPool.usedRenderPics.end(); ++it) ++ { ++ if (((*it)->sourceIdx == m_bufferPool.outputSurfaces[i]) && (*it)->valid) ++ { ++ used = true; ++ break; ++ } ++ } ++ if (used) ++ continue; ++ ++#ifdef GL_NV_vdpau_interop ++ // unmap surface ++ std::map::iterator it_map; ++ it_map = m_bufferPool.glOutputSurfaceMap.find(m_bufferPool.outputSurfaces[i]); ++ if (it_map == m_bufferPool.glOutputSurfaceMap.end()) ++ { ++ CLog::Log(LOGERROR, "%s - could not find gl surface", __FUNCTION__); ++ continue; ++ } ++ glVDPAUUnregisterSurfaceNV(it_map->second.glVdpauSurface); ++ glDeleteTextures(1, it_map->second.texture); ++ m_bufferPool.glOutputSurfaceMap.erase(it_map); ++#endif ++ ++ vdp_st = m_config.vdpProcs.vdp_output_surface_destroy(m_bufferPool.outputSurfaces[i]); ++ CheckStatus(vdp_st, __LINE__); ++ ++ m_bufferPool.outputSurfaces[i] = VDP_INVALID_HANDLE; ++ ++ CLog::Log(LOGDEBUG, "VDPAU::PreCleanup - released output surface"); ++ } ++ ++} ++ +void COutput::InitMixer() +{ + for (unsigned int i = 0; i < m_bufferPool.outputSurfaces.size(); ++i) @@ -8312,7 +5544,7 @@ index f70a4f9..07cfc04 100644 + glVDPAUGetSurfaceivNV = NULL; +#endif + -+ m_config.usePixmaps = !g_guiSettings.GetBool("videoplayer.usevdpauinterop"); ++ m_config.usePixmaps = false; + +#ifdef GL_NV_vdpau_interop + if (glewIsSupported("GL_NV_vdpau_interop")) @@ -8344,8 +5576,7 @@ index f70a4f9..07cfc04 100644 +#endif + { + m_config.usePixmaps = true; -+ g_guiSettings.SetBool("videoplayer.usevdpauinterop",false); -+ g_guiSettings.SetBool("videoplayer.usevdpauinteropyuv",false); ++ g_guiSettings.SetBool("videoplayer.usevdpaumixer",true); + } + if (!glXBindTexImageEXT) + glXBindTexImageEXT = (PFNGLXBINDTEXIMAGEEXTPROC)glXGetProcAddress((GLubyte *) "glXBindTexImageEXT"); @@ -8629,10 +5860,9 @@ index f70a4f9..07cfc04 100644 +} + #endif -diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/VDPAU.h b/xbmc/cores/dvdplayer/DVDCodecs/Video/VDPAU.h -index 2f53edf..4d1559c 100644 ---- a/xbmc/cores/dvdplayer/DVDCodecs/Video/VDPAU.h -+++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/VDPAU.h +diff -Naur xbmc-12.0.4/xbmc/cores/dvdplayer/DVDCodecs/Video/VDPAU.h xbmc-12.0.4.patch/xbmc/cores/dvdplayer/DVDCodecs/Video/VDPAU.h +--- xbmc-12.0.4/xbmc/cores/dvdplayer/DVDCodecs/Video/VDPAU.h 2013-03-08 13:01:31.000000000 +0100 ++++ xbmc-12.0.4.patch/xbmc/cores/dvdplayer/DVDCodecs/Video/VDPAU.h 2013-03-10 13:00:12.332988098 +0100 @@ -1,5 +1,3 @@ - -#pragma once @@ -8704,7 +5934,9 @@ index 2f53edf..4d1559c 100644 - uint32_t id; - uint32_t aux; /* optional extra parameter... */ - }; -- ++#include "threads/Thread.h" ++#include "utils/ActorProtocol.h" + - CVDPAU(); - virtual ~CVDPAU(); - @@ -8713,11 +5945,12 @@ index 2f53edf..4d1559c 100644 - virtual bool GetPicture(AVCodecContext* avctx, AVFrame* frame, DVDVideoPicture* picture); - virtual void Reset(); - virtual void Close(); -- ++using namespace Actor; + - virtual int Check(AVCodecContext* avctx); - - virtual const std::string Name() { return "vdpau"; } -- + - bool MakePixmap(int width, int height); - bool MakePixmapGL(); - @@ -8741,16 +5974,15 @@ index 2f53edf..4d1559c 100644 - void InitCSCMatrix(int Height); - bool CheckStatus(VdpStatus vdp_st, int line); - bool IsSurfaceValid(vdpau_render_state *render); -+#include "threads/Thread.h" -+#include "utils/ActorProtocol.h" - +- - void CheckFeatures(); - void SetColor(); - void SetNoiseReduction(); - void SetSharpness(); - void SetDeinterlacing(); - void SetHWUpscaling(); -+using namespace Actor; ++#define FULLHD_WIDTH 1920 ++#define MAX_PIC_Q_LENGTH 20 //for non-interop_yuv this controls the max length of the decoded pic to render completion Q - pictureAge picAge; - vdpau_render_state *past[2], *current, *future; @@ -8760,7 +5992,7 @@ index 2f53edf..4d1559c 100644 - int OutWidth, OutHeight; - bool upScale; - std::queue m_DVDVideoPics; - +- - static inline void ClearUsedForRender(vdpau_render_state **st) - { - if (*st) { @@ -8768,16 +6000,21 @@ index 2f53edf..4d1559c 100644 - *st = NULL; - } - } -- ++namespace VDPAU ++{ + - VdpProcamp m_Procamp; - VdpCSCMatrix m_CSCMatrix; - VdpDevice HasDevice() { return vdp_device != VDP_INVALID_HANDLE; }; - VdpChromaType vdp_chroma_type; -+#define FULLHD_WIDTH 1920 -+#define MAX_PIC_Q_LENGTH 20 //for non-interop_yuv this controls the max length of the decoded pic to render completion Q ++/** ++ * VDPAU interface to driver ++ */ -+namespace VDPAU ++struct VDPAU_procs +{ ++ VdpGetProcAddress * vdp_get_proc_address; ++ VdpDeviceDestroy * vdp_device_destroy; - // protected: - void InitVDPAUProcs(); @@ -8785,20 +6022,13 @@ index 2f53edf..4d1559c 100644 - void FiniVDPAUOutput(); - bool ConfigOutputMethod(AVCodecContext *avctx, AVFrame *pFrame); - bool FiniOutputMethod(); -+/** -+ * VDPAU interface to driver -+ */ - +- - VdpDevice vdp_device; - VdpGetProcAddress * vdp_get_proc_address; - VdpPresentationQueueTarget vdp_flip_target; - VdpPresentationQueue vdp_flip_queue; - VdpDeviceDestroy * vdp_device_destroy; -+struct VDPAU_procs -+{ -+ VdpGetProcAddress * vdp_get_proc_address; -+ VdpDeviceDestroy * vdp_device_destroy; - +- - VdpVideoSurfaceCreate * vdp_video_surface_create; - VdpVideoSurfaceDestroy * vdp_video_surface_destroy; - VdpVideoSurfacePutBitsYCbCr * vdp_video_surface_put_bits_y_cb_cr; @@ -8810,7 +6040,7 @@ index 2f53edf..4d1559c 100644 VdpOutputSurfacePutBitsYCbCr * vdp_output_surface_put_bits_y_cb_cr; VdpOutputSurfacePutBitsNative * vdp_output_surface_put_bits_native; -@@ -158,15 +92,15 @@ class CVDPAU +@@ -158,15 +92,15 @@ VdpOutputSurfaceRenderOutputSurface * vdp_output_surface_render_output_surface; VdpOutputSurfacePutBitsIndexed * vdp_output_surface_put_bits_indexed; @@ -8834,7 +6064,7 @@ index 2f53edf..4d1559c 100644 VdpPresentationQueueTargetDestroy * vdp_presentation_queue_target_destroy; VdpPresentationQueueCreate * vdp_presentation_queue_create; -@@ -179,64 +113,459 @@ class CVDPAU +@@ -179,64 +113,462 @@ VdpGetErrorString * vdp_get_error_string; @@ -8852,21 +6082,20 @@ index 2f53edf..4d1559c 100644 - VdpOutputSurface outputSurfaces[NUM_OUTPUT_SURFACES]; - VdpOutputSurface outputSurface; - VdpOutputSurface presentSurface; -+}; - +- - VdpDecoder decoder; - VdpVideoMixer videoMixer; - VdpRect outRect; - VdpRect outRectVid; -+//----------------------------------------------------------------------------- -+// VDPAU data structs -+//----------------------------------------------------------------------------- ++}; - static void* dl_handle; - VdpStatus (*dl_vdp_device_create_x11)(Display* display, int screen, VdpDevice* device, VdpGetProcAddress **get_proc_address); - VdpStatus (*dl_vdp_get_proc_address)(VdpDevice device, VdpFuncId function_id, void** function_pointer); - VdpStatus (*dl_vdp_preemption_callback_register)(VdpDevice device, VdpPreemptionCallback callback, void* context); -+class CDecoder; ++//----------------------------------------------------------------------------- ++// VDPAU data structs ++//----------------------------------------------------------------------------- - int surfaceNum; - int presentSurfaceNum; @@ -8877,10 +6106,12 @@ index 2f53edf..4d1559c 100644 - Display* m_Display; - bool vdpauConfigured; - uint32_t *m_BlackBar; ++class CDecoder; ++ +/** + * Buffer statistics used to control number of frames in queue + */ - ++ +class CVdpauBufferStats +{ +public: @@ -8915,7 +6146,7 @@ index 2f53edf..4d1559c 100644 + * The structure is sent to the internal classes CMixer and COutput + * for init. + */ - ++ +struct CVdpauConfig +{ + int surfaceWidth; @@ -8940,7 +6171,7 @@ index 2f53edf..4d1559c 100644 + uint32_t maxReferences; + bool useInteropYuv; +}; -+ + +/** + * Holds a decoded frame + * Input to COutput for further processing @@ -9022,7 +6253,7 @@ index 2f53edf..4d1559c 100644 + PICTURE, + }; +}; -+ + +/** + * Embeds the vdpau video mixer + * Embedded by COutput class, gets decoded frames from COutput, processes @@ -9035,6 +6266,7 @@ index 2f53edf..4d1559c 100644 + virtual ~CMixer(); + void Start(); + void Dispose(); ++ bool IsActive(); + CMixerControlProtocol m_controlPort; + CMixerDataProtocol m_dataPort; +protected: @@ -9083,6 +6315,7 @@ index 2f53edf..4d1559c 100644 + int m_DeintMode; + int m_Deint; + int m_Upscale; ++ unsigned int m_ColorMatrix : 4; + uint32_t *m_BlackBar; VdpVideoMixerPictureStructure m_mixerfield; - int m_mixerstep; @@ -9203,6 +6436,7 @@ index 2f53edf..4d1559c 100644 + bool DestroyGlxContext(); + bool EnsureBufferPool(); + void ReleaseBufferPool(); ++ void PreCleanup(); + void InitMixer(); + bool GLInit(); + void GLMapSurfaces(); @@ -9333,7 +6567,7 @@ index 2f53edf..4d1559c 100644 // OnLostDevice triggers transition from all states to LOST // internal errors trigger transition from OPEN to RESET -@@ -247,9 +576,24 @@ class CVDPAU +@@ -247,9 +579,24 @@ , VDPAU_LOST , VDPAU_ERROR } m_DisplayState; @@ -9362,7357 +6596,9 @@ index 2f53edf..4d1559c 100644 }; + +} -diff --git a/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp b/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp -index d004153..92f62bb 100644 ---- a/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp -+++ b/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp -@@ -1146,6 +1146,10 @@ int CDVDPlayerVideo::OutputPicture(const DVDVideoPicture* src, double pts) - formatstr = "VDPAU"; - buffering = true; - break; -+ case RENDER_FMT_VDPAU_420: -+ formatstr = "VDPAU_420"; -+ buffering = true; -+ break; - case RENDER_FMT_DXVA: - formatstr = "DXVA"; - buffering = true; -diff --git a/xbmc/settings/AdvancedSettings.cpp b/xbmc/settings/AdvancedSettings.cpp -index 16800b7..844f8e8 100644 ---- a/xbmc/settings/AdvancedSettings.cpp -+++ b/xbmc/settings/AdvancedSettings.cpp -@@ -98,7 +98,7 @@ void CAdvancedSettings::Initialize() - m_videoIgnoreSecondsAtStart = 3*60; - m_videoIgnorePercentAtEnd = 8.0f; - m_videoPlayCountMinimumPercent = 90.0f; -- m_videoVDPAUScaling = false; -+ m_videoVDPAUScaling = -1; - m_videoNonLinStretchRatio = 0.5f; - m_videoEnableHighQualityHwScalers = false; - m_videoAutoScaleMaxFps = 30.0f; -@@ -106,6 +106,8 @@ void CAdvancedSettings::Initialize() - m_videoAllowMpeg4VAAPI = false; - m_videoDisableBackgroundDeinterlace = false; - m_videoCaptureUseOcclusionQuery = -1; //-1 is auto detect -+ m_videoVDPAUtelecine = false; -+ m_videoVDPAUdeintSkipChromaHD = false; - m_DXVACheckCompatibility = false; - m_DXVACheckCompatibilityPresent = false; - m_DXVAForceProcessorRenderer = true; -@@ -493,7 +495,7 @@ void CAdvancedSettings::ParseSettingsFile(const CStdString &file) - XMLUtils::GetString(pElement,"cleandatetime", m_videoCleanDateTimeRegExp); - XMLUtils::GetString(pElement,"ppffmpegdeinterlacing",m_videoPPFFmpegDeint); - XMLUtils::GetString(pElement,"ppffmpegpostprocessing",m_videoPPFFmpegPostProc); -- XMLUtils::GetBoolean(pElement,"vdpauscaling",m_videoVDPAUScaling); -+ XMLUtils::GetInt(pElement,"vdpauscaling",m_videoVDPAUScaling); - XMLUtils::GetFloat(pElement, "nonlinearstretchratio", m_videoNonLinStretchRatio, 0.01f, 1.0f); - XMLUtils::GetBoolean(pElement,"enablehighqualityhwscalers", m_videoEnableHighQualityHwScalers); - XMLUtils::GetFloat(pElement,"autoscalemaxfps",m_videoAutoScaleMaxFps, 0.0f, 1000.0f); -@@ -501,6 +503,8 @@ void CAdvancedSettings::ParseSettingsFile(const CStdString &file) - XMLUtils::GetBoolean(pElement,"allowmpeg4vaapi",m_videoAllowMpeg4VAAPI); - XMLUtils::GetBoolean(pElement, "disablebackgrounddeinterlace", m_videoDisableBackgroundDeinterlace); - XMLUtils::GetInt(pElement, "useocclusionquery", m_videoCaptureUseOcclusionQuery, -1, 1); -+ XMLUtils::GetBoolean(pElement,"vdpauInvTelecine",m_videoVDPAUtelecine); -+ XMLUtils::GetBoolean(pElement,"vdpauHDdeintSkipChroma",m_videoVDPAUdeintSkipChromaHD); - - TiXmlElement* pAdjustRefreshrate = pElement->FirstChildElement("adjustrefreshrate"); - if (pAdjustRefreshrate) -diff --git a/xbmc/settings/AdvancedSettings.h b/xbmc/settings/AdvancedSettings.h -index 27887d4..72718e5 100644 ---- a/xbmc/settings/AdvancedSettings.h -+++ b/xbmc/settings/AdvancedSettings.h -@@ -133,6 +133,8 @@ class CAdvancedSettings - int m_videoPercentSeekBackwardBig; - CStdString m_videoPPFFmpegDeint; - CStdString m_videoPPFFmpegPostProc; -+ bool m_videoVDPAUtelecine; -+ bool m_videoVDPAUdeintSkipChromaHD; - bool m_musicUseTimeSeeking; - int m_musicTimeSeekForward; - int m_musicTimeSeekBackward; -@@ -148,7 +150,7 @@ class CAdvancedSettings - CStdString m_audioHost; - bool m_audioApplyDrc; - -- bool m_videoVDPAUScaling; -+ int m_videoVDPAUScaling; - float m_videoNonLinStretchRatio; - bool m_videoEnableHighQualityHwScalers; - float m_videoAutoScaleMaxFps; -diff --git a/xbmc/settings/GUISettings.cpp b/xbmc/settings/GUISettings.cpp -index 76ec0cc..4cdb093 100644 ---- a/xbmc/settings/GUISettings.cpp -+++ b/xbmc/settings/GUISettings.cpp -@@ -685,6 +685,8 @@ void CGUISettings::Initialize() - - #ifdef HAVE_LIBVDPAU - AddBool(vp, "videoplayer.usevdpau", 13425, true); -+ AddBool(vp, "videoplayer.usevdpauinterop", 13435, true); -+ AddBool(vp, "videoplayer.usevdpauinteropyuv", 13436, false); - #endif - #ifdef HAVE_LIBVA - AddBool(vp, "videoplayer.usevaapi", 13426, true); -diff --git a/xbmc/settings/GUIWindowSettingsCategory.cpp b/xbmc/settings/GUIWindowSettingsCategory.cpp -index 4ac2663..d988598 100644 ---- a/xbmc/settings/GUIWindowSettingsCategory.cpp -+++ b/xbmc/settings/GUIWindowSettingsCategory.cpp -@@ -596,6 +596,40 @@ void CGUIWindowSettingsCategory::UpdateSettings() - pControl->SetEnabled(true); - } - } -+ else if (strSetting.Equals("videoplayer.usevdpauinteropyuv")) -+ { -+ bool hasInterop = g_guiSettings.GetBool("videoplayer.usevdpauinterop"); -+#ifndef GL_NV_vdpau_interop -+ hasInterop = false; -+#endif -+ CGUIControl *pControl = (CGUIControl *)GetControl(pSettingControl->GetID()); -+ if (pControl && hasInterop && glewIsSupported("GL_NV_vdpau_interop")) -+ { -+ pControl->SetEnabled(true); -+ } -+ else -+ { -+ pControl->SetEnabled(false); -+ g_guiSettings.SetBool("videoplayer.usevdpauinteropyuv",false); -+ } -+ } -+ else if (strSetting.Equals("videoplayer.usevdpauinterop")) -+ { -+ bool hasInterop = g_guiSettings.GetBool("videoplayer.usevdpau"); -+#ifndef GL_NV_vdpau_interop -+ hasInterop = false; -+#endif -+ CGUIControl *pControl = (CGUIControl *)GetControl(pSettingControl->GetID()); -+ if (pControl && hasInterop && glewIsSupported("GL_NV_vdpau_interop")) -+ { -+ pControl->SetEnabled(true); -+ } -+ else -+ { -+ pControl->SetEnabled(false); -+ g_guiSettings.SetBool("videoplayer.usevdpauinterop",false); -+ } -+ } - else - #endif - if (strSetting.Equals("videoscreen.resolution")) -diff --git a/xbmc/utils/ActorProtocol.cpp b/xbmc/utils/ActorProtocol.cpp -new file mode 100644 -index 0000000..e0cfd0e ---- /dev/null -+++ b/xbmc/utils/ActorProtocol.cpp -@@ -0,0 +1,253 @@ -+/* -+ * Copyright (C) 2005-2012 Team XBMC -+ * http://www.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 -+ * . -+ * -+ */ -+ -+#include "ActorProtocol.h" -+ -+using namespace Actor; -+ -+void Message::Release() -+{ -+ bool skip; -+ origin->Lock(); -+ skip = isSync ? !isSyncFini : false; -+ isSyncFini = true; -+ origin->Unlock(); -+ -+ if (skip) -+ return; -+ -+ // free data buffer -+ if (data != buffer) -+ delete [] data; -+ -+ // delete event in case of sync message -+ if (event) -+ delete event; -+ -+ origin->ReturnMessage(this); -+} -+ -+bool Message::Reply(int sig, void *data /* = NULL*/, int size /* = 0 */) -+{ -+ if (!isSync) -+ { -+ if (isOut) -+ return origin->SendInMessage(sig, data, size); -+ else -+ return origin->SendOutMessage(sig, data, size); -+ } -+ -+ origin->Lock(); -+ -+ if (!isSyncTimeout) -+ { -+ Message *msg = origin->GetMessage(); -+ msg->signal = sig; -+ msg->isOut = !isOut; -+ replyMessage = msg; -+ if (data) -+ { -+ if (size > MSG_INTERNAL_BUFFER_SIZE) -+ msg->data = new uint8_t[size]; -+ else -+ msg->data = msg->buffer; -+ memcpy(msg->data, data, size); -+ } -+ } -+ -+ origin->Unlock(); -+ -+ if (event) -+ event->Set(); -+ -+ return true; -+} -+ -+Protocol::~Protocol() -+{ -+ Message *msg; -+ Purge(); -+ while (!freeMessageQueue.empty()) -+ { -+ msg = freeMessageQueue.front(); -+ freeMessageQueue.pop(); -+ delete msg; -+ } -+} -+ -+Message *Protocol::GetMessage() -+{ -+ Message *msg; -+ -+ CSingleLock lock(criticalSection); -+ -+ if (!freeMessageQueue.empty()) -+ { -+ msg = freeMessageQueue.front(); -+ freeMessageQueue.pop(); -+ } -+ else -+ msg = new Message(); -+ -+ msg->isSync = false; -+ msg->isSyncFini = false; -+ msg->isSyncTimeout = false; -+ msg->event = NULL; -+ msg->data = NULL; -+ msg->payloadSize = 0; -+ msg->replyMessage = NULL; -+ msg->origin = this; -+ -+ return msg; -+} -+ -+void Protocol::ReturnMessage(Message *msg) -+{ -+ CSingleLock lock(criticalSection); -+ -+ freeMessageQueue.push(msg); -+} -+ -+bool Protocol::SendOutMessage(int signal, void *data /* = NULL */, int size /* = 0 */, Message *outMsg /* = NULL */) -+{ -+ Message *msg; -+ if (outMsg) -+ msg = outMsg; -+ else -+ msg = GetMessage(); -+ -+ msg->signal = signal; -+ msg->isOut = true; -+ -+ if (data) -+ { -+ if (size > MSG_INTERNAL_BUFFER_SIZE) -+ msg->data = new uint8_t[size]; -+ else -+ msg->data = msg->buffer; -+ memcpy(msg->data, data, size); -+ } -+ -+ { CSingleLock lock(criticalSection); -+ outMessages.push(msg); -+ } -+ containerOutEvent->Set(); -+ -+ return true; -+} -+ -+bool Protocol::SendInMessage(int signal, void *data /* = NULL */, int size /* = 0 */, Message *outMsg /* = NULL */) -+{ -+ Message *msg; -+ if (outMsg) -+ msg = outMsg; -+ else -+ msg = GetMessage(); -+ -+ msg->signal = signal; -+ msg->isOut = false; -+ -+ if (data) -+ { -+ if (size > MSG_INTERNAL_BUFFER_SIZE) -+ msg->data = new uint8_t[size]; -+ else -+ msg->data = msg->buffer; -+ memcpy(msg->data, data, size); -+ } -+ -+ { CSingleLock lock(criticalSection); -+ inMessages.push(msg); -+ } -+ containerInEvent->Set(); -+ -+ return true; -+} -+ -+ -+bool Protocol::SendOutMessageSync(int signal, Message **retMsg, int timeout, void *data /* = NULL */, int size /* = 0 */) -+{ -+ Message *msg = GetMessage(); -+ msg->isOut = true; -+ msg->isSync = true; -+ msg->event = new CEvent; -+ msg->event->Reset(); -+ SendOutMessage(signal, data, size, msg); -+ -+ if (!msg->event->WaitMSec(timeout)) -+ { -+ msg->origin->Lock(); -+ if (msg->replyMessage) -+ *retMsg = msg->replyMessage; -+ else -+ { -+ *retMsg = NULL; -+ msg->isSyncTimeout = true; -+ } -+ msg->origin->Unlock(); -+ } -+ else -+ *retMsg = msg->replyMessage; -+ -+ msg->Release(); -+ -+ if (*retMsg) -+ return true; -+ else -+ return false; -+} -+ -+bool Protocol::ReceiveOutMessage(Message **msg) -+{ -+ CSingleLock lock(criticalSection); -+ -+ if (outMessages.empty() || outDefered) -+ return false; -+ -+ *msg = outMessages.front(); -+ outMessages.pop(); -+ -+ return true; -+} -+ -+bool Protocol::ReceiveInMessage(Message **msg) -+{ -+ CSingleLock lock(criticalSection); -+ -+ if (inMessages.empty() || inDefered) -+ return false; -+ -+ *msg = inMessages.front(); -+ inMessages.pop(); -+ -+ return true; -+} -+ -+ -+void Protocol::Purge() -+{ -+ Message *msg; -+ -+ while (ReceiveInMessage(&msg)) -+ msg->Release(); -+ -+ while (ReceiveOutMessage(&msg)) -+ msg->Release(); -+} -diff --git a/xbmc/utils/ActorProtocol.h b/xbmc/utils/ActorProtocol.h -new file mode 100644 -index 0000000..e7108ac ---- /dev/null -+++ b/xbmc/utils/ActorProtocol.h -@@ -0,0 +1,87 @@ -+/* -+ * Copyright (C) 2005-2012 Team XBMC -+ * http://www.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 -+ * . -+ * -+ */ -+ -+#pragma once -+ -+#include "threads/Thread.h" -+#include "utils/log.h" -+#include -+#include "memory.h" -+ -+#define MSG_INTERNAL_BUFFER_SIZE 32 -+ -+namespace Actor -+{ -+ -+class Protocol; -+ -+class Message -+{ -+ friend class Protocol; -+public: -+ int signal; -+ bool isSync; -+ bool isSyncFini; -+ bool isOut; -+ bool isSyncTimeout; -+ int payloadSize; -+ uint8_t buffer[MSG_INTERNAL_BUFFER_SIZE]; -+ uint8_t *data; -+ Message *replyMessage; -+ Protocol *origin; -+ CEvent *event; -+ -+ void Release(); -+ bool Reply(int sig, void *data = NULL, int size = 0); -+ -+private: -+ Message() {isSync = false; data = NULL; event = NULL; replyMessage = NULL;}; -+}; -+ -+class Protocol -+{ -+public: -+ Protocol(std::string name, CEvent* inEvent, CEvent *outEvent) -+ : portName(name), inDefered(false), outDefered(false) {containerInEvent = inEvent; containerOutEvent = outEvent;}; -+ virtual ~Protocol(); -+ Message *GetMessage(); -+ void ReturnMessage(Message *msg); -+ bool SendOutMessage(int signal, void *data = NULL, int size = 0, Message *outMsg = NULL); -+ bool SendInMessage(int signal, void *data = NULL, int size = 0, Message *outMsg = NULL); -+ bool SendOutMessageSync(int signal, Message **retMsg, int timeout, void *data = NULL, int size = 0); -+ bool ReceiveOutMessage(Message **msg); -+ bool ReceiveInMessage(Message **msg); -+ void Purge(); -+ void DeferIn(bool value) {inDefered = value;}; -+ void DeferOut(bool value) {outDefered = value;}; -+ void Lock() {criticalSection.lock();}; -+ void Unlock() {criticalSection.unlock();}; -+ std::string portName; -+ -+protected: -+ CEvent *containerInEvent, *containerOutEvent; -+ CCriticalSection criticalSection; -+ std::queue outMessages; -+ std::queue inMessages; -+ std::queue freeMessageQueue; -+ bool inDefered, outDefered; -+}; -+ -+} -diff --git a/xbmc/utils/Makefile b/xbmc/utils/Makefile -index d201884..7d1f9f0 100644 ---- a/xbmc/utils/Makefile -+++ b/xbmc/utils/Makefile -@@ -70,6 +70,7 @@ SRCS=AlarmClock.cpp \ - Weather.cpp \ - XBMCTinyXML.cpp \ - XMLUtils.cpp \ -+ ActorProtocol.cpp \ - - LIB=utils.a - -diff --git a/xbmc/video/dialogs/GUIDialogVideoSettings.cpp b/xbmc/video/dialogs/GUIDialogVideoSettings.cpp -index ac5f007..f25d10d 100644 ---- a/xbmc/video/dialogs/GUIDialogVideoSettings.cpp -+++ b/xbmc/video/dialogs/GUIDialogVideoSettings.cpp -@@ -103,7 +103,7 @@ void CGUIDialogVideoSettings::CreateSettings() - entries.push_back(make_pair(VS_INTERLACEMETHOD_INVERSE_TELECINE , 16314)); - entries.push_back(make_pair(VS_INTERLACEMETHOD_VDPAU_TEMPORAL_SPATIAL , 16311)); - entries.push_back(make_pair(VS_INTERLACEMETHOD_VDPAU_TEMPORAL , 16310)); -- entries.push_back(make_pair(VS_INTERLACEMETHOD_VDPAU_BOB , 16021)); -+ entries.push_back(make_pair(VS_INTERLACEMETHOD_VDPAU_BOB , 16325)); - entries.push_back(make_pair(VS_INTERLACEMETHOD_VDPAU_TEMPORAL_SPATIAL_HALF, 16318)); - entries.push_back(make_pair(VS_INTERLACEMETHOD_VDPAU_TEMPORAL_HALF , 16317)); - entries.push_back(make_pair(VS_INTERLACEMETHOD_VDPAU_INVERSE_TELECINE , 16314)); -diff --git a/xbmc/windowing/X11/WinSystemX11.h b/xbmc/windowing/X11/WinSystemX11.h -index e7af3cb..2dd8a9f 100644 ---- a/xbmc/windowing/X11/WinSystemX11.h -+++ b/xbmc/windowing/X11/WinSystemX11.h -@@ -63,6 +63,7 @@ class CWinSystemX11 : public CWinSystemBase - // Local to WinSystemX11 only - Display* GetDisplay() { return m_dpy; } - GLXWindow GetWindow() { return m_glWindow; } -+ GLXContext GetGlxContext() { return m_glContext; } - - protected: - bool RefreshGlxContext(); --- -1.7.10 - - -From 999408daf66880f2efca154bf70bf2b778a5b67b Mon Sep 17 00:00:00 2001 -From: xbmc -Date: Wed, 12 Dec 2012 09:52:17 +0100 -Subject: [PATCH 28/88] vdpau: make interop gl default and remove setting, - rename and intvert interop yuv - ---- - language/English/strings.po | 2 +- - xbmc/cores/dvdplayer/DVDCodecs/Video/VDPAU.cpp | 17 ++++++++++------- - xbmc/settings/GUISettings.cpp | 3 +-- - xbmc/settings/GUIWindowSettingsCategory.cpp | 23 +++-------------------- - 4 files changed, 15 insertions(+), 30 deletions(-) - -diff --git a/language/English/strings.po b/language/English/strings.po -index 88292d3..4094fd0 100644 ---- a/language/English/strings.po -+++ b/language/English/strings.po -@@ -5119,7 +5119,7 @@ msgid "Allow Vdpau OpenGL interop" - msgstr "" - - msgctxt "#13436" --msgid "Allow Vdpau OpenGL interop YUV" -+msgid "Prefer VDPAU Video Mixer" - msgstr "" - - #empty strings from id 13437 to 13499 -diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/VDPAU.cpp b/xbmc/cores/dvdplayer/DVDCodecs/Video/VDPAU.cpp -index 07cfc04..0381c44 100644 ---- a/xbmc/cores/dvdplayer/DVDCodecs/Video/VDPAU.cpp -+++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/VDPAU.cpp -@@ -365,12 +365,15 @@ bool CDecoder::Supports(EINTERLACEMETHOD method) - || method == VS_INTERLACEMETHOD_AUTO) - return true; - -- if (g_guiSettings.GetBool("videoplayer.usevdpauinteropyuv")) -+ if (!m_vdpauConfig.usePixmaps) - { - if (method == VS_INTERLACEMETHOD_RENDER_BOB) - return true; - } - -+ if (method == VS_INTERLACEMETHOD_VDPAU_INVERSE_TELECINE) -+ return false; -+ - for(SInterlaceMapping* p = g_interlace_mapping; p->method != VS_INTERLACEMETHOD_NONE; p++) - { - if(p->method == method) -@@ -1847,7 +1850,7 @@ void CMixer::SetDeinterlacing() - - SetDeintSkipChroma(); - -- m_config.useInteropYuv = g_guiSettings.GetBool("videoplayer.usevdpauinteropyuv"); -+ m_config.useInteropYuv = !g_guiSettings.GetBool("videoplayer.usevdpaumixer"); - } - - void CMixer::SetDeintSkipChroma() -@@ -2039,7 +2042,7 @@ void CMixer::Init() - m_vdpError = false; - - m_config.upscale = g_advancedSettings.m_videoVDPAUScaling; -- m_config.useInteropYuv = g_guiSettings.GetBool("videoplayer.usevdpauinteropyuv"); -+ m_config.useInteropYuv = !g_guiSettings.GetBool("videoplayer.usevdpaumixer"); - - CreateVdpauMixer(); - } -@@ -2149,11 +2152,12 @@ void CMixer::InitCycle() - DVP_FLAG_INTERLACED); - m_config.useInteropYuv = false; - } -- else if (method == VS_INTERLACEMETHOD_RENDER_BOB && m_config.useInteropYuv) -+ else if (method == VS_INTERLACEMETHOD_RENDER_BOB) - { - m_mixersteps = 1; - m_mixerfield = VDP_VIDEO_MIXER_PICTURE_STRUCTURE_FRAME; - m_mixerInput[1].DVDPic.format = RENDER_FMT_VDPAU_420; -+ m_config.useInteropYuv = true; - } - else - { -@@ -3185,7 +3189,7 @@ bool COutput::GLInit() - glVDPAUGetSurfaceivNV = NULL; - #endif - -- m_config.usePixmaps = !g_guiSettings.GetBool("videoplayer.usevdpauinterop"); -+ m_config.usePixmaps = false; - - #ifdef GL_NV_vdpau_interop - if (glewIsSupported("GL_NV_vdpau_interop")) -@@ -3217,8 +3221,7 @@ bool COutput::GLInit() - #endif - { - m_config.usePixmaps = true; -- g_guiSettings.SetBool("videoplayer.usevdpauinterop",false); -- g_guiSettings.SetBool("videoplayer.usevdpauinteropyuv",false); -+ g_guiSettings.SetBool("videoplayer.usevdpaumixer",true); - } - if (!glXBindTexImageEXT) - glXBindTexImageEXT = (PFNGLXBINDTEXIMAGEEXTPROC)glXGetProcAddress((GLubyte *) "glXBindTexImageEXT"); -diff --git a/xbmc/settings/GUISettings.cpp b/xbmc/settings/GUISettings.cpp -index 4cdb093..33467d9 100644 ---- a/xbmc/settings/GUISettings.cpp -+++ b/xbmc/settings/GUISettings.cpp -@@ -685,8 +685,7 @@ void CGUISettings::Initialize() - - #ifdef HAVE_LIBVDPAU - AddBool(vp, "videoplayer.usevdpau", 13425, true); -- AddBool(vp, "videoplayer.usevdpauinterop", 13435, true); -- AddBool(vp, "videoplayer.usevdpauinteropyuv", 13436, false); -+ AddBool(vp, "videoplayer.usevdpaumixer", 13436, true); - #endif - #ifdef HAVE_LIBVA - AddBool(vp, "videoplayer.usevaapi", 13426, true); -diff --git a/xbmc/settings/GUIWindowSettingsCategory.cpp b/xbmc/settings/GUIWindowSettingsCategory.cpp -index d988598..2af9315 100644 ---- a/xbmc/settings/GUIWindowSettingsCategory.cpp -+++ b/xbmc/settings/GUIWindowSettingsCategory.cpp -@@ -596,9 +596,9 @@ void CGUIWindowSettingsCategory::UpdateSettings() - pControl->SetEnabled(true); - } - } -- else if (strSetting.Equals("videoplayer.usevdpauinteropyuv")) -+ else if (strSetting.Equals("videoplayer.usevdpaumixer")) - { -- bool hasInterop = g_guiSettings.GetBool("videoplayer.usevdpauinterop"); -+ bool hasInterop = true; - #ifndef GL_NV_vdpau_interop - hasInterop = false; - #endif -@@ -610,24 +610,7 @@ void CGUIWindowSettingsCategory::UpdateSettings() - else - { - pControl->SetEnabled(false); -- g_guiSettings.SetBool("videoplayer.usevdpauinteropyuv",false); -- } -- } -- else if (strSetting.Equals("videoplayer.usevdpauinterop")) -- { -- bool hasInterop = g_guiSettings.GetBool("videoplayer.usevdpau"); --#ifndef GL_NV_vdpau_interop -- hasInterop = false; --#endif -- CGUIControl *pControl = (CGUIControl *)GetControl(pSettingControl->GetID()); -- if (pControl && hasInterop && glewIsSupported("GL_NV_vdpau_interop")) -- { -- pControl->SetEnabled(true); -- } -- else -- { -- pControl->SetEnabled(false); -- g_guiSettings.SetBool("videoplayer.usevdpauinterop",false); -+ g_guiSettings.SetBool("videoplayer.usevdpaumixer",true); - } - } - else --- -1.7.10 - - -From 9a26e5a08777c1d928bc3e9e9f8cdb2bb9258917 Mon Sep 17 00:00:00 2001 -From: xbmc -Date: Wed, 12 Dec 2012 18:34:47 +0100 -Subject: [PATCH 29/88] vdpau: drop studio level conversion - ---- - language/English/strings.po | 6 +- - xbmc/cores/VideoRenderers/LinuxRendererGL.cpp | 4 +- - xbmc/cores/dvdplayer/DVDCodecs/Video/VDPAU.cpp | 94 +----------------------- - xbmc/settings/GUISettings.cpp | 1 - - 4 files changed, 7 insertions(+), 98 deletions(-) - -diff --git a/language/English/strings.po b/language/English/strings.po -index 4094fd0..c3ba92f 100644 ---- a/language/English/strings.po -+++ b/language/English/strings.po -@@ -4369,11 +4369,7 @@ msgctxt "#13121" - msgid "VDPAU HQ Upscaling level" - msgstr "" - --msgctxt "#13122" --msgid "VDPAU Studio level color conversion" --msgstr "" -- --#empty strings from id 13123 to 13129 -+#empty strings from id 13122 to 13129 - - msgctxt "#13130" - msgid "Blank other displays" -diff --git a/xbmc/cores/VideoRenderers/LinuxRendererGL.cpp b/xbmc/cores/VideoRenderers/LinuxRendererGL.cpp -index 4ee50c1..d2ba962 100644 ---- a/xbmc/cores/VideoRenderers/LinuxRendererGL.cpp -+++ b/xbmc/cores/VideoRenderers/LinuxRendererGL.cpp -@@ -3344,7 +3344,7 @@ bool CLinuxRendererGL::Supports(ERENDERFEATURE feature) - { - if(feature == RENDERFEATURE_BRIGHTNESS) - { -- if ((m_renderMethod & RENDER_VDPAU) && !g_guiSettings.GetBool("videoplayer.vdpaustudiolevel")) -+ if (m_renderMethod & RENDER_VDPAU) - return true; - - if (m_renderMethod & RENDER_VAAPI) -@@ -3357,7 +3357,7 @@ bool CLinuxRendererGL::Supports(ERENDERFEATURE feature) - - if(feature == RENDERFEATURE_CONTRAST) - { -- if ((m_renderMethod & RENDER_VDPAU) && !g_guiSettings.GetBool("videoplayer.vdpaustudiolevel")) -+ if (m_renderMethod & RENDER_VDPAU) - return true; - - if (m_renderMethod & RENDER_VAAPI) -diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/VDPAU.cpp b/xbmc/cores/dvdplayer/DVDCodecs/Video/VDPAU.cpp -index 0381c44..15c58b8 100644 ---- a/xbmc/cores/dvdplayer/DVDCodecs/Video/VDPAU.cpp -+++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/VDPAU.cpp -@@ -57,15 +57,6 @@ - }; - const size_t decoder_profile_count = sizeof(decoder_profiles)/sizeof(CDecoder::Desc); - --//static float studioCSC[3][4] = --//{ --// { 1.0f, 0.0f, 1.57480000f,-0.78740000f}, --// { 1.0f,-0.18737736f,-0.46813736f, 0.32775736f}, --// { 1.0f, 1.85556000f, 0.0f,-0.92780000f} --//}; --static float studioCSCKCoeffs601[3] = {0.299, 0.587, 0.114}; //BT601 {Kr, Kg, Kb} --static float studioCSCKCoeffs709[3] = {0.2126, 0.7152, 0.0722}; //BT709 {Kr, Kg, Kb} -- - static struct SInterlaceMapping - { - const EINTERLACEMETHOD method; -@@ -1614,74 +1605,6 @@ void CMixer::PostProcOff() - DisableHQScaling(); - } - -- --bool CMixer::GenerateStudioCSCMatrix(VdpColorStandard colorStandard, VdpCSCMatrix &studioCSCMatrix) --{ -- // instead use studioCSCKCoeffs601[3], studioCSCKCoeffs709[3] to generate float[3][4] matrix (float studioCSC[3][4]) -- // m00 = mRY = red: luma factor (contrast factor) (1.0) -- // m10 = mGY = green: luma factor (contrast factor) (1.0) -- // m20 = mBY = blue: luma factor (contrast factor) (1.0) -- // -- // m01 = mRB = red: blue color diff coeff (0.0) -- // m11 = mGB = green: blue color diff coeff (-2Kb(1-Kb)/(Kg)) -- // m21 = mBB = blue: blue color diff coeff ((1-Kb)/0.5) -- // -- // m02 = mRR = red: red color diff coeff ((1-Kr)/0.5) -- // m12 = mGR = green: red color diff coeff (-2Kr(1-Kr)/(Kg)) -- // m22 = mBR = blue: red color diff coeff (0.0) -- // -- // m03 = mRC = red: colour zero offset (brightness factor) (-(1-Kr)/0.5 * (128/255)) -- // m13 = mGC = green: colour zero offset (brightness factor) ((256/255) * (Kb(1-Kb) + Kr(1-Kr)) / Kg) -- // m23 = mBC = blue: colour zero offset (brightness factor) (-(1-Kb)/0.5 * (128/255)) -- -- // columns -- int Y = 0; -- int Cb = 1; -- int Cr = 2; -- int C = 3; -- // rows -- int R = 0; -- int G = 1; -- int B = 2; -- // colour standard coefficients for red, geen, blue -- double Kr, Kg, Kb; -- // colour diff zero position (use standard 8-bit coding precision) -- double CDZ = 128; //256*0.5 -- // range excursion (use standard 8-bit coding precision) -- double EXC = 255; //256-1 -- -- if (colorStandard == VDP_COLOR_STANDARD_ITUR_BT_601) -- { -- Kr = studioCSCKCoeffs601[0]; -- Kg = studioCSCKCoeffs601[1]; -- Kb = studioCSCKCoeffs601[2]; -- } -- else // assume VDP_COLOR_STANDARD_ITUR_BT_709 -- { -- Kr = studioCSCKCoeffs709[0]; -- Kg = studioCSCKCoeffs709[1]; -- Kb = studioCSCKCoeffs709[2]; -- } -- // we keep luma unscaled to retain the levels present in source so that 16-235 luma is converted to RGB 16-235 -- studioCSCMatrix[R][Y] = 1.0; -- studioCSCMatrix[G][Y] = 1.0; -- studioCSCMatrix[B][Y] = 1.0; -- -- studioCSCMatrix[R][Cb] = 0.0; -- studioCSCMatrix[G][Cb] = (double)-2 * Kb * (1 - Kb) / Kg; -- studioCSCMatrix[B][Cb] = (double)(1 - Kb) / 0.5; -- -- studioCSCMatrix[R][Cr] = (double)(1 - Kr) / 0.5; -- studioCSCMatrix[G][Cr] = (double)-2 * Kr * (1 - Kr) / Kg; -- studioCSCMatrix[B][Cr] = 0.0; -- -- studioCSCMatrix[R][C] = (double)-1 * studioCSCMatrix[R][Cr] * CDZ/EXC; -- studioCSCMatrix[G][C] = (double)-1 * (studioCSCMatrix[G][Cb] + studioCSCMatrix[G][Cr]) * CDZ/EXC; -- studioCSCMatrix[B][C] = (double)-1 * studioCSCMatrix[B][Cb] * CDZ/EXC; -- -- return true; --} -- - void CMixer::SetColor() - { - VdpStatus vdp_st; -@@ -1701,19 +1624,10 @@ void CMixer::SetColor() - //vdp_st = vdp_generate_csc_matrix(&m_Procamp, VDP_COLOR_STANDARD_ITUR_BT_601, &m_CSCMatrix); - - VdpVideoMixerAttribute attributes[] = { VDP_VIDEO_MIXER_ATTRIBUTE_CSC_MATRIX }; -- if (g_guiSettings.GetBool("videoplayer.vdpaustudiolevel")) -- { -- float studioCSC[3][4]; -- GenerateStudioCSCMatrix(colorStandard, studioCSC); -- void const * pm_CSCMatix[] = { &studioCSC }; -- vdp_st = m_config.vdpProcs.vdp_video_mixer_set_attribute_values(m_videoMixer, ARSIZE(attributes), attributes, pm_CSCMatix); -- } -- else -- { -- vdp_st = m_config.vdpProcs.vdp_generate_csc_matrix(&m_Procamp, colorStandard, &m_CSCMatrix); -- void const * pm_CSCMatix[] = { &m_CSCMatrix }; -- vdp_st = m_config.vdpProcs.vdp_video_mixer_set_attribute_values(m_videoMixer, ARSIZE(attributes), attributes, pm_CSCMatix); -- } -+ vdp_st = m_config.vdpProcs.vdp_generate_csc_matrix(&m_Procamp, colorStandard, &m_CSCMatrix); -+ void const * pm_CSCMatix[] = { &m_CSCMatrix }; -+ vdp_st = m_config.vdpProcs.vdp_video_mixer_set_attribute_values(m_videoMixer, ARSIZE(attributes), attributes, pm_CSCMatix); -+ - CheckStatus(vdp_st, __LINE__); - } - -diff --git a/xbmc/settings/GUISettings.cpp b/xbmc/settings/GUISettings.cpp -index 33467d9..4cec1b3 100644 ---- a/xbmc/settings/GUISettings.cpp -+++ b/xbmc/settings/GUISettings.cpp -@@ -764,7 +764,6 @@ void CGUISettings::Initialize() - AddSeparator(vp, "videoplayer.sep1.5"); - #ifdef HAVE_LIBVDPAU - AddBool(NULL, "videoplayer.vdpauUpscalingLevel", 13121, false); -- AddBool(vp, "videoplayer.vdpaustudiolevel", 13122, false); - #endif - #endif - AddSeparator(vp, "videoplayer.sep5"); --- -1.7.10 - - -From cf77997579bf3f5a46e17b6c1f9753f68ad49ce5 Mon Sep 17 00:00:00 2001 -From: xbmc -Date: Wed, 12 Dec 2012 20:28:49 +0100 -Subject: [PATCH 30/88] vdpau: observe ffmpeg tags for color space - ---- - xbmc/cores/dvdplayer/DVDCodecs/Video/VDPAU.cpp | 38 ++++++++++++++++-------- - xbmc/cores/dvdplayer/DVDCodecs/Video/VDPAU.h | 1 + - 2 files changed, 27 insertions(+), 12 deletions(-) - -diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/VDPAU.cpp b/xbmc/cores/dvdplayer/DVDCodecs/Video/VDPAU.cpp -index 15c58b8..34cc320 100644 ---- a/xbmc/cores/dvdplayer/DVDCodecs/Video/VDPAU.cpp -+++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/VDPAU.cpp -@@ -907,6 +907,7 @@ int CDecoder::Decode(AVCodecContext *avctx, AVFrame *pFrame) - memset(&pic.DVDPic, 0, sizeof(pic.DVDPic)); - ((CDVDVideoCodecFFmpeg*)avctx->opaque)->GetPictureCommon(&pic.DVDPic); - pic.render = render; -+ pic.DVDPic.color_matrix = avctx->colorspace; - m_bufferStats.IncDecoded(); - m_vdpauOutput.m_dataPort.SendOutMessage(COutputDataProtocol::NEWFRAME, &pic, sizeof(pic)); - -@@ -1513,10 +1514,6 @@ void CMixer::InitCSCMatrix(int Width) - m_Procamp.contrast = 1.0; - m_Procamp.saturation = 1.0; - m_Procamp.hue = 0; -- vdp_st = m_config.vdpProcs.vdp_generate_csc_matrix(&m_Procamp, -- (Width < 1000)? VDP_COLOR_STANDARD_ITUR_BT_601 : VDP_COLOR_STANDARD_ITUR_BT_709, -- &m_CSCMatrix); -- CheckStatus(vdp_st, __LINE__); - } - - void CMixer::CheckFeatures() -@@ -1527,11 +1524,13 @@ void CMixer::CheckFeatures() - m_Upscale = m_config.upscale; - } - if (m_Brightness != g_settings.m_currentVideoSettings.m_Brightness || -- m_Contrast != g_settings.m_currentVideoSettings.m_Contrast) -+ m_Contrast != g_settings.m_currentVideoSettings.m_Contrast || -+ m_ColorMatrix != m_mixerInput[1].DVDPic.color_matrix) - { - SetColor(); - m_Brightness = g_settings.m_currentVideoSettings.m_Brightness; - m_Contrast = g_settings.m_currentVideoSettings.m_Contrast; -+ m_ColorMatrix = m_mixerInput[1].DVDPic.color_matrix; - } - if (m_NoiseReduction != g_settings.m_currentVideoSettings.m_NoiseReduction) - { -@@ -1615,13 +1614,27 @@ void CMixer::SetColor() - m_Procamp.contrast = (float)((g_settings.m_currentVideoSettings.m_Contrast)+50) / 100; - - VdpColorStandard colorStandard; --// if(vid_height >= 600 || vid_width > 1024) -- if(m_config.surfaceWidth > 1000) -- colorStandard = VDP_COLOR_STANDARD_ITUR_BT_709; -- //vdp_st = vdp_generate_csc_matrix(&m_Procamp, VDP_COLOR_STANDARD_ITUR_BT_709, &m_CSCMatrix); -- else -- colorStandard = VDP_COLOR_STANDARD_ITUR_BT_601; -- //vdp_st = vdp_generate_csc_matrix(&m_Procamp, VDP_COLOR_STANDARD_ITUR_BT_601, &m_CSCMatrix); -+ switch(m_mixerInput[1].DVDPic.color_matrix) -+ { -+ case AVCOL_SPC_BT709: -+ colorStandard = VDP_COLOR_STANDARD_ITUR_BT_709; -+ break; -+ case AVCOL_SPC_BT470BG: -+ case AVCOL_SPC_SMPTE170M: -+ colorStandard = VDP_COLOR_STANDARD_ITUR_BT_601; -+ break; -+ case AVCOL_SPC_SMPTE240M: -+ colorStandard = VDP_COLOR_STANDARD_SMPTE_240M; -+ break; -+ case AVCOL_SPC_FCC: -+ case AVCOL_SPC_UNSPECIFIED: -+ case AVCOL_SPC_RGB: -+ default: -+ if(m_config.surfaceWidth > 1000) -+ colorStandard = VDP_COLOR_STANDARD_ITUR_BT_709; -+ else -+ colorStandard = VDP_COLOR_STANDARD_ITUR_BT_601; -+ } - - VdpVideoMixerAttribute attributes[] = { VDP_VIDEO_MIXER_ATTRIBUTE_CSC_MATRIX }; - vdp_st = m_config.vdpProcs.vdp_generate_csc_matrix(&m_Procamp, colorStandard, &m_CSCMatrix); -@@ -1952,6 +1965,7 @@ void CMixer::Init() - m_Sharpness = 0.0; - m_DeintMode = 0; - m_Deint = 0; -+ m_ColorMatrix = 0; - m_PostProc = false; - m_vdpError = false; - -diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/VDPAU.h b/xbmc/cores/dvdplayer/DVDCodecs/Video/VDPAU.h -index 4d1559c..471ad68 100644 ---- a/xbmc/cores/dvdplayer/DVDCodecs/Video/VDPAU.h -+++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/VDPAU.h -@@ -334,6 +334,7 @@ class CMixer : private CThread - int m_DeintMode; - int m_Deint; - int m_Upscale; -+ unsigned int m_ColorMatrix : 4; - uint32_t *m_BlackBar; - VdpVideoMixerPictureStructure m_mixerfield; - int m_mixerstep; --- -1.7.10 - - -From 4eef23adc7b4539fc8e1b87c7f2f6797b32b82ea Mon Sep 17 00:00:00 2001 -From: xbmc -Date: Sun, 27 Jan 2013 12:10:19 +0100 -Subject: [PATCH 31/88] vdpau: switch off de-interlacing on ff - ---- - xbmc/cores/dvdplayer/DVDCodecs/Video/VDPAU.cpp | 5 +++-- - 1 file changed, 3 insertions(+), 2 deletions(-) - -diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/VDPAU.cpp b/xbmc/cores/dvdplayer/DVDCodecs/Video/VDPAU.cpp -index 34cc320..5de75ab 100644 ---- a/xbmc/cores/dvdplayer/DVDCodecs/Video/VDPAU.cpp -+++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/VDPAU.cpp -@@ -2043,8 +2043,9 @@ void CMixer::InitCycle() - EINTERLACEMETHOD method = GetDeinterlacingMethod(); - bool interlaced = m_mixerInput[1].DVDPic.iFlags & DVP_FLAG_INTERLACED; - -- if (mode == VS_DEINTERLACEMODE_FORCE || -- (mode == VS_DEINTERLACEMODE_AUTO && interlaced)) -+ if (!(flags & DVP_FLAG_NO_POSTPROC) && -+ (mode == VS_DEINTERLACEMODE_FORCE || -+ (mode == VS_DEINTERLACEMODE_AUTO && interlaced))) - { - if((method == VS_INTERLACEMETHOD_AUTO && interlaced) - || method == VS_INTERLACEMETHOD_VDPAU_BOB --- -1.7.10 - - -From 96ef99611c9cd1740faf8dd02b09e4cbb5e9cdc0 Mon Sep 17 00:00:00 2001 -From: xbmc -Date: Sat, 2 Feb 2013 13:17:09 +0100 -Subject: [PATCH 32/88] vdpau: fix mp4 part2 decoding, activate by default - ---- - xbmc/cores/dvdplayer/DVDCodecs/Video/VDPAU.cpp | 8 ++------ - xbmc/settings/AdvancedSettings.cpp | 2 +- - 2 files changed, 3 insertions(+), 7 deletions(-) - -diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/VDPAU.cpp b/xbmc/cores/dvdplayer/DVDCodecs/Video/VDPAU.cpp -index 5de75ab..68cf36a 100644 ---- a/xbmc/cores/dvdplayer/DVDCodecs/Video/VDPAU.cpp -+++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/VDPAU.cpp -@@ -127,10 +127,9 @@ bool CDecoder::Open(AVCodecContext* avctx, const enum PixelFormat, unsigned int - VdpDecoderProfile profile = 0; - if(avctx->codec_id == CODEC_ID_H264) - profile = VDP_DECODER_PROFILE_H264_HIGH; --#ifdef VDP_DECODER_PROFILE_MPEG4_PART2_ASP - else if(avctx->codec_id == CODEC_ID_MPEG4) - profile = VDP_DECODER_PROFILE_MPEG4_PART2_ASP; --#endif -+ - if(profile) - { - if (!CDVDCodecUtils::IsVP3CompatibleWidth(avctx->coded_width)) -@@ -530,13 +529,10 @@ void CDecoder::ReadFormatOf( PixelFormat fmt - vdp_decoder_profile = VDP_DECODER_PROFILE_VC1_ADVANCED; - vdp_chroma_type = VDP_CHROMA_TYPE_420; - break; --#if (defined PIX_FMT_VDPAU_MPEG4_IN_AVUTIL) && \ -- (defined VDP_DECODER_PROFILE_MP) - case PIX_FMT_VDPAU_MPEG4: -- vdp_decoder_profile = VDP_DECOPEG4_PART2_ASP; -+ vdp_decoder_profile = VDP_DECODER_PROFILE_MPEG4_PART2_ASP; - vdp_chroma_type = VDP_CHROMA_TYPE_420; - break; --#endif - default: - vdp_decoder_profile = 0; - vdp_chroma_type = 0; -diff --git a/xbmc/settings/AdvancedSettings.cpp b/xbmc/settings/AdvancedSettings.cpp -index 844f8e8..04a7c7c 100644 ---- a/xbmc/settings/AdvancedSettings.cpp -+++ b/xbmc/settings/AdvancedSettings.cpp -@@ -102,7 +102,7 @@ void CAdvancedSettings::Initialize() - m_videoNonLinStretchRatio = 0.5f; - m_videoEnableHighQualityHwScalers = false; - m_videoAutoScaleMaxFps = 30.0f; -- m_videoAllowMpeg4VDPAU = false; -+ m_videoAllowMpeg4VDPAU = true; - m_videoAllowMpeg4VAAPI = false; - m_videoDisableBackgroundDeinterlace = false; - m_videoCaptureUseOcclusionQuery = -1; //-1 is auto detect --- -1.7.10 - - -From 477502af4a70f4251652c955e6e048025bb32514 Mon Sep 17 00:00:00 2001 -From: xbmc -Date: Tue, 25 Sep 2012 12:14:15 +0200 -Subject: [PATCH 33/88] linuxrenderer: drop method RenderMultiPass - ---- - xbmc/cores/VideoRenderers/LinuxRendererGL.cpp | 9 ++------- - xbmc/cores/VideoRenderers/LinuxRendererGL.h | 1 - - 2 files changed, 2 insertions(+), 8 deletions(-) - -diff --git a/xbmc/cores/VideoRenderers/LinuxRendererGL.cpp b/xbmc/cores/VideoRenderers/LinuxRendererGL.cpp -index d2ba962..62198f0 100644 ---- a/xbmc/cores/VideoRenderers/LinuxRendererGL.cpp -+++ b/xbmc/cores/VideoRenderers/LinuxRendererGL.cpp -@@ -1205,7 +1205,8 @@ void CLinuxRendererGL::Render(DWORD flags, int renderBuffer) - break; - - case RQ_MULTIPASS: -- RenderMultiPass(renderBuffer, m_currentField); -+ RenderToFBO(renderBuffer, m_currentField); -+ RenderFromFBO(); - VerifyGLState(); - break; - } -@@ -1328,12 +1329,6 @@ void CLinuxRendererGL::RenderSinglePass(int index, int field) - VerifyGLState(); - } - --void CLinuxRendererGL::RenderMultiPass(int index, int field) --{ -- RenderToFBO(index, field); -- RenderFromFBO(); --} -- - void CLinuxRendererGL::RenderToFBO(int index, int field) - { - YUVPLANES &planes = m_buffers[index].fields[field]; -diff --git a/xbmc/cores/VideoRenderers/LinuxRendererGL.h b/xbmc/cores/VideoRenderers/LinuxRendererGL.h -index 329ddee..08f8234 100644 ---- a/xbmc/cores/VideoRenderers/LinuxRendererGL.h -+++ b/xbmc/cores/VideoRenderers/LinuxRendererGL.h -@@ -216,7 +216,6 @@ class CLinuxRendererGL : public CBaseRenderer - void CalculateTextureSourceRects(int source, int num_planes); - - // renderers -- void RenderMultiPass(int renderBuffer, int field); // multi pass glsl renderer - void RenderToFBO(int renderBuffer, int field); - void RenderFromFBO(); - void RenderSinglePass(int renderBuffer, int field); // single pass glsl renderer --- -1.7.10 - - -From 48fb2351e755727506993d6fd0334c368fffbee6 Mon Sep 17 00:00:00 2001 -From: xbmc -Date: Tue, 25 Sep 2012 13:20:47 +0200 -Subject: [PATCH 34/88] linuxrenderer: implement progressive weave for vdpau - ---- - xbmc/cores/VideoRenderers/LinuxRendererGL.cpp | 55 ++++++++++++++++++------- - xbmc/cores/VideoRenderers/LinuxRendererGL.h | 4 +- - 2 files changed, 41 insertions(+), 18 deletions(-) - -diff --git a/xbmc/cores/VideoRenderers/LinuxRendererGL.cpp b/xbmc/cores/VideoRenderers/LinuxRendererGL.cpp -index 62198f0..6e6d97e 100644 ---- a/xbmc/cores/VideoRenderers/LinuxRendererGL.cpp -+++ b/xbmc/cores/VideoRenderers/LinuxRendererGL.cpp -@@ -689,18 +689,6 @@ void CLinuxRendererGL::RenderUpdate(bool clear, DWORD flags, DWORD alpha) - glDisable(GL_POLYGON_STIPPLE); - - } -- else if(m_format == RENDER_FMT_VDPAU_420 -- && !(flags & RENDER_FLAG_BOTH)) -- { -- glDisable(GL_BLEND); -- glColor4f(1.0f, 1.0f, 1.0f, 1.0f); -- Render(flags | RENDER_FLAG_TOP, index); -- -- glEnable(GL_BLEND); -- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); -- glColor4f(1.0f, 1.0f, 1.0f, 128 / 255.0f); -- Render(flags | RENDER_FLAG_BOT , index); -- } - else - Render(flags, index); - -@@ -1200,13 +1188,21 @@ void CLinuxRendererGL::Render(DWORD flags, int renderBuffer) - { - case RQ_LOW: - case RQ_SINGLEPASS: -- RenderSinglePass(renderBuffer, m_currentField); -+ if (m_format == RENDER_FMT_VDPAU_420 && m_currentField == FIELD_FULL) -+ RenderProgressiveWeave(renderBuffer, m_currentField); -+ else -+ RenderSinglePass(renderBuffer, m_currentField); - VerifyGLState(); - break; - - case RQ_MULTIPASS: -- RenderToFBO(renderBuffer, m_currentField); -- RenderFromFBO(); -+ if (m_format == RENDER_FMT_VDPAU_420 && m_currentField == FIELD_FULL) -+ RenderProgressiveWeave(renderBuffer, m_currentField); -+ else -+ { -+ RenderToFBO(renderBuffer, m_currentField); -+ RenderFromFBO(); -+ } - VerifyGLState(); - break; - } -@@ -1329,7 +1325,7 @@ void CLinuxRendererGL::RenderSinglePass(int index, int field) - VerifyGLState(); - } - --void CLinuxRendererGL::RenderToFBO(int index, int field) -+void CLinuxRendererGL::RenderToFBO(int index, int field, bool weave /*= false*/) - { - YUVPLANES &planes = m_buffers[index].fields[field]; - -@@ -1431,6 +1427,8 @@ void CLinuxRendererGL::RenderToFBO(int index, int field) - } - m_fbo.width *= planes[0].pixpertex_x; - m_fbo.height *= planes[0].pixpertex_y; -+ if (weave) -+ m_fbo.height *= 2; - - // 1st Pass to video frame size - glBegin(GL_QUADS); -@@ -1549,6 +1547,31 @@ void CLinuxRendererGL::RenderFromFBO() - VerifyGLState(); - } - -+void CLinuxRendererGL::RenderProgressiveWeave(int index, int field) -+{ -+ bool scaleUp = (int)m_sourceHeight < g_graphicsContext.GetHeight() || (int)m_sourceWidth < g_graphicsContext.GetWidth(); -+ -+ if (m_fbo.fbo.IsSupported() && (scaleUp || m_renderQuality == RQ_MULTIPASS)) -+ { -+ glEnable(GL_POLYGON_STIPPLE); -+ glPolygonStipple(stipple_weave); -+ RenderToFBO(index, FIELD_TOP, true); -+ glPolygonStipple(stipple_weave+4); -+ RenderToFBO(index, FIELD_BOT, true); -+ glDisable(GL_POLYGON_STIPPLE); -+ RenderFromFBO(); -+ } -+ else -+ { -+ glEnable(GL_POLYGON_STIPPLE); -+ glPolygonStipple(stipple_weave); -+ RenderSinglePass(index, FIELD_TOP); -+ glPolygonStipple(stipple_weave+4); -+ RenderSinglePass(index, FIELD_BOT); -+ glDisable(GL_POLYGON_STIPPLE); -+ } -+} -+ - void CLinuxRendererGL::RenderVDPAU(int index, int field) - { - #ifdef HAVE_LIBVDPAU -diff --git a/xbmc/cores/VideoRenderers/LinuxRendererGL.h b/xbmc/cores/VideoRenderers/LinuxRendererGL.h -index 08f8234..13217ce 100644 ---- a/xbmc/cores/VideoRenderers/LinuxRendererGL.h -+++ b/xbmc/cores/VideoRenderers/LinuxRendererGL.h -@@ -216,12 +216,12 @@ class CLinuxRendererGL : public CBaseRenderer - void CalculateTextureSourceRects(int source, int num_planes); - - // renderers -- void RenderToFBO(int renderBuffer, int field); -+ void RenderToFBO(int renderBuffer, int field, bool weave = false); - void RenderFromFBO(); - void RenderSinglePass(int renderBuffer, int field); // single pass glsl renderer - void RenderSoftware(int renderBuffer, int field); // single pass s/w yuv2rgb renderer - void RenderVDPAU(int renderBuffer, int field); // render using vdpau hardware -- void RenderVDPAUYV12(int renderBuffer, int field); // render using vdpau hardware -+ void RenderProgressiveWeave(int renderBuffer, int field); // render using vdpau hardware - void RenderVAAPI(int renderBuffer, int field); // render using vdpau hardware - - struct --- -1.7.10 - - -From 46d819fbe6386640cee6bf94b3c6df8b78addaa5 Mon Sep 17 00:00:00 2001 -From: FernetMenta -Date: Thu, 5 Jul 2012 15:22:05 +0200 -Subject: [PATCH 35/88] X11: ditch SDL for video and window events - ---- - xbmc/Application.cpp | 2 +- - xbmc/system.h | 5 + - xbmc/windowing/Makefile | 1 + - xbmc/windowing/WinEvents.h | 4 + - xbmc/windowing/WinEventsX11.cpp | 765 +++++++++++++++++++++++++++++++++++ - xbmc/windowing/WinEventsX11.h | 57 +++ - xbmc/windowing/X11/WinSystemX11.cpp | 370 ++++++++++++----- - xbmc/windowing/X11/WinSystemX11.h | 9 +- - 8 files changed, 1112 insertions(+), 101 deletions(-) - create mode 100644 xbmc/windowing/WinEventsX11.cpp - create mode 100644 xbmc/windowing/WinEventsX11.h - -diff --git a/xbmc/Application.cpp b/xbmc/Application.cpp -index 5c7017c..8259eba 100644 ---- a/xbmc/Application.cpp -+++ b/xbmc/Application.cpp -@@ -794,7 +794,7 @@ bool CApplication::CreateGUI() - - uint32_t sdlFlags = 0; - --#if defined(HAS_SDL_OPENGL) || (HAS_GLES == 2) -+#if (defined(HAS_SDL_OPENGL) || (HAS_GLES == 2)) && !defined(HAS_GLX) - sdlFlags |= SDL_INIT_VIDEO; - #endif - -diff --git a/xbmc/system.h b/xbmc/system.h -index 4165c01..32584b1 100644 ---- a/xbmc/system.h -+++ b/xbmc/system.h -@@ -162,16 +162,21 @@ - #define HAS_GL - #ifdef HAVE_X11 - #define HAS_GLX -+#define HAS_X11_WIN_EVENTS - #endif - #ifdef HAVE_SDL - #define HAS_SDL - #ifndef HAS_SDL_OPENGL - #define HAS_SDL_OPENGL - #endif -+#ifndef HAVE_X11 - #define HAS_SDL_WIN_EVENTS -+#endif - #else -+#ifndef HAVE_X11 - #define HAS_LINUX_EVENTS - #endif -+#endif - #define HAS_LINUX_NETWORK - #define HAS_LIRC - #ifdef HAVE_LIBPULSE -diff --git a/xbmc/windowing/Makefile b/xbmc/windowing/Makefile -index f109bec..f981642 100644 ---- a/xbmc/windowing/Makefile -+++ b/xbmc/windowing/Makefile -@@ -1,6 +1,7 @@ - SRCS=WinEventsSDL.cpp \ - WinEventsLinux.cpp \ - WinSystem.cpp \ -+ WinEventsX11.cpp \ - - LIB=windowing.a - -diff --git a/xbmc/windowing/WinEvents.h b/xbmc/windowing/WinEvents.h -index 6d322a9..5a671cc 100644 ---- a/xbmc/windowing/WinEvents.h -+++ b/xbmc/windowing/WinEvents.h -@@ -58,6 +58,10 @@ class CWinEventsBase - #include "WinEventsSDL.h" - #define CWinEvents CWinEventsSDL - -+#elif defined(TARGET_LINUX) && defined(HAS_X11_WIN_EVENTS) -+#include "WinEventsX11.h" -+#define CWinEvents CWinEventsX11 -+ - #elif defined(TARGET_LINUX) && defined(HAS_LINUX_EVENTS) - #include "WinEventsLinux.h" - #define CWinEvents CWinEventsLinux -diff --git a/xbmc/windowing/WinEventsX11.cpp b/xbmc/windowing/WinEventsX11.cpp -new file mode 100644 -index 0000000..24477ae ---- /dev/null -+++ b/xbmc/windowing/WinEventsX11.cpp -@@ -0,0 +1,765 @@ -+/* -+* Copyright (C) 2005-2012 Team XBMC -+* http://www.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, write to -+* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. -+* http://www.gnu.org/copyleft/gpl.html -+* -+*/ -+ -+#include "system.h" -+ -+#ifdef HAS_X11_WIN_EVENTS -+ -+#include "WinEvents.h" -+#include "WinEventsX11.h" -+#include "Application.h" -+#include "ApplicationMessenger.h" -+#include -+#include "X11/WinSystemX11GL.h" -+#include "X11/keysymdef.h" -+#include "X11/XF86keysym.h" -+#include "utils/log.h" -+#include "guilib/GUIWindowManager.h" -+#include "input/MouseStat.h" -+ -+CWinEventsX11* CWinEventsX11::WinEvents = 0; -+ -+static uint32_t SymMappingsX11[][2] = -+{ -+ {XK_BackSpace, XBMCK_BACKSPACE} -+, {XK_Tab, XBMCK_TAB} -+, {XK_Clear, XBMCK_CLEAR} -+, {XK_Return, XBMCK_RETURN} -+, {XK_Pause, XBMCK_PAUSE} -+, {XK_Escape, XBMCK_ESCAPE} -+, {XK_Delete, XBMCK_DELETE} -+// multi-media keys -+, {XF86XK_Back, XBMCK_BROWSER_BACK} -+, {XF86XK_Forward, XBMCK_BROWSER_FORWARD} -+, {XF86XK_Refresh, XBMCK_BROWSER_REFRESH} -+, {XF86XK_Stop, XBMCK_BROWSER_STOP} -+, {XF86XK_Search, XBMCK_BROWSER_SEARCH} -+, {XF86XK_Favorites, XBMCK_BROWSER_FAVORITES} -+, {XF86XK_HomePage, XBMCK_BROWSER_HOME} -+, {XF86XK_AudioMute, XBMCK_VOLUME_MUTE} -+, {XF86XK_AudioLowerVolume, XBMCK_VOLUME_DOWN} -+, {XF86XK_AudioRaiseVolume, XBMCK_VOLUME_UP} -+, {XF86XK_AudioNext, XBMCK_MEDIA_NEXT_TRACK} -+, {XF86XK_AudioPrev, XBMCK_MEDIA_PREV_TRACK} -+, {XF86XK_AudioStop, XBMCK_MEDIA_STOP} -+, {XF86XK_AudioPause, XBMCK_MEDIA_PLAY_PAUSE} -+, {XF86XK_Mail, XBMCK_LAUNCH_MAIL} -+, {XF86XK_Select, XBMCK_LAUNCH_MEDIA_SELECT} -+, {XF86XK_Launch0, XBMCK_LAUNCH_APP1} -+, {XF86XK_Launch1, XBMCK_LAUNCH_APP2} -+, {XF86XK_WWW, XBMCK_LAUNCH_FILE_BROWSER} -+, {XF86XK_AudioMedia, XBMCK_LAUNCH_MEDIA_CENTER } -+ // Numeric keypad -+, {XK_KP_0, XBMCK_KP0} -+, {XK_KP_1, XBMCK_KP1} -+, {XK_KP_2, XBMCK_KP2} -+, {XK_KP_3, XBMCK_KP3} -+, {XK_KP_4, XBMCK_KP4} -+, {XK_KP_5, XBMCK_KP5} -+, {XK_KP_6, XBMCK_KP6} -+, {XK_KP_7, XBMCK_KP7} -+, {XK_KP_8, XBMCK_KP8} -+, {XK_KP_9, XBMCK_KP9} -+, {XK_KP_Separator, XBMCK_KP_PERIOD} -+, {XK_KP_Divide, XBMCK_KP_DIVIDE} -+, {XK_KP_Multiply, XBMCK_KP_MULTIPLY} -+, {XK_KP_Subtract, XBMCK_KP_MINUS} -+, {XK_KP_Add, XBMCK_KP_PLUS} -+, {XK_KP_Enter, XBMCK_KP_ENTER} -+, {XK_KP_Equal, XBMCK_KP_EQUALS} -+ // Arrows + Home/End pad -+, {XK_Up, XBMCK_UP} -+, {XK_Down, XBMCK_DOWN} -+, {XK_Right, XBMCK_RIGHT} -+, {XK_Left, XBMCK_LEFT} -+, {XK_Insert, XBMCK_INSERT} -+, {XK_Home, XBMCK_HOME} -+, {XK_End, XBMCK_END} -+, {XK_Page_Up, XBMCK_PAGEUP} -+, {XK_Page_Down, XBMCK_PAGEDOWN} -+ // Function keys -+, {XK_F1, XBMCK_F1} -+, {XK_F2, XBMCK_F2} -+, {XK_F3, XBMCK_F3} -+, {XK_F4, XBMCK_F4} -+, {XK_F5, XBMCK_F5} -+, {XK_F6, XBMCK_F6} -+, {XK_F7, XBMCK_F7} -+, {XK_F8, XBMCK_F8} -+, {XK_F9, XBMCK_F9} -+, {XK_F10, XBMCK_F10} -+, {XK_F11, XBMCK_F11} -+, {XK_F12, XBMCK_F12} -+, {XK_F13, XBMCK_F13} -+, {XK_F14, XBMCK_F14} -+, {XK_F15, XBMCK_F15} -+ // Key state modifier keys -+, {XK_Num_Lock, XBMCK_NUMLOCK} -+, {XK_Caps_Lock, XBMCK_CAPSLOCK} -+, {XK_Scroll_Lock, XBMCK_SCROLLOCK} -+, {XK_Shift_R, XBMCK_RSHIFT} -+, {XK_Shift_L, XBMCK_LSHIFT} -+, {XK_Control_R, XBMCK_RCTRL} -+, {XK_Control_L, XBMCK_LCTRL} -+, {XK_Alt_R, XBMCK_RALT} -+, {XK_Alt_L, XBMCK_LALT} -+, {XK_Meta_R, XBMCK_RMETA} -+, {XK_Meta_L, XBMCK_LMETA} -+, {XK_Super_L, XBMCK_LSUPER} -+, {XK_Super_R, XBMCK_RSUPER} -+, {XK_Mode_switch, XBMCK_MODE} -+, {XK_Multi_key, XBMCK_COMPOSE} -+ // Miscellaneous function keys -+, {XK_Help, XBMCK_HELP} -+, {XK_Print, XBMCK_PRINT} -+//, {0, XBMCK_SYSREQ} -+, {XK_Break, XBMCK_BREAK} -+, {XK_Menu, XBMCK_MENU} -+, {XF86XK_PowerOff, XBMCK_POWER} -+, {XK_EcuSign, XBMCK_EURO} -+, {XK_Undo, XBMCK_UNDO} -+ /* Media keys */ -+, {XF86XK_Eject, XBMCK_EJECT} -+, {XF86XK_Stop, XBMCK_STOP} -+, {XF86XK_AudioRecord, XBMCK_RECORD} -+, {XF86XK_AudioRewind, XBMCK_REWIND} -+, {XF86XK_Phone, XBMCK_PHONE} -+, {XF86XK_AudioPlay, XBMCK_PLAY} -+, {XF86XK_AudioRandomPlay, XBMCK_SHUFFLE} -+, {XF86XK_AudioForward, XBMCK_FASTFORWARD} -+}; -+ -+ -+CWinEventsX11::CWinEventsX11() -+{ -+ m_display = 0; -+ m_window = 0; -+ m_keybuf = 0; -+ m_utf16buf = 0; -+} -+ -+CWinEventsX11::~CWinEventsX11() -+{ -+ if (m_keybuf); -+ { -+ free(m_keybuf); -+ m_keybuf = 0; -+ } -+ -+ if (m_utf16buf) -+ { -+ free(m_utf16buf); -+ m_utf16buf = 0; -+ } -+ -+ if (m_xic) -+ { -+ XUnsetICFocus(m_xic); -+ XDestroyIC(m_xic); -+ m_xic = 0; -+ } -+ -+ if (m_xim) -+ { -+ XCloseIM(m_xim); -+ m_xim = 0; -+ } -+ -+ m_symLookupTable.clear(); -+} -+ -+bool CWinEventsX11::Init(Display *dpy, Window win) -+{ -+ if (WinEvents) -+ return true; -+ -+ WinEvents = new CWinEventsX11(); -+ WinEvents->m_display = dpy; -+ WinEvents->m_window = win; -+ WinEvents->m_keybuf = (char*)malloc(32*sizeof(char)); -+ WinEvents->m_utf16buf = (uint16_t*)malloc(32*sizeof(uint16_t)); -+ WinEvents->m_keymodState = 0; -+ WinEvents->m_wmDeleteMessage = XInternAtom(dpy, "WM_DELETE_WINDOW", False); -+ WinEvents->m_structureChanged = false; -+ memset(&(WinEvents->m_lastKey), 0, sizeof(XBMC_Event)); -+ -+ // open input method -+ char *old_locale = NULL, *old_modifiers = NULL; -+ char res_name[8]; -+ const char *p; -+ size_t n; -+ -+ // set resource name to xbmc, not used -+ strcpy(res_name, "xbmc"); -+ -+ // save current locale, this should be "C" -+ p = setlocale(LC_ALL, NULL); -+ if (p) -+ { -+ old_locale = (char*)malloc(strlen(p) +1); -+ strcpy(old_locale, p); -+ } -+ p = XSetLocaleModifiers(NULL); -+ if (p) -+ { -+ old_modifiers = (char*)malloc(strlen(p) +1); -+ strcpy(old_modifiers, p); -+ } -+ -+ // set users preferences and open input method -+ p = setlocale(LC_ALL, ""); -+ XSetLocaleModifiers(""); -+ WinEvents->m_xim = XOpenIM(WinEvents->m_display, NULL, res_name, res_name); -+ -+ // restore old locale -+ if (old_locale) -+ { -+ setlocale(LC_ALL, old_locale); -+ free(old_locale); -+ } -+ if (old_modifiers) -+ { -+ XSetLocaleModifiers(old_modifiers); -+ free(old_modifiers); -+ } -+ -+ WinEvents->m_xic = NULL; -+ if (WinEvents->m_xim) -+ { -+ WinEvents->m_xic = XCreateIC(WinEvents->m_xim, -+ XNClientWindow, WinEvents->m_window, -+ XNFocusWindow, WinEvents->m_window, -+ XNInputStyle, XIMPreeditNothing | XIMStatusNothing, -+ XNResourceName, res_name, -+ XNResourceClass, res_name, -+ NULL); -+ } -+ -+ if (!WinEvents->m_xic) -+ CLog::Log(LOGWARNING,"CWinEventsX11::Init - no input method found"); -+ -+ // build Keysym lookup table -+ for (unsigned int i = 0; i < sizeof(SymMappingsX11)/(2*sizeof(uint32_t)); ++i) -+ { -+ WinEvents->m_symLookupTable[SymMappingsX11[i][0]] = SymMappingsX11[i][1]; -+ } -+ -+ return true; -+} -+ -+void CWinEventsX11::Quit() -+{ -+ if (!WinEvents) -+ return; -+ -+ delete WinEvents; -+ WinEvents = 0; -+} -+ -+bool CWinEventsX11::HasStructureChanged() -+{ -+ if (!WinEvents) -+ return false; -+ -+ bool ret = WinEvents->m_structureChanged; -+ WinEvents->m_structureChanged = false; -+ return ret; -+} -+ -+bool CWinEventsX11::MessagePump() -+{ -+ if (!WinEvents) -+ return false; -+ -+ bool ret = false; -+ XEvent xevent; -+ unsigned long serial = 0; -+ -+ while (WinEvents && XPending(WinEvents->m_display)) -+ { -+ memset(&xevent, 0, sizeof (XEvent)); -+ XNextEvent(WinEvents->m_display, &xevent); -+ -+ // ignore events generated by auto-repeat -+ if (xevent.type == KeyRelease && XPending(WinEvents->m_display)) -+ { -+ XEvent peekevent; -+ XPeekEvent(WinEvents->m_display, &peekevent); -+ if ((peekevent.type == KeyPress) && -+ (peekevent.xkey.keycode == xevent.xkey.keycode) && -+ ((peekevent.xkey.time - xevent.xkey.time) < 2)) -+ { -+ XNextEvent(WinEvents->m_display, &peekevent); -+ continue; -+ } -+ } -+ -+ if (XFilterEvent(&xevent, None)) -+ continue; -+ -+ switch (xevent.type) -+ { -+ case MapNotify: -+ { -+ g_application.m_AppActive = true; -+ break; -+ } -+ -+ case UnmapNotify: -+ { -+ g_application.m_AppActive = false; -+ break; -+ } -+ -+ case FocusIn: -+ { -+ if (WinEvents->m_xic) -+ XSetICFocus(WinEvents->m_xic); -+ g_application.m_AppFocused = true; -+ if (serial == xevent.xfocus.serial) -+ break; -+ g_Windowing.NotifyAppFocusChange(g_application.m_AppFocused); -+ break; -+ } -+ -+ case FocusOut: -+ { -+ if (WinEvents->m_xic) -+ XUnsetICFocus(WinEvents->m_xic); -+ g_application.m_AppFocused = false; -+ g_Windowing.NotifyAppFocusChange(g_application.m_AppFocused); -+ serial = xevent.xfocus.serial; -+ break; -+ } -+ -+ case Expose: -+ { -+ g_windowManager.MarkDirty(); -+ break; -+ } -+ -+ case ConfigureNotify: -+ { -+ if (xevent.xconfigure.window != WinEvents->m_window) -+ break; -+ -+ WinEvents->m_structureChanged = true; -+ XBMC_Event newEvent; -+ memset(&newEvent, 0, sizeof(newEvent)); -+ newEvent.type = XBMC_VIDEORESIZE; -+ newEvent.resize.w = xevent.xconfigure.width; -+ newEvent.resize.h = xevent.xconfigure.height; -+ ret |= g_application.OnEvent(newEvent); -+ g_windowManager.MarkDirty(); -+ break; -+ } -+ -+ case ClientMessage: -+ { -+ if (xevent.xclient.data.l[0] == WinEvents->m_wmDeleteMessage) -+ if (!g_application.m_bStop) CApplicationMessenger::Get().Quit(); -+ break; -+ } -+ -+ case KeyPress: -+ { -+ XBMC_Event newEvent; -+ memset(&newEvent, 0, sizeof(newEvent)); -+ newEvent.type = XBMC_KEYDOWN; -+ KeySym xkeysym; -+ -+ // fallback if we have no IM -+ if (!WinEvents->m_xic) -+ { -+ static XComposeStatus state; -+ char keybuf[32]; -+ xkeysym = XLookupKeysym(&xevent.xkey, 0); -+ newEvent.key.keysym.sym = LookupXbmcKeySym(xkeysym); -+ newEvent.key.keysym.scancode = xevent.xkey.keycode; -+ newEvent.key.state = xevent.xkey.state; -+ newEvent.key.type = xevent.xkey.type; -+ if (XLookupString(&xevent.xkey, keybuf, sizeof(keybuf), NULL, &state)) -+ { -+ newEvent.key.keysym.unicode = keybuf[0]; -+ } -+ ret |= ProcessKey(newEvent, 500); -+ break; -+ } -+ -+ Status status; -+ int utf16size; -+ int utf16length; -+ int len; -+ len = Xutf8LookupString(WinEvents->m_xic, &xevent.xkey, -+ WinEvents->m_keybuf, sizeof(WinEvents->m_keybuf), -+ &xkeysym, &status); -+ if (status == XBufferOverflow) -+ { -+ WinEvents->m_keybuf = (char*)realloc(WinEvents->m_keybuf, len*sizeof(char)); -+ len = Xutf8LookupString(WinEvents->m_xic, &xevent.xkey, -+ WinEvents->m_keybuf, sizeof(WinEvents->m_keybuf), -+ &xkeysym, &status); -+ } -+ switch (status) -+ { -+ case XLookupNone: -+ break; -+ case XLookupChars: -+ case XLookupBoth: -+ { -+ if (len == 0) -+ break; -+ utf16size = len * sizeof(uint16_t); -+ if (utf16size > sizeof(WinEvents->m_utf16buf)) -+ { -+ WinEvents->m_utf16buf = (uint16_t *)realloc(WinEvents->m_utf16buf,utf16size); -+ if (WinEvents->m_utf16buf == NULL) -+ { -+ break; -+ } -+ } -+ utf16length = Utf8ToUnicode(WinEvents->m_keybuf, len, WinEvents->m_utf16buf, utf16size); -+ if (utf16length < 0) -+ { -+ break; -+ } -+ for (unsigned int i = 0; i < utf16length - 1; i++) -+ { -+ newEvent.key.keysym.sym = XBMCK_UNKNOWN; -+ newEvent.key.keysym.unicode = WinEvents->m_utf16buf[i]; -+ newEvent.key.state = xevent.xkey.state; -+ newEvent.key.type = xevent.xkey.type; -+ ret |= ProcessKey(newEvent, 500); -+ } -+ if (utf16length > 0) -+ { -+ newEvent.key.keysym.scancode = xevent.xkey.keycode; -+ xkeysym = XLookupKeysym(&xevent.xkey, 0); -+ newEvent.key.keysym.sym = LookupXbmcKeySym(xkeysym); -+ newEvent.key.keysym.unicode = WinEvents->m_utf16buf[utf16length - 1]; -+ newEvent.key.state = xevent.xkey.state; -+ newEvent.key.type = xevent.xkey.type; -+ -+ ret |= ProcessKey(newEvent, 500); -+ } -+ break; -+ } -+ -+ case XLookupKeySym: -+ { -+ newEvent.key.keysym.scancode = xevent.xkey.keycode; -+ newEvent.key.keysym.sym = LookupXbmcKeySym(xkeysym); -+ newEvent.key.state = xevent.xkey.state; -+ newEvent.key.type = xevent.xkey.type; -+ ret |= ProcessKey(newEvent, 500); -+ break; -+ } -+ -+ }// switch status -+ break; -+ } //KeyPress -+ -+ case KeyRelease: -+ { -+ XBMC_Event newEvent; -+ KeySym xkeysym; -+ memset(&newEvent, 0, sizeof(newEvent)); -+ newEvent.type = XBMC_KEYUP; -+ xkeysym = XLookupKeysym(&xevent.xkey, 0); -+ newEvent.key.keysym.scancode = xevent.xkey.keycode; -+ newEvent.key.keysym.sym = LookupXbmcKeySym(xkeysym); -+ newEvent.key.state = xevent.xkey.state; -+ newEvent.key.type = xevent.xkey.type; -+ ret |= ProcessKey(newEvent, 0); -+ break; -+ } -+ -+ // lose mouse coverage -+ case LeaveNotify: -+ { -+ g_Mouse.SetActive(false); -+ break; -+ } -+ -+ case MotionNotify: -+ { -+ XBMC_Event newEvent; -+ memset(&newEvent, 0, sizeof(newEvent)); -+ newEvent.type = XBMC_MOUSEMOTION; -+ newEvent.motion.xrel = (int16_t)xevent.xmotion.x_root; -+ newEvent.motion.yrel = (int16_t)xevent.xmotion.y_root; -+ newEvent.motion.x = (int16_t)xevent.xmotion.x; -+ newEvent.motion.y = (int16_t)xevent.xmotion.y; -+ ret |= g_application.OnEvent(newEvent); -+ break; -+ } -+ -+ case ButtonPress: -+ { -+ XBMC_Event newEvent; -+ memset(&newEvent, 0, sizeof(newEvent)); -+ newEvent.type = XBMC_MOUSEBUTTONDOWN; -+ newEvent.button.button = (unsigned char)xevent.xbutton.button; -+ newEvent.button.state = XBMC_PRESSED; -+ newEvent.button.x = (int16_t)xevent.xbutton.x; -+ newEvent.button.y = (int16_t)xevent.xbutton.y; -+ ret |= g_application.OnEvent(newEvent); -+ break; -+ } -+ -+ case ButtonRelease: -+ { -+ XBMC_Event newEvent; -+ memset(&newEvent, 0, sizeof(newEvent)); -+ newEvent.type = XBMC_MOUSEBUTTONUP; -+ newEvent.button.button = (unsigned char)xevent.xbutton.button; -+ newEvent.button.state = XBMC_RELEASED; -+ newEvent.button.x = (int16_t)xevent.xbutton.x; -+ newEvent.button.y = (int16_t)xevent.xbutton.y; -+ ret |= g_application.OnEvent(newEvent); -+ break; -+ } -+ -+ default: -+ { -+ break; -+ } -+ }// switch event.type -+ }// while -+ -+ ret |= ProcessKeyRepeat(); -+ -+ return ret; -+} -+ -+bool CWinEventsX11::ProcessKey(XBMC_Event &event, int repeatDelay) -+{ -+ if (event.type == XBMC_KEYDOWN) -+ { -+ // check key modifiers -+ switch(event.key.keysym.sym) -+ { -+ case XBMCK_LSHIFT: -+ WinEvents->m_keymodState |= XBMCKMOD_LSHIFT; -+ break; -+ case XBMCK_RSHIFT: -+ WinEvents->m_keymodState |= XBMCKMOD_RSHIFT; -+ break; -+ case XBMCK_LCTRL: -+ WinEvents->m_keymodState |= XBMCKMOD_LCTRL; -+ break; -+ case XBMCK_RCTRL: -+ WinEvents->m_keymodState |= XBMCKMOD_RCTRL; -+ break; -+ case XBMCK_LALT: -+ WinEvents->m_keymodState |= XBMCKMOD_LALT; -+ break; -+ case XBMCK_RALT: -+ WinEvents->m_keymodState |= XBMCKMOD_RCTRL; -+ break; -+ case XBMCK_LMETA: -+ WinEvents->m_keymodState |= XBMCKMOD_LMETA; -+ break; -+ case XBMCK_RMETA: -+ WinEvents->m_keymodState |= XBMCKMOD_RMETA; -+ break; -+ case XBMCK_MODE: -+ WinEvents->m_keymodState |= XBMCKMOD_MODE; -+ break; -+ default: -+ break; -+ } -+ event.key.keysym.mod = (XBMCMod)WinEvents->m_keymodState; -+ memcpy(&(WinEvents->m_lastKey), &event, sizeof(event)); -+ WinEvents->m_repeatKeyTimeout.Set(repeatDelay); -+ -+ bool ret = ProcessShortcuts(event); -+ if (ret) -+ return ret; -+ } -+ else if (event.type == XBMC_KEYUP) -+ { -+ switch(event.key.keysym.sym) -+ { -+ case XBMCK_LSHIFT: -+ WinEvents->m_keymodState &= ~XBMCKMOD_LSHIFT; -+ break; -+ case XBMCK_RSHIFT: -+ WinEvents->m_keymodState &= ~XBMCKMOD_RSHIFT; -+ break; -+ case XBMCK_LCTRL: -+ WinEvents->m_keymodState &= ~XBMCKMOD_LCTRL; -+ break; -+ case XBMCK_RCTRL: -+ WinEvents->m_keymodState &= ~XBMCKMOD_RCTRL; -+ break; -+ case XBMCK_LALT: -+ WinEvents->m_keymodState &= ~XBMCKMOD_LALT; -+ break; -+ case XBMCK_RALT: -+ WinEvents->m_keymodState &= ~XBMCKMOD_RCTRL; -+ break; -+ case XBMCK_LMETA: -+ WinEvents->m_keymodState &= ~XBMCKMOD_LMETA; -+ break; -+ case XBMCK_RMETA: -+ WinEvents->m_keymodState &= ~XBMCKMOD_RMETA; -+ break; -+ case XBMCK_MODE: -+ WinEvents->m_keymodState &= ~XBMCKMOD_MODE; -+ break; -+ default: -+ break; -+ } -+ event.key.keysym.mod = (XBMCMod)WinEvents->m_keymodState; -+ memset(&(WinEvents->m_lastKey), 0, sizeof(event)); -+ } -+ -+ return g_application.OnEvent(event); -+} -+ -+bool CWinEventsX11::ProcessShortcuts(XBMC_Event& event) -+{ -+ if (event.key.keysym.mod & XBMCKMOD_ALT) -+ { -+ switch(event.key.keysym.sym) -+ { -+ case XBMCK_TAB: // ALT+TAB to minimize/hide -+ g_application.Minimize(); -+ return true; -+ -+ default: -+ return false; -+ } -+ } -+ return false; -+} -+ -+bool CWinEventsX11::ProcessKeyRepeat() -+{ -+ if (WinEvents && (WinEvents->m_lastKey.type == XBMC_KEYDOWN)) -+ { -+ if (WinEvents->m_repeatKeyTimeout.IsTimePast()) -+ { -+ return ProcessKey(WinEvents->m_lastKey, 10); -+ } -+ } -+ return false; -+} -+ -+int CWinEventsX11::Utf8ToUnicode(const char *utf8, const int utf8Length, uint16_t *utf16, const int utf16MaxLength) -+{ -+ // p moves over the output buffer. max_ptr points to the next to the last slot of the buffer. -+ uint16_t *p = utf16; -+ uint16_t const *const maxPtr = utf16 + utf16MaxLength; -+ -+ // end_of_input points to the last byte of input as opposed to the next to the last byte. -+ char const *const endOfInput = utf8 + utf8Length - 1; -+ -+ while (utf8 <= endOfInput) -+ { -+ unsigned char const c = *utf8; -+ if (p >= maxPtr) -+ { -+ //No more output space. -+ return -1; -+ } -+ if (c < 0x80) -+ { -+ //One byte ASCII. -+ *p++ = c; -+ utf8 += 1; -+ } -+ else if (c < 0xC0) -+ { -+ // Follower byte without preceding leader bytes. -+ return -1; -+ } -+ // 11 bits -+ else if (c < 0xE0) -+ { -+ // Two byte sequence. We need one follower byte. -+ if (endOfInput - utf8 < 1 || (((utf8[1] ^ 0x80)) & 0xC0)) -+ { -+ return -1; -+ } -+ *p++ = (uint16_t)(((c & 0x1F) << 6) + (utf8[1] & 0x3F)); -+ utf8 += 2; -+ } -+ // 16 bis -+ else if (c < 0xF0) -+ { -+ // Three byte sequence. We need two follower byte. -+ if (endOfInput - utf8 < 2 || ((utf8[1] ^ 0x80) & 0xC0) || ((utf8[2] ^ 0x80) & 0xC0)) -+ { -+ return -1; -+ } -+ *p++ = (uint16_t)(((c & 0xF) << 12) + ((utf8[1] & 0x3F) << 6) + (utf8[2] & 0x3F)); -+ utf8 += 3; -+ } -+ // 21 bits -+ else if (c < 0xF8) -+ { -+ int plane; -+ // Four byte sequence. We need three follower bytes. -+ if (endOfInput - utf8 < 3 || ((utf8[1] ^ 0x80) & 0xC0) || -+ ((utf8[2] ^ 0x80) & 0xC0) || ((utf8[3] ^ 0x80) & 0xC0)) -+ { -+ return -1; -+ } -+ uint32_t unicode = ((c & 0x7) << 18) + ((utf8[1] & 0x3F) << 12) + -+ ((utf8[2] & 0x3F) << 6) + (utf8[3] & 0x3F); -+ utf8 += 4; -+ CLog::Log(LOGERROR, "CWinEventsX11::Utf8ToUnicode: 4 byte unicode not supported"); -+ } -+ // 26 bits -+ else if (c < 0xFC) -+ { -+ CLog::Log(LOGERROR, "CWinEventsX11::Utf8ToUnicode: 4 byte unicode not supported"); -+ utf8 += 5; -+ } -+ // 31 bit -+ else -+ { -+ CLog::Log(LOGERROR, "CWinEventsX11::Utf8ToUnicode: 4 byte unicode not supported"); -+ utf8 += 6; -+ } -+ } -+ return p - utf16; -+} -+ -+XBMCKey CWinEventsX11::LookupXbmcKeySym(KeySym keysym) -+{ -+ // try direct mapping first -+ std::map::iterator it; -+ it = WinEvents->m_symLookupTable.find(keysym); -+ if (it != WinEvents->m_symLookupTable.end()) -+ { -+ return (XBMCKey)(it->second); -+ } -+ -+ // try ascii mappings -+ if (keysym>>8 == 0x00) -+ return (XBMCKey)(keysym & 0xFF); -+ -+ return (XBMCKey)keysym; -+} -+#endif -diff --git a/xbmc/windowing/WinEventsX11.h b/xbmc/windowing/WinEventsX11.h -new file mode 100644 -index 0000000..e9b7553 ---- /dev/null -+++ b/xbmc/windowing/WinEventsX11.h -@@ -0,0 +1,57 @@ -+/* -+* Copyright (C) 2005-2012 Team XBMC -+* http://www.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, write to -+* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. -+* http://www.gnu.org/copyleft/gpl.html -+* -+*/ -+#pragma once -+ -+#include "WinEvents.h" -+#include -+#include "threads/SystemClock.h" -+#include -+ -+class CWinEventsX11 : public CWinEventsBase -+{ -+public: -+ CWinEventsX11(); -+ virtual ~CWinEventsX11(); -+ static bool Init(Display *dpy, Window win); -+ static void Quit(); -+ static bool HasStructureChanged(); -+ static bool MessagePump(); -+ -+protected: -+ static int Utf8ToUnicode(const char *utf8, const int utf8Length, uint16_t *utf16, const int utf16MaxLength); -+ static XBMCKey LookupXbmcKeySym(KeySym keysym); -+ static bool ProcessKey(XBMC_Event &event, int repeatDelay); -+ static bool ProcessKeyRepeat(); -+ static bool ProcessShortcuts(XBMC_Event& event); -+ static CWinEventsX11 *WinEvents; -+ Display *m_display; -+ Window m_window; -+ Atom m_wmDeleteMessage; -+ char *m_keybuf; -+ uint16_t *m_utf16buf; -+ XIM m_xim; -+ XIC m_xic; -+ XBMC_Event m_lastKey; -+ XbmcThreads::EndTime m_repeatKeyTimeout; -+ std::map m_symLookupTable; -+ int m_keymodState; -+ bool m_structureChanged; -+}; -diff --git a/xbmc/windowing/X11/WinSystemX11.cpp b/xbmc/windowing/X11/WinSystemX11.cpp -index a839709..76ef462 100644 ---- a/xbmc/windowing/X11/WinSystemX11.cpp -+++ b/xbmc/windowing/X11/WinSystemX11.cpp -@@ -22,7 +22,6 @@ - - #ifdef HAS_GLX - --#include - #include "WinSystemX11.h" - #include "settings/Settings.h" - #include "guilib/Texture.h" -@@ -31,27 +30,30 @@ - #include "XRandR.h" - #include - #include "threads/SingleLock.h" --#include - #include "cores/VideoRenderers/RenderManager.h" - #include "utils/TimeUtils.h" -+#include "settings/GUISettings.h" - - #if defined(HAS_XRANDR) - #include - #endif - -+#include "../WinEvents.h" -+#include "input/MouseStat.h" -+ - using namespace std; - - CWinSystemX11::CWinSystemX11() : CWinSystemBase() - { - m_eWindowSystem = WINDOW_SYSTEM_X11; - m_glContext = NULL; -- m_SDLSurface = NULL; - m_dpy = NULL; - m_glWindow = 0; -- m_wmWindow = 0; - m_bWasFullScreenBeforeMinimize = false; - m_minimized = false; -+ m_bIgnoreNextFocusMessage = false; - m_dpyLostTime = 0; -+ m_invisibleCursor = 0; - - XSetErrorHandler(XErrorHandler); - } -@@ -64,18 +66,6 @@ bool CWinSystemX11::InitWindowSystem() - { - if ((m_dpy = XOpenDisplay(NULL))) - { -- -- SDL_EnableUNICODE(1); -- // set repeat to 10ms to ensure repeat time < frame time -- // so that hold times can be reliably detected -- SDL_EnableKeyRepeat(SDL_DEFAULT_REPEAT_DELAY, 10); -- -- SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8); -- SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8); -- SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8); -- SDL_GL_SetAttribute(SDL_GL_ALPHA_SIZE, 8); -- SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); -- - return CWinSystemBase::InitWindowSystem(); - } - else -@@ -113,45 +103,37 @@ bool CWinSystemX11::DestroyWindowSystem() - - bool CWinSystemX11::CreateNewWindow(const CStdString& name, bool fullScreen, RESOLUTION_INFO& res, PHANDLE_EVENT_FUNC userFunction) - { -- RESOLUTION_INFO& desktop = g_settings.m_ResInfo[RES_DESKTOP]; -- -- if (fullScreen && -- (res.iWidth != desktop.iWidth || res.iHeight != desktop.iHeight || -- res.fRefreshRate != desktop.fRefreshRate || res.iScreen != desktop.iScreen)) -- { -- //on the first call to SDL_SetVideoMode, SDL stores the current displaymode -- //SDL restores the displaymode on SDL_QUIT(), if we change the displaymode -- //before the first call to SDL_SetVideoMode, SDL changes the displaymode back -- //to the wrong mode on exit -- -- CLog::Log(LOGINFO, "CWinSystemX11::CreateNewWindow initializing to desktop resolution first"); -- if (!SetFullScreen(true, desktop, false)) -- return false; -- } -- - if(!SetFullScreen(fullScreen, res, false)) - return false; - -- CBaseTexture* iconTexture = CTexture::LoadFromFile("special://xbmc/media/icon.png"); -- -- if (iconTexture) -- SDL_WM_SetIcon(SDL_CreateRGBSurfaceFrom(iconTexture->GetPixels(), iconTexture->GetWidth(), iconTexture->GetHeight(), 32, iconTexture->GetPitch(), 0xff0000, 0x00ff00, 0x0000ff, 0xff000000L), NULL); -- SDL_WM_SetCaption("XBMC Media Center", NULL); -- delete iconTexture; -- -- // register XRandR Events --#if defined(HAS_XRANDR) -- int iReturn; -- XRRQueryExtension(m_dpy, &m_RREventBase, &iReturn); -- XRRSelectInput(m_dpy, m_wmWindow, RRScreenChangeNotifyMask); --#endif -- - m_bWindowCreated = true; - return true; - } - - bool CWinSystemX11::DestroyWindow() - { -+ if (!m_glWindow) -+ return true; -+ -+ if (m_glContext) -+ glXMakeCurrent(m_dpy, None, NULL); -+ -+ if (m_invisibleCursor) -+ { -+ XUndefineCursor(m_dpy, m_glWindow); -+ XFreeCursor(m_dpy, m_invisibleCursor); -+ m_invisibleCursor = 0; -+ } -+ -+ CWinEvents::Quit(); -+ -+ XUnmapWindow(m_dpy, m_glWindow); -+ XSync(m_dpy,TRUE); -+ XUngrabKeyboard(m_dpy, CurrentTime); -+ XUngrabPointer(m_dpy, CurrentTime); -+ XDestroyWindow(m_dpy, m_glWindow); -+ m_glWindow = 0; -+ - return true; - } - -@@ -161,65 +143,105 @@ bool CWinSystemX11::ResizeWindow(int newWidth, int newHeight, int newLeft, int n - && m_nHeight == newHeight) - return true; - -+ if (!SetWindow(newWidth, newHeight, false)) -+ { -+ return false; -+ } -+ -+ RefreshGlxContext(); - m_nWidth = newWidth; - m_nHeight = newHeight; -+ m_bFullScreen = false; - -- int options = SDL_OPENGL; -- if (m_bFullScreen) -- options |= SDL_FULLSCREEN; -- else -- options |= SDL_RESIZABLE; -+ return false; -+} -+ -+void CWinSystemX11::RefreshWindow() -+{ -+ g_xrandr.Query(true); -+ XOutput out = g_xrandr.GetCurrentOutput(); -+ XMode mode = g_xrandr.GetCurrentMode(out.name); - -- if ((m_SDLSurface = SDL_SetVideoMode(m_nWidth, m_nHeight, 0, options))) -+ // only overwrite desktop resolution, if we are not in fullscreen mode -+ if (!g_graphicsContext.IsFullScreenVideo()) - { -- RefreshGlxContext(); -- return true; -+ CLog::Log(LOGDEBUG, "CWinSystemX11::RefreshWindow - store desktop resolution, width: %d, height: %d, hz: %2.2f", mode.w, mode.h, mode.hz); -+ UpdateDesktopResolution(g_settings.m_ResInfo[RES_DESKTOP], 0, mode.w, mode.h, mode.hz); -+ g_settings.m_ResInfo[RES_DESKTOP].strId = mode.id; -+ g_settings.m_ResInfo[RES_DESKTOP].strOutput = out.name; - } - -- return false; -+ RESOLUTION_INFO res; -+ unsigned int i; -+ bool found(false); -+ for (i = RES_DESKTOP; i < g_settings.m_ResInfo.size(); ++i) -+ { -+ if (g_settings.m_ResInfo[i].strId == mode.id) -+ { -+ found = true; -+ break; -+ } -+ } -+ -+ if (!found) -+ { -+ CLog::Log(LOGERROR, "CWinSystemX11::RefreshWindow - could not find resolution"); -+ return; -+ } -+ -+ if (g_graphicsContext.IsFullScreenRoot()) -+ g_graphicsContext.SetVideoResolution((RESOLUTION)i, true); -+ else -+ g_graphicsContext.SetVideoResolution(RES_WINDOW, true); - } - - bool CWinSystemX11::SetFullScreen(bool fullScreen, RESOLUTION_INFO& res, bool blankOtherDisplays) - { -- m_nWidth = res.iWidth; -- m_nHeight = res.iHeight; -- m_bFullScreen = fullScreen; - - #if defined(HAS_XRANDR) - XOutput out; - XMode mode; -- out.name = res.strOutput; -- mode.w = res.iWidth; -- mode.h = res.iHeight; -- mode.hz = res.fRefreshRate; -- mode.id = res.strId; -+ -+ if (fullScreen) -+ { -+ out.name = res.strOutput; -+ mode.w = res.iWidth; -+ mode.h = res.iHeight; -+ mode.hz = res.fRefreshRate; -+ mode.id = res.strId; -+ } -+ else -+ { -+ out.name = g_settings.m_ResInfo[RES_DESKTOP].strOutput; -+ mode.w = g_settings.m_ResInfo[RES_DESKTOP].iWidth; -+ mode.h = g_settings.m_ResInfo[RES_DESKTOP].iHeight; -+ mode.hz = g_settings.m_ResInfo[RES_DESKTOP].fRefreshRate; -+ mode.id = g_settings.m_ResInfo[RES_DESKTOP].strId; -+ } - -- if(m_bFullScreen) -+ XOutput currout = g_xrandr.GetCurrentOutput(); -+ XMode currmode = g_xrandr.GetCurrentMode(currout.name); -+ -+ // only call xrandr if mode changes -+ if (currout.name != out.name || currmode.w != mode.w || currmode.h != mode.h || -+ currmode.hz != mode.hz || currmode.id != mode.id) - { -+ CLog::Log(LOGNOTICE, "CWinSystemX11::SetFullScreen - calling xrandr"); - OnLostDevice(); - g_xrandr.SetMode(out, mode); - } -- else -- g_xrandr.RestoreState(); - #endif - -- int options = SDL_OPENGL; -- if (m_bFullScreen) -- options |= SDL_FULLSCREEN; -- else -- options |= SDL_RESIZABLE; -- -- if ((m_SDLSurface = SDL_SetVideoMode(m_nWidth, m_nHeight, 0, options))) -- { -- if ((m_SDLSurface->flags & SDL_OPENGL) != SDL_OPENGL) -- CLog::Log(LOGERROR, "CWinSystemX11::SetFullScreen SDL_OPENGL not set, SDL_GetError:%s", SDL_GetError()); -+ if (!SetWindow(res.iWidth, res.iHeight, fullScreen)) -+ return false; - -- RefreshGlxContext(); -+ RefreshGlxContext(); - -- return true; -- } -+ m_nWidth = res.iWidth; -+ m_nHeight = res.iHeight; -+ m_bFullScreen = fullScreen; - -- return false; -+ return true; - } - - void CWinSystemX11::UpdateResolutions() -@@ -321,17 +343,10 @@ bool CWinSystemX11::IsSuitableVisual(XVisualInfo *vInfo) - bool CWinSystemX11::RefreshGlxContext() - { - bool retVal = false; -- SDL_SysWMinfo info; -- SDL_VERSION(&info.version); -- if (SDL_GetWMInfo(&info) <= 0) -- { -- CLog::Log(LOGERROR, "Failed to get window manager info from SDL"); -- return false; -- } - -- if(m_glWindow == info.info.x11.window && m_glContext) -+ if (m_glContext) - { -- CLog::Log(LOGERROR, "GLX: Same window as before, refreshing context"); -+ CLog::Log(LOGDEBUG, "CWinSystemX11::RefreshGlxContext: refreshing context"); - glXMakeCurrent(m_dpy, None, NULL); - glXMakeCurrent(m_dpy, m_glWindow, m_glContext); - return true; -@@ -343,8 +358,6 @@ bool CWinSystemX11::RefreshGlxContext() - int availableVisuals = 0; - vMask.screen = DefaultScreen(m_dpy); - XWindowAttributes winAttr; -- m_glWindow = info.info.x11.window; -- m_wmWindow = info.info.x11.wmwindow; - - /* Assume a depth of 24 in case the below calls to XGetWindowAttributes() - or XGetVisualInfo() fail. That shouldn't happen unless something is -@@ -415,7 +428,10 @@ bool CWinSystemX11::RefreshGlxContext() - - void CWinSystemX11::ShowOSMouse(bool show) - { -- SDL_ShowCursor(show ? 1 : 0); -+ if (show) -+ XUndefineCursor(m_dpy,m_glWindow); -+ else if (m_invisibleCursor) -+ XDefineCursor(m_dpy,m_glWindow, m_invisibleCursor); - } - - void CWinSystemX11::ResetOSScreensaver() -@@ -429,8 +445,6 @@ void CWinSystemX11::ResetOSScreensaver() - { - m_screensaverReset.StartZero(); - XResetScreenSaver(m_dpy); -- //need to flush the output buffer, since we don't check for events on m_dpy -- XFlush(m_dpy); - } - } - else -@@ -446,13 +460,27 @@ void CWinSystemX11::NotifyAppActiveChange(bool bActivated) - - m_minimized = !bActivated; - } -+ -+void CWinSystemX11::NotifyAppFocusChange(bool bGaining) -+{ -+ if (bGaining && m_bWasFullScreenBeforeMinimize && !m_bIgnoreNextFocusMessage && -+ !g_graphicsContext.IsFullScreenRoot()) -+ g_graphicsContext.ToggleFullScreenRoot(); -+ if (!bGaining) -+ m_bIgnoreNextFocusMessage = false; -+} -+ - bool CWinSystemX11::Minimize() - { - m_bWasFullScreenBeforeMinimize = g_graphicsContext.IsFullScreenRoot(); - if (m_bWasFullScreenBeforeMinimize) -+ { -+ m_bIgnoreNextFocusMessage = true; - g_graphicsContext.ToggleFullScreenRoot(); -+ } -+ -+ XIconifyWindow(m_dpy, m_glWindow, DefaultScreen(m_dpy)); - -- SDL_WM_IconifyWindow(); - m_minimized = true; - return true; - } -@@ -462,13 +490,13 @@ bool CWinSystemX11::Restore() - } - bool CWinSystemX11::Hide() - { -- XUnmapWindow(m_dpy, m_wmWindow); -+ XUnmapWindow(m_dpy, m_glWindow); - XSync(m_dpy, False); - return true; - } - bool CWinSystemX11::Show(bool raise) - { -- XMapWindow(m_dpy, m_wmWindow); -+ XMapWindow(m_dpy, m_glWindow); - XSync(m_dpy, False); - m_minimized = false; - return true; -@@ -500,6 +528,7 @@ void CWinSystemX11::CheckDisplayEvents() - if (bGotEvent || bTimeout) - { - CLog::Log(LOGDEBUG, "%s - notify display reset event", __FUNCTION__); -+ RefreshWindow(); - - CSingleLock lock(m_resourceSection); - -@@ -558,4 +587,151 @@ bool CWinSystemX11::EnableFrameLimiter() - return m_minimized; - } - -+bool CWinSystemX11::SetWindow(int width, int height, bool fullscreen) -+{ -+ bool changeWindow = false; -+ bool changeSize = false; -+ bool mouseActive = false; -+ float mouseX, mouseY; -+ -+ if (m_glWindow && (m_bFullScreen != fullscreen)) -+ { -+ mouseActive = g_Mouse.IsActive(); -+ if (mouseActive) -+ { -+ Window root_return, child_return; -+ int root_x_return, root_y_return; -+ int win_x_return, win_y_return; -+ unsigned int mask_return; -+ bool isInWin = XQueryPointer(m_dpy, m_glWindow, &root_return, &child_return, -+ &root_x_return, &root_y_return, -+ &win_x_return, &win_y_return, -+ &mask_return); -+ if (isInWin) -+ { -+ mouseX = (float)win_x_return/m_nWidth; -+ mouseY = (float)win_y_return/m_nHeight; -+ g_Mouse.SetActive(false); -+ } -+ else -+ mouseActive = false; -+ } -+ DestroyWindow(); -+ } -+ -+ // create main window -+ if (!m_glWindow) -+ { -+ GLint att[] = -+ { -+ GLX_RGBA, -+ GLX_RED_SIZE, 8, -+ GLX_GREEN_SIZE, 8, -+ GLX_BLUE_SIZE, 8, -+ GLX_ALPHA_SIZE, 8, -+ GLX_DEPTH_SIZE, 24, -+ GLX_DOUBLEBUFFER, -+ None -+ }; -+ Colormap cmap; -+ XSetWindowAttributes swa; -+ XVisualInfo *vi; -+ -+ vi = glXChooseVisual(m_dpy, DefaultScreen(m_dpy), att); -+ cmap = XCreateColormap(m_dpy, RootWindow(m_dpy, vi->screen), vi->visual, AllocNone); -+ -+ int def_vis = (vi->visual == DefaultVisual(m_dpy, vi->screen)); -+ swa.override_redirect = fullscreen ? True : False; -+ swa.border_pixel = fullscreen ? 0 : 5; -+ swa.background_pixel = def_vis ? BlackPixel(m_dpy, vi->screen) : 0; -+ swa.colormap = cmap; -+ swa.background_pixel = def_vis ? BlackPixel(m_dpy, vi->screen) : 0; -+ swa.event_mask = FocusChangeMask | KeyPressMask | KeyReleaseMask | -+ ButtonPressMask | ButtonReleaseMask | PointerMotionMask | -+ PropertyChangeMask | StructureNotifyMask | KeymapStateMask | -+ EnterWindowMask | LeaveWindowMask | ExposureMask; -+ unsigned long mask = CWBackPixel | CWBorderPixel | CWColormap | CWOverrideRedirect | CWEventMask; -+ -+ m_glWindow = XCreateWindow(m_dpy, RootWindow(m_dpy, vi->screen), -+ 0, 0, width, height, 0, vi->depth, -+ InputOutput, vi->visual, -+ mask, &swa); -+ -+ // define invisible cursor -+ Pixmap bitmapNoData; -+ XColor black; -+ static char noData[] = { 0,0,0,0,0,0,0,0 }; -+ black.red = black.green = black.blue = 0; -+ -+ bitmapNoData = XCreateBitmapFromData(m_dpy, m_glWindow, noData, 8, 8); -+ m_invisibleCursor = XCreatePixmapCursor(m_dpy, bitmapNoData, bitmapNoData, -+ &black, &black, 0, 0); -+ XFreePixmap(m_dpy, bitmapNoData); -+ XDefineCursor(m_dpy,m_glWindow, m_invisibleCursor); -+ -+ //init X11 events -+ CWinEvents::Init(m_dpy, m_glWindow); -+ -+ changeWindow = true; -+ changeSize = true; -+ } -+ -+ if (!CWinEvents::HasStructureChanged() && ((width != m_nWidth) || (height != m_nHeight))) -+ { -+ changeSize = true; -+ } -+ -+ if (changeSize || changeWindow) -+ { -+ XResizeWindow(m_dpy, m_glWindow, width, height); -+ } -+ -+ if (changeWindow) -+ { -+ if (!fullscreen) -+ { -+ XWMHints wm_hints; -+ XClassHint class_hints; -+ XTextProperty windowName, iconName; -+ std::string titleString = "XBMC Media Center"; -+ char *title = (char*)titleString.c_str(); -+ -+ XStringListToTextProperty(&title, 1, &windowName); -+ XStringListToTextProperty(&title, 1, &iconName); -+ wm_hints.initial_state = NormalState; -+ wm_hints.input = True; -+ wm_hints.icon_pixmap = None; -+ wm_hints.flags = StateHint | IconPixmapHint | InputHint; -+ -+ XSetWMProperties(m_dpy, m_glWindow, &windowName, &iconName, -+ NULL, 0, NULL, &wm_hints, -+ NULL); -+ -+ // register interest in the delete window message -+ Atom wmDeleteMessage = XInternAtom(m_dpy, "WM_DELETE_WINDOW", False); -+ XSetWMProtocols(m_dpy, m_glWindow, &wmDeleteMessage, 1); -+ } -+ XMapRaised(m_dpy, m_glWindow); -+ XSync(m_dpy,TRUE); -+ -+ if (changeWindow && mouseActive) -+ { -+ XWarpPointer(m_dpy, None, m_glWindow, 0, 0, 0, 0, mouseX*width, mouseY*height); -+ } -+ -+ if (fullscreen) -+ { -+ int result = -1; -+ while (result != GrabSuccess) -+ { -+ result = XGrabPointer(m_dpy, m_glWindow, True, ButtonPressMask, GrabModeAsync, GrabModeAsync, m_glWindow, None, CurrentTime); -+ XbmcThreads::ThreadSleep(100); -+ } -+ XGrabKeyboard(m_dpy, m_glWindow, True, GrabModeAsync, GrabModeAsync, CurrentTime); -+ -+ } -+ } -+ return true; -+} -+ - #endif -diff --git a/xbmc/windowing/X11/WinSystemX11.h b/xbmc/windowing/X11/WinSystemX11.h -index 2dd8a9f..9616d17 100644 ---- a/xbmc/windowing/X11/WinSystemX11.h -+++ b/xbmc/windowing/X11/WinSystemX11.h -@@ -52,6 +52,7 @@ class CWinSystemX11 : public CWinSystemBase - virtual bool EnableFrameLimiter(); - - virtual void NotifyAppActiveChange(bool bActivated); -+ virtual void NotifyAppFocusChange(bool bGaining); - - virtual bool Minimize(); - virtual bool Restore() ; -@@ -64,19 +65,21 @@ class CWinSystemX11 : public CWinSystemBase - Display* GetDisplay() { return m_dpy; } - GLXWindow GetWindow() { return m_glWindow; } - GLXContext GetGlxContext() { return m_glContext; } -+ void RefreshWindow(); - - protected: - bool RefreshGlxContext(); - void CheckDisplayEvents(); - void OnLostDevice(); -+ bool SetWindow(int width, int height, bool fullscreen); - -- SDL_Surface* m_SDLSurface; -+ Window m_glWindow; - GLXContext m_glContext; -- GLXWindow m_glWindow; -- Window m_wmWindow; - Display* m_dpy; -+ Cursor m_invisibleCursor; - bool m_bWasFullScreenBeforeMinimize; - bool m_minimized; -+ bool m_bIgnoreNextFocusMessage; - int m_RREventBase; - CCriticalSection m_resourceSection; - std::vector m_resources; --- -1.7.10 - - -From 5a5787c6f51a9d92f69e95dea42175f3837777cb Mon Sep 17 00:00:00 2001 -From: FernetMenta -Date: Thu, 5 Jul 2012 15:24:22 +0200 -Subject: [PATCH 36/88] X11: Add xbmc icon - ---- - xbmc/windowing/X11/WinSystemX11.cpp | 126 ++++++++++++++++++++++++++++++++++- - xbmc/windowing/X11/WinSystemX11.h | 2 + - 2 files changed, 127 insertions(+), 1 deletion(-) - -diff --git a/xbmc/windowing/X11/WinSystemX11.cpp b/xbmc/windowing/X11/WinSystemX11.cpp -index 76ef462..c854598 100644 ---- a/xbmc/windowing/X11/WinSystemX11.cpp -+++ b/xbmc/windowing/X11/WinSystemX11.cpp -@@ -134,6 +134,9 @@ bool CWinSystemX11::DestroyWindow() - XDestroyWindow(m_dpy, m_glWindow); - m_glWindow = 0; - -+ if (m_icon) -+ XFreePixmap(m_dpy, m_icon); -+ - return true; - } - -@@ -688,8 +691,10 @@ bool CWinSystemX11::SetWindow(int width, int height, bool fullscreen) - - if (changeWindow) - { -+ m_icon = None; - if (!fullscreen) - { -+ CreateIconPixmap(); - XWMHints wm_hints; - XClassHint class_hints; - XTextProperty windowName, iconName; -@@ -700,7 +705,7 @@ bool CWinSystemX11::SetWindow(int width, int height, bool fullscreen) - XStringListToTextProperty(&title, 1, &iconName); - wm_hints.initial_state = NormalState; - wm_hints.input = True; -- wm_hints.icon_pixmap = None; -+ wm_hints.icon_pixmap = m_icon; - wm_hints.flags = StateHint | IconPixmapHint | InputHint; - - XSetWMProperties(m_dpy, m_glWindow, &windowName, &iconName, -@@ -734,4 +739,123 @@ bool CWinSystemX11::SetWindow(int width, int height, bool fullscreen) - return true; - } - -+bool CWinSystemX11::CreateIconPixmap() -+{ -+ int depth; -+ XImage *img = NULL; -+ Visual *vis; -+ XWindowAttributes wndattribs; -+ XVisualInfo visInfo; -+ double rRatio; -+ double gRatio; -+ double bRatio; -+ int outIndex = 0; -+ int i,j; -+ int numBufBytes; -+ unsigned char *buf; -+ uint32_t *newBuf = 0; -+ size_t numNewBufBytes; -+ -+ // Get visual Info -+ XGetWindowAttributes(m_dpy, m_glWindow, &wndattribs); -+ visInfo.visualid = wndattribs.visual->visualid; -+ int nvisuals = 0; -+ XVisualInfo* visuals = XGetVisualInfo(m_dpy, VisualIDMask, &visInfo, &nvisuals); -+ if (nvisuals != 1) -+ { -+ CLog::Log(LOGERROR, "CWinSystemX11::CreateIconPixmap - could not find visual"); -+ return false; -+ } -+ visInfo = visuals[0]; -+ XFree(visuals); -+ -+ depth = visInfo.depth; -+ vis = visInfo.visual; -+ -+ if (depth < 15) -+ { -+ CLog::Log(LOGERROR, "CWinSystemX11::CreateIconPixmap - no suitable depth"); -+ return false; -+ } -+ -+ rRatio = vis->red_mask / 255.0; -+ gRatio = vis->green_mask / 255.0; -+ bRatio = vis->blue_mask / 255.0; -+ -+ CTexture iconTexture; -+ iconTexture.LoadFromFile("special://xbmc/media/icon.png"); -+ buf = iconTexture.GetPixels(); -+ -+ numBufBytes = iconTexture.GetWidth() * iconTexture.GetHeight() * 4; -+ -+ if (depth>=24) -+ numNewBufBytes = (4 * (iconTexture.GetWidth() * iconTexture.GetHeight())); -+ else -+ numNewBufBytes = (2 * (iconTexture.GetWidth() * iconTexture.GetHeight())); -+ -+ newBuf = (uint32_t*)malloc(numNewBufBytes); -+ if (!newBuf) -+ { -+ CLog::Log(LOGERROR, "CWinSystemX11::CreateIconPixmap - malloc failed"); -+ return false; -+ } -+ -+ for (i=0; ired_mask; -+ g &= vis->green_mask; -+ b &= vis->blue_mask; -+ newBuf[outIndex] = r | g | b; -+ ++outIndex; -+ } -+ } -+ img = XCreateImage(m_dpy, vis, depth,ZPixmap, 0, (char *)newBuf, -+ iconTexture.GetWidth(), iconTexture.GetHeight(), -+ (depth>=24)?32:16, 0); -+ if (!img) -+ { -+ CLog::Log(LOGERROR, "CWinSystemX11::CreateIconPixmap - could not create image"); -+ free(newBuf); -+ return false; -+ } -+ if (!XInitImage(img)) -+ { -+ CLog::Log(LOGERROR, "CWinSystemX11::CreateIconPixmap - init image failed"); -+ XDestroyImage(img); -+ return false; -+ } -+ -+ // set byte order -+ union -+ { -+ char c[sizeof(short)]; -+ short s; -+ } order; -+ order.s = 1; -+ if ((1 == order.c[0])) -+ { -+ img->byte_order = LSBFirst; -+ } -+ else -+ { -+ img->byte_order = MSBFirst; -+ } -+ -+ // create icon pixmap from image -+ m_icon = XCreatePixmap(m_dpy, m_glWindow, img->width, img->height, depth); -+ GC gc = XCreateGC(m_dpy, m_glWindow, 0, NULL); -+ XPutImage(m_dpy, m_icon, gc, img, 0, 0, 0, 0, img->width, img->height); -+ XFreeGC(m_dpy, gc); -+ XDestroyImage(img); // this also frees newBuf -+ -+ return true; -+} -+ - #endif -diff --git a/xbmc/windowing/X11/WinSystemX11.h b/xbmc/windowing/X11/WinSystemX11.h -index 9616d17..debf714 100644 ---- a/xbmc/windowing/X11/WinSystemX11.h -+++ b/xbmc/windowing/X11/WinSystemX11.h -@@ -77,6 +77,7 @@ class CWinSystemX11 : public CWinSystemBase - GLXContext m_glContext; - Display* m_dpy; - Cursor m_invisibleCursor; -+ Pixmap m_icon; - bool m_bWasFullScreenBeforeMinimize; - bool m_minimized; - bool m_bIgnoreNextFocusMessage; -@@ -88,6 +89,7 @@ class CWinSystemX11 : public CWinSystemBase - private: - bool IsSuitableVisual(XVisualInfo *vInfo); - static int XErrorHandler(Display* dpy, XErrorEvent* error); -+ bool CreateIconPixmap(); - - CStopWatch m_screensaverReset; - }; --- -1.7.10 - - -From e6ae1b597d479cb9d9ae2dfc8cf43cceac4a82f7 Mon Sep 17 00:00:00 2001 -From: xbmc -Date: Sun, 20 May 2012 14:11:26 +0200 -Subject: [PATCH 37/88] X11: add SDL joystick until we have a better solution - ---- - xbmc/windowing/WinEventsX11.cpp | 26 ++++++++++++++++++++++++++ - 1 file changed, 26 insertions(+) - -diff --git a/xbmc/windowing/WinEventsX11.cpp b/xbmc/windowing/WinEventsX11.cpp -index 24477ae..2ec86a8 100644 ---- a/xbmc/windowing/WinEventsX11.cpp -+++ b/xbmc/windowing/WinEventsX11.cpp -@@ -35,6 +35,10 @@ - #include "guilib/GUIWindowManager.h" - #include "input/MouseStat.h" - -+#ifdef HAS_SDL_JOYSTICK -+#include "input/SDLJoystick.h" -+#endif -+ - CWinEventsX11* CWinEventsX11::WinEvents = 0; - - static uint32_t SymMappingsX11[][2] = -@@ -547,6 +551,28 @@ bool CWinEventsX11::MessagePump() - - ret |= ProcessKeyRepeat(); - -+#ifdef HAS_SDL_JOYSTICK -+ SDL_Event event; -+ while (SDL_PollEvent(&event)) -+ { -+ switch(event.type) -+ { -+ case SDL_JOYBUTTONUP: -+ case SDL_JOYBUTTONDOWN: -+ case SDL_JOYAXISMOTION: -+ case SDL_JOYBALLMOTION: -+ case SDL_JOYHATMOTION: -+ g_Joystick.Update(event); -+ ret = true; -+ break; -+ -+ default: -+ break; -+ } -+ memset(&event, 0, sizeof(SDL_Event)); -+ } -+#endif -+ - return ret; - } - --- -1.7.10 - - -From 22a59cd9df66e37394ac61b3d03d3ab6ac2f824f Mon Sep 17 00:00:00 2001 -From: Joakim Plate -Date: Thu, 5 Jul 2012 12:35:55 +0200 -Subject: [PATCH 38/88] X11: factor out code handling device reset - notification - ---- - xbmc/windowing/X11/WinSystemX11.cpp | 22 ++++++++++++++-------- - xbmc/windowing/X11/WinSystemX11.h | 1 + - 2 files changed, 15 insertions(+), 8 deletions(-) - -diff --git a/xbmc/windowing/X11/WinSystemX11.cpp b/xbmc/windowing/X11/WinSystemX11.cpp -index c854598..70557d0 100644 ---- a/xbmc/windowing/X11/WinSystemX11.cpp -+++ b/xbmc/windowing/X11/WinSystemX11.cpp -@@ -530,14 +530,7 @@ void CWinSystemX11::CheckDisplayEvents() - - if (bGotEvent || bTimeout) - { -- CLog::Log(LOGDEBUG, "%s - notify display reset event", __FUNCTION__); -- RefreshWindow(); -- -- CSingleLock lock(m_resourceSection); -- -- // tell any shared resources -- for (vector::iterator i = m_resources.begin(); i != m_resources.end(); i++) -- (*i)->OnResetDevice(); -+ NotifyXRREvent(); - - // reset fail safe timer - m_dpyLostTime = 0; -@@ -545,6 +538,19 @@ void CWinSystemX11::CheckDisplayEvents() - #endif - } - -+void CWinSystemX11::NotifyXRREvent() -+{ -+ CLog::Log(LOGDEBUG, "%s - notify display reset event", __FUNCTION__); -+ RefreshWindow(); -+ -+ CSingleLock lock(m_resourceSection); -+ -+ // tell any shared resources -+ for (vector::iterator i = m_resources.begin(); i != m_resources.end(); i++) -+ (*i)->OnResetDevice(); -+ -+} -+ - void CWinSystemX11::OnLostDevice() - { - CLog::Log(LOGDEBUG, "%s - notify display change event", __FUNCTION__); -diff --git a/xbmc/windowing/X11/WinSystemX11.h b/xbmc/windowing/X11/WinSystemX11.h -index debf714..8c28e3f 100644 ---- a/xbmc/windowing/X11/WinSystemX11.h -+++ b/xbmc/windowing/X11/WinSystemX11.h -@@ -66,6 +66,7 @@ class CWinSystemX11 : public CWinSystemBase - GLXWindow GetWindow() { return m_glWindow; } - GLXContext GetGlxContext() { return m_glContext; } - void RefreshWindow(); -+ void NotifyXRREvent(); - - protected: - bool RefreshGlxContext(); --- -1.7.10 - - -From 6c8f71e86c88314ee94673ad58407a8122995049 Mon Sep 17 00:00:00 2001 -From: FernetMenta -Date: Thu, 5 Jul 2012 15:02:00 +0200 -Subject: [PATCH 39/88] X11: move xrandr events to WinEventsX11 - ---- - xbmc/windowing/WinEventsX11.cpp | 42 +++++++++++++++++++++++++++++++++++ - xbmc/windowing/WinEventsX11.h | 5 +++++ - xbmc/windowing/X11/WinSystemX11.cpp | 6 ++++- - 3 files changed, 52 insertions(+), 1 deletion(-) - -diff --git a/xbmc/windowing/WinEventsX11.cpp b/xbmc/windowing/WinEventsX11.cpp -index 2ec86a8..5946a33 100644 ---- a/xbmc/windowing/WinEventsX11.cpp -+++ b/xbmc/windowing/WinEventsX11.cpp -@@ -35,6 +35,10 @@ - #include "guilib/GUIWindowManager.h" - #include "input/MouseStat.h" - -+#if defined(HAS_XRANDR) -+#include -+#endif -+ - #ifdef HAS_SDL_JOYSTICK - #include "input/SDLJoystick.h" - #endif -@@ -203,6 +207,7 @@ bool CWinEventsX11::Init(Display *dpy, Window win) - WinEvents->m_keymodState = 0; - WinEvents->m_wmDeleteMessage = XInternAtom(dpy, "WM_DELETE_WINDOW", False); - WinEvents->m_structureChanged = false; -+ WinEvents->m_xrrEventPending = false; - memset(&(WinEvents->m_lastKey), 0, sizeof(XBMC_Event)); - - // open input method -@@ -266,6 +271,13 @@ bool CWinEventsX11::Init(Display *dpy, Window win) - WinEvents->m_symLookupTable[SymMappingsX11[i][0]] = SymMappingsX11[i][1]; - } - -+ // register for xrandr events -+#if defined(HAS_XRANDR) -+ int iReturn; -+ XRRQueryExtension(WinEvents->m_display, &WinEvents->m_RREventBase, &iReturn); -+ XRRSelectInput(WinEvents->m_display, WinEvents->m_window, RRScreenChangeNotifyMask); -+#endif -+ - return true; - } - -@@ -288,6 +300,15 @@ bool CWinEventsX11::HasStructureChanged() - return ret; - } - -+void CWinEventsX11::SetXRRFailSafeTimer(int millis) -+{ -+ if (!WinEvents) -+ return; -+ -+ WinEvents->m_xrrFailSafeTimer.Set(millis); -+ WinEvents->m_xrrEventPending = true; -+} -+ - bool CWinEventsX11::MessagePump() - { - if (!WinEvents) -@@ -547,10 +568,31 @@ bool CWinEventsX11::MessagePump() - break; - } - }// switch event.type -+ -+#if defined(HAS_XRANDR) -+ if (WinEvents && (xevent.type == WinEvents->m_RREventBase + RRScreenChangeNotify)) -+ { -+ XRRUpdateConfiguration(&xevent); -+ if (xevent.xgeneric.serial != serial) -+ g_Windowing.NotifyXRREvent(); -+ WinEvents->m_xrrEventPending = false; -+ serial = xevent.xgeneric.serial; -+ } -+#endif -+ - }// while - - ret |= ProcessKeyRepeat(); - -+#if defined(HAS_XRANDR) -+ if (WinEvents && WinEvents->m_xrrEventPending && WinEvents->m_xrrFailSafeTimer.IsTimePast()) -+ { -+ CLog::Log(LOGERROR,"CWinEventsX11::MessagePump - missed XRR Events"); -+ g_Windowing.NotifyXRREvent(); -+ WinEvents->m_xrrEventPending = false; -+ } -+#endif -+ - #ifdef HAS_SDL_JOYSTICK - SDL_Event event; - while (SDL_PollEvent(&event)) -diff --git a/xbmc/windowing/WinEventsX11.h b/xbmc/windowing/WinEventsX11.h -index e9b7553..6100933 100644 ---- a/xbmc/windowing/WinEventsX11.h -+++ b/xbmc/windowing/WinEventsX11.h -@@ -33,6 +33,8 @@ class CWinEventsX11 : public CWinEventsBase - static bool Init(Display *dpy, Window win); - static void Quit(); - static bool HasStructureChanged(); -+ static void PendingResize(int width, int height); -+ static void SetXRRFailSafeTimer(int millis); - static bool MessagePump(); - - protected: -@@ -54,4 +56,7 @@ class CWinEventsX11 : public CWinEventsBase - std::map m_symLookupTable; - int m_keymodState; - bool m_structureChanged; -+ int m_RREventBase; -+ XbmcThreads::EndTime m_xrrFailSafeTimer; -+ bool m_xrrEventPending; - }; -diff --git a/xbmc/windowing/X11/WinSystemX11.cpp b/xbmc/windowing/X11/WinSystemX11.cpp -index 70557d0..1cce843 100644 ---- a/xbmc/windowing/X11/WinSystemX11.cpp -+++ b/xbmc/windowing/X11/WinSystemX11.cpp -@@ -507,7 +507,7 @@ bool CWinSystemX11::Show(bool raise) - - void CWinSystemX11::CheckDisplayEvents() - { --#if defined(HAS_XRANDR) -+#if defined(HAS_XRANDR) && defined(HAS_SDL_VIDEO_X11) - bool bGotEvent(false); - bool bTimeout(false); - XEvent Event; -@@ -563,8 +563,12 @@ void CWinSystemX11::OnLostDevice() - (*i)->OnLostDevice(); - } - -+#if defined(HAS_SDL_VIDEO_X11) - // fail safe timer - m_dpyLostTime = CurrentHostCounter(); -+#else -+ CWinEvents::SetXRRFailSafeTimer(3000); -+#endif - } - - void CWinSystemX11::Register(IDispResource *resource) --- -1.7.10 - - -From 9d24be16a3f9cc78ca26645ac2c7808e6e6b1e3e Mon Sep 17 00:00:00 2001 -From: FernetMenta -Date: Thu, 12 Apr 2012 15:43:56 +0200 -Subject: [PATCH 40/88] xrandr: remove method RestoreState - ---- - xbmc/windowing/X11/WinSystemX11.cpp | 13 +++++++++++-- - xbmc/windowing/X11/XRandR.cpp | 19 ------------------- - xbmc/windowing/X11/XRandR.h | 1 - - 3 files changed, 11 insertions(+), 22 deletions(-) - -diff --git a/xbmc/windowing/X11/WinSystemX11.cpp b/xbmc/windowing/X11/WinSystemX11.cpp -index 1cce843..e13ffa4 100644 ---- a/xbmc/windowing/X11/WinSystemX11.cpp -+++ b/xbmc/windowing/X11/WinSystemX11.cpp -@@ -77,9 +77,18 @@ bool CWinSystemX11::InitWindowSystem() - bool CWinSystemX11::DestroyWindowSystem() - { - #if defined(HAS_XRANDR) -- //restore videomode on exit -+ //restore desktop resolution on exit - if (m_bFullScreen) -- g_xrandr.RestoreState(); -+ { -+ XOutput out; -+ XMode mode; -+ out.name = g_settings.m_ResInfo[RES_DESKTOP].strOutput; -+ mode.w = g_settings.m_ResInfo[RES_DESKTOP].iWidth; -+ mode.h = g_settings.m_ResInfo[RES_DESKTOP].iHeight; -+ mode.hz = g_settings.m_ResInfo[RES_DESKTOP].fRefreshRate; -+ mode.id = g_settings.m_ResInfo[RES_DESKTOP].strId; -+ g_xrandr.SetMode(out, mode); -+ } - #endif - - if (m_dpy) -diff --git a/xbmc/windowing/X11/XRandR.cpp b/xbmc/windowing/X11/XRandR.cpp -index d8e9161..59755a6 100644 ---- a/xbmc/windowing/X11/XRandR.cpp -+++ b/xbmc/windowing/X11/XRandR.cpp -@@ -139,25 +139,6 @@ void CXRandR::SaveState() - Query(true); - } - --void CXRandR::RestoreState() --{ -- vector::iterator outiter; -- for (outiter=m_current.begin() ; outiter!=m_current.end() ; outiter++) -- { -- vector modes = (*outiter).modes; -- vector::iterator modeiter; -- for (modeiter=modes.begin() ; modeiter!=modes.end() ; modeiter++) -- { -- XMode mode = *modeiter; -- if (mode.isCurrent) -- { -- SetMode(*outiter, mode); -- return; -- } -- } -- } --} -- - bool CXRandR::SetMode(XOutput output, XMode mode) - { - if ((output.name == m_currentOutput && mode.id == m_currentMode) || (output.name == "" && mode.id == "")) -diff --git a/xbmc/windowing/X11/XRandR.h b/xbmc/windowing/X11/XRandR.h -index 2a269d0..5b64633 100644 ---- a/xbmc/windowing/X11/XRandR.h -+++ b/xbmc/windowing/X11/XRandR.h -@@ -99,7 +99,6 @@ class CXRandR - bool SetMode(XOutput output, XMode mode); - void LoadCustomModeLinesToAllOutputs(void); - void SaveState(); -- void RestoreState(); - //bool Has1080i(); - //bool Has1080p(); - //bool Has720p(); --- -1.7.10 - - -From b74182e365180b8f6bb413ad49ef17846cb6cf66 Mon Sep 17 00:00:00 2001 -From: xbmc -Date: Sun, 20 May 2012 13:17:10 +0200 -Subject: [PATCH 41/88] xrandr: observe orientation - ---- - xbmc/windowing/X11/WinSystemX11.cpp | 61 +++++++++++++++++++++++++++++++++-- - xbmc/windowing/X11/WinSystemX11.h | 2 ++ - xbmc/windowing/X11/XRandR.cpp | 7 ++++ - xbmc/windowing/X11/XRandR.h | 1 + - 4 files changed, 68 insertions(+), 3 deletions(-) - -diff --git a/xbmc/windowing/X11/WinSystemX11.cpp b/xbmc/windowing/X11/WinSystemX11.cpp -index e13ffa4..6b0aa92 100644 ---- a/xbmc/windowing/X11/WinSystemX11.cpp -+++ b/xbmc/windowing/X11/WinSystemX11.cpp -@@ -170,15 +170,24 @@ bool CWinSystemX11::ResizeWindow(int newWidth, int newHeight, int newLeft, int n - - void CWinSystemX11::RefreshWindow() - { -- g_xrandr.Query(true); -+ if (!g_xrandr.Query(true)) -+ { -+ CLog::Log(LOGERROR, "WinSystemX11::RefreshWindow - failed to query xrandr"); -+ return; -+ } - XOutput out = g_xrandr.GetCurrentOutput(); - XMode mode = g_xrandr.GetCurrentMode(out.name); - -+ RotateResolutions(); -+ - // only overwrite desktop resolution, if we are not in fullscreen mode - if (!g_graphicsContext.IsFullScreenVideo()) - { - CLog::Log(LOGDEBUG, "CWinSystemX11::RefreshWindow - store desktop resolution, width: %d, height: %d, hz: %2.2f", mode.w, mode.h, mode.hz); -- UpdateDesktopResolution(g_settings.m_ResInfo[RES_DESKTOP], 0, mode.w, mode.h, mode.hz); -+ if (!out.isRotated) -+ UpdateDesktopResolution(g_settings.m_ResInfo[RES_DESKTOP], 0, mode.w, mode.h, mode.hz); -+ else -+ UpdateDesktopResolution(g_settings.m_ResInfo[RES_DESKTOP], 0, mode.h, mode.w, mode.hz); - g_settings.m_ResInfo[RES_DESKTOP].strId = mode.id; - g_settings.m_ResInfo[RES_DESKTOP].strOutput = out.name; - } -@@ -234,6 +243,14 @@ bool CWinSystemX11::SetFullScreen(bool fullScreen, RESOLUTION_INFO& res, bool bl - XOutput currout = g_xrandr.GetCurrentOutput(); - XMode currmode = g_xrandr.GetCurrentMode(currout.name); - -+ // flip h/w when rotated -+ if (m_bIsRotated) -+ { -+ int w = mode.w; -+ mode.w = mode.h; -+ mode.h = w; -+ } -+ - // only call xrandr if mode changes - if (currout.name != out.name || currmode.w != mode.w || currmode.h != mode.h || - currmode.hz != mode.hz || currmode.id != mode.id) -@@ -266,7 +283,11 @@ void CWinSystemX11::UpdateResolutions() - { - XOutput out = g_xrandr.GetCurrentOutput(); - XMode mode = g_xrandr.GetCurrentMode(out.name); -- UpdateDesktopResolution(g_settings.m_ResInfo[RES_DESKTOP], 0, mode.w, mode.h, mode.hz); -+ m_bIsRotated = out.isRotated; -+ if (!m_bIsRotated) -+ UpdateDesktopResolution(g_settings.m_ResInfo[RES_DESKTOP], 0, mode.w, mode.h, mode.hz); -+ else -+ UpdateDesktopResolution(g_settings.m_ResInfo[RES_DESKTOP], 0, mode.h, mode.w, mode.hz); - g_settings.m_ResInfo[RES_DESKTOP].strId = mode.id; - g_settings.m_ResInfo[RES_DESKTOP].strOutput = out.name; - } -@@ -305,6 +326,16 @@ void CWinSystemX11::UpdateResolutions() - res.iHeight = mode.h; - res.iScreenWidth = mode.w; - res.iScreenHeight = mode.h; -+ if (!m_bIsRotated) -+ { -+ res.iWidth = mode.w; -+ res.iHeight = mode.h; -+ } -+ else -+ { -+ res.iWidth = mode.h; -+ res.iHeight = mode.w; -+ } - if (mode.h>0 && mode.w>0 && out.hmm>0 && out.wmm>0) - res.fPixelRatio = ((float)out.wmm/(float)mode.w) / (((float)out.hmm/(float)mode.h)); - else -@@ -332,6 +363,30 @@ void CWinSystemX11::UpdateResolutions() - - } - -+void CWinSystemX11::RotateResolutions() -+{ -+#if defined(HAS_XRANDR) -+ XOutput out = g_xrandr.GetCurrentOutput(); -+ if (out.isRotated == m_bIsRotated) -+ return; -+ -+ for (unsigned int i = 0; i < g_settings.m_ResInfo.size(); ++i) -+ { -+ int width = g_settings.m_ResInfo[i].iWidth; -+ g_settings.m_ResInfo[i].iWidth = g_settings.m_ResInfo[i].iHeight; -+ g_settings.m_ResInfo[i].iHeight = width; -+ } -+ // update desktop resolution -+// int h = g_settings.m_ResInfo[RES_DESKTOP].iHeight; -+// int w = g_settings.m_ResInfo[RES_DESKTOP].iWidth; -+// float hz = g_settings.m_ResInfo[RES_DESKTOP].fRefreshRate; -+// UpdateDesktopResolution(g_settings.m_ResInfo[RES_DESKTOP], 0, w, h, hz); -+ -+ m_bIsRotated = out.isRotated; -+ -+#endif -+} -+ - bool CWinSystemX11::IsSuitableVisual(XVisualInfo *vInfo) - { - int value; -diff --git a/xbmc/windowing/X11/WinSystemX11.h b/xbmc/windowing/X11/WinSystemX11.h -index 8c28e3f..93cf5db 100644 ---- a/xbmc/windowing/X11/WinSystemX11.h -+++ b/xbmc/windowing/X11/WinSystemX11.h -@@ -73,12 +73,14 @@ class CWinSystemX11 : public CWinSystemBase - void CheckDisplayEvents(); - void OnLostDevice(); - bool SetWindow(int width, int height, bool fullscreen); -+ void RotateResolutions(); - - Window m_glWindow; - GLXContext m_glContext; - Display* m_dpy; - Cursor m_invisibleCursor; - Pixmap m_icon; -+ bool m_bIsRotated; - bool m_bWasFullScreenBeforeMinimize; - bool m_minimized; - bool m_bIgnoreNextFocusMessage; -diff --git a/xbmc/windowing/X11/XRandR.cpp b/xbmc/windowing/X11/XRandR.cpp -index 59755a6..45aeb71 100644 ---- a/xbmc/windowing/X11/XRandR.cpp -+++ b/xbmc/windowing/X11/XRandR.cpp -@@ -98,6 +98,13 @@ bool CXRandR::Query(bool force) - xoutput.y = (output->Attribute("y") != NULL ? atoi(output->Attribute("y")) : 0); - xoutput.wmm = (output->Attribute("wmm") != NULL ? atoi(output->Attribute("wmm")) : 0); - xoutput.hmm = (output->Attribute("hmm") != NULL ? atoi(output->Attribute("hmm")) : 0); -+ if (output->Attribute("rotation") != NULL -+ && (strcasecmp(output->Attribute("rotation"), "left") == 0 || strcasecmp(output->Attribute("rotation"), "right") == 0)) -+ { -+ xoutput.isRotated = true; -+ } -+ else -+ xoutput.isRotated = false; - - if (!xoutput.isConnected) - continue; -diff --git a/xbmc/windowing/X11/XRandR.h b/xbmc/windowing/X11/XRandR.h -index 5b64633..618bd68 100644 ---- a/xbmc/windowing/X11/XRandR.h -+++ b/xbmc/windowing/X11/XRandR.h -@@ -86,6 +86,7 @@ class XOutput - int wmm; - int hmm; - std::vector modes; -+ bool isRotated; - }; - - class CXRandR --- -1.7.10 - - -From 80ebbe1851f21ed959f6b30eac6374d3bbe9258e Mon Sep 17 00:00:00 2001 -From: FernetMenta -Date: Thu, 5 Jul 2012 11:54:15 +0200 -Subject: [PATCH 42/88] xrandr: allow getting info for multiple screen's - -Refactored by: Joakim Plate ---- - xbmc/windowing/X11/XRandR.cpp | 65 ++++++++++++++++++++++++++++++++--------- - xbmc/windowing/X11/XRandR.h | 8 +++-- - 2 files changed, 57 insertions(+), 16 deletions(-) - -diff --git a/xbmc/windowing/X11/XRandR.cpp b/xbmc/windowing/X11/XRandR.cpp -index 45aeb71..cc933b9 100644 ---- a/xbmc/windowing/X11/XRandR.cpp -+++ b/xbmc/windowing/X11/XRandR.cpp -@@ -39,6 +39,7 @@ - CXRandR::CXRandR(bool query) - { - m_bInit = false; -+ m_numScreens = 1; - if (query) - Query(); - } -@@ -55,11 +56,21 @@ bool CXRandR::Query(bool force) - return false; - - m_outputs.clear(); -- m_current.clear(); -+ // query all screens -+ for(unsigned int screennum=0; screennumValue(), "screen") != 0) -+ if (strcasecmp(pRootElement->Value(), "screen") != screennum) - { - // TODO ERROR - return false; -@@ -92,6 +103,7 @@ bool CXRandR::Query(bool force) - xoutput.name.TrimLeft(" \n\r\t"); - xoutput.name.TrimRight(" \n\r\t"); - xoutput.isConnected = (strcasecmp(output->Attribute("connected"), "true") == 0); -+ xoutput.screen = screennum; - xoutput.w = (output->Attribute("w") != NULL ? atoi(output->Attribute("w")) : 0); - xoutput.h = (output->Attribute("h") != NULL ? atoi(output->Attribute("h")) : 0); - xoutput.x = (output->Attribute("x") != NULL ? atoi(output->Attribute("x")) : 0); -@@ -123,7 +135,6 @@ bool CXRandR::Query(bool force) - xoutput.modes.push_back(xmode); - if (xmode.isCurrent) - { -- m_current.push_back(xoutput); - hascurrent = true; - } - } -@@ -247,17 +258,6 @@ bool CXRandR::SetMode(XOutput output, XMode mode) - return true; - } - --XOutput CXRandR::GetCurrentOutput() --{ -- Query(); -- for (unsigned int j = 0; j < m_outputs.size(); j++) -- { -- if(m_outputs[j].isConnected) -- return m_outputs[j]; -- } -- XOutput empty; -- return empty; --} - XMode CXRandR::GetCurrentMode(CStdString outputName) - { - Query(); -@@ -331,6 +331,43 @@ void CXRandR::LoadCustomModeLinesToAllOutputs(void) - } - } - -+void CXRandR::SetNumScreens(unsigned int num) -+{ -+ m_numScreens = num; -+ m_bInit = false; -+} -+ -+bool CXRandR::IsOutputConnected(CStdString name) -+{ -+ bool result = false; -+ Query(); -+ -+ for (unsigned int i = 0; i < m_outputs.size(); ++i) -+ { -+ if (m_outputs[i].name == name) -+ { -+ result = true; -+ break; -+ } -+ } -+ return result; -+} -+ -+XOutput* CXRandR::GetOutput(CStdString outputName) -+{ -+ XOutput *result = 0; -+ Query(); -+ for (unsigned int i = 0; i < m_outputs.size(); ++i) -+ { -+ if (m_outputs[i].name == outputName) -+ { -+ result = &m_outputs[i]; -+ break; -+ } -+ } -+ return result; -+} -+ - CXRandR g_xrandr; - - #endif // HAS_XRANDR -diff --git a/xbmc/windowing/X11/XRandR.h b/xbmc/windowing/X11/XRandR.h -index 618bd68..0824af5 100644 ---- a/xbmc/windowing/X11/XRandR.h -+++ b/xbmc/windowing/X11/XRandR.h -@@ -79,6 +79,7 @@ class XOutput - } - CStdString name; - bool isConnected; -+ int screen; - int w; - int h; - int x; -@@ -94,12 +95,15 @@ class CXRandR - public: - CXRandR(bool query=false); - bool Query(bool force=false); -+ bool Query(bool force, int screennum); - std::vector GetModes(void); -- XOutput GetCurrentOutput(); - XMode GetCurrentMode(CStdString outputName); -+ XOutput *GetOutput(CStdString outputName); - bool SetMode(XOutput output, XMode mode); - void LoadCustomModeLinesToAllOutputs(void); - void SaveState(); -+ void SetNumScreens(unsigned int num); -+ bool IsOutputConnected(CStdString name); - //bool Has1080i(); - //bool Has1080p(); - //bool Has720p(); -@@ -107,10 +111,10 @@ class CXRandR - - private: - bool m_bInit; -- std::vector m_current; - std::vector m_outputs; - CStdString m_currentOutput; - CStdString m_currentMode; -+ unsigned int m_numScreens; - }; - - extern CXRandR g_xrandr; --- -1.7.10 - - -From ec0fa66fe2322cf5cd47ec0b6b832f47e1ab7e1f Mon Sep 17 00:00:00 2001 -From: FernetMenta -Date: Thu, 5 Jul 2012 11:44:00 +0200 -Subject: [PATCH 43/88] X11: fix multi-head setups - ---- - language/English/strings.po | 4 +- - xbmc/rendering/gl/RenderSystemGL.h | 1 + - xbmc/settings/GUISettings.cpp | 5 + - xbmc/settings/GUIWindowSettingsCategory.cpp | 60 +++++- - xbmc/settings/GUIWindowSettingsCategory.h | 1 + - xbmc/windowing/WinEventsX11.cpp | 7 + - xbmc/windowing/X11/WinSystemX11.cpp | 262 ++++++++++++++++----------- - xbmc/windowing/X11/WinSystemX11.h | 10 +- - 8 files changed, 235 insertions(+), 115 deletions(-) - -diff --git a/language/English/strings.po b/language/English/strings.po -index c3ba92f..f2abd3f 100644 ---- a/language/English/strings.po -+++ b/language/English/strings.po -@@ -895,7 +895,9 @@ msgctxt "#245" - msgid "Sizing: (%i,%i)->(%i,%i) (Zoom x%2.2f) AR:%2.2f:1 (Pixels: %2.2f:1) (VShift: %2.2f)" - msgstr "" - --#empty string with id 246 -+msgctxt "#246" -+msgid "Monitor" -+msgstr "" - - msgctxt "#247" - msgid "Scripts" -diff --git a/xbmc/rendering/gl/RenderSystemGL.h b/xbmc/rendering/gl/RenderSystemGL.h -index efe5493..85d780d 100644 ---- a/xbmc/rendering/gl/RenderSystemGL.h -+++ b/xbmc/rendering/gl/RenderSystemGL.h -@@ -44,6 +44,7 @@ class CRenderSystemGL : public CRenderSystemBase - virtual bool IsExtSupported(const char* extension); - - virtual void SetVSync(bool vsync); -+ virtual void ResetVSync() { m_bVsyncInit = false; } - - virtual void SetViewPort(CRect& viewPort); - virtual void GetViewPort(CRect& viewPort); -diff --git a/xbmc/settings/GUISettings.cpp b/xbmc/settings/GUISettings.cpp -index 4cec1b3..30b402d 100644 ---- a/xbmc/settings/GUISettings.cpp -+++ b/xbmc/settings/GUISettings.cpp -@@ -392,11 +392,16 @@ void CGUISettings::Initialize() - AddGroup(SETTINGS_SYSTEM, 13000); - CSettingsCategory* vs = AddCategory(SETTINGS_SYSTEM, "videoscreen", 21373); - -+#if defined(HAS_GLX) -+ AddString(vs, "videoscreen.monitor", 246, "", SPIN_CONTROL_TEXT); -+#endif -+ - // this setting would ideally not be saved, as its value is systematically derived from videoscreen.screenmode. - // contains a DISPLAYMODE - #if !defined(TARGET_DARWIN_IOS_ATV2) && !defined(TARGET_RASPBERRY_PI) - AddInt(vs, "videoscreen.screen", 240, 0, -1, 1, 32, SPIN_CONTROL_TEXT); - #endif -+ - // this setting would ideally not be saved, as its value is systematically derived from videoscreen.screenmode. - // contains an index to the g_settings.m_ResInfo array. the only meaningful fields are iScreen, iWidth, iHeight. - #if defined(TARGET_DARWIN) -diff --git a/xbmc/settings/GUIWindowSettingsCategory.cpp b/xbmc/settings/GUIWindowSettingsCategory.cpp -index 2af9315..b9f18e4 100644 ---- a/xbmc/settings/GUIWindowSettingsCategory.cpp -+++ b/xbmc/settings/GUIWindowSettingsCategory.cpp -@@ -528,6 +528,12 @@ void CGUIWindowSettingsCategory::CreateSettings() - FillInRefreshRates(strSetting, g_guiSettings.GetResolution(), false); - continue; - } -+ else if (strSetting.Equals("videoscreen.monitor")) -+ { -+ AddSetting(pSetting, group->GetWidth(), iControlID); -+ FillInMonitors(strSetting); -+ continue; -+ } - else if (strSetting.Equals("lookandfeel.skintheme")) - { - AddSetting(pSetting, group->GetWidth(), iControlID); -@@ -1477,6 +1483,20 @@ void CGUIWindowSettingsCategory::OnSettingChanged(BaseSettingControlPtr pSetting - // Cascade - FillInResolutions("videoscreen.resolution", mode, RES_DESKTOP, true); - } -+ else if (strSetting.Equals("videoscreen.monitor")) -+ { -+ CSettingString *pSettingString = (CSettingString *)pSettingControl->GetSetting(); -+ CGUISpinControlEx *pControl = (CGUISpinControlEx *)GetControl(pSettingControl->GetID()); -+ CStdString currentMonitor = pControl->GetCurrentLabel(); -+ if (!g_Windowing.IsCurrentOutput(currentMonitor)) -+ { -+ g_guiSettings.SetString("videoscreen.monitor", currentMonitor); -+ g_Windowing.UpdateResolutions(); -+ DisplayMode mode = g_guiSettings.GetInt("videoscreen.screen"); -+ // Cascade -+ FillInResolutions("videoscreen.resolution", mode, RES_DESKTOP, true); -+ } -+ } - else if (strSetting.Equals("videoscreen.resolution")) - { - RESOLUTION nextRes = (RESOLUTION) g_guiSettings.GetInt("videoscreen.resolution"); -@@ -2413,11 +2433,15 @@ DisplayMode CGUIWindowSettingsCategory::FillInScreens(CStdString strSetting, RES - if (g_advancedSettings.m_canWindowed) - pControl->AddLabel(g_localizeStrings.Get(242), -1); - -+#if !defined(HAS_GLX) - for (int idx = 0; idx < g_Windowing.GetNumScreens(); idx++) - { - strScreen.Format(g_localizeStrings.Get(241), g_settings.m_ResInfo[RES_DESKTOP + idx].iScreen + 1); - pControl->AddLabel(strScreen, g_settings.m_ResInfo[RES_DESKTOP + idx].iScreen); - } -+#else -+ pControl->AddLabel(g_localizeStrings.Get(244), 0); -+#endif - pControl->SetValue(mode); - g_guiSettings.SetInt("videoscreen.screen", mode); - } -@@ -2425,6 +2449,36 @@ DisplayMode CGUIWindowSettingsCategory::FillInScreens(CStdString strSetting, RES - return mode; - } - -+void CGUIWindowSettingsCategory::FillInMonitors(CStdString strSetting) -+{ -+ // we expect "videoscreen.monitor" but it might be hidden on some platforms, -+ // so check that we actually have a visable control. -+ CBaseSettingControl *control = GetSetting(strSetting); -+ if (control) -+ { -+ control->SetDelayed(); -+ CGUISpinControlEx *pControl = (CGUISpinControlEx *)GetControl(control->GetID()); -+ pControl->Clear(); -+ -+ std::vector monitors; -+ g_Windowing.GetConnectedOutputs(&monitors); -+ -+ int currentMonitor = 0; -+ for (unsigned int i=0; iAddLabel(monitors[i], i); -+ } -+ -+ pControl->SetValue(currentMonitor); -+ g_guiSettings.SetString("videoscreen.monitor", g_settings.m_ResInfo[RES_DESKTOP].strOutput); -+ } -+} -+ -+ - void CGUIWindowSettingsCategory::FillInResolutions(CStdString strSetting, DisplayMode mode, RESOLUTION res, bool UserChange) - { - BaseSettingControlPtr control = GetSetting(strSetting); -@@ -2553,13 +2607,15 @@ void CGUIWindowSettingsCategory::OnRefreshRateChanged(RESOLUTION nextRes) - RESOLUTION lastRes = g_graphicsContext.GetVideoResolution(); - bool cancelled = false; - -+ bool outputChanged = !g_Windowing.IsCurrentOutput(g_guiSettings.GetString("videoscreen.monitor")); -+ - g_guiSettings.SetResolution(nextRes); -- g_graphicsContext.SetVideoResolution(nextRes); -+ g_graphicsContext.SetVideoResolution(nextRes, outputChanged); - - if (!CGUIDialogYesNo::ShowAndGetInput(13110, 13111, 20022, 20022, -1, -1, cancelled, 10000)) - { - g_guiSettings.SetResolution(lastRes); -- g_graphicsContext.SetVideoResolution(lastRes); -+ g_graphicsContext.SetVideoResolution(lastRes, outputChanged); - - DisplayMode mode = FillInScreens("videoscreen.screen", lastRes); - FillInResolutions("videoscreen.resolution", mode, lastRes, false); -diff --git a/xbmc/settings/GUIWindowSettingsCategory.h b/xbmc/settings/GUIWindowSettingsCategory.h -index 5142c6e..0d4649d 100644 ---- a/xbmc/settings/GUIWindowSettingsCategory.h -+++ b/xbmc/settings/GUIWindowSettingsCategory.h -@@ -51,6 +51,7 @@ class CGUIWindowSettingsCategory : - void FillInSoundSkins(CSetting *pSetting); - void FillInLanguages(CSetting *pSetting, const std::vector &languages = std::vector(), const std::vector &languageKeys = std::vector()); - DisplayMode FillInScreens(CStdString strSetting, RESOLUTION res); -+ void FillInMonitors(CStdString strSetting); - void FillInResolutions(CStdString strSetting, DisplayMode mode, RESOLUTION res, bool UserChange); - void FillInRefreshRates(CStdString strSetting, RESOLUTION res, bool UserChange); - void OnRefreshRateChanged(RESOLUTION resolution); -diff --git a/xbmc/windowing/WinEventsX11.cpp b/xbmc/windowing/WinEventsX11.cpp -index 5946a33..6c22358 100644 ---- a/xbmc/windowing/WinEventsX11.cpp -+++ b/xbmc/windowing/WinEventsX11.cpp -@@ -517,9 +517,16 @@ bool CWinEventsX11::MessagePump() - break; - } - -+ case EnterNotify: -+ { -+ g_Windowing.NotifyMouseCoverage(true); -+ break; -+ } -+ - // lose mouse coverage - case LeaveNotify: - { -+ g_Windowing.NotifyMouseCoverage(false); - g_Mouse.SetActive(false); - break; - } -diff --git a/xbmc/windowing/X11/WinSystemX11.cpp b/xbmc/windowing/X11/WinSystemX11.cpp -index 6b0aa92..5f913f1 100644 ---- a/xbmc/windowing/X11/WinSystemX11.cpp -+++ b/xbmc/windowing/X11/WinSystemX11.cpp -@@ -33,6 +33,7 @@ - #include "cores/VideoRenderers/RenderManager.h" - #include "utils/TimeUtils.h" - #include "settings/GUISettings.h" -+#include "windowing/WindowingFactory.h" - - #if defined(HAS_XRANDR) - #include -@@ -54,6 +55,7 @@ - m_bIgnoreNextFocusMessage = false; - m_dpyLostTime = 0; - m_invisibleCursor = 0; -+ m_bIsInternalXrr = false; - - XSetErrorHandler(XErrorHandler); - } -@@ -66,7 +68,8 @@ bool CWinSystemX11::InitWindowSystem() - { - if ((m_dpy = XOpenDisplay(NULL))) - { -- return CWinSystemBase::InitWindowSystem(); -+ bool ret = CWinSystemBase::InitWindowSystem(); -+ return ret; - } - else - CLog::Log(LOGERROR, "GLX Error: No Display found"); -@@ -103,6 +106,8 @@ bool CWinSystemX11::DestroyWindowSystem() - - //we don't call XCloseDisplay() here, since ati keeps a pointer to our m_dpy - //so instead we just let m_dpy die on exit -+ // i have seen core dumps on ATI if the display is not closed here -+ XCloseDisplay(m_dpy); - } - - // m_SDLSurface is free()'d by SDL_Quit(). -@@ -125,7 +130,10 @@ bool CWinSystemX11::DestroyWindow() - return true; - - if (m_glContext) -+ { -+ glFinish(); - glXMakeCurrent(m_dpy, None, NULL); -+ } - - if (m_invisibleCursor) - { -@@ -155,7 +163,7 @@ bool CWinSystemX11::ResizeWindow(int newWidth, int newHeight, int newLeft, int n - && m_nHeight == newHeight) - return true; - -- if (!SetWindow(newWidth, newHeight, false)) -+ if (!SetWindow(newWidth, newHeight, false, g_guiSettings.GetString("videoscreen.monitor"))) - { - return false; - } -@@ -164,58 +172,11 @@ bool CWinSystemX11::ResizeWindow(int newWidth, int newHeight, int newLeft, int n - m_nWidth = newWidth; - m_nHeight = newHeight; - m_bFullScreen = false; -+ m_currentOutput = g_guiSettings.GetString("videoscreen.monitor"); - - return false; - } - --void CWinSystemX11::RefreshWindow() --{ -- if (!g_xrandr.Query(true)) -- { -- CLog::Log(LOGERROR, "WinSystemX11::RefreshWindow - failed to query xrandr"); -- return; -- } -- XOutput out = g_xrandr.GetCurrentOutput(); -- XMode mode = g_xrandr.GetCurrentMode(out.name); -- -- RotateResolutions(); -- -- // only overwrite desktop resolution, if we are not in fullscreen mode -- if (!g_graphicsContext.IsFullScreenVideo()) -- { -- CLog::Log(LOGDEBUG, "CWinSystemX11::RefreshWindow - store desktop resolution, width: %d, height: %d, hz: %2.2f", mode.w, mode.h, mode.hz); -- if (!out.isRotated) -- UpdateDesktopResolution(g_settings.m_ResInfo[RES_DESKTOP], 0, mode.w, mode.h, mode.hz); -- else -- UpdateDesktopResolution(g_settings.m_ResInfo[RES_DESKTOP], 0, mode.h, mode.w, mode.hz); -- g_settings.m_ResInfo[RES_DESKTOP].strId = mode.id; -- g_settings.m_ResInfo[RES_DESKTOP].strOutput = out.name; -- } -- -- RESOLUTION_INFO res; -- unsigned int i; -- bool found(false); -- for (i = RES_DESKTOP; i < g_settings.m_ResInfo.size(); ++i) -- { -- if (g_settings.m_ResInfo[i].strId == mode.id) -- { -- found = true; -- break; -- } -- } -- -- if (!found) -- { -- CLog::Log(LOGERROR, "CWinSystemX11::RefreshWindow - could not find resolution"); -- return; -- } -- -- if (g_graphicsContext.IsFullScreenRoot()) -- g_graphicsContext.SetVideoResolution((RESOLUTION)i, true); -- else -- g_graphicsContext.SetVideoResolution(RES_WINDOW, true); --} -- - bool CWinSystemX11::SetFullScreen(bool fullScreen, RESOLUTION_INFO& res, bool blankOtherDisplays) - { - -@@ -240,8 +201,7 @@ bool CWinSystemX11::SetFullScreen(bool fullScreen, RESOLUTION_INFO& res, bool bl - mode.id = g_settings.m_ResInfo[RES_DESKTOP].strId; - } - -- XOutput currout = g_xrandr.GetCurrentOutput(); -- XMode currmode = g_xrandr.GetCurrentMode(currout.name); -+ XMode currmode = g_xrandr.GetCurrentMode(out.name); - - // flip h/w when rotated - if (m_bIsRotated) -@@ -252,16 +212,17 @@ bool CWinSystemX11::SetFullScreen(bool fullScreen, RESOLUTION_INFO& res, bool bl - } - - // only call xrandr if mode changes -- if (currout.name != out.name || currmode.w != mode.w || currmode.h != mode.h || -+ if (currmode.w != mode.w || currmode.h != mode.h || - currmode.hz != mode.hz || currmode.id != mode.id) - { - CLog::Log(LOGNOTICE, "CWinSystemX11::SetFullScreen - calling xrandr"); - OnLostDevice(); -+ m_bIsInternalXrr = true; - g_xrandr.SetMode(out, mode); - } - #endif - -- if (!SetWindow(res.iWidth, res.iHeight, fullScreen)) -+ if (!SetWindow(res.iWidth, res.iHeight, fullScreen, g_guiSettings.GetString("videoscreen.monitor"))) - return false; - - RefreshGlxContext(); -@@ -269,6 +230,7 @@ bool CWinSystemX11::SetFullScreen(bool fullScreen, RESOLUTION_INFO& res, bool bl - m_nWidth = res.iWidth; - m_nHeight = res.iHeight; - m_bFullScreen = fullScreen; -+ m_currentOutput = g_guiSettings.GetString("videoscreen.monitor"); - - return true; - } -@@ -277,19 +239,30 @@ void CWinSystemX11::UpdateResolutions() - { - CWinSystemBase::UpdateResolutions(); - -- - #if defined(HAS_XRANDR) -- if(g_xrandr.Query()) -- { -- XOutput out = g_xrandr.GetCurrentOutput(); -- XMode mode = g_xrandr.GetCurrentMode(out.name); -- m_bIsRotated = out.isRotated; -+ CStdString currentMonitor; -+ int numScreens = XScreenCount(m_dpy); -+ g_xrandr.SetNumScreens(numScreens); -+ if(g_xrandr.Query(true)) -+ { -+ currentMonitor = g_guiSettings.GetString("videoscreen.monitor"); -+ // check if the monitor is connected -+ XOutput *out = g_xrandr.GetOutput(currentMonitor); -+ if (!out) -+ { -+ // choose first output -+ currentMonitor = g_xrandr.GetModes()[0].name; -+ out = g_xrandr.GetOutput(currentMonitor); -+ g_guiSettings.SetString("videoscreen.monitor", currentMonitor); -+ } -+ XMode mode = g_xrandr.GetCurrentMode(currentMonitor); -+ m_bIsRotated = out->isRotated; - if (!m_bIsRotated) -- UpdateDesktopResolution(g_settings.m_ResInfo[RES_DESKTOP], 0, mode.w, mode.h, mode.hz); -+ UpdateDesktopResolution(g_settings.m_ResInfo[RES_DESKTOP], out->screen, mode.w, mode.h, mode.hz); - else -- UpdateDesktopResolution(g_settings.m_ResInfo[RES_DESKTOP], 0, mode.h, mode.w, mode.hz); -+ UpdateDesktopResolution(g_settings.m_ResInfo[RES_DESKTOP], out->screen, mode.h, mode.w, mode.hz); - g_settings.m_ResInfo[RES_DESKTOP].strId = mode.id; -- g_settings.m_ResInfo[RES_DESKTOP].strOutput = out.name; -+ g_settings.m_ResInfo[RES_DESKTOP].strOutput = currentMonitor; - } - else - #endif -@@ -300,23 +273,26 @@ void CWinSystemX11::UpdateResolutions() - UpdateDesktopResolution(g_settings.m_ResInfo[RES_DESKTOP], 0, w, h, 0.0); - } - -- - #if defined(HAS_XRANDR) - -+ // erase previous stored modes -+ if (g_settings.m_ResInfo.size() > RES_CUSTOM) -+ { -+ std::vector::iterator firstCustom = g_settings.m_ResInfo.begin()+RES_CUSTOM; -+ g_settings.m_ResInfo.erase(firstCustom, g_settings.m_ResInfo.end()); -+ } -+ - CLog::Log(LOGINFO, "Available videomodes (xrandr):"); -- vector::iterator outiter; -- vector outs; -- outs = g_xrandr.GetModes(); -- CLog::Log(LOGINFO, "Number of connected outputs: %"PRIdS"", outs.size()); -+ -+ XOutput *out = g_xrandr.GetOutput(currentMonitor); - string modename = ""; - -- for (outiter = outs.begin() ; outiter != outs.end() ; outiter++) -+ if (out != NULL) - { -- XOutput out = *outiter; - vector::iterator modeiter; -- CLog::Log(LOGINFO, "Output '%s' has %"PRIdS" modes", out.name.c_str(), out.modes.size()); -+ CLog::Log(LOGINFO, "Output '%s' has %"PRIdS" modes", out->name.c_str(), out->modes.size()); - -- for (modeiter = out.modes.begin() ; modeiter!=out.modes.end() ; modeiter++) -+ for (modeiter = out->modes.begin() ; modeiter!=out->modes.end() ; modeiter++) - { - XMode mode = *modeiter; - CLog::Log(LOGINFO, "ID:%s Name:%s Refresh:%f Width:%d Height:%d", -@@ -336,15 +312,15 @@ void CWinSystemX11::UpdateResolutions() - res.iWidth = mode.h; - res.iHeight = mode.w; - } -- if (mode.h>0 && mode.w>0 && out.hmm>0 && out.wmm>0) -- res.fPixelRatio = ((float)out.wmm/(float)mode.w) / (((float)out.hmm/(float)mode.h)); -+ if (mode.h>0 && mode.w>0 && out->hmm>0 && out->wmm>0) -+ res.fPixelRatio = ((float)out->wmm/(float)mode.w) / (((float)out->hmm/(float)mode.h)); - else - res.fPixelRatio = 1.0f; - - CLog::Log(LOGINFO, "Pixel Ratio: %f", res.fPixelRatio); - -- res.strMode.Format("%s: %s @ %.2fHz", out.name.c_str(), mode.name.c_str(), mode.hz); -- res.strOutput = out.name; -+ res.strMode.Format("%s: %s @ %.2fHz", out->name.c_str(), mode.name.c_str(), mode.hz); -+ res.strOutput = out->name; - res.strId = mode.id; - res.iSubtitles = (int)(0.95*mode.h); - res.fRefreshRate = mode.hz; -@@ -363,28 +339,19 @@ void CWinSystemX11::UpdateResolutions() - - } - --void CWinSystemX11::RotateResolutions() -+void CWinSystemX11::GetConnectedOutputs(std::vector *outputs) - { --#if defined(HAS_XRANDR) -- XOutput out = g_xrandr.GetCurrentOutput(); -- if (out.isRotated == m_bIsRotated) -- return; -- -- for (unsigned int i = 0; i < g_settings.m_ResInfo.size(); ++i) -+ vector outs; -+ outs = g_xrandr.GetModes(); -+ for(unsigned int i=0; ipush_back(outs[i].name); - } -- // update desktop resolution --// int h = g_settings.m_ResInfo[RES_DESKTOP].iHeight; --// int w = g_settings.m_ResInfo[RES_DESKTOP].iWidth; --// float hz = g_settings.m_ResInfo[RES_DESKTOP].fRefreshRate; --// UpdateDesktopResolution(g_settings.m_ResInfo[RES_DESKTOP], 0, w, h, hz); -- -- m_bIsRotated = out.isRotated; -+} - --#endif -+bool CWinSystemX11::IsCurrentOutput(CStdString output) -+{ -+ return m_currentOutput.Equals(output); - } - - bool CWinSystemX11::IsSuitableVisual(XVisualInfo *vInfo) -@@ -414,8 +381,11 @@ bool CWinSystemX11::RefreshGlxContext() - if (m_glContext) - { - CLog::Log(LOGDEBUG, "CWinSystemX11::RefreshGlxContext: refreshing context"); -+ glFinish(); - glXMakeCurrent(m_dpy, None, NULL); - glXMakeCurrent(m_dpy, m_glWindow, m_glContext); -+ XSync(m_dpy, FALSE); -+ g_Windowing.ResetVSync(); - return true; - } - -@@ -481,6 +451,8 @@ bool CWinSystemX11::RefreshGlxContext() - { - // make this context current - glXMakeCurrent(m_dpy, m_glWindow, m_glContext); -+ g_Windowing.ResetVSync(); -+ XSync(m_dpy, False); - retVal = true; - } - else -@@ -522,24 +494,53 @@ void CWinSystemX11::ResetOSScreensaver() - - void CWinSystemX11::NotifyAppActiveChange(bool bActivated) - { -- if (bActivated && m_bWasFullScreenBeforeMinimize && !g_graphicsContext.IsFullScreenRoot()) -+ if (bActivated && m_bWasFullScreenBeforeMinimize && !m_bFullScreen) -+ { - g_graphicsContext.ToggleFullScreenRoot(); - -+ m_bWasFullScreenBeforeMinimize = false; -+ } - m_minimized = !bActivated; - } - - void CWinSystemX11::NotifyAppFocusChange(bool bGaining) - { - if (bGaining && m_bWasFullScreenBeforeMinimize && !m_bIgnoreNextFocusMessage && -- !g_graphicsContext.IsFullScreenRoot()) -+ !m_bFullScreen) -+ { -+ m_bWasFullScreenBeforeMinimize = false; - g_graphicsContext.ToggleFullScreenRoot(); -+ m_minimized = false; -+ } - if (!bGaining) - m_bIgnoreNextFocusMessage = false; - } - -+void CWinSystemX11::NotifyMouseCoverage(bool covered) -+{ -+ if (!m_bFullScreen) -+ return; -+ -+ if (covered) -+ { -+ int result = -1; -+ while (result != GrabSuccess && result != AlreadyGrabbed) -+ { -+ result = XGrabPointer(m_dpy, m_glWindow, True, ButtonPressMask, GrabModeAsync, GrabModeAsync, None, None, CurrentTime); -+ XbmcThreads::ThreadSleep(100); -+ } -+ XGrabKeyboard(m_dpy, m_glWindow, True, GrabModeAsync, GrabModeAsync, CurrentTime); -+ } -+ else -+ { -+ XUngrabKeyboard(m_dpy, CurrentTime); -+ XUngrabPointer(m_dpy, CurrentTime); -+ } -+} -+ - bool CWinSystemX11::Minimize() - { -- m_bWasFullScreenBeforeMinimize = g_graphicsContext.IsFullScreenRoot(); -+ m_bWasFullScreenBeforeMinimize = m_bFullScreen; - if (m_bWasFullScreenBeforeMinimize) - { - m_bIgnoreNextFocusMessage = true; -@@ -605,13 +606,46 @@ void CWinSystemX11::CheckDisplayEvents() - void CWinSystemX11::NotifyXRREvent() - { - CLog::Log(LOGDEBUG, "%s - notify display reset event", __FUNCTION__); -- RefreshWindow(); -+ m_windowDirty = true; - -- CSingleLock lock(m_resourceSection); -+ // if external event update resolutions -+ if (!m_bIsInternalXrr) -+ { -+ UpdateResolutions(); -+ } -+ else if (!g_xrandr.Query(true)) -+ { -+ CLog::Log(LOGERROR, "WinSystemX11::RefreshWindow - failed to query xrandr"); -+ return; -+ } -+ m_bIsInternalXrr = false; - -- // tell any shared resources -- for (vector::iterator i = m_resources.begin(); i != m_resources.end(); i++) -- (*i)->OnResetDevice(); -+ CStdString currentOutput = g_guiSettings.GetString("videoscreen.monitor"); -+ XOutput *out = g_xrandr.GetOutput(currentOutput); -+ XMode mode = g_xrandr.GetCurrentMode(currentOutput); -+ -+ RESOLUTION_INFO res; -+ unsigned int i; -+ bool found(false); -+ for (i = RES_DESKTOP; i < g_settings.m_ResInfo.size(); ++i) -+ { -+ if (g_settings.m_ResInfo[i].strId == mode.id) -+ { -+ found = true; -+ break; -+ } -+ } -+ -+ if (!found) -+ { -+ CLog::Log(LOGERROR, "CWinSystemX11::RefreshWindow - could not find resolution"); -+ i = RES_DESKTOP; -+ } -+ -+ if (g_graphicsContext.IsFullScreenRoot()) -+ g_graphicsContext.SetVideoResolution((RESOLUTION)i, true); -+ else -+ g_graphicsContext.SetVideoResolution(RES_WINDOW, true); - - } - -@@ -664,14 +698,14 @@ bool CWinSystemX11::EnableFrameLimiter() - return m_minimized; - } - --bool CWinSystemX11::SetWindow(int width, int height, bool fullscreen) -+bool CWinSystemX11::SetWindow(int width, int height, bool fullscreen, const CStdString &output) - { - bool changeWindow = false; - bool changeSize = false; - bool mouseActive = false; - float mouseX, mouseY; - -- if (m_glWindow && (m_bFullScreen != fullscreen)) -+ if (m_glWindow && ((m_bFullScreen != fullscreen) || !m_currentOutput.Equals(output) || m_windowDirty)) - { - mouseActive = g_Mouse.IsActive(); - if (mouseActive) -@@ -693,6 +727,7 @@ bool CWinSystemX11::SetWindow(int width, int height, bool fullscreen) - else - mouseActive = false; - } -+ OnLostDevice(); - DestroyWindow(); - } - -@@ -714,7 +749,11 @@ bool CWinSystemX11::SetWindow(int width, int height, bool fullscreen) - XSetWindowAttributes swa; - XVisualInfo *vi; - -- vi = glXChooseVisual(m_dpy, DefaultScreen(m_dpy), att); -+ XOutput *out = g_xrandr.GetOutput(output); -+ if (!out) -+ out = g_xrandr.GetOutput(m_currentOutput); -+ m_nScreen = out->screen; -+ vi = glXChooseVisual(m_dpy, m_nScreen, att); - cmap = XCreateColormap(m_dpy, RootWindow(m_dpy, vi->screen), vi->visual, AllocNone); - - int def_vis = (vi->visual == DefaultVisual(m_dpy, vi->screen)); -@@ -730,7 +769,7 @@ bool CWinSystemX11::SetWindow(int width, int height, bool fullscreen) - unsigned long mask = CWBackPixel | CWBorderPixel | CWColormap | CWOverrideRedirect | CWEventMask; - - m_glWindow = XCreateWindow(m_dpy, RootWindow(m_dpy, vi->screen), -- 0, 0, width, height, 0, vi->depth, -+ out->x, out->y, width, height, 0, vi->depth, - InputOutput, vi->visual, - mask, &swa); - -@@ -801,14 +840,19 @@ bool CWinSystemX11::SetWindow(int width, int height, bool fullscreen) - if (fullscreen) - { - int result = -1; -- while (result != GrabSuccess) -+ while (result != GrabSuccess && result != AlreadyGrabbed) - { -- result = XGrabPointer(m_dpy, m_glWindow, True, ButtonPressMask, GrabModeAsync, GrabModeAsync, m_glWindow, None, CurrentTime); -+ result = XGrabPointer(m_dpy, m_glWindow, True, ButtonPressMask, GrabModeAsync, GrabModeAsync, None, None, CurrentTime); - XbmcThreads::ThreadSleep(100); - } - XGrabKeyboard(m_dpy, m_glWindow, True, GrabModeAsync, GrabModeAsync, CurrentTime); -- - } -+ CSingleLock lock(m_resourceSection); -+ // tell any shared resources -+ for (vector::iterator i = m_resources.begin(); i != m_resources.end(); i++) -+ (*i)->OnResetDevice(); -+ -+ m_windowDirty = false; - } - return true; - } -diff --git a/xbmc/windowing/X11/WinSystemX11.h b/xbmc/windowing/X11/WinSystemX11.h -index 93cf5db..71034fc 100644 ---- a/xbmc/windowing/X11/WinSystemX11.h -+++ b/xbmc/windowing/X11/WinSystemX11.h -@@ -65,15 +65,16 @@ class CWinSystemX11 : public CWinSystemBase - Display* GetDisplay() { return m_dpy; } - GLXWindow GetWindow() { return m_glWindow; } - GLXContext GetGlxContext() { return m_glContext; } -- void RefreshWindow(); - void NotifyXRREvent(); -+ void GetConnectedOutputs(std::vector *outputs); -+ bool IsCurrentOutput(CStdString output); -+ void NotifyMouseCoverage(bool covered); - - protected: - bool RefreshGlxContext(); - void CheckDisplayEvents(); - void OnLostDevice(); -- bool SetWindow(int width, int height, bool fullscreen); -- void RotateResolutions(); -+ bool SetWindow(int width, int height, bool fullscreen, const CStdString &output); - - Window m_glWindow; - GLXContext m_glContext; -@@ -88,6 +89,9 @@ class CWinSystemX11 : public CWinSystemBase - CCriticalSection m_resourceSection; - std::vector m_resources; - uint64_t m_dpyLostTime; -+ CStdString m_currentOutput; -+ bool m_windowDirty; -+ bool m_bIsInternalXrr; - - private: - bool IsSuitableVisual(XVisualInfo *vInfo); --- -1.7.10 - - -From 89a7d265a0e2673b8076bde718690cbb02e59670 Mon Sep 17 00:00:00 2001 -From: FernetMenta -Date: Thu, 5 Jul 2012 11:36:32 +0200 -Subject: [PATCH 44/88] X11: remove all DefaultScreen and RootWindow macros - ---- - xbmc/windowing/X11/WinSystemX11.cpp | 6 +++--- - xbmc/windowing/X11/WinSystemX11.h | 1 + - xbmc/windowing/X11/WinSystemX11GL.cpp | 2 +- - 3 files changed, 5 insertions(+), 4 deletions(-) - -diff --git a/xbmc/windowing/X11/WinSystemX11.cpp b/xbmc/windowing/X11/WinSystemX11.cpp -index 5f913f1..af1307c 100644 ---- a/xbmc/windowing/X11/WinSystemX11.cpp -+++ b/xbmc/windowing/X11/WinSystemX11.cpp -@@ -267,7 +267,7 @@ void CWinSystemX11::UpdateResolutions() - else - #endif - { -- int x11screen = DefaultScreen(m_dpy); -+ int x11screen = m_nScreen; - int w = DisplayWidth(m_dpy, x11screen); - int h = DisplayHeight(m_dpy, x11screen); - UpdateDesktopResolution(g_settings.m_ResInfo[RES_DESKTOP], 0, w, h, 0.0); -@@ -393,7 +393,7 @@ bool CWinSystemX11::RefreshGlxContext() - XVisualInfo *visuals; - XVisualInfo *vInfo = NULL; - int availableVisuals = 0; -- vMask.screen = DefaultScreen(m_dpy); -+ vMask.screen = m_nScreen; - XWindowAttributes winAttr; - - /* Assume a depth of 24 in case the below calls to XGetWindowAttributes() -@@ -547,7 +547,7 @@ bool CWinSystemX11::Minimize() - g_graphicsContext.ToggleFullScreenRoot(); - } - -- XIconifyWindow(m_dpy, m_glWindow, DefaultScreen(m_dpy)); -+ XIconifyWindow(m_dpy, m_glWindow, m_nScreen); - - m_minimized = true; - return true; -diff --git a/xbmc/windowing/X11/WinSystemX11.h b/xbmc/windowing/X11/WinSystemX11.h -index 71034fc..3bb4b8e 100644 ---- a/xbmc/windowing/X11/WinSystemX11.h -+++ b/xbmc/windowing/X11/WinSystemX11.h -@@ -47,6 +47,7 @@ class CWinSystemX11 : public CWinSystemBase - virtual bool SetFullScreen(bool fullScreen, RESOLUTION_INFO& res, bool blankOtherDisplays); - virtual void UpdateResolutions(); - virtual int GetNumScreens() { return 1; } -+ virtual int GetCurrentScreen() { return m_nScreen; } - virtual void ShowOSMouse(bool show); - virtual void ResetOSScreensaver(); - virtual bool EnableFrameLimiter(); -diff --git a/xbmc/windowing/X11/WinSystemX11GL.cpp b/xbmc/windowing/X11/WinSystemX11GL.cpp -index f858f88..d192697 100644 ---- a/xbmc/windowing/X11/WinSystemX11GL.cpp -+++ b/xbmc/windowing/X11/WinSystemX11GL.cpp -@@ -203,7 +203,7 @@ bool CWinSystemX11GL::CreateNewWindow(const CStdString& name, bool fullScreen, R - return false; - - m_glxext = " "; -- m_glxext += (const char*)glXQueryExtensionsString(m_dpy, DefaultScreen(m_dpy)); -+ m_glxext += (const char*)glXQueryExtensionsString(m_dpy, m_nScreen); - m_glxext += " "; - - CLog::Log(LOGDEBUG, "GLX_EXTENSIONS:%s", m_glxext.c_str()); --- -1.7.10 - - -From ac87010f83e230caf6ed03e36c562a4fb0abb2ab Mon Sep 17 00:00:00 2001 -From: FernetMenta -Date: Thu, 5 Jul 2012 11:45:22 +0200 -Subject: [PATCH 45/88] X11: remove all DefaultScreen and RootWindow macros - (VideoRefClock) - -Note this is on a separate display connection. ---- - xbmc/video/VideoReferenceClock.cpp | 15 ++++++++------- - 1 file changed, 8 insertions(+), 7 deletions(-) - -diff --git a/xbmc/video/VideoReferenceClock.cpp b/xbmc/video/VideoReferenceClock.cpp -index 9785fe7..0004e07 100644 ---- a/xbmc/video/VideoReferenceClock.cpp -+++ b/xbmc/video/VideoReferenceClock.cpp -@@ -270,7 +270,7 @@ bool CVideoReferenceClock::SetupGLX() - } - - bool ExtensionFound = false; -- istringstream Extensions(glXQueryExtensionsString(m_Dpy, DefaultScreen(m_Dpy))); -+ istringstream Extensions(glXQueryExtensionsString(m_Dpy, g_Windowing.GetCurrentScreen())); - string ExtensionStr; - - while (!ExtensionFound) -@@ -297,7 +297,7 @@ bool CVideoReferenceClock::SetupGLX() - m_bIsATI = true; - } - -- m_vInfo = glXChooseVisual(m_Dpy, DefaultScreen(m_Dpy), singleBufferAttributes); -+ m_vInfo = glXChooseVisual(m_Dpy, g_Windowing.GetCurrentScreen(), singleBufferAttributes); - if (!m_vInfo) - { - CLog::Log(LOGDEBUG, "CVideoReferenceClock: glXChooseVisual returned NULL"); -@@ -308,15 +308,16 @@ bool CVideoReferenceClock::SetupGLX() - { - Swa.border_pixel = 0; - Swa.event_mask = StructureNotifyMask; -- Swa.colormap = XCreateColormap(m_Dpy, RootWindow(m_Dpy, m_vInfo->screen), m_vInfo->visual, AllocNone ); -+ Swa.colormap = XCreateColormap(m_Dpy, g_Windowing.GetWindow(), m_vInfo->visual, AllocNone ); - SwaMask = CWBorderPixel | CWColormap | CWEventMask; - -- m_Window = XCreateWindow(m_Dpy, RootWindow(m_Dpy, m_vInfo->screen), 0, 0, 256, 256, 0, -+ m_Window = XCreateWindow(m_Dpy, g_Windowing.GetWindow(), 0, 0, 256, 256, 0, - m_vInfo->depth, InputOutput, m_vInfo->visual, SwaMask, &Swa); - } - else - { -- m_pixmap = XCreatePixmap(m_Dpy, DefaultRootWindow(m_Dpy), 256, 256, m_vInfo->depth); -+ Window window = g_Windowing.GetWindow(); -+ m_pixmap = XCreatePixmap(m_Dpy, window, 256, 256, m_vInfo->depth); - if (!m_pixmap) - { - CLog::Log(LOGDEBUG, "CVideoReferenceClock: unable to create pixmap"); -@@ -383,7 +384,7 @@ bool CVideoReferenceClock::SetupGLX() - - //set up receiving of RandR events, we'll get one when the refreshrate changes - XRRQueryExtension(m_Dpy, &m_RREventBase, &ReturnV); -- XRRSelectInput(m_Dpy, RootWindow(m_Dpy, m_vInfo->screen), RRScreenChangeNotifyMask); -+ XRRSelectInput(m_Dpy, g_Windowing.GetWindow(), RRScreenChangeNotifyMask); - - UpdateRefreshrate(true); //forced refreshrate update - m_MissedVblanks = 0; -@@ -518,7 +519,7 @@ int CVideoReferenceClock::GetRandRRate() - int RefreshRate; - XRRScreenConfiguration *CurrInfo; - -- CurrInfo = XRRGetScreenInfo(m_Dpy, RootWindow(m_Dpy, m_vInfo->screen)); -+ CurrInfo = XRRGetScreenInfo(m_Dpy, g_Windowing.GetWindow()); - RefreshRate = XRRConfigCurrentRate(CurrInfo); - XRRFreeScreenConfigInfo(CurrInfo); - --- -1.7.10 - - -From 5510c47704fc1156897abc1932151460e4c07569 Mon Sep 17 00:00:00 2001 -From: xbmc -Date: Wed, 20 Jun 2012 17:37:11 +0200 -Subject: [PATCH 46/88] X11: recreate gl context after output has changed - ---- - xbmc/windowing/X11/WinSystemX11.cpp | 24 ++++++++++++++---------- - xbmc/windowing/X11/WinSystemX11.h | 1 + - xbmc/windowing/X11/WinSystemX11GL.cpp | 9 +++++++++ - 3 files changed, 24 insertions(+), 10 deletions(-) - -diff --git a/xbmc/windowing/X11/WinSystemX11.cpp b/xbmc/windowing/X11/WinSystemX11.cpp -index af1307c..d3d15e2 100644 ---- a/xbmc/windowing/X11/WinSystemX11.cpp -+++ b/xbmc/windowing/X11/WinSystemX11.cpp -@@ -168,7 +168,6 @@ bool CWinSystemX11::ResizeWindow(int newWidth, int newHeight, int newLeft, int n - return false; - } - -- RefreshGlxContext(); - m_nWidth = newWidth; - m_nHeight = newHeight; - m_bFullScreen = false; -@@ -219,14 +218,13 @@ bool CWinSystemX11::SetFullScreen(bool fullScreen, RESOLUTION_INFO& res, bool bl - OnLostDevice(); - m_bIsInternalXrr = true; - g_xrandr.SetMode(out, mode); -+ return true; - } - #endif - - if (!SetWindow(res.iWidth, res.iHeight, fullScreen, g_guiSettings.GetString("videoscreen.monitor"))) - return false; - -- RefreshGlxContext(); -- - m_nWidth = res.iWidth; - m_nHeight = res.iHeight; - m_bFullScreen = fullScreen; -@@ -381,11 +379,8 @@ bool CWinSystemX11::RefreshGlxContext() - if (m_glContext) - { - CLog::Log(LOGDEBUG, "CWinSystemX11::RefreshGlxContext: refreshing context"); -- glFinish(); - glXMakeCurrent(m_dpy, None, NULL); - glXMakeCurrent(m_dpy, m_glWindow, m_glContext); -- XSync(m_dpy, FALSE); -- g_Windowing.ResetVSync(); - return true; - } - -@@ -445,14 +440,14 @@ bool CWinSystemX11::RefreshGlxContext() - { - glXMakeCurrent(m_dpy, None, NULL); - glXDestroyContext(m_dpy, m_glContext); -+ XSync(m_dpy, FALSE); -+ m_newGlContext = true; - } - - if ((m_glContext = glXCreateContext(m_dpy, vInfo, NULL, True))) - { - // make this context current - glXMakeCurrent(m_dpy, m_glWindow, m_glContext); -- g_Windowing.ResetVSync(); -- XSync(m_dpy, False); - retVal = true; - } - else -@@ -729,6 +724,7 @@ bool CWinSystemX11::SetWindow(int width, int height, bool fullscreen, const CStd - } - OnLostDevice(); - DestroyWindow(); -+ m_windowDirty = true; - } - - // create main window -@@ -847,13 +843,21 @@ bool CWinSystemX11::SetWindow(int width, int height, bool fullscreen, const CStd - } - XGrabKeyboard(m_dpy, m_glWindow, True, GrabModeAsync, GrabModeAsync, CurrentTime); - } -+ -+ CDirtyRegionList dr; -+ RefreshGlxContext(); -+ XSync(m_dpy, FALSE); -+ g_graphicsContext.Clear(0); -+ g_graphicsContext.Flip(dr); -+ g_Windowing.ResetVSync(); -+ m_windowDirty = false; -+ - CSingleLock lock(m_resourceSection); - // tell any shared resources - for (vector::iterator i = m_resources.begin(); i != m_resources.end(); i++) - (*i)->OnResetDevice(); -- -- m_windowDirty = false; - } -+ - return true; - } - -diff --git a/xbmc/windowing/X11/WinSystemX11.h b/xbmc/windowing/X11/WinSystemX11.h -index 3bb4b8e..cc28f56 100644 ---- a/xbmc/windowing/X11/WinSystemX11.h -+++ b/xbmc/windowing/X11/WinSystemX11.h -@@ -93,6 +93,7 @@ class CWinSystemX11 : public CWinSystemBase - CStdString m_currentOutput; - bool m_windowDirty; - bool m_bIsInternalXrr; -+ bool m_newGlContext; - - private: - bool IsSuitableVisual(XVisualInfo *vInfo); -diff --git a/xbmc/windowing/X11/WinSystemX11GL.cpp b/xbmc/windowing/X11/WinSystemX11GL.cpp -index d192697..0f2d1d2 100644 ---- a/xbmc/windowing/X11/WinSystemX11GL.cpp -+++ b/xbmc/windowing/X11/WinSystemX11GL.cpp -@@ -23,6 +23,7 @@ - - #include "WinSystemX11GL.h" - #include "utils/log.h" -+#include "Application.h" - - CWinSystemX11GL::CWinSystemX11GL() - { -@@ -245,17 +246,25 @@ bool CWinSystemX11GL::CreateNewWindow(const CStdString& name, bool fullScreen, R - - bool CWinSystemX11GL::ResizeWindow(int newWidth, int newHeight, int newLeft, int newTop) - { -+ m_newGlContext = false; - CWinSystemX11::ResizeWindow(newWidth, newHeight, newLeft, newTop); - CRenderSystemGL::ResetRenderSystem(newWidth, newHeight, false, 0); - -+ if (m_newGlContext) -+ g_application.ReloadSkin(); -+ - return true; - } - - bool CWinSystemX11GL::SetFullScreen(bool fullScreen, RESOLUTION_INFO& res, bool blankOtherDisplays) - { -+ m_newGlContext = false; - CWinSystemX11::SetFullScreen(fullScreen, res, blankOtherDisplays); - CRenderSystemGL::ResetRenderSystem(res.iWidth, res.iHeight, fullScreen, res.fRefreshRate); - -+ if (m_newGlContext) -+ g_application.ReloadSkin(); -+ - return true; - } - --- -1.7.10 - - -From 72196d5e8e45d884bf9ac03d7050d29ced2b3aeb Mon Sep 17 00:00:00 2001 -From: FernetMenta -Date: Thu, 5 Jul 2012 12:06:25 +0200 -Subject: [PATCH 47/88] X11: hook video reference clock in windowing - ---- - xbmc/video/VideoReferenceClock.cpp | 71 ++++++++++++++++++++++++++---------- - xbmc/video/VideoReferenceClock.h | 13 ++++++- - 2 files changed, 63 insertions(+), 21 deletions(-) - -diff --git a/xbmc/video/VideoReferenceClock.cpp b/xbmc/video/VideoReferenceClock.cpp -index 0004e07..fa8e35a 100644 ---- a/xbmc/video/VideoReferenceClock.cpp -+++ b/xbmc/video/VideoReferenceClock.cpp -@@ -135,12 +135,23 @@ - m_Context = NULL; - m_pixmap = None; - m_glPixmap = None; -- m_RREventBase = 0; - m_UseNvSettings = true; - m_bIsATI = false; - #endif - } - -+CVideoReferenceClock::~CVideoReferenceClock() -+{ -+#if defined(HAS_GLX) -+ // some ATI voodoo, if we don't close the display, we crash on exit -+ if (m_Dpy) -+ { -+ XCloseDisplay(m_Dpy); -+ m_Dpy = NULL; -+ } -+#endif -+} -+ - void CVideoReferenceClock::Process() - { - bool SetupSuccess = false; -@@ -151,6 +162,10 @@ void CVideoReferenceClock::Process() - m_D3dCallback.Reset(); - g_Windowing.Register(&m_D3dCallback); - #endif -+#if defined(HAS_GLX) && defined(HAS_XRANDR) -+ g_Windowing.Register(this); -+ m_xrrEvent = false; -+#endif - - while(!m_bStop) - { -@@ -211,6 +226,16 @@ void CVideoReferenceClock::Process() - //clean up the vblank clock - #if defined(HAS_GLX) && defined(HAS_XRANDR) - CleanupGLX(); -+ if (m_xrrEvent) -+ { -+ m_releaseEvent.Set(); -+ while (!m_bStop) -+ { -+ if (m_resetEvent.WaitMSec(100)) -+ break; -+ } -+ m_xrrEvent = false; -+ } - #elif defined(_WIN32) && defined(HAS_DX) - CleanupD3D(); - #elif defined(TARGET_DARWIN) -@@ -222,6 +247,9 @@ void CVideoReferenceClock::Process() - #if defined(_WIN32) && defined(HAS_DX) - g_Windowing.Unregister(&m_D3dCallback); - #endif -+#if defined(HAS_GLX) -+ g_Windowing.Unregister(this); -+#endif - } - - bool CVideoReferenceClock::WaitStarted(int MSecs) -@@ -231,6 +259,24 @@ bool CVideoReferenceClock::WaitStarted(int MSecs) - } - - #if defined(HAS_GLX) && defined(HAS_XRANDR) -+ -+void CVideoReferenceClock::OnLostDevice() -+{ -+ if (!m_xrrEvent) -+ { -+ m_releaseEvent.Reset(); -+ m_resetEvent.Reset(); -+ m_xrrEvent = true; -+ m_releaseEvent.Wait(); -+ } -+} -+ -+void CVideoReferenceClock::OnResetDevice() -+{ -+ m_xrrEvent = false; -+ m_resetEvent.Set(); -+} -+ - bool CVideoReferenceClock::SetupGLX() - { - int singleBufferAttributes[] = { -@@ -382,10 +428,6 @@ bool CVideoReferenceClock::SetupGLX() - return false; - } - -- //set up receiving of RandR events, we'll get one when the refreshrate changes -- XRRQueryExtension(m_Dpy, &m_RREventBase, &ReturnV); -- XRRSelectInput(m_Dpy, g_Windowing.GetWindow(), RRScreenChangeNotifyMask); -- - UpdateRefreshrate(true); //forced refreshrate update - m_MissedVblanks = 0; - -@@ -586,6 +628,9 @@ void CVideoReferenceClock::RunGLX() - - while(!m_bStop) - { -+ if (m_xrrEvent) -+ return; -+ - //wait for the next vblank - if (!m_bIsATI) - { -@@ -649,7 +694,6 @@ void CVideoReferenceClock::RunGLX() - UpdateClock((int)(VblankCount - PrevVblankCount), true); - SingleLock.Leave(); - SendVblankSignal(); -- UpdateRefreshrate(); - IsReset = false; - } - else if (!m_bStop) -@@ -1186,23 +1230,10 @@ bool CVideoReferenceClock::UpdateRefreshrate(bool Forced /*= false*/) - - #if defined(HAS_GLX) && defined(HAS_XRANDR) - -- //check for RandR events -- bool GotEvent = Forced || m_RefreshChanged == 2; -- XEvent Event; -- while (XCheckTypedEvent(m_Dpy, m_RREventBase + RRScreenChangeNotify, &Event)) -- { -- if (Event.type == m_RREventBase + RRScreenChangeNotify) -- { -- CLog::Log(LOGDEBUG, "CVideoReferenceClock: Received RandR event %i", Event.type); -- GotEvent = true; -- } -- XRRUpdateConfiguration(&Event); -- } -- - if (!Forced) - m_RefreshChanged = 0; - -- if (!GotEvent) //refreshrate did not change -+ if (!Forced) //refreshrate did not change - return false; - - //the refreshrate can be wrong on nvidia drivers, so read it from nvidia-settings when it's available -diff --git a/xbmc/video/VideoReferenceClock.h b/xbmc/video/VideoReferenceClock.h -index dcc4f09..7eb6317 100644 ---- a/xbmc/video/VideoReferenceClock.h -+++ b/xbmc/video/VideoReferenceClock.h -@@ -30,6 +30,7 @@ - #include - #include - #include -+ #include "guilib/DispResource.h" - #elif defined(_WIN32) && defined(HAS_DX) - #include - #include "guilib/D3DResource.h" -@@ -56,9 +57,13 @@ class CD3DCallback : public ID3DResource - #endif - - class CVideoReferenceClock : public CThread -+#if defined(HAS_GLX) && defined(HAS_XRANDR) -+ ,public IDispResource -+#endif - { - public: - CVideoReferenceClock(); -+ virtual ~CVideoReferenceClock(); - - int64_t GetTime(bool interpolated = true); - int64_t GetFrequency(); -@@ -75,6 +80,11 @@ class CVideoReferenceClock : public CThread - void VblankHandler(int64_t nowtime, double fps); - #endif - -+#if defined(HAS_GLX) && defined(HAS_XRANDR) -+ virtual void OnLostDevice(); -+ virtual void OnResetDevice(); -+#endif -+ - private: - void Process(); - bool UpdateRefreshrate(bool Forced = false); -@@ -121,7 +131,8 @@ class CVideoReferenceClock : public CThread - GLXContext m_Context; - Pixmap m_pixmap; - GLXPixmap m_glPixmap; -- int m_RREventBase; -+ bool m_xrrEvent; -+ CEvent m_releaseEvent, m_resetEvent; - - bool m_UseNvSettings; - bool m_bIsATI; --- -1.7.10 - - -From ee2f6f0a246b6b684192ee30cb2cd0e5ac1300cf Mon Sep 17 00:00:00 2001 -From: xbmc -Date: Thu, 21 Jun 2012 17:26:51 +0200 -Subject: [PATCH 48/88] X11: fix video calibrations - ---- - xbmc/settings/Settings.cpp | 1 + - xbmc/windowing/WinSystem.h | 1 + - xbmc/windowing/X11/WinSystemX11.cpp | 36 ++++++++++++++++++++++++++++++++++- - xbmc/windowing/X11/WinSystemX11.h | 1 + - 4 files changed, 38 insertions(+), 1 deletion(-) - -diff --git a/xbmc/settings/Settings.cpp b/xbmc/settings/Settings.cpp -index 8a430ad..fde6e4e 100644 ---- a/xbmc/settings/Settings.cpp -+++ b/xbmc/settings/Settings.cpp -@@ -55,6 +55,7 @@ - #include "filesystem/File.h" - #include "filesystem/DirectoryCache.h" - #include "DatabaseManager.h" -+#include "windowing/WindowingFactory.h" - - using namespace std; - using namespace XFILE; -diff --git a/xbmc/windowing/WinSystem.h b/xbmc/windowing/WinSystem.h -index 05c5eda..852d085 100644 ---- a/xbmc/windowing/WinSystem.h -+++ b/xbmc/windowing/WinSystem.h -@@ -100,6 +100,7 @@ class CWinSystemBase - std::vector ScreenResolutions(int screen); - std::vector RefreshRates(int screen, int width, int height, uint32_t dwFlags); - REFRESHRATE DefaultRefreshRate(int screen, std::vector rates); -+ virtual bool HasCalibration(const RESOLUTION_INFO &resInfo) { return true; }; - - protected: - void UpdateDesktopResolution(RESOLUTION_INFO& newRes, int screen, int width, int height, float refreshRate, uint32_t dwFlags = 0); -diff --git a/xbmc/windowing/X11/WinSystemX11.cpp b/xbmc/windowing/X11/WinSystemX11.cpp -index d3d15e2..487b324 100644 ---- a/xbmc/windowing/X11/WinSystemX11.cpp -+++ b/xbmc/windowing/X11/WinSystemX11.cpp -@@ -320,7 +320,7 @@ void CWinSystemX11::UpdateResolutions() - res.strMode.Format("%s: %s @ %.2fHz", out->name.c_str(), mode.name.c_str(), mode.hz); - res.strOutput = out->name; - res.strId = mode.id; -- res.iSubtitles = (int)(0.95*mode.h); -+ res.iSubtitles = (int)(0.965*mode.h); - res.fRefreshRate = mode.hz; - res.bFullScreen = true; - -@@ -333,8 +333,42 @@ void CWinSystemX11::UpdateResolutions() - g_settings.m_ResInfo.push_back(res); - } - } -+ g_settings.ApplyCalibrations(); - #endif -+} -+ -+bool CWinSystemX11::HasCalibration(const RESOLUTION_INFO &resInfo) -+{ -+ XOutput *out = g_xrandr.GetOutput(m_currentOutput); -+ -+ // keep calibrations done on a not connected output -+ if (!out->name.Equals(resInfo.strOutput)) -+ return true; -+ -+ // keep calibrations not updated with resolution data -+ if (resInfo.iWidth == 0) -+ return true; -+ -+ float fPixRatio; -+ if (resInfo.iHeight>0 && resInfo.iWidth>0 && out->hmm>0 && out->wmm>0) -+ fPixRatio = ((float)out->wmm/(float)resInfo.iWidth) / (((float)out->hmm/(float)resInfo.iHeight)); -+ else -+ fPixRatio = 1.0f; - -+ if (resInfo.Overscan.left != 0) -+ return true; -+ if (resInfo.Overscan.top != 0) -+ return true; -+ if (resInfo.Overscan.right != resInfo.iWidth) -+ return true; -+ if (resInfo.Overscan.bottom != resInfo.iHeight) -+ return true; -+ if (resInfo.fPixelRatio != fPixRatio) -+ return true; -+ if (resInfo.iSubtitles != (int)(0.965*resInfo.iHeight)) -+ return true; -+ -+ return false; - } - - void CWinSystemX11::GetConnectedOutputs(std::vector *outputs) -diff --git a/xbmc/windowing/X11/WinSystemX11.h b/xbmc/windowing/X11/WinSystemX11.h -index cc28f56..c046c86 100644 ---- a/xbmc/windowing/X11/WinSystemX11.h -+++ b/xbmc/windowing/X11/WinSystemX11.h -@@ -61,6 +61,7 @@ class CWinSystemX11 : public CWinSystemBase - virtual bool Show(bool raise = true); - virtual void Register(IDispResource *resource); - virtual void Unregister(IDispResource *resource); -+ virtual bool HasCalibration(const RESOLUTION_INFO &resInfo); - - // Local to WinSystemX11 only - Display* GetDisplay() { return m_dpy; } --- -1.7.10 - - -From e4f883d19e247bde088178c96ab3dbb21b7be61d Mon Sep 17 00:00:00 2001 -From: FernetMenta -Date: Thu, 5 Jul 2012 12:00:26 +0200 -Subject: [PATCH 49/88] X11: deactivate screen saver on startup - ---- - xbmc/windowing/X11/WinSystemX11.cpp | 29 +++++++++++++++++++++++++++++ - xbmc/windowing/X11/WinSystemX11.h | 1 + - 2 files changed, 30 insertions(+) - -diff --git a/xbmc/windowing/X11/WinSystemX11.cpp b/xbmc/windowing/X11/WinSystemX11.cpp -index 487b324..b3e7ab5 100644 ---- a/xbmc/windowing/X11/WinSystemX11.cpp -+++ b/xbmc/windowing/X11/WinSystemX11.cpp -@@ -521,6 +521,33 @@ void CWinSystemX11::ResetOSScreensaver() - } - } - -+void CWinSystemX11::EnableSystemScreenSaver(bool bEnable) -+{ -+ if (!m_dpy) -+ return; -+ -+ if (bEnable) -+ XForceScreenSaver(m_dpy, ScreenSaverActive); -+ else -+ { -+ Window root_return, child_return; -+ int root_x_return, root_y_return; -+ int win_x_return, win_y_return; -+ unsigned int mask_return; -+ bool isInWin = XQueryPointer(m_dpy, RootWindow(m_dpy, m_nScreen), &root_return, &child_return, -+ &root_x_return, &root_y_return, -+ &win_x_return, &win_y_return, -+ &mask_return); -+ -+ XWarpPointer(m_dpy, None, RootWindow(m_dpy, m_nScreen), 0, 0, 0, 0, root_x_return+300, root_y_return+300); -+ XSync(m_dpy, FALSE); -+ XWarpPointer(m_dpy, None, RootWindow(m_dpy, m_nScreen), 0, 0, 0, 0, 0, 0); -+ XSync(m_dpy, FALSE); -+ XWarpPointer(m_dpy, None, RootWindow(m_dpy, m_nScreen), 0, 0, 0, 0, root_x_return, root_y_return); -+ XSync(m_dpy, FALSE); -+ } -+} -+ - void CWinSystemX11::NotifyAppActiveChange(bool bActivated) - { - if (bActivated && m_bWasFullScreenBeforeMinimize && !m_bFullScreen) -@@ -764,6 +791,8 @@ bool CWinSystemX11::SetWindow(int width, int height, bool fullscreen, const CStd - // create main window - if (!m_glWindow) - { -+ EnableSystemScreenSaver(false); -+ - GLint att[] = - { - GLX_RGBA, -diff --git a/xbmc/windowing/X11/WinSystemX11.h b/xbmc/windowing/X11/WinSystemX11.h -index c046c86..e953d2d 100644 ---- a/xbmc/windowing/X11/WinSystemX11.h -+++ b/xbmc/windowing/X11/WinSystemX11.h -@@ -51,6 +51,7 @@ class CWinSystemX11 : public CWinSystemBase - virtual void ShowOSMouse(bool show); - virtual void ResetOSScreensaver(); - virtual bool EnableFrameLimiter(); -+ virtual void EnableSystemScreenSaver(bool bEnable); - - virtual void NotifyAppActiveChange(bool bActivated); - virtual void NotifyAppFocusChange(bool bGaining); --- -1.7.10 - - -From 9143044b7d7469751143fda07a5d960403bac8f9 Mon Sep 17 00:00:00 2001 -From: FernetMenta -Date: Thu, 5 Jul 2012 12:10:09 +0200 -Subject: [PATCH 50/88] X11: change method of going full-screen - ---- - xbmc/windowing/X11/WinSystemX11.cpp | 9 ++++++++- - 1 file changed, 8 insertions(+), 1 deletion(-) - -diff --git a/xbmc/windowing/X11/WinSystemX11.cpp b/xbmc/windowing/X11/WinSystemX11.cpp -index b3e7ab5..91f92c1 100644 ---- a/xbmc/windowing/X11/WinSystemX11.cpp -+++ b/xbmc/windowing/X11/WinSystemX11.cpp -@@ -34,6 +34,7 @@ - #include "utils/TimeUtils.h" - #include "settings/GUISettings.h" - #include "windowing/WindowingFactory.h" -+#include - - #if defined(HAS_XRANDR) - #include -@@ -816,7 +817,7 @@ bool CWinSystemX11::SetWindow(int width, int height, bool fullscreen, const CStd - cmap = XCreateColormap(m_dpy, RootWindow(m_dpy, vi->screen), vi->visual, AllocNone); - - int def_vis = (vi->visual == DefaultVisual(m_dpy, vi->screen)); -- swa.override_redirect = fullscreen ? True : False; -+ swa.override_redirect = False; - swa.border_pixel = fullscreen ? 0 : 5; - swa.background_pixel = def_vis ? BlackPixel(m_dpy, vi->screen) : 0; - swa.colormap = cmap; -@@ -832,6 +833,12 @@ bool CWinSystemX11::SetWindow(int width, int height, bool fullscreen, const CStd - InputOutput, vi->visual, - mask, &swa); - -+ if (fullscreen) -+ { -+ Atom fs = XInternAtom(m_dpy, "_NET_WM_STATE_FULLSCREEN", True); -+ XChangeProperty(m_dpy, m_glWindow, XInternAtom(m_dpy, "_NET_WM_STATE", True), XA_ATOM, 32, PropModeReplace, (unsigned char *) &fs, 1); -+ } -+ - // define invisible cursor - Pixmap bitmapNoData; - XColor black; --- -1.7.10 - - -From e9c03d83ef43d874283b9dab8de57601fa610419 Mon Sep 17 00:00:00 2001 -From: xbmc -Date: Thu, 28 Jun 2012 19:12:39 +0200 -Subject: [PATCH 51/88] X11: reset key repeat and key modifier on focus lost - and gain - ---- - xbmc/windowing/WinEventsX11.cpp | 3 +++ - 1 file changed, 3 insertions(+) - -diff --git a/xbmc/windowing/WinEventsX11.cpp b/xbmc/windowing/WinEventsX11.cpp -index 6c22358..d86205d 100644 ---- a/xbmc/windowing/WinEventsX11.cpp -+++ b/xbmc/windowing/WinEventsX11.cpp -@@ -359,6 +359,8 @@ bool CWinEventsX11::MessagePump() - if (WinEvents->m_xic) - XSetICFocus(WinEvents->m_xic); - g_application.m_AppFocused = true; -+ memset(&(WinEvents->m_lastKey), 0, sizeof(XBMC_Event)); -+ WinEvents->m_keymodState = 0; - if (serial == xevent.xfocus.serial) - break; - g_Windowing.NotifyAppFocusChange(g_application.m_AppFocused); -@@ -370,6 +372,7 @@ bool CWinEventsX11::MessagePump() - if (WinEvents->m_xic) - XUnsetICFocus(WinEvents->m_xic); - g_application.m_AppFocused = false; -+ memset(&(WinEvents->m_lastKey), 0, sizeof(XBMC_Event)); - g_Windowing.NotifyAppFocusChange(g_application.m_AppFocused); - serial = xevent.xfocus.serial; - break; --- -1.7.10 - - -From b0fca2b5347e07513a16932875d5384d32eaae57 Mon Sep 17 00:00:00 2001 -From: Joakim Plate -Date: Thu, 5 Jul 2012 14:18:46 +0200 -Subject: [PATCH 52/88] X11: replace custom utf8 to unicode with charset - convertor (squash to x11 events) - ---- - xbmc/windowing/WinEventsX11.cpp | 119 ++++----------------------------------- - xbmc/windowing/WinEventsX11.h | 2 - - 2 files changed, 11 insertions(+), 110 deletions(-) - -diff --git a/xbmc/windowing/WinEventsX11.cpp b/xbmc/windowing/WinEventsX11.cpp -index d86205d..76702e6 100644 ---- a/xbmc/windowing/WinEventsX11.cpp -+++ b/xbmc/windowing/WinEventsX11.cpp -@@ -32,6 +32,7 @@ - #include "X11/keysymdef.h" - #include "X11/XF86keysym.h" - #include "utils/log.h" -+#include "utils/CharsetConverter.h" - #include "guilib/GUIWindowManager.h" - #include "input/MouseStat.h" - -@@ -161,7 +162,6 @@ - m_display = 0; - m_window = 0; - m_keybuf = 0; -- m_utf16buf = 0; - } - - CWinEventsX11::~CWinEventsX11() -@@ -172,12 +172,6 @@ - m_keybuf = 0; - } - -- if (m_utf16buf) -- { -- free(m_utf16buf); -- m_utf16buf = 0; -- } -- - if (m_xic) - { - XUnsetICFocus(m_xic); -@@ -203,7 +197,6 @@ bool CWinEventsX11::Init(Display *dpy, Window win) - WinEvents->m_display = dpy; - WinEvents->m_window = win; - WinEvents->m_keybuf = (char*)malloc(32*sizeof(char)); -- WinEvents->m_utf16buf = (uint16_t*)malloc(32*sizeof(uint16_t)); - WinEvents->m_keymodState = 0; - WinEvents->m_wmDeleteMessage = XInternAtom(dpy, "WM_DELETE_WINDOW", False); - WinEvents->m_structureChanged = false; -@@ -433,8 +426,6 @@ bool CWinEventsX11::MessagePump() - } - - Status status; -- int utf16size; -- int utf16length; - int len; - len = Xutf8LookupString(WinEvents->m_xic, &xevent.xkey, - WinEvents->m_keybuf, sizeof(WinEvents->m_keybuf), -@@ -453,36 +444,29 @@ bool CWinEventsX11::MessagePump() - case XLookupChars: - case XLookupBoth: - { -- if (len == 0) -- break; -- utf16size = len * sizeof(uint16_t); -- if (utf16size > sizeof(WinEvents->m_utf16buf)) -- { -- WinEvents->m_utf16buf = (uint16_t *)realloc(WinEvents->m_utf16buf,utf16size); -- if (WinEvents->m_utf16buf == NULL) -- { -- break; -- } -- } -- utf16length = Utf8ToUnicode(WinEvents->m_keybuf, len, WinEvents->m_utf16buf, utf16size); -- if (utf16length < 0) -+ CStdString data(WinEvents->m_keybuf, len); -+ CStdStringW keys; -+ g_charsetConverter.utf8ToW(data, keys, false); -+ -+ if (keys.length() == 0) - { - break; - } -- for (unsigned int i = 0; i < utf16length - 1; i++) -+ -+ for (unsigned int i = 0; i < keys.length() - 1; i++) - { - newEvent.key.keysym.sym = XBMCK_UNKNOWN; -- newEvent.key.keysym.unicode = WinEvents->m_utf16buf[i]; -+ newEvent.key.keysym.unicode = keys[i]; - newEvent.key.state = xevent.xkey.state; - newEvent.key.type = xevent.xkey.type; - ret |= ProcessKey(newEvent, 500); - } -- if (utf16length > 0) -+ if (keys.length() > 0) - { - newEvent.key.keysym.scancode = xevent.xkey.keycode; - xkeysym = XLookupKeysym(&xevent.xkey, 0); - newEvent.key.keysym.sym = LookupXbmcKeySym(xkeysym); -- newEvent.key.keysym.unicode = WinEvents->m_utf16buf[utf16length - 1]; -+ newEvent.key.keysym.unicode = keys[keys.length() - 1]; - newEvent.key.state = xevent.xkey.state; - newEvent.key.type = xevent.xkey.type; - -@@ -743,87 +727,6 @@ bool CWinEventsX11::ProcessKeyRepeat() - return false; - } - --int CWinEventsX11::Utf8ToUnicode(const char *utf8, const int utf8Length, uint16_t *utf16, const int utf16MaxLength) --{ -- // p moves over the output buffer. max_ptr points to the next to the last slot of the buffer. -- uint16_t *p = utf16; -- uint16_t const *const maxPtr = utf16 + utf16MaxLength; -- -- // end_of_input points to the last byte of input as opposed to the next to the last byte. -- char const *const endOfInput = utf8 + utf8Length - 1; -- -- while (utf8 <= endOfInput) -- { -- unsigned char const c = *utf8; -- if (p >= maxPtr) -- { -- //No more output space. -- return -1; -- } -- if (c < 0x80) -- { -- //One byte ASCII. -- *p++ = c; -- utf8 += 1; -- } -- else if (c < 0xC0) -- { -- // Follower byte without preceding leader bytes. -- return -1; -- } -- // 11 bits -- else if (c < 0xE0) -- { -- // Two byte sequence. We need one follower byte. -- if (endOfInput - utf8 < 1 || (((utf8[1] ^ 0x80)) & 0xC0)) -- { -- return -1; -- } -- *p++ = (uint16_t)(((c & 0x1F) << 6) + (utf8[1] & 0x3F)); -- utf8 += 2; -- } -- // 16 bis -- else if (c < 0xF0) -- { -- // Three byte sequence. We need two follower byte. -- if (endOfInput - utf8 < 2 || ((utf8[1] ^ 0x80) & 0xC0) || ((utf8[2] ^ 0x80) & 0xC0)) -- { -- return -1; -- } -- *p++ = (uint16_t)(((c & 0xF) << 12) + ((utf8[1] & 0x3F) << 6) + (utf8[2] & 0x3F)); -- utf8 += 3; -- } -- // 21 bits -- else if (c < 0xF8) -- { -- int plane; -- // Four byte sequence. We need three follower bytes. -- if (endOfInput - utf8 < 3 || ((utf8[1] ^ 0x80) & 0xC0) || -- ((utf8[2] ^ 0x80) & 0xC0) || ((utf8[3] ^ 0x80) & 0xC0)) -- { -- return -1; -- } -- uint32_t unicode = ((c & 0x7) << 18) + ((utf8[1] & 0x3F) << 12) + -- ((utf8[2] & 0x3F) << 6) + (utf8[3] & 0x3F); -- utf8 += 4; -- CLog::Log(LOGERROR, "CWinEventsX11::Utf8ToUnicode: 4 byte unicode not supported"); -- } -- // 26 bits -- else if (c < 0xFC) -- { -- CLog::Log(LOGERROR, "CWinEventsX11::Utf8ToUnicode: 4 byte unicode not supported"); -- utf8 += 5; -- } -- // 31 bit -- else -- { -- CLog::Log(LOGERROR, "CWinEventsX11::Utf8ToUnicode: 4 byte unicode not supported"); -- utf8 += 6; -- } -- } -- return p - utf16; --} -- - XBMCKey CWinEventsX11::LookupXbmcKeySym(KeySym keysym) - { - // try direct mapping first -diff --git a/xbmc/windowing/WinEventsX11.h b/xbmc/windowing/WinEventsX11.h -index 6100933..72955ad 100644 ---- a/xbmc/windowing/WinEventsX11.h -+++ b/xbmc/windowing/WinEventsX11.h -@@ -38,7 +38,6 @@ class CWinEventsX11 : public CWinEventsBase - static bool MessagePump(); - - protected: -- static int Utf8ToUnicode(const char *utf8, const int utf8Length, uint16_t *utf16, const int utf16MaxLength); - static XBMCKey LookupXbmcKeySym(KeySym keysym); - static bool ProcessKey(XBMC_Event &event, int repeatDelay); - static bool ProcessKeyRepeat(); -@@ -48,7 +47,6 @@ class CWinEventsX11 : public CWinEventsBase - Window m_window; - Atom m_wmDeleteMessage; - char *m_keybuf; -- uint16_t *m_utf16buf; - XIM m_xim; - XIC m_xic; - XBMC_Event m_lastKey; --- -1.7.10 - - -From c93af676cf85551e3f4325808d17098da3bc6811 Mon Sep 17 00:00:00 2001 -From: Joakim Plate -Date: Thu, 5 Jul 2012 14:23:54 +0200 -Subject: [PATCH 53/88] X11: fixed invalid usage of sizeof() (squash into x11 - changes) - ---- - xbmc/windowing/WinEventsX11.cpp | 11 +++++++---- - xbmc/windowing/WinEventsX11.h | 1 + - 2 files changed, 8 insertions(+), 4 deletions(-) - -diff --git a/xbmc/windowing/WinEventsX11.cpp b/xbmc/windowing/WinEventsX11.cpp -index 76702e6..c31877e 100644 ---- a/xbmc/windowing/WinEventsX11.cpp -+++ b/xbmc/windowing/WinEventsX11.cpp -@@ -162,6 +162,7 @@ - m_display = 0; - m_window = 0; - m_keybuf = 0; -+ m_keybuf_len = 0; - } - - CWinEventsX11::~CWinEventsX11() -@@ -196,7 +197,8 @@ bool CWinEventsX11::Init(Display *dpy, Window win) - WinEvents = new CWinEventsX11(); - WinEvents->m_display = dpy; - WinEvents->m_window = win; -- WinEvents->m_keybuf = (char*)malloc(32*sizeof(char)); -+ WinEvents->m_keybuf_len = 32*sizeof(char); -+ WinEvents->m_keybuf = (char*)malloc(WinEvents->m_keybuf_len); - WinEvents->m_keymodState = 0; - WinEvents->m_wmDeleteMessage = XInternAtom(dpy, "WM_DELETE_WINDOW", False); - WinEvents->m_structureChanged = false; -@@ -428,13 +430,14 @@ bool CWinEventsX11::MessagePump() - Status status; - int len; - len = Xutf8LookupString(WinEvents->m_xic, &xevent.xkey, -- WinEvents->m_keybuf, sizeof(WinEvents->m_keybuf), -+ WinEvents->m_keybuf, WinEvents->m_keybuf_len, - &xkeysym, &status); - if (status == XBufferOverflow) - { -- WinEvents->m_keybuf = (char*)realloc(WinEvents->m_keybuf, len*sizeof(char)); -+ WinEvents->m_keybuf_len = len; -+ WinEvents->m_keybuf = (char*)realloc(WinEvents->m_keybuf, WinEvents->m_keybuf_len); - len = Xutf8LookupString(WinEvents->m_xic, &xevent.xkey, -- WinEvents->m_keybuf, sizeof(WinEvents->m_keybuf), -+ WinEvents->m_keybuf, WinEvents->m_keybuf_len, - &xkeysym, &status); - } - switch (status) -diff --git a/xbmc/windowing/WinEventsX11.h b/xbmc/windowing/WinEventsX11.h -index 72955ad..102a076 100644 ---- a/xbmc/windowing/WinEventsX11.h -+++ b/xbmc/windowing/WinEventsX11.h -@@ -47,6 +47,7 @@ class CWinEventsX11 : public CWinEventsBase - Window m_window; - Atom m_wmDeleteMessage; - char *m_keybuf; -+ size_t m_keybuf_len; - XIM m_xim; - XIC m_xic; - XBMC_Event m_lastKey; --- -1.7.10 - - -From 04106be4cdf381658ae92bf20bc468ccad12fb31 Mon Sep 17 00:00:00 2001 -From: xbmc -Date: Sat, 9 Jun 2012 18:23:53 +0200 -Subject: [PATCH 54/88] add missing keys to xbmc keytable - ---- - xbmc/input/XBMC_keytable.cpp | 2 ++ - 1 file changed, 2 insertions(+) - -diff --git a/xbmc/input/XBMC_keytable.cpp b/xbmc/input/XBMC_keytable.cpp -index aaf65ba..9d7922f 100644 ---- a/xbmc/input/XBMC_keytable.cpp -+++ b/xbmc/input/XBMC_keytable.cpp -@@ -179,6 +179,8 @@ - , { XBMCK_LAUNCH_APP2, 0, 0, XBMCVK_LAUNCH_APP2, "launch_app2_pc_icon" } - , { XBMCK_LAUNCH_FILE_BROWSER, 0, 0, XBMCVK_LAUNCH_FILE_BROWSER, "launch_file_browser" } - , { XBMCK_LAUNCH_MEDIA_CENTER, 0, 0, XBMCVK_LAUNCH_MEDIA_CENTER, "launch_media_center" } -+, { XBMCK_PLAY, 0, 0, XBMCVK_MEDIA_PLAY_PAUSE, "play_pause" } -+, { XBMCK_STOP, 0, 0, XBMCVK_MEDIA_STOP, "stop" } - - // Function keys - , { XBMCK_F1, 0, 0, XBMCVK_F1, "f1"} --- -1.7.10 - - -From fb35e45063cf476573ad09c3bed7459164d03066 Mon Sep 17 00:00:00 2001 -From: xbmc -Date: Fri, 16 Mar 2012 15:57:51 +0100 -Subject: [PATCH 55/88] videorefclock: temp deactivate of nv settings - ---- - xbmc/video/VideoReferenceClock.cpp | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/xbmc/video/VideoReferenceClock.cpp b/xbmc/video/VideoReferenceClock.cpp -index fa8e35a..85e36c7 100644 ---- a/xbmc/video/VideoReferenceClock.cpp -+++ b/xbmc/video/VideoReferenceClock.cpp -@@ -135,7 +135,7 @@ - m_Context = NULL; - m_pixmap = None; - m_glPixmap = None; -- m_UseNvSettings = true; -+ m_UseNvSettings = false; - m_bIsATI = false; - #endif - } --- -1.7.10 - - -From 5e10bc67e7b0dffbbf9b7d8242fb78e8cef2403f Mon Sep 17 00:00:00 2001 -From: xbmc -Date: Mon, 20 Aug 2012 09:09:09 +0200 -Subject: [PATCH 56/88] videorefclock: ask graphics context for refresh rate - ---- - xbmc/video/VideoReferenceClock.cpp | 3 ++- - 1 file changed, 2 insertions(+), 1 deletion(-) - -diff --git a/xbmc/video/VideoReferenceClock.cpp b/xbmc/video/VideoReferenceClock.cpp -index 85e36c7..8209163 100644 ---- a/xbmc/video/VideoReferenceClock.cpp -+++ b/xbmc/video/VideoReferenceClock.cpp -@@ -30,6 +30,7 @@ - #include - #include - #include "windowing/WindowingFactory.h" -+ #include "guilib/GraphicContext.h" - #define NVSETTINGSCMD "nvidia-settings -nt -q RefreshRate3" - #elif defined(TARGET_DARWIN_OSX) - #include -@@ -1254,7 +1255,7 @@ bool CVideoReferenceClock::UpdateRefreshrate(bool Forced /*= false*/) - } - - CSingleLock SingleLock(m_CritSection); -- m_RefreshRate = GetRandRRate(); -+ m_RefreshRate = MathUtils::round_int(g_graphicsContext.GetFPS()); - - CLog::Log(LOGDEBUG, "CVideoReferenceClock: Detected refreshrate: %i hertz", (int)m_RefreshRate); - --- -1.7.10 - - -From aed9e87986eb99f21a7cafc6a356a4044b41becc Mon Sep 17 00:00:00 2001 -From: xbmc -Date: Mon, 9 Jul 2012 14:00:18 +0200 -Subject: [PATCH 57/88] X11: fix icon texture after - cc5ed3c2474084ebc0373a3046410e6f766e03f4 - ---- - xbmc/windowing/X11/WinSystemX11.cpp | 43 +++++++++++++++++++++-------------- - 1 file changed, 26 insertions(+), 17 deletions(-) - -diff --git a/xbmc/windowing/X11/WinSystemX11.cpp b/xbmc/windowing/X11/WinSystemX11.cpp -index 91f92c1..174ccef 100644 ---- a/xbmc/windowing/X11/WinSystemX11.cpp -+++ b/xbmc/windowing/X11/WinSystemX11.cpp -@@ -874,22 +874,24 @@ bool CWinSystemX11::SetWindow(int width, int height, bool fullscreen, const CStd - if (!fullscreen) - { - CreateIconPixmap(); -- XWMHints wm_hints; -- XClassHint class_hints; -+ XWMHints *wm_hints; - XTextProperty windowName, iconName; - std::string titleString = "XBMC Media Center"; - char *title = (char*)titleString.c_str(); - - XStringListToTextProperty(&title, 1, &windowName); - XStringListToTextProperty(&title, 1, &iconName); -- wm_hints.initial_state = NormalState; -- wm_hints.input = True; -- wm_hints.icon_pixmap = m_icon; -- wm_hints.flags = StateHint | IconPixmapHint | InputHint; - -+ wm_hints = XAllocWMHints(); -+ wm_hints->initial_state = NormalState; -+ wm_hints->icon_pixmap = m_icon; -+ wm_hints->flags = StateHint | IconPixmapHint; -+ -+ XSync(m_dpy,False); - XSetWMProperties(m_dpy, m_glWindow, &windowName, &iconName, -- NULL, 0, NULL, &wm_hints, -+ NULL, 0, NULL, wm_hints, - NULL); -+ XFree(wm_hints); - - // register interest in the delete window message - Atom wmDeleteMessage = XInternAtom(m_dpy, "WM_DELETE_WINDOW", False); -@@ -974,16 +976,21 @@ bool CWinSystemX11::CreateIconPixmap() - gRatio = vis->green_mask / 255.0; - bRatio = vis->blue_mask / 255.0; - -- CTexture iconTexture; -- iconTexture.LoadFromFile("special://xbmc/media/icon.png"); -- buf = iconTexture.GetPixels(); -+ CBaseTexture *iconTexture = CBaseTexture::LoadFromFile("special://xbmc/media/icon.png"); -+ -+ if (!iconTexture) -+ return false; - -- numBufBytes = iconTexture.GetWidth() * iconTexture.GetHeight() * 4; -+ buf = iconTexture->GetPixels(); -+ -+ numBufBytes = iconTexture->GetWidth() * iconTexture->GetHeight() * 4; -+ int wid = iconTexture->GetWidth(); -+ int hi = iconTexture->GetHeight(); - - if (depth>=24) -- numNewBufBytes = (4 * (iconTexture.GetWidth() * iconTexture.GetHeight())); -+ numNewBufBytes = (4 * (iconTexture->GetWidth() * iconTexture->GetHeight())); - else -- numNewBufBytes = (2 * (iconTexture.GetWidth() * iconTexture.GetHeight())); -+ numNewBufBytes = (2 * (iconTexture->GetWidth() * iconTexture->GetHeight())); - - newBuf = (uint32_t*)malloc(numNewBufBytes); - if (!newBuf) -@@ -992,11 +999,11 @@ bool CWinSystemX11::CreateIconPixmap() - return false; - } - -- for (i=0; iGetHeight();++i) - { -- for (j=0; jGetWidth();++j) - { -- unsigned int pos = i*iconTexture.GetPitch()+j*4; -+ unsigned int pos = i*iconTexture->GetPitch()+j*4; - unsigned int r, g, b; - r = (buf[pos+2] * rRatio); - g = (buf[pos+1] * gRatio); -@@ -1009,7 +1016,7 @@ bool CWinSystemX11::CreateIconPixmap() - } - } - img = XCreateImage(m_dpy, vis, depth,ZPixmap, 0, (char *)newBuf, -- iconTexture.GetWidth(), iconTexture.GetHeight(), -+ iconTexture->GetWidth(), iconTexture->GetHeight(), - (depth>=24)?32:16, 0); - if (!img) - { -@@ -1047,6 +1054,8 @@ bool CWinSystemX11::CreateIconPixmap() - XFreeGC(m_dpy, gc); - XDestroyImage(img); // this also frees newBuf - -+ delete iconTexture; -+ - return true; - } - --- -1.7.10 - - -From 7c4464b9114e5eba42c1cc1fce0cfe750ec44eba Mon Sep 17 00:00:00 2001 -From: xbmc -Date: Tue, 10 Jul 2012 11:14:12 +0200 -Subject: [PATCH 58/88] X11: check for window manager - ---- - xbmc/windowing/X11/WinSystemX11.cpp | 74 ++++++++++++++++++++++++++++++++++- - xbmc/windowing/X11/WinSystemX11.h | 1 + - 2 files changed, 73 insertions(+), 2 deletions(-) - -diff --git a/xbmc/windowing/X11/WinSystemX11.cpp b/xbmc/windowing/X11/WinSystemX11.cpp -index 174ccef..4f1ae26 100644 ---- a/xbmc/windowing/X11/WinSystemX11.cpp -+++ b/xbmc/windowing/X11/WinSystemX11.cpp -@@ -816,8 +816,10 @@ bool CWinSystemX11::SetWindow(int width, int height, bool fullscreen, const CStd - vi = glXChooseVisual(m_dpy, m_nScreen, att); - cmap = XCreateColormap(m_dpy, RootWindow(m_dpy, vi->screen), vi->visual, AllocNone); - -+ bool hasWM = HasWindowManager(); -+ - int def_vis = (vi->visual == DefaultVisual(m_dpy, vi->screen)); -- swa.override_redirect = False; -+ swa.override_redirect = hasWM ? False : True; - swa.border_pixel = fullscreen ? 0 : 5; - swa.background_pixel = def_vis ? BlackPixel(m_dpy, vi->screen) : 0; - swa.colormap = cmap; -@@ -833,7 +835,7 @@ bool CWinSystemX11::SetWindow(int width, int height, bool fullscreen, const CStd - InputOutput, vi->visual, - mask, &swa); - -- if (fullscreen) -+ if (fullscreen && hasWM) - { - Atom fs = XInternAtom(m_dpy, "_NET_WM_STATE_FULLSCREEN", True); - XChangeProperty(m_dpy, m_glWindow, XInternAtom(m_dpy, "_NET_WM_STATE", True), XA_ATOM, 32, PropModeReplace, (unsigned char *) &fs, 1); -@@ -1059,4 +1061,72 @@ bool CWinSystemX11::CreateIconPixmap() - return true; - } - -+bool CWinSystemX11::HasWindowManager() -+{ -+ Window wm_check; -+ unsigned char *data; -+ int status, real_format; -+ Atom real_type, prop; -+ unsigned long items_read, items_left, i; -+ char req = 0; -+ -+ prop = XInternAtom(m_dpy, "_NET_SUPPORTING_WM_CHECK", True); -+ if (prop == None) -+ return false; -+ status = XGetWindowProperty(m_dpy, DefaultRootWindow(m_dpy), prop, -+ 0L, 1L, False, XA_WINDOW, &real_type, &real_format, -+ &items_read, &items_left, &data); -+ if(status != Success || ! items_read) -+ { -+ if(status == Success) -+ XFree(data); -+ return false; -+ } -+ -+ wm_check = ((Window*)data)[0]; -+ XFree(data); -+ -+ status = XGetWindowProperty(m_dpy, wm_check, prop, -+ 0L, 1L, False, XA_WINDOW, &real_type, &real_format, -+ &items_read, &items_left, &data); -+ -+ if(status != Success || !items_read) -+ { -+ if(status == Success) -+ XFree(data); -+ return false; -+ } -+ -+ if(wm_check != ((Window*)data)[0]) -+ { -+ XFree(data); -+ return false; -+ } -+ -+ XFree(data); -+ -+ prop = XInternAtom(m_dpy, "_NET_WM_NAME", True); -+ if (prop == None) -+ { -+ CLog::Log(LOGDEBUG,"Window Manager Name: "); -+ return true; -+ } -+ -+ status = XGetWindowProperty(m_dpy, wm_check, prop, -+ 0L, (~0L), False, AnyPropertyType, &real_type, &real_format, -+ &items_read, &items_left, &data); -+ -+ if(status == Success && items_read) -+ { -+ CLog::Log(LOGDEBUG,"Window Manager Name: %s", data); -+ } -+ else -+ CLog::Log(LOGDEBUG,"Window Manager Name: "); -+ -+ if(status == Success) -+ XFree(data); -+ -+ return true; -+} -+ - #endif -diff --git a/xbmc/windowing/X11/WinSystemX11.h b/xbmc/windowing/X11/WinSystemX11.h -index e953d2d..0b7c10a 100644 ---- a/xbmc/windowing/X11/WinSystemX11.h -+++ b/xbmc/windowing/X11/WinSystemX11.h -@@ -101,6 +101,7 @@ class CWinSystemX11 : public CWinSystemBase - bool IsSuitableVisual(XVisualInfo *vInfo); - static int XErrorHandler(Display* dpy, XErrorEvent* error); - bool CreateIconPixmap(); -+ bool HasWindowManager(); - - CStopWatch m_screensaverReset; - }; --- -1.7.10 - - -From d156746c8968312db2a60fbcbcbb48029ff0d60a Mon Sep 17 00:00:00 2001 -From: xbmc -Date: Thu, 12 Jul 2012 11:11:47 +0200 -Subject: [PATCH 59/88] X11: dont set window on xrandr if no mode available - ---- - xbmc/windowing/X11/WinSystemX11.cpp | 11 ++++++----- - 1 file changed, 6 insertions(+), 5 deletions(-) - -diff --git a/xbmc/windowing/X11/WinSystemX11.cpp b/xbmc/windowing/X11/WinSystemX11.cpp -index 4f1ae26..c11ea89 100644 ---- a/xbmc/windowing/X11/WinSystemX11.cpp -+++ b/xbmc/windowing/X11/WinSystemX11.cpp -@@ -665,16 +665,17 @@ void CWinSystemX11::NotifyXRREvent() - CLog::Log(LOGDEBUG, "%s - notify display reset event", __FUNCTION__); - m_windowDirty = true; - -+ if (!g_xrandr.Query(true)) -+ { -+ CLog::Log(LOGERROR, "WinSystemX11::RefreshWindow - failed to query xrandr"); -+ return; -+ } -+ - // if external event update resolutions - if (!m_bIsInternalXrr) - { - UpdateResolutions(); - } -- else if (!g_xrandr.Query(true)) -- { -- CLog::Log(LOGERROR, "WinSystemX11::RefreshWindow - failed to query xrandr"); -- return; -- } - m_bIsInternalXrr = false; - - CStdString currentOutput = g_guiSettings.GetString("videoscreen.monitor"); --- -1.7.10 - - -From 7da277793b15d9cbd5dcaf27dc7fee2fb3dde945 Mon Sep 17 00:00:00 2001 -From: xbmc -Date: Thu, 26 Jul 2012 09:34:28 +0200 -Subject: [PATCH 60/88] X11: fix crash after a resolution change on startup - ---- - xbmc/windowing/X11/WinSystemX11.cpp | 3 ++- - 1 file changed, 2 insertions(+), 1 deletion(-) - -diff --git a/xbmc/windowing/X11/WinSystemX11.cpp b/xbmc/windowing/X11/WinSystemX11.cpp -index c11ea89..0bd72d4 100644 ---- a/xbmc/windowing/X11/WinSystemX11.cpp -+++ b/xbmc/windowing/X11/WinSystemX11.cpp -@@ -219,7 +219,8 @@ bool CWinSystemX11::SetFullScreen(bool fullScreen, RESOLUTION_INFO& res, bool bl - OnLostDevice(); - m_bIsInternalXrr = true; - g_xrandr.SetMode(out, mode); -- return true; -+ if (m_glWindow) -+ return true; - } - #endif - --- -1.7.10 - - -From 31d401e7052f2e3d03e4c78bccc05909d870e5a6 Mon Sep 17 00:00:00 2001 -From: xbmc -Date: Sat, 15 Sep 2012 18:27:29 +0200 -Subject: [PATCH 61/88] X11: lock graphics context in NotifyXRREvent - ---- - xbmc/windowing/X11/WinSystemX11.cpp | 2 ++ - 1 file changed, 2 insertions(+) - -diff --git a/xbmc/windowing/X11/WinSystemX11.cpp b/xbmc/windowing/X11/WinSystemX11.cpp -index 0bd72d4..ef83133 100644 ---- a/xbmc/windowing/X11/WinSystemX11.cpp -+++ b/xbmc/windowing/X11/WinSystemX11.cpp -@@ -666,6 +666,8 @@ void CWinSystemX11::NotifyXRREvent() - CLog::Log(LOGDEBUG, "%s - notify display reset event", __FUNCTION__); - m_windowDirty = true; - -+ CSingleLock lock(g_graphicsContext); -+ - if (!g_xrandr.Query(true)) - { - CLog::Log(LOGERROR, "WinSystemX11::RefreshWindow - failed to query xrandr"); --- -1.7.10 - - -From b2cd5ea5e38446dc54b73cf2f6a82072add474f1 Mon Sep 17 00:00:00 2001 -From: Rainer Hochecker -Date: Sat, 8 Oct 2011 16:45:13 +0200 -Subject: [PATCH 62/88] ffmpeg: add xvba hwaccel - ---- - lib/ffmpeg/configure | 8 ++ - lib/ffmpeg/libavcodec/Makefile | 7 +- - lib/ffmpeg/libavcodec/allcodecs.c | 4 + - lib/ffmpeg/libavcodec/h264.c | 1 + - lib/ffmpeg/libavcodec/mpegvideo.c | 1 + - lib/ffmpeg/libavcodec/xvba.c | 66 +++++++++++ - lib/ffmpeg/libavcodec/xvba.h | 71 ++++++++++++ - lib/ffmpeg/libavcodec/xvba_h264.c | 195 +++++++++++++++++++++++++++++++++ - lib/ffmpeg/libavcodec/xvba_internal.h | 24 ++++ - lib/ffmpeg/libavcodec/xvba_mpeg2.c | 52 +++++++++ - lib/ffmpeg/libavcodec/xvba_vc1.c | 190 ++++++++++++++++++++++++++++++++ - lib/ffmpeg/libavcodec/xvmc_internal.h | 4 +- - lib/ffmpeg/libavutil/pixdesc.c | 6 + - lib/ffmpeg/libavutil/pixfmt.h | 1 + - 14 files changed, 628 insertions(+), 2 deletions(-) - create mode 100644 lib/ffmpeg/libavcodec/xvba.c - create mode 100644 lib/ffmpeg/libavcodec/xvba.h - create mode 100644 lib/ffmpeg/libavcodec/xvba_h264.c - create mode 100644 lib/ffmpeg/libavcodec/xvba_internal.h - create mode 100644 lib/ffmpeg/libavcodec/xvba_mpeg2.c - create mode 100644 lib/ffmpeg/libavcodec/xvba_vc1.c - -diff --git a/lib/ffmpeg/configure b/lib/ffmpeg/configure -index c06005b..157cfd3 100755 ---- a/lib/ffmpeg/configure -+++ b/lib/ffmpeg/configure -@@ -113,6 +113,7 @@ Configuration options: - --enable-vdpau enable VDPAU code [autodetect] - --disable-dxva2 disable DXVA2 code - --disable-vda disable VDA code -+ --disable-xvba disable XVBA code - --enable-runtime-cpudetect detect cpu capabilities at runtime (bigger binary) - --enable-hardcoded-tables use hardcoded tables instead of runtime generation - --disable-safe-bitstream-reader -@@ -1084,6 +1085,7 @@ CONFIG_LIST=" - vaapi - vda - vdpau -+ xvba - version3 - x11grab - zlib -@@ -1423,6 +1425,7 @@ h264_dxva2_hwaccel_select="dxva2 h264_decoder" - h264_vaapi_hwaccel_select="vaapi h264_decoder" - h264_vda_hwaccel_deps="VideoDecodeAcceleration_VDADecoder_h pthreads" - h264_vda_hwaccel_select="vda h264_decoder" -+h264_xvba_hwaccel_select="xvba h264_decoder" - h264_vdpau_decoder_select="vdpau h264_decoder" - imc_decoder_select="fft mdct sinewin" - jpegls_decoder_select="golomb" -@@ -1459,6 +1462,7 @@ mpeg4_crystalhd_decoder_select="crystalhd" - mpeg4_decoder_select="h263_decoder mpeg4video_parser" - mpeg4_encoder_select="h263_encoder" - mpeg4_vaapi_hwaccel_select="vaapi mpeg4_decoder" -+mpeg2_xvba_hwaccel_select="xvba mpeg2video_decoder" - mpeg4_vdpau_decoder_select="vdpau mpeg4_decoder" - msmpeg4_crystalhd_decoder_select="crystalhd" - msmpeg4v1_decoder_select="h263_decoder" -@@ -1501,6 +1505,7 @@ vc1_decoder_select="h263_decoder h264chroma" - vc1_dxva2_hwaccel_deps="dxva2api_h" - vc1_dxva2_hwaccel_select="dxva2 vc1_decoder" - vc1_vaapi_hwaccel_select="vaapi vc1_decoder" -+vc1_xvba_hwaccel_select="xvba vc1_decoder" - vc1_vdpau_decoder_select="vdpau vc1_decoder" - vc1image_decoder_select="vc1_decoder" - vorbis_decoder_select="mdct" -@@ -1525,6 +1530,7 @@ wmv3_dxva2_hwaccel_select="vc1_dxva2_hwaccel" - wmv3_vaapi_hwaccel_select="vc1_vaapi_hwaccel" - wmv3_vdpau_decoder_select="vc1_vdpau_decoder" - wmv3image_decoder_select="wmv3_decoder" -+wmv3_xvba_hwaccel_select="vc1_xvba_hwaccel" - zlib_decoder_select="zlib" - zlib_encoder_select="zlib" - zmbv_decoder_select="zlib" -@@ -1533,6 +1539,7 @@ zmbv_encoder_select="zlib" - crystalhd_deps="libcrystalhd_libcrystalhd_if_h" - vaapi_deps="va_va_h" - vda_deps="VideoDecodeAcceleration_VDADecoder_h pthreads" -+xvba_deps="amd_amdxvba_h" - vdpau_deps="vdpau_vdpau_h vdpau_vdpau_x11_h" - - # parsers -@@ -3062,6 +3069,7 @@ check_header sys/select.h - check_header termios.h - check_header vdpau/vdpau.h - check_header vdpau/vdpau_x11.h -+check_header amd/amdxvba.h - check_cpp_condition vdpau/vdpau.h "defined(VDP_DECODER_PROFILE_MPEG4_PART2_SP)" && enable vdpau_mpeg4_support - - check_header X11/extensions/XvMClib.h -diff --git a/lib/ffmpeg/libavcodec/Makefile b/lib/ffmpeg/libavcodec/Makefile -index 972cc59..fc441bf 100644 ---- a/lib/ffmpeg/libavcodec/Makefile -+++ b/lib/ffmpeg/libavcodec/Makefile -@@ -3,7 +3,7 @@ include $(SUBDIR)../config.mak - NAME = avcodec - FFLIBS = avutil - --HEADERS = avcodec.h avfft.h dxva2.h opt.h vaapi.h vda.h vdpau.h version.h xvmc.h -+HEADERS = avcodec.h avfft.h dxva2.h opt.h vaapi.h vda.h vdpau.h version.h xvmc.h xvba.h - - OBJS = allcodecs.o \ - audioconvert.o \ -@@ -51,6 +51,7 @@ OBJS-$(CONFIG_SINEWIN) += sinewin.o - OBJS-$(CONFIG_VAAPI) += vaapi.o - OBJS-$(CONFIG_VDA) += vda.o - OBJS-$(CONFIG_VDPAU) += vdpau.o -+OBJS-$(CONFIG_XVBA) += xvba.o - - # decoders/encoders/hardware accelerators - OBJS-$(CONFIG_A64MULTI_ENCODER) += a64multienc.o elbg.o -@@ -201,6 +202,7 @@ OBJS-$(CONFIG_H264_DECODER) += h264.o \ - OBJS-$(CONFIG_H264_DXVA2_HWACCEL) += dxva2_h264.o - OBJS-$(CONFIG_H264_VAAPI_HWACCEL) += vaapi_h264.o - OBJS-$(CONFIG_H264_VDA_HWACCEL) += vda_h264.o -+OBJS-$(CONFIG_H264_XVBA_HWACCEL) += xvba_h264.o - OBJS-$(CONFIG_HUFFYUV_DECODER) += huffyuv.o - OBJS-$(CONFIG_HUFFYUV_ENCODER) += huffyuv.o - OBJS-$(CONFIG_IDCIN_DECODER) += idcinvideo.o -@@ -284,6 +286,7 @@ OBJS-$(CONFIG_MPEG1VIDEO_ENCODER) += mpeg12enc.o mpegvideo_enc.o \ - mpegvideo.o error_resilience.o - OBJS-$(CONFIG_MPEG2_DXVA2_HWACCEL) += dxva2_mpeg2.o - OBJS-$(CONFIG_MPEG2_VAAPI_HWACCEL) += vaapi_mpeg2.o -+OBJS-$(CONFIG_MPEG2_XVBA_HWACCEL) += xvba_mpeg2.o - OBJS-$(CONFIG_MPEG2VIDEO_DECODER) += mpeg12.o mpeg12data.o \ - mpegvideo.o error_resilience.o - OBJS-$(CONFIG_MPEG2VIDEO_ENCODER) += mpeg12enc.o mpegvideo_enc.o \ -@@ -431,6 +434,7 @@ OBJS-$(CONFIG_VC1_DECODER) += vc1dec.o vc1.o vc1data.o vc1dsp.o \ - intrax8.o intrax8dsp.o - OBJS-$(CONFIG_VC1_DXVA2_HWACCEL) += dxva2_vc1.o - OBJS-$(CONFIG_VC1_VAAPI_HWACCEL) += vaapi_vc1.o -+OBJS-$(CONFIG_VC1_XVBA_HWACCEL) += xvba_vc1.o - OBJS-$(CONFIG_VCR1_DECODER) += vcr1.o - OBJS-$(CONFIG_VCR1_ENCODER) += vcr1.o - OBJS-$(CONFIG_VMDAUDIO_DECODER) += vmdav.o -@@ -732,6 +736,7 @@ SKIPHEADERS-$(CONFIG_LIBDIRAC) += libdirac.h - SKIPHEADERS-$(CONFIG_LIBSCHROEDINGER) += libschroedinger.h - SKIPHEADERS-$(CONFIG_VAAPI) += vaapi_internal.h - SKIPHEADERS-$(CONFIG_VDA) += vda_internal.h -+SKIPHEADERS-$(CONFIG_XVBA) += xvba_internal.h - SKIPHEADERS-$(CONFIG_VDPAU) += vdpau.h - SKIPHEADERS-$(CONFIG_XVMC) += xvmc.h - SKIPHEADERS-$(HAVE_W32THREADS) += w32pthreads.h -diff --git a/lib/ffmpeg/libavcodec/allcodecs.c b/lib/ffmpeg/libavcodec/allcodecs.c -index 32f3f52..0ff178e 100644 ---- a/lib/ffmpeg/libavcodec/allcodecs.c -+++ b/lib/ffmpeg/libavcodec/allcodecs.c -@@ -59,14 +59,18 @@ void avcodec_register_all(void) - REGISTER_HWACCEL (H264_VAAPI, h264_vaapi); - REGISTER_HWACCEL (H264_VDA, h264_vda); - REGISTER_HWACCEL (MPEG1_VDPAU, mpeg1_vdpau); -+ REGISTER_HWACCEL (H264_XVBA, h264_xvba); - REGISTER_HWACCEL (MPEG2_DXVA2, mpeg2_dxva2); - REGISTER_HWACCEL (MPEG2_VAAPI, mpeg2_vaapi); - REGISTER_HWACCEL (MPEG2_VDPAU, mpeg2_vdpau); - REGISTER_HWACCEL (MPEG4_VAAPI, mpeg4_vaapi); -+ REGISTER_HWACCEL (MPEG2_XVBA, mpeg2_xvba); - REGISTER_HWACCEL (VC1_DXVA2, vc1_dxva2); - REGISTER_HWACCEL (VC1_VAAPI, vc1_vaapi); -+ REGISTER_HWACCEL (VC1_XVBA, vc1_xvba); - REGISTER_HWACCEL (WMV3_DXVA2, wmv3_dxva2); - REGISTER_HWACCEL (WMV3_VAAPI, wmv3_vaapi); -+ REGISTER_HWACCEL (WMV3_XVBA, wmv3_xvba); - - /* video codecs */ - REGISTER_ENCODER (A64MULTI, a64multi); -diff --git a/lib/ffmpeg/libavcodec/h264.c b/lib/ffmpeg/libavcodec/h264.c -index c4785db..e9e7546 100644 ---- a/lib/ffmpeg/libavcodec/h264.c -+++ b/lib/ffmpeg/libavcodec/h264.c -@@ -60,6 +60,7 @@ - PIX_FMT_DXVA2_VLD, - PIX_FMT_VAAPI_VLD, - PIX_FMT_VDA_VLD, -+ PIX_FMT_XVBA_VLD, - PIX_FMT_YUVJ420P, - PIX_FMT_NONE - }; -diff --git a/lib/ffmpeg/libavcodec/mpegvideo.c b/lib/ffmpeg/libavcodec/mpegvideo.c -index 04c149a..b22b631 100644 ---- a/lib/ffmpeg/libavcodec/mpegvideo.c -+++ b/lib/ffmpeg/libavcodec/mpegvideo.c -@@ -136,6 +136,7 @@ static void dct_unquantize_h263_inter_c(MpegEncContext *s, - PIX_FMT_DXVA2_VLD, - PIX_FMT_VAAPI_VLD, - PIX_FMT_VDA_VLD, -+ PIX_FMT_XVBA_VLD, - PIX_FMT_YUV420P, - PIX_FMT_NONE - }; -diff --git a/lib/ffmpeg/libavcodec/xvba.c b/lib/ffmpeg/libavcodec/xvba.c -new file mode 100644 -index 0000000..be29e5d ---- /dev/null -+++ b/lib/ffmpeg/libavcodec/xvba.c -@@ -0,0 +1,66 @@ -+/* -+ * HW decode acceleration for MPEG-2, H.264 and VC-1 -+ * -+ * Copyright (C) 2005-2011 Team XBMC -+ * -+ * This file is part of FFmpeg. -+ * -+ * FFmpeg is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU Lesser General Public -+ * License as published by the Free Software Foundation; either -+ * version 2.1 of the License, or (at your option) any later version. -+ * -+ * FFmpeg 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 -+ * Lesser General Public License for more details. -+ * -+ * You should have received a copy of the GNU Lesser General Public -+ * License along with FFmpeg; if not, write to the Free Software -+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA -+ */ -+ -+ -+/** -+ * \addtogroup XVBA_Decoding -+ * -+ * @{ -+ */ -+ -+#include -+#include "xvba.h" -+#include "xvba_internal.h" -+#include "avcodec.h" -+ -+int ff_xvba_translate_profile(int profile) { -+ -+ if (profile == 66) -+ return 1; -+ else if (profile == 77) -+ return 2; -+ else if (profile == 100) -+ return 3; -+ else if (profile == 0) -+ return 4; -+ else if (profile == 1) -+ return 5; -+ else if (profile == 3) -+ return 6; -+ else -+ return -1; -+} -+ -+void ff_xvba_add_slice_data(struct xvba_render_state *render, const uint8_t *buffer, uint32_t size) { -+ -+ render->buffers = av_fast_realloc( -+ render->buffers, -+ &render->buffers_alllocated, -+ sizeof(struct xvba_bitstream_buffers)*(render->num_slices + 1) -+ ); -+ -+ render->buffers[render->num_slices].buffer = buffer; -+ render->buffers[render->num_slices].size = size; -+ -+ render->num_slices++; -+} -+ -diff --git a/lib/ffmpeg/libavcodec/xvba.h b/lib/ffmpeg/libavcodec/xvba.h -new file mode 100644 -index 0000000..9f9ff0c ---- /dev/null -+++ b/lib/ffmpeg/libavcodec/xvba.h -@@ -0,0 +1,71 @@ -+/* -+ * HW decode acceleration for MPEG-2, H.264 and VC-1 -+ * -+ * Copyright (C) 2005-2011 Team XBMC -+ * -+ * This file is part of FFmpeg. -+ * -+ * FFmpeg is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU Lesser General Public -+ * License as published by the Free Software Foundation; either -+ * version 2.1 of the License, or (at your option) any later version. -+ * -+ * FFmpeg 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 -+ * Lesser General Public License for more details. -+ * -+ * You should have received a copy of the GNU Lesser General Public -+ * License along with FFmpeg; if not, write to the Free Software -+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA -+ */ -+ -+#ifndef AVCODEC_XVBA_H -+#define AVCODEC_XVBA_H -+ -+#include -+#include -+#include -+ -+ -+/** -+ * \defgroup XVBA_Decoding VA API Decoding -+ * \ingroup Decoder -+ * @{ -+ */ -+ -+/** \brief The videoSurface is used for rendering. */ -+#define FF_XVBA_STATE_USED_FOR_RENDER 1 -+ -+/** -+ * \brief The videoSurface is needed for reference/prediction. -+ * The codec manipulates this. -+ */ -+#define FF_XVBA_STATE_USED_FOR_REFERENCE 2 -+ -+/** -+ * \brief The videoSurface holds a decoded frame. -+ * The codec manipulates this. -+ */ -+#define FF_XVBA_STATE_DECODED 4 -+ -+/* @} */ -+ -+struct xvba_bitstream_buffers -+{ -+ const void *buffer; -+ unsigned int size; -+}; -+ -+struct xvba_render_state { -+ -+ int state; ///< Holds FF_XVBA_STATE_* values. -+ void *surface; -+ XVBAPictureDescriptor *picture_descriptor; -+ XVBAQuantMatrixAvc *iq_matrix; -+ unsigned int num_slices; -+ struct xvba_bitstream_buffers *buffers; -+ uint32_t buffers_alllocated; -+}; -+ -+#endif /* AVCODEC_XVBA_H */ -diff --git a/lib/ffmpeg/libavcodec/xvba_h264.c b/lib/ffmpeg/libavcodec/xvba_h264.c -new file mode 100644 -index 0000000..87af687 ---- /dev/null -+++ b/lib/ffmpeg/libavcodec/xvba_h264.c -@@ -0,0 +1,195 @@ -+/* -+ * H.264 HW decode acceleration through XVBA -+ * -+ * Copyright (C) 2005-2011 Team XBMC -+ * -+ * This file is part of FFmpeg. -+ * -+ * FFmpeg is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU Lesser General Public -+ * License as published by the Free Software Foundation; either -+ * version 2.1 of the License, or (at your option) any later version. -+ * -+ * FFmpeg 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 -+ * Lesser General Public License for more details. -+ * -+ * You should have received a copy of the GNU Lesser General Public -+ * License along with FFmpeg; if not, write to the Free Software -+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA -+ */ -+ -+#include "xvba.h" -+#include "xvba_internal.h" -+#include "h264.h" -+#include -+ -+/** @file -+ * This file implements the glue code between FFmpeg's and XvBA API's -+ * structures for H.264 decoding. -+ */ -+ -+ -+/** Initialize and start decoding a frame with XVBA. */ -+static int start_frame(AVCodecContext *avctx, -+ av_unused const uint8_t *buffer, -+ av_unused uint32_t size) -+{ -+ H264Context * const h = avctx->priv_data; -+ MpegEncContext * const s = &h->s; -+ struct xvba_render_state *render; -+ XVBAPictureDescriptor *pic_descriptor; -+ int i; -+ -+ render = (struct xvba_render_state *)s->current_picture_ptr->f.data[0]; -+ assert(render); -+ -+ if (render->picture_descriptor == 0) -+ return -1; -+ -+ pic_descriptor = render->picture_descriptor; -+ -+ for (i = 0; i < 2; ++i) { -+ int foc = s->current_picture_ptr->field_poc[i]; -+ if (foc == INT_MAX) -+ foc = 0; -+ pic_descriptor->avc_curr_field_order_cnt_list[i] = foc; -+ } -+ -+ pic_descriptor->avc_frame_num = h->frame_num; -+ -+ render->num_slices = 0; -+ -+ return 0; -+} -+ -+/** End a hardware decoding based frame. */ -+static int end_frame(AVCodecContext *avctx) -+{ -+ H264Context * const h = avctx->priv_data; -+ MpegEncContext * const s = &h->s; -+ struct xvba_render_state *render; -+ XVBAPictureDescriptor *pic_descriptor; -+ XVBAQuantMatrixAvc *iq_matrix; -+ -+ render = (struct xvba_render_state *)s->current_picture_ptr->f.data[0]; -+ assert(render); -+ -+ if (render->picture_descriptor == 0 || render->iq_matrix == 0) -+ return -1; -+ -+ pic_descriptor = render->picture_descriptor; -+ iq_matrix = render->iq_matrix; -+ -+ av_dlog(avctx, "end_frame()\n"); -+ -+ /* Fill in Picture Parameters*/ -+ pic_descriptor->profile = ff_xvba_translate_profile(avctx->profile); -+ pic_descriptor->level = avctx->level; -+ pic_descriptor->width_in_mb = s->mb_width; -+ pic_descriptor->height_in_mb = s->mb_height; -+ pic_descriptor->picture_structure = s->picture_structure; -+ pic_descriptor->chroma_format = s->chroma_format ? s->chroma_format : 1; -+ pic_descriptor->avc_intra_flag = (h->slice_type == AV_PICTURE_TYPE_I) ? 1 : 0; -+ pic_descriptor->avc_reference = (s->current_picture_ptr->f.reference & 3) ? 1 : 0; -+ -+ pic_descriptor->avc_bit_depth_luma_minus8 = h->sps.bit_depth_luma - 8; -+ pic_descriptor->avc_bit_depth_chroma_minus8 = h->sps.bit_depth_chroma - 8; -+ pic_descriptor->avc_log2_max_frame_num_minus4 = h->sps.log2_max_frame_num -4; -+ pic_descriptor->avc_pic_order_cnt_type = h->sps.poc_type; -+ pic_descriptor->avc_log2_max_pic_order_cnt_lsb_minus4 = h->sps.log2_max_poc_lsb - 4; -+ pic_descriptor->avc_num_ref_frames = h->sps.ref_frame_count; -+ pic_descriptor->avc_reserved_8bit = 0; -+ -+ /* Set a level that can decode stuff in every case without a lookup table -+ xvba seems to have problems only when the number of Reframes goes beyond -+ the max support number of Level4.1@High. So in praxis decoding a Level 3.0 -+ file that in deed has level4.1@High specs does not matter. We use this fact -+ and check if the ref_frames stay in the range Level4.1@high can decode if -+ not, we set Level5.1 */ -+ if (pic_descriptor->avc_num_ref_frames > 4) { -+ const unsigned int mbw = pic_descriptor->width_in_mb; -+ const unsigned int mbh = pic_descriptor->height_in_mb; -+ // this matches Level4.1@High stats to differ between <= 4.1 and 5.1 -+ const unsigned int max_ref_frames = 12288 * 1024 / (mbw * mbh * 384); -+ const unsigned int num_ref_frames = pic_descriptor->avc_num_ref_frames; -+ if (max_ref_frames < num_ref_frames) -+ pic_descriptor->level = 51; -+ } -+ -+ pic_descriptor->avc_num_slice_groups_minus1 = h->pps.slice_group_count - 1; -+ pic_descriptor->avc_num_ref_idx_l0_active_minus1 = h->pps.ref_count[0] - 1; -+ pic_descriptor->avc_num_ref_idx_l1_active_minus1 = h->pps.ref_count[1] - 1; -+ -+ pic_descriptor->avc_pic_init_qp_minus26 = h->pps.init_qp - 26; -+ pic_descriptor->avc_pic_init_qs_minus26 = h->pps.init_qs - 26; -+ pic_descriptor->avc_chroma_qp_index_offset = h->pps.chroma_qp_index_offset[0]; -+ pic_descriptor->avc_second_chroma_qp_index_offset = h->pps.chroma_qp_index_offset[1]; -+ pic_descriptor->avc_slice_group_change_rate_minus1 = 0; // not implemented in ffmpeg -+ pic_descriptor->avc_reserved_16bit = 0; // must be 0 -+ memset(pic_descriptor->avc_field_order_cnt_list,0,sizeof(pic_descriptor->avc_field_order_cnt_list)); // must be 0 -+ memset(pic_descriptor->avc_slice_group_map,0,sizeof(pic_descriptor->avc_slice_group_map)); // must be 0 -+ -+ // sps -+ pic_descriptor->sps_info.avc.delta_pic_always_zero_flag = h->sps.delta_pic_order_always_zero_flag; -+ pic_descriptor->sps_info.avc.direct_8x8_inference_flag = h->sps.direct_8x8_inference_flag; -+ pic_descriptor->sps_info.avc.frame_mbs_only_flag = h->sps.frame_mbs_only_flag; -+ pic_descriptor->sps_info.avc.gaps_in_frame_num_value_allowed_flag = h->sps.gaps_in_frame_num_allowed_flag; -+ pic_descriptor->sps_info.avc.mb_adaptive_frame_field_flag = h->sps.mb_aff; -+ pic_descriptor->sps_info.avc.residual_colour_transform_flag = h->sps.residual_color_transform_flag; -+ pic_descriptor->sps_info.avc.xvba_avc_sps_reserved = 0; -+ -+ // pps -+ pic_descriptor->pps_info.avc.entropy_coding_mode_flag = h->pps.cabac; -+ pic_descriptor->pps_info.avc.pic_order_present_flag = h->pps.pic_order_present; -+ pic_descriptor->pps_info.avc.weighted_pred_flag = h->pps.weighted_pred; -+ pic_descriptor->pps_info.avc.weighted_bipred_idc = h->pps.weighted_bipred_idc; -+ pic_descriptor->pps_info.avc.deblocking_filter_control_present_flag = h->pps.deblocking_filter_parameters_present; -+ pic_descriptor->pps_info.avc.constrained_intra_pred_flag = h->pps.constrained_intra_pred; -+ pic_descriptor->pps_info.avc.redundant_pic_cnt_present_flag = h->pps.redundant_pic_cnt_present; -+ pic_descriptor->pps_info.avc.transform_8x8_mode_flag = h->pps.transform_8x8_mode; -+ pic_descriptor->pps_info.avc.xvba_avc_pps_reserved = 0; // must be 0 -+ -+ memcpy(iq_matrix->bScalingLists4x4, h->pps.scaling_matrix4, sizeof(iq_matrix->bScalingLists4x4)); -+ memcpy(iq_matrix->bScalingLists8x8[0], h->pps.scaling_matrix8[0], sizeof(iq_matrix->bScalingLists8x8[0])); -+ memcpy(iq_matrix->bScalingLists8x8[1], h->pps.scaling_matrix8[3], sizeof(iq_matrix->bScalingLists8x8[0])); -+ -+ // Wait for an I-frame before start decoding. Workaround for ATI UVD and UVD+ GPUs -+ if (!h->got_first_iframe) { -+ if (h->slice_type != AV_PICTURE_TYPE_I && h->slice_type != AV_PICTURE_TYPE_SI) -+ return -1; -+ h->got_first_iframe = 1; -+ } -+ -+ ff_draw_horiz_band(s, 0, s->avctx->height); -+ -+ return 0; -+} -+ -+/** Decode the given H.264 slice with XVBA. */ -+static int decode_slice(AVCodecContext *avctx, -+ const uint8_t *buffer, -+ uint32_t size) -+{ -+ H264Context * const h = avctx->priv_data; -+ MpegEncContext * const s = &h->s; -+ struct xvba_render_state *render; -+ -+ render = (struct xvba_render_state *)s->current_picture_ptr->f.data[0]; -+ assert(render); -+ -+ ff_xvba_add_slice_data(render, buffer, size); -+ -+ return 0; -+} -+ -+AVHWAccel ff_h264_xvba_hwaccel = { -+ .name = "h264_xvba", -+ .type = AVMEDIA_TYPE_VIDEO, -+ .id = CODEC_ID_H264, -+ .pix_fmt = PIX_FMT_XVBA_VLD, -+ .start_frame = start_frame, -+ .end_frame = end_frame, -+ .decode_slice = decode_slice, -+}; -diff --git a/lib/ffmpeg/libavcodec/xvba_internal.h b/lib/ffmpeg/libavcodec/xvba_internal.h -new file mode 100644 -index 0000000..9653f85 ---- /dev/null -+++ b/lib/ffmpeg/libavcodec/xvba_internal.h -@@ -0,0 +1,24 @@ -+/* -+ * HW decode acceleration for MPEG-2, H.264 and VC-1 -+ * -+ * Copyright (C) 2005-2011 Team XBMC -+ * -+ * This file is part of FFmpeg. -+ * -+ * FFmpeg is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU Lesser General Public -+ * License as published by the Free Software Foundation; either -+ * version 2.1 of the License, or (at your option) any later version. -+ * -+ * FFmpeg 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 -+ * Lesser General Public License for more details. -+ * -+ * You should have received a copy of the GNU Lesser General Public -+ * License along with FFmpeg; if not, write to the Free Software -+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA -+ */ -+ -+int ff_xvba_translate_profile(int profile); -+void ff_xvba_add_slice_data(struct xvba_render_state *render, const uint8_t *buffer, uint32_t size); -diff --git a/lib/ffmpeg/libavcodec/xvba_mpeg2.c b/lib/ffmpeg/libavcodec/xvba_mpeg2.c -new file mode 100644 -index 0000000..552ef95 ---- /dev/null -+++ b/lib/ffmpeg/libavcodec/xvba_mpeg2.c -@@ -0,0 +1,52 @@ -+/* -+ * MPEG-2 HW decode acceleration through XVBA -+ * -+ * Copyright (C) 2005-2011 Team XBMC -+ * -+ * This file is part of FFmpeg. -+ * -+ * FFmpeg is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU Lesser General Public -+ * License as published by the Free Software Foundation; either -+ * version 2.1 of the License, or (at your option) any later version. -+ * -+ * FFmpeg 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 -+ * Lesser General Public License for more details. -+ * -+ * You should have received a copy of the GNU Lesser General Public -+ * License along with FFmpeg; if not, write to the Free Software -+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA -+ */ -+ -+#include "dsputil.h" -+ -+static int start_frame(AVCodecContext *avctx, av_unused const uint8_t *buffer, av_unused uint32_t size) -+{ -+ struct MpegEncContext * const s = avctx->priv_data; -+ return 0; -+} -+ -+static int end_frame(AVCodecContext *avctx) -+{ -+ return 0; -+} -+ -+static int decode_slice(AVCodecContext *avctx, const uint8_t *buffer, uint32_t size) -+{ -+ struct MpegEncContext * const s = avctx->priv_data; -+ return 0; -+} -+ -+AVHWAccel ff_mpeg2_xvba_hwaccel = { -+ .name = "mpeg2_xvba", -+ .type = AVMEDIA_TYPE_VIDEO, -+ .id = CODEC_ID_MPEG2VIDEO, -+ .pix_fmt = PIX_FMT_XVBA_VLD, -+ .capabilities = 0, -+ .start_frame = start_frame, -+ .end_frame = end_frame, -+ .decode_slice = decode_slice, -+ .priv_data_size = 0, -+}; -diff --git a/lib/ffmpeg/libavcodec/xvba_vc1.c b/lib/ffmpeg/libavcodec/xvba_vc1.c -new file mode 100644 -index 0000000..7315b62 ---- /dev/null -+++ b/lib/ffmpeg/libavcodec/xvba_vc1.c -@@ -0,0 +1,190 @@ -+/* -+ * VC-1 HW decode acceleration through XVBA -+ * -+ * Copyright (C) 2005-2011 Team XBMC -+ * -+ * This file is part of FFmpeg. -+ * -+ * FFmpeg is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU Lesser General Public -+ * License as published by the Free Software Foundation; either -+ * version 2.1 of the License, or (at your option) any later version. -+ * -+ * FFmpeg 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 -+ * Lesser General Public License for more details. -+ * -+ * You should have received a copy of the GNU Lesser General Public -+ * License along with FFmpeg; if not, write to the Free Software -+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA -+ */ -+ -+#include "xvba.h" -+#include "xvba_internal.h" -+#include "vc1.h" -+#include "vc1data.h" -+#include -+ -+ -+/** @file -+ * Implement structures of ffmpeg <-> XvBA -+ */ -+ -+/* Initialize and start decoding a frame with XvBA */ -+static int start_frame(AVCodecContext *avctx, -+ av_unused const uint8_t *buffer, -+ av_unused uint32_t size) -+{ -+ VC1Context * const v = avctx->priv_data; -+ MpegEncContext * const s = &v->s; -+ struct xvba_render_state *render; -+ -+ render = (struct xvba_render_state *)s->current_picture_ptr->f.data[0]; -+ assert(render); -+ -+ render->num_slices = 0; -+ return 0; -+} -+ -+/* End a hardware decoding based frame */ -+static int end_frame(AVCodecContext *avctx) -+{ -+ VC1Context* const v = avctx->priv_data; -+ MpegEncContext* const s = &v->s; -+ struct xvba_render_state *render, *last, *next; -+ XVBAPictureDescriptor *pic_descriptor; -+ -+ render = (struct xvba_render_state *)s->current_picture_ptr->f.data[0]; -+ assert(render); -+ -+ if (render->picture_descriptor == 0) -+ return -1; -+ -+ pic_descriptor = render->picture_descriptor; -+ -+ av_dlog(avctx, "xvba_vc1_end_frame()\n"); -+ -+ memset(pic_descriptor, 0, sizeof(*pic_descriptor)); -+ -+ /* Fill in Parameters - for reference see AMD sdk documentation */ -+ pic_descriptor->profile = ff_xvba_translate_profile(v->profile); -+ pic_descriptor->level = v->level; -+ //done like in va-driver and vaapi -+ if (v->profile == PROFILE_ADVANCED) { -+ pic_descriptor->width_in_mb = s->avctx->coded_width; -+ pic_descriptor->height_in_mb = s->avctx->coded_height; -+ } else { -+ pic_descriptor->width_in_mb = s->mb_width; -+ pic_descriptor->height_in_mb = s->mb_height; -+ } -+ pic_descriptor->picture_structure = s->picture_structure; -+ // xvba-video set this to 1 only 4:2:0 supported -+ // doc says: if not set, choose 1 - we try this -+ pic_descriptor->chroma_format = 1; -+ pic_descriptor->avc_intra_flag = s->pict_type == AV_PICTURE_TYPE_I || v->bi_type == 1; -+ pic_descriptor->avc_reference = (s->current_picture_ptr->f.reference & 3) ? 1 : 0; -+ -+ // VC-1 explicit parameters see page 30 of sdk -+ // sps_info -+ pic_descriptor->sps_info.vc1.postprocflag = v->postprocflag; -+ -+ // done as in vaapi -+ pic_descriptor->sps_info.vc1.pulldown = v->broadcast; -+ pic_descriptor->sps_info.vc1.interlace = v->interlace; -+ pic_descriptor->sps_info.vc1.tfcntrflag = v->tfcntrflag; -+ pic_descriptor->sps_info.vc1.finterpflag = v->finterpflag; -+ pic_descriptor->sps_info.vc1.reserved = 1; -+ // eventually check if this makes sense together with interlace -+ pic_descriptor->sps_info.vc1.psf = v->psf; -+ // what about if it is a frame (page 31) -+ // looked at xvba-driver -+ pic_descriptor->sps_info.vc1.second_field = !s->first_field; -+ pic_descriptor->sps_info.vc1.xvba_vc1_sps_reserved = 0; -+ -+ // VC-1 explicit parameters see page 30 of sdk -+ // pps_info -+ pic_descriptor->pps_info.vc1.panscan_flag = v->panscanflag; -+ pic_descriptor->pps_info.vc1.refdist_flag = v->refdist_flag; -+ pic_descriptor->pps_info.vc1.loopfilter = s->loop_filter; -+ pic_descriptor->pps_info.vc1.fastuvmc = v->fastuvmc; -+ pic_descriptor->pps_info.vc1.extended_mv = v->extended_mv; -+ pic_descriptor->pps_info.vc1.dquant = v->dquant; -+ pic_descriptor->pps_info.vc1.vstransform = v->vstransform; -+ pic_descriptor->pps_info.vc1.overlap = v->overlap; -+ pic_descriptor->pps_info.vc1.quantizer = v->quantizer_mode; -+ pic_descriptor->pps_info.vc1.extended_dmv = v->extended_dmv; -+ pic_descriptor->pps_info.vc1.maxbframes = s->avctx->max_b_frames; -+ pic_descriptor->pps_info.vc1.rangered = (pic_descriptor->profile == PROFILE_SIMPLE) ? 0 : v->rangered; -+ pic_descriptor->pps_info.vc1.syncmarker = (pic_descriptor->profile == PROFILE_SIMPLE) ? 0 : s->resync_marker; -+ pic_descriptor->pps_info.vc1.multires = v->multires; -+ pic_descriptor->pps_info.vc1.reserved = 1; -+ pic_descriptor->pps_info.vc1.range_mapy_flag = v->range_mapy_flag; -+ pic_descriptor->pps_info.vc1.range_mapy = v->range_mapy; -+ pic_descriptor->pps_info.vc1.range_mapuv_flag = v->range_mapuv_flag; -+ pic_descriptor->pps_info.vc1.range_mapuv = v->range_mapuv; -+ pic_descriptor->pps_info.vc1.xvba_vc1_pps_reserved = 0; -+ -+ pic_descriptor->past_surface = 0; -+ pic_descriptor->future_surface = 0; -+ switch (s->pict_type) { -+ case AV_PICTURE_TYPE_B: -+ next = (struct xvba_render_state *)s->next_picture.f.data[0]; -+ assert(next); -+ if (next) -+ pic_descriptor->past_surface = next->surface; -+ // fall-through -+ case AV_PICTURE_TYPE_P: -+ last = (struct xvba_render_state *)s->last_picture.f.data[0]; -+ assert(last); -+ if (last) -+ pic_descriptor->future_surface = last->surface; -+ break; -+ } -+ -+ ff_draw_horiz_band(s, 0, s->avctx->height); -+ -+ return 0; -+} -+ -+static int decode_slice(AVCodecContext *avctx, const uint8_t *buffer, uint32_t size) -+{ -+ VC1Context* const v = avctx->priv_data; -+ MpegEncContext* const s = &v->s; -+ struct xvba_render_state *render; -+ -+ render = (struct xvba_render_state *)s->current_picture_ptr->f.data[0]; -+ assert(render); -+ -+ if (avctx->codec_id == CODEC_ID_VC1 && -+ size >= 4 && IS_MARKER(AV_RB32(buffer))) { -+ buffer += 4; -+ size -= 4; -+ } -+ -+ ff_xvba_add_slice_data(render, buffer, size); -+ -+ return 0; -+} -+ -+#if CONFIG_WMV3_XVBA_HWACCEL -+AVHWAccel ff_wmv3_xvba_hwaccel = { -+ .name = "wmv3_xvba", -+ .type = AVMEDIA_TYPE_VIDEO, -+ .id = CODEC_ID_WMV3, -+ .pix_fmt = PIX_FMT_XVBA_VLD, -+ .start_frame = start_frame, -+ .end_frame = end_frame, -+ .decode_slice = decode_slice, -+}; -+#endif -+ -+AVHWAccel ff_vc1_xvba_hwaccel = { -+ .name = "vc1_xvba", -+ .type = AVMEDIA_TYPE_VIDEO, -+ .id = CODEC_ID_VC1, -+ .pix_fmt = PIX_FMT_XVBA_VLD, -+ .start_frame = start_frame, -+ .end_frame = end_frame, -+ .decode_slice = decode_slice, -+}; -diff --git a/lib/ffmpeg/libavcodec/xvmc_internal.h b/lib/ffmpeg/libavcodec/xvmc_internal.h -index 04197ce..d925eb1 100644 ---- a/lib/ffmpeg/libavcodec/xvmc_internal.h -+++ b/lib/ffmpeg/libavcodec/xvmc_internal.h -@@ -1,5 +1,7 @@ - /* -- * XVideo Motion Compensation internal functions -+ * HW decode acceleration for MPEG-2, H.264 and VC-1 -+ * -+ * Copyright (C) 2005-2011 Team XBMC - * - * This file is part of FFmpeg. - * -diff --git a/lib/ffmpeg/libavutil/pixdesc.c b/lib/ffmpeg/libavutil/pixdesc.c -index e73fbfe..5abbd14 100644 ---- a/lib/ffmpeg/libavutil/pixdesc.c -+++ b/lib/ffmpeg/libavutil/pixdesc.c -@@ -874,6 +874,12 @@ void av_write_image_line(const uint16_t *src, uint8_t *data[4], const int linesi - .log2_chroma_h = 1, - .flags = PIX_FMT_HWACCEL, - }, -+ [PIX_FMT_XVBA_VLD] = { -+ .name = "xvba_vld", -+ .log2_chroma_w = 1, -+ .log2_chroma_h = 1, -+ .flags = PIX_FMT_HWACCEL, -+ }, - [PIX_FMT_YUV420P9LE] = { - .name = "yuv420p9le", - .nb_components = 3, -diff --git a/lib/ffmpeg/libavutil/pixfmt.h b/lib/ffmpeg/libavutil/pixfmt.h -index f0d9c01..0f8cf7b 100644 ---- a/lib/ffmpeg/libavutil/pixfmt.h -+++ b/lib/ffmpeg/libavutil/pixfmt.h -@@ -129,6 +129,7 @@ enum PixelFormat { - PIX_FMT_YUV444P16BE, ///< planar YUV 4:4:4, 48bpp, (1 Cr & Cb sample per 1x1 Y samples), big-endian - PIX_FMT_VDPAU_MPEG4, ///< MPEG4 HW decoding with VDPAU, data[0] contains a vdpau_render_state struct which contains the bitstream of the slices as well as various fields extracted from headers - PIX_FMT_DXVA2_VLD, ///< HW decoding through DXVA2, Picture.data[3] contains a LPDIRECT3DSURFACE9 pointer -+ PIX_FMT_XVBA_VLD, ///< HW decoding through DXVA2, Picture.data[3] contains a vaapi_render_state struct which contains the bitstream of the slices as well as various fields extracted from headers - - PIX_FMT_RGB444LE, ///< packed RGB 4:4:4, 16bpp, (msb)4A 4R 4G 4B(lsb), little-endian, most significant bits to 0 - PIX_FMT_RGB444BE, ///< packed RGB 4:4:4, 16bpp, (msb)4A 4R 4G 4B(lsb), big-endian, most significant bits to 0 --- -1.7.10 - - -From bb93e835939fce784f8ad4b2364f174df4ee3978 Mon Sep 17 00:00:00 2001 -From: xbmc -Date: Thu, 12 Apr 2012 12:09:31 +0200 -Subject: [PATCH 63/88] xvba: add decoder - ---- - configure.in | 48 + - language/English/strings.po | 12 +- - xbmc/cores/VideoRenderers/LinuxRendererGL.cpp | 216 +- - xbmc/cores/VideoRenderers/LinuxRendererGL.h | 15 +- - xbmc/cores/VideoRenderers/RenderFormats.h | 1 + - xbmc/cores/VideoRenderers/RenderManager.cpp | 4 + - .../dvdplayer/DVDCodecs/Video/DVDVideoCodec.h | 4 + - .../DVDCodecs/Video/DVDVideoCodecFFmpeg.cpp | 16 + - xbmc/cores/dvdplayer/DVDCodecs/Video/Makefile.in | 4 + - xbmc/cores/dvdplayer/DVDCodecs/Video/XVBA.cpp | 2367 ++++++++++++++++++++ - xbmc/cores/dvdplayer/DVDCodecs/Video/XVBA.h | 382 ++++ - xbmc/cores/dvdplayer/DVDPlayerVideo.cpp | 4 + - xbmc/settings/GUISettings.cpp | 3 + - xbmc/settings/VideoSettings.h | 2 + - xbmc/video/dialogs/GUIDialogVideoSettings.cpp | 1 + - 15 files changed, 3073 insertions(+), 6 deletions(-) - create mode 100644 xbmc/cores/dvdplayer/DVDCodecs/Video/XVBA.cpp - create mode 100644 xbmc/cores/dvdplayer/DVDCodecs/Video/XVBA.h - -diff --git a/configure.in b/configure.in -index 4769315..23439fd 100644 ---- a/configure.in -+++ b/configure.in -@@ -124,6 +124,8 @@ vaapi_not_found="== Could not find libva. VAAPI support disabled. ==" - vaapi_disabled="== VAAPI support manually disabled. ==" - crystalhd_not_found="== Could not find libcrystalhd. CrystalHD support disabled. ==" - crystalhd_disabled="== CrystalHD support manually disabled. ==" -+xvba_not_found="== Could not find amdxvba.h. XVBA support disabled. ==" -+xvba_disabled="== XVBA support manually disabled. ==" - vdadecoder_enabled="== VDADecoder support enabled. ==" - vdadecoder_disabled="== VDADecoder support manually disabled. ==" - vtbdecoder_enabled="== VTBDecoder support enabled. ==" -@@ -247,6 +249,12 @@ AC_ARG_ENABLE([crystalhd], - [enable CrystalHD decoding (default is auto)])], - [use_crystalhd=$enableval], - [use_crystalhd=auto]) -+ -+AC_ARG_ENABLE([xvba], -+ [AS_HELP_STRING([--enable-xvba], -+ [enable XVBA decoding (default is auto)])], -+ [use_xvba=$enableval], -+ [use_xvba=auto]) - - AC_ARG_ENABLE([vdadecoder], - [AS_HELP_STRING([--enable-vdadecoder], -@@ -1751,6 +1759,38 @@ else - USE_CRYSTALHD=0 - fi - -+# XVBA -+if test "x$use_xvba" != "xno"; then -+ if test "$host_vendor" = "apple" ; then -+ if test "x$use_xvba" = "xyes"; then -+ AC_MSG_ERROR([XVBA not supported on this platform]) -+ else -+ use_xvba="no" -+ AC_MSG_NOTICE($xvba_disabled) -+ fi -+ USE_XVBA=0 -+ else -+ initial_val=$use_xvba -+ AC_CHECK_HEADER([amd/amdxvba.h],, use_xvba=no, [#include ]) -+ -+ if test "x$use_xvba" = "xno"; then -+ if test "x$initial_val" = "xyes"; then -+ AC_MSG_ERROR($xvba_not_found) -+ else -+ AC_MSG_RESULT($xvba_not_found) -+ fi -+ USE_XVBA=0 -+ else -+ AC_DEFINE([HAVE_LIBXVBA], [1], [Define to 1 if you have the 'xvba' header (amdxvba.h)]) -+ USE_XVBA=1 -+ fi -+ fi -+else -+ AC_MSG_NOTICE($xvba_disabled) -+ USE_XVBA=0 -+fi -+ -+ - # VDADecoder - if test "x$use_vdadecoder" != "xno"; then - if test "$host_vendor" = "apple" ; then -@@ -1962,6 +2002,12 @@ else - final_message="$final_message\n CrystalHD:\tNo" - fi - -+if test "x$use_xvba" != "xno"; then -+ final_message="$final_message\n XVBA:\t\tYes" -+else -+ final_message="$final_message\n XVBA:\t\tNo" -+fi -+ - if test "x$use_vdadecoder" != "xno"; then - final_message="$final_message\n VDADecoder:\tYes" - else -@@ -2435,6 +2481,7 @@ AC_SUBST(USE_OPENGLES) - AC_SUBST(USE_VDPAU) - AC_SUBST(USE_VAAPI) - AC_SUBST(USE_CRYSTALHD) -+AC_SUBST(USE_XVBA) - AC_SUBST(USE_LIBSMBCLIENT) - AC_SUBST(USE_LIBNFS) - AC_SUBST(USE_LIBAFPCLIENT) -@@ -2618,6 +2665,7 @@ XB_CONFIG_MODULE([lib/ffmpeg], [ - `if test "x$use_vdpau" != "xno"; then echo --enable-vdpau; else echo --disable-vdpau; fi` \ - `if test "x$use_vaapi" != "xno"; then echo --enable-vaapi; else echo --disable-vaapi; fi` \ - `if test "$use_optimizations" != "no"; then echo --enable-optimizations; else echo --disable-optimizations; fi` \ -+ `if test "x$use_xvba" != "xno"; then echo --enable-xvba; else echo --disable-xvba; fi` \ - --enable-protocol=http \ - --enable-pthreads \ - --enable-runtime-cpudetect \ -diff --git a/language/English/strings.po b/language/English/strings.po -index f2abd3f..fc896b3 100644 ---- a/language/English/strings.po -+++ b/language/English/strings.po -@@ -5120,7 +5120,11 @@ msgctxt "#13436" - msgid "Prefer VDPAU Video Mixer" - msgstr "" - --#empty strings from id 13437 to 13499 -+msgctxt "#13437" -+msgid "Allow hardware acceleration (XVBA)" -+msgstr "" -+ -+#empty strings from id 13438 to 13499 - - msgctxt "#13500" - msgid "A/V sync method" -@@ -6342,7 +6346,11 @@ msgctxt "#16325" - msgid "VDPAU - Bob" - msgstr "" - --#empty strings from id 16326 to 16399 -+msgctxt "#16326" -+msgid "XVBA" -+msgstr "" -+ -+#empty strings from id 16327 to 16399 - - msgctxt "#16400" - msgid "Post-processing" -diff --git a/xbmc/cores/VideoRenderers/LinuxRendererGL.cpp b/xbmc/cores/VideoRenderers/LinuxRendererGL.cpp -index 6e6d97e..0bb924b 100644 ---- a/xbmc/cores/VideoRenderers/LinuxRendererGL.cpp -+++ b/xbmc/cores/VideoRenderers/LinuxRendererGL.cpp -@@ -63,6 +63,9 @@ - VA_MICRO_VERSION == 0 && VA_SDS_VERSION < 5))) - - #endif -+#ifdef HAVE_LIBXVBA -+#include "cores/dvdplayer/DVDCodecs/Video/XVBA.h" -+#endif - - #ifdef TARGET_DARWIN - #include "osx/CocoaInterface.h" -@@ -129,6 +132,9 @@ - #ifdef HAVE_LIBVDPAU - vdpau = NULL; - #endif -+#ifdef HAVE_LIBXVBA -+ xvba = NULL; -+#endif - } - - CLinuxRendererGL::YUVBUFFER::~YUVBUFFER() -@@ -604,6 +610,9 @@ void CLinuxRendererGL::ReleaseBuffer(int idx) - #ifdef HAVE_LIBVDPAU - SAFE_RELEASE(buf.vdpau); - #endif -+#ifdef HAVE_LIBXVBA -+ SAFE_RELEASE(buf.xvba); -+#endif - #ifdef HAVE_LIBVA - buf.vaapi.surface.reset(); - #endif -@@ -879,7 +888,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 (((m_renderMethod & RENDER_VDPAU) || (m_renderMethod & RENDER_VAAPI) || (m_renderMethod & RENDER_XVBA)) && m_nonLinStretch) - { - m_pVideoFilterShader = new StretchFilterShader(); - if (!m_pVideoFilterShader->CompileAndLink()) -@@ -965,6 +974,11 @@ void CLinuxRendererGL::LoadShaders(int field) - CLog::Log(LOGNOTICE, "GL: Using CVBREF render method"); - m_renderMethod = RENDER_CVREF; - } -+ else if (m_format == RENDER_FMT_XVBA) -+ { -+ CLog::Log(LOGNOTICE, "GL: Using XVBA render method"); -+ m_renderMethod = RENDER_XVBA; -+ } - else - { - int requestedMethod = g_guiSettings.GetInt("videoplayer.rendermethod"); -@@ -1113,6 +1127,12 @@ void CLinuxRendererGL::LoadShaders(int field) - m_textureCreate = &CLinuxRendererGL::CreateCVRefTexture; - m_textureDelete = &CLinuxRendererGL::DeleteCVRefTexture; - } -+ else if (m_format == RENDER_FMT_XVBA) -+ { -+ m_textureUpload = &CLinuxRendererGL::UploadXVBATexture; -+ m_textureCreate = &CLinuxRendererGL::CreateXVBATexture; -+ m_textureDelete = &CLinuxRendererGL::DeleteXVBATexture; -+ } - else - { - // setup default YV12 texture handlers -@@ -1225,6 +1245,13 @@ void CLinuxRendererGL::Render(DWORD flags, int renderBuffer) - RenderVAAPI(renderBuffer, m_currentField); - } - #endif -+#ifdef HAVE_LIBXVBA -+ else if (m_renderMethod & RENDER_XVBA) -+ { -+ UpdateVideoFilter(); -+ RenderXVBA(renderBuffer, m_currentField); -+ } -+#endif - else - { - // RENDER_CVREF uses the same render as the default case -@@ -1732,6 +1759,77 @@ void CLinuxRendererGL::RenderVAAPI(int index, int field) - #endif - } - -+void CLinuxRendererGL::RenderXVBA(int index, int field) -+{ -+#ifdef HAVE_LIBXVBA -+ YUVPLANE &plane = m_buffers[index].fields[0][1]; -+ -+ glEnable(m_textureTarget); -+ glActiveTextureARB(GL_TEXTURE0); -+ -+ glBindTexture(m_textureTarget, plane.id); -+ -+ // Try some clamping or wrapping -+ glTexParameteri(m_textureTarget, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); -+ glTexParameteri(m_textureTarget, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); -+ -+ if (m_pVideoFilterShader) -+ { -+ GLint filter; -+ if (!m_pVideoFilterShader->GetTextureFilter(filter)) -+ filter = m_scalingMethod == VS_SCALINGMETHOD_NEAREST ? GL_NEAREST : GL_LINEAR; -+ -+ glTexParameteri(m_textureTarget, GL_TEXTURE_MAG_FILTER, filter); -+ glTexParameteri(m_textureTarget, GL_TEXTURE_MIN_FILTER, filter); -+ m_pVideoFilterShader->SetSourceTexture(0); -+ m_pVideoFilterShader->SetWidth(m_sourceWidth); -+ m_pVideoFilterShader->SetHeight(m_sourceHeight); -+ -+ //disable non-linear stretch when a dvd menu is shown, parts of the menu are rendered through the overlay renderer -+ //having non-linear stretch on breaks the alignment -+ if (g_application.m_pPlayer && g_application.m_pPlayer->IsInMenu()) -+ m_pVideoFilterShader->SetNonLinStretch(1.0); -+ else -+ m_pVideoFilterShader->SetNonLinStretch(pow(g_settings.m_fPixelRatio, g_advancedSettings.m_videoNonLinStretchRatio)); -+ -+ m_pVideoFilterShader->Enable(); -+ } -+ else -+ { -+ GLint filter = m_scalingMethod == VS_SCALINGMETHOD_NEAREST ? GL_NEAREST : GL_LINEAR; -+ glTexParameteri(m_textureTarget, GL_TEXTURE_MAG_FILTER, filter); -+ glTexParameteri(m_textureTarget, GL_TEXTURE_MIN_FILTER, filter); -+ } -+ -+ glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); -+ VerifyGLState(); -+ -+ glBegin(GL_QUADS); -+ if (m_textureTarget==GL_TEXTURE_2D) -+ { -+ glTexCoord2f(plane.rect.x1, plane.rect.y1); glVertex2f(m_destRect.x1, m_destRect.y1); -+ glTexCoord2f(plane.rect.x2, plane.rect.y1); glVertex2f(m_destRect.x2, m_destRect.y1); -+ glTexCoord2f(plane.rect.x2, plane.rect.y2); glVertex2f(m_destRect.x2, m_destRect.y2); -+ glTexCoord2f(plane.rect.x1, plane.rect.y2); glVertex2f(m_destRect.x1, m_destRect.y2); -+ } -+ else -+ { -+ glTexCoord2f(m_destRect.x1, m_destRect.y1); glVertex4f(m_destRect.x1, m_destRect.y1, 0.0f, 0.0f); -+ glTexCoord2f(m_destRect.x2, m_destRect.y1); glVertex4f(m_destRect.x2, m_destRect.y1, 1.0f, 0.0f); -+ glTexCoord2f(m_destRect.x2, m_destRect.y2); glVertex4f(m_destRect.x2, m_destRect.y2, 1.0f, 1.0f); -+ glTexCoord2f(m_destRect.x1, m_destRect.y2); glVertex4f(m_destRect.x1, m_destRect.y2, 0.0f, 1.0f); -+ } -+ glEnd(); -+ VerifyGLState(); -+ -+ if (m_pVideoFilterShader) -+ m_pVideoFilterShader->Disable(); -+ -+ glBindTexture (m_textureTarget, 0); -+ glDisable(m_textureTarget); -+#endif -+} -+ - void CLinuxRendererGL::RenderSoftware(int index, int field) - { - // used for textues uploaded from rgba or CVPixelBuffers. -@@ -2783,6 +2881,91 @@ bool CLinuxRendererGL::CreateCVRefTexture(int index) - return true; - } - -+void CLinuxRendererGL::DeleteXVBATexture(int index) -+{ -+#ifdef HAVE_LIBXVBA -+ YUVPLANE &plane = m_buffers[index].fields[0][0]; -+ YUVFIELDS &fields = m_buffers[index].fields; -+ -+ SAFE_RELEASE(m_buffers[index].xvba); -+ -+ if(plane.id && glIsTexture(plane.id)) -+ glDeleteTextures(1, &plane.id); -+ plane.id = 0; -+ fields[0][1].id = 0; -+#endif -+} -+ -+bool CLinuxRendererGL::CreateXVBATexture(int index) -+{ -+#ifdef HAVE_LIBXVBA -+ YV12Image &im = m_buffers[index].image; -+ YUVFIELDS &fields = m_buffers[index].fields; -+ YUVPLANE &plane = fields[0][0]; -+ -+ DeleteXVBATexture(index); -+ -+ memset(&im , 0, sizeof(im)); -+ memset(&fields, 0, sizeof(fields)); -+ -+ glGenTextures(1, &plane.id); -+ -+ m_eventTexturesDone[index]->Set(); -+#endif -+ return true; -+} -+ -+void CLinuxRendererGL::UploadXVBATexture(int index) -+{ -+#ifdef HAVE_LIBXVBA -+ XVBA::CXvbaRenderPicture *xvba = m_buffers[index].xvba; -+ YV12Image &im = m_buffers[index].image; -+ -+ YUVFIELDS &fields = m_buffers[index].fields; -+ YUVPLANE &plane = fields[0][1]; -+ -+ if (!xvba || !xvba->valid) -+ { -+ m_eventTexturesDone[index]->Set(); -+ m_skipRender = true; -+ return; -+ } -+ -+ plane.id = xvba->texture; -+ -+ im.height = xvba->texHeight; -+ im.width = xvba->texWidth; -+ -+ plane.texwidth = xvba->texWidth; -+ plane.texheight = xvba->texHeight; -+ plane.pixpertex_x = 1; -+ plane.pixpertex_y = 1; -+ -+ plane.rect = m_sourceRect; -+ plane.width = im.width; -+ plane.height = im.height; -+ -+ plane.height /= plane.pixpertex_y; -+ plane.rect.y1 /= plane.pixpertex_y; -+ plane.rect.y2 /= plane.pixpertex_y; -+ plane.width /= plane.pixpertex_x; -+ plane.rect.x1 /= plane.pixpertex_x; -+ plane.rect.x2 /= plane.pixpertex_x; -+ -+ if (m_textureTarget == GL_TEXTURE_2D) -+ { -+ plane.height /= plane.texheight; -+ plane.rect.y1 /= plane.texheight; -+ plane.rect.y2 /= plane.texheight; -+ plane.width /= plane.texwidth; -+ plane.rect.x1 /= plane.texwidth; -+ plane.rect.x2 /= plane.texwidth; -+ } -+ -+ m_eventTexturesDone[index]->Set(); -+#endif -+} -+ - void CLinuxRendererGL::UploadYUV422PackedTexture(int source) - { - YUVBUFFER& buf = m_buffers[source]; -@@ -3368,6 +3551,9 @@ bool CLinuxRendererGL::Supports(ERENDERFEATURE feature) - if (m_renderMethod & RENDER_VAAPI) - return false; - -+ if (m_renderMethod & RENDER_XVBA) -+ return false; -+ - return (m_renderMethod & RENDER_GLSL) - || (m_renderMethod & RENDER_ARB) - || ((m_renderMethod & RENDER_SW) && glewIsSupported("GL_ARB_imaging") == GL_TRUE); -@@ -3381,6 +3567,9 @@ bool CLinuxRendererGL::Supports(ERENDERFEATURE feature) - if (m_renderMethod & RENDER_VAAPI) - return false; - -+ if (m_renderMethod & RENDER_XVBA) -+ return false; -+ - return (m_renderMethod & RENDER_GLSL) - || (m_renderMethod & RENDER_ARB) - || ((m_renderMethod & RENDER_SW) && glewIsSupported("GL_ARB_imaging") == GL_TRUE); -@@ -3404,7 +3593,8 @@ bool CLinuxRendererGL::Supports(ERENDERFEATURE feature) - if (feature == RENDERFEATURE_NONLINSTRETCH) - { - if (((m_renderMethod & RENDER_GLSL) && !(m_renderMethod & RENDER_POT)) || -- (m_renderMethod & RENDER_VDPAU) || (m_renderMethod & RENDER_VAAPI)) -+ (m_renderMethod & RENDER_VDPAU) || (m_renderMethod & RENDER_VAAPI) || -+ (m_renderMethod & RENDER_XVBA)) - return true; - } - -@@ -3476,6 +3666,16 @@ bool CLinuxRendererGL::Supports(EINTERLACEMETHOD method) - return false; - } - -+ if(m_renderMethod & RENDER_XVBA) -+ { -+#ifdef HAVE_LIBXVBA -+ XVBA::CXvbaRenderPicture *xvba = m_buffers[m_iYV12RenderBuffer].xvba; -+ if(xvba) -+ return xvba->xvba->Supports(method); -+#endif -+ return false; -+ } -+ - #ifdef TARGET_DARWIN - // YADIF too slow for HD but we have no methods to fall back - // to something that works so just turn it off. -@@ -3518,7 +3718,7 @@ bool CLinuxRendererGL::Supports(ESCALINGMETHOD method) - || method == VS_SCALINGMETHOD_LANCZOS3) - { - if ((glewIsSupported("GL_EXT_framebuffer_object") && (m_renderMethod & RENDER_GLSL)) || -- (m_renderMethod & RENDER_VDPAU) || (m_renderMethod & RENDER_VAAPI)) -+ (m_renderMethod & RENDER_VDPAU) || (m_renderMethod & RENDER_VAAPI) || (m_renderMethod & RENDER_XVBA)) - { - // spline36 and lanczos3 are only allowed through advancedsettings.xml - if(method != VS_SCALINGMETHOD_SPLINE36 -@@ -3610,4 +3810,14 @@ void CLinuxRendererGL::AddProcessor(struct __CVBuffer *cvBufferRef, int index) - } - #endif - -+#ifdef HAVE_LIBXVBA -+void CLinuxRendererGL::AddProcessor(XVBA::CXvbaRenderPicture* xvba, int index) -+{ -+ YUVBUFFER &buf = m_buffers[index]; -+ XVBA::CXvbaRenderPicture *pic = xvba->Acquire(); -+ SAFE_RELEASE(buf.xvba); -+ buf.xvba = pic; -+} -+#endif -+ - #endif -diff --git a/xbmc/cores/VideoRenderers/LinuxRendererGL.h b/xbmc/cores/VideoRenderers/LinuxRendererGL.h -index 13217ce..a189892 100644 ---- a/xbmc/cores/VideoRenderers/LinuxRendererGL.h -+++ b/xbmc/cores/VideoRenderers/LinuxRendererGL.h -@@ -43,6 +43,8 @@ - namespace Shaders { class BaseVideoFilterShader; } - namespace VAAPI { struct CHolder; } - namespace VDPAU { class CVdpauRenderPicture; } -+namespace XVBA { class CXvbaRenderPicture; } -+ - - #undef ALIGN - #define ALIGN(value, alignment) (((value)+((alignment)-1))&~((alignment)-1)) -@@ -88,6 +90,7 @@ enum RenderMethod - RENDER_POT=0x10, - RENDER_VAAPI=0x20, - RENDER_CVREF = 0x40, -+ RENDER_XVBA=0x80, - }; - - enum RenderQuality -@@ -149,7 +152,9 @@ class CLinuxRendererGL : public CBaseRenderer - #ifdef TARGET_DARWIN - virtual void AddProcessor(struct __CVBuffer *cvBufferRef, int index); - #endif -- -+#ifdef HAVE_LIBXVBA -+ virtual void AddProcessor(XVBA::CXvbaRenderPicture* xvba, int index); -+#endif - virtual void RenderUpdate(bool clear, DWORD flags = 0, DWORD alpha = 255); - - // Feature support -@@ -208,6 +213,10 @@ class CLinuxRendererGL : public CBaseRenderer - void DeleteYUV422PackedTexture(int index); - bool CreateYUV422PackedTexture(int index); - -+ void UploadXVBATexture(int index); -+ void DeleteXVBATexture(int index); -+ bool CreateXVBATexture(int index); -+ - void UploadRGBTexture(int index); - void ToRGBFrame(YV12Image* im, unsigned flipIndexPlane, unsigned flipIndexBuf); - void ToRGBFields(YV12Image* im, unsigned flipIndexPlaneTop, unsigned flipIndexPlaneBot, unsigned flipIndexBuf); -@@ -223,6 +232,7 @@ class CLinuxRendererGL : public CBaseRenderer - void RenderVDPAU(int renderBuffer, int field); // render using vdpau hardware - void RenderProgressiveWeave(int renderBuffer, int field); // render using vdpau hardware - void RenderVAAPI(int renderBuffer, int field); // render using vdpau hardware -+ void RenderXVBA(int renderBuffer, int field); // render using xvba hardware - - struct - { -@@ -290,6 +300,9 @@ class CLinuxRendererGL : public CBaseRenderer - #ifdef TARGET_DARWIN_OSX - struct __CVBuffer *cvBufferRef; - #endif -+#ifdef HAVE_LIBXVBA -+ XVBA::CXvbaRenderPicture *xvba; -+#endif - }; - - typedef YUVBUFFER YUVBUFFERS[NUM_BUFFERS]; -diff --git a/xbmc/cores/VideoRenderers/RenderFormats.h b/xbmc/cores/VideoRenderers/RenderFormats.h -index 0262c60..a727d94 100644 ---- a/xbmc/cores/VideoRenderers/RenderFormats.h -+++ b/xbmc/cores/VideoRenderers/RenderFormats.h -@@ -35,6 +35,7 @@ enum ERenderFormat { - RENDER_FMT_OMXEGL, - RENDER_FMT_CVBREF, - RENDER_FMT_BYPASS, -+ RENDER_FMT_XVBA, - }; - - #endif -diff --git a/xbmc/cores/VideoRenderers/RenderManager.cpp b/xbmc/cores/VideoRenderers/RenderManager.cpp -index b89ec67..c99a555 100644 ---- a/xbmc/cores/VideoRenderers/RenderManager.cpp -+++ b/xbmc/cores/VideoRenderers/RenderManager.cpp -@@ -876,6 +876,10 @@ int CXBMCRenderManager::AddVideoPicture(DVDVideoPicture& pic) - else if(pic.format == RENDER_FMT_VAAPI) - m_pRenderer->AddProcessor(*pic.vaapi, index); - #endif -+#ifdef HAVE_LIBXVBA -+ else if(pic.format == RENDER_FMT_XVBA) -+ m_pRenderer->AddProcessor(pic.xvba, index); -+#endif - m_pRenderer->ReleaseImage(index, false); - - m_bRenderBufferUsed = true; -diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodec.h b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodec.h -index 64c5f5f..5fa52c3 100644 ---- a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodec.h -+++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodec.h -@@ -35,6 +35,7 @@ - namespace DXVA { class CSurfaceContext; } - namespace VAAPI { struct CHolder; } - namespace VDPAU { class CVdpauRenderPicture; } -+namespace XVBA { class CXvbaRenderPicture; } - class COpenMax; - class COpenMaxVideo; - struct OpenMaxVideoBuffer; -@@ -60,6 +61,9 @@ struct DVDVideoPicture - struct { - VAAPI::CHolder* vaapi; - }; -+ struct { -+ XVBA::CXvbaRenderPicture* xvba; -+ }; - - struct { - COpenMax *openMax; -diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.cpp b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.cpp -index e0c0f84..fc51dbf 100644 ---- a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.cpp -+++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.cpp -@@ -56,6 +56,9 @@ - #ifdef HAVE_LIBVA - #include "VAAPI.h" - #endif -+#ifdef HAVE_LIBXVBA -+#include "XVBA.h" -+#endif - - using namespace boost; - -@@ -100,6 +103,19 @@ enum PixelFormat CDVDVideoCodecFFmpeg::GetFormat( struct AVCodecContext * avctx - dec->Release(); - } - #endif -+#ifdef HAVE_LIBXVBA -+ if(*cur == PIX_FMT_XVBA_VLD && g_guiSettings.GetBool("videoplayer.usexvba")) -+ { -+ XVBA::CDecoder* dec = new XVBA::CDecoder(); -+ if(dec->Open(avctx, *cur, ctx->m_uSurfacesCount)) -+ { -+ ctx->SetHardware(dec); -+ return *cur; -+ } -+ else -+ dec->Release(); -+ } -+#endif - #ifdef HAVE_LIBVA - // mpeg4 vaapi decoding is disabled - if(*cur == PIX_FMT_VAAPI_VLD && g_guiSettings.GetBool("videoplayer.usevaapi") -diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/Makefile.in b/xbmc/cores/dvdplayer/DVDCodecs/Video/Makefile.in -index 176ceff..c58422b 100644 ---- a/xbmc/cores/dvdplayer/DVDCodecs/Video/Makefile.in -+++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/Makefile.in -@@ -14,6 +14,10 @@ ifeq (@USE_CRYSTALHD@,1) - SRCS += CrystalHD.cpp - SRCS += DVDVideoCodecCrystalHD.cpp - endif -+ifeq (@USE_XVBA@,1) -+SRCS+= XVBA.cpp \ -+ -+endif - ifeq (@USE_VDA@,1) - SRCS += DVDVideoCodecVDA.cpp - endif -diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/XVBA.cpp b/xbmc/cores/dvdplayer/DVDCodecs/Video/XVBA.cpp -new file mode 100644 -index 0000000..47ff25f ---- /dev/null -+++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/XVBA.cpp +diff -Naur xbmc-12.0.4/xbmc/cores/dvdplayer/DVDCodecs/Video/XVBA.cpp xbmc-12.0.4.patch/xbmc/cores/dvdplayer/DVDCodecs/Video/XVBA.cpp +--- xbmc-12.0.4/xbmc/cores/dvdplayer/DVDCodecs/Video/XVBA.cpp 1970-01-01 01:00:00.000000000 +0100 ++++ xbmc-12.0.4.patch/xbmc/cores/dvdplayer/DVDCodecs/Video/XVBA.cpp 2013-03-10 13:00:12.324988156 +0100 @@ -0,0 +1,2367 @@ +/* + * Copyright (C) 2005-2011 Team XBMC @@ -19081,11 +8967,9 @@ index 0000000..47ff25f +} + +#endif -diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/XVBA.h b/xbmc/cores/dvdplayer/DVDCodecs/Video/XVBA.h -new file mode 100644 -index 0000000..f38444c ---- /dev/null -+++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/XVBA.h +diff -Naur xbmc-12.0.4/xbmc/cores/dvdplayer/DVDCodecs/Video/XVBA.h xbmc-12.0.4.patch/xbmc/cores/dvdplayer/DVDCodecs/Video/XVBA.h +--- xbmc-12.0.4/xbmc/cores/dvdplayer/DVDCodecs/Video/XVBA.h 1970-01-01 01:00:00.000000000 +0100 ++++ xbmc-12.0.4.patch/xbmc/cores/dvdplayer/DVDCodecs/Video/XVBA.h 2013-03-10 13:00:12.324988156 +0100 @@ -0,0 +1,382 @@ +/* + * Copyright (C) 2005-2011 Team XBMC @@ -19469,190 +9353,9 @@ index 0000000..f38444c +}; + +} -diff --git a/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp b/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp -index 92f62bb..1e5d2ac5 100644 ---- a/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp -+++ b/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp -@@ -1174,6 +1174,10 @@ int CDVDPlayerVideo::OutputPicture(const DVDVideoPicture* src, double pts) - formatstr = "NONE"; - buffering = false; - break; -+ case RENDER_FMT_XVBA: -+ formatstr = "XVBA"; -+ buffering = true; -+ break; - } - - if(m_bAllowFullscreen) -diff --git a/xbmc/settings/GUISettings.cpp b/xbmc/settings/GUISettings.cpp -index 30b402d..67aeec9 100644 ---- a/xbmc/settings/GUISettings.cpp -+++ b/xbmc/settings/GUISettings.cpp -@@ -695,6 +695,9 @@ void CGUISettings::Initialize() - #ifdef HAVE_LIBVA - AddBool(vp, "videoplayer.usevaapi", 13426, true); - #endif -+#ifdef HAVE_LIBXVBA -+ AddBool(vp, "videoplayer.usexvba", 13437, true); -+#endif - #ifdef HAS_DX - AddBool(g_sysinfo.IsVistaOrHigher() ? vp: NULL, "videoplayer.usedxva2", 13427, g_sysinfo.IsVistaOrHigher() ? true : false); - #endif -diff --git a/xbmc/settings/VideoSettings.h b/xbmc/settings/VideoSettings.h -index f8093b2..f54a837 100644 ---- a/xbmc/settings/VideoSettings.h -+++ b/xbmc/settings/VideoSettings.h -@@ -65,6 +65,8 @@ enum EINTERLACEMETHOD - VS_INTERLACEMETHOD_SW_BLEND = 20, - VS_INTERLACEMETHOD_AUTO_ION = 21, - -+ VS_INTERLACEMETHOD_XVBA = 22, -+ - VS_INTERLACEMETHOD_MAX // do not use and keep as last enum value. - }; - -diff --git a/xbmc/video/dialogs/GUIDialogVideoSettings.cpp b/xbmc/video/dialogs/GUIDialogVideoSettings.cpp -index f25d10d..f6b1ea4 100644 ---- a/xbmc/video/dialogs/GUIDialogVideoSettings.cpp -+++ b/xbmc/video/dialogs/GUIDialogVideoSettings.cpp -@@ -110,6 +110,7 @@ void CGUIDialogVideoSettings::CreateSettings() - entries.push_back(make_pair(VS_INTERLACEMETHOD_DXVA_BOB , 16320)); - entries.push_back(make_pair(VS_INTERLACEMETHOD_DXVA_BEST , 16321)); - entries.push_back(make_pair(VS_INTERLACEMETHOD_AUTO_ION , 16325)); -+ entries.push_back(make_pair(VS_INTERLACEMETHOD_XVBA , 16326)); - - /* remove unsupported methods */ - for(vector >::iterator it = entries.begin(); it != entries.end();) --- -1.7.10 - - -From aa13bba48a76e32136814ab242c18646cd8744ec Mon Sep 17 00:00:00 2001 -From: fritsch -Date: Sun, 4 Nov 2012 16:24:10 +0100 -Subject: [PATCH 64/88] xvba: add string for available decoders - we are - important so make sure we are there - ---- - xbmc/cores/dvdplayer/DVDCodecs/DVDFactoryCodec.cpp | 5 +++++ - 1 file changed, 5 insertions(+) - -diff --git a/xbmc/cores/dvdplayer/DVDCodecs/DVDFactoryCodec.cpp b/xbmc/cores/dvdplayer/DVDCodecs/DVDFactoryCodec.cpp -index 0cea7a9..6fb74b7 100644 ---- a/xbmc/cores/dvdplayer/DVDCodecs/DVDFactoryCodec.cpp -+++ b/xbmc/cores/dvdplayer/DVDCodecs/DVDFactoryCodec.cpp -@@ -169,6 +169,11 @@ CDVDVideoCodec* CDVDFactoryCodec::CreateVideoCodec(CDVDStreamInfo &hint, unsigne - #elif defined(_LINUX) && !defined(TARGET_DARWIN) - hwSupport += "VAAPI:no "; - #endif -+#if defined(HAVE_LIBXVBA) && defined(TARGET_LINUX) -+ hwSupport += "XVBA:yes "; -+#elif defined(TARGET_LINUX) -+ hwSupport += "XVBA:no "; -+#endif - - CLog::Log(LOGDEBUG, "CDVDFactoryCodec: compiled in hardware support: %s", hwSupport.c_str()); - --- -1.7.10 - - -From 82ae5c8a538374f73dd2f728bcda7ff14efe532a Mon Sep 17 00:00:00 2001 -From: xbmc -Date: Sat, 16 Jun 2012 12:46:30 +0200 -Subject: [PATCH 65/88] xvba: do not use vaapi if xvba is present - ---- - xbmc/cores/dvdplayer/DVDCodecs/Video/VAAPI.cpp | 9 +++++++++ - 1 file changed, 9 insertions(+) - -diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/VAAPI.cpp b/xbmc/cores/dvdplayer/DVDCodecs/Video/VAAPI.cpp -index a2b9195..43a05b3 100644 ---- a/xbmc/cores/dvdplayer/DVDCodecs/Video/VAAPI.cpp -+++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/VAAPI.cpp -@@ -261,6 +261,15 @@ void CDecoder::Close() - - bool CDecoder::Open(AVCodecContext *avctx, enum PixelFormat fmt, unsigned int surfaces) - { -+#ifdef HAVE_LIBXVBA -+ std::string Vendor = g_Windowing.GetRenderVendor(); -+ std::transform(Vendor.begin(), Vendor.end(), Vendor.begin(), ::tolower); -+ if (Vendor.compare(0, 3, "ati") == 0) -+ { -+ return false; -+ } -+#endif -+ - VAEntrypoint entrypoint = VAEntrypointVLD; - VAProfile profile; - --- -1.7.10 - - -From 1aabfca9ab8a0acd87b3593f97180946ba08e630 Mon Sep 17 00:00:00 2001 -From: xbmc -Date: Thu, 23 Aug 2012 19:39:49 +0200 -Subject: [PATCH 66/88] ffmpeg: add av_find_default_stream_index to interface - ---- - lib/DllAvFormat.h | 4 ++++ - 1 file changed, 4 insertions(+) - -diff --git a/lib/DllAvFormat.h b/lib/DllAvFormat.h -index 9bda3f3..bf31fcb 100644 ---- a/lib/DllAvFormat.h -+++ b/lib/DllAvFormat.h -@@ -98,6 +98,7 @@ class DllAvFormatInterface - virtual int avformat_write_header (AVFormatContext *s, AVDictionary **options)=0; - virtual int av_write_trailer(AVFormatContext *s)=0; - virtual int av_write_frame (AVFormatContext *s, AVPacket *pkt)=0; -+ virtual int av_find_default_stream_index(AVFormatContext *s)=0; - }; - - #if (defined USE_EXTERNAL_FFMPEG) || (defined TARGET_DARWIN) -@@ -153,6 +154,7 @@ class DllAvFormat : public DllDynamic, DllAvFormatInterface - virtual int avformat_write_header (AVFormatContext *s, AVDictionary **options) { return ::avformat_write_header (s, options); } - virtual int av_write_trailer(AVFormatContext *s) { return ::av_write_trailer(s); } - virtual int av_write_frame (AVFormatContext *s, AVPacket *pkt) { return ::av_write_frame(s, pkt); } -+ virtual int av_find_default_stream_index(AVFormatContext *s) { return ::av_find_default_stream_index(s); } - - // DLL faking. - virtual bool ResolveExports() { return true; } -@@ -209,6 +211,7 @@ class DllAvFormat : public DllDynamic, DllAvFormatInterface - DEFINE_METHOD2(int, avformat_write_header , (AVFormatContext *p1, AVDictionary **p2)) - DEFINE_METHOD1(int, av_write_trailer, (AVFormatContext *p1)) - DEFINE_METHOD2(int, av_write_frame , (AVFormatContext *p1, AVPacket *p2)) -+ DEFINE_METHOD1(int, av_find_default_stream_index, (AVFormatContext *p1)) - BEGIN_METHOD_RESOLVE() - RESOLVE_METHOD_RENAME(av_register_all, av_register_all_dont_call) - RESOLVE_METHOD(av_find_input_format) -@@ -243,6 +246,7 @@ class DllAvFormat : public DllDynamic, DllAvFormatInterface - RESOLVE_METHOD(avformat_write_header) - RESOLVE_METHOD(av_write_trailer) - RESOLVE_METHOD(av_write_frame) -+ RESOLVE_METHOD(av_find_default_stream_index) - END_METHOD_RESOLVE() - - /* dependencies of libavformat */ --- -1.7.10 - - -From 541d9c977d0c3d4ab7710085b7edc2386d76ae03 Mon Sep 17 00:00:00 2001 -From: xbmc -Date: Mon, 20 Aug 2012 16:06:39 +0200 -Subject: [PATCH 67/88] dvdplayer: observe pts counter overflow - ---- - .../cores/dvdplayer/DVDDemuxers/DVDDemuxFFmpeg.cpp | 198 +++++++++++++++++++- - xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxFFmpeg.h | 4 + - 2 files changed, 201 insertions(+), 1 deletion(-) - -diff --git a/xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxFFmpeg.cpp b/xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxFFmpeg.cpp -index 7c0ab03..f91be3c 100644 ---- a/xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxFFmpeg.cpp -+++ b/xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxFFmpeg.cpp +diff -Naur xbmc-12.0.4/xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxFFmpeg.cpp xbmc-12.0.4.patch/xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxFFmpeg.cpp +--- xbmc-12.0.4/xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxFFmpeg.cpp 2013-03-08 13:01:31.000000000 +0100 ++++ xbmc-12.0.4.patch/xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxFFmpeg.cpp 2013-03-10 13:00:12.326988141 +0100 @@ -18,13 +18,13 @@ * */ @@ -19668,7 +9371,7 @@ index 7c0ab03..f91be3c 100644 #ifdef _LINUX #include "stdint.h" #endif -@@ -495,6 +495,9 @@ bool CDVDDemuxFFmpeg::Open(CDVDInputStream* pInput) +@@ -495,6 +495,9 @@ AddStream(i); } @@ -19678,7 +9381,7 @@ index 7c0ab03..f91be3c 100644 return true; } -@@ -605,6 +608,12 @@ double CDVDDemuxFFmpeg::ConvertTimestamp(int64_t pts, int den, int num) +@@ -605,6 +608,12 @@ if (pts == (int64_t)AV_NOPTS_VALUE) return DVD_NOPTS_VALUE; @@ -19691,7 +9394,7 @@ index 7c0ab03..f91be3c 100644 // do calculations in floats as they can easily overflow otherwise // we don't care for having a completly exact timestamp anyway double timestamp = (double)pts * num / den; -@@ -729,6 +738,24 @@ DemuxPacket* CDVDDemuxFFmpeg::Read() +@@ -729,6 +738,24 @@ pkt.pts = AV_NOPTS_VALUE; } @@ -19716,7 +9419,7 @@ index 7c0ab03..f91be3c 100644 // copy contents into our own packet pPacket->iSize = pkt.size; -@@ -845,10 +872,20 @@ bool CDVDDemuxFFmpeg::SeekTime(int time, bool backwords, double *startpts) +@@ -845,10 +872,20 @@ int ret; { CSingleLock lock(m_critSection); @@ -19737,7 +9440,7 @@ index 7c0ab03..f91be3c 100644 } if(m_iCurrentPts == DVD_NOPTS_VALUE) -@@ -867,6 +904,165 @@ bool CDVDDemuxFFmpeg::SeekTime(int time, bool backwords, double *startpts) +@@ -867,6 +904,165 @@ return (ret >= 0); } @@ -19903,11 +9606,10 @@ index 7c0ab03..f91be3c 100644 bool CDVDDemuxFFmpeg::SeekByte(int64_t pos) { g_demuxer.set(this); -diff --git a/xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxFFmpeg.h b/xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxFFmpeg.h -index 2b5f2e8..e0acf29 100644 ---- a/xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxFFmpeg.h -+++ b/xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxFFmpeg.h -@@ -97,6 +97,7 @@ class CDVDDemuxFFmpeg : public CDVDDemux +diff -Naur xbmc-12.0.4/xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxFFmpeg.h xbmc-12.0.4.patch/xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxFFmpeg.h +--- xbmc-12.0.4/xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxFFmpeg.h 2013-03-08 13:01:31.000000000 +0100 ++++ xbmc-12.0.4.patch/xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxFFmpeg.h 2013-03-10 13:00:12.326988141 +0100 +@@ -97,6 +97,7 @@ DemuxPacket* Read(); bool SeekTime(int time, bool backwords = false, double* startpts = NULL); @@ -19915,7 +9617,7 @@ index 2b5f2e8..e0acf29 100644 bool SeekByte(int64_t pos); int GetStreamLength(); CDemuxStream* GetStream(int iStreamId); -@@ -141,5 +142,8 @@ class CDVDDemuxFFmpeg : public CDVDDemux +@@ -141,5 +142,8 @@ XbmcThreads::EndTime m_timeout; CDVDInputStream* m_pInput; @@ -19924,169 +9626,32 @@ index 2b5f2e8..e0acf29 100644 + int64_t m_iStartTime, m_iMaxTime, m_iEndTime; }; --- -1.7.10 - - -From 30b4f0f57c63d3aca9a55e24714d4360edc761c6 Mon Sep 17 00:00:00 2001 -From: xbmc -Date: Tue, 2 Oct 2012 13:02:10 +0200 -Subject: [PATCH 68/88] dvdplayer: avoid short screen flicker caused by - unnecessary reconfigure of renderer - ---- - xbmc/cores/dvdplayer/DVDPlayerVideo.cpp | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) - -diff --git a/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp b/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp -index 1e5d2ac5..69f45d4 100644 ---- a/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp -+++ b/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp -@@ -1030,7 +1030,7 @@ int CDVDPlayerVideo::OutputPicture(const DVDVideoPicture* src, double pts) - || m_output.height != pPicture->iHeight - || m_output.dwidth != pPicture->iDisplayWidth - || m_output.dheight != pPicture->iDisplayHeight -- || m_output.framerate != config_framerate -+ || (!m_bFpsInvalid && fmod(m_output.framerate, config_framerate) != 0.0 ) - || 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 -@@ -1197,7 +1197,7 @@ int CDVDPlayerVideo::OutputPicture(const DVDVideoPicture* src, double pts) - m_output.height = pPicture->iHeight; - m_output.dwidth = pPicture->iDisplayWidth; - m_output.dheight = pPicture->iDisplayHeight; -- m_output.framerate = config_framerate; -+ m_output.framerate = config_framerate == 0.0 ? g_graphicsContext.GetFPS() : config_framerate; - m_output.color_format = pPicture->format; - m_output.extended_format = pPicture->extended_format; - m_output.color_matrix = pPicture->color_matrix; --- -1.7.10 - - -From 545cfa0bee6159fc55dfcaf2969d7bc657502071 Mon Sep 17 00:00:00 2001 -From: xbmc -Date: Thu, 11 Oct 2012 12:05:50 +0200 -Subject: [PATCH 69/88] vdpau: advanced settings for auto deinterlacing - ---- - xbmc/cores/dvdplayer/DVDCodecs/Video/VDPAU.cpp | 8 ++++---- - xbmc/settings/AdvancedSettings.cpp | 4 ++++ - xbmc/settings/AdvancedSettings.h | 2 ++ - 3 files changed, 10 insertions(+), 4 deletions(-) - -diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/VDPAU.cpp b/xbmc/cores/dvdplayer/DVDCodecs/Video/VDPAU.cpp -index 68cf36a..524efae 100644 ---- a/xbmc/cores/dvdplayer/DVDCodecs/Video/VDPAU.cpp -+++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/VDPAU.cpp -@@ -1696,10 +1696,10 @@ EINTERLACEMETHOD CMixer::GetDeinterlacingMethod(bool log /* = false */) - if (method == VS_INTERLACEMETHOD_AUTO) - { - int deint = -1; --// if (m_config.outHeight >= 720) --// deint = g_advancedSettings.m_videoVDPAUdeintHD; --// else --// deint = g_advancedSettings.m_videoVDPAUdeintSD; -+ if (m_config.outHeight >= 720) -+ deint = g_advancedSettings.m_videoVDPAUdeintHD; -+ else -+ deint = g_advancedSettings.m_videoVDPAUdeintSD; - - if (deint != -1) +diff -Naur xbmc-12.0.4/xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxPVRClient.cpp xbmc-12.0.4.patch/xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxPVRClient.cpp +--- xbmc-12.0.4/xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxPVRClient.cpp 2013-03-08 13:01:31.000000000 +0100 ++++ xbmc-12.0.4.patch/xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxPVRClient.cpp 2013-03-10 13:00:12.329988120 +0100 +@@ -348,9 +348,7 @@ + if (stm) + { + st = dynamic_cast(stm); +- if (!st +- || (st->codec != (CodecID)props.stream[i].iCodecId) +- || (st->iChannels != props.stream[i].iChannels)) ++ if (!st || (st->codec != (CodecID)props.stream[i].iCodecId)) + DisposeStream(i); + } + if (!m_streams[i]) +@@ -367,6 +365,7 @@ + st->iBitsPerSample = props.stream[i].iBitsPerSample; + m_streams[i] = st; + st->m_parser_split = true; ++ st->changes++; + } + else if (props.stream[i].iCodecType == AVMEDIA_TYPE_VIDEO) { -diff --git a/xbmc/settings/AdvancedSettings.cpp b/xbmc/settings/AdvancedSettings.cpp -index 04a7c7c..0e68a80 100644 ---- a/xbmc/settings/AdvancedSettings.cpp -+++ b/xbmc/settings/AdvancedSettings.cpp -@@ -106,6 +106,8 @@ void CAdvancedSettings::Initialize() - m_videoAllowMpeg4VAAPI = false; - m_videoDisableBackgroundDeinterlace = false; - m_videoCaptureUseOcclusionQuery = -1; //-1 is auto detect -+ m_videoVDPAUdeintHD = -1; -+ m_videoVDPAUdeintSD = -1; - m_videoVDPAUtelecine = false; - m_videoVDPAUdeintSkipChromaHD = false; - m_DXVACheckCompatibility = false; -@@ -503,6 +505,8 @@ void CAdvancedSettings::ParseSettingsFile(const CStdString &file) - XMLUtils::GetBoolean(pElement,"allowmpeg4vaapi",m_videoAllowMpeg4VAAPI); - XMLUtils::GetBoolean(pElement, "disablebackgrounddeinterlace", m_videoDisableBackgroundDeinterlace); - XMLUtils::GetInt(pElement, "useocclusionquery", m_videoCaptureUseOcclusionQuery, -1, 1); -+ XMLUtils::GetInt(pElement,"vdpauHDdeint",m_videoVDPAUdeintHD); -+ XMLUtils::GetInt(pElement,"vdpauSDdeint",m_videoVDPAUdeintSD); - XMLUtils::GetBoolean(pElement,"vdpauInvTelecine",m_videoVDPAUtelecine); - XMLUtils::GetBoolean(pElement,"vdpauHDdeintSkipChroma",m_videoVDPAUdeintSkipChromaHD); - -diff --git a/xbmc/settings/AdvancedSettings.h b/xbmc/settings/AdvancedSettings.h -index 72718e5..aaa4702 100644 ---- a/xbmc/settings/AdvancedSettings.h -+++ b/xbmc/settings/AdvancedSettings.h -@@ -133,6 +133,8 @@ class CAdvancedSettings - int m_videoPercentSeekBackwardBig; - CStdString m_videoPPFFmpegDeint; - CStdString m_videoPPFFmpegPostProc; -+ int m_videoVDPAUdeintHD; -+ int m_videoVDPAUdeintSD; - bool m_videoVDPAUtelecine; - bool m_videoVDPAUdeintSkipChromaHD; - bool m_musicUseTimeSeeking; --- -1.7.10 - - -From ae14edafa313c667d22cf9a255effab6bcf1fc61 Mon Sep 17 00:00:00 2001 -From: xbmc -Date: Thu, 11 Oct 2012 13:01:08 +0200 -Subject: [PATCH 70/88] dvdplayer: correct determination if video is playing - ---- - xbmc/cores/dvdplayer/DVDPlayer.cpp | 11 +++++++++-- - 1 file changed, 9 insertions(+), 2 deletions(-) - -diff --git a/xbmc/cores/dvdplayer/DVDPlayer.cpp b/xbmc/cores/dvdplayer/DVDPlayer.cpp -index 3737419..890d99e 100644 ---- a/xbmc/cores/dvdplayer/DVDPlayer.cpp -+++ b/xbmc/cores/dvdplayer/DVDPlayer.cpp -@@ -2382,9 +2382,16 @@ bool CDVDPlayer::IsPaused() const - - bool CDVDPlayer::HasVideo() const - { -- if (m_pInputStream && m_pInputStream->IsStreamType(DVDSTREAM_TYPE_DVD)) return true; -+ bool hasVideo(false); - -- return m_SelectionStreams.Count(STREAM_VIDEO) > 0 ? true : false; -+ if (m_pInputStream && m_pInputStream->IsStreamType(DVDSTREAM_TYPE_DVD)) -+ hasVideo = true; -+ else if (m_SelectionStreams.Count(STREAM_VIDEO) > 0) -+ hasVideo = true; -+ else if (g_renderManager.IsConfigured()) -+ hasVideo = true; -+ -+ return hasVideo; - } - - bool CDVDPlayer::HasAudio() const --- -1.7.10 - - -From 1999316cc983ec63d6f9fe05626a0f481d858119 Mon Sep 17 00:00:00 2001 -From: xbmc -Date: Fri, 2 Nov 2012 13:20:03 +0100 -Subject: [PATCH 71/88] player: fix rewind - ---- - xbmc/cores/dvdplayer/DVDMessage.h | 5 ++++- - xbmc/cores/dvdplayer/DVDPlayer.cpp | 30 +++++++++++++++++++----------- - xbmc/cores/dvdplayer/DVDPlayer.h | 7 ++++--- - xbmc/cores/dvdplayer/DVDPlayerVideo.cpp | 10 ++++++---- - xbmc/cores/dvdplayer/DVDPlayerVideo.h | 1 + - 5 files changed, 34 insertions(+), 19 deletions(-) - -diff --git a/xbmc/cores/dvdplayer/DVDMessage.h b/xbmc/cores/dvdplayer/DVDMessage.h -index 30b2f5c..b9831d4 100644 ---- a/xbmc/cores/dvdplayer/DVDMessage.h -+++ b/xbmc/cores/dvdplayer/DVDMessage.h -@@ -218,7 +218,7 @@ class CDVDMsgPlayerSetState : public CDVDMsg +diff -Naur xbmc-12.0.4/xbmc/cores/dvdplayer/DVDMessage.h xbmc-12.0.4.patch/xbmc/cores/dvdplayer/DVDMessage.h +--- xbmc-12.0.4/xbmc/cores/dvdplayer/DVDMessage.h 2013-03-08 13:01:31.000000000 +0100 ++++ xbmc-12.0.4.patch/xbmc/cores/dvdplayer/DVDMessage.h 2013-03-10 13:00:12.327988134 +0100 +@@ -218,7 +218,7 @@ class CDVDMsgPlayerSeek : public CDVDMsg { public: @@ -20095,7 +9660,7 @@ index 30b2f5c..b9831d4 100644 : CDVDMsg(PLAYER_SEEK) , m_time(time) , m_backward(backward) -@@ -226,6 +226,7 @@ class CDVDMsgPlayerSeek : public CDVDMsg +@@ -226,6 +226,7 @@ , m_accurate(accurate) , m_restore(restore) , m_trickplay(trickplay) @@ -20103,7 +9668,7 @@ index 30b2f5c..b9831d4 100644 {} int GetTime() { return m_time; } bool GetBackward() { return m_backward; } -@@ -233,6 +234,7 @@ class CDVDMsgPlayerSeek : public CDVDMsg +@@ -233,6 +234,7 @@ bool GetAccurate() { return m_accurate; } bool GetRestore() { return m_restore; } bool GetTrickPlay() { return m_trickplay; } @@ -20111,7 +9676,7 @@ index 30b2f5c..b9831d4 100644 private: int m_time; bool m_backward; -@@ -240,6 +242,7 @@ class CDVDMsgPlayerSeek : public CDVDMsg +@@ -240,6 +242,7 @@ bool m_accurate; bool m_restore; // whether to restore any EDL cut time bool m_trickplay; @@ -20119,15 +9684,16 @@ index 30b2f5c..b9831d4 100644 }; class CDVDMsgPlayerSeekChapter : public CDVDMsg -diff --git a/xbmc/cores/dvdplayer/DVDPlayer.cpp b/xbmc/cores/dvdplayer/DVDPlayer.cpp -index 890d99e..d02f086 100644 ---- a/xbmc/cores/dvdplayer/DVDPlayer.cpp -+++ b/xbmc/cores/dvdplayer/DVDPlayer.cpp -@@ -1543,11 +1543,13 @@ void CDVDPlayer::HandlePlaySpeed() +diff -Naur xbmc-12.0.4/xbmc/cores/dvdplayer/DVDPlayer.cpp xbmc-12.0.4.patch/xbmc/cores/dvdplayer/DVDPlayer.cpp +--- xbmc-12.0.4/xbmc/cores/dvdplayer/DVDPlayer.cpp 2013-03-08 13:01:31.000000000 +0100 ++++ xbmc-12.0.4.patch/xbmc/cores/dvdplayer/DVDPlayer.cpp 2013-03-10 13:00:12.328988127 +0100 +@@ -1542,12 +1542,14 @@ + } else if (m_CurrentVideo.id >= 0 - && (m_CurrentVideo.inited == true || GetPlaySpeed() < 0) // allow rewind at end of file +- && m_CurrentVideo.inited == true - && m_SpeedState.lastpts != m_dvdPlayerVideo.GetCurrentPts() ++ && (m_CurrentVideo.inited == true || GetPlaySpeed() < 0) // allow rewind at end of file + && (m_SpeedState.lastpts != m_dvdPlayerVideo.GetCurrentPts() || fabs(m_SpeedState.lastabstime - CDVDClock::GetAbsoluteClock()) > DVD_MSEC_TO_TIME(200)) + && (m_dvdPlayerVideo.GetCurrentPts() != DVD_NOPTS_VALUE) && m_SpeedState.lasttime != GetTime()) @@ -20138,7 +9704,7 @@ index 890d99e..d02f086 100644 // check how much off clock video is when ff/rw:ing // a problem here is that seeking isn't very accurate // and since the clock will be resynced after seek -@@ -1566,7 +1568,7 @@ void CDVDPlayer::HandlePlaySpeed() +@@ -1566,7 +1568,7 @@ { CLog::Log(LOGDEBUG, "CDVDPlayer::Process - Seeking to catch up"); int64_t iTime = (int64_t)DVD_TIME_TO_MSEC(m_clock.GetClock() + m_State.time_offset + 500000.0 * m_playSpeed / DVD_PLAYSPEED_NORMAL); @@ -20147,7 +9713,7 @@ index 890d99e..d02f086 100644 } } } -@@ -2030,7 +2032,7 @@ void CDVDPlayer::HandleMessages() +@@ -2030,7 +2032,7 @@ if(!m_pSubtitleDemuxer->SeekTime(time, msg.GetBackward())) CLog::Log(LOGDEBUG, "failed to seek subtitle demuxer: %d, success", time); } @@ -20156,7 +9722,7 @@ index 890d99e..d02f086 100644 } else CLog::Log(LOGWARNING, "error while seeking"); -@@ -2168,9 +2170,10 @@ void CDVDPlayer::HandleMessages() +@@ -2168,9 +2170,10 @@ double offset; offset = CDVDClock::GetAbsoluteClock() - m_State.timestamp; offset *= m_playSpeed / DVD_PLAYSPEED_NORMAL; @@ -20168,17 +9734,40 @@ index 890d99e..d02f086 100644 m_State.timestamp = CDVDClock::GetAbsoluteClock(); } -@@ -2186,7 +2189,8 @@ void CDVDPlayer::HandleMessages() - // do a seek after rewind, clock is not in sync with current pts - if (m_playSpeed < 0 && speed >= 0) - { -- m_messenger.Put(new CDVDMsgPlayerSeek(GetTime(), true, true, true)); -+ int64_t iTime = (int64_t)DVD_TIME_TO_MSEC(m_clock.GetClock() + m_State.time_offset); -+ m_messenger.Put(new CDVDMsgPlayerSeek(iTime, true, true, false, false, true)); +@@ -2183,6 +2186,13 @@ + pvrinputstream->Pause( speed == 0 ); } ++ // do a seek after rewind, clock is not in sync with current pts ++ if (m_playSpeed < 0 && speed >= 0) ++ { ++ int64_t iTime = (int64_t)DVD_TIME_TO_MSEC(m_clock.GetClock() + m_State.time_offset); ++ m_messenger.Put(new CDVDMsgPlayerSeek(iTime, true, true, false, false, true)); ++ } ++ // if playspeed is different then DVD_PLAYSPEED_NORMAL or DVD_PLAYSPEED_PAUSE -@@ -3140,7 +3144,7 @@ bool CDVDPlayer::CloseTeletextStream(bool bWaitForBuffers) + // audioplayer, stops outputing audio to audiorendere, but still tries to + // sleep an correct amount for each packet +@@ -2376,9 +2386,16 @@ + + bool CDVDPlayer::HasVideo() const + { +- if (m_pInputStream && m_pInputStream->IsStreamType(DVDSTREAM_TYPE_DVD)) return true; ++ bool hasVideo(false); ++ ++ if (m_pInputStream && m_pInputStream->IsStreamType(DVDSTREAM_TYPE_DVD)) ++ hasVideo = true; ++ else if (m_SelectionStreams.Count(STREAM_VIDEO) > 0) ++ hasVideo = true; ++ else if (g_renderManager.IsConfigured()) ++ hasVideo = true; + +- return m_SelectionStreams.Count(STREAM_VIDEO) > 0 ? true : false; ++ return hasVideo; + } + + bool CDVDPlayer::HasAudio() const +@@ -3127,7 +3144,7 @@ return true; } @@ -20187,7 +9776,7 @@ index 890d99e..d02f086 100644 { double startpts; if(accurate) -@@ -3152,19 +3156,23 @@ void CDVDPlayer::FlushBuffers(bool queued, double pts, bool accurate) +@@ -3139,19 +3156,23 @@ if(startpts != DVD_NOPTS_VALUE) startpts -= m_offset_pts; @@ -20215,7 +9804,7 @@ index 890d99e..d02f086 100644 m_CurrentTeletext.dts = DVD_NOPTS_VALUE; m_CurrentTeletext.startpts = startpts; -@@ -3208,7 +3216,7 @@ void CDVDPlayer::FlushBuffers(bool queued, double pts, bool accurate) +@@ -3195,7 +3216,7 @@ m_CurrentTeletext.started = false; } @@ -20224,11 +9813,10 @@ index 890d99e..d02f086 100644 m_clock.Discontinuity(pts); UpdatePlayState(0); } -diff --git a/xbmc/cores/dvdplayer/DVDPlayer.h b/xbmc/cores/dvdplayer/DVDPlayer.h -index d3c201e..70ecea9 100644 ---- a/xbmc/cores/dvdplayer/DVDPlayer.h -+++ b/xbmc/cores/dvdplayer/DVDPlayer.h -@@ -310,7 +310,7 @@ class CDVDPlayer : public IPlayer, public CThread, public IDVDPlayer +diff -Naur xbmc-12.0.4/xbmc/cores/dvdplayer/DVDPlayer.h xbmc-12.0.4.patch/xbmc/cores/dvdplayer/DVDPlayer.h +--- xbmc-12.0.4/xbmc/cores/dvdplayer/DVDPlayer.h 2013-03-08 13:01:31.000000000 +0100 ++++ xbmc-12.0.4.patch/xbmc/cores/dvdplayer/DVDPlayer.h 2013-03-10 13:00:12.328988127 +0100 +@@ -310,7 +310,7 @@ bool GetCachingTimes(double& play_left, double& cache_left, double& file_offset); @@ -20237,7 +9825,7 @@ index d3c201e..70ecea9 100644 void HandleMessages(); void HandlePlaySpeed(); -@@ -359,8 +359,9 @@ class CDVDPlayer : public IPlayer, public CThread, public IDVDPlayer +@@ -359,8 +359,9 @@ int m_playSpeed; struct SSpeedState { @@ -20249,293 +9837,2658 @@ index d3c201e..70ecea9 100644 } m_SpeedState; int m_errorCount; -diff --git a/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp b/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp -index 69f45d4..0434cb9 100644 ---- a/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp -+++ b/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp -@@ -1281,13 +1281,13 @@ int CDVDPlayerVideo::OutputPicture(const DVDVideoPicture* src, double pts) +diff -Naur xbmc-12.0.4/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp xbmc-12.0.4.patch/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp +--- xbmc-12.0.4/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp 2013-03-08 13:01:31.000000000 +0100 ++++ xbmc-12.0.4.patch/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp 2013-03-10 13:00:12.328988127 +0100 +@@ -325,8 +325,10 @@ + + int iDropped = 0; //frames dropped in a row + bool bRequestDrop = false; ++ int iDropDirective; + + m_videoStats.Start(); ++ m_droppingStats.Reset(); + + while (!m_bStop) + { +@@ -436,6 +438,7 @@ + picture.iFlags &= ~DVP_FLAG_ALLOCATED; + m_packets.clear(); + m_started = false; ++ m_droppingStats.Reset(); + } + else if (pMsg->IsType(CDVDMsg::GENERAL_FLUSH)) // private message sent by (CDVDPlayerVideo::Flush()) + { +@@ -448,6 +451,7 @@ + //we need to recalculate the framerate + //TODO: this needs to be set on a streamchange instead + ResetFrameRateCalc(); ++ m_droppingStats.Reset(); + + m_stalled = true; + m_started = false; +@@ -465,6 +469,8 @@ + m_speed = static_cast(pMsg)->m_value; + if(m_speed == DVD_PLAYSPEED_PAUSE) + m_iNrOfPicturesNotToSkip = 0; ++ g_renderManager.SetSpeed(m_speed); ++ m_droppingStats.Reset(); + } + else if (pMsg->IsType(CDVDMsg::PLAYER_STARTED)) + { +@@ -499,6 +505,28 @@ + m_iNrOfPicturesNotToSkip = 1; + } + ++ bRequestDrop = false; ++ iDropDirective = CalcDropRequirement(pts); ++ if (iDropDirective & EOS_VERYLATE) ++ { ++ if (m_bAllowDrop) ++ { ++ m_pullupCorrection.Flush(); ++ bRequestDrop = true; ++ } ++ } ++ int codecControl = 0; ++ if (iDropDirective & EOS_BUFFER_LEVEL) ++ codecControl |= DVP_FLAG_DRAIN; ++ if (m_speed > DVD_PLAYSPEED_NORMAL) ++ codecControl |= DVP_FLAG_NO_POSTPROC; ++ m_pVideoCodec->SetCodecControl(codecControl); ++ if (iDropDirective & EOS_DROPPED) ++ { ++ m_iDroppedFrames++; ++ iDropped++; ++ } ++ + #ifdef PROFILE + bRequestDrop = false; + #else +@@ -508,6 +536,7 @@ + bRequestDrop = false; + m_iDroppedRequest = 0; + m_iLateFrames = 0; ++ m_droppingStats.m_requestOutputDrop = false; + } + #endif + +@@ -555,15 +584,8 @@ + } + + m_videoStats.AddSampleBytes(pPacket->iSize); +- // assume decoder dropped a picture if it didn't give us any +- // picture from a demux packet, this should be reasonable +- // for libavformat as a demuxer as it normally packetizes +- // pictures when they come from demuxer +- if(bRequestDrop && !bPacketDrop && (iDecoderState & VC_BUFFER) && !(iDecoderState & VC_PICTURE)) +- { +- m_iDroppedFrames++; +- iDropped++; +- } ++ ++ bRequestDrop = false; + + // loop while no error + while (!m_bStop) +@@ -586,6 +608,8 @@ + + m_pVideoCodec->Reset(); + m_packets.clear(); ++ picture.iFlags &= ~DVP_FLAG_ALLOCATED; ++ g_renderManager.DiscardBuffer(); + break; + } + +@@ -695,6 +719,8 @@ + CDVDCodecUtils::FreePicture(pTempYUVPackedPicture); + #endif + ++ frametime = (double)DVD_TIME_BASE/m_fFrameRate; ++ + if(m_started == false) + { + m_codecname = m_pVideoCodec->GetName(); +@@ -1004,7 +1030,7 @@ + || m_output.height != pPicture->iHeight + || m_output.dwidth != pPicture->iDisplayWidth + || m_output.dheight != pPicture->iDisplayHeight +- || m_output.framerate != config_framerate ++ || (!m_bFpsInvalid && fmod(m_output.framerate, config_framerate) != 0.0 ) + || 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 +@@ -1088,47 +1114,69 @@ + } + + CStdString formatstr; ++ bool buffering; + + switch(pPicture->format) + { + case RENDER_FMT_YUV420P: + formatstr = "YV12"; ++ buffering = true; + break; + case RENDER_FMT_YUV420P16: + formatstr = "YV12P16"; ++ buffering = true; + break; + case RENDER_FMT_YUV420P10: + formatstr = "YV12P10"; ++ buffering = true; + break; + case RENDER_FMT_NV12: + formatstr = "NV12"; ++ buffering = true; + break; + case RENDER_FMT_UYVY422: + formatstr = "UYVY"; ++ buffering = true; + break; + case RENDER_FMT_YUYV422: + formatstr = "YUY2"; ++ buffering = true; + break; + case RENDER_FMT_VDPAU: + formatstr = "VDPAU"; ++ buffering = true; ++ break; ++ case RENDER_FMT_VDPAU_420: ++ formatstr = "VDPAU_420"; ++ buffering = true; + break; + case RENDER_FMT_DXVA: + formatstr = "DXVA"; ++ buffering = true; + break; + case RENDER_FMT_VAAPI: + formatstr = "VAAPI"; ++ buffering = false; + break; + case RENDER_FMT_OMXEGL: + formatstr = "OMXEGL"; ++ buffering = false; + break; + case RENDER_FMT_CVBREF: + formatstr = "BGRA"; ++ buffering = false; + break; + case RENDER_FMT_BYPASS: + formatstr = "BYPASS"; ++ buffering = false; + break; + case RENDER_FMT_NONE: + formatstr = "NONE"; ++ buffering = false; ++ break; ++ case RENDER_FMT_XVBA: ++ formatstr = "XVBA"; ++ buffering = true; + break; + } + +@@ -1139,7 +1187,7 @@ + } + + 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)) ++ if(!g_renderManager.Configure(pPicture->iWidth, pPicture->iHeight, pPicture->iDisplayWidth, pPicture->iDisplayHeight, config_framerate, flags, pPicture->format, pPicture->extended_format, m_hints.orientation, buffering)) + { + CLog::Log(LOGERROR, "%s - failed to configure renderer", __FUNCTION__); + return EOS_ABORT; +@@ -1149,7 +1197,7 @@ + m_output.height = pPicture->iHeight; + m_output.dwidth = pPicture->iDisplayWidth; + m_output.dheight = pPicture->iDisplayHeight; +- m_output.framerate = config_framerate; ++ m_output.framerate = config_framerate == 0.0 ? g_graphicsContext.GetFPS() : config_framerate; + m_output.color_format = pPicture->format; + m_output.extended_format = pPicture->extended_format; + m_output.color_matrix = pPicture->color_matrix; +@@ -1222,66 +1270,30 @@ + else + iSleepTime = iFrameSleep + (iClockSleep - iFrameSleep) / m_autosync; + +-#ifdef PROFILE /* during profiling, try to play as fast as possible */ +- iSleepTime = 0; +-#endif +- +- // present the current pts of this frame to user, and include the actual +- // presentation delay, to allow him to adjust for it +- if( m_stalled ) +- m_iCurrentPts = DVD_NOPTS_VALUE; +- else +- m_iCurrentPts = pts - max(0.0, iSleepTime); +- +- // timestamp when we think next picture should be displayed based on current duration +- m_FlipTimeStamp = iCurrentClock; +- m_FlipTimeStamp += max(0.0, iSleepTime); +- m_FlipTimeStamp += iFrameDuration; +- +- if (iSleepTime <= 0 && m_speed) +- m_iLateFrames++; +- else +- m_iLateFrames = 0; +- +- // ask decoder to drop frames next round, as we are very late +- if(m_iLateFrames > 10) ++ if ((m_droppingStats.m_requestOutputDrop && !(pPicture->iFlags & DVP_FLAG_NOSKIP)) ++ || (pPicture->iFlags & DVP_FLAG_DROPPED)) + { +- if (!(pPicture->iFlags & DVP_FLAG_NOSKIP)) +- { +- //if we're calculating the framerate, +- //don't drop frames until we've calculated a stable framerate +- if (m_bAllowDrop || m_speed != DVD_PLAYSPEED_NORMAL) +- { +- result |= EOS_VERYLATE; +- m_pullupCorrection.Flush(); //dropped frames mess up the pattern, so just flush it +- } +- +- //if we requested 5 drops in a row and we're still late, drop on output +- //this keeps a/v sync if the decoder can't drop, or we're still calculating the framerate +- if (m_iDroppedRequest > 5) +- { +- m_iDroppedRequest--; //decrease so we only drop half the frames +- return result | EOS_DROPPED; +- } +- m_iDroppedRequest++; +- } +- } +- else +- { +- m_iDroppedRequest = 0; ++ m_droppingStats.AddOutputDropGain(pts, 1/m_fFrameRate); ++ m_droppingStats.m_requestOutputDrop = false; ++ CLog::Log(LOGDEBUG,"%s - dropped in output", __FUNCTION__); ++ return result | EOS_DROPPED; + } if( m_speed < 0 ) { -- double decoderPts = m_droppingStats.m_lastDecoderPts; +- if( iClockSleep < -DVD_MSEC_TO_TIME(200) +- && !(pPicture->iFlags & DVP_FLAG_NOSKIP) ) + double inputPts = m_droppingStats.m_lastPts; - double renderPts = m_droppingStats.m_lastRenderPts; - if (pts > renderPts) - { -- if (decoderPts >= renderPts) ++ double renderPts = m_droppingStats.m_lastRenderPts; ++ if (pts > renderPts) ++ { + if (inputPts >= renderPts) - { -- Sleep(200); ++ { + Sleep(50); - } ++ } return result | EOS_DROPPED; - } -@@ -1584,7 +1584,7 @@ double CDVDPlayerVideo::GetCurrentPts() - - if( m_stalled ) - iRenderPts = DVD_NOPTS_VALUE; -- else -+ else if ( m_speed == DVD_PLAYSPEED_NORMAL) - iRenderPts = iRenderPts - max(0.0, iSleepTime); - - return iRenderPts; -@@ -1684,6 +1684,8 @@ int CDVDPlayerVideo::CalcDropRequirement(double pts) - int iSkippedDeint = 0; - int iBufferLevel; - -+ m_droppingStats.m_lastPts = pts; -+ - // get decoder stats - if (!m_pVideoCodec->GetCodecStats(iDecoderPts, iSkippedDeint, interlaced)) - iDecoderPts = pts; -diff --git a/xbmc/cores/dvdplayer/DVDPlayerVideo.h b/xbmc/cores/dvdplayer/DVDPlayerVideo.h -index 509d5f7..7cddda7 100644 ---- a/xbmc/cores/dvdplayer/DVDPlayerVideo.h -+++ b/xbmc/cores/dvdplayer/DVDPlayerVideo.h -@@ -51,6 +51,7 @@ class CDroppingStats - double m_totalGain; - double m_lastDecoderPts; - double m_lastRenderPts; -+ double m_lastPts; - unsigned int m_lateFrames; - unsigned int m_dropRequests; - bool m_requestOutputDrop; --- -1.7.10 - - -From d4c4fafbcd0bce6f566e2e65e1f9009dc445f832 Mon Sep 17 00:00:00 2001 -From: xbmc -Date: Fri, 23 Nov 2012 17:41:12 +0100 -Subject: [PATCH 72/88] xrandr: fix query for multiple screens - ---- - xbmc/windowing/X11/XRandR.cpp | 10 ++++++---- - 1 file changed, 6 insertions(+), 4 deletions(-) - -diff --git a/xbmc/windowing/X11/XRandR.cpp b/xbmc/windowing/X11/XRandR.cpp -index cc933b9..533e03d 100644 ---- a/xbmc/windowing/X11/XRandR.cpp -+++ b/xbmc/windowing/X11/XRandR.cpp -@@ -57,12 +57,14 @@ bool CXRandR::Query(bool force) - - m_outputs.clear(); - // query all screens -+ // we are happy if at least one screen returns results -+ bool success = false; - for(unsigned int screennum=0; screennumiFlags & DVP_FLAG_DROPPED) ) +- return result | EOS_DROPPED; +- +- if( m_speed != DVD_PLAYSPEED_NORMAL && limited ) ++ if( m_speed != DVD_PLAYSPEED_NORMAL && m_speed >= 0 && limited ) + { + // calculate frame dropping pattern to render at this speed + // we do that by deciding if this or next frame is closest +@@ -1317,6 +1329,16 @@ + mDisplayField = FS_BOT; + } + ++ int buffer = g_renderManager.WaitForBuffer(m_bStop); ++ while (buffer < 0 && !CThread::m_bStop && ++ CDVDClock::GetAbsoluteClock(false) < iCurrentClock + iSleepTime + DVD_MSEC_TO_TIME(500) ) ++ { ++ Sleep(1); ++ buffer = g_renderManager.WaitForBuffer(m_bStop); ++ } ++ if (buffer < 0) ++ return EOS_DROPPED; ++ + ProcessOverlays(pPicture, pts); + AutoCrop(pPicture); + +@@ -1333,7 +1355,7 @@ + if (index < 0) + return EOS_DROPPED; + +- g_renderManager.FlipPage(CThread::m_bStop, (iCurrentClock + iSleepTime) / DVD_TIME_BASE, -1, mDisplayField); ++ g_renderManager.FlipPage(CThread::m_bStop, (iCurrentClock + iSleepTime) / DVD_TIME_BASE, pts, -1, mDisplayField); + + return result; + #else +@@ -1552,6 +1574,22 @@ + g_advancedSettings.m_videoFpsDetect == 0; } - bool CXRandR::Query(bool force, int screennum) -@@ -70,7 +72,7 @@ bool CXRandR::Query(bool force, int screennum) - CStdString cmd; - cmd = getenv("XBMC_BIN_HOME"); - cmd += "/xbmc-xrandr"; -- cmd.append("-q --screen %d", screennum); -+ cmd.AppendFormat(" -q --screen %d", screennum); - - FILE* file = popen(cmd.c_str(),"r"); - if (!file) --- -1.7.10 - - -From a4d6cfe137f6a6a91443cdc3f464a7564efb49eb Mon Sep 17 00:00:00 2001 -From: xbmc -Date: Sun, 2 Dec 2012 15:46:55 +0100 -Subject: [PATCH 73/88] X11: add debug log to print out refresh after xrr - event - ---- - xbmc/windowing/X11/WinSystemX11.cpp | 6 ++++++ - 1 file changed, 6 insertions(+) - -diff --git a/xbmc/windowing/X11/WinSystemX11.cpp b/xbmc/windowing/X11/WinSystemX11.cpp -index ef83133..76c6362 100644 ---- a/xbmc/windowing/X11/WinSystemX11.cpp -+++ b/xbmc/windowing/X11/WinSystemX11.cpp -@@ -685,6 +685,12 @@ void CWinSystemX11::NotifyXRREvent() - XOutput *out = g_xrandr.GetOutput(currentOutput); - XMode mode = g_xrandr.GetCurrentMode(currentOutput); - -+ if (out) -+ CLog::Log(LOGDEBUG, "%s - current output: %s, mode: %s, refresh: %.3f", __FUNCTION__ -+ , out->name.c_str(), mode.id.c_str(), mode.hz); -+ else -+ CLog::Log(LOGWARNING, "%s - output name not set", __FUNCTION__); ++double CDVDPlayerVideo::GetCurrentPts() ++{ ++ double iSleepTime, iRenderPts; ++ int iBufferLevel; + - RESOLUTION_INFO res; - unsigned int i; - bool found(false); --- -1.7.10 - - -From ea768fa98309706665097abbf7d642ab9ee2ceae Mon Sep 17 00:00:00 2001 -From: xbmc -Date: Tue, 11 Dec 2012 11:08:13 +0100 -Subject: [PATCH 74/88] X11: dont call XCloseDisplay on shutdown, it crashes - when powered doen by cec on ATI - ---- - xbmc/windowing/X11/WinSystemX11.cpp | 3 ++- - 1 file changed, 2 insertions(+), 1 deletion(-) - -diff --git a/xbmc/windowing/X11/WinSystemX11.cpp b/xbmc/windowing/X11/WinSystemX11.cpp -index 76c6362..e4e25b2 100644 ---- a/xbmc/windowing/X11/WinSystemX11.cpp -+++ b/xbmc/windowing/X11/WinSystemX11.cpp -@@ -108,7 +108,8 @@ bool CWinSystemX11::DestroyWindowSystem() - //we don't call XCloseDisplay() here, since ati keeps a pointer to our m_dpy - //so instead we just let m_dpy die on exit - // i have seen core dumps on ATI if the display is not closed here -- XCloseDisplay(m_dpy); -+ // crashes when shutting down via cec -+// XCloseDisplay(m_dpy); ++ // get render stats ++ g_renderManager.GetStats(iSleepTime, iRenderPts, iBufferLevel); ++ ++ if( m_stalled ) ++ iRenderPts = DVD_NOPTS_VALUE; ++ else if ( m_speed == DVD_PLAYSPEED_NORMAL) ++ iRenderPts = iRenderPts - max(0.0, iSleepTime); ++ ++ return iRenderPts; ++} ++ + #define MAXFRAMERATEDIFF 0.01 + #define MAXFRAMESERR 1000 + +@@ -1576,7 +1614,7 @@ + double frameduration = m_pullupCorrection.GetFrameDuration(); + + if (frameduration == DVD_NOPTS_VALUE || +- (g_advancedSettings.m_videoFpsDetect == 1 && m_pullupCorrection.GetPatternLength() > 1)) ++ (g_advancedSettings.m_videoFpsDetect == 1 && (m_pullupCorrection.GetPatternLength() > 1 && !m_bFpsInvalid))) + { + //reset the stored framerates if no good framerate was detected + m_fStableFrameRate = 0.0; +@@ -1632,3 +1670,147 @@ + m_iFrameRateCount = 0; + } + } ++ ++int CDVDPlayerVideo::CalcDropRequirement(double pts) ++{ ++ int result = 0; ++ double iSleepTime; ++ double iDecoderPts, iRenderPts; ++ double iInterval; ++ int interlaced; ++ double iGain; ++ double iLateness; ++ bool bNewFrame; ++ int iSkippedDeint = 0; ++ int iBufferLevel; ++ ++ m_droppingStats.m_lastPts = pts; ++ ++ // get decoder stats ++ if (!m_pVideoCodec->GetCodecStats(iDecoderPts, iSkippedDeint, interlaced)) ++ iDecoderPts = pts; ++ if (iDecoderPts == DVD_NOPTS_VALUE) ++ iDecoderPts = pts; ++ ++ // get render stats ++ g_renderManager.GetStats(iSleepTime, iRenderPts, iBufferLevel); ++ ++ if (iBufferLevel < 0) ++ result |= EOS_BUFFER_LEVEL; ++ else if (iBufferLevel < 2) ++ { ++ result |= EOS_BUFFER_LEVEL; ++ CLog::Log(LOGDEBUG,"CDVDPlayerVideo::CalcDropRequirement - hurry: %d", iBufferLevel); ++ } ++ ++ bNewFrame = iDecoderPts != m_droppingStats.m_lastDecoderPts; ++ ++ if (interlaced) ++ iInterval = 2/m_fFrameRate*(double)DVD_TIME_BASE; ++ else ++ iInterval = 1/m_fFrameRate*(double)DVD_TIME_BASE; ++ ++ ++ m_FlipTimeStamp = m_pClock->GetAbsoluteClock() + max(0.0, iSleepTime) + iInterval; ++ ++ if( m_stalled ) ++ m_iCurrentPts = DVD_NOPTS_VALUE; ++ else ++ m_iCurrentPts = iRenderPts - max(0.0, iSleepTime); ++ ++ ++ if (m_droppingStats.m_lastDecoderPts > 0 ++ && bNewFrame ++ && m_bAllowDrop ++ && m_droppingStats.m_dropRequests > 0) ++ { ++ iGain = (iDecoderPts - m_droppingStats.m_lastDecoderPts - iInterval)/(double)DVD_TIME_BASE; ++ if (iSkippedDeint) ++ { ++ CDroppingStats::CGain gain; ++ gain.gain = 1/m_fFrameRate; ++ gain.pts = iDecoderPts; ++ m_droppingStats.m_gain.push_back(gain); ++ m_droppingStats.m_totalGain += gain.gain; ++ result |= EOS_DROPPED; ++ m_droppingStats.m_dropRequests = 0; ++ CLog::Log(LOGDEBUG,"CDVDPlayerVideo::CalcDropRequirement - dropped de-interlacing cycle, Sleeptime: %f, Bufferlevel: %d", iSleepTime, iBufferLevel); ++ } ++ else if (iGain > 1/m_fFrameRate) ++ { ++ CDroppingStats::CGain gain; ++ gain.gain = iGain; ++ gain.pts = iDecoderPts; ++ m_droppingStats.m_gain.push_back(gain); ++ m_droppingStats.m_totalGain += iGain; ++ result |= EOS_DROPPED; ++ m_droppingStats.m_dropRequests = 0; ++ CLog::Log(LOGDEBUG,"CDVDPlayerVideo::CalcDropRequirement - dropped in decoder, Sleeptime: %f, Bufferlevel: %d, Gain: %f", iSleepTime, iBufferLevel, iGain); ++ } ++ } ++ m_droppingStats.m_lastDecoderPts = iDecoderPts; ++ ++ // subtract gains ++ while (!m_droppingStats.m_gain.empty() && ++ iRenderPts >= m_droppingStats.m_gain.front().pts) ++ { ++ m_droppingStats.m_totalGain -= m_droppingStats.m_gain.front().gain; ++ m_droppingStats.m_gain.pop_front(); ++ } ++ ++ // calculate lateness ++ iLateness = iSleepTime + m_droppingStats.m_totalGain; ++ if (iLateness < 0 && m_speed) ++ { ++ if (bNewFrame) ++ m_droppingStats.m_lateFrames++; ++ ++ // if lateness is smaller than frametime, we observe this state ++ // for 10 cycles ++ if (m_droppingStats.m_lateFrames > 10 || iLateness < -2/m_fFrameRate) ++ { ++ // is frame allowed to skip ++ if (m_iNrOfPicturesNotToSkip <= 0) ++ { ++ result |= EOS_VERYLATE; ++ ++ // drop in output ++ if (m_droppingStats.m_dropRequests > 7 && g_graphicsContext.IsFullScreenVideo()) ++ { ++ m_droppingStats.m_dropRequests--; //decrease so we only drop half the frames ++ m_droppingStats.m_requestOutputDrop = true; ++ } ++ else if (bNewFrame) ++ m_droppingStats.m_dropRequests++; ++ } ++ } ++ } ++ else ++ { ++ m_droppingStats.m_dropRequests = 0; ++ m_droppingStats.m_lateFrames = 0; ++ m_droppingStats.m_requestOutputDrop = false; ++ } ++ m_droppingStats.m_lastRenderPts = iRenderPts; ++ return result; ++} ++ ++void CDroppingStats::Reset() ++{ ++ m_gain.clear(); ++ m_totalGain = 0; ++ m_lastDecoderPts = 0; ++ m_lastRenderPts = 0; ++ m_lateFrames = 0; ++ m_dropRequests = 0; ++ m_requestOutputDrop = false; ++} ++ ++void CDroppingStats::AddOutputDropGain(double pts, double frametime) ++{ ++ CDroppingStats::CGain gain; ++ gain.gain = frametime; ++ gain.pts = pts; ++ m_gain.push_back(gain); ++ m_totalGain += frametime; ++} +diff -Naur xbmc-12.0.4/xbmc/cores/dvdplayer/DVDPlayerVideo.h xbmc-12.0.4.patch/xbmc/cores/dvdplayer/DVDPlayerVideo.h +--- xbmc-12.0.4/xbmc/cores/dvdplayer/DVDPlayerVideo.h 2013-03-08 13:01:31.000000000 +0100 ++++ xbmc-12.0.4.patch/xbmc/cores/dvdplayer/DVDPlayerVideo.h 2013-03-10 13:00:12.328988127 +0100 +@@ -37,6 +37,27 @@ + + #define VIDEO_PICTURE_QUEUE_SIZE 1 + ++class CDroppingStats ++{ ++public: ++ void Reset(); ++ void AddOutputDropGain(double pts, double frametime); ++ struct CGain ++ { ++ double gain; ++ double pts; ++ }; ++ std::deque m_gain; ++ double m_totalGain; ++ double m_lastDecoderPts; ++ double m_lastRenderPts; ++ double m_lastPts; ++ unsigned int m_lateFrames; ++ unsigned int m_dropRequests; ++ bool m_requestOutputDrop; ++}; ++ ++ + class CDVDPlayerVideo : public CThread + { + public: +@@ -88,7 +109,7 @@ + + bool InitializedOutputDevice(); + +- double GetCurrentPts() { return m_iCurrentPts; } ++ double GetCurrentPts(); + int GetPullupCorrection() { return m_pullupCorrection.GetPatternLength(); } + + double GetOutputDelay(); /* returns the expected delay, from that a packet is put in queue */ +@@ -110,6 +131,7 @@ + #define EOS_ABORT 1 + #define EOS_DROPPED 2 + #define EOS_VERYLATE 4 ++#define EOS_BUFFER_LEVEL 8 + + void AutoCrop(DVDVideoPicture* pPicture); + void AutoCrop(DVDVideoPicture *pPicture, RECT &crop); +@@ -135,6 +157,7 @@ + + void ResetFrameRateCalc(); + void CalcFrameRate(); ++ int CalcDropRequirement(double pts); + + double m_fFrameRate; //framerate of the video currently playing + bool m_bCalcFrameRate; //if we should calculate the framerate from the timestamps +@@ -195,5 +218,7 @@ + CPullupCorrection m_pullupCorrection; + + std::list m_packets; ++ ++ CDroppingStats m_droppingStats; + }; + +diff -Naur xbmc-12.0.4/xbmc/cores/omxplayer/OMXPlayerVideo.cpp xbmc-12.0.4.patch/xbmc/cores/omxplayer/OMXPlayerVideo.cpp +--- xbmc-12.0.4/xbmc/cores/omxplayer/OMXPlayerVideo.cpp 2013-03-10 12:59:17.639379413 +0100 ++++ xbmc-12.0.4.patch/xbmc/cores/omxplayer/OMXPlayerVideo.cpp 2013-03-10 13:01:10.564569304 +0100 +@@ -338,25 +338,16 @@ + m_dropbase = 0.0f; + #endif + +- // DVDPlayer sleeps until m_iSleepEndTime here before calling FlipPage. +- // Video playback in asynchronous in OMXPlayer, so we don't want to do that here, as it prevents the video fifo from being kept full. +- // So, we keep track of when FlipPage would have been called on DVDPlayer and return early if it is not time. +- // m_iSleepEndTime == DVD_NOPTS_VALUE means we are not waiting to call FlipPage, otherwise it is the time we want to call FlipPage +- if (m_iSleepEndTime == DVD_NOPTS_VALUE) { +- m_iSleepEndTime = iCurrentClock + iSleepTime; +- } +- +- if (!CThread::m_bStop && m_av_clock->GetAbsoluteClock(false) < m_iSleepEndTime + DVD_MSEC_TO_TIME(500)) ++ int buffer = g_renderManager.WaitForBuffer(m_bStop, 0); ++ if (buffer < 0) + return; + +- double pts_media = m_av_clock->OMXMediaTime(false, false); +- ProcessOverlays(iGroupId, pts_media); +- +- g_renderManager.FlipPage(CThread::m_bStop, m_iSleepEndTime / DVD_TIME_BASE, -1, FS_NONE); +- +- m_iSleepEndTime = DVD_NOPTS_VALUE; ++ double pts_overlay = m_av_clock->OMXMediaTime(false, false) ++ + 2* (double)DVD_TIME_BASE / g_graphicsContext.GetFPS(); ++ ProcessOverlays(iGroupId, pts_overlay); + +- //m_av_clock->WaitAbsoluteClock((iCurrentClock + iSleepTime)); ++ double timestamp = CDVDClock::GetAbsoluteClock(false) + 2 / g_graphicsContext.GetFPS(); ++ g_renderManager.FlipPage(CThread::m_bStop, timestamp, -1, FS_NONE); + } + + void OMXPlayerVideo::Process() +@@ -789,7 +780,7 @@ + + if(!g_renderManager.Configure(width, height, + iDisplayWidth, iDisplayHeight, m_fFrameRate, flags, format, 0, +- m_hints.orientation)) ++ m_hints.orientation, true)) + { + CLog::Log(LOGERROR, "%s - failed to configure renderer", __FUNCTION__); + return; +diff -Naur xbmc-12.0.4/xbmc/cores/VideoRenderers/BaseRenderer.h xbmc-12.0.4.patch/xbmc/cores/VideoRenderers/BaseRenderer.h +--- xbmc-12.0.4/xbmc/cores/VideoRenderers/BaseRenderer.h 2013-03-08 13:01:31.000000000 +0100 ++++ xbmc-12.0.4.patch/xbmc/cores/VideoRenderers/BaseRenderer.h 2013-03-10 13:00:12.284988442 +0100 +@@ -26,10 +26,11 @@ + + #define MAX_PLANES 3 + #define MAX_FIELDS 3 ++#define NUM_BUFFERS 10 + + typedef struct YV12Image + { +- BYTE * plane[MAX_PLANES]; ++ uint8_t* plane[MAX_PLANES]; + int planesize[MAX_PLANES]; + unsigned stride[MAX_PLANES]; + unsigned width; +@@ -80,10 +81,13 @@ + void GetVideoRect(CRect &source, CRect &dest); + float GetAspectRatio() const; + +- virtual bool AddVideoPicture(DVDVideoPicture* picture) { return false; } ++ virtual bool AddVideoPicture(DVDVideoPicture* picture, int index) { return false; } + virtual void Flush() {}; + + virtual unsigned int GetProcessorSize() { return 0; } ++ virtual unsigned int GetMaxBufferSize() { return 0; } ++ virtual void SetBufferSize(int numBuffers) { } ++ virtual void ReleaseBuffer(int idx) { } + + virtual bool Supports(ERENDERFEATURE feature) { return false; } + +diff -Naur xbmc-12.0.4/xbmc/cores/VideoRenderers/LinuxRendererGL.cpp xbmc-12.0.4.patch/xbmc/cores/VideoRenderers/LinuxRendererGL.cpp +--- xbmc-12.0.4/xbmc/cores/VideoRenderers/LinuxRendererGL.cpp 2013-03-08 13:01:31.000000000 +0100 ++++ xbmc-12.0.4.patch/xbmc/cores/VideoRenderers/LinuxRendererGL.cpp 2013-03-10 13:00:12.333988091 +0100 +@@ -63,6 +63,9 @@ + VA_MICRO_VERSION == 0 && VA_SDS_VERSION < 5))) + + #endif ++#ifdef HAVE_LIBXVBA ++#include "cores/dvdplayer/DVDCodecs/Video/XVBA.h" ++#endif + + #ifdef TARGET_DARWIN + #include "osx/CocoaInterface.h" +@@ -129,6 +132,9 @@ + #ifdef HAVE_LIBVDPAU + vdpau = NULL; + #endif ++#ifdef HAVE_LIBXVBA ++ xvba = NULL; ++#endif + } + + CLinuxRendererGL::YUVBUFFER::~YUVBUFFER() +@@ -235,14 +241,6 @@ + return true; + } + +- +-void CLinuxRendererGL::ManageTextures() +-{ +- m_NumYV12Buffers = 2; +- //m_iYV12RenderBuffer = 0; +- return; +-} +- + bool CLinuxRendererGL::ValidateRenderTarget() + { + if (!m_bValidated) +@@ -259,7 +257,7 @@ + // function pointer for texture might change in + // call to LoadShaders + glFinish(); +- for (int i = 0 ; i < m_NumYV12Buffers ; i++) ++ for (int i = 0 ; i < NUM_BUFFERS ; i++) + (this->*m_textureDelete)(i); + + // trigger update of video filters +@@ -603,13 +601,31 @@ + glFinish(); + m_bValidated = false; + m_fbo.fbo.Cleanup(); ++ m_iYV12RenderBuffer = 0; ++} ++ ++void CLinuxRendererGL::ReleaseBuffer(int idx) ++{ ++ YUVBUFFER &buf = m_buffers[idx]; ++#ifdef HAVE_LIBVDPAU ++ SAFE_RELEASE(buf.vdpau); ++#endif ++#ifdef HAVE_LIBXVBA ++ SAFE_RELEASE(buf.xvba); ++#endif ++#ifdef HAVE_LIBVA ++ buf.vaapi.surface.reset(); ++#endif ++#ifdef TARGET_DARWIN ++ if (buf.cvBufferRef) ++ CVBufferRelease(buf.cvBufferRef); ++#endif + } + + void CLinuxRendererGL::Update(bool bPauseDrawing) + { + if (!m_bConfigured) return; + ManageDisplay(); +- ManageTextures(); + } + + void CLinuxRendererGL::RenderUpdate(bool clear, DWORD flags, DWORD alpha) +@@ -625,7 +641,6 @@ } - // m_SDLSurface is free()'d by SDL_Quit(). --- -1.7.10 - - -From aaf6be8480620bed4631c9da17b62c15d260d298 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Gr=C3=A9gory=20Coutant?= -Date: Wed, 12 Dec 2012 19:49:47 +0100 -Subject: [PATCH 75/88] x11: support for multiple x screens - ---- - xbmc/windowing/X11/XRandR.cpp | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/xbmc/windowing/X11/XRandR.cpp b/xbmc/windowing/X11/XRandR.cpp -index 533e03d..7a16488 100644 ---- a/xbmc/windowing/X11/XRandR.cpp -+++ b/xbmc/windowing/X11/XRandR.cpp -@@ -92,7 +92,7 @@ bool CXRandR::Query(bool force, int screennum) - pclose(file); + ManageDisplay(); +- ManageTextures(); - TiXmlElement *pRootElement = xmlDoc.RootElement(); -- if (strcasecmp(pRootElement->Value(), "screen") != screennum) -+ if (atoi(pRootElement->Attribute("id")) != screennum) + g_graphicsContext.BeginPaint(); + +@@ -763,11 +778,6 @@ + + m_buffers[m_iYV12RenderBuffer].flipindex = ++m_flipindex; + +-#ifdef HAVE_LIBVDPAU +- if((m_renderMethod & RENDER_VDPAU) && m_buffers[m_iYV12RenderBuffer].vdpau) +- m_buffers[m_iYV12RenderBuffer].vdpau->Present(); +-#endif +- + return; + } + +@@ -782,7 +792,6 @@ + m_resolution = RES_DESKTOP; + + m_iYV12RenderBuffer = 0; +- m_NumYV12Buffers = 2; + + m_formats.push_back(RENDER_FMT_YUV420P); + GLint size; +@@ -851,6 +860,14 @@ + m_scalingMethod = VS_SCALINGMETHOD_LINEAR; + } + ++ // no need to scale if source equals dest ++ bool scale = ((float)m_sourceHeight != m_destRect.Height()) || ++ ((float)m_sourceWidth != m_destRect.Width()); ++ if(!scale) ++ { ++ m_scalingMethod = VS_SCALINGMETHOD_LINEAR; ++ } ++ + if (m_pVideoFilterShader) { - // TODO ERROR - return false; --- -1.7.10 - - -From 5c8a99221143e88cc2d076516d78106e09ac2a60 Mon Sep 17 00:00:00 2001 -From: xbmc -Date: Thu, 20 Dec 2012 19:35:38 +0100 -Subject: [PATCH 76/88] fix compile error after recent change - ---- - xbmc/settings/GUIWindowSettingsCategory.cpp | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/xbmc/settings/GUIWindowSettingsCategory.cpp b/xbmc/settings/GUIWindowSettingsCategory.cpp -index b9f18e4..cacb32a 100644 ---- a/xbmc/settings/GUIWindowSettingsCategory.cpp -+++ b/xbmc/settings/GUIWindowSettingsCategory.cpp -@@ -2453,7 +2453,7 @@ void CGUIWindowSettingsCategory::FillInMonitors(CStdString strSetting) - { - // we expect "videoscreen.monitor" but it might be hidden on some platforms, - // so check that we actually have a visable control. -- CBaseSettingControl *control = GetSetting(strSetting); -+ BaseSettingControlPtr control = GetSetting(strSetting); - if (control) - { - control->SetDelayed(); --- -1.7.10 - - -From 9c3bd38c6e2f8da31d8627115f176f2c19e7504e Mon Sep 17 00:00:00 2001 -From: xbmc -Date: Mon, 24 Dec 2012 16:02:42 +0100 -Subject: [PATCH 77/88] pvr: increase changes counter of stream on stream - change, cosmetics after - dd307930d39d92f145a01a16600cd00e01ec39be - ---- - xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxPVRClient.cpp | 5 ++--- - 1 file changed, 2 insertions(+), 3 deletions(-) - -diff --git a/xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxPVRClient.cpp b/xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxPVRClient.cpp -index 8c984f6..034e545 100644 ---- a/xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxPVRClient.cpp -+++ b/xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxPVRClient.cpp -@@ -348,9 +348,7 @@ void CDVDDemuxPVRClient::RequestStreams() - if (stm) - { - st = dynamic_cast(stm); -- if (!st -- || (st->codec != (CodecID)props.stream[i].iCodecId) -- || (st->iChannels != props.stream[i].iChannels)) -+ if (!st || (st->codec != (CodecID)props.stream[i].iCodecId)) - DisposeStream(i); - } - if (!m_streams[i]) -@@ -367,6 +365,7 @@ void CDVDDemuxPVRClient::RequestStreams() - st->iBitsPerSample = props.stream[i].iBitsPerSample; - m_streams[i] = st; - st->m_parser_split = true; -+ st->changes++; - } - else if (props.stream[i].iCodecType == AVMEDIA_TYPE_VIDEO) + m_pVideoFilterShader->Free(); +@@ -879,7 +896,7 @@ + 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 (((m_renderMethod & RENDER_VDPAU) || (m_renderMethod & RENDER_VAAPI) || (m_renderMethod & RENDER_XVBA)) && m_nonLinStretch) { --- -1.7.10 - - -From 8f0c31f9d2f2cb438c74e83185480dc1d6ff1f1a Mon Sep 17 00:00:00 2001 -From: xbmc -Date: Thu, 17 Jan 2013 16:03:22 +0100 -Subject: [PATCH 78/88] X11: add keymapping for XF86XK_Sleep - ---- - xbmc/windowing/WinEventsX11.cpp | 1 + - 1 file changed, 1 insertion(+) - -diff --git a/xbmc/windowing/WinEventsX11.cpp b/xbmc/windowing/WinEventsX11.cpp -index c31877e..ed31c04 100644 ---- a/xbmc/windowing/WinEventsX11.cpp -+++ b/xbmc/windowing/WinEventsX11.cpp -@@ -143,6 +143,7 @@ - , {XK_Break, XBMCK_BREAK} - , {XK_Menu, XBMCK_MENU} - , {XF86XK_PowerOff, XBMCK_POWER} -+, {XF86XK_Sleep, XBMCK_SLEEP} - , {XK_EcuSign, XBMCK_EURO} - , {XK_Undo, XBMCK_UNDO} - /* Media keys */ --- -1.7.10 - - -From 9e099b7ba03687449ae5c725b48bda3ee378408b Mon Sep 17 00:00:00 2001 -From: xbmc -Date: Mon, 21 Jan 2013 09:00:19 +0100 -Subject: [PATCH 79/88] X11: remove toggle full screen after resume - ---- - xbmc/powermanagement/PowerManager.cpp | 5 ----- - 1 file changed, 5 deletions(-) - -diff --git a/xbmc/powermanagement/PowerManager.cpp b/xbmc/powermanagement/PowerManager.cpp -index a5534c9..7e2ddc6 100644 ---- a/xbmc/powermanagement/PowerManager.cpp -+++ b/xbmc/powermanagement/PowerManager.cpp -@@ -223,11 +223,6 @@ void CPowerManager::OnWake() + m_pVideoFilterShader = new StretchFilterShader(); + if (!m_pVideoFilterShader->CompileAndLink()) +@@ -965,6 +982,11 @@ + CLog::Log(LOGNOTICE, "GL: Using CVBREF render method"); + m_renderMethod = RENDER_CVREF; + } ++ else if (m_format == RENDER_FMT_XVBA) ++ { ++ CLog::Log(LOGNOTICE, "GL: Using XVBA render method"); ++ m_renderMethod = RENDER_XVBA; ++ } + else + { + int requestedMethod = g_guiSettings.GetInt("videoplayer.rendermethod"); +@@ -1095,6 +1117,12 @@ + 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; +@@ -1107,6 +1135,12 @@ + m_textureCreate = &CLinuxRendererGL::CreateCVRefTexture; + m_textureDelete = &CLinuxRendererGL::DeleteCVRefTexture; + } ++ else if (m_format == RENDER_FMT_XVBA) ++ { ++ m_textureUpload = &CLinuxRendererGL::UploadXVBATexture; ++ m_textureCreate = &CLinuxRendererGL::CreateXVBATexture; ++ m_textureDelete = &CLinuxRendererGL::DeleteXVBATexture; ++ } + else + { + // setup default YV12 texture handlers +@@ -1170,7 +1204,10 @@ + m_currentField = FIELD_FULL; + + // call texture load function ++ m_skipRender = false; + (this->*m_textureUpload)(renderBuffer); ++ if (m_skipRender) ++ return; + + if (m_renderMethod & RENDER_GLSL) + { +@@ -1179,12 +1216,21 @@ + { + case RQ_LOW: + case RQ_SINGLEPASS: +- RenderSinglePass(renderBuffer, m_currentField); ++ if (m_format == RENDER_FMT_VDPAU_420 && m_currentField == FIELD_FULL) ++ RenderProgressiveWeave(renderBuffer, m_currentField); ++ else ++ RenderSinglePass(renderBuffer, m_currentField); + VerifyGLState(); + break; + + case RQ_MULTIPASS: +- RenderMultiPass(renderBuffer, m_currentField); ++ if (m_format == RENDER_FMT_VDPAU_420 && m_currentField == FIELD_FULL) ++ RenderProgressiveWeave(renderBuffer, m_currentField); ++ else ++ { ++ RenderToFBO(renderBuffer, m_currentField); ++ RenderFromFBO(); ++ } + VerifyGLState(); + break; + } +@@ -1207,6 +1253,13 @@ + RenderVAAPI(renderBuffer, m_currentField); + } + #endif ++#ifdef HAVE_LIBXVBA ++ else if (m_renderMethod & RENDER_XVBA) ++ { ++ UpdateVideoFilter(); ++ RenderXVBA(renderBuffer, m_currentField); ++ } ++#endif + else + { + // RENDER_CVREF uses the same render as the default case +@@ -1307,13 +1360,7 @@ + VerifyGLState(); + } + +-void CLinuxRendererGL::RenderMultiPass(int index, int field) +-{ +- RenderToFBO(index, field); +- RenderFromFBO(); +-} +- +-void CLinuxRendererGL::RenderToFBO(int index, int field) ++void CLinuxRendererGL::RenderToFBO(int index, int field, bool weave /*= false*/) + { + YUVPLANES &planes = m_buffers[index].fields[field]; + +@@ -1415,6 +1462,8 @@ + } + m_fbo.width *= planes[0].pixpertex_x; + m_fbo.height *= planes[0].pixpertex_y; ++ if (weave) ++ m_fbo.height *= 2; + + // 1st Pass to video frame size + glBegin(GL_QUADS); +@@ -1533,20 +1582,40 @@ + VerifyGLState(); + } + ++void CLinuxRendererGL::RenderProgressiveWeave(int index, int field) ++{ ++ bool scaleUp = (int)m_sourceHeight < g_graphicsContext.GetHeight() || (int)m_sourceWidth < g_graphicsContext.GetWidth(); ++ ++ if (m_fbo.fbo.IsSupported() && (scaleUp || m_renderQuality == RQ_MULTIPASS)) ++ { ++ glEnable(GL_POLYGON_STIPPLE); ++ glPolygonStipple(stipple_weave); ++ RenderToFBO(index, FIELD_TOP, true); ++ glPolygonStipple(stipple_weave+4); ++ RenderToFBO(index, FIELD_BOT, true); ++ glDisable(GL_POLYGON_STIPPLE); ++ RenderFromFBO(); ++ } ++ else ++ { ++ glEnable(GL_POLYGON_STIPPLE); ++ glPolygonStipple(stipple_weave); ++ RenderSinglePass(index, FIELD_TOP); ++ glPolygonStipple(stipple_weave+4); ++ RenderSinglePass(index, FIELD_BOT); ++ glDisable(GL_POLYGON_STIPPLE); ++ } ++} ++ + void CLinuxRendererGL::RenderVDPAU(int index, int field) + { + #ifdef HAVE_LIBVDPAU +- YUVPLANE &plane = m_buffers[index].fields[field][0]; +- CVDPAU *vdpau = m_buffers[m_iYV12RenderBuffer].vdpau; +- +- if (!vdpau) +- return; ++ YUVPLANE &plane = m_buffers[index].fields[0][1]; + + glEnable(m_textureTarget); + glActiveTextureARB(GL_TEXTURE0); +- glBindTexture(m_textureTarget, plane.id); + +- vdpau->BindPixmap(); ++ glBindTexture(m_textureTarget, plane.id); + + // Try some clamping or wrapping + glTexParameteri(m_textureTarget, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); +@@ -1604,8 +1673,6 @@ + if (m_pVideoFilterShader) + m_pVideoFilterShader->Disable(); + +- vdpau->ReleasePixmap(); +- + glBindTexture (m_textureTarget, 0); + glDisable(m_textureTarget); + #endif +@@ -1700,6 +1767,77 @@ + #endif + } + ++void CLinuxRendererGL::RenderXVBA(int index, int field) ++{ ++#ifdef HAVE_LIBXVBA ++ YUVPLANE &plane = m_buffers[index].fields[0][1]; ++ ++ glEnable(m_textureTarget); ++ glActiveTextureARB(GL_TEXTURE0); ++ ++ glBindTexture(m_textureTarget, plane.id); ++ ++ // Try some clamping or wrapping ++ glTexParameteri(m_textureTarget, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); ++ glTexParameteri(m_textureTarget, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); ++ ++ if (m_pVideoFilterShader) ++ { ++ GLint filter; ++ if (!m_pVideoFilterShader->GetTextureFilter(filter)) ++ filter = m_scalingMethod == VS_SCALINGMETHOD_NEAREST ? GL_NEAREST : GL_LINEAR; ++ ++ glTexParameteri(m_textureTarget, GL_TEXTURE_MAG_FILTER, filter); ++ glTexParameteri(m_textureTarget, GL_TEXTURE_MIN_FILTER, filter); ++ m_pVideoFilterShader->SetSourceTexture(0); ++ m_pVideoFilterShader->SetWidth(m_sourceWidth); ++ m_pVideoFilterShader->SetHeight(m_sourceHeight); ++ ++ //disable non-linear stretch when a dvd menu is shown, parts of the menu are rendered through the overlay renderer ++ //having non-linear stretch on breaks the alignment ++ if (g_application.m_pPlayer && g_application.m_pPlayer->IsInMenu()) ++ m_pVideoFilterShader->SetNonLinStretch(1.0); ++ else ++ m_pVideoFilterShader->SetNonLinStretch(pow(g_settings.m_fPixelRatio, g_advancedSettings.m_videoNonLinStretchRatio)); ++ ++ m_pVideoFilterShader->Enable(); ++ } ++ else ++ { ++ GLint filter = m_scalingMethod == VS_SCALINGMETHOD_NEAREST ? GL_NEAREST : GL_LINEAR; ++ glTexParameteri(m_textureTarget, GL_TEXTURE_MAG_FILTER, filter); ++ glTexParameteri(m_textureTarget, GL_TEXTURE_MIN_FILTER, filter); ++ } ++ ++ glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); ++ VerifyGLState(); ++ ++ glBegin(GL_QUADS); ++ if (m_textureTarget==GL_TEXTURE_2D) ++ { ++ glTexCoord2f(plane.rect.x1, plane.rect.y1); glVertex2f(m_destRect.x1, m_destRect.y1); ++ glTexCoord2f(plane.rect.x2, plane.rect.y1); glVertex2f(m_destRect.x2, m_destRect.y1); ++ glTexCoord2f(plane.rect.x2, plane.rect.y2); glVertex2f(m_destRect.x2, m_destRect.y2); ++ glTexCoord2f(plane.rect.x1, plane.rect.y2); glVertex2f(m_destRect.x1, m_destRect.y2); ++ } ++ else ++ { ++ glTexCoord2f(m_destRect.x1, m_destRect.y1); glVertex4f(m_destRect.x1, m_destRect.y1, 0.0f, 0.0f); ++ glTexCoord2f(m_destRect.x2, m_destRect.y1); glVertex4f(m_destRect.x2, m_destRect.y1, 1.0f, 0.0f); ++ glTexCoord2f(m_destRect.x2, m_destRect.y2); glVertex4f(m_destRect.x2, m_destRect.y2, 1.0f, 1.0f); ++ glTexCoord2f(m_destRect.x1, m_destRect.y2); glVertex4f(m_destRect.x1, m_destRect.y2, 0.0f, 1.0f); ++ } ++ glEnd(); ++ VerifyGLState(); ++ ++ if (m_pVideoFilterShader) ++ m_pVideoFilterShader->Disable(); ++ ++ glBindTexture (m_textureTarget, 0); ++ glDisable(m_textureTarget); ++#endif ++} ++ + void CLinuxRendererGL::RenderSoftware(int index, int field) + { + // used for textues uploaded from rgba or CVPixelBuffers. +@@ -2290,12 +2428,14 @@ + { + #ifdef HAVE_LIBVDPAU + YUVPLANE &plane = m_buffers[index].fields[0][0]; ++ YUVFIELDS &fields = m_buffers[index].fields; + + SAFE_RELEASE(m_buffers[index].vdpau); + + if(plane.id && glIsTexture(plane.id)) + glDeleteTextures(1, &plane.id); + plane.id = 0; ++ fields[0][1].id = 0; + #endif + } + +@@ -2329,11 +2469,152 @@ + void CLinuxRendererGL::UploadVDPAUTexture(int index) + { + #ifdef HAVE_LIBVDPAU ++ VDPAU::CVdpauRenderPicture *vdpau = m_buffers[index].vdpau; ++ ++ unsigned int flipindex = m_buffers[index].flipindex; ++ YUVFIELDS &fields = m_buffers[index].fields; ++ YUVPLANE &plane = fields[0][0]; ++ ++ if (!vdpau || !vdpau->valid) ++ { ++ m_eventTexturesDone[index]->Set(); ++ m_skipRender = true; ++ return; ++ } ++ ++ fields[0][1].id = vdpau->texture[0]; ++ + m_eventTexturesDone[index]->Set(); +- glPixelStorei(GL_UNPACK_ALIGNMENT,1); //what's this for? + #endif + } + ++void CLinuxRendererGL::DeleteVDPAUTexture420(int index) ++{ ++#ifdef HAVE_LIBVDPAU ++ YUVPLANE &plane = m_buffers[index].fields[0][0]; ++ YUVFIELDS &fields = m_buffers[index].fields; ++ ++ SAFE_RELEASE(m_buffers[index].vdpau); ++ ++ if(plane.id && glIsTexture(plane.id)) ++ glDeleteTextures(1, &plane.id); ++ plane.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; ++ } ++ ++ glEnable(m_textureTarget); ++ glGenTextures(1, &plane.id); ++ glDisable(m_textureTarget); ++ ++ m_eventTexturesDone[index]->Set(); ++#endif ++ return true; ++} ++ ++void CLinuxRendererGL::UploadVDPAUTexture420(int index) ++{ ++#ifdef HAVE_LIBVDPAU ++ VDPAU::CVdpauRenderPicture *vdpau = m_buffers[index].vdpau; ++ YV12Image &im = m_buffers[index].image; ++ ++ unsigned int flipindex = m_buffers[index].flipindex; ++ YUVFIELDS &fields = m_buffers[index].fields; ++ YUVPLANE &plane = fields[0][0]; ++ ++ if (!vdpau || !vdpau->valid) ++ { ++ m_eventTexturesDone[index]->Set(); ++ m_skipRender = true; ++ return; ++ } ++ ++ im.height = vdpau->texHeight; ++ im.width = vdpau->texWidth; ++ ++ // YUV ++ for (int f = FIELD_FULL; f<=FIELD_BOT ; f++) ++ { ++ int fieldshift = (f==FIELD_FULL) ? 0 : 1; ++ YUVPLANES &planes = fields[f]; ++ ++ planes[0].texwidth = im.width; ++ planes[0].texheight = im.height >> fieldshift; ++ ++ 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[2][0].id = vdpau->texture[1]; ++ fields[2][1].id = vdpau->texture[3]; ++ ++ glEnable(m_textureTarget); ++ for (int f = 1; f < 3; 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(); ++ } ++ fields[f][2].id = fields[f][1].id; ++ } ++ CalculateTextureSourceRects(index, 3); ++ glDisable(m_textureTarget); ++ ++ m_eventTexturesDone[index]->Set(); ++#endif ++} + + void CLinuxRendererGL::DeleteVAAPITexture(int index) + { +@@ -2465,7 +2746,7 @@ + || status == VA_STATUS_ERROR_INVALID_DISPLAY) + { + va.display->lost(true); +- for(int i = 0; i < NUM_BUFFERS; i++) ++ for(int i = 0; i < m_NumYV12Buffers; i++) + { + m_buffers[i].vaapi.display.reset(); + m_buffers[i].vaapi.surface.reset(); +@@ -2608,6 +2889,91 @@ + return true; + } + ++void CLinuxRendererGL::DeleteXVBATexture(int index) ++{ ++#ifdef HAVE_LIBXVBA ++ YUVPLANE &plane = m_buffers[index].fields[0][0]; ++ YUVFIELDS &fields = m_buffers[index].fields; ++ ++ SAFE_RELEASE(m_buffers[index].xvba); ++ ++ if(plane.id && glIsTexture(plane.id)) ++ glDeleteTextures(1, &plane.id); ++ plane.id = 0; ++ fields[0][1].id = 0; ++#endif ++} ++ ++bool CLinuxRendererGL::CreateXVBATexture(int index) ++{ ++#ifdef HAVE_LIBXVBA ++ YV12Image &im = m_buffers[index].image; ++ YUVFIELDS &fields = m_buffers[index].fields; ++ YUVPLANE &plane = fields[0][0]; ++ ++ DeleteXVBATexture(index); ++ ++ memset(&im , 0, sizeof(im)); ++ memset(&fields, 0, sizeof(fields)); ++ ++ glGenTextures(1, &plane.id); ++ ++ m_eventTexturesDone[index]->Set(); ++#endif ++ return true; ++} ++ ++void CLinuxRendererGL::UploadXVBATexture(int index) ++{ ++#ifdef HAVE_LIBXVBA ++ XVBA::CXvbaRenderPicture *xvba = m_buffers[index].xvba; ++ YV12Image &im = m_buffers[index].image; ++ ++ YUVFIELDS &fields = m_buffers[index].fields; ++ YUVPLANE &plane = fields[0][1]; ++ ++ if (!xvba || !xvba->valid) ++ { ++ m_eventTexturesDone[index]->Set(); ++ m_skipRender = true; ++ return; ++ } ++ ++ plane.id = xvba->texture; ++ ++ im.height = xvba->texHeight; ++ im.width = xvba->texWidth; ++ ++ plane.texwidth = xvba->texWidth; ++ plane.texheight = xvba->texHeight; ++ plane.pixpertex_x = 1; ++ plane.pixpertex_y = 1; ++ ++ plane.rect = m_sourceRect; ++ plane.width = im.width; ++ plane.height = im.height; ++ ++ plane.height /= plane.pixpertex_y; ++ plane.rect.y1 /= plane.pixpertex_y; ++ plane.rect.y2 /= plane.pixpertex_y; ++ plane.width /= plane.pixpertex_x; ++ plane.rect.x1 /= plane.pixpertex_x; ++ plane.rect.x2 /= plane.pixpertex_x; ++ ++ if (m_textureTarget == GL_TEXTURE_2D) ++ { ++ plane.height /= plane.texheight; ++ plane.rect.y1 /= plane.texheight; ++ plane.rect.y2 /= plane.texheight; ++ plane.width /= plane.texwidth; ++ plane.rect.x1 /= plane.texwidth; ++ plane.rect.x2 /= plane.texwidth; ++ } ++ ++ m_eventTexturesDone[index]->Set(); ++#endif ++} ++ + void CLinuxRendererGL::UploadYUV422PackedTexture(int source) + { + YUVBUFFER& buf = m_buffers[source]; +@@ -3187,12 +3553,15 @@ + { + if(feature == RENDERFEATURE_BRIGHTNESS) + { +- if ((m_renderMethod & RENDER_VDPAU) && !g_guiSettings.GetBool("videoplayer.vdpaustudiolevel")) ++ if (m_renderMethod & RENDER_VDPAU) + return true; + + if (m_renderMethod & RENDER_VAAPI) + return false; + ++ if (m_renderMethod & RENDER_XVBA) ++ return false; ++ + return (m_renderMethod & RENDER_GLSL) + || (m_renderMethod & RENDER_ARB) + || ((m_renderMethod & RENDER_SW) && glewIsSupported("GL_ARB_imaging") == GL_TRUE); +@@ -3200,12 +3569,15 @@ + + if(feature == RENDERFEATURE_CONTRAST) + { +- if ((m_renderMethod & RENDER_VDPAU) && !g_guiSettings.GetBool("videoplayer.vdpaustudiolevel")) ++ if (m_renderMethod & RENDER_VDPAU) + return true; + + if (m_renderMethod & RENDER_VAAPI) + return false; + ++ if (m_renderMethod & RENDER_XVBA) ++ return false; ++ + return (m_renderMethod & RENDER_GLSL) + || (m_renderMethod & RENDER_ARB) + || ((m_renderMethod & RENDER_SW) && glewIsSupported("GL_ARB_imaging") == GL_TRUE); +@@ -3229,7 +3601,8 @@ + if (feature == RENDERFEATURE_NONLINSTRETCH) + { + if (((m_renderMethod & RENDER_GLSL) && !(m_renderMethod & RENDER_POT)) || +- (m_renderMethod & RENDER_VDPAU) || (m_renderMethod & RENDER_VAAPI)) ++ (m_renderMethod & RENDER_VDPAU) || (m_renderMethod & RENDER_VAAPI) || ++ (m_renderMethod & RENDER_XVBA)) + return true; + } + +@@ -3271,12 +3644,13 @@ + if(method == VS_INTERLACEMETHOD_AUTO) + return true; + +- if(m_renderMethod & RENDER_VDPAU) ++ if(m_renderMethod & RENDER_VDPAU || ++ m_format == RENDER_FMT_VDPAU_420) + { + #ifdef HAVE_LIBVDPAU +- CVDPAU *vdpau = m_buffers[m_iYV12RenderBuffer].vdpau; +- if(vdpau) +- return vdpau->Supports(method); ++ VDPAU::CVdpauRenderPicture *vdpauPic = m_buffers[m_iYV12RenderBuffer].vdpau; ++ if(vdpauPic && vdpauPic->vdpau) ++ return vdpauPic->vdpau->Supports(method); + #endif + return false; + } +@@ -3300,6 +3674,16 @@ + return false; + } + ++ if(m_renderMethod & RENDER_XVBA) ++ { ++#ifdef HAVE_LIBXVBA ++ XVBA::CXvbaRenderPicture *xvba = m_buffers[m_iYV12RenderBuffer].xvba; ++ if(xvba) ++ return xvba->xvba->Supports(method); ++#endif ++ return false; ++ } ++ + #ifdef TARGET_DARWIN + // YADIF too slow for HD but we have no methods to fall back + // to something that works so just turn it off. +@@ -3342,7 +3726,7 @@ + || method == VS_SCALINGMETHOD_LANCZOS3) + { + if ((glewIsSupported("GL_EXT_framebuffer_object") && (m_renderMethod & RENDER_GLSL)) || +- (m_renderMethod & RENDER_VDPAU) || (m_renderMethod & RENDER_VAAPI)) ++ (m_renderMethod & RENDER_VDPAU) || (m_renderMethod & RENDER_VAAPI) || (m_renderMethod & RENDER_XVBA)) + { + // spline36 and lanczos3 are only allowed through advancedsettings.xml + if(method != VS_SCALINGMETHOD_SPLINE36 +@@ -3362,14 +3746,7 @@ + return VS_INTERLACEMETHOD_NONE; + + if(m_renderMethod & RENDER_VDPAU) +- { +-#ifdef HAVE_LIBVDPAU +- CVDPAU *vdpau = m_buffers[m_iYV12RenderBuffer].vdpau; +- if(vdpau) +- return vdpau->AutoInterlaceMethod(); +-#endif + return VS_INTERLACEMETHOD_NONE; +- } + + if(Supports(VS_INTERLACEMETHOD_RENDER_BOB)) + return VS_INTERLACEMETHOD_RENDER_BOB; +@@ -3412,26 +3789,27 @@ + } + + #ifdef HAVE_LIBVDPAU +-void CLinuxRendererGL::AddProcessor(CVDPAU* vdpau) ++void CLinuxRendererGL::AddProcessor(VDPAU::CVdpauRenderPicture *vdpau, int index) + { +- YUVBUFFER &buf = m_buffers[NextYV12Texture()]; ++ YUVBUFFER &buf = m_buffers[index]; ++ VDPAU::CVdpauRenderPicture *pic = vdpau->Acquire(); + SAFE_RELEASE(buf.vdpau); +- buf.vdpau = (CVDPAU*)vdpau->Acquire(); ++ buf.vdpau = pic; + } + #endif + + #ifdef HAVE_LIBVA +-void CLinuxRendererGL::AddProcessor(VAAPI::CHolder& holder) ++void CLinuxRendererGL::AddProcessor(VAAPI::CHolder& holder, int index) + { +- YUVBUFFER &buf = m_buffers[NextYV12Texture()]; ++ YUVBUFFER &buf = m_buffers[index]; + buf.vaapi.surface = holder.surface; + } + #endif + + #ifdef TARGET_DARWIN +-void CLinuxRendererGL::AddProcessor(struct __CVBuffer *cvBufferRef) ++void CLinuxRendererGL::AddProcessor(struct __CVBuffer *cvBufferRef, int index) + { +- YUVBUFFER &buf = m_buffers[NextYV12Texture()]; ++ YUVBUFFER &buf = m_buffers[index]; + if (buf.cvBufferRef) + CVBufferRelease(buf.cvBufferRef); + buf.cvBufferRef = cvBufferRef; +@@ -3440,4 +3818,14 @@ + } + #endif + ++#ifdef HAVE_LIBXVBA ++void CLinuxRendererGL::AddProcessor(XVBA::CXvbaRenderPicture* xvba, int index) ++{ ++ YUVBUFFER &buf = m_buffers[index]; ++ XVBA::CXvbaRenderPicture *pic = xvba->Acquire(); ++ SAFE_RELEASE(buf.xvba); ++ buf.xvba = pic; ++} ++#endif ++ + #endif +diff -Naur xbmc-12.0.4/xbmc/cores/VideoRenderers/LinuxRendererGLES.cpp xbmc-12.0.4.patch/xbmc/cores/VideoRenderers/LinuxRendererGLES.cpp +--- xbmc-12.0.4/xbmc/cores/VideoRenderers/LinuxRendererGLES.cpp 2013-03-08 13:01:31.000000000 +0100 ++++ xbmc-12.0.4.patch/xbmc/cores/VideoRenderers/LinuxRendererGLES.cpp 2013-03-10 13:00:12.277988493 +0100 +@@ -135,13 +135,6 @@ + delete m_dllSwScale; + } + +-void CLinuxRendererGLES::ManageTextures() +-{ +- m_NumYV12Buffers = 2; +- //m_iYV12RenderBuffer = 0; +- return; +-} +- + bool CLinuxRendererGLES::ValidateRenderTarget() + { + if (!m_bValidated) +@@ -395,7 +388,6 @@ + { + if (!m_bConfigured) return; + ManageDisplay(); +- ManageTextures(); + } + + void CLinuxRendererGLES::RenderUpdate(bool clear, DWORD flags, DWORD alpha) +@@ -409,7 +401,6 @@ + if (m_renderMethod & RENDER_BYPASS) + { + ManageDisplay(); +- ManageTextures(); + // if running bypass, then the player might need the src/dst rects + // for sizing video playback on a layer other than the gles layer. + if (m_RenderUpdateCallBackFn) +@@ -449,7 +440,6 @@ + return; + + ManageDisplay(); +- ManageTextures(); + + g_graphicsContext.BeginPaint(); + +@@ -1982,16 +1972,16 @@ + } + + #ifdef HAVE_LIBOPENMAX +-void CLinuxRendererGLES::AddProcessor(COpenMax* openMax, DVDVideoPicture *picture) ++void CLinuxRendererGLES::AddProcessor(COpenMax* openMax, DVDVideoPicture *picture, int index) + { +- YUVBUFFER &buf = m_buffers[NextYV12Texture()]; ++ YUVBUFFER &buf = m_buffers[index]; + buf.openMaxBuffer = picture->openMaxBuffer; + } + #endif + #ifdef HAVE_VIDEOTOOLBOXDECODER +-void CLinuxRendererGLES::AddProcessor(struct __CVBuffer *cvBufferRef) ++void CLinuxRendererGLES::AddProcessor(struct __CVBuffer *cvBufferRef, int index) + { +- YUVBUFFER &buf = m_buffers[NextYV12Texture()]; ++ YUVBUFFER &buf = m_buffers[index]; + if (buf.cvBufferRef) + CVBufferRelease(buf.cvBufferRef); + buf.cvBufferRef = cvBufferRef; +diff -Naur xbmc-12.0.4/xbmc/cores/VideoRenderers/LinuxRendererGLES.h xbmc-12.0.4.patch/xbmc/cores/VideoRenderers/LinuxRendererGLES.h +--- xbmc-12.0.4/xbmc/cores/VideoRenderers/LinuxRendererGLES.h 2013-03-08 13:01:31.000000000 +0100 ++++ xbmc-12.0.4.patch/xbmc/cores/VideoRenderers/LinuxRendererGLES.h 2013-03-10 13:00:12.284988442 +0100 +@@ -41,8 +41,6 @@ + class COpenMaxVideo; + typedef std::vector Features; + +-#define NUM_BUFFERS 3 +- + + #undef ALIGN + #define ALIGN(value, alignment) (((value)+((alignment)-1))&~((alignment)-1)) +@@ -138,6 +136,9 @@ + virtual void UnInit(); + virtual void Reset(); /* resets renderer after seek for example */ + virtual void ReorderDrawPoints(); ++ virtual void SetBufferSize(int numBuffers) { m_NumYV12Buffers = numBuffers; } ++ virtual unsigned int GetMaxBufferSize() { return NUM_BUFFERS; } ++ virtual unsigned int GetProcessorSize() { return m_NumYV12Buffers; } + + virtual void RenderUpdate(bool clear, DWORD flags = 0, DWORD alpha = 255); + +@@ -153,16 +154,15 @@ + virtual std::vector SupportedFormats() { return m_formats; } + + #ifdef HAVE_LIBOPENMAX +- virtual void AddProcessor(COpenMax* openMax, DVDVideoPicture *picture); ++ virtual void AddProcessor(COpenMax* openMax, DVDVideoPicture *picture, int index); + #endif + #ifdef HAVE_VIDEOTOOLBOXDECODER +- virtual void AddProcessor(struct __CVBuffer *cvBufferRef); ++ virtual void AddProcessor(struct __CVBuffer *cvBufferRef, int index); + #endif + + protected: + virtual void Render(DWORD flags, int index); + +- virtual void ManageTextures(); + int NextYV12Texture(); + virtual bool ValidateRenderTarget(); + virtual void LoadShaders(int field=FIELD_FULL); +diff -Naur xbmc-12.0.4/xbmc/cores/VideoRenderers/LinuxRendererGL.h xbmc-12.0.4.patch/xbmc/cores/VideoRenderers/LinuxRendererGL.h +--- xbmc-12.0.4/xbmc/cores/VideoRenderers/LinuxRendererGL.h 2013-03-08 13:01:31.000000000 +0100 ++++ xbmc-12.0.4.patch/xbmc/cores/VideoRenderers/LinuxRendererGL.h 2013-03-10 13:00:12.323988163 +0100 +@@ -38,13 +38,12 @@ + + class CRenderCapture; + +-class CVDPAU; + class CBaseTexture; + namespace Shaders { class BaseYUV2RGBShader; } + namespace Shaders { class BaseVideoFilterShader; } + namespace VAAPI { struct CHolder; } +- +-#define NUM_BUFFERS 3 ++namespace VDPAU { class CVdpauRenderPicture; } ++namespace XVBA { class CXvbaRenderPicture; } + + + #undef ALIGN +@@ -91,6 +90,7 @@ + RENDER_POT=0x10, + RENDER_VAAPI=0x20, + RENDER_CVREF = 0x40, ++ RENDER_XVBA=0x80, + }; + + enum RenderQuality +@@ -138,17 +138,23 @@ + 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 unsigned int GetMaxBufferSize() { return NUM_BUFFERS; } ++ virtual unsigned int GetProcessorSize() { return m_NumYV12Buffers; } + + #ifdef HAVE_LIBVDPAU +- virtual void AddProcessor(CVDPAU* vdpau); ++ virtual void AddProcessor(VDPAU::CVdpauRenderPicture* vdpau, int index); + #endif + #ifdef HAVE_LIBVA +- virtual void AddProcessor(VAAPI::CHolder& holder); ++ virtual void AddProcessor(VAAPI::CHolder& holder, int index); + #endif + #ifdef TARGET_DARWIN +- virtual void AddProcessor(struct __CVBuffer *cvBufferRef); ++ virtual void AddProcessor(struct __CVBuffer *cvBufferRef, int index); ++#endif ++#ifdef HAVE_LIBXVBA ++ virtual void AddProcessor(XVBA::CXvbaRenderPicture* xvba, int index); + #endif +- + virtual void RenderUpdate(bool clear, DWORD flags = 0, DWORD alpha = 255); + + // Feature support +@@ -168,7 +174,6 @@ + void DrawBlackBars(); + + bool ValidateRenderer(); +- virtual void ManageTextures(); + int NextYV12Texture(); + virtual bool ValidateRenderTarget(); + virtual void LoadShaders(int field=FIELD_FULL); +@@ -192,6 +197,10 @@ + void DeleteVDPAUTexture(int index); + bool CreateVDPAUTexture(int index); + ++ void UploadVDPAUTexture420(int index); ++ void DeleteVDPAUTexture420(int index); ++ bool CreateVDPAUTexture420(int index); ++ + void UploadVAAPITexture(int index); + void DeleteVAAPITexture(int index); + bool CreateVAAPITexture(int index); +@@ -204,6 +213,10 @@ + void DeleteYUV422PackedTexture(int index); + bool CreateYUV422PackedTexture(int index); + ++ void UploadXVBATexture(int index); ++ void DeleteXVBATexture(int index); ++ bool CreateXVBATexture(int index); ++ + void UploadRGBTexture(int index); + void ToRGBFrame(YV12Image* im, unsigned flipIndexPlane, unsigned flipIndexBuf); + void ToRGBFields(YV12Image* im, unsigned flipIndexPlaneTop, unsigned flipIndexPlaneBot, unsigned flipIndexBuf); +@@ -212,13 +225,14 @@ + void CalculateTextureSourceRects(int source, int num_planes); + + // renderers +- void RenderMultiPass(int renderBuffer, int field); // multi pass glsl renderer +- void RenderToFBO(int renderBuffer, int field); ++ void RenderToFBO(int renderBuffer, int field, bool weave = false); + void RenderFromFBO(); + void RenderSinglePass(int renderBuffer, int field); // single pass glsl renderer + void RenderSoftware(int renderBuffer, int field); // single pass s/w yuv2rgb renderer + void RenderVDPAU(int renderBuffer, int field); // render using vdpau hardware ++ void RenderProgressiveWeave(int renderBuffer, int field); // render using vdpau hardware + void RenderVAAPI(int renderBuffer, int field); // render using vdpau hardware ++ void RenderXVBA(int renderBuffer, int field); // render using xvba hardware + + struct + { +@@ -278,7 +292,7 @@ + GLuint pbo[MAX_PLANES]; + + #ifdef HAVE_LIBVDPAU +- CVDPAU* vdpau; ++ VDPAU::CVdpauRenderPicture *vdpau; + #endif + #ifdef HAVE_LIBVA + VAAPI::CHolder& vaapi; +@@ -286,6 +300,9 @@ + #ifdef TARGET_DARWIN_OSX + struct __CVBuffer *cvBufferRef; + #endif ++#ifdef HAVE_LIBXVBA ++ XVBA::CXvbaRenderPicture *xvba; ++#endif + }; + + typedef YUVBUFFER YUVBUFFERS[NUM_BUFFERS]; +@@ -324,6 +341,7 @@ + bool m_nonLinStretch; + bool m_nonLinStretchGui; + float m_pixelRatio; ++ bool m_skipRender; + }; + + +diff -Naur xbmc-12.0.4/xbmc/cores/VideoRenderers/OverlayRenderer.cpp xbmc-12.0.4.patch/xbmc/cores/VideoRenderers/OverlayRenderer.cpp +--- xbmc-12.0.4/xbmc/cores/VideoRenderers/OverlayRenderer.cpp 2013-03-08 13:01:31.000000000 +0100 ++++ xbmc-12.0.4.patch/xbmc/cores/VideoRenderers/OverlayRenderer.cpp 2013-03-10 13:00:12.289988407 +0100 +@@ -89,29 +89,32 @@ + CRenderer::CRenderer() + { + m_render = 0; +- m_decode = (m_render + 1) % 2; + } + + CRenderer::~CRenderer() + { +- for(int i = 0; i < 2; i++) ++ for(int i = 0; i < NUM_BUFFERS; i++) + Release(m_buffers[i]); + } + +-void CRenderer::AddOverlay(CDVDOverlay* o, double pts) ++void CRenderer::AddOverlay(CDVDOverlay* o, double pts, int index) + { + CSingleLock lock(m_section); + ++ m_decode = index; ++ + SElement e; + e.pts = pts; + e.overlay_dvd = o->Acquire(); + m_buffers[m_decode].push_back(e); + } + +-void CRenderer::AddOverlay(COverlay* o, double pts) ++void CRenderer::AddOverlay(COverlay* o, double pts, int index) + { + CSingleLock lock(m_section); + ++ m_decode = index; ++ + SElement e; + e.pts = pts; + e.overlay = o->Acquire(); +@@ -124,18 +127,22 @@ + m_cleanup.push_back(o->Acquire()); + } + +-void CRenderer::Release(SElementV& list) ++bool CRenderer::Release(SElementV& list) + { + SElementV l = list; + list.clear(); + ++ bool change = false; + for(SElementV::iterator it = l.begin(); it != l.end(); it++) + { + if(it->overlay) + it->overlay->Release(); + if(it->overlay_dvd) + it->overlay_dvd->Release(); ++ ++ change = true; + } ++ return change; + } + + void CRenderer::Release(COverlayV& list) +@@ -151,20 +158,26 @@ + { + CSingleLock lock(m_section); + +- for(int i = 0; i < 2; i++) ++ for(int i = 0; i < m_iNumBuffers; i++) + Release(m_buffers[i]); + ++ m_render = 0; + Release(m_cleanup); + } + +-void CRenderer::Flip() ++void CRenderer::Flip(int source) + { + CSingleLock lock(m_section); ++ if( source >= 0 && source < m_iNumBuffers ) ++ m_render = source; ++ else ++ m_render = (m_render + 1) % m_iNumBuffers; ++} + +- m_render = m_decode; +- m_decode =(m_decode + 1) % 2; +- +- Release(m_buffers[m_decode]); ++long CRenderer::ReleaseBuffer(int idx) ++{ ++ CSingleLock lock(m_section); ++ return Release(m_buffers[idx]); + } + + void CRenderer::Render() +diff -Naur xbmc-12.0.4/xbmc/cores/VideoRenderers/OverlayRenderer.h xbmc-12.0.4.patch/xbmc/cores/VideoRenderers/OverlayRenderer.h +--- xbmc-12.0.4/xbmc/cores/VideoRenderers/OverlayRenderer.h 2013-03-08 13:01:31.000000000 +0100 ++++ xbmc-12.0.4.patch/xbmc/cores/VideoRenderers/OverlayRenderer.h 2013-03-10 13:00:12.289988407 +0100 +@@ -23,6 +23,7 @@ + #pragma once + + #include "threads/CriticalSection.h" ++#include "BaseRenderer.h" + + #include + +@@ -92,12 +93,14 @@ + CRenderer(); + ~CRenderer(); + +- void AddOverlay(CDVDOverlay* o, double pts); +- void AddOverlay(COverlay* o, double pts); ++ void AddOverlay(CDVDOverlay* o, double pts, int index); ++ void AddOverlay(COverlay* o, double pts, int index); + void AddCleanup(COverlay* o); +- void Flip(); ++ void Flip(int source); + void Render(); + void Flush(); ++ void SetNumBuffers(int numBuffers) { m_iNumBuffers = numBuffers; } ++ long ReleaseBuffer(int idx); + + protected: + +@@ -121,10 +124,11 @@ + COverlay* Convert(CDVDOverlaySSA* o, double pts); + + void Release(COverlayV& list); +- void Release(SElementV& list); ++ bool Release(SElementV& list); + + CCriticalSection m_section; +- SElementV m_buffers[2]; ++ SElementV m_buffers[NUM_BUFFERS]; ++ int m_iNumBuffers; + int m_decode; + int m_render; + +diff -Naur xbmc-12.0.4/xbmc/cores/VideoRenderers/RenderFormats.h xbmc-12.0.4.patch/xbmc/cores/VideoRenderers/RenderFormats.h +--- xbmc-12.0.4/xbmc/cores/VideoRenderers/RenderFormats.h 2013-03-08 13:01:31.000000000 +0100 ++++ xbmc-12.0.4.patch/xbmc/cores/VideoRenderers/RenderFormats.h 2013-03-10 13:00:12.323988163 +0100 +@@ -26,6 +26,7 @@ + RENDER_FMT_YUV420P10, + RENDER_FMT_YUV420P16, + RENDER_FMT_VDPAU, ++ RENDER_FMT_VDPAU_420, + RENDER_FMT_NV12, + RENDER_FMT_UYVY422, + RENDER_FMT_YUYV422, +@@ -34,6 +35,7 @@ + RENDER_FMT_OMXEGL, + RENDER_FMT_CVBREF, + RENDER_FMT_BYPASS, ++ RENDER_FMT_XVBA, + }; + + #endif +diff -Naur xbmc-12.0.4/xbmc/cores/VideoRenderers/RenderManager.cpp xbmc-12.0.4.patch/xbmc/cores/VideoRenderers/RenderManager.cpp +--- xbmc-12.0.4/xbmc/cores/VideoRenderers/RenderManager.cpp 2013-03-08 13:01:31.000000000 +0100 ++++ xbmc-12.0.4.patch/xbmc/cores/VideoRenderers/RenderManager.cpp 2013-03-10 13:00:12.333988091 +0100 +@@ -28,6 +28,7 @@ + #include "utils/MathUtils.h" + #include "threads/SingleLock.h" + #include "utils/log.h" ++#include "utils/TimeUtils.h" + + #include "Application.h" + #include "ApplicationMessenger.h" +@@ -227,7 +228,7 @@ + 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) ++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, bool buffering) + { + /* make sure any queued frame was fully presented */ + double timeout = m_presenttime + 0.1; +@@ -247,6 +248,9 @@ + return false; + } + ++ // set buffering ++ m_bCodecSupportsBuffering = buffering; ++ + bool result = m_pRenderer->Configure(width, height, d_width, d_height, fps, flags, format, extended_format, orientation); + if(result) + { +@@ -261,6 +265,8 @@ + m_bReconfigured = true; + m_presentstep = PRESENT_IDLE; + m_presentevent.Set(); ++ ResetRenderBuffer(); ++ EnableBuffering(buffering); + } + + return result; +@@ -292,9 +298,13 @@ + if (!m_pRenderer) + return; + ++ if (m_presentstep == PRESENT_IDLE) ++ PrepareNextRender(); ++ + if(m_presentstep == PRESENT_FLIP) + { +- m_overlays.Flip(); ++ FlipRenderBuffer(); ++ m_overlays.Flip(m_presentsource); + m_pRenderer->FlipPage(m_presentsource); + m_presentstep = PRESENT_FRAME; + m_presentevent.Set(); +@@ -338,6 +348,10 @@ + + UpdateDisplayLatency(); + ++ m_bUseBuffering = false; ++ m_bCodecSupportsBuffering = true; ++ ResetRenderBuffer(); ++ + return m_pRenderer->PreInit(); + } + +@@ -366,7 +380,9 @@ + + CRetakeLock lock(m_sharedSection); + m_pRenderer->Flush(); ++ m_overlays.Flush(); + m_flushEvent.Set(); ++ ResetRenderBuffer(); + } + else + { +@@ -534,25 +550,21 @@ + m_pRenderer->SetViewMode(iViewMode); + } + +-void CXBMCRenderManager::FlipPage(volatile bool& bStop, double timestamp /* = 0LL*/, int source /*= -1*/, EFIELDSYNC sync /*= FS_NONE*/) ++void CXBMCRenderManager::FlipPage(volatile bool& bStop, double timestamp /* = 0LL*/, double pts /* = 0 */, int source /*= -1*/, EFIELDSYNC sync /*= FS_NONE*/) + { +- if(timestamp - GetPresentTime() > MAXPRESENTDELAY) +- timestamp = GetPresentTime() + MAXPRESENTDELAY; +- +- /* can't flip, untill timestamp */ +- if(!g_graphicsContext.IsFullScreenVideo()) +- WaitPresentTime(timestamp); +- +- /* make sure any queued frame was fully presented */ +- double timeout = m_presenttime + 1.0; +- while(m_presentstep != PRESENT_IDLE && !bStop) ++ if (!m_bUseBuffering) + { +- if(!m_presentevent.WaitMSec(100) && GetPresentTime() > timeout && !bStop) ++ /* make sure any queued frame was fully presented */ ++ double timeout = m_presenttime + 1.0; ++ while(m_presentstep != PRESENT_IDLE && !bStop) + { +- CLog::Log(LOGWARNING, "CRenderManager::FlipPage - timeout waiting for previous frame"); +- return; ++ if(!m_presentevent.WaitMSec(100) && GetPresentTime() > timeout && !bStop) ++ { ++ CLog::Log(LOGWARNING, "CRenderManager::FlipPage - timeout waiting for previous frame"); ++ return; ++ } + } +- }; ++ } + + if(bStop) + return; +@@ -560,58 +572,70 @@ + { CRetakeLock lock(m_sharedSection); + if(!m_pRenderer) return; + +- m_presenttime = timestamp; +- m_presentfield = sync; +- m_presentstep = PRESENT_FLIP; +- m_presentsource = source; ++ EFIELDSYNC presentfield = sync; ++ EPRESENTMETHOD presentmethod; ++ + EDEINTERLACEMODE deinterlacemode = g_settings.m_currentVideoSettings.m_DeinterlaceMode; + EINTERLACEMETHOD interlacemethod = AutoInterlaceMethodInternal(g_settings.m_currentVideoSettings.m_InterlaceMethod); + + bool invert = false; + + if (deinterlacemode == VS_DEINTERLACEMODE_OFF) +- m_presentmethod = PRESENT_METHOD_SINGLE; ++ presentmethod = PRESENT_METHOD_SINGLE; + else + { +- if (deinterlacemode == VS_DEINTERLACEMODE_AUTO && m_presentfield == FS_NONE) +- m_presentmethod = PRESENT_METHOD_SINGLE; ++ if (deinterlacemode == VS_DEINTERLACEMODE_AUTO && presentfield == FS_NONE) ++ presentmethod = PRESENT_METHOD_SINGLE; + else + { +- if (interlacemethod == VS_INTERLACEMETHOD_RENDER_BLEND) m_presentmethod = PRESENT_METHOD_BLEND; +- else if (interlacemethod == VS_INTERLACEMETHOD_RENDER_WEAVE) m_presentmethod = PRESENT_METHOD_WEAVE; +- else if (interlacemethod == VS_INTERLACEMETHOD_RENDER_WEAVE_INVERTED) { m_presentmethod = PRESENT_METHOD_WEAVE ; invert = true; } +- else if (interlacemethod == VS_INTERLACEMETHOD_RENDER_BOB) m_presentmethod = PRESENT_METHOD_BOB; +- else if (interlacemethod == VS_INTERLACEMETHOD_RENDER_BOB_INVERTED) { m_presentmethod = PRESENT_METHOD_BOB; invert = true; } +- else if (interlacemethod == VS_INTERLACEMETHOD_DXVA_BOB) m_presentmethod = PRESENT_METHOD_BOB; +- else if (interlacemethod == VS_INTERLACEMETHOD_DXVA_BEST) m_presentmethod = PRESENT_METHOD_BOB; +- else m_presentmethod = PRESENT_METHOD_SINGLE; ++ if (interlacemethod == VS_INTERLACEMETHOD_RENDER_BLEND) presentmethod = PRESENT_METHOD_BLEND; ++ else if (interlacemethod == VS_INTERLACEMETHOD_RENDER_WEAVE) presentmethod = PRESENT_METHOD_WEAVE; ++ else if (interlacemethod == VS_INTERLACEMETHOD_RENDER_WEAVE_INVERTED) { presentmethod = PRESENT_METHOD_WEAVE ; invert = true; } ++ else if (interlacemethod == VS_INTERLACEMETHOD_RENDER_BOB) presentmethod = PRESENT_METHOD_BOB; ++ else if (interlacemethod == VS_INTERLACEMETHOD_RENDER_BOB_INVERTED) { presentmethod = PRESENT_METHOD_BOB; invert = true; } ++ else if (interlacemethod == VS_INTERLACEMETHOD_DXVA_BOB) presentmethod = PRESENT_METHOD_BOB; ++ else if (interlacemethod == VS_INTERLACEMETHOD_DXVA_BEST) presentmethod = PRESENT_METHOD_BOB; ++ else presentmethod = PRESENT_METHOD_SINGLE; + + /* default to odd field if we want to deinterlace and don't know better */ +- if (deinterlacemode == VS_DEINTERLACEMODE_FORCE && m_presentfield == FS_NONE) +- m_presentfield = FS_TOP; ++ if (deinterlacemode == VS_DEINTERLACEMODE_FORCE && presentfield == FS_NONE) ++ presentfield = FS_TOP; + + /* invert present field */ + if(invert) + { +- if( m_presentfield == FS_BOT ) +- m_presentfield = FS_TOP; ++ if( presentfield == FS_BOT ) ++ presentfield = FS_TOP; + else +- m_presentfield = FS_BOT; ++ presentfield = FS_BOT; + } + } + } + ++ if (FlipFreeBuffer() >= 0) ++ { ++ m_renderBuffers[m_iOutputRenderBuffer].pts = pts; ++ m_renderBuffers[m_iOutputRenderBuffer].timestamp = timestamp; ++ m_renderBuffers[m_iOutputRenderBuffer].presentfield = presentfield; ++ m_renderBuffers[m_iOutputRenderBuffer].presentmethod = presentmethod; ++ if (!m_bUseBuffering) ++ PrepareNextRender(); ++ } + } + + g_application.NewFrame(); +- /* wait untill render thread have flipped buffers */ +- timeout = m_presenttime + 1.0; +- while(m_presentstep == PRESENT_FLIP && !bStop) ++ ++ if (!m_bUseBuffering) + { +- if(!m_presentevent.WaitMSec(100) && GetPresentTime() > timeout && !bStop) ++ /* wait untill render thread have flipped buffers */ ++ double timeout = m_presenttime + 1.0; ++ while(m_presentstep == PRESENT_FLIP && !bStop) + { +- CLog::Log(LOGWARNING, "CRenderManager::FlipPage - timeout waiting for flip to complete"); +- return; ++ if(!m_presentevent.WaitMSec(100) && GetPresentTime() > timeout && !bStop) ++ { ++ CLog::Log(LOGWARNING, "CRenderManager::FlipPage - timeout waiting for flip to complete"); ++ return; ++ } + } + } + } +@@ -675,9 +699,13 @@ + if (!m_pRenderer) + return; + ++ if (m_presentstep == PRESENT_IDLE) ++ PrepareNextRender(); ++ + if(m_presentstep == PRESENT_FLIP) + { +- m_overlays.Flip(); ++ FlipRenderBuffer(); ++ m_overlays.Flip(m_presentsource); + m_pRenderer->FlipPage(m_presentsource); + m_presentstep = PRESENT_FRAME; + m_presentevent.Set(); +@@ -800,14 +828,17 @@ + if (!m_pRenderer) + return -1; + +- if(m_pRenderer->AddVideoPicture(&pic)) ++ int index = (m_iOutputRenderBuffer + 1) % m_iNumRenderBuffers; ++ ++ if(m_pRenderer->AddVideoPicture(&pic, index)) ++ { ++ m_bRenderBufferUsed = true; + return 1; ++ } + + YV12Image image; +- int index = m_pRenderer->GetImage(&image); +- +- if(index < 0) +- return index; ++ if (m_pRenderer->GetImage(&image, index) < 0) ++ return -1; + + if(pic.format == RENDER_FMT_YUV420P + || pic.format == RENDER_FMT_YUV420P10 +@@ -829,26 +860,39 @@ + CDVDCodecUtils::CopyDXVA2Picture(&image, &pic); + } + #ifdef HAVE_LIBVDPAU +- else if(pic.format == RENDER_FMT_VDPAU) +- m_pRenderer->AddProcessor(pic.vdpau); ++ else if(pic.format == RENDER_FMT_VDPAU ++ || pic.format == RENDER_FMT_VDPAU_420) ++ m_pRenderer->AddProcessor(pic.vdpau, index); + #endif + #ifdef HAVE_LIBOPENMAX + else if(pic.format == RENDER_FMT_OMXEGL) +- m_pRenderer->AddProcessor(pic.openMax, &pic); ++ m_pRenderer->AddProcessor(pic.openMax, &pic, index); + #endif + #ifdef TARGET_DARWIN + else if(pic.format == RENDER_FMT_CVBREF) +- m_pRenderer->AddProcessor(pic.cvBufferRef); ++ m_pRenderer->AddProcessor(pic.cvBufferRef, index); + #endif + #ifdef HAVE_LIBVA + else if(pic.format == RENDER_FMT_VAAPI) +- m_pRenderer->AddProcessor(*pic.vaapi); ++ m_pRenderer->AddProcessor(*pic.vaapi, index); ++#endif ++#ifdef HAVE_LIBXVBA ++ else if(pic.format == RENDER_FMT_XVBA) ++ m_pRenderer->AddProcessor(pic.xvba, index); + #endif + m_pRenderer->ReleaseImage(index, false); + ++ m_bRenderBufferUsed = true; + return index; + } + ++void CXBMCRenderManager::AddOverlay(CDVDOverlay* o, double pts) ++{ ++ CSharedLock lock(m_sharedSection); ++ m_overlays.AddOverlay(o, pts, (m_iOutputRenderBuffer + 1) % m_iNumRenderBuffers); ++ m_bRenderBufferUsed = true; ++} ++ + bool CXBMCRenderManager::Supports(ERENDERFEATURE feature) + { + CSharedLock lock(m_sharedSection); +@@ -904,3 +948,227 @@ + + return mInt; + } ++ ++int CXBMCRenderManager::WaitForBuffer(volatile bool& bStop, int timeout) ++{ ++ CSharedLock lock(m_sharedSection); ++ if (!m_pRenderer) ++ return -1; ++ ++ XbmcThreads::EndTime endtime(timeout); ++ while(!HasFreeBuffer() && !bStop) ++ { ++ lock.Leave(); ++ m_flipEvent.WaitMSec(std::min(50, timeout)); ++ if(endtime.IsTimePast()) ++ { ++ if (timeout != 0 && !bStop) ++ CLog::Log(LOGWARNING, "CRenderManager::WaitForBuffer - timeout waiting for buffer"); ++ return -1; ++ } ++ lock.Enter(); ++ } ++ lock.Leave(); ++ ++ if (bStop) ++ return -1; ++ ++ // make sure overlay buffer is released, this won't happen on AddOverlay ++ m_overlays.ReleaseBuffer((m_iOutputRenderBuffer + 1) % m_iNumRenderBuffers); ++ return 1; ++} ++ ++int CXBMCRenderManager::GetNextRenderBufferIndex() ++{ ++ if (m_iOutputRenderBuffer == m_iCurrentRenderBuffer) ++ return -1; ++ return (m_iCurrentRenderBuffer + 1) % m_iNumRenderBuffers; ++} ++ ++void CXBMCRenderManager::FlipRenderBuffer() ++{ ++ m_iCurrentRenderBuffer = GetNextRenderBufferIndex(); ++} ++ ++int CXBMCRenderManager::FlipFreeBuffer() ++{ ++ // See "Render Buffer State Description" in header for information. ++ if (HasFreeBuffer()) ++ { ++ if (!m_bRenderBufferUsed && !m_bOverlayReleased) ++ { ++ return -1; ++ } ++ m_bRenderBufferUsed = false; ++ m_bOverlayReleased = false; ++ m_bAllRenderBuffersDisplayed = false; ++ m_iOutputRenderBuffer = (m_iOutputRenderBuffer + 1) % m_iNumRenderBuffers; ++ return m_iOutputRenderBuffer; ++ } ++ else ++ return -1; ++} ++ ++bool CXBMCRenderManager::HasFreeBuffer() ++{ ++ if (!m_bUseBuffering) ++ { ++ if (m_iOutputRenderBuffer != m_iCurrentRenderBuffer) ++ return false; ++ else ++ return true; ++ } ++ ++ int outputPlus1 = (m_iOutputRenderBuffer + 1) % m_iNumRenderBuffers; ++ if ((m_iOutputRenderBuffer == m_iDisplayedRenderBuffer && !m_bAllRenderBuffersDisplayed) ++ || outputPlus1 == m_iCurrentRenderBuffer) ++ return false; ++ else ++ return true; ++} ++ ++void CXBMCRenderManager::ResetRenderBuffer() ++{ ++ m_iNumRenderBuffers = m_pRenderer->GetMaxBufferSize(); ++ m_iNumRenderBuffers = std::min(5, m_iNumRenderBuffers); ++ m_iNumRenderBuffers = std::max(2, m_iNumRenderBuffers); ++ ++ if (!m_bCodecSupportsBuffering) ++ m_iNumRenderBuffers = 2; ++ ++ CLog::Log(LOGNOTICE,"CXBMCRenderManager::ResetRenderBuffer - using %d render buffers", m_iNumRenderBuffers); ++ m_overlays.SetNumBuffers(m_iNumRenderBuffers); ++ m_pRenderer->SetBufferSize(m_iNumRenderBuffers); ++ ++ m_iCurrentRenderBuffer = 0; ++ m_iOutputRenderBuffer = 0; ++ m_iDisplayedRenderBuffer = 0; ++ m_bAllRenderBuffersDisplayed = true; ++ m_sleeptime = 1.0; ++ m_speed = DVD_PLAYSPEED_NORMAL; ++ m_presentPts = DVD_NOPTS_VALUE; ++ m_bRenderBufferUsed = false; ++ m_bOverlayReleased = false; ++} ++ ++void CXBMCRenderManager::PrepareNextRender() ++{ ++ int idx = GetNextRenderBufferIndex(); ++ if (idx < 0) ++ { ++ if (m_speed >= DVD_PLAYSPEED_NORMAL && g_graphicsContext.IsFullScreenVideo()) ++ CLog::Log(LOGDEBUG,"%s no buffer, out: %d, current: %d, display: %d", ++ __FUNCTION__, m_iOutputRenderBuffer, m_iCurrentRenderBuffer, m_iDisplayedRenderBuffer); ++ return; ++ } ++ ++ double clocktime = GetPresentTime(); ++ double frametime = 1 / g_graphicsContext.GetFPS(); ++ ++ // look ahead in the queue ++ // if the next frame is already late, skip the one we are about to render ++// while (idx != m_iOutputRenderBuffer) ++// { ++// int idx_next = (idx + 1) % m_iNumRenderBuffers; ++// if (m_renderBuffers[idx_next].timestamp <= clocktime) ++// { ++// FlipRenderBuffer(); ++// idx = GetNextRenderBufferIndex(); ++// CLog::Log(LOGDEBUG,"%s - skip frame at render buffer index: %d", __FUNCTION__, idx); ++// } ++// else ++// break; ++// } ++ ++ double presenttime = m_renderBuffers[idx].timestamp; ++ ++ if(presenttime - clocktime > MAXPRESENTDELAY) ++ presenttime = clocktime + MAXPRESENTDELAY; ++ ++ m_sleeptime = presenttime - clocktime; ++ ++ if (g_graphicsContext.IsFullScreenVideo() || presenttime <= clocktime + frametime) ++ { ++ m_presentPts = m_renderBuffers[idx].pts; ++ m_presenttime = presenttime; ++ m_presentmethod = m_renderBuffers[idx].presentmethod; ++ m_presentfield = m_renderBuffers[idx].presentfield; ++ m_presentstep = PRESENT_FLIP; ++ m_presentsource = idx; ++ } ++} ++ ++void CXBMCRenderManager::EnableBuffering(bool enable) ++{ ++ CRetakeLock lock(m_sharedSection); ++ ++ if (m_iNumRenderBuffers < 3) ++ { ++ m_bUseBuffering = false; ++ return; ++ } ++ ++ m_bUseBuffering = enable; ++ if (!m_bUseBuffering) ++ m_iOutputRenderBuffer = m_iCurrentRenderBuffer; ++ ++ CLog::Log(LOGDEBUG, "CXBMCRenderManager::EnableBuffering - %d", m_bUseBuffering); ++} ++ ++void CXBMCRenderManager::DiscardBuffer() ++{ ++ CRetakeLock lock(m_sharedSection); ++ m_iOutputRenderBuffer = m_iCurrentRenderBuffer; ++} ++ ++void CXBMCRenderManager::SetSpeed(int speed) ++{ ++ m_speed = speed; ++} ++ ++void CXBMCRenderManager::NotifyDisplayFlip() ++{ ++ CRetakeLock lock(m_sharedSection); ++ if (!m_pRenderer) ++ return; ++ ++ if (m_iNumRenderBuffers >= 3) ++ { ++ int last = m_iDisplayedRenderBuffer; ++ m_iDisplayedRenderBuffer = (m_iCurrentRenderBuffer + m_iNumRenderBuffers - 1) % m_iNumRenderBuffers; ++ ++ if (last != m_iDisplayedRenderBuffer ++ && m_iDisplayedRenderBuffer != m_iCurrentRenderBuffer) ++ { ++ m_pRenderer->ReleaseBuffer(m_iDisplayedRenderBuffer); ++ if (m_overlays.ReleaseBuffer(m_iDisplayedRenderBuffer)) ++ m_bOverlayReleased = true; ++ } ++ } ++ ++ lock.Leave(); ++ m_flipEvent.Set(); ++} ++ ++bool CXBMCRenderManager::GetStats(double &sleeptime, double &pts, int &bufferLevel) ++{ ++ CSharedLock lock(m_sharedSection); ++ sleeptime = m_sleeptime; ++ pts = m_presentPts; ++ if (m_iNumRenderBuffers < 3) ++ bufferLevel = -1; ++ else ++ bufferLevel = (m_iOutputRenderBuffer - m_iCurrentRenderBuffer + m_iNumRenderBuffers) % m_iNumRenderBuffers; ++ return true; ++} ++ ++bool CXBMCRenderManager::HasFrame() ++{ ++ CSharedLock lock(m_sharedSection); ++ if (m_presentstep == PRESENT_IDLE && ++ GetNextRenderBufferIndex() < 0 && ++ m_speed > 0) ++ return false; ++ else ++ return true; ++} +diff -Naur xbmc-12.0.4/xbmc/cores/VideoRenderers/RenderManager.h xbmc-12.0.4.patch/xbmc/cores/VideoRenderers/RenderManager.h +--- xbmc-12.0.4/xbmc/cores/VideoRenderers/RenderManager.h 2013-03-08 13:01:31.000000000 +0100 ++++ xbmc-12.0.4.patch/xbmc/cores/VideoRenderers/RenderManager.h 2013-03-10 13:00:12.295988364 +0100 +@@ -31,10 +31,11 @@ + #include "OverlayRenderer.h" + + class CRenderCapture; ++class CDVDClock; + + namespace DXVA { class CProcessor; } + namespace VAAPI { class CSurfaceHolder; } +-class CVDPAU; ++namespace VDPAU { class CVdpauRenderPicture; } + struct DVDVideoPicture; + + #define ERRORBUFFSIZE 30 +@@ -65,21 +66,44 @@ + void SetViewMode(int iViewMode); + + // Functions called from mplayer +- 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); ++ /** ++ * 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 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 buffering enable buffering in renderer, defaults to false ++ */ ++ 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, bool buffering = false); + bool IsConfigured(); + + int AddVideoPicture(DVDVideoPicture& picture); + +- void FlipPage(volatile bool& bStop, double timestamp = 0.0, int source = -1, EFIELDSYNC sync = FS_NONE); ++ /** ++ * Called by video player to flip render buffers ++ * If buffering is enabled this method does not block. In case of disabled buffering ++ * this method blocks waiting for the render thread to pass by. ++ * When buffering is used there might be no free buffer available after the call to ++ * this method. Player has to call WaitForBuffer. A free buffer will become ++ * available after the main thread has flipped front / back buffers. ++ * ++ * @param bStop reference to stop flag of calling thread ++ * @param timestamp of frame delivered with AddVideoPicture ++ * @param pts used for lateness detection ++ * @param source depreciated ++ * @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) +- { +- CSharedLock lock(m_sharedSection); +- m_overlays.AddOverlay(o, pts); +- } ++ void AddOverlay(CDVDOverlay* o, double pts); + + void AddCleanup(OVERLAY::COverlay* o) + { +@@ -132,6 +156,49 @@ + + void RegisterRenderUpdateCallBack(const void *ctx, RenderUpdateCallBackFn 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 ++ * in case no buffer is available. Player may call this in a loop and decides ++ * by itself when it wants to drop a frame. ++ * If no buffering is requested in Configure, player does not need to call this, ++ * because FlipPage will block. ++ */ ++ int WaitForBuffer(volatile bool& bStop, int timeout = 100); ++ ++ /** ++ * Called by application right after flip. The buffer which has been rendered to ++ * display becomes available for player to deliver a new frame. ++ */ ++ void NotifyDisplayFlip(); ++ ++ /** ++ * Called by application (main thread) to query if there is any frame to render ++ */ ++ bool HasFrame(); ++ ++ /** ++ * Can be called by player for lateness detection. This is done best by ++ * looking at the end of the queue. ++ */ ++ bool GetStats(double &sleeptime, double &pts, int &bufferLevel); ++ ++ /** ++ * Video player can dynamically enable/disable buffering. In situations like ++ * rewind buffering is not ideal. ++ */ ++ void EnableBuffering(bool enable); ++ ++ /** ++ * Video player call this on flush in oder to discard any queued frames ++ */ ++ void DiscardBuffer(); ++ ++ /** ++ * notify RenderManager about play speed ++ */ ++ void SetSpeed(int speed); ++ + protected: + void Render(bool clear, DWORD flags, DWORD alpha); + +@@ -139,6 +206,13 @@ + void PresentFields(bool clear, DWORD flags, DWORD alpha); + void PresentBlend(bool clear, DWORD flags, DWORD alpha); + ++ int GetNextRenderBufferIndex(); ++ void FlipRenderBuffer(); ++ int FlipFreeBuffer(); ++ bool HasFreeBuffer(); ++ void ResetRenderBuffer(); ++ void PrepareNextRender(); ++ + EINTERLACEMETHOD AutoInterlaceMethodInternal(EINTERLACEMETHOD mInt); + + bool m_bPauseDrawing; // true if we should pause rendering +@@ -169,6 +243,40 @@ + double m_displayLatency; + void UpdateDisplayLatency(); + ++ // Render Buffer State Description: ++ // ++ // Output: is the buffer about to or having its texture prepared for render (ie from output thread). ++ // Cannot go past the "Displayed" buffer (otherwise we will probably overwrite buffers not yet ++ // displayed or even rendered). ++ // Current: is the current buffer being or having been submitted for render to back buffer. ++ // Cannot go past "Output" buffer (else it would be rendering old output). ++ // Displayed: is the buffer that is now considered to be safely copied from back buffer to front buffer ++ // (we assume that after two swap-buffer flips for the same "Current" render buffer that that ++ // buffer will be safe, but otherwise we consider that only the previous-to-"Current" is guaranteed). ++ ++ int m_iCurrentRenderBuffer; ++ int m_iNumRenderBuffers; ++ int m_iOutputRenderBuffer; ++ int m_iDisplayedRenderBuffer; ++ bool m_bAllRenderBuffersDisplayed; ++ bool m_bUseBuffering; ++ bool m_bCodecSupportsBuffering; ++ int m_speed; ++ bool m_bRenderBufferUsed; ++ bool m_bOverlayReleased; ++ CEvent m_flipEvent; ++ ++ struct ++ { ++ double pts; ++ double timestamp; ++ EFIELDSYNC presentfield; ++ EPRESENTMETHOD presentmethod; ++ }m_renderBuffers[5]; ++ ++ double m_sleeptime; ++ double m_presentPts; ++ + double m_presenttime; + double m_presentcorr; + double m_presenterr; +diff -Naur xbmc-12.0.4/xbmc/cores/VideoRenderers/VideoShaders/YUV2RGBShader.cpp xbmc-12.0.4.patch/xbmc/cores/VideoRenderers/VideoShaders/YUV2RGBShader.cpp +--- xbmc-12.0.4/xbmc/cores/VideoRenderers/VideoShaders/YUV2RGBShader.cpp 2013-03-08 13:01:31.000000000 +0100 ++++ xbmc-12.0.4.patch/xbmc/cores/VideoRenderers/VideoShaders/YUV2RGBShader.cpp 2013-03-10 13:00:12.295988364 +0100 +@@ -201,6 +201,8 @@ + m_defines += "#define XBMC_YUY2\n"; + else if (m_format == RENDER_FMT_UYVY422) + m_defines += "#define XBMC_UYVY\n"; ++ else if (RENDER_FMT_VDPAU_420) ++ m_defines += "#define XBMC_VDPAU_NV12\n"; + else + CLog::Log(LOGERROR, "GL: BaseYUV2RGBGLSLShader - unsupported format %d", m_format); + +diff -Naur xbmc-12.0.4/xbmc/cores/VideoRenderers/WinRenderer.cpp xbmc-12.0.4.patch/xbmc/cores/VideoRenderers/WinRenderer.cpp +--- xbmc-12.0.4/xbmc/cores/VideoRenderers/WinRenderer.cpp 2013-03-08 13:01:31.000000000 +0100 ++++ xbmc-12.0.4.patch/xbmc/cores/VideoRenderers/WinRenderer.cpp 2013-03-10 13:00:12.278988486 +0100 +@@ -103,21 +103,19 @@ + + void CWinRenderer::ManageTextures() + { +- int neededbuffers = 2; +- +- if( m_NumYV12Buffers < neededbuffers ) ++ if( m_NumYV12Buffers < m_neededBuffers ) + { +- for(int i = m_NumYV12Buffers; i neededbuffers ) ++ else if( m_NumYV12Buffers > m_neededBuffers ) + { +- m_NumYV12Buffers = neededbuffers; ++ m_NumYV12Buffers = m_neededBuffers; + m_iYV12RenderBuffer = m_iYV12RenderBuffer % m_NumYV12Buffers; + +- for(int i = m_NumYV12Buffers-1; i>=neededbuffers;i--) ++ for(int i = m_NumYV12Buffers-1; i>=m_neededBuffers;i--) + DeleteYV12Texture(i); + } + } +@@ -253,12 +251,12 @@ + return -1; + } + +-bool CWinRenderer::AddVideoPicture(DVDVideoPicture* picture) ++bool CWinRenderer::AddVideoPicture(DVDVideoPicture* picture, int index) + { + if (m_renderMethod == RENDER_DXVA) + { +- int source = NextYV12Texture(); +- if(source < 0) ++ int source = index; ++ if(source < 0 || NextYV12Texture() < 0) + return false; + + DXVABuffer *buf = (DXVABuffer*)m_VideoBuffers[source]; +@@ -274,7 +272,7 @@ + if( source == AUTOSOURCE ) + source = NextYV12Texture(); + +- if( source < 0 ) ++ if( source < 0 || NextYV12Texture() < 0) + return -1; + + YUVBuffer *buf = (YUVBuffer*)m_VideoBuffers[source]; +diff -Naur xbmc-12.0.4/xbmc/cores/VideoRenderers/WinRenderer.h xbmc-12.0.4.patch/xbmc/cores/VideoRenderers/WinRenderer.h +--- xbmc-12.0.4/xbmc/cores/VideoRenderers/WinRenderer.h 2013-03-08 13:01:31.000000000 +0100 ++++ xbmc-12.0.4.patch/xbmc/cores/VideoRenderers/WinRenderer.h 2013-03-10 13:00:12.285988435 +0100 +@@ -32,14 +32,6 @@ + #include "cores/VideoRenderers/RenderFlags.h" + #include "cores/VideoRenderers/RenderFormats.h" + +-//#define MP_DIRECTRENDERING +- +-#ifdef MP_DIRECTRENDERING +-#define NUM_BUFFERS 3 +-#else +-#define NUM_BUFFERS 2 +-#endif +- + #define ALIGN(value, alignment) (((value)+((alignment)-1))&~((alignment)-1)) + #define CLAMP(a, min, max) ((a) > (max) ? (max) : ( (a) < (min) ? (min) : a )) + +@@ -157,7 +149,7 @@ + virtual 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); + virtual int GetImage(YV12Image *image, int source = AUTOSOURCE, bool readonly = false); + virtual void ReleaseImage(int source, bool preserve = false); +- virtual bool AddVideoPicture(DVDVideoPicture* picture); ++ virtual bool AddVideoPicture(DVDVideoPicture* picture, int index); + virtual void FlipPage(int source); + virtual unsigned int PreInit(); + virtual void UnInit(); +@@ -176,6 +168,8 @@ + void RenderUpdate(bool clear, DWORD flags = 0, DWORD alpha = 255); + + virtual unsigned int GetProcessorSize() { return m_processor.Size(); } ++ virtual void SetBufferSize(int numBuffers) { m_neededBuffers = numBuffers; } ++ virtual unsigned int GetMaxBufferSize() { return NUM_BUFFERS; } + + protected: + virtual void Render(DWORD flags); +@@ -245,6 +239,8 @@ + // the separable HQ scalers need this info, but could the m_destRect be used instead? + unsigned int m_destWidth; + unsigned int m_destHeight; ++ ++ int m_neededBuffers; + }; + + #else +diff -Naur xbmc-12.0.4/xbmc/input/XBMC_keytable.cpp xbmc-12.0.4.patch/xbmc/input/XBMC_keytable.cpp +--- xbmc-12.0.4/xbmc/input/XBMC_keytable.cpp 2013-03-08 13:01:28.000000000 +0100 ++++ xbmc-12.0.4.patch/xbmc/input/XBMC_keytable.cpp 2013-03-10 13:00:12.316988213 +0100 +@@ -179,6 +179,8 @@ + , { XBMCK_LAUNCH_APP2, 0, 0, XBMCVK_LAUNCH_APP2, "launch_app2_pc_icon" } + , { XBMCK_LAUNCH_FILE_BROWSER, 0, 0, XBMCVK_LAUNCH_FILE_BROWSER, "launch_file_browser" } + , { XBMCK_LAUNCH_MEDIA_CENTER, 0, 0, XBMCVK_LAUNCH_MEDIA_CENTER, "launch_media_center" } ++, { XBMCK_PLAY, 0, 0, XBMCVK_MEDIA_PLAY_PAUSE, "play_pause" } ++, { XBMCK_STOP, 0, 0, XBMCVK_MEDIA_STOP, "stop" } + + // Function keys + , { XBMCK_F1, 0, 0, XBMCVK_F1, "f1"} +diff -Naur xbmc-12.0.4/xbmc/powermanagement/PowerManager.cpp xbmc-12.0.4.patch/xbmc/powermanagement/PowerManager.cpp +--- xbmc-12.0.4/xbmc/powermanagement/PowerManager.cpp 2013-03-08 13:01:28.000000000 +0100 ++++ xbmc-12.0.4.patch/xbmc/powermanagement/PowerManager.cpp 2013-03-10 13:00:12.330988113 +0100 +@@ -223,11 +223,6 @@ #if defined(_WIN32) ShowWindow(g_hWnd,SW_RESTORE); SetForegroundWindow(g_hWnd); @@ -20547,181 +12500,10 @@ index a5534c9..7e2ddc6 100644 #endif } g_application.ResetScreenSaver(); --- -1.7.10 - - -From b1420829ab0a6ab832f2bf36ed49a46e6e5e8d9f Mon Sep 17 00:00:00 2001 -From: xbmc -Date: Wed, 23 Jan 2013 17:03:02 +0100 -Subject: [PATCH 80/88] xrandr: set screen on mode change command - ---- - xbmc/windowing/X11/XRandR.cpp | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/xbmc/windowing/X11/XRandR.cpp b/xbmc/windowing/X11/XRandR.cpp -index 7a16488..6531ba3 100644 ---- a/xbmc/windowing/X11/XRandR.cpp -+++ b/xbmc/windowing/X11/XRandR.cpp -@@ -246,7 +246,7 @@ bool CXRandR::SetMode(XOutput output, XMode mode) - m_currentMode = modeFound.id; - char cmd[255]; - if (getenv("XBMC_BIN_HOME")) -- snprintf(cmd, sizeof(cmd), "%s/xbmc-xrandr --output %s --mode %s", getenv("XBMC_BIN_HOME"), outputFound.name.c_str(), modeFound.id.c_str()); -+ snprintf(cmd, sizeof(cmd), "%s/xbmc-xrandr --screen %d --output %s --mode %s", getenv("XBMC_BIN_HOME"), outputFound.screen, outputFound.name.c_str(), modeFound.id.c_str()); - else - return false; - CLog::Log(LOGINFO, "XRANDR: %s", cmd); --- -1.7.10 - - -From 2855a651752902838fd69fd298261cd9770132c0 Mon Sep 17 00:00:00 2001 -From: xbmc -Date: Wed, 23 Jan 2013 17:03:39 +0100 -Subject: [PATCH 81/88] X11: recreate glx context when output changes - ---- - xbmc/windowing/X11/WinSystemX11.cpp | 6 +++--- - xbmc/windowing/X11/WinSystemX11.h | 2 +- - 2 files changed, 4 insertions(+), 4 deletions(-) - -diff --git a/xbmc/windowing/X11/WinSystemX11.cpp b/xbmc/windowing/X11/WinSystemX11.cpp -index e4e25b2..b87e264 100644 ---- a/xbmc/windowing/X11/WinSystemX11.cpp -+++ b/xbmc/windowing/X11/WinSystemX11.cpp -@@ -409,11 +409,11 @@ bool CWinSystemX11::IsSuitableVisual(XVisualInfo *vInfo) - return true; - } - --bool CWinSystemX11::RefreshGlxContext() -+bool CWinSystemX11::RefreshGlxContext(bool force) - { - bool retVal = false; - -- if (m_glContext) -+ if (m_glContext && !force) - { - CLog::Log(LOGDEBUG, "CWinSystemX11::RefreshGlxContext: refreshing context"); - glXMakeCurrent(m_dpy, None, NULL); -@@ -930,7 +930,7 @@ bool CWinSystemX11::SetWindow(int width, int height, bool fullscreen, const CStd - } - - CDirtyRegionList dr; -- RefreshGlxContext(); -+ RefreshGlxContext(!m_currentOutput.Equals(output)); - XSync(m_dpy, FALSE); - g_graphicsContext.Clear(0); - g_graphicsContext.Flip(dr); -diff --git a/xbmc/windowing/X11/WinSystemX11.h b/xbmc/windowing/X11/WinSystemX11.h -index 0b7c10a..33b1739 100644 ---- a/xbmc/windowing/X11/WinSystemX11.h -+++ b/xbmc/windowing/X11/WinSystemX11.h -@@ -74,7 +74,7 @@ class CWinSystemX11 : public CWinSystemBase - void NotifyMouseCoverage(bool covered); - - protected: -- bool RefreshGlxContext(); -+ bool RefreshGlxContext(bool force); - void CheckDisplayEvents(); - void OnLostDevice(); - bool SetWindow(int width, int height, bool fullscreen, const CStdString &output); --- -1.7.10 - - -From 171c0cde342915677b0b9467675eba4b89961ee8 Mon Sep 17 00:00:00 2001 -From: unknown -Date: Fri, 18 Jan 2013 15:16:38 +0100 -Subject: [PATCH 82/88] multi-screen: fix compilation on windows - ---- - xbmc/settings/GUIWindowSettingsCategory.cpp | 11 ++++++++++- - 1 file changed, 10 insertions(+), 1 deletion(-) - -diff --git a/xbmc/settings/GUIWindowSettingsCategory.cpp b/xbmc/settings/GUIWindowSettingsCategory.cpp -index cacb32a..cbf0acb 100644 ---- a/xbmc/settings/GUIWindowSettingsCategory.cpp -+++ b/xbmc/settings/GUIWindowSettingsCategory.cpp -@@ -528,12 +528,14 @@ void CGUIWindowSettingsCategory::CreateSettings() - FillInRefreshRates(strSetting, g_guiSettings.GetResolution(), false); - continue; - } -+#if defined(HAS_GLX) - else if (strSetting.Equals("videoscreen.monitor")) - { - AddSetting(pSetting, group->GetWidth(), iControlID); - FillInMonitors(strSetting); - continue; - } -+#endif - else if (strSetting.Equals("lookandfeel.skintheme")) - { - AddSetting(pSetting, group->GetWidth(), iControlID); -@@ -1483,6 +1485,7 @@ void CGUIWindowSettingsCategory::OnSettingChanged(BaseSettingControlPtr pSetting - // Cascade - FillInResolutions("videoscreen.resolution", mode, RES_DESKTOP, true); - } -+#if defined(HAS_GLX) - else if (strSetting.Equals("videoscreen.monitor")) - { - CSettingString *pSettingString = (CSettingString *)pSettingControl->GetSetting(); -@@ -1497,6 +1500,7 @@ void CGUIWindowSettingsCategory::OnSettingChanged(BaseSettingControlPtr pSetting - FillInResolutions("videoscreen.resolution", mode, RES_DESKTOP, true); - } - } -+#endif - else if (strSetting.Equals("videoscreen.resolution")) - { - RESOLUTION nextRes = (RESOLUTION) g_guiSettings.GetInt("videoscreen.resolution"); -@@ -2451,6 +2455,7 @@ DisplayMode CGUIWindowSettingsCategory::FillInScreens(CStdString strSetting, RES - - void CGUIWindowSettingsCategory::FillInMonitors(CStdString strSetting) - { -+#if defined(HAS_GLX) - // we expect "videoscreen.monitor" but it might be hidden on some platforms, - // so check that we actually have a visable control. - BaseSettingControlPtr control = GetSetting(strSetting); -@@ -2476,6 +2481,7 @@ void CGUIWindowSettingsCategory::FillInMonitors(CStdString strSetting) - pControl->SetValue(currentMonitor); - g_guiSettings.SetString("videoscreen.monitor", g_settings.m_ResInfo[RES_DESKTOP].strOutput); - } -+#endif - } - - -@@ -2607,7 +2613,10 @@ void CGUIWindowSettingsCategory::OnRefreshRateChanged(RESOLUTION nextRes) - RESOLUTION lastRes = g_graphicsContext.GetVideoResolution(); - bool cancelled = false; - -- bool outputChanged = !g_Windowing.IsCurrentOutput(g_guiSettings.GetString("videoscreen.monitor")); -+ bool outputChanged = true; -+#if defined(HAS_GLX) -+ outputChanged = !g_Windowing.IsCurrentOutput(g_guiSettings.GetString("videoscreen.monitor")); -+#endif - - g_guiSettings.SetResolution(nextRes); - g_graphicsContext.SetVideoResolution(nextRes, outputChanged); --- -1.7.10 - - -From b4c3030639f4f89678d96597596c98ed49abb8c0 Mon Sep 17 00:00:00 2001 -From: xbmc -Date: Fri, 14 Dec 2012 14:19:15 +0100 -Subject: [PATCH 83/88] pvr: do not show selection dialog for a single menu - hook - ---- - xbmc/pvr/addons/PVRClients.cpp | 19 +++++++++++-------- - 1 file changed, 11 insertions(+), 8 deletions(-) - -diff --git a/xbmc/pvr/addons/PVRClients.cpp b/xbmc/pvr/addons/PVRClients.cpp -index ae11936..69d8b0d 100644 ---- a/xbmc/pvr/addons/PVRClients.cpp -+++ b/xbmc/pvr/addons/PVRClients.cpp -@@ -717,16 +717,19 @@ void CPVRClients::ProcessMenuHooks(int iClientID, PVR_MENUHOOK_CAT cat) +diff -Naur xbmc-12.0.4/xbmc/pvr/addons/PVRClients.cpp xbmc-12.0.4.patch/xbmc/pvr/addons/PVRClients.cpp +--- xbmc-12.0.4/xbmc/pvr/addons/PVRClients.cpp 2013-03-08 13:01:28.000000000 +0100 ++++ xbmc-12.0.4.patch/xbmc/pvr/addons/PVRClients.cpp 2013-03-10 13:00:12.331988105 +0100 +@@ -717,16 +717,19 @@ if (GetConnectedClient(iClientID, client) && client->HaveMenuHooks(cat)) { hooks = client->GetMenuHooks(); @@ -20749,37 +12531,2074 @@ index ae11936..69d8b0d 100644 if (selection >= 0) client->CallMenuHook(hooks->at(selection)); } --- -1.7.10 - - -From fe99ee421cb83fea7342729fe89153c9ba4c1842 Mon Sep 17 00:00:00 2001 -From: xbmc -Date: Sun, 3 Feb 2013 08:17:16 +0100 -Subject: [PATCH 84/88] X11: use default screen parameters if no output - connected - ---- - xbmc/windowing/X11/WinSystemX11.cpp | 55 +++++++++++++++++++++-------------- - 1 file changed, 33 insertions(+), 22 deletions(-) - -diff --git a/xbmc/windowing/X11/WinSystemX11.cpp b/xbmc/windowing/X11/WinSystemX11.cpp -index b87e264..3cadd13 100644 ---- a/xbmc/windowing/X11/WinSystemX11.cpp -+++ b/xbmc/windowing/X11/WinSystemX11.cpp -@@ -203,25 +203,27 @@ bool CWinSystemX11::SetFullScreen(bool fullScreen, RESOLUTION_INFO& res, bool bl +diff -Naur xbmc-12.0.4/xbmc/rendering/gl/RenderSystemGL.h xbmc-12.0.4.patch/xbmc/rendering/gl/RenderSystemGL.h +--- xbmc-12.0.4/xbmc/rendering/gl/RenderSystemGL.h 2013-03-08 13:01:27.000000000 +0100 ++++ xbmc-12.0.4.patch/xbmc/rendering/gl/RenderSystemGL.h 2013-03-10 13:00:12.312988242 +0100 +@@ -44,6 +44,7 @@ + virtual bool IsExtSupported(const char* extension); + + virtual void SetVSync(bool vsync); ++ virtual void ResetVSync() { m_bVsyncInit = false; } + + virtual void SetViewPort(CRect& viewPort); + virtual void GetViewPort(CRect& viewPort); +diff -Naur xbmc-12.0.4/xbmc/settings/AdvancedSettings.cpp xbmc-12.0.4.patch/xbmc/settings/AdvancedSettings.cpp +--- xbmc-12.0.4/xbmc/settings/AdvancedSettings.cpp 2013-03-08 13:01:31.000000000 +0100 ++++ xbmc-12.0.4.patch/xbmc/settings/AdvancedSettings.cpp 2013-03-10 13:00:12.327988134 +0100 +@@ -98,14 +98,18 @@ + m_videoIgnoreSecondsAtStart = 3*60; + m_videoIgnorePercentAtEnd = 8.0f; + m_videoPlayCountMinimumPercent = 90.0f; +- m_videoVDPAUScaling = false; ++ m_videoVDPAUScaling = -1; + m_videoNonLinStretchRatio = 0.5f; + m_videoEnableHighQualityHwScalers = false; + m_videoAutoScaleMaxFps = 30.0f; +- m_videoAllowMpeg4VDPAU = false; ++ m_videoAllowMpeg4VDPAU = true; + m_videoAllowMpeg4VAAPI = false; + m_videoDisableBackgroundDeinterlace = false; + m_videoCaptureUseOcclusionQuery = -1; //-1 is auto detect ++ m_videoVDPAUdeintHD = -1; ++ m_videoVDPAUdeintSD = -1; ++ m_videoVDPAUtelecine = false; ++ m_videoVDPAUdeintSkipChromaHD = false; + m_DXVACheckCompatibility = false; + m_DXVACheckCompatibilityPresent = false; + m_DXVAForceProcessorRenderer = true; +@@ -493,7 +497,7 @@ + XMLUtils::GetString(pElement,"cleandatetime", m_videoCleanDateTimeRegExp); + XMLUtils::GetString(pElement,"ppffmpegdeinterlacing",m_videoPPFFmpegDeint); + XMLUtils::GetString(pElement,"ppffmpegpostprocessing",m_videoPPFFmpegPostProc); +- XMLUtils::GetBoolean(pElement,"vdpauscaling",m_videoVDPAUScaling); ++ XMLUtils::GetInt(pElement,"vdpauscaling",m_videoVDPAUScaling); + XMLUtils::GetFloat(pElement, "nonlinearstretchratio", m_videoNonLinStretchRatio, 0.01f, 1.0f); + XMLUtils::GetBoolean(pElement,"enablehighqualityhwscalers", m_videoEnableHighQualityHwScalers); + XMLUtils::GetFloat(pElement,"autoscalemaxfps",m_videoAutoScaleMaxFps, 0.0f, 1000.0f); +@@ -501,6 +505,10 @@ + XMLUtils::GetBoolean(pElement,"allowmpeg4vaapi",m_videoAllowMpeg4VAAPI); + XMLUtils::GetBoolean(pElement, "disablebackgrounddeinterlace", m_videoDisableBackgroundDeinterlace); + XMLUtils::GetInt(pElement, "useocclusionquery", m_videoCaptureUseOcclusionQuery, -1, 1); ++ XMLUtils::GetInt(pElement,"vdpauHDdeint",m_videoVDPAUdeintHD); ++ XMLUtils::GetInt(pElement,"vdpauSDdeint",m_videoVDPAUdeintSD); ++ XMLUtils::GetBoolean(pElement,"vdpauInvTelecine",m_videoVDPAUtelecine); ++ XMLUtils::GetBoolean(pElement,"vdpauHDdeintSkipChroma",m_videoVDPAUdeintSkipChromaHD); + + TiXmlElement* pAdjustRefreshrate = pElement->FirstChildElement("adjustrefreshrate"); + if (pAdjustRefreshrate) +diff -Naur xbmc-12.0.4/xbmc/settings/AdvancedSettings.h xbmc-12.0.4.patch/xbmc/settings/AdvancedSettings.h +--- xbmc-12.0.4/xbmc/settings/AdvancedSettings.h 2013-03-08 13:01:31.000000000 +0100 ++++ xbmc-12.0.4.patch/xbmc/settings/AdvancedSettings.h 2013-03-10 13:00:12.327988134 +0100 +@@ -133,6 +133,10 @@ + int m_videoPercentSeekBackwardBig; + CStdString m_videoPPFFmpegDeint; + CStdString m_videoPPFFmpegPostProc; ++ int m_videoVDPAUdeintHD; ++ int m_videoVDPAUdeintSD; ++ bool m_videoVDPAUtelecine; ++ bool m_videoVDPAUdeintSkipChromaHD; + bool m_musicUseTimeSeeking; + int m_musicTimeSeekForward; + int m_musicTimeSeekBackward; +@@ -148,7 +152,7 @@ + CStdString m_audioHost; + bool m_audioApplyDrc; + +- bool m_videoVDPAUScaling; ++ int m_videoVDPAUScaling; + float m_videoNonLinStretchRatio; + bool m_videoEnableHighQualityHwScalers; + float m_videoAutoScaleMaxFps; +diff -Naur xbmc-12.0.4/xbmc/settings/GUISettings.cpp xbmc-12.0.4.patch/xbmc/settings/GUISettings.cpp +--- xbmc-12.0.4/xbmc/settings/GUISettings.cpp 2013-03-08 13:01:31.000000000 +0100 ++++ xbmc-12.0.4.patch/xbmc/settings/GUISettings.cpp 2013-03-10 13:00:12.325988148 +0100 +@@ -392,11 +392,16 @@ + AddGroup(SETTINGS_SYSTEM, 13000); + CSettingsCategory* vs = AddCategory(SETTINGS_SYSTEM, "videoscreen", 21373); + ++#if defined(HAS_GLX) ++ AddString(vs, "videoscreen.monitor", 246, "", SPIN_CONTROL_TEXT); ++#endif ++ + // this setting would ideally not be saved, as its value is systematically derived from videoscreen.screenmode. + // contains a DISPLAYMODE + #if !defined(TARGET_DARWIN_IOS_ATV2) && !defined(TARGET_RASPBERRY_PI) + AddInt(vs, "videoscreen.screen", 240, 0, -1, 1, 32, SPIN_CONTROL_TEXT); + #endif ++ + // this setting would ideally not be saved, as its value is systematically derived from videoscreen.screenmode. + // contains an index to the g_settings.m_ResInfo array. the only meaningful fields are iScreen, iWidth, iHeight. + #if defined(TARGET_DARWIN) +@@ -685,10 +690,14 @@ + + #ifdef HAVE_LIBVDPAU + AddBool(vp, "videoplayer.usevdpau", 13425, true); ++ AddBool(vp, "videoplayer.usevdpaumixer", 13436, true); + #endif + #ifdef HAVE_LIBVA + AddBool(vp, "videoplayer.usevaapi", 13426, true); + #endif ++#ifdef HAVE_LIBXVBA ++ AddBool(vp, "videoplayer.usexvba", 13437, true); ++#endif + #ifdef HAS_DX + AddBool(g_sysinfo.IsVistaOrHigher() ? vp: NULL, "videoplayer.usedxva2", 13427, g_sysinfo.IsVistaOrHigher() ? true : false); + #endif +@@ -763,7 +772,6 @@ + AddSeparator(vp, "videoplayer.sep1.5"); + #ifdef HAVE_LIBVDPAU + AddBool(NULL, "videoplayer.vdpauUpscalingLevel", 13121, false); +- AddBool(vp, "videoplayer.vdpaustudiolevel", 13122, false); + #endif + #endif + AddSeparator(vp, "videoplayer.sep5"); +diff -Naur xbmc-12.0.4/xbmc/settings/GUIWindowSettingsCategory.cpp xbmc-12.0.4.patch/xbmc/settings/GUIWindowSettingsCategory.cpp +--- xbmc-12.0.4/xbmc/settings/GUIWindowSettingsCategory.cpp 2013-03-08 13:01:31.000000000 +0100 ++++ xbmc-12.0.4.patch/xbmc/settings/GUIWindowSettingsCategory.cpp 2013-03-10 13:00:12.331988105 +0100 +@@ -528,6 +528,14 @@ + FillInRefreshRates(strSetting, g_guiSettings.GetResolution(), false); + continue; + } ++#if defined(HAS_GLX) ++ else if (strSetting.Equals("videoscreen.monitor")) ++ { ++ AddSetting(pSetting, group->GetWidth(), iControlID); ++ FillInMonitors(strSetting); ++ continue; ++ } ++#endif + else if (strSetting.Equals("lookandfeel.skintheme")) + { + AddSetting(pSetting, group->GetWidth(), iControlID); +@@ -596,6 +604,23 @@ + pControl->SetEnabled(true); + } + } ++ else if (strSetting.Equals("videoplayer.usevdpaumixer")) ++ { ++ bool hasInterop = true; ++#ifndef GL_NV_vdpau_interop ++ hasInterop = false; ++#endif ++ CGUIControl *pControl = (CGUIControl *)GetControl(pSettingControl->GetID()); ++ if (pControl && hasInterop && glewIsSupported("GL_NV_vdpau_interop")) ++ { ++ pControl->SetEnabled(true); ++ } ++ else ++ { ++ pControl->SetEnabled(false); ++ g_guiSettings.SetBool("videoplayer.usevdpaumixer",true); ++ } ++ } + else + #endif + if (strSetting.Equals("videoscreen.resolution")) +@@ -1460,6 +1485,22 @@ + // Cascade + FillInResolutions("videoscreen.resolution", mode, RES_DESKTOP, true); } - - XMode currmode = g_xrandr.GetCurrentMode(out.name); -- -- // flip h/w when rotated -- if (m_bIsRotated) -+ if (!currmode.name.empty()) ++#if defined(HAS_GLX) ++ else if (strSetting.Equals("videoscreen.monitor")) ++ { ++ CSettingString *pSettingString = (CSettingString *)pSettingControl->GetSetting(); ++ CGUISpinControlEx *pControl = (CGUISpinControlEx *)GetControl(pSettingControl->GetID()); ++ CStdString currentMonitor = pControl->GetCurrentLabel(); ++ if (!g_Windowing.IsCurrentOutput(currentMonitor)) ++ { ++ g_guiSettings.SetString("videoscreen.monitor", currentMonitor); ++ g_Windowing.UpdateResolutions(); ++ DisplayMode mode = g_guiSettings.GetInt("videoscreen.screen"); ++ // Cascade ++ FillInResolutions("videoscreen.resolution", mode, RES_DESKTOP, true); ++ } ++ } ++#endif + else if (strSetting.Equals("videoscreen.resolution")) { -- int w = mode.w; -- mode.w = mode.h; -- mode.h = w; + RESOLUTION nextRes = (RESOLUTION) g_guiSettings.GetInt("videoscreen.resolution"); +@@ -2396,11 +2437,15 @@ + if (g_advancedSettings.m_canWindowed) + pControl->AddLabel(g_localizeStrings.Get(242), -1); + ++#if !defined(HAS_GLX) + for (int idx = 0; idx < g_Windowing.GetNumScreens(); idx++) + { + strScreen.Format(g_localizeStrings.Get(241), g_settings.m_ResInfo[RES_DESKTOP + idx].iScreen + 1); + pControl->AddLabel(strScreen, g_settings.m_ResInfo[RES_DESKTOP + idx].iScreen); + } ++#else ++ pControl->AddLabel(g_localizeStrings.Get(244), 0); ++#endif + pControl->SetValue(mode); + g_guiSettings.SetInt("videoscreen.screen", mode); + } +@@ -2408,6 +2453,38 @@ + return mode; + } + ++void CGUIWindowSettingsCategory::FillInMonitors(CStdString strSetting) ++{ ++#if defined(HAS_GLX) ++ // we expect "videoscreen.monitor" but it might be hidden on some platforms, ++ // so check that we actually have a visable control. ++ BaseSettingControlPtr control = GetSetting(strSetting); ++ if (control) ++ { ++ control->SetDelayed(); ++ CGUISpinControlEx *pControl = (CGUISpinControlEx *)GetControl(control->GetID()); ++ pControl->Clear(); ++ ++ std::vector monitors; ++ g_Windowing.GetConnectedOutputs(&monitors); ++ ++ int currentMonitor = 0; ++ for (unsigned int i=0; iAddLabel(monitors[i], i); ++ } ++ ++ pControl->SetValue(currentMonitor); ++ g_guiSettings.SetString("videoscreen.monitor", g_settings.m_ResInfo[RES_DESKTOP].strOutput); ++ } ++#endif ++} ++ ++ + void CGUIWindowSettingsCategory::FillInResolutions(CStdString strSetting, DisplayMode mode, RESOLUTION res, bool UserChange) + { + BaseSettingControlPtr control = GetSetting(strSetting); +@@ -2536,13 +2613,18 @@ + RESOLUTION lastRes = g_graphicsContext.GetVideoResolution(); + bool cancelled = false; + ++ bool outputChanged = true; ++#if defined(HAS_GLX) ++ outputChanged = !g_Windowing.IsCurrentOutput(g_guiSettings.GetString("videoscreen.monitor")); ++#endif ++ + g_guiSettings.SetResolution(nextRes); +- g_graphicsContext.SetVideoResolution(nextRes); ++ g_graphicsContext.SetVideoResolution(nextRes, outputChanged); + + if (!CGUIDialogYesNo::ShowAndGetInput(13110, 13111, 20022, 20022, -1, -1, cancelled, 10000)) + { + g_guiSettings.SetResolution(lastRes); +- g_graphicsContext.SetVideoResolution(lastRes); ++ g_graphicsContext.SetVideoResolution(lastRes, outputChanged); + + DisplayMode mode = FillInScreens("videoscreen.screen", lastRes); + FillInResolutions("videoscreen.resolution", mode, lastRes, false); +diff -Naur xbmc-12.0.4/xbmc/settings/GUIWindowSettingsCategory.h xbmc-12.0.4.patch/xbmc/settings/GUIWindowSettingsCategory.h +--- xbmc-12.0.4/xbmc/settings/GUIWindowSettingsCategory.h 2013-03-08 13:01:31.000000000 +0100 ++++ xbmc-12.0.4.patch/xbmc/settings/GUIWindowSettingsCategory.h 2013-03-10 13:00:12.313988234 +0100 +@@ -51,6 +51,7 @@ + void FillInSoundSkins(CSetting *pSetting); + void FillInLanguages(CSetting *pSetting, const std::vector &languages = std::vector(), const std::vector &languageKeys = std::vector()); + DisplayMode FillInScreens(CStdString strSetting, RESOLUTION res); ++ void FillInMonitors(CStdString strSetting); + void FillInResolutions(CStdString strSetting, DisplayMode mode, RESOLUTION res, bool UserChange); + void FillInRefreshRates(CStdString strSetting, RESOLUTION res, bool UserChange); + void OnRefreshRateChanged(RESOLUTION resolution); +diff -Naur xbmc-12.0.4/xbmc/settings/Settings.cpp xbmc-12.0.4.patch/xbmc/settings/Settings.cpp +--- xbmc-12.0.4/xbmc/settings/Settings.cpp 2013-03-08 13:01:31.000000000 +0100 ++++ xbmc-12.0.4.patch/xbmc/settings/Settings.cpp 2013-03-10 13:00:12.315988220 +0100 +@@ -55,6 +55,7 @@ + #include "filesystem/File.h" + #include "filesystem/DirectoryCache.h" + #include "DatabaseManager.h" ++#include "windowing/WindowingFactory.h" + + using namespace std; + using namespace XFILE; +diff -Naur xbmc-12.0.4/xbmc/settings/VideoSettings.h xbmc-12.0.4.patch/xbmc/settings/VideoSettings.h +--- xbmc-12.0.4/xbmc/settings/VideoSettings.h 2013-03-08 13:01:31.000000000 +0100 ++++ xbmc-12.0.4.patch/xbmc/settings/VideoSettings.h 2013-03-10 13:00:12.325988148 +0100 +@@ -65,6 +65,8 @@ + VS_INTERLACEMETHOD_SW_BLEND = 20, + VS_INTERLACEMETHOD_AUTO_ION = 21, + ++ VS_INTERLACEMETHOD_XVBA = 22, ++ + VS_INTERLACEMETHOD_MAX // do not use and keep as last enum value. + }; + +diff -Naur xbmc-12.0.4/xbmc/system.h xbmc-12.0.4.patch/xbmc/system.h +--- xbmc-12.0.4/xbmc/system.h 2013-03-08 13:01:29.000000000 +0100 ++++ xbmc-12.0.4.patch/xbmc/system.h 2013-03-10 13:00:12.308988270 +0100 +@@ -162,16 +162,21 @@ + #define HAS_GL + #ifdef HAVE_X11 + #define HAS_GLX ++#define HAS_X11_WIN_EVENTS + #endif + #ifdef HAVE_SDL + #define HAS_SDL + #ifndef HAS_SDL_OPENGL + #define HAS_SDL_OPENGL + #endif ++#ifndef HAVE_X11 + #define HAS_SDL_WIN_EVENTS ++#endif + #else ++#ifndef HAVE_X11 + #define HAS_LINUX_EVENTS + #endif ++#endif + #define HAS_LINUX_NETWORK + #define HAS_LIRC + #ifdef HAVE_LIBPULSE +diff -Naur xbmc-12.0.4/xbmc/utils/ActorProtocol.cpp xbmc-12.0.4.patch/xbmc/utils/ActorProtocol.cpp +--- xbmc-12.0.4/xbmc/utils/ActorProtocol.cpp 1970-01-01 01:00:00.000000000 +0100 ++++ xbmc-12.0.4.patch/xbmc/utils/ActorProtocol.cpp 2013-03-10 13:00:12.300988328 +0100 +@@ -0,0 +1,253 @@ ++/* ++ * Copyright (C) 2005-2012 Team XBMC ++ * http://www.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 ++ * . ++ * ++ */ ++ ++#include "ActorProtocol.h" ++ ++using namespace Actor; ++ ++void Message::Release() ++{ ++ bool skip; ++ origin->Lock(); ++ skip = isSync ? !isSyncFini : false; ++ isSyncFini = true; ++ origin->Unlock(); ++ ++ if (skip) ++ return; ++ ++ // free data buffer ++ if (data != buffer) ++ delete [] data; ++ ++ // delete event in case of sync message ++ if (event) ++ delete event; ++ ++ origin->ReturnMessage(this); ++} ++ ++bool Message::Reply(int sig, void *data /* = NULL*/, int size /* = 0 */) ++{ ++ if (!isSync) ++ { ++ if (isOut) ++ return origin->SendInMessage(sig, data, size); ++ else ++ return origin->SendOutMessage(sig, data, size); ++ } ++ ++ origin->Lock(); ++ ++ if (!isSyncTimeout) ++ { ++ Message *msg = origin->GetMessage(); ++ msg->signal = sig; ++ msg->isOut = !isOut; ++ replyMessage = msg; ++ if (data) ++ { ++ if (size > MSG_INTERNAL_BUFFER_SIZE) ++ msg->data = new uint8_t[size]; ++ else ++ msg->data = msg->buffer; ++ memcpy(msg->data, data, size); ++ } ++ } ++ ++ origin->Unlock(); ++ ++ if (event) ++ event->Set(); ++ ++ return true; ++} ++ ++Protocol::~Protocol() ++{ ++ Message *msg; ++ Purge(); ++ while (!freeMessageQueue.empty()) ++ { ++ msg = freeMessageQueue.front(); ++ freeMessageQueue.pop(); ++ delete msg; ++ } ++} ++ ++Message *Protocol::GetMessage() ++{ ++ Message *msg; ++ ++ CSingleLock lock(criticalSection); ++ ++ if (!freeMessageQueue.empty()) ++ { ++ msg = freeMessageQueue.front(); ++ freeMessageQueue.pop(); ++ } ++ else ++ msg = new Message(); ++ ++ msg->isSync = false; ++ msg->isSyncFini = false; ++ msg->isSyncTimeout = false; ++ msg->event = NULL; ++ msg->data = NULL; ++ msg->payloadSize = 0; ++ msg->replyMessage = NULL; ++ msg->origin = this; ++ ++ return msg; ++} ++ ++void Protocol::ReturnMessage(Message *msg) ++{ ++ CSingleLock lock(criticalSection); ++ ++ freeMessageQueue.push(msg); ++} ++ ++bool Protocol::SendOutMessage(int signal, void *data /* = NULL */, int size /* = 0 */, Message *outMsg /* = NULL */) ++{ ++ Message *msg; ++ if (outMsg) ++ msg = outMsg; ++ else ++ msg = GetMessage(); ++ ++ msg->signal = signal; ++ msg->isOut = true; ++ ++ if (data) ++ { ++ if (size > MSG_INTERNAL_BUFFER_SIZE) ++ msg->data = new uint8_t[size]; ++ else ++ msg->data = msg->buffer; ++ memcpy(msg->data, data, size); ++ } ++ ++ { CSingleLock lock(criticalSection); ++ outMessages.push(msg); ++ } ++ containerOutEvent->Set(); ++ ++ return true; ++} ++ ++bool Protocol::SendInMessage(int signal, void *data /* = NULL */, int size /* = 0 */, Message *outMsg /* = NULL */) ++{ ++ Message *msg; ++ if (outMsg) ++ msg = outMsg; ++ else ++ msg = GetMessage(); ++ ++ msg->signal = signal; ++ msg->isOut = false; ++ ++ if (data) ++ { ++ if (size > MSG_INTERNAL_BUFFER_SIZE) ++ msg->data = new uint8_t[size]; ++ else ++ msg->data = msg->buffer; ++ memcpy(msg->data, data, size); ++ } ++ ++ { CSingleLock lock(criticalSection); ++ inMessages.push(msg); ++ } ++ containerInEvent->Set(); ++ ++ return true; ++} ++ ++ ++bool Protocol::SendOutMessageSync(int signal, Message **retMsg, int timeout, void *data /* = NULL */, int size /* = 0 */) ++{ ++ Message *msg = GetMessage(); ++ msg->isOut = true; ++ msg->isSync = true; ++ msg->event = new CEvent; ++ msg->event->Reset(); ++ SendOutMessage(signal, data, size, msg); ++ ++ if (!msg->event->WaitMSec(timeout)) ++ { ++ msg->origin->Lock(); ++ if (msg->replyMessage) ++ *retMsg = msg->replyMessage; ++ else ++ { ++ *retMsg = NULL; ++ msg->isSyncTimeout = true; ++ } ++ msg->origin->Unlock(); ++ } ++ else ++ *retMsg = msg->replyMessage; ++ ++ msg->Release(); ++ ++ if (*retMsg) ++ return true; ++ else ++ return false; ++} ++ ++bool Protocol::ReceiveOutMessage(Message **msg) ++{ ++ CSingleLock lock(criticalSection); ++ ++ if (outMessages.empty() || outDefered) ++ return false; ++ ++ *msg = outMessages.front(); ++ outMessages.pop(); ++ ++ return true; ++} ++ ++bool Protocol::ReceiveInMessage(Message **msg) ++{ ++ CSingleLock lock(criticalSection); ++ ++ if (inMessages.empty() || inDefered) ++ return false; ++ ++ *msg = inMessages.front(); ++ inMessages.pop(); ++ ++ return true; ++} ++ ++ ++void Protocol::Purge() ++{ ++ Message *msg; ++ ++ while (ReceiveInMessage(&msg)) ++ msg->Release(); ++ ++ while (ReceiveOutMessage(&msg)) ++ msg->Release(); ++} +diff -Naur xbmc-12.0.4/xbmc/utils/ActorProtocol.h xbmc-12.0.4.patch/xbmc/utils/ActorProtocol.h +--- xbmc-12.0.4/xbmc/utils/ActorProtocol.h 1970-01-01 01:00:00.000000000 +0100 ++++ xbmc-12.0.4.patch/xbmc/utils/ActorProtocol.h 2013-03-10 13:00:12.300988328 +0100 +@@ -0,0 +1,87 @@ ++/* ++ * Copyright (C) 2005-2012 Team XBMC ++ * http://www.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 ++ * . ++ * ++ */ ++ ++#pragma once ++ ++#include "threads/Thread.h" ++#include "utils/log.h" ++#include ++#include "memory.h" ++ ++#define MSG_INTERNAL_BUFFER_SIZE 32 ++ ++namespace Actor ++{ ++ ++class Protocol; ++ ++class Message ++{ ++ friend class Protocol; ++public: ++ int signal; ++ bool isSync; ++ bool isSyncFini; ++ bool isOut; ++ bool isSyncTimeout; ++ int payloadSize; ++ uint8_t buffer[MSG_INTERNAL_BUFFER_SIZE]; ++ uint8_t *data; ++ Message *replyMessage; ++ Protocol *origin; ++ CEvent *event; ++ ++ void Release(); ++ bool Reply(int sig, void *data = NULL, int size = 0); ++ ++private: ++ Message() {isSync = false; data = NULL; event = NULL; replyMessage = NULL;}; ++}; ++ ++class Protocol ++{ ++public: ++ Protocol(std::string name, CEvent* inEvent, CEvent *outEvent) ++ : portName(name), inDefered(false), outDefered(false) {containerInEvent = inEvent; containerOutEvent = outEvent;}; ++ virtual ~Protocol(); ++ Message *GetMessage(); ++ void ReturnMessage(Message *msg); ++ bool SendOutMessage(int signal, void *data = NULL, int size = 0, Message *outMsg = NULL); ++ bool SendInMessage(int signal, void *data = NULL, int size = 0, Message *outMsg = NULL); ++ bool SendOutMessageSync(int signal, Message **retMsg, int timeout, void *data = NULL, int size = 0); ++ bool ReceiveOutMessage(Message **msg); ++ bool ReceiveInMessage(Message **msg); ++ void Purge(); ++ void DeferIn(bool value) {inDefered = value;}; ++ void DeferOut(bool value) {outDefered = value;}; ++ void Lock() {criticalSection.lock();}; ++ void Unlock() {criticalSection.unlock();}; ++ std::string portName; ++ ++protected: ++ CEvent *containerInEvent, *containerOutEvent; ++ CCriticalSection criticalSection; ++ std::queue outMessages; ++ std::queue inMessages; ++ std::queue freeMessageQueue; ++ bool inDefered, outDefered; ++}; ++ ++} +diff -Naur xbmc-12.0.4/xbmc/utils/Makefile xbmc-12.0.4.patch/xbmc/utils/Makefile +--- xbmc-12.0.4/xbmc/utils/Makefile 2013-03-08 13:01:28.000000000 +0100 ++++ xbmc-12.0.4.patch/xbmc/utils/Makefile 2013-03-10 13:00:12.300988328 +0100 +@@ -70,6 +70,7 @@ + Weather.cpp \ + XBMCTinyXML.cpp \ + XMLUtils.cpp \ ++ ActorProtocol.cpp \ + + LIB=utils.a + +diff -Naur xbmc-12.0.4/xbmc/video/dialogs/GUIDialogVideoSettings.cpp xbmc-12.0.4.patch/xbmc/video/dialogs/GUIDialogVideoSettings.cpp +--- xbmc-12.0.4/xbmc/video/dialogs/GUIDialogVideoSettings.cpp 2013-03-08 13:01:28.000000000 +0100 ++++ xbmc-12.0.4.patch/xbmc/video/dialogs/GUIDialogVideoSettings.cpp 2013-03-10 13:00:12.325988148 +0100 +@@ -103,13 +103,14 @@ + entries.push_back(make_pair(VS_INTERLACEMETHOD_INVERSE_TELECINE , 16314)); + entries.push_back(make_pair(VS_INTERLACEMETHOD_VDPAU_TEMPORAL_SPATIAL , 16311)); + entries.push_back(make_pair(VS_INTERLACEMETHOD_VDPAU_TEMPORAL , 16310)); +- entries.push_back(make_pair(VS_INTERLACEMETHOD_VDPAU_BOB , 16021)); ++ entries.push_back(make_pair(VS_INTERLACEMETHOD_VDPAU_BOB , 16325)); + entries.push_back(make_pair(VS_INTERLACEMETHOD_VDPAU_TEMPORAL_SPATIAL_HALF, 16318)); + entries.push_back(make_pair(VS_INTERLACEMETHOD_VDPAU_TEMPORAL_HALF , 16317)); + entries.push_back(make_pair(VS_INTERLACEMETHOD_VDPAU_INVERSE_TELECINE , 16314)); + entries.push_back(make_pair(VS_INTERLACEMETHOD_DXVA_BOB , 16320)); + entries.push_back(make_pair(VS_INTERLACEMETHOD_DXVA_BEST , 16321)); + entries.push_back(make_pair(VS_INTERLACEMETHOD_AUTO_ION , 16325)); ++ entries.push_back(make_pair(VS_INTERLACEMETHOD_XVBA , 16326)); + + /* remove unsupported methods */ + for(vector >::iterator it = entries.begin(); it != entries.end();) +diff -Naur xbmc-12.0.4/xbmc/video/VideoReferenceClock.cpp xbmc-12.0.4.patch/xbmc/video/VideoReferenceClock.cpp +--- xbmc-12.0.4/xbmc/video/VideoReferenceClock.cpp 2013-03-08 13:01:28.000000000 +0100 ++++ xbmc-12.0.4.patch/xbmc/video/VideoReferenceClock.cpp 2013-03-10 13:00:12.317988206 +0100 +@@ -30,6 +30,7 @@ + #include + #include + #include "windowing/WindowingFactory.h" ++ #include "guilib/GraphicContext.h" + #define NVSETTINGSCMD "nvidia-settings -nt -q RefreshRate3" + #elif defined(TARGET_DARWIN_OSX) + #include +@@ -135,12 +136,23 @@ + m_Context = NULL; + m_pixmap = None; + m_glPixmap = None; +- m_RREventBase = 0; +- m_UseNvSettings = true; ++ m_UseNvSettings = false; + m_bIsATI = false; + #endif + } + ++CVideoReferenceClock::~CVideoReferenceClock() ++{ ++#if defined(HAS_GLX) ++ // some ATI voodoo, if we don't close the display, we crash on exit ++ if (m_Dpy) ++ { ++ XCloseDisplay(m_Dpy); ++ m_Dpy = NULL; ++ } ++#endif ++} ++ + void CVideoReferenceClock::Process() + { + bool SetupSuccess = false; +@@ -151,6 +163,10 @@ + m_D3dCallback.Reset(); + g_Windowing.Register(&m_D3dCallback); + #endif ++#if defined(HAS_GLX) && defined(HAS_XRANDR) ++ g_Windowing.Register(this); ++ m_xrrEvent = false; ++#endif + + while(!m_bStop) + { +@@ -211,6 +227,16 @@ + //clean up the vblank clock + #if defined(HAS_GLX) && defined(HAS_XRANDR) + CleanupGLX(); ++ if (m_xrrEvent) ++ { ++ m_releaseEvent.Set(); ++ while (!m_bStop) ++ { ++ if (m_resetEvent.WaitMSec(100)) ++ break; ++ } ++ m_xrrEvent = false; ++ } + #elif defined(_WIN32) && defined(HAS_DX) + CleanupD3D(); + #elif defined(TARGET_DARWIN) +@@ -222,6 +248,9 @@ + #if defined(_WIN32) && defined(HAS_DX) + g_Windowing.Unregister(&m_D3dCallback); + #endif ++#if defined(HAS_GLX) ++ g_Windowing.Unregister(this); ++#endif + } + + bool CVideoReferenceClock::WaitStarted(int MSecs) +@@ -231,6 +260,24 @@ + } + + #if defined(HAS_GLX) && defined(HAS_XRANDR) ++ ++void CVideoReferenceClock::OnLostDevice() ++{ ++ if (!m_xrrEvent) ++ { ++ m_releaseEvent.Reset(); ++ m_resetEvent.Reset(); ++ m_xrrEvent = true; ++ m_releaseEvent.Wait(); ++ } ++} ++ ++void CVideoReferenceClock::OnResetDevice() ++{ ++ m_xrrEvent = false; ++ m_resetEvent.Set(); ++} ++ + bool CVideoReferenceClock::SetupGLX() + { + int singleBufferAttributes[] = { +@@ -270,7 +317,7 @@ + } + + bool ExtensionFound = false; +- istringstream Extensions(glXQueryExtensionsString(m_Dpy, DefaultScreen(m_Dpy))); ++ istringstream Extensions(glXQueryExtensionsString(m_Dpy, g_Windowing.GetCurrentScreen())); + string ExtensionStr; + + while (!ExtensionFound) +@@ -297,7 +344,7 @@ + m_bIsATI = true; + } + +- m_vInfo = glXChooseVisual(m_Dpy, DefaultScreen(m_Dpy), singleBufferAttributes); ++ m_vInfo = glXChooseVisual(m_Dpy, g_Windowing.GetCurrentScreen(), singleBufferAttributes); + if (!m_vInfo) + { + CLog::Log(LOGDEBUG, "CVideoReferenceClock: glXChooseVisual returned NULL"); +@@ -308,15 +355,16 @@ + { + Swa.border_pixel = 0; + Swa.event_mask = StructureNotifyMask; +- Swa.colormap = XCreateColormap(m_Dpy, RootWindow(m_Dpy, m_vInfo->screen), m_vInfo->visual, AllocNone ); ++ Swa.colormap = XCreateColormap(m_Dpy, g_Windowing.GetWindow(), m_vInfo->visual, AllocNone ); + SwaMask = CWBorderPixel | CWColormap | CWEventMask; + +- m_Window = XCreateWindow(m_Dpy, RootWindow(m_Dpy, m_vInfo->screen), 0, 0, 256, 256, 0, ++ m_Window = XCreateWindow(m_Dpy, g_Windowing.GetWindow(), 0, 0, 256, 256, 0, + m_vInfo->depth, InputOutput, m_vInfo->visual, SwaMask, &Swa); + } + else + { +- m_pixmap = XCreatePixmap(m_Dpy, DefaultRootWindow(m_Dpy), 256, 256, m_vInfo->depth); ++ Window window = g_Windowing.GetWindow(); ++ m_pixmap = XCreatePixmap(m_Dpy, window, 256, 256, m_vInfo->depth); + if (!m_pixmap) + { + CLog::Log(LOGDEBUG, "CVideoReferenceClock: unable to create pixmap"); +@@ -381,10 +429,6 @@ + return false; + } + +- //set up receiving of RandR events, we'll get one when the refreshrate changes +- XRRQueryExtension(m_Dpy, &m_RREventBase, &ReturnV); +- XRRSelectInput(m_Dpy, RootWindow(m_Dpy, m_vInfo->screen), RRScreenChangeNotifyMask); +- + UpdateRefreshrate(true); //forced refreshrate update + m_MissedVblanks = 0; + +@@ -518,7 +562,7 @@ + int RefreshRate; + XRRScreenConfiguration *CurrInfo; + +- CurrInfo = XRRGetScreenInfo(m_Dpy, RootWindow(m_Dpy, m_vInfo->screen)); ++ CurrInfo = XRRGetScreenInfo(m_Dpy, g_Windowing.GetWindow()); + RefreshRate = XRRConfigCurrentRate(CurrInfo); + XRRFreeScreenConfigInfo(CurrInfo); + +@@ -585,6 +629,9 @@ + + while(!m_bStop) + { ++ if (m_xrrEvent) ++ return; ++ + //wait for the next vblank + if (!m_bIsATI) + { +@@ -648,7 +695,6 @@ + UpdateClock((int)(VblankCount - PrevVblankCount), true); + SingleLock.Leave(); + SendVblankSignal(); +- UpdateRefreshrate(); + IsReset = false; + } + else if (!m_bStop) +@@ -1185,23 +1231,10 @@ + + #if defined(HAS_GLX) && defined(HAS_XRANDR) + +- //check for RandR events +- bool GotEvent = Forced || m_RefreshChanged == 2; +- XEvent Event; +- while (XCheckTypedEvent(m_Dpy, m_RREventBase + RRScreenChangeNotify, &Event)) +- { +- if (Event.type == m_RREventBase + RRScreenChangeNotify) +- { +- CLog::Log(LOGDEBUG, "CVideoReferenceClock: Received RandR event %i", Event.type); +- GotEvent = true; +- } +- XRRUpdateConfiguration(&Event); - } +- + if (!Forced) + m_RefreshChanged = 0; + +- if (!GotEvent) //refreshrate did not change ++ if (!Forced) //refreshrate did not change + return false; + + //the refreshrate can be wrong on nvidia drivers, so read it from nvidia-settings when it's available +@@ -1222,7 +1255,7 @@ + } + + CSingleLock SingleLock(m_CritSection); +- m_RefreshRate = GetRandRRate(); ++ m_RefreshRate = MathUtils::round_int(g_graphicsContext.GetFPS()); + + CLog::Log(LOGDEBUG, "CVideoReferenceClock: Detected refreshrate: %i hertz", (int)m_RefreshRate); + +diff -Naur xbmc-12.0.4/xbmc/video/VideoReferenceClock.h xbmc-12.0.4.patch/xbmc/video/VideoReferenceClock.h +--- xbmc-12.0.4/xbmc/video/VideoReferenceClock.h 2013-03-08 13:01:28.000000000 +0100 ++++ xbmc-12.0.4.patch/xbmc/video/VideoReferenceClock.h 2013-03-10 13:00:12.315988220 +0100 +@@ -30,6 +30,7 @@ + #include + #include + #include ++ #include "guilib/DispResource.h" + #elif defined(_WIN32) && defined(HAS_DX) + #include + #include "guilib/D3DResource.h" +@@ -56,9 +57,13 @@ + #endif + + class CVideoReferenceClock : public CThread ++#if defined(HAS_GLX) && defined(HAS_XRANDR) ++ ,public IDispResource ++#endif + { + public: + CVideoReferenceClock(); ++ virtual ~CVideoReferenceClock(); + + int64_t GetTime(bool interpolated = true); + int64_t GetFrequency(); +@@ -75,6 +80,11 @@ + void VblankHandler(int64_t nowtime, double fps); + #endif + ++#if defined(HAS_GLX) && defined(HAS_XRANDR) ++ virtual void OnLostDevice(); ++ virtual void OnResetDevice(); ++#endif ++ + private: + void Process(); + bool UpdateRefreshrate(bool Forced = false); +@@ -121,7 +131,8 @@ + GLXContext m_Context; + Pixmap m_pixmap; + GLXPixmap m_glPixmap; +- int m_RREventBase; ++ bool m_xrrEvent; ++ CEvent m_releaseEvent, m_resetEvent; + + bool m_UseNvSettings; + bool m_bIsATI; +diff -Naur xbmc-12.0.4/xbmc/windowing/Makefile xbmc-12.0.4.patch/xbmc/windowing/Makefile +--- xbmc-12.0.4/xbmc/windowing/Makefile 2013-03-08 13:01:29.000000000 +0100 ++++ xbmc-12.0.4.patch/xbmc/windowing/Makefile 2013-03-10 13:00:12.308988270 +0100 +@@ -1,6 +1,7 @@ + SRCS=WinEventsSDL.cpp \ + WinEventsLinux.cpp \ + WinSystem.cpp \ ++ WinEventsX11.cpp \ + + LIB=windowing.a + +diff -Naur xbmc-12.0.4/xbmc/windowing/WinEvents.h xbmc-12.0.4.patch/xbmc/windowing/WinEvents.h +--- xbmc-12.0.4/xbmc/windowing/WinEvents.h 2013-03-08 13:01:29.000000000 +0100 ++++ xbmc-12.0.4.patch/xbmc/windowing/WinEvents.h 2013-03-10 13:00:12.308988270 +0100 +@@ -58,6 +58,10 @@ + #include "WinEventsSDL.h" + #define CWinEvents CWinEventsSDL + ++#elif defined(TARGET_LINUX) && defined(HAS_X11_WIN_EVENTS) ++#include "WinEventsX11.h" ++#define CWinEvents CWinEventsX11 ++ + #elif defined(TARGET_LINUX) && defined(HAS_LINUX_EVENTS) + #include "WinEventsLinux.h" + #define CWinEvents CWinEventsLinux +diff -Naur xbmc-12.0.4/xbmc/windowing/WinEventsX11.cpp xbmc-12.0.4.patch/xbmc/windowing/WinEventsX11.cpp +--- xbmc-12.0.4/xbmc/windowing/WinEventsX11.cpp 1970-01-01 01:00:00.000000000 +0100 ++++ xbmc-12.0.4.patch/xbmc/windowing/WinEventsX11.cpp 2013-03-10 13:00:12.330988113 +0100 +@@ -0,0 +1,750 @@ ++/* ++* Copyright (C) 2005-2012 Team XBMC ++* http://www.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, write to ++* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. ++* http://www.gnu.org/copyleft/gpl.html ++* ++*/ ++ ++#include "system.h" ++ ++#ifdef HAS_X11_WIN_EVENTS ++ ++#include "WinEvents.h" ++#include "WinEventsX11.h" ++#include "Application.h" ++#include "ApplicationMessenger.h" ++#include ++#include "X11/WinSystemX11GL.h" ++#include "X11/keysymdef.h" ++#include "X11/XF86keysym.h" ++#include "utils/log.h" ++#include "utils/CharsetConverter.h" ++#include "guilib/GUIWindowManager.h" ++#include "input/MouseStat.h" ++ ++#if defined(HAS_XRANDR) ++#include ++#endif ++ ++#ifdef HAS_SDL_JOYSTICK ++#include "input/SDLJoystick.h" ++#endif ++ ++CWinEventsX11* CWinEventsX11::WinEvents = 0; ++ ++static uint32_t SymMappingsX11[][2] = ++{ ++ {XK_BackSpace, XBMCK_BACKSPACE} ++, {XK_Tab, XBMCK_TAB} ++, {XK_Clear, XBMCK_CLEAR} ++, {XK_Return, XBMCK_RETURN} ++, {XK_Pause, XBMCK_PAUSE} ++, {XK_Escape, XBMCK_ESCAPE} ++, {XK_Delete, XBMCK_DELETE} ++// multi-media keys ++, {XF86XK_Back, XBMCK_BROWSER_BACK} ++, {XF86XK_Forward, XBMCK_BROWSER_FORWARD} ++, {XF86XK_Refresh, XBMCK_BROWSER_REFRESH} ++, {XF86XK_Stop, XBMCK_BROWSER_STOP} ++, {XF86XK_Search, XBMCK_BROWSER_SEARCH} ++, {XF86XK_Favorites, XBMCK_BROWSER_FAVORITES} ++, {XF86XK_HomePage, XBMCK_BROWSER_HOME} ++, {XF86XK_AudioMute, XBMCK_VOLUME_MUTE} ++, {XF86XK_AudioLowerVolume, XBMCK_VOLUME_DOWN} ++, {XF86XK_AudioRaiseVolume, XBMCK_VOLUME_UP} ++, {XF86XK_AudioNext, XBMCK_MEDIA_NEXT_TRACK} ++, {XF86XK_AudioPrev, XBMCK_MEDIA_PREV_TRACK} ++, {XF86XK_AudioStop, XBMCK_MEDIA_STOP} ++, {XF86XK_AudioPause, XBMCK_MEDIA_PLAY_PAUSE} ++, {XF86XK_Mail, XBMCK_LAUNCH_MAIL} ++, {XF86XK_Select, XBMCK_LAUNCH_MEDIA_SELECT} ++, {XF86XK_Launch0, XBMCK_LAUNCH_APP1} ++, {XF86XK_Launch1, XBMCK_LAUNCH_APP2} ++, {XF86XK_WWW, XBMCK_LAUNCH_FILE_BROWSER} ++, {XF86XK_AudioMedia, XBMCK_LAUNCH_MEDIA_CENTER } ++ // Numeric keypad ++, {XK_KP_0, XBMCK_KP0} ++, {XK_KP_1, XBMCK_KP1} ++, {XK_KP_2, XBMCK_KP2} ++, {XK_KP_3, XBMCK_KP3} ++, {XK_KP_4, XBMCK_KP4} ++, {XK_KP_5, XBMCK_KP5} ++, {XK_KP_6, XBMCK_KP6} ++, {XK_KP_7, XBMCK_KP7} ++, {XK_KP_8, XBMCK_KP8} ++, {XK_KP_9, XBMCK_KP9} ++, {XK_KP_Separator, XBMCK_KP_PERIOD} ++, {XK_KP_Divide, XBMCK_KP_DIVIDE} ++, {XK_KP_Multiply, XBMCK_KP_MULTIPLY} ++, {XK_KP_Subtract, XBMCK_KP_MINUS} ++, {XK_KP_Add, XBMCK_KP_PLUS} ++, {XK_KP_Enter, XBMCK_KP_ENTER} ++, {XK_KP_Equal, XBMCK_KP_EQUALS} ++ // Arrows + Home/End pad ++, {XK_Up, XBMCK_UP} ++, {XK_Down, XBMCK_DOWN} ++, {XK_Right, XBMCK_RIGHT} ++, {XK_Left, XBMCK_LEFT} ++, {XK_Insert, XBMCK_INSERT} ++, {XK_Home, XBMCK_HOME} ++, {XK_End, XBMCK_END} ++, {XK_Page_Up, XBMCK_PAGEUP} ++, {XK_Page_Down, XBMCK_PAGEDOWN} ++ // Function keys ++, {XK_F1, XBMCK_F1} ++, {XK_F2, XBMCK_F2} ++, {XK_F3, XBMCK_F3} ++, {XK_F4, XBMCK_F4} ++, {XK_F5, XBMCK_F5} ++, {XK_F6, XBMCK_F6} ++, {XK_F7, XBMCK_F7} ++, {XK_F8, XBMCK_F8} ++, {XK_F9, XBMCK_F9} ++, {XK_F10, XBMCK_F10} ++, {XK_F11, XBMCK_F11} ++, {XK_F12, XBMCK_F12} ++, {XK_F13, XBMCK_F13} ++, {XK_F14, XBMCK_F14} ++, {XK_F15, XBMCK_F15} ++ // Key state modifier keys ++, {XK_Num_Lock, XBMCK_NUMLOCK} ++, {XK_Caps_Lock, XBMCK_CAPSLOCK} ++, {XK_Scroll_Lock, XBMCK_SCROLLOCK} ++, {XK_Shift_R, XBMCK_RSHIFT} ++, {XK_Shift_L, XBMCK_LSHIFT} ++, {XK_Control_R, XBMCK_RCTRL} ++, {XK_Control_L, XBMCK_LCTRL} ++, {XK_Alt_R, XBMCK_RALT} ++, {XK_Alt_L, XBMCK_LALT} ++, {XK_Meta_R, XBMCK_RMETA} ++, {XK_Meta_L, XBMCK_LMETA} ++, {XK_Super_L, XBMCK_LSUPER} ++, {XK_Super_R, XBMCK_RSUPER} ++, {XK_Mode_switch, XBMCK_MODE} ++, {XK_Multi_key, XBMCK_COMPOSE} ++ // Miscellaneous function keys ++, {XK_Help, XBMCK_HELP} ++, {XK_Print, XBMCK_PRINT} ++//, {0, XBMCK_SYSREQ} ++, {XK_Break, XBMCK_BREAK} ++, {XK_Menu, XBMCK_MENU} ++, {XF86XK_PowerOff, XBMCK_POWER} ++, {XF86XK_Sleep, XBMCK_SLEEP} ++, {XK_EcuSign, XBMCK_EURO} ++, {XK_Undo, XBMCK_UNDO} ++ /* Media keys */ ++, {XF86XK_Eject, XBMCK_EJECT} ++, {XF86XK_Stop, XBMCK_STOP} ++, {XF86XK_AudioRecord, XBMCK_RECORD} ++, {XF86XK_AudioRewind, XBMCK_REWIND} ++, {XF86XK_Phone, XBMCK_PHONE} ++, {XF86XK_AudioPlay, XBMCK_PLAY} ++, {XF86XK_AudioRandomPlay, XBMCK_SHUFFLE} ++, {XF86XK_AudioForward, XBMCK_FASTFORWARD} ++}; ++ ++ ++CWinEventsX11::CWinEventsX11() ++{ ++ m_display = 0; ++ m_window = 0; ++ m_keybuf = 0; ++ m_keybuf_len = 0; ++} ++ ++CWinEventsX11::~CWinEventsX11() ++{ ++ if (m_keybuf); ++ { ++ free(m_keybuf); ++ m_keybuf = 0; ++ } ++ ++ if (m_xic) ++ { ++ XUnsetICFocus(m_xic); ++ XDestroyIC(m_xic); ++ m_xic = 0; ++ } ++ ++ if (m_xim) ++ { ++ XCloseIM(m_xim); ++ m_xim = 0; ++ } ++ ++ m_symLookupTable.clear(); ++} ++ ++bool CWinEventsX11::Init(Display *dpy, Window win) ++{ ++ if (WinEvents) ++ return true; ++ ++ WinEvents = new CWinEventsX11(); ++ WinEvents->m_display = dpy; ++ WinEvents->m_window = win; ++ WinEvents->m_keybuf_len = 32*sizeof(char); ++ WinEvents->m_keybuf = (char*)malloc(WinEvents->m_keybuf_len); ++ WinEvents->m_keymodState = 0; ++ WinEvents->m_wmDeleteMessage = XInternAtom(dpy, "WM_DELETE_WINDOW", False); ++ WinEvents->m_structureChanged = false; ++ WinEvents->m_xrrEventPending = false; ++ memset(&(WinEvents->m_lastKey), 0, sizeof(XBMC_Event)); ++ ++ // open input method ++ char *old_locale = NULL, *old_modifiers = NULL; ++ char res_name[8]; ++ const char *p; ++ size_t n; ++ ++ // set resource name to xbmc, not used ++ strcpy(res_name, "xbmc"); ++ ++ // save current locale, this should be "C" ++ p = setlocale(LC_ALL, NULL); ++ if (p) ++ { ++ old_locale = (char*)malloc(strlen(p) +1); ++ strcpy(old_locale, p); ++ } ++ p = XSetLocaleModifiers(NULL); ++ if (p) ++ { ++ old_modifiers = (char*)malloc(strlen(p) +1); ++ strcpy(old_modifiers, p); ++ } ++ ++ // set users preferences and open input method ++ p = setlocale(LC_ALL, ""); ++ XSetLocaleModifiers(""); ++ WinEvents->m_xim = XOpenIM(WinEvents->m_display, NULL, res_name, res_name); ++ ++ // restore old locale ++ if (old_locale) ++ { ++ setlocale(LC_ALL, old_locale); ++ free(old_locale); ++ } ++ if (old_modifiers) ++ { ++ XSetLocaleModifiers(old_modifiers); ++ free(old_modifiers); ++ } ++ ++ WinEvents->m_xic = NULL; ++ if (WinEvents->m_xim) ++ { ++ WinEvents->m_xic = XCreateIC(WinEvents->m_xim, ++ XNClientWindow, WinEvents->m_window, ++ XNFocusWindow, WinEvents->m_window, ++ XNInputStyle, XIMPreeditNothing | XIMStatusNothing, ++ XNResourceName, res_name, ++ XNResourceClass, res_name, ++ NULL); ++ } ++ ++ if (!WinEvents->m_xic) ++ CLog::Log(LOGWARNING,"CWinEventsX11::Init - no input method found"); ++ ++ // build Keysym lookup table ++ for (unsigned int i = 0; i < sizeof(SymMappingsX11)/(2*sizeof(uint32_t)); ++i) ++ { ++ WinEvents->m_symLookupTable[SymMappingsX11[i][0]] = SymMappingsX11[i][1]; ++ } ++ ++ // register for xrandr events ++#if defined(HAS_XRANDR) ++ int iReturn; ++ XRRQueryExtension(WinEvents->m_display, &WinEvents->m_RREventBase, &iReturn); ++ XRRSelectInput(WinEvents->m_display, WinEvents->m_window, RRScreenChangeNotifyMask); ++#endif ++ ++ return true; ++} ++ ++void CWinEventsX11::Quit() ++{ ++ if (!WinEvents) ++ return; ++ ++ delete WinEvents; ++ WinEvents = 0; ++} ++ ++bool CWinEventsX11::HasStructureChanged() ++{ ++ if (!WinEvents) ++ return false; ++ ++ bool ret = WinEvents->m_structureChanged; ++ WinEvents->m_structureChanged = false; ++ return ret; ++} ++ ++void CWinEventsX11::SetXRRFailSafeTimer(int millis) ++{ ++ if (!WinEvents) ++ return; ++ ++ WinEvents->m_xrrFailSafeTimer.Set(millis); ++ WinEvents->m_xrrEventPending = true; ++} ++ ++bool CWinEventsX11::MessagePump() ++{ ++ if (!WinEvents) ++ return false; ++ ++ bool ret = false; ++ XEvent xevent; ++ unsigned long serial = 0; ++ ++ while (WinEvents && XPending(WinEvents->m_display)) ++ { ++ memset(&xevent, 0, sizeof (XEvent)); ++ XNextEvent(WinEvents->m_display, &xevent); ++ ++ // ignore events generated by auto-repeat ++ if (xevent.type == KeyRelease && XPending(WinEvents->m_display)) ++ { ++ XEvent peekevent; ++ XPeekEvent(WinEvents->m_display, &peekevent); ++ if ((peekevent.type == KeyPress) && ++ (peekevent.xkey.keycode == xevent.xkey.keycode) && ++ ((peekevent.xkey.time - xevent.xkey.time) < 2)) ++ { ++ XNextEvent(WinEvents->m_display, &peekevent); ++ continue; ++ } ++ } ++ ++ if (XFilterEvent(&xevent, None)) ++ continue; ++ ++ switch (xevent.type) ++ { ++ case MapNotify: ++ { ++ g_application.m_AppActive = true; ++ break; ++ } ++ ++ case UnmapNotify: ++ { ++ g_application.m_AppActive = false; ++ break; ++ } ++ ++ case FocusIn: ++ { ++ if (WinEvents->m_xic) ++ XSetICFocus(WinEvents->m_xic); ++ g_application.m_AppFocused = true; ++ memset(&(WinEvents->m_lastKey), 0, sizeof(XBMC_Event)); ++ WinEvents->m_keymodState = 0; ++ if (serial == xevent.xfocus.serial) ++ break; ++ g_Windowing.NotifyAppFocusChange(g_application.m_AppFocused); ++ break; ++ } ++ ++ case FocusOut: ++ { ++ if (WinEvents->m_xic) ++ XUnsetICFocus(WinEvents->m_xic); ++ g_application.m_AppFocused = false; ++ memset(&(WinEvents->m_lastKey), 0, sizeof(XBMC_Event)); ++ g_Windowing.NotifyAppFocusChange(g_application.m_AppFocused); ++ serial = xevent.xfocus.serial; ++ break; ++ } ++ ++ case Expose: ++ { ++ g_windowManager.MarkDirty(); ++ break; ++ } ++ ++ case ConfigureNotify: ++ { ++ if (xevent.xconfigure.window != WinEvents->m_window) ++ break; ++ ++ WinEvents->m_structureChanged = true; ++ XBMC_Event newEvent; ++ memset(&newEvent, 0, sizeof(newEvent)); ++ newEvent.type = XBMC_VIDEORESIZE; ++ newEvent.resize.w = xevent.xconfigure.width; ++ newEvent.resize.h = xevent.xconfigure.height; ++ ret |= g_application.OnEvent(newEvent); ++ g_windowManager.MarkDirty(); ++ break; ++ } ++ ++ case ClientMessage: ++ { ++ if (xevent.xclient.data.l[0] == WinEvents->m_wmDeleteMessage) ++ if (!g_application.m_bStop) CApplicationMessenger::Get().Quit(); ++ break; ++ } ++ ++ case KeyPress: ++ { ++ XBMC_Event newEvent; ++ memset(&newEvent, 0, sizeof(newEvent)); ++ newEvent.type = XBMC_KEYDOWN; ++ KeySym xkeysym; ++ ++ // fallback if we have no IM ++ if (!WinEvents->m_xic) ++ { ++ static XComposeStatus state; ++ char keybuf[32]; ++ xkeysym = XLookupKeysym(&xevent.xkey, 0); ++ newEvent.key.keysym.sym = LookupXbmcKeySym(xkeysym); ++ newEvent.key.keysym.scancode = xevent.xkey.keycode; ++ newEvent.key.state = xevent.xkey.state; ++ newEvent.key.type = xevent.xkey.type; ++ if (XLookupString(&xevent.xkey, keybuf, sizeof(keybuf), NULL, &state)) ++ { ++ newEvent.key.keysym.unicode = keybuf[0]; ++ } ++ ret |= ProcessKey(newEvent, 500); ++ break; ++ } ++ ++ Status status; ++ int len; ++ len = Xutf8LookupString(WinEvents->m_xic, &xevent.xkey, ++ WinEvents->m_keybuf, WinEvents->m_keybuf_len, ++ &xkeysym, &status); ++ if (status == XBufferOverflow) ++ { ++ WinEvents->m_keybuf_len = len; ++ WinEvents->m_keybuf = (char*)realloc(WinEvents->m_keybuf, WinEvents->m_keybuf_len); ++ len = Xutf8LookupString(WinEvents->m_xic, &xevent.xkey, ++ WinEvents->m_keybuf, WinEvents->m_keybuf_len, ++ &xkeysym, &status); ++ } ++ switch (status) ++ { ++ case XLookupNone: ++ break; ++ case XLookupChars: ++ case XLookupBoth: ++ { ++ CStdString data(WinEvents->m_keybuf, len); ++ CStdStringW keys; ++ g_charsetConverter.utf8ToW(data, keys, false); ++ ++ if (keys.length() == 0) ++ { ++ break; ++ } ++ ++ for (unsigned int i = 0; i < keys.length() - 1; i++) ++ { ++ newEvent.key.keysym.sym = XBMCK_UNKNOWN; ++ newEvent.key.keysym.unicode = keys[i]; ++ newEvent.key.state = xevent.xkey.state; ++ newEvent.key.type = xevent.xkey.type; ++ ret |= ProcessKey(newEvent, 500); ++ } ++ if (keys.length() > 0) ++ { ++ newEvent.key.keysym.scancode = xevent.xkey.keycode; ++ xkeysym = XLookupKeysym(&xevent.xkey, 0); ++ newEvent.key.keysym.sym = LookupXbmcKeySym(xkeysym); ++ newEvent.key.keysym.unicode = keys[keys.length() - 1]; ++ newEvent.key.state = xevent.xkey.state; ++ newEvent.key.type = xevent.xkey.type; ++ ++ ret |= ProcessKey(newEvent, 500); ++ } ++ break; ++ } ++ ++ case XLookupKeySym: ++ { ++ newEvent.key.keysym.scancode = xevent.xkey.keycode; ++ newEvent.key.keysym.sym = LookupXbmcKeySym(xkeysym); ++ newEvent.key.state = xevent.xkey.state; ++ newEvent.key.type = xevent.xkey.type; ++ ret |= ProcessKey(newEvent, 500); ++ break; ++ } ++ ++ }// switch status ++ break; ++ } //KeyPress ++ ++ case KeyRelease: ++ { ++ XBMC_Event newEvent; ++ KeySym xkeysym; ++ memset(&newEvent, 0, sizeof(newEvent)); ++ newEvent.type = XBMC_KEYUP; ++ xkeysym = XLookupKeysym(&xevent.xkey, 0); ++ newEvent.key.keysym.scancode = xevent.xkey.keycode; ++ newEvent.key.keysym.sym = LookupXbmcKeySym(xkeysym); ++ newEvent.key.state = xevent.xkey.state; ++ newEvent.key.type = xevent.xkey.type; ++ ret |= ProcessKey(newEvent, 0); ++ break; ++ } ++ ++ case EnterNotify: ++ { ++ g_Windowing.NotifyMouseCoverage(true); ++ break; ++ } ++ ++ // lose mouse coverage ++ case LeaveNotify: ++ { ++ g_Windowing.NotifyMouseCoverage(false); ++ g_Mouse.SetActive(false); ++ break; ++ } ++ ++ case MotionNotify: ++ { ++ XBMC_Event newEvent; ++ memset(&newEvent, 0, sizeof(newEvent)); ++ newEvent.type = XBMC_MOUSEMOTION; ++ newEvent.motion.xrel = (int16_t)xevent.xmotion.x_root; ++ newEvent.motion.yrel = (int16_t)xevent.xmotion.y_root; ++ newEvent.motion.x = (int16_t)xevent.xmotion.x; ++ newEvent.motion.y = (int16_t)xevent.xmotion.y; ++ ret |= g_application.OnEvent(newEvent); ++ break; ++ } ++ ++ case ButtonPress: ++ { ++ XBMC_Event newEvent; ++ memset(&newEvent, 0, sizeof(newEvent)); ++ newEvent.type = XBMC_MOUSEBUTTONDOWN; ++ newEvent.button.button = (unsigned char)xevent.xbutton.button; ++ newEvent.button.state = XBMC_PRESSED; ++ newEvent.button.x = (int16_t)xevent.xbutton.x; ++ newEvent.button.y = (int16_t)xevent.xbutton.y; ++ ret |= g_application.OnEvent(newEvent); ++ break; ++ } ++ ++ case ButtonRelease: ++ { ++ XBMC_Event newEvent; ++ memset(&newEvent, 0, sizeof(newEvent)); ++ newEvent.type = XBMC_MOUSEBUTTONUP; ++ newEvent.button.button = (unsigned char)xevent.xbutton.button; ++ newEvent.button.state = XBMC_RELEASED; ++ newEvent.button.x = (int16_t)xevent.xbutton.x; ++ newEvent.button.y = (int16_t)xevent.xbutton.y; ++ ret |= g_application.OnEvent(newEvent); ++ break; ++ } ++ ++ default: ++ { ++ break; ++ } ++ }// switch event.type ++ ++#if defined(HAS_XRANDR) ++ if (WinEvents && (xevent.type == WinEvents->m_RREventBase + RRScreenChangeNotify)) ++ { ++ XRRUpdateConfiguration(&xevent); ++ if (xevent.xgeneric.serial != serial) ++ g_Windowing.NotifyXRREvent(); ++ WinEvents->m_xrrEventPending = false; ++ serial = xevent.xgeneric.serial; ++ } ++#endif ++ ++ }// while ++ ++ ret |= ProcessKeyRepeat(); ++ ++#if defined(HAS_XRANDR) ++ if (WinEvents && WinEvents->m_xrrEventPending && WinEvents->m_xrrFailSafeTimer.IsTimePast()) ++ { ++ CLog::Log(LOGERROR,"CWinEventsX11::MessagePump - missed XRR Events"); ++ g_Windowing.NotifyXRREvent(); ++ WinEvents->m_xrrEventPending = false; ++ } ++#endif ++ ++#ifdef HAS_SDL_JOYSTICK ++ SDL_Event event; ++ while (SDL_PollEvent(&event)) ++ { ++ switch(event.type) ++ { ++ case SDL_JOYBUTTONUP: ++ case SDL_JOYBUTTONDOWN: ++ case SDL_JOYAXISMOTION: ++ case SDL_JOYBALLMOTION: ++ case SDL_JOYHATMOTION: ++ g_Joystick.Update(event); ++ ret = true; ++ break; ++ ++ default: ++ break; ++ } ++ memset(&event, 0, sizeof(SDL_Event)); ++ } ++#endif ++ ++ return ret; ++} ++ ++bool CWinEventsX11::ProcessKey(XBMC_Event &event, int repeatDelay) ++{ ++ if (event.type == XBMC_KEYDOWN) ++ { ++ // check key modifiers ++ switch(event.key.keysym.sym) ++ { ++ case XBMCK_LSHIFT: ++ WinEvents->m_keymodState |= XBMCKMOD_LSHIFT; ++ break; ++ case XBMCK_RSHIFT: ++ WinEvents->m_keymodState |= XBMCKMOD_RSHIFT; ++ break; ++ case XBMCK_LCTRL: ++ WinEvents->m_keymodState |= XBMCKMOD_LCTRL; ++ break; ++ case XBMCK_RCTRL: ++ WinEvents->m_keymodState |= XBMCKMOD_RCTRL; ++ break; ++ case XBMCK_LALT: ++ WinEvents->m_keymodState |= XBMCKMOD_LALT; ++ break; ++ case XBMCK_RALT: ++ WinEvents->m_keymodState |= XBMCKMOD_RCTRL; ++ break; ++ case XBMCK_LMETA: ++ WinEvents->m_keymodState |= XBMCKMOD_LMETA; ++ break; ++ case XBMCK_RMETA: ++ WinEvents->m_keymodState |= XBMCKMOD_RMETA; ++ break; ++ case XBMCK_MODE: ++ WinEvents->m_keymodState |= XBMCKMOD_MODE; ++ break; ++ default: ++ break; ++ } ++ event.key.keysym.mod = (XBMCMod)WinEvents->m_keymodState; ++ memcpy(&(WinEvents->m_lastKey), &event, sizeof(event)); ++ WinEvents->m_repeatKeyTimeout.Set(repeatDelay); ++ ++ bool ret = ProcessShortcuts(event); ++ if (ret) ++ return ret; ++ } ++ else if (event.type == XBMC_KEYUP) ++ { ++ switch(event.key.keysym.sym) ++ { ++ case XBMCK_LSHIFT: ++ WinEvents->m_keymodState &= ~XBMCKMOD_LSHIFT; ++ break; ++ case XBMCK_RSHIFT: ++ WinEvents->m_keymodState &= ~XBMCKMOD_RSHIFT; ++ break; ++ case XBMCK_LCTRL: ++ WinEvents->m_keymodState &= ~XBMCKMOD_LCTRL; ++ break; ++ case XBMCK_RCTRL: ++ WinEvents->m_keymodState &= ~XBMCKMOD_RCTRL; ++ break; ++ case XBMCK_LALT: ++ WinEvents->m_keymodState &= ~XBMCKMOD_LALT; ++ break; ++ case XBMCK_RALT: ++ WinEvents->m_keymodState &= ~XBMCKMOD_RCTRL; ++ break; ++ case XBMCK_LMETA: ++ WinEvents->m_keymodState &= ~XBMCKMOD_LMETA; ++ break; ++ case XBMCK_RMETA: ++ WinEvents->m_keymodState &= ~XBMCKMOD_RMETA; ++ break; ++ case XBMCK_MODE: ++ WinEvents->m_keymodState &= ~XBMCKMOD_MODE; ++ break; ++ default: ++ break; ++ } ++ event.key.keysym.mod = (XBMCMod)WinEvents->m_keymodState; ++ memset(&(WinEvents->m_lastKey), 0, sizeof(event)); ++ } ++ ++ return g_application.OnEvent(event); ++} ++ ++bool CWinEventsX11::ProcessShortcuts(XBMC_Event& event) ++{ ++ if (event.key.keysym.mod & XBMCKMOD_ALT) ++ { ++ switch(event.key.keysym.sym) ++ { ++ case XBMCK_TAB: // ALT+TAB to minimize/hide ++ g_application.Minimize(); ++ return true; ++ ++ default: ++ return false; ++ } ++ } ++ return false; ++} ++ ++bool CWinEventsX11::ProcessKeyRepeat() ++{ ++ if (WinEvents && (WinEvents->m_lastKey.type == XBMC_KEYDOWN)) ++ { ++ if (WinEvents->m_repeatKeyTimeout.IsTimePast()) ++ { ++ return ProcessKey(WinEvents->m_lastKey, 10); ++ } ++ } ++ return false; ++} ++ ++XBMCKey CWinEventsX11::LookupXbmcKeySym(KeySym keysym) ++{ ++ // try direct mapping first ++ std::map::iterator it; ++ it = WinEvents->m_symLookupTable.find(keysym); ++ if (it != WinEvents->m_symLookupTable.end()) ++ { ++ return (XBMCKey)(it->second); ++ } ++ ++ // try ascii mappings ++ if (keysym>>8 == 0x00) ++ return (XBMCKey)(keysym & 0xFF); ++ ++ return (XBMCKey)keysym; ++} ++#endif +diff -Naur xbmc-12.0.4/xbmc/windowing/WinEventsX11.h xbmc-12.0.4.patch/xbmc/windowing/WinEventsX11.h +--- xbmc-12.0.4/xbmc/windowing/WinEventsX11.h 1970-01-01 01:00:00.000000000 +0100 ++++ xbmc-12.0.4.patch/xbmc/windowing/WinEventsX11.h 2013-03-10 13:00:12.316988213 +0100 +@@ -0,0 +1,61 @@ ++/* ++* Copyright (C) 2005-2012 Team XBMC ++* http://www.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, write to ++* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. ++* http://www.gnu.org/copyleft/gpl.html ++* ++*/ ++#pragma once ++ ++#include "WinEvents.h" ++#include ++#include "threads/SystemClock.h" ++#include ++ ++class CWinEventsX11 : public CWinEventsBase ++{ ++public: ++ CWinEventsX11(); ++ virtual ~CWinEventsX11(); ++ static bool Init(Display *dpy, Window win); ++ static void Quit(); ++ static bool HasStructureChanged(); ++ static void PendingResize(int width, int height); ++ static void SetXRRFailSafeTimer(int millis); ++ static bool MessagePump(); ++ ++protected: ++ static XBMCKey LookupXbmcKeySym(KeySym keysym); ++ static bool ProcessKey(XBMC_Event &event, int repeatDelay); ++ static bool ProcessKeyRepeat(); ++ static bool ProcessShortcuts(XBMC_Event& event); ++ static CWinEventsX11 *WinEvents; ++ Display *m_display; ++ Window m_window; ++ Atom m_wmDeleteMessage; ++ char *m_keybuf; ++ size_t m_keybuf_len; ++ XIM m_xim; ++ XIC m_xic; ++ XBMC_Event m_lastKey; ++ XbmcThreads::EndTime m_repeatKeyTimeout; ++ std::map m_symLookupTable; ++ int m_keymodState; ++ bool m_structureChanged; ++ int m_RREventBase; ++ XbmcThreads::EndTime m_xrrFailSafeTimer; ++ bool m_xrrEventPending; ++}; +diff -Naur xbmc-12.0.4/xbmc/windowing/WinSystem.h xbmc-12.0.4.patch/xbmc/windowing/WinSystem.h +--- xbmc-12.0.4/xbmc/windowing/WinSystem.h 2013-03-08 13:01:29.000000000 +0100 ++++ xbmc-12.0.4.patch/xbmc/windowing/WinSystem.h 2013-03-10 13:00:12.315988220 +0100 +@@ -100,6 +100,7 @@ + std::vector ScreenResolutions(int screen); + std::vector RefreshRates(int screen, int width, int height, uint32_t dwFlags); + REFRESHRATE DefaultRefreshRate(int screen, std::vector rates); ++ virtual bool HasCalibration(const RESOLUTION_INFO &resInfo) { return true; }; + + protected: + void UpdateDesktopResolution(RESOLUTION_INFO& newRes, int screen, int width, int height, float refreshRate, uint32_t dwFlags = 0); +diff -Naur xbmc-12.0.4/xbmc/windowing/X11/WinSystemX11.cpp xbmc-12.0.4.patch/xbmc/windowing/X11/WinSystemX11.cpp +--- xbmc-12.0.4/xbmc/windowing/X11/WinSystemX11.cpp 2013-03-08 13:01:29.000000000 +0100 ++++ xbmc-12.0.4.patch/xbmc/windowing/X11/WinSystemX11.cpp 2013-03-10 13:00:12.331988105 +0100 +@@ -22,7 +22,6 @@ + + #ifdef HAS_GLX + +-#include + #include "WinSystemX11.h" + #include "settings/Settings.h" + #include "guilib/Texture.h" +@@ -31,27 +30,33 @@ + #include "XRandR.h" + #include + #include "threads/SingleLock.h" +-#include + #include "cores/VideoRenderers/RenderManager.h" + #include "utils/TimeUtils.h" ++#include "settings/GUISettings.h" ++#include "windowing/WindowingFactory.h" ++#include + + #if defined(HAS_XRANDR) + #include + #endif + ++#include "../WinEvents.h" ++#include "input/MouseStat.h" ++ + using namespace std; + + CWinSystemX11::CWinSystemX11() : CWinSystemBase() + { + m_eWindowSystem = WINDOW_SYSTEM_X11; + m_glContext = NULL; +- m_SDLSurface = NULL; + m_dpy = NULL; + m_glWindow = 0; +- m_wmWindow = 0; + m_bWasFullScreenBeforeMinimize = false; + m_minimized = false; ++ m_bIgnoreNextFocusMessage = false; + m_dpyLostTime = 0; ++ m_invisibleCursor = 0; ++ m_bIsInternalXrr = false; + + XSetErrorHandler(XErrorHandler); + } +@@ -64,19 +69,8 @@ + { + if ((m_dpy = XOpenDisplay(NULL))) + { +- +- SDL_EnableUNICODE(1); +- // set repeat to 10ms to ensure repeat time < frame time +- // so that hold times can be reliably detected +- SDL_EnableKeyRepeat(SDL_DEFAULT_REPEAT_DELAY, 10); +- +- SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8); +- SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8); +- SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8); +- SDL_GL_SetAttribute(SDL_GL_ALPHA_SIZE, 8); +- SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); +- +- return CWinSystemBase::InitWindowSystem(); ++ bool ret = CWinSystemBase::InitWindowSystem(); ++ return ret; + } + else + CLog::Log(LOGERROR, "GLX Error: No Display found"); +@@ -87,9 +81,18 @@ + bool CWinSystemX11::DestroyWindowSystem() + { + #if defined(HAS_XRANDR) +- //restore videomode on exit ++ //restore desktop resolution on exit + if (m_bFullScreen) +- g_xrandr.RestoreState(); ++ { ++ XOutput out; ++ XMode mode; ++ out.name = g_settings.m_ResInfo[RES_DESKTOP].strOutput; ++ mode.w = g_settings.m_ResInfo[RES_DESKTOP].iWidth; ++ mode.h = g_settings.m_ResInfo[RES_DESKTOP].iHeight; ++ mode.hz = g_settings.m_ResInfo[RES_DESKTOP].fRefreshRate; ++ mode.id = g_settings.m_ResInfo[RES_DESKTOP].strId; ++ g_xrandr.SetMode(out, mode); ++ } + #endif + + if (m_dpy) +@@ -104,6 +107,9 @@ + + //we don't call XCloseDisplay() here, since ati keeps a pointer to our m_dpy + //so instead we just let m_dpy die on exit ++ // i have seen core dumps on ATI if the display is not closed here ++ // crashes when shutting down via cec ++// XCloseDisplay(m_dpy); + } + + // m_SDLSurface is free()'d by SDL_Quit(). +@@ -113,45 +119,43 @@ + + bool CWinSystemX11::CreateNewWindow(const CStdString& name, bool fullScreen, RESOLUTION_INFO& res, PHANDLE_EVENT_FUNC userFunction) + { +- RESOLUTION_INFO& desktop = g_settings.m_ResInfo[RES_DESKTOP]; +- +- if (fullScreen && +- (res.iWidth != desktop.iWidth || res.iHeight != desktop.iHeight || +- res.fRefreshRate != desktop.fRefreshRate || res.iScreen != desktop.iScreen)) +- { +- //on the first call to SDL_SetVideoMode, SDL stores the current displaymode +- //SDL restores the displaymode on SDL_QUIT(), if we change the displaymode +- //before the first call to SDL_SetVideoMode, SDL changes the displaymode back +- //to the wrong mode on exit +- +- CLog::Log(LOGINFO, "CWinSystemX11::CreateNewWindow initializing to desktop resolution first"); +- if (!SetFullScreen(true, desktop, false)) +- return false; +- } +- + if(!SetFullScreen(fullScreen, res, false)) + return false; + +- CBaseTexture* iconTexture = CTexture::LoadFromFile("special://xbmc/media/icon.png"); +- +- if (iconTexture) +- SDL_WM_SetIcon(SDL_CreateRGBSurfaceFrom(iconTexture->GetPixels(), iconTexture->GetWidth(), iconTexture->GetHeight(), 32, iconTexture->GetPitch(), 0xff0000, 0x00ff00, 0x0000ff, 0xff000000L), NULL); +- SDL_WM_SetCaption("XBMC Media Center", NULL); +- delete iconTexture; +- +- // register XRandR Events +-#if defined(HAS_XRANDR) +- int iReturn; +- XRRQueryExtension(m_dpy, &m_RREventBase, &iReturn); +- XRRSelectInput(m_dpy, m_wmWindow, RRScreenChangeNotifyMask); +-#endif +- + m_bWindowCreated = true; + return true; + } + + bool CWinSystemX11::DestroyWindow() + { ++ if (!m_glWindow) ++ return true; ++ ++ if (m_glContext) ++ { ++ glFinish(); ++ glXMakeCurrent(m_dpy, None, NULL); ++ } ++ ++ if (m_invisibleCursor) ++ { ++ XUndefineCursor(m_dpy, m_glWindow); ++ XFreeCursor(m_dpy, m_invisibleCursor); ++ m_invisibleCursor = 0; ++ } ++ ++ CWinEvents::Quit(); ++ ++ XUnmapWindow(m_dpy, m_glWindow); ++ XSync(m_dpy,TRUE); ++ XUngrabKeyboard(m_dpy, CurrentTime); ++ XUngrabPointer(m_dpy, CurrentTime); ++ XDestroyWindow(m_dpy, m_glWindow); ++ m_glWindow = 0; ++ ++ if (m_icon) ++ XFreePixmap(m_dpy, m_icon); ++ + return true; + } + +@@ -161,107 +165,138 @@ + && m_nHeight == newHeight) + return true; + +- m_nWidth = newWidth; +- m_nHeight = newHeight; +- +- int options = SDL_OPENGL; +- if (m_bFullScreen) +- options |= SDL_FULLSCREEN; +- else +- options |= SDL_RESIZABLE; +- +- if ((m_SDLSurface = SDL_SetVideoMode(m_nWidth, m_nHeight, 0, options))) ++ if (!SetWindow(newWidth, newHeight, false, g_guiSettings.GetString("videoscreen.monitor"))) + { +- RefreshGlxContext(); +- return true; ++ return false; + } + ++ m_nWidth = newWidth; ++ m_nHeight = newHeight; ++ m_bFullScreen = false; ++ m_currentOutput = g_guiSettings.GetString("videoscreen.monitor"); ++ + return false; + } + + bool CWinSystemX11::SetFullScreen(bool fullScreen, RESOLUTION_INFO& res, bool blankOtherDisplays) + { +- m_nWidth = res.iWidth; +- m_nHeight = res.iHeight; +- m_bFullScreen = fullScreen; + + #if defined(HAS_XRANDR) + XOutput out; + XMode mode; +- out.name = res.strOutput; +- mode.w = res.iWidth; +- mode.h = res.iHeight; +- mode.hz = res.fRefreshRate; +- mode.id = res.strId; +- +- if(m_bFullScreen) ++ ++ if (fullScreen) + { +- OnLostDevice(); +- g_xrandr.SetMode(out, mode); ++ out.name = res.strOutput; ++ mode.w = res.iWidth; ++ mode.h = res.iHeight; ++ mode.hz = res.fRefreshRate; ++ mode.id = res.strId; + } + else +- g_xrandr.RestoreState(); +-#endif +- +- int options = SDL_OPENGL; +- if (m_bFullScreen) +- options |= SDL_FULLSCREEN; +- else +- options |= SDL_RESIZABLE; +- +- if ((m_SDLSurface = SDL_SetVideoMode(m_nWidth, m_nHeight, 0, options))) + { +- if ((m_SDLSurface->flags & SDL_OPENGL) != SDL_OPENGL) +- CLog::Log(LOGERROR, "CWinSystemX11::SetFullScreen SDL_OPENGL not set, SDL_GetError:%s", SDL_GetError()); +- +- RefreshGlxContext(); ++ out.name = g_settings.m_ResInfo[RES_DESKTOP].strOutput; ++ mode.w = g_settings.m_ResInfo[RES_DESKTOP].iWidth; ++ mode.h = g_settings.m_ResInfo[RES_DESKTOP].iHeight; ++ mode.hz = g_settings.m_ResInfo[RES_DESKTOP].fRefreshRate; ++ mode.id = g_settings.m_ResInfo[RES_DESKTOP].strId; ++ } ++ ++ XMode currmode = g_xrandr.GetCurrentMode(out.name); ++ if (!currmode.name.empty()) ++ { + // flip h/w when rotated + if (m_bIsRotated) + { @@ -20788,16 +14607,7 @@ index b87e264..3cadd13 100644 + mode.h = w; + } -- // only call xrandr if mode changes -- if (currmode.w != mode.w || currmode.h != mode.h || -- currmode.hz != mode.hz || currmode.id != mode.id) -- { -- CLog::Log(LOGNOTICE, "CWinSystemX11::SetFullScreen - calling xrandr"); -- OnLostDevice(); -- m_bIsInternalXrr = true; -- g_xrandr.SetMode(out, mode); -- if (m_glWindow) -- return true; +- return true; + // only call xrandr if mode changes + if (currmode.w != mode.w || currmode.h != mode.h || + currmode.hz != mode.hz || currmode.id != mode.id) @@ -20810,13 +14620,59 @@ index b87e264..3cadd13 100644 + return true; + } } - #endif ++#endif -@@ -268,9 +270,10 @@ void CWinSystemX11::UpdateResolutions() +- return false; ++ if (!SetWindow(res.iWidth, res.iHeight, fullScreen, g_guiSettings.GetString("videoscreen.monitor"))) ++ return false; ++ ++ m_nWidth = res.iWidth; ++ m_nHeight = res.iHeight; ++ m_bFullScreen = fullScreen; ++ m_currentOutput = g_guiSettings.GetString("videoscreen.monitor"); ++ ++ return true; + } + + void CWinSystemX11::UpdateResolutions() + { + CWinSystemBase::UpdateResolutions(); + +- + #if defined(HAS_XRANDR) +- if(g_xrandr.Query()) ++ CStdString currentMonitor; ++ int numScreens = XScreenCount(m_dpy); ++ g_xrandr.SetNumScreens(numScreens); ++ if(g_xrandr.Query(true)) + { +- XOutput out = g_xrandr.GetCurrentOutput(); +- XMode mode = g_xrandr.GetCurrentMode(out.name); +- UpdateDesktopResolution(g_settings.m_ResInfo[RES_DESKTOP], 0, mode.w, mode.h, mode.hz); ++ currentMonitor = g_guiSettings.GetString("videoscreen.monitor"); ++ // check if the monitor is connected ++ XOutput *out = g_xrandr.GetOutput(currentMonitor); ++ if (!out) ++ { ++ // choose first output ++ currentMonitor = g_xrandr.GetModes()[0].name; ++ out = g_xrandr.GetOutput(currentMonitor); ++ g_guiSettings.SetString("videoscreen.monitor", currentMonitor); ++ } ++ XMode mode = g_xrandr.GetCurrentMode(currentMonitor); ++ m_bIsRotated = out->isRotated; ++ if (!m_bIsRotated) ++ UpdateDesktopResolution(g_settings.m_ResInfo[RES_DESKTOP], out->screen, mode.w, mode.h, mode.hz); ++ else ++ UpdateDesktopResolution(g_settings.m_ResInfo[RES_DESKTOP], out->screen, mode.h, mode.w, mode.hz); + g_settings.m_ResInfo[RES_DESKTOP].strId = mode.id; +- g_settings.m_ResInfo[RES_DESKTOP].strOutput = out.name; ++ g_settings.m_ResInfo[RES_DESKTOP].strOutput = currentMonitor; + } else #endif { -- int x11screen = m_nScreen; +- int x11screen = DefaultScreen(m_dpy); - int w = DisplayWidth(m_dpy, x11screen); - int h = DisplayHeight(m_dpy, x11screen); + g_guiSettings.SetString("videoscreen.monitor", "Default"); @@ -20826,17 +14682,467 @@ index b87e264..3cadd13 100644 UpdateDesktopResolution(g_settings.m_ResInfo[RES_DESKTOP], 0, w, h, 0.0); } -@@ -819,11 +822,19 @@ bool CWinSystemX11::SetWindow(int width, int height, bool fullscreen, const CStd - Colormap cmap; - XSetWindowAttributes swa; - XVisualInfo *vi; +- + #if defined(HAS_XRANDR) + ++ // erase previous stored modes ++ if (g_settings.m_ResInfo.size() > RES_CUSTOM) ++ { ++ std::vector::iterator firstCustom = g_settings.m_ResInfo.begin()+RES_CUSTOM; ++ g_settings.m_ResInfo.erase(firstCustom, g_settings.m_ResInfo.end()); ++ } ++ + CLog::Log(LOGINFO, "Available videomodes (xrandr):"); +- vector::iterator outiter; +- vector outs; +- outs = g_xrandr.GetModes(); +- CLog::Log(LOGINFO, "Number of connected outputs: %"PRIdS"", outs.size()); ++ ++ XOutput *out = g_xrandr.GetOutput(currentMonitor); + string modename = ""; + +- for (outiter = outs.begin() ; outiter != outs.end() ; outiter++) ++ if (out != NULL) + { +- XOutput out = *outiter; + vector::iterator modeiter; +- CLog::Log(LOGINFO, "Output '%s' has %"PRIdS" modes", out.name.c_str(), out.modes.size()); ++ CLog::Log(LOGINFO, "Output '%s' has %"PRIdS" modes", out->name.c_str(), out->modes.size()); + +- for (modeiter = out.modes.begin() ; modeiter!=out.modes.end() ; modeiter++) ++ for (modeiter = out->modes.begin() ; modeiter!=out->modes.end() ; modeiter++) + { + XMode mode = *modeiter; + CLog::Log(LOGINFO, "ID:%s Name:%s Refresh:%f Width:%d Height:%d", +@@ -271,17 +306,27 @@ + res.iHeight = mode.h; + res.iScreenWidth = mode.w; + res.iScreenHeight = mode.h; +- if (mode.h>0 && mode.w>0 && out.hmm>0 && out.wmm>0) +- res.fPixelRatio = ((float)out.wmm/(float)mode.w) / (((float)out.hmm/(float)mode.h)); ++ if (!m_bIsRotated) ++ { ++ res.iWidth = mode.w; ++ res.iHeight = mode.h; ++ } ++ else ++ { ++ res.iWidth = mode.h; ++ res.iHeight = mode.w; ++ } ++ if (mode.h>0 && mode.w>0 && out->hmm>0 && out->wmm>0) ++ res.fPixelRatio = ((float)out->wmm/(float)mode.w) / (((float)out->hmm/(float)mode.h)); + else + res.fPixelRatio = 1.0f; + + CLog::Log(LOGINFO, "Pixel Ratio: %f", res.fPixelRatio); + +- res.strMode.Format("%s: %s @ %.2fHz", out.name.c_str(), mode.name.c_str(), mode.hz); +- res.strOutput = out.name; ++ res.strMode.Format("%s: %s @ %.2fHz", out->name.c_str(), mode.name.c_str(), mode.hz); ++ res.strOutput = out->name; + res.strId = mode.id; +- res.iSubtitles = (int)(0.95*mode.h); ++ res.iSubtitles = (int)(0.965*mode.h); + res.fRefreshRate = mode.hz; + res.bFullScreen = true; + +@@ -294,8 +339,57 @@ + g_settings.m_ResInfo.push_back(res); + } + } ++ g_settings.ApplyCalibrations(); + #endif ++} ++ ++bool CWinSystemX11::HasCalibration(const RESOLUTION_INFO &resInfo) ++{ ++ XOutput *out = g_xrandr.GetOutput(m_currentOutput); ++ ++ // keep calibrations done on a not connected output ++ if (!out->name.Equals(resInfo.strOutput)) ++ return true; ++ ++ // keep calibrations not updated with resolution data ++ if (resInfo.iWidth == 0) ++ return true; + ++ float fPixRatio; ++ if (resInfo.iHeight>0 && resInfo.iWidth>0 && out->hmm>0 && out->wmm>0) ++ fPixRatio = ((float)out->wmm/(float)resInfo.iWidth) / (((float)out->hmm/(float)resInfo.iHeight)); ++ else ++ fPixRatio = 1.0f; ++ ++ if (resInfo.Overscan.left != 0) ++ return true; ++ if (resInfo.Overscan.top != 0) ++ return true; ++ if (resInfo.Overscan.right != resInfo.iWidth) ++ return true; ++ if (resInfo.Overscan.bottom != resInfo.iHeight) ++ return true; ++ if (resInfo.fPixelRatio != fPixRatio) ++ return true; ++ if (resInfo.iSubtitles != (int)(0.965*resInfo.iHeight)) ++ return true; ++ ++ return false; ++} ++ ++void CWinSystemX11::GetConnectedOutputs(std::vector *outputs) ++{ ++ vector outs; ++ outs = g_xrandr.GetModes(); ++ for(unsigned int i=0; ipush_back(outs[i].name); ++ } ++} ++ ++bool CWinSystemX11::IsCurrentOutput(CStdString output) ++{ ++ return m_currentOutput.Equals(output); + } + + bool CWinSystemX11::IsSuitableVisual(XVisualInfo *vInfo) +@@ -318,20 +412,13 @@ + return true; + } + +-bool CWinSystemX11::RefreshGlxContext() ++bool CWinSystemX11::RefreshGlxContext(bool force) + { + bool retVal = false; +- SDL_SysWMinfo info; +- SDL_VERSION(&info.version); +- if (SDL_GetWMInfo(&info) <= 0) +- { +- CLog::Log(LOGERROR, "Failed to get window manager info from SDL"); +- return false; +- } + +- if(m_glWindow == info.info.x11.window && m_glContext) ++ if (m_glContext && !force) + { +- CLog::Log(LOGERROR, "GLX: Same window as before, refreshing context"); ++ CLog::Log(LOGDEBUG, "CWinSystemX11::RefreshGlxContext: refreshing context"); + glXMakeCurrent(m_dpy, None, NULL); + glXMakeCurrent(m_dpy, m_glWindow, m_glContext); + return true; +@@ -341,10 +428,8 @@ + XVisualInfo *visuals; + XVisualInfo *vInfo = NULL; + int availableVisuals = 0; +- vMask.screen = DefaultScreen(m_dpy); ++ vMask.screen = m_nScreen; + XWindowAttributes winAttr; +- m_glWindow = info.info.x11.window; +- m_wmWindow = info.info.x11.wmwindow; + + /* Assume a depth of 24 in case the below calls to XGetWindowAttributes() + or XGetVisualInfo() fail. That shouldn't happen unless something is +@@ -395,6 +480,8 @@ + { + glXMakeCurrent(m_dpy, None, NULL); + glXDestroyContext(m_dpy, m_glContext); ++ XSync(m_dpy, FALSE); ++ m_newGlContext = true; + } + + if ((m_glContext = glXCreateContext(m_dpy, vInfo, NULL, True))) +@@ -415,7 +502,10 @@ + + void CWinSystemX11::ShowOSMouse(bool show) + { +- SDL_ShowCursor(show ? 1 : 0); ++ if (show) ++ XUndefineCursor(m_dpy,m_glWindow); ++ else if (m_invisibleCursor) ++ XDefineCursor(m_dpy,m_glWindow, m_invisibleCursor); + } + + void CWinSystemX11::ResetOSScreensaver() +@@ -429,8 +519,6 @@ + { + m_screensaverReset.StartZero(); + XResetScreenSaver(m_dpy); +- //need to flush the output buffer, since we don't check for events on m_dpy +- XFlush(m_dpy); + } + } + else +@@ -439,20 +527,90 @@ + } + } + ++void CWinSystemX11::EnableSystemScreenSaver(bool bEnable) ++{ ++ if (!m_dpy) ++ return; ++ ++ if (bEnable) ++ XForceScreenSaver(m_dpy, ScreenSaverActive); ++ else ++ { ++ Window root_return, child_return; ++ int root_x_return, root_y_return; ++ int win_x_return, win_y_return; ++ unsigned int mask_return; ++ bool isInWin = XQueryPointer(m_dpy, RootWindow(m_dpy, m_nScreen), &root_return, &child_return, ++ &root_x_return, &root_y_return, ++ &win_x_return, &win_y_return, ++ &mask_return); ++ ++ XWarpPointer(m_dpy, None, RootWindow(m_dpy, m_nScreen), 0, 0, 0, 0, root_x_return+300, root_y_return+300); ++ XSync(m_dpy, FALSE); ++ XWarpPointer(m_dpy, None, RootWindow(m_dpy, m_nScreen), 0, 0, 0, 0, 0, 0); ++ XSync(m_dpy, FALSE); ++ XWarpPointer(m_dpy, None, RootWindow(m_dpy, m_nScreen), 0, 0, 0, 0, root_x_return, root_y_return); ++ XSync(m_dpy, FALSE); ++ } ++} ++ + void CWinSystemX11::NotifyAppActiveChange(bool bActivated) + { +- if (bActivated && m_bWasFullScreenBeforeMinimize && !g_graphicsContext.IsFullScreenRoot()) ++ if (bActivated && m_bWasFullScreenBeforeMinimize && !m_bFullScreen) ++ { + g_graphicsContext.ToggleFullScreenRoot(); + ++ m_bWasFullScreenBeforeMinimize = false; ++ } + m_minimized = !bActivated; + } ++ ++void CWinSystemX11::NotifyAppFocusChange(bool bGaining) ++{ ++ if (bGaining && m_bWasFullScreenBeforeMinimize && !m_bIgnoreNextFocusMessage && ++ !m_bFullScreen) ++ { ++ m_bWasFullScreenBeforeMinimize = false; ++ g_graphicsContext.ToggleFullScreenRoot(); ++ m_minimized = false; ++ } ++ if (!bGaining) ++ m_bIgnoreNextFocusMessage = false; ++} ++ ++void CWinSystemX11::NotifyMouseCoverage(bool covered) ++{ ++ if (!m_bFullScreen) ++ return; ++ ++ if (covered) ++ { ++ int result = -1; ++ while (result != GrabSuccess && result != AlreadyGrabbed) ++ { ++ result = XGrabPointer(m_dpy, m_glWindow, True, ButtonPressMask, GrabModeAsync, GrabModeAsync, None, None, CurrentTime); ++ XbmcThreads::ThreadSleep(100); ++ } ++ XGrabKeyboard(m_dpy, m_glWindow, True, GrabModeAsync, GrabModeAsync, CurrentTime); ++ } ++ else ++ { ++ XUngrabKeyboard(m_dpy, CurrentTime); ++ XUngrabPointer(m_dpy, CurrentTime); ++ } ++} ++ + bool CWinSystemX11::Minimize() + { +- m_bWasFullScreenBeforeMinimize = g_graphicsContext.IsFullScreenRoot(); ++ m_bWasFullScreenBeforeMinimize = m_bFullScreen; + if (m_bWasFullScreenBeforeMinimize) ++ { ++ m_bIgnoreNextFocusMessage = true; + g_graphicsContext.ToggleFullScreenRoot(); ++ } ++ ++ XIconifyWindow(m_dpy, m_glWindow, m_nScreen); + +- SDL_WM_IconifyWindow(); + m_minimized = true; + return true; + } +@@ -462,13 +620,13 @@ + } + bool CWinSystemX11::Hide() + { +- XUnmapWindow(m_dpy, m_wmWindow); ++ XUnmapWindow(m_dpy, m_glWindow); + XSync(m_dpy, False); + return true; + } + bool CWinSystemX11::Show(bool raise) + { +- XMapWindow(m_dpy, m_wmWindow); ++ XMapWindow(m_dpy, m_glWindow); + XSync(m_dpy, False); + m_minimized = false; + return true; +@@ -476,7 +634,7 @@ + + void CWinSystemX11::CheckDisplayEvents() + { +-#if defined(HAS_XRANDR) ++#if defined(HAS_XRANDR) && defined(HAS_SDL_VIDEO_X11) + bool bGotEvent(false); + bool bTimeout(false); + XEvent Event; +@@ -499,13 +657,7 @@ + + if (bGotEvent || bTimeout) + { +- CLog::Log(LOGDEBUG, "%s - notify display reset event", __FUNCTION__); +- +- CSingleLock lock(m_resourceSection); +- +- // tell any shared resources +- for (vector::iterator i = m_resources.begin(); i != m_resources.end(); i++) +- (*i)->OnResetDevice(); ++ NotifyXRREvent(); + + // reset fail safe timer + m_dpyLostTime = 0; +@@ -513,6 +665,61 @@ + #endif + } + ++void CWinSystemX11::NotifyXRREvent() ++{ ++ CLog::Log(LOGDEBUG, "%s - notify display reset event", __FUNCTION__); ++ m_windowDirty = true; ++ ++ CSingleLock lock(g_graphicsContext); ++ ++ if (!g_xrandr.Query(true)) ++ { ++ CLog::Log(LOGERROR, "WinSystemX11::RefreshWindow - failed to query xrandr"); ++ return; ++ } ++ ++ // if external event update resolutions ++ if (!m_bIsInternalXrr) ++ { ++ UpdateResolutions(); ++ } ++ m_bIsInternalXrr = false; ++ ++ CStdString currentOutput = g_guiSettings.GetString("videoscreen.monitor"); ++ XOutput *out = g_xrandr.GetOutput(currentOutput); ++ XMode mode = g_xrandr.GetCurrentMode(currentOutput); ++ ++ if (out) ++ CLog::Log(LOGDEBUG, "%s - current output: %s, mode: %s, refresh: %.3f", __FUNCTION__ ++ , out->name.c_str(), mode.id.c_str(), mode.hz); ++ else ++ CLog::Log(LOGWARNING, "%s - output name not set", __FUNCTION__); ++ ++ RESOLUTION_INFO res; ++ unsigned int i; ++ bool found(false); ++ for (i = RES_DESKTOP; i < g_settings.m_ResInfo.size(); ++i) ++ { ++ if (g_settings.m_ResInfo[i].strId == mode.id) ++ { ++ found = true; ++ break; ++ } ++ } ++ ++ if (!found) ++ { ++ CLog::Log(LOGERROR, "CWinSystemX11::RefreshWindow - could not find resolution"); ++ i = RES_DESKTOP; ++ } ++ ++ if (g_graphicsContext.IsFullScreenRoot()) ++ g_graphicsContext.SetVideoResolution((RESOLUTION)i, true); ++ else ++ g_graphicsContext.SetVideoResolution(RES_WINDOW, true); ++ ++} ++ + void CWinSystemX11::OnLostDevice() + { + CLog::Log(LOGDEBUG, "%s - notify display change event", __FUNCTION__); +@@ -525,8 +732,12 @@ + (*i)->OnLostDevice(); + } + ++#if defined(HAS_SDL_VIDEO_X11) + // fail safe timer + m_dpyLostTime = CurrentHostCounter(); ++#else ++ CWinEvents::SetXRRFailSafeTimer(3000); ++#endif + } + + void CWinSystemX11::Register(IDispResource *resource) +@@ -558,4 +769,386 @@ + return m_minimized; + } + ++bool CWinSystemX11::SetWindow(int width, int height, bool fullscreen, const CStdString &output) ++{ ++ bool changeWindow = false; ++ bool changeSize = false; ++ bool mouseActive = false; ++ float mouseX, mouseY; ++ ++ if (m_glWindow && ((m_bFullScreen != fullscreen) || !m_currentOutput.Equals(output) || m_windowDirty)) ++ { ++ mouseActive = g_Mouse.IsActive(); ++ if (mouseActive) ++ { ++ Window root_return, child_return; ++ int root_x_return, root_y_return; ++ int win_x_return, win_y_return; ++ unsigned int mask_return; ++ bool isInWin = XQueryPointer(m_dpy, m_glWindow, &root_return, &child_return, ++ &root_x_return, &root_y_return, ++ &win_x_return, &win_y_return, ++ &mask_return); ++ if (isInWin) ++ { ++ mouseX = (float)win_x_return/m_nWidth; ++ mouseY = (float)win_y_return/m_nHeight; ++ g_Mouse.SetActive(false); ++ } ++ else ++ mouseActive = false; ++ } ++ OnLostDevice(); ++ DestroyWindow(); ++ m_windowDirty = true; ++ } ++ ++ // create main window ++ if (!m_glWindow) ++ { ++ EnableSystemScreenSaver(false); ++ ++ GLint att[] = ++ { ++ GLX_RGBA, ++ GLX_RED_SIZE, 8, ++ GLX_GREEN_SIZE, 8, ++ GLX_BLUE_SIZE, 8, ++ GLX_ALPHA_SIZE, 8, ++ GLX_DEPTH_SIZE, 24, ++ GLX_DOUBLEBUFFER, ++ None ++ }; ++ Colormap cmap; ++ XSetWindowAttributes swa; ++ XVisualInfo *vi; + int x0 = 0; + int y0 = 0; - - XOutput *out = g_xrandr.GetOutput(output); - if (!out) - out = g_xrandr.GetOutput(m_currentOutput); -- m_nScreen = out->screen; ++ ++ XOutput *out = g_xrandr.GetOutput(output); ++ if (!out) ++ out = g_xrandr.GetOutput(m_currentOutput); + if (out) + { + m_nScreen = out->screen; @@ -20844,274 +15150,655 @@ index b87e264..3cadd13 100644 + y0 = out->y; + } + - vi = glXChooseVisual(m_dpy, m_nScreen, att); - cmap = XCreateColormap(m_dpy, RootWindow(m_dpy, vi->screen), vi->visual, AllocNone); - -@@ -842,7 +853,7 @@ bool CWinSystemX11::SetWindow(int width, int height, bool fullscreen, const CStd - unsigned long mask = CWBackPixel | CWBorderPixel | CWColormap | CWOverrideRedirect | CWEventMask; - - m_glWindow = XCreateWindow(m_dpy, RootWindow(m_dpy, vi->screen), -- out->x, out->y, width, height, 0, vi->depth, ++ vi = glXChooseVisual(m_dpy, m_nScreen, att); ++ cmap = XCreateColormap(m_dpy, RootWindow(m_dpy, vi->screen), vi->visual, AllocNone); ++ ++ bool hasWM = HasWindowManager(); ++ ++ int def_vis = (vi->visual == DefaultVisual(m_dpy, vi->screen)); ++ swa.override_redirect = hasWM ? False : True; ++ swa.border_pixel = fullscreen ? 0 : 5; ++ swa.background_pixel = def_vis ? BlackPixel(m_dpy, vi->screen) : 0; ++ swa.colormap = cmap; ++ swa.background_pixel = def_vis ? BlackPixel(m_dpy, vi->screen) : 0; ++ swa.event_mask = FocusChangeMask | KeyPressMask | KeyReleaseMask | ++ ButtonPressMask | ButtonReleaseMask | PointerMotionMask | ++ PropertyChangeMask | StructureNotifyMask | KeymapStateMask | ++ EnterWindowMask | LeaveWindowMask | ExposureMask; ++ unsigned long mask = CWBackPixel | CWBorderPixel | CWColormap | CWOverrideRedirect | CWEventMask; ++ ++ m_glWindow = XCreateWindow(m_dpy, RootWindow(m_dpy, vi->screen), + x0, y0, width, height, 0, vi->depth, - InputOutput, vi->visual, - mask, &swa); - --- -1.7.10 - - -From 11696cc729a3a94d8aa5434b1e7948ae5e7b249d Mon Sep 17 00:00:00 2001 -From: xbmc -Date: Mon, 25 Feb 2013 08:47:10 +0100 -Subject: [PATCH 85/88] vdpau: release more resources on pre-cleanup - ---- - xbmc/cores/dvdplayer/DVDCodecs/Video/VDPAU.cpp | 72 ++++++++++++++++++++++-- - xbmc/cores/dvdplayer/DVDCodecs/Video/VDPAU.h | 2 + - 2 files changed, 68 insertions(+), 6 deletions(-) - -diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/VDPAU.cpp b/xbmc/cores/dvdplayer/DVDCodecs/Video/VDPAU.cpp -index 524efae..38ef375 100644 ---- a/xbmc/cores/dvdplayer/DVDCodecs/Video/VDPAU.cpp -+++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/VDPAU.cpp -@@ -1142,6 +1142,11 @@ void CMixer::Dispose() - m_dataPort.Purge(); - } - -+bool CMixer::IsActive() -+{ -+ return IsRunning(); ++ InputOutput, vi->visual, ++ mask, &swa); ++ ++ if (fullscreen && hasWM) ++ { ++ Atom fs = XInternAtom(m_dpy, "_NET_WM_STATE_FULLSCREEN", True); ++ XChangeProperty(m_dpy, m_glWindow, XInternAtom(m_dpy, "_NET_WM_STATE", True), XA_ATOM, 32, PropModeReplace, (unsigned char *) &fs, 1); ++ } ++ ++ // define invisible cursor ++ Pixmap bitmapNoData; ++ XColor black; ++ static char noData[] = { 0,0,0,0,0,0,0,0 }; ++ black.red = black.green = black.blue = 0; ++ ++ bitmapNoData = XCreateBitmapFromData(m_dpy, m_glWindow, noData, 8, 8); ++ m_invisibleCursor = XCreatePixmapCursor(m_dpy, bitmapNoData, bitmapNoData, ++ &black, &black, 0, 0); ++ XFreePixmap(m_dpy, bitmapNoData); ++ XDefineCursor(m_dpy,m_glWindow, m_invisibleCursor); ++ ++ //init X11 events ++ CWinEvents::Init(m_dpy, m_glWindow); ++ ++ changeWindow = true; ++ changeSize = true; ++ } ++ ++ if (!CWinEvents::HasStructureChanged() && ((width != m_nWidth) || (height != m_nHeight))) ++ { ++ changeSize = true; ++ } ++ ++ if (changeSize || changeWindow) ++ { ++ XResizeWindow(m_dpy, m_glWindow, width, height); ++ } ++ ++ if (changeWindow) ++ { ++ m_icon = None; ++ if (!fullscreen) ++ { ++ CreateIconPixmap(); ++ XWMHints *wm_hints; ++ XTextProperty windowName, iconName; ++ std::string titleString = "XBMC Media Center"; ++ char *title = (char*)titleString.c_str(); ++ ++ XStringListToTextProperty(&title, 1, &windowName); ++ XStringListToTextProperty(&title, 1, &iconName); ++ ++ wm_hints = XAllocWMHints(); ++ wm_hints->initial_state = NormalState; ++ wm_hints->icon_pixmap = m_icon; ++ wm_hints->flags = StateHint | IconPixmapHint; ++ ++ XSync(m_dpy,False); ++ XSetWMProperties(m_dpy, m_glWindow, &windowName, &iconName, ++ NULL, 0, NULL, wm_hints, ++ NULL); ++ XFree(wm_hints); ++ ++ // register interest in the delete window message ++ Atom wmDeleteMessage = XInternAtom(m_dpy, "WM_DELETE_WINDOW", False); ++ XSetWMProtocols(m_dpy, m_glWindow, &wmDeleteMessage, 1); ++ } ++ XMapRaised(m_dpy, m_glWindow); ++ XSync(m_dpy,TRUE); ++ ++ if (changeWindow && mouseActive) ++ { ++ XWarpPointer(m_dpy, None, m_glWindow, 0, 0, 0, 0, mouseX*width, mouseY*height); ++ } ++ ++ if (fullscreen) ++ { ++ int result = -1; ++ while (result != GrabSuccess && result != AlreadyGrabbed) ++ { ++ result = XGrabPointer(m_dpy, m_glWindow, True, ButtonPressMask, GrabModeAsync, GrabModeAsync, None, None, CurrentTime); ++ XbmcThreads::ThreadSleep(100); ++ } ++ XGrabKeyboard(m_dpy, m_glWindow, True, GrabModeAsync, GrabModeAsync, CurrentTime); ++ } ++ ++ CDirtyRegionList dr; ++ RefreshGlxContext(!m_currentOutput.Equals(output)); ++ XSync(m_dpy, FALSE); ++ g_graphicsContext.Clear(0); ++ g_graphicsContext.Flip(dr); ++ g_Windowing.ResetVSync(); ++ m_windowDirty = false; ++ ++ CSingleLock lock(m_resourceSection); ++ // tell any shared resources ++ for (vector::iterator i = m_resources.begin(); i != m_resources.end(); i++) ++ (*i)->OnResetDevice(); ++ } ++ ++ return true; +} + - void CMixer::OnStartup() - { - CLog::Log(LOGNOTICE, "CMixer::OnStartup: Output Thread created"); -@@ -2455,6 +2460,7 @@ void COutput::StateMachine(int signal, Protocol *port, Message *msg) - return; - case COutputControlProtocol::PRECLEANUP: - Flush(); -+ PreCleanup(); - msg->Reply(COutputControlProtocol::ACC); - return; - default: -@@ -2661,15 +2667,18 @@ bool COutput::Uninit() - - void COutput::Flush() - { -- Message *reply; -- if (m_mixer.m_controlPort.SendOutMessageSync(CMixerControlProtocol::FLUSH, -+ if (m_mixer.IsActive()) ++bool CWinSystemX11::CreateIconPixmap() ++{ ++ int depth; ++ XImage *img = NULL; ++ Visual *vis; ++ XWindowAttributes wndattribs; ++ XVisualInfo visInfo; ++ double rRatio; ++ double gRatio; ++ double bRatio; ++ int outIndex = 0; ++ int i,j; ++ int numBufBytes; ++ unsigned char *buf; ++ uint32_t *newBuf = 0; ++ size_t numNewBufBytes; ++ ++ // Get visual Info ++ XGetWindowAttributes(m_dpy, m_glWindow, &wndattribs); ++ visInfo.visualid = wndattribs.visual->visualid; ++ int nvisuals = 0; ++ XVisualInfo* visuals = XGetVisualInfo(m_dpy, VisualIDMask, &visInfo, &nvisuals); ++ if (nvisuals != 1) + { -+ Message *reply; -+ if (m_mixer.m_controlPort.SendOutMessageSync(CMixerControlProtocol::FLUSH, - &reply, - 2000)) -- { -- reply->Release(); ++ CLog::Log(LOGERROR, "CWinSystemX11::CreateIconPixmap - could not find visual"); ++ return false; ++ } ++ visInfo = visuals[0]; ++ XFree(visuals); ++ ++ depth = visInfo.depth; ++ vis = visInfo.visual; ++ ++ if (depth < 15) ++ { ++ CLog::Log(LOGERROR, "CWinSystemX11::CreateIconPixmap - no suitable depth"); ++ return false; ++ } ++ ++ rRatio = vis->red_mask / 255.0; ++ gRatio = vis->green_mask / 255.0; ++ bRatio = vis->blue_mask / 255.0; ++ ++ CBaseTexture *iconTexture = CBaseTexture::LoadFromFile("special://xbmc/media/icon.png"); ++ ++ if (!iconTexture) ++ return false; ++ ++ buf = iconTexture->GetPixels(); ++ ++ numBufBytes = iconTexture->GetWidth() * iconTexture->GetHeight() * 4; ++ int wid = iconTexture->GetWidth(); ++ int hi = iconTexture->GetHeight(); ++ ++ if (depth>=24) ++ numNewBufBytes = (4 * (iconTexture->GetWidth() * iconTexture->GetHeight())); ++ else ++ numNewBufBytes = (2 * (iconTexture->GetWidth() * iconTexture->GetHeight())); ++ ++ newBuf = (uint32_t*)malloc(numNewBufBytes); ++ if (!newBuf) ++ { ++ CLog::Log(LOGERROR, "CWinSystemX11::CreateIconPixmap - malloc failed"); ++ return false; ++ } ++ ++ for (i=0; iGetHeight();++i) ++ { ++ for (j=0; jGetWidth();++j) + { -+ reply->Release(); ++ unsigned int pos = i*iconTexture->GetPitch()+j*4; ++ unsigned int r, g, b; ++ r = (buf[pos+2] * rRatio); ++ g = (buf[pos+1] * gRatio); ++ b = (buf[pos+0] * bRatio); ++ r &= vis->red_mask; ++ g &= vis->green_mask; ++ b &= vis->blue_mask; ++ newBuf[outIndex] = r | g | b; ++ ++outIndex; ++ } ++ } ++ img = XCreateImage(m_dpy, vis, depth,ZPixmap, 0, (char *)newBuf, ++ iconTexture->GetWidth(), iconTexture->GetHeight(), ++ (depth>=24)?32:16, 0); ++ if (!img) ++ { ++ CLog::Log(LOGERROR, "CWinSystemX11::CreateIconPixmap - could not create image"); ++ free(newBuf); ++ return false; ++ } ++ if (!XInitImage(img)) ++ { ++ CLog::Log(LOGERROR, "CWinSystemX11::CreateIconPixmap - init image failed"); ++ XDestroyImage(img); ++ return false; ++ } ++ ++ // set byte order ++ union ++ { ++ char c[sizeof(short)]; ++ short s; ++ } order; ++ order.s = 1; ++ if ((1 == order.c[0])) ++ { ++ img->byte_order = LSBFirst; ++ } ++ else ++ { ++ img->byte_order = MSBFirst; ++ } ++ ++ // create icon pixmap from image ++ m_icon = XCreatePixmap(m_dpy, m_glWindow, img->width, img->height, depth); ++ GC gc = XCreateGC(m_dpy, m_glWindow, 0, NULL); ++ XPutImage(m_dpy, m_icon, gc, img, 0, 0, 0, 0, img->width, img->height); ++ XFreeGC(m_dpy, gc); ++ XDestroyImage(img); // this also frees newBuf ++ ++ delete iconTexture; ++ ++ return true; ++} ++ ++bool CWinSystemX11::HasWindowManager() ++{ ++ Window wm_check; ++ unsigned char *data; ++ int status, real_format; ++ Atom real_type, prop; ++ unsigned long items_read, items_left, i; ++ char req = 0; ++ ++ prop = XInternAtom(m_dpy, "_NET_SUPPORTING_WM_CHECK", True); ++ if (prop == None) ++ return false; ++ status = XGetWindowProperty(m_dpy, DefaultRootWindow(m_dpy), prop, ++ 0L, 1L, False, XA_WINDOW, &real_type, &real_format, ++ &items_read, &items_left, &data); ++ if(status != Success || ! items_read) ++ { ++ if(status == Success) ++ XFree(data); ++ return false; ++ } ++ ++ wm_check = ((Window*)data)[0]; ++ XFree(data); ++ ++ status = XGetWindowProperty(m_dpy, wm_check, prop, ++ 0L, 1L, False, XA_WINDOW, &real_type, &real_format, ++ &items_read, &items_left, &data); ++ ++ if(status != Success || !items_read) ++ { ++ if(status == Success) ++ XFree(data); ++ return false; ++ } ++ ++ if(wm_check != ((Window*)data)[0]) ++ { ++ XFree(data); ++ return false; ++ } ++ ++ XFree(data); ++ ++ prop = XInternAtom(m_dpy, "_NET_WM_NAME", True); ++ if (prop == None) ++ { ++ CLog::Log(LOGDEBUG,"Window Manager Name: "); ++ return true; ++ } ++ ++ status = XGetWindowProperty(m_dpy, wm_check, prop, ++ 0L, (~0L), False, AnyPropertyType, &real_type, &real_format, ++ &items_read, &items_left, &data); ++ ++ if(status == Success && items_read) ++ { ++ CLog::Log(LOGDEBUG,"Window Manager Name: %s", data); ++ } ++ else ++ CLog::Log(LOGDEBUG,"Window Manager Name: "); ++ ++ if(status == Success) ++ XFree(data); ++ ++ return true; ++} ++ + #endif +diff -Naur xbmc-12.0.4/xbmc/windowing/X11/WinSystemX11GL.cpp xbmc-12.0.4.patch/xbmc/windowing/X11/WinSystemX11GL.cpp +--- xbmc-12.0.4/xbmc/windowing/X11/WinSystemX11GL.cpp 2013-03-08 13:01:29.000000000 +0100 ++++ xbmc-12.0.4.patch/xbmc/windowing/X11/WinSystemX11GL.cpp 2013-03-10 13:00:12.314988227 +0100 +@@ -23,6 +23,7 @@ + + #include "WinSystemX11GL.h" + #include "utils/log.h" ++#include "Application.h" + + CWinSystemX11GL::CWinSystemX11GL() + { +@@ -203,7 +204,7 @@ + return false; + + m_glxext = " "; +- m_glxext += (const char*)glXQueryExtensionsString(m_dpy, DefaultScreen(m_dpy)); ++ m_glxext += (const char*)glXQueryExtensionsString(m_dpy, m_nScreen); + m_glxext += " "; + + CLog::Log(LOGDEBUG, "GLX_EXTENSIONS:%s", m_glxext.c_str()); +@@ -245,17 +246,25 @@ + + bool CWinSystemX11GL::ResizeWindow(int newWidth, int newHeight, int newLeft, int newTop) + { ++ m_newGlContext = false; + CWinSystemX11::ResizeWindow(newWidth, newHeight, newLeft, newTop); + CRenderSystemGL::ResetRenderSystem(newWidth, newHeight, false, 0); + ++ if (m_newGlContext) ++ g_application.ReloadSkin(); ++ + return true; + } + + bool CWinSystemX11GL::SetFullScreen(bool fullScreen, RESOLUTION_INFO& res, bool blankOtherDisplays) + { ++ m_newGlContext = false; + CWinSystemX11::SetFullScreen(fullScreen, res, blankOtherDisplays); + CRenderSystemGL::ResetRenderSystem(res.iWidth, res.iHeight, fullScreen, res.fRefreshRate); + ++ if (m_newGlContext) ++ g_application.ReloadSkin(); ++ + return true; + } + +diff -Naur xbmc-12.0.4/xbmc/windowing/X11/WinSystemX11.h xbmc-12.0.4.patch/xbmc/windowing/X11/WinSystemX11.h +--- xbmc-12.0.4/xbmc/windowing/X11/WinSystemX11.h 2013-03-08 13:01:29.000000000 +0100 ++++ xbmc-12.0.4.patch/xbmc/windowing/X11/WinSystemX11.h 2013-03-10 13:00:12.330988113 +0100 +@@ -47,11 +47,14 @@ + virtual bool SetFullScreen(bool fullScreen, RESOLUTION_INFO& res, bool blankOtherDisplays); + virtual void UpdateResolutions(); + virtual int GetNumScreens() { return 1; } ++ virtual int GetCurrentScreen() { return m_nScreen; } + virtual void ShowOSMouse(bool show); + virtual void ResetOSScreensaver(); + virtual bool EnableFrameLimiter(); ++ virtual void EnableSystemScreenSaver(bool bEnable); + + virtual void NotifyAppActiveChange(bool bActivated); ++ virtual void NotifyAppFocusChange(bool bGaining); + + virtual bool Minimize(); + virtual bool Restore() ; +@@ -59,31 +62,46 @@ + virtual bool Show(bool raise = true); + virtual void Register(IDispResource *resource); + virtual void Unregister(IDispResource *resource); ++ virtual bool HasCalibration(const RESOLUTION_INFO &resInfo); + + // Local to WinSystemX11 only + Display* GetDisplay() { return m_dpy; } + GLXWindow GetWindow() { return m_glWindow; } ++ GLXContext GetGlxContext() { return m_glContext; } ++ void NotifyXRREvent(); ++ void GetConnectedOutputs(std::vector *outputs); ++ bool IsCurrentOutput(CStdString output); ++ void NotifyMouseCoverage(bool covered); + + protected: +- bool RefreshGlxContext(); ++ bool RefreshGlxContext(bool force); + void CheckDisplayEvents(); + void OnLostDevice(); ++ bool SetWindow(int width, int height, bool fullscreen, const CStdString &output); + +- SDL_Surface* m_SDLSurface; ++ Window m_glWindow; + GLXContext m_glContext; +- GLXWindow m_glWindow; +- Window m_wmWindow; + Display* m_dpy; ++ Cursor m_invisibleCursor; ++ Pixmap m_icon; ++ bool m_bIsRotated; + bool m_bWasFullScreenBeforeMinimize; + bool m_minimized; ++ bool m_bIgnoreNextFocusMessage; + int m_RREventBase; + CCriticalSection m_resourceSection; + std::vector m_resources; + uint64_t m_dpyLostTime; ++ CStdString m_currentOutput; ++ bool m_windowDirty; ++ bool m_bIsInternalXrr; ++ bool m_newGlContext; + + private: + bool IsSuitableVisual(XVisualInfo *vInfo); + static int XErrorHandler(Display* dpy, XErrorEvent* error); ++ bool CreateIconPixmap(); ++ bool HasWindowManager(); + + CStopWatch m_screensaverReset; + }; +diff -Naur xbmc-12.0.4/xbmc/windowing/X11/XRandR.cpp xbmc-12.0.4.patch/xbmc/windowing/X11/XRandR.cpp +--- xbmc-12.0.4/xbmc/windowing/X11/XRandR.cpp 2013-03-08 13:01:29.000000000 +0100 ++++ xbmc-12.0.4.patch/xbmc/windowing/X11/XRandR.cpp 2013-03-10 13:00:12.330988113 +0100 +@@ -39,6 +39,7 @@ + CXRandR::CXRandR(bool query) + { + m_bInit = false; ++ m_numScreens = 1; + if (query) + Query(); + } +@@ -55,11 +56,23 @@ + return false; + + m_outputs.clear(); +- m_current.clear(); ++ // query all screens ++ // we are happy if at least one screen returns results ++ bool success = false; ++ for(unsigned int screennum=0; screennumValue(), "screen") != 0) ++ if (atoi(pRootElement->Attribute("id")) != screennum) + { + // TODO ERROR + return false; +@@ -92,12 +105,20 @@ + xoutput.name.TrimLeft(" \n\r\t"); + xoutput.name.TrimRight(" \n\r\t"); + xoutput.isConnected = (strcasecmp(output->Attribute("connected"), "true") == 0); ++ xoutput.screen = screennum; + xoutput.w = (output->Attribute("w") != NULL ? atoi(output->Attribute("w")) : 0); + xoutput.h = (output->Attribute("h") != NULL ? atoi(output->Attribute("h")) : 0); + xoutput.x = (output->Attribute("x") != NULL ? atoi(output->Attribute("x")) : 0); + xoutput.y = (output->Attribute("y") != NULL ? atoi(output->Attribute("y")) : 0); + xoutput.wmm = (output->Attribute("wmm") != NULL ? atoi(output->Attribute("wmm")) : 0); + xoutput.hmm = (output->Attribute("hmm") != NULL ? atoi(output->Attribute("hmm")) : 0); ++ if (output->Attribute("rotation") != NULL ++ && (strcasecmp(output->Attribute("rotation"), "left") == 0 || strcasecmp(output->Attribute("rotation"), "right") == 0)) ++ { ++ xoutput.isRotated = true; + } + else -+ CLog::Log(LOGERROR, "Coutput::%s - failed to flush mixer", __FUNCTION__); - } -- else -- CLog::Log(LOGERROR, "Coutput::%s - failed to flush mixer", __FUNCTION__); ++ xoutput.isRotated = false; - Message *msg; - while (m_mixer.m_dataPort.ReceiveInMessage(&msg)) -@@ -3008,6 +3017,57 @@ void COutput::ReleaseBufferPool() + if (!xoutput.isConnected) + continue; +@@ -116,7 +137,6 @@ + xoutput.modes.push_back(xmode); + if (xmode.isCurrent) + { +- m_current.push_back(xoutput); + hascurrent = true; + } + } +@@ -139,25 +159,6 @@ + Query(true); + } + +-void CXRandR::RestoreState() +-{ +- vector::iterator outiter; +- for (outiter=m_current.begin() ; outiter!=m_current.end() ; outiter++) +- { +- vector modes = (*outiter).modes; +- vector::iterator modeiter; +- for (modeiter=modes.begin() ; modeiter!=modes.end() ; modeiter++) +- { +- XMode mode = *modeiter; +- if (mode.isCurrent) +- { +- SetMode(*outiter, mode); +- return; +- } +- } +- } +-} +- + bool CXRandR::SetMode(XOutput output, XMode mode) + { + if ((output.name == m_currentOutput && mode.id == m_currentMode) || (output.name == "" && mode.id == "")) +@@ -245,7 +246,7 @@ + m_currentMode = modeFound.id; + char cmd[255]; + if (getenv("XBMC_BIN_HOME")) +- snprintf(cmd, sizeof(cmd), "%s/xbmc-xrandr --output %s --mode %s", getenv("XBMC_BIN_HOME"), outputFound.name.c_str(), modeFound.id.c_str()); ++ snprintf(cmd, sizeof(cmd), "%s/xbmc-xrandr --screen %d --output %s --mode %s", getenv("XBMC_BIN_HOME"), outputFound.screen, outputFound.name.c_str(), modeFound.id.c_str()); + else + return false; + CLog::Log(LOGINFO, "XRANDR: %s", cmd); +@@ -259,17 +260,6 @@ + return true; + } + +-XOutput CXRandR::GetCurrentOutput() +-{ +- Query(); +- for (unsigned int j = 0; j < m_outputs.size(); j++) +- { +- if(m_outputs[j].isConnected) +- return m_outputs[j]; +- } +- XOutput empty; +- return empty; +-} + XMode CXRandR::GetCurrentMode(CStdString outputName) + { + Query(); +@@ -343,6 +333,43 @@ } } -+void COutput::PreCleanup() ++void CXRandR::SetNumScreens(unsigned int num) +{ -+ -+ VdpStatus vdp_st; -+ -+ m_mixer.Dispose(); -+ -+ CSingleLock lock(m_bufferPool.renderPicSec); -+ for (unsigned int i = 0; i < m_bufferPool.outputSurfaces.size(); ++i) -+ { -+ if (m_bufferPool.outputSurfaces[i] == VDP_INVALID_HANDLE) -+ continue; -+ -+ // check if output surface is in use -+ bool used = false; -+ std::deque::iterator it; -+ for (it = m_bufferPool.usedRenderPics.begin(); it != m_bufferPool.usedRenderPics.end(); ++it) -+ { -+ if (((*it)->sourceIdx == m_bufferPool.outputSurfaces[i]) && (*it)->valid) -+ { -+ used = true; -+ break; -+ } -+ } -+ if (used) -+ continue; -+ -+#ifdef GL_NV_vdpau_interop -+ // unmap surface -+ std::map::iterator it_map; -+ it_map = m_bufferPool.glOutputSurfaceMap.find(m_bufferPool.outputSurfaces[i]); -+ if (it_map == m_bufferPool.glOutputSurfaceMap.end()) -+ { -+ CLog::Log(LOGERROR, "%s - could not find gl surface", __FUNCTION__); -+ continue; -+ } -+ glVDPAUUnregisterSurfaceNV(it_map->second.glVdpauSurface); -+ glDeleteTextures(1, it_map->second.texture); -+ m_bufferPool.glOutputSurfaceMap.erase(it_map); -+#endif -+ -+ vdp_st = m_config.vdpProcs.vdp_output_surface_destroy(m_bufferPool.outputSurfaces[i]); -+ CheckStatus(vdp_st, __LINE__); -+ -+ m_bufferPool.outputSurfaces[i] = VDP_INVALID_HANDLE; -+ -+ CLog::Log(LOGDEBUG, "VDPAU::PreCleanup - released output surface"); -+ } -+ ++ m_numScreens = num; ++ m_bInit = false; +} + - void COutput::InitMixer() - { - for (unsigned int i = 0; i < m_bufferPool.outputSurfaces.size(); ++i) -diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/VDPAU.h b/xbmc/cores/dvdplayer/DVDCodecs/Video/VDPAU.h -index 471ad68..e33b6f5 100644 ---- a/xbmc/cores/dvdplayer/DVDCodecs/Video/VDPAU.h -+++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/VDPAU.h -@@ -286,6 +286,7 @@ class CMixer : private CThread - virtual ~CMixer(); - void Start(); - void Dispose(); -+ bool IsActive(); - CMixerControlProtocol m_controlPort; - CMixerDataProtocol m_dataPort; - protected: -@@ -454,6 +455,7 @@ class COutput : private CThread - bool DestroyGlxContext(); - bool EnsureBufferPool(); - void ReleaseBufferPool(); -+ void PreCleanup(); - void InitMixer(); - bool GLInit(); - void GLMapSurfaces(); --- -1.7.10 - - -From 046ece78a7cb25c9d9feca0d907c4547943843c5 Mon Sep 17 00:00:00 2001 -From: xbmc -Date: Tue, 5 Mar 2013 17:01:53 +0100 -Subject: [PATCH 86/88] LinuxRendererGL: do not upscale if source equals dest - ---- - xbmc/cores/VideoRenderers/LinuxRendererGL.cpp | 8 ++++++++ - 1 file changed, 8 insertions(+) - -diff --git a/xbmc/cores/VideoRenderers/LinuxRendererGL.cpp b/xbmc/cores/VideoRenderers/LinuxRendererGL.cpp -index 0bb924b..b5b0838 100644 ---- a/xbmc/cores/VideoRenderers/LinuxRendererGL.cpp -+++ b/xbmc/cores/VideoRenderers/LinuxRendererGL.cpp -@@ -860,6 +860,14 @@ void CLinuxRendererGL::UpdateVideoFilter() - m_scalingMethod = VS_SCALINGMETHOD_LINEAR; - } - -+ // no need to scale if source equals dest -+ bool scale = ((float)m_sourceHeight != m_destRect.Height()) || -+ ((float)m_sourceWidth != m_destRect.Width()); -+ if(!scale) ++bool CXRandR::IsOutputConnected(CStdString name) ++{ ++ bool result = false; ++ Query(); ++ ++ for (unsigned int i = 0; i < m_outputs.size(); ++i) + { -+ m_scalingMethod = VS_SCALINGMETHOD_LINEAR; ++ if (m_outputs[i].name == name) ++ { ++ result = true; ++ break; ++ } + } ++ return result; ++} + - if (m_pVideoFilterShader) - { - m_pVideoFilterShader->Free(); --- -1.7.10 - - -From 1ac2908aa3fd49bdbfd7e271ddd3a8f6c552929c Mon Sep 17 00:00:00 2001 -From: xbmc -Date: Wed, 6 Mar 2013 07:35:10 +0100 -Subject: [PATCH 87/88] vdpau: set deinterlacing method to auto, if default - method not supported - ---- - xbmc/cores/dvdplayer/DVDCodecs/Video/VDPAU.cpp | 4 +++- - 1 file changed, 3 insertions(+), 1 deletion(-) - -diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/VDPAU.cpp b/xbmc/cores/dvdplayer/DVDCodecs/Video/VDPAU.cpp -index 38ef375..b69ae8c 100644 ---- a/xbmc/cores/dvdplayer/DVDCodecs/Video/VDPAU.cpp -+++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/VDPAU.cpp -@@ -2091,13 +2091,15 @@ void CMixer::InitCycle() - } - else - { -- CLog::Log(LOGERROR, "CMixer::%s - interlace method not supported", __FUNCTION__); -+ CLog::Log(LOGERROR, "CMixer::%s - interlace method: %d not supported, setting to AUTO", __FUNCTION__, method); - m_mixersteps = 1; - m_mixerfield = VDP_VIDEO_MIXER_PICTURE_STRUCTURE_FRAME; - m_mixerInput[1].DVDPic.format = RENDER_FMT_VDPAU; - m_mixerInput[1].DVDPic.iFlags &= ~(DVP_FLAG_TOP_FIELD_FIRST | - DVP_FLAG_REPEAT_TOP_FIELD | - DVP_FLAG_INTERLACED); ++XOutput* CXRandR::GetOutput(CStdString outputName) ++{ ++ XOutput *result = 0; ++ Query(); ++ for (unsigned int i = 0; i < m_outputs.size(); ++i) ++ { ++ if (m_outputs[i].name == outputName) ++ { ++ result = &m_outputs[i]; ++ break; ++ } ++ } ++ return result; ++} + -+ g_settings.m_currentVideoSettings.m_InterlaceMethod = VS_INTERLACEMETHOD_AUTO; + CXRandR g_xrandr; + + #endif // HAS_XRANDR +diff -Naur xbmc-12.0.4/xbmc/windowing/X11/XRandR.h xbmc-12.0.4.patch/xbmc/windowing/X11/XRandR.h +--- xbmc-12.0.4/xbmc/windowing/X11/XRandR.h 2013-03-08 13:01:29.000000000 +0100 ++++ xbmc-12.0.4.patch/xbmc/windowing/X11/XRandR.h 2013-03-10 13:00:12.311988249 +0100 +@@ -79,6 +79,7 @@ } - } - else --- -1.7.10 - - -From 1f1e576daead67677f3cacbb592f47129ad6f5f5 Mon Sep 17 00:00:00 2001 -From: xbmc -Date: Sat, 9 Mar 2013 14:04:15 +0100 -Subject: [PATCH 88/88] buffering: do not drop in RenderManager - ---- - xbmc/cores/VideoRenderers/RenderManager.cpp | 24 ++++++++++++------------ - 1 file changed, 12 insertions(+), 12 deletions(-) - -diff --git a/xbmc/cores/VideoRenderers/RenderManager.cpp b/xbmc/cores/VideoRenderers/RenderManager.cpp -index c99a555..bc764da 100644 ---- a/xbmc/cores/VideoRenderers/RenderManager.cpp -+++ b/xbmc/cores/VideoRenderers/RenderManager.cpp -@@ -1067,18 +1067,18 @@ void CXBMCRenderManager::PrepareNextRender() + CStdString name; + bool isConnected; ++ int screen; + int w; + int h; + int x; +@@ -86,6 +87,7 @@ + int wmm; + int hmm; + std::vector modes; ++ bool isRotated; + }; - // look ahead in the queue - // if the next frame is already late, skip the one we are about to render -- while (idx != m_iOutputRenderBuffer) -- { -- int idx_next = (idx + 1) % m_iNumRenderBuffers; -- if (m_renderBuffers[idx_next].timestamp <= clocktime) -- { -- FlipRenderBuffer(); -- idx = GetNextRenderBufferIndex(); -- CLog::Log(LOGDEBUG,"%s - skip frame at render buffer index: %d", __FUNCTION__, idx); -- } -- else -- break; -- } -+// while (idx != m_iOutputRenderBuffer) -+// { -+// int idx_next = (idx + 1) % m_iNumRenderBuffers; -+// if (m_renderBuffers[idx_next].timestamp <= clocktime) -+// { -+// FlipRenderBuffer(); -+// idx = GetNextRenderBufferIndex(); -+// CLog::Log(LOGDEBUG,"%s - skip frame at render buffer index: %d", __FUNCTION__, idx); -+// } -+// else -+// break; -+// } + class CXRandR +@@ -93,13 +95,15 @@ + public: + CXRandR(bool query=false); + bool Query(bool force=false); ++ bool Query(bool force, int screennum); + std::vector GetModes(void); +- XOutput GetCurrentOutput(); + XMode GetCurrentMode(CStdString outputName); ++ XOutput *GetOutput(CStdString outputName); + bool SetMode(XOutput output, XMode mode); + void LoadCustomModeLinesToAllOutputs(void); + void SaveState(); +- void RestoreState(); ++ void SetNumScreens(unsigned int num); ++ bool IsOutputConnected(CStdString name); + //bool Has1080i(); + //bool Has1080p(); + //bool Has720p(); +@@ -107,10 +111,10 @@ - double presenttime = m_renderBuffers[idx].timestamp; + private: + bool m_bInit; +- std::vector m_current; + std::vector m_outputs; + CStdString m_currentOutput; + CStdString m_currentMode; ++ unsigned int m_numScreens; + }; --- -1.7.10 - + extern CXRandR g_xrandr;