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.
5 #include "cc/resources/resource_provider.h"
10 #include "base/containers/hash_tables.h"
11 #include "base/debug/trace_event.h"
12 #include "base/stl_util.h"
13 #include "base/strings/string_split.h"
14 #include "base/strings/string_util.h"
15 #include "cc/base/util.h"
16 #include "cc/output/gl_renderer.h" // For the GLC() macro.
17 #include "cc/resources/platform_color.h"
18 #include "cc/resources/returned_resource.h"
19 #include "cc/resources/shared_bitmap_manager.h"
20 #include "cc/resources/transferable_resource.h"
21 #include "cc/scheduler/texture_uploader.h"
22 #include "gpu/GLES2/gl2extchromium.h"
23 #include "third_party/WebKit/public/platform/WebGraphicsContext3D.h"
24 #include "third_party/khronos/GLES2/gl2.h"
25 #include "third_party/khronos/GLES2/gl2ext.h"
26 #include "ui/gfx/rect.h"
27 #include "ui/gfx/vector2d.h"
29 using WebKit::WebGraphicsContext3D;
35 // Measured in seconds.
36 const double kSoftwareUploadTickRate = 0.000250;
37 const double kTextureUploadTickRate = 0.004;
39 GLenum TextureToStorageFormat(ResourceFormat format) {
40 GLenum storage_format = GL_RGBA8_OES;
45 storage_format = GL_BGRA8_EXT;
55 return storage_format;
58 bool IsFormatSupportedForStorage(ResourceFormat format) {
72 class ScopedSetActiveTexture {
74 ScopedSetActiveTexture(WebGraphicsContext3D* context3d, GLenum unit)
75 : context3d_(context3d), unit_(unit) {
76 DCHECK_EQ(GL_TEXTURE0, ResourceProvider::GetActiveTextureUnit(context3d_));
78 if (unit_ != GL_TEXTURE0)
79 GLC(context3d_, context3d_->activeTexture(unit_));
82 ~ScopedSetActiveTexture() {
83 // Active unit being GL_TEXTURE0 is effectively the ground state.
84 if (unit_ != GL_TEXTURE0)
85 GLC(context3d_, context3d_->activeTexture(GL_TEXTURE0));
89 WebGraphicsContext3D* context3d_;
95 ResourceProvider::Resource::Resource()
98 gl_pixel_buffer_id(0),
99 gl_upload_query_id(0),
102 lock_for_read_count(0),
105 locked_for_write(false),
107 marked_for_deletion(false),
108 pending_set_pixels(false),
109 set_pixels_completion_forced(false),
111 enable_read_lock_fences(false),
112 read_lock_fence(NULL),
123 hint(TextureUsageAny),
124 type(static_cast<ResourceType>(0)),
126 shared_bitmap(NULL) {}
128 ResourceProvider::Resource::~Resource() {}
130 ResourceProvider::Resource::Resource(unsigned texture_id,
136 TextureUsageHint hint,
137 ResourceFormat format)
140 gl_pixel_buffer_id(0),
141 gl_upload_query_id(0),
144 lock_for_read_count(0),
147 locked_for_write(false),
149 marked_for_deletion(false),
150 pending_set_pixels(false),
151 set_pixels_completion_forced(false),
153 enable_read_lock_fences(false),
154 read_lock_fence(NULL),
157 original_filter(filter),
162 texture_pool(texture_pool),
163 wrap_mode(wrap_mode),
168 shared_bitmap(NULL) {
169 DCHECK(wrap_mode == GL_CLAMP_TO_EDGE || wrap_mode == GL_REPEAT);
172 ResourceProvider::Resource::Resource(uint8_t* pixels,
173 SharedBitmap* bitmap,
179 gl_pixel_buffer_id(0),
180 gl_upload_query_id(0),
183 lock_for_read_count(0),
186 locked_for_write(false),
188 marked_for_deletion(false),
189 pending_set_pixels(false),
190 set_pixels_completion_forced(false),
192 enable_read_lock_fences(false),
193 read_lock_fence(NULL),
196 original_filter(filter),
202 wrap_mode(wrap_mode),
204 hint(TextureUsageAny),
207 shared_bitmap(bitmap) {
208 DCHECK(wrap_mode == GL_CLAMP_TO_EDGE || wrap_mode == GL_REPEAT);
211 ResourceProvider::Child::Child() {}
213 ResourceProvider::Child::~Child() {}
215 scoped_ptr<ResourceProvider> ResourceProvider::Create(
216 OutputSurface* output_surface,
217 SharedBitmapManager* shared_bitmap_manager,
218 int highp_threshold_min,
219 bool use_rgba_4444_texture_format,
220 size_t texture_id_allocation_chunk_size) {
221 scoped_ptr<ResourceProvider> resource_provider(
222 new ResourceProvider(output_surface,
223 shared_bitmap_manager,
225 use_rgba_4444_texture_format,
226 texture_id_allocation_chunk_size));
228 bool success = false;
229 if (resource_provider->Context3d()) {
230 success = resource_provider->InitializeGL();
232 resource_provider->InitializeSoftware();
237 return scoped_ptr<ResourceProvider>();
239 DCHECK_NE(InvalidType, resource_provider->default_resource_type());
240 return resource_provider.Pass();
243 ResourceProvider::~ResourceProvider() {
244 while (!children_.empty())
245 DestroyChild(children_.begin()->first);
246 while (!resources_.empty())
247 DeleteResourceInternal(resources_.begin(), ForShutdown);
252 bool ResourceProvider::InUseByConsumer(ResourceId id) {
253 Resource* resource = GetResource(id);
254 return resource->lock_for_read_count > 0 || resource->exported_count > 0 ||
258 bool ResourceProvider::IsLost(ResourceId id) {
259 Resource* resource = GetResource(id);
260 return resource->lost;
263 ResourceProvider::ResourceId ResourceProvider::CreateResource(
266 TextureUsageHint hint,
267 ResourceFormat format) {
268 DCHECK(!size.IsEmpty());
269 switch (default_resource_type_) {
271 return CreateGLTexture(
272 size, GL_TEXTURE_POOL_UNMANAGED_CHROMIUM, wrap_mode, hint, format);
274 DCHECK_EQ(RGBA_8888, format);
275 return CreateBitmap(size);
280 LOG(FATAL) << "Invalid default resource type.";
284 ResourceProvider::ResourceId ResourceProvider::CreateManagedResource(
287 TextureUsageHint hint,
288 ResourceFormat format) {
289 DCHECK(!size.IsEmpty());
290 switch (default_resource_type_) {
292 return CreateGLTexture(
293 size, GL_TEXTURE_POOL_MANAGED_CHROMIUM, wrap_mode, hint, format);
295 DCHECK_EQ(RGBA_8888, format);
296 return CreateBitmap(size);
301 LOG(FATAL) << "Invalid default resource type.";
305 ResourceProvider::ResourceId ResourceProvider::CreateGLTexture(
309 TextureUsageHint hint,
310 ResourceFormat format) {
311 DCHECK_LE(size.width(), max_texture_size_);
312 DCHECK_LE(size.height(), max_texture_size_);
313 DCHECK(thread_checker_.CalledOnValidThread());
315 ResourceId id = next_id_++;
317 0, size, GL_TEXTURE_2D, GL_LINEAR, texture_pool, wrap_mode, hint, format);
318 resource.allocated = false;
319 resources_[id] = resource;
323 ResourceProvider::ResourceId ResourceProvider::CreateBitmap(gfx::Size size) {
324 DCHECK(thread_checker_.CalledOnValidThread());
326 scoped_ptr<SharedBitmap> bitmap;
327 if (shared_bitmap_manager_)
328 bitmap = shared_bitmap_manager_->AllocateSharedBitmap(size);
332 pixels = bitmap->pixels();
334 pixels = new uint8_t[4 * size.GetArea()];
336 ResourceId id = next_id_++;
338 pixels, bitmap.release(), size, GL_LINEAR, GL_CLAMP_TO_EDGE);
339 resource.allocated = true;
340 resources_[id] = resource;
344 ResourceProvider::ResourceId
345 ResourceProvider::CreateResourceFromExternalTexture(
346 unsigned texture_target,
347 unsigned texture_id) {
348 DCHECK(thread_checker_.CalledOnValidThread());
350 WebGraphicsContext3D* context3d = Context3d();
352 GLC(context3d, context3d->bindTexture(texture_target, texture_id));
353 GLC(context3d, context3d->texParameteri(
354 texture_target, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
355 GLC(context3d, context3d->texParameteri(
356 texture_target, GL_TEXTURE_MAG_FILTER, GL_LINEAR));
357 GLC(context3d, context3d->texParameteri(
358 texture_target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE));
359 GLC(context3d, context3d->texParameteri(
360 texture_target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE));
362 ResourceId id = next_id_++;
363 Resource resource(texture_id,
371 resource.external = true;
372 resource.allocated = true;
373 resources_[id] = resource;
377 ResourceProvider::ResourceId ResourceProvider::CreateResourceFromTextureMailbox(
378 const TextureMailbox& mailbox,
379 scoped_ptr<SingleReleaseCallback> release_callback) {
380 DCHECK(thread_checker_.CalledOnValidThread());
381 // Just store the information. Mailbox will be consumed in LockForRead().
382 ResourceId id = next_id_++;
383 DCHECK(mailbox.IsValid());
384 Resource& resource = resources_[id];
385 if (mailbox.IsTexture()) {
386 resource = Resource(0,
395 DCHECK(mailbox.IsSharedMemory());
396 base::SharedMemory* shared_memory = mailbox.shared_memory();
397 DCHECK(shared_memory->memory());
398 uint8_t* pixels = reinterpret_cast<uint8_t*>(shared_memory->memory());
399 scoped_ptr<SharedBitmap> shared_bitmap;
400 if (shared_bitmap_manager_) {
402 shared_bitmap_manager_->GetBitmapForSharedMemory(shared_memory);
404 resource = Resource(pixels,
405 shared_bitmap.release(),
406 mailbox.shared_memory_size(),
410 resource.external = true;
411 resource.allocated = true;
412 resource.mailbox = mailbox;
413 resource.release_callback =
414 base::Bind(&SingleReleaseCallback::Run,
415 base::Owned(release_callback.release()));
419 void ResourceProvider::DeleteResource(ResourceId id) {
420 DCHECK(thread_checker_.CalledOnValidThread());
421 ResourceMap::iterator it = resources_.find(id);
422 CHECK(it != resources_.end());
423 Resource* resource = &it->second;
424 DCHECK(!resource->lock_for_read_count);
425 DCHECK(!resource->marked_for_deletion);
426 DCHECK_EQ(resource->imported_count, 0);
427 DCHECK(resource->pending_set_pixels || !resource->locked_for_write);
429 if (resource->exported_count > 0) {
430 resource->marked_for_deletion = true;
433 DeleteResourceInternal(it, Normal);
437 void ResourceProvider::DeleteResourceInternal(ResourceMap::iterator it,
439 TRACE_EVENT0("cc", "ResourceProvider::DeleteResourceInternal");
440 Resource* resource = &it->second;
441 bool lost_resource = resource->lost;
443 DCHECK(resource->exported_count == 0 || style != Normal);
444 if (style == ForShutdown && resource->exported_count > 0)
445 lost_resource = true;
447 if (resource->image_id) {
448 WebGraphicsContext3D* context3d = Context3d();
450 GLC(context3d, context3d->destroyImageCHROMIUM(resource->image_id));
453 if (resource->gl_id && !resource->external) {
454 WebGraphicsContext3D* context3d = Context3d();
456 GLC(context3d, context3d->deleteTexture(resource->gl_id));
458 if (resource->gl_upload_query_id) {
459 WebGraphicsContext3D* context3d = Context3d();
461 GLC(context3d, context3d->deleteQueryEXT(resource->gl_upload_query_id));
463 if (resource->gl_pixel_buffer_id) {
464 WebGraphicsContext3D* context3d = Context3d();
466 GLC(context3d, context3d->deleteBuffer(resource->gl_pixel_buffer_id));
468 if (resource->mailbox.IsValid() && resource->external) {
469 unsigned sync_point = resource->mailbox.sync_point();
470 if (resource->mailbox.IsTexture()) {
471 lost_resource |= lost_output_surface_;
472 WebGraphicsContext3D* context3d = Context3d();
475 GLC(context3d, context3d->deleteTexture(resource->gl_id));
476 if (!lost_resource && resource->gl_id)
477 sync_point = context3d->insertSyncPoint();
479 DCHECK(resource->mailbox.IsSharedMemory());
480 base::SharedMemory* shared_memory = resource->mailbox.shared_memory();
481 if (resource->pixels && shared_memory) {
482 DCHECK(shared_memory->memory() == resource->pixels);
483 resource->pixels = NULL;
484 delete resource->shared_bitmap;
485 resource->shared_bitmap = NULL;
488 resource->release_callback.Run(sync_point, lost_resource);
490 if (resource->shared_bitmap) {
491 delete resource->shared_bitmap;
492 resource->pixels = NULL;
494 if (resource->pixels)
495 delete[] resource->pixels;
496 if (resource->pixel_buffer)
497 delete[] resource->pixel_buffer;
499 resources_.erase(it);
502 ResourceProvider::ResourceType ResourceProvider::GetResourceType(
504 return GetResource(id)->type;
507 void ResourceProvider::SetPixels(ResourceId id,
508 const uint8_t* image,
509 gfx::Rect image_rect,
510 gfx::Rect source_rect,
511 gfx::Vector2d dest_offset) {
512 Resource* resource = GetResource(id);
513 DCHECK(!resource->locked_for_write);
514 DCHECK(!resource->lock_for_read_count);
515 DCHECK(!resource->external);
516 DCHECK_EQ(resource->exported_count, 0);
517 DCHECK(ReadLockFenceHasPassed(resource));
518 LazyAllocate(resource);
520 if (resource->gl_id) {
521 DCHECK(!resource->pending_set_pixels);
522 DCHECK_EQ(resource->target, static_cast<GLenum>(GL_TEXTURE_2D));
523 WebGraphicsContext3D* context3d = Context3d();
525 DCHECK(texture_uploader_.get());
526 context3d->bindTexture(GL_TEXTURE_2D, resource->gl_id);
527 texture_uploader_->Upload(image,
535 if (resource->pixels) {
536 DCHECK(resource->allocated);
537 DCHECK_EQ(RGBA_8888, resource->format);
540 SkBitmap::kARGB_8888_Config, image_rect.width(), image_rect.height());
541 src_full.setPixels(const_cast<uint8_t*>(image));
543 SkIRect sk_source_rect = SkIRect::MakeXYWH(source_rect.x(),
546 source_rect.height());
547 sk_source_rect.offset(-image_rect.x(), -image_rect.y());
548 src_full.extractSubset(&src_subset, sk_source_rect);
550 ScopedWriteLockSoftware lock(this, id);
551 SkCanvas* dest = lock.sk_canvas();
552 dest->writePixels(src_subset, dest_offset.x(), dest_offset.y());
556 size_t ResourceProvider::NumBlockingUploads() {
557 if (!texture_uploader_)
560 return texture_uploader_->NumBlockingUploads();
563 void ResourceProvider::MarkPendingUploadsAsNonBlocking() {
564 if (!texture_uploader_)
567 texture_uploader_->MarkPendingUploadsAsNonBlocking();
570 double ResourceProvider::EstimatedUploadsPerSecond() {
571 if (!texture_uploader_)
574 return texture_uploader_->EstimatedTexturesPerSecond();
577 void ResourceProvider::FlushUploads() {
578 if (!texture_uploader_)
581 texture_uploader_->Flush();
584 void ResourceProvider::ReleaseCachedData() {
585 if (!texture_uploader_)
588 texture_uploader_->ReleaseCachedQueries();
591 base::TimeDelta ResourceProvider::TextureUpdateTickRate() {
592 // Software resource uploads happen on impl thread, so don't bother batching
593 // them up and trying to wait for them to complete.
595 texture_uploader_ ? kTextureUploadTickRate : kSoftwareUploadTickRate;
596 return base::TimeDelta::FromMicroseconds(base::Time::kMicrosecondsPerSecond *
600 void ResourceProvider::Flush() {
601 DCHECK(thread_checker_.CalledOnValidThread());
602 WebGraphicsContext3D* context3d = Context3d();
607 void ResourceProvider::Finish() {
608 DCHECK(thread_checker_.CalledOnValidThread());
609 WebGraphicsContext3D* context3d = Context3d();
614 bool ResourceProvider::ShallowFlushIfSupported() {
615 DCHECK(thread_checker_.CalledOnValidThread());
616 WebGraphicsContext3D* context3d = Context3d();
617 if (!context3d || !use_shallow_flush_)
620 context3d->shallowFlushCHROMIUM();
624 ResourceProvider::Resource* ResourceProvider::GetResource(ResourceId id) {
625 DCHECK(thread_checker_.CalledOnValidThread());
626 ResourceMap::iterator it = resources_.find(id);
627 CHECK(it != resources_.end());
631 const ResourceProvider::Resource* ResourceProvider::LockForRead(ResourceId id) {
632 Resource* resource = GetResource(id);
633 DCHECK(!resource->locked_for_write ||
634 resource->set_pixels_completion_forced) <<
635 "locked for write: " << resource->locked_for_write <<
636 " pixels completion forced: " << resource->set_pixels_completion_forced;
637 DCHECK_EQ(resource->exported_count, 0);
638 // Uninitialized! Call SetPixels or LockForWrite first.
639 DCHECK(resource->allocated);
641 LazyCreate(resource);
643 if (resource->external) {
644 if (!resource->gl_id && resource->mailbox.IsTexture()) {
645 WebGraphicsContext3D* context3d = Context3d();
647 if (resource->mailbox.sync_point()) {
649 context3d->waitSyncPoint(resource->mailbox.sync_point()));
650 resource->mailbox.ResetSyncPoint();
652 resource->gl_id = NextTextureId();
653 GLC(context3d, context3d->bindTexture(resource->target, resource->gl_id));
655 context3d->consumeTextureCHROMIUM(resource->target,
656 resource->mailbox.data()));
660 resource->lock_for_read_count++;
661 if (resource->enable_read_lock_fences)
662 resource->read_lock_fence = current_read_lock_fence_;
667 void ResourceProvider::UnlockForRead(ResourceId id) {
668 Resource* resource = GetResource(id);
669 DCHECK_GT(resource->lock_for_read_count, 0);
670 DCHECK_EQ(resource->exported_count, 0);
671 resource->lock_for_read_count--;
674 const ResourceProvider::Resource* ResourceProvider::LockForWrite(
676 Resource* resource = GetResource(id);
677 DCHECK(!resource->locked_for_write);
678 DCHECK(!resource->lock_for_read_count);
679 DCHECK_EQ(resource->exported_count, 0);
680 DCHECK(!resource->external);
681 DCHECK(!resource->lost);
682 DCHECK(ReadLockFenceHasPassed(resource));
683 LazyAllocate(resource);
685 resource->locked_for_write = true;
689 bool ResourceProvider::CanLockForWrite(ResourceId id) {
690 Resource* resource = GetResource(id);
691 return !resource->locked_for_write && !resource->lock_for_read_count &&
692 !resource->exported_count && !resource->external && !resource->lost &&
693 ReadLockFenceHasPassed(resource);
696 void ResourceProvider::UnlockForWrite(ResourceId id) {
697 Resource* resource = GetResource(id);
698 DCHECK(resource->locked_for_write);
699 DCHECK_EQ(resource->exported_count, 0);
700 DCHECK(!resource->external);
701 resource->locked_for_write = false;
704 ResourceProvider::ScopedReadLockGL::ScopedReadLockGL(
705 ResourceProvider* resource_provider,
706 ResourceProvider::ResourceId resource_id)
707 : resource_provider_(resource_provider),
708 resource_id_(resource_id),
709 texture_id_(resource_provider->LockForRead(resource_id)->gl_id) {
713 ResourceProvider::ScopedReadLockGL::~ScopedReadLockGL() {
714 resource_provider_->UnlockForRead(resource_id_);
717 ResourceProvider::ScopedSamplerGL::ScopedSamplerGL(
718 ResourceProvider* resource_provider,
719 ResourceProvider::ResourceId resource_id,
722 : ScopedReadLockGL(resource_provider, resource_id),
725 resource_provider->BindForSampling(resource_id, target, unit_, filter);
728 ResourceProvider::ScopedSamplerGL::ScopedSamplerGL(
729 ResourceProvider* resource_provider,
730 ResourceProvider::ResourceId resource_id,
734 : ScopedReadLockGL(resource_provider, resource_id),
737 resource_provider->BindForSampling(resource_id, target, unit, filter);
740 ResourceProvider::ScopedSamplerGL::~ScopedSamplerGL() {
743 ResourceProvider::ScopedWriteLockGL::ScopedWriteLockGL(
744 ResourceProvider* resource_provider,
745 ResourceProvider::ResourceId resource_id)
746 : resource_provider_(resource_provider),
747 resource_id_(resource_id),
748 texture_id_(resource_provider->LockForWrite(resource_id)->gl_id) {
752 ResourceProvider::ScopedWriteLockGL::~ScopedWriteLockGL() {
753 resource_provider_->UnlockForWrite(resource_id_);
756 void ResourceProvider::PopulateSkBitmapWithResource(
757 SkBitmap* sk_bitmap, const Resource* resource) {
758 DCHECK(resource->pixels);
759 DCHECK_EQ(RGBA_8888, resource->format);
760 sk_bitmap->setConfig(SkBitmap::kARGB_8888_Config,
761 resource->size.width(),
762 resource->size.height());
763 sk_bitmap->setPixels(resource->pixels);
766 ResourceProvider::ScopedReadLockSoftware::ScopedReadLockSoftware(
767 ResourceProvider* resource_provider,
768 ResourceProvider::ResourceId resource_id)
769 : resource_provider_(resource_provider),
770 resource_id_(resource_id) {
771 ResourceProvider::PopulateSkBitmapWithResource(
772 &sk_bitmap_, resource_provider->LockForRead(resource_id));
775 ResourceProvider::ScopedReadLockSoftware::~ScopedReadLockSoftware() {
776 resource_provider_->UnlockForRead(resource_id_);
779 ResourceProvider::ScopedWriteLockSoftware::ScopedWriteLockSoftware(
780 ResourceProvider* resource_provider,
781 ResourceProvider::ResourceId resource_id)
782 : resource_provider_(resource_provider),
783 resource_id_(resource_id) {
784 ResourceProvider::PopulateSkBitmapWithResource(
785 &sk_bitmap_, resource_provider->LockForWrite(resource_id));
786 sk_canvas_.reset(new SkCanvas(sk_bitmap_));
789 ResourceProvider::ScopedWriteLockSoftware::~ScopedWriteLockSoftware() {
790 resource_provider_->UnlockForWrite(resource_id_);
793 ResourceProvider::ResourceProvider(OutputSurface* output_surface,
794 SharedBitmapManager* shared_bitmap_manager,
795 int highp_threshold_min,
796 bool use_rgba_4444_texture_format,
797 size_t texture_id_allocation_chunk_size)
798 : output_surface_(output_surface),
799 shared_bitmap_manager_(shared_bitmap_manager),
800 lost_output_surface_(false),
801 highp_threshold_min_(highp_threshold_min),
804 default_resource_type_(InvalidType),
805 use_texture_storage_ext_(false),
806 use_texture_usage_hint_(false),
807 use_shallow_flush_(false),
808 max_texture_size_(0),
809 best_texture_format_(RGBA_8888),
810 use_rgba_4444_texture_format_(use_rgba_4444_texture_format),
811 texture_id_allocation_chunk_size_(texture_id_allocation_chunk_size) {
812 DCHECK(output_surface_->HasClient());
813 DCHECK(texture_id_allocation_chunk_size_);
816 void ResourceProvider::InitializeSoftware() {
817 DCHECK(thread_checker_.CalledOnValidThread());
818 DCHECK_NE(Bitmap, default_resource_type_);
822 default_resource_type_ = Bitmap;
823 max_texture_size_ = INT_MAX / 2;
824 best_texture_format_ = RGBA_8888;
827 bool ResourceProvider::InitializeGL() {
828 DCHECK(thread_checker_.CalledOnValidThread());
829 DCHECK(!texture_uploader_);
830 DCHECK_NE(GLTexture, default_resource_type_);
832 WebGraphicsContext3D* context3d = Context3d();
835 if (!context3d->makeContextCurrent())
838 default_resource_type_ = GLTexture;
840 const ContextProvider::Capabilities& caps =
841 output_surface_->context_provider()->ContextCapabilities();
843 bool use_map_sub = caps.map_sub;
844 bool use_bgra = caps.texture_format_bgra8888;
845 use_texture_storage_ext_ = caps.texture_storage;
846 use_shallow_flush_ = caps.shallow_flush;
847 use_texture_usage_hint_ = caps.texture_usage;
848 use_compressed_texture_etc1_ = caps.texture_format_etc1;
851 TextureUploader::Create(context3d, use_map_sub, use_shallow_flush_);
852 GLC(context3d, context3d->getIntegerv(GL_MAX_TEXTURE_SIZE,
853 &max_texture_size_));
854 best_texture_format_ = PlatformColor::BestTextureFormat(use_bgra);
859 void ResourceProvider::CleanUpGLIfNeeded() {
860 WebGraphicsContext3D* context3d = Context3d();
861 if (default_resource_type_ != GLTexture) {
862 // We are not in GL mode, but double check before returning.
864 DCHECK(!texture_uploader_);
869 context3d->makeContextCurrent();
870 texture_uploader_.reset();
871 if (!unused_texture_ids_.empty()) {
872 size_t size = unused_texture_ids_.size();
873 scoped_ptr<WebKit::WebGLId[]> ids(new WebKit::WebGLId[size]);
874 for (size_t i = 0; i < size; ++i)
875 ids[i] = unused_texture_ids_[i];
876 GLC(context3d, context3d->deleteTextures(size, ids.get()));
877 unused_texture_ids_.clear();
882 int ResourceProvider::CreateChild(const ReturnCallback& return_callback) {
883 DCHECK(thread_checker_.CalledOnValidThread());
886 child_info.return_callback = return_callback;
888 int child = next_child_++;
889 children_[child] = child_info;
893 void ResourceProvider::DestroyChild(int child_id) {
894 DCHECK(thread_checker_.CalledOnValidThread());
896 ChildMap::iterator it = children_.find(child_id);
897 DCHECK(it != children_.end());
898 Child& child = it->second;
900 ResourceIdArray resources_for_child;
902 for (ResourceIdMap::iterator child_it = child.child_to_parent_map.begin();
903 child_it != child.child_to_parent_map.end();
905 ResourceId id = child_it->second;
906 resources_for_child.push_back(id);
909 // If the child is going away, don't consider any resources in use.
910 child.in_use_resources.clear();
912 DeleteAndReturnUnusedResourcesToChild(
913 &child, ForShutdown, resources_for_child);
918 const ResourceProvider::ResourceIdMap& ResourceProvider::GetChildToParentMap(
920 DCHECK(thread_checker_.CalledOnValidThread());
921 ChildMap::const_iterator it = children_.find(child);
922 DCHECK(it != children_.end());
923 return it->second.child_to_parent_map;
926 void ResourceProvider::PrepareSendToParent(const ResourceIdArray& resources,
927 TransferableResourceArray* list) {
928 DCHECK(thread_checker_.CalledOnValidThread());
929 WebGraphicsContext3D* context3d = Context3d();
931 context3d->makeContextCurrent();
932 bool need_sync_point = false;
933 for (ResourceIdArray::const_iterator it = resources.begin();
934 it != resources.end();
936 TransferableResource resource;
937 TransferResource(context3d, *it, &resource);
938 if (!resource.sync_point && !resource.is_software)
939 need_sync_point = true;
940 ++resources_.find(*it)->second.exported_count;
941 list->push_back(resource);
943 if (need_sync_point) {
944 unsigned int sync_point = context3d->insertSyncPoint();
945 for (TransferableResourceArray::iterator it = list->begin();
949 it->sync_point = sync_point;
954 void ResourceProvider::ReceiveFromChild(
955 int child, const TransferableResourceArray& resources) {
956 DCHECK(thread_checker_.CalledOnValidThread());
957 WebGraphicsContext3D* context3d = Context3d();
959 context3d->makeContextCurrent();
960 Child& child_info = children_.find(child)->second;
961 for (TransferableResourceArray::const_iterator it = resources.begin();
962 it != resources.end();
964 ResourceIdMap::iterator resource_in_map_it =
965 child_info.child_to_parent_map.find(it->id);
966 if (resource_in_map_it != child_info.child_to_parent_map.end()) {
967 resources_[resource_in_map_it->second].imported_count++;
971 scoped_ptr<SharedBitmap> bitmap;
972 uint8_t* pixels = NULL;
973 if (it->is_software) {
974 if (shared_bitmap_manager_)
975 bitmap = shared_bitmap_manager_->GetSharedBitmapFromId(it->size,
978 pixels = bitmap->pixels();
981 if ((!it->is_software && !context3d) || (it->is_software && !pixels)) {
982 TRACE_EVENT0("cc", "ResourceProvider::ReceiveFromChild dropping invalid");
983 ReturnedResourceArray to_return;
984 to_return.push_back(it->ToReturnedResource());
985 child_info.return_callback.Run(to_return);
989 ResourceId local_id = next_id_++;
990 Resource& resource = resources_[local_id];
991 if (it->is_software) {
993 pixels, bitmap.release(), it->size, GL_LINEAR, GL_CLAMP_TO_EDGE);
996 // NOTE: If the parent is a browser and the child a renderer, the parent
997 // is not supposed to have its context wait, because that could induce
998 // deadlocks and/or security issues. The caller is responsible for
999 // waiting asynchronously, and resetting sync_point before calling this.
1000 // However if the parent is a renderer (e.g. browser tag), it may be ok
1001 // (and is simpler) to wait.
1003 GLC(context3d, context3d->waitSyncPoint(it->sync_point));
1004 texture_id = NextTextureId();
1005 GLC(context3d, context3d->bindTexture(it->target, texture_id));
1007 context3d->consumeTextureCHROMIUM(it->target, it->mailbox.name));
1008 resource = Resource(texture_id,
1016 resource.mailbox.SetName(it->mailbox);
1018 resource.child_id = child;
1019 // Don't allocate a texture for a child.
1020 resource.allocated = true;
1021 resource.imported_count = 1;
1022 child_info.parent_to_child_map[local_id] = it->id;
1023 child_info.child_to_parent_map[it->id] = local_id;
1027 void ResourceProvider::DeclareUsedResourcesFromChild(
1029 const ResourceIdArray& resources_from_child) {
1030 DCHECK(thread_checker_.CalledOnValidThread());
1032 Child& child_info = children_.find(child)->second;
1033 child_info.in_use_resources.clear();
1035 for (size_t i = 0; i < resources_from_child.size(); ++i) {
1036 ResourceIdMap::iterator it =
1037 child_info.child_to_parent_map.find(resources_from_child[i]);
1038 DCHECK(it != child_info.child_to_parent_map.end());
1040 ResourceId local_id = it->second;
1041 child_info.in_use_resources.insert(local_id);
1044 ResourceIdArray unused;
1045 for (ResourceIdMap::iterator it = child_info.child_to_parent_map.begin();
1046 it != child_info.child_to_parent_map.end();
1048 ResourceId local_id = it->second;
1049 bool resource_is_in_use = child_info.in_use_resources.count(local_id) > 0;
1050 if (!resource_is_in_use)
1051 unused.push_back(local_id);
1053 DeleteAndReturnUnusedResourcesToChild(&child_info, Normal, unused);
1057 bool ResourceProvider::CompareResourceMapIteratorsByChildId(
1058 const std::pair<ReturnedResource, ResourceMap::iterator>& a,
1059 const std::pair<ReturnedResource, ResourceMap::iterator>& b) {
1060 const ResourceMap::iterator& a_it = a.second;
1061 const ResourceMap::iterator& b_it = b.second;
1062 const Resource& a_resource = a_it->second;
1063 const Resource& b_resource = b_it->second;
1064 return a_resource.child_id < b_resource.child_id;
1067 void ResourceProvider::ReceiveReturnsFromParent(
1068 const ReturnedResourceArray& resources) {
1069 DCHECK(thread_checker_.CalledOnValidThread());
1070 WebGraphicsContext3D* context3d = Context3d();
1072 context3d->makeContextCurrent();
1075 Child* child_info = NULL;
1076 ResourceIdArray resources_for_child;
1078 std::vector<std::pair<ReturnedResource, ResourceMap::iterator> >
1081 for (ReturnedResourceArray::const_iterator it = resources.begin();
1082 it != resources.end();
1084 ResourceId local_id = it->id;
1085 ResourceMap::iterator map_iterator = resources_.find(local_id);
1087 // Resource was already lost (e.g. it belonged to a child that was
1089 if (map_iterator == resources_.end())
1092 sorted_resources.push_back(
1093 std::pair<ReturnedResource, ResourceMap::iterator>(*it, map_iterator));
1096 std::sort(sorted_resources.begin(),
1097 sorted_resources.end(),
1098 CompareResourceMapIteratorsByChildId);
1100 for (size_t i = 0; i < sorted_resources.size(); ++i) {
1101 ReturnedResource& returned = sorted_resources[i].first;
1102 ResourceMap::iterator& map_iterator = sorted_resources[i].second;
1103 ResourceId local_id = map_iterator->first;
1104 Resource* resource = &map_iterator->second;
1106 CHECK_GE(resource->exported_count, returned.count);
1107 resource->exported_count -= returned.count;
1108 resource->lost |= returned.lost;
1109 if (resource->exported_count)
1112 if (resource->gl_id) {
1113 if (returned.sync_point)
1114 GLC(context3d, context3d->waitSyncPoint(returned.sync_point));
1115 } else if (!resource->shared_bitmap) {
1117 TextureMailbox(resource->mailbox.name(), returned.sync_point);
1120 if (!resource->marked_for_deletion)
1123 if (!resource->child_id) {
1124 // The resource belongs to this ResourceProvider, so it can be destroyed.
1125 DeleteResourceInternal(map_iterator, Normal);
1129 // Delete the resource and return it to the child it came from one.
1130 if (resource->child_id != child_id) {
1131 ChildMap::iterator child_it = children_.find(resource->child_id);
1132 DCHECK(child_it != children_.end());
1135 DCHECK_NE(resources_for_child.size(), 0u);
1136 DeleteAndReturnUnusedResourcesToChild(
1137 child_info, Normal, resources_for_child);
1138 resources_for_child.clear();
1141 child_info = &child_it->second;
1142 child_id = resource->child_id;
1144 resources_for_child.push_back(local_id);
1148 DCHECK_NE(resources_for_child.size(), 0u);
1149 DeleteAndReturnUnusedResourcesToChild(
1150 child_info, Normal, resources_for_child);
1154 void ResourceProvider::TransferResource(WebGraphicsContext3D* context,
1156 TransferableResource* resource) {
1157 Resource* source = GetResource(id);
1158 DCHECK(!source->locked_for_write);
1159 DCHECK(!source->lock_for_read_count);
1160 DCHECK(!source->external || (source->external && source->mailbox.IsValid()));
1161 DCHECK(source->allocated);
1163 resource->format = source->format;
1164 resource->target = source->target;
1165 resource->filter = source->filter;
1166 resource->size = source->size;
1168 if (source->shared_bitmap) {
1169 resource->mailbox = source->shared_bitmap->id();
1170 resource->is_software = true;
1171 } else if (!source->mailbox.IsValid()) {
1172 // This is a resource allocated by the compositor, we need to produce it.
1173 // Don't set a sync point, the caller will do it.
1174 DCHECK(source->gl_id);
1175 GLC(context, context->bindTexture(resource->target, source->gl_id));
1176 GLC(context, context->genMailboxCHROMIUM(resource->mailbox.name));
1178 context->produceTextureCHROMIUM(resource->target,
1179 resource->mailbox.name));
1180 source->mailbox.SetName(resource->mailbox);
1182 DCHECK(source->mailbox.IsTexture());
1183 // This is either an external resource, or a compositor resource that we
1184 // already exported. Make sure to forward the sync point that we were given.
1185 resource->mailbox = source->mailbox.name();
1186 resource->sync_point = source->mailbox.sync_point();
1187 source->mailbox.ResetSyncPoint();
1191 void ResourceProvider::DeleteAndReturnUnusedResourcesToChild(
1194 const ResourceIdArray& unused) {
1195 DCHECK(thread_checker_.CalledOnValidThread());
1201 WebGraphicsContext3D* context3d = Context3d();
1203 context3d->makeContextCurrent();
1205 ReturnedResourceArray to_return;
1207 bool need_sync_point = false;
1208 for (size_t i = 0; i < unused.size(); ++i) {
1209 ResourceId local_id = unused[i];
1211 ResourceMap::iterator it = resources_.find(local_id);
1212 CHECK(it != resources_.end());
1213 Resource& resource = it->second;
1215 DCHECK(!resource.locked_for_write);
1216 DCHECK(!resource.lock_for_read_count);
1217 DCHECK_EQ(0u, child_info->in_use_resources.count(local_id));
1218 DCHECK(child_info->parent_to_child_map.count(local_id));
1220 ResourceId child_id = child_info->parent_to_child_map[local_id];
1221 DCHECK(child_info->child_to_parent_map.count(child_id));
1224 resource.lost || (!resource.shared_bitmap && lost_output_surface_);
1225 if (resource.exported_count > 0) {
1226 if (style != ForShutdown) {
1227 // Defer this until we receive the resource back from the parent.
1228 resource.marked_for_deletion = true;
1232 // We still have an exported_count, so we'll have to lose it.
1236 if (context3d && resource.filter != resource.original_filter) {
1237 DCHECK(resource.target);
1238 DCHECK(resource.gl_id);
1240 GLC(context3d, context3d->bindTexture(resource.target, resource.gl_id));
1242 context3d->texParameteri(resource.target,
1243 GL_TEXTURE_MIN_FILTER,
1244 resource.original_filter));
1246 context3d->texParameteri(resource.target,
1247 GL_TEXTURE_MAG_FILTER,
1248 resource.original_filter));
1251 ReturnedResource returned;
1252 returned.id = child_id;
1253 returned.sync_point = resource.mailbox.sync_point();
1254 if (!returned.sync_point && !resource.shared_bitmap)
1255 need_sync_point = true;
1256 returned.count = resource.imported_count;
1257 returned.lost = is_lost;
1258 to_return.push_back(returned);
1260 child_info->parent_to_child_map.erase(local_id);
1261 child_info->child_to_parent_map.erase(child_id);
1262 resource.imported_count = 0;
1263 DeleteResourceInternal(it, style);
1265 if (need_sync_point) {
1267 unsigned int sync_point = context3d->insertSyncPoint();
1268 for (size_t i = 0; i < to_return.size(); ++i) {
1269 if (!to_return[i].sync_point)
1270 to_return[i].sync_point = sync_point;
1274 if (!to_return.empty())
1275 child_info->return_callback.Run(to_return);
1278 void ResourceProvider::AcquirePixelBuffer(ResourceId id) {
1279 Resource* resource = GetResource(id);
1280 DCHECK(!resource->external);
1281 DCHECK_EQ(resource->exported_count, 0);
1282 DCHECK(!resource->image_id);
1283 DCHECK_NE(ETC1, resource->format);
1285 if (resource->type == GLTexture) {
1286 WebGraphicsContext3D* context3d = Context3d();
1288 if (!resource->gl_pixel_buffer_id)
1289 resource->gl_pixel_buffer_id = context3d->createBuffer();
1290 context3d->bindBuffer(
1291 GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM,
1292 resource->gl_pixel_buffer_id);
1293 unsigned bytes_per_pixel = BitsPerPixel(resource->format) / 8;
1294 context3d->bufferData(
1295 GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM,
1296 resource->size.height() * RoundUp(bytes_per_pixel
1297 * resource->size.width(), 4u),
1300 context3d->bindBuffer(GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM, 0);
1303 if (resource->pixels) {
1304 if (resource->pixel_buffer)
1307 resource->pixel_buffer = new uint8_t[4 * resource->size.GetArea()];
1311 void ResourceProvider::ReleasePixelBuffer(ResourceId id) {
1312 Resource* resource = GetResource(id);
1313 DCHECK(!resource->external);
1314 DCHECK_EQ(resource->exported_count, 0);
1315 DCHECK(!resource->image_id);
1317 // The pixel buffer can be released while there is a pending "set pixels"
1318 // if completion has been forced. Any shared memory associated with this
1319 // pixel buffer will not be freed until the waitAsyncTexImage2DCHROMIUM
1320 // command has been processed on the service side. It is also safe to
1321 // reuse any query id associated with this resource before they complete
1322 // as each new query has a unique submit count.
1323 if (resource->pending_set_pixels) {
1324 DCHECK(resource->set_pixels_completion_forced);
1325 resource->pending_set_pixels = false;
1329 if (resource->type == GLTexture) {
1330 if (!resource->gl_pixel_buffer_id)
1332 WebGraphicsContext3D* context3d = Context3d();
1334 context3d->bindBuffer(
1335 GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM,
1336 resource->gl_pixel_buffer_id);
1337 context3d->bufferData(
1338 GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM,
1342 context3d->bindBuffer(GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM, 0);
1345 if (resource->pixels) {
1346 if (!resource->pixel_buffer)
1348 delete[] resource->pixel_buffer;
1349 resource->pixel_buffer = NULL;
1353 uint8_t* ResourceProvider::MapPixelBuffer(ResourceId id) {
1354 Resource* resource = GetResource(id);
1355 DCHECK(!resource->external);
1356 DCHECK_EQ(resource->exported_count, 0);
1357 DCHECK(!resource->image_id);
1359 if (resource->type == GLTexture) {
1360 WebGraphicsContext3D* context3d = Context3d();
1362 DCHECK(resource->gl_pixel_buffer_id);
1363 context3d->bindBuffer(
1364 GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM,
1365 resource->gl_pixel_buffer_id);
1366 uint8_t* image = static_cast<uint8_t*>(
1367 context3d->mapBufferCHROMIUM(
1368 GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM, GL_WRITE_ONLY));
1369 context3d->bindBuffer(GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM, 0);
1370 // Buffer is required to be 4-byte aligned.
1371 CHECK(!(reinterpret_cast<intptr_t>(image) & 3));
1375 if (resource->pixels)
1376 return resource->pixel_buffer;
1381 void ResourceProvider::UnmapPixelBuffer(ResourceId id) {
1382 Resource* resource = GetResource(id);
1383 DCHECK(!resource->external);
1384 DCHECK_EQ(resource->exported_count, 0);
1385 DCHECK(!resource->image_id);
1387 if (resource->type == GLTexture) {
1388 WebGraphicsContext3D* context3d = Context3d();
1390 DCHECK(resource->gl_pixel_buffer_id);
1391 context3d->bindBuffer(
1392 GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM,
1393 resource->gl_pixel_buffer_id);
1394 context3d->unmapBufferCHROMIUM(GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM);
1395 context3d->bindBuffer(GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM, 0);
1399 void ResourceProvider::BindForSampling(ResourceProvider::ResourceId resource_id,
1403 DCHECK(thread_checker_.CalledOnValidThread());
1404 WebGraphicsContext3D* context3d = Context3d();
1405 ResourceMap::iterator it = resources_.find(resource_id);
1406 DCHECK(it != resources_.end());
1407 Resource* resource = &it->second;
1408 DCHECK(resource->lock_for_read_count);
1409 DCHECK(!resource->locked_for_write || resource->set_pixels_completion_forced);
1411 ScopedSetActiveTexture scoped_active_tex(context3d, unit);
1412 GLC(context3d, context3d->bindTexture(target, resource->gl_id));
1413 if (filter != resource->filter) {
1414 DCHECK_EQ(resource->target, target);
1416 context3d->texParameteri(target, GL_TEXTURE_MIN_FILTER, filter));
1418 context3d->texParameteri(target, GL_TEXTURE_MAG_FILTER, filter));
1419 resource->filter = filter;
1422 if (resource->image_id && resource->dirty_image) {
1423 // Release image currently bound to texture.
1424 if (resource->bound_image_id)
1425 context3d->releaseTexImage2DCHROMIUM(target, resource->bound_image_id);
1426 context3d->bindTexImage2DCHROMIUM(target, resource->image_id);
1427 resource->bound_image_id = resource->image_id;
1428 resource->dirty_image = false;
1432 void ResourceProvider::BeginSetPixels(ResourceId id) {
1433 Resource* resource = GetResource(id);
1434 DCHECK(!resource->pending_set_pixels);
1436 LazyCreate(resource);
1437 DCHECK(resource->gl_id || resource->allocated);
1438 DCHECK(ReadLockFenceHasPassed(resource));
1439 DCHECK(!resource->image_id);
1441 bool allocate = !resource->allocated;
1442 resource->allocated = true;
1445 if (resource->gl_id) {
1446 WebGraphicsContext3D* context3d = Context3d();
1448 DCHECK(resource->gl_pixel_buffer_id);
1449 DCHECK_EQ(resource->target, static_cast<GLenum>(GL_TEXTURE_2D));
1450 context3d->bindTexture(GL_TEXTURE_2D, resource->gl_id);
1451 context3d->bindBuffer(
1452 GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM,
1453 resource->gl_pixel_buffer_id);
1454 if (!resource->gl_upload_query_id)
1455 resource->gl_upload_query_id = context3d->createQueryEXT();
1456 context3d->beginQueryEXT(
1457 GL_ASYNC_PIXEL_UNPACK_COMPLETED_CHROMIUM,
1458 resource->gl_upload_query_id);
1460 context3d->asyncTexImage2DCHROMIUM(
1463 GLInternalFormat(resource->format),
1464 resource->size.width(),
1465 resource->size.height(),
1467 GLDataFormat(resource->format),
1468 GLDataType(resource->format),
1471 context3d->asyncTexSubImage2DCHROMIUM(
1476 resource->size.width(),
1477 resource->size.height(),
1478 GLDataFormat(resource->format),
1479 GLDataType(resource->format),
1482 context3d->endQueryEXT(GL_ASYNC_PIXEL_UNPACK_COMPLETED_CHROMIUM);
1483 context3d->bindBuffer(GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM, 0);
1486 if (resource->pixels) {
1487 DCHECK(!resource->mailbox.IsValid());
1488 DCHECK(resource->pixel_buffer);
1489 DCHECK_EQ(RGBA_8888, resource->format);
1491 std::swap(resource->pixels, resource->pixel_buffer);
1492 delete[] resource->pixel_buffer;
1493 resource->pixel_buffer = NULL;
1496 resource->pending_set_pixels = true;
1497 resource->set_pixels_completion_forced = false;
1500 void ResourceProvider::ForceSetPixelsToComplete(ResourceId id) {
1501 Resource* resource = GetResource(id);
1502 DCHECK(resource->locked_for_write);
1503 DCHECK(resource->pending_set_pixels);
1504 DCHECK(!resource->set_pixels_completion_forced);
1506 if (resource->gl_id) {
1507 WebGraphicsContext3D* context3d = Context3d();
1508 GLC(context3d, context3d->bindTexture(GL_TEXTURE_2D, resource->gl_id));
1509 GLC(context3d, context3d->waitAsyncTexImage2DCHROMIUM(GL_TEXTURE_2D));
1510 GLC(context3d, context3d->bindTexture(GL_TEXTURE_2D, 0));
1513 resource->set_pixels_completion_forced = true;
1516 bool ResourceProvider::DidSetPixelsComplete(ResourceId id) {
1517 Resource* resource = GetResource(id);
1518 DCHECK(resource->locked_for_write);
1519 DCHECK(resource->pending_set_pixels);
1521 if (resource->gl_id) {
1522 WebGraphicsContext3D* context3d = Context3d();
1524 DCHECK(resource->gl_upload_query_id);
1525 unsigned complete = 1;
1526 context3d->getQueryObjectuivEXT(
1527 resource->gl_upload_query_id,
1528 GL_QUERY_RESULT_AVAILABLE_EXT,
1534 resource->pending_set_pixels = false;
1540 void ResourceProvider::CreateForTesting(ResourceId id) {
1541 LazyCreate(GetResource(id));
1544 GLint ResourceProvider::WrapModeForTesting(ResourceId id) {
1545 Resource* resource = GetResource(id);
1546 return resource->wrap_mode;
1549 GLenum ResourceProvider::TargetForTesting(ResourceId id) {
1550 Resource* resource = GetResource(id);
1551 return resource->target;
1554 void ResourceProvider::LazyCreate(Resource* resource) {
1555 if (resource->type != GLTexture || resource->gl_id != 0)
1558 // Early out for resources that don't require texture creation.
1559 if (resource->texture_pool == 0)
1562 resource->gl_id = NextTextureId();
1564 WebGraphicsContext3D* context3d = Context3d();
1567 // Create and set texture properties. Allocation is delayed until needed.
1568 GLC(context3d, context3d->bindTexture(resource->target, resource->gl_id));
1570 context3d->texParameteri(
1571 resource->target, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
1573 context3d->texParameteri(
1574 resource->target, GL_TEXTURE_MAG_FILTER, GL_LINEAR));
1576 context3d->texParameteri(
1577 resource->target, GL_TEXTURE_WRAP_S, resource->wrap_mode));
1579 context3d->texParameteri(
1580 resource->target, GL_TEXTURE_WRAP_T, resource->wrap_mode));
1582 context3d->texParameteri(
1583 resource->target, GL_TEXTURE_POOL_CHROMIUM, resource->texture_pool));
1584 if (use_texture_usage_hint_ && resource->hint == TextureUsageFramebuffer) {
1586 context3d->texParameteri(resource->target,
1587 GL_TEXTURE_USAGE_ANGLE,
1588 GL_FRAMEBUFFER_ATTACHMENT_ANGLE));
1592 void ResourceProvider::AllocateForTesting(ResourceId id) {
1593 LazyAllocate(GetResource(id));
1596 void ResourceProvider::LazyAllocate(Resource* resource) {
1598 LazyCreate(resource);
1600 DCHECK(resource->gl_id || resource->allocated);
1601 if (resource->allocated || !resource->gl_id)
1603 resource->allocated = true;
1604 WebGraphicsContext3D* context3d = Context3d();
1605 gfx::Size& size = resource->size;
1606 DCHECK_EQ(resource->target, static_cast<GLenum>(GL_TEXTURE_2D));
1607 ResourceFormat format = resource->format;
1608 GLC(context3d, context3d->bindTexture(GL_TEXTURE_2D, resource->gl_id));
1609 if (use_texture_storage_ext_ && IsFormatSupportedForStorage(format)) {
1610 GLenum storage_format = TextureToStorageFormat(format);
1611 GLC(context3d, context3d->texStorage2DEXT(GL_TEXTURE_2D,
1617 // ETC1 does not support preallocation.
1618 if (format != ETC1) {
1620 context3d->texImage2D(GL_TEXTURE_2D,
1622 GLInternalFormat(format),
1626 GLDataFormat(format),
1633 void ResourceProvider::EnableReadLockFences(ResourceProvider::ResourceId id,
1635 Resource* resource = GetResource(id);
1636 resource->enable_read_lock_fences = enable;
1639 void ResourceProvider::AcquireImage(ResourceId id) {
1640 Resource* resource = GetResource(id);
1641 DCHECK(!resource->external);
1642 DCHECK_EQ(resource->exported_count, 0);
1644 if (resource->type != GLTexture)
1647 if (resource->image_id)
1650 resource->allocated = true;
1651 WebGraphicsContext3D* context3d = Context3d();
1653 DCHECK_EQ(RGBA_8888, resource->format);
1654 resource->image_id = context3d->createImageCHROMIUM(
1655 resource->size.width(), resource->size.height(), GL_RGBA8_OES);
1656 DCHECK(resource->image_id);
1659 void ResourceProvider::ReleaseImage(ResourceId id) {
1660 Resource* resource = GetResource(id);
1661 DCHECK(!resource->external);
1662 DCHECK_EQ(resource->exported_count, 0);
1664 if (!resource->image_id)
1667 WebGraphicsContext3D* context3d = Context3d();
1669 context3d->destroyImageCHROMIUM(resource->image_id);
1670 resource->image_id = 0;
1671 resource->bound_image_id = 0;
1672 resource->dirty_image = false;
1673 resource->allocated = false;
1676 uint8_t* ResourceProvider::MapImage(ResourceId id) {
1677 Resource* resource = GetResource(id);
1678 DCHECK(ReadLockFenceHasPassed(resource));
1679 DCHECK(!resource->external);
1680 DCHECK_EQ(resource->exported_count, 0);
1682 if (resource->image_id) {
1683 WebGraphicsContext3D* context3d = Context3d();
1685 return static_cast<uint8_t*>(
1686 context3d->mapImageCHROMIUM(resource->image_id, GL_READ_WRITE));
1689 if (resource->pixels)
1690 return resource->pixels;
1695 void ResourceProvider::UnmapImage(ResourceId id) {
1696 Resource* resource = GetResource(id);
1697 DCHECK(!resource->external);
1698 DCHECK_EQ(resource->exported_count, 0);
1700 if (resource->image_id) {
1701 WebGraphicsContext3D* context3d = Context3d();
1703 context3d->unmapImageCHROMIUM(resource->image_id);
1704 resource->dirty_image = true;
1708 int ResourceProvider::GetImageStride(ResourceId id) {
1709 Resource* resource = GetResource(id);
1710 DCHECK(!resource->external);
1711 DCHECK_EQ(resource->exported_count, 0);
1715 if (resource->image_id) {
1716 WebGraphicsContext3D* context3d = Context3d();
1718 context3d->getImageParameterivCHROMIUM(
1719 resource->image_id, GL_IMAGE_ROWBYTES_CHROMIUM, &stride);
1725 base::SharedMemory* ResourceProvider::GetSharedMemory(ResourceId id) {
1726 Resource* resource = GetResource(id);
1727 DCHECK(!resource->external);
1728 DCHECK_EQ(resource->exported_count, 0);
1730 if (!resource->shared_bitmap)
1732 return resource->shared_bitmap->memory();
1735 GLint ResourceProvider::GetActiveTextureUnit(WebGraphicsContext3D* context) {
1736 GLint active_unit = 0;
1737 context->getIntegerv(GL_ACTIVE_TEXTURE, &active_unit);
1741 WebKit::WebGraphicsContext3D* ResourceProvider::Context3d() const {
1742 ContextProvider* context_provider = output_surface_->context_provider();
1743 return context_provider ? context_provider->Context3d() : NULL;
1746 unsigned ResourceProvider::NextTextureId() {
1747 if (unused_texture_ids_.empty()) {
1748 size_t size = texture_id_allocation_chunk_size_;
1749 scoped_ptr<WebKit::WebGLId[]> ids(new WebKit::WebGLId[size]);
1750 WebGraphicsContext3D* context3d = Context3d();
1752 GLC(context3d, context3d->genTextures(size, ids.get()));
1753 unused_texture_ids_.assign(ids.get(), ids.get() + size);
1756 unsigned gl_id = unused_texture_ids_.front();
1757 unused_texture_ids_.pop_front();