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 #if defined(__GNUG__) && !defined(NO_GCC_PRAGMA)
13 #pragma implementation "glcanvas.h"
16 #include "wx/wxprec.h"
18 #if defined(__BORLANDC__)
26 #include "wx/settings.h"
32 #include "wx/msw/private.h"
34 // DLL options compatibility check:
36 WX_CHECK_BUILD_OPTIONS("wxGL")
38 #include "wx/glcanvas.h"
41 The following two compiler directives are specific to the Microsoft Visual
42 C++ family of compilers
44 Fundementally what they do is instruct the linker to use these two libraries
45 for the resolution of symbols. In essence, this is the equivalent of adding
46 these two libraries to either the Makefile or project file.
48 This is NOT a recommended technique, and certainly is unlikely to be used
49 anywhere else in wxWidgets given it is so specific to not only wxMSW, but
50 also the VC compiler. However, in the case of opengl support, it's an
51 applicable technique as opengl is optional in setup.h This code (wrapped by
52 wxUSE_GLCANVAS), now allows opengl support to be added purely by modifying
53 setup.h rather than by having to modify either the project or DSP fle.
55 See MSDN for further information on the exact usage of these commands.
58 # pragma comment( lib, "opengl32" )
59 # pragma comment( lib, "glu32" )
63 static const wxChar
*wxGLCanvasClassName
= wxT("wxGLCanvasClass");
64 static const wxChar
*wxGLCanvasClassNameNoRedraw
= wxT("wxGLCanvasClassNR");
66 LRESULT WXDLLEXPORT APIENTRY _EXPORT
wxWndProc(HWND hWnd
, UINT message
,
67 WPARAM wParam
, LPARAM lParam
);
70 * GLContext implementation
73 wxGLContext::wxGLContext(bool WXUNUSED(isRGB
), wxGLCanvas
*win
, const wxPalette
& WXUNUSED(palette
))
77 m_hDC
= win
->GetHDC();
79 m_glContext
= wglCreateContext((HDC
) m_hDC
);
80 wxCHECK_RET( m_glContext
, wxT("Couldn't create OpenGl context") );
82 wglMakeCurrent((HDC
) m_hDC
, m_glContext
);
85 wxGLContext::wxGLContext(
86 bool WXUNUSED(isRGB
), wxGLCanvas
*win
,
87 const wxPalette
& WXUNUSED(palette
),
88 const wxGLContext
*other
/* for sharing display lists */
93 m_hDC
= win
->GetHDC();
95 m_glContext
= wglCreateContext((HDC
) m_hDC
);
96 wxCHECK_RET( m_glContext
, wxT("Couldn't create OpenGl context") );
99 wglShareLists( other
->m_glContext
, m_glContext
);
101 wglMakeCurrent((HDC
) m_hDC
, m_glContext
);
104 wxGLContext::~wxGLContext()
108 wglMakeCurrent(NULL
, NULL
);
109 wglDeleteContext(m_glContext
);
113 void wxGLContext::SwapBuffers()
117 wglMakeCurrent((HDC
) m_hDC
, m_glContext
);
118 ::SwapBuffers((HDC
) m_hDC
); //blits the backbuffer into DC
122 void wxGLContext::SetCurrent()
126 wglMakeCurrent((HDC
) m_hDC
, m_glContext
);
130 setupPixelFormat(hDC);
135 void wxGLContext::SetColour(const wxChar
*colour
)
137 wxColour col
= wxTheColourDatabase
->Find(colour
);
140 float r
= (float)(col
.Red()/256.0);
141 float g
= (float)(col
.Green()/256.0);
142 float b
= (float)(col
.Blue()/256.0);
149 * wxGLCanvas implementation
152 IMPLEMENT_CLASS(wxGLCanvas
, wxWindow
)
154 BEGIN_EVENT_TABLE(wxGLCanvas
, wxWindow
)
155 EVT_SIZE(wxGLCanvas::OnSize
)
156 EVT_PALETTE_CHANGED(wxGLCanvas::OnPaletteChanged
)
157 EVT_QUERY_NEW_PALETTE(wxGLCanvas::OnQueryNewPalette
)
160 wxGLCanvas::wxGLCanvas(wxWindow
*parent
, wxWindowID id
,
161 const wxPoint
& pos
, const wxSize
& size
, long style
, const wxString
& name
,
162 int *attribList
, const wxPalette
& palette
) : wxWindow()
164 m_glContext
= (wxGLContext
*) NULL
;
166 bool ret
= Create(parent
, id
, pos
, size
, style
, name
);
170 SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_3DFACE
));
171 SetFont(wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT
));
174 m_hDC
= (WXHDC
) ::GetDC((HWND
) GetHWND());
176 SetupPixelFormat(attribList
);
177 SetupPalette(palette
);
179 m_glContext
= new wxGLContext(TRUE
, this, palette
);
182 wxGLCanvas::wxGLCanvas( wxWindow
*parent
,
183 const wxGLContext
*shared
, wxWindowID id
,
184 const wxPoint
& pos
, const wxSize
& size
, long style
, const wxString
& name
,
185 int *attribList
, const wxPalette
& palette
)
188 m_glContext
= (wxGLContext
*) NULL
;
190 bool ret
= Create(parent
, id
, pos
, size
, style
, name
);
194 SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_3DFACE
));
195 SetFont(wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT
));
198 m_hDC
= (WXHDC
) ::GetDC((HWND
) GetHWND());
200 SetupPixelFormat(attribList
);
201 SetupPalette(palette
);
203 m_glContext
= new wxGLContext(TRUE
, this, palette
, shared
);
206 // Not very useful for wxMSW, but this is to be wxGTK compliant
208 wxGLCanvas::wxGLCanvas( wxWindow
*parent
, const wxGLCanvas
*shared
, wxWindowID id
,
209 const wxPoint
& pos
, const wxSize
& size
, long style
, const wxString
& name
,
210 int *attribList
, const wxPalette
& palette
):
213 m_glContext
= (wxGLContext
*) NULL
;
215 bool ret
= Create(parent
, id
, pos
, size
, style
, name
);
219 SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_3DFACE
));
220 SetFont(wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT
));
223 m_hDC
= (WXHDC
) ::GetDC((HWND
) GetHWND());
225 SetupPixelFormat(attribList
);
226 SetupPalette(palette
);
228 wxGLContext
*sharedContext
=0;
229 if (shared
) sharedContext
=shared
->GetContext();
230 m_glContext
= new wxGLContext(TRUE
, this, palette
, sharedContext
);
233 wxGLCanvas::~wxGLCanvas()
238 ::ReleaseDC((HWND
) GetHWND(), (HDC
) m_hDC
);
241 // Replaces wxWindow::Create functionality, since we need to use a different
243 bool wxGLCanvas::Create(wxWindow
*parent
,
248 const wxString
& name
)
250 static bool s_registeredGLCanvasClass
= FALSE
;
252 // We have to register a special window class because we need
253 // the CS_OWNDC style for GLCanvas.
256 From Angel Popov <jumpo@bitex.com>
258 Here are two snips from a dicussion in the OpenGL Gamedev list that explains
259 how this problem can be fixed:
261 "There are 5 common DCs available in Win95. These are aquired when you call
262 GetDC or GetDCEx from a window that does _not_ have the OWNDC flag.
263 OWNDC flagged windows do not get their DC from the common DC pool, the issue
264 is they require 800 bytes each from the limited 64Kb local heap for GDI."
266 "The deal is, if you hold onto one of the 5 shared DC's too long (as GL apps
267 do), Win95 will actually "steal" it from you. MakeCurrent fails,
268 apparently, because Windows re-assigns the HDC to a different window. The
269 only way to prevent this, the only reliable means, is to set CS_OWNDC."
272 if (!s_registeredGLCanvasClass
)
276 // the fields which are common to all classes
277 wndclass
.lpfnWndProc
= (WNDPROC
)wxWndProc
;
278 wndclass
.cbClsExtra
= 0;
279 wndclass
.cbWndExtra
= sizeof( DWORD
); // VZ: what is this DWORD used for?
280 wndclass
.hInstance
= wxhInstance
;
281 wndclass
.hIcon
= (HICON
) NULL
;
282 wndclass
.hCursor
= ::LoadCursor((HINSTANCE
)NULL
, IDC_ARROW
);
283 wndclass
.lpszMenuName
= NULL
;
285 // Register the GLCanvas class name
286 wndclass
.hbrBackground
= (HBRUSH
)NULL
;
287 wndclass
.lpszClassName
= wxGLCanvasClassName
;
288 wndclass
.style
= CS_HREDRAW
| CS_VREDRAW
| CS_DBLCLKS
| CS_OWNDC
;
290 if ( !::RegisterClass(&wndclass
) )
292 wxLogLastError(wxT("RegisterClass(wxGLCanvasClass)"));
296 // Register the GLCanvas class name for windows which don't do full repaint
298 wndclass
.lpszClassName
= wxGLCanvasClassNameNoRedraw
;
299 wndclass
.style
&= ~(CS_HREDRAW
| CS_VREDRAW
);
301 if ( !::RegisterClass(&wndclass
) )
303 wxLogLastError(wxT("RegisterClass(wxGLCanvasClassNameNoRedraw)"));
305 ::UnregisterClass(wxGLCanvasClassName
, wxhInstance
);
310 s_registeredGLCanvasClass
= TRUE
;
313 wxCHECK_MSG( parent
, FALSE
, wxT("can't create wxWindow without parent") );
315 if ( !CreateBase(parent
, id
, pos
, size
, style
, wxDefaultValidator
, name
) )
318 parent
->AddChild(this);
323 A general rule with OpenGL and Win32 is that any window that will have a
324 HGLRC built for it must have two flags: WS_CLIPCHILDREN & WS_CLIPSIBLINGS.
325 You can find references about this within the knowledge base and most OpenGL
326 books that contain the wgl function descriptions.
330 msflags
|= WS_CHILD
| WS_VISIBLE
| WS_CLIPSIBLINGS
| WS_CLIPCHILDREN
;
331 msflags
|= MSWGetStyle(style
, & exStyle
) ;
333 return MSWCreate(wxGLCanvasClassName
, NULL
, pos
, size
, msflags
, exStyle
);
336 static void AdjustPFDForAttributes(PIXELFORMATDESCRIPTOR
& pfd
, int *attribList
)
339 pfd
.dwFlags
&= ~PFD_DOUBLEBUFFER
;
340 pfd
.iPixelType
= PFD_TYPE_COLORINDEX
;
344 while( (attribList
[arg
]!=0) )
346 switch( attribList
[arg
++] )
349 pfd
.iPixelType
= PFD_TYPE_RGBA
;
351 case WX_GL_BUFFER_SIZE
:
352 pfd
.cColorBits
= attribList
[arg
++];
355 // this member looks like it may be obsolete
356 if (attribList
[arg
] > 0) {
357 pfd
.iLayerType
= (BYTE
)PFD_OVERLAY_PLANE
;
358 } else if (attribList
[arg
] < 0) {
359 pfd
.iLayerType
= (BYTE
)PFD_UNDERLAY_PLANE
;
361 pfd
.iLayerType
= (BYTE
)PFD_MAIN_PLANE
;
365 case WX_GL_DOUBLEBUFFER
:
366 pfd
.dwFlags
|= PFD_DOUBLEBUFFER
;
369 pfd
.dwFlags
|= PFD_STEREO
;
371 case WX_GL_AUX_BUFFERS
:
372 pfd
.cAuxBuffers
= attribList
[arg
++];
375 pfd
.cColorBits
+= (pfd
.cRedBits
= attribList
[arg
++]);
377 case WX_GL_MIN_GREEN
:
378 pfd
.cColorBits
+= (pfd
.cGreenBits
= attribList
[arg
++]);
381 pfd
.cColorBits
+= (pfd
.cBlueBits
= attribList
[arg
++]);
383 case WX_GL_MIN_ALPHA
:
384 // doesn't count in cColorBits
385 pfd
.cAlphaBits
= attribList
[arg
++];
387 case WX_GL_DEPTH_SIZE
:
388 pfd
.cDepthBits
= attribList
[arg
++];
390 case WX_GL_STENCIL_SIZE
:
391 pfd
.cStencilBits
= attribList
[arg
++];
393 case WX_GL_MIN_ACCUM_RED
:
394 pfd
.cAccumBits
+= (pfd
.cAccumRedBits
= attribList
[arg
++]);
396 case WX_GL_MIN_ACCUM_GREEN
:
397 pfd
.cAccumBits
+= (pfd
.cAccumGreenBits
= attribList
[arg
++]);
399 case WX_GL_MIN_ACCUM_BLUE
:
400 pfd
.cAccumBits
+= (pfd
.cAccumBlueBits
= attribList
[arg
++]);
402 case WX_GL_MIN_ACCUM_ALPHA
:
403 pfd
.cAccumBits
+= (pfd
.cAccumAlphaBits
= attribList
[arg
++]);
412 void wxGLCanvas::SetupPixelFormat(int *attribList
) // (HDC hDC)
414 PIXELFORMATDESCRIPTOR pfd
= {
415 sizeof(PIXELFORMATDESCRIPTOR
), /* size */
419 PFD_DOUBLEBUFFER
, /* support double-buffering */
420 PFD_TYPE_RGBA
, /* color type */
421 16, /* prefered color depth */
422 0, 0, 0, 0, 0, 0, /* color bits (ignored) */
423 0, /* no alpha buffer */
424 0, /* alpha bits (ignored) */
425 0, /* no accumulation buffer */
426 0, 0, 0, 0, /* accum bits (ignored) */
427 16, /* depth buffer */
428 0, /* no stencil buffer */
429 0, /* no auxiliary buffers */
430 PFD_MAIN_PLANE
, /* main layer */
432 0, 0, 0, /* no layer, visible, damage masks */
435 AdjustPFDForAttributes(pfd
, attribList
);
437 int pixelFormat
= ChoosePixelFormat((HDC
) m_hDC
, &pfd
);
438 if (pixelFormat
== 0) {
439 wxLogLastError(_T("ChoosePixelFormat"));
442 if ( !::SetPixelFormat((HDC
) m_hDC
, pixelFormat
, &pfd
) ) {
443 wxLogLastError(_T("SetPixelFormat"));
448 void wxGLCanvas::SetupPalette(const wxPalette
& palette
)
450 int pixelFormat
= GetPixelFormat((HDC
) m_hDC
);
451 PIXELFORMATDESCRIPTOR pfd
;
453 DescribePixelFormat((HDC
) m_hDC
, pixelFormat
, sizeof(PIXELFORMATDESCRIPTOR
), &pfd
);
455 if (pfd
.dwFlags
& PFD_NEED_PALETTE
)
465 if ( !m_palette
.Ok() )
467 m_palette
= CreateDefaultPalette();
472 SelectPalette((HDC
) m_hDC
, (HPALETTE
) m_palette
.GetHPALETTE(), FALSE
);
473 RealizePalette((HDC
) m_hDC
);
477 wxPalette
wxGLCanvas::CreateDefaultPalette()
479 PIXELFORMATDESCRIPTOR pfd
;
481 int pixelFormat
= GetPixelFormat((HDC
) m_hDC
);
483 DescribePixelFormat((HDC
) m_hDC
, pixelFormat
, sizeof(PIXELFORMATDESCRIPTOR
), &pfd
);
485 paletteSize
= 1 << pfd
.cColorBits
;
488 (LOGPALETTE
*) malloc(sizeof(LOGPALETTE
) + paletteSize
* sizeof(PALETTEENTRY
));
489 pPal
->palVersion
= 0x300;
490 pPal
->palNumEntries
= paletteSize
;
492 /* build a simple RGB color palette */
494 int redMask
= (1 << pfd
.cRedBits
) - 1;
495 int greenMask
= (1 << pfd
.cGreenBits
) - 1;
496 int blueMask
= (1 << pfd
.cBlueBits
) - 1;
499 for (i
=0; i
<paletteSize
; ++i
) {
500 pPal
->palPalEntry
[i
].peRed
=
501 (((i
>> pfd
.cRedShift
) & redMask
) * 255) / redMask
;
502 pPal
->palPalEntry
[i
].peGreen
=
503 (((i
>> pfd
.cGreenShift
) & greenMask
) * 255) / greenMask
;
504 pPal
->palPalEntry
[i
].peBlue
=
505 (((i
>> pfd
.cBlueShift
) & blueMask
) * 255) / blueMask
;
506 pPal
->palPalEntry
[i
].peFlags
= 0;
510 HPALETTE hPalette
= CreatePalette(pPal
);
514 palette
.SetHPALETTE((WXHPALETTE
) hPalette
);
519 void wxGLCanvas::SwapBuffers()
522 m_glContext
->SwapBuffers();
525 void wxGLCanvas::OnSize(wxSizeEvent
& WXUNUSED(event
))
529 void wxGLCanvas::SetCurrent()
533 m_glContext
->SetCurrent();
537 void wxGLCanvas::SetColour(const wxChar
*colour
)
540 m_glContext
->SetColour(colour
);
543 // TODO: Have to have this called by parent frame (?)
544 // So we need wxFrame to call OnQueryNewPalette for all children...
545 void wxGLCanvas::OnQueryNewPalette(wxQueryNewPaletteEvent
& event
)
547 /* realize palette if this is the current window */
548 if ( GetPalette()->Ok() ) {
549 ::UnrealizeObject((HPALETTE
) GetPalette()->GetHPALETTE());
550 ::SelectPalette((HDC
) GetHDC(), (HPALETTE
) GetPalette()->GetHPALETTE(), FALSE
);
551 ::RealizePalette((HDC
) GetHDC());
553 event
.SetPaletteRealized(TRUE
);
556 event
.SetPaletteRealized(FALSE
);
559 // I think this doesn't have to be propagated to child windows.
560 void wxGLCanvas::OnPaletteChanged(wxPaletteChangedEvent
& event
)
562 /* realize palette if this is *not* the current window */
564 GetPalette()->Ok() && (this != event
.GetChangedWindow()) )
566 ::UnrealizeObject((HPALETTE
) GetPalette()->GetHPALETTE());
567 ::SelectPalette((HDC
) GetHDC(), (HPALETTE
) GetPalette()->GetHPALETTE(), FALSE
);
568 ::RealizePalette((HDC
) GetHDC());
573 /* Give extensions proper function names. */
575 /* EXT_vertex_array */
576 void glArrayElementEXT(GLint
WXUNUSED(i
))
580 void glColorPointerEXT(GLint
WXUNUSED(size
), GLenum
WXUNUSED(type
), GLsizei
WXUNUSED(stride
), GLsizei
WXUNUSED(count
), const GLvoid
*WXUNUSED(pointer
))
584 void glDrawArraysEXT(GLenum mode
, GLint first
, GLsizei count
)
586 #ifdef GL_EXT_vertex_array
587 static PFNGLDRAWARRAYSEXTPROC proc
= 0;
591 proc
= (PFNGLDRAWARRAYSEXTPROC
) wglGetProcAddress("glDrawArraysEXT");
595 (* proc
) (mode
, first
, count
);
599 void glEdgeFlagPointerEXT(GLsizei
WXUNUSED(stride
), GLsizei
WXUNUSED(count
), const GLboolean
*WXUNUSED(pointer
))
603 void glGetPointervEXT(GLenum
WXUNUSED(pname
), GLvoid
* *WXUNUSED(params
))
607 void glIndexPointerEXT(GLenum
WXUNUSED(type
), GLsizei
WXUNUSED(stride
), GLsizei
WXUNUSED(count
), const GLvoid
*WXUNUSED(pointer
))
611 void glNormalPointerEXT(GLenum type
, GLsizei stride
, GLsizei count
, const GLvoid
*pointer
)
613 #ifdef GL_EXT_vertex_array
614 static PFNGLNORMALPOINTEREXTPROC proc
= 0;
618 proc
= (PFNGLNORMALPOINTEREXTPROC
) wglGetProcAddress("glNormalPointerEXT");
622 (* proc
) (type
, stride
, count
, pointer
);
626 void glTexCoordPointerEXT(GLint
WXUNUSED(size
), GLenum
WXUNUSED(type
), GLsizei
WXUNUSED(stride
), GLsizei
WXUNUSED(count
), const GLvoid
*WXUNUSED(pointer
))
630 void glVertexPointerEXT(GLint size
, GLenum type
, GLsizei stride
, GLsizei count
, const GLvoid
*pointer
)
632 #ifdef GL_EXT_vertex_array
633 static PFNGLVERTEXPOINTEREXTPROC proc
= 0;
637 proc
= (PFNGLVERTEXPOINTEREXTPROC
) wglGetProcAddress("glVertexPointerEXT");
640 (* proc
) (size
, type
, stride
, count
, pointer
);
644 /* EXT_color_subtable */
645 void glColorSubtableEXT(GLenum
WXUNUSED(target
), GLsizei
WXUNUSED(start
), GLsizei
WXUNUSED(count
), GLenum
WXUNUSED(format
), GLenum
WXUNUSED(type
), const GLvoid
*WXUNUSED(table
))
649 /* EXT_color_table */
650 void glColorTableEXT(GLenum
WXUNUSED(target
), GLenum
WXUNUSED(internalformat
), GLsizei
WXUNUSED(width
), GLenum
WXUNUSED(format
), GLenum
WXUNUSED(type
), const GLvoid
*WXUNUSED(table
))
654 void glCopyColorTableEXT(GLenum
WXUNUSED(target
), GLenum
WXUNUSED(internalformat
), GLint
WXUNUSED(x
), GLint
WXUNUSED(y
), GLsizei
WXUNUSED(width
))
658 void glGetColorTableEXT(GLenum
WXUNUSED(target
), GLenum
WXUNUSED(format
), GLenum
WXUNUSED(type
), GLvoid
*WXUNUSED(table
))
662 void glGetColorTableParamaterfvEXT(GLenum
WXUNUSED(target
), GLenum
WXUNUSED(pname
), GLfloat
*WXUNUSED(params
))
666 void glGetColorTavleParameterivEXT(GLenum
WXUNUSED(target
), GLenum
WXUNUSED(pname
), GLint
*WXUNUSED(params
))
670 /* SGI_compiled_vertex_array */
671 void glLockArraysSGI(GLint
WXUNUSED(first
), GLsizei
WXUNUSED(count
))
675 void glUnlockArraysSGI()
680 /* SGI_cull_vertex */
681 void glCullParameterdvSGI(GLenum
WXUNUSED(pname
), GLdouble
* WXUNUSED(params
))
685 void glCullParameterfvSGI(GLenum
WXUNUSED(pname
), GLfloat
* WXUNUSED(params
))
690 void glIndexFuncSGI(GLenum
WXUNUSED(func
), GLclampf
WXUNUSED(ref
))
694 /* SGI_index_material */
695 void glIndexMaterialSGI(GLenum
WXUNUSED(face
), GLenum
WXUNUSED(mode
))
700 void glAddSwapHintRectWin(GLint
WXUNUSED(x
), GLint
WXUNUSED(y
), GLsizei
WXUNUSED(width
), GLsizei
WXUNUSED(height
))
705 //---------------------------------------------------------------------------
707 //---------------------------------------------------------------------------
709 IMPLEMENT_CLASS(wxGLApp
, wxApp
)
711 bool wxGLApp::InitGLVisual(int *attribList
)
714 PIXELFORMATDESCRIPTOR pfd
= {
715 sizeof(PIXELFORMATDESCRIPTOR
), /* size */
719 PFD_DOUBLEBUFFER
, /* support double-buffering */
720 PFD_TYPE_RGBA
, /* color type */
721 16, /* prefered color depth */
722 0, 0, 0, 0, 0, 0, /* color bits (ignored) */
723 0, /* no alpha buffer */
724 0, /* alpha bits (ignored) */
725 0, /* no accumulation buffer */
726 0, 0, 0, 0, /* accum bits (ignored) */
727 16, /* depth buffer */
728 0, /* no stencil buffer */
729 0, /* no auxiliary buffers */
730 PFD_MAIN_PLANE
, /* main layer */
732 0, 0, 0, /* no layer, visible, damage masks */
735 AdjustPFDForAttributes(pfd
, attribList
);
737 // use DC for whole (root) screen, since no windows have yet been created
738 pixelFormat
= ChoosePixelFormat(ScreenHDC(), &pfd
);
740 if (pixelFormat
== 0) {
741 wxLogError(_("Failed to initialize OpenGL"));