2 * Initial code sponsored by: Voddler Inc (voddler.com)
3 * Copyright (C) 2005-2013 Team XBMC
6 * This Program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2, or (at your option)
11 * This Program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with XBMC; see the file COPYING. If not, see
18 * <http://www.gnu.org/licenses/>.
23 #include "OverlayRenderer.h"
24 #include "cores/dvdplayer/DVDCodecs/Overlay/DVDOverlay.h"
25 #include "cores/dvdplayer/DVDCodecs/Overlay/DVDOverlayImage.h"
26 #include "cores/dvdplayer/DVDCodecs/Overlay/DVDOverlaySpu.h"
27 #include "cores/dvdplayer/DVDCodecs/Overlay/DVDOverlaySSA.h"
28 #include "cores/VideoRenderers/RenderManager.h"
29 #include "guilib/GraphicContext.h"
30 #include "Application.h"
31 #include "guilib/GraphicContext.h"
32 #include "windowing/WindowingFactory.h"
33 #include "settings/DisplaySettings.h"
34 #include "settings/Settings.h"
35 #include "settings/DisplaySettings.h"
36 #include "threads/SingleLock.h"
37 #include "utils/MathUtils.h"
38 #include "OverlayRendererUtil.h"
39 #include "OverlayRendererGUI.h"
40 #if defined(HAS_GL) || defined(HAS_GLES)
41 #include "OverlayRendererGL.h"
43 #include "OverlayRendererDX.h"
46 using namespace OVERLAY;
56 m_align = ALIGN_SCREEN;
57 m_pos = POSITION_RELATIVE;
65 COverlay* COverlay::Acquire()
67 AtomicIncrement(&m_references);
71 long COverlay::Release()
73 long count = AtomicDecrement(&m_references);
80 long COverlayMainThread::Release()
82 long count = AtomicDecrement(&m_references);
85 if (g_application.IsCurrentThread())
88 g_renderManager.AddCleanup(this);
94 CRenderer::CRenderer()
98 CRenderer::~CRenderer()
100 for(int i = 0; i < NUM_BUFFERS; i++)
101 Release(m_buffers[i]);
104 void CRenderer::AddOverlay(CDVDOverlay* o, double pts, int index)
106 CSingleLock lock(m_section);
110 e.overlay_dvd = o->Acquire();
111 m_buffers[index].push_back(e);
114 void CRenderer::AddOverlay(COverlay* o, double pts, int index)
116 CSingleLock lock(m_section);
120 e.overlay = o->Acquire();
121 m_buffers[index].push_back(e);
124 void CRenderer::AddCleanup(COverlay* o)
126 CSingleLock lock(m_section);
127 m_cleanup.push_back(o->Acquire());
130 void CRenderer::Release(SElementV& list)
135 for(SElementV::iterator it = l.begin(); it != l.end(); ++it)
138 it->overlay->Release();
140 it->overlay_dvd->Release();
144 void CRenderer::Release(COverlayV& list)
149 for(COverlayV::iterator it = l.begin(); it != l.end(); ++it)
153 void CRenderer::Flush()
155 CSingleLock lock(m_section);
157 for(int i = 0; i < NUM_BUFFERS; i++)
158 Release(m_buffers[i]);
163 void CRenderer::Release(int idx)
165 CSingleLock lock(m_section);
166 Release(m_buffers[idx]);
169 void CRenderer::Render(int idx)
171 CSingleLock lock(m_section);
175 SElementV& list = m_buffers[idx];
176 for(SElementV::iterator it = list.begin(); it != list.end(); ++it)
181 o = it->overlay->Acquire();
182 else if(it->overlay_dvd)
183 o = Convert(it->overlay_dvd, it->pts);
194 void CRenderer::Render(COverlay* o)
198 g_renderManager.GetVideoRect(rs, rd);
199 rv = g_graphicsContext.GetViewWindow();
200 res = g_graphicsContext.GetResInfo(g_renderManager.GetResolution());
205 state.width = o->m_width;
206 state.height = o->m_height;
208 COverlay::EPosition pos = o->m_pos;
209 COverlay::EAlign align = o->m_align;
211 if(pos == COverlay::POSITION_RELATIVE)
216 if(align == COverlay::ALIGN_SCREEN
217 || align == COverlay::ALIGN_SUBTITLE)
219 scale_x = (float)res.iWidth;
220 scale_y = (float)res.iHeight;
223 if(align == COverlay::ALIGN_VIDEO)
225 scale_x = rs.Width();
226 scale_y = rs.Height();
231 state.width *= scale_x;
232 state.height *= scale_y;
234 pos = COverlay::POSITION_ABSOLUTE;
237 if(pos == COverlay::POSITION_ABSOLUTE)
239 if(align == COverlay::ALIGN_SCREEN
240 || align == COverlay::ALIGN_SUBTITLE)
242 float scale_x = rv.Width() / res.iWidth;
243 float scale_y = rv.Height() / res.iHeight;
247 state.width *= scale_x;
248 state.height *= scale_y;
250 if(align == COverlay::ALIGN_SUBTITLE)
252 state.x += rv.x1 + rv.Width() * 0.5f;
253 state.y += rv.y1 + (res.iSubtitles - res.Overscan.top) * scale_y;
262 if(align == COverlay::ALIGN_VIDEO)
264 float scale_x = rd.Width() / rs.Width();
265 float scale_y = rd.Height() / rs.Height();
269 state.width *= scale_x;
270 state.height *= scale_y;
278 state.x += GetStereoscopicDepth();
283 COverlay* CRenderer::Convert(CDVDOverlaySSA* o, double pts)
286 g_renderManager.GetVideoRect(src, dst);
288 int width = MathUtils::round_int(dst.Width());
289 int height = MathUtils::round_int(dst.Height());
292 ASS_Image* images = o->m_libass->RenderImage(width, height, pts, &changes);
297 return o->m_overlay->Acquire();
300 #if defined(HAS_GL) || defined(HAS_GLES)
301 return new COverlayGlyphGL(images, width, height);
302 #elif defined(HAS_DX)
303 return new COverlayQuadsDX(images, width, height);
309 COverlay* CRenderer::Convert(CDVDOverlay* o, double pts)
313 if(o->IsOverlayType(DVDOVERLAY_TYPE_SSA))
314 r = Convert((CDVDOverlaySSA*)o, pts);
315 else if(o->m_overlay)
316 r = o->m_overlay->Acquire();
321 o->m_overlay->Release();
322 o->m_overlay = r->Acquire();
326 #if defined(HAS_GL) || defined(HAS_GLES)
327 if (o->IsOverlayType(DVDOVERLAY_TYPE_IMAGE))
328 r = new COverlayTextureGL((CDVDOverlayImage*)o);
329 else if(o->IsOverlayType(DVDOVERLAY_TYPE_SPU))
330 r = new COverlayTextureGL((CDVDOverlaySpu*)o);
331 #elif defined(HAS_DX)
332 if (o->IsOverlayType(DVDOVERLAY_TYPE_IMAGE))
333 r = new COverlayImageDX((CDVDOverlayImage*)o);
334 else if(o->IsOverlayType(DVDOVERLAY_TYPE_SPU))
335 r = new COverlayImageDX((CDVDOverlaySpu*)o);
338 if(!r && o->IsOverlayType(DVDOVERLAY_TYPE_TEXT))
339 r = new COverlayText((CDVDOverlayText*)o);
342 o->m_overlay = r->Acquire();