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;}
 
  115 const Int_t dblBuff[] =
 
  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 &);
 
  142    TX11GLImpl &operator = (
const TX11GLImpl &);
 
  145 ClassImp(TX11GLManager);
 
  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);
 
  172             gVirtualX->ClosePixmap();
 
  174                XDestroyImage(ctx.fXImage);
 
  184 TX11GLManager::TX11GLManager() : fPimpl(new TX11GLImpl)
 
  187    gROOT->GetListOfSpecials()->Add(
this);
 
  194 TX11GLManager::~TX11GLManager()
 
  203 Int_t TX11GLManager::InitGLWindow(Window_t winID)
 
  205    XVisualInfo *visInfo = glXChooseVisual(
 
  206                                           fPimpl->fDpy, DefaultScreen(fPimpl->fDpy),
 
  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);
 
  240    Int_t x11Ind = gVirtualX->AddWindow(glWin,  w, h);
 
  243    fPimpl->fGLWindows[x11Ind] = visInfo;
 
  253 Int_t TX11GLManager::CreateGLContext(Int_t winInd)
 
  255    GLXContext glxCtx = glXCreateContext(fPimpl->fDpy, fPimpl->fGLWindows[winInd], None, True);
 
  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);
 
  278       return Int_t(fPimpl->fGLContexts.size()) - 1;
 
  286 Bool_t TX11GLManager::MakeCurrent(Int_t ctxInd)
 
  288    TGLContext_t &ctx = fPimpl->fGLContexts[ctxInd];
 
  289    return glXMakeCurrent(fPimpl->fDpy, gVirtualX->GetWindowID(ctx.fWindowIndex), ctx.fGLXContext);
 
  296 void TX11GLManager::Flush(Int_t ctxInd)
 
  298    TGLContext_t &ctx = fPimpl->fGLContexts[ctxInd];
 
  299    Window winID = gVirtualX->GetWindowID(ctx.fWindowIndex);
 
  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");
 
  309          ctx.fDirect = kFALSE;
 
  313       XCopyArea(fPimpl->fDpy, ctx.fX11Pixmap, winID, ctx.fDirectGC, 0, 0, ctx.fW, ctx.fH, ctx.fX, ctx.fY);
 
  321 Bool_t TX11GLManager::CreateGLPixmap(TGLContext_t &ctx)
 
  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");
 
  367 Bool_t TX11GLManager::AttachOffScreenDevice(Int_t ctxInd, Int_t x, Int_t y, UInt_t w, UInt_t h)
 
  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;
 
  376    if (CreateGLPixmap(newCtx)) {
 
  377       ctx.fPixmapIndex = newCtx.fPixmapIndex;
 
  378       ctx.fX11Pixmap = newCtx.fX11Pixmap;
 
  379       ctx.fW = w, ctx.fH = h, ctx.fX = x, ctx.fY = y;
 
  380       ctx.fDirect = kFALSE;
 
  381       ctx.fXImage = newCtx.fXImage;
 
  382       ctx.fBUBuffer.swap(newCtx.fBUBuffer);
 
  393 Bool_t TX11GLManager::ResizeOffScreenDevice(Int_t ctxInd, Int_t x, Int_t y, UInt_t w, UInt_t h)
 
  396    TGLContext_t &ctx = fPimpl->fGLContexts[ctxInd];
 
  398    if (ctx.fPixmapIndex != -1) {
 
  399       if (TMath::Abs(Int_t(w) - Int_t(ctx.fW)) > 1 || TMath::Abs(Int_t(h) - Int_t(ctx.fH)) > 1) {
 
  401          newCtx.fWindowIndex = ctx.fWindowIndex;
 
  402          newCtx.fW = w, newCtx.fH = h, newCtx.fX = x, newCtx.fY = y;
 
  403          newCtx.fGLXContext = ctx.fGLXContext;
 
  405          if (CreateGLPixmap(newCtx)) {
 
  406             gVirtualX->SelectWindow(ctx.fPixmapIndex);
 
  407             gVirtualX->ClosePixmap();
 
  408             ctx.fPixmapIndex = newCtx.fPixmapIndex;
 
  409             ctx.fX11Pixmap = newCtx.fX11Pixmap;
 
  410             ctx.fW = w, ctx.fH = h, ctx.fX = x, ctx.fY = y;
 
  411             ctx.fDirect = kFALSE;
 
  412             if (ctx.fXImage) XDestroyImage(ctx.fXImage);
 
  413             ctx.fXImage = newCtx.fXImage;
 
  414             ctx.fBUBuffer.swap(newCtx.fBUBuffer);
 
  417             Error(
"ResizeOffScreenDevice", 
"Resize failed\n");
 
  431 void TX11GLManager::SelectOffScreenDevice(Int_t ctxInd)
 
  433    gVirtualX->SelectWindow(fPimpl->fGLContexts[ctxInd].fPixmapIndex);
 
  440 void TX11GLManager::MarkForDirectCopy(Int_t ctxInd, Bool_t dir)
 
  442    if (fPimpl->fGLContexts[ctxInd].fPixmapIndex != -1)
 
  443       fPimpl->fGLContexts[ctxInd].fDirect = dir;
 
  451 void TX11GLManager::ReadGLBuffer(Int_t ctxInd)
 
  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");
 
  483 void TX11GLManager::DeleteGLContext(Int_t ctxInd)
 
  485    TGLContext_t &ctx = fPimpl->fGLContexts[ctxInd];
 
  488    glXDestroyContext(fPimpl->fDpy, ctx.fGLXContext);
 
  492    if (ctx.fPixmapIndex != -1) {
 
  493       gVirtualX->SelectWindow(ctx.fPixmapIndex);
 
  494       gVirtualX->ClosePixmap();
 
  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;
 
  515 Int_t TX11GLManager::GetVirtualXInd(Int_t ctxInd)
 
  517    return fPimpl->fGLContexts[ctxInd].fPixmapIndex;
 
  524 void TX11GLManager::ExtractViewport(Int_t ctxInd, Int_t *viewport)
 
  526    TGLContext_t &ctx = fPimpl->fGLContexts[ctxInd];
 
  528    if (ctx.fPixmapIndex != -1) {
 
  531       viewport[2] = ctx.fW;
 
  532       viewport[3] = ctx.fH;
 
  540 void TX11GLManager::PaintSingleObject(TVirtualGLPainter *p)
 
  549 void TX11GLManager::PrintViewer(TVirtualViewer3D *vv)
 
  557 Bool_t TX11GLManager::SelectManip(TVirtualGLManip *manip, 
const TGLCamera * camera, 
const TGLRect * rect, 
const TGLBoundingBox * sceneBox)
 
  559    return manip->Select(*camera, *rect, *sceneBox);
 
  566 void TX11GLManager::PanObject(TVirtualGLPainter *o, Int_t x, Int_t y)
 
  574 Bool_t TX11GLManager::PlotSelected(TVirtualGLPainter *plot, Int_t px, Int_t py)
 
  576    return plot->PlotSelected(px, py);
 
  582 char *TX11GLManager::GetPlotInfo(TVirtualGLPainter *plot, Int_t px, Int_t py)
 
  584    return plot->GetPlotInfo(px, py);