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