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