OLD | NEW |
---|---|
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "gpu/command_buffer/service/texture_manager.h" | 5 #include "gpu/command_buffer/service/texture_manager.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 #include <utility> | 8 #include <utility> |
9 | 9 |
10 #include "base/bits.h" | 10 #include "base/bits.h" |
(...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
121 DCHECK_EQ(0u, memory_tracker_managed_->GetMemRepresented()); | 121 DCHECK_EQ(0u, memory_tracker_managed_->GetMemRepresented()); |
122 DCHECK_EQ(0u, memory_tracker_unmanaged_->GetMemRepresented()); | 122 DCHECK_EQ(0u, memory_tracker_unmanaged_->GetMemRepresented()); |
123 } | 123 } |
124 | 124 |
125 Texture::Texture(GLuint service_id) | 125 Texture::Texture(GLuint service_id) |
126 : mailbox_manager_(NULL), | 126 : mailbox_manager_(NULL), |
127 memory_tracking_ref_(NULL), | 127 memory_tracking_ref_(NULL), |
128 service_id_(service_id), | 128 service_id_(service_id), |
129 cleared_(true), | 129 cleared_(true), |
130 num_uncleared_mips_(0), | 130 num_uncleared_mips_(0), |
131 num_npot_faces_(0), | |
132 num_complete_faces_(0), | |
133 num_incomplete_mips_(0), | |
131 target_(0), | 134 target_(0), |
132 min_filter_(GL_NEAREST_MIPMAP_LINEAR), | 135 min_filter_(GL_NEAREST_MIPMAP_LINEAR), |
133 mag_filter_(GL_LINEAR), | 136 mag_filter_(GL_LINEAR), |
134 wrap_s_(GL_REPEAT), | 137 wrap_s_(GL_REPEAT), |
135 wrap_t_(GL_REPEAT), | 138 wrap_t_(GL_REPEAT), |
136 usage_(GL_NONE), | 139 usage_(GL_NONE), |
137 pool_(GL_TEXTURE_POOL_UNMANAGED_CHROMIUM), | 140 pool_(GL_TEXTURE_POOL_UNMANAGED_CHROMIUM), |
138 max_level_set_(-1), | 141 max_level_set_(-1), |
139 texture_complete_(false), | 142 texture_complete_(false), |
140 cube_complete_(false), | 143 cube_complete_(false), |
(...skipping 181 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
322 if (!CanGenerateMipmaps(feature_info)) { | 325 if (!CanGenerateMipmaps(feature_info)) { |
323 return false; | 326 return false; |
324 } | 327 } |
325 for (size_t ii = 0; ii < level_infos_.size(); ++ii) { | 328 for (size_t ii = 0; ii < level_infos_.size(); ++ii) { |
326 const Texture::LevelInfo& info1 = level_infos_[ii][0]; | 329 const Texture::LevelInfo& info1 = level_infos_[ii][0]; |
327 GLsizei width = info1.width; | 330 GLsizei width = info1.width; |
328 GLsizei height = info1.height; | 331 GLsizei height = info1.height; |
329 GLsizei depth = info1.depth; | 332 GLsizei depth = info1.depth; |
330 GLenum target = target_ == GL_TEXTURE_2D ? GL_TEXTURE_2D : | 333 GLenum target = target_ == GL_TEXTURE_2D ? GL_TEXTURE_2D : |
331 GLES2Util::IndexToGLFaceTarget(ii); | 334 GLES2Util::IndexToGLFaceTarget(ii); |
332 int num_mips = | 335 |
333 TextureManager::ComputeMipMapCount(target_, width, height, depth); | 336 const int num_mips = num_mip_levels_[ii]; |
334 for (int level = 1; level < num_mips; ++level) { | 337 for (int level = 1; level < num_mips; ++level) { |
335 width = std::max(1, width >> 1); | 338 width = std::max(1, width >> 1); |
336 height = std::max(1, height >> 1); | 339 height = std::max(1, height >> 1); |
337 depth = std::max(1, depth >> 1); | 340 depth = std::max(1, depth >> 1); |
338 SetLevelInfo(feature_info, | 341 SetLevelInfo(feature_info, |
339 target, | 342 target, |
340 level, | 343 level, |
341 info1.internal_format, | 344 info1.internal_format, |
342 width, | 345 width, |
343 height, | 346 height, |
(...skipping 10 matching lines...) Expand all Loading... | |
354 | 357 |
355 void Texture::SetTarget( | 358 void Texture::SetTarget( |
356 const FeatureInfo* feature_info, GLenum target, GLint max_levels) { | 359 const FeatureInfo* feature_info, GLenum target, GLint max_levels) { |
357 DCHECK_EQ(0u, target_); // you can only set this once. | 360 DCHECK_EQ(0u, target_); // you can only set this once. |
358 target_ = target; | 361 target_ = target; |
359 size_t num_faces = (target == GL_TEXTURE_CUBE_MAP) ? 6 : 1; | 362 size_t num_faces = (target == GL_TEXTURE_CUBE_MAP) ? 6 : 1; |
360 level_infos_.resize(num_faces); | 363 level_infos_.resize(num_faces); |
361 for (size_t ii = 0; ii < num_faces; ++ii) { | 364 for (size_t ii = 0; ii < num_faces; ++ii) { |
362 level_infos_[ii].resize(max_levels); | 365 level_infos_[ii].resize(max_levels); |
363 } | 366 } |
367 num_mip_levels_.resize(num_faces); | |
364 | 368 |
365 if (target == GL_TEXTURE_EXTERNAL_OES || target == GL_TEXTURE_RECTANGLE_ARB) { | 369 if (target == GL_TEXTURE_EXTERNAL_OES || target == GL_TEXTURE_RECTANGLE_ARB) { |
366 min_filter_ = GL_LINEAR; | 370 min_filter_ = GL_LINEAR; |
367 wrap_s_ = wrap_t_ = GL_CLAMP_TO_EDGE; | 371 wrap_s_ = wrap_t_ = GL_CLAMP_TO_EDGE; |
368 } | 372 } |
369 | 373 |
370 if (target == GL_TEXTURE_EXTERNAL_OES) { | 374 if (target == GL_TEXTURE_EXTERNAL_OES) { |
371 immutable_ = true; | 375 immutable_ = true; |
372 } | 376 } |
373 Update(feature_info); | 377 Update(feature_info); |
(...skipping 26 matching lines...) Expand all Loading... | |
400 (info.type != first.type) || | 404 (info.type != first.type) || |
401 feature_info->validators()->compressed_texture_format.IsValid( | 405 feature_info->validators()->compressed_texture_format.IsValid( |
402 info.internal_format) || | 406 info.internal_format) || |
403 info.image.get()) { | 407 info.image.get()) { |
404 return false; | 408 return false; |
405 } | 409 } |
406 } | 410 } |
407 return true; | 411 return true; |
408 } | 412 } |
409 | 413 |
414 bool Texture::TextureIsNPOT(GLsizei width, | |
415 GLsizei height, | |
416 GLsizei depth) { | |
417 return (GLES2Util::IsNPOT(width) || | |
418 GLES2Util::IsNPOT(height) || | |
419 GLES2Util::IsNPOT(depth)); | |
420 } | |
421 | |
422 bool Texture::TextureFaceComplete(const Texture::LevelInfo& first_face, | |
423 size_t face_index, | |
424 GLenum target, | |
425 GLenum internal_format, | |
426 GLsizei width, | |
427 GLsizei height, | |
428 GLsizei depth, | |
429 GLenum format, | |
430 GLenum type) { | |
431 bool complete = (target != 0 && depth == 1); | |
432 if (face_index != 0) { | |
433 complete &= (width == first_face.width && | |
434 height == first_face.height && | |
435 internal_format == first_face.internal_format && | |
436 format == first_face.format && | |
437 type == first_face.type); | |
438 } | |
439 return complete; | |
440 } | |
441 | |
442 bool Texture::TextureMipComplete(const Texture::LevelInfo& level0_face, | |
443 GLenum target, | |
444 GLint level, | |
445 GLenum internal_format, | |
446 GLsizei width, | |
447 GLsizei height, | |
448 GLsizei depth, | |
449 GLenum format, | |
450 GLenum type) { | |
451 bool complete = (target != 0); | |
452 if (level != 0) { | |
453 const GLsizei mip_width = std::max(1, level0_face.width >> level); | |
454 const GLsizei mip_height = std::max(1, level0_face.height >> level); | |
455 const GLsizei mip_depth = std::max(1, level0_face.depth >> level); | |
vmiura
2014/10/07 00:13:03
Do we need to handle the case of width/height/dept
David Yen
2014/10/09 20:20:16
That check is already done before this function is
| |
456 | |
457 complete &= (width == mip_width && | |
458 height == mip_height && | |
459 depth == mip_depth && | |
460 internal_format == level0_face.internal_format && | |
461 format == level0_face.format && | |
462 type == level0_face.type); | |
463 } | |
464 return complete; | |
465 } | |
466 | |
410 void Texture::SetLevelCleared(GLenum target, GLint level, bool cleared) { | 467 void Texture::SetLevelCleared(GLenum target, GLint level, bool cleared) { |
411 DCHECK_GE(level, 0); | 468 DCHECK_GE(level, 0); |
412 size_t face_index = GLES2Util::GLTargetToFaceIndex(target); | 469 size_t face_index = GLES2Util::GLTargetToFaceIndex(target); |
413 DCHECK_LT(static_cast<size_t>(face_index), | 470 DCHECK_LT(static_cast<size_t>(face_index), |
414 level_infos_.size()); | 471 level_infos_.size()); |
415 DCHECK_LT(static_cast<size_t>(level), | 472 DCHECK_LT(static_cast<size_t>(level), |
416 level_infos_[face_index].size()); | 473 level_infos_[face_index].size()); |
417 Texture::LevelInfo& info = | 474 Texture::LevelInfo& info = |
418 level_infos_[face_index][level]; | 475 level_infos_[face_index][level]; |
419 UpdateMipCleared(&info, cleared); | 476 UpdateMipCleared(&info, cleared); |
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
509 size_t face_index = GLES2Util::GLTargetToFaceIndex(target); | 566 size_t face_index = GLES2Util::GLTargetToFaceIndex(target); |
510 DCHECK_LT(static_cast<size_t>(face_index), | 567 DCHECK_LT(static_cast<size_t>(face_index), |
511 level_infos_.size()); | 568 level_infos_.size()); |
512 DCHECK_LT(static_cast<size_t>(level), | 569 DCHECK_LT(static_cast<size_t>(level), |
513 level_infos_[face_index].size()); | 570 level_infos_[face_index].size()); |
514 DCHECK_GE(width, 0); | 571 DCHECK_GE(width, 0); |
515 DCHECK_GE(height, 0); | 572 DCHECK_GE(height, 0); |
516 DCHECK_GE(depth, 0); | 573 DCHECK_GE(depth, 0); |
517 Texture::LevelInfo& info = | 574 Texture::LevelInfo& info = |
518 level_infos_[face_index][level]; | 575 level_infos_[face_index][level]; |
576 | |
577 // Update counters only if any attributes have changed. Counters are | |
578 // comparisons between the old and new values so it must be done before any | |
579 // assignment has been done to the LevelInfo. | |
580 if (info.target != target || | |
581 info.internal_format != internal_format || | |
582 info.width != width || | |
583 info.height != height || | |
584 info.depth != depth || | |
585 info.format != format || | |
586 info.type != type) { | |
587 if (level == 0) { | |
588 // Calculate the mip level count. | |
589 num_mip_levels_[face_index] = TextureManager::ComputeMipMapCount( | |
590 target_, width, height, depth); | |
591 | |
592 // Update NPOT face count for the first level. | |
593 bool prev_npot = TextureIsNPOT(info.width, info.height, info.depth); | |
594 bool now_npot = TextureIsNPOT(width, height, depth); | |
595 if (prev_npot != now_npot) | |
596 num_npot_faces_ += now_npot ? 1 : -1; | |
597 | |
598 // Update number of complete faces. | |
599 const Texture::LevelInfo& first_face = level_infos_[0][0]; | |
600 for (size_t i = face_index; i < level_infos_.size(); ++i) { | |
vmiura
2014/10/07 00:13:03
I think this compares face 0 to itself, so I think
David Yen
2014/10/09 20:20:16
No longer relevant, using dirty bit now.
| |
601 bool prev_face_status = TextureFaceComplete(first_face, | |
602 face_index, | |
603 info.target, | |
604 info.internal_format, | |
605 info.width, | |
606 info.height, | |
607 info.depth, | |
608 info.format, | |
609 info.type); | |
610 bool new_face_status = TextureFaceComplete(first_face, | |
611 face_index, | |
612 target, | |
613 internal_format, | |
614 width, | |
615 height, | |
616 depth, | |
617 format, | |
618 type); | |
619 if (prev_face_status != new_face_status) | |
620 num_complete_faces_ += new_face_status ? 1 : -1; | |
621 | |
622 // Only need to validate all faces if the first face is changing. | |
623 if (face_index != 0) | |
624 break; | |
625 } | |
626 } | |
627 | |
628 // Update incomplete mip counter. | |
629 const Texture::LevelInfo& level0_face = level_infos_[face_index][0]; | |
630 const GLsizei num_mip_levels = num_mip_levels_[face_index]; | |
vmiura
2014/10/07 00:13:03
If num_mip_levels changes, for example decreasing,
David Yen
2014/10/09 20:20:16
No longer relevant, using dirty bit now.
| |
631 for (GLsizei i = static_cast<GLsizei>(level); i < num_mip_levels; ++i) { | |
632 bool prev_mip_status = TextureMipComplete(level0_face, | |
633 info.target, | |
634 i, | |
635 info.internal_format, | |
636 info.width, | |
637 info.height, | |
638 info.depth, | |
639 info.format, | |
640 info.type); | |
641 bool new_mip_status = TextureMipComplete(level0_face, | |
642 target, | |
643 i, | |
644 internal_format, | |
645 width, | |
646 height, | |
647 depth, | |
648 format, | |
649 type); | |
650 if (prev_mip_status != new_mip_status) | |
651 num_incomplete_mips_ += new_mip_status ? -1 : 1; | |
vmiura
2014/10/07 00:13:03
As above, I'm not sure we will count correctly whe
David Yen
2014/10/09 20:20:16
No longer relevant, using dirty bit now.
| |
652 | |
653 // Only need to validate all faces if the first face is changing. | |
654 if (face_index != 0) | |
655 break; | |
656 } | |
657 } | |
658 | |
519 info.target = target; | 659 info.target = target; |
520 info.level = level; | 660 info.level = level; |
521 info.internal_format = internal_format; | 661 info.internal_format = internal_format; |
522 info.width = width; | 662 info.width = width; |
523 info.height = height; | 663 info.height = height; |
524 info.depth = depth; | 664 info.depth = depth; |
525 info.border = border; | 665 info.border = border; |
526 info.format = format; | 666 info.format = format; |
527 info.type = type; | 667 info.type = type; |
528 info.image = 0; | 668 info.image = 0; |
(...skipping 164 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
693 default: | 833 default: |
694 NOTREACHED(); | 834 NOTREACHED(); |
695 return GL_INVALID_ENUM; | 835 return GL_INVALID_ENUM; |
696 } | 836 } |
697 return GL_NO_ERROR; | 837 return GL_NO_ERROR; |
698 } | 838 } |
699 | 839 |
700 void Texture::Update(const FeatureInfo* feature_info) { | 840 void Texture::Update(const FeatureInfo* feature_info) { |
701 // Update npot status. | 841 // Update npot status. |
702 // Assume GL_TEXTURE_EXTERNAL_OES textures are npot, all others | 842 // Assume GL_TEXTURE_EXTERNAL_OES textures are npot, all others |
703 npot_ = target_ == GL_TEXTURE_EXTERNAL_OES; | 843 npot_ = (target_ == GL_TEXTURE_EXTERNAL_OES) || (num_npot_faces_ > 0); |
704 | 844 |
705 if (level_infos_.empty()) { | 845 if (level_infos_.empty()) { |
706 texture_complete_ = false; | 846 texture_complete_ = false; |
707 cube_complete_ = false; | 847 cube_complete_ = false; |
708 return; | 848 return; |
709 } | 849 } |
710 | 850 |
711 // checks that the first mip of any face is npot. | |
712 for (size_t ii = 0; ii < level_infos_.size(); ++ii) { | |
713 const Texture::LevelInfo& info = level_infos_[ii][0]; | |
714 if (GLES2Util::IsNPOT(info.width) || | |
715 GLES2Util::IsNPOT(info.height) || | |
716 GLES2Util::IsNPOT(info.depth)) { | |
717 npot_ = true; | |
718 break; | |
719 } | |
720 } | |
721 | |
722 // Update texture_complete and cube_complete status. | 851 // Update texture_complete and cube_complete status. |
723 const Texture::LevelInfo& first_face = level_infos_[0][0]; | 852 const Texture::LevelInfo& first_face = level_infos_[0][0]; |
724 int levels_needed = TextureManager::ComputeMipMapCount( | 853 int levels_needed = num_mip_levels_[0]; |
725 target_, first_face.width, first_face.height, first_face.depth); | |
726 texture_complete_ = | 854 texture_complete_ = |
727 max_level_set_ >= (levels_needed - 1) && max_level_set_ >= 0; | 855 max_level_set_ >= (levels_needed - 1) && max_level_set_ >= 0; |
728 cube_complete_ = (level_infos_.size() == 6) && | 856 cube_complete_ = (level_infos_.size() == 6) && |
729 (first_face.width == first_face.height); | 857 (first_face.width == first_face.height) && |
858 (num_complete_faces_ == 6); | |
730 | 859 |
731 if (first_face.width == 0 || first_face.height == 0) { | 860 if (first_face.width == 0 || first_face.height == 0) { |
732 texture_complete_ = false; | 861 texture_complete_ = false; |
733 } | 862 } else if (first_face.type == GL_FLOAT && |
734 if (first_face.type == GL_FLOAT && | 863 !feature_info->feature_flags().enable_texture_float_linear && |
735 !feature_info->feature_flags().enable_texture_float_linear && | 864 (min_filter_ != GL_NEAREST_MIPMAP_NEAREST || |
736 (min_filter_ != GL_NEAREST_MIPMAP_NEAREST || | 865 mag_filter_ != GL_NEAREST)) { |
737 mag_filter_ != GL_NEAREST)) { | |
738 texture_complete_ = false; | 866 texture_complete_ = false; |
739 } else if (first_face.type == GL_HALF_FLOAT_OES && | 867 } else if (first_face.type == GL_HALF_FLOAT_OES && |
740 !feature_info->feature_flags().enable_texture_half_float_linear && | 868 !feature_info->feature_flags().enable_texture_half_float_linear && |
741 (min_filter_ != GL_NEAREST_MIPMAP_NEAREST || | 869 (min_filter_ != GL_NEAREST_MIPMAP_NEAREST || |
742 mag_filter_ != GL_NEAREST)) { | 870 mag_filter_ != GL_NEAREST)) { |
743 texture_complete_ = false; | 871 texture_complete_ = false; |
744 } | 872 } else if (num_incomplete_mips_ > 0) { |
745 for (size_t ii = 0; | 873 texture_complete_ = false; |
746 ii < level_infos_.size() && (cube_complete_ || texture_complete_); | |
747 ++ii) { | |
748 const Texture::LevelInfo& level0 = level_infos_[ii][0]; | |
749 if (level0.target == 0 || | |
750 level0.width != first_face.width || | |
751 level0.height != first_face.height || | |
752 level0.depth != 1 || | |
753 level0.internal_format != first_face.internal_format || | |
754 level0.format != first_face.format || | |
755 level0.type != first_face.type) { | |
756 cube_complete_ = false; | |
757 } | |
758 // Get level0 dimensions | |
759 GLsizei width = level0.width; | |
760 GLsizei height = level0.height; | |
761 GLsizei depth = level0.depth; | |
762 for (GLint jj = 1; jj < levels_needed; ++jj) { | |
763 // compute required size for mip. | |
764 width = std::max(1, width >> 1); | |
765 height = std::max(1, height >> 1); | |
766 depth = std::max(1, depth >> 1); | |
767 const Texture::LevelInfo& info = level_infos_[ii][jj]; | |
768 if (info.target == 0 || | |
769 info.width != width || | |
770 info.height != height || | |
771 info.depth != depth || | |
772 info.internal_format != level0.internal_format || | |
773 info.format != level0.format || | |
774 info.type != level0.type) { | |
775 texture_complete_ = false; | |
776 break; | |
777 } | |
778 } | |
779 } | 874 } |
780 } | 875 } |
781 | 876 |
782 bool Texture::ClearRenderableLevels(GLES2Decoder* decoder) { | 877 bool Texture::ClearRenderableLevels(GLES2Decoder* decoder) { |
783 DCHECK(decoder); | 878 DCHECK(decoder); |
784 if (cleared_) { | 879 if (cleared_) { |
785 return true; | 880 return true; |
786 } | 881 } |
787 | 882 |
788 const Texture::LevelInfo& first_face = level_infos_[0][0]; | 883 const Texture::LevelInfo& first_face = level_infos_[0][0]; |
789 int levels_needed = TextureManager::ComputeMipMapCount( | 884 int levels_needed = num_mip_levels_[0]; |
790 target_, first_face.width, first_face.height, first_face.depth); | |
791 | 885 |
792 for (size_t ii = 0; ii < level_infos_.size(); ++ii) { | 886 for (size_t ii = 0; ii < level_infos_.size(); ++ii) { |
793 for (GLint jj = 0; jj < levels_needed; ++jj) { | 887 for (GLint jj = 0; jj < levels_needed; ++jj) { |
794 Texture::LevelInfo& info = level_infos_[ii][jj]; | 888 Texture::LevelInfo& info = level_infos_[ii][jj]; |
795 if (info.target != 0) { | 889 if (info.target != 0) { |
796 if (!ClearLevel(decoder, info.target, jj)) { | 890 if (!ClearLevel(decoder, info.target, jj)) { |
797 return false; | 891 return false; |
798 } | 892 } |
799 } | 893 } |
800 } | 894 } |
(...skipping 811 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1612 } | 1706 } |
1613 | 1707 |
1614 ScopedTextureUploadTimer::~ScopedTextureUploadTimer() { | 1708 ScopedTextureUploadTimer::~ScopedTextureUploadTimer() { |
1615 texture_state_->texture_upload_count++; | 1709 texture_state_->texture_upload_count++; |
1616 texture_state_->total_texture_upload_time += | 1710 texture_state_->total_texture_upload_time += |
1617 base::TimeTicks::HighResNow() - begin_time_; | 1711 base::TimeTicks::HighResNow() - begin_time_; |
1618 } | 1712 } |
1619 | 1713 |
1620 } // namespace gles2 | 1714 } // namespace gles2 |
1621 } // namespace gpu | 1715 } // namespace gpu |
OLD | NEW |