cc: Added inline to Tile::IsReadyToDraw
[chromium-blink-merge.git] / gpu / command_buffer / client / program_info_manager.cc
blobfb0c1f3f9406f487e66cdd828ab7009d305bd4f3
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 <map>
7 #include "base/compiler_specific.h"
8 #include "gpu/command_buffer/client/atomicops.h"
9 #include "gpu/command_buffer/client/gles2_implementation.h"
10 #include "gpu/command_buffer/client/program_info_manager.h"
11 #include "gpu/command_buffer/common/gles2_cmd_utils.h"
13 namespace gpu {
14 namespace gles2 {
16 class NonCachedProgramInfoManager : public ProgramInfoManager {
17 public:
18 NonCachedProgramInfoManager();
19 virtual ~NonCachedProgramInfoManager();
21 virtual void CreateInfo(GLuint program) OVERRIDE;
23 virtual void DeleteInfo(GLuint program) OVERRIDE;
25 virtual bool GetProgramiv(GLES2Implementation* gl,
26 GLuint program,
27 GLenum pname,
28 GLint* params) OVERRIDE;
30 virtual GLint GetAttribLocation(GLES2Implementation* gl,
31 GLuint program,
32 const char* name) OVERRIDE;
34 virtual GLint GetUniformLocation(GLES2Implementation* gl,
35 GLuint program,
36 const char* name) OVERRIDE;
38 virtual bool GetActiveAttrib(GLES2Implementation* gl,
39 GLuint program,
40 GLuint index,
41 GLsizei bufsize,
42 GLsizei* length,
43 GLint* size,
44 GLenum* type,
45 char* name) OVERRIDE;
47 virtual bool GetActiveUniform(GLES2Implementation* gl,
48 GLuint program,
49 GLuint index,
50 GLsizei bufsize,
51 GLsizei* length,
52 GLint* size,
53 GLenum* type,
54 char* name) OVERRIDE;
58 NonCachedProgramInfoManager::NonCachedProgramInfoManager() {
61 NonCachedProgramInfoManager::~NonCachedProgramInfoManager() {
64 void NonCachedProgramInfoManager::CreateInfo(GLuint /* program */) {
67 void NonCachedProgramInfoManager::DeleteInfo(GLuint /* program */) {
70 bool NonCachedProgramInfoManager::GetProgramiv(
71 GLES2Implementation* /* gl */,
72 GLuint /* program */,
73 GLenum /* pname */,
74 GLint* /* params */) {
75 return false;
78 GLint NonCachedProgramInfoManager::GetAttribLocation(
79 GLES2Implementation* gl, GLuint program, const char* name) {
80 return gl->GetAttribLocationHelper(program, name);
83 GLint NonCachedProgramInfoManager::GetUniformLocation(
84 GLES2Implementation* gl, GLuint program, const char* name) {
85 return gl->GetUniformLocationHelper(program, name);
88 bool NonCachedProgramInfoManager::GetActiveAttrib(
89 GLES2Implementation* gl,
90 GLuint program, GLuint index, GLsizei bufsize, GLsizei* length,
91 GLint* size, GLenum* type, char* name) {
92 return gl->GetActiveAttribHelper(
93 program, index, bufsize, length, size, type, name);
96 bool NonCachedProgramInfoManager::GetActiveUniform(
97 GLES2Implementation* gl,
98 GLuint program, GLuint index, GLsizei bufsize, GLsizei* length,
99 GLint* size, GLenum* type, char* name) {
100 return gl->GetActiveUniformHelper(
101 program, index, bufsize, length, size, type, name);
104 class CachedProgramInfoManager : public ProgramInfoManager {
105 public:
106 CachedProgramInfoManager();
107 virtual ~CachedProgramInfoManager();
109 virtual void CreateInfo(GLuint program) OVERRIDE;
111 virtual void DeleteInfo(GLuint program) OVERRIDE;
113 virtual bool GetProgramiv(GLES2Implementation* gl,
114 GLuint program,
115 GLenum pname,
116 GLint* params) OVERRIDE;
118 virtual GLint GetAttribLocation(GLES2Implementation* gl,
119 GLuint program,
120 const char* name) OVERRIDE;
122 virtual GLint GetUniformLocation(GLES2Implementation* gl,
123 GLuint program,
124 const char* name) OVERRIDE;
126 virtual bool GetActiveAttrib(GLES2Implementation* gl,
127 GLuint program,
128 GLuint index,
129 GLsizei bufsize,
130 GLsizei* length,
131 GLint* size,
132 GLenum* type,
133 char* name) OVERRIDE;
135 virtual bool GetActiveUniform(GLES2Implementation* gl,
136 GLuint program,
137 GLuint index,
138 GLsizei bufsize,
139 GLsizei* length,
140 GLint* size,
141 GLenum* type,
142 char* name) OVERRIDE;
144 private:
145 class Program {
146 public:
147 struct UniformInfo {
148 UniformInfo(GLsizei _size, GLenum _type, const std::string& _name);
150 GLsizei size;
151 GLenum type;
152 bool is_array;
153 std::string name;
154 std::vector<GLint> element_locations;
156 struct VertexAttrib {
157 VertexAttrib(GLsizei _size, GLenum _type, const std::string& _name,
158 GLint _location)
159 : size(_size),
160 type(_type),
161 location(_location),
162 name(_name) {
164 GLsizei size;
165 GLenum type;
166 GLint location;
167 std::string name;
170 typedef std::vector<UniformInfo> UniformInfoVector;
171 typedef std::vector<VertexAttrib> AttribInfoVector;
173 Program();
175 const AttribInfoVector& GetAttribInfos() const {
176 return attrib_infos_;
179 const VertexAttrib* GetAttribInfo(GLint index) const {
180 return (static_cast<size_t>(index) < attrib_infos_.size()) ?
181 &attrib_infos_[index] : NULL;
184 GLint GetAttribLocation(const std::string& name) const;
186 const UniformInfo* GetUniformInfo(GLint index) const {
187 return (static_cast<size_t>(index) < uniform_infos_.size()) ?
188 &uniform_infos_[index] : NULL;
191 // Gets the location of a uniform by name.
192 GLint GetUniformLocation(const std::string& name) const;
194 bool GetProgramiv(GLenum pname, GLint* params);
196 // Updates the program info after a successful link.
197 void Update(GLES2Implementation* gl, GLuint program);
199 private:
200 bool cached_;
202 GLsizei max_attrib_name_length_;
204 // Attrib by index.
205 AttribInfoVector attrib_infos_;
207 GLsizei max_uniform_name_length_;
209 // Uniform info by index.
210 UniformInfoVector uniform_infos_;
212 // This is true if glLinkProgram was successful last time it was called.
213 bool link_status_;
216 Program* GetProgramInfo(GLES2Implementation* gl, GLuint program);
218 // TODO(gman): Switch to a faster container.
219 typedef std::map<GLuint, Program> ProgramInfoMap;
221 ProgramInfoMap program_infos_;
223 mutable Lock lock_;
226 CachedProgramInfoManager::Program::UniformInfo::UniformInfo(
227 GLsizei _size, GLenum _type, const std::string& _name)
228 : size(_size),
229 type(_type),
230 name(_name) {
231 is_array = (!name.empty() && name[name.size() - 1] == ']');
232 GPU_DCHECK(!(size > 1 && !is_array));
235 CachedProgramInfoManager::Program::Program()
236 : cached_(false),
237 max_attrib_name_length_(0),
238 max_uniform_name_length_(0),
239 link_status_(false) {
242 // TODO(gman): Add a faster lookup.
243 GLint CachedProgramInfoManager::Program::GetAttribLocation(
244 const std::string& name) const {
245 for (GLuint ii = 0; ii < attrib_infos_.size(); ++ii) {
246 const VertexAttrib& info = attrib_infos_[ii];
247 if (info.name == name) {
248 return info.location;
251 return -1;
254 GLint CachedProgramInfoManager::Program::GetUniformLocation(
255 const std::string& name) const {
256 bool getting_array_location = false;
257 size_t open_pos = std::string::npos;
258 int index = 0;
259 if (!GLES2Util::ParseUniformName(
260 name, &open_pos, &index, &getting_array_location)) {
261 return -1;
263 for (GLuint ii = 0; ii < uniform_infos_.size(); ++ii) {
264 const UniformInfo& info = uniform_infos_[ii];
265 if (info.name == name ||
266 (info.is_array &&
267 info.name.compare(0, info.name.size() - 3, name) == 0)) {
268 return info.element_locations[0];
269 } else if (getting_array_location && info.is_array) {
270 // Look for an array specification.
271 size_t open_pos_2 = info.name.find_last_of('[');
272 if (open_pos_2 == open_pos &&
273 name.compare(0, open_pos, info.name, 0, open_pos) == 0) {
274 if (index >= 0 && index < info.size) {
275 return info.element_locations[index];
280 return -1;
283 bool CachedProgramInfoManager::Program::GetProgramiv(
284 GLenum pname, GLint* params) {
285 switch (pname) {
286 case GL_LINK_STATUS:
287 *params = link_status_;
288 return true;
289 case GL_ACTIVE_ATTRIBUTES:
290 *params = attrib_infos_.size();
291 return true;
292 case GL_ACTIVE_ATTRIBUTE_MAX_LENGTH:
293 *params = max_attrib_name_length_;
294 return true;
295 case GL_ACTIVE_UNIFORMS:
296 *params = uniform_infos_.size();
297 return true;
298 case GL_ACTIVE_UNIFORM_MAX_LENGTH:
299 *params = max_uniform_name_length_;
300 return true;
301 default:
302 break;
304 return false;
307 template<typename T> static T LocalGetAs(
308 const std::vector<int8>& data, uint32 offset, size_t size) {
309 const int8* p = &data[0] + offset;
310 if (offset + size > data.size()) {
311 GPU_NOTREACHED();
312 return NULL;
314 return static_cast<T>(static_cast<const void*>(p));
317 void CachedProgramInfoManager::Program::Update(
318 GLES2Implementation* gl, GLuint program) {
319 if (cached_) {
320 return;
322 std::vector<int8> result;
323 gl->GetProgramInfoCHROMIUMHelper(program, &result);
324 if (result.empty()) {
325 // This should only happen on a lost context.
326 return;
328 GPU_DCHECK_GE(result.size(), sizeof(ProgramInfoHeader));
329 const ProgramInfoHeader* header = LocalGetAs<const ProgramInfoHeader*>(
330 result, 0, sizeof(header));
331 link_status_ = header->link_status != 0;
332 if (!link_status_) {
333 return;
335 attrib_infos_.clear();
336 uniform_infos_.clear();
337 max_attrib_name_length_ = 0;
338 max_uniform_name_length_ = 0;
339 const ProgramInput* inputs = LocalGetAs<const ProgramInput*>(
340 result, sizeof(*header),
341 sizeof(ProgramInput) * (header->num_attribs + header->num_uniforms));
342 const ProgramInput* input = inputs;
343 for (uint32 ii = 0; ii < header->num_attribs; ++ii) {
344 const int32* location = LocalGetAs<const int32*>(
345 result, input->location_offset, sizeof(int32));
346 const char* name_buf = LocalGetAs<const char*>(
347 result, input->name_offset, input->name_length);
348 std::string name(name_buf, input->name_length);
349 attrib_infos_.push_back(
350 VertexAttrib(input->size, input->type, name, *location));
351 max_attrib_name_length_ = std::max(
352 static_cast<GLsizei>(name.size() + 1), max_attrib_name_length_);
353 ++input;
355 for (uint32 ii = 0; ii < header->num_uniforms; ++ii) {
356 const int32* locations = LocalGetAs<const int32*>(
357 result, input->location_offset, sizeof(int32) * input->size);
358 const char* name_buf = LocalGetAs<const char*>(
359 result, input->name_offset, input->name_length);
360 std::string name(name_buf, input->name_length);
361 UniformInfo info(input->size, input->type, name);
362 max_uniform_name_length_ = std::max(
363 static_cast<GLsizei>(name.size() + 1), max_uniform_name_length_);
364 for (int32 jj = 0; jj < input->size; ++jj) {
365 info.element_locations.push_back(locations[jj]);
367 uniform_infos_.push_back(info);
368 ++input;
370 GPU_DCHECK_EQ(header->num_attribs + header->num_uniforms,
371 static_cast<uint32>(input - inputs));
372 cached_ = true;
375 CachedProgramInfoManager::CachedProgramInfoManager() {
378 CachedProgramInfoManager::~CachedProgramInfoManager() {
382 CachedProgramInfoManager::Program*
383 CachedProgramInfoManager::GetProgramInfo(
384 GLES2Implementation* gl, GLuint program) {
385 ProgramInfoMap::iterator it = program_infos_.find(program);
386 if (it == program_infos_.end()) {
387 return NULL;
389 Program* info = &it->second;
390 info->Update(gl, program);
391 return info;
394 void CachedProgramInfoManager::CreateInfo(GLuint program) {
395 AutoLock auto_lock(lock_);
396 DeleteInfo(program);
397 std::pair<ProgramInfoMap::iterator, bool> result =
398 program_infos_.insert(std::make_pair(program, Program()));
400 GPU_DCHECK(result.second);
403 void CachedProgramInfoManager::DeleteInfo(GLuint program) {
404 program_infos_.erase(program);
407 bool CachedProgramInfoManager::GetProgramiv(
408 GLES2Implementation* gl, GLuint program, GLenum pname, GLint* params) {
409 AutoLock auto_lock(lock_);
410 Program* info = GetProgramInfo(gl, program);
411 if (!info) {
412 return false;
414 return info->GetProgramiv(pname, params);
417 GLint CachedProgramInfoManager::GetAttribLocation(
418 GLES2Implementation* gl, GLuint program, const char* name) {
419 AutoLock auto_lock(lock_);
420 Program* info = GetProgramInfo(gl, program);
421 if (info) {
422 return info->GetAttribLocation(name);
424 return gl->GetAttribLocationHelper(program, name);
427 GLint CachedProgramInfoManager::GetUniformLocation(
428 GLES2Implementation* gl, GLuint program, const char* name) {
429 AutoLock auto_lock(lock_);
430 Program* info = GetProgramInfo(gl, program);
431 if (info) {
432 return info->GetUniformLocation(name);
434 return gl->GetUniformLocationHelper(program, name);
437 bool CachedProgramInfoManager::GetActiveAttrib(
438 GLES2Implementation* gl,
439 GLuint program, GLuint index, GLsizei bufsize, GLsizei* length,
440 GLint* size, GLenum* type, char* name) {
441 AutoLock auto_lock(lock_);
442 Program* info = GetProgramInfo(gl, program);
443 if (info) {
444 const Program::VertexAttrib* attrib_info =
445 info->GetAttribInfo(index);
446 if (attrib_info) {
447 if (size) {
448 *size = attrib_info->size;
450 if (type) {
451 *type = attrib_info->type;
453 if (length || name) {
454 GLsizei max_size = std::min(static_cast<size_t>(bufsize) - 1,
455 std::max(static_cast<size_t>(0),
456 attrib_info->name.size()));
457 if (length) {
458 *length = max_size;
460 if (name && bufsize > 0) {
461 memcpy(name, attrib_info->name.c_str(), max_size);
462 name[max_size] = '\0';
465 return true;
468 return gl->GetActiveAttribHelper(
469 program, index, bufsize, length, size, type, name);
472 bool CachedProgramInfoManager::GetActiveUniform(
473 GLES2Implementation* gl,
474 GLuint program, GLuint index, GLsizei bufsize, GLsizei* length,
475 GLint* size, GLenum* type, char* name) {
476 AutoLock auto_lock(lock_);
477 Program* info = GetProgramInfo(gl, program);
478 if (info) {
479 const Program::UniformInfo* uniform_info = info->GetUniformInfo(index);
480 if (uniform_info) {
481 if (size) {
482 *size = uniform_info->size;
484 if (type) {
485 *type = uniform_info->type;
487 if (length || name) {
488 GLsizei max_size = std::min(static_cast<size_t>(bufsize) - 1,
489 std::max(static_cast<size_t>(0),
490 uniform_info->name.size()));
491 if (length) {
492 *length = max_size;
494 if (name && bufsize > 0) {
495 memcpy(name, uniform_info->name.c_str(), max_size);
496 name[max_size] = '\0';
499 return true;
502 return gl->GetActiveUniformHelper(
503 program, index, bufsize, length, size, type, name);
506 ProgramInfoManager::ProgramInfoManager() {
509 ProgramInfoManager::~ProgramInfoManager() {
512 ProgramInfoManager* ProgramInfoManager::Create(
513 bool shared_resources_across_processes) {
514 if (shared_resources_across_processes) {
515 return new NonCachedProgramInfoManager();
516 } else {
517 return new CachedProgramInfoManager();
521 } // namespace gles2
522 } // namespace gpu