| OLD | NEW |
| 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 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 #include "base/bits.h" | 6 #include "base/bits.h" |
| 7 #include "gpu/command_buffer/common/gles2_cmd_utils.h" | 7 #include "gpu/command_buffer/common/gles2_cmd_utils.h" |
| 8 #include "gpu/command_buffer/service/feature_info.h" | 8 #include "gpu/command_buffer/service/feature_info.h" |
| 9 #include "gpu/command_buffer/service/gles2_cmd_decoder.h" | 9 #include "gpu/command_buffer/service/gles2_cmd_decoder.h" |
| 10 | 10 |
| 11 namespace gpu { | 11 namespace gpu { |
| 12 namespace gles2 { | 12 namespace gles2 { |
| 13 | 13 |
| 14 static GLsizei ComputeMipMapCount( | 14 static GLsizei ComputeMipMapCount( |
| 15 GLsizei width, GLsizei height, GLsizei depth) { | 15 GLsizei width, GLsizei height, GLsizei depth) { |
| 16 return 1 + base::bits::Log2Floor(std::max(std::max(width, height), depth)); | 16 return 1 + base::bits::Log2Floor(std::max(std::max(width, height), depth)); |
| 17 } | 17 } |
| 18 | 18 |
| 19 static size_t GLTargetToFaceIndex(GLenum target) { | 19 static size_t GLTargetToFaceIndex(GLenum target) { |
| 20 switch (target) { | 20 switch (target) { |
| 21 case GL_TEXTURE_2D: | 21 case GL_TEXTURE_2D: |
| 22 case GL_TEXTURE_EXTERNAL_OES: | 22 case GL_TEXTURE_EXTERNAL_OES: |
| 23 case GL_TEXTURE_RECTANGLE_ARB: |
| 23 return 0; | 24 return 0; |
| 24 case GL_TEXTURE_CUBE_MAP_POSITIVE_X: | 25 case GL_TEXTURE_CUBE_MAP_POSITIVE_X: |
| 25 return 0; | 26 return 0; |
| 26 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X: | 27 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X: |
| 27 return 1; | 28 return 1; |
| 28 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y: | 29 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y: |
| 29 return 2; | 30 return 2; |
| 30 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y: | 31 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y: |
| 31 return 3; | 32 return 3; |
| 32 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z: | 33 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z: |
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 85 glDeleteTextures(arraysize(ids), ids); | 86 glDeleteTextures(arraysize(ids), ids); |
| 86 } | 87 } |
| 87 } | 88 } |
| 88 | 89 |
| 89 bool TextureManager::TextureInfo::CanRender( | 90 bool TextureManager::TextureInfo::CanRender( |
| 90 const FeatureInfo* feature_info) const { | 91 const FeatureInfo* feature_info) const { |
| 91 if (target_ == 0) { | 92 if (target_ == 0) { |
| 92 return false; | 93 return false; |
| 93 } | 94 } |
| 94 bool needs_mips = NeedsMips(); | 95 bool needs_mips = NeedsMips(); |
| 95 if (npot() && !feature_info->feature_flags().npot_ok) { | 96 if ((npot() && !feature_info->feature_flags().npot_ok) || |
| 97 (target_ == GL_TEXTURE_RECTANGLE_ARB)) { |
| 96 return !needs_mips && | 98 return !needs_mips && |
| 97 wrap_s_ == GL_CLAMP_TO_EDGE && | 99 wrap_s_ == GL_CLAMP_TO_EDGE && |
| 98 wrap_t_ == GL_CLAMP_TO_EDGE; | 100 wrap_t_ == GL_CLAMP_TO_EDGE; |
| 99 } | 101 } |
| 100 if (needs_mips) { | 102 if (needs_mips) { |
| 101 if (target_ == GL_TEXTURE_2D) { | 103 if (target_ == GL_TEXTURE_2D) { |
| 102 return texture_complete(); | 104 return texture_complete(); |
| 103 } else { | 105 } else { |
| 104 return texture_complete() && cube_complete(); | 106 return texture_complete() && cube_complete(); |
| 105 } | 107 } |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 144 | 146 |
| 145 void TextureManager::TextureInfo::SetTarget(GLenum target, GLint max_levels) { | 147 void TextureManager::TextureInfo::SetTarget(GLenum target, GLint max_levels) { |
| 146 DCHECK_EQ(0u, target_); // you can only set this once. | 148 DCHECK_EQ(0u, target_); // you can only set this once. |
| 147 target_ = target; | 149 target_ = target; |
| 148 size_t num_faces = (target == GL_TEXTURE_CUBE_MAP) ? 6 : 1; | 150 size_t num_faces = (target == GL_TEXTURE_CUBE_MAP) ? 6 : 1; |
| 149 level_infos_.resize(num_faces); | 151 level_infos_.resize(num_faces); |
| 150 for (size_t ii = 0; ii < num_faces; ++ii) { | 152 for (size_t ii = 0; ii < num_faces; ++ii) { |
| 151 level_infos_[ii].resize(max_levels); | 153 level_infos_[ii].resize(max_levels); |
| 152 } | 154 } |
| 153 | 155 |
| 154 if (target == GL_TEXTURE_EXTERNAL_OES) { | 156 if (target == GL_TEXTURE_EXTERNAL_OES || target == GL_TEXTURE_RECTANGLE_ARB) { |
| 155 min_filter_ = GL_LINEAR; | 157 min_filter_ = GL_LINEAR; |
| 156 wrap_s_ = wrap_t_ = GL_CLAMP_TO_EDGE; | 158 wrap_s_ = wrap_t_ = GL_CLAMP_TO_EDGE; |
| 157 } | 159 } |
| 158 } | 160 } |
| 159 | 161 |
| 160 bool TextureManager::TextureInfo::CanGenerateMipmaps( | 162 bool TextureManager::TextureInfo::CanGenerateMipmaps( |
| 161 const FeatureInfo* feature_info) const { | 163 const FeatureInfo* feature_info) const { |
| 162 if ((npot() && !feature_info->feature_flags().npot_ok) || | 164 if ((npot() && !feature_info->feature_flags().npot_ok) || |
| 163 level_infos_.empty() || | 165 level_infos_.empty() || |
| 164 target_ == GL_TEXTURE_EXTERNAL_OES) { | 166 target_ == GL_TEXTURE_EXTERNAL_OES || |
| 167 target_ == GL_TEXTURE_RECTANGLE_ARB) { |
| 165 return false; | 168 return false; |
| 166 } | 169 } |
| 167 const TextureInfo::LevelInfo& first = level_infos_[0][0]; | 170 const TextureInfo::LevelInfo& first = level_infos_[0][0]; |
| 168 // TODO(gman): Check internal_format, format and type. | 171 // TODO(gman): Check internal_format, format and type. |
| 169 for (size_t ii = 0; ii < level_infos_.size(); ++ii) { | 172 for (size_t ii = 0; ii < level_infos_.size(); ++ii) { |
| 170 const LevelInfo& info = level_infos_[ii][0]; | 173 const LevelInfo& info = level_infos_[ii][0]; |
| 171 if ((info.target == 0) || | 174 if ((info.target == 0) || |
| 172 (info.width != first.width) || | 175 (info.width != first.width) || |
| 173 (info.height != first.height) || | 176 (info.height != first.height) || |
| 174 (info.depth != 1) || | 177 (info.depth != 1) || |
| (...skipping 145 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 320 return true; | 323 return true; |
| 321 } | 324 } |
| 322 } | 325 } |
| 323 return false; | 326 return false; |
| 324 } | 327 } |
| 325 | 328 |
| 326 bool TextureManager::TextureInfo::SetParameter( | 329 bool TextureManager::TextureInfo::SetParameter( |
| 327 const FeatureInfo* feature_info, GLenum pname, GLint param) { | 330 const FeatureInfo* feature_info, GLenum pname, GLint param) { |
| 328 DCHECK(feature_info); | 331 DCHECK(feature_info); |
| 329 | 332 |
| 330 if (target_ == GL_TEXTURE_EXTERNAL_OES) { | 333 if (target_ == GL_TEXTURE_EXTERNAL_OES || |
| 334 target_ == GL_TEXTURE_RECTANGLE_ARB) { |
| 331 if (pname == GL_TEXTURE_MIN_FILTER && | 335 if (pname == GL_TEXTURE_MIN_FILTER && |
| 332 (param != GL_NEAREST && param != GL_LINEAR)) | 336 (param != GL_NEAREST && param != GL_LINEAR)) |
| 333 return false; | 337 return false; |
| 334 if ((pname == GL_TEXTURE_WRAP_S || pname == GL_TEXTURE_WRAP_T) && | 338 if ((pname == GL_TEXTURE_WRAP_S || pname == GL_TEXTURE_WRAP_T) && |
| 335 param != GL_CLAMP_TO_EDGE) | 339 param != GL_CLAMP_TO_EDGE) |
| 336 return false; | 340 return false; |
| 337 } | 341 } |
| 338 | 342 |
| 339 switch (pname) { | 343 switch (pname) { |
| 340 case GL_TEXTURE_MIN_FILTER: | 344 case GL_TEXTURE_MIN_FILTER: |
| (...skipping 192 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 533 max_levels_(ComputeMipMapCount(max_texture_size, | 537 max_levels_(ComputeMipMapCount(max_texture_size, |
| 534 max_texture_size, | 538 max_texture_size, |
| 535 max_texture_size)), | 539 max_texture_size)), |
| 536 max_cube_map_levels_(ComputeMipMapCount(max_cube_map_texture_size, | 540 max_cube_map_levels_(ComputeMipMapCount(max_cube_map_texture_size, |
| 537 max_cube_map_texture_size, | 541 max_cube_map_texture_size, |
| 538 max_cube_map_texture_size)), | 542 max_cube_map_texture_size)), |
| 539 num_unrenderable_textures_(0), | 543 num_unrenderable_textures_(0), |
| 540 num_unsafe_textures_(0), | 544 num_unsafe_textures_(0), |
| 541 num_uncleared_mips_(0), | 545 num_uncleared_mips_(0), |
| 542 black_2d_texture_id_(0), | 546 black_2d_texture_id_(0), |
| 543 black_cube_texture_id_(0) { | 547 black_cube_texture_id_(0), |
| 548 black_oes_external_texture_id_(0), |
| 549 black_arb_texture_rectangle_id_(0) { |
| 544 } | 550 } |
| 545 | 551 |
| 546 bool TextureManager::Initialize(const FeatureInfo* feature_info) { | 552 bool TextureManager::Initialize(const FeatureInfo* feature_info) { |
| 547 // TODO(gman): The default textures have to be real textures, not the 0 | 553 // TODO(gman): The default textures have to be real textures, not the 0 |
| 548 // texture because we simulate non shared resources on top of shared | 554 // texture because we simulate non shared resources on top of shared |
| 549 // resources and all contexts that share resource share the same default | 555 // resources and all contexts that share resource share the same default |
| 550 // texture. | 556 // texture. |
| 551 | 557 |
| 552 // Make default textures and texture for replacing non-renderable textures. | 558 default_texture_2d_ = CreateDefaultAndBlackTextures( |
| 553 GLuint ids[4]; | 559 feature_info, GL_TEXTURE_2D, &black_2d_texture_id_); |
| 554 glGenTextures(arraysize(ids), ids); | 560 default_texture_cube_map_ = CreateDefaultAndBlackTextures( |
| 555 static uint8 black[] = {0, 0, 0, 255}; | 561 feature_info, GL_TEXTURE_CUBE_MAP, &black_cube_texture_id_); |
| 556 for (int ii = 0; ii < 2; ++ii) { | |
| 557 glBindTexture(GL_TEXTURE_2D, ids[ii]); | |
| 558 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, | |
| 559 GL_UNSIGNED_BYTE, black); | |
| 560 glBindTexture(GL_TEXTURE_CUBE_MAP, ids[2 + ii]); | |
| 561 for (int ii = 0; ii < GLES2Util::kNumFaces; ++ii) { | |
| 562 glTexImage2D(GLES2Util::IndexToGLFaceTarget(ii), 0, GL_RGBA, 1, 1, 0, | |
| 563 GL_RGBA, GL_UNSIGNED_BYTE, black); | |
| 564 } | |
| 565 } | |
| 566 glBindTexture(GL_TEXTURE_2D, 0); | |
| 567 glBindTexture(GL_TEXTURE_CUBE_MAP, 0); | |
| 568 | 562 |
| 569 // Since we are manually setting up these textures | 563 if (feature_info->feature_flags().oes_egl_image_external) { |
| 570 // we need to manually manipulate some of the their bookkeeping. | 564 default_texture_external_oes_ = CreateDefaultAndBlackTextures( |
| 571 num_unrenderable_textures_ += 2; | 565 feature_info, GL_TEXTURE_EXTERNAL_OES, |
| 572 FeatureInfo temp_feature_info; | 566 &black_oes_external_texture_id_); |
| 573 default_texture_2d_ = TextureInfo::Ref(new TextureInfo(ids[1])); | |
| 574 SetInfoTarget(feature_info, default_texture_2d_, GL_TEXTURE_2D); | |
| 575 SetLevelInfo(&temp_feature_info, default_texture_2d_, | |
| 576 GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, true); | |
| 577 default_texture_cube_map_ = TextureInfo::Ref(new TextureInfo(ids[3])); | |
| 578 SetInfoTarget(feature_info, default_texture_cube_map_, GL_TEXTURE_CUBE_MAP); | |
| 579 for (int ii = 0; ii < GLES2Util::kNumFaces; ++ii) { | |
| 580 SetLevelInfo( | |
| 581 &temp_feature_info, default_texture_cube_map_, | |
| 582 GLES2Util::IndexToGLFaceTarget(ii), | |
| 583 0, GL_RGBA, 1, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, true); | |
| 584 } | 567 } |
| 585 | 568 |
| 586 black_2d_texture_id_ = ids[0]; | 569 if (feature_info->feature_flags().arb_texture_rectangle) { |
| 587 black_cube_texture_id_ = ids[2]; | 570 default_texture_rectangle_arb_ = CreateDefaultAndBlackTextures( |
| 588 | 571 feature_info, GL_TEXTURE_RECTANGLE_ARB, |
| 589 if (feature_info->feature_flags().oes_egl_image_external) { | 572 &black_arb_texture_rectangle_id_); |
| 590 // Since we are manually setting up these textures | |
| 591 // we need to manually manipulate some of the their bookkeeping. | |
| 592 num_unrenderable_textures_ += 1; | |
| 593 GLuint external_ids[2]; | |
| 594 glGenTextures(arraysize(external_ids), external_ids); | |
| 595 glBindTexture(GL_TEXTURE_EXTERNAL_OES, 0); | |
| 596 default_texture_external_oes_ = TextureInfo::Ref( | |
| 597 new TextureInfo(external_ids[0])); | |
| 598 SetInfoTarget(feature_info, | |
| 599 default_texture_external_oes_, | |
| 600 GL_TEXTURE_EXTERNAL_OES); | |
| 601 default_texture_external_oes_->SetLevelInfo( | |
| 602 &temp_feature_info, GL_TEXTURE_EXTERNAL_OES, 0, | |
| 603 GL_RGBA, 1, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, true); | |
| 604 | |
| 605 // Sampling a texture not associated with any EGLImage sibling will return | |
| 606 // black values according to the spec. | |
| 607 black_oes_external_texture_id_ = external_ids[1]; | |
| 608 } | 573 } |
| 609 | 574 |
| 610 return true; | 575 return true; |
| 611 } | 576 } |
| 612 | 577 |
| 578 TextureManager::TextureInfo::Ref TextureManager::CreateDefaultAndBlackTextures( |
| 579 const FeatureInfo* feature_info, |
| 580 GLenum target, |
| 581 GLuint* black_texture) { |
| 582 static uint8 black[] = {0, 0, 0, 255}; |
| 583 |
| 584 // Sampling a texture not associated with any EGLImage sibling will return |
| 585 // black values according to the spec. |
| 586 bool needs_initialization = (target != GL_TEXTURE_EXTERNAL_OES); |
| 587 bool needs_faces = (target == GL_TEXTURE_CUBE_MAP); |
| 588 |
| 589 // Make default textures and texture for replacing non-renderable textures. |
| 590 GLuint ids[2]; |
| 591 glGenTextures(arraysize(ids), ids); |
| 592 for (unsigned long ii = 0; ii < arraysize(ids); ++ii) { |
| 593 glBindTexture(target, ids[ii]); |
| 594 if (needs_initialization) { |
| 595 if (needs_faces) { |
| 596 for (int jj = 0; jj < GLES2Util::kNumFaces; ++jj) { |
| 597 glTexImage2D(GLES2Util::IndexToGLFaceTarget(jj), 0, GL_RGBA, 1, 1, 0, |
| 598 GL_RGBA, GL_UNSIGNED_BYTE, black); |
| 599 } |
| 600 } else { |
| 601 glTexImage2D(target, 0, GL_RGBA, 1, 1, 0, GL_RGBA, |
| 602 GL_UNSIGNED_BYTE, black); |
| 603 } |
| 604 } |
| 605 } |
| 606 glBindTexture(target, 0); |
| 607 |
| 608 // Since we are manually setting up these textures |
| 609 // we need to manually manipulate some of the their bookkeeping. |
| 610 ++num_unrenderable_textures_; |
| 611 TextureInfo::Ref default_texture = TextureInfo::Ref(new TextureInfo(ids[1])); |
| 612 SetInfoTarget(feature_info, default_texture, target); |
| 613 FeatureInfo temp_feature_info; |
| 614 if (needs_faces) { |
| 615 for (int ii = 0; ii < GLES2Util::kNumFaces; ++ii) { |
| 616 SetLevelInfo( |
| 617 &temp_feature_info, default_texture, |
| 618 GLES2Util::IndexToGLFaceTarget(ii), |
| 619 0, GL_RGBA, 1, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, true); |
| 620 } |
| 621 } else { |
| 622 // TODO(kbr): previous code called SetLevelInfo directly on the |
| 623 // TextureInfo object for the GL_TEXTURE_EXTERNAL_OES case. |
| 624 // Unclear whether this was deliberate. |
| 625 if (needs_initialization) { |
| 626 SetLevelInfo(&temp_feature_info, default_texture, |
| 627 GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 1, 0, |
| 628 GL_RGBA, GL_UNSIGNED_BYTE, true); |
| 629 } else { |
| 630 default_texture->SetLevelInfo( |
| 631 &temp_feature_info, GL_TEXTURE_EXTERNAL_OES, 0, |
| 632 GL_RGBA, 1, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, true); |
| 633 } |
| 634 } |
| 635 |
| 636 *black_texture = ids[0]; |
| 637 return default_texture; |
| 638 } |
| 639 |
| 613 bool TextureManager::ValidForTarget( | 640 bool TextureManager::ValidForTarget( |
| 614 const FeatureInfo* feature_info, | 641 const FeatureInfo* feature_info, |
| 615 GLenum target, GLint level, | 642 GLenum target, GLint level, |
| 616 GLsizei width, GLsizei height, GLsizei depth) { | 643 GLsizei width, GLsizei height, GLsizei depth) { |
| 617 GLsizei max_size = MaxSizeForTarget(target); | 644 GLsizei max_size = MaxSizeForTarget(target); |
| 618 return level >= 0 && | 645 return level >= 0 && |
| 619 width >= 0 && | 646 width >= 0 && |
| 620 height >= 0 && | 647 height >= 0 && |
| 621 depth >= 0 && | 648 depth >= 0 && |
| 622 level < MaxLevelsForTarget(target) && | 649 level < MaxLevelsForTarget(target) && |
| (...skipping 214 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 837 return true; | 864 return true; |
| 838 } | 865 } |
| 839 } | 866 } |
| 840 return false; | 867 return false; |
| 841 } | 868 } |
| 842 | 869 |
| 843 } // namespace gles2 | 870 } // namespace gles2 |
| 844 } // namespace gpu | 871 } // namespace gpu |
| 845 | 872 |
| 846 | 873 |
| OLD | NEW |