1/*
2-----------------------------------------------------------------------------
3This source file is part of OGRE
4    (Object-oriented Graphics Rendering Engine)
5For the latest info, see http://www.ogre3d.org/
6
7Copyright (c) 2000-2013 Torus Knot Software Ltd
8
9Permission is hereby granted, free of charge, to any person obtaining a copy
10of this software and associated documentation files (the "Software"), to deal
11in the Software without restriction, including without limitation the rights
12to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13copies of the Software, and to permit persons to whom the Software is
14furnished to do so, subject to the following conditions:
15
16The above copyright notice and this permission notice shall be included in
17all copies or substantial portions of the Software.
18
19THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
25THE SOFTWARE.
26-----------------------------------------------------------------------------
27*/
28
29#include "OgreRoot.h"
30
31#include "OgreGLES2RenderSystem.h"
32#include "OgreEAGLES2Context.h"
33
34#include "OgreEAGL2Support.h"
35#include "OgreEAGL2Window.h"
36
37#include "macUtils.h"
38
39#import <UIKit/UIScreen.h>
40
41namespace Ogre {
42
43    EAGL2Support::EAGL2Support()
44    {
45        mCurrentOSVersion = [[[UIDevice currentDevice] systemVersion] floatValue];
46    }
47
48    EAGL2Support::~EAGL2Support()
49    {
50    }
51
52    void EAGL2Support::addConfig(void)
53    {
54        ConfigOption optFullScreen;
55        ConfigOption optVideoMode;
56        ConfigOption optDisplayFrequency;
57        ConfigOption optContentScalingFactor;
58        ConfigOption optFSAA;
59        ConfigOption optRTTMode;
60
61        optFullScreen.name = "Full Screen";
62        optFullScreen.possibleValues.push_back("Yes");
63        optFullScreen.possibleValues.push_back("No");
64        optFullScreen.currentValue = "Yes";
65        optFullScreen.immutable = false;
66
67        // Get the application frame size.  On all iPhones(including iPhone 4) this will be 320 x 480
68        // The iPad, at least with iPhone OS 3.2 will report 768 x 1024
69        CGSize screenSize = [[UIScreen mainScreen] bounds].size;
70
71        optVideoMode.name = "Video Mode";
72        optVideoMode.possibleValues.push_back("320 x 480");
73        optVideoMode.possibleValues.push_back("320 x 568");
74        optVideoMode.possibleValues.push_back("768 x 1024");
75        optVideoMode.currentValue = StringConverter::toString(screenSize.width) + " x " +
76                                    StringConverter::toString(screenSize.height);
77        optVideoMode.immutable = false;
78
79        optDisplayFrequency.name = "Display Frequency";
80        optDisplayFrequency.possibleValues.push_back("0 Hz");
81        optDisplayFrequency.currentValue = "0 Hz";
82        optDisplayFrequency.immutable = false;
83
84        optContentScalingFactor.name = "Content Scaling Factor";
85        optContentScalingFactor.possibleValues.push_back( "1.0" );
86        optContentScalingFactor.possibleValues.push_back( "1.33" );
87        optContentScalingFactor.possibleValues.push_back( "1.5" );
88        optContentScalingFactor.possibleValues.push_back( "2.0" );
89        optContentScalingFactor.currentValue = StringConverter::toString([UIScreen mainScreen].scale);
90        optContentScalingFactor.immutable = false;
91
92        optFSAA.name = "FSAA";
93        optFSAA.possibleValues.push_back( "0" );
94        optFSAA.possibleValues.push_back( "2" );
95        optFSAA.possibleValues.push_back( "4" );
96        optFSAA.possibleValues.push_back( "8" );
97        optFSAA.currentValue = "0";
98        optFSAA.immutable = false;
99
100        optRTTMode.name = "RTT Preferred Mode";
101        optRTTMode.possibleValues.push_back("Copy");
102        optRTTMode.possibleValues.push_back("FBO");
103        optRTTMode.currentValue = "FBO";
104        optRTTMode.immutable = false;
105
106        mOptions[optFullScreen.name] = optFullScreen;
107        mOptions[optVideoMode.name] = optVideoMode;
108        mOptions[optDisplayFrequency.name] = optDisplayFrequency;
109        mOptions[optContentScalingFactor.name] = optContentScalingFactor;
110        mOptions[optFSAA.name] = optFSAA;
111        mOptions[optRTTMode.name] = optRTTMode;
112
113#if OGRE_NO_VIEWPORT_ORIENTATIONMODE == 0
114        ConfigOption optOrientation;
115        optOrientation.name = "Orientation";
116        optOrientation.possibleValues.push_back("Portrait");
117        optOrientation.possibleValues.push_back("Landscape Left");
118        optOrientation.possibleValues.push_back("Landscape Right");
119        optOrientation.currentValue = "Portrait";
120        optOrientation.immutable = false;
121        mOptions[optOrientation.name] = optOrientation;
122#endif
123
124        // Set the shader cache path
125        NSArray *paths = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES);
126        NSString *cachesDirectory = [paths objectAtIndex:0];
127
128        setShaderCachePath([[cachesDirectory stringByAppendingString:@"/"] cStringUsingEncoding:NSASCIIStringEncoding]);
129
130        // Set the shader library path
131        setShaderLibraryPath(Ogre::macBundlePath() + "/Contents/Media/RTShaderLib");
132    }
133
134    String EAGL2Support::validateConfig(void)
135    {
136        // TODO - DJR
137        return StringUtil::BLANK;
138    }
139
140    String EAGL2Support::getDisplayName(void)
141    {
142        return "todo";
143	}
144
145    CFDictionaryRef EAGL2Support::chooseGLConfig(const GLint *attribList, GLint *nElements)
146    {
147        // TODO: DJR - implement
148        CFDictionaryRef configs = NULL;
149
150        return configs;
151    }
152
153    GLint EAGL2Support::getGLConfigAttrib(CFDictionaryRef glConfig, GLint attribute, GLint *value)
154    {
155        // TODO: DJR - implement
156        GLint status = 0;
157
158        return status;
159    }
160
161    CFDictionaryRef EAGL2Support::getGLConfigFromContext(EAGLES2Context context)
162    {
163        // TODO: DJR - implement
164        CFDictionaryRef glConfig = 0;
165
166        return glConfig;
167    }
168
169    CFDictionaryRef EAGL2Support::getGLConfigFromDrawable(CAEAGLLayer *drawable,
170                                                    unsigned int *w, unsigned int *h)
171    {
172        // TODO: DJR - implement
173        CFDictionaryRef glConfig = 0;
174
175        return glConfig;
176    }
177
178    //------------------------------------------------------------------------
179    // A helper class for the implementation of selectFBConfig
180    //------------------------------------------------------------------------
181    class GLConfigAttribs
182    {
183        public:
184            GLConfigAttribs(const int* attribs)
185            {
186                for (int i = 0; attribs[2*i] != 0; i++)
187                {
188                    fields[attribs[2*i]] = attribs[2*i+1];
189                }
190            }
191
192            void load(EAGL2Support* const glSupport, CFDictionaryRef glConfig)
193            {
194                std::map<int,int>::iterator it;
195
196                for (it = fields.begin(); it != fields.end(); it++)
197                {
198                    it->second = 0;
199
200                    glSupport->getGLConfigAttrib(glConfig, it->first, &it->second);
201                }
202            }
203
204            bool operator>(GLConfigAttribs& alternative)
205            {
206                return false;
207            }
208
209            std::map<int,int> fields;
210    };
211
212    CFDictionaryRef EAGL2Support::selectGLConfig(const int* minAttribs, const int *maxAttribs)
213    {
214        // TODO: DJR - implement
215        CFDictionaryRef glConfig = 0;
216        int nConfigs = 0;//, config;
217
218        glConfig = chooseGLConfig(minAttribs, &nConfigs);
219
220        if (!nConfigs)
221        {
222            return 0;
223        }
224
225        return glConfig;
226    }
227
228    RenderWindow * EAGL2Support::createWindow(bool autoCreateWindow,
229                                           GLES2RenderSystem* renderSystem,
230                                           const String& windowTitle)
231    {
232        RenderWindow *window = 0;
233
234        if (autoCreateWindow)
235        {
236            ConfigOptionMap::iterator opt;
237            ConfigOptionMap::iterator end = mOptions.end();
238            NameValuePairList miscParams;
239
240            CGSize screenSize = [[UIScreen mainScreen] bounds].size;
241            bool fullscreen = false;
242            uint w = (uint)screenSize.width, h = (uint)screenSize.height;
243
244            if ((opt = mOptions.find("Full Screen")) != end)
245            {
246                fullscreen = (opt->second.currentValue == "Yes");
247            }
248
249            if ((opt = mOptions.find("Display Frequency")) != end)
250            {
251                miscParams["displayFrequency"] = opt->second.currentValue;
252            }
253
254            if ((opt = mOptions.find("Content Scaling Factor")) != end)
255            {
256                miscParams["contentScalingFactor"] = opt->second.currentValue;
257            }
258
259            if ((opt = mOptions.find("Video Mode")) != end)
260            {
261                String val = opt->second.currentValue;
262                String::size_type pos = val.find('x');
263
264                if (pos != String::npos)
265                {
266                    w = StringConverter::parseUnsignedInt(val.substr(0, pos));
267                    h = StringConverter::parseUnsignedInt(val.substr(pos + 1));
268                }
269            }
270
271            if ((opt = mOptions.find("FSAA")) != end)
272            {
273                miscParams["FSAA"] = opt->second.currentValue;
274            }
275
276            window = renderSystem->_createRenderWindow(windowTitle, w, h, fullscreen, &miscParams);
277        }
278
279        return window;
280    }
281
282    RenderWindow * EAGL2Support::newWindow(const String &name,
283                                        unsigned int width, unsigned int height,
284                                        bool fullScreen,
285                                        const NameValuePairList *miscParams)
286    {
287        EAGL2Window *window = OGRE_NEW EAGL2Window(this);
288        window->create(name, width, height, fullScreen, miscParams);
289
290        return window;
291    }
292
293    EAGLES2Context * EAGL2Support::createNewContext(CFDictionaryRef &glconfig, CAEAGLLayer *drawable, EAGLSharegroup *group) const
294    {
295        EAGLES2Context *context = new EAGLES2Context(drawable, group);
296        if (context == NULL)
297        {
298            OGRE_EXCEPT(Exception::ERR_RENDERINGAPI_ERROR,
299                        "Fail to create new context",
300                        __FUNCTION__);
301            return context;
302        }
303
304        // Initialise GL3W
305        if (gleswInit())
306            LogManager::getSingleton().logMessage("Failed to initialize GL3W");
307
308        return context;
309    }
310
311    void * EAGL2Support::getProcAddress(const Ogre::String& name)
312    {
313        return NULL;
314    }
315
316    void EAGL2Support::start()
317    {
318    }
319
320    void EAGL2Support::stop()
321    {
322    }
323
324    bool EAGL2Support::interfaceOrientationIsSupported(NSString *orientation)
325    {
326        NSArray *supportedOrientations = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"UISupportedInterfaceOrientations"];
327
328        return [supportedOrientations containsObject:orientation];
329    }
330
331    bool EAGL2Support::portraitIsSupported()
332    {
333        NSArray *supportedOrientations = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"UISupportedInterfaceOrientations"];
334
335        return ([supportedOrientations containsObject:@"UIInterfaceOrientationPortrait"] ||
336                [supportedOrientations containsObject:@"UIInterfaceOrientationPortraitUpsideDown"]);
337    }
338}
339