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

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