]> git.saurik.com Git - wxWidgets.git/blob - src/msw/glcanvas.cpp
Pass focus window to submenu items too (no reason I can think of not to).
[wxWidgets.git] / src / msw / glcanvas.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/msw/glcanvas.cpp
3 // Purpose: wxGLCanvas, for using OpenGL with wxWindows under MS Windows
4 // Author: Julian Smart
5 // Modified by:
6 // Created: 04/01/98
7 // RCS-ID: $Id$
8 // Copyright: (c) Julian Smart
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
11
12 #ifdef __GNUG__
13 #pragma implementation "glcanvas.h"
14 #endif
15
16 #include "wx/wxprec.h"
17
18 #if defined(__BORLANDC__)
19 #pragma hdrstop
20 #endif
21
22 #if wxUSE_GLCANVAS
23
24 #ifndef WX_PRECOMP
25 #include "wx/frame.h"
26 #include "wx/settings.h"
27 #include "wx/intl.h"
28 #include "wx/log.h"
29 #endif
30
31 #include "wx/msw/private.h"
32
33 #include "wx/glcanvas.h"
34
35 static const wxChar *wxGLCanvasClassName = wxT("wxGLCanvasClass");
36 static const wxChar *wxGLCanvasClassNameNoRedraw = wxT("wxGLCanvasClassNR");
37
38 LRESULT WXDLLEXPORT APIENTRY _EXPORT wxWndProc(HWND hWnd, UINT message,
39 WPARAM wParam, LPARAM lParam);
40
41 /*
42 * GLContext implementation
43 */
44
45 wxGLContext::wxGLContext(bool isRGB, wxGLCanvas *win, const wxPalette& palette)
46 {
47 m_window = win;
48
49 m_hDC = win->GetHDC();
50
51 m_glContext = wglCreateContext((HDC) m_hDC);
52 wxCHECK_RET( m_glContext, wxT("Couldn't create OpenGl context") );
53
54 wglMakeCurrent((HDC) m_hDC, m_glContext);
55 }
56
57 wxGLContext::wxGLContext(
58 bool isRGB, wxGLCanvas *win,
59 const wxPalette& palette,
60 const wxGLContext *other /* for sharing display lists */
61 )
62 {
63 m_window = win;
64
65 m_hDC = win->GetHDC();
66
67 m_glContext = wglCreateContext((HDC) m_hDC);
68 wxCHECK_RET( m_glContext, wxT("Couldn't create OpenGl context") );
69
70 if( other != 0 )
71 wglShareLists( other->m_glContext, m_glContext );
72
73 wglMakeCurrent((HDC) m_hDC, m_glContext);
74 }
75
76 wxGLContext::~wxGLContext()
77 {
78 if (m_glContext)
79 {
80 wglMakeCurrent(NULL, NULL);
81 wglDeleteContext(m_glContext);
82 }
83 }
84
85 void wxGLContext::SwapBuffers()
86 {
87 if (m_glContext)
88 {
89 wglMakeCurrent((HDC) m_hDC, m_glContext);
90 ::SwapBuffers((HDC) m_hDC); //blits the backbuffer into DC
91 }
92 }
93
94 void wxGLContext::SetCurrent()
95 {
96 if (m_glContext)
97 {
98 wglMakeCurrent((HDC) m_hDC, m_glContext);
99 }
100
101 /*
102 setupPixelFormat(hDC);
103 setupPalette(hDC);
104 */
105 }
106
107 void wxGLContext::SetColour(const wxChar *colour)
108 {
109 float r = 0.0;
110 float g = 0.0;
111 float b = 0.0;
112 wxColour *col = wxTheColourDatabase->FindColour(colour);
113 if (col)
114 {
115 r = (float)(col->Red()/256.0);
116 g = (float)(col->Green()/256.0);
117 b = (float)(col->Blue()/256.0);
118 glColor3f( r, g, b);
119 }
120 }
121
122
123 /*
124 * wxGLCanvas implementation
125 */
126
127 IMPLEMENT_CLASS(wxGLCanvas, wxWindow)
128
129 BEGIN_EVENT_TABLE(wxGLCanvas, wxWindow)
130 EVT_SIZE(wxGLCanvas::OnSize)
131 EVT_PALETTE_CHANGED(wxGLCanvas::OnPaletteChanged)
132 EVT_QUERY_NEW_PALETTE(wxGLCanvas::OnQueryNewPalette)
133 END_EVENT_TABLE()
134
135 wxGLCanvas::wxGLCanvas(wxWindow *parent, wxWindowID id,
136 const wxPoint& pos, const wxSize& size, long style, const wxString& name,
137 int *attribList, const wxPalette& palette) : wxWindow()
138 {
139 m_glContext = (wxGLContext*) NULL;
140
141 bool ret = Create(parent, id, pos, size, style, name);
142
143 if ( ret )
144 {
145 SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_3DFACE));
146 SetFont(wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT));
147 }
148
149 m_hDC = (WXHDC) ::GetDC((HWND) GetHWND());
150
151 SetupPixelFormat(attribList);
152 SetupPalette(palette);
153
154 m_glContext = new wxGLContext(TRUE, this, palette);
155 }
156
157 wxGLCanvas::wxGLCanvas( wxWindow *parent,
158 const wxGLContext *shared, wxWindowID id,
159 const wxPoint& pos, const wxSize& size, long style, const wxString& name,
160 int *attribList, const wxPalette& palette )
161 : wxWindow()
162 {
163 m_glContext = (wxGLContext*) NULL;
164
165 bool ret = Create(parent, id, pos, size, style, name);
166
167 if ( ret )
168 {
169 SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_3DFACE));
170 SetFont(wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT));
171 }
172
173 m_hDC = (WXHDC) ::GetDC((HWND) GetHWND());
174
175 SetupPixelFormat(attribList);
176 SetupPalette(palette);
177
178 m_glContext = new wxGLContext(TRUE, this, palette, shared );
179 }
180
181 // Not very useful for wxMSW, but this is to be wxGTK compliant
182
183 wxGLCanvas::wxGLCanvas( wxWindow *parent, const wxGLCanvas *shared, wxWindowID id,
184 const wxPoint& pos, const wxSize& size, long style, const wxString& name,
185 int *attribList, const wxPalette& palette ):
186 wxWindow()
187 {
188 m_glContext = (wxGLContext*) NULL;
189
190 bool ret = Create(parent, id, pos, size, style, name);
191
192 if ( ret )
193 {
194 SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_3DFACE));
195 SetFont(wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT));
196 }
197
198 m_hDC = (WXHDC) ::GetDC((HWND) GetHWND());
199
200 SetupPixelFormat(attribList);
201 SetupPalette(palette);
202
203 wxGLContext *sharedContext=0;
204 if (shared) sharedContext=shared->GetContext();
205 m_glContext = new wxGLContext(TRUE, this, palette, sharedContext );
206 }
207
208 wxGLCanvas::~wxGLCanvas()
209 {
210 if (m_glContext)
211 delete m_glContext;
212
213 ::ReleaseDC((HWND) GetHWND(), (HDC) m_hDC);
214 }
215
216 // Replaces wxWindow::Create functionality, since we need to use a different
217 // window class
218 bool wxGLCanvas::Create(wxWindow *parent,
219 wxWindowID id,
220 const wxPoint& pos,
221 const wxSize& size,
222 long style,
223 const wxString& name)
224 {
225 static bool s_registeredGLCanvasClass = FALSE;
226
227 // We have to register a special window class because we need
228 // the CS_OWNDC style for GLCanvas.
229
230 /*
231 From Angel Popov <jumpo@bitex.com>
232
233 Here are two snips from a dicussion in the OpenGL Gamedev list that explains
234 how this problem can be fixed:
235
236 "There are 5 common DCs available in Win95. These are aquired when you call
237 GetDC or GetDCEx from a window that does _not_ have the OWNDC flag.
238 OWNDC flagged windows do not get their DC from the common DC pool, the issue
239 is they require 800 bytes each from the limited 64Kb local heap for GDI."
240
241 "The deal is, if you hold onto one of the 5 shared DC's too long (as GL apps
242 do), Win95 will actually "steal" it from you. MakeCurrent fails,
243 apparently, because Windows re-assigns the HDC to a different window. The
244 only way to prevent this, the only reliable means, is to set CS_OWNDC."
245 */
246
247 if (!s_registeredGLCanvasClass)
248 {
249 WNDCLASS wndclass;
250
251 // the fields which are common to all classes
252 wndclass.lpfnWndProc = (WNDPROC)wxWndProc;
253 wndclass.cbClsExtra = 0;
254 wndclass.cbWndExtra = sizeof( DWORD ); // VZ: what is this DWORD used for?
255 wndclass.hInstance = wxhInstance;
256 wndclass.hIcon = (HICON) NULL;
257 wndclass.hCursor = ::LoadCursor((HINSTANCE)NULL, IDC_ARROW);
258 wndclass.lpszMenuName = NULL;
259
260 // Register the GLCanvas class name
261 wndclass.hbrBackground = (HBRUSH)NULL;
262 wndclass.lpszClassName = wxGLCanvasClassName;
263 wndclass.style = CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS | CS_OWNDC;
264
265 if ( !::RegisterClass(&wndclass) )
266 {
267 wxLogLastError(wxT("RegisterClass(wxGLCanvasClass)"));
268 return FALSE;
269 }
270
271 // Register the GLCanvas class name for windows which don't do full repaint
272 // on resize
273 wndclass.lpszClassName = wxGLCanvasClassNameNoRedraw;
274 wndclass.style &= ~(CS_HREDRAW | CS_VREDRAW);
275
276 if ( !::RegisterClass(&wndclass) )
277 {
278 wxLogLastError(wxT("RegisterClass(wxGLCanvasClassNameNoRedraw)"));
279
280 ::UnregisterClass(wxGLCanvasClassName, wxhInstance);
281
282 return FALSE;
283 }
284
285 s_registeredGLCanvasClass = TRUE;
286 }
287
288 wxCHECK_MSG( parent, FALSE, wxT("can't create wxWindow without parent") );
289
290 if ( !CreateBase(parent, id, pos, size, style, wxDefaultValidator, name) )
291 return FALSE;
292
293 parent->AddChild(this);
294
295 DWORD msflags = 0;
296
297 /*
298 A general rule with OpenGL and Win32 is that any window that will have a
299 HGLRC built for it must have two flags: WS_CLIPCHILDREN & WS_CLIPSIBLINGS.
300 You can find references about this within the knowledge base and most OpenGL
301 books that contain the wgl function descriptions.
302 */
303
304 WXDWORD exStyle = 0;
305 msflags |= WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN;
306 msflags |= MSWGetStyle(style, & exStyle) ;
307
308 return MSWCreate(wxGLCanvasClassName, NULL, pos, size, msflags, exStyle);
309 }
310
311 static void AdjustPFDForAttributes(PIXELFORMATDESCRIPTOR& pfd, int *attribList)
312 {
313 if (attribList) {
314 pfd.dwFlags &= ~PFD_DOUBLEBUFFER;
315 pfd.iPixelType = PFD_TYPE_COLORINDEX;
316 pfd.cColorBits = 0;
317 int arg=0;
318
319 while( (attribList[arg]!=0) )
320 {
321 switch( attribList[arg++] )
322 {
323 case WX_GL_RGBA:
324 pfd.iPixelType = PFD_TYPE_RGBA;
325 break;
326 case WX_GL_BUFFER_SIZE:
327 pfd.cColorBits = attribList[arg++];
328 break;
329 case WX_GL_LEVEL:
330 // this member looks like it may be obsolete
331 if (attribList[arg] > 0) {
332 pfd.iLayerType = (BYTE)PFD_OVERLAY_PLANE;
333 } else if (attribList[arg] < 0) {
334 pfd.iLayerType = (BYTE)PFD_UNDERLAY_PLANE;
335 } else {
336 pfd.iLayerType = (BYTE)PFD_MAIN_PLANE;
337 }
338 arg++;
339 break;
340 case WX_GL_DOUBLEBUFFER:
341 pfd.dwFlags |= PFD_DOUBLEBUFFER;
342 break;
343 case WX_GL_STEREO:
344 pfd.dwFlags |= PFD_STEREO;
345 break;
346 case WX_GL_AUX_BUFFERS:
347 pfd.cAuxBuffers = attribList[arg++];
348 break;
349 case WX_GL_MIN_RED:
350 pfd.cColorBits += (pfd.cRedBits = attribList[arg++]);
351 break;
352 case WX_GL_MIN_GREEN:
353 pfd.cColorBits += (pfd.cGreenBits = attribList[arg++]);
354 break;
355 case WX_GL_MIN_BLUE:
356 pfd.cColorBits += (pfd.cBlueBits = attribList[arg++]);
357 break;
358 case WX_GL_MIN_ALPHA:
359 // doesn't count in cColorBits
360 pfd.cAlphaBits = attribList[arg++];
361 break;
362 case WX_GL_DEPTH_SIZE:
363 pfd.cDepthBits = attribList[arg++];
364 break;
365 case WX_GL_STENCIL_SIZE:
366 pfd.cStencilBits = attribList[arg++];
367 break;
368 case WX_GL_MIN_ACCUM_RED:
369 pfd.cAccumBits += (pfd.cAccumRedBits = attribList[arg++]);
370 break;
371 case WX_GL_MIN_ACCUM_GREEN:
372 pfd.cAccumBits += (pfd.cAccumGreenBits = attribList[arg++]);
373 break;
374 case WX_GL_MIN_ACCUM_BLUE:
375 pfd.cAccumBits += (pfd.cAccumBlueBits = attribList[arg++]);
376 break;
377 case WX_GL_MIN_ACCUM_ALPHA:
378 pfd.cAccumBits += (pfd.cAccumAlphaBits = attribList[arg++]);
379 break;
380 default:
381 break;
382 }
383 }
384 }
385 }
386
387 void wxGLCanvas::SetupPixelFormat(int *attribList) // (HDC hDC)
388 {
389 PIXELFORMATDESCRIPTOR pfd = {
390 sizeof(PIXELFORMATDESCRIPTOR), /* size */
391 1, /* version */
392 PFD_SUPPORT_OPENGL |
393 PFD_DRAW_TO_WINDOW |
394 PFD_DOUBLEBUFFER, /* support double-buffering */
395 PFD_TYPE_RGBA, /* color type */
396 16, /* prefered color depth */
397 0, 0, 0, 0, 0, 0, /* color bits (ignored) */
398 0, /* no alpha buffer */
399 0, /* alpha bits (ignored) */
400 0, /* no accumulation buffer */
401 0, 0, 0, 0, /* accum bits (ignored) */
402 16, /* depth buffer */
403 0, /* no stencil buffer */
404 0, /* no auxiliary buffers */
405 PFD_MAIN_PLANE, /* main layer */
406 0, /* reserved */
407 0, 0, 0, /* no layer, visible, damage masks */
408 };
409
410 AdjustPFDForAttributes(pfd, attribList);
411
412 int pixelFormat = ChoosePixelFormat((HDC) m_hDC, &pfd);
413 if (pixelFormat == 0) {
414 wxLogLastError(_T("ChoosePixelFormat"));
415 }
416 else {
417 if ( !::SetPixelFormat((HDC) m_hDC, pixelFormat, &pfd) ) {
418 wxLogLastError(_T("SetPixelFormat"));
419 }
420 }
421 }
422
423 void wxGLCanvas::SetupPalette(const wxPalette& palette)
424 {
425 int pixelFormat = GetPixelFormat((HDC) m_hDC);
426 PIXELFORMATDESCRIPTOR pfd;
427
428 DescribePixelFormat((HDC) m_hDC, pixelFormat, sizeof(PIXELFORMATDESCRIPTOR), &pfd);
429
430 if (pfd.dwFlags & PFD_NEED_PALETTE)
431 {
432 }
433 else
434 {
435 return;
436 }
437
438 m_palette = palette;
439
440 if ( !m_palette.Ok() )
441 {
442 m_palette = CreateDefaultPalette();
443 }
444
445 if (m_palette.Ok())
446 {
447 SelectPalette((HDC) m_hDC, (HPALETTE) m_palette.GetHPALETTE(), FALSE);
448 RealizePalette((HDC) m_hDC);
449 }
450 }
451
452 wxPalette wxGLCanvas::CreateDefaultPalette()
453 {
454 PIXELFORMATDESCRIPTOR pfd;
455 int paletteSize;
456 int pixelFormat = GetPixelFormat((HDC) m_hDC);
457
458 DescribePixelFormat((HDC) m_hDC, pixelFormat, sizeof(PIXELFORMATDESCRIPTOR), &pfd);
459
460 paletteSize = 1 << pfd.cColorBits;
461
462 LOGPALETTE* pPal =
463 (LOGPALETTE*) malloc(sizeof(LOGPALETTE) + paletteSize * sizeof(PALETTEENTRY));
464 pPal->palVersion = 0x300;
465 pPal->palNumEntries = paletteSize;
466
467 /* build a simple RGB color palette */
468 {
469 int redMask = (1 << pfd.cRedBits) - 1;
470 int greenMask = (1 << pfd.cGreenBits) - 1;
471 int blueMask = (1 << pfd.cBlueBits) - 1;
472 int i;
473
474 for (i=0; i<paletteSize; ++i) {
475 pPal->palPalEntry[i].peRed =
476 (((i >> pfd.cRedShift) & redMask) * 255) / redMask;
477 pPal->palPalEntry[i].peGreen =
478 (((i >> pfd.cGreenShift) & greenMask) * 255) / greenMask;
479 pPal->palPalEntry[i].peBlue =
480 (((i >> pfd.cBlueShift) & blueMask) * 255) / blueMask;
481 pPal->palPalEntry[i].peFlags = 0;
482 }
483 }
484
485 HPALETTE hPalette = CreatePalette(pPal);
486 free(pPal);
487
488 wxPalette palette;
489 palette.SetHPALETTE((WXHPALETTE) hPalette);
490
491 return palette;
492 }
493
494 void wxGLCanvas::SwapBuffers()
495 {
496 if (m_glContext)
497 m_glContext->SwapBuffers();
498 }
499
500 void wxGLCanvas::OnSize(wxSizeEvent& event)
501 {
502 }
503
504 void wxGLCanvas::SetCurrent()
505 {
506 if (m_glContext)
507 {
508 m_glContext->SetCurrent();
509 }
510 }
511
512 void wxGLCanvas::SetColour(const wxChar *colour)
513 {
514 if (m_glContext)
515 m_glContext->SetColour(colour);
516 }
517
518 // TODO: Have to have this called by parent frame (?)
519 // So we need wxFrame to call OnQueryNewPalette for all children...
520 void wxGLCanvas::OnQueryNewPalette(wxQueryNewPaletteEvent& event)
521 {
522 /* realize palette if this is the current window */
523 if ( GetPalette()->Ok() ) {
524 ::UnrealizeObject((HPALETTE) GetPalette()->GetHPALETTE());
525 ::SelectPalette((HDC) GetHDC(), (HPALETTE) GetPalette()->GetHPALETTE(), FALSE);
526 ::RealizePalette((HDC) GetHDC());
527 Refresh();
528 event.SetPaletteRealized(TRUE);
529 }
530 else
531 event.SetPaletteRealized(FALSE);
532 }
533
534 // I think this doesn't have to be propagated to child windows.
535 void wxGLCanvas::OnPaletteChanged(wxPaletteChangedEvent& event)
536 {
537 /* realize palette if this is *not* the current window */
538 if ( GetPalette() &&
539 GetPalette()->Ok() && (this != event.GetChangedWindow()) )
540 {
541 ::UnrealizeObject((HPALETTE) GetPalette()->GetHPALETTE());
542 ::SelectPalette((HDC) GetHDC(), (HPALETTE) GetPalette()->GetHPALETTE(), FALSE);
543 ::RealizePalette((HDC) GetHDC());
544 Refresh();
545 }
546 }
547
548 /* Give extensions proper function names. */
549
550 /* EXT_vertex_array */
551 void glArrayElementEXT(GLint i)
552 {
553 }
554
555 void glColorPointerEXT(GLint size, GLenum type, GLsizei stride, GLsizei count, const GLvoid *pointer)
556 {
557 }
558
559 void glDrawArraysEXT(GLenum mode, GLint first, GLsizei count)
560 {
561 #ifdef GL_EXT_vertex_array
562 static PFNGLDRAWARRAYSEXTPROC proc = 0;
563
564 if ( !proc )
565 {
566 proc = (PFNGLDRAWARRAYSEXTPROC) wglGetProcAddress("glDrawArraysEXT");
567 }
568
569 if ( proc )
570 (* proc) (mode, first, count);
571 #endif
572 }
573
574 void glEdgeFlagPointerEXT(GLsizei stride, GLsizei count, const GLboolean *pointer)
575 {
576 }
577
578 void glGetPointervEXT(GLenum pname, GLvoid* *params)
579 {
580 }
581
582 void glIndexPointerEXT(GLenum type, GLsizei stride, GLsizei count, const GLvoid *pointer)
583 {
584 }
585
586 void glNormalPointerEXT(GLenum type, GLsizei stride, GLsizei count, const GLvoid *pointer)
587 {
588 #ifdef GL_EXT_vertex_array
589 static PFNGLNORMALPOINTEREXTPROC proc = 0;
590
591 if ( !proc )
592 {
593 proc = (PFNGLNORMALPOINTEREXTPROC) wglGetProcAddress("glNormalPointerEXT");
594 }
595
596 if ( proc )
597 (* proc) (type, stride, count, pointer);
598 #endif
599 }
600
601 void glTexCoordPointerEXT(GLint size, GLenum type, GLsizei stride, GLsizei count, const GLvoid *pointer)
602 {
603 }
604
605 void glVertexPointerEXT(GLint size, GLenum type, GLsizei stride, GLsizei count, const GLvoid *pointer)
606 {
607 #ifdef GL_EXT_vertex_array
608 static PFNGLVERTEXPOINTEREXTPROC proc = 0;
609
610 if ( !proc )
611 {
612 proc = (PFNGLVERTEXPOINTEREXTPROC) wglGetProcAddress("glVertexPointerEXT");
613 }
614 if ( proc )
615 (* proc) (size, type, stride, count, pointer);
616 #endif
617 }
618
619 /* EXT_color_subtable */
620 void glColorSubtableEXT(GLenum target, GLsizei start, GLsizei count, GLenum format, GLenum type, const GLvoid *table)
621 {
622 }
623
624 /* EXT_color_table */
625 void glColorTableEXT(GLenum target, GLenum internalformat, GLsizei width, GLenum format, GLenum type, const GLvoid *table)
626 {
627 }
628
629 void glCopyColorTableEXT(GLenum target, GLenum internalformat, GLint x, GLint y, GLsizei width)
630 {
631 }
632
633 void glGetColorTableEXT(GLenum target, GLenum format, GLenum type, GLvoid *table)
634 {
635 }
636
637 void glGetColorTableParamaterfvEXT(GLenum target, GLenum pname, GLfloat *params)
638 {
639 }
640
641 void glGetColorTavleParameterivEXT(GLenum target, GLenum pname, GLint *params)
642 {
643 }
644
645 /* SGI_compiled_vertex_array */
646 void glLockArraysSGI(GLint first, GLsizei count)
647 {
648 }
649
650 void glUnlockArraysSGI()
651 {
652 }
653
654
655 /* SGI_cull_vertex */
656 void glCullParameterdvSGI(GLenum pname, GLdouble* params)
657 {
658 }
659
660 void glCullParameterfvSGI(GLenum pname, GLfloat* params)
661 {
662 }
663
664 /* SGI_index_func */
665 void glIndexFuncSGI(GLenum func, GLclampf ref)
666 {
667 }
668
669 /* SGI_index_material */
670 void glIndexMaterialSGI(GLenum face, GLenum mode)
671 {
672 }
673
674 /* WIN_swap_hint */
675 void glAddSwapHintRectWin(GLint x, GLint y, GLsizei width, GLsizei height)
676 {
677 }
678
679
680 //---------------------------------------------------------------------------
681 // wxGLApp
682 //---------------------------------------------------------------------------
683
684 IMPLEMENT_CLASS(wxGLApp, wxApp)
685
686 bool wxGLApp::InitGLVisual(int *attribList)
687 {
688 int pixelFormat;
689 PIXELFORMATDESCRIPTOR pfd = {
690 sizeof(PIXELFORMATDESCRIPTOR), /* size */
691 1, /* version */
692 PFD_SUPPORT_OPENGL |
693 PFD_DRAW_TO_WINDOW |
694 PFD_DOUBLEBUFFER, /* support double-buffering */
695 PFD_TYPE_RGBA, /* color type */
696 16, /* prefered color depth */
697 0, 0, 0, 0, 0, 0, /* color bits (ignored) */
698 0, /* no alpha buffer */
699 0, /* alpha bits (ignored) */
700 0, /* no accumulation buffer */
701 0, 0, 0, 0, /* accum bits (ignored) */
702 16, /* depth buffer */
703 0, /* no stencil buffer */
704 0, /* no auxiliary buffers */
705 PFD_MAIN_PLANE, /* main layer */
706 0, /* reserved */
707 0, 0, 0, /* no layer, visible, damage masks */
708 };
709
710 AdjustPFDForAttributes(pfd, attribList);
711
712 // use DC for whole (root) screen, since no windows have yet been created
713 pixelFormat = ChoosePixelFormat(ScreenHDC(), &pfd);
714
715 if (pixelFormat == 0) {
716 wxLogError(_("Failed to initialize OpenGL"));
717 return FALSE;
718 }
719
720 return TRUE;
721 }
722
723 wxGLApp::~wxGLApp()
724 {
725 }
726
727 #endif
728 // wxUSE_GLCANVAS