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