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/qpaintengineex_opengl2.cpp \
gl2paintengineex/qglcustomshaderstage.cpp \ gl2paintengineex/qglcustomshaderstage.cpp \
gl2paintengineex/qtextureglyphcache_gl.cpp gl2paintengineex/qtextureglyphcache_gl.cpp
SOURCES += qgl_qpa.cpp

View File

@ -70,6 +70,11 @@
#include "qlibrary.h" #include "qlibrary.h"
#include <qmutex.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 #ifndef QT_OPENGL_ES_2
#include <qopenglfunctions_1_1.h> #include <qopenglfunctions_1_1.h>
#endif #endif
@ -438,6 +443,80 @@ QGLFormat::~QGLFormat()
delete d; 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 \fn bool QGLFormat::doubleBuffer() const
@ -1132,8 +1211,11 @@ QGLFormat::OpenGLContextProfile QGLFormat::profile() const
\warning This function must not be called until the QApplication \warning This function must not be called until the QApplication
object has been created. object has been created.
*/ */
bool QGLFormat::hasOpenGL()
{
return QApplicationPrivate::platformIntegration()
->hasCapability(QPlatformIntegration::OpenGL);
}
/*! /*!
\fn bool QGLFormat::hasOpenGLOverlays() \fn bool QGLFormat::hasOpenGLOverlays()
@ -1144,6 +1226,10 @@ QGLFormat::OpenGLContextProfile QGLFormat::profile() const
\warning This function must not be called until the QApplication \warning This function must not be called until the QApplication
object has been created. object has been created.
*/ */
bool QGLFormat::hasOpenGLOverlays()
{
return false;
}
QGLFormat::OpenGLVersionFlags Q_AUTOTEST_EXPORT qOpenGLVersionFlagsFromString(const QString &versionString) 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; 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 Read back the contents of the currently bound framebuffer, used in
QGLWidget::grabFrameBuffer(), QGLPixelbuffer::toImage() and QGLWidget::grabFrameBuffer(), QGLPixelbuffer::toImage() and
@ -2000,6 +2140,47 @@ QGLContext::QGLContext(const QGLFormat &format)
d->init(0, 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. 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 Returns a colormap index for the color c, in ColorIndex mode. Used
by qglColor() and qglClearColor(). by qglColor() and qglClearColor().
*/ */
uint QGLContext::colorIndex(const QColor&) const
{
return 0;
}
/*! /*!
\fn bool QGLContext::initialized() const \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 also be used to draw transparent graphics with a QPainter. See the
examples/opengl/overlay_x11 example for details. 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 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 the virtual function chooseVisual() which finds an appropriate X
visual. On other platforms it may work differently. 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() \fn void QGLContext::reset()
@ -3275,7 +3507,33 @@ void QGLContext::moveToThread(QThread *thread)
\sa create(), isValid() \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() \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 make sure you've first pushed the context to the relevant thread
from the UI thread using moveToThread(). 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 \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 this to finish a frame of OpenGL rendering, and make sure to
call makeCurrent() again before you begin a new frame. 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() \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 Makes no GL context the current context. Normally, you do not need
to call this function; QGLContext calls it as necessary. to call this function; QGLContext calls it as necessary.
*/ */
void QGLContext::doneCurrent()
{
Q_D(QGLContext);
d->guiGlContext->doneCurrent();
}
/*! /*!
\fn QPaintDevice* QGLContext::device() const \fn QPaintDevice* QGLContext::device() const
@ -3317,7 +3609,6 @@ void QGLContext::moveToThread(QThread *thread)
\sa QGLContext::QGLContext() \sa QGLContext::QGLContext()
*/ */
/***************************************************************************** /*****************************************************************************
QGLWidget implementation QGLWidget implementation
*****************************************************************************/ *****************************************************************************/
@ -3716,6 +4007,11 @@ QGLWidget::~QGLWidget()
\a proc. 0 is returned if a pointer to the function could not be \a proc. 0 is returned if a pointer to the function could not be
obtained. obtained.
*/ */
QFunctionPointer QGLContext::getProcAddress(const QString &procName) const
{
Q_D(const QGLContext);
return d->guiGlContext->getProcAddress(procName.toLatin1());
}
/*! /*!
\fn bool QGLWidget::isValid() const \fn bool QGLWidget::isValid() const
@ -3803,8 +4099,10 @@ void QGLWidget::swapBuffers()
\sa context() \sa context()
*/ */
const QGLContext* QGLWidget::overlayContext() const
{
return 0;
}
/*! /*!
\fn void QGLWidget::makeOverlayCurrent() \fn void QGLWidget::makeOverlayCurrent()
@ -3817,7 +4115,9 @@ void QGLWidget::swapBuffers()
\sa makeCurrent() \sa makeCurrent()
*/ */
void QGLWidget::makeOverlayCurrent()
{
}
/*! /*!
\obsolete \obsolete
@ -3893,8 +4193,28 @@ void QGLWidget::setFormat(const QGLFormat &format)
\sa context(), isSharing() \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() \fn void QGLWidget::updateGL()
@ -3920,7 +4240,9 @@ void QGLWidget::updateGL()
The widget's rendering context will become the current context and The widget's rendering context will become the current context and
initializeGL() will be called if it hasn't already been called. 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 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) \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. Handles resize events that are passed in the \a event parameter.
Calls the virtual function resizeGL(). 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. 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() \sa setColormap(), QGLColormap::isEmpty()
*/ */
const QGLColormap & QGLWidget::colormap() const
{
Q_D(const QGLWidget);
return d->cmap;
}
/*! /*!
\fn void QGLWidget::setColormap(const QGLColormap & cmap) \fn void QGLWidget::setColormap(const QGLColormap & cmap)
@ -4342,6 +4697,10 @@ QImage QGLWidget::convertToGLFormat(const QImage& img)
\sa colormap() \sa colormap()
*/ */
void QGLWidget::setColormap(const QGLColormap & c)
{
Q_UNUSED(c);
}
#ifndef QT_OPENGL_ES #ifndef QT_OPENGL_ES
@ -4767,6 +5126,11 @@ QPaintEngine *QGLWidget::paintEngine() const
return qt_qgl_paint_engine(); 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() 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); 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) Q_GLOBAL_STATIC(QString, qt_gl_lib_name)
void qt_set_gl_library_name(const QString& 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