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: 103671icc-effect-5.14.5
parent
6b52a4ef19
commit
050d991cb1
|
@ -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.
|
||||
**/
|
||||
|
|
75
scene.cpp
75
scene.cpp
|
@ -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)
|
||||
|
|
4
scene.h
4
scene.h
|
@ -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;
|
||||
};
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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,\
|
||||
|
|
Loading…
Reference in New Issue