Skip to content
Permalink
Branch: master
Find file Copy path
Find file Copy path
Fetching contributors…
Cannot retrieve contributors at this time
960 lines (785 sloc) 25.6 KB
/* ______ ___ ___
* /\ _ \ /\_ \ /\_ \
* \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___
* \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\
* \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \
* \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/
* \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/
* /\____/
* \_/__/
*
* OpenGL extensions management subsystem
*
* By Elias Pschernig and Milan Mimica.
*
* Based on AllegroGL extensions management.
*/
#include <ctype.h>
#include <math.h>
#include <stdio.h>
#include <string.h>
#include "allegro5/allegro.h"
#include "allegro5/allegro_opengl.h"
#include "allegro5/opengl/gl_ext.h"
#include "allegro5/internal/aintern.h"
#include "allegro5/internal/aintern_opengl.h"
#include "allegro5/internal/aintern_display.h"
#include "allegro5/internal/aintern_system.h"
/* We need some driver specific details not worth of a vtable entry. */
#if defined ALLEGRO_WINDOWS
#include "../win/wgl.h"
#elif defined ALLEGRO_UNIX && !defined ALLEGRO_EXCLUDE_GLX
#include "allegro5/internal/aintern_xdisplay.h"
#include "allegro5/internal/aintern_xsystem.h"
#endif
#if defined ALLEGRO_MACOSX
#include <OpenGL/glu.h>
#elif !defined ALLEGRO_CFG_OPENGLES
#include <GL/glu.h>
#endif
ALLEGRO_DEBUG_CHANNEL("opengl")
#ifdef ALLEGRO_HAVE_DYNAMIC_LINK
#include <dlfcn.h>
/* Handle for dynamic library libGL.so */
static void *__libgl_handle = NULL;
/* Pointer to glXGetProcAddressARB */
typedef void *(*GLXGETPROCADDRESSARBPROC) (const GLubyte *);
static GLXGETPROCADDRESSARBPROC alXGetProcAddress;
#else /* #ifdef ALLEGRO_HAVE_DYNAMIC_LINK */
/* Tries static linking */
/* FIXME: set ALLEGRO_GLXGETPROCADDRESSARB on configure time, if
* glXGetProcAddressARB must be used!
*/
#if defined ALLEGRO_GLXGETPROCADDRESSARB
#define alXGetProcAddress glXGetProcAddressARB
#elif defined ALLEGRO_RASPBERRYPI
#define alXGetProcAddress eglGetProcAddress
#else
#define alXGetProcAddress glXGetProcAddress
#endif
#endif /* #ifdef ALLEGRO_HAVE_DYNAMIC_LINK */
#ifdef ALLEGRO_MACOSX
#include <CoreFoundation/CoreFoundation.h>
static CFBundleRef opengl_bundle_ref;
#endif
/* Define the GL API pointers.
* Example:
* _ALLEGRO_glBlendEquation_t _al_glBlendEquation = NULL;
*/
#define AGL_API(type, name, args) _ALLEGRO_gl##name##_t _al_gl##name = NULL;
# include "allegro5/opengl/GLext/gl_ext_api.h"
#undef AGL_API
#ifdef ALLEGRO_WINDOWS
#define AGL_API(type, name, args) _ALLEGRO_wgl##name##_t _al_wgl##name = NULL;
# include "allegro5/opengl/GLext/wgl_ext_api.h"
#undef AGL_API
#elif defined ALLEGRO_UNIX
#define AGL_API(type, name, args) _ALLEGRO_glX##name##_t _al_glX##name = NULL;
# include "allegro5/opengl/GLext/glx_ext_api.h"
#undef AGL_API
#endif
static uint32_t parse_opengl_version(const char *s)
{
char *p = (char *) s;
int v[4] = {0, 0, 0, 0};
int n;
uint32_t ver;
/* For OpenGL ES version strings have the form:
* "OpenGL ES-<profile> <major>.<minor>"
* So for example: "OpenGL ES-CM 2.0". We simply skip any non-digit
* characters and then parse it like for normal OpenGL.
*/
while (*p && !isdigit(*p)) {
p++;
}
/* e.g. "4.0.0 Vendor blah blah" */
for (n = 0; n < 4; n++) {
char *end;
long l;
errno = 0;
l = strtol(p, &end, 10);
if (errno)
break;
v[n] = _ALLEGRO_CLAMP(0, l, 255);
if (*end != '.')
break;
p = end + 1; /* skip dot */
}
ver = (v[0] << 24) | (v[1] << 16) | (v[2] << 8) | v[3];
ALLEGRO_DEBUG("Parsed '%s' as 0x%08x\n", s, ver);
return ver;
}
/* Reads version info out of glGetString(GL_VERSION) */
static uint32_t _al_ogl_version(void)
{
char const *value = al_get_config_value(al_get_system_config(), "opengl",
"force_opengl_version");
if (value) {
uint32_t v = parse_opengl_version(value);
ALLEGRO_INFO("OpenGL version forced to %d.%d.%d.%d.\n",
(v >> 24) & 0xff,
(v >> 16) & 0xff,
(v >> 8) & 0xff,
(v & 0xff));
return v;
}
const char *str;
str = (const char *)glGetString(GL_VERSION);
if (str) {
#ifdef ALLEGRO_CFG_OPENGLES
char *str2 = strstr(str, "ES ");
if (str2)
str = str2 + 3;
#endif
return parse_opengl_version(str);
}
else {
/* The OpenGL driver does not return a version
* number. However it probably supports at least OpenGL 1.0
*/
return _ALLEGRO_OPENGL_VERSION_1_0;
}
}
static bool _al_ogl_version_3_only(int flags)
{
const int mask = ALLEGRO_OPENGL_3_0 | ALLEGRO_OPENGL_FORWARD_COMPATIBLE;
return (flags & mask) == mask;
}
/* print_extensions:
* Given a string containing extensions (i.e. a NULL terminated string where
* each extension are separated by a space and which names do not contain any
* space)
*/
static void print_extensions(char const *extension)
{
char buf[80];
char *start;
ASSERT(extension);
while (*extension != '\0') {
start = buf;
_al_sane_strncpy(buf, extension, 80);
while ((*start != ' ') && (*start != '\0')) {
extension++;
start++;
}
*start = '\0';
if (*extension != '\0')
extension++;
ALLEGRO_DEBUG("%s\n", buf);
}
}
#if !defined ALLEGRO_CFG_OPENGLES
/* Print all extensions the OpenGL 3.0 way. */
static void print_extensions_3_0(void)
{
int i;
GLint n;
GLubyte const *name;
glGetIntegerv(GL_NUM_EXTENSIONS, &n);
for (i = 0; i < n; i++) {
name = glGetStringi(GL_EXTENSIONS, i);
ALLEGRO_DEBUG("%s\n", name);
}
}
#endif
/* Function: al_get_opengl_version
*/
uint32_t al_get_opengl_version(void)
{
ALLEGRO_DISPLAY *ogl_disp;
ogl_disp = al_get_current_display();
if (!ogl_disp || !ogl_disp->ogl_extras)
return 0x0;
return ogl_disp->ogl_extras->ogl_info.version;
}
/* NOTE: al_get_opengl_variant is pretty simple right now but may
* eventually need driver support.
*/
/* Function: al_get_opengl_variant
*/
int al_get_opengl_variant(void)
{
#if defined ALLEGRO_CFG_OPENGLES
return ALLEGRO_OPENGL_ES;
#else
return ALLEGRO_DESKTOP_OPENGL;
#endif
}
/* Create the extension list */
static ALLEGRO_OGL_EXT_LIST *create_extension_list(void)
{
ALLEGRO_OGL_EXT_LIST *ret = al_calloc(1, sizeof(ALLEGRO_OGL_EXT_LIST));
if (!ret) {
return NULL;
}
return ret;
}
/* Create the extension API table */
static ALLEGRO_OGL_EXT_API *create_extension_api_table(void)
{
ALLEGRO_OGL_EXT_API *ret = al_calloc(1, sizeof(ALLEGRO_OGL_EXT_API));
if (!ret) {
return NULL;
}
return ret;
}
typedef void (*VOID_FPTR)(void);
/* GCC 4.8.2 and possibly others are really slow at optimizing the 100's of the
* if statements in the load_extensions function below, so we extract them to
* this function.
*/
static VOID_FPTR load_extension(const char* name)
{
VOID_FPTR fptr = NULL;
#ifdef ALLEGRO_WINDOWS
fptr = (VOID_FPTR)wglGetProcAddress(name);
#elif defined ALLEGRO_UNIX
fptr = (VOID_FPTR)alXGetProcAddress((const GLubyte*)name);
#elif defined ALLEGRO_MACOSX
CFStringRef cfstr = CFStringCreateWithCStringNoCopy(NULL, name,
kCFStringEncodingUTF8, kCFAllocatorNull);
if (cfstr) {
fptr = (VOID_FPTR)CFBundleGetFunctionPointerForName(opengl_bundle_ref, cfstr);
CFRelease(cfstr);
}
#elif defined ALLEGRO_SDL
fptr = SDL_GL_GetProcAddress(name);
#endif
if (fptr) {
ALLEGRO_DEBUG("%s successfully loaded (%p)\n", name, fptr);
}
return fptr;
}
/* Load the extension API addresses into the table.
* Should only be done on context creation.
*/
static void load_extensions(ALLEGRO_OGL_EXT_API *ext)
{
if (!ext) {
return;
}
#ifdef ALLEGRO_UNIX
#ifdef ALLEGRO_HAVE_DYNAMIC_LINK
if (!alXGetProcAddress) {
return;
}
#endif
#endif
#ifdef ALLEGRO_WINDOWS
#define AGL_API(type, name, args) \
ext->name = (_ALLEGRO_gl##name##_t)load_extension("gl" #name);
#include "allegro5/opengl/GLext/gl_ext_api.h"
#undef AGL_API
#define AGL_API(type, name, args) \
ext->name = (_ALLEGRO_wgl##name##_t)load_extension("wgl" #name);
#include "allegro5/opengl/GLext/wgl_ext_api.h"
#undef AGL_API
#elif defined ALLEGRO_UNIX
#define AGL_API(type, name, args) \
ext->name = (_ALLEGRO_gl##name##_t)load_extension("gl" #name);
#include "allegro5/opengl/GLext/gl_ext_api.h"
#undef AGL_API
#define AGL_API(type, name, args) \
ext->name = (_ALLEGRO_glX##name##_t)load_extension("glX" #name);
#include "allegro5/opengl/GLext/glx_ext_api.h"
#undef AGL_API
#elif defined ALLEGRO_MACOSX
#define AGL_API(type, name, args) \
ext->name = (_ALLEGRO_gl##name##_t)load_extension("gl" # name);
#include "allegro5/opengl/GLext/gl_ext_api.h"
#undef AGL_API
#elif defined ALLEGRO_SDL
#define AGL_API(type, name, args) \
ext->name = (_ALLEGRO_gl##name##_t)load_extension("gl" # name);
#include "allegro5/opengl/GLext/gl_ext_api.h"
#undef AGL_API
#endif
}
/* Set the GL API pointers to the current table
* Should only be called on context switches.
*/
void _al_ogl_set_extensions(ALLEGRO_OGL_EXT_API *ext)
{
if (!ext) {
return;
}
#define AGL_API(type, name, args) _al_gl##name = ext->name;
# include "allegro5/opengl/GLext/gl_ext_api.h"
#undef AGL_API
#ifdef ALLEGRO_WINDOWS
#define AGL_API(type, name, args) _al_wgl##name = ext->name;
# include "allegro5/opengl/GLext/wgl_ext_api.h"
#undef AGL_API
#elif defined ALLEGRO_UNIX
#define AGL_API(type, name, args) _al_glX##name = ext->name;
# include "allegro5/opengl/GLext/glx_ext_api.h"
#undef AGL_API
#endif
}
/* Destroys the extension API table */
static void destroy_extension_api_table(ALLEGRO_OGL_EXT_API *ext)
{
if (ext) {
al_free(ext);
}
}
/* Destroys the extension list */
static void destroy_extension_list(ALLEGRO_OGL_EXT_LIST *list)
{
if (list) {
al_free(list);
}
}
/* _al_ogl_look_for_an_extension:
* This function has been written by Mark J. Kilgard in one of his
* tutorials about OpenGL extensions
*/
int _al_ogl_look_for_an_extension(const char *name, const GLubyte *extensions)
{
const GLubyte *start;
GLubyte *where, *terminator;
ASSERT(extensions);
/* Extension names should not have spaces. */
where = (GLubyte *) strchr(name, ' ');
if (where || *name == '\0')
return false;
/* It takes a bit of care to be fool-proof about parsing the
* OpenGL extensions string. Don't be fooled by sub-strings, etc.
*/
start = extensions;
for (;;) {
where = (GLubyte *) strstr((const char *)start, name);
if (!where)
break;
terminator = where + strlen(name);
if (where == start || *(where - 1) == ' ')
if (*terminator == ' ' || *terminator == '\0')
return true;
start = terminator;
}
return false;
}
static bool _ogl_is_extension_supported(const char *extension,
ALLEGRO_DISPLAY *disp)
{
int ret = 0;
GLubyte const *ext_str;
#if !defined ALLEGRO_CFG_OPENGLES
int v = al_get_opengl_version();
#endif
(void)disp;
#if !defined ALLEGRO_CFG_OPENGLES
if (disp->flags & ALLEGRO_OPENGL_3_0 || v >= _ALLEGRO_OPENGL_VERSION_3_0) {
int i;
GLint ext_cnt;
glGetIntegerv(GL_NUM_EXTENSIONS, &ext_cnt);
for (i = 0; i < ext_cnt; i++) {
ext_str = glGetStringi(GL_EXTENSIONS, i);
if (ext_str && !strcmp(extension, (char*)ext_str)) {
ret = 1;
break;
}
}
}
else
#endif
{
ext_str = glGetString(GL_EXTENSIONS);
if (!ext_str)
return false;
ret = _al_ogl_look_for_an_extension(extension, ext_str);
}
#ifdef ALLEGRO_WINDOWS
if (!ret && strncmp(extension, "WGL", 3) == 0) {
ALLEGRO_DISPLAY_WGL *wgl_disp = (void*)disp;
_ALLEGRO_wglGetExtensionsStringARB_t _wglGetExtensionsStringARB;
if (!wgl_disp->dc)
return false;
_wglGetExtensionsStringARB = (void *)
wglGetProcAddress("wglGetExtensionsStringARB");
if (_wglGetExtensionsStringARB) {
ret = _al_ogl_look_for_an_extension(extension, (const GLubyte *)
_wglGetExtensionsStringARB(wgl_disp->dc));
}
}
#elif defined ALLEGRO_UNIX && !defined ALLEGRO_EXCLUDE_GLX
if (!ret && strncmp(extension, "GLX", 3) == 0) {
ALLEGRO_SYSTEM_XGLX *sys = (void*)al_get_system_driver();
ALLEGRO_DISPLAY_XGLX *glx_disp = (void*)disp;
char const *ext;
if (!sys->gfxdisplay)
return false;
ext = glXQueryExtensionsString(sys->gfxdisplay, glx_disp->xscreen);
if (!ext) {
/* work around driver bugs? */
ext = "";
}
ret = _al_ogl_look_for_an_extension(extension, (const GLubyte *)ext);
}
#endif
return ret;
}
static bool _ogl_is_extension_with_version_supported(
const char *extension, ALLEGRO_DISPLAY *disp, uint32_t ver)
{
char const *value;
/* For testing purposes, any OpenGL extension can be disable in
* the config by using something like:
*
* [opengl_disabled_extensions]
* GL_ARB_texture_non_power_of_two=0
* GL_EXT_framebuffer_object=0
*
*/
value = al_get_config_value(al_get_system_config(),
"opengl_disabled_extensions", extension);
if (value) {
ALLEGRO_WARN("%s found in [opengl_disabled_extensions].\n",
extension);
return false;
}
/* If the extension is included in the OpenGL version, there is no
* need to check the extensions list.
*/
if (ver > 0 && disp->ogl_extras->ogl_info.version >= ver) {
return true;
}
return _ogl_is_extension_supported(extension, disp);
}
/* Function: al_have_opengl_extension
*/
bool al_have_opengl_extension(const char *extension)
{
ALLEGRO_DISPLAY *disp;
disp = al_get_current_display();
if (!disp)
return false;
if (!(disp->flags & ALLEGRO_OPENGL))
return false;
return _ogl_is_extension_supported(extension, disp);
}
/* Function: al_get_opengl_proc_address
*/
void *al_get_opengl_proc_address(const char *name)
{
void *symbol = NULL;
#ifdef ALLEGRO_MACOSX
CFStringRef function;
#endif
ALLEGRO_DISPLAY *disp;
disp = al_get_current_display();
if (!disp)
return NULL;
if (!(disp->flags & ALLEGRO_OPENGL))
return NULL;
#if defined ALLEGRO_WINDOWS
/* For once Windows is the easiest platform to use :)
* It provides a standardized way to get a function address
* But of course there is a drawback : the symbol is only valid
* under the current context :P
*/
{
ALLEGRO_DISPLAY_WGL *wgl_disp = (void*)disp;
if (!wgl_disp->dc)
return NULL;
symbol = wglGetProcAddress(name);
}
#elif defined ALLEGRO_UNIX
#if defined ALLEGRO_HAVE_DYNAMIC_LINK
if (alXGetProcAddress)
#endif
{
/* This is definitely the *good* way on Unix to get a GL proc
* address. Unfortunately glXGetProcAddress is an extension
* and may not be available on all platforms
*/
#if defined ALLEGRO_RASPBERRYPI
symbol = alXGetProcAddress(name);
#else
symbol = alXGetProcAddress((const GLubyte *)name);
#endif
}
#elif defined ALLEGRO_HAVE_DYNAMIC_LINK
else {
/* Hack if glXGetProcAddress is not available :
* we try to find the symbol into libGL.so
*/
if (__al_handle) {
symbol = dlsym(__al_handle, name);
}
}
#elif defined ALLEGRO_MACOSX
function = CFStringCreateWithCString(kCFAllocatorDefault, name,
kCFStringEncodingASCII);
if (function) {
symbol =
CFBundleGetFunctionPointerForName(opengl_bundle_ref, function);
CFRelease(function);
}
#endif
if (!symbol) {
#if defined ALLEGRO_HAVE_DYNAMIC_LINK
if (!alXGetProcAddress) {
ALLEGRO_WARN("get_proc_address: libdl::dlsym: %s\n", dlerror());
}
#endif
ALLEGRO_WARN("get_proc_address : Unable to load symbol %s\n", name);
}
else {
ALLEGRO_DEBUG("get_proc_address : Symbol %s successfully loaded\n", name);
}
return symbol;
}
/* fill_in_info_struct:
* Fills in the OPENGL_INFO info struct for blacklisting video cards.
*/
static void fill_in_info_struct(const GLubyte *rendereru, OPENGL_INFO *info)
{
const char *renderer = (const char *)rendereru;
ASSERT(renderer);
/* Some cards are "special"... */
if (strstr(renderer, "3Dfx/Voodoo")) {
info->is_voodoo = 1;
}
else if (strstr(renderer, "Matrox G200")) {
info->is_matrox_g200 = 1;
}
else if (strstr(renderer, "RagePRO")) {
info->is_ati_rage_pro = 1;
}
else if (strstr(renderer, "RADEON 7000")) {
info->is_ati_radeon_7000 = 1;
}
else if (strstr(renderer, "Mesa DRI R200")) {
info->is_ati_r200_chip = 1;
}
else if (strstr(renderer, "Intel HD Graphics 3000 OpenGL Engine")) {
info->is_intel_hd_graphics_3000 = 1;
}
if ((strncmp(renderer, "3Dfx/Voodoo3 ", 13) == 0)
|| (strncmp(renderer, "3Dfx/Voodoo2 ", 13) == 0)
|| (strncmp(renderer, "3Dfx/Voodoo ", 12) == 0)) {
info->is_voodoo3_and_under = 1;
}
/* Read OpenGL properties */
info->version = _al_ogl_version();
ALLEGRO_INFO("Assumed OpenGL version: %d.%d.%d.%d\n",
(info->version >> 24) & 0xff,
(info->version >> 16) & 0xff,
(info->version >> 8) & 0xff,
(info->version ) & 0xff);
return;
}
/* _al_ogl_manage_extensions:
* This functions fills the extensions API table and extension list
* structures and displays on the log file which extensions are available.
*/
void _al_ogl_manage_extensions(ALLEGRO_DISPLAY *gl_disp)
{
//const GLubyte *buf;
#if defined ALLEGRO_MACOSX
CFURLRef bundle_url;
#endif
ALLEGRO_OGL_EXT_API *ext_api;
ALLEGRO_OGL_EXT_LIST *ext_list;
/* Some functions depend on knowing the version of opengl in use */
fill_in_info_struct(glGetString(GL_RENDERER), &(gl_disp->ogl_extras->ogl_info));
/* Print out OpenGL extensions
* We should use glGetStringi(GL_EXTENSIONS, i) for OpenGL 3.0+
* but it doesn't seem to work until later.
*/
if (gl_disp->ogl_extras->ogl_info.version < _ALLEGRO_OPENGL_VERSION_3_0) {
ALLEGRO_DEBUG("OpenGL Extensions:\n");
print_extensions((char const *)glGetString(GL_EXTENSIONS));
}
/* Print out GLU version */
//buf = gluGetString(GLU_VERSION);
//ALLEGRO_INFO("GLU Version : %s\n", buf);
#ifdef ALLEGRO_HAVE_DYNAMIC_LINK
/* Get glXGetProcAddress entry */
__libgl_handle = dlopen("libGL.so", RTLD_LAZY);
if (__libgl_handle) {
alXGetProcAddress = (GLXGETPROCADDRESSARBPROC) dlsym(__libgl_handle,
"glXGetProcAddressARB");
if (!alXGetProcAddress) {
alXGetProcAddress = (GLXGETPROCADDRESSARBPROC) dlsym(__libgl_handle,
"glXGetProcAddress");
if (!alXGetProcAddress) {
alXGetProcAddress = (GLXGETPROCADDRESSARBPROC) dlsym(__libgl_handle,
"eglGetProcAddress");
}
}
}
else {
ALLEGRO_WARN("Failed to dlopen libGL.so : %s\n", dlerror());
}
ALLEGRO_INFO("glXGetProcAddress Extension: %s\n",
alXGetProcAddress ? "Supported" : "Unsupported");
#elif defined ALLEGRO_UNIX
#ifdef ALLEGROGL_GLXGETPROCADDRESSARB
ALLEGRO_INFO("glXGetProcAddressARB Extension: supported\n");
#else
ALLEGRO_INFO("glXGetProcAddress Extension: supported\n");
#endif
#endif
#ifdef ALLEGRO_MACOSX
bundle_url = CFURLCreateWithFileSystemPath(kCFAllocatorDefault,
CFSTR
("/System/Library/Frameworks/OpenGL.framework"),
kCFURLPOSIXPathStyle, true);
opengl_bundle_ref = CFBundleCreate(kCFAllocatorDefault, bundle_url);
CFRelease(bundle_url);
#endif
#if defined ALLEGRO_UNIX && !defined ALLEGRO_EXCLUDE_GLX
ALLEGRO_DEBUG("GLX Extensions:\n");
ALLEGRO_SYSTEM_XGLX *glx_sys = (void*)al_get_system_driver();
ALLEGRO_DISPLAY_XGLX *glx_disp = (void *)gl_disp;
char const *ext = glXQueryExtensionsString(
glx_sys->gfxdisplay, glx_disp->xscreen);
if (!ext) {
/* work around driver bugs? */
ext = "";
}
print_extensions(ext);
#endif
/* Create & load extension API table */
ext_api = create_extension_api_table();
load_extensions(ext_api);
gl_disp->ogl_extras->extension_api = ext_api;
#if !defined ALLEGRO_CFG_OPENGLES
/* Need that symbol already so can't wait until it is assigned later. */
glGetStringi = ext_api->GetStringi;
if (gl_disp->ogl_extras->ogl_info.version >= _ALLEGRO_OPENGL_VERSION_3_0) {
ALLEGRO_DEBUG("OpenGL Extensions:\n");
print_extensions_3_0();
}
#endif
/* Create the list of supported extensions. */
ext_list = create_extension_list();
gl_disp->ogl_extras->extension_list = ext_list;
/* Fill the list. */
#define AGL_EXT(name, ver) { \
ext_list->ALLEGRO_GL_##name = \
_ogl_is_extension_with_version_supported("GL_" #name, gl_disp, \
_ALLEGRO_OPENGL_VERSION_##ver); \
}
#include "allegro5/opengl/GLext/gl_ext_list.h"
#undef AGL_EXT
#ifdef ALLEGRO_UNIX
#define AGL_EXT(name, ver) { \
ext_list->ALLEGRO_GLX_##name = \
_ogl_is_extension_with_version_supported("GLX_" #name, gl_disp, \
_ALLEGRO_OPENGL_VERSION_##ver); \
}
#include "allegro5/opengl/GLext/glx_ext_list.h"
#undef AGL_EXT
#elif defined ALLEGRO_WINDOWS
#define AGL_EXT(name, ver) { \
ext_list->ALLEGRO_WGL_##name = \
_ogl_is_extension_with_version_supported("WGL_" #name, gl_disp, \
_ALLEGRO_OPENGL_VERSION_##ver); \
}
#include "allegro5/opengl/GLext/wgl_ext_list.h"
#undef AGL_EXT
#endif
/* Get max texture size */
glGetIntegerv(GL_MAX_TEXTURE_SIZE,
(GLint *) & gl_disp->ogl_extras->ogl_info.max_texture_size);
/* Note: Voodoo (even V5) don't seem to correctly support
* packed pixel formats. Disabling them for those cards.
*/
ext_list->ALLEGRO_GL_EXT_packed_pixels &= !gl_disp->ogl_extras->ogl_info.is_voodoo;
if (ext_list->ALLEGRO_GL_EXT_packed_pixels) {
ALLEGRO_INFO("Packed Pixels formats available\n");
/* XXX On NV cards, we want to use BGRA instead of RGBA for speed */
/* Fills the __allegro_gl_texture_format array */
/* TODO: use these somewhere */
#if 0
__allegro_gl_texture_read_format[0] = GL_UNSIGNED_BYTE_3_3_2;
__allegro_gl_texture_read_format[1] = GL_UNSIGNED_SHORT_5_5_5_1;
__allegro_gl_texture_read_format[2] = GL_UNSIGNED_SHORT_5_6_5;
#endif /* #if 0 */
}
/* NVidia and ATI cards expose OpenGL 2.0 but often don't accelerate
* non-power-of-2 textures. This check is how you verify that NP2
* textures are hardware accelerated or not.
* We should clobber the NPOT support if it's not accelerated.
*/
{
const char *vendor = (const char *)glGetString(GL_VENDOR);
if (strstr(vendor, "NVIDIA Corporation")) {
if (!ext_list->ALLEGRO_GL_NV_fragment_program2
|| !ext_list->ALLEGRO_GL_NV_vertex_program3) {
ext_list->ALLEGRO_GL_ARB_texture_non_power_of_two = 0;
}
}
else if (strstr(vendor, "ATI Technologies")) {
if (gl_disp->ogl_extras->ogl_info.version >= _ALLEGRO_OPENGL_VERSION_3_0) {
/* Assume okay. */
}
else if (!strstr((const char *)glGetString(GL_EXTENSIONS),
"GL_ARB_texture_non_power_of_two")
&& gl_disp->ogl_extras->ogl_info.version >= _ALLEGRO_OPENGL_VERSION_2_0) {
ext_list->ALLEGRO_GL_ARB_texture_non_power_of_two = 0;
}
}
}
{
int *s = gl_disp->extra_settings.settings;
glGetIntegerv(GL_MAX_TEXTURE_SIZE, s + ALLEGRO_MAX_BITMAP_SIZE);
if (gl_disp->ogl_extras->ogl_info.version >= _ALLEGRO_OPENGL_VERSION_2_0)
s[ALLEGRO_SUPPORT_SEPARATE_ALPHA] = 1;
s[ALLEGRO_SUPPORT_NPOT_BITMAP] =
ext_list->ALLEGRO_GL_ARB_texture_non_power_of_two ||
ext_list->ALLEGRO_GL_OES_texture_npot;
ALLEGRO_INFO("Use of non-power-of-two textures %s.\n",
s[ALLEGRO_SUPPORT_NPOT_BITMAP] ? "enabled" : "disabled");
#if defined ALLEGRO_CFG_OPENGLES
if (gl_disp->flags & ALLEGRO_PROGRAMMABLE_PIPELINE) {
s[ALLEGRO_CAN_DRAW_INTO_BITMAP] = true;
}
else {
s[ALLEGRO_CAN_DRAW_INTO_BITMAP] =
ext_list->ALLEGRO_GL_OES_framebuffer_object;
}
ALLEGRO_INFO("Use of FBO to draw to textures %s.\n",
s[ALLEGRO_CAN_DRAW_INTO_BITMAP] ? "enabled" :
"disabled");
#else
s[ALLEGRO_CAN_DRAW_INTO_BITMAP] =
ext_list->ALLEGRO_GL_EXT_framebuffer_object;
ALLEGRO_INFO("Use of FBO to draw to textures %s.\n",
s[ALLEGRO_CAN_DRAW_INTO_BITMAP] ? "enabled" :
"disabled");
#endif
}
}
/* Function: al_get_opengl_extension_list
*/
ALLEGRO_OGL_EXT_LIST *al_get_opengl_extension_list(void)
{
ALLEGRO_DISPLAY *disp;
disp = al_get_current_display();
ASSERT(disp);
if (!(disp->flags & ALLEGRO_OPENGL))
return NULL;
ASSERT(disp->ogl_extras);
return disp->ogl_extras->extension_list;
}
void _al_ogl_unmanage_extensions(ALLEGRO_DISPLAY *gl_disp)
{
destroy_extension_api_table(gl_disp->ogl_extras->extension_api);
destroy_extension_list(gl_disp->ogl_extras->extension_list);
gl_disp->ogl_extras->extension_api = NULL;
gl_disp->ogl_extras->extension_list = NULL;
#ifdef ALLEGRO_MACOSX
CFRelease(opengl_bundle_ref);
#endif
#ifdef ALLEGRO_HAVE_DYNAMIC_LINK
if (__libgl_handle) {
dlclose(__libgl_handle);
__libgl_handle = NULL;
}
#endif
}
/* vim: set sts=3 sw=3 et: */
You can’t perform that action at this time.