Upstream version 10.39.225.0
[platform/framework/web/crosswalk.git] / src / gpu / command_buffer / service / shader_translator.cc
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "gpu/command_buffer/service/shader_translator.h"
6
7 #include <string.h>
8 #include <GLES2/gl2.h>
9 #include <algorithm>
10
11 #include "base/at_exit.h"
12 #include "base/debug/trace_event.h"
13 #include "base/lazy_instance.h"
14 #include "base/logging.h"
15 #include "base/strings/string_number_conversions.h"
16
17 namespace {
18
19 using gpu::gles2::ShaderTranslator;
20
21 class ShaderTranslatorInitializer {
22  public:
23   ShaderTranslatorInitializer() {
24     TRACE_EVENT0("gpu", "ShInitialize");
25     CHECK(ShInitialize());
26   }
27
28   ~ShaderTranslatorInitializer() {
29     TRACE_EVENT0("gpu", "ShFinalize");
30     ShFinalize();
31   }
32 };
33
34 base::LazyInstance<ShaderTranslatorInitializer> g_translator_initializer =
35     LAZY_INSTANCE_INITIALIZER;
36
37 void GetVariableInfo(ShHandle compiler, ShShaderInfo var_type,
38                      ShaderTranslator::VariableMap* var_map) {
39   if (!var_map)
40     return;
41   var_map->clear();
42
43   size_t name_len = 0, mapped_name_len = 0;
44   switch (var_type) {
45     case SH_ACTIVE_ATTRIBUTES:
46       ShGetInfo(compiler, SH_ACTIVE_ATTRIBUTE_MAX_LENGTH, &name_len);
47       break;
48     case SH_ACTIVE_UNIFORMS:
49       ShGetInfo(compiler, SH_ACTIVE_UNIFORM_MAX_LENGTH, &name_len);
50       break;
51     case SH_VARYINGS:
52       ShGetInfo(compiler, SH_VARYING_MAX_LENGTH, &name_len);
53       break;
54     default: NOTREACHED();
55   }
56   ShGetInfo(compiler, SH_MAPPED_NAME_MAX_LENGTH, &mapped_name_len);
57   if (name_len <= 1 || mapped_name_len <= 1) return;
58   scoped_ptr<char[]> name(new char[name_len]);
59   scoped_ptr<char[]> mapped_name(new char[mapped_name_len]);
60
61   size_t num_vars = 0;
62   ShGetInfo(compiler, var_type, &num_vars);
63   for (size_t i = 0; i < num_vars; ++i) {
64     size_t len = 0;
65     int size = 0;
66     sh::GLenum type = GL_NONE;
67     ShPrecisionType precision = SH_PRECISION_UNDEFINED;
68     int static_use = 0;
69
70     ShGetVariableInfo(compiler, var_type, i,
71                       &len, &size, &type, &precision, &static_use,
72                       name.get(), mapped_name.get());
73
74     // In theory we should CHECK(len <= name_len - 1) here, but ANGLE needs
75     // to handle long struct field name mapping before we can do this.
76     // Also, we should modify the ANGLE interface to also return a length
77     // for mapped_name.
78     std::string name_string(name.get(), std::min(len, name_len - 1));
79     mapped_name.get()[mapped_name_len - 1] = '\0';
80
81     ShaderTranslator::VariableInfo info(
82         type, size, precision, static_use, name_string);
83     (*var_map)[mapped_name.get()] = info;
84   }
85 }
86
87 void GetNameHashingInfo(
88     ShHandle compiler, ShaderTranslator::NameMap* name_map) {
89   if (!name_map)
90     return;
91   name_map->clear();
92
93   size_t hashed_names_count = 0;
94   ShGetInfo(compiler, SH_HASHED_NAMES_COUNT, &hashed_names_count);
95   if (hashed_names_count == 0)
96     return;
97
98   size_t name_max_len = 0, hashed_name_max_len = 0;
99   ShGetInfo(compiler, SH_NAME_MAX_LENGTH, &name_max_len);
100   ShGetInfo(compiler, SH_HASHED_NAME_MAX_LENGTH, &hashed_name_max_len);
101
102   scoped_ptr<char[]> name(new char[name_max_len]);
103   scoped_ptr<char[]> hashed_name(new char[hashed_name_max_len]);
104
105   for (size_t i = 0; i < hashed_names_count; ++i) {
106     ShGetNameHashingEntry(compiler, i, name.get(), hashed_name.get());
107     (*name_map)[hashed_name.get()] = name.get();
108   }
109 }
110
111 }  // namespace
112
113 namespace gpu {
114 namespace gles2 {
115
116 ShaderTranslator::DestructionObserver::DestructionObserver() {
117 }
118
119 ShaderTranslator::DestructionObserver::~DestructionObserver() {
120 }
121
122 ShaderTranslator::ShaderTranslator()
123     : compiler_(NULL),
124       implementation_is_glsl_es_(false),
125       driver_bug_workarounds_(static_cast<ShCompileOptions>(0)) {
126 }
127
128 bool ShaderTranslator::Init(
129     GLenum shader_type,
130     ShShaderSpec shader_spec,
131     const ShBuiltInResources* resources,
132     ShaderTranslatorInterface::GlslImplementationType glsl_implementation_type,
133     ShCompileOptions driver_bug_workarounds) {
134   // Make sure Init is called only once.
135   DCHECK(compiler_ == NULL);
136   DCHECK(shader_type == GL_FRAGMENT_SHADER || shader_type == GL_VERTEX_SHADER);
137   DCHECK(shader_spec == SH_GLES2_SPEC || shader_spec == SH_WEBGL_SPEC);
138   DCHECK(resources != NULL);
139
140   g_translator_initializer.Get();
141
142   ShShaderOutput shader_output =
143       (glsl_implementation_type == kGlslES ? SH_ESSL_OUTPUT : SH_GLSL_OUTPUT);
144
145   {
146     TRACE_EVENT0("gpu", "ShConstructCompiler");
147     compiler_ = ShConstructCompiler(
148         shader_type, shader_spec, shader_output, resources);
149   }
150   compiler_options_ = *resources;
151   implementation_is_glsl_es_ = (glsl_implementation_type == kGlslES);
152   driver_bug_workarounds_ = driver_bug_workarounds;
153   return compiler_ != NULL;
154 }
155
156 int ShaderTranslator::GetCompileOptions() const {
157   int compile_options =
158       SH_OBJECT_CODE | SH_VARIABLES | SH_ENFORCE_PACKING_RESTRICTIONS |
159       SH_LIMIT_EXPRESSION_COMPLEXITY | SH_LIMIT_CALL_STACK_DEPTH |
160       SH_CLAMP_INDIRECT_ARRAY_BOUNDS;
161
162   compile_options |= driver_bug_workarounds_;
163
164   return compile_options;
165 }
166
167 bool ShaderTranslator::Translate(const std::string& shader_source,
168                                  std::string* info_log,
169                                  std::string* translated_source,
170                                  VariableMap* attrib_map,
171                                  VariableMap* uniform_map,
172                                  VariableMap* varying_map,
173                                  NameMap* name_map) const {
174   // Make sure this instance is initialized.
175   DCHECK(compiler_ != NULL);
176
177   bool success = false;
178   {
179     TRACE_EVENT0("gpu", "ShCompile");
180     const char* const shader_strings[] = { shader_source.c_str() };
181     success = !!ShCompile(
182         compiler_, shader_strings, 1, GetCompileOptions());
183   }
184   if (success) {
185     if (translated_source) {
186       translated_source->clear();
187       // Get translated shader.
188       size_t obj_code_len = 0;
189       ShGetInfo(compiler_, SH_OBJECT_CODE_LENGTH, &obj_code_len);
190       if (obj_code_len > 1) {
191         scoped_ptr<char[]> buffer(new char[obj_code_len]);
192         ShGetObjectCode(compiler_, buffer.get());
193         *translated_source = std::string(buffer.get(), obj_code_len - 1);
194       }
195     }
196     // Get info for attribs, uniforms, and varyings.
197     GetVariableInfo(compiler_, SH_ACTIVE_ATTRIBUTES, attrib_map);
198     GetVariableInfo(compiler_, SH_ACTIVE_UNIFORMS, uniform_map);
199     GetVariableInfo(compiler_, SH_VARYINGS, varying_map);
200     // Get info for name hashing.
201     GetNameHashingInfo(compiler_, name_map);
202   }
203
204   // Get info log.
205   if (info_log) {
206     info_log->clear();
207     size_t info_log_len = 0;
208     ShGetInfo(compiler_, SH_INFO_LOG_LENGTH, &info_log_len);
209     if (info_log_len > 1) {
210       scoped_ptr<char[]> buffer(new char[info_log_len]);
211       ShGetInfoLog(compiler_, buffer.get());
212       *info_log = std::string(buffer.get(), info_log_len - 1);
213     }
214   }
215
216   return success;
217 }
218
219 std::string ShaderTranslator::GetStringForOptionsThatWouldAffectCompilation()
220     const {
221   DCHECK(compiler_ != NULL);
222
223   size_t resource_len = 0;
224   ShGetInfo(compiler_, SH_RESOURCES_STRING_LENGTH, &resource_len);
225   DCHECK(resource_len > 1);
226   scoped_ptr<char[]> resource_str(new char[resource_len]);
227
228   ShGetBuiltInResourcesString(compiler_, resource_len, resource_str.get());
229
230   return std::string(":CompileOptions:" +
231          base::IntToString(GetCompileOptions())) +
232          std::string(resource_str.get());
233 }
234
235 void ShaderTranslator::AddDestructionObserver(
236     DestructionObserver* observer) {
237   destruction_observers_.AddObserver(observer);
238 }
239
240 void ShaderTranslator::RemoveDestructionObserver(
241     DestructionObserver* observer) {
242   destruction_observers_.RemoveObserver(observer);
243 }
244
245 ShaderTranslator::~ShaderTranslator() {
246   FOR_EACH_OBSERVER(DestructionObserver,
247                     destruction_observers_,
248                     OnDestruct(this));
249
250   if (compiler_ != NULL)
251     ShDestruct(compiler_);
252 }
253
254 }  // namespace gles2
255 }  // namespace gpu
256