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. 4 5 #ifndef GPU_COMMAND_BUFFER_SERVICE_TEXTURE_MANAGER_H_ 6 #define GPU_COMMAND_BUFFER_SERVICE_TEXTURE_MANAGER_H_ 7 8 #include <list> 9 #include <set> 10 #include <string> 11 #include <vector> 12 #include "base/basictypes.h" 13 #include "base/containers/hash_tables.h" 14 #include "base/logging.h" 15 #include "base/memory/ref_counted.h" 16 #include "base/observer_list.h" 17 #include "gpu/command_buffer/service/async_pixel_transfer_delegate.h" 18 #include "gpu/command_buffer/service/gl_utils.h" 19 #include "gpu/command_buffer/service/memory_tracking.h" 20 #include "gpu/gpu_export.h" 21 #include "ui/gl/gl_image.h" 22 23 namespace gpu { 24 25 class StreamTextureManager; 26 27 namespace gles2 { 28 29 class GLES2Decoder; 30 class Display; 31 class ErrorState; 32 class FeatureInfo; 33 class FramebufferManager; 34 class MailboxManager; 35 class TextureManager; 36 class TextureRef; 37 38 // Info about Textures currently in the system. 39 // This class wraps a real GL texture, keeping track of its meta-data. It is 40 // jointly owned by possibly multiple TextureRef. 41 class GPU_EXPORT Texture { 42 public: 43 explicit Texture(GLuint service_id); 44 45 GLenum min_filter() const { 46 return min_filter_; 47 } 48 49 GLenum mag_filter() const { 50 return mag_filter_; 51 } 52 53 GLenum wrap_s() const { 54 return wrap_s_; 55 } 56 57 GLenum wrap_t() const { 58 return wrap_t_; 59 } 60 61 GLenum usage() const { 62 return usage_; 63 } 64 65 GLenum pool() const { 66 return pool_; 67 } 68 69 int num_uncleared_mips() const { 70 return num_uncleared_mips_; 71 } 72 73 uint32 estimated_size() const { 74 return estimated_size_; 75 } 76 77 bool CanRenderTo() const { 78 return !stream_texture_ && target_ != GL_TEXTURE_EXTERNAL_OES; 79 } 80 81 // The service side OpenGL id of the texture. 82 GLuint service_id() const { 83 return service_id_; 84 } 85 86 void SetServiceId(GLuint service_id) { 87 DCHECK(service_id); 88 service_id_ = service_id; 89 } 90 91 // Returns the target this texure was first bound to or 0 if it has not 92 // been bound. Once a texture is bound to a specific target it can never be 93 // bound to a different target. 94 GLenum target() const { 95 return target_; 96 } 97 98 bool SafeToRenderFrom() const { 99 return cleared_; 100 } 101 102 // Get the width and height for a particular level. Returns false if level 103 // does not exist. 104 bool GetLevelSize( 105 GLint target, GLint level, GLsizei* width, GLsizei* height) const; 106 107 // Get the type of a level. Returns false if level does not exist. 108 bool GetLevelType( 109 GLint target, GLint level, GLenum* type, GLenum* internal_format) const; 110 111 // Get the image bound to a particular level. Returns NULL if level 112 // does not exist. 113 gfx::GLImage* GetLevelImage(GLint target, GLint level) const; 114 115 bool HasImages() const { 116 return has_images_; 117 } 118 119 // Returns true of the given dimensions are inside the dimensions of the 120 // level and if the format and type match the level. 121 bool ValidForTexture( 122 GLint target, 123 GLint level, 124 GLint xoffset, 125 GLint yoffset, 126 GLsizei width, 127 GLsizei height, 128 GLenum format, 129 GLenum type) const; 130 131 bool IsValid() const { 132 return !!target(); 133 } 134 135 bool IsAttachedToFramebuffer() const { 136 return framebuffer_attachment_count_ != 0; 137 } 138 139 void AttachToFramebuffer() { 140 ++framebuffer_attachment_count_; 141 } 142 143 void DetachFromFramebuffer() { 144 DCHECK_GT(framebuffer_attachment_count_, 0); 145 --framebuffer_attachment_count_; 146 } 147 148 bool IsStreamTexture() const { 149 return stream_texture_; 150 } 151 152 void SetImmutable(bool immutable) { 153 immutable_ = immutable; 154 } 155 156 bool IsImmutable() const { 157 return immutable_; 158 } 159 160 // Whether a particular level/face is cleared. 161 bool IsLevelCleared(GLenum target, GLint level) const; 162 163 // Whether the texture has been defined 164 bool IsDefined() const { 165 return estimated_size() > 0; 166 } 167 168 private: 169 friend class MailboxManager; 170 friend class MailboxManagerTest; 171 friend class TextureManager; 172 friend class TextureRef; 173 friend class TextureTestHelper; 174 175 ~Texture(); 176 void AddTextureRef(TextureRef* ref); 177 void RemoveTextureRef(TextureRef* ref, bool have_context); 178 MemoryTypeTracker* GetMemTracker(); 179 180 // Condition on which this texture is renderable. Can be ONLY_IF_NPOT if it 181 // depends on context support for non-power-of-two textures (i.e. will be 182 // renderable if NPOT support is in the context, otherwise not, e.g. texture 183 // with a NPOT level). ALWAYS means it doesn't depend on context features 184 // (e.g. complete POT), NEVER means it's not renderable regardless (e.g. 185 // incomplete). 186 enum CanRenderCondition { 187 CAN_RENDER_ALWAYS, 188 CAN_RENDER_NEVER, 189 CAN_RENDER_ONLY_IF_NPOT 190 }; 191 192 struct LevelInfo { 193 LevelInfo(); 194 LevelInfo(const LevelInfo& rhs); 195 ~LevelInfo(); 196 197 bool cleared; 198 GLenum target; 199 GLint level; 200 GLenum internal_format; 201 GLsizei width; 202 GLsizei height; 203 GLsizei depth; 204 GLint border; 205 GLenum format; 206 GLenum type; 207 scoped_refptr<gfx::GLImage> image; 208 uint32 estimated_size; 209 }; 210 211 // Set the info for a particular level. 212 void SetLevelInfo( 213 const FeatureInfo* feature_info, 214 GLenum target, 215 GLint level, 216 GLenum internal_format, 217 GLsizei width, 218 GLsizei height, 219 GLsizei depth, 220 GLint border, 221 GLenum format, 222 GLenum type, 223 bool cleared); 224 225 // In GLES2 "texture complete" means it has all required mips for filtering 226 // down to a 1x1 pixel texture, they are in the correct order, they are all 227 // the same format. 228 bool texture_complete() const { 229 return texture_complete_; 230 } 231 232 // In GLES2 "cube complete" means all 6 faces level 0 are defined, all the 233 // same format, all the same dimensions and all width = height. 234 bool cube_complete() const { 235 return cube_complete_; 236 } 237 238 // Whether or not this texture is a non-power-of-two texture. 239 bool npot() const { 240 return npot_; 241 } 242 243 void SetStreamTexture(bool stream_texture) { 244 stream_texture_ = stream_texture; 245 UpdateCanRenderCondition(); 246 } 247 248 // Marks a particular level as cleared or uncleared. 249 void SetLevelCleared(GLenum target, GLint level, bool cleared); 250 251 // Updates the cleared flag for this texture by inspecting all the mips. 252 void UpdateCleared(); 253 254 // Clears any renderable uncleared levels. 255 // Returns false if a GL error was generated. 256 bool ClearRenderableLevels(GLES2Decoder* decoder); 257 258 // Clears the level. 259 // Returns false if a GL error was generated. 260 bool ClearLevel(GLES2Decoder* decoder, GLenum target, GLint level); 261 262 // Sets a texture parameter. 263 // TODO(gman): Expand to SetParameteri,f,iv,fv 264 // Returns GL_NO_ERROR on success. Otherwise the error to generate. 265 GLenum SetParameter( 266 const FeatureInfo* feature_info, GLenum pname, GLint param); 267 268 // Makes each of the mip levels as though they were generated. 269 bool MarkMipmapsGenerated(const FeatureInfo* feature_info); 270 271 bool NeedsMips() const { 272 return min_filter_ != GL_NEAREST && min_filter_ != GL_LINEAR; 273 } 274 275 // True if this texture meets all the GLES2 criteria for rendering. 276 // See section 3.8.2 of the GLES2 spec. 277 bool CanRender(const FeatureInfo* feature_info) const; 278 279 // Returns true if mipmaps can be generated by GL. 280 bool CanGenerateMipmaps(const FeatureInfo* feature_info) const; 281 282 // Sets the Texture's target 283 // Parameters: 284 // target: GL_TEXTURE_2D or GL_TEXTURE_CUBE_MAP or 285 // GL_TEXTURE_EXTERNAL_OES or GL_TEXTURE_RECTANGLE_ARB 286 // max_levels: The maximum levels this type of target can have. 287 void SetTarget( 288 const FeatureInfo* feature_info, GLenum target, GLint max_levels); 289 290 // Update info about this texture. 291 void Update(const FeatureInfo* feature_info); 292 293 // Set the image for a particular level. 294 void SetLevelImage( 295 const FeatureInfo* feature_info, 296 GLenum target, 297 GLint level, 298 gfx::GLImage* image); 299 300 // Appends a signature for the given level. 301 void AddToSignature( 302 const FeatureInfo* feature_info, 303 GLenum target, GLint level, std::string* signature) const; 304 305 void SetMailboxManager(MailboxManager* mailbox_manager); 306 307 // Updates the unsafe textures count in all the managers referencing this 308 // texture. 309 void UpdateSafeToRenderFrom(bool cleared); 310 311 // Updates the uncleared mip count in all the managers referencing this 312 // texture. 313 void UpdateMipCleared(LevelInfo* info, bool cleared); 314 315 // Computes the CanRenderCondition flag. 316 CanRenderCondition GetCanRenderCondition() const; 317 318 // Updates the unrenderable texture count in all the managers referencing this 319 // texture. 320 void UpdateCanRenderCondition(); 321 322 // Updates the images count in all the managers referencing this 323 // texture. 324 void UpdateHasImages(); 325 326 // Increment the framebuffer state change count in all the managers 327 // referencing this texture. 328 void IncAllFramebufferStateChangeCount(); 329 330 MailboxManager* mailbox_manager_; 331 332 // Info about each face and level of texture. 333 std::vector<std::vector<LevelInfo> > level_infos_; 334 335 // The texture refs that point to this Texture. 336 typedef std::set<TextureRef*> RefSet; 337 RefSet refs_; 338 339 // The single TextureRef that accounts for memory for this texture. Must be 340 // one of refs_. 341 TextureRef* memory_tracking_ref_; 342 343 // The id of the texure 344 GLuint service_id_; 345 346 // Whether all renderable mips of this texture have been cleared. 347 bool cleared_; 348 349 int num_uncleared_mips_; 350 351 // The target. 0 if unset, otherwise GL_TEXTURE_2D or GL_TEXTURE_CUBE_MAP. 352 GLenum target_; 353 354 // Texture parameters. 355 GLenum min_filter_; 356 GLenum mag_filter_; 357 GLenum wrap_s_; 358 GLenum wrap_t_; 359 GLenum usage_; 360 GLenum pool_; 361 362 // The maximum level that has been set. 363 GLint max_level_set_; 364 365 // Whether or not this texture is "texture complete" 366 bool texture_complete_; 367 368 // Whether or not this texture is "cube complete" 369 bool cube_complete_; 370 371 // Whether or not this texture is non-power-of-two 372 bool npot_; 373 374 // Whether this texture has ever been bound. 375 bool has_been_bound_; 376 377 // The number of framebuffers this texture is attached to. 378 int framebuffer_attachment_count_; 379 380 // Whether this is a special streaming texture. 381 bool stream_texture_; 382 383 // Whether the texture is immutable and no further changes to the format 384 // or dimensions of the texture object can be made. 385 bool immutable_; 386 387 // Whether or not this texture has images. 388 bool has_images_; 389 390 // Size in bytes this texture is assumed to take in memory. 391 uint32 estimated_size_; 392 393 // Cache of the computed CanRenderCondition flag. 394 CanRenderCondition can_render_condition_; 395 396 DISALLOW_COPY_AND_ASSIGN(Texture); 397 }; 398 399 // This class represents a texture in a client context group. It's mostly 1:1 400 // with a client id, though it can outlive the client id if it's still bound to 401 // a FBO or another context when destroyed. 402 // Multiple TextureRef can point to the same texture with cross-context sharing. 403 // 404 // Note: for stream textures, the TextureRef that created the stream texture is 405 // set as the "owner" of the stream texture, i.e. it will call 406 // DestroyStreamTexture on destruction. This is because the StreamTextureManager 407 // isn't generally shared between ContextGroups, so ownership can't be at the 408 // Texture level. We also can't have multiple StreamTexture on the same service 409 // id, so there can be only one owner. 410 class GPU_EXPORT TextureRef : public base::RefCounted<TextureRef> { 411 public: 412 TextureRef(TextureManager* manager, GLuint client_id, Texture* texture); 413 static scoped_refptr<TextureRef> Create(TextureManager* manager, 414 GLuint client_id, 415 GLuint service_id); 416 const Texture* texture() const { return texture_; } 417 Texture* texture() { return texture_; } 418 GLuint client_id() const { return client_id_; } 419 GLuint service_id() const { return texture_->service_id(); } 420 421 private: 422 friend class base::RefCounted<TextureRef>; 423 friend class Texture; 424 friend class TextureManager; 425 426 ~TextureRef(); 427 const TextureManager* manager() const { return manager_; } 428 TextureManager* manager() { return manager_; } 429 void reset_client_id() { client_id_ = 0; } 430 void set_is_stream_texture_owner(bool owner) { 431 is_stream_texture_owner_ = owner; 432 } 433 bool is_stream_texture_owner() const { return is_stream_texture_owner_; } 434 435 TextureManager* manager_; 436 Texture* texture_; 437 GLuint client_id_; 438 bool is_stream_texture_owner_; 439 440 DISALLOW_COPY_AND_ASSIGN(TextureRef); 441 }; 442 443 // This class keeps track of the textures and their sizes so we can do NPOT and 444 // texture complete checking. 445 // 446 // NOTE: To support shared resources an instance of this class will need to be 447 // shared by multiple GLES2Decoders. 448 class GPU_EXPORT TextureManager { 449 public: 450 class GPU_EXPORT DestructionObserver { 451 public: 452 DestructionObserver(); 453 virtual ~DestructionObserver(); 454 455 // Called in ~TextureManager. 456 virtual void OnTextureManagerDestroying(TextureManager* manager) = 0; 457 458 // Called via ~TextureRef. 459 virtual void OnTextureRefDestroying(TextureRef* texture) = 0; 460 461 private: 462 DISALLOW_COPY_AND_ASSIGN(DestructionObserver); 463 }; 464 465 enum DefaultAndBlackTextures { 466 kTexture2D, 467 kCubeMap, 468 kExternalOES, 469 kRectangleARB, 470 kNumDefaultTextures 471 }; 472 473 TextureManager(MemoryTracker* memory_tracker, 474 FeatureInfo* feature_info, 475 GLsizei max_texture_size, 476 GLsizei max_cube_map_texture_size); 477 ~TextureManager(); 478 479 void set_framebuffer_manager(FramebufferManager* manager) { 480 framebuffer_manager_ = manager; 481 } 482 483 void set_stream_texture_manager(StreamTextureManager* manager) { 484 stream_texture_manager_ = manager; 485 } 486 487 // Init the texture manager. 488 bool Initialize(); 489 490 // Must call before destruction. 491 void Destroy(bool have_context); 492 493 // Returns the maximum number of levels. 494 GLint MaxLevelsForTarget(GLenum target) const { 495 switch (target) { 496 case GL_TEXTURE_2D: 497 return max_levels_; 498 case GL_TEXTURE_EXTERNAL_OES: 499 return 1; 500 default: 501 return max_cube_map_levels_; 502 } 503 } 504 505 // Returns the maximum size. 506 GLsizei MaxSizeForTarget(GLenum target) const { 507 switch (target) { 508 case GL_TEXTURE_2D: 509 case GL_TEXTURE_EXTERNAL_OES: 510 return max_texture_size_; 511 default: 512 return max_cube_map_texture_size_; 513 } 514 } 515 516 // Returns the maxium number of levels a texture of the given size can have. 517 static GLsizei ComputeMipMapCount( 518 GLsizei width, GLsizei height, GLsizei depth); 519 520 // Checks if a dimensions are valid for a given target. 521 bool ValidForTarget( 522 GLenum target, GLint level, 523 GLsizei width, GLsizei height, GLsizei depth); 524 525 // True if this texture meets all the GLES2 criteria for rendering. 526 // See section 3.8.2 of the GLES2 spec. 527 bool CanRender(const TextureRef* ref) const { 528 return ref->texture()->CanRender(feature_info_.get()); 529 } 530 531 // Returns true if mipmaps can be generated by GL. 532 bool CanGenerateMipmaps(const TextureRef* ref) const { 533 return ref->texture()->CanGenerateMipmaps(feature_info_.get()); 534 } 535 536 // Sets the Texture's target 537 // Parameters: 538 // target: GL_TEXTURE_2D or GL_TEXTURE_CUBE_MAP 539 // max_levels: The maximum levels this type of target can have. 540 void SetTarget( 541 TextureRef* ref, 542 GLenum target); 543 544 // Marks a texture as a stream texture, and the ref as the stream texture 545 // owner. 546 void SetStreamTexture(TextureRef* ref, bool stream_texture); 547 548 // Whether the TextureRef is the stream texture owner. 549 bool IsStreamTextureOwner(TextureRef* ref); 550 551 // Set the info for a particular level in a TexureInfo. 552 void SetLevelInfo( 553 TextureRef* ref, 554 GLenum target, 555 GLint level, 556 GLenum internal_format, 557 GLsizei width, 558 GLsizei height, 559 GLsizei depth, 560 GLint border, 561 GLenum format, 562 GLenum type, 563 bool cleared); 564 565 // Adapter to call above function. 566 void SetLevelInfoFromParams(TextureRef* ref, 567 const gpu::AsyncTexImage2DParams& params) { 568 SetLevelInfo( 569 ref, params.target, params.level, params.internal_format, 570 params.width, params.height, 1 /* depth */, 571 params.border, params.format, 572 params.type, true /* cleared */ ); 573 } 574 575 Texture* Produce(TextureRef* ref); 576 577 // Maps an existing texture into the texture manager, at a given client ID. 578 TextureRef* Consume(GLuint client_id, Texture* texture); 579 580 // Sets a mip as cleared. 581 void SetLevelCleared(TextureRef* ref, GLenum target, 582 GLint level, bool cleared); 583 584 // Sets a texture parameter of a Texture 585 // Returns GL_NO_ERROR on success. Otherwise the error to generate. 586 // TODO(gman): Expand to SetParameteri,f,iv,fv 587 void SetParameter( 588 const char* function_name, ErrorState* error_state, 589 TextureRef* ref, GLenum pname, GLint param); 590 591 // Makes each of the mip levels as though they were generated. 592 // Returns false if that's not allowed for the given texture. 593 bool MarkMipmapsGenerated(TextureRef* ref); 594 595 // Clears any uncleared renderable levels. 596 bool ClearRenderableLevels(GLES2Decoder* decoder, TextureRef* ref); 597 598 // Clear a specific level. 599 bool ClearTextureLevel( 600 GLES2Decoder* decoder, TextureRef* ref, GLenum target, GLint level); 601 602 // Creates a new texture info. 603 TextureRef* CreateTexture(GLuint client_id, GLuint service_id); 604 605 // Gets the texture info for the given texture. 606 TextureRef* GetTexture(GLuint client_id) const; 607 608 // Removes a texture info. 609 void RemoveTexture(GLuint client_id); 610 611 // Gets a Texture for a given service id (note: it assumes the texture object 612 // is still mapped in this TextureManager). 613 Texture* GetTextureForServiceId(GLuint service_id) const; 614 615 TextureRef* GetDefaultTextureInfo(GLenum target) { 616 switch (target) { 617 case GL_TEXTURE_2D: 618 return default_textures_[kTexture2D].get(); 619 case GL_TEXTURE_CUBE_MAP: 620 return default_textures_[kCubeMap].get(); 621 case GL_TEXTURE_EXTERNAL_OES: 622 return default_textures_[kExternalOES].get(); 623 case GL_TEXTURE_RECTANGLE_ARB: 624 return default_textures_[kRectangleARB].get(); 625 default: 626 NOTREACHED(); 627 return NULL; 628 } 629 } 630 631 bool HaveUnrenderableTextures() const { 632 return num_unrenderable_textures_ > 0; 633 } 634 635 bool HaveUnsafeTextures() const { 636 return num_unsafe_textures_ > 0; 637 } 638 639 bool HaveUnclearedMips() const { 640 return num_uncleared_mips_ > 0; 641 } 642 643 bool HaveImages() const { 644 return num_images_ > 0; 645 } 646 647 GLuint black_texture_id(GLenum target) const { 648 switch (target) { 649 case GL_SAMPLER_2D: 650 return black_texture_ids_[kTexture2D]; 651 case GL_SAMPLER_CUBE: 652 return black_texture_ids_[kCubeMap]; 653 case GL_SAMPLER_EXTERNAL_OES: 654 return black_texture_ids_[kExternalOES]; 655 case GL_SAMPLER_2D_RECT_ARB: 656 return black_texture_ids_[kRectangleARB]; 657 default: 658 NOTREACHED(); 659 return 0; 660 } 661 } 662 663 size_t mem_represented() const { 664 return 665 memory_tracker_managed_->GetMemRepresented() + 666 memory_tracker_unmanaged_->GetMemRepresented(); 667 } 668 669 void SetLevelImage( 670 TextureRef* ref, 671 GLenum target, 672 GLint level, 673 gfx::GLImage* image); 674 675 void AddToSignature( 676 TextureRef* ref, 677 GLenum target, 678 GLint level, 679 std::string* signature) const; 680 681 void AddObserver(DestructionObserver* observer) { 682 destruction_observers_.AddObserver(observer); 683 } 684 685 void RemoveObserver(DestructionObserver* observer) { 686 destruction_observers_.RemoveObserver(observer); 687 } 688 689 private: 690 friend class Texture; 691 friend class TextureRef; 692 693 // Helper for Initialize(). 694 scoped_refptr<TextureRef> CreateDefaultAndBlackTextures( 695 GLenum target, 696 GLuint* black_texture); 697 698 void StartTracking(TextureRef* texture); 699 void StopTracking(TextureRef* texture); 700 701 void UpdateSafeToRenderFrom(int delta); 702 void UpdateUnclearedMips(int delta); 703 void UpdateCanRenderCondition(Texture::CanRenderCondition old_condition, 704 Texture::CanRenderCondition new_condition); 705 void UpdateNumImages(int delta); 706 void IncFramebufferStateChangeCount(); 707 708 MemoryTypeTracker* GetMemTracker(GLenum texture_pool); 709 scoped_ptr<MemoryTypeTracker> memory_tracker_managed_; 710 scoped_ptr<MemoryTypeTracker> memory_tracker_unmanaged_; 711 712 scoped_refptr<FeatureInfo> feature_info_; 713 714 FramebufferManager* framebuffer_manager_; 715 StreamTextureManager* stream_texture_manager_; 716 717 // Info for each texture in the system. 718 typedef base::hash_map<GLuint, scoped_refptr<TextureRef> > TextureMap; 719 TextureMap textures_; 720 721 GLsizei max_texture_size_; 722 GLsizei max_cube_map_texture_size_; 723 GLint max_levels_; 724 GLint max_cube_map_levels_; 725 726 int num_unrenderable_textures_; 727 int num_unsafe_textures_; 728 int num_uncleared_mips_; 729 int num_images_; 730 731 // Counts the number of Textures allocated with 'this' as its manager. 732 // Allows to check no Texture will outlive this. 733 unsigned int texture_count_; 734 735 bool have_context_; 736 737 // Black (0,0,0,1) textures for when non-renderable textures are used. 738 // NOTE: There is no corresponding Texture for these textures. 739 // TextureInfos are only for textures the client side can access. 740 GLuint black_texture_ids_[kNumDefaultTextures]; 741 742 // The default textures for each target (texture name = 0) 743 scoped_refptr<TextureRef> default_textures_[kNumDefaultTextures]; 744 745 ObserverList<DestructionObserver> destruction_observers_; 746 747 DISALLOW_COPY_AND_ASSIGN(TextureManager); 748 }; 749 750 } // namespace gles2 751 } // namespace gpu 752 753 #endif // GPU_COMMAND_BUFFER_SERVICE_TEXTURE_MANAGER_H_ 754