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__)
29 * GLContext implementation
32 wxGLContext::wxGLContext(bool isRGB
, wxGLCanvas
*win
, const wxPalette
& palette
)
36 m_hDC
= win
->GetHDC();
38 m_glContext
= wglCreateContext((HDC
) m_hDC
);
39 wxCHECK_RET( m_glContext
, "Couldn't create OpenGl context" );
41 wglMakeCurrent((HDC
) m_hDC
, m_glContext
);
44 wxGLContext::wxGLContext(
45 bool isRGB
, wxGLCanvas
*win
,
46 const wxPalette
& palette
,
47 const wxGLContext
*other
/* for sharing display lists */
52 m_hDC
= win
->GetHDC();
54 m_glContext
= wglCreateContext((HDC
) m_hDC
);
55 wxCHECK_RET( m_glContext
, "Couldn't create OpenGl context" );
58 wglShareLists( other
->m_glContext
, m_glContext
);
60 wglMakeCurrent((HDC
) m_hDC
, m_glContext
);
63 wxGLContext::~wxGLContext()
67 wglMakeCurrent(NULL
, NULL
);
68 wglDeleteContext(m_glContext
);
72 void wxGLContext::SwapBuffers()
76 wglMakeCurrent((HDC
) m_hDC
, m_glContext
);
77 ::SwapBuffers((HDC
) m_hDC
); //blits the backbuffer into DC
81 void wxGLContext::SetCurrent()
85 wglMakeCurrent((HDC
) m_hDC
, m_glContext
);
89 setupPixelFormat(hDC);
94 void wxGLContext::SetColour(const char *colour
)
99 wxColour
*col
= wxTheColourDatabase
->FindColour(colour
);
102 r
= (float)(col
->Red()/256.0);
103 g
= (float)(col
->Green()/256.0);
104 b
= (float)(col
->Blue()/256.0);
111 * wxGLCanvas implementation
114 IMPLEMENT_CLASS(wxGLCanvas
, wxScrolledWindow
)
116 BEGIN_EVENT_TABLE(wxGLCanvas
, wxScrolledWindow
)
117 EVT_SIZE(wxGLCanvas::OnSize
)
118 EVT_PALETTE_CHANGED(wxGLCanvas::OnPaletteChanged
)
119 EVT_QUERY_NEW_PALETTE(wxGLCanvas::OnQueryNewPalette
)
122 wxGLCanvas::wxGLCanvas(wxWindow
*parent
, wxWindowID id
,
123 const wxPoint
& pos
, const wxSize
& size
, long style
, const wxString
& name
,
124 int *attribList
/* not used yet! */, const wxPalette
& palette
):
125 wxScrolledWindow(parent
, id
, pos
, size
, style
, name
)
127 m_hDC
= (WXHDC
) ::GetDC((HWND
) GetHWND());
130 SetupPalette(palette
);
132 m_glContext
= new wxGLContext(TRUE
, this, palette
);
134 wxGLCanvas::wxGLCanvas( wxWindow
*parent
,
135 const wxGLContext
*shared
, wxWindowID id
,
136 const wxPoint
& pos
, const wxSize
& size
, long style
, const wxString
& name
,
137 int *attribList
, const wxPalette
& palette
) :
138 wxScrolledWindow(parent
, id
, pos
, size
, style
, name
)
140 m_hDC
= (WXHDC
) ::GetDC((HWND
) GetHWND());
143 SetupPalette(palette
);
145 m_glContext
= new wxGLContext(TRUE
, this, palette
, shared
);
148 wxGLCanvas::~wxGLCanvas()
153 ::ReleaseDC((HWND
) GetHWND(), (HDC
) m_hDC
);
156 void wxGLCanvas::SetupPixelFormat() // (HDC hDC)
158 PIXELFORMATDESCRIPTOR pfd
= {
159 sizeof(PIXELFORMATDESCRIPTOR
), /* size */
163 PFD_DOUBLEBUFFER
, /* support double-buffering */
164 PFD_TYPE_RGBA
, /* color type */
165 16, /* prefered color depth */
166 0, 0, 0, 0, 0, 0, /* color bits (ignored) */
167 0, /* no alpha buffer */
168 0, /* alpha bits (ignored) */
169 0, /* no accumulation buffer */
170 0, 0, 0, 0, /* accum bits (ignored) */
171 16, /* depth buffer */
172 0, /* no stencil buffer */
173 0, /* no auxiliary buffers */
174 PFD_MAIN_PLANE
, /* main layer */
176 0, 0, 0, /* no layer, visible, damage masks */
180 pixelFormat
= ChoosePixelFormat((HDC
) m_hDC
, &pfd
);
181 if (pixelFormat
== 0) {
182 MessageBox(WindowFromDC((HDC
) m_hDC
), "ChoosePixelFormat failed.", "Error",
183 MB_ICONERROR
| MB_OK
);
187 if (SetPixelFormat((HDC
) m_hDC
, pixelFormat
, &pfd
) != TRUE
) {
188 MessageBox(WindowFromDC((HDC
) m_hDC
), "SetPixelFormat failed.", "Error",
189 MB_ICONERROR
| MB_OK
);
194 void wxGLCanvas::SetupPalette(const wxPalette
& palette
)
196 int pixelFormat
= GetPixelFormat((HDC
) m_hDC
);
197 PIXELFORMATDESCRIPTOR pfd
;
199 DescribePixelFormat((HDC
) m_hDC
, pixelFormat
, sizeof(PIXELFORMATDESCRIPTOR
), &pfd
);
201 if (pfd
.dwFlags
& PFD_NEED_PALETTE
)
211 if ( !m_palette
.Ok() )
213 m_palette
= CreateDefaultPalette();
218 SelectPalette((HDC
) m_hDC
, (HPALETTE
) m_palette
.GetHPALETTE(), FALSE
);
219 RealizePalette((HDC
) m_hDC
);
223 wxPalette
wxGLCanvas::CreateDefaultPalette()
225 PIXELFORMATDESCRIPTOR pfd
;
227 int pixelFormat
= GetPixelFormat((HDC
) m_hDC
);
229 DescribePixelFormat((HDC
) m_hDC
, pixelFormat
, sizeof(PIXELFORMATDESCRIPTOR
), &pfd
);
231 paletteSize
= 1 << pfd
.cColorBits
;
234 (LOGPALETTE
*) malloc(sizeof(LOGPALETTE
) + paletteSize
* sizeof(PALETTEENTRY
));
235 pPal
->palVersion
= 0x300;
236 pPal
->palNumEntries
= paletteSize
;
238 /* build a simple RGB color palette */
240 int redMask
= (1 << pfd
.cRedBits
) - 1;
241 int greenMask
= (1 << pfd
.cGreenBits
) - 1;
242 int blueMask
= (1 << pfd
.cBlueBits
) - 1;
245 for (i
=0; i
<paletteSize
; ++i
) {
246 pPal
->palPalEntry
[i
].peRed
=
247 (((i
>> pfd
.cRedShift
) & redMask
) * 255) / redMask
;
248 pPal
->palPalEntry
[i
].peGreen
=
249 (((i
>> pfd
.cGreenShift
) & greenMask
) * 255) / greenMask
;
250 pPal
->palPalEntry
[i
].peBlue
=
251 (((i
>> pfd
.cBlueShift
) & blueMask
) * 255) / blueMask
;
252 pPal
->palPalEntry
[i
].peFlags
= 0;
256 HPALETTE hPalette
= CreatePalette(pPal
);
260 palette
.SetHPALETTE((WXHPALETTE
) hPalette
);
265 void wxGLCanvas::SwapBuffers()
268 m_glContext
->SwapBuffers();
271 void wxGLCanvas::OnSize(wxSizeEvent
& event
)
274 GetClientSize(& width
, & height
);
278 m_glContext
->SetCurrent();
280 glViewport(0, 0, (GLint
)width
, (GLint
)height
);
281 glMatrixMode(GL_PROJECTION
);
283 glFrustum( -1.0, 1.0, -1.0, 1.0, 5.0, 15.0 );
284 glMatrixMode(GL_MODELVIEW
);
288 void wxGLCanvas::SetCurrent()
292 m_glContext
->SetCurrent();
296 void wxGLCanvas::SetColour(const char *colour
)
299 m_glContext
->SetColour(colour
);
302 // TODO: Have to have this called by parent frame (?)
303 // So we need wxFrame to call OnQueryNewPalette for all children...
304 void wxGLCanvas::OnQueryNewPalette(wxQueryNewPaletteEvent
& event
)
306 /* realize palette if this is the current window */
307 if ( GetPalette()->Ok() ) {
308 ::UnrealizeObject((HPALETTE
) GetPalette()->GetHPALETTE());
309 ::SelectPalette((HDC
) GetHDC(), (HPALETTE
) GetPalette()->GetHPALETTE(), FALSE
);
310 ::RealizePalette((HDC
) GetHDC());
312 event
.SetPaletteRealized(TRUE
);
315 event
.SetPaletteRealized(FALSE
);
318 // I think this doesn't have to be propagated to child windows.
319 void wxGLCanvas::OnPaletteChanged(wxPaletteChangedEvent
& event
)
321 /* realize palette if this is *not* the current window */
323 GetPalette()->Ok() && (this != event
.GetChangedWindow()) )
325 ::UnrealizeObject((HPALETTE
) GetPalette()->GetHPALETTE());
326 ::SelectPalette((HDC
) GetHDC(), (HPALETTE
) GetPalette()->GetHPALETTE(), FALSE
);
327 ::RealizePalette((HDC
) GetHDC());
332 /* Give extensions proper function names. */
334 /* EXT_vertex_array */
335 void glArrayElementEXT(GLint i
)
339 void glColorPointerEXT(GLint size
, GLenum type
, GLsizei stride
, GLsizei count
, const GLvoid
*pointer
)
343 void glDrawArraysEXT(GLenum mode
, GLint first
, GLsizei count
)
345 #ifdef GL_EXT_vertex_array
346 static PFNGLDRAWARRAYSEXTPROC proc
= 0;
350 proc
= (PFNGLDRAWARRAYSEXTPROC
) wglGetProcAddress("glDrawArraysEXT");
354 (* proc
) (mode
, first
, count
);
358 void glEdgeFlagPointerEXT(GLsizei stride
, GLsizei count
, const GLboolean
*pointer
)
362 void glGetPointervEXT(GLenum pname
, GLvoid
* *params
)
366 void glIndexPointerEXT(GLenum type
, GLsizei stride
, GLsizei count
, const GLvoid
*pointer
)
370 void glNormalPointerEXT(GLenum type
, GLsizei stride
, GLsizei count
, const GLvoid
*pointer
)
372 #ifdef GL_EXT_vertex_array
373 static PFNGLNORMALPOINTEREXTPROC proc
= 0;
377 proc
= (PFNGLNORMALPOINTEREXTPROC
) wglGetProcAddress("glNormalPointerEXT");
381 (* proc
) (type
, stride
, count
, pointer
);
385 void glTexCoordPointerEXT(GLint size
, GLenum type
, GLsizei stride
, GLsizei count
, const GLvoid
*pointer
)
389 void glVertexPointerEXT(GLint size
, GLenum type
, GLsizei stride
, GLsizei count
, const GLvoid
*pointer
)
391 #ifdef GL_EXT_vertex_array
392 static PFNGLVERTEXPOINTEREXTPROC proc
= 0;
396 proc
= (PFNGLVERTEXPOINTEREXTPROC
) wglGetProcAddress("glVertexPointerEXT");
400 (* proc
) (size
, type
, stride
, count
, pointer
);
404 /* EXT_color_subtable */
405 void glColorSubtableEXT(GLenum target
, GLsizei start
, GLsizei count
, GLenum format
, GLenum type
, const GLvoid
*table
)
409 /* EXT_color_table */
410 void glColorTableEXT(GLenum target
, GLenum internalformat
, GLsizei width
, GLenum format
, GLenum type
, const GLvoid
*table
)
414 void glCopyColorTableEXT(GLenum target
, GLenum internalformat
, GLint x
, GLint y
, GLsizei width
)
418 void glGetColorTableEXT(GLenum target
, GLenum format
, GLenum type
, GLvoid
*table
)
422 void glGetColorTableParamaterfvEXT(GLenum target
, GLenum pname
, GLfloat
*params
)
426 void glGetColorTavleParameterivEXT(GLenum target
, GLenum pname
, GLint
*params
)
430 /* SGI_compiled_vertex_array */
431 void glLockArraysSGI(GLint first
, GLsizei count
)
435 void glUnlockArraysSGI()
440 /* SGI_cull_vertex */
441 void glCullParameterdvSGI(GLenum pname
, GLdouble
* params
)
445 void glCullParameterfvSGI(GLenum pname
, GLfloat
* params
)
450 void glIndexFuncSGI(GLenum func
, GLclampf ref
)
454 /* SGI_index_material */
455 void glIndexMaterialSGI(GLenum face
, GLenum mode
)
460 void glAddSwapHintRectWin(GLint x
, GLint y
, GLsizei width
, GLsizei height
)