document that SetCurrent() must be called on a visible window; assert that this is...
[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 void wxGLContext::SetColour(const wxChar *colour)
249 {
250 wxColour col = wxTheColourDatabase->Find(colour);
251 if (col.Ok())
252 {
253 float r = (float)(col.Red()/256.0);
254 float g = (float)(col.Green()/256.0);
255 float b = (float)(col.Blue()/256.0);
256 glColor3f( r, g, b);
257 }
258 }
259
260
261 /*
262 * wxGLCanvas implementation
263 */
264
265 IMPLEMENT_CLASS(wxGLCanvas, wxWindow)
266
267 BEGIN_EVENT_TABLE(wxGLCanvas, wxWindow)
268 EVT_SIZE(wxGLCanvas::OnSize)
269 EVT_PALETTE_CHANGED(wxGLCanvas::OnPaletteChanged)
270 EVT_QUERY_NEW_PALETTE(wxGLCanvas::OnQueryNewPalette)
271 END_EVENT_TABLE()
272
273 wxGLCanvas::wxGLCanvas(wxWindow *parent, wxWindowID id,
274 const wxPoint& pos, const wxSize& size, long style, const wxString& name,
275 int *attribList, const wxPalette& palette) : wxWindow()
276 {
277 m_glContext = (wxGLContext*) NULL;
278
279 bool ret = Create(parent, id, pos, size, style, name);
280
281 if ( ret )
282 {
283 SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_3DFACE));
284 }
285
286 m_hDC = (WXHDC) ::GetDC((HWND) GetHWND());
287
288 SetupPixelFormat(attribList);
289 SetupPalette(palette);
290
291 m_glContext = new wxGLContext(true, this, palette);
292 }
293
294 wxGLCanvas::wxGLCanvas( wxWindow *parent,
295 const wxGLContext *shared, wxWindowID id,
296 const wxPoint& pos, const wxSize& size, long style, const wxString& name,
297 int *attribList, const wxPalette& palette )
298 : wxWindow()
299 {
300 m_glContext = (wxGLContext*) NULL;
301
302 bool ret = Create(parent, id, pos, size, style, name);
303
304 if ( ret )
305 {
306 SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_3DFACE));
307 }
308
309 m_hDC = (WXHDC) ::GetDC((HWND) GetHWND());
310
311 SetupPixelFormat(attribList);
312 SetupPalette(palette);
313
314 m_glContext = new wxGLContext(true, this, palette, shared );
315 }
316
317 // Not very useful for wxMSW, but this is to be wxGTK compliant
318
319 wxGLCanvas::wxGLCanvas( wxWindow *parent, const wxGLCanvas *shared, wxWindowID id,
320 const wxPoint& pos, const wxSize& size, long style, const wxString& name,
321 int *attribList, const wxPalette& palette ):
322 wxWindow()
323 {
324 m_glContext = (wxGLContext*) NULL;
325
326 bool ret = Create(parent, id, pos, size, style, name);
327
328 if ( ret )
329 {
330 SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_3DFACE));
331 }
332
333 m_hDC = (WXHDC) ::GetDC((HWND) GetHWND());
334
335 SetupPixelFormat(attribList);
336 SetupPalette(palette);
337
338 wxGLContext *sharedContext=0;
339 if (shared) sharedContext=shared->GetContext();
340 m_glContext = new wxGLContext(true, this, palette, sharedContext );
341 }
342
343 wxGLCanvas::~wxGLCanvas()
344 {
345 delete m_glContext;
346
347 ::ReleaseDC((HWND) GetHWND(), (HDC) m_hDC);
348 }
349
350 // Replaces wxWindow::Create functionality, since we need to use a different
351 // window class
352 bool wxGLCanvas::Create(wxWindow *parent,
353 wxWindowID id,
354 const wxPoint& pos,
355 const wxSize& size,
356 long style,
357 const wxString& name)
358 {
359 wxCHECK_MSG( parent, false, wxT("can't create wxWindow without parent") );
360
361 if ( !wxGLModule::RegisterClasses() )
362 {
363 wxLogError(_("Failed to register OpenGL window class."));
364
365 return false;
366 }
367
368 if ( !CreateBase(parent, id, pos, size, style, wxDefaultValidator, name) )
369 return false;
370
371 parent->AddChild(this);
372
373 DWORD msflags = 0;
374
375 /*
376 A general rule with OpenGL and Win32 is that any window that will have a
377 HGLRC built for it must have two flags: WS_CLIPCHILDREN & WS_CLIPSIBLINGS.
378 You can find references about this within the knowledge base and most OpenGL
379 books that contain the wgl function descriptions.
380 */
381
382 WXDWORD exStyle = 0;
383 msflags |= WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN;
384 msflags |= MSWGetStyle(style, & exStyle) ;
385
386 return MSWCreate(wxGLCanvasClassName, NULL, pos, size, msflags, exStyle);
387 }
388
389 static void AdjustPFDForAttributes(PIXELFORMATDESCRIPTOR& pfd, int *attribList)
390 {
391 if (attribList) {
392 pfd.dwFlags &= ~PFD_DOUBLEBUFFER;
393 pfd.iPixelType = PFD_TYPE_COLORINDEX;
394 pfd.cColorBits = 0;
395 int arg=0;
396
397 while( (attribList[arg]!=0) )
398 {
399 switch( attribList[arg++] )
400 {
401 case WX_GL_RGBA:
402 pfd.iPixelType = PFD_TYPE_RGBA;
403 break;
404 case WX_GL_BUFFER_SIZE:
405 pfd.cColorBits = (BYTE)attribList[arg++];
406 break;
407 case WX_GL_LEVEL:
408 // this member looks like it may be obsolete
409 if (attribList[arg] > 0) {
410 pfd.iLayerType = (BYTE)PFD_OVERLAY_PLANE;
411 } else if (attribList[arg] < 0) {
412 pfd.iLayerType = (BYTE)PFD_UNDERLAY_PLANE;
413 } else {
414 pfd.iLayerType = (BYTE)PFD_MAIN_PLANE;
415 }
416 arg++;
417 break;
418 case WX_GL_DOUBLEBUFFER:
419 pfd.dwFlags |= PFD_DOUBLEBUFFER;
420 break;
421 case WX_GL_STEREO:
422 pfd.dwFlags |= PFD_STEREO;
423 break;
424 case WX_GL_AUX_BUFFERS:
425 pfd.cAuxBuffers = (BYTE)attribList[arg++];
426 break;
427 case WX_GL_MIN_RED:
428 pfd.cColorBits = (BYTE)(pfd.cColorBits + (pfd.cRedBits = (BYTE)attribList[arg++]));
429 break;
430 case WX_GL_MIN_GREEN:
431 pfd.cColorBits = (BYTE)(pfd.cColorBits + (pfd.cGreenBits = (BYTE)attribList[arg++]));
432 break;
433 case WX_GL_MIN_BLUE:
434 pfd.cColorBits = (BYTE)(pfd.cColorBits + (pfd.cBlueBits = (BYTE)attribList[arg++]));
435 break;
436 case WX_GL_MIN_ALPHA:
437 // doesn't count in cColorBits
438 pfd.cAlphaBits = (BYTE)attribList[arg++];
439 break;
440 case WX_GL_DEPTH_SIZE:
441 pfd.cDepthBits = (BYTE)attribList[arg++];
442 break;
443 case WX_GL_STENCIL_SIZE:
444 pfd.cStencilBits = (BYTE)attribList[arg++];
445 break;
446 case WX_GL_MIN_ACCUM_RED:
447 pfd.cAccumBits = (BYTE)(pfd.cAccumBits + (pfd.cAccumRedBits = (BYTE)attribList[arg++]));
448 break;
449 case WX_GL_MIN_ACCUM_GREEN:
450 pfd.cAccumBits = (BYTE)(pfd.cAccumBits + (pfd.cAccumGreenBits = (BYTE)attribList[arg++]));
451 break;
452 case WX_GL_MIN_ACCUM_BLUE:
453 pfd.cAccumBits = (BYTE)(pfd.cAccumBits + (pfd.cAccumBlueBits = (BYTE)attribList[arg++]));
454 break;
455 case WX_GL_MIN_ACCUM_ALPHA:
456 pfd.cAccumBits = (BYTE)(pfd.cAccumBits + (pfd.cAccumAlphaBits = (BYTE)attribList[arg++]));
457 break;
458 default:
459 break;
460 }
461 }
462 }
463 }
464
465 void wxGLCanvas::SetupPixelFormat(int *attribList) // (HDC hDC)
466 {
467 PIXELFORMATDESCRIPTOR pfd = {
468 sizeof(PIXELFORMATDESCRIPTOR), /* size */
469 1, /* version */
470 PFD_SUPPORT_OPENGL |
471 PFD_DRAW_TO_WINDOW |
472 PFD_DOUBLEBUFFER, /* support double-buffering */
473 PFD_TYPE_RGBA, /* color type */
474 16, /* preferred color depth */
475 0, 0, 0, 0, 0, 0, /* color bits (ignored) */
476 0, /* no alpha buffer */
477 0, /* alpha bits (ignored) */
478 0, /* no accumulation buffer */
479 0, 0, 0, 0, /* accum bits (ignored) */
480 16, /* depth buffer */
481 0, /* no stencil buffer */
482 0, /* no auxiliary buffers */
483 PFD_MAIN_PLANE, /* main layer */
484 0, /* reserved */
485 0, 0, 0, /* no layer, visible, damage masks */
486 };
487
488 AdjustPFDForAttributes(pfd, attribList);
489
490 int pixelFormat = ChoosePixelFormat((HDC) m_hDC, &pfd);
491 if (pixelFormat == 0) {
492 wxLogLastError(_T("ChoosePixelFormat"));
493 }
494 else {
495 if ( !::SetPixelFormat((HDC) m_hDC, pixelFormat, &pfd) ) {
496 wxLogLastError(_T("SetPixelFormat"));
497 }
498 }
499 }
500
501 void wxGLCanvas::SetupPalette(const wxPalette& palette)
502 {
503 int pixelFormat = GetPixelFormat((HDC) m_hDC);
504 PIXELFORMATDESCRIPTOR pfd;
505
506 DescribePixelFormat((HDC) m_hDC, pixelFormat, sizeof(PIXELFORMATDESCRIPTOR), &pfd);
507
508 if (pfd.dwFlags & PFD_NEED_PALETTE)
509 {
510 }
511 else
512 {
513 return;
514 }
515
516 m_palette = palette;
517
518 if ( !m_palette.Ok() )
519 {
520 m_palette = CreateDefaultPalette();
521 }
522
523 if (m_palette.Ok())
524 {
525 ::SelectPalette((HDC) m_hDC, (HPALETTE) m_palette.GetHPALETTE(), FALSE);
526 ::RealizePalette((HDC) m_hDC);
527 }
528 }
529
530 wxPalette wxGLCanvas::CreateDefaultPalette()
531 {
532 PIXELFORMATDESCRIPTOR pfd;
533 int paletteSize;
534 int pixelFormat = GetPixelFormat((HDC) m_hDC);
535
536 DescribePixelFormat((HDC) m_hDC, pixelFormat, sizeof(PIXELFORMATDESCRIPTOR), &pfd);
537
538 paletteSize = 1 << pfd.cColorBits;
539
540 LOGPALETTE* pPal =
541 (LOGPALETTE*) malloc(sizeof(LOGPALETTE) + paletteSize * sizeof(PALETTEENTRY));
542 pPal->palVersion = 0x300;
543 pPal->palNumEntries = (WORD)paletteSize;
544
545 /* build a simple RGB color palette */
546 {
547 int redMask = (1 << pfd.cRedBits) - 1;
548 int greenMask = (1 << pfd.cGreenBits) - 1;
549 int blueMask = (1 << pfd.cBlueBits) - 1;
550 int i;
551
552 for (i=0; i<paletteSize; ++i) {
553 pPal->palPalEntry[i].peRed =
554 (BYTE)((((i >> pfd.cRedShift) & redMask) * 255) / redMask);
555 pPal->palPalEntry[i].peGreen =
556 (BYTE)((((i >> pfd.cGreenShift) & greenMask) * 255) / greenMask);
557 pPal->palPalEntry[i].peBlue =
558 (BYTE)((((i >> pfd.cBlueShift) & blueMask) * 255) / blueMask);
559 pPal->palPalEntry[i].peFlags = 0;
560 }
561 }
562
563 HPALETTE hPalette = CreatePalette(pPal);
564 free(pPal);
565
566 wxPalette palette;
567 palette.SetHPALETTE((WXHPALETTE) hPalette);
568
569 return palette;
570 }
571
572 void wxGLCanvas::SwapBuffers()
573 {
574 if (m_glContext)
575 m_glContext->SwapBuffers();
576 }
577
578 void wxGLCanvas::OnSize(wxSizeEvent& WXUNUSED(event))
579 {
580 }
581
582 void wxGLCanvas::SetCurrent()
583 {
584 // although on MSW it works even if the window is still hidden, it doesn't
585 // under wxGTK and documentation mentions that SetCurrent() can only be
586 // called for a shown window, so check it
587 wxASSERT_MSG( GetParent()->IsShown(),
588 _T("can't make hidden GL canvas current") );
589
590 if (m_glContext)
591 {
592 m_glContext->SetCurrent();
593 }
594 }
595
596 void wxGLCanvas::SetColour(const wxChar *colour)
597 {
598 if (m_glContext)
599 m_glContext->SetColour(colour);
600 }
601
602 // TODO: Have to have this called by parent frame (?)
603 // So we need wxFrame to call OnQueryNewPalette for all children...
604 void wxGLCanvas::OnQueryNewPalette(wxQueryNewPaletteEvent& event)
605 {
606 /* realize palette if this is the current window */
607 if ( GetPalette()->Ok() ) {
608 ::UnrealizeObject((HPALETTE) GetPalette()->GetHPALETTE());
609 ::SelectPalette((HDC) GetHDC(), (HPALETTE) GetPalette()->GetHPALETTE(), FALSE);
610 ::RealizePalette((HDC) GetHDC());
611 Refresh();
612 event.SetPaletteRealized(true);
613 }
614 else
615 event.SetPaletteRealized(false);
616 }
617
618 // I think this doesn't have to be propagated to child windows.
619 void wxGLCanvas::OnPaletteChanged(wxPaletteChangedEvent& event)
620 {
621 /* realize palette if this is *not* the current window */
622 if ( GetPalette() &&
623 GetPalette()->Ok() && (this != event.GetChangedWindow()) )
624 {
625 ::UnrealizeObject((HPALETTE) GetPalette()->GetHPALETTE());
626 ::SelectPalette((HDC) GetHDC(), (HPALETTE) GetPalette()->GetHPALETTE(), FALSE);
627 ::RealizePalette((HDC) GetHDC());
628 Refresh();
629 }
630 }
631
632 /* Give extensions proper function names. */
633
634 /* EXT_vertex_array */
635 void glArrayElementEXT(GLint WXUNUSED(i))
636 {
637 }
638
639 void glColorPointerEXT(GLint WXUNUSED(size), GLenum WXUNUSED(type), GLsizei WXUNUSED(stride), GLsizei WXUNUSED(count), const GLvoid *WXUNUSED(pointer))
640 {
641 }
642
643 void glDrawArraysEXT(GLenum WXUNUSED_WITHOUT_GL_EXT_vertex_array(mode),
644 GLint WXUNUSED_WITHOUT_GL_EXT_vertex_array(first),
645 GLsizei WXUNUSED_WITHOUT_GL_EXT_vertex_array(count))
646 {
647 #ifdef GL_EXT_vertex_array
648 static PFNGLDRAWARRAYSEXTPROC proc = 0;
649
650 if ( !proc )
651 {
652 proc = (PFNGLDRAWARRAYSEXTPROC) wglGetProcAddress("glDrawArraysEXT");
653 }
654
655 if ( proc )
656 (* proc) (mode, first, count);
657 #endif
658 }
659
660 void glEdgeFlagPointerEXT(GLsizei WXUNUSED(stride), GLsizei WXUNUSED(count), const GLboolean *WXUNUSED(pointer))
661 {
662 }
663
664 void glGetPointervEXT(GLenum WXUNUSED(pname), GLvoid* *WXUNUSED(params))
665 {
666 }
667
668 void glIndexPointerEXT(GLenum WXUNUSED(type), GLsizei WXUNUSED(stride), GLsizei WXUNUSED(count), const GLvoid *WXUNUSED(pointer))
669 {
670 }
671
672 void glNormalPointerEXT(GLenum WXUNUSED_WITHOUT_GL_EXT_vertex_array(type),
673 GLsizei WXUNUSED_WITHOUT_GL_EXT_vertex_array(stride),
674 GLsizei WXUNUSED_WITHOUT_GL_EXT_vertex_array(count),
675 const GLvoid *WXUNUSED_WITHOUT_GL_EXT_vertex_array(pointer))
676 {
677 #ifdef GL_EXT_vertex_array
678 static PFNGLNORMALPOINTEREXTPROC proc = 0;
679
680 if ( !proc )
681 {
682 proc = (PFNGLNORMALPOINTEREXTPROC) wglGetProcAddress("glNormalPointerEXT");
683 }
684
685 if ( proc )
686 (* proc) (type, stride, count, pointer);
687 #endif
688 }
689
690 void glTexCoordPointerEXT(GLint WXUNUSED(size), GLenum WXUNUSED(type), GLsizei WXUNUSED(stride), GLsizei WXUNUSED(count), const GLvoid *WXUNUSED(pointer))
691 {
692 }
693
694 void glVertexPointerEXT(GLint WXUNUSED_WITHOUT_GL_EXT_vertex_array(size),
695 GLenum WXUNUSED_WITHOUT_GL_EXT_vertex_array(type),
696 GLsizei WXUNUSED_WITHOUT_GL_EXT_vertex_array(stride),
697 GLsizei WXUNUSED_WITHOUT_GL_EXT_vertex_array(count),
698 const GLvoid *WXUNUSED_WITHOUT_GL_EXT_vertex_array(pointer))
699 {
700 #ifdef GL_EXT_vertex_array
701 static PFNGLVERTEXPOINTEREXTPROC proc = 0;
702
703 if ( !proc )
704 {
705 proc = (PFNGLVERTEXPOINTEREXTPROC) wglGetProcAddress("glVertexPointerEXT");
706 }
707 if ( proc )
708 (* proc) (size, type, stride, count, pointer);
709 #endif
710 }
711
712 /* EXT_color_subtable */
713 void glColorSubtableEXT(GLenum WXUNUSED(target), GLsizei WXUNUSED(start), GLsizei WXUNUSED(count), GLenum WXUNUSED(format), GLenum WXUNUSED(type), const GLvoid *WXUNUSED(table))
714 {
715 }
716
717 /* EXT_color_table */
718 void glColorTableEXT(GLenum WXUNUSED(target), GLenum WXUNUSED(internalformat), GLsizei WXUNUSED(width), GLenum WXUNUSED(format), GLenum WXUNUSED(type), const GLvoid *WXUNUSED(table))
719 {
720 }
721
722 void glCopyColorTableEXT(GLenum WXUNUSED(target), GLenum WXUNUSED(internalformat), GLint WXUNUSED(x), GLint WXUNUSED(y), GLsizei WXUNUSED(width))
723 {
724 }
725
726 void glGetColorTableEXT(GLenum WXUNUSED(target), GLenum WXUNUSED(format), GLenum WXUNUSED(type), GLvoid *WXUNUSED(table))
727 {
728 }
729
730 void glGetColorTableParamaterfvEXT(GLenum WXUNUSED(target), GLenum WXUNUSED(pname), GLfloat *WXUNUSED(params))
731 {
732 }
733
734 void glGetColorTavleParameterivEXT(GLenum WXUNUSED(target), GLenum WXUNUSED(pname), GLint *WXUNUSED(params))
735 {
736 }
737
738 /* SGI_compiled_vertex_array */
739 void glLockArraysSGI(GLint WXUNUSED(first), GLsizei WXUNUSED(count))
740 {
741 }
742
743 void glUnlockArraysSGI()
744 {
745 }
746
747
748 /* SGI_cull_vertex */
749 void glCullParameterdvSGI(GLenum WXUNUSED(pname), GLdouble* WXUNUSED(params))
750 {
751 }
752
753 void glCullParameterfvSGI(GLenum WXUNUSED(pname), GLfloat* WXUNUSED(params))
754 {
755 }
756
757 /* SGI_index_func */
758 void glIndexFuncSGI(GLenum WXUNUSED(func), GLclampf WXUNUSED(ref))
759 {
760 }
761
762 /* SGI_index_material */
763 void glIndexMaterialSGI(GLenum WXUNUSED(face), GLenum WXUNUSED(mode))
764 {
765 }
766
767 /* WIN_swap_hint */
768 void glAddSwapHintRectWin(GLint WXUNUSED(x), GLint WXUNUSED(y), GLsizei WXUNUSED(width), GLsizei WXUNUSED(height))
769 {
770 }
771
772
773 //---------------------------------------------------------------------------
774 // wxGLApp
775 //---------------------------------------------------------------------------
776
777 IMPLEMENT_CLASS(wxGLApp, wxApp)
778
779 bool wxGLApp::InitGLVisual(int *attribList)
780 {
781 int pixelFormat;
782 PIXELFORMATDESCRIPTOR pfd = {
783 sizeof(PIXELFORMATDESCRIPTOR), /* size */
784 1, /* version */
785 PFD_SUPPORT_OPENGL |
786 PFD_DRAW_TO_WINDOW |
787 PFD_DOUBLEBUFFER, /* support double-buffering */
788 PFD_TYPE_RGBA, /* color type */
789 16, /* preferred color depth */
790 0, 0, 0, 0, 0, 0, /* color bits (ignored) */
791 0, /* no alpha buffer */
792 0, /* alpha bits (ignored) */
793 0, /* no accumulation buffer */
794 0, 0, 0, 0, /* accum bits (ignored) */
795 16, /* depth buffer */
796 0, /* no stencil buffer */
797 0, /* no auxiliary buffers */
798 PFD_MAIN_PLANE, /* main layer */
799 0, /* reserved */
800 0, 0, 0, /* no layer, visible, damage masks */
801 };
802
803 AdjustPFDForAttributes(pfd, attribList);
804
805 // use DC for whole (root) screen, since no windows have yet been created
806 pixelFormat = ChoosePixelFormat(ScreenHDC(), &pfd);
807
808 if (pixelFormat == 0) {
809 wxLogError(_("Failed to initialize OpenGL"));
810 return false;
811 }
812
813 return true;
814 }
815
816 wxGLApp::~wxGLApp()
817 {
818 }
819
820 #endif
821 // wxUSE_GLCANVAS