OpenGL RTT interface; X11 Pbuffer implementation (GL_ARB_pixel_buffer_object coming soon)
This commit is contained in:
@@ -8,6 +8,9 @@
|
||||
#include "DisplayResolutions.h"
|
||||
#include "LocalizedString.h"
|
||||
|
||||
#include "RageDisplay_OGL_Helpers.h"
|
||||
using namespace RageDisplay_OGL_Helpers;
|
||||
|
||||
#include <stack>
|
||||
#include <math.h> // ceil()
|
||||
#define GLX_GLXEXT_PROTOTYPES
|
||||
@@ -312,6 +315,174 @@ bool LowLevelWindow_X11::SupportsThreadedRendering()
|
||||
return g_pBackgroundContext != NULL;
|
||||
}
|
||||
|
||||
class RenderTarget_X11: public RenderTarget
|
||||
{
|
||||
public:
|
||||
RenderTarget_X11( LowLevelWindow_X11 *pWind );
|
||||
~RenderTarget_X11();
|
||||
|
||||
void Create( const RenderTargetParam ¶m, int &iTextureWidthOut, int &iTextureHeightOut );
|
||||
unsigned GetTexture() const { return m_iTexHandle; }
|
||||
void StartRenderingTo();
|
||||
void FinishRenderingTo();
|
||||
|
||||
/* Copying from the Pbuffer to the texture flips Y. */
|
||||
virtual bool InvertY() const { return true; }
|
||||
|
||||
private:
|
||||
int m_iWidth, m_iHeight;
|
||||
LowLevelWindow_X11 *m_pWind;
|
||||
GLXPbuffer m_iPbuffer;
|
||||
GLXContext m_pPbufferContext;
|
||||
unsigned int m_iTexHandle;
|
||||
|
||||
GLXContext m_pOldContext;
|
||||
GLXDrawable m_pOldDrawable;
|
||||
};
|
||||
|
||||
RenderTarget_X11::RenderTarget_X11( LowLevelWindow_X11 *pWind )
|
||||
{
|
||||
m_pWind = pWind;
|
||||
m_iPbuffer = 0;
|
||||
m_pPbufferContext = NULL;
|
||||
m_iTexHandle = 0;
|
||||
m_pOldContext = NULL;
|
||||
m_pOldDrawable = 0;
|
||||
}
|
||||
|
||||
RenderTarget_X11::~RenderTarget_X11()
|
||||
{
|
||||
if( m_pPbufferContext )
|
||||
glXDestroyContext( X11Helper::Dpy, m_pPbufferContext );
|
||||
if( m_iPbuffer )
|
||||
glXDestroyPbuffer( X11Helper::Dpy, m_iPbuffer );
|
||||
if( m_iTexHandle )
|
||||
glDeleteTextures( 1, reinterpret_cast<GLuint*>(&m_iTexHandle) );
|
||||
}
|
||||
|
||||
/* Note that although the texture size may need to be a power of 2, the Pbuffer
|
||||
* does not. */
|
||||
void RenderTarget_X11::Create( const RenderTargetParam ¶m, int &iTextureWidthOut, int &iTextureHeightOut )
|
||||
{
|
||||
//ASSERT( param.iWidth == power_of_two(param.iWidth) && param.iHeight == power_of_two(param.iHeight) );
|
||||
|
||||
m_iWidth = param.iWidth;
|
||||
m_iHeight = param.iHeight;
|
||||
|
||||
int pConfigAttribs[] =
|
||||
{
|
||||
GLX_DRAWABLE_TYPE, GLX_PBUFFER_BIT,
|
||||
GLX_RENDER_TYPE, GLX_RGBA_BIT,
|
||||
|
||||
GLX_RED_SIZE, 8,
|
||||
GLX_GREEN_SIZE, 8,
|
||||
GLX_BLUE_SIZE, 8,
|
||||
GLX_ALPHA_SIZE, param.bWithAlpha? 8:GLX_DONT_CARE,
|
||||
|
||||
GLX_DOUBLEBUFFER, False,
|
||||
GLX_DEPTH_SIZE, param.bWithDepthBuffer? 16:GLX_DONT_CARE,
|
||||
None
|
||||
};
|
||||
int iConfigs;
|
||||
GLXFBConfig *pConfigs = glXChooseFBConfig( X11Helper::Dpy, DefaultScreen(X11Helper::Dpy), pConfigAttribs, &iConfigs );
|
||||
ASSERT( pConfigs );
|
||||
|
||||
const int pPbufferAttribs[] =
|
||||
{
|
||||
GLX_PBUFFER_WIDTH, param.iWidth,
|
||||
GLX_PBUFFER_HEIGHT, param.iHeight,
|
||||
None
|
||||
};
|
||||
|
||||
for( int i = 0; i < iConfigs; ++i )
|
||||
{
|
||||
m_iPbuffer = glXCreatePbuffer( X11Helper::Dpy, pConfigs[i], pPbufferAttribs );
|
||||
if( m_iPbuffer == 0 )
|
||||
continue;
|
||||
|
||||
XVisualInfo *pVisual = glXGetVisualFromFBConfig( X11Helper::Dpy, pConfigs[i] );
|
||||
m_pPbufferContext = glXCreateContext( X11Helper::Dpy, pVisual, g_pContext, True );
|
||||
ASSERT( m_pPbufferContext );
|
||||
XFree( pVisual );
|
||||
break;
|
||||
}
|
||||
|
||||
ASSERT( m_iPbuffer );
|
||||
|
||||
// allocate OpenGL texture resource
|
||||
glGenTextures( 1, reinterpret_cast<GLuint*>(&m_iTexHandle) );
|
||||
glBindTexture( GL_TEXTURE_2D, m_iTexHandle );
|
||||
|
||||
LOG->Trace( "n %i, %ix%i", m_iTexHandle, param.iWidth, param.iHeight );
|
||||
while( glGetError() != GL_NO_ERROR )
|
||||
;
|
||||
|
||||
int iTextureWidth = power_of_two( param.iWidth );
|
||||
int iTextureHeight = power_of_two( param.iHeight );
|
||||
iTextureWidthOut = iTextureWidth;
|
||||
iTextureHeightOut = iTextureHeight;
|
||||
|
||||
glTexImage2D( GL_TEXTURE_2D, 0, param.bWithAlpha? GL_RGBA8:GL_RGB8,
|
||||
iTextureWidth, iTextureHeight, 0, param.bWithAlpha? GL_RGBA:GL_RGB, GL_UNSIGNED_BYTE, NULL );
|
||||
GLenum error = glGetError();
|
||||
ASSERT_M( error == GL_NO_ERROR, GLToString(error) );
|
||||
|
||||
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
|
||||
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
|
||||
|
||||
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE );
|
||||
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE );
|
||||
}
|
||||
|
||||
void RenderTarget_X11::StartRenderingTo()
|
||||
{
|
||||
m_pOldContext = glXGetCurrentContext();
|
||||
m_pOldDrawable = glXGetCurrentDrawable();
|
||||
glXMakeCurrent( X11Helper::Dpy, m_iPbuffer, m_pPbufferContext );
|
||||
|
||||
glViewport( 0, 0, m_iWidth, m_iHeight );
|
||||
}
|
||||
|
||||
void RenderTarget_X11::FinishRenderingTo()
|
||||
{
|
||||
glFlush();
|
||||
|
||||
glBindTexture( GL_TEXTURE_2D, m_iTexHandle );
|
||||
|
||||
while( glGetError() != GL_NO_ERROR )
|
||||
;
|
||||
|
||||
glCopyTexSubImage2D( GL_TEXTURE_2D, 0, 0, 0, 0, 0, m_iWidth, m_iHeight );
|
||||
|
||||
GLenum error = glGetError();
|
||||
ASSERT_M( error == GL_NO_ERROR, GLToString(error) );
|
||||
|
||||
glBindTexture( GL_TEXTURE_2D, 0 );
|
||||
|
||||
glXMakeCurrent( X11Helper::Dpy, m_pOldDrawable, m_pOldContext );
|
||||
m_pOldContext = NULL;
|
||||
m_pOldDrawable = 0;
|
||||
|
||||
}
|
||||
|
||||
bool LowLevelWindow_X11::SupportsRenderToTexture() const
|
||||
{
|
||||
/* Server must support pbuffers: */
|
||||
const int iScreen = DefaultScreen( X11Helper::Dpy );
|
||||
float fVersion = strtof( glXQueryServerString(X11Helper::Dpy, iScreen, GLX_VERSION), NULL );
|
||||
if( fVersion < 1.3f )
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
RenderTarget *LowLevelWindow_X11::CreateRenderTarget( const RenderTargetParam ¶m, int &iTextureWidthOut, int &iTextureHeightOut )
|
||||
{
|
||||
RenderTarget_X11 *pTarget = new RenderTarget_X11( this );
|
||||
pTarget->Create( param, iTextureWidthOut, iTextureHeightOut );
|
||||
return pTarget;
|
||||
}
|
||||
|
||||
void LowLevelWindow_X11::BeginConcurrentRenderingMainThread()
|
||||
{
|
||||
/* Move the main thread, which is going to be loading textures, etc. but
|
||||
|
||||
Reference in New Issue
Block a user