]> git.saurik.com Git - wxWidgets.git/blame - src/msw/glcanvas.cpp
call Update() from SetStatusText() to ensure that the message is shown to the user...
[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
8b089c5e
JS
12#include "wx/wxprec.h"
13
14#if defined(__BORLANDC__)
15#pragma hdrstop
16#endif
17
8b089c5e
JS
18#if wxUSE_GLCANVAS
19
20#ifndef WX_PRECOMP
af0b1533
VZ
21 #include "wx/frame.h"
22 #include "wx/settings.h"
23 #include "wx/intl.h"
24 #include "wx/log.h"
234d8e90 25 #include "wx/app.h"
8b089c5e
JS
26#endif
27
53fcd32e
VZ
28#include "wx/module.h"
29
af0b1533 30#include "wx/msw/private.h"
8b089c5e 31
34fdf762
VS
32// DLL options compatibility check:
33#include "wx/build.h"
34WX_CHECK_BUILD_OPTIONS("wxGL")
35
af0b1533 36#include "wx/glcanvas.h"
8b089c5e 37
b8ee9a86
WS
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
0e82bd96
VZ
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
77ffb593 53 anywhere else in wxWidgets given it is so specific to not only wxMSW, but
0e82bd96
VZ
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
34fdf762 66
b225f659
VZ
67static const wxChar *wxGLCanvasClassName = wxT("wxGLCanvasClass");
68static const wxChar *wxGLCanvasClassNameNoRedraw = wxT("wxGLCanvasClassNR");
8b089c5e
JS
69
70LRESULT WXDLLEXPORT APIENTRY _EXPORT wxWndProc(HWND hWnd, UINT message,
71 WPARAM wParam, LPARAM lParam);
72
53fcd32e
VZ
73// ----------------------------------------------------------------------------
74// wxGLModule is responsible for unregistering wxGLCanvasClass Windows class
75// ----------------------------------------------------------------------------
76
77class wxGLModule : public wxModule
78{
79public:
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
90private:
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
97IMPLEMENT_DYNAMIC_CLASS(wxGLModule, wxModule)
98
99bool wxGLModule::ms_registeredGLClasses = false;
100
101/* static */
102bool 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 */
169void 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
8b089c5e
JS
183/*
184 * GLContext implementation
185 */
186
2341cf5f 187wxGLContext::wxGLContext(bool WXUNUSED(isRGB), wxGLCanvas *win, const wxPalette& WXUNUSED(palette))
8b089c5e
JS
188{
189 m_window = win;
190
191 m_hDC = win->GetHDC();
192
193 m_glContext = wglCreateContext((HDC) m_hDC);
87b6002d 194 wxCHECK_RET( m_glContext, wxT("Couldn't create OpenGL context") );
8b089c5e
JS
195
196 wglMakeCurrent((HDC) m_hDC, m_glContext);
197}
198
199wxGLContext::wxGLContext(
2341cf5f
MB
200 bool WXUNUSED(isRGB), wxGLCanvas *win,
201 const wxPalette& WXUNUSED(palette),
f48d169c
UN
202 const wxGLContext *other /* for sharing display lists */
203 )
8b089c5e 204{
f48d169c 205 m_window = win;
8b089c5e 206
f48d169c 207 m_hDC = win->GetHDC();
8b089c5e 208
f48d169c 209 m_glContext = wglCreateContext((HDC) m_hDC);
87b6002d 210 wxCHECK_RET( m_glContext, wxT("Couldn't create OpenGL context") );
8b089c5e 211
f48d169c
UN
212 if( other != 0 )
213 wglShareLists( other->m_glContext, m_glContext );
8b089c5e 214
f48d169c 215 wglMakeCurrent((HDC) m_hDC, m_glContext);
8b089c5e
JS
216}
217
218wxGLContext::~wxGLContext()
219{
220 if (m_glContext)
221 {
222 wglMakeCurrent(NULL, NULL);
f48d169c 223 wglDeleteContext(m_glContext);
8b089c5e
JS
224 }
225}
226
227void 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
236void wxGLContext::SetCurrent()
237{
238 if (m_glContext)
239 {
240 wglMakeCurrent((HDC) m_hDC, m_glContext);
241 }
8b089c5e
JS
242}
243
2b5f62a0 244void wxGLContext::SetColour(const wxChar *colour)
8b089c5e 245{
564a150b
VZ
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 }
8b089c5e
JS
254}
255
256
257/*
258 * wxGLCanvas implementation
259 */
260
4660d7e5 261IMPLEMENT_CLASS(wxGLCanvas, wxWindow)
8b089c5e 262
4660d7e5 263BEGIN_EVENT_TABLE(wxGLCanvas, wxWindow)
8b089c5e
JS
264 EVT_SIZE(wxGLCanvas::OnSize)
265 EVT_PALETTE_CHANGED(wxGLCanvas::OnPaletteChanged)
266 EVT_QUERY_NEW_PALETTE(wxGLCanvas::OnQueryNewPalette)
267END_EVENT_TABLE()
268
269wxGLCanvas::wxGLCanvas(wxWindow *parent, wxWindowID id,
270 const wxPoint& pos, const wxSize& size, long style, const wxString& name,
4660d7e5 271 int *attribList, const wxPalette& palette) : wxWindow()
8b089c5e 272{
f48d169c 273 m_glContext = (wxGLContext*) NULL;
8b089c5e 274
f48d169c 275 bool ret = Create(parent, id, pos, size, style, name);
8b089c5e 276
f48d169c
UN
277 if ( ret )
278 {
a756f210 279 SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_3DFACE));
f48d169c 280 }
8b089c5e 281
f48d169c 282 m_hDC = (WXHDC) ::GetDC((HWND) GetHWND());
8b089c5e 283
f48d169c
UN
284 SetupPixelFormat(attribList);
285 SetupPalette(palette);
8b089c5e 286
213ceb3f 287 m_glContext = new wxGLContext(true, this, palette);
8b089c5e
JS
288}
289
290wxGLCanvas::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 )
4660d7e5 294 : wxWindow()
8b089c5e 295{
f48d169c 296 m_glContext = (wxGLContext*) NULL;
8b089c5e 297
f48d169c 298 bool ret = Create(parent, id, pos, size, style, name);
8b089c5e 299
f48d169c
UN
300 if ( ret )
301 {
a756f210 302 SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_3DFACE));
f48d169c 303 }
8b089c5e 304
f48d169c 305 m_hDC = (WXHDC) ::GetDC((HWND) GetHWND());
8b089c5e 306
f48d169c
UN
307 SetupPixelFormat(attribList);
308 SetupPalette(palette);
8b089c5e 309
213ceb3f 310 m_glContext = new wxGLContext(true, this, palette, shared );
8b089c5e
JS
311}
312
f6bcfd97 313// Not very useful for wxMSW, but this is to be wxGTK compliant
8b089c5e
JS
314
315wxGLCanvas::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 ):
4660d7e5 318 wxWindow()
8b089c5e 319{
f48d169c 320 m_glContext = (wxGLContext*) NULL;
8b089c5e 321
f48d169c 322 bool ret = Create(parent, id, pos, size, style, name);
8b089c5e 323
f48d169c
UN
324 if ( ret )
325 {
a756f210 326 SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_3DFACE));
f48d169c 327 }
8b089c5e 328
f48d169c 329 m_hDC = (WXHDC) ::GetDC((HWND) GetHWND());
8b089c5e 330
f48d169c
UN
331 SetupPixelFormat(attribList);
332 SetupPalette(palette);
8b089c5e 333
f48d169c
UN
334 wxGLContext *sharedContext=0;
335 if (shared) sharedContext=shared->GetContext();
213ceb3f 336 m_glContext = new wxGLContext(true, this, palette, sharedContext );
8b089c5e
JS
337}
338
339wxGLCanvas::~wxGLCanvas()
340{
53fcd32e 341 delete m_glContext;
8b089c5e
JS
342
343 ::ReleaseDC((HWND) GetHWND(), (HDC) m_hDC);
344}
345
b225f659
VZ
346// Replaces wxWindow::Create functionality, since we need to use a different
347// window class
348bool wxGLCanvas::Create(wxWindow *parent,
349 wxWindowID id,
350 const wxPoint& pos,
351 const wxSize& size,
352 long style,
353 const wxString& name)
8b089c5e 354{
53fcd32e 355 wxCHECK_MSG( parent, false, wxT("can't create wxWindow without parent") );
8b089c5e 356
53fcd32e 357 if ( !wxGLModule::RegisterClasses() )
b225f659 358 {
53fcd32e 359 wxLogError(_("Failed to register OpenGL window class."));
b225f659 360
213ceb3f 361 return false;
b225f659
VZ
362 }
363
53fcd32e
VZ
364 if ( !CreateBase(parent, id, pos, size, style, wxDefaultValidator, name) )
365 return false;
f48d169c 366
53fcd32e 367 parent->AddChild(this);
f48d169c 368
53fcd32e 369 DWORD msflags = 0;
f48d169c 370
53fcd32e
VZ
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 */
8b089c5e 377
53fcd32e
VZ
378 WXDWORD exStyle = 0;
379 msflags |= WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN;
380 msflags |= MSWGetStyle(style, & exStyle) ;
f48d169c 381
53fcd32e 382 return MSWCreate(wxGLCanvasClassName, NULL, pos, size, msflags, exStyle);
8b089c5e
JS
383}
384
a3081354 385static void AdjustPFDForAttributes(PIXELFORMATDESCRIPTOR& pfd, int *attribList)
8b089c5e 386{
f48d169c
UN
387 if (attribList) {
388 pfd.dwFlags &= ~PFD_DOUBLEBUFFER;
389 pfd.iPixelType = PFD_TYPE_COLORINDEX;
390 pfd.cColorBits = 0;
391 int arg=0;
b225f659 392
f48d169c
UN
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:
b8ee9a86 401 pfd.cColorBits = (BYTE)attribList[arg++];
f48d169c
UN
402 break;
403 case WX_GL_LEVEL:
404 // this member looks like it may be obsolete
405 if (attribList[arg] > 0) {
d728116a 406 pfd.iLayerType = (BYTE)PFD_OVERLAY_PLANE;
f48d169c 407 } else if (attribList[arg] < 0) {
d728116a 408 pfd.iLayerType = (BYTE)PFD_UNDERLAY_PLANE;
f48d169c 409 } else {
d728116a 410 pfd.iLayerType = (BYTE)PFD_MAIN_PLANE;
f48d169c
UN
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:
b8ee9a86 421 pfd.cAuxBuffers = (BYTE)attribList[arg++];
f48d169c
UN
422 break;
423 case WX_GL_MIN_RED:
b8ee9a86 424 pfd.cColorBits = (BYTE)(pfd.cColorBits + (pfd.cRedBits = (BYTE)attribList[arg++]));
f48d169c
UN
425 break;
426 case WX_GL_MIN_GREEN:
b8ee9a86 427 pfd.cColorBits = (BYTE)(pfd.cColorBits + (pfd.cGreenBits = (BYTE)attribList[arg++]));
f48d169c
UN
428 break;
429 case WX_GL_MIN_BLUE:
b8ee9a86 430 pfd.cColorBits = (BYTE)(pfd.cColorBits + (pfd.cBlueBits = (BYTE)attribList[arg++]));
f48d169c
UN
431 break;
432 case WX_GL_MIN_ALPHA:
433 // doesn't count in cColorBits
b8ee9a86 434 pfd.cAlphaBits = (BYTE)attribList[arg++];
f48d169c 435 break;
b225f659 436 case WX_GL_DEPTH_SIZE:
b8ee9a86 437 pfd.cDepthBits = (BYTE)attribList[arg++];
f48d169c 438 break;
b225f659 439 case WX_GL_STENCIL_SIZE:
b8ee9a86 440 pfd.cStencilBits = (BYTE)attribList[arg++];
f48d169c
UN
441 break;
442 case WX_GL_MIN_ACCUM_RED:
b8ee9a86 443 pfd.cAccumBits = (BYTE)(pfd.cAccumBits + (pfd.cAccumRedBits = (BYTE)attribList[arg++]));
f48d169c
UN
444 break;
445 case WX_GL_MIN_ACCUM_GREEN:
b8ee9a86 446 pfd.cAccumBits = (BYTE)(pfd.cAccumBits + (pfd.cAccumGreenBits = (BYTE)attribList[arg++]));
f48d169c
UN
447 break;
448 case WX_GL_MIN_ACCUM_BLUE:
b8ee9a86 449 pfd.cAccumBits = (BYTE)(pfd.cAccumBits + (pfd.cAccumBlueBits = (BYTE)attribList[arg++]));
f48d169c
UN
450 break;
451 case WX_GL_MIN_ACCUM_ALPHA:
b8ee9a86 452 pfd.cAccumBits = (BYTE)(pfd.cAccumBits + (pfd.cAccumAlphaBits = (BYTE)attribList[arg++]));
f48d169c
UN
453 break;
454 default:
455 break;
456 }
8b089c5e 457 }
f48d169c 458 }
a3081354
VZ
459}
460
461void wxGLCanvas::SetupPixelFormat(int *attribList) // (HDC hDC)
462{
a3081354 463 PIXELFORMATDESCRIPTOR pfd = {
b225f659
VZ
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 */
3103e8a9 470 16, /* preferred color depth */
b225f659
VZ
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 };
a3081354
VZ
483
484 AdjustPFDForAttributes(pfd, attribList);
485
72adfc4b 486 int pixelFormat = ChoosePixelFormat((HDC) m_hDC, &pfd);
f48d169c 487 if (pixelFormat == 0) {
72adfc4b 488 wxLogLastError(_T("ChoosePixelFormat"));
f48d169c 489 }
a3081354 490 else {
72adfc4b
VZ
491 if ( !::SetPixelFormat((HDC) m_hDC, pixelFormat, &pfd) ) {
492 wxLogLastError(_T("SetPixelFormat"));
a3081354 493 }
f48d169c 494 }
8b089c5e
JS
495}
496
497void 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 {
b225f659 509 return;
8b089c5e
JS
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 {
213ceb3f
WS
521 ::SelectPalette((HDC) m_hDC, (HPALETTE) m_palette.GetHPALETTE(), FALSE);
522 ::RealizePalette((HDC) m_hDC);
8b089c5e
JS
523 }
524}
525
526wxPalette 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
f48d169c 534 paletteSize = 1 << pfd.cColorBits;
8b089c5e
JS
535
536 LOGPALETTE* pPal =
537 (LOGPALETTE*) malloc(sizeof(LOGPALETTE) + paletteSize * sizeof(PALETTEENTRY));
538 pPal->palVersion = 0x300;
b8ee9a86 539 pPal->palNumEntries = (WORD)paletteSize;
8b089c5e
JS
540
541 /* build a simple RGB color palette */
542 {
b225f659
VZ
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 =
b8ee9a86 550 (BYTE)((((i >> pfd.cRedShift) & redMask) * 255) / redMask);
b225f659 551 pPal->palPalEntry[i].peGreen =
b8ee9a86 552 (BYTE)((((i >> pfd.cGreenShift) & greenMask) * 255) / greenMask);
b225f659 553 pPal->palPalEntry[i].peBlue =
b8ee9a86 554 (BYTE)((((i >> pfd.cBlueShift) & blueMask) * 255) / blueMask);
b225f659
VZ
555 pPal->palPalEntry[i].peFlags = 0;
556 }
8b089c5e
JS
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
568void wxGLCanvas::SwapBuffers()
569{
570 if (m_glContext)
571 m_glContext->SwapBuffers();
572}
573
2341cf5f 574void wxGLCanvas::OnSize(wxSizeEvent& WXUNUSED(event))
8b089c5e 575{
8b089c5e
JS
576}
577
578void wxGLCanvas::SetCurrent()
579{
2d918775
VZ
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
8b089c5e
JS
586 if (m_glContext)
587 {
588 m_glContext->SetCurrent();
589 }
590}
591
2b5f62a0 592void wxGLCanvas::SetColour(const wxChar *colour)
8b089c5e
JS
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...
600void wxGLCanvas::OnQueryNewPalette(wxQueryNewPaletteEvent& event)
601{
f48d169c
UN
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();
213ceb3f 608 event.SetPaletteRealized(true);
f48d169c
UN
609 }
610 else
213ceb3f 611 event.SetPaletteRealized(false);
8b089c5e
JS
612}
613
614// I think this doesn't have to be propagated to child windows.
615void wxGLCanvas::OnPaletteChanged(wxPaletteChangedEvent& event)
616{
f48d169c
UN
617 /* realize palette if this is *not* the current window */
618 if ( GetPalette() &&
8b089c5e 619 GetPalette()->Ok() && (this != event.GetChangedWindow()) )
f48d169c
UN
620 {
621 ::UnrealizeObject((HPALETTE) GetPalette()->GetHPALETTE());
622 ::SelectPalette((HDC) GetHDC(), (HPALETTE) GetPalette()->GetHPALETTE(), FALSE);
623 ::RealizePalette((HDC) GetHDC());
624 Refresh();
625 }
8b089c5e
JS
626}
627
628/* Give extensions proper function names. */
629
630/* EXT_vertex_array */
2341cf5f 631void glArrayElementEXT(GLint WXUNUSED(i))
8b089c5e
JS
632{
633}
634
2341cf5f 635void glColorPointerEXT(GLint WXUNUSED(size), GLenum WXUNUSED(type), GLsizei WXUNUSED(stride), GLsizei WXUNUSED(count), const GLvoid *WXUNUSED(pointer))
8b089c5e
JS
636{
637}
638
b8ee9a86
WS
639void 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))
8b089c5e
JS
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
2341cf5f 656void glEdgeFlagPointerEXT(GLsizei WXUNUSED(stride), GLsizei WXUNUSED(count), const GLboolean *WXUNUSED(pointer))
8b089c5e
JS
657{
658}
659
2341cf5f 660void glGetPointervEXT(GLenum WXUNUSED(pname), GLvoid* *WXUNUSED(params))
8b089c5e
JS
661{
662}
663
2341cf5f 664void glIndexPointerEXT(GLenum WXUNUSED(type), GLsizei WXUNUSED(stride), GLsizei WXUNUSED(count), const GLvoid *WXUNUSED(pointer))
8b089c5e
JS
665{
666}
667
b8ee9a86
WS
668void 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))
8b089c5e
JS
672{
673#ifdef GL_EXT_vertex_array
f48d169c 674 static PFNGLNORMALPOINTEREXTPROC proc = 0;
8b089c5e 675
f48d169c
UN
676 if ( !proc )
677 {
678 proc = (PFNGLNORMALPOINTEREXTPROC) wglGetProcAddress("glNormalPointerEXT");
679 }
8b089c5e 680
f48d169c
UN
681 if ( proc )
682 (* proc) (type, stride, count, pointer);
8b089c5e
JS
683#endif
684}
685
2341cf5f 686void glTexCoordPointerEXT(GLint WXUNUSED(size), GLenum WXUNUSED(type), GLsizei WXUNUSED(stride), GLsizei WXUNUSED(count), const GLvoid *WXUNUSED(pointer))
8b089c5e
JS
687{
688}
689
b8ee9a86
WS
690void 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))
8b089c5e
JS
695{
696#ifdef GL_EXT_vertex_array
f48d169c 697 static PFNGLVERTEXPOINTEREXTPROC proc = 0;
8b089c5e 698
f48d169c
UN
699 if ( !proc )
700 {
701 proc = (PFNGLVERTEXPOINTEREXTPROC) wglGetProcAddress("glVertexPointerEXT");
702 }
703 if ( proc )
704 (* proc) (size, type, stride, count, pointer);
8b089c5e
JS
705#endif
706}
707
708/* EXT_color_subtable */
2341cf5f 709void glColorSubtableEXT(GLenum WXUNUSED(target), GLsizei WXUNUSED(start), GLsizei WXUNUSED(count), GLenum WXUNUSED(format), GLenum WXUNUSED(type), const GLvoid *WXUNUSED(table))
8b089c5e
JS
710{
711}
712
713/* EXT_color_table */
2341cf5f 714void glColorTableEXT(GLenum WXUNUSED(target), GLenum WXUNUSED(internalformat), GLsizei WXUNUSED(width), GLenum WXUNUSED(format), GLenum WXUNUSED(type), const GLvoid *WXUNUSED(table))
8b089c5e
JS
715{
716}
717
2341cf5f 718void glCopyColorTableEXT(GLenum WXUNUSED(target), GLenum WXUNUSED(internalformat), GLint WXUNUSED(x), GLint WXUNUSED(y), GLsizei WXUNUSED(width))
8b089c5e
JS
719{
720}
721
2341cf5f 722void glGetColorTableEXT(GLenum WXUNUSED(target), GLenum WXUNUSED(format), GLenum WXUNUSED(type), GLvoid *WXUNUSED(table))
8b089c5e
JS
723{
724}
725
2341cf5f 726void glGetColorTableParamaterfvEXT(GLenum WXUNUSED(target), GLenum WXUNUSED(pname), GLfloat *WXUNUSED(params))
8b089c5e
JS
727{
728}
729
2341cf5f 730void glGetColorTavleParameterivEXT(GLenum WXUNUSED(target), GLenum WXUNUSED(pname), GLint *WXUNUSED(params))
8b089c5e
JS
731{
732}
733
734/* SGI_compiled_vertex_array */
2341cf5f 735void glLockArraysSGI(GLint WXUNUSED(first), GLsizei WXUNUSED(count))
8b089c5e
JS
736{
737}
738
739void glUnlockArraysSGI()
740{
741}
742
743
744/* SGI_cull_vertex */
2341cf5f 745void glCullParameterdvSGI(GLenum WXUNUSED(pname), GLdouble* WXUNUSED(params))
8b089c5e
JS
746{
747}
748
2341cf5f 749void glCullParameterfvSGI(GLenum WXUNUSED(pname), GLfloat* WXUNUSED(params))
8b089c5e
JS
750{
751}
752
753/* SGI_index_func */
2341cf5f 754void glIndexFuncSGI(GLenum WXUNUSED(func), GLclampf WXUNUSED(ref))
8b089c5e
JS
755{
756}
757
758/* SGI_index_material */
2341cf5f 759void glIndexMaterialSGI(GLenum WXUNUSED(face), GLenum WXUNUSED(mode))
8b089c5e
JS
760{
761}
762
763/* WIN_swap_hint */
2341cf5f 764void glAddSwapHintRectWin(GLint WXUNUSED(x), GLint WXUNUSED(y), GLsizei WXUNUSED(width), GLsizei WXUNUSED(height))
8b089c5e
JS
765{
766}
767
a3081354
VZ
768
769//---------------------------------------------------------------------------
770// wxGLApp
771//---------------------------------------------------------------------------
772
773IMPLEMENT_CLASS(wxGLApp, wxApp)
774
775bool wxGLApp::InitGLVisual(int *attribList)
776{
777 int pixelFormat;
778 PIXELFORMATDESCRIPTOR pfd = {
b225f659
VZ
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 */
3103e8a9 785 16, /* preferred color depth */
b225f659
VZ
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 };
a3081354
VZ
798
799 AdjustPFDForAttributes(pfd, attribList);
800
801 // use DC for whole (root) screen, since no windows have yet been created
2b8646e0 802 pixelFormat = ChoosePixelFormat(ScreenHDC(), &pfd);
a3081354
VZ
803
804 if (pixelFormat == 0) {
805 wxLogError(_("Failed to initialize OpenGL"));
213ceb3f 806 return false;
a3081354
VZ
807 }
808
213ceb3f 809 return true;
a3081354
VZ
810}
811
812wxGLApp::~wxGLApp()
813{
814}
815
8b089c5e
JS
816#endif
817 // wxUSE_GLCANVAS