Changeset 52504 in webkit


Ignore:
Timestamp:
Dec 22, 2009 3:00:20 PM (14 years ago)
Author:
eric@webkit.org
Message:

2009-12-22 Kenneth Russell <kbr@google.com>

Reviewed by Eric Seidel.

[Chromium] WebGL crashes intermittently on Linux
https://bugs.webkit.org/show_bug.cgi?id=32845

The dlclose'ing of libGL.so.1 and dlopen'ing of it each time a
GraphicsContext3D was created was occasionally causing it to be
re-mapped at a different base address. Since GLEW is not
re-initialized every time, primarily for performance reasons, its
cached function pointers were pointing to garbage. Stopped closing
and re-opening libGL.so.1 each time; now it is loaded lazily, when
the first 3D context is created. Also reused the X display
connection since the GLX routines' correctness might hinge upon it
not resulting in a change of GL implementation.

  • src/GraphicsContext3D.cpp: (WebCore::GraphicsContext3DInternal::GLConnection::chooseFBConfig): (WebCore::GraphicsContext3DInternal::GLConnection::createNewContext): (WebCore::GraphicsContext3DInternal::GLConnection::createPbuffer): (WebCore::GraphicsContext3DInternal::GLConnection::destroyPbuffer): (WebCore::GraphicsContext3DInternal::GLConnection::makeCurrent): (WebCore::GraphicsContext3DInternal::GLConnection::destroyContext): (WebCore::GraphicsContext3DInternal::GLConnection::getCurrentContext): (WebCore::GraphicsContext3DInternal::GLConnection::GLConnection): (WebCore::GraphicsContext3DInternal::GLConnection::tryLoad): (WebCore::GraphicsContext3DInternal::GLConnection::create): (WebCore::GraphicsContext3DInternal::GLConnection::~GLConnection): (WebCore::GraphicsContext3DInternal::GraphicsContext3DInternal): (WebCore::GraphicsContext3DInternal::~GraphicsContext3DInternal): (WebCore::GraphicsContext3DInternal::makeContextCurrent):
Location:
trunk/WebKit/chromium
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/WebKit/chromium/ChangeLog

    r52488 r52504  
     12009-12-22  Kenneth Russell  <kbr@google.com>
     2
     3        Reviewed by Eric Seidel.
     4
     5        [Chromium] WebGL crashes intermittently on Linux
     6        https://bugs.webkit.org/show_bug.cgi?id=32845
     7       
     8        The dlclose'ing of libGL.so.1 and dlopen'ing of it each time a
     9        GraphicsContext3D was created was occasionally causing it to be
     10        re-mapped at a different base address. Since GLEW is not
     11        re-initialized every time, primarily for performance reasons, its
     12        cached function pointers were pointing to garbage. Stopped closing
     13        and re-opening libGL.so.1 each time; now it is loaded lazily, when
     14        the first 3D context is created. Also reused the X display
     15        connection since the GLX routines' correctness might hinge upon it
     16        not resulting in a change of GL implementation.
     17
     18        * src/GraphicsContext3D.cpp:
     19        (WebCore::GraphicsContext3DInternal::GLConnection::chooseFBConfig):
     20        (WebCore::GraphicsContext3DInternal::GLConnection::createNewContext):
     21        (WebCore::GraphicsContext3DInternal::GLConnection::createPbuffer):
     22        (WebCore::GraphicsContext3DInternal::GLConnection::destroyPbuffer):
     23        (WebCore::GraphicsContext3DInternal::GLConnection::makeCurrent):
     24        (WebCore::GraphicsContext3DInternal::GLConnection::destroyContext):
     25        (WebCore::GraphicsContext3DInternal::GLConnection::getCurrentContext):
     26        (WebCore::GraphicsContext3DInternal::GLConnection::GLConnection):
     27        (WebCore::GraphicsContext3DInternal::GLConnection::tryLoad):
     28        (WebCore::GraphicsContext3DInternal::GLConnection::create):
     29        (WebCore::GraphicsContext3DInternal::GLConnection::~GLConnection):
     30        (WebCore::GraphicsContext3DInternal::GraphicsContext3DInternal):
     31        (WebCore::GraphicsContext3DInternal::~GraphicsContext3DInternal):
     32        (WebCore::GraphicsContext3DInternal::makeContextCurrent):
     33
    1342009-12-22  Yaar Schnitman  <yaar@chromium.org>
    235
  • trunk/WebKit/chromium/src/GraphicsContext3D.cpp

    r52380 r52504  
    182182#endif
    183183
     184    static bool s_initializedGLEW;
    184185#if PLATFORM(WIN_OS)
    185186    HWND  m_canvasWindow;
     
    191192    unsigned char* m_renderOutput;
    192193#elif PLATFORM(LINUX)
    193     Display* m_display;
    194194    GLXContext m_contextObj;
    195195    GLXPbuffer m_pbuffer;
     196
    196197    // In order to avoid problems caused by linking against libGL, we
    197198    // dynamically look up all the symbols we need.
    198199    // http://code.google.com/p/chromium/issues/detail?id=16800
    199     void* m_libGL;
    200     PFNGLXCHOOSEFBCONFIGPROC m_glXChooseFBConfig;
    201     PFNGLXCREATENEWCONTEXTPROC m_glXCreateNewContext;
    202     PFNGLXCREATEPBUFFERPROC m_glXCreatePbuffer;
    203     PFNGLXDESTROYPBUFFERPROC m_glXDestroyPbuffer;
    204     typedef Bool (* PFNGLXMAKECURRENTPROC)(Display* dpy, GLXDrawable drawable, GLXContext ctx);
    205     PFNGLXMAKECURRENTPROC m_glXMakeCurrent;
    206     typedef void (* PFNGLXDESTROYCONTEXTPROC)(Display* dpy, GLXContext ctx);
    207     PFNGLXDESTROYCONTEXTPROC m_glXDestroyContext;
    208     typedef GLXContext (* PFNGLXGETCURRENTCONTEXTPROC)(void);
    209     PFNGLXGETCURRENTCONTEXTPROC m_glXGetCurrentContext;
     200    class GLConnection {
     201      public:
     202        ~GLConnection();
     203
     204        static GLConnection* create();
     205
     206        GLXFBConfig* chooseFBConfig(int screen, const int *attrib_list, int *nelements)
     207        {
     208            return m_glXChooseFBConfig(m_display, screen, attrib_list, nelements);
     209        }
     210
     211        GLXContext createNewContext(GLXFBConfig config, int renderType, GLXContext shareList, Bool direct)
     212        {
     213            return m_glXCreateNewContext(m_display, config, renderType, shareList, direct);
     214        }
     215
     216        GLXPbuffer createPbuffer(GLXFBConfig config, const int *attribList)
     217        {
     218            return m_glXCreatePbuffer(m_display, config, attribList);
     219        }
     220
     221        void destroyPbuffer(GLXPbuffer pbuf)
     222        {
     223            m_glXDestroyPbuffer(m_display, pbuf);
     224        }
     225
     226        Bool makeCurrent(GLXDrawable drawable, GLXContext ctx)
     227        {
     228            return m_glXMakeCurrent(m_display, drawable, ctx);
     229        }
     230
     231        void destroyContext(GLXContext ctx)
     232        {
     233            m_glXDestroyContext(m_display, ctx);
     234        }
     235
     236        GLXContext getCurrentContext()
     237        {
     238            return m_glXGetCurrentContext();
     239        }
     240
     241      private:
     242        Display* m_display;
     243        void* m_libGL;
     244        PFNGLXCHOOSEFBCONFIGPROC m_glXChooseFBConfig;
     245        PFNGLXCREATENEWCONTEXTPROC m_glXCreateNewContext;
     246        PFNGLXCREATEPBUFFERPROC m_glXCreatePbuffer;
     247        PFNGLXDESTROYPBUFFERPROC m_glXDestroyPbuffer;
     248        typedef Bool (* PFNGLXMAKECURRENTPROC)(Display* dpy, GLXDrawable drawable, GLXContext ctx);
     249        PFNGLXMAKECURRENTPROC m_glXMakeCurrent;
     250        typedef void (* PFNGLXDESTROYCONTEXTPROC)(Display* dpy, GLXContext ctx);
     251        PFNGLXDESTROYCONTEXTPROC m_glXDestroyContext;
     252        typedef GLXContext (* PFNGLXGETCURRENTCONTEXTPROC)(void);
     253        PFNGLXGETCURRENTCONTEXTPROC m_glXGetCurrentContext;
     254
     255        GLConnection(Display* display,
     256                     void* libGL,
     257                     PFNGLXCHOOSEFBCONFIGPROC chooseFBConfig,
     258                     PFNGLXCREATENEWCONTEXTPROC createNewContext,
     259                     PFNGLXCREATEPBUFFERPROC createPbuffer,
     260                     PFNGLXDESTROYPBUFFERPROC destroyPbuffer,
     261                     PFNGLXMAKECURRENTPROC makeCurrent,
     262                     PFNGLXDESTROYCONTEXTPROC destroyContext,
     263                     PFNGLXGETCURRENTCONTEXTPROC getCurrentContext)
     264            : m_libGL(libGL)
     265            , m_display(display)
     266            , m_glXChooseFBConfig(chooseFBConfig)
     267            , m_glXCreateNewContext(createNewContext)
     268            , m_glXCreatePbuffer(createPbuffer)
     269            , m_glXDestroyPbuffer(destroyPbuffer)
     270            , m_glXMakeCurrent(makeCurrent)
     271            , m_glXDestroyContext(destroyContext)
     272            , m_glXGetCurrentContext(getCurrentContext)
     273        {
     274        }
     275
     276        static void* tryLoad(const char* libName)
     277        {
     278            // We use RTLD_GLOBAL semantics so that GLEW initialization works;
     279            // GLEW expects to be able to open the current process's handle
     280            // and do dlsym's of GL entry points from there.
     281            return dlopen(libName, RTLD_LAZY | RTLD_GLOBAL);
     282        }
     283    };
     284
     285    static GLConnection* s_gl;
    210286#else
    211287    #error Must port GraphicsContext3D to your platform
    212288#endif
    213289};
     290
     291bool GraphicsContext3DInternal::s_initializedGLEW = false;
     292#if PLATFORM(LINUX)
     293GraphicsContext3DInternal::GLConnection* GraphicsContext3DInternal::s_gl = 0;
     294#endif
     295
     296GraphicsContext3DInternal::GLConnection* GraphicsContext3DInternal::GLConnection::create()
     297{
     298    Display* dpy = XOpenDisplay(0);
     299    if (!dpy) {
     300        printf("GraphicsContext3D: error opening X display\n");
     301        return 0;
     302    }
     303
     304    void* libGL = 0;
     305    const char* libNames[] = {
     306        "/usr/lib/libGL.so.1",
     307        "/usr/lib32/libGL.so.1",
     308        "/usr/lib64/libGL.so.1",
     309    };
     310    for (int i = 0; i < sizeof(libNames) / sizeof(const char*); i++) {
     311        libGL = tryLoad(libNames[i]);
     312        if (libGL)
     313            break;
     314    }
     315    if (!libGL) {
     316        printf("GraphicsContext3D: error opening libGL.so.1\n");
     317        printf("GraphicsContext3D: tried:\n");
     318        for (int i = 0; i < sizeof(libNames) / sizeof(const char*); i++)
     319            printf(" %s\n", libNames[i]);
     320        return 0;
     321    }
     322
     323    PFNGLXCHOOSEFBCONFIGPROC chooseFBConfig = (PFNGLXCHOOSEFBCONFIGPROC) dlsym(libGL, "glXChooseFBConfig");
     324    PFNGLXCREATENEWCONTEXTPROC createNewContext = (PFNGLXCREATENEWCONTEXTPROC) dlsym(libGL, "glXCreateNewContext");
     325    PFNGLXCREATEPBUFFERPROC createPbuffer = (PFNGLXCREATEPBUFFERPROC) dlsym(libGL, "glXCreatePbuffer");
     326    PFNGLXDESTROYPBUFFERPROC destroyPbuffer = (PFNGLXDESTROYPBUFFERPROC) dlsym(libGL, "glXDestroyPbuffer");
     327    PFNGLXMAKECURRENTPROC makeCurrent = (PFNGLXMAKECURRENTPROC) dlsym(libGL, "glXMakeCurrent");
     328    PFNGLXDESTROYCONTEXTPROC destroyContext = (PFNGLXDESTROYCONTEXTPROC) dlsym(libGL, "glXDestroyContext");
     329    PFNGLXGETCURRENTCONTEXTPROC getCurrentContext = (PFNGLXGETCURRENTCONTEXTPROC) dlsym(libGL, "glXGetCurrentContext");
     330    if (!chooseFBConfig || !createNewContext || !createPbuffer
     331        || !destroyPbuffer || !makeCurrent || !destroyContext
     332        || !getCurrentContext) {
     333        XCloseDisplay(dpy);
     334        dlclose(libGL);
     335        printf("GraphicsContext3D: error looking up bootstrapping entry points\n");
     336        return 0;
     337    }
     338    return new GLConnection(dpy,
     339                            libGL,
     340                            chooseFBConfig,
     341                            createNewContext,
     342                            createPbuffer,
     343                            destroyPbuffer,
     344                            makeCurrent,
     345                            destroyContext,
     346                            getCurrentContext);
     347}
     348
     349GraphicsContext3DInternal::GLConnection::~GLConnection()
     350{
     351    XCloseDisplay(m_display);
     352    dlclose(m_libGL);
     353}
    214354
    215355GraphicsContext3DInternal::VertexAttribPointerState::VertexAttribPointerState()
     
    225365}
    226366
    227 #if PLATFORM(LINUX)
    228 static void* tryLoad(const char* libName)
    229 {
    230     // We use RTLD_GLOBAL semantics so that GLEW initialization works;
    231     // GLEW expects to be able to open the current process's handle
    232     // and do dlsym's of GL entry points from there.
    233     return dlopen(libName, RTLD_LAZY | RTLD_GLOBAL);
    234 }
    235 #endif
    236 
    237367GraphicsContext3DInternal::GraphicsContext3DInternal()
    238368    : m_texture(0)
     
    256386    , m_renderOutput(0)
    257387#elif PLATFORM(LINUX)
    258     , m_display(0)
    259388    , m_contextObj(0)
    260389    , m_pbuffer(0)
    261     , m_glXChooseFBConfig(0)
    262     , m_glXCreateNewContext(0)
    263     , m_glXCreatePbuffer(0)
    264     , m_glXDestroyPbuffer(0)
    265     , m_glXMakeCurrent(0)
    266     , m_glXDestroyContext(0)
    267     , m_glXGetCurrentContext(0)
    268390#else
    269391#error Must port to your platform
     
    383505    m_contextObj = context;
    384506#elif PLATFORM(LINUX)
    385     m_display = XOpenDisplay(0);
    386     if (!m_display) {
    387         printf("GraphicsContext3D: error opening X display\n");
    388         return;
    389     }
    390 
    391     const char* libNames[] = {
    392         "/usr/lib/libGL.so.1",
    393         "/usr/lib32/libGL.so.1",
    394         "/usr/lib64/libGL.so.1",
    395     };
    396     for (int i = 0; i < sizeof(libNames) / sizeof(const char*); i++) {
    397         m_libGL = tryLoad(libNames[i]);
    398         if (m_libGL)
    399             break;
    400     }
    401     if (!m_libGL) {
    402         printf("GraphicsContext3D: error opening libGL.so.1\n");
    403         printf("GraphicsContext3D: tried:");
    404         for (int i = 0; i < sizeof(libNames) / sizeof(const char*); i++)
    405             printf(" %s", libNames[i]);
    406         return;
    407     }
    408     m_glXChooseFBConfig = (PFNGLXCHOOSEFBCONFIGPROC) dlsym(m_libGL, "glXChooseFBConfig");
    409     m_glXCreateNewContext = (PFNGLXCREATENEWCONTEXTPROC) dlsym(m_libGL, "glXCreateNewContext");
    410     m_glXCreatePbuffer = (PFNGLXCREATEPBUFFERPROC) dlsym(m_libGL, "glXCreatePbuffer");
    411     m_glXDestroyPbuffer = (PFNGLXDESTROYPBUFFERPROC) dlsym(m_libGL, "glXDestroyPbuffer");
    412     m_glXMakeCurrent = (PFNGLXMAKECURRENTPROC) dlsym(m_libGL, "glXMakeCurrent");
    413     m_glXDestroyContext = (PFNGLXDESTROYCONTEXTPROC) dlsym(m_libGL, "glXDestroyContext");
    414     m_glXGetCurrentContext = (PFNGLXGETCURRENTCONTEXTPROC) dlsym(m_libGL, "glXGetCurrentContext");
    415     if (!m_glXChooseFBConfig || !m_glXCreateNewContext || !m_glXCreatePbuffer
    416         || !m_glXDestroyPbuffer || !m_glXMakeCurrent || !m_glXDestroyContext
    417         || !m_glXGetCurrentContext) {
    418         printf("GraphicsContext3D: error looking up bootstrapping entry points\n");
    419         return;
    420     }
     507    if (!s_gl) {
     508        s_gl = GLConnection::create();
     509        if (!s_gl)
     510            return;
     511    }
     512
    421513    int configAttrs[] = {
    422514        GLX_DRAWABLE_TYPE,
     
    429521    };
    430522    int nelements = 0;
    431     GLXFBConfig* config = m_glXChooseFBConfig(m_display, 0, configAttrs, &nelements);
     523    GLXFBConfig* config = s_gl->chooseFBConfig(0, configAttrs, &nelements);
    432524    if (!config) {
    433525        printf("GraphicsContext3D: glXChooseFBConfig failed\n");
     
    439531        return;
    440532    }
    441     GLXContext context = m_glXCreateNewContext(m_display, config[0], GLX_RGBA_TYPE, 0, True);
     533    GLXContext context = s_gl->createNewContext(config[0], GLX_RGBA_TYPE, 0, True);
    442534    if (!context) {
    443535        printf("GraphicsContext3D: glXCreateNewContext failed\n");
     
    452544        0
    453545    };
    454     GLXPbuffer pbuffer = m_glXCreatePbuffer(m_display, config[0], pbufferAttrs);
     546    GLXPbuffer pbuffer = s_gl->createPbuffer(config[0], pbufferAttrs);
    455547    XFree(config);
    456548    if (!pbuffer) {
     
    458550        return;
    459551    }
    460     if (!m_glXMakeCurrent(m_display, pbuffer, context)) {
     552    if (!s_gl->makeCurrent(pbuffer, context)) {
    461553        printf("GraphicsContext3D: glXMakeCurrent failed\n");
    462554        return;
     
    468560#endif
    469561
    470     static bool initializedGLEW = false;
    471     if (!initializedGLEW) {
     562    if (!s_initializedGLEW) {
    472563        // Initialize GLEW and check for GL 2.0 support by the drivers.
    473564        GLenum glewInitResult = glewInit();
     
    480571            return;
    481572        }
    482         initializedGLEW = true;
     573        s_initializedGLEW = true;
    483574    }
    484575}
     
    512603        delete[] m_renderOutput;
    513604#elif PLATFORM(LINUX)
    514     m_glXMakeCurrent(m_display, 0, 0);
    515     m_glXDestroyContext(m_display, m_contextObj);
    516     m_glXDestroyPbuffer(m_display, m_pbuffer);
    517     XCloseDisplay(m_display);
    518     dlclose(m_libGL);
     605    s_gl->makeCurrent(0, 0);
     606    s_gl->destroyContext(m_contextObj);
     607    s_gl->destroyPbuffer(m_pbuffer);
    519608#else
    520609#error Must port to your platform
     
    534623            return true;
    535624#elif PLATFORM(LINUX)
    536     if (m_glXGetCurrentContext() != m_contextObj)
    537         if (m_glXMakeCurrent(m_display, m_pbuffer, m_contextObj))
     625    if (s_gl->getCurrentContext() != m_contextObj)
     626        if (s_gl->makeCurrent(m_pbuffer, m_contextObj))
    538627            return true;
    539628#else
Note: See TracChangeset for help on using the changeset viewer.