30 struct TX11GLManager::TGLContext_t {
32 TGLContext_t() : fWindowIndex(-1), fPixmapIndex(-1), fX11Pixmap(0), fW(0),
33 fH(0), fX(0), fY(0), fGLXContext(0), fDirect(
kFALSE),
34 fXImage(0), fNextFreeContext(0), fDirectGC(0), fPixmapGC(0)
48 GLXContext fGLXContext;
52 std::vector<UChar_t> fBUBuffer;
54 TGLContext_t *fNextFreeContext;
61 typedef std::deque<TX11GLManager::TGLContext_t> DeviceTable_t;
62 typedef DeviceTable_t::size_type SizeType_t;
63 typedef std::map<Int_t, XVisualInfo *> WinTable_t;
64 XSetWindowAttributes dummyAttr;
73 TX11PixGuard(Display *dpy, Pixmap pix) : fDpy(dpy), fPix(pix) {}
74 ~TX11PixGuard(){
if (fPix) XFreePixmap(fDpy, fPix);}
75 void Stop(){fPix = 0;}
78 TX11PixGuard(
const TX11PixGuard &);
79 TX11PixGuard &
operator = (
const TX11PixGuard &);
89 TGLXCtxGuard(Display *dpy, GLXContext ctx) : fDpy(dpy), fCtx(ctx) {}
90 ~TGLXCtxGuard(){
if (fCtx) glXDestroyContext(fDpy, fCtx);}
91 void Stop(){fCtx = 0;}
94 TGLXCtxGuard(
const TGLXCtxGuard &);
95 TGLXCtxGuard &
operator = (
const TGLXCtxGuard &);
103 TXImageGuard(
const TXImageGuard &);
104 TXImageGuard &
operator = (
const TXImageGuard &);
107 explicit TXImageGuard(XImage *im) : fImage(im) {}
108 ~TXImageGuard(){
if (fImage) XDestroyImage(fImage);}
109 void Stop(){fImage = 0;}
128 const Int_t *snglBuff = dblBuff + 1;
130 class TX11GLManager::TX11GLImpl {
135 WinTable_t fGLWindows;
136 DeviceTable_t fGLContexts;
138 TGLContext_t *fNextFreeContext;
141 TX11GLImpl(
const TX11GLImpl &);
150 TX11GLManager::TX11GLImpl::TX11GLImpl() : fDpy(0), fNextFreeContext(0)
152 fDpy =
reinterpret_cast<Display *
>(
gVirtualX->GetDisplay());
161 TX11GLManager::TX11GLImpl::~TX11GLImpl()
163 for (SizeType_t i = 0, e = fGLContexts.size(); i < e; ++i) {
164 TGLContext_t &ctx = fGLContexts[i];
166 if (ctx.fGLXContext) {
167 ::Warning(
"TX11GLManager::~TX11GLManager",
"opengl device with index %ld was not destroyed", (
Long_t)i);
168 glXDestroyContext(fDpy, ctx.fGLXContext);
170 if (ctx.fPixmapIndex != -1) {
171 gVirtualX->SelectWindow(ctx.fPixmapIndex);
174 XDestroyImage(ctx.fXImage);
187 gROOT->GetListOfSpecials()->Add(
this);
205 XVisualInfo *visInfo = glXChooseVisual(
207 const_cast<Int_t *>(dblBuff)
211 Error(
"InitGLWindow",
"No good visual found!\n");
216 UInt_t w = 0,
h = 0, b = 0, d = 0;
218 XGetGeometry(
fPimpl->fDpy, winID, &root, &x, &
y, &w, &
h, &b, &d);
220 XSetWindowAttributes
attr(dummyAttr);
221 attr.colormap = XCreateColormap(
fPimpl->fDpy, root, visInfo->visual, AllocNone);
222 attr.event_mask = NoEventMask;
223 attr.backing_store = Always;
224 attr.bit_gravity = NorthWestGravity;
226 ULong_t mask = CWBackPixel | CWBorderPixel | CWColormap | CWEventMask | CWBackingStore | CWBitGravity;
229 Window glWin = XCreateWindow(
232 0, visInfo->depth, InputOutput,
233 visInfo->visual, mask, &attr
237 XMapWindow(
fPimpl->fDpy, glWin);
243 fPimpl->fGLWindows[x11Ind] = visInfo;
258 Error(
"CreateContext",
"glXCreateContext failed\n");
263 if (TGLContext_t *ctx =
fPimpl->fNextFreeContext) {
264 Int_t ind = ctx->fWindowIndex;
265 ctx->fWindowIndex = winInd;
266 ctx->fGLXContext = glxCtx;
267 fPimpl->fNextFreeContext =
fPimpl->fNextFreeContext->fNextFreeContext;
270 TGLXCtxGuard glxCtxGuard(
fPimpl->fDpy, glxCtx);
272 newDev.fWindowIndex = winInd;
273 newDev.fGLXContext = glxCtx;
275 fPimpl->fGLContexts.push_back(newDev);
288 TGLContext_t &ctx =
fPimpl->fGLContexts[ctxInd];
289 return glXMakeCurrent(
fPimpl->fDpy,
gVirtualX->GetWindowID(ctx.fWindowIndex), ctx.fGLXContext);
298 TGLContext_t &ctx =
fPimpl->fGLContexts[ctxInd];
301 if (ctx.fPixmapIndex == -1)
302 glXSwapBuffers(
fPimpl->fDpy, winID);
303 else if (ctx.fXImage && ctx.fDirect) {
305 ctx.fDirectGC = XCreateGC(
fPimpl->fDpy, winID, 0, 0);
307 if (!ctx.fDirectGC) {
308 Error(
"Flush",
"XCreateGC failed while copying pixmap\n");
313 XCopyArea(
fPimpl->fDpy, ctx.fX11Pixmap, winID, ctx.fDirectGC, 0, 0, ctx.fW, ctx.fH, ctx.fX, ctx.fY);
324 Pixmap x11Pix = XCreatePixmap(
fPimpl->fDpy,
gVirtualX->GetWindowID(ctx.fWindowIndex), ctx.fW,
325 ctx.fH,
fPimpl->fGLWindows[ctx.fWindowIndex]->depth);
328 Error(
"CreateGLPixmap",
"XCreatePixmap failed\n");
332 TX11PixGuard pixGuard(
fPimpl->fDpy, x11Pix);
335 XVisualInfo *visInfo =
fPimpl->fGLWindows[ctx.fWindowIndex];
336 XImage *testIm = XCreateImage(
fPimpl->fDpy, visInfo->visual, visInfo->depth, ZPixmap, 0, 0, ctx.fW, ctx.fH, 32, 0);
339 TXImageGuard imGuard(testIm);
340 testIm->data =
static_cast<Char_t *
>(
malloc(testIm->bytes_per_line * testIm->height));
343 Error(
"CreateGLPixmap",
"Cannot malloc XImage data\n");
347 if (XInitImage(testIm)) {
348 ctx.fPixmapIndex =
gVirtualX->AddPixmap(x11Pix, ctx.fW, ctx.fH);
349 ctx.fBUBuffer.resize(testIm->bytes_per_line * testIm->height);
350 ctx.fX11Pixmap = x11Pix;
351 ctx.fXImage = testIm;
356 Error(
"CreateGLPixmap",
"XInitImage error!\n");
358 Error(
"CreateGLPixmap",
"XCreateImage error!\n");
370 TGLContext_t &ctx =
fPimpl->fGLContexts[ctxInd];
372 newCtx.fWindowIndex = ctx.fWindowIndex;
373 newCtx.fW = w, newCtx.fH =
h, newCtx.fX =
x, newCtx.fY =
y;
374 newCtx.fGLXContext = ctx.fGLXContext;
377 ctx.fPixmapIndex = newCtx.fPixmapIndex;
378 ctx.fX11Pixmap = newCtx.fX11Pixmap;
379 ctx.fW = w, ctx.fH =
h, ctx.fX =
x, ctx.fY =
y;
381 ctx.fXImage = newCtx.fXImage;
382 ctx.fBUBuffer.swap(newCtx.fBUBuffer);
396 TGLContext_t &ctx =
fPimpl->fGLContexts[ctxInd];
398 if (ctx.fPixmapIndex != -1) {
401 newCtx.fWindowIndex = ctx.fWindowIndex;
402 newCtx.fW = w, newCtx.fH =
h, newCtx.fX =
x, newCtx.fY =
y;
403 newCtx.fGLXContext = ctx.fGLXContext;
406 gVirtualX->SelectWindow(ctx.fPixmapIndex);
408 ctx.fPixmapIndex = newCtx.fPixmapIndex;
409 ctx.fX11Pixmap = newCtx.fX11Pixmap;
410 ctx.fW = w, ctx.fH =
h, ctx.fX =
x, ctx.fY =
y;
412 if (ctx.fXImage) XDestroyImage(ctx.fXImage);
413 ctx.fXImage = newCtx.fXImage;
414 ctx.fBUBuffer.swap(newCtx.fBUBuffer);
417 Error(
"ResizeOffScreenDevice",
"Resize failed\n");
442 if (
fPimpl->fGLContexts[ctxInd].fPixmapIndex != -1)
443 fPimpl->fGLContexts[ctxInd].fDirect = dir;
453 TGLContext_t &ctx =
fPimpl->fGLContexts[ctxInd];
455 if (ctx.fPixmapIndex != -1 && ctx.fXImage) {
457 glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
458 glReadBuffer(GL_BACK);
459 glReadPixels(0, 0, ctx.fW, ctx.fH,
GL_BGRA, GL_UNSIGNED_BYTE, &ctx.fBUBuffer[0]);
462 ctx.fPixmapGC = XCreateGC(
fPimpl->fDpy, ctx.fX11Pixmap, 0, 0);
466 char *
dest = ctx.fXImage->data;
467 const UChar_t *src = &ctx.fBUBuffer[ctx.fW * 4 * (ctx.fH - 1)];
468 for (
UInt_t i = 0, e = ctx.fH; i < e; ++i) {
469 memcpy(dest, src, ctx.fW * 4);
473 XPutImage(
fPimpl->fDpy, ctx.fX11Pixmap, ctx.fPixmapGC, ctx.fXImage, 0, 0, 0, 0, ctx.fW, ctx.fH);
475 Error(
"ReadGLBuffer",
"XCreateGC error while attempt to copy XImage\n");
485 TGLContext_t &ctx =
fPimpl->fGLContexts[ctxInd];
488 glXDestroyContext(
fPimpl->fDpy, ctx.fGLXContext);
492 if (ctx.fPixmapIndex != -1) {
493 gVirtualX->SelectWindow(ctx.fPixmapIndex);
495 ctx.fPixmapIndex = -1;
497 XDestroyImage(ctx.fXImage);
501 XFreeGC(
fPimpl->fDpy, ctx.fDirectGC), ctx.fDirectGC = 0;
503 XFreeGC(
fPimpl->fDpy, ctx.fPixmapGC), ctx.fPixmapGC = 0;
506 ctx.fNextFreeContext =
fPimpl->fNextFreeContext;
507 fPimpl->fNextFreeContext = &ctx;
508 ctx.fWindowIndex = ctxInd;
517 return fPimpl->fGLContexts[ctxInd].fPixmapIndex;
526 TGLContext_t &ctx =
fPimpl->fGLContexts[ctxInd];
528 if (ctx.fPixmapIndex != -1) {
531 viewport[2] = ctx.fW;
532 viewport[3] = ctx.fH;
559 return manip->
Select(*camera, *rect, *sceneBox);
void DeleteGLContext(Int_t devInd)
Deletes GLX context and frees pixmap and image (if any).
Abstract base camera class - concrete classes for orthographic and perspective cameras derive from it...
Bool_t CreateGLPixmap(TGLContext_t &)
Create GL pixmap.
char * GetPlotInfo(TVirtualGLPainter *plot, Int_t px, Int_t py)
Analog of TObject::GetObjectInfo.
virtual Bool_t Select(const TGLCamera &camera, const TGLRect &rect, const TGLBoundingBox &sceneBox)=0
void MarkForDirectCopy(Int_t devInd, Bool_t)
Selection-rotation support for TPad/TCanvas.
Int_t InitGLWindow(Window_t winID)
Try to find correct visual.
void PrintViewer(TVirtualViewer3D *vv)
Print viewer.
Bool_t AttachOffScreenDevice(Int_t ctxInd, Int_t x, Int_t y, UInt_t w, UInt_t h)
Attach off screen device.
virtual char * GetPlotInfo(Int_t px, Int_t py)=0
virtual Bool_t PlotSelected(Int_t px, Int_t py)=0
~TX11GLManager()
Destructor.
void ReadGLBuffer(Int_t devInd)
GL buffer is read info buffer, after that lines are reordered into XImage, XImage copied into pixmap...
Viewport (pixel base) 2D rectangle class.
Abstract 3D shapes viewer.
void PaintSingleObject(TVirtualGLPainter *)
Paint a single object.
Int_t CreateGLContext(Int_t winInd)
Context creation requires Display * and XVisualInfo (was saved for such winInd).
virtual void Error(const char *method, const char *msgfmt,...) const
Issue error message.
TX11GLManager()
Constructor.
void SelectOffScreenDevice(Int_t devInd)
Selects off-screen device to make it accessible by gVirtualX.
The TX11GLManager is X11 implementation of TGLManager.
void Flush(Int_t ctxInd)
Swaps buffers or copy pixmap.
Bool_t PlotSelected(TVirtualGLPainter *plot, Int_t px, Int_t py)
Analog of TObject::DistancetoPrimitive.
void Warning(const char *location, const char *msgfmt,...)
virtual void Pan(Int_t px, Int_t py)=0
ClassImp(TX11GLManager) TX11GLManager
Constructor.
Bool_t ResizeOffScreenDevice(Int_t devInd, Int_t x, Int_t y, UInt_t w, UInt_t h)
Resize off screen device.
Binding & operator=(OUT(*fun)(void))
Concrete class describing an orientated (free) or axis aligned box of 8 vertices. ...
void PanObject(TVirtualGLPainter *o, Int_t x, Int_t y)
Pan objects.
Bool_t SelectManip(TVirtualGLManip *manip, const TGLCamera *camera, const TGLRect *rect, const TGLBoundingBox *sceneBox)
Select manipulator.
#define dest(otri, vertexptr)
virtual void PrintObjects()
TX11GLManager & operator=(const TX11GLManager &)
Vc_ALWAYS_INLINE_L T *Vc_ALWAYS_INLINE_R malloc(size_t n)
Allocates memory on the Heap with alignment and padding suitable for vectorized access.
Int_t GetVirtualXInd(Int_t devInd)
Returns an index suitable for gVirtualX.
Bool_t MakeCurrent(Int_t devInd)
Make GL context current.
void ExtractViewport(Int_t devInd, Int_t *vp)
Returns the current dimensions of a GL pixmap.