Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
TGLContext.cxx
Go to the documentation of this file.
1// @(#)root/gl:$Id$
2// Author: Timur Pocheptsov, Jun 2007
3
4/*************************************************************************
5 * Copyright (C) 1995-2004, Rene Brun and Fons Rademakers. *
6 * All rights reserved. *
7 * *
8 * For the licensing terms see $ROOTSYS/LICENSE. *
9 * For the list of contributors see $ROOTSYS/README/CREDITS. *
10 *************************************************************************/
11
12#include <memory>
13#include <stdexcept>
14#include <algorithm>
15#include <memory>
16
17#include "TVirtualX.h"
18#include "GuiTypes.h"
19#include "TString.h"
20#include "TError.h"
21
22#include "TROOT.h"
23#include "TVirtualMutex.h"
24
25#include "TGLContextPrivate.h"
26#include "RConfigure.h"
27#include "TGLIncludes.h"
28#include "TGLContext.h"
29#include "TGLWidget.h"
30#include "TGLFormat.h"
31#include "TGLUtil.h"
32
33#include "TGLFontManager.h"
34
35/** \class TGLContext
36\ingroup opengl
37This class encapsulates window-system specific information about a
38GL-context and alows their proper management in ROOT.
39*/
40
41
43
44////////////////////////////////////////////////////////////////////////////////
45/// TGLContext ctor "from" TGLWidget.
46/// Is shareDefault is true, the shareList is set from default
47/// context-identity. Otherwise the given shareList is used (can be
48/// null).
49/// Makes thread switching.
50
52 const TGLContext *shareList)
53 : fDevice(wid),
54 fFromCtor(kTRUE),
55 fValid(kFALSE),
56 fIdentity(nullptr)
57{
58 if (shareDefault)
60
61 if (!gVirtualX->IsCmdThread()) {
62 gROOT->ProcessLineFast(Form("((TGLContext *)0x%zx)->SetContext((TGLWidget *)0x%zx, (TGLContext *)0x%zx)",
63 (size_t)this, (size_t)wid, (size_t)shareList));
64 } else {
65
67
69 }
70
71 if (shareDefault)
73 else
74 fIdentity = shareList ? shareList->GetIdentity() : new TGLContextIdentity;
75
76 fIdentity->AddRef(this);
77
79}
80
81////////////////////////////////////////////////////////////////////////////////
82/// Initialize GLEW - static private function.
83/// Called immediately after creation of the first GL context.
84
86{
87 if (!fgGlewInitDone)
88 {
89 GLenum status = glewInit();
90 if (status != GLEW_OK)
91 Warning("TGLContext::GlewInit", "GLEW initalization failed.");
92 else if (gDebug > 0)
93 Info("TGLContext::GlewInit", "GLEW initalization successful.");
95 }
96}
97
98//==============================================================================
99#ifdef WIN32
100//==============================================================================
101
102namespace {
103
104 struct LayoutCompatible_t {
105 void *fDummy0;
106 void *fDummy1;
107 HWND *fPHwnd;
108 unsigned char fDummy2;
109 unsigned fDummy3;
110 unsigned short fDummy4;
111 unsigned short fDummy5;
112 void *fDummy6;
113 unsigned fDummy7:2;
114 };
115
116}
117
118////////////////////////////////////////////////////////////////////////////////
119///WIN32 gl-context creation. Defined as a member-function (this code removed from ctor)
120///to make WIN32/X11 separation cleaner.
121///This function is public only for calls via gROOT and called from ctor.
122
124{
125 if (!fFromCtor) {
126 Error("TGLContext::SetContext", "SetContext must be called only from ctor");
127 return;
128 }
129
130 fPimpl.reset(new TGLContextPrivate);
132 reinterpret_cast<LayoutCompatible_t *>(widget->GetId());
133 HWND hWND = *trick->fPHwnd;
134 HDC hDC = GetWindowDC(hWND);
135
136 if (!hDC) {
137 Error("TGLContext::SetContext", "GetWindowDC failed");
138 throw std::runtime_error("GetWindowDC failed");
139 }
140
142 if (HGLRC glContext = wglCreateContext(hDC)) {
143 if (shareList && !wglShareLists(shareList->fPimpl->fGLContext, glContext)) {
145 Error("TGLContext::SetContext", "Context sharing failed!");
146 throw std::runtime_error("Context sharing failed");
147 }
148 fPimpl->fHWND = hWND;
149 fPimpl->fHDC = hDC;
150 fPimpl->fGLContext = glContext;
151 } else {
152 Error("TGLContext::SetContext", "wglCreateContext failed");
153 throw std::runtime_error("wglCreateContext failed");
154 }
155
156 //Register context for "parent" gl-device.
157 fValid = kTRUE;
158 fDevice->AddContext(this);
160
161 dcGuard.Stop();
162}
163
164////////////////////////////////////////////////////////////////////////////////
165///If context is valid (TGLPaintDevice, for which context was created still exists),
166///make it current.
167
169{
170 if (!fValid) {
171 Error("TGLContext::MakeCurrent", "This context is invalid.");
172 return kFALSE;
173 }
174
175 if (!gVirtualX->IsCmdThread())
176 return Bool_t(gROOT->ProcessLineFast(Form("((TGLContext *)0x%zx)->MakeCurrent()", (size_t)this)));
177 else {
178
180
181 Bool_t rez = wglMakeCurrent(fPimpl->fHDC, fPimpl->fGLContext);
182 if (rez) {
183 if (!fgGlewInitDone)
184 GlewInit();
186 }
187 return rez;
188 }
189}
190
191////////////////////////////////////////////////////////////////////////////////
192///Reset current context.
193
195{
196 return wglMakeCurrent(0, 0);
197}
198
199////////////////////////////////////////////////////////////////////////////////
200///If context is valid (TGLPaintDevice, for which context was created still exists),
201///swap buffers (in case of P-buffer call glFinish()).
202
204{
205 if (!fValid) {
206 Error("TGLContext::SwapBuffers", "This context is invalid.");
207 return;
208 }
209
210 if (!gVirtualX->IsCmdThread())
211 gROOT->ProcessLineFast(Form("((TGLContext *)0x%zx)->SwapBuffers()", (size_t)this));
212 else {
213
215
216 if (fPimpl->fHWND)
218 else
219 glFinish();
220 }
221}
222
223////////////////////////////////////////////////////////////////////////////////
224///Make the context invalid and (do thread switch, if needed)
225///free resources.
226
228{
229 if (!gVirtualX->IsCmdThread()) {
230 gROOT->ProcessLineFast(Form("((TGLContext *)0x%zx)->Release()", (size_t)this));
231 return;
232 }
233
235
236 if (fPimpl->fHWND)
237 ReleaseDC(fPimpl->fHWND, fPimpl->fHDC);
238
240 wglDeleteContext(fPimpl->fGLContext);
241 fValid = kFALSE;
242}
243
244#elif defined(R__HAS_COCOA)
245
246////////////////////////////////////////////////////////////////////////////////
247///This function is public only for calls via gROOT and called from ctor.
248
250{
251 if (!fFromCtor) {
252 Error("TGLContext::SetContext", "SetContext must be called only from ctor");
253 return;
254 }
255
256 fPimpl.reset(new TGLContextPrivate);
257
258 fPimpl->fGLContext = gVirtualX->CreateOpenGLContext(widget->GetId(), shareList ? shareList->fPimpl->fGLContext : 0);
259 fPimpl->fWindowID = widget->GetId();
260
261 fValid = kTRUE;
262 fDevice->AddContext(this);
264}
265
266////////////////////////////////////////////////////////////////////////////////
267///If context is valid (TGLPaintDevice, for which context was created still exists),
268///make it current.
269
271{
272 if (!fValid) {
273 Error("TGLContext::MakeCurrent", "This context is invalid.");
274 return kFALSE;
275 }
276
277 const Bool_t rez = gVirtualX->MakeOpenGLContextCurrent(fPimpl->fGLContext, fPimpl->fWindowID);
278 if (rez) {
279 if (!fgGlewInitDone)
280 GlewInit();
282
283 }
284
285 return rez;
286}
287
288////////////////////////////////////////////////////////////////////////////////
289///Reset current context.
290
292{
293 return kFALSE;
294}
295
296////////////////////////////////////////////////////////////////////////////////
297///If context is valid (TGLPaintDevice, for which context was created still exists),
298///swap buffers (in case of P-buffer call glFinish()).
299
301{
302 if (!fValid) {
303 Error("TGLContext::SwapBuffers", "This context is invalid.");
304 return;
305 }
306
307 gVirtualX->FlushOpenGLBuffer(fPimpl->fGLContext);
308}
309
310////////////////////////////////////////////////////////////////////////////////
311///Make the context invalid and free resources.
312
314{
316 gVirtualX->DeleteOpenGLContext(fPimpl->fGLContext);
317 fValid = kFALSE;
318}
319
320//==============================================================================
321#else // X11
322//==============================================================================
323
324////////////////////////////////////////////////////////////////////////////////
325///X11 gl-context creation. Defined as a member-function (this code removed from ctor)
326///to make WIN32/X11 separation cleaner.
327///This function is public only for calls via gROOT and called from ctor.
328
330{
331 if (!fFromCtor) {
332 Error("TGLContext::SetContext", "SetContext must be called only from ctor");
333 return;
334 }
335
336 fPimpl = std::make_unique<TGLContextPrivate>();
337 Display *dpy = static_cast<Display *>(widget->GetInnerData().first);
338 XVisualInfo *visInfo = static_cast<XVisualInfo *>(widget->GetInnerData().second);
339
340 GLXContext glCtx = shareList ? glXCreateContext(dpy, visInfo, shareList->fPimpl->fGLContext, True)
341 : glXCreateContext(dpy, visInfo, None, True);
342
343 if (!glCtx) {
344 Error("TGLContext::SetContext", "glXCreateContext failed!");
345 throw std::runtime_error("glXCreateContext failed!");
346 }
347
348 fPimpl->fDpy = dpy;
349 fPimpl->fVisualInfo = visInfo;
350 fPimpl->fGLContext = glCtx;
351 fPimpl->fWindowID = widget->GetId();
352
353 fValid = kTRUE;
354 fDevice->AddContext(this);
356}
357
358////////////////////////////////////////////////////////////////////////////////
359///If context is valid (TGLPaintDevice, for which context was created still exists),
360///make it current.
361
363{
364 if (!fValid) {
365 Error("TGLContext::MakeCurrent", "This context is invalid.");
366 return kFALSE;
367 }
368
369 if (fPimpl->fWindowID != 0) {
370 const Bool_t rez = glXMakeCurrent(fPimpl->fDpy, fPimpl->fWindowID,
371 fPimpl->fGLContext);
372 if (rez) {
373 if (!fgGlewInitDone)
374 GlewInit();
376 }
377 return rez;
378 }
379
380 return kFALSE;
381}
382
383////////////////////////////////////////////////////////////////////////////////
384///Reset current context.
385
387{
388 return glXMakeCurrent(fPimpl->fDpy, None, nullptr);
389}
390
391////////////////////////////////////////////////////////////////////////////////
392///If context is valid (TGLPaintDevice, for which context was created still exists),
393///swap buffers (in case of P-buffer call glFinish()).
394
396{
397 if (!fValid) {
398 Error("TGLContext::SwapCurrent", "This context is invalid.");
399 return;
400 }
401
402 if (fPimpl->fWindowID != 0)
403 glXSwapBuffers(fPimpl->fDpy, fPimpl->fWindowID);
404 else
405 glFinish();
406}
407
408////////////////////////////////////////////////////////////////////////////////
409///Make the context invalid and (do thread switch, if needed)
410///free resources.
411
413{
415 glXDestroyContext(fPimpl->fDpy, fPimpl->fGLContext);
416 fValid = kFALSE;
417}
418
419//==============================================================================
420#endif
421//==============================================================================
422
423////////////////////////////////////////////////////////////////////////////////
424///TGLContext dtor. If it's called before TGLPaintDevice's dtor
425///(context is valid) resource will be freed and context
426///un-registered.
427
429{
430 if (fValid) {
431 Release();
432 fDevice->RemoveContext(this);
433 }
434
435 fIdentity->Release(this);
436}
437
438////////////////////////////////////////////////////////////////////////////////
439///We can have several shared contexts,
440///and gl-scene wants to know, if some context
441///(defined by its identity) can be used.
442
447
448////////////////////////////////////////////////////////////////////////////////
449///Ask TGLContextPrivate to lookup context in its internal map.
450
455
456
457/** \class TGLContextIdentity
458\ingroup opengl
459Identifier of a shared GL-context.
460Objects shared among GL-contexts include:
461display-list definitions, texture objects and shader programs.
462*/
463
464
466
467////////////////////////////////////////////////////////////////////////////////
468/// Constructor.
469
471fFontManager(nullptr), fCnt(0), fClientCnt(0)
472{
473}
474
475////////////////////////////////////////////////////////////////////////////////
476/// Destructor.
477
482
483////////////////////////////////////////////////////////////////////////////////
484///Add context ctx to the list of references.
485
487{
488 ++fCnt;
489 fCtxs.push_back(ctx);
490}
491
492////////////////////////////////////////////////////////////////////////////////
493///Remove context ctx from the list of references.
494
496{
497 CtxList_t::iterator i = std::find(fCtxs.begin(), fCtxs.end(), ctx);
498 if (i != fCtxs.end())
499 {
500 fCtxs.erase(i);
501 --fCnt;
502 CheckDestroy();
503 }
504 else
505 {
506 Error("TGLContextIdentity::Release", "unregistered context.");
507 }
508}
509
510////////////////////////////////////////////////////////////////////////////////
511///Remember dl range for deletion in next MakeCurrent or dtor execution.
512
517
518////////////////////////////////////////////////////////////////////////////////
519///Delete GL resources registered for destruction.
520
522{
523 if (!fDLTrash.empty())
524 {
525 for (DLTrashIt_t it = fDLTrash.begin(), e = fDLTrash.end(); it != e; ++it)
526 glDeleteLists(it->first, it->second);
527 fDLTrash.clear();
528 }
529
530 if (fFontManager)
532}
533
534////////////////////////////////////////////////////////////////////////////////
535///Find identitfy of current context. Static.
536
538{
540 return ctx ? ctx->GetIdentity() : nullptr;
541}
542
543////////////////////////////////////////////////////////////////////////////////
544///Get identity of a default Gl context. Static.
545
552
553////////////////////////////////////////////////////////////////////////////////
554///Get the first GL context with the default identity.
555///Can return zero, but that's OK, too. Static.
556
558{
559 if (fgDefaultIdentity == nullptr || fgDefaultIdentity->fCtxs.empty())
560 return nullptr;
561 return fgDefaultIdentity->fCtxs.front();
562}
563
564////////////////////////////////////////////////////////////////////////////////
565///Get the free-type font-manager associated with this context-identity.
566
572
573////////////////////////////////////////////////////////////////////////////////
574///Private function called when reference count is reduced.
575
577{
578 if (fCnt <= 0 && fClientCnt <= 0)
579 {
580 if (this == fgDefaultIdentity)
581 fgDefaultIdentity = nullptr;
582 delete this;
583 }
584}
#define e(i)
Definition RSha256.hxx:103
size_t size(const MatrixT &matrix)
retrieve the size of a square matrix
bool Bool_t
Boolean (0=false, 1=true) (bool)
Definition RtypesCore.h:77
constexpr Bool_t kFALSE
Definition RtypesCore.h:108
constexpr Bool_t kTRUE
Definition RtypesCore.h:107
ROOT::Detail::TRangeCast< T, true > TRangeDynCast
TRangeDynCast is an adapter class that allows the typed iteration through a TCollection.
void Info(const char *location, const char *msgfmt,...)
Use this function for informational messages.
Definition TError.cxx:241
void Error(const char *location, const char *msgfmt,...)
Use this function in case an error occurred.
Definition TError.cxx:208
void Warning(const char *location, const char *msgfmt,...)
Use this function in warning situations.
Definition TError.cxx:252
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize wid
Int_t gDebug
Global variable setting the debug level. Set to 0 to disable, increase it in steps of 1 to increase t...
Definition TROOT.cxx:627
R__EXTERN TVirtualMutex * gROOTMutex
Definition TROOT.h:63
#define gROOT
Definition TROOT.h:411
char * Form(const char *fmt,...)
Formats a string in a circular formatting buffer.
Definition TString.cxx:2495
#define R__LOCKGUARD(mutex)
#define gVirtualX
Definition TVirtualX.h:337
Identifier of a shared GL-context.
Definition TGLContext.h:81
virtual ~TGLContextIdentity()
Destructor.
static TGLContextIdentity * GetDefaultIdentity()
Get identity of a default Gl context. Static.
void CheckDestroy()
Private function called when reference count is reduced.
TGLContextIdentity()
Constructor.
std::pair< UInt_t, Int_t > DLRange_t
Definition TGLContext.h:117
TGLFontManager * fFontManager
Definition TGLContext.h:84
static TGLContextIdentity * fgDefaultIdentity
Definition TGLContext.h:126
void DeleteGLResources()
Delete GL resources registered for destruction.
void Release(TGLContext *ctx)
Remove context ctx from the list of references.
DLTrash_t::const_iterator DLTrashIt_t
Definition TGLContext.h:119
static TGLContextIdentity * GetCurrent()
Find identitfy of current context. Static.
TGLFontManager * GetFontManager()
Get the free-type font-manager associated with this context-identity.
void AddRef(TGLContext *ctx)
Add context ctx to the list of references.
void RegisterDLNameRangeToWipe(UInt_t base, Int_t size)
Remember dl range for deletion in next MakeCurrent or dtor execution.
static TGLContext * GetDefaultContextAny()
Get the first GL context with the default identity.
static void RegisterContext(TGLContext *ctx)
Register gl-context to find it later as current (GetCurrentContext)
static void RemoveContext(TGLContext *ctx)
Un-register deleted context.
static TGLContext * GetCurrentContext()
Ask wgl what HGLRC is current and look up corresponding TGLContext.
This class encapsulates window-system specific information about a GL-context and alows their proper ...
Definition TGLContext.h:31
Bool_t fValid
Definition TGLContext.h:41
void Release()
Make the context invalid and (do thread switch, if needed) free resources.
void SwapBuffers()
If context is valid (TGLPaintDevice, for which context was created still exists), swap buffers (in ca...
TGLContextIdentity * GetIdentity() const
We can have several shared contexts, and gl-scene wants to know, if some context (defined by its iden...
static Bool_t fgGlewInitDone
Definition TGLContext.h:45
std::unique_ptr< TGLContextPrivate > fPimpl
Definition TGLContext.h:38
TGLContext(TGLWidget *glWidget, Bool_t shareDefault=kTRUE, const TGLContext *shareList=nullptr)
TGLContext ctor "from" TGLWidget.
virtual ~TGLContext()
TGLContext dtor.
Bool_t MakeCurrent()
If context is valid (TGLPaintDevice, for which context was created still exists), make it current.
void SetContext(TGLWidget *widget, const TGLContext *shareList)
X11 gl-context creation.
static void GlewInit()
Initialize GLEW - static private function.
Bool_t ClearCurrent()
Reset current context.
TGLContextIdentity * fIdentity
Definition TGLContext.h:43
TGLPaintDevice * fDevice
Definition TGLContext.h:37
static TGLContext * GetCurrent()
Ask TGLContextPrivate to lookup context in its internal map.
Bool_t fFromCtor
Definition TGLContext.h:40
A FreeType GL font manager.
void ClearFontTrash()
Delete FTFFont objects registered for destruction.
virtual void AddContext(TGLContext *ctx)=0
virtual void RemoveContext(TGLContext *ctx)=0
GL window with context.
Definition TGLWidget.h:28
TOneArgGuard< Func, Arg > make_guard(Func f, Arg a)
Definition TGLUtil.h:1329