source: trunk/src/lib/gl.cc @ 326

Last change on this file since 326 was 323, checked in by epyon, 11 years ago
  • nova now compiles again under all three compilers with -Winsane and no warnings
File size: 9.8 KB
Line 
1// Copyright (C) 2012-2014 ChaosForge Ltd
2// http://chaosforge.org/
3//
4// This file is part of NV Libraries.
5// For conditions of distribution and use, see copyright notice in nv.hh
6
7#include "nv/core/common.hh"
8#include "nv/core/range.hh"
9#include "nv/lib/gl.hh"
10
11#if defined( NV_GL_DYNAMIC )
12
13#include "nv/core/library.hh"
14
15#if defined( NV_SDL_GL )
16#       include "nv/lib/sdl.hh"
17#endif
18
19// for wgl support
20#if NV_PLATFORM == NV_WINDOWS
21#include <windows.h>
22#endif
23
24#define NV_GL_FUN( rtype, fname, fparams ) rtype (NV_GL_APIENTRY *fname) fparams = nullptr;
25#define NV_GL_FUN_REN( rtype, fname, rname, fparams ) rtype (NV_GL_APIENTRY *rname) fparams = nullptr;
26#define NV_GL_FUN_EXT NV_GL_FUN
27#include <nv/lib/detail/gl_functions.inc>
28#if NV_PLATFORM == NV_WINDOWS
29#include <nv/lib/detail/wgl_functions.inc>
30#endif
31#include <nv/lib/detail/gl_ext/gl_ext_all_functions.inc>
32#undef NV_GL_FUN_REN
33#undef NV_GL_FUN_EXT
34#undef NV_GL_FUN
35
36static nv::library gl_library;
37static nv::gl_extensions gl_loaded_extensions = nv::gl_extensions(0);
38static void* (NV_GL_APIENTRY *gl_ext_loader) ( const char* ) = nullptr;
39static bool gl_library_loaded = false;
40static bool wgl_library_loaded = false;
41
42static const char *gl_extension_names[] = {
43        "UNKNOWN",
44#define NV_GL_EXTENSION( count, id, name ) "GL_EXT_"#id,
45#include <nv/lib/detail/gl_ext/gl_ext_info.inc>
46#undef NV_GL_EXTENSION
47};
48
49// static const char *gl_extension_ids[] = {
50//      "UNKNOWN",
51// #define NV_GL_EXTENSION( count, id, name ) #id,
52// #include <nv/lib/detail/gl_ext/gl_ext_info.inc>
53// #undef NV_GL_EXTENSION
54// };
55
56
57static void* load_gl_ext_symbol_impl( const char* name, nv::log_level fail_level = nv::LOG_DEBUG )
58{
59        void* result = gl_ext_loader( name );
60        NV_LOG( ( result ? nv::LOG_DEBUG : fail_level ), "load_gl_ext_symbol : " << name << ( result ? " succeded." : "failed." ) );
61        return result;
62}
63
64static void* load_gl_ext_symbol( const char* name, bool iterate, const char* ext )
65{
66        void * result        = nullptr;
67        result = load_gl_ext_symbol_impl( ext ? ( std::string(name) + ext ).c_str() : name );
68        if ( result ) return result;
69        if ( iterate )
70        {
71                result = gl_ext_loader( (std::string(name) + "ARB").c_str() );
72                if ( result ) return result;
73                result = gl_ext_loader( (std::string(name) + "EXT").c_str() );
74                if ( result ) return result;
75        }
76        return result;
77}
78
79bool nv::load_gl_library( const char* path, bool force_reload )
80{
81        if ( gl_library_loaded && !force_reload ) return true;
82#if defined( NV_SDL_GL )
83#               define NV_GL_LOAD( symbol ) *(void **) (&symbol) = SDL_GL_GetProcAddress(#symbol);
84#               define NV_GL_LOAD_EXT( symbol ) *(void **) (&symbol) = SDL_GL_GetProcAddress(#symbol);
85        *(void **) (&gl_ext_loader) = SDL_GL_GetProcAddress;
86#else
87        if ( !gl_library.is_open() ) gl_library.open( path );
88
89#       if NV_PLATFORM == NV_WINDOWS
90#               define NV_GL_LOAD( symbol ) *(void **) (&symbol) = gl_library.get(#symbol);
91                *(void **) (&gl_ext_loader) = gl_library.get("wglGetProcAddress");
92#               define NV_GL_LOAD_EXT( symbol ) *(void **) (&symbol) = gl_ext_loader(#symbol);
93#       elif (NV_PLATFORM == NV_LINUX || NV_PLATFORM == NV_APPLE)
94#               define NV_GL_LOAD( symbol ) *(void **) (&symbol) = gl_library.get(#symbol);
95                *(void **) (&gl_ext_loader) = gl_library.get("glXGetProcAddress");
96#               define NV_GL_LOAD_EXT( symbol ) *(void **) (&symbol) = gl_ext_loader(#symbol);
97#       else
98#               define NV_GL_LOAD( symbol ) *(void **) (&symbol) = gl_library.get(#symbol);
99#               define NV_GL_LOAD_EXT( symbol ) *(void **) (&symbol) = gl_library.get(#symbol);
100#       endif
101#endif
102
103#       define NV_GL_FUN( rtype, fname, fparams ) NV_GL_LOAD( fname )
104#       define NV_GL_FUN_EXT( rtype, fname, fparams ) NV_GL_LOAD_EXT( fname )
105#       include <nv/lib/detail/gl_functions.inc>
106#       undef NV_GL_FUN_EXT
107#       undef NV_GL_FUN
108
109#       undef NV_GL_LOAD
110#       undef NV_GL_LOAD_EXT
111        gl_library_loaded = true;
112        return true;
113}
114
115bool nv::load_wgl_library( const char* path /*= NV_GL_PATH */, bool force_reload )
116{
117        if ( wgl_library_loaded && !force_reload ) return true;
118#if NV_PLATFORM == NV_WINDOWS
119#if defined( NV_SDL_GL )
120#               define NV_GL_LOAD( symbol ) *(void **) (&symbol) = SDL_GL_GetProcAddress(#symbol);
121#               define NV_GL_LOAD_EXT( symbol ) *(void **) (&symbol) = SDL_GL_GetProcAddress(#symbol);
122#           define NV_GL_LOAD_REN( fname, rname )  *(void **) (&rname) = SDL_GL_GetProcAddress(#fname);
123        (void **) (&gl_ext_loader) = SDL_GL_GetProcAddress;
124#else //
125        if ( !gl_library.is_open() ) gl_library.open( path );
126
127        *(void **) (&gl_ext_loader) = gl_library.get("wglGetProcAddress");
128#define NV_GL_LOAD( symbol ) *(void **) (&symbol) = gl_library.get(#symbol);
129#define NV_GL_LOAD_EXT( symbol ) *(void **) (&symbol) = gl_ext_loader(#symbol);
130#define NV_GL_LOAD_REN( fname, rname ) *(void **) (&rname) = gl_library.get(#fname);
131#endif
132#       define NV_GL_FUN( rtype, fname, fparams ) NV_GL_LOAD( fname )
133#       define NV_GL_FUN_EXT( rtype, fname, fparams ) NV_GL_LOAD_EXT( fname )
134#       define NV_GL_FUN_REN( rtype, fname, rname, fparams ) NV_GL_LOAD_REN( fname, rname )
135#       include <nv/lib/detail/wgl_functions.inc>
136#       undef NV_GL_FUN_REN
137#       undef NV_GL_FUN_EXT
138#       undef NV_GL_FUN
139
140#       undef NV_GL_LOAD
141#       undef NV_GL_LOAD_EXT
142#       undef NV_GL_LOAD_REN
143        wgl_library_loaded = true;
144        return true;
145#else
146        return false;
147#endif
148}
149
150#endif // NV_DYNAMIC
151
152bool nv::load_gl_no_context( const char* path /*= NV_GL_PATH */ )
153{
154#if NV_PLATFORM == NV_WINDOWS
155        if ( !gl_library.is_open() ) gl_library.open( path );
156        if ( wgl_library_loaded ) return true;
157
158        HGLRC (NV_GL_APIENTRY *wgl_createcontext) (HDC)        = nullptr;
159        BOOL  (NV_GL_APIENTRY *wgl_makecurrent)   (HDC, HGLRC) = nullptr;
160        BOOL  (NV_GL_APIENTRY *wgl_deletecontext) (HGLRC)      = nullptr;
161
162        *(void **) &wgl_createcontext = gl_library.get("wglCreateContext");
163        *(void **) &wgl_makecurrent   = gl_library.get("wglMakeCurrent");
164        *(void **) &wgl_deletecontext = gl_library.get("wglDeleteContext");
165
166        WNDCLASS wndClass;
167        HINSTANCE hInstance = 0;
168
169        ZeroMemory(&wndClass, sizeof(WNDCLASS));
170
171        wndClass.cbClsExtra = 0;
172        wndClass.cbWndExtra = 0;                       
173        wndClass.hCursor = LoadCursor(NULL, IDC_ARROW);
174        wndClass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
175        wndClass.hInstance = hInstance;
176        wndClass.lpfnWndProc = (WNDPROC) DefWindowProc;
177        wndClass.lpszClassName = TEXT("Dummy67789");
178        wndClass.lpszMenuName = 0;
179        wndClass.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
180
181        /*DWORD err = */GetLastError();
182        RegisterClass(&wndClass);
183        /*err = */GetLastError();
184
185
186        HWND hWndFake = CreateWindow(TEXT("Dummy67789"), "FAKE", WS_OVERLAPPEDWINDOW | WS_MAXIMIZE | WS_CLIPCHILDREN,
187                0, 0, CW_USEDEFAULT, CW_USEDEFAULT, NULL,
188                NULL, GetModuleHandle(nullptr), NULL);
189
190        HDC hDC = GetDC(hWndFake);
191
192        PIXELFORMATDESCRIPTOR pfd;
193        memset(&pfd, 0, sizeof(PIXELFORMATDESCRIPTOR));
194        pfd.nSize= sizeof(PIXELFORMATDESCRIPTOR);
195        pfd.nVersion   = 1;
196        pfd.dwFlags    = PFD_DOUBLEBUFFER | PFD_SUPPORT_OPENGL | PFD_DRAW_TO_WINDOW;
197        pfd.iPixelType = PFD_TYPE_RGBA;
198        pfd.cColorBits = 32;
199        pfd.cDepthBits = 24;
200        pfd.iLayerType = PFD_MAIN_PLANE;
201
202        int iPixelFormat = ChoosePixelFormat(hDC, &pfd);
203        if (iPixelFormat == 0)return false;
204
205        if(!SetPixelFormat(hDC, iPixelFormat, &pfd))return false;
206
207        HGLRC hRCFake = wgl_createcontext(hDC);
208        wgl_makecurrent(hDC, hRCFake);
209
210        LoadLibrary( "gdi32.dll" );
211        bool gl_loaded = nv::load_gl_library( path );
212        bool wgl_loaded = nv::load_wgl_library( path );
213        bool result = gl_loaded && wgl_loaded;
214
215        wgl_makecurrent(NULL, NULL);
216        wgl_deletecontext(hRCFake);
217        DestroyWindow(hWndFake);
218        return result;
219#else
220        return false;
221#endif
222}
223
224const char* nv::get_gl_extension_name( gl_extensions extension )
225{
226        uint32 value = uint32( extension );
227        uint32 index = 0;
228        while ( value >>= 1 ) index++;
229        return NV_SAFE_ARRAY(gl_extension_names, index+1, gl_extension_names[0] );
230}
231
232bool nv::load_gl_extension( gl_extensions extension )
233{
234        const char* name = get_gl_extension_name( extension );
235        // TODO: first check for support using gl mechanisms
236        //       see SDL 2.0 SDL_video.c
237        if ( !gl_library.is_open() )
238        {
239                NV_LOG( nv::LOG_ERROR, "load_gl_extension used, while gl_library was closed!" );
240                return false;
241        }
242
243        if ( gl_ext_loader == nullptr )
244        {
245                NV_LOG( nv::LOG_ERROR, "load_gl_extension used, while gl_ext_loader was undefined!" );
246                return false;
247        }
248        NV_LOG( nv::LOG_DEBUG, "load_gl_extension - loading extension - \"" << name << "\"..." );
249
250        uint32 count      = 0;
251        uint32 fail_count = 0;
252
253#       define NV_GL_FUN_EXT( rtype, symbol, fparams ) \
254        *(void **) (&symbol) = load_gl_ext_symbol(#symbol, true, nullptr); \
255        count++; if ( !symbol ) fail_count++;
256
257        switch ( extension )
258        {
259        case GL_EXT_FRAMEBUFFER_BLIT : {
260#include <nv/lib/detail/gl_ext/gl_ext_framebuffer_blit_functions.inc>
261        } break;
262        case GL_EXT_FRAMEBUFFER_OBJECT : {
263#include <nv/lib/detail/gl_ext/gl_ext_framebuffer_object_functions.inc>
264        } break;
265        default : {
266                NV_LOG( nv::LOG_ERROR, "load_gl_extension - unknown extension \"" << name << "\"!" );
267                return nullptr;
268        }
269        }
270#       undef NV_GL_FUN_EXT
271
272        if ( fail_count == 0 )
273        {
274                NV_LOG( nv::LOG_NOTICE, "load_gl_extension - extension \"" << name << "\" loaded (" << count << " symbols)" );
275                return false;
276        }
277        NV_LOG( nv::LOG_NOTICE, "load_gl_extension - failed to load extension \"" << name << "\" (" << count << "/" << fail_count << " symbols loaded)" );
278        return true;
279}
280
281nv::gl_extensions nv::load_gl_extensions( uint32 extensions )
282{
283        gl_extensions result = gl_extensions(0);
284        for ( auto ext : nv::bits( gl_extensions(extensions) ) )
285        {
286                if ( load_gl_extension(ext) ) result = gl_extensions( result | ext );
287        }
288        return result;
289}
290
291bool nv::is_gl_extension_loaded( gl_extensions extensions )
292{
293        return ( gl_loaded_extensions & extensions ) != 0;
294}
295
296bool nv::are_gl_extensions_loaded( uint32 extensions )
297{
298        for ( auto ext : nv::bits( gl_extensions(extensions) ) )
299        {
300                if ( !is_gl_extension_loaded(ext) ) return false;
301        }
302        return true;
303}
304
Note: See TracBrowser for help on using the repository browser.