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