kwin: simplifying paintSimpleScreen

This patch reduces the number of QRegion and WindowQuadList operations
by drawing the opaque and translucent parts of the window within the
same bottom to top pass.

REVIEW: 103671
icc-effect-5.14.5
Philipp Knechtges 2012-01-10 18:56:14 +01:00
parent 6b52a4ef19
commit 050d991cb1
5 changed files with 44 additions and 76 deletions

View File

@ -311,10 +311,7 @@ public:
* Clear whole background as the very first step, without optimizing it
**/
PAINT_SCREEN_BACKGROUND_FIRST = 1 << 6,
/**
* Temporary solution since (_OPAQUE | _TRANSLUCENT) is not working currently.
**/
PAINT_DECORATION_ONLY = 1 << 7,
// PAINT_DECORATION_ONLY = 1 << 7 has been deprecated
/**
* Window will be painted with a lanczos filter.
**/

View File

@ -254,7 +254,7 @@ void Scene::paintSimpleScreen(int orig_mask, QRegion region)
| PAINT_SCREEN_WITH_TRANSFORMED_WINDOWS
| PAINT_SCREEN_WITH_TRANSFORMED_WINDOWS_WITHOUT_FULL_REPAINTS
| PAINT_WINDOW_TRANSLUCENT | PAINT_WINDOW_OPAQUE)) == 0);
QHash< Window*, Phase2Data > phase2data;
QList< QPair< Window*, Phase2Data > > phase2data;
QRegion dirtyArea = region;
for (int i = 0; // do prePaintWindow bottom to top
@ -302,81 +302,58 @@ void Scene::paintSimpleScreen(int orig_mask, QRegion region)
}
dirtyArea |= data.paint;
// Schedule the window for painting
phase2data[w] = Phase2Data(w, data.paint, data.clip, data.mask, data.quads);
phase2data.append(QPair< Window*, Phase2Data >(w,Phase2Data(w, data.paint, data.clip,
data.mask, data.quads)));
// no transformations, but translucency requires window pixmap
w->suspendUnredirect(data.mask & PAINT_WINDOW_TRANSLUCENT);
}
// Do the actual painting
// First opaque windows, top to bottom
// This also calculates correct paint regions for windows, also taking
// care of clipping
QRegion allclips, upperTranslucentDamage;
for (int i = stacking_order.count() - 1; i >= 0; --i) {
QHash< Window*, Phase2Data >::iterator data = phase2data.find(stacking_order[ i ]);
if (data == phase2data.end())
continue;
Toplevel *tlw = data.key()->window();
// This is the occlusion culling pass
QRegion allclips, upperTranslucentDamage;
for (int i = phase2data.count() - 1; i >= 0; --i) {
QPair< Window*, Phase2Data > *entry = &phase2data[i];
Phase2Data *data = &entry->second;
Toplevel *tlw = entry->first->window();
// In case there is a window with a higher stackposition which has translucent regions
// (e.g. decorations) that still have to be drawn, we also have to repaint the current window
// in these particular regions
data->region |= (upperTranslucentDamage & tlw->decorationRect().translated(tlw->pos()));
// subtract the parts which have possibly been drawn already as part of
// subtract the parts which will possibly been drawn as part of
// a higher opaque window
data->region -= allclips;
// Here we rely on WindowPrePaintData::setTranslucent() to remove
// the clip if needed.
if (!data->clip.isEmpty()) {
// clip away this region for all windows below this one
// clip away the opaque regions for all windows below this one
allclips |= data->clip;
// Paint the opaque window
data->painted_1stpass = data->clip & data->region;
paintWindow(data->window, data->mask, data->painted_1stpass, data->quads);
painted_region |= data->painted_1stpass;
// Clip out the client area, so we only draw the rest in the next pass
data->region -= data->clip;
// if prePaintWindow didn't change the clipping area we only have to paint
// the decoration
if ((data-> clip ^
data.key()->clientShape().translated(data.key()->x(), data.key()->y())).isEmpty()) {
data->mask |= PAINT_DECORATION_ONLY;
}
// extend the translucent damage for windows below this by remaining (translucent) regions
upperTranslucentDamage |= data->region - data->clip;
} else {
upperTranslucentDamage |= data->region;
}
// extend the translucent damage for windows below this by remaining (translucent) regions
upperTranslucentDamage |= data->region;
}
QRegion painted_2ndpass;
QRegion paintedArea;
// Fill any areas of the root window not covered by opaque windows
if (!(orig_mask & PAINT_SCREEN_BACKGROUND_FIRST)) {
painted_2ndpass = dirtyArea - allclips;
paintBackground(painted_2ndpass);
paintedArea = dirtyArea - allclips;
paintBackground(paintedArea);
}
// Now walk the list bottom to top, drawing translucent windows.
QRegion lowerOpaqueDamage;
for (int i = 0; i < stacking_order.count(); i++) {
QHash< Window*, Phase2Data >::iterator data = phase2data.find(stacking_order[ i ]);
if (data == phase2data.end())
continue;
// Now walk the list bottom to top and draw the windows.
for (int i = 0; i < phase2data.count(); ++i) {
Phase2Data *data = &phase2data[i].second;
Toplevel *tlw = data.key()->window();
// add all regions of the lower windows which have already be drawn in the 1st pass
data->region |= (lowerOpaqueDamage & tlw->decorationRect().translated(tlw->pos()));
// and extend that region by opaque parts of ourself
lowerOpaqueDamage |= data->painted_1stpass;
// add all regions which have been drawn so far in the 2nd pass
painted_2ndpass |= data->region;
data->region = painted_2ndpass;
// add all regions which have been drawn so far
paintedArea |= data->region;
data->region = paintedArea;
paintWindow(data->window, data->mask, data->region, data->quads);
}
painted_region |= painted_2ndpass;
painted_region |= paintedArea;
}
void Scene::paintWindow(Window* w, int mask, QRegion region, WindowQuadList quads)

View File

@ -77,8 +77,7 @@ public:
PAINT_SCREEN_WITH_TRANSFORMED_WINDOWS = 1 << 5,
// Clear whole background as the very first step, without optimizing it
PAINT_SCREEN_BACKGROUND_FIRST = 1 << 6,
// Temporary solution since (_OPAQUE | _TRANSLUCENT) is not working currently.
PAINT_DECORATION_ONLY = 1 << 7,
// PAINT_DECORATION_ONLY = 1 << 7 has been removed
// Window will be painted with a lanczos filter.
PAINT_WINDOW_LANCZOS = 1 << 8,
// same as PAINT_SCREEN_TRANSFORMED without full repainting
@ -134,7 +133,6 @@ protected:
Window* window;
QRegion region;
QRegion clip;
QRegion painted_1stpass;
int mask;
WindowQuadList quads;
};

View File

@ -586,20 +586,18 @@ void SceneOpenGL::Window::performPaint(int mask, QRegion region, WindowPaintData
}
// paint the content
if (!(mask & PAINT_DECORATION_ONLY)) {
texture.bind();
prepareStates(Content, data.opacity * data.contents_opacity, data.brightness, data.saturation, data.shader);
renderQuads(mask, region, data.quads.select(WindowQuadContents), &texture);
restoreStates(Content, data.opacity * data.contents_opacity, data.brightness, data.saturation, data.shader);
texture.unbind();
texture.bind();
prepareStates(Content, data.opacity * data.contents_opacity, data.brightness, data.saturation, data.shader);
renderQuads(mask, region, data.quads.select(WindowQuadContents), &texture);
restoreStates(Content, data.opacity * data.contents_opacity, data.brightness, data.saturation, data.shader);
texture.unbind();
#ifndef KWIN_HAVE_OPENGLES
if (static_cast<SceneOpenGL*>(scene)->debug) {
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
renderQuads(mask, region, data.quads.select(WindowQuadContents), &texture);
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
}
#endif
if (static_cast<SceneOpenGL*>(scene)->debug) {
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
renderQuads(mask, region, data.quads.select(WindowQuadContents), &texture);
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
}
#endif
if (sceneShader) {
ShaderManager::instance()->popShader();

View File

@ -594,7 +594,7 @@ void SceneXrender::Window::performPaint(int mask, QRegion region, WindowPaintDat
PaintClipper pcreg(region); // clip by the region to paint
PaintClipper pc(transformed_shape); // clip by window's shape
const bool wantShadow = m_shadow && !m_shadow->shadowRegion().isEmpty() && (isOpaque() || !(mask & PAINT_DECORATION_ONLY));
const bool wantShadow = m_shadow && !m_shadow->shadowRegion().isEmpty() && isOpaque();
// In order to obtain a pixel perfect rescaling
// we need to blit the window content togheter with
@ -724,13 +724,11 @@ XRenderComposite(display(), PictOpOver, m_xrenderShadow->shadowPixmap(SceneXRend
}
#undef RENDER_SHADOW_TILE
if (!(mask & PAINT_DECORATION_ONLY)) {
// Paint the window contents
Picture clientAlpha = opaque ? None : alphaMask(data.opacity);
XRenderComposite(display(), clientRenderOp, pic, clientAlpha, renderTarget, cr.x(), cr.y(), 0, 0, dr.x(), dr.y(), dr.width(), dr.height());
if (!opaque)
transformed_shape = QRegion();
}
// Paint the window contents
Picture clientAlpha = opaque ? None : alphaMask(data.opacity);
XRenderComposite(display(), clientRenderOp, pic, clientAlpha, renderTarget, cr.x(), cr.y(), 0, 0, dr.x(), dr.y(), dr.width(), dr.height());
if (!opaque)
transformed_shape = QRegion();
#define RENDER_DECO_PART(_PART_, _RECT_) \
XRenderComposite(display(), PictOpOver, _PART_->x11PictureHandle(), decorationAlpha, renderTarget,\