Logo ROOT   6.12/07
Reference Guide
TGWin32GL.cxx
Go to the documentation of this file.
1 // @(#)root/win32gdk:$Id$
2 // Author: Valeriy Onuchin(TGWin32GL)/ Timur Pocheptsov (TGWin32GLManager)
3 
4 /*************************************************************************
5  * Copyright (C) 1995-2000, 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 /** \class TGWin32GL
13 \ingroup win32
14 
15 The TGWin32GL is win32gdk implementation of TVirtualGLImp class.
16 */
17 
18 #include <deque>
19 
20 #include "TGWin32GL.h"
21 #include "TGWin32VirtualGLProxy.h"
22 #include "TVirtualViewer3D.h"
23 #include "TVirtualX.h"
24 #include "TError.h"
25 #include "TROOT.h"
26 
27 #include "Windows4Root.h"
28 #include "gdk/gdk.h"
29 #include "gdk/win32/gdkwin32.h"
30 
31 #include <GL/gl.h>
32 #include <GL/glu.h>
33 
34 
35 // Win32 GL Manager's stuff
36 
37 struct TGWin32GLManager::TGLContext {
38  Int_t fWindowIndex;
39  Int_t fPixmapIndex;
40  //
41  HDC fDC;
42  HBITMAP fHBitmap;
43  HGLRC fGLContext;
44  //
45  UInt_t fW;
46  UInt_t fH;
47  //
48  Int_t fX;
49  Int_t fY;
50  //
51  Bool_t fHighColor;
52  //
53  Bool_t fDirect;
54  //
55  UChar_t *fDIBData;
56  //
57  TGLContext *fNextFreeContext;
58 };
59 
60 namespace {
61 
62  //RAII class for HDC, returned by CreateCompatibleDC
63  class CDCGuard {
64  private:
65  HDC fHDC;
66 
67  CDCGuard(const CDCGuard &);
68  CDCGuard &operator = (const CDCGuard &);
69 
70  public:
71  explicit CDCGuard(HDC hDC) : fHDC(hDC)
72  {}
73  ~CDCGuard()
74  {
75  if (fHDC)
76  DeleteDC(fHDC);
77  }
78  void Stop()
79  {
80  fHDC = 0;
81  }
82  };
83 
84  //RAII class for HDC, returned by GetWindowDC
85  class WDCGuard {
86  private:
87  HDC fHDC;
88  Window_t fWinID;
89 
90  WDCGuard(const WDCGuard &);
91  WDCGuard &operator = (const WDCGuard &);
92 
93  public:
94  WDCGuard(HDC hDC, Window_t winID) : fHDC(hDC), fWinID(winID)
95  {}
96  ~WDCGuard()
97  {
98  if (fHDC)
99  ReleaseDC((HWND)GDK_DRAWABLE_XID((GdkWindow *)fWinID), fHDC);
100  }
101  void Stop()
102  {
103  fHDC = 0;
104  }
105  };
106 
107  //RAII class for HBITMAP
108  class BMPGuard {
109  private:
110  HBITMAP fBMP;
111 
112  BMPGuard(const BMPGuard &);
113  BMPGuard &operator = (const BMPGuard &);
114 
115  public:
116  explicit BMPGuard(HBITMAP bmp) : fBMP(bmp)
117  {}
118  ~BMPGuard()
119  {
120  if (fBMP)
121  DeleteObject(fBMP);
122  }
123  void Stop()
124  {
125  fBMP = 0;
126  }
127  };
128 
129  //RAII class for HGLRC
130  class WGLGuard {
131  private:
132  HGLRC fCtx;
133 
134  WGLGuard(const WGLGuard &);
135  WGLGuard &operator = (const WGLGuard &);
136 
137  public:
138  explicit WGLGuard(HGLRC glrc) : fCtx(glrc)
139  {}
140  ~WGLGuard()
141  {
142  if (fCtx)
143  wglDeleteContext(fCtx);
144  }
145  void Stop()
146  {
147  fCtx = 0;
148  }
149  };
150 }
151 
152 const PIXELFORMATDESCRIPTOR
154  sizeof doubleBufferDesc, // size of this pfd
155  1, // version number
156  PFD_DRAW_TO_WINDOW | // support window
157  PFD_SUPPORT_OPENGL | // support OpenGL
158  PFD_DOUBLEBUFFER, // double buffered
159  PFD_TYPE_RGBA, // RGBA type
160  24, // 24-bit color depth
161  0, 0, 0, 0, 0, 0, // color bits ignored
162  0, // no alpha buffer
163  0, // shift bit ignored
164  0, // no accumulation buffer
165  0, 0, 0, 0, // accum bits ignored
166  32, // 32-bit z-buffer
167  8, // stencil buffer depth
168  0, // no auxiliary buffer
169  PFD_MAIN_PLANE // main layer
170 };
171 
172 const PIXELFORMATDESCRIPTOR
174  sizeof singleScreenDesc, // size of this pfd
175  1, // version number
176  PFD_DRAW_TO_BITMAP | // draw into bitmap
177  PFD_SUPPORT_OPENGL, // support OpenGL
178  PFD_TYPE_RGBA, // RGBA type
179  24, // 24-bit color depth
180  0, 0, 0, 0, 0, 0, // color bits ignored
181  0, // no alpha buffer
182  0, // shift bit ignored
183  0, // no accumulation buffer
184  0, 0, 0, 0, // accum bits ignored
185  32, // 32-bit z-buffer
186  8, // stencil buffer depth
187  0, // no auxiliary buffer
188  PFD_MAIN_PLANE // main layer
189 };
190 
191 class TGWin32GLManager::TGWin32GLImpl {
192 public:
193  TGWin32GLImpl() : fNextFreeContext(0)
194  {}
195  ~TGWin32GLImpl();
196  std::deque<TGLContext> fGLContexts;
197  TGLContext *fNextFreeContext;
198 };
199 
200 TGWin32GLManager::TGWin32GLImpl::~TGWin32GLImpl()
201 {
202  //all devices should be destroyed at this moment
203  std::deque<TGLContext>::size_type i = 0;
204 
205  for (; i < fGLContexts.size(); ++i) {
206  TGLContext &ctx = fGLContexts[i];
207 
208  if (ctx.fGLContext) {
209  //gl context (+DIB, if exists) must be destroyed from outside, by pad.
210  ::Warning("TGWin32GLManager::~TGLWin32GLManager", "You forget to destroy gl-context %d\n", i);
211  //destroy hdc and glrc, pixmap will be destroyed by TVirtualX
212  if (ctx.fPixmapIndex != -1) {
213  gVirtualX->SelectWindow(ctx.fPixmapIndex);
214  gVirtualX->ClosePixmap();
215  }
216 
217  wglDeleteContext(ctx.fGLContext);
218  ReleaseDC((HWND)GDK_DRAWABLE_XID((GdkWindow *)gVirtualX->GetWindowID(ctx.fWindowIndex)),
219  ctx.fDC);
220  }
221  }
222 }
223 
225 
226 ////////////////////////////////////////////////////////////////////////////////
227 
229 {
231  gROOT->GetListOfSpecials()->AddLast(this);
232  gGLManager = this;
233 }
234 
235 ////////////////////////////////////////////////////////////////////////////////
236 
238 {
239  delete fPimpl;
240 }
241 
242 ////////////////////////////////////////////////////////////////////////////////
243 
245 {
246  return gVirtualX->InitWindow(winID);
247 }
248 
249 ////////////////////////////////////////////////////////////////////////////////
250 ///winInd is TGWin32 index, returned by previous call gGLManager->InitGLWindow
251 ///returns descripto (index) of gl context or -1 if failed
252 
254 {
255  Window_t winID = gVirtualX->GetWindowID(winInd);
256  HDC hDC = GetWindowDC((HWND)GDK_DRAWABLE_XID((GdkWindow *)winID));
257 
258  if (!hDC) {
259  Error("CreateGLContext", "GetWindowDC failed\n");
260  return -1;
261  }
262 
263  WDCGuard dcGuard(hDC, winID);
264 
265  if (Int_t pixFormat = ChoosePixelFormat(hDC, &doubleBufferDesc)) {
266  if (SetPixelFormat(hDC, pixFormat, &doubleBufferDesc)) {
267  HGLRC glCtx = wglCreateContext(hDC);
268 
269  if (!glCtx) {
270  Error("CreateGLContext", "wglCreateContext failed\n");
271  return -1;
272  }
273 
274  TGLContext newDevice = {winInd, -1, hDC, 0, glCtx};
275  PIXELFORMATDESCRIPTOR testFormat = {};
276  DescribePixelFormat(hDC, pixFormat, sizeof testFormat, &testFormat);
277  newDevice.fHighColor = testFormat.cColorBits < 24 ? kTRUE : kFALSE;
278 
279  if (TGLContext *ctx = fPimpl->fNextFreeContext) {
280  Int_t ind = ctx->fWindowIndex;
281  fPimpl->fNextFreeContext = fPimpl->fNextFreeContext->fNextFreeContext;
282  *ctx = newDevice;
283  dcGuard.Stop();
284  return ind;
285  } else {
286  WGLGuard wglGuard(glCtx);
287  fPimpl->fGLContexts.push_back(newDevice);
288  wglGuard.Stop();
289  dcGuard.Stop();
290  return fPimpl->fGLContexts.size() - 1;
291  }
292  } else
293  Error("CreateGLContext", "SetPixelFormat failed\n");
294  } else
295  Error("CreateGLContext", "ChoosePixelFormat failed\n");
296 
297  return -1;
298 }
299 
300 ////////////////////////////////////////////////////////////////////////////////
301 ///Create DIB section to read GL buffer into
302 
303 Bool_t TGWin32GLManager::CreateDIB(TGLContext &ctx)const
304 {
305  HDC dibDC = CreateCompatibleDC(0);
306 
307  if (!dibDC) {
308  Error("CreateDIB", "CreateCompatibleDC failed\n");
309  return kFALSE;
310  }
311 
312  CDCGuard dcGuard(dibDC);
313 
314  BITMAPINFOHEADER bmpHeader = {sizeof bmpHeader, ctx.fW, ctx.fH, 1, 32, BI_RGB};
315  void *bmpCnt = 0;
316  HBITMAP hDIB = CreateDIBSection(dibDC, (BITMAPINFO*)&bmpHeader, DIB_RGB_COLORS, &bmpCnt, 0, 0);
317 
318  if (!hDIB) {
319  Error("CreateDIB", "CreateDIBSection failed\n");
320  return kFALSE;
321  }
322 
323  BMPGuard bmpGuard(hDIB);
324 
325  ctx.fPixmapIndex = gVirtualX->AddPixmap((ULong_t)hDIB, ctx.fW, ctx.fH);
326  ctx.fHBitmap = hDIB;
327  ctx.fDIBData = static_cast<UChar_t *>(bmpCnt);
328 
329  bmpGuard.Stop();
330 
331  return kTRUE;
332 }
333 
334 ////////////////////////////////////////////////////////////////////////////////
335 
337 {
338  TGLContext &ctx = fPimpl->fGLContexts[ctxInd];
339  TGLContext newCtx = {ctx.fWindowIndex, -1, ctx.fDC, 0, ctx.fGLContext, w, h, x, y, ctx.fHighColor};
340 
341  if (CreateDIB(newCtx)) {
342  ctx = newCtx;
343  return kTRUE;
344  }
345 
346  return kFALSE;
347 }
348 
349 ////////////////////////////////////////////////////////////////////////////////
350 ///Create new DIB if needed
351 
353 {
354  TGLContext &ctx = fPimpl->fGLContexts[ctxInd];
355 
356  if (ctx.fPixmapIndex != -1)
357  if (TMath::Abs(Int_t(w) - Int_t(ctx.fW)) > 1 || TMath::Abs(Int_t(h) - Int_t(ctx.fH)) > 1) {
358  TGLContext newCtx = {ctx.fWindowIndex, -1, ctx.fDC, 0, ctx.fGLContext, w, h, x, y, ctx.fHighColor};
359  if (CreateDIB(newCtx)) {
360  //new DIB created
361  gVirtualX->SelectWindow(ctx.fPixmapIndex);
362  gVirtualX->ClosePixmap();
363  ctx = newCtx;
364  } else {
365  Error("ResizeOffScreenDevice", "Error trying to create new DIB\n");
366  return kFALSE;
367  }
368  } else {
369  ctx.fX = x;
370  ctx.fY = y;
371  }
372 
373  return kTRUE;
374 }
375 
376 ////////////////////////////////////////////////////////////////////////////////
377 
379 {
380  gVirtualX->SelectWindow(fPimpl->fGLContexts[ctxInd].fPixmapIndex);
381 }
382 
383 ////////////////////////////////////////////////////////////////////////////////
384 
386 {
387  if (fPimpl->fGLContexts[pixInd].fPixmapIndex != -1)
388  fPimpl->fGLContexts[pixInd].fDirect = isDirect;
389 }
390 
391 ////////////////////////////////////////////////////////////////////////////////
392 
394 {
395  TGLContext &ctx = fPimpl->fGLContexts[ctxInd];
396 
397  if (ctx.fPixmapIndex != -1) {
398  glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
399  glReadBuffer(GL_BACK);
400  glReadPixels(0, 0, ctx.fW, ctx.fH, GL_BGRA_EXT, GL_UNSIGNED_BYTE, ctx.fDIBData);
401  }
402 }
403 
404 ////////////////////////////////////////////////////////////////////////////////
405 
407 {
408  return fPimpl->fGLContexts[ctxInd].fPixmapIndex;
409 }
410 
411 ////////////////////////////////////////////////////////////////////////////////
412 
414 {
415  TGLContext &ctx = fPimpl->fGLContexts[ctxInd];
416  return (Bool_t)wglMakeCurrent(ctx.fDC, ctx.fGLContext);
417 }
418 
419 ////////////////////////////////////////////////////////////////////////////////
420 
422 {
423  TGLContext &ctx = fPimpl->fGLContexts[ctxInd];
424 
425  if (ctx.fPixmapIndex == -1) {
426  //doube-buffered OpenGL
427  wglSwapLayerBuffers(ctx.fDC, WGL_SWAP_MAIN_PLANE);
428  } else if (ctx.fDirect) {
429  //DIB is flushed by viewer directly
430  HDC hDC = CreateCompatibleDC(0);
431 
432  if (!hDC) {
433  Error("Flush", "CreateCompatibleDC failed\n");
434  return;
435  }
436 
437  HBITMAP oldDIB = (HBITMAP)SelectObject(hDC, ctx.fHBitmap);
438 
439  if (!BitBlt(ctx.fDC, ctx.fX, ctx.fY, ctx.fW, ctx.fH, hDC, 0, 0, SRCCOPY))
440  ctx.fDirect = kFALSE;
441 
442  SelectObject(hDC, oldDIB);
443  DeleteDC(hDC);
444  }
445  //do nothing for non-direct off-screen device
446 }
447 
448 ////////////////////////////////////////////////////////////////////////////////
449 
451 {
452  TGLContext &ctx = fPimpl->fGLContexts[ctxInd];
453 
454  if (ctx.fPixmapIndex != -1) {
455  gVirtualX->SelectWindow(ctx.fPixmapIndex);
456  gVirtualX->ClosePixmap();
457  ctx.fPixmapIndex = -1;
458  }
459 
460  wglDeleteContext(ctx.fGLContext);
461  ctx.fGLContext = 0;
462  ReleaseDC((HWND)GDK_DRAWABLE_XID((GdkWindow *)gVirtualX->GetWindowID(ctx.fWindowIndex)),
463  ctx.fDC);
464  //now, save its own index before putting into list of free devices
465  ctx.fWindowIndex = ctxInd;
466  ctx.fNextFreeContext = fPimpl->fNextFreeContext;
467  fPimpl->fNextFreeContext = &ctx;
468 }
469 
470 ////////////////////////////////////////////////////////////////////////////////
471 
473 {
474  TGLContext &ctx = fPimpl->fGLContexts[ctxInd];
475 
476  if (ctx.fPixmapIndex != -1) {
477  viewport[0] = 0;
478  viewport[1] = 0;
479  viewport[2] = ctx.fW;
480  viewport[3] = ctx.fH;
481  }
482 }
483 
484 ////////////////////////////////////////////////////////////////////////////////
485 
487 {
488  p->Paint();
489 }
490 
491 ////////////////////////////////////////////////////////////////////////////////
492 
494 {
495  vv->PrintObjects();
496 }
497 
498 ////////////////////////////////////////////////////////////////////////////////
499 
500 Bool_t TGWin32GLManager::SelectManip(TVirtualGLManip *manip, const TGLCamera * camera, const TGLRect * rect, const TGLBoundingBox * sceneBox)
501 {
502  return manip->Select(*camera, *rect, *sceneBox);
503 }
504 
505 ////////////////////////////////////////////////////////////////////////////////
506 
508 {
509  return o->Pan(x, y);
510 }
511 
512 ////////////////////////////////////////////////////////////////////////////////
513 
515 {
516  return plot->PlotSelected(px, py);
517 }
518 
519 ////////////////////////////////////////////////////////////////////////////////
520 
522 {
523  return plot->GetPlotInfo(px, py);
524 }
525 
526 ////////////////////////////////////////////////////////////////////////////////
527 
529 {
530  if (ctxInd == -1)
531  return kFALSE;
532 
533  return fPimpl->fGLContexts[ctxInd].fHighColor;
534 }
char * GetPlotInfo(TVirtualGLPainter *plot, Int_t px, Int_t py)
Definition: TGWin32GL.cxx:521
Int_t GetVirtualXInd(Int_t devInd)
Definition: TGWin32GL.cxx:406
Abstract base camera class - concrete classes for orthographic and perspective cameras derive from it...
Definition: TGLCamera.h:43
void DeleteGLContext(Int_t devInd)
Definition: TGWin32GL.cxx:450
void MarkForDirectCopy(Int_t devInd, Bool_t)
Definition: TGWin32GL.cxx:385
Int_t CreateGLContext(Int_t winInd)
winInd is TGWin32 index, returned by previous call gGLManager->InitGLWindow returns descripto (index)...
Definition: TGWin32GL.cxx:253
virtual Bool_t Select(const TGLCamera &camera, const TGLRect &rect, const TGLBoundingBox &sceneBox)=0
TH1 * h
Definition: legend2.C:5
void ExtractViewport(Int_t devInd, Int_t *vp)
Definition: TGWin32GL.cxx:472
#define gROOT
Definition: TROOT.h:402
Int_t InitGLWindow(Window_t winID)
Definition: TGWin32GL.cxx:244
virtual char * GetPlotInfo(Int_t px, Int_t py)=0
int Int_t
Definition: RtypesCore.h:41
virtual Bool_t PlotSelected(Int_t px, Int_t py)=0
bool Bool_t
Definition: RtypesCore.h:59
Bool_t CreateDIB(TGLContext &ctx) const
Create DIB section to read GL buffer into.
Definition: TGWin32GL.cxx:303
Short_t Abs(Short_t d)
Definition: TMathBase.h:108
static TGLManager * ProxyObject()
Double_t x[n]
Definition: legend1.C:17
Bool_t AttachOffScreenDevice(Int_t ctxInd, Int_t x, Int_t y, UInt_t w, UInt_t h)
Definition: TGWin32GL.cxx:336
Bool_t ResizeOffScreenDevice(Int_t devInd, Int_t x, Int_t y, UInt_t w, UInt_t h)
Create new DIB if needed.
Definition: TGWin32GL.cxx:352
Viewport (pixel base) 2D rectangle class.
Definition: TGLUtil.h:422
Bool_t HighColorFormat(Int_t ctx)
Definition: TGWin32GL.cxx:528
Abstract 3D shapes viewer.
void PrintViewer(TVirtualViewer3D *vv)
Definition: TGWin32GL.cxx:493
void Flush(Int_t ctxInd)
Definition: TGWin32GL.cxx:421
unsigned int UInt_t
Definition: RtypesCore.h:42
virtual void Error(const char *method, const char *msgfmt,...) const
Issue error message.
Definition: TObject.cxx:880
Bool_t MakeCurrent(Int_t devInd)
Definition: TGWin32GL.cxx:413
Bool_t PlotSelected(TVirtualGLPainter *plot, Int_t px, Int_t py)
Definition: TGWin32GL.cxx:514
#define gVirtualX
Definition: TVirtualX.h:350
void SelectOffScreenDevice(Int_t devInd)
Definition: TGWin32GL.cxx:378
virtual void Paint()=0
const Bool_t kFALSE
Definition: RtypesCore.h:88
virtual void Pan(Int_t px, Int_t py)=0
R__EXTERN TGLManager *(* gPtr2GLManager)()
Definition: TVirtualGL.h:163
const PIXELFORMATDESCRIPTOR doubleBufferDesc
Definition: TGWin32GL.cxx:153
#define ClassImp(name)
Definition: Rtypes.h:359
This class encapsulates window-system specific information about a GL-context and alows their proper ...
Definition: TGLContext.h:30
unsigned long ULong_t
Definition: RtypesCore.h:51
Double_t y[n]
Definition: legend1.C:17
#define gGLManager
Definition: TVirtualGL.h:162
Bool_t SelectManip(TVirtualGLManip *manip, const TGLCamera *camera, const TGLRect *rect, const TGLBoundingBox *sceneBox)
Definition: TGWin32GL.cxx:500
const PIXELFORMATDESCRIPTOR singleScreenDesc
Definition: TGWin32GL.cxx:173
TGWin32GLManager & operator=(const TGWin32GLManager &)
Concrete class describing an orientated (free) or axis aligned box of 8 vertices. ...
void ReadGLBuffer(Int_t devInd)
Definition: TGWin32GL.cxx:393
TGWin32GLImpl * fPimpl
Definition: TGWin32GL.h:22
Handle_t Window_t
Definition: GuiTypes.h:28
void PanObject(TVirtualGLPainter *o, Int_t x, Int_t y)
Definition: TGWin32GL.cxx:507
virtual void PrintObjects()
unsigned char UChar_t
Definition: RtypesCore.h:34
void PaintSingleObject(TVirtualGLPainter *)
Definition: TGWin32GL.cxx:486
const Bool_t kTRUE
Definition: RtypesCore.h:87
virtual void Warning(const char *method, const char *msgfmt,...) const
Issue warning message.
Definition: TObject.cxx:866