[prev in list] [next in list] [prev in thread] [next in thread] 

List:       kde-optimize
Subject:    Prelink and libGL.so : a tip
From:       Leon Bottou <leon () bottou ! org>
Date:       2003-11-29 2:18:54
[Download RAW message or body]

It is often quite difficult to use prelink with KDE
because QT depends on libGL.so and libGL.so
is often compiled as a non-PIC library for
performance reasons. 

The NVidia libraries are compiled this way,
and I cannot recompile them in PIC mode
for lack of source.  Sigh.

This is frustrating because 95% of the KDE executables do not need libGL.
Why not make QT load libGL when it needs it only?

The attached patch does this.
It creates little stubs for all the openGL functions needed by QT.  
libGL.so is loaded with dlopen the first time one of these stubs 
is called. Otherwise the stub simply calls the required function.

Rough recipe:
- Get the qt-3.1.2 package for your distribution.
- Apply the distribution specific patches  (e.g. redhat9 has a lot of them...)
- Apply the attached patch.
- Run the script 'configure' that comes with Qt with the appropriate options.
- Edit the file src/Makefile to remove -lGL from the command for linking qt.so.
- Make.

I did it on my redhat9 box by loading the fedora source rpm  (qt-3.1.2-7.fdr.3.src.rpm)
and modifying the spec file to apply the pactch and tweak the makefile.

Result:

[leonb@humbert SPECS]$ LD_DEBUG=statistics konqueror
     25895:
     25895:     runtime linker statistics:
     25895:       total startup time in dynamic loader: 7824120 clock cycles
     25895:                 time needed for relocation: 2653360 clock cycles (33.9%)
     25895:                      number of relocations: 0
     25895:           number of relocations from cache: 1940
     25895:                time needed to load objects: 4555144 clock cycles (58.2%)




P.S. -- 
I am talking about Jakub Jelinek's ELF prelinker, 
not about my old objprelink hack.  It does
not work with gcc-3 anyway.

["qt-x11-free-3.1.2-glstubs.patch" (text/x-diff)]

diff -Nur qt-x11-free-3.1.2.orig/src/opengl/glstubs.cpp \
                qt-x11-free-3.1.2/src/opengl/glstubs.cpp
--- qt-x11-free-3.1.2.orig/src/opengl/glstubs.cpp	1969-12-31 19:00:00.000000000 -0500
+++ qt-x11-free-3.1.2/src/opengl/glstubs.cpp	2003-11-28 18:51:28.000000000 -0500
@@ -0,0 +1,261 @@
+// -*- C++ -*-
+
+#include <stdlib.h>
+#include <dlfcn.h>
+
+#include <GL/gl.h>
+#include <GL/glx.h>
+
+
+
+// loadGL
+
+static void * glhandle = 0;
+
+static char * glnames[] = {
+  "libGL.so",
+  "libGL.so.1",
+  "libGL.so.1.2",
+  0
+};
+
+static void loadgl(void)
+{
+  for (int i=0; !glhandle && glnames[i]; i++)
+    glhandle = dlopen(glnames[i], RTLD_LAZY);
+  if (! glhandle)
+    abort();
+}
+
+#define _cat(a,b) a ## b
+#define cat(a,b) _cat(a,b)
+
+#define RESOLVE(x)                         \
+  if (! cat(p_,x) ) {                      \
+    if (! glhandle)                        \
+      loadgl();                            \
+    (void*) cat(p_,x) = dlsym(glhandle,cat(s_,x)); \
+    if (! cat(p_,x))                       \
+      abort();                             \
+  }
+
+#define STUBV(x,args)                      \
+  RESOLVE(x)                               \
+  (* cat(p_,x)) args
+
+#define STUB(x,args)                       \
+  RESOLVE(x)                               \
+  return (* cat(p_,x)) args
+
+
+
+
+void glCallLists( GLsizei n, GLenum type, const GLvoid *lists );
+static void (*p_glCallLists)( GLsizei n, GLenum type, const GLvoid *lists );
+static const char *s_glCallLists = "glCallLists";
+void glCallLists( GLsizei n, GLenum type, const GLvoid *lists )
+{ STUBV( glCallLists, ( n, type, lists ) ); }
+
+// glClearColor
+static void (*p_glClearColor)( GLclampf red, GLclampf green, GLclampf blue, GLclampf \
alpha ); +static const char *s_glClearColor = "glClearColor";
+void glClearColor( GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha )
+{ STUBV( glClearColor, ( red, green, blue, alpha ) ); }
+
+// glClearIndex
+static void (*p_glClearIndex)( GLfloat c );
+static const char *s_glClearIndex = "glClearIndex";
+void glClearIndex( GLfloat c )
+{ STUBV( glClearIndex, ( c ) ); }
+
+// glColor3ub
+static void (*p_glColor3ub)( GLubyte red, GLubyte green, GLubyte blue );
+static const char *s_glColor3ub = "glColor3ub";
+void glColor3ub( GLubyte red, GLubyte green, GLubyte blue )
+{ STUBV( glColor3ub, ( red, green, blue ) ); }
+
+// glDeleteLists
+static void (*p_glDeleteLists)( GLuint list, GLsizei range );
+static const char *s_glDeleteLists = "glDeleteLists";
+void glDeleteLists( GLuint list, GLsizei range )
+{ STUBV( glDeleteLists, ( list, range ) ); }
+
+// glDrawBuffer
+static void (*p_glDrawBuffer)( GLenum mode );
+static const char *s_glDrawBuffer = "glDrawBuffer";
+void glDrawBuffer( GLenum mode )
+{ STUBV( glDrawBuffer, ( mode ) ); }
+
+// glFlush
+static void (*p_glFlush)( void );
+static const char *s_glFlush = "glFlush";
+void glFlush( void )
+{ STUBV( glFlush, ( ) ); }
+
+// glIndexi
+static void (*p_glIndexi)( GLint c );
+static const char *s_glIndexi = "glIndexi";
+void glIndexi( GLint c )
+{ STUBV( glIndexi, ( c ) ); }
+
+// glListBase
+static void (*p_glListBase)( GLuint base );
+static const char *s_glListBase = "glListBase";
+void glListBase( GLuint base )
+{ STUBV( glListBase, ( base ) ); }
+
+// glLoadIdentity
+static void (*p_glLoadIdentity)( void );
+static const char *s_glLoadIdentity = "glLoadIdentity";
+void glLoadIdentity( void )
+{ STUBV( glLoadIdentity, ( ) ); }
+
+// glMatrixMode
+static void (*p_glMatrixMode)( GLenum mode );
+static const char *s_glMatrixMode = "glMatrixMode";
+void glMatrixMode( GLenum mode )
+{ STUBV( glMatrixMode, ( mode ) ); }
+
+// glOrtho
+static void (*p_glOrtho)( GLdouble left, GLdouble right, GLdouble bottom, GLdouble \
top, GLdouble near_val, GLdouble far_val ); +static const char *s_glOrtho = \
"glOrtho"; +void glOrtho( GLdouble left, GLdouble right, GLdouble bottom, GLdouble \
top, GLdouble near_val, GLdouble far_val ) +{ STUBV( glOrtho, ( left, right, bottom, \
top, near_val, far_val ) ); } +
+// glPopAttrib
+static void (*p_glPushAttrib)( GLbitfield mask );
+static const char *s_glPushAttrib = "glPushAttrib";
+void glPushAttrib( GLbitfield mask )
+{ STUBV( glPushAttrib, ( mask ) ); }
+
+// glPopMatrix
+static void (*p_glPopMatrix)( void );
+static const char *s_glPopMatrix = "glPopMatrix";
+void glPopMatrix( void )
+{ STUBV( glPopMatrix, ( ) ); }
+
+// glPushAttrib
+static void (*p_glPopAttrib)( void );
+static const char *s_glPopAttrib = "glPopAttrib";
+void glPopAttrib( void )
+{ STUBV( glPopAttrib, ( ) ); }
+
+// glPushMatrix
+static void (*p_glPushMatrix)( void );
+static const char *s_glPushMatrix = "glPushMatrix";
+void glPushMatrix( void )
+{ STUBV( glPushMatrix, ( ) ); }
+
+// glRasterPos2i
+static void (*p_glRasterPos2i)( GLint x, GLint y );
+static const char *s_glRasterPos2i = "glRasterPos2i";
+void glRasterPos2i( GLint x, GLint y )
+{ STUBV( glRasterPos2i, ( x, y ) ); }
+
+// glRasterPos3d
+static void (*p_glRasterPos3d)( GLdouble x, GLdouble y, GLdouble z );
+static const char *s_glRasterPos3d = "glRasterPos3d";
+void glRasterPos3d( GLdouble x, GLdouble y, GLdouble z )
+{ STUBV( glRasterPos3d, ( x, y, z ) ); }
+
+// glReadPixels
+static void (*p_glReadPixels)( GLint x, GLint y, GLsizei width, GLsizei height, \
GLenum format, GLenum type, GLvoid *pixels ); +static const char *s_glReadPixels = \
"glReadPixels"; +void glReadPixels( GLint x, GLint y, GLsizei width, GLsizei height, \
GLenum format, GLenum type, GLvoid *pixels ) +{ STUBV( glReadPixels, ( x, y, width, \
height, format, type, pixels ) ); } +
+// glViewport
+static void (*p_glViewport)( GLint x, GLint y, GLsizei width, GLsizei height );
+static const char *s_glViewport = "glViewport";
+void glViewport( GLint x, GLint y, GLsizei width, GLsizei height )
+{ STUBV( glViewport, ( x, y, width, height ) ); }
+
+// glXChooseVisual
+static XVisualInfo* (*p_glXChooseVisual )(Display *dpy, int screen, int \
*attribList); +static const char *s_glXChooseVisual  = "glXChooseVisual";
+XVisualInfo* glXChooseVisual (Display *dpy, int screen, int *attribList)
+{ STUB( glXChooseVisual , (dpy, screen, attribList) ); }
+
+// glXCreateContext
+static GLXContext (*p_glXCreateContext )(Display *dpy, XVisualInfo *vis, GLXContext \
shareList, Bool direct); +static const char *s_glXCreateContext  = \
"glXCreateContext"; +GLXContext glXCreateContext (Display *dpy, XVisualInfo *vis, \
GLXContext shareList, Bool direct) +{ STUB( glXCreateContext , (dpy, vis, shareList, \
direct) ); } +
+// glXCreateGLXPixmap
+static GLXPixmap (*p_glXCreateGLXPixmap )(Display *dpy, XVisualInfo *vis, Pixmap \
pixmap); +static const char *s_glXCreateGLXPixmap  = "glXCreateGLXPixmap";
+GLXPixmap glXCreateGLXPixmap (Display *dpy, XVisualInfo *vis, Pixmap pixmap)
+{ STUB( glXCreateGLXPixmap , (dpy, vis, pixmap) ); }
+
+// glXDestroyContext
+static void (*p_glXDestroyContext )(Display *dpy, GLXContext ctx);
+static const char *s_glXDestroyContext  = "glXDestroyContext";
+void glXDestroyContext (Display *dpy, GLXContext ctx)
+{ STUBV( glXDestroyContext , (dpy, ctx) ); }
+
+// glXDestroyGLXPixmap
+static void (*p_glXDestroyGLXPixmap )(Display *dpy, GLXPixmap pix);
+static const char *s_glXDestroyGLXPixmap  = "glXDestroyGLXPixmap";
+void glXDestroyGLXPixmap (Display *dpy, GLXPixmap pix)
+{ STUBV( glXDestroyGLXPixmap , (dpy, pix) ); }
+
+// glXGetClientString
+static const char * (*p_glXGetClientString )(Display *dpy, int name );
+static const char *s_glXGetClientString  = "glXGetClientString";
+const char * glXGetClientString (Display *dpy, int name )
+{ STUB( glXGetClientString , (dpy, name ) ); }
+
+// glXGetConfig
+static int (*p_glXGetConfig )(Display *dpy, XVisualInfo *vis, int attrib, int \
*value); +static const char *s_glXGetConfig  = "glXGetConfig";
+int glXGetConfig (Display *dpy, XVisualInfo *vis, int attrib, int *value)
+{ STUB( glXGetConfig , (dpy, vis, attrib, value) ); }
+
+// glXIsDirect
+static Bool (*p_glXIsDirect )(Display *dpy, GLXContext ctx);
+static const char *s_glXIsDirect  = "glXIsDirect";
+Bool glXIsDirect (Display *dpy, GLXContext ctx)
+{ STUB( glXIsDirect , (dpy, ctx) ); }
+
+// glXMakeCurrent
+static Bool (*p_glXMakeCurrent )(Display *dpy, GLXDrawable drawable, GLXContext \
ctx); +static const char *s_glXMakeCurrent  = "glXMakeCurrent";
+Bool glXMakeCurrent (Display *dpy, GLXDrawable drawable, GLXContext ctx)
+{ STUB( glXMakeCurrent , (dpy, drawable, ctx) ); }
+
+// glXQueryExtension
+static Bool (*p_glXQueryExtension )(Display *dpy, int *errorBase, int *eventBase);
+static const char *s_glXQueryExtension  = "glXQueryExtension";
+Bool glXQueryExtension (Display *dpy, int *errorBase, int *eventBase)
+{ STUB( glXQueryExtension , (dpy, errorBase, eventBase) ); }
+
+// glXQueryExtensionsString
+static const char * (*p_glXQueryExtensionsString )(Display *dpy, int screen );
+static const char *s_glXQueryExtensionsString  = "glXQueryExtensionsString";
+const char * glXQueryExtensionsString (Display *dpy, int screen )
+{ STUB( glXQueryExtensionsString , (dpy, screen ) ); }
+
+// glXQueryServerString
+static const char * (*p_glXQueryServerString )(Display *dpy, int screen, int name );
+static const char *s_glXQueryServerString  = "glXQueryServerString";
+const char * glXQueryServerString (Display *dpy, int screen, int name )
+{ STUB( glXQueryServerString , (dpy, screen, name ) ); }
+
+// glXSwapBuffers
+static void (*p_glXSwapBuffers )(Display *dpy, GLXDrawable drawable);
+static const char *s_glXSwapBuffers  = "glXSwapBuffers";
+void glXSwapBuffers (Display *dpy, GLXDrawable drawable)
+{ STUBV( glXSwapBuffers , (dpy, drawable) ); }
+
+// glXUseXFont
+static void (*p_glXUseXFont )(Font font, int first, int count, int listBase);
+static const char *s_glXUseXFont  = "glXUseXFont";
+void glXUseXFont (Font font, int first, int count, int listBase)
+{ STUBV( glXUseXFont , (font, first, count, listBase) ); }
+
+// glXWaitX
+static void (*p_glXWaitX )(void);
+static const char *s_glXWaitX  = "glXWaitX";
+void glXWaitX (void)
+{ STUBV( glXWaitX, ( ) ); }
diff -Nur qt-x11-free-3.1.2.orig/src/opengl/qt_opengl.pri \
                qt-x11-free-3.1.2/src/opengl/qt_opengl.pri
--- qt-x11-free-3.1.2.orig/src/opengl/qt_opengl.pri	2002-11-07 10:55:32.000000000 \
                -0500
+++ qt-x11-free-3.1.2/src/opengl/qt_opengl.pri	2003-11-28 18:25:24.000000000 -0500
@@ -7,6 +7,7 @@
 		   $$OPENGL_CPP/qglcolormap.cpp
 	mac:SOURCES += $$OPENGL_CPP/qgl_mac.cpp
 	x11:SOURCES += $$OPENGL_CPP/qgl_x11.cpp
+	x11:SOURCES += $$OPENGL_CPP/glstubs.cpp
 	win32:SOURCES += $$OPENGL_CPP/qgl_win.cpp
 }
 



_______________________________________________
Kde-optimize mailing list
Kde-optimize@kde.org
https://mail.kde.org/mailman/listinfo/kde-optimize


[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic