diff options
author | Joakim Plate <elupus@ecce.se> | 2013-08-01 08:46:35 -0700 |
---|---|---|
committer | Joakim Plate <elupus@ecce.se> | 2013-08-01 08:46:35 -0700 |
commit | d60e1f9a7383c73cc45ff6272de794b2587ace9f (patch) | |
tree | 74e9173737a75d42df03d34f67b0ee10f0befc1b | |
parent | 38238bd32339115d7f43a94d422b2c4fa27f294c (diff) | |
parent | a2e704b3cf69f00f88af06821a211d2c19bb513b (diff) |
Merge pull request #2848 from elupus/3d
Stereoscopic 3d rendering support
101 files changed, 2750 insertions, 690 deletions
diff --git a/XBMC.xcodeproj/project.pbxproj b/XBMC.xcodeproj/project.pbxproj index caae0ef9b1..bcd3e1b2a3 100644 --- a/XBMC.xcodeproj/project.pbxproj +++ b/XBMC.xcodeproj/project.pbxproj @@ -246,6 +246,8 @@ 5538432B15F3646C00CE061B /* NptPosixTime.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 5538432A15F3646C00CE061B /* NptPosixTime.cpp */; settings = {COMPILER_FLAGS = "-I$SRCROOT/lib/libUPnP/Platinum/Source/Core -I$SRCROOT/lib/libUPnP/Platinum/Source/Platinum -I$SRCROOT/lib/libUPnP/Platinum/Source/Devices/MediaConnect -I$SRCROOT/lib/libUPnP/Platinum/Source/Devices/MediaRenderer -I$SRCROOT/lib/libUPnP/Platinum/Source/Devices/MediaServer -I$SRCROOT/lib/libUPnP/Platinum/Source/Extras -I$SRCROOT/lib/libUPnP/Neptune/Source/System/Posix -I$SRCROOT/lib/libUPnP/Neptune/Source/Core"; }; }; 5538433115F3678900CE061B /* NptCocoaEnviroment.mm in Sources */ = {isa = PBXBuildFile; fileRef = 5538432D15F3678900CE061B /* NptCocoaEnviroment.mm */; settings = {COMPILER_FLAGS = "-I$SRCROOT/lib/libUPnP/Platinum/Source/Core -I$SRCROOT/lib/libUPnP/Platinum/Source/Platinum -I$SRCROOT/lib/libUPnP/Platinum/Source/Devices/MediaConnect -I$SRCROOT/lib/libUPnP/Platinum/Source/Devices/MediaRenderer -I$SRCROOT/lib/libUPnP/Platinum/Source/Devices/MediaServer -I$SRCROOT/lib/libUPnP/Platinum/Source/Extras -I$SRCROOT/lib/libUPnP/Neptune/Source/System/Posix -I$SRCROOT/lib/libUPnP/Neptune/Source/Core"; }; }; 5538433415F3685C00CE061B /* NptAppleAutoreleasePool.mm in Sources */ = {isa = PBXBuildFile; fileRef = 5538433315F3685C00CE061B /* NptAppleAutoreleasePool.mm */; settings = {COMPILER_FLAGS = "-I$SRCROOT/lib/libUPnP/Platinum/Source/Core -I$SRCROOT/lib/libUPnP/Platinum/Source/Platinum -I$SRCROOT/lib/libUPnP/Platinum/Source/Devices/MediaConnect -I$SRCROOT/lib/libUPnP/Platinum/Source/Devices/MediaRenderer -I$SRCROOT/lib/libUPnP/Platinum/Source/Devices/MediaServer -I$SRCROOT/lib/libUPnP/Platinum/Source/Extras -I$SRCROOT/lib/libUPnP/Neptune/Source/System/Posix -I$SRCROOT/lib/libUPnP/Neptune/Source/Core"; }; }; + 55611BA31766672F00754072 /* RenderFlags.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 55611BA21766672F00754072 /* RenderFlags.cpp */; }; + 5558ED10176396CD00118C35 /* StereoscopicsManager.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 5558ED0E176396CD00118C35 /* StereoscopicsManager.cpp */; }; 7C0B98A4154B79C30065A238 /* AEDeviceInfo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7C0B98A1154B79C30065A238 /* AEDeviceInfo.cpp */; }; 7C1A492315A962EE004AF4A4 /* SeekHandler.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7C1A492115A962EE004AF4A4 /* SeekHandler.cpp */; }; 7C1A85661520522500C63311 /* TextureCacheJob.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7C1A85631520522500C63311 /* TextureCacheJob.cpp */; }; @@ -3640,6 +3642,10 @@ 5538432A15F3646C00CE061B /* NptPosixTime.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = NptPosixTime.cpp; path = lib/libUPnP/Neptune/Source/System/Posix/NptPosixTime.cpp; sourceTree = SOURCE_ROOT; }; 5538432D15F3678900CE061B /* NptCocoaEnviroment.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = NptCocoaEnviroment.mm; path = lib/libUPnP/Neptune/Source/System/Cocoa/NptCocoaEnviroment.mm; sourceTree = SOURCE_ROOT; }; 5538433315F3685C00CE061B /* NptAppleAutoreleasePool.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = NptAppleAutoreleasePool.mm; path = lib/libUPnP/Neptune/Source/System/Apple/NptAppleAutoreleasePool.mm; sourceTree = SOURCE_ROOT; }; + 55611BA21766672F00754072 /* RenderFlags.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = RenderFlags.cpp; sourceTree = "<group>"; }; + 55611BA41766679200754072 /* RenderFlags.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RenderFlags.h; sourceTree = "<group>"; }; + 5558ED0E176396CD00118C35 /* StereoscopicsManager.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = StereoscopicsManager.cpp; sourceTree = "<group>"; }; + 5558ED0F176396CD00118C35 /* StereoscopicsManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = StereoscopicsManager.h; sourceTree = "<group>"; }; 6E2FACD20E26E92800DF79EA /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; }; 6E97BDBF0DA2B620003A2A89 /* EventClient.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = EventClient.h; sourceTree = "<group>"; }; 6E97BDC00DA2B620003A2A89 /* EventPacket.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = EventPacket.h; sourceTree = "<group>"; }; @@ -5870,6 +5876,8 @@ 18B7C7461294222E009E7A26 /* Resolution.h */, 18B7C79E1294222E009E7A26 /* Shader.cpp */, 18B7C7471294222E009E7A26 /* Shader.h */, + 5558ED0E176396CD00118C35 /* StereoscopicsManager.cpp */, + 5558ED0F176396CD00118C35 /* StereoscopicsManager.h */, 18B7C79F1294222E009E7A26 /* Texture.cpp */, 18B7C7481294222E009E7A26 /* Texture.h */, 18B7C7A01294222E009E7A26 /* TextureBundle.cpp */, @@ -7664,6 +7672,8 @@ 431AE5D8109C1A63007428C3 /* OverlayRendererUtil.h */, F56579AD13060D1E0085ED7F /* RenderCapture.cpp */, F56579AE13060D1E0085ED7F /* RenderCapture.h */, + 55611BA21766672F00754072 /* RenderFlags.cpp */, + 55611BA41766679200754072 /* RenderFlags.h */, E38E16650D25F9FA00618676 /* RenderManager.cpp */, E38E16660D25F9FA00618676 /* RenderManager.h */, E38E16740D25F9FA00618676 /* WinRenderer.h */, @@ -10562,6 +10572,8 @@ DF40BC2F178B4C07009DB567 /* LanguageInvokerThread.cpp in Sources */, DF40BC31178B4C07009DB567 /* ScriptInvocationManager.cpp in Sources */, DFBB430A178B574E006CC20A /* AddonCallbacksCodec.cpp in Sources */, + 55611BA31766672F00754072 /* RenderFlags.cpp in Sources */, + 5558ED10176396CD00118C35 /* StereoscopicsManager.cpp in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/addons/skin.confluence/720p/VideoOSD.xml b/addons/skin.confluence/720p/VideoOSD.xml index c31671c2d4..0760e155a9 100644 --- a/addons/skin.confluence/720p/VideoOSD.xml +++ b/addons/skin.confluence/720p/VideoOSD.xml @@ -138,7 +138,7 @@ <texturefocus>OSDNextTrackFO.png</texturefocus> <texturenofocus>OSDNextTrackNF.png</texturenofocus> <onleft>204</onleft> - <onright>250</onright> + <onright>255</onright> <onup>1000</onup> <ondown>1000</ondown> <onclick>PlayerControl(Next)</onclick> @@ -280,7 +280,7 @@ <texturefocus>OSDepgFO.png</texturefocus> <texturenofocus>OSDepgNF.png</texturenofocus> <onleft>306</onleft> - <onright>350</onright> + <onright>354</onright> <onup>1000</onup> <ondown>1000</ondown> <onclick>ActivateWindow(PVROSDGuide)</onclick> @@ -290,27 +290,42 @@ <!-- !LiveTV --> <control type="group"> - <posx>300r</posx> + <posx>355r</posx> <posy>60r</posy> <animation effect="fade" time="200">VisibleChange</animation> <visible>![Window.IsVisible(SliderDialog) | Window.IsVisible(OSDVideoSettings) | Window.IsVisible(OSDAudioSettings) | Window.IsVisible(VideoBookmarks)]</visible> <visible>!VideoPlayer.Content(LiveTV)</visible> - <control type="button" id="250"> + <control type="button" id="255"> + <visible>VideoPlayer.IsStereoscopic</visible> <posx>0</posx> <posy>0</posy> <width>55</width> <height>55</height> + <label>36501</label> + <font>-</font> + <texturefocus>OSDStereoscopicFO.png</texturefocus> + <texturenofocus>OSDStereoscopicNF.png</texturenofocus> + <onleft>205</onleft> + <onright>250</onright> + <onup>501</onup> + <ondown>1000</ondown> + </control> + <control type="button" id="250"> + <posx>55</posx> + <posy>0</posy> + <width>55</width> + <height>55</height> <label>31356</label> <font>-</font> <texturefocus>OSDSubtitlesFO.png</texturefocus> <texturenofocus>OSDSubtitlesNF.png</texturenofocus> - <onleft>205</onleft> + <onleft>255</onleft> <onright>251</onright> <onup>404</onup> <ondown>1000</ondown> </control> <control type="button" id="251"> - <posx>55</posx> + <posx>110</posx> <posy>0</posy> <width>55</width> <height>55</height> @@ -325,7 +340,7 @@ <onclick>ActivateWindow(OSDVideoSettings)</onclick> </control> <control type="button" id="252"> - <posx>110</posx> + <posx>165</posx> <posy>0</posy> <width>55</width> <height>55</height> @@ -340,7 +355,7 @@ <onclick>ActivateWindow(OSDAudioSettings)</onclick> </control> <control type="button" id="253"> - <posx>165</posx> + <posx>220</posx> <posy>0</posy> <width>55</width> <height>55</height> @@ -355,7 +370,7 @@ <onclick>ActivateWindow(VideoBookmarks)</onclick> </control> <control type="button" id="254"> - <posx>220</posx> + <posx>275</posx> <posy>0</posy> <width>55</width> <height>55</height> @@ -380,23 +395,38 @@ <animation effect="fade" time="200">VisibleChange</animation> <visible>![Window.IsVisible(SliderDialog) | Window.IsVisible(OSDVideoSettings) | Window.IsVisible(OSDAudioSettings) | Window.IsVisible(VideoBookmarks) | Window.IsVisible(PVROSDChannels) | Window.IsVisible(PVROSDGuide)]</visible> <visible>VideoPlayer.Content(LiveTV)</visible> - <control type="button" id="350"> + <control type="button" id="354"> + <visible>VideoPlayer.IsStereoscopic</visible> <posx>0</posx> <posy>0</posy> <width>55</width> <height>55</height> + <label>36501</label> + <font>-</font> + <texturefocus>OSDStereoscopicFO.png</texturefocus> + <texturenofocus>OSDStereoscopicNF.png</texturenofocus> + <onleft>307</onleft> + <onright>350</onright> + <onup>551</onup> + <ondown>1000</ondown> + </control> + <control type="button" id="350"> + <posx>55</posx> + <posy>0</posy> + <width>55</width> + <height>55</height> <label>31356</label> <font>-</font> <texturefocus>OSDTeleTextFO.png</texturefocus> <texturenofocus>OSDTeleTextNF.png</texturenofocus> - <onleft>307</onleft> + <onleft>354</onleft> <onright>351</onright> <onup>1000</onup> <ondown>1000</ondown> <onclick>ActivateWindow(Teletext)</onclick> </control> <control type="button" id="351"> - <posx>55</posx> + <posx>110</posx> <posy>0</posy> <width>55</width> <height>55</height> @@ -411,7 +441,7 @@ <onclick>ActivateWindow(OSDVideoSettings)</onclick> </control> <control type="button" id="352"> - <posx>110</posx> + <posx>165</posx> <posy>0</posy> <width>55</width> <height>55</height> @@ -426,7 +456,7 @@ <onclick>ActivateWindow(OSDAudioSettings)</onclick> </control> <control type="togglebutton" id="353"> - <posx>165</posx> + <posx>220</posx> <posy>0</posy> <width>55</width> <height>55</height> @@ -568,5 +598,205 @@ <texture border="20,0,20,50">SubMenuBack-Footer.png</texture> </control> </control> + <!-- STEREOSCOPIC 3D !LiveTV --> + <control type="button" id="520"> + <description>Fake button for mouse control</description> + <posx>455r</posx> + <posy>350r</posy> + <width>256</width> + <height>300</height> + <label>-</label> + <font>-</font> + <texturenofocus>-</texturenofocus> + <texturefocus>-</texturefocus> + <visible>Control.HasFocus(520) | Control.HasFocus(255) | ControlGroup(500).HasFocus</visible> + </control> + <control type="grouplist" id="500"> + <visible>VideoPlayer.IsStereoscopic + ![Window.IsVisible(SliderDialog) | Window.IsVisible(OSDVideoSettings) | Window.IsVisible(OSDAudioSettings) | Window.IsVisible(VideoBookmarks)]</visible> + <animation effect="fade" time="200">VisibleChange</animation> + <posx>455r</posx> + <posy>350r</posy> + <width>256</width> + <height>300</height> + <align>bottom</align> + <itemgap>0</itemgap> + <onleft>500</onleft> + <onright>500</onright> + <onup>255</onup> + <ondown>255</ondown> + <orientation>vertical</orientation> + <visible>Control.HasFocus(255) | ControlGroup(500).HasFocus | Control.HasFocus(520)</visible> + <include>VisibleFadeEffect</include> + <control type="group"> + <description>Header</description> + <width>256</width> + <height>40</height> + <control type="image"> + <description>Header</description> + <posx>0</posx> + <posy>0</posy> + <width>256</width> + <height>40</height> + <texture border="20,18,20,0">SubMenuBack-Header.png</texture> + </control> + <control type="label" id=""> + <posx>30</posx> + <posy>20</posy> + <width>196</width> + <height>15</height> + <font>font12</font> + <label>36501</label> + <textcolor>blue</textcolor> + <align>center</align> + <aligny>center</aligny> + </control> + </control> + <control type="radiobutton" id="503"> + <height>40</height> + <width>256</width> + <textoffsetx>30</textoffsetx> + <aligny>center</aligny> + <font>font13</font> + <label>31362</label> + <radioposx>200</radioposx> + <texturefocus border="25,5,25,5">SubMenuBack-MiddleFO.png</texturefocus> + <texturenofocus border="25,5,25,5">SubMenuBack-MiddleNF.png</texturenofocus> + <onclick>ToggleStereoMode</onclick> + <selected>IntegerGreaterThan(System.StereoscopicMode,0)</selected> + <pulseonselect>false</pulseonselect> + </control> + <control type="button" id="502"> + <height>40</height> + <width>256</width> + <aligny>center</aligny> + <font>font13</font> + <textoffsetx>30</textoffsetx> + <texturefocus border="25,5,25,5">SubMenuBack-MiddleFO.png</texturefocus> + <texturenofocus border="25,5,25,5">SubMenuBack-MiddleNF.png</texturenofocus> + <pulseonselect>false</pulseonselect> + <label>31361</label> + <onclick>StereoMode</onclick> + </control> + <control type="radiobutton" id="501"> + <height>40</height> + <width>256</width> + <textoffsetx>30</textoffsetx> + <aligny>center</aligny> + <font>font13</font> + <label>31360</label> + <radioposx>200</radioposx> + <texturefocus border="25,5,25,5">SubMenuBack-MiddleFO.png</texturefocus> + <texturenofocus border="25,5,25,5">SubMenuBack-MiddleNF.png</texturenofocus> + <onclick>StereoModeToMono</onclick> + <selected>StringCompare(System.StereoscopicMode,7)</selected> + <pulseonselect>false</pulseonselect> + </control> + <control type="image" id="549"> + <description>Footer</description> + <width>256</width> + <height>52</height> + <texture border="20,0,20,50">SubMenuBack-Footer.png</texture> + </control> + </control> + <!-- STEREOSCOPIC 3D LiveTV --> + <control type="button" id="570"> + <description>Fake button for mouse control</description> + <posx>340r</posx> + <posy>350r</posy> + <width>256</width> + <height>300</height> + <label>-</label> + <font>-</font> + <texturenofocus>-</texturenofocus> + <texturefocus>-</texturefocus> + <visible>Control.HasFocus(570) | Control.HasFocus(354) | ControlGroup(550).HasFocus</visible> + </control> + <control type="grouplist" id="550"> + <visible>videoplayer.isstereoscopic + ![Window.IsVisible(SliderDialog) | Window.IsVisible(OSDVideoSettings) | Window.IsVisible(OSDAudioSettings) | Window.IsVisible(VideoBookmarks) | Window.IsVisible(PVROSDChannels) | Window.IsVisible(PVROSDGuide)]</visible> + <animation effect="fade" time="200">VisibleChange</animation> + <posx>340r</posx> + <posy>350r</posy> + <width>256</width> + <height>300</height> + <align>bottom</align> + <itemgap>0</itemgap> + <onleft>550</onleft> + <onright>550</onright> + <onup>354</onup> + <ondown>354</ondown> + <orientation>vertical</orientation> + <visible>Control.HasFocus(354) | ControlGroup(550).HasFocus | Control.HasFocus(570)</visible> + <include>VisibleFadeEffect</include> + <control type="group"> + <description>Header</description> + <width>256</width> + <height>40</height> + <control type="image"> + <description>Header</description> + <posx>0</posx> + <posy>0</posy> + <width>256</width> + <height>40</height> + <texture border="20,18,20,0">SubMenuBack-Header.png</texture> + </control> + <control type="label" id=""> + <posx>30</posx> + <posy>20</posy> + <width>196</width> + <height>15</height> + <font>font12</font> + <label>36501</label> + <textcolor>blue</textcolor> + <align>center</align> + <aligny>center</aligny> + </control> + </control> + <control type="radiobutton" id="553"> + <height>40</height> + <width>256</width> + <textoffsetx>30</textoffsetx> + <aligny>center</aligny> + <font>font13</font> + <label>31362</label> + <radioposx>200</radioposx> + <texturefocus border="25,5,25,5">SubMenuBack-MiddleFO.png</texturefocus> + <texturenofocus border="25,5,25,5">SubMenuBack-MiddleNF.png</texturenofocus> + <onclick>ToggleStereoMode</onclick> + <selected>IntegerGreaterThan(System.StereoscopicMode,0)</selected> + <pulseonselect>false</pulseonselect> + </control> + <control type="button" id="552"> + <height>40</height> + <width>256</width> + <aligny>center</aligny> + <font>font13</font> + <textoffsetx>30</textoffsetx> + <texturefocus border="25,5,25,5">SubMenuBack-MiddleFO.png</texturefocus> + <texturenofocus border="25,5,25,5">SubMenuBack-MiddleNF.png</texturenofocus> + <pulseonselect>false</pulseonselect> + <label>31361</label> + <onclick>StereoMode</onclick> + </control> + <control type="radiobutton" id="551"> + <height>40</height> + <width>256</width> + <textoffsetx>30</textoffsetx> + <aligny>center</aligny> + <font>font13</font> + <label>31360</label> + <radioposx>200</radioposx> + <texturefocus border="25,5,25,5">SubMenuBack-MiddleFO.png</texturefocus> + <texturenofocus border="25,5,25,5">SubMenuBack-MiddleNF.png</texturenofocus> + <onclick>StereoModeToMono</onclick> + <selected>StringCompare(System.StereoscopicMode,7)</selected> + <pulseonselect>false</pulseonselect> + </control> + <control type="image" id="599"> + <description>Footer</description> + <width>256</width> + <height>52</height> + <texture border="20,0,20,50">SubMenuBack-Footer.png</texture> + </control> + </control> </controls> - </window> +</window>
\ No newline at end of file diff --git a/addons/skin.confluence/language/English/strings.po b/addons/skin.confluence/language/English/strings.po index 793b66d8b4..310a997eb1 100644 --- a/addons/skin.confluence/language/English/strings.po +++ b/addons/skin.confluence/language/English/strings.po @@ -474,7 +474,21 @@ msgctxt "#31356" msgid "Download Subtitles" msgstr "" -#empty strings from id 31357 to 31389 +#empty strings from id 31357 to 31358 +# Stereoscopic labels +msgctxt "#31360" +msgid "Watch as 2D" +msgstr "" + +msgctxt "#31361" +msgid "Change mode" +msgstr "" + +msgctxt "#31362" +msgid "Enabled" +msgstr "" + +#empty strings from id 3136 to 31389 msgctxt "#31390" msgid "Skin default" diff --git a/addons/skin.confluence/media/OSDStereoscopicFO.png b/addons/skin.confluence/media/OSDStereoscopicFO.png Binary files differnew file mode 100644 index 0000000000..70fc9523fc --- /dev/null +++ b/addons/skin.confluence/media/OSDStereoscopicFO.png diff --git a/addons/skin.confluence/media/OSDStereoscopicNF.png b/addons/skin.confluence/media/OSDStereoscopicNF.png Binary files differnew file mode 100644 index 0000000000..8d45542b64 --- /dev/null +++ b/addons/skin.confluence/media/OSDStereoscopicNF.png diff --git a/language/English/strings.po b/language/English/strings.po index 6fbd2697dc..e893090bf6 100644 --- a/language/English/strings.po +++ b/language/English/strings.po @@ -14145,9 +14145,133 @@ msgctxt "#36420" msgid "No info available yet." msgstr "" -#empty strings from id 36421 to 36999 +#empty strings from id 36421 to 36499 #end reservation +#: system/settings/settings.xml +msgctxt "#36500" +msgid "Stereoscopic mode (current)" +msgstr "" + +#: guilib/StereoscopicsManager.cpp +msgctxt "#36501" +msgid "Stereoscopic mode" +msgstr "" + +#: system/settings/settings.xml +msgctxt "#36502" +msgid "None" +msgstr "" + +#: system/settings/settings.xml +msgctxt "#36503" +msgid "Over/Under" +msgstr "" + +#: system/settings/settings.xml +msgctxt "#36504" +msgid "Side by side" +msgstr "" + +#: system/settings/settings.xml +msgctxt "#36505" +msgid "Anaglyph Red/Cyan" +msgstr "" + +#: system/settings/settings.xml +msgctxt "#36506" +msgid "Anaglyph Green/Magenta" +msgstr "" + +#: system/settings/settings.xml +msgctxt "#36507" +msgid "Interlaced" +msgstr "" + +#: system/settings/settings.xml +msgctxt "#36508" +msgid "Hardware Based" +msgstr "" + +#: system/settings/settings.xml +msgctxt "#36509" +msgid "Monoscopic - 2D" +msgstr "" + +#reserved strings for 3d modes 36509 - 36520 + +#: system/settings/settings.xml +msgctxt "#36520" +msgid "Playback mode of stereoscopic videos" +msgstr "" + +#: system/settings/settings.xml +msgctxt "#36521" +msgid "Ask me" +msgstr "" + +#: system/settings/settings.xml +msgctxt "#36522" +msgid "Use preferred mode" +msgstr "" + +#: system/settings/settings.xml +msgctxt "#36524" +msgid "Preferred mode" +msgstr "" + +#: settings/DisplaySettings.cpp +msgctxt "#36525" +msgid "Same as movie (autodetect)" +msgstr "" + +#: guilib/StereoscopicsManager.cpp +msgctxt "#36526" +msgid "Disable stereoscopic mode when playback is stopped" +msgstr "" + +#: guilib/StereoscopicsManager.cpp +msgctxt "#36527" +msgid "This video is stereoscopic. Select playback mode" +msgstr "" + +#: system/settings/settings.xml +msgctxt "#36528" +msgid "Select stereoscopic mode" +msgstr "" + +#: guilib/StereoscopicsManager.cpp +msgctxt "#36529" +msgid "Mono (2D)" +msgstr "" + +#: guilib/StereoscopicsManager.cpp +msgctxt "#36530" +msgid "Preferred mode" +msgstr "" + +#: guilib/StereoscopicsManager.cpp +msgctxt "#36531" +msgid "Select alternate mode..." +msgstr "" + +#: settings/DisplaySettings.cpp +msgctxt "#36532" +msgid "Same as movie" +msgstr "" + +#: guilib/StereoscopicsManager.cpp +msgctxt "#36535" +msgid "Stereoscopic mode of video" +msgstr "" + +#: guilib/StereoscopicsManager.cpp +msgctxt "#36536" +msgid "Stereoscopic mode inverted" +msgstr "" + +#reserved strings 365XX + #: xbmc/cores/dvdplayer/DVDInputStreams/DVDInputStreamNavigator.cpp msgctxt "#37000" msgid "(Visually Impaired)" diff --git a/lib/DllAvCodec.h b/lib/DllAvCodec.h index a71f9cfac3..d1360608c1 100644 --- a/lib/DllAvCodec.h +++ b/lib/DllAvCodec.h @@ -98,6 +98,7 @@ public: virtual int avcodec_fill_audio_frame(AVFrame *frame, int nb_channels, enum AVSampleFormat sample_fmt, const uint8_t *buf, int buf_size, int align) = 0; virtual void avcodec_free_frame(AVFrame **frame)=0; virtual int av_codec_is_decoder(const AVCodec *codec)=0; + virtual AVDictionary* av_frame_get_metadata(const AVFrame* frame)=0; }; #if (defined USE_EXTERNAL_FFMPEG) || (defined TARGET_DARWIN) @@ -167,6 +168,7 @@ public: virtual int avcodec_fill_audio_frame(AVFrame *frame, int nb_channels, enum AVSampleFormat sample_fmt, const uint8_t *buf, int buf_size, int align) { return ::avcodec_fill_audio_frame(frame, nb_channels, sample_fmt, buf, buf_size, align); } virtual void avcodec_free_frame(AVFrame **frame) { return ::avcodec_free_frame(frame); }; virtual int av_codec_is_decoder(const AVCodec *codec) { return ::av_codec_is_decoder(codec); } + virtual AVDictionary* av_frame_get_metadata(const AVFrame* frame) { return ::av_frame_get_metadata(frame); } // DLL faking. virtual bool ResolveExports() { return true; } @@ -217,6 +219,7 @@ class DllAvCodec : public DllDynamic, DllAvCodecInterface DEFINE_METHOD1(void, avcodec_free_frame, (AVFrame **p1)) DEFINE_METHOD1(AVCodec*, av_codec_next, (AVCodec *p1)) DEFINE_METHOD1(int, av_codec_is_decoder, (const AVCodec *p1)) + DEFINE_METHOD1(AVDictionary*, av_frame_get_metadata, (const AVFrame* p1)) BEGIN_METHOD_RESOLVE() RESOLVE_METHOD(avcodec_flush_buffers) @@ -251,6 +254,7 @@ class DllAvCodec : public DllDynamic, DllAvCodecInterface RESOLVE_METHOD(avcodec_fill_audio_frame) RESOLVE_METHOD(avcodec_free_frame) RESOLVE_METHOD(av_codec_is_decoder) + RESOLVE_METHOD(av_frame_get_metadata) END_METHOD_RESOLVE() /* dependencies of libavcodec */ diff --git a/lib/ffmpeg/libavcodec/h264.c b/lib/ffmpeg/libavcodec/h264.c index 937ad7a3e2..85f2372e2e 100644 --- a/lib/ffmpeg/libavcodec/h264.c +++ b/lib/ffmpeg/libavcodec/h264.c @@ -1437,6 +1437,7 @@ av_cold int ff_h264_decode_init(AVCodecContext *avctx) h->prev_poc_msb = 1 << 16; h->prev_frame_num = -1; h->x264_build = -1; + h->sei_fpa.frame_packing_arrangement_cancel_flag = -1; ff_h264_reset_sei(h); if (avctx->codec_id == AV_CODEC_ID_H264) { if (avctx->ticks_per_frame == 1) { @@ -4783,6 +4784,7 @@ static int decode_frame(AVCodecContext *avctx, void *data, out->f.reference &= ~DELAYED_PIC_REF; *got_frame = 1; *pict = out->f; + av_dict_set(&pict->metadata, "stereo_mode", ff_h264_sei_stereo_mode(h), 0); } return buf_index; @@ -4839,6 +4841,7 @@ not_extra: if (h->next_output_pic && (h->next_output_pic->sync || h->sync>1)) { *got_frame = 1; *pict = h->next_output_pic->f; + av_dict_set(&pict->metadata, "stereo_mode", ff_h264_sei_stereo_mode(h), 0); } } diff --git a/lib/ffmpeg/libavcodec/h264.h b/lib/ffmpeg/libavcodec/h264.h index 7ea613c6f3..15a0b212fb 100644 --- a/lib/ffmpeg/libavcodec/h264.h +++ b/lib/ffmpeg/libavcodec/h264.h @@ -126,7 +126,8 @@ typedef enum { SEI_TYPE_PIC_TIMING = 1, ///< picture timing SEI_TYPE_USER_DATA_ITU_T_T35 = 4, ///< user data registered by ITU-T Recommendation T.35 SEI_TYPE_USER_DATA_UNREGISTERED = 5, ///< unregistered user data - SEI_TYPE_RECOVERY_POINT = 6 ///< recovery point (frame # to decoder sync) + SEI_TYPE_RECOVERY_POINT = 6, ///< recovery point (frame # to decoder sync) + SEI_TYPE_FRAME_PACKING = 45, ///< frame packing arrangement } SEI_Type; /** @@ -145,6 +146,19 @@ typedef enum { } SEI_PicStructType; /** + * frame_packing_arrangement types + */ +typedef enum { + SEI_FPA_TYPE_CHECKERBOARD = 0, + SEI_FPA_TYPE_INTERLEAVE_COLUMN = 1, + SEI_FPA_TYPE_INTERLEAVE_ROW = 2, + SEI_FPA_TYPE_SIDE_BY_SIDE = 3, + SEI_FPA_TYPE_TOP_BOTTOM = 4, + SEI_FPA_TYPE_INTERLEAVE_TEMPORAL = 5, + SEI_FPA_TYPE_2D = 6, +} SEI_FpaType; + +/** * Sequence parameter set */ typedef struct SPS { @@ -230,6 +244,17 @@ typedef struct PPS { } PPS; /** + * Frame Packing Arrangement Type + */ +typedef struct FPA { + int frame_packing_arrangement_id; + int frame_packing_arrangement_cancel_flag; ///< is previous arrangement canceled, -1 if never received + SEI_FpaType frame_packing_arrangement_type; + int content_interpretation_type; + int quincunx_sampling_flag; +} FPA; + +/** * Memory management control operation opcode. */ typedef enum MMCOOpcode { @@ -626,6 +651,8 @@ typedef struct H264Context { */ int valid_recovery_point; + FPA sei_fpa; + int luma_weight_flag[2]; ///< 7.4.3.2 luma_weight_lX_flag int chroma_weight_flag[2]; ///< 7.4.3.2 chroma_weight_lX_flag @@ -771,6 +798,12 @@ void ff_h264_filter_mb(H264Context *h, int mb_x, int mb_y, */ void ff_h264_reset_sei(H264Context *h); +/** + * Get stereo_mode string from the h264 frame_packing_arrangement + * @param h H.264 context. + */ +const char* ff_h264_sei_stereo_mode(H264Context *h); + /* * o-o o-o * / / / diff --git a/lib/ffmpeg/libavcodec/h264_parser.c b/lib/ffmpeg/libavcodec/h264_parser.c index 44b92b79e3..aff9ba17f0 100644 --- a/lib/ffmpeg/libavcodec/h264_parser.c +++ b/lib/ffmpeg/libavcodec/h264_parser.c @@ -158,6 +158,7 @@ static inline int parse_nal_units(AVCodecParserContext *s, h->sei_dpb_output_delay = 0; h->sei_cpb_removal_delay = -1; h->sei_buffering_period_present = 0; + h->sei_fpa.frame_packing_arrangement_cancel_flag = -1; if (!buf_size) return 0; diff --git a/lib/ffmpeg/libavcodec/h264_sei.c b/lib/ffmpeg/libavcodec/h264_sei.c index ece54f1007..fc9b96f71e 100644 --- a/lib/ffmpeg/libavcodec/h264_sei.c +++ b/lib/ffmpeg/libavcodec/h264_sei.c @@ -194,6 +194,43 @@ static int decode_buffering_period(H264Context *h){ return 0; } +static int decode_frame_packing(H264Context *h, int size){ + int bits = get_bits_left(&h->gb); + + h->sei_fpa.frame_packing_arrangement_id = get_ue_golomb(&h->gb); + h->sei_fpa.frame_packing_arrangement_cancel_flag = get_bits(&h->gb, 1); + if (!h->sei_fpa.frame_packing_arrangement_cancel_flag) { + h->sei_fpa.frame_packing_arrangement_type = get_bits(&h->gb, 7); + h->sei_fpa.quincunx_sampling_flag = get_bits(&h->gb, 1); + h->sei_fpa.content_interpretation_type = get_bits(&h->gb, 6); + skip_bits(&h->gb, 1); /* spatial_flipping_flag */ + skip_bits(&h->gb, 1); /* frame0_flipped_flag */ + skip_bits(&h->gb, 1); /* field_views_flag */ + skip_bits(&h->gb, 1); /* current_frame_is_frame0_flag */ + skip_bits(&h->gb, 1); /* frame0_self_contained_flag */ + skip_bits(&h->gb, 1); /* frame1_self_contained_flag */ + if (!h->sei_fpa.quincunx_sampling_flag && h->sei_fpa.frame_packing_arrangement_type != 5) { + skip_bits(&h->gb, 4); /* frame0_grid_position_x */ + skip_bits(&h->gb, 4); /* frame0_grid_position_y */ + skip_bits(&h->gb, 4); /* frame1_grid_position_x */ + skip_bits(&h->gb, 4); /* frame1_grid_position_y */ + } + skip_bits(&h->gb, 8); /* frame_packing_arrangement_reserved_byte */ + get_ue_golomb(&h->gb) /* frame_packing_arrangement_repetition_period */; + } + skip_bits(&h->gb, 1); /* frame_packing_arrangement_extension_flag */ + + if (h->avctx->debug & FF_DEBUG_PICT_INFO) + av_log(h->avctx, AV_LOG_DEBUG, "SEI FPA %d %d %d %d %d\n", + h->sei_fpa.frame_packing_arrangement_id, + h->sei_fpa.frame_packing_arrangement_cancel_flag, + h->sei_fpa.frame_packing_arrangement_type, + h->sei_fpa.quincunx_sampling_flag, + h->sei_fpa.content_interpretation_type); + skip_bits(&h->gb, 8*size - (bits - get_bits_left(&h->gb))); + return 0; +} + int ff_h264_decode_sei(H264Context *h){ while (get_bits_left(&h->gb) > 16) { int size, type; @@ -236,6 +273,9 @@ int ff_h264_decode_sei(H264Context *h){ if(decode_buffering_period(h) < 0) return -1; break; + case SEI_TYPE_FRAME_PACKING: + if(decode_frame_packing(h, size) < 0) + return -1; default: skip_bits(&h->gb, 8*size); } @@ -246,3 +286,48 @@ int ff_h264_decode_sei(H264Context *h){ return 0; } + +const char* ff_h264_sei_stereo_mode(H264Context *h) +{ + if (h->sei_fpa.frame_packing_arrangement_cancel_flag == 0) { + switch (h->sei_fpa.frame_packing_arrangement_type) { + case SEI_FPA_TYPE_CHECKERBOARD: + if (h->sei_fpa.content_interpretation_type == 2) + return "checkerboard_rl"; + else + return "checkerboard_lr"; + case SEI_FPA_TYPE_INTERLEAVE_COLUMN: + if (h->sei_fpa.content_interpretation_type == 2) + return "col_interleaved_rl"; + else + return "col_interleaved_lr"; + case SEI_FPA_TYPE_INTERLEAVE_ROW: + if (h->sei_fpa.content_interpretation_type == 2) + return "row_interleaved_rl"; + else + return "row_interleaved_lr"; + case SEI_FPA_TYPE_SIDE_BY_SIDE: + if (h->sei_fpa.content_interpretation_type == 2) + return "right_left"; + else + return "left_right"; + case SEI_FPA_TYPE_TOP_BOTTOM: + if (h->sei_fpa.content_interpretation_type == 2) + return "bottom_top"; + else + return "top_bottom"; + case SEI_FPA_TYPE_INTERLEAVE_TEMPORAL: + if (h->sei_fpa.content_interpretation_type == 2) + return "block_rl"; + else + return "block_lr"; + case SEI_FPA_TYPE_2D: + default: + return "mono"; + } + } else if (h->sei_fpa.frame_packing_arrangement_cancel_flag == 1) { + return "mono"; + } else { + return NULL; + } +} diff --git a/lib/ffmpeg/patches/0039-h264-expose-h264-frame-packing-as-stereo_mode-metada.patch b/lib/ffmpeg/patches/0039-h264-expose-h264-frame-packing-as-stereo_mode-metada.patch new file mode 100644 index 0000000000..5c6384f87c --- /dev/null +++ b/lib/ffmpeg/patches/0039-h264-expose-h264-frame-packing-as-stereo_mode-metada.patch @@ -0,0 +1,236 @@ +From 3a6ea59e122d5bc981a2a5c8f9bafcba0f9f8754 Mon Sep 17 00:00:00 2001 +From: Joakim Plate <elupus@ecce.se> +Date: Wed, 26 Jun 2013 22:07:28 +0200 +Subject: [PATCH 1/1] h264: expose h264 frame packing as stereo_mode metadata + +--- + libavcodec/h264.c | 3 ++ + libavcodec/h264.h | 35 ++++++++++++++- + libavcodec/h264_parser.c | 1 + + libavcodec/h264_sei.c | 85 +++++++++++++++++++++++++++++++++++++ + 4 files changed, 123 insertions(+), 1 deletion(-) + +diff --git a/libavcodec/h264.c b/libavcodec/h264.c +index 937ad7a..85f2372 100644 +--- a/libavcodec/h264.c ++++ b/libavcodec/h264.c +@@ -1437,6 +1437,7 @@ av_cold int ff_h264_decode_init(AVCodecContext *avctx) + h->prev_poc_msb = 1 << 16; + h->prev_frame_num = -1; + h->x264_build = -1; ++ h->sei_fpa.frame_packing_arrangement_cancel_flag = -1; + ff_h264_reset_sei(h); + if (avctx->codec_id == AV_CODEC_ID_H264) { + if (avctx->ticks_per_frame == 1) { +@@ -4783,6 +4784,7 @@ static int decode_frame(AVCodecContext *avctx, void *data, + out->f.reference &= ~DELAYED_PIC_REF; + *got_frame = 1; + *pict = out->f; ++ av_dict_set(&pict->metadata, "stereo_mode", ff_h264_sei_stereo_mode(h), 0); + } + + return buf_index; +@@ -4839,6 +4841,7 @@ not_extra: + if (h->next_output_pic && (h->next_output_pic->sync || h->sync>1)) { + *got_frame = 1; + *pict = h->next_output_pic->f; ++ av_dict_set(&pict->metadata, "stereo_mode", ff_h264_sei_stereo_mode(h), 0); + } + } + +diff --git a/libavcodec/h264.h b/libavcodec/h264.h +index 7ea613c..15a0b21 100644 +--- a/libavcodec/h264.h ++++ b/libavcodec/h264.h +@@ -126,7 +126,8 @@ typedef enum { + SEI_TYPE_PIC_TIMING = 1, ///< picture timing + SEI_TYPE_USER_DATA_ITU_T_T35 = 4, ///< user data registered by ITU-T Recommendation T.35 + SEI_TYPE_USER_DATA_UNREGISTERED = 5, ///< unregistered user data +- SEI_TYPE_RECOVERY_POINT = 6 ///< recovery point (frame # to decoder sync) ++ SEI_TYPE_RECOVERY_POINT = 6, ///< recovery point (frame # to decoder sync) ++ SEI_TYPE_FRAME_PACKING = 45, ///< frame packing arrangement + } SEI_Type; + + /** +@@ -145,6 +146,19 @@ typedef enum { + } SEI_PicStructType; + + /** ++ * frame_packing_arrangement types ++ */ ++typedef enum { ++ SEI_FPA_TYPE_CHECKERBOARD = 0, ++ SEI_FPA_TYPE_INTERLEAVE_COLUMN = 1, ++ SEI_FPA_TYPE_INTERLEAVE_ROW = 2, ++ SEI_FPA_TYPE_SIDE_BY_SIDE = 3, ++ SEI_FPA_TYPE_TOP_BOTTOM = 4, ++ SEI_FPA_TYPE_INTERLEAVE_TEMPORAL = 5, ++ SEI_FPA_TYPE_2D = 6, ++} SEI_FpaType; ++ ++/** + * Sequence parameter set + */ + typedef struct SPS { +@@ -230,6 +244,17 @@ typedef struct PPS { + } PPS; + + /** ++ * Frame Packing Arrangement Type ++ */ ++typedef struct FPA { ++ int frame_packing_arrangement_id; ++ int frame_packing_arrangement_cancel_flag; ///< is previous arrangement canceled, -1 if never received ++ SEI_FpaType frame_packing_arrangement_type; ++ int content_interpretation_type; ++ int quincunx_sampling_flag; ++} FPA; ++ ++/** + * Memory management control operation opcode. + */ + typedef enum MMCOOpcode { +@@ -626,6 +651,8 @@ typedef struct H264Context { + */ + int valid_recovery_point; + ++ FPA sei_fpa; ++ + int luma_weight_flag[2]; ///< 7.4.3.2 luma_weight_lX_flag + int chroma_weight_flag[2]; ///< 7.4.3.2 chroma_weight_lX_flag + +@@ -771,6 +798,12 @@ void ff_h264_filter_mb(H264Context *h, int mb_x, int mb_y, + */ + void ff_h264_reset_sei(H264Context *h); + ++/** ++ * Get stereo_mode string from the h264 frame_packing_arrangement ++ * @param h H.264 context. ++ */ ++const char* ff_h264_sei_stereo_mode(H264Context *h); ++ + /* + * o-o o-o + * / / / +diff --git a/libavcodec/h264_parser.c b/libavcodec/h264_parser.c +index 44b92b7..aff9ba1 100644 +--- a/libavcodec/h264_parser.c ++++ b/libavcodec/h264_parser.c +@@ -158,6 +158,7 @@ static inline int parse_nal_units(AVCodecParserContext *s, + h->sei_dpb_output_delay = 0; + h->sei_cpb_removal_delay = -1; + h->sei_buffering_period_present = 0; ++ h->sei_fpa.frame_packing_arrangement_cancel_flag = -1; + + if (!buf_size) + return 0; +diff --git a/libavcodec/h264_sei.c b/libavcodec/h264_sei.c +index ece54f1..fc9b96f 100644 +--- a/libavcodec/h264_sei.c ++++ b/libavcodec/h264_sei.c +@@ -194,6 +194,43 @@ static int decode_buffering_period(H264Context *h){ + return 0; + } + ++static int decode_frame_packing(H264Context *h, int size){ ++ int bits = get_bits_left(&h->gb); ++ ++ h->sei_fpa.frame_packing_arrangement_id = get_ue_golomb(&h->gb); ++ h->sei_fpa.frame_packing_arrangement_cancel_flag = get_bits(&h->gb, 1); ++ if (!h->sei_fpa.frame_packing_arrangement_cancel_flag) { ++ h->sei_fpa.frame_packing_arrangement_type = get_bits(&h->gb, 7); ++ h->sei_fpa.quincunx_sampling_flag = get_bits(&h->gb, 1); ++ h->sei_fpa.content_interpretation_type = get_bits(&h->gb, 6); ++ skip_bits(&h->gb, 1); /* spatial_flipping_flag */ ++ skip_bits(&h->gb, 1); /* frame0_flipped_flag */ ++ skip_bits(&h->gb, 1); /* field_views_flag */ ++ skip_bits(&h->gb, 1); /* current_frame_is_frame0_flag */ ++ skip_bits(&h->gb, 1); /* frame0_self_contained_flag */ ++ skip_bits(&h->gb, 1); /* frame1_self_contained_flag */ ++ if (!h->sei_fpa.quincunx_sampling_flag && h->sei_fpa.frame_packing_arrangement_type != 5) { ++ skip_bits(&h->gb, 4); /* frame0_grid_position_x */ ++ skip_bits(&h->gb, 4); /* frame0_grid_position_y */ ++ skip_bits(&h->gb, 4); /* frame1_grid_position_x */ ++ skip_bits(&h->gb, 4); /* frame1_grid_position_y */ ++ } ++ skip_bits(&h->gb, 8); /* frame_packing_arrangement_reserved_byte */ ++ get_ue_golomb(&h->gb) /* frame_packing_arrangement_repetition_period */; ++ } ++ skip_bits(&h->gb, 1); /* frame_packing_arrangement_extension_flag */ ++ ++ if (h->avctx->debug & FF_DEBUG_PICT_INFO) ++ av_log(h->avctx, AV_LOG_DEBUG, "SEI FPA %d %d %d %d %d\n", ++ h->sei_fpa.frame_packing_arrangement_id, ++ h->sei_fpa.frame_packing_arrangement_cancel_flag, ++ h->sei_fpa.frame_packing_arrangement_type, ++ h->sei_fpa.quincunx_sampling_flag, ++ h->sei_fpa.content_interpretation_type); ++ skip_bits(&h->gb, 8*size - (bits - get_bits_left(&h->gb))); ++ return 0; ++} ++ + int ff_h264_decode_sei(H264Context *h){ + while (get_bits_left(&h->gb) > 16) { + int size, type; +@@ -236,6 +273,9 @@ int ff_h264_decode_sei(H264Context *h){ + if(decode_buffering_period(h) < 0) + return -1; + break; ++ case SEI_TYPE_FRAME_PACKING: ++ if(decode_frame_packing(h, size) < 0) ++ return -1; + default: + skip_bits(&h->gb, 8*size); + } +@@ -246,3 +286,48 @@ int ff_h264_decode_sei(H264Context *h){ + + return 0; + } ++ ++const char* ff_h264_sei_stereo_mode(H264Context *h) ++{ ++ if (h->sei_fpa.frame_packing_arrangement_cancel_flag == 0) { ++ switch (h->sei_fpa.frame_packing_arrangement_type) { ++ case SEI_FPA_TYPE_CHECKERBOARD: ++ if (h->sei_fpa.content_interpretation_type == 2) ++ return "checkerboard_rl"; ++ else ++ return "checkerboard_lr"; ++ case SEI_FPA_TYPE_INTERLEAVE_COLUMN: ++ if (h->sei_fpa.content_interpretation_type == 2) ++ return "col_interleaved_rl"; ++ else ++ return "col_interleaved_lr"; ++ case SEI_FPA_TYPE_INTERLEAVE_ROW: ++ if (h->sei_fpa.content_interpretation_type == 2) ++ return "row_interleaved_rl"; ++ else ++ return "row_interleaved_lr"; ++ case SEI_FPA_TYPE_SIDE_BY_SIDE: ++ if (h->sei_fpa.content_interpretation_type == 2) ++ return "right_left"; ++ else ++ return "left_right"; ++ case SEI_FPA_TYPE_TOP_BOTTOM: ++ if (h->sei_fpa.content_interpretation_type == 2) ++ return "bottom_top"; ++ else ++ return "top_bottom"; ++ case SEI_FPA_TYPE_INTERLEAVE_TEMPORAL: ++ if (h->sei_fpa.content_interpretation_type == 2) ++ return "block_rl"; ++ else ++ return "block_lr"; ++ case SEI_FPA_TYPE_2D: ++ default: ++ return "mono"; ++ } ++ } else if (h->sei_fpa.frame_packing_arrangement_cancel_flag == 1) { ++ return "mono"; ++ } else { ++ return NULL; ++ } ++} +-- +1.8.2 + diff --git a/project/VS2010Express/XBMC.vcxproj b/project/VS2010Express/XBMC.vcxproj index e06fb25bdc..32f29fdd87 100644 --- a/project/VS2010Express/XBMC.vcxproj +++ b/project/VS2010Express/XBMC.vcxproj @@ -692,6 +692,7 @@ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug Testsuite|Win32'">true</ExcludedFromBuild> <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release (DirectX)|Win32'">true</ExcludedFromBuild> </ClCompile> + <ClCompile Include="..\..\xbmc\guilib\StereoscopicsManager.cpp" /> <ClCompile Include="..\..\xbmc\guilib\Texture.cpp" /> <ClCompile Include="..\..\xbmc\guilib\TextureBundle.cpp" /> <ClCompile Include="..\..\xbmc\guilib\TextureBundleXBT.cpp" /> @@ -1910,6 +1911,7 @@ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release (DirectX)|Win32'">true</ExcludedFromBuild> </ClCompile> <ClCompile Include="..\..\xbmc\cores\VideoRenderers\OverlayRendererUtil.cpp" /> + <ClCompile Include="..\..\xbmc\cores\VideoRenderers\RenderFlags.cpp" /> <ClCompile Include="..\..\xbmc\cores\VideoRenderers\RenderManager.cpp" /> <ClCompile Include="..\..\xbmc\cores\VideoRenderers\WinRenderer.cpp" /> <ClCompile Include="..\..\xbmc\cores\VideoRenderers\VideoShaders\ConvolutionKernels.cpp" /> @@ -2205,6 +2207,7 @@ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug Testsuite|Win32'">true</ExcludedFromBuild> <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release (DirectX)|Win32'">true</ExcludedFromBuild> </ClInclude> + <ClInclude Include="..\..\xbmc\guilib\StereoscopicsManager.h" /> <ClInclude Include="..\..\xbmc\guilib\Texture.h" /> <ClInclude Include="..\..\xbmc\guilib\TextureBundle.h" /> <ClInclude Include="..\..\xbmc\guilib\TextureBundleXBT.h" /> @@ -2724,6 +2727,7 @@ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release (DirectX)|Win32'">true</ExcludedFromBuild> </ClInclude> <ClInclude Include="..\..\xbmc\cores\VideoRenderers\OverlayRendererUtil.h" /> + <ClInclude Include="..\..\xbmc\cores\VideoRenderers\RenderFlags.h" /> <ClInclude Include="..\..\xbmc\cores\VideoRenderers\RenderManager.h" /> <ClInclude Include="..\..\xbmc\cores\VideoRenderers\WinRenderer.h" /> <ClInclude Include="..\..\xbmc\cores\VideoRenderers\VideoShaders\ConvolutionKernels.h" /> @@ -2990,4 +2994,4 @@ </VisualStudio> </ProjectExtensions> <Import Project="$(SolutionDir)\$(ProjectFileName).targets.user" Condition="Exists('$(SolutionDir)\$(ProjectFileName).targets.user')" /> -</Project>
\ No newline at end of file +</Project> diff --git a/project/VS2010Express/XBMC.vcxproj.filters b/project/VS2010Express/XBMC.vcxproj.filters index 3b2c73da82..85b11d2cca 100644 --- a/project/VS2010Express/XBMC.vcxproj.filters +++ b/project/VS2010Express/XBMC.vcxproj.filters @@ -648,6 +648,9 @@ <ClCompile Include="..\..\xbmc\cores\VideoRenderers\OverlayRendererUtil.cpp"> <Filter>cores\VideoRenderers</Filter> </ClCompile> + <ClCompile Include="..\..\xbmc\cores\VideoRenderers\RenderFlags.cpp"> + <Filter>cores\VideoRenderers</Filter> + </ClCompile> <ClCompile Include="..\..\xbmc\cores\VideoRenderers\RenderManager.cpp"> <Filter>cores\VideoRenderers</Filter> </ClCompile> @@ -2400,6 +2403,9 @@ <ClCompile Include="..\..\xbmc\guilib\GUITexture.cpp"> <Filter>guilib</Filter> </ClCompile> + <ClCompile Include="..\..\xbmc\guilib\StereoscopicsManager.cpp"> + <Filter>guilib</Filter> + </ClCompile> <ClCompile Include="..\..\xbmc\guilib\Texture.cpp"> <Filter>guilib</Filter> </ClCompile> @@ -3530,6 +3536,9 @@ <ClInclude Include="..\..\xbmc\cores\VideoRenderers\OverlayRendererUtil.h"> <Filter>cores\VideoRenderers</Filter> </ClInclude> + <ClInclude Include="..\..\xbmc\cores\VideoRenderers\RenderFlags.h"> + <Filter>cores\VideoRenderers</Filter> + </ClInclude> <ClInclude Include="..\..\xbmc\cores\VideoRenderers\RenderManager.h"> <Filter>cores\VideoRenderers</Filter> </ClInclude> @@ -5466,6 +5475,9 @@ <ClInclude Include="..\..\xbmc\guilib\GUITexture.h"> <Filter>guilib</Filter> </ClInclude> + <ClInclude Include="..\..\xbmc\guilib\StereoscopicsManager.h"> + <Filter>guilib</Filter> + </ClInclude> <ClInclude Include="..\..\xbmc\guilib\Texture.h"> <Filter>guilib</Filter> </ClInclude> @@ -6046,4 +6058,4 @@ <Filter>interfaces\swig</Filter> </None> </ItemGroup> -</Project>
\ No newline at end of file +</Project> diff --git a/system/settings/settings.xml b/system/settings/settings.xml index 32573dcfd0..a6218f64ff 100644 --- a/system/settings/settings.xml +++ b/system/settings/settings.xml @@ -547,6 +547,23 @@ <default>true</default> </setting> </group> + <group id="5"> + <setting id="videoplayer.stereoscopicplaybackmode" type="integer" label="36520" help=""> + <level>2</level> + <default>0</default> + <constraints> + <options> + <option label="36521">0</option> <!-- ASK --> + <option label="36522">1</option> <!-- Preferred mode --> + </options> + </constraints> + <control type="spinner" format="integer" delayed="true"/> + </setting> + <setting id="videoplayer.quitstereomodeonstop" type="boolean" label="36526" help=""> + <level>2</level> + <default>true</default> + </setting> + </group> </category> <category id="myvideos" label="14081" help="36176"> <group id="1"> @@ -1893,6 +1910,24 @@ </setting> </group> <group id="2"> + <setting id="videoscreen.stereoscopicmode" type="integer" label="36500" help=""> + <level>2</level> + <default>0</default> + <constraints> + <options>stereoscopicmodes</options> + </constraints> + <control type="list" format="integer"/> + </setting> + <setting id="videoscreen.preferedstereoscopicmode" parent="videoscreen.stereoscopicmode" type="integer" label="36524" help=""> + <level>2</level> + <default>0</default> + <constraints> + <options>preferedstereoscopicviewmodes</options> + </constraints> + <control type="list" format="integer"/> + </setting> + </group> + <group id="3"> <setting id="videoscreen.vsync" type="integer" label="13105" help="36356"> <level>2</level> <default>3</default> <!-- VSYNC_DRIVER --> diff --git a/xbmc/Application.cpp b/xbmc/Application.cpp index 7972df36d9..b4fa73b43a 100644 --- a/xbmc/Application.cpp +++ b/xbmc/Application.cpp @@ -44,6 +44,7 @@ #include "playlists/PlayListFactory.h" #include "guilib/GUIFontManager.h" #include "guilib/GUIColorManager.h" +#include "guilib/StereoscopicsManager.h" #include "guilib/GUITextLayout.h" #include "addons/Skin.h" #include "interfaces/generic/ScriptInvocationManager.h" @@ -939,11 +940,11 @@ bool CApplication::CreateGUI() if (!CButtonTranslator::GetInstance().Load()) return false; - int iResolution = g_graphicsContext.GetVideoResolution(); + RESOLUTION_INFO info = g_graphicsContext.GetResInfo(); CLog::Log(LOGINFO, "GUI format %ix%i, Display %s", - CDisplaySettings::Get().GetResolutionInfo(iResolution).iWidth, - CDisplaySettings::Get().GetResolutionInfo(iResolution).iHeight, - CDisplaySettings::Get().GetResolutionInfo(iResolution).strMode.c_str()); + info.iWidth, + info.iHeight, + info.strMode.c_str()); g_windowManager.Initialize(); return true; @@ -1414,6 +1415,8 @@ bool CApplication::Initialize() StartPVRManager(false); g_windowManager.ActivateWindow(g_SkinInfo->GetFirstWindow()); } + + CStereoscopicsManager::Get().Initialize(); } } @@ -1846,6 +1849,7 @@ void CApplication::LoadSkin(const SkinPtr& skin) g_windowManager.AddMsgTarget(&g_playlistPlayer); g_windowManager.AddMsgTarget(&g_infoManager); g_windowManager.AddMsgTarget(&g_fontManager); + g_windowManager.AddMsgTarget(&CStereoscopicsManager::Get()); g_windowManager.SetCallback(*this); g_windowManager.Initialize(); CTextureCache::Get().Initialize(); @@ -2115,8 +2119,25 @@ void CApplication::Render() g_renderManager.FrameMove(); CDirtyRegionList dirtyRegions = g_windowManager.GetDirty(); - if (RenderNoPresent()) - hasRendered = true; + if(g_graphicsContext.GetStereoMode()) + { + g_graphicsContext.SetStereoView(RENDER_STEREO_VIEW_LEFT); + if(RenderNoPresent()) + hasRendered = true; + + if(g_graphicsContext.GetStereoMode() != RENDER_STEREO_MODE_MONO) + { + g_graphicsContext.SetStereoView(RENDER_STEREO_VIEW_RIGHT); + if(RenderNoPresent()) + hasRendered = true; + } + g_graphicsContext.SetStereoView(RENDER_STEREO_VIEW_OFF); + } + else + { + if(RenderNoPresent()) + hasRendered = true; + } g_renderManager.FrameFinish(); @@ -2555,6 +2576,10 @@ bool CApplication::OnAction(const CAction &action) if (g_PVRManager.OnAction(action)) return true; + // forward action to graphic context and see if it can handle it + if (CStereoscopicsManager::Get().OnAction(action)) + return true; + if (IsPlaying()) { // forward channel switches to the player - he knows what to do diff --git a/xbmc/GUIInfoManager.cpp b/xbmc/GUIInfoManager.cpp index cdaf94b3e9..3f4bbd8992 100644 --- a/xbmc/GUIInfoManager.cpp +++ b/xbmc/GUIInfoManager.cpp @@ -280,7 +280,8 @@ const infomap system_labels[] = {{ "hasnetwork", SYSTEM_ETHERNET_LINK_ACT { "isinhibit", SYSTEM_ISINHIBIT }, { "hasshutdown", SYSTEM_HAS_SHUTDOWN }, { "haspvr", SYSTEM_HAS_PVR }, - { "startupwindow", SYSTEM_STARTUP_WINDOW }}; + { "startupwindow", SYSTEM_STARTUP_WINDOW }, + { "stereoscopicmode", SYSTEM_STEREOSCOPIC_MODE } }; const infomap system_param[] = {{ "hasalarm", SYSTEM_HAS_ALARM }, { "hascoreid", SYSTEM_HAS_CORE_ID }, @@ -392,7 +393,10 @@ const infomap videoplayer[] = {{ "title", VIDEOPLAYER_TITLE }, { "channelnumber", VIDEOPLAYER_CHANNEL_NUMBER }, { "channelgroup", VIDEOPLAYER_CHANNEL_GROUP }, { "hasepg", VIDEOPLAYER_HAS_EPG }, - { "parentalrating", VIDEOPLAYER_PARENTAL_RATING }}; + { "parentalrating", VIDEOPLAYER_PARENTAL_RATING }, + { "isstereoscopic", VIDEOPLAYER_IS_STEREOSCOPIC }, + { "stereoscopicmode", VIDEOPLAYER_STEREOSCOPIC_MODE }, +}; const infomap mediacontainer[] = {{ "hasfiles", CONTAINER_HASFILES }, { "hasfolders", CONTAINER_HASFOLDERS }, @@ -1540,6 +1544,13 @@ CStdString CGUIInfoManager::GetLabel(int info, int contextWindow, CStdString *fa strLabel.Format("%i", m_audioInfo.channels); } break; + case VIDEOPLAYER_STEREOSCOPIC_MODE: + if(g_application.IsPlaying() && g_application.m_pPlayer) + { + UpdateAVInfo(); + strLabel = m_videoInfo.stereoMode; + } + break; case PLAYLIST_LENGTH: case PLAYLIST_POSITION: case PLAYLIST_RANDOM: @@ -1708,13 +1719,13 @@ CStdString CGUIInfoManager::GetLabel(int info, int contextWindow, CStdString *fa } break; case SYSTEM_SCREEN_MODE: - strLabel = CDisplaySettings::Get().GetResolutionInfo(g_graphicsContext.GetVideoResolution()).strMode; + strLabel = g_graphicsContext.GetResInfo().strMode; break; case SYSTEM_SCREEN_WIDTH: - strLabel.Format("%i", CDisplaySettings::Get().GetResolutionInfo(g_graphicsContext.GetVideoResolution()).iScreenWidth); + strLabel.Format("%i", g_graphicsContext.GetResInfo().iScreenWidth); break; case SYSTEM_SCREEN_HEIGHT: - strLabel.Format("%i", CDisplaySettings::Get().GetResolutionInfo(g_graphicsContext.GetVideoResolution()).iScreenHeight); + strLabel.Format("%i", g_graphicsContext.GetResInfo().iScreenHeight); break; case SYSTEM_CURRENT_WINDOW: return g_localizeStrings.Get(g_windowManager.GetFocusedWindow()); @@ -1785,6 +1796,12 @@ CStdString CGUIInfoManager::GetLabel(int info, int contextWindow, CStdString *fa strLabel = friendlyName; } break; + case SYSTEM_STEREOSCOPIC_MODE: + { + int stereoMode = CSettings::Get().GetInt("videoscreen.stereoscopicmode"); + strLabel.Format("%i", stereoMode); + } + break; case SKIN_THEME: strLabel = CSettings::Get().GetString("lookandfeel.skintheme"); @@ -2491,6 +2508,13 @@ bool CGUIInfoManager::GetBool(int condition1, int contextWindow, const CGUIListI bReturn = m_currentFile->GetPVRChannelInfoTag()->GetEPGNow(epgTag); } break; + case VIDEOPLAYER_IS_STEREOSCOPIC: + if(g_application.IsPlaying() && g_application.m_pPlayer) + { + UpdateAVInfo(); + bReturn = !m_videoInfo.stereoMode.empty(); + } + break; default: // default, use integer value different from 0 as true { int val; @@ -4092,8 +4116,14 @@ void CGUIInfoManager::UpdateAVInfo() { if (!m_AVInfoValid) { - g_application.m_pPlayer->GetVideoStreamInfo(m_videoInfo); - g_application.m_pPlayer->GetAudioStreamInfo(g_application.m_pPlayer->GetAudioStream(), m_audioInfo); + SPlayerVideoStreamInfo video; + SPlayerAudioStreamInfo audio; + + g_application.m_pPlayer->GetVideoStreamInfo(video); + g_application.m_pPlayer->GetAudioStreamInfo(g_application.m_pPlayer->GetAudioStream(), audio); + + m_videoInfo = video; + m_audioInfo = audio; m_AVInfoValid = true; } } diff --git a/xbmc/GUIInfoManager.h b/xbmc/GUIInfoManager.h index da96d71d11..03e98bc0c0 100644 --- a/xbmc/GUIInfoManager.h +++ b/xbmc/GUIInfoManager.h @@ -172,6 +172,7 @@ namespace INFO #define SYSTEM_HAS_SHUTDOWN 185 #define SYSTEM_HAS_PVR 186 #define SYSTEM_STARTUP_WINDOW 187 +#define SYSTEM_STEREOSCOPIC_MODE 188 #define NETWORK_IP_ADDRESS 190 #define NETWORK_MAC_ADDRESS 191 @@ -272,6 +273,8 @@ namespace INFO #define VIDEOPLAYER_PARENTAL_RATING 307 #define VIDEOPLAYER_HAS_EPG 308 #define VIDEOPLAYER_VOTES 309 +#define VIDEOPLAYER_IS_STEREOSCOPIC 310 +#define VIDEOPLAYER_STEREOSCOPIC_MODE 311 #define CONTAINER_CAN_FILTER 342 #define CONTAINER_CAN_FILTERADVANCED 343 diff --git a/xbmc/addons/ScreenSaver.cpp b/xbmc/addons/ScreenSaver.cpp index be5881f546..69f4372ccd 100644 --- a/xbmc/addons/ScreenSaver.cpp +++ b/xbmc/addons/ScreenSaver.cpp @@ -62,7 +62,7 @@ bool CScreenSaver::CreateScreenSaver() m_pInfo->y = 0; m_pInfo->width = iWidth; m_pInfo->height = iHeight; - m_pInfo->pixelRatio = CDisplaySettings::Get().GetResolutionInfo(g_graphicsContext.GetVideoResolution()).fPixelRatio; + m_pInfo->pixelRatio = g_graphicsContext.GetResInfo().fPixelRatio; m_pInfo->name = strdup(Name().c_str()); m_pInfo->presets = strdup(CSpecialProtocol::TranslatePath(Path()).c_str()); m_pInfo->profile = strdup(CSpecialProtocol::TranslatePath(Profile()).c_str()); diff --git a/xbmc/addons/Visualisation.cpp b/xbmc/addons/Visualisation.cpp index 8ac8ca9992..5c91cb40d0 100644 --- a/xbmc/addons/Visualisation.cpp +++ b/xbmc/addons/Visualisation.cpp @@ -23,7 +23,6 @@ #include "GUIInfoManager.h" #include "Application.h" #include "music/tags/MusicInfoTag.h" -#include "settings/DisplaySettings.h" #include "settings/Settings.h" #include "settings/AdvancedSettings.h" #include "settings/DisplaySettings.h" @@ -78,7 +77,7 @@ bool CVisualisation::Create(int x, int y, int w, int h, void *device) m_pInfo->y = y; m_pInfo->width = w; m_pInfo->height = h; - m_pInfo->pixelRatio = CDisplaySettings::Get().GetResolutionInfo(g_graphicsContext.GetVideoResolution()).fPixelRatio; + m_pInfo->pixelRatio = g_graphicsContext.GetResInfo().fPixelRatio; m_pInfo->name = strdup(Name().c_str()); m_pInfo->presets = strdup(CSpecialProtocol::TranslatePath(Path()).c_str()); diff --git a/xbmc/cores/IPlayer.h b/xbmc/cores/IPlayer.h index 846ccdc9d7..f153c7b644 100644 --- a/xbmc/cores/IPlayer.h +++ b/xbmc/cores/IPlayer.h @@ -105,6 +105,7 @@ struct SPlayerVideoStreamInfo std::string videoCodecName; CRect SrcRect; CRect DestRect; + std::string stereoMode; SPlayerVideoStreamInfo() { diff --git a/xbmc/cores/VideoRenderers/BaseRenderer.cpp b/xbmc/cores/VideoRenderers/BaseRenderer.cpp index 56cfb979c8..d0a2569aa9 100644 --- a/xbmc/cores/VideoRenderers/BaseRenderer.cpp +++ b/xbmc/cores/VideoRenderers/BaseRenderer.cpp @@ -91,16 +91,18 @@ void CBaseRenderer::ChooseBestResolution(float fps) } CLog::Log(LOGNOTICE, "Display resolution ADJUST : %s (%d) (weight: %.3f)", - CDisplaySettings::Get().GetResolutionInfo(m_resolution).strMode.c_str(), m_resolution, weight); + g_graphicsContext.GetResInfo(m_resolution).strMode.c_str(), m_resolution, weight); } else #endif CLog::Log(LOGNOTICE, "Display resolution %s : %s (%d)", - m_resolution == RES_DESKTOP ? "DESKTOP" : "USER", CDisplaySettings::Get().GetResolutionInfo(m_resolution).strMode.c_str(), m_resolution); + m_resolution == RES_DESKTOP ? "DESKTOP" : "USER", g_graphicsContext.GetResInfo(m_resolution).strMode.c_str(), m_resolution); } bool CBaseRenderer::FindResolutionFromOverride(float fps, float& weight, bool fallback) { + RESOLUTION_INFO curr = g_graphicsContext.GetResInfo(m_resolution); + //try to find a refreshrate from the override for (int i = 0; i < (int)g_advancedSettings.m_videoAdjustRefreshOverrides.size(); i++) { @@ -115,29 +117,31 @@ bool CBaseRenderer::FindResolutionFromOverride(float fps, float& weight, bool fa for (size_t j = (int)RES_DESKTOP; j < CDisplaySettings::Get().ResolutionInfoSize(); j++) { - if (CDisplaySettings::Get().GetResolutionInfo(j).iScreenWidth == CDisplaySettings::Get().GetResolutionInfo(m_resolution).iScreenWidth - && CDisplaySettings::Get().GetResolutionInfo(j).iScreenHeight == CDisplaySettings::Get().GetResolutionInfo(m_resolution).iScreenHeight - && CDisplaySettings::Get().GetResolutionInfo(j).iScreen == CDisplaySettings::Get().GetResolutionInfo(m_resolution).iScreen) + RESOLUTION_INFO info = g_graphicsContext.GetResInfo((RESOLUTION)j); + + if (info.iScreenWidth == curr.iScreenWidth + && info.iScreenHeight == curr.iScreenHeight + && info.iScreen == curr.iScreen) { - if (CDisplaySettings::Get().GetResolutionInfo(j).fRefreshRate <= override.refreshmax - && CDisplaySettings::Get().GetResolutionInfo(j).fRefreshRate >= override.refreshmin) + if (info.fRefreshRate <= override.refreshmax + && info.fRefreshRate >= override.refreshmin) { m_resolution = (RESOLUTION)j; if (fallback) { CLog::Log(LOGDEBUG, "Found Resolution %s (%d) from fallback (refreshmin:%.3f refreshmax:%.3f)", - CDisplaySettings::Get().GetResolutionInfo(m_resolution).strMode.c_str(), m_resolution, + info.strMode.c_str(), m_resolution, override.refreshmin, override.refreshmax); } else { CLog::Log(LOGDEBUG, "Found Resolution %s (%d) from override of fps %.3f (fpsmin:%.3f fpsmax:%.3f refreshmin:%.3f refreshmax:%.3f)", - CDisplaySettings::Get().GetResolutionInfo(m_resolution).strMode.c_str(), m_resolution, fps, + info.strMode.c_str(), m_resolution, fps, override.fpsmin, override.fpsmax, override.refreshmin, override.refreshmax); } - weight = RefreshWeight(CDisplaySettings::Get().GetResolutionInfo(m_resolution).fRefreshRate, fps); + weight = RefreshWeight(info.fRefreshRate, fps); return true; //fps and refresh match with this override, use this resolution } @@ -151,113 +155,88 @@ bool CBaseRenderer::FindResolutionFromOverride(float fps, float& weight, bool fa void CBaseRenderer::FindResolutionFromFpsMatch(float fps, float& weight) { const float maxWeight = 0.0021f; + RESOLUTION_INFO curr; m_resolution = FindClosestResolution(fps, 1.0, m_resolution, weight); + curr = g_graphicsContext.GetResInfo(m_resolution); if (weight >= maxWeight) //not a very good match, try a 2:3 cadence instead { CLog::Log(LOGDEBUG, "Resolution %s (%d) not a very good match for fps %.3f (weight: %.3f), trying 2:3 cadence", - CDisplaySettings::Get().GetResolutionInfo(m_resolution).strMode.c_str(), m_resolution, fps, weight); + curr.strMode.c_str(), m_resolution, fps, weight); m_resolution = FindClosestResolution(fps, 2.5, m_resolution, weight); + curr = g_graphicsContext.GetResInfo(m_resolution); if (weight >= maxWeight) //2:3 cadence not a good match { CLog::Log(LOGDEBUG, "Resolution %s (%d) not a very good match for fps %.3f with 2:3 cadence (weight: %.3f), choosing 60 hertz", - CDisplaySettings::Get().GetResolutionInfo(m_resolution).strMode.c_str(), m_resolution, fps, weight); + curr.strMode.c_str(), m_resolution, fps, weight); //get the resolution with the refreshrate closest to 60 hertz for (size_t i = (int)RES_DESKTOP; i < CDisplaySettings::Get().ResolutionInfoSize(); i++) { - if (MathUtils::round_int(CDisplaySettings::Get().GetResolutionInfo(i).fRefreshRate) == 60 - && CDisplaySettings::Get().GetResolutionInfo(i).iScreenWidth == CDisplaySettings::Get().GetResolutionInfo(m_resolution).iScreenWidth - && CDisplaySettings::Get().GetResolutionInfo(i).iScreenHeight == CDisplaySettings::Get().GetResolutionInfo(m_resolution).iScreenHeight - && CDisplaySettings::Get().GetResolutionInfo(i).iScreen == CDisplaySettings::Get().GetResolutionInfo(m_resolution).iScreen) + RESOLUTION_INFO info = g_graphicsContext.GetResInfo((RESOLUTION)i); + + if (MathUtils::round_int(info.fRefreshRate) == 60 + && info.iScreenWidth == curr.iScreenWidth + && info.iScreenHeight == curr.iScreenHeight + && info.iScreen == curr.iScreen) { - if (fabs(CDisplaySettings::Get().GetResolutionInfo(i).fRefreshRate - 60.0) < fabs(CDisplaySettings::Get().GetResolutionInfo(m_resolution).fRefreshRate - 60.0)) + if (fabs(info.fRefreshRate - 60.0) < fabs(curr.fRefreshRate - 60.0)) { m_resolution = (RESOLUTION)i; + curr = info; + } } } //60 hertz not available, get the highest refreshrate - if (MathUtils::round_int(CDisplaySettings::Get().GetResolutionInfo(m_resolution).fRefreshRate) != 60) + if (MathUtils::round_int(curr.fRefreshRate) != 60) { CLog::Log(LOGDEBUG, "60 hertz refreshrate not available, choosing highest"); for (size_t i = (int)RES_DESKTOP; i < CDisplaySettings::Get().ResolutionInfoSize(); i++) { - if (CDisplaySettings::Get().GetResolutionInfo(i).fRefreshRate > CDisplaySettings::Get().GetResolutionInfo(m_resolution).fRefreshRate - && CDisplaySettings::Get().GetResolutionInfo(i).iScreenWidth == CDisplaySettings::Get().GetResolutionInfo(m_resolution).iScreenWidth - && CDisplaySettings::Get().GetResolutionInfo(i).iScreenHeight == CDisplaySettings::Get().GetResolutionInfo(m_resolution).iScreenHeight - && CDisplaySettings::Get().GetResolutionInfo(i).iScreen == CDisplaySettings::Get().GetResolutionInfo(m_resolution).iScreen) + RESOLUTION_INFO info = g_graphicsContext.GetResInfo((RESOLUTION)i); + + if (info.fRefreshRate > curr.fRefreshRate + && info.iScreenWidth == curr.iScreenWidth + && info.iScreenHeight == curr.iScreenHeight + && info.iScreen == curr.iScreen) { m_resolution = (RESOLUTION)i; + curr = info; } } } - weight = RefreshWeight(CDisplaySettings::Get().GetResolutionInfo(m_resolution).fRefreshRate, fps); + weight = RefreshWeight(curr.fRefreshRate, fps); } } } RESOLUTION CBaseRenderer::FindClosestResolution(float fps, float multiplier, RESOLUTION current, float& weight) { - RESOLUTION_INFO &curr = CDisplaySettings::Get().GetResolutionInfo(current); + RESOLUTION_INFO curr = g_graphicsContext.GetResInfo(current); - int iScreenWidth = curr.iScreenWidth; - int iScreenHeight = curr.iScreenHeight; float fRefreshRate = fps; - /* - * For 3D modes the following is assumed : - * - * side-by-side : - * - * width is width / 2 : 1920 -> 960 - * - * tob-bottom : - * - * height is height / 2 : 1080 -> 540 - * - */ - - // work out current non-3D resolution (in case we are currently in 3D mode) - if (curr.dwFlags & D3DPRESENTFLAG_MODE3DSBS) - { - iScreenWidth *= 2; - } - else if (curr.dwFlags & D3DPRESENTFLAG_MODE3DTB) - { - iScreenHeight *= 2; - } - // work out resolution if we switch to 3D mode - if(m_iFlags & CONF_FLAGS_FORMAT_SBS) - { - iScreenWidth /= 2; - } - else if(m_iFlags & CONF_FLAGS_FORMAT_TB) - { - iScreenHeight /= 2; - } - float last_diff = fRefreshRate; // Find closest refresh rate for (size_t i = (int)RES_DESKTOP; i < CDisplaySettings::Get().ResolutionInfoSize(); i++) { - RESOLUTION_INFO &info = CDisplaySettings::Get().GetResolutionInfo(i); - RESOLUTION_INFO &best = CDisplaySettings::Get().GetResolutionInfo(current); + const RESOLUTION_INFO info = g_graphicsContext.GetResInfo((RESOLUTION)i); //discard resolutions that are not the same width and height //or have a too low refreshrate - if (info.iScreenWidth != iScreenWidth - || info.iScreenHeight != iScreenHeight - || info.iScreen != curr.iScreen + if (info.iScreenWidth != curr.iScreenWidth + || info.iScreenHeight != curr.iScreenHeight + || info.iScreen != curr.iScreen || info.fRefreshRate < (fRefreshRate * multiplier / 1.001) - 0.001) continue; // For 3D choose the closest refresh rate - if(m_iFlags & CONF_FLAGS_FORMAT_SBS || m_iFlags & CONF_FLAGS_FORMAT_TB) + if(CONF_FLAGS_STEREO_MODE_MASK(m_iFlags)) { float diff = (info.fRefreshRate - fRefreshRate); if(diff < 0) @@ -267,25 +246,27 @@ RESOLUTION CBaseRenderer::FindClosestResolution(float fps, float multiplier, RES { last_diff = diff; current = (RESOLUTION)i; + curr = info; } } else { - int c_weight = MathUtils::round_int(RefreshWeight(best.fRefreshRate, fRefreshRate * multiplier) * 1000.0); + int c_weight = MathUtils::round_int(RefreshWeight(curr.fRefreshRate, fRefreshRate * multiplier) * 1000.0); int i_weight = MathUtils::round_int(RefreshWeight(info.fRefreshRate, fRefreshRate * multiplier) * 1000.0); // Closer the better, prefer higher refresh rate if the same if ((i_weight < c_weight) - || (i_weight == c_weight && info.fRefreshRate > best.fRefreshRate)) + || (i_weight == c_weight && info.fRefreshRate > curr.fRefreshRate)) current = (RESOLUTION)i; + curr = info; } } // For 3D overwrite weight - if(m_iFlags & CONF_FLAGS_FORMAT_SBS || m_iFlags & CONF_FLAGS_FORMAT_TB) + if(CONF_FLAGS_STEREO_MODE_MASK(m_iFlags)) weight = 0; else - weight = RefreshWeight(CDisplaySettings::Get().GetResolutionInfo(current).fRefreshRate, fRefreshRate * multiplier); + weight = RefreshWeight(curr.fRefreshRate, fRefreshRate * multiplier); return current; } @@ -430,7 +411,7 @@ void CBaseRenderer::CalcNormalDisplayRect(float offsetX, float offsetY, float sc // calculate the correct output frame ratio (using the users pixel ratio setting // and the output pixel ratio setting) - float outputFrameRatio = inputFrameRatio / CDisplaySettings::Get().GetResolutionInfo(GetResolution()).fPixelRatio; + float outputFrameRatio = inputFrameRatio / g_graphicsContext.GetResInfo(GetResolution()).fPixelRatio; // allow a certain error to maximize screen size float fCorrection = screenWidth / screenHeight / outputFrameRatio - 1.0f; @@ -574,10 +555,44 @@ void CBaseRenderer::ManageDisplay() { const CRect view = g_graphicsContext.GetViewWindow(); - m_sourceRect.x1 = (float)CMediaSettings::Get().GetCurrentVideoSettings().m_CropLeft; - m_sourceRect.y1 = (float)CMediaSettings::Get().GetCurrentVideoSettings().m_CropTop; - m_sourceRect.x2 = (float)m_sourceWidth - CMediaSettings::Get().GetCurrentVideoSettings().m_CropRight; - m_sourceRect.y2 = (float)m_sourceHeight - CMediaSettings::Get().GetCurrentVideoSettings().m_CropBottom; + m_sourceRect.x1 = 0.0f; + m_sourceRect.y1 = 0.0f; + m_sourceRect.x2 = (float)m_sourceWidth; + m_sourceRect.y2 = (float)m_sourceHeight; + + unsigned int stereo_mode = CONF_FLAGS_STEREO_MODE_MASK(m_iFlags); + int stereo_view = g_graphicsContext.GetStereoView(); + + if(CONF_FLAGS_STEREO_CADENCE(m_iFlags) == CONF_FLAGS_STEREO_CADANCE_RIGHT_LEFT) + { + if (stereo_view == RENDER_STEREO_VIEW_LEFT) stereo_view = RENDER_STEREO_VIEW_RIGHT; + else if(stereo_view == RENDER_STEREO_VIEW_RIGHT) stereo_view = RENDER_STEREO_VIEW_LEFT; + } + + switch(stereo_mode) + { + case CONF_FLAGS_STEREO_MODE_TAB: + if (stereo_view == RENDER_STEREO_VIEW_LEFT) + m_sourceRect.y2 *= 0.5f; + else if(stereo_view == RENDER_STEREO_VIEW_RIGHT) + m_sourceRect.y1 += m_sourceRect.y2*0.5f; + break; + + case CONF_FLAGS_STEREO_MODE_SBS: + if (stereo_view == RENDER_STEREO_VIEW_LEFT) + m_sourceRect.x2 *= 0.5f; + else if(stereo_view == RENDER_STEREO_VIEW_RIGHT) + m_sourceRect.x1 += m_sourceRect.x2*0.5f; + break; + + default: + break; + } + + m_sourceRect.x1 += (float)CMediaSettings::Get().GetCurrentVideoSettings().m_CropLeft; + m_sourceRect.y1 += (float)CMediaSettings::Get().GetCurrentVideoSettings().m_CropTop; + m_sourceRect.x2 -= (float)CMediaSettings::Get().GetCurrentVideoSettings().m_CropRight; + m_sourceRect.y2 -= (float)CMediaSettings::Get().GetCurrentVideoSettings().m_CropBottom; CalcNormalDisplayRect(view.x1, view.y1, view.Width(), view.Height(), GetAspectRatio() * CDisplaySettings::Get().GetPixelRatio(), CDisplaySettings::Get().GetZoomAmount(), CDisplaySettings::Get().GetVerticalShift()); } @@ -587,20 +602,14 @@ void CBaseRenderer::SetViewMode(int viewMode) if (viewMode < ViewModeNormal || viewMode > ViewModeCustom) viewMode = ViewModeNormal; - if (m_iFlags & (CONF_FLAGS_FORMAT_SBS | CONF_FLAGS_FORMAT_TB)) - viewMode = ViewModeNormal; - CMediaSettings::Get().GetCurrentVideoSettings().m_ViewMode = viewMode; // get our calibrated full screen resolution RESOLUTION res = GetResolution(); - float screenWidth = (float)(CDisplaySettings::Get().GetResolutionInfo(res).Overscan.right - CDisplaySettings::Get().GetResolutionInfo(res).Overscan.left); - float screenHeight = (float)(CDisplaySettings::Get().GetResolutionInfo(res).Overscan.bottom - CDisplaySettings::Get().GetResolutionInfo(res).Overscan.top); + RESOLUTION_INFO info = g_graphicsContext.GetResInfo(m_resolution); + float screenWidth = (float)(info.Overscan.right - info.Overscan.left); + float screenHeight = (float)(info.Overscan.bottom - info.Overscan.top); - if(m_iFlags & CONF_FLAGS_FORMAT_SBS) - screenWidth /= 2; - else if(m_iFlags & CONF_FLAGS_FORMAT_TB) - screenHeight /= 2; // and the source frame ratio float sourceFrameRatio = GetAspectRatio(); @@ -608,8 +617,8 @@ void CBaseRenderer::SetViewMode(int viewMode) CMediaSettings::Get().GetCurrentVideoSettings().m_ViewMode == ViewModeNormal); // Splitres scaling factor - float xscale = (float)CDisplaySettings::Get().GetResolutionInfo(res).iScreenWidth / (float)CDisplaySettings::Get().GetResolutionInfo(res).iWidth; - float yscale = (float)CDisplaySettings::Get().GetResolutionInfo(res).iScreenHeight / (float)CDisplaySettings::Get().GetResolutionInfo(res).iHeight; + float xscale = (float)info.iScreenWidth / (float)info.iWidth; + float yscale = (float)info.iScreenHeight / (float)info.iHeight; screenWidth *= xscale; screenHeight *= yscale; @@ -622,7 +631,7 @@ void CBaseRenderer::SetViewMode(int viewMode) { // zoom image so no black bars CDisplaySettings::Get().SetPixelRatio(1.0); // calculate the desired output ratio - float outputFrameRatio = sourceFrameRatio * CDisplaySettings::Get().GetPixelRatio() / CDisplaySettings::Get().GetResolutionInfo(res).fPixelRatio; + float outputFrameRatio = sourceFrameRatio * CDisplaySettings::Get().GetPixelRatio() / info.fPixelRatio; // now calculate the correct zoom amount. First zoom to full height. float newHeight = screenHeight; float newWidth = newHeight * outputFrameRatio; @@ -640,7 +649,7 @@ void CBaseRenderer::SetViewMode(int viewMode) if (res == RES_PAL_4x3 || res == RES_PAL60_4x3 || res == RES_NTSC_4x3 || res == RES_HDTV_480p_4x3) { // stretch to the limits of the 4:3 screen. // incorrect behaviour, but it's what the users want, so... - CDisplaySettings::Get().SetPixelRatio((screenWidth / screenHeight) * CDisplaySettings::Get().GetResolutionInfo(res).fPixelRatio / sourceFrameRatio); + CDisplaySettings::Get().SetPixelRatio((screenWidth / screenHeight) * info.fPixelRatio / sourceFrameRatio); } else { @@ -652,7 +661,7 @@ void CBaseRenderer::SetViewMode(int viewMode) else if ( CMediaSettings::Get().GetCurrentVideoSettings().m_ViewMode == ViewModeWideZoom || (is43 && CSettings::Get().GetInt("videoplayer.stretch43") == ViewModeWideZoom)) { // super zoom - float stretchAmount = (screenWidth / screenHeight) * CDisplaySettings::Get().GetResolutionInfo(res).fPixelRatio / sourceFrameRatio; + float stretchAmount = (screenWidth / screenHeight) * info.fPixelRatio / sourceFrameRatio; CDisplaySettings::Get().SetPixelRatio(pow(stretchAmount, float(2.0/3.0))); CDisplaySettings::Get().SetZoomAmount(pow(stretchAmount, float((stretchAmount < 1.0) ? -1.0/3.0 : 1.0/3.0))); CDisplaySettings::Get().SetNonLinearStretched(true); @@ -669,7 +678,7 @@ void CBaseRenderer::SetViewMode(int viewMode) else { // stretch to the limits of the 16:9 screen. // incorrect behaviour, but it's what the users want, so... - CDisplaySettings::Get().SetPixelRatio((screenWidth / screenHeight) * CDisplaySettings::Get().GetResolutionInfo(res).fPixelRatio / sourceFrameRatio); + CDisplaySettings::Get().SetPixelRatio((screenWidth / screenHeight) * info.fPixelRatio / sourceFrameRatio); } } else if (CMediaSettings::Get().GetCurrentVideoSettings().m_ViewMode == ViewModeOriginal) @@ -677,7 +686,7 @@ void CBaseRenderer::SetViewMode(int viewMode) CDisplaySettings::Get().SetPixelRatio(1.0); // get the size of the media file // calculate the desired output ratio - float outputFrameRatio = sourceFrameRatio * CDisplaySettings::Get().GetPixelRatio() / CDisplaySettings::Get().GetResolutionInfo(res).fPixelRatio; + float outputFrameRatio = sourceFrameRatio * CDisplaySettings::Get().GetPixelRatio() / info.fPixelRatio; // now calculate the correct zoom amount. First zoom to full width. float newHeight = screenWidth / outputFrameRatio; if (newHeight > screenHeight) diff --git a/xbmc/cores/VideoRenderers/LinuxRendererGL.cpp b/xbmc/cores/VideoRenderers/LinuxRendererGL.cpp index d4ed4a1364..d52deadf31 100644 --- a/xbmc/cores/VideoRenderers/LinuxRendererGL.cpp +++ b/xbmc/cores/VideoRenderers/LinuxRendererGL.cpp @@ -380,6 +380,27 @@ void CLinuxRendererGL::ReleaseImage(int source, bool preserve) m_bImageReady = true; } +void CLinuxRendererGL::GetPlaneTextureSize(YUVPLANE& plane) +{ + /* texture is assumed to be bound */ + GLint width = 0 + , height = 0 + , border = 0; + glGetTexLevelParameteriv(m_textureTarget, 0, GL_TEXTURE_WIDTH , &width); + glGetTexLevelParameteriv(m_textureTarget, 0, GL_TEXTURE_HEIGHT, &height); + glGetTexLevelParameteriv(m_textureTarget, 0, GL_TEXTURE_BORDER, &border); + plane.texwidth = width - 2 * border; + plane.texheight = height - 2 * border; + if(plane.texwidth <= 0 || plane.texheight <= 0) + { + CLog::Log(LOGDEBUG, "CLinuxRendererGL::GetPlaneTextureSize - invalid size %dx%d - %d", width, height, border); + /* to something that avoid division by zero */ + plane.texwidth = 1; + plane.texheight = 1; + } + +} + void CLinuxRendererGL::CalculateTextureSourceRects(int source, int num_planes) { YUVBUFFER& buf = m_buffers[source]; @@ -1542,6 +1563,10 @@ void CLinuxRendererGL::RenderVDPAU(int index, int field) vdpau->BindPixmap(); + // make sure we know the correct texture size + GetPlaneTextureSize(plane); + CalculateTextureSourceRects(index, 1); + // 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); @@ -1580,10 +1605,10 @@ void CLinuxRendererGL::RenderVDPAU(int index, int field) glBegin(GL_QUADS); if (m_textureTarget==GL_TEXTURE_2D) { - glTexCoord2f(0.0, 0.0); glVertex2f(m_rotatedDestCoords[0].x, m_rotatedDestCoords[0].y); - glTexCoord2f(1.0, 0.0); glVertex2f(m_rotatedDestCoords[1].x, m_rotatedDestCoords[1].y); - glTexCoord2f(1.0, 1.0); glVertex2f(m_rotatedDestCoords[2].x, m_rotatedDestCoords[2].y); - glTexCoord2f(0.0, 1.0); glVertex2f(m_rotatedDestCoords[3].x, m_rotatedDestCoords[3].y); + glTexCoord2f(plane.rect.x1, plane.rect.y1); glVertex2f(m_rotatedDestCoords[0].x, m_rotatedDestCoords[0].y); + glTexCoord2f(plane.rect.x2, plane.rect.y1); glVertex2f(m_rotatedDestCoords[1].x, m_rotatedDestCoords[1].y); + glTexCoord2f(plane.rect.x2, plane.rect.y2); glVertex2f(m_rotatedDestCoords[2].x, m_rotatedDestCoords[2].y); + glTexCoord2f(plane.rect.x1, plane.rect.y2); glVertex2f(m_rotatedDestCoords[3].x, m_rotatedDestCoords[3].y); } else { @@ -1633,6 +1658,10 @@ void CLinuxRendererGL::RenderVAAPI(int index, int field) } #endif + // make sure we know the correct texture size + GetPlaneTextureSize(plane); + CalculateTextureSourceRects(index, 1); + // 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); @@ -1669,10 +1698,10 @@ void CLinuxRendererGL::RenderVAAPI(int index, int field) VerifyGLState(); glBegin(GL_QUADS); - glTexCoord2f(0.0, 0.0); glVertex2f(m_rotatedDestCoords[0].x, m_rotatedDestCoords[0].y); - glTexCoord2f(1.0, 0.0); glVertex2f(m_rotatedDestCoords[1].x, m_rotatedDestCoords[1].y); - glTexCoord2f(1.0, 1.0); glVertex2f(m_rotatedDestCoords[2].x, m_rotatedDestCoords[2].y); - glTexCoord2f(0.0, 1.0); glVertex2f(m_rotatedDestCoords[3].x, m_rotatedDestCoords[3].y); + glTexCoord2f(plane.rect.x1, plane.rect.y1); glVertex2f(m_rotatedDestCoords[0].x, m_rotatedDestCoords[0].y); + glTexCoord2f(plane.rect.x2, plane.rect.y1); glVertex2f(m_rotatedDestCoords[1].x, m_rotatedDestCoords[1].y); + glTexCoord2f(plane.rect.x2, plane.rect.y2); glVertex2f(m_rotatedDestCoords[2].x, m_rotatedDestCoords[2].y); + glTexCoord2f(plane.rect.x1, plane.rect.y2); glVertex2f(m_rotatedDestCoords[3].x, m_rotatedDestCoords[3].y); glEnd(); VerifyGLState(); diff --git a/xbmc/cores/VideoRenderers/LinuxRendererGL.h b/xbmc/cores/VideoRenderers/LinuxRendererGL.h index 93b1a6954c..b986d933a0 100644 --- a/xbmc/cores/VideoRenderers/LinuxRendererGL.h +++ b/xbmc/cores/VideoRenderers/LinuxRendererGL.h @@ -300,6 +300,7 @@ protected: , unsigned width, unsigned height , int stride, int bpp, void* data, GLuint* pbo = NULL ); + void GetPlaneTextureSize(YUVPLANE& plane); Shaders::BaseYUV2RGBShader *m_pYUVShader; Shaders::BaseVideoFilterShader *m_pVideoFilterShader; diff --git a/xbmc/cores/VideoRenderers/LinuxRendererGLES.cpp b/xbmc/cores/VideoRenderers/LinuxRendererGLES.cpp index 86fcb88834..2f0d547219 100644 --- a/xbmc/cores/VideoRenderers/LinuxRendererGLES.cpp +++ b/xbmc/cores/VideoRenderers/LinuxRendererGLES.cpp @@ -443,9 +443,9 @@ void CLinuxRendererGLES::RenderUpdate(bool clear, DWORD flags, DWORD alpha) if (m_RenderUpdateCallBackFn) (*m_RenderUpdateCallBackFn)(m_RenderUpdateCallBackCtx, m_sourceRect, m_destRect); - RESOLUTION res = GetResolution(); - int iWidth = CDisplaySettings::Get().GetResolutionInfo(res).iWidth; - int iHeight = CDisplaySettings::Get().GetResolutionInfo(res).iHeight; + const RESOLUTION_INFO info = g_graphicsContext.GetResInfo(GetResolution()); + int iWidth = info.iWidth; + int iHeight = info.iHeight; g_graphicsContext.BeginPaint(); diff --git a/xbmc/cores/VideoRenderers/Makefile.in b/xbmc/cores/VideoRenderers/Makefile.in index 3c1214dbd1..4803029208 100644 --- a/xbmc/cores/VideoRenderers/Makefile.in +++ b/xbmc/cores/VideoRenderers/Makefile.in @@ -3,6 +3,7 @@ SRCS += OverlayRenderer.cpp SRCS += OverlayRendererUtil.cpp SRCS += RenderCapture.cpp SRCS += RenderManager.cpp +SRCS += RenderFlags.cpp ifeq ($(findstring arm,@ARCH@),arm) SRCS += yuv2rgb.neon.S diff --git a/xbmc/cores/VideoRenderers/OverlayRenderer.cpp b/xbmc/cores/VideoRenderers/OverlayRenderer.cpp index 5389d69500..ce9584d6d1 100644 --- a/xbmc/cores/VideoRenderers/OverlayRenderer.cpp +++ b/xbmc/cores/VideoRenderers/OverlayRenderer.cpp @@ -196,7 +196,7 @@ void CRenderer::Render(COverlay* o) RESOLUTION_INFO res; g_renderManager.GetVideoRect(rs, rd); rv = g_graphicsContext.GetViewWindow(); - res = CDisplaySettings::Get().GetResolutionInfo(g_renderManager.GetResolution()); + res = g_graphicsContext.GetResInfo(g_renderManager.GetResolution()); SRenderState state; state.x = o->m_x; @@ -263,9 +263,6 @@ void CRenderer::Render(COverlay* o) float scale_x = rd.Width() / rs.Width(); float scale_y = rd.Height() / rs.Height(); - state.x -= rs.x1; - state.y -= rs.y1; - state.x *= scale_x; state.y *= scale_y; state.width *= scale_x; diff --git a/xbmc/cores/VideoRenderers/RenderFlags.cpp b/xbmc/cores/VideoRenderers/RenderFlags.cpp new file mode 100644 index 0000000000..bd3e53b975 --- /dev/null +++ b/xbmc/cores/VideoRenderers/RenderFlags.cpp @@ -0,0 +1,134 @@ +/* + * Copyright (C) 2005-2013 Team XBMC + * http://www.xbmc.org + * + * This library 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. + * + * This library 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 this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#include "RenderFlags.h" +#include <string> +#include <map> + + +namespace RenderManager { + + unsigned int GetFlagsColorMatrix(unsigned int color_matrix, unsigned width, unsigned height) + { + switch(color_matrix) + { + case 7: // SMPTE 240M (1987) + return CONF_FLAGS_YUVCOEF_240M; + case 6: // SMPTE 170M + case 5: // ITU-R BT.470-2 + case 4: // FCC + return CONF_FLAGS_YUVCOEF_BT601; + case 1: // ITU-R Rec.709 (1990) -- BT.709 + return CONF_FLAGS_YUVCOEF_BT709; + case 3: // RESERVED + case 2: // UNSPECIFIED + default: + if(width > 1024 || height >= 600) + return CONF_FLAGS_YUVCOEF_BT709; + else + return CONF_FLAGS_YUVCOEF_BT601; + break; + } + } + + unsigned int GetFlagsChromaPosition(unsigned int chroma_position) + { + switch(chroma_position) + { + case 1: return CONF_FLAGS_CHROMA_LEFT; + case 2: return CONF_FLAGS_CHROMA_CENTER; + case 3: return CONF_FLAGS_CHROMA_TOPLEFT; + } + return 0; + } + + unsigned int GetFlagsColorPrimaries(unsigned int color_primaries) + { + switch(color_primaries) + { + case 1: return CONF_FLAGS_COLPRI_BT709; + case 4: return CONF_FLAGS_COLPRI_BT470M; + case 5: return CONF_FLAGS_COLPRI_BT470BG; + case 6: return CONF_FLAGS_COLPRI_170M; + case 7: return CONF_FLAGS_COLPRI_240M; + } + return 0; + } + + unsigned int GetFlagsColorTransfer(unsigned int color_transfer) + { + switch(color_transfer) + { + case 1: return CONF_FLAGS_TRC_BT709; + case 4: return CONF_FLAGS_TRC_GAMMA22; + case 5: return CONF_FLAGS_TRC_GAMMA28; + } + return 0; + } + + unsigned int GetStereoModeFlags(const std::string mode) + { + static std::map<std::string, unsigned int> convert; + if(convert.empty()) + { + convert["mono"] = 0u; + convert["left_right"] = CONF_FLAGS_STEREO_MODE_SBS | CONF_FLAGS_STEREO_CADANCE_LEFT_RIGHT; + convert["bottom_top"] = CONF_FLAGS_STEREO_MODE_TAB | CONF_FLAGS_STEREO_CADANCE_RIGHT_LEFT; + convert["top_bottom"] = CONF_FLAGS_STEREO_MODE_TAB | CONF_FLAGS_STEREO_CADANCE_LEFT_RIGHT; + convert["checkerboard_rl"] = 0u; + convert["checkerboard_lr"] = 0u; + convert["row_interleaved_rl"] = 0u; + convert["row_interleaved_lr"] = 0u; + convert["col_interleaved_rl"] = 0u; + convert["col_interleaved_lr"] = 0u; + convert["anaglyph_cyan_red"] = 0u; + convert["right_left"] = CONF_FLAGS_STEREO_MODE_SBS | CONF_FLAGS_STEREO_CADANCE_RIGHT_LEFT; + convert["anaglyph_green_magenta"] = 0u; + convert["block_lr"] = 0u; + convert["block_rl"] = 0u; + } + return convert[mode]; + } + + std::string GetStereoModeInvert(const std::string& mode) + { + static std::map<std::string, std::string> convert; + if(convert.empty()) + { + convert["left_right"] = "right_left"; + convert["right_left"] = "left_right"; + convert["bottom_top"] = "top_bottom"; + convert["top_bottom"] = "bottom_top"; + convert["checkerboard_rl"] = "checkerboard_lr"; + convert["checkerboard_lr"] = "checkerboard_rl"; + convert["row_interleaved_rl"] = "row_interleaved_lr"; + convert["row_interleaved_lr"] = "row_interleaved_rl"; + convert["col_interleaved_rl"] = "col_interleaved_lr"; + convert["col_interleaved_lr"] = "col_interleaved_rl"; + convert["block_lr"] = "block_lr"; + convert["block_rl"] = "block_rl"; + } + std::string res = convert[mode]; + if(res.empty()) + return mode; + else + return res; + } +} diff --git a/xbmc/cores/VideoRenderers/RenderFlags.h b/xbmc/cores/VideoRenderers/RenderFlags.h index b9e6038617..c20557c2f1 100644 --- a/xbmc/cores/VideoRenderers/RenderFlags.h +++ b/xbmc/cores/VideoRenderers/RenderFlags.h @@ -21,6 +21,8 @@ * */ +#include <string> + #define RENDER_FLAG_BOT 0x01 #define RENDER_FLAG_TOP 0x02 #define RENDER_FLAG_BOTH (RENDER_FLAG_BOT | RENDER_FLAG_TOP) @@ -70,7 +72,25 @@ #define CONF_FLAGS_TRC_GAMMA28 0x0c00 /* defines 3d modes */ -#define CONF_FLAGS_FORMAT_SBS 0x001000 -#define CONF_FLAGS_FORMAT_TB 0x002000 +#define CONF_FLAGS_STEREO_MODE_MASK(a) ((a) & 0x007000) +#define CONF_FLAGS_STEREO_MODE_SBS 0x001000 +#define CONF_FLAGS_STEREO_MODE_TAB 0x002000 + +#define CONF_FLAGS_STEREO_CADENCE(a) ((a) & 0x008000) +#define CONF_FLAGS_STEREO_CADANCE_LEFT_RIGHT 0x000000 +#define CONF_FLAGS_STEREO_CADANCE_RIGHT_LEFT 0x008000 + + + +namespace RenderManager { + + unsigned int GetFlagsColorMatrix(unsigned int color_matrix, unsigned width, unsigned height); + unsigned int GetFlagsChromaPosition(unsigned int chroma_position); + unsigned int GetFlagsColorPrimaries(unsigned int color_primaries); + unsigned int GetFlagsColorTransfer(unsigned int color_transfer); + unsigned int GetStereoModeFlags(const std::string mode); + std::string GetStereoModeInvert(const std::string& mode); + +} #endif diff --git a/xbmc/cores/VideoRenderers/WinRenderer.cpp b/xbmc/cores/VideoRenderers/WinRenderer.cpp index de9f093ad2..205ed4e42b 100644 --- a/xbmc/cores/VideoRenderers/WinRenderer.cpp +++ b/xbmc/cores/VideoRenderers/WinRenderer.cpp @@ -247,8 +247,8 @@ bool CWinRenderer::Configure(unsigned int width, unsigned int height, unsigned i // calculate the input frame aspect ratio CalculateFrameAspectRatio(d_width, d_height); ChooseBestResolution(fps); - m_destWidth = CDisplaySettings::Get().GetResolutionInfo(m_resolution).iWidth; - m_destHeight = CDisplaySettings::Get().GetResolutionInfo(m_resolution).iHeight; + m_destWidth = g_graphicsContext.GetResInfo(m_resolution).iWidth; + m_destHeight = g_graphicsContext.GetResInfo(m_resolution).iHeight; SetViewMode(CMediaSettings::Get().GetCurrentVideoSettings().m_ViewMode); ManageDisplay(); @@ -334,7 +334,7 @@ void CWinRenderer::RenderUpdate(bool clear, DWORD flags, DWORD alpha) LPDIRECT3DDEVICE9 pD3DDevice = g_Windowing.Get3DDevice(); if (clear) - pD3DDevice->Clear( 0L, NULL, D3DCLEAR_TARGET, m_clearColour, 1.0f, 0L ); + g_graphicsContext.Clear(m_clearColour); if(alpha < 255) pD3DDevice->SetRenderState( D3DRS_ALPHABLENDENABLE, TRUE ); @@ -792,12 +792,15 @@ void CWinRenderer::ScaleFixedPipeline() FLOAT tu, tv; }; + // Vertex format ignores viewport offsets, so correct for that here + CRect dest = g_graphicsContext.StereoCorrection(m_destRect); + VERTEX vertex[] = { - {m_destRect.x1, m_destRect.y1, 0.0f, 1.0f, diffuse, specular, m_sourceRect.x1 / srcWidth, m_sourceRect.y1 / srcHeight}, - {m_destRect.x2, m_destRect.y1, 0.0f, 1.0f, diffuse, specular, m_sourceRect.x2 / srcWidth, m_sourceRect.y1 / srcHeight}, - {m_destRect.x2, m_destRect.y2, 0.0f, 1.0f, diffuse, specular, m_sourceRect.x2 / srcWidth, m_sourceRect.y2 / srcHeight}, - {m_destRect.x1, m_destRect.y2, 0.0f, 1.0f, diffuse, specular, m_sourceRect.x1 / srcWidth, m_sourceRect.y2 / srcHeight}, + {dest.x1, dest.y1, 0.0f, 1.0f, diffuse, specular, m_sourceRect.x1 / srcWidth, m_sourceRect.y1 / srcHeight}, + {dest.x2, dest.y1, 0.0f, 1.0f, diffuse, specular, m_sourceRect.x2 / srcWidth, m_sourceRect.y1 / srcHeight}, + {dest.x2, dest.y2, 0.0f, 1.0f, diffuse, specular, m_sourceRect.x2 / srcWidth, m_sourceRect.y2 / srcHeight}, + {dest.x1, dest.y2, 0.0f, 1.0f, diffuse, specular, m_sourceRect.x1 / srcWidth, m_sourceRect.y2 / srcHeight}, }; // Compensate for D3D coordinates system @@ -843,7 +846,6 @@ void CWinRenderer::ScaleFixedPipeline() pD3DDev->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE); pD3DDev->SetRenderState(D3DRS_ALPHATESTENABLE, FALSE); pD3DDev->SetRenderState(D3DRS_SCISSORTESTENABLE, FALSE); - pD3DDev->SetRenderState(D3DRS_COLORWRITEENABLE, D3DCOLORWRITEENABLE_ALPHA|D3DCOLORWRITEENABLE_BLUE|D3DCOLORWRITEENABLE_GREEN|D3DCOLORWRITEENABLE_RED); pD3DDev->SetSamplerState(0, D3DSAMP_MAGFILTER, m_TextureFilter); pD3DDev->SetSamplerState(0, D3DSAMP_MINFILTER, m_TextureFilter); @@ -875,7 +877,7 @@ void CWinRenderer::Stage1() { if (!m_bUseHQScaler) { - m_colorShader->Render(m_sourceRect, m_destRect, + m_colorShader->Render(m_sourceRect, g_graphicsContext.StereoCorrection(m_destRect), CMediaSettings::Get().GetCurrentVideoSettings().m_Contrast, CMediaSettings::Get().GetCurrentVideoSettings().m_Brightness, m_iFlags, @@ -909,7 +911,7 @@ void CWinRenderer::Stage1() void CWinRenderer::Stage2() { - m_scalerShader->Render(m_IntermediateTarget, m_sourceWidth, m_sourceHeight, m_destWidth, m_destHeight, m_sourceRect, m_destRect); + m_scalerShader->Render(m_IntermediateTarget, m_sourceWidth, m_sourceHeight, m_destWidth, m_destHeight, m_sourceRect, g_graphicsContext.StereoCorrection(m_destRect)); } void CWinRenderer::RenderProcessor(DWORD flags) @@ -926,7 +928,7 @@ void CWinRenderer::RenderProcessor(DWORD flags) return; } - m_processor.Render(m_sourceRect, m_destRect, target, image->id, flags); + m_processor.Render(m_sourceRect, g_graphicsContext.StereoCorrection(m_destRect), target, image->id, flags); target->Release(); } diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodec.h b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodec.h index c29204c386..8fc76b7246 100644 --- a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodec.h +++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodec.h @@ -89,6 +89,7 @@ struct DVDVideoPicture unsigned int color_primaries; unsigned int color_transfer; unsigned int extended_format; + char stereo_mode[32]; int8_t* qscale_table; // Quantization parameters, primarily used by filters int qscale_stride; diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.cpp b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.cpp index 4040f38493..5820dfebeb 100644 --- a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.cpp +++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.cpp @@ -605,6 +605,13 @@ bool CDVDVideoCodecFFmpeg::GetPictureCommon(DVDVideoPicture* pDvdVideoPicture) if (!m_pFrame) return false; + AVDictionaryEntry * entry = m_dllAvUtil.av_dict_get(m_dllAvCodec.av_frame_get_metadata(m_pFrame), "stereo_mode", NULL, 0); + if(entry && entry->value) + { + strncpy(pDvdVideoPicture->stereo_mode, (const char*)entry->value, sizeof(pDvdVideoPicture->stereo_mode)); + pDvdVideoPicture->stereo_mode[sizeof(pDvdVideoPicture->stereo_mode)-1] = '\0'; + } + pDvdVideoPicture->iRepeatPicture = 0.5 * m_pFrame->repeat_pict; pDvdVideoPicture->iFlags = DVP_FLAG_ALLOCATED; pDvdVideoPicture->iFlags |= m_pFrame->interlaced_frame ? DVP_FLAG_INTERLACED : 0; diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/DXVA.cpp b/xbmc/cores/dvdplayer/DVDCodecs/Video/DXVA.cpp index 84e0596ba9..2ee852ba23 100644 --- a/xbmc/cores/dvdplayer/DVDCodecs/Video/DXVA.cpp +++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/DXVA.cpp @@ -447,6 +447,15 @@ static bool CheckCompatibility(AVCodecContext *avctx) return false; } + // DXVA has this as a max resolution + if(avctx->width >= 1920 + || avctx->height >= 1088) + { + CLog::Log(LOGDEBUG, "DXVA - frame size (%dx%d) too large - disallowing", avctx->width, avctx->height); + return false; + } + + // Check for hardware limited to H264 L4.1 (ie Bluray). // No advanced settings: autodetect. diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/VAAPI.cpp b/xbmc/cores/dvdplayer/DVDCodecs/Video/VAAPI.cpp index 7951ee7bb1..52b356db61 100644 --- a/xbmc/cores/dvdplayer/DVDCodecs/Video/VAAPI.cpp +++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/VAAPI.cpp @@ -266,6 +266,13 @@ bool CDecoder::Open(AVCodecContext *avctx, enum PixelFormat fmt, unsigned int su CLog::Log(LOGDEBUG, "VAAPI - attempting to open codec %d with profile %d at level %d with %d reference frames", avctx->codec_id, avctx->profile, avctx->level, avctx->refs); + if(avctx->width >= 1920 + || avctx->height >= 1088) + { + CLog::Log(LOGDEBUG, "VAAPI - frame size (%dx%d) too large - disallowing", avctx->width, avctx->height); + return false; + } + vector<VAProfile> accepted; switch (avctx->codec_id) { case AV_CODEC_ID_MPEG2VIDEO: diff --git a/xbmc/cores/dvdplayer/DVDDemuxers/DVDDemux.h b/xbmc/cores/dvdplayer/DVDDemuxers/DVDDemux.h index 950e8664c1..9c642f687b 100644 --- a/xbmc/cores/dvdplayer/DVDDemuxers/DVDDemux.h +++ b/xbmc/cores/dvdplayer/DVDDemuxers/DVDDemux.h @@ -171,6 +171,7 @@ public: bool bForcedAspect; // aspect is forced from container int iOrientation; // orientation of the video in degress counter clockwise int iBitsPerPixel; + std::string stereo_mode; // expected stereo mode }; class CDemuxStreamAudio : public CDemuxStream diff --git a/xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxFFmpeg.cpp b/xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxFFmpeg.cpp index 9c395dace3..4e7ca894bf 100644 --- a/xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxFFmpeg.cpp +++ b/xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxFFmpeg.cpp @@ -1140,6 +1140,11 @@ CDemuxStream* CDVDDemuxFFmpeg::AddStream(int iId) AVDictionaryEntry *rtag = m_dllAvUtil.av_dict_get(pStream->metadata, "rotate", NULL, 0); if (rtag) st->iOrientation = atoi(rtag->value); + + rtag = m_dllAvUtil.av_dict_get(pStream->metadata, "stereo_mode", NULL, 0); + if (rtag && rtag->value) + st->stereo_mode = rtag->value; + if ( m_pInput->IsStreamType(DVDSTREAM_TYPE_DVD) ) { diff --git a/xbmc/cores/dvdplayer/DVDPlayer.cpp b/xbmc/cores/dvdplayer/DVDPlayer.cpp index 1246b9f060..27e9ff149a 100644 --- a/xbmc/cores/dvdplayer/DVDPlayer.cpp +++ b/xbmc/cores/dvdplayer/DVDPlayer.cpp @@ -47,6 +47,7 @@ #include "utils/URIUtils.h" #include "GUIInfoManager.h" #include "guilib/GUIWindowManager.h" +#include "guilib/StereoscopicsManager.h" #include "Application.h" #include "ApplicationMessenger.h" #include "DVDPerformanceCounter.h" @@ -2918,6 +2919,9 @@ bool CDVDPlayer::OpenVideoStream(int iStream, int source, bool reset) if(pMenus && pMenus->IsInMenu()) hint.stills = true; + if (hint.stereo_mode.empty()) + hint.stereo_mode = CStereoscopicsManager::Get().DetectStereoModeByString(m_filename); + if(m_CurrentVideo.id < 0 || m_CurrentVideo.hint != hint) { @@ -3825,6 +3829,9 @@ void CDVDPlayer::GetVideoStreamInfo(SPlayerVideoStreamInfo &info) info.videoCodecName = retVal; info.videoAspectRatio = m_dvdPlayerVideo.GetAspectRatio(); m_dvdPlayerVideo.GetVideoRect(info.SrcRect, info.DestRect); + info.stereoMode = m_dvdPlayerVideo.GetStereoMode(); + if (info.stereoMode == "mono") + info.stereoMode = ""; } int CDVDPlayer::GetSourceBitrate() diff --git a/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp b/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp index 5bfbd1dedb..51caa05b2e 100644 --- a/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp +++ b/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp @@ -47,6 +47,7 @@ #include "utils/log.h" using namespace std; +using namespace RenderManager; class CPulldownCorrection { @@ -999,62 +1000,20 @@ static std::string GetRenderFormatName(ERenderFormat format) return "UNKNOWN"; } -static unsigned int GetFlagsColorMatrix(unsigned int color_matrix, unsigned width, unsigned height) +std::string CDVDPlayerVideo::GetStereoMode() { - switch(color_matrix) - { - case 7: // SMPTE 240M (1987) - return CONF_FLAGS_YUVCOEF_240M; - case 6: // SMPTE 170M - case 5: // ITU-R BT.470-2 - case 4: // FCC - return CONF_FLAGS_YUVCOEF_BT601; - case 1: // ITU-R Rec.709 (1990) -- BT.709 - return CONF_FLAGS_YUVCOEF_BT709; - case 3: // RESERVED - case 2: // UNSPECIFIED - default: - if(width > 1024 || height >= 600) - return CONF_FLAGS_YUVCOEF_BT709; - else - return CONF_FLAGS_YUVCOEF_BT601; - break; - } -} - -static unsigned int GetFlagsChromaPosition(unsigned int chroma_position) -{ - switch(chroma_position) - { - case 1: return CONF_FLAGS_CHROMA_LEFT; - case 2: return CONF_FLAGS_CHROMA_CENTER; - case 3: return CONF_FLAGS_CHROMA_TOPLEFT; - } - return 0; -} + std::string stereo_mode; -static unsigned int GetFlagsColorPrimaries(unsigned int color_primaries) -{ - switch(color_primaries) + switch(CMediaSettings::Get().GetCurrentVideoSettings().m_StereoMode) { - case 1: return CONF_FLAGS_COLPRI_BT709; - case 4: return CONF_FLAGS_COLPRI_BT470M; - case 5: return CONF_FLAGS_COLPRI_BT470BG; - case 6: return CONF_FLAGS_COLPRI_170M; - case 7: return CONF_FLAGS_COLPRI_240M; + case RENDER_STEREO_MODE_SPLIT_VERTICAL: stereo_mode = "left_right"; break; + case RENDER_STEREO_MODE_SPLIT_HORIZONTAL: stereo_mode = "top_bottom"; break; + default: stereo_mode = m_hints.stereo_mode; break; } - return 0; -} -static unsigned int GetFlagsColorTransfer(unsigned int color_transfer) -{ - switch(color_transfer) - { - case 1: return CONF_FLAGS_TRC_BT709; - case 4: return CONF_FLAGS_TRC_GAMMA22; - case 5: return CONF_FLAGS_TRC_GAMMA28; - } - return 0; + if(CMediaSettings::Get().GetCurrentVideoSettings().m_StereoInvert) + stereo_mode = GetStereoModeInvert(stereo_mode); + return stereo_mode; } int CDVDPlayerVideo::OutputPicture(const DVDVideoPicture* src, double pts) @@ -1063,6 +1022,13 @@ int CDVDPlayerVideo::OutputPicture(const DVDVideoPicture* src, double pts) DVDVideoPicture picture(*src); DVDVideoPicture* pPicture = &picture; + /* grab stereo mode from image if available */ + if(src->stereo_mode[0]) + m_hints.stereo_mode = src->stereo_mode; + + /* figure out steremode expected based on user settings and hints */ + unsigned int stereo_flags = GetStereoModeFlags(GetStereoMode()); + #ifdef HAS_VIDEO_PLAYBACK double config_framerate = m_bFpsInvalid ? 0.0 : m_fFrameRate; /* check so that our format or aspect has changed. if it has, reconfigure renderer */ @@ -1078,7 +1044,8 @@ int CDVDPlayerVideo::OutputPicture(const DVDVideoPicture* src, double pts) || ( m_output.chroma_position != pPicture->chroma_position && pPicture->chroma_position != 0 ) || ( m_output.color_primaries != pPicture->color_primaries && pPicture->color_primaries != 0 ) || ( m_output.color_transfer != pPicture->color_transfer && pPicture->color_transfer != 0 ) - || ( m_output.color_range != pPicture->color_range )) + || ( m_output.color_range != pPicture->color_range ) + || ( m_output.stereo_flags != stereo_flags)) { CLog::Log(LOGNOTICE, " fps: %f, pwidth: %i, pheight: %i, dwidth: %i, dheight: %i" , config_framerate @@ -1104,6 +1071,8 @@ int CDVDPlayerVideo::OutputPicture(const DVDVideoPicture* src, double pts) m_bAllowFullscreen = false; // only allow on first configure } + flags |= stereo_flags; + CLog::Log(LOGDEBUG,"%s - change configuration. %dx%d. framerate: %4.2f. format: %s",__FUNCTION__,pPicture->iWidth, pPicture->iHeight, config_framerate, formatstr.c_str()); if(!g_renderManager.Configure(pPicture->iWidth , pPicture->iHeight @@ -1132,6 +1101,7 @@ int CDVDPlayerVideo::OutputPicture(const DVDVideoPicture* src, double pts) m_output.color_primaries = pPicture->color_primaries; m_output.color_transfer = pPicture->color_transfer; m_output.color_range = pPicture->color_range; + m_output.stereo_flags = stereo_flags; } int result = 0; diff --git a/xbmc/cores/dvdplayer/DVDPlayerVideo.h b/xbmc/cores/dvdplayer/DVDPlayerVideo.h index 0aee790578..f8ad541224 100644 --- a/xbmc/cores/dvdplayer/DVDPlayerVideo.h +++ b/xbmc/cores/dvdplayer/DVDPlayerVideo.h @@ -87,6 +87,7 @@ public: double GetOutputDelay(); /* returns the expected delay, from that a packet is put in queue */ std::string GetPlayerInfo(); int GetVideoBitrate(); + std::string GetStereoMode(); void SetSpeed(int iSpeed); @@ -153,6 +154,7 @@ protected: unsigned int chroma_position; unsigned int color_primaries; unsigned int color_transfer; + unsigned int stereo_flags; double framerate; } m_output; //holds currently configured output diff --git a/xbmc/cores/dvdplayer/DVDStreamInfo.cpp b/xbmc/cores/dvdplayer/DVDStreamInfo.cpp index be21939932..e1dd87f688 100644 --- a/xbmc/cores/dvdplayer/DVDStreamInfo.cpp +++ b/xbmc/cores/dvdplayer/DVDStreamInfo.cpp @@ -63,6 +63,7 @@ void CDVDStreamInfo::Clear() forced_aspect = false; bitsperpixel = 0; pid = 0; + stereo_mode.clear(); channels = 0; samplerate = 0; @@ -103,7 +104,8 @@ bool CDVDStreamInfo::Equal(const CDVDStreamInfo& right, bool withextradata) || forced_aspect != right.forced_aspect || bitsperpixel != right.bitsperpixel || pid != right.pid - || vfr != right.vfr) return false; + || vfr != right.vfr + || stereo_mode != right.stereo_mode ) return false; // AUDIO if( channels != right.channels @@ -164,6 +166,7 @@ void CDVDStreamInfo::Assign(const CDVDStreamInfo& right, bool withextradata) pid = right.pid; vfr = right.vfr; software = right.software; + stereo_mode = right.stereo_mode; // AUDIO channels = right.channels; @@ -217,6 +220,7 @@ void CDVDStreamInfo::Assign(const CDemuxStream& right, bool withextradata) orientation = stream->iOrientation; bitsperpixel = stream->iBitsPerPixel; pid = stream->iPhysicalId; + stereo_mode = stream->stereo_mode; } else if( right.type == STREAM_SUBTITLE ) { diff --git a/xbmc/cores/dvdplayer/DVDStreamInfo.h b/xbmc/cores/dvdplayer/DVDStreamInfo.h index dd71e5484f..8aa9b95d63 100644 --- a/xbmc/cores/dvdplayer/DVDStreamInfo.h +++ b/xbmc/cores/dvdplayer/DVDStreamInfo.h @@ -67,6 +67,7 @@ public: int orientation; // orientation of the video in degress counter clockwise int bitsperpixel; int pid; + std::string stereo_mode; // stereoscopic 3d mode // AUDIO int channels; diff --git a/xbmc/cores/omxplayer/OMXPlayer.cpp b/xbmc/cores/omxplayer/OMXPlayer.cpp index b3d43145a2..31b690c2fe 100644 --- a/xbmc/cores/omxplayer/OMXPlayer.cpp +++ b/xbmc/cores/omxplayer/OMXPlayer.cpp @@ -81,6 +81,7 @@ #include "utils/URIUtils.h" #include "GUIInfoManager.h" #include "guilib/GUIWindowManager.h" +#include "guilib/StereoscopicsManager.h" #include "Application.h" #include "ApplicationMessenger.h" #include "DVDPerformanceCounter.h" @@ -3181,6 +3182,9 @@ bool COMXPlayer::OpenVideoStream(int iStream, int source, bool reset) if(pMenus && pMenus->IsInMenu()) hint.stills = true; + if (hint.stereo_mode.empty()) + hint.stereo_mode = CStereoscopicsManager::Get().DetectStereoModeByString(m_filename); + if(m_CurrentVideo.id < 0 || m_CurrentVideo.hint != hint) { @@ -3205,13 +3209,6 @@ bool COMXPlayer::OpenVideoStream(int iStream, int source, bool reset) else if (reset) m_omxPlayerVideo.SendMessage(new CDVDMsg(CDVDMsg::GENERAL_RESET)); - unsigned flags = 0; - if(m_filename.find("3DSBS") != string::npos || m_filename.find("HSBS") != string::npos) - flags = CONF_FLAGS_FORMAT_SBS; - else if(m_filename.find("3DTAB") != string::npos || m_filename.find("HTAB") != string::npos) - flags = CONF_FLAGS_FORMAT_TB; - m_omxPlayerVideo.SetFlags(flags); - /* store information about stream */ m_CurrentVideo.id = iStream; m_CurrentVideo.source = source; @@ -4094,6 +4091,10 @@ void COMXPlayer::GetVideoStreamInfo(SPlayerVideoStreamInfo &info) info.videoCodecName = retVal; info.videoAspectRatio = g_renderManager.GetAspectRatio(); g_renderManager.GetVideoRect(info.SrcRect, info.DestRect); + if (m_CurrentVideo.hint.stereo_mode == "mono") + info.stereoMode = ""; + else + info.stereoMode = m_CurrentVideo.hint.stereo_mode; } int COMXPlayer::GetSourceBitrate() diff --git a/xbmc/cores/omxplayer/OMXPlayerVideo.cpp b/xbmc/cores/omxplayer/OMXPlayerVideo.cpp index d621b7509c..e75f28512f 100644 --- a/xbmc/cores/omxplayer/OMXPlayerVideo.cpp +++ b/xbmc/cores/omxplayer/OMXPlayerVideo.cpp @@ -50,6 +50,8 @@ #include "OMXPlayer.h" #include "linux/RBP.h" +using namespace RenderManager; + class COMXMsgVideoCodecChange : public CDVDMsg { public: @@ -615,6 +617,11 @@ int OMXPlayerVideo::GetFreeSpace() void OMXPlayerVideo::SetVideoRect(const CRect &SrcRect, const CRect &DestRect) { + // in 3d modes skip this - we get called as the gui switches from left eye to right eye + unsigned flags = GetStereoModeFlags(m_hints.stereo_mode); + if (CONF_FLAGS_STEREO_MODE_MASK(flags)) + return; + // check if destination rect or video view mode has changed if ((m_dst_rect != DestRect) || (m_view_mode != CMediaSettings::Get().GetCurrentVideoSettings().m_ViewMode)) { @@ -638,9 +645,6 @@ void OMXPlayerVideo::SetVideoRect(const CRect &SrcRect, const CRect &DestRect) { float xscale = display.Width() / gui.Width(); float yscale = display.Height() / gui.Height(); - // video is displayed in absolute coordinates (bypassing half width or height GUI mode) - if (m_flags & CONF_FLAGS_FORMAT_SBS) xscale *= 2.0f; - if (m_flags & CONF_FLAGS_FORMAT_TB) yscale *= 2.0f; dst_rect.x1 *= xscale; dst_rect.x2 *= xscale; dst_rect.y1 *= yscale; @@ -670,22 +674,30 @@ void OMXPlayerVideo::ResolutionUpdateCallBack(uint32_t width, uint32_t height, f m_bAllowFullscreen = false; // only allow on first configure } - if(m_flags & CONF_FLAGS_FORMAT_SBS) + flags |= GetStereoModeFlags(m_hints.stereo_mode); + + if(flags & CONF_FLAGS_STEREO_MODE_SBS) { if(g_Windowing.Support3D(video_width, video_height, D3DPRESENTFLAG_MODE3DSBS)) - { CLog::Log(LOGNOTICE, "3DSBS movie found"); - flags |= CONF_FLAGS_FORMAT_SBS; + else + { + flags &= ~CONF_FLAGS_STEREO_MODE_MASK(~0); + CLog::Log(LOGNOTICE, "3DSBS movie found but not supported"); } } - else if(m_flags & CONF_FLAGS_FORMAT_TB) + else if(flags & CONF_FLAGS_STEREO_MODE_TAB) { if(g_Windowing.Support3D(video_width, video_height, D3DPRESENTFLAG_MODE3DTB)) - { CLog::Log(LOGNOTICE, "3DTB movie found"); - flags |= CONF_FLAGS_FORMAT_TB; + else + { + flags &= ~CONF_FLAGS_STEREO_MODE_MASK(~0); + CLog::Log(LOGNOTICE, "3DTB movie found but not supported"); } } + else + CLog::Log(LOGNOTICE, "not a 3D movie"); unsigned int iDisplayWidth = width; unsigned int iDisplayHeight = height; diff --git a/xbmc/dialogs/GUIDialogSelect.cpp b/xbmc/dialogs/GUIDialogSelect.cpp index 2865e2921d..1b7d4166f3 100644 --- a/xbmc/dialogs/GUIDialogSelect.cpp +++ b/xbmc/dialogs/GUIDialogSelect.cpp @@ -161,10 +161,11 @@ void CGUIDialogSelect::Reset() m_selectedItems->Clear(); } -void CGUIDialogSelect::Add(const CStdString& strLabel) +int CGUIDialogSelect::Add(const CStdString& strLabel) { CFileItemPtr pItem(new CFileItem(strLabel)); m_vecList->Add(pItem); + return m_vecList->Size() - 1; } void CGUIDialogSelect::Add(const CFileItemList& items) @@ -176,10 +177,11 @@ void CGUIDialogSelect::Add(const CFileItemList& items) } } -void CGUIDialogSelect::Add(const CFileItem* pItem) +int CGUIDialogSelect::Add(const CFileItem* pItem) { CFileItemPtr item(new CFileItem(*pItem)); m_vecList->Add(item); + return m_vecList->Size() - 1; } void CGUIDialogSelect::SetItems(CFileItemList* pList) diff --git a/xbmc/dialogs/GUIDialogSelect.h b/xbmc/dialogs/GUIDialogSelect.h index 373e89e1c1..2655b8c274 100644 --- a/xbmc/dialogs/GUIDialogSelect.h +++ b/xbmc/dialogs/GUIDialogSelect.h @@ -37,8 +37,8 @@ public: virtual bool OnBack(int actionID); void Reset(); - void Add(const CStdString& strLabel); - void Add(const CFileItem* pItem); + int Add(const CStdString& strLabel); + int Add(const CFileItem* pItem); void Add(const CFileItemList& items); void SetItems(CFileItemList* items); int GetSelectedLabel() const; diff --git a/xbmc/guilib/GUIFadeLabelControl.cpp b/xbmc/guilib/GUIFadeLabelControl.cpp index 64f4761161..fe056aa25d 100644 --- a/xbmc/guilib/GUIFadeLabelControl.cpp +++ b/xbmc/guilib/GUIFadeLabelControl.cpp @@ -146,6 +146,9 @@ void CGUIFadeLabelControl::Process(unsigned int currentTime, CDirtyRegionList &d m_fadeAnim.QueueAnimation(ANIM_PROCESS_REVERSE); } } + + m_textLayout.UpdateScrollinfo(m_scrollInfo); + g_graphicsContext.RemoveTransform(); } diff --git a/xbmc/guilib/GUIFont.cpp b/xbmc/guilib/GUIFont.cpp index d2eaba906a..63ecf856bf 100644 --- a/xbmc/guilib/GUIFont.cpp +++ b/xbmc/guilib/GUIFont.cpp @@ -111,24 +111,8 @@ void CGUIFont::DrawText( float x, float y, const vecColors &colors, color_t shad g_graphicsContext.RestoreClipRegion(); } -void CGUIFont::DrawScrollingText(float x, float y, const vecColors &colors, color_t shadowColor, - const vecText &text, uint32_t alignment, float maxWidth, CScrollInfo &scrollInfo) +bool CGUIFont::UpdateScrollInfo(const vecText &text, CScrollInfo &scrollInfo) { - if (!m_font) return; - if (!shadowColor) shadowColor = m_shadowColor; - - float spaceWidth = GetCharWidth(L' '); - // max chars on screen + extra margin chars - vecText::size_type maxChars = - std::min<vecText::size_type>( - (text.size() + (vecText::size_type)scrollInfo.suffix.size()), - (vecText::size_type)((maxWidth * 1.05f) / spaceWidth)); - - if (!text.size() || ClippedRegionIsEmpty(x, y, maxWidth, alignment)) - return; // nothing to render - - maxWidth = ROUND(maxWidth / g_graphicsContext.GetGUIScaleX()); - // draw at our scroll position // we handle the scrolling as follows: // We scroll on a per-pixel basis up until we have scrolled the first character outside @@ -137,62 +121,97 @@ void CGUIFont::DrawScrollingText(float x, float y, const vecColors &colors, colo // pixelPos is the amount in pixels to move the string by. // characterPos is the amount in characters to rotate the string by. // - float offset = scrollInfo.pixelPos; - if (!scrollInfo.waitTime) + if (scrollInfo.waitTime) + { + scrollInfo.waitTime--; + return false; + } + + if (text.empty()) + return false; + + CScrollInfo old(scrollInfo); + + // move along by the appropriate scroll amount + float scrollAmount = fabs(scrollInfo.GetPixelsPerFrame() * g_graphicsContext.GetGUIScaleX()); + + if (scrollInfo.pixelSpeed > 0) { - // move along by the appropriate scroll amount - float scrollAmount = fabs(scrollInfo.GetPixelsPerFrame() * g_graphicsContext.GetGUIScaleX()); - - if (scrollInfo.pixelSpeed > 0) - { - // we want to move scrollAmount, grab the next character - float charWidth = GetCharWidth(scrollInfo.GetCurrentChar(text)); - if (scrollInfo.pixelPos + scrollAmount < charWidth) - scrollInfo.pixelPos += scrollAmount; // within the current character - else - { // past the current character, decrement scrollAmount by the charWidth and move to the next character - while (scrollInfo.pixelPos + scrollAmount >= charWidth) + // we want to move scrollAmount, grab the next character + float charWidth = GetCharWidth(scrollInfo.GetCurrentChar(text)); + if (scrollInfo.pixelPos + scrollAmount < charWidth) + scrollInfo.pixelPos += scrollAmount; // within the current character + else + { // past the current character, decrement scrollAmount by the charWidth and move to the next character + while (scrollInfo.pixelPos + scrollAmount >= charWidth) + { + scrollAmount -= (charWidth - scrollInfo.pixelPos); + scrollInfo.pixelPos = 0; + scrollInfo.characterPos++; + if (scrollInfo.characterPos >= text.size() + scrollInfo.suffix.size()) { - scrollAmount -= (charWidth - scrollInfo.pixelPos); - scrollInfo.pixelPos = 0; - scrollInfo.characterPos++; - if (scrollInfo.characterPos >= text.size() + scrollInfo.suffix.size()) - { - scrollInfo.Reset(); - break; - } - charWidth = GetCharWidth(scrollInfo.GetCurrentChar(text)); + scrollInfo.Reset(); + break; } + charWidth = GetCharWidth(scrollInfo.GetCurrentChar(text)); } - offset = scrollInfo.pixelPos; } - else if (scrollInfo.pixelSpeed < 0) - { // scrolling backwards - // we want to move scrollAmount, grab the next character - float charWidth = GetCharWidth(scrollInfo.GetCurrentChar(text)); - if (scrollInfo.pixelPos + scrollAmount < charWidth) - scrollInfo.pixelPos += scrollAmount; // within the current character - else - { // past the current character, decrement scrollAmount by the charWidth and move to the next character - while (scrollInfo.pixelPos + scrollAmount >= charWidth) + } + else if (scrollInfo.pixelSpeed < 0) + { // scrolling backwards + // we want to move scrollAmount, grab the next character + float charWidth = GetCharWidth(scrollInfo.GetCurrentChar(text)); + if (scrollInfo.pixelPos + scrollAmount < charWidth) + scrollInfo.pixelPos += scrollAmount; // within the current character + else + { // past the current character, decrement scrollAmount by the charWidth and move to the next character + while (scrollInfo.pixelPos + scrollAmount >= charWidth) + { + scrollAmount -= (charWidth - scrollInfo.pixelPos); + scrollInfo.pixelPos = 0; + if (scrollInfo.characterPos == 0) { - scrollAmount -= (charWidth - scrollInfo.pixelPos); - scrollInfo.pixelPos = 0; - if (scrollInfo.characterPos == 0) - { - scrollInfo.Reset(); - scrollInfo.characterPos = text.size() + scrollInfo.suffix.size() - 1; - break; - } - scrollInfo.characterPos--; - charWidth = GetCharWidth(scrollInfo.GetCurrentChar(text)); + scrollInfo.Reset(); + scrollInfo.characterPos = text.size() + scrollInfo.suffix.size() - 1; + break; } + scrollInfo.characterPos--; + charWidth = GetCharWidth(scrollInfo.GetCurrentChar(text)); } - offset = charWidth - scrollInfo.pixelPos; } } + + if(scrollInfo.characterPos != old.characterPos + || scrollInfo.pixelPos != old.pixelPos) + return true; else - scrollInfo.waitTime--; + return false; +} + +void CGUIFont::DrawScrollingText(float x, float y, const vecColors &colors, color_t shadowColor, + const vecText &text, uint32_t alignment, float maxWidth, const CScrollInfo &scrollInfo) +{ + if (!m_font) return; + if (!shadowColor) shadowColor = m_shadowColor; + + float spaceWidth = GetCharWidth(L' '); + // max chars on screen + extra margin chars + vecText::size_type maxChars = + std::min<vecText::size_type>( + (text.size() + (vecText::size_type)scrollInfo.suffix.size()), + (vecText::size_type)((maxWidth * 1.05f) / spaceWidth)); + + if (!text.size() || ClippedRegionIsEmpty(x, y, maxWidth, alignment)) + return; // nothing to render + + maxWidth = ROUND(maxWidth / g_graphicsContext.GetGUIScaleX()); + + float charWidth = GetCharWidth(scrollInfo.GetCurrentChar(text)); + float offset; + if(scrollInfo.pixelSpeed >= 0) + offset = scrollInfo.pixelPos; + else + offset = charWidth - scrollInfo.pixelPos; // Now rotate our string as needed, only take a slightly larger then visible part of the text. unsigned int pos = scrollInfo.characterPos; diff --git a/xbmc/guilib/GUIFont.h b/xbmc/guilib/GUIFont.h index 50bcdcf29c..c55db48250 100644 --- a/xbmc/guilib/GUIFont.h +++ b/xbmc/guilib/GUIFont.h @@ -123,7 +123,9 @@ public: const vecText &text, uint32_t alignment, float maxPixelWidth); void DrawScrollingText( float x, float y, const vecColors &colors, color_t shadowColor, - const vecText &text, uint32_t alignment, float maxPixelWidth, CScrollInfo &scrollInfo); + const vecText &text, uint32_t alignment, float maxPixelWidth, const CScrollInfo &scrollInfo); + + bool UpdateScrollInfo(const vecText &text, CScrollInfo &scrollInfo); float GetTextWidth( const vecText &text ); float GetCharWidth( character_t ch ); diff --git a/xbmc/guilib/GUIFontManager.cpp b/xbmc/guilib/GUIFontManager.cpp index 68e4507ccb..bef28832f0 100644 --- a/xbmc/guilib/GUIFontManager.cpp +++ b/xbmc/guilib/GUIFontManager.cpp @@ -61,7 +61,7 @@ void GUIFontManager::RescaleFontSizeAndAspect(float *size, float *aspect, const if (preserveAspect) { // font always displayed in the aspect specified by the aspect parameter - *aspect /= g_graphicsContext.GetPixelRatio(g_graphicsContext.GetVideoResolution()); + *aspect /= g_graphicsContext.GetResInfo().fPixelRatio; } else { diff --git a/xbmc/guilib/GUILabel.cpp b/xbmc/guilib/GUILabel.cpp index 98916ce003..527e18fedd 100644 --- a/xbmc/guilib/GUILabel.cpp +++ b/xbmc/guilib/GUILabel.cpp @@ -89,6 +89,11 @@ bool CGUILabel::Process(unsigned int currentTime) // TODO Add the correct processing bool overFlows = (m_renderRect.Width() + 0.5f < m_textLayout.GetTextWidth()); // 0.5f to deal with floating point rounding issues + bool renderSolid = (m_color == COLOR_DISABLED); + + if (overFlows && m_scrolling && !renderSolid) + m_textLayout.UpdateScrollinfo(m_scrollInfo); + return (overFlows && m_scrolling); } diff --git a/xbmc/guilib/GUIRSSControl.cpp b/xbmc/guilib/GUIRSSControl.cpp index d8865673c6..e79cbd77ef 100644 --- a/xbmc/guilib/GUIRSSControl.cpp +++ b/xbmc/guilib/GUIRSSControl.cpp @@ -47,7 +47,7 @@ CGUIRSSControl::CGUIRSSControl(int parentID, int controlID, float posX, float po } CGUIRSSControl::CGUIRSSControl(const CGUIRSSControl &from) -: CGUIControl(from),m_scrollInfo(from.m_scrollInfo) +: CGUIControl(from),m_scrollInfo(from.m_scrollInfo), m_dirty(true) { m_label = from.m_label; m_headlineColor = from.m_headlineColor; @@ -89,40 +89,32 @@ bool CGUIRSSControl::UpdateColors() changed |= m_label.UpdateColors(); changed |= m_headlineColor.Update(); changed |= m_channelColor.Update(); - return changed; } void CGUIRSSControl::Process(unsigned int currentTime, CDirtyRegionList &dirtyregions) { - // TODO Proper processing which marks when its actually changed. Just mark always for now. - MarkDirtyRegion(); - - CGUIControl::Process(currentTime, dirtyregions); -} - -void CGUIRSSControl::Render() -{ - // only render the control if they are enabled + bool dirty = false; if (CSettings::Get().GetBool("lookandfeel.enablerssfeeds") && CRssManager::Get().IsActive()) { CSingleLock lock(m_criticalSection); // Create RSS background/worker thread if needed if (m_pReader == NULL) { + RssUrls::const_iterator iter = CRssManager::Get().GetUrls().find(m_urlset); - if (iter == CRssManager::Get().GetUrls().end()) + if (iter != CRssManager::Get().GetUrls().end()) { - CGUIControl::Render(); - return; + m_rtl = iter->second.rtl; + m_vecUrls = iter->second.url; + m_vecIntervals = iter->second.interval; + if (m_scrollInfo.pixelSpeed > 0 && m_rtl) + m_scrollInfo.pixelSpeed *= -1; + else if (m_scrollInfo.pixelSpeed < 0 && !m_rtl) + m_scrollInfo.pixelSpeed *= -1; } - m_rtl = iter->second.rtl; - m_vecUrls = iter->second.url; - m_vecIntervals = iter->second.interval; - if (m_scrollInfo.pixelSpeed > 0 && m_rtl) - m_scrollInfo.pixelSpeed *= -1; - else if (m_scrollInfo.pixelSpeed < 0 && !m_rtl) - m_scrollInfo.pixelSpeed *= -1; + + dirty = true; if (CRssManager::Get().GetReader(GetID(), GetParentID(), this, m_pReader)) m_scrollInfo.characterPos = m_pReader->m_SavedScrollPos; @@ -143,18 +135,40 @@ void CGUIRSSControl::Render() } } + if(m_dirty) + dirty = true; + m_dirty = false; + if (m_label.font) { - vecColors colors; - colors.push_back(m_label.textColor); - colors.push_back(m_headlineColor); - colors.push_back(m_channelColor); - if ( m_stopped ) m_scrollInfo.SetSpeed(0); else m_scrollInfo.SetSpeed(m_label.scrollSpeed); + if(m_label.font->UpdateScrollInfo(m_feed, m_scrollInfo)) + dirty = true; + } + } + + if(dirty) + MarkDirtyRegion(); + + CGUIControl::Process(currentTime, dirtyregions); +} + +void CGUIRSSControl::Render() +{ + // only render the control if they are enabled + if (CSettings::Get().GetBool("lookandfeel.enablerssfeeds") && CRssManager::Get().IsActive()) + { + + if (m_label.font) + { + vecColors colors; + colors.push_back(m_label.textColor); + colors.push_back(m_headlineColor); + colors.push_back(m_channelColor); m_label.font->DrawScrollingText(m_posX, m_posY, colors, m_label.shadowColor, m_feed, 0, m_width, m_scrollInfo); } @@ -178,6 +192,7 @@ void CGUIRSSControl::OnFeedUpdate(const vecText &feed) { CSingleLock lock(m_criticalSection); m_feed = feed; + m_dirty = true; } void CGUIRSSControl::OnFeedRelease() diff --git a/xbmc/guilib/GUIRSSControl.h b/xbmc/guilib/GUIRSSControl.h index 30d4c72b65..fa23842fde 100644 --- a/xbmc/guilib/GUIRSSControl.h +++ b/xbmc/guilib/GUIRSSControl.h @@ -79,6 +79,7 @@ protected: std::vector<int> m_vecIntervals; bool m_rtl; CScrollInfo m_scrollInfo; + bool m_dirty; bool m_stopped; int m_urlset; }; diff --git a/xbmc/guilib/GUITextLayout.cpp b/xbmc/guilib/GUITextLayout.cpp index a0ce9b6c50..57715a5b12 100644 --- a/xbmc/guilib/GUITextLayout.cpp +++ b/xbmc/guilib/GUITextLayout.cpp @@ -98,8 +98,18 @@ void CGUITextLayout::Render(float x, float y, float angle, color_t color, color_ g_graphicsContext.RemoveTransform(); } +bool CGUITextLayout::UpdateScrollinfo(CScrollInfo &scrollInfo) +{ + if (!m_font) + return false; + if (m_lines.empty()) + return false; + + return m_font->UpdateScrollInfo(m_lines[0].m_text, scrollInfo); +} + -void CGUITextLayout::RenderScrolling(float x, float y, float angle, color_t color, color_t shadowColor, uint32_t alignment, float maxWidth, CScrollInfo &scrollInfo) +void CGUITextLayout::RenderScrolling(float x, float y, float angle, color_t color, color_t shadowColor, uint32_t alignment, float maxWidth, const CScrollInfo &scrollInfo) { if (!m_font) return; @@ -133,9 +143,7 @@ void CGUITextLayout::RenderScrolling(float x, float y, float angle, color_t colo const CGUIString &string = *i; m_font->DrawScrollingText(x, y, m_colors, shadowColor, string.m_text, alignment, maxWidth, scrollInfo); y += m_font->GetLineHeight(); - scrollInfo.pixelSpeed = 0; } - scrollInfo.pixelSpeed = speed; m_font->End(); if (angle) g_graphicsContext.RemoveTransform(); diff --git a/xbmc/guilib/GUITextLayout.h b/xbmc/guilib/GUITextLayout.h index ddfea2cf97..5146a28f9f 100644 --- a/xbmc/guilib/GUITextLayout.h +++ b/xbmc/guilib/GUITextLayout.h @@ -66,9 +66,11 @@ class CGUITextLayout public: CGUITextLayout(CGUIFont *font, bool wrap, float fHeight=0.0f, CGUIFont *borderFont = NULL); // this may need changing - we may just use this class to replace CLabelInfo completely + bool UpdateScrollinfo(CScrollInfo &scrollInfo); + // main function to render strings void Render(float x, float y, float angle, color_t color, color_t shadowColor, uint32_t alignment, float maxWidth, bool solid = false); - void RenderScrolling(float x, float y, float angle, color_t color, color_t shadowColor, uint32_t alignment, float maxWidth, CScrollInfo &scrollInfo); + void RenderScrolling(float x, float y, float angle, color_t color, color_t shadowColor, uint32_t alignment, float maxWidth, const CScrollInfo &scrollInfo); void RenderOutline(float x, float y, color_t color, color_t outlineColor, uint32_t alignment, float maxWidth); /*! \brief Returns the precalculated width and height of the text to be rendered (in constant time). diff --git a/xbmc/guilib/Geometry.h b/xbmc/guilib/Geometry.h index 8d5b6ca527..a7c1229c91 100644 --- a/xbmc/guilib/Geometry.h +++ b/xbmc/guilib/Geometry.h @@ -92,6 +92,13 @@ public: CRectGen<T>() { x1 = y1 = x2 = y2 = 0;}; CRectGen<T>(T left, T top, T right, T bottom) { x1 = left; y1 = top; x2 = right; y2 = bottom; }; + CRectGen<T>(const CPointGen<T> &p1, const CPointGen<T> &p2) + { + x1 = p1.x; + y1 = p1.y; + x2 = p2.x; + y2 = p2.y; + } template <class U> CRectGen<T>(const CRectGen<U>& rhs) { @@ -158,6 +165,16 @@ public: return (x2 - x1) * (y2 - y1) == 0; }; + inline CPointGen<T> P1() const XBMC_FORCE_INLINE + { + return CPointGen<T>(x1, y1); + } + + inline CPointGen<T> P2() const XBMC_FORCE_INLINE + { + return CPointGen<T>(x2, y2); + } + inline T Width() const XBMC_FORCE_INLINE { return x2 - x1; diff --git a/xbmc/guilib/GraphicContext.cpp b/xbmc/guilib/GraphicContext.cpp index 7404779a40..2afc2d8e96 100644 --- a/xbmc/guilib/GraphicContext.cpp +++ b/xbmc/guilib/GraphicContext.cpp @@ -61,6 +61,9 @@ CGraphicContext::CGraphicContext(void) : /*m_guiTransform,*/ /*m_finalTransform, */ /*m_groupTransform*/ + , m_stereoView(RENDER_STEREO_VIEW_OFF) + , m_stereoMode(RENDER_STEREO_MODE_OFF) + , m_nextStereoMode(RENDER_STEREO_MODE_OFF) { } @@ -168,9 +171,6 @@ void CGraphicContext::ClipRect(CRect &vertex, CRect &texture, CRect *texture2) bool CGraphicContext::SetViewPort(float fx, float fy, float fwidth, float fheight, bool intersectPrevious /* = false */) { - CRect oldviewport; - g_Windowing.GetViewPort(oldviewport); - // transform coordinates - we may have a rotation which changes the positioning of the // minimal and maximal viewport extents. We currently go to the maximal extent. float x[4], y[4]; @@ -198,6 +198,7 @@ bool CGraphicContext::SetViewPort(float fx, float fy, float fwidth, float fheigh int newBottom = (int)(maxY + 0.5f); if (intersectPrevious) { + CRect oldviewport = m_viewStack.top(); // do the intersection int oldLeft = (int)oldviewport.x1; int oldTop = (int)oldviewport.y1; @@ -230,9 +231,12 @@ bool CGraphicContext::SetViewPort(float fx, float fy, float fwidth, float fheigh ASSERT(newTop < newBottom); CRect newviewport((float)newLeft, (float)newTop, (float)newRight, (float)newBottom); + + m_viewStack.push(newviewport); + + newviewport = StereoCorrection(newviewport); g_Windowing.SetViewPort(newviewport); - m_viewStack.push(oldviewport); UpdateCameraPosition(m_cameras.top()); return true; @@ -240,27 +244,54 @@ bool CGraphicContext::SetViewPort(float fx, float fy, float fwidth, float fheigh void CGraphicContext::RestoreViewPort() { - if (!m_viewStack.size()) return; - - CRect oldviewport = m_viewStack.top(); - g_Windowing.SetViewPort(oldviewport); + if (m_viewStack.size() <= 1) return; m_viewStack.pop(); + CRect viewport = StereoCorrection(m_viewStack.top()); + g_Windowing.SetViewPort(viewport); UpdateCameraPosition(m_cameras.top()); } +CPoint CGraphicContext::StereoCorrection(const CPoint &point) const +{ + CPoint res(point); + + if(m_stereoMode == RENDER_STEREO_MODE_SPLIT_HORIZONTAL) + { + const RESOLUTION_INFO info = GetResInfo(); + + if(m_stereoView == RENDER_STEREO_VIEW_RIGHT) + res.y += info.iHeight + info.iBlanking; + } + if(m_stereoMode == RENDER_STEREO_MODE_SPLIT_VERTICAL) + { + const RESOLUTION_INFO info = GetResInfo(); + + if(m_stereoView == RENDER_STEREO_VIEW_RIGHT) + res.x += info.iWidth + info.iBlanking; + } + return res; +} + +CRect CGraphicContext::StereoCorrection(const CRect &rect) const +{ + CRect res(StereoCorrection(rect.P1()) + , StereoCorrection(rect.P2())); + return res; +} + void CGraphicContext::SetScissors(const CRect &rect) { m_scissors = rect; m_scissors.Intersect(CRect(0,0,(float)m_iScreenWidth, (float)m_iScreenHeight)); - g_Windowing.SetScissors(m_scissors); + g_Windowing.SetScissors(StereoCorrection(m_scissors)); } void CGraphicContext::ResetScissors() { m_scissors.SetRect(0, 0, (float)m_iScreenWidth, (float)m_iScreenHeight); - g_Windowing.ResetScissors(); // SetScissors(m_scissors) instead? + g_Windowing.SetScissors(StereoCorrection(m_scissors)); } const CRect CGraphicContext::GetViewWindow() const @@ -268,10 +299,11 @@ const CRect CGraphicContext::GetViewWindow() const if (m_bCalibrating || m_bFullScreenVideo) { CRect rect; - rect.x1 = (float)CDisplaySettings::Get().GetResolutionInfo(m_Resolution).Overscan.left; - rect.y1 = (float)CDisplaySettings::Get().GetResolutionInfo(m_Resolution).Overscan.top; - rect.x2 = (float)CDisplaySettings::Get().GetResolutionInfo(m_Resolution).Overscan.right; - rect.y2 = (float)CDisplaySettings::Get().GetResolutionInfo(m_Resolution).Overscan.bottom; + RESOLUTION_INFO info = GetResInfo(); + rect.x1 = (float)info.Overscan.left; + rect.y1 = (float)info.Overscan.top; + rect.x2 = (float)info.Overscan.right; + rect.y2 = (float)info.Overscan.bottom; return rect; } return m_videoRect; @@ -377,9 +409,34 @@ void CGraphicContext::SetVideoResolution(RESOLUTION res, bool forceUpdate) Lock(); - m_iScreenWidth = CDisplaySettings::Get().GetResolutionInfo(res).iWidth; - m_iScreenHeight = CDisplaySettings::Get().GetResolutionInfo(res).iHeight; - m_iScreenId = CDisplaySettings::Get().GetResolutionInfo(res).iScreen; + RESOLUTION_INFO info_org = CDisplaySettings::Get().GetResolutionInfo(res); + RESOLUTION_INFO info_last = CDisplaySettings::Get().GetResolutionInfo(lastRes); + + RENDER_STEREO_MODE stereo_mode = m_stereoMode; + + // if the new mode is an actual stereo mode, switch to that + // if the old mode was an actual stereo mode, switch to no 3d mode + if (info_org.dwFlags & D3DPRESENTFLAG_MODE3DTB) + stereo_mode = RENDER_STEREO_MODE_SPLIT_HORIZONTAL; + else if (info_org.dwFlags & D3DPRESENTFLAG_MODE3DSBS) + stereo_mode = RENDER_STEREO_MODE_SPLIT_VERTICAL; + else if ((info_last.dwFlags & D3DPRESENTFLAG_MODE3DSBS) != 0 + || (info_last.dwFlags & D3DPRESENTFLAG_MODE3DTB) != 0) + stereo_mode = RENDER_STEREO_MODE_OFF; + + if(stereo_mode != m_stereoMode) + { + m_stereoView = RENDER_STEREO_VIEW_OFF; + m_stereoMode = stereo_mode; + m_nextStereoMode = stereo_mode; + CSettings::Get().SetInt("videoscreen.stereoscopicmode", (int)m_stereoMode); + } + + RESOLUTION_INFO info_mod = GetResInfo(res); + + m_iScreenWidth = info_mod.iWidth; + m_iScreenHeight = info_mod.iHeight; + m_iScreenId = info_mod.iScreen; m_scissors.SetRect(0, 0, (float)m_iScreenWidth, (float)m_iScreenHeight); m_Resolution = res; @@ -390,19 +447,22 @@ void CGraphicContext::SetVideoResolution(RESOLUTION res, bool forceUpdate) { #if defined (TARGET_DARWIN) || defined (TARGET_WINDOWS) bool blankOtherDisplays = CSettings::Get().GetBool("videoscreen.blankdisplays"); - g_Windowing.SetFullScreen(true, CDisplaySettings::Get().GetResolutionInfo(res), blankOtherDisplays); + g_Windowing.SetFullScreen(true, info_org, blankOtherDisplays); #else - g_Windowing.SetFullScreen(true, CDisplaySettings::Get().GetResolutionInfo(res), false); + g_Windowing.SetFullScreen(true, info_org, false); #endif } else if (lastRes >= RES_DESKTOP ) - g_Windowing.SetFullScreen(false, CDisplaySettings::Get().GetResolutionInfo(res), false); + g_Windowing.SetFullScreen(false, info_org, false); else - g_Windowing.ResizeWindow(m_iScreenWidth, m_iScreenHeight, -1, -1); + g_Windowing.ResizeWindow(info_org.iWidth, info_org.iHeight, -1, -1); + + // make sure all stereo stuff are correctly setup + SetStereoView(RENDER_STEREO_VIEW_OFF); // update anyone that relies on sizing information g_renderManager.Recover(); - g_Mouse.SetResolution(m_iScreenWidth, m_iScreenHeight, 1, 1); + g_Mouse.SetResolution(info_org.iWidth, info_org.iHeight, 1, 1); g_windowManager.SendMessage(GUI_MSG_NOTIFY_ALL, 0, 0, GUI_MSG_WINDOW_RESIZE); Unlock(); @@ -466,8 +526,9 @@ void CGraphicContext::ResetOverscan(RESOLUTION res, OVERSCAN &overscan) overscan.bottom = 576; break; default: - overscan.right = CDisplaySettings::Get().GetResolutionInfo(res).iWidth; - overscan.bottom = CDisplaySettings::Get().GetResolutionInfo(res).iHeight; + RESOLUTION_INFO info = GetResInfo(res); + overscan.right = info.iWidth; + overscan.bottom = info.iHeight; break; } } @@ -475,136 +536,135 @@ void CGraphicContext::ResetOverscan(RESOLUTION res, OVERSCAN &overscan) void CGraphicContext::ResetScreenParameters(RESOLUTION res) { // For now these are all on the first screen. - CDisplaySettings::Get().GetResolutionInfo(res).iScreen = 0; + RESOLUTION_INFO& info = CDisplaySettings::Get().GetResolutionInfo(res); + + info.iScreen = 0; // 1080i switch (res) { case RES_HDTV_1080i: - CDisplaySettings::Get().GetResolutionInfo(res).iSubtitles = (int)(0.965 * 1080); - CDisplaySettings::Get().GetResolutionInfo(res).iWidth = 1920; - CDisplaySettings::Get().GetResolutionInfo(res).iHeight = 1080; - CDisplaySettings::Get().GetResolutionInfo(res).dwFlags = D3DPRESENTFLAG_INTERLACED | D3DPRESENTFLAG_WIDESCREEN; - CDisplaySettings::Get().GetResolutionInfo(res).fPixelRatio = 1.0f; - CDisplaySettings::Get().GetResolutionInfo(res).strMode ="1080i 16:9"; + info.iSubtitles = (int)(0.965 * 1080); + info.iWidth = 1920; + info.iHeight = 1080; + info.dwFlags = D3DPRESENTFLAG_INTERLACED | D3DPRESENTFLAG_WIDESCREEN; + info.fPixelRatio = 1.0f; + info.strMode ="1080i 16:9"; break; case RES_HDTV_720pSBS: - CDisplaySettings::Get().GetResolutionInfo(res).iSubtitles = (int)(0.965 * 720); - CDisplaySettings::Get().GetResolutionInfo(res).iWidth = 640; - CDisplaySettings::Get().GetResolutionInfo(res).iHeight = 720; - CDisplaySettings::Get().GetResolutionInfo(res).dwFlags = D3DPRESENTFLAG_PROGRESSIVE | D3DPRESENTFLAG_WIDESCREEN | D3DPRESENTFLAG_MODE3DSBS; - CDisplaySettings::Get().GetResolutionInfo(res).fPixelRatio = 1.0f; - CDisplaySettings::Get().GetResolutionInfo(res).strMode = "720pSBS 16:9"; + info.iSubtitles = (int)(0.965 * 720); + info.iWidth = 640; + info.iHeight = 720; + info.dwFlags = D3DPRESENTFLAG_PROGRESSIVE | D3DPRESENTFLAG_WIDESCREEN | D3DPRESENTFLAG_MODE3DSBS; + info.fPixelRatio = 2.0f; + info.strMode = "720pSBS 16:9"; break; case RES_HDTV_720pTB: - CDisplaySettings::Get().GetResolutionInfo(res).iSubtitles = (int)(0.965 * 360); - CDisplaySettings::Get().GetResolutionInfo(res).iWidth = 1280; - CDisplaySettings::Get().GetResolutionInfo(res).iHeight = 360; - CDisplaySettings::Get().GetResolutionInfo(res).dwFlags = D3DPRESENTFLAG_PROGRESSIVE | D3DPRESENTFLAG_WIDESCREEN | D3DPRESENTFLAG_MODE3DTB; - CDisplaySettings::Get().GetResolutionInfo(res).fPixelRatio = 1.0f; - CDisplaySettings::Get().GetResolutionInfo(res).strMode = "720pTB 16:9"; + info.iSubtitles = (int)(0.965 * 720); + info.iWidth = 1280; + info.iHeight = 720; + info.dwFlags = D3DPRESENTFLAG_PROGRESSIVE | D3DPRESENTFLAG_WIDESCREEN | D3DPRESENTFLAG_MODE3DTB; + info.fPixelRatio = 0.5f; + info.strMode = "720pTB 16:9"; break; case RES_HDTV_1080pSBS: - CDisplaySettings::Get().GetResolutionInfo(res).iSubtitles = (int)(0.965 * 1080); - CDisplaySettings::Get().GetResolutionInfo(res).iWidth = 960; - CDisplaySettings::Get().GetResolutionInfo(res).iHeight = 1080; - CDisplaySettings::Get().GetResolutionInfo(res).dwFlags = D3DPRESENTFLAG_PROGRESSIVE | D3DPRESENTFLAG_WIDESCREEN | D3DPRESENTFLAG_MODE3DSBS; - CDisplaySettings::Get().GetResolutionInfo(res).fPixelRatio = 1.0f; - CDisplaySettings::Get().GetResolutionInfo(res).strMode = "1080pSBS 16:9"; + info.iSubtitles = (int)(0.965 * 1080); + info.iWidth = 1920; + info.iHeight = 1080; + info.dwFlags = D3DPRESENTFLAG_PROGRESSIVE | D3DPRESENTFLAG_WIDESCREEN | D3DPRESENTFLAG_MODE3DSBS; + info.fPixelRatio = 2.0f; + info.strMode = "1080pSBS 16:9"; break; case RES_HDTV_1080pTB: - CDisplaySettings::Get().GetResolutionInfo(res).iSubtitles = (int)(0.965 * 540); - CDisplaySettings::Get().GetResolutionInfo(res).iWidth = 1920; - CDisplaySettings::Get().GetResolutionInfo(res).iHeight = 540; - CDisplaySettings::Get().GetResolutionInfo(res).dwFlags = D3DPRESENTFLAG_PROGRESSIVE | D3DPRESENTFLAG_WIDESCREEN | D3DPRESENTFLAG_MODE3DTB; - CDisplaySettings::Get().GetResolutionInfo(res).fPixelRatio = 1.0f; - CDisplaySettings::Get().GetResolutionInfo(res).strMode = "1080pTB 16:9"; + info.iSubtitles = (int)(0.965 * 1080); + info.iWidth = 1920; + info.iHeight = 1080; + info.dwFlags = D3DPRESENTFLAG_PROGRESSIVE | D3DPRESENTFLAG_WIDESCREEN | D3DPRESENTFLAG_MODE3DTB; + info.fPixelRatio = 0.5f; + info.strMode = "1080pTB 16:9"; break; case RES_HDTV_720p: - CDisplaySettings::Get().GetResolutionInfo(res).iSubtitles = (int)(0.965 * 720); - CDisplaySettings::Get().GetResolutionInfo(res).iWidth = 1280; - CDisplaySettings::Get().GetResolutionInfo(res).iHeight = 720; - CDisplaySettings::Get().GetResolutionInfo(res).dwFlags = D3DPRESENTFLAG_PROGRESSIVE | D3DPRESENTFLAG_WIDESCREEN; - CDisplaySettings::Get().GetResolutionInfo(res).fPixelRatio = 1.0f; - CDisplaySettings::Get().GetResolutionInfo(res).strMode = "720p 16:9"; + info.iSubtitles = (int)(0.965 * 720); + info.iWidth = 1280; + info.iHeight = 720; + info.dwFlags = D3DPRESENTFLAG_PROGRESSIVE | D3DPRESENTFLAG_WIDESCREEN; + info.fPixelRatio = 1.0f; + info.strMode = "720p 16:9"; break; case RES_HDTV_480p_4x3: - CDisplaySettings::Get().GetResolutionInfo(res).iSubtitles = (int)(0.9 * 480); - CDisplaySettings::Get().GetResolutionInfo(res).iWidth = 720; - CDisplaySettings::Get().GetResolutionInfo(res).iHeight = 480; - CDisplaySettings::Get().GetResolutionInfo(res).dwFlags = D3DPRESENTFLAG_PROGRESSIVE; - CDisplaySettings::Get().GetResolutionInfo(res).fPixelRatio = 4320.0f / 4739.0f; - CDisplaySettings::Get().GetResolutionInfo(res).strMode = "480p 4:3"; + info.iSubtitles = (int)(0.9 * 480); + info.iWidth = 720; + info.iHeight = 480; + info.dwFlags = D3DPRESENTFLAG_PROGRESSIVE; + info.fPixelRatio = 4320.0f / 4739.0f; + info.strMode = "480p 4:3"; break; case RES_HDTV_480p_16x9: - CDisplaySettings::Get().GetResolutionInfo(res).iSubtitles = (int)(0.965 * 480); - CDisplaySettings::Get().GetResolutionInfo(res).iWidth = 720; - CDisplaySettings::Get().GetResolutionInfo(res).iHeight = 480; - CDisplaySettings::Get().GetResolutionInfo(res).dwFlags = D3DPRESENTFLAG_PROGRESSIVE | D3DPRESENTFLAG_WIDESCREEN; - CDisplaySettings::Get().GetResolutionInfo(res).fPixelRatio = 4320.0f / 4739.0f*4.0f / 3.0f; - CDisplaySettings::Get().GetResolutionInfo(res).strMode = "480p 16:9"; + info.iSubtitles = (int)(0.965 * 480); + info.iWidth = 720; + info.iHeight = 480; + info.dwFlags = D3DPRESENTFLAG_PROGRESSIVE | D3DPRESENTFLAG_WIDESCREEN; + info.fPixelRatio = 4320.0f / 4739.0f*4.0f / 3.0f; + info.strMode = "480p 16:9"; break; case RES_NTSC_4x3: - CDisplaySettings::Get().GetResolutionInfo(res).iSubtitles = (int)(0.9 * 480); - CDisplaySettings::Get().GetResolutionInfo(res).iWidth = 720; - CDisplaySettings::Get().GetResolutionInfo(res).iHeight = 480; - CDisplaySettings::Get().GetResolutionInfo(res).dwFlags = D3DPRESENTFLAG_INTERLACED; - CDisplaySettings::Get().GetResolutionInfo(res).fPixelRatio = 4320.0f / 4739.0f; - CDisplaySettings::Get().GetResolutionInfo(res).strMode = "NTSC 4:3"; + info.iSubtitles = (int)(0.9 * 480); + info.iWidth = 720; + info.iHeight = 480; + info.dwFlags = D3DPRESENTFLAG_INTERLACED; + info.fPixelRatio = 4320.0f / 4739.0f; + info.strMode = "NTSC 4:3"; break; case RES_NTSC_16x9: - CDisplaySettings::Get().GetResolutionInfo(res).iSubtitles = (int)(0.965 * 480); - CDisplaySettings::Get().GetResolutionInfo(res).iWidth = 720; - CDisplaySettings::Get().GetResolutionInfo(res).iHeight = 480; - CDisplaySettings::Get().GetResolutionInfo(res).dwFlags = D3DPRESENTFLAG_INTERLACED | D3DPRESENTFLAG_WIDESCREEN; - CDisplaySettings::Get().GetResolutionInfo(res).fPixelRatio = 4320.0f / 4739.0f*4.0f / 3.0f; - CDisplaySettings::Get().GetResolutionInfo(res).strMode = "NTSC 16:9"; + info.iSubtitles = (int)(0.965 * 480); + info.iWidth = 720; + info.iHeight = 480; + info.dwFlags = D3DPRESENTFLAG_INTERLACED | D3DPRESENTFLAG_WIDESCREEN; + info.fPixelRatio = 4320.0f / 4739.0f*4.0f / 3.0f; + info.strMode = "NTSC 16:9"; break; case RES_PAL_4x3: - CDisplaySettings::Get().GetResolutionInfo(res).iSubtitles = (int)(0.9 * 576); - CDisplaySettings::Get().GetResolutionInfo(res).iWidth = 720; - CDisplaySettings::Get().GetResolutionInfo(res).iHeight = 576; - CDisplaySettings::Get().GetResolutionInfo(res).dwFlags = D3DPRESENTFLAG_INTERLACED; - CDisplaySettings::Get().GetResolutionInfo(res).fPixelRatio = 128.0f / 117.0f; - CDisplaySettings::Get().GetResolutionInfo(res).strMode = "PAL 4:3"; + info.iSubtitles = (int)(0.9 * 576); + info.iWidth = 720; + info.iHeight = 576; + info.dwFlags = D3DPRESENTFLAG_INTERLACED; + info.fPixelRatio = 128.0f / 117.0f; + info.strMode = "PAL 4:3"; break; case RES_PAL_16x9: - CDisplaySettings::Get().GetResolutionInfo(res).iSubtitles = (int)(0.965 * 576); - CDisplaySettings::Get().GetResolutionInfo(res).iWidth = 720; - CDisplaySettings::Get().GetResolutionInfo(res).iHeight = 576; - CDisplaySettings::Get().GetResolutionInfo(res).dwFlags = D3DPRESENTFLAG_INTERLACED | D3DPRESENTFLAG_WIDESCREEN; - CDisplaySettings::Get().GetResolutionInfo(res).fPixelRatio = 128.0f / 117.0f*4.0f / 3.0f; - CDisplaySettings::Get().GetResolutionInfo(res).strMode = "PAL 16:9"; + info.iSubtitles = (int)(0.965 * 576); + info.iWidth = 720; + info.iHeight = 576; + info.dwFlags = D3DPRESENTFLAG_INTERLACED | D3DPRESENTFLAG_WIDESCREEN; + info.fPixelRatio = 128.0f / 117.0f*4.0f / 3.0f; + info.strMode = "PAL 16:9"; break; case RES_PAL60_4x3: - CDisplaySettings::Get().GetResolutionInfo(res).iSubtitles = (int)(0.9 * 480); - CDisplaySettings::Get().GetResolutionInfo(res).iWidth = 720; - CDisplaySettings::Get().GetResolutionInfo(res).iHeight = 480; - CDisplaySettings::Get().GetResolutionInfo(res).dwFlags = D3DPRESENTFLAG_INTERLACED; - CDisplaySettings::Get().GetResolutionInfo(res).fPixelRatio = 4320.0f / 4739.0f; - CDisplaySettings::Get().GetResolutionInfo(res).strMode = "PAL60 4:3"; + info.iSubtitles = (int)(0.9 * 480); + info.iWidth = 720; + info.iHeight = 480; + info.dwFlags = D3DPRESENTFLAG_INTERLACED; + info.fPixelRatio = 4320.0f / 4739.0f; + info.strMode = "PAL60 4:3"; break; case RES_PAL60_16x9: - CDisplaySettings::Get().GetResolutionInfo(res).iSubtitles = (int)(0.965 * 480); - CDisplaySettings::Get().GetResolutionInfo(res).iWidth = 720; - CDisplaySettings::Get().GetResolutionInfo(res).iHeight = 480; - CDisplaySettings::Get().GetResolutionInfo(res).dwFlags = D3DPRESENTFLAG_INTERLACED | D3DPRESENTFLAG_WIDESCREEN; - CDisplaySettings::Get().GetResolutionInfo(res).fPixelRatio = 4320.0f / 4739.0f*4.0f / 3.0f; - CDisplaySettings::Get().GetResolutionInfo(res).strMode = "PAL60 16:9"; + info.iSubtitles = (int)(0.965 * 480); + info.iWidth = 720; + info.iHeight = 480; + info.dwFlags = D3DPRESENTFLAG_INTERLACED | D3DPRESENTFLAG_WIDESCREEN; + info.fPixelRatio = 4320.0f / 4739.0f*4.0f / 3.0f; + info.strMode = "PAL60 16:9"; + break; + case RES_WINDOW: + info.iSubtitles = (int)(0.965 * info.iHeight); + info.fPixelRatio = 1.0; break; default: break; } - CDisplaySettings::Get().GetResolutionInfo(res).iScreenWidth = CDisplaySettings::Get().GetResolutionInfo(res).iWidth; - CDisplaySettings::Get().GetResolutionInfo(res).iScreenHeight = CDisplaySettings::Get().GetResolutionInfo(res).iHeight; - ResetOverscan(res, CDisplaySettings::Get().GetResolutionInfo(res).Overscan); -} - -float CGraphicContext::GetPixelRatio(RESOLUTION iRes) const -{ - if (iRes >= 0 && iRes < (int)CDisplaySettings::Get().ResolutionInfoSize()) - return CDisplaySettings::Get().GetResolutionInfo(iRes).fPixelRatio; - return 0.0f; + info.iScreenWidth = info.iWidth; + info.iScreenHeight = info.iHeight; + ResetOverscan(res, info.Overscan); } void CGraphicContext::Clear(color_t color) @@ -622,11 +682,56 @@ void CGraphicContext::ApplyStateBlock() g_Windowing.ApplyStateBlock(); } -const RESOLUTION_INFO &CGraphicContext::GetResInfo() const +const RESOLUTION_INFO CGraphicContext::GetResInfo(RESOLUTION res) const { - return CDisplaySettings::Get().GetResolutionInfo(m_Resolution); + RESOLUTION_INFO info = CDisplaySettings::Get().GetResolutionInfo(res); + + if(m_stereoMode == RENDER_STEREO_MODE_SPLIT_HORIZONTAL) + { + if((info.dwFlags & D3DPRESENTFLAG_MODE3DTB) == 0) + { + info.fPixelRatio /= 2; + info.iBlanking = 0; + info.dwFlags |= D3DPRESENTFLAG_MODE3DTB; + } + info.iHeight = (info.iHeight - info.iBlanking) / 2; + info.Overscan.top /= 2; + info.Overscan.bottom = (info.Overscan.bottom - info.iBlanking) / 2; + info.iSubtitles = (info.iSubtitles - info.iBlanking) / 2; + } + + if(m_stereoMode == RENDER_STEREO_MODE_SPLIT_VERTICAL) + { + if((info.dwFlags & D3DPRESENTFLAG_MODE3DSBS) == 0) + { + info.fPixelRatio *= 2; + info.iBlanking = 0; + info.dwFlags |= D3DPRESENTFLAG_MODE3DSBS; + } + info.iWidth = (info.iWidth - info.iBlanking) / 2; + info.Overscan.left /= 2; + info.Overscan.right = (info.Overscan.right - info.iBlanking) / 2; + } + return info; +} + +void CGraphicContext::SetResInfo(RESOLUTION res, const RESOLUTION_INFO& info) +{ + RESOLUTION_INFO& curr = CDisplaySettings::Get().GetResolutionInfo(res); + curr.Overscan = info.Overscan; + curr.iSubtitles = info.iSubtitles; + + if(info.dwFlags & D3DPRESENTFLAG_MODE3DSBS) + curr.Overscan.right = info.Overscan.right * 2 + info.iBlanking; + + if(info.dwFlags & D3DPRESENTFLAG_MODE3DTB) + { + curr.Overscan.bottom = info.Overscan.bottom * 2 + info.iBlanking; + curr.iSubtitles = info.iSubtitles * 2 + info.iBlanking; + } } + void CGraphicContext::SetScalingResolution(const RESOLUTION_INFO &res, bool needsScaling) { Lock(); @@ -641,13 +746,15 @@ void CGraphicContext::SetScalingResolution(const RESOLUTION_INFO &res, bool need float fToWidth; float fToHeight; + RESOLUTION_INFO info = GetResInfo(); + { - fFromWidth = (float)res.iWidth; + fFromWidth = (float)res.iWidth; fFromHeight = (float)res.iHeight; - fToPosX = (float)CDisplaySettings::Get().GetResolutionInfo(m_Resolution).Overscan.left; - fToPosY = (float)CDisplaySettings::Get().GetResolutionInfo(m_Resolution).Overscan.top; - fToWidth = (float)CDisplaySettings::Get().GetResolutionInfo(m_Resolution).Overscan.right - fToPosX; - fToHeight = (float)CDisplaySettings::Get().GetResolutionInfo(m_Resolution).Overscan.bottom - fToPosY; + fToPosX = (float)info.Overscan.left; + fToPosY = (float)info.Overscan.top; + fToWidth = (float)info.Overscan.right - fToPosX; + fToHeight = (float)info.Overscan.bottom - fToPosY; } if(!g_guiSkinzoom) // lookup gui setting if we didn't have it already @@ -663,7 +770,7 @@ void CGraphicContext::SetScalingResolution(const RESOLUTION_INFO &res, bool need // adjust for aspect ratio as zoom is given in the vertical direction and we don't // do aspect ratio corrections in the gui code - fZoom = fZoom / CDisplaySettings::Get().GetResolutionInfo(m_Resolution).fPixelRatio; + fZoom = fZoom / info.fPixelRatio; fToPosY -= fToHeight * fZoom * 0.5f; fToHeight *= fZoom + 1.0f; @@ -679,6 +786,7 @@ void CGraphicContext::SetScalingResolution(const RESOLUTION_INFO &res, bool need m_guiScaleX = 1.0f; m_guiScaleY = 1.0f; } + // reset our origin and camera while (m_origins.size()) m_origins.pop(); @@ -702,10 +810,28 @@ void CGraphicContext::SetRenderingResolution(const RESOLUTION_INFO &res, bool ne void CGraphicContext::UpdateFinalTransform(const TransformMatrix &matrix) { - m_finalTransform = matrix; // We could set the world transform here to GPU-ize the animation system. // trouble is that we require the resulting x,y coords to be rounded to // the nearest pixel (vertex shader perhaps?) + m_finalTransform.Reset(); + m_finalTransform *= matrix; +} + +void CGraphicContext::SetStereoView(RENDER_STEREO_VIEW view) +{ + m_stereoView = view; + + while(m_viewStack.size()) + m_viewStack.pop(); + + CRect viewport(0.0f, 0.0f, (float)m_iScreenWidth, (float)m_iScreenHeight); + + m_viewStack.push(viewport); + + viewport = StereoCorrection(viewport); + g_Windowing.SetStereoMode(m_stereoMode, m_stereoView); + g_Windowing.SetViewPort(viewport); + g_Windowing.SetScissors(viewport); } void CGraphicContext::InvertFinalCoords(float &x, float &y) const @@ -717,13 +843,7 @@ float CGraphicContext::GetScalingPixelRatio() const { // assume the resolutions are different - we want to return the aspect ratio of the video resolution // but only once it's been corrected for the skin -> screen coordinates scaling - float winWidth = (float)m_windowResolution.iWidth; - float winHeight = (float)m_windowResolution.iHeight; - float outWidth = (float)CDisplaySettings::Get().GetResolutionInfo(m_Resolution).iWidth; - float outHeight = (float)CDisplaySettings::Get().GetResolutionInfo(m_Resolution).iHeight; - float outPR = GetPixelRatio(m_Resolution); - - return outPR * (outWidth / outHeight) / (winWidth / winHeight); + return GetResInfo().fPixelRatio * (m_guiScaleY / m_guiScaleX); } void CGraphicContext::SetCameraPosition(const CPoint &camera) @@ -805,8 +925,9 @@ float CGraphicContext::GetFPS() const { if (m_Resolution != RES_INVALID) { - if (CDisplaySettings::Get().GetResolutionInfo(m_Resolution).fRefreshRate > 0) - return CDisplaySettings::Get().GetResolutionInfo(m_Resolution).fRefreshRate; + RESOLUTION_INFO info = g_graphicsContext.GetResInfo(); + if (info.fRefreshRate > 0) + return info.fRefreshRate; if (m_Resolution == RES_PAL_4x3 || m_Resolution == RES_PAL_16x9) return 50.0f; if (m_Resolution == RES_HDTV_1080i) @@ -872,6 +993,13 @@ void CGraphicContext::SetMediaDir(const CStdString &strMediaDir) void CGraphicContext::Flip(const CDirtyRegionList& dirty) { g_Windowing.PresentRender(dirty); + + if(m_stereoMode != m_nextStereoMode) + { + m_stereoMode = m_nextStereoMode; + SetVideoResolution(GetVideoResolution(), true); + g_windowManager.SendMessage(GUI_MSG_NOTIFY_ALL, 0, 0, GUI_MSG_RENDERER_RESET); + } } void CGraphicContext::ApplyHardwareTransform() diff --git a/xbmc/guilib/GraphicContext.h b/xbmc/guilib/GraphicContext.h index 6ee8d98d7a..c15a7e02b4 100644 --- a/xbmc/guilib/GraphicContext.h +++ b/xbmc/guilib/GraphicContext.h @@ -48,6 +48,7 @@ #include "utils/GlobalsHandling.h" #include "DirtyRegion.h" #include "settings/ISettingCallback.h" +#include "rendering/RenderSystem.h" enum VIEW_TYPE { VIEW_TYPE_NONE = 0, VIEW_TYPE_LIST, @@ -112,14 +113,20 @@ public: void ResetScreenParameters(RESOLUTION res); void Lock() { lock(); } void Unlock() { unlock(); } - float GetPixelRatio(RESOLUTION iRes) const; void CaptureStateBlock(); void ApplyStateBlock(); void Clear(color_t color = 0); void GetAllowedResolutions(std::vector<RESOLUTION> &res); // output scaling - const RESOLUTION_INFO &GetResInfo() const; + const RESOLUTION_INFO GetResInfo() const + { + return GetResInfo(m_Resolution); + } + const RESOLUTION_INFO GetResInfo(RESOLUTION res) const; + void SetResInfo(RESOLUTION res, const RESOLUTION_INFO& info); + + void SetRenderingResolution(const RESOLUTION_INFO &res, bool needsScaling); ///< Sets scaling up for rendering void SetScalingResolution(const RESOLUTION_INFO &res, bool needsScaling); ///< Sets scaling up for skin loading etc. float GetScalingPixelRatio() const; @@ -143,6 +150,10 @@ public: void SetOrigin(float x, float y); void RestoreOrigin(); void SetCameraPosition(const CPoint &camera); + void SetStereoView(RENDER_STEREO_VIEW view); + RENDER_STEREO_VIEW GetStereoView() { return m_stereoView; } + void SetStereoMode(RENDER_STEREO_MODE mode) { m_nextStereoMode = mode; } + RENDER_STEREO_MODE GetStereoMode() { return m_stereoMode; } void RestoreCameraPosition(); /*! \brief Set a region in which to clip all rendering Anything that is rendered after setting a clip region will be clipped so that no part renders @@ -211,6 +222,10 @@ public: UpdateFinalTransform(TransformMatrix()); } + /* modifies final coordinates according to stereo mode if needed */ + CRect StereoCorrection(const CRect &rect) const; + CPoint StereoCorrection(const CPoint &point) const; + CRect generateAABB(const CRect &rect) const; protected: @@ -239,6 +254,9 @@ private: TransformMatrix m_guiTransform; TransformMatrix m_finalTransform; std::stack<TransformMatrix> m_groupTransform; + RENDER_STEREO_VIEW m_stereoView; + RENDER_STEREO_MODE m_stereoMode; + RENDER_STEREO_MODE m_nextStereoMode; CRect m_scissors; }; diff --git a/xbmc/guilib/Key.h b/xbmc/guilib/Key.h index 09ec3148b7..3bb2621134 100644 --- a/xbmc/guilib/Key.h +++ b/xbmc/guilib/Key.h @@ -319,6 +319,12 @@ #define ACTION_SWITCH_PLAYER 234 +#define ACTION_STEREOMODE_NEXT 235 +#define ACTION_STEREOMODE_PREVIOUS 236 +#define ACTION_STEREOMODE_TOGGLE 237 // turns 3d mode on/off +#define ACTION_STEREOMODE_SELECT 238 +#define ACTION_STEREOMODE_TOMONO 239 + #define ACTION_SETTINGS_RESET 240 #define ACTION_SETTINGS_LEVEL_CHANGE 241 diff --git a/xbmc/guilib/Makefile.in b/xbmc/guilib/Makefile.in index d06ab090ca..74260abf4b 100644 --- a/xbmc/guilib/Makefile.in +++ b/xbmc/guilib/Makefile.in @@ -68,6 +68,7 @@ SRCS += JpegIO.cpp SRCS += Key.cpp SRCS += LocalizeStrings.cpp SRCS += Shader.cpp +SRCS += StereoscopicsManager.cpp SRCS += Texture.cpp SRCS += TextureBundleXPR.cpp SRCS += TextureBundleXBT.cpp diff --git a/xbmc/guilib/Resolution.h b/xbmc/guilib/Resolution.h index 1e62d0a018..7dbda95775 100644 --- a/xbmc/guilib/Resolution.h +++ b/xbmc/guilib/Resolution.h @@ -88,6 +88,7 @@ struct RESOLUTION_INFO int iScreen; int iWidth; int iHeight; + int iBlanking; /**< number of pixels of padding between stereoscopic frames */ int iScreenWidth; int iScreenHeight; int iSubtitles; @@ -102,6 +103,7 @@ public: { iWidth = width; iHeight = height; + iBlanking = 0; iScreenWidth = width; iScreenHeight = height; fPixelRatio = aspect ? ((float)width)/height / aspect : 1.0f; @@ -122,5 +124,6 @@ public: iSubtitles = res.iSubtitles; dwFlags = res.dwFlags; fPixelRatio = res.fPixelRatio; fRefreshRate = res.fRefreshRate; strMode = res.strMode; strOutput = res.strOutput; strId = res.strId; + iBlanking = res.iBlanking; } }; diff --git a/xbmc/guilib/StereoscopicsManager.cpp b/xbmc/guilib/StereoscopicsManager.cpp new file mode 100644 index 0000000000..313a128c50 --- /dev/null +++ b/xbmc/guilib/StereoscopicsManager.cpp @@ -0,0 +1,406 @@ +/* + * Copyright (C) 2005-2013 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 + * <http://www.gnu.org/licenses/>. + * + */ + +/*! + * @file StereoscopicsManager.cpp + * @brief This class acts as container for stereoscopic related functions + */ + +#include <stdlib.h> +#include "StereoscopicsManager.h" + +#include "Application.h" +#include "ApplicationMessenger.h" +#include "dialogs/GUIDialogKaiToast.h" +#include "dialogs/GUIDialogSelect.h" +#include "FileItem.h" +#include "GUIInfoManager.h" +#include "GUIUserMessages.h" +#include "guilib/LocalizeStrings.h" +#include "guilib/Key.h" +#include "guilib/GUIWindowManager.h" +#include "settings/AdvancedSettings.h" +#include "settings/ISettingCallback.h" +#include "settings/Setting.h" +#include "settings/Settings.h" +#include "rendering/RenderSystem.h" +#include "utils/log.h" +#include "utils/StringUtils.h" +#include "windowing/WindowingFactory.h" + + +CStereoscopicsManager::CStereoscopicsManager(void) +{ + m_lastStereoMode = RENDER_STEREO_MODE_OFF; +} + +CStereoscopicsManager::~CStereoscopicsManager(void) +{ +} + +CStereoscopicsManager& CStereoscopicsManager::Get(void) +{ + static CStereoscopicsManager sStereoscopicsManager; + return sStereoscopicsManager; +} + +void CStereoscopicsManager::Initialize(void) +{ + m_lastStereoMode = GetStereoMode(); + // turn off stereo mode on XBMC startup + SetStereoMode(RENDER_STEREO_MODE_OFF); +} + +RENDER_STEREO_MODE CStereoscopicsManager::GetStereoMode(void) +{ + return (RENDER_STEREO_MODE) CSettings::Get().GetInt("videoscreen.stereoscopicmode"); +} + +void CStereoscopicsManager::SetStereoMode(const RENDER_STEREO_MODE &mode) +{ + RENDER_STEREO_MODE currentMode = GetStereoMode(); + if (mode != currentMode && mode >= RENDER_STEREO_MODE_OFF) + { + if(!g_Windowing.SupportsStereo(mode)) + return; + + m_lastStereoMode = currentMode; + CSettings::Get().SetInt("videoscreen.stereoscopicmode", mode); + } +} + +RENDER_STEREO_MODE CStereoscopicsManager::GetNextSupportedStereoMode(const RENDER_STEREO_MODE ¤tMode, int step) +{ + RENDER_STEREO_MODE mode = currentMode; + do { + mode = (RENDER_STEREO_MODE) ((mode + step) % RENDER_STEREO_MODE_COUNT); + if(g_Windowing.SupportsStereo(mode)) + break; + } while (mode != currentMode); + return mode; +} + +std::string CStereoscopicsManager::DetectStereoModeByString(const std::string &needle) +{ + std::string stereoMode; + CStdString searchString(needle); + CStdStringArray tags; + StringUtils::ToUpper(searchString); + + CStdString tag( g_advancedSettings.m_stereoscopicflags_sbs ); + if (stereoMode.empty() && !tag.IsEmpty()) + { + StringUtils::ToUpper(tag); + StringUtils::SplitString(tag, "|", tags); + if (StringUtils::ContainsKeyword(searchString, tags)) + stereoMode = "left_right"; + } + + tag = g_advancedSettings.m_stereoscopicflags_tab; + if (stereoMode.empty() && !tag.IsEmpty()) + { + StringUtils::ToUpper(tag); + StringUtils::SplitString(tag, "|", tags); + if (StringUtils::ContainsKeyword(searchString, tags)) + stereoMode = "top_bottom"; + } + + if (stereoMode.empty()) + stereoMode = "mono"; + + CLog::Log(LOGDEBUG, "StereoscopicsManager: Detected stereo mode in string '%s' is '%s'", needle.c_str(), stereoMode.c_str()); + return stereoMode; +} + +RENDER_STEREO_MODE CStereoscopicsManager::ConvertVideoToGuiStereoMode(const std::string &mode) +{ + static std::map<std::string, RENDER_STEREO_MODE> convert; + if(convert.empty()) + { + convert["mono"] = RENDER_STEREO_MODE_OFF; + convert["left_right"] = RENDER_STEREO_MODE_SPLIT_VERTICAL; + convert["bottom_top"] = RENDER_STEREO_MODE_SPLIT_HORIZONTAL; + convert["top_bottom"] = RENDER_STEREO_MODE_SPLIT_HORIZONTAL; + convert["checkerboard_rl"] = RENDER_STEREO_MODE_OFF; + convert["checkerboard_lr"] = RENDER_STEREO_MODE_OFF; + convert["row_interleaved_rl"] = RENDER_STEREO_MODE_INTERLACED; + convert["row_interleaved_lr"] = RENDER_STEREO_MODE_INTERLACED; + convert["col_interleaved_rl"] = RENDER_STEREO_MODE_OFF; + convert["col_interleaved_lr"] = RENDER_STEREO_MODE_OFF; + convert["anaglyph_cyan_red"] = RENDER_STEREO_MODE_ANAGLYPH_RED_CYAN; + convert["right_left"] = RENDER_STEREO_MODE_SPLIT_VERTICAL; + convert["anaglyph_green_magenta"] = RENDER_STEREO_MODE_ANAGLYPH_GREEN_MAGENTA; + convert["block_lr"] = RENDER_STEREO_MODE_OFF; + convert["block_rl"] = RENDER_STEREO_MODE_OFF; + } + + return (RENDER_STEREO_MODE) convert[mode]; +} + +RENDER_STEREO_MODE CStereoscopicsManager::GetStereoModeByUserChoice(const CStdString &heading) +{ + RENDER_STEREO_MODE mode = GetStereoMode(); + // if no stereo mode is set already, suggest mode of current video by preselecting it + if (mode == RENDER_STEREO_MODE_OFF && g_infoManager.EvaluateBool("videoplayer.isstereoscopic")) + mode = GetStereoModeOfPlayingVideo(); + + CGUIDialogSelect* pDlgSelect = (CGUIDialogSelect*)g_windowManager.GetWindow(WINDOW_DIALOG_SELECT); + pDlgSelect->Reset(); + if (heading.IsEmpty()) + pDlgSelect->SetHeading(g_localizeStrings.Get(36528).c_str()); + else + pDlgSelect->SetHeading(heading.c_str()); + + // prepare selectable stereo modes + std::vector<RENDER_STEREO_MODE> selectableModes; + for (int i = RENDER_STEREO_MODE_OFF; i < RENDER_STEREO_MODE_COUNT; i++) + { + RENDER_STEREO_MODE selectableMode = (RENDER_STEREO_MODE) i; + if (g_Windowing.SupportsStereo(selectableMode)) + { + selectableModes.push_back(selectableMode); + CStdString label = g_localizeStrings.Get(36502+i); + pDlgSelect->Add( label ); + if (mode == selectableMode) + pDlgSelect->SetSelected( label ); + } + } + + pDlgSelect->DoModal(); + + int iItem = pDlgSelect->GetSelectedLabel(); + if (iItem > -1 && pDlgSelect->IsConfirmed()) + mode = (RENDER_STEREO_MODE) selectableModes[iItem]; + else + mode = GetStereoMode(); + + return mode; +} + +RENDER_STEREO_MODE CStereoscopicsManager::GetStereoModeOfPlayingVideo(void) +{ + RENDER_STEREO_MODE mode = RENDER_STEREO_MODE_OFF; + + CStdString playerMode = g_infoManager.GetLabel(VIDEOPLAYER_STEREOSCOPIC_MODE); + if (!playerMode.IsEmpty()) + mode = (RENDER_STEREO_MODE) ConvertVideoToGuiStereoMode(playerMode); + + CLog::Log(LOGDEBUG, "StereoscopicsManager: autodetected GUI stereo mode for movie mode %s is: %s", playerMode.c_str(), GetLabelForStereoMode(mode).c_str()); + return mode; +} + +CStdString CStereoscopicsManager::GetLabelForStereoMode(const RENDER_STEREO_MODE &mode) +{ + return g_localizeStrings.Get(36502 + mode); +} + +RENDER_STEREO_MODE CStereoscopicsManager::GetPreferredPlaybackMode(void) +{ + RENDER_STEREO_MODE playbackMode = m_lastStereoMode; + int preferredMode = CSettings::Get().GetInt("videoscreen.preferedstereoscopicmode"); + if (preferredMode == RENDER_STEREO_MODE_AUTO) // automatic mode, detect by movie + { + if (g_infoManager.EvaluateBool("videoplayer.isstereoscopic")) + playbackMode = GetStereoModeOfPlayingVideo(); + else if (playbackMode == RENDER_STEREO_MODE_OFF) + playbackMode = GetNextSupportedStereoMode(RENDER_STEREO_MODE_OFF); + } + else // predefined mode + { + playbackMode = (RENDER_STEREO_MODE) preferredMode; + } + return playbackMode; +} + +bool CStereoscopicsManager::OnMessage(CGUIMessage &message) +{ + switch (message.GetMessage()) + { + case GUI_MSG_PLAYBACK_STARTED: + OnPlaybackStarted(); + break; + case GUI_MSG_PLAYBACK_STOPPED: + case GUI_MSG_PLAYLISTPLAYER_STOPPED: + OnPlaybackStopped(); + break; + } + + return false; +} + +void CStereoscopicsManager::OnSettingChanged(const CSetting *setting) +{ + if (setting == NULL) + return; + + const std::string &settingId = setting->GetId(); + + if (settingId == "videoscreen.stereoscopicmode") + { + RENDER_STEREO_MODE mode = GetStereoMode(); + CLog::Log(LOGDEBUG, "StereoscopicsManager: stereo mode setting changed to %s", GetLabelForStereoMode(mode).c_str()); + ApplyStereoMode(mode); + } +} + +bool CStereoscopicsManager::OnAction(const CAction &action) +{ + RENDER_STEREO_MODE mode = GetStereoMode(); + + if (action.GetID() == ACTION_STEREOMODE_NEXT) + { + SetStereoMode(GetNextSupportedStereoMode(mode)); + return true; + } + else if (action.GetID() == ACTION_STEREOMODE_PREVIOUS) + { + SetStereoMode(GetNextSupportedStereoMode(mode, RENDER_STEREO_MODE_COUNT - 1)); + return true; + } + else if (action.GetID() == ACTION_STEREOMODE_TOGGLE) + { + if (mode == RENDER_STEREO_MODE_OFF) + { + RENDER_STEREO_MODE targetMode = m_lastStereoMode; + if (targetMode == RENDER_STEREO_MODE_OFF) + targetMode = GetPreferredPlaybackMode(); + SetStereoMode(targetMode); + } + else + { + SetStereoMode(RENDER_STEREO_MODE_OFF); + } + return true; + } + else if (action.GetID() == ACTION_STEREOMODE_SELECT) + { + SetStereoMode(GetStereoModeByUserChoice()); + return true; + } + else if (action.GetID() == ACTION_STEREOMODE_TOMONO) + { + if (mode == RENDER_STEREO_MODE_MONO) + { + RENDER_STEREO_MODE targetMode = m_lastStereoMode; + if (targetMode == RENDER_STEREO_MODE_OFF) + targetMode = GetPreferredPlaybackMode(); + SetStereoMode(targetMode); + } + else + { + SetStereoMode(RENDER_STEREO_MODE_MONO); + } + } + + return false; +} + +void CStereoscopicsManager::ApplyStereoMode(const RENDER_STEREO_MODE &mode, bool notify) +{ + RENDER_STEREO_MODE currentMode = g_graphicsContext.GetStereoMode(); + CLog::Log(LOGDEBUG, "StereoscopicsManager::ApplyStereoMode: trying to apply stereo mode. Current: %s | Target: %s", GetLabelForStereoMode(currentMode).c_str(), GetLabelForStereoMode(mode).c_str()); + if (currentMode != mode) + { + g_graphicsContext.SetStereoMode(mode); + CLog::Log(LOGDEBUG, "StereoscopicsManager: stereo mode changed to %s", GetLabelForStereoMode(mode).c_str()); + if (notify) + CGUIDialogKaiToast::QueueNotification(CGUIDialogKaiToast::Info, g_localizeStrings.Get(36501), GetLabelForStereoMode(mode)); + } +} + +void CStereoscopicsManager::OnPlaybackStarted(void) +{ + if (!g_infoManager.EvaluateBool("videoplayer.isstereoscopic")) + return; + + // only change stereo mode if not yet in stereo mode + RENDER_STEREO_MODE mode = GetStereoMode(); + if (mode != RENDER_STEREO_MODE_OFF) + return; + + int playbackMode = CSettings::Get().GetInt("videoplayer.stereoscopicplaybackmode"); + switch (playbackMode) + { + case 0: // Ask + { + CApplicationMessenger::Get().MediaPause(); + + CGUIDialogSelect* pDlgSelect = (CGUIDialogSelect*)g_windowManager.GetWindow(WINDOW_DIALOG_SELECT); + pDlgSelect->Reset(); + pDlgSelect->SetHeading(g_localizeStrings.Get(36527).c_str()); + + RENDER_STEREO_MODE preferred = GetPreferredPlaybackMode(); + RENDER_STEREO_MODE playing = GetStereoModeOfPlayingVideo(); + + int idx_preferred = -1 + , idx_playing = -1 + , idx_mono = -1 + , idx_select = -1; + + // add choices + idx_preferred = pDlgSelect->Add( g_localizeStrings.Get(36530) + + " (" + + GetLabelForStereoMode(preferred) + + ")"); + + if(preferred != RENDER_STEREO_MODE_MONO) + idx_mono = pDlgSelect->Add( g_localizeStrings.Get(36529) ); // mono / 2d + + + if(playing != RENDER_STEREO_MODE_OFF && g_Windowing.SupportsStereo(playing)) + idx_playing = pDlgSelect->Add( g_localizeStrings.Get(36532) + + " (" + + GetLabelForStereoMode(playing) + + ")"); + + idx_select = pDlgSelect->Add( g_localizeStrings.Get(36531) ); // other / select + + pDlgSelect->DoModal(); + + if(pDlgSelect->IsConfirmed()) + { + int iItem = pDlgSelect->GetSelectedLabel(); + if (iItem == idx_preferred) mode = preferred; + else if (iItem == idx_mono) mode = RENDER_STEREO_MODE_MONO; + else if (iItem == idx_playing) mode = playing; + else if (iItem == idx_select) mode = GetStereoModeByUserChoice(); + + SetStereoMode(mode); + } + + CApplicationMessenger::Get().MediaUnPause(); + } + break; + case 1: // Stereoscopic + SetStereoMode( GetPreferredPlaybackMode() ); + break; + default: + break; + } +} + +void CStereoscopicsManager::OnPlaybackStopped(void) +{ + RENDER_STEREO_MODE mode = GetStereoMode(); + if (CSettings::Get().GetBool("videoplayer.quitstereomodeonstop") == true && mode != RENDER_STEREO_MODE_OFF) + { + SetStereoMode(RENDER_STEREO_MODE_OFF); + } +} diff --git a/xbmc/guilib/StereoscopicsManager.h b/xbmc/guilib/StereoscopicsManager.h new file mode 100644 index 0000000000..292430bafe --- /dev/null +++ b/xbmc/guilib/StereoscopicsManager.h @@ -0,0 +1,73 @@ +/* + * Copyright (C) 2005-2013 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 + * <http://www.gnu.org/licenses/>. + * + */ + +/*! + * @file StereoscopicsManager.cpp + * @brief This class acts as container for stereoscopic related functions + */ + +#pragma once + +#include <stdlib.h> +#include "settings/ISettingCallback.h" +#include "guilib/IMsgTargetCallback.h" +#include "rendering/RenderSystem.h" + +class CAction; + +class CStereoscopicsManager : public ISettingCallback, + public IMsgTargetCallback +{ +public: + CStereoscopicsManager(void); + virtual ~CStereoscopicsManager(void); + + /*! + * @return static instance of CStereoscopicsManager + */ + static CStereoscopicsManager& Get(void); + + void Initialize(void); + void SetStereoMode(const RENDER_STEREO_MODE &mode); + RENDER_STEREO_MODE GetStereoMode(void); + RENDER_STEREO_MODE GetNextSupportedStereoMode(const RENDER_STEREO_MODE ¤tMode, int step = 1); + std::string DetectStereoModeByString(const std::string &needle); + RENDER_STEREO_MODE ConvertVideoToGuiStereoMode(const std::string &mode); + RENDER_STEREO_MODE GetStereoModeByUserChoice(const CStdString& heading = ""); + RENDER_STEREO_MODE GetStereoModeOfPlayingVideo(void); + CStdString GetLabelForStereoMode(const RENDER_STEREO_MODE &mode); + RENDER_STEREO_MODE GetPreferredPlaybackMode(void); + + virtual void OnSettingChanged(const CSetting *setting); + virtual bool OnMessage(CGUIMessage &message); + /*! + * @brief Handle 3D specific cActions + * @param action The action to process + * @return True if action could be handled, false otherwise. + */ + bool OnAction(const CAction &action); + +private: + void ApplyStereoMode(const RENDER_STEREO_MODE &mode, bool notify = true); + void OnPlaybackStarted(void); + void OnPlaybackStopped(void); + + RENDER_STEREO_MODE m_lastStereoMode; +}; diff --git a/xbmc/guilib/gui3d.h b/xbmc/guilib/gui3d.h index c455a7d26c..b461268f66 100644 --- a/xbmc/guilib/gui3d.h +++ b/xbmc/guilib/gui3d.h @@ -37,6 +37,11 @@ #define D3DPRESENTFLAG_MODE3DSBS 8 #define D3DPRESENTFLAG_MODE3DTB 16 +/* what types are important for mode setting */ +#define D3DPRESENTFLAG_MODEMASK ( D3DPRESENTFLAG_INTERLACED \ + | D3DPRESENTFLAG_MODE3DSBS \ + | D3DPRESENTFLAG_MODE3DTB ) + #define D3DFMT_LIN_A8R8G8B8 D3DFMT_A8R8G8B8 #define D3DFMT_LIN_X8R8G8B8 D3DFMT_X8R8G8B8 #define D3DFMT_LIN_L8 D3DFMT_L8 diff --git a/xbmc/input/ButtonTranslator.cpp b/xbmc/input/ButtonTranslator.cpp index c6af0d69ca..811caf00f5 100644 --- a/xbmc/input/ButtonTranslator.cpp +++ b/xbmc/input/ButtonTranslator.cpp @@ -223,6 +223,13 @@ static const ActionMapping actions[] = {"settingsreset" , ACTION_SETTINGS_RESET}, {"settingslevelchange", ACTION_SETTINGS_LEVEL_CHANGE}, + // 3D movie playback/GUI + {"stereomode" , ACTION_STEREOMODE_SELECT}, // cycle 3D modes, for now an alias for next + {"nextstereomode" , ACTION_STEREOMODE_NEXT}, + {"previousstereomode" , ACTION_STEREOMODE_PREVIOUS}, + {"togglestereomode" , ACTION_STEREOMODE_TOGGLE}, + {"stereomodetomono" , ACTION_STEREOMODE_TOMONO}, + // PVR actions {"channelup" , ACTION_CHANNEL_UP}, {"channeldown" , ACTION_CHANNEL_DOWN}, diff --git a/xbmc/interfaces/legacy/Window.cpp b/xbmc/interfaces/legacy/Window.cpp index 034b9b1433..f29fca6d68 100644 --- a/xbmc/interfaces/legacy/Window.cpp +++ b/xbmc/interfaces/legacy/Window.cpp @@ -25,7 +25,6 @@ #include "guilib/GUICheckMarkControl.h" #include "guilib/GUIRadioButtonControl.h" #include "guilib/GUIWindowManager.h" -#include "settings/DisplaySettings.h" #include "Application.h" #include "ApplicationMessenger.h" #include "utils/Variant.h" @@ -634,7 +633,7 @@ namespace XBMCAddon throw WindowException("Invalid resolution."); SingleLockWithDelayGuard gslock(g_graphicsContext,languageHook); - ref(window)->SetCoordsRes(CDisplaySettings::Get().GetResolutionInfo(res)); + ref(window)->SetCoordsRes(g_graphicsContext.GetResInfo((RESOLUTION)res)); } void Window::setProperty(const char* key, const String& value) diff --git a/xbmc/music/karaoke/karaokelyricscdg.cpp b/xbmc/music/karaoke/karaokelyricscdg.cpp index 3871d4f9af..f85414e44d 100644 --- a/xbmc/music/karaoke/karaokelyricscdg.cpp +++ b/xbmc/music/karaoke/karaokelyricscdg.cpp @@ -186,11 +186,11 @@ void CKaraokeLyricsCDG::Render() (float)(CDG_FULL_HEIGHT - CDG_BORDER_HEIGHT) / CDG_FULL_HEIGHT); // Get screen coordinates - RESOLUTION res = g_graphicsContext.GetVideoResolution(); - CRect vertCoords((float)CDisplaySettings::Get().GetResolutionInfo(res).Overscan.left, - (float)CDisplaySettings::Get().GetResolutionInfo(res).Overscan.top, - (float)CDisplaySettings::Get().GetResolutionInfo(res).Overscan.right, - (float)CDisplaySettings::Get().GetResolutionInfo(res).Overscan.bottom); + const RESOLUTION_INFO info = g_graphicsContext.GetResInfo(); + CRect vertCoords((float)info.Overscan.left, + (float)info.Overscan.top, + (float)info.Overscan.right, + (float)info.Overscan.bottom); CGUITexture::DrawQuad(vertCoords, 0xffffffff, m_pCdgTexture, &texCoords); } diff --git a/xbmc/music/karaoke/karaokelyricstext.cpp b/xbmc/music/karaoke/karaokelyricstext.cpp index 2e3a31641a..f04f4c531d 100644 --- a/xbmc/music/karaoke/karaokelyricstext.cpp +++ b/xbmc/music/karaoke/karaokelyricstext.cpp @@ -313,9 +313,9 @@ void CKaraokeLyricsText::Render() } // Calculate drawing parameters - RESOLUTION resolution = g_graphicsContext.GetVideoResolution(); - g_graphicsContext.SetRenderingResolution(g_graphicsContext.GetResInfo(), false); - float maxWidth = (float) CDisplaySettings::Get().GetResolutionInfo(resolution).Overscan.right - CDisplaySettings::Get().GetResolutionInfo(resolution).Overscan.left; + const RESOLUTION_INFO info = g_graphicsContext.GetResInfo(); + g_graphicsContext.SetRenderingResolution(info, false); + float maxWidth = (float) info.Overscan.right - info.Overscan.left; // We must only fall through for STATE_DRAW_SYLLABLE or STATE_PREAMBLE if ( updateText ) @@ -375,9 +375,9 @@ void CKaraokeLyricsText::Render() m_preambleLayout->Update( m_currentPreamble, maxWidth * 0.9f ); } - float x = maxWidth * 0.5f + CDisplaySettings::Get().GetResolutionInfo(resolution).Overscan.left; - float y = (float)CDisplaySettings::Get().GetResolutionInfo(resolution).Overscan.top + - (CDisplaySettings::Get().GetResolutionInfo(resolution).Overscan.bottom - CDisplaySettings::Get().GetResolutionInfo(resolution).Overscan.top) / 8; + float x = maxWidth * 0.5f + info.Overscan.left; + float y = (float)info.Overscan.top + + (info.Overscan.bottom - info.Overscan.top) / 8; float textWidth, textHeight; m_karaokeLayout->GetTextExtent(textWidth, textHeight); @@ -460,8 +460,8 @@ void CKaraokeLyricsText::rescanLyrics() // Second, add spaces if less than 5%, and rescan to gather more data. bool add_spaces = (syllables && (spaces * 100 / syllables < 5)) ? true : false; - RESOLUTION res = g_graphicsContext.GetVideoResolution(); - float maxWidth = (float) CDisplaySettings::Get().GetResolutionInfo(res).Overscan.right - CDisplaySettings::Get().GetResolutionInfo(res).Overscan.left; + const RESOLUTION_INFO info = g_graphicsContext.GetResInfo(); + float maxWidth = (float) info.Overscan.right - info.Overscan.left; CStdString line_text; int prev_line_idx = -1; diff --git a/xbmc/music/karaoke/karaokevideobackground.cpp b/xbmc/music/karaoke/karaokevideobackground.cpp index f71d0152ba..e36ebe7750 100644 --- a/xbmc/music/karaoke/karaokevideobackground.cpp +++ b/xbmc/music/karaoke/karaokevideobackground.cpp @@ -62,11 +62,11 @@ bool KaraokeVideoBackground::openVideoFile( const CStdString& filename ) m_curVideoFile = filename; // Find out the necessary aspect ratio for height (assuming fit by width) and width (assuming fit by height) - RESOLUTION res = g_graphicsContext.GetVideoResolution(); - m_displayLeft = CDisplaySettings::Get().GetResolutionInfo(res).Overscan.left; - m_displayRight = CDisplaySettings::Get().GetResolutionInfo(res).Overscan.right; - m_displayTop = CDisplaySettings::Get().GetResolutionInfo(res).Overscan.top; - m_displayBottom = CDisplaySettings::Get().GetResolutionInfo(res).Overscan.bottom; + const RESOLUTION_INFO info = g_graphicsContext.GetResInfo(); + m_displayLeft = info.Overscan.left; + m_displayRight = info.Overscan.right; + m_displayTop = info.Overscan.top; + m_displayBottom = info.Overscan.bottom; int screen_width = m_displayRight - m_displayLeft; int screen_height = m_displayBottom - m_displayTop; diff --git a/xbmc/pictures/GUIWindowSlideShow.cpp b/xbmc/pictures/GUIWindowSlideShow.cpp index b5a8e636e1..753c264d88 100644 --- a/xbmc/pictures/GUIWindowSlideShow.cpp +++ b/xbmc/pictures/GUIWindowSlideShow.cpp @@ -399,6 +399,8 @@ void CGUIWindowSlideShow::SetDirection(int direction) void CGUIWindowSlideShow::Process(unsigned int currentTime, CDirtyRegionList ®ions) { + const RESOLUTION_INFO res = g_graphicsContext.GetResInfo(); + // reset the screensaver if we're in a slideshow // (unless we are the screensaver!) if (m_bSlideShow && !m_bPause && !g_application.IsInScreenSaver()) @@ -512,8 +514,9 @@ void CGUIWindowSlideShow::Process(unsigned int currentTime, CDirtyRegionList &re // load using the background loader int maxWidth, maxHeight; - GetCheckedSize((float)CDisplaySettings::Get().GetResolutionInfo(m_Resolution).iWidth * m_fZoom, - (float)CDisplaySettings::Get().GetResolutionInfo(m_Resolution).iHeight * m_fZoom, + + GetCheckedSize((float)res.iWidth * m_fZoom, + (float)res.iHeight * m_fZoom, maxWidth, maxHeight); m_pBackgroundLoader->LoadPic(m_iCurrentPic, m_iCurrentSlide, picturePath, maxWidth, maxHeight); m_iLastFailedNextSlide = -1; @@ -538,8 +541,8 @@ void CGUIWindowSlideShow::Process(unsigned int currentTime, CDirtyRegionList &re CLog::Log(LOGDEBUG, "Loading the next image %d: %s", m_iNextSlide, item->GetPath().c_str()); int maxWidth, maxHeight; - GetCheckedSize((float)CDisplaySettings::Get().GetResolutionInfo(m_Resolution).iWidth * m_fZoom, - (float)CDisplaySettings::Get().GetResolutionInfo(m_Resolution).iHeight * m_fZoom, + GetCheckedSize((float)res.iWidth * m_fZoom, + (float)res.iHeight * m_fZoom, maxWidth, maxHeight); m_pBackgroundLoader->LoadPic(1 - m_iCurrentPic, m_iNextSlide, picturePath, maxWidth, maxHeight); } diff --git a/xbmc/pictures/SlideShowPicture.cpp b/xbmc/pictures/SlideShowPicture.cpp index 8ec6d7c667..3a2a529416 100644 --- a/xbmc/pictures/SlideShowPicture.cpp +++ b/xbmc/pictures/SlideShowPicture.cpp @@ -23,7 +23,6 @@ #include "guilib/GraphicContext.h" #include "guilib/Texture.h" #include "settings/AdvancedSettings.h" -#include "settings/DisplaySettings.h" #include "settings/Settings.h" #include "windowing/WindowingFactory.h" #include "utils/log.h" @@ -160,9 +159,9 @@ void CSlideShowPic::SetTexture_Internal(int iSlideNumber, CBaseTexture* pTexture int iFrames = max((int)(g_graphicsContext.GetFPS() * CSettings::Get().GetInt("slideshow.staytime")), 1); if (m_displayEffect == EFFECT_PANORAMA) { - RESOLUTION iRes = g_graphicsContext.GetVideoResolution(); - float fScreenWidth = (float)CDisplaySettings::Get().GetResolutionInfo(iRes).Overscan.right - CDisplaySettings::Get().GetResolutionInfo(iRes).Overscan.left; - float fScreenHeight = (float)CDisplaySettings::Get().GetResolutionInfo(iRes).Overscan.bottom - CDisplaySettings::Get().GetResolutionInfo(iRes).Overscan.top; + RESOLUTION_INFO res = g_graphicsContext.GetResInfo(); + float fScreenWidth = (float)res.Overscan.right - res.Overscan.left; + float fScreenHeight = (float)res.Overscan.bottom - res.Overscan.top; if (m_fWidth > m_fHeight) { @@ -417,15 +416,15 @@ void CSlideShowPic::Process(unsigned int currentTime, CDirtyRegionList &dirtyreg if (m_iCounter > m_transistionEnd.start + m_transistionEnd.length) m_bIsFinished = true; + RESOLUTION_INFO info = g_graphicsContext.GetResInfo(); + // calculate where we should render (and how large it should be) // calculate aspect ratio correction factor - RESOLUTION iRes = g_graphicsContext.GetVideoResolution(); - float fOffsetX = (float)CDisplaySettings::Get().GetResolutionInfo(iRes).Overscan.left; - float fOffsetY = (float)CDisplaySettings::Get().GetResolutionInfo(iRes).Overscan.top; - float fScreenWidth = (float)CDisplaySettings::Get().GetResolutionInfo(iRes).Overscan.right - CDisplaySettings::Get().GetResolutionInfo(iRes).Overscan.left; - float fScreenHeight = (float)CDisplaySettings::Get().GetResolutionInfo(iRes).Overscan.bottom - CDisplaySettings::Get().GetResolutionInfo(iRes).Overscan.top; - - float fPixelRatio = CDisplaySettings::Get().GetResolutionInfo(iRes).fPixelRatio; + float fOffsetX = (float)info.Overscan.left; + float fOffsetY = (float)info.Overscan.top; + float fScreenWidth = (float)info.Overscan.right - info.Overscan.left; + float fScreenHeight = (float)info.Overscan.bottom - info.Overscan.top; + float fPixelRatio = info.fPixelRatio; // Rotate the image as needed float x[4]; @@ -747,17 +746,17 @@ void CSlideShowPic::Render(float *x, float *y, CBaseTexture* pTexture, color_t c #ifdef HAS_DX struct VERTEX { - D3DXVECTOR4 p; + D3DXVECTOR3 p; D3DCOLOR col; FLOAT tu, tv; }; - static const DWORD FVF_VERTEX = D3DFVF_XYZRHW | D3DFVF_DIFFUSE | D3DFVF_TEX1; + static const DWORD FVF_VERTEX = D3DFVF_XYZ | D3DFVF_DIFFUSE | D3DFVF_TEX1; VERTEX vertex[5]; for (int i = 0; i < 4; i++) { - vertex[i].p = D3DXVECTOR4( x[i], y[i], 0, 1.0f); + vertex[i].p = D3DXVECTOR3( x[i], y[i], 0); vertex[i].tu = 0; vertex[i].tv = 0; vertex[i].col = color; diff --git a/xbmc/rendering/RenderSystem.cpp b/xbmc/rendering/RenderSystem.cpp index 663754f6a0..e5a98f69f2 100644 --- a/xbmc/rendering/RenderSystem.cpp +++ b/xbmc/rendering/RenderSystem.cpp @@ -65,3 +65,17 @@ bool CRenderSystemBase::SupportsBGRAApple() const return (m_renderCaps & RENDER_CAPS_BGRA_APPLE) == RENDER_CAPS_BGRA_APPLE; } +bool CRenderSystemBase::SupportsStereo(RENDER_STEREO_MODE mode) const +{ + switch(mode) + { + case RENDER_STEREO_MODE_OFF: + case RENDER_STEREO_MODE_SPLIT_HORIZONTAL: + case RENDER_STEREO_MODE_SPLIT_VERTICAL: + case RENDER_STEREO_MODE_MONO: + return true; + default: + return false; + } +} + diff --git a/xbmc/rendering/RenderSystem.h b/xbmc/rendering/RenderSystem.h index e394b56383..2bceb67190 100644 --- a/xbmc/rendering/RenderSystem.h +++ b/xbmc/rendering/RenderSystem.h @@ -60,6 +60,30 @@ enum RENDER_QUIRKS_BROKEN_OCCLUSION_QUERY = 1 << 2, }; +enum RENDER_STEREO_VIEW +{ + RENDER_STEREO_VIEW_OFF, + RENDER_STEREO_VIEW_LEFT, + RENDER_STEREO_VIEW_RIGHT, +}; + +enum RENDER_STEREO_MODE +{ + RENDER_STEREO_MODE_OFF, + RENDER_STEREO_MODE_SPLIT_HORIZONTAL, + RENDER_STEREO_MODE_SPLIT_VERTICAL, + RENDER_STEREO_MODE_ANAGLYPH_RED_CYAN, + RENDER_STEREO_MODE_ANAGLYPH_GREEN_MAGENTA, + RENDER_STEREO_MODE_INTERLACED, + RENDER_STEREO_MODE_HARDWAREBASED, + RENDER_STEREO_MODE_MONO, + RENDER_STEREO_MODE_COUNT, + + // psuevdo modes + RENDER_STEREO_MODE_AUTO = 100, +}; + + class CRenderSystemBase { public: @@ -94,6 +118,11 @@ public: virtual void SetCameraPosition(const CPoint &camera, int screenWidth, int screenHeight) = 0; virtual void ApplyHardwareTransform(const TransformMatrix &matrix) = 0; virtual void RestoreHardwareTransform() = 0; + virtual void SetStereoMode(RENDER_STEREO_MODE mode, RENDER_STEREO_VIEW view) + { + m_stereoMode = mode; + m_stereoView = view; + } virtual bool TestRender() = 0; @@ -110,6 +139,7 @@ public: bool SupportsBGRA() const; bool SupportsBGRAApple() const; bool SupportsNPOT(bool dxt) const; + bool SupportsStereo(RENDER_STEREO_MODE mode) const; unsigned int GetMaxTextureSize() const { return m_maxTextureSize; } unsigned int GetMinDXTPitch() const { return m_minDXTPitch; } unsigned int GetRenderQuirks() const { return m_renderQuirks; } @@ -128,6 +158,8 @@ protected: int m_RenderVersionMajor; unsigned int m_renderCaps; unsigned int m_renderQuirks; + RENDER_STEREO_VIEW m_stereoView; + RENDER_STEREO_MODE m_stereoMode; }; #endif // RENDER_SYSTEM_H diff --git a/xbmc/rendering/dx/RenderSystemDX.cpp b/xbmc/rendering/dx/RenderSystemDX.cpp index a14d56d897..facf8ec3e1 100644 --- a/xbmc/rendering/dx/RenderSystemDX.cpp +++ b/xbmc/rendering/dx/RenderSystemDX.cpp @@ -734,19 +734,24 @@ bool CRenderSystemDX::EndRender() bool CRenderSystemDX::ClearBuffers(color_t color) { - HRESULT hr; - if (!m_bRenderCreated) return false; - if( FAILED( hr = m_pD3DDevice->Clear( + if(m_stereoMode == RENDER_STEREO_MODE_ANAGLYPH_RED_CYAN + || m_stereoMode == RENDER_STEREO_MODE_ANAGLYPH_GREEN_MAGENTA) + { + // if stereo anaglyph, data was cleared when left view was rendererd + if(m_stereoView == RENDER_STEREO_VIEW_RIGHT) + return true; + } + + return SUCCEEDED(m_pD3DDevice->Clear( 0, NULL, D3DCLEAR_TARGET, color, 1.0, - 0 ) ) ) - return false; + 0 ) ); return true; } @@ -821,7 +826,7 @@ void CRenderSystemDX::SetCameraPosition(const CPoint &camera, int screenWidth, i // position. D3DXMATRIX flipY, translate, mtxView; D3DXMatrixScaling(&flipY, 1.0f, -1.0f, 1.0f); - D3DXMatrixTranslation(&translate, -(viewport.X + w + offset.x), -(viewport.Y + h + offset.y), 2*h); + D3DXMatrixTranslation(&translate, -(w + offset.x), -(h + offset.y), 2*h); D3DXMatrixMultiply(&mtxView, &translate, &flipY); m_pD3DDevice->SetTransform(D3DTS_VIEW, &mtxView); @@ -1005,4 +1010,38 @@ CStdString CRenderSystemDX::GetErrorDescription(HRESULT hr) return strError; } +void CRenderSystemDX::SetStereoMode(RENDER_STEREO_MODE mode, RENDER_STEREO_VIEW view) +{ + CRenderSystemBase::SetStereoMode(mode, view); + + m_pD3DDevice->SetRenderState( D3DRS_COLORWRITEENABLE, D3DCOLORWRITEENABLE_ALPHA | D3DCOLORWRITEENABLE_RED | D3DCOLORWRITEENABLE_BLUE | D3DCOLORWRITEENABLE_GREEN); + if(m_stereoMode == RENDER_STEREO_MODE_ANAGLYPH_RED_CYAN) + { + if(m_stereoView == RENDER_STEREO_VIEW_LEFT) + m_pD3DDevice->SetRenderState( D3DRS_COLORWRITEENABLE, D3DCOLORWRITEENABLE_RED ); + else if(m_stereoView == RENDER_STEREO_VIEW_RIGHT) + m_pD3DDevice->SetRenderState( D3DRS_COLORWRITEENABLE, D3DCOLORWRITEENABLE_BLUE | D3DCOLORWRITEENABLE_GREEN ); + } + if(m_stereoMode == RENDER_STEREO_MODE_ANAGLYPH_GREEN_MAGENTA) + { + if(m_stereoView == RENDER_STEREO_VIEW_LEFT) + m_pD3DDevice->SetRenderState( D3DRS_COLORWRITEENABLE, D3DCOLORWRITEENABLE_GREEN ); + else if(m_stereoView == RENDER_STEREO_VIEW_RIGHT) + m_pD3DDevice->SetRenderState( D3DRS_COLORWRITEENABLE, D3DCOLORWRITEENABLE_BLUE | D3DCOLORWRITEENABLE_RED ); + } +} + +bool CRenderSystemDX::SupportsStereo(RENDER_STEREO_MODE mode) const +{ + switch(mode) + { + case RENDER_STEREO_MODE_ANAGLYPH_RED_CYAN: + case RENDER_STEREO_MODE_ANAGLYPH_GREEN_MAGENTA: + return true; + default: + return CRenderSystemBase::SupportsStereo(mode); + } +} + + #endif diff --git a/xbmc/rendering/dx/RenderSystemDX.h b/xbmc/rendering/dx/RenderSystemDX.h index 011334a63d..dcdd843034 100644 --- a/xbmc/rendering/dx/RenderSystemDX.h +++ b/xbmc/rendering/dx/RenderSystemDX.h @@ -72,7 +72,8 @@ public: virtual void ApplyHardwareTransform(const TransformMatrix &matrix); virtual void RestoreHardwareTransform(); - + virtual void SetStereoMode(RENDER_STEREO_MODE mode, RENDER_STEREO_VIEW view); + virtual bool SupportsStereo(RENDER_STEREO_MODE mode) const; virtual bool TestRender(); virtual void Project(float &x, float &y, float &z); diff --git a/xbmc/rendering/gl/RenderSystemGL.cpp b/xbmc/rendering/gl/RenderSystemGL.cpp index 3e5ac9d1b5..6e225bf937 100644 --- a/xbmc/rendering/gl/RenderSystemGL.cpp +++ b/xbmc/rendering/gl/RenderSystemGL.cpp @@ -264,6 +264,10 @@ bool CRenderSystemGL::ClearBuffers(color_t color) if (!m_bRenderCreated) return false; + /* clear is not affected by stipple pattern, so we can only clear on first frame */ + if(m_stereoMode == RENDER_STEREO_MODE_INTERLACED && m_stereoView == RENDER_STEREO_VIEW_RIGHT) + return true; + float r = GET_R(color) / 255.0f; float g = GET_G(color) / 255.0f; float b = GET_B(color) / 255.0f; @@ -441,7 +445,7 @@ void CRenderSystemGL::SetCameraPosition(const CPoint &camera, int screenWidth, i glMatrixMode(GL_MODELVIEW); glLoadIdentity(); - glTranslatef(-(viewport[0] + w + offset.x), +(viewport[1] + h + offset.y), 0); + glTranslatef(-(w + offset.x), +(h + offset.y), 0); gluLookAt(0.0, 0.0, -2.0*h, 0.0, 0.0, 0.0, 0.0, -1.0, 0.0); glMatrixMode(GL_PROJECTION); glLoadIdentity(); @@ -461,7 +465,7 @@ void CRenderSystemGL::Project(float &x, float &y, float &z) if (gluProject(x, y, z, m_view, m_projection, m_viewPort, &coordX, &coordY, &coordZ) == GLU_TRUE) { x = (float)coordX; - y = (float)(m_viewPort[3] - coordY); + y = (float)(m_viewPort[1] + m_viewPort[3] - coordY); z = 0; } } @@ -470,9 +474,6 @@ bool CRenderSystemGL::TestRender() { static float theta = 0.0; - //RESOLUTION_INFO resInfo = CDisplaySettings::Get().GetResolutionInfo(CDisplaySettings::Get().GetCurrentResolution()]; - //glViewport(0, 0, resInfo.iWidth, resInfo.iHeight); - glPushMatrix(); glRotatef( theta, 0.0f, 0.0f, 1.0f ); glBegin( GL_TRIANGLES ); @@ -621,5 +622,105 @@ void CRenderSystemGL::ResetGLErrors() } } } +static const GLubyte stipple_3d[] = { + 0x00, 0x00, 0x00, 0x00, + 0xFF, 0xFF, 0xFF, 0xFF, + 0x00, 0x00, 0x00, 0x00, + 0xFF, 0xFF, 0xFF, 0xFF, + 0x00, 0x00, 0x00, 0x00, + 0xFF, 0xFF, 0xFF, 0xFF, + 0x00, 0x00, 0x00, 0x00, + 0xFF, 0xFF, 0xFF, 0xFF, + 0x00, 0x00, 0x00, 0x00, + 0xFF, 0xFF, 0xFF, 0xFF, + 0x00, 0x00, 0x00, 0x00, + 0xFF, 0xFF, 0xFF, 0xFF, + 0x00, 0x00, 0x00, 0x00, + 0xFF, 0xFF, 0xFF, 0xFF, + 0x00, 0x00, 0x00, 0x00, + 0xFF, 0xFF, 0xFF, 0xFF, + 0x00, 0x00, 0x00, 0x00, + 0xFF, 0xFF, 0xFF, 0xFF, + 0x00, 0x00, 0x00, 0x00, + 0xFF, 0xFF, 0xFF, 0xFF, + 0x00, 0x00, 0x00, 0x00, + 0xFF, 0xFF, 0xFF, 0xFF, + 0x00, 0x00, 0x00, 0x00, + 0xFF, 0xFF, 0xFF, 0xFF, + 0x00, 0x00, 0x00, 0x00, + 0xFF, 0xFF, 0xFF, 0xFF, + 0x00, 0x00, 0x00, 0x00, + 0xFF, 0xFF, 0xFF, 0xFF, + 0x00, 0x00, 0x00, 0x00, + 0xFF, 0xFF, 0xFF, 0xFF, + 0x00, 0x00, 0x00, 0x00, + 0xFF, 0xFF, 0xFF, 0xFF, + 0x00, 0x00, 0x00, 0x00, +}; + +void CRenderSystemGL::SetStereoMode(RENDER_STEREO_MODE mode, RENDER_STEREO_VIEW view) +{ + CRenderSystemBase::SetStereoMode(mode, view); + + glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); + glDisable(GL_POLYGON_STIPPLE); + glDrawBuffer(GL_BACK); + + if(m_stereoMode == RENDER_STEREO_MODE_ANAGLYPH_RED_CYAN) + { + if(m_stereoView == RENDER_STEREO_VIEW_LEFT) + glColorMask(GL_TRUE, GL_FALSE, GL_FALSE, GL_TRUE); + else if(m_stereoView == RENDER_STEREO_VIEW_RIGHT) + glColorMask(GL_FALSE, GL_TRUE, GL_TRUE, GL_TRUE); + } + if(m_stereoMode == RENDER_STEREO_MODE_ANAGLYPH_GREEN_MAGENTA) + { + if(m_stereoView == RENDER_STEREO_VIEW_LEFT) + glColorMask(GL_FALSE, GL_TRUE, GL_FALSE, GL_TRUE); + else if(m_stereoView == RENDER_STEREO_VIEW_RIGHT) + glColorMask(GL_TRUE, GL_FALSE, GL_TRUE, GL_TRUE); + } + + if(m_stereoMode == RENDER_STEREO_MODE_INTERLACED) + { + glEnable(GL_POLYGON_STIPPLE); + if(m_stereoView == RENDER_STEREO_VIEW_LEFT) + glPolygonStipple(stipple_3d); + else if(m_stereoView == RENDER_STEREO_VIEW_RIGHT) + glPolygonStipple(stipple_3d+4); + } + + if(m_stereoMode == RENDER_STEREO_MODE_HARDWAREBASED) + { + if(m_stereoView == RENDER_STEREO_VIEW_LEFT) + glDrawBuffer(GL_BACK_LEFT); + else if(m_stereoView == RENDER_STEREO_VIEW_RIGHT) + glDrawBuffer(GL_BACK_RIGHT); + } + +} + +bool CRenderSystemGL::SupportsStereo(RENDER_STEREO_MODE mode) +{ + switch(mode) + { + case RENDER_STEREO_MODE_ANAGLYPH_RED_CYAN: + case RENDER_STEREO_MODE_ANAGLYPH_GREEN_MAGENTA: + case RENDER_STEREO_MODE_INTERLACED: + return true; + case RENDER_STEREO_MODE_HARDWAREBASED: { + //This is called by setting init, at which point GL is not inited + //luckily if GL doesn't support this, it will just behave as if + //it was not in effect. + //GLboolean stereo = GL_FALSE; + //glGetBooleanv(GL_STEREO, &stereo); + //return stereo == GL_TRUE ? true : false; + return true; + } + default: + return CRenderSystemBase::SupportsStereo(mode); + } +} + #endif diff --git a/xbmc/rendering/gl/RenderSystemGL.h b/xbmc/rendering/gl/RenderSystemGL.h index 662134d59c..4bd540bfd8 100644 --- a/xbmc/rendering/gl/RenderSystemGL.h +++ b/xbmc/rendering/gl/RenderSystemGL.h @@ -58,6 +58,8 @@ public: virtual void ApplyHardwareTransform(const TransformMatrix &matrix); virtual void RestoreHardwareTransform(); + virtual void SetStereoMode(RENDER_STEREO_MODE mode, RENDER_STEREO_VIEW view); + virtual bool SupportsStereo(RENDER_STEREO_MODE mode); virtual bool TestRender(); diff --git a/xbmc/rendering/gles/RenderSystemGLES.cpp b/xbmc/rendering/gles/RenderSystemGLES.cpp index e81956690b..68a594f734 100644 --- a/xbmc/rendering/gles/RenderSystemGLES.cpp +++ b/xbmc/rendering/gles/RenderSystemGLES.cpp @@ -392,7 +392,7 @@ void CRenderSystemGLES::SetCameraPosition(const CPoint &camera, int screenWidth, g_matrices.MatrixMode(MM_MODELVIEW); g_matrices.LoadIdentity(); - g_matrices.Translatef(-(viewport[0] + w + offset.x), +(viewport[1] + h + offset.y), 0); + g_matrices.Translatef(-(w + offset.x), +(h + offset.y), 0); g_matrices.LookAt(0.0, 0.0, -2.0*h, 0.0, 0.0, 0.0, 0.0, -1.0, 0.0); g_matrices.MatrixMode(MM_PROJECTION); g_matrices.LoadIdentity(); @@ -415,7 +415,7 @@ void CRenderSystemGLES::Project(float &x, float &y, float &z) if (g_matrices.Project(x, y, z, m_view, m_projection, m_viewPort, &coordX, &coordY, &coordZ)) { x = coordX; - y = (float)(m_viewPort[3] - coordY); + y = (float)(m_viewPort[1] + m_viewPort[3] - coordY); z = 0; } } diff --git a/xbmc/settings/AdvancedSettings.cpp b/xbmc/settings/AdvancedSettings.cpp index 8e053addf5..0e1e80d197 100644 --- a/xbmc/settings/AdvancedSettings.cpp +++ b/xbmc/settings/AdvancedSettings.cpp @@ -395,6 +395,9 @@ void CAdvancedSettings::Initialize() // internal video extensions m_videoExtensions += "|.pvr"; + m_stereoscopicflags_sbs = "3DSBS|3D.SBS|HSBS|H.SBS|H-SBS| SBS |FULL-SBS|FULL.SBS|FULLSBS|FSBS|HALF-SBS"; + m_stereoscopicflags_tab = "3DTAB|3D.TAB|HTAB|H.TAB|3DOU|3D.OU|3D.HOU| HOU | OU |HALF-TAB"; + m_logLevelHint = m_logLevel = LOG_LEVEL_NORMAL; m_extraLogLevels = 0; @@ -535,6 +538,8 @@ void CAdvancedSettings::ParseSettingsFile(const CStdString &file) pElement = pRootElement->FirstChildElement("video"); if (pElement) { + XMLUtils::GetString(pElement, "stereoscopicflagssbs", m_stereoscopicflags_sbs); + XMLUtils::GetString(pElement, "stereoscopicflagstab", m_stereoscopicflags_tab); XMLUtils::GetFloat(pElement, "subsdelayrange", m_videoSubsDelayRange, 10, 600); XMLUtils::GetFloat(pElement, "audiodelayrange", m_videoAudioDelayRange, 10, 600); XMLUtils::GetInt(pElement, "blackbarcolour", m_videoBlackBarColour, 0, 255); diff --git a/xbmc/settings/AdvancedSettings.h b/xbmc/settings/AdvancedSettings.h index bc7c69aa14..224268a47b 100644 --- a/xbmc/settings/AdvancedSettings.h +++ b/xbmc/settings/AdvancedSettings.h @@ -395,6 +395,9 @@ class CAdvancedSettings : public ISettingCallback, public ISettingsHandler CStdString m_videoExtensions; CStdString m_discStubExtensions; + CStdString m_stereoscopicflags_sbs; + CStdString m_stereoscopicflags_tab; + CStdString m_logFolder; CStdString m_userAgent; diff --git a/xbmc/settings/DisplaySettings.cpp b/xbmc/settings/DisplaySettings.cpp index 032e7521ef..bf307f6a3f 100644 --- a/xbmc/settings/DisplaySettings.cpp +++ b/xbmc/settings/DisplaySettings.cpp @@ -26,6 +26,7 @@ #include "guilib/GraphicContext.h" #include "guilib/gui3d.h" #include "guilib/LocalizeStrings.h" +#include "guilib/StereoscopicsManager.h" #include "settings/AdvancedSettings.h" #include "settings/Setting.h" #include "settings/Settings.h" @@ -50,6 +51,26 @@ float square_error(float x, float y) return std::max(yonx, xony); } +static CStdString ModeFlagsToString(unsigned int flags, bool identifier) +{ + CStdString res; + if(flags & D3DPRESENTFLAG_INTERLACED) + res += "i"; + else + res += "p"; + + if(!identifier) + res += " "; + + if(flags & D3DPRESENTFLAG_MODE3DSBS) + res += "sbs"; + else if(flags & D3DPRESENTFLAG_MODE3DTB) + res += "tab"; + else if(identifier) + res += "std"; + return res; +} + CDisplaySettings::CDisplaySettings() { m_resolutions.insert(m_resolutions.begin(), RES_CUSTOM, RESOLUTION_INFO()); @@ -250,8 +271,11 @@ bool CDisplaySettings::OnSettingUpdate(CSetting* &setting, const char *oldSettin std::string screenmode = screenmodeSetting->GetValue(); // in Eden there was no character ("i" or "p") indicating interlaced/progressive // at the end so we just add a "p" and assume progressive + // no 3d mode existed before, so just assume std modes if (screenmode.size() == 20) - return screenmodeSetting->SetValue(screenmode + "p"); + return screenmodeSetting->SetValue(screenmode + "pstd"); + if (screenmode.size() == 21) + return screenmodeSetting->SetValue(screenmode + "std"); } return false; @@ -318,7 +342,27 @@ RESOLUTION_INFO& CDisplaySettings::GetResolutionInfo(RESOLUTION resolution) void CDisplaySettings::AddResolutionInfo(const RESOLUTION_INFO &resolution) { CSingleLock lock(m_critical); - m_resolutions.push_back(resolution); + RESOLUTION_INFO res(resolution); + + if((res.dwFlags & D3DPRESENTFLAG_MODE3DTB) == 0) + { + /* add corrections for some special case modes frame packing modes */ + + if(res.iScreenWidth == 1920 + && res.iScreenHeight == 2205) + { + res.iBlanking = 45; + res.dwFlags |= D3DPRESENTFLAG_MODE3DTB; + } + + if(res.iScreenWidth == 1280 + && res.iScreenHeight == 1470) + { + res.iBlanking = 30; + res.dwFlags |= D3DPRESENTFLAG_MODE3DTB; + } + } + m_resolutions.push_back(res); } void CDisplaySettings::ApplyCalibrations() @@ -407,23 +451,24 @@ DisplayMode CDisplaySettings::GetCurrentDisplayMode() const return GetCurrentResolutionInfo().iScreen; } -RESOLUTION CDisplaySettings::FindBestMatchingResolution(const std::map<RESOLUTION, RESOLUTION_INFO> &resolutionInfos, int screen, int width, int height, float refreshrate, bool interlaced) +RESOLUTION CDisplaySettings::FindBestMatchingResolution(const std::map<RESOLUTION, RESOLUTION_INFO> &resolutionInfos, int screen, int width, int height, float refreshrate, unsigned flags) { - int interlace = interlaced ? 100 : 200; - // find the closest match to these in our res vector. If we have the screen, we score the res RESOLUTION bestRes = RES_DESKTOP; float bestScore = FLT_MAX; + flags &= D3DPRESENTFLAG_MODEMASK; for (std::map<RESOLUTION, RESOLUTION_INFO>::const_iterator it = resolutionInfos.begin(); it != resolutionInfos.end(); ++it) { const RESOLUTION_INFO &info = it->second; - if (info.iScreen != screen) + + if ( info.iScreen != screen + || (info.dwFlags & D3DPRESENTFLAG_MODEMASK) != flags) continue; + float score = 10 * (square_error((float)info.iScreenWidth, (float)width) + square_error((float)info.iScreenHeight, (float)height) + - square_error(info.fRefreshRate, refreshrate) + - square_error((float)((info.dwFlags & D3DPRESENTFLAG_INTERLACED) ? 100 : 200), (float)interlace)); + square_error(info.fRefreshRate, refreshrate)); if (score < bestScore) { bestScore = score; @@ -440,22 +485,29 @@ RESOLUTION CDisplaySettings::GetResolutionFromString(const std::string &strResol return RES_DESKTOP; else if (strResolution == "WINDOW") return RES_WINDOW; - else if (strResolution.size() == 21) + else if (strResolution.size() >= 21) { - // format: SWWWWWHHHHHRRR.RRRRRP, where S = screen, W = width, H = height, R = refresh, P = interlace + // format: SWWWWWHHHHHRRR.RRRRRP333, where S = screen, W = width, H = height, R = refresh, P = interlace, 3 = stereo mode int screen = strtol(StringUtils::Mid(strResolution, 0,1).c_str(), NULL, 10); int width = strtol(StringUtils::Mid(strResolution, 1,5).c_str(), NULL, 10); int height = strtol(StringUtils::Mid(strResolution, 6,5).c_str(), NULL, 10); float refresh = (float)strtod(StringUtils::Mid(strResolution, 11,9).c_str(), NULL); + unsigned flags = 0; + // look for 'i' and treat everything else as progressive, - // and use 100/200 to get a nice square_error. - bool interlaced = StringUtils::EndsWith(strResolution, "i"); + if(StringUtils::Mid(strResolution, 20,1) == "i") + flags |= D3DPRESENTFLAG_INTERLACED; + + if(StringUtils::Mid(strResolution, 21,3) == "sbs") + flags |= D3DPRESENTFLAG_MODE3DSBS; + else if(StringUtils::Mid(strResolution, 21,3) == "tab") + flags |= D3DPRESENTFLAG_MODE3DTB; std::map<RESOLUTION, RESOLUTION_INFO> resolutionInfos; for (size_t resolution = RES_DESKTOP; resolution < CDisplaySettings::Get().ResolutionInfoSize(); resolution++) resolutionInfos.insert(make_pair((RESOLUTION)resolution, CDisplaySettings::Get().GetResolutionInfo(resolution))); - return FindBestMatchingResolution(resolutionInfos, screen, width, height, refresh, interlaced); + return FindBestMatchingResolution(resolutionInfos, screen, width, height, refresh, flags); } return RES_DESKTOP; @@ -474,8 +526,7 @@ std::string CDisplaySettings::GetStringFromResolution(RESOLUTION resolution, flo { return StringUtils::Format("%1i%05i%05i%09.5f%s", info.iScreen, info.iScreenWidth, info.iScreenHeight, - refreshrate > 0.0f ? refreshrate : info.fRefreshRate, - (info.dwFlags & D3DPRESENTFLAG_INTERLACED) ? "i":"p"); + refreshrate > 0.0f ? refreshrate : info.fRefreshRate, ModeFlagsToString(info.dwFlags, true).c_str()); } } @@ -554,7 +605,7 @@ void CDisplaySettings::SettingOptionsResolutionsFiller(const CSetting *setting, { list.push_back(make_pair( StringUtils::Format("%dx%d%s", resolution->width, resolution->height, - (resolution->interlaced == D3DPRESENTFLAG_INTERLACED) ? "i" : "p"), + ModeFlagsToString(resolution->flags, false).c_str()), resolution->ResInfo_Index)); resolutionInfos.insert(make_pair((RESOLUTION)resolution->ResInfo_Index, CDisplaySettings::Get().GetResolutionInfo(resolution->ResInfo_Index))); @@ -562,7 +613,7 @@ void CDisplaySettings::SettingOptionsResolutionsFiller(const CSetting *setting, current = FindBestMatchingResolution(resolutionInfos, info.iScreen, info.iScreenWidth, info.iScreenHeight, - info.fRefreshRate, info.dwFlags & D3DPRESENTFLAG_INTERLACED); + info.fRefreshRate, info.dwFlags); } } @@ -596,3 +647,19 @@ void CDisplaySettings::SettingOptionsVerticalSyncsFiller(const CSetting *setting list.push_back(make_pair(g_localizeStrings.Get(13107), VSYNC_VIDEO)); list.push_back(make_pair(g_localizeStrings.Get(13108), VSYNC_ALWAYS)); } + +void CDisplaySettings::SettingOptionsStereoscopicModesFiller(const CSetting *setting, std::vector< std::pair<std::string, int> > &list, int ¤t) +{ + for (int i = RENDER_STEREO_MODE_OFF; i < RENDER_STEREO_MODE_COUNT; i++) + { + RENDER_STEREO_MODE mode = (RENDER_STEREO_MODE) i; + if (g_Windowing.SupportsStereo(mode)) + list.push_back(make_pair(CStereoscopicsManager::Get().GetLabelForStereoMode(mode), mode)); + } +} + +void CDisplaySettings::SettingOptionsPreferredStereoscopicViewModesFiller(const CSetting *setting, std::vector< std::pair<std::string, int> > &list, int ¤t) +{ + SettingOptionsStereoscopicModesFiller(setting, list, current); + list.push_back(make_pair(g_localizeStrings.Get(36525), RENDER_STEREO_MODE_AUTO)); // option for autodetect +} diff --git a/xbmc/settings/DisplaySettings.h b/xbmc/settings/DisplaySettings.h index 4540a34c3e..cc4002b593 100644 --- a/xbmc/settings/DisplaySettings.h +++ b/xbmc/settings/DisplaySettings.h @@ -93,6 +93,8 @@ public: static void SettingOptionsResolutionsFiller(const CSetting *setting, std::vector< std::pair<std::string, int> > &list, int ¤t); static void SettingOptionsScreensFiller(const CSetting *setting, std::vector< std::pair<std::string, int> > &list, int ¤t); static void SettingOptionsVerticalSyncsFiller(const CSetting *setting, std::vector< std::pair<std::string, int> > &list, int ¤t); + static void SettingOptionsStereoscopicModesFiller(const CSetting *setting, std::vector< std::pair<std::string, int> > &list, int ¤t); + static void SettingOptionsPreferredStereoscopicViewModesFiller(const CSetting *setting, std::vector< std::pair<std::string, int> > &list, int ¤t); protected: CDisplaySettings(); @@ -106,7 +108,7 @@ protected: static std::string GetStringFromResolution(RESOLUTION resolution, float refreshrate = 0.0f); static RESOLUTION GetResolutionForScreen(); - static RESOLUTION FindBestMatchingResolution(const std::map<RESOLUTION, RESOLUTION_INFO> &resolutionInfos, int screen, int width, int height, float refreshrate, bool interlaced); + static RESOLUTION FindBestMatchingResolution(const std::map<RESOLUTION, RESOLUTION_INFO> &resolutionInfos, int screen, int width, int height, float refreshrate, unsigned int flags); private: // holds the real gui resolution diff --git a/xbmc/settings/MediaSettings.cpp b/xbmc/settings/MediaSettings.cpp index 558327f377..7c89f3a55a 100644 --- a/xbmc/settings/MediaSettings.cpp +++ b/xbmc/settings/MediaSettings.cpp @@ -129,6 +129,8 @@ bool CMediaSettings::Load(const TiXmlNode *settings) m_defaultVideoSettings.m_SubtitleDelay = 0.0f; XMLUtils::GetBoolean(pElement, "autocrop", m_defaultVideoSettings.m_Crop); XMLUtils::GetBoolean(pElement, "nonlinstretch", m_defaultVideoSettings.m_CustomNonLinStretch); + if (!XMLUtils::GetInt(pElement, "stereomode", m_defaultVideoSettings.m_StereoMode)) + m_defaultVideoSettings.m_StereoMode = 0; m_defaultVideoSettings.m_SubtitleCached = false; } @@ -204,6 +206,7 @@ bool CMediaSettings::Save(TiXmlNode *settings) const XMLUtils::SetFloat(pNode, "subtitledelay", m_defaultVideoSettings.m_SubtitleDelay); XMLUtils::SetBoolean(pNode, "autocrop", m_defaultVideoSettings.m_Crop); XMLUtils::SetBoolean(pNode, "nonlinstretch", m_defaultVideoSettings.m_CustomNonLinStretch); + XMLUtils::SetInt(pNode, "stereomode", m_defaultVideoSettings.m_StereoMode); // mymusic pNode = settings->FirstChild("mymusic"); diff --git a/xbmc/settings/Settings.cpp b/xbmc/settings/Settings.cpp index 2a13509f44..c1d6443b98 100644 --- a/xbmc/settings/Settings.cpp +++ b/xbmc/settings/Settings.cpp @@ -39,6 +39,7 @@ #include "guilib/GUIAudioManager.h" #include "guilib/GUIFontManager.h" #include "guilib/LocalizeStrings.h" +#include "guilib/StereoscopicsManager.h" #include "input/MouseStat.h" #if defined(TARGET_WINDOWS) #include "input/windows/WINJoystick.h" @@ -378,6 +379,8 @@ void CSettings::Uninitialize() m_settingsManager->UnregisterSettingOptionsFiller("rendermethods"); m_settingsManager->UnregisterSettingOptionsFiller("resolutions"); m_settingsManager->UnregisterSettingOptionsFiller("screens"); + m_settingsManager->UnregisterSettingOptionsFiller("stereoscopicmodes"); + m_settingsManager->UnregisterSettingOptionsFiller("preferedstereoscopicviewmodes"); m_settingsManager->UnregisterSettingOptionsFiller("shutdownstates"); m_settingsManager->UnregisterSettingOptionsFiller("startupwindows"); m_settingsManager->UnregisterSettingOptionsFiller("streamlanguages"); @@ -395,6 +398,7 @@ void CSettings::Uninitialize() m_settingsManager->UnregisterCallback(&g_advancedSettings); m_settingsManager->UnregisterCallback(&CMediaSettings::Get()); m_settingsManager->UnregisterCallback(&CDisplaySettings::Get()); + m_settingsManager->UnregisterCallback(&CStereoscopicsManager::Get()); m_settingsManager->UnregisterCallback(&g_application); m_settingsManager->UnregisterCallback(&g_audioManager); m_settingsManager->UnregisterCallback(&g_charsetConverter); @@ -682,6 +686,8 @@ void CSettings::InitializeOptionFillers() m_settingsManager->RegisterSettingOptionsFiller("rendermethods", CBaseRenderer::SettingOptionsRenderMethodsFiller); m_settingsManager->RegisterSettingOptionsFiller("resolutions", CDisplaySettings::SettingOptionsResolutionsFiller); m_settingsManager->RegisterSettingOptionsFiller("screens", CDisplaySettings::SettingOptionsScreensFiller); + m_settingsManager->RegisterSettingOptionsFiller("stereoscopicmodes", CDisplaySettings::SettingOptionsStereoscopicModesFiller); + m_settingsManager->RegisterSettingOptionsFiller("preferedstereoscopicviewmodes", CDisplaySettings::SettingOptionsPreferredStereoscopicViewModesFiller); m_settingsManager->RegisterSettingOptionsFiller("shutdownstates", CPowerManager::SettingOptionsShutdownStatesFiller); m_settingsManager->RegisterSettingOptionsFiller("startupwindows", ADDON::CSkinInfo::SettingOptionsStartupWindowsFiller); m_settingsManager->RegisterSettingOptionsFiller("streamlanguages", CLangInfo::SettingOptionsStreamLanguagesFiller); @@ -854,6 +860,10 @@ void CSettings::InitializeISettingCallbacks() m_settingsManager->RegisterCallback(&CDisplaySettings::Get(), settingSet); settingSet.clear(); + settingSet.insert("videoscreen.stereoscopicmode"); + m_settingsManager->RegisterCallback(&CStereoscopicsManager::Get(), settingSet); + + settingSet.clear(); settingSet.insert("audiooutput.mode"); settingSet.insert("audiooutput.channels"); settingSet.insert("audiooutput.processquality"); diff --git a/xbmc/settings/VideoSettings.cpp b/xbmc/settings/VideoSettings.cpp index 1be3248d66..e61f49a28a 100644 --- a/xbmc/settings/VideoSettings.cpp +++ b/xbmc/settings/VideoSettings.cpp @@ -89,5 +89,7 @@ bool CVideoSettings::operator!=(const CVideoSettings &right) const if (m_CropBottom != right.m_CropBottom) return true; if (m_CropLeft != right.m_CropLeft) return true; if (m_CropRight != right.m_CropRight) return true; + if (m_StereoMode != right.m_StereoMode) return true; + if (m_StereoInvert != right.m_StereoInvert) return true; return false; } diff --git a/xbmc/settings/VideoSettings.h b/xbmc/settings/VideoSettings.h index 0de785d2c3..293f363bc6 100644 --- a/xbmc/settings/VideoSettings.h +++ b/xbmc/settings/VideoSettings.h @@ -138,6 +138,8 @@ public: int m_CropBottom; int m_CropLeft; int m_CropRight; + int m_StereoMode; + bool m_StereoInvert; private: }; diff --git a/xbmc/settings/windows/GUIWindowSettingsScreenCalibration.cpp b/xbmc/settings/windows/GUIWindowSettingsScreenCalibration.cpp index 53eed4c12b..efd45f1a39 100644 --- a/xbmc/settings/windows/GUIWindowSettingsScreenCalibration.cpp +++ b/xbmc/settings/windows/GUIWindowSettingsScreenCalibration.cpp @@ -75,7 +75,7 @@ bool CGUIWindowSettingsScreenCalibration::OnAction(const CAction &action) CGUIDialogYesNo* pDialog = (CGUIDialogYesNo*)g_windowManager.GetWindow(WINDOW_DIALOG_YES_NO); pDialog->SetHeading(20325); CStdString strText; - strText.Format(g_localizeStrings.Get(20326).c_str(), CDisplaySettings::Get().GetResolutionInfo(m_Res[m_iCurRes]).strMode.c_str()); + strText.Format(g_localizeStrings.Get(20326).c_str(), g_graphicsContext.GetResInfo(m_Res[m_iCurRes]).strMode.c_str()); pDialog->SetLine(0, strText); pDialog->SetLine(1, 20327); pDialog->SetChoice(0, 222); @@ -250,49 +250,50 @@ void CGUIWindowSettingsScreenCalibration::ResetControls() // and set their limits // also, set them to invisible if they don't have focus CGUIMoverControl *pControl = (CGUIMoverControl*)GetControl(CONTROL_TOP_LEFT); + RESOLUTION_INFO info = g_graphicsContext.GetResInfo(m_Res[m_iCurRes]); if (pControl) { - pControl->SetLimits( -CDisplaySettings::Get().GetResolutionInfo(m_Res[m_iCurRes]).iWidth / 4, - -CDisplaySettings::Get().GetResolutionInfo(m_Res[m_iCurRes]).iHeight / 4, - CDisplaySettings::Get().GetResolutionInfo(m_Res[m_iCurRes]).iWidth / 4, - CDisplaySettings::Get().GetResolutionInfo(m_Res[m_iCurRes]).iHeight / 4); - pControl->SetPosition((float)CDisplaySettings::Get().GetResolutionInfo(m_Res[m_iCurRes]).Overscan.left, - (float)CDisplaySettings::Get().GetResolutionInfo(m_Res[m_iCurRes]).Overscan.top); - pControl->SetLocation(CDisplaySettings::Get().GetResolutionInfo(m_Res[m_iCurRes]).Overscan.left, - CDisplaySettings::Get().GetResolutionInfo(m_Res[m_iCurRes]).Overscan.top, false); + pControl->SetLimits( -info.iWidth / 4, + -info.iHeight / 4, + info.iWidth / 4, + info.iHeight / 4); + pControl->SetPosition((float)info.Overscan.left, + (float)info.Overscan.top); + pControl->SetLocation(info.Overscan.left, + info.Overscan.top, false); } pControl = (CGUIMoverControl*)GetControl(CONTROL_BOTTOM_RIGHT); if (pControl) { - pControl->SetLimits(CDisplaySettings::Get().GetResolutionInfo(m_Res[m_iCurRes]).iWidth*3 / 4, - CDisplaySettings::Get().GetResolutionInfo(m_Res[m_iCurRes]).iHeight*3 / 4, - CDisplaySettings::Get().GetResolutionInfo(m_Res[m_iCurRes]).iWidth*5 / 4, - CDisplaySettings::Get().GetResolutionInfo(m_Res[m_iCurRes]).iHeight*5 / 4); - pControl->SetPosition((float)CDisplaySettings::Get().GetResolutionInfo(m_Res[m_iCurRes]).Overscan.right - (int)pControl->GetWidth(), - (float)CDisplaySettings::Get().GetResolutionInfo(m_Res[m_iCurRes]).Overscan.bottom - (int)pControl->GetHeight()); - pControl->SetLocation(CDisplaySettings::Get().GetResolutionInfo(m_Res[m_iCurRes]).Overscan.right, - CDisplaySettings::Get().GetResolutionInfo(m_Res[m_iCurRes]).Overscan.bottom, false); + pControl->SetLimits(info.iWidth*3 / 4, + info.iHeight*3 / 4, + info.iWidth*5 / 4, + info.iHeight*5 / 4); + pControl->SetPosition((float)info.Overscan.right - (int)pControl->GetWidth(), + (float)info.Overscan.bottom - (int)pControl->GetHeight()); + pControl->SetLocation(info.Overscan.right, + info.Overscan.bottom, false); } // Subtitles and OSD controls can only move up and down pControl = (CGUIMoverControl*)GetControl(CONTROL_SUBTITLES); if (pControl) { - pControl->SetLimits(0, CDisplaySettings::Get().GetResolutionInfo(m_Res[m_iCurRes]).iHeight*3 / 4, - 0, CDisplaySettings::Get().GetResolutionInfo(m_Res[m_iCurRes]).iHeight*5 / 4); - pControl->SetPosition((CDisplaySettings::Get().GetResolutionInfo(m_Res[m_iCurRes]).iWidth - pControl->GetWidth()) * 0.5f, - CDisplaySettings::Get().GetResolutionInfo(m_Res[m_iCurRes]).iSubtitles - pControl->GetHeight()); - pControl->SetLocation(0, CDisplaySettings::Get().GetResolutionInfo(m_Res[m_iCurRes]).iSubtitles, false); + pControl->SetLimits(0, info.iHeight*3 / 4, + 0, info.iHeight*5 / 4); + pControl->SetPosition((info.iWidth - pControl->GetWidth()) * 0.5f, + info.iSubtitles - pControl->GetHeight()); + pControl->SetLocation(0, info.iSubtitles, false); } // lastly the pixel ratio control... CGUIResizeControl *pResize = (CGUIResizeControl*)GetControl(CONTROL_PIXEL_RATIO); if (pResize) { - pResize->SetLimits(CDisplaySettings::Get().GetResolutionInfo(m_Res[m_iCurRes]).iWidth*0.25f, CDisplaySettings::Get().GetResolutionInfo(m_Res[m_iCurRes]).iHeight*0.5f, - CDisplaySettings::Get().GetResolutionInfo(m_Res[m_iCurRes]).iWidth*0.75f, CDisplaySettings::Get().GetResolutionInfo(m_Res[m_iCurRes]).iHeight*0.5f); - pResize->SetHeight(CDisplaySettings::Get().GetResolutionInfo(m_Res[m_iCurRes]).iHeight * 0.5f); - pResize->SetWidth(pResize->GetHeight() / CDisplaySettings::Get().GetResolutionInfo(m_Res[m_iCurRes]).fPixelRatio); - pResize->SetPosition((CDisplaySettings::Get().GetResolutionInfo(m_Res[m_iCurRes]).iWidth - pResize->GetWidth()) / 2, - (CDisplaySettings::Get().GetResolutionInfo(m_Res[m_iCurRes]).iHeight - pResize->GetHeight()) / 2); + pResize->SetLimits(info.iWidth*0.25f, info.iHeight*0.5f, + info.iWidth*0.75f, info.iHeight*0.5f); + pResize->SetHeight(info.iHeight * 0.5f); + pResize->SetWidth(pResize->GetHeight() / info.fPixelRatio); + pResize->SetPosition((info.iWidth - pResize->GetWidth()) / 2, + (info.iHeight - pResize->GetHeight()) / 2); } // Enable the default control EnableControl(m_iControl); @@ -301,6 +302,8 @@ void CGUIWindowSettingsScreenCalibration::ResetControls() void CGUIWindowSettingsScreenCalibration::UpdateFromControl(int iControl) { CStdString strStatus; + RESOLUTION_INFO info = g_graphicsContext.GetResInfo(m_Res[m_iCurRes]); + if (iControl == CONTROL_PIXEL_RATIO) { CGUIResizeControl *pControl = (CGUIResizeControl*)GetControl(CONTROL_PIXEL_RATIO); @@ -308,11 +311,11 @@ void CGUIWindowSettingsScreenCalibration::UpdateFromControl(int iControl) { float fWidth = (float)pControl->GetWidth(); float fHeight = (float)pControl->GetHeight(); - CDisplaySettings::Get().GetResolutionInfo(m_Res[m_iCurRes]).fPixelRatio = fHeight / fWidth; + info.fPixelRatio = fHeight / fWidth; // recenter our control... - pControl->SetPosition((CDisplaySettings::Get().GetResolutionInfo(m_Res[m_iCurRes]).iWidth - pControl->GetWidth()) / 2, - (CDisplaySettings::Get().GetResolutionInfo(m_Res[m_iCurRes]).iHeight - pControl->GetHeight()) / 2); - strStatus.Format("%s (%5.3f)", g_localizeStrings.Get(275).c_str(), CDisplaySettings::Get().GetResolutionInfo(m_Res[m_iCurRes]).fPixelRatio); + pControl->SetPosition((info.iWidth - pControl->GetWidth()) / 2, + (info.iHeight - pControl->GetHeight()) / 2); + strStatus.Format("%s (%5.3f)", g_localizeStrings.Get(275).c_str(), info.fPixelRatio); SET_CONTROL_LABEL(CONTROL_LABEL_ROW2, 278); } } @@ -325,8 +328,8 @@ void CGUIWindowSettingsScreenCalibration::UpdateFromControl(int iControl) { case CONTROL_TOP_LEFT: { - CDisplaySettings::Get().GetResolutionInfo(m_Res[m_iCurRes]).Overscan.left = pControl->GetXLocation(); - CDisplaySettings::Get().GetResolutionInfo(m_Res[m_iCurRes]).Overscan.top = pControl->GetYLocation(); + info.Overscan.left = pControl->GetXLocation(); + info.Overscan.top = pControl->GetYLocation(); strStatus.Format("%s (%i,%i)", g_localizeStrings.Get(272).c_str(), pControl->GetXLocation(), pControl->GetYLocation()); SET_CONTROL_LABEL(CONTROL_LABEL_ROW2, 276); } @@ -334,10 +337,10 @@ void CGUIWindowSettingsScreenCalibration::UpdateFromControl(int iControl) case CONTROL_BOTTOM_RIGHT: { - CDisplaySettings::Get().GetResolutionInfo(m_Res[m_iCurRes]).Overscan.right = pControl->GetXLocation(); - CDisplaySettings::Get().GetResolutionInfo(m_Res[m_iCurRes]).Overscan.bottom = pControl->GetYLocation(); - int iXOff1 = CDisplaySettings::Get().GetResolutionInfo(m_Res[m_iCurRes]).iWidth - pControl->GetXLocation(); - int iYOff1 = CDisplaySettings::Get().GetResolutionInfo(m_Res[m_iCurRes]).iHeight - pControl->GetYLocation(); + info.Overscan.right = pControl->GetXLocation(); + info.Overscan.bottom = pControl->GetYLocation(); + int iXOff1 = info.iWidth - pControl->GetXLocation(); + int iYOff1 = info.iHeight - pControl->GetYLocation(); strStatus.Format("%s (%i,%i)", g_localizeStrings.Get(273).c_str(), iXOff1, iYOff1); SET_CONTROL_LABEL(CONTROL_LABEL_ROW2, 276); } @@ -345,7 +348,7 @@ void CGUIWindowSettingsScreenCalibration::UpdateFromControl(int iControl) case CONTROL_SUBTITLES: { - CDisplaySettings::Get().GetResolutionInfo(m_Res[m_iCurRes]).iSubtitles = pControl->GetYLocation(); + info.iSubtitles = pControl->GetYLocation(); strStatus.Format("%s (%i)", g_localizeStrings.Get(274).c_str(), pControl->GetYLocation()); SET_CONTROL_LABEL(CONTROL_LABEL_ROW2, 277); } @@ -353,15 +356,18 @@ void CGUIWindowSettingsScreenCalibration::UpdateFromControl(int iControl) } } } + + g_graphicsContext.SetResInfo(m_Res[m_iCurRes], info); + // set the label control correctly CStdString strText; if (g_Windowing.IsFullScreen()) - strText.Format("%ix%i@%.2f - %s | %s", CDisplaySettings::Get().GetResolutionInfo(m_Res[m_iCurRes]).iScreenWidth, - CDisplaySettings::Get().GetResolutionInfo(m_Res[m_iCurRes]).iScreenHeight, CDisplaySettings::Get().GetResolutionInfo(m_Res[m_iCurRes]).fRefreshRate, + strText.Format("%ix%i@%.2f - %s | %s", info.iScreenWidth, + info.iScreenHeight, info.fRefreshRate, g_localizeStrings.Get(244).c_str(), strStatus.c_str()); else - strText.Format("%ix%i - %s | %s", CDisplaySettings::Get().GetResolutionInfo(m_Res[m_iCurRes]).iScreenWidth, - CDisplaySettings::Get().GetResolutionInfo(m_Res[m_iCurRes]).iScreenHeight, + strText.Format("%ix%i - %s | %s", info.iScreenWidth, + info.iScreenHeight, g_localizeStrings.Get(242).c_str(), strStatus.c_str()); SET_CONTROL_LABEL(CONTROL_LABEL_ROW1, strText); diff --git a/xbmc/settings/windows/GUIWindowTestPattern.cpp b/xbmc/settings/windows/GUIWindowTestPattern.cpp index 4c80006aac..18c4f37b3a 100644 --- a/xbmc/settings/windows/GUIWindowTestPattern.cpp +++ b/xbmc/settings/windows/GUIWindowTestPattern.cpp @@ -87,11 +87,12 @@ void CGUIWindowTestPattern::Process(unsigned int currentTime, CDirtyRegionList & void CGUIWindowTestPattern::Render() { BeginRender(); + const RESOLUTION_INFO info = g_graphicsContext.GetResInfo(); - int top = CDisplaySettings::Get().GetResolutionInfo(g_graphicsContext.GetVideoResolution()).Overscan.top; - int bottom = CDisplaySettings::Get().GetResolutionInfo(g_graphicsContext.GetVideoResolution()).Overscan.bottom; - int left = CDisplaySettings::Get().GetResolutionInfo(g_graphicsContext.GetVideoResolution()).Overscan.left; - int right = CDisplaySettings::Get().GetResolutionInfo(g_graphicsContext.GetVideoResolution()).Overscan.right; + int top = info.Overscan.top; + int bottom = info.Overscan.bottom; + int left = info.Overscan.left; + int right = info.Overscan.right; switch (m_pattern) { diff --git a/xbmc/utils/StringUtils.cpp b/xbmc/utils/StringUtils.cpp index aa5c01969e..686e543d56 100644 --- a/xbmc/utils/StringUtils.cpp +++ b/xbmc/utils/StringUtils.cpp @@ -712,6 +712,16 @@ int StringUtils::FindBestMatch(const CStdString &str, const CStdStringArray &str return best; } +bool StringUtils::ContainsKeyword(const CStdString &str, const CStdStringArray &keywords) +{ + for (CStdStringArray::const_iterator it = keywords.begin(); it != keywords.end(); it++) + { + if (str.find(*it) != str.npos) + return true; + } + return false; +} + size_t StringUtils::utf8_strlen(const char *s) { size_t length = 0; diff --git a/xbmc/utils/StringUtils.h b/xbmc/utils/StringUtils.h index 0cae3e3399..9bf6cf5918 100644 --- a/xbmc/utils/StringUtils.h +++ b/xbmc/utils/StringUtils.h @@ -115,6 +115,7 @@ public: static bool ValidateUUID(const CStdString &uuid); // NB only validates syntax static double CompareFuzzy(const CStdString &left, const CStdString &right); static int FindBestMatch(const CStdString &str, const CStdStringArray &strings, double &matchscore); + static bool ContainsKeyword(const CStdString &str, const CStdStringArray &keywords); /*! \brief Escapes the given string to be able to be used as a parameter. diff --git a/xbmc/video/PlayerController.cpp b/xbmc/video/PlayerController.cpp index 931e4a9232..c7e9a89756 100644 --- a/xbmc/video/PlayerController.cpp +++ b/xbmc/video/PlayerController.cpp @@ -290,7 +290,7 @@ bool CPlayerController::OnAction(const CAction &action) case ACTION_SUBTITLE_VSHIFT_UP: { - RESOLUTION_INFO& res_info = CDisplaySettings::Get().GetResolutionInfo(g_graphicsContext.GetVideoResolution()); + RESOLUTION_INFO res_info = g_graphicsContext.GetResInfo(); int subalign = CSettings::Get().GetInt("subtitles.align"); if ((subalign == SUBTITLE_ALIGN_BOTTOM_OUTSIDE) || (subalign == SUBTITLE_ALIGN_TOP_INSIDE)) { @@ -311,12 +311,13 @@ bool CPlayerController::OnAction(const CAction &action) else ShowSlider(action.GetID(), 274, (float) res_info.iSubtitles - res_info.iHeight, (float) -res_info.iHeight, -1.0f, 0.0f); } + g_graphicsContext.SetResInfo(g_graphicsContext.GetVideoResolution(), res_info); return true; } case ACTION_SUBTITLE_VSHIFT_DOWN: { - RESOLUTION_INFO& res_info = CDisplaySettings::Get().GetResolutionInfo(g_graphicsContext.GetVideoResolution()); + RESOLUTION_INFO res_info = g_graphicsContext.GetResInfo(); int subalign = CSettings::Get().GetInt("subtitles.align"); if ((subalign == SUBTITLE_ALIGN_BOTTOM_OUTSIDE) || (subalign == SUBTITLE_ALIGN_TOP_INSIDE)) { @@ -337,12 +338,13 @@ bool CPlayerController::OnAction(const CAction &action) else ShowSlider(action.GetID(), 274, (float) res_info.iSubtitles - res_info.iHeight, (float) -res_info.iHeight, -1.0f, 0.0f); } + g_graphicsContext.SetResInfo(g_graphicsContext.GetVideoResolution(), res_info); return true; } case ACTION_SUBTITLE_ALIGN: { - RESOLUTION_INFO& res_info = CDisplaySettings::Get().GetResolutionInfo(g_graphicsContext.GetVideoResolution()); + RESOLUTION_INFO res_info = g_graphicsContext.GetResInfo(); int subalign = CSettings::Get().GetInt("subtitles.align"); subalign++; @@ -356,6 +358,7 @@ bool CPlayerController::OnAction(const CAction &action) g_localizeStrings.Get(21460), g_localizeStrings.Get(21461 + subalign), TOAST_DISPLAY_TIME, false); + g_graphicsContext.SetResInfo(g_graphicsContext.GetVideoResolution(), res_info); return true; } diff --git a/xbmc/video/VideoDatabase.cpp b/xbmc/video/VideoDatabase.cpp index 7bbb1bb433..bdbadc9299 100644 --- a/xbmc/video/VideoDatabase.cpp +++ b/xbmc/video/VideoDatabase.cpp @@ -108,7 +108,7 @@ bool CVideoDatabase::CreateTables() "SubtitleDelay float, SubtitlesOn bool, Brightness float, Contrast float, Gamma float," "VolumeAmplification float, AudioDelay float, OutputToAllSpeakers bool, ResumeTime integer, Crop bool, CropLeft integer," "CropRight integer, CropTop integer, CropBottom integer, Sharpness float, NoiseReduction float, NonLinStretch bool, PostProcess bool," - "ScalingMethod integer, DeinterlaceMode integer)\n"); + "ScalingMethod integer, DeinterlaceMode integer, StereoMode integer, StereoInvert bool)\n"); m_pDS->exec("CREATE UNIQUE INDEX ix_settings ON settings ( idFile )\n"); CLog::Log(LOGINFO, "create stacktimes table"); @@ -3619,6 +3619,8 @@ bool CVideoDatabase::GetVideoSettings(const CStdString &strFilenameAndPath, CVid settings.m_VolumeAmplification = m_pDS->fv("VolumeAmplification").get_asFloat(); settings.m_OutputToAllSpeakers = m_pDS->fv("OutputToAllSpeakers").get_asBool(); settings.m_ScalingMethod = (ESCALINGMETHOD)m_pDS->fv("ScalingMethod").get_asInt(); + settings.m_StereoMode = m_pDS->fv("StereoMode").get_asInt(); + settings.m_StereoInvert = m_pDS->fv("StereoInvert").get_asBool(); settings.m_SubtitleCached = false; m_pDS->close(); return true; @@ -3659,7 +3661,7 @@ void CVideoDatabase::SetVideoSettings(const CStdString& strFilenameAndPath, cons setting.m_OutputToAllSpeakers,setting.m_Sharpness,setting.m_NoiseReduction,setting.m_CustomNonLinStretch,setting.m_PostProcess,setting.m_ScalingMethod, setting.m_DeinterlaceMode); CStdString strSQL2; - strSQL2=PrepareSQL("ResumeTime=%i,Crop=%i,CropLeft=%i,CropRight=%i,CropTop=%i,CropBottom=%i where idFile=%i\n", setting.m_ResumeTime, setting.m_Crop, setting.m_CropLeft, setting.m_CropRight, setting.m_CropTop, setting.m_CropBottom, idFile); + strSQL2=PrepareSQL("ResumeTime=%i,Crop=%i,CropLeft=%i,CropRight=%i,CropTop=%i,CropBottom=%i,StereoMode=%i,StereoInvert=%i where idFile=%i\n", setting.m_ResumeTime, setting.m_Crop, setting.m_CropLeft, setting.m_CropRight, setting.m_CropTop, setting.m_CropBottom, setting.m_StereoMode, setting.m_StereoInvert, idFile); strSQL += strSQL2; m_pDS->exec(strSQL.c_str()); return ; @@ -3671,7 +3673,7 @@ void CVideoDatabase::SetVideoSettings(const CStdString& strFilenameAndPath, cons "AudioStream,SubtitleStream,SubtitleDelay,SubtitlesOn,Brightness," "Contrast,Gamma,VolumeAmplification,AudioDelay,OutputToAllSpeakers," "ResumeTime,Crop,CropLeft,CropRight,CropTop,CropBottom," - "Sharpness,NoiseReduction,NonLinStretch,PostProcess,ScalingMethod,DeinterlaceMode) " + "Sharpness,NoiseReduction,NonLinStretch,PostProcess,ScalingMethod,DeinterlaceMode,StereoMode,StereoInvert) " "VALUES "; strSQL += PrepareSQL("(%i,%i,%i,%f,%f,%f,%i,%i,%f,%i,%f,%f,%f,%f,%f,%i,%i,%i,%i,%i,%i,%i,%f,%f,%i,%i,%i,%i)", idFile, setting.m_InterlaceMethod, setting.m_ViewMode, setting.m_CustomZoomAmount, setting.m_CustomPixelRatio, setting.m_CustomVerticalShift, @@ -3679,7 +3681,7 @@ void CVideoDatabase::SetVideoSettings(const CStdString& strFilenameAndPath, cons setting.m_Contrast, setting.m_Gamma, setting.m_VolumeAmplification, setting.m_AudioDelay, setting.m_OutputToAllSpeakers, setting.m_ResumeTime, setting.m_Crop, setting.m_CropLeft, setting.m_CropRight, setting.m_CropTop, setting.m_CropBottom, setting.m_Sharpness, setting.m_NoiseReduction, setting.m_CustomNonLinStretch, setting.m_PostProcess, setting.m_ScalingMethod, - setting.m_DeinterlaceMode); + setting.m_DeinterlaceMode, setting.m_StereoMode, setting.m_StereoInvert); m_pDS->exec(strSQL.c_str()); } } @@ -4418,6 +4420,11 @@ bool CVideoDatabase::UpdateOldVersion(int iVersion) m_pDS->exec("CREATE INDEX ix_path ON path ( strPath(255) )"); m_pDS->exec("CREATE INDEX ix_files ON files ( idPath, strFilename(255) )"); } + if (iVersion < 76) + { + m_pDS->exec("ALTER TABLE settings ADD StereoMode integer"); + m_pDS->exec("ALTER TABLE settings ADD StereoInvert bool"); + } // always recreate the view after any table change CreateViews(); return true; @@ -4425,7 +4432,7 @@ bool CVideoDatabase::UpdateOldVersion(int iVersion) int CVideoDatabase::GetMinVersion() const { - return 75; + return 76; } bool CVideoDatabase::LookupByFolders(const CStdString &path, bool shows) diff --git a/xbmc/video/dialogs/GUIDialogVideoSettings.cpp b/xbmc/video/dialogs/GUIDialogVideoSettings.cpp index 684b4716c4..a27aed30c4 100644 --- a/xbmc/video/dialogs/GUIDialogVideoSettings.cpp +++ b/xbmc/video/dialogs/GUIDialogVideoSettings.cpp @@ -25,6 +25,7 @@ #include "utils/MathUtils.h" #ifdef HAS_VIDEO_PLAYBACK #include "cores/VideoRenderers/RenderManager.h" +#include "cores/VideoRenderers/RenderFlags.h" #endif #include "video/VideoDatabase.h" #include "dialogs/GUIDialogYesNo.h" @@ -69,6 +70,9 @@ CGUIDialogVideoSettings::~CGUIDialogVideoSettings(void) #define VIDEO_SETTINGS_VERTICAL_SHIFT 23 #define VIDEO_SETTINGS_DEINTERLACEMODE 24 +#define VIDEO_SETTINGS_STEREOSCOPICMODE 25 +#define VIDEO_SETTINGS_STEREOSCOPICINVERT 26 + void CGUIDialogVideoSettings::CreateSettings() { m_usePopupSliders = g_SkinInfo->HasSkinFile("DialogSlider.xml"); @@ -188,6 +192,14 @@ void CGUIDialogVideoSettings::CreateSettings() if (g_renderManager.Supports(RENDERFEATURE_NONLINSTRETCH)) AddBool(VIDEO_SETTINGS_NONLIN_STRETCH, 659, &CMediaSettings::Get().GetCurrentVideoSettings().m_CustomNonLinStretch); #endif + + vector<pair<int, int> > stereomode; + stereomode.push_back(make_pair(RENDER_STEREO_MODE_OFF , 16316)); + stereomode.push_back(make_pair(RENDER_STEREO_MODE_SPLIT_HORIZONTAL, 36503)); + stereomode.push_back(make_pair(RENDER_STEREO_MODE_SPLIT_VERTICAL , 36504)); + AddSpin(VIDEO_SETTINGS_STEREOSCOPICMODE , 36535, &CMediaSettings::Get().GetCurrentVideoSettings().m_StereoMode, stereomode); + AddBool(VIDEO_SETTINGS_STEREOSCOPICINVERT, 36536, &CMediaSettings::Get().GetCurrentVideoSettings().m_StereoInvert); + AddSeparator(8); AddButton(VIDEO_SETTINGS_MAKE_DEFAULT, 12376); AddButton(VIDEO_SETTINGS_CALIBRATION, 214); diff --git a/xbmc/video/windows/GUIWindowFullScreen.cpp b/xbmc/video/windows/GUIWindowFullScreen.cpp index 3e6d714f2f..75ff89de41 100644 --- a/xbmc/video/windows/GUIWindowFullScreen.cpp +++ b/xbmc/video/windows/GUIWindowFullScreen.cpp @@ -632,6 +632,8 @@ void CGUIWindowFullScreen::FrameMove() } if (m_bShowViewModeInfo) { + RESOLUTION_INFO res = g_graphicsContext.GetResInfo(); + { // get the "View Mode" string CStdString strTitle = g_localizeStrings.Get(629); @@ -647,9 +649,8 @@ void CGUIWindowFullScreen::FrameMove() g_application.m_pPlayer->GetVideoStreamInfo(info); { // Splitres scaling factor - RESOLUTION res = g_graphicsContext.GetVideoResolution(); - float xscale = (float)CDisplaySettings::Get().GetResolutionInfo(res).iScreenWidth / (float)CDisplaySettings::Get().GetResolutionInfo(res).iWidth; - float yscale = (float)CDisplaySettings::Get().GetResolutionInfo(res).iScreenHeight / (float)CDisplaySettings::Get().GetResolutionInfo(res).iHeight; + float xscale = (float)res.iScreenWidth / (float)res.iWidth; + float yscale = (float)res.iScreenHeight / (float)res.iHeight; CStdString strSizing; strSizing.Format(g_localizeStrings.Get(245), @@ -662,18 +663,17 @@ void CGUIWindowFullScreen::FrameMove() OnMessage(msg); } // show resolution information - int iResolution = g_graphicsContext.GetVideoResolution(); { CStdString strStatus; if (g_Windowing.IsFullScreen()) strStatus.Format("%s %ix%i@%.2fHz - %s", - g_localizeStrings.Get(13287), CDisplaySettings::Get().GetResolutionInfo(iResolution).iScreenWidth, - CDisplaySettings::Get().GetResolutionInfo(iResolution).iScreenHeight, CDisplaySettings::Get().GetResolutionInfo(iResolution).fRefreshRate, + g_localizeStrings.Get(13287), res.iScreenWidth, + res.iScreenHeight, res.fRefreshRate, g_localizeStrings.Get(244)); else strStatus.Format("%s %ix%i - %s", - g_localizeStrings.Get(13287), CDisplaySettings::Get().GetResolutionInfo(iResolution).iScreenWidth, - CDisplaySettings::Get().GetResolutionInfo(iResolution).iScreenHeight, g_localizeStrings.Get(242)); + g_localizeStrings.Get(13287), res.iScreenWidth, + res.iScreenHeight, g_localizeStrings.Get(242)); CGUIMessage msg(GUI_MSG_LABEL_SET, GetID(), LABEL_ROW3); msg.SetLabel(strStatus); @@ -796,20 +796,20 @@ void CGUIWindowFullScreen::RenderTTFSubtitles() subtitleText.Replace("</b", "[/B]"); subtitleText.Replace("</u", ""); - RESOLUTION res = g_graphicsContext.GetVideoResolution(); - g_graphicsContext.SetRenderingResolution(g_graphicsContext.GetResInfo(), false); + RESOLUTION_INFO res = g_graphicsContext.GetResInfo(); + g_graphicsContext.SetRenderingResolution(res, false); - float maxWidth = (float) CDisplaySettings::Get().GetResolutionInfo(res).Overscan.right - CDisplaySettings::Get().GetResolutionInfo(res).Overscan.left; + float maxWidth = (float) res.Overscan.right - res.Overscan.left; m_subsLayout->Update(subtitleText, maxWidth * 0.9f, false, true); // true to force LTR reading order (most Hebrew subs are this format) int subalign = CSettings::Get().GetInt("subtitles.align"); float textWidth, textHeight; m_subsLayout->GetTextExtent(textWidth, textHeight); - float x = maxWidth * 0.5f + CDisplaySettings::Get().GetResolutionInfo(res).Overscan.left; - float y = (float) CDisplaySettings::Get().GetResolutionInfo(res).iSubtitles; + float x = maxWidth * 0.5f + res.Overscan.left; + float y = (float) res.iSubtitles; if (subalign == SUBTITLE_ALIGN_MANUAL) - y = (float) CDisplaySettings::Get().GetResolutionInfo(res).iSubtitles - textHeight; + y = (float) res.iSubtitles - textHeight; else { SPlayerVideoStreamInfo info; @@ -822,12 +822,12 @@ void CGUIWindowFullScreen::RenderTTFSubtitles() // use the manual distance to the screenbottom as an offset to the automatic location if ((subalign == SUBTITLE_ALIGN_BOTTOM_INSIDE) || (subalign == SUBTITLE_ALIGN_TOP_OUTSIDE)) - y -= textHeight + g_graphicsContext.GetHeight() - CDisplaySettings::Get().GetResolutionInfo(res).iSubtitles; + y -= textHeight + g_graphicsContext.GetHeight() - res.iSubtitles; else - y += g_graphicsContext.GetHeight() - CDisplaySettings::Get().GetResolutionInfo(res).iSubtitles; + y += g_graphicsContext.GetHeight() - res.iSubtitles; - y = std::max(y, (float) CDisplaySettings::Get().GetResolutionInfo(res).Overscan.top); - y = std::min(y, CDisplaySettings::Get().GetResolutionInfo(res).Overscan.bottom - textHeight); + y = std::max(y, (float) res.Overscan.top); + y = std::min(y, res.Overscan.bottom - textHeight); } m_subsLayout->RenderOutline(x, y, 0, 0xFF000000, XBFONT_CENTER_X, maxWidth); diff --git a/xbmc/visualizations/WaveForm/Main.cpp b/xbmc/visualizations/WaveForm/Main.cpp index e818dc42cf..c54f581d2d 100644 --- a/xbmc/visualizations/WaveForm/Main.cpp +++ b/xbmc/visualizations/WaveForm/Main.cpp @@ -55,12 +55,12 @@ D3DVIEWPORT9 g_viewport; struct Vertex_t { - float x, y, z, w; + float x, y, z; D3DCOLOR col; }; #ifndef HAS_SDL_OPENGL -#define VERTEX_FORMAT (D3DFVF_XYZRHW | D3DFVF_DIFFUSE) +#define VERTEX_FORMAT (D3DFVF_XYZ | D3DFVF_DIFFUSE) #endif //-- Create ------------------------------------------------------------------- @@ -142,7 +142,6 @@ extern "C" void Render() verts[i].x = g_viewport.X + ((i / 255.0f) * g_viewport.Width); verts[i].y = g_viewport.Y + g_viewport.Height * 0.33f + (g_fWaveform[0][i] * g_viewport.Height * 0.15f); verts[i].z = 1.0; - verts[i].w = 1; #ifdef HAS_SDL_OPENGL glVertex2f(verts[i].x, verts[i].y); #endif @@ -167,7 +166,6 @@ extern "C" void Render() verts[i].x = g_viewport.X + ((i / 255.0f) * g_viewport.Width); verts[i].y = g_viewport.Y + g_viewport.Height * 0.66f + (g_fWaveform[1][i] * g_viewport.Height * 0.15f); verts[i].z = 1.0; - verts[i].w = 1; #ifdef HAS_SDL_OPENGL glVertex2f(verts[i].x, verts[i].y); #endif diff --git a/xbmc/visualizations/XBMCProjectM/libprojectM/Renderer.cpp b/xbmc/visualizations/XBMCProjectM/libprojectM/Renderer.cpp index 7b0a199b68..d96a3d8fb0 100644 --- a/xbmc/visualizations/XBMCProjectM/libprojectM/Renderer.cpp +++ b/xbmc/visualizations/XBMCProjectM/libprojectM/Renderer.cpp @@ -132,6 +132,8 @@ void Renderer::RenderFrame(PresetOutputs *presetOutputs, PresetInputs *presetInp glPushMatrix(); glMatrixMode(GL_MODELVIEW); glPushMatrix(); + GLint viewport[4]; + glGetIntegerv(GL_VIEWPORT, viewport); totalframes++; @@ -228,7 +230,7 @@ void Renderer::RenderFrame(PresetOutputs *presetOutputs, PresetInputs *presetInp } else #endif - glViewport( vx, vy, this->vw + vx, this->vh + vy ); + glViewport( viewport[0], viewport[1], viewport[2], viewport[3] ); diff --git a/xbmc/windowing/WinSystem.cpp b/xbmc/windowing/WinSystem.cpp index 3dff898dbc..c1641bef9c 100644 --- a/xbmc/windowing/WinSystem.cpp +++ b/xbmc/windowing/WinSystem.cpp @@ -70,9 +70,17 @@ void CWinSystemBase::UpdateDesktopResolution(RESOLUTION_INFO& newRes, int screen newRes.iScreenHeight = height; newRes.strMode.Format("%dx%d", width, height); if (refreshRate > 1) - newRes.strMode.Format("%s @ %.2f%s - Full Screen", newRes.strMode, refreshRate, dwFlags & D3DPRESENTFLAG_INTERLACED ? "i" : ""); + newRes.strMode.AppendFormat("@ %.2f", refreshRate); + if (dwFlags & D3DPRESENTFLAG_INTERLACED) + newRes.strMode += "i"; + if (dwFlags & D3DPRESENTFLAG_MODE3DTB) + newRes.strMode += "tab"; + if (dwFlags & D3DPRESENTFLAG_MODE3DSBS) + newRes.strMode += "sbs"; if (screen > 0) newRes.strMode.Format("%s #%d", newRes.strMode, screen + 1); + if (refreshRate > 1) + newRes.strMode += " - Full Screen"; } void CWinSystemBase::UpdateResolutions() @@ -117,13 +125,13 @@ static void AddResolution(vector<RESOLUTION_WHR> &resolutions, unsigned int addi RESOLUTION_INFO resInfo = CDisplaySettings::Get().GetResolutionInfo(addindex); int width = resInfo.iScreenWidth; int height = resInfo.iScreenHeight; - int interlaced = resInfo.dwFlags & D3DPRESENTFLAG_INTERLACED; + int flags = resInfo.dwFlags & D3DPRESENTFLAG_MODEMASK; float refreshrate = resInfo.fRefreshRate; for (unsigned int idx = 0; idx < resolutions.size(); idx++) if ( resolutions[idx].width == width && resolutions[idx].height == height - && resolutions[idx].interlaced == interlaced) + &&(resolutions[idx].flags & D3DPRESENTFLAG_MODEMASK) == flags) { // check if the refresh rate of this resolution is better suited than // the refresh rate of the resolution with the same width/height/interlaced @@ -135,7 +143,7 @@ static void AddResolution(vector<RESOLUTION_WHR> &resolutions, unsigned int addi return; } - RESOLUTION_WHR res = {width, height, interlaced, (int)addindex}; + RESOLUTION_WHR res = {width, height, flags, (int)addindex}; resolutions.push_back(res); } @@ -143,7 +151,7 @@ static bool resSortPredicate(RESOLUTION_WHR i, RESOLUTION_WHR j) { return ( i.width < j.width || (i.width == j.width && i.height < j.height) - || (i.width == j.width && i.height == j.height && i.interlaced != j.interlaced) ); + || (i.width == j.width && i.height == j.height && i.flags != j.flags) ); } vector<RESOLUTION_WHR> CWinSystemBase::ScreenResolutions(int screen, float refreshrate) @@ -188,7 +196,7 @@ vector<REFRESHRATE> CWinSystemBase::RefreshRates(int screen, int width, int heig if ( CDisplaySettings::Get().GetResolutionInfo(idx).iScreen == screen && CDisplaySettings::Get().GetResolutionInfo(idx).iScreenWidth == width && CDisplaySettings::Get().GetResolutionInfo(idx).iScreenHeight == height - && (CDisplaySettings::Get().GetResolutionInfo(idx).dwFlags & D3DPRESENTFLAG_INTERLACED) == (dwFlags & D3DPRESENTFLAG_INTERLACED)) + && (CDisplaySettings::Get().GetResolutionInfo(idx).dwFlags & D3DPRESENTFLAG_MODEMASK) == (dwFlags & D3DPRESENTFLAG_MODEMASK)) AddRefreshRate(refreshrates, idx); // Can't assume a sort order diff --git a/xbmc/windowing/WinSystem.h b/xbmc/windowing/WinSystem.h index 3500a8db5c..fc467f1768 100644 --- a/xbmc/windowing/WinSystem.h +++ b/xbmc/windowing/WinSystem.h @@ -40,7 +40,7 @@ struct RESOLUTION_WHR { int width; int height; - int interlaced; + int flags; //< only D3DPRESENTFLAG_MODEMASK flags int ResInfo_Index; }; diff --git a/xbmc/windowing/egl/EGLNativeTypeRaspberryPI.cpp b/xbmc/windowing/egl/EGLNativeTypeRaspberryPI.cpp index 6cf35c450d..fb5c1c64b7 100644 --- a/xbmc/windowing/egl/EGLNativeTypeRaspberryPI.cpp +++ b/xbmc/windowing/egl/EGLNativeTypeRaspberryPI.cpp @@ -88,7 +88,6 @@ void CEGLNativeTypeRaspberryPI::Initialize() #if defined(TARGET_RASPBERRY_PI) m_DllBcmHost = NULL; m_dispman_element = DISPMANX_NO_HANDLE; - m_dispman_element2 = DISPMANX_NO_HANDLE; m_dispman_display = DISPMANX_NO_HANDLE; m_width = 1280; @@ -181,7 +180,8 @@ int CEGLNativeTypeRaspberryPI::FindMatchingResolution(const RESOLUTION_INFO &res { for (int i = 0; i < (int)resolutions.size(); i++) { - if(resolutions[i].iScreenWidth == res.iScreenWidth && resolutions[i].iScreenHeight == res.iScreenHeight && resolutions[i].fRefreshRate == res.fRefreshRate) + if(resolutions[i].iScreenWidth == res.iScreenWidth && resolutions[i].iScreenHeight == res.iScreenHeight && resolutions[i].fRefreshRate == res.fRefreshRate && + (resolutions[i].dwFlags & (D3DPRESENTFLAG_MODE3DSBS|D3DPRESENTFLAG_MODE3DTB)) == (res.dwFlags & (D3DPRESENTFLAG_MODE3DSBS|D3DPRESENTFLAG_MODE3DTB))) { return i; } @@ -289,46 +289,6 @@ bool CEGLNativeTypeRaspberryPI::SetNativeResolution(const RESOLUTION_INFO &res) CLog::Log(LOGDEBUG, "EGL set resolution %dx%d -> %dx%d @ %.2f fps (%d,%d) flags:%x aspect:%.2f\n", m_width, m_height, dst_rect.width, dst_rect.height, res.fRefreshRate, GETFLAGS_GROUP(res.dwFlags), GETFLAGS_MODE(res.dwFlags), (int)res.dwFlags, res.fPixelRatio); - // The trick for SBS is that we stick two dispman elements together - // and the PI firmware knows that we are in SBS/TAB mode and it renders the gui in SBS/TAB - if(res.dwFlags & (D3DPRESENTFLAG_MODE3DSBS|D3DPRESENTFLAG_MODE3DTB)) - { - if (res.dwFlags & D3DPRESENTFLAG_MODE3DTB) - { - // bottom half - dst_rect.y = res.iScreenHeight; - } - else - { - // right side - dst_rect.x = res.iScreenWidth; - } - - m_dispman_element2 = m_DllBcmHost->vc_dispmanx_element_add(dispman_update, - m_dispman_display, - 1, // layer - &dst_rect, - (DISPMANX_RESOURCE_HANDLE_T)0, // src - &src_rect, - DISPMANX_PROTECTION_NONE, - &alpha, // alpha - &clamp, // clamp - transform); // transform - assert(m_dispman_element2 != DISPMANX_NO_HANDLE); - assert(m_dispman_element2 != (unsigned)DISPMANX_INVALID); - - if (res.dwFlags & D3DPRESENTFLAG_MODE3DTB) - { - // top half - fall through - dst_rect.y = 0; - } - else - { - // left side - fall through - dst_rect.x = 0; - } - } - m_dispman_element = m_DllBcmHost->vc_dispmanx_element_add(dispman_update, m_dispman_display, 1, // layer @@ -425,21 +385,19 @@ bool CEGLNativeTypeRaspberryPI::ProbeResolutions(std::vector<RESOLUTION_INFO> &r m_desktopRes.iScreenWidth = tv_state.display.hdmi.width; m_desktopRes.iScreenHeight= tv_state.display.hdmi.height; m_desktopRes.dwFlags = MAKEFLAGS(tv_state.display.hdmi.group, tv_state.display.hdmi.mode, tv_state.display.hdmi.scan_mode); + m_desktopRes.fPixelRatio = get_display_aspect_ratio((HDMI_ASPECT_T)tv_state.display.hdmi.display_options.aspect) / ((float)m_desktopRes.iScreenWidth / (float)m_desktopRes.iScreenHeight); // Also add 3D flags if (tv_state.display.hdmi.format_3d == HDMI_3D_FORMAT_SBS_HALF) { m_desktopRes.dwFlags |= D3DPRESENTFLAG_MODE3DSBS; - m_desktopRes.iWidth >>= 1; - m_desktopRes.iScreenWidth >>= 1; + m_desktopRes.fPixelRatio *= 2.0; } else if (tv_state.display.hdmi.format_3d == HDMI_3D_FORMAT_TB_HALF) { m_desktopRes.dwFlags |= D3DPRESENTFLAG_MODE3DTB; - m_desktopRes.iHeight >>= 1; - m_desktopRes.iScreenHeight >>= 1; + m_desktopRes.fPixelRatio *= 0.5; } m_desktopRes.fRefreshRate = (float)tv_state.display.hdmi.frame_rate; - m_desktopRes.fPixelRatio = get_display_aspect_ratio((HDMI_ASPECT_T)tv_state.display.hdmi.display_options.aspect) / ((float)m_desktopRes.iScreenWidth / (float)m_desktopRes.iScreenHeight); } else // sdtv { @@ -522,11 +480,6 @@ void CEGLNativeTypeRaspberryPI::DestroyDispmaxWindow() m_DllBcmHost->vc_dispmanx_element_remove(dispman_update, m_dispman_element); m_dispman_element = DISPMANX_NO_HANDLE; } - if (m_dispman_element2 != DISPMANX_NO_HANDLE) - { - m_DllBcmHost->vc_dispmanx_element_remove(dispman_update, m_dispman_element2); - m_dispman_element2 = DISPMANX_NO_HANDLE; - } m_DllBcmHost->vc_dispmanx_update_submit_sync(dispman_update); if (m_dispman_display != DISPMANX_NO_HANDLE) @@ -603,9 +556,8 @@ void CEGLNativeTypeRaspberryPI::GetSupportedModes(HDMI_RES_GROUP_T group, std::v { RESOLUTION_INFO res2 = res; res2.dwFlags |= D3DPRESENTFLAG_MODE3DSBS; - res2.iWidth >>= 1; - res2.iScreenWidth >>= 1; res2.fPixelRatio = get_display_aspect_ratio((HDMI_ASPECT_T)tv->aspect_ratio) / ((float)res2.iScreenWidth / (float)res2.iScreenHeight); + res2.fPixelRatio *= 2.0f; res2.strMode.Format("%dx%d", res2.iScreenWidth, res2.iScreenHeight); res2.strMode.Format("%dx%d @ %.2f%s - Full Screen", res2.iScreenWidth, res2.iScreenHeight, res2.fRefreshRate, res2.dwFlags & D3DPRESENTFLAG_INTERLACED ? "i" : ""); @@ -619,9 +571,8 @@ void CEGLNativeTypeRaspberryPI::GetSupportedModes(HDMI_RES_GROUP_T group, std::v { RESOLUTION_INFO res2 = res; res2.dwFlags |= D3DPRESENTFLAG_MODE3DTB; - res2.iHeight >>= 1; - res2.iScreenHeight >>= 1; res2.fPixelRatio = get_display_aspect_ratio((HDMI_ASPECT_T)tv->aspect_ratio) / ((float)res2.iScreenWidth / (float)res2.iScreenHeight); + res2.fPixelRatio *= 0.5f; res2.strMode.Format("%dx%d", res2.iScreenWidth, res2.iScreenHeight); res2.strMode.Format("%dx%d @ %.2f%s - Full Screen", res2.iScreenWidth, res2.iScreenHeight, res2.fRefreshRate, res2.dwFlags & D3DPRESENTFLAG_INTERLACED ? "i" : ""); diff --git a/xbmc/windowing/egl/EGLNativeTypeRaspberryPI.h b/xbmc/windowing/egl/EGLNativeTypeRaspberryPI.h index 64bbe993bd..20699313d5 100644 --- a/xbmc/windowing/egl/EGLNativeTypeRaspberryPI.h +++ b/xbmc/windowing/egl/EGLNativeTypeRaspberryPI.h @@ -57,7 +57,6 @@ private: DllBcmHost *m_DllBcmHost; DISPMANX_ELEMENT_HANDLE_T m_dispman_display; DISPMANX_ELEMENT_HANDLE_T m_dispman_element; - DISPMANX_ELEMENT_HANDLE_T m_dispman_element2; TV_GET_STATE_RESP_T m_tv_state; sem_t m_tv_synced; bool m_fixedMode; diff --git a/xbmc/windowing/egl/WinSystemEGL.cpp b/xbmc/windowing/egl/WinSystemEGL.cpp index cf88054df7..e5efbfe76d 100644 --- a/xbmc/windowing/egl/WinSystemEGL.cpp +++ b/xbmc/windowing/egl/WinSystemEGL.cpp @@ -237,7 +237,8 @@ bool CWinSystemEGL::CreateNewWindow(const CStdString& name, bool fullScreen, RES if ((m_bWindowCreated && m_egl && m_egl->GetNativeResolution(¤t_resolution)) && current_resolution.iWidth == res.iWidth && current_resolution.iHeight == res.iHeight && current_resolution.iScreenWidth == res.iScreenWidth && current_resolution.iScreenHeight == res.iScreenHeight && - m_bFullScreen == fullScreen && current_resolution.fRefreshRate == res.fRefreshRate) + m_bFullScreen == fullScreen && current_resolution.fRefreshRate == res.fRefreshRate && + (current_resolution.dwFlags & D3DPRESENTFLAG_MODEMASK) == (res.dwFlags & D3DPRESENTFLAG_MODEMASK)) { CLog::Log(LOGDEBUG, "CWinSystemEGL::CreateNewWindow: No need to create a new window"); return true; @@ -343,6 +344,7 @@ void CWinSystemEGL::UpdateResolutions() resDesktop.iHeight == resolutions[i].iHeight && resDesktop.iScreenWidth == resolutions[i].iScreenWidth && resDesktop.iScreenHeight == resolutions[i].iScreenHeight && + (resDesktop.dwFlags & D3DPRESENTFLAG_MODEMASK) == (resolutions[i].dwFlags & D3DPRESENTFLAG_MODEMASK) && resDesktop.fRefreshRate == resolutions[i].fRefreshRate) { ResDesktop = res_index; @@ -458,24 +460,6 @@ bool CWinSystemEGL::Support3D(int width, int height, uint32_t mode) const int searchWidth = curr.iScreenWidth; int searchHeight = curr.iScreenHeight; - // work out current non-3D resolution (in case we are currently in 3D mode) - if (curr.dwFlags & D3DPRESENTFLAG_MODE3DSBS) - { - searchWidth *= 2; - } - else if (curr.dwFlags & D3DPRESENTFLAG_MODE3DTB) - { - searchHeight *= 2; - } - // work out resolution if we switch to 3D mode - if (mode & D3DPRESENTFLAG_MODE3DSBS) - { - searchWidth /= 2; - } - else if (mode & D3DPRESENTFLAG_MODE3DTB) - { - searchHeight /= 2; - } // only search the custom resolutions for (unsigned int i = (int)RES_DESKTOP; i < CDisplaySettings::Get().ResolutionInfoSize(); i++) { diff --git a/xbmc/windows/GUIWindowLoginScreen.cpp b/xbmc/windows/GUIWindowLoginScreen.cpp index 95d4c46735..c4d7e87317 100644 --- a/xbmc/windows/GUIWindowLoginScreen.cpp +++ b/xbmc/windows/GUIWindowLoginScreen.cpp @@ -38,6 +38,7 @@ #include "guilib/GUIMessage.h" #include "GUIUserMessages.h" #include "guilib/GUIWindowManager.h" +#include "guilib/StereoscopicsManager.h" #include "dialogs/GUIDialogOK.h" #include "settings/Settings.h" #include "FileItem.h" @@ -318,4 +319,5 @@ void CGUIWindowLoginScreen::LoadProfile(unsigned int profile) g_windowManager.ChangeActiveWindow(g_SkinInfo->GetFirstWindow()); g_application.UpdateLibraries(); + CStereoscopicsManager::Get().Initialize(); } |