Handle account removal correctly on all platforms.
[chromium-blink-merge.git] / gpu / command_buffer / client / program_info_manager.cc
blobd854aa01f75065353e52a97b1adc91cef2a65e76
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "gpu/command_buffer/client/program_info_manager.h"
7 #include <map>
9 #include "base/compiler_specific.h"
10 #include "base/synchronization/lock.h"
11 #include "gpu/command_buffer/client/gles2_implementation.h"
12 #include "gpu/command_buffer/common/gles2_cmd_utils.h"
14 namespace gpu {
15 namespace gles2 {
17 class NonCachedProgramInfoManager : public ProgramInfoManager {
18 public:
19 NonCachedProgramInfoManager();
20 virtual ~NonCachedProgramInfoManager();
22 virtual void CreateInfo(GLuint program) OVERRIDE;
24 virtual void DeleteInfo(GLuint program) OVERRIDE;
26 virtual bool GetProgramiv(GLES2Implementation* gl,
27 GLuint program,
28 GLenum pname,
29 GLint* params) OVERRIDE;
31 virtual GLint GetAttribLocation(GLES2Implementation* gl,
32 GLuint program,
33 const char* name) OVERRIDE;
35 virtual GLint GetUniformLocation(GLES2Implementation* gl,
36 GLuint program,
37 const char* name) OVERRIDE;
39 virtual bool GetActiveAttrib(GLES2Implementation* gl,
40 GLuint program,
41 GLuint index,
42 GLsizei bufsize,
43 GLsizei* length,
44 GLint* size,
45 GLenum* type,
46 char* name) OVERRIDE;
48 virtual bool GetActiveUniform(GLES2Implementation* gl,
49 GLuint program,
50 GLuint index,
51 GLsizei bufsize,
52 GLsizei* length,
53 GLint* size,
54 GLenum* type,
55 char* name) OVERRIDE;
59 NonCachedProgramInfoManager::NonCachedProgramInfoManager() {
62 NonCachedProgramInfoManager::~NonCachedProgramInfoManager() {
65 void NonCachedProgramInfoManager::CreateInfo(GLuint /* program */) {
68 void NonCachedProgramInfoManager::DeleteInfo(GLuint /* program */) {
71 bool NonCachedProgramInfoManager::GetProgramiv(
72 GLES2Implementation* /* gl */,
73 GLuint /* program */,
74 GLenum /* pname */,
75 GLint* /* params */) {
76 return false;
79 GLint NonCachedProgramInfoManager::GetAttribLocation(
80 GLES2Implementation* gl, GLuint program, const char* name) {
81 return gl->GetAttribLocationHelper(program, name);
84 GLint NonCachedProgramInfoManager::GetUniformLocation(
85 GLES2Implementation* gl, GLuint program, const char* name) {
86 return gl->GetUniformLocationHelper(program, name);
89 bool NonCachedProgramInfoManager::GetActiveAttrib(
90 GLES2Implementation* gl,
91 GLuint program, GLuint index, GLsizei bufsize, GLsizei* length,
92 GLint* size, GLenum* type, char* name) {
93 return gl->GetActiveAttribHelper(
94 program, index, bufsize, length, size, type, name);
97 bool NonCachedProgramInfoManager::GetActiveUniform(
98 GLES2Implementation* gl,
99 GLuint program, GLuint index, GLsizei bufsize, GLsizei* length,
100 GLint* size, GLenum* type, char* name) {
101 return gl->GetActiveUniformHelper(
102 program, index, bufsize, length, size, type, name);
105 class CachedProgramInfoManager : public ProgramInfoManager {
106 public:
107 CachedProgramInfoManager();
108 virtual ~CachedProgramInfoManager();
110 virtual void CreateInfo(GLuint program) OVERRIDE;
112 virtual void DeleteInfo(GLuint program) OVERRIDE;
114 virtual bool GetProgramiv(GLES2Implementation* gl,
115 GLuint program,
116 GLenum pname,
117 GLint* params) OVERRIDE;
119 virtual GLint GetAttribLocation(GLES2Implementation* gl,
120 GLuint program,
121 const char* name) OVERRIDE;
123 virtual GLint GetUniformLocation(GLES2Implementation* gl,
124 GLuint program,
125 const char* name) OVERRIDE;
127 virtual bool GetActiveAttrib(GLES2Implementation* gl,
128 GLuint program,
129 GLuint index,
130 GLsizei bufsize,
131 GLsizei* length,
132 GLint* size,
133 GLenum* type,
134 char* name) OVERRIDE;
136 virtual bool GetActiveUniform(GLES2Implementation* gl,
137 GLuint program,
138 GLuint index,
139 GLsizei bufsize,
140 GLsizei* length,
141 GLint* size,
142 GLenum* type,
143 char* name) OVERRIDE;
145 private:
146 class Program {
147 public:
148 struct UniformInfo {
149 UniformInfo(GLsizei _size, GLenum _type, const std::string& _name);
151 GLsizei size;
152 GLenum type;
153 bool is_array;
154 std::string name;
155 std::vector<GLint> element_locations;
157 struct VertexAttrib {
158 VertexAttrib(GLsizei _size, GLenum _type, const std::string& _name,
159 GLint _location)
160 : size(_size),
161 type(_type),
162 location(_location),
163 name(_name) {
165 GLsizei size;
166 GLenum type;
167 GLint location;
168 std::string name;
171 typedef std::vector<UniformInfo> UniformInfoVector;
172 typedef std::vector<VertexAttrib> AttribInfoVector;
174 Program();
176 const AttribInfoVector& GetAttribInfos() const {
177 return attrib_infos_;
180 const VertexAttrib* GetAttribInfo(GLint index) const {
181 return (static_cast<size_t>(index) < attrib_infos_.size()) ?
182 &attrib_infos_[index] : NULL;
185 GLint GetAttribLocation(const std::string& name) const;
187 const UniformInfo* GetUniformInfo(GLint index) const {
188 return (static_cast<size_t>(index) < uniform_infos_.size()) ?
189 &uniform_infos_[index] : NULL;
192 // Gets the location of a uniform by name.
193 GLint GetUniformLocation(const std::string& name) const;
195 bool GetProgramiv(GLenum pname, GLint* params);
197 // Updates the program info after a successful link.
198 void Update(GLES2Implementation* gl, GLuint program);
200 private:
201 bool cached_;
203 GLsizei max_attrib_name_length_;
205 // Attrib by index.
206 AttribInfoVector attrib_infos_;
208 GLsizei max_uniform_name_length_;
210 // Uniform info by index.
211 UniformInfoVector uniform_infos_;
213 // This is true if glLinkProgram was successful last time it was called.
214 bool link_status_;
217 Program* GetProgramInfo(GLES2Implementation* gl, GLuint program);
219 // TODO(gman): Switch to a faster container.
220 typedef std::map<GLuint, Program> ProgramInfoMap;
222 ProgramInfoMap program_infos_;
224 mutable base::Lock lock_;
227 CachedProgramInfoManager::Program::UniformInfo::UniformInfo(
228 GLsizei _size, GLenum _type, const std::string& _name)
229 : size(_size),
230 type(_type),
231 name(_name) {
232 is_array = (!name.empty() && name[name.size() - 1] == ']');
233 DCHECK(!(size > 1 && !is_array));
236 CachedProgramInfoManager::Program::Program()
237 : cached_(false),
238 max_attrib_name_length_(0),
239 max_uniform_name_length_(0),
240 link_status_(false) {
243 // TODO(gman): Add a faster lookup.
244 GLint CachedProgramInfoManager::Program::GetAttribLocation(
245 const std::string& name) const {
246 for (GLuint ii = 0; ii < attrib_infos_.size(); ++ii) {
247 const VertexAttrib& info = attrib_infos_[ii];
248 if (info.name == name) {
249 return info.location;
252 return -1;
255 GLint CachedProgramInfoManager::Program::GetUniformLocation(
256 const std::string& name) const {
257 bool getting_array_location = false;
258 size_t open_pos = std::string::npos;
259 int index = 0;
260 if (!GLES2Util::ParseUniformName(
261 name, &open_pos, &index, &getting_array_location)) {
262 return -1;
264 for (GLuint ii = 0; ii < uniform_infos_.size(); ++ii) {
265 const UniformInfo& info = uniform_infos_[ii];
266 if (info.name == name ||
267 (info.is_array &&
268 info.name.compare(0, info.name.size() - 3, name) == 0)) {
269 return info.element_locations[0];
270 } else if (getting_array_location && info.is_array) {
271 // Look for an array specification.
272 size_t open_pos_2 = info.name.find_last_of('[');
273 if (open_pos_2 == open_pos &&
274 name.compare(0, open_pos, info.name, 0, open_pos) == 0) {
275 if (index >= 0 && index < info.size) {
276 return info.element_locations[index];
281 return -1;
284 bool CachedProgramInfoManager::Program::GetProgramiv(
285 GLenum pname, GLint* params) {
286 switch (pname) {
287 case GL_LINK_STATUS:
288 *params = link_status_;
289 return true;
290 case GL_ACTIVE_ATTRIBUTES:
291 *params = attrib_infos_.size();
292 return true;
293 case GL_ACTIVE_ATTRIBUTE_MAX_LENGTH:
294 *params = max_attrib_name_length_;
295 return true;
296 case GL_ACTIVE_UNIFORMS:
297 *params = uniform_infos_.size();
298 return true;
299 case GL_ACTIVE_UNIFORM_MAX_LENGTH:
300 *params = max_uniform_name_length_;
301 return true;
302 default:
303 break;
305 return false;
308 template<typename T> static T LocalGetAs(
309 const std::vector<int8>& data, uint32 offset, size_t size) {
310 const int8* p = &data[0] + offset;
311 if (offset + size > data.size()) {
312 NOTREACHED();
313 return NULL;
315 return static_cast<T>(static_cast<const void*>(p));
318 void CachedProgramInfoManager::Program::Update(
319 GLES2Implementation* gl, GLuint program) {
320 if (cached_) {
321 return;
323 std::vector<int8> result;
324 gl->GetProgramInfoCHROMIUMHelper(program, &result);
325 if (result.empty()) {
326 // This should only happen on a lost context.
327 return;
329 DCHECK_GE(result.size(), sizeof(ProgramInfoHeader));
330 const ProgramInfoHeader* header = LocalGetAs<const ProgramInfoHeader*>(
331 result, 0, sizeof(header));
332 link_status_ = header->link_status != 0;
333 if (!link_status_) {
334 return;
336 attrib_infos_.clear();
337 uniform_infos_.clear();
338 max_attrib_name_length_ = 0;
339 max_uniform_name_length_ = 0;
340 const ProgramInput* inputs = LocalGetAs<const ProgramInput*>(
341 result, sizeof(*header),
342 sizeof(ProgramInput) * (header->num_attribs + header->num_uniforms));
343 const ProgramInput* input = inputs;
344 for (uint32 ii = 0; ii < header->num_attribs; ++ii) {
345 const int32* location = LocalGetAs<const int32*>(
346 result, input->location_offset, sizeof(int32));
347 const char* name_buf = LocalGetAs<const char*>(
348 result, input->name_offset, input->name_length);
349 std::string name(name_buf, input->name_length);
350 attrib_infos_.push_back(
351 VertexAttrib(input->size, input->type, name, *location));
352 max_attrib_name_length_ = std::max(
353 static_cast<GLsizei>(name.size() + 1), max_attrib_name_length_);
354 ++input;
356 for (uint32 ii = 0; ii < header->num_uniforms; ++ii) {
357 const int32* locations = LocalGetAs<const int32*>(
358 result, input->location_offset, sizeof(int32) * input->size);
359 const char* name_buf = LocalGetAs<const char*>(
360 result, input->name_offset, input->name_length);
361 std::string name(name_buf, input->name_length);
362 UniformInfo info(input->size, input->type, name);
363 max_uniform_name_length_ = std::max(
364 static_cast<GLsizei>(name.size() + 1), max_uniform_name_length_);
365 for (int32 jj = 0; jj < input->size; ++jj) {
366 info.element_locations.push_back(locations[jj]);
368 uniform_infos_.push_back(info);
369 ++input;
371 DCHECK_EQ(header->num_attribs + header->num_uniforms,
372 static_cast<uint32>(input - inputs));
373 cached_ = true;
376 CachedProgramInfoManager::CachedProgramInfoManager() {
379 CachedProgramInfoManager::~CachedProgramInfoManager() {
383 CachedProgramInfoManager::Program*
384 CachedProgramInfoManager::GetProgramInfo(
385 GLES2Implementation* gl, GLuint program) {
386 lock_.AssertAcquired();
387 ProgramInfoMap::iterator it = program_infos_.find(program);
388 if (it == program_infos_.end()) {
389 return NULL;
391 Program* info = &it->second;
392 info->Update(gl, program);
393 return info;
396 void CachedProgramInfoManager::CreateInfo(GLuint program) {
397 base::AutoLock auto_lock(lock_);
398 program_infos_.erase(program);
399 std::pair<ProgramInfoMap::iterator, bool> result =
400 program_infos_.insert(std::make_pair(program, Program()));
402 DCHECK(result.second);
405 void CachedProgramInfoManager::DeleteInfo(GLuint program) {
406 base::AutoLock auto_lock(lock_);
407 program_infos_.erase(program);
410 bool CachedProgramInfoManager::GetProgramiv(
411 GLES2Implementation* gl, GLuint program, GLenum pname, GLint* params) {
412 base::AutoLock auto_lock(lock_);
413 Program* info = GetProgramInfo(gl, program);
414 if (!info) {
415 return false;
417 return info->GetProgramiv(pname, params);
420 GLint CachedProgramInfoManager::GetAttribLocation(
421 GLES2Implementation* gl, GLuint program, const char* name) {
422 base::AutoLock auto_lock(lock_);
423 Program* info = GetProgramInfo(gl, program);
424 if (info) {
425 return info->GetAttribLocation(name);
427 return gl->GetAttribLocationHelper(program, name);
430 GLint CachedProgramInfoManager::GetUniformLocation(
431 GLES2Implementation* gl, GLuint program, const char* name) {
432 base::AutoLock auto_lock(lock_);
433 Program* info = GetProgramInfo(gl, program);
434 if (info) {
435 return info->GetUniformLocation(name);
437 return gl->GetUniformLocationHelper(program, name);
440 bool CachedProgramInfoManager::GetActiveAttrib(
441 GLES2Implementation* gl,
442 GLuint program, GLuint index, GLsizei bufsize, GLsizei* length,
443 GLint* size, GLenum* type, char* name) {
444 base::AutoLock auto_lock(lock_);
445 Program* info = GetProgramInfo(gl, program);
446 if (info) {
447 const Program::VertexAttrib* attrib_info =
448 info->GetAttribInfo(index);
449 if (attrib_info) {
450 if (size) {
451 *size = attrib_info->size;
453 if (type) {
454 *type = attrib_info->type;
456 if (length || name) {
457 GLsizei max_size = std::min(static_cast<size_t>(bufsize) - 1,
458 std::max(static_cast<size_t>(0),
459 attrib_info->name.size()));
460 if (length) {
461 *length = max_size;
463 if (name && bufsize > 0) {
464 memcpy(name, attrib_info->name.c_str(), max_size);
465 name[max_size] = '\0';
468 return true;
471 return gl->GetActiveAttribHelper(
472 program, index, bufsize, length, size, type, name);
475 bool CachedProgramInfoManager::GetActiveUniform(
476 GLES2Implementation* gl,
477 GLuint program, GLuint index, GLsizei bufsize, GLsizei* length,
478 GLint* size, GLenum* type, char* name) {
479 base::AutoLock auto_lock(lock_);
480 Program* info = GetProgramInfo(gl, program);
481 if (info) {
482 const Program::UniformInfo* uniform_info = info->GetUniformInfo(index);
483 if (uniform_info) {
484 if (size) {
485 *size = uniform_info->size;
487 if (type) {
488 *type = uniform_info->type;
490 if (length || name) {
491 GLsizei max_size = std::min(static_cast<size_t>(bufsize) - 1,
492 std::max(static_cast<size_t>(0),
493 uniform_info->name.size()));
494 if (length) {
495 *length = max_size;
497 if (name && bufsize > 0) {
498 memcpy(name, uniform_info->name.c_str(), max_size);
499 name[max_size] = '\0';
502 return true;
505 return gl->GetActiveUniformHelper(
506 program, index, bufsize, length, size, type, name);
509 ProgramInfoManager::ProgramInfoManager() {
512 ProgramInfoManager::~ProgramInfoManager() {
515 ProgramInfoManager* ProgramInfoManager::Create(
516 bool shared_resources_across_processes) {
517 if (shared_resources_across_processes) {
518 return new NonCachedProgramInfoManager();
519 } else {
520 return new CachedProgramInfoManager();
524 } // namespace gles2
525 } // namespace gpu