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 #include "gpu/command_buffer/service/texture_manager.h" 6 #include "base/bits.h" 7 #include "base/strings/stringprintf.h" 8 #include "gpu/command_buffer/common/gles2_cmd_utils.h" 9 #include "gpu/command_buffer/service/error_state.h" 10 #include "gpu/command_buffer/service/feature_info.h" 11 #include "gpu/command_buffer/service/framebuffer_manager.h" 12 #include "gpu/command_buffer/service/gles2_cmd_decoder.h" 13 #include "gpu/command_buffer/service/mailbox_manager.h" 14 #include "gpu/command_buffer/service/memory_tracking.h" 15 #include "gpu/command_buffer/service/stream_texture_manager.h" 16 17 namespace gpu { 18 namespace gles2 { 19 20 static size_t GLTargetToFaceIndex(GLenum target) { 21 switch (target) { 22 case GL_TEXTURE_2D: 23 case GL_TEXTURE_EXTERNAL_OES: 24 case GL_TEXTURE_RECTANGLE_ARB: 25 return 0; 26 case GL_TEXTURE_CUBE_MAP_POSITIVE_X: 27 return 0; 28 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X: 29 return 1; 30 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y: 31 return 2; 32 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y: 33 return 3; 34 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z: 35 return 4; 36 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z: 37 return 5; 38 default: 39 NOTREACHED(); 40 return 0; 41 } 42 } 43 44 static size_t FaceIndexToGLTarget(size_t index) { 45 switch (index) { 46 case 0: 47 return GL_TEXTURE_CUBE_MAP_POSITIVE_X; 48 case 1: 49 return GL_TEXTURE_CUBE_MAP_NEGATIVE_X; 50 case 2: 51 return GL_TEXTURE_CUBE_MAP_POSITIVE_Y; 52 case 3: 53 return GL_TEXTURE_CUBE_MAP_NEGATIVE_Y; 54 case 4: 55 return GL_TEXTURE_CUBE_MAP_POSITIVE_Z; 56 case 5: 57 return GL_TEXTURE_CUBE_MAP_NEGATIVE_Z; 58 default: 59 NOTREACHED(); 60 return 0; 61 } 62 } 63 64 TextureManager::DestructionObserver::DestructionObserver() {} 65 66 TextureManager::DestructionObserver::~DestructionObserver() {} 67 68 TextureManager::~TextureManager() { 69 FOR_EACH_OBSERVER(DestructionObserver, 70 destruction_observers_, 71 OnTextureManagerDestroying(this)); 72 73 DCHECK(textures_.empty()); 74 75 // If this triggers, that means something is keeping a reference to 76 // a Texture belonging to this. 77 CHECK_EQ(texture_count_, 0u); 78 79 DCHECK_EQ(0, num_unrenderable_textures_); 80 DCHECK_EQ(0, num_unsafe_textures_); 81 DCHECK_EQ(0, num_uncleared_mips_); 82 } 83 84 void TextureManager::Destroy(bool have_context) { 85 have_context_ = have_context; 86 textures_.clear(); 87 for (int ii = 0; ii < kNumDefaultTextures; ++ii) { 88 default_textures_[ii] = NULL; 89 } 90 91 if (have_context) { 92 glDeleteTextures(arraysize(black_texture_ids_), black_texture_ids_); 93 } 94 95 DCHECK_EQ(0u, memory_tracker_managed_->GetMemRepresented()); 96 DCHECK_EQ(0u, memory_tracker_unmanaged_->GetMemRepresented()); 97 } 98 99 Texture::Texture(GLuint service_id) 100 : mailbox_manager_(NULL), 101 memory_tracking_ref_(NULL), 102 service_id_(service_id), 103 cleared_(true), 104 num_uncleared_mips_(0), 105 target_(0), 106 min_filter_(GL_NEAREST_MIPMAP_LINEAR), 107 mag_filter_(GL_LINEAR), 108 wrap_s_(GL_REPEAT), 109 wrap_t_(GL_REPEAT), 110 usage_(GL_NONE), 111 pool_(GL_TEXTURE_POOL_UNMANAGED_CHROMIUM), 112 max_level_set_(-1), 113 texture_complete_(false), 114 cube_complete_(false), 115 npot_(false), 116 has_been_bound_(false), 117 framebuffer_attachment_count_(0), 118 stream_texture_(false), 119 immutable_(false), 120 estimated_size_(0), 121 can_render_condition_(CAN_RENDER_ALWAYS) { 122 } 123 124 Texture::~Texture() { 125 if (mailbox_manager_) 126 mailbox_manager_->TextureDeleted(this); 127 } 128 129 void Texture::AddTextureRef(TextureRef* ref) { 130 DCHECK(refs_.find(ref) == refs_.end()); 131 refs_.insert(ref); 132 if (!memory_tracking_ref_) { 133 memory_tracking_ref_ = ref; 134 GetMemTracker()->TrackMemAlloc(estimated_size()); 135 } 136 } 137 138 void Texture::RemoveTextureRef(TextureRef* ref, bool have_context) { 139 if (memory_tracking_ref_ == ref) { 140 GetMemTracker()->TrackMemFree(estimated_size()); 141 memory_tracking_ref_ = NULL; 142 } 143 size_t result = refs_.erase(ref); 144 DCHECK_EQ(result, 1u); 145 if (refs_.empty()) { 146 if (have_context) { 147 GLuint id = service_id(); 148 glDeleteTextures(1, &id); 149 } 150 delete this; 151 } else if (memory_tracking_ref_ == NULL) { 152 // TODO(piman): tune ownership semantics for cross-context group shared 153 // textures. 154 memory_tracking_ref_ = *refs_.begin(); 155 GetMemTracker()->TrackMemAlloc(estimated_size()); 156 } 157 } 158 159 MemoryTypeTracker* Texture::GetMemTracker() { 160 DCHECK(memory_tracking_ref_); 161 return memory_tracking_ref_->manager()->GetMemTracker(pool_); 162 } 163 164 Texture::LevelInfo::LevelInfo() 165 : cleared(true), 166 target(0), 167 level(-1), 168 internal_format(0), 169 width(0), 170 height(0), 171 depth(0), 172 border(0), 173 format(0), 174 type(0), 175 estimated_size(0) { 176 } 177 178 Texture::LevelInfo::LevelInfo(const LevelInfo& rhs) 179 : cleared(rhs.cleared), 180 target(rhs.target), 181 level(rhs.level), 182 internal_format(rhs.internal_format), 183 width(rhs.width), 184 height(rhs.height), 185 depth(rhs.depth), 186 border(rhs.border), 187 format(rhs.format), 188 type(rhs.type), 189 image(rhs.image), 190 estimated_size(rhs.estimated_size) { 191 } 192 193 Texture::LevelInfo::~LevelInfo() { 194 } 195 196 Texture::CanRenderCondition Texture::GetCanRenderCondition() const { 197 if (target_ == 0) 198 return CAN_RENDER_ALWAYS; 199 200 if (target_ == GL_TEXTURE_EXTERNAL_OES) { 201 if (!IsStreamTexture()) { 202 return CAN_RENDER_NEVER; 203 } 204 } else { 205 if (level_infos_.empty()) { 206 return CAN_RENDER_NEVER; 207 } 208 209 const Texture::LevelInfo& first_face = level_infos_[0][0]; 210 if (first_face.width == 0 || 211 first_face.height == 0 || 212 first_face.depth == 0) { 213 return CAN_RENDER_NEVER; 214 } 215 } 216 217 bool needs_mips = NeedsMips(); 218 if (needs_mips) { 219 if (!texture_complete()) 220 return CAN_RENDER_NEVER; 221 if (target_ == GL_TEXTURE_CUBE_MAP && !cube_complete()) 222 return CAN_RENDER_NEVER; 223 } 224 225 bool is_npot_compatible = !needs_mips && 226 wrap_s_ == GL_CLAMP_TO_EDGE && 227 wrap_t_ == GL_CLAMP_TO_EDGE; 228 229 if (!is_npot_compatible) { 230 if (target_ == GL_TEXTURE_RECTANGLE_ARB) 231 return CAN_RENDER_NEVER; 232 else if (npot()) 233 return CAN_RENDER_ONLY_IF_NPOT; 234 } 235 236 return CAN_RENDER_ALWAYS; 237 } 238 239 bool Texture::CanRender(const FeatureInfo* feature_info) const { 240 switch (can_render_condition_) { 241 case CAN_RENDER_ALWAYS: 242 return true; 243 case CAN_RENDER_NEVER: 244 return false; 245 case CAN_RENDER_ONLY_IF_NPOT: 246 break; 247 } 248 return feature_info->feature_flags().npot_ok; 249 } 250 251 void Texture::AddToSignature( 252 const FeatureInfo* feature_info, 253 GLenum target, 254 GLint level, 255 std::string* signature) const { 256 DCHECK(feature_info); 257 DCHECK(signature); 258 DCHECK_GE(level, 0); 259 DCHECK_LT(static_cast<size_t>(GLTargetToFaceIndex(target)), 260 level_infos_.size()); 261 DCHECK_LT(static_cast<size_t>(level), 262 level_infos_[GLTargetToFaceIndex(target)].size()); 263 const Texture::LevelInfo& info = 264 level_infos_[GLTargetToFaceIndex(target)][level]; 265 *signature += base::StringPrintf( 266 "|Texture|target=%04x|level=%d|internal_format=%04x" 267 "|width=%d|height=%d|depth=%d|border=%d|format=%04x|type=%04x" 268 "|image=%d|canrender=%d|canrenderto=%d|npot_=%d" 269 "|min_filter=%04x|mag_filter=%04x|wrap_s=%04x|wrap_t=%04x" 270 "|usage=%04x", 271 target, level, info.internal_format, 272 info.width, info.height, info.depth, info.border, 273 info.format, info.type, info.image.get() != NULL, 274 CanRender(feature_info), CanRenderTo(), npot_, 275 min_filter_, mag_filter_, wrap_s_, wrap_t_, 276 usage_); 277 } 278 279 void Texture::SetMailboxManager(MailboxManager* mailbox_manager) { 280 DCHECK(!mailbox_manager_ || mailbox_manager_ == mailbox_manager); 281 mailbox_manager_ = mailbox_manager; 282 } 283 284 bool Texture::MarkMipmapsGenerated( 285 const FeatureInfo* feature_info) { 286 if (!CanGenerateMipmaps(feature_info)) { 287 return false; 288 } 289 for (size_t ii = 0; ii < level_infos_.size(); ++ii) { 290 const Texture::LevelInfo& info1 = level_infos_[ii][0]; 291 GLsizei width = info1.width; 292 GLsizei height = info1.height; 293 GLsizei depth = info1.depth; 294 GLenum target = target_ == GL_TEXTURE_2D ? GL_TEXTURE_2D : 295 FaceIndexToGLTarget(ii); 296 int num_mips = TextureManager::ComputeMipMapCount(width, height, depth); 297 for (int level = 1; level < num_mips; ++level) { 298 width = std::max(1, width >> 1); 299 height = std::max(1, height >> 1); 300 depth = std::max(1, depth >> 1); 301 SetLevelInfo(feature_info, 302 target, 303 level, 304 info1.internal_format, 305 width, 306 height, 307 depth, 308 info1.border, 309 info1.format, 310 info1.type, 311 true); 312 } 313 } 314 315 return true; 316 } 317 318 void Texture::SetTarget( 319 const FeatureInfo* feature_info, GLenum target, GLint max_levels) { 320 DCHECK_EQ(0u, target_); // you can only set this once. 321 target_ = target; 322 size_t num_faces = (target == GL_TEXTURE_CUBE_MAP) ? 6 : 1; 323 level_infos_.resize(num_faces); 324 for (size_t ii = 0; ii < num_faces; ++ii) { 325 level_infos_[ii].resize(max_levels); 326 } 327 328 if (target == GL_TEXTURE_EXTERNAL_OES || target == GL_TEXTURE_RECTANGLE_ARB) { 329 min_filter_ = GL_LINEAR; 330 wrap_s_ = wrap_t_ = GL_CLAMP_TO_EDGE; 331 } 332 333 if (target == GL_TEXTURE_EXTERNAL_OES) { 334 immutable_ = true; 335 } 336 Update(feature_info); 337 UpdateCanRenderCondition(); 338 } 339 340 bool Texture::CanGenerateMipmaps( 341 const FeatureInfo* feature_info) const { 342 if ((npot() && !feature_info->feature_flags().npot_ok) || 343 level_infos_.empty() || 344 target_ == GL_TEXTURE_EXTERNAL_OES || 345 target_ == GL_TEXTURE_RECTANGLE_ARB) { 346 return false; 347 } 348 349 // Can't generate mips for depth or stencil textures. 350 const Texture::LevelInfo& first = level_infos_[0][0]; 351 uint32 channels = GLES2Util::GetChannelsForFormat(first.format); 352 if (channels & (GLES2Util::kDepth | GLES2Util::kStencil)) { 353 return false; 354 } 355 356 // TODO(gman): Check internal_format, format and type. 357 for (size_t ii = 0; ii < level_infos_.size(); ++ii) { 358 const LevelInfo& info = level_infos_[ii][0]; 359 if ((info.target == 0) || (info.width != first.width) || 360 (info.height != first.height) || (info.depth != 1) || 361 (info.format != first.format) || 362 (info.internal_format != first.internal_format) || 363 (info.type != first.type) || 364 feature_info->validators()->compressed_texture_format.IsValid( 365 info.internal_format) || 366 info.image.get()) { 367 return false; 368 } 369 } 370 return true; 371 } 372 373 void Texture::SetLevelCleared(GLenum target, GLint level, bool cleared) { 374 DCHECK_GE(level, 0); 375 DCHECK_LT(static_cast<size_t>(GLTargetToFaceIndex(target)), 376 level_infos_.size()); 377 DCHECK_LT(static_cast<size_t>(level), 378 level_infos_[GLTargetToFaceIndex(target)].size()); 379 Texture::LevelInfo& info = 380 level_infos_[GLTargetToFaceIndex(target)][level]; 381 UpdateMipCleared(&info, cleared); 382 UpdateCleared(); 383 } 384 385 void Texture::UpdateCleared() { 386 if (level_infos_.empty()) { 387 return; 388 } 389 390 const Texture::LevelInfo& first_face = level_infos_[0][0]; 391 int levels_needed = TextureManager::ComputeMipMapCount( 392 first_face.width, first_face.height, first_face.depth); 393 bool cleared = true; 394 for (size_t ii = 0; ii < level_infos_.size(); ++ii) { 395 for (GLint jj = 0; jj < levels_needed; ++jj) { 396 const Texture::LevelInfo& info = level_infos_[ii][jj]; 397 if (info.width > 0 && info.height > 0 && info.depth > 0 && 398 !info.cleared) { 399 cleared = false; 400 break; 401 } 402 } 403 } 404 UpdateSafeToRenderFrom(cleared); 405 } 406 407 void Texture::UpdateSafeToRenderFrom(bool cleared) { 408 if (cleared_ == cleared) 409 return; 410 cleared_ = cleared; 411 int delta = cleared ? -1 : +1; 412 for (RefSet::iterator it = refs_.begin(); it != refs_.end(); ++it) 413 (*it)->manager()->UpdateSafeToRenderFrom(delta); 414 } 415 416 void Texture::UpdateMipCleared(LevelInfo* info, bool cleared) { 417 if (info->cleared == cleared) 418 return; 419 info->cleared = cleared; 420 int delta = cleared ? -1 : +1; 421 num_uncleared_mips_ += delta; 422 for (RefSet::iterator it = refs_.begin(); it != refs_.end(); ++it) 423 (*it)->manager()->UpdateUnclearedMips(delta); 424 } 425 426 void Texture::UpdateCanRenderCondition() { 427 CanRenderCondition can_render_condition = GetCanRenderCondition(); 428 if (can_render_condition_ == can_render_condition) 429 return; 430 for (RefSet::iterator it = refs_.begin(); it != refs_.end(); ++it) 431 (*it)->manager()->UpdateCanRenderCondition(can_render_condition_, 432 can_render_condition); 433 can_render_condition_ = can_render_condition; 434 } 435 436 void Texture::IncAllFramebufferStateChangeCount() { 437 for (RefSet::iterator it = refs_.begin(); it != refs_.end(); ++it) 438 (*it)->manager()->IncFramebufferStateChangeCount(); 439 } 440 441 void Texture::SetLevelInfo( 442 const FeatureInfo* feature_info, 443 GLenum target, 444 GLint level, 445 GLenum internal_format, 446 GLsizei width, 447 GLsizei height, 448 GLsizei depth, 449 GLint border, 450 GLenum format, 451 GLenum type, 452 bool cleared) { 453 DCHECK_GE(level, 0); 454 DCHECK_LT(static_cast<size_t>(GLTargetToFaceIndex(target)), 455 level_infos_.size()); 456 DCHECK_LT(static_cast<size_t>(level), 457 level_infos_[GLTargetToFaceIndex(target)].size()); 458 DCHECK_GE(width, 0); 459 DCHECK_GE(height, 0); 460 DCHECK_GE(depth, 0); 461 Texture::LevelInfo& info = 462 level_infos_[GLTargetToFaceIndex(target)][level]; 463 info.target = target; 464 info.level = level; 465 info.internal_format = internal_format; 466 info.width = width; 467 info.height = height; 468 info.depth = depth; 469 info.border = border; 470 info.format = format; 471 info.type = type; 472 info.image = 0; 473 474 estimated_size_ -= info.estimated_size; 475 GLES2Util::ComputeImageDataSizes( 476 width, height, format, type, 4, &info.estimated_size, NULL, NULL); 477 estimated_size_ += info.estimated_size; 478 479 UpdateMipCleared(&info, cleared); 480 max_level_set_ = std::max(max_level_set_, level); 481 Update(feature_info); 482 UpdateCleared(); 483 UpdateCanRenderCondition(); 484 if (IsAttachedToFramebuffer()) { 485 // TODO(gman): If textures tracked which framebuffers they were attached to 486 // we could just mark those framebuffers as not complete. 487 IncAllFramebufferStateChangeCount(); 488 } 489 } 490 491 bool Texture::ValidForTexture( 492 GLint target, 493 GLint level, 494 GLint xoffset, 495 GLint yoffset, 496 GLsizei width, 497 GLsizei height, 498 GLenum format, 499 GLenum type) const { 500 size_t face_index = GLTargetToFaceIndex(target); 501 if (level >= 0 && face_index < level_infos_.size() && 502 static_cast<size_t>(level) < level_infos_[face_index].size()) { 503 const LevelInfo& info = level_infos_[GLTargetToFaceIndex(target)][level]; 504 int32 right; 505 int32 top; 506 return SafeAddInt32(xoffset, width, &right) && 507 SafeAddInt32(yoffset, height, &top) && 508 xoffset >= 0 && 509 yoffset >= 0 && 510 right <= info.width && 511 top <= info.height && 512 format == info.internal_format && 513 type == info.type; 514 } 515 return false; 516 } 517 518 bool Texture::GetLevelSize( 519 GLint target, GLint level, GLsizei* width, GLsizei* height) const { 520 DCHECK(width); 521 DCHECK(height); 522 size_t face_index = GLTargetToFaceIndex(target); 523 if (level >= 0 && face_index < level_infos_.size() && 524 static_cast<size_t>(level) < level_infos_[face_index].size()) { 525 const LevelInfo& info = level_infos_[GLTargetToFaceIndex(target)][level]; 526 if (info.target != 0) { 527 *width = info.width; 528 *height = info.height; 529 return true; 530 } 531 } 532 return false; 533 } 534 535 bool Texture::GetLevelType( 536 GLint target, GLint level, GLenum* type, GLenum* internal_format) const { 537 DCHECK(type); 538 DCHECK(internal_format); 539 size_t face_index = GLTargetToFaceIndex(target); 540 if (level >= 0 && face_index < level_infos_.size() && 541 static_cast<size_t>(level) < level_infos_[face_index].size()) { 542 const LevelInfo& info = level_infos_[GLTargetToFaceIndex(target)][level]; 543 if (info.target != 0) { 544 *type = info.type; 545 *internal_format = info.internal_format; 546 return true; 547 } 548 } 549 return false; 550 } 551 552 GLenum Texture::SetParameter( 553 const FeatureInfo* feature_info, GLenum pname, GLint param) { 554 DCHECK(feature_info); 555 556 if (target_ == GL_TEXTURE_EXTERNAL_OES || 557 target_ == GL_TEXTURE_RECTANGLE_ARB) { 558 if (pname == GL_TEXTURE_MIN_FILTER && 559 (param != GL_NEAREST && param != GL_LINEAR)) 560 return GL_INVALID_ENUM; 561 if ((pname == GL_TEXTURE_WRAP_S || pname == GL_TEXTURE_WRAP_T) && 562 param != GL_CLAMP_TO_EDGE) 563 return GL_INVALID_ENUM; 564 } 565 566 switch (pname) { 567 case GL_TEXTURE_MIN_FILTER: 568 if (!feature_info->validators()->texture_min_filter_mode.IsValid(param)) { 569 return GL_INVALID_ENUM; 570 } 571 min_filter_ = param; 572 break; 573 case GL_TEXTURE_MAG_FILTER: 574 if (!feature_info->validators()->texture_mag_filter_mode.IsValid(param)) { 575 return GL_INVALID_ENUM; 576 } 577 mag_filter_ = param; 578 break; 579 case GL_TEXTURE_POOL_CHROMIUM: 580 if (!feature_info->validators()->texture_pool.IsValid(param)) { 581 return GL_INVALID_ENUM; 582 } 583 GetMemTracker()->TrackMemFree(estimated_size()); 584 pool_ = param; 585 GetMemTracker()->TrackMemAlloc(estimated_size()); 586 break; 587 case GL_TEXTURE_WRAP_S: 588 if (!feature_info->validators()->texture_wrap_mode.IsValid(param)) { 589 return GL_INVALID_ENUM; 590 } 591 wrap_s_ = param; 592 break; 593 case GL_TEXTURE_WRAP_T: 594 if (!feature_info->validators()->texture_wrap_mode.IsValid(param)) { 595 return GL_INVALID_ENUM; 596 } 597 wrap_t_ = param; 598 break; 599 case GL_TEXTURE_MAX_ANISOTROPY_EXT: 600 if (param < 1) { 601 return GL_INVALID_VALUE; 602 } 603 break; 604 case GL_TEXTURE_USAGE_ANGLE: 605 if (!feature_info->validators()->texture_usage.IsValid(param)) { 606 return GL_INVALID_ENUM; 607 } 608 usage_ = param; 609 break; 610 default: 611 NOTREACHED(); 612 return GL_INVALID_ENUM; 613 } 614 Update(feature_info); 615 UpdateCleared(); 616 UpdateCanRenderCondition(); 617 return GL_NO_ERROR; 618 } 619 620 void Texture::Update(const FeatureInfo* feature_info) { 621 // Update npot status. 622 // Assume GL_TEXTURE_EXTERNAL_OES textures are npot, all others 623 npot_ = target_ == GL_TEXTURE_EXTERNAL_OES; 624 625 if (level_infos_.empty()) { 626 texture_complete_ = false; 627 cube_complete_ = false; 628 return; 629 } 630 631 // checks that the first mip of any face is npot. 632 for (size_t ii = 0; ii < level_infos_.size(); ++ii) { 633 const Texture::LevelInfo& info = level_infos_[ii][0]; 634 if (GLES2Util::IsNPOT(info.width) || 635 GLES2Util::IsNPOT(info.height) || 636 GLES2Util::IsNPOT(info.depth)) { 637 npot_ = true; 638 break; 639 } 640 } 641 642 // Update texture_complete and cube_complete status. 643 const Texture::LevelInfo& first_face = level_infos_[0][0]; 644 int levels_needed = TextureManager::ComputeMipMapCount( 645 first_face.width, first_face.height, first_face.depth); 646 texture_complete_ = 647 max_level_set_ >= (levels_needed - 1) && max_level_set_ >= 0; 648 cube_complete_ = (level_infos_.size() == 6) && 649 (first_face.width == first_face.height); 650 651 if (first_face.width == 0 || first_face.height == 0) { 652 texture_complete_ = false; 653 } 654 if (first_face.type == GL_FLOAT && 655 !feature_info->feature_flags().enable_texture_float_linear && 656 (min_filter_ != GL_NEAREST_MIPMAP_NEAREST || 657 mag_filter_ != GL_NEAREST)) { 658 texture_complete_ = false; 659 } else if (first_face.type == GL_HALF_FLOAT_OES && 660 !feature_info->feature_flags().enable_texture_half_float_linear && 661 (min_filter_ != GL_NEAREST_MIPMAP_NEAREST || 662 mag_filter_ != GL_NEAREST)) { 663 texture_complete_ = false; 664 } 665 for (size_t ii = 0; 666 ii < level_infos_.size() && (cube_complete_ || texture_complete_); 667 ++ii) { 668 const Texture::LevelInfo& level0 = level_infos_[ii][0]; 669 if (level0.target == 0 || 670 level0.width != first_face.width || 671 level0.height != first_face.height || 672 level0.depth != 1 || 673 level0.internal_format != first_face.internal_format || 674 level0.format != first_face.format || 675 level0.type != first_face.type) { 676 cube_complete_ = false; 677 } 678 // Get level0 dimensions 679 GLsizei width = level0.width; 680 GLsizei height = level0.height; 681 GLsizei depth = level0.depth; 682 for (GLint jj = 1; jj < levels_needed; ++jj) { 683 // compute required size for mip. 684 width = std::max(1, width >> 1); 685 height = std::max(1, height >> 1); 686 depth = std::max(1, depth >> 1); 687 const Texture::LevelInfo& info = level_infos_[ii][jj]; 688 if (info.target == 0 || 689 info.width != width || 690 info.height != height || 691 info.depth != depth || 692 info.internal_format != level0.internal_format || 693 info.format != level0.format || 694 info.type != level0.type) { 695 texture_complete_ = false; 696 break; 697 } 698 } 699 } 700 } 701 702 bool Texture::ClearRenderableLevels(GLES2Decoder* decoder) { 703 DCHECK(decoder); 704 if (cleared_) { 705 return true; 706 } 707 708 const Texture::LevelInfo& first_face = level_infos_[0][0]; 709 int levels_needed = TextureManager::ComputeMipMapCount( 710 first_face.width, first_face.height, first_face.depth); 711 712 for (size_t ii = 0; ii < level_infos_.size(); ++ii) { 713 for (GLint jj = 0; jj < levels_needed; ++jj) { 714 Texture::LevelInfo& info = level_infos_[ii][jj]; 715 if (info.target != 0) { 716 if (!ClearLevel(decoder, info.target, jj)) { 717 return false; 718 } 719 } 720 } 721 } 722 UpdateSafeToRenderFrom(true); 723 return true; 724 } 725 726 bool Texture::IsLevelCleared(GLenum target, GLint level) const { 727 size_t face_index = GLTargetToFaceIndex(target); 728 if (face_index >= level_infos_.size() || 729 level >= static_cast<GLint>(level_infos_[face_index].size())) { 730 return true; 731 } 732 733 const Texture::LevelInfo& info = level_infos_[face_index][level]; 734 735 return info.cleared; 736 } 737 738 bool Texture::ClearLevel( 739 GLES2Decoder* decoder, GLenum target, GLint level) { 740 DCHECK(decoder); 741 size_t face_index = GLTargetToFaceIndex(target); 742 if (face_index >= level_infos_.size() || 743 level >= static_cast<GLint>(level_infos_[face_index].size())) { 744 return true; 745 } 746 747 Texture::LevelInfo& info = level_infos_[face_index][level]; 748 749 DCHECK(target == info.target); 750 751 if (info.target == 0 || 752 info.cleared || 753 info.width == 0 || 754 info.height == 0 || 755 info.depth == 0) { 756 return true; 757 } 758 759 // NOTE: It seems kind of gross to call back into the decoder for this 760 // but only the decoder knows all the state (like unpack_alignment_) that's 761 // needed to be able to call GL correctly. 762 bool cleared = decoder->ClearLevel( 763 service_id_, target_, info.target, info.level, info.format, info.type, 764 info.width, info.height, immutable_); 765 UpdateMipCleared(&info, cleared); 766 return info.cleared; 767 } 768 769 void Texture::SetLevelImage( 770 const FeatureInfo* feature_info, 771 GLenum target, 772 GLint level, 773 gfx::GLImage* image) { 774 DCHECK_GE(level, 0); 775 DCHECK_LT(static_cast<size_t>(GLTargetToFaceIndex(target)), 776 level_infos_.size()); 777 DCHECK_LT(static_cast<size_t>(level), 778 level_infos_[GLTargetToFaceIndex(target)].size()); 779 Texture::LevelInfo& info = 780 level_infos_[GLTargetToFaceIndex(target)][level]; 781 DCHECK_EQ(info.target, target); 782 DCHECK_EQ(info.level, level); 783 info.image = image; 784 UpdateCanRenderCondition(); 785 } 786 787 gfx::GLImage* Texture::GetLevelImage( 788 GLint target, GLint level) const { 789 size_t face_index = GLTargetToFaceIndex(target); 790 if (level >= 0 && face_index < level_infos_.size() && 791 static_cast<size_t>(level) < level_infos_[face_index].size()) { 792 const LevelInfo& info = level_infos_[GLTargetToFaceIndex(target)][level]; 793 if (info.target != 0) { 794 return info.image.get(); 795 } 796 } 797 return 0; 798 } 799 800 801 TextureRef::TextureRef(TextureManager* manager, 802 GLuint client_id, 803 Texture* texture) 804 : manager_(manager), 805 texture_(texture), 806 client_id_(client_id), 807 is_stream_texture_owner_(false) { 808 DCHECK(manager_); 809 DCHECK(texture_); 810 texture_->AddTextureRef(this); 811 manager_->StartTracking(this); 812 } 813 814 scoped_refptr<TextureRef> TextureRef::Create(TextureManager* manager, 815 GLuint client_id, 816 GLuint service_id) { 817 return new TextureRef(manager, client_id, new Texture(service_id)); 818 } 819 820 TextureRef::~TextureRef() { 821 manager_->StopTracking(this); 822 texture_->RemoveTextureRef(this, manager_->have_context_); 823 manager_ = NULL; 824 } 825 826 TextureManager::TextureManager( 827 MemoryTracker* memory_tracker, 828 FeatureInfo* feature_info, 829 GLint max_texture_size, 830 GLint max_cube_map_texture_size) 831 : memory_tracker_managed_( 832 new MemoryTypeTracker(memory_tracker, MemoryTracker::kManaged)), 833 memory_tracker_unmanaged_( 834 new MemoryTypeTracker(memory_tracker, MemoryTracker::kUnmanaged)), 835 feature_info_(feature_info), 836 framebuffer_manager_(NULL), 837 stream_texture_manager_(NULL), 838 max_texture_size_(max_texture_size), 839 max_cube_map_texture_size_(max_cube_map_texture_size), 840 max_levels_(ComputeMipMapCount(max_texture_size, 841 max_texture_size, 842 max_texture_size)), 843 max_cube_map_levels_(ComputeMipMapCount(max_cube_map_texture_size, 844 max_cube_map_texture_size, 845 max_cube_map_texture_size)), 846 num_unrenderable_textures_(0), 847 num_unsafe_textures_(0), 848 num_uncleared_mips_(0), 849 texture_count_(0), 850 have_context_(true) { 851 for (int ii = 0; ii < kNumDefaultTextures; ++ii) { 852 black_texture_ids_[ii] = 0; 853 } 854 } 855 856 bool TextureManager::Initialize() { 857 // TODO(gman): The default textures have to be real textures, not the 0 858 // texture because we simulate non shared resources on top of shared 859 // resources and all contexts that share resource share the same default 860 // texture. 861 default_textures_[kTexture2D] = CreateDefaultAndBlackTextures( 862 GL_TEXTURE_2D, &black_texture_ids_[kTexture2D]); 863 default_textures_[kCubeMap] = CreateDefaultAndBlackTextures( 864 GL_TEXTURE_CUBE_MAP, &black_texture_ids_[kCubeMap]); 865 866 if (feature_info_->feature_flags().oes_egl_image_external) { 867 default_textures_[kExternalOES] = CreateDefaultAndBlackTextures( 868 GL_TEXTURE_EXTERNAL_OES, &black_texture_ids_[kExternalOES]); 869 } 870 871 if (feature_info_->feature_flags().arb_texture_rectangle) { 872 default_textures_[kRectangleARB] = CreateDefaultAndBlackTextures( 873 GL_TEXTURE_RECTANGLE_ARB, &black_texture_ids_[kRectangleARB]); 874 } 875 876 return true; 877 } 878 879 scoped_refptr<TextureRef> 880 TextureManager::CreateDefaultAndBlackTextures( 881 GLenum target, 882 GLuint* black_texture) { 883 static uint8 black[] = {0, 0, 0, 255}; 884 885 // Sampling a texture not associated with any EGLImage sibling will return 886 // black values according to the spec. 887 bool needs_initialization = (target != GL_TEXTURE_EXTERNAL_OES); 888 bool needs_faces = (target == GL_TEXTURE_CUBE_MAP); 889 890 // Make default textures and texture for replacing non-renderable textures. 891 GLuint ids[2]; 892 glGenTextures(arraysize(ids), ids); 893 for (unsigned long ii = 0; ii < arraysize(ids); ++ii) { 894 glBindTexture(target, ids[ii]); 895 if (needs_initialization) { 896 if (needs_faces) { 897 for (int jj = 0; jj < GLES2Util::kNumFaces; ++jj) { 898 glTexImage2D(GLES2Util::IndexToGLFaceTarget(jj), 0, GL_RGBA, 1, 1, 0, 899 GL_RGBA, GL_UNSIGNED_BYTE, black); 900 } 901 } else { 902 glTexImage2D(target, 0, GL_RGBA, 1, 1, 0, GL_RGBA, 903 GL_UNSIGNED_BYTE, black); 904 } 905 } 906 } 907 glBindTexture(target, 0); 908 909 scoped_refptr<TextureRef> default_texture( 910 TextureRef::Create(this, 0, ids[1])); 911 SetTarget(default_texture.get(), target); 912 if (needs_faces) { 913 for (int ii = 0; ii < GLES2Util::kNumFaces; ++ii) { 914 SetLevelInfo(default_texture.get(), 915 GLES2Util::IndexToGLFaceTarget(ii), 916 0, 917 GL_RGBA, 918 1, 919 1, 920 1, 921 0, 922 GL_RGBA, 923 GL_UNSIGNED_BYTE, 924 true); 925 } 926 } else { 927 if (needs_initialization) { 928 SetLevelInfo(default_texture.get(), 929 GL_TEXTURE_2D, 930 0, 931 GL_RGBA, 932 1, 933 1, 934 1, 935 0, 936 GL_RGBA, 937 GL_UNSIGNED_BYTE, 938 true); 939 } else { 940 SetLevelInfo(default_texture.get(), 941 GL_TEXTURE_EXTERNAL_OES, 942 0, 943 GL_RGBA, 944 1, 945 1, 946 1, 947 0, 948 GL_RGBA, 949 GL_UNSIGNED_BYTE, 950 true); 951 } 952 } 953 954 *black_texture = ids[0]; 955 return default_texture; 956 } 957 958 bool TextureManager::ValidForTarget( 959 GLenum target, GLint level, GLsizei width, GLsizei height, GLsizei depth) { 960 GLsizei max_size = MaxSizeForTarget(target) >> level; 961 return level >= 0 && 962 width >= 0 && 963 height >= 0 && 964 depth >= 0 && 965 level < MaxLevelsForTarget(target) && 966 width <= max_size && 967 height <= max_size && 968 depth <= max_size && 969 (level == 0 || feature_info_->feature_flags().npot_ok || 970 (!GLES2Util::IsNPOT(width) && 971 !GLES2Util::IsNPOT(height) && 972 !GLES2Util::IsNPOT(depth))) && 973 (target != GL_TEXTURE_CUBE_MAP || (width == height && depth == 1)) && 974 (target != GL_TEXTURE_2D || (depth == 1)); 975 } 976 977 void TextureManager::SetTarget(TextureRef* ref, GLenum target) { 978 DCHECK(ref); 979 ref->texture() 980 ->SetTarget(feature_info_.get(), target, MaxLevelsForTarget(target)); 981 } 982 983 void TextureManager::SetStreamTexture(TextureRef* ref, bool stream_texture) { 984 DCHECK(ref); 985 // Only the owner can mark as non-stream texture. 986 DCHECK_EQ(stream_texture, !ref->is_stream_texture_owner_); 987 ref->texture()->SetStreamTexture(stream_texture); 988 ref->set_is_stream_texture_owner(stream_texture); 989 } 990 991 bool TextureManager::IsStreamTextureOwner(TextureRef* ref) { 992 DCHECK(ref); 993 return ref->is_stream_texture_owner(); 994 } 995 996 void TextureManager::SetLevelCleared(TextureRef* ref, 997 GLenum target, 998 GLint level, 999 bool cleared) { 1000 DCHECK(ref); 1001 ref->texture()->SetLevelCleared(target, level, cleared); 1002 } 1003 1004 bool TextureManager::ClearRenderableLevels( 1005 GLES2Decoder* decoder, TextureRef* ref) { 1006 DCHECK(ref); 1007 return ref->texture()->ClearRenderableLevels(decoder); 1008 } 1009 1010 bool TextureManager::ClearTextureLevel( 1011 GLES2Decoder* decoder, TextureRef* ref, 1012 GLenum target, GLint level) { 1013 DCHECK(ref); 1014 Texture* texture = ref->texture(); 1015 if (texture->num_uncleared_mips() == 0) { 1016 return true; 1017 } 1018 bool result = texture->ClearLevel(decoder, target, level); 1019 texture->UpdateCleared(); 1020 return result; 1021 } 1022 1023 void TextureManager::SetLevelInfo( 1024 TextureRef* ref, 1025 GLenum target, 1026 GLint level, 1027 GLenum internal_format, 1028 GLsizei width, 1029 GLsizei height, 1030 GLsizei depth, 1031 GLint border, 1032 GLenum format, 1033 GLenum type, 1034 bool cleared) { 1035 DCHECK(ref); 1036 Texture* texture = ref->texture(); 1037 1038 texture->GetMemTracker()->TrackMemFree(texture->estimated_size()); 1039 texture->SetLevelInfo(feature_info_.get(), 1040 target, 1041 level, 1042 internal_format, 1043 width, 1044 height, 1045 depth, 1046 border, 1047 format, 1048 type, 1049 cleared); 1050 texture->GetMemTracker()->TrackMemAlloc(texture->estimated_size()); 1051 } 1052 1053 Texture* TextureManager::Produce(TextureRef* ref) { 1054 DCHECK(ref); 1055 return ref->texture(); 1056 } 1057 1058 TextureRef* TextureManager::Consume( 1059 GLuint client_id, 1060 Texture* texture) { 1061 DCHECK(client_id); 1062 scoped_refptr<TextureRef> ref(new TextureRef(this, client_id, texture)); 1063 bool result = textures_.insert(std::make_pair(client_id, ref)).second; 1064 DCHECK(result); 1065 return ref.get(); 1066 } 1067 1068 void TextureManager::SetParameter( 1069 const char* function_name, ErrorState* error_state, 1070 TextureRef* ref, GLenum pname, GLint param) { 1071 DCHECK(error_state); 1072 DCHECK(ref); 1073 Texture* texture = ref->texture(); 1074 GLenum result = texture->SetParameter(feature_info_.get(), pname, param); 1075 if (result != GL_NO_ERROR) { 1076 if (result == GL_INVALID_ENUM) { 1077 ERRORSTATE_SET_GL_ERROR_INVALID_ENUM( 1078 error_state, function_name, param, "param"); 1079 } else { 1080 ERRORSTATE_SET_GL_ERROR_INVALID_PARAM( 1081 error_state, result, function_name, pname, static_cast<GLint>(param)); 1082 } 1083 } else { 1084 // Texture tracking pools exist only for the command decoder, so 1085 // do not pass them on to the native GL implementation. 1086 if (pname != GL_TEXTURE_POOL_CHROMIUM) { 1087 glTexParameteri(texture->target(), pname, param); 1088 } 1089 } 1090 } 1091 1092 bool TextureManager::MarkMipmapsGenerated(TextureRef* ref) { 1093 DCHECK(ref); 1094 Texture* texture = ref->texture(); 1095 texture->GetMemTracker()->TrackMemFree(texture->estimated_size()); 1096 bool result = texture->MarkMipmapsGenerated(feature_info_.get()); 1097 texture->GetMemTracker()->TrackMemAlloc(texture->estimated_size()); 1098 return result; 1099 } 1100 1101 TextureRef* TextureManager::CreateTexture( 1102 GLuint client_id, GLuint service_id) { 1103 DCHECK_NE(0u, service_id); 1104 scoped_refptr<TextureRef> ref(TextureRef::Create( 1105 this, client_id, service_id)); 1106 std::pair<TextureMap::iterator, bool> result = 1107 textures_.insert(std::make_pair(client_id, ref)); 1108 DCHECK(result.second); 1109 return ref.get(); 1110 } 1111 1112 TextureRef* TextureManager::GetTexture( 1113 GLuint client_id) const { 1114 TextureMap::const_iterator it = textures_.find(client_id); 1115 return it != textures_.end() ? it->second.get() : NULL; 1116 } 1117 1118 void TextureManager::RemoveTexture(GLuint client_id) { 1119 TextureMap::iterator it = textures_.find(client_id); 1120 if (it != textures_.end()) { 1121 it->second->reset_client_id(); 1122 textures_.erase(it); 1123 } 1124 } 1125 1126 void TextureManager::StartTracking(TextureRef* ref) { 1127 Texture* texture = ref->texture(); 1128 ++texture_count_; 1129 num_uncleared_mips_ += texture->num_uncleared_mips(); 1130 if (!texture->SafeToRenderFrom()) 1131 ++num_unsafe_textures_; 1132 if (!texture->CanRender(feature_info_.get())) 1133 ++num_unrenderable_textures_; 1134 } 1135 1136 void TextureManager::StopTracking(TextureRef* ref) { 1137 FOR_EACH_OBSERVER(DestructionObserver, 1138 destruction_observers_, 1139 OnTextureRefDestroying(ref)); 1140 1141 Texture* texture = ref->texture(); 1142 if (ref->is_stream_texture_owner_ && stream_texture_manager_) { 1143 DCHECK(texture->IsStreamTexture()); 1144 stream_texture_manager_->DestroyStreamTexture(texture->service_id()); 1145 } 1146 1147 --texture_count_; 1148 if (!texture->CanRender(feature_info_.get())) { 1149 DCHECK_NE(0, num_unrenderable_textures_); 1150 --num_unrenderable_textures_; 1151 } 1152 if (!texture->SafeToRenderFrom()) { 1153 DCHECK_NE(0, num_unsafe_textures_); 1154 --num_unsafe_textures_; 1155 } 1156 num_uncleared_mips_ -= texture->num_uncleared_mips(); 1157 DCHECK_GE(num_uncleared_mips_, 0); 1158 } 1159 1160 MemoryTypeTracker* TextureManager::GetMemTracker(GLenum tracking_pool) { 1161 switch(tracking_pool) { 1162 case GL_TEXTURE_POOL_MANAGED_CHROMIUM: 1163 return memory_tracker_managed_.get(); 1164 break; 1165 case GL_TEXTURE_POOL_UNMANAGED_CHROMIUM: 1166 return memory_tracker_unmanaged_.get(); 1167 break; 1168 default: 1169 break; 1170 } 1171 NOTREACHED(); 1172 return NULL; 1173 } 1174 1175 Texture* TextureManager::GetTextureForServiceId(GLuint service_id) const { 1176 // This doesn't need to be fast. It's only used during slow queries. 1177 for (TextureMap::const_iterator it = textures_.begin(); 1178 it != textures_.end(); ++it) { 1179 Texture* texture = it->second->texture(); 1180 if (texture->service_id() == service_id) 1181 return texture; 1182 } 1183 return NULL; 1184 } 1185 1186 GLsizei TextureManager::ComputeMipMapCount( 1187 GLsizei width, GLsizei height, GLsizei depth) { 1188 return 1 + base::bits::Log2Floor(std::max(std::max(width, height), depth)); 1189 } 1190 1191 void TextureManager::SetLevelImage( 1192 TextureRef* ref, 1193 GLenum target, 1194 GLint level, 1195 gfx::GLImage* image) { 1196 DCHECK(ref); 1197 ref->texture()->SetLevelImage(feature_info_.get(), target, level, image); 1198 } 1199 1200 void TextureManager::AddToSignature( 1201 TextureRef* ref, 1202 GLenum target, 1203 GLint level, 1204 std::string* signature) const { 1205 ref->texture()->AddToSignature(feature_info_.get(), target, level, signature); 1206 } 1207 1208 void TextureManager::UpdateSafeToRenderFrom(int delta) { 1209 num_unsafe_textures_ += delta; 1210 DCHECK_GE(num_unsafe_textures_, 0); 1211 } 1212 1213 void TextureManager::UpdateUnclearedMips(int delta) { 1214 num_uncleared_mips_ += delta; 1215 DCHECK_GE(num_uncleared_mips_, 0); 1216 } 1217 1218 void TextureManager::UpdateCanRenderCondition( 1219 Texture::CanRenderCondition old_condition, 1220 Texture::CanRenderCondition new_condition) { 1221 if (old_condition == Texture::CAN_RENDER_NEVER || 1222 (old_condition == Texture::CAN_RENDER_ONLY_IF_NPOT && 1223 !feature_info_->feature_flags().npot_ok)) { 1224 DCHECK_GT(num_unrenderable_textures_, 0); 1225 --num_unrenderable_textures_; 1226 } 1227 if (new_condition == Texture::CAN_RENDER_NEVER || 1228 (new_condition == Texture::CAN_RENDER_ONLY_IF_NPOT && 1229 !feature_info_->feature_flags().npot_ok)) 1230 ++num_unrenderable_textures_; 1231 } 1232 1233 void TextureManager::IncFramebufferStateChangeCount() { 1234 if (framebuffer_manager_) 1235 framebuffer_manager_->IncFramebufferStateChangeCount(); 1236 1237 } 1238 1239 } // namespace gles2 1240 } // namespace gpu 1241