CWallpaper.cpp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293
  1. #include "CWallpaper.h"
  2. #include "WallpaperEngine/Render/Wallpapers/CScene.h"
  3. #include "WallpaperEngine/Render/Wallpapers/CVideo.h"
  4. #include "WallpaperEngine/Render/Wallpapers/CWeb.h"
  5. #include "common.h"
  6. #include <glm/glm.hpp>
  7. #include <glm/gtc/type_ptr.hpp>
  8. #include <utility>
  9. using namespace WallpaperEngine::Render;
  10. CWallpaper::CWallpaper (Core::CWallpaper* wallpaperData, std::string type, CRenderContext& context,
  11. CAudioContext& audioContext, const CWallpaperState::TextureUVsScaling& scalingMode) :
  12. CContextAware (context),
  13. m_wallpaperData (wallpaperData),
  14. m_type (std::move (type)),
  15. m_destFramebuffer (GL_NONE),
  16. m_sceneFBO (nullptr),
  17. m_texCoordBuffer (GL_NONE),
  18. m_positionBuffer (GL_NONE),
  19. m_shader (GL_NONE),
  20. g_Texture0 (GL_NONE),
  21. a_Position (GL_NONE),
  22. a_TexCoord (GL_NONE),
  23. m_vaoBuffer (GL_NONE),
  24. m_audioContext (audioContext),
  25. m_state (scalingMode) {
  26. // generate the VAO to stop opengl from complaining
  27. glGenVertexArrays (1, &this->m_vaoBuffer);
  28. glBindVertexArray (this->m_vaoBuffer);
  29. this->setupShaders ();
  30. const GLfloat texCoords [] = {0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f};
  31. // inverted positions so the final texture is rendered properly
  32. const GLfloat position [] = {-1.0f, 1.0f, 0.0f, 1.0, 1.0f, 0.0f, -1.0f, -1.0f, 0.0f,
  33. -1.0f, -1.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f, -1.0f, 0.0f};
  34. glGenBuffers (1, &this->m_texCoordBuffer);
  35. glBindBuffer (GL_ARRAY_BUFFER, this->m_texCoordBuffer);
  36. glBufferData (GL_ARRAY_BUFFER, sizeof (texCoords), texCoords, GL_STATIC_DRAW);
  37. glGenBuffers (1, &this->m_positionBuffer);
  38. glBindBuffer (GL_ARRAY_BUFFER, this->m_positionBuffer);
  39. glBufferData (GL_ARRAY_BUFFER, sizeof (position), position, GL_STATIC_DRAW);
  40. }
  41. CWallpaper::~CWallpaper () = default;
  42. CContainer* CWallpaper::getContainer () const {
  43. return this->m_wallpaperData->getProject ().getContainer ();
  44. }
  45. WallpaperEngine::Core::CWallpaper* CWallpaper::getWallpaperData () const {
  46. return this->m_wallpaperData;
  47. }
  48. GLuint CWallpaper::getWallpaperFramebuffer () const {
  49. return this->m_sceneFBO->getFramebuffer ();
  50. }
  51. GLuint CWallpaper::getWallpaperTexture () const {
  52. return this->m_sceneFBO->getTextureID (0);
  53. }
  54. void CWallpaper::setupShaders () {
  55. // reserve shaders in OpenGL
  56. const GLuint vertexShaderID = glCreateShader (GL_VERTEX_SHADER);
  57. // give shader's source code to OpenGL to be compiled
  58. const char* sourcePointer = "#version 330\n"
  59. "precision highp float;\n"
  60. "in vec3 a_Position;\n"
  61. "in vec2 a_TexCoord;\n"
  62. "out vec2 v_TexCoord;\n"
  63. "void main () {\n"
  64. "gl_Position = vec4 (a_Position, 1.0);\n"
  65. "v_TexCoord = a_TexCoord;\n"
  66. "}";
  67. glShaderSource (vertexShaderID, 1, &sourcePointer, nullptr);
  68. glCompileShader (vertexShaderID);
  69. GLint result = GL_FALSE;
  70. int infoLogLength = 0;
  71. // ensure the vertex shader was correctly compiled
  72. glGetShaderiv (vertexShaderID, GL_COMPILE_STATUS, &result);
  73. glGetShaderiv (vertexShaderID, GL_INFO_LOG_LENGTH, &infoLogLength);
  74. if (infoLogLength > 0) {
  75. char* logBuffer = new char [infoLogLength + 1];
  76. // ensure logBuffer ends with a \0
  77. memset (logBuffer, 0, infoLogLength + 1);
  78. // get information about the error
  79. glGetShaderInfoLog (vertexShaderID, infoLogLength, nullptr, logBuffer);
  80. // throw an exception about the issue
  81. const std::string message = logBuffer;
  82. // free the buffer
  83. delete [] logBuffer;
  84. // throw an exception
  85. sLog.exception (message);
  86. }
  87. // reserve shaders in OpenGL
  88. const GLuint fragmentShaderID = glCreateShader (GL_FRAGMENT_SHADER);
  89. // give shader's source code to OpenGL to be compiled
  90. sourcePointer = "#version 330\n"
  91. "precision highp float;\n"
  92. "uniform sampler2D g_Texture0;\n"
  93. "in vec2 v_TexCoord;\n"
  94. "out vec4 out_FragColor;\n"
  95. "void main () {\n"
  96. "out_FragColor = texture (g_Texture0, v_TexCoord);\n"
  97. "}";
  98. glShaderSource (fragmentShaderID, 1, &sourcePointer, nullptr);
  99. glCompileShader (fragmentShaderID);
  100. result = GL_FALSE;
  101. infoLogLength = 0;
  102. // ensure the vertex shader was correctly compiled
  103. glGetShaderiv (fragmentShaderID, GL_COMPILE_STATUS, &result);
  104. glGetShaderiv (fragmentShaderID, GL_INFO_LOG_LENGTH, &infoLogLength);
  105. if (infoLogLength > 0) {
  106. char* logBuffer = new char [infoLogLength + 1];
  107. // ensure logBuffer ends with a \0
  108. memset (logBuffer, 0, infoLogLength + 1);
  109. // get information about the error
  110. glGetShaderInfoLog (fragmentShaderID, infoLogLength, nullptr, logBuffer);
  111. // throw an exception about the issue
  112. const std::string message = logBuffer;
  113. // free the buffer
  114. delete [] logBuffer;
  115. // throw an exception
  116. sLog.exception (message);
  117. }
  118. // create the final program
  119. this->m_shader = glCreateProgram ();
  120. // link the shaders together
  121. glAttachShader (this->m_shader, vertexShaderID);
  122. glAttachShader (this->m_shader, fragmentShaderID);
  123. glLinkProgram (this->m_shader);
  124. // check that the shader was properly linked
  125. result = GL_FALSE;
  126. infoLogLength = 0;
  127. glGetProgramiv (this->m_shader, GL_LINK_STATUS, &result);
  128. glGetProgramiv (this->m_shader, GL_INFO_LOG_LENGTH, &infoLogLength);
  129. if (infoLogLength > 0) {
  130. char* logBuffer = new char [infoLogLength + 1];
  131. // ensure logBuffer ends with a \0
  132. memset (logBuffer, 0, infoLogLength + 1);
  133. // get information about the error
  134. glGetProgramInfoLog (this->m_shader, infoLogLength, nullptr, logBuffer);
  135. // throw an exception about the issue
  136. const std::string message = logBuffer;
  137. // free the buffer
  138. delete [] logBuffer;
  139. // throw an exception
  140. sLog.exception (message);
  141. }
  142. // after being liked shaders can be dettached and deleted
  143. glDetachShader (this->m_shader, vertexShaderID);
  144. glDetachShader (this->m_shader, fragmentShaderID);
  145. glDeleteShader (vertexShaderID);
  146. glDeleteShader (fragmentShaderID);
  147. // get textures
  148. this->g_Texture0 = glGetUniformLocation (this->m_shader, "g_Texture0");
  149. this->a_Position = glGetAttribLocation (this->m_shader, "a_Position");
  150. this->a_TexCoord = glGetAttribLocation (this->m_shader, "a_TexCoord");
  151. }
  152. void CWallpaper::setDestinationFramebuffer (GLuint framebuffer) {
  153. this->m_destFramebuffer = framebuffer;
  154. }
  155. void CWallpaper::updateUVs (const glm::ivec4& viewport, const bool vflip) {
  156. // update UVs if something has changed, otherwise use old values
  157. if (this->m_state.hasChanged (viewport, vflip, this->getWidth (), this->getHeight ())) {
  158. // Update wallpaper state
  159. this->m_state.updateState (viewport, vflip, this->getWidth (), this->getHeight ());
  160. }
  161. }
  162. void CWallpaper::render (glm::ivec4 viewport, bool vflip) {
  163. this->renderFrame (viewport);
  164. // Update UVs coordinates according to scaling mode of this wallpaper
  165. updateUVs (viewport, vflip);
  166. auto [ustart, uend, vstart, vend] = this->m_state.getTextureUVs ();
  167. const GLfloat texCoords [] = {
  168. ustart, vstart, uend, vstart, ustart, vend, ustart, vend, uend, vstart, uend, vend,
  169. };
  170. glViewport (viewport.x, viewport.y, viewport.z, viewport.w);
  171. glBindFramebuffer (GL_FRAMEBUFFER, this->m_destFramebuffer);
  172. glBindVertexArray (this->m_vaoBuffer);
  173. glDisable (GL_BLEND);
  174. glDisable (GL_DEPTH_TEST);
  175. // do not use any shader
  176. glUseProgram (this->m_shader);
  177. // activate scene texture
  178. glActiveTexture (GL_TEXTURE0);
  179. glBindTexture (GL_TEXTURE_2D, this->getWallpaperTexture ());
  180. // set uniforms and attribs
  181. glEnableVertexAttribArray (this->a_TexCoord);
  182. glBindBuffer (GL_ARRAY_BUFFER, this->m_texCoordBuffer);
  183. glBufferData (GL_ARRAY_BUFFER, sizeof (texCoords), texCoords, GL_STATIC_DRAW);
  184. glVertexAttribPointer (this->a_TexCoord, 2, GL_FLOAT, GL_FALSE, 0, nullptr);
  185. glEnableVertexAttribArray (this->a_Position);
  186. glBindBuffer (GL_ARRAY_BUFFER, this->m_positionBuffer);
  187. glVertexAttribPointer (this->a_Position, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
  188. glUniform1i (this->g_Texture0, 0);
  189. // write the framebuffer as is to the screen
  190. glBindBuffer (GL_ARRAY_BUFFER, this->m_texCoordBuffer);
  191. glDrawArrays (GL_TRIANGLES, 0, 6);
  192. }
  193. void CWallpaper::setupFramebuffers () {
  194. const uint32_t width = this->getWidth ();
  195. const uint32_t height = this->getHeight ();
  196. const ITexture::TextureFlags clamp = this->getContext ().getApp ().getContext ().settings.render.window.clamp;
  197. // create framebuffer for the scene
  198. this->m_sceneFBO = this->createFBO ("_rt_FullFrameBuffer", ITexture::TextureFormat::ARGB8888, clamp, 1.0, width,
  199. height, width, height);
  200. this->aliasFBO ("_rt_MipMappedFrameBuffer", this->m_sceneFBO);
  201. }
  202. CAudioContext& CWallpaper::getAudioContext () {
  203. return this->m_audioContext;
  204. }
  205. CFBO* CWallpaper::createFBO (const std::string& name, ITexture::TextureFormat format, ITexture::TextureFlags flags,
  206. float scale, uint32_t realWidth, uint32_t realHeight, uint32_t textureWidth,
  207. uint32_t textureHeight) {
  208. CFBO* fbo = new CFBO (name, format, flags, scale, realWidth, realHeight, textureWidth, textureHeight);
  209. this->m_fbos.insert (std::make_pair (name, fbo));
  210. return fbo;
  211. }
  212. void CWallpaper::aliasFBO (const std::string& alias, CFBO* original) {
  213. this->m_fbos.insert (std::make_pair (alias, original));
  214. }
  215. const std::map<std::string, CFBO*>& CWallpaper::getFBOs () const {
  216. return this->m_fbos;
  217. }
  218. CFBO* CWallpaper::findFBO (const std::string& name) const {
  219. const auto it = this->m_fbos.find (name);
  220. if (it == this->m_fbos.end ())
  221. sLog.exception ("Cannot find FBO ", name);
  222. return it->second;
  223. }
  224. CFBO* CWallpaper::getFBO () const {
  225. return this->m_sceneFBO;
  226. }
  227. CWallpaper* CWallpaper::fromWallpaper (Core::CWallpaper* wallpaper, CRenderContext& context,
  228. CAudioContext& audioContext,
  229. const CWallpaperState::TextureUVsScaling& scalingMode) {
  230. if (wallpaper->is<Core::CScene> ())
  231. return new WallpaperEngine::Render::CScene (wallpaper->as<Core::CScene> (), context, audioContext, scalingMode);
  232. if (wallpaper->is<Core::CVideo> ())
  233. return new WallpaperEngine::Render::CVideo (wallpaper->as<Core::CVideo> (), context, audioContext, scalingMode);
  234. else if (wallpaper->is<Core::CWeb> ())
  235. return new WallpaperEngine::Render::CWeb (wallpaper->as<Core::CWeb> (), context, audioContext, scalingMode);
  236. else
  237. sLog.exception ("Unsupported wallpaper type");
  238. }