Add explicit |forceOnlineSignin| to user pod status
[chromium-blink-merge.git] / gpu / command_buffer / client / program_info_manager.cc
blob1b5a348d6cc35be2065d47b0dc34bbd3849516e7
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 ProgramInfoMap::iterator it = program_infos_.find(program);
387 if (it == program_infos_.end()) {
388 return NULL;
390 Program* info = &it->second;
391 info->Update(gl, program);
392 return info;
395 void CachedProgramInfoManager::CreateInfo(GLuint program) {
396 base::AutoLock auto_lock(lock_);
397 DeleteInfo(program);
398 std::pair<ProgramInfoMap::iterator, bool> result =
399 program_infos_.insert(std::make_pair(program, Program()));
401 DCHECK(result.second);
404 void CachedProgramInfoManager::DeleteInfo(GLuint program) {
405 program_infos_.erase(program);
408 bool CachedProgramInfoManager::GetProgramiv(
409 GLES2Implementation* gl, GLuint program, GLenum pname, GLint* params) {
410 base::AutoLock auto_lock(lock_);
411 Program* info = GetProgramInfo(gl, program);
412 if (!info) {
413 return false;
415 return info->GetProgramiv(pname, params);
418 GLint CachedProgramInfoManager::GetAttribLocation(
419 GLES2Implementation* gl, GLuint program, const char* name) {
420 base::AutoLock auto_lock(lock_);
421 Program* info = GetProgramInfo(gl, program);
422 if (info) {
423 return info->GetAttribLocation(name);
425 return gl->GetAttribLocationHelper(program, name);
428 GLint CachedProgramInfoManager::GetUniformLocation(
429 GLES2Implementation* gl, GLuint program, const char* name) {
430 base::AutoLock auto_lock(lock_);
431 Program* info = GetProgramInfo(gl, program);
432 if (info) {
433 return info->GetUniformLocation(name);
435 return gl->GetUniformLocationHelper(program, name);
438 bool CachedProgramInfoManager::GetActiveAttrib(
439 GLES2Implementation* gl,
440 GLuint program, GLuint index, GLsizei bufsize, GLsizei* length,
441 GLint* size, GLenum* type, char* name) {
442 base::AutoLock auto_lock(lock_);
443 Program* info = GetProgramInfo(gl, program);
444 if (info) {
445 const Program::VertexAttrib* attrib_info =
446 info->GetAttribInfo(index);
447 if (attrib_info) {
448 if (size) {
449 *size = attrib_info->size;
451 if (type) {
452 *type = attrib_info->type;
454 if (length || name) {
455 GLsizei max_size = std::min(static_cast<size_t>(bufsize) - 1,
456 std::max(static_cast<size_t>(0),
457 attrib_info->name.size()));
458 if (length) {
459 *length = max_size;
461 if (name && bufsize > 0) {
462 memcpy(name, attrib_info->name.c_str(), max_size);
463 name[max_size] = '\0';
466 return true;
469 return gl->GetActiveAttribHelper(
470 program, index, bufsize, length, size, type, name);
473 bool CachedProgramInfoManager::GetActiveUniform(
474 GLES2Implementation* gl,
475 GLuint program, GLuint index, GLsizei bufsize, GLsizei* length,
476 GLint* size, GLenum* type, char* name) {
477 base::AutoLock auto_lock(lock_);
478 Program* info = GetProgramInfo(gl, program);
479 if (info) {
480 const Program::UniformInfo* uniform_info = info->GetUniformInfo(index);
481 if (uniform_info) {
482 if (size) {
483 *size = uniform_info->size;
485 if (type) {
486 *type = uniform_info->type;
488 if (length || name) {
489 GLsizei max_size = std::min(static_cast<size_t>(bufsize) - 1,
490 std::max(static_cast<size_t>(0),
491 uniform_info->name.size()));
492 if (length) {
493 *length = max_size;
495 if (name && bufsize > 0) {
496 memcpy(name, uniform_info->name.c_str(), max_size);
497 name[max_size] = '\0';
500 return true;
503 return gl->GetActiveUniformHelper(
504 program, index, bufsize, length, size, type, name);
507 ProgramInfoManager::ProgramInfoManager() {
510 ProgramInfoManager::~ProgramInfoManager() {
513 ProgramInfoManager* ProgramInfoManager::Create(
514 bool shared_resources_across_processes) {
515 if (shared_resources_across_processes) {
516 return new NonCachedProgramInfoManager();
517 } else {
518 return new CachedProgramInfoManager();
522 } // namespace gles2
523 } // namespace gpu