regal/scripts/Export.py
2012-08-19 19:36:32 -05:00

3156 lines
88 KiB
Python
Executable file

#!/usr/bin/python -B
# This exporter is undocumented - REVISIT
#
#
#
# CodeGen Imports
from string import Template, upper, replace
from optparse import OptionParser
from copy import deepcopy
import re
from ApiUtil import validVersion
from ApiUtil import outputCode
from ApiUtil import importAttr
from ApiUtil import hexValue
from ApiUtil import toLong
from ApiUtil import typeIsVoid
from ApiCodeGen import *
from EmuContextState import formulae as contextStateFormulae
from EmuGetString import formulae as getStringFormulae
from EmuForceCore import formulae as forceCoreFormulae
from EmuLookup import formulae as lookupFormulae
from EmuMarker import formulae as markerFormulae
from EmuExtensionQuery import formulae as extensionQueryFormulae
from EmuErrorString import formulae as errorStringFormulae
from EmuEnable import formulae as enableFormulae
from Emu import emuFindEntry, emuCodeGen
from EmuDsa import dsaFormulae
from EmuVao import vaoFormulae
from EmuPpc import ppcFormulae
from EmuPpa import ppaFormulae
from EmuIff import iffFormulae
from EmuBin import binFormulae
from EmuLog import logFormulae
from EmuObj import objFormulae
from DispatchDebug import debugDispatchFormulae
# Regal.cpp emulation
emuRegal = [
{ 'type' : None, 'member' : None, 'conditional' : None, 'ifdef' : None, 'formulae' : contextStateFormulae },
{ 'type' : None, 'member' : None, 'conditional' : None, 'ifdef' : None, 'formulae' : getStringFormulae },
{ 'type' : None, 'member' : None, 'conditional' : None, 'ifdef' : None, 'formulae' : forceCoreFormulae },
{ 'type' : None, 'member' : None, 'conditional' : None, 'ifdef' : None, 'formulae' : lookupFormulae },
{ 'type' : 'Marker', 'member' : 'marker', 'conditional' : None, 'ifdef' : None, 'formulae' : markerFormulae },
{ 'type' : None, 'member' : None, 'conditional' : None, 'ifdef' : None, 'formulae' : extensionQueryFormulae },
{ 'type' : None, 'member' : None, 'conditional' : None, 'ifdef' : None, 'formulae' : errorStringFormulae },
{ 'type' : None, 'member' : None, 'conditional' : None, 'ifdef' : None, 'formulae' : logFormulae },
{ 'type' : None, 'member' : None, 'conditional' : None, 'ifdef' : None, 'formulae' : enableFormulae },
]
# RegalDispathEmu.cpp fixed-function emulation
emu = [
{ 'type' : 'RegalObj', 'member' : 'obj', 'conditional' : 'Config::enableEmuObj', 'ifdef' : 'REGAL_EMU_OBJ', 'formulae' : objFormulae },
#{ 'type' : 'RegalPpc', 'member' : 'ppc', 'conditional' : None, 'ifdef' : '', 'formulae' : ppcFormulae },
{ 'type' : 'RegalPpa', 'member' : 'ppa', 'conditional' : 'Config::enableEmuPpa', 'ifdef' : 'REGAL_EMU_PPA', 'formulae' : ppaFormulae },
{ 'type' : 'RegalBin', 'member' : 'bin', 'conditional' : 'Config::enableEmuBin', 'ifdef' : 'REGAL_EMU_BIN', 'formulae' : binFormulae },
{ 'type' : 'RegalDsa', 'member' : 'dsa', 'conditional' : 'Config::enableEmuDsa', 'ifdef' : 'REGAL_EMU_DSA', 'formulae' : dsaFormulae },
{ 'type' : 'RegalIff', 'member' : 'iff', 'conditional' : 'Config::enableEmuIff', 'ifdef' : 'REGAL_EMU_IFF', 'formulae' : iffFormulae },
{ 'type' : 'RegalVao', 'member' : 'vao', 'conditional' : 'Config::enableEmuVao', 'ifdef' : 'REGAL_EMU_VAO', 'formulae' : vaoFormulae },
{ 'type' : 'void', 'member' : None, 'conditional' : None, 'ifdef' : None, 'formulae' : None }
]
cond = { 'wgl' : 'REGAL_SYS_WGL', 'glx' : 'REGAL_SYS_GLX', 'cgl' : 'REGAL_SYS_OSX', 'egl' : 'REGAL_SYS_ANDROID' }
regalLicense = '''
/*
Copyright (c) 2011 NVIDIA Corporation
Copyright (c) 2011-2012 Cass Everitt
Copyright (c) 2012 Scott Nations
Copyright (c) 2012 Mathias Schott
Copyright (c) 2012 Nigel Stewart
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
OF THE POSSIBILITY OF SUCH DAMAGE.
*/
'''
def cmpCategoryName(a,b):
if a.category==b.category:
return cmp(a.name,b.name)
if a.category.startswith('GL_VERSION') and b.category.startswith('GL_VERSION'): return cmp(a.category,b.category)
if a.category.startswith('GL_VERSION'): return -1
if b.category.startswith('GL_VERSION'): return 1
if a.category.startswith('GLX_VERSION') and b.category.startswith('GLX_VERSION'): return cmp(a.category,b.category)
if a.category.startswith('GLX_VERSION'): return -1
if b.category.startswith('GLX_VERSION'): return 1
if a.category.startswith('CGL_VERSION') and b.category.startswith('CGL_VERSION'): return cmp(a.category,b.category)
if a.category.startswith('CGL_VERSION'): return -1
if b.category.startswith('CGL_VERSION'): return 1
return cmp(a.category,b.category)
def traverse(apis, args):
for i in range( len( emu ) ) :
emu[i]['level'] = len( emu ) - 1 - i
for api in apis:
# Fixup GL categories
if api.name=='gl':
for i in api.functions:
if len(i.category):
i.category = i.category.replace('_DEPRECATED','',1)
else:
i.category = 'GL_VERSION_%s_%s'%(i.version.split('.')[0],i.version.split('.')[1])
api.functions.sort(cmpCategoryName)
if api.name=='gl':
for i in api.enums:
if i.name=='defines':
i.enumerants.sort(cmpCategoryName)
apiHasCtx = api.name == 'gl';
toRemove = set()
for function in api.functions:
# In the database, functions can be disabled one-by-one
if not getattr(function,'regal',True):
toRemove.add(function)
function.loadFunction = True
function.loadFuncPtrDeclare = True
function.loadFuncPtrLoad = True
function.loadGetProcAddress = True
function.needsContext = apiHasCtx
for function in toRemove:
api.functions.remove(function)
# In the database, typedefs can be disabled one-by-one
toRemove = set()
for typedef in api.typedefs:
if not getattr(typedef,'regal',True):
toRemove.add(typedef)
for typedef in toRemove:
api.typedefs.remove(typedef)
traverseContextInfo(apis,args)
def generate(apis, args):
traverse(apis, args)
generatePublicHeader(apis, args)
generateDispatchHeader(apis, args)
generateContextHeader(apis, args)
generateContextSource(apis, args)
generateContextInfoHeader(apis, args)
generateContextInfoSource(apis, args)
generateLookupSource(apis, args)
generateLookupHeader(apis, args)
generateTokenSource(apis, args)
generateTokenHeader(apis, args)
generateEnumHeader(apis, args)
additional_exports = ['RegalSetErrorCallback', 'RegalMakeCurrent']
generateDefFile( apis, args, additional_exports)
generateLoaderSource( apis, args )
generateErrorSource( apis, args )
generateDebugSource( apis, args )
generateEmuSource( apis, args )
generateDispatchLog( apis, args )
generateNaclSource( apis, args )
generateMissingSource( apis, args )
generateSource(apis, args)
##############################################################################################
publicHeaderTemplate = Template( '''${AUTOGENERATED}
${LICENSE}
#define __gl_h_
#define __GL_H__
#define __X_GL_H
#define __glext_h_
#define __GLEXT_H_
#define __gl_ATI_h_
#ifndef REGAL_DECLARATIONS_H
#define REGAL_DECLARATIONS_H
#if _WIN32
# define REGAL_SYS_WGL 1
#elif __APPLE__
# include <TargetConditionals.h>
# if TARGET_OS_IPHONE
# define REGAL_SYS_IOS 1
# else
# define REGAL_SYS_OSX 1
# endif
#elif defined(__native_client__)
# define REGAL_SYS_NACL 1
#elif defined(__ANDROID__)
# define REGAL_SYS_ANDROID 1
#elif !defined(_WIN32) && !defined(__APPLE__) && !defined(__native_client__)
# define REGAL_SYS_GLX 1
#endif
#if REGAL_SYS_WGL
# define REGAL_CALL __stdcall
#else
# define REGAL_CALL
#endif
#ifndef GLAPIENTRY
#define GLAPIENTRY REGAL_CALL
#endif
#ifdef _WIN32
# if REGAL_DECL_EXPORT
# define REGAL_DECL
# else
# define REGAL_DECL __declspec(dllimport)
# endif
#elif defined(__GNUC__) && __GNUC__>=4
# if REGAL_DECL_EXPORT
# define REGAL_DECL __attribute__ ((visibility("default")))
# else
# define REGAL_DECL
# endif
#elif defined(__SUNPRO_C) || defined(__SUNPRO_CC)
# if REGAL_DECL_EXPORT
# define REGAL_DECL __global
# else
# define REGAL_DECL
# endif
#else
# define REGAL_DECL
#endif
#endif // REGAL_DECLARATIONS_H
#ifndef __${HEADER_NAME}_H__
#define __${HEADER_NAME}_H__
#if REGAL_SYS_GLX
#include <X11/Xdefs.h>
#include <X11/Xutil.h>
typedef XID GLXDrawable;
#endif
#ifdef __cplusplus
extern "C" {
#endif
#include <stddef.h>
#if REGAL_SYS_WGL
typedef __int64 int64_t;
typedef unsigned __int64 uint64_t;
#ifdef REGAL_SYS_WGL_DECLARE_WGL
#ifndef _WINDEF_
struct HDC__ {int unused;};
typedef struct HDC__* HDC;
struct HGLRC__ {int unused;};
typedef struct HGLRC__* HGLRC;
#endif
#endif
#else
# include <inttypes.h>
#endif
${API_TYPEDEF}
// TODO: make this automatic?
typedef void (*GLDEBUGPROCAMD)(GLuint id, GLenum category, GLenum severity, GLsizei length, const GLchar *message, GLvoid *userParam);
typedef void (*GLDEBUGPROCARB)(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar *message, GLvoid *userParam);
typedef void (*GLDEBUGPROC)(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar *message, GLvoid *userParam);
typedef void (*GLLOGPROCREGAL)(GLenum stream, GLsizei length, const GLchar *message, GLvoid *context);
${API_ENUM}
${API_FUNC_DECLARE}
#ifdef __cplusplus
}
#endif
#endif // __REGAL_H__
#ifndef REGAL_API_H
#define REGAL_API_H
#if REGAL_SYS_NACL
#include <stdint.h>
struct PPB_OpenGLES2;
#endif
// Regal-specific API... try to keep this minimal
// this is a seperate include guard to work nicely with RegalGLEW.h
#ifdef __cplusplus
extern "C" {
#endif
typedef void (*RegalErrorCallback)(GLenum);
REGAL_DECL RegalErrorCallback RegalSetErrorCallback( RegalErrorCallback callback );
#if REGAL_SYS_NACL
typedef int32_t RegalSystemContext;
REGAL_DECL void RegalMakeCurrent( RegalSystemContext ctx, struct PPB_OpenGLES2 *interface );
#else
typedef void * RegalSystemContext;
REGAL_DECL void RegalMakeCurrent( RegalSystemContext ctx );
#endif
#ifdef __cplusplus
}
#endif
#endif // ${HEADER_NAME}_H
''')
def generatePublicHeader(apis, args):
apiTypedef = apiTypedefCode( apis, args )
apiEnum = apiEnumCode(apis, args) # CodeGen for API enums
apiFuncDeclare = apiFuncDeclareCode( apis, args ) # CodeGen for API functions
# Output
substitute = {}
substitute['LICENSE'] = regalLicense
substitute['AUTOGENERATED'] = autoGeneratedMessage
substitute['COPYRIGHT'] = args.copyright
substitute['HEADER_NAME'] = "REGAL"
substitute['API_TYPEDEF'] = apiTypedef
substitute['API_ENUM'] = apiEnum
substitute['API_FUNC_DECLARE'] = apiFuncDeclare
outputCode( 'include/GL/Regal.h', publicHeaderTemplate.substitute(substitute))
##############################################################################################
dispatchHeaderTemplate = Template( '''${AUTOGENERATED}
${LICENSE}
#ifndef __${HEADER_NAME}_H__
#define __${HEADER_NAME}_H__
#include "RegalUtil.h"
REGAL_GLOBAL_BEGIN
#include <GL/Regal.h>
REGAL_GLOBAL_END
REGAL_NAMESPACE_BEGIN
${API_GLOBAL_DISPATCH_TABLE_DEFINE}
extern DispatchTableGlobal dispatchTableGlobal;
${API_DISPATCH_TABLE_DEFINE}
REGAL_NAMESPACE_END
#endif // __${HEADER_NAME}_H__
''')
def generateDispatchHeader(apis, args):
globalDispatchTableDefine = apiGlobalDispatchTableDefineCode( apis, args )
dispatchTableDefine = apiDispatchTableDefineCode(apis, args)
# Output
substitute = {}
substitute['LICENSE'] = regalLicense
substitute['AUTOGENERATED'] = autoGeneratedMessage
substitute['COPYRIGHT'] = args.copyright
substitute['HEADER_NAME'] = 'REGAL_DISPATCH'
substitute['API_GLOBAL_DISPATCH_TABLE_DEFINE'] = globalDispatchTableDefine
substitute['API_DISPATCH_TABLE_DEFINE'] = dispatchTableDefine
outputCode( '%s/RegalDispatch.h' % args.outdir, dispatchHeaderTemplate.substitute(substitute))
##############################################################################################
contextHeaderTemplate = Template( '''${AUTOGENERATED}
${LICENSE}
#ifndef __${HEADER_NAME}_H__
#define __${HEADER_NAME}_H__
#include "RegalUtil.h"
REGAL_GLOBAL_BEGIN
#include "RegalPrivate.h"
#include "RegalDispatchError.h"
#if defined(__native_client__)
#define __gl2_h_ // HACK - revisit
#include <ppapi/c/pp_resource.h>
#include <ppapi/c/ppb_opengles2.h>
#endif
REGAL_GLOBAL_END
REGAL_NAMESPACE_BEGIN
struct DebugInfo;
struct ContextInfo;
struct DispatchState;
${EMU_FORWARD_DECLARE}
struct RegalContext
{
RegalContext();
~RegalContext();
void Init();
DispatchState *dsp;
DispatchErrorState err;
DebugInfo *dbg;
ContextInfo *info;
${EMU_MEMBER_DECLARE}
#if defined(__native_client__)
PPB_OpenGLES2 *naclES2;
PP_Resource naclResource;
#endif
RegalSystemContext sysCtx;
Thread thread;
GLLOGPROCREGAL logCallback;
// State tracked via EmuContextState.py / Regal.cpp
size_t depthBeginEnd; // Normally zero or one
size_t depthPushAttrib; //
};
REGAL_NAMESPACE_END
#endif // __${HEADER_NAME}_H__
''')
contextSourceTemplate = Template( '''${AUTOGENERATED}
${LICENSE}
#include "pch.h" /* For MS precompiled header support */
#include "RegalUtil.h"
REGAL_GLOBAL_BEGIN
#include "RegalConfig.h"
#include "RegalContext.h"
#include "RegalDispatchState.h"
#include "RegalDebugInfo.h"
#include "RegalContextInfo.h"
${EMU_INCLUDES}
REGAL_GLOBAL_END
REGAL_NAMESPACE_BEGIN
using namespace Logging;
RegalContext::RegalContext()
: dsp(new DispatchState()),
dbg(NULL),
info(NULL),
${EMU_MEMBER_CONSTRUCT}
#if defined(__native_client__)
naclES2(NULL),
naclResource(NULL),
#endif
sysCtx(NULL),
thread(0),
logCallback(NULL),
depthBeginEnd(0),
depthPushAttrib(0)
{
ITrace("RegalContext::RegalContext");
dsp->Init();
if (Config::enableDebug) {
dbg = new DebugInfo();
dbg->Init(this);
}
RegalAssert(dsp);
}
void
RegalContext::Init()
{
ITrace("RegalContext::Init");
info = new ContextInfo();
RegalAssert(this);
RegalAssert(info);
info->init(*this);
${MEMBER_INIT}
#if !REGAL_FORCE_EMULATION
if
(
Config::forceEmulation ||
(
Config::enableEmulation &&
(
info->core ||
info->gles ||
( info->compat && !info->gl_ext_direct_state_access )
)
)
)
#endif
{
RegalAssert(info);
${EMU_MEMBER_INIT}
}
}
RegalContext::~RegalContext()
{
ITrace("RegalContext::~RegalContext");
delete dsp;
delete info;
${EMU_MEMBER_CLEANUP}
}
REGAL_NAMESPACE_END
''')
def generateContextHeader(apis, args):
emuForwardDeclare = ''
emuMemberDeclare = ''
for i in emuRegal:
if i.get('member')!=None:
emuForwardDeclare += 'struct %s;\n' % i['type']
emuMemberDeclare += ' %-18s *%s;\n' % ( i['type'], i['member'] )
emuMemberDeclare += ' // Fixed function emulation\n'
emuMemberDeclare += ' int emuLevel;\n'
for i in emu:
if i.get('member')!=None:
emuForwardDeclare += 'struct %s;\n' % i['type']
emuMemberDeclare += ' %-18s *%s;\n' % ( i['type'], i['member'] )
# Output
substitute = {}
substitute['LICENSE'] = regalLicense
substitute['AUTOGENERATED'] = autoGeneratedMessage
substitute['COPYRIGHT'] = args.copyright
substitute['HEADER_NAME'] = "REGAL_CONTEXT"
substitute['EMU_FORWARD_DECLARE'] = emuForwardDeclare
substitute['EMU_MEMBER_DECLARE'] = emuMemberDeclare
outputCode( '%s/RegalContext.h' % args.outdir, contextHeaderTemplate.substitute(substitute))
def generateContextSource(apis, args):
emuIncludes = ''
emuMemberConstruct = ''
memberInit = ''
emuMemberInit = ''
emuMemberCleanup = ''
for i in emuRegal:
if i['member']:
emuMemberConstruct += ' %s(NULL),\n' % ( i['member'] )
emuIncludes += '#include "Regal%s.h"\n' % i['type']
memberInit += ' %s = new %s;\n'%(i['member'],i['type'])
emuMemberCleanup += ' delete %s;\n' % i['member']
emuMemberInit += ' // emu\n'
emuMemberInit += ' emuLevel = %d;\n' % ( len( emu ) - 1 )
emuMemberCleanup += ' // emu\n'
for i in range( len( emu ) - 1 ) :
if emu[i]['member']:
emuMemberConstruct += ' %s(NULL),\n' % emu[i]['member']
for i in range( len( emu ) - 1 ) :
if emu[i]['member']:
emuIncludes += '#include "%s.h"\n' % emu[i]['type']
emuMemberCleanup += ' delete %s;\n' % emu[i]['member']
revi = len( emu ) - 2 - i;
if emu[revi]['member']:
init = ''
if emu[revi]['member']=='dsa':
init += 'ITrace("RegalContext::Init GL_EXT_direct_state_access");\n'
init += 'info->regal_ext_direct_state_access = true;\n'
# init += '#ifndef REGAL_GL_EXTENSIONS\n'
init += 'info->regalExtensionsSet.insert("GL_EXT_direct_state_access");\n'
init += 'info->regalExtensions = ::boost::print::detail::join(info->regalExtensionsSet,std::string(" "));\n'
# init += '#endif\n'
init += '%s = new %s;\n' % ( emu[revi]['member'], emu[revi]['type'] )
init += '%s->emuLevel = %d;\n' % ( emu[revi]['member'], emu[revi]['level'] )
init += '%s->Init( this );\n' % emu[revi]['member']
emuMemberInit += indent(wrapIf(emu[revi]['ifdef'],wrapCIf(emu[revi]['conditional'],init)),' ')
# Output
substitute = {}
substitute['LICENSE'] = regalLicense
substitute['AUTOGENERATED'] = autoGeneratedMessage
substitute['COPYRIGHT'] = args.copyright
substitute['EMU_INCLUDES'] = emuIncludes
substitute['MEMBER_INIT'] = memberInit
substitute['EMU_MEMBER_CONSTRUCT'] = emuMemberConstruct
substitute['EMU_MEMBER_INIT'] = emuMemberInit
substitute['EMU_MEMBER_CLEANUP'] = emuMemberCleanup
outputCode( '%s/RegalContext.cpp' % args.outdir, contextSourceTemplate.substitute(substitute))
##############################################################################################
contextInfoHeaderTemplate = Template( '''${AUTOGENERATED}
${LICENSE}
#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 RegalContext;
struct ContextInfo
{
ContextInfo();
~ContextInfo();
void init(const RegalContext &context);
// glewGetExtension, glewIsSupported
bool getExtension(const char *ext) const;
bool isSupported(const char *ext) const;
// As reported by OpenGL implementation
std::string vendor;
std::string renderer;
std::string version;
std::string extensions;
// As reported by Regal
std::string regalVendor;
std::string regalRenderer;
std::string regalVersion;
std::string regalExtensions;
bool regal_ext_direct_state_access;
std::set<std::string> regalExtensionsSet;
// As supported by the OpenGL implementation
${VERSION_DECLARE}
GLuint maxVertexAttribs;
};
REGAL_NAMESPACE_END
#endif // __${HEADER_NAME}_H__
''')
contextInfoSourceTemplate = Template( '''${AUTOGENERATED}
${LICENSE}
#include "pch.h" /* For MS precompiled header support */
#include "RegalUtil.h"
REGAL_GLOBAL_BEGIN
#include <GL/Regal.h>
#include <string>
#include <set>
using namespace std;
#include <boost/print/string_list.hpp>
using namespace boost::print;
#include "RegalToken.h"
#include "RegalContext.h"
#include "RegalContextInfo.h"
#include "RegalIff.h" // For REGAL_MAX_VERTEX_ATTRIBS
REGAL_GLOBAL_END
REGAL_NAMESPACE_BEGIN
using namespace ::REGAL_NAMESPACE_INTERNAL::Logging;
using namespace ::REGAL_NAMESPACE_INTERNAL::Token;
ContextInfo::ContextInfo()
: regal_ext_direct_state_access(false),
${VERSION_INIT}
maxVertexAttribs(0)
{
ITrace("ContextInfo::ContextInfo");
}
ContextInfo::~ContextInfo()
{
ITrace("ContextInfo::~ContextInfo");
}
inline string getString(const RegalContext &context, const GLenum e)
{
ITrace("getString ",toString(e));
RegalAssert(context.dsp->driverTbl.glGetString);
const GLubyte *str = context.dsp->driverTbl.glGetString(e);
return str ? string(reinterpret_cast<const char *>(str)) : string();
}
void
ContextInfo::init(const RegalContext &context)
{
// OpenGL Version.
vendor = getString(context, GL_VENDOR);
renderer = getString(context, GL_RENDERER);
version = getString(context, GL_VERSION);
Info("OpenGL vendor : ",vendor);
Info("OpenGL renderer : ",renderer);
Info("OpenGL version : ",version);
gl_version_major = 0;
gl_version_minor = 0;
gles_version_major = 0;
gles_version_minor = 0;
// Detect GL context version
gles = starts_with(version,"OpenGL ES ");
if (gles)
sscanf(version.c_str(), "OpenGL ES %d.%d", &gles_version_major, &gles_version_minor);
else
sscanf(version.c_str(), "%d.%d", &gl_version_major, &gl_version_minor);
// Detect core context
if (!gles && gl_version_major>=3)
{
GLint flags = 0;
RegalAssert(context.dsp->driverTbl.glGetIntegerv);
context.dsp->driverTbl.glGetIntegerv(GL_CONTEXT_PROFILE_MASK, &flags);
core = flags & GL_CONTEXT_CORE_PROFILE_BIT ? GL_TRUE : GL_FALSE;
}
compat = !core && !gles;
// Detect extensions
string_list<string> extList;
if (core)
{
RegalAssert(context.dsp->driverTbl.glGetStringi);
RegalAssert(context.dsp->driverTbl.glGetIntegerv);
GLint n = 0;
context.dsp->driverTbl.glGetIntegerv(GL_NUM_EXTENSIONS, &n);
for (GLint i=0; i<n; ++i)
extList.push_back(reinterpret_cast<const char *>(context.dsp->driverTbl.glGetStringi(GL_EXTENSIONS,i)));
extensions = extList.join(" ");
}
else
{
extensions = getString(context, GL_EXTENSIONS);
extList.split(extensions,' ');
}
Info("OpenGL extensions: ",extensions);
// TODO - filter out extensions Regal doesn't support?
#ifdef REGAL_GL_VENDOR
regalVendor = REGAL_EQUOTE(REGAL_GL_VENDOR);
#else
regalVendor = vendor;
#endif
#ifdef REGAL_GL_RENDERER
regalRenderer = REGAL_EQUOTE(REGAL_GL_RENDERER);
#else
regalRenderer = renderer;
#endif
#ifdef REGAL_GL_VERSION
regalVersion = REGAL_EQUOTE(REGAL_GL_VERSION);
#else
regalVersion = version;
#endif
#ifdef REGAL_GL_EXTENSIONS
regalExtensions = REGAL_EQUOTE(REGAL_GL_EXTENSIONS);
#else
static const char *ourExtensions[5] = {
"GL_REGAL_error_string",
"GL_REGAL_extension_query",
"GL_REGAL_log",
"GL_REGAL_enable",
"GL_EXT_debug_marker"
};
regalExtensionsSet.insert(extList.begin(),extList.end());
regalExtensionsSet.insert(&ourExtensions[0],&ourExtensions[5]);
regalExtensions = ::boost::print::detail::join(regalExtensionsSet,string(" "));
#endif
#ifndef REGAL_NO_GETENV
{
const char *vendorEnv = GetEnv("REGAL_GL_VENDOR");
if (vendorEnv) regalVendor = vendorEnv;
const char *rendererEnv = GetEnv("REGAL_GL_RENDERER");
if (rendererEnv) regalRenderer = rendererEnv;
const char *versionEnv = GetEnv("REGAL_GL_VERSION");
if (versionEnv) regalVersion = versionEnv;
const char *extensionsEnv = GetEnv("REGAL_GL_EXTENSIONS");
if (extensionsEnv) regalExtensions = extensionsEnv;
}
#endif
Info("Regal vendor : ",regalVendor);
Info("Regal renderer : ",regalRenderer);
Info("Regal version : ",regalVersion);
Info("Regal extensions : ",regalExtensions);
${VERSION_DETECT}
// Vendor, rendering, version, extensions reported by Regal to application
set<string> e;
e.insert(extList.begin(),extList.end());
${EXT_INIT}
RegalAssert(context.dsp->driverTbl.glGetIntegerv);
context.dsp->driverTbl.glGetIntegerv( GL_MAX_VERTEX_ATTRIBS, reinterpret_cast<GLint *>(&maxVertexAttribs));
if (maxVertexAttribs > REGAL_MAX_VERTEX_ATTRIBS)
maxVertexAttribs = REGAL_MAX_VERTEX_ATTRIBS;
// Qualcomm fails with float4 attribs with 256 byte stride, so artificially limit to 8 attribs
if (vendor == "Qualcomm" || vendor == "Chromium")
maxVertexAttribs = 8;
}
${EXT_CODE}
REGAL_NAMESPACE_END
''')
def traverseContextInfo(apis, args):
for api in apis:
if api.name == 'gles':
api.versions = [ [2, 0] ]
if api.name == 'gl':
api.versions = [ [4,2], [4, 1], [4, 0] ]
api.versions += [ [3, 3], [3, 2], [3, 1], [3, 0] ]
api.versions += [ [2, 1], [2, 0] ]
api.versions += [ [1, 5], [1, 4], [1, 3], [1, 2], [1, 1], [1, 0] ]
if api.name == 'glx':
api.versions = [ [1, 4], [1, 3], [1, 2], [1, 1], [1, 0] ]
c = set()
c.update([i.category for i in api.functions])
c.update([i.category for i in api.typedefs])
c.update([i.category for i in api.enums])
api.categories = [i for i in c if i and len(i) and i.find('_VERSION_')==-1 and i.find('WGL_core')==-1]
def versionDeclareCode(apis, args):
code = ''
for api in apis:
name = api.name.lower()
if name == 'gl':
code += ' GLboolean compat : 1;\n'
code += ' GLboolean core : 1;\n'
code += ' GLboolean gles : 1;\n\n'
if name in ['gl', 'glx']:
code += ' GLint %s_version_major;\n' % name
code += ' GLint %s_version_minor;\n' % name
code += '\n'
if hasattr(api, 'versions'):
for version in sorted(api.versions):
code += ' GLboolean %s_version_%d_%d : 1;\n' % (name, version[0], version[1])
code += '\n'
if name == 'gl':
code += ' GLint gles_version_major;\n'
code += ' GLint gles_version_minor;\n'
code += '\n'
code += ' GLint glsl_version_major;\n'
code += ' GLint glsl_version_minor;\n'
code += '\n'
for api in apis:
name = api.name.lower()
if name in cond:
code += '#ifdef %s\n'%cond[name]
for c in sorted(api.categories):
code += ' GLboolean %s : 1;\n' % (c.lower())
if name in cond:
code += '#endif\n'
code += '\n'
return code
def versionInitCode(apis, args):
code = ''
for api in apis:
name = api.name.lower()
if name == 'gl':
code += ' compat(false),\n'
code += ' core(false),\n'
code += ' gles(false),\n'
if name in ['gl', 'glx']:
code += ' %s_version_major(-1),\n' % name
code += ' %s_version_minor(-1),\n' % name
if hasattr(api, 'versions'):
for version in sorted(api.versions):
code += ' %s_version_%d_%d(false),\n' % (name, version[0], version[1])
if name == 'gl':
code += ' gles_version_major(-1),\n'
code += ' gles_version_minor(-1),\n'
code += ' glsl_version_major(-1),\n'
code += ' glsl_version_minor(-1),\n'
for api in apis:
name = api.name.lower()
if name in cond:
code += '#ifdef %s\n'%cond[name]
for c in sorted(api.categories):
code += ' %s(false),\n' % (c.lower())
if name in cond:
code += '#endif\n'
return code
def versionDetectCode(apis, args):
code = ''
for api in apis:
name = api.name.lower()
if not hasattr(api, 'versions'):
continue
indent = ''
if api.name=='gl':
indent = ' '
code += ' if (!gles)\n {\n'
for i in range(len(api.versions)):
version = api.versions[i]
versionMajor = version[0]
versionMinor = version[1]
# Latest version
if i is 0:
code += '%s %s_version_%d_%d = '%(indent, name, versionMajor, versionMinor)
if versionMinor > 0:
code += '%s_version_major > %d || (%s_version_major == %d && %s_version_minor >= %d);\n' % (name, versionMajor, name, versionMajor, name, versionMinor)
else:
code += '%s_version_major >= %d;\n' % (name, versionMajor)
continue
versionLast = api.versions[i-1]
code += '%s %s_version_%d_%d = %s_version_%d_%d || '%(indent,name,versionMajor,versionMinor,name,versionLast[0],versionLast[1])
if versionMinor > 0:
code += '(%s_version_major == %d && %s_version_minor == %d);\n' % (name, versionMajor, name, versionMinor)
else:
code += '%s_version_major == %d;\n' % (name, versionMajor)
if len(indent):
code += ' }\n'
code += '\n'
return code
def extensionStringCode(apis, args):
code = ''
for api in apis:
name = api.name.lower()
if name in cond:
code += '#ifdef %s\n'%cond[name]
for c in sorted(api.categories):
code += ' %s = e.find("%s")!=e.end();\n' % (c.lower(),c)
if name in cond:
code += '#endif\n'
code += '\n'
return code
def getExtensionCode(apis, args):
code = ''
code += 'bool\n'
code += 'ContextInfo::getExtension(const char *ext) const\n'
code += '{\n'
code += ' ITrace("ContextInfo::getExtension ",boost::print::quote(ext,\'"\'));\n'
code += '\n'
for api in apis:
name = api.name.lower()
if name in cond:
code += '#ifdef %s\n'%cond[name]
for c in sorted(api.categories):
if c.startswith('GL_REGAL_') or c=='GL_EXT_debug_marker':
code += ' if (!strcmp(ext,"%s")) return true;\n' % (c)
elif c=='GL_EXT_direct_state_access':
code += ' if (!strcmp(ext,"%s")) return regal_ext_direct_state_access || %s;\n' % (c,c.lower())
else:
code += ' if (!strcmp(ext,"%s")) return %s;\n' % (c,c.lower())
if name in cond:
code += '#endif\n'
code += '\n'
code += 'return false;\n'
code += '}\n\n'
code += 'bool\n'
code += 'ContextInfo::isSupported(const char *ext) const\n'
code += '{\n'
code += ' ITrace("ContextInfo::isSupported ",boost::print::quote(ext,\'"\'));\n'
code += '\n'
code += ' string_list<string> e;\n'
code += ' e.split(ext,\' \');\n'
code += ' for (string_list<string>::const_iterator i=e.begin(); i!=e.end(); ++i)\n'
code += ' if (i->length() && !getExtension(i->c_str())) return false;\n'
code += ' return true;\n'
code += '}\n'
return code
def generateContextInfoHeader(apis, args):
substitute = {}
substitute['LICENSE'] = regalLicense
substitute['AUTOGENERATED'] = autoGeneratedMessage
substitute['COPYRIGHT'] = args.copyright
substitute['HEADER_NAME'] = "REGAL_CONTEXT_INFO"
substitute['VERSION_DECLARE'] = versionDeclareCode(apis,args)
outputCode( '%s/RegalContextInfo.h' % args.outdir, contextInfoHeaderTemplate.substitute(substitute))
def generateContextInfoSource(apis, args):
substitute = {}
substitute['LICENSE'] = regalLicense
substitute['AUTOGENERATED'] = autoGeneratedMessage
substitute['COPYRIGHT'] = args.copyright
substitute['VERSION_INIT'] = versionInitCode(apis,args)
substitute['VERSION_DETECT'] = versionDetectCode(apis,args)
substitute['EXT_INIT'] = extensionStringCode(apis,args)
substitute['EXT_CODE'] = getExtensionCode(apis,args)
outputCode( '%s/RegalContextInfo.cpp' % args.outdir, contextInfoSourceTemplate.substitute(substitute))
##############################################################################################
lookupSourceTemplate = Template( '''${AUTOGENERATED}
${LICENSE}
#include "pch.h" /* For MS precompiled header support */
#include "RegalUtil.h"
REGAL_GLOBAL_BEGIN
#include "RegalPrivate.h"
#include "RegalLookup.h"
REGAL_GLOBAL_END
REGAL_NAMESPACE_BEGIN
namespace Lookup {
${CODE}
}
REGAL_NAMESPACE_END
''')
def generateLookupSource(apis, args):
code = []
for i in apis:
names = []
for j in i.functions:
names.append(j.name)
if i.name in cond:
code.append( '#ifdef %s'%cond[i.name] )
code.extend(pointerLookupByNameCode([ (j,j) for j in names ],("%s_Name"%i.name,"%s_Value"%i.name),valueCast = '(void *)(%s)'))
# offset table
table = "DispatchTableGlobal"
if( i.name == "gl" ):
table = "DispatchTable"
val = [ (j,"offsetof(%s,%s)/sizeof(void *)"%(table,j)) for j in names ]
val = sorted( val )
code.append( 'const size_t %s_Offset[%d] = {' % (i.name, len(val)+1) ) # terminating NULL
for j in val:
code.append( ' ' + j[1] + ',' )
code.append( ' 0')
code.append('};')
code.append('')
if i.name in cond:
code.append( '#endif' )
code.append( '' )
substitute = {}
substitute['LICENSE'] = regalLicense
substitute['AUTOGENERATED'] = autoGeneratedMessage
substitute['COPYRIGHT'] = args.copyright
substitute['CODE'] = '\n'.join(code)
outputCode( '%s/RegalLookup.cpp' % args.outdir, lookupSourceTemplate.substitute(substitute))
##############################################################################################
lookupHeaderTemplate = Template( '''${AUTOGENERATED}
${LICENSE}
#ifndef __${HEADER_NAME}_H__
#define __${HEADER_NAME}_H__
#include "RegalUtil.h"
REGAL_GLOBAL_BEGIN
#include <cstdlib>
#include <cstring>
REGAL_GLOBAL_END
REGAL_NAMESPACE_BEGIN
namespace Lookup {
inline int NameCmp(const void *a, const void *b)
{
return std::strcmp(*(const char **) a, *(const char **) b);
}
${CODE}
}
REGAL_NAMESPACE_END
#endif
''')
def generateLookupHeader(apis, args):
code = []
for i in apis:
if i.name in cond:
code.append( '#ifdef %s'%cond[i.name] )
names = []
for j in i.functions:
names.append( j.name )
lName = '%s_Name'%i.name
lValue = '%s_Value'%i.name
lOffset = '%s_Offset'%i.name
lSize = len(names)+1
code.append( '' )
code.append( 'extern const char * const %s[%d];'%(lName,lSize) )
code.append( 'extern const void *%s[%d];'%(lValue,lSize) )
code.append( 'extern const size_t %s[%d];'%(lOffset,lSize) )
code.append('''
template<typename T>
T
%s(const char *name, T def = NULL)
{
const char **res = (const char **) std::bsearch(&name, %s, %d, sizeof(const char *), NameCmp);
return res ? reinterpret_cast<T>(const_cast<void *>(%s[(size_t) (res - %s)])) : def;
}
'''%('%s_Lookup'%i.name,lName,lSize-1,lValue,lName))
code.append('''
inline size_t %s(const char *name)
{
const char **res = (const char **) std::bsearch(&name, %s, %d, sizeof(const char *), NameCmp);
return res ? %s[(size_t) (res - %s)] : 0;
}
'''%('%s_LookupOffset'%i.name,lName,lSize-1,lOffset,lName))
if i.name in cond:
code.append( '#endif' )
code.append( '' )
substitute = {}
substitute['LICENSE'] = regalLicense
substitute['AUTOGENERATED'] = autoGeneratedMessage
substitute['COPYRIGHT'] = args.copyright
substitute['HEADER_NAME'] = "REGAL_LOOKUP"
substitute['CODE'] = '\n'.join(code)
outputCode( '%s/RegalLookup.h' % args.outdir, lookupHeaderTemplate.substitute(substitute))
##############################################################################################
tokenSourceTemplate = Template( '''${AUTOGENERATED}
${LICENSE}
#include "pch.h" /* For MS precompiled header support */
#include "RegalUtil.h"
REGAL_GLOBAL_BEGIN
#include "RegalPrivate.h"
#include "RegalToken.h"
REGAL_GLOBAL_END
REGAL_NAMESPACE_BEGIN
namespace Token {
const char * GLbooleanToString(GLboolean v)
{
return v==GL_FALSE ? "GL_FALSE" : "GL_TRUE";
}
const char * internalFormatToString(GLint v)
{
const char *integer[5] = { "", "1", "2", "3", "4" };
return 1<=v && v<=4 ? integer[v] : GLenumToString(v);
}
${CODE}
}
REGAL_NAMESPACE_END
''')
def generateTokenSource(apis, args):
code = []
e = {}
code.append(' const char * GLenumToString( GLenum e ) {')
code.append(' switch( e ) {')
for i in apis:
if i.name != 'gl':
continue
for j in i.enums:
if j.name != 'defines':
continue
for k in j.enumerants:
value = toLong(k.value)
if value != None:
if not value in e:
e[value] = set()
e[value].add(k.name)
e = sorted([ (i,sorted(list(e[i]))) for i in e.iterkeys() ])
e = [ i for i in e if i[0] < 0xfffffffff ]
# Filter out extension duplicates
u = e
for i in ['_ARB','_EXT','_NV','_ATI','_PGI','_OES','_IBM','_SUN','_SGI','_SGIX','_SGIS','_APPLE']:
u = [ (j[0], [ k for k in j[1] if not k.endswith(i) ]) for j in u ]
# Filter out _BIT duplicates
for i in ['_BIT','_BITS']:
u = [ (j[0], [ k for k in j[1] if not k.endswith(i) ]) for j in u ]
u = [ (i[0], [ j for j in i[1] if not j.startswith('GL_KTX_') ]) for i in u ]
# Form tuple of value, filtered names, all names, per GLenum
e = [ (e[i][0], u[i][1], e[i][1]) for i in xrange(len(e)) ]
for i in e:
value = i[0]
if len(i[1]):
name = i[1][0]
else:
name = i[2][0]
if value==0:
name = 'GL_ZERO'
if value==1:
name = 'GL_ONE'
code.append(' case %s: return "%s";'%(hexValue(value,'0x%08x'),name))
code.append(' default: break;')
code.append(' }')
code.append(' return "unknown_gl_enum";')
code.append(' }')
# GLerrorToString
code.append('')
code.append(' const char * GLerrorToString( GLenum e ) {')
code.append(' switch( e ) {')
for i in apis:
if i.name != 'gl':
continue
for j in i.enums:
if j.name != 'defines':
continue
for k in j.enumerants:
if getattr(k,'gluErrorString',None):
code.append(' case %s: return "%s";'%(k.name,k.gluErrorString))
code.append(' default: break;')
code.append(' }')
code.append(' return NULL;')
code.append(' }')
substitute = {}
substitute['LICENSE'] = regalLicense
substitute['AUTOGENERATED'] = autoGeneratedMessage
substitute['COPYRIGHT'] = args.copyright
substitute['CODE'] = '\n'.join(code)
outputCode( '%s/RegalToken.cpp' % args.outdir, tokenSourceTemplate.substitute(substitute))
##############################################################################################
tokenHeaderTemplate = Template( '''${AUTOGENERATED}
${LICENSE}
#ifndef __${HEADER_NAME}_H__
#define __${HEADER_NAME}_H__
#include "RegalUtil.h"
REGAL_GLOBAL_BEGIN
#include <GL/Regal.h>
REGAL_GLOBAL_END
REGAL_NAMESPACE_BEGIN
namespace Token {
const char * GLenumToString (GLenum v);
const char * GLerrorToString (GLenum v); // gluErrorString
const char * GLbooleanToString (GLboolean v);
const char * internalFormatToString(GLint v);
inline const char *toString(const GLenum v) { return GLenumToString(v); }
inline const char *toString(const GLboolean v) { return GLbooleanToString(v); }
}
REGAL_NAMESPACE_END
#endif
''')
def generateTokenHeader(apis, args):
substitute = {}
used = {}
for i in apis:
if i.name != 'gl':
continue
for enum in i.enums:
if enum.name != 'defines':
continue
for enumerant in enum.enumerants:
value = enumerant.value
if isinstance(value, str) or isinstance(value, unicode):
try:
value = long(value)
except:
value = enumerant.value
if value > pow(2,32):
continue
if (not value in used) or (len(used[ value ].name) > len(enumerant.name)):
used[ value ] = enumerant
sorted_used = [ x for x in used ]
sorted_used.sort(key=lambda x: x)
for u in sorted_used:
value = u
name = used[u].name
# use hex value, if possible
valueHex = value
if isinstance(value, int):
valueHex = '0x%x'%(value)
if isinstance(value, long):
valueHex = '0x%x'%(value)
# Don't bother with decimal for 0-10
if isinstance(value, int) or isinstance(value, long):
if value>=0 and value<10:
value = valueHex
substitute['LICENSE'] = regalLicense
substitute['AUTOGENERATED'] = autoGeneratedMessage
substitute['COPYRIGHT'] = args.copyright
substitute['HEADER_NAME'] = "REGAL_TOKEN"
outputCode( '%s/RegalToken.h' % args.outdir, tokenHeaderTemplate.substitute(substitute))
##############################################################################################
enumHeaderTemplate = Template( '''${AUTOGENERATED}
${LICENSE}
#ifndef __${HEADER_NAME}_H__
#define __${HEADER_NAME}_H__
#include "RegalUtil.h"
REGAL_GLOBAL_BEGIN
#include <GL/Regal.h>
REGAL_GLOBAL_END
REGAL_NAMESPACE_BEGIN
enum Enum {
${REGAL_ENUM}
};
REGAL_NAMESPACE_END
#endif
''')
def generateEnumHeader(apis, args):
regalEnumSet = set()
regalEnum = []
for i in apis:
if i.name == 'gl':
for enum in i.enums:
if enum.name == 'defines':
for enumerant in enum.enumerants:
if not enumerant.name in regalEnumSet:
regalEnumSet.add(enumerant.name)
regalEnum.append(enumerant.name)
# GL_TIMEOUT_IGNORED 0xffffffffffffffff can't be represented as an enum
regalEnum = [ ' R%s = %s,'%(i,i) for i in regalEnum if i not in [ 'GL_TIMEOUT_IGNORED' ] ]
substitute = {}
substitute['LICENSE'] = regalLicense
substitute['AUTOGENERATED'] = autoGeneratedMessage
substitute['COPYRIGHT'] = args.copyright
substitute['REGAL_ENUM'] = '\n'.join(regalEnum)
substitute['HEADER_NAME'] = "REGAL_ENUM"
outputCode( '%s/RegalEnum.h' % args.outdir, enumHeaderTemplate.substitute(substitute))
##############################################################################################
dispatchLogTemplate = Template('''${AUTOGENERATED}
${LICENSE}
#include "pch.h" /* For MS precompiled header support */
#include "RegalUtil.h"
#if REGAL_LOG
REGAL_GLOBAL_BEGIN
#include "RegalLog.h"
#include "RegalToken.h"
#include "RegalHelper.h"
#include "RegalPrivate.h"
#include "RegalDispatchState.h"
using namespace REGAL_NAMESPACE_INTERNAL;
using namespace ::REGAL_NAMESPACE_INTERNAL::Logging;
using namespace ::REGAL_NAMESPACE_INTERNAL::Token;
#ifdef __cplusplus
extern "C" {
#endif
${API_FUNC_DEFINE}
#ifdef __cplusplus
}
#endif
REGAL_GLOBAL_END
REGAL_NAMESPACE_BEGIN
void InitDispatchTableLog(DispatchTable &tbl)
{
${API_GLOBAL_DISPATCH_INIT}
}
REGAL_NAMESPACE_END
#endif
''')
def generateDispatchLog(apis, args):
# CodeGen for API functions.
code = ''
categoryPrev = None
for api in apis:
code += '\n'
if api.name in cond:
code += '#if %s\n' % cond[api.name]
for function in api.functions:
if not function.needsContext:
continue
name = function.name
params = paramsDefaultCode(function.parameters, True)
callParams = paramsNameCode(function.parameters)
rType = typeCode(function.ret.type)
category = getattr(function, 'category', None)
version = getattr(function, 'version', None)
if category:
category = category.replace('_DEPRECATED', '')
elif version:
category = version.replace('.', '_')
category = 'GL_VERSION_' + category
# Close prev category block.
if categoryPrev and not (category == categoryPrev):
code += '\n'
# Begin new category block.
if category and not (category == categoryPrev):
code += '// %s\n\n' % category
categoryPrev = category
code += 'static %sREGAL_CALL %s%s(%s) \n{\n' % (rType, 'log_', name, params)
code += ' %s\n' % debugPrintFunction( function, 'GTrace' )
code += ' RegalContext * rCtx = GET_REGAL_CONTEXT();\n'
code += ' RegalAssert(rCtx);\n'
code += ' RegalAssert(rCtx->dsp);\n'
code += ' DispatchStateScopedStepDown stepDown(rCtx->dsp);\n'
code += ' RegalAssert(rCtx->dsp->curr);\n'
code += ' '
if not typeIsVoid(rType):
code += '%s ret = '%(rType)
code += 'rCtx->dsp->driverTbl.%s(%s);\n' % ( name, callParams )
if not typeIsVoid(rType):
code += ' return ret;\n'
code += '}\n\n'
if api.name in cond:
code += '#endif // %s\n' % cond[api.name]
code += '\n'
# Close pending if block.
if categoryPrev:
code += '\n'
funcInit = apiDispatchFuncInitCode( apis, args, 'log' )
# Output
substitute = {}
substitute['LICENSE'] = regalLicense
substitute['AUTOGENERATED'] = autoGeneratedMessage
# substitute['COPYRIGHT'] = args.copyright
substitute['API_FUNC_DEFINE'] = code
substitute['API_GLOBAL_DISPATCH_INIT'] = funcInit
outputCode( '%s/RegalDispatchLog.cpp' % args.outdir, dispatchLogTemplate.substitute(substitute))
##############################################################################################
def generateDefFile(apis, args, additional_exports):
code1 = []
code2 = []
code3 = []
for i in apis:
if i.name=='wgl' or i.name=='gl':
for j in i.functions:
code1.append(' %s'%j.name)
code2.append(' r%s'%j.name)
if i.name=='cgl' or i.name=='gl':
for j in i.functions:
code3.append('_%s'%j.name)
code1.sort()
code2.sort()
code3.sort()
code1.insert( 0, ' SetPixelFormat' )
code2.insert( 0, ' SetPixelFormat' )
# RegalMakeCurrent, RegalSetErrorCallback
code1 += [' %s' % export for export in additional_exports]
code2 += [' %s' % export for export in additional_exports]
code3 += ['_%s' % export for export in additional_exports]
outputCode( '%s/Regal.def' % args.outdir, 'EXPORTS\n' + '\n'.join(code1))
outputCode( '%s/Regalm.def' % args.outdir, 'EXPORTS\n' + '\n'.join(code2))
outputCode( '%s/export_list_mac.txt' % args.outdir, '# File: export_list\n' + '\n'.join(code3))
##############################################################################################
sourceTemplate = Template('''${AUTOGENERATED}
${LICENSE}
#include "pch.h" /* For MS precompiled header support */
#include "RegalUtil.h"
REGAL_GLOBAL_BEGIN
#include "RegalLog.h"
#include "RegalIff.h"
#include "RegalToken.h"
#include "RegalState.h"
#include "RegalHelper.h"
#include "RegalMarker.h"
using namespace REGAL_NAMESPACE_INTERNAL;
using namespace ::REGAL_NAMESPACE_INTERNAL::Logging;
using namespace ::REGAL_NAMESPACE_INTERNAL::Token;
#ifdef __cplusplus
extern "C" {
#endif
${API_FUNC_DEFINE}
#ifdef __cplusplus
}
#endif
REGAL_GLOBAL_END
''')
def generateSource(apis, args):
# CodeGen for API functions.
apiFuncDefine = apiFuncDefineCode( apis, args )
globalDispatch = apiGlobalDispatchFuncInitCode( apis, args )
# Output
substitute = {}
substitute['LICENSE'] = regalLicense
substitute['AUTOGENERATED'] = autoGeneratedMessage
substitute['COPYRIGHT'] = args.copyright
substitute['API_FUNC_DEFINE'] = apiFuncDefine
substitute['API_GLOBAL_DISPATCH_INIT'] = globalDispatch
outputCode( '%s/Regal.cpp' % args.outdir, sourceTemplate.substitute(substitute))
##############################################################################################
dispatchSourceTemplate = Template('''${AUTOGENERATED}
${LICENSE}
#include "pch.h" /* For MS precompiled header support */
#include "RegalUtil.h"
${IFDEF}REGAL_GLOBAL_BEGIN
#include <string>
using namespace std;
#include "RegalLog.h"
#include "RegalToken.h"
#include "RegalHelper.h"
#include "RegalPrivate.h"
#include "RegalContext.h"
#include "RegalDispatchState.h"
${LOCAL_INCLUDE}
REGAL_GLOBAL_END
REGAL_NAMESPACE_BEGIN
using namespace ::REGAL_NAMESPACE_INTERNAL::Logging;
using namespace ::REGAL_NAMESPACE_INTERNAL::Token;
${LOCAL_CODE}
${API_DISPATCH_FUNC_DEFINE}
void InitDispatchTable${DISPATCH_NAME}(DispatchTable &tbl)
{
${API_DISPATCH_FUNC_INIT}
}
REGAL_NAMESPACE_END
${ENDIF}''')
##############################################################################################
loaderLocalCode = ''
def generateLoaderSource(apis, args):
funcDefine = apiLoaderFuncDefineCode( apis, args )
funcInit = apiDispatchFuncInitCode( apis, args, 'loader' )
# Output
substitute = {}
substitute['LICENSE'] = regalLicense
substitute['DISPATCH_NAME'] = 'Loader'
substitute['LOCAL_CODE'] = loaderLocalCode
substitute['LOCAL_INCLUDE'] = ''
substitute['AUTOGENERATED'] = autoGeneratedMessage
substitute['COPYRIGHT'] = args.copyright
substitute['API_DISPATCH_FUNC_DEFINE'] = funcDefine
substitute['API_DISPATCH_FUNC_INIT'] = funcInit
substitute['IFDEF'] = '#ifndef __native_client__\n\n'
substitute['ENDIF'] = '#endif\n'
outputCode( '%s/RegalDispatchLoader.cpp' % args.outdir, dispatchSourceTemplate.substitute(substitute))
##############################################################################################
emuLocalCode = '''
'''
def generateEmuSource(apis, args):
funcDefine = apiEmuFuncDefineCode( apis, args )
funcInit = apiEmuDispatchFuncInitCode( apis, args )
emuLocalInclude = '''
#include "RegalBin.h"
#include "RegalEmu.h"
#include "RegalPpa.h"
#include "RegalIff.h"
#include "RegalMarker.h"
#include "RegalObj.h"
#include "RegalDsa.h"
#include "RegalVao.h"'''
# Output
substitute = {}
substitute['LICENSE'] = regalLicense
substitute['DISPATCH_NAME'] = 'Emu'
substitute['LOCAL_CODE'] = emuLocalCode
substitute['LOCAL_INCLUDE'] = emuLocalInclude
substitute['AUTOGENERATED'] = autoGeneratedMessage
substitute['COPYRIGHT'] = args.copyright
substitute['API_DISPATCH_FUNC_DEFINE'] = funcDefine
substitute['API_DISPATCH_FUNC_INIT'] = funcInit
substitute['IFDEF'] = ''
substitute['ENDIF'] = ''
outputCode( '%s/RegalDispatchEmu.cpp' % args.outdir, dispatchSourceTemplate.substitute(substitute))
##############################################################################################
def generateErrorSource(apis, args):
funcDefine = apiErrorFuncDefineCode( apis, args )
funcInit = apiDispatchFuncInitCode( apis, args, 'error' )
# Output
substitute = {}
substitute['LICENSE'] = regalLicense
substitute['DISPATCH_NAME'] = 'Error'
substitute['LOCAL_INCLUDE'] = ''
substitute['LOCAL_CODE'] = ''
substitute['AUTOGENERATED'] = autoGeneratedMessage
substitute['COPYRIGHT'] = args.copyright
substitute['API_DISPATCH_FUNC_DEFINE'] = funcDefine
substitute['API_DISPATCH_FUNC_INIT'] = funcInit
substitute['IFDEF'] = '#if REGAL_ERROR\n\n'
substitute['ENDIF'] = '#endif\n'
outputCode( '%s/RegalDispatchError.cpp' % args.outdir, dispatchSourceTemplate.substitute(substitute))
##############################################################################################
# CodeGen for NaCL dispatch functions
def apiNaclFuncDefineCode(apis, args):
code = ''
for api in apis:
if api.name=='gl':
for function in api.functions:
if not function.needsContext:
continue
if getattr(function,'esVersions',None)==None or 2.0 not in function.esVersions:
continue
name = function.name
params = paramsDefaultCode(function.parameters, True)
callParams = paramsNameCode(function.parameters)
rType = typeCode(function.ret.type)
naclName = name
if naclName.startswith('gl'):
naclName = naclName[2:]
code += 'static %sREGAL_CALL %s%s(%s) \n{\n' % (rType, 'nacl_', name, params)
code += ' ITrace("nacl_%s");\n' % name
code += ' RegalContext * rCtx = GET_REGAL_CONTEXT();\n'
code += ' RegalAssert(rCtx)\n'
code += ' RegalAssert(rCtx->naclES2)\n'
code += ' RegalAssert(rCtx->naclES2->%s)\n'%(naclName)
code += ' RegalAssert(rCtx->naclResource)\n'
if not typeIsVoid(rType):
code += ' %s ret = ' % rType
else:
code += ' '
if len(callParams):
callParams = 'rCtx->naclResource, %s'%callParams
else:
callParams = 'rCtx->naclResource'
code += 'rCtx->naclES2->%s(%s);\n' % ( naclName, callParams )
if not typeIsVoid(rType):
code += ' return ret;\n'
code += '}\n\n'
return code
def apiNaclFuncInitCode(apis, args):
code = '// OpenGL ES 2.0 only\n'
for api in apis:
if api.name=='gl':
for function in api.functions:
if not function.needsContext:
continue
if getattr(function,'esVersions',None)==None or 2.0 not in function.esVersions:
continue
name = function.name
params = paramsDefaultCode(function.parameters, True)
callParams = paramsNameCode(function.parameters)
rType = typeCode(function.ret.type)
code += ' tbl.%s = %s_%s;\n' % ( name, 'nacl', name )
return code
def generateNaclSource(apis, args):
funcDefine = apiNaclFuncDefineCode( apis, args )
funcInit = apiNaclFuncInitCode ( apis, args )
# Output
substitute = {}
substitute['LICENSE'] = regalLicense
substitute['DISPATCH_NAME'] = 'Nacl'
substitute['LOCAL_INCLUDE'] = '#include <ppapi/c/ppb_opengles2.h>'
substitute['LOCAL_CODE'] = ''
substitute['AUTOGENERATED'] = autoGeneratedMessage
substitute['COPYRIGHT'] = args.copyright
substitute['API_DISPATCH_FUNC_DEFINE'] = funcDefine
substitute['API_DISPATCH_FUNC_INIT'] = funcInit
substitute['IFDEF'] = '#if defined(__native_client__)\n'
substitute['ENDIF'] = '#endif\n'
outputCode( '%s/RegalDispatchNacl.cpp' % args.outdir, dispatchSourceTemplate.substitute(substitute))
##############################################################################################
# CodeGen for missing dispatch functions
def apiMissingFuncDefineCode(apis, args):
code = ''
categoryPrev = None
for api in apis:
code += '\n'
if api.name in cond:
code += '#if %s\n' % cond[api.name]
for function in api.functions:
if not function.needsContext:
continue
name = function.name
params = paramsDefaultCode(function.parameters, True)
callParams = paramsNameCode(function.parameters)
rType = typeCode(function.ret.type)
category = getattr(function, 'category', None)
version = getattr(function, 'version', None)
if category:
category = category.replace('_DEPRECATED', '')
elif version:
category = version.replace('.', '_')
category = 'GL_VERSION_' + category
# Close prev category block.
if categoryPrev and not (category == categoryPrev):
code += '\n'
# Begin new category block.
if category and not (category == categoryPrev):
code += '// %s\n\n' % category
categoryPrev = category
code += '%sREGAL_CALL %s%s(%s) \n{\n' % (rType, 'missing_', name, params)
for param in function.parameters:
code += ' UNUSED_PARAMETER(%s);\n' % param.name
code += ' Warning( "%s not available." );\n' % name
if not typeIsVoid(rType):
if rType[-1] != '*':
code += ' %s ret = (%s)0;\n' % ( rType, rType )
else:
code += ' %s ret = NULL;\n' % rType
code += ' return ret;\n'
code += '}\n\n'
if api.name in cond:
code += '#endif // %s\n' % cond[api.name]
code += '\n'
return code
def generateMissingSource(apis, args):
# Output
substitute = {}
substitute['LICENSE'] = regalLicense
substitute['DISPATCH_NAME'] = 'Missing'
substitute['LOCAL_INCLUDE'] = ''
substitute['LOCAL_CODE'] = ''
substitute['AUTOGENERATED'] = autoGeneratedMessage
substitute['COPYRIGHT'] = args.copyright
substitute['API_DISPATCH_FUNC_DEFINE'] = apiMissingFuncDefineCode( apis, args )
substitute['API_DISPATCH_FUNC_INIT'] = apiDispatchFuncInitCode( apis, args, 'missing' )
substitute['IFDEF'] = ''
substitute['ENDIF'] = ''
outputCode( '%s/RegalDispatchMissing.cpp' % args.outdir, dispatchSourceTemplate.substitute(substitute))
##############################################################################################
debugGlobalCode = '''
#include "RegalDebugInfo.h"
'''
debugLocalCode = '''
'''
def generateDebugSource(apis, args):
funcDefine = apiDebugFuncDefineCode( apis, args )
funcInit = apiDispatchFuncInitCode( apis, args, 'debug' )
# Output
substitute = {}
substitute['LICENSE'] = regalLicense
substitute['DISPATCH_NAME'] = 'Debug'
substitute['LOCAL_INCLUDE'] = debugGlobalCode
substitute['LOCAL_CODE'] = debugLocalCode
substitute['AUTOGENERATED'] = autoGeneratedMessage
substitute['COPYRIGHT'] = args.copyright
substitute['API_DISPATCH_FUNC_DEFINE'] = funcDefine
substitute['API_DISPATCH_FUNC_INIT'] = funcInit
substitute['IFDEF'] = '#if REGAL_DEBUG\n\n'
substitute['ENDIF'] = '#endif\n'
outputCode( '%s/RegalDispatchDebug.cpp' % args.outdir, dispatchSourceTemplate.substitute(substitute))
##############################################################################################
def apiTypedefCode( apis, args ):
code = ''
for api in apis:
code += '\n'
if api.name in cond:
code += '#if %s\n' % cond[api.name]
if api.name == 'wgl':
code += '#ifdef REGAL_SYS_WGL_DECLARE_WGL\n'
code += '#ifndef _WINDEF_\n'
for typedef in api.typedefs:
if api.name == 'wgl' and typedef.name=='GLYPHMETRICSFLOAT':
code += '#endif\n'
code += '#ifndef _WINGDI_\n'
if api.name == 'wgl' and typedef.name=='HPBUFFERARB':
code += '#endif\n'
if re.search( '\(\s*\*\s*\)', typedef.type ):
code += 'typedef %s;\n' % ( re.sub( '\(\s*\*\s*\)', '(*%s)' % typedef.name, typedef.type ) )
else:
code += 'typedef %s %s;\n' % ( typedef.type, typedef.name )
if api.name == 'wgl':
code += '#endif // REGAL_SYS_WGL_DECLARE_WGL\n'
if api.name in cond:
code += '#endif // %s\n' % cond[api.name]
code += '\n'
return code
# CodeGen for custom API definitions.
def apiEnumCode( apis, args ):
code = ''
for api in apis:
code += '\n'
if api.name in cond:
code += '#if %s\n' % cond[api.name]
if api.name == 'wgl':
code += '#if REGAL_SYS_WGL_DECLARE_WGL\n'
for enum in api.enums:
if enum.name == 'defines':
pass
else:
code += '\ntypedef enum _%s {\n' % enum.name
for enumerant in enum.enumerants:
code += ' %s = %s,\n' % ( enumerant.name, enumerant.value )
code += '} %s;\n\n' % enum.name
if api.name == 'wgl':
code += '#endif // REGAL_SYS_WGL_DECLARE_WGL\n'
if api.name in cond:
code += '#endif // %s\n' % cond[api.name]
code += '\n'
return code
def apiGlobalDispatchTableDefineCode(apis, args):
categoryPrev = None
code = ''
code += 'struct DispatchTableGlobal {\n'
for api in apis:
code += '\n'
if api.name in cond:
code += '#if %s\n' % cond[api.name]
for function in api.functions:
if function.needsContext:
continue
name = function.name
params = paramsDefaultCode(function.parameters, True)
rType = typeCode(function.ret.type)
category = getattr(function, 'category', None)
version = getattr(function, 'version', None)
if category:
category = category.replace('_DEPRECATED', '')
elif version:
category = version.replace('.', '_')
category = 'GL_VERSION_' + category
# Close prev if block.
if categoryPrev and not (category == categoryPrev):
code += '\n'
# Begin new if block.
if category and not (category == categoryPrev):
code += ' // %s\n\n' % category
code += ' %s(REGAL_CALL *%s)(%s);\n' % (rType, name, params)
categoryPrev = category
if api.name in cond:
code += '#endif // %s\n' % cond[api.name]
code += '\n'
# Close pending if block.
if categoryPrev:
code += '\n'
code += '};\n'
return code
def apiDispatchTableDefineCode(apis, args):
categoryPrev = None
code = ''
code += 'struct DispatchTable {\n'
for api in apis:
code += '\n'
if api.name in cond:
code += '#if %s\n' % cond[api.name]
for function in api.functions:
if not function.needsContext:
continue
name = function.name
params = paramsDefaultCode(function.parameters, True)
rType = typeCode(function.ret.type)
category = getattr(function, 'category', None)
version = getattr(function, 'version', None)
if category:
category = category.replace('_DEPRECATED', '')
elif version:
category = version.replace('.', '_')
category = 'GL_VERSION_' + category
# Close prev if block.
if categoryPrev and not (category == categoryPrev):
code += '\n'
# Begin new if block.
if category and not (category == categoryPrev):
code += ' // %s\n\n' % category
code += ' %s(REGAL_CALL *%s)(%s);\n' % (rType, name, params)
categoryPrev = category
if api.name in cond:
code += '#endif // %s\n' % cond[api.name]
code += '\n'
# Close pending if block.
if categoryPrev:
code += '\n'
code += '};\n'
return code
# CodeGen for API function declaration.
def apiFuncDeclareCode(apis, args):
code = ''
for api in apis:
d = [] # defines
e = [] # enums
t = [] # function pointer typedefs
m = [] # mangled names for REGAL_NAMESPACE support
f = [] # gl names
for enum in api.enums:
if enum.name == 'defines':
for enumerant in enum.enumerants:
value = toLong(enumerant.value)
if value==None:
value = enumerant.value
# Don't bother with decimal for 0-10
if isinstance(value, long) and value>=10:
e.append((enumerant.category, '#define %s %s /* %s */'%(enumerant.name,hexValue(value),value)))
else:
e.append((enumerant.category, '#define %s %s'%(enumerant.name,hexValue(value))))
for function in api.functions:
name = function.name
params = paramsDefaultCode(function.parameters, True)
rType = typeCode(function.ret.type)
category = getattr(function, 'category', None)
version = getattr(function, 'version', None)
if category:
category = category.replace('_DEPRECATED', '')
elif version:
category = version.replace('.', '_')
category = 'GL_VERSION_' + category
t.append((category,funcProtoCode(function, version, 'REGAL_CALL', True)))
m.append((category,'#define %-35s r%-35s' % (name, name) ))
f.append((category,'REGAL_DECL %sREGAL_CALL %s(%s);' % (rType, name, params) ))
def cmpEnum(a,b):
if a[0]==b[0]:
aValue = a[1].split(' ')[2]
bValue = b[1].split(' ')[2]
if aValue==bValue:
return cmp(a[1].split(' ')[1], b[1].split(' ')[1])
else:
return cmp(aValue,bValue)
return cmp(a[0],b[0])
def enumIfDef(category):
return '#ifndef REGAL_NO_ENUM_%s'%(upper(category).replace(' ','_'))
def typedefIfDef(category):
return '#ifndef REGAL_NO_TYPEDEF_%s'%(upper(category).replace(' ','_'))
def namespaceIfDef(category):
return '#ifndef REGAL_NO_NAMESPACE_%s'%(upper(category).replace(' ','_'))
def declarationIfDef(category):
return '#ifndef REGAL_NO_DECLARATION_%s'%(upper(category).replace(' ','_'))
categories = set()
categories.update([ i[0] for i in e ])
categories.update([ i[0] for i in t ])
categories.update([ i[0] for i in m ])
categories.update([ i[0] for i in f ])
for i in categories:
if len(i):
cat = upper(i).replace(' ','_')
d.append((i,'#if (defined(%s) || defined(REGAL_NO_ENUM) || defined(REGAL_NO_%s)) && !defined(REGAL_NO_ENUM_%s)'%(cat,cat,cat)))
d.append((i,'#define REGAL_NO_ENUM_%s'%(cat)))
d.append((i,'#endif'))
d.append((i,''))
d.append((i,'#if (defined(%s) || defined(REGAL_NO_TYPEDEF) || defined(REGAL_NO_%s)) && !defined(REGAL_NO_TYPEDEF_%s)'%(cat,cat,cat)))
d.append((i,'#define REGAL_NO_TYPEDEF_%s'%(cat)))
d.append((i,'#endif'))
d.append((i,''))
d.append((i,'#if (defined(%s) || !defined(REGAL_NAMESPACE) || defined(REGAL_NO_%s)) && !defined(REGAL_NO_NAMESPACE_%s)'%(cat,cat,cat)))
d.append((i,'#define REGAL_NO_NAMESPACE_%s'%(cat)))
d.append((i,'#endif'))
d.append((i,''))
d.append((i,'#if (defined(%s) || defined(REGAL_NO_DECLARATION) || defined(REGAL_NO_%s)) && !defined(REGAL_NO_DECLARATION_%s)'%(cat,cat,cat)))
d.append((i,'#define REGAL_NO_DECLARATION_%s'%(cat)))
d.append((i,'#endif'))
d.append((i,''))
d.append((i,'#ifndef %s'%(i)))
d.append((i,'#define %s 1'%(i)))
d.append((i,'#endif'))
d.append((i,''))
e.sort(cmpEnum)
e = alignDefineCategory(e)
e = ifCategory(e,enumIfDef)
e = spaceCategory(e)
t.sort()
t = ifCategory(t,typedefIfDef)
t = spaceCategory(t)
m.sort()
m = ifCategory(m,namespaceIfDef)
m = spaceCategory(m)
f.sort()
f = ifCategory(f,declarationIfDef)
f = spaceCategory(f)
d.extend(e)
d.extend(t)
d.extend(m)
d.extend(f)
tmp = listToString(unfoldCategory(d,'/**\n ** %s\n **/',lambda x,y: cmp(x[0], y[0])))
if api.name == 'wgl':
tmp = wrapIf('REGAL_SYS_WGL_DECLARE_WGL',tmp)
if api.name in cond:
tmp = wrapIf(cond[api.name], tmp)
code += '%s\n'%(tmp)
return code
## Map gl.py helper functions to Regal namespace
helpers = {
'helperGLCallListsSize' : 'helper::size::callLists',
'helperGLFogvSize' : 'helper::size::fogv',
'helperGLLightvSize' : 'helper::size::lightv',
'helperGLLightModelvSize' : 'helper::size::lightModelv',
'helperGLMaterialvSize' : 'helper::size::materialv',
'helperGLTexParametervSize' : 'helper::size::texParameterv',
'helperGLTexEnvvSize' : 'helper::size::texEnvv',
'helperGLTexGenvSize' : 'helper::size::texGenv',
'helperGLNamedStringSize' : 'helper::size::namedString',
# 'helperGLDrawElementsSize' : 'helper::size::drawElements',
'helperGLNamedStringParamsSize' : 'helper::size::namedStringParams'
}
# debug print function
def debugPrintFunction(function, trace = 'ITrace'):
c = ''
args = []
for i in function.parameters:
if i.output:
continue
# Use a cast, if necessary
t = i.type
n = i.name
if i.cast != None:
t = i.cast
n = 'reinterpret_cast<%s>(%s)'%(t,n)
# If it's array of strings, quote each string
quote = ''
if t == 'char **' or t == 'const char **' or t == 'GLchar **' or t == 'const GLchar **' or t == 'LPCSTR *':
quote = ',"\\\""'
if i.regalLog != None:
args.append('%s'%i.regalLog)
elif t == 'GLenum':
args.append('toString(%s)'%n)
elif t == 'GLboolean' or t == 'const GLboolean':
args.append('toString(%s)'%n)
elif t == 'char *' or t == 'const char *' or t == 'GLchar *' or t == 'const GLchar *' or t == 'LPCSTR':
args.append('boost::print::quote(%s,\'"\')'%n)
elif i.input and i.size!=None and (isinstance(i.size,int) or isinstance(i.size, long)) and t.find('void')==-1 and t.find('PIXELFORMATDESCRIPTOR')==-1:
args.append('boost::print::array(%s,%s)'%(n,i.size))
elif i.input and i.size!=None and (isinstance(i.size, str) or isinstance(i.size, unicode)) and t.find('void')==-1 and t.find('PIXELFORMATDESCRIPTOR')==-1 and i.size.find('helper')==-1:
args.append('boost::print::array(%s,%s%s)'%(n,i.size,quote))
elif i.input and i.size!=None and (isinstance(i.size, str) or isinstance(i.size, unicode)) and t.find('void')==-1 and t.find('PIXELFORMATDESCRIPTOR')==-1 and i.size.find('helper')==0:
h = i.size.split('(')[0]
if h in helpers:
args.append('boost::print::array(%s,%s(%s%s)'%(n,helpers[h],i.size.split('(',1)[1],quote))
else:
args.append(n)
elif t.startswith('GLDEBUG'):
pass
elif t.startswith('GLLOGPROC'):
pass
else:
args.append(n)
args = args[:9]
if len(args):
c += '%s("%s(", ' % (trace, function.name)
c += ', ", ", '.join(args)
c += ', ")");'
else:
c += '%s("%s()");' % (trace, function.name)
return c
def apiFuncDefineCode(apis, args):
code = ''
for api in apis:
tmp = []
for function in api.functions:
name = function.name
params = paramsDefaultCode(function.parameters, True)
callParams = paramsNameCode(function.parameters)
rType = typeCode(function.ret.type)
category = getattr(function, 'category', None)
version = getattr(function, 'version', None)
if category:
category = category.replace('_DEPRECATED', '')
elif version:
category = version.replace('.', '_')
category = 'GL_VERSION_' + category
c = ''
c += 'REGAL_DECL %sREGAL_CALL %s(%s) \n{\n' % (rType, name, params)
emue = [ emuFindEntry( function, i['formulae'], i['member'] ) for i in emuRegal ]
if function.needsContext:
c += ' RegalContext * rCtx = GET_REGAL_CONTEXT();\n'
c += ' %s\n' % debugPrintFunction( function, 'RTrace' )
c += ' if (!rCtx) return'
if typeIsVoid(rType):
c += ';\n'
else:
if rType[-1] != '*':
c += ' (%s)0;\n' % ( rType )
else:
c += ' NULL;\n'
c += ' RegalAssert(rCtx);\n'
c += ' RegalAssert(rCtx->dsp);\n'
c += ' RegalAssert(rCtx->dsp->curr);\n'
c += ' RegalAssert(rCtx->dsp->curr->%s);\n' % ( name)
c += ' RegalAssert(rCtx->dsp->curr->%s != %s);\n' % ( name, name)
c += listToString(indent(emuCodeGen(emue,'impl'),' '))
c += ' '
if not typeIsVoid(rType):
c += 'return '
c += 'rCtx->dsp->curr->%s(%s);\n' % ( name, callParams )
else:
c += ' %s\n' % debugPrintFunction(function, 'RTrace' )
c += ' if (dispatchTableGlobal.%s == NULL) {\n' % name
c += ' GetProcAddress( dispatchTableGlobal.%s, "%s" );\n' % ( name, name )
c += ' RegalAssert(dispatchTableGlobal.%s!=%s);\n' % ( name, name )
c += ' }\n'
if not typeIsVoid(rType):
if rType[-1] != '*':
c += ' %s ret = (%s)0;\n' % ( rType, rType )
else:
c += ' %s ret = NULL;\n' % rType
c += listToString(indent(emuCodeGen(emue,'impl'),' '))
c += ' if (dispatchTableGlobal.%s) {\n' % name
c += ' %s\n' % debugPrintFunction( function, 'GTrace' )
c += ' '
if not typeIsVoid(rType):
c += 'ret = '
c += 'dispatchTableGlobal.%s(%s);\n' % ( name, callParams )
if name == 'wglMakeCurrent':
c += ' RegalMakeCurrent(RegalSystemContext(hglrc));\n'
elif name == 'CGLSetCurrentContext':
c += ' RegalMakeCurrent( ctx );\n'
elif name == 'glXMakeCurrent':
c += ' RegalMakeCurrent( RegalSystemContext(ctx) );\n'
c += ' }\n'
c += ' else\n'
c += ' Warning( "%s not available." );\n' % name
c += listToString(indent(emuCodeGen(emue,'suffix'),' '))
if not typeIsVoid(rType):
c += ' return ret;\n'
c += '}\n\n'
tmp.append( (category, c) )
tmp = listToString(unfoldCategory(tmp))
if api.name in cond:
tmp = wrapIf(cond[api.name], tmp)
code += tmp
return code
# CodeGen for API loader function definition.
def apiLoaderFuncDefineCode(apis, args):
categoryPrev = None
code = ''
for api in apis:
code += '\n'
if api.name in cond:
code += '#if %s\n' % cond[api.name]
for function in api.functions:
if not function.needsContext:
continue
name = function.name
params = paramsDefaultCode(function.parameters, True)
callParams = paramsNameCode(function.parameters)
rType = typeCode(function.ret.type)
category = getattr(function, 'category', None)
version = getattr(function, 'version', None)
if category:
category = category.replace('_DEPRECATED', '')
elif version:
category = version.replace('.', '_')
category = 'GL_VERSION_' + category
# Close prev category block.
if categoryPrev and not (category == categoryPrev):
code += '\n'
# Begin new category block.
if category and not (category == categoryPrev):
code += '// %s\n\n' % category
categoryPrev = category
code += 'extern %sREGAL_CALL %s%s(%s);\n\n' % (rType, 'missing_', name, params)
code += 'static %sREGAL_CALL %s%s(%s) \n{\n' % (rType, 'loader_', name, params)
code += ' RegalContext * rCtx = GET_REGAL_CONTEXT();\n'
code += ' RegalAssert(rCtx);\n'
code += ' RegalAssert(rCtx->dsp);\n'
code += ' DispatchTable & driverTbl = rCtx->dsp->driverTbl;\n'
code += ' GetProcAddress( driverTbl.%s, "%s");\n' % (name, name)
code += ' if ( !driverTbl.%s ) {\n' % name
code += ' driverTbl.%s = missing_%s;\n' % (name, name)
code += ' }\n'
code += ' // If emu table is using the loader, update its entry too.\n'
code += ' if (rCtx->dsp->emuTbl.%s == loader_%s) {\n' % (name, name)
code += ' rCtx->dsp->emuTbl.%s = driverTbl.%s;\n' % (name, name)
code += ' }\n'
code += ' '
if not typeIsVoid(rType):
code += 'return '
code += 'driverTbl.%s(%s);\n' % ( name, callParams )
code += '}\n\n'
if api.name in cond:
code += '#endif // %s\n' % cond[api.name]
code += '\n'
# Close pending if block.
if categoryPrev:
code += '\n'
return code
# CodeGen for API emu function definition.
def apiEmuFuncDefineCode(apis, args):
categoryPrev = None
code = ''
for api in apis:
code += '\n'
if api.name in cond:
code += '#if %s\n' % cond[api.name]
for function in api.functions:
if not function.needsContext:
continue
name = function.name
params = paramsDefaultCode(function.parameters, True)
callParams = paramsNameCode(function.parameters)
rType = typeCode(function.ret.type)
category = getattr(function, 'category', None)
version = getattr(function, 'version', None)
if category:
category = category.replace('_DEPRECATED', '')
elif version:
category = version.replace('.', '_')
category = 'GL_VERSION_' + category
# Close prev category block.
if categoryPrev and not (category == categoryPrev):
code += '\n'
# Begin new category block.
if category and not (category == categoryPrev):
code += '// %s\n\n' % category
categoryPrev = category
emue = [ emuFindEntry( function, i['formulae'], i['member'] ) for i in emu ]
if all(i is None for i in emue):
continue
code += '\nstatic %sREGAL_CALL %s%s(%s) \n{\n' % (rType, 'emu_', name, params)
code += ' RegalContext * rCtx = GET_REGAL_CONTEXT();\n'
#code += ' RegalCheckGLError( rCtx );\n'
code += '\n'
level = [ (emu[i], emuFindEntry( function, emu[i]['formulae'], emu[i]['member'] )) for i in range( len( emue ) - 1 ) ]
if not all(i[1]==None or not 'prefix' in i[1] and not 'impl' in i[1] for i in level):
code += ' // prefix\n'
code += ' switch( rCtx->emuLevel ) {\n'
for i in level:
l,e = i[0], i[1]
code += ' case %d :\n' % l['level']
if l['ifdef']:
code += ' #if %s\n' % l['ifdef']
if e != None and 'prefix' in e :
if l['member'] :
code += ' if (rCtx->%s) {\n' % l['member']
code += ' RegalEmuScopedActivate activate( rCtx, rCtx->%s );\n' % l['member']
for j in e['prefix'] :
code += ' %s\n' % j
if l['member'] :
code += ' }\n'
if e!= None and 'impl' in e and l['member']:
code += ' if (rCtx->%s) break;\n' % l['member'];
if l['ifdef']:
code += ' #endif\n'
code += ' default:\n'
code += ' break;\n'
code += ' }\n\n'
if not all(i[1]==None or not 'impl' in i[1] for i in level):
code += ' // impl\n'
code += ' switch( rCtx->emuLevel ) {\n'
for i in level:
l,e = i[0], i[1]
code += ' case %d :\n' % l['level']
if l['ifdef']:
code += ' #if %s\n' % l['ifdef']
if e != None and 'impl' in e :
if l['member'] :
code += ' if (rCtx->%s) {\n' % l['member']
code += ' RegalEmuScopedActivate activate( rCtx, rCtx->%s );\n' % l['member']
for j in e['impl'] :
code += ' %s\n' % j
if l['member'] :
if typeIsVoid(rType):
code += ' return;\n'
code += ' }\n'
if l['ifdef']:
code += ' #endif\n'
code += ' default: {\n'
# debug print
# code += ' %s\n' % debugPrintFunction( function, 'GTrace' )
# debug print
code += ' DispatchStateScopedStepDown stepDown(rCtx->dsp);\n'
code += ' '
if not typeIsVoid(rType):
code += 'return '
code += 'rCtx->dsp->curr->%s(%s);\n' % ( name, callParams )
code += ' break;\n'
code += ' }\n\n'
code += ' }\n\n'
else:
code += ' DispatchStateScopedStepDown stepDown(rCtx->dsp);\n'
code += ' '
if not typeIsVoid(rType):
code += 'return '
code += 'rCtx->dsp->curr->%s(%s);\n' % ( name, callParams )
code += '}\n\n'
if api.name in cond:
code += '#endif // %s\n' % cond[api.name]
code += '\n'
# Close pending if block.
if categoryPrev:
code += '\n'
return code
# CodeGen for API error checking function definition.
def apiErrorFuncDefineCode(apis, args):
categoryPrev = None
code = ''
for api in apis:
code += '\n'
if api.name in cond:
code += '#if %s\n' % cond[api.name]
for function in api.functions:
if not function.needsContext:
continue
name = function.name
params = paramsDefaultCode(function.parameters, True)
callParams = paramsNameCode(function.parameters)
rType = typeCode(function.ret.type)
category = getattr(function, 'category', None)
version = getattr(function, 'version', None)
if category:
category = category.replace('_DEPRECATED', '')
elif version:
category = version.replace('.', '_')
category = 'GL_VERSION_' + category
# Close prev category block.
if categoryPrev and not (category == categoryPrev):
code += '\n'
# Begin new category block.
if category and not (category == categoryPrev):
code += '// %s\n\n' % category
categoryPrev = category
code += 'static %sREGAL_CALL %s%s(%s) \n{\n' % (rType, 'error_', name, params)
code += ' ITrace("error_%s");\n' % name
code += ' RegalContext * rCtx = GET_REGAL_CONTEXT();\n'
code += ' RegalAssert(rCtx)\n'
code += ' RegalAssert(rCtx->dsp)\n'
code += ' RegalAssert(rCtx->dsp->curr)\n'
if name != 'glGetError':
code += ' GLenum _error = GL_NO_ERROR;\n'
code += ' DispatchStateScopedStepDown stepDown(rCtx->dsp);\n'
code += ' if (!rCtx->depthBeginEnd)\n'
code += ' _error = rCtx->dsp->curr->glGetError();\n'
code += ' RegalAssert(_error==GL_NO_ERROR);\n'
code += ' '
if not typeIsVoid(rType):
code += '%s ret = ' % rType
code += 'rCtx->dsp->curr->%s(%s);\n' % ( name, callParams )
code += ' if (!rCtx->depthBeginEnd) {\n'
code += ' _error = rCtx->dsp->curr->glGetError();\n'
code += ' if (_error!=GL_NO_ERROR) {\n'
code += ' Error("%s : ",Token::GLerrorToString(_error));\n'%(name)
code += ' if (rCtx->err.callback)\n'
code += ' rCtx->err.callback( _error );\n'
code += ' }\n'
code += ' }\n'
if not typeIsVoid(rType):
code += 'return ret;\n'
else:
code += ' DispatchStateScopedStepDown stepDown(rCtx->dsp);\n'
code += ' GLenum err = rCtx->dsp->curr->glGetError();\n'
code += ' return err;\n'
code += '}\n\n'
if api.name in cond:
code += '#endif // %s\n' % cond[api.name]
code += '\n'
# Close pending if block.
if categoryPrev:
code += '\n'
return code
# CodeGen for API debug function definition.
def apiDebugFuncDefineCode(apis, args):
categoryPrev = None
code = ''
for api in apis:
code += '\n'
if api.name in cond:
code += '#if %s\n' % cond[api.name]
for function in api.functions:
if not function.needsContext:
continue
name = function.name
params = paramsDefaultCode(function.parameters, True)
callParams = paramsNameCode(function.parameters)
rType = typeCode(function.ret.type)
category = getattr(function, 'category', None)
version = getattr(function, 'version', None)
if category:
category = category.replace('_DEPRECATED', '')
elif version:
category = version.replace('.', '_')
category = 'GL_VERSION_' + category
# Close prev category block.
if categoryPrev and not (category == categoryPrev):
code += '\n'
# Begin new category block.
if category and not (category == categoryPrev):
code += '// %s\n\n' % category
categoryPrev = category
code += 'static %sREGAL_CALL %s%s(%s) \n{\n' % (rType, 'debug_', name, params)
code += ' RegalContext * rCtx = GET_REGAL_CONTEXT();\n'
code += ' DispatchStateScopedStepDown stepDown(rCtx->dsp);\n'
e = emuFindEntry( function, debugDispatchFormulae, '' )
if e != None and 'prefix' in e :
for l in e['prefix'] :
code += ' %s\n' % l
code += ' '
if not typeIsVoid(rType):
code += '%s ret = ' % rType
code += 'rCtx->dsp->curr->%s(%s);\n' % ( name, callParams )
if not typeIsVoid(rType):
code += ' return ret;\n'
code += '}\n\n'
if api.name in cond:
code += '#endif // %s\n' % cond[api.name]
code += '\n'
# Close pending if block.
if categoryPrev:
code += '\n'
return code
# CodeGen for dispatch table init.
def apiGlobalDispatchFuncInitCode(apis, args):
categoryPrev = None
code = ''
for api in apis:
code += '\n'
if api.name in cond:
code += '#if %s\n' % cond[api.name]
for function in api.functions:
if function.needsContext:
continue
name = function.name
params = paramsDefaultCode(function.parameters, True)
callParams = paramsNameCode(function.parameters)
rType = typeCode(function.ret.type)
category = getattr(function, 'category', None)
version = getattr(function, 'version', None)
if category:
category = category.replace('_DEPRECATED', '')
elif version:
category = version.replace('.', '_')
category = 'GL_VERSION_' + category
# Close prev category block.
if categoryPrev and not (category == categoryPrev):
code += '\n'
# Begin new category block.
if category and not (category == categoryPrev):
code += '// %s\n\n' % category
categoryPrev = category
code += ' dispatchTableGlobal.%s = %s_%s;\n' % ( name, 'loader', name )
if api.name in cond:
code += '#endif // %s\n' % cond[api.name]
code += '\n'
# Close pending if block.
if categoryPrev:
code += '\n'
return code
# CodeGen for dispatch table init.
def apiDispatchFuncInitCode(apis, args, dispatchName):
categoryPrev = None
code = ''
for api in apis:
code += '\n'
if api.name in cond:
code += '#if %s\n' % cond[api.name]
for function in api.functions:
if not function.needsContext:
continue
name = function.name
params = paramsDefaultCode(function.parameters, True)
callParams = paramsNameCode(function.parameters)
rType = typeCode(function.ret.type)
category = getattr(function, 'category', None)
version = getattr(function, 'version', None)
if category:
category = category.replace('_DEPRECATED', '')
elif version:
category = version.replace('.', '_')
category = 'GL_VERSION_' + category
# Close prev category block.
if categoryPrev and not (category == categoryPrev):
code += '\n'
# Begin new category block.
if category and not (category == categoryPrev):
code += ' // %s\n\n' % category
categoryPrev = category
code += ' tbl.%s = %s_%s;\n' % ( name, dispatchName, name )
if api.name in cond:
code += '#endif // %s\n' % cond[api.name]
code += '\n'
# Close pending if block.
if categoryPrev:
code += '\n'
return code
# CodeGen for dispatch table init.
def apiEmuDispatchFuncInitCode(apis, args):
dispatchName = 'emu'
categoryPrev = None
code = ''
for api in apis:
code += '\n'
if api.name in cond:
code += '#if %s\n' % cond[api.name]
for function in api.functions:
if not function.needsContext:
continue
name = function.name
emue = [ None ]
for i in range( len( emu ) - 1 ) :
emue.append( emuFindEntry( function, emu[i]['formulae'], emu[i]['member'] ) )
if all(i is None for i in emue):
continue
params = paramsDefaultCode(function.parameters, True)
callParams = paramsNameCode(function.parameters)
rType = typeCode(function.ret.type)
category = getattr(function, 'category', None)
version = getattr(function, 'version', None)
if category:
category = category.replace('_DEPRECATED', '')
elif version:
category = version.replace('.', '_')
category = 'GL_VERSION_' + category
# Close prev category block.
if categoryPrev and not (category == categoryPrev):
code += '\n'
# Begin new category block.
if category and not (category == categoryPrev):
code += '// %s\n\n' % category
categoryPrev = category
code += ' tbl.%s = %s_%s;\n' % ( name, dispatchName, name )
if api.name in cond:
code += '#endif // %s\n' % cond[api.name]
code += '\n'
# Close pending if block.
if categoryPrev:
code += '\n'
return code
# Class Export
class Export:
def __init__(self):
parser = OptionParser()
parser.add_option('-a', '--api', dest = 'apis', metavar = 'API VERSION', action = 'append', nargs = 2, help = 'generate loader for API and VERSION')
parser.add_option('-c', '--copyright', dest = 'copyright', action = 'store_true', help = 'include copyright notice')
parser.add_option( '--outdir', dest = 'outdir', metavar = 'DIR', help = 'output directory')
parser.set_defaults(apis = [])
(options, args) = parser.parse_args()
if not len(options.apis):
parser.error('Specify an api.\n See Export.py --help')
apis = []
for apiItem in options.apis:
# Some fakery for gles - use the gl database
if apiItem[0]=='gles':
api = deepcopy(importAttr('gl'))
api.name = 'gles'
else:
api = importAttr(apiItem[0])
api.version = float(apiItem[1])
api.name = '%s' % apiItem[0]
apis.append(api)
class Args(object) : pass
genArgs = Args()
genArgs.copyright = ''
if options.copyright:
genArgs.copyright = copyrightMessage
genArgs.outdir = options.outdir.strip()
generate(apis, genArgs)
export = Export()