
git-svn-id: https://sfml.svn.sourceforge.net/svnroot/sfml/branches/sfml2@1362 4e206d99-4929-0410-ac5d-dfc041789085
228 lines
7.2 KiB
C++
228 lines
7.2 KiB
C++
////////////////////////////////////////////////////////////
|
|
//
|
|
// 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 <SFML/Graphics/Linux/RenderImageImplPBuffer.hpp>
|
|
#include <SFML/Graphics/GLCheck.hpp>
|
|
#include <SFML/Window/Context.hpp>
|
|
#include <iostream>
|
|
|
|
|
|
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::SetReferenceActive();
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////
|
|
/// Check whether the system supports P-Buffer or not
|
|
////////////////////////////////////////////////////////////
|
|
bool RenderImageImplPBuffer::IsSupported()
|
|
{
|
|
// Make sure that GLEW is initialized
|
|
EnsureGlewInit();
|
|
|
|
return glxewIsSupported("GLX_SGIX_pbuffer");
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////
|
|
/// /see RenderImageImpl::Create
|
|
////////////////////////////////////////////////////////////
|
|
bool RenderImageImplPBuffer::Create(unsigned int width, unsigned int height, unsigned int, 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)
|
|
{
|
|
if (glXGetCurrentContext() != myContext)
|
|
return glXMakeCurrent(myDisplay, myPBuffer, myContext) != 0;
|
|
else
|
|
return true;
|
|
}
|
|
else
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// To deactivate the P-Buffer's context, we actually activate
|
|
// another one so that we make sure that there is always an
|
|
// active context for subsequent graphics operations
|
|
return Context::SetReferenceActive();
|
|
}
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////
|
|
/// /see RenderImageImpl::UpdateTexture
|
|
////////////////////////////////////////////////////////////
|
|
bool RenderImageImplPBuffer::UpdateTexture(unsigned int textureId)
|
|
{
|
|
if (Activate(true))
|
|
{
|
|
GLint previous;
|
|
GLCheck(glGetIntegerv(GL_TEXTURE_BINDING_2D, &previous));
|
|
|
|
// 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));
|
|
|
|
GLCheck(glBindTexture(GL_TEXTURE_2D, previous));
|
|
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
} // namespace priv
|
|
|
|
} // namespace sf
|