| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "gpu/command_buffer/service/texture_manager.h" | 5 #include "gpu/command_buffer/service/texture_manager.h" |
| 6 | 6 |
| 7 #include <algorithm> | 7 #include <algorithm> |
| 8 #include <utility> | 8 #include <utility> |
| 9 | 9 |
| 10 #include "base/bits.h" | 10 #include "base/bits.h" |
| (...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 121 DCHECK_EQ(0u, memory_tracker_managed_->GetMemRepresented()); | 121 DCHECK_EQ(0u, memory_tracker_managed_->GetMemRepresented()); |
| 122 DCHECK_EQ(0u, memory_tracker_unmanaged_->GetMemRepresented()); | 122 DCHECK_EQ(0u, memory_tracker_unmanaged_->GetMemRepresented()); |
| 123 } | 123 } |
| 124 | 124 |
| 125 Texture::Texture(GLuint service_id) | 125 Texture::Texture(GLuint service_id) |
| 126 : mailbox_manager_(NULL), | 126 : mailbox_manager_(NULL), |
| 127 memory_tracking_ref_(NULL), | 127 memory_tracking_ref_(NULL), |
| 128 service_id_(service_id), | 128 service_id_(service_id), |
| 129 cleared_(true), | 129 cleared_(true), |
| 130 num_uncleared_mips_(0), | 130 num_uncleared_mips_(0), |
| 131 num_npot_faces_(0), |
| 131 target_(0), | 132 target_(0), |
| 132 min_filter_(GL_NEAREST_MIPMAP_LINEAR), | 133 min_filter_(GL_NEAREST_MIPMAP_LINEAR), |
| 133 mag_filter_(GL_LINEAR), | 134 mag_filter_(GL_LINEAR), |
| 134 wrap_s_(GL_REPEAT), | 135 wrap_s_(GL_REPEAT), |
| 135 wrap_t_(GL_REPEAT), | 136 wrap_t_(GL_REPEAT), |
| 136 usage_(GL_NONE), | 137 usage_(GL_NONE), |
| 137 pool_(GL_TEXTURE_POOL_UNMANAGED_CHROMIUM), | 138 pool_(GL_TEXTURE_POOL_UNMANAGED_CHROMIUM), |
| 138 max_level_set_(-1), | 139 max_level_set_(-1), |
| 139 texture_complete_(false), | 140 texture_complete_(false), |
| 141 texture_mips_dirty_(false), |
| 142 texture_mips_complete_(false), |
| 140 cube_complete_(false), | 143 cube_complete_(false), |
| 144 texture_level0_dirty_(false), |
| 145 texture_level0_complete_(false), |
| 141 npot_(false), | 146 npot_(false), |
| 142 has_been_bound_(false), | 147 has_been_bound_(false), |
| 143 framebuffer_attachment_count_(0), | 148 framebuffer_attachment_count_(0), |
| 144 immutable_(false), | 149 immutable_(false), |
| 145 has_images_(false), | 150 has_images_(false), |
| 146 estimated_size_(0), | 151 estimated_size_(0), |
| 147 can_render_condition_(CAN_RENDER_ALWAYS), | 152 can_render_condition_(CAN_RENDER_ALWAYS), |
| 148 texture_max_anisotropy_initialized_(false) { | 153 texture_max_anisotropy_initialized_(false) { |
| 149 } | 154 } |
| 150 | 155 |
| (...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 213 border(rhs.border), | 218 border(rhs.border), |
| 214 format(rhs.format), | 219 format(rhs.format), |
| 215 type(rhs.type), | 220 type(rhs.type), |
| 216 image(rhs.image), | 221 image(rhs.image), |
| 217 estimated_size(rhs.estimated_size) { | 222 estimated_size(rhs.estimated_size) { |
| 218 } | 223 } |
| 219 | 224 |
| 220 Texture::LevelInfo::~LevelInfo() { | 225 Texture::LevelInfo::~LevelInfo() { |
| 221 } | 226 } |
| 222 | 227 |
| 228 Texture::FaceInfo::FaceInfo() |
| 229 : num_mip_levels(0) { |
| 230 } |
| 231 |
| 232 Texture::FaceInfo::~FaceInfo() { |
| 233 } |
| 234 |
| 223 Texture::CanRenderCondition Texture::GetCanRenderCondition() const { | 235 Texture::CanRenderCondition Texture::GetCanRenderCondition() const { |
| 224 if (target_ == 0) | 236 if (target_ == 0) |
| 225 return CAN_RENDER_ALWAYS; | 237 return CAN_RENDER_ALWAYS; |
| 226 | 238 |
| 227 if (target_ != GL_TEXTURE_EXTERNAL_OES) { | 239 if (target_ != GL_TEXTURE_EXTERNAL_OES) { |
| 228 if (level_infos_.empty()) { | 240 if (face_infos_.empty()) { |
| 229 return CAN_RENDER_NEVER; | 241 return CAN_RENDER_NEVER; |
| 230 } | 242 } |
| 231 | 243 |
| 232 const Texture::LevelInfo& first_face = level_infos_[0][0]; | 244 const Texture::LevelInfo& first_face = face_infos_[0].level_infos[0]; |
| 233 if (first_face.width == 0 || | 245 if (first_face.width == 0 || |
| 234 first_face.height == 0 || | 246 first_face.height == 0 || |
| 235 first_face.depth == 0) { | 247 first_face.depth == 0) { |
| 236 return CAN_RENDER_NEVER; | 248 return CAN_RENDER_NEVER; |
| 237 } | 249 } |
| 238 } | 250 } |
| 239 | 251 |
| 240 bool needs_mips = NeedsMips(); | 252 bool needs_mips = NeedsMips(); |
| 241 if (needs_mips) { | 253 if (needs_mips) { |
| 242 if (!texture_complete()) | 254 if (!texture_complete()) |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 274 void Texture::AddToSignature( | 286 void Texture::AddToSignature( |
| 275 const FeatureInfo* feature_info, | 287 const FeatureInfo* feature_info, |
| 276 GLenum target, | 288 GLenum target, |
| 277 GLint level, | 289 GLint level, |
| 278 std::string* signature) const { | 290 std::string* signature) const { |
| 279 DCHECK(feature_info); | 291 DCHECK(feature_info); |
| 280 DCHECK(signature); | 292 DCHECK(signature); |
| 281 DCHECK_GE(level, 0); | 293 DCHECK_GE(level, 0); |
| 282 size_t face_index = GLES2Util::GLTargetToFaceIndex(target); | 294 size_t face_index = GLES2Util::GLTargetToFaceIndex(target); |
| 283 DCHECK_LT(static_cast<size_t>(face_index), | 295 DCHECK_LT(static_cast<size_t>(face_index), |
| 284 level_infos_.size()); | 296 face_infos_.size()); |
| 285 DCHECK_LT(static_cast<size_t>(level), | 297 DCHECK_LT(static_cast<size_t>(level), |
| 286 level_infos_[face_index].size()); | 298 face_infos_[face_index].level_infos.size()); |
| 287 | 299 |
| 288 const Texture::LevelInfo& info = | 300 const Texture::LevelInfo& info = |
| 289 level_infos_[face_index][level]; | 301 face_infos_[face_index].level_infos[level]; |
| 290 | 302 |
| 291 TextureSignature signature_data(target, | 303 TextureSignature signature_data(target, |
| 292 level, | 304 level, |
| 293 min_filter_, | 305 min_filter_, |
| 294 mag_filter_, | 306 mag_filter_, |
| 295 wrap_s_, | 307 wrap_s_, |
| 296 wrap_t_, | 308 wrap_t_, |
| 297 usage_, | 309 usage_, |
| 298 info.internal_format, | 310 info.internal_format, |
| 299 info.width, | 311 info.width, |
| (...skipping 15 matching lines...) Expand all Loading... |
| 315 void Texture::SetMailboxManager(MailboxManager* mailbox_manager) { | 327 void Texture::SetMailboxManager(MailboxManager* mailbox_manager) { |
| 316 DCHECK(!mailbox_manager_ || mailbox_manager_ == mailbox_manager); | 328 DCHECK(!mailbox_manager_ || mailbox_manager_ == mailbox_manager); |
| 317 mailbox_manager_ = mailbox_manager; | 329 mailbox_manager_ = mailbox_manager; |
| 318 } | 330 } |
| 319 | 331 |
| 320 bool Texture::MarkMipmapsGenerated( | 332 bool Texture::MarkMipmapsGenerated( |
| 321 const FeatureInfo* feature_info) { | 333 const FeatureInfo* feature_info) { |
| 322 if (!CanGenerateMipmaps(feature_info)) { | 334 if (!CanGenerateMipmaps(feature_info)) { |
| 323 return false; | 335 return false; |
| 324 } | 336 } |
| 325 for (size_t ii = 0; ii < level_infos_.size(); ++ii) { | 337 for (size_t ii = 0; ii < face_infos_.size(); ++ii) { |
| 326 const Texture::LevelInfo& info1 = level_infos_[ii][0]; | 338 const Texture::FaceInfo& face_info = face_infos_[ii]; |
| 327 GLsizei width = info1.width; | 339 const Texture::LevelInfo& level0_info = face_info.level_infos[0]; |
| 328 GLsizei height = info1.height; | 340 GLsizei width = level0_info.width; |
| 329 GLsizei depth = info1.depth; | 341 GLsizei height = level0_info.height; |
| 342 GLsizei depth = level0_info.depth; |
| 330 GLenum target = target_ == GL_TEXTURE_2D ? GL_TEXTURE_2D : | 343 GLenum target = target_ == GL_TEXTURE_2D ? GL_TEXTURE_2D : |
| 331 GLES2Util::IndexToGLFaceTarget(ii); | 344 GLES2Util::IndexToGLFaceTarget(ii); |
| 332 int num_mips = | 345 |
| 333 TextureManager::ComputeMipMapCount(target_, width, height, depth); | 346 const GLsizei num_mips = face_info.num_mip_levels; |
| 334 for (int level = 1; level < num_mips; ++level) { | 347 for (GLsizei level = 1; level < num_mips; ++level) { |
| 335 width = std::max(1, width >> 1); | 348 width = std::max(1, width >> 1); |
| 336 height = std::max(1, height >> 1); | 349 height = std::max(1, height >> 1); |
| 337 depth = std::max(1, depth >> 1); | 350 depth = std::max(1, depth >> 1); |
| 338 SetLevelInfo(feature_info, | 351 SetLevelInfo(feature_info, |
| 339 target, | 352 target, |
| 340 level, | 353 level, |
| 341 info1.internal_format, | 354 level0_info.internal_format, |
| 342 width, | 355 width, |
| 343 height, | 356 height, |
| 344 depth, | 357 depth, |
| 345 info1.border, | 358 level0_info.border, |
| 346 info1.format, | 359 level0_info.format, |
| 347 info1.type, | 360 level0_info.type, |
| 348 true); | 361 true); |
| 349 } | 362 } |
| 350 } | 363 } |
| 351 | 364 |
| 352 return true; | 365 return true; |
| 353 } | 366 } |
| 354 | 367 |
| 355 void Texture::SetTarget( | 368 void Texture::SetTarget( |
| 356 const FeatureInfo* feature_info, GLenum target, GLint max_levels) { | 369 const FeatureInfo* feature_info, GLenum target, GLint max_levels) { |
| 357 DCHECK_EQ(0u, target_); // you can only set this once. | 370 DCHECK_EQ(0u, target_); // you can only set this once. |
| 358 target_ = target; | 371 target_ = target; |
| 359 size_t num_faces = (target == GL_TEXTURE_CUBE_MAP) ? 6 : 1; | 372 size_t num_faces = (target == GL_TEXTURE_CUBE_MAP) ? 6 : 1; |
| 360 level_infos_.resize(num_faces); | 373 face_infos_.resize(num_faces); |
| 361 for (size_t ii = 0; ii < num_faces; ++ii) { | 374 for (size_t ii = 0; ii < num_faces; ++ii) { |
| 362 level_infos_[ii].resize(max_levels); | 375 face_infos_[ii].level_infos.resize(max_levels); |
| 363 } | 376 } |
| 364 | 377 |
| 365 if (target == GL_TEXTURE_EXTERNAL_OES || target == GL_TEXTURE_RECTANGLE_ARB) { | 378 if (target == GL_TEXTURE_EXTERNAL_OES || target == GL_TEXTURE_RECTANGLE_ARB) { |
| 366 min_filter_ = GL_LINEAR; | 379 min_filter_ = GL_LINEAR; |
| 367 wrap_s_ = wrap_t_ = GL_CLAMP_TO_EDGE; | 380 wrap_s_ = wrap_t_ = GL_CLAMP_TO_EDGE; |
| 368 } | 381 } |
| 369 | 382 |
| 370 if (target == GL_TEXTURE_EXTERNAL_OES) { | 383 if (target == GL_TEXTURE_EXTERNAL_OES) { |
| 371 immutable_ = true; | 384 immutable_ = true; |
| 372 } | 385 } |
| 373 Update(feature_info); | 386 Update(feature_info); |
| 374 UpdateCanRenderCondition(); | 387 UpdateCanRenderCondition(); |
| 375 } | 388 } |
| 376 | 389 |
| 377 bool Texture::CanGenerateMipmaps( | 390 bool Texture::CanGenerateMipmaps( |
| 378 const FeatureInfo* feature_info) const { | 391 const FeatureInfo* feature_info) const { |
| 379 if ((npot() && !feature_info->feature_flags().npot_ok) || | 392 if ((npot() && !feature_info->feature_flags().npot_ok) || |
| 380 level_infos_.empty() || | 393 face_infos_.empty() || |
| 381 target_ == GL_TEXTURE_EXTERNAL_OES || | 394 target_ == GL_TEXTURE_EXTERNAL_OES || |
| 382 target_ == GL_TEXTURE_RECTANGLE_ARB) { | 395 target_ == GL_TEXTURE_RECTANGLE_ARB) { |
| 383 return false; | 396 return false; |
| 384 } | 397 } |
| 385 | 398 |
| 386 // Can't generate mips for depth or stencil textures. | 399 // Can't generate mips for depth or stencil textures. |
| 387 const Texture::LevelInfo& first = level_infos_[0][0]; | 400 const Texture::LevelInfo& first = face_infos_[0].level_infos[0]; |
| 388 uint32 channels = GLES2Util::GetChannelsForFormat(first.format); | 401 uint32 channels = GLES2Util::GetChannelsForFormat(first.format); |
| 389 if (channels & (GLES2Util::kDepth | GLES2Util::kStencil)) { | 402 if (channels & (GLES2Util::kDepth | GLES2Util::kStencil)) { |
| 390 return false; | 403 return false; |
| 391 } | 404 } |
| 392 | 405 |
| 393 // TODO(gman): Check internal_format, format and type. | 406 // TODO(gman): Check internal_format, format and type. |
| 394 for (size_t ii = 0; ii < level_infos_.size(); ++ii) { | 407 for (size_t ii = 0; ii < face_infos_.size(); ++ii) { |
| 395 const LevelInfo& info = level_infos_[ii][0]; | 408 const LevelInfo& info = face_infos_[ii].level_infos[0]; |
| 396 if ((info.target == 0) || (info.width != first.width) || | 409 if ((info.target == 0) || (info.width != first.width) || |
| 397 (info.height != first.height) || (info.depth != 1) || | 410 (info.height != first.height) || (info.depth != 1) || |
| 398 (info.format != first.format) || | 411 (info.format != first.format) || |
| 399 (info.internal_format != first.internal_format) || | 412 (info.internal_format != first.internal_format) || |
| 400 (info.type != first.type) || | 413 (info.type != first.type) || |
| 401 feature_info->validators()->compressed_texture_format.IsValid( | 414 feature_info->validators()->compressed_texture_format.IsValid( |
| 402 info.internal_format) || | 415 info.internal_format) || |
| 403 info.image.get()) { | 416 info.image.get()) { |
| 404 return false; | 417 return false; |
| 405 } | 418 } |
| 406 } | 419 } |
| 407 return true; | 420 return true; |
| 408 } | 421 } |
| 409 | 422 |
| 423 bool Texture::TextureIsNPOT(GLsizei width, |
| 424 GLsizei height, |
| 425 GLsizei depth) { |
| 426 return (GLES2Util::IsNPOT(width) || |
| 427 GLES2Util::IsNPOT(height) || |
| 428 GLES2Util::IsNPOT(depth)); |
| 429 } |
| 430 |
| 431 bool Texture::TextureFaceComplete(const Texture::LevelInfo& first_face, |
| 432 size_t face_index, |
| 433 GLenum target, |
| 434 GLenum internal_format, |
| 435 GLsizei width, |
| 436 GLsizei height, |
| 437 GLsizei depth, |
| 438 GLenum format, |
| 439 GLenum type) { |
| 440 bool complete = (target != 0 && depth == 1); |
| 441 if (face_index != 0) { |
| 442 complete &= (width == first_face.width && |
| 443 height == first_face.height && |
| 444 internal_format == first_face.internal_format && |
| 445 format == first_face.format && |
| 446 type == first_face.type); |
| 447 } |
| 448 return complete; |
| 449 } |
| 450 |
| 451 bool Texture::TextureMipComplete(const Texture::LevelInfo& level0_face, |
| 452 GLenum target, |
| 453 GLint level, |
| 454 GLenum internal_format, |
| 455 GLsizei width, |
| 456 GLsizei height, |
| 457 GLsizei depth, |
| 458 GLenum format, |
| 459 GLenum type) { |
| 460 bool complete = (target != 0); |
| 461 if (level != 0) { |
| 462 const GLsizei mip_width = std::max(1, level0_face.width >> level); |
| 463 const GLsizei mip_height = std::max(1, level0_face.height >> level); |
| 464 const GLsizei mip_depth = std::max(1, level0_face.depth >> level); |
| 465 |
| 466 complete &= (width == mip_width && |
| 467 height == mip_height && |
| 468 depth == mip_depth && |
| 469 internal_format == level0_face.internal_format && |
| 470 format == level0_face.format && |
| 471 type == level0_face.type); |
| 472 } |
| 473 return complete; |
| 474 } |
| 475 |
| 410 void Texture::SetLevelCleared(GLenum target, GLint level, bool cleared) { | 476 void Texture::SetLevelCleared(GLenum target, GLint level, bool cleared) { |
| 411 DCHECK_GE(level, 0); | 477 DCHECK_GE(level, 0); |
| 412 size_t face_index = GLES2Util::GLTargetToFaceIndex(target); | 478 size_t face_index = GLES2Util::GLTargetToFaceIndex(target); |
| 413 DCHECK_LT(static_cast<size_t>(face_index), | 479 DCHECK_LT(static_cast<size_t>(face_index), |
| 414 level_infos_.size()); | 480 face_infos_.size()); |
| 415 DCHECK_LT(static_cast<size_t>(level), | 481 DCHECK_LT(static_cast<size_t>(level), |
| 416 level_infos_[face_index].size()); | 482 face_infos_[face_index].level_infos.size()); |
| 417 Texture::LevelInfo& info = | 483 Texture::LevelInfo& info = |
| 418 level_infos_[face_index][level]; | 484 face_infos_[face_index].level_infos[level]; |
| 419 UpdateMipCleared(&info, cleared); | 485 UpdateMipCleared(&info, cleared); |
| 420 UpdateCleared(); | 486 UpdateCleared(); |
| 421 } | 487 } |
| 422 | 488 |
| 423 void Texture::UpdateCleared() { | 489 void Texture::UpdateCleared() { |
| 424 if (level_infos_.empty()) { | 490 if (face_infos_.empty()) { |
| 425 return; | 491 return; |
| 426 } | 492 } |
| 427 | 493 |
| 428 const bool cleared = (num_uncleared_mips_ == 0); | 494 const bool cleared = (num_uncleared_mips_ == 0); |
| 429 | 495 |
| 430 // If texture is uncleared and is attached to a framebuffer, | 496 // If texture is uncleared and is attached to a framebuffer, |
| 431 // that framebuffer must be marked possibly incomplete. | 497 // that framebuffer must be marked possibly incomplete. |
| 432 if (!cleared && IsAttachedToFramebuffer()) { | 498 if (!cleared && IsAttachedToFramebuffer()) { |
| 433 IncAllFramebufferStateChangeCount(); | 499 IncAllFramebufferStateChangeCount(); |
| 434 } | 500 } |
| (...skipping 24 matching lines...) Expand all Loading... |
| 459 CanRenderCondition can_render_condition = GetCanRenderCondition(); | 525 CanRenderCondition can_render_condition = GetCanRenderCondition(); |
| 460 if (can_render_condition_ == can_render_condition) | 526 if (can_render_condition_ == can_render_condition) |
| 461 return; | 527 return; |
| 462 for (RefSet::iterator it = refs_.begin(); it != refs_.end(); ++it) | 528 for (RefSet::iterator it = refs_.begin(); it != refs_.end(); ++it) |
| 463 (*it)->manager()->UpdateCanRenderCondition(can_render_condition_, | 529 (*it)->manager()->UpdateCanRenderCondition(can_render_condition_, |
| 464 can_render_condition); | 530 can_render_condition); |
| 465 can_render_condition_ = can_render_condition; | 531 can_render_condition_ = can_render_condition; |
| 466 } | 532 } |
| 467 | 533 |
| 468 void Texture::UpdateHasImages() { | 534 void Texture::UpdateHasImages() { |
| 469 if (level_infos_.empty()) | 535 if (face_infos_.empty()) |
| 470 return; | 536 return; |
| 471 | 537 |
| 472 bool has_images = false; | 538 bool has_images = false; |
| 473 for (size_t ii = 0; ii < level_infos_.size(); ++ii) { | 539 for (size_t ii = 0; ii < face_infos_.size(); ++ii) { |
| 474 for (size_t jj = 0; jj < level_infos_[ii].size(); ++jj) { | 540 for (size_t jj = 0; jj < face_infos_[ii].level_infos.size(); ++jj) { |
| 475 const Texture::LevelInfo& info = level_infos_[ii][jj]; | 541 const Texture::LevelInfo& info = face_infos_[ii].level_infos[jj]; |
| 476 if (info.image.get() != NULL) { | 542 if (info.image.get() != NULL) { |
| 477 has_images = true; | 543 has_images = true; |
| 478 break; | 544 break; |
| 479 } | 545 } |
| 480 } | 546 } |
| 481 } | 547 } |
| 482 | 548 |
| 483 if (has_images_ == has_images) | 549 if (has_images_ == has_images) |
| 484 return; | 550 return; |
| 485 has_images_ = has_images; | 551 has_images_ = has_images; |
| (...skipping 15 matching lines...) Expand all Loading... |
| 501 GLsizei width, | 567 GLsizei width, |
| 502 GLsizei height, | 568 GLsizei height, |
| 503 GLsizei depth, | 569 GLsizei depth, |
| 504 GLint border, | 570 GLint border, |
| 505 GLenum format, | 571 GLenum format, |
| 506 GLenum type, | 572 GLenum type, |
| 507 bool cleared) { | 573 bool cleared) { |
| 508 DCHECK_GE(level, 0); | 574 DCHECK_GE(level, 0); |
| 509 size_t face_index = GLES2Util::GLTargetToFaceIndex(target); | 575 size_t face_index = GLES2Util::GLTargetToFaceIndex(target); |
| 510 DCHECK_LT(static_cast<size_t>(face_index), | 576 DCHECK_LT(static_cast<size_t>(face_index), |
| 511 level_infos_.size()); | 577 face_infos_.size()); |
| 512 DCHECK_LT(static_cast<size_t>(level), | 578 DCHECK_LT(static_cast<size_t>(level), |
| 513 level_infos_[face_index].size()); | 579 face_infos_[face_index].level_infos.size()); |
| 514 DCHECK_GE(width, 0); | 580 DCHECK_GE(width, 0); |
| 515 DCHECK_GE(height, 0); | 581 DCHECK_GE(height, 0); |
| 516 DCHECK_GE(depth, 0); | 582 DCHECK_GE(depth, 0); |
| 517 Texture::LevelInfo& info = | 583 Texture::LevelInfo& info = |
| 518 level_infos_[face_index][level]; | 584 face_infos_[face_index].level_infos[level]; |
| 585 |
| 586 // Update counters only if any attributes have changed. Counters are |
| 587 // comparisons between the old and new values so it must be done before any |
| 588 // assignment has been done to the LevelInfo. |
| 589 if (info.target != target || |
| 590 info.internal_format != internal_format || |
| 591 info.width != width || |
| 592 info.height != height || |
| 593 info.depth != depth || |
| 594 info.format != format || |
| 595 info.type != type) { |
| 596 if (level == 0) { |
| 597 // Calculate the mip level count. |
| 598 face_infos_[face_index].num_mip_levels = |
| 599 TextureManager::ComputeMipMapCount(target_, width, height, depth); |
| 600 |
| 601 // Update NPOT face count for the first level. |
| 602 bool prev_npot = TextureIsNPOT(info.width, info.height, info.depth); |
| 603 bool now_npot = TextureIsNPOT(width, height, depth); |
| 604 if (prev_npot != now_npot) |
| 605 num_npot_faces_ += now_npot ? 1 : -1; |
| 606 |
| 607 // Signify that level 0 has been changed, so they need to be reverified. |
| 608 texture_level0_dirty_ = true; |
| 609 } |
| 610 |
| 611 // Signify that at least one of the mips has changed. |
| 612 texture_mips_dirty_ = true; |
| 613 } |
| 614 |
| 519 info.target = target; | 615 info.target = target; |
| 520 info.level = level; | 616 info.level = level; |
| 521 info.internal_format = internal_format; | 617 info.internal_format = internal_format; |
| 522 info.width = width; | 618 info.width = width; |
| 523 info.height = height; | 619 info.height = height; |
| 524 info.depth = depth; | 620 info.depth = depth; |
| 525 info.border = border; | 621 info.border = border; |
| 526 info.format = format; | 622 info.format = format; |
| 527 info.type = type; | 623 info.type = type; |
| 528 info.image = 0; | 624 info.image = 0; |
| (...skipping 18 matching lines...) Expand all Loading... |
| 547 | 643 |
| 548 bool Texture::ValidForTexture( | 644 bool Texture::ValidForTexture( |
| 549 GLint target, | 645 GLint target, |
| 550 GLint level, | 646 GLint level, |
| 551 GLint xoffset, | 647 GLint xoffset, |
| 552 GLint yoffset, | 648 GLint yoffset, |
| 553 GLsizei width, | 649 GLsizei width, |
| 554 GLsizei height, | 650 GLsizei height, |
| 555 GLenum type) const { | 651 GLenum type) const { |
| 556 size_t face_index = GLES2Util::GLTargetToFaceIndex(target); | 652 size_t face_index = GLES2Util::GLTargetToFaceIndex(target); |
| 557 if (level >= 0 && face_index < level_infos_.size() && | 653 if (level >= 0 && face_index < face_infos_.size() && |
| 558 static_cast<size_t>(level) < level_infos_[face_index].size()) { | 654 static_cast<size_t>(level) < face_infos_[face_index].level_infos.size()) { |
| 559 const LevelInfo& info = level_infos_[face_index][level]; | 655 const LevelInfo& info = face_infos_[face_index].level_infos[level]; |
| 560 int32 right; | 656 int32 right; |
| 561 int32 top; | 657 int32 top; |
| 562 return SafeAddInt32(xoffset, width, &right) && | 658 return SafeAddInt32(xoffset, width, &right) && |
| 563 SafeAddInt32(yoffset, height, &top) && | 659 SafeAddInt32(yoffset, height, &top) && |
| 564 xoffset >= 0 && | 660 xoffset >= 0 && |
| 565 yoffset >= 0 && | 661 yoffset >= 0 && |
| 566 right <= info.width && | 662 right <= info.width && |
| 567 top <= info.height && | 663 top <= info.height && |
| 568 type == info.type; | 664 type == info.type; |
| 569 } | 665 } |
| 570 return false; | 666 return false; |
| 571 } | 667 } |
| 572 | 668 |
| 573 bool Texture::GetLevelSize( | 669 bool Texture::GetLevelSize( |
| 574 GLint target, GLint level, GLsizei* width, GLsizei* height) const { | 670 GLint target, GLint level, GLsizei* width, GLsizei* height) const { |
| 575 DCHECK(width); | 671 DCHECK(width); |
| 576 DCHECK(height); | 672 DCHECK(height); |
| 577 size_t face_index = GLES2Util::GLTargetToFaceIndex(target); | 673 size_t face_index = GLES2Util::GLTargetToFaceIndex(target); |
| 578 if (level >= 0 && face_index < level_infos_.size() && | 674 if (level >= 0 && face_index < face_infos_.size() && |
| 579 static_cast<size_t>(level) < level_infos_[face_index].size()) { | 675 static_cast<size_t>(level) < face_infos_[face_index].level_infos.size()) { |
| 580 const LevelInfo& info = level_infos_[face_index][level]; | 676 const LevelInfo& info = face_infos_[face_index].level_infos[level]; |
| 581 if (info.target != 0) { | 677 if (info.target != 0) { |
| 582 *width = info.width; | 678 *width = info.width; |
| 583 *height = info.height; | 679 *height = info.height; |
| 584 return true; | 680 return true; |
| 585 } | 681 } |
| 586 } | 682 } |
| 587 return false; | 683 return false; |
| 588 } | 684 } |
| 589 | 685 |
| 590 bool Texture::GetLevelType( | 686 bool Texture::GetLevelType( |
| 591 GLint target, GLint level, GLenum* type, GLenum* internal_format) const { | 687 GLint target, GLint level, GLenum* type, GLenum* internal_format) const { |
| 592 DCHECK(type); | 688 DCHECK(type); |
| 593 DCHECK(internal_format); | 689 DCHECK(internal_format); |
| 594 size_t face_index = GLES2Util::GLTargetToFaceIndex(target); | 690 size_t face_index = GLES2Util::GLTargetToFaceIndex(target); |
| 595 if (level >= 0 && face_index < level_infos_.size() && | 691 if (level >= 0 && face_index < face_infos_.size() && |
| 596 static_cast<size_t>(level) < level_infos_[face_index].size()) { | 692 static_cast<size_t>(level) < face_infos_[face_index].level_infos.size()) { |
| 597 const LevelInfo& info = level_infos_[face_index][level]; | 693 const LevelInfo& info = face_infos_[face_index].level_infos[level]; |
| 598 if (info.target != 0) { | 694 if (info.target != 0) { |
| 599 *type = info.type; | 695 *type = info.type; |
| 600 *internal_format = info.internal_format; | 696 *internal_format = info.internal_format; |
| 601 return true; | 697 return true; |
| 602 } | 698 } |
| 603 } | 699 } |
| 604 return false; | 700 return false; |
| 605 } | 701 } |
| 606 | 702 |
| 607 GLenum Texture::SetParameteri( | 703 GLenum Texture::SetParameteri( |
| (...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 693 default: | 789 default: |
| 694 NOTREACHED(); | 790 NOTREACHED(); |
| 695 return GL_INVALID_ENUM; | 791 return GL_INVALID_ENUM; |
| 696 } | 792 } |
| 697 return GL_NO_ERROR; | 793 return GL_NO_ERROR; |
| 698 } | 794 } |
| 699 | 795 |
| 700 void Texture::Update(const FeatureInfo* feature_info) { | 796 void Texture::Update(const FeatureInfo* feature_info) { |
| 701 // Update npot status. | 797 // Update npot status. |
| 702 // Assume GL_TEXTURE_EXTERNAL_OES textures are npot, all others | 798 // Assume GL_TEXTURE_EXTERNAL_OES textures are npot, all others |
| 703 npot_ = target_ == GL_TEXTURE_EXTERNAL_OES; | 799 npot_ = (target_ == GL_TEXTURE_EXTERNAL_OES) || (num_npot_faces_ > 0); |
| 704 | 800 |
| 705 if (level_infos_.empty()) { | 801 if (face_infos_.empty()) { |
| 706 texture_complete_ = false; | 802 texture_complete_ = false; |
| 707 cube_complete_ = false; | 803 cube_complete_ = false; |
| 708 return; | 804 return; |
| 709 } | 805 } |
| 710 | 806 |
| 711 // checks that the first mip of any face is npot. | 807 // Update texture_complete and cube_complete status. |
| 712 for (size_t ii = 0; ii < level_infos_.size(); ++ii) { | 808 const Texture::FaceInfo& first_face = face_infos_[0]; |
| 713 const Texture::LevelInfo& info = level_infos_[ii][0]; | 809 const Texture::LevelInfo& first_level = first_face.level_infos[0]; |
| 714 if (GLES2Util::IsNPOT(info.width) || | 810 const GLsizei levels_needed = first_face.num_mip_levels; |
| 715 GLES2Util::IsNPOT(info.height) || | |
| 716 GLES2Util::IsNPOT(info.depth)) { | |
| 717 npot_ = true; | |
| 718 break; | |
| 719 } | |
| 720 } | |
| 721 | 811 |
| 722 // Update texture_complete and cube_complete status. | |
| 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 texture_complete_ = | 812 texture_complete_ = |
| 727 max_level_set_ >= (levels_needed - 1) && max_level_set_ >= 0; | 813 max_level_set_ >= (levels_needed - 1) && max_level_set_ >= 0; |
| 728 cube_complete_ = (level_infos_.size() == 6) && | 814 cube_complete_ = (face_infos_.size() == 6) && |
| 729 (first_face.width == first_face.height); | 815 (first_level.width == first_level.height); |
| 730 | 816 |
| 731 if (first_face.width == 0 || first_face.height == 0) { | 817 if (first_level.width == 0 || first_level.height == 0) { |
| 732 texture_complete_ = false; | 818 texture_complete_ = false; |
| 733 } | 819 } else if (first_level.type == GL_FLOAT && |
| 734 if (first_face.type == GL_FLOAT && | |
| 735 !feature_info->feature_flags().enable_texture_float_linear && | 820 !feature_info->feature_flags().enable_texture_float_linear && |
| 736 (min_filter_ != GL_NEAREST_MIPMAP_NEAREST || | 821 (min_filter_ != GL_NEAREST_MIPMAP_NEAREST || |
| 737 mag_filter_ != GL_NEAREST)) { | 822 mag_filter_ != GL_NEAREST)) { |
| 738 texture_complete_ = false; | 823 texture_complete_ = false; |
| 739 } else if (first_face.type == GL_HALF_FLOAT_OES && | 824 } else if (first_level.type == GL_HALF_FLOAT_OES && |
| 740 !feature_info->feature_flags().enable_texture_half_float_linear && | 825 !feature_info->feature_flags().enable_texture_half_float_linear && |
| 741 (min_filter_ != GL_NEAREST_MIPMAP_NEAREST || | 826 (min_filter_ != GL_NEAREST_MIPMAP_NEAREST || |
| 742 mag_filter_ != GL_NEAREST)) { | 827 mag_filter_ != GL_NEAREST)) { |
| 743 texture_complete_ = false; | 828 texture_complete_ = false; |
| 744 } | 829 } |
| 745 for (size_t ii = 0; | 830 |
| 746 ii < level_infos_.size() && (cube_complete_ || texture_complete_); | 831 if (cube_complete_ && texture_level0_dirty_) { |
| 747 ++ii) { | 832 texture_level0_complete_ = true; |
| 748 const Texture::LevelInfo& level0 = level_infos_[ii][0]; | 833 for (size_t ii = 0; ii < face_infos_.size(); ++ii) { |
| 749 if (level0.target == 0 || | 834 const Texture::LevelInfo& level0 = face_infos_[ii].level_infos[0]; |
| 750 level0.width != first_face.width || | 835 if (!TextureFaceComplete(first_level, |
| 751 level0.height != first_face.height || | 836 ii, |
| 752 level0.depth != 1 || | 837 level0.target, |
| 753 level0.internal_format != first_face.internal_format || | 838 level0.internal_format, |
| 754 level0.format != first_face.format || | 839 level0.width, |
| 755 level0.type != first_face.type) { | 840 level0.height, |
| 756 cube_complete_ = false; | 841 level0.depth, |
| 757 } | 842 level0.format, |
| 758 // Get level0 dimensions | 843 level0.type)) { |
| 759 GLsizei width = level0.width; | 844 texture_level0_complete_ = false; |
| 760 GLsizei height = level0.height; | |
| 761 GLsizei depth = level0.depth; | |
| 762 for (GLint jj = 1; jj < levels_needed; ++jj) { | |
| 763 // compute required size for mip. | |
| 764 width = std::max(1, width >> 1); | |
| 765 height = std::max(1, height >> 1); | |
| 766 depth = std::max(1, depth >> 1); | |
| 767 const Texture::LevelInfo& info = level_infos_[ii][jj]; | |
| 768 if (info.target == 0 || | |
| 769 info.width != width || | |
| 770 info.height != height || | |
| 771 info.depth != depth || | |
| 772 info.internal_format != level0.internal_format || | |
| 773 info.format != level0.format || | |
| 774 info.type != level0.type) { | |
| 775 texture_complete_ = false; | |
| 776 break; | 845 break; |
| 777 } | 846 } |
| 778 } | 847 } |
| 848 texture_level0_dirty_ = false; |
| 779 } | 849 } |
| 850 cube_complete_ &= texture_level0_complete_; |
| 851 |
| 852 if (texture_complete_ && texture_mips_dirty_) { |
| 853 texture_mips_complete_ = true; |
| 854 for (size_t ii = 0; |
| 855 ii < face_infos_.size() && texture_mips_complete_; |
| 856 ++ii) { |
| 857 const Texture::FaceInfo& face_info = face_infos_[ii]; |
| 858 const Texture::LevelInfo& level0 = face_info.level_infos[0]; |
| 859 for (GLsizei jj = 1; jj < levels_needed; ++jj) { |
| 860 const Texture::LevelInfo& level_info = face_infos_[ii].level_infos[jj]; |
| 861 if (!TextureMipComplete(level0, |
| 862 level_info.target, |
| 863 jj, |
| 864 level_info.internal_format, |
| 865 level_info.width, |
| 866 level_info.height, |
| 867 level_info.depth, |
| 868 level_info.format, |
| 869 level_info.type)) { |
| 870 texture_mips_complete_ = false; |
| 871 break; |
| 872 } |
| 873 } |
| 874 } |
| 875 texture_mips_dirty_ = false; |
| 876 } |
| 877 texture_complete_ &= texture_mips_complete_; |
| 780 } | 878 } |
| 781 | 879 |
| 782 bool Texture::ClearRenderableLevels(GLES2Decoder* decoder) { | 880 bool Texture::ClearRenderableLevels(GLES2Decoder* decoder) { |
| 783 DCHECK(decoder); | 881 DCHECK(decoder); |
| 784 if (cleared_) { | 882 if (cleared_) { |
| 785 return true; | 883 return true; |
| 786 } | 884 } |
| 787 | 885 |
| 788 const Texture::LevelInfo& first_face = level_infos_[0][0]; | 886 for (size_t ii = 0; ii < face_infos_.size(); ++ii) { |
| 789 int levels_needed = TextureManager::ComputeMipMapCount( | 887 const Texture::FaceInfo& face_info = face_infos_[ii]; |
| 790 target_, first_face.width, first_face.height, first_face.depth); | 888 for (GLint jj = 0; jj < face_info.num_mip_levels; ++jj) { |
| 791 | 889 const Texture::LevelInfo& info = face_info.level_infos[jj]; |
| 792 for (size_t ii = 0; ii < level_infos_.size(); ++ii) { | |
| 793 for (GLint jj = 0; jj < levels_needed; ++jj) { | |
| 794 Texture::LevelInfo& info = level_infos_[ii][jj]; | |
| 795 if (info.target != 0) { | 890 if (info.target != 0) { |
| 796 if (!ClearLevel(decoder, info.target, jj)) { | 891 if (!ClearLevel(decoder, info.target, jj)) { |
| 797 return false; | 892 return false; |
| 798 } | 893 } |
| 799 } | 894 } |
| 800 } | 895 } |
| 801 } | 896 } |
| 802 UpdateSafeToRenderFrom(true); | 897 UpdateSafeToRenderFrom(true); |
| 803 return true; | 898 return true; |
| 804 } | 899 } |
| 805 | 900 |
| 806 bool Texture::IsLevelCleared(GLenum target, GLint level) const { | 901 bool Texture::IsLevelCleared(GLenum target, GLint level) const { |
| 807 size_t face_index = GLES2Util::GLTargetToFaceIndex(target); | 902 size_t face_index = GLES2Util::GLTargetToFaceIndex(target); |
| 808 if (face_index >= level_infos_.size() || | 903 if (face_index >= face_infos_.size() || |
| 809 level >= static_cast<GLint>(level_infos_[face_index].size())) { | 904 level >= static_cast<GLint>(face_infos_[face_index].level_infos.size())) { |
| 810 return true; | 905 return true; |
| 811 } | 906 } |
| 812 | 907 |
| 813 const Texture::LevelInfo& info = level_infos_[face_index][level]; | 908 const Texture::LevelInfo& info = face_infos_[face_index].level_infos[level]; |
| 814 | 909 |
| 815 return info.cleared; | 910 return info.cleared; |
| 816 } | 911 } |
| 817 | 912 |
| 818 void Texture::InitTextureMaxAnisotropyIfNeeded(GLenum target) { | 913 void Texture::InitTextureMaxAnisotropyIfNeeded(GLenum target) { |
| 819 if (texture_max_anisotropy_initialized_) | 914 if (texture_max_anisotropy_initialized_) |
| 820 return; | 915 return; |
| 821 texture_max_anisotropy_initialized_ = true; | 916 texture_max_anisotropy_initialized_ = true; |
| 822 GLfloat params[] = { 1.0f }; | 917 GLfloat params[] = { 1.0f }; |
| 823 glTexParameterfv(target, GL_TEXTURE_MAX_ANISOTROPY_EXT, params); | 918 glTexParameterfv(target, GL_TEXTURE_MAX_ANISOTROPY_EXT, params); |
| 824 } | 919 } |
| 825 | 920 |
| 826 bool Texture::ClearLevel( | 921 bool Texture::ClearLevel( |
| 827 GLES2Decoder* decoder, GLenum target, GLint level) { | 922 GLES2Decoder* decoder, GLenum target, GLint level) { |
| 828 DCHECK(decoder); | 923 DCHECK(decoder); |
| 829 size_t face_index = GLES2Util::GLTargetToFaceIndex(target); | 924 size_t face_index = GLES2Util::GLTargetToFaceIndex(target); |
| 830 if (face_index >= level_infos_.size() || | 925 if (face_index >= face_infos_.size() || |
| 831 level >= static_cast<GLint>(level_infos_[face_index].size())) { | 926 level >= static_cast<GLint>(face_infos_[face_index].level_infos.size())) { |
| 832 return true; | 927 return true; |
| 833 } | 928 } |
| 834 | 929 |
| 835 Texture::LevelInfo& info = level_infos_[face_index][level]; | 930 Texture::LevelInfo& info = face_infos_[face_index].level_infos[level]; |
| 836 | 931 |
| 837 DCHECK(target == info.target); | 932 DCHECK(target == info.target); |
| 838 | 933 |
| 839 if (info.target == 0 || | 934 if (info.target == 0 || |
| 840 info.cleared || | 935 info.cleared || |
| 841 info.width == 0 || | 936 info.width == 0 || |
| 842 info.height == 0 || | 937 info.height == 0 || |
| 843 info.depth == 0) { | 938 info.depth == 0) { |
| 844 return true; | 939 return true; |
| 845 } | 940 } |
| 846 | 941 |
| 847 // NOTE: It seems kind of gross to call back into the decoder for this | 942 // NOTE: It seems kind of gross to call back into the decoder for this |
| 848 // but only the decoder knows all the state (like unpack_alignment_) that's | 943 // but only the decoder knows all the state (like unpack_alignment_) that's |
| 849 // needed to be able to call GL correctly. | 944 // needed to be able to call GL correctly. |
| 850 bool cleared = decoder->ClearLevel( | 945 bool cleared = decoder->ClearLevel( |
| 851 service_id_, target_, info.target, info.level, info.internal_format, | 946 service_id_, target_, info.target, info.level, info.internal_format, |
| 852 info.format, info.type, info.width, info.height, immutable_); | 947 info.format, info.type, info.width, info.height, immutable_); |
| 853 UpdateMipCleared(&info, cleared); | 948 UpdateMipCleared(&info, cleared); |
| 854 return info.cleared; | 949 return info.cleared; |
| 855 } | 950 } |
| 856 | 951 |
| 857 void Texture::SetLevelImage( | 952 void Texture::SetLevelImage( |
| 858 const FeatureInfo* feature_info, | 953 const FeatureInfo* feature_info, |
| 859 GLenum target, | 954 GLenum target, |
| 860 GLint level, | 955 GLint level, |
| 861 gfx::GLImage* image) { | 956 gfx::GLImage* image) { |
| 862 DCHECK_GE(level, 0); | 957 DCHECK_GE(level, 0); |
| 863 size_t face_index = GLES2Util::GLTargetToFaceIndex(target); | 958 size_t face_index = GLES2Util::GLTargetToFaceIndex(target); |
| 864 DCHECK_LT(static_cast<size_t>(face_index), | 959 DCHECK_LT(static_cast<size_t>(face_index), |
| 865 level_infos_.size()); | 960 face_infos_.size()); |
| 866 DCHECK_LT(static_cast<size_t>(level), | 961 DCHECK_LT(static_cast<size_t>(level), |
| 867 level_infos_[face_index].size()); | 962 face_infos_[face_index].level_infos.size()); |
| 868 Texture::LevelInfo& info = | 963 Texture::LevelInfo& info = |
| 869 level_infos_[face_index][level]; | 964 face_infos_[face_index].level_infos[level]; |
| 870 DCHECK_EQ(info.target, target); | 965 DCHECK_EQ(info.target, target); |
| 871 DCHECK_EQ(info.level, level); | 966 DCHECK_EQ(info.level, level); |
| 872 info.image = image; | 967 info.image = image; |
| 873 UpdateCanRenderCondition(); | 968 UpdateCanRenderCondition(); |
| 874 UpdateHasImages(); | 969 UpdateHasImages(); |
| 875 } | 970 } |
| 876 | 971 |
| 877 gfx::GLImage* Texture::GetLevelImage(GLint target, GLint level) const { | 972 gfx::GLImage* Texture::GetLevelImage(GLint target, GLint level) const { |
| 878 if (target != GL_TEXTURE_2D && target != GL_TEXTURE_EXTERNAL_OES && | 973 if (target != GL_TEXTURE_2D && target != GL_TEXTURE_EXTERNAL_OES && |
| 879 target != GL_TEXTURE_RECTANGLE_ARB) { | 974 target != GL_TEXTURE_RECTANGLE_ARB) { |
| 880 return NULL; | 975 return NULL; |
| 881 } | 976 } |
| 882 | 977 |
| 883 size_t face_index = GLES2Util::GLTargetToFaceIndex(target); | 978 size_t face_index = GLES2Util::GLTargetToFaceIndex(target); |
| 884 if (level >= 0 && face_index < level_infos_.size() && | 979 if (level >= 0 && face_index < face_infos_.size() && |
| 885 static_cast<size_t>(level) < level_infos_[face_index].size()) { | 980 static_cast<size_t>(level) < face_infos_[face_index].level_infos.size()) { |
| 886 const LevelInfo& info = level_infos_[face_index][level]; | 981 const LevelInfo& info = face_infos_[face_index].level_infos[level]; |
| 887 if (info.target != 0) { | 982 if (info.target != 0) { |
| 888 return info.image.get(); | 983 return info.image.get(); |
| 889 } | 984 } |
| 890 } | 985 } |
| 891 return NULL; | 986 return NULL; |
| 892 } | 987 } |
| 893 | 988 |
| 894 void Texture::OnWillModifyPixels() { | 989 void Texture::OnWillModifyPixels() { |
| 895 gfx::GLImage* image = GetLevelImage(target(), 0); | 990 gfx::GLImage* image = GetLevelImage(target(), 0); |
| 896 if (image) | 991 if (image) |
| (...skipping 715 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1612 } | 1707 } |
| 1613 | 1708 |
| 1614 ScopedTextureUploadTimer::~ScopedTextureUploadTimer() { | 1709 ScopedTextureUploadTimer::~ScopedTextureUploadTimer() { |
| 1615 texture_state_->texture_upload_count++; | 1710 texture_state_->texture_upload_count++; |
| 1616 texture_state_->total_texture_upload_time += | 1711 texture_state_->total_texture_upload_time += |
| 1617 base::TimeTicks::HighResNow() - begin_time_; | 1712 base::TimeTicks::HighResNow() - begin_time_; |
| 1618 } | 1713 } |
| 1619 | 1714 |
| 1620 } // namespace gles2 | 1715 } // namespace gles2 |
| 1621 } // namespace gpu | 1716 } // namespace gpu |
| OLD | NEW |