]> git.saurik.com Git - wxWidgets.git/blame - src/msw/glcanvas.cpp
*wprintf() functions should be extern, not static, when we define them in wxNEED_WPRI...
[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
dc3065a5
VZ
12// ============================================================================
13// declarations
14// ============================================================================
15
16// ----------------------------------------------------------------------------
17// headers
18// ----------------------------------------------------------------------------
19
8b089c5e
JS
20#include "wx/wxprec.h"
21
22#if defined(__BORLANDC__)
02761f6c 23 #pragma hdrstop
8b089c5e
JS
24#endif
25
8b089c5e
JS
26#if wxUSE_GLCANVAS
27
28#ifndef WX_PRECOMP
af0b1533
VZ
29 #include "wx/intl.h"
30 #include "wx/log.h"
234d8e90 31 #include "wx/app.h"
02761f6c 32 #include "wx/module.h"
8b089c5e
JS
33#endif
34
af0b1533 35#include "wx/msw/private.h"
8b089c5e 36
af0b1533 37#include "wx/glcanvas.h"
8b089c5e 38
dc3065a5
VZ
39// from src/msw/window.cpp
40LRESULT WXDLLEXPORT APIENTRY _EXPORT wxWndProc(HWND hWnd, UINT message,
41 WPARAM wParam, LPARAM lParam);
42
43#ifdef GL_EXT_vertex_array
b8ee9a86
WS
44 #define WXUNUSED_WITHOUT_GL_EXT_vertex_array(name) name
45#else
46 #define WXUNUSED_WITHOUT_GL_EXT_vertex_array(name) WXUNUSED(name)
47#endif
48
dc3065a5
VZ
49// ----------------------------------------------------------------------------
50// libraries
51// ----------------------------------------------------------------------------
52
0e82bd96
VZ
53/*
54 The following two compiler directives are specific to the Microsoft Visual
55 C++ family of compilers
56
57 Fundementally what they do is instruct the linker to use these two libraries
58 for the resolution of symbols. In essence, this is the equivalent of adding
59 these two libraries to either the Makefile or project file.
60
61 This is NOT a recommended technique, and certainly is unlikely to be used
77ffb593 62 anywhere else in wxWidgets given it is so specific to not only wxMSW, but
0e82bd96
VZ
63 also the VC compiler. However, in the case of opengl support, it's an
64 applicable technique as opengl is optional in setup.h This code (wrapped by
65 wxUSE_GLCANVAS), now allows opengl support to be added purely by modifying
66 setup.h rather than by having to modify either the project or DSP fle.
67
68 See MSDN for further information on the exact usage of these commands.
69*/
70#ifdef _MSC_VER
71# pragma comment( lib, "opengl32" )
72# pragma comment( lib, "glu32" )
73#endif
74
dc3065a5
VZ
75// ----------------------------------------------------------------------------
76// constants
77// ----------------------------------------------------------------------------
34fdf762 78
b225f659
VZ
79static const wxChar *wxGLCanvasClassName = wxT("wxGLCanvasClass");
80static const wxChar *wxGLCanvasClassNameNoRedraw = wxT("wxGLCanvasClassNR");
8b089c5e 81
dc3065a5
VZ
82// ============================================================================
83// implementation
84// ============================================================================
8b089c5e 85
53fcd32e
VZ
86// ----------------------------------------------------------------------------
87// wxGLModule is responsible for unregistering wxGLCanvasClass Windows class
88// ----------------------------------------------------------------------------
89
90class wxGLModule : public wxModule
91{
92public:
93 bool OnInit() { return true; }
94 void OnExit() { UnregisterClasses(); }
95
96 // register the GL classes if not done yet, return true if ok, false if
97 // registration failed
98 static bool RegisterClasses();
99
100 // unregister the classes, done automatically on program termination
101 static void UnregisterClasses();
102
103private:
104 // wxGLCanvas is only used from the main thread so this is MT-ok
105 static bool ms_registeredGLClasses;
106
107 DECLARE_DYNAMIC_CLASS(wxGLModule)
108};
109
110IMPLEMENT_DYNAMIC_CLASS(wxGLModule, wxModule)
111
112bool wxGLModule::ms_registeredGLClasses = false;
113
114/* static */
115bool wxGLModule::RegisterClasses()
116{
dc3065a5 117 if ( ms_registeredGLClasses )
53fcd32e
VZ
118 return true;
119
120 // We have to register a special window class because we need the CS_OWNDC
dc3065a5
VZ
121 // style for GLCanvas: some OpenGL drivers are buggy and don't work with
122 // windows without this style
53fcd32e
VZ
123 WNDCLASS wndclass;
124
125 // the fields which are common to all classes
126 wndclass.lpfnWndProc = (WNDPROC)wxWndProc;
127 wndclass.cbClsExtra = 0;
128 wndclass.cbWndExtra = sizeof( DWORD ); // VZ: what is this DWORD used for?
129 wndclass.hInstance = wxhInstance;
130 wndclass.hIcon = (HICON) NULL;
131 wndclass.hCursor = ::LoadCursor((HINSTANCE)NULL, IDC_ARROW);
132 wndclass.lpszMenuName = NULL;
133
134 // Register the GLCanvas class name
135 wndclass.hbrBackground = (HBRUSH)NULL;
136 wndclass.lpszClassName = wxGLCanvasClassName;
137 wndclass.style = CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS | CS_OWNDC;
138
139 if ( !::RegisterClass(&wndclass) )
140 {
141 wxLogLastError(wxT("RegisterClass(wxGLCanvasClass)"));
142 return false;
143 }
144
145 // Register the GLCanvas class name for windows which don't do full repaint
146 // on resize
147 wndclass.lpszClassName = wxGLCanvasClassNameNoRedraw;
148 wndclass.style &= ~(CS_HREDRAW | CS_VREDRAW);
149
150 if ( !::RegisterClass(&wndclass) )
151 {
152 wxLogLastError(wxT("RegisterClass(wxGLCanvasClassNameNoRedraw)"));
153
154 ::UnregisterClass(wxGLCanvasClassName, wxhInstance);
155
156 return false;
157 }
158
159 ms_registeredGLClasses = true;
160
161 return true;
162}
163
164/* static */
165void wxGLModule::UnregisterClasses()
166{
167 // we need to unregister the classes in case we're in a DLL which is
168 // unloaded and then loaded again because if we don't, the registration is
169 // going to fail in wxGLCanvas::Create() the next time we're loaded
170 if ( ms_registeredGLClasses )
171 {
172 ::UnregisterClass(wxGLCanvasClassName, wxhInstance);
173 ::UnregisterClass(wxGLCanvasClassNameNoRedraw, wxhInstance);
174
175 ms_registeredGLClasses = false;
176 }
177}
178
dc3065a5
VZ
179// ----------------------------------------------------------------------------
180// wxGLContext
181// ----------------------------------------------------------------------------
8b089c5e 182
b7ea712c 183IMPLEMENT_CLASS(wxGLContext, wxObject)
8b089c5e 184
dc3065a5 185wxGLContext::wxGLContext(wxGLCanvas *win, const wxGLContext* other)
8b089c5e 186{
dc3065a5
VZ
187 m_glContext = wglCreateContext(win->GetHDC());
188 wxCHECK_RET( m_glContext, wxT("Couldn't create OpenGL context") );
8b089c5e 189
dc3065a5
VZ
190 if ( other )
191 {
192 if ( !wglShareLists(other->m_glContext, m_glContext) )
193 wxLogLastError(_T("wglShareLists"));
194 }
8b089c5e
JS
195}
196
197wxGLContext::~wxGLContext()
198{
dc3065a5 199 // note that it's ok to delete the context even if it's the current one
f48d169c 200 wglDeleteContext(m_glContext);
8b089c5e
JS
201}
202
b7ea712c 203void wxGLContext::SetCurrent(const wxGLCanvas& win) const
8b089c5e 204{
dc3065a5
VZ
205 if ( !wglMakeCurrent(win.GetHDC(), m_glContext) )
206 {
207 wxLogLastError(_T("wglMakeCurrent"));
208 }
8b089c5e
JS
209}
210
dc3065a5
VZ
211// ============================================================================
212// wxGLCanvas
213// ============================================================================
8b089c5e 214
4660d7e5 215IMPLEMENT_CLASS(wxGLCanvas, wxWindow)
8b089c5e 216
4660d7e5 217BEGIN_EVENT_TABLE(wxGLCanvas, wxWindow)
8b089c5e
JS
218 EVT_PALETTE_CHANGED(wxGLCanvas::OnPaletteChanged)
219 EVT_QUERY_NEW_PALETTE(wxGLCanvas::OnQueryNewPalette)
220END_EVENT_TABLE()
221
dc3065a5
VZ
222// ----------------------------------------------------------------------------
223// wxGLCanvas construction
224// ----------------------------------------------------------------------------
8b089c5e 225
dc3065a5 226void wxGLCanvas::Init()
8b089c5e 227{
dc3065a5
VZ
228#if WXWIN_COMPATIBILITY_2_8
229 m_glContext = NULL;
230#endif
231 m_hDC = NULL;
8b089c5e
JS
232}
233
dc3065a5
VZ
234wxGLCanvas::wxGLCanvas(wxWindow *parent,
235 wxWindowID id,
236 const int *attribList,
237 const wxPoint& pos,
238 const wxSize& size,
239 long style,
240 const wxString& name,
241 const wxPalette& palette)
8b089c5e 242{
dc3065a5 243 Init();
8b089c5e 244
dc3065a5 245 (void)Create(parent, id, pos, size, style, name, attribList, palette);
8b089c5e
JS
246}
247
248wxGLCanvas::~wxGLCanvas()
249{
dc3065a5
VZ
250#if WXWIN_COMPATIBILITY_2_8
251 delete m_glContext;
252#endif
8b089c5e 253
dc3065a5 254 ::ReleaseDC(GetHwnd(), m_hDC);
8b089c5e
JS
255}
256
b225f659
VZ
257// Replaces wxWindow::Create functionality, since we need to use a different
258// window class
259bool wxGLCanvas::Create(wxWindow *parent,
260 wxWindowID id,
261 const wxPoint& pos,
262 const wxSize& size,
263 long style,
dc3065a5
VZ
264 const wxString& name,
265 const int *attribList,
266 const wxPalette& palette)
8b089c5e 267{
53fcd32e 268 wxCHECK_MSG( parent, false, wxT("can't create wxWindow without parent") );
8b089c5e 269
53fcd32e 270 if ( !wxGLModule::RegisterClasses() )
b225f659 271 {
53fcd32e 272 wxLogError(_("Failed to register OpenGL window class."));
b225f659 273
213ceb3f 274 return false;
b225f659
VZ
275 }
276
53fcd32e
VZ
277 if ( !CreateBase(parent, id, pos, size, style, wxDefaultValidator, name) )
278 return false;
f48d169c 279
53fcd32e 280 parent->AddChild(this);
f48d169c 281
53fcd32e
VZ
282 /*
283 A general rule with OpenGL and Win32 is that any window that will have a
284 HGLRC built for it must have two flags: WS_CLIPCHILDREN & WS_CLIPSIBLINGS.
285 You can find references about this within the knowledge base and most OpenGL
286 books that contain the wgl function descriptions.
287 */
53fcd32e 288 WXDWORD exStyle = 0;
dc3065a5
VZ
289 DWORD msflags = WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN;
290 msflags |= MSWGetStyle(style, &exStyle);
291
292 if ( !MSWCreate(wxGLCanvasClassName, NULL, pos, size, msflags, exStyle) )
293 return false;
f48d169c 294
dc3065a5
VZ
295 m_hDC = ::GetDC(GetHwnd());
296 if ( !m_hDC )
297 return false;
298
299 if ( !DoSetup(attribList) )
300 return false;
301
302#if wxUSE_PALETTE
303 if ( !SetupPalette(palette) )
304 return false;
305#else // !wxUSE_PALETTE
306 wxUnusedVar(palette);
307#endif // wxUSE_PALETTE/!wxUSE_PALETTE
308
309 return true;
310}
311
312// ----------------------------------------------------------------------------
313// operations
314// ----------------------------------------------------------------------------
315
316void wxGLCanvas::SwapBuffers()
317{
318 if ( !::SwapBuffers(m_hDC) )
319 wxLogLastError(_T("SwapBuffers"));
8b089c5e
JS
320}
321
dc3065a5
VZ
322// ----------------------------------------------------------------------------
323// pixel format stuff
324// ----------------------------------------------------------------------------
325
326static void
327AdjustPFDForAttributes(PIXELFORMATDESCRIPTOR& pfd, const int *attribList)
8b089c5e 328{
dc3065a5
VZ
329 if ( !attribList )
330 return;
331
f48d169c
UN
332 pfd.dwFlags &= ~PFD_DOUBLEBUFFER;
333 pfd.iPixelType = PFD_TYPE_COLORINDEX;
334 pfd.cColorBits = 0;
335 int arg=0;
b225f659 336
dc3065a5 337 while ( attribList[arg] )
f48d169c 338 {
dc3065a5
VZ
339 switch ( attribList[arg++] )
340 {
341 case WX_GL_RGBA:
342 pfd.iPixelType = PFD_TYPE_RGBA;
343 break;
344 case WX_GL_BUFFER_SIZE:
345 pfd.cColorBits = attribList[arg++];
346 break;
347 case WX_GL_LEVEL:
348 // this member looks like it may be obsolete
349 if ( attribList[arg] > 0 )
350 pfd.iLayerType = PFD_OVERLAY_PLANE;
351 else if ( attribList[arg] < 0 )
352 pfd.iLayerType = (BYTE)PFD_UNDERLAY_PLANE;
353 else
354 pfd.iLayerType = PFD_MAIN_PLANE;
355 arg++;
356 break;
357 case WX_GL_DOUBLEBUFFER:
358 pfd.dwFlags |= PFD_DOUBLEBUFFER;
359 break;
360 case WX_GL_STEREO:
361 pfd.dwFlags |= PFD_STEREO;
362 break;
363 case WX_GL_AUX_BUFFERS:
364 pfd.cAuxBuffers = attribList[arg++];
365 break;
366 case WX_GL_MIN_RED:
367 pfd.cColorBits = (pfd.cColorBits +
368 (pfd.cRedBits = attribList[arg++]));
369 break;
370 case WX_GL_MIN_GREEN:
371 pfd.cColorBits = (pfd.cColorBits +
372 (pfd.cGreenBits = attribList[arg++]));
373 break;
374 case WX_GL_MIN_BLUE:
375 pfd.cColorBits = (pfd.cColorBits +
376 (pfd.cBlueBits = attribList[arg++]));
377 break;
378 case WX_GL_MIN_ALPHA:
379 // doesn't count in cColorBits
380 pfd.cAlphaBits = attribList[arg++];
381 break;
382 case WX_GL_DEPTH_SIZE:
383 pfd.cDepthBits = attribList[arg++];
384 break;
385 case WX_GL_STENCIL_SIZE:
386 pfd.cStencilBits = attribList[arg++];
387 break;
388 case WX_GL_MIN_ACCUM_RED:
389 pfd.cAccumBits = (pfd.cAccumBits +
390 (pfd.cAccumRedBits = attribList[arg++]));
391 break;
392 case WX_GL_MIN_ACCUM_GREEN:
393 pfd.cAccumBits = (pfd.cAccumBits +
394 (pfd.cAccumGreenBits = attribList[arg++]));
395 break;
396 case WX_GL_MIN_ACCUM_BLUE:
397 pfd.cAccumBits = (pfd.cAccumBits +
398 (pfd.cAccumBlueBits = attribList[arg++]));
399 break;
400 case WX_GL_MIN_ACCUM_ALPHA:
401 pfd.cAccumBits = (pfd.cAccumBits +
402 (pfd.cAccumAlphaBits = attribList[arg++]));
403 break;
404 }
8b089c5e 405 }
a3081354
VZ
406}
407
dc3065a5
VZ
408/* static */
409int
410wxGLCanvas::ChooseMatchingPixelFormat(HDC hdc,
411 const int *attribList,
412 PIXELFORMATDESCRIPTOR *ppfd)
a3081354 413{
dc3065a5
VZ
414 // default neutral pixel format
415 PIXELFORMATDESCRIPTOR pfd =
416 {
417 sizeof(PIXELFORMATDESCRIPTOR), // size
418 1, // version
b225f659
VZ
419 PFD_SUPPORT_OPENGL |
420 PFD_DRAW_TO_WINDOW |
dc3065a5
VZ
421 PFD_DOUBLEBUFFER, // support double-buffering
422 PFD_TYPE_RGBA, // color type
423 16, // preferred color depth
424 0, 0, 0, 0, 0, 0, // color bits (ignored)
425 0, // no alpha buffer
426 0, // alpha bits (ignored)
427 0, // no accumulation buffer
428 0, 0, 0, 0, // accumulator bits (ignored)
429 16, // depth buffer
430 0, // no stencil buffer
431 0, // no auxiliary buffers
432 PFD_MAIN_PLANE, // main layer
433 0, // reserved
434 0, 0, 0, // no layer, visible, damage masks
b225f659 435 };
a3081354 436
dc3065a5
VZ
437 if ( !ppfd )
438 ppfd = &pfd;
439 else
440 *ppfd = pfd;
a3081354 441
dc3065a5
VZ
442 AdjustPFDForAttributes(*ppfd, attribList);
443
444 return ::ChoosePixelFormat(hdc, ppfd);
8b089c5e
JS
445}
446
dc3065a5 447bool wxGLCanvas::DoSetup(const int *attribList)
8b089c5e 448{
8b089c5e 449 PIXELFORMATDESCRIPTOR pfd;
dc3065a5
VZ
450 const int pixelFormat = ChooseMatchingPixelFormat(m_hDC, attribList, &pfd);
451 if ( !pixelFormat )
452 {
453 wxLogLastError(_T("ChoosePixelFormat"));
454 return false;
455 }
456
457 if ( !::SetPixelFormat(m_hDC, pixelFormat, &pfd) )
458 {
459 wxLogLastError(_T("SetPixelFormat"));
460 return false;
461 }
462
463 return true;
464}
465
466// ----------------------------------------------------------------------------
467// palette stuff
468// ----------------------------------------------------------------------------
8b089c5e 469
dc3065a5 470#if wxUSE_PALETTE
8b089c5e 471
dc3065a5
VZ
472bool wxGLCanvas::SetupPalette(const wxPalette& palette)
473{
474 const int pixelFormat = ::GetPixelFormat(m_hDC);
475 if ( !pixelFormat )
8b089c5e 476 {
dc3065a5
VZ
477 wxLogLastError(_T("GetPixelFormat"));
478 return false;
8b089c5e 479 }
dc3065a5
VZ
480
481 PIXELFORMATDESCRIPTOR pfd;
482 if ( !::DescribePixelFormat(m_hDC, pixelFormat, sizeof(pfd), &pfd) )
8b089c5e 483 {
dc3065a5
VZ
484 wxLogLastError(_T("DescribePixelFormat"));
485 return false;
8b089c5e
JS
486 }
487
dc3065a5
VZ
488 if ( !(pfd.dwFlags & PFD_NEED_PALETTE) )
489 return true;
490
8b089c5e
JS
491 m_palette = palette;
492
493 if ( !m_palette.Ok() )
494 {
495 m_palette = CreateDefaultPalette();
dc3065a5
VZ
496 if ( !m_palette.Ok() )
497 return false;
498 }
499
500 if ( !::SelectPalette(m_hDC, GetHpaletteOf(m_palette), FALSE) )
501 {
502 wxLogLastError(_T("SelectPalette"));
503 return false;
8b089c5e
JS
504 }
505
dc3065a5 506 if ( ::RealizePalette(m_hDC) == GDI_ERROR )
8b089c5e 507 {
dc3065a5
VZ
508 wxLogLastError(_T("RealizePalette"));
509 return false;
8b089c5e 510 }
dc3065a5
VZ
511
512 return true;
8b089c5e
JS
513}
514
515wxPalette wxGLCanvas::CreateDefaultPalette()
516{
517 PIXELFORMATDESCRIPTOR pfd;
518 int paletteSize;
dc3065a5 519 int pixelFormat = GetPixelFormat(m_hDC);
8b089c5e 520
dc3065a5 521 DescribePixelFormat(m_hDC, pixelFormat, sizeof(PIXELFORMATDESCRIPTOR), &pfd);
8b089c5e 522
f48d169c 523 paletteSize = 1 << pfd.cColorBits;
8b089c5e
JS
524
525 LOGPALETTE* pPal =
526 (LOGPALETTE*) malloc(sizeof(LOGPALETTE) + paletteSize * sizeof(PALETTEENTRY));
527 pPal->palVersion = 0x300;
b8ee9a86 528 pPal->palNumEntries = (WORD)paletteSize;
8b089c5e
JS
529
530 /* build a simple RGB color palette */
531 {
b225f659
VZ
532 int redMask = (1 << pfd.cRedBits) - 1;
533 int greenMask = (1 << pfd.cGreenBits) - 1;
534 int blueMask = (1 << pfd.cBlueBits) - 1;
535 int i;
536
537 for (i=0; i<paletteSize; ++i) {
538 pPal->palPalEntry[i].peRed =
b8ee9a86 539 (BYTE)((((i >> pfd.cRedShift) & redMask) * 255) / redMask);
b225f659 540 pPal->palPalEntry[i].peGreen =
b8ee9a86 541 (BYTE)((((i >> pfd.cGreenShift) & greenMask) * 255) / greenMask);
b225f659 542 pPal->palPalEntry[i].peBlue =
b8ee9a86 543 (BYTE)((((i >> pfd.cBlueShift) & blueMask) * 255) / blueMask);
b225f659
VZ
544 pPal->palPalEntry[i].peFlags = 0;
545 }
8b089c5e
JS
546 }
547
548 HPALETTE hPalette = CreatePalette(pPal);
549 free(pPal);
550
551 wxPalette palette;
552 palette.SetHPALETTE((WXHPALETTE) hPalette);
553
554 return palette;
555}
556
8b089c5e
JS
557void wxGLCanvas::OnQueryNewPalette(wxQueryNewPaletteEvent& event)
558{
f48d169c
UN
559 /* realize palette if this is the current window */
560 if ( GetPalette()->Ok() ) {
561 ::UnrealizeObject((HPALETTE) GetPalette()->GetHPALETTE());
dc3065a5
VZ
562 ::SelectPalette(GetHDC(), (HPALETTE) GetPalette()->GetHPALETTE(), FALSE);
563 ::RealizePalette(GetHDC());
f48d169c 564 Refresh();
213ceb3f 565 event.SetPaletteRealized(true);
f48d169c
UN
566 }
567 else
213ceb3f 568 event.SetPaletteRealized(false);
8b089c5e
JS
569}
570
8b089c5e
JS
571void wxGLCanvas::OnPaletteChanged(wxPaletteChangedEvent& event)
572{
f48d169c
UN
573 /* realize palette if this is *not* the current window */
574 if ( GetPalette() &&
8b089c5e 575 GetPalette()->Ok() && (this != event.GetChangedWindow()) )
f48d169c
UN
576 {
577 ::UnrealizeObject((HPALETTE) GetPalette()->GetHPALETTE());
dc3065a5
VZ
578 ::SelectPalette(GetHDC(), (HPALETTE) GetPalette()->GetHPALETTE(), FALSE);
579 ::RealizePalette(GetHDC());
f48d169c
UN
580 Refresh();
581 }
8b089c5e
JS
582}
583
dc3065a5 584#endif // wxUSE_PALETTE
a3081354 585
dc3065a5
VZ
586// ----------------------------------------------------------------------------
587// deprecated wxGLCanvas methods using implicit wxGLContext
588// ----------------------------------------------------------------------------
a3081354 589
dc3065a5
VZ
590// deprecated constructors creating an implicit m_glContext
591#if WXWIN_COMPATIBILITY_2_8
592
593wxGLCanvas::wxGLCanvas(wxWindow *parent,
594 wxWindowID id,
595 const wxPoint& pos,
596 const wxSize& size,
597 long style,
598 const wxString& name,
599 const int *attribList,
600 const wxPalette& palette)
a3081354 601{
dc3065a5 602 Init();
a3081354 603
dc3065a5
VZ
604 if ( Create(parent, id, pos, size, style, name, attribList, palette) )
605 m_glContext = new wxGLContext(this);
606}
a3081354 607
dc3065a5
VZ
608wxGLCanvas::wxGLCanvas(wxWindow *parent,
609 const wxGLContext *shared,
610 wxWindowID id,
611 const wxPoint& pos,
612 const wxSize& size,
613 long style,
614 const wxString& name,
615 const int *attribList,
616 const wxPalette& palette)
617{
618 Init();
a3081354 619
dc3065a5
VZ
620 if ( Create(parent, id, pos, size, style, name, attribList, palette) )
621 m_glContext = new wxGLContext(this, shared);
622}
623
624wxGLCanvas::wxGLCanvas(wxWindow *parent,
625 const wxGLCanvas *shared,
626 wxWindowID id,
627 const wxPoint& pos,
628 const wxSize& size,
629 long style,
630 const wxString& name,
631 const int *attribList,
632 const wxPalette& palette)
633{
634 Init();
a3081354 635
dc3065a5
VZ
636 if ( Create(parent, id, pos, size, style, name, attribList, palette) )
637 m_glContext = new wxGLContext(this, shared ? shared->m_glContext : NULL);
a3081354
VZ
638}
639
dc3065a5
VZ
640#endif // WXWIN_COMPATIBILITY_2_8
641
642
643// ----------------------------------------------------------------------------
644// wxGLApp
645// ----------------------------------------------------------------------------
646
647bool wxGLApp::InitGLVisual(const int *attribList)
a3081354 648{
dc3065a5
VZ
649 if ( !wxGLCanvas::ChooseMatchingPixelFormat(ScreenHDC(), attribList) )
650 {
651 wxLogError(_("Failed to initialize OpenGL"));
652 return false;
653 }
654
655 return true;
a3081354
VZ
656}
657
dc3065a5 658#endif // wxUSE_GLCANVAS