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