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__) 
  26 #define wxUSE_GLCANVAS 1 
  33 #include <wx/msw/private.h> 
  34 #include <wx/settings.h> 
  37 #include "myglcanvas.h" 
  39 static const wxChar 
*wxGLCanvasClassName 
= wxT("wxGLCanvasClass"); 
  40 static const wxChar 
*wxGLCanvasClassNameNoRedraw 
= wxT("wxGLCanvasClassNR"); 
  42 LRESULT WXDLLEXPORT APIENTRY _EXPORT 
wxWndProc(HWND hWnd
, UINT message
, 
  43                                    WPARAM wParam
, LPARAM lParam
); 
  46  * GLContext implementation 
  49 wxGLContext::wxGLContext(bool isRGB
, wxGLCanvas 
*win
, const wxPalette
& palette
) 
  53   m_hDC 
= win
->GetHDC(); 
  55   m_glContext 
= wglCreateContext((HDC
) m_hDC
); 
  56   wxCHECK_RET( m_glContext
, wxT("Couldn't create OpenGl context") ); 
  58   wglMakeCurrent((HDC
) m_hDC
, m_glContext
); 
  61 wxGLContext::wxGLContext( 
  62                bool isRGB
, wxGLCanvas 
*win
, 
  63                const wxPalette
& palette
, 
  64                const wxGLContext 
*other  
/* for sharing display lists */ 
  69   m_hDC 
= win
->GetHDC(); 
  71   m_glContext 
= wglCreateContext((HDC
) m_hDC
); 
  72   wxCHECK_RET( m_glContext
, wxT("Couldn't create OpenGl context") ); 
  75     wglShareLists( other
->m_glContext
, m_glContext 
); 
  77   wglMakeCurrent((HDC
) m_hDC
, m_glContext
); 
  80 wxGLContext::~wxGLContext() 
  84     wglMakeCurrent(NULL
, NULL
); 
  85     wglDeleteContext(m_glContext
); 
  89 void wxGLContext::SwapBuffers() 
  93     wglMakeCurrent((HDC
) m_hDC
, m_glContext
); 
  94     ::SwapBuffers((HDC
) m_hDC
);    //blits the backbuffer into DC 
  98 void wxGLContext::SetCurrent() 
 102     wglMakeCurrent((HDC
) m_hDC
, m_glContext
); 
 106   setupPixelFormat(hDC); 
 111 void wxGLContext::SetColour(const char *colour
) 
 116   wxColour 
*col 
= wxTheColourDatabase
->FindColour(colour
); 
 119     r 
= (float)(col
->Red()/256.0); 
 120     g 
= (float)(col
->Green()/256.0); 
 121     b 
= (float)(col
->Blue()/256.0); 
 128  * wxGLCanvas implementation 
 131 IMPLEMENT_CLASS(wxGLCanvas
, wxWindow
) 
 133 BEGIN_EVENT_TABLE(wxGLCanvas
, wxWindow
) 
 134     EVT_SIZE(wxGLCanvas::OnSize
) 
 135     EVT_PALETTE_CHANGED(wxGLCanvas::OnPaletteChanged
) 
 136     EVT_QUERY_NEW_PALETTE(wxGLCanvas::OnQueryNewPalette
) 
 139 wxGLCanvas::wxGLCanvas(wxWindow 
*parent
, wxWindowID id
, 
 140     const wxPoint
& pos
, const wxSize
& size
, long style
, const wxString
& name
, 
 141     int *attribList
, const wxPalette
& palette
) : wxWindow() 
 143   m_glContext 
= (wxGLContext
*) NULL
; 
 145   bool ret 
= Create(parent
, id
, pos
, size
, style
, name
); 
 149     SetBackgroundColour(wxSystemSettings::GetSystemColour(wxSYS_COLOUR_3DFACE
)); 
 150     SetFont(wxSystemSettings::GetSystemFont(wxSYS_DEFAULT_GUI_FONT
)); 
 153   m_hDC 
= (WXHDC
) ::GetDC((HWND
) GetHWND()); 
 155   SetupPixelFormat(attribList
); 
 156   SetupPalette(palette
); 
 158   m_glContext 
= new wxGLContext(TRUE
, this, palette
); 
 161 wxGLCanvas::wxGLCanvas( wxWindow 
*parent
, 
 162               const wxGLContext 
*shared
, wxWindowID id
, 
 163               const wxPoint
& pos
, const wxSize
& size
, long style
, const wxString
& name
, 
 164               int *attribList
, const wxPalette
& palette 
) 
 167   m_glContext 
= (wxGLContext
*) NULL
; 
 169   bool ret 
= Create(parent
, id
, pos
, size
, style
, name
); 
 173     SetBackgroundColour(wxSystemSettings::GetSystemColour(wxSYS_COLOUR_3DFACE
)); 
 174     SetFont(wxSystemSettings::GetSystemFont(wxSYS_DEFAULT_GUI_FONT
)); 
 177   m_hDC 
= (WXHDC
) ::GetDC((HWND
) GetHWND()); 
 179   SetupPixelFormat(attribList
); 
 180   SetupPalette(palette
); 
 182   m_glContext 
= new wxGLContext(TRUE
, this, palette
, shared 
); 
 185 // Not very useful for wxMSW, but this is to be wxGTK compliant 
 187 wxGLCanvas::wxGLCanvas( wxWindow 
*parent
, const wxGLCanvas 
*shared
, wxWindowID id
, 
 188                         const wxPoint
& pos
, const wxSize
& size
, long style
, const wxString
& name
, 
 189                         int *attribList
, const wxPalette
& palette 
): 
 192   m_glContext 
= (wxGLContext
*) NULL
; 
 194   bool ret 
= Create(parent
, id
, pos
, size
, style
, name
); 
 198     SetBackgroundColour(wxSystemSettings::GetSystemColour(wxSYS_COLOUR_3DFACE
)); 
 199     SetFont(wxSystemSettings::GetSystemFont(wxSYS_DEFAULT_GUI_FONT
)); 
 202   m_hDC 
= (WXHDC
) ::GetDC((HWND
) GetHWND()); 
 204   SetupPixelFormat(attribList
); 
 205   SetupPalette(palette
); 
 207   wxGLContext 
*sharedContext
=0; 
 208   if (shared
) sharedContext
=shared
->GetContext(); 
 209   m_glContext 
= new wxGLContext(TRUE
, this, palette
, sharedContext 
); 
 212 wxGLCanvas::~wxGLCanvas() 
 217   ::ReleaseDC((HWND
) GetHWND(), (HDC
) m_hDC
); 
 220 // Replaces wxWindow::Create functionality, since we need to use a different 
 222 bool wxGLCanvas::Create(wxWindow 
*parent
, 
 227                         const wxString
& name
) 
 229   static bool s_registeredGLCanvasClass 
= FALSE
; 
 231   // We have to register a special window class because we need 
 232   // the CS_OWNDC style for GLCanvas. 
 235   From Angel Popov <jumpo@bitex.com> 
 237   Here are two snips from a dicussion in the OpenGL Gamedev list that explains 
 238   how this problem can be fixed: 
 240   "There are 5 common DCs available in Win95. These are aquired when you call 
 241   GetDC or GetDCEx from a window that does _not_ have the OWNDC flag. 
 242   OWNDC flagged windows do not get their DC from the common DC pool, the issue 
 243   is they require 800 bytes each from the limited 64Kb local heap for GDI." 
 245   "The deal is, if you hold onto one of the 5 shared DC's too long (as GL apps 
 246   do), Win95 will actually "steal" it from you.  MakeCurrent fails, 
 247   apparently, because Windows re-assigns the HDC to a different window.  The 
 248   only way to prevent this, the only reliable means, is to set CS_OWNDC." 
 251   if (!s_registeredGLCanvasClass
) 
 255     // the fields which are common to all classes 
 256     wndclass
.lpfnWndProc   
= (WNDPROC
)wxWndProc
; 
 257     wndclass
.cbClsExtra    
= 0; 
 258     wndclass
.cbWndExtra    
= sizeof( DWORD 
); // VZ: what is this DWORD used for? 
 259     wndclass
.hInstance     
= wxhInstance
; 
 260     wndclass
.hIcon         
= (HICON
) NULL
; 
 261     wndclass
.hCursor       
= ::LoadCursor((HINSTANCE
)NULL
, IDC_ARROW
); 
 262     wndclass
.lpszMenuName  
= NULL
; 
 264     // Register the GLCanvas class name 
 265     wndclass
.hbrBackground 
= (HBRUSH
)NULL
; 
 266     wndclass
.lpszClassName 
= wxGLCanvasClassName
; 
 267     wndclass
.style         
= CS_HREDRAW 
| CS_VREDRAW 
| CS_DBLCLKS 
| CS_OWNDC
; 
 269     if ( !::RegisterClass(&wndclass
) ) 
 271       wxLogLastError(wxT("RegisterClass(wxGLCanvasClass)")); 
 275     // Register the GLCanvas class name for windows which don't do full repaint 
 277     wndclass
.lpszClassName 
= wxGLCanvasClassNameNoRedraw
; 
 278     wndclass
.style        
&= ~(CS_HREDRAW 
| CS_VREDRAW
); 
 280     if ( !::RegisterClass(&wndclass
) ) 
 282         wxLogLastError(wxT("RegisterClass(wxGLCanvasClassNameNoRedraw)")); 
 284         ::UnregisterClass(wxGLCanvasClassName
, wxhInstance
); 
 289     s_registeredGLCanvasClass 
= TRUE
; 
 292   wxCHECK_MSG( parent
, FALSE
, wxT("can't create wxWindow without parent") ); 
 294   if ( !CreateBase(parent
, id
, pos
, size
, style
, wxDefaultValidator
, name
) ) 
 297   parent
->AddChild(this); 
 300   if ( style 
& wxBORDER 
) 
 301     msflags 
|= WS_BORDER
; 
 302   if ( style 
& wxTHICK_FRAME 
) 
 303     msflags 
|= WS_THICKFRAME
; 
 306   A general rule with OpenGL and Win32 is that any window that will have a 
 307   HGLRC built for it must have two flags:  WS_CLIPCHILDREN & WS_CLIPSIBLINGS. 
 308   You can find references about this within the knowledge base and most OpenGL 
 309   books that contain the wgl function descriptions. 
 312   msflags 
|= WS_CHILD 
| WS_VISIBLE 
| WS_CLIPSIBLINGS 
| WS_CLIPCHILDREN
; 
 315   WXDWORD exStyle 
= Determine3DEffects(WS_EX_CLIENTEDGE
, &want3D
); 
 317   // Even with extended styles, need to combine with WS_BORDER 
 318   // for them to look right. 
 319   if ( want3D 
|| (m_windowStyle 
& wxSIMPLE_BORDER
) || (m_windowStyle 
& wxRAISED_BORDER 
) || 
 320        (m_windowStyle 
& wxSUNKEN_BORDER
) || (m_windowStyle 
& wxDOUBLE_BORDER
)) 
 322     msflags 
|= WS_BORDER
; 
 325   // calculate the value to return from WM_GETDLGCODE handler 
 326   if ( GetWindowStyleFlag() & wxWANTS_CHARS 
) 
 328     // want everything: i.e. all keys and WM_CHAR message 
 329     m_lDlgCode 
= DLGC_WANTARROWS 
| DLGC_WANTCHARS 
| 
 330                  DLGC_WANTTAB 
| DLGC_WANTMESSAGE
; 
 333   return MSWCreate(wxGLCanvasClassName
, NULL
, pos
, size
, msflags
, exStyle
); 
 336 static void AdjustPFDForAttributes(PIXELFORMATDESCRIPTOR
& pfd
, int *attribList
) 
 339     pfd
.dwFlags 
&= ~PFD_DOUBLEBUFFER
; 
 340     pfd
.iPixelType 
= PFD_TYPE_COLORINDEX
; 
 344     while( (attribList
[arg
]!=0) ) 
 346       switch( attribList
[arg
++] ) 
 349           pfd
.iPixelType 
= PFD_TYPE_RGBA
; 
 351         case WX_GL_BUFFER_SIZE
: 
 352           pfd
.cColorBits 
= attribList
[arg
++]; 
 355           // this member looks like it may be obsolete 
 356           if (attribList
[arg
] > 0) { 
 357             pfd
.iLayerType 
= PFD_OVERLAY_PLANE
; 
 358           } else if (attribList
[arg
] < 0) { 
 359             pfd
.iLayerType 
= PFD_UNDERLAY_PLANE
; 
 361             pfd
.iLayerType 
= PFD_MAIN_PLANE
; 
 365         case WX_GL_DOUBLEBUFFER
: 
 366           pfd
.dwFlags 
|= PFD_DOUBLEBUFFER
; 
 369           pfd
.dwFlags 
|= PFD_STEREO
; 
 371         case WX_GL_AUX_BUFFERS
: 
 372           pfd
.cAuxBuffers 
= attribList
[arg
++]; 
 375           pfd
.cColorBits 
+= (pfd
.cRedBits 
= attribList
[arg
++]); 
 377         case WX_GL_MIN_GREEN
: 
 378           pfd
.cColorBits 
+= (pfd
.cGreenBits 
= attribList
[arg
++]); 
 381           pfd
.cColorBits 
+= (pfd
.cBlueBits 
= attribList
[arg
++]); 
 383         case WX_GL_MIN_ALPHA
: 
 384           // doesn't count in cColorBits 
 385           pfd
.cAlphaBits 
= attribList
[arg
++]; 
 387         case WX_GL_DEPTH_SIZE
: 
 388           pfd
.cDepthBits 
= attribList
[arg
++]; 
 390         case WX_GL_STENCIL_SIZE
: 
 391           pfd
.cStencilBits 
= attribList
[arg
++]; 
 393         case WX_GL_MIN_ACCUM_RED
: 
 394           pfd
.cAccumBits 
+= (pfd
.cAccumRedBits 
= attribList
[arg
++]); 
 396         case WX_GL_MIN_ACCUM_GREEN
: 
 397           pfd
.cAccumBits 
+= (pfd
.cAccumGreenBits 
= attribList
[arg
++]); 
 399         case WX_GL_MIN_ACCUM_BLUE
: 
 400           pfd
.cAccumBits 
+= (pfd
.cAccumBlueBits 
= attribList
[arg
++]); 
 402         case WX_GL_MIN_ACCUM_ALPHA
: 
 403           pfd
.cAccumBits 
+= (pfd
.cAccumAlphaBits 
= attribList
[arg
++]); 
 412 void wxGLCanvas::SetupPixelFormat(int *attribList
) // (HDC hDC) 
 415   PIXELFORMATDESCRIPTOR pfd 
= { 
 416         sizeof(PIXELFORMATDESCRIPTOR
),    /* size */ 
 420         PFD_DOUBLEBUFFER
,        /* support double-buffering */ 
 421         PFD_TYPE_RGBA
,            /* color type */ 
 422         16,                /* prefered color depth */ 
 423         0, 0, 0, 0, 0, 0,        /* color bits (ignored) */ 
 424         0,                /* no alpha buffer */ 
 425         0,                /* alpha bits (ignored) */ 
 426         0,                /* no accumulation buffer */ 
 427         0, 0, 0, 0,            /* accum bits (ignored) */ 
 428         16,                /* depth buffer */ 
 429         0,                /* no stencil buffer */ 
 430         0,                /* no auxiliary buffers */ 
 431         PFD_MAIN_PLANE
,            /* main layer */ 
 433         0, 0, 0,            /* no layer, visible, damage masks */ 
 436   AdjustPFDForAttributes(pfd
, attribList
); 
 438   pixelFormat 
= ChoosePixelFormat((HDC
) m_hDC
, &pfd
); 
 439   if (pixelFormat 
== 0) { 
 440     wxLogWarning(_("ChoosePixelFormat failed.")); 
 443     if (SetPixelFormat((HDC
) m_hDC
, pixelFormat
, &pfd
) != TRUE
) { 
 444       wxLogWarning(_("SetPixelFormat failed.")); 
 449 void wxGLCanvas::SetupPalette(const wxPalette
& palette
) 
 451     int pixelFormat 
= GetPixelFormat((HDC
) m_hDC
); 
 452     PIXELFORMATDESCRIPTOR pfd
; 
 454     DescribePixelFormat((HDC
) m_hDC
, pixelFormat
, sizeof(PIXELFORMATDESCRIPTOR
), &pfd
); 
 456     if (pfd
.dwFlags 
& PFD_NEED_PALETTE
) 
 466     if ( !m_palette
.Ok() ) 
 468         m_palette 
= CreateDefaultPalette(); 
 473         SelectPalette((HDC
) m_hDC
, (HPALETTE
) m_palette
.GetHPALETTE(), FALSE
); 
 474         RealizePalette((HDC
) m_hDC
); 
 478 wxPalette 
wxGLCanvas::CreateDefaultPalette() 
 480     PIXELFORMATDESCRIPTOR pfd
; 
 482     int pixelFormat 
= GetPixelFormat((HDC
) m_hDC
); 
 484     DescribePixelFormat((HDC
) m_hDC
, pixelFormat
, sizeof(PIXELFORMATDESCRIPTOR
), &pfd
); 
 486     paletteSize 
= 1 << pfd
.cColorBits
; 
 489      (LOGPALETTE
*) malloc(sizeof(LOGPALETTE
) + paletteSize 
* sizeof(PALETTEENTRY
)); 
 490     pPal
->palVersion 
= 0x300; 
 491     pPal
->palNumEntries 
= paletteSize
; 
 493     /* build a simple RGB color palette */ 
 495     int redMask 
= (1 << pfd
.cRedBits
) - 1; 
 496     int greenMask 
= (1 << pfd
.cGreenBits
) - 1; 
 497     int blueMask 
= (1 << pfd
.cBlueBits
) - 1; 
 500     for (i
=0; i
<paletteSize
; ++i
) { 
 501         pPal
->palPalEntry
[i
].peRed 
= 
 502             (((i 
>> pfd
.cRedShift
) & redMask
) * 255) / redMask
; 
 503         pPal
->palPalEntry
[i
].peGreen 
= 
 504             (((i 
>> pfd
.cGreenShift
) & greenMask
) * 255) / greenMask
; 
 505         pPal
->palPalEntry
[i
].peBlue 
= 
 506             (((i 
>> pfd
.cBlueShift
) & blueMask
) * 255) / blueMask
; 
 507         pPal
->palPalEntry
[i
].peFlags 
= 0; 
 511     HPALETTE hPalette 
= CreatePalette(pPal
); 
 515     palette
.SetHPALETTE((WXHPALETTE
) hPalette
); 
 520 void wxGLCanvas::SwapBuffers() 
 523     m_glContext
->SwapBuffers(); 
 526 void wxGLCanvas::OnSize(wxSizeEvent
& event
) 
 530 void wxGLCanvas::SetCurrent() 
 534     m_glContext
->SetCurrent(); 
 538 void wxGLCanvas::SetColour(const char *colour
) 
 541     m_glContext
->SetColour(colour
); 
 544 // TODO: Have to have this called by parent frame (?) 
 545 // So we need wxFrame to call OnQueryNewPalette for all children... 
 546 void wxGLCanvas::OnQueryNewPalette(wxQueryNewPaletteEvent
& event
) 
 548   /* realize palette if this is the current window */ 
 549   if ( GetPalette()->Ok() ) { 
 550     ::UnrealizeObject((HPALETTE
) GetPalette()->GetHPALETTE()); 
 551     ::SelectPalette((HDC
) GetHDC(), (HPALETTE
) GetPalette()->GetHPALETTE(), FALSE
); 
 552     ::RealizePalette((HDC
) GetHDC()); 
 554     event
.SetPaletteRealized(TRUE
); 
 557     event
.SetPaletteRealized(FALSE
); 
 560 // I think this doesn't have to be propagated to child windows. 
 561 void wxGLCanvas::OnPaletteChanged(wxPaletteChangedEvent
& event
) 
 563   /* realize palette if this is *not* the current window */ 
 565        GetPalette()->Ok() && (this != event
.GetChangedWindow()) ) 
 567     ::UnrealizeObject((HPALETTE
) GetPalette()->GetHPALETTE()); 
 568     ::SelectPalette((HDC
) GetHDC(), (HPALETTE
) GetPalette()->GetHPALETTE(), FALSE
); 
 569     ::RealizePalette((HDC
) GetHDC()); 
 574 /* Give extensions proper function names. */ 
 576 /* EXT_vertex_array */ 
 577 void glArrayElementEXT(GLint i
) 
 581 void glColorPointerEXT(GLint size
, GLenum type
, GLsizei stride
, GLsizei count
, const GLvoid 
*pointer
) 
 585 void glDrawArraysEXT(GLenum mode
, GLint first
, GLsizei count
) 
 587 #ifdef GL_EXT_vertex_array 
 588     static PFNGLDRAWARRAYSEXTPROC proc 
= 0; 
 592         proc 
= (PFNGLDRAWARRAYSEXTPROC
) wglGetProcAddress("glDrawArraysEXT"); 
 596         (* proc
) (mode
, first
, count
); 
 600 void glEdgeFlagPointerEXT(GLsizei stride
, GLsizei count
, const GLboolean 
*pointer
) 
 604 void glGetPointervEXT(GLenum pname
, GLvoid
* *params
) 
 608 void glIndexPointerEXT(GLenum type
, GLsizei stride
, GLsizei count
, const GLvoid 
*pointer
) 
 612 void glNormalPointerEXT(GLenum type
, GLsizei stride
, GLsizei count
, const GLvoid 
*pointer
) 
 614 #ifdef GL_EXT_vertex_array 
 615   static PFNGLNORMALPOINTEREXTPROC proc 
= 0; 
 619     proc 
= (PFNGLNORMALPOINTEREXTPROC
) wglGetProcAddress("glNormalPointerEXT"); 
 623     (* proc
) (type
, stride
, count
, pointer
); 
 627 void glTexCoordPointerEXT(GLint size
, GLenum type
, GLsizei stride
, GLsizei count
, const GLvoid 
*pointer
) 
 631 void glVertexPointerEXT(GLint size
, GLenum type
, GLsizei stride
, GLsizei count
, const GLvoid 
*pointer
) 
 633 #ifdef GL_EXT_vertex_array 
 634   static PFNGLVERTEXPOINTEREXTPROC proc 
= 0; 
 638     proc 
= (PFNGLVERTEXPOINTEREXTPROC
) wglGetProcAddress("glVertexPointerEXT"); 
 641     (* proc
) (size
, type
, stride
, count
, pointer
); 
 645 /* EXT_color_subtable */ 
 646 void glColorSubtableEXT(GLenum target
, GLsizei start
, GLsizei count
, GLenum format
, GLenum type
, const GLvoid 
*table
) 
 650 /* EXT_color_table */ 
 651 void glColorTableEXT(GLenum target
, GLenum internalformat
, GLsizei width
, GLenum format
, GLenum type
, const GLvoid 
*table
) 
 655 void glCopyColorTableEXT(GLenum target
, GLenum internalformat
, GLint x
, GLint y
, GLsizei width
) 
 659 void glGetColorTableEXT(GLenum target
, GLenum format
, GLenum type
, GLvoid 
*table
) 
 663 void glGetColorTableParamaterfvEXT(GLenum target
, GLenum pname
, GLfloat 
*params
) 
 667 void glGetColorTavleParameterivEXT(GLenum target
, GLenum pname
, GLint 
*params
) 
 671 /* SGI_compiled_vertex_array */ 
 672 void glLockArraysSGI(GLint first
, GLsizei count
) 
 676 void glUnlockArraysSGI() 
 681 /* SGI_cull_vertex */ 
 682 void glCullParameterdvSGI(GLenum pname
, GLdouble
* params
) 
 686 void glCullParameterfvSGI(GLenum pname
, GLfloat
* params
) 
 691 void glIndexFuncSGI(GLenum func
, GLclampf ref
) 
 695 /* SGI_index_material */ 
 696 void glIndexMaterialSGI(GLenum face
, GLenum mode
) 
 701 void glAddSwapHintRectWin(GLint x
, GLint y
, GLsizei width
, GLsizei height
) 
 706 //--------------------------------------------------------------------------- 
 708 //--------------------------------------------------------------------------- 
 710 IMPLEMENT_CLASS(wxGLApp
, wxApp
) 
 712 bool wxGLApp::InitGLVisual(int *attribList
) 
 715   PIXELFORMATDESCRIPTOR pfd 
= { 
 716         sizeof(PIXELFORMATDESCRIPTOR
),    /* size */ 
 720         PFD_DOUBLEBUFFER
,        /* support double-buffering */ 
 721         PFD_TYPE_RGBA
,            /* color type */ 
 722         16,                /* prefered color depth */ 
 723         0, 0, 0, 0, 0, 0,        /* color bits (ignored) */ 
 724         0,                /* no alpha buffer */ 
 725         0,                /* alpha bits (ignored) */ 
 726         0,                /* no accumulation buffer */ 
 727         0, 0, 0, 0,            /* accum bits (ignored) */ 
 728         16,                /* depth buffer */ 
 729         0,                /* no stencil buffer */ 
 730         0,                /* no auxiliary buffers */ 
 731         PFD_MAIN_PLANE
,            /* main layer */ 
 733         0, 0, 0,            /* no layer, visible, damage masks */ 
 736   AdjustPFDForAttributes(pfd
, attribList
); 
 738   // use DC for whole (root) screen, since no windows have yet been created 
 739   pixelFormat 
= ChoosePixelFormat((HDC
) ::GetDC(NULL
), &pfd
); 
 741   if (pixelFormat 
== 0) { 
 742     wxLogError(_("Failed to initialize OpenGL"));