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/gfx/gpu_memory_buffer.h"
37 #include "ui/gl/trace_util.h"
39 using gpu::gles2::GLES2Interface
;
45 virtual ~IdAllocator() {}
47 virtual GLuint
NextId() = 0;
50 IdAllocator(GLES2Interface
* gl
, size_t id_allocation_chunk_size
)
52 id_allocation_chunk_size_(id_allocation_chunk_size
),
53 ids_(new GLuint
[id_allocation_chunk_size
]),
54 next_id_index_(id_allocation_chunk_size
) {
55 DCHECK(id_allocation_chunk_size_
);
56 DCHECK_LE(id_allocation_chunk_size_
,
57 static_cast<size_t>(std::numeric_limits
<int>::max()));
61 const size_t id_allocation_chunk_size_
;
62 scoped_ptr
<GLuint
[]> ids_
;
63 size_t next_id_index_
;
68 GLenum
TextureToStorageFormat(ResourceFormat format
) {
69 GLenum storage_format
= GL_RGBA8_OES
;
74 storage_format
= GL_BGRA8_EXT
;
86 return storage_format
;
89 bool IsFormatSupportedForStorage(ResourceFormat format
, bool use_bgra
) {
106 GrPixelConfig
ToGrPixelConfig(ResourceFormat format
) {
109 return kRGBA_8888_GrPixelConfig
;
111 return kBGRA_8888_GrPixelConfig
;
113 return kRGBA_4444_GrPixelConfig
;
117 DCHECK(false) << "Unsupported resource format.";
118 return kSkia8888_GrPixelConfig
;
121 gfx::BufferFormat
ToGpuMemoryBufferFormat(ResourceFormat format
) {
124 return gfx::BufferFormat::RGBA_8888
;
126 return gfx::BufferFormat::BGRA_8888
;
128 return gfx::BufferFormat::RGBA_4444
;
137 return gfx::BufferFormat::RGBA_8888
;
140 class ScopedSetActiveTexture
{
142 ScopedSetActiveTexture(GLES2Interface
* gl
, GLenum unit
)
143 : gl_(gl
), unit_(unit
) {
144 DCHECK_EQ(GL_TEXTURE0
, ResourceProvider::GetActiveTextureUnit(gl_
));
146 if (unit_
!= GL_TEXTURE0
)
147 gl_
->ActiveTexture(unit_
);
150 ~ScopedSetActiveTexture() {
151 // Active unit being GL_TEXTURE0 is effectively the ground state.
152 if (unit_
!= GL_TEXTURE0
)
153 gl_
->ActiveTexture(GL_TEXTURE0
);
161 class TextureIdAllocator
: public IdAllocator
{
163 TextureIdAllocator(GLES2Interface
* gl
,
164 size_t texture_id_allocation_chunk_size
)
165 : IdAllocator(gl
, texture_id_allocation_chunk_size
) {}
166 ~TextureIdAllocator() override
{
168 static_cast<int>(id_allocation_chunk_size_
- next_id_index_
),
169 ids_
.get() + next_id_index_
);
172 // Overridden from IdAllocator:
173 GLuint
NextId() override
{
174 if (next_id_index_
== id_allocation_chunk_size_
) {
175 gl_
->GenTextures(static_cast<int>(id_allocation_chunk_size_
), ids_
.get());
179 return ids_
[next_id_index_
++];
183 DISALLOW_COPY_AND_ASSIGN(TextureIdAllocator
);
186 class BufferIdAllocator
: public IdAllocator
{
188 BufferIdAllocator(GLES2Interface
* gl
, size_t buffer_id_allocation_chunk_size
)
189 : IdAllocator(gl
, buffer_id_allocation_chunk_size
) {}
190 ~BufferIdAllocator() override
{
192 static_cast<int>(id_allocation_chunk_size_
- next_id_index_
),
193 ids_
.get() + next_id_index_
);
196 // Overridden from IdAllocator:
197 GLuint
NextId() override
{
198 if (next_id_index_
== id_allocation_chunk_size_
) {
199 gl_
->GenBuffers(static_cast<int>(id_allocation_chunk_size_
), ids_
.get());
203 return ids_
[next_id_index_
++];
207 DISALLOW_COPY_AND_ASSIGN(BufferIdAllocator
);
210 // Query object based fence implementation used to detect completion of copy
211 // texture operations. Fence has passed when query result is available.
212 class CopyTextureFence
: public ResourceProvider::Fence
{
214 CopyTextureFence(gpu::gles2::GLES2Interface
* gl
, unsigned query_id
)
215 : gl_(gl
), query_id_(query_id
) {}
217 // Overridden from ResourceProvider::Fence:
218 void Set() override
{}
219 bool HasPassed() override
{
220 unsigned available
= 1;
221 gl_
->GetQueryObjectuivEXT(
222 query_id_
, GL_QUERY_RESULT_AVAILABLE_EXT
, &available
);
229 void Wait() override
{
230 // ProcessResult() will wait for result to become available.
235 ~CopyTextureFence() override
{}
237 void ProcessResult() {
238 unsigned time_elapsed_us
= 0;
239 gl_
->GetQueryObjectuivEXT(query_id_
, GL_QUERY_RESULT_EXT
, &time_elapsed_us
);
240 UMA_HISTOGRAM_CUSTOM_COUNTS("Renderer4.CopyTextureLatency", time_elapsed_us
,
244 gpu::gles2::GLES2Interface
* gl_
;
247 DISALLOW_COPY_AND_ASSIGN(CopyTextureFence
);
250 // Generates process-unique IDs to use for tracing a ResourceProvider's
252 base::StaticAtomicSequenceNumber g_next_resource_provider_tracing_id
;
256 ResourceProvider::Resource::~Resource() {}
258 ResourceProvider::Resource::Resource(GLuint texture_id
,
259 const gfx::Size
& size
,
266 ResourceFormat format
)
269 gl_pixel_buffer_id(0),
270 gl_upload_query_id(0),
271 gl_read_lock_query_id(0),
273 lock_for_read_count(0),
277 locked_for_write(false),
279 marked_for_deletion(false),
280 pending_set_pixels(false),
281 set_pixels_completion_forced(false),
283 read_lock_fences_enabled(false),
284 has_shared_bitmap_id(false),
285 read_lock_fence(NULL
),
289 original_filter(filter
),
293 texture_pool(texture_pool
),
294 wrap_mode(wrap_mode
),
296 type(RESOURCE_TYPE_GL_TEXTURE
),
299 gpu_memory_buffer(NULL
) {
300 DCHECK(wrap_mode
== GL_CLAMP_TO_EDGE
|| wrap_mode
== GL_REPEAT
);
301 DCHECK_EQ(origin
== INTERNAL
, !!texture_pool
);
304 ResourceProvider::Resource::Resource(uint8_t* pixels
,
305 SharedBitmap
* bitmap
,
306 const gfx::Size
& size
,
312 gl_pixel_buffer_id(0),
313 gl_upload_query_id(0),
314 gl_read_lock_query_id(0),
316 lock_for_read_count(0),
320 locked_for_write(false),
322 marked_for_deletion(false),
323 pending_set_pixels(false),
324 set_pixels_completion_forced(false),
326 read_lock_fences_enabled(false),
327 has_shared_bitmap_id(!!bitmap
),
328 read_lock_fence(NULL
),
332 original_filter(filter
),
337 wrap_mode(wrap_mode
),
338 hint(TEXTURE_HINT_IMMUTABLE
),
339 type(RESOURCE_TYPE_BITMAP
),
341 shared_bitmap(bitmap
),
342 gpu_memory_buffer(NULL
) {
343 DCHECK(wrap_mode
== GL_CLAMP_TO_EDGE
|| wrap_mode
== GL_REPEAT
);
344 DCHECK(origin
== DELEGATED
|| pixels
);
346 shared_bitmap_id
= bitmap
->id();
349 ResourceProvider::Resource::Resource(const SharedBitmapId
& bitmap_id
,
350 const gfx::Size
& size
,
356 gl_pixel_buffer_id(0),
357 gl_upload_query_id(0),
358 gl_read_lock_query_id(0),
360 lock_for_read_count(0),
364 locked_for_write(false),
366 marked_for_deletion(false),
367 pending_set_pixels(false),
368 set_pixels_completion_forced(false),
370 read_lock_fences_enabled(false),
371 has_shared_bitmap_id(true),
372 read_lock_fence(NULL
),
376 original_filter(filter
),
381 wrap_mode(wrap_mode
),
382 hint(TEXTURE_HINT_IMMUTABLE
),
383 type(RESOURCE_TYPE_BITMAP
),
385 shared_bitmap_id(bitmap_id
),
387 gpu_memory_buffer(NULL
) {
388 DCHECK(wrap_mode
== GL_CLAMP_TO_EDGE
|| wrap_mode
== GL_REPEAT
);
391 ResourceProvider::Child::Child()
392 : marked_for_deletion(false), needs_sync_points(true) {
395 ResourceProvider::Child::~Child() {}
397 scoped_ptr
<ResourceProvider
> ResourceProvider::Create(
398 OutputSurface
* output_surface
,
399 SharedBitmapManager
* shared_bitmap_manager
,
400 gpu::GpuMemoryBufferManager
* gpu_memory_buffer_manager
,
401 BlockingTaskRunner
* blocking_main_thread_task_runner
,
402 int highp_threshold_min
,
403 bool use_rgba_4444_texture_format
,
404 size_t id_allocation_chunk_size
,
405 bool use_persistent_map_for_gpu_memory_buffers
,
406 const std::vector
<unsigned>& use_image_texture_targets
) {
407 scoped_ptr
<ResourceProvider
> resource_provider(new ResourceProvider(
408 output_surface
, shared_bitmap_manager
, gpu_memory_buffer_manager
,
409 blocking_main_thread_task_runner
, highp_threshold_min
,
410 use_rgba_4444_texture_format
, id_allocation_chunk_size
,
411 use_persistent_map_for_gpu_memory_buffers
, use_image_texture_targets
));
412 resource_provider
->Initialize();
413 return resource_provider
;
416 ResourceProvider::~ResourceProvider() {
417 base::trace_event::MemoryDumpManager::GetInstance()->UnregisterDumpProvider(
420 while (!children_
.empty())
421 DestroyChildInternal(children_
.begin(), FOR_SHUTDOWN
);
422 while (!resources_
.empty())
423 DeleteResourceInternal(resources_
.begin(), FOR_SHUTDOWN
);
425 GLES2Interface
* gl
= ContextGL();
426 if (default_resource_type_
!= RESOURCE_TYPE_GL_TEXTURE
) {
427 // We are not in GL mode, but double check before returning.
434 // Check that all GL resources has been deleted.
435 for (ResourceMap::const_iterator itr
= resources_
.begin();
436 itr
!= resources_
.end(); ++itr
) {
437 DCHECK_NE(RESOURCE_TYPE_GL_TEXTURE
, itr
->second
.type
);
439 #endif // DCHECK_IS_ON()
441 texture_id_allocator_
= nullptr;
442 buffer_id_allocator_
= nullptr;
446 bool ResourceProvider::InUseByConsumer(ResourceId id
) {
447 Resource
* resource
= GetResource(id
);
448 return resource
->lock_for_read_count
> 0 || resource
->exported_count
> 0 ||
452 bool ResourceProvider::IsLost(ResourceId id
) {
453 Resource
* resource
= GetResource(id
);
454 return resource
->lost
;
457 void ResourceProvider::LoseResourceForTesting(ResourceId id
) {
458 Resource
* resource
= GetResource(id
);
460 resource
->lost
= true;
463 ResourceId
ResourceProvider::CreateResource(const gfx::Size
& size
,
466 ResourceFormat format
) {
467 DCHECK(!size
.IsEmpty());
468 switch (default_resource_type_
) {
469 case RESOURCE_TYPE_GL_TEXTURE
:
470 return CreateGLTexture(size
,
472 GL_TEXTURE_POOL_UNMANAGED_CHROMIUM
,
476 case RESOURCE_TYPE_BITMAP
:
477 DCHECK_EQ(RGBA_8888
, format
);
478 return CreateBitmap(size
, wrap_mode
);
481 LOG(FATAL
) << "Invalid default resource type.";
485 ResourceId
ResourceProvider::CreateManagedResource(const gfx::Size
& size
,
489 ResourceFormat format
) {
490 DCHECK(!size
.IsEmpty());
491 switch (default_resource_type_
) {
492 case RESOURCE_TYPE_GL_TEXTURE
:
493 return CreateGLTexture(size
,
495 GL_TEXTURE_POOL_MANAGED_CHROMIUM
,
499 case RESOURCE_TYPE_BITMAP
:
500 DCHECK_EQ(RGBA_8888
, format
);
501 return CreateBitmap(size
, wrap_mode
);
504 LOG(FATAL
) << "Invalid default resource type.";
508 ResourceId
ResourceProvider::CreateGLTexture(const gfx::Size
& size
,
513 ResourceFormat format
) {
514 DCHECK_LE(size
.width(), max_texture_size_
);
515 DCHECK_LE(size
.height(), max_texture_size_
);
516 DCHECK(thread_checker_
.CalledOnValidThread());
518 ResourceId id
= next_id_
++;
519 Resource
* resource
= InsertResource(
520 id
, Resource(0, size
, Resource::INTERNAL
, target
, GL_LINEAR
, texture_pool
,
521 wrap_mode
, hint
, format
));
522 resource
->allocated
= false;
526 ResourceId
ResourceProvider::CreateBitmap(const gfx::Size
& size
,
528 DCHECK(thread_checker_
.CalledOnValidThread());
530 scoped_ptr
<SharedBitmap
> bitmap
=
531 shared_bitmap_manager_
->AllocateSharedBitmap(size
);
532 uint8_t* pixels
= bitmap
->pixels();
535 ResourceId id
= next_id_
++;
537 InsertResource(id
, Resource(pixels
, bitmap
.release(), size
,
538 Resource::INTERNAL
, GL_LINEAR
, wrap_mode
));
539 resource
->allocated
= true;
543 ResourceId
ResourceProvider::CreateResourceFromIOSurface(
544 const gfx::Size
& size
,
545 unsigned io_surface_id
) {
546 DCHECK(thread_checker_
.CalledOnValidThread());
548 ResourceId id
= next_id_
++;
549 Resource
* resource
= InsertResource(
550 id
, Resource(0, gfx::Size(), Resource::INTERNAL
, GL_TEXTURE_RECTANGLE_ARB
,
551 GL_LINEAR
, GL_TEXTURE_POOL_UNMANAGED_CHROMIUM
,
552 GL_CLAMP_TO_EDGE
, TEXTURE_HINT_IMMUTABLE
, RGBA_8888
));
553 LazyCreate(resource
);
554 GLES2Interface
* gl
= ContextGL();
556 gl
->BindTexture(GL_TEXTURE_RECTANGLE_ARB
, resource
->gl_id
);
557 gl
->TexImageIOSurface2DCHROMIUM(
558 GL_TEXTURE_RECTANGLE_ARB
, size
.width(), size
.height(), io_surface_id
, 0);
559 resource
->allocated
= true;
563 ResourceId
ResourceProvider::CreateResourceFromTextureMailbox(
564 const TextureMailbox
& mailbox
,
565 scoped_ptr
<SingleReleaseCallbackImpl
> release_callback_impl
,
566 bool read_lock_fences_enabled
) {
567 DCHECK(thread_checker_
.CalledOnValidThread());
568 // Just store the information. Mailbox will be consumed in LockForRead().
569 ResourceId id
= next_id_
++;
570 DCHECK(mailbox
.IsValid());
571 Resource
* resource
= nullptr;
572 if (mailbox
.IsTexture()) {
573 resource
= InsertResource(
574 id
, Resource(0, gfx::Size(), Resource::EXTERNAL
, mailbox
.target(),
575 mailbox
.nearest_neighbor() ? GL_NEAREST
: GL_LINEAR
, 0,
576 GL_CLAMP_TO_EDGE
, TEXTURE_HINT_IMMUTABLE
, RGBA_8888
));
578 DCHECK(mailbox
.IsSharedMemory());
579 SharedBitmap
* shared_bitmap
= mailbox
.shared_bitmap();
580 uint8_t* pixels
= shared_bitmap
->pixels();
582 resource
= InsertResource(
583 id
, Resource(pixels
, shared_bitmap
, mailbox
.size_in_pixels(),
584 Resource::EXTERNAL
, GL_LINEAR
, GL_CLAMP_TO_EDGE
));
586 resource
->allocated
= true;
587 resource
->mailbox
= mailbox
;
588 resource
->release_callback_impl
=
589 base::Bind(&SingleReleaseCallbackImpl::Run
,
590 base::Owned(release_callback_impl
.release()));
591 resource
->read_lock_fences_enabled
= read_lock_fences_enabled
;
595 ResourceId
ResourceProvider::CreateResourceFromTextureMailbox(
596 const TextureMailbox
& mailbox
,
597 scoped_ptr
<SingleReleaseCallbackImpl
> release_callback_impl
) {
598 return CreateResourceFromTextureMailbox(mailbox
, release_callback_impl
.Pass(),
602 void ResourceProvider::DeleteResource(ResourceId id
) {
603 DCHECK(thread_checker_
.CalledOnValidThread());
604 ResourceMap::iterator it
= resources_
.find(id
);
605 CHECK(it
!= resources_
.end());
606 Resource
* resource
= &it
->second
;
607 DCHECK(!resource
->marked_for_deletion
);
608 DCHECK_EQ(resource
->imported_count
, 0);
609 DCHECK(resource
->pending_set_pixels
|| !resource
->locked_for_write
);
611 if (resource
->exported_count
> 0 || resource
->lock_for_read_count
> 0 ||
612 !ReadLockFenceHasPassed(resource
)) {
613 resource
->marked_for_deletion
= true;
616 DeleteResourceInternal(it
, NORMAL
);
620 void ResourceProvider::DeleteResourceInternal(ResourceMap::iterator it
,
622 TRACE_EVENT0("cc", "ResourceProvider::DeleteResourceInternal");
623 Resource
* resource
= &it
->second
;
624 bool lost_resource
= resource
->lost
;
626 DCHECK(resource
->exported_count
== 0 || style
!= NORMAL
);
627 if (style
== FOR_SHUTDOWN
&& resource
->exported_count
> 0)
628 lost_resource
= true;
630 if (resource
->image_id
) {
631 DCHECK(resource
->origin
== Resource::INTERNAL
);
632 GLES2Interface
* gl
= ContextGL();
634 gl
->DestroyImageCHROMIUM(resource
->image_id
);
636 if (resource
->gl_upload_query_id
) {
637 DCHECK(resource
->origin
== Resource::INTERNAL
);
638 GLES2Interface
* gl
= ContextGL();
640 gl
->DeleteQueriesEXT(1, &resource
->gl_upload_query_id
);
642 if (resource
->gl_read_lock_query_id
) {
643 DCHECK(resource
->origin
== Resource::INTERNAL
);
644 GLES2Interface
* gl
= ContextGL();
646 gl
->DeleteQueriesEXT(1, &resource
->gl_read_lock_query_id
);
648 if (resource
->gl_pixel_buffer_id
) {
649 DCHECK(resource
->origin
== Resource::INTERNAL
);
650 GLES2Interface
* gl
= ContextGL();
652 gl
->DeleteBuffers(1, &resource
->gl_pixel_buffer_id
);
654 if (resource
->origin
== Resource::EXTERNAL
) {
655 DCHECK(resource
->mailbox
.IsValid());
656 GLuint sync_point
= resource
->mailbox
.sync_point();
657 if (resource
->type
== RESOURCE_TYPE_GL_TEXTURE
) {
658 DCHECK(resource
->mailbox
.IsTexture());
659 lost_resource
|= lost_output_surface_
;
660 GLES2Interface
* gl
= ContextGL();
662 if (resource
->gl_id
) {
663 gl
->DeleteTextures(1, &resource
->gl_id
);
666 sync_point
= gl
->InsertSyncPointCHROMIUM();
669 DCHECK(resource
->mailbox
.IsSharedMemory());
670 resource
->shared_bitmap
= nullptr;
671 resource
->pixels
= nullptr;
673 resource
->release_callback_impl
.Run(
674 sync_point
, lost_resource
, blocking_main_thread_task_runner_
);
676 if (resource
->gl_id
) {
677 GLES2Interface
* gl
= ContextGL();
679 gl
->DeleteTextures(1, &resource
->gl_id
);
682 if (resource
->shared_bitmap
) {
683 DCHECK(resource
->origin
!= Resource::EXTERNAL
);
684 DCHECK_EQ(RESOURCE_TYPE_BITMAP
, resource
->type
);
685 delete resource
->shared_bitmap
;
686 resource
->pixels
= NULL
;
688 if (resource
->pixels
) {
689 DCHECK(resource
->origin
== Resource::INTERNAL
);
690 delete[] resource
->pixels
;
691 resource
->pixels
= NULL
;
693 if (resource
->gpu_memory_buffer
) {
694 DCHECK(resource
->origin
== Resource::INTERNAL
);
695 delete resource
->gpu_memory_buffer
;
696 resource
->gpu_memory_buffer
= NULL
;
698 resources_
.erase(it
);
701 ResourceProvider::ResourceType
ResourceProvider::GetResourceType(
703 return GetResource(id
)->type
;
706 void ResourceProvider::CopyToResource(ResourceId id
,
707 const uint8_t* image
,
708 const gfx::Size
& image_size
) {
709 Resource
* resource
= GetResource(id
);
710 DCHECK(!resource
->locked_for_write
);
711 DCHECK(!resource
->lock_for_read_count
);
712 DCHECK(resource
->origin
== Resource::INTERNAL
);
713 DCHECK_EQ(resource
->exported_count
, 0);
714 DCHECK(ReadLockFenceHasPassed(resource
));
715 LazyAllocate(resource
);
717 DCHECK_EQ(image_size
.width(), resource
->size
.width());
718 DCHECK_EQ(image_size
.height(), resource
->size
.height());
720 if (resource
->type
== RESOURCE_TYPE_BITMAP
) {
721 DCHECK_EQ(RESOURCE_TYPE_BITMAP
, resource
->type
);
722 DCHECK(resource
->allocated
);
723 DCHECK_EQ(RGBA_8888
, resource
->format
);
724 SkImageInfo source_info
=
725 SkImageInfo::MakeN32Premul(image_size
.width(), image_size
.height());
726 size_t image_stride
= image_size
.width() * 4;
728 ScopedWriteLockSoftware
lock(this, id
);
729 SkCanvas
dest(lock
.sk_bitmap());
730 dest
.writePixels(source_info
, image
, image_stride
, 0, 0);
732 DCHECK(resource
->gl_id
);
733 DCHECK(!resource
->pending_set_pixels
);
734 DCHECK_EQ(resource
->target
, static_cast<GLenum
>(GL_TEXTURE_2D
));
735 GLES2Interface
* gl
= ContextGL();
737 gl
->BindTexture(GL_TEXTURE_2D
, resource
->gl_id
);
739 if (resource
->format
== ETC1
) {
740 int image_bytes
= ResourceUtil::CheckedSizeInBytes
<int>(image_size
, ETC1
);
741 gl
->CompressedTexImage2D(GL_TEXTURE_2D
, 0, GLInternalFormat(ETC1
),
742 image_size
.width(), image_size
.height(), 0,
745 gl
->TexSubImage2D(GL_TEXTURE_2D
, 0, 0, 0, image_size
.width(),
746 image_size
.height(), GLDataFormat(resource
->format
),
747 GLDataType(resource
->format
), image
);
752 ResourceProvider::Resource
* ResourceProvider::InsertResource(
754 const Resource
& resource
) {
755 std::pair
<ResourceMap::iterator
, bool> result
=
756 resources_
.insert(ResourceMap::value_type(id
, resource
));
757 DCHECK(result
.second
);
758 return &result
.first
->second
;
761 ResourceProvider::Resource
* ResourceProvider::GetResource(ResourceId id
) {
762 DCHECK(thread_checker_
.CalledOnValidThread());
764 ResourceMap::iterator it
= resources_
.find(id
);
765 DCHECK(it
!= resources_
.end());
769 const ResourceProvider::Resource
* ResourceProvider::LockForRead(ResourceId id
) {
770 Resource
* resource
= GetResource(id
);
771 DCHECK(!resource
->locked_for_write
||
772 resource
->set_pixels_completion_forced
) <<
773 "locked for write: " << resource
->locked_for_write
<<
774 " pixels completion forced: " << resource
->set_pixels_completion_forced
;
775 DCHECK_EQ(resource
->exported_count
, 0);
776 // Uninitialized! Call SetPixels or LockForWrite first.
777 DCHECK(resource
->allocated
);
779 LazyCreate(resource
);
781 if (resource
->type
== RESOURCE_TYPE_GL_TEXTURE
&& !resource
->gl_id
) {
782 DCHECK(resource
->origin
!= Resource::INTERNAL
);
783 DCHECK(resource
->mailbox
.IsTexture());
785 // Mailbox sync_points must be processed by a call to
786 // WaitSyncPointIfNeeded() prior to calling LockForRead().
787 DCHECK(!resource
->mailbox
.sync_point());
789 GLES2Interface
* gl
= ContextGL();
791 resource
->gl_id
= gl
->CreateAndConsumeTextureCHROMIUM(
792 resource
->mailbox
.target(), resource
->mailbox
.name());
795 if (!resource
->pixels
&& resource
->has_shared_bitmap_id
&&
796 shared_bitmap_manager_
) {
797 scoped_ptr
<SharedBitmap
> bitmap
=
798 shared_bitmap_manager_
->GetSharedBitmapFromId(
799 resource
->size
, resource
->shared_bitmap_id
);
801 resource
->shared_bitmap
= bitmap
.release();
802 resource
->pixels
= resource
->shared_bitmap
->pixels();
806 resource
->lock_for_read_count
++;
807 if (resource
->read_lock_fences_enabled
) {
808 if (current_read_lock_fence_
.get())
809 current_read_lock_fence_
->Set();
810 resource
->read_lock_fence
= current_read_lock_fence_
;
816 void ResourceProvider::UnlockForRead(ResourceId id
) {
817 DCHECK(thread_checker_
.CalledOnValidThread());
818 ResourceMap::iterator it
= resources_
.find(id
);
819 CHECK(it
!= resources_
.end());
821 Resource
* resource
= &it
->second
;
822 DCHECK_GT(resource
->lock_for_read_count
, 0);
823 DCHECK_EQ(resource
->exported_count
, 0);
824 resource
->lock_for_read_count
--;
825 if (resource
->marked_for_deletion
&& !resource
->lock_for_read_count
) {
826 if (!resource
->child_id
) {
827 // The resource belongs to this ResourceProvider, so it can be destroyed.
828 DeleteResourceInternal(it
, NORMAL
);
830 ChildMap::iterator child_it
= children_
.find(resource
->child_id
);
831 ResourceIdArray unused
;
832 unused
.push_back(id
);
833 DeleteAndReturnUnusedResourcesToChild(child_it
, NORMAL
, unused
);
838 ResourceProvider::Resource
* ResourceProvider::LockForWrite(ResourceId id
) {
839 Resource
* resource
= GetResource(id
);
840 DCHECK(CanLockForWrite(id
));
842 resource
->locked_for_write
= true;
846 bool ResourceProvider::CanLockForWrite(ResourceId id
) {
847 Resource
* resource
= GetResource(id
);
848 return !resource
->locked_for_write
&& !resource
->lock_for_read_count
&&
849 !resource
->exported_count
&& resource
->origin
== Resource::INTERNAL
&&
850 !resource
->lost
&& ReadLockFenceHasPassed(resource
);
853 void ResourceProvider::UnlockForWrite(ResourceProvider::Resource
* resource
) {
854 DCHECK(resource
->locked_for_write
);
855 DCHECK_EQ(resource
->exported_count
, 0);
856 DCHECK(resource
->origin
== Resource::INTERNAL
);
857 resource
->locked_for_write
= false;
860 void ResourceProvider::EnableReadLockFencesForTesting(ResourceId id
) {
861 Resource
* resource
= GetResource(id
);
863 resource
->read_lock_fences_enabled
= true;
866 ResourceProvider::ScopedReadLockGL::ScopedReadLockGL(
867 ResourceProvider
* resource_provider
,
868 ResourceId resource_id
)
869 : resource_provider_(resource_provider
),
870 resource_id_(resource_id
),
871 resource_(resource_provider
->LockForRead(resource_id
)) {
875 ResourceProvider::ScopedReadLockGL::~ScopedReadLockGL() {
876 resource_provider_
->UnlockForRead(resource_id_
);
879 ResourceProvider::ScopedSamplerGL::ScopedSamplerGL(
880 ResourceProvider
* resource_provider
,
881 ResourceId resource_id
,
883 : ScopedReadLockGL(resource_provider
, resource_id
),
885 target_(resource_provider
->BindForSampling(resource_id
, unit_
, filter
)) {
888 ResourceProvider::ScopedSamplerGL::ScopedSamplerGL(
889 ResourceProvider
* resource_provider
,
890 ResourceId resource_id
,
893 : ScopedReadLockGL(resource_provider
, resource_id
),
895 target_(resource_provider
->BindForSampling(resource_id
, unit_
, filter
)) {
898 ResourceProvider::ScopedSamplerGL::~ScopedSamplerGL() {
901 ResourceProvider::ScopedWriteLockGL::ScopedWriteLockGL(
902 ResourceProvider
* resource_provider
,
903 ResourceId resource_id
)
904 : resource_provider_(resource_provider
),
905 resource_(resource_provider
->LockForWrite(resource_id
)) {
906 resource_provider_
->LazyAllocate(resource_
);
907 texture_id_
= resource_
->gl_id
;
911 ResourceProvider::ScopedWriteLockGL::~ScopedWriteLockGL() {
912 resource_provider_
->UnlockForWrite(resource_
);
915 void ResourceProvider::PopulateSkBitmapWithResource(
916 SkBitmap
* sk_bitmap
, const Resource
* resource
) {
917 DCHECK_EQ(RGBA_8888
, resource
->format
);
918 SkImageInfo info
= SkImageInfo::MakeN32Premul(resource
->size
.width(),
919 resource
->size
.height());
920 sk_bitmap
->installPixels(info
, resource
->pixels
, info
.minRowBytes());
923 ResourceProvider::ScopedReadLockSoftware::ScopedReadLockSoftware(
924 ResourceProvider
* resource_provider
,
925 ResourceId resource_id
)
926 : resource_provider_(resource_provider
), resource_id_(resource_id
) {
927 const Resource
* resource
= resource_provider
->LockForRead(resource_id
);
928 wrap_mode_
= resource
->wrap_mode
;
929 ResourceProvider::PopulateSkBitmapWithResource(&sk_bitmap_
, resource
);
932 ResourceProvider::ScopedReadLockSoftware::~ScopedReadLockSoftware() {
933 resource_provider_
->UnlockForRead(resource_id_
);
936 ResourceProvider::ScopedWriteLockSoftware::ScopedWriteLockSoftware(
937 ResourceProvider
* resource_provider
,
938 ResourceId resource_id
)
939 : resource_provider_(resource_provider
),
940 resource_(resource_provider
->LockForWrite(resource_id
)) {
941 ResourceProvider::PopulateSkBitmapWithResource(&sk_bitmap_
, resource_
);
945 ResourceProvider::ScopedWriteLockSoftware::~ScopedWriteLockSoftware() {
946 DCHECK(thread_checker_
.CalledOnValidThread());
947 resource_provider_
->UnlockForWrite(resource_
);
950 ResourceProvider::ScopedWriteLockGpuMemoryBuffer::
951 ScopedWriteLockGpuMemoryBuffer(ResourceProvider
* resource_provider
,
952 ResourceId resource_id
)
953 : resource_provider_(resource_provider
),
954 resource_(resource_provider
->LockForWrite(resource_id
)),
955 gpu_memory_buffer_manager_(resource_provider
->gpu_memory_buffer_manager_
),
956 gpu_memory_buffer_(nullptr),
957 size_(resource_
->size
),
958 format_(resource_
->format
) {
959 DCHECK_EQ(RESOURCE_TYPE_GL_TEXTURE
, resource_
->type
);
960 std::swap(gpu_memory_buffer_
, resource_
->gpu_memory_buffer
);
963 ResourceProvider::ScopedWriteLockGpuMemoryBuffer::
964 ~ScopedWriteLockGpuMemoryBuffer() {
965 DCHECK(thread_checker_
.CalledOnValidThread());
966 resource_provider_
->UnlockForWrite(resource_
);
967 if (!gpu_memory_buffer_
)
970 resource_provider_
->LazyCreate(resource_
);
972 if (!resource_
->image_id
) {
973 GLES2Interface
* gl
= resource_provider_
->ContextGL();
976 #if defined(OS_CHROMEOS)
977 // TODO(reveman): GL_COMMANDS_ISSUED_CHROMIUM is used for synchronization
978 // on ChromeOS to avoid some performance issues. This only works with
979 // shared memory backed buffers. crbug.com/436314
980 DCHECK_EQ(gpu_memory_buffer_
->GetHandle().type
, gfx::SHARED_MEMORY_BUFFER
);
983 resource_
->image_id
= gl
->CreateImageCHROMIUM(
984 gpu_memory_buffer_
->AsClientBuffer(), size_
.width(), size_
.height(),
985 GLInternalFormat(resource_
->format
));
988 std::swap(resource_
->gpu_memory_buffer
, gpu_memory_buffer_
);
989 resource_
->allocated
= true;
990 resource_
->dirty_image
= true;
992 // GpuMemoryBuffer provides direct access to the memory used by the GPU.
993 // Read lock fences are required to ensure that we're not trying to map a
994 // buffer that is currently in-use by the GPU.
995 resource_
->read_lock_fences_enabled
= true;
998 gfx::GpuMemoryBuffer
*
999 ResourceProvider::ScopedWriteLockGpuMemoryBuffer::GetGpuMemoryBuffer() {
1000 if (gpu_memory_buffer_
)
1001 return gpu_memory_buffer_
;
1002 gfx::BufferUsage usage
=
1003 resource_provider_
->use_persistent_map_for_gpu_memory_buffers()
1004 ? gfx::BufferUsage::PERSISTENT_MAP
1005 : gfx::BufferUsage::MAP
;
1006 scoped_ptr
<gfx::GpuMemoryBuffer
> gpu_memory_buffer
=
1007 gpu_memory_buffer_manager_
->AllocateGpuMemoryBuffer(
1008 size_
, ToGpuMemoryBufferFormat(format_
), usage
);
1009 gpu_memory_buffer_
= gpu_memory_buffer
.release();
1010 return gpu_memory_buffer_
;
1013 ResourceProvider::ScopedWriteLockGr::ScopedWriteLockGr(
1014 ResourceProvider
* resource_provider
,
1015 ResourceId resource_id
)
1016 : resource_provider_(resource_provider
),
1017 resource_(resource_provider
->LockForWrite(resource_id
)) {
1018 DCHECK(thread_checker_
.CalledOnValidThread());
1019 resource_provider_
->LazyAllocate(resource_
);
1022 ResourceProvider::ScopedWriteLockGr::~ScopedWriteLockGr() {
1023 DCHECK(thread_checker_
.CalledOnValidThread());
1024 DCHECK(resource_
->locked_for_write
);
1025 resource_provider_
->UnlockForWrite(resource_
);
1028 void ResourceProvider::ScopedWriteLockGr::InitSkSurface(
1029 bool use_distance_field_text
,
1030 bool can_use_lcd_text
,
1031 int msaa_sample_count
) {
1032 DCHECK(resource_
->locked_for_write
);
1034 GrBackendTextureDesc desc
;
1035 desc
.fFlags
= kRenderTarget_GrBackendTextureFlag
;
1036 desc
.fWidth
= resource_
->size
.width();
1037 desc
.fHeight
= resource_
->size
.height();
1038 desc
.fConfig
= ToGrPixelConfig(resource_
->format
);
1039 desc
.fOrigin
= kTopLeft_GrSurfaceOrigin
;
1040 desc
.fTextureHandle
= resource_
->gl_id
;
1041 desc
.fSampleCnt
= msaa_sample_count
;
1043 bool use_worker_context
= true;
1044 class GrContext
* gr_context
=
1045 resource_provider_
->GrContext(use_worker_context
);
1047 use_distance_field_text
? SkSurfaceProps::kUseDistanceFieldFonts_Flag
: 0;
1048 // Use unknown pixel geometry to disable LCD text.
1049 SkSurfaceProps
surface_props(flags
, kUnknown_SkPixelGeometry
);
1050 if (can_use_lcd_text
) {
1051 // LegacyFontHost will get LCD text and skia figures out what type to use.
1053 SkSurfaceProps(flags
, SkSurfaceProps::kLegacyFontHost_InitType
);
1055 sk_surface_
= skia::AdoptRef(
1056 SkSurface::NewWrappedRenderTarget(gr_context
, desc
, &surface_props
));
1059 void ResourceProvider::ScopedWriteLockGr::ReleaseSkSurface() {
1060 sk_surface_
.clear();
1063 ResourceProvider::SynchronousFence::SynchronousFence(
1064 gpu::gles2::GLES2Interface
* gl
)
1065 : gl_(gl
), has_synchronized_(true) {
1068 ResourceProvider::SynchronousFence::~SynchronousFence() {
1071 void ResourceProvider::SynchronousFence::Set() {
1072 has_synchronized_
= false;
1075 bool ResourceProvider::SynchronousFence::HasPassed() {
1076 if (!has_synchronized_
) {
1077 has_synchronized_
= true;
1083 void ResourceProvider::SynchronousFence::Wait() {
1087 void ResourceProvider::SynchronousFence::Synchronize() {
1088 TRACE_EVENT0("cc", "ResourceProvider::SynchronousFence::Synchronize");
1092 ResourceProvider::ResourceProvider(
1093 OutputSurface
* output_surface
,
1094 SharedBitmapManager
* shared_bitmap_manager
,
1095 gpu::GpuMemoryBufferManager
* gpu_memory_buffer_manager
,
1096 BlockingTaskRunner
* blocking_main_thread_task_runner
,
1097 int highp_threshold_min
,
1098 bool use_rgba_4444_texture_format
,
1099 size_t id_allocation_chunk_size
,
1100 bool use_persistent_map_for_gpu_memory_buffers
,
1101 const std::vector
<unsigned>& use_image_texture_targets
)
1102 : output_surface_(output_surface
),
1103 shared_bitmap_manager_(shared_bitmap_manager
),
1104 gpu_memory_buffer_manager_(gpu_memory_buffer_manager
),
1105 blocking_main_thread_task_runner_(blocking_main_thread_task_runner
),
1106 lost_output_surface_(false),
1107 highp_threshold_min_(highp_threshold_min
),
1110 default_resource_type_(RESOURCE_TYPE_BITMAP
),
1111 use_texture_storage_ext_(false),
1112 use_texture_format_bgra_(false),
1113 use_texture_usage_hint_(false),
1114 use_compressed_texture_etc1_(false),
1115 yuv_resource_format_(LUMINANCE_8
),
1116 max_texture_size_(0),
1117 best_texture_format_(RGBA_8888
),
1118 best_render_buffer_format_(RGBA_8888
),
1119 use_rgba_4444_texture_format_(use_rgba_4444_texture_format
),
1120 id_allocation_chunk_size_(id_allocation_chunk_size
),
1121 use_sync_query_(false),
1122 use_persistent_map_for_gpu_memory_buffers_(
1123 use_persistent_map_for_gpu_memory_buffers
),
1124 use_image_texture_targets_(use_image_texture_targets
),
1125 tracing_id_(g_next_resource_provider_tracing_id
.GetNext()) {
1126 DCHECK(output_surface_
->HasClient());
1127 DCHECK(id_allocation_chunk_size_
);
1130 void ResourceProvider::Initialize() {
1131 DCHECK(thread_checker_
.CalledOnValidThread());
1133 // In certain cases, ThreadTaskRunnerHandle isn't set (Android Webview).
1134 // Don't register a dump provider in these cases.
1135 // TODO(ericrk): Get this working in Android Webview. crbug.com/517156
1136 if (base::ThreadTaskRunnerHandle::IsSet()) {
1137 base::trace_event::MemoryDumpManager::GetInstance()->RegisterDumpProvider(
1138 this, base::ThreadTaskRunnerHandle::Get());
1141 GLES2Interface
* gl
= ContextGL();
1143 default_resource_type_
= RESOURCE_TYPE_BITMAP
;
1144 // Pick an arbitrary limit here similar to what hardware might.
1145 max_texture_size_
= 16 * 1024;
1146 best_texture_format_
= RGBA_8888
;
1150 DCHECK(!texture_id_allocator_
);
1151 DCHECK(!buffer_id_allocator_
);
1153 const ContextProvider::Capabilities
& caps
=
1154 output_surface_
->context_provider()->ContextCapabilities();
1156 default_resource_type_
= RESOURCE_TYPE_GL_TEXTURE
;
1157 use_texture_storage_ext_
= caps
.gpu
.texture_storage
;
1158 use_texture_format_bgra_
= caps
.gpu
.texture_format_bgra8888
;
1159 use_texture_usage_hint_
= caps
.gpu
.texture_usage
;
1160 use_compressed_texture_etc1_
= caps
.gpu
.texture_format_etc1
;
1161 yuv_resource_format_
= caps
.gpu
.texture_rg
? RED_8
: LUMINANCE_8
;
1162 use_sync_query_
= caps
.gpu
.sync_query
;
1164 max_texture_size_
= 0; // Context expects cleared value.
1165 gl
->GetIntegerv(GL_MAX_TEXTURE_SIZE
, &max_texture_size_
);
1166 best_texture_format_
=
1167 PlatformColor::BestTextureFormat(use_texture_format_bgra_
);
1169 best_render_buffer_format_
=
1170 PlatformColor::BestTextureFormat(caps
.gpu
.render_buffer_format_bgra8888
);
1172 texture_id_allocator_
.reset(
1173 new TextureIdAllocator(gl
, id_allocation_chunk_size_
));
1174 buffer_id_allocator_
.reset(
1175 new BufferIdAllocator(gl
, id_allocation_chunk_size_
));
1178 int ResourceProvider::CreateChild(const ReturnCallback
& return_callback
) {
1179 DCHECK(thread_checker_
.CalledOnValidThread());
1182 child_info
.return_callback
= return_callback
;
1184 int child
= next_child_
++;
1185 children_
[child
] = child_info
;
1189 void ResourceProvider::SetChildNeedsSyncPoints(int child_id
, bool needs
) {
1190 ChildMap::iterator it
= children_
.find(child_id
);
1191 DCHECK(it
!= children_
.end());
1192 it
->second
.needs_sync_points
= needs
;
1195 void ResourceProvider::DestroyChild(int child_id
) {
1196 ChildMap::iterator it
= children_
.find(child_id
);
1197 DCHECK(it
!= children_
.end());
1198 DestroyChildInternal(it
, NORMAL
);
1201 void ResourceProvider::DestroyChildInternal(ChildMap::iterator it
,
1202 DeleteStyle style
) {
1203 DCHECK(thread_checker_
.CalledOnValidThread());
1205 Child
& child
= it
->second
;
1206 DCHECK(style
== FOR_SHUTDOWN
|| !child
.marked_for_deletion
);
1208 ResourceIdArray resources_for_child
;
1210 for (ResourceIdMap::iterator child_it
= child
.child_to_parent_map
.begin();
1211 child_it
!= child
.child_to_parent_map
.end();
1213 ResourceId id
= child_it
->second
;
1214 resources_for_child
.push_back(id
);
1217 child
.marked_for_deletion
= true;
1219 DeleteAndReturnUnusedResourcesToChild(it
, style
, resources_for_child
);
1222 const ResourceProvider::ResourceIdMap
& ResourceProvider::GetChildToParentMap(
1224 DCHECK(thread_checker_
.CalledOnValidThread());
1225 ChildMap::const_iterator it
= children_
.find(child
);
1226 DCHECK(it
!= children_
.end());
1227 DCHECK(!it
->second
.marked_for_deletion
);
1228 return it
->second
.child_to_parent_map
;
1231 void ResourceProvider::PrepareSendToParent(const ResourceIdArray
& resources
,
1232 TransferableResourceArray
* list
) {
1233 DCHECK(thread_checker_
.CalledOnValidThread());
1234 GLES2Interface
* gl
= ContextGL();
1235 bool need_sync_point
= false;
1236 for (ResourceIdArray::const_iterator it
= resources
.begin();
1237 it
!= resources
.end();
1239 TransferableResource resource
;
1240 TransferResource(gl
, *it
, &resource
);
1241 if (!resource
.mailbox_holder
.sync_point
&& !resource
.is_software
)
1242 need_sync_point
= true;
1243 ++resources_
.find(*it
)->second
.exported_count
;
1244 list
->push_back(resource
);
1246 if (need_sync_point
&&
1247 output_surface_
->capabilities().delegated_sync_points_required
) {
1248 GLuint sync_point
= gl
->InsertSyncPointCHROMIUM();
1249 for (TransferableResourceArray::iterator it
= list
->begin();
1252 if (!it
->mailbox_holder
.sync_point
)
1253 it
->mailbox_holder
.sync_point
= sync_point
;
1258 void ResourceProvider::ReceiveFromChild(
1259 int child
, const TransferableResourceArray
& resources
) {
1260 DCHECK(thread_checker_
.CalledOnValidThread());
1261 GLES2Interface
* gl
= ContextGL();
1262 Child
& child_info
= children_
.find(child
)->second
;
1263 DCHECK(!child_info
.marked_for_deletion
);
1264 for (TransferableResourceArray::const_iterator it
= resources
.begin();
1265 it
!= resources
.end();
1267 ResourceIdMap::iterator resource_in_map_it
=
1268 child_info
.child_to_parent_map
.find(it
->id
);
1269 if (resource_in_map_it
!= child_info
.child_to_parent_map
.end()) {
1270 Resource
* resource
= GetResource(resource_in_map_it
->second
);
1271 resource
->marked_for_deletion
= false;
1272 resource
->imported_count
++;
1276 if ((!it
->is_software
&& !gl
) ||
1277 (it
->is_software
&& !shared_bitmap_manager_
)) {
1278 TRACE_EVENT0("cc", "ResourceProvider::ReceiveFromChild dropping invalid");
1279 ReturnedResourceArray to_return
;
1280 to_return
.push_back(it
->ToReturnedResource());
1281 child_info
.return_callback
.Run(to_return
,
1282 blocking_main_thread_task_runner_
);
1286 ResourceId local_id
= next_id_
++;
1287 Resource
* resource
= nullptr;
1288 if (it
->is_software
) {
1289 resource
= InsertResource(
1291 Resource(it
->mailbox_holder
.mailbox
, it
->size
, Resource::DELEGATED
,
1292 GL_LINEAR
, it
->is_repeated
? GL_REPEAT
: GL_CLAMP_TO_EDGE
));
1294 resource
= InsertResource(
1295 local_id
, Resource(0, it
->size
, Resource::DELEGATED
,
1296 it
->mailbox_holder
.texture_target
, it
->filter
, 0,
1297 it
->is_repeated
? GL_REPEAT
: GL_CLAMP_TO_EDGE
,
1298 TEXTURE_HINT_IMMUTABLE
, it
->format
));
1299 resource
->mailbox
= TextureMailbox(it
->mailbox_holder
.mailbox
,
1300 it
->mailbox_holder
.texture_target
,
1301 it
->mailbox_holder
.sync_point
);
1302 resource
->read_lock_fences_enabled
= it
->read_lock_fences_enabled
;
1304 resource
->child_id
= child
;
1305 // Don't allocate a texture for a child.
1306 resource
->allocated
= true;
1307 resource
->imported_count
= 1;
1308 child_info
.parent_to_child_map
[local_id
] = it
->id
;
1309 child_info
.child_to_parent_map
[it
->id
] = local_id
;
1313 void ResourceProvider::DeclareUsedResourcesFromChild(
1315 const ResourceIdSet
& resources_from_child
) {
1316 DCHECK(thread_checker_
.CalledOnValidThread());
1318 ChildMap::iterator child_it
= children_
.find(child
);
1319 DCHECK(child_it
!= children_
.end());
1320 Child
& child_info
= child_it
->second
;
1321 DCHECK(!child_info
.marked_for_deletion
);
1323 ResourceIdArray unused
;
1324 for (ResourceIdMap::iterator it
= child_info
.child_to_parent_map
.begin();
1325 it
!= child_info
.child_to_parent_map
.end();
1327 ResourceId local_id
= it
->second
;
1328 bool resource_is_in_use
= resources_from_child
.count(it
->first
) > 0;
1329 if (!resource_is_in_use
)
1330 unused
.push_back(local_id
);
1332 DeleteAndReturnUnusedResourcesToChild(child_it
, NORMAL
, unused
);
1335 void ResourceProvider::ReceiveReturnsFromParent(
1336 const ReturnedResourceArray
& resources
) {
1337 DCHECK(thread_checker_
.CalledOnValidThread());
1338 GLES2Interface
* gl
= ContextGL();
1340 base::hash_map
<int, ResourceIdArray
> resources_for_child
;
1342 for (const ReturnedResource
& returned
: resources
) {
1343 ResourceId local_id
= returned
.id
;
1344 ResourceMap::iterator map_iterator
= resources_
.find(local_id
);
1345 // Resource was already lost (e.g. it belonged to a child that was
1347 if (map_iterator
== resources_
.end())
1350 Resource
* resource
= &map_iterator
->second
;
1352 CHECK_GE(resource
->exported_count
, returned
.count
);
1353 resource
->exported_count
-= returned
.count
;
1354 resource
->lost
|= returned
.lost
;
1355 if (resource
->exported_count
)
1358 if (returned
.sync_point
) {
1359 DCHECK(!resource
->has_shared_bitmap_id
);
1360 if (resource
->origin
== Resource::INTERNAL
) {
1361 DCHECK(resource
->gl_id
);
1362 gl
->WaitSyncPointCHROMIUM(returned
.sync_point
);
1364 DCHECK(!resource
->gl_id
);
1365 resource
->mailbox
.set_sync_point(returned
.sync_point
);
1369 if (!resource
->marked_for_deletion
)
1372 if (!resource
->child_id
) {
1373 // The resource belongs to this ResourceProvider, so it can be destroyed.
1374 DeleteResourceInternal(map_iterator
, NORMAL
);
1378 DCHECK(resource
->origin
== Resource::DELEGATED
);
1379 resources_for_child
[resource
->child_id
].push_back(local_id
);
1382 for (const auto& children
: resources_for_child
) {
1383 ChildMap::iterator child_it
= children_
.find(children
.first
);
1384 DCHECK(child_it
!= children_
.end());
1385 DeleteAndReturnUnusedResourcesToChild(child_it
, NORMAL
, children
.second
);
1389 void ResourceProvider::TransferResource(GLES2Interface
* gl
,
1391 TransferableResource
* resource
) {
1392 Resource
* source
= GetResource(id
);
1393 DCHECK(!source
->locked_for_write
);
1394 DCHECK(!source
->lock_for_read_count
);
1395 DCHECK(source
->origin
!= Resource::EXTERNAL
|| source
->mailbox
.IsValid());
1396 DCHECK(source
->allocated
);
1398 resource
->format
= source
->format
;
1399 resource
->mailbox_holder
.texture_target
= source
->target
;
1400 resource
->filter
= source
->filter
;
1401 resource
->size
= source
->size
;
1402 resource
->read_lock_fences_enabled
= source
->read_lock_fences_enabled
;
1403 resource
->is_repeated
= (source
->wrap_mode
== GL_REPEAT
);
1405 if (source
->type
== RESOURCE_TYPE_BITMAP
) {
1406 resource
->mailbox_holder
.mailbox
= source
->shared_bitmap_id
;
1407 resource
->is_software
= true;
1408 } else if (!source
->mailbox
.IsValid()) {
1410 DCHECK(source
->gl_id
);
1411 DCHECK(source
->origin
== Resource::INTERNAL
);
1412 if (source
->image_id
) {
1413 DCHECK(source
->dirty_image
);
1414 gl
->BindTexture(resource
->mailbox_holder
.texture_target
, source
->gl_id
);
1415 BindImageForSampling(source
);
1417 // This is a resource allocated by the compositor, we need to produce it.
1418 // Don't set a sync point, the caller will do it.
1419 gl
->GenMailboxCHROMIUM(resource
->mailbox_holder
.mailbox
.name
);
1420 gl
->ProduceTextureDirectCHROMIUM(source
->gl_id
,
1421 resource
->mailbox_holder
.texture_target
,
1422 resource
->mailbox_holder
.mailbox
.name
);
1424 source
->mailbox
= TextureMailbox(resource
->mailbox_holder
);
1426 DCHECK(source
->mailbox
.IsTexture());
1427 if (source
->image_id
&& source
->dirty_image
) {
1428 DCHECK(source
->gl_id
);
1429 DCHECK(source
->origin
== Resource::INTERNAL
);
1430 gl
->BindTexture(resource
->mailbox_holder
.texture_target
, source
->gl_id
);
1431 BindImageForSampling(source
);
1433 // This is either an external resource, or a compositor resource that we
1434 // already exported. Make sure to forward the sync point that we were given.
1435 resource
->mailbox_holder
.mailbox
= source
->mailbox
.mailbox();
1436 resource
->mailbox_holder
.texture_target
= source
->mailbox
.target();
1437 resource
->mailbox_holder
.sync_point
= source
->mailbox
.sync_point();
1438 source
->mailbox
.set_sync_point(0);
1442 void ResourceProvider::DeleteAndReturnUnusedResourcesToChild(
1443 ChildMap::iterator child_it
,
1445 const ResourceIdArray
& unused
) {
1446 DCHECK(thread_checker_
.CalledOnValidThread());
1447 DCHECK(child_it
!= children_
.end());
1448 Child
* child_info
= &child_it
->second
;
1450 if (unused
.empty() && !child_info
->marked_for_deletion
)
1453 ReturnedResourceArray to_return
;
1455 GLES2Interface
* gl
= ContextGL();
1456 bool need_sync_point
= false;
1457 for (size_t i
= 0; i
< unused
.size(); ++i
) {
1458 ResourceId local_id
= unused
[i
];
1460 ResourceMap::iterator it
= resources_
.find(local_id
);
1461 CHECK(it
!= resources_
.end());
1462 Resource
& resource
= it
->second
;
1464 DCHECK(!resource
.locked_for_write
);
1465 DCHECK(child_info
->parent_to_child_map
.count(local_id
));
1467 ResourceId child_id
= child_info
->parent_to_child_map
[local_id
];
1468 DCHECK(child_info
->child_to_parent_map
.count(child_id
));
1472 (resource
.type
== RESOURCE_TYPE_GL_TEXTURE
&& lost_output_surface_
);
1473 if (resource
.exported_count
> 0 || resource
.lock_for_read_count
> 0) {
1474 if (style
!= FOR_SHUTDOWN
) {
1475 // Defer this resource deletion.
1476 resource
.marked_for_deletion
= true;
1479 // We can't postpone the deletion, so we'll have to lose it.
1481 } else if (!ReadLockFenceHasPassed(&resource
)) {
1482 // TODO(dcastagna): see if it's possible to use this logic for
1483 // the branch above too, where the resource is locked or still exported.
1484 if (style
!= FOR_SHUTDOWN
&& !child_info
->marked_for_deletion
) {
1485 // Defer this resource deletion.
1486 resource
.marked_for_deletion
= true;
1489 // We can't postpone the deletion, so we'll have to lose it.
1493 if (gl
&& resource
.filter
!= resource
.original_filter
) {
1494 DCHECK(resource
.target
);
1495 DCHECK(resource
.gl_id
);
1497 gl
->BindTexture(resource
.target
, resource
.gl_id
);
1498 gl
->TexParameteri(resource
.target
, GL_TEXTURE_MIN_FILTER
,
1499 resource
.original_filter
);
1500 gl
->TexParameteri(resource
.target
, GL_TEXTURE_MAG_FILTER
,
1501 resource
.original_filter
);
1504 ReturnedResource returned
;
1505 returned
.id
= child_id
;
1506 returned
.sync_point
= resource
.mailbox
.sync_point();
1507 if (!returned
.sync_point
&& resource
.type
== RESOURCE_TYPE_GL_TEXTURE
)
1508 need_sync_point
= true;
1509 returned
.count
= resource
.imported_count
;
1510 returned
.lost
= is_lost
;
1511 to_return
.push_back(returned
);
1513 child_info
->parent_to_child_map
.erase(local_id
);
1514 child_info
->child_to_parent_map
.erase(child_id
);
1515 resource
.imported_count
= 0;
1516 DeleteResourceInternal(it
, style
);
1518 if (need_sync_point
&& child_info
->needs_sync_points
) {
1520 GLuint sync_point
= gl
->InsertSyncPointCHROMIUM();
1521 for (size_t i
= 0; i
< to_return
.size(); ++i
) {
1522 if (!to_return
[i
].sync_point
)
1523 to_return
[i
].sync_point
= sync_point
;
1527 if (!to_return
.empty())
1528 child_info
->return_callback
.Run(to_return
,
1529 blocking_main_thread_task_runner_
);
1531 if (child_info
->marked_for_deletion
&&
1532 child_info
->parent_to_child_map
.empty()) {
1533 DCHECK(child_info
->child_to_parent_map
.empty());
1534 children_
.erase(child_it
);
1538 void ResourceProvider::AcquirePixelBuffer(ResourceId id
) {
1539 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug"),
1540 "ResourceProvider::AcquirePixelBuffer");
1542 Resource
* resource
= GetResource(id
);
1543 DCHECK(resource
->origin
== Resource::INTERNAL
);
1544 DCHECK_EQ(resource
->exported_count
, 0);
1545 DCHECK(!resource
->image_id
);
1546 DCHECK_NE(ETC1
, resource
->format
);
1548 DCHECK_EQ(RESOURCE_TYPE_GL_TEXTURE
, resource
->type
);
1549 GLES2Interface
* gl
= ContextGL();
1551 if (!resource
->gl_pixel_buffer_id
)
1552 resource
->gl_pixel_buffer_id
= buffer_id_allocator_
->NextId();
1553 gl
->BindBuffer(GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM
,
1554 resource
->gl_pixel_buffer_id
);
1555 size_t resource_bytes
= ResourceUtil::UncheckedSizeInBytesAligned
<size_t>(
1556 resource
->size
, resource
->format
);
1557 gl
->BufferData(GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM
, resource_bytes
, NULL
,
1559 gl
->BindBuffer(GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM
, 0);
1562 void ResourceProvider::ReleasePixelBuffer(ResourceId id
) {
1563 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug"),
1564 "ResourceProvider::ReleasePixelBuffer");
1566 Resource
* resource
= GetResource(id
);
1567 DCHECK(resource
->origin
== Resource::INTERNAL
);
1568 DCHECK_EQ(resource
->exported_count
, 0);
1569 DCHECK(!resource
->image_id
);
1571 // The pixel buffer can be released while there is a pending "set pixels"
1572 // if completion has been forced. Any shared memory associated with this
1573 // pixel buffer will not be freed until the waitAsyncTexImage2DCHROMIUM
1574 // command has been processed on the service side. It is also safe to
1575 // reuse any query id associated with this resource before they complete
1576 // as each new query has a unique submit count.
1577 if (resource
->pending_set_pixels
) {
1578 DCHECK(resource
->set_pixels_completion_forced
);
1579 resource
->pending_set_pixels
= false;
1580 resource
->locked_for_write
= false;
1583 DCHECK_EQ(RESOURCE_TYPE_GL_TEXTURE
, resource
->type
);
1584 if (!resource
->gl_pixel_buffer_id
)
1586 GLES2Interface
* gl
= ContextGL();
1588 gl
->BindBuffer(GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM
,
1589 resource
->gl_pixel_buffer_id
);
1591 GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM
, 0, NULL
, GL_DYNAMIC_DRAW
);
1592 gl
->BindBuffer(GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM
, 0);
1595 uint8_t* ResourceProvider::MapPixelBuffer(ResourceId id
, int* stride
) {
1596 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug"),
1597 "ResourceProvider::MapPixelBuffer");
1599 Resource
* resource
= GetResource(id
);
1600 DCHECK(resource
->origin
== Resource::INTERNAL
);
1601 DCHECK_EQ(resource
->exported_count
, 0);
1602 DCHECK(!resource
->image_id
);
1605 DCHECK_EQ(RESOURCE_TYPE_GL_TEXTURE
, resource
->type
);
1606 GLES2Interface
* gl
= ContextGL();
1608 DCHECK(resource
->gl_pixel_buffer_id
);
1609 gl
->BindBuffer(GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM
,
1610 resource
->gl_pixel_buffer_id
);
1611 uint8_t* image
= static_cast<uint8_t*>(gl
->MapBufferCHROMIUM(
1612 GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM
, GL_WRITE_ONLY
));
1613 gl
->BindBuffer(GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM
, 0);
1614 // Buffer is required to be 4-byte aligned.
1615 CHECK(!(reinterpret_cast<intptr_t>(image
) & 3));
1619 void ResourceProvider::UnmapPixelBuffer(ResourceId id
) {
1620 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug"),
1621 "ResourceProvider::UnmapPixelBuffer");
1623 Resource
* resource
= GetResource(id
);
1624 DCHECK(resource
->origin
== Resource::INTERNAL
);
1625 DCHECK_EQ(resource
->exported_count
, 0);
1626 DCHECK(!resource
->image_id
);
1628 DCHECK_EQ(RESOURCE_TYPE_GL_TEXTURE
, resource
->type
);
1629 GLES2Interface
* gl
= ContextGL();
1631 DCHECK(resource
->gl_pixel_buffer_id
);
1632 gl
->BindBuffer(GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM
,
1633 resource
->gl_pixel_buffer_id
);
1634 gl
->UnmapBufferCHROMIUM(GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM
);
1635 gl
->BindBuffer(GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM
, 0);
1638 GLenum
ResourceProvider::BindForSampling(ResourceId resource_id
,
1641 DCHECK(thread_checker_
.CalledOnValidThread());
1642 GLES2Interface
* gl
= ContextGL();
1643 ResourceMap::iterator it
= resources_
.find(resource_id
);
1644 DCHECK(it
!= resources_
.end());
1645 Resource
* resource
= &it
->second
;
1646 DCHECK(resource
->lock_for_read_count
);
1647 DCHECK(!resource
->locked_for_write
|| resource
->set_pixels_completion_forced
);
1649 ScopedSetActiveTexture
scoped_active_tex(gl
, unit
);
1650 GLenum target
= resource
->target
;
1651 gl
->BindTexture(target
, resource
->gl_id
);
1652 if (filter
!= resource
->filter
) {
1653 gl
->TexParameteri(target
, GL_TEXTURE_MIN_FILTER
, filter
);
1654 gl
->TexParameteri(target
, GL_TEXTURE_MAG_FILTER
, filter
);
1655 resource
->filter
= filter
;
1658 if (resource
->image_id
&& resource
->dirty_image
)
1659 BindImageForSampling(resource
);
1664 void ResourceProvider::BeginSetPixels(ResourceId id
) {
1665 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug"),
1666 "ResourceProvider::BeginSetPixels");
1668 Resource
* resource
= GetResource(id
);
1669 DCHECK(!resource
->pending_set_pixels
);
1671 LazyCreate(resource
);
1672 DCHECK(resource
->origin
== Resource::INTERNAL
);
1673 DCHECK(resource
->gl_id
|| resource
->allocated
);
1674 DCHECK(ReadLockFenceHasPassed(resource
));
1675 DCHECK(!resource
->image_id
);
1677 bool allocate
= !resource
->allocated
;
1678 resource
->allocated
= true;
1681 DCHECK_EQ(RESOURCE_TYPE_GL_TEXTURE
, resource
->type
);
1682 DCHECK(resource
->gl_id
);
1683 GLES2Interface
* gl
= ContextGL();
1685 DCHECK(resource
->gl_pixel_buffer_id
);
1686 DCHECK_EQ(resource
->target
, static_cast<GLenum
>(GL_TEXTURE_2D
));
1687 gl
->BindTexture(GL_TEXTURE_2D
, resource
->gl_id
);
1688 gl
->BindBuffer(GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM
,
1689 resource
->gl_pixel_buffer_id
);
1690 if (!resource
->gl_upload_query_id
)
1691 gl
->GenQueriesEXT(1, &resource
->gl_upload_query_id
);
1692 gl
->BeginQueryEXT(GL_ASYNC_PIXEL_UNPACK_COMPLETED_CHROMIUM
,
1693 resource
->gl_upload_query_id
);
1695 gl
->AsyncTexImage2DCHROMIUM(GL_TEXTURE_2D
,
1697 GLInternalFormat(resource
->format
),
1698 resource
->size
.width(),
1699 resource
->size
.height(),
1701 GLDataFormat(resource
->format
),
1702 GLDataType(resource
->format
),
1705 gl
->AsyncTexSubImage2DCHROMIUM(GL_TEXTURE_2D
,
1709 resource
->size
.width(),
1710 resource
->size
.height(),
1711 GLDataFormat(resource
->format
),
1712 GLDataType(resource
->format
),
1715 gl
->EndQueryEXT(GL_ASYNC_PIXEL_UNPACK_COMPLETED_CHROMIUM
);
1716 gl
->BindBuffer(GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM
, 0);
1718 resource
->pending_set_pixels
= true;
1719 resource
->set_pixels_completion_forced
= false;
1722 void ResourceProvider::ForceSetPixelsToComplete(ResourceId id
) {
1723 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug"),
1724 "ResourceProvider::ForceSetPixelsToComplete");
1726 Resource
* resource
= GetResource(id
);
1728 DCHECK(resource
->locked_for_write
);
1729 DCHECK(resource
->pending_set_pixels
);
1730 DCHECK(!resource
->set_pixels_completion_forced
);
1732 if (resource
->gl_id
) {
1733 GLES2Interface
* gl
= ContextGL();
1734 gl
->BindTexture(GL_TEXTURE_2D
, resource
->gl_id
);
1735 gl
->WaitAsyncTexImage2DCHROMIUM(GL_TEXTURE_2D
);
1736 gl
->BindTexture(GL_TEXTURE_2D
, 0);
1739 resource
->set_pixels_completion_forced
= true;
1742 bool ResourceProvider::DidSetPixelsComplete(ResourceId id
) {
1743 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug"),
1744 "ResourceProvider::DidSetPixelsComplete");
1746 Resource
* resource
= GetResource(id
);
1748 DCHECK(resource
->locked_for_write
);
1749 DCHECK(resource
->pending_set_pixels
);
1751 if (resource
->gl_id
) {
1752 GLES2Interface
* gl
= ContextGL();
1754 DCHECK(resource
->gl_upload_query_id
);
1755 GLuint complete
= 1;
1756 gl
->GetQueryObjectuivEXT(
1757 resource
->gl_upload_query_id
, GL_QUERY_RESULT_AVAILABLE_EXT
, &complete
);
1762 resource
->pending_set_pixels
= false;
1763 UnlockForWrite(resource
);
1765 // Async set pixels commands are not necessarily processed in-sequence with
1766 // drawing commands. Read lock fences are required to ensure that async
1767 // commands don't access the resource while used for drawing.
1768 resource
->read_lock_fences_enabled
= true;
1773 void ResourceProvider::CreateForTesting(ResourceId id
) {
1774 LazyCreate(GetResource(id
));
1777 GLenum
ResourceProvider::TargetForTesting(ResourceId id
) {
1778 Resource
* resource
= GetResource(id
);
1779 return resource
->target
;
1782 void ResourceProvider::LazyCreate(Resource
* resource
) {
1783 if (resource
->type
!= RESOURCE_TYPE_GL_TEXTURE
||
1784 resource
->origin
!= Resource::INTERNAL
)
1787 if (resource
->gl_id
)
1790 DCHECK(resource
->texture_pool
);
1791 DCHECK(resource
->origin
== Resource::INTERNAL
);
1792 DCHECK(!resource
->mailbox
.IsValid());
1793 resource
->gl_id
= texture_id_allocator_
->NextId();
1795 GLES2Interface
* gl
= ContextGL();
1798 // Create and set texture properties. Allocation is delayed until needed.
1799 gl
->BindTexture(resource
->target
, resource
->gl_id
);
1800 gl
->TexParameteri(resource
->target
, GL_TEXTURE_MIN_FILTER
,
1801 resource
->original_filter
);
1802 gl
->TexParameteri(resource
->target
, GL_TEXTURE_MAG_FILTER
,
1803 resource
->original_filter
);
1804 gl
->TexParameteri(resource
->target
, GL_TEXTURE_WRAP_S
, resource
->wrap_mode
);
1805 gl
->TexParameteri(resource
->target
, GL_TEXTURE_WRAP_T
, resource
->wrap_mode
);
1806 gl
->TexParameteri(resource
->target
, GL_TEXTURE_POOL_CHROMIUM
,
1807 resource
->texture_pool
);
1808 if (use_texture_usage_hint_
&& (resource
->hint
& TEXTURE_HINT_FRAMEBUFFER
)) {
1809 gl
->TexParameteri(resource
->target
, GL_TEXTURE_USAGE_ANGLE
,
1810 GL_FRAMEBUFFER_ATTACHMENT_ANGLE
);
1814 void ResourceProvider::AllocateForTesting(ResourceId id
) {
1815 LazyAllocate(GetResource(id
));
1818 void ResourceProvider::LazyAllocate(Resource
* resource
) {
1820 if (resource
->allocated
)
1822 LazyCreate(resource
);
1823 if (!resource
->gl_id
)
1825 resource
->allocated
= true;
1826 GLES2Interface
* gl
= ContextGL();
1827 gfx::Size
& size
= resource
->size
;
1828 ResourceFormat format
= resource
->format
;
1829 gl
->BindTexture(resource
->target
, resource
->gl_id
);
1830 if (use_texture_storage_ext_
&&
1831 IsFormatSupportedForStorage(format
, use_texture_format_bgra_
) &&
1832 (resource
->hint
& TEXTURE_HINT_IMMUTABLE
)) {
1833 GLenum storage_format
= TextureToStorageFormat(format
);
1834 gl
->TexStorage2DEXT(resource
->target
, 1, storage_format
, size
.width(),
1837 // ETC1 does not support preallocation.
1838 if (format
!= ETC1
) {
1839 gl
->TexImage2D(resource
->target
, 0, GLInternalFormat(format
),
1840 size
.width(), size
.height(), 0, GLDataFormat(format
),
1841 GLDataType(format
), NULL
);
1846 void ResourceProvider::BindImageForSampling(Resource
* resource
) {
1847 GLES2Interface
* gl
= ContextGL();
1848 DCHECK(resource
->gl_id
);
1849 DCHECK(resource
->image_id
);
1851 // Release image currently bound to texture.
1852 if (resource
->bound_image_id
)
1853 gl
->ReleaseTexImage2DCHROMIUM(resource
->target
, resource
->bound_image_id
);
1854 gl
->BindTexImage2DCHROMIUM(resource
->target
, resource
->image_id
);
1855 resource
->bound_image_id
= resource
->image_id
;
1856 resource
->dirty_image
= false;
1859 void ResourceProvider::CopyResource(ResourceId source_id
,
1861 const gfx::Rect
& rect
) {
1862 TRACE_EVENT0("cc", "ResourceProvider::CopyResource");
1864 Resource
* source_resource
= GetResource(source_id
);
1865 DCHECK(!source_resource
->lock_for_read_count
);
1866 DCHECK(source_resource
->origin
== Resource::INTERNAL
);
1867 DCHECK_EQ(source_resource
->exported_count
, 0);
1868 DCHECK_EQ(RESOURCE_TYPE_GL_TEXTURE
, source_resource
->type
);
1869 LazyAllocate(source_resource
);
1871 Resource
* dest_resource
= GetResource(dest_id
);
1872 DCHECK(!dest_resource
->locked_for_write
);
1873 DCHECK(!dest_resource
->lock_for_read_count
);
1874 DCHECK(dest_resource
->origin
== Resource::INTERNAL
);
1875 DCHECK_EQ(dest_resource
->exported_count
, 0);
1876 DCHECK_EQ(RESOURCE_TYPE_GL_TEXTURE
, dest_resource
->type
);
1877 LazyAllocate(dest_resource
);
1879 DCHECK_EQ(source_resource
->type
, dest_resource
->type
);
1880 DCHECK_EQ(source_resource
->format
, dest_resource
->format
);
1881 DCHECK(source_resource
->size
== dest_resource
->size
);
1882 DCHECK(gfx::Rect(dest_resource
->size
).Contains(rect
));
1884 GLES2Interface
* gl
= ContextGL();
1886 if (source_resource
->image_id
&& source_resource
->dirty_image
) {
1887 gl
->BindTexture(source_resource
->target
, source_resource
->gl_id
);
1888 BindImageForSampling(source_resource
);
1890 if (use_sync_query_
) {
1891 if (!source_resource
->gl_read_lock_query_id
)
1892 gl
->GenQueriesEXT(1, &source_resource
->gl_read_lock_query_id
);
1893 #if defined(OS_CHROMEOS)
1894 // TODO(reveman): This avoids a performance problem on some ChromeOS
1895 // devices. This needs to be removed to support native GpuMemoryBuffer
1896 // implementations. crbug.com/436314
1897 gl
->BeginQueryEXT(GL_COMMANDS_ISSUED_CHROMIUM
,
1898 source_resource
->gl_read_lock_query_id
);
1900 gl
->BeginQueryEXT(GL_COMMANDS_COMPLETED_CHROMIUM
,
1901 source_resource
->gl_read_lock_query_id
);
1904 DCHECK(!dest_resource
->image_id
);
1905 dest_resource
->allocated
= true;
1906 gl
->CopySubTextureCHROMIUM(dest_resource
->target
, source_resource
->gl_id
,
1907 dest_resource
->gl_id
, rect
.x(), rect
.y(), rect
.x(),
1908 rect
.y(), rect
.width(), rect
.height(),
1909 false, false, false);
1910 if (source_resource
->gl_read_lock_query_id
) {
1911 // End query and create a read lock fence that will prevent access to
1912 // source resource until CopySubTextureCHROMIUM command has completed.
1913 #if defined(OS_CHROMEOS)
1914 gl
->EndQueryEXT(GL_COMMANDS_ISSUED_CHROMIUM
);
1916 gl
->EndQueryEXT(GL_COMMANDS_COMPLETED_CHROMIUM
);
1918 source_resource
->read_lock_fence
= make_scoped_refptr(
1919 new CopyTextureFence(gl
, source_resource
->gl_read_lock_query_id
));
1921 // Create a SynchronousFence when CHROMIUM_sync_query extension is missing.
1922 // Try to use one synchronous fence for as many CopyResource operations as
1923 // possible as that reduce the number of times we have to synchronize with
1925 if (!synchronous_fence_
.get() || synchronous_fence_
->has_synchronized())
1926 synchronous_fence_
= make_scoped_refptr(new SynchronousFence(gl
));
1927 source_resource
->read_lock_fence
= synchronous_fence_
;
1928 source_resource
->read_lock_fence
->Set();
1932 void ResourceProvider::WaitSyncPointIfNeeded(ResourceId id
) {
1933 Resource
* resource
= GetResource(id
);
1934 DCHECK_EQ(resource
->exported_count
, 0);
1935 DCHECK(resource
->allocated
);
1936 if (resource
->type
!= RESOURCE_TYPE_GL_TEXTURE
|| resource
->gl_id
)
1938 if (!resource
->mailbox
.sync_point())
1940 DCHECK(resource
->mailbox
.IsValid());
1941 GLES2Interface
* gl
= ContextGL();
1943 gl
->WaitSyncPointCHROMIUM(resource
->mailbox
.sync_point());
1944 resource
->mailbox
.set_sync_point(0);
1947 void ResourceProvider::WaitReadLockIfNeeded(ResourceId id
) {
1948 Resource
* resource
= GetResource(id
);
1949 DCHECK_EQ(resource
->exported_count
, 0);
1950 if (!resource
->read_lock_fence
.get())
1953 resource
->read_lock_fence
->Wait();
1956 GLint
ResourceProvider::GetActiveTextureUnit(GLES2Interface
* gl
) {
1957 GLint active_unit
= 0;
1958 gl
->GetIntegerv(GL_ACTIVE_TEXTURE
, &active_unit
);
1962 GLenum
ResourceProvider::GetImageTextureTarget(ResourceFormat format
) {
1963 gfx::BufferFormat buffer_format
= ToGpuMemoryBufferFormat(format
);
1964 DCHECK_GT(use_image_texture_targets_
.size(),
1965 static_cast<size_t>(buffer_format
));
1966 return use_image_texture_targets_
[static_cast<size_t>(buffer_format
)];
1969 void ResourceProvider::ValidateResource(ResourceId id
) const {
1970 DCHECK(thread_checker_
.CalledOnValidThread());
1972 DCHECK(resources_
.find(id
) != resources_
.end());
1975 GLES2Interface
* ResourceProvider::ContextGL() const {
1976 ContextProvider
* context_provider
= output_surface_
->context_provider();
1977 return context_provider
? context_provider
->ContextGL() : NULL
;
1980 class GrContext
* ResourceProvider::GrContext(bool worker_context
) const {
1981 ContextProvider
* context_provider
=
1982 worker_context
? output_surface_
->worker_context_provider()
1983 : output_surface_
->context_provider();
1984 return context_provider
? context_provider
->GrContext() : NULL
;
1987 bool ResourceProvider::OnMemoryDump(
1988 const base::trace_event::MemoryDumpArgs
& args
,
1989 base::trace_event::ProcessMemoryDump
* pmd
) {
1990 DCHECK(thread_checker_
.CalledOnValidThread());
1992 const uint64 tracing_process_id
=
1993 base::trace_event::MemoryDumpManager::GetInstance()
1994 ->GetTracingProcessId();
1996 for (const auto& resource_entry
: resources_
) {
1997 const auto& resource
= resource_entry
.second
;
1999 // Resource IDs are not process-unique, so log with the ResourceProvider's
2001 std::string dump_name
= base::StringPrintf(
2002 "cc/resource_memory/resource_provider_%d/resource_%d", tracing_id_
,
2003 resource_entry
.first
);
2004 base::trace_event::MemoryAllocatorDump
* dump
=
2005 pmd
->CreateAllocatorDump(dump_name
);
2007 uint64_t total_bytes
= ResourceUtil::UncheckedSizeInBytesAligned
<size_t>(
2008 resource
.size
, resource
.format
);
2009 dump
->AddScalar(base::trace_event::MemoryAllocatorDump::kNameSize
,
2010 base::trace_event::MemoryAllocatorDump::kUnitsBytes
,
2011 static_cast<uint64_t>(total_bytes
));
2013 // Resources which are shared across processes require a shared GUID to
2014 // prevent double counting the memory. We currently support shared GUIDs for
2015 // GpuMemoryBuffer, SharedBitmap, and GL backed resources.
2016 base::trace_event::MemoryAllocatorDumpGuid guid
;
2017 if (resource
.gpu_memory_buffer
) {
2018 guid
= gfx::GetGpuMemoryBufferGUIDForTracing(
2019 tracing_process_id
, resource
.gpu_memory_buffer
->GetHandle().id
);
2020 } else if (resource
.shared_bitmap
) {
2021 guid
= GetSharedBitmapGUIDForTracing(resource
.shared_bitmap
->id());
2022 } else if (resource
.gl_id
&& resource
.allocated
) {
2024 gfx::GetGLTextureGUIDForTracing(tracing_process_id
, resource
.gl_id
);
2027 if (!guid
.empty()) {
2028 const int kImportance
= 2;
2029 pmd
->CreateSharedGlobalAllocatorDump(guid
);
2030 pmd
->AddOwnershipEdge(dump
->guid(), guid
, kImportance
);