diff --git a/effects/coverswitch.cpp b/effects/coverswitch.cpp index a4643f6b72..562445107b 100644 --- a/effects/coverswitch.cpp +++ b/effects/coverswitch.cpp @@ -261,7 +261,7 @@ void CoverSwitchEffect::paintScreen( int mask, QRegion region, ScreenPaintData& frameRect.y() + frameRect.height()*0.1f, frameRect.height()*0.8f, frameRect.height()*0.8f ); - icon->render( false, region, iconRect); + icon->render( region, iconRect); icon->unbind(); glDisable( GL_BLEND ); glPopAttrib(); diff --git a/effects/desktopgrid.cpp b/effects/desktopgrid.cpp index 8bddc442c0..8bb5b99e9e 100644 --- a/effects/desktopgrid.cpp +++ b/effects/desktopgrid.cpp @@ -146,11 +146,19 @@ void DesktopGridEffect::paintScreen( int mask, QRegion region, ScreenPaintData& ++desktop ) { if( desktop != desktop_with_move ) + { + PaintClipper pc( desktopRect( desktop, true )); paintScreenDesktop( desktop, mask, region, data ); + } } // paint the desktop with the window being moved as the last one, i.e. on top of others if( desktop_with_move != -1 ) + { + QRegion paintreg = desktopRect( desktop_with_move, true ); // paint only the desktop + paintreg |= windowRect( window_move ); // and wherever the moved window is + PaintClipper pc( paintreg ); paintScreenDesktop( desktop_with_move, mask, region, data ); + } } void DesktopGridEffect::paintScreenDesktop( int desktop, int mask, QRegion region, ScreenPaintData data ) diff --git a/effects/flipswitch.cpp b/effects/flipswitch.cpp index 3664323a6d..b94ce44385 100644 --- a/effects/flipswitch.cpp +++ b/effects/flipswitch.cpp @@ -363,7 +363,7 @@ void FlipSwitchEffect::paintScreen( int mask, QRegion region, ScreenPaintData& d frameRect.y() + frameRect.height()*0.1f, frameRect.height()*0.8f, frameRect.height()*0.8f ); - icon->render( false, region, iconRect); + icon->render( region, iconRect); icon->unbind(); glPopAttrib(); #endif diff --git a/effects/magnifier.cpp b/effects/magnifier.cpp index 0b91dd5a88..430a1e6b46 100644 --- a/effects/magnifier.cpp +++ b/effects/magnifier.cpp @@ -81,13 +81,8 @@ void MagnifierEffect::paintScreen( int mask, QRegion region, ScreenPaintData& da effects->paintScreen( mask, region, data ); // paint normal screen if( zoom != 1.0 ) { // paint magnifier -// ## TODO this should be inside KWIN_HAVE_OPENGL_COMPOSITING - glPushAttrib( GL_ENABLE_BIT ); QRect area = magnifierArea(); - glEnable( GL_SCISSOR_TEST ); - int dh = displayHeight(); - // Scissor rect has to be given in OpenGL coords - glScissor( area.x(), dh - area.y() - area.height(), area.width(), area.height()); + PaintClipper::push( area ); // don't allow any painting outside of the area mask |= PAINT_SCREEN_TRANSFORMED; data2.xScale *= zoom; data2.yScale *= zoom; @@ -96,27 +91,33 @@ void MagnifierEffect::paintScreen( int mask, QRegion region, ScreenPaintData& da data2.xTranslate = - int( cursor.x() * ( zoom - 1 )); data2.yTranslate = - int( cursor.y() * ( zoom - 1 )); effects->paintScreen( mask, region, data2 ); - glPopAttrib(); + PaintClipper::pop( area ); +// ## TODO this should be inside KWIN_HAVE_OPENGL_COMPOSITING glPushAttrib( GL_CURRENT_BIT ); glColor4f( 0, 0, 0, 1 ); // black - glBegin( GL_QUADS ); - glVertex2i( area.left() - FRAME_WIDTH, area.top() - FRAME_WIDTH ); // top frame - glVertex2i( area.right() + FRAME_WIDTH, area.top() - FRAME_WIDTH ); - glVertex2i( area.right() + FRAME_WIDTH, area.top() - 1 ); - glVertex2i( area.left() - FRAME_WIDTH, area.top() - 1 ); - glVertex2i( area.left() - FRAME_WIDTH, area.top() - FRAME_WIDTH ); // left frame - glVertex2i( area.left() - 1, area.top() - FRAME_WIDTH ); - glVertex2i( area.left() - 1, area.bottom() + FRAME_WIDTH ); - glVertex2i( area.left() - FRAME_WIDTH, area.bottom() + FRAME_WIDTH ); - glVertex2i( area.right() + 1, area.top() - FRAME_WIDTH ); // right frame - glVertex2i( area.right() + FRAME_WIDTH, area.top() - FRAME_WIDTH ); - glVertex2i( area.right() + FRAME_WIDTH, area.bottom() + FRAME_WIDTH ); - glVertex2i( area.right() + 1, area.bottom() + FRAME_WIDTH ); - glVertex2i( area.left() - FRAME_WIDTH, area.bottom() + 1 ); // bottom frame - glVertex2i( area.right() + FRAME_WIDTH, area.bottom() + 1 ); - glVertex2i( area.right() + FRAME_WIDTH, area.bottom() + FRAME_WIDTH ); - glVertex2i( area.left() - FRAME_WIDTH, area.bottom() + FRAME_WIDTH ); - glEnd(); + for( PaintClipper::Iterator iterator; + !iterator.isDone(); + iterator.next()) + { + glBegin( GL_QUADS ); + glVertex2i( area.left() - FRAME_WIDTH, area.top() - FRAME_WIDTH ); // top frame + glVertex2i( area.right() + FRAME_WIDTH, area.top() - FRAME_WIDTH ); + glVertex2i( area.right() + FRAME_WIDTH, area.top() - 1 ); + glVertex2i( area.left() - FRAME_WIDTH, area.top() - 1 ); + glVertex2i( area.left() - FRAME_WIDTH, area.top() - FRAME_WIDTH ); // left frame + glVertex2i( area.left() - 1, area.top() - FRAME_WIDTH ); + glVertex2i( area.left() - 1, area.bottom() + FRAME_WIDTH ); + glVertex2i( area.left() - FRAME_WIDTH, area.bottom() + FRAME_WIDTH ); + glVertex2i( area.right() + 1, area.top() - FRAME_WIDTH ); // right frame + glVertex2i( area.right() + FRAME_WIDTH, area.top() - FRAME_WIDTH ); + glVertex2i( area.right() + FRAME_WIDTH, area.bottom() + FRAME_WIDTH ); + glVertex2i( area.right() + 1, area.bottom() + FRAME_WIDTH ); + glVertex2i( area.left() - FRAME_WIDTH, area.bottom() + 1 ); // bottom frame + glVertex2i( area.right() + FRAME_WIDTH, area.bottom() + 1 ); + glVertex2i( area.right() + FRAME_WIDTH, area.bottom() + FRAME_WIDTH ); + glVertex2i( area.left() - FRAME_WIDTH, area.bottom() + FRAME_WIDTH ); + glEnd(); + } glPopAttrib(); } } diff --git a/effects/presentwindows.cpp b/effects/presentwindows.cpp index 3665d1b361..6412f3f72b 100644 --- a/effects/presentwindows.cpp +++ b/effects/presentwindows.cpp @@ -149,7 +149,7 @@ void PresentWindowsEffect::paintScreen( int mask, QRegion region, ScreenPaintDat renderRoundBoxWithEdge( filterFrameRect ); // And then the text on top of it filterTexture->bind(); - filterTexture->render( mask, region, filterTextureRect ); + filterTexture->render( region, filterTextureRect ); filterTexture->unbind(); glPopAttrib(); } diff --git a/effects/shadow.cpp b/effects/shadow.cpp index be016fe431..dbac01d9c0 100644 --- a/effects/shadow.cpp +++ b/effects/shadow.cpp @@ -89,7 +89,7 @@ void ShadowEffect::drawWindow( EffectWindow* w, int mask, QRegion region, Window { // For translucent windows, shadow needs to be drawn before the // window itself. - drawShadow( w, mask, region, data, false ); + drawShadow( w, mask, region, data ); } else { @@ -145,7 +145,7 @@ void ShadowEffect::drawQueuedShadows( EffectWindow* behindWindow ) // that are behind that window. if( !behindWindow || stack.indexOf(d.w) < stack.indexOf(behindWindow)) { - drawShadow( d.w, d.mask, d.region.subtracted( d.clip ), d.data, true ); + drawShadow( d.w, d.mask, d.region.subtracted( d.clip ), d.data ); } else { @@ -155,7 +155,7 @@ void ShadowEffect::drawQueuedShadows( EffectWindow* behindWindow ) shadowDatas = newShadowDatas; } -void ShadowEffect::drawShadow( EffectWindow* window, int mask, QRegion region, WindowPaintData& data, bool clip ) +void ShadowEffect::drawShadow( EffectWindow* window, int mask, QRegion region, WindowPaintData& data ) { glPushAttrib( GL_CURRENT_BIT | GL_ENABLE_BIT | GL_TEXTURE_BIT ); glEnable( GL_BLEND ); @@ -219,10 +219,7 @@ void ShadowEffect::drawShadow( EffectWindow* window, int mask, QRegion region, W glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); // We have two elements per vertex in the verts array int verticesCount = verts.count() / 2; - if( clip ) - renderGLGeometry( true, region, verticesCount, verts.data(), texcoords.data() ); - else - renderGLGeometry( mask, region, verticesCount, verts.data(), texcoords.data() ); + renderGLGeometry( region, verticesCount, verts.data(), texcoords.data() ); mShadowTexture->unbind(); glPopMatrix(); diff --git a/effects/shadow.h b/effects/shadow.h index 84c63c855a..24e1b0ef9f 100644 --- a/effects/shadow.h +++ b/effects/shadow.h @@ -40,7 +40,7 @@ class ShadowEffect virtual void windowClosed( EffectWindow* c ); virtual QRect transformWindowDamage( EffectWindow* w, const QRect& r ); private: - void drawShadow( EffectWindow* w, int mask, QRegion region, WindowPaintData& data, bool clip ); + void drawShadow( EffectWindow* w, int mask, QRegion region, WindowPaintData& data ); void addQuadVertices(QVector& verts, float x1, float y1, float x2, float y2) const; // transforms window rect -> shadow rect QRect shadowRectangle(const QRect& windowRectangle) const; diff --git a/effects/showfps.cpp b/effects/showfps.cpp index 256c077da6..db73faf373 100644 --- a/effects/showfps.cpp +++ b/effects/showfps.cpp @@ -439,7 +439,7 @@ void ShowFpsEffect::paintFPSText(int fps) delete fpsText; fpsText = new GLTexture(im); fpsText->bind(); - fpsText->render(false, QRegion(fpsTextRect), fpsTextRect); + fpsText->render(QRegion(fpsTextRect), fpsTextRect); fpsText->unbind(); effects->addRepaint(fpsTextRect); #endif diff --git a/effects/snow.cpp b/effects/snow.cpp index b240dcda03..8efe401f90 100644 --- a/effects/snow.cpp +++ b/effects/snow.cpp @@ -142,7 +142,7 @@ void SnowEffect::paintScreen( int mask, QRegion region, ScreenPaintData& data ) glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA ); for (int i=0; icount(); i++) { - texture->render( false, region, flakes->at(i)); + texture->render( region, flakes->at(i)); } texture->unbind(); glPopAttrib(); diff --git a/effects/trackmouse.cpp b/effects/trackmouse.cpp index 6b860b9df3..25fef5cf34 100644 --- a/effects/trackmouse.cpp +++ b/effects/trackmouse.cpp @@ -77,7 +77,7 @@ void TrackMouseEffect::paintScreen( int mask, QRegion region, ScreenPaintData& d ++i ) { QRect r = starRect( i ); - texture->render( mask, region, r ); + texture->render( region, r ); } texture->unbind(); glPopAttrib(); diff --git a/lib/kwineffects.cpp b/lib/kwineffects.cpp index 3f4d8e58f5..7d1d6b0632 100644 --- a/lib/kwineffects.cpp +++ b/lib/kwineffects.cpp @@ -677,4 +677,168 @@ bool WindowQuadList::smoothNeeded() const return false; } +/*************************************************************** + PaintClipper +***************************************************************/ + +QStack< QRegion >* PaintClipper::areas = NULL; + +PaintClipper::PaintClipper( const QRegion& allowed_area ) + : area( allowed_area ) + { + push( area ); + } + +PaintClipper::~PaintClipper() + { + pop( area ); + } + +void PaintClipper::push( const QRegion& allowed_area ) + { + if( allowed_area == infiniteRegion()) // don't push these + return; + if( areas == NULL ) + areas = new QStack< QRegion >; + areas->push( allowed_area ); + } + +void PaintClipper::pop( const QRegion& allowed_area ) + { + if( allowed_area == infiniteRegion()) + return; + Q_ASSERT( areas != NULL ); + Q_ASSERT( areas->top() == allowed_area ); + areas->pop(); + if( areas->isEmpty()) + { + delete areas; + areas = NULL; + } + } + +bool PaintClipper::clip() + { + return areas != NULL; + } + +QRegion PaintClipper::paintArea() + { + QRegion ret = QRegion( 0, 0, displayWidth(), displayHeight()); + foreach( QRegion r, *areas ) + ret &= r; + return ret; + } + +struct PaintClipper::Iterator::Data + { + Data() : index( 0 ) {} + int index; +#ifdef KWIN_HAVE_OPENGL_COMPOSITING + QVector< QRect > rects; +#endif + }; + +PaintClipper::Iterator::Iterator() + : data( new Data ) + { +#ifdef KWIN_HAVE_OPENGL_COMPOSITING + if( clip() && effects->compositingType() == OpenGLCompositing ) + { + glPushAttrib( GL_SCISSOR_BIT ); + glEnable( GL_SCISSOR_TEST ); + data->rects = paintArea().rects(); + data->index = -1; + next(); // move to the first one + } +#endif +#ifdef KWIN_HAVE_XRENDER_COMPOSITING + if( clip() && effects->compositingType() == XRenderCompositing ) + { + XserverRegion region = toXserverRegion( paintArea()); + XFixesSetPictureClipRegion( display(), effects->xrenderBufferPicture(), 0, 0, region ); + XFixesDestroyRegion( display(), region ); // it's ref-counted + } +#endif + } + +PaintClipper::Iterator::~Iterator() + { +#ifdef KWIN_HAVE_OPENGL_COMPOSITING + if( clip() && effects->compositingType() == OpenGLCompositing ) + glPopAttrib(); +#endif +#ifdef KWIN_HAVE_XRENDER_COMPOSITING + if( clip() && effects->compositingType() == XRenderCompositing ) + XFixesSetPictureClipRegion( display(), effects->xrenderBufferPicture(), 0, 0, None ); +#endif + delete data; + } + +bool PaintClipper::Iterator::isDone() + { + if( !clip()) + return data->index == 1; // run once +#ifdef KWIN_HAVE_OPENGL_COMPOSITING + if( effects->compositingType() == OpenGLCompositing ) + return data->index >= data->rects.count(); // run once per each area +#endif +#ifdef KWIN_HAVE_XRENDER_COMPOSITING + if( effects->compositingType() == XRenderCompositing ) + return data->index == 1; // run once +#endif + assert( false ); + } + +void PaintClipper::Iterator::next() + { + data->index++; +#ifdef KWIN_HAVE_OPENGL_COMPOSITING + if( clip() && effects->compositingType() == OpenGLCompositing && data->index < data->rects.count()) + { + const QRect& r = data->rects[ data->index ]; + // Scissor rect has to be given in OpenGL coords + glScissor( r.x(), displayHeight() - r.y() - r.height(), r.width(), r.height()); + } +#endif + } + +QRect PaintClipper::Iterator::boundingRect() const + { + if( !clip()) + return infiniteRegion(); +#ifdef KWIN_HAVE_OPENGL_COMPOSITING + if( effects->compositingType() == OpenGLCompositing ) + return data->rects[ data->index ]; +#endif +#ifdef KWIN_HAVE_XRENDER_COMPOSITING + if( effects->compositingType() == XRenderCompositing ) + return paintArea().boundingRect(); +#endif + assert( false ); + } + + +// Convert QRegion to XserverRegion. All code uses XserverRegion +// only when really necessary as the shared implementation uses +// QRegion. +XserverRegion toXserverRegion( QRegion region ) + { + QVector< QRect > rects = region.rects(); + XRectangle* xr = new XRectangle[ rects.count() ]; + for( int i = 0; + i < rects.count(); + ++i ) + { + xr[ i ].x = rects[ i ].x(); + xr[ i ].y = rects[ i ].y(); + xr[ i ].width = rects[ i ].width(); + xr[ i ].height = rects[ i ].height(); + } + XserverRegion ret = XFixesCreateRegion( display(), xr, rects.count()); + delete[] xr; + return ret; + } + + } // namespace diff --git a/lib/kwineffects.h b/lib/kwineffects.h index 3871591666..6b98f6511f 100644 --- a/lib/kwineffects.h +++ b/lib/kwineffects.h @@ -32,12 +32,17 @@ along with this program. If not, see . #include #include #include +#include #include #include #include +#include +#ifdef KWIN_HAVE_XRENDER_COMPOSITING +#include +#endif class KLibrary; class KConfigGroup; @@ -160,10 +165,26 @@ X-KDE-Library=kwin4_effect_cooleffect #define KWIN_EFFECT_API_MAKE_VERSION( major, minor ) (( major ) << 8 | ( minor )) #define KWIN_EFFECT_API_VERSION_MAJOR 0 -#define KWIN_EFFECT_API_VERSION_MINOR 6 +#define KWIN_EFFECT_API_VERSION_MINOR 7 #define KWIN_EFFECT_API_VERSION KWIN_EFFECT_API_MAKE_VERSION( \ KWIN_EFFECT_API_VERSION_MAJOR, KWIN_EFFECT_API_VERSION_MINOR ) +/** + * Infinite region (i.e. a special region type saying that everything needs to be painted). + */ +KWIN_EXPORT inline +QRect infiniteRegion() + { // INT_MIN / 2 because width/height is used (INT_MIN+INT_MAX==-1) + return QRect( INT_MIN / 2, INT_MIN / 2, INT_MAX, INT_MAX ); + } + +#ifdef KWIN_HAVE_XRENDER_COMPOSITING +/** + * Convert QRegion to XserverRegion. + */ +KWIN_EXPORT XserverRegion toXserverRegion( QRegion region ); +#endif + /** * @short Base class for all KWin effects * @@ -822,6 +843,71 @@ class KWIN_EXPORT ScreenPrePaintData QRegion paint; }; +/** + * @short Helper class for restricting painting area only to allowed area. + * + * This helper class helps specifying areas that should be painted, clipping + * out the rest. The simplest usage is creating an object on the stack + * and giving it the area that is allowed to be painted to. When the object + * is destroyed, the restriction will be removed. + * Note that all painting code must use paintArea() to actually perform the clipping. + */ +class KWIN_EXPORT PaintClipper + { + public: + /** + * Calls push(). + */ + PaintClipper( const QRegion& allowed_area ); + /** + * Calls pop(). + */ + ~PaintClipper(); + /** + * Allows painting only in the given area. When areas have been already + * specified, painting is allowed only in the intersection of all areas. + */ + static void push( const QRegion& allowed_area ); + /** + * Removes the given area. It must match the top item in the stack. + */ + static void pop( const QRegion& allowed_area ); + /** + * Returns true if any clipping should be performed. + */ + static bool clip(); + /** + * If clip() returns true, this function gives the resulting area in which + * painting is allowed. It is usually simpler to use the helper Iterator class. + */ + static QRegion paintArea(); + /** + * Helper class to perform the clipped painting. The usage is: + * @code + * for( PaintClipper::Iterator iterator; + * !iterator.isDone(); + * iterator.next()) + * { // do the painting, possibly use iterator.boundingRect() + * } + * @endcode + */ + class Iterator + { + public: + Iterator(); + ~Iterator(); + bool isDone(); + void next(); + QRect boundingRect() const; + private: + struct Data; + Data* data; + }; + private: + QRegion area; + static QStack< QRegion >* areas; + }; + /** * Pointer to the global EffectsHandler object. **/ diff --git a/lib/kwinglutils.cpp b/lib/kwinglutils.cpp index afc4a9d491..0d047ce4fb 100644 --- a/lib/kwinglutils.cpp +++ b/lib/kwinglutils.cpp @@ -128,18 +128,10 @@ int nearestPowerOfTwo( int x ) void renderGLGeometry( int count, const float* vertices, const float* texture, const float* color, int dim, int stride ) { - return renderGLGeometry( false, QRegion(), count, vertices, texture, color, dim, stride ); + return renderGLGeometry( infiniteRegion(), count, vertices, texture, color, dim, stride ); } -void renderGLGeometry( int mask, const QRegion& region, int count, - const float* vertices, const float* texture, const float* color, - int dim, int stride ) - { - return renderGLGeometry( !( mask & ( Effect::PAINT_WINDOW_TRANSFORMED | Effect::PAINT_SCREEN_TRANSFORMED )), - region, count, vertices, texture, color, dim, stride ); - } - -void renderGLGeometry( bool clip, const QRegion& region, int count, +void renderGLGeometry( const QRegion& region, int count, const float* vertices, const float* texture, const float* color, int dim, int stride ) { @@ -166,40 +158,17 @@ void renderGLGeometry( bool clip, const QRegion& region, int count, } } - // Render - if( !clip ) + // Clip using scissoring + PaintClipper pc( region ); + for( PaintClipper::Iterator iterator; + !iterator.isDone(); + iterator.next()) { - // Just draw the entire window, no clipping if( use_arrays ) glDrawArrays( GL_QUADS, 0, count ); else renderGLGeometryImmediate( count, vertices, texture, color, dim, stride ); } - else - { - // Make sure there's only a single quad (no transformed vertices) - // Clip using scissoring - glEnable( GL_SCISSOR_TEST ); - int dh = displayHeight(); - if( use_arrays ) - { - foreach( QRect r, region.rects()) - { - // Scissor rect has to be given in OpenGL coords - glScissor(r.x(), dh - r.y() - r.height(), r.width(), r.height()); - glDrawArrays( GL_QUADS, 0, count ); - } - } - else - { - foreach( QRect r, region.rects()) - { - // Scissor rect has to be given in OpenGL coords - glScissor(r.x(), dh - r.y() - r.height(), r.width(), r.height()); - renderGLGeometryImmediate( count, vertices, texture, color, dim, stride ); - } - } - } if( use_arrays ) { @@ -500,13 +469,7 @@ void GLTexture::unbind() glDisable( mTarget ); } -void GLTexture::render( int mask, QRegion region, const QRect& rect ) - { - return render( !( mask & ( Effect::PAINT_WINDOW_TRANSFORMED | Effect::PAINT_SCREEN_TRANSFORMED )), - region, rect ); - } - -void GLTexture::render( bool clip, QRegion region, const QRect& rect ) +void GLTexture::render( QRegion region, const QRect& rect ) { const float verts[ 4 * 2 ] = { @@ -522,7 +485,7 @@ void GLTexture::render( bool clip, QRegion region, const QRect& rect ) 1, 0, 1, 1 }; - renderGLGeometry( clip, region, 4, verts, texcoords ); + renderGLGeometry( region, 4, verts, texcoords ); } void GLTexture::enableUnnormalizedTexCoords() diff --git a/lib/kwinglutils.h b/lib/kwinglutils.h index 0ffc53ec6d..96ed9037c7 100644 --- a/lib/kwinglutils.h +++ b/lib/kwinglutils.h @@ -82,22 +82,17 @@ int KWIN_EXPORT nearestPowerOfTwo( int x ); * @param stride byte offset of consecutive elements in arrays. If 0, then * arrays must be tighly packed. Stride must be a multiple of sizeof(float)! **/ -KWIN_EXPORT void renderGLGeometry( bool clip, const QRegion& region, int count, +KWIN_EXPORT void renderGLGeometry( const QRegion& region, int count, const float* vertices, const float* texture = 0, const float* color = 0, int dim = 2, int stride = 0 ); /** - * Same as above, sets clip parameter according to mask. - **/ -KWIN_EXPORT void renderGLGeometry( int mask, const QRegion& region, int count, - const float* vertices, const float* texture = 0, const float* color = 0, - int dim = 2, int stride = 0 ); -/** - * Same as above, renders without clipping + * Same as above, renders without specified region **/ KWIN_EXPORT void renderGLGeometry( int count, const float* vertices, const float* texture = 0, const float* color = 0, int dim = 2, int stride = 0 ); + KWIN_EXPORT void renderGLGeometryImmediate( int count, const float* vertices, const float* texture = 0, const float* color = 0, int dim = 2, int stride = 0 ); @@ -125,8 +120,7 @@ class KWIN_EXPORT GLTexture virtual void discard(); virtual void bind(); virtual void unbind(); - void render( bool clip, QRegion region, const QRect& rect ); - void render( int mask, QRegion region, const QRect& rect ); + void render( QRegion region, const QRect& rect ); void enableUnnormalizedTexCoords(); void disableUnnormalizedTexCoords(); diff --git a/scene.cpp b/scene.cpp index 0848122258..bab07ccaa0 100644 --- a/scene.cpp +++ b/scene.cpp @@ -135,6 +135,8 @@ void Scene::paintScreen( int* mask, QRegion* region ) *region |= painted_region; // make sure not to go outside of the screen area *region &= QRegion( 0, 0, displayWidth(), displayHeight()); + // make sure all clipping is restored + Q_ASSERT( !PaintClipper::clip()); } // Compute time since the last painting pass. diff --git a/scene.h b/scene.h index a5b0c70d6f..870ec32a67 100644 --- a/scene.h +++ b/scene.h @@ -105,8 +105,6 @@ class Scene virtual void paintWindow( Window* w, int mask, QRegion region, WindowQuadList quads ); // called after all effects had their drawWindow() called void finalDrawWindow( EffectWindowImpl* w, int mask, QRegion region, WindowPaintData& data ); - // infinite region, i.e. everything - static QRegion infiniteRegion(); // compute time since the last repaint void updateTimeDiff(); // saved data for 2nd pass of optimized screen painting @@ -197,12 +195,6 @@ class Scene::Window extern Scene* scene; -inline -QRegion Scene::infiniteRegion() - { // INT_MIN / 2 because width/height is used (INT_MIN+INT_MAX==-1) - return QRegion( INT_MIN / 2, INT_MIN / 2, INT_MAX, INT_MAX ); - } - inline int Scene::Window::x() const { diff --git a/scene_opengl.cpp b/scene_opengl.cpp index 4376b164a7..821b36071e 100644 --- a/scene_opengl.cpp +++ b/scene_opengl.cpp @@ -723,22 +723,24 @@ void SceneOpenGL::paintGenericScreen( int mask, ScreenPaintData data ) void SceneOpenGL::paintBackground( QRegion region ) { - if( region == infiniteRegion()) + PaintClipper pc( region ); + if( !PaintClipper::clip()) { glClearColor( 0, 0, 0, 1 ); // black glClear( GL_COLOR_BUFFER_BIT ); + return; } - else + glColor4f( 0, 0, 0, 1 ); // black + for( PaintClipper::Iterator iterator; + !iterator.isDone(); + iterator.next()) { - glColor4f( 0, 0, 0, 1 ); // black glBegin( GL_QUADS ); - foreach( QRect r, region.rects()) - { - glVertex2i( r.x(), r.y()); - glVertex2i( r.x() + r.width(), r.y()); - glVertex2i( r.x() + r.width(), r.y() + r.height()); - glVertex2i( r.x(), r.y() + r.height()); - } + QRect r = iterator.boundingRect(); + glVertex2i( r.x(), r.y()); + glVertex2i( r.x() + r.width(), r.y()); + glVertex2i( r.x() + r.width(), r.y() + r.height()); + glVertex2i( r.x(), r.y() + r.height()); glEnd(); } } @@ -1257,7 +1259,7 @@ void SceneOpenGL::Window::performPaint( int mask, QRegion region, WindowPaintDat glPopMatrix(); } -void SceneOpenGL::Window::renderQuads( int mask, const QRegion& region, const WindowQuadList& quads ) +void SceneOpenGL::Window::renderQuads( int, const QRegion& region, const WindowQuadList& quads ) { if( quads.isEmpty()) return; @@ -1265,7 +1267,7 @@ void SceneOpenGL::Window::renderQuads( int mask, const QRegion& region, const Wi float* vertices; float* texcoords; quads.makeArrays( &vertices, &texcoords ); - renderGLGeometry( mask, region, quads.count() * 4, + renderGLGeometry( region, quads.count() * 4, vertices, texcoords, NULL, 2, 0 ); delete[] vertices; delete[] texcoords; diff --git a/scene_xrender.cpp b/scene_xrender.cpp index c392d98772..7432a75958 100644 --- a/scene_xrender.cpp +++ b/scene_xrender.cpp @@ -267,15 +267,14 @@ void SceneXrender::paintTransformedScreen( int orig_mask ) // fill the screen background void SceneXrender::paintBackground( QRegion region ) { - if( region != infiniteRegion()) + PaintClipper pc( region ); + for( PaintClipper::Iterator iterator; + !iterator.isDone(); + iterator.next()) { - XserverRegion background_region = toXserverRegion( region ); - XFixesSetPictureClipRegion( display(), buffer, 0, 0, background_region ); - XFixesDestroyRegion( display(), background_region ); + XRenderColor col = { 0, 0, 0, 0xffff }; // black + XRenderFillRectangle( display(), PictOpSrc, buffer, &col, 0, 0, displayWidth(), displayHeight()); } - XRenderColor col = { 0, 0, 0, 0xffff }; // black - XRenderFillRectangle( display(), PictOpSrc, buffer, &col, 0, 0, displayWidth(), displayHeight()); - XFixesSetPictureClipRegion( display(), buffer, 0, 0, None ); } void SceneXrender::windowGeometryShapeChanged( Toplevel* c ) @@ -326,27 +325,6 @@ void SceneXrender::windowAdded( Toplevel* c ) c->effectWindow()->setSceneWindow( windows[ c ]); } -// Convert QRegion to XserverRegion. This code uses XserverRegion -// only when really necessary as the shared implementation uses -// QRegion. -XserverRegion SceneXrender::toXserverRegion( QRegion region ) - { - QVector< QRect > rects = region.rects(); - XRectangle* xr = new XRectangle[ rects.count() ]; - for( int i = 0; - i < rects.count(); - ++i ) - { - xr[ i ].x = rects[ i ].x(); - xr[ i ].y = rects[ i ].y(); - xr[ i ].width = rects[ i ].width(); - xr[ i ].height = rects[ i ].height(); - } - XserverRegion ret = XFixesCreateRegion( display(), xr, rects.count()); - delete[] xr; - return ret; - } - //**************************************** // SceneXrender::Window //**************************************** @@ -451,12 +429,6 @@ void SceneXrender::Window::performPaint( int mask, QRegion region, WindowPaintDa if( opaque ) return; } - if( region != infiniteRegion()) - { - XserverRegion clip_region = toXserverRegion( region ); - XFixesSetPictureClipRegion( display(), buffer, 0, 0, clip_region ); - XFixesDestroyRegion( display(), clip_region ); - } Picture pic = picture(); // get XRender picture if( pic == None ) // The render format can be null for GL and/or Xv visuals return; @@ -522,17 +494,23 @@ void SceneXrender::Window::performPaint( int mask, QRegion region, WindowPaintDa } if( x != toplevel->x() || y != toplevel->y()) transformed_shape.translate( x, y ); - if( opaque ) + PaintClipper pc( region ); + for( PaintClipper::Iterator iterator; + !iterator.isDone(); + iterator.next()) { - XRenderComposite( display(), PictOpSrc, pic, None, buffer, 0, 0, 0, 0, - x, y, width, height); - } - else - { - Picture alpha = alphaMask( data.opacity ); - XRenderComposite( display(), PictOpOver, pic, alpha, buffer, 0, 0, 0, 0, - x, y, width, height); - transformed_shape = QRegion(); + if( opaque ) + { + XRenderComposite( display(), PictOpSrc, pic, None, buffer, 0, 0, 0, 0, + x, y, width, height); + } + else + { + Picture alpha = alphaMask( data.opacity ); + XRenderComposite( display(), PictOpOver, pic, alpha, buffer, 0, 0, 0, 0, + x, y, width, height); + transformed_shape = QRegion(); + } } if( xscale != 1 || yscale != 1 ) { @@ -545,7 +523,6 @@ void SceneXrender::Window::performPaint( int mask, QRegion region, WindowPaintDa if( filter == ImageFilterGood ) XRenderSetPictureFilter( display(), pic, const_cast< char* >( "fast" ), NULL, 0 ); } - XFixesSetPictureClipRegion( display(), buffer, 0, 0, None ); } } // namespace diff --git a/scene_xrender.h b/scene_xrender.h index 854bb48711..5492e41cd7 100644 --- a/scene_xrender.h +++ b/scene_xrender.h @@ -54,7 +54,6 @@ class SceneXrender private: void paintTransformedScreen( int mask ); void createBuffer(); - static XserverRegion toXserverRegion( QRegion region ); XRenderPictFormat* format; Picture front; static Picture buffer;