platforms/x11: Move XRenderBackend to platformsupport directory
This change moves the XRender backend to platformsupport directory, similar to the OpenGL and the QPainter backend. This allows to put platform-specific logic in XRenderBackend.
This commit is contained in:
parent
b41a1eba50
commit
d99e6b5d2a
14 changed files with 411 additions and 295 deletions
|
@ -90,6 +90,11 @@ QPainterBackend *Platform::createQPainterBackend()
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
XRenderBackend *Platform::createXRenderBackend()
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void Platform::prepareShutdown()
|
||||
{
|
||||
setOutputsEnabled(false);
|
||||
|
|
|
@ -42,6 +42,7 @@ class Scene;
|
|||
class Screens;
|
||||
class ScreenEdges;
|
||||
class Toplevel;
|
||||
class XRenderBackend;
|
||||
|
||||
namespace Decoration
|
||||
{
|
||||
|
@ -70,6 +71,7 @@ public:
|
|||
virtual Screens *createScreens(QObject *parent = nullptr);
|
||||
virtual OpenGLBackend *createOpenGLBackend();
|
||||
virtual QPainterBackend *createQPainterBackend();
|
||||
virtual XRenderBackend *createXRenderBackend();
|
||||
virtual DmaBufTexture *createDmaBufTexture(const QSize &size) {
|
||||
Q_UNUSED(size);
|
||||
return nullptr;
|
||||
|
|
|
@ -1,2 +1,3 @@
|
|||
add_subdirectory(qpainter)
|
||||
add_subdirectory(opengl)
|
||||
add_subdirectory(xrender)
|
||||
|
|
11
platformsupport/scenes/xrender/CMakeLists.txt
Normal file
11
platformsupport/scenes/xrender/CMakeLists.txt
Normal file
|
@ -0,0 +1,11 @@
|
|||
set(xrenderbackend_SOURCES xrenderbackend.cpp)
|
||||
|
||||
ecm_qt_declare_logging_category(xrenderbackend_SOURCES
|
||||
HEADER logging.h
|
||||
IDENTIFIER KWIN_XRENDER
|
||||
CATEGORY_NAME kwin_scene_xrender
|
||||
DEFAULT_SEVERITY Critical
|
||||
)
|
||||
|
||||
add_library(SceneXRenderBackend STATIC ${xrenderbackend_SOURCES})
|
||||
target_link_libraries(SceneXRenderBackend kwin Qt5::Core Qt5::Gui)
|
78
platformsupport/scenes/xrender/xrenderbackend.cpp
Normal file
78
platformsupport/scenes/xrender/xrenderbackend.cpp
Normal file
|
@ -0,0 +1,78 @@
|
|||
/*
|
||||
KWin - the KDE window manager
|
||||
This file is part of the KDE project.
|
||||
|
||||
SPDX-FileCopyrightText: 2006 Lubos Lunak <l.lunak@kde.org>
|
||||
SPDX-FileCopyrightText: 2009 Fredrik Höglund <fredrik@kde.org>
|
||||
SPDX-FileCopyrightText: 2013 Martin Gräßlin <mgraesslin@kde.org>
|
||||
|
||||
SPDX-License-Identifier: GPL-2.0-or-later
|
||||
*/
|
||||
|
||||
#include "xrenderbackend.h"
|
||||
#include "logging.h"
|
||||
#include "xcbutils.h"
|
||||
|
||||
namespace KWin
|
||||
{
|
||||
|
||||
XRenderBackend::XRenderBackend()
|
||||
: m_buffer(XCB_RENDER_PICTURE_NONE)
|
||||
, m_failed(false)
|
||||
{
|
||||
if (!Xcb::Extensions::self()->isRenderAvailable()) {
|
||||
setFailed("No XRender extension available");
|
||||
return;
|
||||
}
|
||||
if (!Xcb::Extensions::self()->isFixesRegionAvailable()) {
|
||||
setFailed("No XFixes v3+ extension available");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
XRenderBackend::~XRenderBackend()
|
||||
{
|
||||
if (m_buffer) {
|
||||
xcb_render_free_picture(connection(), m_buffer);
|
||||
}
|
||||
}
|
||||
|
||||
OverlayWindow *XRenderBackend::overlayWindow()
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void XRenderBackend::showOverlay()
|
||||
{
|
||||
}
|
||||
|
||||
xcb_render_picture_t XRenderBackend::buffer() const
|
||||
{
|
||||
return m_buffer;
|
||||
}
|
||||
|
||||
void XRenderBackend::setBuffer(xcb_render_picture_t buffer)
|
||||
{
|
||||
if (m_buffer != XCB_RENDER_PICTURE_NONE) {
|
||||
xcb_render_free_picture(connection(), m_buffer);
|
||||
}
|
||||
m_buffer = buffer;
|
||||
}
|
||||
|
||||
bool XRenderBackend::isFailed() const
|
||||
{
|
||||
return m_failed;
|
||||
}
|
||||
|
||||
void XRenderBackend::setFailed(const QString &reason)
|
||||
{
|
||||
qCCritical(KWIN_XRENDER) << "Creating the XRender backend failed: " << reason;
|
||||
m_failed = true;
|
||||
}
|
||||
|
||||
void XRenderBackend::screenGeometryChanged(const QSize &size)
|
||||
{
|
||||
Q_UNUSED(size)
|
||||
}
|
||||
|
||||
} // namespace KWin
|
104
platformsupport/scenes/xrender/xrenderbackend.h
Normal file
104
platformsupport/scenes/xrender/xrenderbackend.h
Normal file
|
@ -0,0 +1,104 @@
|
|||
/*
|
||||
KWin - the KDE window manager
|
||||
This file is part of the KDE project.
|
||||
|
||||
SPDX-FileCopyrightText: 2006 Lubos Lunak <l.lunak@kde.org>
|
||||
|
||||
SPDX-License-Identifier: GPL-2.0-or-later
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <QRegion>
|
||||
#include <QSize>
|
||||
|
||||
#include <xcb/render.h>
|
||||
|
||||
namespace KWin
|
||||
{
|
||||
|
||||
class OverlayWindow;
|
||||
|
||||
/**
|
||||
* @brief Backend for the SceneXRender to hold the compositing buffer and take care of buffer
|
||||
* swapping.
|
||||
*
|
||||
* This class is intended as a small abstraction to support multiple compositing backends in the
|
||||
* SceneXRender.
|
||||
*/
|
||||
class XRenderBackend
|
||||
{
|
||||
public:
|
||||
virtual ~XRenderBackend();
|
||||
virtual void present(int mask, const QRegion &damage) = 0;
|
||||
|
||||
/**
|
||||
* @brief Returns the OverlayWindow used by the backend.
|
||||
*
|
||||
* A backend does not have to use an OverlayWindow, this is mostly for the X world.
|
||||
* In case the backend does not use an OverlayWindow it is allowed to return @c null.
|
||||
* It's the task of the caller to check whether it is @c null.
|
||||
*
|
||||
* @return :OverlayWindow*
|
||||
*/
|
||||
virtual OverlayWindow *overlayWindow();
|
||||
virtual bool usesOverlayWindow() const = 0;
|
||||
/**
|
||||
* @brief Shows the Overlay Window
|
||||
*
|
||||
* Default implementation does nothing.
|
||||
*/
|
||||
virtual void showOverlay();
|
||||
/**
|
||||
* @brief React on screen geometry changes.
|
||||
*
|
||||
* Default implementation does nothing. Override if specific functionality is required.
|
||||
*
|
||||
* @param size The new screen size
|
||||
*/
|
||||
virtual void screenGeometryChanged(const QSize &size);
|
||||
/**
|
||||
* @brief The compositing buffer hold by this backend.
|
||||
*
|
||||
* The Scene composites the new frame into this buffer.
|
||||
*
|
||||
* @return xcb_render_picture_t
|
||||
*/
|
||||
xcb_render_picture_t buffer() const;
|
||||
/**
|
||||
* @brief Whether the creation of the Backend failed.
|
||||
*
|
||||
* The SceneXRender should test whether the Backend got constructed correctly. If this method
|
||||
* returns @c true, the SceneXRender should not try to start the rendering.
|
||||
*
|
||||
* @return bool @c true if the creation of the Backend failed, @c false otherwise.
|
||||
*/
|
||||
bool isFailed() const;
|
||||
|
||||
protected:
|
||||
XRenderBackend();
|
||||
/**
|
||||
* @brief A subclass needs to call this method once it created the compositing back buffer.
|
||||
*
|
||||
* @param buffer The buffer to use for compositing
|
||||
* @return void
|
||||
*/
|
||||
void setBuffer(xcb_render_picture_t buffer);
|
||||
/**
|
||||
* @brief Sets the backend initialization to failed.
|
||||
*
|
||||
* This method should be called by the concrete subclass in case the initialization failed.
|
||||
* The given @p reason is logged as a warning.
|
||||
*
|
||||
* @param reason The reason why the initialization failed.
|
||||
*/
|
||||
void setFailed(const QString &reason);
|
||||
|
||||
private:
|
||||
// Create the compositing buffer. The root window is not double-buffered,
|
||||
// so it is done manually using this buffer,
|
||||
xcb_render_picture_t m_buffer;
|
||||
bool m_failed;
|
||||
};
|
||||
|
||||
} // namespace KWin
|
|
@ -12,6 +12,7 @@ set(X11PLATFORM_SOURCES
|
|||
x11_output.cpp
|
||||
x11_platform.cpp
|
||||
x11cursor.cpp
|
||||
x11xrenderbackend.cpp
|
||||
xfixes_cursor_event_filter.cpp
|
||||
)
|
||||
|
||||
|
@ -24,10 +25,11 @@ if (HAVE_EPOXY_GLX)
|
|||
endif()
|
||||
|
||||
include_directories(${CMAKE_SOURCE_DIR}/platformsupport/scenes/opengl)
|
||||
include_directories(${CMAKE_SOURCE_DIR}/platformsupport/scenes/xrender)
|
||||
|
||||
add_library(KWinX11Platform MODULE ${X11PLATFORM_SOURCES})
|
||||
set_target_properties(KWinX11Platform PROPERTIES LIBRARY_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin/org.kde.kwin.platforms/")
|
||||
target_link_libraries(KWinX11Platform eglx11common kwin kwinxrenderutils SceneOpenGLBackend Qt5::X11Extras XCB::CURSOR KF5::Crash )
|
||||
target_link_libraries(KWinX11Platform eglx11common kwin kwinxrenderutils SceneOpenGLBackend SceneXRenderBackend Qt5::X11Extras XCB::CURSOR KF5::Crash )
|
||||
if (X11_Xinput_FOUND)
|
||||
target_link_libraries(KWinX11Platform ${X11_Xinput_LIB})
|
||||
endif()
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
#include "x11cursor.h"
|
||||
#include "edge.h"
|
||||
#include "windowselector.h"
|
||||
#include "x11xrenderbackend.h"
|
||||
#include <config-kwin.h>
|
||||
#include <kwinconfig.h>
|
||||
#if HAVE_EPOXY_GLX
|
||||
|
@ -119,6 +120,11 @@ OpenGLBackend *X11StandalonePlatform::createOpenGLBackend()
|
|||
}
|
||||
}
|
||||
|
||||
XRenderBackend *X11StandalonePlatform::createXRenderBackend()
|
||||
{
|
||||
return new X11XRenderBackend(this);
|
||||
}
|
||||
|
||||
Edge *X11StandalonePlatform::createScreenEdge(ScreenEdges *edges)
|
||||
{
|
||||
if (m_screenEdgesFilter.isNull()) {
|
||||
|
|
|
@ -35,6 +35,7 @@ public:
|
|||
|
||||
Screens *createScreens(QObject *parent = nullptr) override;
|
||||
OpenGLBackend *createOpenGLBackend() override;
|
||||
XRenderBackend *createXRenderBackend() override;
|
||||
Edge *createScreenEdge(ScreenEdges *parent) override;
|
||||
void createPlatformCursor(QObject *parent = nullptr) override;
|
||||
bool requiresCompositing() const override;
|
||||
|
|
133
plugins/platforms/x11/standalone/x11xrenderbackend.cpp
Normal file
133
plugins/platforms/x11/standalone/x11xrenderbackend.cpp
Normal file
|
@ -0,0 +1,133 @@
|
|||
/*
|
||||
KWin - the KDE window manager
|
||||
This file is part of the KDE project.
|
||||
|
||||
SPDX-FileCopyrightText: 2006 Lubos Lunak <l.lunak@kde.org>
|
||||
SPDX-FileCopyrightText: 2009 Fredrik Höglund <fredrik@kde.org>
|
||||
SPDX-FileCopyrightText: 2013 Martin Gräßlin <mgraesslin@kde.org>
|
||||
|
||||
SPDX-License-Identifier: GPL-2.0-or-later
|
||||
*/
|
||||
|
||||
#include "x11xrenderbackend.h"
|
||||
#include "main.h"
|
||||
#include "platform.h"
|
||||
#include "overlaywindow.h"
|
||||
#include "scene.h"
|
||||
#include "screens.h"
|
||||
#include "utils.h"
|
||||
#include "x11_platform.h"
|
||||
|
||||
#include "kwinxrenderutils.h"
|
||||
|
||||
namespace KWin
|
||||
{
|
||||
|
||||
X11XRenderBackend::X11XRenderBackend(X11StandalonePlatform *backend)
|
||||
: XRenderBackend()
|
||||
, m_backend(backend)
|
||||
, m_overlayWindow(backend->createOverlayWindow())
|
||||
, m_front(XCB_RENDER_PICTURE_NONE)
|
||||
, m_format(0)
|
||||
{
|
||||
init(true);
|
||||
}
|
||||
|
||||
X11XRenderBackend::~X11XRenderBackend()
|
||||
{
|
||||
if (m_front) {
|
||||
xcb_render_free_picture(connection(), m_front);
|
||||
}
|
||||
m_overlayWindow->destroy();
|
||||
}
|
||||
|
||||
OverlayWindow *X11XRenderBackend::overlayWindow()
|
||||
{
|
||||
return m_overlayWindow.data();
|
||||
}
|
||||
|
||||
void X11XRenderBackend::showOverlay()
|
||||
{
|
||||
if (m_overlayWindow->window()) { // show the window only after the first pass, since
|
||||
m_overlayWindow->show(); // that pass may take long
|
||||
}
|
||||
}
|
||||
|
||||
void X11XRenderBackend::init(bool createOverlay)
|
||||
{
|
||||
if (m_front != XCB_RENDER_PICTURE_NONE)
|
||||
xcb_render_free_picture(connection(), m_front);
|
||||
bool haveOverlay = createOverlay ? m_overlayWindow->create() : (m_overlayWindow->window() != XCB_WINDOW_NONE);
|
||||
if (haveOverlay) {
|
||||
m_overlayWindow->setup(XCB_WINDOW_NONE);
|
||||
ScopedCPointer<xcb_get_window_attributes_reply_t> attribs(xcb_get_window_attributes_reply(connection(),
|
||||
xcb_get_window_attributes_unchecked(connection(), m_overlayWindow->window()), nullptr));
|
||||
if (!attribs) {
|
||||
setFailed("Failed getting window attributes for overlay window");
|
||||
return;
|
||||
}
|
||||
m_format = XRenderUtils::findPictFormat(attribs->visual);
|
||||
if (m_format == 0) {
|
||||
setFailed("Failed to find XRender format for overlay window");
|
||||
return;
|
||||
}
|
||||
m_front = xcb_generate_id(connection());
|
||||
xcb_render_create_picture(connection(), m_front, m_overlayWindow->window(), m_format, 0, nullptr);
|
||||
} else {
|
||||
// create XRender picture for the root window
|
||||
m_format = XRenderUtils::findPictFormat(kwinApp()->x11DefaultScreen()->root_visual);
|
||||
if (m_format == 0) {
|
||||
setFailed("Failed to find XRender format for root window");
|
||||
return; // error
|
||||
}
|
||||
m_front = xcb_generate_id(connection());
|
||||
const uint32_t values[] = {XCB_SUBWINDOW_MODE_INCLUDE_INFERIORS};
|
||||
xcb_render_create_picture(connection(), m_front, rootWindow(), m_format, XCB_RENDER_CP_SUBWINDOW_MODE, values);
|
||||
}
|
||||
createBuffer();
|
||||
}
|
||||
|
||||
void X11XRenderBackend::createBuffer()
|
||||
{
|
||||
xcb_pixmap_t pixmap = xcb_generate_id(connection());
|
||||
const auto displaySize = screens()->displaySize();
|
||||
xcb_create_pixmap(connection(), Xcb::defaultDepth(), pixmap, rootWindow(), displaySize.width(), displaySize.height());
|
||||
xcb_render_picture_t b = xcb_generate_id(connection());
|
||||
xcb_render_create_picture(connection(), b, pixmap, m_format, 0, nullptr);
|
||||
xcb_free_pixmap(connection(), pixmap); // The picture owns the pixmap now
|
||||
setBuffer(b);
|
||||
}
|
||||
|
||||
void X11XRenderBackend::present(int mask, const QRegion &damage)
|
||||
{
|
||||
const auto displaySize = screens()->displaySize();
|
||||
if (mask & Scene::PAINT_SCREEN_REGION) {
|
||||
// Use the damage region as the clip region for the root window
|
||||
XFixesRegion frontRegion(damage);
|
||||
xcb_xfixes_set_picture_clip_region(connection(), m_front, frontRegion, 0, 0);
|
||||
// copy composed buffer to the root window
|
||||
xcb_xfixes_set_picture_clip_region(connection(), buffer(), XCB_XFIXES_REGION_NONE, 0, 0);
|
||||
xcb_render_composite(connection(), XCB_RENDER_PICT_OP_SRC, buffer(), XCB_RENDER_PICTURE_NONE,
|
||||
m_front, 0, 0, 0, 0, 0, 0, displaySize.width(), displaySize.height());
|
||||
xcb_xfixes_set_picture_clip_region(connection(), m_front, XCB_XFIXES_REGION_NONE, 0, 0);
|
||||
} else {
|
||||
// copy composed buffer to the root window
|
||||
xcb_render_composite(connection(), XCB_RENDER_PICT_OP_SRC, buffer(), XCB_RENDER_PICTURE_NONE,
|
||||
m_front, 0, 0, 0, 0, 0, 0, displaySize.width(), displaySize.height());
|
||||
}
|
||||
|
||||
xcb_flush(connection());
|
||||
}
|
||||
|
||||
void X11XRenderBackend::screenGeometryChanged(const QSize &size)
|
||||
{
|
||||
Q_UNUSED(size)
|
||||
init(false);
|
||||
}
|
||||
|
||||
bool X11XRenderBackend::usesOverlayWindow() const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace KWin
|
43
plugins/platforms/x11/standalone/x11xrenderbackend.h
Normal file
43
plugins/platforms/x11/standalone/x11xrenderbackend.h
Normal file
|
@ -0,0 +1,43 @@
|
|||
/*
|
||||
KWin - the KDE window manager
|
||||
This file is part of the KDE project.
|
||||
|
||||
SPDX-FileCopyrightText: 2006 Lubos Lunak <l.lunak@kde.org>
|
||||
|
||||
SPDX-License-Identifier: GPL-2.0-or-later
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "xrenderbackend.h"
|
||||
|
||||
namespace KWin
|
||||
{
|
||||
|
||||
class X11StandalonePlatform;
|
||||
|
||||
/**
|
||||
* @brief XRenderBackend using an X11 Overlay Window as compositing target.
|
||||
*/
|
||||
class X11XRenderBackend : public XRenderBackend
|
||||
{
|
||||
public:
|
||||
explicit X11XRenderBackend(X11StandalonePlatform *backend);
|
||||
~X11XRenderBackend() override;
|
||||
|
||||
void present(int mask, const QRegion &damage) override;
|
||||
OverlayWindow *overlayWindow() override;
|
||||
void showOverlay() override;
|
||||
void screenGeometryChanged(const QSize &size) override;
|
||||
bool usesOverlayWindow() const override;
|
||||
|
||||
private:
|
||||
void init(bool createOverlay);
|
||||
void createBuffer();
|
||||
X11StandalonePlatform *m_backend;
|
||||
QScopedPointer<OverlayWindow> m_overlayWindow;
|
||||
xcb_render_picture_t m_front;
|
||||
xcb_render_pictformat_t m_format;
|
||||
};
|
||||
|
||||
} // namespace KWin
|
|
@ -12,12 +12,11 @@ ecm_qt_declare_logging_category(
|
|||
Critical
|
||||
)
|
||||
|
||||
include_directories(${CMAKE_SOURCE_DIR}/platformsupport/scenes/xrender)
|
||||
|
||||
add_library(KWinSceneXRender MODULE ${SCENE_XRENDER_SRCS})
|
||||
set_target_properties(KWinSceneXRender PROPERTIES LIBRARY_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin/org.kde.kwin.scenes/")
|
||||
target_link_libraries(KWinSceneXRender
|
||||
kwin
|
||||
kwinxrenderutils
|
||||
)
|
||||
target_link_libraries(KWinSceneXRender kwin kwinxrenderutils SceneXRenderBackend)
|
||||
|
||||
install(
|
||||
TARGETS
|
||||
|
|
|
@ -9,8 +9,8 @@
|
|||
SPDX-License-Identifier: GPL-2.0-or-later
|
||||
*/
|
||||
#include "scene_xrender.h"
|
||||
|
||||
#include "utils.h"
|
||||
#include "xrenderbackend.h"
|
||||
|
||||
#ifdef KWIN_HAVE_XRENDER_COMPOSITING
|
||||
|
||||
|
@ -44,177 +44,14 @@ ScreenPaintData SceneXrender::screen_paint;
|
|||
#define DOUBLE_TO_FIXED(d) ((xcb_render_fixed_t) ((d) * 65536))
|
||||
#define FIXED_TO_DOUBLE(f) ((double) ((f) / 65536.0))
|
||||
|
||||
|
||||
//****************************************
|
||||
// XRenderBackend
|
||||
//****************************************
|
||||
XRenderBackend::XRenderBackend()
|
||||
: m_buffer(XCB_RENDER_PICTURE_NONE)
|
||||
, m_failed(false)
|
||||
{
|
||||
if (!Xcb::Extensions::self()->isRenderAvailable()) {
|
||||
setFailed("No XRender extension available");
|
||||
return;
|
||||
}
|
||||
if (!Xcb::Extensions::self()->isFixesRegionAvailable()) {
|
||||
setFailed("No XFixes v3+ extension available");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
XRenderBackend::~XRenderBackend()
|
||||
{
|
||||
if (m_buffer) {
|
||||
xcb_render_free_picture(connection(), m_buffer);
|
||||
}
|
||||
}
|
||||
|
||||
OverlayWindow* XRenderBackend::overlayWindow()
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void XRenderBackend::showOverlay()
|
||||
{
|
||||
}
|
||||
|
||||
void XRenderBackend::setBuffer(xcb_render_picture_t buffer)
|
||||
{
|
||||
if (m_buffer != XCB_RENDER_PICTURE_NONE) {
|
||||
xcb_render_free_picture(connection(), m_buffer);
|
||||
}
|
||||
m_buffer = buffer;
|
||||
}
|
||||
|
||||
void XRenderBackend::setFailed(const QString& reason)
|
||||
{
|
||||
qCCritical(KWIN_XRENDER) << "Creating the XRender backend failed: " << reason;
|
||||
m_failed = true;
|
||||
}
|
||||
|
||||
void XRenderBackend::screenGeometryChanged(const QSize &size)
|
||||
{
|
||||
Q_UNUSED(size)
|
||||
}
|
||||
|
||||
|
||||
//****************************************
|
||||
// X11XRenderBackend
|
||||
//****************************************
|
||||
X11XRenderBackend::X11XRenderBackend()
|
||||
: XRenderBackend()
|
||||
, m_overlayWindow(kwinApp()->platform()->createOverlayWindow())
|
||||
, m_front(XCB_RENDER_PICTURE_NONE)
|
||||
, m_format(0)
|
||||
{
|
||||
init(true);
|
||||
}
|
||||
|
||||
X11XRenderBackend::~X11XRenderBackend()
|
||||
{
|
||||
if (m_front) {
|
||||
xcb_render_free_picture(connection(), m_front);
|
||||
}
|
||||
m_overlayWindow->destroy();
|
||||
}
|
||||
|
||||
OverlayWindow* X11XRenderBackend::overlayWindow()
|
||||
{
|
||||
return m_overlayWindow.data();
|
||||
}
|
||||
|
||||
void X11XRenderBackend::showOverlay()
|
||||
{
|
||||
if (m_overlayWindow->window()) // show the window only after the first pass, since
|
||||
m_overlayWindow->show(); // that pass may take long
|
||||
}
|
||||
|
||||
void X11XRenderBackend::init(bool createOverlay)
|
||||
{
|
||||
if (m_front != XCB_RENDER_PICTURE_NONE)
|
||||
xcb_render_free_picture(connection(), m_front);
|
||||
bool haveOverlay = createOverlay ? m_overlayWindow->create() : (m_overlayWindow->window() != XCB_WINDOW_NONE);
|
||||
if (haveOverlay) {
|
||||
m_overlayWindow->setup(XCB_WINDOW_NONE);
|
||||
ScopedCPointer<xcb_get_window_attributes_reply_t> attribs(xcb_get_window_attributes_reply(connection(),
|
||||
xcb_get_window_attributes_unchecked(connection(), m_overlayWindow->window()), nullptr));
|
||||
if (!attribs) {
|
||||
setFailed("Failed getting window attributes for overlay window");
|
||||
return;
|
||||
}
|
||||
m_format = XRenderUtils::findPictFormat(attribs->visual);
|
||||
if (m_format == 0) {
|
||||
setFailed("Failed to find XRender format for overlay window");
|
||||
return;
|
||||
}
|
||||
m_front = xcb_generate_id(connection());
|
||||
xcb_render_create_picture(connection(), m_front, m_overlayWindow->window(), m_format, 0, nullptr);
|
||||
} else {
|
||||
// create XRender picture for the root window
|
||||
m_format = XRenderUtils::findPictFormat(kwinApp()->x11DefaultScreen()->root_visual);
|
||||
if (m_format == 0) {
|
||||
setFailed("Failed to find XRender format for root window");
|
||||
return; // error
|
||||
}
|
||||
m_front = xcb_generate_id(connection());
|
||||
const uint32_t values[] = {XCB_SUBWINDOW_MODE_INCLUDE_INFERIORS};
|
||||
xcb_render_create_picture(connection(), m_front, rootWindow(), m_format, XCB_RENDER_CP_SUBWINDOW_MODE, values);
|
||||
}
|
||||
createBuffer();
|
||||
}
|
||||
|
||||
void X11XRenderBackend::createBuffer()
|
||||
{
|
||||
xcb_pixmap_t pixmap = xcb_generate_id(connection());
|
||||
const auto displaySize = screens()->displaySize();
|
||||
xcb_create_pixmap(connection(), Xcb::defaultDepth(), pixmap, rootWindow(), displaySize.width(), displaySize.height());
|
||||
xcb_render_picture_t b = xcb_generate_id(connection());
|
||||
xcb_render_create_picture(connection(), b, pixmap, m_format, 0, nullptr);
|
||||
xcb_free_pixmap(connection(), pixmap); // The picture owns the pixmap now
|
||||
setBuffer(b);
|
||||
}
|
||||
|
||||
void X11XRenderBackend::present(int mask, const QRegion &damage)
|
||||
{
|
||||
const auto displaySize = screens()->displaySize();
|
||||
if (mask & Scene::PAINT_SCREEN_REGION) {
|
||||
// Use the damage region as the clip region for the root window
|
||||
XFixesRegion frontRegion(damage);
|
||||
xcb_xfixes_set_picture_clip_region(connection(), m_front, frontRegion, 0, 0);
|
||||
// copy composed buffer to the root window
|
||||
xcb_xfixes_set_picture_clip_region(connection(), buffer(), XCB_XFIXES_REGION_NONE, 0, 0);
|
||||
xcb_render_composite(connection(), XCB_RENDER_PICT_OP_SRC, buffer(), XCB_RENDER_PICTURE_NONE,
|
||||
m_front, 0, 0, 0, 0, 0, 0, displaySize.width(), displaySize.height());
|
||||
xcb_xfixes_set_picture_clip_region(connection(), m_front, XCB_XFIXES_REGION_NONE, 0, 0);
|
||||
xcb_flush(connection());
|
||||
} else {
|
||||
// copy composed buffer to the root window
|
||||
xcb_render_composite(connection(), XCB_RENDER_PICT_OP_SRC, buffer(), XCB_RENDER_PICTURE_NONE,
|
||||
m_front, 0, 0, 0, 0, 0, 0, displaySize.width(), displaySize.height());
|
||||
xcb_flush(connection());
|
||||
}
|
||||
}
|
||||
|
||||
void X11XRenderBackend::screenGeometryChanged(const QSize &size)
|
||||
{
|
||||
Q_UNUSED(size)
|
||||
init(false);
|
||||
}
|
||||
|
||||
bool X11XRenderBackend::usesOverlayWindow() const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
//****************************************
|
||||
// SceneXrender
|
||||
//****************************************
|
||||
|
||||
SceneXrender* SceneXrender::createScene(QObject *parent)
|
||||
{
|
||||
QScopedPointer<XRenderBackend> backend;
|
||||
backend.reset(new X11XRenderBackend);
|
||||
if (backend->isFailed()) {
|
||||
QScopedPointer<XRenderBackend> backend(kwinApp()->platform()->createXRenderBackend());
|
||||
if (!backend || backend->isFailed()) {
|
||||
return nullptr;
|
||||
}
|
||||
return new SceneXrender(backend.take(), parent);
|
||||
|
@ -781,6 +618,21 @@ void SceneXrender::screenGeometryChanged(const QSize &size)
|
|||
m_backend->screenGeometryChanged(size);
|
||||
}
|
||||
|
||||
xcb_render_picture_t SceneXrender::xrenderBufferPicture() const
|
||||
{
|
||||
return m_backend->buffer();
|
||||
}
|
||||
|
||||
OverlayWindow *SceneXrender::overlayWindow() const
|
||||
{
|
||||
return m_backend->overlayWindow();
|
||||
}
|
||||
|
||||
bool SceneXrender::usesOverlayWindow() const
|
||||
{
|
||||
return m_backend->usesOverlayWindow();
|
||||
}
|
||||
|
||||
//****************************************
|
||||
// XRenderWindowPixmap
|
||||
//****************************************
|
||||
|
|
|
@ -19,118 +19,7 @@
|
|||
namespace KWin
|
||||
{
|
||||
|
||||
namespace Xcb
|
||||
{
|
||||
class Shm;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Backend for the SceneXRender to hold the compositing buffer and take care of buffer
|
||||
* swapping.
|
||||
*
|
||||
* This class is intended as a small abstraction to support multiple compositing backends in the
|
||||
* SceneXRender.
|
||||
*/
|
||||
class XRenderBackend
|
||||
{
|
||||
public:
|
||||
virtual ~XRenderBackend();
|
||||
virtual void present(int mask, const QRegion &damage) = 0;
|
||||
|
||||
/**
|
||||
* @brief Returns the OverlayWindow used by the backend.
|
||||
*
|
||||
* A backend does not have to use an OverlayWindow, this is mostly for the X world.
|
||||
* In case the backend does not use an OverlayWindow it is allowed to return @c null.
|
||||
* It's the task of the caller to check whether it is @c null.
|
||||
*
|
||||
* @return :OverlayWindow*
|
||||
*/
|
||||
virtual OverlayWindow *overlayWindow();
|
||||
virtual bool usesOverlayWindow() const = 0;
|
||||
/**
|
||||
* @brief Shows the Overlay Window
|
||||
*
|
||||
* Default implementation does nothing.
|
||||
*/
|
||||
virtual void showOverlay();
|
||||
/**
|
||||
* @brief React on screen geometry changes.
|
||||
*
|
||||
* Default implementation does nothing. Override if specific functionality is required.
|
||||
*
|
||||
* @param size The new screen size
|
||||
*/
|
||||
virtual void screenGeometryChanged(const QSize &size);
|
||||
/**
|
||||
* @brief The compositing buffer hold by this backend.
|
||||
*
|
||||
* The Scene composites the new frame into this buffer.
|
||||
*
|
||||
* @return xcb_render_picture_t
|
||||
*/
|
||||
xcb_render_picture_t buffer() const {
|
||||
return m_buffer;
|
||||
}
|
||||
/**
|
||||
* @brief Whether the creation of the Backend failed.
|
||||
*
|
||||
* The SceneXRender should test whether the Backend got constructed correctly. If this method
|
||||
* returns @c true, the SceneXRender should not try to start the rendering.
|
||||
*
|
||||
* @return bool @c true if the creation of the Backend failed, @c false otherwise.
|
||||
*/
|
||||
bool isFailed() const {
|
||||
return m_failed;
|
||||
}
|
||||
|
||||
protected:
|
||||
XRenderBackend();
|
||||
/**
|
||||
* @brief A subclass needs to call this method once it created the compositing back buffer.
|
||||
*
|
||||
* @param buffer The buffer to use for compositing
|
||||
* @return void
|
||||
*/
|
||||
void setBuffer(xcb_render_picture_t buffer);
|
||||
/**
|
||||
* @brief Sets the backend initialization to failed.
|
||||
*
|
||||
* This method should be called by the concrete subclass in case the initialization failed.
|
||||
* The given @p reason is logged as a warning.
|
||||
*
|
||||
* @param reason The reason why the initialization failed.
|
||||
*/
|
||||
void setFailed(const QString &reason);
|
||||
|
||||
private:
|
||||
// Create the compositing buffer. The root window is not double-buffered,
|
||||
// so it is done manually using this buffer,
|
||||
xcb_render_picture_t m_buffer;
|
||||
bool m_failed;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief XRenderBackend using an X11 Overlay Window as compositing target.
|
||||
*/
|
||||
class X11XRenderBackend : public XRenderBackend
|
||||
{
|
||||
public:
|
||||
X11XRenderBackend();
|
||||
~X11XRenderBackend() override;
|
||||
|
||||
void present(int mask, const QRegion &damage) override;
|
||||
OverlayWindow* overlayWindow() override;
|
||||
void showOverlay() override;
|
||||
void screenGeometryChanged(const QSize &size) override;
|
||||
bool usesOverlayWindow() const override;
|
||||
private:
|
||||
void init(bool createOverlay);
|
||||
void createBuffer();
|
||||
QScopedPointer<OverlayWindow> m_overlayWindow;
|
||||
xcb_render_picture_t m_front;
|
||||
xcb_render_pictformat_t m_format;
|
||||
};
|
||||
class XRenderBackend;
|
||||
|
||||
class SceneXrender
|
||||
: public Scene
|
||||
|
@ -148,12 +37,8 @@ public:
|
|||
Shadow *createShadow(Toplevel *toplevel) override;
|
||||
void screenGeometryChanged(const QSize &size) override;
|
||||
xcb_render_picture_t xrenderBufferPicture() const override;
|
||||
OverlayWindow *overlayWindow() const override {
|
||||
return m_backend->overlayWindow();
|
||||
}
|
||||
bool usesOverlayWindow() const override {
|
||||
return m_backend->usesOverlayWindow();
|
||||
}
|
||||
OverlayWindow *overlayWindow() const override;
|
||||
bool usesOverlayWindow() const override;
|
||||
Decoration::Renderer *createDecorationRenderer(Decoration::DecoratedClientImpl *client) override;
|
||||
|
||||
bool animationsSupported() const override {
|
||||
|
@ -243,12 +128,6 @@ private:
|
|||
static XRenderPicture* s_effectFrameCircle;
|
||||
};
|
||||
|
||||
inline
|
||||
xcb_render_picture_t SceneXrender::xrenderBufferPicture() const
|
||||
{
|
||||
return m_backend->buffer();
|
||||
}
|
||||
|
||||
inline
|
||||
QRegion SceneXrender::Window::transformedShape() const
|
||||
{
|
||||
|
|
Loading…
Reference in a new issue