Abstract paint clipping into PaintClipper helper class that allows

stacking of clipping regions.
(http://lists.kde.org/?l=kwin&m=120138051215450&w=2)
BUG: 156798


svn path=/trunk/KDE/kdebase/workspace/; revision=779045
This commit is contained in:
Luboš Luňák 2008-02-25 11:32:21 +00:00
parent 73ad1f1adc
commit cff2b0e6cd
19 changed files with 347 additions and 162 deletions

View file

@ -261,7 +261,7 @@ void CoverSwitchEffect::paintScreen( int mask, QRegion region, ScreenPaintData&
frameRect.y() + frameRect.height()*0.1f, frameRect.y() + frameRect.height()*0.1f,
frameRect.height()*0.8f, frameRect.height()*0.8f,
frameRect.height()*0.8f ); frameRect.height()*0.8f );
icon->render( false, region, iconRect); icon->render( region, iconRect);
icon->unbind(); icon->unbind();
glDisable( GL_BLEND ); glDisable( GL_BLEND );
glPopAttrib(); glPopAttrib();

View file

@ -146,11 +146,19 @@ void DesktopGridEffect::paintScreen( int mask, QRegion region, ScreenPaintData&
++desktop ) ++desktop )
{ {
if( desktop != desktop_with_move ) if( desktop != desktop_with_move )
{
PaintClipper pc( desktopRect( desktop, true ));
paintScreenDesktop( desktop, mask, region, data ); paintScreenDesktop( desktop, mask, region, data );
}
} }
// paint the desktop with the window being moved as the last one, i.e. on top of others // paint the desktop with the window being moved as the last one, i.e. on top of others
if( desktop_with_move != -1 ) 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 ); paintScreenDesktop( desktop_with_move, mask, region, data );
}
} }
void DesktopGridEffect::paintScreenDesktop( int desktop, int mask, QRegion region, ScreenPaintData data ) void DesktopGridEffect::paintScreenDesktop( int desktop, int mask, QRegion region, ScreenPaintData data )

View file

@ -363,7 +363,7 @@ void FlipSwitchEffect::paintScreen( int mask, QRegion region, ScreenPaintData& d
frameRect.y() + frameRect.height()*0.1f, frameRect.y() + frameRect.height()*0.1f,
frameRect.height()*0.8f, frameRect.height()*0.8f,
frameRect.height()*0.8f ); frameRect.height()*0.8f );
icon->render( false, region, iconRect); icon->render( region, iconRect);
icon->unbind(); icon->unbind();
glPopAttrib(); glPopAttrib();
#endif #endif

View file

@ -81,13 +81,8 @@ void MagnifierEffect::paintScreen( int mask, QRegion region, ScreenPaintData& da
effects->paintScreen( mask, region, data ); // paint normal screen effects->paintScreen( mask, region, data ); // paint normal screen
if( zoom != 1.0 ) if( zoom != 1.0 )
{ // paint magnifier { // paint magnifier
// ## TODO this should be inside KWIN_HAVE_OPENGL_COMPOSITING
glPushAttrib( GL_ENABLE_BIT );
QRect area = magnifierArea(); QRect area = magnifierArea();
glEnable( GL_SCISSOR_TEST ); PaintClipper::push( area ); // don't allow any painting outside of the area
int dh = displayHeight();
// Scissor rect has to be given in OpenGL coords
glScissor( area.x(), dh - area.y() - area.height(), area.width(), area.height());
mask |= PAINT_SCREEN_TRANSFORMED; mask |= PAINT_SCREEN_TRANSFORMED;
data2.xScale *= zoom; data2.xScale *= zoom;
data2.yScale *= 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.xTranslate = - int( cursor.x() * ( zoom - 1 ));
data2.yTranslate = - int( cursor.y() * ( zoom - 1 )); data2.yTranslate = - int( cursor.y() * ( zoom - 1 ));
effects->paintScreen( mask, region, data2 ); effects->paintScreen( mask, region, data2 );
glPopAttrib(); PaintClipper::pop( area );
// ## TODO this should be inside KWIN_HAVE_OPENGL_COMPOSITING
glPushAttrib( GL_CURRENT_BIT ); glPushAttrib( GL_CURRENT_BIT );
glColor4f( 0, 0, 0, 1 ); // black glColor4f( 0, 0, 0, 1 ); // black
glBegin( GL_QUADS ); for( PaintClipper::Iterator iterator;
glVertex2i( area.left() - FRAME_WIDTH, area.top() - FRAME_WIDTH ); // top frame !iterator.isDone();
glVertex2i( area.right() + FRAME_WIDTH, area.top() - FRAME_WIDTH ); iterator.next())
glVertex2i( area.right() + FRAME_WIDTH, area.top() - 1 ); {
glVertex2i( area.left() - FRAME_WIDTH, area.top() - 1 ); glBegin( GL_QUADS );
glVertex2i( area.left() - FRAME_WIDTH, area.top() - FRAME_WIDTH ); // left frame glVertex2i( area.left() - FRAME_WIDTH, area.top() - FRAME_WIDTH ); // top frame
glVertex2i( area.left() - 1, area.top() - FRAME_WIDTH ); glVertex2i( area.right() + FRAME_WIDTH, area.top() - FRAME_WIDTH );
glVertex2i( area.left() - 1, area.bottom() + FRAME_WIDTH ); glVertex2i( area.right() + FRAME_WIDTH, area.top() - 1 );
glVertex2i( area.left() - FRAME_WIDTH, area.bottom() + FRAME_WIDTH ); glVertex2i( area.left() - FRAME_WIDTH, area.top() - 1 );
glVertex2i( area.right() + 1, area.top() - FRAME_WIDTH ); // right frame glVertex2i( area.left() - FRAME_WIDTH, area.top() - FRAME_WIDTH ); // left frame
glVertex2i( area.right() + FRAME_WIDTH, area.top() - FRAME_WIDTH ); glVertex2i( area.left() - 1, area.top() - FRAME_WIDTH );
glVertex2i( area.right() + FRAME_WIDTH, area.bottom() + FRAME_WIDTH ); glVertex2i( area.left() - 1, area.bottom() + FRAME_WIDTH );
glVertex2i( area.right() + 1, area.bottom() + FRAME_WIDTH ); glVertex2i( area.left() - FRAME_WIDTH, area.bottom() + FRAME_WIDTH );
glVertex2i( area.left() - FRAME_WIDTH, area.bottom() + 1 ); // bottom frame glVertex2i( area.right() + 1, area.top() - FRAME_WIDTH ); // right frame
glVertex2i( area.right() + FRAME_WIDTH, area.bottom() + 1 ); glVertex2i( area.right() + FRAME_WIDTH, area.top() - FRAME_WIDTH );
glVertex2i( area.right() + FRAME_WIDTH, area.bottom() + FRAME_WIDTH ); glVertex2i( area.right() + FRAME_WIDTH, area.bottom() + FRAME_WIDTH );
glVertex2i( area.left() - FRAME_WIDTH, area.bottom() + FRAME_WIDTH ); glVertex2i( area.right() + 1, area.bottom() + FRAME_WIDTH );
glEnd(); 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(); glPopAttrib();
} }
} }

View file

@ -149,7 +149,7 @@ void PresentWindowsEffect::paintScreen( int mask, QRegion region, ScreenPaintDat
renderRoundBoxWithEdge( filterFrameRect ); renderRoundBoxWithEdge( filterFrameRect );
// And then the text on top of it // And then the text on top of it
filterTexture->bind(); filterTexture->bind();
filterTexture->render( mask, region, filterTextureRect ); filterTexture->render( region, filterTextureRect );
filterTexture->unbind(); filterTexture->unbind();
glPopAttrib(); glPopAttrib();
} }

View file

@ -89,7 +89,7 @@ void ShadowEffect::drawWindow( EffectWindow* w, int mask, QRegion region, Window
{ {
// For translucent windows, shadow needs to be drawn before the // For translucent windows, shadow needs to be drawn before the
// window itself. // window itself.
drawShadow( w, mask, region, data, false ); drawShadow( w, mask, region, data );
} }
else else
{ {
@ -145,7 +145,7 @@ void ShadowEffect::drawQueuedShadows( EffectWindow* behindWindow )
// that are behind that window. // that are behind that window.
if( !behindWindow || stack.indexOf(d.w) < stack.indexOf(behindWindow)) 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 else
{ {
@ -155,7 +155,7 @@ void ShadowEffect::drawQueuedShadows( EffectWindow* behindWindow )
shadowDatas = newShadowDatas; 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 ); glPushAttrib( GL_CURRENT_BIT | GL_ENABLE_BIT | GL_TEXTURE_BIT );
glEnable( GL_BLEND ); 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); glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
// We have two elements per vertex in the verts array // We have two elements per vertex in the verts array
int verticesCount = verts.count() / 2; int verticesCount = verts.count() / 2;
if( clip ) renderGLGeometry( region, verticesCount, verts.data(), texcoords.data() );
renderGLGeometry( true, region, verticesCount, verts.data(), texcoords.data() );
else
renderGLGeometry( mask, region, verticesCount, verts.data(), texcoords.data() );
mShadowTexture->unbind(); mShadowTexture->unbind();
glPopMatrix(); glPopMatrix();

View file

@ -40,7 +40,7 @@ class ShadowEffect
virtual void windowClosed( EffectWindow* c ); virtual void windowClosed( EffectWindow* c );
virtual QRect transformWindowDamage( EffectWindow* w, const QRect& r ); virtual QRect transformWindowDamage( EffectWindow* w, const QRect& r );
private: 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<float>& verts, float x1, float y1, float x2, float y2) const; void addQuadVertices(QVector<float>& verts, float x1, float y1, float x2, float y2) const;
// transforms window rect -> shadow rect // transforms window rect -> shadow rect
QRect shadowRectangle(const QRect& windowRectangle) const; QRect shadowRectangle(const QRect& windowRectangle) const;

View file

@ -439,7 +439,7 @@ void ShowFpsEffect::paintFPSText(int fps)
delete fpsText; delete fpsText;
fpsText = new GLTexture(im); fpsText = new GLTexture(im);
fpsText->bind(); fpsText->bind();
fpsText->render(false, QRegion(fpsTextRect), fpsTextRect); fpsText->render(QRegion(fpsTextRect), fpsTextRect);
fpsText->unbind(); fpsText->unbind();
effects->addRepaint(fpsTextRect); effects->addRepaint(fpsTextRect);
#endif #endif

View file

@ -142,7 +142,7 @@ void SnowEffect::paintScreen( int mask, QRegion region, ScreenPaintData& data )
glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA ); glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
for (int i=0; i<flakes->count(); i++) for (int i=0; i<flakes->count(); i++)
{ {
texture->render( false, region, flakes->at(i)); texture->render( region, flakes->at(i));
} }
texture->unbind(); texture->unbind();
glPopAttrib(); glPopAttrib();

View file

@ -77,7 +77,7 @@ void TrackMouseEffect::paintScreen( int mask, QRegion region, ScreenPaintData& d
++i ) ++i )
{ {
QRect r = starRect( i ); QRect r = starRect( i );
texture->render( mask, region, r ); texture->render( region, r );
} }
texture->unbind(); texture->unbind();
glPopAttrib(); glPopAttrib();

View file

@ -677,4 +677,168 @@ bool WindowQuadList::smoothNeeded() const
return false; 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 } // namespace

View file

@ -32,12 +32,17 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#include <QtCore/QVector> #include <QtCore/QVector>
#include <QtCore/QList> #include <QtCore/QList>
#include <QtCore/QHash> #include <QtCore/QHash>
#include <QtCore/QStack>
#include <KDE/KPluginFactory> #include <KDE/KPluginFactory>
#include <KDE/KShortcutsEditor> #include <KDE/KShortcutsEditor>
#include <assert.h> #include <assert.h>
#include <limits.h>
#ifdef KWIN_HAVE_XRENDER_COMPOSITING
#include <X11/extensions/Xfixes.h>
#endif
class KLibrary; class KLibrary;
class KConfigGroup; 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_MAKE_VERSION( major, minor ) (( major ) << 8 | ( minor ))
#define KWIN_EFFECT_API_VERSION_MAJOR 0 #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( \ #define KWIN_EFFECT_API_VERSION KWIN_EFFECT_API_MAKE_VERSION( \
KWIN_EFFECT_API_VERSION_MAJOR, KWIN_EFFECT_API_VERSION_MINOR ) 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 * @short Base class for all KWin effects
* *
@ -822,6 +843,71 @@ class KWIN_EXPORT ScreenPrePaintData
QRegion paint; 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. * Pointer to the global EffectsHandler object.
**/ **/

View file

@ -128,18 +128,10 @@ int nearestPowerOfTwo( int x )
void renderGLGeometry( int count, const float* vertices, const float* texture, const float* color, void renderGLGeometry( int count, const float* vertices, const float* texture, const float* color,
int dim, int stride ) 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, void renderGLGeometry( 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,
const float* vertices, const float* texture, const float* color, const float* vertices, const float* texture, const float* color,
int dim, int stride ) int dim, int stride )
{ {
@ -166,40 +158,17 @@ void renderGLGeometry( bool clip, const QRegion& region, int count,
} }
} }
// Render // Clip using scissoring
if( !clip ) PaintClipper pc( region );
for( PaintClipper::Iterator iterator;
!iterator.isDone();
iterator.next())
{ {
// Just draw the entire window, no clipping
if( use_arrays ) if( use_arrays )
glDrawArrays( GL_QUADS, 0, count ); glDrawArrays( GL_QUADS, 0, count );
else else
renderGLGeometryImmediate( count, vertices, texture, color, dim, stride ); 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 ) if( use_arrays )
{ {
@ -500,13 +469,7 @@ void GLTexture::unbind()
glDisable( mTarget ); glDisable( mTarget );
} }
void GLTexture::render( int mask, QRegion region, const QRect& rect ) void GLTexture::render( 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 )
{ {
const float verts[ 4 * 2 ] = const float verts[ 4 * 2 ] =
{ {
@ -522,7 +485,7 @@ void GLTexture::render( bool clip, QRegion region, const QRect& rect )
1, 0, 1, 0,
1, 1 1, 1
}; };
renderGLGeometry( clip, region, 4, verts, texcoords ); renderGLGeometry( region, 4, verts, texcoords );
} }
void GLTexture::enableUnnormalizedTexCoords() void GLTexture::enableUnnormalizedTexCoords()

View file

@ -82,22 +82,17 @@ int KWIN_EXPORT nearestPowerOfTwo( int x );
* @param stride byte offset of consecutive elements in arrays. If 0, then * @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)! * 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, const float* vertices, const float* texture = 0, const float* color = 0,
int dim = 2, int stride = 0 ); int dim = 2, int stride = 0 );
/** /**
* Same as above, sets clip parameter according to mask. * Same as above, renders without specified region
**/
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
**/ **/
KWIN_EXPORT void renderGLGeometry( int count, KWIN_EXPORT void renderGLGeometry( int count,
const float* vertices, const float* texture = 0, const float* color = 0, const float* vertices, const float* texture = 0, const float* color = 0,
int dim = 2, int stride = 0 ); int dim = 2, int stride = 0 );
KWIN_EXPORT void renderGLGeometryImmediate( int count, KWIN_EXPORT void renderGLGeometryImmediate( int count,
const float* vertices, const float* texture = 0, const float* color = 0, const float* vertices, const float* texture = 0, const float* color = 0,
int dim = 2, int stride = 0 ); int dim = 2, int stride = 0 );
@ -125,8 +120,7 @@ class KWIN_EXPORT GLTexture
virtual void discard(); virtual void discard();
virtual void bind(); virtual void bind();
virtual void unbind(); virtual void unbind();
void render( bool clip, QRegion region, const QRect& rect ); void render( QRegion region, const QRect& rect );
void render( int mask, QRegion region, const QRect& rect );
void enableUnnormalizedTexCoords(); void enableUnnormalizedTexCoords();
void disableUnnormalizedTexCoords(); void disableUnnormalizedTexCoords();

View file

@ -135,6 +135,8 @@ void Scene::paintScreen( int* mask, QRegion* region )
*region |= painted_region; *region |= painted_region;
// make sure not to go outside of the screen area // make sure not to go outside of the screen area
*region &= QRegion( 0, 0, displayWidth(), displayHeight()); *region &= QRegion( 0, 0, displayWidth(), displayHeight());
// make sure all clipping is restored
Q_ASSERT( !PaintClipper::clip());
} }
// Compute time since the last painting pass. // Compute time since the last painting pass.

View file

@ -105,8 +105,6 @@ class Scene
virtual void paintWindow( Window* w, int mask, QRegion region, WindowQuadList quads ); virtual void paintWindow( Window* w, int mask, QRegion region, WindowQuadList quads );
// called after all effects had their drawWindow() called // called after all effects had their drawWindow() called
void finalDrawWindow( EffectWindowImpl* w, int mask, QRegion region, WindowPaintData& data ); void finalDrawWindow( EffectWindowImpl* w, int mask, QRegion region, WindowPaintData& data );
// infinite region, i.e. everything
static QRegion infiniteRegion();
// compute time since the last repaint // compute time since the last repaint
void updateTimeDiff(); void updateTimeDiff();
// saved data for 2nd pass of optimized screen painting // saved data for 2nd pass of optimized screen painting
@ -197,12 +195,6 @@ class Scene::Window
extern Scene* scene; 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 inline
int Scene::Window::x() const int Scene::Window::x() const
{ {

View file

@ -723,22 +723,24 @@ void SceneOpenGL::paintGenericScreen( int mask, ScreenPaintData data )
void SceneOpenGL::paintBackground( QRegion region ) void SceneOpenGL::paintBackground( QRegion region )
{ {
if( region == infiniteRegion()) PaintClipper pc( region );
if( !PaintClipper::clip())
{ {
glClearColor( 0, 0, 0, 1 ); // black glClearColor( 0, 0, 0, 1 ); // black
glClear( GL_COLOR_BUFFER_BIT ); 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 ); glBegin( GL_QUADS );
foreach( QRect r, region.rects()) QRect r = iterator.boundingRect();
{ glVertex2i( r.x(), r.y());
glVertex2i( r.x(), r.y()); glVertex2i( r.x() + r.width(), r.y());
glVertex2i( r.x() + r.width(), r.y()); glVertex2i( r.x() + r.width(), r.y() + r.height());
glVertex2i( r.x() + r.width(), r.y() + r.height()); glVertex2i( r.x(), r.y() + r.height());
glVertex2i( r.x(), r.y() + r.height());
}
glEnd(); glEnd();
} }
} }
@ -1257,7 +1259,7 @@ void SceneOpenGL::Window::performPaint( int mask, QRegion region, WindowPaintDat
glPopMatrix(); 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()) if( quads.isEmpty())
return; return;
@ -1265,7 +1267,7 @@ void SceneOpenGL::Window::renderQuads( int mask, const QRegion& region, const Wi
float* vertices; float* vertices;
float* texcoords; float* texcoords;
quads.makeArrays( &vertices, &texcoords ); quads.makeArrays( &vertices, &texcoords );
renderGLGeometry( mask, region, quads.count() * 4, renderGLGeometry( region, quads.count() * 4,
vertices, texcoords, NULL, 2, 0 ); vertices, texcoords, NULL, 2, 0 );
delete[] vertices; delete[] vertices;
delete[] texcoords; delete[] texcoords;

View file

@ -267,15 +267,14 @@ void SceneXrender::paintTransformedScreen( int orig_mask )
// fill the screen background // fill the screen background
void SceneXrender::paintBackground( QRegion region ) void SceneXrender::paintBackground( QRegion region )
{ {
if( region != infiniteRegion()) PaintClipper pc( region );
for( PaintClipper::Iterator iterator;
!iterator.isDone();
iterator.next())
{ {
XserverRegion background_region = toXserverRegion( region ); XRenderColor col = { 0, 0, 0, 0xffff }; // black
XFixesSetPictureClipRegion( display(), buffer, 0, 0, background_region ); XRenderFillRectangle( display(), PictOpSrc, buffer, &col, 0, 0, displayWidth(), displayHeight());
XFixesDestroyRegion( display(), background_region );
} }
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 ) void SceneXrender::windowGeometryShapeChanged( Toplevel* c )
@ -326,27 +325,6 @@ void SceneXrender::windowAdded( Toplevel* c )
c->effectWindow()->setSceneWindow( windows[ 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 // SceneXrender::Window
//**************************************** //****************************************
@ -451,12 +429,6 @@ void SceneXrender::Window::performPaint( int mask, QRegion region, WindowPaintDa
if( opaque ) if( opaque )
return; 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 Picture pic = picture(); // get XRender picture
if( pic == None ) // The render format can be null for GL and/or Xv visuals if( pic == None ) // The render format can be null for GL and/or Xv visuals
return; return;
@ -522,17 +494,23 @@ void SceneXrender::Window::performPaint( int mask, QRegion region, WindowPaintDa
} }
if( x != toplevel->x() || y != toplevel->y()) if( x != toplevel->x() || y != toplevel->y())
transformed_shape.translate( x, 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, if( opaque )
x, y, width, height); {
} XRenderComposite( display(), PictOpSrc, pic, None, buffer, 0, 0, 0, 0,
else x, y, width, height);
{ }
Picture alpha = alphaMask( data.opacity ); else
XRenderComposite( display(), PictOpOver, pic, alpha, buffer, 0, 0, 0, 0, {
x, y, width, height); Picture alpha = alphaMask( data.opacity );
transformed_shape = QRegion(); XRenderComposite( display(), PictOpOver, pic, alpha, buffer, 0, 0, 0, 0,
x, y, width, height);
transformed_shape = QRegion();
}
} }
if( xscale != 1 || yscale != 1 ) if( xscale != 1 || yscale != 1 )
{ {
@ -545,7 +523,6 @@ void SceneXrender::Window::performPaint( int mask, QRegion region, WindowPaintDa
if( filter == ImageFilterGood ) if( filter == ImageFilterGood )
XRenderSetPictureFilter( display(), pic, const_cast< char* >( "fast" ), NULL, 0 ); XRenderSetPictureFilter( display(), pic, const_cast< char* >( "fast" ), NULL, 0 );
} }
XFixesSetPictureClipRegion( display(), buffer, 0, 0, None );
} }
} // namespace } // namespace

View file

@ -54,7 +54,6 @@ class SceneXrender
private: private:
void paintTransformedScreen( int mask ); void paintTransformedScreen( int mask );
void createBuffer(); void createBuffer();
static XserverRegion toXserverRegion( QRegion region );
XRenderPictFormat* format; XRenderPictFormat* format;
Picture front; Picture front;
static Picture buffer; static Picture buffer;