1/*
2    SDL - Simple DirectMedia Layer
3    Copyright (C) 1997-2006 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)
36void ph_GL_SwapBuffers(_THIS)
37{
38    PgSetRegion(PtWidgetRid(window));
39    PdOpenGLContextSwapBuffers(oglctx);
40}
41#else
42void ph_GL_SwapBuffers(_THIS)
43{
44    qnxgl_swap_buffers(oglbuffers);
45}
46#endif /* 6.3.0 */
47
48int 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)
98int 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
106int 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)
134void* ph_GL_GetProcAddress(_THIS, const char* proc)
135{
136    return NULL;
137}
138#else
139void* 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)
163int 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
175int 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
195int 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
278int 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 */
407