Add GLRenderTarget class.

The render target is used to render the scene (or part of it) onto texture. This texture can then be used
  e.g. to do some postprocessing.
  Demo effect coming soon.

Move checkGLError() to kwineffects.*
Add GLTexture ctor which takes width and height and creates an empty texture (to be used with
  GLRenderTarget to render onto it)

svn path=/branches/work/kwin_composite/; revision=655489
This commit is contained in:
Rivo Laks 2007-04-18 15:22:13 +00:00
parent 1af89da210
commit cc1a7a9eca
3 changed files with 143 additions and 8 deletions

View file

@ -18,6 +18,7 @@ License. See the file "COPYING" for the exact licensing terms.
#include <QImage>
#include <QHash>
#include <QFile>
#include <QString>
#define MAKE_GL_VERSION(major, minor, release) ( ((major) << 16) | ((minor) << 8) | (release) )
@ -90,6 +91,13 @@ bool hasGLExtension(const QString& extension)
return glExtensions.contains(extension);
}
void checkGLError( const char* txt )
{
GLenum err = glGetError();
if( err != GL_NO_ERROR )
kWarning() << "GL error (" << txt << "): 0x" << QString::number( err, 16 ) << endl;
}
int nearestPowerOfTwo( int x )
{
// This method had been copied from Qt's nearest_gl_texture_size()
@ -138,6 +146,24 @@ GLTexture::GLTexture( const QString& fileName )
load( fileName );
}
GLTexture::GLTexture( int width, int height )
{
init();
if( NPOTTextureSupported() || ( isPowerOfTwo( width ) && isPowerOfTwo( height )))
{
mTarget = GL_TEXTURE_2D;
mScale.setWidth( 1.0 );
mScale.setHeight( 1.0 );
can_use_mipmaps = true;
glGenTextures( 1, &mTexture );
bind();
glTexImage2D( mTarget, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
unbind();
}
}
GLTexture::~GLTexture()
{
discard();
@ -591,6 +617,76 @@ bool GLShader::setAttribute(const QString& name, float value)
return (location >= 0);
}
/*** GLRenderTarget ***/
GLRenderTarget::GLRenderTarget(GLTexture* color)
{
// Reset variables
mValid = false;
mTexture = color;
// Make sure FBO is supported
if(hasGLExtension("GL_EXT_framebuffer_object") && glFramebufferTexture2D &&
mTexture && !mTexture->isNull())
{
initFBO();
}
}
GLRenderTarget::~GLRenderTarget()
{
if(mValid)
{
glDeleteFramebuffers(1, &mFramebuffer);
}
}
bool GLRenderTarget::enable()
{
if(!valid())
{
kError(1212) << k_funcinfo << "Can't enable invalid render target!" << endl;
return false;
}
glBindFramebuffer(GL_FRAMEBUFFER_EXT, mFramebuffer);
return true;
}
bool GLRenderTarget::disable()
{
if(!valid())
{
kError(1212) << k_funcinfo << "Can't disable invalid render target!" << endl;
return false;
}
glBindFramebuffer(GL_FRAMEBUFFER_EXT, 0);
mTexture->setDirty();
return true;
}
void GLRenderTarget::initFBO()
{
glGenFramebuffers(1, &mFramebuffer);
glBindFramebuffer(GL_FRAMEBUFFER_EXT, mFramebuffer);
glFramebufferTexture2D(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, mTexture->texture(), 0);
GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER_EXT);
if(status != GL_FRAMEBUFFER_COMPLETE_EXT)
{
kError(1212) << k_funcinfo << "Invalid fb status: " << status << endl;
}
glBindFramebuffer(GL_FRAMEBUFFER_EXT, 0);
mValid = true;
}
#endif
} // namespace

View file

@ -51,6 +51,9 @@ bool KWIN_EXPORT hasGLXVersion(int major, int minor, int release = 0);
// use for both OpenGL and GLX extensions
bool KWIN_EXPORT hasGLExtension(const QString& extension);
// detect OpenGL error (add to various places in code to pinpoint the place)
void KWIN_EXPORT checkGLError( const char* txt );
inline bool KWIN_EXPORT isPowerOfTwo( int x ) { return (( x & ( x - 1 )) == 0 ); }
int KWIN_EXPORT nearestPowerOfTwo( int x );
@ -63,6 +66,7 @@ class KWIN_EXPORT GLTexture
GLTexture( const QImage& image, GLenum target = GL_TEXTURE_2D );
GLTexture( const QPixmap& pixmap, GLenum target = GL_TEXTURE_2D );
GLTexture( const QString& fileName );
GLTexture( int width, int height );
virtual ~GLTexture();
bool isNull() const;
@ -145,6 +149,49 @@ class KWIN_EXPORT GLShader
static bool mVertexShaderSupported;
};
/**
* @short Render target object
*
* Render target object enables you to render onto a texture. This texture can
* later be used to e.g. do post-processing of the scene.
*
* @author Rivo Laks <rivolaks@hot.ee>
**/
class KWIN_EXPORT GLRenderTarget
{
public:
/**
* Constructs a GLRenderTarget
* @param color texture where the scene will be rendered onto
**/
GLRenderTarget(GLTexture* color);
~GLRenderTarget();
/**
* Enables this render target.
* All OpenGL commands from now on affect this render target until the
* @ref disable method is called
**/
bool enable();
/**
* Disables this render target, activating whichever target was active
* when @ref enable was called.
**/
bool disable();
bool valid() const { return mValid; }
protected:
void initFBO();
private:
GLTexture* mTexture;
bool mValid;
GLuint mFramebuffer;
};
#endif
} // namespace

View file

@ -97,14 +97,6 @@ XShmSegmentInfo SceneOpenGL::shm;
#endif
// detect OpenGL error (add to various places in code to pinpoint the place)
static void checkGLError( const char* txt )
{
GLenum err = glGetError();
if( err != GL_NO_ERROR )
kWarning() << "GL error (" << txt << "): 0x" << QString::number( err, 16 ) << endl;
}
SceneOpenGL::SceneOpenGL( Workspace* ws )
: Scene( ws )
{