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