]> git.saurik.com Git - wxWidgets.git/blob - src/msw/glcanvas.cpp
Swap client data pointers in wxRearrangeList too.
[wxWidgets.git] / src / msw / glcanvas.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/msw/glcanvas.cpp
3 // Purpose: wxGLCanvas, for using OpenGL with wxWidgets under MS Windows
4 // Author: Julian Smart
5 // Modified by:
6 // Created: 04/01/98
7 // RCS-ID: $Id$
8 // Copyright: (c) Julian Smart
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
11
12 // ============================================================================
13 // declarations
14 // ============================================================================
15
16 // ----------------------------------------------------------------------------
17 // headers
18 // ----------------------------------------------------------------------------
19
20 #include "wx/wxprec.h"
21
22 #if defined(__BORLANDC__)
23 #pragma hdrstop
24 #endif
25
26 #if wxUSE_GLCANVAS
27
28 #ifndef WX_PRECOMP
29 #include "wx/intl.h"
30 #include "wx/log.h"
31 #include "wx/app.h"
32 #endif
33
34 #include "wx/msw/private.h"
35
36 #include "wx/glcanvas.h"
37
38 // from src/msw/window.cpp
39 LRESULT WXDLLEXPORT APIENTRY _EXPORT wxWndProc(HWND hWnd, UINT message,
40 WPARAM wParam, LPARAM lParam);
41
42 #ifdef GL_EXT_vertex_array
43 #define WXUNUSED_WITHOUT_GL_EXT_vertex_array(name) name
44 #else
45 #define WXUNUSED_WITHOUT_GL_EXT_vertex_array(name) WXUNUSED(name)
46 #endif
47
48 // ----------------------------------------------------------------------------
49 // define possibly missing WGL constants
50 // ----------------------------------------------------------------------------
51
52 #ifndef WGL_ARB_pixel_format
53 #define WGL_DRAW_TO_WINDOW_ARB 0x2001
54 #define WGL_ACCELERATION_ARB 0x2003
55 #define WGL_NUMBER_OVERLAYS_ARB 0x2008
56 #define WGL_NUMBER_UNDERLAYS_ARB 0x2009
57 #define WGL_SUPPORT_OPENGL_ARB 0x2010
58 #define WGL_DOUBLE_BUFFER_ARB 0x2011
59 #define WGL_STEREO_ARB 0x2012
60 #define WGL_COLOR_BITS_ARB 0x2014
61 #define WGL_RED_BITS_ARB 0x2015
62 #define WGL_GREEN_BITS_ARB 0x2017
63 #define WGL_BLUE_BITS_ARB 0x2019
64 #define WGL_ALPHA_BITS_ARB 0x201B
65 #define WGL_ACCUM_RED_BITS_ARB 0x201E
66 #define WGL_ACCUM_GREEN_BITS_ARB 0x201F
67 #define WGL_ACCUM_BLUE_BITS_ARB 0x2020
68 #define WGL_ACCUM_ALPHA_BITS_ARB 0x2021
69 #define WGL_DEPTH_BITS_ARB 0x2022
70 #define WGL_STENCIL_BITS_ARB 0x2023
71 #define WGL_AUX_BUFFERS_ARB 0x2024
72 #define WGL_FULL_ACCELERATION_ARB 0x2027
73 #endif
74
75 #ifndef WGL_ARB_multisample
76 #define WGL_SAMPLE_BUFFERS_ARB 0x2041
77 #define WGL_SAMPLES_ARB 0x2042
78 #endif
79
80 // ----------------------------------------------------------------------------
81 // libraries
82 // ----------------------------------------------------------------------------
83
84 /*
85 The following two compiler directives are specific to the Microsoft Visual
86 C++ family of compilers
87
88 Fundementally what they do is instruct the linker to use these two libraries
89 for the resolution of symbols. In essence, this is the equivalent of adding
90 these two libraries to either the Makefile or project file.
91
92 This is NOT a recommended technique, and certainly is unlikely to be used
93 anywhere else in wxWidgets given it is so specific to not only wxMSW, but
94 also the VC compiler. However, in the case of opengl support, it's an
95 applicable technique as opengl is optional in setup.h This code (wrapped by
96 wxUSE_GLCANVAS), now allows opengl support to be added purely by modifying
97 setup.h rather than by having to modify either the project or DSP fle.
98
99 See MSDN for further information on the exact usage of these commands.
100 */
101 #ifdef _MSC_VER
102 # pragma comment( lib, "opengl32" )
103 # pragma comment( lib, "glu32" )
104 #endif
105
106 // ----------------------------------------------------------------------------
107 // wxGLContext
108 // ----------------------------------------------------------------------------
109
110 IMPLEMENT_CLASS(wxGLContext, wxObject)
111
112 wxGLContext::wxGLContext(wxGLCanvas *win, const wxGLContext* other)
113 {
114 m_glContext = wglCreateContext(win->GetHDC());
115 wxCHECK_RET( m_glContext, wxT("Couldn't create OpenGL context") );
116
117 if ( other )
118 {
119 if ( !wglShareLists(other->m_glContext, m_glContext) )
120 {
121 wxLogLastError(wxT("wglShareLists"));
122 }
123 }
124 }
125
126 wxGLContext::~wxGLContext()
127 {
128 // note that it's ok to delete the context even if it's the current one
129 wglDeleteContext(m_glContext);
130 }
131
132 bool wxGLContext::SetCurrent(const wxGLCanvas& win) const
133 {
134 if ( !wglMakeCurrent(win.GetHDC(), m_glContext) )
135 {
136 wxLogLastError(wxT("wglMakeCurrent"));
137 return false;
138 }
139 return true;
140 }
141
142 // ============================================================================
143 // wxGLCanvas
144 // ============================================================================
145
146 IMPLEMENT_CLASS(wxGLCanvas, wxWindow)
147
148 BEGIN_EVENT_TABLE(wxGLCanvas, wxWindow)
149 EVT_PALETTE_CHANGED(wxGLCanvas::OnPaletteChanged)
150 EVT_QUERY_NEW_PALETTE(wxGLCanvas::OnQueryNewPalette)
151 END_EVENT_TABLE()
152
153 // ----------------------------------------------------------------------------
154 // wxGLCanvas construction
155 // ----------------------------------------------------------------------------
156
157 static int ChoosePixelFormatARB(HDC hdc, const int *attribList);
158
159 void wxGLCanvas::Init()
160 {
161 #if WXWIN_COMPATIBILITY_2_8
162 m_glContext = NULL;
163 #endif
164 m_hDC = NULL;
165 }
166
167 wxGLCanvas::wxGLCanvas(wxWindow *parent,
168 wxWindowID id,
169 const int *attribList,
170 const wxPoint& pos,
171 const wxSize& size,
172 long style,
173 const wxString& name,
174 const wxPalette& palette)
175 {
176 Init();
177
178 (void)Create(parent, id, pos, size, style, name, attribList, palette);
179 }
180
181 wxGLCanvas::~wxGLCanvas()
182 {
183 ::ReleaseDC(GetHwnd(), m_hDC);
184 }
185
186 // Replaces wxWindow::Create functionality, since we need to use a different
187 // window class
188 bool wxGLCanvas::CreateWindow(wxWindow *parent,
189 wxWindowID id,
190 const wxPoint& pos,
191 const wxSize& size,
192 long style,
193 const wxString& name)
194 {
195 wxCHECK_MSG( parent, false, wxT("can't create wxWindow without parent") );
196
197 if ( !CreateBase(parent, id, pos, size, style, wxDefaultValidator, name) )
198 return false;
199
200 parent->AddChild(this);
201
202 /*
203 A general rule with OpenGL and Win32 is that any window that will have a
204 HGLRC built for it must have two flags: WS_CLIPCHILDREN & WS_CLIPSIBLINGS.
205 You can find references about this within the knowledge base and most OpenGL
206 books that contain the wgl function descriptions.
207 */
208 WXDWORD exStyle = 0;
209 DWORD msflags = WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN;
210 msflags |= MSWGetStyle(style, &exStyle);
211
212 if ( !MSWCreate(wxApp::GetRegisteredClassName(wxT("wxGLCanvas"), -1, CS_OWNDC),
213 NULL, pos, size, msflags, exStyle) )
214 return false;
215
216 m_hDC = ::GetDC(GetHwnd());
217 if ( !m_hDC )
218 return false;
219
220 return true;
221 }
222
223 bool wxGLCanvas::Create(wxWindow *parent,
224 wxWindowID id,
225 const wxPoint& pos,
226 const wxSize& size,
227 long style,
228 const wxString& name,
229 const int *attribList,
230 const wxPalette& palette)
231 {
232 // Create the window first: we will either use it as is or use it to query
233 // for multisampling support and recreate it later with another pixel format
234 if ( !CreateWindow(parent, id, pos, size, style, name) )
235 return false;
236
237 PIXELFORMATDESCRIPTOR pfd;
238 const int setupVal = DoSetup(pfd, attribList);
239 if ( setupVal == 0 ) // PixelFormat error
240 return false;
241
242 if ( setupVal == -1 ) // FSAA requested
243 {
244 // now that we have a valid OpenGL window, query it for FSAA support
245 int pixelFormat;
246 {
247 wxGLContext ctx(this);
248 ctx.SetCurrent(*this);
249 pixelFormat = ::ChoosePixelFormatARB(m_hDC, attribList);
250 }
251
252 if ( pixelFormat > 0 )
253 {
254 // from http://msdn.microsoft.com/en-us/library/ms537559(VS.85).aspx:
255 //
256 // Setting the pixel format of a window more than once can
257 // lead to significant complications for the Window Manager
258 // and for multithread applications, so it is not allowed. An
259 // application can only set the pixel format of a window one
260 // time. Once a window's pixel format is set, it cannot be
261 // changed.
262 //
263 // so we need to delete the old window and create the new one
264
265 // destroy Window
266 ::ReleaseDC(GetHwnd(), m_hDC);
267 m_hDC = 0;
268
269 parent->RemoveChild(this);
270 const HWND hwnd = GetHwnd();
271 DissociateHandle(); // will do SetHWND(0);
272 ::DestroyWindow(hwnd);
273
274 // now recreate with FSAA pixelFormat
275 if ( !CreateWindow(parent, id, pos, size, style, name) )
276 return false;
277
278 if ( !::SetPixelFormat(m_hDC, pixelFormat, &pfd) )
279 {
280 wxLogLastError(wxT("SetPixelFormat"));
281 return false;
282 }
283 }
284 }
285
286 #if wxUSE_PALETTE
287 if ( !SetupPalette(palette) )
288 return false;
289 #else // !wxUSE_PALETTE
290 wxUnusedVar(palette);
291 #endif // wxUSE_PALETTE/!wxUSE_PALETTE
292
293 return true;
294 }
295
296 // ----------------------------------------------------------------------------
297 // operations
298 // ----------------------------------------------------------------------------
299
300 bool wxGLCanvas::SwapBuffers()
301 {
302 if ( !::SwapBuffers(m_hDC) )
303 {
304 wxLogLastError(wxT("SwapBuffers"));
305 return false;
306 }
307
308 return true;
309 }
310
311
312 // ----------------------------------------------------------------------------
313 // multi sample support
314 // ----------------------------------------------------------------------------
315
316 // this macro defines a variable of type "name_t" called "name" and initializes
317 // it with the pointer to WGL function "name" (which may be NULL)
318 #define wxDEFINE_WGL_FUNC(name) \
319 name##_t name = (name##_t)wglGetProcAddress(#name)
320
321 /* static */
322 bool wxGLCanvasBase::IsExtensionSupported(const char *extension)
323 {
324 static const char *s_extensionsList = (char *)wxUIntPtr(-1);
325 if ( s_extensionsList == (char *)wxUIntPtr(-1) )
326 {
327 typedef const char * (WINAPI *wglGetExtensionsStringARB_t)(HDC hdc);
328
329 wxDEFINE_WGL_FUNC(wglGetExtensionsStringARB);
330 if ( wglGetExtensionsStringARB )
331 {
332 s_extensionsList = wglGetExtensionsStringARB(wglGetCurrentDC());
333 }
334 else
335 {
336 typedef const char * (WINAPI * wglGetExtensionsStringEXT_t)();
337
338 wxDEFINE_WGL_FUNC(wglGetExtensionsStringEXT);
339 if ( wglGetExtensionsStringEXT )
340 {
341 s_extensionsList = wglGetExtensionsStringEXT();
342 }
343 else
344 {
345 s_extensionsList = NULL;
346 }
347 }
348 }
349
350 return s_extensionsList && IsExtensionInList(s_extensionsList, extension);
351 }
352
353 // this is a wrapper around wglChoosePixelFormatARB(): returns the pixel format
354 // index matching the given attributes on success or 0 on failure
355 static int ChoosePixelFormatARB(HDC hdc, const int *attribList)
356 {
357 if ( !wxGLCanvas::IsExtensionSupported("WGL_ARB_multisample") )
358 return 0;
359
360 typedef BOOL (WINAPI * wglChoosePixelFormatARB_t)
361 (HDC hdc,
362 const int *piAttribIList,
363 const FLOAT *pfAttribFList,
364 UINT nMaxFormats,
365 int *piFormats,
366 UINT *nNumFormats
367 );
368
369 wxDEFINE_WGL_FUNC(wglChoosePixelFormatARB);
370 if ( !wglChoosePixelFormatARB )
371 return 0; // should not occur if extension is supported
372
373 int iAttributes[128];
374 int dst = 0; // index in iAttributes array
375
376 #define ADD_ATTR(attr, value) \
377 iAttributes[dst++] = attr; iAttributes[dst++] = value
378
379 ADD_ATTR( WGL_DRAW_TO_WINDOW_ARB, GL_TRUE );
380 ADD_ATTR( WGL_SUPPORT_OPENGL_ARB, GL_TRUE );
381 ADD_ATTR( WGL_ACCELERATION_ARB, WGL_FULL_ACCELERATION_ARB );
382
383 if ( !attribList )
384 {
385 ADD_ATTR( WGL_COLOR_BITS_ARB, 24 );
386 ADD_ATTR( WGL_ALPHA_BITS_ARB, 8 );
387 ADD_ATTR( WGL_DEPTH_BITS_ARB, 16 );
388 ADD_ATTR( WGL_STENCIL_BITS_ARB, 0 );
389 ADD_ATTR( WGL_DOUBLE_BUFFER_ARB, GL_TRUE );
390 ADD_ATTR( WGL_SAMPLE_BUFFERS_ARB, GL_TRUE );
391 ADD_ATTR( WGL_SAMPLES_ARB, 4 );
392 }
393 else // have custom attributes
394 {
395 #define ADD_ATTR_VALUE(attr) ADD_ATTR(attr, attribList[src++])
396
397 int src = 0;
398 while ( attribList[src] )
399 {
400 switch ( attribList[src++] )
401 {
402 case WX_GL_RGBA:
403 ADD_ATTR( WGL_COLOR_BITS_ARB, 24 );
404 ADD_ATTR( WGL_ALPHA_BITS_ARB, 8 );
405 break;
406
407 case WX_GL_BUFFER_SIZE:
408 ADD_ATTR_VALUE( WGL_COLOR_BITS_ARB);
409 break;
410
411 case WX_GL_LEVEL:
412 if ( attribList[src] > 0 )
413 {
414 ADD_ATTR( WGL_NUMBER_OVERLAYS_ARB, 1 );
415 }
416 else if ( attribList[src] <0 )
417 {
418 ADD_ATTR( WGL_NUMBER_UNDERLAYS_ARB, 1 );
419 }
420 //else: ignore it
421
422 src++; // skip the value in any case
423 break;
424
425 case WX_GL_DOUBLEBUFFER:
426 ADD_ATTR( WGL_DOUBLE_BUFFER_ARB, GL_TRUE );
427 break;
428
429 case WX_GL_STEREO:
430 ADD_ATTR( WGL_STEREO_ARB, GL_TRUE );
431 break;
432
433 case WX_GL_AUX_BUFFERS:
434 ADD_ATTR_VALUE( WGL_AUX_BUFFERS_ARB );
435 break;
436
437 case WX_GL_MIN_RED:
438 ADD_ATTR_VALUE( WGL_RED_BITS_ARB );
439 break;
440
441 case WX_GL_MIN_GREEN:
442 ADD_ATTR_VALUE( WGL_GREEN_BITS_ARB );
443 break;
444
445 case WX_GL_MIN_BLUE:
446 ADD_ATTR_VALUE( WGL_BLUE_BITS_ARB );
447 break;
448
449 case WX_GL_MIN_ALPHA:
450 ADD_ATTR_VALUE( WGL_ALPHA_BITS_ARB );
451 break;
452
453 case WX_GL_DEPTH_SIZE:
454 ADD_ATTR_VALUE( WGL_DEPTH_BITS_ARB );
455 break;
456
457 case WX_GL_STENCIL_SIZE:
458 ADD_ATTR_VALUE( WGL_STENCIL_BITS_ARB );
459 break;
460
461 case WX_GL_MIN_ACCUM_RED:
462 ADD_ATTR_VALUE( WGL_ACCUM_RED_BITS_ARB );
463 break;
464
465 case WX_GL_MIN_ACCUM_GREEN:
466 ADD_ATTR_VALUE( WGL_ACCUM_GREEN_BITS_ARB );
467 break;
468
469 case WX_GL_MIN_ACCUM_BLUE:
470 ADD_ATTR_VALUE( WGL_ACCUM_BLUE_BITS_ARB );
471 break;
472
473 case WX_GL_MIN_ACCUM_ALPHA:
474 ADD_ATTR_VALUE( WGL_ACCUM_ALPHA_BITS_ARB );
475 break;
476
477 case WX_GL_SAMPLE_BUFFERS:
478 ADD_ATTR_VALUE( WGL_SAMPLE_BUFFERS_ARB );
479 break;
480
481 case WX_GL_SAMPLES:
482 ADD_ATTR_VALUE( WGL_SAMPLES_ARB );
483 break;
484 }
485 }
486
487 #undef ADD_ATTR_VALUE
488 }
489
490 #undef ADD_ATTR
491
492 iAttributes[dst++] = 0;
493
494 int pf;
495 UINT numFormats = 0;
496 if ( !wglChoosePixelFormatARB(hdc, iAttributes, NULL, 1, &pf, &numFormats) )
497 {
498 wxLogLastError(wxT("wglChoosePixelFormatARB"));
499 return 0;
500 }
501
502 return pf;
503 }
504
505 // ----------------------------------------------------------------------------
506 // pixel format stuff
507 // ----------------------------------------------------------------------------
508
509 // returns true if pfd was adjusted accordingly to attributes provided, false
510 // if there is an error with attributes or -1 if the attributes indicate
511 // features not supported by ChoosePixelFormat() at all (currently only multi
512 // sampling)
513 static int
514 AdjustPFDForAttributes(PIXELFORMATDESCRIPTOR& pfd, const int *attribList)
515 {
516 if ( !attribList )
517 return 1;
518
519 // remove default attributes
520 pfd.dwFlags &= ~PFD_DOUBLEBUFFER;
521 pfd.iPixelType = PFD_TYPE_COLORINDEX;
522
523 bool requestFSAA = false;
524 for ( int arg = 0; attribList[arg]; )
525 {
526 switch ( attribList[arg++] )
527 {
528 case WX_GL_RGBA:
529 pfd.iPixelType = PFD_TYPE_RGBA;
530 break;
531
532 case WX_GL_BUFFER_SIZE:
533 pfd.cColorBits = attribList[arg++];
534 break;
535
536 case WX_GL_LEVEL:
537 // this member looks like it may be obsolete
538 if ( attribList[arg] > 0 )
539 pfd.iLayerType = PFD_OVERLAY_PLANE;
540 else if ( attribList[arg] < 0 )
541 pfd.iLayerType = (BYTE)PFD_UNDERLAY_PLANE;
542 else
543 pfd.iLayerType = PFD_MAIN_PLANE;
544 arg++;
545 break;
546
547 case WX_GL_DOUBLEBUFFER:
548 pfd.dwFlags |= PFD_DOUBLEBUFFER;
549 break;
550
551 case WX_GL_STEREO:
552 pfd.dwFlags |= PFD_STEREO;
553 break;
554
555 case WX_GL_AUX_BUFFERS:
556 pfd.cAuxBuffers = attribList[arg++];
557 break;
558
559 case WX_GL_MIN_RED:
560 pfd.cColorBits += (pfd.cRedBits = attribList[arg++]);
561 break;
562
563 case WX_GL_MIN_GREEN:
564 pfd.cColorBits += (pfd.cGreenBits = attribList[arg++]);
565 break;
566
567 case WX_GL_MIN_BLUE:
568 pfd.cColorBits += (pfd.cBlueBits = attribList[arg++]);
569 break;
570
571 case WX_GL_MIN_ALPHA:
572 // doesn't count in cColorBits
573 pfd.cAlphaBits = attribList[arg++];
574 break;
575
576 case WX_GL_DEPTH_SIZE:
577 pfd.cDepthBits = attribList[arg++];
578 break;
579
580 case WX_GL_STENCIL_SIZE:
581 pfd.cStencilBits = attribList[arg++];
582 break;
583
584 case WX_GL_MIN_ACCUM_RED:
585 pfd.cAccumBits += (pfd.cAccumRedBits = attribList[arg++]);
586 break;
587
588 case WX_GL_MIN_ACCUM_GREEN:
589 pfd.cAccumBits += (pfd.cAccumGreenBits = attribList[arg++]);
590 break;
591
592 case WX_GL_MIN_ACCUM_BLUE:
593 pfd.cAccumBits += (pfd.cAccumBlueBits = attribList[arg++]);
594 break;
595
596 case WX_GL_MIN_ACCUM_ALPHA:
597 pfd.cAccumBits += (pfd.cAccumAlphaBits = attribList[arg++]);
598 break;
599
600 case WX_GL_SAMPLE_BUFFERS:
601 case WX_GL_SAMPLES:
602 // There is no support for multisample when using PIXELFORMATDESCRIPTOR
603 requestFSAA = true; // Remember that multi sample is requested.
604 arg++; // will call ChoosePixelFormatARB() later
605 break;
606 }
607 }
608
609 return requestFSAA ? -1 : 1;
610 }
611
612 /* static */
613 int
614 wxGLCanvas::ChooseMatchingPixelFormat(HDC hdc,
615 const int *attribList,
616 PIXELFORMATDESCRIPTOR *ppfd)
617 {
618 // default neutral pixel format
619 PIXELFORMATDESCRIPTOR pfd =
620 {
621 sizeof(PIXELFORMATDESCRIPTOR), // size
622 1, // version
623 PFD_SUPPORT_OPENGL |
624 PFD_DRAW_TO_WINDOW |
625 PFD_DOUBLEBUFFER, // use double-buffering by default
626 PFD_TYPE_RGBA, // default pixel type
627 0, // preferred color depth (don't care)
628 0, 0, 0, 0, 0, 0, // color bits and shift bits (ignored)
629 0, 0, // alpha bits and shift (ignored)
630 0, // accumulation total bits
631 0, 0, 0, 0, // accumulator RGBA bits (not used)
632 16, // depth buffer
633 0, // no stencil buffer
634 0, // no auxiliary buffers
635 PFD_MAIN_PLANE, // main layer
636 0, // reserved
637 0, 0, 0, // no layer, visible, damage masks
638 };
639
640 if ( !ppfd )
641 ppfd = &pfd;
642 else
643 *ppfd = pfd;
644
645 // adjust the PFD using the provided attributes and also check if we can
646 // use PIXELFORMATDESCRIPTOR at all: if multisampling is requested, we
647 // can't as it's not supported by ChoosePixelFormat()
648 switch ( AdjustPFDForAttributes(*ppfd, attribList) )
649 {
650 case 1:
651 return ::ChoosePixelFormat(hdc, ppfd);
652
653 default:
654 wxFAIL_MSG( "unexpected AdjustPFDForAttributes() return value" );
655 // fall through
656
657 case 0:
658 // error in attributes
659 return 0;
660
661 case -1:
662 // requestFSAA == true, will continue as normal
663 // in order to query later for a FSAA pixelformat
664 return -1;
665 }
666 }
667
668 /* static */
669 bool wxGLCanvasBase::IsDisplaySupported(const int *attribList)
670 {
671 // We need a device context to test the pixel format, so get one
672 // for the root window.
673 return wxGLCanvas::ChooseMatchingPixelFormat(ScreenHDC(), attribList) > 0;
674 }
675
676 int wxGLCanvas::DoSetup(PIXELFORMATDESCRIPTOR &pfd, const int *attribList)
677 {
678 int pixelFormat = ChooseMatchingPixelFormat(m_hDC, attribList, &pfd);
679
680 const bool requestFSAA = pixelFormat == -1;
681 if ( requestFSAA )
682 pixelFormat = ::ChoosePixelFormat(m_hDC, &pfd);
683
684 if ( !pixelFormat )
685 {
686 wxLogLastError(wxT("ChoosePixelFormat"));
687 return 0;
688 }
689
690 if ( !::SetPixelFormat(m_hDC, pixelFormat, &pfd) )
691 {
692 wxLogLastError(wxT("SetPixelFormat"));
693 return 0;
694 }
695
696 return requestFSAA ? -1 : 1;
697 }
698
699 // ----------------------------------------------------------------------------
700 // palette stuff
701 // ----------------------------------------------------------------------------
702
703 #if wxUSE_PALETTE
704
705 bool wxGLCanvas::SetupPalette(const wxPalette& palette)
706 {
707 const int pixelFormat = ::GetPixelFormat(m_hDC);
708 if ( !pixelFormat )
709 {
710 wxLogLastError(wxT("GetPixelFormat"));
711 return false;
712 }
713
714 PIXELFORMATDESCRIPTOR pfd;
715 if ( !::DescribePixelFormat(m_hDC, pixelFormat, sizeof(pfd), &pfd) )
716 {
717 wxLogLastError(wxT("DescribePixelFormat"));
718 return false;
719 }
720
721 if ( !(pfd.dwFlags & PFD_NEED_PALETTE) )
722 return true;
723
724 m_palette = palette;
725
726 if ( !m_palette.Ok() )
727 {
728 m_palette = CreateDefaultPalette();
729 if ( !m_palette.Ok() )
730 return false;
731 }
732
733 if ( !::SelectPalette(m_hDC, GetHpaletteOf(m_palette), FALSE) )
734 {
735 wxLogLastError(wxT("SelectPalette"));
736 return false;
737 }
738
739 if ( ::RealizePalette(m_hDC) == GDI_ERROR )
740 {
741 wxLogLastError(wxT("RealizePalette"));
742 return false;
743 }
744
745 return true;
746 }
747
748 wxPalette wxGLCanvas::CreateDefaultPalette()
749 {
750 PIXELFORMATDESCRIPTOR pfd;
751 int paletteSize;
752 int pixelFormat = GetPixelFormat(m_hDC);
753
754 DescribePixelFormat(m_hDC, pixelFormat, sizeof(PIXELFORMATDESCRIPTOR), &pfd);
755
756 paletteSize = 1 << pfd.cColorBits;
757
758 LOGPALETTE* pPal =
759 (LOGPALETTE*) malloc(sizeof(LOGPALETTE) + paletteSize * sizeof(PALETTEENTRY));
760 pPal->palVersion = 0x300;
761 pPal->palNumEntries = (WORD)paletteSize;
762
763 /* build a simple RGB color palette */
764 int redMask = (1 << pfd.cRedBits) - 1;
765 int greenMask = (1 << pfd.cGreenBits) - 1;
766 int blueMask = (1 << pfd.cBlueBits) - 1;
767
768 for (int i=0; i<paletteSize; ++i)
769 {
770 pPal->palPalEntry[i].peRed =
771 (BYTE)((((i >> pfd.cRedShift) & redMask) * 255) / redMask);
772 pPal->palPalEntry[i].peGreen =
773 (BYTE)((((i >> pfd.cGreenShift) & greenMask) * 255) / greenMask);
774 pPal->palPalEntry[i].peBlue =
775 (BYTE)((((i >> pfd.cBlueShift) & blueMask) * 255) / blueMask);
776 pPal->palPalEntry[i].peFlags = 0;
777 }
778
779 HPALETTE hPalette = CreatePalette(pPal);
780 free(pPal);
781
782 wxPalette palette;
783 palette.SetHPALETTE((WXHPALETTE) hPalette);
784
785 return palette;
786 }
787
788 void wxGLCanvas::OnQueryNewPalette(wxQueryNewPaletteEvent& event)
789 {
790 /* realize palette if this is the current window */
791 if ( GetPalette()->Ok() ) {
792 ::UnrealizeObject((HPALETTE) GetPalette()->GetHPALETTE());
793 ::SelectPalette(GetHDC(), (HPALETTE) GetPalette()->GetHPALETTE(), FALSE);
794 ::RealizePalette(GetHDC());
795 Refresh();
796 event.SetPaletteRealized(true);
797 }
798 else
799 event.SetPaletteRealized(false);
800 }
801
802 void wxGLCanvas::OnPaletteChanged(wxPaletteChangedEvent& event)
803 {
804 /* realize palette if this is *not* the current window */
805 if ( GetPalette() &&
806 GetPalette()->Ok() && (this != event.GetChangedWindow()) )
807 {
808 ::UnrealizeObject((HPALETTE) GetPalette()->GetHPALETTE());
809 ::SelectPalette(GetHDC(), (HPALETTE) GetPalette()->GetHPALETTE(), FALSE);
810 ::RealizePalette(GetHDC());
811 Refresh();
812 }
813 }
814
815 #endif // wxUSE_PALETTE
816
817 // ----------------------------------------------------------------------------
818 // deprecated wxGLCanvas methods using implicit wxGLContext
819 // ----------------------------------------------------------------------------
820
821 // deprecated constructors creating an implicit m_glContext
822 #if WXWIN_COMPATIBILITY_2_8
823
824 wxGLCanvas::wxGLCanvas(wxWindow *parent,
825 wxWindowID id,
826 const wxPoint& pos,
827 const wxSize& size,
828 long style,
829 const wxString& name,
830 const int *attribList,
831 const wxPalette& palette)
832 {
833 Init();
834
835 if ( Create(parent, id, pos, size, style, name, attribList, palette) )
836 m_glContext = new wxGLContext(this);
837 }
838
839 wxGLCanvas::wxGLCanvas(wxWindow *parent,
840 const wxGLContext *shared,
841 wxWindowID id,
842 const wxPoint& pos,
843 const wxSize& size,
844 long style,
845 const wxString& name,
846 const int *attribList,
847 const wxPalette& palette)
848 {
849 Init();
850
851 if ( Create(parent, id, pos, size, style, name, attribList, palette) )
852 m_glContext = new wxGLContext(this, shared);
853 }
854
855 wxGLCanvas::wxGLCanvas(wxWindow *parent,
856 const wxGLCanvas *shared,
857 wxWindowID id,
858 const wxPoint& pos,
859 const wxSize& size,
860 long style,
861 const wxString& name,
862 const int *attribList,
863 const wxPalette& palette)
864 {
865 Init();
866
867 if ( Create(parent, id, pos, size, style, name, attribList, palette) )
868 m_glContext = new wxGLContext(this, shared ? shared->m_glContext : NULL);
869 }
870
871 #endif // WXWIN_COMPATIBILITY_2_8
872
873
874 // ----------------------------------------------------------------------------
875 // wxGLApp
876 // ----------------------------------------------------------------------------
877
878 bool wxGLApp::InitGLVisual(const int *attribList)
879 {
880 if ( !wxGLCanvas::ChooseMatchingPixelFormat(ScreenHDC(), attribList) )
881 {
882 wxLogError(_("Failed to initialize OpenGL"));
883 return false;
884 }
885
886 return true;
887 }
888
889 #endif // wxUSE_GLCANVAS