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_NUMBER_PIXEL_FORMATS_ARB 0x2000
55 #define WGL_DRAW_TO_WINDOW_ARB 0x2001
56 #define WGL_DRAW_TO_BITMAP_ARB 0x2002
57 #define WGL_ACCELERATION_ARB 0x2003
58 #define WGL_NEED_PALETTE_ARB 0x2004
59 #define WGL_NEED_SYSTEM_PALETTE_ARB 0x2005
60 #define WGL_SWAP_LAYER_BUFFERS_ARB 0x2006
61 #define WGL_SWAP_METHOD_ARB 0x2007
62 #define WGL_NUMBER_OVERLAYS_ARB 0x2008
63 #define WGL_NUMBER_UNDERLAYS_ARB 0x2009
64 #define WGL_TRANSPARENT_ARB 0x200A
65 #define WGL_TRANSPARENT_RED_VALUE_ARB 0x2037
66 #define WGL_TRANSPARENT_GREEN_VALUE_ARB 0x2038
67 #define WGL_TRANSPARENT_BLUE_VALUE_ARB 0x2039
68 #define WGL_TRANSPARENT_ALPHA_VALUE_ARB 0x203A
69 #define WGL_TRANSPARENT_INDEX_VALUE_ARB 0x203B
70 #define WGL_SHARE_DEPTH_ARB 0x200C
71 #define WGL_SHARE_STENCIL_ARB 0x200D
72 #define WGL_SHARE_ACCUM_ARB 0x200E
73 #define WGL_SUPPORT_GDI_ARB 0x200F
74 #define WGL_SUPPORT_OPENGL_ARB 0x2010
75 #define WGL_DOUBLE_BUFFER_ARB 0x2011
76 #define WGL_STEREO_ARB 0x2012
77 #define WGL_PIXEL_TYPE_ARB 0x2013
78 #define WGL_COLOR_BITS_ARB 0x2014
79 #define WGL_RED_BITS_ARB 0x2015
80 #define WGL_RED_SHIFT_ARB 0x2016
81 #define WGL_GREEN_BITS_ARB 0x2017
82 #define WGL_GREEN_SHIFT_ARB 0x2018
83 #define WGL_BLUE_BITS_ARB 0x2019
84 #define WGL_BLUE_SHIFT_ARB 0x201A
85 #define WGL_ALPHA_BITS_ARB 0x201B
86 #define WGL_ALPHA_SHIFT_ARB 0x201C
87 #define WGL_ACCUM_BITS_ARB 0x201D
88 #define WGL_ACCUM_RED_BITS_ARB 0x201E
89 #define WGL_ACCUM_GREEN_BITS_ARB 0x201F
90 #define WGL_ACCUM_BLUE_BITS_ARB 0x2020
91 #define WGL_ACCUM_ALPHA_BITS_ARB 0x2021
92 #define WGL_DEPTH_BITS_ARB 0x2022
93 #define WGL_STENCIL_BITS_ARB 0x2023
94 #define WGL_AUX_BUFFERS_ARB 0x2024
95 #define WGL_NO_ACCELERATION_ARB 0x2025
96 #define WGL_GENERIC_ACCELERATION_ARB 0x2026
97 #define WGL_FULL_ACCELERATION_ARB 0x2027
98 #define WGL_SWAP_EXCHANGE_ARB 0x2028
99 #define WGL_SWAP_COPY_ARB 0x2029
100 #define WGL_SWAP_UNDEFINED_ARB 0x202A
101 #define WGL_TYPE_RGBA_ARB 0x202B
102 #define WGL_TYPE_COLORINDEX_ARB 0x202C
105 #ifndef WGL_ARB_multisample
106 #define WGL_SAMPLE_BUFFERS_ARB 0x2041
107 #define WGL_SAMPLES_ARB 0x2042
110 // ----------------------------------------------------------------------------
112 // ----------------------------------------------------------------------------
115 The following two compiler directives are specific to the Microsoft Visual
116 C++ family of compilers
118 Fundementally what they do is instruct the linker to use these two libraries
119 for the resolution of symbols. In essence, this is the equivalent of adding
120 these two libraries to either the Makefile or project file.
122 This is NOT a recommended technique, and certainly is unlikely to be used
123 anywhere else in wxWidgets given it is so specific to not only wxMSW, but
124 also the VC compiler. However, in the case of opengl support, it's an
125 applicable technique as opengl is optional in setup.h This code (wrapped by
126 wxUSE_GLCANVAS), now allows opengl support to be added purely by modifying
127 setup.h rather than by having to modify either the project or DSP fle.
129 See MSDN for further information on the exact usage of these commands.
132 # pragma comment( lib, "opengl32" )
133 # pragma comment( lib, "glu32" )
136 // ----------------------------------------------------------------------------
138 // ----------------------------------------------------------------------------
140 static const wxChar
*wxGLCanvasClassName
= wxT("wxGLCanvasClass");
141 static const wxChar
*wxGLCanvasClassNameNoRedraw
= wxT("wxGLCanvasClassNR");
143 // ============================================================================
145 // ============================================================================
147 // ----------------------------------------------------------------------------
148 // wxGLModule is responsible for unregistering wxGLCanvasClass Windows class
149 // ----------------------------------------------------------------------------
151 class wxGLModule
: public wxModule
154 bool OnInit() { return true; }
155 void OnExit() { UnregisterClasses(); }
157 // register the GL classes if not done yet, return true if ok, false if
158 // registration failed
159 static bool RegisterClasses();
161 // unregister the classes, done automatically on program termination
162 static void UnregisterClasses();
165 // wxGLCanvas is only used from the main thread so this is MT-ok
166 static bool ms_registeredGLClasses
;
168 DECLARE_DYNAMIC_CLASS(wxGLModule
)
171 IMPLEMENT_DYNAMIC_CLASS(wxGLModule
, wxModule
)
173 bool wxGLModule::ms_registeredGLClasses
= false;
176 bool wxGLModule::RegisterClasses()
178 if ( ms_registeredGLClasses
)
181 // We have to register a special window class because we need the CS_OWNDC
182 // style for GLCanvas: some OpenGL drivers are buggy and don't work with
183 // windows without this style
186 // the fields which are common to all classes
187 wndclass
.lpfnWndProc
= (WNDPROC
)wxWndProc
;
188 wndclass
.cbClsExtra
= 0;
189 wndclass
.cbWndExtra
= sizeof( DWORD
); // VZ: what is this DWORD used for?
190 wndclass
.hInstance
= wxhInstance
;
191 wndclass
.hIcon
= (HICON
) NULL
;
192 wndclass
.hCursor
= ::LoadCursor((HINSTANCE
)NULL
, IDC_ARROW
);
193 wndclass
.lpszMenuName
= NULL
;
195 // Register the GLCanvas class name
196 wndclass
.hbrBackground
= (HBRUSH
)NULL
;
197 wndclass
.lpszClassName
= wxGLCanvasClassName
;
198 wndclass
.style
= CS_HREDRAW
| CS_VREDRAW
| CS_DBLCLKS
| CS_OWNDC
;
200 if ( !::RegisterClass(&wndclass
) )
202 wxLogLastError(wxT("RegisterClass(wxGLCanvasClass)"));
206 // Register the GLCanvas class name for windows which don't do full repaint
208 wndclass
.lpszClassName
= wxGLCanvasClassNameNoRedraw
;
209 wndclass
.style
&= ~(CS_HREDRAW
| CS_VREDRAW
);
211 if ( !::RegisterClass(&wndclass
) )
213 wxLogLastError(wxT("RegisterClass(wxGLCanvasClassNameNoRedraw)"));
215 ::UnregisterClass(wxGLCanvasClassName
, wxhInstance
);
220 ms_registeredGLClasses
= true;
226 void wxGLModule::UnregisterClasses()
228 // we need to unregister the classes in case we're in a DLL which is
229 // unloaded and then loaded again because if we don't, the registration is
230 // going to fail in wxGLCanvas::Create() the next time we're loaded
231 if ( ms_registeredGLClasses
)
233 ::UnregisterClass(wxGLCanvasClassName
, wxhInstance
);
234 ::UnregisterClass(wxGLCanvasClassNameNoRedraw
, wxhInstance
);
236 ms_registeredGLClasses
= false;
240 // ----------------------------------------------------------------------------
242 // ----------------------------------------------------------------------------
244 IMPLEMENT_CLASS(wxGLContext
, wxObject
)
246 wxGLContext::wxGLContext(wxGLCanvas
*win
, const wxGLContext
* other
)
248 m_glContext
= wglCreateContext(win
->GetHDC());
249 wxCHECK_RET( m_glContext
, wxT("Couldn't create OpenGL context") );
253 if ( !wglShareLists(other
->m_glContext
, m_glContext
) )
254 wxLogLastError(_T("wglShareLists"));
258 wxGLContext::~wxGLContext()
260 // note that it's ok to delete the context even if it's the current one
261 wglDeleteContext(m_glContext
);
264 bool wxGLContext::SetCurrent(const wxGLCanvas
& win
) const
266 if ( !wglMakeCurrent(win
.GetHDC(), m_glContext
) )
268 wxLogLastError(_T("wglMakeCurrent"));
274 // ============================================================================
276 // ============================================================================
278 IMPLEMENT_CLASS(wxGLCanvas
, wxWindow
)
280 BEGIN_EVENT_TABLE(wxGLCanvas
, wxWindow
)
281 EVT_PALETTE_CHANGED(wxGLCanvas::OnPaletteChanged
)
282 EVT_QUERY_NEW_PALETTE(wxGLCanvas::OnQueryNewPalette
)
285 // ----------------------------------------------------------------------------
286 // wxGLCanvas construction
287 // ----------------------------------------------------------------------------
289 void wxGLCanvas::Init()
291 #if WXWIN_COMPATIBILITY_2_8
297 wxGLCanvas::wxGLCanvas(wxWindow
*parent
,
299 const int *attribList
,
303 const wxString
& name
,
304 const wxPalette
& palette
)
308 (void)Create(parent
, id
, pos
, size
, style
, name
, attribList
, palette
);
311 wxGLCanvas::~wxGLCanvas()
313 ::ReleaseDC(GetHwnd(), m_hDC
);
316 // Replaces wxWindow::Create functionality, since we need to use a different
318 bool wxGLCanvas::Create(wxWindow
*parent
,
323 const wxString
& name
,
324 const int *attribList
,
325 const wxPalette
& palette
)
327 wxCHECK_MSG( parent
, false, wxT("can't create wxWindow without parent") );
329 if ( !wxGLModule::RegisterClasses() )
331 wxLogError(_("Failed to register OpenGL window class."));
336 if ( !CreateBase(parent
, id
, pos
, size
, style
, wxDefaultValidator
, name
) )
339 parent
->AddChild(this);
342 A general rule with OpenGL and Win32 is that any window that will have a
343 HGLRC built for it must have two flags: WS_CLIPCHILDREN & WS_CLIPSIBLINGS.
344 You can find references about this within the knowledge base and most OpenGL
345 books that contain the wgl function descriptions.
348 DWORD msflags
= WS_CHILD
| WS_VISIBLE
| WS_CLIPSIBLINGS
| WS_CLIPCHILDREN
;
349 msflags
|= MSWGetStyle(style
, &exStyle
);
351 if ( !MSWCreate(wxGLCanvasClassName
, NULL
, pos
, size
, msflags
, exStyle
) )
354 m_hDC
= ::GetDC(GetHwnd());
358 if ( !DoSetup(attribList
) )
362 if ( !SetupPalette(palette
) )
364 #else // !wxUSE_PALETTE
365 wxUnusedVar(palette
);
366 #endif // wxUSE_PALETTE/!wxUSE_PALETTE
371 // ----------------------------------------------------------------------------
373 // ----------------------------------------------------------------------------
375 bool wxGLCanvas::SwapBuffers()
377 if ( !::SwapBuffers(m_hDC
) )
379 wxLogLastError(_T("SwapBuffers"));
387 // ----------------------------------------------------------------------------
388 // multi sample support
389 // ----------------------------------------------------------------------------
391 // this macro defines a variable of type "name_t" called "name" and initializes
392 // it with the pointer to WGL function "name" (which may be NULL)
393 #define wxDEFINE_WGL_FUNC(name) \
394 name##_t name = (name##_t)wglGetProcAddress(#name)
397 bool wxGLCanvasBase::IsExtensionSupported(const char *extension
)
399 static const char *s_extensionsList
= (char *)wxUIntPtr(-1);
400 if ( s_extensionsList
== (char *)wxUIntPtr(-1) )
402 typedef const char * (WINAPI
*wglGetExtensionsStringARB_t
)(HDC hdc
);
404 wxDEFINE_WGL_FUNC(wglGetExtensionsStringARB
);
405 if ( wglGetExtensionsStringARB
)
407 s_extensionsList
= wglGetExtensionsStringARB(wglGetCurrentDC());
411 typedef const char * (WINAPI
* wglGetExtensionsStringEXT_t
)();
413 wxDEFINE_WGL_FUNC(wglGetExtensionsStringEXT
);
414 if ( wglGetExtensionsStringEXT
)
416 s_extensionsList
= wglGetExtensionsStringEXT();
420 s_extensionsList
= NULL
;
425 return s_extensionsList
&& IsExtensionInList(s_extensionsList
, extension
);
428 // this is a wrapper around wglChoosePixelFormatARB(): returns the pixel format
429 // index matching the given attributes on success or 0 on failure
430 static int ChoosePixelFormatARB(HDC hdc
, const int *attribList
)
432 if ( !wxGLCanvas::IsExtensionSupported("WGL_ARB_multisample") )
435 typedef BOOL (WINAPI
* wglChoosePixelFormatARB_t
)
437 const int *piAttribIList
,
438 const FLOAT
*pfAttribFList
,
444 wxDEFINE_WGL_FUNC(wglChoosePixelFormatARB
);
445 if ( !wglChoosePixelFormatARB
)
446 return 0; // should not occur if extension is supported
448 int iAttributes
[128];
449 int dst
= 0; // index in iAttributes array
451 #define ADD_ATTR(attr, value) \
452 iAttributes[dst++] = attr; iAttributes[dst++] = value
454 ADD_ATTR( WGL_DRAW_TO_WINDOW_ARB
, GL_TRUE
);
455 ADD_ATTR( WGL_SUPPORT_OPENGL_ARB
, GL_TRUE
);
456 ADD_ATTR( WGL_ACCELERATION_ARB
, WGL_FULL_ACCELERATION_ARB
);
460 ADD_ATTR( WGL_COLOR_BITS_ARB
, 24 );
461 ADD_ATTR( WGL_ALPHA_BITS_ARB
, 8 );
462 ADD_ATTR( WGL_DEPTH_BITS_ARB
, 16 );
463 ADD_ATTR( WGL_STENCIL_BITS_ARB
, 0 );
464 ADD_ATTR( WGL_DOUBLE_BUFFER_ARB
, GL_TRUE
);
465 ADD_ATTR( WGL_SAMPLE_BUFFERS_ARB
, GL_TRUE
);
466 ADD_ATTR( WGL_SAMPLES_ARB
, 4 );
468 else // have custom attributes
470 #define ADD_ATTR_VALUE(attr) ADD_ATTR(attr, attribList[src++])
473 while ( attribList
[src
] )
475 switch ( attribList
[src
++] )
478 ADD_ATTR( WGL_COLOR_BITS_ARB
, 24 );
479 ADD_ATTR( WGL_ALPHA_BITS_ARB
, 8 );
482 case WX_GL_BUFFER_SIZE
:
483 ADD_ATTR_VALUE( WGL_COLOR_BITS_ARB
);
487 if ( attribList
[src
] > 0 )
489 ADD_ATTR( WGL_NUMBER_OVERLAYS_ARB
, 1 );
491 else if ( attribList
[src
] <0 )
493 ADD_ATTR( WGL_NUMBER_UNDERLAYS_ARB
, 1 );
497 src
++; // skip the value in any case
500 case WX_GL_DOUBLEBUFFER
:
501 ADD_ATTR( WGL_DOUBLE_BUFFER_ARB
, GL_TRUE
);
505 ADD_ATTR( WGL_STEREO_ARB
, GL_TRUE
);
508 case WX_GL_AUX_BUFFERS
:
509 ADD_ATTR_VALUE( WGL_AUX_BUFFERS_ARB
);
513 ADD_ATTR_VALUE( WGL_RED_BITS_ARB
);
516 case WX_GL_MIN_GREEN
:
517 ADD_ATTR_VALUE( WGL_GREEN_BITS_ARB
);
521 ADD_ATTR_VALUE( WGL_BLUE_BITS_ARB
);
524 case WX_GL_MIN_ALPHA
:
525 ADD_ATTR_VALUE( WGL_ALPHA_BITS_ARB
);
528 case WX_GL_DEPTH_SIZE
:
529 ADD_ATTR_VALUE( WGL_DEPTH_BITS_ARB
);
532 case WX_GL_STENCIL_SIZE
:
533 ADD_ATTR_VALUE( WGL_STENCIL_BITS_ARB
);
536 case WX_GL_MIN_ACCUM_RED
:
537 ADD_ATTR_VALUE( WGL_ACCUM_RED_BITS_ARB
);
540 case WX_GL_MIN_ACCUM_GREEN
:
541 ADD_ATTR_VALUE( WGL_ACCUM_GREEN_BITS_ARB
);
544 case WX_GL_MIN_ACCUM_BLUE
:
545 ADD_ATTR_VALUE( WGL_ACCUM_BLUE_BITS_ARB
);
548 case WX_GL_MIN_ACCUM_ALPHA
:
549 ADD_ATTR_VALUE( WGL_ACCUM_ALPHA_BITS_ARB
);
552 case WX_GL_SAMPLE_BUFFERS
:
553 ADD_ATTR_VALUE( WGL_SAMPLE_BUFFERS_ARB
);
557 ADD_ATTR_VALUE( WGL_SAMPLES_ARB
);
562 #undef ADD_ATTR_VALUE
567 iAttributes
[dst
++] = 0;
571 if ( !wglChoosePixelFormatARB(hdc
, iAttributes
, NULL
, 1, &pf
, &numFormats
) )
573 wxLogLastError(_T("wglChoosePixelFormatARB"));
580 // ----------------------------------------------------------------------------
581 // pixel format stuff
582 // ----------------------------------------------------------------------------
584 // returns true if pfd was adjusted accordingly to attributes provided, false
585 // if there is an error with attributes or -1 if the attributes indicate
586 // features not supported by ChoosePixelFormat() at all (currently only multi
589 AdjustPFDForAttributes(PIXELFORMATDESCRIPTOR
& pfd
, const int *attribList
)
594 // remove default attributes
595 pfd
.dwFlags
&= ~PFD_DOUBLEBUFFER
;
596 pfd
.iPixelType
= PFD_TYPE_COLORINDEX
;
598 for ( int arg
= 0; attribList
[arg
]; )
600 switch ( attribList
[arg
++] )
603 pfd
.iPixelType
= PFD_TYPE_RGBA
;
606 case WX_GL_BUFFER_SIZE
:
607 pfd
.cColorBits
= attribList
[arg
++];
611 // this member looks like it may be obsolete
612 if ( attribList
[arg
] > 0 )
613 pfd
.iLayerType
= PFD_OVERLAY_PLANE
;
614 else if ( attribList
[arg
] < 0 )
615 pfd
.iLayerType
= (BYTE
)PFD_UNDERLAY_PLANE
;
617 pfd
.iLayerType
= PFD_MAIN_PLANE
;
621 case WX_GL_DOUBLEBUFFER
:
622 pfd
.dwFlags
|= PFD_DOUBLEBUFFER
;
626 pfd
.dwFlags
|= PFD_STEREO
;
629 case WX_GL_AUX_BUFFERS
:
630 pfd
.cAuxBuffers
= attribList
[arg
++];
634 pfd
.cColorBits
+= (pfd
.cRedBits
= attribList
[arg
++]);
637 case WX_GL_MIN_GREEN
:
638 pfd
.cColorBits
+= (pfd
.cGreenBits
= attribList
[arg
++]);
642 pfd
.cColorBits
+= (pfd
.cBlueBits
= attribList
[arg
++]);
645 case WX_GL_MIN_ALPHA
:
646 // doesn't count in cColorBits
647 pfd
.cAlphaBits
= attribList
[arg
++];
650 case WX_GL_DEPTH_SIZE
:
651 pfd
.cDepthBits
= attribList
[arg
++];
654 case WX_GL_STENCIL_SIZE
:
655 pfd
.cStencilBits
= attribList
[arg
++];
658 case WX_GL_MIN_ACCUM_RED
:
659 pfd
.cAccumBits
+= (pfd
.cAccumRedBits
= attribList
[arg
++]);
662 case WX_GL_MIN_ACCUM_GREEN
:
663 pfd
.cAccumBits
+= (pfd
.cAccumGreenBits
= attribList
[arg
++]);
666 case WX_GL_MIN_ACCUM_BLUE
:
667 pfd
.cAccumBits
+= (pfd
.cAccumBlueBits
= attribList
[arg
++]);
670 case WX_GL_MIN_ACCUM_ALPHA
:
671 pfd
.cAccumBits
+= (pfd
.cAccumAlphaBits
= attribList
[arg
++]);
674 case WX_GL_SAMPLE_BUFFERS
:
685 wxGLCanvas::ChooseMatchingPixelFormat(HDC hdc
,
686 const int *attribList
,
687 PIXELFORMATDESCRIPTOR
*ppfd
)
689 // default neutral pixel format
690 PIXELFORMATDESCRIPTOR pfd
=
692 sizeof(PIXELFORMATDESCRIPTOR
), // size
696 PFD_DOUBLEBUFFER
, // use double-buffering by default
697 PFD_TYPE_RGBA
, // default pixel type
698 0, // preferred color depth (don't care)
699 0, 0, 0, 0, 0, 0, // color bits and shift bits (ignored)
700 0, 0, // alpha bits and shift (ignored)
701 0, // accumulation total bits
702 0, 0, 0, 0, // accumulator RGBA bits (not used)
704 0, // no stencil buffer
705 0, // no auxiliary buffers
706 PFD_MAIN_PLANE
, // main layer
708 0, 0, 0, // no layer, visible, damage masks
716 // adjust the PFD using the provided attributes and also check if we can
717 // use PIXELFORMATDESCRIPTOR at all: if multisampling is requested, we
718 // can't as it's not supported by ChoosePixelFormat()
719 switch ( AdjustPFDForAttributes(*ppfd
, attribList
) )
722 return ::ChoosePixelFormat(hdc
, ppfd
);
725 wxFAIL_MSG( "unexpected AdjustPFDForAttributes() return value" );
729 // error in attributes
733 return ::ChoosePixelFormatARB(hdc
, attribList
);
738 bool wxGLCanvasBase::IsDisplaySupported(const int *attribList
)
740 // We need a device context to test the pixel format, so get one
741 // for the root window.
742 return wxGLCanvas::ChooseMatchingPixelFormat(ScreenHDC(), attribList
) > 0;
745 bool wxGLCanvas::DoSetup(const int *attribList
)
747 PIXELFORMATDESCRIPTOR pfd
;
748 const int pixelFormat
= ChooseMatchingPixelFormat(m_hDC
, attribList
, &pfd
);
751 wxLogLastError(_T("ChoosePixelFormat"));
755 if ( !::SetPixelFormat(m_hDC
, pixelFormat
, &pfd
) )
757 wxLogLastError(_T("SetPixelFormat"));
764 // ----------------------------------------------------------------------------
766 // ----------------------------------------------------------------------------
770 bool wxGLCanvas::SetupPalette(const wxPalette
& palette
)
772 const int pixelFormat
= ::GetPixelFormat(m_hDC
);
775 wxLogLastError(_T("GetPixelFormat"));
779 PIXELFORMATDESCRIPTOR pfd
;
780 if ( !::DescribePixelFormat(m_hDC
, pixelFormat
, sizeof(pfd
), &pfd
) )
782 wxLogLastError(_T("DescribePixelFormat"));
786 if ( !(pfd
.dwFlags
& PFD_NEED_PALETTE
) )
791 if ( !m_palette
.Ok() )
793 m_palette
= CreateDefaultPalette();
794 if ( !m_palette
.Ok() )
798 if ( !::SelectPalette(m_hDC
, GetHpaletteOf(m_palette
), FALSE
) )
800 wxLogLastError(_T("SelectPalette"));
804 if ( ::RealizePalette(m_hDC
) == GDI_ERROR
)
806 wxLogLastError(_T("RealizePalette"));
813 wxPalette
wxGLCanvas::CreateDefaultPalette()
815 PIXELFORMATDESCRIPTOR pfd
;
817 int pixelFormat
= GetPixelFormat(m_hDC
);
819 DescribePixelFormat(m_hDC
, pixelFormat
, sizeof(PIXELFORMATDESCRIPTOR
), &pfd
);
821 paletteSize
= 1 << pfd
.cColorBits
;
824 (LOGPALETTE
*) malloc(sizeof(LOGPALETTE
) + paletteSize
* sizeof(PALETTEENTRY
));
825 pPal
->palVersion
= 0x300;
826 pPal
->palNumEntries
= (WORD
)paletteSize
;
828 /* build a simple RGB color palette */
829 int redMask
= (1 << pfd
.cRedBits
) - 1;
830 int greenMask
= (1 << pfd
.cGreenBits
) - 1;
831 int blueMask
= (1 << pfd
.cBlueBits
) - 1;
833 for (int i
=0; i
<paletteSize
; ++i
)
835 pPal
->palPalEntry
[i
].peRed
=
836 (BYTE
)((((i
>> pfd
.cRedShift
) & redMask
) * 255) / redMask
);
837 pPal
->palPalEntry
[i
].peGreen
=
838 (BYTE
)((((i
>> pfd
.cGreenShift
) & greenMask
) * 255) / greenMask
);
839 pPal
->palPalEntry
[i
].peBlue
=
840 (BYTE
)((((i
>> pfd
.cBlueShift
) & blueMask
) * 255) / blueMask
);
841 pPal
->palPalEntry
[i
].peFlags
= 0;
844 HPALETTE hPalette
= CreatePalette(pPal
);
848 palette
.SetHPALETTE((WXHPALETTE
) hPalette
);
853 void wxGLCanvas::OnQueryNewPalette(wxQueryNewPaletteEvent
& event
)
855 /* realize palette if this is the current window */
856 if ( GetPalette()->Ok() ) {
857 ::UnrealizeObject((HPALETTE
) GetPalette()->GetHPALETTE());
858 ::SelectPalette(GetHDC(), (HPALETTE
) GetPalette()->GetHPALETTE(), FALSE
);
859 ::RealizePalette(GetHDC());
861 event
.SetPaletteRealized(true);
864 event
.SetPaletteRealized(false);
867 void wxGLCanvas::OnPaletteChanged(wxPaletteChangedEvent
& event
)
869 /* realize palette if this is *not* the current window */
871 GetPalette()->Ok() && (this != event
.GetChangedWindow()) )
873 ::UnrealizeObject((HPALETTE
) GetPalette()->GetHPALETTE());
874 ::SelectPalette(GetHDC(), (HPALETTE
) GetPalette()->GetHPALETTE(), FALSE
);
875 ::RealizePalette(GetHDC());
880 #endif // wxUSE_PALETTE
882 // ----------------------------------------------------------------------------
883 // deprecated wxGLCanvas methods using implicit wxGLContext
884 // ----------------------------------------------------------------------------
886 // deprecated constructors creating an implicit m_glContext
887 #if WXWIN_COMPATIBILITY_2_8
889 wxGLCanvas::wxGLCanvas(wxWindow
*parent
,
894 const wxString
& name
,
895 const int *attribList
,
896 const wxPalette
& palette
)
900 if ( Create(parent
, id
, pos
, size
, style
, name
, attribList
, palette
) )
901 m_glContext
= new wxGLContext(this);
904 wxGLCanvas::wxGLCanvas(wxWindow
*parent
,
905 const wxGLContext
*shared
,
910 const wxString
& name
,
911 const int *attribList
,
912 const wxPalette
& palette
)
916 if ( Create(parent
, id
, pos
, size
, style
, name
, attribList
, palette
) )
917 m_glContext
= new wxGLContext(this, shared
);
920 wxGLCanvas::wxGLCanvas(wxWindow
*parent
,
921 const wxGLCanvas
*shared
,
926 const wxString
& name
,
927 const int *attribList
,
928 const wxPalette
& palette
)
932 if ( Create(parent
, id
, pos
, size
, style
, name
, attribList
, palette
) )
933 m_glContext
= new wxGLContext(this, shared
? shared
->m_glContext
: NULL
);
936 #endif // WXWIN_COMPATIBILITY_2_8
939 // ----------------------------------------------------------------------------
941 // ----------------------------------------------------------------------------
943 bool wxGLApp::InitGLVisual(const int *attribList
)
945 if ( !wxGLCanvas::ChooseMatchingPixelFormat(ScreenHDC(), attribList
) )
947 wxLogError(_("Failed to initialize OpenGL"));
954 #endif // wxUSE_GLCANVAS