GLCtrl refactoring by Koldo

git-svn-id: svn://ultimatepp.org/upp/trunk@598 f0d560ea-af0d-0410-9eb7-867de7ffcac7
This commit is contained in:
cxl 2008-11-05 07:59:31 +00:00
parent 284f3e26cb
commit a907bee20e
5 changed files with 180 additions and 301 deletions

View file

@ -20,4 +20,16 @@ void GLCtrl::StdView()
glLoadIdentity();
}
Image GLCtrl::GLPane::MouseEvent(int event, Point p, int zdelta, dword keyflags)
{
p = p - GetScreenView().TopLeft() + ctrl->GetScreenView().TopLeft();
return ctrl->MouseEvent(event, p, zdelta, keyflags);
}
Vector<int> GLCtrl::Pick(int x, int y)
{
pane.ActivateContext();
return picking.Pick(x, y, THISBACK2(GLResize, GetSize().cx, GetSize().cy), THISBACK(GLPickingPaint));
}
END_UPP_NAMESPACE

View file

@ -8,54 +8,38 @@
NAMESPACE_UPP
class GLPicking
{
private:
static int const _bufferSize = 512;
bool _isPicking;
Point _pickPoint;
Vector<int> ParseHits(GLuint *buffer, int hits);
public:
void InitPickMatrix();
Vector<int> Pick(int x, int y, Callback resizeCallback, Callback paintCallback);
GLPicking();
};
#ifdef PLATFORM_X11
#include <GL/glx.h>
#include <GL/glx.h>
#endif
class GLCtrl : public ParentCtrl {
typedef GLCtrl CLASSNAME;
private:
class GLPicking
{
private:
static int const _bufferSize = 512;
bool _isPicking;
Point _pickPoint;
Vector<int> ParseHits(GLuint *buffer, int hits);
public:
void InitPickMatrix();
Vector<int> Pick(int x, int y, Callback resizeCallback, Callback paintCallback);
GLPicking() : _isPicking(false) {}
};
#ifdef PLATFORM_X11
class GLPane : public DHCtrl {
friend class GLCtrl;
GLCtrl *ctrl;
GLPicking _picking;
GLCtrl *ctrl;
// OpenGL Context
GLXContext WindowContext;
// Number of instances
static int Instances;
// Current instance number
int InstanceNum;
// OpenGL parameters
int DepthSize;
int StencilSize;
int NumberOfSamples;
bool DoubleBuffering;
bool MultiSampleBuffering;
// Currently activated context number
static int ContextActivated;
// Activates current OpenGL context
void ActivateContext();
// Ovverridden method to choose the correct visual
virtual XVisualInfo *CreateVisual(void);
@ -68,88 +52,51 @@ class GLCtrl : public ParentCtrl {
virtual void BeforeTerminate(void);
// Overridden method to resize GL windows
virtual void Resize(int w, int h);
// Internal OpenGL Paint method
void doPaint(void);
virtual void Layout();
// Paint method - with graphic context
// Called from DHCtrl - Graphic context is *not* used
virtual void Paint(Draw &/*draw*/);
public:
Image MouseEvent(int event, Point p, int zdelta, dword keyflags);
typedef GLCtrl CLASSNAME;
// Constructor class GLCtrl
GLPane( int depthsize = 24,
int stencilsize = 0,
bool doublebuffer = true,
bool multisamplebuffering = false,
int numberofsamples = 0 );
// Destructor class GLCtrl
GLPane() : WindowContext(NULL) { NoWantFocus(); }
~GLPane();
void InitPickMatrix() { _picking.InitPickMatrix(); }
Vector<int> Pick(int x, int y);
}; // END Class GLCtrl
GLPane pane;
protected:
// Overridable methods for derived controls
// Called after succesful OpenGL initialization
virtual void GLInit() {}
// Called just before OpenGL termination
virtual void GLDone() {}
// Called on resize events
virtual void GLResize( int w, int h ) {}
// Called on paint events
virtual void GLPaint() {}
virtual void GLPickingPaint() {}
void StdView();
void InitPickMatrix() { pane.InitPickMatrix(); }
Vector<int> Pick(int x, int y) { return pane.Pick(x, y); }
GLCtrl(int depthsize = 24, int stencilsize = 0, bool doublebuffer = true,
bool multisamplebuffering = false, int numberofsamples = 0);
};
virtual Image MouseEvent(int event, Point p, int zdelta, dword keyflags);
// Activates current OpenGL context
void ActivateContext();
};
#else
class GLCtrl : public ParentCtrl {
typedef GLCtrl CLASSNAME;
struct GLPane : DHCtrl {
friend class GLCtrl;
HDC hDC;
HGLRC hRC;
GLCtrl *ctrl;
public:
GLPane() : hDC(NULL), hRC(NULL) { NoWantFocus(); }
~GLPane() { Destroy(); }
virtual void State(int reason);
virtual LRESULT WindowProc(UINT message, WPARAM wParam, LPARAM lParam);
virtual Image MouseEvent(int event, Point p, int zdelta, dword keyflags);
GLPane() { NoWantFocus(); }
void Init();
void Destroy();
void ActivateContext();
};
#endif
friend class GLCtrl;
private:
HDC hDC;
HGLRC hRC;
GLPicking _picking;
GLPane glpane;
void OpenGL();
void CloseGL();
GLPicking picking;
GLPane pane;
int depthSize;
int stencilSize;
bool doubleBuffering;
bool multiSampleBuffering;
int numberOfSamples;
protected:
// Overridable methods for derived controls
@ -164,24 +111,29 @@ protected:
virtual void GLResize(int w, int h) {}
// Called on paint events
virtual void GLPaint();
virtual void GLPaint() { WhenGLPaint(); }
virtual void GLPickingPaint() {}
public:
Callback WhenGLPaint;
GLCtrl();
~GLCtrl();
void StdView();
GLCtrl(int depthsize = 24, int stencilsize = 0, bool doublebuffer = true,
bool multisamplebuffering = false, int numberofsamples = 0)
: depthSize(depthsize),
stencilSize(stencilsize),
doubleBuffering(doublebuffer),
multiSampleBuffering(multisamplebuffering),
numberOfSamples(numberofsamples)
{
pane.ctrl = this;
Add(pane.SizePos());
}
HDC GetDC() const { return hDC; }
HGLRC GetHGLRC() const { return hRC; }
void StdView();
void InitPickMatrix() { _picking.InitPickMatrix(); }
void InitPickMatrix() { picking.InitPickMatrix(); }
Vector<int> Pick(int x, int y);
};
#endif
END_UPP_NAMESPACE

View file

@ -1,65 +1,61 @@
#include "GLCtrl.h"
NAMESPACE_UPP
GLPicking::GLPicking()
: _isPicking(false)
{}
void GLPicking::InitPickMatrix()
{
if (_isPicking)
{
GLint viewport[4];
glGetIntegerv(GL_VIEWPORT, viewport);
gluPickMatrix(_pickPoint.x, viewport[3] - _pickPoint.y, 3, 3, viewport);
}
}
Vector<int> GLPicking::Pick(int x, int y, Callback resizeCallback, Callback paintCallback)
{
GLuint buffer[_bufferSize];
_pickPoint = Point(x, y);
glSelectBuffer(_bufferSize, buffer);
glRenderMode(GL_SELECT);
_isPicking = true;
resizeCallback();
glInitNames();
paintCallback();
_isPicking = false;
resizeCallback();
// returning to normal rendering mode
int hits = glRenderMode(GL_RENDER);
if (hits == 0)
return Vector<int>();
else
return ParseHits(buffer, hits);
}
Vector<int> GLPicking::ParseHits(GLuint *buffer, int hits)
{
GLuint *minPtr = buffer;
for (int i = 0; i < hits; i++)
{
if (*(buffer + 1) < *(minPtr + 1))
minPtr = buffer;
buffer += *buffer + 3;
}
Vector<int> result;
for (GLuint i = 0; i < *minPtr; i++)
result.Add(*(minPtr + 3 + i));
return result;
}
END_UPP_NAMESPACE
#include "GLCtrl.h"
NAMESPACE_UPP
void GLCtrl::GLPicking::InitPickMatrix()
{
if (_isPicking)
{
GLint viewport[4];
glGetIntegerv(GL_VIEWPORT, viewport);
gluPickMatrix(_pickPoint.x, viewport[3] - _pickPoint.y, 3, 3, viewport);
}
}
Vector<int> GLCtrl::GLPicking::Pick(int x, int y, Callback resizeCallback, Callback paintCallback)
{
GLuint buffer[_bufferSize];
_pickPoint = Point(x, y);
glSelectBuffer(_bufferSize, buffer);
glRenderMode(GL_SELECT);
_isPicking = true;
resizeCallback();
glInitNames();
paintCallback();
_isPicking = false;
resizeCallback();
// returning to normal rendering mode
int hits = glRenderMode(GL_RENDER);
if (hits == 0)
return Vector<int>();
else
return ParseHits(buffer, hits);
}
Vector<int> GLCtrl::GLPicking::ParseHits(GLuint *buffer, int hits)
{
GLuint *minPtr = buffer;
for (int i = 0; i < hits; i++)
{
if (*(buffer + 1) < *(minPtr + 1))
minPtr = buffer;
buffer += *buffer + 3;
}
Vector<int> result;
for (GLuint i = 0; i < *minPtr; i++)
result.Add(*(minPtr + 3 + i));
return result;
}
END_UPP_NAMESPACE

View file

@ -7,28 +7,9 @@ NAMESPACE_UPP
#pragma comment( lib, "opengl32.lib" ) // Search For OpenGL32.lib While Linking
#pragma comment( lib, "glu32.lib" ) // Search For GLu32.lib While Linking
GLCtrl::GLCtrl()
void GLCtrl::GLPane::Init()
{
hDC = NULL;
hRC = NULL;
glpane.ctrl = this;
Add(glpane.SizePos());
}
GLCtrl::~GLCtrl()
{
CloseGL();
}
Image GLCtrl::GLPane::MouseEvent(int event, Point p, int zdelta, dword keyflags)
{
p = p - GetScreenView().TopLeft() + ctrl->GetScreenView().TopLeft();
return ctrl->MouseEvent(event, p, zdelta, keyflags);
}
void GLCtrl::OpenGL()
{
HWND hwnd = glpane.GetHWND();
HWND hwnd = GetHWND();
if(!hwnd)
return;
hDC = ::GetDC(hwnd);
@ -38,18 +19,20 @@ void GLCtrl::OpenGL()
memset(&pfd, 0, sizeof(pfd));
pfd.nSize = sizeof(pfd);
pfd.nVersion = 1;
pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER | 0x00008000;
pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | 0x00008000;
if (ctrl->doubleBuffering) pfd.dwFlags |= PFD_DOUBLEBUFFER;
pfd.iPixelType = PFD_TYPE_RGBA;
pfd.cColorBits = 32;
pfd.cDepthBits = 32;
pfd.cDepthBits = ctrl->depthSize;
pfd.cStencilBits = ctrl->stencilSize;
pfd.iLayerType = PFD_MAIN_PLANE;
int pf = ChoosePixelFormat(hDC, &pfd);
if(!pf) {
CloseGL();
Destroy();
return;
}
if(!SetPixelFormat(hDC, pf, &pfd)) {
CloseGL();
Destroy();
return;
}
DescribePixelFormat(hDC, pf, sizeof(PIXELFORMATDESCRIPTOR), &pfd);
@ -58,61 +41,60 @@ void GLCtrl::OpenGL()
if (!hRC)
return;
wglMakeCurrent(hDC, hRC);
GLInit();
GLResize(GetSize().cx, GetSize().cy);
ActivateContext();
ctrl->GLInit();
ctrl->GLResize(GetSize().cx, GetSize().cy);
}
void GLCtrl::CloseGL()
void GLCtrl::GLPane::Destroy()
{
if (hDC != NULL && hRC != NULL)
{
wglMakeCurrent(hDC, hRC);
GLDone();
ActivateContext();
ctrl->GLDone();
wglMakeCurrent(NULL, NULL);
}
if(hRC)
wglDeleteContext(hRC);
if(hDC)
ReleaseDC(glpane.GetHWND(), hDC);
ReleaseDC(GetHWND(), hDC);
}
void GLCtrl::GLPaint()
void GLCtrl::GLPane::ActivateContext()
{
WhenGLPaint();
if (hRC != NULL && wglGetCurrentContext() != hRC)
wglMakeCurrent(hDC, hRC);
}
void GLCtrl::GLPane::State(int reason)
{
if (reason == CLOSE)
ctrl->CloseGL();
Destroy();
if (reason == LAYOUTPOS && ctrl->hDC != NULL && ctrl->hRC != NULL)
if (reason == LAYOUTPOS && hDC != NULL && hRC != NULL)
{
wglMakeCurrent(ctrl->hDC, ctrl->hRC);
ActivateContext();
ctrl->GLResize(GetSize().cx, GetSize().cy);
wglMakeCurrent(NULL, NULL);
}
DHCtrl::State(reason);
if (reason == OPEN)
ctrl->OpenGL();
Init();
}
LRESULT GLCtrl::GLPane::WindowProc(UINT message, WPARAM wParam, LPARAM lParam)
{
if(message == WM_PAINT && ctrl->hDC && ctrl->hRC)
if(message == WM_PAINT && hDC && hRC)
{
PAINTSTRUCT ps;
BeginPaint(GetHWND(), &ps);
wglMakeCurrent(ctrl->hDC, ctrl->hRC);
ActivateContext();
ctrl->GLPaint();
glFlush();
glFinish();
SwapBuffers(ctrl->hDC);
wglMakeCurrent(NULL, NULL);
if (ctrl->doubleBuffering) SwapBuffers(hDC);
EndPaint(GetHWND(), &ps);
return 0;
}
@ -122,15 +104,6 @@ LRESULT GLCtrl::GLPane::WindowProc(UINT message, WPARAM wParam, LPARAM lParam)
return DHCtrl::WindowProc(message, wParam, lParam);
}
Vector<int> GLCtrl::Pick(int x, int y)
{
wglMakeCurrent(hDC, hRC);
Vector<int> result = _picking.Pick(x, y, THISBACK2(GLResize, GetSize().cx, GetSize().cy), THISBACK(GLPickingPaint));
wglMakeCurrent(NULL, NULL);
return result;
}
#endif
END_UPP_NAMESPACE

View file

@ -4,28 +4,6 @@ NAMESPACE_UPP
#ifdef PLATFORM_X11
/////////////////////////////////////////////////////////////////////////////////////////
// Static members initialization
int GLCtrl::GLPane::Instances = 0;
int GLCtrl::GLPane::ContextActivated = 0;
/////////////////////////////////////////////////////////////////////////////////////////
// Constructor
GLCtrl::GLPane::GLPane(int depthsize, int stencilsize, bool doublebuffer,
bool multisamplebuffering, int numberofsamples )
{
// Sets the current instance number and updates total instances
InstanceNum = ++Instances;
WindowContext = NULL;
DepthSize = depthsize;
StencilSize = stencilsize;
DoubleBuffering = doublebuffer;
NumberOfSamples = numberofsamples;
NoWantFocus();
} // END Constructor class GLCtrl::GLPane
/////////////////////////////////////////////////////////////////////////////////////////
// Destructor
GLCtrl::GLPane::~GLPane()
@ -44,17 +22,17 @@ GLCtrl::GLPane::~GLPane()
XVisualInfo *GLCtrl::GLPane::CreateVisual(void)
{
Vector<int> visual;
visual << GLX_RGBA << GLX_DEPTH_SIZE << DepthSize;
visual << GLX_RGBA << GLX_DEPTH_SIZE << ctrl->depthSize;
if( StencilSize > 0 )
visual << GLX_STENCIL_SIZE << StencilSize;
if( ctrl->stencilSize > 0 )
visual << GLX_STENCIL_SIZE << ctrl->stencilSize;
if( DoubleBuffering )
if( ctrl->doubleBuffering )
visual << GLX_DOUBLEBUFFER;
if( MultiSampleBuffering && NumberOfSamples > 1 )
if( ctrl->multiSampleBuffering && ctrl->numberOfSamples > 1 )
{
visual << GLX_SAMPLE_BUFFERS_ARB << 1 << GLX_SAMPLES_ARB << NumberOfSamples;
visual << GLX_SAMPLE_BUFFERS_ARB << 1 << GLX_SAMPLES_ARB << ctrl->numberOfSamples;
}
visual << None;
@ -91,11 +69,8 @@ void GLCtrl::GLPane::SetAttributes(unsigned long &ValueMask, XSetWindowAttribute
// Activates current OpenGL context
void GLCtrl::GLPane::ActivateContext()
{
if( Instances > 0 && ContextActivated != InstanceNum )
{
if (WindowContext != NULL && glXGetCurrentContext() != WindowContext)
glXMakeCurrent( (Display*)Xdisplay, GetWindow(), WindowContext );
ContextActivated = InstanceNum;
}
}
/////////////////////////////////////////////////////////////////////////////////////////
@ -146,18 +121,21 @@ void GLCtrl::GLPane::BeforeTerminate(void)
/////////////////////////////////////////////////////////////////////////////////////////
// Overridden method to resize GL windows
void GLCtrl::GLPane::Resize(int x, int y)
void GLCtrl::GLPane::Layout()
{
// Activates the current context
ActivateContext();
if (glXGetCurrentContext() == NULL)
return;
// Calls user resize hook
ctrl->GLResize(x, y);
ctrl->GLResize(GetSize().cx, GetSize().cy);
} // END GLCtrl::GLPane::Resize()
/////////////////////////////////////////////////////////////////////////////////////////
// Internal OpenGL Paint method
void GLCtrl::GLPane::doPaint(void)
// Paint method - with graphic context
void GLCtrl::GLPane::Paint(Draw &draw)
{
// Activates the current context
ActivateContext();
@ -166,44 +144,12 @@ void GLCtrl::GLPane::doPaint(void)
ctrl->GLPaint();
// Swap buffers or flush as needed
if( DoubleBuffering )
if( ctrl->doubleBuffering )
glXSwapBuffers( (Display*)Xdisplay, GetWindow() ); // Buffer swap does implicit glFlush
else
glFlush();
} // END GLCtrl::GLPane::doPaint()
/////////////////////////////////////////////////////////////////////////////////////////
// Paint method - with graphic context
void GLCtrl::GLPane::Paint(Draw &draw)
{
// Calls internal OpenGL Paint method
doPaint();
} // END GLCtrl::GLPane::Paint()
Vector<int> GLCtrl::GLPane::Pick(int x, int y)
{
ActivateContext();
Vector<int> result = _picking.Pick(x, y,
callback2(ctrl, &GLCtrl::GLResize, GetSize().cx, GetSize().cy),
callback(ctrl, &GLCtrl::GLPickingPaint));
return result;
}
Image GLCtrl::GLPane::MouseEvent(int event, Point p, int zdelta, dword keyflags)
{
p = p - GetScreenView().TopLeft() + ctrl->GetScreenView().TopLeft();
return ctrl->MouseEvent(event, p, zdelta, keyflags);
}
GLCtrl::GLCtrl(int depthsize, int stencilsize, bool doublebuffer, bool multisamplebuffering, int numberofsamples)
: pane(depthsize, stencilsize, doublebuffer, multisamplebuffering, numberofsamples)
{
pane.ctrl = this;
Add(pane.SizePos());
}
#endif
END_UPP_NAMESPACE