]> git.saurik.com Git - wxWidgets.git/blob - utils/glcanvas/win/glcanvas.cpp
no message
[wxWidgets.git] / utils / glcanvas / win / glcanvas.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: glcanvas.cpp
3 // Purpose: wxGLCanvas, for using OpenGL with wxWindows 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 #ifdef __GNUG__
13 #pragma implementation "glcanvas.h"
14 #endif
15
16 #include "wx/wxprec.h"
17
18 #if defined(__BORLANDC__)
19 #pragma hdrstop
20 #endif
21
22 #ifndef WX_PRECOMP
23 #include <wx/frame.h>
24 #endif
25
26 #include "GL/gl.h"
27
28 #include "glcanvas.h"
29
30 /*
31 * GLContext implementation
32 */
33
34 wxGLContext::wxGLContext(bool isRGB, wxWindow *win, const wxPalette& palette)
35 {
36 m_window = win;
37
38 m_hDC = (WXHDC) ::GetDC((HWND) win->GetHWND());
39
40 SetupPixelFormat();
41 SetupPalette(palette);
42
43 m_glContext = wglCreateContext((HDC) m_hDC);
44 wglMakeCurrent((HDC) m_hDC, m_glContext);
45 }
46
47 wxGLContext::~wxGLContext()
48 {
49 if (m_glContext)
50 {
51 wglMakeCurrent(NULL, NULL);
52 wglDeleteContext(m_glContext);
53 }
54
55 ::ReleaseDC((HWND) m_window->GetHWND(), (HDC) m_hDC);
56 }
57
58 void wxGLContext::SwapBuffers()
59 {
60 if (m_glContext)
61 {
62 wglMakeCurrent((HDC) m_hDC, m_glContext);
63 ::SwapBuffers((HDC) m_hDC); //blits the backbuffer into DC
64 }
65 }
66
67 void wxGLContext::SetCurrent()
68 {
69 if (m_glContext)
70 {
71 wglMakeCurrent((HDC) m_hDC, m_glContext);
72 }
73
74 /*
75 setupPixelFormat(hDC);
76 setupPalette(hDC);
77 */
78 }
79
80 void wxGLContext::SetColour(const char *colour)
81 {
82 float r = 0.0;
83 float g = 0.0;
84 float b = 0.0;
85 wxColour *col = wxTheColourDatabase->FindColour(colour);
86 if (col)
87 {
88 r = (float)(col->Red()/256.0);
89 g = (float)(col->Green()/256.0);
90 b = (float)(col->Blue()/256.0);
91 glColor3f( r, g, b);
92 }
93 }
94
95 void wxGLContext::SetupPixelFormat() // (HDC hDC)
96 {
97 PIXELFORMATDESCRIPTOR pfd = {
98 sizeof(PIXELFORMATDESCRIPTOR), /* size */
99 1, /* version */
100 PFD_SUPPORT_OPENGL |
101 PFD_DRAW_TO_WINDOW |
102 PFD_DOUBLEBUFFER, /* support double-buffering */
103 PFD_TYPE_RGBA, /* color type */
104 16, /* prefered color depth */
105 0, 0, 0, 0, 0, 0, /* color bits (ignored) */
106 0, /* no alpha buffer */
107 0, /* alpha bits (ignored) */
108 0, /* no accumulation buffer */
109 0, 0, 0, 0, /* accum bits (ignored) */
110 16, /* depth buffer */
111 0, /* no stencil buffer */
112 0, /* no auxiliary buffers */
113 PFD_MAIN_PLANE, /* main layer */
114 0, /* reserved */
115 0, 0, 0, /* no layer, visible, damage masks */
116 };
117 int pixelFormat;
118
119 pixelFormat = ChoosePixelFormat((HDC) m_hDC, &pfd);
120 if (pixelFormat == 0) {
121 MessageBox(WindowFromDC((HDC) m_hDC), "ChoosePixelFormat failed.", "Error",
122 MB_ICONERROR | MB_OK);
123 exit(1);
124 }
125
126 if (SetPixelFormat((HDC) m_hDC, pixelFormat, &pfd) != TRUE) {
127 MessageBox(WindowFromDC((HDC) m_hDC), "SetPixelFormat failed.", "Error",
128 MB_ICONERROR | MB_OK);
129 exit(1);
130 }
131 }
132
133 void wxGLContext::SetupPalette(const wxPalette& palette)
134 {
135 int pixelFormat = GetPixelFormat((HDC) m_hDC);
136 PIXELFORMATDESCRIPTOR pfd;
137
138 DescribePixelFormat((HDC) m_hDC, pixelFormat, sizeof(PIXELFORMATDESCRIPTOR), &pfd);
139
140 if (pfd.dwFlags & PFD_NEED_PALETTE)
141 {
142 }
143 else
144 {
145 return;
146 }
147
148 m_palette = palette;
149
150 if ( !m_palette.Ok() )
151 {
152 m_palette = CreateDefaultPalette();
153 }
154
155 if (m_palette.Ok())
156 {
157 SelectPalette((HDC) m_hDC, (HPALETTE) m_palette.GetHPALETTE(), FALSE);
158 RealizePalette((HDC) m_hDC);
159 }
160 }
161
162 wxPalette wxGLContext::CreateDefaultPalette()
163 {
164 PIXELFORMATDESCRIPTOR pfd;
165 int paletteSize;
166 int pixelFormat = GetPixelFormat((HDC) m_hDC);
167
168 DescribePixelFormat((HDC) m_hDC, pixelFormat, sizeof(PIXELFORMATDESCRIPTOR), &pfd);
169
170 paletteSize = 1 << pfd.cColorBits;
171
172 LOGPALETTE* pPal =
173 (LOGPALETTE*) malloc(sizeof(LOGPALETTE) + paletteSize * sizeof(PALETTEENTRY));
174 pPal->palVersion = 0x300;
175 pPal->palNumEntries = paletteSize;
176
177 /* build a simple RGB color palette */
178 {
179 int redMask = (1 << pfd.cRedBits) - 1;
180 int greenMask = (1 << pfd.cGreenBits) - 1;
181 int blueMask = (1 << pfd.cBlueBits) - 1;
182 int i;
183
184 for (i=0; i<paletteSize; ++i) {
185 pPal->palPalEntry[i].peRed =
186 (((i >> pfd.cRedShift) & redMask) * 255) / redMask;
187 pPal->palPalEntry[i].peGreen =
188 (((i >> pfd.cGreenShift) & greenMask) * 255) / greenMask;
189 pPal->palPalEntry[i].peBlue =
190 (((i >> pfd.cBlueShift) & blueMask) * 255) / blueMask;
191 pPal->palPalEntry[i].peFlags = 0;
192 }
193 }
194
195 HPALETTE hPalette = CreatePalette(pPal);
196 free(pPal);
197
198 wxPalette palette;
199 palette.SetHPALETTE((WXHPALETTE) hPalette);
200
201 return palette;
202 }
203
204 /*
205 * wxGLCanvas implementation
206 */
207
208 IMPLEMENT_CLASS(wxGLCanvas, wxScrolledWindow)
209
210 BEGIN_EVENT_TABLE(wxGLCanvas, wxScrolledWindow)
211 EVT_SIZE(wxGLCanvas::OnSize)
212 EVT_PALETTE_CHANGED(wxGLCanvas::OnPaletteChanged)
213 EVT_QUERY_NEW_PALETTE(wxGLCanvas::OnQueryNewPalette)
214 END_EVENT_TABLE()
215
216 wxGLCanvas::wxGLCanvas(wxWindow *parent, wxWindowID id,
217 const wxPoint& pos, const wxSize& size, long style, const wxString& name,
218 int *attribList /* not used yet! */, const wxPalette& palette):
219 wxScrolledWindow(parent, id, pos, size, style, name)
220 {
221 m_glContext = new wxGLContext(TRUE, this, palette);
222 }
223
224 wxGLCanvas::~wxGLCanvas()
225 {
226 if (m_glContext)
227 delete m_glContext;
228 }
229
230 void wxGLCanvas::SwapBuffers()
231 {
232 if (m_glContext)
233 m_glContext->SwapBuffers();
234 }
235
236 void wxGLCanvas::OnSize(wxSizeEvent& event)
237 {
238 int width, height;
239 GetClientSize(& width, & height);
240
241 if (m_glContext)
242 {
243 m_glContext->SetCurrent();
244
245 glViewport(0, 0, (GLint)width, (GLint)height);
246 glMatrixMode(GL_PROJECTION);
247 glLoadIdentity();
248 glFrustum( -1.0, 1.0, -1.0, 1.0, 5.0, 15.0 );
249 glMatrixMode(GL_MODELVIEW);
250 }
251 }
252
253 void wxGLCanvas::SetCurrent()
254 {
255 if (m_glContext)
256 {
257 m_glContext->SetCurrent();
258 }
259 }
260
261 void wxGLCanvas::SetColour(const char *colour)
262 {
263 if (m_glContext)
264 m_glContext->SetColour(colour);
265 }
266
267 // TODO: Have to have this called by parent frame (?)
268 // So we need wxFrame to call OnQueryNewPalette for all children...
269 void wxGLCanvas::OnQueryNewPalette(wxQueryNewPaletteEvent& event)
270 {
271 /* realize palette if this is the current window */
272 if (m_glContext && m_glContext->GetPalette()->Ok()) {
273 ::UnrealizeObject((HPALETTE) m_glContext->GetPalette()->GetHPALETTE());
274 ::SelectPalette((HDC) m_glContext->GetHDC(), (HPALETTE) m_glContext->GetPalette()->GetHPALETTE(), FALSE);
275 ::RealizePalette((HDC) m_glContext->GetHDC());
276 Refresh();
277 event.SetPaletteRealized(TRUE);
278 }
279 else
280 event.SetPaletteRealized(FALSE);
281 }
282
283 // I think this doesn't have to be propagated to child windows.
284 void wxGLCanvas::OnPaletteChanged(wxPaletteChangedEvent& event)
285 {
286 /* realize palette if this is *not* the current window */
287 if ( m_glContext &&
288 m_glContext->GetPalette() &&
289 m_glContext->GetPalette()->Ok() &&
290 (this != event.GetChangedWindow()) )
291 {
292 ::UnrealizeObject((HPALETTE) m_glContext->GetPalette()->GetHPALETTE());
293 ::SelectPalette((HDC) m_glContext->GetHDC(), (HPALETTE) m_glContext->GetPalette()->GetHPALETTE(), FALSE);
294 ::RealizePalette((HDC) m_glContext->GetHDC());
295 Refresh();
296 }
297 }
298
299 /* Give extensions proper function names. */
300
301 /* EXT_vertex_array */
302 void glArrayElementEXT(GLint i)
303 {
304 }
305
306 void glColorPointerEXT(GLint size, GLenum type, GLsizei stride, GLsizei count, const GLvoid *pointer)
307 {
308 }
309
310 void glDrawArraysEXT(GLenum mode, GLint first, GLsizei count)
311 {
312 #ifdef GL_EXT_vertex_array
313 static PFNGLDRAWARRAYSEXTPROC proc = 0;
314
315 if ( !proc )
316 {
317 proc = (PFNGLDRAWARRAYSEXTPROC) wglGetProcAddress("glDrawArraysEXT");
318 }
319
320 if ( proc )
321 (* proc) (mode, first, count);
322 #endif
323 }
324
325 void glEdgeFlagPointerEXT(GLsizei stride, GLsizei count, const GLboolean *pointer)
326 {
327 }
328
329 void glGetPointervEXT(GLenum pname, GLvoid* *params)
330 {
331 }
332
333 void glIndexPointerEXT(GLenum type, GLsizei stride, GLsizei count, const GLvoid *pointer)
334 {
335 }
336
337 void glNormalPointerEXT(GLenum type, GLsizei stride, GLsizei count, const GLvoid *pointer)
338 {
339 #ifdef GL_EXT_vertex_array
340 static PFNGLNORMALPOINTEREXTPROC proc = 0;
341
342 if ( !proc )
343 {
344 proc = (PFNGLNORMALPOINTEREXTPROC) wglGetProcAddress("glNormalPointerEXT");
345 }
346
347 if ( proc )
348 (* proc) (type, stride, count, pointer);
349 #endif
350 }
351
352 void glTexCoordPointerEXT(GLint size, GLenum type, GLsizei stride, GLsizei count, const GLvoid *pointer)
353 {
354 }
355
356 void glVertexPointerEXT(GLint size, GLenum type, GLsizei stride, GLsizei count, const GLvoid *pointer)
357 {
358 #ifdef GL_EXT_vertex_array
359 static PFNGLVERTEXPOINTEREXTPROC proc = 0;
360
361 if ( !proc )
362 {
363 proc = (PFNGLVERTEXPOINTEREXTPROC) wglGetProcAddress("glVertexPointerEXT");
364 }
365
366 if ( proc )
367 (* proc) (size, type, stride, count, pointer);
368 #endif
369 }
370
371 /* EXT_color_subtable */
372 void glColorSubtableEXT(GLenum target, GLsizei start, GLsizei count, GLenum format, GLenum type, const GLvoid *table)
373 {
374 }
375
376 /* EXT_color_table */
377 void glColorTableEXT(GLenum target, GLenum internalformat, GLsizei width, GLenum format, GLenum type, const GLvoid *table)
378 {
379 }
380
381 void glCopyColorTableEXT(GLenum target, GLenum internalformat, GLint x, GLint y, GLsizei width)
382 {
383 }
384
385 void glGetColorTableEXT(GLenum target, GLenum format, GLenum type, GLvoid *table)
386 {
387 }
388
389 void glGetColorTableParamaterfvEXT(GLenum target, GLenum pname, GLfloat *params)
390 {
391 }
392
393 void glGetColorTavleParameterivEXT(GLenum target, GLenum pname, GLint *params)
394 {
395 }
396
397 /* SGI_compiled_vertex_array */
398 void glLockArraysSGI(GLint first, GLsizei count)
399 {
400 }
401
402 void glUnlockArraysSGI()
403 {
404 }
405
406
407 /* SGI_cull_vertex */
408 void glCullParameterdvSGI(GLenum pname, GLdouble* params)
409 {
410 }
411
412 void glCullParameterfvSGI(GLenum pname, GLfloat* params)
413 {
414 }
415
416 /* SGI_index_func */
417 void glIndexFuncSGI(GLenum func, GLclampf ref)
418 {
419 }
420
421 /* SGI_index_material */
422 void glIndexMaterialSGI(GLenum face, GLenum mode)
423 {
424 }
425
426 /* WIN_swap_hint */
427 void glAddSwapHintRectWin(GLint x, GLint y, GLsizei width, GLsizei height)
428 {
429 }
430