#include <stdexcept>
#include <vector>
#ifndef WIN32
#include <GL/glx.h>
#endif
#include "TVirtualX.h"
#include "TGClient.h"
#include "TError.h"
#include "TROOT.h"
#include "TGLWidget.h"
#include "TGLIncludes.h"
#include "TGLUtil.h"
ClassImp(TGLWidgetContainer)
TGLWidgetContainer::TGLWidgetContainer(TGLWidget *owner, Window_t id, const TGWindow *parent)
: TGCompositeFrame(gClient, id, parent),
fOwner(owner)
{
}
Bool_t TGLWidgetContainer::HandleButton(Event_t *ev)
{
return fOwner->HandleButton(ev);
}
Bool_t TGLWidgetContainer::HandleDoubleClick(Event_t *ev)
{
return fOwner->HandleDoubleClick(ev);
}
Bool_t TGLWidgetContainer::HandleConfigureNotify(Event_t *ev)
{
return fOwner->HandleConfigureNotify(ev);
}
Bool_t TGLWidgetContainer::HandleKey(Event_t *ev)
{
return fOwner->HandleKey(ev);
}
Bool_t TGLWidgetContainer::HandleMotion(Event_t *ev)
{
return fOwner->HandleMotion(ev);
}
void TGLWidgetContainer::DoRedraw()
{
return fOwner->Repaint();
}
ClassImp(TGLWidget)
TGLWidget::TGLWidget(const TGWindow &p, Bool_t select,
const TGLPaintDevice *shareDevice,
UInt_t w, UInt_t h, UInt_t opt, Pixel_t back)
: TGCanvas(&p, w, h, opt, back),
fWindowIndex(-1),
fFromCtor(kTRUE)
{
CreateWidget(shareDevice);
if (select) {
gVirtualX->GrabButton(
fContainer->GetId(), kAnyButton, kAnyModifier,
kButtonPressMask | kButtonReleaseMask, kNone, kNone
);
gVirtualX->SelectInput(
fContainer->GetId(), kKeyPressMask | kExposureMask | kPointerMotionMask
| kStructureNotifyMask | kFocusChangeMask
);
gVirtualX->SetInputFocus(fContainer->GetId());
}
fFromCtor = kFALSE;
}
TGLWidget::TGLWidget(const TGLFormat &format, const TGWindow &p, Bool_t select,
const TGLPaintDevice *shareDevice,
UInt_t w, UInt_t h, UInt_t opt, Pixel_t back)
: TGCanvas(&p, w, h, opt, back),
fWindowIndex(-1),
fGLFormat(format),
fFromCtor(kTRUE)
{
CreateWidget(shareDevice);
if (select) {
gVirtualX->GrabButton(
fContainer->GetId(), kAnyButton, kAnyModifier,
kButtonPressMask | kButtonReleaseMask, kNone, kNone
);
gVirtualX->SelectInput(
fContainer->GetId(), kKeyPressMask | kExposureMask | kPointerMotionMask
| kStructureNotifyMask | kFocusChangeMask
);
gVirtualX->SetInputFocus(fContainer->GetId());
}
fFromCtor = kFALSE;
}
TGLWidget::TGLWidget(const TGWindow &p, Bool_t select,
UInt_t w, UInt_t h, UInt_t opt, Pixel_t back)
: TGCanvas(&p, w, h, opt, back),
fWindowIndex(-1),
fFromCtor(kTRUE)
{
CreateWidget();
if (select) {
gVirtualX->GrabButton(
fContainer->GetId(), kAnyButton, kAnyModifier,
kButtonPressMask | kButtonReleaseMask, kNone, kNone
);
gVirtualX->SelectInput(
fContainer->GetId(), kKeyPressMask | kExposureMask | kPointerMotionMask
| kStructureNotifyMask | kFocusChangeMask
);
gVirtualX->SetInputFocus(fContainer->GetId());
}
fFromCtor = kFALSE;
}
TGLWidget::TGLWidget(const TGLFormat &format, const TGWindow &p, Bool_t select,
UInt_t w, UInt_t h, UInt_t opt, Pixel_t back)
: TGCanvas(&p, w, h, opt, back),
fWindowIndex(-1),
fGLFormat(format),
fFromCtor(kTRUE)
{
CreateWidget();
if (select) {
gVirtualX->GrabButton(
fContainer->GetId(), kAnyButton, kAnyModifier,
kButtonPressMask | kButtonReleaseMask, kNone, kNone
);
gVirtualX->SelectInput(
fContainer->GetId(), kKeyPressMask | kExposureMask | kPointerMotionMask
| kStructureNotifyMask | kFocusChangeMask
);
gVirtualX->SetInputFocus(fContainer->GetId());
}
fFromCtor = kFALSE;
}
TGLWidget::~TGLWidget()
{
gVirtualX->SelectWindow(fWindowIndex);
gVirtualX->CloseWindow();
#ifndef WIN32
XFree(fInnerData.second);
#endif
if (fValidContexts.size() > 1u) {
Warning("~TGLWidget", "There are some gl-contexts connected to this gl device"
"which have longer lifetime than lifetime of gl-device");
}
std::set<TGLContext *>::iterator it = fValidContexts.begin();
for (; it != fValidContexts.end(); ++it) {
(*it)->Release();
}
}
void TGLWidget::InitGL()
{
}
void TGLWidget::PaintGL()
{
}
Bool_t TGLWidget::MakeCurrent()
{
return fGLContext->MakeCurrent();
}
void TGLWidget::SwapBuffers()
{
fGLContext->SwapBuffers();
}
const TGLContext *TGLWidget::GetContext()const
{
return fGLContext.get();
}
Bool_t TGLWidget::HandleButton(Event_t *ev)
{
if (!gVirtualX->IsCmdThread()) {
gROOT->ProcessLineFast(Form("((TGLWidget *)0x%lx)->HandleButton((Event_t *)0x%lx)", this, ev));
return kTRUE;
}
Emit("HandleButton(Event_t*)", (Long_t)ev);
return kTRUE;
}
Bool_t TGLWidget::HandleDoubleClick(Event_t *ev)
{
if (!gVirtualX->IsCmdThread()) {
gROOT->ProcessLineFast(Form("((TGLWidget *)0x%lx)->HandleDoubleClick((Event_t *)0x%lx)", this, ev));
return kTRUE;
}
Emit("HandleDoubleClick(Event_t*)", (Long_t)ev);
return kTRUE;
}
Bool_t TGLWidget::HandleConfigureNotify(Event_t *ev)
{
if (!gVirtualX->IsCmdThread()) {
gROOT->ProcessLineFast(Form("((TGLWidget *)0x%lx)->HandleConfigureNotify((Event_t *)0x%lx)", this, ev));
return kTRUE;
}
Emit("HandleConfigureNotify(Event_t*)", (Long_t)ev);
return kTRUE;
}
Bool_t TGLWidget::HandleKey(Event_t *ev)
{
if (!gVirtualX->IsCmdThread()) {
gROOT->ProcessLineFast(Form("((TGLWidget *)0x%lx)->HandleKey((Event_t *)0x%lx)", this, ev));
return kTRUE;
}
Emit("HandleKey(Event_t*)", (Long_t)ev);
return kTRUE;
}
Bool_t TGLWidget::HandleMotion(Event_t *ev)
{
if (!gVirtualX->IsCmdThread()) {
gROOT->ProcessLineFast(Form("((TGLWidget *)0x%lx)->HandleMotion((Event_t *)0x%lx)", this, ev));
return kTRUE;
}
Emit("HandleMotion(Event_t*)", (Long_t)ev);
return kTRUE;
}
Int_t TGLWidget::GetWindowIndex()const
{
return fWindowIndex;
}
const TGLFormat *TGLWidget::GetPixelFormat()const
{
return &fGLFormat;
}
Int_t TGLWidget::GetContId()const
{
return fContainer->GetId();
}
std::pair<void *, void *> TGLWidget::GetInnerData()const
{
return fInnerData;
}
#ifdef WIN32
namespace {
struct LayoutCompatible_t {
void *fDummy0;
void *fDummy1;
HWND *fPHwnd;
unsigned char fDummy2;
unsigned fDummy3;
unsigned short fDummy4;
unsigned short fDummy5;
void *fDummy6;
unsigned fDummy7:2;
};
void fill_pfd(PIXELFORMATDESCRIPTOR *pfd, const TGLFormat &request)
{
pfd->nSize = sizeof(PIXELFORMATDESCRIPTOR);
pfd->nVersion = 1;
pfd->dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL;
if (request.IsDoubleBuffered())
pfd->dwFlags |= PFD_DOUBLEBUFFER;
pfd->iPixelType = PFD_TYPE_RGBA;
pfd->cColorBits = 24;
if (UInt_t acc = request.GetAccumSize())
pfd->cAccumBits = acc;
if (UInt_t depth = request.GetDepthSize())
pfd->cDepthBits = depth;
if (UInt_t stencil = request.GetStencilSize())
pfd->cStencilBits = stencil;
}
void check_pixel_format(Int_t pixIndex, HDC hDC, TGLFormat &request)
{
PIXELFORMATDESCRIPTOR pfd = {};
if (!DescribePixelFormat(hDC, pixIndex, sizeof pfd, &pfd)) {
Warning("TGLContext::SetContext", "DescribePixelFormat failed");
return;
}
if (pfd.cAccumBits)
request.SetAccumSize(pfd.cAccumBits);
if (pfd.cDepthBits)
request.SetDepthSize(pfd.cDepthBits);
if (pfd.cStencilBits)
request.SetStencilSize(pfd.cStencilBits);
}
}
void TGLWidget::CreateWidget(const TGLPaintDevice *shareDevice)
{
fWindowIndex = gVirtualX->InitWindow((ULong_t)GetViewPort()->GetId());
try {
if (!gVirtualX->IsCmdThread())
gROOT->ProcessLineFast(Form("((TGLWidget *)0x%lx)->SetFormat()", this));
else
SetFormat();
fGLContext.reset(new TGLContext(this, shareDevice ? shareDevice->GetContext() : 0));
fContainer.reset(new TGLWidgetContainer(this, gVirtualX->GetWindowID(fWindowIndex), GetViewPort()));
SetContainer(fContainer.get());
} catch (std::exception &) {
gVirtualX->SelectWindow(fWindowIndex);
gVirtualX->CloseWindow();
throw;
}
}
void TGLWidget::CreateWidget()
{
fWindowIndex = gVirtualX->InitWindow((ULong_t)GetViewPort()->GetId());
try {
if (!gVirtualX->IsCmdThread())
gROOT->ProcessLineFast(Form("((TGLWidget *)0x%lx)->SetFormat()", this));
else
SetFormat();
fGLContext.reset(new TGLContext(this));
fContainer.reset(new TGLWidgetContainer(this, gVirtualX->GetWindowID(fWindowIndex), GetViewPort()));
SetContainer(fContainer.get());
} catch (std::exception &) {
gVirtualX->SelectWindow(fWindowIndex);
gVirtualX->CloseWindow();
throw;
}
}
void TGLWidget::SetFormat()
{
if (!fFromCtor) {
Error("TGLWidget::SetFormat", "Sorry, you should not call this function");
return;
}
LayoutCompatible_t *trick =
reinterpret_cast<LayoutCompatible_t *>(gVirtualX->GetWindowID(GetWindowIndex()));
HWND hWND = *trick->fPHwnd;
HDC hDC = GetWindowDC(hWND);
if (!hDC) {
Error("TGLWidget::SetFormat", "GetWindowDC failed");
throw std::runtime_error("GetWindowDC failed");
}
const Rgl::TGuardBase &dcGuard = Rgl::make_guard(ReleaseDC, hWND, hDC);
PIXELFORMATDESCRIPTOR pfd = {};
fill_pfd(&pfd, fGLFormat);
if (const Int_t pixIndex = ChoosePixelFormat(hDC, &pfd)) {
check_pixel_format(pixIndex, hDC, fGLFormat);
if (!SetPixelFormat(hDC, pixIndex, &pfd)) {
Error("TGLWidget::SetFormat", "SetPixelFormat failed");
throw std::runtime_error("SetPixelFormat failed");
}
} else {
Error("TGLWidget::SetFormat", "ChoosePixelFormat failed");
throw std::runtime_error("ChoosePixelFormat failed");
}
}
#else
namespace {
void fill_format(std::vector<Int_t> &format, const TGLFormat &request)
{
format.push_back(GLX_RGBA);
format.push_back(GLX_RED_SIZE);
format.push_back(1);
format.push_back(GLX_GREEN_SIZE);
format.push_back(1);
format.push_back(GLX_BLUE_SIZE);
format.push_back(1);
if (request.IsDoubleBuffered())
format.push_back(GLX_DOUBLEBUFFER);
if (request.HasDepth()) {
format.push_back(GLX_DEPTH_SIZE);
format.push_back(request.GetDepthSize());
}
if (request.HasStencil()) {
format.push_back(GLX_STENCIL_SIZE);
format.push_back(request.GetStencilSize());
}
if (request.HasAccumBuffer()) {
format.push_back(GLX_ACCUM_RED_SIZE);
format.push_back(1);
format.push_back(GLX_ACCUM_GREEN_SIZE);
format.push_back(1);
format.push_back(GLX_ACCUM_BLUE_SIZE);
format.push_back(1);
}
format.push_back(None);
}
XSetWindowAttributes dummyAttr;
}
void TGLWidget::CreateWidget(const TGLPaintDevice *shareDevice)
{
std::vector<Int_t> format;
fill_format(format, fGLFormat);
Window_t winID = GetViewPort()->GetId();
Display *dpy = reinterpret_cast<Display *>(gVirtualX->GetDisplay());
XVisualInfo *visInfo = glXChooseVisual(dpy, DefaultScreen(dpy), &format[0]);
if (!visInfo) {
Error("CreateGLContainer", "No good visual found!");
throw std::runtime_error("No good visual found!");
}
Int_t x = 0, y = 0;
UInt_t w = 0, h = 0, b = 0, d = 0;
Window root = 0;
XGetGeometry(dpy, winID, &root, &x, &y, &w, &h, &b, &d);
XSetWindowAttributes attr(dummyAttr);
attr.colormap = XCreateColormap(dpy, root, visInfo->visual, AllocNone);
attr.event_mask = NoEventMask;
attr.backing_store = Always;
attr.bit_gravity = NorthWestGravity;
ULong_t mask = CWBackPixel | CWBorderPixel | CWColormap | CWEventMask | CWBackingStore | CWBitGravity;
Window glWin = XCreateWindow(dpy, winID, x, y, w, h, 0, visInfo->depth,
InputOutput, visInfo->visual, mask, &attr);
XMapWindow(dpy, glWin);
fWindowIndex = gVirtualX->AddWindow(glWin, w, h);
fInnerData.first = dpy;
fInnerData.second = visInfo;
try {
fGLContext.reset(new TGLContext(this, shareDevice ? shareDevice->GetContext() : 0));
fContainer.reset(new TGLWidgetContainer(this, gVirtualX->GetWindowID(fWindowIndex), GetViewPort()));
SetContainer(fContainer.get());
} catch (const std::exception &) {
gVirtualX->SelectWindow(fWindowIndex);
gVirtualX->CloseWindow();
XFree(fInnerData.second);
throw;
}
}
void TGLWidget::CreateWidget()
{
std::vector<Int_t> format;
fill_format(format, fGLFormat);
Window_t winID = GetViewPort()->GetId();
Display *dpy = reinterpret_cast<Display *>(gVirtualX->GetDisplay());
XVisualInfo *visInfo = glXChooseVisual(dpy, DefaultScreen(dpy), &format[0]);
if (!visInfo) {
Error("CreateGLContainer", "No good visual found!");
throw std::runtime_error("No good visual found!");
}
Int_t x = 0, y = 0;
UInt_t w = 0, h = 0, b = 0, d = 0;
Window root = 0;
XGetGeometry(dpy, winID, &root, &x, &y, &w, &h, &b, &d);
XSetWindowAttributes attr(dummyAttr);
attr.colormap = XCreateColormap(dpy, root, visInfo->visual, AllocNone);
attr.event_mask = NoEventMask;
attr.backing_store = Always;
attr.bit_gravity = NorthWestGravity;
ULong_t mask = CWBackPixel | CWBorderPixel | CWColormap | CWEventMask | CWBackingStore | CWBitGravity;
Window glWin = XCreateWindow(dpy, winID, x, y, w, h, 0, visInfo->depth,
InputOutput, visInfo->visual, mask, &attr);
XMapWindow(dpy, glWin);
fWindowIndex = gVirtualX->AddWindow(glWin, w, h);
fInnerData.first = dpy;
fInnerData.second = visInfo;
try {
fGLContext.reset(new TGLContext(this));
fContainer.reset(new TGLWidgetContainer(this, gVirtualX->GetWindowID(fWindowIndex), GetViewPort()));
SetContainer(fContainer.get());
} catch (const std::exception &) {
gVirtualX->SelectWindow(fWindowIndex);
gVirtualX->CloseWindow();
XFree(fInnerData.second);
throw;
}
}
void TGLWidget::SetFormat()
{
}
#endif
void TGLWidget::Repaint()
{
Emit("Repaint()");
}
void TGLWidget::AddContext(TGLContext *ctx)
{
fValidContexts.insert(ctx);
}
void TGLWidget::RemoveContext(TGLContext *ctx)
{
std::set<TGLContext *>::iterator it = fValidContexts.find(ctx);
if (it != fValidContexts.end())
fValidContexts.erase(it);
}
void TGLWidget::ExtractViewport(Int_t *vp)const
{
vp[0] = 0;
vp[1] = 0;
vp[2] = GetWidth();
vp[3] = GetHeight();
}
Last update: Thu Jan 17 08:52:33 2008
This page has been automatically generated. If you have any comments or suggestions about the page layout send a mail to ROOT support, or contact the developers with any questions or problems regarding ROOT.