Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / gpu / command_buffer / service / program_manager.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/program_manager.h"
6
7 #include <algorithm>
8 #include <set>
9 #include <utility>
10 #include <vector>
11
12 #include "base/basictypes.h"
13 #include "base/command_line.h"
14 #include "base/logging.h"
15 #include "base/memory/scoped_ptr.h"
16 #include "base/metrics/histogram.h"
17 #include "base/strings/string_number_conversions.h"
18 #include "base/strings/string_util.h"
19 #include "base/time/time.h"
20 #include "gpu/command_buffer/common/gles2_cmd_format.h"
21 #include "gpu/command_buffer/common/gles2_cmd_utils.h"
22 #include "gpu/command_buffer/service/gles2_cmd_decoder.h"
23 #include "gpu/command_buffer/service/gpu_switches.h"
24 #include "gpu/command_buffer/service/program_cache.h"
25 #include "gpu/command_buffer/service/shader_manager.h"
26 #include "gpu/command_buffer/service/shader_translator.h"
27 #include "third_party/re2/re2/re2.h"
28
29 using base::TimeDelta;
30 using base::TimeTicks;
31
32 namespace gpu {
33 namespace gles2 {
34
35 namespace {
36
37 int ShaderTypeToIndex(GLenum shader_type) {
38   switch (shader_type) {
39     case GL_VERTEX_SHADER:
40       return 0;
41     case GL_FRAGMENT_SHADER:
42       return 1;
43     default:
44       NOTREACHED();
45       return 0;
46   }
47 }
48
49 // Given a name like "foo.bar[123].moo[456]" sets new_name to "foo.bar[123].moo"
50 // and sets element_index to 456. returns false if element expression was not a
51 // whole decimal number. For example: "foo[1b2]"
52 bool GetUniformNameSansElement(
53     const std::string& name, int* element_index, std::string* new_name) {
54   DCHECK(element_index);
55   DCHECK(new_name);
56   if (name.size() < 3 || name[name.size() - 1] != ']') {
57     *element_index = 0;
58     *new_name = name;
59     return true;
60   }
61
62   // Look for an array specification.
63   size_t open_pos = name.find_last_of('[');
64   if (open_pos == std::string::npos ||
65       open_pos >= name.size() - 2) {
66     return false;
67   }
68
69   GLint index = 0;
70   size_t last = name.size() - 1;
71   for (size_t pos = open_pos + 1; pos < last; ++pos) {
72     int8 digit = name[pos] - '0';
73     if (digit < 0 || digit > 9) {
74       return false;
75     }
76     index = index * 10 + digit;
77   }
78
79   *element_index = index;
80   *new_name = name.substr(0, open_pos);
81   return true;
82 }
83
84 bool IsBuiltInFragmentVarying(const std::string& name) {
85   // Built-in variables for fragment shaders.
86   const char* kBuiltInVaryings[] = {
87       "gl_FragCoord",
88       "gl_FrontFacing",
89       "gl_PointCoord"
90   };
91   for (size_t ii = 0; ii < arraysize(kBuiltInVaryings); ++ii) {
92     if (name == kBuiltInVaryings[ii])
93       return true;
94   }
95   return false;
96 }
97
98 bool IsBuiltInInvariant(
99     const VaryingMap& varyings, const std::string& name) {
100   VaryingMap::const_iterator hit = varyings.find(name);
101   if (hit == varyings.end())
102     return false;
103   return hit->second.isInvariant;
104 }
105
106 }  // anonymous namespace.
107
108 Program::UniformInfo::UniformInfo()
109     : size(0),
110       type(GL_NONE),
111       fake_location_base(0),
112       is_array(false) {
113 }
114
115 Program::UniformInfo::UniformInfo(GLsizei _size,
116                                   GLenum _type,
117                                   int _fake_location_base,
118                                   const std::string& _name)
119     : size(_size),
120       type(_type),
121       accepts_api_type(0),
122       fake_location_base(_fake_location_base),
123       is_array(false),
124       name(_name) {
125   switch (type) {
126     case GL_INT:
127       accepts_api_type = kUniform1i;
128       break;
129     case GL_INT_VEC2:
130       accepts_api_type = kUniform2i;
131       break;
132     case GL_INT_VEC3:
133       accepts_api_type = kUniform3i;
134       break;
135     case GL_INT_VEC4:
136       accepts_api_type = kUniform4i;
137       break;
138
139     case GL_BOOL:
140       accepts_api_type = kUniform1i | kUniform1f;
141       break;
142     case GL_BOOL_VEC2:
143       accepts_api_type = kUniform2i | kUniform2f;
144       break;
145     case GL_BOOL_VEC3:
146       accepts_api_type = kUniform3i | kUniform3f;
147       break;
148     case GL_BOOL_VEC4:
149       accepts_api_type = kUniform4i | kUniform4f;
150       break;
151
152     case GL_FLOAT:
153       accepts_api_type = kUniform1f;
154       break;
155     case GL_FLOAT_VEC2:
156       accepts_api_type = kUniform2f;
157       break;
158     case GL_FLOAT_VEC3:
159       accepts_api_type = kUniform3f;
160       break;
161     case GL_FLOAT_VEC4:
162       accepts_api_type = kUniform4f;
163       break;
164
165     case GL_FLOAT_MAT2:
166       accepts_api_type = kUniformMatrix2f;
167       break;
168     case GL_FLOAT_MAT3:
169       accepts_api_type = kUniformMatrix3f;
170       break;
171     case GL_FLOAT_MAT4:
172       accepts_api_type = kUniformMatrix4f;
173       break;
174
175     case GL_SAMPLER_2D:
176     case GL_SAMPLER_2D_RECT_ARB:
177     case GL_SAMPLER_CUBE:
178     case GL_SAMPLER_3D_OES:
179     case GL_SAMPLER_EXTERNAL_OES:
180       accepts_api_type = kUniform1i;
181       break;
182     default:
183       NOTREACHED() << "Unhandled UniformInfo type " << type;
184       break;
185   }
186 }
187
188 Program::UniformInfo::~UniformInfo() {}
189
190 bool ProgramManager::IsInvalidPrefix(const char* name, size_t length) {
191   static const char kInvalidPrefix[] = { 'g', 'l', '_' };
192   return (length >= sizeof(kInvalidPrefix) &&
193       memcmp(name, kInvalidPrefix, sizeof(kInvalidPrefix)) == 0);
194 }
195
196 Program::Program(ProgramManager* manager, GLuint service_id)
197     : manager_(manager),
198       use_count_(0),
199       max_attrib_name_length_(0),
200       max_uniform_name_length_(0),
201       service_id_(service_id),
202       deleted_(false),
203       valid_(false),
204       link_status_(false),
205       uniforms_cleared_(false),
206       num_uniforms_(0) {
207   manager_->StartTracking(this);
208 }
209
210 void Program::Reset() {
211   valid_ = false;
212   link_status_ = false;
213   num_uniforms_ = 0;
214   max_uniform_name_length_ = 0;
215   max_attrib_name_length_ = 0;
216   attrib_infos_.clear();
217   uniform_infos_.clear();
218   sampler_indices_.clear();
219   attrib_location_to_index_map_.clear();
220 }
221
222 std::string Program::ProcessLogInfo(
223     const std::string& log) {
224   std::string output;
225   re2::StringPiece input(log);
226   std::string prior_log;
227   std::string hashed_name;
228   while (RE2::Consume(&input,
229                       "(.*?)(webgl_[0123456789abcdefABCDEF]+)",
230                       &prior_log,
231                       &hashed_name)) {
232     output += prior_log;
233
234     const std::string* original_name =
235         GetOriginalNameFromHashedName(hashed_name);
236     if (original_name)
237       output += *original_name;
238     else
239       output += hashed_name;
240   }
241
242   return output + input.as_string();
243 }
244
245 void Program::UpdateLogInfo() {
246   GLint max_len = 0;
247   glGetProgramiv(service_id_, GL_INFO_LOG_LENGTH, &max_len);
248   if (max_len == 0) {
249     set_log_info(NULL);
250     return;
251   }
252   scoped_ptr<char[]> temp(new char[max_len]);
253   GLint len = 0;
254   glGetProgramInfoLog(service_id_, max_len, &len, temp.get());
255   DCHECK(max_len == 0 || len < max_len);
256   DCHECK(len == 0 || temp[len] == '\0');
257   std::string log(temp.get(), len);
258   set_log_info(ProcessLogInfo(log).c_str());
259 }
260
261 void Program::ClearUniforms(
262     std::vector<uint8>* zero_buffer) {
263   DCHECK(zero_buffer);
264   if (uniforms_cleared_) {
265     return;
266   }
267   uniforms_cleared_ = true;
268   for (size_t ii = 0; ii < uniform_infos_.size(); ++ii) {
269     const UniformInfo& uniform_info = uniform_infos_[ii];
270     if (!uniform_info.IsValid()) {
271       continue;
272     }
273     GLint location = uniform_info.element_locations[0];
274     GLsizei size = uniform_info.size;
275     uint32 unit_size =  GLES2Util::GetGLDataTypeSizeForUniforms(
276         uniform_info.type);
277     uint32 size_needed = size * unit_size;
278     if (size_needed > zero_buffer->size()) {
279       zero_buffer->resize(size_needed, 0u);
280     }
281     const void* zero = &(*zero_buffer)[0];
282     switch (uniform_info.type) {
283     case GL_FLOAT:
284       glUniform1fv(location, size, reinterpret_cast<const GLfloat*>(zero));
285       break;
286     case GL_FLOAT_VEC2:
287       glUniform2fv(location, size, reinterpret_cast<const GLfloat*>(zero));
288       break;
289     case GL_FLOAT_VEC3:
290       glUniform3fv(location, size, reinterpret_cast<const GLfloat*>(zero));
291       break;
292     case GL_FLOAT_VEC4:
293       glUniform4fv(location, size, reinterpret_cast<const GLfloat*>(zero));
294       break;
295     case GL_INT:
296     case GL_BOOL:
297     case GL_SAMPLER_2D:
298     case GL_SAMPLER_CUBE:
299     case GL_SAMPLER_EXTERNAL_OES:
300     case GL_SAMPLER_3D_OES:
301     case GL_SAMPLER_2D_RECT_ARB:
302       glUniform1iv(location, size, reinterpret_cast<const GLint*>(zero));
303       break;
304     case GL_INT_VEC2:
305     case GL_BOOL_VEC2:
306       glUniform2iv(location, size, reinterpret_cast<const GLint*>(zero));
307       break;
308     case GL_INT_VEC3:
309     case GL_BOOL_VEC3:
310       glUniform3iv(location, size, reinterpret_cast<const GLint*>(zero));
311       break;
312     case GL_INT_VEC4:
313     case GL_BOOL_VEC4:
314       glUniform4iv(location, size, reinterpret_cast<const GLint*>(zero));
315       break;
316     case GL_FLOAT_MAT2:
317       glUniformMatrix2fv(
318           location, size, false, reinterpret_cast<const GLfloat*>(zero));
319       break;
320     case GL_FLOAT_MAT3:
321       glUniformMatrix3fv(
322           location, size, false, reinterpret_cast<const GLfloat*>(zero));
323       break;
324     case GL_FLOAT_MAT4:
325       glUniformMatrix4fv(
326           location, size, false, reinterpret_cast<const GLfloat*>(zero));
327       break;
328     default:
329       NOTREACHED();
330       break;
331     }
332   }
333 }
334
335 namespace {
336
337 struct UniformData {
338   UniformData() : size(-1), type(GL_NONE), location(0), added(false) {
339   }
340   std::string queried_name;
341   std::string corrected_name;
342   std::string original_name;
343   GLsizei size;
344   GLenum type;
345   GLint location;
346   bool added;
347 };
348
349 struct UniformDataComparer {
350   bool operator()(const UniformData& lhs, const UniformData& rhs) const {
351     return lhs.queried_name < rhs.queried_name;
352   }
353 };
354
355 }  // anonymous namespace
356
357 void Program::Update() {
358   Reset();
359   UpdateLogInfo();
360   link_status_ = true;
361   uniforms_cleared_ = false;
362   GLint num_attribs = 0;
363   GLint max_len = 0;
364   GLint max_location = -1;
365   glGetProgramiv(service_id_, GL_ACTIVE_ATTRIBUTES, &num_attribs);
366   glGetProgramiv(service_id_, GL_ACTIVE_ATTRIBUTE_MAX_LENGTH, &max_len);
367   // TODO(gman): Should we check for error?
368   scoped_ptr<char[]> name_buffer(new char[max_len]);
369   for (GLint ii = 0; ii < num_attribs; ++ii) {
370     GLsizei length = 0;
371     GLsizei size = 0;
372     GLenum type = 0;
373     glGetActiveAttrib(
374         service_id_, ii, max_len, &length, &size, &type, name_buffer.get());
375     DCHECK(max_len == 0 || length < max_len);
376     DCHECK(length == 0 || name_buffer[length] == '\0');
377     if (!ProgramManager::IsInvalidPrefix(name_buffer.get(), length)) {
378       std::string original_name;
379       GetVertexAttribData(name_buffer.get(), &original_name, &type);
380       // TODO(gman): Should we check for error?
381       GLint location = glGetAttribLocation(service_id_, name_buffer.get());
382       if (location > max_location) {
383         max_location = location;
384       }
385       attrib_infos_.push_back(
386           VertexAttrib(1, type, original_name, location));
387       max_attrib_name_length_ = std::max(
388           max_attrib_name_length_, static_cast<GLsizei>(original_name.size()));
389     }
390   }
391
392   // Create attrib location to index map.
393   attrib_location_to_index_map_.resize(max_location + 1);
394   for (GLint ii = 0; ii <= max_location; ++ii) {
395     attrib_location_to_index_map_[ii] = -1;
396   }
397   for (size_t ii = 0; ii < attrib_infos_.size(); ++ii) {
398     const VertexAttrib& info = attrib_infos_[ii];
399     attrib_location_to_index_map_[info.location] = ii;
400   }
401
402 #if !defined(NDEBUG)
403   if (CommandLine::ForCurrentProcess()->HasSwitch(
404       switches::kEnableGPUServiceLoggingGPU)) {
405     DVLOG(1) << "----: attribs for service_id: " << service_id();
406     for (size_t ii = 0; ii < attrib_infos_.size(); ++ii) {
407       const VertexAttrib& info = attrib_infos_[ii];
408       DVLOG(1) << ii << ": loc = " << info.location
409                << ", size = " << info.size
410                << ", type = " << GLES2Util::GetStringEnum(info.type)
411                << ", name = " << info.name;
412     }
413   }
414 #endif
415
416   max_len = 0;
417   GLint num_uniforms = 0;
418   glGetProgramiv(service_id_, GL_ACTIVE_UNIFORMS, &num_uniforms);
419   glGetProgramiv(service_id_, GL_ACTIVE_UNIFORM_MAX_LENGTH, &max_len);
420   name_buffer.reset(new char[max_len]);
421
422   // Reads all the names.
423   std::vector<UniformData> uniform_data;
424   for (GLint ii = 0; ii < num_uniforms; ++ii) {
425     GLsizei length = 0;
426     UniformData data;
427     glGetActiveUniform(
428         service_id_, ii, max_len, &length,
429         &data.size, &data.type, name_buffer.get());
430     DCHECK(max_len == 0 || length < max_len);
431     DCHECK(length == 0 || name_buffer[length] == '\0');
432     if (!ProgramManager::IsInvalidPrefix(name_buffer.get(), length)) {
433       data.queried_name = std::string(name_buffer.get());
434       GetCorrectedUniformData(
435           data.queried_name,
436           &data.corrected_name, &data.original_name, &data.size, &data.type);
437       uniform_data.push_back(data);
438     }
439   }
440
441   // NOTE: We don't care if 2 uniforms are bound to the same location.
442   // One of them will take preference. The spec allows this, same as
443   // BindAttribLocation.
444   //
445   // The reason we don't check is if we were to fail we'd have to
446   // restore the previous program but since we've already linked successfully
447   // at this point the previous program is gone.
448
449   // Assigns the uniforms with bindings.
450   size_t next_available_index = 0;
451   for (size_t ii = 0; ii < uniform_data.size(); ++ii) {
452     UniformData& data = uniform_data[ii];
453     data.location = glGetUniformLocation(
454         service_id_, data.queried_name.c_str());
455     // remove "[0]"
456     std::string short_name;
457     int element_index = 0;
458     bool good = GetUniformNameSansElement(data.queried_name, &element_index,
459                                           &short_name);
460     DCHECK(good);
461     LocationMap::const_iterator it = bind_uniform_location_map_.find(
462         short_name);
463     if (it != bind_uniform_location_map_.end()) {
464       data.added = AddUniformInfo(
465           data.size, data.type, data.location, it->second, data.corrected_name,
466           data.original_name, &next_available_index);
467     }
468   }
469
470   // Assigns the uniforms that were not bound.
471   for (size_t ii = 0; ii < uniform_data.size(); ++ii) {
472     const UniformData& data = uniform_data[ii];
473     if (!data.added) {
474       AddUniformInfo(
475           data.size, data.type, data.location, -1, data.corrected_name,
476           data.original_name, &next_available_index);
477     }
478   }
479
480 #if !defined(NDEBUG)
481   if (CommandLine::ForCurrentProcess()->HasSwitch(
482       switches::kEnableGPUServiceLoggingGPU)) {
483     DVLOG(1) << "----: uniforms for service_id: " << service_id();
484     for (size_t ii = 0; ii < uniform_infos_.size(); ++ii) {
485       const UniformInfo& info = uniform_infos_[ii];
486       if (info.IsValid()) {
487         DVLOG(1) << ii << ": loc = " << info.element_locations[0]
488                  << ", size = " << info.size
489                  << ", type = " << GLES2Util::GetStringEnum(info.type)
490                  << ", name = " << info.name;
491       }
492     }
493   }
494 #endif
495
496   valid_ = true;
497 }
498
499 void Program::ExecuteBindAttribLocationCalls() {
500   for (LocationMap::const_iterator it = bind_attrib_location_map_.begin();
501        it != bind_attrib_location_map_.end(); ++it) {
502     const std::string* mapped_name = GetAttribMappedName(it->first);
503     if (mapped_name)
504       glBindAttribLocation(service_id_, it->second, mapped_name->c_str());
505   }
506 }
507
508 bool Program::Link(ShaderManager* manager,
509                    ShaderTranslator* vertex_translator,
510                    ShaderTranslator* fragment_translator,
511                    Program::VaryingsPackingOption varyings_packing_option,
512                    const ShaderCacheCallback& shader_callback) {
513   ClearLinkStatus();
514   if (!CanLink()) {
515     set_log_info("missing shaders");
516     return false;
517   }
518   if (DetectAttribLocationBindingConflicts()) {
519     set_log_info("glBindAttribLocation() conflicts");
520     return false;
521   }
522   std::string conflicting_name;
523   if (DetectUniformsMismatch(&conflicting_name)) {
524     std::string info_log = "Uniforms with the same name but different "
525                            "type/precision: " + conflicting_name;
526     set_log_info(ProcessLogInfo(info_log).c_str());
527     return false;
528   }
529   if (DetectVaryingsMismatch(&conflicting_name)) {
530     std::string info_log = "Varyings with the same name but different type, "
531                            "or statically used varyings in fragment shader are "
532                            "not declared in vertex shader: " + conflicting_name;
533     set_log_info(ProcessLogInfo(info_log).c_str());
534     return false;
535   }
536   if (DetectBuiltInInvariantConflicts()) {
537     set_log_info("Invariant settings for certain built-in varyings "
538                  "have to match");
539     return false;
540   }
541   if (DetectGlobalNameConflicts(&conflicting_name)) {
542     std::string info_log = "Name conflicts between an uniform and an "
543                            "attribute: " + conflicting_name;
544     set_log_info(ProcessLogInfo(info_log).c_str());
545     return false;
546   }
547   if (!CheckVaryingsPacking(varyings_packing_option)) {
548     set_log_info("Varyings over maximum register limit");
549     return false;
550   }
551
552   TimeTicks before_time = TimeTicks::HighResNow();
553   bool link = true;
554   ProgramCache* cache = manager_->program_cache_;
555   if (cache) {
556     DCHECK(!attached_shaders_[0]->signature_source().empty() &&
557            !attached_shaders_[1]->signature_source().empty());
558     ProgramCache::LinkedProgramStatus status = cache->GetLinkedProgramStatus(
559         attached_shaders_[0]->signature_source(),
560         vertex_translator,
561         attached_shaders_[1]->signature_source(),
562         fragment_translator,
563         &bind_attrib_location_map_);
564
565     if (status == ProgramCache::LINK_SUCCEEDED) {
566       ProgramCache::ProgramLoadResult success =
567           cache->LoadLinkedProgram(service_id(),
568                                    attached_shaders_[0].get(),
569                                    vertex_translator,
570                                    attached_shaders_[1].get(),
571                                    fragment_translator,
572                                    &bind_attrib_location_map_,
573                                    shader_callback);
574       link = success != ProgramCache::PROGRAM_LOAD_SUCCESS;
575       UMA_HISTOGRAM_BOOLEAN("GPU.ProgramCache.LoadBinarySuccess", !link);
576     }
577   }
578
579   if (link) {
580     ExecuteBindAttribLocationCalls();
581     before_time = TimeTicks::HighResNow();
582     if (cache && gfx::g_driver_gl.ext.b_GL_ARB_get_program_binary) {
583       glProgramParameteri(service_id(),
584                           PROGRAM_BINARY_RETRIEVABLE_HINT,
585                           GL_TRUE);
586     }
587     glLinkProgram(service_id());
588   }
589
590   GLint success = 0;
591   glGetProgramiv(service_id(), GL_LINK_STATUS, &success);
592   if (success == GL_TRUE) {
593     Update();
594     if (link) {
595       if (cache) {
596         cache->SaveLinkedProgram(service_id(),
597                                  attached_shaders_[0].get(),
598                                  vertex_translator,
599                                  attached_shaders_[1].get(),
600                                  fragment_translator,
601                                  &bind_attrib_location_map_,
602                                  shader_callback);
603       }
604       UMA_HISTOGRAM_CUSTOM_COUNTS(
605           "GPU.ProgramCache.BinaryCacheMissTime",
606           static_cast<base::HistogramBase::Sample>(
607               (TimeTicks::HighResNow() - before_time).InMicroseconds()),
608           0,
609           static_cast<base::HistogramBase::Sample>(
610               TimeDelta::FromSeconds(10).InMicroseconds()),
611           50);
612     } else {
613       UMA_HISTOGRAM_CUSTOM_COUNTS(
614           "GPU.ProgramCache.BinaryCacheHitTime",
615           static_cast<base::HistogramBase::Sample>(
616               (TimeTicks::HighResNow() - before_time).InMicroseconds()),
617           0,
618           static_cast<base::HistogramBase::Sample>(
619               TimeDelta::FromSeconds(1).InMicroseconds()),
620           50);
621     }
622   } else {
623     UpdateLogInfo();
624   }
625   return success == GL_TRUE;
626 }
627
628 void Program::Validate() {
629   if (!IsValid()) {
630     set_log_info("program not linked");
631     return;
632   }
633   glValidateProgram(service_id());
634   UpdateLogInfo();
635 }
636
637 GLint Program::GetUniformFakeLocation(
638     const std::string& name) const {
639   bool getting_array_location = false;
640   size_t open_pos = std::string::npos;
641   int index = 0;
642   if (!GLES2Util::ParseUniformName(
643       name, &open_pos, &index, &getting_array_location)) {
644     return -1;
645   }
646   for (GLuint ii = 0; ii < uniform_infos_.size(); ++ii) {
647     const UniformInfo& info = uniform_infos_[ii];
648     if (!info.IsValid()) {
649       continue;
650     }
651     if (info.name == name ||
652         (info.is_array &&
653          info.name.compare(0, info.name.size() - 3, name) == 0)) {
654       return info.fake_location_base;
655     } else if (getting_array_location && info.is_array) {
656       // Look for an array specification.
657       size_t open_pos_2 = info.name.find_last_of('[');
658       if (open_pos_2 == open_pos &&
659           name.compare(0, open_pos, info.name, 0, open_pos) == 0) {
660         if (index >= 0 && index < info.size) {
661           DCHECK_GT(static_cast<int>(info.element_locations.size()), index);
662           if (info.element_locations[index] == -1)
663             return -1;
664           return ProgramManager::MakeFakeLocation(
665               info.fake_location_base, index);
666         }
667       }
668     }
669   }
670   return -1;
671 }
672
673 GLint Program::GetAttribLocation(
674     const std::string& original_name) const {
675   for (GLuint ii = 0; ii < attrib_infos_.size(); ++ii) {
676     const VertexAttrib& info = attrib_infos_[ii];
677     if (info.name == original_name) {
678       return info.location;
679     }
680   }
681   return -1;
682 }
683
684 const Program::UniformInfo*
685     Program::GetUniformInfoByFakeLocation(
686         GLint fake_location, GLint* real_location, GLint* array_index) const {
687   DCHECK(real_location);
688   DCHECK(array_index);
689   if (fake_location < 0) {
690     return NULL;
691   }
692
693   GLint uniform_index = GetUniformInfoIndexFromFakeLocation(fake_location);
694   if (uniform_index >= 0 &&
695       static_cast<size_t>(uniform_index) < uniform_infos_.size()) {
696     const UniformInfo& uniform_info = uniform_infos_[uniform_index];
697     if (!uniform_info.IsValid()) {
698       return NULL;
699     }
700     GLint element_index = GetArrayElementIndexFromFakeLocation(fake_location);
701     if (element_index < uniform_info.size) {
702       *real_location = uniform_info.element_locations[element_index];
703       *array_index = element_index;
704       return &uniform_info;
705     }
706   }
707   return NULL;
708 }
709
710 const std::string* Program::GetAttribMappedName(
711     const std::string& original_name) const {
712   for (int ii = 0; ii < kMaxAttachedShaders; ++ii) {
713     Shader* shader = attached_shaders_[ii].get();
714     if (shader) {
715       const std::string* mapped_name =
716           shader->GetAttribMappedName(original_name);
717       if (mapped_name)
718         return mapped_name;
719     }
720   }
721   return NULL;
722 }
723
724 const std::string* Program::GetOriginalNameFromHashedName(
725     const std::string& hashed_name) const {
726   for (int ii = 0; ii < kMaxAttachedShaders; ++ii) {
727     Shader* shader = attached_shaders_[ii].get();
728     if (shader) {
729       const std::string* original_name =
730           shader->GetOriginalNameFromHashedName(hashed_name);
731       if (original_name)
732         return original_name;
733     }
734   }
735   return NULL;
736 }
737
738 bool Program::SetUniformLocationBinding(
739     const std::string& name, GLint location) {
740   std::string short_name;
741   int element_index = 0;
742   if (!GetUniformNameSansElement(name, &element_index, &short_name) ||
743       element_index != 0) {
744     return false;
745   }
746
747   bind_uniform_location_map_[short_name] = location;
748   return true;
749 }
750
751 // Note: This is only valid to call right after a program has been linked
752 // successfully.
753 void Program::GetCorrectedUniformData(
754     const std::string& name,
755     std::string* corrected_name, std::string* original_name,
756     GLsizei* size, GLenum* type) const {
757   DCHECK(corrected_name && original_name && size && type);
758   for (int ii = 0; ii < kMaxAttachedShaders; ++ii) {
759     Shader* shader = attached_shaders_[ii].get();
760     if (!shader)
761       continue;
762     const sh::ShaderVariable* info = NULL;
763     const sh::Uniform* uniform = shader->GetUniformInfo(name);
764     bool found = false;
765     if (uniform)
766       found = uniform->findInfoByMappedName(name, &info, original_name);
767     if (found) {
768       const std::string kArraySpec("[0]");
769       if (info->arraySize > 0 && !EndsWith(name, kArraySpec, true)) {
770         *corrected_name = name + kArraySpec;
771         *original_name += kArraySpec;
772       } else {
773         *corrected_name = name;
774       }
775       *type = info->type;
776       *size = std::max(1u, info->arraySize);
777       return;
778     }
779   }
780   // TODO(zmo): this path should never be reached unless there is a serious
781   // bug in the driver or in ANGLE translator.
782   *corrected_name = name;
783   *original_name = name;
784 }
785
786 void Program::GetVertexAttribData(
787     const std::string& name, std::string* original_name, GLenum* type) const {
788   DCHECK(original_name);
789   DCHECK(type);
790   Shader* shader = attached_shaders_[ShaderTypeToIndex(GL_VERTEX_SHADER)].get();
791   if (shader) {
792     // Vertex attributes can not be arrays or structs (GLSL ES 3.00.4, section
793     // 4.3.4, "Input Variables"), so the top level sh::Attribute returns the
794     // information we need.
795     const sh::Attribute* info = shader->GetAttribInfo(name);
796     if (info) {
797       *original_name = info->name;
798       *type = info->type;
799       return;
800     }
801   }
802   // TODO(zmo): this path should never be reached unless there is a serious
803   // bug in the driver or in ANGLE translator.
804   *original_name = name;
805 }
806
807 bool Program::AddUniformInfo(
808         GLsizei size, GLenum type, GLint location, GLint fake_base_location,
809         const std::string& name, const std::string& original_name,
810         size_t* next_available_index) {
811   DCHECK(next_available_index);
812   const char* kArraySpec = "[0]";
813   size_t uniform_index =
814       fake_base_location >= 0 ? fake_base_location : *next_available_index;
815   if (uniform_infos_.size() < uniform_index + 1) {
816     uniform_infos_.resize(uniform_index + 1);
817   }
818
819   // return if this location is already in use.
820   if (uniform_infos_[uniform_index].IsValid()) {
821     DCHECK_GE(fake_base_location, 0);
822     return false;
823   }
824
825   uniform_infos_[uniform_index] = UniformInfo(
826       size, type, uniform_index, original_name);
827   ++num_uniforms_;
828
829   UniformInfo& info = uniform_infos_[uniform_index];
830   info.element_locations.resize(size);
831   info.element_locations[0] = location;
832   DCHECK_GE(size, 0);
833   size_t num_texture_units = info.IsSampler() ? static_cast<size_t>(size) : 0u;
834   info.texture_units.clear();
835   info.texture_units.resize(num_texture_units, 0);
836
837   if (size > 1) {
838     // Go through the array element locations looking for a match.
839     // We can skip the first element because it's the same as the
840     // the location without the array operators.
841     size_t array_pos = name.rfind(kArraySpec);
842     std::string base_name = name;
843     if (name.size() > 3) {
844       if (array_pos != name.size() - 3) {
845         info.name = name + kArraySpec;
846       } else {
847         base_name = name.substr(0, name.size() - 3);
848       }
849     }
850     for (GLsizei ii = 1; ii < info.size; ++ii) {
851       std::string element_name(base_name + "[" + base::IntToString(ii) + "]");
852       info.element_locations[ii] =
853           glGetUniformLocation(service_id_, element_name.c_str());
854     }
855   }
856
857   info.is_array =
858      (size > 1 ||
859       (info.name.size() > 3 &&
860        info.name.rfind(kArraySpec) == info.name.size() - 3));
861
862   if (info.IsSampler()) {
863     sampler_indices_.push_back(info.fake_location_base);
864   }
865   max_uniform_name_length_ =
866       std::max(max_uniform_name_length_,
867                static_cast<GLsizei>(info.name.size()));
868
869   while (*next_available_index < uniform_infos_.size() &&
870          uniform_infos_[*next_available_index].IsValid()) {
871     *next_available_index = *next_available_index + 1;
872   }
873
874   return true;
875 }
876
877 const Program::UniformInfo*
878     Program::GetUniformInfo(
879         GLint index) const {
880   if (static_cast<size_t>(index) >= uniform_infos_.size()) {
881     return NULL;
882   }
883
884   const UniformInfo& info = uniform_infos_[index];
885   return info.IsValid() ? &info : NULL;
886 }
887
888 bool Program::SetSamplers(
889     GLint num_texture_units, GLint fake_location,
890     GLsizei count, const GLint* value) {
891   if (fake_location < 0) {
892     return true;
893   }
894   GLint uniform_index = GetUniformInfoIndexFromFakeLocation(fake_location);
895   if (uniform_index >= 0 &&
896       static_cast<size_t>(uniform_index) < uniform_infos_.size()) {
897     UniformInfo& info = uniform_infos_[uniform_index];
898     if (!info.IsValid()) {
899       return false;
900     }
901     GLint element_index = GetArrayElementIndexFromFakeLocation(fake_location);
902     if (element_index < info.size) {
903       count = std::min(info.size - element_index, count);
904       if (info.IsSampler() && count > 0) {
905         for (GLsizei ii = 0; ii < count; ++ii) {
906           if (value[ii] < 0 || value[ii] >= num_texture_units) {
907             return false;
908           }
909         }
910         std::copy(value, value + count,
911                   info.texture_units.begin() + element_index);
912         return true;
913       }
914     }
915   }
916   return true;
917 }
918
919 void Program::GetProgramiv(GLenum pname, GLint* params) {
920   switch (pname) {
921     case GL_ACTIVE_ATTRIBUTES:
922       *params = attrib_infos_.size();
923       break;
924     case GL_ACTIVE_ATTRIBUTE_MAX_LENGTH:
925       // Notice +1 to accomodate NULL terminator.
926       *params = max_attrib_name_length_ + 1;
927       break;
928     case GL_ACTIVE_UNIFORMS:
929       *params = num_uniforms_;
930       break;
931     case GL_ACTIVE_UNIFORM_MAX_LENGTH:
932       // Notice +1 to accomodate NULL terminator.
933       *params = max_uniform_name_length_ + 1;
934       break;
935     case GL_LINK_STATUS:
936       *params = link_status_;
937       break;
938     case GL_INFO_LOG_LENGTH:
939       // Notice +1 to accomodate NULL terminator.
940       *params = log_info_.get() ? (log_info_->size() + 1) : 0;
941       break;
942     case GL_DELETE_STATUS:
943       *params = deleted_;
944       break;
945     case GL_VALIDATE_STATUS:
946       if (!IsValid()) {
947         *params = GL_FALSE;
948       } else {
949         glGetProgramiv(service_id_, pname, params);
950       }
951       break;
952     default:
953       glGetProgramiv(service_id_, pname, params);
954       break;
955   }
956 }
957
958 bool Program::AttachShader(
959     ShaderManager* shader_manager,
960     Shader* shader) {
961   DCHECK(shader_manager);
962   DCHECK(shader);
963   int index = ShaderTypeToIndex(shader->shader_type());
964   if (attached_shaders_[index].get() != NULL) {
965     return false;
966   }
967   attached_shaders_[index] = scoped_refptr<Shader>(shader);
968   shader_manager->UseShader(shader);
969   return true;
970 }
971
972 bool Program::DetachShader(
973     ShaderManager* shader_manager,
974     Shader* shader) {
975   DCHECK(shader_manager);
976   DCHECK(shader);
977   if (attached_shaders_[ShaderTypeToIndex(shader->shader_type())].get() !=
978       shader) {
979     return false;
980   }
981   attached_shaders_[ShaderTypeToIndex(shader->shader_type())] = NULL;
982   shader_manager->UnuseShader(shader);
983   return true;
984 }
985
986 void Program::DetachShaders(ShaderManager* shader_manager) {
987   DCHECK(shader_manager);
988   for (int ii = 0; ii < kMaxAttachedShaders; ++ii) {
989     if (attached_shaders_[ii].get()) {
990       DetachShader(shader_manager, attached_shaders_[ii].get());
991     }
992   }
993 }
994
995 bool Program::CanLink() const {
996   for (int ii = 0; ii < kMaxAttachedShaders; ++ii) {
997     if (!attached_shaders_[ii].get() || !attached_shaders_[ii]->valid()) {
998       return false;
999     }
1000   }
1001   return true;
1002 }
1003
1004 bool Program::DetectAttribLocationBindingConflicts() const {
1005   std::set<GLint> location_binding_used;
1006   for (LocationMap::const_iterator it = bind_attrib_location_map_.begin();
1007        it != bind_attrib_location_map_.end(); ++it) {
1008     // Find out if an attribute is statically used in this program's shaders.
1009     const sh::Attribute* attrib = NULL;
1010     const std::string* mapped_name = GetAttribMappedName(it->first);
1011     if (!mapped_name)
1012       continue;
1013     for (int ii = 0; ii < kMaxAttachedShaders; ++ii) {
1014       if (!attached_shaders_[ii].get() || !attached_shaders_[ii]->valid())
1015         continue;
1016       attrib = attached_shaders_[ii]->GetAttribInfo(*mapped_name);
1017       if (attrib) {
1018         if (attrib->staticUse)
1019           break;
1020         else
1021           attrib = NULL;
1022       }
1023     }
1024     if (attrib) {
1025       size_t num_of_locations = 1;
1026       switch (attrib->type) {
1027         case GL_FLOAT_MAT2:
1028           num_of_locations = 2;
1029           break;
1030         case GL_FLOAT_MAT3:
1031           num_of_locations = 3;
1032           break;
1033         case GL_FLOAT_MAT4:
1034           num_of_locations = 4;
1035           break;
1036         default:
1037           break;
1038       }
1039       for (size_t ii = 0; ii < num_of_locations; ++ii) {
1040         GLint loc = it->second + ii;
1041         std::pair<std::set<GLint>::iterator, bool> result =
1042             location_binding_used.insert(loc);
1043         if (!result.second)
1044           return true;
1045       }
1046     }
1047   }
1048   return false;
1049 }
1050
1051 bool Program::DetectUniformsMismatch(std::string* conflicting_name) const {
1052   typedef std::map<std::string, const sh::Uniform*> UniformPointerMap;
1053   UniformPointerMap uniform_pointer_map;
1054   for (int ii = 0; ii < kMaxAttachedShaders; ++ii) {
1055     const UniformMap& shader_uniforms = attached_shaders_[ii]->uniform_map();
1056     for (UniformMap::const_iterator iter = shader_uniforms.begin();
1057          iter != shader_uniforms.end(); ++iter) {
1058       const std::string& name = iter->first;
1059       UniformPointerMap::iterator hit = uniform_pointer_map.find(name);
1060       if (hit == uniform_pointer_map.end()) {
1061         uniform_pointer_map[name] = &(iter->second);
1062       } else {
1063         // If a uniform is in the map, i.e., it has already been declared by
1064         // another shader, then the type, precision, etc. must match.
1065         if (hit->second->isSameUniformAtLinkTime(iter->second))
1066           continue;
1067         *conflicting_name = name;
1068         return true;
1069       }
1070     }
1071   }
1072   return false;
1073 }
1074
1075 bool Program::DetectVaryingsMismatch(std::string* conflicting_name) const {
1076   DCHECK(attached_shaders_[0].get() &&
1077          attached_shaders_[0]->shader_type() == GL_VERTEX_SHADER &&
1078          attached_shaders_[1].get() &&
1079          attached_shaders_[1]->shader_type() == GL_FRAGMENT_SHADER);
1080   const VaryingMap* vertex_varyings = &(attached_shaders_[0]->varying_map());
1081   const VaryingMap* fragment_varyings = &(attached_shaders_[1]->varying_map());
1082
1083   for (VaryingMap::const_iterator iter = fragment_varyings->begin();
1084        iter != fragment_varyings->end(); ++iter) {
1085     const std::string& name = iter->first;
1086     if (IsBuiltInFragmentVarying(name))
1087       continue;
1088
1089     VaryingMap::const_iterator hit = vertex_varyings->find(name);
1090     if (hit == vertex_varyings->end()) {
1091       if (iter->second.staticUse) {
1092         *conflicting_name = name;
1093         return true;
1094       }
1095       continue;
1096     }
1097
1098     if (!hit->second.isSameVaryingAtLinkTime(iter->second)) {
1099       *conflicting_name = name;
1100       return true;
1101     }
1102
1103   }
1104   return false;
1105 }
1106
1107 bool Program::DetectBuiltInInvariantConflicts() const {
1108   DCHECK(attached_shaders_[0].get() &&
1109          attached_shaders_[0]->shader_type() == GL_VERTEX_SHADER &&
1110          attached_shaders_[1].get() &&
1111          attached_shaders_[1]->shader_type() == GL_FRAGMENT_SHADER);
1112   const VaryingMap& vertex_varyings = attached_shaders_[0]->varying_map();
1113   const VaryingMap& fragment_varyings = attached_shaders_[1]->varying_map();
1114
1115   bool gl_position_invariant = IsBuiltInInvariant(
1116       vertex_varyings, "gl_Position");
1117   bool gl_point_size_invariant = IsBuiltInInvariant(
1118       vertex_varyings, "gl_PointSize");
1119
1120   bool gl_frag_coord_invariant = IsBuiltInInvariant(
1121       fragment_varyings, "gl_FragCoord");
1122   bool gl_point_coord_invariant = IsBuiltInInvariant(
1123       fragment_varyings, "gl_PointCoord");
1124
1125   return ((gl_frag_coord_invariant && !gl_position_invariant) ||
1126           (gl_point_coord_invariant && !gl_point_size_invariant));
1127 }
1128
1129 bool Program::DetectGlobalNameConflicts(std::string* conflicting_name) const {
1130   DCHECK(attached_shaders_[0].get() &&
1131          attached_shaders_[0]->shader_type() == GL_VERTEX_SHADER &&
1132          attached_shaders_[1].get() &&
1133          attached_shaders_[1]->shader_type() == GL_FRAGMENT_SHADER);
1134   const UniformMap* uniforms[2];
1135   uniforms[0] = &(attached_shaders_[0]->uniform_map());
1136   uniforms[1] = &(attached_shaders_[1]->uniform_map());
1137   const AttributeMap* attribs =
1138       &(attached_shaders_[0]->attrib_map());
1139
1140   for (AttributeMap::const_iterator iter = attribs->begin();
1141        iter != attribs->end(); ++iter) {
1142     for (int ii = 0; ii < 2; ++ii) {
1143       if (uniforms[ii]->find(iter->first) != uniforms[ii]->end()) {
1144         *conflicting_name = iter->first;
1145         return true;
1146       }
1147     }
1148   }
1149   return false;
1150 }
1151
1152 bool Program::CheckVaryingsPacking(
1153     Program::VaryingsPackingOption option) const {
1154   DCHECK(attached_shaders_[0].get() &&
1155          attached_shaders_[0]->shader_type() == GL_VERTEX_SHADER &&
1156          attached_shaders_[1].get() &&
1157          attached_shaders_[1]->shader_type() == GL_FRAGMENT_SHADER);
1158   const VaryingMap* vertex_varyings = &(attached_shaders_[0]->varying_map());
1159   const VaryingMap* fragment_varyings = &(attached_shaders_[1]->varying_map());
1160
1161   std::map<std::string, ShVariableInfo> combined_map;
1162
1163   for (VaryingMap::const_iterator iter = fragment_varyings->begin();
1164        iter != fragment_varyings->end(); ++iter) {
1165     if (!iter->second.staticUse && option == kCountOnlyStaticallyUsed)
1166       continue;
1167     if (!IsBuiltInFragmentVarying(iter->first)) {
1168       VaryingMap::const_iterator vertex_iter =
1169           vertex_varyings->find(iter->first);
1170       if (vertex_iter == vertex_varyings->end() ||
1171           (!vertex_iter->second.staticUse &&
1172            option == kCountOnlyStaticallyUsed))
1173         continue;
1174     }
1175
1176     ShVariableInfo var;
1177     var.type = static_cast<sh::GLenum>(iter->second.type);
1178     var.size = std::max(1u, iter->second.arraySize);
1179     combined_map[iter->first] = var;
1180   }
1181
1182   if (combined_map.size() == 0)
1183     return true;
1184   scoped_ptr<ShVariableInfo[]> variables(
1185       new ShVariableInfo[combined_map.size()]);
1186   size_t index = 0;
1187   for (std::map<std::string, ShVariableInfo>::const_iterator iter =
1188            combined_map.begin();
1189        iter != combined_map.end(); ++iter) {
1190     variables[index].type = iter->second.type;
1191     variables[index].size = iter->second.size;
1192     ++index;
1193   }
1194   return ShCheckVariablesWithinPackingLimits(
1195       static_cast<int>(manager_->max_varying_vectors()),
1196       variables.get(),
1197       combined_map.size());
1198 }
1199
1200 static uint32 ComputeOffset(const void* start, const void* position) {
1201   return static_cast<const uint8*>(position) -
1202          static_cast<const uint8*>(start);
1203 }
1204
1205 void Program::GetProgramInfo(
1206     ProgramManager* manager, CommonDecoder::Bucket* bucket) const {
1207   // NOTE: It seems to me the math in here does not need check for overflow
1208   // because the data being calucated from has various small limits. The max
1209   // number of attribs + uniforms is somewhere well under 1024. The maximum size
1210   // of an identifier is 256 characters.
1211   uint32 num_locations = 0;
1212   uint32 total_string_size = 0;
1213
1214   for (size_t ii = 0; ii < attrib_infos_.size(); ++ii) {
1215     const VertexAttrib& info = attrib_infos_[ii];
1216     num_locations += 1;
1217     total_string_size += info.name.size();
1218   }
1219
1220   for (size_t ii = 0; ii < uniform_infos_.size(); ++ii) {
1221     const UniformInfo& info = uniform_infos_[ii];
1222     if (info.IsValid()) {
1223       num_locations += info.element_locations.size();
1224       total_string_size += info.name.size();
1225     }
1226   }
1227
1228   uint32 num_inputs = attrib_infos_.size() + num_uniforms_;
1229   uint32 input_size = num_inputs * sizeof(ProgramInput);
1230   uint32 location_size = num_locations * sizeof(int32);
1231   uint32 size = sizeof(ProgramInfoHeader) +
1232       input_size + location_size + total_string_size;
1233
1234   bucket->SetSize(size);
1235   ProgramInfoHeader* header = bucket->GetDataAs<ProgramInfoHeader*>(0, size);
1236   ProgramInput* inputs = bucket->GetDataAs<ProgramInput*>(
1237       sizeof(ProgramInfoHeader), input_size);
1238   int32* locations = bucket->GetDataAs<int32*>(
1239       sizeof(ProgramInfoHeader) + input_size, location_size);
1240   char* strings = bucket->GetDataAs<char*>(
1241       sizeof(ProgramInfoHeader) + input_size + location_size,
1242       total_string_size);
1243   DCHECK(header);
1244   DCHECK(inputs);
1245   DCHECK(locations);
1246   DCHECK(strings);
1247
1248   header->link_status = link_status_;
1249   header->num_attribs = attrib_infos_.size();
1250   header->num_uniforms = num_uniforms_;
1251
1252   for (size_t ii = 0; ii < attrib_infos_.size(); ++ii) {
1253     const VertexAttrib& info = attrib_infos_[ii];
1254     inputs->size = info.size;
1255     inputs->type = info.type;
1256     inputs->location_offset = ComputeOffset(header, locations);
1257     inputs->name_offset = ComputeOffset(header, strings);
1258     inputs->name_length = info.name.size();
1259     *locations++ = info.location;
1260     memcpy(strings, info.name.c_str(), info.name.size());
1261     strings += info.name.size();
1262     ++inputs;
1263   }
1264
1265   for (size_t ii = 0; ii < uniform_infos_.size(); ++ii) {
1266     const UniformInfo& info = uniform_infos_[ii];
1267     if (info.IsValid()) {
1268       inputs->size = info.size;
1269       inputs->type = info.type;
1270       inputs->location_offset = ComputeOffset(header, locations);
1271       inputs->name_offset = ComputeOffset(header, strings);
1272       inputs->name_length = info.name.size();
1273       DCHECK(static_cast<size_t>(info.size) == info.element_locations.size());
1274       for (size_t jj = 0; jj < info.element_locations.size(); ++jj) {
1275         if (info.element_locations[jj] == -1)
1276           *locations++ = -1;
1277         else
1278           *locations++ = ProgramManager::MakeFakeLocation(ii, jj);
1279       }
1280       memcpy(strings, info.name.c_str(), info.name.size());
1281       strings += info.name.size();
1282       ++inputs;
1283     }
1284   }
1285
1286   DCHECK_EQ(ComputeOffset(header, strings), size);
1287 }
1288
1289 Program::~Program() {
1290   if (manager_) {
1291     if (manager_->have_context_) {
1292       glDeleteProgram(service_id());
1293     }
1294     manager_->StopTracking(this);
1295     manager_ = NULL;
1296   }
1297 }
1298
1299
1300 ProgramManager::ProgramManager(ProgramCache* program_cache,
1301                                uint32 max_varying_vectors)
1302     : program_count_(0),
1303       have_context_(true),
1304       program_cache_(program_cache),
1305       max_varying_vectors_(max_varying_vectors) { }
1306
1307 ProgramManager::~ProgramManager() {
1308   DCHECK(programs_.empty());
1309 }
1310
1311 void ProgramManager::Destroy(bool have_context) {
1312   have_context_ = have_context;
1313   programs_.clear();
1314 }
1315
1316 void ProgramManager::StartTracking(Program* /* program */) {
1317   ++program_count_;
1318 }
1319
1320 void ProgramManager::StopTracking(Program* /* program */) {
1321   --program_count_;
1322 }
1323
1324 Program* ProgramManager::CreateProgram(
1325     GLuint client_id, GLuint service_id) {
1326   std::pair<ProgramMap::iterator, bool> result =
1327       programs_.insert(
1328           std::make_pair(client_id,
1329                          scoped_refptr<Program>(
1330                              new Program(this, service_id))));
1331   DCHECK(result.second);
1332   return result.first->second.get();
1333 }
1334
1335 Program* ProgramManager::GetProgram(GLuint client_id) {
1336   ProgramMap::iterator it = programs_.find(client_id);
1337   return it != programs_.end() ? it->second.get() : NULL;
1338 }
1339
1340 bool ProgramManager::GetClientId(GLuint service_id, GLuint* client_id) const {
1341   // This doesn't need to be fast. It's only used during slow queries.
1342   for (ProgramMap::const_iterator it = programs_.begin();
1343        it != programs_.end(); ++it) {
1344     if (it->second->service_id() == service_id) {
1345       *client_id = it->first;
1346       return true;
1347     }
1348   }
1349   return false;
1350 }
1351
1352 ProgramCache* ProgramManager::program_cache() const {
1353   return program_cache_;
1354 }
1355
1356 bool ProgramManager::IsOwned(Program* program) {
1357   for (ProgramMap::iterator it = programs_.begin();
1358        it != programs_.end(); ++it) {
1359     if (it->second.get() == program) {
1360       return true;
1361     }
1362   }
1363   return false;
1364 }
1365
1366 void ProgramManager::RemoveProgramInfoIfUnused(
1367     ShaderManager* shader_manager, Program* program) {
1368   DCHECK(shader_manager);
1369   DCHECK(program);
1370   DCHECK(IsOwned(program));
1371   if (program->IsDeleted() && !program->InUse()) {
1372     program->DetachShaders(shader_manager);
1373     for (ProgramMap::iterator it = programs_.begin();
1374          it != programs_.end(); ++it) {
1375       if (it->second.get() == program) {
1376         programs_.erase(it);
1377         return;
1378       }
1379     }
1380     NOTREACHED();
1381   }
1382 }
1383
1384 void ProgramManager::MarkAsDeleted(
1385     ShaderManager* shader_manager,
1386     Program* program) {
1387   DCHECK(shader_manager);
1388   DCHECK(program);
1389   DCHECK(IsOwned(program));
1390   program->MarkAsDeleted();
1391   RemoveProgramInfoIfUnused(shader_manager, program);
1392 }
1393
1394 void ProgramManager::UseProgram(Program* program) {
1395   DCHECK(program);
1396   DCHECK(IsOwned(program));
1397   program->IncUseCount();
1398 }
1399
1400 void ProgramManager::UnuseProgram(
1401     ShaderManager* shader_manager,
1402     Program* program) {
1403   DCHECK(shader_manager);
1404   DCHECK(program);
1405   DCHECK(IsOwned(program));
1406   program->DecUseCount();
1407   RemoveProgramInfoIfUnused(shader_manager, program);
1408 }
1409
1410 void ProgramManager::ClearUniforms(Program* program) {
1411   DCHECK(program);
1412   program->ClearUniforms(&zero_);
1413 }
1414
1415 int32 ProgramManager::MakeFakeLocation(int32 index, int32 element) {
1416   return index + element * 0x10000;
1417 }
1418
1419 }  // namespace gles2
1420 }  // namespace gpu