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/atomic_sequence_num.h"
11 #include "base/containers/hash_tables.h"
12 #include "base/metrics/histogram.h"
13 #include "base/numerics/safe_math.h"
14 #include "base/stl_util.h"
15 #include "base/strings/string_split.h"
16 #include "base/strings/string_util.h"
17 #include "base/strings/stringprintf.h"
18 #include "base/thread_task_runner_handle.h"
19 #include "base/trace_event/memory_dump_manager.h"
20 #include "base/trace_event/trace_event.h"
21 #include "cc/resources/platform_color.h"
22 #include "cc/resources/resource_util.h"
23 #include "cc/resources/returned_resource.h"
24 #include "cc/resources/shared_bitmap_manager.h"
25 #include "cc/resources/transferable_resource.h"
26 #include "gpu/GLES2/gl2extchromium.h"
27 #include "gpu/command_buffer/client/gles2_interface.h"
28 #include "gpu/command_buffer/client/gpu_memory_buffer_manager.h"
29 #include "third_party/khronos/GLES2/gl2.h"
30 #include "third_party/khronos/GLES2/gl2ext.h"
31 #include "third_party/skia/include/core/SkSurface.h"
32 #include "third_party/skia/include/gpu/GrContext.h"
33 #include "third_party/skia/include/gpu/GrTextureProvider.h"
34 #include "ui/gfx/geometry/rect.h"
35 #include "ui/gfx/geometry/vector2d.h"
36 #include "ui/gl/trace_util.h"
38 using gpu::gles2::GLES2Interface
;
44 virtual ~IdAllocator() {}
46 virtual GLuint
NextId() = 0;
49 IdAllocator(GLES2Interface
* gl
, size_t id_allocation_chunk_size
)
51 id_allocation_chunk_size_(id_allocation_chunk_size
),
52 ids_(new GLuint
[id_allocation_chunk_size
]),
53 next_id_index_(id_allocation_chunk_size
) {
54 DCHECK(id_allocation_chunk_size_
);
55 DCHECK_LE(id_allocation_chunk_size_
,
56 static_cast<size_t>(std::numeric_limits
<int>::max()));
60 const size_t id_allocation_chunk_size_
;
61 scoped_ptr
<GLuint
[]> ids_
;
62 size_t next_id_index_
;
67 GLenum
TextureToStorageFormat(ResourceFormat format
) {
68 GLenum storage_format
= GL_RGBA8_OES
;
73 storage_format
= GL_BGRA8_EXT
;
85 return storage_format
;
88 bool IsFormatSupportedForStorage(ResourceFormat format
, bool use_bgra
) {
105 GrPixelConfig
ToGrPixelConfig(ResourceFormat format
) {
108 return kRGBA_8888_GrPixelConfig
;
110 return kBGRA_8888_GrPixelConfig
;
112 return kRGBA_4444_GrPixelConfig
;
116 DCHECK(false) << "Unsupported resource format.";
117 return kSkia8888_GrPixelConfig
;
120 class ScopedSetActiveTexture
{
122 ScopedSetActiveTexture(GLES2Interface
* gl
, GLenum unit
)
123 : gl_(gl
), unit_(unit
) {
124 DCHECK_EQ(GL_TEXTURE0
, ResourceProvider::GetActiveTextureUnit(gl_
));
126 if (unit_
!= GL_TEXTURE0
)
127 gl_
->ActiveTexture(unit_
);
130 ~ScopedSetActiveTexture() {
131 // Active unit being GL_TEXTURE0 is effectively the ground state.
132 if (unit_
!= GL_TEXTURE0
)
133 gl_
->ActiveTexture(GL_TEXTURE0
);
141 class TextureIdAllocator
: public IdAllocator
{
143 TextureIdAllocator(GLES2Interface
* gl
,
144 size_t texture_id_allocation_chunk_size
)
145 : IdAllocator(gl
, texture_id_allocation_chunk_size
) {}
146 ~TextureIdAllocator() override
{
148 static_cast<int>(id_allocation_chunk_size_
- next_id_index_
),
149 ids_
.get() + next_id_index_
);
152 // Overridden from IdAllocator:
153 GLuint
NextId() override
{
154 if (next_id_index_
== id_allocation_chunk_size_
) {
155 gl_
->GenTextures(static_cast<int>(id_allocation_chunk_size_
), ids_
.get());
159 return ids_
[next_id_index_
++];
163 DISALLOW_COPY_AND_ASSIGN(TextureIdAllocator
);
166 class BufferIdAllocator
: public IdAllocator
{
168 BufferIdAllocator(GLES2Interface
* gl
, size_t buffer_id_allocation_chunk_size
)
169 : IdAllocator(gl
, buffer_id_allocation_chunk_size
) {}
170 ~BufferIdAllocator() override
{
172 static_cast<int>(id_allocation_chunk_size_
- next_id_index_
),
173 ids_
.get() + next_id_index_
);
176 // Overridden from IdAllocator:
177 GLuint
NextId() override
{
178 if (next_id_index_
== id_allocation_chunk_size_
) {
179 gl_
->GenBuffers(static_cast<int>(id_allocation_chunk_size_
), ids_
.get());
183 return ids_
[next_id_index_
++];
187 DISALLOW_COPY_AND_ASSIGN(BufferIdAllocator
);
190 // Generates process-unique IDs to use for tracing a ResourceProvider's
192 base::StaticAtomicSequenceNumber g_next_resource_provider_tracing_id
;
196 ResourceProvider::Resource::~Resource() {}
198 ResourceProvider::Resource::Resource(GLuint texture_id
,
199 const gfx::Size
& size
,
206 ResourceFormat format
)
209 gl_pixel_buffer_id(0),
210 gl_upload_query_id(0),
211 gl_read_lock_query_id(0),
213 lock_for_read_count(0),
217 locked_for_write(false),
219 marked_for_deletion(false),
220 pending_set_pixels(false),
221 set_pixels_completion_forced(false),
223 read_lock_fences_enabled(false),
224 has_shared_bitmap_id(false),
225 read_lock_fence(NULL
),
229 original_filter(filter
),
233 texture_pool(texture_pool
),
234 wrap_mode(wrap_mode
),
236 type(RESOURCE_TYPE_GL_TEXTURE
),
239 gpu_memory_buffer(NULL
) {
240 DCHECK(wrap_mode
== GL_CLAMP_TO_EDGE
|| wrap_mode
== GL_REPEAT
);
241 DCHECK_EQ(origin
== INTERNAL
, !!texture_pool
);
244 ResourceProvider::Resource::Resource(uint8_t* pixels
,
245 SharedBitmap
* bitmap
,
246 const gfx::Size
& size
,
252 gl_pixel_buffer_id(0),
253 gl_upload_query_id(0),
254 gl_read_lock_query_id(0),
256 lock_for_read_count(0),
260 locked_for_write(false),
262 marked_for_deletion(false),
263 pending_set_pixels(false),
264 set_pixels_completion_forced(false),
266 read_lock_fences_enabled(false),
267 has_shared_bitmap_id(!!bitmap
),
268 read_lock_fence(NULL
),
272 original_filter(filter
),
277 wrap_mode(wrap_mode
),
278 hint(TEXTURE_HINT_IMMUTABLE
),
279 type(RESOURCE_TYPE_BITMAP
),
281 shared_bitmap(bitmap
),
282 gpu_memory_buffer(NULL
) {
283 DCHECK(wrap_mode
== GL_CLAMP_TO_EDGE
|| wrap_mode
== GL_REPEAT
);
284 DCHECK(origin
== DELEGATED
|| pixels
);
286 shared_bitmap_id
= bitmap
->id();
289 ResourceProvider::Resource::Resource(const SharedBitmapId
& bitmap_id
,
290 const gfx::Size
& size
,
296 gl_pixel_buffer_id(0),
297 gl_upload_query_id(0),
298 gl_read_lock_query_id(0),
300 lock_for_read_count(0),
304 locked_for_write(false),
306 marked_for_deletion(false),
307 pending_set_pixels(false),
308 set_pixels_completion_forced(false),
310 read_lock_fences_enabled(false),
311 has_shared_bitmap_id(true),
312 read_lock_fence(NULL
),
316 original_filter(filter
),
321 wrap_mode(wrap_mode
),
322 hint(TEXTURE_HINT_IMMUTABLE
),
323 type(RESOURCE_TYPE_BITMAP
),
325 shared_bitmap_id(bitmap_id
),
327 gpu_memory_buffer(NULL
) {
328 DCHECK(wrap_mode
== GL_CLAMP_TO_EDGE
|| wrap_mode
== GL_REPEAT
);
331 ResourceProvider::Child::Child()
332 : marked_for_deletion(false), needs_sync_points(true) {
335 ResourceProvider::Child::~Child() {}
337 scoped_ptr
<ResourceProvider
> ResourceProvider::Create(
338 OutputSurface
* output_surface
,
339 SharedBitmapManager
* shared_bitmap_manager
,
340 gpu::GpuMemoryBufferManager
* gpu_memory_buffer_manager
,
341 BlockingTaskRunner
* blocking_main_thread_task_runner
,
342 int highp_threshold_min
,
343 bool use_rgba_4444_texture_format
,
344 size_t id_allocation_chunk_size
,
345 const std::vector
<unsigned>& use_image_texture_targets
) {
346 scoped_ptr
<ResourceProvider
> resource_provider(new ResourceProvider(
347 output_surface
, shared_bitmap_manager
, gpu_memory_buffer_manager
,
348 blocking_main_thread_task_runner
, highp_threshold_min
,
349 use_rgba_4444_texture_format
, id_allocation_chunk_size
,
350 use_image_texture_targets
));
351 resource_provider
->Initialize();
352 return resource_provider
;
355 ResourceProvider::~ResourceProvider() {
356 base::trace_event::MemoryDumpManager::GetInstance()->UnregisterDumpProvider(
359 while (!children_
.empty())
360 DestroyChildInternal(children_
.begin(), FOR_SHUTDOWN
);
361 while (!resources_
.empty())
362 DeleteResourceInternal(resources_
.begin(), FOR_SHUTDOWN
);
364 GLES2Interface
* gl
= ContextGL();
365 if (default_resource_type_
!= RESOURCE_TYPE_GL_TEXTURE
) {
366 // We are not in GL mode, but double check before returning.
373 // Check that all GL resources has been deleted.
374 for (ResourceMap::const_iterator itr
= resources_
.begin();
375 itr
!= resources_
.end(); ++itr
) {
376 DCHECK_NE(RESOURCE_TYPE_GL_TEXTURE
, itr
->second
.type
);
378 #endif // DCHECK_IS_ON()
380 texture_id_allocator_
= nullptr;
381 buffer_id_allocator_
= nullptr;
385 bool ResourceProvider::InUseByConsumer(ResourceId id
) {
386 Resource
* resource
= GetResource(id
);
387 return resource
->lock_for_read_count
> 0 || resource
->exported_count
> 0 ||
391 bool ResourceProvider::IsLost(ResourceId id
) {
392 Resource
* resource
= GetResource(id
);
393 return resource
->lost
;
396 void ResourceProvider::LoseResourceForTesting(ResourceId id
) {
397 Resource
* resource
= GetResource(id
);
399 resource
->lost
= true;
402 ResourceId
ResourceProvider::CreateResource(const gfx::Size
& size
,
405 ResourceFormat format
) {
406 DCHECK(!size
.IsEmpty());
407 switch (default_resource_type_
) {
408 case RESOURCE_TYPE_GL_TEXTURE
:
409 return CreateGLTexture(size
,
411 GL_TEXTURE_POOL_UNMANAGED_CHROMIUM
,
415 case RESOURCE_TYPE_BITMAP
:
416 DCHECK_EQ(RGBA_8888
, format
);
417 return CreateBitmap(size
, wrap_mode
);
420 LOG(FATAL
) << "Invalid default resource type.";
424 ResourceId
ResourceProvider::CreateManagedResource(const gfx::Size
& size
,
428 ResourceFormat format
) {
429 DCHECK(!size
.IsEmpty());
430 switch (default_resource_type_
) {
431 case RESOURCE_TYPE_GL_TEXTURE
:
432 return CreateGLTexture(size
,
434 GL_TEXTURE_POOL_MANAGED_CHROMIUM
,
438 case RESOURCE_TYPE_BITMAP
:
439 DCHECK_EQ(RGBA_8888
, format
);
440 return CreateBitmap(size
, wrap_mode
);
443 LOG(FATAL
) << "Invalid default resource type.";
447 ResourceId
ResourceProvider::CreateGLTexture(const gfx::Size
& size
,
452 ResourceFormat format
) {
453 DCHECK_LE(size
.width(), max_texture_size_
);
454 DCHECK_LE(size
.height(), max_texture_size_
);
455 DCHECK(thread_checker_
.CalledOnValidThread());
457 ResourceId id
= next_id_
++;
458 Resource
* resource
= InsertResource(
459 id
, Resource(0, size
, Resource::INTERNAL
, target
, GL_LINEAR
, texture_pool
,
460 wrap_mode
, hint
, format
));
461 resource
->allocated
= false;
465 ResourceId
ResourceProvider::CreateBitmap(const gfx::Size
& size
,
467 DCHECK(thread_checker_
.CalledOnValidThread());
469 scoped_ptr
<SharedBitmap
> bitmap
=
470 shared_bitmap_manager_
->AllocateSharedBitmap(size
);
471 uint8_t* pixels
= bitmap
->pixels();
474 ResourceId id
= next_id_
++;
476 InsertResource(id
, Resource(pixels
, bitmap
.release(), size
,
477 Resource::INTERNAL
, GL_LINEAR
, wrap_mode
));
478 resource
->allocated
= true;
482 ResourceId
ResourceProvider::CreateResourceFromIOSurface(
483 const gfx::Size
& size
,
484 unsigned io_surface_id
) {
485 DCHECK(thread_checker_
.CalledOnValidThread());
487 ResourceId id
= next_id_
++;
488 Resource
* resource
= InsertResource(
489 id
, Resource(0, gfx::Size(), Resource::INTERNAL
, GL_TEXTURE_RECTANGLE_ARB
,
490 GL_LINEAR
, GL_TEXTURE_POOL_UNMANAGED_CHROMIUM
,
491 GL_CLAMP_TO_EDGE
, TEXTURE_HINT_IMMUTABLE
, RGBA_8888
));
492 LazyCreate(resource
);
493 GLES2Interface
* gl
= ContextGL();
495 gl
->BindTexture(GL_TEXTURE_RECTANGLE_ARB
, resource
->gl_id
);
496 gl
->TexImageIOSurface2DCHROMIUM(
497 GL_TEXTURE_RECTANGLE_ARB
, size
.width(), size
.height(), io_surface_id
, 0);
498 resource
->allocated
= true;
502 ResourceId
ResourceProvider::CreateResourceFromTextureMailbox(
503 const TextureMailbox
& mailbox
,
504 scoped_ptr
<SingleReleaseCallbackImpl
> release_callback_impl
,
505 bool read_lock_fences_enabled
) {
506 DCHECK(thread_checker_
.CalledOnValidThread());
507 // Just store the information. Mailbox will be consumed in LockForRead().
508 ResourceId id
= next_id_
++;
509 DCHECK(mailbox
.IsValid());
510 Resource
* resource
= nullptr;
511 if (mailbox
.IsTexture()) {
512 resource
= InsertResource(
513 id
, Resource(0, gfx::Size(), Resource::EXTERNAL
, mailbox
.target(),
514 mailbox
.nearest_neighbor() ? GL_NEAREST
: GL_LINEAR
, 0,
515 GL_CLAMP_TO_EDGE
, TEXTURE_HINT_IMMUTABLE
, RGBA_8888
));
517 DCHECK(mailbox
.IsSharedMemory());
518 SharedBitmap
* shared_bitmap
= mailbox
.shared_bitmap();
519 uint8_t* pixels
= shared_bitmap
->pixels();
521 resource
= InsertResource(
522 id
, Resource(pixels
, shared_bitmap
, mailbox
.size_in_pixels(),
523 Resource::EXTERNAL
, GL_LINEAR
, GL_CLAMP_TO_EDGE
));
525 resource
->allocated
= true;
526 resource
->mailbox
= mailbox
;
527 resource
->release_callback_impl
=
528 base::Bind(&SingleReleaseCallbackImpl::Run
,
529 base::Owned(release_callback_impl
.release()));
530 resource
->read_lock_fences_enabled
= read_lock_fences_enabled
;
534 ResourceId
ResourceProvider::CreateResourceFromTextureMailbox(
535 const TextureMailbox
& mailbox
,
536 scoped_ptr
<SingleReleaseCallbackImpl
> release_callback_impl
) {
537 return CreateResourceFromTextureMailbox(mailbox
, release_callback_impl
.Pass(),
541 void ResourceProvider::DeleteResource(ResourceId id
) {
542 DCHECK(thread_checker_
.CalledOnValidThread());
543 ResourceMap::iterator it
= resources_
.find(id
);
544 CHECK(it
!= resources_
.end());
545 Resource
* resource
= &it
->second
;
546 DCHECK(!resource
->marked_for_deletion
);
547 DCHECK_EQ(resource
->imported_count
, 0);
548 DCHECK(resource
->pending_set_pixels
|| !resource
->locked_for_write
);
550 if (resource
->exported_count
> 0 || resource
->lock_for_read_count
> 0 ||
551 !ReadLockFenceHasPassed(resource
)) {
552 resource
->marked_for_deletion
= true;
555 DeleteResourceInternal(it
, NORMAL
);
559 void ResourceProvider::DeleteResourceInternal(ResourceMap::iterator it
,
561 TRACE_EVENT0("cc", "ResourceProvider::DeleteResourceInternal");
562 Resource
* resource
= &it
->second
;
563 bool lost_resource
= resource
->lost
;
565 DCHECK(resource
->exported_count
== 0 || style
!= NORMAL
);
566 if (style
== FOR_SHUTDOWN
&& resource
->exported_count
> 0)
567 lost_resource
= true;
569 if (resource
->image_id
) {
570 DCHECK(resource
->origin
== Resource::INTERNAL
);
571 GLES2Interface
* gl
= ContextGL();
573 gl
->DestroyImageCHROMIUM(resource
->image_id
);
575 if (resource
->gl_upload_query_id
) {
576 DCHECK(resource
->origin
== Resource::INTERNAL
);
577 GLES2Interface
* gl
= ContextGL();
579 gl
->DeleteQueriesEXT(1, &resource
->gl_upload_query_id
);
581 if (resource
->gl_read_lock_query_id
) {
582 DCHECK(resource
->origin
== Resource::INTERNAL
);
583 GLES2Interface
* gl
= ContextGL();
585 gl
->DeleteQueriesEXT(1, &resource
->gl_read_lock_query_id
);
587 if (resource
->gl_pixel_buffer_id
) {
588 DCHECK(resource
->origin
== Resource::INTERNAL
);
589 GLES2Interface
* gl
= ContextGL();
591 gl
->DeleteBuffers(1, &resource
->gl_pixel_buffer_id
);
593 if (resource
->origin
== Resource::EXTERNAL
) {
594 DCHECK(resource
->mailbox
.IsValid());
595 GLuint sync_point
= resource
->mailbox
.sync_point();
596 if (resource
->type
== RESOURCE_TYPE_GL_TEXTURE
) {
597 DCHECK(resource
->mailbox
.IsTexture());
598 lost_resource
|= lost_output_surface_
;
599 GLES2Interface
* gl
= ContextGL();
601 if (resource
->gl_id
) {
602 gl
->DeleteTextures(1, &resource
->gl_id
);
605 sync_point
= gl
->InsertSyncPointCHROMIUM();
608 DCHECK(resource
->mailbox
.IsSharedMemory());
609 resource
->shared_bitmap
= nullptr;
610 resource
->pixels
= nullptr;
612 resource
->release_callback_impl
.Run(
613 sync_point
, lost_resource
, blocking_main_thread_task_runner_
);
615 if (resource
->gl_id
) {
616 GLES2Interface
* gl
= ContextGL();
618 gl
->DeleteTextures(1, &resource
->gl_id
);
621 if (resource
->shared_bitmap
) {
622 DCHECK(resource
->origin
!= Resource::EXTERNAL
);
623 DCHECK_EQ(RESOURCE_TYPE_BITMAP
, resource
->type
);
624 delete resource
->shared_bitmap
;
625 resource
->pixels
= NULL
;
627 if (resource
->pixels
) {
628 DCHECK(resource
->origin
== Resource::INTERNAL
);
629 delete[] resource
->pixels
;
630 resource
->pixels
= NULL
;
632 if (resource
->gpu_memory_buffer
) {
633 DCHECK(resource
->origin
== Resource::INTERNAL
);
634 delete resource
->gpu_memory_buffer
;
635 resource
->gpu_memory_buffer
= NULL
;
637 resources_
.erase(it
);
640 ResourceProvider::ResourceType
ResourceProvider::GetResourceType(
642 return GetResource(id
)->type
;
645 void ResourceProvider::CopyToResource(ResourceId id
,
646 const uint8_t* image
,
647 const gfx::Size
& image_size
) {
648 Resource
* resource
= GetResource(id
);
649 DCHECK(!resource
->locked_for_write
);
650 DCHECK(!resource
->lock_for_read_count
);
651 DCHECK(resource
->origin
== Resource::INTERNAL
);
652 DCHECK_EQ(resource
->exported_count
, 0);
653 DCHECK(ReadLockFenceHasPassed(resource
));
654 LazyAllocate(resource
);
656 DCHECK_EQ(image_size
.width(), resource
->size
.width());
657 DCHECK_EQ(image_size
.height(), resource
->size
.height());
659 if (resource
->type
== RESOURCE_TYPE_BITMAP
) {
660 DCHECK_EQ(RESOURCE_TYPE_BITMAP
, resource
->type
);
661 DCHECK(resource
->allocated
);
662 DCHECK_EQ(RGBA_8888
, resource
->format
);
663 SkImageInfo source_info
=
664 SkImageInfo::MakeN32Premul(image_size
.width(), image_size
.height());
665 size_t image_stride
= image_size
.width() * 4;
667 ScopedWriteLockSoftware
lock(this, id
);
668 SkCanvas
dest(lock
.sk_bitmap());
669 dest
.writePixels(source_info
, image
, image_stride
, 0, 0);
671 DCHECK(resource
->gl_id
);
672 DCHECK(!resource
->pending_set_pixels
);
673 DCHECK_EQ(resource
->target
, static_cast<GLenum
>(GL_TEXTURE_2D
));
674 GLES2Interface
* gl
= ContextGL();
676 gl
->BindTexture(GL_TEXTURE_2D
, resource
->gl_id
);
678 if (resource
->format
== ETC1
) {
679 int image_bytes
= ResourceUtil::CheckedSizeInBytes
<int>(image_size
, ETC1
);
680 gl
->CompressedTexImage2D(GL_TEXTURE_2D
, 0, GLInternalFormat(ETC1
),
681 image_size
.width(), image_size
.height(), 0,
684 gl
->TexSubImage2D(GL_TEXTURE_2D
, 0, 0, 0, image_size
.width(),
685 image_size
.height(), GLDataFormat(resource
->format
),
686 GLDataType(resource
->format
), image
);
691 ResourceProvider::Resource
* ResourceProvider::InsertResource(
693 const Resource
& resource
) {
694 std::pair
<ResourceMap::iterator
, bool> result
=
695 resources_
.insert(ResourceMap::value_type(id
, resource
));
696 DCHECK(result
.second
);
697 return &result
.first
->second
;
700 ResourceProvider::Resource
* ResourceProvider::GetResource(ResourceId id
) {
701 DCHECK(thread_checker_
.CalledOnValidThread());
703 ResourceMap::iterator it
= resources_
.find(id
);
704 DCHECK(it
!= resources_
.end());
708 const ResourceProvider::Resource
* ResourceProvider::LockForRead(ResourceId id
) {
709 Resource
* resource
= GetResource(id
);
710 DCHECK(!resource
->locked_for_write
||
711 resource
->set_pixels_completion_forced
) <<
712 "locked for write: " << resource
->locked_for_write
<<
713 " pixels completion forced: " << resource
->set_pixels_completion_forced
;
714 DCHECK_EQ(resource
->exported_count
, 0);
715 // Uninitialized! Call SetPixels or LockForWrite first.
716 DCHECK(resource
->allocated
);
718 LazyCreate(resource
);
720 if (resource
->type
== RESOURCE_TYPE_GL_TEXTURE
&& !resource
->gl_id
) {
721 DCHECK(resource
->origin
!= Resource::INTERNAL
);
722 DCHECK(resource
->mailbox
.IsTexture());
724 // Mailbox sync_points must be processed by a call to
725 // WaitSyncPointIfNeeded() prior to calling LockForRead().
726 DCHECK(!resource
->mailbox
.sync_point());
728 GLES2Interface
* gl
= ContextGL();
730 resource
->gl_id
= gl
->CreateAndConsumeTextureCHROMIUM(
731 resource
->mailbox
.target(), resource
->mailbox
.name());
734 if (!resource
->pixels
&& resource
->has_shared_bitmap_id
&&
735 shared_bitmap_manager_
) {
736 scoped_ptr
<SharedBitmap
> bitmap
=
737 shared_bitmap_manager_
->GetSharedBitmapFromId(
738 resource
->size
, resource
->shared_bitmap_id
);
740 resource
->shared_bitmap
= bitmap
.release();
741 resource
->pixels
= resource
->shared_bitmap
->pixels();
745 resource
->lock_for_read_count
++;
746 if (resource
->read_lock_fences_enabled
) {
747 if (current_read_lock_fence_
.get())
748 current_read_lock_fence_
->Set();
749 resource
->read_lock_fence
= current_read_lock_fence_
;
755 void ResourceProvider::UnlockForRead(ResourceId id
) {
756 DCHECK(thread_checker_
.CalledOnValidThread());
757 ResourceMap::iterator it
= resources_
.find(id
);
758 CHECK(it
!= resources_
.end());
760 Resource
* resource
= &it
->second
;
761 DCHECK_GT(resource
->lock_for_read_count
, 0);
762 DCHECK_EQ(resource
->exported_count
, 0);
763 resource
->lock_for_read_count
--;
764 if (resource
->marked_for_deletion
&& !resource
->lock_for_read_count
) {
765 if (!resource
->child_id
) {
766 // The resource belongs to this ResourceProvider, so it can be destroyed.
767 DeleteResourceInternal(it
, NORMAL
);
769 ChildMap::iterator child_it
= children_
.find(resource
->child_id
);
770 ResourceIdArray unused
;
771 unused
.push_back(id
);
772 DeleteAndReturnUnusedResourcesToChild(child_it
, NORMAL
, unused
);
777 ResourceProvider::Resource
* ResourceProvider::LockForWrite(ResourceId id
) {
778 Resource
* resource
= GetResource(id
);
779 DCHECK(CanLockForWrite(id
));
781 resource
->locked_for_write
= true;
785 bool ResourceProvider::CanLockForWrite(ResourceId id
) {
786 Resource
* resource
= GetResource(id
);
787 return !resource
->locked_for_write
&& !resource
->lock_for_read_count
&&
788 !resource
->exported_count
&& resource
->origin
== Resource::INTERNAL
&&
789 !resource
->lost
&& ReadLockFenceHasPassed(resource
);
792 void ResourceProvider::UnlockForWrite(ResourceProvider::Resource
* resource
) {
793 DCHECK(resource
->locked_for_write
);
794 DCHECK_EQ(resource
->exported_count
, 0);
795 DCHECK(resource
->origin
== Resource::INTERNAL
);
796 resource
->locked_for_write
= false;
799 void ResourceProvider::EnableReadLockFencesForTesting(ResourceId id
) {
800 Resource
* resource
= GetResource(id
);
802 resource
->read_lock_fences_enabled
= true;
805 ResourceProvider::ScopedReadLockGL::ScopedReadLockGL(
806 ResourceProvider
* resource_provider
,
807 ResourceId resource_id
)
808 : resource_provider_(resource_provider
),
809 resource_id_(resource_id
),
810 resource_(resource_provider
->LockForRead(resource_id
)) {
814 ResourceProvider::ScopedReadLockGL::~ScopedReadLockGL() {
815 resource_provider_
->UnlockForRead(resource_id_
);
818 ResourceProvider::ScopedSamplerGL::ScopedSamplerGL(
819 ResourceProvider
* resource_provider
,
820 ResourceId resource_id
,
822 : ScopedReadLockGL(resource_provider
, resource_id
),
824 target_(resource_provider
->BindForSampling(resource_id
, unit_
, filter
)) {
827 ResourceProvider::ScopedSamplerGL::ScopedSamplerGL(
828 ResourceProvider
* resource_provider
,
829 ResourceId resource_id
,
832 : ScopedReadLockGL(resource_provider
, resource_id
),
834 target_(resource_provider
->BindForSampling(resource_id
, unit_
, filter
)) {
837 ResourceProvider::ScopedSamplerGL::~ScopedSamplerGL() {
840 ResourceProvider::ScopedWriteLockGL::ScopedWriteLockGL(
841 ResourceProvider
* resource_provider
,
842 ResourceId resource_id
)
843 : resource_provider_(resource_provider
),
844 resource_(resource_provider
->LockForWrite(resource_id
)) {
845 resource_provider_
->LazyAllocate(resource_
);
846 texture_id_
= resource_
->gl_id
;
850 ResourceProvider::ScopedWriteLockGL::~ScopedWriteLockGL() {
851 resource_provider_
->UnlockForWrite(resource_
);
854 void ResourceProvider::PopulateSkBitmapWithResource(
855 SkBitmap
* sk_bitmap
, const Resource
* resource
) {
856 DCHECK_EQ(RGBA_8888
, resource
->format
);
857 SkImageInfo info
= SkImageInfo::MakeN32Premul(resource
->size
.width(),
858 resource
->size
.height());
859 sk_bitmap
->installPixels(info
, resource
->pixels
, info
.minRowBytes());
862 ResourceProvider::ScopedReadLockSoftware::ScopedReadLockSoftware(
863 ResourceProvider
* resource_provider
,
864 ResourceId resource_id
)
865 : resource_provider_(resource_provider
), resource_id_(resource_id
) {
866 const Resource
* resource
= resource_provider
->LockForRead(resource_id
);
867 wrap_mode_
= resource
->wrap_mode
;
868 ResourceProvider::PopulateSkBitmapWithResource(&sk_bitmap_
, resource
);
871 ResourceProvider::ScopedReadLockSoftware::~ScopedReadLockSoftware() {
872 resource_provider_
->UnlockForRead(resource_id_
);
875 ResourceProvider::ScopedWriteLockSoftware::ScopedWriteLockSoftware(
876 ResourceProvider
* resource_provider
,
877 ResourceId resource_id
)
878 : resource_provider_(resource_provider
),
879 resource_(resource_provider
->LockForWrite(resource_id
)) {
880 ResourceProvider::PopulateSkBitmapWithResource(&sk_bitmap_
, resource_
);
884 ResourceProvider::ScopedWriteLockSoftware::~ScopedWriteLockSoftware() {
885 DCHECK(thread_checker_
.CalledOnValidThread());
886 resource_provider_
->UnlockForWrite(resource_
);
889 ResourceProvider::ScopedWriteLockGpuMemoryBuffer::
890 ScopedWriteLockGpuMemoryBuffer(ResourceProvider
* resource_provider
,
891 ResourceId resource_id
)
892 : resource_provider_(resource_provider
),
893 resource_(resource_provider
->LockForWrite(resource_id
)),
894 gpu_memory_buffer_manager_(resource_provider
->gpu_memory_buffer_manager_
),
895 gpu_memory_buffer_(nullptr),
896 size_(resource_
->size
),
897 format_(resource_
->format
) {
898 DCHECK_EQ(RESOURCE_TYPE_GL_TEXTURE
, resource_
->type
);
899 std::swap(gpu_memory_buffer_
, resource_
->gpu_memory_buffer
);
902 ResourceProvider::ScopedWriteLockGpuMemoryBuffer::
903 ~ScopedWriteLockGpuMemoryBuffer() {
904 DCHECK(thread_checker_
.CalledOnValidThread());
905 resource_provider_
->UnlockForWrite(resource_
);
906 if (!gpu_memory_buffer_
)
909 resource_provider_
->LazyCreate(resource_
);
911 if (!resource_
->image_id
) {
912 GLES2Interface
* gl
= resource_provider_
->ContextGL();
915 #if defined(OS_CHROMEOS)
916 // TODO(reveman): GL_COMMANDS_ISSUED_CHROMIUM is used for synchronization
917 // on ChromeOS to avoid some performance issues. This only works with
918 // shared memory backed buffers. crbug.com/436314
919 DCHECK_EQ(gpu_memory_buffer_
->GetHandle().type
, gfx::SHARED_MEMORY_BUFFER
);
922 resource_
->image_id
= gl
->CreateImageCHROMIUM(
923 gpu_memory_buffer_
->AsClientBuffer(), size_
.width(), size_
.height(),
924 GLInternalFormat(resource_
->format
));
927 std::swap(resource_
->gpu_memory_buffer
, gpu_memory_buffer_
);
928 resource_
->allocated
= true;
929 resource_
->dirty_image
= true;
931 // GpuMemoryBuffer provides direct access to the memory used by the GPU.
932 // Read lock fences are required to ensure that we're not trying to map a
933 // buffer that is currently in-use by the GPU.
934 resource_
->read_lock_fences_enabled
= true;
937 gfx::GpuMemoryBuffer
*
938 ResourceProvider::ScopedWriteLockGpuMemoryBuffer::GetGpuMemoryBuffer() {
939 if (gpu_memory_buffer_
)
940 return gpu_memory_buffer_
;
941 scoped_ptr
<gfx::GpuMemoryBuffer
> gpu_memory_buffer
=
942 gpu_memory_buffer_manager_
->AllocateGpuMemoryBuffer(
943 size_
, BufferFormat(format_
), gfx::BufferUsage::MAP
);
944 gpu_memory_buffer_
= gpu_memory_buffer
.release();
945 return gpu_memory_buffer_
;
948 ResourceProvider::ScopedWriteLockGr::ScopedWriteLockGr(
949 ResourceProvider
* resource_provider
,
950 ResourceId resource_id
)
951 : resource_provider_(resource_provider
),
952 resource_(resource_provider
->LockForWrite(resource_id
)) {
953 DCHECK(thread_checker_
.CalledOnValidThread());
954 resource_provider_
->LazyAllocate(resource_
);
957 ResourceProvider::ScopedWriteLockGr::~ScopedWriteLockGr() {
958 DCHECK(thread_checker_
.CalledOnValidThread());
959 DCHECK(resource_
->locked_for_write
);
960 resource_provider_
->UnlockForWrite(resource_
);
963 void ResourceProvider::ScopedWriteLockGr::InitSkSurface(
964 bool use_distance_field_text
,
965 bool can_use_lcd_text
,
966 int msaa_sample_count
) {
967 DCHECK(resource_
->locked_for_write
);
969 GrBackendTextureDesc desc
;
970 desc
.fFlags
= kRenderTarget_GrBackendTextureFlag
;
971 desc
.fWidth
= resource_
->size
.width();
972 desc
.fHeight
= resource_
->size
.height();
973 desc
.fConfig
= ToGrPixelConfig(resource_
->format
);
974 desc
.fOrigin
= kTopLeft_GrSurfaceOrigin
;
975 desc
.fTextureHandle
= resource_
->gl_id
;
976 desc
.fSampleCnt
= msaa_sample_count
;
978 bool use_worker_context
= true;
979 class GrContext
* gr_context
=
980 resource_provider_
->GrContext(use_worker_context
);
982 use_distance_field_text
? SkSurfaceProps::kUseDistanceFieldFonts_Flag
: 0;
983 // Use unknown pixel geometry to disable LCD text.
984 SkSurfaceProps
surface_props(flags
, kUnknown_SkPixelGeometry
);
985 if (can_use_lcd_text
) {
986 // LegacyFontHost will get LCD text and skia figures out what type to use.
988 SkSurfaceProps(flags
, SkSurfaceProps::kLegacyFontHost_InitType
);
990 sk_surface_
= skia::AdoptRef(
991 SkSurface::NewWrappedRenderTarget(gr_context
, desc
, &surface_props
));
994 void ResourceProvider::ScopedWriteLockGr::ReleaseSkSurface() {
998 ResourceProvider::SynchronousFence::SynchronousFence(
999 gpu::gles2::GLES2Interface
* gl
)
1000 : gl_(gl
), has_synchronized_(true) {
1003 ResourceProvider::SynchronousFence::~SynchronousFence() {
1006 void ResourceProvider::SynchronousFence::Set() {
1007 has_synchronized_
= false;
1010 bool ResourceProvider::SynchronousFence::HasPassed() {
1011 if (!has_synchronized_
) {
1012 has_synchronized_
= true;
1018 void ResourceProvider::SynchronousFence::Wait() {
1022 void ResourceProvider::SynchronousFence::Synchronize() {
1023 TRACE_EVENT0("cc", "ResourceProvider::SynchronousFence::Synchronize");
1027 ResourceProvider::ResourceProvider(
1028 OutputSurface
* output_surface
,
1029 SharedBitmapManager
* shared_bitmap_manager
,
1030 gpu::GpuMemoryBufferManager
* gpu_memory_buffer_manager
,
1031 BlockingTaskRunner
* blocking_main_thread_task_runner
,
1032 int highp_threshold_min
,
1033 bool use_rgba_4444_texture_format
,
1034 size_t id_allocation_chunk_size
,
1035 const std::vector
<unsigned>& use_image_texture_targets
)
1036 : output_surface_(output_surface
),
1037 shared_bitmap_manager_(shared_bitmap_manager
),
1038 gpu_memory_buffer_manager_(gpu_memory_buffer_manager
),
1039 blocking_main_thread_task_runner_(blocking_main_thread_task_runner
),
1040 lost_output_surface_(false),
1041 highp_threshold_min_(highp_threshold_min
),
1044 default_resource_type_(RESOURCE_TYPE_BITMAP
),
1045 use_texture_storage_ext_(false),
1046 use_texture_format_bgra_(false),
1047 use_texture_usage_hint_(false),
1048 use_compressed_texture_etc1_(false),
1049 yuv_resource_format_(LUMINANCE_8
),
1050 max_texture_size_(0),
1051 best_texture_format_(RGBA_8888
),
1052 best_render_buffer_format_(RGBA_8888
),
1053 use_rgba_4444_texture_format_(use_rgba_4444_texture_format
),
1054 id_allocation_chunk_size_(id_allocation_chunk_size
),
1055 use_sync_query_(false),
1056 use_image_texture_targets_(use_image_texture_targets
),
1057 tracing_id_(g_next_resource_provider_tracing_id
.GetNext()) {
1058 DCHECK(output_surface_
->HasClient());
1059 DCHECK(id_allocation_chunk_size_
);
1062 void ResourceProvider::Initialize() {
1063 DCHECK(thread_checker_
.CalledOnValidThread());
1065 // In certain cases, ThreadTaskRunnerHandle isn't set (Android Webview).
1066 // Don't register a dump provider in these cases.
1067 // TODO(ericrk): Get this working in Android Webview. crbug.com/517156
1068 if (base::ThreadTaskRunnerHandle::IsSet()) {
1069 base::trace_event::MemoryDumpManager::GetInstance()->RegisterDumpProvider(
1070 this, base::ThreadTaskRunnerHandle::Get());
1073 GLES2Interface
* gl
= ContextGL();
1075 default_resource_type_
= RESOURCE_TYPE_BITMAP
;
1076 // Pick an arbitrary limit here similar to what hardware might.
1077 max_texture_size_
= 16 * 1024;
1078 best_texture_format_
= RGBA_8888
;
1082 DCHECK(!texture_id_allocator_
);
1083 DCHECK(!buffer_id_allocator_
);
1085 const ContextProvider::Capabilities
& caps
=
1086 output_surface_
->context_provider()->ContextCapabilities();
1088 default_resource_type_
= RESOURCE_TYPE_GL_TEXTURE
;
1089 use_texture_storage_ext_
= caps
.gpu
.texture_storage
;
1090 use_texture_format_bgra_
= caps
.gpu
.texture_format_bgra8888
;
1091 use_texture_usage_hint_
= caps
.gpu
.texture_usage
;
1092 use_compressed_texture_etc1_
= caps
.gpu
.texture_format_etc1
;
1093 yuv_resource_format_
= caps
.gpu
.texture_rg
? RED_8
: LUMINANCE_8
;
1094 use_sync_query_
= caps
.gpu
.sync_query
;
1096 max_texture_size_
= 0; // Context expects cleared value.
1097 gl
->GetIntegerv(GL_MAX_TEXTURE_SIZE
, &max_texture_size_
);
1098 best_texture_format_
=
1099 PlatformColor::BestTextureFormat(use_texture_format_bgra_
);
1101 best_render_buffer_format_
=
1102 PlatformColor::BestTextureFormat(caps
.gpu
.render_buffer_format_bgra8888
);
1104 texture_id_allocator_
.reset(
1105 new TextureIdAllocator(gl
, id_allocation_chunk_size_
));
1106 buffer_id_allocator_
.reset(
1107 new BufferIdAllocator(gl
, id_allocation_chunk_size_
));
1110 int ResourceProvider::CreateChild(const ReturnCallback
& return_callback
) {
1111 DCHECK(thread_checker_
.CalledOnValidThread());
1114 child_info
.return_callback
= return_callback
;
1116 int child
= next_child_
++;
1117 children_
[child
] = child_info
;
1121 void ResourceProvider::SetChildNeedsSyncPoints(int child_id
, bool needs
) {
1122 ChildMap::iterator it
= children_
.find(child_id
);
1123 DCHECK(it
!= children_
.end());
1124 it
->second
.needs_sync_points
= needs
;
1127 void ResourceProvider::DestroyChild(int child_id
) {
1128 ChildMap::iterator it
= children_
.find(child_id
);
1129 DCHECK(it
!= children_
.end());
1130 DestroyChildInternal(it
, NORMAL
);
1133 void ResourceProvider::DestroyChildInternal(ChildMap::iterator it
,
1134 DeleteStyle style
) {
1135 DCHECK(thread_checker_
.CalledOnValidThread());
1137 Child
& child
= it
->second
;
1138 DCHECK(style
== FOR_SHUTDOWN
|| !child
.marked_for_deletion
);
1140 ResourceIdArray resources_for_child
;
1142 for (ResourceIdMap::iterator child_it
= child
.child_to_parent_map
.begin();
1143 child_it
!= child
.child_to_parent_map
.end();
1145 ResourceId id
= child_it
->second
;
1146 resources_for_child
.push_back(id
);
1149 child
.marked_for_deletion
= true;
1151 DeleteAndReturnUnusedResourcesToChild(it
, style
, resources_for_child
);
1154 const ResourceProvider::ResourceIdMap
& ResourceProvider::GetChildToParentMap(
1156 DCHECK(thread_checker_
.CalledOnValidThread());
1157 ChildMap::const_iterator it
= children_
.find(child
);
1158 DCHECK(it
!= children_
.end());
1159 DCHECK(!it
->second
.marked_for_deletion
);
1160 return it
->second
.child_to_parent_map
;
1163 void ResourceProvider::PrepareSendToParent(const ResourceIdArray
& resources
,
1164 TransferableResourceArray
* list
) {
1165 DCHECK(thread_checker_
.CalledOnValidThread());
1166 GLES2Interface
* gl
= ContextGL();
1167 bool need_sync_point
= false;
1168 for (ResourceIdArray::const_iterator it
= resources
.begin();
1169 it
!= resources
.end();
1171 TransferableResource resource
;
1172 TransferResource(gl
, *it
, &resource
);
1173 if (!resource
.mailbox_holder
.sync_point
&& !resource
.is_software
)
1174 need_sync_point
= true;
1175 ++resources_
.find(*it
)->second
.exported_count
;
1176 list
->push_back(resource
);
1178 if (need_sync_point
&&
1179 output_surface_
->capabilities().delegated_sync_points_required
) {
1180 GLuint sync_point
= gl
->InsertSyncPointCHROMIUM();
1181 for (TransferableResourceArray::iterator it
= list
->begin();
1184 if (!it
->mailbox_holder
.sync_point
)
1185 it
->mailbox_holder
.sync_point
= sync_point
;
1190 void ResourceProvider::ReceiveFromChild(
1191 int child
, const TransferableResourceArray
& resources
) {
1192 DCHECK(thread_checker_
.CalledOnValidThread());
1193 GLES2Interface
* gl
= ContextGL();
1194 Child
& child_info
= children_
.find(child
)->second
;
1195 DCHECK(!child_info
.marked_for_deletion
);
1196 for (TransferableResourceArray::const_iterator it
= resources
.begin();
1197 it
!= resources
.end();
1199 ResourceIdMap::iterator resource_in_map_it
=
1200 child_info
.child_to_parent_map
.find(it
->id
);
1201 if (resource_in_map_it
!= child_info
.child_to_parent_map
.end()) {
1202 Resource
* resource
= GetResource(resource_in_map_it
->second
);
1203 resource
->marked_for_deletion
= false;
1204 resource
->imported_count
++;
1208 if ((!it
->is_software
&& !gl
) ||
1209 (it
->is_software
&& !shared_bitmap_manager_
)) {
1210 TRACE_EVENT0("cc", "ResourceProvider::ReceiveFromChild dropping invalid");
1211 ReturnedResourceArray to_return
;
1212 to_return
.push_back(it
->ToReturnedResource());
1213 child_info
.return_callback
.Run(to_return
,
1214 blocking_main_thread_task_runner_
);
1218 ResourceId local_id
= next_id_
++;
1219 Resource
* resource
= nullptr;
1220 if (it
->is_software
) {
1221 resource
= InsertResource(
1223 Resource(it
->mailbox_holder
.mailbox
, it
->size
, Resource::DELEGATED
,
1224 GL_LINEAR
, it
->is_repeated
? GL_REPEAT
: GL_CLAMP_TO_EDGE
));
1226 resource
= InsertResource(
1227 local_id
, Resource(0, it
->size
, Resource::DELEGATED
,
1228 it
->mailbox_holder
.texture_target
, it
->filter
, 0,
1229 it
->is_repeated
? GL_REPEAT
: GL_CLAMP_TO_EDGE
,
1230 TEXTURE_HINT_IMMUTABLE
, it
->format
));
1231 resource
->mailbox
= TextureMailbox(it
->mailbox_holder
.mailbox
,
1232 it
->mailbox_holder
.texture_target
,
1233 it
->mailbox_holder
.sync_point
);
1234 resource
->read_lock_fences_enabled
= it
->read_lock_fences_enabled
;
1236 resource
->child_id
= child
;
1237 // Don't allocate a texture for a child.
1238 resource
->allocated
= true;
1239 resource
->imported_count
= 1;
1240 child_info
.parent_to_child_map
[local_id
] = it
->id
;
1241 child_info
.child_to_parent_map
[it
->id
] = local_id
;
1245 void ResourceProvider::DeclareUsedResourcesFromChild(
1247 const ResourceIdSet
& resources_from_child
) {
1248 DCHECK(thread_checker_
.CalledOnValidThread());
1250 ChildMap::iterator child_it
= children_
.find(child
);
1251 DCHECK(child_it
!= children_
.end());
1252 Child
& child_info
= child_it
->second
;
1253 DCHECK(!child_info
.marked_for_deletion
);
1255 ResourceIdArray unused
;
1256 for (ResourceIdMap::iterator it
= child_info
.child_to_parent_map
.begin();
1257 it
!= child_info
.child_to_parent_map
.end();
1259 ResourceId local_id
= it
->second
;
1260 bool resource_is_in_use
= resources_from_child
.count(it
->first
) > 0;
1261 if (!resource_is_in_use
)
1262 unused
.push_back(local_id
);
1264 DeleteAndReturnUnusedResourcesToChild(child_it
, NORMAL
, unused
);
1267 void ResourceProvider::ReceiveReturnsFromParent(
1268 const ReturnedResourceArray
& resources
) {
1269 DCHECK(thread_checker_
.CalledOnValidThread());
1270 GLES2Interface
* gl
= ContextGL();
1272 base::hash_map
<int, ResourceIdArray
> resources_for_child
;
1274 for (const ReturnedResource
& returned
: resources
) {
1275 ResourceId local_id
= returned
.id
;
1276 ResourceMap::iterator map_iterator
= resources_
.find(local_id
);
1277 // Resource was already lost (e.g. it belonged to a child that was
1279 if (map_iterator
== resources_
.end())
1282 Resource
* resource
= &map_iterator
->second
;
1284 CHECK_GE(resource
->exported_count
, returned
.count
);
1285 resource
->exported_count
-= returned
.count
;
1286 resource
->lost
|= returned
.lost
;
1287 if (resource
->exported_count
)
1290 if (returned
.sync_point
) {
1291 DCHECK(!resource
->has_shared_bitmap_id
);
1292 if (resource
->origin
== Resource::INTERNAL
) {
1293 DCHECK(resource
->gl_id
);
1294 gl
->WaitSyncPointCHROMIUM(returned
.sync_point
);
1296 DCHECK(!resource
->gl_id
);
1297 resource
->mailbox
.set_sync_point(returned
.sync_point
);
1301 if (!resource
->marked_for_deletion
)
1304 if (!resource
->child_id
) {
1305 // The resource belongs to this ResourceProvider, so it can be destroyed.
1306 DeleteResourceInternal(map_iterator
, NORMAL
);
1310 DCHECK(resource
->origin
== Resource::DELEGATED
);
1311 resources_for_child
[resource
->child_id
].push_back(local_id
);
1314 for (const auto& children
: resources_for_child
) {
1315 ChildMap::iterator child_it
= children_
.find(children
.first
);
1316 DCHECK(child_it
!= children_
.end());
1317 DeleteAndReturnUnusedResourcesToChild(child_it
, NORMAL
, children
.second
);
1321 void ResourceProvider::TransferResource(GLES2Interface
* gl
,
1323 TransferableResource
* resource
) {
1324 Resource
* source
= GetResource(id
);
1325 DCHECK(!source
->locked_for_write
);
1326 DCHECK(!source
->lock_for_read_count
);
1327 DCHECK(source
->origin
!= Resource::EXTERNAL
|| source
->mailbox
.IsValid());
1328 DCHECK(source
->allocated
);
1330 resource
->format
= source
->format
;
1331 resource
->mailbox_holder
.texture_target
= source
->target
;
1332 resource
->filter
= source
->filter
;
1333 resource
->size
= source
->size
;
1334 resource
->read_lock_fences_enabled
= source
->read_lock_fences_enabled
;
1335 resource
->is_repeated
= (source
->wrap_mode
== GL_REPEAT
);
1337 if (source
->type
== RESOURCE_TYPE_BITMAP
) {
1338 resource
->mailbox_holder
.mailbox
= source
->shared_bitmap_id
;
1339 resource
->is_software
= true;
1340 } else if (!source
->mailbox
.IsValid()) {
1342 DCHECK(source
->gl_id
);
1343 DCHECK(source
->origin
== Resource::INTERNAL
);
1344 if (source
->image_id
) {
1345 DCHECK(source
->dirty_image
);
1346 gl
->BindTexture(resource
->mailbox_holder
.texture_target
, source
->gl_id
);
1347 BindImageForSampling(source
);
1349 // This is a resource allocated by the compositor, we need to produce it.
1350 // Don't set a sync point, the caller will do it.
1351 gl
->GenMailboxCHROMIUM(resource
->mailbox_holder
.mailbox
.name
);
1352 gl
->ProduceTextureDirectCHROMIUM(source
->gl_id
,
1353 resource
->mailbox_holder
.texture_target
,
1354 resource
->mailbox_holder
.mailbox
.name
);
1356 source
->mailbox
= TextureMailbox(resource
->mailbox_holder
);
1358 DCHECK(source
->mailbox
.IsTexture());
1359 if (source
->image_id
&& source
->dirty_image
) {
1360 DCHECK(source
->gl_id
);
1361 DCHECK(source
->origin
== Resource::INTERNAL
);
1362 gl
->BindTexture(resource
->mailbox_holder
.texture_target
, source
->gl_id
);
1363 BindImageForSampling(source
);
1365 // This is either an external resource, or a compositor resource that we
1366 // already exported. Make sure to forward the sync point that we were given.
1367 resource
->mailbox_holder
.mailbox
= source
->mailbox
.mailbox();
1368 resource
->mailbox_holder
.texture_target
= source
->mailbox
.target();
1369 resource
->mailbox_holder
.sync_point
= source
->mailbox
.sync_point();
1370 source
->mailbox
.set_sync_point(0);
1374 void ResourceProvider::DeleteAndReturnUnusedResourcesToChild(
1375 ChildMap::iterator child_it
,
1377 const ResourceIdArray
& unused
) {
1378 DCHECK(thread_checker_
.CalledOnValidThread());
1379 DCHECK(child_it
!= children_
.end());
1380 Child
* child_info
= &child_it
->second
;
1382 if (unused
.empty() && !child_info
->marked_for_deletion
)
1385 ReturnedResourceArray to_return
;
1387 GLES2Interface
* gl
= ContextGL();
1388 bool need_sync_point
= false;
1389 for (size_t i
= 0; i
< unused
.size(); ++i
) {
1390 ResourceId local_id
= unused
[i
];
1392 ResourceMap::iterator it
= resources_
.find(local_id
);
1393 CHECK(it
!= resources_
.end());
1394 Resource
& resource
= it
->second
;
1396 DCHECK(!resource
.locked_for_write
);
1397 DCHECK(child_info
->parent_to_child_map
.count(local_id
));
1399 ResourceId child_id
= child_info
->parent_to_child_map
[local_id
];
1400 DCHECK(child_info
->child_to_parent_map
.count(child_id
));
1404 (resource
.type
== RESOURCE_TYPE_GL_TEXTURE
&& lost_output_surface_
);
1405 if (resource
.exported_count
> 0 || resource
.lock_for_read_count
> 0) {
1406 if (style
!= FOR_SHUTDOWN
) {
1407 // Defer this resource deletion.
1408 resource
.marked_for_deletion
= true;
1411 // We can't postpone the deletion, so we'll have to lose it.
1413 } else if (!ReadLockFenceHasPassed(&resource
)) {
1414 // TODO(dcastagna): see if it's possible to use this logic for
1415 // the branch above too, where the resource is locked or still exported.
1416 if (style
!= FOR_SHUTDOWN
&& !child_info
->marked_for_deletion
) {
1417 // Defer this resource deletion.
1418 resource
.marked_for_deletion
= true;
1421 // We can't postpone the deletion, so we'll have to lose it.
1425 if (gl
&& resource
.filter
!= resource
.original_filter
) {
1426 DCHECK(resource
.target
);
1427 DCHECK(resource
.gl_id
);
1429 gl
->BindTexture(resource
.target
, resource
.gl_id
);
1430 gl
->TexParameteri(resource
.target
, GL_TEXTURE_MIN_FILTER
,
1431 resource
.original_filter
);
1432 gl
->TexParameteri(resource
.target
, GL_TEXTURE_MAG_FILTER
,
1433 resource
.original_filter
);
1436 ReturnedResource returned
;
1437 returned
.id
= child_id
;
1438 returned
.sync_point
= resource
.mailbox
.sync_point();
1439 if (!returned
.sync_point
&& resource
.type
== RESOURCE_TYPE_GL_TEXTURE
)
1440 need_sync_point
= true;
1441 returned
.count
= resource
.imported_count
;
1442 returned
.lost
= is_lost
;
1443 to_return
.push_back(returned
);
1445 child_info
->parent_to_child_map
.erase(local_id
);
1446 child_info
->child_to_parent_map
.erase(child_id
);
1447 resource
.imported_count
= 0;
1448 DeleteResourceInternal(it
, style
);
1450 if (need_sync_point
&& child_info
->needs_sync_points
) {
1452 GLuint sync_point
= gl
->InsertSyncPointCHROMIUM();
1453 for (size_t i
= 0; i
< to_return
.size(); ++i
) {
1454 if (!to_return
[i
].sync_point
)
1455 to_return
[i
].sync_point
= sync_point
;
1459 if (!to_return
.empty())
1460 child_info
->return_callback
.Run(to_return
,
1461 blocking_main_thread_task_runner_
);
1463 if (child_info
->marked_for_deletion
&&
1464 child_info
->parent_to_child_map
.empty()) {
1465 DCHECK(child_info
->child_to_parent_map
.empty());
1466 children_
.erase(child_it
);
1470 void ResourceProvider::AcquirePixelBuffer(ResourceId id
) {
1471 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug"),
1472 "ResourceProvider::AcquirePixelBuffer");
1474 Resource
* resource
= GetResource(id
);
1475 DCHECK(resource
->origin
== Resource::INTERNAL
);
1476 DCHECK_EQ(resource
->exported_count
, 0);
1477 DCHECK(!resource
->image_id
);
1478 DCHECK_NE(ETC1
, resource
->format
);
1480 DCHECK_EQ(RESOURCE_TYPE_GL_TEXTURE
, resource
->type
);
1481 GLES2Interface
* gl
= ContextGL();
1483 if (!resource
->gl_pixel_buffer_id
)
1484 resource
->gl_pixel_buffer_id
= buffer_id_allocator_
->NextId();
1485 gl
->BindBuffer(GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM
,
1486 resource
->gl_pixel_buffer_id
);
1487 size_t resource_bytes
= ResourceUtil::UncheckedSizeInBytesAligned
<size_t>(
1488 resource
->size
, resource
->format
);
1489 gl
->BufferData(GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM
, resource_bytes
, NULL
,
1491 gl
->BindBuffer(GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM
, 0);
1494 void ResourceProvider::ReleasePixelBuffer(ResourceId id
) {
1495 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug"),
1496 "ResourceProvider::ReleasePixelBuffer");
1498 Resource
* resource
= GetResource(id
);
1499 DCHECK(resource
->origin
== Resource::INTERNAL
);
1500 DCHECK_EQ(resource
->exported_count
, 0);
1501 DCHECK(!resource
->image_id
);
1503 // The pixel buffer can be released while there is a pending "set pixels"
1504 // if completion has been forced. Any shared memory associated with this
1505 // pixel buffer will not be freed until the waitAsyncTexImage2DCHROMIUM
1506 // command has been processed on the service side. It is also safe to
1507 // reuse any query id associated with this resource before they complete
1508 // as each new query has a unique submit count.
1509 if (resource
->pending_set_pixels
) {
1510 DCHECK(resource
->set_pixels_completion_forced
);
1511 resource
->pending_set_pixels
= false;
1512 resource
->locked_for_write
= false;
1515 DCHECK_EQ(RESOURCE_TYPE_GL_TEXTURE
, resource
->type
);
1516 if (!resource
->gl_pixel_buffer_id
)
1518 GLES2Interface
* gl
= ContextGL();
1520 gl
->BindBuffer(GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM
,
1521 resource
->gl_pixel_buffer_id
);
1523 GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM
, 0, NULL
, GL_DYNAMIC_DRAW
);
1524 gl
->BindBuffer(GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM
, 0);
1527 uint8_t* ResourceProvider::MapPixelBuffer(ResourceId id
, int* stride
) {
1528 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug"),
1529 "ResourceProvider::MapPixelBuffer");
1531 Resource
* resource
= GetResource(id
);
1532 DCHECK(resource
->origin
== Resource::INTERNAL
);
1533 DCHECK_EQ(resource
->exported_count
, 0);
1534 DCHECK(!resource
->image_id
);
1537 DCHECK_EQ(RESOURCE_TYPE_GL_TEXTURE
, resource
->type
);
1538 GLES2Interface
* gl
= ContextGL();
1540 DCHECK(resource
->gl_pixel_buffer_id
);
1541 gl
->BindBuffer(GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM
,
1542 resource
->gl_pixel_buffer_id
);
1543 uint8_t* image
= static_cast<uint8_t*>(gl
->MapBufferCHROMIUM(
1544 GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM
, GL_WRITE_ONLY
));
1545 gl
->BindBuffer(GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM
, 0);
1546 // Buffer is required to be 4-byte aligned.
1547 CHECK(!(reinterpret_cast<intptr_t>(image
) & 3));
1551 void ResourceProvider::UnmapPixelBuffer(ResourceId id
) {
1552 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug"),
1553 "ResourceProvider::UnmapPixelBuffer");
1555 Resource
* resource
= GetResource(id
);
1556 DCHECK(resource
->origin
== Resource::INTERNAL
);
1557 DCHECK_EQ(resource
->exported_count
, 0);
1558 DCHECK(!resource
->image_id
);
1560 DCHECK_EQ(RESOURCE_TYPE_GL_TEXTURE
, resource
->type
);
1561 GLES2Interface
* gl
= ContextGL();
1563 DCHECK(resource
->gl_pixel_buffer_id
);
1564 gl
->BindBuffer(GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM
,
1565 resource
->gl_pixel_buffer_id
);
1566 gl
->UnmapBufferCHROMIUM(GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM
);
1567 gl
->BindBuffer(GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM
, 0);
1570 GLenum
ResourceProvider::BindForSampling(ResourceId resource_id
,
1573 DCHECK(thread_checker_
.CalledOnValidThread());
1574 GLES2Interface
* gl
= ContextGL();
1575 ResourceMap::iterator it
= resources_
.find(resource_id
);
1576 DCHECK(it
!= resources_
.end());
1577 Resource
* resource
= &it
->second
;
1578 DCHECK(resource
->lock_for_read_count
);
1579 DCHECK(!resource
->locked_for_write
|| resource
->set_pixels_completion_forced
);
1581 ScopedSetActiveTexture
scoped_active_tex(gl
, unit
);
1582 GLenum target
= resource
->target
;
1583 gl
->BindTexture(target
, resource
->gl_id
);
1584 if (filter
!= resource
->filter
) {
1585 gl
->TexParameteri(target
, GL_TEXTURE_MIN_FILTER
, filter
);
1586 gl
->TexParameteri(target
, GL_TEXTURE_MAG_FILTER
, filter
);
1587 resource
->filter
= filter
;
1590 if (resource
->image_id
&& resource
->dirty_image
)
1591 BindImageForSampling(resource
);
1596 void ResourceProvider::BeginSetPixels(ResourceId id
) {
1597 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug"),
1598 "ResourceProvider::BeginSetPixels");
1600 Resource
* resource
= GetResource(id
);
1601 DCHECK(!resource
->pending_set_pixels
);
1603 LazyCreate(resource
);
1604 DCHECK(resource
->origin
== Resource::INTERNAL
);
1605 DCHECK(resource
->gl_id
|| resource
->allocated
);
1606 DCHECK(ReadLockFenceHasPassed(resource
));
1607 DCHECK(!resource
->image_id
);
1609 bool allocate
= !resource
->allocated
;
1610 resource
->allocated
= true;
1613 DCHECK_EQ(RESOURCE_TYPE_GL_TEXTURE
, resource
->type
);
1614 DCHECK(resource
->gl_id
);
1615 GLES2Interface
* gl
= ContextGL();
1617 DCHECK(resource
->gl_pixel_buffer_id
);
1618 DCHECK_EQ(resource
->target
, static_cast<GLenum
>(GL_TEXTURE_2D
));
1619 gl
->BindTexture(GL_TEXTURE_2D
, resource
->gl_id
);
1620 gl
->BindBuffer(GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM
,
1621 resource
->gl_pixel_buffer_id
);
1622 if (!resource
->gl_upload_query_id
)
1623 gl
->GenQueriesEXT(1, &resource
->gl_upload_query_id
);
1624 gl
->BeginQueryEXT(GL_ASYNC_PIXEL_UNPACK_COMPLETED_CHROMIUM
,
1625 resource
->gl_upload_query_id
);
1627 gl
->AsyncTexImage2DCHROMIUM(GL_TEXTURE_2D
,
1629 GLInternalFormat(resource
->format
),
1630 resource
->size
.width(),
1631 resource
->size
.height(),
1633 GLDataFormat(resource
->format
),
1634 GLDataType(resource
->format
),
1637 gl
->AsyncTexSubImage2DCHROMIUM(GL_TEXTURE_2D
,
1641 resource
->size
.width(),
1642 resource
->size
.height(),
1643 GLDataFormat(resource
->format
),
1644 GLDataType(resource
->format
),
1647 gl
->EndQueryEXT(GL_ASYNC_PIXEL_UNPACK_COMPLETED_CHROMIUM
);
1648 gl
->BindBuffer(GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM
, 0);
1650 resource
->pending_set_pixels
= true;
1651 resource
->set_pixels_completion_forced
= false;
1654 void ResourceProvider::ForceSetPixelsToComplete(ResourceId id
) {
1655 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug"),
1656 "ResourceProvider::ForceSetPixelsToComplete");
1658 Resource
* resource
= GetResource(id
);
1660 DCHECK(resource
->locked_for_write
);
1661 DCHECK(resource
->pending_set_pixels
);
1662 DCHECK(!resource
->set_pixels_completion_forced
);
1664 if (resource
->gl_id
) {
1665 GLES2Interface
* gl
= ContextGL();
1666 gl
->BindTexture(GL_TEXTURE_2D
, resource
->gl_id
);
1667 gl
->WaitAsyncTexImage2DCHROMIUM(GL_TEXTURE_2D
);
1668 gl
->BindTexture(GL_TEXTURE_2D
, 0);
1671 resource
->set_pixels_completion_forced
= true;
1674 bool ResourceProvider::DidSetPixelsComplete(ResourceId id
) {
1675 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug"),
1676 "ResourceProvider::DidSetPixelsComplete");
1678 Resource
* resource
= GetResource(id
);
1680 DCHECK(resource
->locked_for_write
);
1681 DCHECK(resource
->pending_set_pixels
);
1683 if (resource
->gl_id
) {
1684 GLES2Interface
* gl
= ContextGL();
1686 DCHECK(resource
->gl_upload_query_id
);
1687 GLuint complete
= 1;
1688 gl
->GetQueryObjectuivEXT(
1689 resource
->gl_upload_query_id
, GL_QUERY_RESULT_AVAILABLE_EXT
, &complete
);
1694 resource
->pending_set_pixels
= false;
1695 UnlockForWrite(resource
);
1697 // Async set pixels commands are not necessarily processed in-sequence with
1698 // drawing commands. Read lock fences are required to ensure that async
1699 // commands don't access the resource while used for drawing.
1700 resource
->read_lock_fences_enabled
= true;
1705 void ResourceProvider::CreateForTesting(ResourceId id
) {
1706 LazyCreate(GetResource(id
));
1709 GLenum
ResourceProvider::TargetForTesting(ResourceId id
) {
1710 Resource
* resource
= GetResource(id
);
1711 return resource
->target
;
1714 void ResourceProvider::LazyCreate(Resource
* resource
) {
1715 if (resource
->type
!= RESOURCE_TYPE_GL_TEXTURE
||
1716 resource
->origin
!= Resource::INTERNAL
)
1719 if (resource
->gl_id
)
1722 DCHECK(resource
->texture_pool
);
1723 DCHECK(resource
->origin
== Resource::INTERNAL
);
1724 DCHECK(!resource
->mailbox
.IsValid());
1725 resource
->gl_id
= texture_id_allocator_
->NextId();
1727 GLES2Interface
* gl
= ContextGL();
1730 // Create and set texture properties. Allocation is delayed until needed.
1731 gl
->BindTexture(resource
->target
, resource
->gl_id
);
1732 gl
->TexParameteri(resource
->target
, GL_TEXTURE_MIN_FILTER
,
1733 resource
->original_filter
);
1734 gl
->TexParameteri(resource
->target
, GL_TEXTURE_MAG_FILTER
,
1735 resource
->original_filter
);
1736 gl
->TexParameteri(resource
->target
, GL_TEXTURE_WRAP_S
, resource
->wrap_mode
);
1737 gl
->TexParameteri(resource
->target
, GL_TEXTURE_WRAP_T
, resource
->wrap_mode
);
1738 gl
->TexParameteri(resource
->target
, GL_TEXTURE_POOL_CHROMIUM
,
1739 resource
->texture_pool
);
1740 if (use_texture_usage_hint_
&& (resource
->hint
& TEXTURE_HINT_FRAMEBUFFER
)) {
1741 gl
->TexParameteri(resource
->target
, GL_TEXTURE_USAGE_ANGLE
,
1742 GL_FRAMEBUFFER_ATTACHMENT_ANGLE
);
1746 void ResourceProvider::AllocateForTesting(ResourceId id
) {
1747 LazyAllocate(GetResource(id
));
1750 void ResourceProvider::LazyAllocate(Resource
* resource
) {
1752 if (resource
->allocated
)
1754 LazyCreate(resource
);
1755 if (!resource
->gl_id
)
1757 resource
->allocated
= true;
1758 GLES2Interface
* gl
= ContextGL();
1759 gfx::Size
& size
= resource
->size
;
1760 ResourceFormat format
= resource
->format
;
1761 gl
->BindTexture(resource
->target
, resource
->gl_id
);
1762 if (use_texture_storage_ext_
&&
1763 IsFormatSupportedForStorage(format
, use_texture_format_bgra_
) &&
1764 (resource
->hint
& TEXTURE_HINT_IMMUTABLE
)) {
1765 GLenum storage_format
= TextureToStorageFormat(format
);
1766 gl
->TexStorage2DEXT(resource
->target
, 1, storage_format
, size
.width(),
1769 // ETC1 does not support preallocation.
1770 if (format
!= ETC1
) {
1771 gl
->TexImage2D(resource
->target
, 0, GLInternalFormat(format
),
1772 size
.width(), size
.height(), 0, GLDataFormat(format
),
1773 GLDataType(format
), NULL
);
1778 void ResourceProvider::BindImageForSampling(Resource
* resource
) {
1779 GLES2Interface
* gl
= ContextGL();
1780 DCHECK(resource
->gl_id
);
1781 DCHECK(resource
->image_id
);
1783 // Release image currently bound to texture.
1784 if (resource
->bound_image_id
)
1785 gl
->ReleaseTexImage2DCHROMIUM(resource
->target
, resource
->bound_image_id
);
1786 gl
->BindTexImage2DCHROMIUM(resource
->target
, resource
->image_id
);
1787 resource
->bound_image_id
= resource
->image_id
;
1788 resource
->dirty_image
= false;
1791 void ResourceProvider::WaitSyncPointIfNeeded(ResourceId id
) {
1792 Resource
* resource
= GetResource(id
);
1793 DCHECK_EQ(resource
->exported_count
, 0);
1794 DCHECK(resource
->allocated
);
1795 if (resource
->type
!= RESOURCE_TYPE_GL_TEXTURE
|| resource
->gl_id
)
1797 if (!resource
->mailbox
.sync_point())
1799 DCHECK(resource
->mailbox
.IsValid());
1800 GLES2Interface
* gl
= ContextGL();
1802 gl
->WaitSyncPointCHROMIUM(resource
->mailbox
.sync_point());
1803 resource
->mailbox
.set_sync_point(0);
1806 GLint
ResourceProvider::GetActiveTextureUnit(GLES2Interface
* gl
) {
1807 GLint active_unit
= 0;
1808 gl
->GetIntegerv(GL_ACTIVE_TEXTURE
, &active_unit
);
1812 GLenum
ResourceProvider::GetImageTextureTarget(ResourceFormat format
) {
1813 gfx::BufferFormat buffer_format
= BufferFormat(format
);
1814 DCHECK_GT(use_image_texture_targets_
.size(),
1815 static_cast<size_t>(buffer_format
));
1816 return use_image_texture_targets_
[static_cast<size_t>(buffer_format
)];
1819 void ResourceProvider::ValidateResource(ResourceId id
) const {
1820 DCHECK(thread_checker_
.CalledOnValidThread());
1822 DCHECK(resources_
.find(id
) != resources_
.end());
1825 GLES2Interface
* ResourceProvider::ContextGL() const {
1826 ContextProvider
* context_provider
= output_surface_
->context_provider();
1827 return context_provider
? context_provider
->ContextGL() : NULL
;
1830 class GrContext
* ResourceProvider::GrContext(bool worker_context
) const {
1831 ContextProvider
* context_provider
=
1832 worker_context
? output_surface_
->worker_context_provider()
1833 : output_surface_
->context_provider();
1834 return context_provider
? context_provider
->GrContext() : NULL
;
1837 bool ResourceProvider::OnMemoryDump(
1838 const base::trace_event::MemoryDumpArgs
& args
,
1839 base::trace_event::ProcessMemoryDump
* pmd
) {
1840 DCHECK(thread_checker_
.CalledOnValidThread());
1842 const uint64 tracing_process_id
=
1843 base::trace_event::MemoryDumpManager::GetInstance()
1844 ->GetTracingProcessId();
1846 for (const auto& resource_entry
: resources_
) {
1847 const auto& resource
= resource_entry
.second
;
1849 // Resource IDs are not process-unique, so log with the ResourceProvider's
1851 std::string dump_name
=
1852 base::StringPrintf("cc/resource_memory/provider_%d/resource_%d",
1853 tracing_id_
, resource_entry
.first
);
1854 base::trace_event::MemoryAllocatorDump
* dump
=
1855 pmd
->CreateAllocatorDump(dump_name
);
1857 uint64_t total_bytes
= ResourceUtil::UncheckedSizeInBytesAligned
<size_t>(
1858 resource
.size
, resource
.format
);
1859 dump
->AddScalar(base::trace_event::MemoryAllocatorDump::kNameSize
,
1860 base::trace_event::MemoryAllocatorDump::kUnitsBytes
,
1861 static_cast<uint64_t>(total_bytes
));
1863 // Resources which are shared across processes require a shared GUID to
1864 // prevent double counting the memory. We currently support shared GUIDs for
1865 // GpuMemoryBuffer, SharedBitmap, and GL backed resources.
1866 base::trace_event::MemoryAllocatorDumpGuid guid
;
1867 if (resource
.gpu_memory_buffer
) {
1868 guid
= gfx::GetGpuMemoryBufferGUIDForTracing(
1869 tracing_process_id
, resource
.gpu_memory_buffer
->GetHandle().id
);
1870 } else if (resource
.shared_bitmap
) {
1871 guid
= GetSharedBitmapGUIDForTracing(resource
.shared_bitmap
->id());
1872 } else if (resource
.gl_id
&& resource
.allocated
) {
1874 gfx::GetGLTextureGUIDForTracing(tracing_process_id
, resource
.gl_id
);
1877 if (!guid
.empty()) {
1878 const int kImportance
= 2;
1879 pmd
->CreateSharedGlobalAllocatorDump(guid
);
1880 pmd
->AddOwnershipEdge(dump
->guid(), guid
, kImportance
);