diff options
author | Trond Kjernåsen <trond@trolltech.com> | 2009-12-10 16:38:30 (GMT) |
---|---|---|
committer | Trond Kjernåsen <trond@trolltech.com> | 2009-12-10 16:49:29 (GMT) |
commit | bf9456c5a2d8dfe9a35a2175186630cb426858ad (patch) | |
tree | 2430371741ecea3f6c0b27d61887ada433559af0 /src/opengl | |
parent | 6db96dcd4acccbc13161f85adf3164907b7b5cae (diff) | |
download | Qt-bf9456c5a2d8dfe9a35a2175186630cb426858ad.zip Qt-bf9456c5a2d8dfe9a35a2175186630cb426858ad.tar.gz Qt-bf9456c5a2d8dfe9a35a2175186630cb426858ad.tar.bz2 |
Optimize our GL extension checks to avoid mallocs.
We want to avoid any unnecessary mallocs when checking GL/GLX
extensions. The GL extension string can be quite long and contain
several hundred extensions. The old code forced one malloc for each
extension + 1 extra malloc for the extension string itself when
it was copied into the QByteArray.
Reviewed-by: Kim
Diffstat (limited to 'src/opengl')
-rw-r--r-- | src/opengl/qgl.cpp | 47 | ||||
-rw-r--r-- | src/opengl/qgl_p.h | 43 | ||||
-rw-r--r-- | src/opengl/qgl_x11.cpp | 24 |
3 files changed, 79 insertions, 35 deletions
diff --git a/src/opengl/qgl.cpp b/src/opengl/qgl.cpp index dcf8c00..b6f8919 100644 --- a/src/opengl/qgl.cpp +++ b/src/opengl/qgl.cpp @@ -4822,38 +4822,39 @@ QGLWidget::QGLWidget(QGLContext *context, QWidget *parent, void QGLExtensions::init_extensions() { - QList<QByteArray> extensions = QByteArray(reinterpret_cast<const char *>(glGetString(GL_EXTENSIONS))).split(' '); - if (extensions.contains("GL_ARB_texture_rectangle")) + QGLExtensionMatcher extensions(reinterpret_cast<const char *>(glGetString(GL_EXTENSIONS))); + + if (extensions.match("GL_ARB_texture_rectangle")) glExtensions |= TextureRectangle; - if (extensions.contains("GL_ARB_multisample")) + if (extensions.match("GL_ARB_multisample")) glExtensions |= SampleBuffers; - if (extensions.contains("GL_SGIS_generate_mipmap")) + if (extensions.match("GL_SGIS_generate_mipmap")) glExtensions |= GenerateMipmap; - if (extensions.contains("GL_ARB_texture_compression")) + if (extensions.match("GL_ARB_texture_compression")) glExtensions |= TextureCompression; - if (extensions.contains("GL_EXT_texture_compression_s3tc")) + if (extensions.match("GL_EXT_texture_compression_s3tc")) glExtensions |= DDSTextureCompression; - if (extensions.contains("GL_OES_compressed_ETC1_RGB8_texture")) + if (extensions.match("GL_OES_compressed_ETC1_RGB8_texture")) glExtensions |= ETC1TextureCompression; - if (extensions.contains("GL_IMG_texture_compression_pvrtc")) + if (extensions.match("GL_IMG_texture_compression_pvrtc")) glExtensions |= PVRTCTextureCompression; - if (extensions.contains("GL_ARB_fragment_program")) + if (extensions.match("GL_ARB_fragment_program")) glExtensions |= FragmentProgram; - if (extensions.contains("GL_ARB_fragment_shader")) + if (extensions.match("GL_ARB_fragment_shader")) glExtensions |= FragmentShader; - if (extensions.contains("GL_ARB_texture_mirrored_repeat")) + if (extensions.match("GL_ARB_texture_mirrored_repeat")) glExtensions |= MirroredRepeat; - if (extensions.contains("GL_EXT_framebuffer_object")) + if (extensions.match("GL_EXT_framebuffer_object")) glExtensions |= FramebufferObject; - if (extensions.contains("GL_EXT_stencil_two_side")) + if (extensions.match("GL_EXT_stencil_two_side")) glExtensions |= StencilTwoSide; - if (extensions.contains("GL_EXT_stencil_wrap")) + if (extensions.match("GL_EXT_stencil_wrap")) glExtensions |= StencilWrap; - if (extensions.contains("GL_EXT_packed_depth_stencil")) + if (extensions.match("GL_EXT_packed_depth_stencil")) glExtensions |= PackedDepthStencil; - if (extensions.contains("GL_NV_float_buffer")) + if (extensions.match("GL_NV_float_buffer")) glExtensions |= NVFloatBuffer; - if (extensions.contains("GL_ARB_pixel_buffer_object")) + if (extensions.match("GL_ARB_pixel_buffer_object")) glExtensions |= PixelBufferObject; #if defined(QT_OPENGL_ES_2) glExtensions |= FramebufferObject; @@ -4861,26 +4862,26 @@ void QGLExtensions::init_extensions() glExtensions |= FragmentShader; #endif #if defined(QT_OPENGL_ES_1) || defined(QT_OPENGL_ES_1_CL) - if (extensions.contains("GL_OES_framebuffer_object")) + if (extensions.match("GL_OES_framebuffer_object")) glExtensions |= FramebufferObject; #endif #if defined(QT_OPENGL_ES) - if (extensions.contains("GL_OES_packed_depth_stencil")) + if (extensions.match("GL_OES_packed_depth_stencil")) glExtensions |= PackedDepthStencil; #endif - if (extensions.contains("GL_ARB_framebuffer_object")) { + if (extensions.match("GL_ARB_framebuffer_object")) { // ARB_framebuffer_object also includes EXT_framebuffer_blit. glExtensions |= FramebufferObject; glExtensions |= FramebufferBlit; } - if (extensions.contains("GL_EXT_framebuffer_blit")) + if (extensions.match("GL_EXT_framebuffer_blit")) glExtensions |= FramebufferBlit; - if (extensions.contains("GL_ARB_texture_non_power_of_two")) + if (extensions.match("GL_ARB_texture_non_power_of_two")) glExtensions |= NPOTTextures; - if (extensions.contains("GL_EXT_bgra")) + if (extensions.match("GL_EXT_bgra")) glExtensions |= BGRATextureFormat; } diff --git a/src/opengl/qgl_p.h b/src/opengl/qgl_p.h index 8a0b31f..11770d3 100644 --- a/src/opengl/qgl_p.h +++ b/src/opengl/qgl_p.h @@ -610,6 +610,49 @@ private: friend class QGLContextGroup; }; + +// This class can be used to match GL extensions with doing any mallocs. The +// class assumes that the GL extension string ends with a space character, +// which it should do on all conformant platforms. Create the object and pass +// in a pointer to the extension string, then call match() on each extension +// that should be matched. The match() function takes the extension name +// *without* the terminating space character as input. + +class QGLExtensionMatcher +{ +public: + QGLExtensionMatcher(const char *str) + : gl_extensions(str), gl_extensions_length(qstrlen(str)) + {} + + bool match(const char *str) { + int str_length = qstrlen(str); + const char *extensions = gl_extensions; + int extensions_length = gl_extensions_length; + + while (1) { + // the total length that needs to be matched is the str_length + + // the space character that terminates the extension name + if (extensions_length < str_length + 1) + return false; + if (qstrncmp(extensions, str, str_length) == 0 && extensions[str_length] == ' ') + return true; + + int split_pos = 0; + while (split_pos < extensions_length && extensions[split_pos] != ' ') + ++split_pos; + ++split_pos; // added for the terminating space character + extensions += split_pos; + extensions_length -= split_pos; + } + return false; + } + +private: + const char *gl_extensions; + int gl_extensions_length; +}; + QT_END_NAMESPACE #endif // QGL_P_H diff --git a/src/opengl/qgl_x11.cpp b/src/opengl/qgl_x11.cpp index a037282..9c3fc79 100644 --- a/src/opengl/qgl_x11.cpp +++ b/src/opengl/qgl_x11.cpp @@ -343,8 +343,8 @@ void* qglx_getProcAddress(const char* procName) static bool triedResolvingGlxGetProcAddress = false; if (!triedResolvingGlxGetProcAddress) { triedResolvingGlxGetProcAddress = true; - QList<QByteArray> glxExt = QByteArray(glXGetClientString(QX11Info::display(), GLX_EXTENSIONS)).split(' '); - if (glxExt.contains("GLX_ARB_get_proc_address")) { + QGLExtensionMatcher extensions(glXGetClientString(QX11Info::display(), GLX_EXTENSIONS)); + if (extensions.match("GLX_ARB_get_proc_address")) { #if defined(Q_OS_LINUX) || defined(Q_OS_BSD4) void *handle = dlopen(NULL, RTLD_LAZY); if (handle) { @@ -523,8 +523,8 @@ bool QGLContext::chooseContext(const QGLContext* shareContext) if (!d->gpm) return false; } - QList<QByteArray> glxExt = QByteArray(glXQueryExtensionsString(xinfo->display(), xinfo->screen())).split(' '); - if (glxExt.contains("GLX_SGI_video_sync")) { + QGLExtensionMatcher extensions(glXQueryExtensionsString(xinfo->display(), xinfo->screen())); + if (extensions.match("GLX_SGI_video_sync")) { if (d->glFormat.swapInterval() == -1) d->glFormat.setSwapInterval(0); } else { @@ -630,8 +630,8 @@ void *QGLContext::tryVisual(const QGLFormat& f, int bufDepth) static bool useTranspExt = false; static bool useTranspExtChecked = false; if (f.plane() && !useTranspExtChecked && d->paintDevice) { - QByteArray estr(glXQueryExtensionsString(xinfo->display(), xinfo->screen())); - useTranspExt = estr.contains("GLX_EXT_visual_info"); + QGLExtensionMatcher extensions(glXQueryExtensionsString(xinfo->display(), xinfo->screen())); + useTranspExt = extensions.match("GLX_EXT_visual_info"); //# (A bit simplistic; that could theoretically be a substring) if (useTranspExt) { QByteArray cstr(glXGetClientString(xinfo->display(), GLX_VENDOR)); @@ -875,8 +875,8 @@ void QGLContext::swapBuffers() const static bool resolved = false; if (!resolved) { const QX11Info *xinfo = qt_x11Info(d->paintDevice); - QList<QByteArray> glxExt = QByteArray(glXQueryExtensionsString(xinfo->display(), xinfo->screen())).split(' '); - if (glxExt.contains("GLX_SGI_video_sync")) { + QGLExtensionMatcher extensions(glXQueryExtensionsString(xinfo->display(), xinfo->screen())); + if (extensions.match("GLX_SGI_video_sync")) { glXGetVideoSyncSGI = (qt_glXGetVideoSyncSGI)qglx_getProcAddress("glXGetVideoSyncSGI"); glXWaitVideoSyncSGI = (qt_glXWaitVideoSyncSGI)qglx_getProcAddress("glXWaitVideoSyncSGI"); } @@ -1107,8 +1107,8 @@ void *QGLContext::getProcAddress(const QString &proc) const if (resolved && !glXGetProcAddressARB) return 0; if (!glXGetProcAddressARB) { - QList<QByteArray> glxExt = QByteArray(glXGetClientString(QX11Info::display(), GLX_EXTENSIONS)).split(' '); - if (glxExt.contains("GLX_ARB_get_proc_address")) { + QGLExtensionMatcher extensions(glXGetClientString(QX11Info::display(), GLX_EXTENSIONS)); + if (extensions.match("GLX_ARB_get_proc_address")) { #if defined(Q_OS_LINUX) || defined(Q_OS_BSD4) void *handle = dlopen(NULL, RTLD_LAZY); if (handle) { @@ -1609,8 +1609,8 @@ static bool qt_resolveTextureFromPixmap(QPaintDevice *paintDevice) return false; // Can't use TFP without NPOT } const QX11Info *xinfo = qt_x11Info(paintDevice); - QList<QByteArray> glxExt = QByteArray(glXQueryExtensionsString(xinfo->display(), xinfo->screen())).split(' '); - if (glxExt.contains("GLX_EXT_texture_from_pixmap")) { + QGLExtensionMatcher extensions(glXQueryExtensionsString(xinfo->display(), xinfo->screen())); + if (extensions.match("GLX_EXT_texture_from_pixmap")) { glXBindTexImageEXT = (qt_glXBindTexImageEXT) qglx_getProcAddress("glXBindTexImageEXT"); glXReleaseTexImageEXT = (qt_glXReleaseTexImageEXT) qglx_getProcAddress("glXReleaseTexImageEXT"); } |