30#include <QQuickWindow> 
   43WaylandCompositor::WaylandCompositor(QObject *parent)
 
   54bool WaylandCompositor::attemptOpenGLCompositing()
 
   56    std::unique_ptr<OpenGLBackend> 
backend = kwinApp()->outputBackend()->createOpenGLBackend();
 
   67    const QByteArray forceEnv = qgetenv(
"KWIN_COMPOSE");
 
   68    if (!forceEnv.isEmpty()) {
 
   69        if (qstrcmp(forceEnv, 
"O2") == 0 || qstrcmp(forceEnv, 
"O2ES") == 0) {
 
   70            qCDebug(KWIN_CORE) << 
"OpenGL 2 compositing enforced by environment variable";
 
   77            qCDebug(KWIN_CORE) << 
"Driver does not recommend OpenGL compositing";
 
   84        qCDebug(KWIN_CORE) << 
"OpenGL 2.0 is not supported";
 
   89    m_cursorScene = std::make_unique<CursorScene>(std::make_unique<ItemRendererOpenGL>());
 
   92    qCDebug(KWIN_CORE) << 
"OpenGL compositing has been successfully initialized";
 
   96bool WaylandCompositor::attemptQPainterCompositing()
 
   98    std::unique_ptr<QPainterBackend> 
backend(kwinApp()->outputBackend()->createQPainterBackend());
 
  103    m_scene = std::make_unique<WorkspaceSceneQPainter>(
backend.get());
 
  104    m_cursorScene = std::make_unique<CursorScene>(std::make_unique<ItemRendererQPainter>());
 
  107    qCDebug(KWIN_CORE) << 
"QPainter compositing has been successfully initialized";
 
  113    if (kwinApp()->isTerminating()) {
 
  124    const QList<CompositingType> availableCompositors = kwinApp()->outputBackend()->supportedCompositors();
 
  125    QList<CompositingType> candidateCompositors;
 
  128        candidateCompositors.append(m_selectedCompositor);
 
  130        candidateCompositors = availableCompositors;
 
  132        const auto userConfigIt = std::find(candidateCompositors.begin(), candidateCompositors.end(), 
options->
compositingMode());
 
  133        if (userConfigIt != candidateCompositors.end()) {
 
  134            candidateCompositors.erase(userConfigIt);
 
  137            qCWarning(KWIN_CORE) << 
"Configured compositor not supported by Platform. Falling back to defaults";
 
  141    for (
auto type : std::as_const(candidateCompositors)) {
 
  145            qCDebug(KWIN_CORE) << 
"Attempting to load the OpenGL scene";
 
  146            stop = attemptOpenGLCompositing();
 
  149            qCDebug(KWIN_CORE) << 
"Attempting to load the QPainter scene";
 
  150            stop = attemptQPainterCompositing();
 
  153            qCDebug(KWIN_CORE) << 
"Starting without compositing...";
 
  160        } 
else if (qEnvironmentVariableIsSet(
"KWIN_COMPOSE")) {
 
  161            qCCritical(KWIN_CORE) << 
"Could not fulfill the requested compositing mode in KWIN_COMPOSE:" << 
type << 
". Exiting.";
 
  169        qCCritical(KWIN_CORE) << 
"The used windowing system requires compositing";
 
  170        qCCritical(KWIN_CORE) << 
"We are going to quit KWin now as it is broken";
 
  176        m_selectedCompositor = 
m_backend->compositingType();
 
  178        switch (m_selectedCompositor) {
 
  182            QQuickWindow::setGraphicsApi(QSGRendererInterface::OpenGL);
 
  185            QQuickWindow::setGraphicsApi(QSGRendererInterface::Software);
 
  193    for (
Output *output : outputs) {
 
  202    for (
Window *window : windows) {
 
  203        window->setupCompositing();
 
  207    kwinApp()->createEffectsHandler(
this, 
m_scene.get());
 
 
  228        for (
Window *window : windows) {
 
  229            window->finishCompositing();
 
  241    for (
auto it = superlayers.begin(); it != superlayers.end(); ++it) {
 
 
  253void WaylandCompositor::addOutput(
Output *output)
 
  258    auto workspaceLayer = 
new RenderLayer(output->
renderLoop());
 
  259    workspaceLayer->setDelegate(std::make_unique<SceneDelegate>(
m_scene.get(), output));
 
  260    workspaceLayer->setGeometry(output->
rectF());
 
  262        workspaceLayer->setGeometry(output->
rectF());
 
  265    auto cursorLayer = 
new RenderLayer(output->
renderLoop());
 
  266    cursorLayer->setVisible(
false);
 
  268        cursorLayer->setDelegate(std::make_unique<CursorDelegateOpenGL>(output));
 
  270        cursorLayer->setDelegate(std::make_unique<CursorDelegateQPainter>(output));
 
  272    cursorLayer->setParent(workspaceLayer);
 
  273    cursorLayer->setSuperlayer(workspaceLayer);
 
  277    static bool forceSoftwareCursorIsSet;
 
  278    static const bool forceSoftwareCursor = qEnvironmentVariableIntValue(
"KWIN_FORCE_SW_CURSOR", &forceSoftwareCursorIsSet) == 1
 
  281    auto updateCursorLayer = [
this, output, cursorLayer]() {
 
  283        const QRectF outputLocalRect = output->
mapFromGlobal(cursor->geometry());
 
  284        const auto outputLayer = 
m_backend->cursorLayer(output);
 
  285        if (!cursor->isOnOutput(output)) {
 
  286            if (outputLayer && outputLayer->isEnabled()) {
 
  287                outputLayer->setEnabled(
false);
 
  290            cursorLayer->setVisible(
false);
 
  293        const auto renderHardwareCursor = [&]() {
 
  294            if (!outputLayer || forceSoftwareCursor) {
 
  298            QSize bufferSize(std::ceil(nativeCursorRect.width()), std::ceil(nativeCursorRect.height()));
 
  299            if (
const auto fixedSize = outputLayer->fixedSize()) {
 
  300                if (fixedSize->width() < bufferSize.width() || fixedSize->height() < bufferSize.height()) {
 
  303                bufferSize = *fixedSize;
 
  304                nativeCursorRect = output->
transform().
map(QRectF(outputLocalRect.topLeft() * output->
scale(), bufferSize), output->
pixelSize());
 
  306            outputLayer->setPosition(nativeCursorRect.topLeft());
 
  307            outputLayer->setHotspot(output->
transform().
map(cursor->hotspot() * output->
scale(), bufferSize));
 
  308            outputLayer->setSize(bufferSize);
 
  309            if (
auto beginInfo = outputLayer->beginFrame()) {
 
  310                const RenderTarget &renderTarget = beginInfo->renderTarget;
 
  312                RenderLayer renderLayer(output->
renderLoop());
 
  313                renderLayer.setDelegate(std::make_unique<SceneDelegate>(
m_cursorScene.get(), output));
 
  314                renderLayer.setOutputLayer(outputLayer);
 
  316                renderLayer.delegate()->prePaint();
 
  318                renderLayer.delegate()->postPaint();
 
  326            outputLayer->setEnabled(
true);
 
  329        if (renderHardwareCursor()) {
 
  330            cursorLayer->setVisible(
false);
 
  333            if (outputLayer && outputLayer->isEnabled()) {
 
  334                outputLayer->setEnabled(
false);
 
  337            cursorLayer->setVisible(cursor->isOnOutput(output));
 
  338            cursorLayer->setGeometry(outputLocalRect);
 
  339            cursorLayer->addRepaintFull();
 
  343    auto moveCursorLayer = [
this, output, cursorLayer, updateCursorLayer]() {
 
  345        const QRectF outputLocalRect = output->
mapFromGlobal(cursor->geometry());
 
  346        const auto outputLayer = 
m_backend->cursorLayer(output);
 
  347        bool hardwareCursor = 
false;
 
  349            if (outputLayer->isEnabled()) {
 
  350                const QRectF nativeCursorRect = output->
transform()
 
  351                                                    .
map(QRectF(outputLocalRect.topLeft() * output->
scale(), outputLayer->size()), output->
pixelSize());
 
  352                outputLayer->setPosition(nativeCursorRect.topLeft());
 
  354            } 
else if (!cursorLayer->isVisible() && !forceSoftwareCursor) {
 
  356                hardwareCursor = updateCursorLayer();
 
  359        cursorLayer->setVisible(cursor->isOnOutput(output) && !hardwareCursor);
 
  360        cursorLayer->setGeometry(outputLocalRect);
 
  361        cursorLayer->addRepaintFull();
 
  372void WaylandCompositor::removeOutput(Output *output)
 
  374    if (output->isPlaceholder()) {
 
  382#include "moc_compositor_wayland.cpp" 
void compositingToggled(bool active)
static Compositor * s_compositor
std::unique_ptr< RenderBackend > m_backend
std::unique_ptr< CursorScene > m_cursorScene
void aboutToToggleCompositing()
void removeSuperLayer(RenderLayer *layer)
RenderBackend * backend() const
std::unique_ptr< WorkspaceScene > m_scene
QHash< RenderLoop *, RenderLayer * > m_superlayers
void addSuperLayer(RenderLayer *layer)
void positionChanged(Cursor *cursor, const QPointF &position)
void currentCursorChanged(Cursor *cursor)
Cursor * currentCursor() const
The OpenGLBackend creates and holds the OpenGL context and is responsible for Texture from Pixmap.
bool isPlaceholder() const
OutputTransform transform() const
QRect mapFromGlobal(const QRect &rect) const
virtual RenderLoop * renderLoop() const =0
virtual bool updateCursorLayer()
~WaylandCompositor() override
static WaylandCompositor * create(QObject *parent=nullptr)
void outputAdded(KWin::Output *)
static Workspace * self()
QList< Output * > outputs() const
const QList< Window * > windows() const
void outputRemoved(KWin::Output *)
KWIN_EXPORT QRect infiniteRegion()
bool hasGLVersion(int major, int minor, int release)
KWIN_EXPORT QRectF scaledRect(const QRectF &rect, qreal scale)