diff options
Diffstat (limited to 'src/opengl/qgl.cpp')
-rw-r--r-- | src/opengl/qgl.cpp | 301 |
1 files changed, 61 insertions, 240 deletions
diff --git a/src/opengl/qgl.cpp b/src/opengl/qgl.cpp index 71f1bd2b54..def0470622 100644 --- a/src/opengl/qgl.cpp +++ b/src/opengl/qgl.cpp @@ -59,6 +59,7 @@ #include <qglpixelbuffer.h> #include <qglframebufferobject.h> +#include <private/qopenglextensions_p.h> #include <private/qimage_p.h> #include <qpa/qplatformpixmap.h> @@ -73,7 +74,52 @@ QT_BEGIN_NAMESPACE -QGLExtensionFuncs QGLContextPrivate::qt_extensionFuncs; +class QGLDefaultExtensions +{ +public: + QGLDefaultExtensions() : extensions(0) { + QGLTemporaryContext tempContext; + Q_ASSERT(QOpenGLContext::currentContext()); + QOpenGLExtensions *ext = qgl_extensions(); + Q_ASSERT(ext); + extensions = ext->openGLExtensions(); + features = ext->openGLFeatures(); + } + + QOpenGLFunctions::OpenGLFeatures features; + QOpenGLExtensions::OpenGLExtensions extensions; +}; + +Q_GLOBAL_STATIC(QGLDefaultExtensions, qtDefaultExtensions) + +bool qgl_hasFeature(QOpenGLFunctions::OpenGLFeature feature) +{ + if (QOpenGLContext::currentContext()) + return QOpenGLContext::currentContext()->functions()->hasOpenGLFeature(feature); + return qtDefaultExtensions()->features & feature; +} + +bool qgl_hasExtension(QOpenGLExtensions::OpenGLExtension extension) +{ + if (QOpenGLContext::currentContext()) + return qgl_extensions()->hasOpenGLExtension(extension); + return qtDefaultExtensions()->extensions & extension; +} + +QOpenGLExtensions::OpenGLExtensions extensions; +/* + Returns the GL extensions for the current QOpenGLContext. If there is no + current QOpenGLContext, a default context will be created and the extensions + for that context will be returned instead. +*/ +QOpenGLExtensions* qgl_extensions() +{ + if (QOpenGLContext *context = QOpenGLContext::currentContext()) + return static_cast<QOpenGLExtensions *>(context->functions()); + + Q_ASSERT(false); + return 0; +} struct QGLThreadContext { ~QGLThreadContext() { @@ -1567,8 +1613,6 @@ void QGLContextPrivate::init(QPaintDevice *dev, const QGLFormat &format) max_texture_size = -1; version_flags_cached = false; version_flags = QGLFormat::OpenGL_Version_None; - extension_flags_cached = false; - extension_flags = 0; current_fbo = 0; default_fbo = 0; active_engine = 0; @@ -1956,30 +2000,32 @@ void QGLContextPrivate::cleanup() #define ctx q_ptr void QGLContextPrivate::setVertexAttribArrayEnabled(int arrayIndex, bool enabled) { + Q_Q(QGLContext); Q_ASSERT(arrayIndex < QT_GL_VERTEX_ARRAY_TRACKED_COUNT); #ifdef glEnableVertexAttribArray Q_ASSERT(glEnableVertexAttribArray); #endif if (vertexAttributeArraysEnabledState[arrayIndex] && !enabled) - glDisableVertexAttribArray(arrayIndex); + q->functions()->glDisableVertexAttribArray(arrayIndex); if (!vertexAttributeArraysEnabledState[arrayIndex] && enabled) - glEnableVertexAttribArray(arrayIndex); + q->functions()->glEnableVertexAttribArray(arrayIndex); vertexAttributeArraysEnabledState[arrayIndex] = enabled; } void QGLContextPrivate::syncGlState() { + Q_Q(QGLContext); #ifdef glEnableVertexAttribArray Q_ASSERT(glEnableVertexAttribArray); #endif for (int i = 0; i < QT_GL_VERTEX_ARRAY_TRACKED_COUNT; ++i) { if (vertexAttributeArraysEnabledState[i]) - glEnableVertexAttribArray(i); + q->functions()->glEnableVertexAttribArray(i); else - glDisableVertexAttribArray(i); + q->functions()->glDisableVertexAttribArray(i); } } @@ -2041,11 +2087,6 @@ static inline QRgb qt_gl_convertToGLFormatHelper(QRgb src_pixel, GLenum texture_ } } -QRgb qt_gl_convertToGLFormat(QRgb src_pixel, GLenum texture_format) -{ - return qt_gl_convertToGLFormatHelper(src_pixel, texture_format); -} - static void convertToGLFormatHelper(QImage &dst, const QImage &img, GLenum texture_format) { Q_ASSERT(dst.depth() == 32); @@ -2134,23 +2175,6 @@ static void convertToGLFormatHelper(QImage &dst, const QImage &img, GLenum textu } } -QGLExtensionFuncs& QGLContextPrivate::extensionFuncs(const QGLContext *) -{ - return qt_extensionFuncs; -} - -QImage QGLContextPrivate::convertToGLFormat(const QImage &image, bool force_premul, - GLenum texture_format) -{ - QImage::Format target_format = image.format(); - if (force_premul || image.format() != QImage::Format_ARGB32) - target_format = QImage::Format_ARGB32_Premultiplied; - - QImage result(image.width(), image.height(), target_format); - convertToGLFormatHelper(result, image.convertToFormat(target_format), texture_format); - return result; -} - /*! \internal */ QGLTexture *QGLContextPrivate::bindTexture(const QImage &image, GLenum target, GLint format, QGLContext::BindOptions options) @@ -2238,7 +2262,7 @@ QGLTexture* QGLContextPrivate::bindTexture(const QImage &image, GLenum target, G QImage img = image; - if (!(QGLExtensions::glExtensions() & QGLExtensions::NPOTTextures) + if (!qgl_extensions()->hasOpenGLFeature(QOpenGLFunctions::NPOTTextures) && !(QGLFormat::openGLVersionFlags() & QGLFormat::OpenGL_ES_Version_2_0) && (target == GL_TEXTURE_2D && (tx_w != image.width() || tx_h != image.height()))) { @@ -2260,7 +2284,7 @@ QGLTexture* QGLContextPrivate::bindTexture(const QImage &image, GLenum target, G bool genMipmap = false; #endif if (glFormat.directRendering() - && (QGLExtensions::glExtensions() & QGLExtensions::GenerateMipmap) + && (qgl_extensions()->hasOpenGLExtension(QOpenGLExtensions::GenerateMipmap)) && target == GL_TEXTURE_2D && (options & QGLContext::MipmapBindOption)) { @@ -2284,7 +2308,7 @@ QGLTexture* QGLContextPrivate::bindTexture(const QImage &image, GLenum target, G bool premul = options & QGLContext::PremultipliedAlphaBindOption; GLenum externalFormat; GLuint pixel_type; - if (QGLExtensions::glExtensions() & QGLExtensions::BGRATextureFormat) { + if (qgl_extensions()->hasOpenGLExtension(QOpenGLExtensions::BGRATextureFormat)) { externalFormat = GL_BGRA; if (QGLFormat::openGLVersionFlags() & QGLFormat::OpenGL_Version_1_2) pixel_type = GL_UNSIGNED_INT_8_8_8_8_REV; @@ -4674,192 +4698,6 @@ QPaintEngine *QGLWidget::paintEngine() const return qt_qgl_paint_engine(); } -typedef const GLubyte * (QGLF_APIENTRYP qt_glGetStringi)(GLenum, GLuint); - -#ifndef GL_NUM_EXTENSIONS -#define GL_NUM_EXTENSIONS 0x821D -#endif - -QGLExtensionMatcher::QGLExtensionMatcher(const char *str) -{ - init(str); -} - -QGLExtensionMatcher::QGLExtensionMatcher() -{ - const char *extensionStr = reinterpret_cast<const char *>(glGetString(GL_EXTENSIONS)); - - if (extensionStr) { - init(extensionStr); - } else { - // clear error state - while (glGetError()) {} - - const QGLContext *ctx = QGLContext::currentContext(); - if (ctx) { - qt_glGetStringi glGetStringi = (qt_glGetStringi)ctx->getProcAddress(QLatin1String("glGetStringi")); - - GLint numExtensions; - glGetIntegerv(GL_NUM_EXTENSIONS, &numExtensions); - - for (int i = 0; i < numExtensions; ++i) { - const char *str = reinterpret_cast<const char *>(glGetStringi(GL_EXTENSIONS, i)); - - m_offsets << m_extensions.size(); - - while (*str != 0) - m_extensions.append(*str++); - m_extensions.append(' '); - } - } - } -} - -void QGLExtensionMatcher::init(const char *str) -{ - m_extensions = str; - - // make sure extension string ends with a space - if (!m_extensions.endsWith(' ')) - m_extensions.append(' '); - - int index = 0; - int next = 0; - while ((next = m_extensions.indexOf(' ', index)) >= 0) { - m_offsets << index; - index = next + 1; - } -} - -// ####TODO Properly #ifdef this class to use #define symbols actually defined -// by OpenGL/ES includes -#ifndef GL_FRAMEBUFFER_SRGB_CAPABLE_EXT -#define GL_FRAMEBUFFER_SRGB_CAPABLE_EXT 0x8DBA -#endif - -/* - Returns the GL extensions for the current context. -*/ -QGLExtensions::Extensions QGLExtensions::currentContextExtensions() -{ - QGLExtensionMatcher extensions; - Extensions glExtensions; - - if (extensions.match("GL_ARB_texture_rectangle")) - glExtensions |= TextureRectangle; - if (extensions.match("GL_ARB_multisample")) - glExtensions |= SampleBuffers; - if (extensions.match("GL_SGIS_generate_mipmap")) - glExtensions |= GenerateMipmap; - if (extensions.match("GL_ARB_texture_compression")) - glExtensions |= TextureCompression; - if (extensions.match("GL_EXT_texture_compression_s3tc")) - glExtensions |= DDSTextureCompression; - if (extensions.match("GL_OES_compressed_ETC1_RGB8_texture")) - glExtensions |= ETC1TextureCompression; - if (extensions.match("GL_IMG_texture_compression_pvrtc")) - glExtensions |= PVRTCTextureCompression; - if (extensions.match("GL_ARB_fragment_program")) - glExtensions |= FragmentProgram; - if (extensions.match("GL_ARB_fragment_shader")) - glExtensions |= FragmentShader; - if (extensions.match("GL_ARB_shader_objects")) - glExtensions |= FragmentShader; - if (extensions.match("GL_ARB_texture_mirrored_repeat")) - glExtensions |= MirroredRepeat; - if (extensions.match("GL_EXT_framebuffer_object")) - glExtensions |= FramebufferObject; - if (extensions.match("GL_EXT_stencil_two_side")) - glExtensions |= StencilTwoSide; - if (extensions.match("GL_EXT_stencil_wrap")) - glExtensions |= StencilWrap; - if (extensions.match("GL_EXT_packed_depth_stencil")) - glExtensions |= PackedDepthStencil; - if (extensions.match("GL_NV_float_buffer")) - glExtensions |= NVFloatBuffer; - if (extensions.match("GL_ARB_pixel_buffer_object")) - glExtensions |= PixelBufferObject; - if (extensions.match("GL_IMG_texture_format_BGRA8888")) - glExtensions |= BGRATextureFormat; -#if defined(QT_OPENGL_ES_2) - glExtensions |= FramebufferObject; - glExtensions |= GenerateMipmap; - glExtensions |= FragmentShader; -#endif -#if defined(QT_OPENGL_ES) - if (extensions.match("GL_OES_packed_depth_stencil")) - glExtensions |= PackedDepthStencil; - if (extensions.match("GL_OES_element_index_uint")) - glExtensions |= ElementIndexUint; - if (extensions.match("GL_OES_depth24")) - glExtensions |= Depth24; -#else - glExtensions |= ElementIndexUint; -#endif - if (extensions.match("GL_ARB_framebuffer_object")) { - // ARB_framebuffer_object also includes EXT_framebuffer_blit. - glExtensions |= FramebufferObject; - glExtensions |= FramebufferBlit; - } - - if (extensions.match("GL_EXT_framebuffer_blit")) - glExtensions |= FramebufferBlit; - - if (extensions.match("GL_ARB_texture_non_power_of_two")) - glExtensions |= NPOTTextures; - - if (extensions.match("GL_EXT_bgra")) - glExtensions |= BGRATextureFormat; - -#if !defined(QT_OPENGL_ES) - { - GLboolean srgbCapableFramebuffers = false; - glGetBooleanv(GL_FRAMEBUFFER_SRGB_CAPABLE_EXT, &srgbCapableFramebuffers); - if (srgbCapableFramebuffers) - glExtensions |= SRGBFrameBuffer; - } -#endif - - return glExtensions; -} - - -class QGLDefaultExtensions -{ -public: - QGLDefaultExtensions() { - QGLTemporaryContext tempContext; - extensions = QGLExtensions::currentContextExtensions(); - } - - QGLExtensions::Extensions extensions; -}; - -Q_GLOBAL_STATIC(QGLDefaultExtensions, qtDefaultExtensions) - -/* - Returns the GL extensions for the current QGLContext. If there is no - current QGLContext, a default context will be created and the extensions - for that context will be returned instead. -*/ -QGLExtensions::Extensions QGLExtensions::glExtensions() -{ - Extensions extensionFlags = 0; - QGLContext *currentCtx = const_cast<QGLContext *>(QGLContext::currentContext()); - - if (currentCtx && currentCtx->d_func()->extension_flags_cached) - return currentCtx->d_func()->extension_flags; - - if (!currentCtx) { - extensionFlags = qtDefaultExtensions()->extensions; - } else { - extensionFlags = currentContextExtensions(); - currentCtx->d_func()->extension_flags_cached = true; - currentCtx->d_func()->extension_flags = extensionFlags; - } - return extensionFlags; -} - /* This is the shared initialization for all platforms. Called from QGLWidgetPrivate::init() */ @@ -5046,21 +4884,6 @@ QSize QGLTexture::bindCompressedTexture // systems such as x86 and ARM at the moment. return QSize(); } -#if !defined(QT_OPENGL_ES) - if (!glCompressedTexImage2D) { - if (!(QGLExtensions::glExtensions() & QGLExtensions::TextureCompression)) { - qWarning("QGLContext::bindTexture(): The GL implementation does " - "not support texture compression extensions."); - return QSize(); - } - glCompressedTexImage2D = (_glCompressedTexImage2DARB) ctx->getProcAddress(QLatin1String("glCompressedTexImage2DARB")); - if (!glCompressedTexImage2D) { - qWarning("QGLContext::bindTexture(): could not resolve " - "glCompressedTexImage2DARB."); - return QSize(); - } - } -#endif if (!format) { // Auto-detect the format from the header. if (len >= 4 && !qstrncmp(buf, "DDS ", 4)) @@ -5087,7 +4910,7 @@ QSize QGLTexture::bindCompressedTextureDDS(const char *buf, int len) return QSize(); // Bail out if the necessary extension is not present. - if (!(QGLExtensions::glExtensions() & QGLExtensions::DDSTextureCompression)) { + if (!qgl_extensions()->hasOpenGLExtension(QOpenGLExtensions::DDSTextureCompression)) { qWarning("QGLContext::bindTexture(): DDS texture compression is not supported."); return QSize(); } @@ -5139,7 +4962,7 @@ QSize QGLTexture::bindCompressedTextureDDS(const char *buf, int len) size = ((w+3)/4) * ((h+3)/4) * blockSize; if (size > available) break; - glCompressedTexImage2D(GL_TEXTURE_2D, i, format, w, h, 0, + qgl_extensions()->glCompressedTexImage2D(GL_TEXTURE_2D, i, format, w, h, 0, size, pixels + offset); offset += size; available -= size; @@ -5197,14 +5020,12 @@ QSize QGLTexture::bindCompressedTexturePVR(const char *buf, int len) // Bail out if the necessary extension is not present. if (textureFormat == GL_ETC1_RGB8_OES) { - if (!(QGLExtensions::glExtensions() & - QGLExtensions::ETC1TextureCompression)) { + if (!qgl_extensions()->hasOpenGLExtension(QOpenGLExtensions::ETC1TextureCompression)) { qWarning("QGLContext::bindTexture(): ETC1 texture compression is not supported."); return QSize(); } } else { - if (!(QGLExtensions::glExtensions() & - QGLExtensions::PVRTCTextureCompression)) { + if (!qgl_extensions()->hasOpenGLExtension(QOpenGLExtensions::PVRTCTextureCompression)) { qWarning("QGLContext::bindTexture(): PVRTC texture compression is not supported."); return QSize(); } @@ -5250,7 +5071,7 @@ QSize QGLTexture::bindCompressedTexturePVR(const char *buf, int len) pvrHeader->bitsPerPixel) / 8; if (size > bufferSize) break; - glCompressedTexImage2D(GL_TEXTURE_2D, GLint(level), textureFormat, + qgl_extensions()->glCompressedTexImage2D(GL_TEXTURE_2D, GLint(level), textureFormat, GLsizei(width), GLsizei(height), 0, GLsizei(size), buffer); width /= 2; |