220 class QGLSharedResourceGuard; |
220 class QGLSharedResourceGuard; |
221 |
221 |
222 typedef QHash<QString, GLuint> QGLDDSCache; |
222 typedef QHash<QString, GLuint> QGLDDSCache; |
223 |
223 |
224 // QGLContextPrivate has the responsibility of creating context groups. |
224 // QGLContextPrivate has the responsibility of creating context groups. |
225 // QGLContextPrivate and QGLShareRegister will both maintain the reference counter and destroy |
225 // QGLContextPrivate maintains the reference counter and destroys |
226 // context groups when needed. |
226 // context groups when needed. |
227 // QGLShareRegister has the responsibility of keeping the context pointer up to date. |
|
228 class QGLContextGroup |
227 class QGLContextGroup |
229 { |
228 { |
230 public: |
229 public: |
231 ~QGLContextGroup(); |
230 ~QGLContextGroup(); |
232 |
231 |
233 QGLExtensionFuncs &extensionFuncs() {return m_extensionFuncs;} |
232 QGLExtensionFuncs &extensionFuncs() {return m_extensionFuncs;} |
234 const QGLContext *context() const {return m_context;} |
233 const QGLContext *context() const {return m_context;} |
235 bool isSharing() const { return m_shares.size() >= 2; } |
234 bool isSharing() const { return m_shares.size() >= 2; } |
|
235 QList<const QGLContext *> shares() const { return m_shares; } |
236 |
236 |
237 void addGuard(QGLSharedResourceGuard *guard); |
237 void addGuard(QGLSharedResourceGuard *guard); |
238 void removeGuard(QGLSharedResourceGuard *guard); |
238 void removeGuard(QGLSharedResourceGuard *guard); |
|
239 |
|
240 static void addShare(const QGLContext *context, const QGLContext *share); |
|
241 static void removeShare(const QGLContext *context); |
239 private: |
242 private: |
240 QGLContextGroup(const QGLContext *context) : m_context(context), m_guards(0), m_refs(1) { } |
243 QGLContextGroup(const QGLContext *context) : m_context(context), m_guards(0), m_refs(1) { } |
241 |
244 |
242 QGLExtensionFuncs m_extensionFuncs; |
245 QGLExtensionFuncs m_extensionFuncs; |
243 const QGLContext *m_context; // context group's representative |
246 const QGLContext *m_context; // context group's representative |
247 QAtomicInt m_refs; |
250 QAtomicInt m_refs; |
248 QGLDDSCache m_dds_cache; |
251 QGLDDSCache m_dds_cache; |
249 |
252 |
250 void cleanupResources(const QGLContext *ctx); |
253 void cleanupResources(const QGLContext *ctx); |
251 |
254 |
252 friend class QGLShareRegister; |
|
253 friend class QGLContext; |
255 friend class QGLContext; |
254 friend class QGLContextPrivate; |
256 friend class QGLContextPrivate; |
255 friend class QGLContextResource; |
257 friend class QGLContextResource; |
256 }; |
258 }; |
257 |
259 |
258 class QGLTexture; |
260 // Get the context that resources for "ctx" will transfer to once |
259 |
261 // "ctx" is destroyed. Returns null if nothing is sharing with ctx. |
260 class QGLContextPrivate |
262 Q_OPENGL_EXPORT const QGLContext *qt_gl_transfer_context(const QGLContext *); |
261 { |
|
262 Q_DECLARE_PUBLIC(QGLContext) |
|
263 public: |
|
264 explicit QGLContextPrivate(QGLContext *context) : internal_context(false), q_ptr(context) {group = new QGLContextGroup(context);} |
|
265 ~QGLContextPrivate(); |
|
266 QGLTexture *bindTexture(const QImage &image, GLenum target, GLint format, |
|
267 QGLContext::BindOptions options); |
|
268 QGLTexture *bindTexture(const QImage &image, GLenum target, GLint format, const qint64 key, |
|
269 QGLContext::BindOptions options); |
|
270 QGLTexture *bindTexture(const QPixmap &pixmap, GLenum target, GLint format, |
|
271 QGLContext::BindOptions options); |
|
272 QGLTexture *textureCacheLookup(const qint64 key, GLenum target); |
|
273 void init(QPaintDevice *dev, const QGLFormat &format); |
|
274 QImage convertToGLFormat(const QImage &image, bool force_premul, GLenum texture_format); |
|
275 int maxTextureSize(); |
|
276 |
|
277 void cleanup(); |
|
278 |
|
279 #if defined(Q_WS_WIN) |
|
280 HGLRC rc; |
|
281 HDC dc; |
|
282 WId win; |
|
283 int pixelFormatId; |
|
284 QGLCmap* cmap; |
|
285 HBITMAP hbitmap; |
|
286 HDC hbitmap_hdc; |
|
287 #endif |
|
288 #if defined(QT_OPENGL_ES) |
|
289 QEglContext *eglContext; |
|
290 EGLSurface eglSurface; |
|
291 void destroyEglSurfaceForDevice(); |
|
292 #elif defined(Q_WS_X11) || defined(Q_WS_MAC) |
|
293 void* cx; |
|
294 #endif |
|
295 #if defined(Q_WS_X11) || defined(Q_WS_MAC) |
|
296 void* vi; |
|
297 #endif |
|
298 #if defined(Q_WS_X11) |
|
299 void* pbuf; |
|
300 quint32 gpm; |
|
301 int screen; |
|
302 QHash<QPixmapData*, QPixmap> boundPixmaps; |
|
303 QGLTexture *bindTextureFromNativePixmap(QPixmapData*, const qint64 key, |
|
304 QGLContext::BindOptions options); |
|
305 static void destroyGlSurfaceForPixmap(QPixmapData*); |
|
306 static void unbindPixmapFromTexture(QPixmapData*); |
|
307 #endif |
|
308 #if defined(Q_WS_MAC) |
|
309 bool update; |
|
310 void *tryFormat(const QGLFormat &format); |
|
311 void clearDrawable(); |
|
312 #endif |
|
313 QGLFormat glFormat; |
|
314 QGLFormat reqFormat; |
|
315 GLuint fbo; |
|
316 |
|
317 uint valid : 1; |
|
318 uint sharing : 1; |
|
319 uint initDone : 1; |
|
320 uint crWin : 1; |
|
321 uint internal_context : 1; |
|
322 uint version_flags_cached : 1; |
|
323 QPaintDevice *paintDevice; |
|
324 QColor transpColor; |
|
325 QGLContext *q_ptr; |
|
326 QGLFormat::OpenGLVersionFlags version_flags; |
|
327 |
|
328 QGLContextGroup *group; |
|
329 GLint max_texture_size; |
|
330 |
|
331 GLuint current_fbo; |
|
332 GLuint default_fbo; |
|
333 QPaintEngine *active_engine; |
|
334 |
|
335 static inline QGLContextGroup *contextGroup(const QGLContext *ctx) { return ctx->d_ptr->group; } |
|
336 |
|
337 #ifdef Q_WS_WIN |
|
338 static inline QGLExtensionFuncs& extensionFuncs(const QGLContext *ctx) { return ctx->d_ptr->group->extensionFuncs(); } |
|
339 #endif |
|
340 |
|
341 #if defined(Q_WS_X11) || defined(Q_WS_MAC) || defined(Q_WS_QWS) |
|
342 static QGLExtensionFuncs qt_extensionFuncs; |
|
343 static inline QGLExtensionFuncs& extensionFuncs(const QGLContext *) { return qt_extensionFuncs; } |
|
344 #endif |
|
345 |
|
346 static void setCurrentContext(QGLContext *context); |
|
347 }; |
|
348 |
|
349 // ### make QGLContext a QObject in 5.0 and remove the proxy stuff |
|
350 class Q_OPENGL_EXPORT QGLSignalProxy : public QObject |
|
351 { |
|
352 Q_OBJECT |
|
353 public: |
|
354 QGLSignalProxy() : QObject() {} |
|
355 void emitAboutToDestroyContext(const QGLContext *context) { |
|
356 emit aboutToDestroyContext(context); |
|
357 } |
|
358 static QGLSignalProxy *instance(); |
|
359 Q_SIGNALS: |
|
360 void aboutToDestroyContext(const QGLContext *context); |
|
361 }; |
|
362 |
263 |
363 // GL extension definitions |
264 // GL extension definitions |
364 class QGLExtensions { |
265 class QGLExtensions { |
365 public: |
266 public: |
366 enum Extension { |
267 enum Extension { |
384 PVRTCTextureCompression = 0x00020000, |
285 PVRTCTextureCompression = 0x00020000, |
385 FragmentShader = 0x00040000 |
286 FragmentShader = 0x00040000 |
386 }; |
287 }; |
387 Q_DECLARE_FLAGS(Extensions, Extension) |
288 Q_DECLARE_FLAGS(Extensions, Extension) |
388 |
289 |
389 static Extensions glExtensions; |
290 static Extensions glExtensions(); |
390 static bool nvidiaFboNeedsFinish; |
291 |
391 static void init(); // sys dependent |
292 private: |
392 static void init_extensions(); // general: called by init() |
293 static Extensions currentContextExtensions(); |
|
294 }; |
|
295 |
|
296 /* |
|
297 QGLTemporaryContext - the main objective of this class is to have a way of |
|
298 creating a GL context and making it current, without going via QGLWidget |
|
299 and friends. At certain points during GL initialization we need a current |
|
300 context in order decide what GL features are available, and to resolve GL |
|
301 extensions. Having a light-weight way of creating such a context saves |
|
302 initial application startup time, and it doesn't wind up creating recursive |
|
303 conflicts. |
|
304 The class currently uses a private d pointer to hide the platform specific |
|
305 types. This could possibly been done inline with #ifdef'ery, but it causes |
|
306 major headaches on e.g. X11 due to namespace pollution. |
|
307 */ |
|
308 class QGLTemporaryContextPrivate; |
|
309 class QGLTemporaryContext { |
|
310 public: |
|
311 QGLTemporaryContext(bool directRendering = true, QWidget *parent = 0); |
|
312 ~QGLTemporaryContext(); |
|
313 |
|
314 private: |
|
315 QScopedPointer<QGLTemporaryContextPrivate> d; |
|
316 }; |
|
317 |
|
318 class QGLTexture; |
|
319 |
|
320 // This probably needs to grow to GL_MAX_VERTEX_ATTRIBS, but 3 is ok for now as that's |
|
321 // all the GL2 engine uses: |
|
322 #define QT_GL_VERTEX_ARRAY_TRACKED_COUNT 3 |
|
323 |
|
324 class QGLContextPrivate |
|
325 { |
|
326 Q_DECLARE_PUBLIC(QGLContext) |
|
327 public: |
|
328 explicit QGLContextPrivate(QGLContext *context) : internal_context(false), q_ptr(context) {group = new QGLContextGroup(context);} |
|
329 ~QGLContextPrivate(); |
|
330 QGLTexture *bindTexture(const QImage &image, GLenum target, GLint format, |
|
331 QGLContext::BindOptions options); |
|
332 QGLTexture *bindTexture(const QImage &image, GLenum target, GLint format, const qint64 key, |
|
333 QGLContext::BindOptions options); |
|
334 QGLTexture *bindTexture(const QPixmap &pixmap, GLenum target, GLint format, |
|
335 QGLContext::BindOptions options); |
|
336 QGLTexture *textureCacheLookup(const qint64 key, GLenum target); |
|
337 void init(QPaintDevice *dev, const QGLFormat &format); |
|
338 QImage convertToGLFormat(const QImage &image, bool force_premul, GLenum texture_format); |
|
339 int maxTextureSize(); |
|
340 |
|
341 void cleanup(); |
|
342 |
|
343 void setVertexAttribArrayEnabled(int arrayIndex, bool enabled = true); |
|
344 void syncGlState(); // Makes sure the GL context's state is what we think it is |
|
345 |
|
346 #if defined(Q_WS_WIN) |
|
347 HGLRC rc; |
|
348 HDC dc; |
|
349 WId win; |
|
350 int pixelFormatId; |
|
351 QGLCmap* cmap; |
|
352 HBITMAP hbitmap; |
|
353 HDC hbitmap_hdc; |
|
354 #endif |
|
355 #if defined(QT_OPENGL_ES) |
|
356 QEglContext *eglContext; |
|
357 EGLSurface eglSurface; |
|
358 void destroyEglSurfaceForDevice(); |
|
359 #elif defined(Q_WS_X11) || defined(Q_WS_MAC) |
|
360 void* cx; |
|
361 #endif |
|
362 #if defined(Q_WS_X11) || defined(Q_WS_MAC) |
|
363 void* vi; |
|
364 #endif |
|
365 #if defined(Q_WS_X11) |
|
366 void* pbuf; |
|
367 quint32 gpm; |
|
368 int screen; |
|
369 QHash<QPixmapData*, QPixmap> boundPixmaps; |
|
370 QGLTexture *bindTextureFromNativePixmap(QPixmapData*, const qint64 key, |
|
371 QGLContext::BindOptions options); |
|
372 static void destroyGlSurfaceForPixmap(QPixmapData*); |
|
373 static void unbindPixmapFromTexture(QPixmapData*); |
|
374 #endif |
|
375 #if defined(Q_WS_MAC) |
|
376 bool update; |
|
377 void *tryFormat(const QGLFormat &format); |
|
378 void clearDrawable(); |
|
379 #endif |
|
380 QGLFormat glFormat; |
|
381 QGLFormat reqFormat; |
|
382 GLuint fbo; |
|
383 |
|
384 uint valid : 1; |
|
385 uint sharing : 1; |
|
386 uint initDone : 1; |
|
387 uint crWin : 1; |
|
388 uint internal_context : 1; |
|
389 uint version_flags_cached : 1; |
|
390 uint extension_flags_cached : 1; |
|
391 QPaintDevice *paintDevice; |
|
392 QColor transpColor; |
|
393 QGLContext *q_ptr; |
|
394 QGLFormat::OpenGLVersionFlags version_flags; |
|
395 QGLExtensions::Extensions extension_flags; |
|
396 |
|
397 QGLContextGroup *group; |
|
398 GLint max_texture_size; |
|
399 |
|
400 GLuint current_fbo; |
|
401 GLuint default_fbo; |
|
402 QPaintEngine *active_engine; |
|
403 |
|
404 bool vertexAttributeArraysEnabledState[QT_GL_VERTEX_ARRAY_TRACKED_COUNT]; |
|
405 |
|
406 static inline QGLContextGroup *contextGroup(const QGLContext *ctx) { return ctx->d_ptr->group; } |
|
407 |
|
408 #ifdef Q_WS_WIN |
|
409 static inline QGLExtensionFuncs& extensionFuncs(const QGLContext *ctx) { return ctx->d_ptr->group->extensionFuncs(); } |
|
410 #endif |
|
411 |
|
412 #if defined(Q_WS_X11) || defined(Q_WS_MAC) || defined(Q_WS_QWS) |
|
413 static QGLExtensionFuncs qt_extensionFuncs; |
|
414 static inline QGLExtensionFuncs& extensionFuncs(const QGLContext *) { return qt_extensionFuncs; } |
|
415 #endif |
|
416 |
|
417 static void setCurrentContext(QGLContext *context); |
|
418 }; |
|
419 |
|
420 // ### make QGLContext a QObject in 5.0 and remove the proxy stuff |
|
421 class Q_OPENGL_EXPORT QGLSignalProxy : public QObject |
|
422 { |
|
423 Q_OBJECT |
|
424 public: |
|
425 QGLSignalProxy() : QObject() {} |
|
426 void emitAboutToDestroyContext(const QGLContext *context) { |
|
427 emit aboutToDestroyContext(context); |
|
428 } |
|
429 static QGLSignalProxy *instance(); |
|
430 Q_SIGNALS: |
|
431 void aboutToDestroyContext(const QGLContext *context); |
393 }; |
432 }; |
394 |
433 |
395 Q_DECLARE_OPERATORS_FOR_FLAGS(QGLExtensions::Extensions) |
434 Q_DECLARE_OPERATORS_FOR_FLAGS(QGLExtensions::Extensions) |
396 |
|
397 |
|
398 class Q_OPENGL_EXPORT QGLShareRegister |
|
399 { |
|
400 public: |
|
401 QGLShareRegister() {} |
|
402 ~QGLShareRegister() {} |
|
403 |
|
404 void addShare(const QGLContext *context, const QGLContext *share); |
|
405 QList<const QGLContext *> shares(const QGLContext *context); |
|
406 void removeShare(const QGLContext *context); |
|
407 }; |
|
408 |
|
409 extern Q_OPENGL_EXPORT QGLShareRegister* qgl_share_reg(); |
|
410 |
435 |
411 // Temporarily make a context current if not already current or |
436 // Temporarily make a context current if not already current or |
412 // shared with the current contex. The previous context is made |
437 // shared with the current contex. The previous context is made |
413 // current when the object goes out of scope. |
438 // current when the object goes out of scope. |
414 class Q_OPENGL_EXPORT QGLShareContextScope |
439 class Q_OPENGL_EXPORT QGLShareContextScope |