1 // Copyright 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 "cc/resources/resource_provider.h" 6 7 #include <algorithm> 8 #include <limits> 9 10 #include "base/containers/hash_tables.h" 11 #include "base/debug/alias.h" 12 #include "base/stl_util.h" 13 #include "base/strings/string_split.h" 14 #include "base/strings/string_util.h" 15 #include "cc/output/gl_renderer.h" // For the GLC() macro. 16 #include "cc/resources/platform_color.h" 17 #include "cc/resources/transferable_resource.h" 18 #include "cc/scheduler/texture_uploader.h" 19 #include "gpu/GLES2/gl2extchromium.h" 20 #include "third_party/WebKit/public/platform/WebGraphicsContext3D.h" 21 #include "third_party/khronos/GLES2/gl2.h" 22 #include "third_party/khronos/GLES2/gl2ext.h" 23 #include "ui/gfx/rect.h" 24 #include "ui/gfx/vector2d.h" 25 26 using WebKit::WebGraphicsContext3D; 27 28 namespace cc { 29 30 namespace { 31 32 GLenum TextureToStorageFormat(GLenum texture_format) { 33 GLenum storage_format = GL_RGBA8_OES; 34 switch (texture_format) { 35 case GL_RGBA: 36 break; 37 case GL_BGRA_EXT: 38 storage_format = GL_BGRA8_EXT; 39 break; 40 default: 41 NOTREACHED(); 42 break; 43 } 44 45 return storage_format; 46 } 47 48 bool IsTextureFormatSupportedForStorage(GLenum format) { 49 return (format == GL_RGBA || format == GL_BGRA_EXT); 50 } 51 52 unsigned CreateTextureId(WebGraphicsContext3D* context3d) { 53 unsigned texture_id = 0; 54 GLC(context3d, texture_id = context3d->createTexture()); 55 GLC(context3d, context3d->bindTexture(GL_TEXTURE_2D, texture_id)); 56 GLC(context3d, context3d->texParameteri( 57 GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR)); 58 GLC(context3d, context3d->texParameteri( 59 GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR)); 60 GLC(context3d, context3d->texParameteri( 61 GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE)); 62 GLC(context3d, context3d->texParameteri( 63 GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE)); 64 return texture_id; 65 } 66 67 } // namespace 68 69 ResourceProvider::Resource::Resource() 70 : gl_id(0), 71 gl_pixel_buffer_id(0), 72 gl_upload_query_id(0), 73 pixels(NULL), 74 pixel_buffer(NULL), 75 lock_for_read_count(0), 76 locked_for_write(false), 77 external(false), 78 exported(false), 79 marked_for_deletion(false), 80 pending_set_pixels(false), 81 set_pixels_completion_forced(false), 82 allocated(false), 83 enable_read_lock_fences(false), 84 read_lock_fence(NULL), 85 size(), 86 format(0), 87 filter(0), 88 image_id(0), 89 texture_pool(0), 90 hint(TextureUsageAny), 91 type(static_cast<ResourceType>(0)) {} 92 93 ResourceProvider::Resource::~Resource() {} 94 95 ResourceProvider::Resource::Resource( 96 unsigned texture_id, 97 gfx::Size size, 98 GLenum format, 99 GLenum filter, 100 GLenum texture_pool, 101 TextureUsageHint hint) 102 : gl_id(texture_id), 103 gl_pixel_buffer_id(0), 104 gl_upload_query_id(0), 105 pixels(NULL), 106 pixel_buffer(NULL), 107 lock_for_read_count(0), 108 locked_for_write(false), 109 external(false), 110 exported(false), 111 marked_for_deletion(false), 112 pending_set_pixels(false), 113 set_pixels_completion_forced(false), 114 allocated(false), 115 enable_read_lock_fences(false), 116 read_lock_fence(NULL), 117 size(size), 118 format(format), 119 filter(filter), 120 image_id(0), 121 texture_pool(texture_pool), 122 hint(hint), 123 type(GLTexture) {} 124 125 ResourceProvider::Resource::Resource( 126 uint8_t* pixels, gfx::Size size, GLenum format, GLenum filter) 127 : gl_id(0), 128 gl_pixel_buffer_id(0), 129 gl_upload_query_id(0), 130 pixels(pixels), 131 pixel_buffer(NULL), 132 lock_for_read_count(0), 133 locked_for_write(false), 134 external(false), 135 exported(false), 136 marked_for_deletion(false), 137 pending_set_pixels(false), 138 set_pixels_completion_forced(false), 139 allocated(false), 140 enable_read_lock_fences(false), 141 read_lock_fence(NULL), 142 size(size), 143 format(format), 144 filter(filter), 145 image_id(0), 146 texture_pool(0), 147 hint(TextureUsageAny), 148 type(Bitmap) {} 149 150 ResourceProvider::Child::Child() {} 151 152 ResourceProvider::Child::~Child() {} 153 154 scoped_ptr<ResourceProvider> ResourceProvider::Create( 155 OutputSurface* output_surface, 156 int highp_threshold_min) { 157 scoped_ptr<ResourceProvider> resource_provider( 158 new ResourceProvider(output_surface, highp_threshold_min)); 159 160 bool success = false; 161 if (output_surface->context3d()) { 162 success = resource_provider->InitializeGL(); 163 } else { 164 resource_provider->InitializeSoftware(); 165 success = true; 166 } 167 168 if (!success) 169 return scoped_ptr<ResourceProvider>(); 170 171 DCHECK_NE(InvalidType, resource_provider->default_resource_type()); 172 return resource_provider.Pass(); 173 } 174 175 ResourceProvider::~ResourceProvider() { 176 while (!resources_.empty()) 177 DeleteResourceInternal(resources_.begin(), ForShutdown); 178 179 CleanUpGLIfNeeded(); 180 } 181 182 WebGraphicsContext3D* ResourceProvider::GraphicsContext3D() { 183 DCHECK(thread_checker_.CalledOnValidThread()); 184 return output_surface_->context3d(); 185 } 186 187 bool ResourceProvider::InUseByConsumer(ResourceId id) { 188 DCHECK(thread_checker_.CalledOnValidThread()); 189 ResourceMap::iterator it = resources_.find(id); 190 CHECK(it != resources_.end()); 191 Resource* resource = &it->second; 192 return !!resource->lock_for_read_count || resource->exported; 193 } 194 195 ResourceProvider::ResourceId ResourceProvider::CreateResource( 196 gfx::Size size, GLenum format, TextureUsageHint hint) { 197 DCHECK(!size.IsEmpty()); 198 switch (default_resource_type_) { 199 case GLTexture: 200 return CreateGLTexture( 201 size, format, GL_TEXTURE_POOL_UNMANAGED_CHROMIUM, hint); 202 case Bitmap: 203 DCHECK(format == GL_RGBA); 204 return CreateBitmap(size); 205 case InvalidType: 206 break; 207 } 208 209 LOG(FATAL) << "Invalid default resource type."; 210 return 0; 211 } 212 213 ResourceProvider::ResourceId ResourceProvider::CreateManagedResource( 214 gfx::Size size, GLenum format, TextureUsageHint hint) { 215 DCHECK(!size.IsEmpty()); 216 switch (default_resource_type_) { 217 case GLTexture: 218 return CreateGLTexture( 219 size, format, GL_TEXTURE_POOL_MANAGED_CHROMIUM, hint); 220 case Bitmap: 221 DCHECK(format == GL_RGBA); 222 return CreateBitmap(size); 223 case InvalidType: 224 break; 225 } 226 227 LOG(FATAL) << "Invalid default resource type."; 228 return 0; 229 } 230 231 ResourceProvider::ResourceId ResourceProvider::CreateGLTexture( 232 gfx::Size size, GLenum format, GLenum texture_pool, TextureUsageHint hint) { 233 DCHECK_LE(size.width(), max_texture_size_); 234 DCHECK_LE(size.height(), max_texture_size_); 235 DCHECK(thread_checker_.CalledOnValidThread()); 236 237 ResourceId id = next_id_++; 238 Resource resource(0, size, format, GL_LINEAR, texture_pool, hint); 239 resource.allocated = false; 240 resources_[id] = resource; 241 return id; 242 } 243 244 ResourceProvider::ResourceId ResourceProvider::CreateBitmap(gfx::Size size) { 245 DCHECK(thread_checker_.CalledOnValidThread()); 246 247 uint8_t* pixels = new uint8_t[4 * size.GetArea()]; 248 249 ResourceId id = next_id_++; 250 Resource resource(pixels, size, GL_RGBA, GL_LINEAR); 251 resource.allocated = true; 252 resources_[id] = resource; 253 return id; 254 } 255 256 ResourceProvider::ResourceId 257 ResourceProvider::CreateResourceFromExternalTexture( 258 unsigned texture_target, 259 unsigned texture_id) { 260 DCHECK(thread_checker_.CalledOnValidThread()); 261 262 WebGraphicsContext3D* context3d = output_surface_->context3d(); 263 DCHECK(context3d); 264 GLC(context3d, context3d->bindTexture(texture_target, texture_id)); 265 GLC(context3d, context3d->texParameteri( 266 texture_target, GL_TEXTURE_MIN_FILTER, GL_LINEAR)); 267 GLC(context3d, context3d->texParameteri( 268 texture_target, GL_TEXTURE_MAG_FILTER, GL_LINEAR)); 269 GLC(context3d, context3d->texParameteri( 270 texture_target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE)); 271 GLC(context3d, context3d->texParameteri( 272 texture_target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE)); 273 274 ResourceId id = next_id_++; 275 Resource resource(texture_id, gfx::Size(), 0, GL_LINEAR, 0, TextureUsageAny); 276 resource.external = true; 277 resource.allocated = true; 278 resources_[id] = resource; 279 return id; 280 } 281 282 ResourceProvider::ResourceId ResourceProvider::CreateResourceFromTextureMailbox( 283 const TextureMailbox& mailbox) { 284 DCHECK(thread_checker_.CalledOnValidThread()); 285 // Just store the information. Mailbox will be consumed in LockForRead(). 286 ResourceId id = next_id_++; 287 DCHECK(mailbox.IsValid()); 288 Resource& resource = resources_[id]; 289 if (mailbox.IsTexture()) { 290 resource = Resource(0, gfx::Size(), 0, GL_LINEAR, 0, TextureUsageAny); 291 } else { 292 DCHECK(mailbox.IsSharedMemory()); 293 base::SharedMemory* shared_memory = mailbox.shared_memory(); 294 DCHECK(shared_memory->memory()); 295 uint8_t* pixels = reinterpret_cast<uint8_t*>(shared_memory->memory()); 296 resource = Resource(pixels, mailbox.shared_memory_size(), 297 GL_RGBA, GL_LINEAR); 298 } 299 resource.external = true; 300 resource.allocated = true; 301 resource.mailbox = mailbox; 302 return id; 303 } 304 305 void ResourceProvider::DeleteResource(ResourceId id) { 306 DCHECK(thread_checker_.CalledOnValidThread()); 307 ResourceMap::iterator it = resources_.find(id); 308 CHECK(it != resources_.end()); 309 Resource* resource = &it->second; 310 DCHECK(!resource->lock_for_read_count); 311 DCHECK(!resource->marked_for_deletion); 312 DCHECK(resource->pending_set_pixels || !resource->locked_for_write); 313 314 if (resource->exported) { 315 resource->marked_for_deletion = true; 316 return; 317 } else { 318 DeleteResourceInternal(it, Normal); 319 } 320 } 321 322 void ResourceProvider::DeleteResourceInternal(ResourceMap::iterator it, 323 DeleteStyle style) { 324 Resource* resource = &it->second; 325 bool lost_resource = lost_output_surface_; 326 327 DCHECK(!resource->exported || style != Normal); 328 if (style == ForShutdown && resource->exported) 329 lost_resource = true; 330 331 if (resource->image_id) { 332 WebGraphicsContext3D* context3d = output_surface_->context3d(); 333 DCHECK(context3d); 334 GLC(context3d, context3d->destroyImageCHROMIUM(resource->image_id)); 335 } 336 337 if (resource->gl_id && !resource->external) { 338 WebGraphicsContext3D* context3d = output_surface_->context3d(); 339 DCHECK(context3d); 340 GLC(context3d, context3d->deleteTexture(resource->gl_id)); 341 } 342 if (resource->gl_upload_query_id) { 343 WebGraphicsContext3D* context3d = output_surface_->context3d(); 344 DCHECK(context3d); 345 GLC(context3d, context3d->deleteQueryEXT(resource->gl_upload_query_id)); 346 } 347 if (resource->gl_pixel_buffer_id) { 348 WebGraphicsContext3D* context3d = output_surface_->context3d(); 349 DCHECK(context3d); 350 GLC(context3d, context3d->deleteBuffer(resource->gl_pixel_buffer_id)); 351 } 352 if (resource->mailbox.IsValid() && resource->external) { 353 unsigned sync_point = resource->mailbox.sync_point(); 354 if (resource->mailbox.IsTexture()) { 355 WebGraphicsContext3D* context3d = output_surface_->context3d(); 356 DCHECK(context3d); 357 if (resource->gl_id) 358 GLC(context3d, context3d->deleteTexture(resource->gl_id)); 359 if (!lost_resource && resource->gl_id) 360 sync_point = context3d->insertSyncPoint(); 361 } else { 362 DCHECK(resource->mailbox.IsSharedMemory()); 363 base::SharedMemory* shared_memory = resource->mailbox.shared_memory(); 364 if (resource->pixels && shared_memory) { 365 DCHECK(shared_memory->memory() == resource->pixels); 366 resource->pixels = NULL; 367 } 368 } 369 resource->mailbox.RunReleaseCallback(sync_point, lost_resource); 370 } 371 if (resource->pixels) 372 delete[] resource->pixels; 373 if (resource->pixel_buffer) 374 delete[] resource->pixel_buffer; 375 376 resources_.erase(it); 377 } 378 379 ResourceProvider::ResourceType ResourceProvider::GetResourceType( 380 ResourceId id) { 381 ResourceMap::iterator it = resources_.find(id); 382 CHECK(it != resources_.end()); 383 Resource* resource = &it->second; 384 return resource->type; 385 } 386 387 void ResourceProvider::SetPixels(ResourceId id, 388 const uint8_t* image, 389 gfx::Rect image_rect, 390 gfx::Rect source_rect, 391 gfx::Vector2d dest_offset) { 392 DCHECK(thread_checker_.CalledOnValidThread()); 393 ResourceMap::iterator it = resources_.find(id); 394 CHECK(it != resources_.end()); 395 Resource* resource = &it->second; 396 DCHECK(!resource->locked_for_write); 397 DCHECK(!resource->lock_for_read_count); 398 DCHECK(!resource->external); 399 DCHECK(!resource->exported); 400 DCHECK(ReadLockFenceHasPassed(resource)); 401 LazyAllocate(resource); 402 403 if (resource->gl_id) { 404 DCHECK(!resource->pending_set_pixels); 405 WebGraphicsContext3D* context3d = output_surface_->context3d(); 406 DCHECK(context3d); 407 DCHECK(texture_uploader_.get()); 408 context3d->bindTexture(GL_TEXTURE_2D, resource->gl_id); 409 texture_uploader_->Upload(image, 410 image_rect, 411 source_rect, 412 dest_offset, 413 resource->format, 414 resource->size); 415 } 416 417 if (resource->pixels) { 418 DCHECK(resource->allocated); 419 DCHECK(resource->format == GL_RGBA); 420 SkBitmap src_full; 421 src_full.setConfig( 422 SkBitmap::kARGB_8888_Config, image_rect.width(), image_rect.height()); 423 src_full.setPixels(const_cast<uint8_t*>(image)); 424 SkBitmap src_subset; 425 SkIRect sk_source_rect = SkIRect::MakeXYWH(source_rect.x(), 426 source_rect.y(), 427 source_rect.width(), 428 source_rect.height()); 429 sk_source_rect.offset(-image_rect.x(), -image_rect.y()); 430 src_full.extractSubset(&src_subset, sk_source_rect); 431 432 ScopedWriteLockSoftware lock(this, id); 433 SkCanvas* dest = lock.sk_canvas(); 434 dest->writePixels(src_subset, dest_offset.x(), dest_offset.y()); 435 } 436 } 437 438 size_t ResourceProvider::NumBlockingUploads() { 439 if (!texture_uploader_) 440 return 0; 441 442 return texture_uploader_->NumBlockingUploads(); 443 } 444 445 void ResourceProvider::MarkPendingUploadsAsNonBlocking() { 446 if (!texture_uploader_) 447 return; 448 449 texture_uploader_->MarkPendingUploadsAsNonBlocking(); 450 } 451 452 double ResourceProvider::EstimatedUploadsPerSecond() { 453 if (!texture_uploader_) 454 return 0.0; 455 456 return texture_uploader_->EstimatedTexturesPerSecond(); 457 } 458 459 void ResourceProvider::FlushUploads() { 460 if (!texture_uploader_) 461 return; 462 463 texture_uploader_->Flush(); 464 } 465 466 void ResourceProvider::ReleaseCachedData() { 467 if (!texture_uploader_) 468 return; 469 470 texture_uploader_->ReleaseCachedQueries(); 471 } 472 473 void ResourceProvider::Flush() { 474 DCHECK(thread_checker_.CalledOnValidThread()); 475 WebGraphicsContext3D* context3d = output_surface_->context3d(); 476 if (context3d) 477 context3d->flush(); 478 } 479 480 void ResourceProvider::Finish() { 481 DCHECK(thread_checker_.CalledOnValidThread()); 482 WebGraphicsContext3D* context3d = output_surface_->context3d(); 483 if (context3d) 484 context3d->finish(); 485 } 486 487 bool ResourceProvider::ShallowFlushIfSupported() { 488 DCHECK(thread_checker_.CalledOnValidThread()); 489 WebGraphicsContext3D* context3d = output_surface_->context3d(); 490 if (!context3d || !use_shallow_flush_) 491 return false; 492 493 context3d->shallowFlushCHROMIUM(); 494 return true; 495 } 496 497 const ResourceProvider::Resource* ResourceProvider::LockForRead(ResourceId id) { 498 DCHECK(thread_checker_.CalledOnValidThread()); 499 ResourceMap::iterator it = resources_.find(id); 500 CHECK(it != resources_.end()); 501 Resource* resource = &it->second; 502 DCHECK(!resource->locked_for_write || 503 resource->set_pixels_completion_forced) << 504 "locked for write: " << resource->locked_for_write << 505 " pixels completion forced: " << resource->set_pixels_completion_forced; 506 DCHECK(!resource->exported); 507 // Uninitialized! Call SetPixels or LockForWrite first. 508 DCHECK(resource->allocated); 509 510 LazyCreate(resource); 511 512 if (resource->external) { 513 if (!resource->gl_id && resource->mailbox.IsTexture()) { 514 WebGraphicsContext3D* context3d = output_surface_->context3d(); 515 DCHECK(context3d); 516 if (resource->mailbox.sync_point()) { 517 GLC(context3d, 518 context3d->waitSyncPoint(resource->mailbox.sync_point())); 519 resource->mailbox.ResetSyncPoint(); 520 } 521 resource->gl_id = context3d->createTexture(); 522 GLC(context3d, context3d->bindTexture( 523 resource->mailbox.target(), resource->gl_id)); 524 GLC(context3d, context3d->consumeTextureCHROMIUM( 525 resource->mailbox.target(), resource->mailbox.data())); 526 } 527 } 528 529 resource->lock_for_read_count++; 530 if (resource->enable_read_lock_fences) 531 resource->read_lock_fence = current_read_lock_fence_; 532 533 return resource; 534 } 535 536 void ResourceProvider::UnlockForRead(ResourceId id) { 537 DCHECK(thread_checker_.CalledOnValidThread()); 538 ResourceMap::iterator it = resources_.find(id); 539 CHECK(it != resources_.end()); 540 Resource* resource = &it->second; 541 DCHECK_GT(resource->lock_for_read_count, 0); 542 DCHECK(!resource->exported); 543 resource->lock_for_read_count--; 544 } 545 546 const ResourceProvider::Resource* ResourceProvider::LockForWrite( 547 ResourceId id) { 548 DCHECK(thread_checker_.CalledOnValidThread()); 549 ResourceMap::iterator it = resources_.find(id); 550 CHECK(it != resources_.end()); 551 Resource* resource = &it->second; 552 DCHECK(!resource->locked_for_write); 553 DCHECK(!resource->lock_for_read_count); 554 DCHECK(!resource->exported); 555 DCHECK(!resource->external); 556 DCHECK(ReadLockFenceHasPassed(resource)); 557 LazyAllocate(resource); 558 559 resource->locked_for_write = true; 560 return resource; 561 } 562 563 bool ResourceProvider::CanLockForWrite(ResourceId id) { 564 DCHECK(thread_checker_.CalledOnValidThread()); 565 ResourceMap::iterator it = resources_.find(id); 566 CHECK(it != resources_.end()); 567 Resource* resource = &it->second; 568 return !resource->locked_for_write && 569 !resource->lock_for_read_count && 570 !resource->exported && 571 !resource->external && 572 ReadLockFenceHasPassed(resource); 573 } 574 575 void ResourceProvider::UnlockForWrite(ResourceId id) { 576 DCHECK(thread_checker_.CalledOnValidThread()); 577 ResourceMap::iterator it = resources_.find(id); 578 CHECK(it != resources_.end()); 579 Resource* resource = &it->second; 580 DCHECK(resource->locked_for_write); 581 DCHECK(!resource->exported); 582 DCHECK(!resource->external); 583 resource->locked_for_write = false; 584 } 585 586 ResourceProvider::ScopedReadLockGL::ScopedReadLockGL( 587 ResourceProvider* resource_provider, 588 ResourceProvider::ResourceId resource_id) 589 : resource_provider_(resource_provider), 590 resource_id_(resource_id), 591 texture_id_(resource_provider->LockForRead(resource_id)->gl_id) { 592 DCHECK(texture_id_); 593 } 594 595 ResourceProvider::ScopedReadLockGL::~ScopedReadLockGL() { 596 resource_provider_->UnlockForRead(resource_id_); 597 } 598 599 ResourceProvider::ScopedSamplerGL::ScopedSamplerGL( 600 ResourceProvider* resource_provider, 601 ResourceProvider::ResourceId resource_id, 602 GLenum target, 603 GLenum filter) 604 : ScopedReadLockGL(resource_provider, resource_id), 605 target_(target), 606 unit_(GL_TEXTURE0) { 607 resource_provider->BindForSampling(resource_id, target, unit_, filter); 608 } 609 610 ResourceProvider::ScopedSamplerGL::ScopedSamplerGL( 611 ResourceProvider* resource_provider, 612 ResourceProvider::ResourceId resource_id, 613 GLenum target, 614 GLenum unit, 615 GLenum filter) 616 : ScopedReadLockGL(resource_provider, resource_id), 617 target_(target), 618 unit_(unit) { 619 resource_provider->BindForSampling(resource_id, target, unit, filter); 620 } 621 622 ResourceProvider::ScopedSamplerGL::~ScopedSamplerGL() { 623 resource_provider_->UnbindForSampling(resource_id_, target_, unit_); 624 } 625 626 ResourceProvider::ScopedWriteLockGL::ScopedWriteLockGL( 627 ResourceProvider* resource_provider, 628 ResourceProvider::ResourceId resource_id) 629 : resource_provider_(resource_provider), 630 resource_id_(resource_id), 631 texture_id_(resource_provider->LockForWrite(resource_id)->gl_id) { 632 DCHECK(texture_id_); 633 } 634 635 ResourceProvider::ScopedWriteLockGL::~ScopedWriteLockGL() { 636 resource_provider_->UnlockForWrite(resource_id_); 637 } 638 639 void ResourceProvider::PopulateSkBitmapWithResource( 640 SkBitmap* sk_bitmap, const Resource* resource) { 641 DCHECK(resource->pixels); 642 DCHECK(resource->format == GL_RGBA); 643 sk_bitmap->setConfig(SkBitmap::kARGB_8888_Config, 644 resource->size.width(), 645 resource->size.height()); 646 sk_bitmap->setPixels(resource->pixels); 647 } 648 649 ResourceProvider::ScopedReadLockSoftware::ScopedReadLockSoftware( 650 ResourceProvider* resource_provider, 651 ResourceProvider::ResourceId resource_id) 652 : resource_provider_(resource_provider), 653 resource_id_(resource_id) { 654 ResourceProvider::PopulateSkBitmapWithResource( 655 &sk_bitmap_, resource_provider->LockForRead(resource_id)); 656 } 657 658 ResourceProvider::ScopedReadLockSoftware::~ScopedReadLockSoftware() { 659 resource_provider_->UnlockForRead(resource_id_); 660 } 661 662 ResourceProvider::ScopedWriteLockSoftware::ScopedWriteLockSoftware( 663 ResourceProvider* resource_provider, 664 ResourceProvider::ResourceId resource_id) 665 : resource_provider_(resource_provider), 666 resource_id_(resource_id) { 667 ResourceProvider::PopulateSkBitmapWithResource( 668 &sk_bitmap_, resource_provider->LockForWrite(resource_id)); 669 sk_canvas_.reset(new SkCanvas(sk_bitmap_)); 670 } 671 672 ResourceProvider::ScopedWriteLockSoftware::~ScopedWriteLockSoftware() { 673 resource_provider_->UnlockForWrite(resource_id_); 674 } 675 676 ResourceProvider::ResourceProvider(OutputSurface* output_surface, 677 int highp_threshold_min) 678 : output_surface_(output_surface), 679 lost_output_surface_(false), 680 highp_threshold_min_(highp_threshold_min), 681 next_id_(1), 682 next_child_(1), 683 default_resource_type_(InvalidType), 684 use_texture_storage_ext_(false), 685 use_texture_usage_hint_(false), 686 use_shallow_flush_(false), 687 max_texture_size_(0), 688 best_texture_format_(0) {} 689 690 void ResourceProvider::InitializeSoftware() { 691 DCHECK(thread_checker_.CalledOnValidThread()); 692 DCHECK_NE(Bitmap, default_resource_type_); 693 694 CleanUpGLIfNeeded(); 695 696 default_resource_type_ = Bitmap; 697 max_texture_size_ = INT_MAX / 2; 698 best_texture_format_ = GL_RGBA; 699 } 700 701 bool ResourceProvider::InitializeGL() { 702 DCHECK(thread_checker_.CalledOnValidThread()); 703 DCHECK(!texture_uploader_); 704 DCHECK_NE(GLTexture, default_resource_type_); 705 706 WebGraphicsContext3D* context3d = output_surface_->context3d(); 707 DCHECK(context3d); 708 709 if (!context3d->makeContextCurrent()) 710 return false; 711 712 default_resource_type_ = GLTexture; 713 714 std::string extensions_string = 715 UTF16ToASCII(context3d->getString(GL_EXTENSIONS)); 716 std::vector<std::string> extensions; 717 base::SplitString(extensions_string, ' ', &extensions); 718 bool use_map_sub = false; 719 bool use_bgra = false; 720 for (size_t i = 0; i < extensions.size(); ++i) { 721 if (extensions[i] == "GL_EXT_texture_storage") 722 use_texture_storage_ext_ = true; 723 else if (extensions[i] == "GL_ANGLE_texture_usage") 724 use_texture_usage_hint_ = true; 725 else if (extensions[i] == "GL_CHROMIUM_map_sub") 726 use_map_sub = true; 727 else if (extensions[i] == "GL_CHROMIUM_shallow_flush") 728 use_shallow_flush_ = true; 729 else if (extensions[i] == "GL_EXT_texture_format_BGRA8888") 730 use_bgra = true; 731 } 732 733 texture_uploader_ = 734 TextureUploader::Create(context3d, use_map_sub, use_shallow_flush_); 735 GLC(context3d, context3d->getIntegerv(GL_MAX_TEXTURE_SIZE, 736 &max_texture_size_)); 737 best_texture_format_ = PlatformColor::BestTextureFormat(use_bgra); 738 739 return true; 740 } 741 742 void ResourceProvider::CleanUpGLIfNeeded() { 743 WebGraphicsContext3D* context3d = output_surface_->context3d(); 744 if (default_resource_type_ != GLTexture) { 745 // We are not in GL mode, but double check before returning. 746 DCHECK(!context3d); 747 DCHECK(!texture_uploader_); 748 return; 749 } 750 751 DCHECK(context3d); 752 context3d->makeContextCurrent(); 753 texture_uploader_.reset(); 754 Finish(); 755 } 756 757 int ResourceProvider::CreateChild() { 758 DCHECK(thread_checker_.CalledOnValidThread()); 759 Child child_info; 760 int child = next_child_++; 761 children_[child] = child_info; 762 return child; 763 } 764 765 void ResourceProvider::DestroyChild(int child_id) { 766 DCHECK(thread_checker_.CalledOnValidThread()); 767 ChildMap::iterator it = children_.find(child_id); 768 DCHECK(it != children_.end()); 769 Child& child = it->second; 770 for (ResourceIdMap::iterator child_it = child.child_to_parent_map.begin(); 771 child_it != child.child_to_parent_map.end(); 772 ++child_it) 773 DeleteResource(child_it->second); 774 children_.erase(it); 775 } 776 777 const ResourceProvider::ResourceIdMap& ResourceProvider::GetChildToParentMap( 778 int child) const { 779 DCHECK(thread_checker_.CalledOnValidThread()); 780 ChildMap::const_iterator it = children_.find(child); 781 DCHECK(it != children_.end()); 782 return it->second.child_to_parent_map; 783 } 784 785 void ResourceProvider::PrepareSendToParent(const ResourceIdArray& resources, 786 TransferableResourceArray* list) { 787 DCHECK(thread_checker_.CalledOnValidThread()); 788 WebGraphicsContext3D* context3d = output_surface_->context3d(); 789 if (!context3d || !context3d->makeContextCurrent()) { 790 // TODO(skaslev): Implement this path for software compositing. 791 return; 792 } 793 bool need_sync_point = false; 794 for (ResourceIdArray::const_iterator it = resources.begin(); 795 it != resources.end(); 796 ++it) { 797 TransferableResource resource; 798 if (TransferResource(context3d, *it, &resource)) { 799 if (!resource.sync_point) 800 need_sync_point = true; 801 resources_.find(*it)->second.exported = true; 802 list->push_back(resource); 803 } 804 } 805 if (need_sync_point) { 806 unsigned int sync_point = context3d->insertSyncPoint(); 807 for (TransferableResourceArray::iterator it = list->begin(); 808 it != list->end(); 809 ++it) { 810 if (!it->sync_point) 811 it->sync_point = sync_point; 812 } 813 } 814 } 815 816 void ResourceProvider::PrepareSendToChild(int child, 817 const ResourceIdArray& resources, 818 TransferableResourceArray* list) { 819 DCHECK(thread_checker_.CalledOnValidThread()); 820 WebGraphicsContext3D* context3d = output_surface_->context3d(); 821 if (!context3d || !context3d->makeContextCurrent()) { 822 // TODO(skaslev): Implement this path for software compositing. 823 return; 824 } 825 Child& child_info = children_.find(child)->second; 826 bool need_sync_point = false; 827 for (ResourceIdArray::const_iterator it = resources.begin(); 828 it != resources.end(); 829 ++it) { 830 TransferableResource resource; 831 if (!TransferResource(context3d, *it, &resource)) 832 NOTREACHED(); 833 if (!resource.sync_point) 834 need_sync_point = true; 835 DCHECK(child_info.parent_to_child_map.find(*it) != 836 child_info.parent_to_child_map.end()); 837 resource.id = child_info.parent_to_child_map[*it]; 838 child_info.parent_to_child_map.erase(*it); 839 child_info.child_to_parent_map.erase(resource.id); 840 list->push_back(resource); 841 DeleteResource(*it); 842 } 843 if (need_sync_point) { 844 unsigned int sync_point = context3d->insertSyncPoint(); 845 for (TransferableResourceArray::iterator it = list->begin(); 846 it != list->end(); 847 ++it) { 848 if (!it->sync_point) 849 it->sync_point = sync_point; 850 } 851 } 852 } 853 854 void ResourceProvider::ReceiveFromChild( 855 int child, const TransferableResourceArray& resources) { 856 DCHECK(thread_checker_.CalledOnValidThread()); 857 WebGraphicsContext3D* context3d = output_surface_->context3d(); 858 if (!context3d || !context3d->makeContextCurrent()) { 859 // TODO(skaslev): Implement this path for software compositing. 860 return; 861 } 862 Child& child_info = children_.find(child)->second; 863 for (TransferableResourceArray::const_iterator it = resources.begin(); 864 it != resources.end(); 865 ++it) { 866 unsigned texture_id; 867 // NOTE: If the parent is a browser and the child a renderer, the parent 868 // is not supposed to have its context wait, because that could induce 869 // deadlocks and/or security issues. The caller is responsible for 870 // waiting asynchronously, and resetting sync_point before calling this. 871 // However if the parent is a renderer (e.g. browser tag), it may be ok 872 // (and is simpler) to wait. 873 if (it->sync_point) 874 GLC(context3d, context3d->waitSyncPoint(it->sync_point)); 875 GLC(context3d, texture_id = context3d->createTexture()); 876 GLC(context3d, context3d->bindTexture(GL_TEXTURE_2D, texture_id)); 877 GLC(context3d, context3d->consumeTextureCHROMIUM(GL_TEXTURE_2D, 878 it->mailbox.name)); 879 ResourceId id = next_id_++; 880 Resource resource( 881 texture_id, it->size, it->format, it->filter, 0, TextureUsageAny); 882 resource.mailbox.SetName(it->mailbox); 883 // Don't allocate a texture for a child. 884 resource.allocated = true; 885 resources_[id] = resource; 886 child_info.parent_to_child_map[id] = it->id; 887 child_info.child_to_parent_map[it->id] = id; 888 } 889 } 890 891 void ResourceProvider::ReceiveFromParent( 892 const TransferableResourceArray& resources) { 893 DCHECK(thread_checker_.CalledOnValidThread()); 894 WebGraphicsContext3D* context3d = output_surface_->context3d(); 895 if (!context3d || !context3d->makeContextCurrent()) { 896 // TODO(skaslev): Implement this path for software compositing. 897 return; 898 } 899 for (TransferableResourceArray::const_iterator it = resources.begin(); 900 it != resources.end(); 901 ++it) { 902 ResourceMap::iterator map_iterator = resources_.find(it->id); 903 DCHECK(map_iterator != resources_.end()); 904 Resource* resource = &map_iterator->second; 905 DCHECK(resource->exported); 906 resource->exported = false; 907 resource->filter = it->filter; 908 DCHECK(resource->mailbox.ContainsMailbox(it->mailbox)); 909 if (resource->gl_id) { 910 if (it->sync_point) 911 GLC(context3d, context3d->waitSyncPoint(it->sync_point)); 912 } else { 913 resource->mailbox = TextureMailbox(resource->mailbox.name(), 914 resource->mailbox.callback(), 915 it->sync_point); 916 } 917 if (resource->marked_for_deletion) 918 DeleteResourceInternal(map_iterator, Normal); 919 } 920 } 921 922 bool ResourceProvider::TransferResource(WebGraphicsContext3D* context, 923 ResourceId id, 924 TransferableResource* resource) { 925 DCHECK(thread_checker_.CalledOnValidThread()); 926 ResourceMap::iterator it = resources_.find(id); 927 CHECK(it != resources_.end()); 928 Resource* source = &it->second; 929 DCHECK(!source->locked_for_write); 930 DCHECK(!source->lock_for_read_count); 931 DCHECK(!source->external || (source->external && source->mailbox.IsValid())); 932 DCHECK(source->allocated); 933 if (source->exported) 934 return false; 935 resource->id = id; 936 resource->format = source->format; 937 resource->filter = source->filter; 938 resource->size = source->size; 939 940 // TODO(skaslev) Implement this path for shared memory resources. 941 DCHECK(!source->mailbox.IsSharedMemory()); 942 943 if (!source->mailbox.IsTexture()) { 944 // This is a resource allocated by the compositor, we need to produce it. 945 // Don't set a sync point, the caller will do it. 946 DCHECK(source->gl_id); 947 GLC(context, context->bindTexture(GL_TEXTURE_2D, source->gl_id)); 948 GLC(context, context->genMailboxCHROMIUM(resource->mailbox.name)); 949 GLC(context, context->produceTextureCHROMIUM(GL_TEXTURE_2D, 950 resource->mailbox.name)); 951 source->mailbox.SetName(resource->mailbox); 952 } else { 953 // This is either an external resource, or a compositor resource that we 954 // already exported. Make sure to forward the sync point that we were given. 955 resource->mailbox = source->mailbox.name(); 956 resource->sync_point = source->mailbox.sync_point(); 957 source->mailbox.ResetSyncPoint(); 958 } 959 960 return true; 961 } 962 963 void ResourceProvider::AcquirePixelBuffer(ResourceId id) { 964 DCHECK(thread_checker_.CalledOnValidThread()); 965 ResourceMap::iterator it = resources_.find(id); 966 CHECK(it != resources_.end()); 967 Resource* resource = &it->second; 968 DCHECK(!resource->external); 969 DCHECK(!resource->exported); 970 DCHECK(!resource->image_id); 971 972 if (resource->type == GLTexture) { 973 WebGraphicsContext3D* context3d = output_surface_->context3d(); 974 DCHECK(context3d); 975 if (!resource->gl_pixel_buffer_id) 976 resource->gl_pixel_buffer_id = context3d->createBuffer(); 977 context3d->bindBuffer( 978 GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM, 979 resource->gl_pixel_buffer_id); 980 context3d->bufferData( 981 GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM, 982 4 * resource->size.GetArea(), 983 NULL, 984 GL_DYNAMIC_DRAW); 985 context3d->bindBuffer(GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM, 0); 986 } 987 988 if (resource->pixels) { 989 if (resource->pixel_buffer) 990 return; 991 992 resource->pixel_buffer = new uint8_t[4 * resource->size.GetArea()]; 993 } 994 } 995 996 void ResourceProvider::ReleasePixelBuffer(ResourceId id) { 997 DCHECK(thread_checker_.CalledOnValidThread()); 998 ResourceMap::iterator it = resources_.find(id); 999 CHECK(it != resources_.end()); 1000 Resource* resource = &it->second; 1001 DCHECK(!resource->external); 1002 DCHECK(!resource->exported); 1003 DCHECK(!resource->image_id); 1004 1005 // The pixel buffer can be released while there is a pending "set pixels" 1006 // if completion has been forced. Any shared memory associated with this 1007 // pixel buffer will not be freed until the waitAsyncTexImage2DCHROMIUM 1008 // command has been processed on the service side. It is also safe to 1009 // reuse any query id associated with this resource before they complete 1010 // as each new query has a unique submit count. 1011 if (resource->pending_set_pixels) { 1012 DCHECK(resource->set_pixels_completion_forced); 1013 resource->pending_set_pixels = false; 1014 UnlockForWrite(id); 1015 } 1016 1017 if (resource->type == GLTexture) { 1018 if (!resource->gl_pixel_buffer_id) 1019 return; 1020 WebGraphicsContext3D* context3d = output_surface_->context3d(); 1021 DCHECK(context3d); 1022 context3d->bindBuffer( 1023 GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM, 1024 resource->gl_pixel_buffer_id); 1025 context3d->bufferData( 1026 GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM, 1027 0, 1028 NULL, 1029 GL_DYNAMIC_DRAW); 1030 context3d->bindBuffer(GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM, 0); 1031 } 1032 1033 if (resource->pixels) { 1034 if (!resource->pixel_buffer) 1035 return; 1036 delete[] resource->pixel_buffer; 1037 resource->pixel_buffer = NULL; 1038 } 1039 } 1040 1041 uint8_t* ResourceProvider::MapPixelBuffer(ResourceId id) { 1042 DCHECK(thread_checker_.CalledOnValidThread()); 1043 ResourceMap::iterator it = resources_.find(id); 1044 CHECK(it != resources_.end()); 1045 Resource* resource = &it->second; 1046 DCHECK(!resource->external); 1047 DCHECK(!resource->exported); 1048 DCHECK(!resource->image_id); 1049 1050 if (resource->type == GLTexture) { 1051 WebGraphicsContext3D* context3d = output_surface_->context3d(); 1052 DCHECK(context3d); 1053 DCHECK(resource->gl_pixel_buffer_id); 1054 context3d->bindBuffer( 1055 GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM, 1056 resource->gl_pixel_buffer_id); 1057 uint8_t* image = static_cast<uint8_t*>( 1058 context3d->mapBufferCHROMIUM( 1059 GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM, GL_WRITE_ONLY)); 1060 context3d->bindBuffer(GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM, 0); 1061 // Buffer is required to be 4-byte aligned. 1062 CHECK(!(reinterpret_cast<intptr_t>(image) & 3)); 1063 return image; 1064 } 1065 1066 if (resource->pixels) 1067 return resource->pixel_buffer; 1068 1069 return NULL; 1070 } 1071 1072 void ResourceProvider::UnmapPixelBuffer(ResourceId id) { 1073 DCHECK(thread_checker_.CalledOnValidThread()); 1074 ResourceMap::iterator it = resources_.find(id); 1075 CHECK(it != resources_.end()); 1076 Resource* resource = &it->second; 1077 DCHECK(!resource->external); 1078 DCHECK(!resource->exported); 1079 DCHECK(!resource->image_id); 1080 1081 if (resource->type == GLTexture) { 1082 WebGraphicsContext3D* context3d = output_surface_->context3d(); 1083 DCHECK(context3d); 1084 DCHECK(resource->gl_pixel_buffer_id); 1085 context3d->bindBuffer( 1086 GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM, 1087 resource->gl_pixel_buffer_id); 1088 context3d->unmapBufferCHROMIUM(GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM); 1089 context3d->bindBuffer(GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM, 0); 1090 } 1091 } 1092 1093 void ResourceProvider::BindForSampling(ResourceProvider::ResourceId resource_id, 1094 GLenum target, 1095 GLenum unit, 1096 GLenum filter) { 1097 DCHECK(thread_checker_.CalledOnValidThread()); 1098 WebGraphicsContext3D* context3d = output_surface_->context3d(); 1099 ResourceMap::iterator it = resources_.find(resource_id); 1100 DCHECK(it != resources_.end()); 1101 Resource* resource = &it->second; 1102 DCHECK(resource->lock_for_read_count); 1103 DCHECK(!resource->locked_for_write || resource->set_pixels_completion_forced); 1104 DCHECK_EQ(GL_TEXTURE0, GetActiveTextureUnit(context3d)); 1105 1106 if (unit != GL_TEXTURE0) 1107 GLC(context3d, context3d->activeTexture(unit)); 1108 GLC(context3d, context3d->bindTexture(target, resource->gl_id)); 1109 if (filter != resource->filter) { 1110 GLC(context3d, context3d->texParameteri(target, 1111 GL_TEXTURE_MIN_FILTER, 1112 filter)); 1113 GLC(context3d, context3d->texParameteri(target, 1114 GL_TEXTURE_MAG_FILTER, 1115 filter)); 1116 resource->filter = filter; 1117 } 1118 1119 if (resource->image_id) 1120 context3d->bindTexImage2DCHROMIUM(target, resource->image_id); 1121 1122 // Active unit being GL_TEXTURE0 is effectively the ground state. 1123 if (unit != GL_TEXTURE0) 1124 GLC(context3d, context3d->activeTexture(GL_TEXTURE0)); 1125 } 1126 1127 void ResourceProvider::UnbindForSampling( 1128 ResourceProvider::ResourceId resource_id, GLenum target, GLenum unit) { 1129 DCHECK(thread_checker_.CalledOnValidThread()); 1130 ResourceMap::iterator it = resources_.find(resource_id); 1131 DCHECK(it != resources_.end()); 1132 Resource* resource = &it->second; 1133 1134 if (!resource->image_id) 1135 return; 1136 1137 WebGraphicsContext3D* context3d = output_surface_->context3d(); 1138 DCHECK_EQ(GL_TEXTURE0, GetActiveTextureUnit(context3d)); 1139 if (unit != GL_TEXTURE0) 1140 GLC(context3d, context3d->activeTexture(unit)); 1141 context3d->releaseTexImage2DCHROMIUM(target, resource->image_id); 1142 // Active unit being GL_TEXTURE0 is effectively the ground state. 1143 if (unit != GL_TEXTURE0) 1144 GLC(context3d, context3d->activeTexture(GL_TEXTURE0)); 1145 } 1146 1147 void ResourceProvider::BeginSetPixels(ResourceId id) { 1148 DCHECK(thread_checker_.CalledOnValidThread()); 1149 ResourceMap::iterator it = resources_.find(id); 1150 CHECK(it != resources_.end()); 1151 Resource* resource = &it->second; 1152 DCHECK(!resource->pending_set_pixels); 1153 1154 LazyCreate(resource); 1155 DCHECK(resource->gl_id || resource->allocated); 1156 DCHECK(ReadLockFenceHasPassed(resource)); 1157 DCHECK(!resource->image_id); 1158 1159 bool allocate = !resource->allocated; 1160 resource->allocated = true; 1161 LockForWrite(id); 1162 1163 if (resource->gl_id) { 1164 WebGraphicsContext3D* context3d = output_surface_->context3d(); 1165 DCHECK(context3d); 1166 DCHECK(resource->gl_pixel_buffer_id); 1167 context3d->bindTexture(GL_TEXTURE_2D, resource->gl_id); 1168 context3d->bindBuffer( 1169 GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM, 1170 resource->gl_pixel_buffer_id); 1171 if (!resource->gl_upload_query_id) 1172 resource->gl_upload_query_id = context3d->createQueryEXT(); 1173 context3d->beginQueryEXT( 1174 GL_ASYNC_PIXEL_TRANSFERS_COMPLETED_CHROMIUM, 1175 resource->gl_upload_query_id); 1176 if (allocate) { 1177 context3d->asyncTexImage2DCHROMIUM(GL_TEXTURE_2D, 1178 0, /* level */ 1179 resource->format, 1180 resource->size.width(), 1181 resource->size.height(), 1182 0, /* border */ 1183 resource->format, 1184 GL_UNSIGNED_BYTE, 1185 NULL); 1186 } else { 1187 context3d->asyncTexSubImage2DCHROMIUM(GL_TEXTURE_2D, 1188 0, /* level */ 1189 0, /* x */ 1190 0, /* y */ 1191 resource->size.width(), 1192 resource->size.height(), 1193 resource->format, 1194 GL_UNSIGNED_BYTE, 1195 NULL); 1196 } 1197 context3d->endQueryEXT(GL_ASYNC_PIXEL_TRANSFERS_COMPLETED_CHROMIUM); 1198 context3d->bindBuffer(GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM, 0); 1199 } 1200 1201 if (resource->pixels) { 1202 DCHECK(!resource->mailbox.IsValid()); 1203 DCHECK(resource->pixel_buffer); 1204 DCHECK(resource->format == GL_RGBA); 1205 1206 std::swap(resource->pixels, resource->pixel_buffer); 1207 delete[] resource->pixel_buffer; 1208 resource->pixel_buffer = NULL; 1209 } 1210 1211 resource->pending_set_pixels = true; 1212 resource->set_pixels_completion_forced = false; 1213 } 1214 1215 void ResourceProvider::ForceSetPixelsToComplete(ResourceId id) { 1216 DCHECK(thread_checker_.CalledOnValidThread()); 1217 ResourceMap::iterator it = resources_.find(id); 1218 CHECK(it != resources_.end()); 1219 Resource* resource = &it->second; 1220 DCHECK(resource->locked_for_write); 1221 DCHECK(resource->pending_set_pixels); 1222 DCHECK(!resource->set_pixels_completion_forced); 1223 1224 if (resource->gl_id) { 1225 WebGraphicsContext3D* context3d = output_surface_->context3d(); 1226 GLC(context3d, context3d->bindTexture(GL_TEXTURE_2D, resource->gl_id)); 1227 GLC(context3d, context3d->waitAsyncTexImage2DCHROMIUM(GL_TEXTURE_2D)); 1228 GLC(context3d, context3d->bindTexture(GL_TEXTURE_2D, 0)); 1229 } 1230 1231 resource->set_pixels_completion_forced = true; 1232 } 1233 1234 bool ResourceProvider::DidSetPixelsComplete(ResourceId id) { 1235 DCHECK(thread_checker_.CalledOnValidThread()); 1236 ResourceMap::iterator it = resources_.find(id); 1237 CHECK(it != resources_.end()); 1238 Resource* resource = &it->second; 1239 DCHECK(resource->locked_for_write); 1240 DCHECK(resource->pending_set_pixels); 1241 1242 if (resource->gl_id) { 1243 WebGraphicsContext3D* context3d = output_surface_->context3d(); 1244 DCHECK(context3d); 1245 DCHECK(resource->gl_upload_query_id); 1246 unsigned complete = 1; 1247 context3d->getQueryObjectuivEXT( 1248 resource->gl_upload_query_id, 1249 GL_QUERY_RESULT_AVAILABLE_EXT, 1250 &complete); 1251 if (!complete) 1252 return false; 1253 } 1254 1255 resource->pending_set_pixels = false; 1256 UnlockForWrite(id); 1257 1258 return true; 1259 } 1260 1261 void ResourceProvider::CreateForTesting(ResourceId id) { 1262 ResourceMap::iterator it = resources_.find(id); 1263 CHECK(it != resources_.end()); 1264 Resource* resource = &it->second; 1265 LazyCreate(resource); 1266 } 1267 1268 void ResourceProvider::LazyCreate(Resource* resource) { 1269 if (resource->type != GLTexture || resource->gl_id != 0) 1270 return; 1271 1272 // Early out for resources that don't require texture creation. 1273 if (resource->texture_pool == 0) 1274 return; 1275 1276 WebGraphicsContext3D* context3d = output_surface_->context3d(); 1277 DCHECK(context3d); 1278 // Create and set texture properties. Allocation is delayed until needed. 1279 resource->gl_id = CreateTextureId(context3d); 1280 GLC(context3d, context3d->texParameteri(GL_TEXTURE_2D, 1281 GL_TEXTURE_POOL_CHROMIUM, 1282 resource->texture_pool)); 1283 if (use_texture_usage_hint_ && resource->hint == TextureUsageFramebuffer) { 1284 GLC(context3d, context3d->texParameteri(GL_TEXTURE_2D, 1285 GL_TEXTURE_USAGE_ANGLE, 1286 GL_FRAMEBUFFER_ATTACHMENT_ANGLE)); 1287 } 1288 } 1289 1290 void ResourceProvider::AllocateForTesting(ResourceId id) { 1291 ResourceMap::iterator it = resources_.find(id); 1292 CHECK(it != resources_.end()); 1293 Resource* resource = &it->second; 1294 LazyAllocate(resource); 1295 } 1296 1297 void ResourceProvider::LazyAllocate(Resource* resource) { 1298 DCHECK(resource); 1299 LazyCreate(resource); 1300 1301 DCHECK(resource->gl_id || resource->allocated); 1302 if (resource->allocated || !resource->gl_id) 1303 return; 1304 resource->allocated = true; 1305 WebGraphicsContext3D* context3d = output_surface_->context3d(); 1306 gfx::Size& size = resource->size; 1307 GLenum format = resource->format; 1308 GLC(context3d, context3d->bindTexture(GL_TEXTURE_2D, resource->gl_id)); 1309 if (use_texture_storage_ext_ && IsTextureFormatSupportedForStorage(format)) { 1310 GLenum storage_format = TextureToStorageFormat(format); 1311 GLC(context3d, context3d->texStorage2DEXT(GL_TEXTURE_2D, 1312 1, 1313 storage_format, 1314 size.width(), 1315 size.height())); 1316 } else { 1317 GLC(context3d, context3d->texImage2D(GL_TEXTURE_2D, 1318 0, 1319 format, 1320 size.width(), 1321 size.height(), 1322 0, 1323 format, 1324 GL_UNSIGNED_BYTE, 1325 NULL)); 1326 } 1327 } 1328 1329 void ResourceProvider::EnableReadLockFences(ResourceProvider::ResourceId id, 1330 bool enable) { 1331 DCHECK(thread_checker_.CalledOnValidThread()); 1332 ResourceMap::iterator it = resources_.find(id); 1333 CHECK(it != resources_.end()); 1334 Resource* resource = &it->second; 1335 resource->enable_read_lock_fences = enable; 1336 } 1337 1338 void ResourceProvider::AcquireImage(ResourceId id) { 1339 DCHECK(thread_checker_.CalledOnValidThread()); 1340 ResourceMap::iterator it = resources_.find(id); 1341 CHECK(it != resources_.end()); 1342 Resource* resource = &it->second; 1343 1344 DCHECK(!resource->external); 1345 DCHECK(!resource->exported); 1346 1347 if (resource->type != GLTexture) 1348 return; 1349 1350 if (resource->image_id) 1351 return; 1352 1353 resource->allocated = true; 1354 WebGraphicsContext3D* context3d = output_surface_->context3d(); 1355 DCHECK(context3d); 1356 resource->image_id = context3d->createImageCHROMIUM( 1357 resource->size.width(), resource->size.height(), GL_RGBA8_OES); 1358 DCHECK(resource->image_id); 1359 } 1360 1361 void ResourceProvider::ReleaseImage(ResourceId id) { 1362 DCHECK(thread_checker_.CalledOnValidThread()); 1363 ResourceMap::iterator it = resources_.find(id); 1364 CHECK(it != resources_.end()); 1365 Resource* resource = &it->second; 1366 1367 DCHECK(!resource->external); 1368 DCHECK(!resource->exported); 1369 1370 if (!resource->image_id) 1371 return; 1372 1373 WebGraphicsContext3D* context3d = output_surface_->context3d(); 1374 DCHECK(context3d); 1375 context3d->destroyImageCHROMIUM(resource->image_id); 1376 resource->image_id = 0; 1377 resource->allocated = false; 1378 } 1379 1380 uint8_t* ResourceProvider::MapImage(ResourceId id) { 1381 DCHECK(thread_checker_.CalledOnValidThread()); 1382 ResourceMap::iterator it = resources_.find(id); 1383 CHECK(it != resources_.end()); 1384 Resource* resource = &it->second; 1385 1386 DCHECK(ReadLockFenceHasPassed(resource)); 1387 DCHECK(!resource->external); 1388 DCHECK(!resource->exported); 1389 1390 if (resource->image_id) { 1391 WebGraphicsContext3D* context3d = output_surface_->context3d(); 1392 DCHECK(context3d); 1393 return static_cast<uint8_t*>( 1394 context3d->mapImageCHROMIUM(resource->image_id, GL_READ_WRITE)); 1395 } 1396 1397 if (resource->pixels) 1398 return resource->pixels; 1399 1400 return NULL; 1401 } 1402 1403 void ResourceProvider::UnmapImage(ResourceId id) { 1404 DCHECK(thread_checker_.CalledOnValidThread()); 1405 ResourceMap::iterator it = resources_.find(id); 1406 CHECK(it != resources_.end()); 1407 Resource* resource = &it->second; 1408 1409 DCHECK(!resource->external); 1410 DCHECK(!resource->exported); 1411 1412 if (resource->image_id) { 1413 WebGraphicsContext3D* context3d = output_surface_->context3d(); 1414 DCHECK(context3d); 1415 context3d->unmapImageCHROMIUM(resource->image_id); 1416 } 1417 } 1418 1419 int ResourceProvider::GetImageStride(ResourceId id) { 1420 DCHECK(thread_checker_.CalledOnValidThread()); 1421 ResourceMap::iterator it = resources_.find(id); 1422 CHECK(it != resources_.end()); 1423 Resource* resource = &it->second; 1424 1425 DCHECK(!resource->external); 1426 DCHECK(!resource->exported); 1427 1428 int stride = 0; 1429 1430 if (resource->image_id) { 1431 WebGraphicsContext3D* context3d = output_surface_->context3d(); 1432 DCHECK(context3d); 1433 context3d->getImageParameterivCHROMIUM( 1434 resource->image_id, GL_IMAGE_ROWBYTES_CHROMIUM, &stride); 1435 } 1436 1437 return stride; 1438 } 1439 1440 GLint ResourceProvider::GetActiveTextureUnit(WebGraphicsContext3D* context) { 1441 GLint active_unit = 0; 1442 context->getIntegerv(GL_ACTIVE_TEXTURE, &active_unit); 1443 return active_unit; 1444 } 1445 1446 } // namespace cc 1447