#include <stdexcept>
#include <vector>
#ifndef WIN32
#include <GL/glx.h>
#endif
#include "TVirtualX.h"
#include "TGClient.h"
#include "TError.h"
#include "TROOT.h"
#include "TGLWidget.h"
#include "TGLIncludes.h"
#include "TGLUtil.h"
ClassImp(TGLWidgetContainer)
TGLWidgetContainer::TGLWidgetContainer(TGLWidget *owner, Window_t id, const TGWindow *parent)
                     : TGCompositeFrame(gClient, id, parent),
                       fOwner(owner)
{
   
}
Bool_t TGLWidgetContainer::HandleButton(Event_t *ev)
{
   
   return fOwner->HandleButton(ev);
}
Bool_t TGLWidgetContainer::HandleDoubleClick(Event_t *ev)
{
   
   return fOwner->HandleDoubleClick(ev);
}
Bool_t TGLWidgetContainer::HandleConfigureNotify(Event_t *ev)
{
   
   return fOwner->HandleConfigureNotify(ev);
}
Bool_t TGLWidgetContainer::HandleKey(Event_t *ev)
{
   
   return fOwner->HandleKey(ev);
}
Bool_t TGLWidgetContainer::HandleMotion(Event_t *ev)
{
   
   return fOwner->HandleMotion(ev);
}
void TGLWidgetContainer::DoRedraw()
{
   
   return fOwner->Repaint();
}
ClassImp(TGLWidget)
TGLWidget::TGLWidget(const TGWindow &p, Bool_t select,
                     const TGLPaintDevice *shareDevice,
                     UInt_t w, UInt_t h, UInt_t opt, Pixel_t back)
              : TGCanvas(&p, w, h, opt, back),
                fWindowIndex(-1),
                fFromCtor(kTRUE)
{
   
   CreateWidget(shareDevice);
   if (select) {
      gVirtualX->GrabButton(
                            fContainer->GetId(), kAnyButton, kAnyModifier,
                            kButtonPressMask | kButtonReleaseMask, kNone, kNone
                           );
      gVirtualX->SelectInput(
                             fContainer->GetId(), kKeyPressMask | kExposureMask | kPointerMotionMask
                             | kStructureNotifyMask | kFocusChangeMask
                            );
      gVirtualX->SetInputFocus(fContainer->GetId());
   }
   fFromCtor = kFALSE;
}
TGLWidget::TGLWidget(const TGLFormat &format, const TGWindow &p, Bool_t select,
                     const TGLPaintDevice *shareDevice,
                     UInt_t w, UInt_t h, UInt_t opt, Pixel_t back)
              : TGCanvas(&p, w, h, opt, back),
                fWindowIndex(-1),
                fGLFormat(format),
                fFromCtor(kTRUE)
{
   
   CreateWidget(shareDevice);
   if (select) {
      gVirtualX->GrabButton(
                            fContainer->GetId(), kAnyButton, kAnyModifier,
                            kButtonPressMask | kButtonReleaseMask, kNone, kNone
                           );
      gVirtualX->SelectInput(
                             fContainer->GetId(), kKeyPressMask | kExposureMask | kPointerMotionMask
                             | kStructureNotifyMask | kFocusChangeMask
                            );
      gVirtualX->SetInputFocus(fContainer->GetId());
   }
   fFromCtor = kFALSE;
}
TGLWidget::TGLWidget(const TGWindow &p, Bool_t select,
                     UInt_t w, UInt_t h, UInt_t opt, Pixel_t back)
              : TGCanvas(&p, w, h, opt, back),
                fWindowIndex(-1),
                fFromCtor(kTRUE)
{
   
   CreateWidget();
   if (select) {
      gVirtualX->GrabButton(
                            fContainer->GetId(), kAnyButton, kAnyModifier,
                            kButtonPressMask | kButtonReleaseMask, kNone, kNone
                           );
      gVirtualX->SelectInput(
                             fContainer->GetId(), kKeyPressMask | kExposureMask | kPointerMotionMask
                             | kStructureNotifyMask | kFocusChangeMask
                            );
      gVirtualX->SetInputFocus(fContainer->GetId());
   }
   fFromCtor = kFALSE;
}
TGLWidget::TGLWidget(const TGLFormat &format, const TGWindow &p, Bool_t select,
                     UInt_t w, UInt_t h, UInt_t opt, Pixel_t back)
              : TGCanvas(&p, w, h, opt, back),
                fWindowIndex(-1),
                fGLFormat(format),
                fFromCtor(kTRUE)
{
   
   CreateWidget();
   if (select) {
      gVirtualX->GrabButton(
                            fContainer->GetId(), kAnyButton, kAnyModifier,
                            kButtonPressMask | kButtonReleaseMask, kNone, kNone
                           );
      gVirtualX->SelectInput(
                             fContainer->GetId(), kKeyPressMask | kExposureMask | kPointerMotionMask
                             | kStructureNotifyMask | kFocusChangeMask
                            );
      gVirtualX->SetInputFocus(fContainer->GetId());
   }
   fFromCtor = kFALSE;
}
TGLWidget::~TGLWidget()
{
   
   gVirtualX->SelectWindow(fWindowIndex);
   gVirtualX->CloseWindow();
#ifndef WIN32
   XFree(fInnerData.second);
#endif
   if (fValidContexts.size() > 1u) {
      Warning("~TGLWidget", "There are some gl-contexts connected to this gl device"
                            "which have longer lifetime than lifetime of gl-device");
   }
   std::set<TGLContext *>::iterator it = fValidContexts.begin();
   for (; it != fValidContexts.end(); ++it) {
      (*it)->Release();
   }
}
void TGLWidget::InitGL()
{
   
}
void TGLWidget::PaintGL()
{
   
}
Bool_t TGLWidget::MakeCurrent()
{
   
   return fGLContext->MakeCurrent();
}
void TGLWidget::SwapBuffers()
{
   
   fGLContext->SwapBuffers();
}
const TGLContext *TGLWidget::GetContext()const
{
   
   return fGLContext.get();
}
Bool_t TGLWidget::HandleButton(Event_t *ev)
{
   
   
   if (!gVirtualX->IsCmdThread()) {
      gROOT->ProcessLineFast(Form("((TGLWidget *)0x%x)->HandleButton((Event_t *)0x%x)", this, ev));
      return kTRUE;
   }
   Emit("HandleButton(Event_t*)", (Long_t)ev);
   return kTRUE;
}
Bool_t TGLWidget::HandleDoubleClick(Event_t *ev)
{
   
   
   if (!gVirtualX->IsCmdThread()) {
      gROOT->ProcessLineFast(Form("((TGLWidget *)0x%x)->HandleDoubleClick((Event_t *)0x%x)", this, ev));
      return kTRUE;
   }
   Emit("HandleDoubleClick(Event_t*)", (Long_t)ev);
   return kTRUE;
}
Bool_t TGLWidget::HandleConfigureNotify(Event_t *ev)
{
   
   
   if (!gVirtualX->IsCmdThread()) {
      gROOT->ProcessLineFast(Form("((TGLWidget *)0x%x)->HandleConfigureNotify((Event_t *)0x%x)", this, ev));
      return kTRUE;
   }
   Emit("HandleConfigureNotify(Event_t*)", (Long_t)ev);
   return kTRUE;
}
Bool_t TGLWidget::HandleKey(Event_t *ev)
{
   
   
   if (!gVirtualX->IsCmdThread()) {
      gROOT->ProcessLineFast(Form("((TGLWidget *)0x%x)->HandleKey((Event_t *)0x%x)", this, ev));
      return kTRUE;
   }
   Emit("HandleKey(Event_t*)", (Long_t)ev);
   return kTRUE;
}
Bool_t TGLWidget::HandleMotion(Event_t *ev)
{
   
   
   if (!gVirtualX->IsCmdThread()) {
      gROOT->ProcessLineFast(Form("((TGLWidget *)0x%x)->HandleMotion((Event_t *)0x%x)", this, ev));
      return kTRUE;
   }
   Emit("HandleMotion(Event_t*)", (Long_t)ev);
   return kTRUE;
}
Int_t TGLWidget::GetWindowIndex()const
{
   
   return fWindowIndex;
}
const TGLFormat *TGLWidget::GetPixelFormat()const
{
   
   return &fGLFormat;
}
Int_t TGLWidget::GetContId()const
{
   
   return fContainer->GetId();
}
std::pair<void *, void *> TGLWidget::GetInnerData()const
{
   
   return fInnerData;
}
#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 fill_pfd(PIXELFORMATDESCRIPTOR *pfd, const TGLFormat &request)
   {
      pfd->nSize = sizeof(PIXELFORMATDESCRIPTOR);
      pfd->nVersion = 1;
      pfd->dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL;
      if (request.IsDoubleBuffered())
         pfd->dwFlags |= PFD_DOUBLEBUFFER;
      pfd->iPixelType = PFD_TYPE_RGBA;
      pfd->cColorBits = 24;
      if (UInt_t acc = request.GetAccumSize())
         pfd->cAccumBits = acc;
      if (UInt_t depth = request.GetDepthSize())
         pfd->cDepthBits = depth;
      if (UInt_t stencil = request.GetStencilSize())
         pfd->cStencilBits = stencil;
   }
   void check_pixel_format(Int_t pixIndex, HDC hDC, TGLFormat &request)
   {
      PIXELFORMATDESCRIPTOR pfd = {};
      if (!DescribePixelFormat(hDC, pixIndex, sizeof pfd, &pfd)) {
         Warning("TGLContext::SetContext", "DescribePixelFormat failed");
         return;
      }
      if (pfd.cAccumBits)
         request.SetAccumSize(pfd.cAccumBits);
      if (pfd.cDepthBits)
         request.SetDepthSize(pfd.cDepthBits);
      if (pfd.cStencilBits)
         request.SetStencilSize(pfd.cStencilBits);
   }
}
void TGLWidget::CreateWidget(const TGLPaintDevice *shareDevice)
{
   
   
   
   
   
   
   
   
   fWindowIndex = gVirtualX->InitWindow((ULong_t)GetViewPort()->GetId());
   try {
      if (!gVirtualX->IsCmdThread())
         gROOT->ProcessLineFast(Form("((TGLWidget *)0x%x)->SetFormat()", this));
      else
         SetFormat();
      fGLContext.reset(new TGLContext(this, shareDevice ? shareDevice->GetContext() : 0));
      fContainer.reset(new TGLWidgetContainer(this, gVirtualX->GetWindowID(fWindowIndex), GetViewPort()));
      SetContainer(fContainer.get());
   } catch (std::exception &) {
      gVirtualX->SelectWindow(fWindowIndex);
      gVirtualX->CloseWindow();
      throw;
   }
}
void TGLWidget::CreateWidget()
{
   
   fWindowIndex = gVirtualX->InitWindow((ULong_t)GetViewPort()->GetId());
   try {
      if (!gVirtualX->IsCmdThread())
         gROOT->ProcessLineFast(Form("((TGLWidget *)0x%x)->SetFormat()", this));
      else
         SetFormat();
      fGLContext.reset(new TGLContext(this));
      fContainer.reset(new TGLWidgetContainer(this, gVirtualX->GetWindowID(fWindowIndex), GetViewPort()));
      SetContainer(fContainer.get());
   } catch (std::exception &) {
      gVirtualX->SelectWindow(fWindowIndex);
      gVirtualX->CloseWindow();
      throw;
   }
}
void TGLWidget::SetFormat()
{
   
   
   if (!fFromCtor) {
      Error("TGLWidget::SetFormat", "Sorry, you should not call this function");
      return;
   }
   LayoutCompatible_t *trick =
      reinterpret_cast<LayoutCompatible_t *>(gVirtualX->GetWindowID(GetWindowIndex()));
   HWND hWND = *trick->fPHwnd;
   HDC  hDC  = GetWindowDC(hWND);
   if (!hDC) {
      Error("TGLWidget::SetFormat", "GetWindowDC failed");
      throw std::runtime_error("GetWindowDC failed");
   }
   const Rgl::TGuardBase &dcGuard = Rgl::make_guard(ReleaseDC, hWND, hDC);
   PIXELFORMATDESCRIPTOR pfd = {};
   fill_pfd(&pfd, fGLFormat);
   if (const Int_t pixIndex = ChoosePixelFormat(hDC, &pfd)) {
      check_pixel_format(pixIndex, hDC, fGLFormat);
      if (!SetPixelFormat(hDC, pixIndex, &pfd)) {
         Error("TGLWidget::SetFormat", "SetPixelFormat failed");
         throw std::runtime_error("SetPixelFormat failed");
      }
   } else {
      Error("TGLWidget::SetFormat", "ChoosePixelFormat failed");
      throw std::runtime_error("ChoosePixelFormat failed");
   }
}
#else
namespace {
   void fill_format(std::vector<Int_t> &format, const TGLFormat &request)
   {
      format.push_back(GLX_RGBA);
      format.push_back(GLX_RED_SIZE);
      format.push_back(1);
      format.push_back(GLX_GREEN_SIZE);
      format.push_back(1);
      format.push_back(GLX_BLUE_SIZE);
      format.push_back(1);
      if (request.IsDoubleBuffered())
         format.push_back(GLX_DOUBLEBUFFER);
      if (request.HasDepth()) {
         format.push_back(GLX_DEPTH_SIZE);
         format.push_back(request.GetDepthSize());
      }
      if (request.HasStencil()) {
         format.push_back(GLX_STENCIL_SIZE);
         format.push_back(request.GetStencilSize());
      }
      if (request.HasAccumBuffer()) {
         format.push_back(GLX_ACCUM_RED_SIZE);
         format.push_back(1);
         format.push_back(GLX_ACCUM_GREEN_SIZE);
         format.push_back(1);
         format.push_back(GLX_ACCUM_BLUE_SIZE);
         format.push_back(1);
      }
      format.push_back(None);
   }
   XSetWindowAttributes dummyAttr;
}
void TGLWidget::CreateWidget(const TGLPaintDevice *shareDevice)
{
   
   
   
   
   
   
   std::vector<Int_t> format;
   fill_format(format, fGLFormat);
   Window_t winID = GetViewPort()->GetId();
   Display *dpy = reinterpret_cast<Display *>(gVirtualX->GetDisplay());
   XVisualInfo *visInfo = glXChooseVisual(dpy, DefaultScreen(dpy), &format[0]);
   if (!visInfo) {
      Error("CreateGLContainer", "No good visual found!");
      throw std::runtime_error("No good visual found!");
   }
   Int_t  x = 0, y = 0;
   UInt_t w = 0, h = 0, b = 0, d = 0;
   Window root = 0;
   XGetGeometry(dpy, winID, &root, &x, &y, &w, &h, &b, &d);
   XSetWindowAttributes attr(dummyAttr);
   attr.colormap = XCreateColormap(dpy, root, visInfo->visual, AllocNone); 
   attr.event_mask = NoEventMask;
   attr.backing_store = Always;
   attr.bit_gravity = NorthWestGravity;
   ULong_t mask = CWBackPixel | CWBorderPixel | CWColormap | CWEventMask | CWBackingStore | CWBitGravity;
   Window glWin = XCreateWindow(dpy, winID, x, y, w, h, 0, visInfo->depth,
                                InputOutput, visInfo->visual, mask, &attr);
   XMapWindow(dpy, glWin);
   
   fWindowIndex = gVirtualX->AddWindow(glWin, w, h);
   fInnerData.first  = dpy;
   fInnerData.second = visInfo;
   try {
      fGLContext.reset(new TGLContext(this, shareDevice ? shareDevice->GetContext() : 0));
      fContainer.reset(new TGLWidgetContainer(this, gVirtualX->GetWindowID(fWindowIndex), GetViewPort()));
      SetContainer(fContainer.get());
   } catch (const std::exception &) {
      gVirtualX->SelectWindow(fWindowIndex);
      gVirtualX->CloseWindow();
      XFree(fInnerData.second);
      throw;
   }
}
void TGLWidget::CreateWidget()
{
   
   std::vector<Int_t> format;
   fill_format(format, fGLFormat);
   Window_t winID = GetViewPort()->GetId();
   Display *dpy = reinterpret_cast<Display *>(gVirtualX->GetDisplay());
   XVisualInfo *visInfo = glXChooseVisual(dpy, DefaultScreen(dpy), &format[0]);
   if (!visInfo) {
      Error("CreateGLContainer", "No good visual found!");
      throw std::runtime_error("No good visual found!");
   }
   Int_t  x = 0, y = 0;
   UInt_t w = 0, h = 0, b = 0, d = 0;
   Window root = 0;
   XGetGeometry(dpy, winID, &root, &x, &y, &w, &h, &b, &d);
   XSetWindowAttributes attr(dummyAttr);
   attr.colormap = XCreateColormap(dpy, root, visInfo->visual, AllocNone); 
   attr.event_mask = NoEventMask;
   attr.backing_store = Always;
   attr.bit_gravity = NorthWestGravity;
   ULong_t mask = CWBackPixel | CWBorderPixel | CWColormap | CWEventMask | CWBackingStore | CWBitGravity;
   Window glWin = XCreateWindow(dpy, winID, x, y, w, h, 0, visInfo->depth,
                                InputOutput, visInfo->visual, mask, &attr);
   XMapWindow(dpy, glWin);
   
   fWindowIndex = gVirtualX->AddWindow(glWin, w, h);
   fInnerData.first  = dpy;
   fInnerData.second = visInfo;
   try {
      fGLContext.reset(new TGLContext(this));
      fContainer.reset(new TGLWidgetContainer(this, gVirtualX->GetWindowID(fWindowIndex), GetViewPort()));
      SetContainer(fContainer.get());
   } catch (const std::exception &) {
      gVirtualX->SelectWindow(fWindowIndex);
      gVirtualX->CloseWindow();
      XFree(fInnerData.second);
      throw;
   }
}
void TGLWidget::SetFormat()
{
   
   
}
#endif
void TGLWidget::Repaint()
{
   
   
   Emit("Repaint()");
}
void TGLWidget::AddContext(TGLContext *ctx)
{
   
   fValidContexts.insert(ctx);
}
void TGLWidget::RemoveContext(TGLContext *ctx)
{
   
   std::set<TGLContext *>::iterator it = fValidContexts.find(ctx);
   if (it != fValidContexts.end())
      fValidContexts.erase(it);
}
void TGLWidget::ExtractViewport(Int_t *vp)const
{
   
   vp[0] = 0;
   vp[1] = 0;
   vp[2] = GetWidth();
   vp[3] = GetHeight();
}
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.