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 ** |
122 setPlane(1); |
122 setPlane(1); |
123 } |
123 } |
124 }; |
124 }; |
125 Q_GLOBAL_STATIC(QGLDefaultOverlayFormat, defaultOverlayFormatInstance) |
125 Q_GLOBAL_STATIC(QGLDefaultOverlayFormat, defaultOverlayFormatInstance) |
126 |
126 |
127 QGLExtensions::Extensions QGLExtensions::glExtensions = 0; |
|
128 bool QGLExtensions::nvidiaFboNeedsFinish = false; |
|
129 |
|
130 Q_GLOBAL_STATIC(QGLSignalProxy, theSignalProxy) |
127 Q_GLOBAL_STATIC(QGLSignalProxy, theSignalProxy) |
131 QGLSignalProxy *QGLSignalProxy::instance() |
128 QGLSignalProxy *QGLSignalProxy::instance() |
132 { |
129 { |
133 return theSignalProxy(); |
130 return theSignalProxy(); |
134 } |
131 } |
152 // values from functions in GLSL. Since working around this in |
149 // values from functions in GLSL. Since working around this in |
153 // the GL2 engine would require a big, ugly rewrite, we're |
150 // the GL2 engine would require a big, ugly rewrite, we're |
154 // falling back to the GL 1 engine.. |
151 // falling back to the GL 1 engine.. |
155 static bool mac_x1600_check_done = false; |
152 static bool mac_x1600_check_done = false; |
156 if (!mac_x1600_check_done) { |
153 if (!mac_x1600_check_done) { |
157 QGLWidget *tmp = 0; |
154 QGLTemporaryContext *tmp = 0; |
158 if (!QGLContext::currentContext()) { |
155 if (!QGLContext::currentContext()) |
159 tmp = new QGLWidget(); |
156 tmp = new QGLTemporaryContext(); |
160 tmp->makeCurrent(); |
|
161 } |
|
162 if (strstr((char *) glGetString(GL_RENDERER), "X1600")) |
157 if (strstr((char *) glGetString(GL_RENDERER), "X1600")) |
163 engineType = QPaintEngine::OpenGL; |
158 engineType = QPaintEngine::OpenGL; |
164 if (tmp) |
159 if (tmp) |
165 delete tmp; |
160 delete tmp; |
166 mac_x1600_check_done = true; |
161 mac_x1600_check_done = true; |
176 // Also check for the FragmentShader extension in conjunction with |
171 // Also check for the FragmentShader extension in conjunction with |
177 // the 2.0 version flag, to cover the case where we export the display |
172 // 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 |
173 // from an old GL 1.1 server to a GL 2.x client. In that case we can't |
179 // use GL 2.0. |
174 // use GL 2.0. |
180 if ((QGLFormat::openGLVersionFlags() & QGLFormat::OpenGL_Version_2_0) |
175 if ((QGLFormat::openGLVersionFlags() & QGLFormat::OpenGL_Version_2_0) |
181 && (QGLExtensions::glExtensions & QGLExtensions::FragmentShader) |
176 && (QGLExtensions::glExtensions() & QGLExtensions::FragmentShader) |
182 && qgetenv("QT_GL_USE_OPENGL1ENGINE").isEmpty()) |
177 && qgetenv("QT_GL_USE_OPENGL1ENGINE").isEmpty()) |
183 engineType = QPaintEngine::OpenGL2; |
178 engineType = QPaintEngine::OpenGL2; |
184 else |
179 else |
185 engineType = QPaintEngine::OpenGL; |
180 engineType = QPaintEngine::OpenGL; |
186 #endif |
181 #endif |
1248 QGLFormat::OpenGLVersionFlags QGLFormat::openGLVersionFlags() |
1243 QGLFormat::OpenGLVersionFlags QGLFormat::openGLVersionFlags() |
1249 { |
1244 { |
1250 static bool cachedDefault = false; |
1245 static bool cachedDefault = false; |
1251 static OpenGLVersionFlags defaultVersionFlags = OpenGL_Version_None; |
1246 static OpenGLVersionFlags defaultVersionFlags = OpenGL_Version_None; |
1252 QGLContext *currentCtx = const_cast<QGLContext *>(QGLContext::currentContext()); |
1247 QGLContext *currentCtx = const_cast<QGLContext *>(QGLContext::currentContext()); |
1253 QGLWidget *dummy = 0; |
1248 QGLTemporaryContext *tmpContext = 0; |
1254 |
1249 |
1255 if (currentCtx && currentCtx->d_func()->version_flags_cached) |
1250 if (currentCtx && currentCtx->d_func()->version_flags_cached) |
1256 return currentCtx->d_func()->version_flags; |
1251 return currentCtx->d_func()->version_flags; |
1257 |
1252 |
1258 if (!currentCtx) { |
1253 if (!currentCtx) { |
1259 if (cachedDefault) { |
1254 if (cachedDefault) { |
1260 return defaultVersionFlags; |
1255 return defaultVersionFlags; |
1261 } else { |
1256 } else { |
1262 if (!hasOpenGL()) |
1257 if (!hasOpenGL()) |
1263 return defaultVersionFlags; |
1258 return defaultVersionFlags; |
1264 dummy = new QGLWidget; |
1259 tmpContext = new QGLTemporaryContext; |
1265 dummy->makeCurrent(); // glGetString() needs a current context |
|
1266 cachedDefault = true; |
1260 cachedDefault = true; |
1267 } |
1261 } |
1268 } |
1262 } |
1269 |
1263 |
1270 QString versionString(QLatin1String(reinterpret_cast<const char*>(glGetString(GL_VERSION)))); |
1264 QString versionString(QLatin1String(reinterpret_cast<const char*>(glGetString(GL_VERSION)))); |
1271 OpenGLVersionFlags versionFlags = qOpenGLVersionFlagsFromString(versionString); |
1265 OpenGLVersionFlags versionFlags = qOpenGLVersionFlagsFromString(versionString); |
1272 if (currentCtx) { |
1266 if (currentCtx) { |
1273 currentCtx->d_func()->version_flags_cached = true; |
1267 currentCtx->d_func()->version_flags_cached = true; |
1274 currentCtx->d_func()->version_flags = versionFlags; |
1268 currentCtx->d_func()->version_flags = versionFlags; |
1275 } |
1269 } |
1276 if (dummy) { |
1270 if (tmpContext) { |
1277 defaultVersionFlags = versionFlags; |
1271 defaultVersionFlags = versionFlags; |
1278 delete dummy; |
1272 delete tmpContext; |
1279 } |
1273 } |
1280 |
1274 |
1281 return versionFlags; |
1275 return versionFlags; |
1282 } |
1276 } |
1283 |
1277 |
1434 guard->m_prev->m_next = guard->m_next; |
1428 guard->m_prev->m_next = guard->m_next; |
1435 else |
1429 else |
1436 m_guards = guard->m_next; |
1430 m_guards = guard->m_next; |
1437 } |
1431 } |
1438 |
1432 |
|
1433 const QGLContext *qt_gl_transfer_context(const QGLContext *ctx) |
|
1434 { |
|
1435 if (!ctx) |
|
1436 return 0; |
|
1437 QList<const QGLContext *> shares |
|
1438 (QGLContextPrivate::contextGroup(ctx)->shares()); |
|
1439 if (shares.size() >= 2) |
|
1440 return (ctx == shares.at(0)) ? shares.at(1) : shares.at(0); |
|
1441 else |
|
1442 return 0; |
|
1443 } |
|
1444 |
1439 QGLContextPrivate::~QGLContextPrivate() |
1445 QGLContextPrivate::~QGLContextPrivate() |
1440 { |
1446 { |
1441 if (!group->m_refs.deref()) { |
1447 if (!group->m_refs.deref()) { |
1442 Q_ASSERT(group->context() == q_ptr); |
1448 Q_ASSERT(group->context() == q_ptr); |
1443 delete group; |
1449 delete group; |
1479 initDone = false; |
1485 initDone = false; |
1480 sharing = false; |
1486 sharing = false; |
1481 max_texture_size = -1; |
1487 max_texture_size = -1; |
1482 version_flags_cached = false; |
1488 version_flags_cached = false; |
1483 version_flags = QGLFormat::OpenGL_Version_None; |
1489 version_flags = QGLFormat::OpenGL_Version_None; |
|
1490 extension_flags_cached = false; |
|
1491 extension_flags = 0; |
1484 current_fbo = 0; |
1492 current_fbo = 0; |
1485 default_fbo = 0; |
1493 default_fbo = 0; |
1486 active_engine = 0; |
1494 active_engine = 0; |
|
1495 for (int i = 0; i < QT_GL_VERTEX_ARRAY_TRACKED_COUNT; ++i) |
|
1496 vertexAttributeArraysEnabledState[i] = false; |
1487 } |
1497 } |
1488 |
1498 |
1489 QGLContext* QGLContext::currentCtx = 0; |
1499 QGLContext* QGLContext::currentCtx = 0; |
1490 |
1500 |
1491 /* |
1501 /* |
1539 return img; |
1549 return img; |
1540 } |
1550 } |
1541 |
1551 |
1542 QImage qt_gl_read_texture(const QSize &size, bool alpha_format, bool include_alpha) |
1552 QImage qt_gl_read_texture(const QSize &size, bool alpha_format, bool include_alpha) |
1543 { |
1553 { |
1544 QImage img(size, alpha_format ? QImage::Format_ARGB32 : QImage::Format_RGB32); |
1554 QImage img(size, alpha_format ? QImage::Format_ARGB32_Premultiplied : QImage::Format_RGB32); |
1545 int w = size.width(); |
1555 int w = size.width(); |
1546 int h = size.height(); |
1556 int h = size.height(); |
1547 #if !defined(QT_OPENGL_ES_2) && !defined(QT_OPENGL_ES_1) && !defined(QT_OPENGL_ES_1_CL) |
1557 #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! |
1558 //### 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()); |
1559 glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE, img.bits()); |
1727 #ifndef GL_GENERATE_MIPMAP_SGIS |
1737 #ifndef GL_GENERATE_MIPMAP_SGIS |
1728 #define GL_GENERATE_MIPMAP_SGIS 0x8191 |
1738 #define GL_GENERATE_MIPMAP_SGIS 0x8191 |
1729 #define GL_GENERATE_MIPMAP_HINT_SGIS 0x8192 |
1739 #define GL_GENERATE_MIPMAP_HINT_SGIS 0x8192 |
1730 #endif |
1740 #endif |
1731 |
1741 |
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 /*! |
1742 /*! |
1739 \class QGLContext |
1743 \class QGLContext |
1740 \brief The QGLContext class encapsulates an OpenGL rendering context. |
1744 \brief The QGLContext class encapsulates an OpenGL rendering context. |
1741 |
1745 |
1742 \ingroup painting-3D |
1746 \ingroup painting-3D |
1871 } |
1875 } |
1872 |
1876 |
1873 void QGLContextPrivate::cleanup() |
1877 void QGLContextPrivate::cleanup() |
1874 { |
1878 { |
1875 } |
1879 } |
|
1880 |
|
1881 #define ctx q_ptr |
|
1882 void QGLContextPrivate::setVertexAttribArrayEnabled(int arrayIndex, bool enabled) |
|
1883 { |
|
1884 Q_ASSERT(arrayIndex < QT_GL_VERTEX_ARRAY_TRACKED_COUNT); |
|
1885 Q_ASSERT(glEnableVertexAttribArray); |
|
1886 |
|
1887 if (vertexAttributeArraysEnabledState[arrayIndex] && !enabled) |
|
1888 glDisableVertexAttribArray(arrayIndex); |
|
1889 |
|
1890 if (!vertexAttributeArraysEnabledState[arrayIndex] && enabled) |
|
1891 glEnableVertexAttribArray(arrayIndex); |
|
1892 |
|
1893 vertexAttributeArraysEnabledState[arrayIndex] = enabled; |
|
1894 } |
|
1895 |
|
1896 void QGLContextPrivate::syncGlState() |
|
1897 { |
|
1898 Q_ASSERT(glEnableVertexAttribArray); |
|
1899 for (int i = 0; i < QT_GL_VERTEX_ARRAY_TRACKED_COUNT; ++i) { |
|
1900 if (vertexAttributeArraysEnabledState[i]) |
|
1901 glEnableVertexAttribArray(i); |
|
1902 else |
|
1903 glDisableVertexAttribArray(i); |
|
1904 } |
|
1905 |
|
1906 } |
|
1907 #undef ctx |
|
1908 |
1876 |
1909 |
1877 /*! |
1910 /*! |
1878 \overload |
1911 \overload |
1879 |
1912 |
1880 Reads the compressed texture file \a fileName and generates a 2D GL |
1913 Reads the compressed texture file \a fileName and generates a 2D GL |
2108 // 2.0 or use the GL_TEXTURE_RECTANGLE texture target |
2141 // 2.0 or use the GL_TEXTURE_RECTANGLE texture target |
2109 int tx_w = qt_next_power_of_two(image.width()); |
2142 int tx_w = qt_next_power_of_two(image.width()); |
2110 int tx_h = qt_next_power_of_two(image.height()); |
2143 int tx_h = qt_next_power_of_two(image.height()); |
2111 |
2144 |
2112 QImage img = image; |
2145 QImage img = image; |
2113 if (!(QGLExtensions::glExtensions & QGLExtensions::NPOTTextures) |
2146 if (!(QGLExtensions::glExtensions() & QGLExtensions::NPOTTextures) |
2114 && !(QGLFormat::openGLVersionFlags() & QGLFormat::OpenGL_ES_Version_2_0) |
2147 && !(QGLFormat::openGLVersionFlags() & QGLFormat::OpenGL_ES_Version_2_0) |
2115 && (target == GL_TEXTURE_2D && (tx_w != image.width() || tx_h != image.height()))) |
2148 && (target == GL_TEXTURE_2D && (tx_w != image.width() || tx_h != image.height()))) |
2116 { |
2149 { |
2117 img = img.scaled(tx_w, tx_h); |
2150 img = img.scaled(tx_w, tx_h); |
2118 #ifdef QGL_BIND_TEXTURE_DEBUG |
2151 #ifdef QGL_BIND_TEXTURE_DEBUG |
2130 |
2163 |
2131 #if defined(QT_OPENGL_ES_2) |
2164 #if defined(QT_OPENGL_ES_2) |
2132 bool genMipmap = false; |
2165 bool genMipmap = false; |
2133 #endif |
2166 #endif |
2134 if (glFormat.directRendering() |
2167 if (glFormat.directRendering() |
2135 && (QGLExtensions::glExtensions & QGLExtensions::GenerateMipmap) |
2168 && (QGLExtensions::glExtensions() & QGLExtensions::GenerateMipmap) |
2136 && target == GL_TEXTURE_2D |
2169 && target == GL_TEXTURE_2D |
2137 && (options & QGLContext::MipmapBindOption)) |
2170 && (options & QGLContext::MipmapBindOption)) |
2138 { |
2171 { |
2139 #ifdef QGL_BIND_TEXTURE_DEBUG |
2172 #ifdef QGL_BIND_TEXTURE_DEBUG |
2140 printf(" - generating mipmaps (%d ms)\n", time.elapsed()); |
2173 printf(" - generating mipmaps (%d ms)\n", time.elapsed()); |
2158 |
2191 |
2159 QImage::Format target_format = img.format(); |
2192 QImage::Format target_format = img.format(); |
2160 bool premul = options & QGLContext::PremultipliedAlphaBindOption; |
2193 bool premul = options & QGLContext::PremultipliedAlphaBindOption; |
2161 GLenum externalFormat; |
2194 GLenum externalFormat; |
2162 GLuint pixel_type; |
2195 GLuint pixel_type; |
2163 if (QGLExtensions::glExtensions & QGLExtensions::BGRATextureFormat) { |
2196 if (QGLExtensions::glExtensions() & QGLExtensions::BGRATextureFormat) { |
2164 externalFormat = GL_BGRA; |
2197 externalFormat = GL_BGRA; |
2165 pixel_type = GL_UNSIGNED_INT_8_8_8_8_REV; |
2198 if (QGLFormat::openGLVersionFlags() & QGLFormat::OpenGL_Version_1_2) |
|
2199 pixel_type = GL_UNSIGNED_INT_8_8_8_8_REV; |
|
2200 else |
|
2201 pixel_type = GL_UNSIGNED_BYTE; |
2166 } else { |
2202 } else { |
2167 externalFormat = GL_RGBA; |
2203 externalFormat = GL_RGBA; |
2168 pixel_type = GL_UNSIGNED_BYTE; |
2204 pixel_type = GL_UNSIGNED_BYTE; |
2169 } |
2205 } |
2170 |
2206 |
2239 // the format to GL_RGB |
2275 // the format to GL_RGB |
2240 Q_ASSERT(img.depth() == 32); |
2276 Q_ASSERT(img.depth() == 32); |
2241 qgl_byteSwapImage(img, pixel_type); |
2277 qgl_byteSwapImage(img, pixel_type); |
2242 } |
2278 } |
2243 #ifdef QT_OPENGL_ES |
2279 #ifdef QT_OPENGL_ES |
2244 // OpenGL/ES requires that the internal and external formats be identical. |
2280 // OpenGL/ES requires that the internal and external formats be |
2245 // This is typically used to convert GL_RGBA into GL_BGRA. |
2281 // identical. |
2246 // Also, we need to use GL_UNSIGNED_BYTE when the format is GL_BGRA. |
|
2247 internalFormat = externalFormat; |
2282 internalFormat = externalFormat; |
2248 if (pixel_type == GL_UNSIGNED_INT_8_8_8_8_REV) |
|
2249 pixel_type = GL_UNSIGNED_BYTE; |
|
2250 #endif |
2283 #endif |
2251 #ifdef QGL_BIND_TEXTURE_DEBUG |
2284 #ifdef QGL_BIND_TEXTURE_DEBUG |
2252 printf(" - uploading, image.format=%d, externalFormat=0x%x, internalFormat=0x%x, pixel_type=0x%x\n", |
2285 printf(" - uploading, image.format=%d, externalFormat=0x%x, internalFormat=0x%x, pixel_type=0x%x\n", |
2253 img.format(), externalFormat, internalFormat, pixel_type); |
2286 img.format(), externalFormat, internalFormat, pixel_type); |
2254 #endif |
2287 #endif |
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 { |
4376 glGetIntegerv(GL_VIEWPORT, &view[0]); |
4409 glGetIntegerv(GL_VIEWPORT, &view[0]); |
4377 int width = d->glcx->device()->width(); |
4410 int width = d->glcx->device()->width(); |
4378 int height = d->glcx->device()->height(); |
4411 int height = d->glcx->device()->height(); |
4379 bool auto_swap = autoBufferSwap(); |
4412 bool auto_swap = autoBufferSwap(); |
4380 |
4413 |
|
4414 QPaintEngine::Type oldEngineType = qgl_engine_selector()->preferredPaintEngine(); |
|
4415 qgl_engine_selector()->setPreferredPaintEngine(QPaintEngine::OpenGL); |
4381 QPaintEngine *engine = paintEngine(); |
4416 QPaintEngine *engine = paintEngine(); |
4382 if (engine->type() == QPaintEngine::OpenGL2) |
|
4383 static_cast<QGL2PaintEngineEx *>(engine)->setRenderTextActive(true); |
|
4384 QPainter *p; |
4417 QPainter *p; |
4385 bool reuse_painter = false; |
4418 bool reuse_painter = false; |
4386 if (engine->isActive()) { |
4419 if (engine->isActive()) { |
4387 reuse_painter = true; |
4420 reuse_painter = true; |
4388 p = engine->painter(); |
4421 p = engine->painter(); |
4398 glLoadIdentity(); |
4431 glLoadIdentity(); |
4399 } else { |
4432 } else { |
4400 setAutoBufferSwap(false); |
4433 setAutoBufferSwap(false); |
4401 // disable glClear() as a result of QPainter::begin() |
4434 // disable glClear() as a result of QPainter::begin() |
4402 d->disable_clear_on_painter_begin = true; |
4435 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); |
4436 p = new QPainter(this); |
4409 } |
4437 } |
4410 |
4438 |
4411 QRect viewport(view[0], view[1], view[2], view[3]); |
4439 QRect viewport(view[0], view[1], view[2], view[3]); |
4412 if (!use_scissor_testing && viewport != rect()) { |
4440 if (!use_scissor_testing && viewport != rect()) { |
4426 } else { |
4454 } else { |
4427 p->end(); |
4455 p->end(); |
4428 delete p; |
4456 delete p; |
4429 setAutoBufferSwap(auto_swap); |
4457 setAutoBufferSwap(auto_swap); |
4430 d->disable_clear_on_painter_begin = false; |
4458 d->disable_clear_on_painter_begin = false; |
4431 if (engine->type() == QPaintEngine::OpenGL2) |
4459 } |
4432 qt_restore_gl_state(); |
4460 qgl_engine_selector()->setPreferredPaintEngine(oldEngineType); |
4433 } |
|
4434 if (engine->type() == QPaintEngine::OpenGL2) |
|
4435 static_cast<QGL2PaintEngineEx *>(engine)->setRenderTextActive(false); |
|
4436 #else // QT_OPENGL_ES |
4461 #else // QT_OPENGL_ES |
4437 Q_UNUSED(x); |
4462 Q_UNUSED(x); |
4438 Q_UNUSED(y); |
4463 Q_UNUSED(y); |
4439 Q_UNUSED(str); |
4464 Q_UNUSED(str); |
4440 Q_UNUSED(font); |
4465 Q_UNUSED(font); |
4478 GLdouble win_x = 0, win_y = 0, win_z = 0; |
4503 GLdouble win_x = 0, win_y = 0, win_z = 0; |
4479 qgluProject(x, y, z, &model[0][0], &proj[0][0], &view[0], |
4504 qgluProject(x, y, z, &model[0][0], &proj[0][0], &view[0], |
4480 &win_x, &win_y, &win_z); |
4505 &win_x, &win_y, &win_z); |
4481 win_y = height - win_y; // y is inverted |
4506 win_y = height - win_y; // y is inverted |
4482 |
4507 |
|
4508 QPaintEngine::Type oldEngineType = qgl_engine_selector()->preferredPaintEngine(); |
|
4509 qgl_engine_selector()->setPreferredPaintEngine(QPaintEngine::OpenGL); |
4483 QPaintEngine *engine = paintEngine(); |
4510 QPaintEngine *engine = paintEngine(); |
4484 if (engine->type() == QPaintEngine::OpenGL2) |
|
4485 static_cast<QGL2PaintEngineEx *>(engine)->setRenderTextActive(true); |
|
4486 QPainter *p; |
4511 QPainter *p; |
4487 bool reuse_painter = false; |
4512 bool reuse_painter = false; |
4488 bool use_depth_testing = glIsEnabled(GL_DEPTH_TEST); |
4513 bool use_depth_testing = glIsEnabled(GL_DEPTH_TEST); |
4489 bool use_scissor_testing = glIsEnabled(GL_SCISSOR_TEST); |
4514 bool use_scissor_testing = glIsEnabled(GL_SCISSOR_TEST); |
4490 |
4515 |
4494 qt_save_gl_state(); |
4519 qt_save_gl_state(); |
4495 } else { |
4520 } else { |
4496 setAutoBufferSwap(false); |
4521 setAutoBufferSwap(false); |
4497 // disable glClear() as a result of QPainter::begin() |
4522 // disable glClear() as a result of QPainter::begin() |
4498 d->disable_clear_on_painter_begin = true; |
4523 d->disable_clear_on_painter_begin = true; |
4499 if (engine->type() == QPaintEngine::OpenGL2) |
|
4500 qt_save_gl_state(); |
|
4501 p = new QPainter(this); |
4524 p = new QPainter(this); |
4502 } |
4525 } |
4503 |
4526 |
4504 QRect viewport(view[0], view[1], view[2], view[3]); |
4527 QRect viewport(view[0], view[1], view[2], view[3]); |
4505 if (!use_scissor_testing && viewport != rect()) { |
4528 if (!use_scissor_testing && viewport != rect()) { |
4524 if (reuse_painter) { |
4547 if (reuse_painter) { |
4525 qt_restore_gl_state(); |
4548 qt_restore_gl_state(); |
4526 } else { |
4549 } else { |
4527 p->end(); |
4550 p->end(); |
4528 delete p; |
4551 delete p; |
4529 if (engine->type() == QPaintEngine::OpenGL2) |
|
4530 qt_restore_gl_state(); |
|
4531 setAutoBufferSwap(auto_swap); |
4552 setAutoBufferSwap(auto_swap); |
4532 d->disable_clear_on_painter_begin = false; |
4553 d->disable_clear_on_painter_begin = false; |
4533 } |
4554 } |
4534 if (engine->type() == QPaintEngine::OpenGL2) |
4555 qgl_engine_selector()->setPreferredPaintEngine(oldEngineType); |
4535 static_cast<QGL2PaintEngineEx *>(engine)->setRenderTextActive(false); |
|
4536 #else // QT_OPENGL_ES |
4556 #else // QT_OPENGL_ES |
4537 Q_UNUSED(x); |
4557 Q_UNUSED(x); |
4538 Q_UNUSED(y); |
4558 Q_UNUSED(y); |
4539 Q_UNUSED(z); |
4559 Q_UNUSED(z); |
4540 Q_UNUSED(str); |
4560 Q_UNUSED(str); |
4842 d->init(context, shareWidget); |
4862 d->init(context, shareWidget); |
4843 } |
4863 } |
4844 |
4864 |
4845 #endif // QT3_SUPPORT |
4865 #endif // QT3_SUPPORT |
4846 |
4866 |
4847 void QGLExtensions::init_extensions() |
4867 /* |
|
4868 Returns the GL extensions for the current context. |
|
4869 */ |
|
4870 QGLExtensions::Extensions QGLExtensions::currentContextExtensions() |
4848 { |
4871 { |
4849 QGLExtensionMatcher extensions(reinterpret_cast<const char *>(glGetString(GL_EXTENSIONS))); |
4872 QGLExtensionMatcher extensions(reinterpret_cast<const char *>(glGetString(GL_EXTENSIONS))); |
|
4873 Extensions glExtensions; |
4850 |
4874 |
4851 if (extensions.match("GL_ARB_texture_rectangle")) |
4875 if (extensions.match("GL_ARB_texture_rectangle")) |
4852 glExtensions |= TextureRectangle; |
4876 glExtensions |= TextureRectangle; |
4853 if (extensions.match("GL_ARB_multisample")) |
4877 if (extensions.match("GL_ARB_multisample")) |
4854 glExtensions |= SampleBuffers; |
4878 glExtensions |= SampleBuffers; |
4905 if (extensions.match("GL_ARB_texture_non_power_of_two")) |
4929 if (extensions.match("GL_ARB_texture_non_power_of_two")) |
4906 glExtensions |= NPOTTextures; |
4930 glExtensions |= NPOTTextures; |
4907 |
4931 |
4908 if (extensions.match("GL_EXT_bgra")) |
4932 if (extensions.match("GL_EXT_bgra")) |
4909 glExtensions |= BGRATextureFormat; |
4933 glExtensions |= BGRATextureFormat; |
|
4934 |
|
4935 return glExtensions; |
|
4936 } |
|
4937 |
|
4938 /* |
|
4939 Returns the GL extensions for the current QGLContext. If there is no |
|
4940 current QGLContext, a default context will be created and the extensions |
|
4941 for that context will be returned instead. |
|
4942 */ |
|
4943 QGLExtensions::Extensions QGLExtensions::glExtensions() |
|
4944 { |
|
4945 QGLTemporaryContext *tmpContext = 0; |
|
4946 static bool cachedDefault = false; |
|
4947 static Extensions defaultExtensions = 0; |
|
4948 QGLContext *currentCtx = const_cast<QGLContext *>(QGLContext::currentContext()); |
|
4949 |
|
4950 if (currentCtx && currentCtx->d_func()->extension_flags_cached) |
|
4951 return currentCtx->d_func()->extension_flags; |
|
4952 |
|
4953 if (!currentCtx) { |
|
4954 if (cachedDefault) { |
|
4955 return defaultExtensions; |
|
4956 } else { |
|
4957 tmpContext = new QGLTemporaryContext; |
|
4958 cachedDefault = true; |
|
4959 } |
|
4960 } |
|
4961 |
|
4962 Extensions extensionFlags = currentContextExtensions(); |
|
4963 if (currentCtx) { |
|
4964 currentCtx->d_func()->extension_flags_cached = true; |
|
4965 currentCtx->d_func()->extension_flags = extensionFlags; |
|
4966 } else { |
|
4967 defaultExtensions = extensionFlags; |
|
4968 } |
|
4969 |
|
4970 if (tmpContext) |
|
4971 delete tmpContext; |
|
4972 |
|
4973 return extensionFlags; |
4910 } |
4974 } |
4911 |
4975 |
4912 /* |
4976 /* |
4913 This is the shared initialization for all platforms. Called from QGLWidgetPrivate::init() |
4977 This is the shared initialization for all platforms. Called from QGLWidgetPrivate::init() |
4914 */ |
4978 */ |
4916 { |
4980 { |
4917 Q_Q(QGLWidget); |
4981 Q_Q(QGLWidget); |
4918 |
4982 |
4919 glDevice.setWidget(q); |
4983 glDevice.setWidget(q); |
4920 |
4984 |
4921 QGLExtensions::init(); |
|
4922 glcx = 0; |
4985 glcx = 0; |
4923 autoSwap = true; |
4986 autoSwap = true; |
4924 |
4987 |
4925 if (context && !context->device()) |
4988 if (context && !context->device()) |
4926 context->setDevice(q); |
4989 context->setDevice(q); |
4927 q->setContext(context, shareWidget ? shareWidget->context() : 0); |
4990 q->setContext(context, shareWidget ? shareWidget->context() : 0); |
4928 |
4991 |
4929 if (!glcx) |
4992 if (!glcx) |
4930 glcx = new QGLContext(QGLFormat::defaultFormat(), q); |
4993 glcx = new QGLContext(QGLFormat::defaultFormat(), q); |
4931 |
|
4932 q->setAttribute(Qt::WA_NoSystemBackground); |
|
4933 } |
4994 } |
4934 |
4995 |
4935 #if defined(Q_WS_X11) || defined(Q_WS_MAC) || defined(Q_WS_QWS) |
4996 #if defined(Q_WS_X11) || defined(Q_WS_MAC) || defined(Q_WS_QWS) |
4936 Q_GLOBAL_STATIC(QString, qt_gl_lib_name) |
4997 Q_GLOBAL_STATIC(QString, qt_gl_lib_name) |
4937 |
4998 |
4951 } |
5012 } |
4952 return *qt_gl_lib_name(); |
5013 return *qt_gl_lib_name(); |
4953 } |
5014 } |
4954 #endif |
5015 #endif |
4955 |
5016 |
4956 void QGLShareRegister::addShare(const QGLContext *context, const QGLContext *share) { |
5017 void QGLContextGroup::addShare(const QGLContext *context, const QGLContext *share) { |
4957 Q_ASSERT(context && share); |
5018 Q_ASSERT(context && share); |
4958 if (context->d_ptr->group == share->d_ptr->group) |
5019 if (context->d_ptr->group == share->d_ptr->group) |
4959 return; |
5020 return; |
4960 |
5021 |
4961 // Make sure 'context' is not already shared with another group of contexts. |
5022 // Make sure 'context' is not already shared with another group of contexts. |
4972 if (group->m_shares.isEmpty()) |
5033 if (group->m_shares.isEmpty()) |
4973 group->m_shares.append(share); |
5034 group->m_shares.append(share); |
4974 group->m_shares.append(context); |
5035 group->m_shares.append(context); |
4975 } |
5036 } |
4976 |
5037 |
4977 QList<const QGLContext *> QGLShareRegister::shares(const QGLContext *context) { |
5038 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. |
5039 // Remove the context from the group. |
4983 QGLContextGroup *group = context->d_ptr->group; |
5040 QGLContextGroup *group = context->d_ptr->group; |
4984 if (group->m_shares.isEmpty()) |
5041 if (group->m_shares.isEmpty()) |
4985 return; |
5042 return; |
4986 group->m_shares.removeAll(context); |
5043 group->m_shares.removeAll(context); |
5171 // systems such as x86 and ARM at the moment. |
5228 // systems such as x86 and ARM at the moment. |
5172 return QSize(); |
5229 return QSize(); |
5173 } |
5230 } |
5174 #if !defined(QT_OPENGL_ES) |
5231 #if !defined(QT_OPENGL_ES) |
5175 if (!glCompressedTexImage2D) { |
5232 if (!glCompressedTexImage2D) { |
5176 if (!(QGLExtensions::glExtensions & QGLExtensions::TextureCompression)) { |
5233 if (!(QGLExtensions::glExtensions() & QGLExtensions::TextureCompression)) { |
5177 qWarning("QGLContext::bindTexture(): The GL implementation does " |
5234 qWarning("QGLContext::bindTexture(): The GL implementation does " |
5178 "not support texture compression extensions."); |
5235 "not support texture compression extensions."); |
5179 return QSize(); |
5236 return QSize(); |
5180 } |
5237 } |
5181 glCompressedTexImage2D = (_glCompressedTexImage2DARB) ctx->getProcAddress(QLatin1String("glCompressedTexImage2DARB")); |
5238 glCompressedTexImage2D = (_glCompressedTexImage2DARB) ctx->getProcAddress(QLatin1String("glCompressedTexImage2DARB")); |
5210 // We only support 2D texture loading at present. |
5267 // We only support 2D texture loading at present. |
5211 if (target != GL_TEXTURE_2D) |
5268 if (target != GL_TEXTURE_2D) |
5212 return QSize(); |
5269 return QSize(); |
5213 |
5270 |
5214 // Bail out if the necessary extension is not present. |
5271 // Bail out if the necessary extension is not present. |
5215 if (!(QGLExtensions::glExtensions & QGLExtensions::DDSTextureCompression)) { |
5272 if (!(QGLExtensions::glExtensions() & QGLExtensions::DDSTextureCompression)) { |
5216 qWarning("QGLContext::bindTexture(): DDS texture compression is not supported."); |
5273 qWarning("QGLContext::bindTexture(): DDS texture compression is not supported."); |
5217 return QSize(); |
5274 return QSize(); |
5218 } |
5275 } |
5219 |
5276 |
5220 const DDSFormat *ddsHeader = reinterpret_cast<const DDSFormat *>(buf + 4); |
5277 const DDSFormat *ddsHeader = reinterpret_cast<const DDSFormat *>(buf + 4); |
5320 return QSize(); |
5377 return QSize(); |
5321 } |
5378 } |
5322 |
5379 |
5323 // Bail out if the necessary extension is not present. |
5380 // Bail out if the necessary extension is not present. |
5324 if (textureFormat == GL_ETC1_RGB8_OES) { |
5381 if (textureFormat == GL_ETC1_RGB8_OES) { |
5325 if (!(QGLExtensions::glExtensions & |
5382 if (!(QGLExtensions::glExtensions() & |
5326 QGLExtensions::ETC1TextureCompression)) { |
5383 QGLExtensions::ETC1TextureCompression)) { |
5327 qWarning("QGLContext::bindTexture(): ETC1 texture compression is not supported."); |
5384 qWarning("QGLContext::bindTexture(): ETC1 texture compression is not supported."); |
5328 return QSize(); |
5385 return QSize(); |
5329 } |
5386 } |
5330 } else { |
5387 } else { |
5331 if (!(QGLExtensions::glExtensions & |
5388 if (!(QGLExtensions::glExtensions() & |
5332 QGLExtensions::PVRTCTextureCompression)) { |
5389 QGLExtensions::PVRTCTextureCompression)) { |
5333 qWarning("QGLContext::bindTexture(): PVRTC texture compression is not supported."); |
5390 qWarning("QGLContext::bindTexture(): PVRTC texture compression is not supported."); |
5334 return QSize(); |
5391 return QSize(); |
5335 } |
5392 } |
5336 } |
5393 } |