KWin supports graphicssystem Raster
With raster a QPixmap is no longer a XPixmap which fails all code which assumes that an QPixmap is an XPixmap. Depending on were in the codebase we either convert such pixmaps to images (OpenGL) or create a XPixmap and use QPixmap::fromX11Pixmap to get a "real" pixmap. It is possible that there are more code pathes were we would need a XPixmap. Currently tested is basic functionality of no-compositing, XRender compositing, OpenGl/GLX and OpenGL ES/EGL compositing. For OpenGL compositing raster might result in performance improvements, for XRender it is possible that there are regressions when using raster. By default KWin uses whatever is the default of the system, so we just no longer enforce native. Of course it is a bad idea to use graphicssystem OpenGL. As that is broken anyways in Qt, we do not check for it. Many thanks to Philipp Knechtges for bringing up the issue, convincing me that we need it and providing most of the patch. REVIEW: 101132 CCMAIL: Philipp.Knechtges@rwth-aachen.de
This commit is contained in:
parent
264fcfa49f
commit
234ec644d2
10 changed files with 95 additions and 37 deletions
24
client.cpp
24
client.cpp
|
@ -582,17 +582,25 @@ void Client::resizeDecorationPixmaps()
|
|||
QRect lr, rr, tr, br;
|
||||
layoutDecorationRects(lr, tr, rr, br, DecorationRelative);
|
||||
|
||||
if (decorationPixmapTop.size() != tr.size())
|
||||
decorationPixmapTop = QPixmap(tr.size());
|
||||
if (decorationPixmapTop.size() != tr.size()) {
|
||||
Pixmap pixmap = XCreatePixmap(display(), rootWindow(), tr.width(), tr.height(), 32);
|
||||
decorationPixmapTop = QPixmap::fromX11Pixmap(pixmap, QPixmap::ExplicitlyShared);
|
||||
}
|
||||
|
||||
if (decorationPixmapBottom.size() != br.size())
|
||||
decorationPixmapBottom = QPixmap(br.size());
|
||||
if (decorationPixmapBottom.size() != br.size()) {
|
||||
Pixmap pixmap = XCreatePixmap(display(), rootWindow(), br.width(), br.height(), 32);
|
||||
decorationPixmapBottom = QPixmap::fromX11Pixmap(pixmap, QPixmap::ExplicitlyShared);
|
||||
}
|
||||
|
||||
if (decorationPixmapLeft.size() != lr.size())
|
||||
decorationPixmapLeft = QPixmap(lr.size());
|
||||
if (decorationPixmapLeft.size() != lr.size()) {
|
||||
Pixmap pixmap = XCreatePixmap(display(), rootWindow(), lr.width(), lr.height(), 32);
|
||||
decorationPixmapLeft = QPixmap::fromX11Pixmap(pixmap, QPixmap::ExplicitlyShared);
|
||||
}
|
||||
|
||||
if (decorationPixmapRight.size() != rr.size())
|
||||
decorationPixmapRight = QPixmap(rr.size());
|
||||
if (decorationPixmapRight.size() != rr.size()) {
|
||||
Pixmap pixmap = XCreatePixmap(display(), rootWindow(), rr.width(), rr.height(), 32);
|
||||
decorationPixmapRight = QPixmap::fromX11Pixmap(pixmap, QPixmap::ExplicitlyShared);
|
||||
}
|
||||
|
||||
#ifdef HAVE_XRENDER
|
||||
if (Extensions::renderAvailable()) {
|
||||
|
|
|
@ -116,6 +116,13 @@ void ScreenShotEffect::postPaintScreen()
|
|||
grabPointerImage(img, m_scheduledScreenshot->x() + left, m_scheduledScreenshot->y() + top);
|
||||
}
|
||||
m_lastScreenshot = QPixmap::fromImage(img);
|
||||
if (m_lastScreenshot.handle() == 0) {
|
||||
Pixmap xpix = XCreatePixmap(display(), rootWindow(), m_lastScreenshot.width(),
|
||||
m_lastScreenshot.height(), XDefaultDepth(display(), QX11Info::appScreen()));
|
||||
m_lastScreenshot = QPixmap::fromX11Pixmap(xpix, QPixmap::ExplicitlyShared);
|
||||
QPainter p(&m_lastScreenshot);
|
||||
p.drawImage(QPoint(0, 0), img);
|
||||
}
|
||||
emit screenshotCreated(m_lastScreenshot.handle());
|
||||
}
|
||||
delete offscreenTexture;
|
||||
|
|
|
@ -690,9 +690,9 @@ QImage GLTexture::convertToGLFormat(const QImage& img) const
|
|||
// Copied from Qt's QGLWidget::convertToGLFormat()
|
||||
QImage res(img.size(), QImage::Format_ARGB32);
|
||||
#ifdef KWIN_HAVE_OPENGLES
|
||||
convertToGLFormatHelper(res, img.convertToFormat(QImage::Format_ARGB32), GL_RGBA);
|
||||
convertToGLFormatHelper(res, img.convertToFormat(QImage::Format_ARGB32_Premultiplied), GL_RGBA);
|
||||
#else
|
||||
convertToGLFormatHelper(res, img.convertToFormat(QImage::Format_ARGB32), GL_BGRA);
|
||||
convertToGLFormatHelper(res, img.convertToFormat(QImage::Format_ARGB32_Premultiplied), GL_BGRA);
|
||||
#endif
|
||||
return res;
|
||||
}
|
||||
|
|
|
@ -26,6 +26,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|||
#include <QPixmap>
|
||||
#include <QPainter>
|
||||
#include <kdebug.h>
|
||||
#include <QPaintEngine>
|
||||
|
||||
namespace KWin
|
||||
{
|
||||
|
@ -191,8 +192,17 @@ static Picture createPicture(Pixmap pix, int depth)
|
|||
}
|
||||
|
||||
XRenderPicture::XRenderPicture(QPixmap pix)
|
||||
: d(new XRenderPictureData(createPicture(pix.handle(), pix.depth())))
|
||||
{
|
||||
if (pix.paintEngine()->type() != QPaintEngine::X11 || pix.handle() == 0) {
|
||||
Pixmap xPix = XCreatePixmap(display(), rootWindow(), pix.width(), pix.height(), pix.depth());
|
||||
QPixmap tempPix = QPixmap::fromX11Pixmap(xPix);
|
||||
tempPix.fill(Qt::transparent);
|
||||
QPainter p(&tempPix);
|
||||
p.drawPixmap(QPoint(0, 0), pix);
|
||||
d = new XRenderPictureData(createPicture(tempPix.handle(), tempPix.depth()));
|
||||
} else {
|
||||
d = new XRenderPictureData(createPicture(pix.handle(), pix.depth()));
|
||||
}
|
||||
}
|
||||
|
||||
XRenderPicture::XRenderPicture(Pixmap pix, int depth)
|
||||
|
|
4
main.cpp
4
main.cpp
|
@ -404,10 +404,6 @@ KDE_EXPORT int kdemain(int argc, char * argv[])
|
|||
}
|
||||
}
|
||||
|
||||
// KWin only works properly with Qt's native X11 backend; override any compile-time
|
||||
// or command line settings to raster or OpenGL.
|
||||
QApplication::setGraphicsSystem("native");
|
||||
|
||||
Display* dpy = XOpenDisplay(NULL);
|
||||
if (!dpy) {
|
||||
fprintf(stderr, "%s: FATAL ERROR while trying to open display %s\n",
|
||||
|
|
21
outline.cpp
21
outline.cpp
|
@ -96,13 +96,18 @@ void Outline::showWithX()
|
|||
CopyFromParent, CopyFromParent, CopyFromParent, CWOverrideRedirect, &attr);
|
||||
m_initialized = true;
|
||||
}
|
||||
|
||||
int defaultDepth = XDefaultDepth(QX11Info::display(), QX11Info::appScreen());
|
||||
|
||||
// left/right parts are between top/bottom, they don't reach as far as the corners
|
||||
XMoveResizeWindow(QX11Info::display(), m_leftOutline, m_outlineGeometry.x(), m_outlineGeometry.y() + 5, 5, m_outlineGeometry.height() - 10);
|
||||
XMoveResizeWindow(QX11Info::display(), m_rightOutline, m_outlineGeometry.x() + m_outlineGeometry.width() - 5, m_outlineGeometry.y() + 5, 5, m_outlineGeometry.height() - 10);
|
||||
XMoveResizeWindow(QX11Info::display(), m_topOutline, m_outlineGeometry.x(), m_outlineGeometry.y(), m_outlineGeometry.width(), 5);
|
||||
XMoveResizeWindow(QX11Info::display(), m_bottomOutline, m_outlineGeometry.x(), m_outlineGeometry.y() + m_outlineGeometry.height() - 5, m_outlineGeometry.width(), 5);
|
||||
{
|
||||
QPixmap pix(5, m_outlineGeometry.height() - 10);
|
||||
Pixmap xpix = XCreatePixmap(display(), rootWindow(), 5,
|
||||
m_outlineGeometry.height() - 10, defaultDepth);
|
||||
QPixmap pix = QPixmap::fromX11Pixmap(xpix, QPixmap::ExplicitlyShared);
|
||||
QPainter p(&pix);
|
||||
p.setPen(Qt::white);
|
||||
p.drawLine(0, 0, 0, pix.height() - 1);
|
||||
|
@ -115,9 +120,13 @@ void Outline::showWithX()
|
|||
p.end();
|
||||
XSetWindowBackgroundPixmap(QX11Info::display(), m_leftOutline, pix.handle());
|
||||
XSetWindowBackgroundPixmap(QX11Info::display(), m_rightOutline, pix.handle());
|
||||
// According to the XSetWindowBackgroundPixmap documentation the pixmap can be freed.
|
||||
XFreePixmap (display(), xpix);
|
||||
}
|
||||
{
|
||||
QPixmap pix(m_outlineGeometry.width(), 5);
|
||||
Pixmap xpix = XCreatePixmap(display(), rootWindow(), m_outlineGeometry.width(),
|
||||
5, defaultDepth);
|
||||
QPixmap pix = QPixmap::fromX11Pixmap(xpix, QPixmap::ExplicitlyShared);
|
||||
QPainter p(&pix);
|
||||
p.setPen(Qt::white);
|
||||
p.drawLine(0, 0, pix.width() - 1 - 0, 0);
|
||||
|
@ -137,9 +146,13 @@ void Outline::showWithX()
|
|||
p.drawLine(pix.width() - 1 - 2, 2, pix.width() - 1 - 2, 4);
|
||||
p.end();
|
||||
XSetWindowBackgroundPixmap(QX11Info::display(), m_topOutline, pix.handle());
|
||||
// According to the XSetWindowBackgroundPixmap documentation the pixmap can be freed.
|
||||
XFreePixmap (display(), xpix);
|
||||
}
|
||||
{
|
||||
QPixmap pix(m_outlineGeometry.width(), 5);
|
||||
Pixmap xpix = XCreatePixmap(display(), rootWindow(), m_outlineGeometry.width(),
|
||||
5, defaultDepth);
|
||||
QPixmap pix = QPixmap::fromX11Pixmap(xpix, QPixmap::ExplicitlyShared);
|
||||
QPainter p(&pix);
|
||||
p.setPen(Qt::white);
|
||||
p.drawLine(4, 0, pix.width() - 1 - 4, 0);
|
||||
|
@ -159,6 +172,8 @@ void Outline::showWithX()
|
|||
p.drawLine(pix.width() - 1 - 2, 0, pix.width() - 1 - 2, 2);
|
||||
p.end();
|
||||
XSetWindowBackgroundPixmap(QX11Info::display(), m_bottomOutline, pix.handle());
|
||||
// According to the XSetWindowBackgroundPixmap documentation the pixmap can be freed.
|
||||
XFreePixmap (display(), xpix);
|
||||
}
|
||||
XClearWindow(QX11Info::display(), m_leftOutline);
|
||||
XClearWindow(QX11Info::display(), m_rightOutline);
|
||||
|
|
|
@ -92,6 +92,7 @@ Sources and other compositing managers:
|
|||
#include <QVector2D>
|
||||
#include <QVector4D>
|
||||
#include <QMatrix4x4>
|
||||
#include <QPaintEngine>
|
||||
|
||||
namespace KWin
|
||||
{
|
||||
|
@ -278,6 +279,13 @@ SceneOpenGL::Texture::Texture(const Pixmap& pix, const QSize& size, int depth) :
|
|||
load(pix, size, depth);
|
||||
}
|
||||
|
||||
SceneOpenGL::Texture::Texture(const QPixmap& pix, GLenum target)
|
||||
: GLTexture()
|
||||
{
|
||||
init();
|
||||
load(pix, target);
|
||||
}
|
||||
|
||||
SceneOpenGL::Texture::~Texture()
|
||||
{
|
||||
discard();
|
||||
|
@ -329,9 +337,15 @@ bool SceneOpenGL::Texture::load(const QImage& image, GLenum target)
|
|||
|
||||
bool SceneOpenGL::Texture::load(const QPixmap& pixmap, GLenum target)
|
||||
{
|
||||
Q_UNUSED(target); // SceneOpenGL::Texture::findTarget() detects the target
|
||||
if (pixmap.isNull())
|
||||
return false;
|
||||
|
||||
// Checking whether QPixmap comes with its own X11 Pixmap
|
||||
if (pixmap.paintEngine()->type() != QPaintEngine::X11 || pixmap.handle() == 0) {
|
||||
return GLTexture::load(pixmap.toImage(), target);
|
||||
}
|
||||
|
||||
// use the X11 pixmap provided by Qt
|
||||
return load(pixmap.handle(), pixmap.size(), pixmap.depth());
|
||||
}
|
||||
|
||||
|
@ -618,7 +632,7 @@ void SceneOpenGL::Window::paintDecoration(const QPixmap* decoration, TextureType
|
|||
// texture doesn't need updating, just bind it
|
||||
glBindTexture(decorationTexture->target(), decorationTexture->texture());
|
||||
} else if (!decoration->isNull()) {
|
||||
bool success = decorationTexture->load(decoration->handle(), decoration->size(), decoration->depth());
|
||||
bool success = decorationTexture->load(*decoration);
|
||||
if (!success) {
|
||||
kDebug(1212) << "Failed to bind decoartion";
|
||||
return;
|
||||
|
@ -1316,8 +1330,7 @@ void SceneOpenGL::EffectFrame::render(QRegion region, double opacity, double fra
|
|||
if (!m_effectFrame->selection().isNull()) {
|
||||
if (!m_selectionTexture) { // Lazy creation
|
||||
QPixmap pixmap = m_effectFrame->selectionFrame().framePixmap();
|
||||
m_selectionTexture = new Texture(pixmap.handle(), pixmap.size(), pixmap.depth());
|
||||
m_selectionTexture->setYInverted(true);
|
||||
m_selectionTexture = new Texture(pixmap);
|
||||
}
|
||||
if (shader) {
|
||||
const float a = opacity * frameOpacity;
|
||||
|
@ -1372,10 +1385,7 @@ void SceneOpenGL::EffectFrame::render(QRegion region, double opacity, double fra
|
|||
}
|
||||
|
||||
if (!m_iconTexture) { // lazy creation
|
||||
m_iconTexture = new Texture(m_effectFrame->icon().handle(),
|
||||
m_effectFrame->icon().size(),
|
||||
m_effectFrame->icon().depth());
|
||||
m_iconTexture->setYInverted(true);
|
||||
m_iconTexture = new Texture(m_effectFrame->icon());
|
||||
}
|
||||
m_iconTexture->bind();
|
||||
m_iconTexture->render(region, QRect(topLeft, m_effectFrame->iconSize()));
|
||||
|
@ -1437,8 +1447,7 @@ void SceneOpenGL::EffectFrame::updateTexture()
|
|||
delete m_texture;
|
||||
if (m_effectFrame->style() == EffectFrameStyled) {
|
||||
QPixmap pixmap = m_effectFrame->frame().framePixmap();
|
||||
m_texture = new Texture(pixmap.handle(), pixmap.size(), pixmap.depth());
|
||||
m_texture->setYInverted(true);
|
||||
m_texture = new Texture(pixmap);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1472,8 +1481,7 @@ void SceneOpenGL::EffectFrame::updateTextTexture()
|
|||
p.setPen(Qt::white);
|
||||
p.drawText(rect, m_effectFrame->alignment(), text);
|
||||
p.end();
|
||||
m_textTexture = new Texture(m_textPixmap->handle(), m_textPixmap->size(), m_textPixmap->depth());
|
||||
m_textTexture->setYInverted(true);
|
||||
m_textTexture = new Texture(*m_textPixmap);
|
||||
}
|
||||
|
||||
void SceneOpenGL::EffectFrame::updateUnstyledTexture()
|
||||
|
@ -1491,8 +1499,7 @@ void SceneOpenGL::EffectFrame::updateUnstyledTexture()
|
|||
p.drawEllipse(m_unstyledPixmap->rect());
|
||||
p.end();
|
||||
#undef CS
|
||||
m_unstyledTexture = new Texture(m_unstyledPixmap->handle(), m_unstyledPixmap->size(), m_unstyledPixmap->depth());
|
||||
m_unstyledTexture->setYInverted(true);
|
||||
m_unstyledTexture = new Texture(*m_unstyledPixmap);
|
||||
}
|
||||
|
||||
void SceneOpenGL::EffectFrame::cleanup()
|
||||
|
@ -1563,7 +1570,7 @@ SceneOpenGL::Texture *SceneOpenGLShadow::textureForQuadType(WindowQuadType type)
|
|||
if (texture->texture() != None) {
|
||||
glBindTexture(texture->target(), texture->texture());
|
||||
} else if (!pixmap.isNull()) {
|
||||
const bool success = texture->load(pixmap.handle(), pixmap.size(), pixmap.depth());
|
||||
const bool success = texture->load(pixmap);
|
||||
if (!success) {
|
||||
kDebug(1212) << "Failed to bind shadow pixmap";
|
||||
return NULL;
|
||||
|
|
|
@ -106,13 +106,10 @@ class SceneOpenGL::Texture
|
|||
{
|
||||
public:
|
||||
Texture();
|
||||
Texture(const Pixmap& pix, const QSize& size, int depth);
|
||||
Texture(const QPixmap& pix, GLenum target = GL_TEXTURE_2D);
|
||||
virtual ~Texture();
|
||||
|
||||
using GLTexture::load;
|
||||
virtual bool load(const Pixmap& pix, const QSize& size, int depth,
|
||||
QRegion region);
|
||||
virtual bool load(const Pixmap& pix, const QSize& size, int depth);
|
||||
virtual bool load(const QImage& image, GLenum target = GL_TEXTURE_2D);
|
||||
virtual bool load(const QPixmap& pixmap, GLenum target = GL_TEXTURE_2D);
|
||||
virtual void discard();
|
||||
|
@ -124,9 +121,13 @@ public:
|
|||
}
|
||||
|
||||
protected:
|
||||
Texture(const Pixmap& pix, const QSize& size, int depth);
|
||||
void findTarget();
|
||||
QRegion optimizeBindDamage(const QRegion& reg, int limit);
|
||||
void createTexture();
|
||||
virtual bool load(const Pixmap& pix, const QSize& size, int depth,
|
||||
QRegion region);
|
||||
virtual bool load(const Pixmap& pix, const QSize& size, int depth);
|
||||
|
||||
private:
|
||||
void init();
|
||||
|
@ -134,6 +135,8 @@ private:
|
|||
#ifndef KWIN_HAVE_OPENGLES
|
||||
GLXPixmap glxpixmap; // the glx pixmap the texture is bound to, only for tfp_mode
|
||||
#endif
|
||||
|
||||
friend class SceneOpenGL::Window;
|
||||
};
|
||||
|
||||
class SceneOpenGL::Window
|
||||
|
|
|
@ -258,6 +258,7 @@ bool SceneOpenGL::Texture::load(const Pixmap& pix, const QSize& size,
|
|||
eglDestroyImageKHR(dpy, image);
|
||||
unbind();
|
||||
checkGLError("load texture");
|
||||
setYInverted(true);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -53,6 +53,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|||
#include <kxerrorhandler.h>
|
||||
|
||||
#include <QtGui/QPainter>
|
||||
#include <QtGui/QPaintEngine>
|
||||
|
||||
namespace KWin
|
||||
{
|
||||
|
@ -190,6 +191,12 @@ void SceneXrender::selfCheckSetup()
|
|||
img.setPixel(1, 1, QColor(Qt::black).rgb());
|
||||
img.setPixel(2, 1, QColor(Qt::white).rgb());
|
||||
QPixmap pix = QPixmap::fromImage(img);
|
||||
if (pix.handle() == 0) {
|
||||
Pixmap xPix = XCreatePixmap(display(), rootWindow(), pix.width(), pix.height(), DefaultDepth(display(), DefaultScreen(display())));
|
||||
pix = QPixmap::fromX11Pixmap(xPix);
|
||||
QPainter p(&pix);
|
||||
p.drawImage(QPoint(0, 0), img);
|
||||
}
|
||||
foreach (const QPoint & p, selfCheckPoints()) {
|
||||
XSetWindowAttributes wa;
|
||||
wa.override_redirect = True;
|
||||
|
@ -585,6 +592,10 @@ void SceneXrender::Window::prepareTempPixmap(const QPixmap *left, const QPixmap
|
|||
temp_pixmap = new QPixmap(r.width(), r.height());
|
||||
else if (temp_pixmap->width() < r.width() || temp_pixmap->height() < r.height())
|
||||
*temp_pixmap = QPixmap(r.width(), r.height());
|
||||
if (temp_pixmap->paintEngine()->type() != QPaintEngine::X11 || temp_pixmap->handle() == 0) {
|
||||
Pixmap pix = XCreatePixmap(display(), rootWindow(), temp_pixmap->width(), temp_pixmap->height(), DefaultDepth(display(), DefaultScreen(display())));
|
||||
*temp_pixmap = QPixmap::fromX11Pixmap(pix);
|
||||
}
|
||||
|
||||
temp_pixmap->fill(Qt::transparent);
|
||||
|
||||
|
|
Loading…
Reference in a new issue