]> git.saurik.com Git - wxWidgets.git/blob - src/mac/carbon/glcanvas.cpp
another attempt to fix wxPanel/wxFrame::m_winLastFocused handling
[wxWidgets.git] / src / mac / carbon / glcanvas.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: glcanvas.cpp
3 // Purpose: wxGLCanvas, for using OpenGL with wxWindows under Macintosh
4 // Author: AUTHOR
5 // Modified by:
6 // Created: ??/??/98
7 // RCS-ID: $Id$
8 // Copyright: (c) AUTHOR
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 #include "wx/setup.h"
23
24 #if wxUSE_GLCANVAS
25
26 #ifndef WX_PRECOMP
27 #include "wx/frame.h"
28 #endif
29
30 #include "wx/settings.h"
31 #include "wx/log.h"
32
33 #include "wx/glcanvas.h"
34 #include "wx/mac/uma.h"
35
36 #include <agl.h>
37
38 /*
39 * GLContext implementation
40 */
41
42 wxGLContext::wxGLContext(
43 AGLPixelFormat fmt, wxGLCanvas *win,
44 const wxPalette& palette,
45 const wxGLContext *other /* for sharing display lists */
46 )
47 {
48 m_window = win;
49
50 m_drawable = (AGLDrawable) UMAGetWindowPort(win->GetMacRootWindow());
51
52 m_glContext = aglCreateContext(fmt, other ? other->m_glContext : NULL);
53 wxCHECK_RET( m_glContext, wxT("Couldn't create OpenGl context") );
54
55 GLboolean b;
56 b = aglSetDrawable(m_glContext, m_drawable);
57 wxCHECK_RET( b, wxT("Couldn't bind OpenGl context") );
58 aglEnable(m_glContext , AGL_BUFFER_RECT ) ;
59 b = aglSetCurrentContext(m_glContext);
60 wxCHECK_RET( b, wxT("Couldn't activate OpenGl context") );
61 }
62
63 wxGLContext::~wxGLContext()
64 {
65 if (m_glContext)
66 {
67 aglSetCurrentContext(NULL);
68 aglDestroyContext(m_glContext);
69 }
70 }
71
72 void wxGLContext::SwapBuffers()
73 {
74 if (m_glContext)
75 {
76 aglSwapBuffers(m_glContext);
77 }
78 }
79
80 void wxGLContext::SetCurrent()
81 {
82 if (m_glContext)
83 {
84 aglSetCurrentContext(m_glContext);
85 }
86 }
87
88 void wxGLContext::Update()
89 {
90 if (m_glContext)
91 {
92 aglUpdateContext(m_glContext);
93 }
94 }
95
96 void wxGLContext::SetColour(const char *colour)
97 {
98 float r = 0.0;
99 float g = 0.0;
100 float b = 0.0;
101 wxColour *col = wxTheColourDatabase->FindColour(colour);
102 if (col)
103 {
104 r = (float)(col->Red()/256.0);
105 g = (float)(col->Green()/256.0);
106 b = (float)(col->Blue()/256.0);
107 glColor3f( r, g, b);
108 }
109 }
110
111
112 /*
113 * wxGLCanvas implementation
114 */
115
116 IMPLEMENT_CLASS(wxGLCanvas, wxScrolledWindow)
117
118 BEGIN_EVENT_TABLE(wxGLCanvas, wxScrolledWindow)
119 EVT_SIZE(wxGLCanvas::OnSize)
120 END_EVENT_TABLE()
121
122 wxGLCanvas::wxGLCanvas(wxWindow *parent, wxWindowID id,
123 const wxPoint& pos, const wxSize& size, long style, const wxString& name,
124 int *attribList, const wxPalette& palette)
125 {
126 Create(parent, NULL, id, pos, size, style, name, attribList, palette);
127 }
128
129 wxGLCanvas::wxGLCanvas( wxWindow *parent,
130 const wxGLContext *shared, wxWindowID id,
131 const wxPoint& pos, const wxSize& size, long style, const wxString& name,
132 int *attribList, const wxPalette& palette )
133 {
134 Create(parent, shared, id, pos, size, style, name, attribList, palette);
135 }
136
137 wxGLCanvas::wxGLCanvas( wxWindow *parent, const wxGLCanvas *shared, wxWindowID id,
138 const wxPoint& pos, const wxSize& size, long style, const wxString& name,
139 int *attribList, const wxPalette& palette )
140 {
141 Create(parent, shared ? shared->GetContext() : NULL, id, pos, size, style, name, attribList, palette);
142 }
143
144 wxGLCanvas::~wxGLCanvas()
145 {
146 if (m_glContext)
147 delete m_glContext;
148 }
149
150 bool wxGLCanvas::Create(wxWindow *parent, const wxGLContext *shared, wxWindowID id,
151 const wxPoint& pos, const wxSize& size, long style, const wxString& name,
152 int *attribList, const wxPalette& palette)
153 {
154 m_macEraseOnRedraw = false ;
155 GLint data[512];
156 GLint defs[] = { AGL_RGBA,
157 AGL_DOUBLEBUFFER,
158 AGL_MINIMUM_POLICY,
159 AGL_DEPTH_SIZE, 1, // use largest available depth buffer
160 AGL_RED_SIZE, 1,
161 AGL_GREEN_SIZE, 1,
162 AGL_BLUE_SIZE, 1,
163 AGL_ALPHA_SIZE, 0,
164 AGL_NONE };
165 GLint *attribs;
166 if (!attribList)
167 {
168 attribs = defs;
169 }
170 else
171 {
172 int data[512], arg=0, p=0;
173
174 data[p++] = AGL_MINIMUM_POLICY; // make _SIZE tags behave more like GLX
175 while( (attribList[arg]!=0) && (p<512) )
176 {
177 switch( attribList[arg++] )
178 {
179 case WX_GL_RGBA: data[p++] = AGL_RGBA; break;
180 case WX_GL_BUFFER_SIZE:
181 data[p++]=AGL_BUFFER_SIZE; data[p++]=attribList[arg++]; break;
182 case WX_GL_LEVEL:
183 data[p++]=AGL_LEVEL; data[p++]=attribList[arg++]; break;
184 case WX_GL_DOUBLEBUFFER: data[p++] = AGL_DOUBLEBUFFER; break;
185 case WX_GL_STEREO: data[p++] = AGL_STEREO; break;
186 case WX_GL_AUX_BUFFERS:
187 data[p++]=AGL_AUX_BUFFERS; data[p++]=attribList[arg++]; break;
188 case WX_GL_MIN_RED:
189 data[p++]=AGL_RED_SIZE; data[p++]=attribList[arg++]; break;
190 case WX_GL_MIN_GREEN:
191 data[p++]=AGL_GREEN_SIZE; data[p++]=attribList[arg++]; break;
192 case WX_GL_MIN_BLUE:
193 data[p++]=AGL_BLUE_SIZE; data[p++]=attribList[arg++]; break;
194 case WX_GL_MIN_ALPHA:
195 data[p++]=AGL_ALPHA_SIZE; data[p++]=attribList[arg++]; break;
196 case WX_GL_DEPTH_SIZE:
197 data[p++]=AGL_DEPTH_SIZE; data[p++]=attribList[arg++]; break;
198 case WX_GL_STENCIL_SIZE:
199 data[p++]=AGL_STENCIL_SIZE; data[p++]=attribList[arg++]; break;
200 case WX_GL_MIN_ACCUM_RED:
201 data[p++]=AGL_ACCUM_RED_SIZE; data[p++]=attribList[arg++]; break;
202 case WX_GL_MIN_ACCUM_GREEN:
203 data[p++]=AGL_ACCUM_GREEN_SIZE; data[p++]=attribList[arg++]; break;
204 case WX_GL_MIN_ACCUM_BLUE:
205 data[p++]=AGL_ACCUM_BLUE_SIZE; data[p++]=attribList[arg++]; break;
206 case WX_GL_MIN_ACCUM_ALPHA:
207 data[p++]=AGL_ACCUM_ALPHA_SIZE; data[p++]=attribList[arg++]; break;
208 default:
209 break;
210 }
211 }
212 data[p] = 0;
213
214 attribs = defs;
215 }
216 wxScrolledWindow::Create( parent, id, pos, size, style, name );
217
218 AGLPixelFormat fmt = aglChoosePixelFormat(NULL, 0, attribs);
219 wxCHECK_MSG( fmt, false, wxT("Couldn't create OpenGl pixel format") );
220
221 m_glContext = new wxGLContext(fmt, this, palette, shared);
222
223 aglDestroyPixelFormat(fmt);
224
225 return true;
226 }
227
228 void wxGLCanvas::SwapBuffers()
229 {
230 if (m_glContext)
231 m_glContext->SwapBuffers();
232 }
233
234 void wxGLCanvas::UpdateContext()
235 {
236 if (m_glContext)
237 m_glContext->Update();
238 }
239
240 void wxGLCanvas::SetViewport()
241 {
242 // viewport is initially set to entire port
243 // adjust glViewport to just this window
244 int x = 0 ;
245 int y = 0 ;
246
247 MacClientToRootWindow( &x , &y ) ;
248 int width, height;
249 GetClientSize(& width, & height);
250 Rect bounds ;
251 GetWindowPortBounds( GetMacRootWindow() , &bounds ) ;
252 GLint parms[4] ;
253 parms[0] = x ;
254 parms[1] = bounds.bottom - bounds.top - ( y + height ) ;
255 parms[2] = width ;
256 parms[3] = height ;
257
258 aglSetInteger( m_glContext->m_glContext , AGL_BUFFER_RECT , parms ) ;
259 }
260
261 void wxGLCanvas::OnSize(wxSizeEvent& event)
262 {
263 if (m_glContext)
264 {
265 UpdateContext();
266 m_glContext->SetCurrent();
267
268 SetViewport();
269 glMatrixMode(GL_PROJECTION);
270 glLoadIdentity();
271 glFrustum( -1.0, 1.0, -1.0, 1.0, 5.0, 15.0 );
272 glMatrixMode(GL_MODELVIEW);
273 }
274 }
275
276 void wxGLCanvas::SetCurrent()
277 {
278 if (m_glContext)
279 {
280 m_glContext->SetCurrent();
281 }
282 }
283
284 void wxGLCanvas::SetColour(const char *colour)
285 {
286 if (m_glContext)
287 m_glContext->SetColour(colour);
288 }
289
290 #endif // wxUSE_GLCANVAS