]> git.saurik.com Git - wxWidgets.git/blame - src/msw/glcanvas.cpp
really fixed wrong argument to wxString::Format()
[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 }
8b089c5e
JS
246}
247
2b5f62a0 248void wxGLContext::SetColour(const wxChar *colour)
8b089c5e 249{
564a150b
VZ
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 }
8b089c5e
JS
258}
259
260
261/*
262 * wxGLCanvas implementation
263 */
264
4660d7e5 265IMPLEMENT_CLASS(wxGLCanvas, wxWindow)
8b089c5e 266
4660d7e5 267BEGIN_EVENT_TABLE(wxGLCanvas, wxWindow)
8b089c5e
JS
268 EVT_SIZE(wxGLCanvas::OnSize)
269 EVT_PALETTE_CHANGED(wxGLCanvas::OnPaletteChanged)
270 EVT_QUERY_NEW_PALETTE(wxGLCanvas::OnQueryNewPalette)
271END_EVENT_TABLE()
272
273wxGLCanvas::wxGLCanvas(wxWindow *parent, wxWindowID id,
274 const wxPoint& pos, const wxSize& size, long style, const wxString& name,
4660d7e5 275 int *attribList, const wxPalette& palette) : wxWindow()
8b089c5e 276{
f48d169c 277 m_glContext = (wxGLContext*) NULL;
8b089c5e 278
f48d169c 279 bool ret = Create(parent, id, pos, size, style, name);
8b089c5e 280
f48d169c
UN
281 if ( ret )
282 {
a756f210 283 SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_3DFACE));
f48d169c 284 }
8b089c5e 285
f48d169c 286 m_hDC = (WXHDC) ::GetDC((HWND) GetHWND());
8b089c5e 287
f48d169c
UN
288 SetupPixelFormat(attribList);
289 SetupPalette(palette);
8b089c5e 290
213ceb3f 291 m_glContext = new wxGLContext(true, this, palette);
8b089c5e
JS
292}
293
294wxGLCanvas::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 )
4660d7e5 298 : wxWindow()
8b089c5e 299{
f48d169c 300 m_glContext = (wxGLContext*) NULL;
8b089c5e 301
f48d169c 302 bool ret = Create(parent, id, pos, size, style, name);
8b089c5e 303
f48d169c
UN
304 if ( ret )
305 {
a756f210 306 SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_3DFACE));
f48d169c 307 }
8b089c5e 308
f48d169c 309 m_hDC = (WXHDC) ::GetDC((HWND) GetHWND());
8b089c5e 310
f48d169c
UN
311 SetupPixelFormat(attribList);
312 SetupPalette(palette);
8b089c5e 313
213ceb3f 314 m_glContext = new wxGLContext(true, this, palette, shared );
8b089c5e
JS
315}
316
f6bcfd97 317// Not very useful for wxMSW, but this is to be wxGTK compliant
8b089c5e
JS
318
319wxGLCanvas::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 ):
4660d7e5 322 wxWindow()
8b089c5e 323{
f48d169c 324 m_glContext = (wxGLContext*) NULL;
8b089c5e 325
f48d169c 326 bool ret = Create(parent, id, pos, size, style, name);
8b089c5e 327
f48d169c
UN
328 if ( ret )
329 {
a756f210 330 SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_3DFACE));
f48d169c 331 }
8b089c5e 332
f48d169c 333 m_hDC = (WXHDC) ::GetDC((HWND) GetHWND());
8b089c5e 334
f48d169c
UN
335 SetupPixelFormat(attribList);
336 SetupPalette(palette);
8b089c5e 337
f48d169c
UN
338 wxGLContext *sharedContext=0;
339 if (shared) sharedContext=shared->GetContext();
213ceb3f 340 m_glContext = new wxGLContext(true, this, palette, sharedContext );
8b089c5e
JS
341}
342
343wxGLCanvas::~wxGLCanvas()
344{
53fcd32e 345 delete m_glContext;
8b089c5e
JS
346
347 ::ReleaseDC((HWND) GetHWND(), (HDC) m_hDC);
348}
349
b225f659
VZ
350// Replaces wxWindow::Create functionality, since we need to use a different
351// window class
352bool wxGLCanvas::Create(wxWindow *parent,
353 wxWindowID id,
354 const wxPoint& pos,
355 const wxSize& size,
356 long style,
357 const wxString& name)
8b089c5e 358{
53fcd32e 359 wxCHECK_MSG( parent, false, wxT("can't create wxWindow without parent") );
8b089c5e 360
53fcd32e 361 if ( !wxGLModule::RegisterClasses() )
b225f659 362 {
53fcd32e 363 wxLogError(_("Failed to register OpenGL window class."));
b225f659 364
213ceb3f 365 return false;
b225f659
VZ
366 }
367
53fcd32e
VZ
368 if ( !CreateBase(parent, id, pos, size, style, wxDefaultValidator, name) )
369 return false;
f48d169c 370
53fcd32e 371 parent->AddChild(this);
f48d169c 372
53fcd32e 373 DWORD msflags = 0;
f48d169c 374
53fcd32e
VZ
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 */
8b089c5e 381
53fcd32e
VZ
382 WXDWORD exStyle = 0;
383 msflags |= WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN;
384 msflags |= MSWGetStyle(style, & exStyle) ;
f48d169c 385
53fcd32e 386 return MSWCreate(wxGLCanvasClassName, NULL, pos, size, msflags, exStyle);
8b089c5e
JS
387}
388
a3081354 389static void AdjustPFDForAttributes(PIXELFORMATDESCRIPTOR& pfd, int *attribList)
8b089c5e 390{
f48d169c
UN
391 if (attribList) {
392 pfd.dwFlags &= ~PFD_DOUBLEBUFFER;
393 pfd.iPixelType = PFD_TYPE_COLORINDEX;
394 pfd.cColorBits = 0;
395 int arg=0;
b225f659 396
f48d169c
UN
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:
b8ee9a86 405 pfd.cColorBits = (BYTE)attribList[arg++];
f48d169c
UN
406 break;
407 case WX_GL_LEVEL:
408 // this member looks like it may be obsolete
409 if (attribList[arg] > 0) {
d728116a 410 pfd.iLayerType = (BYTE)PFD_OVERLAY_PLANE;
f48d169c 411 } else if (attribList[arg] < 0) {
d728116a 412 pfd.iLayerType = (BYTE)PFD_UNDERLAY_PLANE;
f48d169c 413 } else {
d728116a 414 pfd.iLayerType = (BYTE)PFD_MAIN_PLANE;
f48d169c
UN
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:
b8ee9a86 425 pfd.cAuxBuffers = (BYTE)attribList[arg++];
f48d169c
UN
426 break;
427 case WX_GL_MIN_RED:
b8ee9a86 428 pfd.cColorBits = (BYTE)(pfd.cColorBits + (pfd.cRedBits = (BYTE)attribList[arg++]));
f48d169c
UN
429 break;
430 case WX_GL_MIN_GREEN:
b8ee9a86 431 pfd.cColorBits = (BYTE)(pfd.cColorBits + (pfd.cGreenBits = (BYTE)attribList[arg++]));
f48d169c
UN
432 break;
433 case WX_GL_MIN_BLUE:
b8ee9a86 434 pfd.cColorBits = (BYTE)(pfd.cColorBits + (pfd.cBlueBits = (BYTE)attribList[arg++]));
f48d169c
UN
435 break;
436 case WX_GL_MIN_ALPHA:
437 // doesn't count in cColorBits
b8ee9a86 438 pfd.cAlphaBits = (BYTE)attribList[arg++];
f48d169c 439 break;
b225f659 440 case WX_GL_DEPTH_SIZE:
b8ee9a86 441 pfd.cDepthBits = (BYTE)attribList[arg++];
f48d169c 442 break;
b225f659 443 case WX_GL_STENCIL_SIZE:
b8ee9a86 444 pfd.cStencilBits = (BYTE)attribList[arg++];
f48d169c
UN
445 break;
446 case WX_GL_MIN_ACCUM_RED:
b8ee9a86 447 pfd.cAccumBits = (BYTE)(pfd.cAccumBits + (pfd.cAccumRedBits = (BYTE)attribList[arg++]));
f48d169c
UN
448 break;
449 case WX_GL_MIN_ACCUM_GREEN:
b8ee9a86 450 pfd.cAccumBits = (BYTE)(pfd.cAccumBits + (pfd.cAccumGreenBits = (BYTE)attribList[arg++]));
f48d169c
UN
451 break;
452 case WX_GL_MIN_ACCUM_BLUE:
b8ee9a86 453 pfd.cAccumBits = (BYTE)(pfd.cAccumBits + (pfd.cAccumBlueBits = (BYTE)attribList[arg++]));
f48d169c
UN
454 break;
455 case WX_GL_MIN_ACCUM_ALPHA:
b8ee9a86 456 pfd.cAccumBits = (BYTE)(pfd.cAccumBits + (pfd.cAccumAlphaBits = (BYTE)attribList[arg++]));
f48d169c
UN
457 break;
458 default:
459 break;
460 }
8b089c5e 461 }
f48d169c 462 }
a3081354
VZ
463}
464
465void wxGLCanvas::SetupPixelFormat(int *attribList) // (HDC hDC)
466{
a3081354 467 PIXELFORMATDESCRIPTOR pfd = {
b225f659
VZ
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 */
3103e8a9 474 16, /* preferred color depth */
b225f659
VZ
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 };
a3081354
VZ
487
488 AdjustPFDForAttributes(pfd, attribList);
489
72adfc4b 490 int pixelFormat = ChoosePixelFormat((HDC) m_hDC, &pfd);
f48d169c 491 if (pixelFormat == 0) {
72adfc4b 492 wxLogLastError(_T("ChoosePixelFormat"));
f48d169c 493 }
a3081354 494 else {
72adfc4b
VZ
495 if ( !::SetPixelFormat((HDC) m_hDC, pixelFormat, &pfd) ) {
496 wxLogLastError(_T("SetPixelFormat"));
a3081354 497 }
f48d169c 498 }
8b089c5e
JS
499}
500
501void 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 {
b225f659 513 return;
8b089c5e
JS
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 {
213ceb3f
WS
525 ::SelectPalette((HDC) m_hDC, (HPALETTE) m_palette.GetHPALETTE(), FALSE);
526 ::RealizePalette((HDC) m_hDC);
8b089c5e
JS
527 }
528}
529
530wxPalette 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
f48d169c 538 paletteSize = 1 << pfd.cColorBits;
8b089c5e
JS
539
540 LOGPALETTE* pPal =
541 (LOGPALETTE*) malloc(sizeof(LOGPALETTE) + paletteSize * sizeof(PALETTEENTRY));
542 pPal->palVersion = 0x300;
b8ee9a86 543 pPal->palNumEntries = (WORD)paletteSize;
8b089c5e
JS
544
545 /* build a simple RGB color palette */
546 {
b225f659
VZ
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 =
b8ee9a86 554 (BYTE)((((i >> pfd.cRedShift) & redMask) * 255) / redMask);
b225f659 555 pPal->palPalEntry[i].peGreen =
b8ee9a86 556 (BYTE)((((i >> pfd.cGreenShift) & greenMask) * 255) / greenMask);
b225f659 557 pPal->palPalEntry[i].peBlue =
b8ee9a86 558 (BYTE)((((i >> pfd.cBlueShift) & blueMask) * 255) / blueMask);
b225f659
VZ
559 pPal->palPalEntry[i].peFlags = 0;
560 }
8b089c5e
JS
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
572void wxGLCanvas::SwapBuffers()
573{
574 if (m_glContext)
575 m_glContext->SwapBuffers();
576}
577
2341cf5f 578void wxGLCanvas::OnSize(wxSizeEvent& WXUNUSED(event))
8b089c5e 579{
8b089c5e
JS
580}
581
582void wxGLCanvas::SetCurrent()
583{
2d918775
VZ
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
8b089c5e
JS
590 if (m_glContext)
591 {
592 m_glContext->SetCurrent();
593 }
594}
595
2b5f62a0 596void wxGLCanvas::SetColour(const wxChar *colour)
8b089c5e
JS
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...
604void wxGLCanvas::OnQueryNewPalette(wxQueryNewPaletteEvent& event)
605{
f48d169c
UN
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();
213ceb3f 612 event.SetPaletteRealized(true);
f48d169c
UN
613 }
614 else
213ceb3f 615 event.SetPaletteRealized(false);
8b089c5e
JS
616}
617
618// I think this doesn't have to be propagated to child windows.
619void wxGLCanvas::OnPaletteChanged(wxPaletteChangedEvent& event)
620{
f48d169c
UN
621 /* realize palette if this is *not* the current window */
622 if ( GetPalette() &&
8b089c5e 623 GetPalette()->Ok() && (this != event.GetChangedWindow()) )
f48d169c
UN
624 {
625 ::UnrealizeObject((HPALETTE) GetPalette()->GetHPALETTE());
626 ::SelectPalette((HDC) GetHDC(), (HPALETTE) GetPalette()->GetHPALETTE(), FALSE);
627 ::RealizePalette((HDC) GetHDC());
628 Refresh();
629 }
8b089c5e
JS
630}
631
632/* Give extensions proper function names. */
633
634/* EXT_vertex_array */
2341cf5f 635void glArrayElementEXT(GLint WXUNUSED(i))
8b089c5e
JS
636{
637}
638
2341cf5f 639void glColorPointerEXT(GLint WXUNUSED(size), GLenum WXUNUSED(type), GLsizei WXUNUSED(stride), GLsizei WXUNUSED(count), const GLvoid *WXUNUSED(pointer))
8b089c5e
JS
640{
641}
642
b8ee9a86
WS
643void 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))
8b089c5e
JS
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
2341cf5f 660void glEdgeFlagPointerEXT(GLsizei WXUNUSED(stride), GLsizei WXUNUSED(count), const GLboolean *WXUNUSED(pointer))
8b089c5e
JS
661{
662}
663
2341cf5f 664void glGetPointervEXT(GLenum WXUNUSED(pname), GLvoid* *WXUNUSED(params))
8b089c5e
JS
665{
666}
667
2341cf5f 668void glIndexPointerEXT(GLenum WXUNUSED(type), GLsizei WXUNUSED(stride), GLsizei WXUNUSED(count), const GLvoid *WXUNUSED(pointer))
8b089c5e
JS
669{
670}
671
b8ee9a86
WS
672void 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))
8b089c5e
JS
676{
677#ifdef GL_EXT_vertex_array
f48d169c 678 static PFNGLNORMALPOINTEREXTPROC proc = 0;
8b089c5e 679
f48d169c
UN
680 if ( !proc )
681 {
682 proc = (PFNGLNORMALPOINTEREXTPROC) wglGetProcAddress("glNormalPointerEXT");
683 }
8b089c5e 684
f48d169c
UN
685 if ( proc )
686 (* proc) (type, stride, count, pointer);
8b089c5e
JS
687#endif
688}
689
2341cf5f 690void glTexCoordPointerEXT(GLint WXUNUSED(size), GLenum WXUNUSED(type), GLsizei WXUNUSED(stride), GLsizei WXUNUSED(count), const GLvoid *WXUNUSED(pointer))
8b089c5e
JS
691{
692}
693
b8ee9a86
WS
694void 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))
8b089c5e
JS
699{
700#ifdef GL_EXT_vertex_array
f48d169c 701 static PFNGLVERTEXPOINTEREXTPROC proc = 0;
8b089c5e 702
f48d169c
UN
703 if ( !proc )
704 {
705 proc = (PFNGLVERTEXPOINTEREXTPROC) wglGetProcAddress("glVertexPointerEXT");
706 }
707 if ( proc )
708 (* proc) (size, type, stride, count, pointer);
8b089c5e
JS
709#endif
710}
711
712/* EXT_color_subtable */
2341cf5f 713void glColorSubtableEXT(GLenum WXUNUSED(target), GLsizei WXUNUSED(start), GLsizei WXUNUSED(count), GLenum WXUNUSED(format), GLenum WXUNUSED(type), const GLvoid *WXUNUSED(table))
8b089c5e
JS
714{
715}
716
717/* EXT_color_table */
2341cf5f 718void glColorTableEXT(GLenum WXUNUSED(target), GLenum WXUNUSED(internalformat), GLsizei WXUNUSED(width), GLenum WXUNUSED(format), GLenum WXUNUSED(type), const GLvoid *WXUNUSED(table))
8b089c5e
JS
719{
720}
721
2341cf5f 722void glCopyColorTableEXT(GLenum WXUNUSED(target), GLenum WXUNUSED(internalformat), GLint WXUNUSED(x), GLint WXUNUSED(y), GLsizei WXUNUSED(width))
8b089c5e
JS
723{
724}
725
2341cf5f 726void glGetColorTableEXT(GLenum WXUNUSED(target), GLenum WXUNUSED(format), GLenum WXUNUSED(type), GLvoid *WXUNUSED(table))
8b089c5e
JS
727{
728}
729
2341cf5f 730void glGetColorTableParamaterfvEXT(GLenum WXUNUSED(target), GLenum WXUNUSED(pname), GLfloat *WXUNUSED(params))
8b089c5e
JS
731{
732}
733
2341cf5f 734void glGetColorTavleParameterivEXT(GLenum WXUNUSED(target), GLenum WXUNUSED(pname), GLint *WXUNUSED(params))
8b089c5e
JS
735{
736}
737
738/* SGI_compiled_vertex_array */
2341cf5f 739void glLockArraysSGI(GLint WXUNUSED(first), GLsizei WXUNUSED(count))
8b089c5e
JS
740{
741}
742
743void glUnlockArraysSGI()
744{
745}
746
747
748/* SGI_cull_vertex */
2341cf5f 749void glCullParameterdvSGI(GLenum WXUNUSED(pname), GLdouble* WXUNUSED(params))
8b089c5e
JS
750{
751}
752
2341cf5f 753void glCullParameterfvSGI(GLenum WXUNUSED(pname), GLfloat* WXUNUSED(params))
8b089c5e
JS
754{
755}
756
757/* SGI_index_func */
2341cf5f 758void glIndexFuncSGI(GLenum WXUNUSED(func), GLclampf WXUNUSED(ref))
8b089c5e
JS
759{
760}
761
762/* SGI_index_material */
2341cf5f 763void glIndexMaterialSGI(GLenum WXUNUSED(face), GLenum WXUNUSED(mode))
8b089c5e
JS
764{
765}
766
767/* WIN_swap_hint */
2341cf5f 768void glAddSwapHintRectWin(GLint WXUNUSED(x), GLint WXUNUSED(y), GLsizei WXUNUSED(width), GLsizei WXUNUSED(height))
8b089c5e
JS
769{
770}
771
a3081354
VZ
772
773//---------------------------------------------------------------------------
774// wxGLApp
775//---------------------------------------------------------------------------
776
777IMPLEMENT_CLASS(wxGLApp, wxApp)
778
779bool wxGLApp::InitGLVisual(int *attribList)
780{
781 int pixelFormat;
782 PIXELFORMATDESCRIPTOR pfd = {
b225f659
VZ
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 */
3103e8a9 789 16, /* preferred color depth */
b225f659
VZ
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 };
a3081354
VZ
802
803 AdjustPFDForAttributes(pfd, attribList);
804
805 // use DC for whole (root) screen, since no windows have yet been created
2b8646e0 806 pixelFormat = ChoosePixelFormat(ScreenHDC(), &pfd);
a3081354
VZ
807
808 if (pixelFormat == 0) {
809 wxLogError(_("Failed to initialize OpenGL"));
213ceb3f 810 return false;
a3081354
VZ
811 }
812
213ceb3f 813 return true;
a3081354
VZ
814}
815
816wxGLApp::~wxGLApp()
817{
818}
819
8b089c5e
JS
820#endif
821 // wxUSE_GLCANVAS