1 /*------------------------------------------------------------------------ |
|
2 * |
|
3 * EGL 1.3 |
|
4 * ------- |
|
5 * |
|
6 * Copyright (c) 2007 The Khronos Group Inc. |
|
7 * |
|
8 * Permission is hereby granted, free of charge, to any person obtaining a |
|
9 * copy of this software and /or associated documentation files |
|
10 * (the "Materials "), to deal in the Materials without restriction, |
|
11 * including without limitation the rights to use, copy, modify, merge, |
|
12 * publish, distribute, sublicense, and/or sell copies of the Materials, |
|
13 * and to permit persons to whom the Materials are furnished to do so, |
|
14 * subject to the following conditions: |
|
15 * |
|
16 * The above copyright notice and this permission notice shall be included |
|
17 * in all copies or substantial portions of the Materials. |
|
18 * |
|
19 * THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, |
|
20 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF |
|
21 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. |
|
22 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, |
|
23 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR |
|
24 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE MATERIALS OR |
|
25 * THE USE OR OTHER DEALINGS IN THE MATERIALS. |
|
26 * |
|
27 *//** |
|
28 * \file |
|
29 * \brief Mac OS X specific EGL functionality |
|
30 * \note |
|
31 *//*-------------------------------------------------------------------*/ |
|
32 |
|
33 #include "egl.h" |
|
34 #include "riImage.h" |
|
35 #include <pthread.h> |
|
36 #include <sys/errno.h> |
|
37 |
|
38 namespace OpenVGRI |
|
39 { |
|
40 |
|
41 /*-------------------------------------------------------------------*//*! |
|
42 * \brief |
|
43 * \param |
|
44 * \return |
|
45 * \note |
|
46 *//*-------------------------------------------------------------------*/ |
|
47 |
|
48 void* OSGetCurrentThreadID(void) |
|
49 { |
|
50 return (void*)pthread_self(); //TODO this is not safe |
|
51 } |
|
52 |
|
53 /*-------------------------------------------------------------------*//*! |
|
54 * \brief |
|
55 * \param |
|
56 * \return |
|
57 * \note |
|
58 *//*-------------------------------------------------------------------*/ |
|
59 |
|
60 static pthread_mutex_t mutex; |
|
61 static int mutexRefCount = 0; |
|
62 static bool mutexInitialized = false; |
|
63 //acquired mutex cannot be deinited |
|
64 void OSDeinitMutex(void) |
|
65 { |
|
66 RI_ASSERT(mutexInitialized); |
|
67 RI_ASSERT(mutexRefCount == 0); |
|
68 int ret = pthread_mutex_destroy(&mutex); |
|
69 RI_ASSERT(ret != EINVAL); //assert that the mutex has been initialized |
|
70 RI_ASSERT(ret != EAGAIN); //assert that the maximum number of recursive locks hasn't been exceeded |
|
71 RI_ASSERT(!ret); //check that there aren't other errors |
|
72 RI_UNREF(ret); |
|
73 } |
|
74 void OSAcquireMutex(void) |
|
75 { |
|
76 if(!mutexInitialized) |
|
77 { |
|
78 int ret; |
|
79 pthread_mutexattr_t attr; |
|
80 ret = pthread_mutexattr_init(&attr); //initially not locked |
|
81 RI_ASSERT(!ret); //check that there aren't any errors |
|
82 ret = pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE); //count the number of recursive locks |
|
83 RI_ASSERT(!ret); //check that there aren't any errors |
|
84 ret = pthread_mutex_init(&mutex, &attr); |
|
85 pthread_mutexattr_destroy(&attr); |
|
86 RI_ASSERT(!ret); //check that there aren't more errors |
|
87 RI_UNREF(ret); |
|
88 mutexInitialized = true; |
|
89 } |
|
90 int ret = pthread_mutex_lock(&mutex); |
|
91 RI_ASSERT(ret != EINVAL); //assert that the mutex has been initialized |
|
92 RI_ASSERT(ret != EAGAIN); //assert that the maximum number of recursive locks hasn't been exceeded |
|
93 RI_ASSERT(ret != EDEADLK); //recursive mutexes shouldn't return this |
|
94 RI_ASSERT(!ret); //check that there aren't other errors |
|
95 RI_UNREF(ret); |
|
96 mutexRefCount++; |
|
97 } |
|
98 void OSReleaseMutex(void) |
|
99 { |
|
100 RI_ASSERT(mutexInitialized); |
|
101 mutexRefCount--; |
|
102 RI_ASSERT(mutexRefCount >= 0); |
|
103 int ret = pthread_mutex_unlock(&mutex); |
|
104 RI_ASSERT(ret != EPERM); //assert that the current thread owns the mutex |
|
105 RI_ASSERT(!ret); //check that there aren't more errors |
|
106 RI_UNREF(ret); |
|
107 } |
|
108 |
|
109 /*-------------------------------------------------------------------*//*! |
|
110 * \brief |
|
111 * \param |
|
112 * \return |
|
113 * \note |
|
114 *//*-------------------------------------------------------------------*/ |
|
115 |
|
116 static bool isBigEndian() |
|
117 { |
|
118 static const RIuint32 v = 0x12345678u; |
|
119 const RIuint8* p = (const RIuint8*)&v; |
|
120 RI_ASSERT (*p == (RIuint8)0x12u || *p == (RIuint8)0x78u); |
|
121 return (*p == (RIuint8)(0x12)) ? true : false; |
|
122 } |
|
123 |
|
124 |
|
125 /*-------------------------------------------------------------------*//*! |
|
126 * \brief |
|
127 * \param |
|
128 * \return |
|
129 * \note |
|
130 *//*-------------------------------------------------------------------*/ |
|
131 |
|
132 #ifdef RI_USE_GLUT |
|
133 # include <OpenGL/gl.h> |
|
134 # include <GLUT/glut.h> |
|
135 |
|
136 struct OSWindowContext |
|
137 { |
|
138 int window; |
|
139 unsigned int* tmp; |
|
140 int tmpWidth; |
|
141 int tmpHeight; |
|
142 }; |
|
143 |
|
144 OSWindowContext* OSCreateWindowContext(EGLNativeWindowType window) |
|
145 { |
|
146 try |
|
147 { |
|
148 OSWindowContext* ctx = RI_NEW(OSWindowContext, ()); |
|
149 ctx->window = window; |
|
150 ctx->tmp = NULL; |
|
151 ctx->tmpWidth = 0; |
|
152 ctx->tmpHeight = 0; |
|
153 return ctx; |
|
154 } |
|
155 catch(std::bad_alloc) |
|
156 { |
|
157 return NULL; |
|
158 } |
|
159 } |
|
160 |
|
161 void OSDestroyWindowContext(OSWindowContext* ctx) |
|
162 { |
|
163 if(ctx) |
|
164 { |
|
165 RI_DELETE_ARRAY(ctx->tmp); |
|
166 RI_DELETE(ctx); |
|
167 } |
|
168 } |
|
169 |
|
170 bool OSIsWindow(const void* context) |
|
171 { |
|
172 OSWindowContext* ctx = (OSWindowContext*)context; |
|
173 if(ctx) |
|
174 { |
|
175 //TODO implement |
|
176 return true; |
|
177 } |
|
178 return false; |
|
179 } |
|
180 |
|
181 void OSGetWindowSize(const OSWindowContext* ctx, int& width, int& height) |
|
182 { |
|
183 if(ctx) |
|
184 { |
|
185 int currWin = glutGetWindow(); |
|
186 glutSetWindow((int)ctx->window); |
|
187 width = glutGet(GLUT_WINDOW_WIDTH); |
|
188 height = glutGet(GLUT_WINDOW_HEIGHT); |
|
189 glutSetWindow(currWin); |
|
190 } |
|
191 else |
|
192 { |
|
193 width = 0; |
|
194 height = 0; |
|
195 } |
|
196 } |
|
197 |
|
198 void OSBlitToWindow(OSWindowContext* ctx, const Drawable* drawable) |
|
199 { |
|
200 if(ctx) |
|
201 { |
|
202 int w = drawable->getWidth(); |
|
203 int h = drawable->getHeight(); |
|
204 |
|
205 int currWin = glutGetWindow(); |
|
206 glutSetWindow((int)ctx->window); |
|
207 |
|
208 if(!ctx->tmp || ctx->tmpWidth != w || ctx->tmpHeight != h) |
|
209 { |
|
210 RI_DELETE_ARRAY(ctx->tmp); |
|
211 ctx->tmp = NULL; |
|
212 try |
|
213 { |
|
214 ctx->tmp = RI_NEW_ARRAY(unsigned int, w*h); //throws bad_alloc |
|
215 ctx->tmpWidth = w; |
|
216 ctx->tmpHeight = h; |
|
217 } |
|
218 catch(std::bad_alloc) |
|
219 { |
|
220 //do nothing |
|
221 } |
|
222 } |
|
223 |
|
224 if(ctx->tmp) |
|
225 { |
|
226 glViewport(0, 0, w, h); |
|
227 glDisable(GL_DEPTH_TEST); |
|
228 glMatrixMode(GL_PROJECTION); |
|
229 glLoadIdentity(); |
|
230 glMatrixMode(GL_MODELVIEW); |
|
231 glLoadIdentity(); |
|
232 //NOTE: we assume here that the display is always in sRGB color space |
|
233 VGImageFormat f = VG_sXBGR_8888; |
|
234 if(isBigEndian()) |
|
235 f = VG_sRGBX_8888; |
|
236 vgReadPixels(ctx->tmp, w*sizeof(unsigned int), f, 0, 0, w, h); |
|
237 glDrawPixels(w, h, GL_RGBA, GL_UNSIGNED_BYTE, ctx->tmp); |
|
238 } |
|
239 |
|
240 glutSwapBuffers(); //shows the OpenGL frame buffer |
|
241 glutSetWindow(currWin); //restore the current window |
|
242 } |
|
243 } |
|
244 |
|
245 #else |
|
246 |
|
247 /*-------------------------------------------------------------------*//*! |
|
248 * \brief |
|
249 * \param |
|
250 * \return |
|
251 * \note |
|
252 *//*-------------------------------------------------------------------*/ |
|
253 |
|
254 //Mac OS X native |
|
255 #include <OpenGL/gl.h> |
|
256 #include <AGL/agl.h> |
|
257 |
|
258 struct OSWindowContext |
|
259 { |
|
260 AGLPixelFormat aglPixFmt; |
|
261 AGLContext aglContext; |
|
262 WindowPtr window; |
|
263 unsigned int* tmp; |
|
264 int tmpWidth; |
|
265 int tmpHeight; |
|
266 }; |
|
267 |
|
268 void* OSCreateWindowContext(EGLNativeWindowType window) |
|
269 { |
|
270 OSWindowContext* ctx = NULL; |
|
271 try |
|
272 { |
|
273 ctx = RI_NEW(OSWindowContext, ()); |
|
274 } |
|
275 catch(std::bad_alloc) |
|
276 { |
|
277 return NULL; |
|
278 } |
|
279 |
|
280 GLint attrib[] = { AGL_RGBA, AGL_DOUBLEBUFFER, AGL_DEPTH_SIZE, 32, AGL_NONE }; |
|
281 ctx->aglPixFmt = aglChoosePixelFormat(NULL, 0, attrib); |
|
282 if(!ctx->aglPixFmt) |
|
283 { |
|
284 RI_DELETE(ctx); |
|
285 return NULL; |
|
286 } |
|
287 |
|
288 ctx->aglContext = aglCreateContext(ctx->aglPixFmt, NULL); |
|
289 if(!ctx->aglContext) |
|
290 { |
|
291 aglDestroyPixelFormat(ctx->aglPixFmt); |
|
292 RI_DELETE(ctx); |
|
293 return NULL; |
|
294 } |
|
295 |
|
296 GLint opaque = 1; |
|
297 GLint sync = 1; |
|
298 aglSetInteger(ctx->aglContext, AGL_SURFACE_OPACITY, &opaque); |
|
299 aglSetInteger(ctx->aglContext, AGL_SWAP_INTERVAL, &sync); |
|
300 |
|
301 ctx->window = (WindowPtr)window; |
|
302 ctx->tmp = NULL; |
|
303 ctx->tmpWidth = 0; |
|
304 ctx->tmpHeight = 0; |
|
305 return ctx; |
|
306 } |
|
307 |
|
308 void OSDestroyWindowContext(void* context) |
|
309 { |
|
310 OSWindowContext* ctx = (OSWindowContext*)context; |
|
311 if(ctx) |
|
312 { |
|
313 aglSetDrawable(ctx->aglContext, NULL); |
|
314 aglSetCurrentContext(NULL); |
|
315 aglDestroyContext(ctx->aglContext); |
|
316 aglDestroyPixelFormat(ctx->aglPixFmt); |
|
317 RI_DELETE_ARRAY(ctx->tmp); |
|
318 RI_DELETE(ctx); |
|
319 } |
|
320 } |
|
321 |
|
322 bool OSIsWindow(const void* context) |
|
323 { |
|
324 OSWindowContext* ctx = (OSWindowContext*)context; |
|
325 if(ctx) |
|
326 { |
|
327 if(IsValidWindowPtr(ctx->window)) |
|
328 return true; |
|
329 } |
|
330 return false; |
|
331 } |
|
332 |
|
333 void OSGetWindowSize(const void* context, int& width, int& height) |
|
334 { |
|
335 OSWindowContext* ctx = (OSWindowContext*)context; |
|
336 if(ctx) |
|
337 { |
|
338 Rect rectPort; |
|
339 GetWindowPortBounds(ctx->window, &rectPort); |
|
340 width = rectPort.right - rectPort.left; |
|
341 height = rectPort.bottom - rectPort.top; |
|
342 } |
|
343 else |
|
344 { |
|
345 width = 0; |
|
346 height = 0; |
|
347 } |
|
348 } |
|
349 |
|
350 void OSBlitToWindow(void* context, const Drawable* drawable) |
|
351 { |
|
352 OSWindowContext* ctx = (OSWindowContext*)context; |
|
353 if(ctx) |
|
354 { |
|
355 int w = drawable->getWidth(); |
|
356 int h = drawable->getHeight(); |
|
357 |
|
358 GrafPtr portSave = NULL; |
|
359 GetPort(&portSave); |
|
360 SetPort((GrafPtr)GetWindowPort(ctx->window)); |
|
361 aglSetDrawable(ctx->aglContext, GetWindowPort(ctx->window)); |
|
362 aglSetCurrentContext(ctx->aglContext); |
|
363 |
|
364 if(!ctx->tmp || ctx->tmpWidth != w || ctx->tmpHeight != h) |
|
365 { |
|
366 RI_DELETE_ARRAY(ctx->tmp); |
|
367 ctx->tmp = NULL; |
|
368 try |
|
369 { |
|
370 ctx->tmp = RI_NEW_ARRAY(unsigned int, w*h); //throws bad_alloc |
|
371 ctx->tmpWidth = w; |
|
372 ctx->tmpHeight = h; |
|
373 } |
|
374 catch(std::bad_alloc) |
|
375 { |
|
376 //do nothing |
|
377 } |
|
378 } |
|
379 |
|
380 if(ctx->tmp) |
|
381 { |
|
382 glViewport(0, 0, w, h); |
|
383 glDisable(GL_DEPTH_TEST); |
|
384 glMatrixMode(GL_PROJECTION); |
|
385 glLoadIdentity(); |
|
386 glMatrixMode(GL_MODELVIEW); |
|
387 glLoadIdentity(); |
|
388 //NOTE: we assume here that the display is always in sRGB color space |
|
389 VGImageFormat f = VG_sXBGR_8888; |
|
390 if(isBigEndian()) |
|
391 f = VG_sRGBX_8888; |
|
392 vgReadPixels(ctx->tmp, w*sizeof(unsigned int), f, 0, 0, w, h); |
|
393 glDrawPixels(w, h, GL_RGBA, GL_UNSIGNED_BYTE, ctx->tmp); |
|
394 } |
|
395 |
|
396 aglSwapBuffers(ctx->aglContext); |
|
397 SetPort(portSave); |
|
398 } |
|
399 } |
|
400 |
|
401 #endif |
|
402 |
|
403 EGLDisplay OSGetDisplay(EGLNativeDisplayType display_id) |
|
404 { |
|
405 RI_UNREF(display_id); |
|
406 return (EGLDisplay)1; //support only a single display |
|
407 } |
|
408 |
|
409 } //namespace OpenVGRI |
|