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 #include "osx/DarwinUtils.h"
51 CWinSystemIOS::CWinSystemIOS() : CWinSystemBase()
53 m_eWindowSystem = WINDOW_SYSTEM_IOS;
58 CWinSystemIOS::~CWinSystemIOS()
62 bool CWinSystemIOS::InitWindowSystem()
64 return CWinSystemBase::InitWindowSystem();
67 bool CWinSystemIOS::DestroyWindowSystem()
72 bool CWinSystemIOS::CreateNewWindow(const CStdString& name, bool fullScreen, RESOLUTION_INFO& res, PHANDLE_EVENT_FUNC userFunction)
74 //NSLog(@"%s", __PRETTY_FUNCTION__);
76 if(!SetFullScreen(fullScreen, res, false))
79 [g_xbmcController setFramebuffer];
81 m_bWindowCreated = true;
84 m_eglext += (const char*) glGetString(GL_EXTENSIONS);
87 CLog::Log(LOGDEBUG, "EGL_EXTENSIONS:%s", m_eglext.c_str());
91 bool CWinSystemIOS::DestroyWindow()
96 bool CWinSystemIOS::ResizeWindow(int newWidth, int newHeight, int newLeft, int newTop)
98 //NSLog(@"%s", __PRETTY_FUNCTION__);
100 if (m_nWidth != newWidth || m_nHeight != newHeight)
103 m_nHeight = newHeight;
106 CRenderSystemGLES::ResetRenderSystem(newWidth, newHeight, false, 0);
111 bool CWinSystemIOS::SetFullScreen(bool fullScreen, RESOLUTION_INFO& res, bool blankOtherDisplays)
113 //NSLog(@"%s", __PRETTY_FUNCTION__);
115 m_nWidth = res.iWidth;
116 m_nHeight = res.iHeight;
117 m_bFullScreen = fullScreen;
119 CLog::Log(LOGDEBUG, "About to switch to %i x %i on screen %i",m_nWidth, m_nHeight, res.iScreen);
120 #ifndef TARGET_DARWIN_IOS_ATV2
121 SwitchToVideoMode(res.iWidth, res.iHeight, res.fRefreshRate, res.iScreen);
122 #endif//TARGET_DARWIN_IOS_ATV2
123 CRenderSystemGLES::ResetRenderSystem(res.iWidth, res.iHeight, fullScreen, res.fRefreshRate);
128 UIScreenMode *getModeForResolution(int width, int height, unsigned int screenIdx)
130 if( screenIdx >= [[UIScreen screens] count])
133 UIScreen *aScreen = [[UIScreen screens]objectAtIndex:screenIdx];
134 for ( UIScreenMode *mode in [aScreen availableModes] )
136 //for main screen also find modes where width and height are
137 //exchanged (because of the 90°degree rotated buildinscreens)
138 if((mode.size.width == width && mode.size.height == height) ||
139 (screenIdx == 0 && mode.size.width == height && mode.size.height == width))
141 CLog::Log(LOGDEBUG,"Found matching mode");
145 CLog::Log(LOGERROR,"No matching mode found!");
149 bool CWinSystemIOS::SwitchToVideoMode(int width, int height, double refreshrate, int screenIdx)
152 // SwitchToVideoMode will not return until the display has actually switched over.
153 // This can take several seconds.
154 if( screenIdx >= GetNumScreens())
157 //get the mode to pass to the controller
158 UIScreenMode *newMode = getModeForResolution(width, height, screenIdx);
162 ret = [g_xbmcController changeScreen:screenIdx withMode:newMode];
167 int CWinSystemIOS::GetNumScreens()
169 return [[UIScreen screens] count];
172 bool CWinSystemIOS::GetScreenResolution(int* w, int* h, double* fps, int screenIdx)
174 // Figure out the screen size. (default to main screen)
175 if(screenIdx >= GetNumScreens())
177 UIScreen *screen = [[UIScreen screens] objectAtIndex:screenIdx];
178 CGSize screenSize = [screen currentMode].size;
179 *w = screenSize.width;
180 *h = screenSize.height;
182 //if current mode is 0x0 (happens with external screens which arn't active)
183 //then use the preferred mode
184 if(*h == 0 || *w ==0)
186 UIScreenMode *firstMode = [screen preferredMode];
187 *w = firstMode.size.width;
188 *h = firstMode.size.height;
191 //for mainscreen use the eagl bounds
192 //because mainscreen is build in
196 *w = [g_xbmcController getScreenSize].width;
197 *h = [g_xbmcController getScreenSize].height;
199 CLog::Log(LOGDEBUG,"Current resolution Screen: %i with %i x %i",screenIdx, *w, *h);
203 void CWinSystemIOS::UpdateResolutions()
205 // Add display resolution
208 CWinSystemBase::UpdateResolutions();
210 //first screen goes into the current desktop mode
211 if(GetScreenResolution(&w, &h, &fps, 0))
213 UpdateDesktopResolution(CDisplaySettings::Get().GetResolutionInfo(RES_DESKTOP), 0, w, h, fps);
216 #ifndef TARGET_DARWIN_IOS_ATV2
217 //see resolution.h enum RESOLUTION for how the resolutions
218 //have to appear in the resolution info vector in CDisplaySettings
219 //add the desktop resolutions of the other screens
220 for(int i = 1; i < GetNumScreens(); i++)
223 //get current resolution of screen i
224 if(GetScreenResolution(&w, &h, &fps, i))
226 UpdateDesktopResolution(res, i, w, h, fps);
227 CDisplaySettings::Get().AddResolutionInfo(res);
231 //now just fill in the possible reolutions for the attached screens
232 //and push to the resolution info vector
234 #endif //TARGET_DARWIN_IOS_ATV2
237 void CWinSystemIOS::FillInVideoModes()
239 // Add full screen settings for additional monitors
240 int numDisplays = GetNumScreens();
242 for (int disp = 0; disp < numDisplays; disp++)
246 // atm we don't get refreshrate info from iOS
247 // but this may change in the future. In that case
248 // we will adapt this code for filling some
249 // usefull info into this local var :)
250 double refreshrate = 0.0;
251 //screen 0 is mainscreen - 1 has to be the external one...
252 UIScreen *aScreen = [[UIScreen screens]objectAtIndex:disp];
253 //found external screen
254 for ( UIScreenMode *mode in [aScreen availableModes] )
257 h = mode.size.height;
258 UpdateDesktopResolution(res, disp, w, h, refreshrate);
259 CLog::Log(LOGNOTICE, "Found possible resolution for display %d with %d x %d\n", disp, w, h);
261 //overwrite the mode str because UpdateDesktopResolution adds a
262 //"Full Screen". Since the current resolution is there twice
263 //this would lead to 2 identical resolution entrys in the guisettings.xml.
264 //That would cause problems with saving screen overscan calibration
265 //because the wrong entry is picked on load.
266 //So we just use UpdateDesktopResolutions for the current DESKTOP_RESOLUTIONS
267 //in UpdateResolutions. And on all othere resolutions make a unique
268 //mode str by doing it without appending "Full Screen".
269 //this is what linux does - though it feels that there shouldn't be
270 //the same resolution twice... - thats why i add a FIXME here.
271 res.strMode = StringUtils::Format("%dx%d @ %.2f", w, h, refreshrate);
272 g_graphicsContext.ResetOverscan(res);
273 CDisplaySettings::Get().AddResolutionInfo(res);
278 bool CWinSystemIOS::IsExtSupported(const char* extension)
280 if(strncmp(extension, "EGL_", 4) != 0)
281 return CRenderSystemGLES::IsExtSupported(extension);
289 return m_eglext.find(name) != string::npos;
292 bool CWinSystemIOS::BeginRender()
296 [g_xbmcController setFramebuffer];
298 rtn = CRenderSystemGLES::BeginRender();
302 bool CWinSystemIOS::EndRender()
306 rtn = CRenderSystemGLES::EndRender();
310 void CWinSystemIOS::InitDisplayLink(void)
313 void CWinSystemIOS::DeinitDisplayLink(void)
316 double CWinSystemIOS::GetDisplayLinkFPS(void)
320 fps = [g_xbmcController getDisplayLinkFPS];
324 bool CWinSystemIOS::PresentRenderImpl(const CDirtyRegionList &dirty)
327 [g_xbmcController presentFramebuffer];
331 void CWinSystemIOS::SetVSyncImpl(bool enable)
334 // set swapinterval if possible
335 void *eglSwapInterval;
336 eglSwapInterval = dlsym( RTLD_DEFAULT, "eglSwapInterval" );
337 if ( eglSwapInterval )
339 ((void(*)(int))eglSwapInterval)( 1 ) ;
345 void CWinSystemIOS::ShowOSMouse(bool show)
349 bool CWinSystemIOS::HasCursor()
351 if( DarwinIsAppleTV2() )
355 else//apple touch devices
361 void CWinSystemIOS::NotifyAppActiveChange(bool bActivated)
363 if (bActivated && m_bWasFullScreenBeforeMinimize && !g_graphicsContext.IsFullScreenRoot())
364 g_graphicsContext.ToggleFullScreenRoot();
367 bool CWinSystemIOS::Minimize()
369 m_bWasFullScreenBeforeMinimize = g_graphicsContext.IsFullScreenRoot();
370 if (m_bWasFullScreenBeforeMinimize)
371 g_graphicsContext.ToggleFullScreenRoot();
376 bool CWinSystemIOS::Restore()
381 bool CWinSystemIOS::Hide()
386 bool CWinSystemIOS::Show(bool raise)