view src/video/photon/SDL_ph_gl.c @ 910:4ab6d1fd028f

Date: Sat, 26 Jun 2004 14:58:42 +0300 From: "Mike Gorchak" Subject: QNX 6.3 fixes for SDL Sam, I've added new OpenGL framework for SDL, which appeared in the new QNX version - 6.3. I've leave compatibility with previous QNX versions. And I've moved all GL specific functions to the separate module, like it done for the other platforms. SDL is now ready for the QNX 6.3 :)
author Sam Lantinga <slouken@libsdl.org>
date Sun, 18 Jul 2004 19:46:38 +0000
parents
children c9b51268668f
line wrap: on
line source

/*
    SDL - Simple DirectMedia Layer
    Copyright (C) 1997-2004 Sam Lantinga

    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Library General Public
    License as published by the Free Software Foundation; either
    version 2 of the License, or (at your option) any later version.

    This library is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    Library General Public License for more details.

    You should have received a copy of the GNU Library General Public
    License along with this library; if not, write to the Free
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

    Sam Lantinga
    slouken@libsdl.org
*/

#ifdef SAVE_RCSID
    char rcsid = "@(#) $Id$";
#endif

#include <dlfcn.h>
#include "SDL.h"
#include "SDL_ph_gl.h"

#ifdef HAVE_OPENGL

#if (_NTO_VERSION >= 630)
    /* PhotonGL functions */
    GLPH_DECLARE_FUNCS;
#endif /* 6.3.0 */

#if (_NTO_VERSION < 630)
void ph_GL_SwapBuffers(_THIS)
{
    PgSetRegion(PtWidgetRid(window));
    PdOpenGLContextSwapBuffers(oglctx);
}
#else
void ph_GL_SwapBuffers(_THIS)
{
    qnxgl_swap_buffers(oglbuffers);
}
#endif /* 6.3.0 */

int ph_GL_GetAttribute(_THIS, SDL_GLattr attrib, int* value)
{
    switch (attrib)
    {
        case SDL_GL_DOUBLEBUFFER:
             *value=this->gl_config.double_buffer;
             break;
        case SDL_GL_STENCIL_SIZE:
             *value=this->gl_config.stencil_size;
             break;
        case SDL_GL_DEPTH_SIZE:
             *value=this->gl_config.depth_size;
             break;
#if (_NTO_VERSION >= 630)
        case SDL_GL_RED_SIZE:
             *value=this->gl_config.red_size;
             break;
        case SDL_GL_GREEN_SIZE:
             *value=this->gl_config.green_size;
             break;
        case SDL_GL_BLUE_SIZE:
             *value=this->gl_config.blue_size;
             break;
        case SDL_GL_ALPHA_SIZE:
             *value=this->gl_config.alpha_size;
             break;
        case SDL_GL_ACCUM_RED_SIZE:
             *value=this->gl_config.accum_red_size;
             break;
        case SDL_GL_ACCUM_GREEN_SIZE:
             *value=this->gl_config.accum_green_size;
             break;
        case SDL_GL_ACCUM_BLUE_SIZE:
             *value=this->gl_config.accum_blue_size;
             break;
        case SDL_GL_ACCUM_ALPHA_SIZE:
             *value=this->gl_config.accum_alpha_size;
             break;
        case SDL_GL_STEREO:
             *value=this->gl_config.stereo;
             break;
#endif /* 6.3.0 */
        default:
             *value=0;
             return(-1);
    }
    return 0;
}

#if (_NTO_VERSION < 630)
int ph_GL_LoadLibrary(_THIS, const char* path)
{
    /* if code compiled with HAVE_OPENGL, that mean that library already linked */
    this->gl_config.driver_loaded = 1;

    return 0;
}
#else
int ph_GL_LoadLibrary(_THIS, const char* path)
{
    void* handle;
    int dlopen_flags=RTLD_WORLD | RTLD_GROUP;

    if (this->gl_config.dll_handle!=NULL)
    {
        return 0;
    }

    handle = dlopen(path, dlopen_flags);

    if (handle==NULL)
    {
        SDL_SetError("ph_GL_LoadLibrary(): Could not load OpenGL library");
        return -1;
    }

    this->gl_config.dll_handle = handle;
    this->gl_config.driver_loaded = 1;

    strncpy(this->gl_config.driver_path, path, sizeof(this->gl_config.driver_path)-1);

    return 0;
}
#endif /* 6.3.0 */

#if (_NTO_VERSION < 630)
void* ph_GL_GetProcAddress(_THIS, const char* proc)
{
    return NULL;
}
#else
void* ph_GL_GetProcAddress(_THIS, const char* proc)
{
    void* function;

    if (this->gl_config.dll_handle==NULL)
    {
        ph_GL_LoadLibrary(this, DEFAULT_OPENGL);
        if (this->gl_config.dll_handle==NULL)
        {
            return NULL;
        }
    }
   
    function=qnxgl_get_func(proc, oglctx, 0);
    if (function==NULL)
    {
        function=dlsym(this->gl_config.dll_handle, proc);
    }

    return function;
}
#endif /* 6.3.0 */

#if (_NTO_VERSION < 630)
int ph_GL_MakeCurrent(_THIS)
{
    PgSetRegion(PtWidgetRid(window));

    if (oglctx!=NULL)
    {
        PhDCSetCurrent(oglctx);
    }

    return 0;
}
#else
int ph_GL_MakeCurrent(_THIS)
{
    PgSetRegion(PtWidgetRid(window));

    if (oglctx!=NULL)
    {
        if (qnxgl_set_current(oglctx) == -1)
        {
           return -1;
        }
    }

    return 0;
}
#endif /* 6.3.0 */

#if (_NTO_VERSION < 630)

/* This code is actual for the Photon3D Runtime which was available prior to 6.3 only */

int ph_SetupOpenGLContext(_THIS, int width, int height, int bpp, Uint32 flags)
{
    PhDim_t dim;
    uint64_t OGLAttrib[PH_OGL_MAX_ATTRIBS];
    int exposepost=0;
    int OGLargc;

    dim.w=width;
    dim.h=height;
    
    if ((oglctx!=NULL) && (oglflags==flags) && (oglbpp==bpp))
    {
       PdOpenGLContextResize(oglctx, &dim);
       PhDCSetCurrent(oglctx);
       return 0;
    }
    else
    {
       if (oglctx!=NULL)
       {
          PhDCSetCurrent(NULL);
          PhDCRelease(oglctx);
          oglctx=NULL;
          exposepost=1;
       }
    }

    OGLargc=0;
    if (this->gl_config.depth_size)
    {
        OGLAttrib[OGLargc++]=PHOGL_ATTRIB_DEPTH_BITS;
        OGLAttrib[OGLargc++]=this->gl_config.depth_size;
    }
    if (this->gl_config.stencil_size)
    {
        OGLAttrib[OGLargc++]=PHOGL_ATTRIB_STENCIL_BITS;
        OGLAttrib[OGLargc++]=this->gl_config.stencil_size;
    }
    OGLAttrib[OGLargc++]=PHOGL_ATTRIB_FORCE_SW;
    if (flags & SDL_FULLSCREEN)
    {
        OGLAttrib[OGLargc++]=PHOGL_ATTRIB_FULLSCREEN;
        OGLAttrib[OGLargc++]=PHOGL_ATTRIB_DIRECT;
        OGLAttrib[OGLargc++]=PHOGL_ATTRIB_FULLSCREEN_BEST;
        OGLAttrib[OGLargc++]=PHOGL_ATTRIB_FULLSCREEN_CENTER;
    }
    OGLAttrib[OGLargc++]=PHOGL_ATTRIB_NONE;

    if (this->gl_config.double_buffer)
    {
        oglctx=PdCreateOpenGLContext(2, &dim, 0, OGLAttrib);
    }
    else
    {
        oglctx=PdCreateOpenGLContext(1, &dim, 0, OGLAttrib);
    }

    if (oglctx==NULL)
    {
        SDL_SetError("ph_SetupOpenGLContext(): cannot create OpenGL context !\n");
        return -1;
    }

    PhDCSetCurrent(oglctx);

    PtFlush();

    oglflags=flags;
    oglbpp=bpp;

    if (exposepost!=0)
    {
        /* OpenGL context has been recreated, so report about this fact */
        SDL_PrivateExpose();
    }

    return 0;
}

#else /* _NTO_VERSION */

/* This code is actual for the built-in PhGL support, which became available since 6.3 */

int ph_SetupOpenGLContext(_THIS, int width, int height, int bpp, Uint32 flags)
{
    qnxgl_buf_attrib_t qnxgl_attribs[PH_OGL_MAX_ATTRIBS];
    qnxgl_buf_attrib_t* qnxgl_attribs_slide;
    int num_interfaces = 0;
    int num_buffers = 0;

    /* Initialize the OpenGL subsystem */

    num_interfaces = qnxgl_init(NULL, NULL, 0);

    if (num_interfaces < 0)
    {
        SDL_SetError("ph_SetupOpenGLContext(): cannot initialize OpenGL subsystem !\n");
        return -1;
    }
    if (num_interfaces == 0)
    {
        SDL_SetError("ph_SetupOpenGLContext(): there are no available OpenGL renderers was found !\n");
        return -1;
    }

    /* Driver is linked */
    this->gl_config.driver_loaded=1;

    /* Initialize the OpenGL context attributes */
    qnxgl_attribs_slide=qnxgl_attribs;

    /* Depth size */
    if (this->gl_config.depth_size)
    {
        fprintf(stderr, "setted depth size %d\n", this->gl_config.depth_size);
        qnxgl_attribs_slide = qnxgl_attrib_set_depth(qnxgl_attribs_slide, this->gl_config.depth_size);
    }

    /* Stencil size */
    if (this->gl_config.stencil_size)
    {
        qnxgl_attribs_slide = qnxgl_attrib_set_stencil(qnxgl_attribs_slide, this->gl_config.stencil_size);
    }

    /* The sum of the accum bits of each channel */
    if ((this->gl_config.accum_red_size != 0) && (this->gl_config.accum_blue_size != 0) &&
        (this->gl_config.accum_green_size != 0))
    {
        qnxgl_attribs_slide = qnxgl_attrib_set_accum(qnxgl_attribs_slide,
           this->gl_config.accum_red_size + this->gl_config.accum_blue_size +
           this->gl_config.accum_green_size + this->gl_config.accum_alpha_size);
    }
    
    /* Stereo mode */
    if (this->gl_config.stereo)
    {
        qnxgl_attribs_slide = qnxgl_attrib_set_stereo(qnxgl_attribs_slide);
    }

    /* Fullscreen mode */
    if ((flags & SDL_FULLSCREEN) == SDL_FULLSCREEN)
    {
        qnxgl_attribs_slide = qnxgl_attrib_set_hint_fullscreen(qnxgl_attribs_slide);
    }
    
    /* Double buffering mode */
    if (this->gl_config.double_buffer)
    {
        num_buffers=2;
    }
    else
    {
        num_buffers=1;
    }

    /* Loading the function pointers so we can use the extensions */
    GLPH_LOAD_FUNCS_GC(oglctx);

    /* Set the buffers region to be that of our window's region */
    qnxgl_attribs_slide = glph_attrib_set_region(qnxgl_attribs_slide, PtWidgetRid(window));

    /* End of the attributes array */
    qnxgl_attribs_slide = qnxgl_attrib_set_end(qnxgl_attribs_slide);
    
    /* Create the buffers with the specified color model */
    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);
    oglbuffers = qnxgl_buffers_create(
                   QNXGL_FORMAT_BEST_RGB,
/*                 __QNXGL_BUILD_FORMAT(0, __QNXGL_COLOR_MODEL_RGB, this->gl_config.alpha_size,
                     this->gl_config.red_size, this->gl_config.green_size, this->gl_config.blue_size), */
                 num_buffers, width, height, qnxgl_attribs, -1);


    if (oglbuffers == NULL)
    {
        SDL_SetError("ph_SetupOpenGLContext(): failed to create OpenGL buffers !\n");
        qnxgl_finish();
        return -1;
    }

    /* Create a QNXGL context for the previously created buffer */
    oglctx = qnxgl_context_create(oglbuffers, NULL);

    if (oglctx == NULL)
    {
        SDL_SetError("ph_SetupOpenGLContext(): failed to create OpenGL context !\n");
        qnxgl_buffers_destroy(oglbuffers);
        qnxgl_finish();
        return -1;
    }

    /* Attempt to make the context current so we can use OpenGL commands */
    if (qnxgl_set_current(oglctx) == -1)
    {
        SDL_SetError("ph_SetupOpenGLContext(): failed to make the OpenGL context current !\n");
        qnxgl_context_destroy(oglctx);
        qnxgl_buffers_destroy(oglbuffers);
        qnxgl_finish();
        return -1;
    }

    PtFlush();

    oglflags=flags;
    oglbpp=bpp;

    return 0;
}

#endif /* _NTO_VERSION */

#endif /* HAVE_OPENGL */