1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/msw/glcanvas.cpp
3 // Purpose: wxGLCanvas, for using OpenGL with wxWidgets under MS Windows
4 // Author: Julian Smart
8 // Copyright: (c) Julian Smart
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
12 // ============================================================================
14 // ============================================================================
16 // ----------------------------------------------------------------------------
18 // ----------------------------------------------------------------------------
20 #include "wx/wxprec.h"
22 #if defined(__BORLANDC__)
32 #include "wx/module.h"
35 #include "wx/msw/private.h"
37 #include "wx/glcanvas.h"
39 // from src/msw/window.cpp
40 LRESULT WXDLLEXPORT APIENTRY _EXPORT
wxWndProc(HWND hWnd
, UINT message
,
41 WPARAM wParam
, LPARAM lParam
);
43 #ifdef GL_EXT_vertex_array
44 #define WXUNUSED_WITHOUT_GL_EXT_vertex_array(name) name
46 #define WXUNUSED_WITHOUT_GL_EXT_vertex_array(name) WXUNUSED(name)
49 // ----------------------------------------------------------------------------
50 // define possibly missing WGL constants
51 // ----------------------------------------------------------------------------
53 #ifndef WGL_ARB_pixel_format
54 #define WGL_DRAW_TO_WINDOW_ARB 0x2001
55 #define WGL_ACCELERATION_ARB 0x2003
56 #define WGL_NUMBER_OVERLAYS_ARB 0x2008
57 #define WGL_NUMBER_UNDERLAYS_ARB 0x2009
58 #define WGL_SUPPORT_OPENGL_ARB 0x2010
59 #define WGL_DOUBLE_BUFFER_ARB 0x2011
60 #define WGL_STEREO_ARB 0x2012
61 #define WGL_COLOR_BITS_ARB 0x2014
62 #define WGL_RED_BITS_ARB 0x2015
63 #define WGL_GREEN_BITS_ARB 0x2017
64 #define WGL_BLUE_BITS_ARB 0x2019
65 #define WGL_ALPHA_BITS_ARB 0x201B
66 #define WGL_ACCUM_RED_BITS_ARB 0x201E
67 #define WGL_ACCUM_GREEN_BITS_ARB 0x201F
68 #define WGL_ACCUM_BLUE_BITS_ARB 0x2020
69 #define WGL_ACCUM_ALPHA_BITS_ARB 0x2021
70 #define WGL_DEPTH_BITS_ARB 0x2022
71 #define WGL_STENCIL_BITS_ARB 0x2023
72 #define WGL_AUX_BUFFERS_ARB 0x2024
73 #define WGL_FULL_ACCELERATION_ARB 0x2027
76 #ifndef WGL_ARB_multisample
77 #define WGL_SAMPLE_BUFFERS_ARB 0x2041
78 #define WGL_SAMPLES_ARB 0x2042
81 // ----------------------------------------------------------------------------
83 // ----------------------------------------------------------------------------
86 The following two compiler directives are specific to the Microsoft Visual
87 C++ family of compilers
89 Fundementally what they do is instruct the linker to use these two libraries
90 for the resolution of symbols. In essence, this is the equivalent of adding
91 these two libraries to either the Makefile or project file.
93 This is NOT a recommended technique, and certainly is unlikely to be used
94 anywhere else in wxWidgets given it is so specific to not only wxMSW, but
95 also the VC compiler. However, in the case of opengl support, it's an
96 applicable technique as opengl is optional in setup.h This code (wrapped by
97 wxUSE_GLCANVAS), now allows opengl support to be added purely by modifying
98 setup.h rather than by having to modify either the project or DSP fle.
100 See MSDN for further information on the exact usage of these commands.
103 # pragma comment( lib, "opengl32" )
104 # pragma comment( lib, "glu32" )
107 // ----------------------------------------------------------------------------
109 // ----------------------------------------------------------------------------
111 static const wxChar
*wxGLCanvasClassName
= wxT("wxGLCanvasClass");
112 static const wxChar
*wxGLCanvasClassNameNoRedraw
= wxT("wxGLCanvasClassNR");
114 // ============================================================================
116 // ============================================================================
118 // ----------------------------------------------------------------------------
119 // wxGLModule is responsible for unregistering wxGLCanvasClass Windows class
120 // ----------------------------------------------------------------------------
122 class wxGLModule
: public wxModule
125 bool OnInit() { return true; }
126 void OnExit() { UnregisterClasses(); }
128 // register the GL classes if not done yet, return true if ok, false if
129 // registration failed
130 static bool RegisterClasses();
132 // unregister the classes, done automatically on program termination
133 static void UnregisterClasses();
136 // wxGLCanvas is only used from the main thread so this is MT-ok
137 static bool ms_registeredGLClasses
;
139 DECLARE_DYNAMIC_CLASS(wxGLModule
)
142 IMPLEMENT_DYNAMIC_CLASS(wxGLModule
, wxModule
)
144 bool wxGLModule::ms_registeredGLClasses
= false;
147 bool wxGLModule::RegisterClasses()
149 if ( ms_registeredGLClasses
)
152 // We have to register a special window class because we need the CS_OWNDC
153 // style for GLCanvas: some OpenGL drivers are buggy and don't work with
154 // windows without this style
157 // the fields which are common to all classes
158 wndclass
.lpfnWndProc
= (WNDPROC
)wxWndProc
;
159 wndclass
.cbClsExtra
= 0;
160 wndclass
.cbWndExtra
= sizeof( DWORD
); // VZ: what is this DWORD used for?
161 wndclass
.hInstance
= wxhInstance
;
162 wndclass
.hIcon
= (HICON
) NULL
;
163 wndclass
.hCursor
= ::LoadCursor((HINSTANCE
)NULL
, IDC_ARROW
);
164 wndclass
.lpszMenuName
= NULL
;
166 // Register the GLCanvas class name
167 wndclass
.hbrBackground
= (HBRUSH
)NULL
;
168 wndclass
.lpszClassName
= wxGLCanvasClassName
;
169 wndclass
.style
= CS_HREDRAW
| CS_VREDRAW
| CS_DBLCLKS
| CS_OWNDC
;
171 if ( !::RegisterClass(&wndclass
) )
173 wxLogLastError(wxT("RegisterClass(wxGLCanvasClass)"));
177 // Register the GLCanvas class name for windows which don't do full repaint
179 wndclass
.lpszClassName
= wxGLCanvasClassNameNoRedraw
;
180 wndclass
.style
&= ~(CS_HREDRAW
| CS_VREDRAW
);
182 if ( !::RegisterClass(&wndclass
) )
184 wxLogLastError(wxT("RegisterClass(wxGLCanvasClassNameNoRedraw)"));
186 ::UnregisterClass(wxGLCanvasClassName
, wxhInstance
);
191 ms_registeredGLClasses
= true;
197 void wxGLModule::UnregisterClasses()
199 // we need to unregister the classes in case we're in a DLL which is
200 // unloaded and then loaded again because if we don't, the registration is
201 // going to fail in wxGLCanvas::Create() the next time we're loaded
202 if ( ms_registeredGLClasses
)
204 ::UnregisterClass(wxGLCanvasClassName
, wxhInstance
);
205 ::UnregisterClass(wxGLCanvasClassNameNoRedraw
, wxhInstance
);
207 ms_registeredGLClasses
= false;
211 // ----------------------------------------------------------------------------
213 // ----------------------------------------------------------------------------
215 IMPLEMENT_CLASS(wxGLContext
, wxObject
)
217 wxGLContext::wxGLContext(wxGLCanvas
*win
, const wxGLContext
* other
)
219 m_glContext
= wglCreateContext(win
->GetHDC());
220 wxCHECK_RET( m_glContext
, wxT("Couldn't create OpenGL context") );
224 if ( !wglShareLists(other
->m_glContext
, m_glContext
) )
225 wxLogLastError(_T("wglShareLists"));
229 wxGLContext::~wxGLContext()
231 // note that it's ok to delete the context even if it's the current one
232 wglDeleteContext(m_glContext
);
235 bool wxGLContext::SetCurrent(const wxGLCanvas
& win
) const
237 if ( !wglMakeCurrent(win
.GetHDC(), m_glContext
) )
239 wxLogLastError(_T("wglMakeCurrent"));
245 // ============================================================================
247 // ============================================================================
249 IMPLEMENT_CLASS(wxGLCanvas
, wxWindow
)
251 BEGIN_EVENT_TABLE(wxGLCanvas
, wxWindow
)
252 EVT_PALETTE_CHANGED(wxGLCanvas::OnPaletteChanged
)
253 EVT_QUERY_NEW_PALETTE(wxGLCanvas::OnQueryNewPalette
)
256 // ----------------------------------------------------------------------------
257 // wxGLCanvas construction
258 // ----------------------------------------------------------------------------
260 static int ChoosePixelFormatARB(HDC hdc
, const int *attribList
);
262 void wxGLCanvas::Init()
264 #if WXWIN_COMPATIBILITY_2_8
270 wxGLCanvas::wxGLCanvas(wxWindow
*parent
,
272 const int *attribList
,
276 const wxString
& name
,
277 const wxPalette
& palette
)
281 (void)Create(parent
, id
, pos
, size
, style
, name
, attribList
, palette
);
284 wxGLCanvas::~wxGLCanvas()
286 ::ReleaseDC(GetHwnd(), m_hDC
);
289 // Replaces wxWindow::Create functionality, since we need to use a different
291 bool wxGLCanvas::CreateWindow(wxWindow
*parent
,
296 const wxString
& name
)
298 wxCHECK_MSG( parent
, false, wxT("can't create wxWindow without parent") );
300 if ( !wxGLModule::RegisterClasses() )
302 wxLogError(_("Failed to register OpenGL window class."));
307 if ( !CreateBase(parent
, id
, pos
, size
, style
, wxDefaultValidator
, name
) )
310 parent
->AddChild(this);
313 A general rule with OpenGL and Win32 is that any window that will have a
314 HGLRC built for it must have two flags: WS_CLIPCHILDREN & WS_CLIPSIBLINGS.
315 You can find references about this within the knowledge base and most OpenGL
316 books that contain the wgl function descriptions.
319 DWORD msflags
= WS_CHILD
| WS_VISIBLE
| WS_CLIPSIBLINGS
| WS_CLIPCHILDREN
;
320 msflags
|= MSWGetStyle(style
, &exStyle
);
322 if ( !MSWCreate(wxGLCanvasClassName
, NULL
, pos
, size
, msflags
, exStyle
) )
325 m_hDC
= ::GetDC(GetHwnd());
332 bool wxGLCanvas::Create(wxWindow
*parent
,
337 const wxString
& name
,
338 const int *attribList
,
339 const wxPalette
& palette
)
341 // Create the window first: we will either use it as is or use it to query
342 // for multisampling support and recreate it later with another pixel format
343 if ( !CreateWindow(parent
, id
, pos
, size
, style
, name
) )
346 PIXELFORMATDESCRIPTOR pfd
;
347 const int setupVal
= DoSetup(pfd
, attribList
);
348 if ( setupVal
== 0 ) // PixelFormat error
351 if ( setupVal
== -1 ) // FSAA requested
353 // now that we have a valid OpenGL window, query it for FSAA support
356 wxGLContext
ctx(this);
357 ctx
.SetCurrent(*this);
358 pixelFormat
= ::ChoosePixelFormatARB(m_hDC
, attribList
);
361 if ( pixelFormat
> 0 )
363 // from http://msdn.microsoft.com/en-us/library/ms537559(VS.85).aspx:
365 // Setting the pixel format of a window more than once can
366 // lead to significant complications for the Window Manager
367 // and for multithread applications, so it is not allowed. An
368 // application can only set the pixel format of a window one
369 // time. Once a window's pixel format is set, it cannot be
372 // so we need to delete the old window and create the new one
375 ::ReleaseDC(GetHwnd(), m_hDC
);
378 parent
->RemoveChild(this);
379 const HWND hwnd
= GetHwnd();
380 DissociateHandle(); // will do SetHWND(0);
381 ::DestroyWindow(hwnd
);
383 // now recreate with FSAA pixelFormat
384 if ( !CreateWindow(parent
, id
, pos
, size
, style
, name
) )
387 if ( !::SetPixelFormat(m_hDC
, pixelFormat
, &pfd
) )
389 wxLogLastError(_T("SetPixelFormat"));
396 if ( !SetupPalette(palette
) )
398 #else // !wxUSE_PALETTE
399 wxUnusedVar(palette
);
400 #endif // wxUSE_PALETTE/!wxUSE_PALETTE
405 // ----------------------------------------------------------------------------
407 // ----------------------------------------------------------------------------
409 bool wxGLCanvas::SwapBuffers()
411 if ( !::SwapBuffers(m_hDC
) )
413 wxLogLastError(_T("SwapBuffers"));
421 // ----------------------------------------------------------------------------
422 // multi sample support
423 // ----------------------------------------------------------------------------
425 // this macro defines a variable of type "name_t" called "name" and initializes
426 // it with the pointer to WGL function "name" (which may be NULL)
427 #define wxDEFINE_WGL_FUNC(name) \
428 name##_t name = (name##_t)wglGetProcAddress(#name)
431 bool wxGLCanvasBase::IsExtensionSupported(const char *extension
)
433 static const char *s_extensionsList
= (char *)wxUIntPtr(-1);
434 if ( s_extensionsList
== (char *)wxUIntPtr(-1) )
436 typedef const char * (WINAPI
*wglGetExtensionsStringARB_t
)(HDC hdc
);
438 wxDEFINE_WGL_FUNC(wglGetExtensionsStringARB
);
439 if ( wglGetExtensionsStringARB
)
441 s_extensionsList
= wglGetExtensionsStringARB(wglGetCurrentDC());
445 typedef const char * (WINAPI
* wglGetExtensionsStringEXT_t
)();
447 wxDEFINE_WGL_FUNC(wglGetExtensionsStringEXT
);
448 if ( wglGetExtensionsStringEXT
)
450 s_extensionsList
= wglGetExtensionsStringEXT();
454 s_extensionsList
= NULL
;
459 return s_extensionsList
&& IsExtensionInList(s_extensionsList
, extension
);
462 // this is a wrapper around wglChoosePixelFormatARB(): returns the pixel format
463 // index matching the given attributes on success or 0 on failure
464 static int ChoosePixelFormatARB(HDC hdc
, const int *attribList
)
466 if ( !wxGLCanvas::IsExtensionSupported("WGL_ARB_multisample") )
469 typedef BOOL (WINAPI
* wglChoosePixelFormatARB_t
)
471 const int *piAttribIList
,
472 const FLOAT
*pfAttribFList
,
478 wxDEFINE_WGL_FUNC(wglChoosePixelFormatARB
);
479 if ( !wglChoosePixelFormatARB
)
480 return 0; // should not occur if extension is supported
482 int iAttributes
[128];
483 int dst
= 0; // index in iAttributes array
485 #define ADD_ATTR(attr, value) \
486 iAttributes[dst++] = attr; iAttributes[dst++] = value
488 ADD_ATTR( WGL_DRAW_TO_WINDOW_ARB
, GL_TRUE
);
489 ADD_ATTR( WGL_SUPPORT_OPENGL_ARB
, GL_TRUE
);
490 ADD_ATTR( WGL_ACCELERATION_ARB
, WGL_FULL_ACCELERATION_ARB
);
494 ADD_ATTR( WGL_COLOR_BITS_ARB
, 24 );
495 ADD_ATTR( WGL_ALPHA_BITS_ARB
, 8 );
496 ADD_ATTR( WGL_DEPTH_BITS_ARB
, 16 );
497 ADD_ATTR( WGL_STENCIL_BITS_ARB
, 0 );
498 ADD_ATTR( WGL_DOUBLE_BUFFER_ARB
, GL_TRUE
);
499 ADD_ATTR( WGL_SAMPLE_BUFFERS_ARB
, GL_TRUE
);
500 ADD_ATTR( WGL_SAMPLES_ARB
, 4 );
502 else // have custom attributes
504 #define ADD_ATTR_VALUE(attr) ADD_ATTR(attr, attribList[src++])
507 while ( attribList
[src
] )
509 switch ( attribList
[src
++] )
512 ADD_ATTR( WGL_COLOR_BITS_ARB
, 24 );
513 ADD_ATTR( WGL_ALPHA_BITS_ARB
, 8 );
516 case WX_GL_BUFFER_SIZE
:
517 ADD_ATTR_VALUE( WGL_COLOR_BITS_ARB
);
521 if ( attribList
[src
] > 0 )
523 ADD_ATTR( WGL_NUMBER_OVERLAYS_ARB
, 1 );
525 else if ( attribList
[src
] <0 )
527 ADD_ATTR( WGL_NUMBER_UNDERLAYS_ARB
, 1 );
531 src
++; // skip the value in any case
534 case WX_GL_DOUBLEBUFFER
:
535 ADD_ATTR( WGL_DOUBLE_BUFFER_ARB
, GL_TRUE
);
539 ADD_ATTR( WGL_STEREO_ARB
, GL_TRUE
);
542 case WX_GL_AUX_BUFFERS
:
543 ADD_ATTR_VALUE( WGL_AUX_BUFFERS_ARB
);
547 ADD_ATTR_VALUE( WGL_RED_BITS_ARB
);
550 case WX_GL_MIN_GREEN
:
551 ADD_ATTR_VALUE( WGL_GREEN_BITS_ARB
);
555 ADD_ATTR_VALUE( WGL_BLUE_BITS_ARB
);
558 case WX_GL_MIN_ALPHA
:
559 ADD_ATTR_VALUE( WGL_ALPHA_BITS_ARB
);
562 case WX_GL_DEPTH_SIZE
:
563 ADD_ATTR_VALUE( WGL_DEPTH_BITS_ARB
);
566 case WX_GL_STENCIL_SIZE
:
567 ADD_ATTR_VALUE( WGL_STENCIL_BITS_ARB
);
570 case WX_GL_MIN_ACCUM_RED
:
571 ADD_ATTR_VALUE( WGL_ACCUM_RED_BITS_ARB
);
574 case WX_GL_MIN_ACCUM_GREEN
:
575 ADD_ATTR_VALUE( WGL_ACCUM_GREEN_BITS_ARB
);
578 case WX_GL_MIN_ACCUM_BLUE
:
579 ADD_ATTR_VALUE( WGL_ACCUM_BLUE_BITS_ARB
);
582 case WX_GL_MIN_ACCUM_ALPHA
:
583 ADD_ATTR_VALUE( WGL_ACCUM_ALPHA_BITS_ARB
);
586 case WX_GL_SAMPLE_BUFFERS
:
587 ADD_ATTR_VALUE( WGL_SAMPLE_BUFFERS_ARB
);
591 ADD_ATTR_VALUE( WGL_SAMPLES_ARB
);
596 #undef ADD_ATTR_VALUE
601 iAttributes
[dst
++] = 0;
605 if ( !wglChoosePixelFormatARB(hdc
, iAttributes
, NULL
, 1, &pf
, &numFormats
) )
607 wxLogLastError(_T("wglChoosePixelFormatARB"));
614 // ----------------------------------------------------------------------------
615 // pixel format stuff
616 // ----------------------------------------------------------------------------
618 // returns true if pfd was adjusted accordingly to attributes provided, false
619 // if there is an error with attributes or -1 if the attributes indicate
620 // features not supported by ChoosePixelFormat() at all (currently only multi
623 AdjustPFDForAttributes(PIXELFORMATDESCRIPTOR
& pfd
, const int *attribList
)
628 // remove default attributes
629 pfd
.dwFlags
&= ~PFD_DOUBLEBUFFER
;
630 pfd
.iPixelType
= PFD_TYPE_COLORINDEX
;
632 bool requestFSAA
= false;
633 for ( int arg
= 0; attribList
[arg
]; )
635 switch ( attribList
[arg
++] )
638 pfd
.iPixelType
= PFD_TYPE_RGBA
;
641 case WX_GL_BUFFER_SIZE
:
642 pfd
.cColorBits
= attribList
[arg
++];
646 // this member looks like it may be obsolete
647 if ( attribList
[arg
] > 0 )
648 pfd
.iLayerType
= PFD_OVERLAY_PLANE
;
649 else if ( attribList
[arg
] < 0 )
650 pfd
.iLayerType
= (BYTE
)PFD_UNDERLAY_PLANE
;
652 pfd
.iLayerType
= PFD_MAIN_PLANE
;
656 case WX_GL_DOUBLEBUFFER
:
657 pfd
.dwFlags
|= PFD_DOUBLEBUFFER
;
661 pfd
.dwFlags
|= PFD_STEREO
;
664 case WX_GL_AUX_BUFFERS
:
665 pfd
.cAuxBuffers
= attribList
[arg
++];
669 pfd
.cColorBits
+= (pfd
.cRedBits
= attribList
[arg
++]);
672 case WX_GL_MIN_GREEN
:
673 pfd
.cColorBits
+= (pfd
.cGreenBits
= attribList
[arg
++]);
677 pfd
.cColorBits
+= (pfd
.cBlueBits
= attribList
[arg
++]);
680 case WX_GL_MIN_ALPHA
:
681 // doesn't count in cColorBits
682 pfd
.cAlphaBits
= attribList
[arg
++];
685 case WX_GL_DEPTH_SIZE
:
686 pfd
.cDepthBits
= attribList
[arg
++];
689 case WX_GL_STENCIL_SIZE
:
690 pfd
.cStencilBits
= attribList
[arg
++];
693 case WX_GL_MIN_ACCUM_RED
:
694 pfd
.cAccumBits
+= (pfd
.cAccumRedBits
= attribList
[arg
++]);
697 case WX_GL_MIN_ACCUM_GREEN
:
698 pfd
.cAccumBits
+= (pfd
.cAccumGreenBits
= attribList
[arg
++]);
701 case WX_GL_MIN_ACCUM_BLUE
:
702 pfd
.cAccumBits
+= (pfd
.cAccumBlueBits
= attribList
[arg
++]);
705 case WX_GL_MIN_ACCUM_ALPHA
:
706 pfd
.cAccumBits
+= (pfd
.cAccumAlphaBits
= attribList
[arg
++]);
709 case WX_GL_SAMPLE_BUFFERS
:
711 // There is no support for multisample when using PIXELFORMATDESCRIPTOR
712 requestFSAA
= true; // Remember that multi sample is requested.
713 arg
++; // will call ChoosePixelFormatARB() later
718 return requestFSAA
? -1 : 1;
723 wxGLCanvas::ChooseMatchingPixelFormat(HDC hdc
,
724 const int *attribList
,
725 PIXELFORMATDESCRIPTOR
*ppfd
)
727 // default neutral pixel format
728 PIXELFORMATDESCRIPTOR pfd
=
730 sizeof(PIXELFORMATDESCRIPTOR
), // size
734 PFD_DOUBLEBUFFER
, // use double-buffering by default
735 PFD_TYPE_RGBA
, // default pixel type
736 0, // preferred color depth (don't care)
737 0, 0, 0, 0, 0, 0, // color bits and shift bits (ignored)
738 0, 0, // alpha bits and shift (ignored)
739 0, // accumulation total bits
740 0, 0, 0, 0, // accumulator RGBA bits (not used)
742 0, // no stencil buffer
743 0, // no auxiliary buffers
744 PFD_MAIN_PLANE
, // main layer
746 0, 0, 0, // no layer, visible, damage masks
754 // adjust the PFD using the provided attributes and also check if we can
755 // use PIXELFORMATDESCRIPTOR at all: if multisampling is requested, we
756 // can't as it's not supported by ChoosePixelFormat()
757 switch ( AdjustPFDForAttributes(*ppfd
, attribList
) )
760 return ::ChoosePixelFormat(hdc
, ppfd
);
763 wxFAIL_MSG( "unexpected AdjustPFDForAttributes() return value" );
767 // error in attributes
771 // requestFSAA == true, will continue as normal
772 // in order to query later for a FSAA pixelformat
778 bool wxGLCanvasBase::IsDisplaySupported(const int *attribList
)
780 // We need a device context to test the pixel format, so get one
781 // for the root window.
782 return wxGLCanvas::ChooseMatchingPixelFormat(ScreenHDC(), attribList
) > 0;
785 int wxGLCanvas::DoSetup(PIXELFORMATDESCRIPTOR
&pfd
, const int *attribList
)
787 int pixelFormat
= ChooseMatchingPixelFormat(m_hDC
, attribList
, &pfd
);
789 const bool requestFSAA
= pixelFormat
== -1;
791 pixelFormat
= ::ChoosePixelFormat(m_hDC
, &pfd
);
795 wxLogLastError(_T("ChoosePixelFormat"));
799 if ( !::SetPixelFormat(m_hDC
, pixelFormat
, &pfd
) )
801 wxLogLastError(_T("SetPixelFormat"));
805 return requestFSAA
? -1 : 1;
808 // ----------------------------------------------------------------------------
810 // ----------------------------------------------------------------------------
814 bool wxGLCanvas::SetupPalette(const wxPalette
& palette
)
816 const int pixelFormat
= ::GetPixelFormat(m_hDC
);
819 wxLogLastError(_T("GetPixelFormat"));
823 PIXELFORMATDESCRIPTOR pfd
;
824 if ( !::DescribePixelFormat(m_hDC
, pixelFormat
, sizeof(pfd
), &pfd
) )
826 wxLogLastError(_T("DescribePixelFormat"));
830 if ( !(pfd
.dwFlags
& PFD_NEED_PALETTE
) )
835 if ( !m_palette
.Ok() )
837 m_palette
= CreateDefaultPalette();
838 if ( !m_palette
.Ok() )
842 if ( !::SelectPalette(m_hDC
, GetHpaletteOf(m_palette
), FALSE
) )
844 wxLogLastError(_T("SelectPalette"));
848 if ( ::RealizePalette(m_hDC
) == GDI_ERROR
)
850 wxLogLastError(_T("RealizePalette"));
857 wxPalette
wxGLCanvas::CreateDefaultPalette()
859 PIXELFORMATDESCRIPTOR pfd
;
861 int pixelFormat
= GetPixelFormat(m_hDC
);
863 DescribePixelFormat(m_hDC
, pixelFormat
, sizeof(PIXELFORMATDESCRIPTOR
), &pfd
);
865 paletteSize
= 1 << pfd
.cColorBits
;
868 (LOGPALETTE
*) malloc(sizeof(LOGPALETTE
) + paletteSize
* sizeof(PALETTEENTRY
));
869 pPal
->palVersion
= 0x300;
870 pPal
->palNumEntries
= (WORD
)paletteSize
;
872 /* build a simple RGB color palette */
873 int redMask
= (1 << pfd
.cRedBits
) - 1;
874 int greenMask
= (1 << pfd
.cGreenBits
) - 1;
875 int blueMask
= (1 << pfd
.cBlueBits
) - 1;
877 for (int i
=0; i
<paletteSize
; ++i
)
879 pPal
->palPalEntry
[i
].peRed
=
880 (BYTE
)((((i
>> pfd
.cRedShift
) & redMask
) * 255) / redMask
);
881 pPal
->palPalEntry
[i
].peGreen
=
882 (BYTE
)((((i
>> pfd
.cGreenShift
) & greenMask
) * 255) / greenMask
);
883 pPal
->palPalEntry
[i
].peBlue
=
884 (BYTE
)((((i
>> pfd
.cBlueShift
) & blueMask
) * 255) / blueMask
);
885 pPal
->palPalEntry
[i
].peFlags
= 0;
888 HPALETTE hPalette
= CreatePalette(pPal
);
892 palette
.SetHPALETTE((WXHPALETTE
) hPalette
);
897 void wxGLCanvas::OnQueryNewPalette(wxQueryNewPaletteEvent
& event
)
899 /* realize palette if this is the current window */
900 if ( GetPalette()->Ok() ) {
901 ::UnrealizeObject((HPALETTE
) GetPalette()->GetHPALETTE());
902 ::SelectPalette(GetHDC(), (HPALETTE
) GetPalette()->GetHPALETTE(), FALSE
);
903 ::RealizePalette(GetHDC());
905 event
.SetPaletteRealized(true);
908 event
.SetPaletteRealized(false);
911 void wxGLCanvas::OnPaletteChanged(wxPaletteChangedEvent
& event
)
913 /* realize palette if this is *not* the current window */
915 GetPalette()->Ok() && (this != event
.GetChangedWindow()) )
917 ::UnrealizeObject((HPALETTE
) GetPalette()->GetHPALETTE());
918 ::SelectPalette(GetHDC(), (HPALETTE
) GetPalette()->GetHPALETTE(), FALSE
);
919 ::RealizePalette(GetHDC());
924 #endif // wxUSE_PALETTE
926 // ----------------------------------------------------------------------------
927 // deprecated wxGLCanvas methods using implicit wxGLContext
928 // ----------------------------------------------------------------------------
930 // deprecated constructors creating an implicit m_glContext
931 #if WXWIN_COMPATIBILITY_2_8
933 wxGLCanvas::wxGLCanvas(wxWindow
*parent
,
938 const wxString
& name
,
939 const int *attribList
,
940 const wxPalette
& palette
)
944 if ( Create(parent
, id
, pos
, size
, style
, name
, attribList
, palette
) )
945 m_glContext
= new wxGLContext(this);
948 wxGLCanvas::wxGLCanvas(wxWindow
*parent
,
949 const wxGLContext
*shared
,
954 const wxString
& name
,
955 const int *attribList
,
956 const wxPalette
& palette
)
960 if ( Create(parent
, id
, pos
, size
, style
, name
, attribList
, palette
) )
961 m_glContext
= new wxGLContext(this, shared
);
964 wxGLCanvas::wxGLCanvas(wxWindow
*parent
,
965 const wxGLCanvas
*shared
,
970 const wxString
& name
,
971 const int *attribList
,
972 const wxPalette
& palette
)
976 if ( Create(parent
, id
, pos
, size
, style
, name
, attribList
, palette
) )
977 m_glContext
= new wxGLContext(this, shared
? shared
->m_glContext
: NULL
);
980 #endif // WXWIN_COMPATIBILITY_2_8
983 // ----------------------------------------------------------------------------
985 // ----------------------------------------------------------------------------
987 bool wxGLApp::InitGLVisual(const int *attribList
)
989 if ( !wxGLCanvas::ChooseMatchingPixelFormat(ScreenHDC(), attribList
) )
991 wxLogError(_("Failed to initialize OpenGL"));
998 #endif // wxUSE_GLCANVAS