1 /**************************************************************************** |
1 /**************************************************************************** |
2 ** |
2 ** |
3 ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). |
3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). |
4 ** All rights reserved. |
4 ** All rights reserved. |
5 ** Contact: Nokia Corporation (qt-info@nokia.com) |
5 ** Contact: Nokia Corporation (qt-info@nokia.com) |
6 ** |
6 ** |
7 ** This file is part of the QtOpenGL module of the Qt Toolkit. |
7 ** This file is part of the QtOpenGL module of the Qt Toolkit. |
8 ** |
8 ** |
102 |
102 |
103 #if defined(Q_WS_X11) || defined(Q_WS_MAC) || defined(Q_WS_QWS) |
103 #if defined(Q_WS_X11) || defined(Q_WS_MAC) || defined(Q_WS_QWS) |
104 QGLExtensionFuncs QGLContextPrivate::qt_extensionFuncs; |
104 QGLExtensionFuncs QGLContextPrivate::qt_extensionFuncs; |
105 #endif |
105 #endif |
106 |
106 |
|
107 #ifdef Q_WS_X11 |
|
108 extern const QX11Info *qt_x11Info(const QPaintDevice *pd); |
|
109 #endif |
|
110 |
107 struct QGLThreadContext { |
111 struct QGLThreadContext { |
108 QGLContext *context; |
112 QGLContext *context; |
109 }; |
113 }; |
110 |
114 |
111 static QThreadStorage<QGLThreadContext *> qgl_context_storage; |
115 static QThreadStorage<QGLThreadContext *> qgl_context_storage; |
121 setOption(QGL::DirectRendering); |
125 setOption(QGL::DirectRendering); |
122 setPlane(1); |
126 setPlane(1); |
123 } |
127 } |
124 }; |
128 }; |
125 Q_GLOBAL_STATIC(QGLDefaultOverlayFormat, defaultOverlayFormatInstance) |
129 Q_GLOBAL_STATIC(QGLDefaultOverlayFormat, defaultOverlayFormatInstance) |
126 |
|
127 QGLExtensions::Extensions QGLExtensions::glExtensions = 0; |
|
128 bool QGLExtensions::nvidiaFboNeedsFinish = false; |
|
129 |
130 |
130 Q_GLOBAL_STATIC(QGLSignalProxy, theSignalProxy) |
131 Q_GLOBAL_STATIC(QGLSignalProxy, theSignalProxy) |
131 QGLSignalProxy *QGLSignalProxy::instance() |
132 QGLSignalProxy *QGLSignalProxy::instance() |
132 { |
133 { |
133 return theSignalProxy(); |
134 return theSignalProxy(); |
152 // values from functions in GLSL. Since working around this in |
153 // values from functions in GLSL. Since working around this in |
153 // the GL2 engine would require a big, ugly rewrite, we're |
154 // the GL2 engine would require a big, ugly rewrite, we're |
154 // falling back to the GL 1 engine.. |
155 // falling back to the GL 1 engine.. |
155 static bool mac_x1600_check_done = false; |
156 static bool mac_x1600_check_done = false; |
156 if (!mac_x1600_check_done) { |
157 if (!mac_x1600_check_done) { |
157 QGLWidget *tmp = 0; |
158 QGLTemporaryContext *tmp = 0; |
158 if (!QGLContext::currentContext()) { |
159 if (!QGLContext::currentContext()) |
159 tmp = new QGLWidget(); |
160 tmp = new QGLTemporaryContext(); |
160 tmp->makeCurrent(); |
|
161 } |
|
162 if (strstr((char *) glGetString(GL_RENDERER), "X1600")) |
161 if (strstr((char *) glGetString(GL_RENDERER), "X1600")) |
163 engineType = QPaintEngine::OpenGL; |
162 engineType = QPaintEngine::OpenGL; |
164 if (tmp) |
163 if (tmp) |
165 delete tmp; |
164 delete tmp; |
166 mac_x1600_check_done = true; |
165 mac_x1600_check_done = true; |
176 // Also check for the FragmentShader extension in conjunction with |
175 // Also check for the FragmentShader extension in conjunction with |
177 // the 2.0 version flag, to cover the case where we export the display |
176 // the 2.0 version flag, to cover the case where we export the display |
178 // from an old GL 1.1 server to a GL 2.x client. In that case we can't |
177 // from an old GL 1.1 server to a GL 2.x client. In that case we can't |
179 // use GL 2.0. |
178 // use GL 2.0. |
180 if ((QGLFormat::openGLVersionFlags() & QGLFormat::OpenGL_Version_2_0) |
179 if ((QGLFormat::openGLVersionFlags() & QGLFormat::OpenGL_Version_2_0) |
181 && (QGLExtensions::glExtensions & QGLExtensions::FragmentShader) |
180 && (QGLExtensions::glExtensions() & QGLExtensions::FragmentShader) |
182 && qgetenv("QT_GL_USE_OPENGL1ENGINE").isEmpty()) |
181 && qgetenv("QT_GL_USE_OPENGL1ENGINE").isEmpty()) |
183 engineType = QPaintEngine::OpenGL2; |
182 engineType = QPaintEngine::OpenGL2; |
184 else |
183 else |
185 engineType = QPaintEngine::OpenGL; |
184 engineType = QPaintEngine::OpenGL; |
186 #endif |
185 #endif |
1248 QGLFormat::OpenGLVersionFlags QGLFormat::openGLVersionFlags() |
1247 QGLFormat::OpenGLVersionFlags QGLFormat::openGLVersionFlags() |
1249 { |
1248 { |
1250 static bool cachedDefault = false; |
1249 static bool cachedDefault = false; |
1251 static OpenGLVersionFlags defaultVersionFlags = OpenGL_Version_None; |
1250 static OpenGLVersionFlags defaultVersionFlags = OpenGL_Version_None; |
1252 QGLContext *currentCtx = const_cast<QGLContext *>(QGLContext::currentContext()); |
1251 QGLContext *currentCtx = const_cast<QGLContext *>(QGLContext::currentContext()); |
1253 QGLWidget *dummy = 0; |
1252 QGLTemporaryContext *tmpContext = 0; |
1254 |
1253 |
1255 if (currentCtx && currentCtx->d_func()->version_flags_cached) |
1254 if (currentCtx && currentCtx->d_func()->version_flags_cached) |
1256 return currentCtx->d_func()->version_flags; |
1255 return currentCtx->d_func()->version_flags; |
1257 |
1256 |
1258 if (!currentCtx) { |
1257 if (!currentCtx) { |
1259 if (cachedDefault) { |
1258 if (cachedDefault) { |
1260 return defaultVersionFlags; |
1259 return defaultVersionFlags; |
1261 } else { |
1260 } else { |
1262 if (!hasOpenGL()) |
1261 if (!hasOpenGL()) |
1263 return defaultVersionFlags; |
1262 return defaultVersionFlags; |
1264 dummy = new QGLWidget; |
1263 tmpContext = new QGLTemporaryContext; |
1265 dummy->makeCurrent(); // glGetString() needs a current context |
|
1266 cachedDefault = true; |
1264 cachedDefault = true; |
1267 } |
1265 } |
1268 } |
1266 } |
1269 |
1267 |
1270 QString versionString(QLatin1String(reinterpret_cast<const char*>(glGetString(GL_VERSION)))); |
1268 QString versionString(QLatin1String(reinterpret_cast<const char*>(glGetString(GL_VERSION)))); |
1271 OpenGLVersionFlags versionFlags = qOpenGLVersionFlagsFromString(versionString); |
1269 OpenGLVersionFlags versionFlags = qOpenGLVersionFlagsFromString(versionString); |
1272 if (currentCtx) { |
1270 if (currentCtx) { |
1273 currentCtx->d_func()->version_flags_cached = true; |
1271 currentCtx->d_func()->version_flags_cached = true; |
1274 currentCtx->d_func()->version_flags = versionFlags; |
1272 currentCtx->d_func()->version_flags = versionFlags; |
1275 } |
1273 } |
1276 if (dummy) { |
1274 if (tmpContext) { |
1277 defaultVersionFlags = versionFlags; |
1275 defaultVersionFlags = versionFlags; |
1278 delete dummy; |
1276 delete tmpContext; |
1279 } |
1277 } |
1280 |
1278 |
1281 return versionFlags; |
1279 return versionFlags; |
1282 } |
1280 } |
1283 |
1281 |
1434 guard->m_prev->m_next = guard->m_next; |
1432 guard->m_prev->m_next = guard->m_next; |
1435 else |
1433 else |
1436 m_guards = guard->m_next; |
1434 m_guards = guard->m_next; |
1437 } |
1435 } |
1438 |
1436 |
|
1437 const QGLContext *qt_gl_transfer_context(const QGLContext *ctx) |
|
1438 { |
|
1439 if (!ctx) |
|
1440 return 0; |
|
1441 QList<const QGLContext *> shares |
|
1442 (QGLContextPrivate::contextGroup(ctx)->shares()); |
|
1443 if (shares.size() >= 2) |
|
1444 return (ctx == shares.at(0)) ? shares.at(1) : shares.at(0); |
|
1445 else |
|
1446 return 0; |
|
1447 } |
|
1448 |
1439 QGLContextPrivate::~QGLContextPrivate() |
1449 QGLContextPrivate::~QGLContextPrivate() |
1440 { |
1450 { |
1441 if (!group->m_refs.deref()) { |
1451 if (!group->m_refs.deref()) { |
1442 Q_ASSERT(group->context() == q_ptr); |
1452 Q_ASSERT(group->context() == q_ptr); |
1443 delete group; |
1453 delete group; |
1479 initDone = false; |
1489 initDone = false; |
1480 sharing = false; |
1490 sharing = false; |
1481 max_texture_size = -1; |
1491 max_texture_size = -1; |
1482 version_flags_cached = false; |
1492 version_flags_cached = false; |
1483 version_flags = QGLFormat::OpenGL_Version_None; |
1493 version_flags = QGLFormat::OpenGL_Version_None; |
|
1494 extension_flags_cached = false; |
|
1495 extension_flags = 0; |
1484 current_fbo = 0; |
1496 current_fbo = 0; |
1485 default_fbo = 0; |
1497 default_fbo = 0; |
1486 active_engine = 0; |
1498 active_engine = 0; |
|
1499 for (int i = 0; i < QT_GL_VERTEX_ARRAY_TRACKED_COUNT; ++i) |
|
1500 vertexAttributeArraysEnabledState[i] = false; |
1487 } |
1501 } |
1488 |
1502 |
1489 QGLContext* QGLContext::currentCtx = 0; |
1503 QGLContext* QGLContext::currentCtx = 0; |
1490 |
1504 |
1491 /* |
1505 /* |
1539 return img; |
1553 return img; |
1540 } |
1554 } |
1541 |
1555 |
1542 QImage qt_gl_read_texture(const QSize &size, bool alpha_format, bool include_alpha) |
1556 QImage qt_gl_read_texture(const QSize &size, bool alpha_format, bool include_alpha) |
1543 { |
1557 { |
1544 QImage img(size, alpha_format ? QImage::Format_ARGB32 : QImage::Format_RGB32); |
1558 QImage img(size, alpha_format ? QImage::Format_ARGB32_Premultiplied : QImage::Format_RGB32); |
1545 int w = size.width(); |
1559 int w = size.width(); |
1546 int h = size.height(); |
1560 int h = size.height(); |
1547 #if !defined(QT_OPENGL_ES_2) && !defined(QT_OPENGL_ES_1) && !defined(QT_OPENGL_ES_1_CL) |
1561 #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! |
1562 //### 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()); |
1563 glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE, img.bits()); |
1578 : m_cache(64*1024) // cache ~64 MB worth of textures - this is not accurate though |
1592 : m_cache(64*1024) // cache ~64 MB worth of textures - this is not accurate though |
1579 { |
1593 { |
1580 Q_ASSERT(qt_gl_texture_cache == 0); |
1594 Q_ASSERT(qt_gl_texture_cache == 0); |
1581 qt_gl_texture_cache = this; |
1595 qt_gl_texture_cache = this; |
1582 |
1596 |
1583 QImagePixmapCleanupHooks::instance()->addPixmapModificationHook(cleanupTextures); |
1597 QImagePixmapCleanupHooks::instance()->addPixmapDataModificationHook(cleanupTexturesForPixampData); |
1584 #ifdef Q_WS_X11 |
1598 QImagePixmapCleanupHooks::instance()->addPixmapDataDestructionHook(cleanupBeforePixmapDestruction); |
1585 QImagePixmapCleanupHooks::instance()->addPixmapDestructionHook(cleanupPixmapSurfaces); |
1599 QImagePixmapCleanupHooks::instance()->addImageHook(cleanupTexturesForCacheKey); |
1586 #endif |
|
1587 QImagePixmapCleanupHooks::instance()->addImageHook(imageCleanupHook); |
|
1588 } |
1600 } |
1589 |
1601 |
1590 QGLTextureCache::~QGLTextureCache() |
1602 QGLTextureCache::~QGLTextureCache() |
1591 { |
1603 { |
1592 qt_gl_texture_cache = 0; |
1604 qt_gl_texture_cache = 0; |
1593 |
1605 |
1594 QImagePixmapCleanupHooks::instance()->removePixmapModificationHook(cleanupTextures); |
1606 QImagePixmapCleanupHooks::instance()->removePixmapDataModificationHook(cleanupTexturesForPixampData); |
1595 #ifdef Q_WS_X11 |
1607 QImagePixmapCleanupHooks::instance()->removePixmapDataDestructionHook(cleanupBeforePixmapDestruction); |
1596 QImagePixmapCleanupHooks::instance()->removePixmapDestructionHook(cleanupPixmapSurfaces); |
1608 QImagePixmapCleanupHooks::instance()->removeImageHook(cleanupTexturesForCacheKey); |
1597 #endif |
|
1598 QImagePixmapCleanupHooks::instance()->removeImageHook(imageCleanupHook); |
|
1599 } |
1609 } |
1600 |
1610 |
1601 void QGLTextureCache::insert(QGLContext* ctx, qint64 key, QGLTexture* texture, int cost) |
1611 void QGLTextureCache::insert(QGLContext* ctx, qint64 key, QGLTexture* texture, int cost) |
1602 { |
1612 { |
1603 if (m_cache.totalCost() + cost > m_cache.maxCost()) { |
1613 if (m_cache.totalCost() + cost > m_cache.maxCost()) { |
1649 |
1659 |
1650 /* |
1660 /* |
1651 a hook that removes textures from the cache when a pixmap/image |
1661 a hook that removes textures from the cache when a pixmap/image |
1652 is deref'ed |
1662 is deref'ed |
1653 */ |
1663 */ |
1654 void QGLTextureCache::imageCleanupHook(qint64 cacheKey) |
1664 void QGLTextureCache::cleanupTexturesForCacheKey(qint64 cacheKey) |
1655 { |
|
1656 // ### remove when the GL texture cache becomes thread-safe |
|
1657 if (qApp->thread() != QThread::currentThread()) |
|
1658 return; |
|
1659 QGLTexture *texture = instance()->getTexture(cacheKey); |
|
1660 if (texture && texture->options & QGLContext::MemoryManagedBindOption) |
|
1661 instance()->remove(cacheKey); |
|
1662 } |
|
1663 |
|
1664 |
|
1665 void QGLTextureCache::cleanupTextures(QPixmap* pixmap) |
|
1666 { |
1665 { |
1667 // ### remove when the GL texture cache becomes thread-safe |
1666 // ### remove when the GL texture cache becomes thread-safe |
1668 if (qApp->thread() == QThread::currentThread()) { |
1667 if (qApp->thread() == QThread::currentThread()) { |
1669 const qint64 cacheKey = pixmap->cacheKey(); |
1668 instance()->remove(cacheKey); |
1670 QGLTexture *texture = instance()->getTexture(cacheKey); |
1669 Q_ASSERT(instance()->getTexture(cacheKey) == 0); |
1671 if (texture && texture->options & QGLContext::MemoryManagedBindOption) |
1670 } |
1672 instance()->remove(cacheKey); |
1671 } |
1673 } |
1672 |
1674 } |
1673 |
|
1674 void QGLTextureCache::cleanupTexturesForPixampData(QPixmapData* pmd) |
|
1675 { |
|
1676 cleanupTexturesForCacheKey(pmd->cacheKey()); |
|
1677 } |
|
1678 |
|
1679 void QGLTextureCache::cleanupBeforePixmapDestruction(QPixmapData* pmd) |
|
1680 { |
|
1681 // Remove any bound textures first: |
|
1682 cleanupTexturesForPixampData(pmd); |
1675 |
1683 |
1676 #if defined(Q_WS_X11) |
1684 #if defined(Q_WS_X11) |
1677 void QGLTextureCache::cleanupPixmapSurfaces(QPixmap* pixmap) |
1685 if (pmd->classId() == QPixmapData::X11Class) { |
1678 { |
1686 Q_ASSERT(pmd->ref == 0); // Make sure reference counting isn't broken |
1679 // Remove any bound textures first: |
1687 QGLContextPrivate::destroyGlSurfaceForPixmap(pmd); |
1680 cleanupTextures(pixmap); |
1688 } |
1681 |
1689 #endif |
1682 QPixmapData *pd = pixmap->data_ptr().data(); |
1690 } |
1683 if (pd->classId() == QPixmapData::X11Class) { |
|
1684 Q_ASSERT(pd->ref == 1); // Make sure reference counting isn't broken |
|
1685 QGLContextPrivate::destroyGlSurfaceForPixmap(pd); |
|
1686 } |
|
1687 } |
|
1688 #endif |
|
1689 |
1691 |
1690 void QGLTextureCache::deleteIfEmpty() |
1692 void QGLTextureCache::deleteIfEmpty() |
1691 { |
1693 { |
1692 if (instance()->size() == 0) |
1694 if (instance()->size() == 0) |
1693 delete instance(); |
1695 delete instance(); |
1727 #ifndef GL_GENERATE_MIPMAP_SGIS |
1729 #ifndef GL_GENERATE_MIPMAP_SGIS |
1728 #define GL_GENERATE_MIPMAP_SGIS 0x8191 |
1730 #define GL_GENERATE_MIPMAP_SGIS 0x8191 |
1729 #define GL_GENERATE_MIPMAP_HINT_SGIS 0x8192 |
1731 #define GL_GENERATE_MIPMAP_HINT_SGIS 0x8192 |
1730 #endif |
1732 #endif |
1731 |
1733 |
1732 Q_GLOBAL_STATIC(QGLShareRegister, _qgl_share_reg) |
|
1733 Q_OPENGL_EXPORT QGLShareRegister* qgl_share_reg() |
|
1734 { |
|
1735 return _qgl_share_reg(); |
|
1736 } |
|
1737 |
|
1738 /*! |
1734 /*! |
1739 \class QGLContext |
1735 \class QGLContext |
1740 \brief The QGLContext class encapsulates an OpenGL rendering context. |
1736 \brief The QGLContext class encapsulates an OpenGL rendering context. |
1741 |
1737 |
1742 \ingroup painting-3D |
1738 \ingroup painting-3D |
1871 } |
1867 } |
1872 |
1868 |
1873 void QGLContextPrivate::cleanup() |
1869 void QGLContextPrivate::cleanup() |
1874 { |
1870 { |
1875 } |
1871 } |
|
1872 |
|
1873 #define ctx q_ptr |
|
1874 void QGLContextPrivate::setVertexAttribArrayEnabled(int arrayIndex, bool enabled) |
|
1875 { |
|
1876 Q_ASSERT(arrayIndex < QT_GL_VERTEX_ARRAY_TRACKED_COUNT); |
|
1877 Q_ASSERT(glEnableVertexAttribArray); |
|
1878 |
|
1879 if (vertexAttributeArraysEnabledState[arrayIndex] && !enabled) |
|
1880 glDisableVertexAttribArray(arrayIndex); |
|
1881 |
|
1882 if (!vertexAttributeArraysEnabledState[arrayIndex] && enabled) |
|
1883 glEnableVertexAttribArray(arrayIndex); |
|
1884 |
|
1885 vertexAttributeArraysEnabledState[arrayIndex] = enabled; |
|
1886 } |
|
1887 |
|
1888 void QGLContextPrivate::syncGlState() |
|
1889 { |
|
1890 Q_ASSERT(glEnableVertexAttribArray); |
|
1891 for (int i = 0; i < QT_GL_VERTEX_ARRAY_TRACKED_COUNT; ++i) { |
|
1892 if (vertexAttributeArraysEnabledState[i]) |
|
1893 glEnableVertexAttribArray(i); |
|
1894 else |
|
1895 glDisableVertexAttribArray(i); |
|
1896 } |
|
1897 |
|
1898 } |
|
1899 #undef ctx |
|
1900 |
1876 |
1901 |
1877 /*! |
1902 /*! |
1878 \overload |
1903 \overload |
1879 |
1904 |
1880 Reads the compressed texture file \a fileName and generates a 2D GL |
1905 Reads the compressed texture file \a fileName and generates a 2D GL |
2053 if (!texture) |
2078 if (!texture) |
2054 texture = bindTexture(image, target, format, key, options); |
2079 texture = bindTexture(image, target, format, key, options); |
2055 // NOTE: bindTexture(const QImage&, GLenum, GLint, const qint64, bool) should never return null |
2080 // NOTE: bindTexture(const QImage&, GLenum, GLint, const qint64, bool) should never return null |
2056 Q_ASSERT(texture); |
2081 Q_ASSERT(texture); |
2057 |
2082 |
2058 if (texture->id > 0) |
2083 // Enable the cleanup hooks for this image so that the texture cache entry is removed when the |
2059 QImagePixmapCleanupHooks::enableCleanupHooks(image); |
2084 // image gets deleted: |
|
2085 QImagePixmapCleanupHooks::enableCleanupHooks(image); |
2060 |
2086 |
2061 return texture; |
2087 return texture; |
2062 } |
2088 } |
2063 |
2089 |
2064 // #define QGL_BIND_TEXTURE_DEBUG |
2090 // #define QGL_BIND_TEXTURE_DEBUG |
2108 // 2.0 or use the GL_TEXTURE_RECTANGLE texture target |
2134 // 2.0 or use the GL_TEXTURE_RECTANGLE texture target |
2109 int tx_w = qt_next_power_of_two(image.width()); |
2135 int tx_w = qt_next_power_of_two(image.width()); |
2110 int tx_h = qt_next_power_of_two(image.height()); |
2136 int tx_h = qt_next_power_of_two(image.height()); |
2111 |
2137 |
2112 QImage img = image; |
2138 QImage img = image; |
2113 if (!(QGLExtensions::glExtensions & QGLExtensions::NPOTTextures) |
2139 |
|
2140 if (!(QGLExtensions::glExtensions() & QGLExtensions::NPOTTextures) |
2114 && !(QGLFormat::openGLVersionFlags() & QGLFormat::OpenGL_ES_Version_2_0) |
2141 && !(QGLFormat::openGLVersionFlags() & QGLFormat::OpenGL_ES_Version_2_0) |
2115 && (target == GL_TEXTURE_2D && (tx_w != image.width() || tx_h != image.height()))) |
2142 && (target == GL_TEXTURE_2D && (tx_w != image.width() || tx_h != image.height()))) |
2116 { |
2143 { |
2117 img = img.scaled(tx_w, tx_h); |
2144 img = img.scaled(tx_w, tx_h); |
2118 #ifdef QGL_BIND_TEXTURE_DEBUG |
2145 #ifdef QGL_BIND_TEXTURE_DEBUG |
2130 |
2157 |
2131 #if defined(QT_OPENGL_ES_2) |
2158 #if defined(QT_OPENGL_ES_2) |
2132 bool genMipmap = false; |
2159 bool genMipmap = false; |
2133 #endif |
2160 #endif |
2134 if (glFormat.directRendering() |
2161 if (glFormat.directRendering() |
2135 && (QGLExtensions::glExtensions & QGLExtensions::GenerateMipmap) |
2162 && (QGLExtensions::glExtensions() & QGLExtensions::GenerateMipmap) |
2136 && target == GL_TEXTURE_2D |
2163 && target == GL_TEXTURE_2D |
2137 && (options & QGLContext::MipmapBindOption)) |
2164 && (options & QGLContext::MipmapBindOption)) |
2138 { |
2165 { |
2139 #ifdef QGL_BIND_TEXTURE_DEBUG |
2166 #ifdef QGL_BIND_TEXTURE_DEBUG |
2140 printf(" - generating mipmaps (%d ms)\n", time.elapsed()); |
2167 printf(" - generating mipmaps (%d ms)\n", time.elapsed()); |
2158 |
2185 |
2159 QImage::Format target_format = img.format(); |
2186 QImage::Format target_format = img.format(); |
2160 bool premul = options & QGLContext::PremultipliedAlphaBindOption; |
2187 bool premul = options & QGLContext::PremultipliedAlphaBindOption; |
2161 GLenum externalFormat; |
2188 GLenum externalFormat; |
2162 GLuint pixel_type; |
2189 GLuint pixel_type; |
2163 if (QGLExtensions::glExtensions & QGLExtensions::BGRATextureFormat) { |
2190 if (QGLExtensions::glExtensions() & QGLExtensions::BGRATextureFormat) { |
2164 externalFormat = GL_BGRA; |
2191 externalFormat = GL_BGRA; |
2165 pixel_type = GL_UNSIGNED_INT_8_8_8_8_REV; |
2192 if (QGLFormat::openGLVersionFlags() & QGLFormat::OpenGL_Version_1_2) |
|
2193 pixel_type = GL_UNSIGNED_INT_8_8_8_8_REV; |
|
2194 else |
|
2195 pixel_type = GL_UNSIGNED_BYTE; |
2166 } else { |
2196 } else { |
2167 externalFormat = GL_RGBA; |
2197 externalFormat = GL_RGBA; |
2168 pixel_type = GL_UNSIGNED_BYTE; |
2198 pixel_type = GL_UNSIGNED_BYTE; |
2169 } |
2199 } |
2170 |
2200 |
2239 // the format to GL_RGB |
2269 // the format to GL_RGB |
2240 Q_ASSERT(img.depth() == 32); |
2270 Q_ASSERT(img.depth() == 32); |
2241 qgl_byteSwapImage(img, pixel_type); |
2271 qgl_byteSwapImage(img, pixel_type); |
2242 } |
2272 } |
2243 #ifdef QT_OPENGL_ES |
2273 #ifdef QT_OPENGL_ES |
2244 // OpenGL/ES requires that the internal and external formats be identical. |
2274 // OpenGL/ES requires that the internal and external formats be |
2245 // This is typically used to convert GL_RGBA into GL_BGRA. |
2275 // identical. |
2246 // Also, we need to use GL_UNSIGNED_BYTE when the format is GL_BGRA. |
|
2247 internalFormat = externalFormat; |
2276 internalFormat = externalFormat; |
2248 if (pixel_type == GL_UNSIGNED_INT_8_8_8_8_REV) |
|
2249 pixel_type = GL_UNSIGNED_BYTE; |
|
2250 #endif |
2277 #endif |
2251 #ifdef QGL_BIND_TEXTURE_DEBUG |
2278 #ifdef QGL_BIND_TEXTURE_DEBUG |
2252 printf(" - uploading, image.format=%d, externalFormat=0x%x, internalFormat=0x%x, pixel_type=0x%x\n", |
2279 printf(" - uploading, image.format=%d, externalFormat=0x%x, internalFormat=0x%x, pixel_type=0x%x\n", |
2253 img.format(), externalFormat, internalFormat, pixel_type); |
2280 img.format(), externalFormat, internalFormat, pixel_type); |
2254 #endif |
2281 #endif |
2276 |
2303 |
2277 // this assumes the size of a texture is always smaller than the max cache size |
2304 // this assumes the size of a texture is always smaller than the max cache size |
2278 int cost = img.width()*img.height()*4/1024; |
2305 int cost = img.width()*img.height()*4/1024; |
2279 QGLTexture *texture = new QGLTexture(q, tx_id, target, options); |
2306 QGLTexture *texture = new QGLTexture(q, tx_id, target, options); |
2280 QGLTextureCache::instance()->insert(q, key, texture, cost); |
2307 QGLTextureCache::instance()->insert(q, key, texture, cost); |
|
2308 |
2281 return texture; |
2309 return texture; |
2282 } |
2310 } |
2283 |
2311 |
2284 QGLTexture *QGLContextPrivate::textureCacheLookup(const qint64 key, GLenum target) |
2312 QGLTexture *QGLContextPrivate::textureCacheLookup(const qint64 key, GLenum target) |
2285 { |
2313 { |
2320 return texture; |
2348 return texture; |
2321 } |
2349 } |
2322 |
2350 |
2323 #if defined(Q_WS_X11) |
2351 #if defined(Q_WS_X11) |
2324 // Try to use texture_from_pixmap |
2352 // Try to use texture_from_pixmap |
2325 if (pd->classId() == QPixmapData::X11Class && pd->pixelType() == QPixmapData::PixmapType) { |
2353 const QX11Info *xinfo = qt_x11Info(paintDevice); |
|
2354 if (pd->classId() == QPixmapData::X11Class && pd->pixelType() == QPixmapData::PixmapType |
|
2355 && xinfo && xinfo->screen() == pixmap.x11Info().screen()) |
|
2356 { |
2326 texture = bindTextureFromNativePixmap(pd, key, options); |
2357 texture = bindTextureFromNativePixmap(pd, key, options); |
2327 if (texture) { |
2358 if (texture) { |
2328 texture->options |= QGLContext::MemoryManagedBindOption; |
2359 texture->options |= QGLContext::MemoryManagedBindOption; |
2329 texture->boundPixmap = pd; |
2360 texture->boundPixmap = pd; |
2330 boundPixmaps.insert(pd, QPixmap(pixmap)); |
2361 boundPixmaps.insert(pd, QPixmap(pixmap)); |
2529 QGLDDSCache *dds_cache = &(d->group->m_dds_cache); |
2560 QGLDDSCache *dds_cache = &(d->group->m_dds_cache); |
2530 QList<QString> ddsKeys = dds_cache->keys(); |
2561 QList<QString> ddsKeys = dds_cache->keys(); |
2531 for (int i = 0; i < ddsKeys.size(); ++i) { |
2562 for (int i = 0; i < ddsKeys.size(); ++i) { |
2532 GLuint texture = dds_cache->value(ddsKeys.at(i)); |
2563 GLuint texture = dds_cache->value(ddsKeys.at(i)); |
2533 if (id == texture) { |
2564 if (id == texture) { |
2534 glDeleteTextures(1, &texture); |
|
2535 dds_cache->remove(ddsKeys.at(i)); |
2565 dds_cache->remove(ddsKeys.at(i)); |
2536 return; |
2566 break; |
2537 } |
2567 } |
2538 } |
2568 } |
|
2569 |
|
2570 // Finally, actually delete the texture ID |
|
2571 glDeleteTextures(1, &id); |
2539 } |
2572 } |
2540 |
2573 |
2541 #ifdef Q_MAC_COMPAT_GL_FUNCTIONS |
2574 #ifdef Q_MAC_COMPAT_GL_FUNCTIONS |
2542 /*! \internal */ |
2575 /*! \internal */ |
2543 void QGLContext::deleteTexture(QMacCompatGLuint id) |
2576 void QGLContext::deleteTexture(QMacCompatGLuint id) |
2952 if (d->valid && d->paintDevice->devType() == QInternal::Widget) { |
2985 if (d->valid && d->paintDevice->devType() == QInternal::Widget) { |
2953 QWidgetPrivate *wd = qt_widget_private(static_cast<QWidget *>(d->paintDevice)); |
2986 QWidgetPrivate *wd = qt_widget_private(static_cast<QWidget *>(d->paintDevice)); |
2954 wd->usesDoubleBufferedGLContext = d->glFormat.doubleBuffer(); |
2987 wd->usesDoubleBufferedGLContext = d->glFormat.doubleBuffer(); |
2955 } |
2988 } |
2956 if (d->sharing) // ok, we managed to share |
2989 if (d->sharing) // ok, we managed to share |
2957 qgl_share_reg()->addShare(this, shareContext); |
2990 QGLContextGroup::addShare(this, shareContext); |
2958 return d->valid; |
2991 return d->valid; |
2959 } |
2992 } |
2960 |
2993 |
2961 bool QGLContext::isValid() const |
2994 bool QGLContext::isValid() const |
2962 { |
2995 { |
4358 \note This function is not supported on OpenGL/ES systems. |
4391 \note This function is not supported on OpenGL/ES systems. |
4359 |
4392 |
4360 \note This function temporarily disables depth-testing when the |
4393 \note This function temporarily disables depth-testing when the |
4361 text is drawn. |
4394 text is drawn. |
4362 |
4395 |
|
4396 \note This function can only be used inside a |
|
4397 QPainter::beginNativePainting()/QPainter::endNativePainting() block |
|
4398 if the default OpenGL paint engine is QPaintEngine::OpenGL. To make |
|
4399 QPaintEngine::OpenGL the default GL engine, call |
|
4400 QGL::setPreferredPaintEngine(QPaintEngine::OpenGL) before the |
|
4401 QApplication constructor. |
|
4402 |
4363 \l{Overpainting Example}{Overpaint} with QPainter::drawText() instead. |
4403 \l{Overpainting Example}{Overpaint} with QPainter::drawText() instead. |
4364 */ |
4404 */ |
4365 |
4405 |
4366 void QGLWidget::renderText(int x, int y, const QString &str, const QFont &font, int) |
4406 void QGLWidget::renderText(int x, int y, const QString &str, const QFont &font, int) |
4367 { |
4407 { |
4376 glGetIntegerv(GL_VIEWPORT, &view[0]); |
4416 glGetIntegerv(GL_VIEWPORT, &view[0]); |
4377 int width = d->glcx->device()->width(); |
4417 int width = d->glcx->device()->width(); |
4378 int height = d->glcx->device()->height(); |
4418 int height = d->glcx->device()->height(); |
4379 bool auto_swap = autoBufferSwap(); |
4419 bool auto_swap = autoBufferSwap(); |
4380 |
4420 |
|
4421 QPaintEngine::Type oldEngineType = qgl_engine_selector()->preferredPaintEngine(); |
|
4422 |
4381 QPaintEngine *engine = paintEngine(); |
4423 QPaintEngine *engine = paintEngine(); |
4382 if (engine->type() == QPaintEngine::OpenGL2) |
4424 if (engine && (oldEngineType == QPaintEngine::OpenGL2) && engine->isActive()) { |
4383 static_cast<QGL2PaintEngineEx *>(engine)->setRenderTextActive(true); |
4425 qWarning("QGLWidget::renderText(): Calling renderText() while a GL 2 paint engine is" |
|
4426 " active on the same device is not allowed."); |
|
4427 return; |
|
4428 } |
|
4429 |
|
4430 // this changes what paintEngine() returns |
|
4431 qgl_engine_selector()->setPreferredPaintEngine(QPaintEngine::OpenGL); |
|
4432 engine = paintEngine(); |
4384 QPainter *p; |
4433 QPainter *p; |
4385 bool reuse_painter = false; |
4434 bool reuse_painter = false; |
4386 if (engine->isActive()) { |
4435 if (engine->isActive()) { |
4387 reuse_painter = true; |
4436 reuse_painter = true; |
4388 p = engine->painter(); |
4437 p = engine->painter(); |
4398 glLoadIdentity(); |
4447 glLoadIdentity(); |
4399 } else { |
4448 } else { |
4400 setAutoBufferSwap(false); |
4449 setAutoBufferSwap(false); |
4401 // disable glClear() as a result of QPainter::begin() |
4450 // disable glClear() as a result of QPainter::begin() |
4402 d->disable_clear_on_painter_begin = true; |
4451 d->disable_clear_on_painter_begin = true; |
4403 if (engine->type() == QPaintEngine::OpenGL2) { |
|
4404 qt_save_gl_state(); |
|
4405 glMatrixMode(GL_MODELVIEW); |
|
4406 glLoadIdentity(); |
|
4407 } |
|
4408 p = new QPainter(this); |
4452 p = new QPainter(this); |
4409 } |
4453 } |
4410 |
4454 |
4411 QRect viewport(view[0], view[1], view[2], view[3]); |
4455 QRect viewport(view[0], view[1], view[2], view[3]); |
4412 if (!use_scissor_testing && viewport != rect()) { |
4456 if (!use_scissor_testing && viewport != rect()) { |
4426 } else { |
4470 } else { |
4427 p->end(); |
4471 p->end(); |
4428 delete p; |
4472 delete p; |
4429 setAutoBufferSwap(auto_swap); |
4473 setAutoBufferSwap(auto_swap); |
4430 d->disable_clear_on_painter_begin = false; |
4474 d->disable_clear_on_painter_begin = false; |
4431 if (engine->type() == QPaintEngine::OpenGL2) |
4475 } |
4432 qt_restore_gl_state(); |
4476 qgl_engine_selector()->setPreferredPaintEngine(oldEngineType); |
4433 } |
|
4434 if (engine->type() == QPaintEngine::OpenGL2) |
|
4435 static_cast<QGL2PaintEngineEx *>(engine)->setRenderTextActive(false); |
|
4436 #else // QT_OPENGL_ES |
4477 #else // QT_OPENGL_ES |
4437 Q_UNUSED(x); |
4478 Q_UNUSED(x); |
4438 Q_UNUSED(y); |
4479 Q_UNUSED(y); |
4439 Q_UNUSED(str); |
4480 Q_UNUSED(str); |
4440 Q_UNUSED(font); |
4481 Q_UNUSED(font); |
4478 GLdouble win_x = 0, win_y = 0, win_z = 0; |
4519 GLdouble win_x = 0, win_y = 0, win_z = 0; |
4479 qgluProject(x, y, z, &model[0][0], &proj[0][0], &view[0], |
4520 qgluProject(x, y, z, &model[0][0], &proj[0][0], &view[0], |
4480 &win_x, &win_y, &win_z); |
4521 &win_x, &win_y, &win_z); |
4481 win_y = height - win_y; // y is inverted |
4522 win_y = height - win_y; // y is inverted |
4482 |
4523 |
|
4524 QPaintEngine::Type oldEngineType = qgl_engine_selector()->preferredPaintEngine(); |
4483 QPaintEngine *engine = paintEngine(); |
4525 QPaintEngine *engine = paintEngine(); |
4484 if (engine->type() == QPaintEngine::OpenGL2) |
4526 |
4485 static_cast<QGL2PaintEngineEx *>(engine)->setRenderTextActive(true); |
4527 if (engine && (oldEngineType == QPaintEngine::OpenGL2) && engine->isActive()) { |
|
4528 qWarning("QGLWidget::renderText(): Calling renderText() while a GL 2 paint engine is" |
|
4529 " active on the same device is not allowed."); |
|
4530 return; |
|
4531 } |
|
4532 |
|
4533 // this changes what paintEngine() returns |
|
4534 qgl_engine_selector()->setPreferredPaintEngine(QPaintEngine::OpenGL); |
|
4535 engine = paintEngine(); |
4486 QPainter *p; |
4536 QPainter *p; |
4487 bool reuse_painter = false; |
4537 bool reuse_painter = false; |
4488 bool use_depth_testing = glIsEnabled(GL_DEPTH_TEST); |
4538 bool use_depth_testing = glIsEnabled(GL_DEPTH_TEST); |
4489 bool use_scissor_testing = glIsEnabled(GL_SCISSOR_TEST); |
4539 bool use_scissor_testing = glIsEnabled(GL_SCISSOR_TEST); |
4490 |
4540 |
4494 qt_save_gl_state(); |
4544 qt_save_gl_state(); |
4495 } else { |
4545 } else { |
4496 setAutoBufferSwap(false); |
4546 setAutoBufferSwap(false); |
4497 // disable glClear() as a result of QPainter::begin() |
4547 // disable glClear() as a result of QPainter::begin() |
4498 d->disable_clear_on_painter_begin = true; |
4548 d->disable_clear_on_painter_begin = true; |
4499 if (engine->type() == QPaintEngine::OpenGL2) |
|
4500 qt_save_gl_state(); |
|
4501 p = new QPainter(this); |
4549 p = new QPainter(this); |
4502 } |
4550 } |
4503 |
4551 |
4504 QRect viewport(view[0], view[1], view[2], view[3]); |
4552 QRect viewport(view[0], view[1], view[2], view[3]); |
4505 if (!use_scissor_testing && viewport != rect()) { |
4553 if (!use_scissor_testing && viewport != rect()) { |
4524 if (reuse_painter) { |
4572 if (reuse_painter) { |
4525 qt_restore_gl_state(); |
4573 qt_restore_gl_state(); |
4526 } else { |
4574 } else { |
4527 p->end(); |
4575 p->end(); |
4528 delete p; |
4576 delete p; |
4529 if (engine->type() == QPaintEngine::OpenGL2) |
|
4530 qt_restore_gl_state(); |
|
4531 setAutoBufferSwap(auto_swap); |
4577 setAutoBufferSwap(auto_swap); |
4532 d->disable_clear_on_painter_begin = false; |
4578 d->disable_clear_on_painter_begin = false; |
4533 } |
4579 } |
4534 if (engine->type() == QPaintEngine::OpenGL2) |
4580 qgl_engine_selector()->setPreferredPaintEngine(oldEngineType); |
4535 static_cast<QGL2PaintEngineEx *>(engine)->setRenderTextActive(false); |
|
4536 #else // QT_OPENGL_ES |
4581 #else // QT_OPENGL_ES |
4537 Q_UNUSED(x); |
4582 Q_UNUSED(x); |
4538 Q_UNUSED(y); |
4583 Q_UNUSED(y); |
4539 Q_UNUSED(z); |
4584 Q_UNUSED(z); |
4540 Q_UNUSED(str); |
4585 Q_UNUSED(str); |
4842 d->init(context, shareWidget); |
4887 d->init(context, shareWidget); |
4843 } |
4888 } |
4844 |
4889 |
4845 #endif // QT3_SUPPORT |
4890 #endif // QT3_SUPPORT |
4846 |
4891 |
4847 void QGLExtensions::init_extensions() |
4892 /* |
|
4893 Returns the GL extensions for the current context. |
|
4894 */ |
|
4895 QGLExtensions::Extensions QGLExtensions::currentContextExtensions() |
4848 { |
4896 { |
4849 QGLExtensionMatcher extensions(reinterpret_cast<const char *>(glGetString(GL_EXTENSIONS))); |
4897 QGLExtensionMatcher extensions(reinterpret_cast<const char *>(glGetString(GL_EXTENSIONS))); |
|
4898 Extensions glExtensions; |
4850 |
4899 |
4851 if (extensions.match("GL_ARB_texture_rectangle")) |
4900 if (extensions.match("GL_ARB_texture_rectangle")) |
4852 glExtensions |= TextureRectangle; |
4901 glExtensions |= TextureRectangle; |
4853 if (extensions.match("GL_ARB_multisample")) |
4902 if (extensions.match("GL_ARB_multisample")) |
4854 glExtensions |= SampleBuffers; |
4903 glExtensions |= SampleBuffers; |
4905 if (extensions.match("GL_ARB_texture_non_power_of_two")) |
4954 if (extensions.match("GL_ARB_texture_non_power_of_two")) |
4906 glExtensions |= NPOTTextures; |
4955 glExtensions |= NPOTTextures; |
4907 |
4956 |
4908 if (extensions.match("GL_EXT_bgra")) |
4957 if (extensions.match("GL_EXT_bgra")) |
4909 glExtensions |= BGRATextureFormat; |
4958 glExtensions |= BGRATextureFormat; |
|
4959 |
|
4960 return glExtensions; |
|
4961 } |
|
4962 |
|
4963 /* |
|
4964 Returns the GL extensions for the current QGLContext. If there is no |
|
4965 current QGLContext, a default context will be created and the extensions |
|
4966 for that context will be returned instead. |
|
4967 */ |
|
4968 QGLExtensions::Extensions QGLExtensions::glExtensions() |
|
4969 { |
|
4970 QGLTemporaryContext *tmpContext = 0; |
|
4971 static bool cachedDefault = false; |
|
4972 static Extensions defaultExtensions = 0; |
|
4973 QGLContext *currentCtx = const_cast<QGLContext *>(QGLContext::currentContext()); |
|
4974 |
|
4975 if (currentCtx && currentCtx->d_func()->extension_flags_cached) |
|
4976 return currentCtx->d_func()->extension_flags; |
|
4977 |
|
4978 if (!currentCtx) { |
|
4979 if (cachedDefault) { |
|
4980 return defaultExtensions; |
|
4981 } else { |
|
4982 tmpContext = new QGLTemporaryContext; |
|
4983 cachedDefault = true; |
|
4984 } |
|
4985 } |
|
4986 |
|
4987 Extensions extensionFlags = currentContextExtensions(); |
|
4988 if (currentCtx) { |
|
4989 currentCtx->d_func()->extension_flags_cached = true; |
|
4990 currentCtx->d_func()->extension_flags = extensionFlags; |
|
4991 } else { |
|
4992 defaultExtensions = extensionFlags; |
|
4993 } |
|
4994 |
|
4995 if (tmpContext) |
|
4996 delete tmpContext; |
|
4997 |
|
4998 return extensionFlags; |
4910 } |
4999 } |
4911 |
5000 |
4912 /* |
5001 /* |
4913 This is the shared initialization for all platforms. Called from QGLWidgetPrivate::init() |
5002 This is the shared initialization for all platforms. Called from QGLWidgetPrivate::init() |
4914 */ |
5003 */ |
4916 { |
5005 { |
4917 Q_Q(QGLWidget); |
5006 Q_Q(QGLWidget); |
4918 |
5007 |
4919 glDevice.setWidget(q); |
5008 glDevice.setWidget(q); |
4920 |
5009 |
4921 QGLExtensions::init(); |
|
4922 glcx = 0; |
5010 glcx = 0; |
4923 autoSwap = true; |
5011 autoSwap = true; |
4924 |
5012 |
4925 if (context && !context->device()) |
5013 if (context && !context->device()) |
4926 context->setDevice(q); |
5014 context->setDevice(q); |
4927 q->setContext(context, shareWidget ? shareWidget->context() : 0); |
5015 q->setContext(context, shareWidget ? shareWidget->context() : 0); |
4928 |
5016 |
4929 if (!glcx) |
5017 if (!glcx) |
4930 glcx = new QGLContext(QGLFormat::defaultFormat(), q); |
5018 glcx = new QGLContext(QGLFormat::defaultFormat(), q); |
4931 |
|
4932 q->setAttribute(Qt::WA_NoSystemBackground); |
|
4933 } |
5019 } |
4934 |
5020 |
4935 #if defined(Q_WS_X11) || defined(Q_WS_MAC) || defined(Q_WS_QWS) |
5021 #if defined(Q_WS_X11) || defined(Q_WS_MAC) || defined(Q_WS_QWS) |
4936 Q_GLOBAL_STATIC(QString, qt_gl_lib_name) |
5022 Q_GLOBAL_STATIC(QString, qt_gl_lib_name) |
4937 |
5023 |
4951 } |
5037 } |
4952 return *qt_gl_lib_name(); |
5038 return *qt_gl_lib_name(); |
4953 } |
5039 } |
4954 #endif |
5040 #endif |
4955 |
5041 |
4956 void QGLShareRegister::addShare(const QGLContext *context, const QGLContext *share) { |
5042 void QGLContextGroup::addShare(const QGLContext *context, const QGLContext *share) { |
4957 Q_ASSERT(context && share); |
5043 Q_ASSERT(context && share); |
4958 if (context->d_ptr->group == share->d_ptr->group) |
5044 if (context->d_ptr->group == share->d_ptr->group) |
4959 return; |
5045 return; |
4960 |
5046 |
4961 // Make sure 'context' is not already shared with another group of contexts. |
5047 // Make sure 'context' is not already shared with another group of contexts. |
4972 if (group->m_shares.isEmpty()) |
5058 if (group->m_shares.isEmpty()) |
4973 group->m_shares.append(share); |
5059 group->m_shares.append(share); |
4974 group->m_shares.append(context); |
5060 group->m_shares.append(context); |
4975 } |
5061 } |
4976 |
5062 |
4977 QList<const QGLContext *> QGLShareRegister::shares(const QGLContext *context) { |
5063 void QGLContextGroup::removeShare(const QGLContext *context) { |
4978 return context->d_ptr->group->m_shares; |
|
4979 } |
|
4980 |
|
4981 void QGLShareRegister::removeShare(const QGLContext *context) { |
|
4982 // Remove the context from the group. |
5064 // Remove the context from the group. |
4983 QGLContextGroup *group = context->d_ptr->group; |
5065 QGLContextGroup *group = context->d_ptr->group; |
4984 if (group->m_shares.isEmpty()) |
5066 if (group->m_shares.isEmpty()) |
4985 return; |
5067 return; |
4986 group->m_shares.removeAll(context); |
5068 group->m_shares.removeAll(context); |
5171 // systems such as x86 and ARM at the moment. |
5253 // systems such as x86 and ARM at the moment. |
5172 return QSize(); |
5254 return QSize(); |
5173 } |
5255 } |
5174 #if !defined(QT_OPENGL_ES) |
5256 #if !defined(QT_OPENGL_ES) |
5175 if (!glCompressedTexImage2D) { |
5257 if (!glCompressedTexImage2D) { |
5176 if (!(QGLExtensions::glExtensions & QGLExtensions::TextureCompression)) { |
5258 if (!(QGLExtensions::glExtensions() & QGLExtensions::TextureCompression)) { |
5177 qWarning("QGLContext::bindTexture(): The GL implementation does " |
5259 qWarning("QGLContext::bindTexture(): The GL implementation does " |
5178 "not support texture compression extensions."); |
5260 "not support texture compression extensions."); |
5179 return QSize(); |
5261 return QSize(); |
5180 } |
5262 } |
5181 glCompressedTexImage2D = (_glCompressedTexImage2DARB) ctx->getProcAddress(QLatin1String("glCompressedTexImage2DARB")); |
5263 glCompressedTexImage2D = (_glCompressedTexImage2DARB) ctx->getProcAddress(QLatin1String("glCompressedTexImage2DARB")); |
5210 // We only support 2D texture loading at present. |
5292 // We only support 2D texture loading at present. |
5211 if (target != GL_TEXTURE_2D) |
5293 if (target != GL_TEXTURE_2D) |
5212 return QSize(); |
5294 return QSize(); |
5213 |
5295 |
5214 // Bail out if the necessary extension is not present. |
5296 // Bail out if the necessary extension is not present. |
5215 if (!(QGLExtensions::glExtensions & QGLExtensions::DDSTextureCompression)) { |
5297 if (!(QGLExtensions::glExtensions() & QGLExtensions::DDSTextureCompression)) { |
5216 qWarning("QGLContext::bindTexture(): DDS texture compression is not supported."); |
5298 qWarning("QGLContext::bindTexture(): DDS texture compression is not supported."); |
5217 return QSize(); |
5299 return QSize(); |
5218 } |
5300 } |
5219 |
5301 |
5220 const DDSFormat *ddsHeader = reinterpret_cast<const DDSFormat *>(buf + 4); |
5302 const DDSFormat *ddsHeader = reinterpret_cast<const DDSFormat *>(buf + 4); |
5320 return QSize(); |
5402 return QSize(); |
5321 } |
5403 } |
5322 |
5404 |
5323 // Bail out if the necessary extension is not present. |
5405 // Bail out if the necessary extension is not present. |
5324 if (textureFormat == GL_ETC1_RGB8_OES) { |
5406 if (textureFormat == GL_ETC1_RGB8_OES) { |
5325 if (!(QGLExtensions::glExtensions & |
5407 if (!(QGLExtensions::glExtensions() & |
5326 QGLExtensions::ETC1TextureCompression)) { |
5408 QGLExtensions::ETC1TextureCompression)) { |
5327 qWarning("QGLContext::bindTexture(): ETC1 texture compression is not supported."); |
5409 qWarning("QGLContext::bindTexture(): ETC1 texture compression is not supported."); |
5328 return QSize(); |
5410 return QSize(); |
5329 } |
5411 } |
5330 } else { |
5412 } else { |
5331 if (!(QGLExtensions::glExtensions & |
5413 if (!(QGLExtensions::glExtensions() & |
5332 QGLExtensions::PVRTCTextureCompression)) { |
5414 QGLExtensions::PVRTCTextureCompression)) { |
5333 qWarning("QGLContext::bindTexture(): PVRTC texture compression is not supported."); |
5415 qWarning("QGLContext::bindTexture(): PVRTC texture compression is not supported."); |
5334 return QSize(); |
5416 return QSize(); |
5335 } |
5417 } |
5336 } |
5418 } |