Introduce an XRenderBackend similar to OpenGLBackend
An abstract backend is split out of SceneXRender which takes care of managing the render pictures and swapping them after a frame is rendered. Having this abstract allows to implement further backends for XRender which do not use the Overlay Window for compositing. To have it consistant the SceneXRender is now also created by a factory method.
This commit is contained in:
parent
2cf7a4bad3
commit
cfa1ead9e1
3 changed files with 271 additions and 97 deletions
|
@ -207,7 +207,7 @@ void Compositor::slotCompositingOptionsInitialized()
|
||||||
#ifdef KWIN_HAVE_XRENDER_COMPOSITING
|
#ifdef KWIN_HAVE_XRENDER_COMPOSITING
|
||||||
case XRenderCompositing:
|
case XRenderCompositing:
|
||||||
qDebug() << "Initializing XRender compositing";
|
qDebug() << "Initializing XRender compositing";
|
||||||
m_scene = new SceneXrender(Workspace::self());
|
m_scene = SceneXrender::createScene();
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
default:
|
default:
|
||||||
|
|
|
@ -30,6 +30,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
#include "effects.h"
|
#include "effects.h"
|
||||||
#include "overlaywindow.h"
|
#include "overlaywindow.h"
|
||||||
#include "paintredirector.h"
|
#include "paintredirector.h"
|
||||||
|
#include "workspace.h"
|
||||||
#include "xcbutils.h"
|
#include "xcbutils.h"
|
||||||
#include "kwinxrenderutils.h"
|
#include "kwinxrenderutils.h"
|
||||||
|
|
||||||
|
@ -42,11 +43,6 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
namespace KWin
|
namespace KWin
|
||||||
{
|
{
|
||||||
|
|
||||||
//****************************************
|
|
||||||
// SceneXrender
|
|
||||||
//****************************************
|
|
||||||
|
|
||||||
xcb_render_picture_t SceneXrender::buffer = XCB_RENDER_PICTURE_NONE;
|
|
||||||
ScreenPaintData SceneXrender::screen_paint;
|
ScreenPaintData SceneXrender::screen_paint;
|
||||||
|
|
||||||
#define DOUBLE_TO_FIXED(d) ((xcb_render_fixed_t) ((d) * 65536))
|
#define DOUBLE_TO_FIXED(d) ((xcb_render_fixed_t) ((d) * 65536))
|
||||||
|
@ -89,92 +85,187 @@ static xcb_render_pictformat_t findFormatForVisual(xcb_visualid_t visual)
|
||||||
return s_cache.value(visual, 0);
|
return s_cache.value(visual, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
SceneXrender::SceneXrender(Workspace* ws)
|
//****************************************
|
||||||
: Scene(ws)
|
// XRenderBackend
|
||||||
, format(0)
|
//****************************************
|
||||||
, front(XCB_RENDER_PICTURE_NONE)
|
XRenderBackend::XRenderBackend()
|
||||||
, m_overlayWindow(new OverlayWindow())
|
: m_buffer(XCB_RENDER_PICTURE_NONE)
|
||||||
, init_ok(false)
|
, m_failed(false)
|
||||||
{
|
{
|
||||||
if (!Xcb::Extensions::self()->isRenderAvailable()) {
|
if (!Xcb::Extensions::self()->isRenderAvailable()) {
|
||||||
qCritical() << "No XRender extension available";
|
setFailed("No XRender extension available");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (!Xcb::Extensions::self()->isFixesRegionAvailable()) {
|
if (!Xcb::Extensions::self()->isFixesRegionAvailable()) {
|
||||||
qCritical() << "No XFixes v3+ extension available";
|
setFailed("No XFixes v3+ extension available");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
initXRender(true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
SceneXrender::~SceneXrender()
|
XRenderBackend::~XRenderBackend()
|
||||||
{
|
{
|
||||||
if (!init_ok) {
|
if (m_buffer) {
|
||||||
// TODO this probably needs to clean up whatever has been created until the failure
|
xcb_render_free_picture(connection(), m_buffer);
|
||||||
m_overlayWindow->destroy();
|
}
|
||||||
return;
|
}
|
||||||
|
|
||||||
|
OverlayWindow* XRenderBackend::overlayWindow()
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
qCritical() << "Creating the XRender backend failed: " << reason;
|
||||||
|
m_failed = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void XRenderBackend::screenGeometryChanged(const QSize &size)
|
||||||
|
{
|
||||||
|
Q_UNUSED(size)
|
||||||
|
}
|
||||||
|
|
||||||
|
//****************************************
|
||||||
|
// X11XRenderBackend
|
||||||
|
//****************************************
|
||||||
|
X11XRenderBackend::X11XRenderBackend()
|
||||||
|
: XRenderBackend()
|
||||||
|
, m_overlayWindow(new OverlayWindow())
|
||||||
|
, m_front(XCB_RENDER_PICTURE_NONE)
|
||||||
|
, m_format(0)
|
||||||
|
{
|
||||||
|
init(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
X11XRenderBackend::~X11XRenderBackend()
|
||||||
|
{
|
||||||
|
if (m_front) {
|
||||||
|
xcb_render_free_picture(connection(), m_front);
|
||||||
}
|
}
|
||||||
SceneXrender::Window::cleanup();
|
|
||||||
SceneXrender::EffectFrame::cleanup();
|
|
||||||
xcb_render_free_picture(connection(), front);
|
|
||||||
xcb_render_free_picture(connection(), buffer);
|
|
||||||
buffer = XCB_RENDER_PICTURE_NONE;
|
|
||||||
m_overlayWindow->destroy();
|
m_overlayWindow->destroy();
|
||||||
delete m_overlayWindow;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SceneXrender::initXRender(bool createOverlay)
|
OverlayWindow* X11XRenderBackend::overlayWindow()
|
||||||
{
|
{
|
||||||
init_ok = false;
|
return m_overlayWindow.data();
|
||||||
if (front != XCB_RENDER_PICTURE_NONE)
|
}
|
||||||
xcb_render_free_picture(connection(), front);
|
|
||||||
|
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);
|
bool haveOverlay = createOverlay ? m_overlayWindow->create() : (m_overlayWindow->window() != XCB_WINDOW_NONE);
|
||||||
if (haveOverlay) {
|
if (haveOverlay) {
|
||||||
m_overlayWindow->setup(XCB_WINDOW_NONE);
|
m_overlayWindow->setup(XCB_WINDOW_NONE);
|
||||||
ScopedCPointer<xcb_get_window_attributes_reply_t> attribs(xcb_get_window_attributes_reply(connection(),
|
ScopedCPointer<xcb_get_window_attributes_reply_t> attribs(xcb_get_window_attributes_reply(connection(),
|
||||||
xcb_get_window_attributes_unchecked(connection(), m_overlayWindow->window()), NULL));
|
xcb_get_window_attributes_unchecked(connection(), m_overlayWindow->window()), NULL));
|
||||||
if (!attribs) {
|
if (!attribs) {
|
||||||
qCritical() << "Failed getting window attributes for overlay window";
|
setFailed("Failed getting window attributes for overlay window");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
format = findFormatForVisual(attribs->visual);
|
m_format = findFormatForVisual(attribs->visual);
|
||||||
if (format == 0) {
|
if (m_format == 0) {
|
||||||
qCritical() << "Failed to find XRender format for overlay window";
|
setFailed("Failed to find XRender format for overlay window");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
front = xcb_generate_id(connection());
|
m_front = xcb_generate_id(connection());
|
||||||
xcb_render_create_picture(connection(), front, m_overlayWindow->window(), format, 0, NULL);
|
xcb_render_create_picture(connection(), m_front, m_overlayWindow->window(), m_format, 0, NULL);
|
||||||
} else {
|
} else {
|
||||||
// create XRender picture for the root window
|
// create XRender picture for the root window
|
||||||
format = findFormatForVisual(defaultScreen()->root_visual);
|
m_format = findFormatForVisual(defaultScreen()->root_visual);
|
||||||
if (format == 0) {
|
if (m_format == 0) {
|
||||||
qCritical() << "Failed to find XRender format for root window";
|
setFailed("Failed to find XRender format for root window");
|
||||||
return; // error
|
return; // error
|
||||||
}
|
}
|
||||||
front = xcb_generate_id(connection());
|
m_front = xcb_generate_id(connection());
|
||||||
const uint32_t values[] = {XCB_SUBWINDOW_MODE_INCLUDE_INFERIORS};
|
const uint32_t values[] = {XCB_SUBWINDOW_MODE_INCLUDE_INFERIORS};
|
||||||
xcb_render_create_picture(connection(), front, rootWindow(), format, XCB_RENDER_CP_SUBWINDOW_MODE, values);
|
xcb_render_create_picture(connection(), m_front, rootWindow(), m_format, XCB_RENDER_CP_SUBWINDOW_MODE, values);
|
||||||
}
|
}
|
||||||
createBuffer();
|
createBuffer();
|
||||||
init_ok = true;
|
}
|
||||||
|
|
||||||
|
void X11XRenderBackend::createBuffer()
|
||||||
|
{
|
||||||
|
xcb_pixmap_t pixmap = xcb_generate_id(connection());
|
||||||
|
xcb_create_pixmap(connection(), Xcb::defaultDepth(), pixmap, rootWindow(), displayWidth(), displayHeight());
|
||||||
|
xcb_render_picture_t b = xcb_generate_id(connection());
|
||||||
|
xcb_render_create_picture(connection(), b, pixmap, m_format, 0, NULL);
|
||||||
|
xcb_free_pixmap(connection(), pixmap); // The picture owns the pixmap now
|
||||||
|
setBuffer(b);
|
||||||
|
}
|
||||||
|
|
||||||
|
void X11XRenderBackend::present(int mask, const QRegion &damage)
|
||||||
|
{
|
||||||
|
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, displayWidth(), displayHeight());
|
||||||
|
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, displayWidth(), displayHeight());
|
||||||
|
xcb_flush(connection());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void X11XRenderBackend::screenGeometryChanged(const QSize &size)
|
||||||
|
{
|
||||||
|
Q_UNUSED(size)
|
||||||
|
init(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
//****************************************
|
||||||
|
// SceneXrender
|
||||||
|
//****************************************
|
||||||
|
SceneXrender* SceneXrender::createScene()
|
||||||
|
{
|
||||||
|
QScopedPointer<XRenderBackend> backend;
|
||||||
|
backend.reset(new X11XRenderBackend);
|
||||||
|
if (backend->isFailed()) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
return new SceneXrender(backend.take());
|
||||||
|
}
|
||||||
|
|
||||||
|
SceneXrender::SceneXrender(XRenderBackend *backend)
|
||||||
|
: Scene(Workspace::self())
|
||||||
|
, m_backend(backend)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
SceneXrender::~SceneXrender()
|
||||||
|
{
|
||||||
|
SceneXrender::Window::cleanup();
|
||||||
|
SceneXrender::EffectFrame::cleanup();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SceneXrender::initFailed() const
|
bool SceneXrender::initFailed() const
|
||||||
{
|
{
|
||||||
return !init_ok;
|
return false;
|
||||||
}
|
|
||||||
|
|
||||||
// Create the compositing buffer. The root window is not double-buffered,
|
|
||||||
// so it is done manually using this buffer,
|
|
||||||
void SceneXrender::createBuffer()
|
|
||||||
{
|
|
||||||
if (buffer != XCB_RENDER_PICTURE_NONE)
|
|
||||||
xcb_render_free_picture(connection(), buffer);
|
|
||||||
xcb_pixmap_t pixmap = xcb_generate_id(connection());
|
|
||||||
xcb_create_pixmap(connection(), Xcb::defaultDepth(), pixmap, rootWindow(), displayWidth(), displayHeight());
|
|
||||||
buffer = xcb_generate_id(connection());
|
|
||||||
xcb_render_create_picture(connection(), buffer, pixmap, format, 0, NULL);
|
|
||||||
xcb_free_pixmap(connection(), pixmap); // The picture owns the pixmap now
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// the entry point for painting
|
// the entry point for painting
|
||||||
|
@ -189,36 +280,15 @@ qint64 SceneXrender::paint(QRegion damage, ToplevelList toplevels)
|
||||||
QRegion updateRegion, validRegion;
|
QRegion updateRegion, validRegion;
|
||||||
paintScreen(&mask, damage, QRegion(), &updateRegion, &validRegion);
|
paintScreen(&mask, damage, QRegion(), &updateRegion, &validRegion);
|
||||||
|
|
||||||
if (m_overlayWindow->window()) // show the window only after the first pass, since
|
m_backend->showOverlay();
|
||||||
m_overlayWindow->show(); // that pass may take long
|
|
||||||
|
|
||||||
present(mask, updateRegion);
|
m_backend->present(mask, updateRegion);
|
||||||
// do cleanup
|
// do cleanup
|
||||||
clearStackingOrder();
|
clearStackingOrder();
|
||||||
|
|
||||||
return renderTimer.nsecsElapsed();
|
return renderTimer.nsecsElapsed();
|
||||||
}
|
}
|
||||||
|
|
||||||
void SceneXrender::present(int mask, QRegion damage)
|
|
||||||
{
|
|
||||||
if (mask & 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(), 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,
|
|
||||||
front, 0, 0, 0, 0, 0, 0, displayWidth(), displayHeight());
|
|
||||||
xcb_xfixes_set_picture_clip_region(connection(), 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,
|
|
||||||
front, 0, 0, 0, 0, 0, 0, displayWidth(), displayHeight());
|
|
||||||
xcb_flush(connection());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void SceneXrender::paintGenericScreen(int mask, ScreenPaintData data)
|
void SceneXrender::paintGenericScreen(int mask, ScreenPaintData data)
|
||||||
{
|
{
|
||||||
screen_paint = data; // save, transformations will be done when painting windows
|
screen_paint = data; // save, transformations will be done when painting windows
|
||||||
|
@ -237,12 +307,12 @@ void SceneXrender::paintBackground(QRegion region)
|
||||||
{
|
{
|
||||||
xcb_render_color_t col = { 0, 0, 0, 0xffff }; // black
|
xcb_render_color_t col = { 0, 0, 0, 0xffff }; // black
|
||||||
const QVector<xcb_rectangle_t> &rects = Xcb::regionToRects(region);
|
const QVector<xcb_rectangle_t> &rects = Xcb::regionToRects(region);
|
||||||
xcb_render_fill_rectangles(connection(), XCB_RENDER_PICT_OP_SRC, buffer, col, rects.count(), rects.data());
|
xcb_render_fill_rectangles(connection(), XCB_RENDER_PICT_OP_SRC, bufferPicture(), col, rects.count(), rects.data());
|
||||||
}
|
}
|
||||||
|
|
||||||
Scene::Window *SceneXrender::createWindow(Toplevel *toplevel)
|
Scene::Window *SceneXrender::createWindow(Toplevel *toplevel)
|
||||||
{
|
{
|
||||||
return new Window(toplevel);
|
return new Window(toplevel, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
Scene::EffectFrame *SceneXrender::createEffectFrame(EffectFrameImpl *frame)
|
Scene::EffectFrame *SceneXrender::createEffectFrame(EffectFrameImpl *frame)
|
||||||
|
@ -262,8 +332,9 @@ Shadow *SceneXrender::createShadow(Toplevel *toplevel)
|
||||||
XRenderPicture *SceneXrender::Window::s_tempPicture = 0;
|
XRenderPicture *SceneXrender::Window::s_tempPicture = 0;
|
||||||
QRect SceneXrender::Window::temp_visibleRect;
|
QRect SceneXrender::Window::temp_visibleRect;
|
||||||
|
|
||||||
SceneXrender::Window::Window(Toplevel* c)
|
SceneXrender::Window::Window(Toplevel* c, SceneXrender *scene)
|
||||||
: Scene::Window(c)
|
: Scene::Window(c)
|
||||||
|
, m_scene(scene)
|
||||||
, format(findFormatForVisual(c->visual()->visualid))
|
, format(findFormatForVisual(c->visual()->visualid))
|
||||||
, alpha_cached_opacity(0.0)
|
, alpha_cached_opacity(0.0)
|
||||||
{
|
{
|
||||||
|
@ -464,7 +535,7 @@ void SceneXrender::Window::performPaint(int mask, QRegion region, WindowPaintDat
|
||||||
const bool blitInTempPixmap = xRenderOffscreen() || (data.crossFadeProgress() < 1.0 && !opaque) ||
|
const bool blitInTempPixmap = xRenderOffscreen() || (data.crossFadeProgress() < 1.0 && !opaque) ||
|
||||||
(scaled && (wantShadow || (client && !client->noBorder()) || (deleted && !deleted->noBorder())));
|
(scaled && (wantShadow || (client && !client->noBorder()) || (deleted && !deleted->noBorder())));
|
||||||
|
|
||||||
xcb_render_picture_t renderTarget = buffer;
|
xcb_render_picture_t renderTarget = m_scene->bufferPicture();
|
||||||
if (blitInTempPixmap) {
|
if (blitInTempPixmap) {
|
||||||
if (scene_xRenderOffscreenTarget()) {
|
if (scene_xRenderOffscreenTarget()) {
|
||||||
temp_visibleRect = toplevel->visibleRect().translated(-toplevel->pos());
|
temp_visibleRect = toplevel->visibleRect().translated(-toplevel->pos());
|
||||||
|
@ -675,7 +746,7 @@ xcb_render_composite(connection(), XCB_RENDER_PICT_OP_OVER, _PART_, decorationAl
|
||||||
xcb_render_set_picture_transform(connection(), *s_tempPicture, xform);
|
xcb_render_set_picture_transform(connection(), *s_tempPicture, xform);
|
||||||
setPictureFilter(*s_tempPicture, filter);
|
setPictureFilter(*s_tempPicture, filter);
|
||||||
xcb_render_composite(connection(), XCB_RENDER_PICT_OP_OVER, *s_tempPicture,
|
xcb_render_composite(connection(), XCB_RENDER_PICT_OP_OVER, *s_tempPicture,
|
||||||
XCB_RENDER_PICTURE_NONE, buffer,
|
XCB_RENDER_PICTURE_NONE, m_scene->bufferPicture(),
|
||||||
0, 0, 0, 0, r.x(), r.y(), r.width(), r.height());
|
0, 0, 0, 0, r.x(), r.y(), r.width(), r.height());
|
||||||
xcb_render_set_picture_transform(connection(), *s_tempPicture, identity);
|
xcb_render_set_picture_transform(connection(), *s_tempPicture, identity);
|
||||||
}
|
}
|
||||||
|
@ -715,7 +786,7 @@ WindowPixmap* SceneXrender::Window::createWindowPixmap()
|
||||||
void SceneXrender::screenGeometryChanged(const QSize &size)
|
void SceneXrender::screenGeometryChanged(const QSize &size)
|
||||||
{
|
{
|
||||||
Scene::screenGeometryChanged(size);
|
Scene::screenGeometryChanged(size);
|
||||||
initXRender(false);
|
m_backend->screenGeometryChanged(size);
|
||||||
}
|
}
|
||||||
|
|
||||||
//****************************************
|
//****************************************
|
||||||
|
|
127
scene_xrender.h
127
scene_xrender.h
|
@ -29,6 +29,113 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
namespace KWin
|
namespace KWin
|
||||||
{
|
{
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @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();
|
||||||
|
/**
|
||||||
|
* @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();
|
||||||
|
|
||||||
|
virtual void present(int mask, const QRegion &damage);
|
||||||
|
virtual OverlayWindow* overlayWindow();
|
||||||
|
virtual void showOverlay();
|
||||||
|
virtual void screenGeometryChanged(const QSize &size);
|
||||||
|
private:
|
||||||
|
void init(bool createOverlay);
|
||||||
|
void createBuffer();
|
||||||
|
QScopedPointer<OverlayWindow> m_overlayWindow;
|
||||||
|
xcb_render_picture_t m_front;
|
||||||
|
xcb_render_pictformat_t m_format;
|
||||||
|
};
|
||||||
|
|
||||||
class SceneXrender
|
class SceneXrender
|
||||||
: public Scene
|
: public Scene
|
||||||
|
@ -36,7 +143,6 @@ class SceneXrender
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
class EffectFrame;
|
class EffectFrame;
|
||||||
explicit SceneXrender(Workspace* ws);
|
|
||||||
virtual ~SceneXrender();
|
virtual ~SceneXrender();
|
||||||
virtual bool initFailed() const;
|
virtual bool initFailed() const;
|
||||||
virtual CompositingType compositingType() const {
|
virtual CompositingType compositingType() const {
|
||||||
|
@ -48,31 +154,27 @@ public:
|
||||||
virtual void screenGeometryChanged(const QSize &size);
|
virtual void screenGeometryChanged(const QSize &size);
|
||||||
xcb_render_picture_t bufferPicture();
|
xcb_render_picture_t bufferPicture();
|
||||||
virtual OverlayWindow *overlayWindow() {
|
virtual OverlayWindow *overlayWindow() {
|
||||||
return m_overlayWindow;
|
return m_backend->overlayWindow();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static SceneXrender *createScene();
|
||||||
protected:
|
protected:
|
||||||
virtual Scene::Window *createWindow(Toplevel *toplevel);
|
virtual Scene::Window *createWindow(Toplevel *toplevel);
|
||||||
virtual void paintBackground(QRegion region);
|
virtual void paintBackground(QRegion region);
|
||||||
virtual void paintGenericScreen(int mask, ScreenPaintData data);
|
virtual void paintGenericScreen(int mask, ScreenPaintData data);
|
||||||
virtual void paintDesktop(int desktop, int mask, const QRegion ®ion, ScreenPaintData &data);
|
virtual void paintDesktop(int desktop, int mask, const QRegion ®ion, ScreenPaintData &data);
|
||||||
private:
|
private:
|
||||||
void createBuffer();
|
explicit SceneXrender(XRenderBackend *backend);
|
||||||
void present(int mask, QRegion damage);
|
|
||||||
void initXRender(bool createOverlay);
|
|
||||||
xcb_render_pictformat_t format;
|
|
||||||
xcb_render_picture_t front;
|
|
||||||
static xcb_render_picture_t buffer;
|
|
||||||
static ScreenPaintData screen_paint;
|
static ScreenPaintData screen_paint;
|
||||||
class Window;
|
class Window;
|
||||||
OverlayWindow* m_overlayWindow;
|
QScopedPointer<XRenderBackend> m_backend;
|
||||||
bool init_ok;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class SceneXrender::Window
|
class SceneXrender::Window
|
||||||
: public Scene::Window
|
: public Scene::Window
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Window(Toplevel* c);
|
Window(Toplevel* c, SceneXrender *scene);
|
||||||
virtual ~Window();
|
virtual ~Window();
|
||||||
virtual void performPaint(int mask, QRegion region, WindowPaintData data);
|
virtual void performPaint(int mask, QRegion region, WindowPaintData data);
|
||||||
QRegion transformedShape() const;
|
QRegion transformedShape() const;
|
||||||
|
@ -85,6 +187,7 @@ private:
|
||||||
QPoint mapToScreen(int mask, const WindowPaintData &data, const QPoint &point) const;
|
QPoint mapToScreen(int mask, const WindowPaintData &data, const QPoint &point) const;
|
||||||
void prepareTempPixmap();
|
void prepareTempPixmap();
|
||||||
void setPictureFilter(xcb_render_picture_t pic, ImageFilterType filter);
|
void setPictureFilter(xcb_render_picture_t pic, ImageFilterType filter);
|
||||||
|
SceneXrender *m_scene;
|
||||||
xcb_render_pictformat_t format;
|
xcb_render_pictformat_t format;
|
||||||
double alpha_cached_opacity;
|
double alpha_cached_opacity;
|
||||||
QRegion transformed_shape;
|
QRegion transformed_shape;
|
||||||
|
@ -135,7 +238,7 @@ private:
|
||||||
inline
|
inline
|
||||||
xcb_render_picture_t SceneXrender::bufferPicture()
|
xcb_render_picture_t SceneXrender::bufferPicture()
|
||||||
{
|
{
|
||||||
return buffer;
|
return m_backend->buffer();
|
||||||
}
|
}
|
||||||
|
|
||||||
inline
|
inline
|
||||||
|
|
Loading…
Reference in a new issue