Rename QWindowSurface -> QBackingStore and split into platform / public.

Also get rid of GL window surface and related classes.
This commit is contained in:
Samuel Rødal 2011-06-20 13:29:26 +02:00
parent 891a86f0f3
commit 6ce6b8a378
58 changed files with 549 additions and 5470 deletions

View File

@ -1,8 +1,8 @@
#include "window.h"
#include <private/qguiapplication_p.h>
#include <private/qwindowsurface_p.h>
#include <QBackingStore>
#include <QPainter>
static int colorIndexId = 0;
@ -33,7 +33,7 @@ Window::Window(QWindow *parent)
}
create();
QGuiApplicationPrivate::platformIntegration()->createWindowSurface(this, winId());
m_backingStore = new QBackingStore(this);
m_image = QImage(geometry().size(), QImage::Format_RGB32);
m_image.fill(colorTable[m_backgroundColorIndex % (sizeof(colorTable) / sizeof(colorTable[0]))].rgba());
@ -110,11 +110,11 @@ void Window::keyPressEvent(QKeyEvent *event)
void Window::render()
{
QRect rect(QPoint(), geometry().size());
surface()->resize(rect.size());
m_backingStore->resize(rect.size());
surface()->beginPaint(rect);
m_backingStore->beginPaint(rect);
QPaintDevice *device = surface()->paintDevice();
QPaintDevice *device = m_backingStore->paintDevice();
QPainter p(device);
p.drawImage(0, 0, m_image);
@ -125,8 +125,8 @@ void Window::render()
p.setFont(font);
p.drawText(rect, 0, m_text);
surface()->endPaint(rect);
surface()->flush(this, rect, QPoint());
m_backingStore->endPaint();
m_backingStore->flush(rect);
}

View File

@ -22,4 +22,5 @@ private:
QImage m_image;
QPoint m_lastPos;
int m_backgroundColorIndex;
QBackingStore *m_backingStore;
};

View File

@ -156,19 +156,17 @@ QPlatformNativeInterface * QPlatformIntegration::nativeInterface() const
created.
\sa QPlatformWindow, QPlatformWindowFormat
\sa createWindowSurface(QWindow *window, WId winId) const
\sa createPlatformBackingStore(QWindow *window) const
*/
/*!
\fn QWindowSurface *QPlatformIntegration::createWindowSurface(QWindow *window, WId winId) const
\fn QPlatformBackingStore *QPlatformIntegration::createPlatformBackingStore(QWindow *window) const
Factory function for QWindowSurface. The QWindow parameter is a pointer to the
Factory function for QPlatformBackingStore. The QWindow parameter is a pointer to the
top level widget(tlw) the window surface is created for. A QPlatformWindow is always created
before the QWindowSurface for tlw where the widget also requires a WindowSurface. It is
possible to create top level QWindow without a QWindowSurface by specifying
QPlatformWindowFormat::setWindowSurface(false) for the tlw QPlatformWindowFormat.
before the QPlatformBackingStore for tlw where the widget also requires a backing store.
\sa QWindowSurface
\sa QBackingStore
\sa createPlatformWindow(QWindow *window, WId winId = 0) const
*/

View File

@ -43,7 +43,6 @@
#define QPLATFORMINTEGRATION_H
#include <QtGui/qwindowdefs.h>
#include <QtGui/private/qwindowsurface_p.h>
#include <QtGui/private/qpixmapdata_p.h>
#include <QtGui/qplatformscreen_qpa.h>
@ -55,7 +54,7 @@ QT_MODULE(Gui)
class QPlatformWindow;
class QWindow;
class QBlittable;
class QPlatformBackingStore;
class QPlatformFontDatabase;
class QPlatformClipboard;
class QPlatformNativeInterface;
@ -79,7 +78,7 @@ public:
// GraphicsSystem functions
virtual QPixmapData *createPixmapData(QPixmapData::PixelType type) const = 0;
virtual QPlatformWindow *createPlatformWindow(QWindow *window) const = 0;
virtual QWindowSurface *createWindowSurface(QWindow *window, WId winId) const = 0;
virtual QPlatformBackingStore *createPlatformBackingStore(QWindow *window) const = 0;
virtual QPlatformGLContext *createPlatformGLContext(const QGuiGLFormat &glFormat, QPlatformGLContext *share) const;
// Window System functions

View File

@ -426,11 +426,6 @@ QPlatformWindow *QWindow::handle() const
return d->platformWindow;
}
QWindowSurface *QWindow::surface() const
{
Q_D(const QWindow);
return d->surface;
}
bool QWindow::setKeyboardGrabEnabled(bool grab)
{
@ -531,11 +526,6 @@ bool QWindow::event(QEvent *event)
destroy();
break;
case QEvent::Expose:
if (d->surface)
d->surface->flush(this, static_cast<QExposeEvent *>(event)->region, QPoint());
break;
default:
return QObject::event(event);
}

View File

@ -69,7 +69,7 @@ class QWheelEvent;
class QPlatformGLSurface;
class QPlatformWindow;
class QWindowSurface;
class QBackingStore;
class Q_GUI_EXPORT QWindow : public QObject
{
@ -146,7 +146,6 @@ public:
void destroy();
QPlatformWindow *handle() const;
QWindowSurface *surface() const;
bool setKeyboardGrabEnabled(bool grab);
bool setMouseGrabEnabled(bool grab);
@ -192,7 +191,6 @@ private:
friend class QGuiApplication;
friend class QGuiApplicationPrivate;
friend class QWindowSurface;
friend Q_GUI_EXPORT QWindowPrivate *qt_window_private(QWindow *window);
};

View File

@ -65,7 +65,6 @@ public:
, platformWindow(0)
, visible(false)
, glSurface(0)
, surface(0)
, windowState(Qt::WindowNoState)
, maximumSize(QWINDOWSIZE_MAX, QWINDOWSIZE_MAX)
, modality(Qt::NonModal)
@ -87,7 +86,6 @@ public:
QString windowTitle;
QRect geometry;
QPlatformGLSurface *glSurface;
QWindowSurface *surface;
Qt::WindowState windowState;
QSize minimumSize;

View File

@ -1,6 +1,7 @@
# Qt gui library, paint module
HEADERS += \
painting/qbackingstore.h \
painting/qbezier_p.h \
painting/qbrush.h \
painting/qcolor.h \
@ -38,11 +39,12 @@ HEADERS += \
painting/qtessellator_p.h \
painting/qtextureglyphcache_p.h \
painting/qtransform.h \
painting/qwindowsurface_p.h \
painting/qplatformbackingstore_qpa.h \
painting/qpaintbuffer_p.h
SOURCES += \
painting/qbackingstore.cpp \
painting/qbezier.cpp \
painting/qblendfunctions.cpp \
painting/qbrush.cpp \
@ -74,7 +76,7 @@ SOURCES += \
painting/qtessellator.cpp \
painting/qtextureglyphcache.cpp \
painting/qtransform.cpp \
painting/qwindowsurface.cpp \
painting/qplatformbackingstore_qpa.cpp \
painting/qpaintbuffer.cpp
SOURCES += \

View File

@ -39,44 +39,40 @@
**
****************************************************************************/
#include <private/qwindowsurface_p.h>
#include <qbackingstore.h>
#include <qwindow.h>
#include <qpixmap.h>
#include <qplatformbackingstore_qpa.h>
#include <private/qguiapplication_p.h>
#include <private/qwindow_p.h>
QT_BEGIN_NAMESPACE
class QWindowSurfacePrivate
class QBackingStorePrivate
{
public:
QWindowSurfacePrivate(QWindow *w)
QBackingStorePrivate(QWindow *w)
: window(w)
{
}
QWindow *window;
#if !defined(Q_WS_QPA)
QRect geometry;
#else
QSize size;
#endif //Q_WS_QPA
QPlatformBackingStore *platformBackingStore;
QRegion staticContents;
QSize size;
};
/*!
\class QWindowSurface
\since 4.3
\internal
\preliminary
\ingroup qws qpa
\class QBackingStore
\since 5.0
\brief The QWindowSurface class provides the drawing area for top-level
windows.
\brief The QBackingStore class provides the drawing area for top-level windows.
*/
/*!
\fn void QWindowSurface::beginPaint(const QRegion &region)
\fn void QBackingStore::beginPaint(const QRegion &region)
This function is called before painting onto the surface begins,
with the \a region in which the painting will occur.
@ -85,7 +81,7 @@ public:
*/
/*!
\fn void QWindowSurface::endPaint(const QRegion &region)
\fn void QBackingStore::endPaint(const QRegion &region)
This function is called after painting onto the surface has ended,
with the \a region in which the painting was performed.
@ -94,7 +90,7 @@ public:
*/
/*!
\fn void QWindowSurface::flush(QWindow *window, const QRegion &region,
\fn void QBackingStore::flush(QWindow *window, const QRegion &region,
const QPoint &offset)
Flushes the given \a region from the specified \a window onto the
@ -102,91 +98,77 @@ public:
Note that the \a offset parameter is currently unused.
*/
void QBackingStore::flush(const QRegion &region, QWindow *win, const QPoint &offset)
{
if (!win)
win = window();
d_ptr->platformBackingStore->flush(win, region, offset);
}
/*!
\fn QPaintDevice* QWindowSurface::paintDevice()
\fn QPaintDevice* QBackingStore::paintDevice()
Implement this function to return the appropriate paint device.
*/
QPaintDevice *QBackingStore::paintDevice()
{
return d_ptr->platformBackingStore->paintDevice();
}
/*!
Constructs an empty surface for the given top-level \a window.
*/
QWindowSurface::QWindowSurface(QWindow *window, bool /*setDefaultSurface*/)
: d_ptr(new QWindowSurfacePrivate(window))
QBackingStore::QBackingStore(QWindow *window)
: d_ptr(new QBackingStorePrivate(window))
{
if (window)
window->d_func()->surface = this;
d_ptr->platformBackingStore = QGuiApplicationPrivate::platformIntegration()->createPlatformBackingStore(window);
}
/*!
Destroys this surface.
*/
QWindowSurface::~QWindowSurface()
QBackingStore::~QBackingStore()
{
// if (d_ptr->window)
// d_ptr->window->d_func()->extra->topextra->windowSurface = 0;
delete d_ptr;
delete d_ptr->platformBackingStore;
}
/*!
Returns a pointer to the top-level window associated with this
surface.
*/
QWindow* QWindowSurface::window() const
QWindow* QBackingStore::window() const
{
return d_ptr->window;
}
void QWindowSurface::beginPaint(const QRegion &)
void QBackingStore::beginPaint(const QRegion &region)
{
d_ptr->platformBackingStore->beginPaint(region);
}
void QWindowSurface::endPaint(const QRegion &)
void QBackingStore::endPaint()
{
d_ptr->platformBackingStore->endPaint();
}
#if !defined(Q_WS_QPA)
/*!
Sets the currently allocated area to be the given \a rect.
This function is called whenever area covered by the top-level
window changes.
\sa geometry()
*/
void QWindowSurface::setGeometry(const QRect &rect)
{
d_ptr->geometry = rect;
}
/*!
Returns the currently allocated area on the screen.
*/
QRect QWindowSurface::geometry() const
{
return d_ptr->geometry;
}
#else
/*!
Sets the size of the windowsurface to be \a size.
\sa size()
*/
void QWindowSurface::resize(const QSize &size)
void QBackingStore::resize(const QSize &size)
{
d_ptr->size = size;
d_ptr->platformBackingStore->resize(size, d_ptr->staticContents);
}
/*!
Returns the current size of the windowsurface.
*/
QSize QWindowSurface::size() const
QSize QBackingStore::size() const
{
return d_ptr->size;
}
#endif //Q_WS_QPA
/*!
Scrolls the given \a area \a dx pixels to the right and \a dy
@ -194,108 +176,31 @@ QSize QWindowSurface::size() const
Returns true if the area was scrolled successfully; false otherwise.
*/
bool QWindowSurface::scroll(const QRegion &area, int dx, int dy)
bool QBackingStore::scroll(const QRegion &area, int dx, int dy)
{
Q_UNUSED(area);
Q_UNUSED(dx);
Q_UNUSED(dy);
return false;
return d_ptr->platformBackingStore->scroll(area, dx, dy);
}
/*!
Returns a QPixmap generated from the part of the backing store
corresponding to \a window. Returns a null QPixmap if an error
occurs. The contents of the pixmap are only defined for the regions
of \a window that have received paint events since the last resize
of the backing store.
If \a rectangle is a null rectangle (the default), the entire window
is grabbed. Otherwise, the grabbed area is limited to \a rectangle.
The default implementation uses QWindowSurface::buffer().
\sa QPixmap::grabWindow()
*/
QPixmap QWindowSurface::grabWindow(const QWindow *, const QRect &) const
{
QPixmap result;
#if 0
if (window->window() != window())
return result;
const QImage *img = const_cast<QWindowSurface *>(this)->buffer(window->window());
if (!img || img->isNull())
return result;
QRect rect = rectangle.isEmpty() ? window->rect() : (window->rect() & rectangle);
rect.translate(offset(window) - offset(window->window()));
rect &= QRect(QPoint(), img->size());
if (rect.isEmpty())
return result;
QImage subimg(img->scanLine(rect.y()) + rect.x() * img->depth() / 8,
rect.width(), rect.height(),
img->bytesPerLine(), img->format());
subimg.detach(); //### expensive -- maybe we should have a real SubImage that shares reference count
result = QPixmap::fromImage(subimg);
#endif
return result;
}
/*!
Returns the offset of \a window in the coordinates of this
window surface.
*/
QPoint QWindowSurface::offset(const QWindow *) const
{
QPoint offset;
#if 0
QWindow *window = d_ptr->window;
QPoint offset = window->mapTo(window, QPoint());
#endif
return offset;
}
/*!
\fn QRect QWindowSurface::rect(const QWindow *window) const
Returns the rectangle for \a window in the coordinates of this
window surface.
*/
void QWindowSurface::setStaticContents(const QRegion &region)
void QBackingStore::setStaticContents(const QRegion &region)
{
d_ptr->staticContents = region;
}
QRegion QWindowSurface::staticContents() const
QRegion QBackingStore::staticContents() const
{
return d_ptr->staticContents;
}
bool QWindowSurface::hasStaticContents() const
bool QBackingStore::hasStaticContents() const
{
return hasFeature(QWindowSurface::StaticContents) && !d_ptr->staticContents.isEmpty();
return !d_ptr->staticContents.isEmpty();
}
QWindowSurface::WindowSurfaceFeatures QWindowSurface::features() const
{
return PartialUpdates | PreservedContents;
}
#ifdef Q_WS_QPA
#define Q_EXPORT_SCROLLRECT Q_GUI_EXPORT
#else
#define Q_EXPORT_SCROLLRECT
#endif
void Q_EXPORT_SCROLLRECT qt_scrollRectInImage(QImage &img, const QRect &rect, const QPoint &offset)
void Q_GUI_EXPORT qt_scrollRectInImage(QImage &img, const QRect &rect, const QPoint &offset)
{
// make sure we don't detach
uchar *mem = const_cast<uchar*>(const_cast<const QImage &>(img).bits());

View File

@ -4,7 +4,7 @@
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the QtOpenGL module of the Qt Toolkit.
** This file is part of the QtGui module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** GNU Lesser General Public License Usage
@ -39,45 +39,52 @@
**
****************************************************************************/
#ifndef QWINDOWSURFACE_X11GL_P_H
#define QWINDOWSURFACE_X11GL_P_H
#ifndef QBACKINGSTORE_H
#define QBACKINGSTORE_H
//
// W A R N I N G
// -------------
//
// This file is not part of the Qt API. It exists purely as an
// implementation detail. This header file may change from version to
// version without notice, or even be removed.
//
// We mean it.
//
#include <QtCore/qrect.h>
#include <private/qwindowsurface_p.h>
#include <QtGui/qwindow.h>
#include <QtGui/qregion.h>
QT_BEGIN_NAMESPACE
class QX11GLWindowSurface : public QWindowSurface
class QRegion;
class QRect;
class QPoint;
class QImage;
class QBackingStorePrivate;
class Q_GUI_EXPORT QBackingStore
{
public:
QX11GLWindowSurface(QWidget* window);
virtual ~QX11GLWindowSurface();
QBackingStore(QWindow *window);
~QBackingStore();
QWindow *window() const;
// Inherreted from QWindowSurface
QPaintDevice *paintDevice();
void flush(QWidget *widget, const QRegion &region, const QPoint &offset);
void setGeometry(const QRect &rect);
// 'window' can be a child window, in which case 'region' is in child window coordinates and
// offset is the (child) window's offset in relation to the window surface.
void flush(const QRegion &region, QWindow *window = 0, const QPoint &offset = QPoint());
void resize(const QSize &size);
QSize size() const;
bool scroll(const QRegion &area, int dx, int dy);
QPixmap grabWidget(const QWidget *widget, const QRect& rectangle = QRect()) const;
void beginPaint(const QRegion &);
void endPaint();
void setStaticContents(const QRegion &region);
QRegion staticContents() const;
bool hasStaticContents() const;
private:
GC m_windowGC;
GC m_pixmapGC;
QPixmap m_backBuffer;
QWidget *m_window;
QScopedPointer<QBackingStorePrivate> d_ptr;
};
QT_END_NAMESPACE
#endif // QWINDOWSURFACE_X11GL_P_H
#endif // QBACKINGSTORE_H

View File

@ -0,0 +1,155 @@
/****************************************************************************
**
** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the QtGui module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** GNU Lesser General Public License Usage
** This file may be used under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation and
** appearing in the file LICENSE.LGPL included in the packaging of this
** file. Please review the following information to ensure the GNU Lesser
** General Public License version 2.1 requirements will be met:
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU General
** Public License version 3.0 as published by the Free Software Foundation
** and appearing in the file LICENSE.GPL included in the packaging of this
** file. Please review the following information to ensure the GNU General
** Public License version 3.0 requirements will be met:
** http://www.gnu.org/copyleft/gpl.html.
**
** Other Usage
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include <qplatformbackingstore_qpa.h>
#include <qwindow.h>
#include <qpixmap.h>
#include <private/qwindow_p.h>
QT_BEGIN_NAMESPACE
class QPlatformBackingStorePrivate
{
public:
QPlatformBackingStorePrivate(QWindow *w)
: window(w)
{
}
QWindow *window;
QSize size;
};
/*!
\class QPlatformBackingStore
\since 5.0
\internal
\preliminary
\ingroup qpa
\brief The QPlatformBackingStore class provides the drawing area for top-level
windows.
*/
/*!
\fn void QPlatformBackingStore::beginPaint(const QRegion &region)
This function is called before painting onto the surface begins,
with the \a region in which the painting will occur.
\sa endPaint(), paintDevice()
*/
/*!
\fn void QPlatformBackingStore::endPaint(const QRegion &region)
This function is called after painting onto the surface has ended,
with the \a region in which the painting was performed.
\sa beginPaint(), paintDevice()
*/
/*!
\fn void QPlatformBackingStore::flush(QWindow *window, const QRegion &region,
const QPoint &offset)
Flushes the given \a region from the specified \a window onto the
screen.
Note that the \a offset parameter is currently unused.
*/
/*!
\fn QPaintDevice* QPlatformBackingStore::paintDevice()
Implement this function to return the appropriate paint device.
*/
/*!
Constructs an empty surface for the given top-level \a window.
*/
QPlatformBackingStore::QPlatformBackingStore(QWindow *window)
: d_ptr(new QPlatformBackingStorePrivate(window))
{
}
/*!
Destroys this surface.
*/
QPlatformBackingStore::~QPlatformBackingStore()
{
delete d_ptr;
}
/*!
Returns a pointer to the top-level window associated with this
surface.
*/
QWindow* QPlatformBackingStore::window() const
{
return d_ptr->window;
}
void QPlatformBackingStore::beginPaint(const QRegion &)
{
}
void QPlatformBackingStore::endPaint()
{
}
/*!
Scrolls the given \a area \a dx pixels to the right and \a dy
downward; both \a dx and \a dy may be negative.
Returns true if the area was scrolled successfully; false otherwise.
*/
bool QPlatformBackingStore::scroll(const QRegion &area, int dx, int dy)
{
Q_UNUSED(area);
Q_UNUSED(dx);
Q_UNUSED(dy);
return false;
}
QT_END_NAMESPACE

View File

@ -0,0 +1,86 @@
/****************************************************************************
**
** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the QtGui module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** GNU Lesser General Public License Usage
** This file may be used under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation and
** appearing in the file LICENSE.LGPL included in the packaging of this
** file. Please review the following information to ensure the GNU Lesser
** General Public License version 2.1 requirements will be met:
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU General
** Public License version 3.0 as published by the Free Software Foundation
** and appearing in the file LICENSE.GPL included in the packaging of this
** file. Please review the following information to ensure the GNU General
** Public License version 3.0 requirements will be met:
** http://www.gnu.org/copyleft/gpl.html.
**
** Other Usage
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#ifndef QPLATFORMBACKINGSTORE_QPA_H
#define QPLATFORMBACKINGSTORE_QPA_H
#include <QtCore/qrect.h>
#include <QtGui/qwindow.h>
#include <QtGui/qregion.h>
QT_BEGIN_NAMESPACE
class QRegion;
class QRect;
class QPoint;
class QImage;
class QPlatformBackingStorePrivate;
class QPlatformWindow;
class Q_GUI_EXPORT QPlatformBackingStore
{
public:
QPlatformBackingStore(QWindow *window);
virtual ~QPlatformBackingStore();
QWindow *window() const;
virtual QPaintDevice *paintDevice() = 0;
// 'window' can be a child window, in which case 'region' is in child window coordinates and
// offset is the (child) window's offset in relation to the window surface.
virtual void flush(QWindow *window, const QRegion &region, const QPoint &offset) = 0;
virtual void resize(const QSize &size, const QRegion &staticContents) = 0;
virtual bool scroll(const QRegion &area, int dx, int dy);
virtual void beginPaint(const QRegion &);
virtual void endPaint();
private:
QPlatformBackingStorePrivate *d_ptr;
};
QT_END_NAMESPACE
#endif // QPLATFORMBACKINGSTORE_QPA_H

View File

@ -1,140 +0,0 @@
/****************************************************************************
**
** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the QtGui module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** GNU Lesser General Public License Usage
** This file may be used under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation and
** appearing in the file LICENSE.LGPL included in the packaging of this
** file. Please review the following information to ensure the GNU Lesser
** General Public License version 2.1 requirements will be met:
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU General
** Public License version 3.0 as published by the Free Software Foundation
** and appearing in the file LICENSE.GPL included in the packaging of this
** file. Please review the following information to ensure the GNU General
** Public License version 3.0 requirements will be met:
** http://www.gnu.org/copyleft/gpl.html.
**
** Other Usage
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#ifndef QWINDOWSURFACE_P_H
#define QWINDOWSURFACE_P_H
//
// W A R N I N G
// -------------
//
// This file is not part of the Qt API. It exists for the convenience
// of other Qt classes. This header file may change from version to
// version without notice, or even be removed.
//
// We mean it.
//
#include <QtCore/qrect.h>
#include <QtGui/qwindow.h>
#include <QtGui/qregion.h>
QT_BEGIN_NAMESPACE
class QPaintDevice;
class QRegion;
class QRect;
class QPoint;
class QImage;
class QWindowSurfacePrivate;
class QPlatformWindow;
class Q_GUI_EXPORT QWindowSurface
{
public:
enum WindowSurfaceFeature {
PartialUpdates = 0x00000001, // Supports doing partial updates.
PreservedContents = 0x00000002, // Supports doing flush without first doing a repaint.
StaticContents = 0x00000004, // Supports having static content regions when being resized.
AllFeatures = 0xffffffff // For convenience
};
Q_DECLARE_FLAGS(WindowSurfaceFeatures, WindowSurfaceFeature)
QWindowSurface(QWindow *window, bool setDefaultSurface = true);
virtual ~QWindowSurface();
QWindow *window() const;
virtual QPaintDevice *paintDevice() = 0;
// 'window' can be a child window, in which case 'region' is in child window coordinates and
// offset is the (child) window's offset in relation to the window surface. On QWS, 'offset'
// can be larger than just the offset from the top-level window as there may also be window
// decorations which are painted into the window surface.
virtual void flush(QWindow *window, const QRegion &region, const QPoint &offset) = 0;
#if !defined(Q_WS_QPA)
virtual void setGeometry(const QRect &rect);
QRect geometry() const;
#else
virtual void resize(const QSize &size);
QSize size() const;
inline QRect geometry() const { return QRect(QPoint(), size()); } //### cleanup before Qt 5
#endif
virtual bool scroll(const QRegion &area, int dx, int dy);
virtual void beginPaint(const QRegion &);
virtual void endPaint(const QRegion &);
virtual QPixmap grabWindow(const QWindow *window, const QRect& rectangle = QRect()) const;
virtual QPoint offset(const QWindow *window) const;
inline QRect rect(const QWindow *window) const;
bool hasFeature(WindowSurfaceFeature feature) const;
virtual WindowSurfaceFeatures features() const;
void setStaticContents(const QRegion &region);
QRegion staticContents() const;
protected:
bool hasStaticContents() const;
private:
QWindowSurfacePrivate *d_ptr;
};
Q_DECLARE_OPERATORS_FOR_FLAGS(QWindowSurface::WindowSurfaceFeatures)
inline QRect QWindowSurface::rect(const QWindow *window) const
{
return window->geometry().translated(offset(window));
}
inline bool QWindowSurface::hasFeature(WindowSurfaceFeature feature) const
{
return (features() & feature) != 0;
}
QT_END_NAMESPACE
#endif // QWINDOWSURFACE_P_H

View File

@ -76,7 +76,6 @@
#include <QPaintEngine>
#include <private/qpainter_p.h>
#include <private/qfontengine_p.h>
#include <private/qpixmapdata_gl_p.h>
#include <private/qdatabuffer_p.h>
#include <private/qstatictext_p.h>
#include <private/qtriangulator_p.h>

View File

@ -57,8 +57,6 @@ SOURCES += qgl.cpp \
HEADERS += qglshaderprogram.h \
qglpixmapfilter_p.h \
qgraphicsshadereffect_p.h \
qwindowsurface_gl_p.h \
qpixmapdata_gl_p.h \
gl2paintengineex/qglgradientcache_p.h \
gl2paintengineex/qglengineshadermanager_p.h \
gl2paintengineex/qgl2pexvertexarray_p.h \
@ -74,8 +72,6 @@ SOURCES += qgl.cpp \
SOURCES += qglshaderprogram.cpp \
qglpixmapfilter.cpp \
qgraphicsshadereffect.cpp \
qwindowsurface_gl.cpp \
qpixmapdata_gl.cpp \
gl2paintengineex/qglgradientcache.cpp \
gl2paintengineex/qglengineshadermanager.cpp \
gl2paintengineex/qgl2pexvertexarray.cpp \
@ -96,13 +92,9 @@ x11 {
contains(QT_CONFIG, egl) {
SOURCES += qgl_x11egl.cpp \
qglpixelbuffer_egl.cpp \
qgl_egl.cpp \
qpixmapdata_x11gl_egl.cpp \
qwindowsurface_x11gl.cpp
qgl_egl.cpp
HEADERS += qgl_egl_p.h \
qpixmapdata_x11gl_p.h \
qwindowsurface_x11gl_p.h
HEADERS += qgl_egl_p.h
} else {
SOURCES += qgl_x11.cpp \
@ -144,16 +136,12 @@ wince*: {
}
symbian {
DEFINES += QGL_USE_TEXTURE_POOL QGL_NO_PRESERVED_SWAP
SOURCES -= qpixmapdata_gl.cpp
DEFINES += QGL_NO_PRESERVED_SWAP
SOURCES += qgl_symbian.cpp \
qpixmapdata_poolgl.cpp \
qglpixelbuffer_egl.cpp \
qgl_egl.cpp \
qgltexturepool.cpp
qgl_egl.cpp
HEADERS += qgl_egl_p.h \
qgltexturepool_p.h
HEADERS += qgl_egl_p.h
contains(QT_CONFIG, freetype) {
DEFINES += QT_NO_FONTCONFIG

View File

@ -70,17 +70,12 @@
#if !defined(QT_OPENGL_ES_1)
#include "gl2paintengineex/qpaintengineex_opengl2_p.h"
#include <private/qwindowsurface_gl_p.h>
#endif
#ifndef QT_OPENGL_ES_2
#include <private/qpaintengine_opengl_p.h>
#endif
#ifdef Q_WS_QWS
#include <private/qglwindowsurface_qws_p.h>
#endif
#ifdef Q_WS_QPA
#include <QtGui/QPlatformGLContext>
#endif
@ -90,7 +85,6 @@
#include <private/qimage_p.h>
#include <private/qpixmapdata_p.h>
#include <private/qpixmapdata_gl_p.h>
#include <private/qglpixelbuffer_p.h>
#include <private/qimagepixmapcleanuphooks_p.h>
#include "qcolormap.h"
@ -101,9 +95,6 @@
#if defined(QT_OPENGL_ES) && !defined(QT_NO_EGL)
#include <EGL/egl.h>
#endif
#ifdef QGL_USE_TEXTURE_POOL
#include <private/qgltexturepool_p.h>
#endif
// #define QT_GL_CONTEXT_RESOURCE_DEBUG
@ -2547,18 +2538,8 @@ QGLTexture* QGLContextPrivate::bindTexture(const QImage &image, GLenum target, G
#endif
const QImage &constRef = img; // to avoid detach in bits()...
#ifdef QGL_USE_TEXTURE_POOL
QGLTexturePool::instance()->createPermanentTexture(tx_id,
target,
0, internalFormat,
img.width(), img.height(),
externalFormat,
pixel_type,
constRef.bits());
#else
glTexImage2D(target, 0, internalFormat, img.width(), img.height(), 0, externalFormat,
pixel_type, constRef.bits());
#endif
#if defined(QT_OPENGL_ES_2)
if (genMipmap)
glGenerateMipmap(target);
@ -2602,18 +2583,7 @@ QGLTexture *QGLContextPrivate::bindTexture(const QPixmap &pixmap, GLenum target,
{
Q_Q(QGLContext);
QPixmapData *pd = pixmap.pixmapData();
#if !defined(QT_OPENGL_ES_1)
if (target == GL_TEXTURE_2D && pd->classId() == QPixmapData::OpenGLClass) {
const QGLPixmapData *data = static_cast<const QGLPixmapData *>(pd);
if (data->isValidContext(q)) {
data->bind();
return data->texture();
}
}
#else
Q_UNUSED(pd);
#endif
const qint64 key = pixmap.cacheKey();
QGLTexture *texture = textureCacheLookup(key, target);

View File

@ -444,8 +444,6 @@ private:
friend class QGL2PaintEngineEx;
friend class QGL2PaintEngineExPrivate;
friend class QGLEngineShaderManager;
friend class QGLWindowSurface;
friend class QGLPixmapData;
friend class QGLPixmapFilterBase;
friend class QGLTextureGlyphCache;
friend struct QGLGlyphTexture;
@ -467,7 +465,6 @@ private:
friend class QGLFBOGLPaintDevice;
friend class QGLPaintDevice;
friend class QGLWidgetGLPaintDevice;
friend class QX11GLPixmapData;
friend class QX11GLSharedContexts;
friend class QGLContextResourceBase;
friend class QSGDistanceFieldGlyphCache;

View File

@ -261,8 +261,7 @@ void QGLContextPrivate::destroyEglSurfaceForDevice()
#if defined(Q_WS_X11) || defined(Q_OS_SYMBIAN)
// Make sure we don't call eglDestroySurface on a surface which
// was created for a different winId. This applies only to QGLWidget
// paint device, so make sure this is the one we're operating on
// (as opposed to a QGLWindowSurface use case).
// paint device, so make sure this is the one we're operating on.
if (paintDevice && paintDevice->devType() == QInternal::Widget) {
QWidget *w = static_cast<QWidget *>(paintDevice);
if (QGLWidget *wgl = qobject_cast<QGLWidget *>(w)) {

View File

@ -96,10 +96,6 @@ QT_END_INCLUDE_NAMESPACE
class QMacWindowChangeEvent;
#endif
#ifdef Q_WS_QWS
class QWSGLWindowSurface;
#endif
#ifndef QT_NO_EGL
class QEglContext;
#endif
@ -212,8 +208,6 @@ public:
#elif defined(Q_WS_MAC)
QGLContext *olcx;
void updatePaintDevice();
#elif defined(Q_WS_QWS)
QWSGLWindowSurface *wsurf;
#endif
#ifdef Q_OS_SYMBIAN
void recreateEglSurface();

View File

@ -43,14 +43,6 @@
#include <private/qgl_p.h>
#include <private/qglpixelbuffer_p.h>
#include <private/qglframebufferobject_p.h>
#ifdef Q_WS_X11
#include <private/qpixmapdata_x11gl_p.h>
#endif
#if !defined(QT_OPENGL_ES_1)
#include <private/qpixmapdata_gl_p.h>
#include <private/qwindowsurface_gl_p.h>
#endif
QT_BEGIN_NAMESPACE
@ -220,19 +212,7 @@ QGLPaintDevice* QGLPaintDevice::getDevice(QPaintDevice* pd)
glpd = &(static_cast<QGLFramebufferObject*>(pd)->d_func()->glDevice);
break;
case QInternal::Pixmap: {
#if !defined(QT_OPENGL_ES_1)
QPixmapData* pmd = static_cast<QPixmap*>(pd)->pixmapData();
if (pmd->classId() == QPixmapData::OpenGLClass)
glpd = static_cast<QGLPixmapData*>(pmd)->glDevice();
#ifdef Q_WS_X11
else if (pmd->classId() == QPixmapData::X11Class)
glpd = static_cast<QX11GLPixmapData*>(pmd);
#endif
else
qWarning("Pixmap type not supported for GL rendering");
#else
qWarning("Pixmap render targets not supported on OpenGL ES 1.x");
#endif
qWarning("Pixmap type not supported for GL rendering");
break;
}
default:

View File

@ -109,7 +109,6 @@ private:
Q_DISABLE_COPY(QGLPixelBuffer)
QScopedPointer<QGLPixelBufferPrivate> d_ptr;
friend class QGLDrawable;
friend class QGLWindowSurface;
friend class QGLPaintDevice;
friend class QGLPBufferGLPaintDevice;
friend class QGLContextPrivate;

View File

@ -40,7 +40,6 @@
****************************************************************************/
#include "private/qpixmapfilter_p.h"
#include "private/qpixmapdata_gl_p.h"
#include "private/qpaintengineex_opengl2_p.h"
#include "private/qglengineshadermanager_p.h"
#include "private/qpixmapdata_p.h"

View File

@ -1,244 +0,0 @@
/****************************************************************************
**
** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the QtOpenVG module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** GNU Lesser General Public License Usage
** This file may be used under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation and
** appearing in the file LICENSE.LGPL included in the packaging of this
** file. Please review the following information to ensure the GNU Lesser
** General Public License version 2.1 requirements will be met:
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU General
** Public License version 3.0 as published by the Free Software Foundation
** and appearing in the file LICENSE.GPL included in the packaging of this
** file. Please review the following information to ensure the GNU General
** Public License version 3.0 requirements will be met:
** http://www.gnu.org/copyleft/gpl.html.
**
** Other Usage
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include "qgltexturepool_p.h"
#include "qpixmapdata_gl_p.h"
QT_BEGIN_NAMESPACE
Q_OPENGL_EXPORT extern QGLWidget* qt_gl_share_widget();
static QGLTexturePool *qt_gl_texture_pool = 0;
class QGLTexturePoolPrivate
{
public:
QGLTexturePoolPrivate() : lruFirst(0), lruLast(0) {}
QGLPixmapData *lruFirst;
QGLPixmapData *lruLast;
};
QGLTexturePool::QGLTexturePool()
: d_ptr(new QGLTexturePoolPrivate())
{
}
QGLTexturePool::~QGLTexturePool()
{
}
QGLTexturePool *QGLTexturePool::instance()
{
if (!qt_gl_texture_pool)
qt_gl_texture_pool = new QGLTexturePool();
return qt_gl_texture_pool;
}
GLuint QGLTexturePool::createTextureForPixmap(GLenum target,
GLint level,
GLint internalformat,
GLsizei width,
GLsizei height,
GLenum format,
GLenum type,
QGLPixmapData *data)
{
GLuint texture;
glGenTextures(1, &texture);
glBindTexture(target, texture);
do {
glTexImage2D(target, level, internalformat, width, height, 0, format, type, 0);
GLenum error = glGetError();
if (error == GL_NO_ERROR) {
if (data)
moveToHeadOfLRU(data);
return texture;
} else if (error != GL_OUT_OF_MEMORY) {
qWarning("QGLTexturePool: cannot create temporary texture because of invalid params");
return 0;
}
} while (reclaimSpace(internalformat, width, height, format, type, data));
qWarning("QGLTexturePool: cannot reclaim sufficient space for a %dx%d pixmap",
width, height);
return 0;
}
bool QGLTexturePool::createPermanentTexture(GLuint texture,
GLenum target,
GLint level,
GLint internalformat,
GLsizei width,
GLsizei height,
GLenum format,
GLenum type,
const GLvoid *data)
{
glBindTexture(target, texture);
do {
glTexImage2D(target, level, internalformat, width, height, 0, format, type, data);
GLenum error = glGetError();
if (error == GL_NO_ERROR) {
return true;
} else if (error != GL_OUT_OF_MEMORY) {
qWarning("QGLTexturePool: cannot create permanent texture because of invalid params");
return false;
}
} while (reclaimSpace(internalformat, width, height, format, type, 0));
qWarning("QGLTexturePool: cannot reclaim sufficient space for a %dx%d pixmap",
width, height);
return 0;
}
void QGLTexturePool::releaseTexture(QGLPixmapData *data, GLuint texture)
{
// Very simple strategy at the moment: just destroy the texture.
if (data)
removeFromLRU(data);
QGLWidget *shareWidget = qt_gl_share_widget();
if (shareWidget) {
QGLShareContextScope ctx(shareWidget->context());
glDeleteTextures(1, &texture);
}
}
void QGLTexturePool::useTexture(QGLPixmapData *data)
{
moveToHeadOfLRU(data);
}
void QGLTexturePool::detachTexture(QGLPixmapData *data)
{
removeFromLRU(data);
}
bool QGLTexturePool::reclaimSpace(GLint internalformat,
GLsizei width,
GLsizei height,
GLenum format,
GLenum type,
QGLPixmapData *data)
{
Q_UNUSED(internalformat); // For future use in picking the best texture to eject.
Q_UNUSED(width);
Q_UNUSED(height);
Q_UNUSED(format);
Q_UNUSED(type);
bool succeeded = false;
bool wasInLRU = false;
if (data) {
wasInLRU = data->inLRU;
moveToHeadOfLRU(data);
}
QGLPixmapData *lrudata = pixmapLRU();
if (lrudata && lrudata != data) {
lrudata->reclaimTexture();
succeeded = true;
}
if (data && !wasInLRU)
removeFromLRU(data);
return succeeded;
}
void QGLTexturePool::hibernate()
{
Q_D(QGLTexturePool);
QGLPixmapData *pd = d->lruLast;
while (pd) {
QGLPixmapData *prevLRU = pd->prevLRU;
pd->inTexturePool = false;
pd->inLRU = false;
pd->nextLRU = 0;
pd->prevLRU = 0;
pd->hibernate();
pd = prevLRU;
}
d->lruFirst = 0;
d->lruLast = 0;
}
void QGLTexturePool::moveToHeadOfLRU(QGLPixmapData *data)
{
Q_D(QGLTexturePool);
if (data->inLRU) {
if (!data->prevLRU)
return; // Already at the head of the list.
removeFromLRU(data);
}
data->inLRU = true;
data->nextLRU = d->lruFirst;
data->prevLRU = 0;
if (d->lruFirst)
d->lruFirst->prevLRU = data;
else
d->lruLast = data;
d->lruFirst = data;
}
void QGLTexturePool::removeFromLRU(QGLPixmapData *data)
{
Q_D(QGLTexturePool);
if (!data->inLRU)
return;
if (data->nextLRU)
data->nextLRU->prevLRU = data->prevLRU;
else
d->lruLast = data->prevLRU;
if (data->prevLRU)
data->prevLRU->nextLRU = data->nextLRU;
else
d->lruFirst = data->nextLRU;
data->inLRU = false;
}
QGLPixmapData *QGLTexturePool::pixmapLRU()
{
Q_D(QGLTexturePool);
return d->lruLast;
}
QT_END_NAMESPACE

View File

@ -1,147 +0,0 @@
/****************************************************************************
**
** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the QtOpenVG module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** GNU Lesser General Public License Usage
** This file may be used under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation and
** appearing in the file LICENSE.LGPL included in the packaging of this
** file. Please review the following information to ensure the GNU Lesser
** General Public License version 2.1 requirements will be met:
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU General
** Public License version 3.0 as published by the Free Software Foundation
** and appearing in the file LICENSE.GPL included in the packaging of this
** file. Please review the following information to ensure the GNU General
** Public License version 3.0 requirements will be met:
** http://www.gnu.org/copyleft/gpl.html.
**
** Other Usage
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#ifndef QGLTEXTUREPOOL_P_H
#define QGLTEXTUREPOOL_P_H
//
// W A R N I N G
// -------------
//
// This file is not part of the Qt API. It exists for the convenience
// of other Qt classes. This header file may change from version to
// version without notice, or even be removed.
//
// We mean it.
//
#include "qgl.h"
#include <QtCore/qscopedpointer.h>
QT_BEGIN_NAMESPACE
class QGLPixmapData;
class QGLTexturePoolPrivate;
class QGLTexturePool
{
public:
QGLTexturePool();
virtual ~QGLTexturePool();
static QGLTexturePool *instance();
// Create a new texture with the specified parameters and associate
// it with "data". The QGLPixmapData will be notified when the
// texture needs to be reclaimed by the pool.
//
// This function will call reclaimSpace() when texture creation fails.
GLuint createTextureForPixmap(GLenum target,
GLint level,
GLint internalformat,
GLsizei width,
GLsizei height,
GLenum format,
GLenum type,
QGLPixmapData *data);
// Create a permanent texture with the specified parameters.
// If there is insufficient space for the texture,
// then this function will call reclaimSpace() and try again.
//
// The caller is responsible for calling glDeleteTextures()
// when it no longer needs the texture, as the texture is not
// recorded in the texture pool.
bool createPermanentTexture(GLuint texture,
GLenum target,
GLint level,
GLint internalformat,
GLsizei width,
GLsizei height,
GLenum format,
GLenum type,
const GLvoid *data);
// Release a texture that is no longer required.
void releaseTexture(QGLPixmapData *data, GLuint texture);
// Notify the pool that a QGLPixmapData object is using
// an texture again. This allows the pool to move the texture
// within a least-recently-used list of QGLPixmapData objects.
void useTexture(QGLPixmapData *data);
// Notify the pool that the texture associated with a
// QGLPixmapData is being detached from the pool. The caller
// will become responsible for calling glDeleteTextures().
void detachTexture(QGLPixmapData *data);
// Reclaim space for an image allocation with the specified parameters.
// Returns true if space was reclaimed, or false if there is no
// further space that can be reclaimed. The "data" parameter
// indicates the pixmap that is trying to obtain space which should
// not itself be reclaimed.
bool reclaimSpace(GLint internalformat,
GLsizei width,
GLsizei height,
GLenum format,
GLenum type,
QGLPixmapData *data);
// Hibernate the image pool because the context is about to be
// destroyed. All textures left in the pool should be released.
void hibernate();
protected:
// Helper functions for managing the LRU list of QGLPixmapData objects.
void moveToHeadOfLRU(QGLPixmapData *data);
void removeFromLRU(QGLPixmapData *data);
QGLPixmapData *pixmapLRU();
private:
QScopedPointer<QGLTexturePoolPrivate> d_ptr;
Q_DECLARE_PRIVATE(QGLTexturePool)
Q_DISABLE_COPY(QGLTexturePool)
};
QT_END_NAMESPACE
#endif

View File

@ -1,829 +0,0 @@
/****************************************************************************
**
** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the QtOpenGL module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** GNU Lesser General Public License Usage
** This file may be used under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation and
** appearing in the file LICENSE.LGPL included in the packaging of this
** file. Please review the following information to ensure the GNU Lesser
** General Public License version 2.1 requirements will be met:
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU General
** Public License version 3.0 as published by the Free Software Foundation
** and appearing in the file LICENSE.GPL included in the packaging of this
** file. Please review the following information to ensure the GNU General
** Public License version 3.0 requirements will be met:
** http://www.gnu.org/copyleft/gpl.html.
**
** Other Usage
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include "qpixmap.h"
#include "qglframebufferobject.h"
#include <private/qpaintengine_raster_p.h>
#include "qpixmapdata_gl_p.h"
#include <private/qgl_p.h>
#include <private/qdrawhelper_p.h>
#include <private/qimage_p.h>
#include <private/qfont_p.h>
#include <private/qpaintengineex_opengl2_p.h>
#include <qdesktopwidget.h>
#include <qfile.h>
#include <qimagereader.h>
#include <qbuffer.h>
QT_BEGIN_NAMESPACE
Q_OPENGL_EXPORT extern const QGLContext* qt_gl_share_context();
/*!
\class QGLFramebufferObjectPool
\since 4.6
\brief The QGLFramebufferObject class provides a pool of framebuffer
objects for offscreen rendering purposes.
When requesting an FBO of a given size and format, an FBO of the same
format and a size at least as big as the requested size will be returned.
\internal
*/
static inline int areaDiff(const QSize &size, const QGLFramebufferObject *fbo)
{
return qAbs(size.width() * size.height() - fbo->width() * fbo->height());
}
extern int qt_next_power_of_two(int v);
static inline QSize maybeRoundToNextPowerOfTwo(const QSize &sz)
{
#ifdef QT_OPENGL_ES_2
QSize rounded(qt_next_power_of_two(sz.width()), qt_next_power_of_two(sz.height()));
if (rounded.width() * rounded.height() < 1.20 * sz.width() * sz.height())
return rounded;
#endif
return sz;
}
QGLFramebufferObject *QGLFramebufferObjectPool::acquire(const QSize &requestSize, const QGLFramebufferObjectFormat &requestFormat, bool strictSize)
{
QGLFramebufferObject *chosen = 0;
QGLFramebufferObject *candidate = 0;
for (int i = 0; !chosen && i < m_fbos.size(); ++i) {
QGLFramebufferObject *fbo = m_fbos.at(i);
if (strictSize) {
if (fbo->size() == requestSize && fbo->format() == requestFormat) {
chosen = fbo;
break;
} else {
continue;
}
}
if (fbo->format() == requestFormat) {
// choose the fbo with a matching format and the closest size
if (!candidate || areaDiff(requestSize, candidate) > areaDiff(requestSize, fbo))
candidate = fbo;
}
if (candidate) {
m_fbos.removeOne(candidate);
const QSize fboSize = candidate->size();
QSize sz = fboSize;
if (sz.width() < requestSize.width())
sz.setWidth(qMax(requestSize.width(), qRound(sz.width() * 1.5)));
if (sz.height() < requestSize.height())
sz.setHeight(qMax(requestSize.height(), qRound(sz.height() * 1.5)));
// wasting too much space?
if (sz.width() * sz.height() > requestSize.width() * requestSize.height() * 4)
sz = requestSize;
if (sz != fboSize) {
delete candidate;
candidate = new QGLFramebufferObject(maybeRoundToNextPowerOfTwo(sz), requestFormat);
}
chosen = candidate;
}
}
if (!chosen) {
if (strictSize)
chosen = new QGLFramebufferObject(requestSize, requestFormat);
else
chosen = new QGLFramebufferObject(maybeRoundToNextPowerOfTwo(requestSize), requestFormat);
}
if (!chosen->isValid()) {
delete chosen;
chosen = 0;
}
return chosen;
}
void QGLFramebufferObjectPool::release(QGLFramebufferObject *fbo)
{
if (fbo)
m_fbos << fbo;
}
QPaintEngine* QGLPixmapGLPaintDevice::paintEngine() const
{
return data->paintEngine();
}
void QGLPixmapGLPaintDevice::beginPaint()
{
if (!data->isValid())
return;
// QGLPaintDevice::beginPaint will store the current binding and replace
// it with m_thisFBO:
m_thisFBO = data->m_renderFbo->handle();
QGLPaintDevice::beginPaint();
Q_ASSERT(data->paintEngine()->type() == QPaintEngine::OpenGL2);
// QPixmap::fill() is deferred until now, where we actually need to do the fill:
if (data->needsFill()) {
const QColor &c = data->fillColor();
float alpha = c.alphaF();
glDisable(GL_SCISSOR_TEST);
glClearColor(c.redF() * alpha, c.greenF() * alpha, c.blueF() * alpha, alpha);
glClear(GL_COLOR_BUFFER_BIT);
}
else if (!data->isUninitialized()) {
// If the pixmap (GL Texture) has valid content (it has been
// uploaded from an image or rendered into before), we need to
// copy it from the texture to the render FBO.
glDisable(GL_DEPTH_TEST);
glDisable(GL_SCISSOR_TEST);
glDisable(GL_BLEND);
#if !defined(QT_OPENGL_ES_2)
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0, data->width(), data->height(), 0, -999999, 999999);
#endif
glViewport(0, 0, data->width(), data->height());
// Pass false to bind so it doesn't copy the FBO into the texture!
context()->drawTexture(QRect(0, 0, data->width(), data->height()), data->bind(false));
}
}
void QGLPixmapGLPaintDevice::endPaint()
{
if (!data->isValid())
return;
data->copyBackFromRenderFbo(false);
// Base's endPaint will restore the previous FBO binding
QGLPaintDevice::endPaint();
qgl_fbo_pool()->release(data->m_renderFbo);
data->m_renderFbo = 0;
}
QGLContext* QGLPixmapGLPaintDevice::context() const
{
data->ensureCreated();
return data->m_ctx;
}
QSize QGLPixmapGLPaintDevice::size() const
{
return data->size();
}
bool QGLPixmapGLPaintDevice::alphaRequested() const
{
return data->m_hasAlpha;
}
void QGLPixmapGLPaintDevice::setPixmapData(QGLPixmapData* d)
{
data = d;
}
static int qt_gl_pixmap_serial = 0;
QGLPixmapData::QGLPixmapData(PixelType type)
: QPixmapData(type, OpenGLClass)
, m_renderFbo(0)
, m_engine(0)
, m_ctx(0)
, m_dirty(false)
, m_hasFillColor(false)
, m_hasAlpha(false)
{
setSerialNumber(++qt_gl_pixmap_serial);
m_glDevice.setPixmapData(this);
}
QGLPixmapData::~QGLPixmapData()
{
const QGLContext *shareContext = qt_gl_share_context();
if (!shareContext)
return;
delete m_engine;
if (m_texture.id) {
QGLShareContextScope ctx(shareContext);
glDeleteTextures(1, &m_texture.id);
}
}
QPixmapData *QGLPixmapData::createCompatiblePixmapData() const
{
return new QGLPixmapData(pixelType());
}
bool QGLPixmapData::isValid() const
{
return w > 0 && h > 0;
}
bool QGLPixmapData::isValidContext(const QGLContext *ctx) const
{
if (ctx == m_ctx)
return true;
const QGLContext *share_ctx = qt_gl_share_context();
return ctx == share_ctx || QGLContext::areSharing(ctx, share_ctx);
}
void QGLPixmapData::resize(int width, int height)
{
if (width == w && height == h)
return;
if (width <= 0 || height <= 0) {
width = 0;
height = 0;
}
w = width;
h = height;
is_null = (w <= 0 || h <= 0);
d = pixelType() == QPixmapData::PixmapType ? 32 : 1;
if (m_texture.id) {
QGLShareContextScope ctx(qt_gl_share_context());
glDeleteTextures(1, &m_texture.id);
m_texture.id = 0;
}
m_source = QImage();
m_dirty = isValid();
setSerialNumber(++qt_gl_pixmap_serial);
}
void QGLPixmapData::ensureCreated() const
{
if (!m_dirty)
return;
m_dirty = false;
QGLShareContextScope ctx(qt_gl_share_context());
m_ctx = ctx;
const GLenum internal_format = m_hasAlpha ? GL_RGBA : GL_RGB;
#ifdef QT_OPENGL_ES_2
const GLenum external_format = internal_format;
#else
const GLenum external_format = qt_gl_preferredTextureFormat();
#endif
const GLenum target = GL_TEXTURE_2D;
if (!m_texture.id) {
glGenTextures(1, &m_texture.id);
glBindTexture(target, m_texture.id);
glTexImage2D(target, 0, internal_format, w, h, 0, external_format, GL_UNSIGNED_BYTE, 0);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
}
if (!m_source.isNull()) {
if (external_format == GL_RGB) {
const QImage tx = m_source.convertToFormat(QImage::Format_RGB888).mirrored(false, true);
glBindTexture(target, m_texture.id);
glTexSubImage2D(target, 0, 0, 0, w, h, external_format,
GL_UNSIGNED_BYTE, tx.bits());
} else {
const QImage tx = ctx->d_func()->convertToGLFormat(m_source, true, external_format);
glBindTexture(target, m_texture.id);
glTexSubImage2D(target, 0, 0, 0, w, h, external_format,
GL_UNSIGNED_BYTE, tx.bits());
}
if (useFramebufferObjects())
m_source = QImage();
}
m_texture.options &= ~QGLContext::MemoryManagedBindOption;
}
void QGLPixmapData::fromImage(const QImage &image,
Qt::ImageConversionFlags flags)
{
QImage img = image;
createPixmapForImage(img, flags, false);
}
void QGLPixmapData::fromImageReader(QImageReader *imageReader,
Qt::ImageConversionFlags flags)
{
QImage image = imageReader->read();
if (image.isNull())
return;
createPixmapForImage(image, flags, true);
}
bool QGLPixmapData::fromFile(const QString &filename, const char *format,
Qt::ImageConversionFlags flags)
{
if (pixelType() == QPixmapData::BitmapType)
return QPixmapData::fromFile(filename, format, flags);
QFile file(filename);
if (file.open(QIODevice::ReadOnly)) {
QByteArray data = file.peek(64);
bool alpha;
if (m_texture.canBindCompressedTexture
(data.constData(), data.size(), format, &alpha)) {
resize(0, 0);
data = file.readAll();
file.close();
QGLShareContextScope ctx(qt_gl_share_context());
QSize size = m_texture.bindCompressedTexture
(data.constData(), data.size(), format);
if (!size.isEmpty()) {
w = size.width();
h = size.height();
is_null = false;
d = 32;
m_hasAlpha = alpha;
m_source = QImage();
m_dirty = isValid();
return true;
}
return false;
}
}
QImage image = QImageReader(filename, format).read();
if (image.isNull())
return false;
createPixmapForImage(image, flags, true);
return !isNull();
}
bool QGLPixmapData::fromData(const uchar *buffer, uint len, const char *format,
Qt::ImageConversionFlags flags)
{
bool alpha;
const char *buf = reinterpret_cast<const char *>(buffer);
if (m_texture.canBindCompressedTexture(buf, int(len), format, &alpha)) {
resize(0, 0);
QGLShareContextScope ctx(qt_gl_share_context());
QSize size = m_texture.bindCompressedTexture(buf, int(len), format);
if (!size.isEmpty()) {
w = size.width();
h = size.height();
is_null = false;
d = 32;
m_hasAlpha = alpha;
m_source = QImage();
m_dirty = isValid();
return true;
}
}
QByteArray a = QByteArray::fromRawData(reinterpret_cast<const char *>(buffer), len);
QBuffer b(&a);
b.open(QIODevice::ReadOnly);
QImage image = QImageReader(&b, format).read();
if (image.isNull())
return false;
createPixmapForImage(image, flags, true);
return !isNull();
}
/*!
out-of-place conversion (inPlace == false) will always detach()
*/
void QGLPixmapData::createPixmapForImage(QImage &image, Qt::ImageConversionFlags flags, bool inPlace)
{
if (image.size() == QSize(w, h))
setSerialNumber(++qt_gl_pixmap_serial);
resize(image.width(), image.height());
if (pixelType() == BitmapType) {
m_source = image.convertToFormat(QImage::Format_MonoLSB);
} else {
QImage::Format format = QImage::Format_RGB32;
if (qApp->desktop()->depth() == 16)
format = QImage::Format_RGB16;
if (image.hasAlphaChannel()
&& ((flags & Qt::NoOpaqueDetection)
|| const_cast<QImage &>(image).data_ptr()->checkForAlphaPixels()))
format = QImage::Format_ARGB32_Premultiplied;;
if (inPlace && image.data_ptr()->convertInPlace(format, flags)) {
m_source = image;
} else {
m_source = image.convertToFormat(format);
// convertToFormat won't detach the image if format stays the same.
if (image.format() == format)
m_source.detach();
}
}
m_dirty = true;
m_hasFillColor = false;
m_hasAlpha = m_source.hasAlphaChannel();
w = image.width();
h = image.height();
is_null = (w <= 0 || h <= 0);
d = m_source.depth();
if (m_texture.id) {
QGLShareContextScope ctx(qt_gl_share_context());
glDeleteTextures(1, &m_texture.id);
m_texture.id = 0;
}
}
bool QGLPixmapData::scroll(int dx, int dy, const QRect &rect)
{
Q_UNUSED(dx);
Q_UNUSED(dy);
Q_UNUSED(rect);
return false;
}
void QGLPixmapData::copy(const QPixmapData *data, const QRect &rect)
{
if (data->classId() != QPixmapData::OpenGLClass || !static_cast<const QGLPixmapData *>(data)->useFramebufferObjects()) {
QPixmapData::copy(data, rect);
return;
}
const QGLPixmapData *other = static_cast<const QGLPixmapData *>(data);
if (other->m_renderFbo) {
QGLShareContextScope ctx(qt_gl_share_context());
resize(rect.width(), rect.height());
m_hasAlpha = other->m_hasAlpha;
ensureCreated();
if (!ctx->d_ptr->fbo)
glGenFramebuffers(1, &ctx->d_ptr->fbo);
glBindFramebuffer(GL_DRAW_FRAMEBUFFER_EXT, ctx->d_ptr->fbo);
glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT,
GL_TEXTURE_2D, m_texture.id, 0);
if (!other->m_renderFbo->isBound())
glBindFramebuffer(GL_READ_FRAMEBUFFER_EXT, other->m_renderFbo->handle());
glDisable(GL_SCISSOR_TEST);
if (ctx->d_ptr->active_engine && ctx->d_ptr->active_engine->type() == QPaintEngine::OpenGL2)
static_cast<QGL2PaintEngineEx *>(ctx->d_ptr->active_engine)->invalidateState();
glBlitFramebufferEXT(rect.x(), rect.y(), rect.x() + rect.width(), rect.y() + rect.height(),
0, 0, w, h,
GL_COLOR_BUFFER_BIT,
GL_NEAREST);
glBindFramebuffer(GL_FRAMEBUFFER_EXT, ctx->d_ptr->current_fbo);
} else {
QPixmapData::copy(data, rect);
}
}
void QGLPixmapData::fill(const QColor &color)
{
if (!isValid())
return;
bool hasAlpha = color.alpha() != 255;
if (hasAlpha && !m_hasAlpha) {
if (m_texture.id) {
glDeleteTextures(1, &m_texture.id);
m_texture.id = 0;
m_dirty = true;
}
m_hasAlpha = color.alpha() != 255;
}
if (useFramebufferObjects()) {
m_source = QImage();
m_hasFillColor = true;
m_fillColor = color;
} else {
if (m_source.isNull()) {
m_fillColor = color;
m_hasFillColor = true;
} else if (m_source.depth() == 32) {
m_source.fill(PREMUL(color.rgba()));
} else if (m_source.depth() == 1) {
if (color == Qt::color1)
m_source.fill(1);
else
m_source.fill(0);
}
}
}
bool QGLPixmapData::hasAlphaChannel() const
{
return m_hasAlpha;
}
QImage QGLPixmapData::fillImage(const QColor &color) const
{
QImage img;
if (pixelType() == BitmapType) {
img = QImage(w, h, QImage::Format_MonoLSB);
img.setColorCount(2);
img.setColor(0, QColor(Qt::color0).rgba());
img.setColor(1, QColor(Qt::color1).rgba());
if (color == Qt::color1)
img.fill(1);
else
img.fill(0);
} else {
img = QImage(w, h,
m_hasAlpha
? QImage::Format_ARGB32_Premultiplied
: QImage::Format_RGB32);
img.fill(PREMUL(color.rgba()));
}
return img;
}
extern QImage qt_gl_read_texture(const QSize &size, bool alpha_format, bool include_alpha);
QImage QGLPixmapData::toImage() const
{
if (!isValid())
return QImage();
if (m_renderFbo) {
copyBackFromRenderFbo(true);
} else if (!m_source.isNull()) {
QImageData *data = const_cast<QImage &>(m_source).data_ptr();
if (data->paintEngine && data->paintEngine->isActive()
&& data->paintEngine->paintDevice() == &m_source)
{
return m_source.copy();
}
return m_source;
} else if (m_dirty || m_hasFillColor) {
return fillImage(m_fillColor);
} else {
ensureCreated();
}
QGLShareContextScope ctx(qt_gl_share_context());
glBindTexture(GL_TEXTURE_2D, m_texture.id);
return qt_gl_read_texture(QSize(w, h), true, true);
}
struct TextureBuffer
{
QGLFramebufferObject *fbo;
QGL2PaintEngineEx *engine;
};
Q_GLOBAL_STATIC(QGLFramebufferObjectPool, _qgl_fbo_pool)
QGLFramebufferObjectPool* qgl_fbo_pool()
{
return _qgl_fbo_pool();
}
void QGLPixmapData::copyBackFromRenderFbo(bool keepCurrentFboBound) const
{
if (!isValid())
return;
m_hasFillColor = false;
const QGLContext *share_ctx = qt_gl_share_context();
QGLShareContextScope ctx(share_ctx);
ensureCreated();
if (!ctx->d_ptr->fbo)
glGenFramebuffers(1, &ctx->d_ptr->fbo);
glBindFramebuffer(GL_DRAW_FRAMEBUFFER_EXT, ctx->d_ptr->fbo);
glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT,
GL_TEXTURE_2D, m_texture.id, 0);
const int x0 = 0;
const int x1 = w;
const int y0 = 0;
const int y1 = h;
if (!m_renderFbo->isBound())
glBindFramebuffer(GL_READ_FRAMEBUFFER_EXT, m_renderFbo->handle());
glDisable(GL_SCISSOR_TEST);
glBlitFramebufferEXT(x0, y0, x1, y1,
x0, y0, x1, y1,
GL_COLOR_BUFFER_BIT,
GL_NEAREST);
if (keepCurrentFboBound) {
glBindFramebuffer(GL_FRAMEBUFFER_EXT, ctx->d_ptr->current_fbo);
} else {
glBindFramebuffer(GL_DRAW_FRAMEBUFFER_EXT, m_renderFbo->handle());
ctx->d_ptr->current_fbo = m_renderFbo->handle();
}
}
bool QGLPixmapData::useFramebufferObjects() const
{
return QGLFramebufferObject::hasOpenGLFramebufferObjects()
&& QGLFramebufferObject::hasOpenGLFramebufferBlit()
&& qt_gl_preferGL2Engine()
&& (w * h > 32*32); // avoid overhead of FBOs for small pixmaps
}
QPaintEngine* QGLPixmapData::paintEngine() const
{
if (!isValid())
return 0;
if (m_renderFbo)
return m_engine;
if (useFramebufferObjects()) {
extern QGLWidget* qt_gl_share_widget();
if (!QGLContext::currentContext())
const_cast<QGLContext *>(qt_gl_share_context())->makeCurrent();
QGLShareContextScope ctx(qt_gl_share_context());
QGLFramebufferObjectFormat format;
format.setAttachment(QGLFramebufferObject::CombinedDepthStencil);
format.setSamples(4);
format.setInternalTextureFormat(GLenum(m_hasAlpha ? GL_RGBA : GL_RGB));
m_renderFbo = qgl_fbo_pool()->acquire(size(), format);
if (m_renderFbo) {
if (!m_engine)
m_engine = new QGL2PaintEngineEx;
return m_engine;
}
qWarning() << "Failed to create pixmap texture buffer of size " << size() << ", falling back to raster paint engine";
}
m_dirty = true;
if (m_source.size() != size())
m_source = QImage(size(), QImage::Format_ARGB32_Premultiplied);
if (m_hasFillColor) {
m_source.fill(PREMUL(m_fillColor.rgba()));
m_hasFillColor = false;
}
return m_source.paintEngine();
}
extern QRgb qt_gl_convertToGLFormat(QRgb src_pixel, GLenum texture_format);
// If copyBack is true, bind will copy the contents of the render
// FBO to the texture (which is not bound to the texture, as it's
// a multisample FBO).
GLuint QGLPixmapData::bind(bool copyBack) const
{
if (m_renderFbo && copyBack) {
copyBackFromRenderFbo(true);
} else {
ensureCreated();
}
GLuint id = m_texture.id;
glBindTexture(GL_TEXTURE_2D, id);
if (m_hasFillColor) {
if (!useFramebufferObjects()) {
m_source = QImage(w, h, QImage::Format_ARGB32_Premultiplied);
m_source.fill(PREMUL(m_fillColor.rgba()));
}
m_hasFillColor = false;
GLenum format = qt_gl_preferredTextureFormat();
QImage tx(w, h, QImage::Format_ARGB32_Premultiplied);
tx.fill(qt_gl_convertToGLFormat(m_fillColor.rgba(), format));
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, w, h, format, GL_UNSIGNED_BYTE, tx.bits());
}
return id;
}
QGLTexture* QGLPixmapData::texture() const
{
return &m_texture;
}
int QGLPixmapData::metric(QPaintDevice::PaintDeviceMetric metric) const
{
if (w == 0)
return 0;
switch (metric) {
case QPaintDevice::PdmWidth:
return w;
case QPaintDevice::PdmHeight:
return h;
case QPaintDevice::PdmNumColors:
return 0;
case QPaintDevice::PdmDepth:
return d;
case QPaintDevice::PdmWidthMM:
return qRound(w * 25.4 / qt_defaultDpiX());
case QPaintDevice::PdmHeightMM:
return qRound(h * 25.4 / qt_defaultDpiY());
case QPaintDevice::PdmDpiX:
case QPaintDevice::PdmPhysicalDpiX:
return qt_defaultDpiX();
case QPaintDevice::PdmDpiY:
case QPaintDevice::PdmPhysicalDpiY:
return qt_defaultDpiY();
default:
qWarning("QGLPixmapData::metric(): Invalid metric");
return 0;
}
}
QGLPaintDevice *QGLPixmapData::glDevice() const
{
return &m_glDevice;
}
QT_END_NAMESPACE

View File

@ -1,247 +0,0 @@
/****************************************************************************
**
** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the QtOpenGL module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** GNU Lesser General Public License Usage
** This file may be used under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation and
** appearing in the file LICENSE.LGPL included in the packaging of this
** file. Please review the following information to ensure the GNU Lesser
** General Public License version 2.1 requirements will be met:
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU General
** Public License version 3.0 as published by the Free Software Foundation
** and appearing in the file LICENSE.GPL included in the packaging of this
** file. Please review the following information to ensure the GNU General
** Public License version 3.0 requirements will be met:
** http://www.gnu.org/copyleft/gpl.html.
**
** Other Usage
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#ifndef QPIXMAPDATA_GL_P_H
#define QPIXMAPDATA_GL_P_H
//
// W A R N I N G
// -------------
//
// This file is not part of the Qt API. It exists purely as an
// implementation detail. This header file may change from version to
// version without notice, or even be removed.
//
// We mean it.
//
#include "qgl_p.h"
#include "qgl.h"
#include "private/qpixmapdata_p.h"
#include "private/qglpaintdevice_p.h"
#ifdef Q_OS_SYMBIAN
#include "private/qvolatileimage_p.h"
#endif
QT_BEGIN_NAMESPACE
class QPaintEngine;
class QGLFramebufferObject;
class QGLFramebufferObjectFormat;
class QGLPixmapData;
#ifdef QGL_USE_TEXTURE_POOL
void qt_gl_register_pixmap(QGLPixmapData *pd);
void qt_gl_unregister_pixmap(QGLPixmapData *pd);
void qt_gl_hibernate_pixmaps();
#endif
#ifdef Q_OS_SYMBIAN
class QNativeImageHandleProvider;
#endif
class QGLFramebufferObjectPool
{
public:
QGLFramebufferObject *acquire(const QSize &size, const QGLFramebufferObjectFormat &format, bool strictSize = false);
void release(QGLFramebufferObject *fbo);
private:
QList<QGLFramebufferObject *> m_fbos;
};
QGLFramebufferObjectPool* qgl_fbo_pool();
class QGLPixmapGLPaintDevice : public QGLPaintDevice
{
public:
QPaintEngine* paintEngine() const;
void beginPaint();
void endPaint();
QGLContext* context() const;
QSize size() const;
bool alphaRequested() const;
void setPixmapData(QGLPixmapData*);
private:
QGLPixmapData *data;
};
class Q_OPENGL_EXPORT QGLPixmapData : public QPixmapData
{
public:
QGLPixmapData(PixelType type);
~QGLPixmapData();
QPixmapData *createCompatiblePixmapData() const;
// Re-implemented from QPixmapData:
void resize(int width, int height);
void fromImage(const QImage &image, Qt::ImageConversionFlags flags);
void fromImageReader(QImageReader *imageReader,
Qt::ImageConversionFlags flags);
bool fromFile(const QString &filename, const char *format,
Qt::ImageConversionFlags flags);
bool fromData(const uchar *buffer, uint len, const char *format,
Qt::ImageConversionFlags flags);
void copy(const QPixmapData *data, const QRect &rect);
bool scroll(int dx, int dy, const QRect &rect);
void fill(const QColor &color);
bool hasAlphaChannel() const;
QImage toImage() const;
QPaintEngine *paintEngine() const;
int metric(QPaintDevice::PaintDeviceMetric metric) const;
// For accessing as a target:
QGLPaintDevice *glDevice() const;
// For accessing as a source:
bool isValidContext(const QGLContext *ctx) const;
GLuint bind(bool copyBack = true) const;
QGLTexture *texture() const;
#ifdef QGL_USE_TEXTURE_POOL
void destroyTexture();
// Detach this image from the image pool.
void detachTextureFromPool();
// Release the GL resources associated with this pixmap and copy
// the pixmap's contents out of the GPU back into main memory.
// The GL resource will be automatically recreated the next time
// ensureCreated() is called. Does nothing if the pixmap cannot be
// hibernated for some reason (e.g. texture is shared with another
// process via a SgImage).
void hibernate();
// Called when the QGLTexturePool wants to reclaim this pixmap's
// texture objects to reuse storage.
void reclaimTexture();
void forceToImage();
#endif
#ifdef Q_OS_SYMBIAN
QImage::Format idealFormat(QImage &image, Qt::ImageConversionFlags flags);
void* toNativeType(NativeType type);
void fromNativeType(void* pixmap, NativeType type);
bool initFromNativeImageHandle(void *handle, const QString &type);
void createFromNativeImageHandleProvider();
void releaseNativeImageHandle();
#endif
private:
bool isValid() const;
void ensureCreated() const;
bool isUninitialized() const { return m_dirty && m_source.isNull(); }
bool needsFill() const { return m_hasFillColor; }
QColor fillColor() const { return m_fillColor; }
QGLPixmapData(const QGLPixmapData &other);
QGLPixmapData &operator=(const QGLPixmapData &other);
void copyBackFromRenderFbo(bool keepCurrentFboBound) const;
QSize size() const { return QSize(w, h); }
bool useFramebufferObjects() const;
QImage fillImage(const QColor &color) const;
void createPixmapForImage(QImage &image, Qt::ImageConversionFlags flags, bool inPlace);
mutable QGLFramebufferObject *m_renderFbo;
mutable QPaintEngine *m_engine;
mutable QGLContext *m_ctx;
#ifdef Q_OS_SYMBIAN
mutable QVolatileImage m_source;
mutable QNativeImageHandleProvider *nativeImageHandleProvider;
void *nativeImageHandle;
QString nativeImageType;
#else
mutable QImage m_source;
#endif
mutable QGLTexture m_texture;
// the texture is not in sync with the source image
mutable bool m_dirty;
// fill has been called and no painting has been done, so the pixmap is
// represented by a single fill color
mutable QColor m_fillColor;
mutable bool m_hasFillColor;
mutable bool m_hasAlpha;
mutable QGLPixmapGLPaintDevice m_glDevice;
#ifdef QGL_USE_TEXTURE_POOL
QGLPixmapData *nextLRU;
QGLPixmapData *prevLRU;
mutable bool inLRU;
mutable bool failedToAlloc;
mutable bool inTexturePool;
QGLPixmapData *next;
QGLPixmapData *prev;
friend class QGLTexturePool;
friend void qt_gl_register_pixmap(QGLPixmapData *pd);
friend void qt_gl_unregister_pixmap(QGLPixmapData *pd);
friend void qt_gl_hibernate_pixmaps();
#endif
friend class QGLPixmapGLPaintDevice;
friend class QMeeGoPixmapData;
friend class QMeeGoLivePixmapData;
};
QT_END_NAMESPACE
#endif // QPIXMAPDATA_GL_P_H

View File

@ -1,934 +0,0 @@
/****************************************************************************
**
** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the QtOpenGL module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** GNU Lesser General Public License Usage
** This file may be used under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation and
** appearing in the file LICENSE.LGPL included in the packaging of this
** file. Please review the following information to ensure the GNU Lesser
** General Public License version 2.1 requirements will be met:
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU General
** Public License version 3.0 as published by the Free Software Foundation
** and appearing in the file LICENSE.GPL included in the packaging of this
** file. Please review the following information to ensure the GNU General
** Public License version 3.0 requirements will be met:
** http://www.gnu.org/copyleft/gpl.html.
**
** Other Usage
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include "qpixmap.h"
#include "qglframebufferobject.h"
#include <private/qpaintengine_raster_p.h>
#include "qpixmapdata_gl_p.h"
#include <private/qgl_p.h>
#include <private/qdrawhelper_p.h>
#include <private/qimage_p.h>
#include <private/qnativeimagehandleprovider_p.h>
#include <private/qfont_p.h>
#include <private/qpaintengineex_opengl2_p.h>
#include <qdesktopwidget.h>
#include <qfile.h>
#include <qimagereader.h>
#include <qbuffer.h>
#include "qgltexturepool_p.h"
QT_BEGIN_NAMESPACE
Q_OPENGL_EXPORT extern QGLWidget* qt_gl_share_widget();
static inline int areaDiff(const QSize &size, const QGLFramebufferObject *fbo)
{
return qAbs(size.width() * size.height() - fbo->width() * fbo->height());
}
extern int qt_next_power_of_two(int v);
static inline QSize maybeRoundToNextPowerOfTwo(const QSize &sz)
{
#ifdef QT_OPENGL_ES_2
QSize rounded(qt_next_power_of_two(sz.width()), qt_next_power_of_two(sz.height()));
if (rounded.width() * rounded.height() < 1.20 * sz.width() * sz.height())
return rounded;
#endif
return sz;
}
QGLFramebufferObject *QGLFramebufferObjectPool::acquire(const QSize &requestSize, const QGLFramebufferObjectFormat &requestFormat, bool strictSize)
{
QGLFramebufferObject *chosen = 0;
QGLFramebufferObject *candidate = 0;
for (int i = 0; !chosen && i < m_fbos.size(); ++i) {
QGLFramebufferObject *fbo = m_fbos.at(i);
if (strictSize) {
if (fbo->size() == requestSize && fbo->format() == requestFormat) {
chosen = fbo;
break;
} else {
continue;
}
}
if (fbo->format() == requestFormat) {
// choose the fbo with a matching format and the closest size
if (!candidate || areaDiff(requestSize, candidate) > areaDiff(requestSize, fbo))
candidate = fbo;
}
if (candidate) {
m_fbos.removeOne(candidate);
const QSize fboSize = candidate->size();
QSize sz = fboSize;
if (sz.width() < requestSize.width())
sz.setWidth(qMax(requestSize.width(), qRound(sz.width() * 1.5)));
if (sz.height() < requestSize.height())
sz.setHeight(qMax(requestSize.height(), qRound(sz.height() * 1.5)));
// wasting too much space?
if (sz.width() * sz.height() > requestSize.width() * requestSize.height() * 4)
sz = requestSize;
if (sz != fboSize) {
delete candidate;
candidate = new QGLFramebufferObject(maybeRoundToNextPowerOfTwo(sz), requestFormat);
}
chosen = candidate;
}
}
if (!chosen) {
if (strictSize)
chosen = new QGLFramebufferObject(requestSize, requestFormat);
else
chosen = new QGLFramebufferObject(maybeRoundToNextPowerOfTwo(requestSize), requestFormat);
}
if (!chosen->isValid()) {
delete chosen;
chosen = 0;
}
return chosen;
}
void QGLFramebufferObjectPool::release(QGLFramebufferObject *fbo)
{
if (fbo)
m_fbos << fbo;
}
QPaintEngine* QGLPixmapGLPaintDevice::paintEngine() const
{
return data->paintEngine();
}
void QGLPixmapGLPaintDevice::beginPaint()
{
if (!data->isValid())
return;
// QGLPaintDevice::beginPaint will store the current binding and replace
// it with m_thisFBO:
m_thisFBO = data->m_renderFbo->handle();
QGLPaintDevice::beginPaint();
Q_ASSERT(data->paintEngine()->type() == QPaintEngine::OpenGL2);
// QPixmap::fill() is deferred until now, where we actually need to do the fill:
if (data->needsFill()) {
const QColor &c = data->fillColor();
float alpha = c.alphaF();
glDisable(GL_SCISSOR_TEST);
glClearColor(c.redF() * alpha, c.greenF() * alpha, c.blueF() * alpha, alpha);
glClear(GL_COLOR_BUFFER_BIT);
}
else if (!data->isUninitialized()) {
// If the pixmap (GL Texture) has valid content (it has been
// uploaded from an image or rendered into before), we need to
// copy it from the texture to the render FBO.
glDisable(GL_DEPTH_TEST);
glDisable(GL_SCISSOR_TEST);
glDisable(GL_BLEND);
#if !defined(QT_OPENGL_ES_2)
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0, data->width(), data->height(), 0, -999999, 999999);
#endif
glViewport(0, 0, data->width(), data->height());
// Pass false to bind so it doesn't copy the FBO into the texture!
context()->drawTexture(QRect(0, 0, data->width(), data->height()), data->bind(false));
}
}
void QGLPixmapGLPaintDevice::endPaint()
{
if (!data->isValid())
return;
data->copyBackFromRenderFbo(false);
// Base's endPaint will restore the previous FBO binding
QGLPaintDevice::endPaint();
qgl_fbo_pool()->release(data->m_renderFbo);
data->m_renderFbo = 0;
}
QGLContext* QGLPixmapGLPaintDevice::context() const
{
data->ensureCreated();
return data->m_ctx;
}
QSize QGLPixmapGLPaintDevice::size() const
{
return data->size();
}
bool QGLPixmapGLPaintDevice::alphaRequested() const
{
return data->m_hasAlpha;
}
void QGLPixmapGLPaintDevice::setPixmapData(QGLPixmapData* d)
{
data = d;
}
int qt_gl_pixmap_serial = 0;
QGLPixmapData::QGLPixmapData(PixelType type)
: QPixmapData(type, OpenGLClass)
, m_renderFbo(0)
, m_engine(0)
, m_ctx(0)
, nativeImageHandleProvider(0)
, nativeImageHandle(0)
, m_dirty(false)
, m_hasFillColor(false)
, m_hasAlpha(false)
, inLRU(false)
, failedToAlloc(false)
, inTexturePool(false)
{
setSerialNumber(++qt_gl_pixmap_serial);
m_glDevice.setPixmapData(this);
qt_gl_register_pixmap(this);
}
QGLPixmapData::~QGLPixmapData()
{
delete m_engine;
destroyTexture();
qt_gl_unregister_pixmap(this);
}
void QGLPixmapData::destroyTexture()
{
if (inTexturePool) {
QGLTexturePool *pool = QGLTexturePool::instance();
if (m_texture.id)
pool->releaseTexture(this, m_texture.id);
} else {
if (m_texture.id) {
QGLWidget *shareWidget = qt_gl_share_widget();
if (shareWidget) {
QGLShareContextScope ctx(shareWidget->context());
glDeleteTextures(1, &m_texture.id);
}
}
}
m_texture.id = 0;
inTexturePool = false;
releaseNativeImageHandle();
}
QPixmapData *QGLPixmapData::createCompatiblePixmapData() const
{
return new QGLPixmapData(pixelType());
}
bool QGLPixmapData::isValid() const
{
return w > 0 && h > 0;
}
bool QGLPixmapData::isValidContext(const QGLContext *ctx) const
{
if (ctx == m_ctx)
return true;
const QGLContext *share_ctx = qt_gl_share_widget()->context();
return ctx == share_ctx || QGLContext::areSharing(ctx, share_ctx);
}
void QGLPixmapData::resize(int width, int height)
{
if (width == w && height == h)
return;
if (width <= 0 || height <= 0) {
width = 0;
height = 0;
}
w = width;
h = height;
is_null = (w <= 0 || h <= 0);
d = pixelType() == QPixmapData::PixmapType ? 32 : 1;
destroyTexture();
m_source = QVolatileImage();
m_dirty = isValid();
setSerialNumber(++qt_gl_pixmap_serial);
}
void QGLPixmapData::ensureCreated() const
{
if (!m_dirty)
return;
m_dirty = false;
if (nativeImageHandleProvider && !nativeImageHandle)
const_cast<QGLPixmapData *>(this)->createFromNativeImageHandleProvider();
QGLShareContextScope ctx(qt_gl_share_widget()->context());
m_ctx = ctx;
const GLenum internal_format = m_hasAlpha ? GL_RGBA : GL_RGB;
#ifdef QT_OPENGL_ES_2
const GLenum external_format = internal_format;
#else
const GLenum external_format = qt_gl_preferredTextureFormat();
#endif
const GLenum target = GL_TEXTURE_2D;
GLenum type = GL_UNSIGNED_BYTE;
// Avoid conversion when pixmap is created from CFbsBitmap of EColor64K.
if (!m_source.isNull() && m_source.format() == QImage::Format_RGB16)
type = GL_UNSIGNED_SHORT_5_6_5;
m_texture.options &= ~QGLContext::MemoryManagedBindOption;
if (!m_texture.id) {
m_texture.id = QGLTexturePool::instance()->createTextureForPixmap(
target,
0, internal_format,
w, h,
external_format,
type,
const_cast<QGLPixmapData*>(this));
if (!m_texture.id) {
failedToAlloc = true;
return;
}
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
inTexturePool = true;
} else if (inTexturePool) {
glBindTexture(target, m_texture.id);
QGLTexturePool::instance()->useTexture(const_cast<QGLPixmapData*>(this));
}
if (!m_source.isNull() && m_texture.id) {
if (external_format == GL_RGB) {
m_source.beginDataAccess();
QImage tx;
if (type == GL_UNSIGNED_BYTE)
tx = m_source.imageRef().convertToFormat(QImage::Format_RGB888).mirrored(false, true);
else if (type == GL_UNSIGNED_SHORT_5_6_5)
tx = m_source.imageRef().mirrored(false, true);
m_source.endDataAccess(true);
glBindTexture(target, m_texture.id);
if (!tx.isNull())
glTexSubImage2D(target, 0, 0, 0, w, h, external_format,
type, tx.constBits());
else
qWarning("QGLPixmapData: Failed to create GL_RGB image of size %dx%d", w, h);
} else {
// do byte swizzling ARGB -> RGBA
m_source.beginDataAccess();
const QImage tx = ctx->d_func()->convertToGLFormat(m_source.imageRef(), true, external_format);
m_source.endDataAccess(true);
glBindTexture(target, m_texture.id);
if (!tx.isNull())
glTexSubImage2D(target, 0, 0, 0, w, h, external_format,
type, tx.constBits());
else
qWarning("QGLPixmapData: Failed to create GL_RGBA image of size %dx%d", w, h);
}
if (useFramebufferObjects())
m_source = QVolatileImage();
}
}
void QGLPixmapData::fromImage(const QImage &image,
Qt::ImageConversionFlags flags)
{
QImage img = image;
createPixmapForImage(img, flags, false);
}
void QGLPixmapData::fromImageReader(QImageReader *imageReader,
Qt::ImageConversionFlags flags)
{
QImage image = imageReader->read();
if (image.isNull())
return;
createPixmapForImage(image, flags, true);
}
bool QGLPixmapData::fromFile(const QString &filename, const char *format,
Qt::ImageConversionFlags flags)
{
if (pixelType() == QPixmapData::BitmapType)
return QPixmapData::fromFile(filename, format, flags);
QFile file(filename);
if (file.open(QIODevice::ReadOnly)) {
QByteArray data = file.peek(64);
bool alpha;
if (m_texture.canBindCompressedTexture
(data.constData(), data.size(), format, &alpha)) {
resize(0, 0);
data = file.readAll();
file.close();
QGLShareContextScope ctx(qt_gl_share_widget()->context());
QSize size = m_texture.bindCompressedTexture
(data.constData(), data.size(), format);
if (!size.isEmpty()) {
w = size.width();
h = size.height();
is_null = false;
d = 32;
m_hasAlpha = alpha;
m_source = QVolatileImage();
m_dirty = isValid();
return true;
}
return false;
}
}
QImage image = QImageReader(filename, format).read();
if (image.isNull())
return false;
createPixmapForImage(image, flags, true);
return !isNull();
}
bool QGLPixmapData::fromData(const uchar *buffer, uint len, const char *format,
Qt::ImageConversionFlags flags)
{
bool alpha;
const char *buf = reinterpret_cast<const char *>(buffer);
if (m_texture.canBindCompressedTexture(buf, int(len), format, &alpha)) {
resize(0, 0);
QGLShareContextScope ctx(qt_gl_share_widget()->context());
QSize size = m_texture.bindCompressedTexture(buf, int(len), format);
if (!size.isEmpty()) {
w = size.width();
h = size.height();
is_null = false;
d = 32;
m_hasAlpha = alpha;
m_source = QVolatileImage();
m_dirty = isValid();
return true;
}
}
QByteArray a = QByteArray::fromRawData(reinterpret_cast<const char *>(buffer), len);
QBuffer b(&a);
b.open(QIODevice::ReadOnly);
QImage image = QImageReader(&b, format).read();
if (image.isNull())
return false;
createPixmapForImage(image, flags, true);
return !isNull();
}
QImage::Format QGLPixmapData::idealFormat(QImage &image, Qt::ImageConversionFlags flags)
{
QImage::Format format = QImage::Format_RGB32;
if (qApp->desktop()->depth() == 16)
format = QImage::Format_RGB16;
if (image.hasAlphaChannel()
&& ((flags & Qt::NoOpaqueDetection)
|| const_cast<QImage &>(image).data_ptr()->checkForAlphaPixels()))
format = QImage::Format_ARGB32_Premultiplied;
return format;
}
void QGLPixmapData::createPixmapForImage(QImage &image, Qt::ImageConversionFlags flags, bool inPlace)
{
if (image.size() == QSize(w, h))
setSerialNumber(++qt_gl_pixmap_serial);
resize(image.width(), image.height());
if (pixelType() == BitmapType) {
QImage convertedImage = image.convertToFormat(QImage::Format_MonoLSB);
if (image.format() == QImage::Format_MonoLSB)
convertedImage.detach();
m_source = QVolatileImage(convertedImage);
} else {
QImage::Format format = idealFormat(image, flags);
if (inPlace && image.data_ptr()->convertInPlace(format, flags)) {
m_source = QVolatileImage(image);
} else {
QImage convertedImage = image.convertToFormat(format);
// convertToFormat won't detach the image if format stays the same.
if (image.format() == format)
convertedImage.detach();
m_source = QVolatileImage(convertedImage);
}
}
m_dirty = true;
m_hasFillColor = false;
m_hasAlpha = m_source.hasAlphaChannel();
w = image.width();
h = image.height();
is_null = (w <= 0 || h <= 0);
d = m_source.depth();
destroyTexture();
}
bool QGLPixmapData::scroll(int dx, int dy, const QRect &rect)
{
Q_UNUSED(dx);
Q_UNUSED(dy);
Q_UNUSED(rect);
return false;
}
void QGLPixmapData::copy(const QPixmapData *data, const QRect &rect)
{
if (data->classId() != QPixmapData::OpenGLClass || !static_cast<const QGLPixmapData *>(data)->useFramebufferObjects()) {
QPixmapData::copy(data, rect);
return;
}
const QGLPixmapData *other = static_cast<const QGLPixmapData *>(data);
if (other->m_renderFbo) {
QGLShareContextScope ctx(qt_gl_share_widget()->context());
resize(rect.width(), rect.height());
m_hasAlpha = other->m_hasAlpha;
ensureCreated();
if (!ctx->d_ptr->fbo)
glGenFramebuffers(1, &ctx->d_ptr->fbo);
glBindFramebuffer(GL_DRAW_FRAMEBUFFER_EXT, ctx->d_ptr->fbo);
glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT,
GL_TEXTURE_2D, m_texture.id, 0);
if (!other->m_renderFbo->isBound())
glBindFramebuffer(GL_READ_FRAMEBUFFER_EXT, other->m_renderFbo->handle());
glDisable(GL_SCISSOR_TEST);
if (ctx->d_ptr->active_engine && ctx->d_ptr->active_engine->type() == QPaintEngine::OpenGL2)
static_cast<QGL2PaintEngineEx *>(ctx->d_ptr->active_engine)->invalidateState();
glBlitFramebufferEXT(rect.x(), rect.y(), rect.x() + rect.width(), rect.y() + rect.height(),
0, 0, w, h,
GL_COLOR_BUFFER_BIT,
GL_NEAREST);
glBindFramebuffer(GL_FRAMEBUFFER_EXT, ctx->d_ptr->current_fbo);
} else {
QPixmapData::copy(data, rect);
}
}
void QGLPixmapData::fill(const QColor &color)
{
if (!isValid())
return;
bool hasAlpha = color.alpha() != 255;
if (hasAlpha && !m_hasAlpha) {
if (m_texture.id) {
destroyTexture();
m_dirty = true;
}
m_hasAlpha = color.alpha() != 255;
}
if (useFramebufferObjects()) {
m_source = QVolatileImage();
m_hasFillColor = true;
m_fillColor = color;
} else {
forceToImage();
if (m_source.depth() == 32) {
m_source.fill(PREMUL(color.rgba()));
} else if (m_source.depth() == 1) {
if (color == Qt::color1)
m_source.fill(1);
else
m_source.fill(0);
}
}
}
bool QGLPixmapData::hasAlphaChannel() const
{
return m_hasAlpha;
}
QImage QGLPixmapData::fillImage(const QColor &color) const
{
QImage img;
if (pixelType() == BitmapType) {
img = QImage(w, h, QImage::Format_MonoLSB);
img.setColorCount(2);
img.setColor(0, QColor(Qt::color0).rgba());
img.setColor(1, QColor(Qt::color1).rgba());
if (color == Qt::color1)
img.fill(1);
else
img.fill(0);
} else {
img = QImage(w, h,
m_hasAlpha
? QImage::Format_ARGB32_Premultiplied
: QImage::Format_RGB32);
img.fill(PREMUL(color.rgba()));
}
return img;
}
extern QImage qt_gl_read_texture(const QSize &size, bool alpha_format, bool include_alpha);
QImage QGLPixmapData::toImage() const
{
if (!isValid())
return QImage();
if (m_renderFbo) {
copyBackFromRenderFbo(true);
} else if (!m_source.isNull()) {
// QVolatileImage::toImage() will make a copy always so no check
// for active painting is needed.
QImage img = m_source.toImage();
if (img.format() == QImage::Format_MonoLSB) {
img.setColorCount(2);
img.setColor(0, QColor(Qt::color0).rgba());
img.setColor(1, QColor(Qt::color1).rgba());
}
return img;
} else if (m_dirty || m_hasFillColor) {
return fillImage(m_fillColor);
} else {
ensureCreated();
}
QGLShareContextScope ctx(qt_gl_share_widget()->context());
glBindTexture(GL_TEXTURE_2D, m_texture.id);
return qt_gl_read_texture(QSize(w, h), true, true);
}
struct TextureBuffer
{
QGLFramebufferObject *fbo;
QGL2PaintEngineEx *engine;
};
Q_GLOBAL_STATIC(QGLFramebufferObjectPool, _qgl_fbo_pool)
QGLFramebufferObjectPool* qgl_fbo_pool()
{
return _qgl_fbo_pool();
}
void QGLPixmapData::copyBackFromRenderFbo(bool keepCurrentFboBound) const
{
if (!isValid())
return;
m_hasFillColor = false;
const QGLContext *share_ctx = qt_gl_share_widget()->context();
QGLShareContextScope ctx(share_ctx);
ensureCreated();
if (!ctx->d_ptr->fbo)
glGenFramebuffers(1, &ctx->d_ptr->fbo);
glBindFramebuffer(GL_DRAW_FRAMEBUFFER_EXT, ctx->d_ptr->fbo);
glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT,
GL_TEXTURE_2D, m_texture.id, 0);
const int x0 = 0;
const int x1 = w;
const int y0 = 0;
const int y1 = h;
if (!m_renderFbo->isBound())
glBindFramebuffer(GL_READ_FRAMEBUFFER_EXT, m_renderFbo->handle());
glDisable(GL_SCISSOR_TEST);
glBlitFramebufferEXT(x0, y0, x1, y1,
x0, y0, x1, y1,
GL_COLOR_BUFFER_BIT,
GL_NEAREST);
if (keepCurrentFboBound) {
glBindFramebuffer(GL_FRAMEBUFFER_EXT, ctx->d_ptr->current_fbo);
} else {
glBindFramebuffer(GL_DRAW_FRAMEBUFFER_EXT, m_renderFbo->handle());
ctx->d_ptr->current_fbo = m_renderFbo->handle();
}
}
bool QGLPixmapData::useFramebufferObjects() const
{
#ifdef Q_OS_SYMBIAN
// We don't want to use FBOs on Symbian
return false;
#else
return QGLFramebufferObject::hasOpenGLFramebufferObjects()
&& QGLFramebufferObject::hasOpenGLFramebufferBlit()
&& qt_gl_preferGL2Engine()
&& (w * h > 32*32); // avoid overhead of FBOs for small pixmaps
#endif
}
QPaintEngine* QGLPixmapData::paintEngine() const
{
if (!isValid())
return 0;
if (m_renderFbo)
return m_engine;
if (useFramebufferObjects()) {
extern QGLWidget* qt_gl_share_widget();
if (!QGLContext::currentContext())
qt_gl_share_widget()->makeCurrent();
QGLShareContextScope ctx(qt_gl_share_widget()->context());
QGLFramebufferObjectFormat format;
format.setAttachment(QGLFramebufferObject::CombinedDepthStencil);
format.setSamples(4);
format.setInternalTextureFormat(GLenum(m_hasAlpha ? GL_RGBA : GL_RGB));
m_renderFbo = qgl_fbo_pool()->acquire(size(), format);
if (m_renderFbo) {
if (!m_engine)
m_engine = new QGL2PaintEngineEx;
return m_engine;
}
qWarning() << "Failed to create pixmap texture buffer of size " << size() << ", falling back to raster paint engine";
}
// If the application wants to paint into the QPixmap, we first
// force it to QImage format and then paint into that.
// This is simpler than juggling multiple GL contexts.
const_cast<QGLPixmapData *>(this)->forceToImage();
if (m_hasFillColor) {
m_source.fill(PREMUL(m_fillColor.rgba()));
m_hasFillColor = false;
}
return m_source.paintEngine();
}
extern QRgb qt_gl_convertToGLFormat(QRgb src_pixel, GLenum texture_format);
// If copyBack is true, bind will copy the contents of the render
// FBO to the texture (which is not bound to the texture, as it's
// a multisample FBO).
GLuint QGLPixmapData::bind(bool copyBack) const
{
if (m_renderFbo && copyBack) {
copyBackFromRenderFbo(true);
} else {
ensureCreated();
}
GLuint id = m_texture.id;
glBindTexture(GL_TEXTURE_2D, id);
if (m_hasFillColor) {
if (!useFramebufferObjects()) {
m_source = QVolatileImage(w, h, QImage::Format_ARGB32_Premultiplied);
m_source.fill(PREMUL(m_fillColor.rgba()));
}
m_hasFillColor = false;
GLenum format = qt_gl_preferredTextureFormat();
QImage tx(w, h, QImage::Format_ARGB32_Premultiplied);
tx.fill(qt_gl_convertToGLFormat(m_fillColor.rgba(), format));
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, w, h, format, GL_UNSIGNED_BYTE, tx.constBits());
}
return id;
}
QGLTexture* QGLPixmapData::texture() const
{
return &m_texture;
}
void QGLPixmapData::detachTextureFromPool()
{
if (inTexturePool) {
QGLTexturePool::instance()->detachTexture(this);
inTexturePool = false;
}
}
void QGLPixmapData::hibernate()
{
// If the image was imported (e.g, from an SgImage under Symbian), then
// skip the hibernation, there is no sense in copying it back to main
// memory because the data is most likely shared between several processes.
bool skipHibernate = (m_texture.id && m_source.isNull());
#if defined(Q_OS_SYMBIAN)
// However we have to proceed normally if the image was retrieved via
// a handle provider.
skipHibernate &= !nativeImageHandleProvider;
#endif
if (skipHibernate)
return;
forceToImage();
destroyTexture();
}
void QGLPixmapData::reclaimTexture()
{
if (!inTexturePool)
return;
forceToImage();
destroyTexture();
}
int QGLPixmapData::metric(QPaintDevice::PaintDeviceMetric metric) const
{
if (w == 0)
return 0;
switch (metric) {
case QPaintDevice::PdmWidth:
return w;
case QPaintDevice::PdmHeight:
return h;
case QPaintDevice::PdmNumColors:
return 0;
case QPaintDevice::PdmDepth:
return d;
case QPaintDevice::PdmWidthMM:
return qRound(w * 25.4 / qt_defaultDpiX());
case QPaintDevice::PdmHeightMM:
return qRound(h * 25.4 / qt_defaultDpiY());
case QPaintDevice::PdmDpiX:
case QPaintDevice::PdmPhysicalDpiX:
return qt_defaultDpiX();
case QPaintDevice::PdmDpiY:
case QPaintDevice::PdmPhysicalDpiY:
return qt_defaultDpiY();
default:
qWarning("QGLPixmapData::metric(): Invalid metric");
return 0;
}
}
// Force the pixmap data to be backed by some valid data.
void QGLPixmapData::forceToImage()
{
if (!isValid())
return;
if (m_source.isNull()) {
QImage::Format format = QImage::Format_ARGB32_Premultiplied;
if (pixelType() == BitmapType)
format = QImage::Format_MonoLSB;
m_source = QVolatileImage(w, h, format);
}
m_dirty = true;
}
QGLPaintDevice *QGLPixmapData::glDevice() const
{
return &m_glDevice;
}
QT_END_NAMESPACE

View File

@ -1,403 +0,0 @@
/****************************************************************************
**
** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the QtOpenGL module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** GNU Lesser General Public License Usage
** This file may be used under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation and
** appearing in the file LICENSE.LGPL included in the packaging of this
** file. Please review the following information to ensure the GNU Lesser
** General Public License version 2.1 requirements will be met:
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU General
** Public License version 3.0 as published by the Free Software Foundation
** and appearing in the file LICENSE.GPL included in the packaging of this
** file. Please review the following information to ensure the GNU General
** Public License version 3.0 requirements will be met:
** http://www.gnu.org/copyleft/gpl.html.
**
** Other Usage
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include <QDebug>
#include <QtGui/private/qt_x11_p.h>
#include <QtGui/private/qegl_p.h>
#include <QtGui/private/qeglproperties_p.h>
#include <QtGui/private/qeglcontext_p.h>
#if !defined(QT_OPENGL_ES_1)
#include <QtOpenGL/private/qpaintengineex_opengl2_p.h>
#endif
#ifndef QT_OPENGL_ES_2
#include <QtOpenGL/private/qpaintengine_opengl_p.h>
#endif
#include <QtOpenGL/private/qgl_p.h>
#include <QtOpenGL/private/qgl_egl_p.h>
#include "qpixmapdata_x11gl_p.h"
QT_BEGIN_NAMESPACE
class QX11GLSharedContexts
{
public:
QX11GLSharedContexts()
: rgbContext(0)
, argbContext(0)
, sharedQGLContext(0)
, sharePixmap(0)
{
EGLint rgbConfigId;
EGLint argbConfigId;
do {
EGLConfig rgbConfig = QEgl::defaultConfig(QInternal::Pixmap, QEgl::OpenGL, QEgl::Renderable);
EGLConfig argbConfig = QEgl::defaultConfig(QInternal::Pixmap, QEgl::OpenGL,
QEgl::Renderable | QEgl::Translucent);
eglGetConfigAttrib(QEgl::display(), rgbConfig, EGL_CONFIG_ID, &rgbConfigId);
eglGetConfigAttrib(QEgl::display(), argbConfig, EGL_CONFIG_ID, &argbConfigId);
rgbContext = new QEglContext;
rgbContext->setConfig(rgbConfig);
rgbContext->createContext();
if (!rgbContext->isValid())
break;
// If the RGB & ARGB configs are the same, use the same egl context for both:
if (rgbConfig == argbConfig)
argbContext = rgbContext;
// Otherwise, create a separate context to be used for ARGB pixmaps:
if (!argbContext) {
argbContext = new QEglContext;
argbContext->setConfig(argbConfig);
bool success = argbContext->createContext(rgbContext);
if (!success) {
qWarning("QX11GLPixmapData - RGB & ARGB contexts aren't shared");
success = argbContext->createContext();
if (!success)
argbContext = rgbContext; // Might work, worth a shot at least.
}
}
if (!argbContext->isValid())
break;
// Create the pixmap which will be used to create the egl surface for the share QGLContext
QX11PixmapData *rgbPixmapData = new QX11PixmapData(QPixmapData::PixmapType);
rgbPixmapData->resize(8, 8);
rgbPixmapData->fill(Qt::red);
sharePixmap = new QPixmap(rgbPixmapData);
EGLSurface sharePixmapSurface = QEgl::createSurface(sharePixmap, rgbConfig);
rgbPixmapData->gl_surface = (void*)sharePixmapSurface;
// Create the actual QGLContext which will be used for sharing
sharedQGLContext = new QGLContext(QX11GLPixmapData::glFormat());
sharedQGLContext->d_func()->eglContext = rgbContext;
sharedQGLContext->d_func()->eglSurface = sharePixmapSurface;
sharedQGLContext->d_func()->valid = true;
qt_glformat_from_eglconfig(sharedQGLContext->d_func()->glFormat, rgbConfig);
valid = rgbContext->makeCurrent(sharePixmapSurface);
// If the ARGB & RGB configs are different, check ARGB works too:
if (argbConfig != rgbConfig) {
QX11PixmapData *argbPixmapData = new QX11PixmapData(QPixmapData::PixmapType);
argbPixmapData->resize(8, 8);
argbPixmapData->fill(Qt::transparent); // Force ARGB
QPixmap argbPixmap(argbPixmapData); // destroys pixmap data when goes out of scope
EGLSurface argbPixmapSurface = QEgl::createSurface(&argbPixmap, argbConfig);
valid = argbContext->makeCurrent(argbPixmapSurface);
argbContext->doneCurrent();
eglDestroySurface(QEgl::display(), argbPixmapSurface);
argbPixmapData->gl_surface = 0;
}
if (!valid) {
qWarning() << "Unable to make pixmap surface current:" << QEgl::errorString();
break;
}
// The pixmap surface destruction hooks are installed by QGLTextureCache, so we
// must make sure this is instanciated:
QGLTextureCache::instance();
} while(0);
if (!valid)
cleanup();
else
qDebug("Using QX11GLPixmapData with EGL config %d for ARGB and config %d for RGB", argbConfigId, rgbConfigId);
}
~QX11GLSharedContexts() {
cleanup();
}
void cleanup() {
if (sharedQGLContext) {
delete sharedQGLContext;
sharedQGLContext = 0;
}
if (argbContext && argbContext != rgbContext)
delete argbContext;
argbContext = 0;
if (rgbContext) {
delete rgbContext;
rgbContext = 0;
}
// Deleting the QPixmap will fire the pixmap destruction cleanup hooks which in turn
// will destroy the egl surface:
if (sharePixmap) {
delete sharePixmap;
sharePixmap = 0;
}
}
bool isValid() { return valid;}
// On 16bpp systems, RGB & ARGB pixmaps are different bit-depths and therefore need
// different contexts:
QEglContext *rgbContext;
QEglContext *argbContext;
// The share context wraps the rgbContext and is used as the master of the context share
// group. As all other contexts will have the same egl context (or a shared one if rgb != argb)
// all QGLContexts will actually be sharing and can be in the same context group.
QGLContext *sharedQGLContext;
private:
QPixmap *sharePixmap;
bool valid;
};
static void qt_cleanup_x11gl_share_contexts();
Q_GLOBAL_STATIC_WITH_INITIALIZER(QX11GLSharedContexts, qt_x11gl_share_contexts,
{
qAddPostRoutine(qt_cleanup_x11gl_share_contexts);
})
static void qt_cleanup_x11gl_share_contexts()
{
qt_x11gl_share_contexts()->cleanup();
}
QX11GLSharedContexts* QX11GLPixmapData::sharedContexts()
{
return qt_x11gl_share_contexts();
}
bool QX11GLPixmapData::hasX11GLPixmaps()
{
static bool checkedForX11GLPixmaps = false;
static bool haveX11GLPixmaps = false;
if (checkedForX11GLPixmaps)
return haveX11GLPixmaps;
haveX11GLPixmaps = qt_x11gl_share_contexts()->isValid();
checkedForX11GLPixmaps = true;
return haveX11GLPixmaps;
}
QX11GLPixmapData::QX11GLPixmapData()
: QX11PixmapData(QPixmapData::PixmapType),
ctx(0)
{
}
QX11GLPixmapData::~QX11GLPixmapData()
{
if (ctx)
delete ctx;
}
void QX11GLPixmapData::fill(const QColor &color)
{
if (ctx) {
ctx->makeCurrent();
glFinish();
eglWaitClient();
}
QX11PixmapData::fill(color);
XSync(X11->display, False);
if (ctx) {
ctx->makeCurrent();
eglWaitNative(EGL_CORE_NATIVE_ENGINE);
}
}
void QX11GLPixmapData::copy(const QPixmapData *data, const QRect &rect)
{
if (ctx) {
ctx->makeCurrent();
glFinish();
eglWaitClient();
}
QX11PixmapData::copy(data, rect);
XSync(X11->display, False);
if (ctx) {
ctx->makeCurrent();
eglWaitNative(EGL_CORE_NATIVE_ENGINE);
}
}
bool QX11GLPixmapData::scroll(int dx, int dy, const QRect &rect)
{
if (ctx) {
ctx->makeCurrent();
glFinish();
eglWaitClient();
}
bool success = QX11PixmapData::scroll(dx, dy, rect);
XSync(X11->display, False);
if (ctx) {
ctx->makeCurrent();
eglWaitNative(EGL_CORE_NATIVE_ENGINE);
}
return success;
}
#if !defined(QT_OPENGL_ES_1)
Q_GLOBAL_STATIC(QGL2PaintEngineEx, qt_gl_pixmap_2_engine)
#endif
#ifndef QT_OPENGL_ES_2
Q_GLOBAL_STATIC(QOpenGLPaintEngine, qt_gl_pixmap_engine)
#endif
QPaintEngine* QX11GLPixmapData::paintEngine() const
{
// We need to create the context before beginPaint - do it here:
if (!ctx) {
ctx = new QGLContext(glFormat());
Q_ASSERT(ctx->d_func()->eglContext == 0);
ctx->d_func()->eglContext = hasAlphaChannel() ? sharedContexts()->argbContext : sharedContexts()->rgbContext;
// While we use a separate QGLContext for each pixmap, the underlying QEglContext is
// the same. So we must use a "fake" QGLContext and fool the texture cache into thinking
// each pixmap's QGLContext is sharing with this central one. The only place this is
// going to fail is where we the underlying EGL RGB and ARGB contexts aren't sharing.
ctx->d_func()->sharing = true;
QGLContextGroup::addShare(ctx, sharedContexts()->sharedQGLContext);
// Update the glFormat for the QGLContext:
qt_glformat_from_eglconfig(ctx->d_func()->glFormat, ctx->d_func()->eglContext->config());
}
QPaintEngine* engine;
#if defined(QT_OPENGL_ES_1)
engine = qt_gl_pixmap_engine();
#elif defined(QT_OPENGL_ES_2)
engine = qt_gl_pixmap_2_engine();
#else
if (qt_gl_preferGL2Engine())
engine = qt_gl_pixmap_2_engine();
else
engine = qt_gl_pixmap_engine();
#endif
// Support multiple painters on multiple pixmaps simultaniously
if (engine->isActive()) {
qWarning("Pixmap paint engine already active");
#if defined(QT_OPENGL_ES_1)
engine = new QOpenGLPaintEngine;
#elif defined(QT_OPENGL_ES_2)
engine = new QGL2PaintEngineEx;
#else
if (qt_gl_preferGL2Engine())
engine = new QGL2PaintEngineEx;
else
engine = new QOpenGLPaintEngine;
#endif
engine->setAutoDestruct(true);
return engine;
}
return engine;
}
void QX11GLPixmapData::beginPaint()
{
// qDebug("QX11GLPixmapData::beginPaint()");
// TODO: Check to see if the surface is renderable
if ((EGLSurface)gl_surface == EGL_NO_SURFACE) {
QPixmap tmpPixmap(this);
EGLConfig cfg = ctx->d_func()->eglContext->config();
Q_ASSERT(cfg != QEGL_NO_CONFIG);
// qDebug("QX11GLPixmapData - using EGL Config ID %d", ctx->d_func()->eglContext->configAttrib(EGL_CONFIG_ID));
EGLSurface surface = QEgl::createSurface(&tmpPixmap, cfg);
if (surface == EGL_NO_SURFACE) {
qWarning() << "Error creating EGL surface for pixmap:" << QEgl::errorString();
return;
}
gl_surface = (void*)surface;
ctx->d_func()->eglSurface = surface;
ctx->d_func()->valid = true;
}
QGLPaintDevice::beginPaint();
}
QGLContext* QX11GLPixmapData::context() const
{
return ctx;
}
QSize QX11GLPixmapData::size() const
{
return QSize(w, h);
}
QGLFormat QX11GLPixmapData::glFormat()
{
return QGLFormat::defaultFormat(); //###
}
QT_END_NAMESPACE

View File

@ -1,98 +0,0 @@
/****************************************************************************
**
** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the QtOpenGL module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** GNU Lesser General Public License Usage
** This file may be used under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation and
** appearing in the file LICENSE.LGPL included in the packaging of this
** file. Please review the following information to ensure the GNU Lesser
** General Public License version 2.1 requirements will be met:
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU General
** Public License version 3.0 as published by the Free Software Foundation
** and appearing in the file LICENSE.GPL included in the packaging of this
** file. Please review the following information to ensure the GNU General
** Public License version 3.0 requirements will be met:
** http://www.gnu.org/copyleft/gpl.html.
**
** Other Usage
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#ifndef QPIXMAPDATA_X11GL_P_H
#define QPIXMAPDATA_X11GL_P_H
//
// W A R N I N G
// -------------
//
// This file is not part of the Qt API. It exists purely as an
// implementation detail. This header file may change from version to
// version without notice, or even be removed.
//
// We mean it.
//
#include <private/qpixmapdata_p.h>
#include <private/qpixmap_x11_p.h>
#include <private/qglpaintdevice_p.h>
#include <qgl.h>
#ifndef QT_NO_EGL
#include <QtGui/private/qeglcontext_p.h>
#endif
QT_BEGIN_NAMESPACE
class QX11GLSharedContexts;
class QX11GLPixmapData : public QX11PixmapData, public QGLPaintDevice
{
public:
QX11GLPixmapData();
virtual ~QX11GLPixmapData();
// Re-implemented from QX11PixmapData:
void fill(const QColor &color);
void copy(const QPixmapData *data, const QRect &rect);
bool scroll(int dx, int dy, const QRect &rect);
// Re-implemented from QGLPaintDevice
QPaintEngine* paintEngine() const; // Also re-implements QX11PixmapData::paintEngine
void beginPaint();
QGLContext* context() const;
QSize size() const;
static bool hasX11GLPixmaps();
static QGLFormat glFormat();
static QX11GLSharedContexts* sharedContexts();
private:
mutable QGLContext* ctx;
};
QT_END_NAMESPACE
#endif // QPIXMAPDATA_X11GL_P_H

File diff suppressed because it is too large Load Diff

View File

@ -1,127 +0,0 @@
/****************************************************************************
**
** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the QtOpenGL module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** GNU Lesser General Public License Usage
** This file may be used under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation and
** appearing in the file LICENSE.LGPL included in the packaging of this
** file. Please review the following information to ensure the GNU Lesser
** General Public License version 2.1 requirements will be met:
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU General
** Public License version 3.0 as published by the Free Software Foundation
** and appearing in the file LICENSE.GPL included in the packaging of this
** file. Please review the following information to ensure the GNU General
** Public License version 3.0 requirements will be met:
** http://www.gnu.org/copyleft/gpl.html.
**
** Other Usage
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#ifndef QWINDOWSURFACE_GL_P_H
#define QWINDOWSURFACE_GL_P_H
//
// W A R N I N G
// -------------
//
// This file is not part of the Qt API. It exists for the convenience
// of the QLibrary class. This header file may change from
// version to version without notice, or even be removed.
//
// We mean it.
//
#include <qglobal.h>
#include <qgl.h>
#include <private/qwindowsurface_p.h>
#include <private/qglpaintdevice_p.h>
QT_BEGIN_NAMESPACE
class QPaintDevice;
class QPoint;
class QRegion;
class QWindow;
struct QGLWindowSurfacePrivate;
Q_OPENGL_EXPORT QGLWidget* qt_gl_share_widget();
Q_OPENGL_EXPORT void qt_destroy_gl_share_widget();
class QGLWindowSurfaceGLPaintDevice : public QGLPaintDevice
{
public:
QPaintEngine* paintEngine() const;
void endPaint();
QSize size() const;
int metric(PaintDeviceMetric m) const;
QGLContext* context() const;
QGLWindowSurfacePrivate* d;
};
class Q_OPENGL_EXPORT QGLWindowSurface : public QObject, public QWindowSurface // , public QPaintDevice
{
Q_OBJECT
public:
QGLWindowSurface(QWindow *window);
~QGLWindowSurface();
QPaintDevice *paintDevice();
void flush(QWindow *window, const QRegion &region, const QPoint &offset);
#if !defined(Q_WS_QPA)
void setGeometry(const QRect &rect);
#else
virtual void resize(const QSize &size);
#endif
void updateGeometry();
bool scroll(const QRegion &area, int dx, int dy);
void beginPaint(const QRegion &region);
void endPaint(const QRegion &region);
WindowSurfaceFeatures features() const;
QGLContext *context() const;
static QGLFormat surfaceFormat;
enum SwapMode { AutomaticSwap, AlwaysFullSwap, AlwaysPartialSwap, KillSwap };
static SwapMode swapBehavior;
private slots:
void deleted(QObject *object);
private:
void hijackWindow(QWindow *window);
bool initializeOffscreenTexture(const QSize &size);
QGLWindowSurfacePrivate *d_ptr;
};
QT_END_NAMESPACE
#endif // QWINDOWSURFACE_GL_P_H

View File

@ -1,213 +0,0 @@
/****************************************************************************
**
** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the QtOpenGL module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** GNU Lesser General Public License Usage
** This file may be used under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation and
** appearing in the file LICENSE.LGPL included in the packaging of this
** file. Please review the following information to ensure the GNU Lesser
** General Public License version 2.1 requirements will be met:
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU General
** Public License version 3.0 as published by the Free Software Foundation
** and appearing in the file LICENSE.GPL included in the packaging of this
** file. Please review the following information to ensure the GNU General
** Public License version 3.0 requirements will be met:
** http://www.gnu.org/copyleft/gpl.html.
**
** Other Usage
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include <QTime>
#include <QDebug>
#include <private/qt_x11_p.h>
#include <private/qimagepixmapcleanuphooks_p.h>
#include "qwindowsurface_x11gl_p.h"
#include "qpixmapdata_x11gl_p.h"
QT_BEGIN_NAMESPACE
QX11GLWindowSurface::QX11GLWindowSurface(QWidget* window)
: QWindowSurface(window), m_windowGC(0), m_pixmapGC(0), m_window(window)
{
}
QX11GLWindowSurface::~QX11GLWindowSurface()
{
if (m_windowGC)
XFree(m_windowGC);
if (m_pixmapGC)
XFree(m_pixmapGC);
}
QPaintDevice *QX11GLWindowSurface::paintDevice()
{
return &m_backBuffer;
}
extern void *qt_getClipRects(const QRegion &r, int &num); // in qpaintengine_x11.cpp
void QX11GLWindowSurface::flush(QWidget *widget, const QRegion &widgetRegion, const QPoint &offset)
{
// We don't need to know the widget which initiated the flush. Instead we just use the offset
// to translate the widgetRegion:
Q_UNUSED(widget);
if (m_backBuffer.isNull()) {
qDebug("QX11GLWindowSurface::flush() - backBuffer is null, not flushing anything");
return;
}
Q_ASSERT(window()->size() != m_backBuffer.size());
// Wait for all GL rendering to the back buffer pixmap to complete before trying to
// copy it to the window. We do this by making sure the pixmap's context is current
// and then call eglWaitClient. The EGL 1.4 spec says eglWaitClient doesn't have to
// block, just that "All rendering calls...are guaranteed to be executed before native
// rendering calls". This makes it potentially less expensive than glFinish.
QGLContext* ctx = static_cast<QX11GLPixmapData*>(m_backBuffer.data_ptr().data())->context();
if (QGLContext::currentContext() != ctx && ctx && ctx->isValid())
ctx->makeCurrent();
eglWaitClient();
if (m_windowGC == 0) {
XGCValues attribs;
attribs.graphics_exposures = False;
m_windowGC = XCreateGC(X11->display, m_window->handle(), GCGraphicsExposures, &attribs);
}
int rectCount;
XRectangle *rects = (XRectangle *)qt_getClipRects(widgetRegion, rectCount);
if (rectCount <= 0)
return;
XSetClipRectangles(X11->display, m_windowGC, 0, 0, rects, rectCount, YXBanded);
QRect dirtyRect = widgetRegion.boundingRect().translated(-offset);
XCopyArea(X11->display, m_backBuffer.handle(), m_window->handle(), m_windowGC,
dirtyRect.x(), dirtyRect.y(), dirtyRect.width(), dirtyRect.height(),
dirtyRect.x(), dirtyRect.y());
// Make sure the blit of the update from the back buffer to the window completes
// before allowing rendering to start again to the back buffer. Otherwise the GPU
// might start rendering to the back buffer again while the blit takes place.
eglWaitNative(EGL_CORE_NATIVE_ENGINE);
}
void QX11GLWindowSurface::setGeometry(const QRect &rect)
{
if (rect.width() > m_backBuffer.size().width() || rect.height() > m_backBuffer.size().height()) {
QX11GLPixmapData *pd = new QX11GLPixmapData;
QSize newSize = rect.size();
pd->resize(newSize.width(), newSize.height());
m_backBuffer = QPixmap(pd);
if (window()->testAttribute(Qt::WA_TranslucentBackground))
m_backBuffer.fill(Qt::transparent);
if (m_pixmapGC) {
XFreeGC(X11->display, m_pixmapGC);
m_pixmapGC = 0;
}
}
QWindowSurface::setGeometry(rect);
}
bool QX11GLWindowSurface::scroll(const QRegion &area, int dx, int dy)
{
if (m_backBuffer.isNull())
return false;
Q_ASSERT(m_backBuffer.data_ptr()->classId() == QPixmapData::X11Class);
// Make sure all GL rendering is complete before starting the scroll operation:
QGLContext* ctx = static_cast<QX11GLPixmapData*>(m_backBuffer.data_ptr().data())->context();
if (QGLContext::currentContext() != ctx && ctx && ctx->isValid())
ctx->makeCurrent();
eglWaitClient();
if (!m_pixmapGC)
m_pixmapGC = XCreateGC(X11->display, m_backBuffer.handle(), 0, 0);
foreach (const QRect& rect, area.rects()) {
XCopyArea(X11->display, m_backBuffer.handle(), m_backBuffer.handle(), m_pixmapGC,
rect.x(), rect.y(), rect.width(), rect.height(),
rect.x()+dx, rect.y()+dy);
}
// Make sure the scroll operation is complete before allowing GL rendering to resume
eglWaitNative(EGL_CORE_NATIVE_ENGINE);
return true;
}
QPixmap QX11GLWindowSurface::grabWidget(const QWidget *widget, const QRect& rect) const
{
if (!widget || m_backBuffer.isNull())
return QPixmap();
QRect srcRect;
// make sure the rect is inside the widget & clip to widget's rect
if (!rect.isEmpty())
srcRect = rect & widget->rect();
else
srcRect = widget->rect();
if (srcRect.isEmpty())
return QPixmap();
// If it's a child widget we have to translate the coordinates
if (widget != window())
srcRect.translate(widget->mapTo(window(), QPoint(0, 0)));
QPixmap::x11SetDefaultScreen(widget->x11Info().screen());
QX11PixmapData *pmd = new QX11PixmapData(QPixmapData::PixmapType);
pmd->resize(srcRect.width(), srcRect.height());
QPixmap px(pmd);
GC tmpGc = XCreateGC(X11->display, m_backBuffer.handle(), 0, 0);
// Make sure all GL rendering is complete before copying the window
QGLContext* ctx = static_cast<QX11GLPixmapData*>(m_backBuffer.pixmapData())->context();
if (QGLContext::currentContext() != ctx && ctx && ctx->isValid())
ctx->makeCurrent();
eglWaitClient();
// Copy srcRect from the backing store to the new pixmap
XSetGraphicsExposures(X11->display, tmpGc, False);
XCopyArea(X11->display, m_backBuffer.handle(), px.handle(), tmpGc,
srcRect.x(), srcRect.y(), srcRect.width(), srcRect.height(), 0, 0);
XFreeGC(X11->display, tmpGc);
// Wait until the copy has finised before allowing more rendering into the back buffer
eglWaitNative(EGL_CORE_NATIVE_ENGINE);
return px;
}
QT_END_NAMESPACE

View File

@ -6,9 +6,9 @@ DESTDIR = $$QT.gui.plugins/platforms
SOURCES = main.cpp \
qminimalintegration.cpp \
qminimalwindowsurface.cpp
qminimalbackingstore.cpp
HEADERS = qminimalintegration.h \
qminimalwindowsurface.h
qminimalbackingstore.h
target.path += $$[QT_INSTALL_PLUGINS]/platforms
INSTALLS += target

View File

@ -40,29 +40,29 @@
****************************************************************************/
#include "qminimalwindowsurface.h"
#include "qminimalbackingstore.h"
#include <QtCore/qdebug.h>
#include <private/qguiapplication_p.h>
QT_BEGIN_NAMESPACE
QMinimalWindowSurface::QMinimalWindowSurface(QWindow *window)
: QWindowSurface(window)
QMinimalBackingStore::QMinimalBackingStore(QWindow *window)
: QPlatformBackingStore(window)
{
//qDebug() << "QMinimalWindowSurface::QMinimalWindowSurface:" << (long)this;
//qDebug() << "QMinimalBackingStore::QMinimalBackingStore:" << (long)this;
}
QMinimalWindowSurface::~QMinimalWindowSurface()
QMinimalBackingStore::~QMinimalBackingStore()
{
}
QPaintDevice *QMinimalWindowSurface::paintDevice()
QPaintDevice *QMinimalBackingStore::paintDevice()
{
//qDebug() << "QMinimalWindowSurface::paintDevice";
//qDebug() << "QMinimalBackingStore::paintDevice";
return &mImage;
}
void QMinimalWindowSurface::flush(QWindow *window, const QRegion &region, const QPoint &offset)
void QMinimalBackingStore::flush(QWindow *window, const QRegion &region, const QPoint &offset)
{
Q_UNUSED(window);
Q_UNUSED(region);
@ -70,14 +70,13 @@ void QMinimalWindowSurface::flush(QWindow *window, const QRegion &region, const
static int c = 0;
QString filename = QString("output%1.png").arg(c++, 4, 10, QLatin1Char('0'));
qDebug() << "QMinimalWindowSurface::flush() saving contents to" << filename.toLocal8Bit().constData();
qDebug() << "QMinimalBackingStore::flush() saving contents to" << filename.toLocal8Bit().constData();
mImage.save(filename);
}
void QMinimalWindowSurface::resize(const QSize &size)
void QMinimalBackingStore::resize(const QSize &size, const QRegion &)
{
//qDebug() << "QMinimalWindowSurface::setGeometry:" << (long)this << rect;
QWindowSurface::resize(size);
//qDebug() << "QMinimalBackingStore::setGeometry:" << (long)this << rect;
QImage::Format format = QGuiApplicationPrivate::platformIntegration()->screens().first()->format();
if (mImage.size() != size)
mImage = QImage(size, format);

View File

@ -39,25 +39,24 @@
**
****************************************************************************/
#ifndef QWINDOWSURFACE_MINIMAL_H
#define QWINDOWSURFACE_MINIMAL_H
#include <QtGui/private/qwindowsurface_p.h>
#ifndef QBACKINGSTORE_MINIMAL_H
#define QBACKINGSTORE_MINIMAL_H
#include <QtGui/QPlatformBackingStore>
#include <QtGui/QPlatformWindow>
#include <QtGui/QImage>
QT_BEGIN_NAMESPACE
class QMinimalWindowSurface : public QWindowSurface
class QMinimalBackingStore : public QPlatformBackingStore
{
public:
QMinimalWindowSurface(QWindow *window);
~QMinimalWindowSurface();
QMinimalBackingStore(QWindow *window);
~QMinimalBackingStore();
QPaintDevice *paintDevice();
void flush(QWindow *window, const QRegion &region, const QPoint &offset);
void resize(const QSize &size);
void resize(const QSize &size, const QRegion &staticContents);
private:
QImage mImage;

View File

@ -40,7 +40,7 @@
****************************************************************************/
#include "qminimalintegration.h"
#include "qminimalwindowsurface.h"
#include "qminimalbackingstore.h"
#include <QtGui/private/qpixmap_raster_p.h>
#include <QtGui/QPlatformWindow>
@ -75,8 +75,7 @@ QPlatformWindow *QMinimalIntegration::createPlatformWindow(QWindow *window) cons
return new QPlatformWindow(window);
}
QWindowSurface *QMinimalIntegration::createWindowSurface(QWindow *window, WId winId) const
QPlatformBackingStore *QMinimalIntegration::createPlatformBackingStore(QWindow *window) const
{
Q_UNUSED(winId);
return new QMinimalWindowSurface(window);
return new QMinimalBackingStore(window);
}

View File

@ -73,7 +73,7 @@ public:
QPixmapData *createPixmapData(QPixmapData::PixelType type) const;
QPlatformWindow *createPlatformWindow(QWindow *window) const;
QWindowSurface *createWindowSurface(QWindow *window, WId winId) const;
QPlatformBackingStore *createPlatformBackingStore(QWindow *window) const;
QList<QPlatformScreen *> screens() const { return mScreens; }

View File

@ -43,8 +43,8 @@
#include "qwaylanddisplay.h"
#include "qwaylandinputdevice.h"
#include "qwaylandshmsurface.h"
#include "qwaylandscreen.h"
#include "qwaylandshmbackingstore.h"
#include <QtGui/QImageReader>

View File

@ -42,7 +42,7 @@
#include "qwaylandintegration.h"
#include "qwaylanddisplay.h"
#include "qwaylandshmsurface.h"
#include "qwaylandshmbackingstore.h"
#include "qwaylandshmwindow.h"
#include "qwaylandnativeinterface.h"
#include "qwaylandclipboard.h"
@ -116,10 +116,9 @@ QPlatformGLContext *QWaylandIntegration::createPlatformGLContext(const QGuiGLFor
#endif
}
QWindowSurface *QWaylandIntegration::createWindowSurface(QWindow *window, WId winId) const
QPlatformBackingStore *QWaylandIntegration::createPlatformBackingStore(QWindow *window) const
{
Q_UNUSED(winId);
return new QWaylandShmWindowSurface(window);
return new QWaylandShmBackingStore(window);
}
QPlatformFontDatabase *QWaylandIntegration::fontDatabase() const

View File

@ -58,7 +58,7 @@ public:
QPixmapData *createPixmapData(QPixmapData::PixelType type) const;
QPlatformWindow *createPlatformWindow(QWindow *window) const;
QPlatformGLContext *createPlatformGLContext(const QGuiGLFormat &glFormat, QPlatformGLContext *share) const;
QWindowSurface *createWindowSurface(QWindow *window, WId winId) const;
QPlatformBackingStore *createPlatformBackingStore(QWindow *window) const;
QList<QPlatformScreen *> screens() const;

View File

@ -38,7 +38,7 @@
** $QT_END_LICENSE$
**
****************************************************************************/
#include "qwaylandshmsurface.h"
#include "qwaylandshmbackingstore.h"
#include <QtCore/qdebug.h>
@ -90,30 +90,30 @@ QWaylandShmBuffer::~QWaylandShmBuffer(void)
wl_buffer_destroy(mBuffer);
}
QWaylandShmWindowSurface::QWaylandShmWindowSurface(QWindow *window)
: QWindowSurface(window)
QWaylandShmBackingStore::QWaylandShmBackingStore(QWindow *window)
: QPlatformBackingStore(window)
, mBuffer(0)
, mDisplay(QWaylandScreen::waylandScreenFromWindow(window)->display())
{
}
QWaylandShmWindowSurface::~QWaylandShmWindowSurface()
QWaylandShmBackingStore::~QWaylandShmBackingStore()
{
}
QPaintDevice *QWaylandShmWindowSurface::paintDevice()
QPaintDevice *QWaylandShmBackingStore::paintDevice()
{
return mBuffer->image();
}
void QWaylandShmWindowSurface::beginPaint(const QRegion &)
void QWaylandShmBackingStore::beginPaint(const QRegion &)
{
QWaylandShmWindow *waylandWindow = static_cast<QWaylandShmWindow *>(window()->handle());
Q_ASSERT(waylandWindow->windowType() == QWaylandWindow::Shm);
waylandWindow->waitForFrameSync();
}
void QWaylandShmWindowSurface::flush(QWindow *window, const QRegion &region, const QPoint &offset)
void QWaylandShmBackingStore::flush(QWindow *window, const QRegion &region, const QPoint &offset)
{
Q_UNUSED(window);
Q_UNUSED(offset);
@ -122,12 +122,11 @@ void QWaylandShmWindowSurface::flush(QWindow *window, const QRegion &region, con
waylandWindow->damage(region);
}
void QWaylandShmWindowSurface::resize(const QSize &size)
void QWaylandShmBackingStore::resize(const QSize &size, const QRegion &)
{
QWaylandShmWindow *waylandWindow = static_cast<QWaylandShmWindow *>(window()->handle());
Q_ASSERT(waylandWindow->windowType() == QWaylandWindow::Shm);
QWindowSurface::resize(size);
QImage::Format format = QPlatformScreen::platformScreenForWindow(window())->format();
if (mBuffer != NULL && mBuffer->size() == size)

View File

@ -39,11 +39,11 @@
**
****************************************************************************/
#ifndef QWINDOWSURFACE_WAYLAND_H
#define QWINDOWSURFACE_WAYLAND_H
#ifndef QWAYLANDSHMBACKINGSTORE_H
#define QWAYLANDSHMBACKINGSTORE_H
#include "qwaylandbuffer.h"
#include <QtGui/private/qwindowsurface_p.h>
#include <QtGui/QPlatformBackingStore>
#include <QtGui/QImage>
#include <QtGui/QPlatformWindow>
@ -62,15 +62,15 @@ private:
QImage mImage;
};
class QWaylandShmWindowSurface : public QWindowSurface
class QWaylandShmBackingStore : public QPlatformBackingStore
{
public:
QWaylandShmWindowSurface(QWindow *window);
~QWaylandShmWindowSurface();
QWaylandShmBackingStore(QWindow *window);
~QWaylandShmBackingStore();
QPaintDevice *paintDevice();
void flush(QWindow *window, const QRegion &region, const QPoint &offset);
void resize(const QSize &size);
void resize(const QSize &size, const QRegion &staticContents);
void beginPaint(const QRegion &);
private:

View File

@ -13,7 +13,7 @@ QT += core-private gui-private opengl-private platformsupport-private
SOURCES = main.cpp \
qwaylandintegration.cpp \
qwaylandnativeinterface.cpp \
qwaylandshmsurface.cpp \
qwaylandshmbackingstore.cpp \
qwaylandinputdevice.cpp \
qwaylandcursor.cpp \
qwaylanddisplay.cpp \
@ -28,7 +28,7 @@ HEADERS = qwaylandintegration.h \
qwaylanddisplay.h \
qwaylandwindow.h \
qwaylandscreen.h \
qwaylandshmsurface.h \
qwaylandshmbackingstore.h \
qwaylandbuffer.h \
qwaylandshmwindow.h \
qwaylandclipboard.h

View File

@ -39,7 +39,7 @@
**
****************************************************************************/
#include "qxcbwindowsurface.h"
#include "qxcbbackingstore.h"
#include "qxcbconnection.h"
#include "qxcbscreen.h"
@ -64,6 +64,7 @@ public:
~QXcbShmImage() { destroy(); }
QImage *image() { return &m_qimage; }
QSize size() const { return m_qimage.size(); }
void put(xcb_window_t window, const QPoint &dst, const QRect &source);
void preparePaint(const QRegion &region);
@ -113,12 +114,12 @@ QXcbShmImage::QXcbShmImage(QXcbScreen *screen, const QSize &size, uint depth, QI
xcb_generic_error_t *error = xcb_request_check(xcb_connection(), xcb_shm_attach_checked(xcb_connection(), m_shm_info.shmseg, m_shm_info.shmid, false));
if (error) {
qWarning() << "QXcbWindowSurface: Unable to attach to shared memory segment";
qWarning() << "QXcbBackingStore: Unable to attach to shared memory segment";
free(error);
}
if (shmctl(m_shm_info.shmid, IPC_RMID, 0) == -1)
qWarning() << "QXcbWindowSurface: Error while marking the shared memory segment to be destroyed";
qWarning() << "QXcbBackingStore: Error while marking the shared memory segment to be destroyed";
m_qimage = QImage( (uchar*) m_xcb_image->data, m_xcb_image->width, m_xcb_image->height, m_xcb_image->stride, format);
}
@ -183,8 +184,8 @@ void QXcbShmImage::preparePaint(const QRegion &region)
}
}
QXcbWindowSurface::QXcbWindowSurface(QWindow *window, bool setDefaultSurface)
: QWindowSurface(window, setDefaultSurface)
QXcbBackingStore::QXcbBackingStore(QWindow *window)
: QPlatformBackingStore(window)
, m_image(0)
, m_syncingResize(false)
{
@ -192,20 +193,21 @@ QXcbWindowSurface::QXcbWindowSurface(QWindow *window, bool setDefaultSurface)
setConnection(screen->connection());
}
QXcbWindowSurface::~QXcbWindowSurface()
QXcbBackingStore::~QXcbBackingStore()
{
delete m_image;
}
QPaintDevice *QXcbWindowSurface::paintDevice()
QPaintDevice *QXcbBackingStore::paintDevice()
{
return m_image->image();
}
void QXcbWindowSurface::beginPaint(const QRegion &region)
void QXcbBackingStore::beginPaint(const QRegion &region)
{
m_image->preparePaint(region);
#if 0
if (m_image->image()->hasAlphaChannel()) {
QPainter p(m_image->image());
p.setCompositionMode(QPainter::CompositionMode_Source);
@ -215,17 +217,18 @@ void QXcbWindowSurface::beginPaint(const QRegion &region)
p.fillRect(*it, blank);
}
}
#endif
}
void QXcbWindowSurface::endPaint(const QRegion &)
void QXcbBackingStore::endPaint(const QRegion &)
{
}
void QXcbWindowSurface::flush(QWindow *window, const QRegion &region, const QPoint &offset)
void QXcbBackingStore::flush(QWindow *window, const QRegion &region, const QPoint &offset)
{
QRect bounds = region.boundingRect();
if (size().isEmpty() || !geometry().contains(bounds))
if (!m_image || m_image->size().isEmpty())
return;
Q_XCB_NOOP(connection());
@ -246,13 +249,12 @@ void QXcbWindowSurface::flush(QWindow *window, const QRegion &region, const QPoi
}
}
void QXcbWindowSurface::resize(const QSize &size)
void QXcbBackingStore::resize(const QSize &size, const QRegion &)
{
if (size == QWindowSurface::size())
if (m_image && size == m_image->size())
return;
Q_XCB_NOOP(connection());
QWindowSurface::resize(size);
QXcbScreen *screen = static_cast<QXcbScreen *>(QPlatformScreen::platformScreenForWindow(window()));
QXcbWindow* win = static_cast<QXcbWindow *>(window()->handle());
@ -266,7 +268,7 @@ void QXcbWindowSurface::resize(const QSize &size)
extern void qt_scrollRectInImage(QImage &img, const QRect &rect, const QPoint &offset);
bool QXcbWindowSurface::scroll(const QRegion &area, int dx, int dy)
bool QXcbBackingStore::scroll(const QRegion &area, int dx, int dy)
{
if (!m_image || m_image->image()->isNull())
return false;

View File

@ -39,10 +39,10 @@
**
****************************************************************************/
#ifndef QXCBWINDOWSURFACE_H
#define QXCBWINDOWSURFACE_H
#ifndef QXCBBACKINGSTORE_H
#define QXCBBACKINGSTORE_H
#include <private/qwindowsurface_p.h>
#include <qplatformbackingstore_qpa.h>
#include <xcb/xcb.h>
@ -50,15 +50,15 @@
class QXcbShmImage;
class QXcbWindowSurface : public QXcbObject, public QWindowSurface
class QXcbBackingStore : public QXcbObject, public QPlatformBackingStore
{
public:
QXcbWindowSurface(QWindow *widget, bool setDefaultSurface = true);
~QXcbWindowSurface();
QXcbBackingStore(QWindow *widget);
~QXcbBackingStore();
QPaintDevice *paintDevice();
void flush(QWindow *window, const QRegion &region, const QPoint &offset);
void resize(const QSize &size);
void resize(const QSize &size, const QRegion &staticContents);
bool scroll(const QRegion &area, int dx, int dy);
void beginPaint(const QRegion &);

View File

@ -43,7 +43,7 @@
#include "qxcbconnection.h"
#include "qxcbscreen.h"
#include "qxcbwindow.h"
#include "qxcbwindowsurface.h"
#include "qxcbbackingstore.h"
#include "qxcbnativeinterface.h"
#include "qxcbclipboard.h"
#include "qxcbdrag.h"
@ -114,10 +114,9 @@ QPlatformGLContext *QXcbIntegration::createPlatformGLContext(const QGuiGLFormat
#endif
}
QWindowSurface *QXcbIntegration::createWindowSurface(QWindow *window, WId winId) const
QPlatformBackingStore *QXcbIntegration::createPlatformBackingStore(QWindow *window) const
{
Q_UNUSED(winId);
return new QXcbWindowSurface(window);
return new QXcbBackingStore(window);
}
QList<QPlatformScreen *> QXcbIntegration::screens() const

View File

@ -59,7 +59,7 @@ public:
QPixmapData *createPixmapData(QPixmapData::PixelType type) const;
QPlatformWindow *createPlatformWindow(QWindow *window) const;
QPlatformGLContext *createPlatformGLContext(const QGuiGLFormat &glFormat, QPlatformGLContext *share) const;
QWindowSurface *createWindowSurface(QWindow *window, WId winId) const;
QPlatformBackingStore *createPlatformBackingStore(QWindow *window) const;
QList<QPlatformScreen *> screens() const;
void moveToScreen(QWindow *window, int screen);

View File

@ -56,8 +56,8 @@
#include <private/qguiapplication_p.h>
#include <private/qwindow_p.h>
#include <private/qwindowsurface_p.h>
#include <QtGui/QPlatformBackingStore>
#include <QtGui/QWindowSystemInterface>
#include <stdio.h>
@ -1053,12 +1053,8 @@ QPlatformGLSurface *QXcbWindow::createGLSurface() const
void QXcbWindow::handleExposeEvent(const xcb_expose_event_t *event)
{
QWindowSurface *surface = window()->surface();
if (surface) {
QRect rect(event->x, event->y, event->width, event->height);
QWindowSystemInterface::handleExposeEvent(window(), rect);
}
QRect rect(event->x, event->y, event->width, event->height);
QWindowSystemInterface::handleExposeEvent(window(), rect);
}
void QXcbWindow::handleClientMessageEvent(const xcb_client_message_event_t *event)

View File

@ -14,7 +14,7 @@ SOURCES = \
qxcbdrag.cpp \
qxcbscreen.cpp \
qxcbwindow.cpp \
qxcbwindowsurface.cpp \
qxcbbackingstore.cpp \
qxcbwmsupport.cpp \
main.cpp \
qxcbnativeinterface.cpp \
@ -31,7 +31,7 @@ HEADERS = \
qxcbobject.h \
qxcbscreen.h \
qxcbwindow.h \
qxcbwindowsurface.h \
qxcbbackingstore.h \
qxcbwmsupport.h \
qxcbnativeinterface.h \
qxcbcursor.h \

View File

@ -11,7 +11,7 @@ HEADERS += \
kernel/qactiongroup.h \
kernel/qapplication.h \
kernel/qapplication_p.h \
kernel/qbackingstore_p.h \
kernel/qwidgetbackingstore_p.h \
kernel/qboxlayout.h \
kernel/qdesktopwidget.h \
kernel/qformlayout.h \
@ -46,7 +46,7 @@ SOURCES += \
kernel/qaction.cpp \
kernel/qactiongroup.cpp \
kernel/qapplication.cpp \
kernel/qbackingstore.cpp \
kernel/qwidgetbackingstore.cpp \
kernel/qboxlayout.cpp \
kernel/qformlayout.cpp \
kernel/qgridlayout.cpp \

View File

@ -503,17 +503,7 @@ bool qt_tabletChokeMouse = false;
inline bool QApplicationPrivate::isAlien(QWidget *widget)
{
if (!widget)
return false;
#if defined(Q_WS_QWS) || defined(Q_WS_QPA)
return !widget->isWindow()
# ifdef Q_BACKINGSTORE_SUBSURFACES
&& !(widget->d_func()->maybeTopData() && widget->d_func()->maybeTopData()->windowSurface)
# endif
;
#else
return !widget->internalWinId();
#endif
return widget && !widget->isWindow();
}
// ######## move to QApplicationPrivate

View File

@ -70,12 +70,6 @@
# include "qtoolbar.h"
# include <private/qmainwindowlayout_p.h>
#endif
#if defined(Q_WS_QWS)
# include "qwsdisplay_qws.h"
# include "qwsmanager_qws.h"
# include "qpaintengine.h" // for PorterDuff
# include "private/qwindowsurface_qws_p.h"
#endif
#if defined(Q_WS_QPA)
#include "qplatformwindow_qpa.h"
#include "private/qwidgetwindow_qpa_p.h"
@ -100,8 +94,8 @@
#endif
#include <private/qgraphicseffect_p.h>
#include <private/qwindowsurface_p.h>
#include <private/qbackingstore_p.h>
#include <qbackingstore.h>
#include <private/qwidgetbackingstore_p.h>
#ifdef Q_WS_MAC
# include <private/qpaintengine_mac_p.h>
#endif
@ -137,9 +131,7 @@
QT_BEGIN_NAMESPACE
#if !defined(Q_WS_QWS)
static bool qt_enable_backingstore = true;
#endif
#ifdef Q_WS_X11
// for compatibility with Qt 4.0
Q_WIDGETS_EXPORT void qt_x11_set_global_double_buffer(bool enable)
@ -352,32 +344,6 @@ QWidgetPrivate::~QWidgetPrivate()
#endif //QT_NO_GRAPHICSEFFECT
}
class QDummyWindowSurface : public QWindowSurface
{
public:
QDummyWindowSurface(QWindow *window) : QWindowSurface(window) {}
QPaintDevice *paintDevice() { return static_cast<QWidgetWindow *>(window())->widget(); }
void flush(QWindow *, const QRegion &, const QPoint &) {}
};
QWindowSurface *QWidgetPrivate::createDefaultWindowSurface()
{
Q_Q(QWidget);
QWindowSurface *surface;
#ifndef QT_NO_PROPERTIES
if (q->property("_q_DummyWindowSurface").toBool()) {
surface = new QDummyWindowSurface(q->windowHandle());
} else
#endif
{
QWindow *win = topData()->window;
surface = QGuiApplicationPrivate::platformIntegration()->createWindowSurface(win, win->winId());
}
return surface;
}
/*!
\internal
*/
@ -393,10 +359,8 @@ void QWidgetPrivate::scrollChildren(int dx, int dy)
QPoint oldp = w->pos();
QRect r(w->pos() + pd, w->size());
w->data->crect = r;
#ifndef Q_WS_QWS
if (w->testAttribute(Qt::WA_WState_Created))
w->d_func()->setWSGeometry();
#endif
w->d_func()->setDirtyOpaqueRegion();
QMoveEvent e(r.topLeft(), oldp);
QApplication::sendEvent(w, &e);
@ -1508,9 +1472,9 @@ void QWidget::create(WId window, bool initializeWindow, bool destroyOldWindow)
// a real toplevel window needs a backing store
if (isWindow() && windowType() != Qt::Desktop) {
d->topData()->backingStore.destroy();
d->topData()->backingStoreTracker.destroy();
if (hasBackingStoreSupport())
d->topData()->backingStore.create(this);
d->topData()->backingStoreTracker.create(this);
}
d->setModal_sys();
@ -1625,7 +1589,7 @@ QWidget::~QWidget()
else if (!internalWinId() && isVisible()) {
qApp->d_func()->sendSyntheticEnterLeave(this);
}
#elif defined(Q_WS_QWS) || defined(Q_WS_QPA)
#elif defined(Q_WS_QPA)
else if (isVisible()) {
qApp->d_func()->sendSyntheticEnterLeave(this);
}
@ -1732,7 +1696,7 @@ void QWidgetPrivate::createTLExtra()
QTLWExtra* x = extra->topextra = new QTLWExtra;
x->icon = 0;
x->iconPixmap = 0;
x->windowSurface = 0;
x->backingStore = 0;
x->sharedPainter = 0;
x->incw = x->inch = 0;
x->basew = x->baseh = 0;
@ -1815,13 +1779,10 @@ void QWidgetPrivate::deleteExtra()
#endif
if (extra->topextra) {
deleteTLSysExtra();
extra->topextra->backingStore.destroy();
extra->topextra->backingStoreTracker.destroy();
delete extra->topextra->icon;
delete extra->topextra->iconPixmap;
#if defined(Q_WS_QWS) && !defined(QT_NO_QWS_MANAGER)
delete extra->topextra->qwsManager;
#endif
delete extra->topextra->windowSurface;
delete extra->topextra->backingStore;
delete extra->topextra;
}
delete extra;
@ -2212,9 +2173,7 @@ void QWidgetPrivate::clipToEffectiveMask(QRegion &region) const
bool QWidgetPrivate::paintOnScreen() const
{
#if defined(Q_WS_QWS)
return false;
#elif defined(QT_NO_BACKINGSTORE)
#if defined(QT_NO_BACKINGSTORE)
return true;
#else
Q_Q(const QWidget);
@ -2376,10 +2335,6 @@ void QWidgetPrivate::paintBackground(QPainter *painter, const QRegion &rgn, int
if ((flags & DrawAsRoot) && !(q->autoFillBackground() && autoFillBrush.isOpaque())) {
const QBrush bg = q->palette().brush(QPalette::Window);
#ifdef Q_WS_QWS
if (!(flags & DontSetCompositionMode) && painter->paintEngine()->hasFeature(QPaintEngine::PorterDuff))
painter->setCompositionMode(QPainter::CompositionMode_Source); //copy alpha straight in
#endif
fillRegion(painter, rgn, bg);
}
@ -3891,19 +3846,6 @@ bool QWidgetPrivate::setMinimumSize_helper(int &minw, int &minh)
{
Q_Q(QWidget);
#ifdef Q_WS_QWS
if (q->isWindow()) {
const QRect maxWindowRect = QApplication::desktop()->availableGeometry(QApplication::desktop()->screenNumber(q));
if (!maxWindowRect.isEmpty()) {
// ### This is really just a work-around. Layout shouldn't be
// asking for minimum sizes bigger than the screen.
if (minw > maxWindowRect.width())
minw = maxWindowRect.width();
if (minh > maxWindowRect.height())
minh = maxWindowRect.height();
}
}
#endif
int mw = minw, mh = minh;
if (mw == QWIDGETSIZE_MAX)
mw = 0;
@ -4094,15 +4036,7 @@ void QWidget::setFixedSize(const QSize & s)
void QWidget::setFixedSize(int w, int h)
{
Q_D(QWidget);
#ifdef Q_WS_QWS
// temporary fix for 4.3.x.
// Should move the embedded spesific contraints in setMinimumSize_helper into QLayout
int tmpW = w;
int tmpH = h;
bool minSizeSet = d->setMinimumSize_helper(tmpW, tmpH);
#else
bool minSizeSet = d->setMinimumSize_helper(w, h);
#endif
bool maxSizeSet = d->setMaximumSize_helper(w, h);
if (!minSizeSet && !maxSizeSet)
return;
@ -5050,7 +4984,7 @@ void QWidget::setCursor(const QCursor &cursor)
{
Q_D(QWidget);
// On Mac we must set the cursor even if it is the ArrowCursor.
#if !defined(Q_WS_MAC) && !defined(Q_WS_QWS)
#if !defined(Q_WS_MAC)
if (cursor.shape() != Qt::ArrowCursor
|| (d->extra && d->extra->curs))
#endif
@ -5538,7 +5472,7 @@ void QWidgetPrivate::drawWidget(QPaintDevice *pdev, const QRegion &rgn, const QP
//actually send the paint event
QPaintEvent e(toBePainted);
QCoreApplication::sendSpontaneousEvent(q, &e);
#if !defined(Q_WS_QWS) && !defined(Q_WS_QPA)
#if !defined(Q_WS_QPA)
if (backingStore && !onScreen && !asRoot && (q->internalWinId() || !q->nativeParentWidget()->isWindow()))
backingStore->markDirtyOnScreen(toBePainted, q, offset);
#endif
@ -5587,9 +5521,6 @@ void QWidgetPrivate::drawWidget(QPaintDevice *pdev, const QRegion &rgn, const QP
if (recursive && !children.isEmpty()) {
paintSiblingsRecursive(pdev, children, children.size() - 1, rgn, offset, flags & ~DrawAsRoot
#ifdef Q_BACKINGSTORE_SUBSURFACES
, q->windowSurface()
#endif
, sharedPainter, backingStore);
}
}
@ -5661,10 +5592,6 @@ void QWidgetPrivate::render(QPaintDevice *target, const QPoint &targetOffset,
else
flags |= DontSubtractOpaqueChildren;
#ifdef Q_WS_QWS
flags |= DontSetCompositionMode;
#endif
if (target->devType() == QInternal::Printer) {
QPainter p(target);
render_helper(&p, targetOffset, paintRegion, renderFlags);
@ -5686,9 +5613,6 @@ void QWidgetPrivate::render(QPaintDevice *target, const QPoint &targetOffset,
void QWidgetPrivate::paintSiblingsRecursive(QPaintDevice *pdev, const QObjectList& siblings, int index, const QRegion &rgn,
const QPoint &offset, int flags
#ifdef Q_BACKINGSTORE_SUBSURFACES
, const QWindowSurface *currentSurface
#endif
, QPainter *sharedPainter, QWidgetBackingStore *backingStore)
{
QWidget *w = 0;
@ -5707,13 +5631,8 @@ void QWidgetPrivate::paintSiblingsRecursive(QPaintDevice *pdev, const QObjectLis
}
if (qRectIntersects(boundingRect, x->d_func()->effectiveRectFor(x->data->crect))) {
#ifdef Q_BACKINGSTORE_SUBSURFACES
if (x->windowSurface() == currentSurface)
#endif
{
w = x;
break;
}
w = x;
break;
}
}
--index;
@ -5730,9 +5649,6 @@ void QWidgetPrivate::paintSiblingsRecursive(QPaintDevice *pdev, const QObjectLis
if (wd->isOpaque)
wr -= hasMask ? wd->extra->mask.translated(widgetPos) : w->data->crect;
paintSiblingsRecursive(pdev, siblings, --index, wr, offset, flags
#ifdef Q_BACKINGSTORE_SUBSURFACES
, currentSurface
#endif
, sharedPainter, backingStore);
}
@ -7582,7 +7498,7 @@ void QWidgetPrivate::hide_helper()
// next bit tries to move the focus if the focus widget is now
// hidden.
if (wasVisible) {
#if defined(Q_WS_WIN) || defined(Q_WS_X11) || defined (Q_WS_QWS) || defined(Q_WS_MAC) || defined(Q_WS_QPA)
#if defined(Q_WS_WIN) || defined(Q_WS_X11) || defined(Q_WS_MAC) || defined(Q_WS_QPA)
qApp->d_func()->sendSyntheticEnterLeave(q);
#endif
@ -7653,9 +7569,6 @@ void QWidget::setVisible(bool visible)
#if defined(Q_WS_X11)
if (windowType() == Qt::Window)
QApplicationPrivate::applyX11SpecificCommandLineArguments(this);
#elif defined(Q_WS_QWS)
if (windowType() == Qt::Window)
QApplicationPrivate::applyQWSSpecificCommandLineArguments(this);
#endif
bool wasResized = testAttribute(Qt::WA_Resized);
@ -7714,7 +7627,7 @@ void QWidget::setVisible(bool visible)
d->show_helper();
#if defined(Q_WS_WIN) || defined(Q_WS_X11) || defined (Q_WS_QWS) || defined(Q_WS_MAC) || defined(Q_WS_QPA)
#if defined(Q_WS_WIN) || defined(Q_WS_X11) || defined(Q_WS_MAC) || defined(Q_WS_QPA)
qApp->d_func()->sendSyntheticEnterLeave(this);
#endif
}
@ -7846,7 +7759,7 @@ void QWidgetPrivate::hideChildren(bool spontaneous)
widget->d_func()->hide_sys();
}
}
#if defined(Q_WS_WIN) || defined(Q_WS_X11) || defined (Q_WS_QWS) || defined(Q_WS_MAC) || defined(Q_WS_QPA)
#if defined(Q_WS_WIN) || defined(Q_WS_X11) || defined(Q_WS_MAC) || defined(Q_WS_QPA)
qApp->d_func()->sendSyntheticEnterLeave(widget);
#endif
#ifndef QT_NO_ACCESSIBILITY
@ -8049,13 +7962,6 @@ QRegion QWidget::visibleRegion() const
QRegion r(clipRect);
d->subtractOpaqueChildren(r, clipRect);
d->subtractOpaqueSiblings(r);
#ifdef Q_WS_QWS
const QWSWindowSurface *surface = static_cast<const QWSWindowSurface*>(windowSurface());
if (surface) {
const QPoint offset = mapTo(surface->window(), QPoint());
r &= surface->clipRegion().translated(-offset);
}
#endif
return r;
}
@ -8807,10 +8713,6 @@ void QWidget::changeEvent(QEvent * event)
updateGeometry();
if (d->layout)
d->layout->invalidate();
#ifdef Q_WS_QWS
if (isWindow())
d->data.fstrut_dirty = true;
#endif
break;
}
@ -9588,31 +9490,6 @@ bool QWidget::x11Event(XEvent *)
}
#endif
#if defined(Q_WS_QWS)
/*!
\fn bool QWidget::qwsEvent(QWSEvent *event)
This special event handler can be reimplemented in a subclass to
receive native Qt for Embedded Linux events which are passed in the
\a event parameter.
In your reimplementation of this function, if you want to stop the
event being handled by Qt, return true. If you return false, this
native event is passed back to Qt, which translates the event into
a Qt event and sends it to the widget.
\warning This function is not portable.
\sa QApplication::qwsEventFilter()
*/
bool QWidget::qwsEvent(QWSEvent *)
{
return false;
}
#endif
/*!
Ensures that the widget has been polished by QStyle (i.e., has a
@ -10132,34 +10009,18 @@ void QWidget::setParent(QWidget *parent, Qt::WindowFlags f)
focusWidget()->clearFocus();
QTLWExtra *oldTopExtra = window()->d_func()->maybeTopData();
QWidgetBackingStoreTracker *oldBsTracker = oldTopExtra ? &oldTopExtra->backingStore : 0;
QWidgetBackingStoreTracker *oldBsTracker = oldTopExtra ? &oldTopExtra->backingStoreTracker : 0;
d->setParent_sys(parent, f);
QTLWExtra *topExtra = window()->d_func()->maybeTopData();
QWidgetBackingStoreTracker *bsTracker = topExtra ? &topExtra->backingStore : 0;
QWidgetBackingStoreTracker *bsTracker = topExtra ? &topExtra->backingStoreTracker : 0;
if (oldBsTracker && oldBsTracker != bsTracker)
oldBsTracker->unregisterWidgetSubtree(this);
if (desktopWidget)
parent = 0;
#ifdef Q_BACKINGSTORE_SUBSURFACES
QTLWExtra *extra = d->maybeTopData();
QWindowSurface *windowSurface = (extra ? extra->windowSurface : 0);
if (newParent && windowSurface) {
QWidgetBackingStore *oldBs = oldtlw->d_func()->maybeBackingStore();
if (oldBs)
oldBs->subSurfaces.removeAll(windowSurface);
if (parent) {
QWidgetBackingStore *newBs = parent->d_func()->maybeBackingStore();
if (newBs)
newBs->subSurfaces.append(windowSurface);
}
}
#endif
if (QWidgetBackingStore *oldBs = oldtlw->d_func()->maybeBackingStore()) {
if (newParent)
oldBs->removeDirtyWidget(this);
@ -10405,7 +10266,7 @@ void QWidget::repaint(const QRect &rect)
QTLWExtra *tlwExtra = window()->d_func()->maybeTopData();
if (tlwExtra && !tlwExtra->inTopLevelResize && tlwExtra->backingStore) {
tlwExtra->inRepaint = true;
tlwExtra->backingStore->markDirty(rect, this, true);
tlwExtra->backingStoreTracker->markDirty(rect, this, true);
tlwExtra->inRepaint = false;
}
} else {
@ -10440,7 +10301,7 @@ void QWidget::repaint(const QRegion &rgn)
QTLWExtra *tlwExtra = window()->d_func()->maybeTopData();
if (tlwExtra && !tlwExtra->inTopLevelResize && tlwExtra->backingStore) {
tlwExtra->inRepaint = true;
tlwExtra->backingStore->markDirty(rgn, this, true);
tlwExtra->backingStoreTracker->markDirty(rgn, this, true);
tlwExtra->inRepaint = false;
}
} else {
@ -10502,7 +10363,7 @@ void QWidget::update(const QRect &rect)
#endif // QT_MAC_USE_COCOA
QTLWExtra *tlwExtra = window()->d_func()->maybeTopData();
if (tlwExtra && !tlwExtra->inTopLevelResize && tlwExtra->backingStore)
tlwExtra->backingStore->markDirty(rect, this);
tlwExtra->backingStoreTracker->markDirty(rect, this);
} else {
d_func()->repaint_sys(rect);
}
@ -10532,7 +10393,7 @@ void QWidget::update(const QRegion &rgn)
#endif // QT_MAC_USE_COCOA
QTLWExtra *tlwExtra = window()->d_func()->maybeTopData();
if (tlwExtra && !tlwExtra->inTopLevelResize && tlwExtra->backingStore)
tlwExtra->backingStore->markDirty(rgn, this);
tlwExtra->backingStoreTracker->markDirty(rgn, this);
} else {
d_func()->repaint_sys(rgn);
}
@ -10873,14 +10734,6 @@ void QWidget::setAttribute(Qt::WidgetAttribute attribute, bool on)
// from the desktop. show_sys will only update platform specific
// attributes at this point.
d->hide_sys();
#ifdef Q_WS_QWS
// Release the region for this window from qws if the widget has
// been shown before the attribute was set.
if (QWSWindowSurface *surface = static_cast<QWSWindowSurface *>(windowSurface())) {
QWidget::qwsDisplay()->requestRegion(surface->winId(), surface->key(),
surface->permanentState(), QRegion());
}
#endif
d->show_sys();
}
break;
@ -11029,10 +10882,8 @@ void QWidget::setWindowOpacity(qreal opacity)
extra->opacity = uint(opacity * 255);
setAttribute(Qt::WA_WState_WindowOpacitySet);
#ifndef Q_WS_QWS
if (!testAttribute(Qt::WA_WState_Created))
return;
#endif
#ifndef QT_NO_GRAPHICSVIEW
if (QGraphicsProxyWidget *proxy = graphicsProxyWidget()) {
@ -11322,7 +11173,7 @@ void QWidget::setShortcutAutoRepeat(int id, bool enable)
*/
void QWidget::updateMicroFocus()
{
#if !defined(QT_NO_IM) && (defined(Q_WS_X11) || defined(Q_WS_QWS) || defined(Q_OS_SYMBIAN))
#if !defined(QT_NO_IM) && (defined(Q_WS_X11) || defined(Q_OS_SYMBIAN))
Q_D(QWidget);
// and optimization to update input context only it has already been created.
if (d->assignedInputContext() || qApp->d_func()->inputContext) {
@ -12102,83 +11953,55 @@ bool QWidgetPrivate::inTabWidget(QWidget *widget)
#endif
/*!
\preliminary
\since 4.2
\obsolete
\since 5.0
\internal
Sets the window surface to be the \a surface specified.
The QWidget takes will ownership of the \a surface.
widget itself is deleted.
Sets the backing store to be the \a store specified.
The QWidget will take ownership of the \a store.
*/
void QWidget::setWindowSurface(QWindowSurface *surface)
void QWidget::setBackingStore(QBackingStore *store)
{
// ### createWinId() ??
#ifndef Q_BACKINGSTORE_SUBSURFACES
if (!isTopLevel())
return;
#endif
Q_D(QWidget);
QTLWExtra *topData = d->topData();
if (topData->windowSurface == surface)
if (topData->backingStore == store)
return;
QWindowSurface *oldSurface = topData->windowSurface;
delete topData->windowSurface;
topData->windowSurface = surface;
QBackingStore *oldStore = topData->backingStore;
delete topData->backingStore;
topData->backingStore = store;
QWidgetBackingStore *bs = d->maybeBackingStore();
if (!bs)
return;
if (isTopLevel()) {
if (bs->windowSurface != oldSurface && bs->windowSurface != surface)
delete bs->windowSurface;
bs->windowSurface = surface;
if (bs->store != oldStore && bs->store != store)
delete bs->store;
bs->store = store;
}
#ifdef Q_BACKINGSTORE_SUBSURFACES
else {
bs->subSurfaces.append(surface);
}
bs->subSurfaces.removeOne(oldSurface);
#endif
}
/*!
\preliminary
\since 4.2
\since 5.0
Returns the QWindowSurface this widget will be drawn into.
Returns the QBackingStore this widget will be drawn into.
*/
QWindowSurface *QWidget::windowSurface() const
QBackingStore *QWidget::backingStore() const
{
Q_D(const QWidget);
QTLWExtra *extra = d->maybeTopData();
if (extra && extra->windowSurface)
return extra->windowSurface;
if (extra && extra->backingStore)
return extra->backingStore;
QWidgetBackingStore *bs = d->maybeBackingStore();
#ifdef Q_BACKINGSTORE_SUBSURFACES
if (bs && bs->subSurfaces.isEmpty())
return bs->windowSurface;
if (!isTopLevel()) {
const QWidget *w = parentWidget();
while (w) {
QTLWExtra *extra = w->d_func()->maybeTopData();
if (extra && extra->windowSurface)
return extra->windowSurface;
if (w->isTopLevel())
break;
w = w->parentWidget();
}
}
#endif // Q_BACKINGSTORE_SUBSURFACES
return bs ? bs->windowSurface : 0;
return bs ? bs->store : 0;
}
void QWidgetPrivate::getLayoutItemMargins(int *left, int *top, int *right, int *bottom) const

View File

@ -97,7 +97,7 @@ class QShowEvent;
class QHideEvent;
class QInputContext;
class QIcon;
class QWindowSurface;
class QBackingStore;
class QPlatformWindow;
class QLocale;
class QGraphicsProxyWidget;
@ -631,8 +631,7 @@ public:
bool autoFillBackground() const;
void setAutoFillBackground(bool enabled);
void setWindowSurface(QWindowSurface *surface);
QWindowSurface *windowSurface() const;
QBackingStore *backingStore() const;
#if defined(Q_WS_QPA)
void setWindowHandle(QWindow *window);
@ -730,6 +729,7 @@ protected:
protected:
QWidget(QWidgetPrivate &d, QWidget* parent, Qt::WindowFlags f);
private:
void setBackingStore(QBackingStore *store);
bool testAttribute_helper(Qt::WidgetAttribute) const;

View File

@ -163,8 +163,8 @@ struct QTLWExtra {
// Regular pointers (keep them together to avoid gaps on 64 bits architectures).
QIcon *icon; // widget icon
QPixmap *iconPixmap;
QWidgetBackingStoreTracker backingStore;
QWindowSurface *windowSurface;
QWidgetBackingStoreTracker backingStoreTracker;
QBackingStore *backingStore;
QPainter *sharedPainter;
// Implicit pointers (shared_null).
@ -458,11 +458,8 @@ public:
void paintSiblingsRecursive(QPaintDevice *pdev, const QObjectList& children, int index,
const QRegion &rgn, const QPoint &offset, int flags
#ifdef Q_BACKINGSTORE_SUBSURFACES
, const QWindowSurface *currentSurface
#endif
, QPainter *sharedPainter, QWidgetBackingStore *backingStore);
const QRegion &rgn, const QPoint &offset, int flags,
QPainter *sharedPainter, QWidgetBackingStore *backingStore);
QPainter *beginSharedPainter();
@ -470,8 +467,6 @@ public:
#ifndef QT_NO_GRAPHICSVIEW
static QGraphicsProxyWidget * nearestGraphicsProxyWidget(const QWidget *origin);
#endif
QWindowSurface *createDefaultWindowSurface();
QWindowSurface *createDefaultWindowSurface_sys();
void repaint_sys(const QRegion &rgn);
QRect clipRect() const;
@ -884,20 +879,6 @@ public:
static OSStatus qt_widget_event(EventHandlerCallRef er, EventRef event, void *);
static bool qt_widget_rgn(QWidget *, short, RgnHandle, bool);
void registerTouchWindow(bool enable = true);
#elif defined(Q_WS_QWS) // <--------------------------------------------------------- QWS
void setMaxWindowState_helper();
void setFullScreenSize_helper();
void moveSurface(QWindowSurface *surface, const QPoint &offset);
QRegion localRequestedRegion() const;
QRegion localAllocatedRegion() const;
friend class QWSManager;
friend class QWSManagerPrivate;
friend class QDecoration;
#ifndef QT_NO_CURSOR
void updateCursor() const;
#endif
QScreen* getScreen() const;
#elif defined(Q_WS_QPA) // <--------------------------------------------------------- QPA
void setMaxWindowState_helper();
void setFullScreenSize_helper();
@ -1026,7 +1007,7 @@ inline QWidgetBackingStore *QWidgetPrivate::maybeBackingStore() const
{
Q_Q(const QWidget);
QTLWExtra *x = q->window()->d_func()->maybeTopData();
return x ? x->backingStore.data() : 0;
return x ? x->backingStoreTracker.data() : 0;
}
QT_END_NAMESPACE

View File

@ -42,7 +42,7 @@
#include "QtWidgets/qwidget.h"
#include "QtGui/qevent.h"
#include "QtWidgets/qapplication.h"
#include "private/qbackingstore_p.h"
#include "private/qwidgetbackingstore_p.h"
#include "private/qwidget_p.h"
#include "private/qwidgetwindow_qpa_p.h"
#include "private/qapplication_p.h"
@ -94,8 +94,6 @@ void QWidgetPrivate::create_sys(WId window, bool initializeWindow, bool destroyO
if (!q->testAttribute(Qt::WA_NativeWindow) && !q->isWindow())
return; // we only care about real toplevels
QWindowSurface *surface = q->windowSurface();
QWindow *win = topData()->window;
// topData() ensures the extra is created but does not ensure 'window' is non-null
// in case the extra was already valid.
@ -129,13 +127,13 @@ void QWidgetPrivate::create_sys(WId window, bool initializeWindow, bool destroyO
data.window_flags = win->windowFlags();
if (!surface ) {
if (win) {
surface = QGuiApplicationPrivate::platformIntegration()->createWindowSurface(win, win->winId());
q->setWindowSurface(surface);
} else {
q->setAttribute(Qt::WA_PaintOnScreen,true);
}
QBackingStore *store = q->backingStore();
if (!store) {
if (win)
q->setBackingStore(new QBackingStore(win));
else
q->setAttribute(Qt::WA_PaintOnScreen, true);
}
setWinId(win->winId());
@ -449,12 +447,15 @@ void QWidgetPrivate::show_sys()
if (windowRect != geomRect) {
window->setGeometry(geomRect);
}
if (QWindowSurface *surface = q->windowSurface()) {
if (windowRect.size() != geomRect.size()) {
surface->resize(geomRect.size());
if (QBackingStore *store = q->backingStore()) {
if (store->size() != geomRect.size()) {
store->resize(geomRect.size());
}
}
invalidateBuffer(q->rect());
if (window)
window->setVisible(true);
}
@ -663,9 +664,9 @@ void QWidgetPrivate::setGeometry_sys(int x, int y, int w, int h, bool isMove)
q->windowHandle()->setGeometry(QRect(posInNativeParent,r.size()));
}
const QWidgetBackingStore *bs = maybeBackingStore();
if (bs->windowSurface) {
if (bs->store) {
if (isResize)
bs->windowSurface->resize(r.size());
bs->store->resize(r.size());
}
if (needsShow)
@ -854,13 +855,6 @@ QPaintEngine *QWidget::paintEngine() const
return 0; //##### @@@
}
QWindowSurface *QWidgetPrivate::createDefaultWindowSurface_sys()
{
//This function should not be called.
Q_ASSERT(false);
return 0;
}
void QWidgetPrivate::setModal_sys()
{
Q_Q(QWidget);

View File

@ -42,7 +42,7 @@
#include "qplatformdefs.h"
#include "qbackingstore_p.h"
#include "qwidgetbackingstore_p.h"
#include <QtCore/qglobal.h>
#include <QtCore/qdebug.h>
@ -76,20 +76,19 @@ static inline bool qRectIntersects(const QRect &r1, const QRect &r2)
}
/**
* Flushes the contents of the \a windowSurface into the screen area of \a widget.
* Flushes the contents of the \a backingStore into the screen area of \a widget.
* \a tlwOffset is the position of the top level widget relative to the window surface.
* \a region is the region to be updated in \a widget coordinates.
*/
static inline void qt_flush(QWidget *widget, const QRegion &region, QWindowSurface *windowSurface,
static inline void qt_flush(QWidget *widget, const QRegion &region, QBackingStore *backingStore,
QWidget *tlw, const QPoint &tlwOffset)
{
Q_ASSERT(widget);
Q_ASSERT(!region.isEmpty());
Q_ASSERT(windowSurface);
Q_ASSERT(backingStore);
Q_ASSERT(tlw);
#if !defined(QT_NO_PAINT_DEBUG) && !defined(Q_WS_QWS)
// QWS does flush update in QWindowSurface::flush (because it needs to lock the surface etc).
#if !defined(QT_NO_PAINT_DEBUG)
static int flushUpdate = qgetenv("QT_FLUSH_UPDATE").toInt();
if (flushUpdate > 0)
QWidgetBackingStore::showYellowThing(widget, region, flushUpdate * 10, false);
@ -111,9 +110,9 @@ static inline void qt_flush(QWidget *widget, const QRegion &region, QWindowSurfa
}
}
if (widget != tlw)
windowSurface->flush(widget->windowHandle(), region, tlwOffset + widget->mapTo(tlw, QPoint()));
backingStore->flush(region, widget->windowHandle(), tlwOffset + widget->mapTo(tlw, QPoint()));
else
windowSurface->flush(widget->windowHandle(), region, tlwOffset);
backingStore->flush(region, widget->windowHandle(), tlwOffset);
}
#ifndef QT_NO_PAINT_DEBUG
@ -263,7 +262,7 @@ void QWidgetBackingStore::unflushPaint(QWidget *widget, const QRegion &rgn)
return;
const QPoint offset = widget->mapTo(tlw, QPoint());
qt_flush(widget, rgn, tlwExtra->backingStore->windowSurface, tlw, offset);
qt_flush(widget, rgn, tlwExtra->backingStoreTracker->store, tlw, offset);
}
#endif // QT_NO_PAINT_DEBUG
@ -277,21 +276,13 @@ bool QWidgetBackingStore::bltRect(const QRect &rect, int dx, int dy, QWidget *wi
const QRect tlwRect(QRect(pos, rect.size()));
if (fullUpdatePending || dirty.intersects(tlwRect))
return false; // We don't want to scroll junk.
return windowSurface->scroll(tlwRect, dx, dy);
return store->scroll(tlwRect, dx, dy);
}
void QWidgetBackingStore::releaseBuffer()
{
if (windowSurface)
#if defined(Q_WS_QPA)
windowSurface->resize(QSize());
#else
windowSurface->setGeometry(QRect());
#endif
#ifdef Q_BACKINGSTORE_SUBSURFACES
for (int i = 0; i < subSurfaces.size(); ++i)
subSurfaces.at(i)->setGeometry(QRect());
#endif
if (store)
store->resize(QSize());
}
/*!
@ -300,80 +291,17 @@ void QWidgetBackingStore::releaseBuffer()
The \a toClean region might be clipped by the window surface.
*/
void QWidgetBackingStore::beginPaint(QRegion &toClean, QWidget *widget, QWindowSurface *windowSurface,
void QWidgetBackingStore::beginPaint(QRegion &toClean, QWidget *widget, QBackingStore *backingStore,
BeginPaintInfo *returnInfo, bool toCleanIsInTopLevelCoordinates)
{
#ifdef Q_WS_QWS
QWSWindowSurface *surface = static_cast<QWSWindowSurface *>(windowSurface);
QWidget *surfaceWidget = surface->window();
if (!surface->isValid()) {
// this looks strange but it really just releases the surface
surface->releaseSurface();
// the old window surface is deleted in setWindowSurface, which is
// called from QWindowSurface constructor.
windowSurface = tlw->d_func()->createDefaultWindowSurface();
surface = static_cast<QWSWindowSurface *>(windowSurface);
// createDefaultWindowSurface() will set topdata->windowSurface on the
// widget to zero. However, if this is a sub-surface, it should point
// to the widget's sub windowSurface, so we set that here:
if (!surfaceWidget->isWindow())
surfaceWidget->d_func()->topData()->windowSurface = windowSurface;
surface->setGeometry(topLevelRect());
returnInfo->windowSurfaceRecreated = true;
}
const QRegion toCleanUnclipped(toClean);
if (surfaceWidget->isWindow())
tlwOffset = surface->painterOffset();
#ifdef Q_BACKINGSTORE_SUBSURFACES
else if (toCleanIsInTopLevelCoordinates)
toClean &= surface->clipRegion().translated(surfaceWidget->mapTo(tlw, QPoint()));
if (!toCleanIsInTopLevelCoordinates && windowSurface == this->windowSurface)
toClean &= surface->clipRegion().translated(-widget->mapTo(surfaceWidget, QPoint()));
#else
toClean &= surface->clipRegion();
#endif
if (toClean.isEmpty()) {
if (surfaceWidget->isWindow()) {
dirtyFromPreviousSync += toCleanUnclipped;
hasDirtyFromPreviousSync = true;
}
returnInfo->nothingToPaint = true;
// Nothing to repaint. However, we might have newly exposed areas on the
// screen, so we have to make sure those are flushed.
flush();
return;
}
if (surfaceWidget->isWindow()) {
if (toCleanUnclipped != toClean) {
dirtyFromPreviousSync += (toCleanUnclipped - surface->clipRegion());
hasDirtyFromPreviousSync = true;
}
if (hasDirtyFromPreviousSync) {
dirtyFromPreviousSync -= toClean;
hasDirtyFromPreviousSync = !dirtyFromPreviousSync.isEmpty();
}
}
#endif // Q_WS_QWS
Q_UNUSED(widget);
Q_UNUSED(toCleanIsInTopLevelCoordinates);
// Always flush repainted areas.
dirtyOnScreen += toClean;
#if defined(Q_WS_QWS) && !defined(Q_BACKINGSTORE_SUBSURFACES)
toClean.translate(tlwOffset);
#endif
#ifdef QT_NO_PAINT_DEBUG
windowSurface->beginPaint(toClean);
backingStore->beginPaint(toClean);
#else
returnInfo->wasFlushed = QWidgetBackingStore::flushPaint(tlw, toClean);
// Avoid deadlock with QT_FLUSH_PAINT: the server will wait for
@ -381,30 +309,27 @@ void QWidgetBackingStore::beginPaint(QRegion &toClean, QWidget *widget, QWindowS
// never release the Communication lock that we are waiting for in
// sendSynchronousCommand
if (!returnInfo->wasFlushed)
windowSurface->beginPaint(toClean);
backingStore->beginPaint(toClean);
#endif
Q_UNUSED(returnInfo);
}
void QWidgetBackingStore::endPaint(const QRegion &cleaned, QWindowSurface *windowSurface,
void QWidgetBackingStore::endPaint(const QRegion &cleaned, QBackingStore *backingStore,
BeginPaintInfo *beginPaintInfo)
{
#ifndef QT_NO_PAINT_DEBUG
if (!beginPaintInfo->wasFlushed)
windowSurface->endPaint(cleaned);
backingStore->endPaint();
else
QWidgetBackingStore::unflushPaint(tlw, cleaned);
#else
Q_UNUSED(beginPaintInfo);
windowSurface->endPaint(cleaned);
Q_UNUSED(cleaned);
backingStore->endPaint();
#endif
#ifdef Q_BACKINGSTORE_SUBSURFACES
flush(static_cast<QWSWindowSurface *>(windowSurface)->window(), windowSurface);
#else
flush();
#endif
}
/*!
@ -417,11 +342,7 @@ QRegion QWidgetBackingStore::dirtyRegion(QWidget *widget) const
{
const bool widgetDirty = widget && widget != tlw;
const QRect tlwRect(topLevelRect());
#if defined(Q_WS_QPA)
const QRect surfaceGeometry(tlwRect.topLeft(), windowSurface->size());
#else
const QRect surfaceGeometry(windowSurface->geometry());
#endif
const QRect surfaceGeometry(tlwRect.topLeft(), store->size());
if (fullUpdatePending || (surfaceGeometry != tlwRect && surfaceGeometry.size() != tlwRect.size())) {
if (widgetDirty) {
const QRect dirtyTlwRect = QRect(QPoint(), tlwRect.size());
@ -472,11 +393,7 @@ QRegion QWidgetBackingStore::dirtyRegion(QWidget *widget) const
QRegion QWidgetBackingStore::staticContents(QWidget *parent, const QRect &withinClipRect) const
{
if (!parent && tlw->testAttribute(Qt::WA_StaticContents)) {
#if defined(Q_WS_QPA)
const QSize surfaceGeometry(windowSurface->size());
#else
const QRect surfaceGeometry(windowSurface->geometry());
#endif
const QSize surfaceGeometry(store->size());
QRect surfaceRect(0, 0, surfaceGeometry.width(), surfaceGeometry.height());
if (!withinClipRect.isEmpty())
surfaceRect &= withinClipRect;
@ -585,12 +502,6 @@ void QWidgetBackingStore::markDirty(const QRegion &rgn, QWidget *widget, bool up
return;
}
if (!windowSurface->hasFeature(QWindowSurface::PartialUpdates)) {
fullUpdatePending = true;
sendUpdateRequest(tlw, updateImmediately);
return;
}
const QPoint offset = widget->mapTo(tlw, QPoint());
const QRect widgetRect = widget->d_func()->effectiveRectFor(widget->rect());
if (qt_region_strictContains(dirty, widgetRect.translated(offset))) {
@ -680,12 +591,6 @@ void QWidgetBackingStore::markDirty(const QRect &rect, QWidget *widget, bool upd
return;
}
if (!windowSurface->hasFeature(QWindowSurface::PartialUpdates)) {
fullUpdatePending = true;
sendUpdateRequest(tlw, updateImmediately);
return;
}
const QRect widgetRect = widget->d_func()->effectiveRectFor(rect);
const QRect translatedRect(widgetRect.translated(widget->mapTo(tlw, QPoint())));
if (qt_region_strictContains(dirty, translatedRect)) {
@ -787,73 +692,6 @@ void QWidgetBackingStore::removeDirtyWidget(QWidget *w)
}
}
#if defined(Q_WS_QWS) && !defined(QT_NO_QWS_MANAGER)
bool QWidgetBackingStore::hasDirtyWindowDecoration() const
{
QTLWExtra *tlwExtra = tlw->d_func()->maybeTopData();
if (tlwExtra && tlwExtra->qwsManager)
return !tlwExtra->qwsManager->d_func()->dirtyRegions.isEmpty();
return false;
}
void QWidgetBackingStore::paintWindowDecoration()
{
if (!hasDirtyWindowDecoration())
return;
QDecoration &decoration = QApplication::qwsDecoration();
const QRect decorationRect = tlw->rect();
QRegion decorationRegion = decoration.region(tlw, decorationRect);
QWSManagerPrivate *managerPrivate = tlw->d_func()->topData()->qwsManager->d_func();
const bool doClipping = !managerPrivate->entireDecorationNeedsRepaint
&& !managerPrivate->dirtyClip.isEmpty();
if (doClipping) {
decorationRegion &= static_cast<QWSWindowSurface *>(windowSurface)->clipRegion();
decorationRegion &= managerPrivate->dirtyClip;
}
if (decorationRegion.isEmpty())
return;
//### The QWS decorations do not always paint the pixels they promise to paint.
// This causes painting problems with QWSMemorySurface. Since none of the other
// window surfaces actually use the region, passing an empty region is a safe
// workaround.
windowSurface->beginPaint(QRegion());
QPaintEngine *engine = windowSurface->paintDevice()->paintEngine();
Q_ASSERT(engine);
const QRegion oldSystemClip(engine->systemClip());
engine->setSystemClip(decorationRegion.translated(tlwOffset));
QPainter painter(windowSurface->paintDevice());
painter.setFont(QApplication::font());
painter.translate(tlwOffset);
const int numDirty = managerPrivate->dirtyRegions.size();
for (int i = 0; i < numDirty; ++i) {
const int area = managerPrivate->dirtyRegions.at(i);
QRegion clipRegion = decoration.region(tlw, decorationRect, area);
if (!clipRegion.isEmpty()) {
// Decoration styles changes the clip and assumes the old clip is non-empty,
// so we have to set it, but in theory it shouldn't be required.
painter.setClipRegion(clipRegion);
decoration.paint(&painter, tlw, area, managerPrivate->dirtyStates.at(i));
}
}
markDirtyOnScreen(decorationRegion, tlw, QPoint());
painter.end();
windowSurface->endPaint(decorationRegion);
managerPrivate->clearDirtyRegions();
engine->setSystemClip(oldSystemClip);
}
#endif
void QWidgetBackingStore::updateLists(QWidget *cur)
{
if (!cur)
@ -870,28 +708,14 @@ void QWidgetBackingStore::updateLists(QWidget *cur)
if (cur->testAttribute(Qt::WA_StaticContents))
addStaticWidget(cur);
#ifdef Q_BACKINGSTORE_SUBSURFACES
QTLWExtra *extra = cur->d_func()->maybeTopData();
if (extra && extra->windowSurface && cur != tlw)
subSurfaces.append(extra->windowSurface);
#endif
}
QWidgetBackingStore::QWidgetBackingStore(QWidget *topLevel)
: tlw(topLevel), dirtyOnScreenWidgets(0), hasDirtyFromPreviousSync(false)
, fullUpdatePending(0)
{
windowSurface = tlw->windowSurface();
if (!windowSurface)
windowSurface = topLevel->d_func()->createDefaultWindowSurface();
// The QWindowSurface constructor will call QWidget::setWindowSurface(),
// but automatically created surfaces should not be added to the topdata.
#ifdef Q_BACKINGSTORE_SUBSURFACES
Q_ASSERT(topLevel->d_func()->topData()->windowSurface == windowSurface);
#endif
topLevel->d_func()->topData()->windowSurface = 0;
store = tlw->backingStore();
Q_ASSERT(store);
// Ensure all existing subsurfaces and static widgets are added to their respective lists.
updateLists(topLevel);
@ -903,8 +727,6 @@ QWidgetBackingStore::~QWidgetBackingStore()
resetWidget(dirtyWidgets.at(c));
}
delete windowSurface;
windowSurface = 0;
delete dirtyOnScreenWidgets;
dirtyOnScreenWidgets = 0;
}
@ -962,7 +784,7 @@ void QWidgetPrivate::moveRect(const QRect &rect, int dx, int dy)
invalidateBuffer((newRect & clipR).translated(-data.crect.topLeft()));
} else {
QWidgetBackingStore *wbs = x->backingStore.data();
QWidgetBackingStore *wbs = x->backingStoreTracker.data();
QRegion childExpose(newRect & clipR);
if (sourceRect.isValid() && wbs->bltRect(sourceRect, dx, dy, pw))
@ -1005,7 +827,7 @@ void QWidgetPrivate::scrollRect(const QRect &rect, int dx, int dy)
if (x->inTopLevelResize)
return;
QWidgetBackingStore *wbs = x->backingStore.data();
QWidgetBackingStore *wbs = x->backingStoreTracker.data();
if (!wbs)
return;
@ -1140,14 +962,9 @@ void QWidgetBackingStore::sync(QWidget *exposedWidget, const QRegion &exposedReg
return;
}
// If there's no preserved contents support we always need
// to do a full repaint before flushing
if (!windowSurface->hasFeature(QWindowSurface::PreservedContents))
fullUpdatePending = true;
// Nothing to repaint.
if (!isDirty()) {
qt_flush(exposedWidget, exposedRegion, windowSurface, tlw, tlwOffset);
qt_flush(exposedWidget, exposedRegion, store, tlw, tlwOffset);
return;
}
@ -1185,11 +1002,7 @@ void QWidgetBackingStore::sync()
const bool inTopLevelResize = tlwExtra->inTopLevelResize;
const QRect tlwRect(topLevelRect());
#ifdef Q_WS_QPA
const QRect surfaceGeometry(tlwRect.topLeft(), windowSurface->size());
#else
const QRect surfaceGeometry(windowSurface->geometry());
#endif
const QRect surfaceGeometry(tlwRect.topLeft(), store->size());
if ((fullUpdatePending || inTopLevelResize || surfaceGeometry.size() != tlwRect.size()) && !updatesDisabled) {
if (hasStaticContents()) {
// Repaint existing dirty area and newly visible area.
@ -1198,7 +1011,7 @@ void QWidgetBackingStore::sync()
QRegion newVisible(0, 0, tlwRect.width(), tlwRect.height());
newVisible -= staticRegion;
dirty += newVisible;
windowSurface->setStaticContents(staticRegion);
store->setStaticContents(staticRegion);
} else {
// Repaint everything.
dirty = QRegion(0, 0, tlwRect.width(), tlwRect.height());
@ -1209,13 +1022,8 @@ void QWidgetBackingStore::sync()
}
}
#ifdef Q_WS_QPA
if (inTopLevelResize || surfaceGeometry.size() != tlwRect.size())
windowSurface->resize(tlwRect.size());
#else
if (inTopLevelResize || surfaceGeometry != tlwRect)
windowSurface->setGeometry(tlwRect);
#endif
store->resize(tlwRect.size());
if (updatesDisabled)
return;
@ -1296,16 +1104,14 @@ void QWidgetBackingStore::sync()
}
#endif
#ifndef Q_BACKINGSTORE_SUBSURFACES
BeginPaintInfo beginPaintInfo;
beginPaint(toClean, tlw, windowSurface, &beginPaintInfo);
beginPaint(toClean, tlw, store, &beginPaintInfo);
if (beginPaintInfo.nothingToPaint) {
for (int i = 0; i < opaqueNonOverlappedWidgets.size(); ++i)
resetWidget(opaqueNonOverlappedWidgets[i]);
dirty = QRegion();
return;
}
#endif
// Must do this before sending any paint events because
// the size may change in the paint event.
@ -1328,90 +1134,19 @@ void QWidgetBackingStore::sync()
QRegion toBePainted(wd->dirty);
resetWidget(w);
#ifdef Q_BACKINGSTORE_SUBSURFACES
QWindowSurface *subSurface = w->windowSurface();
BeginPaintInfo beginPaintInfo;
QPoint off = w->mapTo(tlw, QPoint());
toBePainted.translate(off);
beginPaint(toBePainted, w, subSurface, &beginPaintInfo, true);
toBePainted.translate(-off);
if (beginPaintInfo.nothingToPaint)
continue;
if (beginPaintInfo.windowSurfaceRecreated) {
// Eep the window surface has changed. The old one may have been
// deleted, in which case we will segfault on the call to
// painterOffset() below. Use the new window surface instead.
subSurface = w->windowSurface();
}
QPoint offset(tlwOffset);
if (subSurface == windowSurface)
offset += w->mapTo(tlw, QPoint());
else
offset = static_cast<QWSWindowSurface*>(subSurface)->painterOffset();
wd->drawWidget(subSurface->paintDevice(), toBePainted, offset, flags, 0, this);
endPaint(toBePainted, subSurface, &beginPaintInfo);
#else
QPoint offset(tlwOffset);
if (w != tlw)
offset += w->mapTo(tlw, QPoint());
wd->drawWidget(windowSurface->paintDevice(), toBePainted, offset, flags, 0, this);
#endif
wd->drawWidget(store->paintDevice(), toBePainted, offset, flags, 0, this);
}
// Paint the rest with composition.
#ifndef Q_BACKINGSTORE_SUBSURFACES
if (repaintAllWidgets || !dirtyCopy.isEmpty()) {
const int flags = QWidgetPrivate::DrawAsRoot | QWidgetPrivate::DrawRecursive;
tlw->d_func()->drawWidget(windowSurface->paintDevice(), dirtyCopy, tlwOffset, flags, 0, this);
tlw->d_func()->drawWidget(store->paintDevice(), dirtyCopy, tlwOffset, flags, 0, this);
}
endPaint(toClean, windowSurface, &beginPaintInfo);
#else
if (!repaintAllWidgets && dirtyCopy.isEmpty())
return; // Nothing more to paint.
QList<QWindowSurface *> surfaceList(subSurfaces);
surfaceList.prepend(windowSurface);
const QRect dirtyBoundingRect(dirtyCopy.boundingRect());
// Loop through all window surfaces (incl. the top-level surface) and
// repaint those intersecting with the bounding rect of the dirty region.
for (int i = 0; i < surfaceList.size(); ++i) {
QWindowSurface *subSurface = surfaceList.at(i);
QWidget *w = subSurface->window();
QWidgetPrivate *wd = w->d_func();
const QRect clipRect = wd->clipRect().translated(w->mapTo(tlw, QPoint()));
if (!qRectIntersects(dirtyBoundingRect, clipRect))
continue;
toClean = dirtyCopy;
BeginPaintInfo beginPaintInfo;
beginPaint(toClean, w, subSurface, &beginPaintInfo);
if (beginPaintInfo.nothingToPaint)
continue;
if (beginPaintInfo.windowSurfaceRecreated) {
// Eep the window surface has changed. The old one may have been
// deleted, in which case we will segfault on the call to
// painterOffset() below. Use the new window surface instead.
subSurface = w->windowSurface();
}
int flags = QWidgetPrivate::DrawRecursive;
if (w == tlw)
flags |= QWidgetPrivate::DrawAsRoot;
const QPoint painterOffset = static_cast<QWSWindowSurface*>(subSurface)->painterOffset();
wd->drawWidget(subSurface->paintDevice(), toClean, painterOffset, flags, 0, this);
endPaint(toClean, subSurface, &beginPaintInfo);
}
#endif
endPaint(toClean, store, &beginPaintInfo);
}
/*!
@ -1419,15 +1154,11 @@ void QWidgetBackingStore::sync()
If the \a widget is non-zero, the content is flushed to the \a widget.
If the \a surface is non-zero, the content of the \a surface is flushed.
*/
void QWidgetBackingStore::flush(QWidget *widget, QWindowSurface *surface)
void QWidgetBackingStore::flush(QWidget *widget, QBackingStore *backingStore)
{
#if defined(Q_WS_QWS) && !defined(QT_NO_QWS_MANAGER)
paintWindowDecoration();
#endif
if (!dirtyOnScreen.isEmpty()) {
QWidget *target = widget ? widget : tlw;
QWindowSurface *source = surface ? surface : windowSurface;
QBackingStore *source = store ? store : backingStore;
qt_flush(target, dirtyOnScreen, source, tlw, tlwOffset);
dirtyOnScreen = QRegion();
}
@ -1439,7 +1170,7 @@ void QWidgetBackingStore::flush(QWidget *widget, QWindowSurface *surface)
QWidget *w = dirtyOnScreenWidgets->at(i);
QWidgetPrivate *wd = w->d_func();
Q_ASSERT(wd->needsFlush);
qt_flush(w, *wd->needsFlush, windowSurface, tlw, tlwOffset);
qt_flush(w, *wd->needsFlush, backingStore, tlw, tlwOffset);
*wd->needsFlush = QRegion();
}
dirtyOnScreenWidgets->clear();
@ -1574,7 +1305,7 @@ void QWidgetPrivate::invalidateBuffer(const QRegion &rgn)
if (wrgn.isEmpty())
return;
tlwExtra->backingStore->markDirty(wrgn, q, false, true);
tlwExtra->backingStoreTracker->markDirty(wrgn, q, false, true);
}
/*!
@ -1598,7 +1329,7 @@ void QWidgetPrivate::invalidateBuffer(const QRect &rect)
return;
if (graphicsEffect || !extra || !extra->hasMask) {
tlwExtra->backingStore->markDirty(wRect, q, false, true);
tlwExtra->backingStoreTracker->markDirty(wRect, q, false, true);
return;
}
@ -1607,7 +1338,7 @@ void QWidgetPrivate::invalidateBuffer(const QRect &rect)
if (wRgn.isEmpty())
return;
tlwExtra->backingStore->markDirty(wRgn, q, false, true);
tlwExtra->backingStoreTracker->markDirty(wRgn, q, false, true);
}
void QWidgetPrivate::repaint_sys(const QRegion &rgn)

View File

@ -39,8 +39,8 @@
**
****************************************************************************/
#ifndef QBACKINGSTORE_P_H
#define QBACKINGSTORE_P_H
#ifndef QWIDGETBACKINGSTORE_P_H
#define QWIDGETBACKINGSTORE_P_H
//
// W A R N I N G
@ -56,20 +56,15 @@
#include <QDebug>
#include <QtWidgets/qwidget.h>
#include <private/qwidget_p.h>
#include <private/qwindowsurface_p.h>
#ifdef Q_WS_QWS
#include <private/qwindowsurface_qws_p.h>
#endif
#include <QtGui/qbackingstore.h>
QT_BEGIN_NAMESPACE
class QWindowSurface;
struct BeginPaintInfo {
inline BeginPaintInfo() : wasFlushed(0), nothingToPaint(0), windowSurfaceRecreated(0) {}
inline BeginPaintInfo() : wasFlushed(0), nothingToPaint(0), backingStoreRecreated(0) {}
uint wasFlushed : 1;
uint nothingToPaint : 1;
uint windowSurfaceRecreated : 1;
uint backingStoreRecreated : 1;
};
class Q_AUTOTEST_EXPORT QWidgetBackingStore
@ -82,11 +77,11 @@ public:
void sync(QWidget *exposedWidget, const QRegion &exposedRegion);
void sync();
void flush(QWidget *widget = 0, QWindowSurface *surface = 0);
void flush(QWidget *widget = 0, QBackingStore *store = 0);
inline QPoint topLevelOffset() const { return tlwOffset; }
QWindowSurface *surface() const { return windowSurface; }
QBackingStore *backingStore() const { return store; }
inline bool isDirty() const
{
@ -112,10 +107,7 @@ private:
QVector<QWidget *> dirtyWidgets;
QVector<QWidget *> *dirtyOnScreenWidgets;
QList<QWidget *> staticWidgets;
QWindowSurface *windowSurface;
#ifdef Q_BACKINGSTORE_SUBSURFACES
QList<QWindowSurface*> subSurfaces;
#endif
QBackingStore *store;
uint hasDirtyFromPreviousSync : 1;
uint fullUpdatePending : 1;
@ -127,9 +119,9 @@ private:
bool bltRect(const QRect &rect, int dx, int dy, QWidget *widget);
void releaseBuffer();
void beginPaint(QRegion &toClean, QWidget *widget, QWindowSurface *windowSurface,
void beginPaint(QRegion &toClean, QWidget *widget, QBackingStore *backingStore,
BeginPaintInfo *returnInfo, bool toCleanIsInTopLevelCoordinates = true);
void endPaint(const QRegion &cleaned, QWindowSurface *windowSurface, BeginPaintInfo *beginPaintInfo);
void endPaint(const QRegion &cleaned, QBackingStore *backingStore, BeginPaintInfo *beginPaintInfo);
QRegion dirtyRegion(QWidget *widget = 0) const;
QRegion staticContents(QWidget *widget = 0, const QRect &withinClipRect = QRect()) const;
@ -262,15 +254,13 @@ private:
}
inline bool hasStaticContents() const
{ return !staticWidgets.isEmpty() && windowSurface->hasFeature(QWindowSurface::StaticContents); }
{ return !staticWidgets.isEmpty(); }
friend QRegion qt_dirtyRegion(QWidget *);
friend class QWidgetPrivate;
friend class QWidget;
friend class QWSManagerPrivate;
friend class QETWidget;
friend class QWindowSurface;
friend class QWSWindowSurface;
friend class QBackingStore;
};
QT_END_NAMESPACE

View File

@ -65,7 +65,7 @@
#include <qdockwidget.h>
#include <qtoolbar.h>
#include <QtGui/qpaintengine.h>
#include <private/qbackingstore_p.h>
#include <QtGui/qbackingstore.h>
#include <qmenubar.h>
#include <qtableview.h>
@ -9081,7 +9081,7 @@ void tst_QWidget::destroyBackingStore()
QTRY_VERIFY(w.numPaintEvents > 0);
w.reset();
w.update();
qt_widget_private(&w)->topData()->backingStore.create(&w);
qt_widget_private(&w)->topData()->backingStoreTracker.create(&w);
w.update();
QApplication::processEvents();
@ -9105,7 +9105,7 @@ QWidgetBackingStore* backingStore(QWidget &widget)
QWidgetBackingStore *backingStore = 0;
#ifdef QT_BUILD_INTERNAL
if (QTLWExtra *topExtra = qt_widget_private(&widget)->maybeTopData())
backingStore = topExtra->backingStore.data();
backingStore = topExtra->backingStoreTracker.data();
#endif
return backingStore;
}
@ -9940,12 +9940,12 @@ class scrollWidgetWBS : public QWidget
public:
void deleteBackingStore()
{
static_cast<QWidgetPrivate*>(d_ptr.data())->topData()->backingStore.destroy();
static_cast<QWidgetPrivate*>(d_ptr.data())->topData()->backingStoreTracker.destroy();
}
void enableBackingStore()
{
if (!static_cast<QWidgetPrivate*>(d_ptr.data())->maybeBackingStore()) {
static_cast<QWidgetPrivate*>(d_ptr.data())->topData()->backingStore.create(this);
static_cast<QWidgetPrivate*>(d_ptr.data())->topData()->backingStoreTracker.create(this);
static_cast<QWidgetPrivate*>(d_ptr.data())->invalidateBuffer(this->rect());
repaint();
}