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