24 #include "base/integral_types.h"
38 using gfxutils::ShaderManager;
45 typedef std::vector<std::string> StringVector;
47 static const char kInfoLogString[] =
"|info log|";
52 static std::string SimpleHtmlList(
const std::string& title,
53 const std::string& description,
54 const std::string& dir,
55 const StringVector& elements) {
56 std::stringstream
str;
57 str <<
"<!DOCTYPE html>\n<html><head><title>" << title <<
"</title></head>"
58 <<
"<body><link rel=\"stylesheet\" href=\"/ion/css/style.css\" />\n"
59 << description <<
"\n<ul>\n";
61 const size_t count = elements.size();
62 for (
size_t i = 0; i < count; ++i) {
63 str <<
" <li><a href=\"" << dir <<
"/" << elements[i] <<
"\">"
64 << elements[i] <<
"</a></li>\n";
66 str <<
"</body>\n</html>\n";
83 std::string* content_type) {
84 StringVector shaders = sm->GetShaderProgramNames();
93 *content_type =
"text/html";
95 shaders.push_back(
"shader_editor");
96 return SimpleHtmlList(
"Registered shader programs",
97 "<h3>List of registered shader programs. Click on a"
98 " name to see shader stages.</h3>",
"/ion/shaders",
104 static const std::string GetShaderStagesString(
const std::string& program_name,
106 std::string* content_type) {
107 StringVector stages(3);
108 stages[0] = kInfoLogString;
109 stages[1] =
"vertex";
110 stages[2] =
"fragment";
114 *content_type =
"text/html";
115 return SimpleHtmlList(
116 std::string(
"Info log and shader stages for ") + program_name,
117 std::string(
"<h3>Info log and shader stages for program '") +
118 program_name +
"'. Click on a stage to see shader sources.</h3>",
119 program_name, stages);
124 static const std::string GetDependenciesString(
125 const std::string& program_name,
const std::string& stage,
126 const StringVector& dependencies,
bool serve_raw,
127 std::string* content_type) {
133 *content_type =
"text/html";
134 return SimpleHtmlList(
135 std::string(
"List of dependencies for the ") + stage +
136 std::string(
" stage of ") + program_name,
137 std::string(
"<h3>List of dependencies for the ") + stage +
138 std::string(
" stage of program '") + program_name +
139 "'. Click on a stage to see shader sources.</h3>",
140 stage, dependencies);
146 static const std::string FormatInfoLog(
147 const std::string& log,
150 const size_t count = lines.size();
151 std::stringstream
str;
152 for (
size_t i = 0; i < count; ++i) {
159 if (tokens[0].find(
'(') != std::string::npos) {
163 str << composer->GetDependencyName(input_id) <<
":" << numbers[1] <<
":"
165 StringVector(tokens.begin() + 2, tokens.end()),
":");
169 str << composer->GetDependencyName(input_id) <<
":" << tokens[2] <<
":"
171 StringVector(tokens.begin() + 3, tokens.end()),
":");
181 static const std::string GetShaderProgramInfoLog(
182 const gfx::ShaderProgram* program,
184 const std::string& stage) {
187 if (stage ==
"vertex" && program->GetVertexShader().Get())
188 log = FormatInfoLog(program->GetVertexShader()->GetInfoLog(), composer);
189 else if (stage ==
"fragment" && program->GetFragmentShader().Get())
190 log = FormatInfoLog(program->GetFragmentShader()->GetInfoLog(), composer);
192 log = program->GetInfoLog();
204 const std::string& path,
206 std::string* content_type) {
207 const bool serve_raw = args.find(
"raw") != args.end();
209 return GetProgramNamesString(sm, serve_raw, content_type);
212 if (
const gfx::ShaderProgram* program =
213 sm->GetShaderProgram(names[0]).Get()) {
215 if (names.size() == 1) {
216 return GetShaderStagesString(names[0], serve_raw, content_type);
217 }
else if (names.size() >= 2) {
220 if (names[1] ==
"vertex")
221 sm->GetShaderProgramComposers(names[0], &composer, NULL);
222 else if (names[1] ==
"fragment")
223 sm->GetShaderProgramComposers(names[0], NULL, &composer);
224 else if (names[1] == kInfoLogString)
225 return GetShaderProgramInfoLog(program, composer,
"link");
227 if (composer.Get()) {
228 StringVector dependencies;
230 dependencies.push_back(kInfoLogString);
231 const StringVector deps = composer->GetDependencyNames();
232 dependencies.insert(dependencies.end(), deps.begin(), deps.end());
235 HttpServer::QueryMap::const_iterator it = args.find(
"set_source");
236 if (it == args.end()) {
239 if (names.size() == 2) {
240 return GetDependenciesString(
241 names[0], names[1], dependencies, serve_raw, content_type);
247 if (names[2] == kInfoLogString)
248 return GetShaderProgramInfoLog(program, composer, names[1]);
251 StringVector(names.begin() + 2, names.end()),
"/"));
257 StringVector(names.begin() + 2, names.end()),
"/");
258 composer->SetDependencySource(dep_name, it->second);
259 sm->RecreateShaderProgramsThatDependOn(dep_name);
261 if (renderer.Get()) {
262 const bool wait_for_completion =
263 (args.find(
"nonblocking") == args.end());
267 gfx::ResourceManager* rm = renderer->GetResourceManager();
268 rm->RequestAllResourceInfos<gfx::ShaderProgram,
271 callback.Get(), std::placeholders::_1));
272 callback->WaitForCompletion(NULL);
274 return "Shader source changed.";
280 return std::string();
286 StringVector shaders = sm->GetShaderProgramNames();
287 const size_t count = shaders.size();
288 StringVector logs(3);
289 for (
size_t i = 0; i < count; ++i) {
291 sm->GetShaderProgram(shaders[i]);
294 sm->GetShaderProgramComposers(shaders[i], &vertex_composer,
298 static const char kOk[] =
"OK";
299 static const char kError[] =
"Error";
300 logs[0] = (!program->GetVertexShader().Get() ||
301 program->GetVertexShader()->GetInfoLog().empty())
304 logs[1] = (!program->GetFragmentShader().Get() ||
305 program->GetFragmentShader()->GetInfoLog().empty())
308 logs[2] = program->GetInfoLog().empty() ? kOk : kError;
323 static const std::string UpdateAndServeChangedDependencies(
325 StringVector shaders = sm->GetShaderProgramNames();
326 const size_t count = shaders.size();
327 std::set<std::string> changed_set;
328 for (
size_t i = 0; i < count; ++i) {
330 sm->GetShaderProgram(shaders[i]);
333 sm->GetShaderProgramComposers(shaders[i], &vertex_composer,
335 if (vertex_composer.Get()) {
336 const std::vector<std::string> changed =
337 vertex_composer->GetChangedDependencies();
338 changed_set.insert(changed.begin(), changed.end());
340 if (fragment_composer.Get()) {
341 const std::vector<std::string> changed =
342 fragment_composer->GetChangedDependencies();
343 changed_set.insert(changed.begin(), changed.end());
348 if (
const size_t count = changed_set.size()) {
349 const std::vector<std::string> changed(changed_set.begin(),
351 for (
size_t i = 0; i < count; ++i)
352 sm->RecreateShaderProgramsThatDependOn(changed[i]);
367 IonRemoteShadersRoot::RegisterAssetsOnce();
374 std::string* content_type) {
375 const std::string path =
376 path_in ==
"shader_editor" ?
"shader_editor/index.html" : path_in;
378 if (path ==
"shader_status") {
379 return ServeShaderStatus(sm_);
380 }
else if (path ==
"update_changed_dependencies") {
381 return UpdateAndServeChangedDependencies(sm_);
384 "ion/shaders/" + path);
386 return std::string();
390 *content_type =
"text/html";
394 return GetShadersRootString(sm_, renderer_, path, args, content_type);
base::ReferentPtr< ShaderManager >::Type ShaderManagerPtr
bool IsInvalidReference(const T &value)
IsInvalidReference() returns true if a passed const reference of type T has an address of InvalidRefe...
kShortTerm is used for objects that are very transient in nature, such as scratch memory used to comp...
void Callback(const std::vector< T > &data)
This function is compatible with ResourceManager::InfoCallback, and should be used as the callback pa...
ION_REGISTER_ASSETS(IonRemoteShadersRoot)
Copyright 2016 Google Inc.
bool StartsWith(const std::string &target, const std::string &start)
Returns whether target begins with start.
base::ReferentPtr< ResourceCallback< T > >::Type RefPtr
ShaderHandler(const gfxutils::ShaderManagerPtr &shader_manager, const gfx::RendererPtr &renderer)
A ShaderHandler requires a valid ShaderManager as well as a Renderer to notify of changes made to sha...
const std::string HandleRequest(const std::string &path, const HttpServer::QueryMap &args, std::string *content_type) override
The HandleRequest() function is passed the path (relative to its base path) of the file or directory ...
std::vector< std::string > ION_API SplitString(const std::string &str, const std::string &delimiters)
Splits a string into a vector of substrings, given a set of delimiter characters (expressed as a stri...
static const std::string & GetFileData(const std::string &filename)
Returns the data of the passed filename if the manager contains it.
gfx::ProgramInfo< ResourceInfo > ProgramInfo
~ShaderHandler() override
int32 ION_API StringToInt32(const std::string &str)
Extracts and returns an integral value from str.
base::ReferentPtr< ShaderProgram >::Type ShaderProgramPtr
std::string JoinStrings(const std::vector< std::string > &strings, const std::string &glue)
Joins the strings in the passed vector together with the passed glue.
bool EndsWith(const std::string &target, const std::string &end)
Returns whether target ends with end.
ResourceCallback< gfx::ResourceManager::ProgramInfo > ProgramCallback
const RendererPtr & renderer_
Renderer used to render images.
std::map< std::string, std::string > QueryMap
base::ReferentPtr< Renderer >::Type RendererPtr
Convenience typedef for shared pointer to a Renderer.
A SharedPtr is a smart shared pointer to an instance of some class that implements reference counting...
base::ReferentPtr< ShaderSourceComposer >::Type ShaderSourceComposerPtr