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