1 ///////////////////////////////////////////////////////////////////////////// 
   3 // Purpose:     wxGLCanvas, for using OpenGL with wxWindows under MS Windows 
   4 // Author:      Julian Smart 
   8 // Copyright:   (c) Julian Smart 
   9 // Licence:       wxWindows licence 
  10 ///////////////////////////////////////////////////////////////////////////// 
  13 #pragma implementation "glcanvas.h" 
  16 #include "wx/wxprec.h" 
  18 #if defined(__BORLANDC__) 
  30 #include <wx/msw/private.h> 
  31 #include <wx/settings.h> 
  34 #include <wx/glcanvas.h> 
  36 static const wxChar 
*wxGLCanvasClassName 
= wxT("wxGLCanvasClass"); 
  37 static const wxChar 
*wxGLCanvasClassNameNoRedraw 
= wxT("wxGLCanvasClassNR"); 
  39 LRESULT WXDLLEXPORT APIENTRY _EXPORT 
wxWndProc(HWND hWnd
, UINT message
, 
  40                                    WPARAM wParam
, LPARAM lParam
); 
  43  * GLContext implementation 
  46 wxGLContext::wxGLContext(bool isRGB
, wxGLCanvas 
*win
, const wxPalette
& palette
) 
  50   m_hDC 
= win
->GetHDC(); 
  52   m_glContext 
= wglCreateContext((HDC
) m_hDC
); 
  53   wxCHECK_RET( m_glContext
, wxT("Couldn't create OpenGl context") ); 
  55   wglMakeCurrent((HDC
) m_hDC
, m_glContext
); 
  58 wxGLContext::wxGLContext( 
  59                bool isRGB
, wxGLCanvas 
*win
, 
  60                const wxPalette
& palette
, 
  61                const wxGLContext 
*other  
/* for sharing display lists */ 
  66   m_hDC 
= win
->GetHDC(); 
  68   m_glContext 
= wglCreateContext((HDC
) m_hDC
); 
  69   wxCHECK_RET( m_glContext
, wxT("Couldn't create OpenGl context") ); 
  72     wglShareLists( other
->m_glContext
, m_glContext 
); 
  74   wglMakeCurrent((HDC
) m_hDC
, m_glContext
); 
  77 wxGLContext::~wxGLContext() 
  81     wglMakeCurrent(NULL
, NULL
); 
  82     wglDeleteContext(m_glContext
); 
  86 void wxGLContext::SwapBuffers() 
  90     wglMakeCurrent((HDC
) m_hDC
, m_glContext
); 
  91     ::SwapBuffers((HDC
) m_hDC
);    //blits the backbuffer into DC 
  95 void wxGLContext::SetCurrent() 
  99     wglMakeCurrent((HDC
) m_hDC
, m_glContext
); 
 103   setupPixelFormat(hDC); 
 108 void wxGLContext::SetColour(const char *colour
) 
 113   wxColour 
*col 
= wxTheColourDatabase
->FindColour(colour
); 
 116     r 
= (float)(col
->Red()/256.0); 
 117     g 
= (float)(col
->Green()/256.0); 
 118     b 
= (float)(col
->Blue()/256.0); 
 125  * wxGLCanvas implementation 
 128 IMPLEMENT_CLASS(wxGLCanvas
, wxScrolledWindow
) 
 130 BEGIN_EVENT_TABLE(wxGLCanvas
, wxScrolledWindow
) 
 131     EVT_SIZE(wxGLCanvas::OnSize
) 
 132     EVT_PALETTE_CHANGED(wxGLCanvas::OnPaletteChanged
) 
 133     EVT_QUERY_NEW_PALETTE(wxGLCanvas::OnQueryNewPalette
) 
 136 wxGLCanvas::wxGLCanvas(wxWindow 
*parent
, wxWindowID id
, 
 137     const wxPoint
& pos
, const wxSize
& size
, long style
, const wxString
& name
, 
 138     int *attribList
, const wxPalette
& palette
) : wxScrolledWindow() 
 140   m_glContext 
= (wxGLContext
*) NULL
; 
 142   bool ret 
= Create(parent
, id
, pos
, size
, style
, name
); 
 146     SetBackgroundColour(wxSystemSettings::GetSystemColour(wxSYS_COLOUR_3DFACE
)); 
 147     SetFont(wxSystemSettings::GetSystemFont(wxSYS_DEFAULT_GUI_FONT
)); 
 150   m_hDC 
= (WXHDC
) ::GetDC((HWND
) GetHWND()); 
 152   SetupPixelFormat(attribList
); 
 153   SetupPalette(palette
); 
 155   m_glContext 
= new wxGLContext(TRUE
, this, palette
); 
 158 wxGLCanvas::wxGLCanvas( wxWindow 
*parent
, 
 159               const wxGLContext 
*shared
, wxWindowID id
, 
 160               const wxPoint
& pos
, const wxSize
& size
, long style
, const wxString
& name
, 
 161               int *attribList
, const wxPalette
& palette 
) 
 164   m_glContext 
= (wxGLContext
*) NULL
; 
 166   bool ret 
= Create(parent
, id
, pos
, size
, style
, name
); 
 170     SetBackgroundColour(wxSystemSettings::GetSystemColour(wxSYS_COLOUR_3DFACE
)); 
 171     SetFont(wxSystemSettings::GetSystemFont(wxSYS_DEFAULT_GUI_FONT
)); 
 174   m_hDC 
= (WXHDC
) ::GetDC((HWND
) GetHWND()); 
 176   SetupPixelFormat(attribList
); 
 177   SetupPalette(palette
); 
 179   m_glContext 
= new wxGLContext(TRUE
, this, palette
, shared 
); 
 182 // Not very useful for wxMSW, but this is to be wxGTK compliant 
 184 wxGLCanvas::wxGLCanvas( wxWindow 
*parent
, const wxGLCanvas 
*shared
, wxWindowID id
, 
 185                         const wxPoint
& pos
, const wxSize
& size
, long style
, const wxString
& name
, 
 186                         int *attribList
, const wxPalette
& palette 
): 
 189   m_glContext 
= (wxGLContext
*) NULL
; 
 191   bool ret 
= Create(parent
, id
, pos
, size
, style
, name
); 
 195     SetBackgroundColour(wxSystemSettings::GetSystemColour(wxSYS_COLOUR_3DFACE
)); 
 196     SetFont(wxSystemSettings::GetSystemFont(wxSYS_DEFAULT_GUI_FONT
)); 
 199   m_hDC 
= (WXHDC
) ::GetDC((HWND
) GetHWND()); 
 201   SetupPixelFormat(attribList
); 
 202   SetupPalette(palette
); 
 204   wxGLContext 
*sharedContext
=0; 
 205   if (shared
) sharedContext
=shared
->GetContext(); 
 206   m_glContext 
= new wxGLContext(TRUE
, this, palette
, sharedContext 
); 
 209 wxGLCanvas::~wxGLCanvas() 
 214   ::ReleaseDC((HWND
) GetHWND(), (HDC
) m_hDC
); 
 217 // Replaces wxWindow::Create functionality, since we need to use a different 
 219 bool wxGLCanvas::Create(wxWindow 
*parent
, 
 224                         const wxString
& name
) 
 226   static bool s_registeredGLCanvasClass 
= FALSE
; 
 228   // We have to register a special window class because we need 
 229   // the CS_OWNDC style for GLCanvas. 
 232   From Angel Popov <jumpo@bitex.com> 
 234   Here are two snips from a dicussion in the OpenGL Gamedev list that explains 
 235   how this problem can be fixed: 
 237   "There are 5 common DCs available in Win95. These are aquired when you call 
 238   GetDC or GetDCEx from a window that does _not_ have the OWNDC flag. 
 239   OWNDC flagged windows do not get their DC from the common DC pool, the issue 
 240   is they require 800 bytes each from the limited 64Kb local heap for GDI." 
 242   "The deal is, if you hold onto one of the 5 shared DC's too long (as GL apps 
 243   do), Win95 will actually "steal" it from you.  MakeCurrent fails, 
 244   apparently, because Windows re-assigns the HDC to a different window.  The 
 245   only way to prevent this, the only reliable means, is to set CS_OWNDC." 
 248   if (!s_registeredGLCanvasClass
) 
 252     // the fields which are common to all classes 
 253     wndclass
.lpfnWndProc   
= (WNDPROC
)wxWndProc
; 
 254     wndclass
.cbClsExtra    
= 0; 
 255     wndclass
.cbWndExtra    
= sizeof( DWORD 
); // VZ: what is this DWORD used for? 
 256     wndclass
.hInstance     
= wxhInstance
; 
 257     wndclass
.hIcon         
= (HICON
) NULL
; 
 258     wndclass
.hCursor       
= ::LoadCursor((HINSTANCE
)NULL
, IDC_ARROW
); 
 259     wndclass
.lpszMenuName  
= NULL
; 
 261     // Register the GLCanvas class name 
 262     wndclass
.hbrBackground 
= (HBRUSH
)NULL
; 
 263     wndclass
.lpszClassName 
= wxGLCanvasClassName
; 
 264     wndclass
.style         
= CS_HREDRAW 
| CS_VREDRAW 
| CS_DBLCLKS 
| CS_OWNDC
; 
 266     if ( !::RegisterClass(&wndclass
) ) 
 268       wxLogLastError(wxT("RegisterClass(wxGLCanvasClass)")); 
 272     // Register the GLCanvas class name for windows which don't do full repaint 
 274     wndclass
.lpszClassName 
= wxGLCanvasClassNameNoRedraw
; 
 275     wndclass
.style        
&= ~(CS_HREDRAW 
| CS_VREDRAW
); 
 277     if ( !::RegisterClass(&wndclass
) ) 
 279         wxLogLastError(wxT("RegisterClass(wxGLCanvasClassNameNoRedraw)")); 
 281         ::UnregisterClass(wxGLCanvasClassName
, wxhInstance()); 
 286     s_registeredGLCanvasClass 
= TRUE
; 
 289   wxCHECK_MSG( parent
, FALSE
, wxT("can't create wxWindow without parent") ); 
 291   if ( !CreateBase(parent
, id
, pos
, size
, style
, wxDefaultValidator
, name
) ) 
 294   parent
->AddChild(this); 
 297   if ( style 
& wxBORDER 
) 
 298     msflags 
|= WS_BORDER
; 
 299   if ( style 
& wxTHICK_FRAME 
) 
 300     msflags 
|= WS_THICKFRAME
; 
 303   A general rule with OpenGL and Win32 is that any window that will have a 
 304   HGLRC built for it must have two flags:  WS_CLIPCHILDREN & WS_CLIPSIBLINGS. 
 305   You can find references about this within the knowledge base and most OpenGL 
 306   books that contain the wgl function descriptions. 
 309   msflags 
|= WS_CHILD 
| WS_VISIBLE 
| WS_CLIPSIBLINGS 
| WS_CLIPCHILDREN
; 
 312   WXDWORD exStyle 
= Determine3DEffects(WS_EX_CLIENTEDGE
, &want3D
); 
 314   // Even with extended styles, need to combine with WS_BORDER 
 315   // for them to look right. 
 316   if ( want3D 
|| (m_windowStyle 
& wxSIMPLE_BORDER
) || (m_windowStyle 
& wxRAISED_BORDER 
) || 
 317        (m_windowStyle 
& wxSUNKEN_BORDER
) || (m_windowStyle 
& wxDOUBLE_BORDER
)) 
 319     msflags 
|= WS_BORDER
; 
 322   // calculate the value to return from WM_GETDLGCODE handler 
 323   if ( GetWindowStyleFlag() & wxWANTS_CHARS 
) 
 325     // want everything: i.e. all keys and WM_CHAR message 
 326     m_lDlgCode 
= DLGC_WANTARROWS 
| DLGC_WANTCHARS 
| 
 327                  DLGC_WANTTAB 
| DLGC_WANTMESSAGE
; 
 330   return MSWCreate(wxGLCanvasClassName
, NULL
, pos
, size
, msflags
, exStyle
); 
 333 static void AdjustPFDForAttributes(PIXELFORMATDESCRIPTOR
& pfd
, int *attribList
) 
 336     pfd
.dwFlags 
&= ~PFD_DOUBLEBUFFER
; 
 337     pfd
.iPixelType 
= PFD_TYPE_COLORINDEX
; 
 341     while( (attribList
[arg
]!=0) ) 
 343       switch( attribList
[arg
++] ) 
 346           pfd
.iPixelType 
= PFD_TYPE_RGBA
; 
 348         case WX_GL_BUFFER_SIZE
: 
 349           pfd
.cColorBits 
= attribList
[arg
++]; 
 352           // this member looks like it may be obsolete 
 353           if (attribList
[arg
] > 0) { 
 354             pfd
.iLayerType 
= PFD_OVERLAY_PLANE
; 
 355           } else if (attribList
[arg
] < 0) { 
 356             pfd
.iLayerType 
= PFD_UNDERLAY_PLANE
; 
 358             pfd
.iLayerType 
= PFD_MAIN_PLANE
; 
 362         case WX_GL_DOUBLEBUFFER
: 
 363           pfd
.dwFlags 
|= PFD_DOUBLEBUFFER
; 
 366           pfd
.dwFlags 
|= PFD_STEREO
; 
 368         case WX_GL_AUX_BUFFERS
: 
 369           pfd
.cAuxBuffers 
= attribList
[arg
++]; 
 372           pfd
.cColorBits 
+= (pfd
.cRedBits 
= attribList
[arg
++]); 
 374         case WX_GL_MIN_GREEN
: 
 375           pfd
.cColorBits 
+= (pfd
.cGreenBits 
= attribList
[arg
++]); 
 378           pfd
.cColorBits 
+= (pfd
.cBlueBits 
= attribList
[arg
++]); 
 380         case WX_GL_MIN_ALPHA
: 
 381           // doesn't count in cColorBits 
 382           pfd
.cAlphaBits 
= attribList
[arg
++]; 
 384         case WX_GL_DEPTH_SIZE
: 
 385           pfd
.cDepthBits 
= attribList
[arg
++]; 
 387         case WX_GL_STENCIL_SIZE
: 
 388           pfd
.cStencilBits 
= attribList
[arg
++]; 
 390         case WX_GL_MIN_ACCUM_RED
: 
 391           pfd
.cAccumBits 
+= (pfd
.cAccumRedBits 
= attribList
[arg
++]); 
 393         case WX_GL_MIN_ACCUM_GREEN
: 
 394           pfd
.cAccumBits 
+= (pfd
.cAccumGreenBits 
= attribList
[arg
++]); 
 396         case WX_GL_MIN_ACCUM_BLUE
: 
 397           pfd
.cAccumBits 
+= (pfd
.cAccumBlueBits 
= attribList
[arg
++]); 
 399         case WX_GL_MIN_ACCUM_ALPHA
: 
 400           pfd
.cAccumBits 
+= (pfd
.cAccumAlphaBits 
= attribList
[arg
++]); 
 409 void wxGLCanvas::SetupPixelFormat(int *attribList
) // (HDC hDC) 
 412   PIXELFORMATDESCRIPTOR pfd 
= { 
 413         sizeof(PIXELFORMATDESCRIPTOR
),    /* size */ 
 417         PFD_DOUBLEBUFFER
,        /* support double-buffering */ 
 418         PFD_TYPE_RGBA
,            /* color type */ 
 419         16,                /* prefered color depth */ 
 420         0, 0, 0, 0, 0, 0,        /* color bits (ignored) */ 
 421         0,                /* no alpha buffer */ 
 422         0,                /* alpha bits (ignored) */ 
 423         0,                /* no accumulation buffer */ 
 424         0, 0, 0, 0,            /* accum bits (ignored) */ 
 425         16,                /* depth buffer */ 
 426         0,                /* no stencil buffer */ 
 427         0,                /* no auxiliary buffers */ 
 428         PFD_MAIN_PLANE
,            /* main layer */ 
 430         0, 0, 0,            /* no layer, visible, damage masks */ 
 433   AdjustPFDForAttributes(pfd
, attribList
); 
 435   pixelFormat 
= ChoosePixelFormat((HDC
) m_hDC
, &pfd
); 
 436   if (pixelFormat 
== 0) { 
 437     wxLogWarning(_("ChoosePixelFormat failed.")); 
 440     if (SetPixelFormat((HDC
) m_hDC
, pixelFormat
, &pfd
) != TRUE
) { 
 441       wxLogWarning(_("SetPixelFormat failed.")); 
 446 void wxGLCanvas::SetupPalette(const wxPalette
& palette
) 
 448     int pixelFormat 
= GetPixelFormat((HDC
) m_hDC
); 
 449     PIXELFORMATDESCRIPTOR pfd
; 
 451     DescribePixelFormat((HDC
) m_hDC
, pixelFormat
, sizeof(PIXELFORMATDESCRIPTOR
), &pfd
); 
 453     if (pfd
.dwFlags 
& PFD_NEED_PALETTE
) 
 463     if ( !m_palette
.Ok() ) 
 465         m_palette 
= CreateDefaultPalette(); 
 470         SelectPalette((HDC
) m_hDC
, (HPALETTE
) m_palette
.GetHPALETTE(), FALSE
); 
 471         RealizePalette((HDC
) m_hDC
); 
 475 wxPalette 
wxGLCanvas::CreateDefaultPalette() 
 477     PIXELFORMATDESCRIPTOR pfd
; 
 479     int pixelFormat 
= GetPixelFormat((HDC
) m_hDC
); 
 481     DescribePixelFormat((HDC
) m_hDC
, pixelFormat
, sizeof(PIXELFORMATDESCRIPTOR
), &pfd
); 
 483     paletteSize 
= 1 << pfd
.cColorBits
; 
 486      (LOGPALETTE
*) malloc(sizeof(LOGPALETTE
) + paletteSize 
* sizeof(PALETTEENTRY
)); 
 487     pPal
->palVersion 
= 0x300; 
 488     pPal
->palNumEntries 
= paletteSize
; 
 490     /* build a simple RGB color palette */ 
 492     int redMask 
= (1 << pfd
.cRedBits
) - 1; 
 493     int greenMask 
= (1 << pfd
.cGreenBits
) - 1; 
 494     int blueMask 
= (1 << pfd
.cBlueBits
) - 1; 
 497     for (i
=0; i
<paletteSize
; ++i
) { 
 498         pPal
->palPalEntry
[i
].peRed 
= 
 499             (((i 
>> pfd
.cRedShift
) & redMask
) * 255) / redMask
; 
 500         pPal
->palPalEntry
[i
].peGreen 
= 
 501             (((i 
>> pfd
.cGreenShift
) & greenMask
) * 255) / greenMask
; 
 502         pPal
->palPalEntry
[i
].peBlue 
= 
 503             (((i 
>> pfd
.cBlueShift
) & blueMask
) * 255) / blueMask
; 
 504         pPal
->palPalEntry
[i
].peFlags 
= 0; 
 508     HPALETTE hPalette 
= CreatePalette(pPal
); 
 512     palette
.SetHPALETTE((WXHPALETTE
) hPalette
); 
 517 void wxGLCanvas::SwapBuffers() 
 520     m_glContext
->SwapBuffers(); 
 523 void wxGLCanvas::OnSize(wxSizeEvent
& event
) 
 526   GetClientSize(& width
, & height
); 
 530     m_glContext
->SetCurrent(); 
 532     glViewport(0, 0, (GLint
)width
, (GLint
)height
); 
 533     glMatrixMode(GL_PROJECTION
); 
 535     glFrustum( -1.0, 1.0, -1.0, 1.0, 5.0, 15.0 ); 
 536     glMatrixMode(GL_MODELVIEW
); 
 540 void wxGLCanvas::SetCurrent() 
 544     m_glContext
->SetCurrent(); 
 548 void wxGLCanvas::SetColour(const char *colour
) 
 551     m_glContext
->SetColour(colour
); 
 554 // TODO: Have to have this called by parent frame (?) 
 555 // So we need wxFrame to call OnQueryNewPalette for all children... 
 556 void wxGLCanvas::OnQueryNewPalette(wxQueryNewPaletteEvent
& event
) 
 558   /* realize palette if this is the current window */ 
 559   if ( GetPalette()->Ok() ) { 
 560     ::UnrealizeObject((HPALETTE
) GetPalette()->GetHPALETTE()); 
 561     ::SelectPalette((HDC
) GetHDC(), (HPALETTE
) GetPalette()->GetHPALETTE(), FALSE
); 
 562     ::RealizePalette((HDC
) GetHDC()); 
 564     event
.SetPaletteRealized(TRUE
); 
 567     event
.SetPaletteRealized(FALSE
); 
 570 // I think this doesn't have to be propagated to child windows. 
 571 void wxGLCanvas::OnPaletteChanged(wxPaletteChangedEvent
& event
) 
 573   /* realize palette if this is *not* the current window */ 
 575        GetPalette()->Ok() && (this != event
.GetChangedWindow()) ) 
 577     ::UnrealizeObject((HPALETTE
) GetPalette()->GetHPALETTE()); 
 578     ::SelectPalette((HDC
) GetHDC(), (HPALETTE
) GetPalette()->GetHPALETTE(), FALSE
); 
 579     ::RealizePalette((HDC
) GetHDC()); 
 584 /* Give extensions proper function names. */ 
 586 /* EXT_vertex_array */ 
 587 void glArrayElementEXT(GLint i
) 
 591 void glColorPointerEXT(GLint size
, GLenum type
, GLsizei stride
, GLsizei count
, const GLvoid 
*pointer
) 
 595 void glDrawArraysEXT(GLenum mode
, GLint first
, GLsizei count
) 
 597 #ifdef GL_EXT_vertex_array 
 598     static PFNGLDRAWARRAYSEXTPROC proc 
= 0; 
 602         proc 
= (PFNGLDRAWARRAYSEXTPROC
) wglGetProcAddress("glDrawArraysEXT"); 
 606         (* proc
) (mode
, first
, count
); 
 610 void glEdgeFlagPointerEXT(GLsizei stride
, GLsizei count
, const GLboolean 
*pointer
) 
 614 void glGetPointervEXT(GLenum pname
, GLvoid
* *params
) 
 618 void glIndexPointerEXT(GLenum type
, GLsizei stride
, GLsizei count
, const GLvoid 
*pointer
) 
 622 void glNormalPointerEXT(GLenum type
, GLsizei stride
, GLsizei count
, const GLvoid 
*pointer
) 
 624 #ifdef GL_EXT_vertex_array 
 625   static PFNGLNORMALPOINTEREXTPROC proc 
= 0; 
 629     proc 
= (PFNGLNORMALPOINTEREXTPROC
) wglGetProcAddress("glNormalPointerEXT"); 
 633     (* proc
) (type
, stride
, count
, pointer
); 
 637 void glTexCoordPointerEXT(GLint size
, GLenum type
, GLsizei stride
, GLsizei count
, const GLvoid 
*pointer
) 
 641 void glVertexPointerEXT(GLint size
, GLenum type
, GLsizei stride
, GLsizei count
, const GLvoid 
*pointer
) 
 643 #ifdef GL_EXT_vertex_array 
 644   static PFNGLVERTEXPOINTEREXTPROC proc 
= 0; 
 648     proc 
= (PFNGLVERTEXPOINTEREXTPROC
) wglGetProcAddress("glVertexPointerEXT"); 
 651     (* proc
) (size
, type
, stride
, count
, pointer
); 
 655 /* EXT_color_subtable */ 
 656 void glColorSubtableEXT(GLenum target
, GLsizei start
, GLsizei count
, GLenum format
, GLenum type
, const GLvoid 
*table
) 
 660 /* EXT_color_table */ 
 661 void glColorTableEXT(GLenum target
, GLenum internalformat
, GLsizei width
, GLenum format
, GLenum type
, const GLvoid 
*table
) 
 665 void glCopyColorTableEXT(GLenum target
, GLenum internalformat
, GLint x
, GLint y
, GLsizei width
) 
 669 void glGetColorTableEXT(GLenum target
, GLenum format
, GLenum type
, GLvoid 
*table
) 
 673 void glGetColorTableParamaterfvEXT(GLenum target
, GLenum pname
, GLfloat 
*params
) 
 677 void glGetColorTavleParameterivEXT(GLenum target
, GLenum pname
, GLint 
*params
) 
 681 /* SGI_compiled_vertex_array */ 
 682 void glLockArraysSGI(GLint first
, GLsizei count
) 
 686 void glUnlockArraysSGI() 
 691 /* SGI_cull_vertex */ 
 692 void glCullParameterdvSGI(GLenum pname
, GLdouble
* params
) 
 696 void glCullParameterfvSGI(GLenum pname
, GLfloat
* params
) 
 701 void glIndexFuncSGI(GLenum func
, GLclampf ref
) 
 705 /* SGI_index_material */ 
 706 void glIndexMaterialSGI(GLenum face
, GLenum mode
) 
 711 void glAddSwapHintRectWin(GLint x
, GLint y
, GLsizei width
, GLsizei height
) 
 716 //--------------------------------------------------------------------------- 
 718 //--------------------------------------------------------------------------- 
 720 IMPLEMENT_CLASS(wxGLApp
, wxApp
) 
 722 bool wxGLApp::InitGLVisual(int *attribList
) 
 725   PIXELFORMATDESCRIPTOR pfd 
= { 
 726         sizeof(PIXELFORMATDESCRIPTOR
),    /* size */ 
 730         PFD_DOUBLEBUFFER
,        /* support double-buffering */ 
 731         PFD_TYPE_RGBA
,            /* color type */ 
 732         16,                /* prefered color depth */ 
 733         0, 0, 0, 0, 0, 0,        /* color bits (ignored) */ 
 734         0,                /* no alpha buffer */ 
 735         0,                /* alpha bits (ignored) */ 
 736         0,                /* no accumulation buffer */ 
 737         0, 0, 0, 0,            /* accum bits (ignored) */ 
 738         16,                /* depth buffer */ 
 739         0,                /* no stencil buffer */ 
 740         0,                /* no auxiliary buffers */ 
 741         PFD_MAIN_PLANE
,            /* main layer */ 
 743         0, 0, 0,            /* no layer, visible, damage masks */ 
 746   AdjustPFDForAttributes(pfd
, attribList
); 
 748   // use DC for whole (root) screen, since no windows have yet been created 
 749   pixelFormat 
= ChoosePixelFormat((HDC
) ::GetDC(NULL
), &pfd
); 
 751   if (pixelFormat 
== 0) { 
 752     wxLogError(_("Failed to initialize OpenGL"));