1 /**************************************************************************** 2 ** 3 ** Copyright (C) 2016 The Qt Company Ltd. 4 ** Contact: https://www.qt.io/licensing/ 5 ** 6 ** This file is part of the QtGui module of the Qt Toolkit. 7 ** 8 ** $QT_BEGIN_LICENSE:LGPL$ 9 ** Commercial License Usage 10 ** Licensees holding valid commercial Qt licenses may use this file in 11 ** accordance with the commercial license agreement provided with the 12 ** Software or, alternatively, in accordance with the terms contained in 13 ** a written agreement between you and The Qt Company. For licensing terms 14 ** and conditions see https://www.qt.io/terms-conditions. For further 15 ** information use the contact form at https://www.qt.io/contact-us. 16 ** 17 ** GNU Lesser General Public License Usage 18 ** Alternatively, this file may be used under the terms of the GNU Lesser 19 ** General Public License version 3 as published by the Free Software 20 ** Foundation and appearing in the file LICENSE.LGPL3 included in the 21 ** packaging of this file. Please review the following information to 22 ** ensure the GNU Lesser General Public License version 3 requirements 23 ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. 24 ** 25 ** GNU General Public License Usage 26 ** Alternatively, this file may be used under the terms of the GNU 27 ** General Public License version 2.0 or (at your option) the GNU General 28 ** Public license version 3 or any later version approved by the KDE Free 29 ** Qt Foundation. The licenses are as published by the Free Software 30 ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 31 ** included in the packaging of this file. Please review the following 32 ** information to ensure the GNU General Public License requirements will 33 ** be met: https://www.gnu.org/licenses/gpl-2.0.html and 34 ** https://www.gnu.org/licenses/gpl-3.0.html. 35 ** 36 ** $QT_END_LICENSE$ 37 ** 38 ****************************************************************************/ 39 40 #ifndef QOPENGLCONTEXT_P_H 41 #define QOPENGLCONTEXT_P_H 42 43 // 44 // W A R N I N G 45 // ------------- 46 // 47 // This file is not part of the Qt API. It exists purely as an 48 // implementation detail. This header file may change from version to 49 // version without notice, or even be removed. 50 // 51 // We mean it. 52 // 53 54 #include <QtGui/private/qtguiglobal_p.h> 55 56 #ifndef QT_NO_OPENGL 57 58 #include <qopengl.h> 59 #include "qopenglcontext.h" 60 #include <private/qobject_p.h> 61 #include <qmutex.h> 62 63 #include <QtCore/QByteArray> 64 #include <QtCore/QHash> 65 #include <QtCore/QSet> 66 67 QT_BEGIN_NAMESPACE 68 69 70 class QOpenGLFunctions; 71 class QOpenGLContext; 72 class QOpenGLFramebufferObject; 73 class QOpenGLMultiGroupSharedResource; 74 75 class Q_GUI_EXPORT QOpenGLSharedResource 76 { 77 public: 78 QOpenGLSharedResource(QOpenGLContextGroup *group); 79 virtual ~QOpenGLSharedResource() = 0; 80 group()81 QOpenGLContextGroup *group() const { return m_group; } 82 83 // schedule the resource for deletion at an appropriate time 84 void free(); 85 86 protected: 87 // the resource's share group no longer exists, invalidate the resource 88 virtual void invalidateResource() = 0; 89 90 // a valid context in the group is current, free the resource 91 virtual void freeResource(QOpenGLContext *context) = 0; 92 93 private: 94 QOpenGLContextGroup *m_group; 95 96 friend class QOpenGLContextGroup; 97 friend class QOpenGLContextGroupPrivate; 98 friend class QOpenGLMultiGroupSharedResource; 99 100 Q_DISABLE_COPY_MOVE(QOpenGLSharedResource) 101 }; 102 103 class Q_GUI_EXPORT QOpenGLSharedResourceGuard : public QOpenGLSharedResource 104 { 105 public: 106 typedef void (*FreeResourceFunc)(QOpenGLFunctions *functions, GLuint id); QOpenGLSharedResourceGuard(QOpenGLContext * context,GLuint id,FreeResourceFunc func)107 QOpenGLSharedResourceGuard(QOpenGLContext *context, GLuint id, FreeResourceFunc func) 108 : QOpenGLSharedResource(context->shareGroup()) 109 , m_id(id) 110 , m_func(func) 111 { 112 } 113 id()114 GLuint id() const { return m_id; } 115 116 protected: invalidateResource()117 void invalidateResource() override 118 { 119 m_id = 0; 120 } 121 122 void freeResource(QOpenGLContext *context) override; 123 124 private: 125 GLuint m_id; 126 FreeResourceFunc m_func; 127 }; 128 129 class Q_GUI_EXPORT QOpenGLContextGroupPrivate : public QObjectPrivate 130 { Q_DECLARE_PUBLIC(QOpenGLContextGroup)131 Q_DECLARE_PUBLIC(QOpenGLContextGroup) 132 public: 133 QOpenGLContextGroupPrivate() 134 : m_context(nullptr) 135 , m_refs(0) 136 { 137 } 138 139 void addContext(QOpenGLContext *ctx); 140 void removeContext(QOpenGLContext *ctx); 141 142 void cleanup(); 143 144 void deletePendingResources(QOpenGLContext *ctx); 145 146 QOpenGLContext *m_context; 147 148 QList<QOpenGLContext *> m_shares; 149 QRecursiveMutex m_mutex; 150 151 QHash<QOpenGLMultiGroupSharedResource *, QOpenGLSharedResource *> m_resources; 152 QAtomicInt m_refs; 153 154 QList<QOpenGLSharedResource *> m_sharedResources; 155 QList<QOpenGLSharedResource *> m_pendingDeletion; 156 }; 157 158 class Q_GUI_EXPORT QOpenGLMultiGroupSharedResource 159 { 160 public: 161 QOpenGLMultiGroupSharedResource(); 162 ~QOpenGLMultiGroupSharedResource(); 163 164 void insert(QOpenGLContext *context, QOpenGLSharedResource *value); 165 void cleanup(QOpenGLContextGroup *group, QOpenGLSharedResource *value); 166 167 QOpenGLSharedResource *value(QOpenGLContext *context); 168 169 QList<QOpenGLSharedResource *> resources() const; 170 171 template <typename T> value(QOpenGLContext * context)172 T *value(QOpenGLContext *context) { 173 QOpenGLContextGroup *group = context->shareGroup(); 174 // Have to use our own mutex here, not the group's, since 175 // m_groups has to be protected too against any concurrent access. 176 QMutexLocker locker(&m_mutex); 177 T *resource = static_cast<T *>(group->d_func()->m_resources.value(this, 0)); 178 if (!resource) { 179 resource = new T(context); 180 insert(context, resource); 181 } 182 return resource; 183 } 184 185 private: 186 QAtomicInt active; 187 QList<QOpenGLContextGroup *> m_groups; 188 QRecursiveMutex m_mutex; 189 }; 190 191 class QPaintEngineEx; 192 class QOpenGLFunctions; 193 class QOpenGLTextureHelper; 194 195 class Q_GUI_EXPORT QOpenGLContextPrivate : public QObjectPrivate 196 { Q_DECLARE_PUBLIC(QOpenGLContext)197 Q_DECLARE_PUBLIC(QOpenGLContext) 198 public: 199 QOpenGLContextPrivate() 200 : qGLContextHandle(nullptr) 201 , qGLContextDeleteFunction(nullptr) 202 , platformGLContext(nullptr) 203 , shareContext(nullptr) 204 , shareGroup(nullptr) 205 , screen(nullptr) 206 , surface(nullptr) 207 , functions(nullptr) 208 , textureFunctions(nullptr) 209 , max_texture_size(-1) 210 , workaround_brokenFBOReadBack(false) 211 , workaround_brokenTexSubImage(false) 212 , workaround_missingPrecisionQualifiers(false) 213 , active_engine(nullptr) 214 , qgl_current_fbo_invalid(false) 215 , qgl_current_fbo(nullptr) 216 , defaultFboRedirect(0) 217 { 218 requestedFormat = QSurfaceFormat::defaultFormat(); 219 } 220 ~QOpenGLContextPrivate()221 ~QOpenGLContextPrivate() 222 { 223 //do not delete the QOpenGLContext handle here as it is deleted in 224 //QWidgetPrivate::deleteTLSysExtra() 225 } 226 227 mutable QHash<QOpenGLVersionProfile, QAbstractOpenGLFunctions *> versionFunctions; 228 mutable QOpenGLVersionFunctionsStorage versionFunctionsStorage; 229 mutable QSet<QAbstractOpenGLFunctions *> externalVersionFunctions; 230 231 void *qGLContextHandle; 232 void (*qGLContextDeleteFunction)(void *handle); 233 234 QSurfaceFormat requestedFormat; 235 QPlatformOpenGLContext *platformGLContext; 236 QOpenGLContext *shareContext; 237 QOpenGLContextGroup *shareGroup; 238 QScreen *screen; 239 QSurface *surface; 240 QOpenGLFunctions *functions; 241 mutable QSet<QByteArray> extensionNames; 242 QOpenGLTextureHelper* textureFunctions; 243 244 GLint max_texture_size; 245 246 bool workaround_brokenFBOReadBack; 247 bool workaround_brokenTexSubImage; 248 bool workaround_missingPrecisionQualifiers; 249 250 QPaintEngineEx *active_engine; 251 252 bool qgl_current_fbo_invalid; 253 254 // Set and unset in QOpenGLFramebufferObject::bind()/unbind(). 255 // (Only meaningful for QOGLFBO since an FBO might be bound by other means) 256 // Saves us from querying the driver for the current FBO in most paths. 257 QOpenGLFramebufferObject *qgl_current_fbo; 258 259 QVariant nativeHandle; 260 GLuint defaultFboRedirect; 261 262 static QOpenGLContext *setCurrentContext(QOpenGLContext *context); 263 264 int maxTextureSize(); 265 get(QOpenGLContext * context)266 static QOpenGLContextPrivate *get(QOpenGLContext *context) 267 { 268 return context ? context->d_func() : nullptr; 269 } 270 271 #if !defined(QT_NO_DEBUG) toggleMakeCurrentTracker(QOpenGLContext * context,bool value)272 static bool toggleMakeCurrentTracker(QOpenGLContext *context, bool value) 273 { 274 QMutexLocker locker(&makeCurrentTrackerMutex); 275 bool old = makeCurrentTracker.value(context, false); 276 makeCurrentTracker.insert(context, value); 277 return old; 278 } cleanMakeCurrentTracker(QOpenGLContext * context)279 static void cleanMakeCurrentTracker(QOpenGLContext *context) 280 { 281 QMutexLocker locker(&makeCurrentTrackerMutex); 282 makeCurrentTracker.remove(context); 283 } 284 static QHash<QOpenGLContext *, bool> makeCurrentTracker; 285 static QMutex makeCurrentTrackerMutex; 286 #endif 287 288 void _q_screenDestroyed(QObject *object); 289 }; 290 291 Q_GUI_EXPORT void qt_gl_set_global_share_context(QOpenGLContext *context); 292 Q_GUI_EXPORT QOpenGLContext *qt_gl_global_share_context(); 293 294 QT_END_NAMESPACE 295 296 #endif // QT_NO_OPENGL 297 #endif // QOPENGLCONTEXT_P_H 298