1 ///////////////////////////////////////////////////////////////////////////// 
   2 // Name:        src/msw/glcanvas.cpp 
   3 // Purpose:     wxGLCanvas, for using OpenGL with wxWidgets under MS Windows 
   4 // Author:      Julian Smart 
   8 // Copyright:   (c) Julian Smart 
   9 // Licence:     wxWindows licence 
  10 ///////////////////////////////////////////////////////////////////////////// 
  12 #if defined(__GNUG__) && !defined(NO_GCC_PRAGMA) 
  13 #pragma implementation "glcanvas.h" 
  16 #include "wx/wxprec.h" 
  18 #if defined(__BORLANDC__) 
  26     #include "wx/settings.h" 
  32 #include "wx/module.h" 
  34 #include "wx/msw/private.h" 
  36 // DLL options compatibility check: 
  38 WX_CHECK_BUILD_OPTIONS("wxGL") 
  40 #include "wx/glcanvas.h" 
  42 #if GL_EXT_vertex_array 
  43     #define WXUNUSED_WITHOUT_GL_EXT_vertex_array(name) name 
  45     #define WXUNUSED_WITHOUT_GL_EXT_vertex_array(name) WXUNUSED(name) 
  49   The following two compiler directives are specific to the Microsoft Visual 
  50   C++ family of compilers 
  52   Fundementally what they do is instruct the linker to use these two libraries 
  53   for the resolution of symbols. In essence, this is the equivalent of adding 
  54   these two libraries to either the Makefile or project file. 
  56   This is NOT a recommended technique, and certainly is unlikely to be used 
  57   anywhere else in wxWidgets given it is so specific to not only wxMSW, but 
  58   also the VC compiler. However, in the case of opengl support, it's an 
  59   applicable technique as opengl is optional in setup.h This code (wrapped by 
  60   wxUSE_GLCANVAS), now allows opengl support to be added purely by modifying 
  61   setup.h rather than by having to modify either the project or DSP fle. 
  63   See MSDN for further information on the exact usage of these commands. 
  66 #  pragma comment( lib, "opengl32" ) 
  67 #  pragma comment( lib, "glu32" ) 
  71 static const wxChar 
*wxGLCanvasClassName 
= wxT("wxGLCanvasClass"); 
  72 static const wxChar 
*wxGLCanvasClassNameNoRedraw 
= wxT("wxGLCanvasClassNR"); 
  74 LRESULT WXDLLEXPORT APIENTRY _EXPORT 
wxWndProc(HWND hWnd
, UINT message
, 
  75                                    WPARAM wParam
, LPARAM lParam
); 
  77 // ---------------------------------------------------------------------------- 
  78 // wxGLModule is responsible for unregistering wxGLCanvasClass Windows class 
  79 // ---------------------------------------------------------------------------- 
  81 class wxGLModule 
: public wxModule
 
  84     bool OnInit() { return true; } 
  85     void OnExit() { UnregisterClasses(); } 
  87     // register the GL classes if not done yet, return true if ok, false if 
  88     // registration failed 
  89     static bool RegisterClasses(); 
  91     // unregister the classes, done automatically on program termination 
  92     static void UnregisterClasses(); 
  95     // wxGLCanvas is only used from the main thread so this is MT-ok 
  96     static bool ms_registeredGLClasses
; 
  98     DECLARE_DYNAMIC_CLASS(wxGLModule
) 
 101 IMPLEMENT_DYNAMIC_CLASS(wxGLModule
, wxModule
) 
 103 bool wxGLModule::ms_registeredGLClasses 
= false; 
 106 bool wxGLModule::RegisterClasses() 
 108     if (ms_registeredGLClasses
) 
 111     // We have to register a special window class because we need the CS_OWNDC 
 112     // style for GLCanvas. 
 115   From Angel Popov <jumpo@bitex.com> 
 117   Here are two snips from a dicussion in the OpenGL Gamedev list that explains 
 118   how this problem can be fixed: 
 120   "There are 5 common DCs available in Win95. These are aquired when you call 
 121   GetDC or GetDCEx from a window that does _not_ have the OWNDC flag. 
 122   OWNDC flagged windows do not get their DC from the common DC pool, the issue 
 123   is they require 800 bytes each from the limited 64Kb local heap for GDI." 
 125   "The deal is, if you hold onto one of the 5 shared DC's too long (as GL apps 
 126   do), Win95 will actually "steal" it from you.  MakeCurrent fails, 
 127   apparently, because Windows re-assigns the HDC to a different window.  The 
 128   only way to prevent this, the only reliable means, is to set CS_OWNDC." 
 133     // the fields which are common to all classes 
 134     wndclass
.lpfnWndProc   
= (WNDPROC
)wxWndProc
; 
 135     wndclass
.cbClsExtra    
= 0; 
 136     wndclass
.cbWndExtra    
= sizeof( DWORD 
); // VZ: what is this DWORD used for? 
 137     wndclass
.hInstance     
= wxhInstance
; 
 138     wndclass
.hIcon         
= (HICON
) NULL
; 
 139     wndclass
.hCursor       
= ::LoadCursor((HINSTANCE
)NULL
, IDC_ARROW
); 
 140     wndclass
.lpszMenuName  
= NULL
; 
 142     // Register the GLCanvas class name 
 143     wndclass
.hbrBackground 
= (HBRUSH
)NULL
; 
 144     wndclass
.lpszClassName 
= wxGLCanvasClassName
; 
 145     wndclass
.style         
= CS_HREDRAW 
| CS_VREDRAW 
| CS_DBLCLKS 
| CS_OWNDC
; 
 147     if ( !::RegisterClass(&wndclass
) ) 
 149         wxLogLastError(wxT("RegisterClass(wxGLCanvasClass)")); 
 153     // Register the GLCanvas class name for windows which don't do full repaint 
 155     wndclass
.lpszClassName 
= wxGLCanvasClassNameNoRedraw
; 
 156     wndclass
.style        
&= ~(CS_HREDRAW 
| CS_VREDRAW
); 
 158     if ( !::RegisterClass(&wndclass
) ) 
 160         wxLogLastError(wxT("RegisterClass(wxGLCanvasClassNameNoRedraw)")); 
 162         ::UnregisterClass(wxGLCanvasClassName
, wxhInstance
); 
 167     ms_registeredGLClasses 
= true; 
 173 void wxGLModule::UnregisterClasses() 
 175     // we need to unregister the classes in case we're in a DLL which is 
 176     // unloaded and then loaded again because if we don't, the registration is 
 177     // going to fail in wxGLCanvas::Create() the next time we're loaded 
 178     if ( ms_registeredGLClasses 
) 
 180         ::UnregisterClass(wxGLCanvasClassName
, wxhInstance
); 
 181         ::UnregisterClass(wxGLCanvasClassNameNoRedraw
, wxhInstance
); 
 183         ms_registeredGLClasses 
= false; 
 188  * GLContext implementation 
 191 wxGLContext::wxGLContext(bool WXUNUSED(isRGB
), wxGLCanvas 
*win
, const wxPalette
& WXUNUSED(palette
)) 
 195   m_hDC 
= win
->GetHDC(); 
 197   m_glContext 
= wglCreateContext((HDC
) m_hDC
); 
 198   wxCHECK_RET( m_glContext
, wxT("Couldn't create OpenGL context") ); 
 200   wglMakeCurrent((HDC
) m_hDC
, m_glContext
); 
 203 wxGLContext::wxGLContext( 
 204                bool WXUNUSED(isRGB
), wxGLCanvas 
*win
, 
 205                const wxPalette
& WXUNUSED(palette
), 
 206                const wxGLContext 
*other  
/* for sharing display lists */ 
 211   m_hDC 
= win
->GetHDC(); 
 213   m_glContext 
= wglCreateContext((HDC
) m_hDC
); 
 214   wxCHECK_RET( m_glContext
, wxT("Couldn't create OpenGL context") ); 
 217     wglShareLists( other
->m_glContext
, m_glContext 
); 
 219   wglMakeCurrent((HDC
) m_hDC
, m_glContext
); 
 222 wxGLContext::~wxGLContext() 
 226     wglMakeCurrent(NULL
, NULL
); 
 227     wglDeleteContext(m_glContext
); 
 231 void wxGLContext::SwapBuffers() 
 235     wglMakeCurrent((HDC
) m_hDC
, m_glContext
); 
 236     ::SwapBuffers((HDC
) m_hDC
);    //blits the backbuffer into DC 
 240 void wxGLContext::SetCurrent() 
 244     wglMakeCurrent((HDC
) m_hDC
, m_glContext
); 
 248   setupPixelFormat(hDC); 
 253 void wxGLContext::SetColour(const wxChar 
*colour
) 
 255     wxColour col 
= wxTheColourDatabase
->Find(colour
); 
 258         float r 
= (float)(col
.Red()/256.0); 
 259         float g 
= (float)(col
.Green()/256.0); 
 260         float b 
= (float)(col
.Blue()/256.0); 
 267  * wxGLCanvas implementation 
 270 IMPLEMENT_CLASS(wxGLCanvas
, wxWindow
) 
 272 BEGIN_EVENT_TABLE(wxGLCanvas
, wxWindow
) 
 273     EVT_SIZE(wxGLCanvas::OnSize
) 
 274     EVT_PALETTE_CHANGED(wxGLCanvas::OnPaletteChanged
) 
 275     EVT_QUERY_NEW_PALETTE(wxGLCanvas::OnQueryNewPalette
) 
 278 wxGLCanvas::wxGLCanvas(wxWindow 
*parent
, wxWindowID id
, 
 279     const wxPoint
& pos
, const wxSize
& size
, long style
, const wxString
& name
, 
 280     int *attribList
, const wxPalette
& palette
) : wxWindow() 
 282   m_glContext 
= (wxGLContext
*) NULL
; 
 284   bool ret 
= Create(parent
, id
, pos
, size
, style
, name
); 
 288     SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_3DFACE
)); 
 291   m_hDC 
= (WXHDC
) ::GetDC((HWND
) GetHWND()); 
 293   SetupPixelFormat(attribList
); 
 294   SetupPalette(palette
); 
 296   m_glContext 
= new wxGLContext(true, this, palette
); 
 299 wxGLCanvas::wxGLCanvas( wxWindow 
*parent
, 
 300               const wxGLContext 
*shared
, wxWindowID id
, 
 301               const wxPoint
& pos
, const wxSize
& size
, long style
, const wxString
& name
, 
 302               int *attribList
, const wxPalette
& palette 
) 
 305   m_glContext 
= (wxGLContext
*) NULL
; 
 307   bool ret 
= Create(parent
, id
, pos
, size
, style
, name
); 
 311     SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_3DFACE
)); 
 314   m_hDC 
= (WXHDC
) ::GetDC((HWND
) GetHWND()); 
 316   SetupPixelFormat(attribList
); 
 317   SetupPalette(palette
); 
 319   m_glContext 
= new wxGLContext(true, this, palette
, shared 
); 
 322 // Not very useful for wxMSW, but this is to be wxGTK compliant 
 324 wxGLCanvas::wxGLCanvas( wxWindow 
*parent
, const wxGLCanvas 
*shared
, wxWindowID id
, 
 325                         const wxPoint
& pos
, const wxSize
& size
, long style
, const wxString
& name
, 
 326                         int *attribList
, const wxPalette
& palette 
): 
 329   m_glContext 
= (wxGLContext
*) NULL
; 
 331   bool ret 
= Create(parent
, id
, pos
, size
, style
, name
); 
 335     SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_3DFACE
)); 
 338   m_hDC 
= (WXHDC
) ::GetDC((HWND
) GetHWND()); 
 340   SetupPixelFormat(attribList
); 
 341   SetupPalette(palette
); 
 343   wxGLContext 
*sharedContext
=0; 
 344   if (shared
) sharedContext
=shared
->GetContext(); 
 345   m_glContext 
= new wxGLContext(true, this, palette
, sharedContext 
); 
 348 wxGLCanvas::~wxGLCanvas() 
 352   ::ReleaseDC((HWND
) GetHWND(), (HDC
) m_hDC
); 
 355 // Replaces wxWindow::Create functionality, since we need to use a different 
 357 bool wxGLCanvas::Create(wxWindow 
*parent
, 
 362                         const wxString
& name
) 
 364     wxCHECK_MSG( parent
, false, wxT("can't create wxWindow without parent") ); 
 366     if ( !wxGLModule::RegisterClasses() ) 
 368         wxLogError(_("Failed to register OpenGL window class.")); 
 373     if ( !CreateBase(parent
, id
, pos
, size
, style
, wxDefaultValidator
, name
) ) 
 376     parent
->AddChild(this); 
 381        A general rule with OpenGL and Win32 is that any window that will have a 
 382        HGLRC built for it must have two flags:  WS_CLIPCHILDREN & WS_CLIPSIBLINGS. 
 383        You can find references about this within the knowledge base and most OpenGL 
 384        books that contain the wgl function descriptions. 
 388     msflags 
|= WS_CHILD 
| WS_VISIBLE 
| WS_CLIPSIBLINGS 
| WS_CLIPCHILDREN
; 
 389     msflags 
|= MSWGetStyle(style
, & exStyle
) ; 
 391     return MSWCreate(wxGLCanvasClassName
, NULL
, pos
, size
, msflags
, exStyle
); 
 394 static void AdjustPFDForAttributes(PIXELFORMATDESCRIPTOR
& pfd
, int *attribList
) 
 397     pfd
.dwFlags 
&= ~PFD_DOUBLEBUFFER
; 
 398     pfd
.iPixelType 
= PFD_TYPE_COLORINDEX
; 
 402     while( (attribList
[arg
]!=0) ) 
 404       switch( attribList
[arg
++] ) 
 407           pfd
.iPixelType 
= PFD_TYPE_RGBA
; 
 409         case WX_GL_BUFFER_SIZE
: 
 410           pfd
.cColorBits 
= (BYTE
)attribList
[arg
++]; 
 413           // this member looks like it may be obsolete 
 414           if (attribList
[arg
] > 0) { 
 415             pfd
.iLayerType 
= (BYTE
)PFD_OVERLAY_PLANE
; 
 416           } else if (attribList
[arg
] < 0) { 
 417             pfd
.iLayerType 
= (BYTE
)PFD_UNDERLAY_PLANE
; 
 419             pfd
.iLayerType 
= (BYTE
)PFD_MAIN_PLANE
; 
 423         case WX_GL_DOUBLEBUFFER
: 
 424           pfd
.dwFlags 
|= PFD_DOUBLEBUFFER
; 
 427           pfd
.dwFlags 
|= PFD_STEREO
; 
 429         case WX_GL_AUX_BUFFERS
: 
 430           pfd
.cAuxBuffers 
= (BYTE
)attribList
[arg
++]; 
 433           pfd
.cColorBits 
= (BYTE
)(pfd
.cColorBits 
+ (pfd
.cRedBits 
= (BYTE
)attribList
[arg
++])); 
 435         case WX_GL_MIN_GREEN
: 
 436           pfd
.cColorBits 
= (BYTE
)(pfd
.cColorBits 
+ (pfd
.cGreenBits 
= (BYTE
)attribList
[arg
++])); 
 439           pfd
.cColorBits 
= (BYTE
)(pfd
.cColorBits 
+ (pfd
.cBlueBits 
= (BYTE
)attribList
[arg
++])); 
 441         case WX_GL_MIN_ALPHA
: 
 442           // doesn't count in cColorBits 
 443           pfd
.cAlphaBits 
= (BYTE
)attribList
[arg
++]; 
 445         case WX_GL_DEPTH_SIZE
: 
 446           pfd
.cDepthBits 
= (BYTE
)attribList
[arg
++]; 
 448         case WX_GL_STENCIL_SIZE
: 
 449           pfd
.cStencilBits 
= (BYTE
)attribList
[arg
++]; 
 451         case WX_GL_MIN_ACCUM_RED
: 
 452           pfd
.cAccumBits 
= (BYTE
)(pfd
.cAccumBits 
+ (pfd
.cAccumRedBits 
= (BYTE
)attribList
[arg
++])); 
 454         case WX_GL_MIN_ACCUM_GREEN
: 
 455           pfd
.cAccumBits 
= (BYTE
)(pfd
.cAccumBits 
+ (pfd
.cAccumGreenBits 
= (BYTE
)attribList
[arg
++])); 
 457         case WX_GL_MIN_ACCUM_BLUE
: 
 458           pfd
.cAccumBits 
= (BYTE
)(pfd
.cAccumBits 
+ (pfd
.cAccumBlueBits 
= (BYTE
)attribList
[arg
++])); 
 460         case WX_GL_MIN_ACCUM_ALPHA
: 
 461           pfd
.cAccumBits 
= (BYTE
)(pfd
.cAccumBits 
+ (pfd
.cAccumAlphaBits 
= (BYTE
)attribList
[arg
++])); 
 470 void wxGLCanvas::SetupPixelFormat(int *attribList
) // (HDC hDC) 
 472   PIXELFORMATDESCRIPTOR pfd 
= { 
 473         sizeof(PIXELFORMATDESCRIPTOR
),    /* size */ 
 477         PFD_DOUBLEBUFFER
,        /* support double-buffering */ 
 478         PFD_TYPE_RGBA
,            /* color type */ 
 479         16,                /* preferred color depth */ 
 480         0, 0, 0, 0, 0, 0,        /* color bits (ignored) */ 
 481         0,                /* no alpha buffer */ 
 482         0,                /* alpha bits (ignored) */ 
 483         0,                /* no accumulation buffer */ 
 484         0, 0, 0, 0,            /* accum bits (ignored) */ 
 485         16,                /* depth buffer */ 
 486         0,                /* no stencil buffer */ 
 487         0,                /* no auxiliary buffers */ 
 488         PFD_MAIN_PLANE
,            /* main layer */ 
 490         0, 0, 0,            /* no layer, visible, damage masks */ 
 493   AdjustPFDForAttributes(pfd
, attribList
); 
 495   int pixelFormat 
= ChoosePixelFormat((HDC
) m_hDC
, &pfd
); 
 496   if (pixelFormat 
== 0) { 
 497     wxLogLastError(_T("ChoosePixelFormat")); 
 500     if ( !::SetPixelFormat((HDC
) m_hDC
, pixelFormat
, &pfd
) ) { 
 501       wxLogLastError(_T("SetPixelFormat")); 
 506 void wxGLCanvas::SetupPalette(const wxPalette
& palette
) 
 508     int pixelFormat 
= GetPixelFormat((HDC
) m_hDC
); 
 509     PIXELFORMATDESCRIPTOR pfd
; 
 511     DescribePixelFormat((HDC
) m_hDC
, pixelFormat
, sizeof(PIXELFORMATDESCRIPTOR
), &pfd
); 
 513     if (pfd
.dwFlags 
& PFD_NEED_PALETTE
) 
 523     if ( !m_palette
.Ok() ) 
 525         m_palette 
= CreateDefaultPalette(); 
 530         ::SelectPalette((HDC
) m_hDC
, (HPALETTE
) m_palette
.GetHPALETTE(), FALSE
); 
 531         ::RealizePalette((HDC
) m_hDC
); 
 535 wxPalette 
wxGLCanvas::CreateDefaultPalette() 
 537     PIXELFORMATDESCRIPTOR pfd
; 
 539     int pixelFormat 
= GetPixelFormat((HDC
) m_hDC
); 
 541     DescribePixelFormat((HDC
) m_hDC
, pixelFormat
, sizeof(PIXELFORMATDESCRIPTOR
), &pfd
); 
 543     paletteSize 
= 1 << pfd
.cColorBits
; 
 546      (LOGPALETTE
*) malloc(sizeof(LOGPALETTE
) + paletteSize 
* sizeof(PALETTEENTRY
)); 
 547     pPal
->palVersion 
= 0x300; 
 548     pPal
->palNumEntries 
= (WORD
)paletteSize
; 
 550     /* build a simple RGB color palette */ 
 552     int redMask 
= (1 << pfd
.cRedBits
) - 1; 
 553     int greenMask 
= (1 << pfd
.cGreenBits
) - 1; 
 554     int blueMask 
= (1 << pfd
.cBlueBits
) - 1; 
 557     for (i
=0; i
<paletteSize
; ++i
) { 
 558         pPal
->palPalEntry
[i
].peRed 
= 
 559             (BYTE
)((((i 
>> pfd
.cRedShift
) & redMask
) * 255) / redMask
); 
 560         pPal
->palPalEntry
[i
].peGreen 
= 
 561             (BYTE
)((((i 
>> pfd
.cGreenShift
) & greenMask
) * 255) / greenMask
); 
 562         pPal
->palPalEntry
[i
].peBlue 
= 
 563             (BYTE
)((((i 
>> pfd
.cBlueShift
) & blueMask
) * 255) / blueMask
); 
 564         pPal
->palPalEntry
[i
].peFlags 
= 0; 
 568     HPALETTE hPalette 
= CreatePalette(pPal
); 
 572     palette
.SetHPALETTE((WXHPALETTE
) hPalette
); 
 577 void wxGLCanvas::SwapBuffers() 
 580     m_glContext
->SwapBuffers(); 
 583 void wxGLCanvas::OnSize(wxSizeEvent
& WXUNUSED(event
)) 
 587 void wxGLCanvas::SetCurrent() 
 591     m_glContext
->SetCurrent(); 
 595 void wxGLCanvas::SetColour(const wxChar 
*colour
) 
 598     m_glContext
->SetColour(colour
); 
 601 // TODO: Have to have this called by parent frame (?) 
 602 // So we need wxFrame to call OnQueryNewPalette for all children... 
 603 void wxGLCanvas::OnQueryNewPalette(wxQueryNewPaletteEvent
& event
) 
 605   /* realize palette if this is the current window */ 
 606   if ( GetPalette()->Ok() ) { 
 607     ::UnrealizeObject((HPALETTE
) GetPalette()->GetHPALETTE()); 
 608     ::SelectPalette((HDC
) GetHDC(), (HPALETTE
) GetPalette()->GetHPALETTE(), FALSE
); 
 609     ::RealizePalette((HDC
) GetHDC()); 
 611     event
.SetPaletteRealized(true); 
 614     event
.SetPaletteRealized(false); 
 617 // I think this doesn't have to be propagated to child windows. 
 618 void wxGLCanvas::OnPaletteChanged(wxPaletteChangedEvent
& event
) 
 620   /* realize palette if this is *not* the current window */ 
 622        GetPalette()->Ok() && (this != event
.GetChangedWindow()) ) 
 624     ::UnrealizeObject((HPALETTE
) GetPalette()->GetHPALETTE()); 
 625     ::SelectPalette((HDC
) GetHDC(), (HPALETTE
) GetPalette()->GetHPALETTE(), FALSE
); 
 626     ::RealizePalette((HDC
) GetHDC()); 
 631 /* Give extensions proper function names. */ 
 633 /* EXT_vertex_array */ 
 634 void glArrayElementEXT(GLint 
WXUNUSED(i
)) 
 638 void glColorPointerEXT(GLint 
WXUNUSED(size
), GLenum 
WXUNUSED(type
), GLsizei 
WXUNUSED(stride
), GLsizei 
WXUNUSED(count
), const GLvoid 
*WXUNUSED(pointer
)) 
 642 void glDrawArraysEXT(GLenum  
WXUNUSED_WITHOUT_GL_EXT_vertex_array(mode
), 
 643                      GLint   
WXUNUSED_WITHOUT_GL_EXT_vertex_array(first
), 
 644                      GLsizei 
WXUNUSED_WITHOUT_GL_EXT_vertex_array(count
)) 
 646 #ifdef GL_EXT_vertex_array 
 647     static PFNGLDRAWARRAYSEXTPROC proc 
= 0; 
 651         proc 
= (PFNGLDRAWARRAYSEXTPROC
) wglGetProcAddress("glDrawArraysEXT"); 
 655         (* proc
) (mode
, first
, count
); 
 659 void glEdgeFlagPointerEXT(GLsizei 
WXUNUSED(stride
), GLsizei 
WXUNUSED(count
), const GLboolean 
*WXUNUSED(pointer
)) 
 663 void glGetPointervEXT(GLenum 
WXUNUSED(pname
), GLvoid
* *WXUNUSED(params
)) 
 667 void glIndexPointerEXT(GLenum 
WXUNUSED(type
), GLsizei 
WXUNUSED(stride
), GLsizei 
WXUNUSED(count
), const GLvoid 
*WXUNUSED(pointer
)) 
 671 void glNormalPointerEXT(GLenum        
WXUNUSED_WITHOUT_GL_EXT_vertex_array(type
), 
 672                         GLsizei       
WXUNUSED_WITHOUT_GL_EXT_vertex_array(stride
), 
 673                         GLsizei       
WXUNUSED_WITHOUT_GL_EXT_vertex_array(count
), 
 674                         const GLvoid 
*WXUNUSED_WITHOUT_GL_EXT_vertex_array(pointer
)) 
 676 #ifdef GL_EXT_vertex_array 
 677   static PFNGLNORMALPOINTEREXTPROC proc 
= 0; 
 681     proc 
= (PFNGLNORMALPOINTEREXTPROC
) wglGetProcAddress("glNormalPointerEXT"); 
 685     (* proc
) (type
, stride
, count
, pointer
); 
 689 void glTexCoordPointerEXT(GLint 
WXUNUSED(size
), GLenum 
WXUNUSED(type
), GLsizei 
WXUNUSED(stride
), GLsizei 
WXUNUSED(count
), const GLvoid 
*WXUNUSED(pointer
)) 
 693 void glVertexPointerEXT(GLint         
WXUNUSED_WITHOUT_GL_EXT_vertex_array(size
), 
 694                         GLenum        
WXUNUSED_WITHOUT_GL_EXT_vertex_array(type
), 
 695                         GLsizei       
WXUNUSED_WITHOUT_GL_EXT_vertex_array(stride
), 
 696                         GLsizei       
WXUNUSED_WITHOUT_GL_EXT_vertex_array(count
), 
 697                         const GLvoid 
*WXUNUSED_WITHOUT_GL_EXT_vertex_array(pointer
)) 
 699 #ifdef GL_EXT_vertex_array 
 700   static PFNGLVERTEXPOINTEREXTPROC proc 
= 0; 
 704     proc 
= (PFNGLVERTEXPOINTEREXTPROC
) wglGetProcAddress("glVertexPointerEXT"); 
 707     (* proc
) (size
, type
, stride
, count
, pointer
); 
 711 /* EXT_color_subtable */ 
 712 void glColorSubtableEXT(GLenum 
WXUNUSED(target
), GLsizei 
WXUNUSED(start
), GLsizei 
WXUNUSED(count
), GLenum 
WXUNUSED(format
), GLenum 
WXUNUSED(type
), const GLvoid 
*WXUNUSED(table
)) 
 716 /* EXT_color_table */ 
 717 void glColorTableEXT(GLenum 
WXUNUSED(target
), GLenum 
WXUNUSED(internalformat
), GLsizei 
WXUNUSED(width
), GLenum 
WXUNUSED(format
), GLenum 
WXUNUSED(type
), const GLvoid 
*WXUNUSED(table
)) 
 721 void glCopyColorTableEXT(GLenum 
WXUNUSED(target
), GLenum 
WXUNUSED(internalformat
), GLint 
WXUNUSED(x
), GLint 
WXUNUSED(y
), GLsizei 
WXUNUSED(width
)) 
 725 void glGetColorTableEXT(GLenum 
WXUNUSED(target
), GLenum 
WXUNUSED(format
), GLenum 
WXUNUSED(type
), GLvoid 
*WXUNUSED(table
)) 
 729 void glGetColorTableParamaterfvEXT(GLenum 
WXUNUSED(target
), GLenum 
WXUNUSED(pname
), GLfloat 
*WXUNUSED(params
)) 
 733 void glGetColorTavleParameterivEXT(GLenum 
WXUNUSED(target
), GLenum 
WXUNUSED(pname
), GLint 
*WXUNUSED(params
)) 
 737 /* SGI_compiled_vertex_array */ 
 738 void glLockArraysSGI(GLint 
WXUNUSED(first
), GLsizei 
WXUNUSED(count
)) 
 742 void glUnlockArraysSGI() 
 747 /* SGI_cull_vertex */ 
 748 void glCullParameterdvSGI(GLenum 
WXUNUSED(pname
), GLdouble
* WXUNUSED(params
)) 
 752 void glCullParameterfvSGI(GLenum 
WXUNUSED(pname
), GLfloat
* WXUNUSED(params
)) 
 757 void glIndexFuncSGI(GLenum 
WXUNUSED(func
), GLclampf 
WXUNUSED(ref
)) 
 761 /* SGI_index_material */ 
 762 void glIndexMaterialSGI(GLenum 
WXUNUSED(face
), GLenum 
WXUNUSED(mode
)) 
 767 void glAddSwapHintRectWin(GLint 
WXUNUSED(x
), GLint 
WXUNUSED(y
), GLsizei 
WXUNUSED(width
), GLsizei 
WXUNUSED(height
)) 
 772 //--------------------------------------------------------------------------- 
 774 //--------------------------------------------------------------------------- 
 776 IMPLEMENT_CLASS(wxGLApp
, wxApp
) 
 778 bool wxGLApp::InitGLVisual(int *attribList
) 
 781   PIXELFORMATDESCRIPTOR pfd 
= { 
 782         sizeof(PIXELFORMATDESCRIPTOR
),    /* size */ 
 786         PFD_DOUBLEBUFFER
,        /* support double-buffering */ 
 787         PFD_TYPE_RGBA
,            /* color type */ 
 788         16,                /* preferred color depth */ 
 789         0, 0, 0, 0, 0, 0,        /* color bits (ignored) */ 
 790         0,                /* no alpha buffer */ 
 791         0,                /* alpha bits (ignored) */ 
 792         0,                /* no accumulation buffer */ 
 793         0, 0, 0, 0,            /* accum bits (ignored) */ 
 794         16,                /* depth buffer */ 
 795         0,                /* no stencil buffer */ 
 796         0,                /* no auxiliary buffers */ 
 797         PFD_MAIN_PLANE
,            /* main layer */ 
 799         0, 0, 0,            /* no layer, visible, damage masks */ 
 802   AdjustPFDForAttributes(pfd
, attribList
); 
 804   // use DC for whole (root) screen, since no windows have yet been created 
 805   pixelFormat 
= ChoosePixelFormat(ScreenHDC(), &pfd
); 
 807   if (pixelFormat 
== 0) { 
 808     wxLogError(_("Failed to initialize OpenGL"));