Source

GL Profile Suite / caps / GenCaps.lua

Full commit

local caps = require "CapsList"

local function RepSep(str, count, sep)
	local value = "";
	for i = 1, count do
		if(i ~= 1) then value = value .. sep; end
		value = value .. str;
	end
	
	return value;
end

local function WritePreamble(hFile)
	hFile:write(
[[
#include <exception>
#include <stdio.h>
#include <glload/gll.h>
#include <glload/gl_all.h>

void ShowCaps()
{
	int integers[32];
	float floats[32];

]]
	);
end

local function WritePostscript(hFile)
	hFile:write(
[[

}
]]
	);
end

local function WriteBasicData(hFile)
	local strings =
	{
		"GL_VENDOR",
		"GL_RENDERER",
		"GL_VERSION",
		"GL_SHADING_LANGUAGE_VERSION",
	}
	
	hFile:write("printf(\"== Implementation Information ==\\n\\n\");\n");
	
	for i, theString in ipairs(strings) do
		hFile:write("printf(\"* ", theString);
		hFile:write([[: %s\n", (const char *)glGetString(]]);
		hFile:write(theString, "));\n");
	end
end

--Components:
-- 1: The printf format
-- 2: The OpenGL base call to get this type.
-- 3: The variable, defined above, to fill with this call.
-- 4: The base C++ type for this value.
local typeData =
{
	int = {"%i", "glGetIntegerv", "integers", "GLint"},
	hex = {"%08x", "glGetIntegerv", "integers", "GLint"},
	float = {"%f", "glGetFloatv", "floats", "GLfloat"},
}

local function TabManager()
	local tm = { tabs = "", tabcnt = 0 }
	
	function tm:Enter()
		self.tabcnt = self.tabcnt + 1
		self.tabs = string.rep("\t", self.tabcnt);
		return self;
	end

	function tm:Exit()
		self.tabcnt = self.tabcnt - 1
		self.tabs = string.rep("\t", self.tabcnt);
		return self;
	end
	
	local tmMeta =
	{
		__call = function(tm) return tm.tabs end
	}
	
	setmetatable(tm, tmMeta);
	return tm;
end

local function PrintLimitNamed(hFile, limit, t)
	local numComponents = limit.numcomps or 1;
	local typeInfo = typeData[limit.type];
	
	if(limit.version or limit.ext) then
		hFile:write(t(), "if(")
		if(limit.version) then
			local major, minor = limit.version:match("(%d+)%.(%d+)");
			hFile:write(string.format("IsVersionGEQ(%i, %i)", major, minor))
		end
		if(limit.ext) then
			if(limit.version) then
				hFile:write(" || ")
			end
			if(type(limit.ext) == "table") then
				for i, ext in ipairs(limit.ext) do
					hFile:write("glext_", ext)
					if(i ~= #limit.ext) then
						hFile:write(" || ")
					end
				end
			else
				hFile:write("glext_", limit.ext)
			end
		end
		hFile:write(")\n")
		hFile:write(t(), "{\n");
		t:Enter()
	end
	
	if(type(numComponents) == "string") then
		if(not(limit.version or limit.ext)) then
			hFile:write(t, "{\n")
			t:Enter()
		end
		hFile:write(t(), "GLint iCount = 0;\n");
		hFile:write(t(), "glGetIntegerv(", numComponents, ", &iCount);\n");
		hFile:write(t(), "if(iCount)\n")
		hFile:write(t(), "{\n")
		t:Enter()		
		hFile:write(t(), typeInfo[4],  "*pData = new ", typeInfo[4], "[iCount];\n")
		hFile:write(t(), typeInfo[2], string.format("(%s, pData);\n", limit.name));
		hFile:write(t(), "if(glGetError() == GL_NO_ERROR)\n");
		hFile:write(t(), "{\n");
		t:Enter()
		hFile:write(t(), "printf(\"* ", limit.desc, "(%i): \", iCount);\n");
		hFile:write(t(), "for(int iLoop = 0; iLoop < iCount; iLoop++)\n");
		hFile:write(t(), "{\n");
		t:Enter()
		hFile:write(t(), "printf(\"", typeInfo[1], "\", pData[iLoop]);\n");
		hFile:write(t(), "if(iLoop != iCount - 1)\n\t\t\t\t\tprintf(\", \");\n")
		t:Exit()
		hFile:write(t(), "}\n")
		hFile:write(t(), "printf(\"\\n\");\n");
		t:Exit()
		hFile:write(t(), "}\n");
		hFile:write(t(), "delete[] pData;\n")
		t:Exit()
		hFile:write(t(), "}\n")
		if(not(limit.version or limit.ext)) then
			t:Exit()
			hFile:write(t(), "}\n");
		end
	else
		hFile:write(t(), typeInfo[2], string.format("(%s, %s);\n", limit.name, typeInfo[3]));

		hFile:write(t(), "if(glGetError() == GL_NO_ERROR)\n");
		t:Enter()
		hFile:write(t(), "printf(\"* ", limit.desc, ": ");
		hFile:write(RepSep(typeInfo[1], numComponents, ", "));
		hFile:write("\\n\", ");
		for k = 1, numComponents do
			hFile:write(typeInfo[3], "[", k - 1, "]");
			if(k ~= numComponents) then hFile:write(", "); end
		end
		hFile:write(");\n");
		t:Exit()
	end

	if(limit.version or limit.ext) then
		t:Exit()
		hFile:write(t(), "}\n");
	end
end

local function WriteNumericLimits(hFile, t)
	hFile:write(t(), "printf(\"== Numeric Limits ==\\n\\n\");\n");
	
	local limits = caps.limits
	
	for i, cat in ipairs(limits) do
		hFile:write(t(), "printf(\"=== ", cat.cat, " ===\\n\\n\");\n");
		
		for j, limit in ipairs(cat) do
			PrintLimitNamed(hFile, limit, t)
		end
		
		hFile:write(t(), [[printf("\n\n");]], "\n\n");
	end
	
end

local hFile = assert(io.open("caps.cpp", "w"), "Could not open file.");

WritePreamble(hFile);
local t = TabManager();
t:Enter();

WriteBasicData(hFile, t);
hFile:write("\n\n");

WriteNumericLimits(hFile, t);
hFile:write("\n\n");
t:Exit()

WritePostscript(hFile);

hFile:close();