avoid calling QPixmap::paintEngine() in scene rendering
by checking the graphicssystem at startup also avoid pixmap and memory leaking on the xrender backend, validate some pointers on deletion in SceneOpnGL and avoid attempts to render ::isNull pixmaps
This commit is contained in:
parent
f1eb4d97bf
commit
3af7395ab8
5 changed files with 70 additions and 33 deletions
|
@ -20,6 +20,10 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|||
|
||||
#include "kwinglobals.h"
|
||||
|
||||
#include <QPainter>
|
||||
#include <QPaintEngine>
|
||||
#include <QPixmap>
|
||||
|
||||
#include <config-workspace.h>
|
||||
#include <config-X11.h>
|
||||
|
||||
|
@ -67,6 +71,7 @@ int Extensions::render_version = 0;
|
|||
bool Extensions::has_glx = false;
|
||||
bool Extensions::has_sync = false;
|
||||
int Extensions::sync_event_base = 0;
|
||||
bool Extensions::non_native_pixmaps = false;
|
||||
// for fillExtensionsData()
|
||||
const char* Extensions::data_extensions[ 32 ];
|
||||
int Extensions::data_nextensions;
|
||||
|
@ -158,6 +163,10 @@ void Extensions::init()
|
|||
}
|
||||
}
|
||||
#endif
|
||||
QPixmap pix(1,1);
|
||||
QPainter p(&pix);
|
||||
non_native_pixmaps = p.paintEngine()->type() != QPaintEngine::X11;
|
||||
p.end();
|
||||
kDebug(1212) << "Extensions: shape: 0x" << QString::number(shape_version, 16)
|
||||
<< " composite: 0x" << QString::number(composite_version, 16)
|
||||
<< " render: 0x" << QString::number(render_version, 16)
|
||||
|
|
|
@ -171,6 +171,9 @@ public:
|
|||
static bool syncAvailable() {
|
||||
return has_sync;
|
||||
}
|
||||
static bool nonNativePixmaps() {
|
||||
return non_native_pixmaps;
|
||||
}
|
||||
static int syncAlarmNotifyEvent();
|
||||
static void fillExtensionsData(const char**& extensions, int& nextensions, int*&majors, int*& error_bases);
|
||||
private:
|
||||
|
@ -191,6 +194,7 @@ private:
|
|||
static int data_nextensions;
|
||||
static int data_opcodes[ 32 ];
|
||||
static int data_error_bases[ 32 ];
|
||||
static bool non_native_pixmaps;
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
|
|
@ -19,6 +19,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|||
*********************************************************************/
|
||||
|
||||
#include "kwinxrenderutils.h"
|
||||
#include "kwinglobals.h"
|
||||
|
||||
#ifdef KWIN_HAVE_XRENDER_COMPOSITING
|
||||
|
||||
|
@ -26,7 +27,6 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|||
#include <QPixmap>
|
||||
#include <QPainter>
|
||||
#include <kdebug.h>
|
||||
#include <QPaintEngine>
|
||||
|
||||
namespace KWin
|
||||
{
|
||||
|
@ -193,13 +193,15 @@ static Picture createPicture(Pixmap pix, int depth)
|
|||
|
||||
XRenderPicture::XRenderPicture(QPixmap pix)
|
||||
{
|
||||
if (pix.paintEngine()->type() != QPaintEngine::X11 || pix.handle() == 0) {
|
||||
if (Extensions::nonNativePixmaps()) {
|
||||
Pixmap xPix = XCreatePixmap(display(), rootWindow(), pix.width(), pix.height(), pix.depth());
|
||||
QPixmap tempPix = QPixmap::fromX11Pixmap(xPix);
|
||||
QPixmap tempPix = QPixmap::fromX11Pixmap(xPix, QPixmap::ExplicitlyShared);
|
||||
tempPix.fill(Qt::transparent);
|
||||
QPainter p(&tempPix);
|
||||
p.drawPixmap(QPoint(0, 0), pix);
|
||||
p.end();
|
||||
d = new XRenderPictureData(createPicture(tempPix.handle(), tempPix.depth()));
|
||||
XFreePixmap(display(), xPix);
|
||||
} else {
|
||||
d = new XRenderPictureData(createPicture(pix.handle(), pix.depth()));
|
||||
}
|
||||
|
|
|
@ -92,7 +92,6 @@ Sources and other compositing managers:
|
|||
#include <QVector2D>
|
||||
#include <QVector4D>
|
||||
#include <QMatrix4x4>
|
||||
#include <QPaintEngine>
|
||||
|
||||
namespace KWin
|
||||
{
|
||||
|
@ -341,7 +340,7 @@ bool SceneOpenGL::Texture::load(const QPixmap& pixmap, GLenum target)
|
|||
return false;
|
||||
|
||||
// Checking whether QPixmap comes with its own X11 Pixmap
|
||||
if (pixmap.paintEngine() == 0 || pixmap.paintEngine()->type() != QPaintEngine::X11 || pixmap.handle() == 0) {
|
||||
if (Extensions::nonNativePixmaps()) {
|
||||
return GLTexture::load(pixmap.toImage(), target);
|
||||
}
|
||||
|
||||
|
@ -1347,21 +1346,24 @@ 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);
|
||||
if (!pixmap.isNull())
|
||||
m_selectionTexture = new Texture(pixmap);
|
||||
}
|
||||
if (shader) {
|
||||
const float a = opacity * frameOpacity;
|
||||
shader->setUniform(GLShader::ModulationConstant, QVector4D(a, a, a, a));
|
||||
if (m_selectionTexture) {
|
||||
if (shader) {
|
||||
const float a = opacity * frameOpacity;
|
||||
shader->setUniform(GLShader::ModulationConstant, QVector4D(a, a, a, a));
|
||||
}
|
||||
#ifndef KWIN_HAVE_OPENGLES
|
||||
else
|
||||
glColor4f(1.0, 1.0, 1.0, opacity * frameOpacity);
|
||||
#endif
|
||||
glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
|
||||
m_selectionTexture->bind();
|
||||
m_selectionTexture->render(region, m_effectFrame->selection());
|
||||
m_selectionTexture->unbind();
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
}
|
||||
#ifndef KWIN_HAVE_OPENGLES
|
||||
else
|
||||
glColor4f(1.0, 1.0, 1.0, opacity * frameOpacity);
|
||||
#endif
|
||||
glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
|
||||
m_selectionTexture->bind();
|
||||
m_selectionTexture->render(region, m_effectFrame->selection());
|
||||
m_selectionTexture->unbind();
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
}
|
||||
|
||||
// Render icon
|
||||
|
@ -1462,6 +1464,7 @@ void SceneOpenGL::EffectFrame::render(QRegion region, double opacity, double fra
|
|||
void SceneOpenGL::EffectFrame::updateTexture()
|
||||
{
|
||||
delete m_texture;
|
||||
m_texture = 0L;
|
||||
if (m_effectFrame->style() == EffectFrameStyled) {
|
||||
QPixmap pixmap = m_effectFrame->frame().framePixmap();
|
||||
m_texture = new Texture(pixmap);
|
||||
|
@ -1471,7 +1474,9 @@ void SceneOpenGL::EffectFrame::updateTexture()
|
|||
void SceneOpenGL::EffectFrame::updateTextTexture()
|
||||
{
|
||||
delete m_textTexture;
|
||||
m_textTexture = 0L;
|
||||
delete m_textPixmap;
|
||||
m_textPixmap = 0L;
|
||||
|
||||
if (m_effectFrame->text().isEmpty())
|
||||
return;
|
||||
|
@ -1504,7 +1509,9 @@ void SceneOpenGL::EffectFrame::updateTextTexture()
|
|||
void SceneOpenGL::EffectFrame::updateUnstyledTexture()
|
||||
{
|
||||
delete m_unstyledTexture;
|
||||
m_unstyledTexture = 0L;
|
||||
delete m_unstyledPixmap;
|
||||
m_unstyledPixmap = 0L;
|
||||
// Based off circle() from kwinxrenderutils.cpp
|
||||
#define CS 8
|
||||
m_unstyledPixmap = new QPixmap(2 * CS, 2 * CS);
|
||||
|
|
|
@ -53,7 +53,6 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|||
#include <kxerrorhandler.h>
|
||||
|
||||
#include <QtGui/QPainter>
|
||||
#include <QtGui/QPaintEngine>
|
||||
|
||||
namespace KWin
|
||||
{
|
||||
|
@ -191,9 +190,11 @@ void SceneXrender::selfCheckSetup()
|
|||
img.setPixel(1, 1, QColor(Qt::black).rgb());
|
||||
img.setPixel(2, 1, QColor(Qt::white).rgb());
|
||||
QPixmap pix = QPixmap::fromImage(img);
|
||||
bool mustFreePix = false;
|
||||
if (pix.handle() == 0) {
|
||||
mustFreePix = true;
|
||||
Pixmap xPix = XCreatePixmap(display(), rootWindow(), pix.width(), pix.height(), DefaultDepth(display(), DefaultScreen(display())));
|
||||
pix = QPixmap::fromX11Pixmap(xPix);
|
||||
pix = QPixmap::fromX11Pixmap(xPix, QPixmap::ExplicitlyShared);
|
||||
QPainter p(&pix);
|
||||
p.drawImage(QPoint(0, 0), img);
|
||||
}
|
||||
|
@ -221,6 +222,8 @@ void SceneXrender::selfCheckSetup()
|
|||
XFreePixmap(display(), wpix);
|
||||
XDestroyWindow(display(), window);
|
||||
}
|
||||
if (mustFreePix)
|
||||
XFreePixmap(display(), pix.handle());
|
||||
err.error(true); // just sync and discard
|
||||
}
|
||||
|
||||
|
@ -588,11 +591,13 @@ void SceneXrender::Window::prepareTempPixmap(const QPixmap *left, const QPixmap
|
|||
{
|
||||
const QRect r = static_cast<Client*>(toplevel)->decorationRect();
|
||||
|
||||
if (temp_pixmap && Extensions::nonNativePixmaps())
|
||||
XFreePixmap(display(), temp_pixmap->handle()); // The picture owns the pixmap now
|
||||
if (!temp_pixmap)
|
||||
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) {
|
||||
if (Extensions::nonNativePixmaps()) {
|
||||
Pixmap pix = XCreatePixmap(display(), rootWindow(), temp_pixmap->width(), temp_pixmap->height(), DefaultDepth(display(), DefaultScreen(display())));
|
||||
*temp_pixmap = QPixmap::fromX11Pixmap(pix);
|
||||
}
|
||||
|
@ -952,20 +957,25 @@ void SceneXrender::EffectFrame::render(QRegion region, double opacity, double fr
|
|||
if (!m_picture) { // Lazy creation
|
||||
updatePicture();
|
||||
}
|
||||
qreal left, top, right, bottom;
|
||||
m_effectFrame->frame().getMargins(left, top, right, bottom); // m_geometry is the inner geometry
|
||||
QRect geom = m_effectFrame->geometry().adjusted(-left, -top, right, bottom);
|
||||
XRenderComposite(display(), PictOpOver, *m_picture, None, effects->xrenderBufferPicture(),
|
||||
0, 0, 0, 0, geom.x(), geom.y(), geom.width(), geom.height());
|
||||
|
||||
if (m_picture) {
|
||||
qreal left, top, right, bottom;
|
||||
m_effectFrame->frame().getMargins(left, top, right, bottom); // m_geometry is the inner geometry
|
||||
QRect geom = m_effectFrame->geometry().adjusted(-left, -top, right, bottom);
|
||||
XRenderComposite(display(), PictOpOver, *m_picture, None, effects->xrenderBufferPicture(),
|
||||
0, 0, 0, 0, geom.x(), geom.y(), geom.width(), geom.height());
|
||||
}
|
||||
}
|
||||
if (!m_effectFrame->selection().isNull()) {
|
||||
if (!m_selectionPicture) { // Lazy creation
|
||||
m_selectionPicture = new XRenderPicture(m_effectFrame->selectionFrame().framePixmap());
|
||||
const QPixmap pix = m_effectFrame->selectionFrame().framePixmap();
|
||||
if (!pix.isNull()) // don't try if there's no content
|
||||
m_selectionPicture = new XRenderPicture(m_effectFrame->selectionFrame().framePixmap());
|
||||
}
|
||||
if (m_selectionPicture) {
|
||||
const QRect geom = m_effectFrame->selection();
|
||||
XRenderComposite(display(), PictOpOver, *m_selectionPicture, None, effects->xrenderBufferPicture(),
|
||||
0, 0, 0, 0, geom.x(), geom.y(), geom.width(), geom.height());
|
||||
}
|
||||
const QRect geom = m_effectFrame->selection();
|
||||
XRenderComposite(display(), PictOpOver, *m_selectionPicture, None, effects->xrenderBufferPicture(),
|
||||
0, 0, 0, 0, geom.x(), geom.y(), geom.width(), geom.height());
|
||||
}
|
||||
|
||||
XRenderPicture fill = xRenderBlendPicture(opacity);
|
||||
|
@ -995,14 +1005,19 @@ void SceneXrender::EffectFrame::render(QRegion region, double opacity, double fr
|
|||
void SceneXrender::EffectFrame::updatePicture()
|
||||
{
|
||||
delete m_picture;
|
||||
if (m_effectFrame->style() == EffectFrameStyled)
|
||||
m_picture = new XRenderPicture(m_effectFrame->frame().framePixmap());
|
||||
m_picture = 0L;
|
||||
if (m_effectFrame->style() == EffectFrameStyled) {
|
||||
const QPixmap pix = m_effectFrame->frame().framePixmap();
|
||||
if (!pix.isNull())
|
||||
m_picture = new XRenderPicture(pix);
|
||||
}
|
||||
}
|
||||
|
||||
void SceneXrender::EffectFrame::updateTextPicture()
|
||||
{
|
||||
// Mostly copied from SceneOpenGL::EffectFrame::updateTextTexture() above
|
||||
delete m_textPicture;
|
||||
m_textPicture = 0L;
|
||||
|
||||
if (m_effectFrame->text().isEmpty()) {
|
||||
return;
|
||||
|
|
Loading…
Reference in a new issue