CContext.cpp 7.1 KB

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