From 9342dc77bbc050870da41264d3786437a9884d9f Mon Sep 17 00:00:00 2001 From: laurentgom Date: Wed, 17 Jun 2009 08:49:20 +0000 Subject: [PATCH] Added the Linux P-Buffer implementation (WIP) git-svn-id: https://sfml.svn.sourceforge.net/svnroot/sfml/branches/sfml2@1146 4e206d99-4929-0410-ac5d-dfc041789085 --- .../Graphics/Linux/RenderImageImplPBuffer.cpp | 226 ++++++++++++++++++ .../Graphics/Linux/RenderImageImplPBuffer.hpp | 103 ++++++++ src/SFML/Graphics/Makefile | 2 +- .../Graphics/Win32/RenderImageImplPBuffer.cpp | 2 +- 4 files changed, 331 insertions(+), 2 deletions(-) create mode 100644 src/SFML/Graphics/Linux/RenderImageImplPBuffer.cpp create mode 100644 src/SFML/Graphics/Linux/RenderImageImplPBuffer.hpp diff --git a/src/SFML/Graphics/Linux/RenderImageImplPBuffer.cpp b/src/SFML/Graphics/Linux/RenderImageImplPBuffer.cpp new file mode 100644 index 00000000..0c9bac7e --- /dev/null +++ b/src/SFML/Graphics/Linux/RenderImageImplPBuffer.cpp @@ -0,0 +1,226 @@ +//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2009 Laurent Gomila (laurent.gom@gmail.com) +// +// This software is provided 'as-is', without any express or implied warranty. +// In no event will the authors be held liable for any damages arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it freely, +// subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; +// you must not claim that you wrote the original software. +// If you use this software in a product, an acknowledgment +// in the product documentation would be appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, +// and must not be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source distribution. +// +//////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////// +// Headers +//////////////////////////////////////////////////////////// +#include +#include +#include +#include + + +namespace sf +{ +namespace priv +{ +//////////////////////////////////////////////////////////// +/// Default constructor +//////////////////////////////////////////////////////////// +RenderImageImplPBuffer::RenderImageImplPBuffer() : +myPBuffer(NULL), +myContext(NULL), +myWidth (0), +myHeight (0) +{ + myDisplay = XOpenDisplay(NULL); +} + + +//////////////////////////////////////////////////////////// +/// Destructor +//////////////////////////////////////////////////////////// +RenderImageImplPBuffer::~RenderImageImplPBuffer() +{ + if (myContext) + glXDestroyContext(myDisplay, myContext); + + if (myPBuffer) + glXDestroyGLXPbufferSGIX(myDisplay, myPBuffer); + + XCloseDisplay(myDisplay); + + // This is to make sure that another valid context is made + // active after we destroy the P-Buffer's one + Context Ctx; +} + + +//////////////////////////////////////////////////////////// +/// Check whether the system supports P-Buffer or not +//////////////////////////////////////////////////////////// +bool RenderImageImplPBuffer::IsSupported() +{ + // Make sure that GLEW is initialized + EnsureGlewInit(); + + return false; //glxewIsSupported("GLX_SGIX_pbuffer"); +} + + +//////////////////////////////////////////////////////////// +/// /see RenderImageImpl::Create +//////////////////////////////////////////////////////////// +bool RenderImageImplPBuffer::Create(unsigned int Width, unsigned int Height, unsigned int /*TextureId*/, bool DepthBuffer) +{ + // Store the dimensions + myWidth = Width; + myHeight = Height; + + // Define the PBuffer attributes + int VisualAttributes[] = + { + GLX_RENDER_TYPE, GLX_RGBA_BIT, + GLX_DRAWABLE_TYPE, GLX_PBUFFER_BIT, + GLX_RED_SIZE, 8, + GLX_GREEN_SIZE, 8, + GLX_BLUE_SIZE, 8, + GLX_ALPHA_SIZE, 8, + GLX_DEPTH_SIZE, (DepthBuffer ? 24 : 0), + 0 + }; + int PBufferAttributes[] = + { + GLX_PBUFFER_WIDTH, Width, + GLX_PBUFFER_HEIGHT, Height, + 0 + }; + + // Get the available FB configurations + int NbConfigs = 0; + GLXFBConfig* Configs = glXChooseFBConfigSGIX(myDisplay, DefaultScreen(myDisplay), VisualAttributes, &NbConfigs); + if (!Configs || !NbConfigs) + { + std::cerr << "Impossible to create render image (failed to find a suitable pixel format for PBuffer)" << std::endl; + return false; + } + + // Create the P-Buffer + myPBuffer = glXCreateGLXPbufferSGIX(myDisplay, Configs[0], Width, Height, PBufferAttributes); + if (!myPBuffer) + { + std::cerr << "Impossible to create render image (failed to create the OpenGL PBuffer)" << std::endl; + XFree(Configs); + return false; + } + + // Check the actual size of the P-Buffer + unsigned int ActualWidth, ActualHeight; + glXQueryGLXPbufferSGIX(myDisplay, myPBuffer, GLX_WIDTH_SGIX, &ActualWidth); + glXQueryGLXPbufferSGIX(myDisplay, myPBuffer, GLX_HEIGHT_SGIX, &ActualHeight); + if ((ActualWidth != Width) || (ActualHeight != Height)) + { + std::cerr << "Impossible to create render image (failed to match the requested size). " + << "Size: " << ActualWidth << "x" << ActualHeight << " - " + << "Requested: " << Width << "x" << Height + << std::endl; + XFree(Configs); + return false; + } + + // We'll have to share the P-Buffer context with the current context + GLXDrawable CurrentDrawable = glXGetCurrentDrawable(); + GLXContext CurrentContext = glXGetCurrentContext(); + if (CurrentContext) + glXMakeCurrent(myDisplay, NULL, NULL); + + // Create the context + XVisualInfo* Visual = glXGetVisualFromFBConfig(myDisplay, Configs[0]); + myContext = glXCreateContext(myDisplay, Visual, CurrentContext, true); + if (!myContext) + { + std::cerr << "Impossible to create render image (failed to create the OpenGL context)" << std::endl; + XFree(Configs); + XFree(Visual); + return false; + } + + // Restore the previous active context + if (CurrentContext) + glXMakeCurrent(myDisplay, CurrentDrawable, CurrentContext); + + // Cleanup resources + XFree(Configs); + XFree(Visual); + + return true; +} + + +//////////////////////////////////////////////////////////// +/// /see RenderImageImpl::Activate +//////////////////////////////////////////////////////////// +bool RenderImageImplPBuffer::Activate(bool Active) +{ + if (Active) + { + if (myPBuffer && myContext && (glXGetCurrentContext() != myContext)) + { + // Bind the OpenGL context of the P-Buffer + if (!glXMakeCurrent(myDisplay, myPBuffer, myContext)) + { + std::cout << "Failed to activate render image" << std::endl; + return false; + } + } + } + else + { + // We don't actually unbind the P-Buffer, for performances reasons + } + + return true; +} + + +//////////////////////////////////////////////////////////// +/// /see RenderImageImpl::UpdateTexture +//////////////////////////////////////////////////////////// +bool RenderImageImplPBuffer::UpdateTexture(unsigned int TextureId) +{ + // Store the current active context + GLXDrawable CurrentDrawable = glXGetCurrentDrawable(); + GLXContext CurrentContext = glXGetCurrentContext(); + + if (Activate(true)) + { + // Bind the texture + GLCheck(glEnable(GL_TEXTURE_2D)); + GLCheck(glBindTexture(GL_TEXTURE_2D, TextureId)); + + // Copy the rendered pixels to the image + GLCheck(glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, myWidth, myHeight)); + + // Restore the previous context + glXMakeCurrent(myDisplay, CurrentDrawable, CurrentContext); + + return true; + } + + return false; +} + +} // namespace priv + +} // namespace sf diff --git a/src/SFML/Graphics/Linux/RenderImageImplPBuffer.hpp b/src/SFML/Graphics/Linux/RenderImageImplPBuffer.hpp new file mode 100644 index 00000000..96dbfa15 --- /dev/null +++ b/src/SFML/Graphics/Linux/RenderImageImplPBuffer.hpp @@ -0,0 +1,103 @@ +//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2009 Laurent Gomila (laurent.gom@gmail.com) +// +// This software is provided 'as-is', without any express or implied warranty. +// In no event will the authors be held liable for any damages arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it freely, +// subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; +// you must not claim that you wrote the original software. +// If you use this software in a product, an acknowledgment +// in the product documentation would be appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, +// and must not be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source distribution. +// +//////////////////////////////////////////////////////////// + +#ifndef SFML_RENDERIMAGEIMPLPBUFFER_HPP +#define SFML_RENDERIMAGEIMPLPBUFFER_HPP + +//////////////////////////////////////////////////////////// +// Headers +//////////////////////////////////////////////////////////// +#include +#include +#include +#include + + +namespace sf +{ +namespace priv +{ +//////////////////////////////////////////////////////////// +/// Specialization of RenderImageImpl using GLX P-Buffers +//////////////////////////////////////////////////////////// +class RenderImageImplPBuffer : public RenderImageImpl +{ +public : + + //////////////////////////////////////////////////////////// + /// Default constructor + /// + //////////////////////////////////////////////////////////// + RenderImageImplPBuffer(); + + //////////////////////////////////////////////////////////// + /// Destructor + /// + //////////////////////////////////////////////////////////// + ~RenderImageImplPBuffer(); + + //////////////////////////////////////////////////////////// + /// Check whether the system supports P-Buffer or not + /// + /// \return True if P-Buffer render images are supported + /// + //////////////////////////////////////////////////////////// + static bool IsSupported(); + +private : + + //////////////////////////////////////////////////////////// + /// /see RenderImageImpl::Create + /// + //////////////////////////////////////////////////////////// + virtual bool Create(unsigned int Width, unsigned int Height, unsigned int TextureId, bool DepthBuffer); + + //////////////////////////////////////////////////////////// + /// /see RenderImageImpl::Activate + /// + //////////////////////////////////////////////////////////// + virtual bool Activate(bool Active); + + //////////////////////////////////////////////////////////// + /// /see RenderImageImpl::UpdateTexture + /// + //////////////////////////////////////////////////////////// + virtual bool UpdateTexture(unsigned TextureId); + + //////////////////////////////////////////////////////////// + // Member data + //////////////////////////////////////////////////////////// + ::Display* myDisplay; ///< Connection to the X display + GLXPbuffer myPBuffer; ///< P-Buffer + GLXContext myContext; ///< Associated OpenGL context + unsigned int myWidth; ///< Width of the P-Buffer + unsigned int myHeight; ///< Height of the P-Buffer +}; + +} // namespace priv + +} // namespace sf + + +#endif // SFML_RENDERIMAGEIMPLPBUFFER_HPP diff --git a/src/SFML/Graphics/Makefile b/src/SFML/Graphics/Makefile index f1cc6ffa..30835dc5 100644 --- a/src/SFML/Graphics/Makefile +++ b/src/SFML/Graphics/Makefile @@ -1,4 +1,4 @@ -SRC = $(wildcard *.cpp) +SRC = $(wildcard *.cpp ./Linux/*.cpp) SRCGLEW = $(wildcard ./GLEW/*.c) SRCJPEG = $(wildcard ./libjpeg/*.c) SRCPNG = $(wildcard ./libpng/*.c) diff --git a/src/SFML/Graphics/Win32/RenderImageImplPBuffer.cpp b/src/SFML/Graphics/Win32/RenderImageImplPBuffer.cpp index a5cf8c37..9eb9e551 100644 --- a/src/SFML/Graphics/Win32/RenderImageImplPBuffer.cpp +++ b/src/SFML/Graphics/Win32/RenderImageImplPBuffer.cpp @@ -72,7 +72,7 @@ RenderImageImplPBuffer::~RenderImageImplPBuffer() //////////////////////////////////////////////////////////// -/// Check whether the system supports FBOs or not +/// Check whether the system supports P-Buffer or not //////////////////////////////////////////////////////////// bool RenderImageImplPBuffer::IsSupported() {