1 /*
2 * OgreApplicationContext.cpp
3 *
4 * Created on: 18.05.2016
5 * Author: pavel
6 */
7
8 #include "OgreApplicationContext.h"
9
10 #include "OgreRoot.h"
11 #include "OgreGpuProgramManager.h"
12 #include "OgreConfigFile.h"
13 #include "OgreRenderWindow.h"
14 #include "OgreViewport.h"
15 #include "OgreOverlaySystem.h"
16 #include "OgreDataStream.h"
17 #include "OgreBitesConfigDialog.h"
18 #include "OgreWindowEventUtilities.h"
19
20 #include "OgreConfigPaths.h"
21
22 #if OGRE_PLATFORM == OGRE_PLATFORM_ANDROID
23 #include "OgreArchiveManager.h"
24 #include "OgreFileSystem.h"
25 #include "OgreZip.h"
26 #endif
27
28 #if OGRE_BITES_HAVE_SDL
29 #include <SDL.h>
30 #include <SDL_video.h>
31 #include <SDL_syswm.h>
32
33 #include "SDLInputMapping.h"
34 #endif
35
36 namespace OgreBites {
37
38 static const char* SHADER_CACHE_FILENAME = "cache.bin";
39
ApplicationContext(const Ogre::String & appName,bool)40 ApplicationContext::ApplicationContext(const Ogre::String& appName, bool)
41 #if (OGRE_THREAD_PROVIDER == 3) && (OGRE_NO_TBB_SCHEDULER == 1)
42 : mTaskScheduler(tbb::task_scheduler_init::deferred)
43 #endif
44 {
45 mAppName = appName;
46 mFSLayer = new Ogre::FileSystemLayer(mAppName);
47 mRoot = NULL;
48 mOverlaySystem = NULL;
49 mFirstRun = true;
50
51 #if OGRE_PLATFORM == OGRE_PLATFORM_ANDROID
52 mAAssetMgr = NULL;
53 mAConfig = NULL;
54 #endif
55
56 #ifdef OGRE_BUILD_COMPONENT_RTSHADERSYSTEM
57 mMaterialMgrListener = NULL;
58 mShaderGenerator = NULL;
59 #endif
60 }
61
~ApplicationContext()62 ApplicationContext::~ApplicationContext()
63 {
64 delete mFSLayer;
65 }
66
initApp()67 void ApplicationContext::initApp()
68 {
69 createRoot();
70 #if OGRE_PLATFORM == OGRE_PLATFORM_APPLE_IOS
71 if (!oneTimeConfig()) return;
72
73 if (!mFirstRun) mRoot->setRenderSystem(mRoot->getRenderSystemByName(mNextRenderer));
74
75 setup();
76
77 mRoot->saveConfig();
78
79 Ogre::Root::getSingleton().getRenderSystem()->_initRenderTargets();
80
81 // Clear event times
82 Ogre::Root::getSingleton().clearEventTimes();
83 #else
84
85 if (!oneTimeConfig()) return;
86
87 #if OGRE_PLATFORM != OGRE_PLATFORM_ANDROID
88 // if the context was reconfigured, set requested renderer
89 if (!mFirstRun) mRoot->setRenderSystem(mRoot->getRenderSystemByName(mNextRenderer));
90 #endif
91
92 setup();
93 #endif
94 }
95
closeApp()96 void ApplicationContext::closeApp()
97 {
98 shutdown();
99 if (mRoot)
100 {
101 #if OGRE_PLATFORM != OGRE_PLATFORM_ANDROID
102 mRoot->saveConfig();
103 #endif
104 OGRE_DELETE mRoot;
105 mRoot = NULL;
106 }
107
108 #ifdef OGRE_STATIC_LIB
109 mStaticPluginLoader.unload();
110 #endif
111
112 #if (OGRE_THREAD_PROVIDER == 3) && (OGRE_NO_TBB_SCHEDULER == 1)
113 if (mTaskScheduler.is_active())
114 mTaskScheduler.terminate();
115 #endif
116 }
117
initialiseRTShaderSystem()118 bool ApplicationContext::initialiseRTShaderSystem()
119 {
120 #ifdef OGRE_BUILD_COMPONENT_RTSHADERSYSTEM
121 if (Ogre::RTShader::ShaderGenerator::initialize())
122 {
123 mShaderGenerator = Ogre::RTShader::ShaderGenerator::getSingletonPtr();
124
125 #if OGRE_PLATFORM != OGRE_PLATFORM_WINRT
126 // Core shader libs not found -> shader generating will fail.
127 if (mRTShaderLibPath.empty())
128 return false;
129 #endif
130
131 // Create and register the material manager listener if it doesn't exist yet.
132 if (!mMaterialMgrListener) {
133 mMaterialMgrListener = new SGTechniqueResolverListener(mShaderGenerator);
134 Ogre::MaterialManager::getSingleton().addListener(mMaterialMgrListener);
135 }
136 }
137
138 return true;
139 #else
140 return false;
141 #endif
142 }
143
setRTSSWriteShadersToDisk(bool write)144 void ApplicationContext::setRTSSWriteShadersToDisk(bool write)
145 {
146 #ifdef OGRE_BUILD_COMPONENT_RTSHADERSYSTEM
147 if(!write) {
148 mShaderGenerator->setShaderCachePath("");
149 return;
150 }
151
152 // Set shader cache path.
153 #if OGRE_PLATFORM == OGRE_PLATFORM_APPLE_IOS
154 mShaderGenerator->setShaderCachePath(mFSLayer->getWritablePath(""));
155 #elif OGRE_PLATFORM == OGRE_PLATFORM_APPLE
156 mShaderGenerator->setShaderCachePath(mFSLayer->getWritablePath("org.ogre3d.RTShaderCache/"));
157 #else
158 mShaderGenerator->setShaderCachePath(mRTShaderLibPath+"/cache/");
159 #endif
160 #endif
161 }
162
destroyRTShaderSystem()163 void ApplicationContext::destroyRTShaderSystem()
164 {
165 #ifdef OGRE_BUILD_COMPONENT_RTSHADERSYSTEM
166 //mShaderGenerator->removeAllShaderBasedTechniques();
167 //mShaderGenerator->flushShaderCache();
168
169 // Restore default scheme.
170 Ogre::MaterialManager::getSingleton().setActiveScheme(Ogre::MaterialManager::DEFAULT_SCHEME_NAME);
171
172 // Unregister the material manager listener.
173 if (mMaterialMgrListener != NULL)
174 {
175 Ogre::MaterialManager::getSingleton().removeListener(mMaterialMgrListener);
176 delete mMaterialMgrListener;
177 mMaterialMgrListener = NULL;
178 }
179
180 // Destroy RTShader system.
181 if (mShaderGenerator != NULL)
182 {
183 Ogre::RTShader::ShaderGenerator::destroy();
184 mShaderGenerator = NULL;
185 }
186 #endif
187 }
188
setup()189 void ApplicationContext::setup()
190 {
191 mRoot->initialise(false);
192 createWindow(mAppName);
193
194 locateResources();
195 initialiseRTShaderSystem();
196 loadResources();
197
198 // adds context as listener to process context-level (above the sample level) events
199 mRoot->addFrameListener(this);
200 }
201
createRoot()202 void ApplicationContext::createRoot()
203 {
204 #if (OGRE_THREAD_PROVIDER == 3) && (OGRE_NO_TBB_SCHEDULER == 1)
205 mTaskScheduler.initialize(OGRE_THREAD_HARDWARE_CONCURRENCY);
206 #endif
207
208 #if OGRE_PLATFORM == OGRE_PLATFORM_ANDROID || OGRE_PLATFORM == OGRE_PLATFORM_EMSCRIPTEN
209 mRoot = OGRE_NEW Ogre::Root("");
210 #else
211 Ogre::String pluginsPath;
212 # ifndef OGRE_STATIC_LIB
213 pluginsPath = mFSLayer->getConfigFilePath("plugins.cfg");
214
215 if (!Ogre::FileSystemLayer::fileExists(pluginsPath))
216 {
217 pluginsPath = Ogre::FileSystemLayer::resolveBundlePath(OGRE_CONFIG_DIR "/plugins" OGRE_BUILD_SUFFIX ".cfg");
218 }
219 # endif
220
221 mRoot = OGRE_NEW Ogre::Root(pluginsPath, mFSLayer->getWritablePath("ogre.cfg"),
222 mFSLayer->getWritablePath("ogre.log"));
223 #endif
224
225 #ifdef OGRE_STATIC_LIB
226 mStaticPluginLoader.load();
227 #endif
228 mOverlaySystem = OGRE_NEW Ogre::OverlaySystem();
229 }
230
oneTimeConfig()231 bool ApplicationContext::oneTimeConfig()
232 {
233 #if OGRE_PLATFORM == OGRE_PLATFORM_ANDROID || OGRE_PLATFORM == OGRE_PLATFORM_EMSCRIPTEN
234 mRoot->setRenderSystem(mRoot->getAvailableRenderers().at(0));
235 #else
236 if (!mRoot->restoreConfig()) {
237 return mRoot->showConfigDialog(OgreBites::getNativeConfigDialog());
238 }
239 #endif
240 return true;
241 }
242
createDummyScene()243 void ApplicationContext::createDummyScene()
244 {
245 mWindows[0].render->removeAllViewports();
246 Ogre::SceneManager* sm = mRoot->createSceneManager("DefaultSceneManager", "DummyScene");
247 sm->addRenderQueueListener(mOverlaySystem);
248 Ogre::Camera* cam = sm->createCamera("DummyCamera");
249 mWindows[0].render->addViewport(cam);
250 #ifdef OGRE_BUILD_COMPONENT_RTSHADERSYSTEM
251 // Initialize shader generator.
252 // Must be before resource loading in order to allow parsing extended material attributes.
253 if (!initialiseRTShaderSystem())
254 {
255 OGRE_EXCEPT(Ogre::Exception::ERR_FILE_NOT_FOUND,
256 "Shader Generator Initialization failed - Core shader libs path not found",
257 "ApplicationContext::createDummyScene");
258 }
259
260 mShaderGenerator->addSceneManager(sm);
261 #endif // OGRE_BUILD_COMPONENT_RTSHADERSYSTEM
262 }
263
destroyDummyScene()264 void ApplicationContext::destroyDummyScene()
265 {
266 if(!mRoot->hasSceneManager("DummyScene"))
267 return;
268
269 Ogre::SceneManager* dummyScene = mRoot->getSceneManager("DummyScene");
270 #ifdef OGRE_BUILD_COMPONENT_RTSHADERSYSTEM
271 mShaderGenerator->removeSceneManager(dummyScene);
272 #endif
273 dummyScene->removeRenderQueueListener(mOverlaySystem);
274 mWindows[0].render->removeAllViewports();
275 mRoot->destroySceneManager(dummyScene);
276 }
277
enableShaderCache() const278 void ApplicationContext::enableShaderCache() const
279 {
280 Ogre::GpuProgramManager::getSingleton().setSaveMicrocodesToCache(true);
281
282 // Load for a package version of the shaders.
283 Ogre::String path = mFSLayer->getWritablePath(SHADER_CACHE_FILENAME);
284 std::ifstream inFile(path.c_str(), std::ios::binary);
285 if (!inFile.is_open())
286 {
287 Ogre::LogManager::getSingleton().logWarning("Could not open '"+path+"'");
288 return;
289 }
290 Ogre::LogManager::getSingleton().logMessage("Loading shader cache from '"+path+"'");
291 Ogre::DataStreamPtr istream(new Ogre::FileStreamDataStream(path, &inFile, false));
292 Ogre::GpuProgramManager::getSingleton().loadMicrocodeCache(istream);
293 }
294
addInputListener(NativeWindowType * win,InputListener * lis)295 void ApplicationContext::addInputListener(NativeWindowType* win, InputListener* lis)
296 {
297 uint32_t id = 0;
298 #if OGRE_BITES_HAVE_SDL
299 id = SDL_GetWindowID(win);
300 #endif
301 mInputListeners.insert(std::make_pair(id, lis));
302 }
303
304
removeInputListener(NativeWindowType * win,InputListener * lis)305 void ApplicationContext::removeInputListener(NativeWindowType* win, InputListener* lis)
306 {
307 uint32_t id = 0;
308 #if OGRE_BITES_HAVE_SDL
309 id = SDL_GetWindowID(win);
310 #endif
311 mInputListeners.erase(std::make_pair(id, lis));
312 }
313
frameRenderingQueued(const Ogre::FrameEvent & evt)314 bool ApplicationContext::frameRenderingQueued(const Ogre::FrameEvent& evt)
315 {
316 for(InputListenerList::iterator it = mInputListeners.begin();
317 it != mInputListeners.end(); ++it) {
318 it->second->frameRendered(evt);
319 }
320
321 return true;
322 }
323
createWindow(const Ogre::String & name,Ogre::uint32 w,Ogre::uint32 h,Ogre::NameValuePairList miscParams)324 NativeWindowPair ApplicationContext::createWindow(const Ogre::String& name, Ogre::uint32 w, Ogre::uint32 h, Ogre::NameValuePairList miscParams)
325 {
326 NativeWindowPair ret = {NULL, NULL};
327 #if OGRE_PLATFORM == OGRE_PLATFORM_ANDROID
328 miscParams["externalWindowHandle"] = Ogre::StringConverter::toString(reinterpret_cast<size_t>(mWindows[0].native));
329 miscParams["androidConfig"] = Ogre::StringConverter::toString(reinterpret_cast<size_t>(mAConfig));
330 miscParams["preserveContext"] = "true"; //Optionally preserve the gl context, prevents reloading all resources, this is false by default
331
332 mWindows[0].render = Ogre::Root::getSingleton().createRenderWindow(name, 0, 0, false, &miscParams);
333 ret = mWindows[0];
334 #else
335 Ogre::ConfigOptionMap ropts = mRoot->getRenderSystem()->getConfigOptions();
336
337 if(w == 0 && h == 0)
338 {
339 std::istringstream mode(ropts["Video Mode"].currentValue);
340 Ogre::String token;
341 mode >> w; // width
342 mode >> token; // 'x' as seperator between width and height
343 mode >> h; // height
344 }
345
346 if(miscParams.empty())
347 {
348 miscParams["FSAA"] = ropts["FSAA"].currentValue;
349 miscParams["vsync"] = ropts["VSync"].currentValue;
350 miscParams["gamma"] = ropts["sRGB Gamma Conversion"].currentValue;
351 }
352
353 if(!mWindows.empty()) {
354 // additional windows should reuse the context
355 miscParams["currentGLContext"] = "true";
356 }
357
358
359
360 #if OGRE_BITES_HAVE_SDL
361 if(!SDL_WasInit(SDL_INIT_VIDEO)) {
362 SDL_InitSubSystem(SDL_INIT_VIDEO);
363 }
364
365 Uint32 flags = SDL_WINDOW_RESIZABLE;
366
367 if(ropts["Full Screen"].currentValue == "Yes"){
368 flags = SDL_WINDOW_FULLSCREEN;
369 } else {
370 flags = SDL_WINDOW_RESIZABLE;
371 }
372
373 ret.native = SDL_CreateWindow(name.c_str(),
374 SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, w, h, flags);
375
376 #if OGRE_PLATFORM == OGRE_PLATFORM_EMSCRIPTEN
377 SDL_GL_CreateContext(ret.native);
378 miscParams["currentGLContext"] = "true";
379 #else
380 SDL_SysWMinfo wmInfo;
381 SDL_VERSION(&wmInfo.version);
382 SDL_GetWindowWMInfo(ret.native, &wmInfo);
383 #endif
384
385 #if OGRE_PLATFORM == OGRE_PLATFORM_LINUX
386 miscParams["parentWindowHandle"] = Ogre::StringConverter::toString(size_t(wmInfo.info.x11.window));
387 #elif OGRE_PLATFORM == OGRE_PLATFORM_WIN32
388 miscParams["externalWindowHandle"] = Ogre::StringConverter::toString(size_t(wmInfo.info.win.window));
389 #elif OGRE_PLATFORM == OGRE_PLATFORM_APPLE
390 assert(wmInfo.subsystem == SDL_SYSWM_COCOA);
391 miscParams["externalWindowHandle"] = Ogre::StringConverter::toString(size_t(wmInfo.info.cocoa.window));
392 #endif
393 #endif
394 ret.render = mRoot->createRenderWindow(name, w, h, false, &miscParams);
395 mWindows.push_back(ret);
396 #endif
397
398 #if OGRE_PLATFORM != OGRE_PLATFORM_ANDROID && !OGRE_BITES_HAVE_SDL
399 WindowEventUtilities::_addRenderWindow(ret.render);
400 #endif
401
402 return ret;
403 }
404
405 #if OGRE_PLATFORM == OGRE_PLATFORM_ANDROID
initAppForAndroid(AAssetManager * assetMgr,ANativeWindow * window)406 void ApplicationContext::initAppForAndroid(AAssetManager* assetMgr, ANativeWindow* window)
407 {
408 mAConfig = AConfiguration_new();
409 AConfiguration_fromAssetManager(mAConfig, assetMgr);
410 mAAssetMgr = assetMgr;
411
412 mWindows.resize(1);
413 mWindows[0].native = window;
414
415 initApp();
416 }
417
openAPKFile(const Ogre::String & fileName)418 Ogre::DataStreamPtr ApplicationContext::openAPKFile(const Ogre::String& fileName)
419 {
420 Ogre::Archive* apk = Ogre::ArchiveManager::getSingleton().load("", "APKFileSystem", true);
421 return apk->open(fileName);
422 }
423
_fireInputEventAndroid(AInputEvent * event,int wheel)424 void ApplicationContext::_fireInputEventAndroid(AInputEvent* event, int wheel) {
425 Event evt = {0};
426
427 static TouchFingerEvent lastTouch = {0};
428
429 if(wheel) {
430 evt.type = MOUSEWHEEL;
431 evt.wheel.y = wheel;
432 _fireInputEvent(evt, 0);
433 lastTouch.fingerId = -1; // prevent move-jump after pinch is over
434 return;
435 }
436
437 if (AInputEvent_getType(event) == AINPUT_EVENT_TYPE_MOTION) {
438 int32_t action = AMOTION_EVENT_ACTION_MASK & AMotionEvent_getAction(event);
439
440 switch (action) {
441 case AMOTION_EVENT_ACTION_DOWN:
442 evt.type = FINGERDOWN;
443 break;
444 case AMOTION_EVENT_ACTION_UP:
445 evt.type = FINGERUP;
446 break;
447 case AMOTION_EVENT_ACTION_MOVE:
448 evt.type = FINGERMOTION;
449 break;
450 default:
451 return;
452 }
453
454 Ogre::RenderWindow* win = getRenderWindow();
455
456 evt.tfinger.fingerId = AMotionEvent_getPointerId(event, 0);
457 evt.tfinger.x = AMotionEvent_getRawX(event, 0) / win->getWidth();
458 evt.tfinger.y = AMotionEvent_getRawY(event, 0) / win->getHeight();
459
460 if(evt.type == FINGERMOTION) {
461 if(evt.tfinger.fingerId != lastTouch.fingerId)
462 return; // wrong finger
463
464 evt.tfinger.dx = evt.tfinger.x - lastTouch.x;
465 evt.tfinger.dy = evt.tfinger.y - lastTouch.y;
466 }
467
468 lastTouch = evt.tfinger;
469 } else {
470 if(AKeyEvent_getKeyCode(event) != AKEYCODE_BACK)
471 return;
472
473 evt.type = AKeyEvent_getAction(event) == AKEY_EVENT_ACTION_DOWN ? KEYDOWN : KEYUP;
474 evt.key.keysym.sym = SDLK_ESCAPE;
475 }
476
477 _fireInputEvent(evt, 0);
478 }
479 #endif
480
_fireInputEvent(const Event & event,uint32_t windowID) const481 void ApplicationContext::_fireInputEvent(const Event& event, uint32_t windowID) const
482 {
483 for(InputListenerList::iterator it = mInputListeners.begin();
484 it != mInputListeners.end(); ++it)
485 {
486 if(it->first != windowID) continue;
487
488 InputListener& l = *it->second;
489
490 switch (event.type)
491 {
492 case KEYDOWN:
493 l.keyPressed(event.key);
494 break;
495 case KEYUP:
496 l.keyReleased(event.key);
497 break;
498 case MOUSEBUTTONDOWN:
499 l.mousePressed(event.button);
500 break;
501 case MOUSEBUTTONUP:
502 l.mouseReleased(event.button);
503 break;
504 case MOUSEWHEEL:
505 l.mouseWheelRolled(event.wheel);
506 break;
507 case MOUSEMOTION:
508 l.mouseMoved(event.motion);
509 break;
510 case FINGERDOWN:
511 // for finger down we have to move the pointer first
512 l.touchMoved(event.tfinger);
513 l.touchPressed(event.tfinger);
514 break;
515 case FINGERUP:
516 l.touchReleased(event.tfinger);
517 break;
518 case FINGERMOTION:
519 l.touchMoved(event.tfinger);
520 break;
521 }
522 }
523 }
524
setWindowGrab(NativeWindowType * win,bool _grab)525 void ApplicationContext::setWindowGrab(NativeWindowType* win, bool _grab)
526 {
527 #if OGRE_BITES_HAVE_SDL
528 SDL_bool grab = SDL_bool(_grab);
529
530 SDL_SetWindowGrab(win, grab);
531 SDL_SetRelativeMouseMode(grab);
532 #endif
533 }
534
getDefaultMediaDir()535 Ogre::String ApplicationContext::getDefaultMediaDir()
536 {
537 return Ogre::FileSystemLayer::resolveBundlePath(OGRE_MEDIA_DIR);
538 }
539
locateResources()540 void ApplicationContext::locateResources()
541 {
542 // load resource paths from config file
543 Ogre::ConfigFile cf;
544 #if OGRE_PLATFORM == OGRE_PLATFORM_ANDROID
545 Ogre::ArchiveManager::getSingleton().addArchiveFactory( new Ogre::APKFileSystemArchiveFactory(mAAssetMgr) );
546 Ogre::ArchiveManager::getSingleton().addArchiveFactory( new Ogre::APKZipArchiveFactory(mAAssetMgr) );
547 Ogre::Archive* apk = Ogre::ArchiveManager::getSingleton().load("", "APKFileSystem", true);
548 cf.load(apk->open(mFSLayer->getConfigFilePath("resources.cfg")));
549 #else
550 Ogre::String resourcesPath = mFSLayer->getConfigFilePath("resources.cfg");
551 if (Ogre::FileSystemLayer::fileExists(resourcesPath) || OGRE_PLATFORM == OGRE_PLATFORM_EMSCRIPTEN)
552 {
553 cf.load(resourcesPath);
554 }
555 else
556 {
557 Ogre::ResourceGroupManager::getSingleton().addResourceLocation(
558 getDefaultMediaDir(), "FileSystem",
559 Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME);
560 }
561
562 #endif
563
564 Ogre::String sec, type, arch;
565 // go through all specified resource groups
566 Ogre::ConfigFile::SettingsBySection_::const_iterator seci;
567 for(seci = cf.getSettingsBySection().begin(); seci != cf.getSettingsBySection().end(); ++seci) {
568 sec = seci->first;
569 const Ogre::ConfigFile::SettingsMultiMap& settings = seci->second;
570 Ogre::ConfigFile::SettingsMultiMap::const_iterator i;
571
572 // go through all resource paths
573 for (i = settings.begin(); i != settings.end(); i++)
574 {
575 type = i->first;
576 arch = Ogre::FileSystemLayer::resolveBundlePath(i->second);
577
578 Ogre::ResourceGroupManager::getSingleton().addResourceLocation(arch, type, sec);
579 }
580 }
581
582 sec = Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME;
583 const Ogre::ResourceGroupManager::LocationList genLocs = Ogre::ResourceGroupManager::getSingleton().getResourceLocationList(sec);
584
585 OgreAssert(!genLocs.empty(), ("Resource Group '"+sec+"' must contain at least one entry").c_str());
586
587 arch = genLocs.front().archive->getName();
588
589 #if OGRE_PLATFORM == OGRE_PLATFORM_APPLE
590 arch = Ogre::FileSystemLayer::resolveBundlePath("Contents/Resources/Media");
591 #elif OGRE_PLATFORM == OGRE_PLATFORM_APPLE_IOS
592 arch = Ogre::FileSystemLayer::resolveBundlePath("Media");
593 #else
594 arch = Ogre::StringUtil::replaceAll(arch, "Media/../../Tests/Media", "");
595 arch = Ogre::StringUtil::replaceAll(arch, "media/../../Tests/Media", "");
596 #endif
597 type = genLocs.front().archive->getType();
598
599 bool hasCgPlugin = false;
600 const Ogre::Root::PluginInstanceList& plugins = getRoot()->getInstalledPlugins();
601 for(size_t i = 0; i < plugins.size(); i++)
602 {
603 if(plugins[i]->getName() == "Cg Program Manager")
604 {
605 hasCgPlugin = true;
606 break;
607 }
608 }
609
610 bool use_HLSL_Cg_shared = hasCgPlugin || Ogre::GpuProgramManager::getSingleton().isSyntaxSupported("hlsl");
611
612 // Add locations for supported shader languages
613 if(Ogre::GpuProgramManager::getSingleton().isSyntaxSupported("glsles"))
614 {
615 Ogre::ResourceGroupManager::getSingleton().addResourceLocation(arch + "/materials/programs/GLSLES", type, sec);
616 }
617 else if(Ogre::GpuProgramManager::getSingleton().isSyntaxSupported("glsl"))
618 {
619 Ogre::ResourceGroupManager::getSingleton().addResourceLocation(arch + "/materials/programs/GLSL120", type, sec);
620
621 if(Ogre::GpuProgramManager::getSingleton().isSyntaxSupported("glsl150"))
622 {
623 Ogre::ResourceGroupManager::getSingleton().addResourceLocation(arch + "/materials/programs/GLSL150", type, sec);
624 }
625 else
626 {
627 Ogre::ResourceGroupManager::getSingleton().addResourceLocation(arch + "/materials/programs/GLSL", type, sec);
628 }
629
630 if(Ogre::GpuProgramManager::getSingleton().isSyntaxSupported("glsl400"))
631 {
632 Ogre::ResourceGroupManager::getSingleton().addResourceLocation(arch + "/materials/programs/GLSL400", type, sec);
633 }
634 }
635 else if(Ogre::GpuProgramManager::getSingleton().isSyntaxSupported("hlsl"))
636 {
637 Ogre::ResourceGroupManager::getSingleton().addResourceLocation(arch + "/materials/programs/HLSL", type, sec);
638 }
639
640 if(hasCgPlugin)
641 Ogre::ResourceGroupManager::getSingleton().addResourceLocation(arch + "/materials/programs/Cg", type, sec);
642 if (use_HLSL_Cg_shared)
643 Ogre::ResourceGroupManager::getSingleton().addResourceLocation(arch + "/materials/programs/HLSL_Cg", type, sec);
644
645 #ifdef OGRE_BUILD_COMPONENT_RTSHADERSYSTEM
646 mRTShaderLibPath = arch + "/RTShaderLib";
647 Ogre::ResourceGroupManager::getSingleton().addResourceLocation(mRTShaderLibPath + "/materials", type, sec);
648
649 if(Ogre::GpuProgramManager::getSingleton().isSyntaxSupported("glsles"))
650 {
651 Ogre::ResourceGroupManager::getSingleton().addResourceLocation(mRTShaderLibPath + "/GLSL", type, sec);
652 Ogre::ResourceGroupManager::getSingleton().addResourceLocation(mRTShaderLibPath + "/GLSLES", type, sec);
653 }
654 else if(Ogre::GpuProgramManager::getSingleton().isSyntaxSupported("glsl"))
655 {
656 Ogre::ResourceGroupManager::getSingleton().addResourceLocation(mRTShaderLibPath + "/GLSL", type, sec);
657 }
658 else if(Ogre::GpuProgramManager::getSingleton().isSyntaxSupported("hlsl"))
659 {
660 Ogre::ResourceGroupManager::getSingleton().addResourceLocation(mRTShaderLibPath + "/HLSL", type, sec);
661 }
662
663 if(hasCgPlugin)
664 Ogre::ResourceGroupManager::getSingleton().addResourceLocation(mRTShaderLibPath + "/Cg", type, sec);
665 if (use_HLSL_Cg_shared)
666 Ogre::ResourceGroupManager::getSingleton().addResourceLocation(mRTShaderLibPath + "/HLSL_Cg", type, sec);
667
668 #endif /* OGRE_BUILD_COMPONENT_RTSHADERSYSTEM */
669 }
670
loadResources()671 void ApplicationContext::loadResources()
672 {
673 Ogre::ResourceGroupManager::getSingleton().initialiseAllResourceGroups();
674 }
675
reconfigure(const Ogre::String & renderer,Ogre::NameValuePairList & options)676 void ApplicationContext::reconfigure(const Ogre::String &renderer, Ogre::NameValuePairList &options)
677 {
678 mNextRenderer = renderer;
679 Ogre::RenderSystem* rs = mRoot->getRenderSystemByName(renderer);
680
681 // set all given render system options
682 for (Ogre::NameValuePairList::iterator it = options.begin(); it != options.end(); it++)
683 {
684 rs->setConfigOption(it->first, it->second);
685
686 #if OGRE_PLATFORM == OGRE_PLATFORM_APPLE_IOS
687 // Change the viewport orientation on the fly if requested
688 if(it->first == "Orientation")
689 {
690 Ogre::RenderWindow* win = getRenderWindow();
691
692 if (it->second == "Landscape Left")
693 win->getViewport(0)->setOrientationMode(Ogre::OR_LANDSCAPELEFT, true);
694 else if (it->second == "Landscape Right")
695 win->getViewport(0)->setOrientationMode(Ogre::OR_LANDSCAPERIGHT, true);
696 else if (it->second == "Portrait")
697 win->getViewport(0)->setOrientationMode(Ogre::OR_PORTRAIT, true);
698 }
699 #endif
700 }
701
702 #if OGRE_PLATFORM == OGRE_PLATFORM_APPLE_IOS
703 // Need to save the config on iOS to make sure that changes are kept on disk
704 mRoot->saveConfig();
705 #endif
706 mRoot->queueEndRendering(); // break from render loop
707 }
708
shutdown()709 void ApplicationContext::shutdown()
710 {
711 const auto& gpuMgr = Ogre::GpuProgramManager::getSingleton();
712 if (gpuMgr.getSaveMicrocodesToCache() && gpuMgr.isCacheDirty())
713 {
714 Ogre::String path = mFSLayer->getWritablePath(SHADER_CACHE_FILENAME);
715 std::fstream outFile(path.c_str(), std::ios::out | std::ios::binary);
716
717 if (outFile.is_open())
718 {
719 Ogre::LogManager::getSingleton().logMessage("Writing shader cache to "+path);
720 Ogre::DataStreamPtr ostream(new Ogre::FileStreamDataStream(path, &outFile, false));
721 gpuMgr.saveMicrocodeCache(ostream);
722 }
723 else
724 Ogre::LogManager::getSingleton().logWarning("Cannot open shader cache for writing "+path);
725 }
726
727 #ifdef OGRE_BUILD_COMPONENT_RTSHADERSYSTEM
728 // Destroy the RT Shader System.
729 destroyRTShaderSystem();
730 #endif
731
732 for(WindowList::iterator it = mWindows.begin(); it != mWindows.end(); ++it)
733 {
734 #if !OGRE_BITES_HAVE_SDL
735 // remove window event listener before destroying it
736 WindowEventUtilities::_removeRenderWindow(it->render);
737 #endif
738 mRoot->destroyRenderTarget(it->render);
739 }
740
741 if (mOverlaySystem)
742 {
743 OGRE_DELETE mOverlaySystem;
744 }
745
746 #if OGRE_BITES_HAVE_SDL
747 for(WindowList::iterator it = mWindows.begin(); it != mWindows.end(); ++it)
748 {
749 if(it->native)
750 SDL_DestroyWindow(it->native);
751 }
752 if(!mWindows.empty()) {
753 SDL_QuitSubSystem(SDL_INIT_VIDEO);
754 }
755 #endif
756
757 mWindows.clear();
758 mInputListeners.clear();
759
760 #if OGRE_PLATFORM == OGRE_PLATFORM_ANDROID
761 AConfiguration_delete(mAConfig);
762 #endif
763 }
764
pollEvents()765 void ApplicationContext::pollEvents()
766 {
767 #if OGRE_BITES_HAVE_SDL
768 if(mWindows.empty())
769 {
770 // SDL events not initialized
771 return;
772 }
773
774 SDL_Event event;
775 while (SDL_PollEvent(&event))
776 {
777 switch (event.type)
778 {
779 case SDL_QUIT:
780 mRoot->queueEndRendering();
781 break;
782 case SDL_WINDOWEVENT:
783 if(event.window.event != SDL_WINDOWEVENT_RESIZED)
784 continue;
785
786 for(WindowList::iterator it = mWindows.begin(); it != mWindows.end(); ++it)
787 {
788 if(event.window.windowID != SDL_GetWindowID(it->native))
789 continue;
790
791 Ogre::RenderWindow* win = it->render;
792 win->windowMovedOrResized();
793 windowResized(win);
794 }
795 break;
796 default:
797 _fireInputEvent(convert(event), event.window.windowID);
798 break;
799 }
800 }
801
802 # if OGRE_PLATFORM == OGRE_PLATFORM_APPLE
803 // hacky workaround for black window on OSX
804 for(const auto& win : mWindows)
805 {
806 SDL_SetWindowSize(win.native, win.render->getWidth(), win.render->getHeight());
807 win.render->windowMovedOrResized();
808 }
809 # endif
810 #elif OGRE_PLATFORM == OGRE_PLATFORM_ANDROID
811 for(WindowList::iterator it = mWindows.begin(); it != mWindows.end(); ++it)
812 {
813 Ogre::RenderWindow* win = it->render;
814 win->windowMovedOrResized();
815 windowResized(win);
816 }
817 #else
818 // just avoid "window not responding"
819 WindowEventUtilities::messagePump();
820 #endif
821 }
822
823 }
824