26 #include "RConfigure.h"
73 TGLWidget* TGLWidget::CreateDummy()
75 TGLFormat format(Rgl::kNone);
77 return Create(format, gClient->GetDefaultRoot(), kFALSE, kFALSE, 0, 1, 1);
83 TGLWidget* TGLWidget::Create(
const TGWindow* parent, Bool_t selectInput,
84 Bool_t shareDefault,
const TGLPaintDevice *shareDevice,
85 UInt_t width, UInt_t height)
89 return Create(format, parent, selectInput, shareDefault, shareDevice,
96 TGLWidget* TGLWidget::Create(
const TGLFormat &format,
97 const TGWindow* parent, Bool_t selectInput,
98 Bool_t shareDefault,
const TGLPaintDevice *shareDevice,
99 UInt_t width, UInt_t height)
102 TGLUtil::InitializeIfNeeded();
104 std::pair<void *, void *> innerData;
106 Window_t wid = CreateWindow(parent, format, width, height, innerData);
108 TGLWidget* glw =
new TGLWidget(wid, parent, selectInput);
111 glw->fWindowIndex = (Int_t) innerData.second;
112 #elif defined(R__HAS_COCOA)
113 glw->fWindowIndex = wid;
115 glw->fWindowIndex = gVirtualX->AddWindow(wid, width, height);
116 glw->fInnerData = innerData;
118 glw->fGLFormat = format;
123 glw->fGLContext =
new TGLContext
124 (glw, shareDefault, shareDevice && !shareDefault ? shareDevice->GetContext() : 0);
126 catch (
const std::exception &)
132 glw->fFromInit = kFALSE;
140 TGLWidget::TGLWidget(Window_t glw,
const TGWindow* p, Bool_t selectInput)
141 : TGFrame(gClient, glw, p),
144 fGLFormat(Rgl::kNone),
150 gVirtualX->GrabButton(GetId(), kAnyButton, kAnyModifier,
151 kButtonPressMask | kButtonReleaseMask, kNone, kNone);
152 gVirtualX->SelectInput(GetId(), kKeyPressMask | kKeyReleaseMask | kExposureMask |
153 kPointerMotionMask | kStructureNotifyMask | kFocusChangeMask |
154 kEnterWindowMask | kLeaveWindowMask);
155 gVirtualX->SetInputFocus(GetId());
162 TGLWidget::~TGLWidget()
166 XFree(fInnerData.second);
169 if (fValidContexts.size() > 1u) {
170 Warning(
"~TGLWidget",
"There are some gl-contexts connected to this gl device"
171 "which have longer lifetime than lifetime of gl-device");
174 std::set<TGLContext *>::iterator it = fValidContexts.begin();
175 for (; it != fValidContexts.end(); ++it) {
180 gVirtualX->SelectWindow(fWindowIndex);
181 gVirtualX->CloseWindow();
187 void TGLWidget::InitGL()
194 void TGLWidget::PaintGL()
201 Bool_t TGLWidget::MakeCurrent()
203 return fGLContext->MakeCurrent();
209 Bool_t TGLWidget::ClearCurrent()
211 return fGLContext->ClearCurrent();
217 void TGLWidget::SwapBuffers()
219 fGLContext->SwapBuffers();
225 const TGLContext *TGLWidget::GetContext()
const
233 const TGLFormat *TGLWidget::GetPixelFormat()
const
241 std::pair<void *, void *> TGLWidget::GetInnerData()
const
249 void TGLWidget::AddContext(TGLContext *ctx)
251 fValidContexts.insert(ctx);
257 void TGLWidget::RemoveContext(TGLContext *ctx)
259 std::set<TGLContext *>::iterator it = fValidContexts.find(ctx);
260 if (it != fValidContexts.end())
261 fValidContexts.erase(it);
267 void TGLWidget::ExtractViewport(Int_t *vp)
const
285 struct LayoutCompatible_t {
289 unsigned char fDummy2;
291 unsigned short fDummy4;
292 unsigned short fDummy5;
297 void fill_pfd(PIXELFORMATDESCRIPTOR *pfd,
const TGLFormat &request)
299 pfd->nSize =
sizeof(PIXELFORMATDESCRIPTOR);
301 pfd->dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL;
302 if (request.IsDoubleBuffered())
303 pfd->dwFlags |= PFD_DOUBLEBUFFER;
304 pfd->iPixelType = PFD_TYPE_RGBA;
305 pfd->cColorBits = 24;
306 if (UInt_t acc = request.GetAccumSize())
307 pfd->cAccumBits = acc;
308 if (UInt_t depth = request.GetDepthSize())
309 pfd->cDepthBits = depth;
310 if (UInt_t stencil = request.GetStencilSize())
311 pfd->cStencilBits = stencil;
314 void check_pixel_format(Int_t pixIndex, HDC hDC, TGLFormat &request)
316 PIXELFORMATDESCRIPTOR pfd = {};
318 if (!DescribePixelFormat(hDC, pixIndex,
sizeof pfd, &pfd)) {
319 Warning(
"TGLContext::SetContext",
"DescribePixelFormat failed");
324 request.SetAccumSize(pfd.cAccumBits);
327 request.SetDepthSize(pfd.cDepthBits);
329 if (pfd.cStencilBits)
330 request.SetStencilSize(pfd.cStencilBits);
346 Window_t TGLWidget::CreateWindow(
const TGWindow* parent,
const TGLFormat& ,
347 UInt_t width, UInt_t height,
348 std::pair<void *, void *>& innerData)
350 Int_t widx = gVirtualX->InitWindow((ULong_t)parent->GetId());
351 innerData.second = (
void*) widx;
352 Window_t win = gVirtualX->GetWindowID(widx);
353 gVirtualX->ResizeWindow(win, width, height);
361 void TGLWidget::SetFormat()
364 Error(
"TGLWidget::SetFormat",
"Sorry, you should not call this function");
367 if (!gVirtualX->IsCmdThread())
368 gROOT->ProcessLineFast(Form(
"((TGLWidget *)0x%lx)->SetFormat()",
this));
370 R__LOCKGUARD(gROOTMutex);
372 LayoutCompatible_t *trick =
373 reinterpret_cast<LayoutCompatible_t *
>(GetId());
374 HWND hWND = *trick->fPHwnd;
375 HDC hDC = GetWindowDC(hWND);
378 Error(
"TGLWidget::SetFormat",
"GetWindowDC failed");
379 throw std::runtime_error(
"GetWindowDC failed");
382 const Rgl::TGuardBase &dcGuard = Rgl::make_guard(ReleaseDC, hWND, hDC);
383 PIXELFORMATDESCRIPTOR pfd = {};
384 fill_pfd(&pfd, fGLFormat);
386 if (
const Int_t pixIndex = ChoosePixelFormat(hDC, &pfd)) {
387 check_pixel_format(pixIndex, hDC, fGLFormat);
389 if (!SetPixelFormat(hDC, pixIndex, &pfd)) {
390 Error(
"TGLWidget::SetFormat",
"SetPixelFormat failed");
391 throw std::runtime_error(
"SetPixelFormat failed");
394 Error(
"TGLWidget::SetFormat",
"ChoosePixelFormat failed");
395 throw std::runtime_error(
"ChoosePixelFormat failed");
399 #elif defined(R__HAS_COCOA) //MacOSX with Cocoa enabled.
406 Window_t TGLWidget::CreateWindow(
const TGWindow* parent,
const TGLFormat &format,
407 UInt_t width, UInt_t height,
408 std::pair<void *, void *>& )
410 typedef std::pair<UInt_t, Int_t> component_type;
412 std::vector<component_type>formatComponents;
414 if (format.HasDepth())
415 formatComponents.push_back(component_type(Rgl::kDepth, format.GetDepthSize()));
416 if (format.HasStencil())
417 formatComponents.push_back(component_type(Rgl::kStencil, format.GetStencilSize()));
418 if (format.HasAccumBuffer())
419 formatComponents.push_back(component_type(Rgl::kAccum, format.GetAccumSize()));
420 if (format.IsDoubleBuffered())
421 formatComponents.push_back(component_type(Rgl::kDoubleBuffer, 0));
422 if (format.IsStereo())
423 formatComponents.push_back(component_type(Rgl::kStereo, 0));
424 if (format.HasMultiSampling())
425 formatComponents.push_back(component_type(Rgl::kMultiSample, format.GetSamples()));
427 return gVirtualX->CreateOpenGLWindow(parent->GetId(), width, height, formatComponents);
434 void TGLWidget::SetFormat()
444 void fill_format(std::vector<Int_t> &format,
const TGLFormat &request)
446 format.push_back(GLX_RGBA);
447 format.push_back(GLX_RED_SIZE);
449 format.push_back(GLX_GREEN_SIZE);
451 format.push_back(GLX_BLUE_SIZE);
454 if (request.IsDoubleBuffered())
455 format.push_back(GLX_DOUBLEBUFFER);
457 if (request.HasDepth()) {
458 format.push_back(GLX_DEPTH_SIZE);
459 format.push_back(request.GetDepthSize());
462 if (request.HasStencil()) {
463 format.push_back(GLX_STENCIL_SIZE);
464 format.push_back(request.GetStencilSize());
467 if (request.HasAccumBuffer()) {
468 format.push_back(GLX_ACCUM_RED_SIZE);
470 format.push_back(GLX_ACCUM_GREEN_SIZE);
472 format.push_back(GLX_ACCUM_BLUE_SIZE);
476 if (request.IsStereo()) {
477 format.push_back(GLX_STEREO);
480 if (request.HasMultiSampling())
482 format.push_back(GLX_SAMPLE_BUFFERS_ARB);
484 format.push_back(GLX_SAMPLES_ARB);
485 format.push_back(request.GetSamples());
488 format.push_back(None);
499 Window_t TGLWidget::CreateWindow(
const TGWindow* parent,
const TGLFormat &format,
500 UInt_t width, UInt_t height,
501 std::pair<void *, void *>& innerData)
503 std::vector<Int_t> glxfmt;
504 fill_format(glxfmt, format);
506 Display *dpy =
reinterpret_cast<Display *
>(gVirtualX->GetDisplay());
508 ::Error(
"TGLWidget::CreateWindow",
"Display is not set!");
509 throw std::runtime_error(
"Display is not set!");
511 XVisualInfo *visInfo = glXChooseVisual(dpy, DefaultScreen(dpy), &glxfmt[0]);
514 ::Error(
"TGLWidget::CreateWindow",
"No good OpenGL visual found!");
515 throw std::runtime_error(
"No good OpenGL visual found!");
518 Window_t winID = parent->GetId();
520 XSetWindowAttributes attr;
521 attr.colormap = XCreateColormap(dpy, winID, visInfo->visual, AllocNone);
522 attr.background_pixel = 0;
523 attr.event_mask = NoEventMask;
524 attr.backing_store = Always;
525 attr.bit_gravity = NorthWestGravity;
527 ULong_t mask = CWBackPixel | CWColormap | CWEventMask | CWBackingStore | CWBitGravity;
528 Window glWin = XCreateWindow(dpy, winID, 0, 0, width, height, 0,
530 InputOutput, visInfo->visual, mask, &attr);
532 innerData.first = dpy;
533 innerData.second = visInfo;
542 void TGLWidget::SetFormat()
558 void TGLWidget::SetEventHandler(TGEventHandler *eh)
566 Bool_t TGLWidget::HandleCrossing(Event_t *ev)
568 if (!gVirtualX->IsCmdThread()) {
569 gROOT->ProcessLineFast(Form(
"((TGLWidget *)0x%lx)->HandleCrossing((Event_t *)0x%lx)", (ULong_t)
this, (ULong_t)ev));
572 R__LOCKGUARD(gROOTMutex);
574 if ((ev->fType == kEnterNotify) &&
575 (!gVirtualX->InheritsFrom(
"TGX11")) &&
576 (gVirtualX->GetInputFocus() != GetId())) {
577 gVirtualX->SetInputFocus(GetId());
580 return fEventHandler->HandleCrossing(ev);
587 Bool_t TGLWidget::HandleButton(Event_t *ev)
589 if (!gVirtualX->IsCmdThread()) {
590 gROOT->ProcessLineFast(Form(
"((TGLWidget *)0x%lx)->HandleButton((Event_t *)0x%lx)", (ULong_t)
this, (ULong_t)ev));
593 R__LOCKGUARD(gROOTMutex);
596 return fEventHandler->HandleButton(ev);
603 Bool_t TGLWidget::HandleDoubleClick(Event_t *ev)
605 if (!gVirtualX->IsCmdThread()) {
606 gROOT->ProcessLineFast(Form(
"((TGLWidget *)0x%lx)->HandleDoubleClick((Event_t *)0x%lx)", (ULong_t)
this, (ULong_t)ev));
609 R__LOCKGUARD(gROOTMutex);
612 return fEventHandler->HandleDoubleClick(ev);
619 Bool_t TGLWidget::HandleConfigureNotify(Event_t *ev)
621 if (!gVirtualX->IsCmdThread()) {
622 gROOT->ProcessLineFast(Form(
"((TGLWidget *)0x%lx)->HandleConfigureNotify((Event_t *)0x%lx)", (ULong_t)
this, (ULong_t)ev));
625 R__LOCKGUARD(gROOTMutex);
627 if (fEventHandler && fEventHandler->HandleConfigureNotify(ev))
629 TGFrame::HandleConfigureNotify(ev);
638 Bool_t TGLWidget::HandleFocusChange(Event_t *ev)
640 if (!gVirtualX->IsCmdThread()) {
641 gROOT->ProcessLineFast(Form(
"((TGLWidget *)0x%lx)->HandleFocusChange((Event_t *)0x%lx)", (ULong_t)
this, (ULong_t)ev));
644 R__LOCKGUARD(gROOTMutex);
647 return fEventHandler->HandleFocusChange(ev);
654 Bool_t TGLWidget::HandleKey(Event_t *ev)
656 if (!gVirtualX->IsCmdThread()) {
657 gROOT->ProcessLineFast(Form(
"((TGLWidget *)0x%lx)->HandleKey((Event_t *)0x%lx)", (ULong_t)
this, (ULong_t)ev));
660 R__LOCKGUARD(gROOTMutex);
663 return fEventHandler->HandleKey(ev);
670 Bool_t TGLWidget::HandleMotion(Event_t *ev)
672 if (!gVirtualX->IsCmdThread()) {
673 gROOT->ProcessLineFast(Form(
"((TGLWidget *)0x%lx)->HandleMotion((Event_t *)0x%lx)", (ULong_t)
this, (ULong_t)ev));
676 R__LOCKGUARD(gROOTMutex);
679 return fEventHandler->HandleMotion(ev);
686 void TGLWidget::DoRedraw()
689 return fEventHandler->Repaint();