Rename QWindowSurface -> QBackingStore and split into platform / public.
Also get rid of GL window surface and related classes.
This commit is contained in:
parent
891a86f0f3
commit
6ce6b8a378
@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
@ -22,4 +22,5 @@ private:
|
||||
QImage m_image;
|
||||
QPoint m_lastPos;
|
||||
int m_backgroundColorIndex;
|
||||
QBackingStore *m_backingStore;
|
||||
};
|
||||
|
@ -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
|
||||
*/
|
||||
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
};
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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 += \
|
||||
|
@ -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 ®ion)
|
||||
\fn void QBackingStore::beginPaint(const QRegion ®ion)
|
||||
|
||||
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 ®ion)
|
||||
\fn void QBackingStore::endPaint(const QRegion ®ion)
|
||||
|
||||
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 ®ion,
|
||||
\fn void QBackingStore::flush(QWindow *window, const QRegion ®ion,
|
||||
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 ®ion, 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 ®ion)
|
||||
{
|
||||
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 ®ion)
|
||||
void QBackingStore::setStaticContents(const QRegion ®ion)
|
||||
{
|
||||
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());
|
@ -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 ®ion, 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 ®ion, 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 ®ion);
|
||||
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
|
155
src/gui/painting/qplatformbackingstore_qpa.cpp
Normal file
155
src/gui/painting/qplatformbackingstore_qpa.cpp
Normal 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 ®ion)
|
||||
|
||||
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 ®ion)
|
||||
|
||||
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 ®ion,
|
||||
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
|
86
src/gui/painting/qplatformbackingstore_qpa.h
Normal file
86
src/gui/painting/qplatformbackingstore_qpa.h
Normal 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 ®ion, 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
|
@ -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 ®ion, 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 ®ion);
|
||||
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
|
@ -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>
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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)) {
|
||||
|
@ -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();
|
||||
|
@ -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:
|
||||
|
@ -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;
|
||||
|
@ -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"
|
||||
|
@ -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
|
@ -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
|
@ -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
|
@ -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
|
||||
|
||||
|
@ -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
|
@ -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
|
@ -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
@ -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 ®ion, 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 ®ion);
|
||||
void endPaint(const QRegion ®ion);
|
||||
|
||||
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
|
||||
|
@ -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
|
@ -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
|
||||
|
@ -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 ®ion, const QPoint &offset)
|
||||
void QMinimalBackingStore::flush(QWindow *window, const QRegion ®ion, const QPoint &offset)
|
||||
{
|
||||
Q_UNUSED(window);
|
||||
Q_UNUSED(region);
|
||||
@ -70,14 +70,13 @@ void QMinimalWindowSurface::flush(QWindow *window, const QRegion ®ion, 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);
|
@ -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 ®ion, const QPoint &offset);
|
||||
void resize(const QSize &size);
|
||||
void resize(const QSize &size, const QRegion &staticContents);
|
||||
|
||||
private:
|
||||
QImage mImage;
|
@ -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);
|
||||
}
|
||||
|
@ -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; }
|
||||
|
||||
|
@ -43,8 +43,8 @@
|
||||
|
||||
#include "qwaylanddisplay.h"
|
||||
#include "qwaylandinputdevice.h"
|
||||
#include "qwaylandshmsurface.h"
|
||||
#include "qwaylandscreen.h"
|
||||
#include "qwaylandshmbackingstore.h"
|
||||
|
||||
#include <QtGui/QImageReader>
|
||||
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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 ®ion, const QPoint &offset)
|
||||
void QWaylandShmBackingStore::flush(QWindow *window, const QRegion ®ion, const QPoint &offset)
|
||||
{
|
||||
Q_UNUSED(window);
|
||||
Q_UNUSED(offset);
|
||||
@ -122,12 +122,11 @@ void QWaylandShmWindowSurface::flush(QWindow *window, const QRegion ®ion, 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)
|
@ -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 ®ion, const QPoint &offset);
|
||||
void resize(const QSize &size);
|
||||
void resize(const QSize &size, const QRegion &staticContents);
|
||||
void beginPaint(const QRegion &);
|
||||
|
||||
private:
|
@ -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
|
||||
|
@ -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 ®ion);
|
||||
@ -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 ®ion)
|
||||
}
|
||||
}
|
||||
|
||||
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 ®ion)
|
||||
void QXcbBackingStore::beginPaint(const QRegion ®ion)
|
||||
{
|
||||
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 ®ion)
|
||||
p.fillRect(*it, blank);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void QXcbWindowSurface::endPaint(const QRegion &)
|
||||
void QXcbBackingStore::endPaint(const QRegion &)
|
||||
{
|
||||
}
|
||||
|
||||
void QXcbWindowSurface::flush(QWindow *window, const QRegion ®ion, const QPoint &offset)
|
||||
void QXcbBackingStore::flush(QWindow *window, const QRegion ®ion, 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 ®ion, 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;
|
@ -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 ®ion, 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 &);
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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)
|
||||
|
@ -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 \
|
||||
|
@ -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 \
|
||||
|
@ -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
|
||||
|
@ -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 ®ion) 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
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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 ®ion, QWindowSurface *windowSurface,
|
||||
static inline void qt_flush(QWidget *widget, const QRegion ®ion, 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 ®ion, 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)
|
@ -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
|
@ -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();
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user