qpa: Merge qgl_qpa.cpp into qgl.cpp

Change-Id: I91cfd7daf7f1dd88659019ccc671ec0d9245067f
Reviewed-by: Paul Olav Tvete <paul.tvete@digia.com>
This commit is contained in:
Tor Arne Vestbø 2014-05-12 15:19:49 +02:00 committed by The Qt Project
parent a5ea74b98b
commit 768f59202d
3 changed files with 387 additions and 476 deletions

View File

@ -53,5 +53,3 @@ SOURCES += qglshaderprogram.cpp \
gl2paintengineex/qpaintengineex_opengl2.cpp \
gl2paintengineex/qglcustomshaderstage.cpp \
gl2paintengineex/qtextureglyphcache_gl.cpp
SOURCES += qgl_qpa.cpp

View File

@ -70,6 +70,11 @@
#include "qlibrary.h"
#include <qmutex.h>
#include "qsurfaceformat.h"
#include <private/qapplication_p.h>
#include <qpa/qplatformopenglcontext.h>
#include <qpa/qplatformwindow.h>
#ifndef QT_OPENGL_ES_2
#include <qopenglfunctions_1_1.h>
#endif
@ -438,6 +443,80 @@ QGLFormat::~QGLFormat()
delete d;
}
/*!
Returns an OpenGL format for the window format specified by \a format.
*/
QGLFormat QGLFormat::fromSurfaceFormat(const QSurfaceFormat &format)
{
QGLFormat retFormat;
if (format.alphaBufferSize() >= 0)
retFormat.setAlphaBufferSize(format.alphaBufferSize());
if (format.blueBufferSize() >= 0)
retFormat.setBlueBufferSize(format.blueBufferSize());
if (format.greenBufferSize() >= 0)
retFormat.setGreenBufferSize(format.greenBufferSize());
if (format.redBufferSize() >= 0)
retFormat.setRedBufferSize(format.redBufferSize());
if (format.depthBufferSize() >= 0)
retFormat.setDepthBufferSize(format.depthBufferSize());
if (format.samples() > 1) {
retFormat.setSampleBuffers(true);
retFormat.setSamples(format.samples());
}
if (format.stencilBufferSize() > 0) {
retFormat.setStencil(true);
retFormat.setStencilBufferSize(format.stencilBufferSize());
}
retFormat.setDoubleBuffer(format.swapBehavior() != QSurfaceFormat::SingleBuffer);
retFormat.setStereo(format.stereo());
retFormat.setVersion(format.majorVersion(), format.minorVersion());
retFormat.setProfile(static_cast<QGLFormat::OpenGLContextProfile>(format.profile()));
return retFormat;
}
/*!
Returns a window format for the OpenGL format specified by \a format.
*/
QSurfaceFormat QGLFormat::toSurfaceFormat(const QGLFormat &format)
{
QSurfaceFormat retFormat;
if (format.alpha())
retFormat.setAlphaBufferSize(format.alphaBufferSize() == -1 ? 1 : format.alphaBufferSize());
if (format.blueBufferSize() >= 0)
retFormat.setBlueBufferSize(format.blueBufferSize());
if (format.greenBufferSize() >= 0)
retFormat.setGreenBufferSize(format.greenBufferSize());
if (format.redBufferSize() >= 0)
retFormat.setRedBufferSize(format.redBufferSize());
if (format.depth())
retFormat.setDepthBufferSize(format.depthBufferSize() == -1 ? 1 : format.depthBufferSize());
retFormat.setSwapBehavior(format.doubleBuffer() ? QSurfaceFormat::DoubleBuffer : QSurfaceFormat::SingleBuffer);
if (format.sampleBuffers())
retFormat.setSamples(format.samples() == -1 ? 4 : format.samples());
if (format.stencil())
retFormat.setStencilBufferSize(format.stencilBufferSize() == -1 ? 1 : format.stencilBufferSize());
retFormat.setStereo(format.stereo());
retFormat.setMajorVersion(format.majorVersion());
retFormat.setMinorVersion(format.minorVersion());
retFormat.setProfile(static_cast<QSurfaceFormat::OpenGLContextProfile>(format.profile()));
// QGLFormat has no way to set DeprecatedFunctions, that is, to tell that forward
// compatibility should not be requested. Some drivers fail to ignore the fwdcompat
// bit with compatibility profiles so make sure it is not set.
if (format.profile() == QGLFormat::CompatibilityProfile)
retFormat.setOption(QSurfaceFormat::DeprecatedFunctions);
return retFormat;
}
void QGLContextPrivate::setupSharing() {
Q_Q(QGLContext);
QOpenGLContext *sharedContext = guiGlContext->shareContext();
if (sharedContext) {
QGLContext *actualSharedContext = QGLContext::fromOpenGLContext(sharedContext);
sharing = true;
QGLContextGroup::addShare(q, actualSharedContext);
}
}
/*!
\fn bool QGLFormat::doubleBuffer() const
@ -1132,8 +1211,11 @@ QGLFormat::OpenGLContextProfile QGLFormat::profile() const
\warning This function must not be called until the QApplication
object has been created.
*/
bool QGLFormat::hasOpenGL()
{
return QApplicationPrivate::platformIntegration()
->hasCapability(QPlatformIntegration::OpenGL);
}
/*!
\fn bool QGLFormat::hasOpenGLOverlays()
@ -1144,6 +1226,10 @@ QGLFormat::OpenGLContextProfile QGLFormat::profile() const
\warning This function must not be called until the QApplication
object has been created.
*/
bool QGLFormat::hasOpenGLOverlays()
{
return false;
}
QGLFormat::OpenGLVersionFlags Q_AUTOTEST_EXPORT qOpenGLVersionFlagsFromString(const QString &versionString)
{
@ -1649,6 +1735,60 @@ void QGLContextPrivate::init(QPaintDevice *dev, const QGLFormat &format)
QGLContext* QGLContext::currentCtx = 0;
/*
QGLTemporaryContext implementation
*/
class QGLTemporaryContextPrivate
{
public:
QWindow *window;
QOpenGLContext *context;
QGLContext *oldContext;
};
QGLTemporaryContext::QGLTemporaryContext(bool, QWidget *)
: d(new QGLTemporaryContextPrivate)
{
d->oldContext = const_cast<QGLContext *>(QGLContext::currentContext());
d->window = new QWindow;
d->window->setSurfaceType(QWindow::OpenGLSurface);
d->window->setGeometry(QRect(0, 0, 3, 3));
d->window->create();
d->context = new QOpenGLContext;
#if !defined(QT_OPENGL_ES)
if (QOpenGLContext::openGLModuleType() == QOpenGLContext::LibGL) {
// On desktop, request latest released version
QSurfaceFormat format;
#if defined(Q_OS_MAC)
// OS X is limited to OpenGL 3.2 Core Profile at present
// so set that here. If we use compatibility profile it
// only reports 2.x contexts.
format.setMajorVersion(3);
format.setMinorVersion(2);
format.setProfile(QSurfaceFormat::CoreProfile);
#else
format.setMajorVersion(4);
format.setMinorVersion(3);
#endif
d->context->setFormat(format);
}
#endif // QT_OPENGL_ES
d->context->create();
d->context->makeCurrent(d->window);
}
QGLTemporaryContext::~QGLTemporaryContext()
{
if (d->oldContext)
d->oldContext->makeCurrent();
delete d->context;
delete d->window;
}
/*
Read back the contents of the currently bound framebuffer, used in
QGLWidget::grabFrameBuffer(), QGLPixelbuffer::toImage() and
@ -2000,6 +2140,47 @@ QGLContext::QGLContext(const QGLFormat &format)
d->init(0, format);
}
void qDeleteQGLContext(void *handle)
{
QGLContext *context = static_cast<QGLContext *>(handle);
delete context;
}
QGLContext::QGLContext(QOpenGLContext *context)
: d_ptr(new QGLContextPrivate(this))
{
Q_D(QGLContext);
d->init(0, QGLFormat::fromSurfaceFormat(context->format()));
d->guiGlContext = context;
d->guiGlContext->setQGLContextHandle(this, qDeleteQGLContext);
d->ownContext = false;
d->valid = context->isValid();
d->setupSharing();
}
QOpenGLContext *QGLContext::contextHandle() const
{
Q_D(const QGLContext);
return d->guiGlContext;
}
/*!
Returns a OpenGL context for the window context specified by the \a context
parameter.
*/
QGLContext *QGLContext::fromOpenGLContext(QOpenGLContext *context)
{
if (!context)
return 0;
if (context->qGLContextHandle()) {
return reinterpret_cast<QGLContext *>(context->qGLContextHandle());
}
QGLContext *glContext = new QGLContext(context);
//Don't call create on context. This can cause the platformFormat to be set on the widget, which
//will cause the platformWindow to be recreated.
return glContext;
}
/*!
Destroys the OpenGL context and frees its resources.
*/
@ -3059,7 +3240,10 @@ bool QGLContext::areSharing(const QGLContext *context1, const QGLContext *contex
Returns a colormap index for the color c, in ColorIndex mode. Used
by qglColor() and qglClearColor().
*/
uint QGLContext::colorIndex(const QColor&) const
{
return 0;
}
/*!
\fn bool QGLContext::initialized() const
@ -3107,7 +3291,10 @@ bool QGLContext::areSharing(const QGLContext *context1, const QGLContext *contex
also be used to draw transparent graphics with a QPainter. See the
examples/opengl/overlay_x11 example for details.
*/
QColor QGLContext::overlayTransparentColor() const
{
return QColor(); // Invalid color
}
/*!
Creates the GL context. Returns \c true if it was successful in
@ -3267,6 +3454,51 @@ void QGLContext::moveToThread(QThread *thread)
the virtual function chooseVisual() which finds an appropriate X
visual. On other platforms it may work differently.
*/
bool QGLContext::chooseContext(const QGLContext* shareContext)
{
Q_D(QGLContext);
if(!d->paintDevice || d->paintDevice->devType() != QInternal::Widget) {
// Unlike in Qt 4, the only possible target is a widget backed by an OpenGL-based
// QWindow. Pixmaps in particular are not supported anymore as paint devices since
// starting from Qt 5 QPixmap is raster-backed on almost all platforms.
d->valid = false;
}else {
QWidget *widget = static_cast<QWidget *>(d->paintDevice);
QGLFormat glformat = format();
QSurfaceFormat winFormat = QGLFormat::toSurfaceFormat(glformat);
if (widget->testAttribute(Qt::WA_TranslucentBackground))
winFormat.setAlphaBufferSize(qMax(winFormat.alphaBufferSize(), 8));
QWindow *window = widget->windowHandle();
if (!window->handle()
|| window->surfaceType() != QWindow::OpenGLSurface
|| window->requestedFormat() != winFormat)
{
window->setSurfaceType(QWindow::OpenGLSurface);
window->setFormat(winFormat);
window->destroy();
window->create();
}
if (d->ownContext)
delete d->guiGlContext;
d->ownContext = true;
QOpenGLContext *shareGlContext = shareContext ? shareContext->d_func()->guiGlContext : 0;
d->guiGlContext = new QOpenGLContext;
d->guiGlContext->setFormat(winFormat);
d->guiGlContext->setShareContext(shareGlContext);
d->valid = d->guiGlContext->create();
if (d->valid)
d->guiGlContext->setQGLContextHandle(this, qDeleteQGLContext);
d->glFormat = QGLFormat::fromSurfaceFormat(d->guiGlContext->format());
d->setupSharing();
}
return d->valid;
}
/*!
\fn void QGLContext::reset()
@ -3275,7 +3507,33 @@ void QGLContext::moveToThread(QThread *thread)
\sa create(), isValid()
*/
void QGLContext::reset()
{
Q_D(QGLContext);
if (!d->valid)
return;
d->cleanup();
d->crWin = false;
d->sharing = false;
d->valid = false;
d->transpColor = QColor();
d->initDone = false;
QGLContextGroup::removeShare(this);
if (d->guiGlContext) {
if (QOpenGLContext::currentContext() == d->guiGlContext)
doneCurrent();
if (d->ownContext) {
if (d->guiGlContext->thread() == QThread::currentThread())
delete d->guiGlContext;
else
d->guiGlContext->deleteLater();
} else
d->guiGlContext->setQGLContextHandle(0,0);
d->guiGlContext = 0;
}
d->ownContext = false;
}
/*!
\fn void QGLContext::makeCurrent()
@ -3291,7 +3549,26 @@ void QGLContext::moveToThread(QThread *thread)
make sure you've first pushed the context to the relevant thread
from the UI thread using moveToThread().
*/
void QGLContext::makeCurrent()
{
Q_D(QGLContext);
if (!d->paintDevice || d->paintDevice->devType() != QInternal::Widget)
return;
QWidget *widget = static_cast<QWidget *>(d->paintDevice);
if (!widget->windowHandle())
return;
if (d->guiGlContext->makeCurrent(widget->windowHandle())) {
if (!d->workaroundsCached) {
d->workaroundsCached = true;
const char *renderer = reinterpret_cast<const char *>(d->guiGlContext->functions()->glGetString(GL_RENDERER));
if (renderer && strstr(renderer, "Mali")) {
d->workaround_brokenFBOReadBack = true;
}
}
}
}
/*!
\fn void QGLContext::swapBuffers() const
@ -3299,7 +3576,18 @@ void QGLContext::moveToThread(QThread *thread)
Call this to finish a frame of OpenGL rendering, and make sure to
call makeCurrent() again before you begin a new frame.
*/
void QGLContext::swapBuffers() const
{
Q_D(const QGLContext);
if (!d->paintDevice || d->paintDevice->devType() != QInternal::Widget)
return;
QWidget *widget = static_cast<QWidget *>(d->paintDevice);
if (!widget->windowHandle())
return;
d->guiGlContext->swapBuffers(widget->windowHandle());
}
/*!
\fn void QGLContext::doneCurrent()
@ -3307,7 +3595,11 @@ void QGLContext::moveToThread(QThread *thread)
Makes no GL context the current context. Normally, you do not need
to call this function; QGLContext calls it as necessary.
*/
void QGLContext::doneCurrent()
{
Q_D(QGLContext);
d->guiGlContext->doneCurrent();
}
/*!
\fn QPaintDevice* QGLContext::device() const
@ -3317,7 +3609,6 @@ void QGLContext::moveToThread(QThread *thread)
\sa QGLContext::QGLContext()
*/
/*****************************************************************************
QGLWidget implementation
*****************************************************************************/
@ -3716,6 +4007,11 @@ QGLWidget::~QGLWidget()
\a proc. 0 is returned if a pointer to the function could not be
obtained.
*/
QFunctionPointer QGLContext::getProcAddress(const QString &procName) const
{
Q_D(const QGLContext);
return d->guiGlContext->getProcAddress(procName.toLatin1());
}
/*!
\fn bool QGLWidget::isValid() const
@ -3803,8 +4099,10 @@ void QGLWidget::swapBuffers()
\sa context()
*/
const QGLContext* QGLWidget::overlayContext() const
{
return 0;
}
/*!
\fn void QGLWidget::makeOverlayCurrent()
@ -3817,7 +4115,9 @@ void QGLWidget::swapBuffers()
\sa makeCurrent()
*/
void QGLWidget::makeOverlayCurrent()
{
}
/*!
\obsolete
@ -3893,8 +4193,28 @@ void QGLWidget::setFormat(const QGLFormat &format)
\sa context(), isSharing()
*/
void QGLWidget::setContext(QGLContext *context,
const QGLContext* shareContext,
bool deleteOldContext)
{
Q_D(QGLWidget);
if (context == 0) {
qWarning("QGLWidget::setContext: Cannot set null context");
return;
}
if (context->device() == 0) // a context may refere to more than 1 window.
context->setDevice(this); //but its better to point to 1 of them than none of them.
QGLContext* oldcx = d->glcx;
d->glcx = context;
if (!d->glcx->isValid())
d->glcx->create(shareContext ? shareContext : oldcx);
if (deleteOldContext)
delete oldcx;
}
/*!
\fn void QGLWidget::updateGL()
@ -3920,7 +4240,9 @@ void QGLWidget::updateGL()
The widget's rendering context will become the current context and
initializeGL() will be called if it hasn't already been called.
*/
void QGLWidget::updateOverlayGL()
{
}
/*!
This virtual function is called once before the first call to
@ -4022,6 +4344,20 @@ void QGLWidget::resizeOverlayGL(int, int)
{
}
bool QGLWidget::event(QEvent *e)
{
Q_D(QGLWidget);
// A re-parent will destroy the window and re-create it. We should not reset the context while it happens.
if (e->type() == QEvent::ParentAboutToChange)
d->parent_changing = true;
if (e->type() == QEvent::ParentChange)
d->parent_changing = false;
return QWidget::event(e);
}
/*!
\fn void QGLWidget::paintEvent(QPaintEvent *event)
@ -4047,7 +4383,21 @@ void QGLWidget::paintEvent(QPaintEvent *)
Handles resize events that are passed in the \a event parameter.
Calls the virtual function resizeGL().
*/
void QGLWidget::resizeEvent(QResizeEvent *e)
{
Q_D(QGLWidget);
QWidget::resizeEvent(e);
if (!isValid())
return;
makeCurrent();
if (!d->glcx->initialized())
glInit();
const qreal scaleFactor = (window() && window()->windowHandle()) ?
window()->windowHandle()->devicePixelRatio() : 1.0;
resizeGL(width() * scaleFactor, height() * scaleFactor);
}
/*!
Renders the current scene on a pixmap and returns the pixmap.
@ -4333,6 +4683,11 @@ QImage QGLWidget::convertToGLFormat(const QImage& img)
\sa setColormap(), QGLColormap::isEmpty()
*/
const QGLColormap & QGLWidget::colormap() const
{
Q_D(const QGLWidget);
return d->cmap;
}
/*!
\fn void QGLWidget::setColormap(const QGLColormap & cmap)
@ -4342,6 +4697,10 @@ QImage QGLWidget::convertToGLFormat(const QImage& img)
\sa colormap()
*/
void QGLWidget::setColormap(const QGLColormap & c)
{
Q_UNUSED(c);
}
#ifndef QT_OPENGL_ES
@ -4767,6 +5126,11 @@ QPaintEngine *QGLWidget::paintEngine() const
return qt_qgl_paint_engine();
}
void QGLWidgetPrivate::init(QGLContext *context, const QGLWidget *shareWidget)
{
initContext(context, shareWidget);
}
/*
This is the shared initialization for all platforms. Called from QGLWidgetPrivate::init()
*/
@ -4787,6 +5151,19 @@ void QGLWidgetPrivate::initContext(QGLContext *context, const QGLWidget* shareWi
glcx = new QGLContext(QGLFormat::defaultFormat(), q);
}
bool QGLWidgetPrivate::renderCxPm(QPixmap*)
{
return false;
}
/*! \internal
Free up any allocated colormaps. This fn is only called for
top-level widgets.
*/
void QGLWidgetPrivate::cleanupColormaps()
{
}
Q_GLOBAL_STATIC(QString, qt_gl_lib_name)
void qt_set_gl_library_name(const QString& name)

View File

@ -1,464 +0,0 @@
/****************************************************************************
**
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the QtOpenGL 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 <QApplication>
#include <private/qapplication_p.h>
#include <QPixmap>
#include <QDebug>
#include <qpa/qplatformopenglcontext.h>
#include <qpa/qplatformwindow.h>
#include <QtGui/QSurfaceFormat>
#include "qgl.h"
#include "qgl_p.h"
QT_BEGIN_NAMESPACE
/*!
Returns an OpenGL format for the window format specified by \a format.
*/
QGLFormat QGLFormat::fromSurfaceFormat(const QSurfaceFormat &format)
{
QGLFormat retFormat;
if (format.alphaBufferSize() >= 0)
retFormat.setAlphaBufferSize(format.alphaBufferSize());
if (format.blueBufferSize() >= 0)
retFormat.setBlueBufferSize(format.blueBufferSize());
if (format.greenBufferSize() >= 0)
retFormat.setGreenBufferSize(format.greenBufferSize());
if (format.redBufferSize() >= 0)
retFormat.setRedBufferSize(format.redBufferSize());
if (format.depthBufferSize() >= 0)
retFormat.setDepthBufferSize(format.depthBufferSize());
if (format.samples() > 1) {
retFormat.setSampleBuffers(true);
retFormat.setSamples(format.samples());
}
if (format.stencilBufferSize() > 0) {
retFormat.setStencil(true);
retFormat.setStencilBufferSize(format.stencilBufferSize());
}
retFormat.setDoubleBuffer(format.swapBehavior() != QSurfaceFormat::SingleBuffer);
retFormat.setStereo(format.stereo());
retFormat.setVersion(format.majorVersion(), format.minorVersion());
retFormat.setProfile(static_cast<QGLFormat::OpenGLContextProfile>(format.profile()));
return retFormat;
}
/*!
Returns a window format for the OpenGL format specified by \a format.
*/
QSurfaceFormat QGLFormat::toSurfaceFormat(const QGLFormat &format)
{
QSurfaceFormat retFormat;
if (format.alpha())
retFormat.setAlphaBufferSize(format.alphaBufferSize() == -1 ? 1 : format.alphaBufferSize());
if (format.blueBufferSize() >= 0)
retFormat.setBlueBufferSize(format.blueBufferSize());
if (format.greenBufferSize() >= 0)
retFormat.setGreenBufferSize(format.greenBufferSize());
if (format.redBufferSize() >= 0)
retFormat.setRedBufferSize(format.redBufferSize());
if (format.depth())
retFormat.setDepthBufferSize(format.depthBufferSize() == -1 ? 1 : format.depthBufferSize());
retFormat.setSwapBehavior(format.doubleBuffer() ? QSurfaceFormat::DoubleBuffer : QSurfaceFormat::SingleBuffer);
if (format.sampleBuffers())
retFormat.setSamples(format.samples() == -1 ? 4 : format.samples());
if (format.stencil())
retFormat.setStencilBufferSize(format.stencilBufferSize() == -1 ? 1 : format.stencilBufferSize());
retFormat.setStereo(format.stereo());
retFormat.setMajorVersion(format.majorVersion());
retFormat.setMinorVersion(format.minorVersion());
retFormat.setProfile(static_cast<QSurfaceFormat::OpenGLContextProfile>(format.profile()));
// QGLFormat has no way to set DeprecatedFunctions, that is, to tell that forward
// compatibility should not be requested. Some drivers fail to ignore the fwdcompat
// bit with compatibility profiles so make sure it is not set.
if (format.profile() == QGLFormat::CompatibilityProfile)
retFormat.setOption(QSurfaceFormat::DeprecatedFunctions);
return retFormat;
}
void QGLContextPrivate::setupSharing() {
Q_Q(QGLContext);
QOpenGLContext *sharedContext = guiGlContext->shareContext();
if (sharedContext) {
QGLContext *actualSharedContext = QGLContext::fromOpenGLContext(sharedContext);
sharing = true;
QGLContextGroup::addShare(q, actualSharedContext);
}
}
bool QGLFormat::hasOpenGL()
{
return QApplicationPrivate::platformIntegration()
->hasCapability(QPlatformIntegration::OpenGL);
}
void qDeleteQGLContext(void *handle)
{
QGLContext *context = static_cast<QGLContext *>(handle);
delete context;
}
bool QGLContext::chooseContext(const QGLContext* shareContext)
{
Q_D(QGLContext);
if(!d->paintDevice || d->paintDevice->devType() != QInternal::Widget) {
// Unlike in Qt 4, the only possible target is a widget backed by an OpenGL-based
// QWindow. Pixmaps in particular are not supported anymore as paint devices since
// starting from Qt 5 QPixmap is raster-backed on almost all platforms.
d->valid = false;
}else {
QWidget *widget = static_cast<QWidget *>(d->paintDevice);
QGLFormat glformat = format();
QSurfaceFormat winFormat = QGLFormat::toSurfaceFormat(glformat);
if (widget->testAttribute(Qt::WA_TranslucentBackground))
winFormat.setAlphaBufferSize(qMax(winFormat.alphaBufferSize(), 8));
QWindow *window = widget->windowHandle();
if (!window->handle()
|| window->surfaceType() != QWindow::OpenGLSurface
|| window->requestedFormat() != winFormat)
{
window->setSurfaceType(QWindow::OpenGLSurface);
window->setFormat(winFormat);
window->destroy();
window->create();
}
if (d->ownContext)
delete d->guiGlContext;
d->ownContext = true;
QOpenGLContext *shareGlContext = shareContext ? shareContext->d_func()->guiGlContext : 0;
d->guiGlContext = new QOpenGLContext;
d->guiGlContext->setFormat(winFormat);
d->guiGlContext->setShareContext(shareGlContext);
d->valid = d->guiGlContext->create();
if (d->valid)
d->guiGlContext->setQGLContextHandle(this,qDeleteQGLContext);
d->glFormat = QGLFormat::fromSurfaceFormat(d->guiGlContext->format());
d->setupSharing();
}
return d->valid;
}
void QGLContext::reset()
{
Q_D(QGLContext);
if (!d->valid)
return;
d->cleanup();
d->crWin = false;
d->sharing = false;
d->valid = false;
d->transpColor = QColor();
d->initDone = false;
QGLContextGroup::removeShare(this);
if (d->guiGlContext) {
if (QOpenGLContext::currentContext() == d->guiGlContext)
doneCurrent();
if (d->ownContext) {
if (d->guiGlContext->thread() == QThread::currentThread())
delete d->guiGlContext;
else
d->guiGlContext->deleteLater();
} else
d->guiGlContext->setQGLContextHandle(0,0);
d->guiGlContext = 0;
}
d->ownContext = false;
}
void QGLContext::makeCurrent()
{
Q_D(QGLContext);
if (!d->paintDevice || d->paintDevice->devType() != QInternal::Widget)
return;
QWidget *widget = static_cast<QWidget *>(d->paintDevice);
if (!widget->windowHandle())
return;
if (d->guiGlContext->makeCurrent(widget->windowHandle())) {
if (!d->workaroundsCached) {
d->workaroundsCached = true;
const char *renderer = reinterpret_cast<const char *>(d->guiGlContext->functions()->glGetString(GL_RENDERER));
if (renderer && strstr(renderer, "Mali")) {
d->workaround_brokenFBOReadBack = true;
}
}
}
}
void QGLContext::doneCurrent()
{
Q_D(QGLContext);
d->guiGlContext->doneCurrent();
}
void QGLContext::swapBuffers() const
{
Q_D(const QGLContext);
if (!d->paintDevice || d->paintDevice->devType() != QInternal::Widget)
return;
QWidget *widget = static_cast<QWidget *>(d->paintDevice);
if (!widget->windowHandle())
return;
d->guiGlContext->swapBuffers(widget->windowHandle());
}
QFunctionPointer QGLContext::getProcAddress(const QString &procName) const
{
Q_D(const QGLContext);
return d->guiGlContext->getProcAddress(procName.toLatin1());
}
void QGLWidget::setContext(QGLContext *context,
const QGLContext* shareContext,
bool deleteOldContext)
{
Q_D(QGLWidget);
if (context == 0) {
qWarning("QGLWidget::setContext: Cannot set null context");
return;
}
if (context->device() == 0) // a context may refere to more than 1 window.
context->setDevice(this); //but its better to point to 1 of them than none of them.
QGLContext* oldcx = d->glcx;
d->glcx = context;
if (!d->glcx->isValid())
d->glcx->create(shareContext ? shareContext : oldcx);
if (deleteOldContext)
delete oldcx;
}
void QGLWidgetPrivate::init(QGLContext *context, const QGLWidget *shareWidget)
{
initContext(context, shareWidget);
}
bool QGLFormat::hasOpenGLOverlays()
{
return false;
}
QColor QGLContext::overlayTransparentColor() const
{
return QColor(); // Invalid color
}
uint QGLContext::colorIndex(const QColor&) const
{
return 0;
}
/*
QGLTemporaryContext implementation
*/
class QGLTemporaryContextPrivate
{
public:
QWindow *window;
QOpenGLContext *context;
QGLContext *oldContext;
};
QGLTemporaryContext::QGLTemporaryContext(bool, QWidget *)
: d(new QGLTemporaryContextPrivate)
{
d->oldContext = const_cast<QGLContext *>(QGLContext::currentContext());
d->window = new QWindow;
d->window->setSurfaceType(QWindow::OpenGLSurface);
d->window->setGeometry(QRect(0, 0, 3, 3));
d->window->create();
d->context = new QOpenGLContext;
#if !defined(QT_OPENGL_ES)
if (QOpenGLContext::openGLModuleType() == QOpenGLContext::LibGL) {
// On desktop, request latest released version
QSurfaceFormat format;
#if defined(Q_OS_MAC)
// OS X is limited to OpenGL 3.2 Core Profile at present
// so set that here. If we use compatibility profile it
// only reports 2.x contexts.
format.setMajorVersion(3);
format.setMinorVersion(2);
format.setProfile(QSurfaceFormat::CoreProfile);
#else
format.setMajorVersion(4);
format.setMinorVersion(3);
#endif
d->context->setFormat(format);
}
#endif // QT_OPENGL_ES
d->context->create();
d->context->makeCurrent(d->window);
}
QGLTemporaryContext::~QGLTemporaryContext()
{
if (d->oldContext)
d->oldContext->makeCurrent();
delete d->context;
delete d->window;
}
bool QGLWidgetPrivate::renderCxPm(QPixmap*)
{
return false;
}
/*! \internal
Free up any allocated colormaps. This fn is only called for
top-level widgets.
*/
void QGLWidgetPrivate::cleanupColormaps()
{
}
bool QGLWidget::event(QEvent *e)
{
Q_D(QGLWidget);
// A re-parent will destroy the window and re-create it. We should not reset the context while it happens.
if (e->type() == QEvent::ParentAboutToChange)
d->parent_changing = true;
if (e->type() == QEvent::ParentChange)
d->parent_changing = false;
return QWidget::event(e);
}
void QGLWidget::resizeEvent(QResizeEvent *e)
{
Q_D(QGLWidget);
QWidget::resizeEvent(e);
if (!isValid())
return;
makeCurrent();
if (!d->glcx->initialized())
glInit();
const qreal scaleFactor = (window() && window()->windowHandle()) ?
window()->windowHandle()->devicePixelRatio() : 1.0;
resizeGL(width() * scaleFactor, height() * scaleFactor);
}
const QGLContext* QGLWidget::overlayContext() const
{
return 0;
}
void QGLWidget::makeOverlayCurrent()
{
}
void QGLWidget::updateOverlayGL()
{
}
const QGLColormap & QGLWidget::colormap() const
{
Q_D(const QGLWidget);
return d->cmap;
}
void QGLWidget::setColormap(const QGLColormap & c)
{
Q_UNUSED(c);
}
QGLContext::QGLContext(QOpenGLContext *context)
: d_ptr(new QGLContextPrivate(this))
{
Q_D(QGLContext);
d->init(0, QGLFormat::fromSurfaceFormat(context->format()));
d->guiGlContext = context;
d->guiGlContext->setQGLContextHandle(this,qDeleteQGLContext);
d->ownContext = false;
d->valid = context->isValid();
d->setupSharing();
}
QOpenGLContext *QGLContext::contextHandle() const
{
Q_D(const QGLContext);
return d->guiGlContext;
}
/*!
Returns a OpenGL context for the window context specified by the \a context
parameter.
*/
QGLContext *QGLContext::fromOpenGLContext(QOpenGLContext *context)
{
if (!context)
return 0;
if (context->qGLContextHandle()) {
return reinterpret_cast<QGLContext *>(context->qGLContextHandle());
}
QGLContext *glContext = new QGLContext(context);
//Don't call create on context. This can cause the platformFormat to be set on the widget, which
//will cause the platformWindow to be recreated.
return glContext;
}
QT_END_NAMESPACE