e14743d1 |
1 | /* |
2 | SDL - Simple DirectMedia Layer |
3 | Copyright (C) 1997-2009 Sam Lantinga |
4 | |
5 | This library is free software; you can redistribute it and/or |
6 | modify it under the terms of the GNU Lesser General Public |
7 | License as published by the Free Software Foundation; either |
8 | version 2.1 of the License, or (at your option) any later version. |
9 | |
10 | This library is distributed in the hope that it will be useful, |
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
13 | Lesser General Public License for more details. |
14 | |
15 | You should have received a copy of the GNU Lesser General Public |
16 | License along with this library; if not, write to the Free Software |
17 | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA |
18 | |
19 | Sam Lantinga |
20 | slouken@libsdl.org |
21 | */ |
22 | #include "SDL_config.h" |
23 | |
24 | #include <dlfcn.h> |
25 | #include "SDL.h" |
26 | #include "SDL_ph_gl.h" |
27 | |
28 | #if SDL_VIDEO_OPENGL |
29 | |
30 | #if (_NTO_VERSION >= 630) |
31 | /* PhotonGL functions */ |
32 | GLPH_DECLARE_FUNCS; |
33 | #endif /* 6.3.0 */ |
34 | |
35 | #if (_NTO_VERSION < 630) |
36 | void ph_GL_SwapBuffers(_THIS) |
37 | { |
38 | PgSetRegion(PtWidgetRid(window)); |
39 | PdOpenGLContextSwapBuffers(oglctx); |
40 | } |
41 | #else |
42 | void ph_GL_SwapBuffers(_THIS) |
43 | { |
44 | qnxgl_swap_buffers(oglbuffers); |
45 | } |
46 | #endif /* 6.3.0 */ |
47 | |
48 | int ph_GL_GetAttribute(_THIS, SDL_GLattr attrib, int* value) |
49 | { |
50 | switch (attrib) |
51 | { |
52 | case SDL_GL_DOUBLEBUFFER: |
53 | *value=this->gl_config.double_buffer; |
54 | break; |
55 | case SDL_GL_STENCIL_SIZE: |
56 | *value=this->gl_config.stencil_size; |
57 | break; |
58 | case SDL_GL_DEPTH_SIZE: |
59 | *value=this->gl_config.depth_size; |
60 | break; |
61 | #if (_NTO_VERSION >= 630) |
62 | case SDL_GL_RED_SIZE: |
63 | *value=this->gl_config.red_size; |
64 | break; |
65 | case SDL_GL_GREEN_SIZE: |
66 | *value=this->gl_config.green_size; |
67 | break; |
68 | case SDL_GL_BLUE_SIZE: |
69 | *value=this->gl_config.blue_size; |
70 | break; |
71 | case SDL_GL_ALPHA_SIZE: |
72 | *value=this->gl_config.alpha_size; |
73 | break; |
74 | case SDL_GL_ACCUM_RED_SIZE: |
75 | *value=this->gl_config.accum_red_size; |
76 | break; |
77 | case SDL_GL_ACCUM_GREEN_SIZE: |
78 | *value=this->gl_config.accum_green_size; |
79 | break; |
80 | case SDL_GL_ACCUM_BLUE_SIZE: |
81 | *value=this->gl_config.accum_blue_size; |
82 | break; |
83 | case SDL_GL_ACCUM_ALPHA_SIZE: |
84 | *value=this->gl_config.accum_alpha_size; |
85 | break; |
86 | case SDL_GL_STEREO: |
87 | *value=this->gl_config.stereo; |
88 | break; |
89 | #endif /* 6.3.0 */ |
90 | default: |
91 | *value=0; |
92 | return(-1); |
93 | } |
94 | return 0; |
95 | } |
96 | |
97 | #if (_NTO_VERSION < 630) |
98 | int ph_GL_LoadLibrary(_THIS, const char* path) |
99 | { |
100 | /* if code compiled with SDL_VIDEO_OPENGL, that mean that library already linked */ |
101 | this->gl_config.driver_loaded = 1; |
102 | |
103 | return 0; |
104 | } |
105 | #else |
106 | int ph_GL_LoadLibrary(_THIS, const char* path) |
107 | { |
108 | void* handle; |
109 | int dlopen_flags=RTLD_WORLD | RTLD_GROUP; |
110 | |
111 | if (this->gl_config.dll_handle!=NULL) |
112 | { |
113 | return 0; |
114 | } |
115 | |
116 | handle = dlopen(path, dlopen_flags); |
117 | |
118 | if (handle==NULL) |
119 | { |
120 | SDL_SetError("ph_GL_LoadLibrary(): Could not load OpenGL library"); |
121 | return -1; |
122 | } |
123 | |
124 | this->gl_config.dll_handle = handle; |
125 | this->gl_config.driver_loaded = 1; |
126 | |
127 | SDL_strlcpy(this->gl_config.driver_path, path, SDL_arraysize(this->gl_config.driver_path)); |
128 | |
129 | return 0; |
130 | } |
131 | #endif /* 6.3.0 */ |
132 | |
133 | #if (_NTO_VERSION < 630) |
134 | void* ph_GL_GetProcAddress(_THIS, const char* proc) |
135 | { |
136 | return NULL; |
137 | } |
138 | #else |
139 | void* ph_GL_GetProcAddress(_THIS, const char* proc) |
140 | { |
141 | void* function; |
142 | |
143 | if (this->gl_config.dll_handle==NULL) |
144 | { |
145 | ph_GL_LoadLibrary(this, DEFAULT_OPENGL); |
146 | if (this->gl_config.dll_handle==NULL) |
147 | { |
148 | return NULL; |
149 | } |
150 | } |
151 | |
152 | function=qnxgl_get_func(proc, oglctx, 0); |
153 | if (function==NULL) |
154 | { |
155 | function=dlsym(this->gl_config.dll_handle, proc); |
156 | } |
157 | |
158 | return function; |
159 | } |
160 | #endif /* 6.3.0 */ |
161 | |
162 | #if (_NTO_VERSION < 630) |
163 | int ph_GL_MakeCurrent(_THIS) |
164 | { |
165 | PgSetRegion(PtWidgetRid(window)); |
166 | |
167 | if (oglctx!=NULL) |
168 | { |
169 | PhDCSetCurrent(oglctx); |
170 | } |
171 | |
172 | return 0; |
173 | } |
174 | #else |
175 | int ph_GL_MakeCurrent(_THIS) |
176 | { |
177 | PgSetRegion(PtWidgetRid(window)); |
178 | |
179 | if (oglctx!=NULL) |
180 | { |
181 | if (qnxgl_set_current(oglctx) == -1) |
182 | { |
183 | return -1; |
184 | } |
185 | } |
186 | |
187 | return 0; |
188 | } |
189 | #endif /* 6.3.0 */ |
190 | |
191 | #if (_NTO_VERSION < 630) |
192 | |
193 | /* This code is actual for the Photon3D Runtime which was available prior to 6.3 only */ |
194 | |
195 | int ph_SetupOpenGLContext(_THIS, int width, int height, int bpp, Uint32 flags) |
196 | { |
197 | PhDim_t dim; |
198 | uint64_t OGLAttrib[PH_OGL_MAX_ATTRIBS]; |
199 | int exposepost=0; |
200 | int OGLargc; |
201 | |
202 | dim.w=width; |
203 | dim.h=height; |
204 | |
205 | if ((oglctx!=NULL) && (oglflags==flags) && (oglbpp==bpp)) |
206 | { |
207 | PdOpenGLContextResize(oglctx, &dim); |
208 | PhDCSetCurrent(oglctx); |
209 | return 0; |
210 | } |
211 | else |
212 | { |
213 | if (oglctx!=NULL) |
214 | { |
215 | PhDCSetCurrent(NULL); |
216 | PhDCRelease(oglctx); |
217 | oglctx=NULL; |
218 | exposepost=1; |
219 | } |
220 | } |
221 | |
222 | OGLargc=0; |
223 | if (this->gl_config.depth_size) |
224 | { |
225 | OGLAttrib[OGLargc++]=PHOGL_ATTRIB_DEPTH_BITS; |
226 | OGLAttrib[OGLargc++]=this->gl_config.depth_size; |
227 | } |
228 | if (this->gl_config.stencil_size) |
229 | { |
230 | OGLAttrib[OGLargc++]=PHOGL_ATTRIB_STENCIL_BITS; |
231 | OGLAttrib[OGLargc++]=this->gl_config.stencil_size; |
232 | } |
233 | OGLAttrib[OGLargc++]=PHOGL_ATTRIB_FORCE_SW; |
234 | if (flags & SDL_FULLSCREEN) |
235 | { |
236 | OGLAttrib[OGLargc++]=PHOGL_ATTRIB_FULLSCREEN; |
237 | OGLAttrib[OGLargc++]=PHOGL_ATTRIB_DIRECT; |
238 | OGLAttrib[OGLargc++]=PHOGL_ATTRIB_FULLSCREEN_BEST; |
239 | OGLAttrib[OGLargc++]=PHOGL_ATTRIB_FULLSCREEN_CENTER; |
240 | } |
241 | OGLAttrib[OGLargc++]=PHOGL_ATTRIB_NONE; |
242 | |
243 | if (this->gl_config.double_buffer) |
244 | { |
245 | oglctx=PdCreateOpenGLContext(2, &dim, 0, OGLAttrib); |
246 | } |
247 | else |
248 | { |
249 | oglctx=PdCreateOpenGLContext(1, &dim, 0, OGLAttrib); |
250 | } |
251 | |
252 | if (oglctx==NULL) |
253 | { |
254 | SDL_SetError("ph_SetupOpenGLContext(): cannot create OpenGL context !\n"); |
255 | return -1; |
256 | } |
257 | |
258 | PhDCSetCurrent(oglctx); |
259 | |
260 | PtFlush(); |
261 | |
262 | oglflags=flags; |
263 | oglbpp=bpp; |
264 | |
265 | if (exposepost!=0) |
266 | { |
267 | /* OpenGL context has been recreated, so report about this fact */ |
268 | SDL_PrivateExpose(); |
269 | } |
270 | |
271 | return 0; |
272 | } |
273 | |
274 | #else /* _NTO_VERSION */ |
275 | |
276 | /* This code is actual for the built-in PhGL support, which became available since 6.3 */ |
277 | |
278 | int ph_SetupOpenGLContext(_THIS, int width, int height, int bpp, Uint32 flags) |
279 | { |
280 | qnxgl_buf_attrib_t qnxgl_attribs[PH_OGL_MAX_ATTRIBS]; |
281 | qnxgl_buf_attrib_t* qnxgl_attribs_slide; |
282 | int num_interfaces = 0; |
283 | int num_buffers = 0; |
284 | |
285 | /* Initialize the OpenGL subsystem */ |
286 | |
287 | num_interfaces = qnxgl_init(NULL, NULL, 0); |
288 | |
289 | if (num_interfaces < 0) |
290 | { |
291 | SDL_SetError("ph_SetupOpenGLContext(): cannot initialize OpenGL subsystem !\n"); |
292 | return -1; |
293 | } |
294 | if (num_interfaces == 0) |
295 | { |
296 | SDL_SetError("ph_SetupOpenGLContext(): there are no available OpenGL renderers was found !\n"); |
297 | return -1; |
298 | } |
299 | |
300 | /* Driver is linked */ |
301 | this->gl_config.driver_loaded=1; |
302 | |
303 | /* Initialize the OpenGL context attributes */ |
304 | qnxgl_attribs_slide=qnxgl_attribs; |
305 | |
306 | /* Depth size */ |
307 | if (this->gl_config.depth_size) |
308 | { |
309 | fprintf(stderr, "setted depth size %d\n", this->gl_config.depth_size); |
310 | qnxgl_attribs_slide = qnxgl_attrib_set_depth(qnxgl_attribs_slide, this->gl_config.depth_size); |
311 | } |
312 | |
313 | /* Stencil size */ |
314 | if (this->gl_config.stencil_size) |
315 | { |
316 | qnxgl_attribs_slide = qnxgl_attrib_set_stencil(qnxgl_attribs_slide, this->gl_config.stencil_size); |
317 | } |
318 | |
319 | /* The sum of the accum bits of each channel */ |
320 | if ((this->gl_config.accum_red_size != 0) && (this->gl_config.accum_blue_size != 0) && |
321 | (this->gl_config.accum_green_size != 0)) |
322 | { |
323 | qnxgl_attribs_slide = qnxgl_attrib_set_accum(qnxgl_attribs_slide, |
324 | this->gl_config.accum_red_size + this->gl_config.accum_blue_size + |
325 | this->gl_config.accum_green_size + this->gl_config.accum_alpha_size); |
326 | } |
327 | |
328 | /* Stereo mode */ |
329 | if (this->gl_config.stereo) |
330 | { |
331 | qnxgl_attribs_slide = qnxgl_attrib_set_stereo(qnxgl_attribs_slide); |
332 | } |
333 | |
334 | /* Fullscreen mode */ |
335 | if ((flags & SDL_FULLSCREEN) == SDL_FULLSCREEN) |
336 | { |
337 | qnxgl_attribs_slide = qnxgl_attrib_set_hint_fullscreen(qnxgl_attribs_slide); |
338 | } |
339 | |
340 | /* Double buffering mode */ |
341 | if (this->gl_config.double_buffer) |
342 | { |
343 | num_buffers=2; |
344 | } |
345 | else |
346 | { |
347 | num_buffers=1; |
348 | } |
349 | |
350 | /* Loading the function pointers so we can use the extensions */ |
351 | GLPH_LOAD_FUNCS_GC(oglctx); |
352 | |
353 | /* Set the buffers region to be that of our window's region */ |
354 | qnxgl_attribs_slide = glph_attrib_set_region(qnxgl_attribs_slide, PtWidgetRid(window)); |
355 | |
356 | /* End of the attributes array */ |
357 | qnxgl_attribs_slide = qnxgl_attrib_set_end(qnxgl_attribs_slide); |
358 | |
359 | /* Create the buffers with the specified color model */ |
360 | fprintf(stderr, "ARGB: %d, %d, %d, %d\n", this->gl_config.alpha_size, this->gl_config.red_size, this->gl_config.green_size, this->gl_config.blue_size); |
361 | oglbuffers = qnxgl_buffers_create( |
362 | QNXGL_FORMAT_BEST_RGB, |
363 | /* __QNXGL_BUILD_FORMAT(0, __QNXGL_COLOR_MODEL_RGB, this->gl_config.alpha_size, |
364 | this->gl_config.red_size, this->gl_config.green_size, this->gl_config.blue_size), */ |
365 | num_buffers, width, height, qnxgl_attribs, -1); |
366 | |
367 | |
368 | if (oglbuffers == NULL) |
369 | { |
370 | SDL_SetError("ph_SetupOpenGLContext(): failed to create OpenGL buffers !\n"); |
371 | qnxgl_finish(); |
372 | return -1; |
373 | } |
374 | |
375 | /* Create a QNXGL context for the previously created buffer */ |
376 | oglctx = qnxgl_context_create(oglbuffers, NULL); |
377 | |
378 | if (oglctx == NULL) |
379 | { |
380 | SDL_SetError("ph_SetupOpenGLContext(): failed to create OpenGL context !\n"); |
381 | qnxgl_buffers_destroy(oglbuffers); |
382 | qnxgl_finish(); |
383 | return -1; |
384 | } |
385 | |
386 | /* Attempt to make the context current so we can use OpenGL commands */ |
387 | if (qnxgl_set_current(oglctx) == -1) |
388 | { |
389 | SDL_SetError("ph_SetupOpenGLContext(): failed to make the OpenGL context current !\n"); |
390 | qnxgl_context_destroy(oglctx); |
391 | qnxgl_buffers_destroy(oglbuffers); |
392 | qnxgl_finish(); |
393 | return -1; |
394 | } |
395 | |
396 | PtFlush(); |
397 | |
398 | oglflags=flags; |
399 | oglbpp=bpp; |
400 | |
401 | return 0; |
402 | } |
403 | |
404 | #endif /* _NTO_VERSION */ |
405 | |
406 | #endif /* SDL_VIDEO_OPENGL */ |