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