Enabling QQuickWidget and QOpenGLWidget
Enable child widgets (without a native window) that render to an FBO and are composed with the raster backingstore by the platform plugin. A preliminary version of QOpenGLWidget is included as private API. Change-Id: I8f984a4d7db285069ce3d6564707942c823d890d Reviewed-by: Jørgen Lind <jorgen.lind@digia.com>
This commit is contained in:
parent
5ae5bebb93
commit
eacd58d4e7
@ -516,6 +516,7 @@ public:
|
|||||||
AA_SynthesizeTouchForUnhandledMouseEvents = 11,
|
AA_SynthesizeTouchForUnhandledMouseEvents = 11,
|
||||||
AA_SynthesizeMouseForUnhandledTouchEvents = 12,
|
AA_SynthesizeMouseForUnhandledTouchEvents = 12,
|
||||||
AA_UseHighDpiPixmaps = 13,
|
AA_UseHighDpiPixmaps = 13,
|
||||||
|
AA_ForceRasterWidgets = 14,
|
||||||
|
|
||||||
// Add new attributes before this line
|
// Add new attributes before this line
|
||||||
AA_AttributeCount
|
AA_AttributeCount
|
||||||
|
@ -165,6 +165,9 @@
|
|||||||
sizes in layout geometry calculations should typically divide by
|
sizes in layout geometry calculations should typically divide by
|
||||||
QPixmap::devicePixelRatio() to get device-independent layout geometry.
|
QPixmap::devicePixelRatio() to get device-independent layout geometry.
|
||||||
|
|
||||||
|
\value AA_ForceRasterWidgets Make top-level widgets use pure raster surfaces,
|
||||||
|
and do not support non-native GL-based child widgets.
|
||||||
|
|
||||||
The following values are obsolete:
|
The following values are obsolete:
|
||||||
|
|
||||||
\value AA_ImmediateWidgetCreation This attribute is no longer fully
|
\value AA_ImmediateWidgetCreation This attribute is no longer fully
|
||||||
|
@ -761,8 +761,7 @@ bool QOpenGLContext::makeCurrent(QSurface *surface)
|
|||||||
|
|
||||||
if (!surface->surfaceHandle())
|
if (!surface->surfaceHandle())
|
||||||
return false;
|
return false;
|
||||||
|
if (!surface->supportsOpenGL()) {
|
||||||
if (surface->surfaceType() != QSurface::OpenGLSurface) {
|
|
||||||
qWarning() << "QOpenGLContext::makeCurrent() called with non-opengl surface" << surface;
|
qWarning() << "QOpenGLContext::makeCurrent() called with non-opengl surface" << surface;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -837,9 +836,9 @@ void QOpenGLContext::swapBuffers(QSurface *surface)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (surface->surfaceType() != QSurface::OpenGLSurface) {
|
if (!surface->supportsOpenGL()) {
|
||||||
qWarning() << "QOpenGLContext::swapBuffers() called with non-opengl surface";
|
qWarning() << "QOpenGLContext::swapBuffers() called with non-opengl surface";
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (surface->surfaceClass() == QSurface::Window
|
if (surface->surfaceClass() == QSurface::Window
|
||||||
|
@ -95,7 +95,8 @@ public:
|
|||||||
NonFullScreenWindows,
|
NonFullScreenWindows,
|
||||||
NativeWidgets,
|
NativeWidgets,
|
||||||
WindowManagement,
|
WindowManagement,
|
||||||
SyncState
|
SyncState,
|
||||||
|
RasterGLSurface
|
||||||
};
|
};
|
||||||
|
|
||||||
virtual ~QPlatformIntegration() { }
|
virtual ~QPlatformIntegration() { }
|
||||||
|
@ -74,6 +74,9 @@ QT_BEGIN_NAMESPACE
|
|||||||
a software rasterizer like Qt's raster paint engine.
|
a software rasterizer like Qt's raster paint engine.
|
||||||
\value OpenGLSurface The surface is an OpenGL compatible surface and can be used
|
\value OpenGLSurface The surface is an OpenGL compatible surface and can be used
|
||||||
in conjunction with QOpenGLContext.
|
in conjunction with QOpenGLContext.
|
||||||
|
\value RasterGLSurface The surface can be rendered to using a software rasterizer,
|
||||||
|
and also supports OpenGL. This surface type is intended for internal Qt use, and
|
||||||
|
requires the use of private API.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
@ -83,6 +86,19 @@ QT_BEGIN_NAMESPACE
|
|||||||
Returns the format of the surface.
|
Returns the format of the surface.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/*!
|
||||||
|
Returns true if the surface is OpenGL compatible and can be used in
|
||||||
|
conjunction with QOpenGLContext; otherwise returns false.
|
||||||
|
|
||||||
|
\since 5.3
|
||||||
|
*/
|
||||||
|
|
||||||
|
bool QSurface::supportsOpenGL() const
|
||||||
|
{
|
||||||
|
SurfaceType type = surfaceType();
|
||||||
|
return type == OpenGLSurface || type == RasterGLSurface;
|
||||||
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
\fn QPlatformSurface *QSurface::surfaceHandle() const
|
\fn QPlatformSurface *QSurface::surfaceHandle() const
|
||||||
|
|
||||||
|
@ -64,7 +64,8 @@ public:
|
|||||||
|
|
||||||
enum SurfaceType {
|
enum SurfaceType {
|
||||||
RasterSurface,
|
RasterSurface,
|
||||||
OpenGLSurface
|
OpenGLSurface,
|
||||||
|
RasterGLSurface
|
||||||
};
|
};
|
||||||
|
|
||||||
virtual ~QSurface();
|
virtual ~QSurface();
|
||||||
@ -75,6 +76,7 @@ public:
|
|||||||
virtual QPlatformSurface *surfaceHandle() const = 0;
|
virtual QPlatformSurface *surfaceHandle() const = 0;
|
||||||
|
|
||||||
virtual SurfaceType surfaceType() const = 0;
|
virtual SurfaceType surfaceType() const = 0;
|
||||||
|
bool supportsOpenGL() const;
|
||||||
|
|
||||||
virtual QSize size() const = 0;
|
virtual QSize size() const = 0;
|
||||||
|
|
||||||
|
@ -44,6 +44,16 @@
|
|||||||
#include <qpixmap.h>
|
#include <qpixmap.h>
|
||||||
#include <private/qwindow_p.h>
|
#include <private/qwindow_p.h>
|
||||||
|
|
||||||
|
#include <qopengl.h>
|
||||||
|
#include <qopenglcontext.h>
|
||||||
|
#include <QtGui/QMatrix4x4>
|
||||||
|
#include <QtGui/QOpenGLShaderProgram>
|
||||||
|
#include <QtGui/QOpenGLContext>
|
||||||
|
#include <QtGui/QOpenGLFunctions>
|
||||||
|
#ifndef QT_NO_OPENGL
|
||||||
|
#include <QtGui/private/qopengltextureblitter_p.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
QT_BEGIN_NAMESPACE
|
QT_BEGIN_NAMESPACE
|
||||||
|
|
||||||
class QPlatformBackingStorePrivate
|
class QPlatformBackingStorePrivate
|
||||||
@ -51,13 +61,103 @@ class QPlatformBackingStorePrivate
|
|||||||
public:
|
public:
|
||||||
QPlatformBackingStorePrivate(QWindow *w)
|
QPlatformBackingStorePrivate(QWindow *w)
|
||||||
: window(w)
|
: window(w)
|
||||||
|
#ifndef QT_NO_OPENGL
|
||||||
|
, blitter(0)
|
||||||
|
#endif
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
~QPlatformBackingStorePrivate()
|
||||||
|
{
|
||||||
|
#ifndef QT_NO_OPENGL
|
||||||
|
if (blitter)
|
||||||
|
blitter->destroy();
|
||||||
|
delete blitter;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
QWindow *window;
|
QWindow *window;
|
||||||
QSize size;
|
QSize size;
|
||||||
|
#ifndef QT_NO_OPENGL
|
||||||
|
mutable GLuint textureId;
|
||||||
|
mutable QSize textureSize;
|
||||||
|
QOpenGLTextureBlitter *blitter;
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#ifndef QT_NO_OPENGL
|
||||||
|
|
||||||
|
struct QBackingstoreTextureInfo
|
||||||
|
{
|
||||||
|
GLuint textureId;
|
||||||
|
QRect rect;
|
||||||
|
};
|
||||||
|
|
||||||
|
Q_DECLARE_TYPEINFO(QBackingstoreTextureInfo, Q_MOVABLE_TYPE);
|
||||||
|
|
||||||
|
class QPlatformTextureListPrivate : public QObjectPrivate
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
QPlatformTextureListPrivate()
|
||||||
|
: locked(false)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
QList<QBackingstoreTextureInfo> textures;
|
||||||
|
bool locked;
|
||||||
|
};
|
||||||
|
|
||||||
|
QPlatformTextureList::QPlatformTextureList(QObject *parent)
|
||||||
|
: QObject(*new QPlatformTextureListPrivate, parent)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
QPlatformTextureList::~QPlatformTextureList()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
int QPlatformTextureList::count() const
|
||||||
|
{
|
||||||
|
Q_D(const QPlatformTextureList);
|
||||||
|
return d->textures.count();
|
||||||
|
}
|
||||||
|
|
||||||
|
GLuint QPlatformTextureList::textureId(int index) const
|
||||||
|
{
|
||||||
|
Q_D(const QPlatformTextureList);
|
||||||
|
return d->textures.at(index).textureId;
|
||||||
|
}
|
||||||
|
|
||||||
|
QRect QPlatformTextureList::geometry(int index) const
|
||||||
|
{
|
||||||
|
Q_D(const QPlatformTextureList);
|
||||||
|
return d->textures.at(index).rect;
|
||||||
|
}
|
||||||
|
|
||||||
|
void QPlatformTextureList::lock(bool on)
|
||||||
|
{
|
||||||
|
Q_D(QPlatformTextureList);
|
||||||
|
if (on != d->locked) {
|
||||||
|
d->locked = on;
|
||||||
|
emit locked(on);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool QPlatformTextureList::isLocked() const
|
||||||
|
{
|
||||||
|
Q_D(const QPlatformTextureList);
|
||||||
|
return d->locked;
|
||||||
|
}
|
||||||
|
|
||||||
|
void QPlatformTextureList::appendTexture(GLuint textureId, const QRect &geometry)
|
||||||
|
{
|
||||||
|
Q_D(QPlatformTextureList);
|
||||||
|
QBackingstoreTextureInfo bi;
|
||||||
|
bi.textureId = textureId;
|
||||||
|
bi.rect = geometry;
|
||||||
|
d->textures.append(bi);
|
||||||
|
}
|
||||||
|
#endif // QT_NO_OPENGL
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
\class QPlatformBackingStore
|
\class QPlatformBackingStore
|
||||||
\since 5.0
|
\since 5.0
|
||||||
@ -79,6 +179,147 @@ public:
|
|||||||
Note that the \a offset parameter is currently unused.
|
Note that the \a offset parameter is currently unused.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#ifndef QT_NO_OPENGL
|
||||||
|
/*!
|
||||||
|
Flushes the given \a region from the specified \a window onto the
|
||||||
|
screen, and composes it with the specified \a textures.
|
||||||
|
|
||||||
|
The default implementation retrieves the contents using toTexture()
|
||||||
|
and composes using OpenGL. May be reimplemented in subclasses if there
|
||||||
|
is a more efficient native way to do it.
|
||||||
|
|
||||||
|
Note that the \a offset parameter is currently unused.
|
||||||
|
*/
|
||||||
|
|
||||||
|
void QPlatformBackingStore::composeAndFlush(QWindow *window, const QRegion ®ion,
|
||||||
|
const QPoint &offset,
|
||||||
|
QPlatformTextureList *textures, QOpenGLContext *context)
|
||||||
|
{
|
||||||
|
Q_UNUSED(offset);
|
||||||
|
|
||||||
|
context->makeCurrent(window);
|
||||||
|
glViewport(0, 0, window->width(), window->height());
|
||||||
|
|
||||||
|
if (!d_ptr->blitter) {
|
||||||
|
d_ptr->blitter = new QOpenGLTextureBlitter;
|
||||||
|
d_ptr->blitter->create();
|
||||||
|
}
|
||||||
|
|
||||||
|
d_ptr->blitter->bind();
|
||||||
|
|
||||||
|
QRect windowRect(QPoint(), window->size());
|
||||||
|
for (int i = 0; i < textures->count(); ++i) {
|
||||||
|
GLuint textureId = textures->textureId(i);
|
||||||
|
glBindTexture(GL_TEXTURE_2D, textureId);
|
||||||
|
|
||||||
|
QMatrix4x4 target = QOpenGLTextureBlitter::targetTransform(textures->geometry(i), windowRect,
|
||||||
|
QOpenGLTextureBlitter::OriginTopLeft);
|
||||||
|
d_ptr->blitter->blit(textureId, target, QOpenGLTextureBlitter::OriginBottomLeft);
|
||||||
|
}
|
||||||
|
|
||||||
|
GLuint textureId = toTexture(region);
|
||||||
|
if (!textureId)
|
||||||
|
return;
|
||||||
|
|
||||||
|
glEnable(GL_BLEND);
|
||||||
|
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||||
|
|
||||||
|
QMatrix4x4 target = QOpenGLTextureBlitter::targetTransform(windowRect, windowRect,
|
||||||
|
QOpenGLTextureBlitter::OriginTopLeft);
|
||||||
|
d_ptr->blitter->setSwizzleRB(true);
|
||||||
|
d_ptr->blitter->blit(textureId, target, QOpenGLTextureBlitter::OriginTopLeft);
|
||||||
|
d_ptr->blitter->setSwizzleRB(false);
|
||||||
|
|
||||||
|
glDisable(GL_BLEND);
|
||||||
|
d_ptr->blitter->release();
|
||||||
|
context->swapBuffers(window);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
Implemented in subclasses to return the content of the backingstore as a QImage.
|
||||||
|
|
||||||
|
If QPlatformIntegration::RasterGLSurface is supported, either this function or
|
||||||
|
toTexture() must be implemented.
|
||||||
|
|
||||||
|
\sa toTexture()
|
||||||
|
*/
|
||||||
|
QImage QPlatformBackingStore::toImage() const
|
||||||
|
{
|
||||||
|
return QImage();
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
May be reimplemented in subclasses to return the content of the
|
||||||
|
backingstore as an OpenGL texture. \a dirtyRegion is the part of the
|
||||||
|
backingstore which may have changed since the last call to this function. The
|
||||||
|
caller of this function must ensure that there is a current context.
|
||||||
|
|
||||||
|
The ownership of the texture is not transferred. The caller must not store
|
||||||
|
the return value between calls, but instead call this function before each use.
|
||||||
|
|
||||||
|
The default implementation returns a cached texture if \a dirtyRegion is
|
||||||
|
empty and the window has not been resized, otherwise it retrieves the
|
||||||
|
content using toImage() and performs a texture upload.
|
||||||
|
*/
|
||||||
|
|
||||||
|
GLuint QPlatformBackingStore::toTexture(const QRegion &dirtyRegion) const
|
||||||
|
{
|
||||||
|
QImage image = toImage();
|
||||||
|
QSize imageSize = image.size();
|
||||||
|
if (imageSize.isEmpty())
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
bool resized = d_ptr->textureSize != imageSize;
|
||||||
|
if (dirtyRegion.isEmpty() && !resized)
|
||||||
|
return d_ptr->textureId;
|
||||||
|
|
||||||
|
if (image.format() != QImage::Format_RGB32 && image.format() != QImage::Format_RGBA8888)
|
||||||
|
image = image.convertToFormat(QImage::Format_RGBA8888);
|
||||||
|
|
||||||
|
if (resized) {
|
||||||
|
if (d_ptr->textureId)
|
||||||
|
glDeleteTextures(1, &d_ptr->textureId);
|
||||||
|
glGenTextures(1, &d_ptr->textureId);
|
||||||
|
glBindTexture(GL_TEXTURE_2D, d_ptr->textureId);
|
||||||
|
#ifndef QT_OPENGL_ES_2
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
|
||||||
|
#endif
|
||||||
|
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||||
|
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||||
|
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
|
||||||
|
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
|
||||||
|
|
||||||
|
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, imageSize.width(), imageSize.height(), 0, GL_RGBA, GL_UNSIGNED_BYTE,
|
||||||
|
const_cast<uchar*>(image.constBits()));
|
||||||
|
d_ptr->textureSize = imageSize;
|
||||||
|
} else {
|
||||||
|
glBindTexture(GL_TEXTURE_2D, d_ptr->textureId);
|
||||||
|
QRect imageRect = image.rect();
|
||||||
|
QRect rect = dirtyRegion.boundingRect() & imageRect;
|
||||||
|
// if the rect is wide enough it's cheaper to just
|
||||||
|
// extend it instead of doing an image copy
|
||||||
|
if (rect.width() >= imageRect.width() / 2) {
|
||||||
|
rect.setX(0);
|
||||||
|
rect.setWidth(imageRect.width());
|
||||||
|
}
|
||||||
|
|
||||||
|
// if the sub-rect is full-width we can pass the image data directly to
|
||||||
|
// OpenGL instead of copying, since there's no gap between scanlines
|
||||||
|
|
||||||
|
if (rect.width() == imageRect.width()) {
|
||||||
|
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, rect.y(), rect.width(), rect.height(), GL_RGBA, GL_UNSIGNED_BYTE,
|
||||||
|
image.constScanLine(rect.y()));
|
||||||
|
} else {
|
||||||
|
glTexSubImage2D(GL_TEXTURE_2D, 0, rect.x(), rect.y(), rect.width(), rect.height(), GL_RGBA, GL_UNSIGNED_BYTE,
|
||||||
|
image.copy(rect).constBits());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return d_ptr->textureId;
|
||||||
|
}
|
||||||
|
#endif // QT_NO_OPENGL
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
\fn QPaintDevice* QPlatformBackingStore::paintDevice()
|
\fn QPaintDevice* QPlatformBackingStore::paintDevice()
|
||||||
|
|
||||||
|
@ -52,9 +52,11 @@
|
|||||||
//
|
//
|
||||||
|
|
||||||
#include <QtCore/qrect.h>
|
#include <QtCore/qrect.h>
|
||||||
|
#include <QtCore/qobject.h>
|
||||||
|
|
||||||
#include <QtGui/qwindow.h>
|
#include <QtGui/qwindow.h>
|
||||||
#include <QtGui/qregion.h>
|
#include <QtGui/qregion.h>
|
||||||
|
#include <QtGui/qopengl.h>
|
||||||
|
|
||||||
QT_BEGIN_NAMESPACE
|
QT_BEGIN_NAMESPACE
|
||||||
|
|
||||||
@ -65,6 +67,31 @@ class QPoint;
|
|||||||
class QImage;
|
class QImage;
|
||||||
class QPlatformBackingStorePrivate;
|
class QPlatformBackingStorePrivate;
|
||||||
class QPlatformWindow;
|
class QPlatformWindow;
|
||||||
|
class QPlatformTextureList;
|
||||||
|
class QPlatformTextureListPrivate;
|
||||||
|
class QOpenGLContext;
|
||||||
|
|
||||||
|
#ifndef QT_NO_OPENGL
|
||||||
|
class Q_GUI_EXPORT QPlatformTextureList : public QObject
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
Q_DECLARE_PRIVATE(QPlatformTextureList)
|
||||||
|
public:
|
||||||
|
explicit QPlatformTextureList(QObject *parent = 0);
|
||||||
|
~QPlatformTextureList();
|
||||||
|
|
||||||
|
int count() const;
|
||||||
|
GLuint textureId(int index) const;
|
||||||
|
QRect geometry(int index) const;
|
||||||
|
void lock(bool on);
|
||||||
|
bool isLocked() const;
|
||||||
|
|
||||||
|
void appendTexture(GLuint textureId, const QRect &geometry);
|
||||||
|
|
||||||
|
Q_SIGNALS:
|
||||||
|
void locked(bool);
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
class Q_GUI_EXPORT QPlatformBackingStore
|
class Q_GUI_EXPORT QPlatformBackingStore
|
||||||
{
|
{
|
||||||
@ -79,6 +106,11 @@ public:
|
|||||||
// 'window' can be a child window, in which case 'region' is in child window coordinates and
|
// '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.
|
// 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 flush(QWindow *window, const QRegion ®ion, const QPoint &offset) = 0;
|
||||||
|
#ifndef QT_NO_OPENGL
|
||||||
|
virtual void composeAndFlush(QWindow *window, const QRegion ®ion, const QPoint &offset, QPlatformTextureList *textures, QOpenGLContext *context);
|
||||||
|
virtual QImage toImage() const;
|
||||||
|
virtual GLuint toTexture(const QRegion &dirtyRegion) const;
|
||||||
|
#endif
|
||||||
|
|
||||||
virtual void resize(const QSize &size, const QRegion &staticContents) = 0;
|
virtual void resize(const QSize &size, const QRegion &staticContents) = 0;
|
||||||
|
|
||||||
|
@ -328,7 +328,7 @@ QGLXContext::~QGLXContext()
|
|||||||
bool QGLXContext::makeCurrent(QPlatformSurface *surface)
|
bool QGLXContext::makeCurrent(QPlatformSurface *surface)
|
||||||
{
|
{
|
||||||
bool success = false;
|
bool success = false;
|
||||||
Q_ASSERT(surface->surface()->surfaceType() == QSurface::OpenGLSurface);
|
Q_ASSERT(surface->surface()->supportsOpenGL());
|
||||||
|
|
||||||
Display *dpy = DISPLAY_FROM_XCB(m_screen);
|
Display *dpy = DISPLAY_FROM_XCB(m_screen);
|
||||||
GLXDrawable glxDrawable = 0;
|
GLXDrawable glxDrawable = 0;
|
||||||
|
@ -280,6 +280,11 @@ void QXcbBackingStore::beginPaint(const QRegion ®ion)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QImage QXcbBackingStore::toImage() const
|
||||||
|
{
|
||||||
|
return m_image && m_image->image() ? *m_image->image() : QImage();
|
||||||
|
}
|
||||||
|
|
||||||
void QXcbBackingStore::flush(QWindow *window, const QRegion ®ion, const QPoint &offset)
|
void QXcbBackingStore::flush(QWindow *window, const QRegion ®ion, const QPoint &offset)
|
||||||
{
|
{
|
||||||
if (!m_image || m_image->size().isEmpty())
|
if (!m_image || m_image->size().isEmpty())
|
||||||
@ -319,6 +324,25 @@ void QXcbBackingStore::flush(QWindow *window, const QRegion ®ion, const QPoin
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifndef QT_NO_OPENGL
|
||||||
|
void QXcbBackingStore::composeAndFlush(QWindow *window, const QRegion ®ion, const QPoint &offset,
|
||||||
|
QPlatformTextureList *textures, QOpenGLContext *context)
|
||||||
|
{
|
||||||
|
QPlatformBackingStore::composeAndFlush(window, region, offset, textures, context);
|
||||||
|
|
||||||
|
Q_XCB_NOOP(connection());
|
||||||
|
|
||||||
|
if (m_syncingResize) {
|
||||||
|
QXcbWindow *platformWindow = static_cast<QXcbWindow *>(window->handle());
|
||||||
|
connection()->sync();
|
||||||
|
m_syncingResize = false;
|
||||||
|
platformWindow->updateSyncRequestCounter();
|
||||||
|
} else {
|
||||||
|
xcb_flush(xcb_connection());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif // QT_NO_OPENGL
|
||||||
|
|
||||||
void QXcbBackingStore::resize(const QSize &size, const QRegion &)
|
void QXcbBackingStore::resize(const QSize &size, const QRegion &)
|
||||||
{
|
{
|
||||||
if (m_image && size == m_image->size())
|
if (m_image && size == m_image->size())
|
||||||
|
@ -60,6 +60,11 @@ public:
|
|||||||
|
|
||||||
QPaintDevice *paintDevice();
|
QPaintDevice *paintDevice();
|
||||||
void flush(QWindow *window, const QRegion ®ion, const QPoint &offset);
|
void flush(QWindow *window, const QRegion ®ion, const QPoint &offset);
|
||||||
|
#ifndef QT_NO_OPENGL
|
||||||
|
void composeAndFlush(QWindow *window, const QRegion ®ion, const QPoint &offset,
|
||||||
|
QPlatformTextureList *textures, QOpenGLContext *context);
|
||||||
|
#endif
|
||||||
|
QImage toImage() const;
|
||||||
void resize(const QSize &size, const QRegion &staticContents);
|
void resize(const QSize &size, const QRegion &staticContents);
|
||||||
bool scroll(const QRegion &area, int dx, int dy);
|
bool scroll(const QRegion &area, int dx, int dy);
|
||||||
|
|
||||||
|
@ -284,6 +284,7 @@ bool QXcbIntegration::hasCapability(QPlatformIntegration::Capability cap) const
|
|||||||
case MultipleWindows: return true;
|
case MultipleWindows: return true;
|
||||||
case ForeignWindows: return true;
|
case ForeignWindows: return true;
|
||||||
case SyncState: return true;
|
case SyncState: return true;
|
||||||
|
case RasterGLSurface: return true;
|
||||||
default: return QPlatformIntegration::hasCapability(cap);
|
default: return QPlatformIntegration::hasCapability(cap);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -292,8 +292,6 @@ void QXcbWindow::create()
|
|||||||
if (QGuiApplicationPrivate::platformIntegration()->hasCapability(QPlatformIntegration::OpenGL)) {
|
if (QGuiApplicationPrivate::platformIntegration()->hasCapability(QPlatformIntegration::OpenGL)) {
|
||||||
#if defined(XCB_USE_GLX)
|
#if defined(XCB_USE_GLX)
|
||||||
XVisualInfo *visualInfo = qglx_findVisualInfo(DISPLAY_FROM_XCB(m_screen), m_screen->screenNumber(), &m_format);
|
XVisualInfo *visualInfo = qglx_findVisualInfo(DISPLAY_FROM_XCB(m_screen), m_screen->screenNumber(), &m_format);
|
||||||
if (!visualInfo && window()->surfaceType() == QSurface::OpenGLSurface)
|
|
||||||
qFatal("Could not initialize GLX");
|
|
||||||
#elif defined(XCB_USE_EGL)
|
#elif defined(XCB_USE_EGL)
|
||||||
EGLDisplay eglDisplay = connection()->egl_display();
|
EGLDisplay eglDisplay = connection()->egl_display();
|
||||||
EGLConfig eglConfig = q_configFromGLFormat(eglDisplay, m_format, true);
|
EGLConfig eglConfig = q_configFromGLFormat(eglDisplay, m_format, true);
|
||||||
@ -308,9 +306,14 @@ void QXcbWindow::create()
|
|||||||
XVisualInfo *visualInfo;
|
XVisualInfo *visualInfo;
|
||||||
int matchingCount = 0;
|
int matchingCount = 0;
|
||||||
visualInfo = XGetVisualInfo(DISPLAY_FROM_XCB(this), VisualIDMask, &visualInfoTemplate, &matchingCount);
|
visualInfo = XGetVisualInfo(DISPLAY_FROM_XCB(this), VisualIDMask, &visualInfoTemplate, &matchingCount);
|
||||||
if (!visualInfo && window()->surfaceType() == QSurface::OpenGLSurface)
|
|
||||||
qFatal("Could not initialize EGL");
|
|
||||||
#endif //XCB_USE_GLX
|
#endif //XCB_USE_GLX
|
||||||
|
if (!visualInfo && window()->surfaceType() == QSurface::OpenGLSurface)
|
||||||
|
qFatal("Could not initialize OpenGL");
|
||||||
|
|
||||||
|
if (!visualInfo && window()->surfaceType() == QSurface::RasterGLSurface) {
|
||||||
|
qWarning("Could not initialize OpenGL for RasterGLSurface, reverting to RasterSurface.");
|
||||||
|
window()->setSurfaceType(QSurface::RasterSurface);
|
||||||
|
}
|
||||||
if (visualInfo) {
|
if (visualInfo) {
|
||||||
m_depth = visualInfo->depth;
|
m_depth = visualInfo->depth;
|
||||||
m_imageFormat = imageFormatForDepth(m_depth);
|
m_imageFormat = imageFormatForDepth(m_depth);
|
||||||
|
@ -79,3 +79,8 @@ wince*: {
|
|||||||
SOURCES += \
|
SOURCES += \
|
||||||
kernel/qwidgetsfunctions_wince.cpp
|
kernel/qwidgetsfunctions_wince.cpp
|
||||||
}
|
}
|
||||||
|
|
||||||
|
contains(QT_CONFIG, opengl) {
|
||||||
|
HEADERS += kernel/qopenglwidget_p.h
|
||||||
|
SOURCES += kernel/qopenglwidget.cpp
|
||||||
|
}
|
||||||
|
183
src/widgets/kernel/qopenglwidget.cpp
Normal file
183
src/widgets/kernel/qopenglwidget.cpp
Normal file
@ -0,0 +1,183 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
|
||||||
|
** Contact: http://www.qt-project.org/legal
|
||||||
|
**
|
||||||
|
** This file is part of the QtWidgets module of the Qt Toolkit.
|
||||||
|
**
|
||||||
|
** $QT_BEGIN_LICENSE:LGPL$
|
||||||
|
** Commercial License Usage
|
||||||
|
** Licensees holding valid commercial Qt licenses may use this file in
|
||||||
|
** accordance with the commercial license agreement provided with the
|
||||||
|
** Software or, alternatively, in accordance with the terms contained in
|
||||||
|
** a written agreement between you and Digia. For licensing terms and
|
||||||
|
** conditions see http://qt.digia.com/licensing. For further information
|
||||||
|
** use the contact form at http://qt.digia.com/contact-us.
|
||||||
|
**
|
||||||
|
** GNU Lesser General Public License Usage
|
||||||
|
** Alternatively, 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, Digia gives you certain additional
|
||||||
|
** rights. These rights are described in the Digia 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.
|
||||||
|
**
|
||||||
|
**
|
||||||
|
** $QT_END_LICENSE$
|
||||||
|
**
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#include "qopenglwidget_p.h"
|
||||||
|
#include <QOpenGLContext>
|
||||||
|
#include <QtWidgets/private/qwidget_p.h>
|
||||||
|
|
||||||
|
#include <QOpenGLFramebufferObject>
|
||||||
|
#include <QWindow>
|
||||||
|
#include <qpa/qplatformwindow.h>
|
||||||
|
#include <QDebug>
|
||||||
|
#include <QtGui/QGuiApplication>
|
||||||
|
#include <QtGui/QScreen>
|
||||||
|
|
||||||
|
QT_BEGIN_NAMESPACE
|
||||||
|
|
||||||
|
class QOpenGLWidgetPrivate : public QWidgetPrivate
|
||||||
|
{
|
||||||
|
Q_DECLARE_PUBLIC(QOpenGLWidget)
|
||||||
|
public:
|
||||||
|
QOpenGLWidgetPrivate()
|
||||||
|
: fbo(0), uninitialized(true)
|
||||||
|
{
|
||||||
|
setRenderToTexture();
|
||||||
|
}
|
||||||
|
GLuint textureId() const { return fbo ? fbo->texture() : 0; }
|
||||||
|
|
||||||
|
const QSurface *surface() const { return q_func()->window()->windowHandle(); }
|
||||||
|
QSurface *surface() { return q_func()->window()->windowHandle(); }
|
||||||
|
void initialize();
|
||||||
|
|
||||||
|
QOpenGLContext context;
|
||||||
|
QOpenGLFramebufferObject *fbo;
|
||||||
|
bool uninitialized;
|
||||||
|
|
||||||
|
int w,h;
|
||||||
|
};
|
||||||
|
|
||||||
|
void QOpenGLWidgetPrivate::initialize()
|
||||||
|
{
|
||||||
|
Q_Q(QOpenGLWidget);
|
||||||
|
if (!uninitialized)
|
||||||
|
return;
|
||||||
|
context.setShareContext(get(q->window())->shareContext());
|
||||||
|
context.setFormat(surface()->format());
|
||||||
|
context.create();
|
||||||
|
context.makeCurrent(surface());
|
||||||
|
q->initializeGL();
|
||||||
|
uninitialized = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
QOpenGLWidget::QOpenGLWidget(QWidget *parent, Qt::WindowFlags f)
|
||||||
|
: QWidget(*(new QOpenGLWidgetPrivate), parent, f)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
QOpenGLWidget::~QOpenGLWidget()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
bool QOpenGLWidget::isValid() const
|
||||||
|
{
|
||||||
|
Q_D(const QOpenGLWidget);
|
||||||
|
return d->context.isValid();
|
||||||
|
}
|
||||||
|
|
||||||
|
void QOpenGLWidget::makeCurrent()
|
||||||
|
{
|
||||||
|
Q_D(QOpenGLWidget);
|
||||||
|
d->context.makeCurrent(d->surface());
|
||||||
|
d->fbo->bind();
|
||||||
|
}
|
||||||
|
|
||||||
|
void QOpenGLWidget::doneCurrent()
|
||||||
|
{
|
||||||
|
Q_D(QOpenGLWidget);
|
||||||
|
d->context.doneCurrent();
|
||||||
|
}
|
||||||
|
|
||||||
|
QSurfaceFormat QOpenGLWidget::format() const
|
||||||
|
{
|
||||||
|
Q_D(const QOpenGLWidget);
|
||||||
|
return d->surface()->format();
|
||||||
|
}
|
||||||
|
|
||||||
|
GLuint QOpenGLWidget::defaultFramebufferObject() const
|
||||||
|
{
|
||||||
|
Q_D(const QOpenGLWidget);
|
||||||
|
return d->fbo ? d->fbo->handle() : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void QOpenGLWidget::initializeGL()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void QOpenGLWidget::resizeGL(int w, int h)
|
||||||
|
{
|
||||||
|
Q_UNUSED(w);
|
||||||
|
Q_UNUSED(h);
|
||||||
|
}
|
||||||
|
|
||||||
|
void QOpenGLWidget::paintGL()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void QOpenGLWidget::updateGL()
|
||||||
|
{
|
||||||
|
makeCurrent();
|
||||||
|
paintGL();
|
||||||
|
glFlush();
|
||||||
|
doneCurrent();
|
||||||
|
update();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void QOpenGLWidget::resizeEvent(QResizeEvent *)
|
||||||
|
{
|
||||||
|
Q_D(QOpenGLWidget);
|
||||||
|
d->w = width();
|
||||||
|
d->h = height();
|
||||||
|
d->initialize();
|
||||||
|
|
||||||
|
d->context.makeCurrent(d->surface());
|
||||||
|
delete d->fbo; // recreate when resized
|
||||||
|
d->fbo = new QOpenGLFramebufferObject(size());
|
||||||
|
d->fbo->bind();
|
||||||
|
glBindTexture(GL_TEXTURE_2D, d->fbo->texture());
|
||||||
|
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||||
|
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||||
|
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
|
||||||
|
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
|
||||||
|
|
||||||
|
resizeGL(width(), height());
|
||||||
|
paintGL();
|
||||||
|
glFlush();
|
||||||
|
}
|
||||||
|
|
||||||
|
void QOpenGLWidget::paintEvent(QPaintEvent *)
|
||||||
|
{
|
||||||
|
qWarning("QOpenGLWidget does not support paintEvent() yet.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
QT_END_NAMESPACE
|
135
src/widgets/kernel/qopenglwidget_p.h
Normal file
135
src/widgets/kernel/qopenglwidget_p.h
Normal file
@ -0,0 +1,135 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
|
||||||
|
** Contact: http://www.qt-project.org/legal
|
||||||
|
**
|
||||||
|
** This file is part of the QtWidgets module of the Qt Toolkit.
|
||||||
|
**
|
||||||
|
** $QT_BEGIN_LICENSE:LGPL$
|
||||||
|
** Commercial License Usage
|
||||||
|
** Licensees holding valid commercial Qt licenses may use this file in
|
||||||
|
** accordance with the commercial license agreement provided with the
|
||||||
|
** Software or, alternatively, in accordance with the terms contained in
|
||||||
|
** a written agreement between you and Digia. For licensing terms and
|
||||||
|
** conditions see http://qt.digia.com/licensing. For further information
|
||||||
|
** use the contact form at http://qt.digia.com/contact-us.
|
||||||
|
**
|
||||||
|
** GNU Lesser General Public License Usage
|
||||||
|
** Alternatively, 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, Digia gives you certain additional
|
||||||
|
** rights. These rights are described in the Digia 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.
|
||||||
|
**
|
||||||
|
**
|
||||||
|
** $QT_END_LICENSE$
|
||||||
|
**
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
//
|
||||||
|
// W A R N I N G
|
||||||
|
// -------------
|
||||||
|
//
|
||||||
|
// This file is not part of the Qt API. It may change from version to version
|
||||||
|
// without notice, or even be removed.
|
||||||
|
//
|
||||||
|
// We mean it.
|
||||||
|
//
|
||||||
|
#ifndef QOPENGLWIDGET_H
|
||||||
|
#define QOPENGLWIDGET_H
|
||||||
|
|
||||||
|
#include <QWidget>
|
||||||
|
#include <QSurfaceFormat>
|
||||||
|
|
||||||
|
#include <QtGui/qopengl.h>
|
||||||
|
|
||||||
|
QT_BEGIN_NAMESPACE
|
||||||
|
|
||||||
|
class QOpenGLWidgetPrivate;
|
||||||
|
|
||||||
|
class Q_WIDGETS_EXPORT QOpenGLWidget : public QWidget
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
Q_DECLARE_PRIVATE(QOpenGLWidget)
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit QOpenGLWidget(QWidget* parent=0,
|
||||||
|
Qt::WindowFlags f=0);
|
||||||
|
|
||||||
|
// This API is not finalized yet. The commented-out functions below are
|
||||||
|
// QGLWidget functions that have not been implemented for QOpenGLWidget.
|
||||||
|
// Some of them may not end up in the final version (which is planned for a
|
||||||
|
// future release of Qt).
|
||||||
|
|
||||||
|
// explicit QOpenGLWidget(const QSurfaceFormat& format, QWidget* parent=0,
|
||||||
|
// Qt::WindowFlags f=0);
|
||||||
|
~QOpenGLWidget();
|
||||||
|
|
||||||
|
// void qglClearColor(const QColor& c) const;
|
||||||
|
|
||||||
|
bool isValid() const;
|
||||||
|
// bool isSharing() const;
|
||||||
|
|
||||||
|
void makeCurrent();
|
||||||
|
void doneCurrent();
|
||||||
|
|
||||||
|
// void swapBuffers();
|
||||||
|
|
||||||
|
QSurfaceFormat format() const;
|
||||||
|
GLuint defaultFramebufferObject() const;
|
||||||
|
|
||||||
|
// QPixmap renderPixmap(int w = 0, int h = 0, bool useContext = false);
|
||||||
|
QImage grabFrameBuffer(bool withAlpha = false);
|
||||||
|
|
||||||
|
// static QImage convertToGLFormat(const QImage& img);
|
||||||
|
|
||||||
|
// QPaintEngine *paintEngine() const;
|
||||||
|
|
||||||
|
// void drawTexture(const QRectF &target, GLuint textureId, GLenum textureTarget = GL_TEXTURE_2D);
|
||||||
|
// void drawTexture(const QPointF &point, GLuint textureId, GLenum textureTarget = GL_TEXTURE_2D);
|
||||||
|
|
||||||
|
public Q_SLOTS:
|
||||||
|
void updateGL();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
// bool event(QEvent *);
|
||||||
|
virtual void initializeGL();
|
||||||
|
virtual void resizeGL(int w, int h);
|
||||||
|
virtual void paintGL();
|
||||||
|
|
||||||
|
// void setAutoBufferSwap(bool on);
|
||||||
|
// bool autoBufferSwap() const;
|
||||||
|
|
||||||
|
void paintEvent(QPaintEvent*);
|
||||||
|
void resizeEvent(QResizeEvent*);
|
||||||
|
|
||||||
|
// virtual void glInit();
|
||||||
|
// virtual void glDraw();
|
||||||
|
|
||||||
|
// QOpenGLWidget(QOpenGLWidgetPrivate &dd,
|
||||||
|
// const QGLFormat &format = QGLFormat(),
|
||||||
|
// QWidget *parent = 0,
|
||||||
|
// const QOpenGLWidget* shareWidget = 0,
|
||||||
|
// Qt::WindowFlags f = 0);
|
||||||
|
private:
|
||||||
|
Q_DISABLE_COPY(QOpenGLWidget)
|
||||||
|
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
QT_END_NAMESPACE
|
||||||
|
|
||||||
|
#endif // QOPENGLWIDGET_H
|
@ -78,6 +78,7 @@
|
|||||||
#include "private/qstyle_p.h"
|
#include "private/qstyle_p.h"
|
||||||
#include "qfileinfo.h"
|
#include "qfileinfo.h"
|
||||||
#include <QtGui/qinputmethod.h>
|
#include <QtGui/qinputmethod.h>
|
||||||
|
#include <QtGui/qopenglcontext.h>
|
||||||
|
|
||||||
#include <private/qgraphicseffect_p.h>
|
#include <private/qgraphicseffect_p.h>
|
||||||
#include <qbackingstore.h>
|
#include <qbackingstore.h>
|
||||||
@ -270,6 +271,8 @@ QWidgetPrivate::QWidgetPrivate(int version)
|
|||||||
, isMoved(0)
|
, isMoved(0)
|
||||||
, usesDoubleBufferedGLContext(0)
|
, usesDoubleBufferedGLContext(0)
|
||||||
, mustHaveWindowHandle(0)
|
, mustHaveWindowHandle(0)
|
||||||
|
, renderToTexture(0)
|
||||||
|
, textureChildSeen(0)
|
||||||
#ifndef QT_NO_IM
|
#ifndef QT_NO_IM
|
||||||
, inheritsInputMethodHints(0)
|
, inheritsInputMethodHints(0)
|
||||||
#endif
|
#endif
|
||||||
@ -1558,6 +1561,7 @@ void QWidgetPrivate::createTLExtra()
|
|||||||
x->inRepaint = false;
|
x->inRepaint = false;
|
||||||
x->embedded = 0;
|
x->embedded = 0;
|
||||||
x->window = 0;
|
x->window = 0;
|
||||||
|
x->shareContext = 0;
|
||||||
x->screenIndex = 0;
|
x->screenIndex = 0;
|
||||||
#ifdef Q_WS_MAC
|
#ifdef Q_WS_MAC
|
||||||
x->wasMaximized = false;
|
x->wasMaximized = false;
|
||||||
@ -5133,9 +5137,17 @@ void QWidgetPrivate::drawWidget(QPaintDevice *pdev, const QRegion &rgn, const QP
|
|||||||
<< "geometry ==" << QRect(q->mapTo(q->window(), QPoint(0, 0)), q->size());
|
<< "geometry ==" << QRect(q->mapTo(q->window(), QPoint(0, 0)), q->size());
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
//actually send the paint event
|
if (renderToTexture) {
|
||||||
QPaintEvent e(toBePainted);
|
// This widget renders into a texture which is composed later. We just need to
|
||||||
QCoreApplication::sendSpontaneousEvent(q, &e);
|
// punch a hole in the backingstore, so the texture will be visible.
|
||||||
|
QPainter p(q);
|
||||||
|
p.setCompositionMode(QPainter::CompositionMode_Source);
|
||||||
|
p.fillRect(q->rect(), Qt::transparent);
|
||||||
|
} else {
|
||||||
|
//actually send the paint event
|
||||||
|
QPaintEvent e(toBePainted);
|
||||||
|
QCoreApplication::sendSpontaneousEvent(q, &e);
|
||||||
|
}
|
||||||
|
|
||||||
// Native widgets need to be marked dirty on screen so painting will be done in correct context
|
// Native widgets need to be marked dirty on screen so painting will be done in correct context
|
||||||
if (backingStore && !onScreen && !asRoot && (q->internalWinId() || !q->nativeParentWidget()->isWindow()))
|
if (backingStore && !onScreen && !asRoot && (q->internalWinId() || !q->nativeParentWidget()->isWindow()))
|
||||||
@ -9637,6 +9649,13 @@ void QWidget::setParent(QWidget *parent, Qt::WindowFlags f)
|
|||||||
if (desktopWidget)
|
if (desktopWidget)
|
||||||
parent = 0;
|
parent = 0;
|
||||||
|
|
||||||
|
#ifndef QT_NO_OPENGL
|
||||||
|
if (d->textureChildSeen && parent) {
|
||||||
|
// set the textureChildSeen flag up the whole parent chain
|
||||||
|
QWidgetPrivate::get(parent)->setTextureChildSeen();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
if (QWidgetBackingStore *oldBs = oldtlw->d_func()->maybeBackingStore()) {
|
if (QWidgetBackingStore *oldBs = oldtlw->d_func()->maybeBackingStore()) {
|
||||||
if (newParent)
|
if (newParent)
|
||||||
oldBs->removeDirtyWidget(this);
|
oldBs->removeDirtyWidget(this);
|
||||||
@ -11108,7 +11127,25 @@ void QWidgetPrivate::adjustQuitOnCloseAttribute()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QOpenGLContext *QWidgetPrivate::shareContext() const
|
||||||
|
{
|
||||||
|
#ifdef QT_NO_OPENGL
|
||||||
|
return 0;
|
||||||
|
#else
|
||||||
|
if (!extra || !extra->topextra || !extra->topextra->window) {
|
||||||
|
qWarning() << "Asking for share context for widget that does not have a window handle";
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
QWidgetPrivate *that = const_cast<QWidgetPrivate *>(this);
|
||||||
|
if (!extra->topextra->shareContext) {
|
||||||
|
QOpenGLContext *ctx = new QOpenGLContext();
|
||||||
|
ctx->setFormat(extra->topextra->window->format());
|
||||||
|
ctx->create();
|
||||||
|
that->extra->topextra->shareContext = ctx;
|
||||||
|
}
|
||||||
|
return that->extra->topextra->shareContext;
|
||||||
|
#endif // QT_NO_OPENGL
|
||||||
|
}
|
||||||
|
|
||||||
Q_WIDGETS_EXPORT QWidgetData *qt_qwidget_data(QWidget *widget)
|
Q_WIDGETS_EXPORT QWidgetData *qt_qwidget_data(QWidget *widget)
|
||||||
{
|
{
|
||||||
|
@ -60,6 +60,7 @@
|
|||||||
#include "QtCore/qset.h"
|
#include "QtCore/qset.h"
|
||||||
#include "QtGui/qregion.h"
|
#include "QtGui/qregion.h"
|
||||||
#include "QtGui/qinputmethod.h"
|
#include "QtGui/qinputmethod.h"
|
||||||
|
#include "QtGui/qopengl.h"
|
||||||
#include "QtWidgets/qsizepolicy.h"
|
#include "QtWidgets/qsizepolicy.h"
|
||||||
#include "QtWidgets/qstyle.h"
|
#include "QtWidgets/qstyle.h"
|
||||||
#include "QtWidgets/qapplication.h"
|
#include "QtWidgets/qapplication.h"
|
||||||
@ -80,6 +81,7 @@ class QPixmap;
|
|||||||
class QWidgetBackingStore;
|
class QWidgetBackingStore;
|
||||||
class QGraphicsProxyWidget;
|
class QGraphicsProxyWidget;
|
||||||
class QWidgetItemV2;
|
class QWidgetItemV2;
|
||||||
|
class QOpenGLContext;
|
||||||
|
|
||||||
class QStyle;
|
class QStyle;
|
||||||
|
|
||||||
@ -216,6 +218,7 @@ struct QTLWExtra {
|
|||||||
bool wasMaximized;
|
bool wasMaximized;
|
||||||
#endif
|
#endif
|
||||||
QWidgetWindow *window;
|
QWidgetWindow *window;
|
||||||
|
QOpenGLContext *shareContext;
|
||||||
quint32 screenIndex; // index in qplatformscreenlist
|
quint32 screenIndex; // index in qplatformscreenlist
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -324,6 +327,8 @@ public:
|
|||||||
explicit QWidgetPrivate(int version = QObjectPrivateVersion);
|
explicit QWidgetPrivate(int version = QObjectPrivateVersion);
|
||||||
~QWidgetPrivate();
|
~QWidgetPrivate();
|
||||||
|
|
||||||
|
static QWidgetPrivate *get(QWidget *w) { return w->d_func(); }
|
||||||
|
|
||||||
QWExtra *extraData() const;
|
QWExtra *extraData() const;
|
||||||
QTLWExtra *topData() const;
|
QTLWExtra *topData() const;
|
||||||
QTLWExtra *maybeTopData() const;
|
QTLWExtra *maybeTopData() const;
|
||||||
@ -618,6 +623,27 @@ public:
|
|||||||
inline QRect mapFromWS(const QRect &r) const
|
inline QRect mapFromWS(const QRect &r) const
|
||||||
{ QRect rr(r); rr.translate(data.wrect.topLeft()); return rr; }
|
{ QRect rr(r); rr.translate(data.wrect.topLeft()); return rr; }
|
||||||
|
|
||||||
|
QOpenGLContext *shareContext() const;
|
||||||
|
|
||||||
|
#ifndef QT_NO_OPENGL
|
||||||
|
virtual GLuint textureId() const { return 0; }
|
||||||
|
|
||||||
|
void setRenderToTexture() { renderToTexture = true; textureChildSeen = true; }
|
||||||
|
void setTextureChildSeen()
|
||||||
|
{
|
||||||
|
Q_Q(QWidget);
|
||||||
|
if (textureChildSeen)
|
||||||
|
return;
|
||||||
|
textureChildSeen = 1;
|
||||||
|
|
||||||
|
if (!q->isWindow()) {
|
||||||
|
QWidget *parent = q->parentWidget();
|
||||||
|
if (parent)
|
||||||
|
get(parent)->setTextureChildSeen();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
// Variables.
|
// Variables.
|
||||||
// Regular pointers (keep them together to avoid gaps on 64 bit architectures).
|
// Regular pointers (keep them together to avoid gaps on 64 bit architectures).
|
||||||
QWExtra *extra;
|
QWExtra *extra;
|
||||||
@ -698,6 +724,8 @@ public:
|
|||||||
uint isMoved : 1;
|
uint isMoved : 1;
|
||||||
uint usesDoubleBufferedGLContext : 1;
|
uint usesDoubleBufferedGLContext : 1;
|
||||||
uint mustHaveWindowHandle : 1;
|
uint mustHaveWindowHandle : 1;
|
||||||
|
uint renderToTexture : 1;
|
||||||
|
uint textureChildSeen : 1;
|
||||||
#ifndef QT_NO_IM
|
#ifndef QT_NO_IM
|
||||||
uint inheritsInputMethodHints : 1;
|
uint inheritsInputMethodHints : 1;
|
||||||
#endif
|
#endif
|
||||||
|
@ -49,6 +49,7 @@
|
|||||||
#include "QtWidgets/qdesktopwidget.h"
|
#include "QtWidgets/qdesktopwidget.h"
|
||||||
#include <qpa/qplatformwindow.h>
|
#include <qpa/qplatformwindow.h>
|
||||||
#include "QtGui/qsurfaceformat.h"
|
#include "QtGui/qsurfaceformat.h"
|
||||||
|
#include <QtGui/qopenglcontext.h>
|
||||||
#include <qpa/qplatformopenglcontext.h>
|
#include <qpa/qplatformopenglcontext.h>
|
||||||
#include <qpa/qplatformintegration.h>
|
#include <qpa/qplatformintegration.h>
|
||||||
#include "QtGui/private/qwindow_p.h"
|
#include "QtGui/private/qwindow_p.h"
|
||||||
@ -953,6 +954,10 @@ void QWidgetPrivate::deleteTLSysExtra()
|
|||||||
delete extra->topextra->backingStore;
|
delete extra->topextra->backingStore;
|
||||||
extra->topextra->backingStore = 0;
|
extra->topextra->backingStore = 0;
|
||||||
|
|
||||||
|
#ifndef QT_NO_OPENGL
|
||||||
|
delete extra->topextra->shareContext;
|
||||||
|
extra->topextra->shareContext = 0;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -57,6 +57,8 @@
|
|||||||
#include <private/qpaintengine_raster_p.h>
|
#include <private/qpaintengine_raster_p.h>
|
||||||
#include <private/qgraphicseffect_p.h>
|
#include <private/qgraphicseffect_p.h>
|
||||||
|
|
||||||
|
#include <qpa/qplatformbackingstore.h>
|
||||||
|
|
||||||
#if defined(Q_OS_WIN) && !defined(QT_NO_PAINT_DEBUG)
|
#if defined(Q_OS_WIN) && !defined(QT_NO_PAINT_DEBUG)
|
||||||
# include <QtCore/qt_windows.h>
|
# include <QtCore/qt_windows.h>
|
||||||
# include <qpa/qplatformnativeinterface.h>
|
# include <qpa/qplatformnativeinterface.h>
|
||||||
@ -72,10 +74,15 @@ extern QRegion qt_dirtyRegion(QWidget *);
|
|||||||
* \a region is the region to be updated in \a widget coordinates.
|
* \a region is the region to be updated in \a widget coordinates.
|
||||||
*/
|
*/
|
||||||
static inline void qt_flush(QWidget *widget, const QRegion ®ion, QBackingStore *backingStore,
|
static inline void qt_flush(QWidget *widget, const QRegion ®ion, QBackingStore *backingStore,
|
||||||
QWidget *tlw, const QPoint &tlwOffset)
|
QWidget *tlw, const QPoint &tlwOffset, QPlatformTextureList *widgetTextures = 0,
|
||||||
|
QOpenGLContext *context = 0)
|
||||||
{
|
{
|
||||||
|
#ifdef QT_NO_OPENGL
|
||||||
|
Q_UNUSED(widgetTextures);
|
||||||
|
Q_UNUSED(context);
|
||||||
|
#endif
|
||||||
Q_ASSERT(widget);
|
Q_ASSERT(widget);
|
||||||
Q_ASSERT(!region.isEmpty());
|
Q_ASSERT(!region.isEmpty() || (context && widgetTextures && widgetTextures->count()));
|
||||||
Q_ASSERT(backingStore);
|
Q_ASSERT(backingStore);
|
||||||
Q_ASSERT(tlw);
|
Q_ASSERT(tlw);
|
||||||
|
|
||||||
@ -104,10 +111,16 @@ static inline void qt_flush(QWidget *widget, const QRegion ®ion, QBackingStor
|
|||||||
if (tlw->testAttribute(Qt::WA_DontShowOnScreen) || widget->testAttribute(Qt::WA_DontShowOnScreen))
|
if (tlw->testAttribute(Qt::WA_DontShowOnScreen) || widget->testAttribute(Qt::WA_DontShowOnScreen))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
QPoint offset = tlwOffset;
|
||||||
if (widget != tlw)
|
if (widget != tlw)
|
||||||
backingStore->flush(region, widget->windowHandle(), tlwOffset + widget->mapTo(tlw, QPoint()));
|
offset += widget->mapTo(tlw, QPoint());
|
||||||
|
|
||||||
|
#ifndef QT_NO_OPENGL
|
||||||
|
if (widgetTextures)
|
||||||
|
backingStore->handle()->composeAndFlush(widget->windowHandle(), region, offset, widgetTextures, context);
|
||||||
else
|
else
|
||||||
backingStore->flush(region, widget->windowHandle(), tlwOffset);
|
#endif
|
||||||
|
backingStore->flush(region, widget->windowHandle(), offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef QT_NO_PAINT_DEBUG
|
#ifndef QT_NO_PAINT_DEBUG
|
||||||
@ -430,7 +443,7 @@ QRegion QWidgetBackingStore::staticContents(QWidget *parent, const QRect &within
|
|||||||
return region;
|
return region;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void sendUpdateRequest(QWidget *widget, bool updateImmediately)
|
void QWidgetBackingStore::sendUpdateRequest(QWidget *widget, bool updateImmediately)
|
||||||
{
|
{
|
||||||
if (!widget)
|
if (!widget)
|
||||||
return;
|
return;
|
||||||
@ -439,6 +452,7 @@ static inline void sendUpdateRequest(QWidget *widget, bool updateImmediately)
|
|||||||
QEvent event(QEvent::UpdateRequest);
|
QEvent event(QEvent::UpdateRequest);
|
||||||
QApplication::sendEvent(widget, &event);
|
QApplication::sendEvent(widget, &event);
|
||||||
} else {
|
} else {
|
||||||
|
updateRequestSent = true;
|
||||||
QApplication::postEvent(widget, new QEvent(QEvent::UpdateRequest), Qt::LowEventPriority);
|
QApplication::postEvent(widget, new QEvent(QEvent::UpdateRequest), Qt::LowEventPriority);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -488,6 +502,7 @@ void QWidgetBackingStore::markDirty(const QRegion &rgn, QWidget *widget, bool up
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//### FIXME fullUpdatePending seems to be always false????
|
||||||
if (fullUpdatePending) {
|
if (fullUpdatePending) {
|
||||||
if (updateImmediately)
|
if (updateImmediately)
|
||||||
sendUpdateRequest(tlw, updateImmediately);
|
sendUpdateRequest(tlw, updateImmediately);
|
||||||
@ -495,6 +510,13 @@ void QWidgetBackingStore::markDirty(const QRegion &rgn, QWidget *widget, bool up
|
|||||||
}
|
}
|
||||||
|
|
||||||
const QPoint offset = widget->mapTo(tlw, QPoint());
|
const QPoint offset = widget->mapTo(tlw, QPoint());
|
||||||
|
|
||||||
|
if (QWidgetPrivate::get(widget)->renderToTexture) {
|
||||||
|
if (!updateRequestSent || updateImmediately)
|
||||||
|
sendUpdateRequest(tlw, updateImmediately);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
const QRect widgetRect = widget->d_func()->effectiveRectFor(widget->rect());
|
const QRect widgetRect = widget->d_func()->effectiveRectFor(widget->rect());
|
||||||
if (qt_region_strictContains(dirty, widgetRect.translated(offset))) {
|
if (qt_region_strictContains(dirty, widgetRect.translated(offset))) {
|
||||||
if (updateImmediately)
|
if (updateImmediately)
|
||||||
@ -503,7 +525,7 @@ void QWidgetBackingStore::markDirty(const QRegion &rgn, QWidget *widget, bool up
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (invalidateBuffer) {
|
if (invalidateBuffer) {
|
||||||
const bool eventAlreadyPosted = !dirty.isEmpty();
|
const bool eventAlreadyPosted = !dirty.isEmpty() || updateRequestSent;
|
||||||
#ifndef QT_NO_GRAPHICSEFFECT
|
#ifndef QT_NO_GRAPHICSEFFECT
|
||||||
if (widget->d_func()->graphicsEffect)
|
if (widget->d_func()->graphicsEffect)
|
||||||
dirty += widget->d_func()->effectiveRectFor(rgn.boundingRect()).translated(offset);
|
dirty += widget->d_func()->effectiveRectFor(rgn.boundingRect()).translated(offset);
|
||||||
@ -583,6 +605,13 @@ void QWidgetBackingStore::markDirty(const QRect &rect, QWidget *widget, bool upd
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (QWidgetPrivate::get(widget)->renderToTexture) {
|
||||||
|
if (!updateRequestSent || updateImmediately)
|
||||||
|
sendUpdateRequest(tlw, updateImmediately);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
const QRect widgetRect = widget->d_func()->effectiveRectFor(rect);
|
const QRect widgetRect = widget->d_func()->effectiveRectFor(rect);
|
||||||
const QRect translatedRect(widgetRect.translated(widget->mapTo(tlw, QPoint())));
|
const QRect translatedRect(widgetRect.translated(widget->mapTo(tlw, QPoint())));
|
||||||
if (qt_region_strictContains(dirty, translatedRect)) {
|
if (qt_region_strictContains(dirty, translatedRect)) {
|
||||||
@ -703,7 +732,11 @@ void QWidgetBackingStore::updateLists(QWidget *cur)
|
|||||||
}
|
}
|
||||||
|
|
||||||
QWidgetBackingStore::QWidgetBackingStore(QWidget *topLevel)
|
QWidgetBackingStore::QWidgetBackingStore(QWidget *topLevel)
|
||||||
: tlw(topLevel), dirtyOnScreenWidgets(0), fullUpdatePending(0)
|
: tlw(topLevel),
|
||||||
|
dirtyOnScreenWidgets(0),
|
||||||
|
widgetTextures(0),
|
||||||
|
fullUpdatePending(0),
|
||||||
|
updateRequestSent(0)
|
||||||
{
|
{
|
||||||
store = tlw->backingStore();
|
store = tlw->backingStore();
|
||||||
Q_ASSERT(store);
|
Q_ASSERT(store);
|
||||||
@ -902,7 +935,7 @@ void QWidgetBackingStore::sync(QWidget *exposedWidget, const QRegion &exposedReg
|
|||||||
|
|
||||||
// Nothing to repaint.
|
// Nothing to repaint.
|
||||||
if (!isDirty()) {
|
if (!isDirty()) {
|
||||||
qt_flush(exposedWidget, exposedRegion, store, tlw, tlwOffset);
|
qt_flush(exposedWidget, exposedRegion, store, tlw, tlwOffset, widgetTextures, tlw->d_func()->shareContext());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -914,11 +947,27 @@ void QWidgetBackingStore::sync(QWidget *exposedWidget, const QRegion &exposedReg
|
|||||||
doSync();
|
doSync();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifndef QT_NO_OPENGL
|
||||||
|
static void findTextureWidgetsRecursively(QWidget *tlw, QWidget *widget, QPlatformTextureList *widgetTextures)
|
||||||
|
{
|
||||||
|
QWidgetPrivate *wd = QWidgetPrivate::get(widget);
|
||||||
|
if (wd->renderToTexture)
|
||||||
|
widgetTextures->appendTexture(wd->textureId(), QRect(widget->mapTo(tlw, QPoint()), widget->size()));
|
||||||
|
|
||||||
|
for (int i = 0; i < wd->children.size(); ++i) {
|
||||||
|
QWidget *w = qobject_cast<QWidget *>(wd->children.at(i));
|
||||||
|
if (w && !w->isWindow() && !w->isHidden() && QWidgetPrivate::get(w)->textureChildSeen)
|
||||||
|
findTextureWidgetsRecursively(tlw, w, widgetTextures);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
Synchronizes the backing store, i.e. dirty areas are repainted and flushed.
|
Synchronizes the backing store, i.e. dirty areas are repainted and flushed.
|
||||||
*/
|
*/
|
||||||
void QWidgetBackingStore::sync()
|
void QWidgetBackingStore::sync()
|
||||||
{
|
{
|
||||||
|
updateRequestSent = false;
|
||||||
QTLWExtra *tlwExtra = tlw->d_func()->maybeTopData();
|
QTLWExtra *tlwExtra = tlw->d_func()->maybeTopData();
|
||||||
if (discardSyncRequest(tlw, tlwExtra)) {
|
if (discardSyncRequest(tlw, tlwExtra)) {
|
||||||
// If the top-level is minimized, it's not visible on the screen so we can delay the
|
// If the top-level is minimized, it's not visible on the screen so we can delay the
|
||||||
@ -1024,7 +1073,15 @@ void QWidgetBackingStore::doSync()
|
|||||||
}
|
}
|
||||||
dirtyWidgets.clear();
|
dirtyWidgets.clear();
|
||||||
|
|
||||||
|
#ifndef QT_NO_OPENGL
|
||||||
|
delete widgetTextures;
|
||||||
|
widgetTextures = 0;
|
||||||
|
if (tlw->d_func()->textureChildSeen) {
|
||||||
|
widgetTextures = new QPlatformTextureList; // TODO: implement support for locking
|
||||||
|
findTextureWidgetsRecursively(tlw, tlw, widgetTextures);
|
||||||
|
}
|
||||||
fullUpdatePending = false;
|
fullUpdatePending = false;
|
||||||
|
#endif
|
||||||
|
|
||||||
if (toClean.isEmpty()) {
|
if (toClean.isEmpty()) {
|
||||||
// Nothing to repaint. However, we might have newly exposed areas on the
|
// Nothing to repaint. However, we might have newly exposed areas on the
|
||||||
@ -1038,6 +1095,7 @@ void QWidgetBackingStore::doSync()
|
|||||||
if (tlw->d_func()->extra->proxyWidget) {
|
if (tlw->d_func()->extra->proxyWidget) {
|
||||||
updateStaticContentsSize();
|
updateStaticContentsSize();
|
||||||
dirty = QRegion();
|
dirty = QRegion();
|
||||||
|
updateRequestSent = false;
|
||||||
const QVector<QRect> rects(toClean.rects());
|
const QVector<QRect> rects(toClean.rects());
|
||||||
for (int i = 0; i < rects.size(); ++i)
|
for (int i = 0; i < rects.size(); ++i)
|
||||||
tlw->d_func()->extra->proxyWidget->update(rects.at(i));
|
tlw->d_func()->extra->proxyWidget->update(rects.at(i));
|
||||||
@ -1051,6 +1109,7 @@ void QWidgetBackingStore::doSync()
|
|||||||
for (int i = 0; i < opaqueNonOverlappedWidgets.size(); ++i)
|
for (int i = 0; i < opaqueNonOverlappedWidgets.size(); ++i)
|
||||||
resetWidget(opaqueNonOverlappedWidgets[i]);
|
resetWidget(opaqueNonOverlappedWidgets[i]);
|
||||||
dirty = QRegion();
|
dirty = QRegion();
|
||||||
|
updateRequestSent = false;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1059,6 +1118,7 @@ void QWidgetBackingStore::doSync()
|
|||||||
updateStaticContentsSize();
|
updateStaticContentsSize();
|
||||||
const QRegion dirtyCopy(dirty);
|
const QRegion dirtyCopy(dirty);
|
||||||
dirty = QRegion();
|
dirty = QRegion();
|
||||||
|
updateRequestSent = false;
|
||||||
|
|
||||||
// Paint opaque non overlapped widgets.
|
// Paint opaque non overlapped widgets.
|
||||||
for (int i = 0; i < opaqueNonOverlappedWidgets.size(); ++i) {
|
for (int i = 0; i < opaqueNonOverlappedWidgets.size(); ++i) {
|
||||||
@ -1099,12 +1159,19 @@ void QWidgetBackingStore::flush(QWidget *widget)
|
|||||||
{
|
{
|
||||||
if (!dirtyOnScreen.isEmpty()) {
|
if (!dirtyOnScreen.isEmpty()) {
|
||||||
QWidget *target = widget ? widget : tlw;
|
QWidget *target = widget ? widget : tlw;
|
||||||
qt_flush(target, dirtyOnScreen, store, tlw, tlwOffset);
|
qt_flush(target, dirtyOnScreen, store, tlw, tlwOffset, widgetTextures, tlw->d_func()->shareContext());
|
||||||
dirtyOnScreen = QRegion();
|
dirtyOnScreen = QRegion();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!dirtyOnScreenWidgets || dirtyOnScreenWidgets->isEmpty())
|
if (!dirtyOnScreenWidgets || dirtyOnScreenWidgets->isEmpty()) {
|
||||||
|
#ifndef QT_NO_OPENGL
|
||||||
|
if (widgetTextures && widgetTextures->count()) {
|
||||||
|
QWidget *target = widget ? widget : tlw;
|
||||||
|
qt_flush(target, QRegion(), store, tlw, tlwOffset, widgetTextures, tlw->d_func()->shareContext());
|
||||||
|
}
|
||||||
|
#endif
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
for (int i = 0; i < dirtyOnScreenWidgets->size(); ++i) {
|
for (int i = 0; i < dirtyOnScreenWidgets->size(); ++i) {
|
||||||
QWidget *w = dirtyOnScreenWidgets->at(i);
|
QWidget *w = dirtyOnScreenWidgets->at(i);
|
||||||
|
@ -60,6 +60,8 @@
|
|||||||
|
|
||||||
QT_BEGIN_NAMESPACE
|
QT_BEGIN_NAMESPACE
|
||||||
|
|
||||||
|
class QPlatformTextureList;
|
||||||
|
|
||||||
struct BeginPaintInfo {
|
struct BeginPaintInfo {
|
||||||
inline BeginPaintInfo() : wasFlushed(0), nothingToPaint(0), backingStoreRecreated(0) {}
|
inline BeginPaintInfo() : wasFlushed(0), nothingToPaint(0), backingStoreRecreated(0) {}
|
||||||
uint wasFlushed : 1;
|
uint wasFlushed : 1;
|
||||||
@ -102,11 +104,15 @@ private:
|
|||||||
QVector<QWidget *> dirtyWidgets;
|
QVector<QWidget *> dirtyWidgets;
|
||||||
QVector<QWidget *> *dirtyOnScreenWidgets;
|
QVector<QWidget *> *dirtyOnScreenWidgets;
|
||||||
QList<QWidget *> staticWidgets;
|
QList<QWidget *> staticWidgets;
|
||||||
|
QPlatformTextureList *widgetTextures;
|
||||||
QBackingStore *store;
|
QBackingStore *store;
|
||||||
uint fullUpdatePending : 1;
|
uint fullUpdatePending : 1;
|
||||||
|
uint updateRequestSent : 1;
|
||||||
|
|
||||||
QPoint tlwOffset;
|
QPoint tlwOffset;
|
||||||
|
|
||||||
|
void sendUpdateRequest(QWidget *widget, bool updateImmediately);
|
||||||
|
|
||||||
static bool flushPaint(QWidget *widget, const QRegion &rgn);
|
static bool flushPaint(QWidget *widget, const QRegion &rgn);
|
||||||
static void unflushPaint(QWidget *widget, const QRegion &rgn);
|
static void unflushPaint(QWidget *widget, const QRegion &rgn);
|
||||||
|
|
||||||
|
@ -92,6 +92,12 @@ QWidgetWindow::QWidgetWindow(QWidget *widget)
|
|||||||
, m_widget(widget)
|
, m_widget(widget)
|
||||||
{
|
{
|
||||||
updateObjectName();
|
updateObjectName();
|
||||||
|
// Enable QOpenGLWidget/QQuickWidget children if the platform plugin supports it,
|
||||||
|
// and the application developer has not explicitly disabled it.
|
||||||
|
if (QGuiApplicationPrivate::platformIntegration()->hasCapability(QPlatformIntegration::RasterGLSurface)
|
||||||
|
&& !QApplication::testAttribute(Qt::AA_ForceRasterWidgets)) {
|
||||||
|
setSurfaceType(QSurface::RasterGLSurface);
|
||||||
|
}
|
||||||
connect(m_widget, &QObject::objectNameChanged, this, &QWidgetWindow::updateObjectName);
|
connect(m_widget, &QObject::objectNameChanged, this, &QWidgetWindow::updateObjectName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
73
tests/manual/qopenglwidget/openglwidget/main.cpp
Normal file
73
tests/manual/qopenglwidget/openglwidget/main.cpp
Normal file
@ -0,0 +1,73 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
|
||||||
|
** Contact: http://www.qt-project.org/legal
|
||||||
|
**
|
||||||
|
** This file is part of the test suite of the Qt Toolkit.
|
||||||
|
**
|
||||||
|
** $QT_BEGIN_LICENSE:LGPL$
|
||||||
|
** Commercial License Usage
|
||||||
|
** Licensees holding valid commercial Qt licenses may use this file in
|
||||||
|
** accordance with the commercial license agreement provided with the
|
||||||
|
** Software or, alternatively, in accordance with the terms contained in
|
||||||
|
** a written agreement between you and Digia. For licensing terms and
|
||||||
|
** conditions see http://qt.digia.com/licensing. For further information
|
||||||
|
** use the contact form at http://qt.digia.com/contact-us.
|
||||||
|
**
|
||||||
|
** GNU Lesser General Public License Usage
|
||||||
|
** Alternatively, 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, Digia gives you certain additional
|
||||||
|
** rights. These rights are described in the Digia 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.
|
||||||
|
**
|
||||||
|
**
|
||||||
|
** $QT_END_LICENSE$
|
||||||
|
**
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#include "openglwidget.h"
|
||||||
|
#include <QApplication>
|
||||||
|
#include <QPushButton>
|
||||||
|
#include <QMdiArea>
|
||||||
|
#include <QLCDNumber>
|
||||||
|
#include <QTimer>
|
||||||
|
|
||||||
|
|
||||||
|
int main(int argc, char *argv[])
|
||||||
|
{
|
||||||
|
QApplication a(argc, argv);
|
||||||
|
|
||||||
|
QMdiArea w;
|
||||||
|
w.resize(400,400);
|
||||||
|
|
||||||
|
OpenGLWidget *glw = new OpenGLWidget;
|
||||||
|
w.addSubWindow(glw);
|
||||||
|
glw->setMinimumSize(100,100);
|
||||||
|
|
||||||
|
OpenGLWidget *glw2 = new OpenGLWidget;
|
||||||
|
glw2->setMinimumSize(100,100);
|
||||||
|
w.addSubWindow(glw2);
|
||||||
|
|
||||||
|
QLCDNumber *lcd = new QLCDNumber;
|
||||||
|
lcd->display(1337);
|
||||||
|
lcd->setMinimumSize(300,100);
|
||||||
|
w.addSubWindow(lcd);
|
||||||
|
|
||||||
|
w.show();
|
||||||
|
|
||||||
|
return a.exec();
|
||||||
|
}
|
193
tests/manual/qopenglwidget/openglwidget/openglwidget.cpp
Normal file
193
tests/manual/qopenglwidget/openglwidget/openglwidget.cpp
Normal file
@ -0,0 +1,193 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
|
||||||
|
** Contact: http://www.qt-project.org/legal
|
||||||
|
**
|
||||||
|
** This file is part of the test suite of the Qt Toolkit.
|
||||||
|
**
|
||||||
|
** $QT_BEGIN_LICENSE:LGPL$
|
||||||
|
** Commercial License Usage
|
||||||
|
** Licensees holding valid commercial Qt licenses may use this file in
|
||||||
|
** accordance with the commercial license agreement provided with the
|
||||||
|
** Software or, alternatively, in accordance with the terms contained in
|
||||||
|
** a written agreement between you and Digia. For licensing terms and
|
||||||
|
** conditions see http://qt.digia.com/licensing. For further information
|
||||||
|
** use the contact form at http://qt.digia.com/contact-us.
|
||||||
|
**
|
||||||
|
** GNU Lesser General Public License Usage
|
||||||
|
** Alternatively, 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, Digia gives you certain additional
|
||||||
|
** rights. These rights are described in the Digia 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.
|
||||||
|
**
|
||||||
|
**
|
||||||
|
** $QT_END_LICENSE$
|
||||||
|
**
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#define GL_GLEXT_PROTOTYPES
|
||||||
|
|
||||||
|
#include "openglwidget.h"
|
||||||
|
#include <QtWidgets/private/qwidget_p.h>
|
||||||
|
#include <QOpenGLFramebufferObject>
|
||||||
|
#include <QWindow>
|
||||||
|
#include <qpa/qplatformwindow.h>
|
||||||
|
#include <QDebug>
|
||||||
|
#include <QTimer>
|
||||||
|
|
||||||
|
#include <QtGui/QOpenGLFunctions>
|
||||||
|
#include <QtGui/QGuiApplication>
|
||||||
|
#include <QtGui/QMatrix4x4>
|
||||||
|
#include <QtGui/QOpenGLShaderProgram>
|
||||||
|
#include <QtGui/QScreen>
|
||||||
|
|
||||||
|
#include <QtCore/qmath.h>
|
||||||
|
#include <qopengl.h>
|
||||||
|
|
||||||
|
#include <GL/glext.h>
|
||||||
|
|
||||||
|
class OpenGLWidgetPrivate
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
OpenGLWidgetPrivate()
|
||||||
|
: m_program(0), m_frame(0)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void initialize();
|
||||||
|
void render();
|
||||||
|
|
||||||
|
|
||||||
|
int width() {return w;}
|
||||||
|
int height() {return h;}
|
||||||
|
|
||||||
|
GLuint m_posAttr;
|
||||||
|
GLuint m_colAttr;
|
||||||
|
GLuint m_matrixUniform;
|
||||||
|
|
||||||
|
QOpenGLShaderProgram *m_program;
|
||||||
|
int m_frame;
|
||||||
|
|
||||||
|
int w,h;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
OpenGLWidget::OpenGLWidget(QWidget *parent)
|
||||||
|
: QOpenGLWidget(parent)
|
||||||
|
{
|
||||||
|
d = new OpenGLWidgetPrivate;
|
||||||
|
QTimer *timer = new QTimer(this);
|
||||||
|
connect(timer, SIGNAL(timeout()), this, SLOT(updateGL()));
|
||||||
|
timer->start(30);
|
||||||
|
}
|
||||||
|
|
||||||
|
OpenGLWidget::~OpenGLWidget()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void OpenGLWidget::initializeGL()
|
||||||
|
{
|
||||||
|
// qDebug("*initializeGL*");
|
||||||
|
d->initialize();
|
||||||
|
}
|
||||||
|
|
||||||
|
void OpenGLWidget::resizeGL(int w, int h)
|
||||||
|
{
|
||||||
|
// qDebug("*resizeGL*");
|
||||||
|
d->w = w;
|
||||||
|
d->h = h;
|
||||||
|
}
|
||||||
|
void OpenGLWidget::paintGL()
|
||||||
|
{
|
||||||
|
// qDebug("*paintGL* %d", d->m_frame);
|
||||||
|
d->render();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static const char *vertexShaderSource =
|
||||||
|
"attribute highp vec4 posAttr;\n"
|
||||||
|
"attribute lowp vec4 colAttr;\n"
|
||||||
|
"varying lowp vec4 col;\n"
|
||||||
|
"uniform highp mat4 matrix;\n"
|
||||||
|
"void main() {\n"
|
||||||
|
" col = colAttr;\n"
|
||||||
|
" gl_Position = matrix * posAttr;\n"
|
||||||
|
"}\n";
|
||||||
|
|
||||||
|
static const char *fragmentShaderSource =
|
||||||
|
"varying lowp vec4 col;\n"
|
||||||
|
"void main() {\n"
|
||||||
|
" gl_FragColor = col;\n"
|
||||||
|
"}\n";
|
||||||
|
|
||||||
|
void OpenGLWidgetPrivate::initialize()
|
||||||
|
{
|
||||||
|
m_program = new QOpenGLShaderProgram;
|
||||||
|
m_program->addShaderFromSourceCode(QOpenGLShader::Vertex, vertexShaderSource);
|
||||||
|
m_program->addShaderFromSourceCode(QOpenGLShader::Fragment, fragmentShaderSource);
|
||||||
|
m_program->link();
|
||||||
|
m_posAttr = m_program->attributeLocation("posAttr");
|
||||||
|
m_colAttr = m_program->attributeLocation("colAttr");
|
||||||
|
m_matrixUniform = m_program->uniformLocation("matrix");
|
||||||
|
}
|
||||||
|
|
||||||
|
void OpenGLWidgetPrivate::render()
|
||||||
|
{
|
||||||
|
const qreal retinaScale = 1.0;//devicePixelRatio();
|
||||||
|
glViewport(0, 0, width() * retinaScale, height() * retinaScale);
|
||||||
|
|
||||||
|
glClearColor(0.0, 0.0, 0.0, 1.0);
|
||||||
|
glClear(GL_COLOR_BUFFER_BIT);
|
||||||
|
|
||||||
|
m_program->bind();
|
||||||
|
|
||||||
|
QMatrix4x4 matrix;
|
||||||
|
matrix.perspective(60, 4.0/3.0, 0.1, 100.0);
|
||||||
|
matrix.translate(0, 0, -2);
|
||||||
|
matrix.rotate(100.0f * m_frame / 30/*screen()->refreshRate()*/, 0, 1, 0);
|
||||||
|
|
||||||
|
m_program->setUniformValue(m_matrixUniform, matrix);
|
||||||
|
|
||||||
|
GLfloat vertices[] = {
|
||||||
|
0.0f, 0.707f,
|
||||||
|
-0.5f, -0.5f,
|
||||||
|
0.5f, -0.5f
|
||||||
|
};
|
||||||
|
|
||||||
|
GLfloat colors[] = {
|
||||||
|
1.0f, 0.0f, 0.0f,
|
||||||
|
0.0f, 1.0f, 0.0f,
|
||||||
|
0.0f, 0.0f, 1.0f
|
||||||
|
};
|
||||||
|
|
||||||
|
glVertexAttribPointer(m_posAttr, 2, GL_FLOAT, GL_FALSE, 0, vertices);
|
||||||
|
glVertexAttribPointer(m_colAttr, 3, GL_FLOAT, GL_FALSE, 0, colors);
|
||||||
|
|
||||||
|
glEnableVertexAttribArray(0);
|
||||||
|
glEnableVertexAttribArray(1);
|
||||||
|
|
||||||
|
glDrawArrays(GL_TRIANGLES, 0, 3);
|
||||||
|
|
||||||
|
glDisableVertexAttribArray(1);
|
||||||
|
glDisableVertexAttribArray(0);
|
||||||
|
|
||||||
|
m_program->release();
|
||||||
|
|
||||||
|
++m_frame;
|
||||||
|
}
|
63
tests/manual/qopenglwidget/openglwidget/openglwidget.h
Normal file
63
tests/manual/qopenglwidget/openglwidget/openglwidget.h
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
|
||||||
|
** Contact: http://www.qt-project.org/legal
|
||||||
|
**
|
||||||
|
** This file is part of the test suite of the Qt Toolkit.
|
||||||
|
**
|
||||||
|
** $QT_BEGIN_LICENSE:LGPL$
|
||||||
|
** Commercial License Usage
|
||||||
|
** Licensees holding valid commercial Qt licenses may use this file in
|
||||||
|
** accordance with the commercial license agreement provided with the
|
||||||
|
** Software or, alternatively, in accordance with the terms contained in
|
||||||
|
** a written agreement between you and Digia. For licensing terms and
|
||||||
|
** conditions see http://qt.digia.com/licensing. For further information
|
||||||
|
** use the contact form at http://qt.digia.com/contact-us.
|
||||||
|
**
|
||||||
|
** GNU Lesser General Public License Usage
|
||||||
|
** Alternatively, 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, Digia gives you certain additional
|
||||||
|
** rights. These rights are described in the Digia 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.
|
||||||
|
**
|
||||||
|
**
|
||||||
|
** $QT_END_LICENSE$
|
||||||
|
**
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#ifndef OPENGLWIDGET_H
|
||||||
|
#define OPENGLWIDGET_H
|
||||||
|
|
||||||
|
#include <QtWidgets/private/qopenglwidget_p.h>
|
||||||
|
|
||||||
|
class OpenGLWidgetPrivate;
|
||||||
|
class OpenGLWidget : public QOpenGLWidget
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
OpenGLWidget(QWidget *parent = 0);
|
||||||
|
~OpenGLWidget();
|
||||||
|
|
||||||
|
void initializeGL();
|
||||||
|
void resizeGL(int w, int h);
|
||||||
|
void paintGL();
|
||||||
|
|
||||||
|
private:
|
||||||
|
OpenGLWidgetPrivate *d;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // OPENGLWIDGET_H
|
9
tests/manual/qopenglwidget/openglwidget/openglwidget.pro
Normal file
9
tests/manual/qopenglwidget/openglwidget/openglwidget.pro
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
QT += widgets widgets-private gui-private core-private
|
||||||
|
|
||||||
|
TARGET = openglwidget
|
||||||
|
TEMPLATE = app
|
||||||
|
|
||||||
|
SOURCES += main.cpp \
|
||||||
|
openglwidget.cpp
|
||||||
|
|
||||||
|
HEADERS += openglwidget.h
|
Loading…
Reference in New Issue
Block a user