00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
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
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
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
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
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
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,
00156 1,
00157 PFD_DRAW_TO_WINDOW |
00158 PFD_SUPPORT_OPENGL |
00159 PFD_DOUBLEBUFFER,
00160 PFD_TYPE_RGBA,
00161 24,
00162 0, 0, 0, 0, 0, 0,
00163 0,
00164 0,
00165 0,
00166 0, 0, 0, 0,
00167 32,
00168 0,
00169 0,
00170 PFD_MAIN_PLANE
00171 };
00172
00173 const PIXELFORMATDESCRIPTOR
00174 singleScreenDesc = {
00175 sizeof singleScreenDesc,
00176 1,
00177 PFD_DRAW_TO_BITMAP |
00178 PFD_SUPPORT_OPENGL,
00179 PFD_TYPE_RGBA,
00180 24,
00181 0, 0, 0, 0, 0, 0,
00182 0,
00183 0,
00184 0,
00185 0, 0, 0, 0,
00186 32,
00187 0,
00188 0,
00189 PFD_MAIN_PLANE
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
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
00211 ::Warning("TGWin32GLManager::~TGLWin32GLManager", "You forget to destroy gl-context %d\n", i);
00212
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
00251
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
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
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
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
00415 wglSwapLayerBuffers(ctx.fDC, WGL_SWAP_MAIN_PLANE);
00416 } else if (ctx.fDirect) {
00417
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
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
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 }