blob: 51838f9d480a198bd5c742bcdc81f430d24f707c [file] [log] [blame]
#!/usr/bin/python -B
from string import Template, upper, replace
from ApiUtil import outputCode
cond = { 'wgl' : 'REGAL_SYS_WGL', 'glx' : 'REGAL_SYS_GLX', 'cgl' : 'REGAL_SYS_OSX', 'egl' : 'REGAL_SYS_EGL' }
emuInfoHeaderTemplate = Template( '''${AUTOGENERATED}
${LICENSE}
/*
Regal emulation information and runtime emulation limits
Nigel Stewart, Scott Nations
*/
#ifndef __${HEADER_NAME}_H__
#define __${HEADER_NAME}_H__
#include "RegalUtil.h"
REGAL_GLOBAL_BEGIN
#include <GL/Regal.h>
#include <set>
#include <string>
REGAL_GLOBAL_END
REGAL_NAMESPACE_BEGIN
struct ContextInfo;
struct EmuInfo
{
EmuInfo();
~EmuInfo();
void init(const ContextInfo &contextInfo);
// glewGetExtension, glewIsSupported
bool getExtension(const ContextInfo &contextInfo, const char *ext) const;
bool isSupported(const ContextInfo &contextInfo, const char *ext) const;
// Reported by Regal to the application
std::string vendor;
std::string renderer;
std::string version;
std::string extensions;
//
std::set<std::string> extensionsSet;
// Emulated extensions and limits
${IMPL_DECLARE}
};
REGAL_NAMESPACE_END
#endif // __${HEADER_NAME}_H__
''')
emuInfoSourceTemplate = Template( '''${AUTOGENERATED}
${LICENSE}
/*
Regal emulation information and runtime emulation limits
Nigel Stewart, Scott Nations
*/
#include "pch.h" /* For MS precompiled header support */
#include "RegalUtil.h"
REGAL_GLOBAL_BEGIN
#include <GL/Regal.h>
#include "RegalEmu.h"
#include "RegalEmuInfo.h"
using namespace std;
#include <boost/print/string_list.hpp>
using namespace boost::print;
#include "RegalToken.h"
#include "RegalContext.h"
#include "RegalContextInfo.h"
#include "RegalEmu.h"
REGAL_GLOBAL_END
REGAL_NAMESPACE_BEGIN
using namespace ::REGAL_NAMESPACE_INTERNAL::Logging;
using namespace ::REGAL_NAMESPACE_INTERNAL::Token;
EmuInfo::EmuInfo()
:
${IMPL_INIT}
{
Internal("EmuInfo::EmuInfo","()");
}
EmuInfo::~EmuInfo()
{
Internal("EmuInfo::~EmuInfo","()");
}
void
EmuInfo::init(const ContextInfo &contextInfo)
{
// TODO - filter out extensions Regal doesn't support?
#ifdef REGAL_GL_VENDOR
vendor = REGAL_EQUOTE(REGAL_GL_VENDOR);
#else
vendor = contextInfo.vendor;
#endif
#ifdef REGAL_GL_RENDERER
renderer = REGAL_EQUOTE(REGAL_GL_RENDERER);
#else
renderer = contextInfo.renderer;
#endif
#ifdef REGAL_GL_VERSION
version = REGAL_EQUOTE(REGAL_GL_VERSION);
#else
version = contextInfo.version;
#endif
#ifdef REGAL_GL_EXTENSIONS
{
string_list<string> extList;
extList.split(REGAL_EQUOTE(REGAL_GL_EXTENSIONS),' ');
extensionsSet.clear();
extensionsSet.insert(extList.begin(),extList.end());
}
#else
static const char *ourExtensions[9] = {
"GL_REGAL_log",
"GL_REGAL_enable",
"GL_REGAL_error_string",
"GL_REGAL_extension_query",
"GL_REGAL_ES1_0_compatibility",
"GL_REGAL_ES1_1_compatibility",
"GL_EXT_debug_marker",
"GL_GREMEDY_string_marker",
"GL_GREMEDY_frame_terminator"
};
extensionsSet = contextInfo.extensionsSet;
extensionsSet.insert(&ourExtensions[0],&ourExtensions[9]);
#endif
#ifndef REGAL_NO_GETENV
{
getEnv("REGAL_GL_VENDOR", vendor);
getEnv("REGAL_GL_RENDERER", renderer);
getEnv("REGAL_GL_VERSION", version);
const char *extensionsEnv = getEnv("REGAL_GL_EXTENSIONS");
if (extensionsEnv)
{
string_list<string> extList;
extList.split(extensionsEnv,' ');
extensionsSet.clear();
extensionsSet.insert(extList.begin(),extList.end());
}
}
#endif
// Form Regal extension string from the set
extensions = ::boost::print::detail::join(extensionsSet,string(" "));
Info("Regal vendor : ",vendor);
Info("Regal renderer : ",renderer);
Info("Regal version : ",version);
Info("Regal extensions : ",extensions);
${IMPL_GET}
if (gl_max_vertex_attribs > REGAL_EMU_MAX_VERTEX_ATTRIBS)
gl_max_vertex_attribs = REGAL_EMU_MAX_VERTEX_ATTRIBS;
// Qualcomm fails with float4 attribs with 256 byte stride, so artificially limit to 8 attribs (n*16 is used
// as the stride in RegalIFF). WebGL (and Pepper) explicitly disallows stride > 255 as well.
if (contextInfo.vendor == "Qualcomm" || contextInfo.vendor == "Chromium" || contextInfo.webgl)
gl_max_vertex_attribs = std::min<GLuint>(gl_max_vertex_attribs,8);
Info("Regal v attribs : ",gl_max_vertex_attribs);
}
${GET_EXT}
REGAL_NAMESPACE_END
''')
def emuInfoDeclareCode(apis, args):
code = ''
for api in apis:
name = api.name.lower()
if name == 'gl':
code += '\n'
for ext in api.extensions:
if len(ext.emulatedBy):
code += ' GLboolean %s : 1;\n' % (ext.name.lower())
code += '\n'
states = sorted([ state.getValue.lower() for state in api.states ])
for state in states:
code += ' GLuint gl_%s;\n' % (state)
code += '\n'
code += ' GLuint gl_max_varying_floats;\n'
return code
def emuInfoInitCode(apis, args):
code = ''
for api in apis:
name = api.name.lower()
if name == 'gl':
for ext in api.extensions:
if len(ext.emulatedBy):
code += ' %s(false),\n' % (ext.name.lower())
code += '\n'
states = sorted([ state.getValue.lower() for state in api.states ])
for state in states:
code += ' gl_%s(0),\n' % (state)
code += ' gl_max_varying_floats(0)\n'
return code
def emuInfoGetCode(apis, args):
code = ''
for api in apis:
name = api.name.lower()
if name == 'gl':
for ext in api.extensions:
if len(ext.emulatedBy):
code += ' %-37s = false;\n' % (ext.name.lower())
code += '\n'
code += ' gl_max_vertex_attribs = 8;\n'
states = sorted([ state.getValue.lower() for state in api.states ])
for state in states:
code += ' gl_%-34s = contextInfo.gl_%s;\n' % (state.lower(), state.lower())
code += '\n'
return code
def emuInfoGetExtensionCode(apis, args):
code = '''
bool
EmuInfo::getExtension(const ContextInfo &contextInfo, const char *ext) const
{
Internal("EmuInfo::getExtension ",boost::print::quote(ext,\'"\'));
// If the context supports it, we're done.
if (contextInfo.getExtension(ext))
return true;
'''
for api in apis:
emulatedExtensions = [extension.name for extension in api.extensions if len(extension.emulatedBy)]
name = api.name.lower()
if name in cond:
code += '#if %s\n'%cond[name]
for c in sorted(api.categories):
if c.startswith('GL_REGAL_') or c=='GL_EXT_debug_marker':
code += ' if %-50s return true;\n' % ('(!strcmp(ext,"%s"))'%c)
elif c in emulatedExtensions:
code += ' if %-50s return %s;\n' % ('(!strcmp(ext,"%s"))'%c,c.lower())
if name in cond:
code += '#endif\n'
code += '\n'
code += '''
return false;
}
'''
code += '''
bool
EmuInfo::isSupported(const ContextInfo &contextInfo, const char *ext) const
{
Internal("EmuInfo::isSupported ",boost::print::quote(ext,\'"\'));
string_list<string> e;
e.split(ext,\' \');
for (string_list<string>::const_iterator i=e.begin(); i!=e.end(); ++i)
if (i->length() && !getExtension(contextInfo, i->c_str())) return false;
return true;
}'''
return code
def generateEmuInfoHeader(apis, args):
substitute = {}
substitute['LICENSE'] = args.license
substitute['AUTOGENERATED'] = args.generated
substitute['COPYRIGHT'] = args.copyright
substitute['HEADER_NAME'] = "REGAL_EMU_INFO"
substitute['IMPL_DECLARE'] = emuInfoDeclareCode(apis,args)
outputCode( '%s/RegalEmuInfo.h' % args.srcdir, emuInfoHeaderTemplate.substitute(substitute))
def generateEmuInfoSource(apis, args):
substitute = {}
substitute['LICENSE'] = args.license
substitute['AUTOGENERATED'] = args.generated
substitute['COPYRIGHT'] = args.copyright
substitute['IMPL_INIT'] = emuInfoInitCode(apis,args)
substitute['IMPL_GET'] = emuInfoGetCode(apis,args)
substitute['GET_EXT'] = emuInfoGetExtensionCode(apis,args)
outputCode( '%s/RegalEmuInfo.cpp' % args.srcdir, emuInfoSourceTemplate.substitute(substitute))