kwin: Upload all the vertex data at the same time

With this change we only map the vertex buffer once per window.
The vertex arrays are also only set up once.
This commit is contained in:
Fredrik Höglund 2013-03-18 16:45:53 +01:00
parent 993b50cf1c
commit 7c4b736cec
2 changed files with 98 additions and 53 deletions

View file

@ -1347,6 +1347,36 @@ void SceneOpenGL2Window::setBlendEnabled(bool enabled)
m_blendingEnabled = enabled;
}
void SceneOpenGL2Window::setupLeafNodes(LeafNode *nodes, const WindowQuadList *quads, const WindowPaintData &data)
{
if (!quads[ShadowLeaf].isEmpty()) {
nodes[ShadowLeaf].texture = static_cast<SceneOpenGLShadow *>(m_shadow)->shadowTexture();
nodes[ShadowLeaf].opacity = data.opacity();
nodes[ShadowLeaf].hasAlpha = true;
nodes[ShadowLeaf].coordinateType = NormalizedCoordinates;
}
if (!quads[LeftRightLeaf].isEmpty() || !quads[TopBottomLeaf].isEmpty()) {
GLTexture *textures[2];
getDecorationTextures(textures);
nodes[LeftRightLeaf].texture = textures[0];
nodes[LeftRightLeaf].opacity = data.opacity() * data.decorationOpacity();
nodes[LeftRightLeaf].hasAlpha = true;
nodes[LeftRightLeaf].coordinateType = UnnormalizedCoordinates;
nodes[TopBottomLeaf].texture = textures[1];
nodes[TopBottomLeaf].opacity = data.opacity() * data.decorationOpacity();
nodes[TopBottomLeaf].hasAlpha = true;
nodes[TopBottomLeaf].coordinateType = UnnormalizedCoordinates;
}
nodes[ContentLeaf].texture = m_texture;
nodes[ContentLeaf].hasAlpha = !isOpaque();
nodes[ContentLeaf].opacity = data.opacity();
nodes[ContentLeaf].coordinateType = UnnormalizedCoordinates;
}
void SceneOpenGL2Window::performPaint(int mask, QRegion region, WindowPaintData data)
{
if (!beginRenderWindow(mask, region, data))
@ -1370,23 +1400,21 @@ void SceneOpenGL2Window::performPaint(int mask, QRegion region, WindowPaintData
const GLenum filter = (mask & (Effect::PAINT_WINDOW_TRANSFORMED | Effect::PAINT_SCREEN_TRANSFORMED))
&& options->glSmoothScale() != 0 ? GL_LINEAR : GL_NEAREST;
WindowQuadList contentQuads;
WindowQuadList shadowQuads;
WindowQuadList decoQuads[2];
WindowQuadList quads[4];
// Split the quads into separate lists for each type
foreach (const WindowQuad &quad, data.quads) {
switch (quad.type()) {
case WindowQuadDecorationLeftRight:
decoQuads[0].append(quad);
quads[LeftRightLeaf].append(quad);
continue;
case WindowQuadDecorationTopBottom:
decoQuads[1].append(quad);
quads[TopBottomLeaf].append(quad);
continue;
case WindowQuadContents:
contentQuads.append(quad);
quads[ContentLeaf].append(quad);
continue;
case WindowQuadShadowTopLeft:
@ -1397,7 +1425,7 @@ void SceneOpenGL2Window::performPaint(int mask, QRegion region, WindowPaintData
case WindowQuadShadowBottomLeft:
case WindowQuadShadowBottom:
case WindowQuadShadowBottomRight:
shadowQuads.append(quad);
quads[ShadowLeaf].append(quad);
continue;
default:
@ -1405,61 +1433,55 @@ void SceneOpenGL2Window::performPaint(int mask, QRegion region, WindowPaintData
}
}
size_t size = 6 * (quads[0].count() + quads[1].count() + quads[2].count() + quads[3].count()) * sizeof(GLVertex2D);
GLVertexBuffer *vbo = GLVertexBuffer::streamingBuffer();
GLVertex2D *map = (GLVertex2D *) vbo->map(size);
LeafNode nodes[4];
setupLeafNodes(nodes, quads, data);
for (int i = 0, v = 0; i < 4; i++) {
if (quads[i].isEmpty() || !nodes[i].texture)
continue;
nodes[i].firstVertex = v;
nodes[i].vertexCount = quads[i].count() * 6;
const QMatrix4x4 matrix = nodes[i].texture->matrix(nodes[i].coordinateType);
quads[i].makeInterleavedArrays(&map[v], matrix);
v += quads[i].count() * 6;
}
vbo->unmap();
vbo->bindArrays();
// Make sure the blend function is set up correctly in case we will be doing blending
glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
float opacity = -1.0;
// Shadow
// -----------
if (m_shadow && !shadowQuads.isEmpty()) {
if (GLTexture *texture = static_cast<SceneOpenGLShadow*>(m_shadow)->shadowTexture()) {
setBlendEnabled(true);
for (int i = 0; i < 4; i++) {
if (nodes[i].vertexCount == 0)
continue;
setBlendEnabled(nodes[i].hasAlpha || nodes[i].opacity < 1.0);
if (opacity != nodes[i].opacity) {
shader->setUniform(GLShader::ModulationConstant,
modulate(data.opacity() * data.decorationOpacity(), data.brightness()));
texture->setFilter(filter);
texture->setWrapMode(GL_CLAMP_TO_EDGE);
texture->bind();
renderQuads(0, region, shadowQuads, texture, true);
modulate(nodes[i].opacity, data.brightness()));
opacity = nodes[i].opacity;
}
nodes[i].texture->setFilter(filter);
nodes[i].texture->setWrapMode(GL_CLAMP_TO_EDGE);
nodes[i].texture->bind();
vbo->draw(region, GL_TRIANGLES, nodes[i].firstVertex, nodes[i].vertexCount, m_hardwareClipping);
}
// Decorations
// -----------
GLTexture *textures[2];
if (!(decoQuads[0].isEmpty() && decoQuads[1].isEmpty()) && getDecorationTextures(textures)) {
setBlendEnabled(true);
shader->setUniform(GLShader::ModulationConstant,
modulate(data.opacity() * data.decorationOpacity(), data.brightness()));
for (int i = 0; i < 2; i++) {
if (!textures[i] || decoQuads[i].isEmpty())
continue;
textures[i]->setFilter(filter);
textures[i]->setWrapMode(GL_CLAMP_TO_EDGE);
textures[i]->bind();
renderQuads(0, region, decoQuads[i], textures[i], false);
}
}
// Content
// ---------
if (!contentQuads.isEmpty()) {
setBlendEnabled(!isOpaque() || data.opacity() < 1.0);
shader->setUniform(GLShader::ModulationConstant, modulate(data.opacity(), data.brightness()));
m_texture->bind();
renderQuads(mask, region, contentQuads, m_texture, false);
}
vbo->unbindArrays();
setBlendEnabled(false);

View file

@ -283,12 +283,35 @@ private:
class SceneOpenGL2Window : public SceneOpenGL::Window
{
public:
enum Leaf { ShadowLeaf = 0, LeftRightLeaf, TopBottomLeaf, ContentLeaf };
struct LeafNode
{
LeafNode()
: texture(0),
firstVertex(0),
vertexCount(0),
opacity(1.0),
hasAlpha(false),
coordinateType(UnnormalizedCoordinates)
{
}
GLTexture *texture;
int firstVertex;
int vertexCount;
float opacity;
bool hasAlpha;
TextureCoordinateType coordinateType;
};
explicit SceneOpenGL2Window(Toplevel *c);
virtual ~SceneOpenGL2Window();
protected:
QVector4D modulate(float opacity, float brightness) const;
void setBlendEnabled(bool enabled);
void setupLeafNodes(LeafNode *nodes, const WindowQuadList *quads, const WindowPaintData &data);
virtual void performPaint(int mask, QRegion region, WindowPaintData data);
virtual void prepareStates(TextureType type, qreal opacity, qreal brightness, qreal saturation, int screen);
virtual void restoreStates(TextureType type, qreal opacity, qreal brightness, qreal saturation);