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 |