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