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