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 cached_es3_uniformsiv_(false) {
90 ProgramInfoManager::Program::~Program() {
93 // TODO(gman): Add a faster lookup.
94 GLint
ProgramInfoManager::Program::GetAttribLocation(
95 const std::string
& name
) const {
96 for (GLuint ii
= 0; ii
< attrib_infos_
.size(); ++ii
) {
97 const VertexAttrib
& info
= attrib_infos_
[ii
];
98 if (info
.name
== name
) {
105 const ProgramInfoManager::Program::VertexAttrib
*
106 ProgramInfoManager::Program::GetAttribInfo(GLint index
) const {
107 return (static_cast<size_t>(index
) < attrib_infos_
.size()) ?
108 &attrib_infos_
[index
] : NULL
;
111 const ProgramInfoManager::Program::UniformInfo
*
112 ProgramInfoManager::Program::GetUniformInfo(GLint index
) const {
113 return (static_cast<size_t>(index
) < uniform_infos_
.size()) ?
114 &uniform_infos_
[index
] : NULL
;
117 const ProgramInfoManager::Program::UniformBlock
*
118 ProgramInfoManager::Program::GetUniformBlock(GLuint index
) const {
119 return (index
< uniform_blocks_
.size()) ? &uniform_blocks_
[index
] : NULL
;
122 GLint
ProgramInfoManager::Program::GetUniformLocation(
123 const std::string
& name
) const {
124 bool getting_array_location
= false;
125 size_t open_pos
= std::string::npos
;
127 if (!GLES2Util::ParseUniformName(
128 name
, &open_pos
, &index
, &getting_array_location
)) {
131 for (GLuint ii
= 0; ii
< uniform_infos_
.size(); ++ii
) {
132 const UniformInfo
& info
= uniform_infos_
[ii
];
133 if (info
.name
== name
||
135 info
.name
.compare(0, info
.name
.size() - 3, name
) == 0)) {
136 return info
.element_locations
[0];
137 } else if (getting_array_location
&& info
.is_array
) {
138 // Look for an array specification.
139 size_t open_pos_2
= info
.name
.find_last_of('[');
140 if (open_pos_2
== open_pos
&&
141 name
.compare(0, open_pos
, info
.name
, 0, open_pos
) == 0) {
142 if (index
>= 0 && index
< info
.size
) {
143 return info
.element_locations
[index
];
151 GLuint
ProgramInfoManager::Program::GetUniformIndex(
152 const std::string
& name
) const {
153 // TODO(zmo): Maybe build a hashed_map for faster lookup.
154 for (GLuint ii
= 0; ii
< uniform_infos_
.size(); ++ii
) {
155 const UniformInfo
& info
= uniform_infos_
[ii
];
156 // For an array, either "var" or "var[0]" is considered as a match.
157 // See "OpenGL ES 3.0.0, Section 2.11.3 Program Objects."
158 if (info
.name
== name
||
160 info
.name
.compare(0, info
.name
.size() - 3, name
) == 0)) {
164 return GL_INVALID_INDEX
;
167 GLint
ProgramInfoManager::Program::GetFragDataLocation(
168 const std::string
& name
) const {
169 base::hash_map
<std::string
, GLint
>::const_iterator iter
=
170 frag_data_locations_
.find(name
);
171 if (iter
== frag_data_locations_
.end())
176 void ProgramInfoManager::Program::CacheFragDataLocation(
177 const std::string
& name
, GLint loc
) {
178 frag_data_locations_
[name
] = loc
;
181 bool ProgramInfoManager::Program::GetProgramiv(
182 GLenum pname
, GLint
* params
) {
185 *params
= static_cast<GLint
>(link_status_
);
187 case GL_ACTIVE_ATTRIBUTES
:
188 *params
= static_cast<GLint
>(attrib_infos_
.size());
190 case GL_ACTIVE_ATTRIBUTE_MAX_LENGTH
:
191 *params
= static_cast<GLint
>(max_attrib_name_length_
);
193 case GL_ACTIVE_UNIFORMS
:
194 *params
= static_cast<GLint
>(uniform_infos_
.size());
196 case GL_ACTIVE_UNIFORM_MAX_LENGTH
:
197 *params
= static_cast<GLint
>(max_uniform_name_length_
);
199 case GL_ACTIVE_UNIFORM_BLOCKS
:
200 *params
= static_cast<GLint
>(uniform_blocks_
.size());
202 case GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH
:
203 *params
= static_cast<GLint
>(active_uniform_block_max_name_length_
);
205 case GL_TRANSFORM_FEEDBACK_VARYINGS
:
206 *params
= static_cast<GLint
>(transform_feedback_varyings_
.size());
208 case GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH
:
209 *params
= static_cast<GLint
>(transform_feedback_varying_max_length_
);
218 GLuint
ProgramInfoManager::Program::GetUniformBlockIndex(
219 const std::string
& name
) const {
220 for (size_t ii
= 0; ii
< uniform_blocks_
.size(); ++ii
) {
221 if (uniform_blocks_
[ii
].name
== name
) {
222 return static_cast<GLuint
>(ii
);
225 return GL_INVALID_INDEX
;
228 void ProgramInfoManager::Program::UniformBlockBinding(
229 GLuint index
, GLuint binding
) {
230 if (index
< uniform_blocks_
.size()) {
231 uniform_blocks_
[index
].binding
= binding
;
235 const ProgramInfoManager::Program::TransformFeedbackVarying
*
236 ProgramInfoManager::Program::GetTransformFeedbackVarying(GLuint index
) const {
237 return (index
< transform_feedback_varyings_
.size()) ?
238 &transform_feedback_varyings_
[index
] : NULL
;
241 bool ProgramInfoManager::Program::GetUniformsiv(
242 GLsizei count
, const GLuint
* indices
, GLenum pname
, GLint
* params
) {
244 // At this point, pname has already been validated.
247 DCHECK(count
> 0 && indices
);
248 size_t num_uniforms
= uniform_infos_
.size();
249 if (num_uniforms
== 0) {
250 num_uniforms
= uniforms_es3_
.size();
252 if (static_cast<size_t>(count
) > num_uniforms
) {
255 for (GLsizei ii
= 0; ii
< count
; ++ii
) {
256 if (indices
[ii
] >= num_uniforms
) {
264 case GL_UNIFORM_SIZE
:
265 DCHECK_EQ(num_uniforms
, uniform_infos_
.size());
266 for (GLsizei ii
= 0; ii
< count
; ++ii
) {
267 params
[ii
] = static_cast<GLint
>(uniform_infos_
[indices
[ii
]].size
);
270 case GL_UNIFORM_TYPE
:
271 DCHECK_EQ(num_uniforms
, uniform_infos_
.size());
272 for (GLsizei ii
= 0; ii
< count
; ++ii
) {
273 params
[ii
] = static_cast<GLint
>(uniform_infos_
[indices
[ii
]].type
);
276 case GL_UNIFORM_NAME_LENGTH
:
277 DCHECK_EQ(num_uniforms
, uniform_infos_
.size());
278 for (GLsizei ii
= 0; ii
< count
; ++ii
) {
279 params
[ii
] = static_cast<GLint
>(
280 uniform_infos_
[indices
[ii
]].name
.length() + 1);
283 case GL_UNIFORM_BLOCK_INDEX
:
284 DCHECK_EQ(num_uniforms
, uniforms_es3_
.size());
285 for (GLsizei ii
= 0; ii
< count
; ++ii
) {
286 params
[ii
] = uniforms_es3_
[indices
[ii
]].block_index
;
289 case GL_UNIFORM_OFFSET
:
290 DCHECK_EQ(num_uniforms
, uniforms_es3_
.size());
291 for (GLsizei ii
= 0; ii
< count
; ++ii
) {
292 params
[ii
] = uniforms_es3_
[indices
[ii
]].offset
;
295 case GL_UNIFORM_ARRAY_STRIDE
:
296 DCHECK_EQ(num_uniforms
, uniforms_es3_
.size());
297 for (GLsizei ii
= 0; ii
< count
; ++ii
) {
298 params
[ii
] = uniforms_es3_
[indices
[ii
]].array_stride
;
301 case GL_UNIFORM_MATRIX_STRIDE
:
302 DCHECK_EQ(num_uniforms
, uniforms_es3_
.size());
303 for (GLsizei ii
= 0; ii
< count
; ++ii
) {
304 params
[ii
] = uniforms_es3_
[indices
[ii
]].matrix_stride
;
307 case GL_UNIFORM_IS_ROW_MAJOR
:
308 DCHECK_EQ(num_uniforms
, uniforms_es3_
.size());
309 for (GLsizei ii
= 0; ii
< count
; ++ii
) {
310 params
[ii
] = uniforms_es3_
[indices
[ii
]].is_row_major
;
320 void ProgramInfoManager::Program::UpdateES2(const std::vector
<int8
>& result
) {
324 if (result
.empty()) {
325 // This should only happen on a lost context.
328 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;
335 DCHECK_EQ(0u, attrib_infos_
.size());
336 DCHECK_EQ(0u, uniform_infos_
.size());
337 DCHECK_EQ(0, max_attrib_name_length_
);
338 DCHECK_EQ(0, max_uniform_name_length_
);
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_
);
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
);
370 DCHECK_EQ(header
->num_attribs
+ header
->num_uniforms
,
371 static_cast<uint32
>(input
- inputs
));
375 void ProgramInfoManager::Program::UpdateES3UniformBlocks(
376 const std::vector
<int8
>& result
) {
377 if (cached_es3_uniform_blocks_
) {
380 if (result
.empty()) {
381 // This should only happen on a lost context.
384 DCHECK_EQ(0u, uniform_blocks_
.size());
385 DCHECK_EQ(0u, active_uniform_block_max_name_length_
);
387 // |result| comes from GPU process. We consider it trusted data. Therefore,
388 // no need to check for overflows as the GPU side did the checks already.
389 uint32_t header_size
= sizeof(UniformBlocksHeader
);
390 DCHECK_GE(result
.size(), header_size
);
391 const UniformBlocksHeader
* header
= LocalGetAs
<const UniformBlocksHeader
*>(
392 result
, 0, header_size
);
394 if (header
->num_uniform_blocks
== 0) {
395 DCHECK_EQ(result
.size(), header_size
);
396 // TODO(zmo): Here we can't tell if no uniform blocks are defined, or
397 // the previous link failed.
400 uniform_blocks_
.resize(header
->num_uniform_blocks
);
402 uint32_t entry_size
= sizeof(UniformBlockInfo
) * header
->num_uniform_blocks
;
403 DCHECK_GE(result
.size(), header_size
+ entry_size
);
404 uint32_t data_size
= result
.size() - header_size
- entry_size
;
405 DCHECK_LT(0u, data_size
);
406 const UniformBlockInfo
* entries
= LocalGetAs
<const UniformBlockInfo
*>(
407 result
, header_size
, entry_size
);
409 const char* data
= LocalGetAs
<const char*>(
410 result
, header_size
+ entry_size
, data_size
);
414 for (uint32_t ii
= 0; ii
< header
->num_uniform_blocks
; ++ii
) {
415 uniform_blocks_
[ii
].binding
= static_cast<GLuint
>(entries
[ii
].binding
);
416 uniform_blocks_
[ii
].data_size
= static_cast<GLuint
>(entries
[ii
].data_size
);
417 uniform_blocks_
[ii
].active_uniform_indices
.resize(
418 entries
[ii
].active_uniforms
);
419 uniform_blocks_
[ii
].referenced_by_vertex_shader
= static_cast<GLboolean
>(
420 entries
[ii
].referenced_by_vertex_shader
);
421 uniform_blocks_
[ii
].referenced_by_fragment_shader
= static_cast<GLboolean
>(
422 entries
[ii
].referenced_by_fragment_shader
);
423 // Uniform block names can't be empty strings.
424 DCHECK_LT(1u, entries
[ii
].name_length
);
425 if (entries
[ii
].name_length
> active_uniform_block_max_name_length_
) {
426 active_uniform_block_max_name_length_
= entries
[ii
].name_length
;
428 size
+= entries
[ii
].name_length
;
429 DCHECK_GE(data_size
, size
);
430 uniform_blocks_
[ii
].name
= std::string(data
, entries
[ii
].name_length
- 1);
431 data
+= entries
[ii
].name_length
;
432 size
+= entries
[ii
].active_uniforms
* sizeof(uint32_t);
433 DCHECK_GE(data_size
, size
);
434 const uint32_t* indices
= reinterpret_cast<const uint32_t*>(data
);
435 for (uint32_t uu
= 0; uu
< entries
[ii
].active_uniforms
; ++uu
) {
436 uniform_blocks_
[ii
].active_uniform_indices
[uu
] =
437 static_cast<GLuint
>(indices
[uu
]);
439 indices
+= entries
[ii
].active_uniforms
;
440 data
= reinterpret_cast<const char*>(indices
);
442 DCHECK_EQ(data_size
, size
);
443 cached_es3_uniform_blocks_
= true;
446 void ProgramInfoManager::Program::UpdateES3Uniformsiv(
447 const std::vector
<int8
>& result
) {
448 if (cached_es3_uniformsiv_
) {
451 if (result
.empty()) {
452 // This should only happen on a lost context.
455 DCHECK_EQ(0u, uniforms_es3_
.size());
457 // |result| comes from GPU process. We consider it trusted data. Therefore,
458 // no need to check for overflows as the GPU side did the checks already.
459 uint32_t header_size
= sizeof(UniformsES3Header
);
460 DCHECK_GE(result
.size(), header_size
);
461 const UniformsES3Header
* header
= LocalGetAs
<const UniformsES3Header
*>(
462 result
, 0, header_size
);
464 if (header
->num_uniforms
== 0) {
465 DCHECK_EQ(result
.size(), header_size
);
466 // TODO(zmo): Here we can't tell if no uniforms are defined, or
467 // the previous link failed.
470 uniforms_es3_
.resize(header
->num_uniforms
);
472 uint32_t entry_size
= sizeof(UniformES3Info
) * header
->num_uniforms
;
473 DCHECK_EQ(result
.size(), header_size
+ entry_size
);
474 const UniformES3Info
* entries
= LocalGetAs
<const UniformES3Info
*>(
475 result
, header_size
, entry_size
);
478 for (uint32_t ii
= 0; ii
< header
->num_uniforms
; ++ii
) {
479 uniforms_es3_
[ii
].block_index
= entries
[ii
].block_index
;
480 uniforms_es3_
[ii
].offset
= entries
[ii
].offset
;
481 uniforms_es3_
[ii
].array_stride
= entries
[ii
].array_stride
;
482 uniforms_es3_
[ii
].matrix_stride
= entries
[ii
].matrix_stride
;
483 uniforms_es3_
[ii
].is_row_major
= entries
[ii
].is_row_major
;
485 cached_es3_uniformsiv_
= true;
488 void ProgramInfoManager::Program::UpdateES3TransformFeedbackVaryings(
489 const std::vector
<int8
>& result
) {
490 if (cached_es3_transform_feedback_varyings_
) {
493 if (result
.empty()) {
494 // This should only happen on a lost context.
497 DCHECK_EQ(0u, transform_feedback_varyings_
.size());
498 DCHECK_EQ(0u, transform_feedback_varying_max_length_
);
500 // |result| comes from GPU process. We consider it trusted data. Therefore,
501 // no need to check for overflows as the GPU side did the checks already.
502 uint32_t header_size
= sizeof(TransformFeedbackVaryingsHeader
);
503 DCHECK_GE(result
.size(), header_size
);
504 const TransformFeedbackVaryingsHeader
* header
=
505 LocalGetAs
<const TransformFeedbackVaryingsHeader
*>(
506 result
, 0, header_size
);
508 if (header
->num_transform_feedback_varyings
== 0) {
509 DCHECK_EQ(result
.size(), header_size
);
510 // TODO(zmo): Here we can't tell if no TransformFeedback varyings are
511 // defined, or the previous link failed.
514 transform_feedback_varyings_
.resize(header
->num_transform_feedback_varyings
);
516 uint32_t entry_size
= sizeof(TransformFeedbackVaryingInfo
) *
517 header
->num_transform_feedback_varyings
;
518 DCHECK_GE(result
.size(), header_size
+ entry_size
);
519 uint32_t data_size
= result
.size() - header_size
- entry_size
;
520 DCHECK_LT(0u, data_size
);
521 const TransformFeedbackVaryingInfo
* entries
=
522 LocalGetAs
<const TransformFeedbackVaryingInfo
*>(
523 result
, header_size
, entry_size
);
525 const char* data
= LocalGetAs
<const char*>(
526 result
, header_size
+ entry_size
, data_size
);
530 for (uint32_t ii
= 0; ii
< header
->num_transform_feedback_varyings
; ++ii
) {
531 transform_feedback_varyings_
[ii
].size
=
532 static_cast<GLsizei
>(entries
[ii
].size
);
533 transform_feedback_varyings_
[ii
].type
=
534 static_cast<GLenum
>(entries
[ii
].type
);
535 DCHECK_LE(1u, entries
[ii
].name_length
);
536 if (entries
[ii
].name_length
> transform_feedback_varying_max_length_
) {
537 transform_feedback_varying_max_length_
= entries
[ii
].name_length
;
539 size
+= entries
[ii
].name_length
;
540 DCHECK_GE(data_size
, size
);
541 transform_feedback_varyings_
[ii
].name
=
542 std::string(data
, entries
[ii
].name_length
- 1);
543 data
+= entries
[ii
].name_length
;
545 DCHECK_EQ(data_size
, size
);
546 cached_es3_transform_feedback_varyings_
= true;
549 bool ProgramInfoManager::Program::IsCached(ProgramInfoType type
) const {
553 case kES3UniformBlocks
:
554 return cached_es3_uniform_blocks_
;
555 case kES3TransformFeedbackVaryings
:
556 return cached_es3_transform_feedback_varyings_
;
558 return cached_es3_uniformsiv_
;
568 ProgramInfoManager::ProgramInfoManager() {
571 ProgramInfoManager::~ProgramInfoManager() {
574 ProgramInfoManager::Program
* ProgramInfoManager::GetProgramInfo(
575 GLES2Implementation
* gl
, GLuint program
, ProgramInfoType type
) {
576 lock_
.AssertAcquired();
577 ProgramInfoMap::iterator it
= program_infos_
.find(program
);
578 if (it
== program_infos_
.end()) {
581 Program
* info
= &it
->second
;
582 if (info
->IsCached(type
))
585 std::vector
<int8
> result
;
589 base::AutoUnlock
unlock(lock_
);
590 // lock_ can't be held across IPC call or else it may deadlock in
591 // pepper. http://crbug.com/418651
592 gl
->GetProgramInfoCHROMIUMHelper(program
, &result
);
594 info
->UpdateES2(result
);
596 case kES3UniformBlocks
:
598 base::AutoUnlock
unlock(lock_
);
599 // lock_ can't be held across IPC call or else it may deadlock in
600 // pepper. http://crbug.com/418651
601 gl
->GetUniformBlocksCHROMIUMHelper(program
, &result
);
603 info
->UpdateES3UniformBlocks(result
);
605 case kES3TransformFeedbackVaryings
:
607 base::AutoUnlock
unlock(lock_
);
608 // lock_ can't be held across IPC call or else it may deadlock in
609 // pepper. http://crbug.com/418651
610 gl
->GetTransformFeedbackVaryingsCHROMIUMHelper(program
, &result
);
612 info
->UpdateES3TransformFeedbackVaryings(result
);
615 base::AutoUnlock
unlock(lock_
);
616 // lock_ can't be held across IPC call or else it may deadlock in
617 // pepper. http://crbug.com/418651
618 gl
->GetUniformsES3CHROMIUMHelper(program
, &result
);
620 info
->UpdateES3Uniformsiv(result
);
628 void ProgramInfoManager::CreateInfo(GLuint program
) {
629 base::AutoLock
auto_lock(lock_
);
630 program_infos_
.erase(program
);
631 std::pair
<ProgramInfoMap::iterator
, bool> result
=
632 program_infos_
.insert(std::make_pair(program
, Program()));
634 DCHECK(result
.second
);
637 void ProgramInfoManager::DeleteInfo(GLuint program
) {
638 base::AutoLock
auto_lock(lock_
);
639 program_infos_
.erase(program
);
642 bool ProgramInfoManager::GetProgramiv(
643 GLES2Implementation
* gl
, GLuint program
, GLenum pname
, GLint
* params
) {
644 base::AutoLock
auto_lock(lock_
);
645 ProgramInfoType type
= kNone
;
647 case GL_ACTIVE_ATTRIBUTES
:
648 case GL_ACTIVE_ATTRIBUTE_MAX_LENGTH
:
649 case GL_ACTIVE_UNIFORMS
:
650 case GL_ACTIVE_UNIFORM_MAX_LENGTH
:
654 case GL_ACTIVE_UNIFORM_BLOCKS
:
655 case GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH
:
656 type
= kES3UniformBlocks
;
658 case GL_TRANSFORM_FEEDBACK_VARYINGS
:
659 case GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH
:
660 type
= kES3TransformFeedbackVaryings
;
665 Program
* info
= GetProgramInfo(gl
, program
, type
);
669 return info
->GetProgramiv(pname
, params
);
672 bool ProgramInfoManager::GetActiveUniformsiv(
673 GLES2Implementation
* gl
, GLuint program
, GLsizei count
,
674 const GLuint
* indices
, GLenum pname
, GLint
* params
) {
675 base::AutoLock
auto_lock(lock_
);
676 ProgramInfoType type
= kNone
;
678 case GL_UNIFORM_SIZE
:
679 case GL_UNIFORM_TYPE
:
680 case GL_UNIFORM_NAME_LENGTH
:
683 case GL_UNIFORM_BLOCK_INDEX
:
684 case GL_UNIFORM_OFFSET
:
685 case GL_UNIFORM_ARRAY_STRIDE
:
686 case GL_UNIFORM_MATRIX_STRIDE
:
687 case GL_UNIFORM_IS_ROW_MAJOR
:
688 type
= kES3Uniformsiv
;
693 Program
* info
= GetProgramInfo(gl
, program
, type
);
695 return info
->GetUniformsiv(count
, indices
, pname
, params
);
697 return gl
->GetActiveUniformsivHelper(program
, count
, indices
, pname
, params
);
700 GLint
ProgramInfoManager::GetAttribLocation(
701 GLES2Implementation
* gl
, GLuint program
, const char* name
) {
703 base::AutoLock
auto_lock(lock_
);
704 Program
* info
= GetProgramInfo(gl
, program
, kES2
);
706 return info
->GetAttribLocation(name
);
709 return gl
->GetAttribLocationHelper(program
, name
);
712 GLint
ProgramInfoManager::GetUniformLocation(
713 GLES2Implementation
* gl
, GLuint program
, const char* name
) {
715 base::AutoLock
auto_lock(lock_
);
716 Program
* info
= GetProgramInfo(gl
, program
, kES2
);
718 return info
->GetUniformLocation(name
);
721 return gl
->GetUniformLocationHelper(program
, name
);
724 GLint
ProgramInfoManager::GetFragDataLocation(
725 GLES2Implementation
* gl
, GLuint program
, const char* name
) {
726 // TODO(zmo): make FragData locations part of the ProgramInfo that are
727 // fetched altogether from the service side. See crbug.com/452104.
729 base::AutoLock
auto_lock(lock_
);
730 Program
* info
= GetProgramInfo(gl
, program
, kNone
);
732 GLint possible_loc
= info
->GetFragDataLocation(name
);
733 if (possible_loc
!= -1)
737 GLint loc
= gl
->GetFragDataLocationHelper(program
, name
);
739 base::AutoLock
auto_lock(lock_
);
740 Program
* info
= GetProgramInfo(gl
, program
, kNone
);
742 info
->CacheFragDataLocation(name
, loc
);
748 bool ProgramInfoManager::GetActiveAttrib(
749 GLES2Implementation
* gl
,
750 GLuint program
, GLuint index
, GLsizei bufsize
, GLsizei
* length
,
751 GLint
* size
, GLenum
* type
, char* name
) {
753 base::AutoLock
auto_lock(lock_
);
754 Program
* info
= GetProgramInfo(gl
, program
, kES2
);
756 const Program::VertexAttrib
* attrib_info
= info
->GetAttribInfo(index
);
759 *size
= attrib_info
->size
;
762 *type
= attrib_info
->type
;
764 if (length
|| name
) {
765 GLsizei max_size
= std::min(
766 static_cast<size_t>(bufsize
) - 1,
767 std::max(static_cast<size_t>(0), attrib_info
->name
.size()));
771 if (name
&& bufsize
> 0) {
772 memcpy(name
, attrib_info
->name
.c_str(), max_size
);
773 name
[max_size
] = '\0';
780 return gl
->GetActiveAttribHelper(
781 program
, index
, bufsize
, length
, size
, type
, name
);
784 bool ProgramInfoManager::GetActiveUniform(
785 GLES2Implementation
* gl
,
786 GLuint program
, GLuint index
, GLsizei bufsize
, GLsizei
* length
,
787 GLint
* size
, GLenum
* type
, char* name
) {
789 base::AutoLock
auto_lock(lock_
);
790 Program
* info
= GetProgramInfo(gl
, program
, kES2
);
792 const Program::UniformInfo
* uniform_info
= info
->GetUniformInfo(index
);
795 *size
= uniform_info
->size
;
798 *type
= uniform_info
->type
;
800 if (length
|| name
) {
801 GLsizei max_size
= std::min(
802 static_cast<size_t>(bufsize
) - 1,
803 std::max(static_cast<size_t>(0), uniform_info
->name
.size()));
807 if (name
&& bufsize
> 0) {
808 memcpy(name
, uniform_info
->name
.c_str(), max_size
);
809 name
[max_size
] = '\0';
816 return gl
->GetActiveUniformHelper(
817 program
, index
, bufsize
, length
, size
, type
, name
);
820 GLuint
ProgramInfoManager::GetUniformBlockIndex(
821 GLES2Implementation
* gl
, GLuint program
, const char* name
) {
823 base::AutoLock
auto_lock(lock_
);
824 Program
* info
= GetProgramInfo(gl
, program
, kES3UniformBlocks
);
826 return info
->GetUniformBlockIndex(name
);
829 return gl
->GetUniformBlockIndexHelper(program
, name
);
832 bool ProgramInfoManager::GetActiveUniformBlockName(
833 GLES2Implementation
* gl
, GLuint program
, GLuint index
,
834 GLsizei buf_size
, GLsizei
* length
, char* name
) {
835 DCHECK_LE(0, buf_size
);
840 base::AutoLock
auto_lock(lock_
);
841 Program
* info
= GetProgramInfo(gl
, program
, kES3UniformBlocks
);
843 const Program::UniformBlock
* uniform_block
= info
->GetUniformBlock(index
);
849 } else if (length
|| name
) {
850 GLsizei max_size
= std::min(
851 buf_size
- 1, static_cast<GLsizei
>(uniform_block
->name
.size()));
856 memcpy(name
, uniform_block
->name
.data(), max_size
);
857 name
[max_size
] = '\0';
864 return gl
->GetActiveUniformBlockNameHelper(
865 program
, index
, buf_size
, length
, name
);
868 bool ProgramInfoManager::GetActiveUniformBlockiv(
869 GLES2Implementation
* gl
, GLuint program
, GLuint index
,
870 GLenum pname
, GLint
* params
) {
872 base::AutoLock
auto_lock(lock_
);
873 Program
* info
= GetProgramInfo(gl
, program
, kES3UniformBlocks
);
875 const Program::UniformBlock
* uniform_block
= info
->GetUniformBlock(index
);
878 case GL_UNIFORM_BLOCK_BINDING
:
879 case GL_UNIFORM_BLOCK_DATA_SIZE
:
880 case GL_UNIFORM_BLOCK_NAME_LENGTH
:
881 case GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS
:
882 case GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES
:
883 case GL_UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER
:
884 case GL_UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER
:
891 if (uniform_block
&& valid_pname
&& params
) {
893 case GL_UNIFORM_BLOCK_BINDING
:
894 *params
= static_cast<GLint
>(uniform_block
->binding
);
896 case GL_UNIFORM_BLOCK_DATA_SIZE
:
897 *params
= static_cast<GLint
>(uniform_block
->data_size
);
899 case GL_UNIFORM_BLOCK_NAME_LENGTH
:
900 *params
= static_cast<GLint
>(uniform_block
->name
.size()) + 1;
902 case GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS
:
903 *params
= static_cast<GLint
>(
904 uniform_block
->active_uniform_indices
.size());
906 case GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES
:
908 ii
< uniform_block
->active_uniform_indices
.size(); ++ii
) {
909 params
[ii
] = static_cast<GLint
>(
910 uniform_block
->active_uniform_indices
[ii
]);
913 case GL_UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER
:
914 *params
= static_cast<GLint
>(
915 uniform_block
->referenced_by_vertex_shader
);
917 case GL_UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER
:
918 *params
= static_cast<GLint
>(
919 uniform_block
->referenced_by_fragment_shader
);
928 return gl
->GetActiveUniformBlockivHelper(program
, index
, pname
, params
);
931 void ProgramInfoManager::UniformBlockBinding(
932 GLES2Implementation
* gl
, GLuint program
, GLuint index
, GLuint binding
) {
933 GLuint max_bindings
=
934 static_cast<GLuint
>(gl
->capabilities().max_uniform_buffer_bindings
);
935 if (binding
< max_bindings
) {
936 base::AutoLock
auto_lock(lock_
);
937 // If UniformBlock info haven't been cached yet, skip updating the binding.
938 Program
* info
= GetProgramInfo(gl
, program
, kNone
);
940 info
->UniformBlockBinding(index
, binding
);
945 bool ProgramInfoManager::GetTransformFeedbackVarying(
946 GLES2Implementation
* gl
, GLuint program
, GLuint index
, GLsizei bufsize
,
947 GLsizei
* length
, GLsizei
* size
, GLenum
* type
, char* name
) {
949 base::AutoLock
auto_lock(lock_
);
950 Program
* info
= GetProgramInfo(gl
, program
, kES3TransformFeedbackVaryings
);
952 const Program::TransformFeedbackVarying
* varying
=
953 info
->GetTransformFeedbackVarying(index
);
956 *size
= varying
->size
;
959 *type
= varying
->type
;
961 if (length
|| name
) {
962 GLsizei max_size
= std::min(
963 bufsize
- 1, static_cast<GLsizei
>(varying
->name
.size()));
965 *length
= static_cast<GLsizei
>(max_size
);
967 if (name
&& bufsize
> 0) {
968 memcpy(name
, varying
->name
.c_str(), max_size
);
969 name
[max_size
] = '\0';
976 return gl
->GetTransformFeedbackVaryingHelper(
977 program
, index
, bufsize
, length
, size
, type
, name
);
980 bool ProgramInfoManager::GetUniformIndices(GLES2Implementation
* gl
,
981 GLuint program
, GLsizei count
, const char* const* names
, GLuint
* indices
) {
983 base::AutoLock
auto_lock(lock_
);
984 Program
* info
= GetProgramInfo(gl
, program
, kES2
);
987 DCHECK(names
&& indices
);
988 for (GLsizei ii
= 0; ii
< count
; ++ii
) {
989 indices
[ii
] = info
->GetUniformIndex(names
[ii
]);
994 return gl
->GetUniformIndicesHelper(program
, count
, names
, indices
);