Changeset 561 for trunk/src/opengl/qgl_p.h
- Timestamp:
- Feb 11, 2010, 11:19:06 PM (15 years ago)
- Location:
- trunk
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk
-
Property svn:mergeinfo
set to (toggle deleted branches)
/branches/vendor/nokia/qt/4.6.1 merged eligible /branches/vendor/nokia/qt/current merged eligible /branches/vendor/trolltech/qt/current 3-149
-
Property svn:mergeinfo
set to (toggle deleted branches)
-
trunk/src/opengl/qgl_p.h
r2 r561 2 2 ** 3 3 ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). 4 ** Contact: Qt Software Information (qt-info@nokia.com) 4 ** All rights reserved. 5 ** Contact: Nokia Corporation (qt-info@nokia.com) 5 6 ** 6 7 ** This file is part of the QtOpenGL module of the Qt Toolkit. … … 21 22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. 22 23 ** 23 ** In addition, as a special exception, Nokia gives you certain 24 ** additional rights. These rights are described in the Nokia Qt LGPL 25 ** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this 26 ** package. 24 ** In addition, as a special exception, Nokia gives you certain additional 25 ** rights. These rights are described in the Nokia Qt LGPL Exception 26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. 27 27 ** 28 28 ** GNU General Public License Usage … … 34 34 ** met: http://www.gnu.org/copyleft/gpl.html. 35 35 ** 36 ** If you are unsure which license is appropriate for your use, please37 ** contact the sales department at qt-sales@nokia.com.36 ** If you have questions regarding the use of this file, please contact 37 ** Nokia at qt-info@nokia.com. 38 38 ** $QT_END_LICENSE$ 39 39 ** … … 60 60 #include "QtCore/qthreadstorage.h" 61 61 #include "QtCore/qhash.h" 62 #include "QtCore/qatomic.h" 62 63 #include "private/qwidget_p.h" 64 #include "qcache.h" 65 #include "qglpaintdevice_p.h" 63 66 64 67 #ifndef QT_OPENGL_ES_1_CL … … 127 130 { 128 131 public: 129 QGLFormatPrivate() { 132 QGLFormatPrivate() 133 : ref(1) 134 { 130 135 opts = QGL::DoubleBuffer | QGL::DepthBuffer | QGL::Rgba | QGL::DirectRendering | QGL::StencilBuffer; 131 #if defined(QT_OPENGL_ES_2)132 opts |= QGL::SampleBuffers;133 #endif134 136 pln = 0; 135 137 depthSize = accumSize = stencilSize = redSize = greenSize = blueSize = alphaSize = -1; … … 137 139 swapInterval = -1; 138 140 } 141 QGLFormatPrivate(const QGLFormatPrivate *other) 142 : ref(1), 143 opts(other->opts), 144 pln(other->pln), 145 depthSize(other->depthSize), 146 accumSize(other->accumSize), 147 stencilSize(other->stencilSize), 148 redSize(other->redSize), 149 greenSize(other->greenSize), 150 blueSize(other->blueSize), 151 alphaSize(other->alphaSize), 152 numSamples(other->numSamples), 153 swapInterval(other->swapInterval) 154 { 155 } 156 QAtomicInt ref; 139 157 QGL::FormatOptions opts; 140 158 int pln; … … 155 173 public: 156 174 QGLWidgetPrivate() : QWidgetPrivate() 175 , disable_clear_on_painter_begin(false) 157 176 #ifdef Q_WS_QWS 158 177 , wsurf(0) … … 171 190 172 191 QGLContext *glcx; 192 QGLWidgetGLPaintDevice glDevice; 173 193 bool autoSwap; 174 194 175 195 QGLColormap cmap; 196 #ifndef QT_OPENGL_ES 176 197 QMap<QString, int> displayListCache; 198 #endif 199 200 bool disable_clear_on_painter_begin; 177 201 178 202 #if defined(Q_WS_WIN) … … 193 217 }; 194 218 219 class QGLContextResource; 220 class QGLSharedResourceGuard; 221 222 typedef QHash<QString, GLuint> QGLDDSCache; 223 224 // QGLContextPrivate has the responsibility of creating context groups. 225 // QGLContextPrivate and QGLShareRegister will both maintain the reference counter and destroy 226 // context groups when needed. 227 // QGLShareRegister has the responsibility of keeping the context pointer up to date. 228 class QGLContextGroup 229 { 230 public: 231 ~QGLContextGroup(); 232 233 QGLExtensionFuncs &extensionFuncs() {return m_extensionFuncs;} 234 const QGLContext *context() const {return m_context;} 235 bool isSharing() const { return m_shares.size() >= 2; } 236 237 void addGuard(QGLSharedResourceGuard *guard); 238 void removeGuard(QGLSharedResourceGuard *guard); 239 private: 240 QGLContextGroup(const QGLContext *context) : m_context(context), m_guards(0), m_refs(1) { } 241 242 QGLExtensionFuncs m_extensionFuncs; 243 const QGLContext *m_context; // context group's representative 244 QList<const QGLContext *> m_shares; 245 QHash<QGLContextResource *, void *> m_resources; 246 QGLSharedResourceGuard *m_guards; // double-linked list of active guards. 247 QAtomicInt m_refs; 248 QGLDDSCache m_dds_cache; 249 250 void cleanupResources(const QGLContext *ctx); 251 252 friend class QGLShareRegister; 253 friend class QGLContext; 254 friend class QGLContextPrivate; 255 friend class QGLContextResource; 256 }; 257 258 class QGLTexture; 259 195 260 class QGLContextPrivate 196 261 { 197 262 Q_DECLARE_PUBLIC(QGLContext) 198 263 public: 199 explicit QGLContextPrivate(QGLContext *context) : internal_context(false), q_ptr(context) {} 200 ~QGLContextPrivate() {} 201 GLuint bindTexture(const QImage &image, GLenum target, GLint format, const qint64 key, 202 bool clean = false); 203 GLuint bindTexture(const QPixmap &pixmap, GLenum target, GLint format, bool clean); 204 GLuint bindTexture(const QImage &image, GLenum target, GLint format, bool clean); 205 bool textureCacheLookup(const qint64 key, GLenum target, GLuint *id); 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); 206 273 void init(QPaintDevice *dev, const QGLFormat &format); 207 274 QImage convertToGLFormat(const QImage &image, bool force_premul, GLenum texture_format); … … 221 288 #if defined(QT_OPENGL_ES) 222 289 QEglContext *eglContext; 290 EGLSurface eglSurface; 291 void destroyEglSurfaceForDevice(); 223 292 #elif defined(Q_WS_X11) || defined(Q_WS_MAC) 224 293 void* cx; … … 231 300 quint32 gpm; 232 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*); 233 307 #endif 234 308 #if defined(Q_WS_MAC) … … 239 313 QGLFormat glFormat; 240 314 QGLFormat reqFormat; 241 GLuint pbo;315 GLuint fbo; 242 316 243 317 uint valid : 1; … … 245 319 uint initDone : 1; 246 320 uint crWin : 1; 247 uint clear_on_painter_begin : 1;248 321 uint internal_context : 1; 249 322 uint version_flags_cached : 1; … … 253 326 QGLFormat::OpenGLVersionFlags version_flags; 254 327 255 QGL ExtensionFuncs extensionFuncs;328 QGLContextGroup *group; 256 329 GLint max_texture_size; 257 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 258 337 #ifdef Q_WS_WIN 259 static inline QGLExtensionFuncs& qt_get_extension_funcs(const QGLContext *ctx) { return ctx->d_ptr->extensionFuncs; }338 static inline QGLExtensionFuncs& extensionFuncs(const QGLContext *ctx) { return ctx->d_ptr->group->extensionFuncs(); } 260 339 #endif 261 340 262 341 #if defined(Q_WS_X11) || defined(Q_WS_MAC) || defined(Q_WS_QWS) 263 342 static QGLExtensionFuncs qt_extensionFuncs; 264 static inline QGLExtensionFuncs& qt_get_extension_funcs(const QGLContext *) { return qt_extensionFuncs; }265 #endif 266 267 QPixmapFilter *createPixmapFilter(int type) const;343 static inline QGLExtensionFuncs& extensionFuncs(const QGLContext *) { return qt_extensionFuncs; } 344 #endif 345 346 static void setCurrentContext(QGLContext *context); 268 347 }; 269 348 270 349 // ### make QGLContext a QObject in 5.0 and remove the proxy stuff 271 class Q GLSignalProxy : public QObject350 class Q_OPENGL_EXPORT QGLSignalProxy : public QObject 272 351 { 273 352 Q_OBJECT … … 297 376 PackedDepthStencil = 0x00000200, 298 377 NVFloatBuffer = 0x00000400, 299 PixelBufferObject = 0x00000800 378 PixelBufferObject = 0x00000800, 379 FramebufferBlit = 0x00001000, 380 NPOTTextures = 0x00002000, 381 BGRATextureFormat = 0x00004000, 382 DDSTextureCompression = 0x00008000, 383 ETC1TextureCompression = 0x00010000, 384 PVRTCTextureCompression = 0x00020000, 385 FragmentShader = 0x00040000 300 386 }; 301 387 Q_DECLARE_FLAGS(Extensions, Extension) … … 310 396 311 397 312 struct QGLThreadContext { 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 411 // Temporarily make a context current if not already current or 412 // shared with the current contex. The previous context is made 413 // current when the object goes out of scope. 414 class Q_OPENGL_EXPORT QGLShareContextScope 415 { 416 public: 417 QGLShareContextScope(const QGLContext *ctx) 418 : m_oldContext(0) 419 { 420 QGLContext *currentContext = const_cast<QGLContext *>(QGLContext::currentContext()); 421 if (currentContext != ctx && !QGLContext::areSharing(ctx, currentContext)) { 422 m_oldContext = currentContext; 423 m_ctx = const_cast<QGLContext *>(ctx); 424 m_ctx->makeCurrent(); 425 } else { 426 m_ctx = currentContext; 427 } 428 } 429 430 operator QGLContext *() 431 { 432 return m_ctx; 433 } 434 435 QGLContext *operator->() 436 { 437 return m_ctx; 438 } 439 440 ~QGLShareContextScope() 441 { 442 if (m_oldContext) 443 m_oldContext->makeCurrent(); 444 } 445 446 private: 447 QGLContext *m_oldContext; 448 QGLContext *m_ctx; 449 }; 450 451 class QGLTexture { 452 public: 453 QGLTexture(QGLContext *ctx = 0, GLuint tx_id = 0, GLenum tx_target = GL_TEXTURE_2D, 454 QGLContext::BindOptions opt = QGLContext::DefaultBindOption) 455 : context(ctx), 456 id(tx_id), 457 target(tx_target), 458 options(opt) 459 #if defined(Q_WS_X11) 460 , boundPixmap(0) 461 #endif 462 {} 463 464 ~QGLTexture() { 465 if (options & QGLContext::MemoryManagedBindOption) { 466 Q_ASSERT(context); 467 QGLShareContextScope scope(context); 468 #if defined(Q_WS_X11) 469 // Although glXReleaseTexImage is a glX call, it must be called while there 470 // is a current context - the context the pixmap was bound to a texture in. 471 // Otherwise the release doesn't do anything and you get BadDrawable errors 472 // when you come to delete the context. 473 if (boundPixmap) 474 QGLContextPrivate::unbindPixmapFromTexture(boundPixmap); 475 #endif 476 glDeleteTextures(1, &id); 477 } 478 } 479 313 480 QGLContext *context; 314 }; 315 extern QThreadStorage<QGLThreadContext *> qgl_context_storage; 316 317 typedef QMultiHash<const QGLContext *, const QGLContext *> QGLSharingHash; 318 class QGLShareRegister 319 { 320 public: 321 QGLShareRegister() {} 322 ~QGLShareRegister() { reg.clear(); } 323 324 bool checkSharing(const QGLContext *context1, const QGLContext *context2, const QGLContext * skip=0) { 325 if (context1 == context2) 326 return true; 327 QList<const QGLContext *> shares = reg.values(context1); 328 for (int k=0; k<shares.size(); ++k) { 329 const QGLContext *ctx = shares.at(k); 330 if (ctx == skip) // avoid an indirect circular loop (infinite recursion) 331 continue; 332 if (ctx == context2) 481 GLuint id; 482 GLenum target; 483 484 QGLContext::BindOptions options; 485 486 #if defined(Q_WS_X11) 487 QPixmapData* boundPixmap; 488 #endif 489 490 bool canBindCompressedTexture 491 (const char *buf, int len, const char *format, bool *hasAlpha); 492 QSize bindCompressedTexture 493 (const QString& fileName, const char *format = 0); 494 QSize bindCompressedTexture 495 (const char *buf, int len, const char *format = 0); 496 QSize bindCompressedTextureDDS(const char *buf, int len); 497 QSize bindCompressedTexturePVR(const char *buf, int len); 498 }; 499 500 class QGLTextureCache { 501 public: 502 QGLTextureCache(); 503 ~QGLTextureCache(); 504 505 void insert(QGLContext *ctx, qint64 key, QGLTexture *texture, int cost); 506 void remove(quint64 key) { m_cache.remove(key); } 507 bool remove(QGLContext *ctx, GLuint textureId); 508 void removeContextTextures(QGLContext *ctx); 509 int size() { return m_cache.size(); } 510 void setMaxCost(int newMax) { m_cache.setMaxCost(newMax); } 511 int maxCost() {return m_cache.maxCost(); } 512 QGLTexture* getTexture(quint64 key) { return m_cache.object(key); } 513 514 static QGLTextureCache *instance(); 515 static void deleteIfEmpty(); 516 static void imageCleanupHook(qint64 cacheKey); 517 static void cleanupTextures(QPixmap* pixmap); 518 #ifdef Q_WS_X11 519 // X11 needs to catch pixmap data destruction to delete EGL/GLX pixmap surfaces 520 static void cleanupPixmapSurfaces(QPixmap* pixmap); 521 #endif 522 523 private: 524 QCache<qint64, QGLTexture> m_cache; 525 }; 526 527 528 extern Q_OPENGL_EXPORT QPaintEngine* qt_qgl_paint_engine(); 529 530 bool qt_gl_preferGL2Engine(); 531 532 inline GLenum qt_gl_preferredTextureFormat() 533 { 534 return (QGLExtensions::glExtensions & QGLExtensions::BGRATextureFormat) && QSysInfo::ByteOrder == QSysInfo::LittleEndian 535 ? GL_BGRA : GL_RGBA; 536 } 537 538 inline GLenum qt_gl_preferredTextureTarget() 539 { 540 #if defined(QT_OPENGL_ES_2) 541 return GL_TEXTURE_2D; 542 #else 543 return (QGLExtensions::glExtensions & QGLExtensions::TextureRectangle) 544 && !qt_gl_preferGL2Engine() 545 ? GL_TEXTURE_RECTANGLE_NV 546 : GL_TEXTURE_2D; 547 #endif 548 } 549 550 // One resource per group of shared contexts. 551 class Q_AUTOTEST_EXPORT QGLContextResource 552 { 553 public: 554 typedef void (*FreeFunc)(void *); 555 QGLContextResource(FreeFunc f); 556 ~QGLContextResource(); 557 // Set resource 'value' for 'key' and all its shared contexts. 558 void insert(const QGLContext *key, void *value); 559 // Return resource for 'key' or a shared context. 560 void *value(const QGLContext *key); 561 // Cleanup 'value' in response to a context group being destroyed. 562 void cleanup(const QGLContext *ctx, void *value); 563 private: 564 FreeFunc free; 565 QAtomicInt active; 566 }; 567 568 // Put a guard around a GL object identifier and its context. 569 // When the context goes away, a shared context will be used 570 // in its place. If there are no more shared contexts, then 571 // the identifier is returned as zero - it is assumed that the 572 // context destruction cleaned up the identifier in this case. 573 class Q_OPENGL_EXPORT QGLSharedResourceGuard 574 { 575 public: 576 QGLSharedResourceGuard(const QGLContext *context) 577 : m_group(0), m_id(0), m_next(0), m_prev(0) 578 { 579 setContext(context); 580 } 581 QGLSharedResourceGuard(const QGLContext *context, GLuint id) 582 : m_group(0), m_id(id), m_next(0), m_prev(0) 583 { 584 setContext(context); 585 } 586 ~QGLSharedResourceGuard(); 587 588 const QGLContext *context() const 589 { 590 return m_group ? m_group->context() : 0; 591 } 592 593 void setContext(const QGLContext *context); 594 595 GLuint id() const 596 { 597 return m_id; 598 } 599 600 void setId(GLuint id) 601 { 602 m_id = id; 603 } 604 605 private: 606 QGLContextGroup *m_group; 607 GLuint m_id; 608 QGLSharedResourceGuard *m_next; 609 QGLSharedResourceGuard *m_prev; 610 611 friend class QGLContextGroup; 612 }; 613 614 615 // This class can be used to match GL extensions with doing any mallocs. The 616 // class assumes that the GL extension string ends with a space character, 617 // which it should do on all conformant platforms. Create the object and pass 618 // in a pointer to the extension string, then call match() on each extension 619 // that should be matched. The match() function takes the extension name 620 // *without* the terminating space character as input. 621 622 class QGLExtensionMatcher 623 { 624 public: 625 QGLExtensionMatcher(const char *str) 626 : gl_extensions(str), gl_extensions_length(qstrlen(str)) 627 {} 628 629 bool match(const char *str) { 630 int str_length = qstrlen(str); 631 const char *extensions = gl_extensions; 632 int extensions_length = gl_extensions_length; 633 634 while (1) { 635 // the total length that needs to be matched is the str_length + 636 // the space character that terminates the extension name 637 if (extensions_length < str_length + 1) 638 return false; 639 if (qstrncmp(extensions, str, str_length) == 0 && extensions[str_length] == ' ') 333 640 return true; 334 if (checkSharing(ctx, context2, context1)) 335 return true; 641 642 int split_pos = 0; 643 while (split_pos < extensions_length && extensions[split_pos] != ' ') 644 ++split_pos; 645 ++split_pos; // added for the terminating space character 646 extensions += split_pos; 647 extensions_length -= split_pos; 336 648 } 337 649 return false; 338 650 } 339 651 340 void addShare(const QGLContext *context, const QGLContext *share) {341 reg.insert(context, share); // context sharing works both ways342 reg.insert(share, context);343 }344 345 void removeShare(const QGLContext *context) {346 QGLSharingHash::iterator it = reg.begin();347 while (it != reg.end()) {348 if (it.key() == context || it.value() == context)349 it = reg.erase(it);350 else351 ++it;352 }353 }354 355 void replaceShare(const QGLContext *oldContext, const QGLContext *newContext) {356 QGLSharingHash::iterator it = reg.begin();357 while (it != reg.end()) {358 if (it.key() == oldContext)359 reg.insert(newContext, it.value());360 else if (it.value() == oldContext)361 reg.insert(it.key(), newContext);362 ++it;363 }364 removeShare(oldContext);365 }366 367 652 private: 368 QGLSharingHash reg; 369 }; 370 371 extern Q_OPENGL_EXPORT QGLShareRegister* qgl_share_reg(); 372 373 #ifdef Q_WS_QWS 374 class QOpenGLPaintEngine; 375 extern QOpenGLPaintEngine* qt_qgl_paint_engine(); 376 377 extern EGLDisplay qt_qgl_egl_display(); 378 #endif 379 380 inline GLenum qt_gl_preferredTextureFormat() 381 { 382 return QSysInfo::ByteOrder == QSysInfo::BigEndian ? GL_RGBA : GL_BGRA; 383 } 384 385 inline GLenum qt_gl_preferredTextureTarget() 386 { 387 return (QGLExtensions::glExtensions & QGLExtensions::TextureRectangle) 388 ? GL_TEXTURE_RECTANGLE_NV 389 : GL_TEXTURE_2D; 390 } 391 653 const char *gl_extensions; 654 int gl_extensions_length; 655 }; 392 656 393 657 QT_END_NAMESPACE
Note:
See TracChangeset
for help on using the changeset viewer.