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