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"
9 template<typename T
> static T
LocalGetAs(
10 const std::vector
<int8
>& data
, uint32 offset
, size_t size
) {
11 const int8
* p
= &data
[0] + offset
;
12 if (offset
+ size
> data
.size()) {
16 return static_cast<T
>(static_cast<const void*>(p
));
19 } // namespace anonymous
24 ProgramInfoManager::Program::VertexAttrib::VertexAttrib(
25 GLsizei _size
, GLenum _type
, const std::string
& _name
, GLint _location
)
32 ProgramInfoManager::Program::VertexAttrib::~VertexAttrib() {
35 ProgramInfoManager::Program::UniformInfo::UniformInfo(
36 GLsizei _size
, GLenum _type
, const std::string
& _name
)
40 is_array
= (!name
.empty() && name
[name
.size() - 1] == ']');
41 DCHECK(!(size
> 1 && !is_array
));
44 ProgramInfoManager::Program::UniformInfo::~UniformInfo() {
47 ProgramInfoManager::Program::UniformES3::UniformES3()
55 ProgramInfoManager::Program::UniformES3::~UniformES3() {
58 ProgramInfoManager::Program::UniformBlock::UniformBlock()
61 referenced_by_vertex_shader(false),
62 referenced_by_fragment_shader(false) {
65 ProgramInfoManager::Program::UniformBlock::~UniformBlock() {
68 ProgramInfoManager::Program::TransformFeedbackVarying::
69 TransformFeedbackVarying()
74 ProgramInfoManager::Program::TransformFeedbackVarying::
75 ~TransformFeedbackVarying() {
78 ProgramInfoManager::Program::Program()
80 max_attrib_name_length_(0),
81 max_uniform_name_length_(0),
83 cached_es3_uniform_blocks_(false),
84 active_uniform_block_max_name_length_(0),
85 cached_es3_transform_feedback_varyings_(false),
86 transform_feedback_varying_max_length_(0),
87 transform_feedback_buffer_mode_(0),
88 cached_es3_uniformsiv_(false) {
91 ProgramInfoManager::Program::~Program() {
94 // TODO(gman): Add a faster lookup.
95 GLint
ProgramInfoManager::Program::GetAttribLocation(
96 const std::string
& name
) const {
97 for (GLuint ii
= 0; ii
< attrib_infos_
.size(); ++ii
) {
98 const VertexAttrib
& info
= attrib_infos_
[ii
];
99 if (info
.name
== name
) {
100 return info
.location
;
106 const ProgramInfoManager::Program::VertexAttrib
*
107 ProgramInfoManager::Program::GetAttribInfo(GLint index
) const {
108 return (static_cast<size_t>(index
) < attrib_infos_
.size()) ?
109 &attrib_infos_
[index
] : NULL
;
112 const ProgramInfoManager::Program::UniformInfo
*
113 ProgramInfoManager::Program::GetUniformInfo(GLint index
) const {
114 return (static_cast<size_t>(index
) < uniform_infos_
.size()) ?
115 &uniform_infos_
[index
] : NULL
;
118 const ProgramInfoManager::Program::UniformBlock
*
119 ProgramInfoManager::Program::GetUniformBlock(GLuint index
) const {
120 return (index
< uniform_blocks_
.size()) ? &uniform_blocks_
[index
] : NULL
;
123 GLint
ProgramInfoManager::Program::GetUniformLocation(
124 const std::string
& name
) const {
125 bool getting_array_location
= false;
126 size_t open_pos
= std::string::npos
;
128 if (!GLES2Util::ParseUniformName(
129 name
, &open_pos
, &index
, &getting_array_location
)) {
132 for (GLuint ii
= 0; ii
< uniform_infos_
.size(); ++ii
) {
133 const UniformInfo
& info
= uniform_infos_
[ii
];
134 if (info
.name
== name
||
136 info
.name
.compare(0, info
.name
.size() - 3, name
) == 0)) {
137 return info
.element_locations
[0];
138 } else if (getting_array_location
&& info
.is_array
) {
139 // Look for an array specification.
140 size_t open_pos_2
= info
.name
.find_last_of('[');
141 if (open_pos_2
== open_pos
&&
142 name
.compare(0, open_pos
, info
.name
, 0, open_pos
) == 0) {
143 if (index
>= 0 && index
< info
.size
) {
144 return info
.element_locations
[index
];
152 GLuint
ProgramInfoManager::Program::GetUniformIndex(
153 const std::string
& name
) const {
154 // TODO(zmo): Maybe build a hashed_map for faster lookup.
155 for (GLuint ii
= 0; ii
< uniform_infos_
.size(); ++ii
) {
156 const UniformInfo
& info
= uniform_infos_
[ii
];
157 // For an array, either "var" or "var[0]" is considered as a match.
158 // See "OpenGL ES 3.0.0, Section 2.11.3 Program Objects."
159 if (info
.name
== name
||
161 info
.name
.compare(0, info
.name
.size() - 3, name
) == 0)) {
165 return GL_INVALID_INDEX
;
168 GLint
ProgramInfoManager::Program::GetFragDataLocation(
169 const std::string
& name
) const {
170 base::hash_map
<std::string
, GLint
>::const_iterator iter
=
171 frag_data_locations_
.find(name
);
172 if (iter
== frag_data_locations_
.end())
177 void ProgramInfoManager::Program::CacheFragDataLocation(
178 const std::string
& name
, GLint loc
) {
179 frag_data_locations_
[name
] = loc
;
182 bool ProgramInfoManager::Program::GetProgramiv(
183 GLenum pname
, GLint
* params
) {
186 *params
= static_cast<GLint
>(link_status_
);
188 case GL_ACTIVE_ATTRIBUTES
:
189 *params
= static_cast<GLint
>(attrib_infos_
.size());
191 case GL_ACTIVE_ATTRIBUTE_MAX_LENGTH
:
192 *params
= static_cast<GLint
>(max_attrib_name_length_
);
194 case GL_ACTIVE_UNIFORMS
:
195 *params
= static_cast<GLint
>(uniform_infos_
.size());
197 case GL_ACTIVE_UNIFORM_MAX_LENGTH
:
198 *params
= static_cast<GLint
>(max_uniform_name_length_
);
200 case GL_ACTIVE_UNIFORM_BLOCKS
:
201 *params
= static_cast<GLint
>(uniform_blocks_
.size());
203 case GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH
:
204 *params
= static_cast<GLint
>(active_uniform_block_max_name_length_
);
206 case GL_TRANSFORM_FEEDBACK_VARYINGS
:
207 *params
= static_cast<GLint
>(transform_feedback_varyings_
.size());
209 case GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH
:
210 *params
= static_cast<GLint
>(transform_feedback_varying_max_length_
);
212 case GL_TRANSFORM_FEEDBACK_BUFFER_MODE
:
213 *params
= static_cast<GLint
>(transform_feedback_buffer_mode_
);
222 GLuint
ProgramInfoManager::Program::GetUniformBlockIndex(
223 const std::string
& name
) const {
224 for (size_t ii
= 0; ii
< uniform_blocks_
.size(); ++ii
) {
225 if (uniform_blocks_
[ii
].name
== name
) {
226 return static_cast<GLuint
>(ii
);
229 return GL_INVALID_INDEX
;
232 void ProgramInfoManager::Program::UniformBlockBinding(
233 GLuint index
, GLuint binding
) {
234 if (index
< uniform_blocks_
.size()) {
235 uniform_blocks_
[index
].binding
= binding
;
239 const ProgramInfoManager::Program::TransformFeedbackVarying
*
240 ProgramInfoManager::Program::GetTransformFeedbackVarying(GLuint index
) const {
241 return (index
< transform_feedback_varyings_
.size()) ?
242 &transform_feedback_varyings_
[index
] : NULL
;
245 bool ProgramInfoManager::Program::GetUniformsiv(
246 GLsizei count
, const GLuint
* indices
, GLenum pname
, GLint
* params
) {
248 // At this point, pname has already been validated.
251 DCHECK(count
> 0 && indices
);
252 size_t num_uniforms
= uniform_infos_
.size();
253 if (num_uniforms
== 0) {
254 num_uniforms
= uniforms_es3_
.size();
256 if (static_cast<size_t>(count
) > num_uniforms
) {
259 for (GLsizei ii
= 0; ii
< count
; ++ii
) {
260 if (indices
[ii
] >= num_uniforms
) {
268 case GL_UNIFORM_SIZE
:
269 DCHECK_EQ(num_uniforms
, uniform_infos_
.size());
270 for (GLsizei ii
= 0; ii
< count
; ++ii
) {
271 params
[ii
] = static_cast<GLint
>(uniform_infos_
[indices
[ii
]].size
);
274 case GL_UNIFORM_TYPE
:
275 DCHECK_EQ(num_uniforms
, uniform_infos_
.size());
276 for (GLsizei ii
= 0; ii
< count
; ++ii
) {
277 params
[ii
] = static_cast<GLint
>(uniform_infos_
[indices
[ii
]].type
);
280 case GL_UNIFORM_NAME_LENGTH
:
281 DCHECK_EQ(num_uniforms
, uniform_infos_
.size());
282 for (GLsizei ii
= 0; ii
< count
; ++ii
) {
283 params
[ii
] = static_cast<GLint
>(
284 uniform_infos_
[indices
[ii
]].name
.length() + 1);
287 case GL_UNIFORM_BLOCK_INDEX
:
288 DCHECK_EQ(num_uniforms
, uniforms_es3_
.size());
289 for (GLsizei ii
= 0; ii
< count
; ++ii
) {
290 params
[ii
] = uniforms_es3_
[indices
[ii
]].block_index
;
293 case GL_UNIFORM_OFFSET
:
294 DCHECK_EQ(num_uniforms
, uniforms_es3_
.size());
295 for (GLsizei ii
= 0; ii
< count
; ++ii
) {
296 params
[ii
] = uniforms_es3_
[indices
[ii
]].offset
;
299 case GL_UNIFORM_ARRAY_STRIDE
:
300 DCHECK_EQ(num_uniforms
, uniforms_es3_
.size());
301 for (GLsizei ii
= 0; ii
< count
; ++ii
) {
302 params
[ii
] = uniforms_es3_
[indices
[ii
]].array_stride
;
305 case GL_UNIFORM_MATRIX_STRIDE
:
306 DCHECK_EQ(num_uniforms
, uniforms_es3_
.size());
307 for (GLsizei ii
= 0; ii
< count
; ++ii
) {
308 params
[ii
] = uniforms_es3_
[indices
[ii
]].matrix_stride
;
311 case GL_UNIFORM_IS_ROW_MAJOR
:
312 DCHECK_EQ(num_uniforms
, uniforms_es3_
.size());
313 for (GLsizei ii
= 0; ii
< count
; ++ii
) {
314 params
[ii
] = uniforms_es3_
[indices
[ii
]].is_row_major
;
324 void ProgramInfoManager::Program::UpdateES2(const std::vector
<int8
>& result
) {
328 if (result
.empty()) {
329 // This should only happen on a lost context.
332 DCHECK_GE(result
.size(), sizeof(ProgramInfoHeader
));
333 const ProgramInfoHeader
* header
= LocalGetAs
<const ProgramInfoHeader
*>(
334 result
, 0, sizeof(header
));
335 link_status_
= header
->link_status
!= 0;
339 DCHECK_EQ(0u, attrib_infos_
.size());
340 DCHECK_EQ(0u, uniform_infos_
.size());
341 DCHECK_EQ(0, max_attrib_name_length_
);
342 DCHECK_EQ(0, max_uniform_name_length_
);
343 const ProgramInput
* inputs
= LocalGetAs
<const ProgramInput
*>(
344 result
, sizeof(*header
),
345 sizeof(ProgramInput
) * (header
->num_attribs
+ header
->num_uniforms
));
346 const ProgramInput
* input
= inputs
;
347 for (uint32 ii
= 0; ii
< header
->num_attribs
; ++ii
) {
348 const int32
* location
= LocalGetAs
<const int32
*>(
349 result
, input
->location_offset
, sizeof(int32
));
350 const char* name_buf
= LocalGetAs
<const char*>(
351 result
, input
->name_offset
, input
->name_length
);
352 std::string
name(name_buf
, input
->name_length
);
353 attrib_infos_
.push_back(
354 VertexAttrib(input
->size
, input
->type
, name
, *location
));
355 max_attrib_name_length_
= std::max(
356 static_cast<GLsizei
>(name
.size() + 1), max_attrib_name_length_
);
359 for (uint32 ii
= 0; ii
< header
->num_uniforms
; ++ii
) {
360 const int32
* locations
= LocalGetAs
<const int32
*>(
361 result
, input
->location_offset
, sizeof(int32
) * input
->size
);
362 const char* name_buf
= LocalGetAs
<const char*>(
363 result
, input
->name_offset
, input
->name_length
);
364 std::string
name(name_buf
, input
->name_length
);
365 UniformInfo
info(input
->size
, input
->type
, name
);
366 max_uniform_name_length_
= std::max(
367 static_cast<GLsizei
>(name
.size() + 1), max_uniform_name_length_
);
368 for (int32 jj
= 0; jj
< input
->size
; ++jj
) {
369 info
.element_locations
.push_back(locations
[jj
]);
371 uniform_infos_
.push_back(info
);
374 DCHECK_EQ(header
->num_attribs
+ header
->num_uniforms
,
375 static_cast<uint32
>(input
- inputs
));
379 void ProgramInfoManager::Program::UpdateES3UniformBlocks(
380 const std::vector
<int8
>& result
) {
381 if (cached_es3_uniform_blocks_
) {
384 if (result
.empty()) {
385 // This should only happen on a lost context.
388 DCHECK_EQ(0u, uniform_blocks_
.size());
389 DCHECK_EQ(0u, active_uniform_block_max_name_length_
);
391 // |result| comes from GPU process. We consider it trusted data. Therefore,
392 // no need to check for overflows as the GPU side did the checks already.
393 uint32_t header_size
= sizeof(UniformBlocksHeader
);
394 DCHECK_GE(result
.size(), header_size
);
395 const UniformBlocksHeader
* header
= LocalGetAs
<const UniformBlocksHeader
*>(
396 result
, 0, header_size
);
398 if (header
->num_uniform_blocks
== 0) {
399 DCHECK_EQ(result
.size(), header_size
);
400 // TODO(zmo): Here we can't tell if no uniform blocks are defined, or
401 // the previous link failed.
404 uniform_blocks_
.resize(header
->num_uniform_blocks
);
406 uint32_t entry_size
= sizeof(UniformBlockInfo
) * header
->num_uniform_blocks
;
407 DCHECK_GE(result
.size(), header_size
+ entry_size
);
408 uint32_t data_size
= result
.size() - header_size
- entry_size
;
409 DCHECK_LT(0u, data_size
);
410 const UniformBlockInfo
* entries
= LocalGetAs
<const UniformBlockInfo
*>(
411 result
, header_size
, entry_size
);
413 const char* data
= LocalGetAs
<const char*>(
414 result
, header_size
+ entry_size
, data_size
);
418 for (uint32_t ii
= 0; ii
< header
->num_uniform_blocks
; ++ii
) {
419 uniform_blocks_
[ii
].binding
= static_cast<GLuint
>(entries
[ii
].binding
);
420 uniform_blocks_
[ii
].data_size
= static_cast<GLuint
>(entries
[ii
].data_size
);
421 uniform_blocks_
[ii
].active_uniform_indices
.resize(
422 entries
[ii
].active_uniforms
);
423 uniform_blocks_
[ii
].referenced_by_vertex_shader
= static_cast<GLboolean
>(
424 entries
[ii
].referenced_by_vertex_shader
);
425 uniform_blocks_
[ii
].referenced_by_fragment_shader
= static_cast<GLboolean
>(
426 entries
[ii
].referenced_by_fragment_shader
);
427 // Uniform block names can't be empty strings.
428 DCHECK_LT(1u, entries
[ii
].name_length
);
429 if (entries
[ii
].name_length
> active_uniform_block_max_name_length_
) {
430 active_uniform_block_max_name_length_
= entries
[ii
].name_length
;
432 size
+= entries
[ii
].name_length
;
433 DCHECK_GE(data_size
, size
);
434 uniform_blocks_
[ii
].name
= std::string(data
, entries
[ii
].name_length
- 1);
435 data
+= entries
[ii
].name_length
;
436 size
+= entries
[ii
].active_uniforms
* sizeof(uint32_t);
437 DCHECK_GE(data_size
, size
);
438 const uint32_t* indices
= reinterpret_cast<const uint32_t*>(data
);
439 for (uint32_t uu
= 0; uu
< entries
[ii
].active_uniforms
; ++uu
) {
440 uniform_blocks_
[ii
].active_uniform_indices
[uu
] =
441 static_cast<GLuint
>(indices
[uu
]);
443 indices
+= entries
[ii
].active_uniforms
;
444 data
= reinterpret_cast<const char*>(indices
);
446 DCHECK_EQ(data_size
, size
);
447 cached_es3_uniform_blocks_
= true;
450 void ProgramInfoManager::Program::UpdateES3Uniformsiv(
451 const std::vector
<int8
>& result
) {
452 if (cached_es3_uniformsiv_
) {
455 if (result
.empty()) {
456 // This should only happen on a lost context.
459 DCHECK_EQ(0u, uniforms_es3_
.size());
461 // |result| comes from GPU process. We consider it trusted data. Therefore,
462 // no need to check for overflows as the GPU side did the checks already.
463 uint32_t header_size
= sizeof(UniformsES3Header
);
464 DCHECK_GE(result
.size(), header_size
);
465 const UniformsES3Header
* header
= LocalGetAs
<const UniformsES3Header
*>(
466 result
, 0, header_size
);
468 if (header
->num_uniforms
== 0) {
469 DCHECK_EQ(result
.size(), header_size
);
470 // TODO(zmo): Here we can't tell if no uniforms are defined, or
471 // the previous link failed.
474 uniforms_es3_
.resize(header
->num_uniforms
);
476 uint32_t entry_size
= sizeof(UniformES3Info
) * header
->num_uniforms
;
477 DCHECK_EQ(result
.size(), header_size
+ entry_size
);
478 const UniformES3Info
* entries
= LocalGetAs
<const UniformES3Info
*>(
479 result
, header_size
, entry_size
);
482 for (uint32_t ii
= 0; ii
< header
->num_uniforms
; ++ii
) {
483 uniforms_es3_
[ii
].block_index
= entries
[ii
].block_index
;
484 uniforms_es3_
[ii
].offset
= entries
[ii
].offset
;
485 uniforms_es3_
[ii
].array_stride
= entries
[ii
].array_stride
;
486 uniforms_es3_
[ii
].matrix_stride
= entries
[ii
].matrix_stride
;
487 uniforms_es3_
[ii
].is_row_major
= entries
[ii
].is_row_major
;
489 cached_es3_uniformsiv_
= true;
492 void ProgramInfoManager::Program::UpdateES3TransformFeedbackVaryings(
493 const std::vector
<int8
>& result
) {
494 if (cached_es3_transform_feedback_varyings_
) {
497 if (result
.empty()) {
498 // This should only happen on a lost context.
501 DCHECK_EQ(0u, transform_feedback_buffer_mode_
);
502 DCHECK_EQ(0u, transform_feedback_varyings_
.size());
503 DCHECK_EQ(0u, transform_feedback_varying_max_length_
);
505 // |result| comes from GPU process. We consider it trusted data. Therefore,
506 // no need to check for overflows as the GPU side did the checks already.
507 uint32_t header_size
= sizeof(TransformFeedbackVaryingsHeader
);
508 DCHECK_GE(result
.size(), header_size
);
509 const TransformFeedbackVaryingsHeader
* header
=
510 LocalGetAs
<const TransformFeedbackVaryingsHeader
*>(
511 result
, 0, header_size
);
513 transform_feedback_buffer_mode_
= header
->transform_feedback_buffer_mode
;
514 if (header
->num_transform_feedback_varyings
== 0) {
515 DCHECK_EQ(result
.size(), header_size
);
516 // TODO(zmo): Here we can't tell if no TransformFeedback varyings are
517 // defined, or the previous link failed.
520 transform_feedback_varyings_
.resize(header
->num_transform_feedback_varyings
);
522 uint32_t entry_size
= sizeof(TransformFeedbackVaryingInfo
) *
523 header
->num_transform_feedback_varyings
;
524 DCHECK_GE(result
.size(), header_size
+ entry_size
);
525 uint32_t data_size
= result
.size() - header_size
- entry_size
;
526 DCHECK_LT(0u, data_size
);
527 const TransformFeedbackVaryingInfo
* entries
=
528 LocalGetAs
<const TransformFeedbackVaryingInfo
*>(
529 result
, header_size
, entry_size
);
531 const char* data
= LocalGetAs
<const char*>(
532 result
, header_size
+ entry_size
, data_size
);
536 for (uint32_t ii
= 0; ii
< header
->num_transform_feedback_varyings
; ++ii
) {
537 transform_feedback_varyings_
[ii
].size
=
538 static_cast<GLsizei
>(entries
[ii
].size
);
539 transform_feedback_varyings_
[ii
].type
=
540 static_cast<GLenum
>(entries
[ii
].type
);
541 DCHECK_LE(1u, entries
[ii
].name_length
);
542 if (entries
[ii
].name_length
> transform_feedback_varying_max_length_
) {
543 transform_feedback_varying_max_length_
= entries
[ii
].name_length
;
545 size
+= entries
[ii
].name_length
;
546 DCHECK_GE(data_size
, size
);
547 transform_feedback_varyings_
[ii
].name
=
548 std::string(data
, entries
[ii
].name_length
- 1);
549 data
+= entries
[ii
].name_length
;
551 DCHECK_EQ(data_size
, size
);
552 cached_es3_transform_feedback_varyings_
= true;
555 bool ProgramInfoManager::Program::IsCached(ProgramInfoType type
) const {
559 case kES3UniformBlocks
:
560 return cached_es3_uniform_blocks_
;
561 case kES3TransformFeedbackVaryings
:
562 return cached_es3_transform_feedback_varyings_
;
564 return cached_es3_uniformsiv_
;
574 ProgramInfoManager::ProgramInfoManager() {
577 ProgramInfoManager::~ProgramInfoManager() {
580 ProgramInfoManager::Program
* ProgramInfoManager::GetProgramInfo(
581 GLES2Implementation
* gl
, GLuint program
, ProgramInfoType type
) {
582 lock_
.AssertAcquired();
583 ProgramInfoMap::iterator it
= program_infos_
.find(program
);
584 if (it
== program_infos_
.end()) {
587 Program
* info
= &it
->second
;
588 if (info
->IsCached(type
))
591 std::vector
<int8
> result
;
595 base::AutoUnlock
unlock(lock_
);
596 // lock_ can't be held across IPC call or else it may deadlock in
597 // pepper. http://crbug.com/418651
598 gl
->GetProgramInfoCHROMIUMHelper(program
, &result
);
600 info
->UpdateES2(result
);
602 case kES3UniformBlocks
:
604 base::AutoUnlock
unlock(lock_
);
605 // lock_ can't be held across IPC call or else it may deadlock in
606 // pepper. http://crbug.com/418651
607 gl
->GetUniformBlocksCHROMIUMHelper(program
, &result
);
609 info
->UpdateES3UniformBlocks(result
);
611 case kES3TransformFeedbackVaryings
:
613 base::AutoUnlock
unlock(lock_
);
614 // lock_ can't be held across IPC call or else it may deadlock in
615 // pepper. http://crbug.com/418651
616 gl
->GetTransformFeedbackVaryingsCHROMIUMHelper(program
, &result
);
618 info
->UpdateES3TransformFeedbackVaryings(result
);
622 base::AutoUnlock
unlock(lock_
);
623 // lock_ can't be held across IPC call or else it may deadlock in
624 // pepper. http://crbug.com/418651
625 gl
->GetUniformsES3CHROMIUMHelper(program
, &result
);
627 info
->UpdateES3Uniformsiv(result
);
636 void ProgramInfoManager::CreateInfo(GLuint program
) {
637 base::AutoLock
auto_lock(lock_
);
638 program_infos_
.erase(program
);
639 std::pair
<ProgramInfoMap::iterator
, bool> result
=
640 program_infos_
.insert(std::make_pair(program
, Program()));
642 DCHECK(result
.second
);
645 void ProgramInfoManager::DeleteInfo(GLuint program
) {
646 base::AutoLock
auto_lock(lock_
);
647 program_infos_
.erase(program
);
650 bool ProgramInfoManager::GetProgramiv(
651 GLES2Implementation
* gl
, GLuint program
, GLenum pname
, GLint
* params
) {
652 base::AutoLock
auto_lock(lock_
);
653 ProgramInfoType type
= kNone
;
655 case GL_ACTIVE_ATTRIBUTES
:
656 case GL_ACTIVE_ATTRIBUTE_MAX_LENGTH
:
657 case GL_ACTIVE_UNIFORMS
:
658 case GL_ACTIVE_UNIFORM_MAX_LENGTH
:
662 case GL_ACTIVE_UNIFORM_BLOCKS
:
663 case GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH
:
664 type
= kES3UniformBlocks
;
666 case GL_TRANSFORM_FEEDBACK_BUFFER_MODE
:
667 case GL_TRANSFORM_FEEDBACK_VARYINGS
:
668 case GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH
:
669 type
= kES3TransformFeedbackVaryings
;
674 Program
* info
= GetProgramInfo(gl
, program
, type
);
678 return info
->GetProgramiv(pname
, params
);
681 bool ProgramInfoManager::GetActiveUniformsiv(
682 GLES2Implementation
* gl
, GLuint program
, GLsizei count
,
683 const GLuint
* indices
, GLenum pname
, GLint
* params
) {
684 base::AutoLock
auto_lock(lock_
);
685 ProgramInfoType type
= kNone
;
687 case GL_UNIFORM_SIZE
:
688 case GL_UNIFORM_TYPE
:
689 case GL_UNIFORM_NAME_LENGTH
:
692 case GL_UNIFORM_BLOCK_INDEX
:
693 case GL_UNIFORM_OFFSET
:
694 case GL_UNIFORM_ARRAY_STRIDE
:
695 case GL_UNIFORM_MATRIX_STRIDE
:
696 case GL_UNIFORM_IS_ROW_MAJOR
:
697 type
= kES3Uniformsiv
;
702 Program
* info
= GetProgramInfo(gl
, program
, type
);
704 return info
->GetUniformsiv(count
, indices
, pname
, params
);
706 return gl
->GetActiveUniformsivHelper(program
, count
, indices
, pname
, params
);
709 GLint
ProgramInfoManager::GetAttribLocation(
710 GLES2Implementation
* gl
, GLuint program
, const char* name
) {
712 base::AutoLock
auto_lock(lock_
);
713 Program
* info
= GetProgramInfo(gl
, program
, kES2
);
715 return info
->GetAttribLocation(name
);
718 return gl
->GetAttribLocationHelper(program
, name
);
721 GLint
ProgramInfoManager::GetUniformLocation(
722 GLES2Implementation
* gl
, GLuint program
, const char* name
) {
724 base::AutoLock
auto_lock(lock_
);
725 Program
* info
= GetProgramInfo(gl
, program
, kES2
);
727 return info
->GetUniformLocation(name
);
730 return gl
->GetUniformLocationHelper(program
, name
);
733 GLint
ProgramInfoManager::GetFragDataLocation(
734 GLES2Implementation
* gl
, GLuint program
, const char* name
) {
735 // TODO(zmo): make FragData locations part of the ProgramInfo that are
736 // fetched altogether from the service side. See crbug.com/452104.
738 base::AutoLock
auto_lock(lock_
);
739 Program
* info
= GetProgramInfo(gl
, program
, kNone
);
741 GLint possible_loc
= info
->GetFragDataLocation(name
);
742 if (possible_loc
!= -1)
746 GLint loc
= gl
->GetFragDataLocationHelper(program
, name
);
748 base::AutoLock
auto_lock(lock_
);
749 Program
* info
= GetProgramInfo(gl
, program
, kNone
);
751 info
->CacheFragDataLocation(name
, loc
);
757 bool ProgramInfoManager::GetActiveAttrib(
758 GLES2Implementation
* gl
,
759 GLuint program
, GLuint index
, GLsizei bufsize
, GLsizei
* length
,
760 GLint
* size
, GLenum
* type
, char* name
) {
762 base::AutoLock
auto_lock(lock_
);
763 Program
* info
= GetProgramInfo(gl
, program
, kES2
);
765 const Program::VertexAttrib
* attrib_info
= info
->GetAttribInfo(index
);
768 *size
= attrib_info
->size
;
771 *type
= attrib_info
->type
;
773 if (length
|| name
) {
774 GLsizei max_size
= std::min(
775 static_cast<size_t>(bufsize
) - 1,
776 std::max(static_cast<size_t>(0), attrib_info
->name
.size()));
780 if (name
&& bufsize
> 0) {
781 memcpy(name
, attrib_info
->name
.c_str(), max_size
);
782 name
[max_size
] = '\0';
789 return gl
->GetActiveAttribHelper(
790 program
, index
, bufsize
, length
, size
, type
, name
);
793 bool ProgramInfoManager::GetActiveUniform(
794 GLES2Implementation
* gl
,
795 GLuint program
, GLuint index
, GLsizei bufsize
, GLsizei
* length
,
796 GLint
* size
, GLenum
* type
, char* name
) {
798 base::AutoLock
auto_lock(lock_
);
799 Program
* info
= GetProgramInfo(gl
, program
, kES2
);
801 const Program::UniformInfo
* uniform_info
= info
->GetUniformInfo(index
);
804 *size
= uniform_info
->size
;
807 *type
= uniform_info
->type
;
809 if (length
|| name
) {
810 GLsizei max_size
= std::min(
811 static_cast<size_t>(bufsize
) - 1,
812 std::max(static_cast<size_t>(0), uniform_info
->name
.size()));
816 if (name
&& bufsize
> 0) {
817 memcpy(name
, uniform_info
->name
.c_str(), max_size
);
818 name
[max_size
] = '\0';
825 return gl
->GetActiveUniformHelper(
826 program
, index
, bufsize
, length
, size
, type
, name
);
829 GLuint
ProgramInfoManager::GetUniformBlockIndex(
830 GLES2Implementation
* gl
, GLuint program
, const char* name
) {
832 base::AutoLock
auto_lock(lock_
);
833 Program
* info
= GetProgramInfo(gl
, program
, kES3UniformBlocks
);
835 return info
->GetUniformBlockIndex(name
);
838 return gl
->GetUniformBlockIndexHelper(program
, name
);
841 bool ProgramInfoManager::GetActiveUniformBlockName(
842 GLES2Implementation
* gl
, GLuint program
, GLuint index
,
843 GLsizei buf_size
, GLsizei
* length
, char* name
) {
844 DCHECK_LE(0, buf_size
);
849 base::AutoLock
auto_lock(lock_
);
850 Program
* info
= GetProgramInfo(gl
, program
, kES3UniformBlocks
);
852 const Program::UniformBlock
* uniform_block
= info
->GetUniformBlock(index
);
858 } else if (length
|| name
) {
859 GLsizei max_size
= std::min(
860 buf_size
- 1, static_cast<GLsizei
>(uniform_block
->name
.size()));
865 memcpy(name
, uniform_block
->name
.data(), max_size
);
866 name
[max_size
] = '\0';
873 return gl
->GetActiveUniformBlockNameHelper(
874 program
, index
, buf_size
, length
, name
);
877 bool ProgramInfoManager::GetActiveUniformBlockiv(
878 GLES2Implementation
* gl
, GLuint program
, GLuint index
,
879 GLenum pname
, GLint
* params
) {
881 base::AutoLock
auto_lock(lock_
);
882 Program
* info
= GetProgramInfo(gl
, program
, kES3UniformBlocks
);
884 const Program::UniformBlock
* uniform_block
= info
->GetUniformBlock(index
);
887 case GL_UNIFORM_BLOCK_BINDING
:
888 case GL_UNIFORM_BLOCK_DATA_SIZE
:
889 case GL_UNIFORM_BLOCK_NAME_LENGTH
:
890 case GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS
:
891 case GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES
:
892 case GL_UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER
:
893 case GL_UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER
:
900 if (uniform_block
&& valid_pname
&& params
) {
902 case GL_UNIFORM_BLOCK_BINDING
:
903 *params
= static_cast<GLint
>(uniform_block
->binding
);
905 case GL_UNIFORM_BLOCK_DATA_SIZE
:
906 *params
= static_cast<GLint
>(uniform_block
->data_size
);
908 case GL_UNIFORM_BLOCK_NAME_LENGTH
:
909 *params
= static_cast<GLint
>(uniform_block
->name
.size()) + 1;
911 case GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS
:
912 *params
= static_cast<GLint
>(
913 uniform_block
->active_uniform_indices
.size());
915 case GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES
:
917 ii
< uniform_block
->active_uniform_indices
.size(); ++ii
) {
918 params
[ii
] = static_cast<GLint
>(
919 uniform_block
->active_uniform_indices
[ii
]);
922 case GL_UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER
:
923 *params
= static_cast<GLint
>(
924 uniform_block
->referenced_by_vertex_shader
);
926 case GL_UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER
:
927 *params
= static_cast<GLint
>(
928 uniform_block
->referenced_by_fragment_shader
);
937 return gl
->GetActiveUniformBlockivHelper(program
, index
, pname
, params
);
940 void ProgramInfoManager::UniformBlockBinding(
941 GLES2Implementation
* gl
, GLuint program
, GLuint index
, GLuint binding
) {
942 GLuint max_bindings
=
943 static_cast<GLuint
>(gl
->capabilities().max_uniform_buffer_bindings
);
944 if (binding
< max_bindings
) {
945 base::AutoLock
auto_lock(lock_
);
946 // If UniformBlock info haven't been cached yet, skip updating the binding.
947 Program
* info
= GetProgramInfo(gl
, program
, kNone
);
949 info
->UniformBlockBinding(index
, binding
);
954 bool ProgramInfoManager::GetTransformFeedbackVarying(
955 GLES2Implementation
* gl
, GLuint program
, GLuint index
, GLsizei bufsize
,
956 GLsizei
* length
, GLsizei
* size
, GLenum
* type
, char* name
) {
958 base::AutoLock
auto_lock(lock_
);
959 Program
* info
= GetProgramInfo(gl
, program
, kES3TransformFeedbackVaryings
);
961 const Program::TransformFeedbackVarying
* varying
=
962 info
->GetTransformFeedbackVarying(index
);
965 *size
= varying
->size
;
968 *type
= varying
->type
;
970 if (length
|| name
) {
971 GLsizei max_size
= std::min(
972 bufsize
- 1, static_cast<GLsizei
>(varying
->name
.size()));
974 *length
= static_cast<GLsizei
>(max_size
);
976 if (name
&& bufsize
> 0) {
977 memcpy(name
, varying
->name
.c_str(), max_size
);
978 name
[max_size
] = '\0';
985 return gl
->GetTransformFeedbackVaryingHelper(
986 program
, index
, bufsize
, length
, size
, type
, name
);
989 bool ProgramInfoManager::GetUniformIndices(GLES2Implementation
* gl
,
990 GLuint program
, GLsizei count
, const char* const* names
, GLuint
* indices
) {
992 base::AutoLock
auto_lock(lock_
);
993 Program
* info
= GetProgramInfo(gl
, program
, kES2
);
996 DCHECK(names
&& indices
);
997 for (GLsizei ii
= 0; ii
< count
; ++ii
) {
998 indices
[ii
] = info
->GetUniformIndex(names
[ii
]);
1003 return gl
->GetUniformIndicesHelper(program
, count
, names
, indices
);
1006 } // namespace gles2