TGWin32GL.cxx

Go to the documentation of this file.
00001 // @(#)root/win32gdk:$Id: TGWin32GL.cxx 28599 2009-05-13 12:58:44Z bellenot $
00002 // Author: Valeriy Onuchin(TGWin32GL)/ Timur Pocheptsov (TGWin32GLManager)
00003 
00004 /*************************************************************************
00005  * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers.               *
00006  * All rights reserved.                                                  *
00007  *                                                                       *
00008  * For the licensing terms see $ROOTSYS/LICENSE.                         *
00009  * For the list of contributors see $ROOTSYS/README/CREDITS.             *
00010  *************************************************************************/
00011 
00012 //////////////////////////////////////////////////////////////////////////
00013 //                                                                      //
00014 // TGWin32GL                                                            //
00015 //                                                                      //
00016 // The TGWin32GL is win32gdk implementation of TVirtualGLImp class.     //
00017 //                                                                      //
00018 //////////////////////////////////////////////////////////////////////////
00019 #include <deque>
00020 
00021 #include "TGWin32GL.h"
00022 #include "TGWin32VirtualGLProxy.h"
00023 #include "TVirtualViewer3D.h"
00024 #include "TVirtualX.h"
00025 #include "TError.h"
00026 #include "TROOT.h"
00027 
00028 #include "Windows4Root.h"
00029 #include "gdk/gdk.h"
00030 #include "gdk/win32/gdkwin32.h"
00031 
00032 #include <GL/gl.h>
00033 #include <GL/glu.h>
00034 
00035 
00036 // Win32 GL Manager's stuff
00037 
00038 struct TGWin32GLManager::TGLContext {
00039    Int_t        fWindowIndex;
00040    Int_t        fPixmapIndex;
00041    //
00042    HDC          fDC;
00043    HBITMAP      fHBitmap;
00044    HGLRC        fGLContext;
00045    //
00046    UInt_t       fW;
00047    UInt_t       fH;
00048    //
00049    Int_t        fX;
00050    Int_t        fY;
00051    //
00052    Bool_t       fHighColor;
00053    //
00054    Bool_t       fDirect;
00055    //
00056    UChar_t     *fDIBData;
00057    //
00058    TGLContext  *fNextFreeContext;
00059 };
00060 
00061 namespace {
00062 
00063    //RAII class for HDC, returned by CreateCompatibleDC
00064    class CDCGuard {
00065    private:
00066       HDC fHDC;
00067 
00068       CDCGuard(const CDCGuard &);
00069       CDCGuard &operator = (const CDCGuard &);
00070 
00071    public:
00072       explicit CDCGuard(HDC hDC) : fHDC(hDC)
00073       {}
00074       ~CDCGuard()
00075       {
00076          if (fHDC)
00077             DeleteDC(fHDC);
00078       }
00079       void Stop()
00080       {
00081          fHDC = 0;
00082       }
00083    };
00084 
00085    //RAII class for HDC, returned by GetWindowDC
00086    class WDCGuard {
00087    private:
00088       HDC fHDC;
00089       Window_t fWinID;
00090 
00091       WDCGuard(const WDCGuard &);
00092       WDCGuard &operator = (const WDCGuard &);
00093 
00094    public:
00095       WDCGuard(HDC hDC, Window_t winID) : fHDC(hDC), fWinID(winID)
00096       {}
00097       ~WDCGuard()
00098       {
00099          if (fHDC)
00100             ReleaseDC((HWND)GDK_DRAWABLE_XID((GdkWindow *)fWinID), fHDC);
00101       }
00102       void Stop()
00103       {
00104          fHDC = 0;
00105       }
00106    };
00107 
00108    //RAII class for HBITMAP
00109    class BMPGuard {
00110    private:
00111       HBITMAP fBMP;
00112 
00113       BMPGuard(const BMPGuard &);
00114       BMPGuard &operator = (const BMPGuard &);
00115 
00116    public:
00117       explicit BMPGuard(HBITMAP bmp) : fBMP(bmp)
00118       {}
00119       ~BMPGuard()
00120       {
00121          if (fBMP)
00122             DeleteObject(fBMP);
00123       }
00124       void Stop()
00125       {
00126          fBMP = 0;
00127       }
00128    };
00129 
00130    //RAII class for HGLRC
00131    class WGLGuard {
00132    private:
00133       HGLRC fCtx;
00134 
00135       WGLGuard(const WGLGuard &);
00136       WGLGuard &operator = (const WGLGuard &);
00137 
00138    public:
00139       explicit WGLGuard(HGLRC glrc) : fCtx(glrc)
00140       {}
00141       ~WGLGuard()
00142       {
00143          if (fCtx)
00144             wglDeleteContext(fCtx);
00145       }
00146       void Stop()
00147       {
00148          fCtx = 0;
00149       }
00150    };
00151 }
00152 
00153 const PIXELFORMATDESCRIPTOR
00154 doubleBufferDesc = {
00155    sizeof doubleBufferDesc,        // size of this pfd
00156    1,                              // version number
00157    PFD_DRAW_TO_WINDOW |            // support window
00158    PFD_SUPPORT_OPENGL |            // support OpenGL
00159    PFD_DOUBLEBUFFER,               // double buffered
00160    PFD_TYPE_RGBA,                  // RGBA type
00161    24,                             // 24-bit color depth
00162    0, 0, 0, 0, 0, 0,               // color bits ignored
00163    0,                              // no alpha buffer
00164    0,                              // shift bit ignored
00165    0,                              // no accumulation buffer
00166    0, 0, 0, 0,                     // accum bits ignored
00167    32,                             // 32-bit z-buffer
00168    0,                              // no stencil buffer
00169    0,                              // no auxiliary buffer
00170    PFD_MAIN_PLANE                  // main layer
00171 };
00172 
00173 const PIXELFORMATDESCRIPTOR
00174 singleScreenDesc = {
00175    sizeof singleScreenDesc,        // size of this pfd
00176    1,                              // version number
00177    PFD_DRAW_TO_BITMAP |            // draw into bitmap
00178    PFD_SUPPORT_OPENGL,             // support OpenGL
00179    PFD_TYPE_RGBA,                  // RGBA type
00180    24,                             // 24-bit color depth
00181    0, 0, 0, 0, 0, 0,               // color bits ignored
00182    0,                              // no alpha buffer
00183    0,                              // shift bit ignored
00184    0,                              // no accumulation buffer
00185    0, 0, 0, 0,                     // accum bits ignored
00186    32,                             // 32-bit z-buffer
00187    0,                              // no stencil buffer
00188    0,                              // no auxiliary buffer
00189    PFD_MAIN_PLANE                  // main layer
00190 };
00191 
00192 class TGWin32GLManager::TGWin32GLImpl {
00193 public:
00194    TGWin32GLImpl() : fNextFreeContext(0)
00195    {}
00196    ~TGWin32GLImpl();
00197    std::deque<TGLContext> fGLContexts;
00198    TGLContext *fNextFreeContext;
00199 };
00200 
00201 TGWin32GLManager::TGWin32GLImpl::~TGWin32GLImpl()
00202 {
00203    //all devices should be destroyed at this moment
00204    std::deque<TGLContext>::size_type i = 0;
00205 
00206    for (; i < fGLContexts.size(); ++i) {
00207       TGLContext &ctx = fGLContexts[i];
00208 
00209       if (ctx.fGLContext) {
00210          //gl context (+DIB, if exists) must be destroyed from outside, by pad.
00211          ::Warning("TGWin32GLManager::~TGLWin32GLManager", "You forget to destroy gl-context %d\n", i);
00212          //destroy hdc and glrc, pixmap will be destroyed by TVirtualX
00213          if (ctx.fPixmapIndex != -1) {
00214             gVirtualX->SelectWindow(ctx.fPixmapIndex);
00215             gVirtualX->ClosePixmap();
00216          }
00217 
00218          wglDeleteContext(ctx.fGLContext);
00219          ReleaseDC((HWND)GDK_DRAWABLE_XID((GdkWindow *)gVirtualX->GetWindowID(ctx.fWindowIndex)),
00220                    ctx.fDC);
00221       }
00222    }
00223 }
00224 
00225 ClassImp(TGWin32GLManager)
00226 
00227 //______________________________________________________________________________
00228 TGWin32GLManager::TGWin32GLManager() : fPimpl(new TGWin32GLImpl)
00229 {
00230    gPtr2GLManager = &TGWin32GLManagerProxy::ProxyObject;
00231    gROOT->GetListOfSpecials()->AddLast(this);
00232    gGLManager = this;
00233 }
00234 
00235 //______________________________________________________________________________
00236 TGWin32GLManager::~TGWin32GLManager()
00237 {
00238    delete fPimpl;
00239 }
00240 
00241 //______________________________________________________________________________
00242 Int_t TGWin32GLManager::InitGLWindow(Window_t winID)
00243 {
00244    return gVirtualX->InitWindow(winID);
00245 }
00246 
00247 //______________________________________________________________________________
00248 Int_t TGWin32GLManager::CreateGLContext(Int_t winInd)
00249 {
00250    //winInd is TGWin32 index, returned by previous call gGLManager->InitGLWindow
00251    //returns descripto (index) of gl context or -1 if failed
00252    Window_t winID = gVirtualX->GetWindowID(winInd);
00253    HDC hDC = GetWindowDC((HWND)GDK_DRAWABLE_XID((GdkWindow *)winID));
00254 
00255    if (!hDC) {
00256       Error("CreateGLContext", "GetWindowDC failed\n");
00257       return -1;
00258    }
00259 
00260    WDCGuard dcGuard(hDC, winID);
00261 
00262    if (Int_t pixFormat = ChoosePixelFormat(hDC, &doubleBufferDesc)) {
00263       if (SetPixelFormat(hDC, pixFormat, &doubleBufferDesc)) {
00264          HGLRC glCtx = wglCreateContext(hDC);
00265 
00266          if (!glCtx) {
00267             Error("CreateGLContext", "wglCreateContext failed\n");
00268             return -1;
00269          }
00270 
00271          TGLContext newDevice = {winInd, -1, hDC, 0, glCtx};
00272          PIXELFORMATDESCRIPTOR testFormat = {};
00273          DescribePixelFormat(hDC, pixFormat, sizeof testFormat, &testFormat);
00274          newDevice.fHighColor = testFormat.cColorBits < 24 ? kTRUE : kFALSE;
00275 
00276          if (TGLContext *ctx = fPimpl->fNextFreeContext) {
00277             Int_t ind = ctx->fWindowIndex;
00278             fPimpl->fNextFreeContext = fPimpl->fNextFreeContext->fNextFreeContext;
00279             *ctx = newDevice;
00280             dcGuard.Stop();
00281             return ind;
00282          } else {
00283             WGLGuard wglGuard(glCtx);
00284             fPimpl->fGLContexts.push_back(newDevice);
00285             wglGuard.Stop();
00286             dcGuard.Stop();
00287             return fPimpl->fGLContexts.size() - 1;
00288          }
00289       } else
00290          Error("CreateGLContext", "SetPixelFormat failed\n");
00291    } else
00292       Error("CreateGLContext", "ChoosePixelFormat failed\n");
00293 
00294    return -1;
00295 }
00296 
00297 //______________________________________________________________________________
00298 Bool_t TGWin32GLManager::CreateDIB(TGLContext &ctx)const
00299 {
00300    //Create DIB section to read GL buffer into
00301    HDC dibDC = CreateCompatibleDC(0);
00302 
00303    if (!dibDC) {
00304       Error("CreateDIB", "CreateCompatibleDC failed\n");
00305       return kFALSE;
00306    }
00307 
00308    CDCGuard dcGuard(dibDC);
00309 
00310    BITMAPINFOHEADER bmpHeader = {sizeof bmpHeader, ctx.fW, ctx.fH, 1, 32, BI_RGB};
00311    void *bmpCnt = 0;
00312    HBITMAP hDIB = CreateDIBSection(dibDC, (BITMAPINFO*)&bmpHeader, DIB_RGB_COLORS, &bmpCnt, 0, 0);
00313 
00314    if (!hDIB) {
00315       Error("CreateDIB", "CreateDIBSection failed\n");
00316       return kFALSE;
00317    }
00318 
00319    BMPGuard bmpGuard(hDIB);
00320 
00321    ctx.fPixmapIndex = gVirtualX->AddPixmap((ULong_t)hDIB, ctx.fW, ctx.fH);
00322    ctx.fHBitmap = hDIB;
00323    ctx.fDIBData = static_cast<UChar_t *>(bmpCnt);
00324 
00325    bmpGuard.Stop();
00326 
00327    return kTRUE;
00328 }
00329 
00330 //______________________________________________________________________________
00331 Bool_t TGWin32GLManager::AttachOffScreenDevice(Int_t ctxInd, Int_t x, Int_t y, UInt_t w, UInt_t h)
00332 {
00333    TGLContext &ctx = fPimpl->fGLContexts[ctxInd];
00334    TGLContext newCtx = {ctx.fWindowIndex, -1, ctx.fDC, 0, ctx.fGLContext, w, h, x, y, ctx.fHighColor};
00335 
00336    if (CreateDIB(newCtx)) {
00337       ctx = newCtx;
00338       return kTRUE;
00339    }
00340 
00341    return kFALSE;
00342 }
00343 
00344 //______________________________________________________________________________
00345 Bool_t TGWin32GLManager::ResizeOffScreenDevice(Int_t ctxInd, Int_t x, Int_t y, UInt_t w, UInt_t h)
00346 {
00347    //Create new DIB if needed
00348    TGLContext &ctx = fPimpl->fGLContexts[ctxInd];
00349 
00350    if (ctx.fPixmapIndex != -1)
00351       if (TMath::Abs(Int_t(w) - Int_t(ctx.fW)) > 1 || TMath::Abs(Int_t(h) - Int_t(ctx.fH)) > 1) {
00352          TGLContext newCtx = {ctx.fWindowIndex, -1, ctx.fDC, 0, ctx.fGLContext, w, h, x, y, ctx.fHighColor};
00353          if (CreateDIB(newCtx)) {
00354             //new DIB created
00355             gVirtualX->SelectWindow(ctx.fPixmapIndex);
00356             gVirtualX->ClosePixmap();
00357             ctx = newCtx;
00358          } else {
00359             Error("ResizeOffScreenDevice", "Error trying to create new DIB\n");
00360             return kFALSE;
00361          }
00362       } else {
00363          ctx.fX = x;
00364          ctx.fY = y;
00365       }
00366 
00367    return kTRUE;
00368 }
00369 
00370 //______________________________________________________________________________
00371 void TGWin32GLManager::SelectOffScreenDevice(Int_t ctxInd)
00372 {
00373    gVirtualX->SelectWindow(fPimpl->fGLContexts[ctxInd].fPixmapIndex);
00374 }
00375 
00376 //______________________________________________________________________________
00377 void TGWin32GLManager::MarkForDirectCopy(Int_t pixInd, Bool_t isDirect)
00378 {
00379    if (fPimpl->fGLContexts[pixInd].fPixmapIndex != -1)
00380       fPimpl->fGLContexts[pixInd].fDirect = isDirect;
00381 }
00382 
00383 //______________________________________________________________________________
00384 void TGWin32GLManager::ReadGLBuffer(Int_t ctxInd)
00385 {
00386    TGLContext &ctx = fPimpl->fGLContexts[ctxInd];
00387 
00388    if (ctx.fPixmapIndex != -1) {
00389       glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
00390       glReadBuffer(GL_BACK);
00391       glReadPixels(0, 0, ctx.fW, ctx.fH, GL_BGRA_EXT, GL_UNSIGNED_BYTE, ctx.fDIBData);
00392    }
00393 }
00394 
00395 //______________________________________________________________________________
00396 Int_t TGWin32GLManager::GetVirtualXInd(Int_t ctxInd)
00397 {
00398    return fPimpl->fGLContexts[ctxInd].fPixmapIndex;
00399 }
00400 
00401 //______________________________________________________________________________
00402 Bool_t TGWin32GLManager::MakeCurrent(Int_t ctxInd)
00403 {
00404    TGLContext &ctx = fPimpl->fGLContexts[ctxInd];
00405    return (Bool_t)wglMakeCurrent(ctx.fDC, ctx.fGLContext);
00406 }
00407 
00408 //______________________________________________________________________________
00409 void TGWin32GLManager::Flush(Int_t ctxInd)
00410 {
00411    TGLContext &ctx = fPimpl->fGLContexts[ctxInd];
00412 
00413    if (ctx.fPixmapIndex == -1) {
00414       //doube-buffered OpenGL
00415       wglSwapLayerBuffers(ctx.fDC, WGL_SWAP_MAIN_PLANE);
00416    } else if (ctx.fDirect) {
00417       //DIB is flushed by viewer directly
00418       HDC hDC = CreateCompatibleDC(0);
00419 
00420       if (!hDC) {
00421          Error("Flush", "CreateCompatibleDC failed\n");
00422          return;
00423       }
00424 
00425       HBITMAP oldDIB = (HBITMAP)SelectObject(hDC, ctx.fHBitmap);
00426 
00427       if (!BitBlt(ctx.fDC, ctx.fX, ctx.fY, ctx.fW, ctx.fH, hDC, 0, 0, SRCCOPY))
00428          ctx.fDirect = kFALSE;
00429 
00430       SelectObject(hDC, oldDIB);
00431       DeleteDC(hDC);
00432    }
00433    //do nothing for non-direct off-screen device
00434 }
00435 
00436 //______________________________________________________________________________
00437 void TGWin32GLManager::DeleteGLContext(Int_t ctxInd)
00438 {
00439    TGLContext &ctx = fPimpl->fGLContexts[ctxInd];
00440 
00441    if (ctx.fPixmapIndex != -1) {
00442       gVirtualX->SelectWindow(ctx.fPixmapIndex);
00443       gVirtualX->ClosePixmap();
00444       ctx.fPixmapIndex = -1;
00445    }
00446 
00447    wglDeleteContext(ctx.fGLContext);
00448    ctx.fGLContext = 0;
00449    ReleaseDC((HWND)GDK_DRAWABLE_XID((GdkWindow *)gVirtualX->GetWindowID(ctx.fWindowIndex)),
00450              ctx.fDC);
00451    //now, save its own index before putting into list of free devices
00452    ctx.fWindowIndex = ctxInd;
00453    ctx.fNextFreeContext = fPimpl->fNextFreeContext;
00454    fPimpl->fNextFreeContext = &ctx;
00455 }
00456 
00457 //______________________________________________________________________________
00458 void TGWin32GLManager::ExtractViewport(Int_t ctxInd, Int_t *viewport)
00459 {
00460    TGLContext &ctx = fPimpl->fGLContexts[ctxInd];
00461 
00462    if (ctx.fPixmapIndex != -1) {
00463       viewport[0] = 0;
00464       viewport[1] = 0;
00465       viewport[2] = ctx.fW;
00466       viewport[3] = ctx.fH;
00467    }
00468 }
00469 
00470 //______________________________________________________________________________
00471 void TGWin32GLManager::PaintSingleObject(TVirtualGLPainter *p)
00472 {
00473    p->Paint();
00474 }
00475 
00476 //______________________________________________________________________________
00477 void TGWin32GLManager::PrintViewer(TVirtualViewer3D *vv)
00478 {
00479    vv->PrintObjects();
00480 }
00481 
00482 //______________________________________________________________________________
00483 Bool_t TGWin32GLManager::SelectManip(TVirtualGLManip *manip, const TGLCamera * camera, const TGLRect * rect, const TGLBoundingBox * sceneBox)
00484 {
00485    return manip->Select(*camera, *rect, *sceneBox);
00486 }
00487 
00488 //______________________________________________________________________________
00489 void TGWin32GLManager::PanObject(TVirtualGLPainter *o, Int_t x, Int_t y)
00490 {
00491    return o->Pan(x, y);
00492 }
00493 
00494 //______________________________________________________________________________
00495 Bool_t TGWin32GLManager::PlotSelected(TVirtualGLPainter *plot, Int_t px, Int_t py)
00496 {
00497     return plot->PlotSelected(px, py);
00498 }
00499 
00500 //______________________________________________________________________________
00501 char *TGWin32GLManager::GetPlotInfo(TVirtualGLPainter *plot, Int_t px, Int_t py)
00502 {
00503     return plot->GetPlotInfo(px, py);
00504 }
00505 
00506 //______________________________________________________________________________
00507 Bool_t TGWin32GLManager::HighColorFormat(Int_t ctxInd)
00508 {
00509    if (ctxInd == -1)
00510       return kFALSE;
00511 
00512    return fPimpl->fGLContexts[ctxInd].fHighColor;
00513 }

Generated on Tue Jul 5 14:14:45 2011 for ROOT_528-00b_version by  doxygen 1.5.1