15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)extern "C" { 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <X11/Xlib.h> 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gl/gl_context_glx.h" 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/debug/trace_event.h" 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h" 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/scoped_ptr.h" 142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ui/gl/GL/glextchromium.h" 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gl/gl_bindings.h" 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gl/gl_implementation.h" 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gl/gl_surface_glx.h" 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace gfx { 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)GLContextGLX::GLContextGLX(GLShareGroup* share_group) 22868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) : GLContextReal(share_group), 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) context_(NULL), 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) display_(NULL) { 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)XDisplay* GLContextGLX::display() { 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return display_; 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool GLContextGLX::Initialize( 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GLSurface* compatible_surface, GpuPreference gpu_preference) { 3368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) display_ = static_cast<XDisplay*>(compatible_surface->GetDisplay()); 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GLXContext share_handle = static_cast<GLXContext>( 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) share_group() ? share_group()->GetHandle() : NULL); 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (GLSurfaceGLX::IsCreateContextSupported()) { 392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DVLOG(1) << "GLX_ARB_create_context supported."; 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::vector<int> attribs; 412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (GLSurfaceGLX::IsCreateContextRobustnessSupported()) { 422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DVLOG(1) << "GLX_ARB_create_context_robustness supported."; 432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) attribs.push_back(GLX_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB); 442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) attribs.push_back(GLX_LOSE_CONTEXT_ON_RESET_ARB); 452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) attribs.push_back(0); 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) context_ = glXCreateContextAttribsARB( 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) display_, 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static_cast<GLXFBConfig>(compatible_surface->GetConfig()), 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) share_handle, 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) True, 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &attribs.front()); 532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!context_) { 542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) LOG(ERROR) << "Failed to create GL context with " 552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) << "glXCreateContextAttribsARB."; 562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return false; 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } else { 592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DVLOG(1) << "GLX_ARB_create_context not supported."; 602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) context_ = glXCreateNewContext( 612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) display_, 622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) static_cast<GLXFBConfig>(compatible_surface->GetConfig()), 632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) GLX_RGBA_TYPE, 642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) share_handle, 652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) True); 662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!context_) { 672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) LOG(ERROR) << "Failed to create GL context with glXCreateNewContext."; 682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return false; 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(context_); 722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DVLOG(1) << " Successfully allocated " 732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) << (compatible_surface->IsOffscreen() ? 742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) "offscreen" : "onscreen") 752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) << " GL context with LOSE_CONTEXT_ON_RESET_ARB"; 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DVLOG(1) << (compatible_surface->IsOffscreen() ? "Offscreen" : "Onscreen") 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << " context was " 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << (glXIsDirect(display_, 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static_cast<GLXContext>(context_)) 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ? "direct" : "indirect") 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << "."; 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void GLContextGLX::Destroy() { 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (context_) { 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) glXDestroyContext(display_, 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static_cast<GLXContext>(context_)); 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) context_ = NULL; 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool GLContextGLX::MakeCurrent(GLSurface* surface) { 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(context_); 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (IsCurrent(surface)) 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 100e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch ScopedReleaseCurrent release_current; 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TRACE_EVENT0("gpu", "GLContextGLX::MakeCurrent"); 1022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!glXMakeContextCurrent( 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) display_, 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) reinterpret_cast<GLXDrawable>(surface->GetHandle()), 1052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) reinterpret_cast<GLXDrawable>(surface->GetHandle()), 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static_cast<GLXContext>(context_))) { 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(ERROR) << "Couldn't make context current with X drawable."; 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Destroy(); 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1127d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) // Set this as soon as the context is current, since we might call into GL. 1137d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) SetRealGLApi(); 1147d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) 115868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) SetCurrent(surface); 1165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (!InitializeDynamicBindings()) { 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Destroy(); 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!surface->OnMakeCurrent(this)) { 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(ERROR) << "Could not make current."; 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Destroy(); 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 127e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch release_current.Cancel(); 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void GLContextGLX::ReleaseCurrent(GLSurface* surface) { 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!IsCurrent(surface)) 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 135868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) SetCurrent(NULL); 1362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!glXMakeContextCurrent(display_, 0, 0, 0)) 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(ERROR) << "glXMakeCurrent failed in ReleaseCurrent"; 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool GLContextGLX::IsCurrent(GLSurface* surface) { 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool native_context_is_current = 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) glXGetCurrentContext() == static_cast<GLXContext>(context_); 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If our context is current then our notion of which GLContext is 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // current must be correct. On the other hand, third-party code 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // using OpenGL might change the current context. 147868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) DCHECK(!native_context_is_current || (GetRealCurrent() == this)); 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!native_context_is_current) 1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (surface) { 1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (glXGetCurrentDrawable() != 1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) reinterpret_cast<GLXDrawable>(surface->GetHandle())) { 1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void* GLContextGLX::GetHandle() { 1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return context_; 1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void GLContextGLX::SetSwapInterval(int interval) { 1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(IsCurrent(NULL)); 1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (HasExtension("GLX_EXT_swap_control") && 1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) g_driver_glx.fn.glXSwapIntervalEXTFn) { 1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) glXSwapIntervalEXT( 1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) display_, 1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) glXGetCurrentDrawable(), 1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) interval); 1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else if (HasExtension("GLX_MESA_swap_control") && 1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) g_driver_glx.fn.glXSwapIntervalMESAFn) { 1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) glXSwapIntervalMESA(interval); 1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if(interval == 0) 1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(WARNING) << 1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "Could not disable vsync: driver does not " 1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "support GLX_EXT_swap_control"; 1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::string GLContextGLX::GetExtensions() { 1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(IsCurrent(NULL)); 1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const char* extensions = GLSurfaceGLX::GetGLXExtensions(); 1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (extensions) { 1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return GLContext::GetExtensions() + " " + extensions; 1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return GLContext::GetExtensions(); 1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool GLContextGLX::GetTotalGpuMemory(size_t* bytes) { 1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(bytes); 1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *bytes = 0; 1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (HasExtension("GL_NVX_gpu_memory_info")) { 1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GLint kbytes = 0; 2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) glGetIntegerv(GL_GPU_MEMORY_INFO_DEDICATED_VIDMEM_NVX, &kbytes); 2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *bytes = 1024*kbytes; 2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool GLContextGLX::WasAllocatedUsingRobustnessExtension() { 2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return GLSurfaceGLX::IsCreateContextRobustnessSupported(); 2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)GLContextGLX::~GLContextGLX() { 2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Destroy(); 2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace gfx 216