]> git.saurik.com Git - wxWidgets.git/blame - src/msw/glcanvas.cpp
Minor header 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
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
b7ea712c 186IMPLEMENT_CLASS(wxGLContext, wxObject)
8b089c5e 187
b7ea712c 188wxGLContext::wxGLContext(wxGLCanvas* win, const wxGLContext* other /* for sharing display lists */)
8b089c5e 189{
b7ea712c 190 m_glContext = wglCreateContext((HDC) win->GetHDC());
87b6002d 191 wxCHECK_RET( m_glContext, wxT("Couldn't create OpenGL context") );
8b089c5e 192
f48d169c
UN
193 if( other != 0 )
194 wglShareLists( other->m_glContext, m_glContext );
8b089c5e
JS
195}
196
197wxGLContext::~wxGLContext()
198{
b7ea712c 199 // If this context happens to be the current context, wglDeleteContext() makes it un-current first.
f48d169c 200 wglDeleteContext(m_glContext);
8b089c5e
JS
201}
202
b7ea712c 203void wxGLContext::SetCurrent(const wxGLCanvas& win) const
8b089c5e 204{
b7ea712c 205 wglMakeCurrent((HDC) win.GetHDC(), m_glContext);
8b089c5e
JS
206}
207
208
209/*
210 * wxGLCanvas implementation
211 */
212
4660d7e5 213IMPLEMENT_CLASS(wxGLCanvas, wxWindow)
8b089c5e 214
4660d7e5 215BEGIN_EVENT_TABLE(wxGLCanvas, wxWindow)
8b089c5e
JS
216 EVT_SIZE(wxGLCanvas::OnSize)
217 EVT_PALETTE_CHANGED(wxGLCanvas::OnPaletteChanged)
218 EVT_QUERY_NEW_PALETTE(wxGLCanvas::OnQueryNewPalette)
219END_EVENT_TABLE()
220
b7ea712c
RR
221wxGLCanvas::wxGLCanvas(wxWindow *parent, wxWindowID id, int *attribList,
222 const wxPoint& pos, const wxSize& size, long style,
223 const wxString& name, const wxPalette& palette) : wxWindow()
224{
225 m_glContext = NULL;
226
227 if (Create(parent, id, pos, size, style, name))
228 {
229 SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_3DFACE));
230 }
231
232 m_hDC = (WXHDC) ::GetDC((HWND) GetHWND());
233
234 SetupPixelFormat(attribList);
235 SetupPalette(palette);
236
237 // This ctor does *not* create an instance of wxGLContext,
238 // m_glContext intentionally remains NULL.
239}
240
8b089c5e
JS
241wxGLCanvas::wxGLCanvas(wxWindow *parent, wxWindowID id,
242 const wxPoint& pos, const wxSize& size, long style, const wxString& name,
4660d7e5 243 int *attribList, const wxPalette& palette) : wxWindow()
8b089c5e 244{
f48d169c 245 m_glContext = (wxGLContext*) NULL;
8b089c5e 246
f48d169c 247 bool ret = Create(parent, id, pos, size, style, name);
8b089c5e 248
f48d169c
UN
249 if ( ret )
250 {
a756f210 251 SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_3DFACE));
f48d169c 252 }
8b089c5e 253
f48d169c 254 m_hDC = (WXHDC) ::GetDC((HWND) GetHWND());
8b089c5e 255
f48d169c
UN
256 SetupPixelFormat(attribList);
257 SetupPalette(palette);
8b089c5e 258
b7ea712c 259 m_glContext = new wxGLContext(this);
8b089c5e
JS
260}
261
262wxGLCanvas::wxGLCanvas( wxWindow *parent,
263 const wxGLContext *shared, wxWindowID id,
264 const wxPoint& pos, const wxSize& size, long style, const wxString& name,
265 int *attribList, const wxPalette& palette )
4660d7e5 266 : wxWindow()
8b089c5e 267{
f48d169c 268 m_glContext = (wxGLContext*) NULL;
8b089c5e 269
f48d169c 270 bool ret = Create(parent, id, pos, size, style, name);
8b089c5e 271
f48d169c
UN
272 if ( ret )
273 {
a756f210 274 SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_3DFACE));
f48d169c 275 }
8b089c5e 276
f48d169c 277 m_hDC = (WXHDC) ::GetDC((HWND) GetHWND());
8b089c5e 278
f48d169c
UN
279 SetupPixelFormat(attribList);
280 SetupPalette(palette);
8b089c5e 281
b7ea712c 282 m_glContext = new wxGLContext(this, shared);
8b089c5e
JS
283}
284
f6bcfd97 285// Not very useful for wxMSW, but this is to be wxGTK compliant
8b089c5e
JS
286
287wxGLCanvas::wxGLCanvas( wxWindow *parent, const wxGLCanvas *shared, wxWindowID id,
288 const wxPoint& pos, const wxSize& size, long style, const wxString& name,
289 int *attribList, const wxPalette& palette ):
4660d7e5 290 wxWindow()
8b089c5e 291{
f48d169c 292 m_glContext = (wxGLContext*) NULL;
8b089c5e 293
f48d169c 294 bool ret = Create(parent, id, pos, size, style, name);
8b089c5e 295
f48d169c
UN
296 if ( ret )
297 {
a756f210 298 SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_3DFACE));
f48d169c 299 }
8b089c5e 300
f48d169c 301 m_hDC = (WXHDC) ::GetDC((HWND) GetHWND());
8b089c5e 302
f48d169c
UN
303 SetupPixelFormat(attribList);
304 SetupPalette(palette);
8b089c5e 305
f48d169c
UN
306 wxGLContext *sharedContext=0;
307 if (shared) sharedContext=shared->GetContext();
b7ea712c 308 m_glContext = new wxGLContext(this, sharedContext);
8b089c5e
JS
309}
310
311wxGLCanvas::~wxGLCanvas()
312{
53fcd32e 313 delete m_glContext;
8b089c5e
JS
314
315 ::ReleaseDC((HWND) GetHWND(), (HDC) m_hDC);
316}
317
b225f659
VZ
318// Replaces wxWindow::Create functionality, since we need to use a different
319// window class
320bool wxGLCanvas::Create(wxWindow *parent,
321 wxWindowID id,
322 const wxPoint& pos,
323 const wxSize& size,
324 long style,
325 const wxString& name)
8b089c5e 326{
53fcd32e 327 wxCHECK_MSG( parent, false, wxT("can't create wxWindow without parent") );
8b089c5e 328
53fcd32e 329 if ( !wxGLModule::RegisterClasses() )
b225f659 330 {
53fcd32e 331 wxLogError(_("Failed to register OpenGL window class."));
b225f659 332
213ceb3f 333 return false;
b225f659
VZ
334 }
335
53fcd32e
VZ
336 if ( !CreateBase(parent, id, pos, size, style, wxDefaultValidator, name) )
337 return false;
f48d169c 338
53fcd32e 339 parent->AddChild(this);
f48d169c 340
53fcd32e 341 DWORD msflags = 0;
f48d169c 342
53fcd32e
VZ
343 /*
344 A general rule with OpenGL and Win32 is that any window that will have a
345 HGLRC built for it must have two flags: WS_CLIPCHILDREN & WS_CLIPSIBLINGS.
346 You can find references about this within the knowledge base and most OpenGL
347 books that contain the wgl function descriptions.
348 */
8b089c5e 349
53fcd32e
VZ
350 WXDWORD exStyle = 0;
351 msflags |= WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN;
352 msflags |= MSWGetStyle(style, & exStyle) ;
f48d169c 353
53fcd32e 354 return MSWCreate(wxGLCanvasClassName, NULL, pos, size, msflags, exStyle);
8b089c5e
JS
355}
356
a3081354 357static void AdjustPFDForAttributes(PIXELFORMATDESCRIPTOR& pfd, int *attribList)
8b089c5e 358{
f48d169c
UN
359 if (attribList) {
360 pfd.dwFlags &= ~PFD_DOUBLEBUFFER;
361 pfd.iPixelType = PFD_TYPE_COLORINDEX;
362 pfd.cColorBits = 0;
363 int arg=0;
b225f659 364
f48d169c
UN
365 while( (attribList[arg]!=0) )
366 {
367 switch( attribList[arg++] )
368 {
369 case WX_GL_RGBA:
370 pfd.iPixelType = PFD_TYPE_RGBA;
371 break;
372 case WX_GL_BUFFER_SIZE:
b8ee9a86 373 pfd.cColorBits = (BYTE)attribList[arg++];
f48d169c
UN
374 break;
375 case WX_GL_LEVEL:
376 // this member looks like it may be obsolete
377 if (attribList[arg] > 0) {
d728116a 378 pfd.iLayerType = (BYTE)PFD_OVERLAY_PLANE;
f48d169c 379 } else if (attribList[arg] < 0) {
d728116a 380 pfd.iLayerType = (BYTE)PFD_UNDERLAY_PLANE;
f48d169c 381 } else {
d728116a 382 pfd.iLayerType = (BYTE)PFD_MAIN_PLANE;
f48d169c
UN
383 }
384 arg++;
385 break;
386 case WX_GL_DOUBLEBUFFER:
387 pfd.dwFlags |= PFD_DOUBLEBUFFER;
388 break;
389 case WX_GL_STEREO:
390 pfd.dwFlags |= PFD_STEREO;
391 break;
392 case WX_GL_AUX_BUFFERS:
b8ee9a86 393 pfd.cAuxBuffers = (BYTE)attribList[arg++];
f48d169c
UN
394 break;
395 case WX_GL_MIN_RED:
b8ee9a86 396 pfd.cColorBits = (BYTE)(pfd.cColorBits + (pfd.cRedBits = (BYTE)attribList[arg++]));
f48d169c
UN
397 break;
398 case WX_GL_MIN_GREEN:
b8ee9a86 399 pfd.cColorBits = (BYTE)(pfd.cColorBits + (pfd.cGreenBits = (BYTE)attribList[arg++]));
f48d169c
UN
400 break;
401 case WX_GL_MIN_BLUE:
b8ee9a86 402 pfd.cColorBits = (BYTE)(pfd.cColorBits + (pfd.cBlueBits = (BYTE)attribList[arg++]));
f48d169c
UN
403 break;
404 case WX_GL_MIN_ALPHA:
405 // doesn't count in cColorBits
b8ee9a86 406 pfd.cAlphaBits = (BYTE)attribList[arg++];
f48d169c 407 break;
b225f659 408 case WX_GL_DEPTH_SIZE:
b8ee9a86 409 pfd.cDepthBits = (BYTE)attribList[arg++];
f48d169c 410 break;
b225f659 411 case WX_GL_STENCIL_SIZE:
b8ee9a86 412 pfd.cStencilBits = (BYTE)attribList[arg++];
f48d169c
UN
413 break;
414 case WX_GL_MIN_ACCUM_RED:
b8ee9a86 415 pfd.cAccumBits = (BYTE)(pfd.cAccumBits + (pfd.cAccumRedBits = (BYTE)attribList[arg++]));
f48d169c
UN
416 break;
417 case WX_GL_MIN_ACCUM_GREEN:
b8ee9a86 418 pfd.cAccumBits = (BYTE)(pfd.cAccumBits + (pfd.cAccumGreenBits = (BYTE)attribList[arg++]));
f48d169c
UN
419 break;
420 case WX_GL_MIN_ACCUM_BLUE:
b8ee9a86 421 pfd.cAccumBits = (BYTE)(pfd.cAccumBits + (pfd.cAccumBlueBits = (BYTE)attribList[arg++]));
f48d169c
UN
422 break;
423 case WX_GL_MIN_ACCUM_ALPHA:
b8ee9a86 424 pfd.cAccumBits = (BYTE)(pfd.cAccumBits + (pfd.cAccumAlphaBits = (BYTE)attribList[arg++]));
f48d169c
UN
425 break;
426 default:
427 break;
428 }
8b089c5e 429 }
f48d169c 430 }
a3081354
VZ
431}
432
433void wxGLCanvas::SetupPixelFormat(int *attribList) // (HDC hDC)
434{
a3081354 435 PIXELFORMATDESCRIPTOR pfd = {
b225f659
VZ
436 sizeof(PIXELFORMATDESCRIPTOR), /* size */
437 1, /* version */
438 PFD_SUPPORT_OPENGL |
439 PFD_DRAW_TO_WINDOW |
440 PFD_DOUBLEBUFFER, /* support double-buffering */
441 PFD_TYPE_RGBA, /* color type */
3103e8a9 442 16, /* preferred color depth */
b225f659
VZ
443 0, 0, 0, 0, 0, 0, /* color bits (ignored) */
444 0, /* no alpha buffer */
445 0, /* alpha bits (ignored) */
446 0, /* no accumulation buffer */
447 0, 0, 0, 0, /* accum bits (ignored) */
448 16, /* depth buffer */
449 0, /* no stencil buffer */
450 0, /* no auxiliary buffers */
451 PFD_MAIN_PLANE, /* main layer */
452 0, /* reserved */
453 0, 0, 0, /* no layer, visible, damage masks */
454 };
a3081354
VZ
455
456 AdjustPFDForAttributes(pfd, attribList);
457
72adfc4b 458 int pixelFormat = ChoosePixelFormat((HDC) m_hDC, &pfd);
f48d169c 459 if (pixelFormat == 0) {
72adfc4b 460 wxLogLastError(_T("ChoosePixelFormat"));
f48d169c 461 }
a3081354 462 else {
72adfc4b
VZ
463 if ( !::SetPixelFormat((HDC) m_hDC, pixelFormat, &pfd) ) {
464 wxLogLastError(_T("SetPixelFormat"));
a3081354 465 }
f48d169c 466 }
8b089c5e
JS
467}
468
469void wxGLCanvas::SetupPalette(const wxPalette& palette)
470{
471 int pixelFormat = GetPixelFormat((HDC) m_hDC);
472 PIXELFORMATDESCRIPTOR pfd;
473
474 DescribePixelFormat((HDC) m_hDC, pixelFormat, sizeof(PIXELFORMATDESCRIPTOR), &pfd);
475
476 if (pfd.dwFlags & PFD_NEED_PALETTE)
477 {
478 }
479 else
480 {
b225f659 481 return;
8b089c5e
JS
482 }
483
484 m_palette = palette;
485
486 if ( !m_palette.Ok() )
487 {
488 m_palette = CreateDefaultPalette();
489 }
490
491 if (m_palette.Ok())
492 {
213ceb3f
WS
493 ::SelectPalette((HDC) m_hDC, (HPALETTE) m_palette.GetHPALETTE(), FALSE);
494 ::RealizePalette((HDC) m_hDC);
8b089c5e
JS
495 }
496}
497
498wxPalette wxGLCanvas::CreateDefaultPalette()
499{
500 PIXELFORMATDESCRIPTOR pfd;
501 int paletteSize;
502 int pixelFormat = GetPixelFormat((HDC) m_hDC);
503
504 DescribePixelFormat((HDC) m_hDC, pixelFormat, sizeof(PIXELFORMATDESCRIPTOR), &pfd);
505
f48d169c 506 paletteSize = 1 << pfd.cColorBits;
8b089c5e
JS
507
508 LOGPALETTE* pPal =
509 (LOGPALETTE*) malloc(sizeof(LOGPALETTE) + paletteSize * sizeof(PALETTEENTRY));
510 pPal->palVersion = 0x300;
b8ee9a86 511 pPal->palNumEntries = (WORD)paletteSize;
8b089c5e
JS
512
513 /* build a simple RGB color palette */
514 {
b225f659
VZ
515 int redMask = (1 << pfd.cRedBits) - 1;
516 int greenMask = (1 << pfd.cGreenBits) - 1;
517 int blueMask = (1 << pfd.cBlueBits) - 1;
518 int i;
519
520 for (i=0; i<paletteSize; ++i) {
521 pPal->palPalEntry[i].peRed =
b8ee9a86 522 (BYTE)((((i >> pfd.cRedShift) & redMask) * 255) / redMask);
b225f659 523 pPal->palPalEntry[i].peGreen =
b8ee9a86 524 (BYTE)((((i >> pfd.cGreenShift) & greenMask) * 255) / greenMask);
b225f659 525 pPal->palPalEntry[i].peBlue =
b8ee9a86 526 (BYTE)((((i >> pfd.cBlueShift) & blueMask) * 255) / blueMask);
b225f659
VZ
527 pPal->palPalEntry[i].peFlags = 0;
528 }
8b089c5e
JS
529 }
530
531 HPALETTE hPalette = CreatePalette(pPal);
532 free(pPal);
533
534 wxPalette palette;
535 palette.SetHPALETTE((WXHPALETTE) hPalette);
536
537 return palette;
538}
539
540void wxGLCanvas::SwapBuffers()
541{
b7ea712c 542 ::SwapBuffers((HDC) m_hDC);
8b089c5e
JS
543}
544
2341cf5f 545void wxGLCanvas::OnSize(wxSizeEvent& WXUNUSED(event))
8b089c5e 546{
8b089c5e
JS
547}
548
b7ea712c
RR
549void wxGLCanvas::SetCurrent(const wxGLContext& RC) const
550{
551 // although on MSW it works even if the window is still hidden, it doesn't
552 // under wxGTK and documentation mentions that SetCurrent() can only be
553 // called for a shown window, so check it
554 wxASSERT_MSG( GetParent()->IsShown(), _T("can't make hidden GL canvas current") );
555
556 RC.SetCurrent(*this);
557}
558
8b089c5e
JS
559void wxGLCanvas::SetCurrent()
560{
2d918775
VZ
561 // although on MSW it works even if the window is still hidden, it doesn't
562 // under wxGTK and documentation mentions that SetCurrent() can only be
563 // called for a shown window, so check it
564 wxASSERT_MSG( GetParent()->IsShown(),
565 _T("can't make hidden GL canvas current") );
566
8b089c5e
JS
567 if (m_glContext)
568 {
b7ea712c 569 m_glContext->SetCurrent(*this);
8b089c5e
JS
570 }
571}
572
2b5f62a0 573void wxGLCanvas::SetColour(const wxChar *colour)
8b089c5e 574{
b7ea712c
RR
575 wxColour col = wxTheColourDatabase->Find(colour);
576
577 if (col.Ok())
578 {
579 float r = (float)(col.Red()/256.0);
580 float g = (float)(col.Green()/256.0);
581 float b = (float)(col.Blue()/256.0);
582 glColor3f( r, g, b);
583 }
8b089c5e
JS
584}
585
586// TODO: Have to have this called by parent frame (?)
587// So we need wxFrame to call OnQueryNewPalette for all children...
588void wxGLCanvas::OnQueryNewPalette(wxQueryNewPaletteEvent& event)
589{
f48d169c
UN
590 /* realize palette if this is the current window */
591 if ( GetPalette()->Ok() ) {
592 ::UnrealizeObject((HPALETTE) GetPalette()->GetHPALETTE());
593 ::SelectPalette((HDC) GetHDC(), (HPALETTE) GetPalette()->GetHPALETTE(), FALSE);
594 ::RealizePalette((HDC) GetHDC());
595 Refresh();
213ceb3f 596 event.SetPaletteRealized(true);
f48d169c
UN
597 }
598 else
213ceb3f 599 event.SetPaletteRealized(false);
8b089c5e
JS
600}
601
602// I think this doesn't have to be propagated to child windows.
603void wxGLCanvas::OnPaletteChanged(wxPaletteChangedEvent& event)
604{
f48d169c
UN
605 /* realize palette if this is *not* the current window */
606 if ( GetPalette() &&
8b089c5e 607 GetPalette()->Ok() && (this != event.GetChangedWindow()) )
f48d169c
UN
608 {
609 ::UnrealizeObject((HPALETTE) GetPalette()->GetHPALETTE());
610 ::SelectPalette((HDC) GetHDC(), (HPALETTE) GetPalette()->GetHPALETTE(), FALSE);
611 ::RealizePalette((HDC) GetHDC());
612 Refresh();
613 }
8b089c5e
JS
614}
615
a3081354
VZ
616
617//---------------------------------------------------------------------------
618// wxGLApp
619//---------------------------------------------------------------------------
620
621IMPLEMENT_CLASS(wxGLApp, wxApp)
622
623bool wxGLApp::InitGLVisual(int *attribList)
624{
625 int pixelFormat;
626 PIXELFORMATDESCRIPTOR pfd = {
b225f659
VZ
627 sizeof(PIXELFORMATDESCRIPTOR), /* size */
628 1, /* version */
629 PFD_SUPPORT_OPENGL |
630 PFD_DRAW_TO_WINDOW |
631 PFD_DOUBLEBUFFER, /* support double-buffering */
632 PFD_TYPE_RGBA, /* color type */
3103e8a9 633 16, /* preferred color depth */
b225f659
VZ
634 0, 0, 0, 0, 0, 0, /* color bits (ignored) */
635 0, /* no alpha buffer */
636 0, /* alpha bits (ignored) */
637 0, /* no accumulation buffer */
638 0, 0, 0, 0, /* accum bits (ignored) */
639 16, /* depth buffer */
640 0, /* no stencil buffer */
641 0, /* no auxiliary buffers */
642 PFD_MAIN_PLANE, /* main layer */
643 0, /* reserved */
644 0, 0, 0, /* no layer, visible, damage masks */
645 };
a3081354
VZ
646
647 AdjustPFDForAttributes(pfd, attribList);
648
649 // use DC for whole (root) screen, since no windows have yet been created
2b8646e0 650 pixelFormat = ChoosePixelFormat(ScreenHDC(), &pfd);
a3081354
VZ
651
652 if (pixelFormat == 0) {
653 wxLogError(_("Failed to initialize OpenGL"));
213ceb3f 654 return false;
a3081354
VZ
655 }
656
213ceb3f 657 return true;
a3081354
VZ
658}
659
660wxGLApp::~wxGLApp()
661{
662}
663
8b089c5e
JS
664#endif
665 // wxUSE_GLCANVAS