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/context_state.h" 10 #include "gpu/command_buffer/service/error_state.h" 11 #include "gpu/command_buffer/service/feature_info.h" 12 #include "gpu/command_buffer/service/framebuffer_manager.h" 13 #include "gpu/command_buffer/service/gles2_cmd_decoder.h" 14 #include "gpu/command_buffer/service/mailbox_manager.h" 15 #include "gpu/command_buffer/service/memory_tracking.h" 16 #include "gpu/command_buffer/service/stream_texture_manager.h" 17 18 namespace gpu { 19 namespace gles2 { 20 21 static size_t GLTargetToFaceIndex(GLenum target) { 22 switch (target) { 23 case GL_TEXTURE_2D: 24 case GL_TEXTURE_EXTERNAL_OES: 25 case GL_TEXTURE_RECTANGLE_ARB: 26 return 0; 27 case GL_TEXTURE_CUBE_MAP_POSITIVE_X: 28 return 0; 29 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X: 30 return 1; 31 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y: 32 return 2; 33 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y: 34 return 3; 35 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z: 36 return 4; 37 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z: 38 return 5; 39 default: 40 NOTREACHED(); 41 return 0; 42 } 43 } 44 45 static size_t FaceIndexToGLTarget(size_t index) { 46 switch (index) { 47 case 0: 48 return GL_TEXTURE_CUBE_MAP_POSITIVE_X; 49 case 1: 50 return GL_TEXTURE_CUBE_MAP_NEGATIVE_X; 51 case 2: 52 return GL_TEXTURE_CUBE_MAP_POSITIVE_Y; 53 case 3: 54 return GL_TEXTURE_CUBE_MAP_NEGATIVE_Y; 55 case 4: 56 return GL_TEXTURE_CUBE_MAP_POSITIVE_Z; 57 case 5: 58 return GL_TEXTURE_CUBE_MAP_NEGATIVE_Z; 59 default: 60 NOTREACHED(); 61 return 0; 62 } 63 } 64 65 TextureManager::DestructionObserver::DestructionObserver() {} 66 67 TextureManager::DestructionObserver::~DestructionObserver() {} 68 69 TextureManager::~TextureManager() { 70 FOR_EACH_OBSERVER(DestructionObserver, 71 destruction_observers_, 72 OnTextureManagerDestroying(this)); 73 74 DCHECK(textures_.empty()); 75 76 // If this triggers, that means something is keeping a reference to 77 // a Texture belonging to this. 78 CHECK_EQ(texture_count_, 0u); 79 80 DCHECK_EQ(0, num_unrenderable_textures_); 81 DCHECK_EQ(0, num_unsafe_textures_); 82 DCHECK_EQ(0, num_uncleared_mips_); 83 DCHECK_EQ(0, num_images_); 84 } 85 86 void TextureManager::Destroy(bool have_context) { 87 have_context_ = have_context; 88 textures_.clear(); 89 for (int ii = 0; ii < kNumDefaultTextures; ++ii) { 90 default_textures_[ii] = NULL; 91 } 92 93 if (have_context) { 94 glDeleteTextures(arraysize(black_texture_ids_), black_texture_ids_); 95 } 96 97 DCHECK_EQ(0u, memory_tracker_managed_->GetMemRepresented()); 98 DCHECK_EQ(0u, memory_tracker_unmanaged_->GetMemRepresented()); 99 } 100 101 Texture::Texture(GLuint service_id) 102 : mailbox_manager_(NULL), 103 memory_tracking_ref_(NULL), 104 service_id_(service_id), 105 cleared_(true), 106 num_uncleared_mips_(0), 107 target_(0), 108 min_filter_(GL_NEAREST_MIPMAP_LINEAR), 109 mag_filter_(GL_LINEAR), 110 wrap_s_(GL_REPEAT), 111 wrap_t_(GL_REPEAT), 112 usage_(GL_NONE), 113 pool_(GL_TEXTURE_POOL_UNMANAGED_CHROMIUM), 114 max_level_set_(-1), 115 texture_complete_(false), 116 cube_complete_(false), 117 npot_(false), 118 has_been_bound_(false), 119 framebuffer_attachment_count_(0), 120 stream_texture_(false), 121 immutable_(false), 122 has_images_(false), 123 estimated_size_(0), 124 can_render_condition_(CAN_RENDER_ALWAYS) { 125 } 126 127 Texture::~Texture() { 128 if (mailbox_manager_) 129 mailbox_manager_->TextureDeleted(this); 130 } 131 132 void Texture::AddTextureRef(TextureRef* ref) { 133 DCHECK(refs_.find(ref) == refs_.end()); 134 refs_.insert(ref); 135 if (!memory_tracking_ref_) { 136 memory_tracking_ref_ = ref; 137 GetMemTracker()->TrackMemAlloc(estimated_size()); 138 } 139 } 140 141 void Texture::RemoveTextureRef(TextureRef* ref, bool have_context) { 142 if (memory_tracking_ref_ == ref) { 143 GetMemTracker()->TrackMemFree(estimated_size()); 144 memory_tracking_ref_ = NULL; 145 } 146 size_t result = refs_.erase(ref); 147 DCHECK_EQ(result, 1u); 148 if (refs_.empty()) { 149 if (have_context) { 150 GLuint id = service_id(); 151 glDeleteTextures(1, &id); 152 } 153 delete this; 154 } else if (memory_tracking_ref_ == NULL) { 155 // TODO(piman): tune ownership semantics for cross-context group shared 156 // textures. 157 memory_tracking_ref_ = *refs_.begin(); 158 GetMemTracker()->TrackMemAlloc(estimated_size()); 159 } 160 } 161 162 MemoryTypeTracker* Texture::GetMemTracker() { 163 DCHECK(memory_tracking_ref_); 164 return memory_tracking_ref_->manager()->GetMemTracker(pool_); 165 } 166 167 Texture::LevelInfo::LevelInfo() 168 : cleared(true), 169 target(0), 170 level(-1), 171 internal_format(0), 172 width(0), 173 height(0), 174 depth(0), 175 border(0), 176 format(0), 177 type(0), 178 estimated_size(0) { 179 } 180 181 Texture::LevelInfo::LevelInfo(const LevelInfo& rhs) 182 : cleared(rhs.cleared), 183 target(rhs.target), 184 level(rhs.level), 185 internal_format(rhs.internal_format), 186 width(rhs.width), 187 height(rhs.height), 188 depth(rhs.depth), 189 border(rhs.border), 190 format(rhs.format), 191 type(rhs.type), 192 image(rhs.image), 193 estimated_size(rhs.estimated_size) { 194 } 195 196 Texture::LevelInfo::~LevelInfo() { 197 } 198 199 Texture::CanRenderCondition Texture::GetCanRenderCondition() const { 200 if (target_ == 0) 201 return CAN_RENDER_ALWAYS; 202 203 if (target_ != GL_TEXTURE_EXTERNAL_OES) { 204 if (level_infos_.empty()) { 205 return CAN_RENDER_NEVER; 206 } 207 208 const Texture::LevelInfo& first_face = level_infos_[0][0]; 209 if (first_face.width == 0 || 210 first_face.height == 0 || 211 first_face.depth == 0) { 212 return CAN_RENDER_NEVER; 213 } 214 } 215 216 bool needs_mips = NeedsMips(); 217 if (needs_mips) { 218 if (!texture_complete()) 219 return CAN_RENDER_NEVER; 220 if (target_ == GL_TEXTURE_CUBE_MAP && !cube_complete()) 221 return CAN_RENDER_NEVER; 222 } 223 224 bool is_npot_compatible = !needs_mips && 225 wrap_s_ == GL_CLAMP_TO_EDGE && 226 wrap_t_ == GL_CLAMP_TO_EDGE; 227 228 if (!is_npot_compatible) { 229 if (target_ == GL_TEXTURE_RECTANGLE_ARB) 230 return CAN_RENDER_NEVER; 231 else if (npot()) 232 return CAN_RENDER_ONLY_IF_NPOT; 233 } 234 235 return CAN_RENDER_ALWAYS; 236 } 237 238 bool Texture::CanRender(const FeatureInfo* feature_info) const { 239 switch (can_render_condition_) { 240 case CAN_RENDER_ALWAYS: 241 return true; 242 case CAN_RENDER_NEVER: 243 return false; 244 case CAN_RENDER_ONLY_IF_NPOT: 245 break; 246 } 247 return feature_info->feature_flags().npot_ok; 248 } 249 250 void Texture::AddToSignature( 251 const FeatureInfo* feature_info, 252 GLenum target, 253 GLint level, 254 std::string* signature) const { 255 DCHECK(feature_info); 256 DCHECK(signature); 257 DCHECK_GE(level, 0); 258 DCHECK_LT(static_cast<size_t>(GLTargetToFaceIndex(target)), 259 level_infos_.size()); 260 DCHECK_LT(static_cast<size_t>(level), 261 level_infos_[GLTargetToFaceIndex(target)].size()); 262 const Texture::LevelInfo& info = 263 level_infos_[GLTargetToFaceIndex(target)][level]; 264 *signature += base::StringPrintf( 265 "|Texture|target=%04x|level=%d|internal_format=%04x" 266 "|width=%d|height=%d|depth=%d|border=%d|format=%04x|type=%04x" 267 "|image=%d|canrender=%d|canrenderto=%d|npot_=%d" 268 "|min_filter=%04x|mag_filter=%04x|wrap_s=%04x|wrap_t=%04x" 269 "|usage=%04x", 270 target, level, info.internal_format, 271 info.width, info.height, info.depth, info.border, 272 info.format, info.type, info.image.get() != NULL, 273 CanRender(feature_info), CanRenderTo(), npot_, 274 min_filter_, mag_filter_, wrap_s_, wrap_t_, 275 usage_); 276 } 277 278 void Texture::SetMailboxManager(MailboxManager* mailbox_manager) { 279 DCHECK(!mailbox_manager_ || mailbox_manager_ == mailbox_manager); 280 mailbox_manager_ = mailbox_manager; 281 } 282 283 bool Texture::MarkMipmapsGenerated( 284 const FeatureInfo* feature_info) { 285 if (!CanGenerateMipmaps(feature_info)) { 286 return false; 287 } 288 for (size_t ii = 0; ii < level_infos_.size(); ++ii) { 289 const Texture::LevelInfo& info1 = level_infos_[ii][0]; 290 GLsizei width = info1.width; 291 GLsizei height = info1.height; 292 GLsizei depth = info1.depth; 293 GLenum target = target_ == GL_TEXTURE_2D ? GL_TEXTURE_2D : 294 FaceIndexToGLTarget(ii); 295 int num_mips = 296 TextureManager::ComputeMipMapCount(target_, 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 target_, 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::UpdateHasImages() { 437 if (level_infos_.empty()) 438 return; 439 440 bool has_images = false; 441 for (size_t ii = 0; ii < level_infos_.size(); ++ii) { 442 for (size_t jj = 0; jj < level_infos_[ii].size(); ++jj) { 443 const Texture::LevelInfo& info = level_infos_[ii][jj]; 444 if (info.image.get() != NULL) { 445 has_images = true; 446 break; 447 } 448 } 449 } 450 451 if (has_images_ == has_images) 452 return; 453 has_images_ = has_images; 454 int delta = has_images ? +1 : -1; 455 for (RefSet::iterator it = refs_.begin(); it != refs_.end(); ++it) 456 (*it)->manager()->UpdateNumImages(delta); 457 } 458 459 void Texture::IncAllFramebufferStateChangeCount() { 460 for (RefSet::iterator it = refs_.begin(); it != refs_.end(); ++it) 461 (*it)->manager()->IncFramebufferStateChangeCount(); 462 } 463 464 void Texture::SetLevelInfo( 465 const FeatureInfo* feature_info, 466 GLenum target, 467 GLint level, 468 GLenum internal_format, 469 GLsizei width, 470 GLsizei height, 471 GLsizei depth, 472 GLint border, 473 GLenum format, 474 GLenum type, 475 bool cleared) { 476 DCHECK_GE(level, 0); 477 DCHECK_LT(static_cast<size_t>(GLTargetToFaceIndex(target)), 478 level_infos_.size()); 479 DCHECK_LT(static_cast<size_t>(level), 480 level_infos_[GLTargetToFaceIndex(target)].size()); 481 DCHECK_GE(width, 0); 482 DCHECK_GE(height, 0); 483 DCHECK_GE(depth, 0); 484 Texture::LevelInfo& info = 485 level_infos_[GLTargetToFaceIndex(target)][level]; 486 info.target = target; 487 info.level = level; 488 info.internal_format = internal_format; 489 info.width = width; 490 info.height = height; 491 info.depth = depth; 492 info.border = border; 493 info.format = format; 494 info.type = type; 495 info.image = 0; 496 497 estimated_size_ -= info.estimated_size; 498 GLES2Util::ComputeImageDataSizes( 499 width, height, format, type, 4, &info.estimated_size, NULL, NULL); 500 estimated_size_ += info.estimated_size; 501 502 UpdateMipCleared(&info, cleared); 503 max_level_set_ = std::max(max_level_set_, level); 504 Update(feature_info); 505 UpdateCleared(); 506 UpdateCanRenderCondition(); 507 UpdateHasImages(); 508 if (IsAttachedToFramebuffer()) { 509 // TODO(gman): If textures tracked which framebuffers they were attached to 510 // we could just mark those framebuffers as not complete. 511 IncAllFramebufferStateChangeCount(); 512 } 513 } 514 515 bool Texture::ValidForTexture( 516 GLint target, 517 GLint level, 518 GLint xoffset, 519 GLint yoffset, 520 GLsizei width, 521 GLsizei height, 522 GLenum format, 523 GLenum type) const { 524 size_t face_index = GLTargetToFaceIndex(target); 525 if (level >= 0 && face_index < level_infos_.size() && 526 static_cast<size_t>(level) < level_infos_[face_index].size()) { 527 const LevelInfo& info = level_infos_[GLTargetToFaceIndex(target)][level]; 528 int32 right; 529 int32 top; 530 return SafeAddInt32(xoffset, width, &right) && 531 SafeAddInt32(yoffset, height, &top) && 532 xoffset >= 0 && 533 yoffset >= 0 && 534 right <= info.width && 535 top <= info.height && 536 format == info.internal_format && 537 type == info.type; 538 } 539 return false; 540 } 541 542 bool Texture::GetLevelSize( 543 GLint target, GLint level, GLsizei* width, GLsizei* height) const { 544 DCHECK(width); 545 DCHECK(height); 546 size_t face_index = GLTargetToFaceIndex(target); 547 if (level >= 0 && face_index < level_infos_.size() && 548 static_cast<size_t>(level) < level_infos_[face_index].size()) { 549 const LevelInfo& info = level_infos_[GLTargetToFaceIndex(target)][level]; 550 if (info.target != 0) { 551 *width = info.width; 552 *height = info.height; 553 return true; 554 } 555 } 556 return false; 557 } 558 559 bool Texture::GetLevelType( 560 GLint target, GLint level, GLenum* type, GLenum* internal_format) const { 561 DCHECK(type); 562 DCHECK(internal_format); 563 size_t face_index = GLTargetToFaceIndex(target); 564 if (level >= 0 && face_index < level_infos_.size() && 565 static_cast<size_t>(level) < level_infos_[face_index].size()) { 566 const LevelInfo& info = level_infos_[GLTargetToFaceIndex(target)][level]; 567 if (info.target != 0) { 568 *type = info.type; 569 *internal_format = info.internal_format; 570 return true; 571 } 572 } 573 return false; 574 } 575 576 GLenum Texture::SetParameter( 577 const FeatureInfo* feature_info, GLenum pname, GLint param) { 578 DCHECK(feature_info); 579 580 if (target_ == GL_TEXTURE_EXTERNAL_OES || 581 target_ == GL_TEXTURE_RECTANGLE_ARB) { 582 if (pname == GL_TEXTURE_MIN_FILTER && 583 (param != GL_NEAREST && param != GL_LINEAR)) 584 return GL_INVALID_ENUM; 585 if ((pname == GL_TEXTURE_WRAP_S || pname == GL_TEXTURE_WRAP_T) && 586 param != GL_CLAMP_TO_EDGE) 587 return GL_INVALID_ENUM; 588 } 589 590 switch (pname) { 591 case GL_TEXTURE_MIN_FILTER: 592 if (!feature_info->validators()->texture_min_filter_mode.IsValid(param)) { 593 return GL_INVALID_ENUM; 594 } 595 min_filter_ = param; 596 break; 597 case GL_TEXTURE_MAG_FILTER: 598 if (!feature_info->validators()->texture_mag_filter_mode.IsValid(param)) { 599 return GL_INVALID_ENUM; 600 } 601 mag_filter_ = param; 602 break; 603 case GL_TEXTURE_POOL_CHROMIUM: 604 if (!feature_info->validators()->texture_pool.IsValid(param)) { 605 return GL_INVALID_ENUM; 606 } 607 GetMemTracker()->TrackMemFree(estimated_size()); 608 pool_ = param; 609 GetMemTracker()->TrackMemAlloc(estimated_size()); 610 break; 611 case GL_TEXTURE_WRAP_S: 612 if (!feature_info->validators()->texture_wrap_mode.IsValid(param)) { 613 return GL_INVALID_ENUM; 614 } 615 wrap_s_ = param; 616 break; 617 case GL_TEXTURE_WRAP_T: 618 if (!feature_info->validators()->texture_wrap_mode.IsValid(param)) { 619 return GL_INVALID_ENUM; 620 } 621 wrap_t_ = param; 622 break; 623 case GL_TEXTURE_MAX_ANISOTROPY_EXT: 624 if (param < 1) { 625 return GL_INVALID_VALUE; 626 } 627 break; 628 case GL_TEXTURE_USAGE_ANGLE: 629 if (!feature_info->validators()->texture_usage.IsValid(param)) { 630 return GL_INVALID_ENUM; 631 } 632 usage_ = param; 633 break; 634 default: 635 NOTREACHED(); 636 return GL_INVALID_ENUM; 637 } 638 Update(feature_info); 639 UpdateCleared(); 640 UpdateCanRenderCondition(); 641 return GL_NO_ERROR; 642 } 643 644 void Texture::Update(const FeatureInfo* feature_info) { 645 // Update npot status. 646 // Assume GL_TEXTURE_EXTERNAL_OES textures are npot, all others 647 npot_ = target_ == GL_TEXTURE_EXTERNAL_OES; 648 649 if (level_infos_.empty()) { 650 texture_complete_ = false; 651 cube_complete_ = false; 652 return; 653 } 654 655 // checks that the first mip of any face is npot. 656 for (size_t ii = 0; ii < level_infos_.size(); ++ii) { 657 const Texture::LevelInfo& info = level_infos_[ii][0]; 658 if (GLES2Util::IsNPOT(info.width) || 659 GLES2Util::IsNPOT(info.height) || 660 GLES2Util::IsNPOT(info.depth)) { 661 npot_ = true; 662 break; 663 } 664 } 665 666 // Update texture_complete and cube_complete status. 667 const Texture::LevelInfo& first_face = level_infos_[0][0]; 668 int levels_needed = TextureManager::ComputeMipMapCount( 669 target_, first_face.width, first_face.height, first_face.depth); 670 texture_complete_ = 671 max_level_set_ >= (levels_needed - 1) && max_level_set_ >= 0; 672 cube_complete_ = (level_infos_.size() == 6) && 673 (first_face.width == first_face.height); 674 675 if (first_face.width == 0 || first_face.height == 0) { 676 texture_complete_ = false; 677 } 678 if (first_face.type == GL_FLOAT && 679 !feature_info->feature_flags().enable_texture_float_linear && 680 (min_filter_ != GL_NEAREST_MIPMAP_NEAREST || 681 mag_filter_ != GL_NEAREST)) { 682 texture_complete_ = false; 683 } else if (first_face.type == GL_HALF_FLOAT_OES && 684 !feature_info->feature_flags().enable_texture_half_float_linear && 685 (min_filter_ != GL_NEAREST_MIPMAP_NEAREST || 686 mag_filter_ != GL_NEAREST)) { 687 texture_complete_ = false; 688 } 689 for (size_t ii = 0; 690 ii < level_infos_.size() && (cube_complete_ || texture_complete_); 691 ++ii) { 692 const Texture::LevelInfo& level0 = level_infos_[ii][0]; 693 if (level0.target == 0 || 694 level0.width != first_face.width || 695 level0.height != first_face.height || 696 level0.depth != 1 || 697 level0.internal_format != first_face.internal_format || 698 level0.format != first_face.format || 699 level0.type != first_face.type) { 700 cube_complete_ = false; 701 } 702 // Get level0 dimensions 703 GLsizei width = level0.width; 704 GLsizei height = level0.height; 705 GLsizei depth = level0.depth; 706 for (GLint jj = 1; jj < levels_needed; ++jj) { 707 // compute required size for mip. 708 width = std::max(1, width >> 1); 709 height = std::max(1, height >> 1); 710 depth = std::max(1, depth >> 1); 711 const Texture::LevelInfo& info = level_infos_[ii][jj]; 712 if (info.target == 0 || 713 info.width != width || 714 info.height != height || 715 info.depth != depth || 716 info.internal_format != level0.internal_format || 717 info.format != level0.format || 718 info.type != level0.type) { 719 texture_complete_ = false; 720 break; 721 } 722 } 723 } 724 } 725 726 bool Texture::ClearRenderableLevels(GLES2Decoder* decoder) { 727 DCHECK(decoder); 728 if (cleared_) { 729 return true; 730 } 731 732 const Texture::LevelInfo& first_face = level_infos_[0][0]; 733 int levels_needed = TextureManager::ComputeMipMapCount( 734 target_, first_face.width, first_face.height, first_face.depth); 735 736 for (size_t ii = 0; ii < level_infos_.size(); ++ii) { 737 for (GLint jj = 0; jj < levels_needed; ++jj) { 738 Texture::LevelInfo& info = level_infos_[ii][jj]; 739 if (info.target != 0) { 740 if (!ClearLevel(decoder, info.target, jj)) { 741 return false; 742 } 743 } 744 } 745 } 746 UpdateSafeToRenderFrom(true); 747 return true; 748 } 749 750 bool Texture::IsLevelCleared(GLenum target, GLint level) const { 751 size_t face_index = GLTargetToFaceIndex(target); 752 if (face_index >= level_infos_.size() || 753 level >= static_cast<GLint>(level_infos_[face_index].size())) { 754 return true; 755 } 756 757 const Texture::LevelInfo& info = level_infos_[face_index][level]; 758 759 return info.cleared; 760 } 761 762 bool Texture::ClearLevel( 763 GLES2Decoder* decoder, GLenum target, GLint level) { 764 DCHECK(decoder); 765 size_t face_index = GLTargetToFaceIndex(target); 766 if (face_index >= level_infos_.size() || 767 level >= static_cast<GLint>(level_infos_[face_index].size())) { 768 return true; 769 } 770 771 Texture::LevelInfo& info = level_infos_[face_index][level]; 772 773 DCHECK(target == info.target); 774 775 if (info.target == 0 || 776 info.cleared || 777 info.width == 0 || 778 info.height == 0 || 779 info.depth == 0) { 780 return true; 781 } 782 783 // NOTE: It seems kind of gross to call back into the decoder for this 784 // but only the decoder knows all the state (like unpack_alignment_) that's 785 // needed to be able to call GL correctly. 786 bool cleared = decoder->ClearLevel( 787 service_id_, target_, info.target, info.level, info.format, info.type, 788 info.width, info.height, immutable_); 789 UpdateMipCleared(&info, cleared); 790 return info.cleared; 791 } 792 793 void Texture::SetLevelImage( 794 const FeatureInfo* feature_info, 795 GLenum target, 796 GLint level, 797 gfx::GLImage* image) { 798 DCHECK_GE(level, 0); 799 DCHECK_LT(static_cast<size_t>(GLTargetToFaceIndex(target)), 800 level_infos_.size()); 801 DCHECK_LT(static_cast<size_t>(level), 802 level_infos_[GLTargetToFaceIndex(target)].size()); 803 Texture::LevelInfo& info = 804 level_infos_[GLTargetToFaceIndex(target)][level]; 805 DCHECK_EQ(info.target, target); 806 DCHECK_EQ(info.level, level); 807 info.image = image; 808 UpdateCanRenderCondition(); 809 UpdateHasImages(); 810 } 811 812 gfx::GLImage* Texture::GetLevelImage(GLint target, GLint level) const { 813 if (target != GL_TEXTURE_2D && target != GL_TEXTURE_EXTERNAL_OES && 814 target != GL_TEXTURE_RECTANGLE_ARB) { 815 return NULL; 816 } 817 818 size_t face_index = GLTargetToFaceIndex(target); 819 if (level >= 0 && face_index < level_infos_.size() && 820 static_cast<size_t>(level) < level_infos_[face_index].size()) { 821 const LevelInfo& info = level_infos_[GLTargetToFaceIndex(target)][level]; 822 if (info.target != 0) { 823 return info.image.get(); 824 } 825 } 826 return 0; 827 } 828 829 void Texture::OnWillModifyPixels() { 830 gfx::GLImage* image = GetLevelImage(target(), 0); 831 if (image) 832 image->WillModifyTexImage(); 833 } 834 835 void Texture::OnDidModifyPixels() { 836 gfx::GLImage* image = GetLevelImage(target(), 0); 837 if (image) 838 image->DidModifyTexImage(); 839 } 840 841 TextureRef::TextureRef(TextureManager* manager, 842 GLuint client_id, 843 Texture* texture) 844 : manager_(manager), 845 texture_(texture), 846 client_id_(client_id), 847 is_stream_texture_owner_(false) { 848 DCHECK(manager_); 849 DCHECK(texture_); 850 texture_->AddTextureRef(this); 851 manager_->StartTracking(this); 852 } 853 854 scoped_refptr<TextureRef> TextureRef::Create(TextureManager* manager, 855 GLuint client_id, 856 GLuint service_id) { 857 return new TextureRef(manager, client_id, new Texture(service_id)); 858 } 859 860 TextureRef::~TextureRef() { 861 manager_->StopTracking(this); 862 texture_->RemoveTextureRef(this, manager_->have_context_); 863 manager_ = NULL; 864 } 865 866 TextureManager::TextureManager(MemoryTracker* memory_tracker, 867 FeatureInfo* feature_info, 868 GLint max_texture_size, 869 GLint max_cube_map_texture_size) 870 : memory_tracker_managed_(new MemoryTypeTracker(memory_tracker, 871 MemoryTracker::kManaged)), 872 memory_tracker_unmanaged_( 873 new MemoryTypeTracker(memory_tracker, MemoryTracker::kUnmanaged)), 874 feature_info_(feature_info), 875 framebuffer_manager_(NULL), 876 stream_texture_manager_(NULL), 877 max_texture_size_(max_texture_size), 878 max_cube_map_texture_size_(max_cube_map_texture_size), 879 max_levels_(ComputeMipMapCount(GL_TEXTURE_2D, 880 max_texture_size, 881 max_texture_size, 882 max_texture_size)), 883 max_cube_map_levels_(ComputeMipMapCount(GL_TEXTURE_CUBE_MAP, 884 max_cube_map_texture_size, 885 max_cube_map_texture_size, 886 max_cube_map_texture_size)), 887 num_unrenderable_textures_(0), 888 num_unsafe_textures_(0), 889 num_uncleared_mips_(0), 890 num_images_(0), 891 texture_count_(0), 892 have_context_(true) { 893 for (int ii = 0; ii < kNumDefaultTextures; ++ii) { 894 black_texture_ids_[ii] = 0; 895 } 896 } 897 898 bool TextureManager::Initialize() { 899 // TODO(gman): The default textures have to be real textures, not the 0 900 // texture because we simulate non shared resources on top of shared 901 // resources and all contexts that share resource share the same default 902 // texture. 903 default_textures_[kTexture2D] = CreateDefaultAndBlackTextures( 904 GL_TEXTURE_2D, &black_texture_ids_[kTexture2D]); 905 default_textures_[kCubeMap] = CreateDefaultAndBlackTextures( 906 GL_TEXTURE_CUBE_MAP, &black_texture_ids_[kCubeMap]); 907 908 if (feature_info_->feature_flags().oes_egl_image_external) { 909 default_textures_[kExternalOES] = CreateDefaultAndBlackTextures( 910 GL_TEXTURE_EXTERNAL_OES, &black_texture_ids_[kExternalOES]); 911 } 912 913 if (feature_info_->feature_flags().arb_texture_rectangle) { 914 default_textures_[kRectangleARB] = CreateDefaultAndBlackTextures( 915 GL_TEXTURE_RECTANGLE_ARB, &black_texture_ids_[kRectangleARB]); 916 } 917 918 return true; 919 } 920 921 scoped_refptr<TextureRef> 922 TextureManager::CreateDefaultAndBlackTextures( 923 GLenum target, 924 GLuint* black_texture) { 925 static uint8 black[] = {0, 0, 0, 255}; 926 927 // Sampling a texture not associated with any EGLImage sibling will return 928 // black values according to the spec. 929 bool needs_initialization = (target != GL_TEXTURE_EXTERNAL_OES); 930 bool needs_faces = (target == GL_TEXTURE_CUBE_MAP); 931 932 // Make default textures and texture for replacing non-renderable textures. 933 GLuint ids[2]; 934 glGenTextures(arraysize(ids), ids); 935 for (unsigned long ii = 0; ii < arraysize(ids); ++ii) { 936 glBindTexture(target, ids[ii]); 937 if (needs_initialization) { 938 if (needs_faces) { 939 for (int jj = 0; jj < GLES2Util::kNumFaces; ++jj) { 940 glTexImage2D(GLES2Util::IndexToGLFaceTarget(jj), 0, GL_RGBA, 1, 1, 0, 941 GL_RGBA, GL_UNSIGNED_BYTE, black); 942 } 943 } else { 944 glTexImage2D(target, 0, GL_RGBA, 1, 1, 0, GL_RGBA, 945 GL_UNSIGNED_BYTE, black); 946 } 947 } 948 } 949 glBindTexture(target, 0); 950 951 scoped_refptr<TextureRef> default_texture( 952 TextureRef::Create(this, 0, ids[1])); 953 SetTarget(default_texture.get(), target); 954 if (needs_faces) { 955 for (int ii = 0; ii < GLES2Util::kNumFaces; ++ii) { 956 SetLevelInfo(default_texture.get(), 957 GLES2Util::IndexToGLFaceTarget(ii), 958 0, 959 GL_RGBA, 960 1, 961 1, 962 1, 963 0, 964 GL_RGBA, 965 GL_UNSIGNED_BYTE, 966 true); 967 } 968 } else { 969 if (needs_initialization) { 970 SetLevelInfo(default_texture.get(), 971 GL_TEXTURE_2D, 972 0, 973 GL_RGBA, 974 1, 975 1, 976 1, 977 0, 978 GL_RGBA, 979 GL_UNSIGNED_BYTE, 980 true); 981 } else { 982 SetLevelInfo(default_texture.get(), 983 GL_TEXTURE_EXTERNAL_OES, 984 0, 985 GL_RGBA, 986 1, 987 1, 988 1, 989 0, 990 GL_RGBA, 991 GL_UNSIGNED_BYTE, 992 true); 993 } 994 } 995 996 *black_texture = ids[0]; 997 return default_texture; 998 } 999 1000 bool TextureManager::ValidForTarget( 1001 GLenum target, GLint level, GLsizei width, GLsizei height, GLsizei depth) { 1002 GLsizei max_size = MaxSizeForTarget(target) >> level; 1003 return level >= 0 && 1004 width >= 0 && 1005 height >= 0 && 1006 depth >= 0 && 1007 level < MaxLevelsForTarget(target) && 1008 width <= max_size && 1009 height <= max_size && 1010 depth <= max_size && 1011 (level == 0 || feature_info_->feature_flags().npot_ok || 1012 (!GLES2Util::IsNPOT(width) && 1013 !GLES2Util::IsNPOT(height) && 1014 !GLES2Util::IsNPOT(depth))) && 1015 (target != GL_TEXTURE_CUBE_MAP || (width == height && depth == 1)) && 1016 (target != GL_TEXTURE_2D || (depth == 1)); 1017 } 1018 1019 void TextureManager::SetTarget(TextureRef* ref, GLenum target) { 1020 DCHECK(ref); 1021 ref->texture() 1022 ->SetTarget(feature_info_.get(), target, MaxLevelsForTarget(target)); 1023 } 1024 1025 void TextureManager::SetStreamTexture(TextureRef* ref, bool stream_texture) { 1026 DCHECK(ref); 1027 // Only the owner can mark as non-stream texture. 1028 DCHECK_EQ(stream_texture, !ref->is_stream_texture_owner_); 1029 ref->texture()->SetStreamTexture(stream_texture); 1030 ref->set_is_stream_texture_owner(stream_texture); 1031 } 1032 1033 bool TextureManager::IsStreamTextureOwner(TextureRef* ref) { 1034 DCHECK(ref); 1035 return ref->is_stream_texture_owner(); 1036 } 1037 1038 void TextureManager::SetLevelCleared(TextureRef* ref, 1039 GLenum target, 1040 GLint level, 1041 bool cleared) { 1042 DCHECK(ref); 1043 ref->texture()->SetLevelCleared(target, level, cleared); 1044 } 1045 1046 bool TextureManager::ClearRenderableLevels( 1047 GLES2Decoder* decoder, TextureRef* ref) { 1048 DCHECK(ref); 1049 return ref->texture()->ClearRenderableLevels(decoder); 1050 } 1051 1052 bool TextureManager::ClearTextureLevel( 1053 GLES2Decoder* decoder, TextureRef* ref, 1054 GLenum target, GLint level) { 1055 DCHECK(ref); 1056 Texture* texture = ref->texture(); 1057 if (texture->num_uncleared_mips() == 0) { 1058 return true; 1059 } 1060 bool result = texture->ClearLevel(decoder, target, level); 1061 texture->UpdateCleared(); 1062 return result; 1063 } 1064 1065 void TextureManager::SetLevelInfo( 1066 TextureRef* ref, 1067 GLenum target, 1068 GLint level, 1069 GLenum internal_format, 1070 GLsizei width, 1071 GLsizei height, 1072 GLsizei depth, 1073 GLint border, 1074 GLenum format, 1075 GLenum type, 1076 bool cleared) { 1077 DCHECK(ref); 1078 Texture* texture = ref->texture(); 1079 1080 texture->GetMemTracker()->TrackMemFree(texture->estimated_size()); 1081 texture->SetLevelInfo(feature_info_.get(), 1082 target, 1083 level, 1084 internal_format, 1085 width, 1086 height, 1087 depth, 1088 border, 1089 format, 1090 type, 1091 cleared); 1092 texture->GetMemTracker()->TrackMemAlloc(texture->estimated_size()); 1093 } 1094 1095 Texture* TextureManager::Produce(TextureRef* ref) { 1096 DCHECK(ref); 1097 return ref->texture(); 1098 } 1099 1100 TextureRef* TextureManager::Consume( 1101 GLuint client_id, 1102 Texture* texture) { 1103 DCHECK(client_id); 1104 scoped_refptr<TextureRef> ref(new TextureRef(this, client_id, texture)); 1105 bool result = textures_.insert(std::make_pair(client_id, ref)).second; 1106 DCHECK(result); 1107 return ref.get(); 1108 } 1109 1110 void TextureManager::SetParameter( 1111 const char* function_name, ErrorState* error_state, 1112 TextureRef* ref, GLenum pname, GLint param) { 1113 DCHECK(error_state); 1114 DCHECK(ref); 1115 Texture* texture = ref->texture(); 1116 GLenum result = texture->SetParameter(feature_info_.get(), pname, param); 1117 if (result != GL_NO_ERROR) { 1118 if (result == GL_INVALID_ENUM) { 1119 ERRORSTATE_SET_GL_ERROR_INVALID_ENUM( 1120 error_state, function_name, param, "param"); 1121 } else { 1122 ERRORSTATE_SET_GL_ERROR_INVALID_PARAM( 1123 error_state, result, function_name, pname, static_cast<GLint>(param)); 1124 } 1125 } else { 1126 // Texture tracking pools exist only for the command decoder, so 1127 // do not pass them on to the native GL implementation. 1128 if (pname != GL_TEXTURE_POOL_CHROMIUM) { 1129 glTexParameteri(texture->target(), pname, param); 1130 } 1131 } 1132 } 1133 1134 bool TextureManager::MarkMipmapsGenerated(TextureRef* ref) { 1135 DCHECK(ref); 1136 Texture* texture = ref->texture(); 1137 texture->GetMemTracker()->TrackMemFree(texture->estimated_size()); 1138 bool result = texture->MarkMipmapsGenerated(feature_info_.get()); 1139 texture->GetMemTracker()->TrackMemAlloc(texture->estimated_size()); 1140 return result; 1141 } 1142 1143 TextureRef* TextureManager::CreateTexture( 1144 GLuint client_id, GLuint service_id) { 1145 DCHECK_NE(0u, service_id); 1146 scoped_refptr<TextureRef> ref(TextureRef::Create( 1147 this, client_id, service_id)); 1148 std::pair<TextureMap::iterator, bool> result = 1149 textures_.insert(std::make_pair(client_id, ref)); 1150 DCHECK(result.second); 1151 return ref.get(); 1152 } 1153 1154 TextureRef* TextureManager::GetTexture( 1155 GLuint client_id) const { 1156 TextureMap::const_iterator it = textures_.find(client_id); 1157 return it != textures_.end() ? it->second.get() : NULL; 1158 } 1159 1160 void TextureManager::RemoveTexture(GLuint client_id) { 1161 TextureMap::iterator it = textures_.find(client_id); 1162 if (it != textures_.end()) { 1163 it->second->reset_client_id(); 1164 textures_.erase(it); 1165 } 1166 } 1167 1168 void TextureManager::StartTracking(TextureRef* ref) { 1169 Texture* texture = ref->texture(); 1170 ++texture_count_; 1171 num_uncleared_mips_ += texture->num_uncleared_mips(); 1172 if (!texture->SafeToRenderFrom()) 1173 ++num_unsafe_textures_; 1174 if (!texture->CanRender(feature_info_.get())) 1175 ++num_unrenderable_textures_; 1176 if (texture->HasImages()) 1177 ++num_images_; 1178 } 1179 1180 void TextureManager::StopTracking(TextureRef* ref) { 1181 FOR_EACH_OBSERVER(DestructionObserver, 1182 destruction_observers_, 1183 OnTextureRefDestroying(ref)); 1184 1185 Texture* texture = ref->texture(); 1186 if (ref->is_stream_texture_owner_ && stream_texture_manager_) { 1187 DCHECK(texture->IsStreamTexture()); 1188 stream_texture_manager_->DestroyStreamTexture(texture->service_id()); 1189 } 1190 1191 --texture_count_; 1192 if (texture->HasImages()) { 1193 DCHECK_NE(0, num_images_); 1194 --num_images_; 1195 } 1196 if (!texture->CanRender(feature_info_.get())) { 1197 DCHECK_NE(0, num_unrenderable_textures_); 1198 --num_unrenderable_textures_; 1199 } 1200 if (!texture->SafeToRenderFrom()) { 1201 DCHECK_NE(0, num_unsafe_textures_); 1202 --num_unsafe_textures_; 1203 } 1204 num_uncleared_mips_ -= texture->num_uncleared_mips(); 1205 DCHECK_GE(num_uncleared_mips_, 0); 1206 } 1207 1208 MemoryTypeTracker* TextureManager::GetMemTracker(GLenum tracking_pool) { 1209 switch(tracking_pool) { 1210 case GL_TEXTURE_POOL_MANAGED_CHROMIUM: 1211 return memory_tracker_managed_.get(); 1212 break; 1213 case GL_TEXTURE_POOL_UNMANAGED_CHROMIUM: 1214 return memory_tracker_unmanaged_.get(); 1215 break; 1216 default: 1217 break; 1218 } 1219 NOTREACHED(); 1220 return NULL; 1221 } 1222 1223 Texture* TextureManager::GetTextureForServiceId(GLuint service_id) const { 1224 // This doesn't need to be fast. It's only used during slow queries. 1225 for (TextureMap::const_iterator it = textures_.begin(); 1226 it != textures_.end(); ++it) { 1227 Texture* texture = it->second->texture(); 1228 if (texture->service_id() == service_id) 1229 return texture; 1230 } 1231 return NULL; 1232 } 1233 1234 GLsizei TextureManager::ComputeMipMapCount(GLenum target, 1235 GLsizei width, 1236 GLsizei height, 1237 GLsizei depth) { 1238 switch (target) { 1239 case GL_TEXTURE_EXTERNAL_OES: 1240 return 1; 1241 default: 1242 return 1 + 1243 base::bits::Log2Floor(std::max(std::max(width, height), depth)); 1244 } 1245 } 1246 1247 void TextureManager::SetLevelImage( 1248 TextureRef* ref, 1249 GLenum target, 1250 GLint level, 1251 gfx::GLImage* image) { 1252 DCHECK(ref); 1253 ref->texture()->SetLevelImage(feature_info_.get(), target, level, image); 1254 } 1255 1256 void TextureManager::AddToSignature( 1257 TextureRef* ref, 1258 GLenum target, 1259 GLint level, 1260 std::string* signature) const { 1261 ref->texture()->AddToSignature(feature_info_.get(), target, level, signature); 1262 } 1263 1264 void TextureManager::UpdateSafeToRenderFrom(int delta) { 1265 num_unsafe_textures_ += delta; 1266 DCHECK_GE(num_unsafe_textures_, 0); 1267 } 1268 1269 void TextureManager::UpdateUnclearedMips(int delta) { 1270 num_uncleared_mips_ += delta; 1271 DCHECK_GE(num_uncleared_mips_, 0); 1272 } 1273 1274 void TextureManager::UpdateCanRenderCondition( 1275 Texture::CanRenderCondition old_condition, 1276 Texture::CanRenderCondition new_condition) { 1277 if (old_condition == Texture::CAN_RENDER_NEVER || 1278 (old_condition == Texture::CAN_RENDER_ONLY_IF_NPOT && 1279 !feature_info_->feature_flags().npot_ok)) { 1280 DCHECK_GT(num_unrenderable_textures_, 0); 1281 --num_unrenderable_textures_; 1282 } 1283 if (new_condition == Texture::CAN_RENDER_NEVER || 1284 (new_condition == Texture::CAN_RENDER_ONLY_IF_NPOT && 1285 !feature_info_->feature_flags().npot_ok)) 1286 ++num_unrenderable_textures_; 1287 } 1288 1289 void TextureManager::UpdateNumImages(int delta) { 1290 num_images_ += delta; 1291 DCHECK_GE(num_images_, 0); 1292 } 1293 1294 void TextureManager::IncFramebufferStateChangeCount() { 1295 if (framebuffer_manager_) 1296 framebuffer_manager_->IncFramebufferStateChangeCount(); 1297 } 1298 1299 bool TextureManager::ValidateTextureParameters( 1300 ErrorState* error_state, const char* function_name, 1301 GLenum target, GLenum format, GLenum type, GLint level) { 1302 if (!feature_info_->GetTextureFormatValidator(format).IsValid(type)) { 1303 ERRORSTATE_SET_GL_ERROR( 1304 error_state, GL_INVALID_OPERATION, function_name, 1305 (std::string("invalid type ") + 1306 GLES2Util::GetStringEnum(type) + " for format " + 1307 GLES2Util::GetStringEnum(format)).c_str()); 1308 return false; 1309 } 1310 1311 uint32 channels = GLES2Util::GetChannelsForFormat(format); 1312 if ((channels & (GLES2Util::kDepth | GLES2Util::kStencil)) != 0 && level) { 1313 ERRORSTATE_SET_GL_ERROR( 1314 error_state, GL_INVALID_OPERATION, function_name, 1315 (std::string("invalid type ") + 1316 GLES2Util::GetStringEnum(type) + " for format " + 1317 GLES2Util::GetStringEnum(format)).c_str()); 1318 return false; 1319 } 1320 return true; 1321 } 1322 1323 // Gets the texture id for a given target. 1324 TextureRef* TextureManager::GetTextureInfoForTarget( 1325 ContextState* state, GLenum target) { 1326 TextureUnit& unit = state->texture_units[state->active_texture_unit]; 1327 TextureRef* texture = NULL; 1328 switch (target) { 1329 case GL_TEXTURE_2D: 1330 texture = unit.bound_texture_2d.get(); 1331 break; 1332 case GL_TEXTURE_CUBE_MAP: 1333 case GL_TEXTURE_CUBE_MAP_POSITIVE_X: 1334 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X: 1335 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y: 1336 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y: 1337 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z: 1338 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z: 1339 texture = unit.bound_texture_cube_map.get(); 1340 break; 1341 case GL_TEXTURE_EXTERNAL_OES: 1342 texture = unit.bound_texture_external_oes.get(); 1343 break; 1344 case GL_TEXTURE_RECTANGLE_ARB: 1345 texture = unit.bound_texture_rectangle_arb.get(); 1346 break; 1347 default: 1348 NOTREACHED(); 1349 return NULL; 1350 } 1351 return texture; 1352 } 1353 1354 TextureRef* TextureManager::GetTextureInfoForTargetUnlessDefault( 1355 ContextState* state, GLenum target) { 1356 TextureRef* texture = GetTextureInfoForTarget(state, target); 1357 if (!texture) 1358 return NULL; 1359 if (texture == GetDefaultTextureInfo(target)) 1360 return NULL; 1361 return texture; 1362 } 1363 1364 bool TextureManager::ValidateTexImage2D( 1365 ContextState* state, 1366 const char* function_name, 1367 const DoTextImage2DArguments& args, 1368 TextureRef** texture_ref) { 1369 ErrorState* error_state = state->GetErrorState(); 1370 const Validators* validators = feature_info_->validators(); 1371 if (!validators->texture_target.IsValid(args.target)) { 1372 ERRORSTATE_SET_GL_ERROR_INVALID_ENUM( 1373 error_state, function_name, args.target, "target"); 1374 return false; 1375 } 1376 if (!validators->texture_format.IsValid(args.internal_format)) { 1377 ERRORSTATE_SET_GL_ERROR_INVALID_ENUM( 1378 error_state, function_name, args.internal_format, 1379 "internal_format"); 1380 return false; 1381 } 1382 if (!validators->texture_format.IsValid(args.format)) { 1383 ERRORSTATE_SET_GL_ERROR_INVALID_ENUM( 1384 error_state, function_name, args.format, "format"); 1385 return false; 1386 } 1387 if (!validators->pixel_type.IsValid(args.type)) { 1388 ERRORSTATE_SET_GL_ERROR_INVALID_ENUM( 1389 error_state, function_name, args.type, "type"); 1390 return false; 1391 } 1392 if (args.format != args.internal_format) { 1393 ERRORSTATE_SET_GL_ERROR( 1394 error_state, GL_INVALID_OPERATION, function_name, 1395 "format != internalFormat"); 1396 return false; 1397 } 1398 if (!ValidateTextureParameters( 1399 error_state, function_name, args.target, args.format, args.type, 1400 args.level)) { 1401 return false; 1402 } 1403 if (!ValidForTarget(args.target, args.level, args.width, args.height, 1) || 1404 args.border != 0) { 1405 ERRORSTATE_SET_GL_ERROR( 1406 error_state, GL_INVALID_VALUE, function_name, 1407 "dimensions out of range"); 1408 return false; 1409 } 1410 if ((GLES2Util::GetChannelsForFormat(args.format) & 1411 (GLES2Util::kDepth | GLES2Util::kStencil)) != 0 && args.pixels) { 1412 ERRORSTATE_SET_GL_ERROR( 1413 error_state, GL_INVALID_OPERATION, 1414 function_name, "can not supply data for depth or stencil textures"); 1415 return false; 1416 } 1417 1418 TextureRef* local_texture_ref = GetTextureInfoForTarget(state, args.target); 1419 if (!local_texture_ref) { 1420 ERRORSTATE_SET_GL_ERROR( 1421 error_state, GL_INVALID_OPERATION, function_name, 1422 "unknown texture for target"); 1423 return false; 1424 } 1425 if (local_texture_ref->texture()->IsImmutable()) { 1426 ERRORSTATE_SET_GL_ERROR( 1427 error_state, GL_INVALID_OPERATION, function_name, 1428 "texture is immutable"); 1429 return false; 1430 } 1431 1432 // TODO - verify that using the managed vs unmanaged does not matter. 1433 // They both use the same MemoryTracker, and this call just re-routes 1434 // to it. 1435 if (!memory_tracker_managed_->EnsureGPUMemoryAvailable(args.pixels_size)) { 1436 ERRORSTATE_SET_GL_ERROR(error_state, GL_OUT_OF_MEMORY, "glTexImage2D", 1437 "out of memory"); 1438 return false; 1439 } 1440 1441 // Write the TextureReference since this is valid. 1442 *texture_ref = local_texture_ref; 1443 return true; 1444 } 1445 1446 void TextureManager::ValidateAndDoTexImage2D( 1447 DecoderTextureState* texture_state, 1448 ContextState* state, 1449 DecoderFramebufferState* framebuffer_state, 1450 const DoTextImage2DArguments& args) { 1451 TextureRef* texture_ref; 1452 if (!ValidateTexImage2D(state, "glTexImage2D", args, &texture_ref)) { 1453 return; 1454 } 1455 1456 DoTexImage2D(texture_state, state->GetErrorState(), framebuffer_state, 1457 texture_ref, args); 1458 } 1459 1460 void TextureManager::DoTexImage2D( 1461 DecoderTextureState* texture_state, 1462 ErrorState* error_state, 1463 DecoderFramebufferState* framebuffer_state, 1464 TextureRef* texture_ref, 1465 const DoTextImage2DArguments& args) { 1466 Texture* texture = texture_ref->texture(); 1467 GLsizei tex_width = 0; 1468 GLsizei tex_height = 0; 1469 GLenum tex_type = 0; 1470 GLenum tex_format = 0; 1471 bool level_is_same = 1472 texture->GetLevelSize(args.target, args.level, &tex_width, &tex_height) && 1473 texture->GetLevelType(args.target, args.level, &tex_type, &tex_format) && 1474 args.width == tex_width && args.height == tex_height && 1475 args.type == tex_type && args.format == tex_format; 1476 1477 if (level_is_same && !args.pixels) { 1478 // Just set the level texture but mark the texture as uncleared. 1479 SetLevelInfo( 1480 texture_ref, 1481 args.target, args.level, args.internal_format, args.width, args.height, 1482 1, args.border, args.format, args.type, false); 1483 texture_state->tex_image_2d_failed = false; 1484 return; 1485 } 1486 1487 if (texture->IsAttachedToFramebuffer()) { 1488 framebuffer_state->clear_state_dirty = true; 1489 } 1490 1491 if (texture_state->texsubimage2d_faster_than_teximage2d && 1492 level_is_same && args.pixels) { 1493 { 1494 ScopedTextureUploadTimer timer(texture_state); 1495 glTexSubImage2D(args.target, args.level, 0, 0, args.width, args.height, 1496 args.format, args.type, args.pixels); 1497 } 1498 SetLevelCleared(texture_ref, args.target, args.level, true); 1499 texture_state->tex_image_2d_failed = false; 1500 return; 1501 } 1502 1503 ERRORSTATE_COPY_REAL_GL_ERRORS_TO_WRAPPER(error_state, "glTexImage2D"); 1504 { 1505 ScopedTextureUploadTimer timer(texture_state); 1506 glTexImage2D( 1507 args.target, args.level, args.internal_format, args.width, args.height, 1508 args.border, args.format, args.type, args.pixels); 1509 } 1510 GLenum error = ERRORSTATE_PEEK_GL_ERROR(error_state, "glTexImage2D"); 1511 if (error == GL_NO_ERROR) { 1512 SetLevelInfo( 1513 texture_ref, 1514 args.target, args.level, args.internal_format, args.width, args.height, 1515 1, args.border, args.format, args.type, args.pixels != NULL); 1516 texture_state->tex_image_2d_failed = false; 1517 } 1518 } 1519 1520 ScopedTextureUploadTimer::ScopedTextureUploadTimer( 1521 DecoderTextureState* texture_state) 1522 : texture_state_(texture_state), 1523 begin_time_(base::TimeTicks::HighResNow()) { 1524 } 1525 1526 ScopedTextureUploadTimer::~ScopedTextureUploadTimer() { 1527 texture_state_->texture_upload_count++; 1528 texture_state_->total_texture_upload_time += 1529 base::TimeTicks::HighResNow() - begin_time_; 1530 } 1531 1532 } // namespace gles2 1533 } // namespace gpu 1534