1d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens// Copyright 2016 The SwiftShader Authors. All Rights Reserved.
2894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman//
3d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens// Licensed under the Apache License, Version 2.0 (the "License");
4d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens// you may not use this file except in compliance with the License.
5d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens// You may obtain a copy of the License at
6894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman//
7d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens//    http://www.apache.org/licenses/LICENSE-2.0
8894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman//
9d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens// Unless required by applicable law or agreed to in writing, software
10d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens// distributed under the License is distributed on an "AS IS" BASIS,
11d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens// See the License for the specific language governing permissions and
13d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens// limitations under the License.
14894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
15894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman#include "SwiftConfig.hpp"
16894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
17894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman#include "Configurator.hpp"
18894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman#include "Debug.hpp"
19894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman#include "Config.hpp"
20894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman#include "Version.h"
21894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
22894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman#include <sstream>
23894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman#include <stdio.h>
24894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman#include <time.h>
25894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman#include <sys/stat.h>
2666b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman#include <string.h>
27894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
28894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Baumannamespace sw
29894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman{
30e72c4328ae76674f0f4c84838ebf5e0be77aa78dNicolas Capens	extern Profiler profiler;
31e72c4328ae76674f0f4c84838ebf5e0be77aa78dNicolas Capens
32894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	std::string itoa(int number)
33894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	{
34894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		std::stringstream ss;
35894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		ss << number;
36894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		return ss.str();
37894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	}
38d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens
39894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	std::string ftoa(double number)
40894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	{
41894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		std::stringstream ss;
42894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		ss << number;
43894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		return ss.str();
44894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	}
45894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
4666b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman	SwiftConfig::SwiftConfig(bool disableServerOverride) : listenSocket(0)
47894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	{
48894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		readConfiguration(disableServerOverride);
49894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
50894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		if(!disableServerOverride)
51894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		{
52894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			writeConfiguration();
53894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		}
54894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
55894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		receiveBuffer = 0;
56894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
57894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		if(!config.disableServer)
58894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		{
59894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			createServer();
60894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		}
61894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	}
62894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
63894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	SwiftConfig::~SwiftConfig()
64894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	{
65894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		destroyServer();
66894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	}
67894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
68894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	void SwiftConfig::createServer()
69894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	{
70894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		bufferLength = 16 * 1024;
71894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		receiveBuffer = new char[bufferLength];
72894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
7366b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman		Socket::startup();
7466b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman		listenSocket = new Socket("localhost", "8080");
7566b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman		listenSocket->listen();
76894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
7766b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman		terminate = false;
7866b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman		serverThread = new Thread(serverRoutine, this);
79894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	}
80894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
81894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	void SwiftConfig::destroyServer()
82894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	{
83894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		if(receiveBuffer)
84894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		{
85894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			terminate = true;
8666b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman			serverThread->join();
8766b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman			delete serverThread;
88894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
8966b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman			delete listenSocket;
9066b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman			listenSocket = 0;
91894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
9266b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman			Socket::cleanup();
93894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
94894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			delete[] receiveBuffer;
95894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			receiveBuffer = 0;
96894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		}
97894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	}
98894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
99894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	bool SwiftConfig::hasNewConfiguration(bool reset)
100894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	{
101894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		bool value = newConfig;
102894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
103894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		if(reset)
104894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		{
105894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			newConfig = false;
106894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		}
107894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
108894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		return value;
109894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	}
110894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
111894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	void SwiftConfig::getConfiguration(Configuration &configuration)
112894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	{
11366b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman		criticalSection.lock();
114894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		configuration = config;
11566b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman		criticalSection.unlock();
116894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	}
117894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
11866b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman	void SwiftConfig::serverRoutine(void *parameters)
119894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	{
120894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		SwiftConfig *swiftConfig = (SwiftConfig*)parameters;
121894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
122894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		swiftConfig->serverLoop();
123894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	}
124894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
125894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	void SwiftConfig::serverLoop()
126894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	{
127894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		readConfiguration();
128894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
129894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		while(!terminate)
130894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		{
13166b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman			if(listenSocket->select(100000))
132894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			{
13366b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman				Socket *clientSocket = listenSocket->accept();
134894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				int bytesReceived = 1;
135894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
136894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				while(bytesReceived > 0 && !terminate)
137894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				{
13866b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman					if(clientSocket->select(10))
139894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					{
14066b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman						bytesReceived = clientSocket->receive(receiveBuffer, bufferLength);
141894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
142894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman						if(bytesReceived > 0)
143894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman						{
144894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman							receiveBuffer[bytesReceived] = 0;
145d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens
14666b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman							respond(clientSocket, receiveBuffer);
147894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman						}
148894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					}
149894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				}
150894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
15166b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman				delete clientSocket;
152894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			}
153894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		}
154894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	}
155894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1560085c440fbbd143181322771c980e49e9c8b99b3Alexis Hetu	bool match(const char **url, const char *string)
157894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	{
158894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		size_t length = strlen(string);
159894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
160894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		if(strncmp(*url, string, length) == 0)
161894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		{
162894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			*url += length;
163894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
164894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			return true;
165894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		}
166894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
167894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		return false;
168894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	}
169894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
17066b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman	void SwiftConfig::respond(Socket *clientSocket, const char *request)
171894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	{
172894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		if(match(&request, "GET /"))
173894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		{
174894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			if(match(&request, "swiftshader") || match(&request, "swiftconfig"))
175894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			{
176894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				if(match(&request, " ") || match(&request, "/ "))
177894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				{
17866b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman					return send(clientSocket, OK, page());
179894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				}
180894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			}
181894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		}
182894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		else if(match(&request, "POST /"))
183894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		{
184894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			if(match(&request, "swiftshader") || match(&request, "swiftconfig"))
185894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			{
186894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				if(match(&request, " ") || match(&request, "/ "))
187894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				{
18866b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman					criticalSection.lock();
189894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
190894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					const char *postData = strstr(request, "\r\n\r\n");
191894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					postData = postData ? postData + 4 : 0;
192894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
193894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					if(postData && strlen(postData) > 0)
194894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					{
195894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman						parsePost(postData);
196894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					}
197894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					else   // POST data in next packet
198894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					{
19966b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman						int bytesReceived = clientSocket->receive(receiveBuffer, bufferLength);
200d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens
201894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman						if(bytesReceived > 0)
202894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman						{
203894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman							receiveBuffer[bytesReceived] = 0;
204894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman							parsePost(receiveBuffer);
205894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman						}
206894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					}
207894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
208894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					writeConfiguration();
209894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					newConfig = true;
210894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
211894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					if(config.disableServer)
212894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					{
213894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman						destroyServer();
214894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					}
215894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
21666b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman					criticalSection.unlock();
217894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
21866b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman					return send(clientSocket, OK, page());
219894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				}
220894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				else if(match(&request, "/profile "))
221894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				{
22266b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman					return send(clientSocket, OK, profile());
223894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				}
224894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			}
225894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		}
226894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
22766b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman		return send(clientSocket, NotFound);
228894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	}
229894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
230894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	std::string SwiftConfig::page()
231894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	{
232894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		std::string html;
233894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
234894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		const std::string selected = "selected='selected'";
235894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		const std::string checked = "checked='checked'";
236894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		const std::string empty = "";
237894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
238894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		html += "<!DOCTYPE HTML PUBLIC '-//W3C//DTD HTML 4.01//EN' 'http://www.w3.org/TR/html4/strict.dtd'>\n";
239894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		html += "<html>\n";
240894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		html += "<head>\n";
241894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		html += "<meta http-equiv='content-type' content='text/html; charset=UTF-8'>\n";
242894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		html += "<title>SwiftShader Configuration Panel</title>\n";
243894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		html += "</head>\n";
244894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		html += "<body>\n";
245894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		html += "<script type='text/javascript'>\n";
246894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		html += "request();\n";
247894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		html += "function request()\n";
248894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		html += "{\n";
249894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		html += "var xhr = new XMLHttpRequest();\n";
250894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		html += "xhr.open('POST', 'http://localhost:8080/swiftshader/profile', true);\n";
251894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		html += "xhr.onreadystatechange = function()\n";
252894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		html += "{\n";
253894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		html += "if(xhr.readyState == 4 && xhr.status == 200)\n";
254894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		html += "{\n";
255894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		html += "document.getElementById('profile').innerHTML = xhr.responseText;\n";
256894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		html += "setTimeout('request()', 1000);\n";
257894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		html += "}\n";
258894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		html += "}\n";
259894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		html += "xhr.send();\n";
260894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		html += "}\n";
261894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		html += "</script>\n";
262894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		html += "<form method='POST' action=''>\n";
263894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		html += "<h1>SwiftShader Configuration Panel</h1>\n";
2646ef6d2afff67ff7fb7af8c253838efcffa5d618dNicolas Capens		html += "<div id='profile'>" + profile() + "</div>\n";
265894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		html += "<hr><p>\n";
266894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		html += "<input type='submit' value='Apply changes' title='Click to apply all settings.'>\n";
267894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	//	html += "<input type='reset' value='Reset changes' title='Click to reset your changes to the previous value.'>\n";
268894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		html += "</p><hr>\n";
269894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		html += "<h2><em>Device capabilities</em></h2>\n";
270894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		html += "<table>\n";
271894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		html += "<tr><td>Build revision:</td><td>" REVISION_STRING "</td></tr>\n";
272894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		html += "<tr><td>Pixel shader model:</td><td><select name='pixelShaderVersion' title='The highest version of pixel shader supported by SwiftShader. Lower versions might be faster if supported by the application. Only effective after restarting the application.'>\n";
273894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		html += "<option value='0'"  + (config.pixelShaderVersion ==  0 ? selected : empty) + ">0.0</option>\n";
274894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		html += "<option value='11'" + (config.pixelShaderVersion == 11 ? selected : empty) + ">1.1</option>\n";
275894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		html += "<option value='12'" + (config.pixelShaderVersion == 12 ? selected : empty) + ">1.2</option>\n";
276894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		html += "<option value='13'" + (config.pixelShaderVersion == 13 ? selected : empty) + ">1.3</option>\n";
277894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		html += "<option value='14'" + (config.pixelShaderVersion == 14 ? selected : empty) + ">1.4</option>\n";
278894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		html += "<option value='20'" + (config.pixelShaderVersion == 20 ? selected : empty) + ">2.0</option>\n";
279894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		html += "<option value='21'" + (config.pixelShaderVersion == 21 ? selected : empty) + ">2.x</option>\n";
280894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		html += "<option value='30'" + (config.pixelShaderVersion == 30 ? selected : empty) + ">3.0 (default)</option>\n";
281894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		html += "</select></td></tr>\n";
282894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		html += "<tr><td>Vertex shader model:</td><td><select name='vertexShaderVersion' title='The highest version of vertex shader supported by SwiftShader. Lower versions might be faster if supported by the application. Only effective after restarting the application.'>\n";
283894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		html += "<option value='0'"  + (config.vertexShaderVersion ==  0 ? selected : empty) + ">0.0</option>\n";
284894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		html += "<option value='11'" + (config.vertexShaderVersion == 11 ? selected : empty) + ">1.1</option>\n";
285894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		html += "<option value='20'" + (config.vertexShaderVersion == 20 ? selected : empty) + ">2.0</option>\n";
286894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		html += "<option value='21'" + (config.vertexShaderVersion == 21 ? selected : empty) + ">2.x</option>\n";
287894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		html += "<option value='30'" + (config.vertexShaderVersion == 30 ? selected : empty) + ">3.0 (default)</option>\n";
288894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		html += "</select></td></tr>\n";
289894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		html += "<tr><td>Texture memory:</td><td><select name='textureMemory' title='The maximum amount of memory used for textures and other resources.'>\n";
290894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		html += "<option value='128'"  + (config.textureMemory == 128  ? selected : empty) + ">128 MB</option>\n";
291894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		html += "<option value='256'"  + (config.textureMemory == 256  ? selected : empty) + ">256 MB (default)</option>\n";
292894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		html += "<option value='512'"  + (config.textureMemory == 512  ? selected : empty) + ">512 MB</option>\n";
293894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		html += "<option value='1024'" + (config.textureMemory == 1024 ? selected : empty) + ">1024 MB</option>\n";
294894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		html += "<option value='2048'" + (config.textureMemory == 2048 ? selected : empty) + ">2048 MB</option>\n";
295894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		html += "</select></td></tr>\n";
296894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		html += "<tr><td>Device identifier:</td><td><select name='identifier' title='The information used by some applications to determine device capabilities.'>\n";
297d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		html += "<option value='0'" + (config.identifier == 0 ? selected : empty) + ">Google SwiftShader (default)</option>\n";
298894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		html += "<option value='1'" + (config.identifier == 1 ? selected : empty) + ">NVIDIA GeForce 7900 GS</option>\n";
299894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		html += "<option value='2'" + (config.identifier == 2 ? selected : empty) + ">ATI Mobility Radeon X1600</option>\n";
300894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		html += "<option value='3'" + (config.identifier == 3 ? selected : empty) + ">Intel GMA X3100</option>\n";
301894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		html += "<option value='4'" + (config.identifier == 4 ? selected : empty) + ">System device</option>\n";
302894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		html += "</select></td></tr>\n";
303894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		html += "</table>\n";
304894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		html += "<h2><em>Cache sizes</em></h2>\n";
305894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		html += "<table>\n";
306894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		html += "<tr><td>Vertex routine cache size:</td><td><select name='vertexRoutineCacheSize' title='The number of dynamically generated vertex processing routines being cached for reuse. Lower numbers save memory but require more routines to be regenerated.'>\n";
307894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		html += "<option value='64'"   + (config.vertexRoutineCacheSize == 64   ? selected : empty) + ">64</option>\n";
308894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		html += "<option value='128'"  + (config.vertexRoutineCacheSize == 128  ? selected : empty) + ">128</option>\n";
309894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		html += "<option value='256'"  + (config.vertexRoutineCacheSize == 256  ? selected : empty) + ">256</option>\n";
310894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		html += "<option value='512'"  + (config.vertexRoutineCacheSize == 512  ? selected : empty) + ">512</option>\n";
311894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		html += "<option value='1024'" + (config.vertexRoutineCacheSize == 1024 ? selected : empty) + ">1024 (default)</option>\n";
312894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		html += "<option value='2048'" + (config.vertexRoutineCacheSize == 2048 ? selected : empty) + ">2048</option>\n";
313894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		html += "<option value='4096'" + (config.vertexRoutineCacheSize == 4096 ? selected : empty) + ">4096</option>\n";
314894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		html += "</select></td>\n";
315894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		html += "</tr>\n";
316894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		html += "<tr><td>Pixel routine cache size:</td><td><select name='pixelRoutineCacheSize' title='The number of dynamically generated pixel processing routines being cached for reuse. Lower numbers save memory but require more routines to be regenerated.'>\n";
317894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		html += "<option value='64'"   + (config.pixelRoutineCacheSize == 64   ? selected : empty) + ">64</option>\n";
318894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		html += "<option value='128'"  + (config.pixelRoutineCacheSize == 128  ? selected : empty) + ">128</option>\n";
319894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		html += "<option value='256'"  + (config.pixelRoutineCacheSize == 256  ? selected : empty) + ">256</option>\n";
320894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		html += "<option value='512'"  + (config.pixelRoutineCacheSize == 512  ? selected : empty) + ">512</option>\n";
321894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		html += "<option value='1024'" + (config.pixelRoutineCacheSize == 1024 ? selected : empty) + ">1024 (default)</option>\n";
322894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		html += "<option value='2048'" + (config.pixelRoutineCacheSize == 2048 ? selected : empty) + ">2048</option>\n";
323894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		html += "<option value='4096'" + (config.pixelRoutineCacheSize == 4096 ? selected : empty) + ">4096</option>\n";
324894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		html += "</select></td>\n";
325894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		html += "</tr>\n";
326894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		html += "<tr><td>Setup routine cache size:</td><td><select name='setupRoutineCacheSize' title='The number of dynamically generated primitive setup routines being cached for reuse. Lower numbers save memory but require more routines to be regenerated.'>\n";
327894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		html += "<option value='64'"   + (config.setupRoutineCacheSize == 64   ? selected : empty) + ">64</option>\n";
328894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		html += "<option value='128'"  + (config.setupRoutineCacheSize == 128  ? selected : empty) + ">128</option>\n";
329894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		html += "<option value='256'"  + (config.setupRoutineCacheSize == 256  ? selected : empty) + ">256</option>\n";
330894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		html += "<option value='512'"  + (config.setupRoutineCacheSize == 512  ? selected : empty) + ">512</option>\n";
331894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		html += "<option value='1024'" + (config.setupRoutineCacheSize == 1024 ? selected : empty) + ">1024 (default)</option>\n";
332894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		html += "<option value='2048'" + (config.setupRoutineCacheSize == 2048 ? selected : empty) + ">2048</option>\n";
333894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		html += "<option value='4096'" + (config.setupRoutineCacheSize == 4096 ? selected : empty) + ">4096</option>\n";
334894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		html += "</select></td>\n";
335894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		html += "</tr>\n";
336894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		html += "<tr><td>Vertex cache size:</td><td><select name='vertexCacheSize' title='The number of processed vertices being cached for reuse. Lower numbers save memory but require more vertices to be reprocessed.'>\n";
337894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		html += "<option value='64'"   + (config.vertexCacheSize == 64   ? selected : empty) + ">64 (default)</option>\n";
338894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		html += "</select></td>\n";
339894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		html += "</tr>\n";
340894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		html += "</table>\n";
341894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		html += "<h2><em>Quality</em></h2>\n";
342894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		html += "<table>\n";
343894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		html += "<tr><td>Maximum texture sampling quality:</td><td><select name='textureSampleQuality' title='The maximum texture filtering quality. Lower settings can be faster but cause visual artifacts.'>\n";
344894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		html += "<option value='0'" + (config.textureSampleQuality == 0 ? selected : empty) + ">Point</option>\n";
345894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		html += "<option value='1'" + (config.textureSampleQuality == 1 ? selected : empty) + ">Linear</option>\n";
346894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		html += "<option value='2'" + (config.textureSampleQuality == 2 ? selected : empty) + ">Anisotropic (default)</option>\n";
347894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		html += "</select></td>\n";
348894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		html += "</tr>\n";
349894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		html += "<tr><td>Maximum mipmapping quality:</td><td><select name='mipmapQuality' title='The maximum mipmap filtering quality. Higher settings can be more visually appealing but are slower.'>\n";
350894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		html += "<option value='0'" + (config.mipmapQuality == 0 ? selected : empty) + ">Point</option>\n";
351894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		html += "<option value='1'" + (config.mipmapQuality == 1 ? selected : empty) + ">Linear (default)</option>\n";
352894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		html += "</select></td>\n";
353894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		html += "</tr>\n";
354894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		html += "<tr><td>Perspective correction:</td><td><select name='perspectiveCorrection' title='Enables or disables perspective correction. Disabling it is faster but can causes distortion. Recommended for 2D applications only.'>\n";
355894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		html += "<option value='0'" + (config.perspectiveCorrection == 0 ? selected : empty) + ">Off</option>\n";
356894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		html += "<option value='1'" + (config.perspectiveCorrection == 1 ? selected : empty) + ">On (default)</option>\n";
357894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		html += "</select></td>\n";
358894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		html += "</tr>\n";
359894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		html += "<tr><td>Transcendental function precision:</td><td><select name='transcendentalPrecision' title='The precision at which log/exp/pow/rcp/rsq/nrm shader instructions are computed. Lower settings can be faster but cause visual artifacts.'>\n";
360894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		html += "<option value='0'" + (config.transcendentalPrecision == 0 ? selected : empty) + ">Approximate</option>\n";
361894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		html += "<option value='1'" + (config.transcendentalPrecision == 1 ? selected : empty) + ">Partial</option>\n";
362894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		html += "<option value='2'" + (config.transcendentalPrecision == 2 ? selected : empty) + ">Accurate (default)</option>\n";
363894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		html += "<option value='3'" + (config.transcendentalPrecision == 3 ? selected : empty) + ">WHQL</option>\n";
364894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		html += "<option value='4'" + (config.transcendentalPrecision == 4 ? selected : empty) + ">IEEE</option>\n";
365894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		html += "</select></td>\n";
366894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		html += "</tr>\n";
367894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		html += "<tr><td>Transparency anti-aliasing:</td><td><select name='transparencyAntialiasing' title='The technique used to anti-alias alpha-tested transparent textures.'>\n";
368894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		html += "<option value='0'" + (config.transparencyAntialiasing == 0 ? selected : empty) + ">None (default)</option>\n";
369894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		html += "<option value='1'" + (config.transparencyAntialiasing == 1 ? selected : empty) + ">Alpha-to-Coverage</option>\n";
370894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		html += "</select></td>\n";
371894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		html += "</table>\n";
372894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		html += "<h2><em>Processor settings</em></h2>\n";
373894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		html += "<table>\n";
374894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		html += "<tr><td>Number of threads:</td><td><select name='threadCount' title='The number of rendering threads to be used.'>\n";
375894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		html += "<option value='-1'" + (config.threadCount == -1 ? selected : empty) + ">Core count</option>\n";
376894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		html += "<option value='0'"  + (config.threadCount == 0  ? selected : empty) + ">Process affinity (default)</option>\n";
377894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		html += "<option value='1'"  + (config.threadCount == 1  ? selected : empty) + ">1</option>\n";
378894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		html += "<option value='2'"  + (config.threadCount == 2  ? selected : empty) + ">2</option>\n";
379894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		html += "<option value='3'"  + (config.threadCount == 3  ? selected : empty) + ">3</option>\n";
380894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		html += "<option value='4'"  + (config.threadCount == 4  ? selected : empty) + ">4</option>\n";
381894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		html += "<option value='5'"  + (config.threadCount == 5  ? selected : empty) + ">5</option>\n";
382894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		html += "<option value='6'"  + (config.threadCount == 6  ? selected : empty) + ">6</option>\n";
383894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		html += "<option value='7'"  + (config.threadCount == 7  ? selected : empty) + ">7</option>\n";
384894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		html += "<option value='8'"  + (config.threadCount == 8  ? selected : empty) + ">8</option>\n";
385894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		html += "<option value='9'"  + (config.threadCount == 9  ? selected : empty) + ">9</option>\n";
386894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		html += "<option value='10'" + (config.threadCount == 10 ? selected : empty) + ">10</option>\n";
387894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		html += "<option value='11'" + (config.threadCount == 11 ? selected : empty) + ">11</option>\n";
388894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		html += "<option value='12'" + (config.threadCount == 12 ? selected : empty) + ">12</option>\n";
389894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		html += "<option value='13'" + (config.threadCount == 13 ? selected : empty) + ">13</option>\n";
390894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		html += "<option value='14'" + (config.threadCount == 14 ? selected : empty) + ">14</option>\n";
391894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		html += "<option value='15'" + (config.threadCount == 15 ? selected : empty) + ">15</option>\n";
392894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		html += "<option value='16'" + (config.threadCount == 16 ? selected : empty) + ">16</option>\n";
393894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		html += "</select></td></tr>\n";
3946ef6d2afff67ff7fb7af8c253838efcffa5d618dNicolas Capens		html += "<tr><td>Enable SSE:</td><td><input name = 'enableSSE' type='checkbox'" + (config.enableSSE ? checked : empty) + " disabled='disabled' title='If checked enables the use of SSE instruction set extentions if supported by the CPU.'></td></tr>";
3956ef6d2afff67ff7fb7af8c253838efcffa5d618dNicolas Capens		html += "<tr><td>Enable SSE2:</td><td><input name = 'enableSSE2' type='checkbox'" + (config.enableSSE2 ? checked : empty) + " title='If checked enables the use of SSE2 instruction set extentions if supported by the CPU.'></td></tr>";
3966ef6d2afff67ff7fb7af8c253838efcffa5d618dNicolas Capens		html += "<tr><td>Enable SSE3:</td><td><input name = 'enableSSE3' type='checkbox'" + (config.enableSSE3 ? checked : empty) + " title='If checked enables the use of SSE3 instruction set extentions if supported by the CPU.'></td></tr>";
3976ef6d2afff67ff7fb7af8c253838efcffa5d618dNicolas Capens		html += "<tr><td>Enable SSSE3:</td><td><input name = 'enableSSSE3' type='checkbox'" + (config.enableSSSE3 ? checked : empty) + " title='If checked enables the use of SSSE3 instruction set extentions if supported by the CPU.'></td></tr>";
3986ef6d2afff67ff7fb7af8c253838efcffa5d618dNicolas Capens		html += "<tr><td>Enable SSE4.1:</td><td><input name = 'enableSSE4_1' type='checkbox'" + (config.enableSSE4_1 ? checked : empty) + " title='If checked enables the use of SSE4.1 instruction set extentions if supported by the CPU.'></td></tr>";
399894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		html += "</table>\n";
400894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		html += "<h2><em>Compiler optimizations</em></h2>\n";
401894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		html += "<table>\n";
402894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
403894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		for(int pass = 0; pass < 10; pass++)
404894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		{
405894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			html += "<tr><td>Optimization pass " + itoa(pass + 1) + ":</td><td><select name='optimization" + itoa(pass + 1) + "' title='An optimization pass for the shader compiler.'>\n";
406894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			html += "<option value='0'"  + (config.optimization[pass] == 0  ? selected : empty) + ">Disabled" + (pass > 0 ? " (default)" : "") + "</option>\n";
407894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			html += "<option value='1'"  + (config.optimization[pass] == 1  ? selected : empty) + ">Instruction Combining" + (pass == 0 ? " (default)" : "") + "</option>\n";
408894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			html += "<option value='2'"  + (config.optimization[pass] == 2  ? selected : empty) + ">Control Flow Simplification</option>\n";
409894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			html += "<option value='3'"  + (config.optimization[pass] == 3  ? selected : empty) + ">Loop Invariant Code Motion</option>\n";
410894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			html += "<option value='4'"  + (config.optimization[pass] == 4  ? selected : empty) + ">Aggressive Dead Code Elimination</option>\n";
411894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			html += "<option value='5'"  + (config.optimization[pass] == 5  ? selected : empty) + ">Global Value Numbering</option>\n";
412894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			html += "<option value='6'"  + (config.optimization[pass] == 6  ? selected : empty) + ">Commutative Expressions Reassociation</option>\n";
413894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			html += "<option value='7'"  + (config.optimization[pass] == 7  ? selected : empty) + ">Dead Store Elimination</option>\n";
414894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			html += "<option value='8'"  + (config.optimization[pass] == 8  ? selected : empty) + ">Sparse Conditional Copy Propagation</option>\n";
41519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman			html += "<option value='9'"  + (config.optimization[pass] == 9  ? selected : empty) + ">Scalar Replacement of Aggregates</option>\n";
416894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			html += "</select></td></tr>\n";
417894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		}
418894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
419894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		html += "</table>\n";
420894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		html += "<h2><em>Testing & Experimental</em></h2>\n";
421894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		html += "<table>\n";
422894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		html += "<tr><td>Disable SwiftConfig server:</td><td><input name = 'disableServer' type='checkbox'" + (config.disableServer == true ? checked : empty) + " title='If checked disables the web browser based control panel.'></td></tr>";
423894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		html += "<tr><td>Force windowed mode:</td><td><input name = 'forceWindowed' type='checkbox'" + (config.forceWindowed == true ? checked : empty) + " title='If checked prevents the application from switching to full-screen mode.'></td></tr>";
424894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		html += "<tr><td>Complementary depth buffer:</td><td><input name = 'complementaryDepthBuffer' type='checkbox'" + (config.complementaryDepthBuffer == true ? checked : empty) + " title='If checked causes 1 - z to be stored in the depth buffer.'></td></tr>";
425894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		html += "<tr><td>Post alpha blend sRGB conversion:</td><td><input name = 'postBlendSRGB' type='checkbox'" + (config.postBlendSRGB == true ? checked : empty) + " title='If checked alpha blending is performed in linear color space.'></td></tr>";
426894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		html += "<tr><td>Exact color rounding:</td><td><input name = 'exactColorRounding' type='checkbox'" + (config.exactColorRounding == true ? checked : empty) + " title='If checked color rounding is done at high accuracy.'></td></tr>";
427894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		html += "<tr><td>Disable alpha display formats:</td><td><input name = 'disableAlphaMode' type='checkbox'" + (config.disableAlphaMode == true ? checked : empty) + " title='If checked the device does not advertise the A8R8G8B8 display mode.'></td></tr>";
428894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		html += "<tr><td>Disable 10-bit display formats:</td><td><input name = 'disable10BitMode' type='checkbox'" + (config.disable10BitMode == true ? checked : empty) + " title='If checked the device does not advertise the A2R10G10B10 display mode.'></td></tr>";
429894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		html += "<tr><td>Frame-buffer API:</td><td><select name='frameBufferAPI' title='The API used for displaying the rendered result on screen (requires restart).'>\n";
430894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		html += "<option value='0'" + (config.frameBufferAPI == 0 ? selected : empty) + ">DirectDraw (default)</option>\n";
431894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		html += "<option value='1'" + (config.frameBufferAPI == 1 ? selected : empty) + ">GDI</option>\n";
432894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		html += "</select></td>\n";
43366b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman		html += "<tr><td>DLL precaching:</td><td><input name = 'precache' type='checkbox'" + (config.precache == true ? checked : empty) + " title='If checked dynamically generated routines will be stored in a DLL for faster loading on application restart.'></td></tr>";
434894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		html += "<tr><td>Shadow mapping extensions:</td><td><select name='shadowMapping' title='Features that may accelerate or improve the quality of shadow mapping.'>\n";
435894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		html += "<option value='0'" + (config.shadowMapping == 0 ? selected : empty) + ">None</option>\n";
436894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		html += "<option value='1'" + (config.shadowMapping == 1 ? selected : empty) + ">Fetch4</option>\n";
437894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		html += "<option value='2'" + (config.shadowMapping == 2 ? selected : empty) + ">DST</option>\n";
438894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		html += "<option value='3'" + (config.shadowMapping == 3 ? selected : empty) + ">Fetch4 & DST (default)</option>\n";
439894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		html += "</select></td>\n";
440894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		html += "<tr><td>Force clearing registers that have no default value:</td><td><input name = 'forceClearRegisters' type='checkbox'" + (config.forceClearRegisters == true ? checked : empty) + " title='Initializes shader register values to 0 even if they have no default.'></td></tr>";
441894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		html += "</table>\n";
442894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	#ifndef NDEBUG
443894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		html += "<h2><em>Debugging</em></h2>\n";
444894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		html += "<table>\n";
445894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		html += "<tr><td>Minimum primitives:</td><td><input type='text' size='10' maxlength='10' name='minPrimitives' value='" + itoa(config.minPrimitives) + "'></td></tr>\n";
446894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		html += "<tr><td>Maximum primitives:</td><td><input type='text' size='10' maxlength='10' name='maxPrimitives' value='" + itoa(config.maxPrimitives) + "'></td></tr>\n";
447894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		html += "</table>\n";
448894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	#endif
449894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		html += "<hr><p>\n";
450894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		html += "<span style='font-size:10pt'>Hover the mouse pointer over a control to get additional information.</span><br>\n";
451894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		html += "<span style='font-size:10pt'>Some settings can be applied interactively, some need a restart of the application.</span><br>\n";
452894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		html += "<span style='font-size:10pt'>Removing the SwiftShader.ini file results in resetting the options to their default.</span></p>\n";
453894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		html += "</form>\n";
454894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		html += "</body>\n";
455894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		html += "</html>\n";
456894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
4576ef6d2afff67ff7fb7af8c253838efcffa5d618dNicolas Capens		profiler.reset();
458894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
459894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		return html;
460894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	}
461894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
462894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	std::string SwiftConfig::profile()
463894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	{
464894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		std::string html;
465894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
4666ef6d2afff67ff7fb7af8c253838efcffa5d618dNicolas Capens		html += "<p>FPS: " + ftoa(profiler.FPS) + "</p>\n";
4676ef6d2afff67ff7fb7af8c253838efcffa5d618dNicolas Capens		html += "<p>Frame: " + itoa(profiler.framesTotal) + "</p>\n";
4686ef6d2afff67ff7fb7af8c253838efcffa5d618dNicolas Capens
469894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		#if PERF_PROFILE
470894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			int texTime = (int)(1000 * profiler.cycles[PERF_TEX] / profiler.cycles[PERF_PIXEL] + 0.5);
471894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			int shaderTime = (int)(1000 * profiler.cycles[PERF_SHADER] / profiler.cycles[PERF_PIXEL] + 0.5);
472894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			int pipeTime = (int)(1000 * profiler.cycles[PERF_PIPE] / profiler.cycles[PERF_PIXEL] + 0.5);
473894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			int ropTime = (int)(1000 * profiler.cycles[PERF_ROP] / profiler.cycles[PERF_PIXEL] + 0.5);
474894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			int interpTime = (int)(1000 * profiler.cycles[PERF_INTERP] / profiler.cycles[PERF_PIXEL] + 0.5);
475894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			int rastTime = 1000 - pipeTime;
476894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
477894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			pipeTime -= shaderTime + ropTime + interpTime;
478894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			shaderTime -= texTime;
479894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
480894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			double texTimeF = (double)texTime / 10;
481894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			double shaderTimeF = (double)shaderTime / 10;
482894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			double pipeTimeF = (double)pipeTime / 10;
483894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			double ropTimeF = (double)ropTime / 10;
484894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			double interpTimeF = (double)interpTime / 10;
485894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			double rastTimeF = (double)rastTime / 10;
486894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
487894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			double averageRopOperations = profiler.ropOperationsTotal / std::max(profiler.framesTotal, 1) / 1.0e6f;
488894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			double averageCompressedTex = profiler.compressedTexTotal / std::max(profiler.framesTotal, 1) / 1.0e6f;
489894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			double averageTexOperations = profiler.texOperationsTotal / std::max(profiler.framesTotal, 1) / 1.0e6f;
490894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
491894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			html += "<p>Raster operations (million): " + ftoa(profiler.ropOperationsFrame / 1.0e6f) + " (current), " + ftoa(averageRopOperations) + " (average)</p>\n";
492894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			html += "<p>Texture operations (million): " + ftoa(profiler.texOperationsFrame / 1.0e6f) + " (current), " + ftoa(averageTexOperations) + " (average)</p>\n";
493894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			html += "<p>Compressed texture operations (million): " + ftoa(profiler.compressedTexFrame / 1.0e6f) + " (current), " + ftoa(averageCompressedTex) + " (average)</p>\n";
494894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			html += "<div id='profile' style='position:relative; width:1010px; height:50px; background-color:silver;'>";
495894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			html += "<div style='position:relative; width:1000px; height:40px; background-color:white; left:5px; top:5px;'>";
496894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			html += "<div style='position:relative; float:left; width:" + itoa(rastTime)   + "px; height:40px; border-style:none; text-align:center; line-height:40px; background-color:#FFFF7F; overflow:hidden;'>" + ftoa(rastTimeF)   + "% rast</div>\n";
497894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			html += "<div style='position:relative; float:left; width:" + itoa(pipeTime)   + "px; height:40px; border-style:none; text-align:center; line-height:40px; background-color:#FF7F7F; overflow:hidden;'>" + ftoa(pipeTimeF)   + "% pipe</div>\n";
498894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			html += "<div style='position:relative; float:left; width:" + itoa(interpTime) + "px; height:40px; border-style:none; text-align:center; line-height:40px; background-color:#7FFFFF; overflow:hidden;'>" + ftoa(interpTimeF) + "% interp</div>\n";
499894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			html += "<div style='position:relative; float:left; width:" + itoa(shaderTime) + "px; height:40px; border-style:none; text-align:center; line-height:40px; background-color:#7FFF7F; overflow:hidden;'>" + ftoa(shaderTimeF) + "% shader</div>\n";
500894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			html += "<div style='position:relative; float:left; width:" + itoa(texTime)    + "px; height:40px; border-style:none; text-align:center; line-height:40px; background-color:#FF7FFF; overflow:hidden;'>" + ftoa(texTimeF)    + "% tex</div>\n";
501894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			html += "<div style='position:relative; float:left; width:" + itoa(ropTime)    + "px; height:40px; border-style:none; text-align:center; line-height:40px; background-color:#7F7FFF; overflow:hidden;'>" + ftoa(ropTimeF)    + "% rop</div>\n";
502894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			html += "</div></div>\n";
503894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
504894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			for(int i = 0; i < PERF_TIMERS; i++)
505894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			{
506894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				profiler.cycles[i] = 0;
507894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			}
508894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		#endif
509894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
510894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		return html;
511894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	}
512894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
51366b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman	void SwiftConfig::send(Socket *clientSocket, Status code, std::string body)
514894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	{
515894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		std::string status;
516894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		char header[1024];
517894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
518894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		switch(code)
519894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		{
520894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		case OK:       status += "HTTP/1.1 200 OK\r\n";        break;
521894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		case NotFound: status += "HTTP/1.1 404 Not Found\r\n"; break;
522894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		}
523894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
524894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		sprintf(header, "Content-Type: text/html; charset=UTF-8\r\n"
525894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman						"Content-Length: %d\r\n"
526894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman						"Host: localhost\r\n"
527894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman						"\r\n", body.size());
528894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
529894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		std::string message = status + header + body;
53066b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman		clientSocket->send(message.c_str(), (int)message.length());
531894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	}
532894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
533894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	void SwiftConfig::parsePost(const char *post)
534894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	{
535894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		// Only enabled checkboxes appear in the POST
536894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		config.enableSSE = true;
53719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman		config.enableSSE2 = false;
538894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		config.enableSSE3 = false;
539894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		config.enableSSSE3 = false;
540894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		config.enableSSE4_1 = false;
541894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		config.disableServer = false;
542894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		config.forceWindowed = false;
543894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		config.complementaryDepthBuffer = false;
544894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		config.postBlendSRGB = false;
545894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		config.exactColorRounding = false;
546894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		config.disableAlphaMode = false;
547894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		config.disable10BitMode = false;
54866b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman		config.precache = false;
549894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		config.forceClearRegisters = false;
550894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
551894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		while(*post != 0)
552894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		{
553894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			int integer;
554894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			int index;
555894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
556894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			if(sscanf(post, "pixelShaderVersion=%d", &integer))
557894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			{
558894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				config.pixelShaderVersion = integer;
559894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			}
560894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			else if(sscanf(post, "vertexShaderVersion=%d", &integer))
561894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			{
562894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				config.vertexShaderVersion = integer;
563894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			}
564894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			else if(sscanf(post, "textureMemory=%d", &integer))
565894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			{
566894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				config.textureMemory = integer;
567894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			}
568894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			else if(sscanf(post, "identifier=%d", &integer))
569894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			{
570894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				config.identifier = integer;
571894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			}
572894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			else if(sscanf(post, "vertexRoutineCacheSize=%d", &integer))
573894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			{
574894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				config.vertexRoutineCacheSize = integer;
575894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			}
576894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			else if(sscanf(post, "pixelRoutineCacheSize=%d", &integer))
577894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			{
578894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				config.pixelRoutineCacheSize = integer;
579894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			}
580894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			else if(sscanf(post, "setupRoutineCacheSize=%d", &integer))
581894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			{
582894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				config.setupRoutineCacheSize = integer;
583894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			}
584894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			else if(sscanf(post, "vertexCacheSize=%d", &integer))
585894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			{
586894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				config.vertexCacheSize = integer;
587894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			}
588894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			else if(sscanf(post, "textureSampleQuality=%d", &integer))
589894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			{
590894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				config.textureSampleQuality = integer;
591894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			}
592894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			else if(sscanf(post, "mipmapQuality=%d", &integer))
593894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			{
594894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				config.mipmapQuality = integer;
595894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			}
596894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			else if(sscanf(post, "perspectiveCorrection=%d", &integer))
597894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			{
598894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				config.perspectiveCorrection = integer != 0;
599894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			}
600894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			else if(sscanf(post, "transcendentalPrecision=%d", &integer))
601894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			{
602894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				config.transcendentalPrecision = integer;
603894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			}
604894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			else if(sscanf(post, "transparencyAntialiasing=%d", &integer))
605894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			{
606894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				config.transparencyAntialiasing = integer;
607894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			}
608894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			else if(sscanf(post, "threadCount=%d", &integer))
609894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			{
610894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				config.threadCount = integer;
611894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			}
612894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			else if(sscanf(post, "frameBufferAPI=%d", &integer))
613894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			{
614894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				config.frameBufferAPI = integer;
615894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			}
616894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			else if(sscanf(post, "shadowMapping=%d", &integer))
617894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			{
618894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				config.shadowMapping = integer;
619894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			}
620894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			else if(strstr(post, "enableSSE=on"))
621894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			{
622894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				config.enableSSE = true;
623894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			}
624894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			else if(strstr(post, "enableSSE2=on"))
625894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			{
626894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				if(config.enableSSE)
627894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				{
628894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					config.enableSSE2 = true;
629894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				}
630894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			}
631894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			else if(strstr(post, "enableSSE3=on"))
632894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			{
633894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				if(config.enableSSE2)
634894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				{
635894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					config.enableSSE3 = true;
636894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				}
637894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			}
638894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			else if(strstr(post, "enableSSSE3=on"))
639894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			{
640894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				if(config.enableSSE3)
641894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				{
642894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					config.enableSSSE3 = true;
643894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				}
644894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			}
645894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			else if(strstr(post, "enableSSE4_1=on"))
646894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			{
647894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				if(config.enableSSSE3)
648894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				{
649894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					config.enableSSE4_1 = true;
650894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				}
651894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			}
652894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			else if(sscanf(post, "optimization%d=%d", &index, &integer))
653894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			{
654894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				config.optimization[index - 1] = (Optimization)integer;
655894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			}
656894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			else if(strstr(post, "disableServer=on"))
657894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			{
658894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				config.disableServer = true;
659894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			}
660894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			else if(strstr(post, "forceWindowed=on"))
661894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			{
662894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				config.forceWindowed = true;
663894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			}
664894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			else if(strstr(post, "complementaryDepthBuffer=on"))
665894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			{
666894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				config.complementaryDepthBuffer = true;
667894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			}
668894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			else if(strstr(post, "postBlendSRGB=on"))
669894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			{
670894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				config.postBlendSRGB = true;
671894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			}
672894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			else if(strstr(post, "exactColorRounding=on"))
673894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			{
674894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				config.exactColorRounding = true;
675894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			}
676894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			else if(strstr(post, "disableAlphaMode=on"))
677894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			{
678894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				config.disableAlphaMode = true;
679894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			}
680894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			else if(strstr(post, "disable10BitMode=on"))
681894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			{
682894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				config.disable10BitMode = true;
683894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			}
68466b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman			else if(strstr(post, "precache=on"))
68566b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman			{
68666b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman				config.precache = true;
68766b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman			}
688894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			else if(strstr(post, "forceClearRegisters=on"))
689894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			{
690894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				config.forceClearRegisters = true;
691894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			}
692d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		#ifndef NDEBUG
693894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			else if(sscanf(post, "minPrimitives=%d", &integer))
694894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			{
695894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				config.minPrimitives = integer;
696894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			}
697894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			else if(sscanf(post, "maxPrimitives=%d", &integer))
698894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			{
699894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				config.maxPrimitives = integer;
700894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			}
701894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		#endif
702894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			else
703894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			{
704894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				ASSERT(false);
705894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			}
706894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
707894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			do
708894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			{
709894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				post++;
710894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			}
711894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			while(post[-1] != '&' && *post != 0);
712894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		}
713894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	}
714894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
715894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	void SwiftConfig::readConfiguration(bool disableServerOverride)
716894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	{
717894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		Configurator ini("SwiftShader.ini");
718894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
719894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		config.pixelShaderVersion = ini.getInteger("Capabilities", "PixelShaderVersion", 30);
720894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		config.vertexShaderVersion = ini.getInteger("Capabilities", "VertexShaderVersion", 30);
721894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		config.textureMemory = ini.getInteger("Capabilities", "TextureMemory", 256);
722894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		config.identifier = ini.getInteger("Capabilities", "Identifier", 0);
723894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		config.vertexRoutineCacheSize = ini.getInteger("Caches", "VertexRoutineCacheSize", 1024);
724894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		config.pixelRoutineCacheSize = ini.getInteger("Caches", "PixelRoutineCacheSize", 1024);
725894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		config.setupRoutineCacheSize = ini.getInteger("Caches", "SetupRoutineCacheSize", 1024);
726894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		config.vertexCacheSize = ini.getInteger("Caches", "VertexCacheSize", 64);
727894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		config.textureSampleQuality = ini.getInteger("Quality", "TextureSampleQuality", 2);
728894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		config.mipmapQuality = ini.getInteger("Quality", "MipmapQuality", 1);
729894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		config.perspectiveCorrection = ini.getBoolean("Quality", "PerspectiveCorrection", true);
730894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		config.transcendentalPrecision = ini.getInteger("Quality", "TranscendentalPrecision", 2);
731894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		config.transparencyAntialiasing = ini.getInteger("Quality", "TransparencyAntialiasing", 0);
732a0355b74be48bae62aa31d353d2fe24210e68a2aNicolas Capens		config.threadCount = ini.getInteger("Processor", "ThreadCount", DEFAULT_THREAD_COUNT);
733894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		config.enableSSE = ini.getBoolean("Processor", "EnableSSE", true);
734894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		config.enableSSE2 = ini.getBoolean("Processor", "EnableSSE2", true);
735894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		config.enableSSE3 = ini.getBoolean("Processor", "EnableSSE3", true);
736894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		config.enableSSSE3 = ini.getBoolean("Processor", "EnableSSSE3", true);
737894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		config.enableSSE4_1 = ini.getBoolean("Processor", "EnableSSE4_1", true);
738894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
739894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		for(int pass = 0; pass < 10; pass++)
740894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		{
741894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			config.optimization[pass] = (Optimization)ini.getInteger("Optimization", "OptimizationPass" + itoa(pass + 1), pass == 0 ? InstructionCombining : Disabled);
742894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		}
743894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
74419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman		config.disableServer = ini.getBoolean("Testing", "DisableServer", false);
745894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		config.forceWindowed = ini.getBoolean("Testing", "ForceWindowed", false);
746894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		config.complementaryDepthBuffer = ini.getBoolean("Testing", "ComplementaryDepthBuffer", false);
747894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		config.postBlendSRGB = ini.getBoolean("Testing", "PostBlendSRGB", false);
74819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman		config.exactColorRounding = ini.getBoolean("Testing", "ExactColorRounding", true);
749894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		config.disableAlphaMode = ini.getBoolean("Testing", "DisableAlphaMode", false);
750894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		config.disable10BitMode = ini.getBoolean("Testing", "Disable10BitMode", false);
751894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		config.frameBufferAPI = ini.getInteger("Testing", "FrameBufferAPI", 0);
75266b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman		config.precache = ini.getBoolean("Testing", "Precache", false);
753894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		config.shadowMapping = ini.getInteger("Testing", "ShadowMapping", 3);
754894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		config.forceClearRegisters = ini.getBoolean("Testing", "ForceClearRegisters", false);
755894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
756894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	#ifndef NDEBUG
757894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		config.minPrimitives = 1;
758894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		config.maxPrimitives = 1 << 21;
759894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	#endif
760894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
761894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		struct stat status;
762894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		int lastModified = ini.getInteger("LastModified", "Time", 0);
763894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
764894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		bool noConfig = stat("SwiftShader.ini", &status) != 0;
765894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		newConfig = !noConfig && abs((int)status.st_mtime - lastModified) > 1;
766894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
767894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		if(disableServerOverride)
768894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		{
769894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			config.disableServer = true;
770894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		}
771894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	}
772894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
773894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	void SwiftConfig::writeConfiguration()
774894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	{
775894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		Configurator ini("SwiftShader.ini");
776d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens
777894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		ini.addValue("Capabilities", "PixelShaderVersion", itoa(config.pixelShaderVersion));
778894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		ini.addValue("Capabilities", "VertexShaderVersion", itoa(config.vertexShaderVersion));
779894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		ini.addValue("Capabilities", "TextureMemory", itoa(config.textureMemory));
780894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		ini.addValue("Capabilities", "Identifier", itoa(config.identifier));
781894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		ini.addValue("Caches", "VertexRoutineCacheSize", itoa(config.vertexRoutineCacheSize));
782894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		ini.addValue("Caches", "PixelRoutineCacheSize", itoa(config.pixelRoutineCacheSize));
783894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		ini.addValue("Caches", "SetupRoutineCacheSize", itoa(config.setupRoutineCacheSize));
784894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		ini.addValue("Caches", "VertexCacheSize", itoa(config.vertexCacheSize));
785894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		ini.addValue("Quality", "TextureSampleQuality", itoa(config.textureSampleQuality));
786894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		ini.addValue("Quality", "MipmapQuality", itoa(config.mipmapQuality));
787894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		ini.addValue("Quality", "PerspectiveCorrection", itoa(config.perspectiveCorrection));
788894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		ini.addValue("Quality", "TranscendentalPrecision", itoa(config.transcendentalPrecision));
789894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		ini.addValue("Quality", "TransparencyAntialiasing", itoa(config.transparencyAntialiasing));
790894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		ini.addValue("Processor", "ThreadCount", itoa(config.threadCount));
791894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	//	ini.addValue("Processor", "EnableSSE", itoa(config.enableSSE));
79219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman		ini.addValue("Processor", "EnableSSE2", itoa(config.enableSSE2));
793894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		ini.addValue("Processor", "EnableSSE3", itoa(config.enableSSE3));
794894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		ini.addValue("Processor", "EnableSSSE3", itoa(config.enableSSSE3));
795894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		ini.addValue("Processor", "EnableSSE4_1", itoa(config.enableSSE4_1));
796894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
797894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		for(int pass = 0; pass < 10; pass++)
798894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		{
799894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			ini.addValue("Optimization", "OptimizationPass" + itoa(pass + 1), itoa(config.optimization[pass]));
800894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		}
801894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
802894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		ini.addValue("Testing", "DisableServer", itoa(config.disableServer));
803894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		ini.addValue("Testing", "ForceWindowed", itoa(config.forceWindowed));
804894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		ini.addValue("Testing", "ComplementaryDepthBuffer", itoa(config.complementaryDepthBuffer));
805894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		ini.addValue("Testing", "PostBlendSRGB", itoa(config.postBlendSRGB));
806894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		ini.addValue("Testing", "ExactColorRounding", itoa(config.exactColorRounding));
807894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		ini.addValue("Testing", "DisableAlphaMode", itoa(config.disableAlphaMode));
808894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		ini.addValue("Testing", "Disable10BitMode", itoa(config.disable10BitMode));
809894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		ini.addValue("Testing", "FrameBufferAPI", itoa(config.frameBufferAPI));
81066b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman		ini.addValue("Testing", "Precache", itoa(config.precache));
811894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		ini.addValue("Testing", "ShadowMapping", itoa(config.shadowMapping));
812894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		ini.addValue("Testing", "ForceClearRegisters", itoa(config.forceClearRegisters));
813894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		ini.addValue("LastModified", "Time", itoa((int)time(0)));
814894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
815894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		ini.writeFile("SwiftShader Configuration File\n"
816894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		              ";\n"
817894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					  "; To get an overview of the valid settings and their meaning,\n"
818894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					  "; run the application in windowed mode and open the\n"
819894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					  "; SwiftConfig application or go to http://localhost:8080/swiftconfig.");
820894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	}
821894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman}
822