CContext.cpp 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236
  1. #include <iostream>
  2. #include <stdexcept>
  3. #include <utility>
  4. #include <X11/Xlib.h>
  5. #include <X11/extensions/Xrandr.h>
  6. #include "WallpaperEngine/Irrlicht/CImageLoaderTEX.h"
  7. #include "WallpaperEngine/Irrlicht/CPkgReader.h"
  8. #include "WallpaperEngine/Render/Shaders/Variables/CShaderVariableFloatPointer.h"
  9. #include "WallpaperEngine/Render/Shaders/Variables/CShaderVariableVector2Pointer.h"
  10. #include "CContext.h"
  11. using namespace WallpaperEngine;
  12. using namespace WallpaperEngine::Irrlicht;
  13. CContext::CContext (std::vector<std::string> screens, bool isRootWindow) :
  14. m_screens (std::move(screens)),
  15. m_isRootWindow (isRootWindow)
  16. {
  17. }
  18. void CContext::setDevice (irr::IrrlichtDevice* device)
  19. {
  20. this->m_device = device;
  21. }
  22. void CContext::initializeContext ()
  23. {
  24. irr::SIrrlichtCreationParameters irrlichtCreationParameters;
  25. // initialize event receiver first
  26. this->m_eventReceiver = new CEventReceiver ();
  27. // prepare basic configuration for irrlicht
  28. irrlichtCreationParameters.AntiAlias = 8;
  29. irrlichtCreationParameters.Bits = 16;
  30. // _irr_params.DeviceType = Irrlicht::EIDT_X11;
  31. irrlichtCreationParameters.DriverType = irr::video::EDT_OPENGL;
  32. irrlichtCreationParameters.Doublebuffer = false;
  33. irrlichtCreationParameters.EventReceiver = this->m_eventReceiver;
  34. irrlichtCreationParameters.Fullscreen = false;
  35. irrlichtCreationParameters.HandleSRGB = false;
  36. irrlichtCreationParameters.IgnoreInput = false;
  37. irrlichtCreationParameters.Stencilbuffer = true;
  38. irrlichtCreationParameters.UsePerformanceTimer = false;
  39. irrlichtCreationParameters.Vsync = false;
  40. irrlichtCreationParameters.WithAlphaChannel = false;
  41. irrlichtCreationParameters.ZBufferBits = 24;
  42. irrlichtCreationParameters.LoggingLevel = irr::ELL_DEBUG;
  43. this->initializeViewports (irrlichtCreationParameters);
  44. this->setDevice (irr::createDeviceEx (irrlichtCreationParameters));
  45. if (this->getDevice () == nullptr)
  46. {
  47. throw std::runtime_error ("Cannot create irrlicht device");
  48. }
  49. this->getDevice ()->setWindowCaption (L"Test game");
  50. // check for ps and vs support
  51. if (
  52. this->getDevice ()->getVideoDriver()->queryFeature (irr::video::EVDF_PIXEL_SHADER_2_0) == false &&
  53. this->getDevice ()->getVideoDriver()->queryFeature (irr::video::EVDF_ARB_FRAGMENT_PROGRAM_1) == false)
  54. {
  55. throw std::runtime_error ("Pixel Shader 2.0 not supported by your video driver/hardware");
  56. }
  57. if (
  58. this->getDevice ()->getVideoDriver()->queryFeature (irr::video::EVDF_VERTEX_SHADER_2_0) == false &&
  59. this->getDevice ()->getVideoDriver()->queryFeature (irr::video::EVDF_ARB_VERTEX_PROGRAM_1) == false)
  60. {
  61. throw std::runtime_error ("Vertex Shader 2.0 not supported by your video driver/hardware");
  62. }
  63. if (this->getDevice ()->getVideoDriver ()->queryFeature (irr::video::EVDF_RENDER_TO_TARGET) == false)
  64. {
  65. throw std::runtime_error ("Render to texture not supported by your video driver/hardware");
  66. }
  67. // load the assets from wallpaper engine
  68. this->getDevice ()->getFileSystem ()->addFileArchive ("assets.zip", true, false);
  69. // register custom loaders
  70. this->getDevice ()->getVideoDriver()->addExternalImageLoader (
  71. new WallpaperEngine::Irrlicht::CImageLoaderTex (this)
  72. );
  73. this->getDevice ()->getFileSystem ()->addArchiveLoader (
  74. new WallpaperEngine::Irrlicht::CArchiveLoaderPkg (this)
  75. );
  76. // register time shader variable
  77. this->insertShaderVariable (
  78. new Render::Shaders::Variables::CShaderVariableFloatPointer (&this->m_time, "g_Time")
  79. );
  80. // register normalized uv position for mouse
  81. this->insertShaderVariable (
  82. new Render::Shaders::Variables::CShaderVariableVector2Pointer (&this->m_pointerPosition, "g_PointerPosition")
  83. );
  84. }
  85. void CContext::initializeViewports (irr::SIrrlichtCreationParameters &irrlichtCreationParameters)
  86. {
  87. if (this->m_isRootWindow == false || this->m_screens.empty () == true)
  88. return;
  89. Display* display = XOpenDisplay (nullptr);
  90. int xrandr_result, xrandr_error;
  91. if (!XRRQueryExtension (display, &xrandr_result, &xrandr_error))
  92. {
  93. std::cerr << "XRandr is not present, cannot detect specified screens, running in window mode" << std::endl;
  94. return;
  95. }
  96. XRRScreenResources* screenResources = XRRGetScreenResources (display, DefaultRootWindow (display));
  97. // there are some situations where xrandr returns null (like screen not using the extension)
  98. if (screenResources == nullptr)
  99. return;
  100. for (int i = 0; i < screenResources->noutput; i ++)
  101. {
  102. XRROutputInfo* info = XRRGetOutputInfo (display, screenResources, screenResources->outputs [i]);
  103. // there are some situations where xrandr returns null (like screen not using the extension)
  104. if (info == nullptr)
  105. continue;
  106. auto cur = this->m_screens.begin ();
  107. auto end = this->m_screens.end ();
  108. for (; cur != end; cur ++)
  109. {
  110. if (info->connection == RR_Connected && strcmp (info->name, (*cur).c_str ()) == 0)
  111. {
  112. XRRCrtcInfo* crtc = XRRGetCrtcInfo (display, screenResources, info->crtc);
  113. std::cout << "Found requested screen: " << info->name << " -> " << crtc->x << "x" << crtc->y << ":" << crtc->width << "x" << crtc->height << std::endl;
  114. irr::core::rect<irr::s32> viewport;
  115. viewport.UpperLeftCorner.X = crtc->x;
  116. viewport.UpperLeftCorner.Y = crtc->y;
  117. viewport.LowerRightCorner.X = crtc->x + crtc->width;
  118. viewport.LowerRightCorner.Y = crtc->y + crtc->height;
  119. this->m_viewports.push_back (viewport);
  120. XRRFreeCrtcInfo (crtc);
  121. }
  122. }
  123. XRRFreeOutputInfo (info);
  124. }
  125. XRRFreeScreenResources (screenResources);
  126. irrlichtCreationParameters.WindowId = reinterpret_cast<void*> (DefaultRootWindow (display));
  127. }
  128. void CContext::renderFrame (Render::CScene* scene)
  129. {
  130. this->m_time = this->getDevice ()->getTimer ()->getTime () / 1000.0f;
  131. this->m_pointerPosition.X = this->m_eventReceiver->getPosition ().X / (irr::f32) this->getDevice ()->getVideoDriver ()->getScreenSize ().Width;
  132. this->m_pointerPosition.Y = this->m_eventReceiver->getPosition ().Y / (irr::f32) this->getDevice ()->getVideoDriver ()->getScreenSize ().Height;
  133. if (this->m_viewports.empty () == true)
  134. {
  135. this->getDevice ()->getVideoDriver ()->beginScene (true, true, scene->getScene ()->getClearColor ().toSColor());
  136. this->getDevice ()->getSceneManager ()->drawAll ();
  137. this->getDevice ()->getVideoDriver ()->endScene ();
  138. }
  139. else
  140. {
  141. auto cur = this->m_viewports.begin ();
  142. auto end = this->m_viewports.end ();
  143. for (; cur != end; cur ++)
  144. {
  145. // change viewport to render to the correct portion of the display
  146. this->getDevice ()->getVideoDriver ()->setViewPort (*cur);
  147. this->getDevice ()->getVideoDriver ()->beginScene (false, true, scene->getScene ()->getClearColor ().toSColor());
  148. this->getDevice ()->getSceneManager ()->drawAll ();
  149. this->getDevice ()->getVideoDriver ()->endScene ();
  150. }
  151. }
  152. }
  153. void CContext::insertShaderVariable (Render::Shaders::Variables::CShaderVariable* variable)
  154. {
  155. this->m_globalShaderVariables.push_back (variable);
  156. }
  157. const std::vector<Render::Shaders::Variables::CShaderVariable*>& CContext::getShaderVariables () const
  158. {
  159. return this->m_globalShaderVariables;
  160. }
  161. irr::IrrlichtDevice* CContext::getDevice ()
  162. {
  163. return this->m_device;
  164. }
  165. irr::io::path CContext::resolveFile (const irr::io::path& file)
  166. {
  167. if (this->getDevice ()->getFileSystem ()->existFile (file) == false)
  168. {
  169. throw std::runtime_error ("Cannot find file " + std::string (file.c_str ()));
  170. }
  171. return file;
  172. }
  173. irr::io::path CContext::resolveMaterials (const std::string& materialName)
  174. {
  175. return this->resolveFile (std::string ("materials/" + materialName + ".tex").c_str ());
  176. }
  177. irr::io::path CContext::resolveVertexShader (const std::string& vertexShader)
  178. {
  179. return this->resolveFile (std::string ("shaders/" + vertexShader + ".vert").c_str ());
  180. }
  181. irr::io::path CContext::resolveFragmentShader (const std::string& fragmentShader)
  182. {
  183. return this->resolveFile (std::string ("shaders/" + fragmentShader + ".frag").c_str ());
  184. }
  185. irr::io::path CContext::resolveIncludeShader (const std::string& includeShader)
  186. {
  187. return this->resolveFile (std::string ("shaders/" + includeShader).c_str ());
  188. }