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