2 * Copyright (C) 2005-2013 Team XBMC
5 * This Program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2, or (at your option)
10 * This Program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with XBMC; see the file COPYING. If not, see
17 * <http://www.gnu.org/licenses/>.
24 #include "BaseRenderer.h"
25 #include "settings/DisplaySettings.h"
26 #include "settings/MediaSettings.h"
27 #include "settings/Settings.h"
28 #include "guilib/GraphicContext.h"
29 #include "guilib/GUIWindowManager.h"
30 #include "guilib/LocalizeStrings.h"
31 #include "utils/log.h"
32 #include "utils/MathUtils.h"
33 #include "utils/SystemInfo.h"
34 #include "settings/AdvancedSettings.h"
35 #include "cores/VideoRenderers/RenderFlags.h"
38 CBaseRenderer::CBaseRenderer()
40 m_sourceFrameRatio = 1.0f;
43 m_resolution = RES_DESKTOP;
45 m_renderOrientation = 0;
46 m_oldRenderOrientation = 0;
47 m_oldDestRect.SetRect(0.0f, 0.0f, 0.0f, 0.0f);
50 for(int i=0; i < 4; i++)
52 m_rotatedDestCoords[i].x = 0;
53 m_rotatedDestCoords[i].y = 0;
54 m_savedRotatedDestCoords[i].x = 0;
55 m_savedRotatedDestCoords[i].y = 0;
58 m_RenderUpdateCallBackFn = NULL;
59 m_RenderUpdateCallBackCtx = NULL;
62 CBaseRenderer::~CBaseRenderer()
66 void CBaseRenderer::RegisterRenderUpdateCallBack(const void *ctx, RenderUpdateCallBackFn fn)
68 m_RenderUpdateCallBackFn = fn;
69 m_RenderUpdateCallBackCtx = ctx;
72 void CBaseRenderer::RegisterRenderFeaturesCallBack(const void *ctx, RenderFeaturesCallBackFn fn)
74 m_RenderFeaturesCallBackFn = fn;
75 m_RenderFeaturesCallBackCtx = ctx;
78 void CBaseRenderer::ChooseBestResolution(float fps)
80 if (fps == 0.0) return;
82 // Adjust refreshrate to match source fps
83 #if !defined(TARGET_DARWIN_IOS)
84 if (CSettings::Get().GetInt("videoplayer.adjustrefreshrate") != ADJUST_REFRESHRATE_OFF)
87 if (!FindResolutionFromOverride(fps, weight, false)) //find a refreshrate from overrides
89 if (!FindResolutionFromOverride(fps, weight, true))//if that fails find it from a fallback
90 FindResolutionFromFpsMatch(fps, weight);//if that fails use automatic refreshrate selection
93 CLog::Log(LOGNOTICE, "Display resolution ADJUST : %s (%d) (weight: %.3f)",
94 g_graphicsContext.GetResInfo(m_resolution).strMode.c_str(), m_resolution, weight);
98 CLog::Log(LOGNOTICE, "Display resolution %s : %s (%d)",
99 m_resolution == RES_DESKTOP ? "DESKTOP" : "USER", g_graphicsContext.GetResInfo(m_resolution).strMode.c_str(), m_resolution);
102 bool CBaseRenderer::FindResolutionFromOverride(float fps, float& weight, bool fallback)
104 RESOLUTION_INFO curr = g_graphicsContext.GetResInfo(m_resolution);
106 //try to find a refreshrate from the override
107 for (int i = 0; i < (int)g_advancedSettings.m_videoAdjustRefreshOverrides.size(); i++)
109 RefreshOverride& override = g_advancedSettings.m_videoAdjustRefreshOverrides[i];
111 if (override.fallback != fallback)
114 //if we're checking for overrides, check if the fps matches
115 if (!fallback && (fps < override.fpsmin || fps > override.fpsmax))
118 for (size_t j = (int)RES_DESKTOP; j < CDisplaySettings::Get().ResolutionInfoSize(); j++)
120 RESOLUTION_INFO info = g_graphicsContext.GetResInfo((RESOLUTION)j);
122 if (info.iScreenWidth == curr.iScreenWidth
123 && info.iScreenHeight == curr.iScreenHeight
124 && (info.dwFlags & D3DPRESENTFLAG_MODEMASK) == (curr.dwFlags & D3DPRESENTFLAG_MODEMASK)
125 && info.iScreen == curr.iScreen)
127 if (info.fRefreshRate <= override.refreshmax
128 && info.fRefreshRate >= override.refreshmin)
130 m_resolution = (RESOLUTION)j;
134 CLog::Log(LOGDEBUG, "Found Resolution %s (%d) from fallback (refreshmin:%.3f refreshmax:%.3f)",
135 info.strMode.c_str(), m_resolution,
136 override.refreshmin, override.refreshmax);
140 CLog::Log(LOGDEBUG, "Found Resolution %s (%d) from override of fps %.3f (fpsmin:%.3f fpsmax:%.3f refreshmin:%.3f refreshmax:%.3f)",
141 info.strMode.c_str(), m_resolution, fps,
142 override.fpsmin, override.fpsmax, override.refreshmin, override.refreshmax);
145 weight = RefreshWeight(info.fRefreshRate, fps);
147 return true; //fps and refresh match with this override, use this resolution
153 return false; //no override found
156 void CBaseRenderer::FindResolutionFromFpsMatch(float fps, float& weight)
158 const float maxWeight = 0.0021f;
159 RESOLUTION_INFO curr;
161 m_resolution = FindClosestResolution(fps, 1.0, m_resolution, weight);
162 curr = g_graphicsContext.GetResInfo(m_resolution);
164 if (weight >= maxWeight) //not a very good match, try a 2:3 cadence instead
166 CLog::Log(LOGDEBUG, "Resolution %s (%d) not a very good match for fps %.3f (weight: %.3f), trying 2:3 cadence",
167 curr.strMode.c_str(), m_resolution, fps, weight);
169 m_resolution = FindClosestResolution(fps, 2.5, m_resolution, weight);
170 curr = g_graphicsContext.GetResInfo(m_resolution);
172 if (weight >= maxWeight) //2:3 cadence not a good match
174 CLog::Log(LOGDEBUG, "Resolution %s (%d) not a very good match for fps %.3f with 2:3 cadence (weight: %.3f), choosing 60 hertz",
175 curr.strMode.c_str(), m_resolution, fps, weight);
177 //get the resolution with the refreshrate closest to 60 hertz
178 for (size_t i = (int)RES_DESKTOP; i < CDisplaySettings::Get().ResolutionInfoSize(); i++)
180 RESOLUTION_INFO info = g_graphicsContext.GetResInfo((RESOLUTION)i);
182 if (MathUtils::round_int(info.fRefreshRate) == 60
183 && info.iScreenWidth == curr.iScreenWidth
184 && info.iScreenHeight == curr.iScreenHeight
185 && (info.dwFlags & D3DPRESENTFLAG_MODEMASK) == (curr.dwFlags & D3DPRESENTFLAG_MODEMASK)
186 && info.iScreen == curr.iScreen)
188 if (fabs(info.fRefreshRate - 60.0) < fabs(curr.fRefreshRate - 60.0)) {
189 m_resolution = (RESOLUTION)i;
195 //60 hertz not available, get the highest refreshrate
196 if (MathUtils::round_int(curr.fRefreshRate) != 60)
198 CLog::Log(LOGDEBUG, "60 hertz refreshrate not available, choosing highest");
199 for (size_t i = (int)RES_DESKTOP; i < CDisplaySettings::Get().ResolutionInfoSize(); i++)
201 RESOLUTION_INFO info = g_graphicsContext.GetResInfo((RESOLUTION)i);
203 if (info.fRefreshRate > curr.fRefreshRate
204 && info.iScreenWidth == curr.iScreenWidth
205 && info.iScreenHeight == curr.iScreenHeight
206 && (info.dwFlags & D3DPRESENTFLAG_MODEMASK) == (curr.dwFlags & D3DPRESENTFLAG_MODEMASK)
207 && info.iScreen == curr.iScreen)
209 m_resolution = (RESOLUTION)i;
215 weight = RefreshWeight(curr.fRefreshRate, fps);
220 RESOLUTION CBaseRenderer::FindClosestResolution(float fps, float multiplier, RESOLUTION current, float& weight)
222 RESOLUTION_INFO curr = g_graphicsContext.GetResInfo(current);
224 float fRefreshRate = fps;
226 float last_diff = fRefreshRate;
228 // Find closest refresh rate
229 for (size_t i = (int)RES_DESKTOP; i < CDisplaySettings::Get().ResolutionInfoSize(); i++)
231 const RESOLUTION_INFO info = g_graphicsContext.GetResInfo((RESOLUTION)i);
233 //discard resolutions that are not the same width and height (and interlaced/3D flags)
234 //or have a too low refreshrate
235 if (info.iScreenWidth != curr.iScreenWidth
236 || info.iScreenHeight != curr.iScreenHeight
237 || info.iScreen != curr.iScreen
238 || (info.dwFlags & D3DPRESENTFLAG_MODEMASK) != (curr.dwFlags & D3DPRESENTFLAG_MODEMASK)
239 || info.fRefreshRate < (fRefreshRate * multiplier / 1.001) - 0.001)
242 // For 3D choose the closest refresh rate
243 if(CONF_FLAGS_STEREO_MODE_MASK(m_iFlags))
245 float diff = (info.fRefreshRate - fRefreshRate);
252 current = (RESOLUTION)i;
258 int c_weight = MathUtils::round_int(RefreshWeight(curr.fRefreshRate, fRefreshRate * multiplier) * 1000.0);
259 int i_weight = MathUtils::round_int(RefreshWeight(info.fRefreshRate, fRefreshRate * multiplier) * 1000.0);
261 // Closer the better, prefer higher refresh rate if the same
262 if ((i_weight < c_weight)
263 || (i_weight == c_weight && info.fRefreshRate > curr.fRefreshRate))
265 current = (RESOLUTION)i;
271 // For 3D overwrite weight
272 if(CONF_FLAGS_STEREO_MODE_MASK(m_iFlags))
275 weight = RefreshWeight(curr.fRefreshRate, fRefreshRate * multiplier);
280 //distance of refresh to the closest multiple of fps (multiple is 1 or higher), as a multiplier of fps
281 float CBaseRenderer::RefreshWeight(float refresh, float fps)
283 float div = refresh / fps;
284 int round = MathUtils::round_int(div);
287 return (fps - refresh) / fps;
289 return (float)fabs(div / round - 1.0);
292 RESOLUTION CBaseRenderer::GetResolution() const
294 if (g_graphicsContext.IsFullScreenRoot() && (g_graphicsContext.IsFullScreenVideo() || g_graphicsContext.IsCalibrating()))
297 return g_graphicsContext.GetVideoResolution();
300 float CBaseRenderer::GetAspectRatio() const
302 float width = (float)m_sourceWidth - CMediaSettings::Get().GetCurrentVideoSettings().m_CropLeft - CMediaSettings::Get().GetCurrentVideoSettings().m_CropRight;
303 float height = (float)m_sourceHeight - CMediaSettings::Get().GetCurrentVideoSettings().m_CropTop - CMediaSettings::Get().GetCurrentVideoSettings().m_CropBottom;
304 return m_sourceFrameRatio * width / height * m_sourceHeight / m_sourceWidth;
307 void CBaseRenderer::GetVideoRect(CRect &source, CRect &dest)
309 source = m_sourceRect;
313 inline void CBaseRenderer::ReorderDrawPoints()
315 // 0 - top left, 1 - top right, 2 - bottom right, 3 - bottom left
316 float origMat[4][2] = {{m_destRect.x1, m_destRect.y1},
317 {m_destRect.x2, m_destRect.y1},
318 {m_destRect.x2, m_destRect.y2},
319 {m_destRect.x1, m_destRect.y2}};
320 bool changeAspect = false;
323 switch (m_renderOrientation)
338 // if renderer doesn't support rotation
339 // treat orientation as 0 degree so that
340 // ffmpeg might handle it.
341 if (!Supports(RENDERFEATURE_ROTATION))
344 changeAspect = false;
348 int diff = (int) ((m_destRect.Height() - m_destRect.Width()) / 2);
350 for (int destIdx=0, srcIdx=pointOffset; destIdx < 4; destIdx++)
352 m_rotatedDestCoords[destIdx].x = origMat[srcIdx][0];
353 m_rotatedDestCoords[destIdx].y = origMat[srcIdx][1];
360 m_rotatedDestCoords[destIdx].x -= diff;
361 m_rotatedDestCoords[destIdx].y += diff;
364 m_rotatedDestCoords[destIdx].x += diff;
365 m_rotatedDestCoords[destIdx].y += diff;
368 m_rotatedDestCoords[destIdx].x += diff;
369 m_rotatedDestCoords[destIdx].y -= diff;
372 m_rotatedDestCoords[destIdx].x -= diff;
373 m_rotatedDestCoords[destIdx].y -= diff;
382 void CBaseRenderer::saveRotatedCoords()
384 for (int i = 0; i < 4; i++)
385 m_savedRotatedDestCoords[i] = m_rotatedDestCoords[i];
388 void CBaseRenderer::syncDestRectToRotatedPoints()
390 m_rotatedDestCoords[0].x = m_destRect.x1;
391 m_rotatedDestCoords[0].y = m_destRect.y1;
392 m_rotatedDestCoords[1].x = m_destRect.x2;
393 m_rotatedDestCoords[1].y = m_destRect.y1;
394 m_rotatedDestCoords[2].x = m_destRect.x2;
395 m_rotatedDestCoords[2].y = m_destRect.y2;
396 m_rotatedDestCoords[3].x = m_destRect.x1;
397 m_rotatedDestCoords[3].y = m_destRect.y2;
400 void CBaseRenderer::restoreRotatedCoords()
402 for (int i = 0; i < 4; i++)
403 m_rotatedDestCoords[i] = m_savedRotatedDestCoords[i];
406 void CBaseRenderer::CalcNormalDisplayRect(float offsetX, float offsetY, float screenWidth, float screenHeight, float inputFrameRatio, float zoomAmount, float verticalShift)
408 // if view window is empty, set empty destination
409 if(screenHeight == 0 || screenWidth == 0)
411 m_destRect.SetRect(0.0f, 0.0f, 0.0f, 0.0f);
415 // scale up image as much as possible
416 // and keep the aspect ratio (introduces with black bars)
417 // calculate the correct output frame ratio (using the users pixel ratio setting
418 // and the output pixel ratio setting)
420 float outputFrameRatio = inputFrameRatio / g_graphicsContext.GetResInfo(GetResolution()).fPixelRatio;
422 // allow a certain error to maximize screen size
423 float fCorrection = screenWidth / screenHeight / outputFrameRatio - 1.0f;
424 float fAllowed = CSettings::Get().GetInt("videoplayer.errorinaspect") * 0.01f;
425 if(fCorrection > fAllowed) fCorrection = fAllowed;
426 if(fCorrection < - fAllowed) fCorrection = - fAllowed;
428 outputFrameRatio *= 1.0f + fCorrection;
430 // maximize the movie width
431 float newWidth = screenWidth;
432 float newHeight = newWidth / outputFrameRatio;
434 if (newHeight > screenHeight)
436 newHeight = screenHeight;
437 newWidth = newHeight * outputFrameRatio;
440 // Scale the movie up by set zoom amount
441 newWidth *= zoomAmount;
442 newHeight *= zoomAmount;
445 float posY = (screenHeight - newHeight) / 2;
446 float posX = (screenWidth - newWidth) / 2;
448 // vertical shift range -1 to 1 shifts within the top and bottom black bars
449 // if there are no top and bottom black bars, this range does nothing
450 float blackBarSize = std::max((screenHeight - newHeight) / 2.0f, 0.0f);
451 posY += blackBarSize * std::max(std::min(verticalShift, 1.0f), -1.0f);
453 // vertical shift ranges -2 to -1 and 1 to 2 will shift the image out of the screen
454 // if vertical shift is -2 it will be completely shifted out the top,
455 // if it's 2 it will be completely shifted out the bottom
456 float shiftRange = std::min(newHeight, newHeight - (newHeight - screenHeight) / 2.0f);
457 if (verticalShift > 1.0f)
458 posY += shiftRange * (verticalShift - 1.0f);
459 else if (verticalShift < -1.0f)
460 posY += shiftRange * (verticalShift + 1.0f);
462 m_destRect.x1 = (float)MathUtils::round_int(posX + offsetX);
463 m_destRect.x2 = m_destRect.x1 + MathUtils::round_int(newWidth);
464 m_destRect.y1 = (float)MathUtils::round_int(posY + offsetY);
465 m_destRect.y2 = m_destRect.y1 + MathUtils::round_int(newHeight);
468 if (!(g_graphicsContext.IsFullScreenVideo() || g_graphicsContext.IsCalibrating()))
470 CRect original(m_destRect);
471 m_destRect.Intersect(CRect(offsetX, offsetY, offsetX + screenWidth, offsetY + screenHeight));
472 if (m_destRect != original)
474 float scaleX = m_sourceRect.Width() / original.Width();
475 float scaleY = m_sourceRect.Height() / original.Height();
476 m_sourceRect.x1 += (m_destRect.x1 - original.x1) * scaleX;
477 m_sourceRect.y1 += (m_destRect.y1 - original.y1) * scaleY;
478 m_sourceRect.x2 += (m_destRect.x2 - original.x2) * scaleX;
479 m_sourceRect.y2 += (m_destRect.y2 - original.y2) * scaleY;
483 if (m_oldDestRect != m_destRect || m_oldRenderOrientation != m_renderOrientation)
485 // adapt the drawing rect points if we have to rotate
486 // and either destrect or orientation changed
488 m_oldDestRect = m_destRect;
489 m_oldRenderOrientation = m_renderOrientation;
493 //***************************************************************************************
494 // CalculateFrameAspectRatio()
496 // Considers the source frame size and output frame size (as suggested by mplayer)
497 // to determine if the pixels in the source are not square. It calculates the aspect
498 // ratio of the output frame. We consider the cases of VCD, SVCD and DVD separately,
499 // as these are intended to be viewed on a non-square pixel TV set, so the pixels are
500 // defined to be the same ratio as the intended display pixels.
501 // These formats are determined by frame size.
502 //***************************************************************************************
503 void CBaseRenderer::CalculateFrameAspectRatio(unsigned int desired_width, unsigned int desired_height)
505 m_sourceFrameRatio = (float)desired_width / desired_height;
507 // Check whether mplayer has decided that the size of the video file should be changed
508 // This indicates either a scaling has taken place (which we didn't ask for) or it has
509 // found an aspect ratio parameter from the file, and is changing the frame size based
511 if (m_sourceWidth == (unsigned int) desired_width && m_sourceHeight == (unsigned int) desired_height)
514 // mplayer is scaling in one or both directions. We must alter our Source Pixel Ratio
515 float imageFrameRatio = (float)m_sourceWidth / m_sourceHeight;
517 // OK, most sources will be correct now, except those that are intended
518 // to be displayed on non-square pixel based output devices (ie PAL or NTSC TVs)
519 // This includes VCD, SVCD, and DVD (and possibly others that we are not doing yet)
520 // For this, we can base the pixel ratio on the pixel ratios of PAL and NTSC,
521 // though we will need to adjust for anamorphic sources (ie those whose
522 // output frame ratio is not 4:3) and for SVCDs which have 2/3rds the
523 // horizontal resolution of the default NTSC or PAL frame sizes
525 // The following are the defined standard ratios for PAL and NTSC pixels
526 // NOTE: These aren't technically (in terms of BT601) correct - the commented values are,
527 // but it seems that many DVDs nowadays are mastered incorrectly, so two wrongs
528 // may indeed make a right. The "wrong" values here ensure the output frame is
530 const float PALPixelRatio = 16.0f / 15.0f; // 128.0f / 117.0f;
531 const float NTSCPixelRatio = 8.0f / 9.0f; // 4320.0f / 4739.0f;
533 // Calculate the correction needed for anamorphic sources
534 float Non4by3Correction = m_sourceFrameRatio / (4.0f / 3.0f);
536 // Finally, check for a VCD, SVCD or DVD frame size as these need special aspect ratios
537 if (m_sourceWidth == 352)
539 if (m_sourceHeight == 240) // NTSC
540 m_sourceFrameRatio = imageFrameRatio * NTSCPixelRatio;
541 if (m_sourceHeight == 288) // PAL
542 m_sourceFrameRatio = imageFrameRatio * PALPixelRatio;
544 if (m_sourceWidth == 480)
546 if (m_sourceHeight == 480) // NTSC
547 m_sourceFrameRatio = imageFrameRatio * 3.0f / 2.0f * NTSCPixelRatio * Non4by3Correction;
548 if (m_sourceHeight == 576) // PAL
549 m_sourceFrameRatio = imageFrameRatio * 3.0f / 2.0f * PALPixelRatio * Non4by3Correction;
551 if (m_sourceWidth == 720)
553 if (m_sourceHeight == 480) // NTSC
554 m_sourceFrameRatio = imageFrameRatio * NTSCPixelRatio * Non4by3Correction;
555 if (m_sourceHeight == 576) // PAL
556 m_sourceFrameRatio = imageFrameRatio * PALPixelRatio * Non4by3Correction;
560 void CBaseRenderer::ManageDisplay()
562 const CRect view = g_graphicsContext.GetViewWindow();
564 m_sourceRect.x1 = 0.0f;
565 m_sourceRect.y1 = 0.0f;
566 m_sourceRect.x2 = (float)m_sourceWidth;
567 m_sourceRect.y2 = (float)m_sourceHeight;
569 unsigned int stereo_mode = CONF_FLAGS_STEREO_MODE_MASK(m_iFlags);
570 int stereo_view = g_graphicsContext.GetStereoView();
572 if(CONF_FLAGS_STEREO_CADENCE(m_iFlags) == CONF_FLAGS_STEREO_CADANCE_RIGHT_LEFT)
574 if (stereo_view == RENDER_STEREO_VIEW_LEFT) stereo_view = RENDER_STEREO_VIEW_RIGHT;
575 else if(stereo_view == RENDER_STEREO_VIEW_RIGHT) stereo_view = RENDER_STEREO_VIEW_LEFT;
580 case CONF_FLAGS_STEREO_MODE_TAB:
581 if (stereo_view == RENDER_STEREO_VIEW_LEFT)
582 m_sourceRect.y2 *= 0.5f;
583 else if(stereo_view == RENDER_STEREO_VIEW_RIGHT)
584 m_sourceRect.y1 += m_sourceRect.y2*0.5f;
587 case CONF_FLAGS_STEREO_MODE_SBS:
588 if (stereo_view == RENDER_STEREO_VIEW_LEFT)
589 m_sourceRect.x2 *= 0.5f;
590 else if(stereo_view == RENDER_STEREO_VIEW_RIGHT)
591 m_sourceRect.x1 += m_sourceRect.x2*0.5f;
598 m_sourceRect.x1 += (float)CMediaSettings::Get().GetCurrentVideoSettings().m_CropLeft;
599 m_sourceRect.y1 += (float)CMediaSettings::Get().GetCurrentVideoSettings().m_CropTop;
600 m_sourceRect.x2 -= (float)CMediaSettings::Get().GetCurrentVideoSettings().m_CropRight;
601 m_sourceRect.y2 -= (float)CMediaSettings::Get().GetCurrentVideoSettings().m_CropBottom;
603 CalcNormalDisplayRect(view.x1, view.y1, view.Width(), view.Height(), GetAspectRatio() * CDisplaySettings::Get().GetPixelRatio(), CDisplaySettings::Get().GetZoomAmount(), CDisplaySettings::Get().GetVerticalShift());
606 void CBaseRenderer::SetViewMode(int viewMode)
608 if (viewMode < ViewModeNormal || viewMode > ViewModeCustom)
609 viewMode = ViewModeNormal;
611 CMediaSettings::Get().GetCurrentVideoSettings().m_ViewMode = viewMode;
613 // get our calibrated full screen resolution
614 RESOLUTION res = GetResolution();
615 RESOLUTION_INFO info = g_graphicsContext.GetResInfo(m_resolution);
616 float screenWidth = (float)(info.Overscan.right - info.Overscan.left);
617 float screenHeight = (float)(info.Overscan.bottom - info.Overscan.top);
619 // and the source frame ratio
620 float sourceFrameRatio = GetAspectRatio();
622 bool is43 = (sourceFrameRatio < 8.f/(3.f*sqrt(3.f)) &&
623 CMediaSettings::Get().GetCurrentVideoSettings().m_ViewMode == ViewModeNormal);
625 // Splitres scaling factor
626 float xscale = (float)info.iScreenWidth / (float)info.iWidth;
627 float yscale = (float)info.iScreenHeight / (float)info.iHeight;
629 screenWidth *= xscale;
630 screenHeight *= yscale;
632 CDisplaySettings::Get().SetVerticalShift(0.0f);
633 CDisplaySettings::Get().SetNonLinearStretched(false);
635 if ( CMediaSettings::Get().GetCurrentVideoSettings().m_ViewMode == ViewModeZoom ||
636 (is43 && CSettings::Get().GetInt("videoplayer.stretch43") == ViewModeZoom))
637 { // zoom image so no black bars
638 CDisplaySettings::Get().SetPixelRatio(1.0);
639 // calculate the desired output ratio
640 float outputFrameRatio = sourceFrameRatio * CDisplaySettings::Get().GetPixelRatio() / info.fPixelRatio;
641 // now calculate the correct zoom amount. First zoom to full height.
642 float newHeight = screenHeight;
643 float newWidth = newHeight * outputFrameRatio;
644 CDisplaySettings::Get().SetZoomAmount(newWidth / screenWidth);
645 if (newWidth < screenWidth)
646 { // zoom to full width
647 newWidth = screenWidth;
648 newHeight = newWidth / outputFrameRatio;
649 CDisplaySettings::Get().SetZoomAmount(newHeight / screenHeight);
652 else if (CMediaSettings::Get().GetCurrentVideoSettings().m_ViewMode == ViewModeStretch4x3)
653 { // stretch image to 4:3 ratio
654 CDisplaySettings::Get().SetZoomAmount(1.0);
655 if (res == RES_PAL_4x3 || res == RES_PAL60_4x3 || res == RES_NTSC_4x3 || res == RES_HDTV_480p_4x3)
656 { // stretch to the limits of the 4:3 screen.
657 // incorrect behaviour, but it's what the users want, so...
658 CDisplaySettings::Get().SetPixelRatio((screenWidth / screenHeight) * info.fPixelRatio / sourceFrameRatio);
662 // now we need to set CDisplaySettings::Get().GetPixelRatio() so that
663 // fOutputFrameRatio = 4:3.
664 CDisplaySettings::Get().SetPixelRatio((4.0f / 3.0f) / sourceFrameRatio);
667 else if ( CMediaSettings::Get().GetCurrentVideoSettings().m_ViewMode == ViewModeWideZoom ||
668 (is43 && CSettings::Get().GetInt("videoplayer.stretch43") == ViewModeWideZoom))
670 float stretchAmount = (screenWidth / screenHeight) * info.fPixelRatio / sourceFrameRatio;
671 CDisplaySettings::Get().SetPixelRatio(pow(stretchAmount, float(2.0/3.0)));
672 CDisplaySettings::Get().SetZoomAmount(pow(stretchAmount, float((stretchAmount < 1.0) ? -1.0/3.0 : 1.0/3.0)));
673 CDisplaySettings::Get().SetNonLinearStretched(true);
675 else if ( CMediaSettings::Get().GetCurrentVideoSettings().m_ViewMode == ViewModeStretch16x9 ||
676 (is43 && CSettings::Get().GetInt("videoplayer.stretch43") == ViewModeStretch16x9))
677 { // stretch image to 16:9 ratio
678 CDisplaySettings::Get().SetZoomAmount(1.0);
679 if (res == RES_PAL_4x3 || res == RES_PAL60_4x3 || res == RES_NTSC_4x3 || res == RES_HDTV_480p_4x3)
680 { // now we need to set CDisplaySettings::Get().GetPixelRatio() so that
681 // outputFrameRatio = 16:9.
682 CDisplaySettings::Get().SetPixelRatio((16.0f / 9.0f) / sourceFrameRatio);
685 { // stretch to the limits of the 16:9 screen.
686 // incorrect behaviour, but it's what the users want, so...
687 CDisplaySettings::Get().SetPixelRatio((screenWidth / screenHeight) * info.fPixelRatio / sourceFrameRatio);
690 else if (CMediaSettings::Get().GetCurrentVideoSettings().m_ViewMode == ViewModeOriginal)
691 { // zoom image so that the height is the original size
692 CDisplaySettings::Get().SetPixelRatio(1.0);
693 // get the size of the media file
694 // calculate the desired output ratio
695 float outputFrameRatio = sourceFrameRatio * CDisplaySettings::Get().GetPixelRatio() / info.fPixelRatio;
696 // now calculate the correct zoom amount. First zoom to full width.
697 float newHeight = screenWidth / outputFrameRatio;
698 if (newHeight > screenHeight)
699 { // zoom to full height
700 newHeight = screenHeight;
702 // now work out the zoom amount so that no zoom is done
703 CDisplaySettings::Get().SetZoomAmount((m_sourceHeight - CMediaSettings::Get().GetCurrentVideoSettings().m_CropTop - CMediaSettings::Get().GetCurrentVideoSettings().m_CropBottom) / newHeight);
705 else if (CMediaSettings::Get().GetCurrentVideoSettings().m_ViewMode == ViewModeCustom)
707 CDisplaySettings::Get().SetZoomAmount(CMediaSettings::Get().GetCurrentVideoSettings().m_CustomZoomAmount);
708 CDisplaySettings::Get().SetPixelRatio(CMediaSettings::Get().GetCurrentVideoSettings().m_CustomPixelRatio);
709 CDisplaySettings::Get().SetNonLinearStretched(CMediaSettings::Get().GetCurrentVideoSettings().m_CustomNonLinStretch);
710 CDisplaySettings::Get().SetVerticalShift(CMediaSettings::Get().GetCurrentVideoSettings().m_CustomVerticalShift);
712 else // if (CMediaSettings::Get().GetCurrentVideoSettings().m_ViewMode == ViewModeNormal)
714 CDisplaySettings::Get().SetPixelRatio(1.0);
715 CDisplaySettings::Get().SetZoomAmount(1.0);
718 CMediaSettings::Get().GetCurrentVideoSettings().m_CustomZoomAmount = CDisplaySettings::Get().GetZoomAmount();
719 CMediaSettings::Get().GetCurrentVideoSettings().m_CustomPixelRatio = CDisplaySettings::Get().GetPixelRatio();
720 CMediaSettings::Get().GetCurrentVideoSettings().m_CustomNonLinStretch = CDisplaySettings::Get().IsNonLinearStretched();
721 CMediaSettings::Get().GetCurrentVideoSettings().m_CustomVerticalShift = CDisplaySettings::Get().GetVerticalShift();
724 void CBaseRenderer::MarkDirty()
726 g_windowManager.MarkDirty(m_destRect);
729 void CBaseRenderer::SettingOptionsRenderMethodsFiller(const CSetting *setting, std::vector< std::pair<std::string, int> > &list, int ¤t)
731 list.push_back(make_pair(g_localizeStrings.Get(13416), RENDER_METHOD_AUTO));
734 if (g_sysinfo.IsWindowsVersionAtLeast(CSysInfo::WindowsVersionVista))
735 list.push_back(make_pair(g_localizeStrings.Get(16319), RENDER_METHOD_DXVA));
736 list.push_back(make_pair(g_localizeStrings.Get(13431), RENDER_METHOD_D3D_PS));
737 list.push_back(make_pair(g_localizeStrings.Get(13419), RENDER_METHOD_SOFTWARE));
741 list.push_back(make_pair(g_localizeStrings.Get(13417), RENDER_METHOD_ARB));
742 list.push_back(make_pair(g_localizeStrings.Get(13418), RENDER_METHOD_GLSL));
743 list.push_back(make_pair(g_localizeStrings.Get(13419), RENDER_METHOD_SOFTWARE));