Selaa lähdekoodia

Fixes issue #59's origial issue

Hynak 4 vuotta sitten
vanhempi
commit
c11c6928ea

+ 24 - 7
src/WallpaperEngine/Render/CContext.cpp

@@ -1,5 +1,6 @@
 #include <iostream>
 #include <X11/Xlib.h>
+#include <X11/Xatom.h>
 #include <X11/extensions/Xrandr.h>
 
 #include <GL/glew.h>
@@ -76,8 +77,8 @@ void CContext::initializeViewports ()
 
     XRRFreeScreenResources (screenResources);
 
-    // set the
-    glfwWindowHintPointer (GLFW_NATIVE_PARENT_HANDLE, reinterpret_cast <void*> (DefaultRootWindow (display)));
+    // Cause of issue for issue #59 origial issue
+    // glfwWindowHintPointer (GLFW_NATIVE_PARENT_HANDLE, reinterpret_cast <void*> (DefaultRootWindow (display)));
 }
 
 void CContext::render ()
@@ -87,19 +88,35 @@ void CContext::render ()
 
     if (this->m_viewports.empty () == false)
     {
+        static Display* display = XOpenDisplay (nullptr);
         bool firstFrame = true;
         bool renderFrame = true;
         auto cur = this->m_viewports.begin ();
         auto end = this->m_viewports.end ();
 
+        Window root = DefaultRootWindow(display);
+        int windowWidth = 1920, windowHeight = 1080;
+        int fullWidth = DisplayWidth (display, DefaultScreen (display));
+        int fullHeight = DisplayHeight (display, DefaultScreen (display));
+
+        Pixmap pm = XCreatePixmap(display, root, fullWidth, fullHeight, 24);
+        GC gc = XCreateGC(display, pm, 0, NULL);
+        XFillRectangle(display, pm, gc, 0, 0, fullWidth, fullHeight);
+
+        char* image_data = this->m_wallpaper->renderImage (*cur, renderFrame, firstFrame);
+        XImage* image = XCreateImage(display, CopyFromParent, 24, ZPixmap, 0, (char *)image_data, windowWidth, windowHeight, 32, 0);
         for (; cur != end; cur ++)
         {
-            this->m_wallpaper->render (*cur, renderFrame, firstFrame);
-            // scenes need to render a new frame for each viewport as they produce different results
-            // but videos should only be rendered once per group of viewports
-            firstFrame = false;
-            renderFrame = !this->m_wallpaper->is <CVideo> ();
+            XPutImage(display, pm, gc, image, 0, 0, (*cur).x, (*cur).y, windowWidth, windowHeight);
         }
+
+        XSetWindowBackgroundPixmap(display, root, pm);
+        XClearWindow(display, root);
+        XFlush(display);
+
+        XDestroyImage(image);
+        XFreePixmap(display, pm);
+        XFreeGC(display, gc);
     }
     else
         this->m_wallpaper->render (this->m_defaultViewport);

+ 125 - 0
src/WallpaperEngine/Render/CWallpaper.cpp

@@ -287,6 +287,131 @@ void CWallpaper::render (glm::vec4 viewport, bool renderFrame, bool newFrame)
     glDrawArrays (GL_TRIANGLES, 0, 6);
 }
 
+char* CWallpaper::renderImage (glm::vec4 viewport, bool renderFrame, bool newFrame)
+{
+    if (renderFrame == true)
+        this->renderFrame (viewport);
+
+    int windowWidth = 1920;
+    int windowHeight = 1080;
+
+    if (this->getWallpaperData ()->is <WallpaperEngine::Core::CScene> ())
+    {
+        auto projection = this->getWallpaperData ()->as <WallpaperEngine::Core::CScene> ()->getOrthogonalProjection ();
+
+        windowWidth = projection->getWidth ();
+        windowHeight = projection->getHeight ();
+    }
+    else if (this->is <WallpaperEngine::Render::CVideo> ())
+    {
+        auto video = this->as <WallpaperEngine::Render::CVideo> ();
+
+        windowWidth = video->getWidth ();
+        windowHeight = video->getHeight ();
+    }
+
+    float widthRatio = windowWidth / viewport.z;
+    float heightRatio = windowHeight / viewport.w;
+
+    if (widthRatio > 1.0f)
+    {
+        float diff = widthRatio - 1.0f;
+
+        widthRatio -= diff;
+        heightRatio -= diff;
+    }
+
+    if (heightRatio > 1.0f)
+    {
+        float diff = heightRatio - 1.0f;
+
+        widthRatio -= diff;
+        heightRatio -= diff;
+    }
+
+    if (widthRatio < 1.0f)
+    {
+        float diff = 1.0f - widthRatio;
+
+        widthRatio += diff;
+        heightRatio += diff;
+    }
+
+    if (heightRatio < 1.0f)
+    {
+        float diff = 1.0f - heightRatio;
+
+        widthRatio += diff;
+        heightRatio += diff;
+    }
+
+    if (widthRatio < 0.0f) widthRatio = -widthRatio;
+    if (heightRatio < 0.0f) heightRatio = -heightRatio;
+
+    GLfloat position [] = {
+        -widthRatio, -heightRatio, 0.0f,
+        widthRatio, -heightRatio, 0.0f,
+        -widthRatio, heightRatio, 0.0f,
+        -widthRatio, heightRatio, 0.0f,
+        widthRatio, -heightRatio, 0.0f,
+        widthRatio, heightRatio, 0.0f
+    };
+
+    glBindBuffer (GL_ARRAY_BUFFER, this->m_positionBuffer);
+    glBufferData (GL_ARRAY_BUFFER, sizeof (position), position, GL_STATIC_DRAW);
+
+    // Need to flip the image (FB stores the image upside down)
+    GLfloat texCoords [] = {
+        0.0f, 1.0f,
+        1.0f, 1.0f,
+        0.0f, 0.0f,
+        0.0f, 0.0f,
+        1.0f, 1.0f,
+        1.0f, 0.0f
+    };
+
+    glBindBuffer (GL_ARRAY_BUFFER, this->m_texCoordBuffer);
+    glBufferData (GL_ARRAY_BUFFER, sizeof (texCoords), texCoords, GL_STATIC_DRAW);
+
+    glViewport (viewport.x, viewport.y, viewport.z, viewport.w);
+
+    // A fbo for flipping the image. Without this call the image will be flipped.
+    static CFBO* screen_fbo = this->createFBO ("_sc_FullFrameBuffer", ITexture::TextureFormat::ARGB8888, 1.0, windowWidth, windowHeight, windowWidth, windowHeight);
+
+    glBindFramebuffer (GL_FRAMEBUFFER, screen_fbo->getFramebuffer());
+
+    if (newFrame == true)
+        glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+    glDisable (GL_BLEND);
+    glDisable (GL_DEPTH_TEST);
+    // do not use any shader
+    glUseProgram (this->m_shader);
+    // activate scene texture
+    glActiveTexture (GL_TEXTURE0);
+    glBindTexture (GL_TEXTURE_2D, this->getWallpaperTexture ());
+    // set uniforms and attribs
+    glEnableVertexAttribArray (this->a_TexCoord);
+    glBindBuffer (GL_ARRAY_BUFFER, this->m_texCoordBuffer);
+    glVertexAttribPointer (this->a_TexCoord, 2, GL_FLOAT, GL_FALSE, 0, nullptr);
+
+    glEnableVertexAttribArray (this->a_Position);
+    glBindBuffer (GL_ARRAY_BUFFER, this->m_positionBuffer);
+    glVertexAttribPointer (this->a_Position, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
+
+    glUniform1i (this->g_Texture0, 0);
+    // write the framebuffer as is to the screen
+    glBindBuffer (GL_ARRAY_BUFFER, this->m_texCoordBuffer);
+    glDrawArrays (GL_TRIANGLES, 0, 6);
+
+    glBindTexture (GL_TEXTURE_2D, screen_fbo->getTextureID ());
+
+    // Get FB data from OpenGL, X11 will free this pointer when it is created into an XImage.
+    char* image;
+    image = (char*)malloc(windowWidth*windowHeight*4);
+    glReadPixels(0, 0, 1920, 1080, GL_BGRA,  GL_UNSIGNED_BYTE, (void*)(image));
+    return image;
+}
+
 void CWallpaper::setupFramebuffers ()
 {
     int windowWidth = 1920;

+ 5 - 0
src/WallpaperEngine/Render/CWallpaper.h

@@ -33,6 +33,11 @@ namespace WallpaperEngine::Render
          */
         void render (glm::vec4 viewport, bool renderFrame = true, bool newFrame = true);
 
+        /**
+         * Performs a render pass of the wallpaper and returns the char* of the image
+         */
+        char* renderImage (glm::vec4 viewport, bool renderFrame = true, bool newFrame = true);
+        
         /**
          * @return The container to resolve files for this wallpaper
          */