コード例 #1
0
ファイル: coverswitch.cpp プロジェクト: KDE/kwin
void CoverSwitchEffect::paintScreen(int mask, QRegion region, ScreenPaintData& data)
{
    effects->paintScreen(mask, region, data);

    if (mActivated || stop || stopRequested) {

        QList< EffectWindow* > tempList = currentWindowList;
        int index = tempList.indexOf(selected_window);
        if (animation || start || stop) {
            if (!start && !stop) {
                if (direction == Right)
                    index++;
                else
                    index--;
                if (index < 0)
                    index = tempList.count() + index;
                if (index >= tempList.count())
                    index = index % tempList.count();
            }
            foreach (Direction direction, scheduled_directions) {
                if (direction == Right)
                    index++;
                else
                    index--;
                if (index < 0)
                    index = tempList.count() + index;
                if (index >= tempList.count())
                    index = index % tempList.count();
            }
        }
        int leftIndex = index - 1;
        if (leftIndex < 0)
            leftIndex = tempList.count() - 1;
        int rightIndex = index + 1;
        if (rightIndex == tempList.count())
            rightIndex = 0;

        EffectWindow* frontWindow = tempList[ index ];
        leftWindows.clear();
        rightWindows.clear();

        bool evenWindows = (tempList.count() % 2 == 0) ? true : false;
        int leftWindowCount = 0;
        if (evenWindows)
            leftWindowCount = tempList.count() / 2 - 1;
        else
            leftWindowCount = (tempList.count() - 1) / 2;
        for (int i = 0; i < leftWindowCount; i++) {
            int tempIndex = (leftIndex - i);
            if (tempIndex < 0)
                tempIndex = tempList.count() + tempIndex;
            leftWindows.prepend(tempList[ tempIndex ]);
        }
        int rightWindowCount = 0;
        if (evenWindows)
            rightWindowCount = tempList.count() / 2;
        else
            rightWindowCount = (tempList.count() - 1) / 2;
        for (int i = 0; i < rightWindowCount; i++) {
            int tempIndex = (rightIndex + i) % tempList.count();
            rightWindows.prepend(tempList[ tempIndex ]);
        }

        if (reflection) {
            // no reflections during start and stop animation
            // except when using a shader
            if ((!start && !stop) || effects->compositingType() == OpenGL2Compositing)
                paintScene(frontWindow, leftWindows, rightWindows, true);
            glEnable(GL_BLEND);
            glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
            // we can use a huge scale factor (needed to calculate the rearground vertices)
            // as we restrict with a PaintClipper painting on the current screen
            float reflectionScaleFactor = 100000 * tan(60.0 * M_PI / 360.0f) / area.width();
            const float width = area.width();
            const float height = area.height();
            float vertices[] = {
                -width * 0.5f, height, 0.0,
                width * 0.5f, height, 0.0,
                width*reflectionScaleFactor, height, -5000,
                -width*reflectionScaleFactor, height, -5000
            };
            // foreground
            if (start) {
                mirrorColor[0][3] = timeLine.currentValue();
            } else if (stop) {
                mirrorColor[0][3] = 1.0 - timeLine.currentValue();
            } else {
                mirrorColor[0][3] = 1.0;
            }

            int y = 0;
            // have to adjust the y values to fit OpenGL
            // in OpenGL y==0 is at bottom, in Qt at top
            if (effects->numScreens() > 1) {
                QRect fullArea = effects->clientArea(FullArea, 0, 1);
                if (fullArea.height() != area.height()) {
                    if (area.y() == 0)
                        y = fullArea.height() - area.height();
                    else
                        y = fullArea.height() - area.y() - area.height();
                }
            }
            // use scissor to restrict painting of the reflection plane to current screen
            glScissor(area.x(), y, area.width(), area.height());
            glEnable(GL_SCISSOR_TEST);

            if (m_reflectionShader && m_reflectionShader->isValid()) {
                ShaderManager::instance()->pushShader(m_reflectionShader);
                QMatrix4x4 windowTransformation = data.projectionMatrix();
                windowTransformation.translate(area.x() + area.width() * 0.5f, 0.0, 0.0);
                m_reflectionShader->setUniform(GLShader::ModelViewProjectionMatrix, windowTransformation);
                m_reflectionShader->setUniform("u_frontColor", QVector4D(mirrorColor[0][0], mirrorColor[0][1], mirrorColor[0][2], mirrorColor[0][3]));
                m_reflectionShader->setUniform("u_backColor", QVector4D(mirrorColor[1][0], mirrorColor[1][1], mirrorColor[1][2], mirrorColor[1][3]));
                // TODO: make this one properly
                QVector<float> verts;
                QVector<float> texcoords;
                verts.reserve(18);
                texcoords.reserve(12);
                texcoords << 1.0 << 0.0;
                verts << vertices[6] << vertices[7] << vertices[8];
                texcoords << 1.0 << 0.0;
                verts << vertices[9] << vertices[10] << vertices[11];
                texcoords << 0.0 << 0.0;
                verts << vertices[0] << vertices[1] << vertices[2];
                texcoords << 0.0 << 0.0;
                verts << vertices[0] << vertices[1] << vertices[2];
                texcoords << 0.0 << 0.0;
                verts << vertices[3] << vertices[4] << vertices[5];
                texcoords << 1.0 << 0.0;
                verts << vertices[6] << vertices[7] << vertices[8];
                GLVertexBuffer *vbo = GLVertexBuffer::streamingBuffer();
                vbo->reset();
                vbo->setData(6, 3, verts.data(), texcoords.data());
                vbo->render(GL_TRIANGLES);

                ShaderManager::instance()->popShader();
            }
            glDisable(GL_SCISSOR_TEST);
            glDisable(GL_BLEND);
        }
        paintScene(frontWindow, leftWindows, rightWindows);

        // Render the caption frame
        if (windowTitle) {
            double opacity = 1.0;
            if (start)
                opacity = timeLine.currentValue();
            else if (stop)
                opacity = 1.0 - timeLine.currentValue();
            if (animation)
                captionFrame->setCrossFadeProgress(timeLine.currentValue());
            captionFrame->render(region, opacity);
        }
    }