Changeset 561 for trunk/src/opengl/qgl.cpp
- 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.cpp
r2 r561 2 2 ** 3 3 ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). 4 ** Contact: Qt Software Information ([email protected]) 4 ** All rights reserved. 5 ** Contact: Nokia Corporation ([email protected]) 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 37 ** @nokia.com. 38 38 ** $QT_END_LICENSE$ 39 39 ** … … 60 60 #endif 61 61 62 63 62 64 #include <stdlib.h> // malloc 63 65 … … 66 68 #include "qgl_p.h" 67 69 68 #if defined(QT_OPENGL_ES_2)70 #if ) 69 71 #include "gl2paintengineex/qpaintengineex_opengl2_p.h" 70 #else 72 #endif 73 74 #ifndef QT_OPENGL_ES_2 71 75 #include <private/qpaintengine_opengl_p.h> 72 76 #endif 77 78 79 80 81 82 83 73 84 74 85 #include <private/qimage_p.h> 75 86 #include <private/qpixmapdata_p.h> 76 87 #include <private/qpixmapdata_gl_p.h> 88 89 90 77 91 #include "qcolormap.h" 78 #include "qcache.h"79 92 #include "qfile.h" 80 93 #include "qlibrary.h" … … 92 105 #endif 93 106 94 QThreadStorage<QGLThreadContext *> qgl_context_storage; 107 struct QGLThreadContext { 108 QGLContext *context; 109 }; 110 111 static QThreadStorage<QGLThreadContext *> qgl_context_storage; 95 112 96 113 Q_GLOBAL_STATIC(QGLFormat, qgl_default_format) … … 111 128 bool QGLExtensions::nvidiaFboNeedsFinish = false; 112 129 113 #ifndef APIENTRY114 # define APIENTRY115 #endif116 typedef void (APIENTRY *pfn_glCompressedTexImage2DARB) (GLenum, GLint, GLenum, GLsizei,117 GLsizei, GLint, GLsizei, const GLvoid *);118 static pfn_glCompressedTexImage2DARB qt_glCompressedTexImage2DARB = 0;119 120 121 #ifndef APIENTRY122 #define APIENTRY123 #endif124 125 130 Q_GLOBAL_STATIC(QGLSignalProxy, theSignalProxy) 126 131 QGLSignalProxy *QGLSignalProxy::instance() … … 129 134 } 130 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 131 204 /*! 132 205 \namespace QGL 206 133 207 134 208 \brief The QGL namespace specifies miscellaneous identifiers used 135 209 in the Qt OpenGL module. 136 210 137 \ingroup multimedia211 \ingroup 138 212 */ 139 213 … … 168 242 */ 169 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 170 270 /***************************************************************************** 171 271 QGLFormat implementation … … 178 278 rendering context. 179 279 180 \ingroup multimedia280 \ingroup 181 281 182 282 A display format has several characteristics: … … 191 291 \i \link setDirectRendering() Direct rendering.\endlink 192 292 \i \link setOverlay() Presence of an overlay.\endlink 193 \i \link setPlane() The plane of an overlay format.\endlink293 \i \link setPlane() .\endlink 194 294 \i \link setSampleBuffers() Multisample buffers.\endlink 195 295 \endlist 196 296 197 You can also specify preferred bit depths for the depth buffer, 198 alpha buffer, accumulation buffer and the stencil buffer with the 199 functions: setDepthBufferSize(), setAlphaBufferSize(), 297 You can also specify preferred bit depths for the color buffer, 298 depth buffer, alpha buffer, accumulation buffer and the stencil 299 buffer with the functions: setRedBufferSize(), setGreenBufferSize(), 300 setBlueBufferSize(), setDepthBufferSize(), setAlphaBufferSize(), 200 301 setAccumBufferSize() and setStencilBufferSize(). 201 302 … … 237 338 \sa QGLContext, QGLWidget 238 339 */ 340 341 239 342 240 343 static inline void transform_point(GLdouble out[4], const GLdouble m[16], const GLdouble in[4]) … … 280 383 } 281 384 282 /*! 283 Constructs a QGLFormat object with the factory default settings: 385 #endif // !QT_OPENGL_ES 386 387 /*! 388 Constructs a QGLFormat object with the following default settings: 284 389 \list 285 390 \i \link setDoubleBuffer() Double buffer:\endlink Enabled. … … 288 393 \i \link setAlpha() Alpha channel:\endlink Disabled. 289 394 \i \link setAccum() Accumulator buffer:\endlink Disabled. 290 \i \link setStencil() Stencil buffer:\endlink Disabled.395 \i \link setStencil() Stencil buffer:\endlink abled. 291 396 \i \link setStereo() Stereo:\endlink Disabled. 292 397 \i \link setDirectRendering() Direct rendering:\endlink Enabled. … … 304 409 305 410 /*! 306 Creates a QGLFormat object that is a copy of the current \link307 defaultFormat() application default format\endlink.308 309 If \a options is not 0, th is copy is modified by these format310 options. The \a options parameter should be \c FormatOption values311 OR'ed together.411 Creates a QGLFormat object that is a copy of the current 412 defaultFormat(). 413 414 If \a options is not 0, th 415 416 OR'ed together. 312 417 313 418 This constructor makes it easy to specify a certain desired format … … 315 420 \snippet doc/src/snippets/code/src_opengl_qgl.cpp 3 316 421 317 Note that there are \cFormatOption values to turn format settings318 both on and off, e.g. \c DepthBuffer and \cNoDepthBuffer,319 \c DirectRendering and \cIndirectRendering, etc.422 Note that there are FormatOption values to turn format settings 423 both on and off, e.g. NoDepthBuffer, 424 IndirectRendering, etc. 320 425 321 426 The \a plane parameter defaults to 0 and is the plane which this … … 323 428 supports overlay/underlay rendering planes. 324 429 325 \sa defaultFormat(), setOption() 430 \sa defaultFormat(), setOption() 326 431 */ 327 432 … … 337 442 338 443 /*! 444 445 446 447 448 449 450 451 452 453 454 455 456 339 457 Constructs a copy of \a other. 340 458 */ … … 342 460 QGLFormat::QGLFormat(const QGLFormat &other) 343 461 { 344 d = new QGLFormatPrivate;345 *d = *other.d;462 d = ; 463 ; 346 464 } 347 465 … … 352 470 QGLFormat &QGLFormat::operator=(const QGLFormat &other) 353 471 { 354 *d = *other.d; 472 if (d != other.d) { 473 other.d->ref.ref(); 474 if (!d->ref.deref()) 475 delete d; 476 d = other.d; 477 } 355 478 return *this; 356 479 } … … 361 484 QGLFormat::~QGLFormat() 362 485 { 363 delete d; 486 if (!d->ref.deref()) 487 delete d; 364 488 } 365 489 … … 515 639 516 640 Returns true if the stencil buffer is enabled; otherwise returns 517 false. The stencil buffer is disabled by default.641 false. The stencil buffer is abled by default. 518 642 519 643 \sa setStencil(), setStencilBufferSize() … … 524 648 disables the stencil buffer. 525 649 526 The stencil buffer is disabled by default.650 The stencil buffer is abled by default. 527 651 528 652 The stencil buffer masks certain parts of the drawing area so that … … 637 761 void QGLFormat::setSamples(int numSamples) 638 762 { 763 639 764 if (numSamples < 0) { 640 765 qWarning("QGLFormat::setSamples: Cannot have negative number of samples per pixel %d", numSamples); … … 664 789 void QGLFormat::setSwapInterval(int interval) 665 790 { 791 666 792 d->swapInterval = interval; 667 793 } … … 709 835 formats is 1, which is the first overlay plane. 710 836 711 \sa setPlane() 837 \sa setPlane() 712 838 */ 713 839 int QGLFormat::plane() const … … 731 857 void QGLFormat::setPlane(int plane) 732 858 { 859 733 860 d->pln = plane; 734 861 } … … 742 869 void QGLFormat::setOption(QGL::FormatOptions opt) 743 870 { 871 744 872 if (opt & 0xffff) 745 873 d->opts |= opt; … … 771 899 void QGLFormat::setDepthBufferSize(int size) 772 900 { 901 773 902 if (size < 0) { 774 903 qWarning("QGLFormat::setDepthBufferSize: Cannot set negative depth buffer size %d", size); … … 797 926 void QGLFormat::setRedBufferSize(int size) 798 927 { 928 799 929 if (size < 0) { 800 930 qWarning("QGLFormat::setRedBufferSize: Cannot set negative red buffer size %d", size); … … 825 955 void QGLFormat::setGreenBufferSize(int size) 826 956 { 957 827 958 if (size < 0) { 828 959 qWarning("QGLFormat::setGreenBufferSize: Cannot set negative green buffer size %d", size); … … 853 984 void QGLFormat::setBlueBufferSize(int size) 854 985 { 986 855 987 if (size < 0) { 856 988 qWarning("QGLFormat::setBlueBufferSize: Cannot set negative blue buffer size %d", size); … … 880 1012 void QGLFormat::setAlphaBufferSize(int size) 881 1013 { 1014 882 1015 if (size < 0) { 883 1016 qWarning("QGLFormat::setAlphaBufferSize: Cannot set negative alpha buffer size %d", size); … … 906 1039 void QGLFormat::setAccumBufferSize(int size) 907 1040 { 1041 908 1042 if (size < 0) { 909 1043 qWarning("QGLFormat::setAccumBufferSize: Cannot set negative accumulate buffer size %d", size); … … 930 1064 void QGLFormat::setStencilBufferSize(int size) 931 1065 { 1066 932 1067 if (size < 0) { 933 1068 qWarning("QGLFormat::setStencilBufferSize: Cannot set negative stencil buffer size %d", size); … … 1125 1260 return defaultVersionFlags; 1126 1261 } else { 1127 cachedDefault = true;1128 1262 if (!hasOpenGL()) 1129 1263 return defaultVersionFlags; 1130 1264 dummy = new QGLWidget; 1131 1265 dummy->makeCurrent(); // glGetString() needs a current context 1266 1132 1267 } 1133 1268 } … … 1149 1284 1150 1285 /*! 1151 Returns the default QGLFormat for the application. All QGLWidget s1152 that are created use this format unless another format is1286 Returns the default QGLFormat for the application. All QGLWidget 1287 that are created use this format unless another format is 1153 1288 specified, e.g. when they are constructed. 1154 1289 … … 1183 1318 Returns the default QGLFormat for overlay contexts. 1184 1319 1185 The factorydefault overlay format is:1320 The default overlay format is: 1186 1321 \list 1187 1322 \i \link setDoubleBuffer() Double buffer:\endlink Disabled. … … 1194 1329 \i \link setDirectRendering() Direct rendering:\endlink Enabled. 1195 1330 \i \link setOverlay() Overlay:\endlink Disabled. 1331 1196 1332 \i \link setPlane() Plane:\endlink 1 (i.e., first overlay plane). 1197 1333 \endlist … … 1236 1372 1237 1373 /*! 1238 Returns true if all the options of the two QGLFormats are equal; 1239 otherwise returns false. 1374 Returns true if all the options of the two QGLFormat objects 1375 \a a and \a b are equal; otherwise returns false. 1376 1377 \relates QGLFormat 1240 1378 */ 1241 1379 … … 1244 1382 return (int) a.d->opts == (int) b.d->opts && a.d->pln == b.d->pln && a.d->alphaSize == b.d->alphaSize 1245 1383 && a.d->accumSize == b.d->accumSize && a.d->stencilSize == b.d->stencilSize 1246 && a.d->depthSize == b.d->depthSize; 1247 } 1248 1249 1250 /*! 1251 Returns false if all the options of the two QGLFormats are equal; 1252 otherwise returns true. 1384 && a.d->depthSize == b.d->depthSize 1385 && a.d->redSize == b.d->redSize 1386 && a.d->greenSize == b.d->greenSize 1387 && a.d->blueSize == b.d->blueSize 1388 && a.d->numSamples == b.d->numSamples 1389 && a.d->swapInterval == b.d->swapInterval; 1390 } 1391 1392 1393 /*! 1394 Returns false if all the options of the two QGLFormat objects 1395 \a a and \a b are equal; otherwise returns true. 1396 1397 \relates QGLFormat 1253 1398 */ 1254 1399 … … 1261 1406 QGLContext implementation 1262 1407 *****************************************************************************/ 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1263 1447 void QGLContextPrivate::init(QPaintDevice *dev, const QGLFormat &format) 1264 1448 { … … 1289 1473 #if defined(QT_OPENGL_ES) 1290 1474 eglContext = 0; 1291 #endif 1292 pbo = 0; 1475 eglSurface = EGL_NO_SURFACE; 1476 #endif 1477 fbo = 0; 1293 1478 crWin = false; 1294 1479 initDone = false; 1295 1480 sharing = false; 1296 clear_on_painter_begin = true;1297 1481 max_texture_size = -1; 1298 1482 version_flags_cached = false; 1299 1483 version_flags = QGLFormat::OpenGL_Version_None; 1484 1485 1486 1300 1487 } 1301 1488 … … 1308 1495 */ 1309 1496 1310 QImage qt_gl_read_framebuffer(const QSize &size, bool alpha_format, bool include_alpha) 1311 { 1312 QImage img(size, alpha_format ? QImage::Format_ARGB32 : QImage::Format_RGB32); 1313 int w = size.width(); 1314 int h = size.height(); 1315 glReadPixels(0, 0, w, h, GL_RGBA, GL_UNSIGNED_BYTE, img.bits()); 1497 static void convertFromGLImage(QImage &img, int w, int h, bool alpha_format, bool include_alpha) 1498 { 1316 1499 if (QSysInfo::ByteOrder == QSysInfo::BigEndian) { 1317 1500 // OpenGL gives RGBA; Qt wants ARGB … … 1328 1511 // we shouldn't remove 1329 1512 while (p < end) { 1330 *p = 0x FF000000 | (*p>>8);1513 *p = 0x000000 | (*p>>8); 1331 1514 ++p; 1332 1515 } … … 1334 1517 } else { 1335 1518 // OpenGL gives ABGR (i.e. RGBA backwards); Qt wants ARGB 1336 img = img.rgbSwapped(); 1337 } 1338 return img.mirrored(); 1519 for (int y = 0; y < h; y++) { 1520 uint *q = (uint*)img.scanLine(y); 1521 for (int x=0; x < w; ++x) { 1522 const uint pixel = *q; 1523 *q = ((pixel << 16) & 0xff0000) | ((pixel >> 16) & 0xff) | (pixel & 0xff00ff00); 1524 q++; 1525 } 1526 } 1527 1528 } 1529 img = img.mirrored(); 1530 } 1531 1532 QImage qt_gl_read_framebuffer(const QSize &size, bool alpha_format, bool include_alpha) 1533 { 1534 QImage img(size, alpha_format ? QImage::Format_ARGB32 : QImage::Format_RGB32); 1535 int w = size.width(); 1536 int h = size.height(); 1537 glReadPixels(0, 0, w, h, GL_RGBA, GL_UNSIGNED_BYTE, img.bits()); 1538 convertFromGLImage(img, w, h, alpha_format, include_alpha); 1539 return img; 1540 } 1541 1542 QImage qt_gl_read_texture(const QSize &size, bool alpha_format, bool include_alpha) 1543 { 1544 QImage img(size, alpha_format ? QImage::Format_ARGB32 : QImage::Format_RGB32); 1545 int w = size.width(); 1546 int h = size.height(); 1547 #if !defined(QT_OPENGL_ES_2) && !defined(QT_OPENGL_ES_1) && !defined(QT_OPENGL_ES_1_CL) 1548 //### glGetTexImage not in GL ES 2.0, need to do something else here! 1549 glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE, img.bits()); 1550 #endif 1551 convertFromGLImage(img, w, h, alpha_format, include_alpha); 1552 return img; 1339 1553 } 1340 1554 … … 1353 1567 } 1354 1568 1355 class QGLTexture {1356 public:1357 QGLTexture(const QGLContext *ctx, GLuint tx_id, GLenum tx_target, bool _clean = false)1358 : context(ctx), id(tx_id), target(tx_target), clean(_clean) {}1359 ~QGLTexture() {1360 if (clean) {1361 QGLContext *current = const_cast<QGLContext *>(QGLContext::currentContext());1362 QGLContext *ctx = const_cast<QGLContext *>(context);1363 bool switch_context = current && current != ctx && !qgl_share_reg()->checkSharing(current, ctx);1364 if (switch_context)1365 ctx->makeCurrent();1366 glDeleteTextures(1, &id);1367 if (switch_context)1368 current->makeCurrent();1369 }1370 }1371 1372 const QGLContext *context;1373 GLuint id;1374 GLenum target;1375 bool clean;1376 };1377 1378 typedef QCache<qint64, QGLTexture> QGLTextureCache;1379 static int qt_tex_cache_limit = 64*1024; // cache ~64 MB worth of textures - this is not accurate though1380 static QGLTextureCache *qt_tex_cache = 0;1381 1382 1569 typedef void (*_qt_pixmap_cleanup_hook_64)(qint64); 1383 1570 typedef void (*_qt_image_cleanup_hook_64)(qint64); … … 1385 1572 extern Q_GUI_EXPORT _qt_pixmap_cleanup_hook_64 qt_pixmap_cleanup_hook_64; 1386 1573 extern Q_GUI_EXPORT _qt_image_cleanup_hook_64 qt_image_cleanup_hook_64; 1574 1575 1576 1577 1578 1579 1580 1581 1582 1583 1584 1585 1586 1587 1588 1589 1590 1591 1592 1593 1594 1595 1596 1597 1598 1599 1600 1601 1602 1603 1604 1605 1606 1607 1608 1609 1610 1611 1612 1613 1614 1615 1616 1617 1618 1619 1620 1621 1622 1623 1624 1625 1626 1627 1628 1629 1630 1631 1632 1633 1634 1635 1636 1637 1638 1639 1640 1641 1642 1643 1644 1645 1646 1647 1648 1649 1650 1651 1652 1653 1654 1655 1656 1657 1658 1659 1660 1661 1662 1663 1664 1665 1666 1667 1668 1669 1670 1671 1672 1673 1674 1675 1676 1677 1678 1679 1680 1681 1682 1683 1684 1685 1686 1687 1688 1689 1690 1691 1692 1693 1694 1387 1695 1388 1696 // DDS format structure … … 1422 1730 #endif 1423 1731 1424 Q_GLOBAL_STATIC(QGLShareRegister, _qgl_share_reg) ;1732 Q_GLOBAL_STATIC(QGLShareRegister, _qgl_share_reg) 1425 1733 Q_OPENGL_EXPORT QGLShareRegister* qgl_share_reg() 1426 1734 { … … 1432 1740 \brief The QGLContext class encapsulates an OpenGL rendering context. 1433 1741 1434 \ingroup multimedia1742 \ingroup 1435 1743 1436 1744 An OpenGL rendering context is a complete set of OpenGL state … … 1457 1765 */ 1458 1766 1767 1768 1769 1770 1771 1772 1773 1774 1775 1776 1777 1778 1779 1780 1781 1782 1783 1784 1785 1786 1787 1788 1789 1790 1791 1792 1793 1794 1795 1796 1797 1798 1799 1800 1801 1802 1803 1804 1805 1806 1807 1459 1808 1460 1809 /*! … … 1477 1826 1478 1827 QGLContext::QGLContext(const QGLFormat &format, QPaintDevice *device) 1479 { 1480 d_ptr = new QGLContextPrivate(this); 1828 : d_ptr(new QGLContextPrivate(this)) 1829 { 1481 1830 Q_D(QGLContext); 1482 1831 d->init(device, format); … … 1500 1849 */ 1501 1850 QGLContext::QGLContext(const QGLFormat &format) 1502 { 1503 d_ptr = new QGLContextPrivate(this); 1851 : d_ptr(new QGLContextPrivate(this)) 1852 { 1504 1853 Q_D(QGLContext); 1505 1854 d->init(0, format); … … 1512 1861 QGLContext::~QGLContext() 1513 1862 { 1514 Q_D(QGLContext);1515 1863 // remove any textures cached in this context 1516 if (qt_tex_cache) { 1517 QList<qint64> keys = qt_tex_cache->keys(); 1518 for (int i = 0; i < keys.size(); ++i) { 1519 const qint64 &key = keys.at(i); 1520 if (qt_tex_cache->object(key)->context == this) 1521 qt_tex_cache->remove(key); 1522 } 1523 // ### thread safety 1524 if (qt_tex_cache->size() == 0) { 1525 qt_pixmap_cleanup_hook_64 = 0; 1526 qt_image_cleanup_hook_64 = 0; 1527 delete qt_tex_cache; 1528 qt_tex_cache = 0; 1529 } 1530 } 1864 QGLTextureCache::instance()->removeContextTextures(this); 1865 QGLTextureCache::deleteIfEmpty(); // ### thread safety 1866 1867 d_ptr->group->cleanupResources(this); 1531 1868 1532 1869 QGLSignalProxy::instance()->emitAboutToDestroyContext(this); 1533 1870 reset(); 1534 delete d;1535 1871 } 1536 1872 1537 1873 void QGLContextPrivate::cleanup() 1538 1874 { 1539 Q_Q(QGLContext); 1540 if (pbo) { 1541 QGLContext *ctx = q; 1542 glDeleteBuffersARB(1, &pbo); 1543 pbo = 0; 1544 } 1545 } 1546 1547 typedef QHash<QString, GLuint> QGLDDSCache; 1548 Q_GLOBAL_STATIC(QGLDDSCache, qgl_dds_cache) 1875 } 1549 1876 1550 1877 /*! 1551 1878 \overload 1552 1879 1553 Reads the DirectDrawSurface (DDS) compressed file \a fileName and 1554 generates a 2D GL texture from it. 1555 1556 Only the DXT1, DXT3 and DXT5 DDS formats are supported. 1557 1558 Note that this will only work if the implementation supports the 1559 \c GL_ARB_texture_compression and \c GL_EXT_texture_compression_s3tc 1560 extensions. 1880 Reads the compressed texture file \a fileName and generates a 2D GL 1881 texture from it. 1882 1883 This function can load DirectDrawSurface (DDS) textures in the 1884 DXT1, DXT3 and DXT5 DDS formats if the \c GL_ARB_texture_compression 1885 and \c GL_EXT_texture_compression_s3tc extensions are supported. 1886 1887 Since 4.6.1, textures in the ETC1 format can be loaded if the 1888 \c GL_OES_compressed_ETC1_RGB8_texture extension is supported 1889 and the ETC1 texture has been encapsulated in the PVR container format. 1890 Also, textures in the PVRTC2 and PVRTC4 formats can be loaded 1891 if the \c GL_IMG_texture_compression_pvrtc extension is supported. 1561 1892 1562 1893 \sa deleteTexture() … … 1565 1896 GLuint QGLContext::bindTexture(const QString &fileName) 1566 1897 { 1567 if (!qt_glCompressedTexImage2DARB) { 1568 qWarning("QGLContext::bindTexture(): The GL implementation does not support texture" 1569 "compression extensions."); 1570 return 0; 1571 } 1572 1573 QGLDDSCache::const_iterator it = qgl_dds_cache()->constFind(fileName); 1574 if (it != qgl_dds_cache()->constEnd()) { 1898 Q_D(QGLContext); 1899 QGLDDSCache *dds_cache = &(d->group->m_dds_cache); 1900 QGLDDSCache::const_iterator it = dds_cache->constFind(fileName); 1901 if (it != dds_cache->constEnd()) { 1575 1902 glBindTexture(GL_TEXTURE_2D, it.value()); 1576 1903 return it.value(); 1577 1904 } 1578 1905 1579 QFile f(fileName); 1580 f.open(QIODevice::ReadOnly); 1581 1582 char tag[4]; 1583 f.read(&tag[0], 4); 1584 if (strncmp(tag,"DDS ", 4) != 0) { 1585 qWarning("QGLContext::bindTexture(): not a DDS image file."); 1906 QGLTexture texture(this); 1907 QSize size = texture.bindCompressedTexture(fileName); 1908 if (!size.isValid()) 1586 1909 return 0; 1587 } 1588 1589 DDSFormat ddsHeader; 1590 f.read((char *) &ddsHeader, sizeof(DDSFormat)); 1591 1592 if (!ddsHeader.dwLinearSize) { 1593 qWarning("QGLContext::bindTexture() DDS image size is not valid."); 1594 return 0; 1595 } 1596 1597 int factor = 4; 1598 int bufferSize = 0; 1599 int blockSize = 16; 1600 GLenum format; 1601 1602 switch(ddsHeader.ddsPixelFormat.dwFourCC) { 1603 case FOURCC_DXT1: 1604 format = GL_COMPRESSED_RGBA_S3TC_DXT1_EXT; 1605 factor = 2; 1606 blockSize = 8; 1607 break; 1608 case FOURCC_DXT3: 1609 format = GL_COMPRESSED_RGBA_S3TC_DXT3_EXT; 1610 break; 1611 case FOURCC_DXT5: 1612 format = GL_COMPRESSED_RGBA_S3TC_DXT5_EXT; 1613 break; 1614 default: 1615 qWarning("QGLContext::bindTexture() DDS image format not supported."); 1616 return 0; 1617 } 1618 1619 if (ddsHeader.dwMipMapCount > 1) 1620 bufferSize = ddsHeader.dwLinearSize * factor; 1621 else 1622 bufferSize = ddsHeader.dwLinearSize; 1623 1624 GLubyte *pixels = (GLubyte *) malloc(bufferSize*sizeof(GLubyte)); 1625 f.seek(ddsHeader.dwSize + 4); 1626 f.read((char *) pixels, bufferSize); 1627 f.close(); 1628 1629 GLuint tx_id; 1630 glGenTextures(1, &tx_id); 1631 glBindTexture(GL_TEXTURE_2D, tx_id); 1632 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 1633 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 1634 1635 int size; 1636 int offset = 0; 1637 int w = ddsHeader.dwWidth; 1638 int h = ddsHeader.dwHeight; 1639 1640 // load mip-maps 1641 for(int i = 0; i < (int) ddsHeader.dwMipMapCount; ++i) { 1642 if (w == 0) w = 1; 1643 if (h == 0) h = 1; 1644 1645 size = ((w+3)/4) * ((h+3)/4) * blockSize; 1646 qt_glCompressedTexImage2DARB(GL_TEXTURE_2D, i, format, w, h, 0, 1647 size, pixels + offset); 1648 offset += size; 1649 1650 // half size for each mip-map level 1651 w = w/2; 1652 h = h/2; 1653 } 1654 1655 free(pixels); 1656 1657 qgl_dds_cache()->insert(fileName, tx_id); 1658 return tx_id; 1659 } 1660 1661 /* 1662 a hook that removes textures from the cache when a pixmap/image 1663 is deref'ed 1664 */ 1665 static void qt_gl_clean_cache(qint64 cacheKey) 1666 { 1667 // ### remove when the GL texture cache becomes thread-safe 1668 if (qApp->thread() != QThread::currentThread()) 1669 return; 1670 if (qt_tex_cache) { 1671 QGLTexture *texture = qt_tex_cache->object(cacheKey); 1672 if (texture && texture->clean) 1673 qt_tex_cache->remove(cacheKey); 1674 } 1910 1911 dds_cache->insert(fileName, texture.id); 1912 return texture.id; 1913 } 1914 1915 static inline QRgb qt_gl_convertToGLFormatHelper(QRgb src_pixel, GLenum texture_format) 1916 { 1917 if (texture_format == GL_BGRA) { 1918 if (QSysInfo::ByteOrder == QSysInfo::BigEndian) { 1919 return ((src_pixel << 24) & 0xff000000) 1920 | ((src_pixel >> 24) & 0x000000ff) 1921 | ((src_pixel << 8) & 0x00ff0000) 1922 | ((src_pixel >> 8) & 0x0000ff00); 1923 } else { 1924 return src_pixel; 1925 } 1926 } else { // GL_RGBA 1927 if (QSysInfo::ByteOrder == QSysInfo::BigEndian) { 1928 return (src_pixel << 8) | ((src_pixel >> 24) & 0xff); 1929 } else { 1930 return ((src_pixel << 16) & 0xff0000) 1931 | ((src_pixel >> 16) & 0xff) 1932 | (src_pixel & 0xff00ff00); 1933 } 1934 } 1935 } 1936 1937 QRgb qt_gl_convertToGLFormat(QRgb src_pixel, GLenum texture_format) 1938 { 1939 return qt_gl_convertToGLFormatHelper(src_pixel, texture_format); 1675 1940 } 1676 1941 1677 1942 static void convertToGLFormatHelper(QImage &dst, const QImage &img, GLenum texture_format) 1678 1943 { 1679 Q_ASSERT(dst.size() == img.size());1680 1944 Q_ASSERT(dst.depth() == 32); 1681 1945 Q_ASSERT(img.depth() == 32); 1682 1946 1683 const int width = img.width(); 1684 const int height = img.height(); 1685 const uint *p = (const uint*) img.scanLine(img.height() - 1); 1686 uint *q = (uint*) dst.scanLine(0); 1687 1688 if (texture_format == GL_BGRA) { 1689 if (QSysInfo::ByteOrder == QSysInfo::BigEndian) { 1690 // mirror + swizzle 1691 for (int i=0; i < height; ++i) { 1692 const uint *end = p + width; 1693 while (p < end) { 1694 *q = ((*p << 24) & 0xff000000) 1695 | ((*p >> 24) & 0x000000ff) 1696 | ((*p << 8) & 0x00ff0000) 1697 | ((*p >> 8) & 0x0000ff00); 1698 p++; 1699 q++; 1947 if (dst.size() != img.size()) { 1948 int target_width = dst.width(); 1949 int target_height = dst.height(); 1950 qreal sx = target_width / qreal(img.width()); 1951 qreal sy = target_height / qreal(img.height()); 1952 1953 quint32 *dest = (quint32 *) dst.scanLine(0); // NB! avoid detach here 1954 uchar *srcPixels = (uchar *) img.scanLine(img.height() - 1); 1955 int sbpl = img.bytesPerLine(); 1956 int dbpl = dst.bytesPerLine(); 1957 1958 int ix = int(0x00010000 / sx); 1959 int iy = int(0x00010000 / sy); 1960 1961 quint32 basex = int(0.5 * ix); 1962 quint32 srcy = int(0.5 * iy); 1963 1964 // scale, swizzle and mirror in one loop 1965 while (target_height--) { 1966 const uint *src = (const quint32 *) (srcPixels - (srcy >> 16) * sbpl); 1967 int srcx = basex; 1968 for (int x=0; x<target_width; ++x) { 1969 dest[x] = qt_gl_convertToGLFormatHelper(src[srcx >> 16], texture_format); 1970 srcx += ix; 1971 } 1972 dest = (quint32 *)(((uchar *) dest) + dbpl); 1973 srcy += iy; 1974 } 1975 } else { 1976 const int width = img.width(); 1977 const int height = img.height(); 1978 const uint *p = (const uint*) img.scanLine(img.height() - 1); 1979 uint *q = (uint*) dst.scanLine(0); 1980 1981 if (texture_format == GL_BGRA) { 1982 if (QSysInfo::ByteOrder == QSysInfo::BigEndian) { 1983 // mirror + swizzle 1984 for (int i=0; i < height; ++i) { 1985 const uint *end = p + width; 1986 while (p < end) { 1987 *q = ((*p << 24) & 0xff000000) 1988 | ((*p >> 24) & 0x000000ff) 1989 | ((*p << 8) & 0x00ff0000) 1990 | ((*p >> 8) & 0x0000ff00); 1991 p++; 1992 q++; 1993 } 1994 p -= 2 * width; 1700 1995 } 1701 p -= 2 * width; 1996 } else { 1997 const uint bytesPerLine = img.bytesPerLine(); 1998 for (int i=0; i < height; ++i) { 1999 memcpy(q, p, bytesPerLine); 2000 q += width; 2001 p -= width; 2002 } 1702 2003 } 1703 2004 } else { 1704 const uint bytesPerLine = img.bytesPerLine(); 1705 for (int i=0; i < height; ++i) { 1706 memcpy(q, p, bytesPerLine); 1707 q += width; 1708 p -= width; 1709 } 1710 } 1711 } else { 1712 if (QSysInfo::ByteOrder == QSysInfo::BigEndian) { 1713 for (int i=0; i < height; ++i) { 1714 const uint *end = p + width; 1715 while (p < end) { 1716 *q = (*p << 8) | ((*p >> 24) & 0xFF); 1717 p++; 1718 q++; 2005 if (QSysInfo::ByteOrder == QSysInfo::BigEndian) { 2006 for (int i=0; i < height; ++i) { 2007 const uint *end = p + width; 2008 while (p < end) { 2009 *q = (*p << 8) | ((*p >> 24) & 0xff); 2010 p++; 2011 q++; 2012 } 2013 p -= 2 * width; 1719 2014 } 1720 p -= 2 * width;1721 }1722 } else {1723 for (int i=0; i < height; ++i) {1724 const uint *end = p + width;1725 while (p < end) {1726 *q = ((*p << 16) & 0xff0000) | ((*p >> 16) & 0xff) | (*p & 0xff00ff00);1727 p++;1728 q++;2015 2016 2017 2018 ) { 2019 ; 2020 2021 ; 2022 2023 ; 1729 2024 } 1730 p -= 2 * width;1731 2025 } 1732 2026 } … … 1746 2040 } 1747 2041 1748 GLuint QGLContextPrivate::bindTexture(const QImage &image, GLenum target, GLint format, 1749 const qint64 key, bool clean) 2042 /*! \internal */ 2043 QGLTexture *QGLContextPrivate::bindTexture(const QImage &image, GLenum target, GLint format, 2044 QGLContext::BindOptions options) 2045 { 2046 const qint64 key = image.cacheKey(); 2047 QGLTexture *texture = textureCacheLookup(key, target); 2048 if (texture) { 2049 glBindTexture(target, texture->id); 2050 return texture; 2051 } 2052 2053 if (!texture) 2054 texture = bindTexture(image, target, format, key, options); 2055 // NOTE: bindTexture(const QImage&, GLenum, GLint, const qint64, bool) should never return null 2056 Q_ASSERT(texture); 2057 2058 if (texture->id > 0) 2059 QImagePixmapCleanupHooks::enableCleanupHooks(image); 2060 2061 return texture; 2062 } 2063 2064 // #define QGL_BIND_TEXTURE_DEBUG 2065 2066 // map from Qt's ARGB endianness-dependent format to GL's big-endian RGBA layout 2067 static inline void qgl_byteSwapImage(QImage &img, GLenum pixel_type) 2068 { 2069 const int width = img.width(); 2070 const int height = img.height(); 2071 2072 if (pixel_type == GL_UNSIGNED_INT_8_8_8_8_REV 2073 || (pixel_type == GL_UNSIGNED_BYTE && QSysInfo::ByteOrder == QSysInfo::LittleEndian)) 2074 { 2075 for (int i = 0; i < height; ++i) { 2076 uint *p = (uint *) img.scanLine(i); 2077 for (int x = 0; x < width; ++x) 2078 p[x] = ((p[x] << 16) & 0xff0000) | ((p[x] >> 16) & 0xff) | (p[x] & 0xff00ff00); 2079 } 2080 } else { 2081 for (int i = 0; i < height; ++i) { 2082 uint *p = (uint *) img.scanLine(i); 2083 for (int x = 0; x < width; ++x) 2084 p[x] = (p[x] << 8) | ((p[x] >> 24) & 0xff); 2085 } 2086 } 2087 } 2088 2089 QGLTexture* QGLContextPrivate::bindTexture(const QImage &image, GLenum target, GLint internalFormat, 2090 const qint64 key, QGLContext::BindOptions options) 1750 2091 { 1751 2092 Q_Q(QGLContext); 1752 2093 1753 QGLContext *ctx = q; 1754 1755 bool use_pbo = false; 1756 if (QGLExtensions::glExtensions & QGLExtensions::PixelBufferObject) { 1757 1758 use_pbo = qt_resolve_buffer_extensions(ctx); 1759 if (use_pbo && pbo == 0) 1760 glGenBuffersARB(1, &pbo); 1761 } 1762 1763 // the GL_BGRA format is only present in GL version >= 1.2 1764 GLenum texture_format = (QGLFormat::openGLVersionFlags() & QGLFormat::OpenGL_Version_1_2) 1765 ? GL_BGRA : GL_RGBA; 1766 if (!qt_tex_cache) { 1767 qt_tex_cache = new QGLTextureCache(qt_tex_cache_limit); 1768 qt_pixmap_cleanup_hook_64 = qt_gl_clean_cache; 1769 qt_image_cleanup_hook_64 = qt_gl_clean_cache; 1770 } 2094 #ifdef QGL_BIND_TEXTURE_DEBUG 2095 printf("QGLContextPrivate::bindTexture(), imageSize=(%d,%d), internalFormat =0x%x, options=%x\n", 2096 image.width(), image.height(), internalFormat, int(options)); 2097 QTime time; 2098 time.start(); 2099 #endif 2100 2101 #ifndef QT_NO_DEBUG 2102 // Reset the gl error stack...git 2103 while (glGetError() != GL_NO_ERROR) ; 2104 #endif 1771 2105 1772 2106 // Scale the pixmap if needed. GL textures needs to have the 1773 // dimensions 2^n+2(border) x 2^m+2(border). 2107 // dimensions 2^n+2(border) x 2^m+2(border), unless we're using GL 2108 // 2.0 or use the GL_TEXTURE_RECTANGLE texture target 1774 2109 int tx_w = qt_next_power_of_two(image.width()); 1775 2110 int tx_h = qt_next_power_of_two(image.height()); 1776 2111 1777 // Note: the clean param is only true when a texture is bound1778 // from the QOpenGLPaintEngine - in that case we have to force1779 // a premultiplied texture format1780 2112 QImage img = image; 1781 if ( ( !(QGLFormat::openGLVersionFlags() & QGLFormat::OpenGL_Version_2_0) &&1782 !(QGLFormat::openGLVersionFlags() & QGLFormat::OpenGL_ES_Version_2_0))2113 if ( 2114 ) 1783 2115 && (target == GL_TEXTURE_2D && (tx_w != image.width() || tx_h != image.height()))) 1784 2116 { 1785 img = image.scaled(tx_w, tx_h); 1786 } 2117 img = img.scaled(tx_w, tx_h); 2118 #ifdef QGL_BIND_TEXTURE_DEBUG 2119 printf(" - upscaled to %dx%d (%d ms)\n", tx_w, tx_h, time.elapsed()); 2120 2121 #endif 2122 } 2123 2124 GLuint filtering = options & QGLContext::LinearFilteringBindOption ? GL_LINEAR : GL_NEAREST; 1787 2125 1788 2126 GLuint tx_id; 1789 2127 glGenTextures(1, &tx_id); 1790 2128 glBindTexture(target, tx_id); 1791 glTexParameterf(target, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 2129 glTexParameterf(target, GL_TEXTURE_MAG_FILTER, filtering); 2130 2131 #if defined(QT_OPENGL_ES_2) 2132 bool genMipmap = false; 2133 #endif 1792 2134 if (glFormat.directRendering() 1793 && QGLExtensions::glExtensions & QGLExtensions::GenerateMipmap 1794 && target == GL_TEXTURE_2D && !clean) 2135 && (QGLExtensions::glExtensions & QGLExtensions::GenerateMipmap) 2136 && target == GL_TEXTURE_2D 2137 && (options & QGLContext::MipmapBindOption)) 1795 2138 { 2139 2140 2141 2142 1796 2143 glHint(GL_GENERATE_MIPMAP_HINT_SGIS, GL_NICEST); 1797 2144 #ifndef QT_OPENGL_ES … … 1800 2147 glTexParameterf(target, GL_GENERATE_MIPMAP_SGIS, GL_TRUE); 1801 2148 #endif 1802 glTexParameterf(target, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); 1803 1804 // Mipmap generation causes huge slowdown with PBO's for some reason 1805 use_pbo = false; 2149 #else 2150 glHint(GL_GENERATE_MIPMAP_HINT, GL_NICEST); 2151 genMipmap = true; 2152 #endif 2153 glTexParameterf(target, GL_TEXTURE_MIN_FILTER, options & QGLContext::LinearFilteringBindOption 2154 ? GL_LINEAR_MIPMAP_LINEAR : GL_NEAREST_MIPMAP_NEAREST); 1806 2155 } else { 1807 glTexParameterf(target, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 1808 } 1809 1810 uchar *ptr = 0; 1811 if (use_pbo) { 1812 glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, pbo); 1813 glBufferDataARB(GL_PIXEL_UNPACK_BUFFER_ARB, img.width() * img.height() * 4, 0, GL_STREAM_DRAW_ARB); 1814 ptr = reinterpret_cast<uchar *>(glMapBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, GL_WRITE_ONLY_ARB)); 1815 } 1816 1817 if (ptr) { 1818 QImage::Format target_format = img.format(); 1819 if (clean || img.format() != QImage::Format_ARGB32) 1820 target_format = QImage::Format_ARGB32_Premultiplied; 1821 1822 QImage buffer(ptr, img.width(), img.height(), target_format); 1823 convertToGLFormatHelper(buffer, img.convertToFormat(target_format), texture_format); 1824 glUnmapBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB); 1825 glTexImage2D(target, 0, format, img.width(), img.height(), 0, texture_format, GL_UNSIGNED_BYTE, 0); 2156 glTexParameterf(target, GL_TEXTURE_MIN_FILTER, filtering); 2157 } 2158 2159 QImage::Format target_format = img.format(); 2160 bool premul = options & QGLContext::PremultipliedAlphaBindOption; 2161 GLenum externalFormat; 2162 GLuint pixel_type; 2163 if (QGLExtensions::glExtensions & QGLExtensions::BGRATextureFormat) { 2164 externalFormat = GL_BGRA; 2165 pixel_type = GL_UNSIGNED_INT_8_8_8_8_REV; 1826 2166 } else { 1827 QImage tx = convertToGLFormat(img, clean, texture_format); 1828 glTexImage2D(target, 0, format, tx.width(), tx.height(), 0, texture_format, 1829 GL_UNSIGNED_BYTE, tx.bits()); 1830 } 1831 1832 if (use_pbo) 1833 glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, 0); 2167 externalFormat = GL_RGBA; 2168 pixel_type = GL_UNSIGNED_BYTE; 2169 } 2170 2171 switch (target_format) { 2172 case QImage::Format_ARGB32: 2173 if (premul) { 2174 img = img.convertToFormat(target_format = QImage::Format_ARGB32_Premultiplied); 2175 #ifdef QGL_BIND_TEXTURE_DEBUG 2176 printf(" - converting ARGB32 -> ARGB32_Premultiplied (%d ms) \n", time.elapsed()); 2177 #endif 2178 } 2179 break; 2180 case QImage::Format_ARGB32_Premultiplied: 2181 if (!premul) { 2182 img = img.convertToFormat(target_format = QImage::Format_ARGB32); 2183 #ifdef QGL_BIND_TEXTURE_DEBUG 2184 printf(" - converting ARGB32_Premultiplied -> ARGB32 (%d ms)\n", time.elapsed()); 2185 #endif 2186 } 2187 break; 2188 case QImage::Format_RGB16: 2189 pixel_type = GL_UNSIGNED_SHORT_5_6_5; 2190 externalFormat = GL_RGB; 2191 internalFormat = GL_RGB; 2192 break; 2193 case QImage::Format_RGB32: 2194 break; 2195 default: 2196 if (img.hasAlphaChannel()) { 2197 img = img.convertToFormat(premul 2198 ? QImage::Format_ARGB32_Premultiplied 2199 : QImage::Format_ARGB32); 2200 #ifdef QGL_BIND_TEXTURE_DEBUG 2201 printf(" - converting to 32-bit alpha format (%d ms)\n", time.elapsed()); 2202 #endif 2203 } else { 2204 img = img.convertToFormat(QImage::Format_RGB32); 2205 #ifdef QGL_BIND_TEXTURE_DEBUG 2206 printf(" - converting to 32-bit (%d ms)\n", time.elapsed()); 2207 #endif 2208 } 2209 } 2210 2211 if (options & QGLContext::InvertedYBindOption) { 2212 #ifdef QGL_BIND_TEXTURE_DEBUG 2213 printf(" - flipping bits over y (%d ms)\n", time.elapsed()); 2214 #endif 2215 if (img.isDetached()) { 2216 int ipl = img.bytesPerLine() / 4; 2217 int h = img.height(); 2218 for (int y=0; y<h/2; ++y) { 2219 int *a = (int *) img.scanLine(y); 2220 int *b = (int *) img.scanLine(h - y - 1); 2221 for (int x=0; x<ipl; ++x) 2222 qSwap(a[x], b[x]); 2223 } 2224 } else { 2225 // Create a new image and copy across. If we use the 2226 // above in-place code then a full copy of the image is 2227 // made before the lines are swapped, which processes the 2228 // data twice. This version should only do it once. 2229 img = img.mirrored(); 2230 } 2231 } 2232 2233 if (externalFormat == GL_RGBA) { 2234 #ifdef QGL_BIND_TEXTURE_DEBUG 2235 printf(" - doing byte swapping (%d ms)\n", time.elapsed()); 2236 #endif 2237 // The only case where we end up with a depth different from 2238 // 32 in the switch above is for the RGB16 case, where we set 2239 // the format to GL_RGB 2240 Q_ASSERT(img.depth() == 32); 2241 qgl_byteSwapImage(img, pixel_type); 2242 } 2243 #ifdef QT_OPENGL_ES 2244 // OpenGL/ES requires that the internal and external formats be identical. 2245 // This is typically used to convert GL_RGBA into GL_BGRA. 2246 // Also, we need to use GL_UNSIGNED_BYTE when the format is GL_BGRA. 2247 internalFormat = externalFormat; 2248 if (pixel_type == GL_UNSIGNED_INT_8_8_8_8_REV) 2249 pixel_type = GL_UNSIGNED_BYTE; 2250 #endif 2251 #ifdef QGL_BIND_TEXTURE_DEBUG 2252 printf(" - uploading, image.format=%d, externalFormat=0x%x, internalFormat=0x%x, pixel_type=0x%x\n", 2253 img.format(), externalFormat, internalFormat, pixel_type); 2254 #endif 2255 2256 const QImage &constRef = img; // to avoid detach in bits()... 2257 glTexImage2D(target, 0, internalFormat, img.width(), img.height(), 0, externalFormat, 2258 pixel_type, constRef.bits()); 2259 #if defined(QT_OPENGL_ES_2) 2260 if (genMipmap) 2261 glGenerateMipmap(target); 2262 #endif 2263 #ifndef QT_NO_DEBUG 2264 GLenum error = glGetError(); 2265 if (error != GL_NO_ERROR) { 2266 qWarning(" - texture upload failed, error code 0x%x\n", error); 2267 } 2268 #endif 2269 2270 #ifdef QGL_BIND_TEXTURE_DEBUG 2271 static int totalUploadTime = 0; 2272 totalUploadTime += time.elapsed(); 2273 printf(" - upload done in (%d ms) time=%d\n", time.elapsed(), totalUploadTime); 2274 #endif 2275 1834 2276 1835 2277 // this assumes the size of a texture is always smaller than the max cache size 1836 2278 int cost = img.width()*img.height()*4/1024; 1837 if (qt_tex_cache->totalCost() + cost > qt_tex_cache->maxCost()) { 1838 // the cache is full - make an attempt to remove something 1839 const QList<qint64> keys = qt_tex_cache->keys(); 1840 int i = 0; 1841 while (i < qt_tex_cache->count() 1842 && (qt_tex_cache->totalCost() + cost > qt_tex_cache->maxCost())) { 1843 QGLTexture *tex = qt_tex_cache->object(keys.at(i)); 1844 if (tex->context == q) 1845 qt_tex_cache->remove(keys.at(i)); 1846 ++i; 2279 QGLTexture *texture = new QGLTexture(q, tx_id, target, options); 2280 QGLTextureCache::instance()->insert(q, key, texture, cost); 2281 return texture; 2282 } 2283 2284 QGLTexture *QGLContextPrivate::textureCacheLookup(const qint64 key, GLenum target) 2285 { 2286 Q_Q(QGLContext); 2287 QGLTexture *texture = QGLTextureCache::instance()->getTexture(key); 2288 if (texture && texture->target == target 2289 && (texture->context == q || QGLContext::areSharing(q, texture->context))) 2290 { 2291 return texture; 2292 } 2293 return 0; 2294 } 2295 2296 2297 /*! \internal */ 2298 QGLTexture *QGLContextPrivate::bindTexture(const QPixmap &pixmap, GLenum target, GLint format, QGLContext::BindOptions options) 2299 { 2300 Q_Q(QGLContext); 2301 QPixmapData *pd = pixmap.pixmapData(); 2302 #if !defined(QT_OPENGL_ES_1) && !defined(QT_OPENGL_ES_1_CL) 2303 if (target == GL_TEXTURE_2D && pd->classId() == QPixmapData::OpenGLClass) { 2304 const QGLPixmapData *data = static_cast<const QGLPixmapData *>(pd); 2305 2306 if (data->isValidContext(q)) { 2307 data->bind(); 2308 return data->texture(); 1847 2309 } 1848 2310 } 1849 qt_tex_cache->insert(key, new QGLTexture(q, tx_id, target, clean), cost); 1850 return tx_id; 1851 } 1852 1853 bool QGLContextPrivate::textureCacheLookup(const qint64 key, GLenum target, GLuint *id) 1854 { 1855 Q_Q(QGLContext); 1856 if (qt_tex_cache) { 1857 QGLTexture *texture = qt_tex_cache->object(key); 1858 if (texture && texture->target == target 1859 && (texture->context == q || qgl_share_reg()->checkSharing(q, texture->context))) 1860 { 1861 *id = texture->id; 1862 return true; 2311 #else 2312 Q_UNUSED(pd); 2313 Q_UNUSED(q); 2314 #endif 2315 2316 const qint64 key = pixmap.cacheKey(); 2317 QGLTexture *texture = textureCacheLookup(key, target); 2318 if (texture) { 2319 glBindTexture(target, texture->id); 2320 return texture; 2321 } 2322 2323 #if defined(Q_WS_X11) 2324 // Try to use texture_from_pixmap 2325 if (pd->classId() == QPixmapData::X11Class && pd->pixelType() == QPixmapData::PixmapType) { 2326 texture = bindTextureFromNativePixmap(pd, key, options); 2327 if (texture) { 2328 texture->options |= QGLContext::MemoryManagedBindOption; 2329 texture->boundPixmap = pd; 2330 boundPixmaps.insert(pd, QPixmap(pixmap)); 1863 2331 } 1864 2332 } 1865 return false; 1866 } 1867 1868 /*! \internal */ 1869 GLuint QGLContextPrivate::bindTexture(const QImage &image, GLenum target, GLint format, bool clean) 1870 { 1871 const qint64 key = image.cacheKey(); 1872 GLuint id; 1873 if (textureCacheLookup(key, target, &id)) { 1874 glBindTexture(target, id); 1875 return id; 1876 } 1877 GLuint cached = bindTexture(image, target, format, key, clean); 1878 const_cast<QImage &>(image).data_ptr()->is_cached = (cached > 0); 1879 return cached; 1880 } 1881 1882 /*! \internal */ 1883 GLuint QGLContextPrivate::bindTexture(const QPixmap &pixmap, GLenum target, GLint format, bool clean) 1884 { 1885 #if !defined(QT_OPENGL_ES_2) 1886 if (target == qt_gl_preferredTextureTarget() && pixmap.pixmapData()->classId() == QPixmapData::OpenGLClass) { 1887 const QGLPixmapData *data = static_cast<const QGLPixmapData *>(pixmap.pixmapData()); 1888 1889 if (data->isValidContext(QGLContext::currentContext())) 1890 return data->bind(); 1891 } 1892 #endif 1893 1894 const qint64 key = pixmap.cacheKey(); 1895 GLuint id; 1896 if (textureCacheLookup(key, target, &id)) { 1897 glBindTexture(target, id); 1898 return id; 1899 } 1900 GLuint cached = bindTexture(pixmap.toImage(), target, format, key, clean); 1901 const_cast<QPixmap &>(pixmap).data_ptr()->is_cached = (cached > 0); 1902 return cached; 2333 #endif 2334 2335 if (!texture) 2336 texture = bindTexture(pixmap.toImage(), target, format, key, options); 2337 // NOTE: bindTexture(const QImage&, GLenum, GLint, const qint64, bool) should never return null 2338 Q_ASSERT(texture); 2339 2340 if (texture->id > 0) 2341 QImagePixmapCleanupHooks::enableCleanupHooks(pixmap); 2342 2343 return texture; 1903 2344 } 1904 2345 … … 1939 2380 1940 2381 /*! 2382 2383 2384 2385 2386 2387 2388 2389 2390 2391 2392 2393 2394 2395 2396 2397 2398 2399 2400 1941 2401 Generates and binds a 2D GL texture to the current context, based 1942 2402 on \a image. The generated texture id is returned and can be used … … 1947 2407 1948 2408 The \a format parameter sets the internal format for the 1949 texture. The default format is \c GL_RGBA8. 1950 1951 If the GL implementation supports the \c GL_SGIS_generate_mipmap 1952 extension, mipmaps will be automatically generated for the 1953 texture. Mipmap generation is only supported for the \c 1954 GL_TEXTURE_2D target. 2409 texture. The default format is \c GL_RGBA. 2410 2411 The binding \a options are a set of options used to decide how to 2412 bind the texture to the context. 1955 2413 1956 2414 The texture that is generated is cached, so multiple calls to … … 1963 2421 \sa deleteTexture() 1964 2422 */ 1965 GLuint QGLContext::bindTexture(const QImage &image, GLenum target, GLint format) 1966 { 2423 GLuint QGLContext::bindTexture(const QImage &image, GLenum target, GLint format, BindOptions options) 2424 { 2425 if (image.isNull()) 2426 return 0; 2427 1967 2428 Q_D(QGLContext); 1968 return d->bindTexture(image, target, format, false); 2429 QGLTexture *texture = d->bindTexture(image, target, format, false, options); 2430 return texture->id; 1969 2431 } 1970 2432 … … 1973 2435 GLuint QGLContext::bindTexture(const QImage &image, QMacCompatGLenum target, QMacCompatGLint format) 1974 2436 { 2437 2438 2439 1975 2440 Q_D(QGLContext); 1976 return d->bindTexture(image, GLenum(target), GLint(format), false); 2441 QGLTexture *texture = d->bindTexture(image, GLenum(target), GLint(format), false, DefaultBindOption); 2442 return texture->id; 2443 } 2444 2445 /*! \internal */ 2446 GLuint QGLContext::bindTexture(const QImage &image, QMacCompatGLenum target, QMacCompatGLint format, 2447 BindOptions options) 2448 { 2449 if (image.isNull()) 2450 return 0; 2451 2452 Q_D(QGLContext); 2453 QGLTexture *texture = d->bindTexture(image, GLenum(target), GLint(format), false, options); 2454 return texture->id; 1977 2455 } 1978 2456 #endif … … 1984 2462 GLuint QGLContext::bindTexture(const QPixmap &pixmap, GLenum target, GLint format) 1985 2463 { 2464 2465 2466 1986 2467 Q_D(QGLContext); 1987 return d->bindTexture(pixmap, target, format, false); 2468 QGLTexture *texture = d->bindTexture(pixmap, target, format, DefaultBindOption); 2469 return texture->id; 2470 } 2471 2472 /*! 2473 \overload 2474 \since 4.6 2475 2476 Generates and binds a 2D GL texture to the current context, based 2477 on \a pixmap. 2478 */ 2479 GLuint QGLContext::bindTexture(const QPixmap &pixmap, GLenum target, GLint format, BindOptions options) 2480 { 2481 if (pixmap.isNull()) 2482 return 0; 2483 2484 Q_D(QGLContext); 2485 QGLTexture *texture = d->bindTexture(pixmap, target, format, options); 2486 return texture->id; 1988 2487 } 1989 2488 … … 1992 2491 GLuint QGLContext::bindTexture(const QPixmap &pixmap, QMacCompatGLenum target, QMacCompatGLint format) 1993 2492 { 2493 2494 2495 1994 2496 Q_D(QGLContext); 1995 return d->bindTexture(pixmap, GLenum(target), GLint(format), false); 2497 QGLTexture *texture = d->bindTexture(pixmap, GLenum(target), GLint(format), DefaultBindOption); 2498 return texture->id; 2499 } 2500 /*! \internal */ 2501 GLuint QGLContext::bindTexture(const QPixmap &pixmap, QMacCompatGLenum target, QMacCompatGLint format, 2502 BindOptions options) 2503 { 2504 if (pixmap.isNull()) 2505 return 0; 2506 2507 Q_D(QGLContext); 2508 QGLTexture *texture = d->bindTexture(pixmap, GLenum(target), GLint(format), options); 2509 return texture->id; 1996 2510 } 1997 2511 #endif … … 2006 2520 void QGLContext::deleteTexture(GLuint id) 2007 2521 { 2008 if (qt_tex_cache) { 2009 QList<qint64> keys = qt_tex_cache->keys(); 2010 for (int i = 0; i < keys.size(); ++i) { 2011 QGLTexture *tex = qt_tex_cache->object(keys.at(i)); 2012 if (tex->id == id && tex->context == this) { 2013 tex->clean = true; // forces a glDeleteTextures() call 2014 qt_tex_cache->remove(keys.at(i)); 2015 return; 2016 } 2017 } 2018 } 2522 Q_D(QGLContext); 2523 2524 if (QGLTextureCache::instance()->remove(this, id)) 2525 return; 2019 2526 2020 2527 // check the DDS cache if the texture wasn't found in the pixmap/image 2021 2528 // cache 2022 QList<QString> ddsKeys = qgl_dds_cache()->keys(); 2529 QGLDDSCache *dds_cache = &(d->group->m_dds_cache); 2530 QList<QString> ddsKeys = dds_cache->keys(); 2023 2531 for (int i = 0; i < ddsKeys.size(); ++i) { 2024 GLuint texture = qgl_dds_cache()->value(ddsKeys.at(i));2532 GLuint texture = ->value(ddsKeys.at(i)); 2025 2533 if (id == texture) { 2026 2534 glDeleteTextures(1, &texture); 2027 qgl_dds_cache()->remove(ddsKeys.at(i));2535 ->remove(ddsKeys.at(i)); 2028 2536 return; 2029 2537 } … … 2039 2547 #endif 2040 2548 2041 // qpaintengine_opengl.cpp 2549 void qt_add_rect_to_array(const QRectF &r, q_vertexType *array) 2550 { 2551 qreal left = r.left(); 2552 qreal right = r.right(); 2553 qreal top = r.top(); 2554 qreal bottom = r.bottom(); 2555 2556 array[0] = f2vt(left); 2557 array[1] = f2vt(top); 2558 array[2] = f2vt(right); 2559 array[3] = f2vt(top); 2560 array[4] = f2vt(right); 2561 array[5] = f2vt(bottom); 2562 array[6] = f2vt(left); 2563 array[7] = f2vt(bottom); 2564 } 2565 2566 void qt_add_texcoords_to_array(qreal x1, qreal y1, qreal x2, qreal y2, q_vertexType *array) 2567 { 2568 array[0] = f2vt(x1); 2569 array[1] = f2vt(y1); 2570 array[2] = f2vt(x2); 2571 array[3] = f2vt(y1); 2572 array[4] = f2vt(x2); 2573 array[5] = f2vt(y2); 2574 array[6] = f2vt(x1); 2575 array[7] = f2vt(y2); 2576 } 2577 2042 2578 #if !defined(QT_OPENGL_ES_2) 2043 extern void qt_add_rect_to_array(const QRectF &r, q_vertexType *array);2044 #else2045 void qt_add_rect_to_array(const QRectF &r, q_vertexType *array) {};2046 #endif2047 2579 2048 2580 static void qDrawTextureRect(const QRectF &target, GLint textureWidth, GLint textureHeight, GLenum textureTarget) … … 2074 2606 qt_add_rect_to_array(target, vertexArray); 2075 2607 2076 #if !defined(QT_OPENGL_ES_2)2077 2608 glVertexPointer(2, q_vertexTypeEnum, 0, vertexArray); 2078 2609 glTexCoordPointer(2, q_vertexTypeEnum, 0, texCoordArray); … … 2084 2615 glDisableClientState(GL_VERTEX_ARRAY); 2085 2616 glDisableClientState(GL_TEXTURE_COORD_ARRAY); 2086 #endif 2087 } 2617 } 2618 2619 #endif // !QT_OPENGL_ES_2 2088 2620 2089 2621 /*! … … 2094 2626 texture target. 2095 2627 2096 Equivalent to the corresponding QGLContext::drawTexture().2628 . 2097 2629 */ 2098 2630 void QGLContext::drawTexture(const QRectF &target, GLuint textureId, GLenum textureTarget) 2099 2631 { 2632 2100 2633 #ifdef QT_OPENGL_ES 2101 2634 if (textureTarget != GL_TEXTURE_2D) { … … 2121 2654 glBindTexture(textureTarget, oldTexture); 2122 2655 #endif 2656 2657 2658 2659 2660 2661 2123 2662 } 2124 2663 … … 2137 2676 space. The \a textureTarget should be a 2D texture target. 2138 2677 2139 Equivalent to the corresponding QGLContext::drawTexture().2678 . 2140 2679 */ 2141 2680 void QGLContext::drawTexture(const QPointF &point, GLuint textureId, GLenum textureTarget) … … 2188 2727 void QGLContext::setTextureCacheLimit(int size) 2189 2728 { 2190 qt_tex_cache_limit = size; 2191 if (qt_tex_cache) 2192 qt_tex_cache->setMaxCost(qt_tex_cache_limit); 2729 QGLTextureCache::instance()->setMaxCost(size); 2193 2730 } 2194 2731 … … 2200 2737 int QGLContext::textureCacheLimit() 2201 2738 { 2202 return qt_tex_cache_limit;2739 return ; 2203 2740 } 2204 2741 … … 2279 2816 formats. 2280 2817 */ 2818 2819 2820 2821 2822 2823 2824 2825 2826 2827 2828 2829 2830 2831 2281 2832 2282 2833 /*! … … 2399 2950 reset(); 2400 2951 d->valid = chooseContext(shareContext); 2952 2953 2954 2955 2401 2956 if (d->sharing) // ok, we managed to share 2402 2957 qgl_share_reg()->addShare(this, shareContext); … … 2419 2974 { 2420 2975 Q_D(const QGLContext); 2421 return d-> sharing;2976 return d->; 2422 2977 } 2423 2978 … … 2474 3029 const QGLContext* QGLContext::currentContext() 2475 3030 { 2476 if (qgl_context_storage.hasLocalData()) 2477 return qgl_context_storage.localData()->context; 3031 QGLThreadContext *threadContext = qgl_context_storage.localData(); 3032 if (threadContext) 3033 return threadContext->context; 2478 3034 return 0; 3035 3036 3037 3038 3039 3040 3041 3042 3043 3044 3045 3046 3047 3048 3049 3050 2479 3051 } 2480 3052 … … 2493 3065 */ 2494 3066 3067 3068 3069 3070 3071 3072 3073 3074 3075 3076 3077 3078 3079 3080 3081 3082 3083 3084 3085 3086 3087 3088 3089 3090 3091 3092 3093 3094 3095 3096 3097 3098 3099 3100 3101 3102 2495 3103 2496 3104 /*! … … 2561 3169 \brief The QGLWidget class is a widget for rendering OpenGL graphics. 2562 3170 2563 \ingroup multimedia2564 \mainclass 3171 \ingroup 3172 2565 3173 2566 3174 QGLWidget provides functionality for displaying OpenGL graphics … … 2577 3185 needs to be updated. 2578 3186 \i resizeGL() - Sets up the OpenGL viewport, projection, etc. Gets 2579 called whenever the thewidget has been resized (and also when it3187 called whenever the widget has been resized (and also when it 2580 3188 is shown for the first time because all newly created widgets get a 2581 3189 resize event automatically). … … 2603 3211 customized rendering \link QGLContext contexts\endlink. 2604 3212 2605 You can also share OpenGL display lists between QGLWidget s (see3213 You can also share OpenGL display lists between QGLWidgets (see 2606 3214 the documentation of the QGLWidget constructors for details). 2607 3215 … … 2885 3493 Returns true if this widget's GL context is shared with another GL 2886 3494 context, otherwise false is returned. Context sharing might not be 2887 possible if the QGLWidgets use different formats.3495 possible if the idgets use different formats. 2888 3496 2889 3497 \sa format() … … 2983 3591 2984 3592 This method will try to keep display list and texture object sharing 2985 in effect with other QGLWidget s, but changing the format might make3593 in effect with other QGLWidgets, but changing the format might make 2986 3594 sharing impossible. Use isSharing() to see if sharing is still in 2987 3595 effect. … … 3009 3617 3010 3618 /* 3619 3620 3621 3011 3622 \obsolete 3012 3013 \fn void QGLWidget::setContext(QGLContext *context,3014 const QGLContext* shareContext,3015 bool deleteOldContext)3016 3623 3017 3624 Sets a new context for this widget. The QGLContext \a context must … … 3163 3770 } 3164 3771 3165 3772 /*! \fn bool QGLWidget::event(QEvent *e) 3773 \reimp 3774 */ 3166 3775 #if !defined(Q_OS_WINCE) && !defined(Q_WS_QWS) 3167 /*! \reimp */3168 3776 bool QGLWidget::event(QEvent *e) 3169 3777 { … … 3191 3799 doneCurrent(); 3192 3800 } else if (e->type() == QEvent::ParentChange) { 3193 if (d->glcx->d_func()->screen != d->xinfo.screen()) { 3801 // if we've reparented a window that has the current context 3802 // bound, we need to rebind that context to the new window id 3803 if (d->glcx == QGLContext::currentContext()) 3804 makeCurrent(); 3805 3806 if (d->glcx->d_func()->screen != d->xinfo.screen() || testAttribute(Qt::WA_TranslucentBackground)) { 3194 3807 setContext(new QGLContext(d->glcx->requestedFormat(), this)); 3195 3808 // ### recreating the overlay isn't supported atm 3196 3809 } 3810 3811 3197 3812 #if defined(QT_OPENGL_ES) 3198 // The window may have been re-created during re-parent - if so, the EGL 3813 // A re-parent is likely to destroy the X11 window and re-create it. It is important 3814 // that we free the EGL surface _before_ the winID changes - otherwise we can leak. 3815 if (e->type() == QEvent::ParentAboutToChange) 3816 d->glcx->d_func()->destroyEglSurfaceForDevice(); 3817 3818 if ((e->type() == QEvent::ParentChange) || (e->type() == QEvent::WindowStateChange)) { 3819 // The window may have been re-created during re-parent or state change - if so, the EGL 3199 3820 // surface will need to be re-created. 3200 3821 d->recreateEglSurface(false); 3201 #endif 3202 } 3822 } 3823 #endif 3203 3824 #elif defined(Q_WS_WIN) 3204 3825 if (e->type() == QEvent::ParentChange) { 3205 3826 QGLContext *newContext = new QGLContext(d->glcx->requestedFormat(), this); 3206 qgl_share_reg()->replaceShare(d->glcx, newContext);3207 setContext(newContext); 3827 ); 3828 3208 3829 // the overlay needs to be recreated as well 3209 3830 delete d->olcx; … … 3284 3905 Renders the current scene on a pixmap and returns the pixmap. 3285 3906 3286 You can use this method on both visible and invisible QGLWidget s.3907 You can use this method on both visible and invisible QGLWidgets. 3287 3908 3288 3909 This method will create a pixmap and a temporary QGLContext to … … 3406 4027 const QVector<QColor> pal = QColormap::instance().colormap(); 3407 4028 if (pal.size()) { 3408 res.set NumColors(pal.size());4029 res.set(pal.size()); 3409 4030 for (int i = 0; i < pal.size(); i++) 3410 4031 res.setColor(i, pal.at(i).rgb()); … … 3470 4091 with the color \a c. Applies to this widgets GL context. 3471 4092 4093 4094 3472 4095 \sa qglClearColor(), QGLContext::currentContext(), QColor 3473 4096 */ … … 3477 4100 #if !defined(QT_OPENGL_ES_2) 3478 4101 #ifdef QT_OPENGL_ES 3479 glColor4f(c.red ()/255.0, c.green()/255.0, c.blue()/255.0, c.alpha()/255.0);4102 glColor4f(c.red); 3480 4103 #else 3481 4104 Q_D(const QGLWidget); … … 3483 4106 if (ctx) { 3484 4107 if (ctx->format().rgba()) 3485 glColor4 ub(c.red(), c.green(), c.blue(), c.alpha());4108 glColor4()); 3486 4109 else if (!d->cmap.isEmpty()) { // QGLColormap in use? 3487 4110 int i = d->cmap.find(c.rgb()); … … 3493 4116 } 3494 4117 #endif //QT_OPENGL_ES 4118 4119 3495 4120 #endif //QT_OPENGL_ES_2 3496 4121 } … … 3507 4132 { 3508 4133 #ifdef QT_OPENGL_ES 3509 glClearColor((GLfloat)c.red() / 255.0, (GLfloat)c.green() / 255.0, 3510 (GLfloat)c.blue() / 255.0, (GLfloat) c.alpha() / 255.0); 4134 glClearColor(c.redF(), c.greenF(), c.blueF(), c.alphaF()); 3511 4135 #else 3512 4136 Q_D(const QGLWidget); … … 3514 4138 if (ctx) { 3515 4139 if (ctx->format().rgba()) 3516 glClearColor((GLfloat)c.red() / 255.0, (GLfloat)c.green() / 255.0, 3517 (GLfloat)c.blue() / 255.0, (GLfloat) c.alpha() / 255.0); 4140 glClearColor(c.redF(), c.greenF(), c.blueF(), c.alphaF()); 3518 4141 else if (!d->cmap.isEmpty()) { // QGLColormap in use? 3519 4142 int i = d->cmap.find(c.rgb()); … … 3586 4209 will return the colormap for the child's top-level widget. 3587 4210 3588 If no colormap has been set for this widget, the Q Colormap4211 If no colormap has been set for this widget, the QColormap 3589 4212 returned will be empty. 3590 4213 3591 \sa setColormap() 4214 \sa setColormap() 3592 4215 */ 3593 4216 … … 3609 4232 value used when generating the display lists for the font. The 3610 4233 default value is 2000. 4234 4235 3611 4236 */ 3612 4237 int QGLWidget::fontDisplayListBase(const QFont & font, int listBase) 3613 4238 { 4239 3614 4240 Q_D(QGLWidget); 3615 4241 int base; … … 3629 4255 if (font.styleStrategy() != QFont::NoAntialias) { 3630 4256 GLfloat color[4]; 3631 #ifndef QT_OPENGL_ES3632 4257 glGetFloatv(GL_CURRENT_COLOR, color); 3633 #endif3634 4258 color_key.sprintf("%f_%f_%f",color[0], color[1], color[2]); 3635 4259 } … … 3654 4278 } 3655 4279 return base; 3656 } 4280 #else // QT_OPENGL_ES 4281 Q_UNUSED(font); 4282 Q_UNUSED(listBase); 4283 return 0; 4284 #endif 4285 } 4286 4287 #ifndef QT_OPENGL_ES 3657 4288 3658 4289 static void qt_save_gl_state() 3659 4290 { 3660 #ifndef QT_OPENGL_ES3661 4291 glPushClientAttrib(GL_CLIENT_ALL_ATTRIB_BITS); 3662 4292 glPushAttrib(GL_ALL_ATTRIB_BITS); 3663 #endif3664 #if !defined(QT_OPENGL_ES_2)3665 4293 glMatrixMode(GL_TEXTURE); 3666 4294 glPushMatrix(); … … 3675 4303 glDisable(GL_LIGHTING); 3676 4304 glDisable(GL_STENCIL_TEST); 4305 3677 4306 glEnable(GL_BLEND); 3678 4307 glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA); 3679 #endif // !defined(QT_OPENGL_ES_2)3680 4308 } 3681 4309 3682 4310 static void qt_restore_gl_state() 3683 4311 { 3684 #if !defined(QT_OPENGL_ES_2)3685 4312 glMatrixMode(GL_TEXTURE); 3686 4313 glPopMatrix(); … … 3689 4316 glMatrixMode(GL_MODELVIEW); 3690 4317 glPopMatrix(); 3691 #endif // !defined(QT_OPENGL_ES_2)3692 #ifndef QT_OPENGL_ES3693 4318 glPopAttrib(); 3694 4319 glPopClientAttrib(); 3695 #endif3696 4320 } 3697 4321 … … 3700 4324 { 3701 4325 GLfloat color[4]; 3702 #ifndef QT_OPENGL_ES3703 4326 glGetFloatv(GL_CURRENT_COLOR, &color[0]); 3704 #endif3705 4327 3706 4328 QColor col; … … 3716 4338 p->setFont(old_font); 3717 4339 } 4340 4341 3718 4342 3719 4343 /*! … … 3731 4355 3732 4356 \note This function clears the stencil buffer. 4357 4358 4359 4360 4361 4362 4363 3733 4364 */ 3734 4365 3735 4366 void QGLWidget::renderText(int x, int y, const QString &str, const QFont &font, int) 3736 4367 { 4368 3737 4369 Q_D(QGLWidget); 3738 4370 if (str.isEmpty() || !isValid()) … … 3740 4372 3741 4373 GLint view[4]; 3742 #ifndef QT_OPENGL_ES3743 4374 bool use_scissor_testing = glIsEnabled(GL_SCISSOR_TEST); 3744 4375 if (!use_scissor_testing) 3745 4376 glGetIntegerv(GL_VIEWPORT, &view[0]); 3746 #else3747 bool use_scissor_testing = false;3748 #endif3749 4377 int width = d->glcx->device()->width(); 3750 4378 int height = d->glcx->device()->height(); 3751 4379 bool auto_swap = autoBufferSwap(); 3752 4380 4381 4382 3753 4383 QPaintEngine *engine = paintEngine(); 3754 4384 QPainter *p; … … 3759 4389 qt_save_gl_state(); 3760 4390 3761 #if !defined(QT_OPENGL_ES_2)3762 4391 glDisable(GL_DEPTH_TEST); 3763 4392 glViewport(0, 0, width, height); 3764 4393 glMatrixMode(GL_PROJECTION); 3765 4394 glLoadIdentity(); 3766 #ifndef QT_OPENGL_ES3767 4395 glOrtho(0, width, height, 0, 0, 1); 3768 #else3769 glOrthof(0, width, height, 0, 0, 1);3770 #endif3771 4396 glMatrixMode(GL_MODELVIEW); 3772 4397 3773 4398 glLoadIdentity(); 3774 #endif // !defined(QT_OPENGL_ES_2)3775 4399 } else { 3776 4400 setAutoBufferSwap(false); 3777 4401 // disable glClear() as a result of QPainter::begin() 3778 d-> glcx->d_func()->clear_on_painter_begin = false;4402 d->e; 3779 4403 p = new QPainter(this); 3780 4404 } … … 3799 4423 delete p; 3800 4424 setAutoBufferSwap(auto_swap); 3801 d->glcx->d_func()->clear_on_painter_begin = true; 3802 } 4425 d->disable_clear_on_painter_begin = false; 4426 } 4427 qgl_engine_selector()->setPreferredPaintEngine(oldEngineType); 4428 #else // QT_OPENGL_ES 4429 Q_UNUSED(x); 4430 Q_UNUSED(y); 4431 Q_UNUSED(str); 4432 Q_UNUSED(font); 4433 qWarning("QGLWidget::renderText is not supported under OpenGL/ES"); 4434 #endif 3803 4435 } 3804 4436 … … 3809 4441 can be useful if you want to annotate models with text labels and 3810 4442 have the labels move with the model as it is rotated etc. 4443 4444 4445 4446 4447 4448 4449 4450 4451 4452 3811 4453 */ 3812 4454 void QGLWidget::renderText(double x, double y, double z, const QString &str, const QFont &font, int) 3813 4455 { 4456 3814 4457 Q_D(QGLWidget); 3815 4458 if (str.isEmpty() || !isValid()) … … 3822 4465 GLdouble model[4][4], proj[4][4]; 3823 4466 GLint view[4]; 3824 #ifndef QT_OPENGL_ES3825 4467 glGetDoublev(GL_MODELVIEW_MATRIX, &model[0][0]); 3826 4468 glGetDoublev(GL_PROJECTION_MATRIX, &proj[0][0]); 3827 4469 glGetIntegerv(GL_VIEWPORT, &view[0]); 3828 #endif3829 4470 GLdouble win_x = 0, win_y = 0, win_z = 0; 3830 4471 qgluProject(x, y, z, &model[0][0], &proj[0][0], &view[0], … … 3832 4473 win_y = height - win_y; // y is inverted 3833 4474 4475 4476 3834 4477 QPaintEngine *engine = paintEngine(); 3835 4478 QPainter *p; 3836 4479 bool reuse_painter = false; 3837 #ifndef QT_OPENGL_ES3838 4480 bool use_depth_testing = glIsEnabled(GL_DEPTH_TEST); 3839 4481 bool use_scissor_testing = glIsEnabled(GL_SCISSOR_TEST); 3840 #else3841 bool use_depth_testing = false;3842 bool use_scissor_testing = false;3843 #endif3844 4482 3845 4483 if (engine->isActive()) { … … 3850 4488 setAutoBufferSwap(false); 3851 4489 // disable glClear() as a result of QPainter::begin() 3852 d-> glcx->d_func()->clear_on_painter_begin = false;4490 d->e; 3853 4491 p = new QPainter(this); 3854 4492 } … … 3861 4499 glEnable(GL_SCISSOR_TEST); 3862 4500 } 3863 #if !defined(QT_OPENGL_ES_2)3864 4501 glMatrixMode(GL_PROJECTION); 3865 4502 glLoadIdentity(); 3866 4503 glViewport(0, 0, width, height); 3867 #ifndef QT_OPENGL_ES3868 4504 glOrtho(0, width, height, 0, 0, 1); 3869 #else3870 glOrthof(0, width, height, 0, 0, 1);3871 #endif3872 4505 glMatrixMode(GL_MODELVIEW); 3873 4506 glLoadIdentity(); … … 3876 4509 if (use_depth_testing) 3877 4510 glEnable(GL_DEPTH_TEST); 3878 #ifndef QT_OPENGL_ES3879 4511 glTranslated(0, 0, -win_z); 3880 #else3881 glTranslatef(0, 0, -win_z);3882 #endif3883 #endif // !defined(QT_OPENGL_ES_2)3884 4512 qt_gl_draw_text(p, qRound(win_x), qRound(win_y), str, font); 3885 4513 … … 3890 4518 delete p; 3891 4519 setAutoBufferSwap(auto_swap); 3892 d->glcx->d_func()->clear_on_painter_begin = true; 3893 } 4520 d->disable_clear_on_painter_begin = false; 4521 } 4522 qgl_engine_selector()->setPreferredPaintEngine(oldEngineType); 4523 #else // QT_OPENGL_ES 4524 Q_UNUSED(x); 4525 Q_UNUSED(y); 4526 Q_UNUSED(z); 4527 Q_UNUSED(str); 4528 Q_UNUSED(font); 4529 qWarning("QGLWidget::renderText is not supported under OpenGL/ES"); 4530 #endif 3894 4531 } 3895 4532 … … 3932 4569 GLuint QGLWidget::bindTexture(const QImage &image, GLenum target, GLint format) 3933 4570 { 4571 4572 4573 3934 4574 Q_D(QGLWidget); 3935 return d->glcx->bindTexture(image, target, format); 3936 } 4575 return d->glcx->bindTexture(image, target, format, QGLContext::DefaultBindOption); 4576 } 4577 4578 /*! 4579 \overload 4580 \since 4.6 4581 4582 The binding \a options are a set of options used to decide how to 4583 bind the texture to the context. 4584 */ 4585 GLuint QGLWidget::bindTexture(const QImage &image, GLenum target, GLint format, QGLContext::BindOptions options) 4586 { 4587 if (image.isNull()) 4588 return 0; 4589 4590 Q_D(QGLWidget); 4591 return d->glcx->bindTexture(image, target, format, options); 4592 } 4593 3937 4594 3938 4595 #ifdef Q_MAC_COMPAT_GL_FUNCTIONS … … 3940 4597 GLuint QGLWidget::bindTexture(const QImage &image, QMacCompatGLenum target, QMacCompatGLint format) 3941 4598 { 4599 4600 4601 3942 4602 Q_D(QGLWidget); 3943 return d->glcx->bindTexture(image, GLenum(target), GLint(format)); 4603 return d->glcx->bindTexture(image, GLenum(target), GLint(format), QGLContext::DefaultBindOption); 4604 } 4605 4606 GLuint QGLWidget::bindTexture(const QImage &image, QMacCompatGLenum target, QMacCompatGLint format, 4607 QGLContext::BindOptions options) 4608 { 4609 if (image.isNull()) 4610 return 0; 4611 4612 Q_D(QGLWidget); 4613 return d->glcx->bindTexture(image, GLenum(target), GLint(format), options); 3944 4614 } 3945 4615 #endif … … 3953 4623 GLuint QGLWidget::bindTexture(const QPixmap &pixmap, GLenum target, GLint format) 3954 4624 { 4625 4626 4627 3955 4628 Q_D(QGLWidget); 3956 return d->glcx->bindTexture(pixmap, target, format); 4629 return d->glcx->bindTexture(pixmap, target, format, QGLContext::DefaultBindOption); 4630 } 4631 4632 /*! 4633 \overload 4634 \since 4.6 4635 4636 Generates and binds a 2D GL texture to the current context, based 4637 on \a pixmap. The generated texture id is returned and can be used in 4638 4639 The binding \a options are a set of options used to decide how to 4640 bind the texture to the context. 4641 */ 4642 GLuint QGLWidget::bindTexture(const QPixmap &pixmap, GLenum target, GLint format, 4643 QGLContext::BindOptions options) 4644 { 4645 Q_D(QGLWidget); 4646 return d->glcx->bindTexture(pixmap, target, format, options); 3957 4647 } 3958 4648 … … 3962 4652 { 3963 4653 Q_D(QGLWidget); 3964 return d->glcx->bindTexture(pixmap, target, format); 4654 return d->glcx->bindTexture(pixmap, target, format, QGLContext::DefaultBindOption); 4655 } 4656 4657 GLuint QGLWidget::bindTexture(const QPixmap &pixmap, QMacCompatGLenum target, QMacCompatGLint format, 4658 QGLContext::BindOptions options) 4659 { 4660 Q_D(QGLWidget); 4661 return d->glcx->bindTexture(pixmap, target, format, options); 3965 4662 } 3966 4663 #endif … … 4047 4744 #endif 4048 4745 4049 #if defined(QT_OPENGL_ES_2) 4050 Q_GLOBAL_STATIC(QGL2PaintEngineEx, qt_gl_engine) 4746 #if !defined(QT_OPENGL_ES_1) && !defined(QT_OPENGL_ES_1_CL) 4747 Q_GLOBAL_STATIC(QGL2PaintEngineEx, qt_gl_2_engine) 4748 #endif 4749 4750 #ifndef QT_OPENGL_ES_2 4751 Q_GLOBAL_STATIC(QOpenGLPaintEngine, qt_gl_engine) 4752 #endif 4753 4754 Q_OPENGL_EXPORT QPaintEngine* qt_qgl_paint_engine() 4755 { 4756 #if defined(QT_OPENGL_ES_1) || defined(QT_OPENGL_ES_1_CL) 4757 return qt_gl_engine(); 4758 #elif defined(QT_OPENGL_ES_2) 4759 return qt_gl_2_engine(); 4051 4760 #else 4052 Q_GLOBAL_STATIC(QOpenGLPaintEngine, qt_gl_engine) 4053 #endif 4054 4055 #ifdef Q_WS_QWS 4056 Q_OPENGL_EXPORT QOpenGLPaintEngine* qt_qgl_paint_engine() 4057 { 4058 #if !defined(QT_OPENGL_ES_2) 4059 return qt_gl_engine(); 4060 #else 4061 return 0; // XXX 4062 #endif 4063 } 4064 #endif 4761 if (qt_gl_preferGL2Engine()) 4762 return qt_gl_2_engine(); 4763 else 4764 return qt_gl_engine(); 4765 #endif 4766 } 4065 4767 4066 4768 /*! … … 4072 4774 QPaintEngine *QGLWidget::paintEngine() const 4073 4775 { 4074 return qt_ gl_engine();4776 return qt__engine(); 4075 4777 } 4076 4778 … … 4132 4834 void QGLExtensions::init_extensions() 4133 4835 { 4134 QString extensions = QLatin1String(reinterpret_cast<const char *>(glGetString(GL_EXTENSIONS))); 4135 if (extensions.contains(QLatin1String("texture_rectangle"))) 4836 QGLExtensionMatcher extensions(reinterpret_cast<const char *>(glGetString(GL_EXTENSIONS))); 4837 4838 if (extensions.match("GL_ARB_texture_rectangle")) 4136 4839 glExtensions |= TextureRectangle; 4137 if (extensions. contains(QLatin1String("multisample")))4840 if (extensions.)) 4138 4841 glExtensions |= SampleBuffers; 4139 if (extensions. contains(QLatin1String("generate_mipmap")))4842 if (extensions.)) 4140 4843 glExtensions |= GenerateMipmap; 4141 if (extensions. contains(QLatin1String("texture_compression_s3tc")))4844 if (extensions.)) 4142 4845 glExtensions |= TextureCompression; 4143 if (extensions.contains(QLatin1String("ARB_fragment_program"))) 4846 if (extensions.match("GL_EXT_texture_compression_s3tc")) 4847 glExtensions |= DDSTextureCompression; 4848 if (extensions.match("GL_OES_compressed_ETC1_RGB8_texture")) 4849 glExtensions |= ETC1TextureCompression; 4850 if (extensions.match("GL_IMG_texture_compression_pvrtc")) 4851 glExtensions |= PVRTCTextureCompression; 4852 if (extensions.match("GL_ARB_fragment_program")) 4144 4853 glExtensions |= FragmentProgram; 4145 if (extensions.contains(QLatin1String("mirrored_repeat"))) 4854 if (extensions.match("GL_ARB_fragment_shader")) 4855 glExtensions |= FragmentShader; 4856 if (extensions.match("GL_ARB_texture_mirrored_repeat")) 4146 4857 glExtensions |= MirroredRepeat; 4147 if (extensions. contains(QLatin1String("EXT_framebuffer_object")))4858 if (extensions.)) 4148 4859 glExtensions |= FramebufferObject; 4149 if (extensions. contains(QLatin1String("EXT_stencil_two_side")))4860 if (extensions.)) 4150 4861 glExtensions |= StencilTwoSide; 4151 if (extensions. contains(QLatin1String("EXT_stencil_wrap")))4862 if (extensions.)) 4152 4863 glExtensions |= StencilWrap; 4153 if (extensions. contains(QLatin1String("EXT_packed_depth_stencil")))4864 if (extensions.)) 4154 4865 glExtensions |= PackedDepthStencil; 4155 if (extensions. contains(QLatin1String("GL_NV_float_buffer")))4866 if (extensions.)) 4156 4867 glExtensions |= NVFloatBuffer; 4157 if (extensions. contains(QLatin1String("ARB_pixel_buffer_object")))4868 if (extensions.)) 4158 4869 glExtensions |= PixelBufferObject; 4159 4870 #if defined(QT_OPENGL_ES_2) 4160 4871 glExtensions |= FramebufferObject; 4161 4872 glExtensions |= GenerateMipmap; 4162 #endif 4163 4164 QGLContext cx(QGLFormat::defaultFormat()); 4165 if (glExtensions & TextureCompression) { 4166 qt_glCompressedTexImage2DARB = (pfn_glCompressedTexImage2DARB) cx.getProcAddress(QLatin1String("glCompressedTexImage2DARB")); 4167 } 4873 glExtensions |= FragmentShader; 4874 #endif 4875 #if defined(QT_OPENGL_ES_1) || defined(QT_OPENGL_ES_1_CL) 4876 if (extensions.match("GL_OES_framebuffer_object")) 4877 glExtensions |= FramebufferObject; 4878 #endif 4879 #if defined(QT_OPENGL_ES) 4880 if (extensions.match("GL_OES_packed_depth_stencil")) 4881 glExtensions |= PackedDepthStencil; 4882 #endif 4883 if (extensions.match("GL_ARB_framebuffer_object")) { 4884 // ARB_framebuffer_object also includes EXT_framebuffer_blit. 4885 glExtensions |= FramebufferObject; 4886 glExtensions |= FramebufferBlit; 4887 } 4888 4889 if (extensions.match("GL_EXT_framebuffer_blit")) 4890 glExtensions |= FramebufferBlit; 4891 4892 if (extensions.match("GL_ARB_texture_non_power_of_two")) 4893 glExtensions |= NPOTTextures; 4894 4895 if (extensions.match("GL_EXT_bgra")) 4896 glExtensions |= BGRATextureFormat; 4168 4897 } 4169 4898 … … 4174 4903 { 4175 4904 Q_Q(QGLWidget); 4905 4906 4176 4907 4177 4908 QGLExtensions::init(); … … 4190 4921 4191 4922 #if defined(Q_WS_X11) || defined(Q_WS_MAC) || defined(Q_WS_QWS) 4192 Q_GLOBAL_STATIC(QString, qt_gl_lib_name) ;4923 Q_GLOBAL_STATIC(QString, qt_gl_lib_name) 4193 4924 4194 4925 Q_OPENGL_EXPORT void qt_set_gl_library_name(const QString& name) … … 4201 4932 if (qt_gl_lib_name()->isNull()) { 4202 4933 #if defined(Q_WS_X11) || defined(Q_WS_QWS) 4203 return Q String(QLatin1String("GL"));4934 return Q); 4204 4935 #else // Q_WS_MAC 4205 4936 return QLatin1String("/System/Library/Frameworks/OpenGL.framework/Versions/A/Libraries/libGL.dylib"); … … 4210 4941 #endif 4211 4942 4943 4944 4945 4946 4947 4948 4949 4950 4951 4952 4953 4954 4955 4956 4957 4958 4959 4960 4961 4962 4963 4964 4965 4966 4967 4968 4969 4970 4971 4972 4973 4974 4975 4976 4977 4978 4979 4980 4981 4982 4983 4984 4985 4986 4987 4988 4989 4990 4991 4992 4993 4994 4995 4996 4997 4998 4999 5000 5001 5002 5003 5004 5005 5006 5007 5008 5009 5010 5011 5012 5013 5014 5015 5016 5017 5018 5019 5020 5021 5022 5023 5024 5025 5026 5027 5028 5029 5030 5031 5032 5033 5034 5035 5036 5037 5038 5039 5040 5041 5042 5043 5044 5045 5046 5047 5048 5049 5050 5051 5052 5053 5054 5055 5056 5057 5058 5059 5060 5061 5062 5063 5064 5065 5066 5067 5068 5069 5070 5071 5072 5073 5074 5075 5076 5077 5078 5079 5080 5081 5082 5083 5084 5085 5086 5087 5088 5089 5090 5091 5092 5093 5094 5095 5096 5097 5098 5099 5100 5101 5102 5103 5104 5105 5106 5107 5108 5109 5110 5111 5112 5113 5114 5115 5116 5117 5118 5119 5120 5121 5122 5123 5124 5125 5126 5127 5128 5129 5130 5131 5132 5133 5134 5135 5136 5137 5138 5139 5140 5141 5142 5143 5144 5145 5146 5147 5148 5149 5150 5151 5152 5153 5154 5155 5156 5157 5158 5159 5160 5161 5162 5163 5164 5165 5166 5167 5168 5169 5170 5171 5172 5173 5174 5175 5176 5177 5178 5179 5180 5181 5182 5183 5184 5185 5186 5187 5188 5189 5190 5191 5192 5193 5194 5195 5196 5197 5198 5199 5200 5201 5202 5203 5204 5205 5206 5207 5208 5209 5210 5211 5212 5213 5214 5215 5216 5217 5218 5219 5220 5221 5222 5223 5224 5225 5226 5227 5228 5229 5230 5231 5232 5233 5234 5235 5236 5237 5238 5239 5240 5241 5242 5243 5244 5245 5246 5247 5248 5249 5250 5251 5252 5253 5254 5255 5256 5257 5258 5259 5260 5261 5262 5263 5264 5265 5266 5267 5268 5269 5270 5271 5272 5273 5274 5275 5276 5277 5278 5279 5280 5281 5282 5283 5284 5285 5286 5287 5288 5289 5290 5291 5292 5293 5294 5295 5296 5297 5298 5299 5300 5301 5302 5303 5304 5305 5306 5307 5308 5309 5310 5311 5312 5313 5314 5315 5316 5317 5318 5319 5320 5321 5322 5323 5324 5325 5326 5327 5328 5329 5330 5331 5332 5333 5334 5335 5336 5337 5338 5339 5340 5341 5342 5343 5344 5345 5346 5347 5348 5349 5350 5351 5352 5353 5354 5355 5356 5357 5358 5359 5360 5361 5362 5363 5364 5365 5366 5367 5368 5369 5370 5371 5372 5373 5374 5375 5376 5377 5378 5379 5380 5381 5382 5383 5384 5385 5386 5387 5388 4212 5389 QT_END_NAMESPACE
Note:
See TracChangeset
for help on using the changeset viewer.