From a907bee20e23fa079eb406252a089ae8dc61d3d7 Mon Sep 17 00:00:00 2001 From: cxl Date: Wed, 5 Nov 2008 07:59:31 +0000 Subject: [PATCH] GLCtrl refactoring by Koldo git-svn-id: svn://ultimatepp.org/upp/trunk@598 f0d560ea-af0d-0410-9eb7-867de7ffcac7 --- uppsrc/GLCtrl/GLCtrl.cpp | 12 +++ uppsrc/GLCtrl/GLCtrl.h | 182 +++++++++++++--------------------- uppsrc/GLCtrl/GLPicking.cpp | 126 ++++++++++++----------- uppsrc/GLCtrl/Win32GLCtrl.cpp | 77 +++++--------- uppsrc/GLCtrl/X11GLCtrl.cpp | 84 +++------------- 5 files changed, 180 insertions(+), 301 deletions(-) diff --git a/uppsrc/GLCtrl/GLCtrl.cpp b/uppsrc/GLCtrl/GLCtrl.cpp index 52a5cc0b9..84f29c14d 100644 --- a/uppsrc/GLCtrl/GLCtrl.cpp +++ b/uppsrc/GLCtrl/GLCtrl.cpp @@ -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 GLCtrl::Pick(int x, int y) +{ + pane.ActivateContext(); + return picking.Pick(x, y, THISBACK2(GLResize, GetSize().cx, GetSize().cy), THISBACK(GLPickingPaint)); +} + END_UPP_NAMESPACE diff --git a/uppsrc/GLCtrl/GLCtrl.h b/uppsrc/GLCtrl/GLCtrl.h index 0c2995d0e..71ab12a4e 100644 --- a/uppsrc/GLCtrl/GLCtrl.h +++ b/uppsrc/GLCtrl/GLCtrl.h @@ -8,54 +8,38 @@ NAMESPACE_UPP -class GLPicking -{ -private: - static int const _bufferSize = 512; - bool _isPicking; - Point _pickPoint; - - Vector ParseHits(GLuint *buffer, int hits); - -public: - void InitPickMatrix(); - Vector Pick(int x, int y, Callback resizeCallback, Callback paintCallback); - - GLPicking(); -}; - #ifdef PLATFORM_X11 - -#include + #include +#endif class GLCtrl : public ParentCtrl { + typedef GLCtrl CLASSNAME; + +private: + class GLPicking + { + private: + static int const _bufferSize = 512; + bool _isPicking; + Point _pickPoint; + + Vector ParseHits(GLuint *buffer, int hits); + + public: + void InitPickMatrix(); + Vector 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 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 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 Pick(int x, int y); }; -#endif END_UPP_NAMESPACE diff --git a/uppsrc/GLCtrl/GLPicking.cpp b/uppsrc/GLCtrl/GLPicking.cpp index 07e6ea0a8..ddf416518 100644 --- a/uppsrc/GLCtrl/GLPicking.cpp +++ b/uppsrc/GLCtrl/GLPicking.cpp @@ -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 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(); - else - return ParseHits(buffer, hits); -} - -Vector 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 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 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(); + else + return ParseHits(buffer, hits); +} + +Vector 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 result; + for (GLuint i = 0; i < *minPtr; i++) + result.Add(*(minPtr + 3 + i)); + + return result; +} + +END_UPP_NAMESPACE diff --git a/uppsrc/GLCtrl/Win32GLCtrl.cpp b/uppsrc/GLCtrl/Win32GLCtrl.cpp index c4d7ea864..c26bc200b 100644 --- a/uppsrc/GLCtrl/Win32GLCtrl.cpp +++ b/uppsrc/GLCtrl/Win32GLCtrl.cpp @@ -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 GLCtrl::Pick(int x, int y) -{ - wglMakeCurrent(hDC, hRC); - Vector result = _picking.Pick(x, y, THISBACK2(GLResize, GetSize().cx, GetSize().cy), THISBACK(GLPickingPaint)); - wglMakeCurrent(NULL, NULL); - - return result; -} - #endif END_UPP_NAMESPACE diff --git a/uppsrc/GLCtrl/X11GLCtrl.cpp b/uppsrc/GLCtrl/X11GLCtrl.cpp index 117669db4..c6e0b407c 100644 --- a/uppsrc/GLCtrl/X11GLCtrl.cpp +++ b/uppsrc/GLCtrl/X11GLCtrl.cpp @@ -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 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 GLCtrl::GLPane::Pick(int x, int y) -{ - ActivateContext(); - - Vector 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