diff --git a/lib/kwinglutils.cpp b/lib/kwinglutils.cpp index 43afde79b3..9f7b8e4517 100644 --- a/lib/kwinglutils.cpp +++ b/lib/kwinglutils.cpp @@ -18,6 +18,7 @@ License. See the file "COPYING" for the exact licensing terms. #include #include #include +#include #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 diff --git a/lib/kwinglutils.h b/lib/kwinglutils.h index 9bc9aaa3bc..bef11250e5 100644 --- a/lib/kwinglutils.h +++ b/lib/kwinglutils.h @@ -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 + **/ +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 diff --git a/scene_opengl.cpp b/scene_opengl.cpp index d2b406c6d9..4d5ddddbb9 100644 --- a/scene_opengl.cpp +++ b/scene_opengl.cpp @@ -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 ) {