Commit bf9456c5a2d8dfe9a35a2175186630cb426858ad

  • avatar
  • Trond Kjernåsen <trond @trol…ech.com>
  • Thu Dec 10 17:49:29 CET 2009
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
  
48224822
48234823void QGLExtensions::init_extensions()
48244824{
4825 QList<QByteArray> extensions = QByteArray(reinterpret_cast<const char *>(glGetString(GL_EXTENSIONS))).split(' ');
4826 if (extensions.contains("GL_ARB_texture_rectangle"))
4825 QGLExtensionMatcher extensions(reinterpret_cast<const char *>(glGetString(GL_EXTENSIONS)));
4826
4827 if (extensions.match("GL_ARB_texture_rectangle"))
48274828 glExtensions |= TextureRectangle;
4828 if (extensions.contains("GL_ARB_multisample"))
4829 if (extensions.match("GL_ARB_multisample"))
48294830 glExtensions |= SampleBuffers;
4830 if (extensions.contains("GL_SGIS_generate_mipmap"))
4831 if (extensions.match("GL_SGIS_generate_mipmap"))
48314832 glExtensions |= GenerateMipmap;
4832 if (extensions.contains("GL_ARB_texture_compression"))
4833 if (extensions.match("GL_ARB_texture_compression"))
48334834 glExtensions |= TextureCompression;
4834 if (extensions.contains("GL_EXT_texture_compression_s3tc"))
4835 if (extensions.match("GL_EXT_texture_compression_s3tc"))
48354836 glExtensions |= DDSTextureCompression;
4836 if (extensions.contains("GL_OES_compressed_ETC1_RGB8_texture"))
4837 if (extensions.match("GL_OES_compressed_ETC1_RGB8_texture"))
48374838 glExtensions |= ETC1TextureCompression;
4838 if (extensions.contains("GL_IMG_texture_compression_pvrtc"))
4839 if (extensions.match("GL_IMG_texture_compression_pvrtc"))
48394840 glExtensions |= PVRTCTextureCompression;
4840 if (extensions.contains("GL_ARB_fragment_program"))
4841 if (extensions.match("GL_ARB_fragment_program"))
48414842 glExtensions |= FragmentProgram;
4842 if (extensions.contains("GL_ARB_fragment_shader"))
4843 if (extensions.match("GL_ARB_fragment_shader"))
48434844 glExtensions |= FragmentShader;
4844 if (extensions.contains("GL_ARB_texture_mirrored_repeat"))
4845 if (extensions.match("GL_ARB_texture_mirrored_repeat"))
48454846 glExtensions |= MirroredRepeat;
4846 if (extensions.contains("GL_EXT_framebuffer_object"))
4847 if (extensions.match("GL_EXT_framebuffer_object"))
48474848 glExtensions |= FramebufferObject;
4848 if (extensions.contains("GL_EXT_stencil_two_side"))
4849 if (extensions.match("GL_EXT_stencil_two_side"))
48494850 glExtensions |= StencilTwoSide;
4850 if (extensions.contains("GL_EXT_stencil_wrap"))
4851 if (extensions.match("GL_EXT_stencil_wrap"))
48514852 glExtensions |= StencilWrap;
4852 if (extensions.contains("GL_EXT_packed_depth_stencil"))
4853 if (extensions.match("GL_EXT_packed_depth_stencil"))
48534854 glExtensions |= PackedDepthStencil;
4854 if (extensions.contains("GL_NV_float_buffer"))
4855 if (extensions.match("GL_NV_float_buffer"))
48554856 glExtensions |= NVFloatBuffer;
4856 if (extensions.contains("GL_ARB_pixel_buffer_object"))
4857 if (extensions.match("GL_ARB_pixel_buffer_object"))
48574858 glExtensions |= PixelBufferObject;
48584859#if defined(QT_OPENGL_ES_2)
48594860 glExtensions |= FramebufferObject;
48624862 glExtensions |= FragmentShader;
48634863#endif
48644864#if defined(QT_OPENGL_ES_1) || defined(QT_OPENGL_ES_1_CL)
4865 if (extensions.contains("GL_OES_framebuffer_object"))
4865 if (extensions.match("GL_OES_framebuffer_object"))
48664866 glExtensions |= FramebufferObject;
48674867#endif
48684868#if defined(QT_OPENGL_ES)
4869 if (extensions.contains("GL_OES_packed_depth_stencil"))
4869 if (extensions.match("GL_OES_packed_depth_stencil"))
48704870 glExtensions |= PackedDepthStencil;
48714871#endif
4872 if (extensions.contains("GL_ARB_framebuffer_object")) {
4872 if (extensions.match("GL_ARB_framebuffer_object")) {
48734873 // ARB_framebuffer_object also includes EXT_framebuffer_blit.
48744874 glExtensions |= FramebufferObject;
48754875 glExtensions |= FramebufferBlit;
48764876 }
48774877
4878 if (extensions.contains("GL_EXT_framebuffer_blit"))
4878 if (extensions.match("GL_EXT_framebuffer_blit"))
48794879 glExtensions |= FramebufferBlit;
48804880
4881 if (extensions.contains("GL_ARB_texture_non_power_of_two"))
4881 if (extensions.match("GL_ARB_texture_non_power_of_two"))
48824882 glExtensions |= NPOTTextures;
48834883
4884 if (extensions.contains("GL_EXT_bgra"))
4884 if (extensions.match("GL_EXT_bgra"))
48854885 glExtensions |= BGRATextureFormat;
48864886}
48874887
  
610610 friend class QGLContextGroup;
611611};
612612
613
614// This class can be used to match GL extensions with doing any mallocs. The
615// class assumes that the GL extension string ends with a space character,
616// which it should do on all conformant platforms. Create the object and pass
617// in a pointer to the extension string, then call match() on each extension
618// that should be matched. The match() function takes the extension name
619// *without* the terminating space character as input.
620
621class QGLExtensionMatcher
622{
623public:
624 QGLExtensionMatcher(const char *str)
625 : gl_extensions(str), gl_extensions_length(qstrlen(str))
626 {}
627
628 bool match(const char *str) {
629 int str_length = qstrlen(str);
630 const char *extensions = gl_extensions;
631 int extensions_length = gl_extensions_length;
632
633 while (1) {
634 // the total length that needs to be matched is the str_length +
635 // the space character that terminates the extension name
636 if (extensions_length < str_length + 1)
637 return false;
638 if (qstrncmp(extensions, str, str_length) == 0 && extensions[str_length] == ' ')
639 return true;
640
641 int split_pos = 0;
642 while (split_pos < extensions_length && extensions[split_pos] != ' ')
643 ++split_pos;
644 ++split_pos; // added for the terminating space character
645 extensions += split_pos;
646 extensions_length -= split_pos;
647 }
648 return false;
649 }
650
651private:
652 const char *gl_extensions;
653 int gl_extensions_length;
654};
655
613656QT_END_NAMESPACE
614657
615658#endif // QGL_P_H
  
343343 static bool triedResolvingGlxGetProcAddress = false;
344344 if (!triedResolvingGlxGetProcAddress) {
345345 triedResolvingGlxGetProcAddress = true;
346 QList<QByteArray> glxExt = QByteArray(glXGetClientString(QX11Info::display(), GLX_EXTENSIONS)).split(' ');
347 if (glxExt.contains("GLX_ARB_get_proc_address")) {
346 QGLExtensionMatcher extensions(glXGetClientString(QX11Info::display(), GLX_EXTENSIONS));
347 if (extensions.match("GLX_ARB_get_proc_address")) {
348348#if defined(Q_OS_LINUX) || defined(Q_OS_BSD4)
349349 void *handle = dlopen(NULL, RTLD_LAZY);
350350 if (handle) {
523523 if (!d->gpm)
524524 return false;
525525 }
526 QList<QByteArray> glxExt = QByteArray(glXQueryExtensionsString(xinfo->display(), xinfo->screen())).split(' ');
527 if (glxExt.contains("GLX_SGI_video_sync")) {
526 QGLExtensionMatcher extensions(glXQueryExtensionsString(xinfo->display(), xinfo->screen()));
527 if (extensions.match("GLX_SGI_video_sync")) {
528528 if (d->glFormat.swapInterval() == -1)
529529 d->glFormat.setSwapInterval(0);
530530 } else {
630630 static bool useTranspExt = false;
631631 static bool useTranspExtChecked = false;
632632 if (f.plane() && !useTranspExtChecked && d->paintDevice) {
633 QByteArray estr(glXQueryExtensionsString(xinfo->display(), xinfo->screen()));
634 useTranspExt = estr.contains("GLX_EXT_visual_info");
633 QGLExtensionMatcher extensions(glXQueryExtensionsString(xinfo->display(), xinfo->screen()));
634 useTranspExt = extensions.match("GLX_EXT_visual_info");
635635 //# (A bit simplistic; that could theoretically be a substring)
636636 if (useTranspExt) {
637637 QByteArray cstr(glXGetClientString(xinfo->display(), GLX_VENDOR));
875875 static bool resolved = false;
876876 if (!resolved) {
877877 const QX11Info *xinfo = qt_x11Info(d->paintDevice);
878 QList<QByteArray> glxExt = QByteArray(glXQueryExtensionsString(xinfo->display(), xinfo->screen())).split(' ');
879 if (glxExt.contains("GLX_SGI_video_sync")) {
878 QGLExtensionMatcher extensions(glXQueryExtensionsString(xinfo->display(), xinfo->screen()));
879 if (extensions.match("GLX_SGI_video_sync")) {
880880 glXGetVideoSyncSGI = (qt_glXGetVideoSyncSGI)qglx_getProcAddress("glXGetVideoSyncSGI");
881881 glXWaitVideoSyncSGI = (qt_glXWaitVideoSyncSGI)qglx_getProcAddress("glXWaitVideoSyncSGI");
882882 }
11071107 if (resolved && !glXGetProcAddressARB)
11081108 return 0;
11091109 if (!glXGetProcAddressARB) {
1110 QList<QByteArray> glxExt = QByteArray(glXGetClientString(QX11Info::display(), GLX_EXTENSIONS)).split(' ');
1111 if (glxExt.contains("GLX_ARB_get_proc_address")) {
1110 QGLExtensionMatcher extensions(glXGetClientString(QX11Info::display(), GLX_EXTENSIONS));
1111 if (extensions.match("GLX_ARB_get_proc_address")) {
11121112#if defined(Q_OS_LINUX) || defined(Q_OS_BSD4)
11131113 void *handle = dlopen(NULL, RTLD_LAZY);
11141114 if (handle) {
16091609 return false; // Can't use TFP without NPOT
16101610 }
16111611 const QX11Info *xinfo = qt_x11Info(paintDevice);
1612 QList<QByteArray> glxExt = QByteArray(glXQueryExtensionsString(xinfo->display(), xinfo->screen())).split(' ');
1613 if (glxExt.contains("GLX_EXT_texture_from_pixmap")) {
1612 QGLExtensionMatcher extensions(glXQueryExtensionsString(xinfo->display(), xinfo->screen()));
1613 if (extensions.match("GLX_EXT_texture_from_pixmap")) {
16141614 glXBindTexImageEXT = (qt_glXBindTexImageEXT) qglx_getProcAddress("glXBindTexImageEXT");
16151615 glXReleaseTexImageEXT = (qt_glXReleaseTexImageEXT) qglx_getProcAddress("glXReleaseTexImageEXT");
16161616 }