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 "OgreGLESRenderSystem.h"
32#include "OgreEAGLESContext.h"
33
34#include "OgreEAGLRenderTexture.h"
35#include "OgreEAGLSupport.h"
36#include "OgreEAGLWindow.h"
37
38namespace Ogre {
39
40    EAGLSupport::EAGLSupport()
41    {
42    }
43
44    EAGLSupport::~EAGLSupport()
45    {
46    }
47
48    void EAGLSupport::addConfig(void)
49    {
50        ConfigOption optFullScreen;
51        ConfigOption optVideoMode;
52        ConfigOption optDisplayFrequency;
53        ConfigOption optContentScalingFactor;
54        ConfigOption optFSAA;
55        ConfigOption optRTTMode;
56
57        optFullScreen.name = "Full Screen";
58        optFullScreen.possibleValues.push_back("Yes");
59        optFullScreen.possibleValues.push_back("No");
60        optFullScreen.currentValue = "Yes";
61        optFullScreen.immutable = false;
62
63        // Get the application frame size.  On all iPhones(including iPhone 4) this will be 320 x 480
64        // The iPad, at least with iPhone OS 3.2 will report 768 x 1024
65        CGSize screenSize = [[UIScreen mainScreen] bounds].size;
66
67        optVideoMode.name = "Video Mode";
68        optVideoMode.possibleValues.push_back("320 x 480");
69        optVideoMode.possibleValues.push_back("320 x 568");
70        optVideoMode.possibleValues.push_back("768 x 1024");
71        optVideoMode.currentValue = StringConverter::toString(screenSize.width) + " x " +
72                                    StringConverter::toString(screenSize.height);
73        optVideoMode.immutable = false;
74
75        optDisplayFrequency.name = "Display Frequency";
76        optDisplayFrequency.possibleValues.push_back("0 Hz");
77        optDisplayFrequency.currentValue = "0 Hz";
78        optDisplayFrequency.immutable = false;
79
80        optContentScalingFactor.name = "Content Scaling Factor";
81        optContentScalingFactor.possibleValues.push_back( "1.0" );
82        optContentScalingFactor.possibleValues.push_back( "1.33" );
83        optContentScalingFactor.possibleValues.push_back( "1.5" );
84        optContentScalingFactor.possibleValues.push_back( "2.0" );
85        optContentScalingFactor.currentValue = StringConverter::toString([UIScreen mainScreen].scale);
86        optContentScalingFactor.immutable = false;
87
88        optFSAA.name = "FSAA";
89        optFSAA.possibleValues.push_back( "0" );
90        optFSAA.possibleValues.push_back( "2" );
91        optFSAA.possibleValues.push_back( "4" );
92        optFSAA.currentValue = "0";
93        optFSAA.immutable = false;
94
95        optRTTMode.name = "RTT Preferred Mode";
96        optRTTMode.possibleValues.push_back("Copy");
97        optRTTMode.possibleValues.push_back("FBO");
98        optRTTMode.currentValue = "FBO";
99        optRTTMode.immutable = false;
100
101        mOptions[optFullScreen.name] = optFullScreen;
102        mOptions[optVideoMode.name] = optVideoMode;
103        mOptions[optDisplayFrequency.name] = optDisplayFrequency;
104        mOptions[optContentScalingFactor.name] = optContentScalingFactor;
105        mOptions[optFSAA.name] = optFSAA;
106        mOptions[optRTTMode.name] = optRTTMode;
107    }
108
109    String EAGLSupport::validateConfig(void)
110    {
111        // TODO - DJR
112        return StringUtil::BLANK;
113    }
114
115    String EAGLSupport::getDisplayName(void)
116    {
117        return "todo";
118	}
119
120    CFDictionaryRef EAGLSupport::chooseGLConfig(const GLint *attribList, GLint *nElements)
121    {
122        // TODO: DJR - implement
123        CFDictionaryRef configs = NULL;
124
125        return configs;
126    }
127
128    GLint EAGLSupport::getGLConfigAttrib(CFDictionaryRef glConfig, GLint attribute, GLint *value)
129    {
130        // TODO: DJR - implement
131        GLint status = 0;
132
133        return status;
134    }
135
136    CFDictionaryRef EAGLSupport::getGLConfigFromContext(EAGLESContext context)
137    {
138        // TODO: DJR - implement
139        CFDictionaryRef glConfig = 0;
140
141        return glConfig;
142    }
143
144    CFDictionaryRef EAGLSupport::getGLConfigFromDrawable(CAEAGLLayer *drawable,
145                                                    unsigned int *w, unsigned int *h)
146    {
147        // TODO: DJR - implement
148        CFDictionaryRef glConfig = 0;
149
150        return glConfig;
151    }
152
153    //------------------------------------------------------------------------
154    // A helper class for the implementation of selectFBConfig
155    //------------------------------------------------------------------------
156    class GLConfigAttribs
157    {
158        public:
159            GLConfigAttribs(const int* attribs)
160            {
161                for (int i = 0; attribs[2*i] != 0; i++)
162                {
163                    fields[attribs[2*i]] = attribs[2*i+1];
164                }
165            }
166
167            void load(EAGLSupport* const glSupport, CFDictionaryRef glConfig)
168            {
169                std::map<int,int>::iterator it;
170
171                for (it = fields.begin(); it != fields.end(); it++)
172                {
173                    it->second = 0;
174
175                    glSupport->getGLConfigAttrib(glConfig, it->first, &it->second);
176                }
177            }
178
179            bool operator>(GLConfigAttribs& alternative)
180            {
181                return false;
182            }
183
184            std::map<int,int> fields;
185    };
186
187    CFDictionaryRef EAGLSupport::selectGLConfig(const int* minAttribs, const int *maxAttribs)
188    {
189        // TODO: DJR - implement
190        CFDictionaryRef glConfig = 0;
191        int nConfigs = 0;//, config;
192
193        glConfig = chooseGLConfig(minAttribs, &nConfigs);
194
195        if (!nConfigs)
196        {
197            return 0;
198        }
199
200        return glConfig;
201    }
202
203    GLESPBuffer * EAGLSupport::createPBuffer( PixelComponentType format, size_t width, size_t height )
204	{
205		return new EAGLPBuffer(this, format, width, height);
206	}
207
208
209    RenderWindow * EAGLSupport::createWindow(bool autoCreateWindow,
210                                           GLESRenderSystem* renderSystem,
211                                           const String& windowTitle)
212    {
213        RenderWindow *window = 0;
214
215        if (autoCreateWindow)
216        {
217            ConfigOptionMap::iterator opt;
218            ConfigOptionMap::iterator end = mOptions.end();
219            NameValuePairList miscParams;
220
221            CGSize screenSize = [[UIScreen mainScreen] bounds].size;
222            bool fullscreen = false;
223            uint w = screenSize.width, h = screenSize.height;
224
225            if ((opt = mOptions.find("Full Screen")) != end)
226            {
227                fullscreen = (opt->second.currentValue == "Yes");
228            }
229
230            if ((opt = mOptions.find("Display Frequency")) != end)
231            {
232                miscParams["displayFrequency"] = opt->second.currentValue;
233            }
234
235            if ((opt = mOptions.find("Content Scaling Factor")) != end)
236            {
237                miscParams["contentScalingFactor"] = opt->second.currentValue;
238            }
239
240            if ((opt = mOptions.find("Video Mode")) != end)
241            {
242                String val = opt->second.currentValue;
243                String::size_type pos = val.find('x');
244
245                if (pos != String::npos)
246                {
247                    w = StringConverter::parseUnsignedInt(val.substr(0, pos));
248                    h = StringConverter::parseUnsignedInt(val.substr(pos + 1));
249                }
250            }
251
252            if ((opt = mOptions.find("FSAA")) != end)
253            {
254                miscParams["FSAA"] = opt->second.currentValue;
255            }
256
257            window = renderSystem->_createRenderWindow(windowTitle, w, h, fullscreen, &miscParams);
258        }
259
260        return window;
261    }
262
263    RenderWindow * EAGLSupport::newWindow(const String &name,
264                                        unsigned int width, unsigned int height,
265                                        bool fullScreen,
266                                        const NameValuePairList *miscParams)
267    {
268        EAGLWindow *window = OGRE_NEW EAGLWindow(this);
269        window->create(name, width, height, fullScreen, miscParams);
270
271        return window;
272    }
273
274    EAGLESContext * EAGLSupport::createNewContext(CFDictionaryRef &glconfig, CAEAGLLayer *drawable, EAGLSharegroup *group) const
275    {
276        EAGLESContext *context = new EAGLESContext(drawable, group);
277        if (context == NULL)
278        {
279            OGRE_EXCEPT(Exception::ERR_RENDERINGAPI_ERROR,
280                        "Fail to create new context",
281                        __FUNCTION__);
282            return context;
283        }
284
285        return context;
286    }
287
288    void * EAGLSupport::getProcAddress(const Ogre::String& name)
289    {
290        return NULL;
291    }
292
293    void EAGLSupport::start()
294    {
295    }
296
297    void EAGLSupport::stop()
298    {
299    }
300
301    bool EAGLSupport::interfaceOrientationIsSupported(NSString *orientation)
302    {
303        NSArray *supportedOrientations = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"UISupportedInterfaceOrientations"];
304
305        return [supportedOrientations containsObject:orientation];
306    }
307
308    bool EAGLSupport::portraitIsSupported()
309    {
310        NSArray *supportedOrientations = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"UISupportedInterfaceOrientations"];
311
312        return ([supportedOrientations containsObject:@"UIInterfaceOrientationPortrait"] ||
313                [supportedOrientations containsObject:@"UIInterfaceOrientationPortraitUpsideDown"]);
314    }
315}
316