Handle account removal correctly on all platforms.
[chromium-blink-merge.git] / gpu / command_buffer / service / shader_translator.cc
blobbc06ab349fff441748642cd0929b91b80f59f7e8
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.
5 #include "gpu/command_buffer/service/shader_translator.h"
7 #include <string.h>
8 #include <GLES2/gl2.h>
9 #include <algorithm>
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"
17 namespace {
19 using gpu::gles2::ShaderTranslator;
21 class ShaderTranslatorInitializer {
22 public:
23 ShaderTranslatorInitializer() {
24 TRACE_EVENT0("gpu", "ShInitialize");
25 CHECK(ShInitialize());
28 ~ShaderTranslatorInitializer() {
29 TRACE_EVENT0("gpu", "ShFinalize");
30 ShFinalize();
34 base::LazyInstance<ShaderTranslatorInitializer> g_translator_initializer =
35 LAZY_INSTANCE_INITIALIZER;
37 void GetVariableInfo(ShHandle compiler, ShShaderInfo var_type,
38 ShaderTranslator::VariableMap* var_map) {
39 if (!var_map)
40 return;
41 var_map->clear();
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();
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]);
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;
70 ShGetVariableInfo(compiler, var_type, i,
71 &len, &size, &type, &precision, &static_use,
72 name.get(), mapped_name.get());
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';
81 ShaderTranslator::VariableInfo info(
82 type, size, precision, static_use, name_string);
83 (*var_map)[mapped_name.get()] = info;
87 void GetNameHashingInfo(
88 ShHandle compiler, ShaderTranslator::NameMap* name_map) {
89 if (!name_map)
90 return;
91 name_map->clear();
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;
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);
102 scoped_ptr<char[]> name(new char[name_max_len]);
103 scoped_ptr<char[]> hashed_name(new char[hashed_name_max_len]);
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();
111 } // namespace
113 namespace gpu {
114 namespace gles2 {
116 ShaderTranslator::DestructionObserver::DestructionObserver() {
119 ShaderTranslator::DestructionObserver::~DestructionObserver() {
122 ShaderTranslator::ShaderTranslator()
123 : compiler_(NULL),
124 implementation_is_glsl_es_(false),
125 driver_bug_workarounds_(static_cast<ShCompileOptions>(0)) {
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);
140 g_translator_initializer.Get();
142 ShShaderOutput shader_output =
143 (glsl_implementation_type == kGlslES ? SH_ESSL_OUTPUT : SH_GLSL_OUTPUT);
146 TRACE_EVENT0("gpu", "ShConstructCompiler");
147 compiler_ = ShConstructCompiler(
148 shader_type, shader_spec, shader_output, resources);
150 compiler_options_ = *resources;
151 implementation_is_glsl_es_ = (glsl_implementation_type == kGlslES);
152 driver_bug_workarounds_ = driver_bug_workarounds;
153 return compiler_ != NULL;
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;
162 compile_options |= driver_bug_workarounds_;
164 return compile_options;
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);
177 bool success = false;
179 TRACE_EVENT0("gpu", "ShCompile");
180 const char* const shader_strings[] = { shader_source.c_str() };
181 success = !!ShCompile(
182 compiler_, shader_strings, 1, GetCompileOptions());
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);
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);
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);
216 return success;
219 std::string ShaderTranslator::GetStringForOptionsThatWouldAffectCompilation()
220 const {
221 DCHECK(compiler_ != NULL);
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]);
228 ShGetBuiltInResourcesString(compiler_, resource_len, resource_str.get());
230 return std::string(":CompileOptions:" +
231 base::IntToString(GetCompileOptions())) +
232 std::string(resource_str.get());
235 void ShaderTranslator::AddDestructionObserver(
236 DestructionObserver* observer) {
237 destruction_observers_.AddObserver(observer);
240 void ShaderTranslator::RemoveDestructionObserver(
241 DestructionObserver* observer) {
242 destruction_observers_.RemoveObserver(observer);
245 ShaderTranslator::~ShaderTranslator() {
246 FOR_EACH_OBSERVER(DestructionObserver,
247 destruction_observers_,
248 OnDestruct(this));
250 if (compiler_ != NULL)
251 ShDestruct(compiler_);
254 } // namespace gles2
255 } // namespace gpu