You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
833 lines
24 KiB
833 lines
24 KiB
/*=========================================================================
|
|
|
|
Program: Visualization Toolkit
|
|
Module: $RCSfile: ParseOGLExt.cxx,v $
|
|
|
|
Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
|
|
All rights reserved.
|
|
See Copyright.txt or http://www.kitware.com/Copyright.htm for details.
|
|
|
|
This software is distributed WITHOUT ANY WARRANTY; without even
|
|
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
|
PURPOSE. See the above copyright notice for more information.
|
|
|
|
=========================================================================*/
|
|
/* A program that will read in OpenGL extension header files and output VTK
|
|
* code that handles extensions in a more platform-independent manner.
|
|
*/
|
|
|
|
|
|
/*
|
|
* Copyright 2003 Sandia Corporation.
|
|
* Under the terms of Contract DE-AC04-94AL85000, there is a non-exclusive
|
|
* license for use of this work by or on behalf of the
|
|
* U.S. Government. Redistribution and use in source and binary forms, with
|
|
* or without modification, are permitted provided that this Notice and any
|
|
* statement of authorship are reproduced on all copies.
|
|
*/
|
|
|
|
#include "vtkSystemIncludes.h"
|
|
|
|
#include "Tokenizer.h"
|
|
|
|
#include <vtkstd/list>
|
|
#include <vtkstd/set>
|
|
#include <vtkstd/map>
|
|
#include <vtkstd/string>
|
|
|
|
#include <string.h>
|
|
#include <ctype.h>
|
|
|
|
// #define this if you want debug output as the parser does its work
|
|
|
|
// #define DEBUG_PARSE
|
|
|
|
static vtkstd::set< vtkstd::pair< vtkstd::string, vtkstd::string > > ConstantsAlreadyWritten;
|
|
|
|
static vtkstd::string ToUpper(vtkstd::string s)
|
|
{
|
|
vtkstd::string u;
|
|
|
|
for (vtkstd::string::size_type i = 0; i < s.length(); i++)
|
|
{
|
|
u.append(1, (char)toupper(s[i]));
|
|
}
|
|
|
|
return u;
|
|
}
|
|
|
|
class Extension {
|
|
public:
|
|
vtkstd::string name;
|
|
enum {GL, WGL, GLX} type;
|
|
|
|
Extension() {}
|
|
Extension(char *line);
|
|
static bool isExtension(char *line);
|
|
|
|
static inline void WriteSupportWrapperBegin(ostream &out, int itype) {
|
|
switch (itype)
|
|
{
|
|
case WGL:
|
|
out << "#ifdef WIN32" << endl;
|
|
break;
|
|
case GLX:
|
|
out << "#ifdef VTK_USE_X" << endl;
|
|
break;
|
|
case GL:
|
|
break;
|
|
}
|
|
}
|
|
inline void WriteSupportWrapperBegin(ostream &out) const {
|
|
WriteSupportWrapperBegin(out, this->type);
|
|
}
|
|
static inline void WriteSupportWrapperEnd(ostream &out, int itype) {
|
|
if ((itype == WGL) || (itype == GLX))
|
|
{
|
|
out << "#endif" << endl;
|
|
}
|
|
}
|
|
inline void WriteSupportWrapperEnd(ostream &out) const {
|
|
WriteSupportWrapperEnd(out, this->type);
|
|
}
|
|
|
|
static inline const char *TypeToCapString(int t) {
|
|
switch (t)
|
|
{
|
|
case GL: return "GL";
|
|
case GLX: return "GLX";
|
|
case WGL: return "WGL";
|
|
}
|
|
return NULL;
|
|
}
|
|
static inline const char *TypeToString(int t) {
|
|
switch (t)
|
|
{
|
|
case GL: return "gl";
|
|
case GLX: return "glX";
|
|
case WGL: return "wgl";
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
bool operator<(const Extension &obj) const { return this->name < obj.name; }
|
|
};
|
|
|
|
Extension::Extension(char *line)
|
|
{
|
|
Tokenizer t(line);
|
|
|
|
t.GetNextToken();
|
|
|
|
this->name = t.GetNextToken();
|
|
|
|
Tokenizer nameTokens(this->name, "_");
|
|
vtkstd::string header = nameTokens.GetNextToken();
|
|
if (header == "WGL")
|
|
{
|
|
this->type = WGL;
|
|
}
|
|
else if (header == "GLX")
|
|
{
|
|
this->type = GLX;
|
|
}
|
|
else
|
|
{
|
|
this->type = GL;
|
|
}
|
|
}
|
|
|
|
bool Extension::isExtension(char *line)
|
|
{
|
|
Tokenizer t(line);
|
|
|
|
if (t.GetNextToken() != "#ifndef") return false;
|
|
|
|
Tokenizer nameTokens(t.GetNextToken(), "_");
|
|
vtkstd::string header = nameTokens.GetNextToken();
|
|
if ((header == "GL") || (header == "WGL") || (header == "GLX"))
|
|
{
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
static Extension currentExtension;
|
|
|
|
class Constant {
|
|
public:
|
|
vtkstd::string name;
|
|
vtkstd::string value;
|
|
|
|
Constant(char *line);
|
|
static bool isConstant(char *line);
|
|
|
|
bool operator<(const Constant &obj) const { return this->name < obj.name; }
|
|
};
|
|
|
|
static vtkstd::map<vtkstd::string, vtkstd::string> EncounteredConstants;
|
|
|
|
Constant::Constant(char *line)
|
|
{
|
|
// Assumes isConstant is true.
|
|
Tokenizer t(line);
|
|
|
|
t.GetNextToken();
|
|
|
|
this->name = t.GetNextToken();
|
|
vtkstd::string fullname = this->name;
|
|
if (currentExtension.type == Extension::GL)
|
|
{
|
|
// Skip the "GL_"
|
|
this->name = this->name.substr(3);
|
|
}
|
|
else
|
|
{
|
|
// Skip the "GLX_" or "WGL_"
|
|
this->name = this->name.substr(4);
|
|
}
|
|
// Make sure name does not start with a numeric.
|
|
if ((this->name[0] >= '0') && (this->name[0] <= '9'))
|
|
{
|
|
this->name = '_' + this->name;
|
|
}
|
|
|
|
this->value = t.GetNextToken();
|
|
// Sometimes, one constant points to another. Handle this properly.
|
|
vtkstd::map<vtkstd::string, vtkstd::string>::iterator found
|
|
= EncounteredConstants.find(value);
|
|
if (found != EncounteredConstants.end())
|
|
{
|
|
this->value = found->second;
|
|
}
|
|
|
|
// Now record this as found.
|
|
EncounteredConstants[fullname] = this->value;
|
|
}
|
|
|
|
bool Constant::isConstant(char *line)
|
|
{
|
|
Tokenizer t(line);
|
|
|
|
if (t.GetNextToken() != "#define")
|
|
{
|
|
return false;
|
|
}
|
|
|
|
vtkstd::string n = t.GetNextToken();
|
|
if ( ( (currentExtension.type == Extension::GL)
|
|
&& (strncmp(n.c_str(), "GL_", 3) == 0) )
|
|
|| ( (currentExtension.type == Extension::WGL)
|
|
&& (strncmp(n.c_str(), "WGL_", 4) == 0) )
|
|
|| ( (currentExtension.type == Extension::GLX)
|
|
&& (strncmp(n.c_str(), "GLX_", 4) == 0) ) )
|
|
{
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
class Typedef {
|
|
public:
|
|
vtkstd::string definition;
|
|
|
|
Typedef(char *line);
|
|
static bool isTypedef(char *line);
|
|
|
|
bool operator<(const Typedef &obj) const { return this->definition < obj.definition; }
|
|
};
|
|
|
|
Typedef::Typedef(char *line)
|
|
{
|
|
// Assumes isTypedef is true.
|
|
this->definition = line;
|
|
}
|
|
|
|
bool Typedef::isTypedef(char *line)
|
|
{
|
|
Tokenizer t(line);
|
|
|
|
// Hack for some SGI stuff that declares a multiline struct.
|
|
if ( (t.GetNextToken() == "typedef")
|
|
&& ((t.GetNextToken() != "struct") || (t.GetNextToken() != "{")) )
|
|
{
|
|
return true;
|
|
}
|
|
|
|
// Hack for how some WIN32 things are declared.
|
|
if (strncmp(line, "DECLARE_HANDLE(", 15) == 0)
|
|
{
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
class Function {
|
|
public:
|
|
vtkstd::string returnType;
|
|
vtkstd::string entry;
|
|
vtkstd::string name;
|
|
vtkstd::string arguments;
|
|
int extensionType;
|
|
|
|
Function(char *line);
|
|
static bool isFunction(char *line);
|
|
const char *GetProcType();
|
|
|
|
bool operator<(const Function &obj) const { return this->name < obj.name; }
|
|
};
|
|
|
|
Function::Function(char *line) : extensionType(currentExtension.type)
|
|
{
|
|
// Assumes isFunction returns true.
|
|
|
|
Tokenizer t(line, " \n\t(");
|
|
|
|
t.GetNextToken();
|
|
vtkstd::string token = t.GetNextToken();
|
|
this->returnType = "";
|
|
while ((token == "const") || (token == "unsigned"))
|
|
{
|
|
this->returnType += token + " ";
|
|
token = t.GetNextToken();
|
|
}
|
|
this->returnType += token;
|
|
|
|
token = t.GetNextToken();
|
|
if (token == "*")
|
|
{
|
|
this->returnType += " *";
|
|
token = t.GetNextToken();
|
|
}
|
|
else if (token[0] == '*')
|
|
{
|
|
this->returnType += " *";
|
|
token = token.substr(1);
|
|
}
|
|
|
|
#ifdef DEBUG_PARSE
|
|
cerr << "Function return type: " << this->returnType << endl;
|
|
#endif
|
|
|
|
if (currentExtension.type == Extension::GL)
|
|
{
|
|
this->entry = "APIENTRY";
|
|
token = t.GetNextToken();
|
|
}
|
|
else if (currentExtension.type == Extension::WGL)
|
|
{
|
|
this->entry = "WINAPI";
|
|
token = t.GetNextToken();
|
|
}
|
|
else
|
|
{
|
|
this->entry = "";
|
|
}
|
|
|
|
#ifdef DEBUG_PARSE
|
|
cerr << "Function entry: " << this->entry << endl;
|
|
#endif
|
|
|
|
if (currentExtension.type == Extension::GL)
|
|
{
|
|
// Strip off "gl"
|
|
this->name = token.substr(2);
|
|
}
|
|
else
|
|
{
|
|
// Strip off "glX" or "wgl"
|
|
this->name = token.substr(3);
|
|
}
|
|
|
|
#ifdef DEBUG_PARSE
|
|
cerr << "Function name: " << this->name << endl;
|
|
#endif
|
|
|
|
this->arguments = t.GetRemainingString();
|
|
|
|
#ifdef DEBUG_PARSE
|
|
cerr << "Function arguments: " << this->arguments << endl;
|
|
#endif
|
|
}
|
|
|
|
bool Function::isFunction(char *line)
|
|
{
|
|
Tokenizer t(line);
|
|
|
|
vtkstd::string modifier = t.GetNextToken();
|
|
vtkstd::string sreturnType = t.GetNextToken();
|
|
if (sreturnType == "const")
|
|
{
|
|
// We don't really need the return type, just to skip over const.
|
|
sreturnType += " ";
|
|
sreturnType += t.GetNextToken();
|
|
}
|
|
|
|
vtkstd::string sentry = t.GetNextToken();
|
|
if (sentry == "*")
|
|
{
|
|
sreturnType += " *";
|
|
sentry = t.GetNextToken();
|
|
}
|
|
else if (sentry.size() && sentry[0] == '*')
|
|
{
|
|
sreturnType += " *";
|
|
sentry = sentry.substr(1);
|
|
}
|
|
|
|
return ( ( (currentExtension.type == Extension::GL)
|
|
&& (modifier == "GLAPI") && (sentry == "APIENTRY") )
|
|
|| ( (currentExtension.type == Extension::GL)
|
|
&& (modifier == "extern") && (sentry == "APIENTRY") )
|
|
|| ( (currentExtension.type == Extension::WGL)
|
|
&& (modifier == "extern") && (sentry == "WINAPI") )
|
|
|| ( (currentExtension.type == Extension::GLX)
|
|
&& (modifier == "extern") ) );
|
|
}
|
|
|
|
const char *Function::GetProcType()
|
|
{
|
|
static vtkstd::string proctype;
|
|
|
|
proctype = "PFN";
|
|
proctype += Extension::TypeToCapString(this->extensionType);
|
|
proctype += ToUpper(this->name);
|
|
proctype += "PROC";
|
|
|
|
return proctype.c_str();
|
|
}
|
|
|
|
static vtkstd::list<Extension> extensions;
|
|
static vtkstd::set<Extension> extensionset;
|
|
static vtkstd::map<Extension, vtkstd::list<Constant> > consts;
|
|
static vtkstd::map<Extension, vtkstd::list<Typedef> > types;
|
|
static vtkstd::map<Extension, vtkstd::list<Function> > functs;
|
|
|
|
static void ParseLine(char *line)
|
|
{
|
|
static bool inExtension = false;
|
|
static int ifLevel = 0;
|
|
|
|
Tokenizer tokens(line);
|
|
vtkstd::string firstToken = tokens.GetNextToken();
|
|
|
|
if (Extension::isExtension(line))
|
|
{
|
|
currentExtension = Extension(line);
|
|
#ifdef DEBUG_PARSE
|
|
cerr << "Recognized extension: " << line << endl;
|
|
#endif
|
|
|
|
// There are some exceptions to the extensions we support. This is
|
|
// because someone has placed some funky nonstandard stuff in the
|
|
// header files.
|
|
if ( (currentExtension.name == "GLX_SGIX_video_source")
|
|
|| (currentExtension.name == "GLX_SGIX_dmbuffer")
|
|
|| (currentExtension.name == "GLX_SGIX_hyperpipe") )
|
|
{
|
|
inExtension = false;
|
|
return;
|
|
}
|
|
|
|
// Only add extension to list if it is not already in it.
|
|
if (extensionset.find(currentExtension) == extensionset.end())
|
|
{
|
|
if (currentExtension.name == "GLX_ARB_get_proc_address")
|
|
{
|
|
// Special case where GLX_VERSION_1_4 depends on a typedef in
|
|
// GLX_ARB_get_proc_address, so we have to move the latter up.
|
|
extensions.push_front(currentExtension);
|
|
}
|
|
else
|
|
{
|
|
extensions.push_back(currentExtension);
|
|
}
|
|
extensionset.insert(currentExtension);
|
|
}
|
|
inExtension = true;
|
|
ifLevel = 0;
|
|
}
|
|
else if (inExtension)
|
|
{
|
|
if (strncmp(firstToken.c_str(), "#if", 3) == 0)
|
|
{
|
|
ifLevel++;
|
|
}
|
|
else if (firstToken == "#endif")
|
|
{
|
|
if (ifLevel == 0)
|
|
{
|
|
inExtension = false;
|
|
}
|
|
else
|
|
{
|
|
ifLevel--;
|
|
}
|
|
}
|
|
else if ( Constant::isConstant(line)
|
|
&& (strncmp(currentExtension.name.c_str(), (line+8),
|
|
currentExtension.name.length()) != 0) )
|
|
{
|
|
#ifdef DEBUG_PARSE
|
|
cerr << "Recognized constant: " << line << endl;
|
|
#endif
|
|
consts[currentExtension].push_back(line);
|
|
}
|
|
else if (Function::isFunction(line))
|
|
{
|
|
#ifdef DEBUG_PARSE
|
|
cerr << "Recognized function: " << line << endl;
|
|
#endif
|
|
functs[currentExtension].push_back(line);
|
|
}
|
|
else if (Typedef::isTypedef(line))
|
|
{
|
|
#ifdef DEBUG_PARSE
|
|
cerr << "Recognized typedef: " << line << endl;
|
|
#endif
|
|
types[currentExtension].push_back(line);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
#ifdef DEBUG_PARSE
|
|
cerr << "Unrecognized line: " << line << endl;
|
|
#endif
|
|
}
|
|
}
|
|
|
|
static void WriteHeader(ostream &file, const char *generator,
|
|
char **srcs, int num_srcs)
|
|
{
|
|
file << "// -*- c++ -*-" << endl << endl;
|
|
file << "//DO NOT EDIT!" << endl;
|
|
file << "//This file was created with " << generator << endl
|
|
<< "//from";
|
|
for (int i = 0; i < num_srcs; i++)
|
|
{
|
|
file << " " << srcs[i];
|
|
}
|
|
file << endl << endl;
|
|
file << "/*" << endl
|
|
<< " * Copyright 2003 Sandia Corporation." << endl
|
|
<< " * Under the terms of Contract DE-AC04-94AL85000, there is a non-exclusive" << endl
|
|
<< " * license for use of this work by or on behalf of the" << endl
|
|
<< " * U.S. Government. Redistribution and use in source and binary forms, with" << endl
|
|
<< " * or without modification, are permitted provided that this Notice and any" << endl
|
|
<< " * statement of authorship are reproduced on all copies." << endl
|
|
<< " */" << endl << endl;
|
|
}
|
|
|
|
static void WriteClassDeclarationGuts(ostream &hfile, int type)
|
|
{
|
|
for (vtkstd::list<Extension>::iterator iextension = extensions.begin();
|
|
iextension != extensions.end(); iextension++)
|
|
{
|
|
if (iextension->type != type) continue;
|
|
hfile << " //Definitions for " << iextension->name.c_str() << endl;
|
|
vtkstd::map<Extension, vtkstd::list<Constant> >::iterator cExts
|
|
= consts.find(*iextension);
|
|
if (cExts != consts.end())
|
|
{
|
|
hfile << " enum " << cExts->first.name.c_str() << "_consts {" << endl;
|
|
bool wroteFirst = false;
|
|
|
|
for (vtkstd::list<Constant>::iterator iconst = cExts->second.begin();
|
|
iconst != cExts->second.end(); iconst++)
|
|
{
|
|
|
|
// New versions of the NVIDIA OpenGL headers for Linux can
|
|
// #define the same constant with the same value in multiple
|
|
// sections. This utility will happily parse those and write
|
|
// out duplicate enums in different enum classes, which
|
|
// confuses the C++ preprocessor terribly. Don't write out a
|
|
// definition for an enum with a name/value pair that's
|
|
// already been used.
|
|
if ( ConstantsAlreadyWritten.find( vtkstd::make_pair( iconst->name,
|
|
iconst->value ) )
|
|
== ConstantsAlreadyWritten.end() )
|
|
{
|
|
if (wroteFirst)
|
|
{
|
|
hfile << "," << endl;
|
|
}
|
|
else
|
|
{
|
|
wroteFirst = true;
|
|
}
|
|
hfile << " " << iconst->name.c_str() << " = "
|
|
<< iconst->value.c_str();
|
|
|
|
ConstantsAlreadyWritten.insert( vtkstd::make_pair( iconst->name,
|
|
iconst->value ) );
|
|
|
|
}
|
|
else
|
|
{
|
|
hfile << "/* skipping duplicate " << iconst->name.c_str()
|
|
<< " = " << iconst->value.c_str() << " */" << endl;
|
|
}
|
|
}
|
|
hfile << endl << " };" << endl;
|
|
}
|
|
vtkstd::map<Extension, vtkstd::list<Typedef> >::iterator tExts
|
|
= types.find(*iextension);
|
|
if (tExts != types.end())
|
|
{
|
|
for (vtkstd::list<Typedef>::iterator itype = tExts->second.begin();
|
|
itype != tExts->second.end(); itype++)
|
|
{
|
|
hfile << " " << itype->definition.c_str() << endl;
|
|
}
|
|
}
|
|
vtkstd::map<Extension, vtkstd::list<Function> >::iterator fExts
|
|
= functs.find(*iextension);
|
|
if (fExts != functs.end())
|
|
{
|
|
for (vtkstd::list<Function>::iterator ifunc = fExts->second.begin();
|
|
ifunc != fExts->second.end(); ifunc++)
|
|
{
|
|
hfile << " extern VTK_RENDERING_EXPORT " << ifunc->GetProcType()
|
|
<< " " << ifunc->name.c_str() << ";" << endl;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
static void WriteFunctionPointerDeclarations(ostream &cxxfile, int type)
|
|
{
|
|
Extension::WriteSupportWrapperBegin(cxxfile, type);
|
|
for (vtkstd::map<Extension, vtkstd::list<Function> >::iterator fExts
|
|
= functs.begin();
|
|
fExts != functs.end(); fExts++)
|
|
{
|
|
if (fExts->first.type != type) continue;
|
|
cxxfile << "//Functions for " << fExts->first.name.c_str() << endl;
|
|
for (vtkstd::list<Function>::iterator ifunc = fExts->second.begin();
|
|
ifunc != fExts->second.end(); ifunc++)
|
|
{
|
|
cxxfile << "vtk" << Extension::TypeToString(type) << "::"
|
|
<< ifunc->GetProcType()
|
|
<< " vtk" << Extension::TypeToString(type) << "::"
|
|
<< ifunc->name.c_str() << " = NULL;" << endl;
|
|
}
|
|
}
|
|
Extension::WriteSupportWrapperEnd(cxxfile, type);
|
|
cxxfile << endl;
|
|
}
|
|
|
|
static void WriteCode(ostream &hfile, ostream &cxxfile)
|
|
{
|
|
// Write data for header file ---------------------------------
|
|
hfile << "#ifndef _vtkgl_h" << endl
|
|
<< "#define _vtkgl_h" << endl << endl;
|
|
hfile << "#include \"vtkToolkits.h\"" << endl;
|
|
hfile << "#include \"vtkSystemIncludes.h\"" << endl;
|
|
hfile << "#include \"vtkWindows.h\"" << endl;
|
|
hfile << "#include \"vtkOpenGL.h\"" << endl;
|
|
hfile << "#include <stddef.h>" << endl << endl;
|
|
hfile << "//#ifdef __APPLE__" << endl
|
|
<< "//#include <OpenGL/glu.h>" << endl
|
|
<< "//#else" << endl
|
|
<< "//#include <GL/glu.h>" << endl
|
|
<< "//#endif" << endl << endl;
|
|
hfile << "#ifdef VTK_USE_X" << endl
|
|
<< "#include <GL/glx.h>" << endl
|
|
<< "#endif" << endl << endl;
|
|
hfile << "class vtkOpenGLExtensionManager;" << endl << endl;
|
|
hfile << "#ifndef APIENTRY" << endl
|
|
<< "#define APIENTRY" << endl
|
|
<< "#define VTKGL_APIENTRY_DEFINED" << endl
|
|
<< "#endif" << endl << endl;
|
|
hfile << "#ifndef APIENTRYP" << endl
|
|
<< "#define APIENTRYP APIENTRY *" << endl
|
|
<< "#define VTKGL_APIENTRYP_DEFINED" << endl
|
|
<< "#endif" << endl << endl;
|
|
|
|
hfile << "/* Undefine all constants to avoid name conflicts. They should be defined */" << endl
|
|
<< "/* with GL_, GLX_, or WGL_ preprended to them anyway, but sometimes you run */" << endl
|
|
<< "/* into a header file that gets it wrong. */" << endl;
|
|
for (vtkstd::map<Extension, vtkstd::list<Constant> >::iterator constlist
|
|
= consts.begin();
|
|
constlist != consts.end(); constlist++)
|
|
{
|
|
for (vtkstd::list<Constant>::iterator c = (*constlist).second.begin();
|
|
c != (*constlist).second.end(); c++)
|
|
{
|
|
hfile << "#ifdef " << (*c).name.c_str() << endl;
|
|
hfile << "#undef " << (*c).name.c_str() << endl;
|
|
hfile << "#endif" << endl;
|
|
}
|
|
}
|
|
|
|
Extension::WriteSupportWrapperBegin(hfile, Extension::GL);
|
|
hfile << endl << "namespace vtkgl {" << endl;
|
|
ConstantsAlreadyWritten.clear();
|
|
WriteClassDeclarationGuts(hfile, Extension::GL);
|
|
hfile << endl << " // Method to load functions for a particular extension.";
|
|
hfile << endl << " int LoadExtension(const char *name, "
|
|
<< "vtkOpenGLExtensionManager *manager);" << endl;
|
|
hfile << endl << " // Strings containing special version extensions.";
|
|
hfile << endl << " const char *GLVersionExtensionsString();" << endl;
|
|
hfile << endl << " const char *GLXVersionExtensionsString();" << endl;
|
|
hfile << "}" << endl;
|
|
Extension::WriteSupportWrapperEnd(hfile, Extension::GL);
|
|
|
|
Extension::WriteSupportWrapperBegin(hfile, Extension::GLX);
|
|
hfile << "namespace vtkglX {" << endl;
|
|
// glxext.h is not written very well. Add some typedefs that may not
|
|
// be defined.
|
|
hfile << " //Miscellaneous definitions." << endl;
|
|
hfile << " typedef XID GLXContextID;" << endl;
|
|
hfile << " typedef XID GLXPbuffer;" << endl;
|
|
hfile << " typedef XID GLXWindow;" << endl;
|
|
hfile << " typedef XID GLXFBConfigID;" << endl;
|
|
hfile << " typedef struct __GLXFBConfigRec *GLXFBConfig;" << endl;
|
|
hfile << " typedef int int32_t;" << endl;
|
|
hfile << " typedef long long int64_t;" << endl;
|
|
ConstantsAlreadyWritten.clear();
|
|
WriteClassDeclarationGuts(hfile, Extension::GLX);
|
|
hfile << "}" << endl;
|
|
Extension::WriteSupportWrapperEnd(hfile, Extension::GLX);
|
|
|
|
Extension::WriteSupportWrapperBegin(hfile, Extension::WGL);
|
|
hfile << "namespace vtkwgl {" << endl;
|
|
ConstantsAlreadyWritten.clear();
|
|
WriteClassDeclarationGuts(hfile, Extension::WGL);
|
|
hfile << "}" << endl;
|
|
Extension::WriteSupportWrapperEnd(hfile, Extension::WGL);
|
|
|
|
hfile << endl
|
|
<< "#ifdef VTKGL_APIENTRY_DEFINED" << endl
|
|
<< "#undef APIENTRY" << endl
|
|
<< "#endif" << endl << endl;
|
|
hfile << "#ifdef VTKGL_APIENTRYP_DEFINED" << endl
|
|
<< "#undef APIENTRYP" << endl
|
|
<< "#endif" << endl << endl;
|
|
hfile << "#endif //_vtkgl_h" << endl;
|
|
|
|
// Write data for C++ file --------------------------------------------
|
|
cxxfile << "#include \"vtkgl.h\"" << endl;
|
|
cxxfile << "#include \"vtkOpenGLExtensionManager.h\"" << endl << endl;
|
|
|
|
// Write function pointer declarations.
|
|
WriteFunctionPointerDeclarations(cxxfile, Extension::GL);
|
|
WriteFunctionPointerDeclarations(cxxfile, Extension::GLX);
|
|
WriteFunctionPointerDeclarations(cxxfile, Extension::WGL);
|
|
|
|
vtkstd::list<Extension>::iterator iextension;
|
|
|
|
// Write function to load function pointers.
|
|
cxxfile << "int vtkgl::LoadExtension(const char *name, vtkOpenGLExtensionManager *manager)" << endl
|
|
<< "{" << endl;
|
|
for (iextension = extensions.begin();
|
|
iextension != extensions.end(); iextension++)
|
|
{
|
|
iextension->WriteSupportWrapperBegin(cxxfile);
|
|
cxxfile << " if (strcmp(name, \"" << iextension->name.c_str()
|
|
<< "\") == 0)" << endl
|
|
<< " {" << endl;
|
|
vtkstd::string vtkglclass = "vtk";
|
|
vtkglclass += Extension::TypeToString(iextension->type);
|
|
vtkstd::list<Function>::iterator ifunct;
|
|
for (ifunct = functs[*iextension].begin();
|
|
ifunct != functs[*iextension].end(); ifunct++)
|
|
{
|
|
cxxfile << " " << vtkglclass.c_str() << "::"
|
|
<< ifunct->name.c_str() << " = (" << vtkglclass.c_str() << "::"
|
|
<< ifunct->GetProcType()
|
|
<< ")manager->GetProcAddress(\""
|
|
<< Extension::TypeToString(iextension->type)
|
|
<< ifunct->name.c_str() << "\");" << endl;
|
|
}
|
|
cxxfile << " return 1";
|
|
for (ifunct = functs[*iextension].begin();
|
|
ifunct != functs[*iextension].end(); ifunct++)
|
|
{
|
|
cxxfile << " && (" << vtkglclass.c_str() << "::" << ifunct->name.c_str()
|
|
<< " != NULL)";
|
|
}
|
|
cxxfile << ";" << endl;
|
|
cxxfile << " }" << endl;
|
|
iextension->WriteSupportWrapperEnd(cxxfile);
|
|
}
|
|
cxxfile << " vtkGenericWarningMacro(<< \"Nothing known about extension \" << name" << endl
|
|
<< " << \". vtkgl may need to be updated.\");" << endl;
|
|
cxxfile << " return 0;" << endl
|
|
<< "}" << endl;
|
|
|
|
// Write functions to report special version extension strings.
|
|
cxxfile << endl << "const char *vtkgl::GLVersionExtensionsString()" << endl
|
|
<< "{" << endl
|
|
<< " return \"";
|
|
for (iextension = extensions.begin();
|
|
iextension != extensions.end(); iextension++)
|
|
{
|
|
if (strncmp("GL_VERSION_", iextension->name.c_str(), 11) == 0)
|
|
{
|
|
cxxfile << iextension->name.c_str() << " ";
|
|
}
|
|
}
|
|
cxxfile << "\";" << endl
|
|
<< "}" << endl;
|
|
|
|
cxxfile << endl << "const char *vtkgl::GLXVersionExtensionsString()" << endl
|
|
<< "{" << endl
|
|
<< " return \"";
|
|
for (iextension = extensions.begin();
|
|
iextension != extensions.end(); iextension++)
|
|
{
|
|
if (strncmp("GLX_VERSION_", iextension->name.c_str(), 12) == 0)
|
|
{
|
|
cxxfile << iextension->name.c_str() << " ";
|
|
}
|
|
}
|
|
cxxfile << "\";" << endl
|
|
<< "}" << endl;
|
|
}
|
|
|
|
int main(int argc, char **argv)
|
|
{
|
|
if (argc < 3)
|
|
{
|
|
cerr << "USAGE: " << argv[0] << "<output dir> <header files>" << endl;
|
|
return 1;
|
|
}
|
|
|
|
vtkstd::string outputDir = argv[1];
|
|
|
|
for (int i = 2; i < argc; i++)
|
|
{
|
|
#ifdef DEBUG_PARSE
|
|
cerr << "*** Parsing declarations from file " << argv[i] << endl;
|
|
#endif
|
|
ifstream file(argv[i]);
|
|
if (!file)
|
|
{
|
|
cerr << "Could not open " << argv[i] << endl;
|
|
return 2;
|
|
}
|
|
|
|
while (!file.eof())
|
|
{
|
|
static char buf[4096]; // What are the odds of needing more?
|
|
file.getline(buf, 4096);
|
|
ParseLine(buf);
|
|
}
|
|
file.close();
|
|
}
|
|
|
|
ofstream hfile((outputDir + "/vtkgl.h").c_str());
|
|
WriteHeader(hfile, argv[0], argv+1, argc-1);
|
|
ofstream cxxfile((outputDir + "/vtkgl.cxx").c_str());
|
|
WriteHeader(cxxfile, argv[0], argv+1, argc-1);
|
|
|
|
WriteCode(hfile, cxxfile);
|
|
|
|
hfile.close();
|
|
cxxfile.close();
|
|
|
|
return 0;
|
|
}
|
|
|