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