2 * Copyright (C) 2010-2013 Team XBMC
5 * This Program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2, or (at your option)
10 * This Program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with XBMC; see the file COPYING. If not, see
17 * <http://www.gnu.org/licenses/>.
21 #if defined(TARGET_DARWIN_IOS)
22 //hack around problem with xbmc's typedef int BOOL
23 // and obj-c's typedef unsigned char BOOL
24 #define BOOL XBMC_BOOL
29 #define BOOL XBMC_BOOL
30 #include "WinSystemIOS.h"
31 #include "utils/log.h"
32 #include "filesystem/SpecialProtocol.h"
33 #include "settings/DisplaySettings.h"
34 #include "guilib/GraphicContext.h"
35 #include "guilib/Texture.h"
36 #include "utils/StringUtils.h"
40 #import <Foundation/Foundation.h>
41 #import <OpenGLES/ES2/gl.h>
42 #import <OpenGLES/ES2/glext.h>
43 #if defined(TARGET_DARWIN_IOS_ATV2)
44 #import "atv2/XBMCController.h"
46 #import "ios/XBMCController.h"
48 #import "osx/IOSScreenManager.h"
49 #include "osx/DarwinUtils.h"
52 CWinSystemIOS::CWinSystemIOS() : CWinSystemBase()
54 m_eWindowSystem = WINDOW_SYSTEM_IOS;
59 CWinSystemIOS::~CWinSystemIOS()
63 bool CWinSystemIOS::InitWindowSystem()
65 return CWinSystemBase::InitWindowSystem();
68 bool CWinSystemIOS::DestroyWindowSystem()
73 bool CWinSystemIOS::CreateNewWindow(const CStdString& name, bool fullScreen, RESOLUTION_INFO& res, PHANDLE_EVENT_FUNC userFunction)
75 //NSLog(@"%s", __PRETTY_FUNCTION__);
77 if(!SetFullScreen(fullScreen, res, false))
80 [g_xbmcController setFramebuffer];
82 m_bWindowCreated = true;
85 m_eglext += (const char*) glGetString(GL_EXTENSIONS);
88 CLog::Log(LOGDEBUG, "EGL_EXTENSIONS:%s", m_eglext.c_str());
92 bool CWinSystemIOS::DestroyWindow()
97 bool CWinSystemIOS::ResizeWindow(int newWidth, int newHeight, int newLeft, int newTop)
99 //NSLog(@"%s", __PRETTY_FUNCTION__);
101 if (m_nWidth != newWidth || m_nHeight != newHeight)
104 m_nHeight = newHeight;
107 CRenderSystemGLES::ResetRenderSystem(newWidth, newHeight, false, 0);
112 bool CWinSystemIOS::SetFullScreen(bool fullScreen, RESOLUTION_INFO& res, bool blankOtherDisplays)
114 //NSLog(@"%s", __PRETTY_FUNCTION__);
116 m_nWidth = res.iWidth;
117 m_nHeight = res.iHeight;
118 m_bFullScreen = fullScreen;
120 CLog::Log(LOGDEBUG, "About to switch to %i x %i on screen %i",m_nWidth, m_nHeight, res.iScreen);
121 #ifndef TARGET_DARWIN_IOS_ATV2
122 SwitchToVideoMode(res.iWidth, res.iHeight, res.fRefreshRate, res.iScreen);
123 #endif//TARGET_DARWIN_IOS_ATV2
124 CRenderSystemGLES::ResetRenderSystem(res.iWidth, res.iHeight, fullScreen, res.fRefreshRate);
129 UIScreenMode *getModeForResolution(int width, int height, unsigned int screenIdx)
131 if( screenIdx >= [[UIScreen screens] count])
134 UIScreen *aScreen = [[UIScreen screens]objectAtIndex:screenIdx];
135 for ( UIScreenMode *mode in [aScreen availableModes] )
137 //for main screen also find modes where width and height are
138 //exchanged (because of the 90°degree rotated buildinscreens)
139 if((mode.size.width == width && mode.size.height == height) ||
140 (screenIdx == 0 && mode.size.width == height && mode.size.height == width))
142 CLog::Log(LOGDEBUG,"Found matching mode");
146 CLog::Log(LOGERROR,"No matching mode found!");
150 bool CWinSystemIOS::SwitchToVideoMode(int width, int height, double refreshrate, int screenIdx)
153 // SwitchToVideoMode will not return until the display has actually switched over.
154 // This can take several seconds.
155 if( screenIdx >= GetNumScreens())
158 //get the mode to pass to the controller
159 UIScreenMode *newMode = getModeForResolution(width, height, screenIdx);
163 ret = [g_xbmcController changeScreen:screenIdx withMode:newMode];
168 int CWinSystemIOS::GetNumScreens()
170 return [[UIScreen screens] count];
173 int CWinSystemIOS::GetCurrentScreen()
176 if ([[IOSScreenManager sharedInstance] isExternalScreen])
183 bool CWinSystemIOS::GetScreenResolution(int* w, int* h, double* fps, int screenIdx)
185 // Figure out the screen size. (default to main screen)
186 if(screenIdx >= GetNumScreens())
188 UIScreen *screen = [[UIScreen screens] objectAtIndex:screenIdx];
189 CGSize screenSize = [screen currentMode].size;
190 *w = screenSize.width;
191 *h = screenSize.height;
193 //if current mode is 0x0 (happens with external screens which arn't active)
194 //then use the preferred mode
195 if(*h == 0 || *w ==0)
197 UIScreenMode *firstMode = [screen preferredMode];
198 *w = firstMode.size.width;
199 *h = firstMode.size.height;
202 //for mainscreen use the eagl bounds
203 //because mainscreen is build in
207 *w = [g_xbmcController getScreenSize].width;
208 *h = [g_xbmcController getScreenSize].height;
210 CLog::Log(LOGDEBUG,"Current resolution Screen: %i with %i x %i",screenIdx, *w, *h);
214 void CWinSystemIOS::UpdateResolutions()
216 // Add display resolution
219 CWinSystemBase::UpdateResolutions();
221 //first screen goes into the current desktop mode
222 if(GetScreenResolution(&w, &h, &fps, 0))
224 UpdateDesktopResolution(CDisplaySettings::Get().GetResolutionInfo(RES_DESKTOP), 0, w, h, fps);
227 #ifndef TARGET_DARWIN_IOS_ATV2
228 //see resolution.h enum RESOLUTION for how the resolutions
229 //have to appear in the resolution info vector in CDisplaySettings
230 //add the desktop resolutions of the other screens
231 for(int i = 1; i < GetNumScreens(); i++)
234 //get current resolution of screen i
235 if(GetScreenResolution(&w, &h, &fps, i))
237 UpdateDesktopResolution(res, i, w, h, fps);
238 CDisplaySettings::Get().AddResolutionInfo(res);
242 //now just fill in the possible reolutions for the attached screens
243 //and push to the resolution info vector
245 #endif //TARGET_DARWIN_IOS_ATV2
248 void CWinSystemIOS::FillInVideoModes()
250 // Add full screen settings for additional monitors
251 int numDisplays = GetNumScreens();
253 for (int disp = 0; disp < numDisplays; disp++)
257 // atm we don't get refreshrate info from iOS
258 // but this may change in the future. In that case
259 // we will adapt this code for filling some
260 // usefull info into this local var :)
261 double refreshrate = 0.0;
262 //screen 0 is mainscreen - 1 has to be the external one...
263 UIScreen *aScreen = [[UIScreen screens]objectAtIndex:disp];
264 //found external screen
265 for ( UIScreenMode *mode in [aScreen availableModes] )
268 h = mode.size.height;
269 UpdateDesktopResolution(res, disp, w, h, refreshrate);
270 CLog::Log(LOGNOTICE, "Found possible resolution for display %d with %d x %d\n", disp, w, h);
272 //overwrite the mode str because UpdateDesktopResolution adds a
273 //"Full Screen". Since the current resolution is there twice
274 //this would lead to 2 identical resolution entrys in the guisettings.xml.
275 //That would cause problems with saving screen overscan calibration
276 //because the wrong entry is picked on load.
277 //So we just use UpdateDesktopResolutions for the current DESKTOP_RESOLUTIONS
278 //in UpdateResolutions. And on all othere resolutions make a unique
279 //mode str by doing it without appending "Full Screen".
280 //this is what linux does - though it feels that there shouldn't be
281 //the same resolution twice... - thats why i add a FIXME here.
282 res.strMode = StringUtils::Format("%dx%d @ %.2f", w, h, refreshrate);
283 g_graphicsContext.ResetOverscan(res);
284 CDisplaySettings::Get().AddResolutionInfo(res);
289 bool CWinSystemIOS::IsExtSupported(const char* extension)
291 if(strncmp(extension, "EGL_", 4) != 0)
292 return CRenderSystemGLES::IsExtSupported(extension);
300 return m_eglext.find(name) != string::npos;
303 bool CWinSystemIOS::BeginRender()
307 [g_xbmcController setFramebuffer];
309 rtn = CRenderSystemGLES::BeginRender();
313 bool CWinSystemIOS::EndRender()
317 rtn = CRenderSystemGLES::EndRender();
321 void CWinSystemIOS::InitDisplayLink(void)
324 void CWinSystemIOS::DeinitDisplayLink(void)
327 double CWinSystemIOS::GetDisplayLinkFPS(void)
331 fps = [g_xbmcController getDisplayLinkFPS];
335 bool CWinSystemIOS::PresentRenderImpl(const CDirtyRegionList &dirty)
338 [g_xbmcController presentFramebuffer];
342 void CWinSystemIOS::SetVSyncImpl(bool enable)
345 // set swapinterval if possible
346 void *eglSwapInterval;
347 eglSwapInterval = dlsym( RTLD_DEFAULT, "eglSwapInterval" );
348 if ( eglSwapInterval )
350 ((void(*)(int))eglSwapInterval)( 1 ) ;
356 void CWinSystemIOS::ShowOSMouse(bool show)
360 bool CWinSystemIOS::HasCursor()
362 if( DarwinIsAppleTV2() )
366 else//apple touch devices
372 void CWinSystemIOS::NotifyAppActiveChange(bool bActivated)
374 if (bActivated && m_bWasFullScreenBeforeMinimize && !g_graphicsContext.IsFullScreenRoot())
375 g_graphicsContext.ToggleFullScreenRoot();
378 bool CWinSystemIOS::Minimize()
380 m_bWasFullScreenBeforeMinimize = g_graphicsContext.IsFullScreenRoot();
381 if (m_bWasFullScreenBeforeMinimize)
382 g_graphicsContext.ToggleFullScreenRoot();
387 bool CWinSystemIOS::Restore()
392 bool CWinSystemIOS::Hide()
397 bool CWinSystemIOS::Show(bool raise)