29 #include "gdk/win32/gdkwin32.h"
37 struct TGWin32GLManager::TGLContext {
57 TGLContext *fNextFreeContext;
67 CDCGuard(
const CDCGuard &);
68 CDCGuard &operator = (
const CDCGuard &);
71 explicit CDCGuard(HDC hDC) : fHDC(hDC)
90 WDCGuard(
const WDCGuard &);
91 WDCGuard &operator = (
const WDCGuard &);
94 WDCGuard(HDC hDC, Window_t winID) : fHDC(hDC), fWinID(winID)
99 ReleaseDC((HWND)GDK_DRAWABLE_XID((GdkWindow *)fWinID), fHDC);
112 BMPGuard(
const BMPGuard &);
113 BMPGuard &operator = (
const BMPGuard &);
116 explicit BMPGuard(HBITMAP bmp) : fBMP(bmp)
134 WGLGuard(
const WGLGuard &);
135 WGLGuard &operator = (
const WGLGuard &);
138 explicit WGLGuard(HGLRC glrc) : fCtx(glrc)
143 wglDeleteContext(fCtx);
152 const PIXELFORMATDESCRIPTOR
154 sizeof doubleBufferDesc,
172 const PIXELFORMATDESCRIPTOR
174 sizeof singleScreenDesc,
191 class TGWin32GLManager::TGWin32GLImpl {
193 TGWin32GLImpl() : fNextFreeContext(nullptr)
196 std::deque<TGLContext> fGLContexts;
197 TGLContext *fNextFreeContext;
200 TGWin32GLManager::TGWin32GLImpl::~TGWin32GLImpl()
203 std::deque<TGLContext>::size_type i = 0;
205 for (; i < fGLContexts.size(); ++i) {
206 TGLContext &ctx = fGLContexts[i];
208 if (ctx.fGLContext) {
210 ::Warning(
"TGWin32GLManager::~TGLWin32GLManager",
"You forget to destroy gl-context %d\n", i);
212 if (ctx.fPixmapIndex != -1) {
213 gVirtualX->SelectWindow(ctx.fPixmapIndex);
214 gVirtualX->ClosePixmap();
217 wglDeleteContext(ctx.fGLContext);
218 ReleaseDC((HWND)GDK_DRAWABLE_XID((GdkWindow *)gVirtualX->GetWindowID(ctx.fWindowIndex)),
224 ClassImp(TGWin32GLManager);
228 TGWin32GLManager::TGWin32GLManager() : fPimpl(new TGWin32GLImpl)
230 gPtr2GLManager = &TGWin32GLManagerProxy::ProxyObject;
231 gROOT->GetListOfSpecials()->AddLast(
this);
237 TGWin32GLManager::~TGWin32GLManager()
244 Int_t TGWin32GLManager::InitGLWindow(Window_t winID)
246 return gVirtualX->InitWindow(winID);
253 Int_t TGWin32GLManager::CreateGLContext(Int_t winInd)
255 Window_t winID = gVirtualX->GetWindowID(winInd);
256 HDC hDC = GetWindowDC((HWND)GDK_DRAWABLE_XID((GdkWindow *)winID));
259 Error(
"CreateGLContext",
"GetWindowDC failed\n");
263 WDCGuard dcGuard(hDC, winID);
265 if (Int_t pixFormat = ChoosePixelFormat(hDC, &doubleBufferDesc)) {
266 if (SetPixelFormat(hDC, pixFormat, &doubleBufferDesc)) {
267 HGLRC glCtx = wglCreateContext(hDC);
270 Error(
"CreateGLContext",
"wglCreateContext failed\n");
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;
279 if (TGLContext *ctx = fPimpl->fNextFreeContext) {
280 Int_t ind = ctx->fWindowIndex;
281 fPimpl->fNextFreeContext = fPimpl->fNextFreeContext->fNextFreeContext;
286 WGLGuard wglGuard(glCtx);
287 fPimpl->fGLContexts.push_back(newDevice);
290 return fPimpl->fGLContexts.size() - 1;
293 Error(
"CreateGLContext",
"SetPixelFormat failed\n");
295 Error(
"CreateGLContext",
"ChoosePixelFormat failed\n");
303 Bool_t TGWin32GLManager::CreateDIB(TGLContext &ctx)
const
305 HDC dibDC = CreateCompatibleDC(0);
308 Error(
"CreateDIB",
"CreateCompatibleDC failed\n");
312 CDCGuard dcGuard(dibDC);
314 BITMAPINFOHEADER bmpHeader = {
sizeof bmpHeader, (LONG) ctx.fW, (LONG) ctx.fH, 1, 32, BI_RGB};
315 void *bmpCnt =
nullptr;
316 HBITMAP hDIB = CreateDIBSection(dibDC, (BITMAPINFO*)&bmpHeader, DIB_RGB_COLORS, &bmpCnt, 0, 0);
319 Error(
"CreateDIB",
"CreateDIBSection failed\n");
323 BMPGuard bmpGuard(hDIB);
325 ctx.fPixmapIndex = gVirtualX->AddPixmap((ULong_t)hDIB, ctx.fW, ctx.fH);
327 ctx.fDIBData =
static_cast<UChar_t *
>(bmpCnt);
336 Bool_t TGWin32GLManager::AttachOffScreenDevice(Int_t ctxInd, Int_t x, Int_t y, UInt_t w, UInt_t h)
338 TGLContext &ctx = fPimpl->fGLContexts[ctxInd];
339 TGLContext newCtx = {ctx.fWindowIndex, -1, ctx.fDC, 0, ctx.fGLContext, w, h, x, y, ctx.fHighColor};
341 if (CreateDIB(newCtx)) {
352 Bool_t TGWin32GLManager::ResizeOffScreenDevice(Int_t ctxInd, Int_t x, Int_t y, UInt_t w, UInt_t h)
354 TGLContext &ctx = fPimpl->fGLContexts[ctxInd];
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)) {
361 gVirtualX->SelectWindow(ctx.fPixmapIndex);
362 gVirtualX->ClosePixmap();
365 Error(
"ResizeOffScreenDevice",
"Error trying to create new DIB\n");
378 void TGWin32GLManager::SelectOffScreenDevice(Int_t ctxInd)
380 gVirtualX->SelectWindow(fPimpl->fGLContexts[ctxInd].fPixmapIndex);
385 void TGWin32GLManager::MarkForDirectCopy(Int_t pixInd, Bool_t isDirect)
387 if (fPimpl->fGLContexts[pixInd].fPixmapIndex != -1)
388 fPimpl->fGLContexts[pixInd].fDirect = isDirect;
393 void TGWin32GLManager::ReadGLBuffer(Int_t ctxInd)
395 TGLContext &ctx = fPimpl->fGLContexts[ctxInd];
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);
406 Int_t TGWin32GLManager::GetVirtualXInd(Int_t ctxInd)
408 return fPimpl->fGLContexts[ctxInd].fPixmapIndex;
413 Bool_t TGWin32GLManager::MakeCurrent(Int_t ctxInd)
415 TGLContext &ctx = fPimpl->fGLContexts[ctxInd];
416 return (Bool_t)wglMakeCurrent(ctx.fDC, ctx.fGLContext);
421 void TGWin32GLManager::Flush(Int_t ctxInd)
423 TGLContext &ctx = fPimpl->fGLContexts[ctxInd];
425 if (ctx.fPixmapIndex == -1) {
427 wglSwapLayerBuffers(ctx.fDC, WGL_SWAP_MAIN_PLANE);
428 }
else if (ctx.fDirect) {
430 HDC hDC = CreateCompatibleDC(0);
433 Error(
"Flush",
"CreateCompatibleDC failed\n");
437 HBITMAP oldDIB = (HBITMAP)SelectObject(hDC, ctx.fHBitmap);
439 if (!BitBlt(ctx.fDC, ctx.fX, ctx.fY, ctx.fW, ctx.fH, hDC, 0, 0, SRCCOPY))
440 ctx.fDirect = kFALSE;
442 SelectObject(hDC, oldDIB);
450 void TGWin32GLManager::DeleteGLContext(Int_t ctxInd)
452 TGLContext &ctx = fPimpl->fGLContexts[ctxInd];
454 if (ctx.fPixmapIndex != -1) {
455 gVirtualX->SelectWindow(ctx.fPixmapIndex);
456 gVirtualX->ClosePixmap();
457 ctx.fPixmapIndex = -1;
460 wglDeleteContext(ctx.fGLContext);
462 ReleaseDC((HWND)GDK_DRAWABLE_XID((GdkWindow *)gVirtualX->GetWindowID(ctx.fWindowIndex)),
465 ctx.fWindowIndex = ctxInd;
466 ctx.fNextFreeContext = fPimpl->fNextFreeContext;
467 fPimpl->fNextFreeContext = &ctx;
472 void TGWin32GLManager::ExtractViewport(Int_t ctxInd, Int_t *viewport)
474 TGLContext &ctx = fPimpl->fGLContexts[ctxInd];
476 if (ctx.fPixmapIndex != -1) {
479 viewport[2] = ctx.fW;
480 viewport[3] = ctx.fH;
486 void TGWin32GLManager::PaintSingleObject(TVirtualGLPainter *p)
493 void TGWin32GLManager::PrintViewer(TVirtualViewer3D *vv)
500 Bool_t TGWin32GLManager::SelectManip(TVirtualGLManip *manip,
const TGLCamera * camera,
const TGLRect * rect,
const TGLBoundingBox * sceneBox)
502 return manip->Select(*camera, *rect, *sceneBox);
507 void TGWin32GLManager::PanObject(TVirtualGLPainter *o, Int_t x, Int_t y)
514 Bool_t TGWin32GLManager::PlotSelected(TVirtualGLPainter *plot, Int_t px, Int_t py)
516 return plot->PlotSelected(px, py);
521 char *TGWin32GLManager::GetPlotInfo(TVirtualGLPainter *plot, Int_t px, Int_t py)
523 return plot->GetPlotInfo(px, py);
528 Bool_t TGWin32GLManager::HighColorFormat(Int_t ctxInd)
533 return fPimpl->fGLContexts[ctxInd].fHighColor;