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

Last change on this file since 331 was 331, checked in by epyon, 11 years ago
  • texture types (1D,2D,Rect,3D,Cube - not all fully supported yet)
  • full framebuffer support
  • fixes to texture support
  • minor fixes
File size: 9.9 KB
RevLine 
[319]1// Copyright (C) 2012-2014 ChaosForge Ltd
[5]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
[319]7#include "nv/core/common.hh"
8#include "nv/core/range.hh"
[5]9#include "nv/lib/gl.hh"
10
11#if defined( NV_GL_DYNAMIC )
12
[319]13#include "nv/core/library.hh"
[5]14
15#if defined( NV_SDL_GL )
[170]16#       include "nv/lib/sdl.hh"
[5]17#endif
18
[245]19// for wgl support
20#if NV_PLATFORM == NV_WINDOWS
21#include <windows.h>
22#endif
23
[323]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;
[167]26#define NV_GL_FUN_EXT NV_GL_FUN
27#include <nv/lib/detail/gl_functions.inc>
[245]28#if NV_PLATFORM == NV_WINDOWS
29#include <nv/lib/detail/wgl_functions.inc>
30#endif
[311]31#include <nv/lib/detail/gl_ext/gl_ext_all_functions.inc>
[245]32#undef NV_GL_FUN_REN
[167]33#undef NV_GL_FUN_EXT
34#undef NV_GL_FUN
[5]35
[245]36static nv::library gl_library;
[311]37static nv::gl_extensions gl_loaded_extensions = nv::gl_extensions(0);
[323]38static void* (NV_GL_APIENTRY *gl_ext_loader) ( const char* ) = nullptr;
[245]39static bool gl_library_loaded = false;
40static bool wgl_library_loaded = false;
41
[311]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
[323]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// };
[311]55
56
57static void* load_gl_ext_symbol_impl( const char* name, nv::log_level fail_level = nv::LOG_DEBUG )
[5]58{
[311]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;
[5]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);
[311]85        *(void **) (&gl_ext_loader) = SDL_GL_GetProcAddress;
[5]86#else
[245]87        if ( !gl_library.is_open() ) gl_library.open( path );
[109]88
[5]89#       if NV_PLATFORM == NV_WINDOWS
90#               define NV_GL_LOAD( symbol ) *(void **) (&symbol) = gl_library.get(#symbol);
[311]91                *(void **) (&gl_ext_loader) = gl_library.get("wglGetProcAddress");
92#               define NV_GL_LOAD_EXT( symbol ) *(void **) (&symbol) = gl_ext_loader(#symbol);
[204]93#       elif (NV_PLATFORM == NV_LINUX || NV_PLATFORM == NV_APPLE)
[5]94#               define NV_GL_LOAD( symbol ) *(void **) (&symbol) = gl_library.get(#symbol);
[311]95                *(void **) (&gl_ext_loader) = gl_library.get("glXGetProcAddress");
96#               define NV_GL_LOAD_EXT( symbol ) *(void **) (&symbol) = gl_ext_loader(#symbol);
[5]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
[167]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
[5]108
109#       undef NV_GL_LOAD
110#       undef NV_GL_LOAD_EXT
[245]111        gl_library_loaded = true;
[5]112        return true;
113}
114
[311]115bool nv::load_wgl_library( const char* path /*= NV_GL_PATH */, bool force_reload )
[245]116{
[311]117        if ( wgl_library_loaded && !force_reload ) return true;
[245]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);
[311]123        (void **) (&gl_ext_loader) = SDL_GL_GetProcAddress;
[245]124#else //
125        if ( !gl_library.is_open() ) gl_library.open( path );
126
[311]127        *(void **) (&gl_ext_loader) = gl_library.get("wglGetProcAddress");
[245]128#define NV_GL_LOAD( symbol ) *(void **) (&symbol) = gl_library.get(#symbol);
[311]129#define NV_GL_LOAD_EXT( symbol ) *(void **) (&symbol) = gl_ext_loader(#symbol);
[245]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;
[20]147#endif
[245]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
[323]181        /*DWORD err = */GetLastError();
[245]182        RegisterClass(&wndClass);
[323]183        /*err = */GetLastError();
[245]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
[311]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)" );
[331]275                gl_loaded_extensions = (gl_extensions)( gl_loaded_extensions | (unsigned)extension );
[311]276                return false;
277        }
278        NV_LOG( nv::LOG_NOTICE, "load_gl_extension - failed to load extension \"" << name << "\" (" << count << "/" << fail_count << " symbols loaded)" );
279        return true;
280}
281
282nv::gl_extensions nv::load_gl_extensions( uint32 extensions )
283{
284        gl_extensions result = gl_extensions(0);
285        for ( auto ext : nv::bits( gl_extensions(extensions) ) )
286        {
287                if ( load_gl_extension(ext) ) result = gl_extensions( result | ext );
288        }
289        return result;
290}
291
292bool nv::is_gl_extension_loaded( gl_extensions extensions )
293{
294        return ( gl_loaded_extensions & extensions ) != 0;
295}
296
297bool nv::are_gl_extensions_loaded( uint32 extensions )
298{
299        for ( auto ext : nv::bits( gl_extensions(extensions) ) )
300        {
301                if ( !is_gl_extension_loaded(ext) ) return false;
302        }
303        return true;
304}
305
Note: See TracBrowser for help on using the repository browser.