Beispiel #1
0
std::vector<CScriptValRooted> SavedGames::GetSavedGames(ScriptInterface& scriptInterface)
{
	TIMER(L"GetSavedGames");

	std::vector<CScriptValRooted> games;

	Status err;

	VfsPaths pathnames;
	err = vfs::GetPathnames(g_VFS, "saves/", L"*.0adsave", pathnames);
	WARN_IF_ERR(err);

	for (size_t i = 0; i < pathnames.size(); ++i)
	{
		OsPath realPath;
		err = g_VFS->GetRealPath(pathnames[i], realPath);
		if (err < 0)
		{
			DEBUG_WARN_ERR(err);
			continue; // skip this file
		}

		PIArchiveReader archiveReader = CreateArchiveReader_Zip(realPath);
		if (!archiveReader)
		{
			// Triggered by e.g. the file being open in another program
			LOGWARNING(L"Failed to read saved game '%ls'", realPath.string().c_str());
			continue; // skip this file
		}

		CScriptValRooted metadata;
		CGameLoader loader(scriptInterface, &metadata, NULL);
		err = archiveReader->ReadEntries(CGameLoader::ReadEntryCallback, (uintptr_t)&loader);
		if (err < 0)
		{
			DEBUG_WARN_ERR(err);
			continue; // skip this file
		}

		CScriptValRooted game;
		scriptInterface.Eval("({})", game);
		scriptInterface.SetProperty(game.get(), "id", pathnames[i].Basename());
		scriptInterface.SetProperty(game.get(), "metadata", metadata);
		games.push_back(game);
	}

	return games;
}
Beispiel #2
0
/**
 * Handle requests from the GUI for the list of players.
 *
 * @return A JS array containing all known players and their presences
 */
CScriptValRooted XmppClient::GUIGetPlayerList(ScriptInterface& scriptInterface)
{
	std::string presence;
	CScriptValRooted playerList;
	scriptInterface.Eval("({})", playerList);
	for(std::map<std::string, gloox::Presence::PresenceType>::const_iterator it = m_PlayerMap.begin(); it != m_PlayerMap.end(); ++it)
	{
		CScriptValRooted player;
		GetPresenceString(it->second, presence);
		scriptInterface.Eval("({})", player);
		scriptInterface.SetProperty(player.get(), "name", wstring_from_utf8(it->first));
		scriptInterface.SetProperty(player.get(), "presence", wstring_from_utf8(presence));

		scriptInterface.SetProperty(playerList.get(), wstring_from_utf8(it->first).c_str(), player);
	}

	return playerList;
}
Beispiel #3
0
/**
 * Handle requests from the GUI for the list of players.
 *
 * @return A JS array containing all known players and their presences
 */
CScriptValRooted XmppClient::GUIGetPlayerList(ScriptInterface& scriptInterface)
{
	CScriptValRooted playerList;
	scriptInterface.Eval("([])", playerList);

	// Convert the internal data structure to a Javascript object.
	for (std::map<std::string, std::vector<std::string> >::const_iterator it = m_PlayerMap.begin(); it != m_PlayerMap.end(); ++it)
	{
		CScriptValRooted player;
		scriptInterface.Eval("({})", player);
		scriptInterface.SetProperty(player.get(), "name", wstring_from_utf8(it->first));
		scriptInterface.SetProperty(player.get(), "presence", wstring_from_utf8(it->second[0]));
		scriptInterface.SetProperty(player.get(), "rating", wstring_from_utf8(it->second[1]));
		scriptInterface.SetProperty(player.get(), "role", wstring_from_utf8(it->second[2]));
		scriptInterface.CallFunctionVoid(playerList.get(), "push", player);
	}

	return playerList;
}
Beispiel #4
0
CScriptVal ConvertTLBs(ScriptInterface& scriptInterface)
{
	CScriptVal ret;
	scriptInterface.Eval("[]", ret);
	for(size_t i = 0; ; i++)
	{
		const x86_x64::Cache* ptlb = x86_x64::Caches(x86_x64::TLB+i);
		if (!ptlb)
			break;
		CScriptVal tlb;
		scriptInterface.Eval("({})", tlb);
		scriptInterface.SetProperty(tlb.get(), "type", (u32)ptlb->type);
		scriptInterface.SetProperty(tlb.get(), "level", (u32)ptlb->level);
		scriptInterface.SetProperty(tlb.get(), "associativity", (u32)ptlb->associativity);
		scriptInterface.SetProperty(tlb.get(), "pagesize", (u32)ptlb->entrySize);
		scriptInterface.SetProperty(tlb.get(), "entries", (u32)ptlb->numEntries);
		scriptInterface.SetPropertyInt(ret.get(), i, tlb);
	}
	return ret;
}
Beispiel #5
0
void ConvertTLBs(ScriptInterface& scriptInterface, JS::MutableHandleValue ret)
{
	JSContext* cx = scriptInterface.GetContext();
	JSAutoRequest rq(cx);
	
	scriptInterface.Eval("[]", ret);
	for(size_t i = 0; ; i++)
	{
		const x86_x64::Cache* ptlb = x86_x64::Caches(x86_x64::TLB+i);
		if (!ptlb)
			break;
		JS::RootedValue tlb(cx);
		scriptInterface.Eval("({})", &tlb);
		scriptInterface.SetProperty(tlb, "type", (u32)ptlb->type);
		scriptInterface.SetProperty(tlb, "level", (u32)ptlb->level);
		scriptInterface.SetProperty(tlb, "associativity", (u32)ptlb->associativity);
		scriptInterface.SetProperty(tlb, "pagesize", (u32)ptlb->entrySize);
		scriptInterface.SetProperty(tlb, "entries", (u32)ptlb->numEntries);
		scriptInterface.SetPropertyInt(ret, i, tlb);
	}
}
Beispiel #6
0
/**
 * Handle requests from the GUI for leaderboard data.
 *
 * @return A JS array containing all known leaderboard data
 */
CScriptValRooted XmppClient::GUIGetBoardList(ScriptInterface& scriptInterface)
{
	CScriptValRooted boardList;
	scriptInterface.Eval("([])", boardList);
	for(std::vector<const glooxwrapper::Tag*>::const_iterator it = m_BoardList.begin(); it != m_BoardList.end(); ++it)
	{
		CScriptValRooted board;
		scriptInterface.Eval("({})", board);

		const char* attributes[] = { "name", "rank", "rating" };
		short attributes_length = 3;
		for (short i = 0; i < attributes_length; i++)
			scriptInterface.SetProperty(board.get(), attributes[i], wstring_from_utf8((*it)->findAttribute(attributes[i]).to_string()));

		scriptInterface.CallFunctionVoid(boardList.get(), "push", board);
	}

	return boardList;
}
Beispiel #7
0
/**
 * Handle requests from the GUI for the list of all active games.
 *
 * @return A JS array containing all known games
 */
CScriptValRooted XmppClient::GUIGetGameList(ScriptInterface& scriptInterface)
{
	CScriptValRooted gameList;
	scriptInterface.Eval("([])", gameList);
	for(std::vector<const glooxwrapper::Tag*>::const_iterator it = m_GameList.begin(); it != m_GameList.end(); ++it)
	{
		CScriptValRooted game;
		scriptInterface.Eval("({})", game);

		const char* stats[] = { "name", "ip", "state", "nbp", "tnbp", "players", "mapName", "niceMapName", "mapSize", "mapType", "victoryCondition" };
		short stats_length = 11;
		for (short i = 0; i < stats_length; i++)
			scriptInterface.SetProperty(game.get(), stats[i], wstring_from_utf8((*it)->findAttribute(stats[i]).to_string()));

		scriptInterface.CallFunctionVoid(gameList.get(), "push", game);
	}

	return gameList;
}
Beispiel #8
0
CScriptVal ConvertCaches(ScriptInterface& scriptInterface, x86_x64::IdxCache idxCache)
{
	CScriptVal ret;
	scriptInterface.Eval("[]", ret);
	for (size_t idxLevel = 0; idxLevel < x86_x64::Cache::maxLevels; ++idxLevel)
	{
		const x86_x64::Cache* pcache = x86_x64::Caches(idxCache+idxLevel);
		if (pcache->type == x86_x64::Cache::kNull || pcache->numEntries == 0)
			continue;
		CScriptVal cache;
		scriptInterface.Eval("({})", cache);
		scriptInterface.SetProperty(cache.get(), "type", (u32)pcache->type);
		scriptInterface.SetProperty(cache.get(), "level", (u32)pcache->level);
		scriptInterface.SetProperty(cache.get(), "associativity", (u32)pcache->associativity);
		scriptInterface.SetProperty(cache.get(), "linesize", (u32)pcache->entrySize);
		scriptInterface.SetProperty(cache.get(), "sharedby", (u32)pcache->sharedBy);
		scriptInterface.SetProperty(cache.get(), "totalsize", (u32)pcache->TotalSize());
		scriptInterface.SetPropertyInt(ret.get(), idxLevel, cache);
	}
	return ret;
}
Beispiel #9
0
void ConvertCaches(ScriptInterface& scriptInterface, x86_x64::IdxCache idxCache, JS::MutableHandleValue ret)
{
	JSContext* cx = scriptInterface.GetContext();
	JSAutoRequest rq(cx);
	
	scriptInterface.Eval("[]", ret);
	for (size_t idxLevel = 0; idxLevel < x86_x64::Cache::maxLevels; ++idxLevel)
	{
		const x86_x64::Cache* pcache = x86_x64::Caches(idxCache+idxLevel);
		if (pcache->type == x86_x64::Cache::kNull || pcache->numEntries == 0)
			continue;
		JS::RootedValue cache(cx);
		scriptInterface.Eval("({})", &cache);
		scriptInterface.SetProperty(cache, "type", (u32)pcache->type);
		scriptInterface.SetProperty(cache, "level", (u32)pcache->level);
		scriptInterface.SetProperty(cache, "associativity", (u32)pcache->associativity);
		scriptInterface.SetProperty(cache, "linesize", (u32)pcache->entrySize);
		scriptInterface.SetProperty(cache, "sharedby", (u32)pcache->sharedBy);
		scriptInterface.SetProperty(cache, "totalsize", (u32)pcache->TotalSize());
		scriptInterface.SetPropertyInt(ret, idxLevel, cache);
	}
}
Beispiel #10
0
/**
 * Send GUI message queue when queried.
 */
CScriptValRooted XmppClient::GuiPollMessage(ScriptInterface& scriptInterface)
{
	if (m_GuiMessageQueue.empty())
		return CScriptValRooted();

	GUIMessage message = m_GuiMessageQueue.front();
	CScriptValRooted messageVal;

	scriptInterface.Eval("({})", messageVal);
	scriptInterface.SetProperty(messageVal.get(), "type", message.type);
	if (!message.from.empty())
		scriptInterface.SetProperty(messageVal.get(), "from", message.from);
	if (!message.text.empty())
		scriptInterface.SetProperty(messageVal.get(), "text", message.text);
	if (!message.level.empty())
		scriptInterface.SetProperty(messageVal.get(), "level", message.level);
	if (!message.message.empty())
		scriptInterface.SetProperty(messageVal.get(), "message", message.message);
	if (!message.data.empty())
		scriptInterface.SetProperty(messageVal.get(), "data", message.data);
	
	m_GuiMessageQueue.pop_front();
	return messageVal;
}
Beispiel #11
0
static void ReportGLLimits(ScriptInterface& scriptInterface, JS::HandleValue settings)
{
	const char* errstr = "(error)";

#define INTEGER(id) do { \
	GLint i = -1; \
	glGetIntegerv(GL_##id, &i); \
	if (ogl_SquelchError(GL_INVALID_ENUM)) \
		scriptInterface.SetProperty(settings, "GL_" #id, errstr); \
	else \
		scriptInterface.SetProperty(settings, "GL_" #id, i); \
	} while (false)

#define INTEGER2(id) do { \
	GLint i[2] = { -1, -1 }; \
	glGetIntegerv(GL_##id, i); \
	if (ogl_SquelchError(GL_INVALID_ENUM)) { \
		scriptInterface.SetProperty(settings, "GL_" #id "[0]", errstr); \
		scriptInterface.SetProperty(settings, "GL_" #id "[1]", errstr); \
	} else { \
		scriptInterface.SetProperty(settings, "GL_" #id "[0]", i[0]); \
		scriptInterface.SetProperty(settings, "GL_" #id "[1]", i[1]); \
	} \
	} while (false)

#define FLOAT(id) do { \
	GLfloat f = std::numeric_limits<GLfloat>::quiet_NaN(); \
	glGetFloatv(GL_##id, &f); \
	if (ogl_SquelchError(GL_INVALID_ENUM)) \
		scriptInterface.SetProperty(settings, "GL_" #id, errstr); \
	else \
		scriptInterface.SetProperty(settings, "GL_" #id, f); \
	} while (false)

#define FLOAT2(id) do { \
	GLfloat f[2] = { std::numeric_limits<GLfloat>::quiet_NaN(), std::numeric_limits<GLfloat>::quiet_NaN() }; \
	glGetFloatv(GL_##id, f); \
	if (ogl_SquelchError(GL_INVALID_ENUM)) { \
		scriptInterface.SetProperty(settings, "GL_" #id "[0]", errstr); \
		scriptInterface.SetProperty(settings, "GL_" #id "[1]", errstr); \
	} else { \
		scriptInterface.SetProperty(settings, "GL_" #id "[0]", f[0]); \
		scriptInterface.SetProperty(settings, "GL_" #id "[1]", f[1]); \
	} \
	} while (false)

#define STRING(id) do { \
	const char* c = (const char*)glGetString(GL_##id); \
	if (!c) c = ""; \
	if (ogl_SquelchError(GL_INVALID_ENUM)) c = errstr; \
	scriptInterface.SetProperty(settings, "GL_" #id, std::string(c)); \
	}  while (false)

#define QUERY(target, pname) do { \
	GLint i = -1; \
	pglGetQueryivARB(GL_##target, GL_##pname, &i); \
	if (ogl_SquelchError(GL_INVALID_ENUM)) \
		scriptInterface.SetProperty(settings, "GL_" #target ".GL_" #pname, errstr); \
	else \
		scriptInterface.SetProperty(settings, "GL_" #target ".GL_" #pname, i); \
	} while (false)

#define VERTEXPROGRAM(id) do { \
	GLint i = -1; \
	pglGetProgramivARB(GL_VERTEX_PROGRAM_ARB, GL_##id, &i); \
	if (ogl_SquelchError(GL_INVALID_ENUM)) \
		scriptInterface.SetProperty(settings, "GL_VERTEX_PROGRAM_ARB.GL_" #id, errstr); \
	else \
		scriptInterface.SetProperty(settings, "GL_VERTEX_PROGRAM_ARB.GL_" #id, i); \
	} while (false)

#define FRAGMENTPROGRAM(id) do { \
	GLint i = -1; \
	pglGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB, GL_##id, &i); \
	if (ogl_SquelchError(GL_INVALID_ENUM)) \
		scriptInterface.SetProperty(settings, "GL_FRAGMENT_PROGRAM_ARB.GL_" #id, errstr); \
	else \
		scriptInterface.SetProperty(settings, "GL_FRAGMENT_PROGRAM_ARB.GL_" #id, i); \
	} while (false)

#define BOOL(id) INTEGER(id)

	ogl_WarnIfError();

	// Core OpenGL 1.3:
	// (We don't bother checking extension strings for anything older than 1.3;
	// it'll just produce harmless warnings)
	STRING(VERSION);
	STRING(VENDOR);
	STRING(RENDERER);
	STRING(EXTENSIONS);
#if !CONFIG2_GLES
	INTEGER(MAX_LIGHTS);
	INTEGER(MAX_CLIP_PLANES);
	// Skip MAX_COLOR_MATRIX_STACK_DEPTH (only in imaging subset)
	INTEGER(MAX_MODELVIEW_STACK_DEPTH);
	INTEGER(MAX_PROJECTION_STACK_DEPTH);
	INTEGER(MAX_TEXTURE_STACK_DEPTH);
#endif
	INTEGER(SUBPIXEL_BITS);
#if !CONFIG2_GLES
	INTEGER(MAX_3D_TEXTURE_SIZE);
#endif
	INTEGER(MAX_TEXTURE_SIZE);
	INTEGER(MAX_CUBE_MAP_TEXTURE_SIZE);
#if !CONFIG2_GLES
	INTEGER(MAX_PIXEL_MAP_TABLE);
	INTEGER(MAX_NAME_STACK_DEPTH);
	INTEGER(MAX_LIST_NESTING);
	INTEGER(MAX_EVAL_ORDER);
#endif
	INTEGER2(MAX_VIEWPORT_DIMS);
#if !CONFIG2_GLES
	INTEGER(MAX_ATTRIB_STACK_DEPTH);
	INTEGER(MAX_CLIENT_ATTRIB_STACK_DEPTH);
	INTEGER(AUX_BUFFERS);
	BOOL(RGBA_MODE);
	BOOL(INDEX_MODE);
	BOOL(DOUBLEBUFFER);
	BOOL(STEREO);
#endif
	FLOAT2(ALIASED_POINT_SIZE_RANGE);
#if !CONFIG2_GLES
	FLOAT2(SMOOTH_POINT_SIZE_RANGE);
	FLOAT(SMOOTH_POINT_SIZE_GRANULARITY);
#endif
	FLOAT2(ALIASED_LINE_WIDTH_RANGE);
#if !CONFIG2_GLES
	FLOAT2(SMOOTH_LINE_WIDTH_RANGE);
	FLOAT(SMOOTH_LINE_WIDTH_GRANULARITY);
	// Skip MAX_CONVOLUTION_WIDTH, MAX_CONVOLUTION_HEIGHT (only in imaging subset)
	INTEGER(MAX_ELEMENTS_INDICES);
	INTEGER(MAX_ELEMENTS_VERTICES);
	INTEGER(MAX_TEXTURE_UNITS);
#endif
	INTEGER(SAMPLE_BUFFERS);
	INTEGER(SAMPLES);
	// TODO: compressed texture formats
	INTEGER(RED_BITS);
	INTEGER(GREEN_BITS);
	INTEGER(BLUE_BITS);
	INTEGER(ALPHA_BITS);
#if !CONFIG2_GLES
	INTEGER(INDEX_BITS);
#endif
	INTEGER(DEPTH_BITS);
	INTEGER(STENCIL_BITS);
#if !CONFIG2_GLES
	INTEGER(ACCUM_RED_BITS);
	INTEGER(ACCUM_GREEN_BITS);
	INTEGER(ACCUM_BLUE_BITS);
	INTEGER(ACCUM_ALPHA_BITS);
#endif

#if !CONFIG2_GLES

	// Core OpenGL 2.0 (treated as extensions):

	if (ogl_HaveExtension("GL_EXT_texture_lod_bias"))
	{
		FLOAT(MAX_TEXTURE_LOD_BIAS_EXT);
	}

	if (ogl_HaveExtension("GL_ARB_occlusion_query"))
	{
		QUERY(SAMPLES_PASSED, QUERY_COUNTER_BITS);
	}

	if (ogl_HaveExtension("GL_ARB_shading_language_100"))
	{
		STRING(SHADING_LANGUAGE_VERSION_ARB);
	}

	if (ogl_HaveExtension("GL_ARB_vertex_shader"))
	{
		INTEGER(MAX_VERTEX_ATTRIBS_ARB);
		INTEGER(MAX_VERTEX_UNIFORM_COMPONENTS_ARB);
		INTEGER(MAX_VARYING_FLOATS_ARB);
		INTEGER(MAX_COMBINED_TEXTURE_IMAGE_UNITS_ARB);
		INTEGER(MAX_VERTEX_TEXTURE_IMAGE_UNITS_ARB);
	}

	if (ogl_HaveExtension("GL_ARB_fragment_shader"))
	{
		INTEGER(MAX_FRAGMENT_UNIFORM_COMPONENTS_ARB);
	}

	if (ogl_HaveExtension("GL_ARB_vertex_shader") || ogl_HaveExtension("GL_ARB_fragment_shader") ||
		ogl_HaveExtension("GL_ARB_vertex_program") || ogl_HaveExtension("GL_ARB_fragment_program"))
	{
		INTEGER(MAX_TEXTURE_IMAGE_UNITS_ARB);
		INTEGER(MAX_TEXTURE_COORDS_ARB);
	}

	if (ogl_HaveExtension("GL_ARB_draw_buffers"))
	{
		INTEGER(MAX_DRAW_BUFFERS_ARB);
	}

	// Core OpenGL 3.0:

	if (ogl_HaveExtension("GL_EXT_gpu_shader4"))
	{
		INTEGER(MIN_PROGRAM_TEXEL_OFFSET); // no _EXT version of these in glext.h
		INTEGER(MAX_PROGRAM_TEXEL_OFFSET);
	}

	if (ogl_HaveExtension("GL_EXT_framebuffer_object"))
	{
		INTEGER(MAX_COLOR_ATTACHMENTS_EXT);
		INTEGER(MAX_RENDERBUFFER_SIZE_EXT);
	}

	if (ogl_HaveExtension("GL_EXT_framebuffer_multisample"))
	{
		INTEGER(MAX_SAMPLES_EXT);
	}

	if (ogl_HaveExtension("GL_EXT_texture_array"))
	{
		INTEGER(MAX_ARRAY_TEXTURE_LAYERS_EXT);
	}

	if (ogl_HaveExtension("GL_EXT_transform_feedback"))
	{
		INTEGER(MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS_EXT);
		INTEGER(MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS_EXT);
		INTEGER(MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS_EXT);
	}


	// Other interesting extensions:

	if (ogl_HaveExtension("GL_EXT_timer_query") || ogl_HaveExtension("GL_ARB_timer_query"))
	{
		QUERY(TIME_ELAPSED, QUERY_COUNTER_BITS);
	}

	if (ogl_HaveExtension("GL_ARB_timer_query"))
	{
		QUERY(TIMESTAMP, QUERY_COUNTER_BITS);
	}

	if (ogl_HaveExtension("GL_EXT_texture_filter_anisotropic"))
	{
		FLOAT(MAX_TEXTURE_MAX_ANISOTROPY_EXT);
	}

	if (ogl_HaveExtension("GL_ARB_texture_rectangle"))
	{
		INTEGER(MAX_RECTANGLE_TEXTURE_SIZE_ARB);
	}

	if (ogl_HaveExtension("GL_ARB_vertex_program") || ogl_HaveExtension("GL_ARB_fragment_program"))
	{
		INTEGER(MAX_PROGRAM_MATRICES_ARB);
		INTEGER(MAX_PROGRAM_MATRIX_STACK_DEPTH_ARB);
	}

	if (ogl_HaveExtension("GL_ARB_vertex_program"))
	{
		VERTEXPROGRAM(MAX_PROGRAM_ENV_PARAMETERS_ARB);
		VERTEXPROGRAM(MAX_PROGRAM_LOCAL_PARAMETERS_ARB);
		VERTEXPROGRAM(MAX_PROGRAM_INSTRUCTIONS_ARB);
		VERTEXPROGRAM(MAX_PROGRAM_TEMPORARIES_ARB);
		VERTEXPROGRAM(MAX_PROGRAM_PARAMETERS_ARB);
		VERTEXPROGRAM(MAX_PROGRAM_ATTRIBS_ARB);
		VERTEXPROGRAM(MAX_PROGRAM_ADDRESS_REGISTERS_ARB);
		VERTEXPROGRAM(MAX_PROGRAM_NATIVE_INSTRUCTIONS_ARB);
		VERTEXPROGRAM(MAX_PROGRAM_NATIVE_TEMPORARIES_ARB);
		VERTEXPROGRAM(MAX_PROGRAM_NATIVE_PARAMETERS_ARB);
		VERTEXPROGRAM(MAX_PROGRAM_NATIVE_ATTRIBS_ARB);
		VERTEXPROGRAM(MAX_PROGRAM_NATIVE_ADDRESS_REGISTERS_ARB);

		if (ogl_HaveExtension("GL_ARB_fragment_program"))
		{
			// The spec seems to say these should be supported, but
			// Mesa complains about them so let's not bother
			/*
			VERTEXPROGRAM(MAX_PROGRAM_ALU_INSTRUCTIONS_ARB);
			VERTEXPROGRAM(MAX_PROGRAM_TEX_INSTRUCTIONS_ARB);
			VERTEXPROGRAM(MAX_PROGRAM_TEX_INDIRECTIONS_ARB);
			VERTEXPROGRAM(MAX_PROGRAM_NATIVE_ALU_INSTRUCTIONS_ARB);
			VERTEXPROGRAM(MAX_PROGRAM_NATIVE_TEX_INSTRUCTIONS_ARB);
			VERTEXPROGRAM(MAX_PROGRAM_NATIVE_TEX_INDIRECTIONS_ARB);
			*/
		}
	}

	if (ogl_HaveExtension("GL_ARB_fragment_program"))
	{
		FRAGMENTPROGRAM(MAX_PROGRAM_ENV_PARAMETERS_ARB);
		FRAGMENTPROGRAM(MAX_PROGRAM_LOCAL_PARAMETERS_ARB);
		FRAGMENTPROGRAM(MAX_PROGRAM_INSTRUCTIONS_ARB);
		FRAGMENTPROGRAM(MAX_PROGRAM_ALU_INSTRUCTIONS_ARB);
		FRAGMENTPROGRAM(MAX_PROGRAM_TEX_INSTRUCTIONS_ARB);
		FRAGMENTPROGRAM(MAX_PROGRAM_TEX_INDIRECTIONS_ARB);
		FRAGMENTPROGRAM(MAX_PROGRAM_TEMPORARIES_ARB);
		FRAGMENTPROGRAM(MAX_PROGRAM_PARAMETERS_ARB);
		FRAGMENTPROGRAM(MAX_PROGRAM_ATTRIBS_ARB);
		FRAGMENTPROGRAM(MAX_PROGRAM_NATIVE_INSTRUCTIONS_ARB);
		FRAGMENTPROGRAM(MAX_PROGRAM_NATIVE_ALU_INSTRUCTIONS_ARB);
		FRAGMENTPROGRAM(MAX_PROGRAM_NATIVE_TEX_INSTRUCTIONS_ARB);
		FRAGMENTPROGRAM(MAX_PROGRAM_NATIVE_TEX_INDIRECTIONS_ARB);
		FRAGMENTPROGRAM(MAX_PROGRAM_NATIVE_TEMPORARIES_ARB);
		FRAGMENTPROGRAM(MAX_PROGRAM_NATIVE_PARAMETERS_ARB);
		FRAGMENTPROGRAM(MAX_PROGRAM_NATIVE_ATTRIBS_ARB);

		if (ogl_HaveExtension("GL_ARB_vertex_program"))
		{
			// The spec seems to say these should be supported, but
			// Intel drivers on Windows complain about them so let's not bother
			/*
			FRAGMENTPROGRAM(MAX_PROGRAM_ADDRESS_REGISTERS_ARB);
			FRAGMENTPROGRAM(MAX_PROGRAM_NATIVE_ADDRESS_REGISTERS_ARB);
			*/
		}
	}

	if (ogl_HaveExtension("GL_ARB_geometry_shader4"))
	{
		INTEGER(MAX_GEOMETRY_TEXTURE_IMAGE_UNITS_ARB);
		INTEGER(MAX_GEOMETRY_OUTPUT_VERTICES_ARB);
		INTEGER(MAX_GEOMETRY_TOTAL_OUTPUT_COMPONENTS_ARB);
		INTEGER(MAX_GEOMETRY_UNIFORM_COMPONENTS_ARB);
		INTEGER(MAX_GEOMETRY_VARYING_COMPONENTS_ARB);
		INTEGER(MAX_VERTEX_VARYING_COMPONENTS_ARB);
	}

#else // CONFIG2_GLES

	// Core OpenGL ES 2.0:

	STRING(SHADING_LANGUAGE_VERSION);
	INTEGER(MAX_VERTEX_ATTRIBS);
	INTEGER(MAX_VERTEX_UNIFORM_VECTORS);
	INTEGER(MAX_VARYING_VECTORS);
	INTEGER(MAX_COMBINED_TEXTURE_IMAGE_UNITS);
	INTEGER(MAX_VERTEX_TEXTURE_IMAGE_UNITS);
	INTEGER(MAX_FRAGMENT_UNIFORM_VECTORS);
	INTEGER(MAX_TEXTURE_IMAGE_UNITS);
	INTEGER(MAX_RENDERBUFFER_SIZE);

#endif // CONFIG2_GLES


#ifdef SDL_VIDEO_DRIVER_X11

#define GLXQCR_INTEGER(id) do { \
	unsigned int i = UINT_MAX; \
	if (pglXQueryCurrentRendererIntegerMESA(id, &i)) \
		scriptInterface.SetProperty(settings, #id, i); \
	} while (false)

#define GLXQCR_INTEGER2(id) do { \
	unsigned int i[2] = { UINT_MAX, UINT_MAX }; \
	if (pglXQueryCurrentRendererIntegerMESA(id, i)) { \
		scriptInterface.SetProperty(settings, #id "[0]", i[0]); \
		scriptInterface.SetProperty(settings, #id "[1]", i[1]); \
	} \
	} while (false)

#define GLXQCR_INTEGER3(id) do { \
	unsigned int i[3] = { UINT_MAX, UINT_MAX, UINT_MAX }; \
	if (pglXQueryCurrentRendererIntegerMESA(id, i)) { \
		scriptInterface.SetProperty(settings, #id "[0]", i[0]); \
		scriptInterface.SetProperty(settings, #id "[1]", i[1]); \
		scriptInterface.SetProperty(settings, #id "[2]", i[2]); \
	} \
	} while (false)

#define GLXQCR_STRING(id) do { \
	const char* str = pglXQueryCurrentRendererStringMESA(id); \
	if (str) \
		scriptInterface.SetProperty(settings, #id ".string", str); \
	} while (false)


	SDL_SysWMinfo wminfo;
	SDL_VERSION(&wminfo.version);
#if SDL_VERSION_ATLEAST(2, 0, 0)
	const int ret = SDL_GetWindowWMInfo(g_VideoMode.GetWindow(), &wminfo);
#else
	const int ret = SDL_GetWMInfo(&wminfo);
#endif
	if (ret && wminfo.subsystem == SDL_SYSWM_X11)
	{
#if SDL_VERSION_ATLEAST(2, 0, 0)
		Display* dpy = wminfo.info.x11.display;
#else
		Display* dpy = wminfo.info.x11.gfxdisplay;
#endif
		int scrnum = DefaultScreen(dpy);

		const char* glxexts = glXQueryExtensionsString(dpy, scrnum);

		scriptInterface.SetProperty(settings, "glx_extensions", glxexts);

		if (strstr(glxexts, "GLX_MESA_query_renderer") && pglXQueryCurrentRendererIntegerMESA && pglXQueryCurrentRendererStringMESA)
		{
			GLXQCR_INTEGER(GLX_RENDERER_VENDOR_ID_MESA);
			GLXQCR_INTEGER(GLX_RENDERER_DEVICE_ID_MESA);
			GLXQCR_INTEGER3(GLX_RENDERER_VERSION_MESA);
			GLXQCR_INTEGER(GLX_RENDERER_ACCELERATED_MESA);
			GLXQCR_INTEGER(GLX_RENDERER_VIDEO_MEMORY_MESA);
			GLXQCR_INTEGER(GLX_RENDERER_UNIFIED_MEMORY_ARCHITECTURE_MESA);
			GLXQCR_INTEGER(GLX_RENDERER_PREFERRED_PROFILE_MESA);
			GLXQCR_INTEGER2(GLX_RENDERER_OPENGL_CORE_PROFILE_VERSION_MESA);
			GLXQCR_INTEGER2(GLX_RENDERER_OPENGL_COMPATIBILITY_PROFILE_VERSION_MESA);
			GLXQCR_INTEGER2(GLX_RENDERER_OPENGL_ES_PROFILE_VERSION_MESA);
			GLXQCR_INTEGER2(GLX_RENDERER_OPENGL_ES2_PROFILE_VERSION_MESA);
			GLXQCR_STRING(GLX_RENDERER_VENDOR_ID_MESA);
			GLXQCR_STRING(GLX_RENDERER_DEVICE_ID_MESA);
		}
	}
#endif // SDL_VIDEO_DRIVER_X11

}