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