#include <stdexcept>
#include <algorithm>
#include <memory>
#ifndef WIN32
#include <GL/glx.h>
#endif
#include "TVirtualX.h"
#include "GuiTypes.h"
#include "TString.h"
#include "TError.h"
#include "TROOT.h"
#include "TGLContextPrivate.h"
#include "TGLIncludes.h"
#include "TGLContext.h"
#include "TGLWidget.h"
#include "TGLFormat.h"
#include "TGLUtil.h"
ClassImp(TGLContext)
TGLContext::TGLContext(TGLWidget *wid)
               : fDevice(wid),
                 fPimpl(0),
                 fFromCtor(kTRUE),
                 fValid(kFALSE),
                 fIdentity(0)
{
   
   
   const TGLContext *shareList = TGLContextIdentity::GetDefaultContextAny();
   if (!gVirtualX->IsCmdThread()) {
      gROOT->ProcessLineFast(Form("((TGLContext *)0x%x)->SetContext((TGLWidget *)0x%x, (TGLContext *)0x%x)",
                                  this, wid, shareList));
   } else
      SetContext(wid, shareList);
   fIdentity = TGLContextIdentity::GetDefaultIdentity();
   fIdentity->AddRef(this);
   fFromCtor = kFALSE;
}
TGLContext::TGLContext(TGLWidget *wid, const TGLContext *shareList)
               : fDevice(wid),
                 fPimpl(0),
                 fFromCtor(kTRUE),
                 fValid(kFALSE),
                 fIdentity(0)
{
   
   
   if (!gVirtualX->IsCmdThread()) {
      gROOT->ProcessLineFast(Form("((TGLContext *)0x%x)->SetContext((TGLWidget *)0x%x, (TGLContext *)0x%x)",
                                  this, wid, shareList));
   } else
      SetContext(wid, shareList);
   fIdentity = shareList ? shareList->GetIdentity() : new TGLContextIdentity;
   fIdentity->AddRef(this);
   fFromCtor = kFALSE;
}
#ifdef WIN32
namespace {
   struct LayoutCompatible_t {
      void          *fDummy0;
      void          *fDummy1;
      HWND          *fPHwnd;
      unsigned char  fDummy2;
      unsigned       fDummy3;
      unsigned short fDummy4;
      unsigned short fDummy5;
      void          *fDummy6;
      unsigned       fDummy7:2;
   };
}
void TGLContext::SetContext(TGLWidget *widget, const TGLContext *shareList)
{
   
   
   
   if (!fFromCtor) {
      Error("TGLContext::SetContext", "SetContext must be called only from ctor");
      return;
   }
   std::auto_ptr<TGLContextPrivate> safe_ptr(fPimpl = new TGLContextPrivate);
   LayoutCompatible_t *trick =
      reinterpret_cast<LayoutCompatible_t *>(gVirtualX->GetWindowID(widget->GetWindowIndex()));
   HWND hWND = *trick->fPHwnd;
   HDC  hDC  = GetWindowDC(hWND);
   if (!hDC) {
      Error("TGLContext::SetContext", "GetWindowDC failed");
      throw std::runtime_error("GetWindowDC failed");
   }
   const Rgl::TGuardBase &dcGuard = Rgl::make_guard(ReleaseDC, hWND, hDC);
   if (HGLRC glContext = wglCreateContext(hDC)) {
      if (shareList && !wglShareLists(shareList->fPimpl->fGLContext, glContext)) {
         wglDeleteContext(glContext);
         Error("TGLContext::SetContext", "Context sharing failed!");
         throw std::runtime_error("Context sharing failed");
      }
      fPimpl->fHWND = hWND;
      fPimpl->fHDC = hDC;
      fPimpl->fGLContext = glContext;
   } else {
      Error("TGLContext::SetContext", "wglCreateContext failed");
      throw std::runtime_error("wglCreateContext failed");
   }
   
   fValid = kTRUE;
   fDevice->AddContext(this);
   TGLContextPrivate::RegisterContext(this);
   dcGuard.Stop();
   safe_ptr.release();
}
Bool_t TGLContext::MakeCurrent()
{
   
   
   if (!fValid) {
      Error("TGLContext::MakeCurrent", "This context is invalid.");
      return kFALSE;
   }
   if (!gVirtualX->IsCmdThread())
      return Bool_t(gROOT->ProcessLineFast(Form("((TGLContext *)0x%x)->MakeCurrent()", this)));
   else {
      Bool_t rez = wglMakeCurrent(fPimpl->fHDC, fPimpl->fGLContext);
      if (rez)
         fIdentity->DeleteDisplayLists();
      return rez;
   }
}
void TGLContext::SwapBuffers()
{
   
   
   if (!fValid) {
      Error("TGLContext::SwapBuffers", "This context is invalid.");
      return;
   }
   if (!gVirtualX->IsCmdThread())
      gROOT->ProcessLineFast(Form("((TGLContext *)0x%x)->SwapBuffers()", this));
   else {
      if (fPimpl->fHWND)
         wglSwapLayerBuffers(fPimpl->fHDC, WGL_SWAP_MAIN_PLANE);
      else
         glFinish();
   }
}
void TGLContext::Release()
{
   
   
   if (!gVirtualX->IsCmdThread()) {
      gROOT->ProcessLineFast(Form("((TGLContext *)0x%x)->Release()", this));
      return;
   }
   if (fPimpl->fHWND)
      ReleaseDC(fPimpl->fHWND, fPimpl->fHDC);
   TGLContextPrivate::RemoveContext(this);
   wglDeleteContext(fPimpl->fGLContext);
   fValid = kFALSE;
}
#else
void TGLContext::SetContext(TGLWidget *widget, const TGLContext *shareList)
{
   
   
   
   if (!fFromCtor) {
      Error("TGLContext::SetContext", "SetContext must be called only from ctor");
      return;
   }
   std::auto_ptr<TGLContextPrivate> safe_ptr(fPimpl = new TGLContextPrivate);
   Display *dpy = static_cast<Display *>(widget->GetInnerData().first);
   XVisualInfo *visInfo = static_cast<XVisualInfo *>(widget->GetInnerData().second);
   GLXContext glCtx = shareList ? glXCreateContext(dpy, visInfo, shareList->fPimpl->fGLContext, True)
                                : glXCreateContext(dpy, visInfo, None, True);
   if (!glCtx) {
      Error("TGLContext::SetContext", "glXCreateContext failed!");
      throw std::runtime_error("glXCreateContext failed!");
   }
   fPimpl->fDpy = dpy;
   fPimpl->fVisualInfo = visInfo;
   fPimpl->fGLContext = glCtx;
   fPimpl->fWindowIndex = widget->GetWindowIndex();
   fValid = kTRUE;
   fDevice->AddContext(this);
   TGLContextPrivate::RegisterContext(this);
   safe_ptr.release();
}
Bool_t TGLContext::MakeCurrent()
{
   
   
   if (!fValid) {
      Error("TGLContext::MakeCurrent", "This context is invalid.");
      return kFALSE;
   }
   if (fPimpl->fWindowIndex != -1) {
      const Bool_t rez = glXMakeCurrent(fPimpl->fDpy,
                                        gVirtualX->GetWindowID(fPimpl->fWindowIndex),
                                        fPimpl->fGLContext);
      if (rez)
         fIdentity->DeleteDisplayLists();
      return rez;
   }
   return kFALSE;
   
}
void TGLContext::SwapBuffers()
{
   
   
   if (!fValid) {
      Error("TGLContext::SwapCurrent", "This context is invalid.");
      return;
   }
   if (fPimpl->fWindowIndex != -1)
      glXSwapBuffers(fPimpl->fDpy, gVirtualX->GetWindowID(fPimpl->fWindowIndex));
   else
      glFinish();
}
void TGLContext::Release()
{
   
   
   TGLContextPrivate::RemoveContext(this);
   glXDestroyContext(fPimpl->fDpy, fPimpl->fGLContext);
   fValid = kFALSE;
}
#endif
TGLContext::~TGLContext()
{
   
   
   if (fValid) {
      Release();
      fDevice->RemoveContext(this);
   }
   fIdentity->Release(this);
   delete fPimpl;
}
TGLContextIdentity *TGLContext::GetIdentity()const
{
   
   
   
   return fIdentity;
}
TGLContext *TGLContext::GetCurrent()
{
   
   return TGLContextPrivate::GetCurrentContext();
}
ClassImp(TGLContextIdentity)
TGLContextIdentity* TGLContextIdentity::fgDefaultIdentity = new TGLContextIdentity;
void TGLContextIdentity::AddRef(TGLContext* ctx)
{
   
   ++fCnt;
   fCtxs.push_back(ctx);
}
void TGLContextIdentity::Release(TGLContext* ctx)
{
   
   CtxList_t::iterator i = std::find(fCtxs.begin(), fCtxs.end(), ctx);
   if (i != fCtxs.end())
   {
      fCtxs.erase(i);
      --fCnt;
      CheckDestroy();
   }
   else
   {
      Error("TGLContextIdentity::Release", "unregistered context.");
   }
}
void TGLContextIdentity::RegisterDLNameRangeToWipe(UInt_t base, Int_t size)
{
   
   fDLTrash.push_back(DLRange_t(base, size));
}
void TGLContextIdentity::DeleteDisplayLists()
{
   
   if (fDLTrash.empty()) return;
   for (DLTrashIt_t it = fDLTrash.begin(), e = fDLTrash.end(); it != e; ++it)
      glDeleteLists(it->first, it->second);
   fDLTrash.clear();
}
TGLContextIdentity* TGLContextIdentity::GetCurrent()
{
   
   TGLContext* ctx = TGLContext::GetCurrent();
   return ctx ? ctx->GetIdentity() : 0;
}
TGLContextIdentity* TGLContextIdentity::GetDefaultIdentity()
{
   
   if (fgDefaultIdentity == 0)
      fgDefaultIdentity = new TGLContextIdentity;
   return fgDefaultIdentity;
}
TGLContext* TGLContextIdentity::GetDefaultContextAny()
{
   
   
   if (fgDefaultIdentity == 0 || fgDefaultIdentity->fCtxs.empty())
      return 0;
   return fgDefaultIdentity->fCtxs.front();
}
void TGLContextIdentity::CheckDestroy()
{
   
   if (fCnt <= 0 && fClientCnt <= 0)
   {
      if (this == fgDefaultIdentity)
         fgDefaultIdentity = 0;
      delete this;
   }
}
This page has been automatically generated. If you have any comments or suggestions about the page layout send a mail to ROOT support, or contact the developers with any questions or problems regarding ROOT.