From eaff0f0bc5ab7db045c77571c4db80f86a06a132 Mon Sep 17 00:00:00 2001 From: fritsch Date: Mon, 26 Jan 2015 18:35:07 +0100 Subject: [PATCH] WT: Backport fullscreen dirty region fixes PR6090 --- .../kodi/kodi-8000-backportPR6090.patch | 1004 +++++++++++++++++ 1 file changed, 1004 insertions(+) create mode 100644 projects/WeTek_Play/patches/kodi/kodi-8000-backportPR6090.patch diff --git a/projects/WeTek_Play/patches/kodi/kodi-8000-backportPR6090.patch b/projects/WeTek_Play/patches/kodi/kodi-8000-backportPR6090.patch new file mode 100644 index 0000000000..a51682ecda --- /dev/null +++ b/projects/WeTek_Play/patches/kodi/kodi-8000-backportPR6090.patch @@ -0,0 +1,1004 @@ +From ced0caecb0c5d4862290a1fbbaec0665ab6847a7 Mon Sep 17 00:00:00 2001 +From: Rainer Hochecker +Date: Fri, 2 Jan 2015 10:02:09 +0100 +Subject: [PATCH 1/6] renderer: drop old tempfix firstflippage, did not work + anyway because RendererHandlesPresent returned always true + +--- + xbmc/Application.cpp | 2 +- + xbmc/cores/VideoRenderers/RenderManager.cpp | 9 --------- + xbmc/cores/VideoRenderers/RenderManager.h | 5 ----- + xbmc/guilib/GUIVideoControl.cpp | 3 +-- + 4 files changed, 2 insertions(+), 17 deletions(-) + +diff --git a/xbmc/Application.cpp b/xbmc/Application.cpp +index 4a5619a..aa7aed0 100644 +--- a/xbmc/Application.cpp ++++ b/xbmc/Application.cpp +@@ -2222,7 +2222,7 @@ void CApplication::Render() + bool extPlayerActive = m_pPlayer->GetCurrentPlayer() == EPC_EXTPLAYER && m_pPlayer->IsPlaying() && !m_AppFocused; + + m_bPresentFrame = false; +- if (!extPlayerActive && g_graphicsContext.IsFullScreenVideo() && !m_pPlayer->IsPausedPlayback() && g_renderManager.RendererHandlesPresent()) ++ if (!extPlayerActive && g_graphicsContext.IsFullScreenVideo() && !m_pPlayer->IsPausedPlayback()) + { + m_bPresentFrame = g_renderManager.FrameWait(100); + hasRendered = true; +diff --git a/xbmc/cores/VideoRenderers/RenderManager.cpp b/xbmc/cores/VideoRenderers/RenderManager.cpp +index b31f3c9..ab894ba 100644 +--- a/xbmc/cores/VideoRenderers/RenderManager.cpp ++++ b/xbmc/cores/VideoRenderers/RenderManager.cpp +@@ -293,19 +293,12 @@ bool CXBMCRenderManager::Configure(unsigned int width, unsigned int height, unsi + m_sleeptime = 1.0; + m_presentevent.notifyAll(); + +- m_firstFlipPage = false; // tempfix +- + CLog::Log(LOGDEBUG, "CXBMCRenderManager::Configure - %d", m_QueueSize); + } + + return result; + } + +-bool CXBMCRenderManager::RendererHandlesPresent() const +-{ +- return IsConfigured() && (m_firstFlipPage || m_format != RENDER_FMT_BYPASS); +-} +- + bool CXBMCRenderManager::IsConfigured() const + { + if (!m_pRenderer) +@@ -661,8 +654,6 @@ void CXBMCRenderManager::FlipPage(volatile bool& bStop, double timestamp /* = 0L + + if(!m_pRenderer) return; + +- m_firstFlipPage = true; // tempfix +- + EPRESENTMETHOD presentmethod; + + EDEINTERLACEMODE deinterlacemode = CMediaSettings::Get().GetCurrentVideoSettings().m_DeinterlaceMode; +diff --git a/xbmc/cores/VideoRenderers/RenderManager.h b/xbmc/cores/VideoRenderers/RenderManager.h +index d3c2f1d..1086066 100644 +--- a/xbmc/cores/VideoRenderers/RenderManager.h ++++ b/xbmc/cores/VideoRenderers/RenderManager.h +@@ -143,8 +143,6 @@ public: + + void UpdateResolution(); + +- bool RendererHandlesPresent() const; +- + #ifdef HAS_GL + CLinuxRendererGL *m_pRenderer; + #elif defined(HAS_MMAL) +@@ -267,9 +265,6 @@ protected: + //set to true when adding something to m_captures, set to false when m_captures is made empty + //std::list::empty() isn't thread safe, using an extra bool will save a lock per render when no captures are requested + bool m_hasCaptures; +- +- // temporary fix for RendererHandlesPresent after #2811 +- bool m_firstFlipPage; + }; + + extern CXBMCRenderManager g_renderManager; +diff --git a/xbmc/guilib/GUIVideoControl.cpp b/xbmc/guilib/GUIVideoControl.cpp +index 22d0fc8..c47a6d5 100644 +--- a/xbmc/guilib/GUIVideoControl.cpp ++++ b/xbmc/guilib/GUIVideoControl.cpp +@@ -43,8 +43,7 @@ CGUIVideoControl::~CGUIVideoControl(void) + void CGUIVideoControl::Process(unsigned int currentTime, CDirtyRegionList &dirtyregions) + { + // TODO Proper processing which marks when its actually changed. Just mark always for now. +- if (g_renderManager.RendererHandlesPresent()) +- MarkDirtyRegion(); ++ MarkDirtyRegion(); + + CGUIControl::Process(currentTime, dirtyregions); + } +-- +1.9.1 + + +From 6d4517a48e8ef757d6f7ae15067858a2bcdf782d Mon Sep 17 00:00:00 2001 +From: smallint +Date: Fri, 2 Jan 2015 15:35:33 +0000 +Subject: [PATCH 2/6] Set dirty flag in teletext dialog if required + +--- + xbmc/video/dialogs/GUIDialogTeletext.cpp | 19 +++++++++++++++++++ + xbmc/video/dialogs/GUIDialogTeletext.h | 1 + + 2 files changed, 20 insertions(+) + +diff --git a/xbmc/video/dialogs/GUIDialogTeletext.cpp b/xbmc/video/dialogs/GUIDialogTeletext.cpp +index c552ae6..9be4548 100644 +--- a/xbmc/video/dialogs/GUIDialogTeletext.cpp ++++ b/xbmc/video/dialogs/GUIDialogTeletext.cpp +@@ -46,7 +46,10 @@ CGUIDialogTeletext::~CGUIDialogTeletext() + bool CGUIDialogTeletext::OnAction(const CAction& action) + { + if (m_TextDecoder.HandleAction(action)) ++ { ++ MarkDirtyRegion(); + return true; ++ } + + return CGUIDialog::OnAction(action); + } +@@ -54,6 +57,7 @@ bool CGUIDialogTeletext::OnAction(const CAction& action) + bool CGUIDialogTeletext::OnBack(int actionID) + { + m_bClose = true; ++ MarkDirtyRegion(); + return true; + } + +@@ -79,6 +83,12 @@ bool CGUIDialogTeletext::OnMessage(CGUIMessage& message) + return CGUIDialog::OnMessage(message); + } + ++void CGUIDialogTeletext::Process(unsigned int currentTime, CDirtyRegionList &dirtyregions) ++{ ++ CGUIDialog::Process(currentTime, dirtyregions); ++ m_renderRegion = m_vertCoords; ++} ++ + void CGUIDialogTeletext::Render() + { + // Do not render if we have no texture +@@ -93,12 +103,18 @@ void CGUIDialogTeletext::Render() + if (!m_bClose) + { + if (teletextFadeAmount < 100) ++ { + teletextFadeAmount = std::min(100, teletextFadeAmount + 5); ++ MarkDirtyRegion(); ++ } + } + else + { + if (teletextFadeAmount > 0) ++ { + teletextFadeAmount = std::max(0, teletextFadeAmount - 10); ++ MarkDirtyRegion(); ++ } + + if (teletextFadeAmount == 0) + Close(); +@@ -109,6 +125,7 @@ void CGUIDialogTeletext::Render() + { + m_pTxtTexture->Update(m_TextDecoder.GetWidth(), m_TextDecoder.GetHeight(), m_TextDecoder.GetWidth()*4, XB_FMT_A8R8G8B8, textureBuffer, false); + m_TextDecoder.RenderingDone(); ++ MarkDirtyRegion(); + } + + color_t color = ((color_t)(teletextFadeAmount * 2.55f) & 0xff) << 24 | 0xFFFFFF; +@@ -184,4 +201,6 @@ void CGUIDialogTeletext::SetCoordinates() + top, + right, + bottom); ++ ++ MarkDirtyRegion(); + } +diff --git a/xbmc/video/dialogs/GUIDialogTeletext.h b/xbmc/video/dialogs/GUIDialogTeletext.h +index 51aced5..e8e11f8 100644 +--- a/xbmc/video/dialogs/GUIDialogTeletext.h ++++ b/xbmc/video/dialogs/GUIDialogTeletext.h +@@ -32,6 +32,7 @@ public: + virtual bool OnMessage(CGUIMessage& message); + virtual bool OnAction(const CAction& action); + virtual bool OnBack(int actionID); ++ virtual void Process(unsigned int currentTime, CDirtyRegionList &dirtyregions); + virtual void Render(); + virtual void OnInitWindow(); + virtual void OnDeinitWindow(int nextWindowID); +-- +1.9.1 + + +From c374f149e72e7786644c49aa096a7c963c6eb254 Mon Sep 17 00:00:00 2001 +From: smallint +Date: Sat, 16 Aug 2014 17:29:15 +0200 +Subject: [PATCH 3/6] renderer: improve rendering to gui and separate video + layer + +--- + xbmc/Application.cpp | 10 +--- + xbmc/cores/VideoRenderers/BaseRenderer.h | 1 + + xbmc/cores/VideoRenderers/LinuxRendererGLES.cpp | 52 +++++++++++++-------- + xbmc/cores/VideoRenderers/LinuxRendererGLES.h | 2 + + xbmc/cores/VideoRenderers/MMALRenderer.cpp | 15 ------ + xbmc/cores/VideoRenderers/MMALRenderer.h | 1 + + xbmc/cores/VideoRenderers/OverlayRenderer.cpp | 18 +++++++ + xbmc/cores/VideoRenderers/OverlayRenderer.h | 1 + + xbmc/cores/VideoRenderers/RenderManager.cpp | 62 ++++++++++++++++++++----- + xbmc/cores/VideoRenderers/RenderManager.h | 5 +- + xbmc/guilib/GUIControl.h | 3 ++ + xbmc/guilib/GUIControlGroup.cpp | 7 +++ + xbmc/guilib/GUIControlGroup.h | 1 + + xbmc/guilib/GUIVideoControl.cpp | 31 ++++++++++++- + xbmc/guilib/GUIVideoControl.h | 1 + + xbmc/guilib/GUIWindowManager.cpp | 22 ++++++++- + xbmc/guilib/GUIWindowManager.h | 1 + + xbmc/video/windows/GUIWindowFullScreen.cpp | 31 ++++++++++++- + xbmc/video/windows/GUIWindowFullScreen.h | 2 + + 19 files changed, 204 insertions(+), 62 deletions(-) + +diff --git a/xbmc/Application.cpp b/xbmc/Application.cpp +index aa7aed0..3a222d4 100644 +--- a/xbmc/Application.cpp ++++ b/xbmc/Application.cpp +@@ -2170,9 +2170,6 @@ bool CApplication::RenderNoPresent() + // dont show GUI when playing full screen video + if (g_graphicsContext.IsFullScreenVideo()) + { +- g_graphicsContext.SetRenderingResolution(g_graphicsContext.GetVideoResolution(), false); +- g_renderManager.Render(true, 0, 255); +- + // close window overlays + CGUIDialog *overlay = (CGUIDialog *)g_windowManager.GetWindow(WINDOW_DIALOG_VIDEO_OVERLAY); + if (overlay) overlay->Close(true); +@@ -2225,7 +2222,6 @@ void CApplication::Render() + if (!extPlayerActive && g_graphicsContext.IsFullScreenVideo() && !m_pPlayer->IsPausedPlayback()) + { + m_bPresentFrame = g_renderManager.FrameWait(100); +- hasRendered = true; + } + else + { +@@ -2268,8 +2264,6 @@ void CApplication::Render() + if(!g_Windowing.BeginRender()) + return; + +- g_renderManager.FrameMove(); +- + CDirtyRegionList dirtyRegions = g_windowManager.GetDirty(); + if(g_graphicsContext.GetStereoMode()) + { +@@ -2291,8 +2285,6 @@ void CApplication::Render() + hasRendered = true; + } + +- g_renderManager.FrameFinish(); +- + g_Windowing.EndRender(); + + // execute post rendering actions (finalize window closing) +@@ -2317,7 +2309,7 @@ void CApplication::Render() + flip = true; + + //fps limiter, make sure each frame lasts at least singleFrameTime milliseconds +- if (limitFrames || !flip) ++ if (limitFrames || !(flip || m_bPresentFrame)) + { + if (!limitFrames) + singleFrameTime = 40; //if not flipping, loop at 25 fps +diff --git a/xbmc/cores/VideoRenderers/BaseRenderer.h b/xbmc/cores/VideoRenderers/BaseRenderer.h +index 850aa6f..8988e35 100644 +--- a/xbmc/cores/VideoRenderers/BaseRenderer.h ++++ b/xbmc/cores/VideoRenderers/BaseRenderer.h +@@ -94,6 +94,7 @@ public: + virtual void SetBufferSize(int numBuffers) { } + virtual void ReleaseBuffer(int idx) { } + virtual bool NeedBufferForRef(int idx) { return false; } ++ virtual bool IsGuiLayer() { return true; } + + virtual bool Supports(ERENDERFEATURE feature) { return false; } + +diff --git a/xbmc/cores/VideoRenderers/LinuxRendererGLES.cpp b/xbmc/cores/VideoRenderers/LinuxRendererGLES.cpp +index 81fe19b..a765461 100644 +--- a/xbmc/cores/VideoRenderers/LinuxRendererGLES.cpp ++++ b/xbmc/cores/VideoRenderers/LinuxRendererGLES.cpp +@@ -526,32 +526,16 @@ void CLinuxRendererGLES::Update() + + void CLinuxRendererGLES::RenderUpdate(bool clear, DWORD flags, DWORD alpha) + { +- if (!m_bConfigured) return; ++ if (!m_bConfigured) ++ return; + + // if its first pass, just init textures and return + if (ValidateRenderTarget()) + return; + +- if (m_renderMethod & RENDER_BYPASS) ++ if (!IsGuiLayer()) + { +- ManageDisplay(); +- // 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) +- (*m_RenderUpdateCallBackFn)(m_RenderUpdateCallBackCtx, m_sourceRect, m_destRect); +- +- CRect old = g_graphicsContext.GetScissors(); +- +- g_graphicsContext.BeginPaint(); +- g_graphicsContext.SetScissors(m_destRect); +- +- glEnable(GL_BLEND); +- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); +- glClearColor(0, 0, 0, 0); +- glClear(GL_COLOR_BUFFER_BIT); +- +- g_graphicsContext.SetScissors(old); +- g_graphicsContext.EndPaint(); ++ RenderUpdateVideo(clear, flags, alpha); + return; + } + +@@ -606,6 +590,26 @@ void CLinuxRendererGLES::RenderUpdate(bool clear, DWORD flags, DWORD alpha) + g_graphicsContext.EndPaint(); + } + ++void CLinuxRendererGLES::RenderUpdateVideo(bool clear, DWORD flags, DWORD alpha) ++{ ++ if (!m_bConfigured) ++ return; ++ ++ if (IsGuiLayer()) ++ return; ++ ++ if (m_renderMethod & RENDER_BYPASS) ++ { ++ ManageDisplay(); ++ // 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) ++ (*m_RenderUpdateCallBackFn)(m_RenderUpdateCallBackCtx, m_sourceRect, m_destRect); ++ ++ return; ++ } ++} ++ + void CLinuxRendererGLES::FlipPage(int source) + { + if( source >= 0 && source < m_NumYV12Buffers ) +@@ -3055,5 +3059,13 @@ void CLinuxRendererGLES::AddProcessor(CDVDVideoCodecIMXBuffer *buffer, int index + } + #endif + ++bool CLinuxRendererGLES::IsGuiLayer() ++{ ++ if (m_format == RENDER_FMT_BYPASS) ++ return false; ++ else ++ return true; ++} ++ + #endif + +diff --git a/xbmc/cores/VideoRenderers/LinuxRendererGLES.h b/xbmc/cores/VideoRenderers/LinuxRendererGLES.h +index d8bf35d..b865033 100644 +--- a/xbmc/cores/VideoRenderers/LinuxRendererGLES.h ++++ b/xbmc/cores/VideoRenderers/LinuxRendererGLES.h +@@ -144,6 +144,7 @@ public: + virtual void SetBufferSize(int numBuffers) { m_NumYV12Buffers = numBuffers; } + virtual unsigned int GetMaxBufferSize() { return NUM_BUFFERS; } + virtual unsigned int GetOptimalBufferSize(); ++ virtual bool IsGuiLayer(); + + virtual void RenderUpdate(bool clear, DWORD flags = 0, DWORD alpha = 255); + +@@ -177,6 +178,7 @@ public: + + protected: + virtual void Render(DWORD flags, int index); ++ void RenderUpdateVideo(bool clear, DWORD flags = 0, DWORD alpha = 255); + + int NextYV12Texture(); + virtual bool ValidateRenderTarget(); +diff --git a/xbmc/cores/VideoRenderers/MMALRenderer.cpp b/xbmc/cores/VideoRenderers/MMALRenderer.cpp +index 03a05de..69ff30a 100644 +--- a/xbmc/cores/VideoRenderers/MMALRenderer.cpp ++++ b/xbmc/cores/VideoRenderers/MMALRenderer.cpp +@@ -347,21 +347,6 @@ void CMMALRenderer::RenderUpdate(bool clear, DWORD flags, DWORD alpha) + // for sizing video playback on a layer other than the gles layer. + if (m_RenderUpdateCallBackFn) + (*m_RenderUpdateCallBackFn)(m_RenderUpdateCallBackCtx, m_sourceRect, m_destRect); +- +- SetVideoRect(m_sourceRect, m_destRect); +- +- CRect old = g_graphicsContext.GetScissors(); +- +- g_graphicsContext.BeginPaint(); +- g_graphicsContext.SetScissors(m_destRect); +- +- glEnable(GL_BLEND); +- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); +- glClearColor(0, 0, 0, 0); +- glClear(GL_COLOR_BUFFER_BIT); +- +- g_graphicsContext.SetScissors(old); +- g_graphicsContext.EndPaint(); + } + + void CMMALRenderer::FlipPage(int source) +diff --git a/xbmc/cores/VideoRenderers/MMALRenderer.h b/xbmc/cores/VideoRenderers/MMALRenderer.h +index 8ca0b94..62d513e 100644 +--- a/xbmc/cores/VideoRenderers/MMALRenderer.h ++++ b/xbmc/cores/VideoRenderers/MMALRenderer.h +@@ -90,6 +90,7 @@ public: + virtual unsigned int GetMaxBufferSize() { return NUM_BUFFERS; } + virtual unsigned int GetOptimalBufferSize() { return NUM_BUFFERS; } + virtual void SetVideoRect(const CRect& SrcRect, const CRect& DestRect); ++ virtual bool IsGuiLayer() { return false; } + + void vout_input_port_cb(MMAL_PORT_T *port, MMAL_BUFFER_HEADER_T *buffer); + protected: +diff --git a/xbmc/cores/VideoRenderers/OverlayRenderer.cpp b/xbmc/cores/VideoRenderers/OverlayRenderer.cpp +index ea07d9f..e8c4bec 100644 +--- a/xbmc/cores/VideoRenderers/OverlayRenderer.cpp ++++ b/xbmc/cores/VideoRenderers/OverlayRenderer.cpp +@@ -306,6 +306,24 @@ void CRenderer::Render(COverlay* o, float adjust_height) + o->Render(state); + } + ++bool CRenderer::HasOverlay(int idx) ++{ ++ bool hasOverlay = false; ++ ++ CSingleLock lock(m_section); ++ ++ SElementV& list = m_buffers[idx]; ++ for(SElementV::iterator it = list.begin(); it != list.end(); ++it) ++ { ++ if (it->overlay || it->overlay_dvd) ++ { ++ hasOverlay = true; ++ break; ++ } ++ } ++ return hasOverlay; ++} ++ + COverlay* CRenderer::Convert(CDVDOverlaySSA* o, double pts) + { + CRect src, dst; +diff --git a/xbmc/cores/VideoRenderers/OverlayRenderer.h b/xbmc/cores/VideoRenderers/OverlayRenderer.h +index 9b8e9da..ca02644 100644 +--- a/xbmc/cores/VideoRenderers/OverlayRenderer.h ++++ b/xbmc/cores/VideoRenderers/OverlayRenderer.h +@@ -100,6 +100,7 @@ namespace OVERLAY { + void Render(int idx); + void Flush(); + void Release(int idx); ++ bool HasOverlay(int idx); + + protected: + +diff --git a/xbmc/cores/VideoRenderers/RenderManager.cpp b/xbmc/cores/VideoRenderers/RenderManager.cpp +index ab894ba..63bbdcc 100644 +--- a/xbmc/cores/VideoRenderers/RenderManager.cpp ++++ b/xbmc/cores/VideoRenderers/RenderManager.cpp +@@ -120,6 +120,7 @@ CXBMCRenderManager::CXBMCRenderManager() + m_QueueSize = 2; + m_QueueSkip = 0; + m_format = RENDER_FMT_NONE; ++ m_renderedOverlay = false; + } + + CXBMCRenderManager::~CXBMCRenderManager() +@@ -233,7 +234,7 @@ bool CXBMCRenderManager::Configure(unsigned int width, unsigned int height, unsi + + /* make sure any queued frame was fully presented */ + XbmcThreads::EndTime endtime(5000); +- while(m_presentstep != PRESENT_IDLE) ++ while(m_presentstep != PRESENT_IDLE && m_presentstep != PRESENT_READY) + { + if(endtime.IsTimePast()) + { +@@ -292,6 +293,7 @@ bool CXBMCRenderManager::Configure(unsigned int width, unsigned int height, unsi + m_presentpts = DVD_NOPTS_VALUE; + m_sleeptime = 1.0; + m_presentevent.notifyAll(); ++ m_renderedOverlay = false; + + CLog::Log(LOGDEBUG, "CXBMCRenderManager::Configure - %d", m_QueueSize); + } +@@ -766,22 +768,58 @@ void CXBMCRenderManager::RegisterRenderFeaturesCallBack(const void *ctx, RenderF + m_pRenderer->RegisterRenderFeaturesCallBack(ctx, fn); + } + +-void CXBMCRenderManager::Render(bool clear, DWORD flags, DWORD alpha) ++void CXBMCRenderManager::Render(bool clear, DWORD flags, DWORD alpha, bool gui) + { + CSharedLock lock(m_sharedSection); + +- SPresent& m = m_Queue[m_presentsource]; ++ if (!gui && m_pRenderer->IsGuiLayer()) ++ return; + +- if( m.presentmethod == PRESENT_METHOD_BOB ) +- PresentFields(clear, flags, alpha); +- else if( m.presentmethod == PRESENT_METHOD_WEAVE ) +- PresentFields(clear, flags | RENDER_FLAG_WEAVE, alpha); +- else if( m.presentmethod == PRESENT_METHOD_BLEND ) +- PresentBlend(clear, flags, alpha); +- else +- PresentSingle(clear, flags, alpha); ++ if (!gui || m_pRenderer->IsGuiLayer()) ++ { ++ SPresent& m = m_Queue[m_presentsource]; ++ ++ if( m.presentmethod == PRESENT_METHOD_BOB ) ++ PresentFields(clear, flags, alpha); ++ else if( m.presentmethod == PRESENT_METHOD_WEAVE ) ++ PresentFields(clear, flags | RENDER_FLAG_WEAVE, alpha); ++ else if( m.presentmethod == PRESENT_METHOD_BLEND ) ++ PresentBlend(clear, flags, alpha); ++ else ++ PresentSingle(clear, flags, alpha); ++ } ++ ++ if (gui) ++ { ++ m_renderedOverlay = m_overlays.HasOverlay(m_presentsource); ++ m_overlays.Render(m_presentsource); ++ } ++} ++ ++bool CXBMCRenderManager::IsGuiLayer() ++{ ++ { CSingleLock lock(m_presentlock); ++ ++ if (!m_pRenderer) ++ return false; ++ ++ if (m_pRenderer->IsGuiLayer() || m_renderedOverlay || m_overlays.HasOverlay(m_presentsource)) ++ return true; ++ } ++ return false; ++} ++ ++bool CXBMCRenderManager::IsVideoLayer() ++{ ++ { CSingleLock lock(m_presentlock); + +- m_overlays.Render(m_presentsource); ++ if (!m_pRenderer) ++ return false; ++ ++ if (!m_pRenderer->IsGuiLayer()) ++ return true; ++ } ++ return false; + } + + /* simple present method */ +diff --git a/xbmc/cores/VideoRenderers/RenderManager.h b/xbmc/cores/VideoRenderers/RenderManager.h +index 1086066..7280423 100644 +--- a/xbmc/cores/VideoRenderers/RenderManager.h ++++ b/xbmc/cores/VideoRenderers/RenderManager.h +@@ -60,7 +60,9 @@ public: + void FrameMove(); + void FrameFinish(); + bool FrameWait(int ms); +- void Render(bool clear, DWORD flags = 0, DWORD alpha = 255); ++ void Render(bool clear, DWORD flags = 0, DWORD alpha = 255, bool gui = true); ++ bool IsGuiLayer(); ++ bool IsVideoLayer(); + void SetupScreenshot(); + + CRenderCapture* AllocRenderCapture(); +@@ -257,6 +259,7 @@ protected: + + + OVERLAY::CRenderer m_overlays; ++ bool m_renderedOverlay; + + void RenderCapture(CRenderCapture* capture); + void RemoveCapture(CRenderCapture* capture); +diff --git a/xbmc/guilib/GUIControl.h b/xbmc/guilib/GUIControl.h +index b303ccc..6e0b92e 100644 +--- a/xbmc/guilib/GUIControl.h ++++ b/xbmc/guilib/GUIControl.h +@@ -83,6 +83,9 @@ public: + virtual void Process(unsigned int currentTime, CDirtyRegionList &dirtyregions); + virtual void DoRender(); + virtual void Render() {}; ++ // Called after the actual rendering is completed to trigger additional ++ // non GUI rendering operations ++ virtual void RenderEx() {}; + + /*! \brief Returns whether or not we have processed */ + bool HasProcessed() const { return m_hasProcessed; }; +diff --git a/xbmc/guilib/GUIControlGroup.cpp b/xbmc/guilib/GUIControlGroup.cpp +index 7858e42..bdd7f54 100644 +--- a/xbmc/guilib/GUIControlGroup.cpp ++++ b/xbmc/guilib/GUIControlGroup.cpp +@@ -133,6 +133,13 @@ void CGUIControlGroup::Render() + g_graphicsContext.RestoreOrigin(); + } + ++void CGUIControlGroup::RenderEx() ++{ ++ for (iControls it = m_children.begin(); it != m_children.end(); ++it) ++ (*it)->RenderEx(); ++ CGUIControl::RenderEx(); ++} ++ + bool CGUIControlGroup::OnAction(const CAction &action) + { + ASSERT(false); // unimplemented +diff --git a/xbmc/guilib/GUIControlGroup.h b/xbmc/guilib/GUIControlGroup.h +index 054757f..0b38a56 100644 +--- a/xbmc/guilib/GUIControlGroup.h ++++ b/xbmc/guilib/GUIControlGroup.h +@@ -42,6 +42,7 @@ public: + + virtual void Process(unsigned int currentTime, CDirtyRegionList &dirtyregions); + virtual void Render(); ++ virtual void RenderEx(); + virtual bool OnAction(const CAction &action); + virtual bool OnMessage(CGUIMessage& message); + virtual bool SendControlMessage(CGUIMessage& message); +diff --git a/xbmc/guilib/GUIVideoControl.cpp b/xbmc/guilib/GUIVideoControl.cpp +index c47a6d5..126e95f 100644 +--- a/xbmc/guilib/GUIVideoControl.cpp ++++ b/xbmc/guilib/GUIVideoControl.cpp +@@ -42,8 +42,11 @@ CGUIVideoControl::~CGUIVideoControl(void) + + void CGUIVideoControl::Process(unsigned int currentTime, CDirtyRegionList &dirtyregions) + { ++ g_renderManager.FrameMove(); ++ + // TODO Proper processing which marks when its actually changed. Just mark always for now. +- MarkDirtyRegion(); ++ if (g_renderManager.IsGuiLayer()) ++ MarkDirtyRegion(); + + CGUIControl::Process(currentTime, dirtyregions); + } +@@ -67,14 +70,38 @@ void CGUIVideoControl::Render() + + #ifdef HAS_VIDEO_PLAYBACK + color_t alpha = g_graphicsContext.MergeAlpha(0xFF000000) >> 24; +- g_renderManager.Render(false, 0, alpha); ++ if (g_renderManager.IsVideoLayer()) ++ { ++ CRect old = g_graphicsContext.GetScissors(); ++ CRect region = GetRenderRegion(); ++ region.Intersect(old); ++ g_graphicsContext.BeginPaint(); ++ g_graphicsContext.SetScissors(region); ++ g_graphicsContext.Clear(0); ++ g_graphicsContext.SetScissors(old); ++ g_graphicsContext.EndPaint(); ++ } ++ else ++ g_renderManager.Render(false, 0, alpha); + #else + ((CDummyVideoPlayer *)g_application.m_pPlayer->GetInternal())->Render(); + #endif + } ++ // TODO: remove this crap: HAS_VIDEO_PLAYBACK ++ // instantiateing a vidio control having no playback is complete nonsense + CGUIControl::Render(); + } + ++void CGUIVideoControl::RenderEx() ++{ ++#ifdef HAS_VIDEO_PLAYBACK ++ if (g_application.m_pPlayer->IsPlayingVideo() && g_renderManager.IsStarted()) ++ g_renderManager.Render(false, 0, 255, false); ++ g_renderManager.FrameFinish(); ++#endif ++ CGUIControl::RenderEx(); ++} ++ + EVENT_RESULT CGUIVideoControl::OnMouseEvent(const CPoint &point, const CMouseEvent &event) + { + if (!g_application.m_pPlayer->IsPlayingVideo()) return EVENT_RESULT_UNHANDLED; +diff --git a/xbmc/guilib/GUIVideoControl.h b/xbmc/guilib/GUIVideoControl.h +index a692d01..0f89a9a 100644 +--- a/xbmc/guilib/GUIVideoControl.h ++++ b/xbmc/guilib/GUIVideoControl.h +@@ -44,6 +44,7 @@ public: + + virtual void Process(unsigned int currentTime, CDirtyRegionList &dirtyregions); + virtual void Render(); ++ virtual void RenderEx(); + virtual EVENT_RESULT OnMouseEvent(const CPoint &point, const CMouseEvent &event); + virtual bool CanFocus() const; + virtual bool CanFocusFromPoint(const CPoint &point) const; +diff --git a/xbmc/guilib/GUIWindowManager.cpp b/xbmc/guilib/GUIWindowManager.cpp +index 788bbe9..ef97251 100644 +--- a/xbmc/guilib/GUIWindowManager.cpp ++++ b/xbmc/guilib/GUIWindowManager.cpp +@@ -547,6 +547,24 @@ void CGUIWindowManager::RenderPass() const + } + } + ++void CGUIWindowManager::RenderEx() const ++{ ++ CGUIWindow* pWindow = GetWindow(GetActiveWindow()); ++ if (pWindow) ++ pWindow->RenderEx(); ++ ++ // We don't call RenderEx for now on dialogs since it is used ++ // to trigger non gui video rendering. We can activate it later at any time. ++ /* ++ vector &activeDialogs = m_activeDialogs; ++ for (iDialog it = activeDialogs.begin(); it != activeDialogs.end(); ++it) ++ { ++ if ((*it)->IsDialogRunning()) ++ (*it)->RenderEx(); ++ } ++ */ ++} ++ + bool CGUIWindowManager::Render() + { + assert(g_application.IsCurrentThread()); +@@ -586,13 +604,15 @@ bool CGUIWindowManager::Render() + if (g_advancedSettings.m_guiVisualizeDirtyRegions) + { + g_graphicsContext.SetRenderingResolution(g_graphicsContext.GetResInfo(), false); +- const CDirtyRegionList &markedRegions = m_tracker.GetMarkedRegions(); ++ const CDirtyRegionList &markedRegions = m_tracker.GetMarkedRegions(); + for (CDirtyRegionList::const_iterator i = markedRegions.begin(); i != markedRegions.end(); ++i) + CGUITexture::DrawQuad(*i, 0x0fff0000); + for (CDirtyRegionList::const_iterator i = dirtyRegions.begin(); i != dirtyRegions.end(); ++i) + CGUITexture::DrawQuad(*i, 0x4c00ff00); + } + ++ RenderEx(); ++ + return hasRendered; + } + +diff --git a/xbmc/guilib/GUIWindowManager.h b/xbmc/guilib/GUIWindowManager.h +index 4f1f96f..ea7239a 100644 +--- a/xbmc/guilib/GUIWindowManager.h ++++ b/xbmc/guilib/GUIWindowManager.h +@@ -144,6 +144,7 @@ public: + #endif + private: + void RenderPass() const; ++ void RenderEx() const; + + void LoadNotOnDemandWindows(); + void UnloadNotOnDemandWindows(); +diff --git a/xbmc/video/windows/GUIWindowFullScreen.cpp b/xbmc/video/windows/GUIWindowFullScreen.cpp +index dfbf773..ed7c090 100644 +--- a/xbmc/video/windows/GUIWindowFullScreen.cpp ++++ b/xbmc/video/windows/GUIWindowFullScreen.cpp +@@ -353,6 +353,12 @@ bool CGUIWindowFullScreen::OnAction(const CAction &action) + return CGUIWindow::OnAction(action); + } + ++void CGUIWindowFullScreen::ClearBackground() ++{ ++ if (g_renderManager.IsVideoLayer()) ++ g_graphicsContext.Clear(0); ++} ++ + void CGUIWindowFullScreen::OnWindowLoaded() + { + CGUIWindow::OnWindowLoaded(); +@@ -455,6 +461,7 @@ bool CGUIWindowFullScreen::OnMessage(CGUIMessage& message) + #ifdef HAS_VIDEO_PLAYBACK + // make sure renderer is uptospeed + g_renderManager.Update(); ++ g_renderManager.FrameFinish(); + #endif + return true; + } +@@ -730,22 +737,40 @@ void CGUIWindowFullScreen::FrameMove() + SET_CONTROL_HIDDEN(BLUE_BAR); + SET_CONTROL_HIDDEN(CONTROL_GROUP_CHOOSER); + } ++ ++ g_renderManager.FrameMove(); + } + + void CGUIWindowFullScreen::Process(unsigned int currentTime, CDirtyRegionList &dirtyregion) + { ++ if (g_renderManager.IsGuiLayer()) ++ MarkDirtyRegion(); ++ ++ CGUIWindow::Process(currentTime, dirtyregion); ++ + // TODO: This isn't quite optimal - ideally we'd only be dirtying up the actual video render rect + // which is probably the job of the renderer as it can more easily track resizing etc. +- MarkDirtyRegion(); +- CGUIWindow::Process(currentTime, dirtyregion); + m_renderRegion.SetRect(0, 0, (float)g_graphicsContext.GetWidth(), (float)g_graphicsContext.GetHeight()); + } + + void CGUIWindowFullScreen::Render() + { ++ g_graphicsContext.SetRenderingResolution(g_graphicsContext.GetVideoResolution(), false); ++ g_renderManager.Render(true, 0, 255); ++ g_graphicsContext.SetRenderingResolution(m_coordsRes, m_needsScaling); + CGUIWindow::Render(); + } + ++void CGUIWindowFullScreen::RenderEx() ++{ ++ CGUIWindow::RenderEx(); ++ g_graphicsContext.SetRenderingResolution(g_graphicsContext.GetVideoResolution(), false); ++#ifdef HAS_VIDEO_PLAYBACK ++ g_renderManager.Render(false, 0, 255, false); ++ g_renderManager.FrameFinish(); ++#endif ++} ++ + void CGUIWindowFullScreen::ChangetheTimeCode(int remote) + { + if (remote >= REMOTE_0 && remote <= REMOTE_9) +@@ -851,6 +876,8 @@ void CGUIWindowFullScreen::ToggleOSD() + else + pOSD->DoModal(); + } ++ ++ MarkDirtyRegion(); + } + + void CGUIWindowFullScreen::TriggerOSD() +diff --git a/xbmc/video/windows/GUIWindowFullScreen.h b/xbmc/video/windows/GUIWindowFullScreen.h +index 03608af..5a9b101 100644 +--- a/xbmc/video/windows/GUIWindowFullScreen.h ++++ b/xbmc/video/windows/GUIWindowFullScreen.h +@@ -30,9 +30,11 @@ public: + virtual ~CGUIWindowFullScreen(void); + virtual bool OnMessage(CGUIMessage& message); + virtual bool OnAction(const CAction &action); ++ virtual void ClearBackground(); + virtual void FrameMove(); + virtual void Process(unsigned int currentTime, CDirtyRegionList &dirtyregion); + virtual void Render(); ++ virtual void RenderEx(); + virtual void OnWindowLoaded(); + void ChangetheTimeCode(int remote); + void ChangetheTVGroup(bool next); +-- +1.9.1 + + +From b7c95f76c19aa172c6e63a9ed327369f0edb84df Mon Sep 17 00:00:00 2001 +From: Rainer Hochecker +Date: Mon, 5 Jan 2015 11:29:15 +0100 +Subject: [PATCH 4/6] guilib: mark control dirty when setting to invisible + +--- + xbmc/guilib/GUIControl.cpp | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/xbmc/guilib/GUIControl.cpp b/xbmc/guilib/GUIControl.cpp +index e3d04db..ff2086b 100644 +--- a/xbmc/guilib/GUIControl.cpp ++++ b/xbmc/guilib/GUIControl.cpp +@@ -511,6 +511,8 @@ void CGUIControl::SetVisible(bool bVisible, bool setVisState) + { + m_forceHidden = !bVisible; + SetInvalid(); ++ if (m_forceHidden) ++ MarkDirtyRegion(); + } + if (m_forceHidden) + { // reset any visible animations that are in process +-- +1.9.1 + + +From b5bb845c2640e8d05d88c761ce9f31a1e5bac91d Mon Sep 17 00:00:00 2001 +From: Rainer Hochecker +Date: Tue, 6 Jan 2015 13:13:27 +0100 +Subject: [PATCH 5/6] renderer: exit gfx lock when waiting for present time + +--- + xbmc/cores/VideoRenderers/RenderManager.cpp | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/xbmc/cores/VideoRenderers/RenderManager.cpp b/xbmc/cores/VideoRenderers/RenderManager.cpp +index 63bbdcc..b394d7b 100644 +--- a/xbmc/cores/VideoRenderers/RenderManager.cpp ++++ b/xbmc/cores/VideoRenderers/RenderManager.cpp +@@ -381,7 +381,10 @@ void CXBMCRenderManager::FrameFinish() + SPresent& m = m_Queue[m_presentsource]; + + if(g_graphicsContext.IsFullScreenVideo()) ++ { ++ CSingleExit lock(g_graphicsContext); + WaitPresentTime(m.timestamp); ++ } + + m_clock_framefinish = GetPresentTime(); + +-- +1.9.1 + + +From a46f3062c805d98947348626651cbff0d805d912 Mon Sep 17 00:00:00 2001 +From: Rainer Hochecker +Date: Fri, 23 Jan 2015 07:41:46 +0100 +Subject: [PATCH 6/6] renderer: fix sequence from WaitFrame, Render, FrameMove + to WaitFrame, FrameMove, Render + +--- + xbmc/Application.cpp | 12 +++++++++--- + xbmc/cores/VideoRenderers/RenderManager.cpp | 12 ++++++++++-- + xbmc/cores/VideoRenderers/RenderManager.h | 3 ++- + 3 files changed, 21 insertions(+), 6 deletions(-) + +diff --git a/xbmc/Application.cpp b/xbmc/Application.cpp +index 3a222d4..5775a76 100644 +--- a/xbmc/Application.cpp ++++ b/xbmc/Application.cpp +@@ -2212,16 +2212,17 @@ void CApplication::Render() + bool limitFrames = false; + unsigned int singleFrameTime = 10; // default limit 100 fps + ++ // Whether externalplayer is playing and we're unfocused ++ bool extPlayerActive = m_pPlayer->GetCurrentPlayer() == EPC_EXTPLAYER && m_pPlayer->IsPlaying() && !m_AppFocused; ++ + { + // Less fps in DPMS + bool lowfps = m_dpmsIsActive || g_Windowing.EnableFrameLimiter(); +- // Whether externalplayer is playing and we're unfocused +- bool extPlayerActive = m_pPlayer->GetCurrentPlayer() == EPC_EXTPLAYER && m_pPlayer->IsPlaying() && !m_AppFocused; + + m_bPresentFrame = false; + if (!extPlayerActive && g_graphicsContext.IsFullScreenVideo() && !m_pPlayer->IsPausedPlayback()) + { +- m_bPresentFrame = g_renderManager.FrameWait(100); ++ m_bPresentFrame = g_renderManager.HasFrame(); + } + else + { +@@ -2322,6 +2323,11 @@ void CApplication::Render() + if (flip) + g_graphicsContext.Flip(dirtyRegions); + ++ if (!extPlayerActive && g_graphicsContext.IsFullScreenVideo() && !m_pPlayer->IsPausedPlayback()) ++ { ++ g_renderManager.FrameWait(100); ++ } ++ + m_lastFrameTime = XbmcThreads::SystemClockMillis(); + CTimeUtils::UpdateFrameTime(flip); + +diff --git a/xbmc/cores/VideoRenderers/RenderManager.cpp b/xbmc/cores/VideoRenderers/RenderManager.cpp +index b394d7b..36c2842 100644 +--- a/xbmc/cores/VideoRenderers/RenderManager.cpp ++++ b/xbmc/cores/VideoRenderers/RenderManager.cpp +@@ -316,13 +316,21 @@ void CXBMCRenderManager::Update() + m_pRenderer->Update(); + } + +-bool CXBMCRenderManager::FrameWait(int ms) ++void CXBMCRenderManager::FrameWait(int ms) + { + XbmcThreads::EndTime timeout(ms); + CSingleLock lock(m_presentlock); + while(m_presentstep == PRESENT_IDLE && !timeout.IsTimePast()) + m_presentevent.wait(lock, timeout.MillisLeft()); +- return m_presentstep != PRESENT_IDLE; ++} ++ ++bool CXBMCRenderManager::HasFrame() ++{ ++ CSingleLock lock(m_presentlock); ++ if (m_presentstep == PRESENT_FRAME || m_presentstep == PRESENT_FRAME2) ++ return true; ++ else ++ return false; + } + + void CXBMCRenderManager::FrameMove() +diff --git a/xbmc/cores/VideoRenderers/RenderManager.h b/xbmc/cores/VideoRenderers/RenderManager.h +index 7280423..b80319a 100644 +--- a/xbmc/cores/VideoRenderers/RenderManager.h ++++ b/xbmc/cores/VideoRenderers/RenderManager.h +@@ -59,7 +59,8 @@ public: + void Update(); + void FrameMove(); + void FrameFinish(); +- bool FrameWait(int ms); ++ void FrameWait(int ms); ++ bool HasFrame(); + void Render(bool clear, DWORD flags = 0, DWORD alpha = 255, bool gui = true); + bool IsGuiLayer(); + bool IsVideoLayer(); +-- +1.9.1 +