scene: Improve window quad management

At the moment, we handle window quads inefficiently. Window quads from
all items are merged into a single list just to be broken up again.

This change removes window quads from libkwineffects. This allows us to
handle window quads efficiently. Furthermore, we could optimize methods
such as WindowVertex::left() and so on. KWin spends reasonable amount
of time in those methods when many windows have to be composited.

It's a necessary prerequisite for making wl_surface painting code role
agnostic.
icc-effect-5.26.4
Vlad Zahorodnii 2021-06-10 13:32:37 +03:00
parent a6268595fb
commit 49744cfc53
12 changed files with 115 additions and 189 deletions

View File

@ -24,7 +24,6 @@ class MockEffectWindow : public EffectWindow
Q_OBJECT
public:
MockEffectWindow(QObject *parent = nullptr);
WindowQuadList buildQuads() const override;
QVariant data(int role) const override;
QRect decorationInnerRect() const override;
void deleteProperty(long int atom) const override;
@ -273,11 +272,6 @@ MockEffectWindow::MockEffectWindow(QObject *parent)
{
}
WindowQuadList MockEffectWindow::buildQuads() const
{
return WindowQuadList();
}
QVariant MockEffectWindow::data(int role) const
{
Q_UNUSED(role)

View File

@ -206,7 +206,7 @@ WindowQuadList DecorationItem::buildQuads() const
const int u1 = (x1 + offsets[i].x()) * textureScale;
const int v1 = (y1 + offsets[i].y()) * textureScale;
WindowQuad quad(const_cast<DecorationItem *>(this));
WindowQuad quad;
quad.setUVAxisSwapped(swap);
if (swap) {

View File

@ -2083,11 +2083,6 @@ EffectWindowList EffectWindowImpl::mainWindows() const
return {};
}
WindowQuadList EffectWindowImpl::buildQuads() const
{
return sceneWindow()->buildQuads();
}
void EffectWindowImpl::setData(int role, const QVariant &data)
{
if (!data.isNull())

View File

@ -488,8 +488,6 @@ public:
EffectWindow* transientFor() override;
EffectWindowList mainWindows() const override;
WindowQuadList buildQuads() const override;
void minimize() override;
void unminimize() override;
void closeWindow() override;

View File

@ -228,7 +228,6 @@ WindowPaintData::WindowPaintData(EffectWindow* w, const QMatrix4x4 &screenProjec
, d(new WindowPaintDataPrivate())
{
d->screenProjectionMatrix = screenProjectionMatrix;
quads = w->buildQuads();
setOpacity(w->opacity());
setSaturation(1.0);
setBrightness(1.0);
@ -238,7 +237,6 @@ WindowPaintData::WindowPaintData(EffectWindow* w, const QMatrix4x4 &screenProjec
WindowPaintData::WindowPaintData(const WindowPaintData &other)
: PaintData()
, quads(other.quads)
, shader(other.shader)
, d(new WindowPaintDataPrivate())
{

View File

@ -2412,11 +2412,6 @@ public:
*/
virtual bool isSkipSwitcher() const = 0;
/**
* Returns the unmodified window quad list. Can also be used to force rebuilding.
*/
virtual WindowQuadList buildQuads() const = 0;
void setMinimized(bool minimize);
virtual void minimize() = 0;
virtual void unminimize() = 0;
@ -2596,13 +2591,12 @@ private:
class KWINEFFECTS_EXPORT WindowQuad
{
public:
explicit WindowQuad(void *userData = nullptr);
WindowQuad();
WindowQuad makeSubQuad(double x1, double y1, double x2, double y2) const;
WindowVertex& operator[](int index);
const WindowVertex& operator[](int index) const;
void setUVAxisSwapped(bool value) { uvSwapped = value; }
bool uvAxisSwapped() const { return uvSwapped; }
void *userData() const;
double left() const;
double right() const;
double top() const;
@ -2616,7 +2610,6 @@ public:
private:
friend class WindowQuadList;
WindowVertex verts[ 4 ];
void *m_userData;
bool uvSwapped;
};
@ -2647,7 +2640,6 @@ public:
* I.e. window will definitely cover it's clip region
*/
QRegion clip;
WindowQuadList quads;
/**
* Simple helper that sets data to say the window will be painted as non-opaque.
* Takes also care of changing the regions.
@ -3009,8 +3001,6 @@ public:
*/
QMatrix4x4 screenProjectionMatrix() const;
WindowQuadList quads;
/**
* Shader to be used for rendering, if any.
*/
@ -3798,9 +3788,8 @@ void WindowVertex::setY(double y)
***************************************************************/
inline
WindowQuad::WindowQuad(void *userData)
: m_userData(userData)
, uvSwapped(false)
WindowQuad::WindowQuad()
: uvSwapped(false)
{
}
@ -3818,12 +3807,6 @@ const WindowVertex& WindowQuad::operator[](int index) const
return verts[ index ];
}
inline
void *WindowQuad::userData() const
{
return m_userData;
}
inline
bool WindowQuad::isTransformed() const
{

View File

@ -1110,94 +1110,33 @@ OpenGLWindow::~OpenGLWindow()
{
}
static QMatrix4x4 transformation(const QPoint &position, int mask, const WindowPaintData &data)
static QMatrix4x4 transformation(const Item *item, const OpenGLWindow::RenderContext *context)
{
const QPoint position = item->rootPosition();
QMatrix4x4 matrix;
matrix.translate(position.x(), position.y());
if (!(mask & Scene::PAINT_WINDOW_TRANSFORMED))
if (!(context->paintFlags & Scene::PAINT_WINDOW_TRANSFORMED))
return matrix;
matrix.translate(data.translation());
const QVector3D scale = data.scale();
const WindowPaintData *data = &context->paintData;
matrix.translate(data->translation());
const QVector3D scale = data->scale();
matrix.scale(scale.x(), scale.y(), scale.z());
if (data.rotationAngle() == 0.0)
if (data->rotationAngle() == 0.0)
return matrix;
// Apply the rotation
// cannot use data.rotation.applyTo(&matrix) as QGraphicsRotation uses projectedRotate to map back to 2D
matrix.translate(data.rotationOrigin());
const QVector3D axis = data.rotationAxis();
matrix.rotate(data.rotationAngle(), axis.x(), axis.y(), axis.z());
matrix.translate(-data.rotationOrigin());
matrix.translate(data->rotationOrigin());
const QVector3D axis = data->rotationAxis();
matrix.rotate(data->rotationAngle(), axis.x(), axis.y(), axis.z());
matrix.translate(-data->rotationOrigin());
return matrix;
}
bool OpenGLWindow::beginRenderWindow(int mask, const QRegion &region, WindowPaintData &data)
{
if (region.isEmpty())
return false;
m_hardwareClipping = region != infiniteRegion() && (mask & Scene::PAINT_WINDOW_TRANSFORMED) && !(mask & Scene::PAINT_SCREEN_TRANSFORMED);
if (region != infiniteRegion() && !m_hardwareClipping) {
WindowQuadList quads;
quads.reserve(data.quads.count());
// split all quads in bounding rect with the actual rects in the region
for (const WindowQuad &quad : qAsConst(data.quads)) {
const Item *item = static_cast<const Item *>(quad.userData());
const QPoint position = item->rootPosition();
for (const QRect &r : region) {
const QRectF rf(r.translated(-position));
const QRectF quadRect(QPointF(quad.left(), quad.top()), QPointF(quad.right(), quad.bottom()));
const QRectF &intersected = rf.intersected(quadRect);
if (intersected.isValid()) {
if (quadRect == intersected) {
// case 1: completely contains, include and do not check other rects
quads << quad;
break;
}
// case 2: intersection
quads << quad.makeSubQuad(intersected.left(), intersected.top(), intersected.right(), intersected.bottom());
}
}
}
data.quads = quads;
}
if (data.quads.isEmpty())
return false;
if (surfaceItem() && !surfaceItem()->damage().isEmpty()) { // only relevant on X11
m_scene->insertWait();
}
if (m_hardwareClipping) {
glEnable(GL_SCISSOR_TEST);
}
const GLVertexAttrib attribs[] = {
{ VA_Position, 2, GL_FLOAT, offsetof(GLVertex2D, position) },
{ VA_TexCoord, 2, GL_FLOAT, offsetof(GLVertex2D, texcoord) },
};
GLVertexBuffer *vbo = GLVertexBuffer::streamingBuffer();
vbo->reset();
vbo->setAttribLayout(attribs, 2, sizeof(GLVertex2D));
return true;
}
void OpenGLWindow::endRenderWindow()
{
if (m_hardwareClipping) {
glDisable(GL_SCISSOR_TEST);
}
}
QVector4D OpenGLWindow::modulate(float opacity, float brightness) const
{
const float a = opacity;
@ -1245,44 +1184,78 @@ static GLTexture *bindSurfaceTexture(SurfaceItem *surfaceItem)
return platformSurfaceTexture->texture();
}
void OpenGLWindow::createRenderNode(Item *item, RenderContext *context, int mask, const WindowPaintData &data)
static WindowQuadList clipQuads(const Item *item, const OpenGLWindow::RenderContext *context)
{
const WindowQuadList quads = item->quads();
if (context->clip != infiniteRegion() && !context->hardwareClipping) {
const QPoint offset = item->rootPosition();
WindowQuadList ret;
ret.reserve(quads.count());
// split all quads in bounding rect with the actual rects in the region
for (const WindowQuad &quad : qAsConst(quads)) {
for (const QRect &r : qAsConst(context->clip)) {
const QRectF rf(r.translated(-offset));
const QRectF quadRect(QPointF(quad.left(), quad.top()), QPointF(quad.right(), quad.bottom()));
const QRectF &intersected = rf.intersected(quadRect);
if (intersected.isValid()) {
if (quadRect == intersected) {
// case 1: completely contains, include and do not check other rects
ret << quad;
break;
}
// case 2: intersection
ret << quad.makeSubQuad(intersected.left(), intersected.top(), intersected.right(), intersected.bottom());
}
}
}
return ret;
}
return quads;
}
void OpenGLWindow::createRenderNode(Item *item, RenderContext *context)
{
if (auto shadowItem = qobject_cast<ShadowItem *>(item)) {
WindowQuadList quads = context->quads.value(item);
WindowQuadList quads = clipQuads(item, context);
if (!quads.isEmpty()) {
SceneOpenGLShadow *shadow = static_cast<SceneOpenGLShadow *>(shadowItem->shadow());
context->renderNodes.append(RenderNode{
.texture = shadow->shadowTexture(),
.quads = quads,
.transformMatrix = transformation(item->rootPosition(), mask, data),
.opacity = data.opacity(),
.transformMatrix = transformation(item, context),
.opacity = context->paintData.opacity(),
.hasAlpha = true,
.coordinateType = NormalizedCoordinates,
});
}
} else if (auto decorationItem = qobject_cast<DecorationItem *>(item)) {
WindowQuadList quads = context->quads.value(item);
WindowQuadList quads = clipQuads(item, context);
if (!quads.isEmpty()) {
auto renderer = static_cast<const SceneOpenGLDecorationRenderer *>(decorationItem->renderer());
context->renderNodes.append(RenderNode{
.texture = renderer->texture(),
.quads = quads,
.transformMatrix = transformation(item->rootPosition(), mask, data),
.opacity = data.opacity(),
.transformMatrix = transformation(item, context),
.opacity = context->paintData.opacity(),
.hasAlpha = true,
.coordinateType = UnnormalizedCoordinates,
});
}
} else if (auto surfaceItem = qobject_cast<SurfaceItem *>(item)) {
WindowQuadList quads = context->quads.value(item);
WindowQuadList quads = clipQuads(item, context);
if (!quads.isEmpty()) {
if (!surfaceItem->damage().isEmpty()) { // only relevant on X11
m_scene->insertWait();
}
SurfacePixmap *pixmap = surfaceItem->pixmap();
if (pixmap) {
context->renderNodes.append(RenderNode{
.texture = bindSurfaceTexture(surfaceItem),
.quads = quads,
.transformMatrix = transformation(item->rootPosition(), mask, data),
.opacity = data.opacity(),
.transformMatrix = transformation(item, context),
.opacity = context->paintData.opacity(),
.hasAlpha = pixmap->hasAlphaChannel(),
.coordinateType = UnnormalizedCoordinates,
});
@ -1293,7 +1266,7 @@ void OpenGLWindow::createRenderNode(Item *item, RenderContext *context, int mask
const QList<Item *> childItems = item->childItems();
for (Item *childItem : childItems) {
if (childItem->isVisible()) {
createRenderNode(childItem, context, mask ,data);
createRenderNode(childItem, context);
}
}
}
@ -1322,11 +1295,27 @@ QMatrix4x4 OpenGLWindow::modelViewProjectionMatrix(int mask, const WindowPaintDa
return scene->projectionMatrix() * mvMatrix;
}
void OpenGLWindow::performPaint(int mask, const QRegion &region, const WindowPaintData &_data)
void OpenGLWindow::performPaint(int mask, const QRegion &region, const WindowPaintData &data)
{
WindowPaintData data = _data;
if (!beginRenderWindow(mask, region, data))
if (region.isEmpty()) {
return;
}
RenderContext renderContext {
.paintFlags = mask,
.clip = region,
.paintData = data,
.hardwareClipping = region != infiniteRegion() && (mask & Scene::PAINT_WINDOW_TRANSFORMED) && !(mask & Scene::PAINT_SCREEN_TRANSFORMED),
};
createRenderNode(windowItem(), &renderContext);
int quadCount = 0;
for (const RenderNode &node : qAsConst(renderContext.renderNodes)) {
quadCount += node.quads.count();
}
if (!quadCount) {
return;
}
GLShader *shader = data.shader;
GLenum filter;
@ -1356,22 +1345,24 @@ void OpenGLWindow::performPaint(int mask, const QRegion &region, const WindowPai
}
shader->setUniform(GLShader::Saturation, data.saturation());
RenderContext renderContext;
// TODO: This is somewhat inefficient, remove window quads from the public api.
for (const WindowQuad &quad : qAsConst(data.quads)) {
Item *item = static_cast<Item *>(quad.userData());
Q_ASSERT(item);
renderContext.quads[item].append(quad);
}
createRenderNode(windowItem(), &renderContext, mask, data);
const bool indexedQuads = GLVertexBuffer::supportsIndexedQuads();
const GLenum primitiveType = indexedQuads ? GL_QUADS : GL_TRIANGLES;
const int verticesPerQuad = indexedQuads ? 4 : 6;
const size_t size = verticesPerQuad * quadCount * sizeof(GLVertex2D);
const size_t size = verticesPerQuad * data.quads.count() * sizeof(GLVertex2D);
if (renderContext.hardwareClipping) {
glEnable(GL_SCISSOR_TEST);
}
const GLVertexAttrib attribs[] = {
{ VA_Position, 2, GL_FLOAT, offsetof(GLVertex2D, position) },
{ VA_TexCoord, 2, GL_FLOAT, offsetof(GLVertex2D, texcoord) },
};
GLVertexBuffer *vbo = GLVertexBuffer::streamingBuffer();
vbo->reset();
vbo->setAttribLayout(attribs, 2, sizeof(GLVertex2D));
GLVertex2D *map = (GLVertex2D *) vbo->map(size);
for (int i = 0, v = 0; i < renderContext.renderNodes.count(); i++) {
@ -1417,7 +1408,7 @@ void OpenGLWindow::performPaint(int mask, const QRegion &region, const WindowPai
renderNode.texture->bind();
vbo->draw(region, primitiveType, renderNode.firstVertex,
renderNode.vertexCount, m_hardwareClipping);
renderNode.vertexCount, renderContext.hardwareClipping);
}
vbo->unbindArrays();
@ -1427,7 +1418,9 @@ void OpenGLWindow::performPaint(int mask, const QRegion &region, const WindowPai
if (!data.shader)
ShaderManager::instance()->popShader();
endRenderWindow();
if (renderContext.hardwareClipping) {
glDisable(GL_SCISSOR_TEST);
}
}
QSharedPointer<GLTexture> OpenGLWindow::windowTexture()

View File

@ -147,7 +147,10 @@ public:
struct RenderContext
{
QVector<RenderNode> renderNodes;
QHash<Item *, WindowQuadList> quads;
const int paintFlags;
const QRegion clip;
const WindowPaintData &paintData;
const bool hardwareClipping;
};
OpenGLWindow(Toplevel *toplevel, SceneOpenGL *scene);
@ -160,12 +163,9 @@ private:
QMatrix4x4 modelViewProjectionMatrix(int mask, const WindowPaintData &data) const;
QVector4D modulate(float opacity, float brightness) const;
void setBlendEnabled(bool enabled);
void createRenderNode(Item *item, RenderContext *context, int mask, const WindowPaintData &data);
bool beginRenderWindow(int mask, const QRegion &region, WindowPaintData &data);
void endRenderWindow();
void createRenderNode(Item *item, RenderContext *context);
SceneOpenGL *m_scene;
bool m_hardwareClipping = false;
bool m_blendingEnabled = false;
};

View File

@ -252,18 +252,12 @@ void Scene::paintGenericScreen(int orig_mask, const ScreenPaintData &)
w->resetPaintingEnabled();
data.paint = infiniteRegion(); // no clipping, so doesn't really matter
data.clip = QRegion();
data.quads = w->buildQuads();
// preparation step
effects->prePaintWindow(effectWindow(w), data, m_expectedPresentTimestamp);
#if !defined(QT_NO_DEBUG)
if (data.quads.isTransformed()) {
qFatal("Pre-paint calls are not allowed to transform quads!");
}
#endif
if (!w->isPaintingEnabled()) {
continue;
}
phase2.append({w, infiniteRegion(), data.clip, data.mask, data.quads});
phase2.append({w, infiniteRegion(), data.clip, data.mask,});
}
damaged_region = QRegion(QRect {{}, screens()->size()});
@ -279,7 +273,7 @@ void Scene::paintGenericScreen(int orig_mask, const ScreenPaintData &)
paintBackground(infiniteRegion());
}
Q_FOREACH (const Phase2Data & d, phase2) {
paintWindow(d.window, d.mask, d.region, d.quads);
paintWindow(d.window, d.mask, d.region);
}
}
@ -351,20 +345,14 @@ void Scene::paintSimpleScreen(int orig_mask, const QRegion &region)
data.clip |= window->decorationShape().translated(window->pos());
}
data.quads = window->buildQuads();
// preparation step
effects->prePaintWindow(effectWindow(window), data, m_expectedPresentTimestamp);
#if !defined(QT_NO_DEBUG)
if (data.quads.isTransformed()) {
qFatal("Pre-paint calls are not allowed to transform quads!");
}
#endif
if (!window->isPaintingEnabled()) {
continue;
}
dirtyArea |= data.paint;
// Schedule the window for painting
phase2data.append({ window, data.paint, data.clip, data.mask, data.quads });
phase2data.append({ window, data.paint, data.clip, data.mask, });
}
// Save the part of the repaint region that's exclusively rendered to
@ -434,7 +422,7 @@ void Scene::paintSimpleScreen(int orig_mask, const QRegion &region)
paintedArea |= data->region;
data->region = paintedArea;
paintWindow(data->window, data->mask, data->region, data->quads);
paintWindow(data->window, data->mask, data->region);
}
if (fullRepaint) {
@ -504,7 +492,7 @@ void Scene::clearStackingOrder()
static Scene::Window *s_recursionCheck = nullptr;
void Scene::paintWindow(Window* w, int mask, const QRegion &_region, const WindowQuadList &quads)
void Scene::paintWindow(Window* w, int mask, const QRegion &_region)
{
// no painting outside visible screen (and no transformations)
const QRegion region = _region & QRect({0, 0}, screens()->size());
@ -520,7 +508,6 @@ void Scene::paintWindow(Window* w, int mask, const QRegion &_region, const Windo
}
WindowPaintData data(w->window()->effectWindow(), screenProjectionMatrix());
data.quads = quads;
effects->paintWindow(effectWindow(w), mask, region, data);
// paint thumbnails on top of window
paintWindowThumbnails(w, region, data.opacity(), data.brightness(), data.saturation());
@ -872,25 +859,6 @@ void Scene::Window::disablePainting(int reason)
disable_painting |= reason;
}
static void buildQuadsHelper(const Item *item, WindowQuadList *ret)
{
*ret += item->quads();
const QList<Item *> childItems = item->childItems();
for (const Item *childItem : childItems) {
if (childItem->isVisible()) {
buildQuadsHelper(childItem, ret);
}
}
}
WindowQuadList Scene::Window::buildQuads() const
{
WindowQuadList ret;
buildQuadsHelper(windowItem(), &ret);
return ret;
}
void Scene::Window::preprocess(Item *item)
{
item->preprocess();

View File

@ -232,7 +232,7 @@ protected:
// called after all effects had their paintWindow() called
void finalPaintWindow(EffectWindowImpl* w, int mask, const QRegion &region, WindowPaintData& data);
// shared implementation, starts painting the window
virtual void paintWindow(Window* w, int mask, const QRegion &region, const WindowQuadList &quads);
virtual void paintWindow(Window* w, int mask, const QRegion &region);
// called after all effects had their drawWindow() called
virtual void finalDrawWindow(EffectWindowImpl* w, int mask, const QRegion &region, WindowPaintData& data);
// let the scene decide whether it's better to paint more of the screen, eg. in order to allow a buffer swap
@ -248,7 +248,6 @@ protected:
QRegion region;
QRegion clip;
int mask = 0;
WindowQuadList quads;
};
// The region which actually has been painted by paintScreen() and should be
// copied from the buffer to the screen. I.e. the region returned from Scene::paintScreen().
@ -339,7 +338,6 @@ public:
bool isOpaque() const;
QRegion decorationShape() const;
void updateToplevel(Deleted *deleted);
WindowQuadList buildQuads() const;
void referencePreviousPixmap();
void unreferencePreviousPixmap();
void preprocess(Item *item);

View File

@ -152,14 +152,13 @@ WindowQuadList ShadowItem::buildQuads() const
WindowQuadList quads;
quads.reserve(8);
void *tag = const_cast<ShadowItem *>(this);
if (topLeftRect.isValid()) {
tx1 = 0.0;
ty1 = 0.0;
tx2 = topLeftRect.width() / width;
ty2 = topLeftRect.height() / height;
WindowQuad topLeftQuad(tag);
WindowQuad topLeftQuad;
topLeftQuad[0] = WindowVertex(topLeftRect.left(), topLeftRect.top(), tx1, ty1);
topLeftQuad[1] = WindowVertex(topLeftRect.right(), topLeftRect.top(), tx2, ty1);
topLeftQuad[2] = WindowVertex(topLeftRect.right(), topLeftRect.bottom(), tx2, ty2);
@ -172,7 +171,7 @@ WindowQuadList ShadowItem::buildQuads() const
ty1 = 0.0;
tx2 = 1.0;
ty2 = topRightRect.height() / height;
WindowQuad topRightQuad(tag);
WindowQuad topRightQuad;
topRightQuad[0] = WindowVertex(topRightRect.left(), topRightRect.top(), tx1, ty1);
topRightQuad[1] = WindowVertex(topRightRect.right(), topRightRect.top(), tx2, ty1);
topRightQuad[2] = WindowVertex(topRightRect.right(), topRightRect.bottom(), tx2, ty2);
@ -185,7 +184,7 @@ WindowQuadList ShadowItem::buildQuads() const
tx2 = 1.0;
ty1 = 1.0 - bottomRightRect.height() / height;
ty2 = 1.0;
WindowQuad bottomRightQuad(tag);
WindowQuad bottomRightQuad;
bottomRightQuad[0] = WindowVertex(bottomRightRect.left(), bottomRightRect.top(), tx1, ty1);
bottomRightQuad[1] = WindowVertex(bottomRightRect.right(), bottomRightRect.top(), tx2, ty1);
bottomRightQuad[2] = WindowVertex(bottomRightRect.right(), bottomRightRect.bottom(), tx2, ty2);
@ -198,7 +197,7 @@ WindowQuadList ShadowItem::buildQuads() const
tx2 = bottomLeftRect.width() / width;
ty1 = 1.0 - bottomLeftRect.height() / height;
ty2 = 1.0;
WindowQuad bottomLeftQuad(tag);
WindowQuad bottomLeftQuad;
bottomLeftQuad[0] = WindowVertex(bottomLeftRect.left(), bottomLeftRect.top(), tx1, ty1);
bottomLeftQuad[1] = WindowVertex(bottomLeftRect.right(), bottomLeftRect.top(), tx2, ty1);
bottomLeftQuad[2] = WindowVertex(bottomLeftRect.right(), bottomLeftRect.bottom(), tx2, ty2);
@ -231,7 +230,7 @@ WindowQuadList ShadowItem::buildQuads() const
ty1 = 0.0;
tx2 = tx1 + top.width() / width;
ty2 = topRect.height() / height;
WindowQuad topQuad(tag);
WindowQuad topQuad;
topQuad[0] = WindowVertex(topRect.left(), topRect.top(), tx1, ty1);
topQuad[1] = WindowVertex(topRect.right(), topRect.top(), tx2, ty1);
topQuad[2] = WindowVertex(topRect.right(), topRect.bottom(), tx2, ty2);
@ -244,7 +243,7 @@ WindowQuadList ShadowItem::buildQuads() const
ty1 = shadowMargins.top() / height;
tx2 = 1.0;
ty2 = ty1 + right.height() / height;
WindowQuad rightQuad(tag);
WindowQuad rightQuad;
rightQuad[0] = WindowVertex(rightRect.left(), rightRect.top(), tx1, ty1);
rightQuad[1] = WindowVertex(rightRect.right(), rightRect.top(), tx2, ty1);
rightQuad[2] = WindowVertex(rightRect.right(), rightRect.bottom(), tx2, ty2);
@ -257,7 +256,7 @@ WindowQuadList ShadowItem::buildQuads() const
ty1 = 1.0 - bottomRect.height() / height;
tx2 = tx1 + bottom.width() / width;
ty2 = 1.0;
WindowQuad bottomQuad(tag);
WindowQuad bottomQuad;
bottomQuad[0] = WindowVertex(bottomRect.left(), bottomRect.top(), tx1, ty1);
bottomQuad[1] = WindowVertex(bottomRect.right(), bottomRect.top(), tx2, ty1);
bottomQuad[2] = WindowVertex(bottomRect.right(), bottomRect.bottom(), tx2, ty2);
@ -270,7 +269,7 @@ WindowQuadList ShadowItem::buildQuads() const
ty1 = shadowMargins.top() / height;
tx2 = leftRect.width() / width;
ty2 = ty1 + left.height() / height;
WindowQuad leftQuad(tag);
WindowQuad leftQuad;
leftQuad[0] = WindowVertex(leftRect.left(), leftRect.top(), tx1, ty1);
leftQuad[1] = WindowVertex(leftRect.right(), leftRect.top(), tx2, ty1);
leftQuad[2] = WindowVertex(leftRect.right(), leftRect.bottom(), tx2, ty2);

View File

@ -120,7 +120,7 @@ WindowQuadList SurfaceItem::buildQuads() const
quads.reserve(region.rectCount());
for (const QRectF rect : region) {
WindowQuad quad(const_cast<SurfaceItem *>(this));
WindowQuad quad;
const QPointF bufferTopLeft = mapToBuffer(rect.topLeft());
const QPointF bufferTopRight = mapToBuffer(rect.topRight());