kwin/scene_xrender.h
2014-03-18 09:23:25 +01:00

341 lines
9.9 KiB
C++

/********************************************************************
KWin - the KDE window manager
This file is part of the KDE project.
Copyright (C) 2006 Lubos Lunak <l.lunak@kde.org>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*********************************************************************/
#ifndef KWIN_SCENE_XRENDER_H
#define KWIN_SCENE_XRENDER_H
#include "scene.h"
#include "shadow.h"
#ifdef KWIN_HAVE_XRENDER_COMPOSITING
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 Backend specific code to determine whether the last frame got rendered.
*
* Default implementation always returns @c true. That is it's always assumed that the last
* frame got rendered. If a backend needs more control it needs to implement this method.
*/
virtual bool isLastFrameRendered() const;
/**
* @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);
virtual bool usesOverlayWindow() const;
private:
void init(bool createOverlay);
void createBuffer();
QScopedPointer<OverlayWindow> m_overlayWindow;
xcb_render_picture_t m_front;
xcb_render_pictformat_t m_format;
};
#if HAVE_WAYLAND
class WaylandXRenderBackend : public XRenderBackend
{
public:
WaylandXRenderBackend();
virtual ~WaylandXRenderBackend();
virtual void present(int mask, const QRegion &damage);
virtual bool isLastFrameRendered() const;
virtual bool usesOverlayWindow() const;
void lastFrameRendered();
private:
void init();
QScopedPointer<Xcb::Shm> m_shm;
bool m_lastFrameRendered;
};
#endif
class SceneXrender
: public Scene
{
Q_OBJECT
public:
class EffectFrame;
virtual ~SceneXrender();
virtual bool initFailed() const;
virtual CompositingType compositingType() const {
return XRenderCompositing;
}
virtual qint64 paint(QRegion damage, ToplevelList windows);
virtual Scene::EffectFrame *createEffectFrame(EffectFrameImpl *frame);
virtual Shadow *createShadow(Toplevel *toplevel);
virtual void screenGeometryChanged(const QSize &size);
xcb_render_picture_t bufferPicture();
virtual OverlayWindow *overlayWindow() {
return m_backend->overlayWindow();
}
virtual bool usesOverlayWindow() const {
return m_backend->usesOverlayWindow();
}
virtual bool isLastFrameRendered() const {
return m_backend->isLastFrameRendered();
}
static SceneXrender *createScene();
protected:
virtual Scene::Window *createWindow(Toplevel *toplevel);
virtual void paintBackground(QRegion region);
virtual void paintGenericScreen(int mask, ScreenPaintData data);
virtual void paintDesktop(int desktop, int mask, const QRegion &region, ScreenPaintData &data);
private:
explicit SceneXrender(XRenderBackend *backend);
static ScreenPaintData screen_paint;
class Window;
QScopedPointer<XRenderBackend> m_backend;
};
class SceneXrender::Window
: public Scene::Window
{
public:
Window(Toplevel* c, SceneXrender *scene);
virtual ~Window();
virtual void performPaint(int mask, QRegion region, WindowPaintData data);
QRegion transformedShape() const;
void setTransformedShape(const QRegion& shape);
static void cleanup();
protected:
virtual WindowPixmap* createWindowPixmap();
private:
QRect mapToScreen(int mask, const WindowPaintData &data, const QRect &rect) const;
QPoint mapToScreen(int mask, const WindowPaintData &data, const QPoint &point) const;
void prepareTempPixmap();
void setPictureFilter(xcb_render_picture_t pic, ImageFilterType filter);
SceneXrender *m_scene;
xcb_render_pictformat_t format;
double alpha_cached_opacity;
QRegion transformed_shape;
static QRect temp_visibleRect;
static XRenderPicture *s_tempPicture;
};
class XRenderWindowPixmap : public WindowPixmap
{
public:
explicit XRenderWindowPixmap(Scene::Window *window, xcb_render_pictformat_t format);
virtual ~XRenderWindowPixmap();
xcb_render_picture_t picture() const;
virtual void create();
private:
xcb_render_picture_t m_picture;
xcb_render_pictformat_t m_format;
};
class SceneXrender::EffectFrame
: public Scene::EffectFrame
{
public:
EffectFrame(EffectFrameImpl* frame);
virtual ~EffectFrame();
virtual void free();
virtual void freeIconFrame();
virtual void freeTextFrame();
virtual void freeSelection();
virtual void crossFadeIcon();
virtual void crossFadeText();
virtual void render(QRegion region, double opacity, double frameOpacity);
static void cleanup();
private:
void updatePicture();
void updateTextPicture();
void renderUnstyled(xcb_render_picture_t pict, const QRect &rect, qreal opacity);
XRenderPicture* m_picture;
XRenderPicture* m_textPicture;
XRenderPicture* m_iconPicture;
XRenderPicture* m_selectionPicture;
static XRenderPicture* s_effectFrameCircle;
};
inline
xcb_render_picture_t SceneXrender::bufferPicture()
{
return m_backend->buffer();
}
inline
QRegion SceneXrender::Window::transformedShape() const
{
return transformed_shape;
}
inline
void SceneXrender::Window::setTransformedShape(const QRegion& shape)
{
transformed_shape = shape;
}
inline
xcb_render_picture_t XRenderWindowPixmap::picture() const
{
return m_picture;
}
/**
* @short XRender implementation of Shadow.
*
* This class extends Shadow by the elements required for XRender rendering.
* @author Jacopo De Simoi <wilderkde@gmail.org>
**/
class SceneXRenderShadow
: public Shadow
{
public:
explicit SceneXRenderShadow(Toplevel *toplevel);
using Shadow::ShadowElements;
using Shadow::ShadowElementTop;
using Shadow::ShadowElementTopRight;
using Shadow::ShadowElementRight;
using Shadow::ShadowElementBottomRight;
using Shadow::ShadowElementBottom;
using Shadow::ShadowElementBottomLeft;
using Shadow::ShadowElementLeft;
using Shadow::ShadowElementTopLeft;
using Shadow::ShadowElementsCount;
using Shadow::shadowPixmap;
virtual ~SceneXRenderShadow();
void layoutShadowRects(QRect& top, QRect& topRight,
QRect& right, QRect& bottomRight,
QRect& bottom, QRect& bottomLeft,
QRect& Left, QRect& topLeft);
xcb_render_picture_t picture(ShadowElements element) const;
protected:
virtual void buildQuads();
virtual bool prepareBackend();
private:
XRenderPicture* m_pictures[ShadowElementsCount];
};
} // namespace
#endif
#endif