1 // Copyright 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "cc/resources/resource_provider.h"
10 #include "base/containers/hash_tables.h"
11 #include "base/metrics/histogram.h"
12 #include "base/numerics/safe_math.h"
13 #include "base/stl_util.h"
14 #include "base/strings/string_split.h"
15 #include "base/strings/string_util.h"
16 #include "base/strings/stringprintf.h"
17 #include "base/thread_task_runner_handle.h"
18 #include "base/trace_event/memory_dump_manager.h"
19 #include "base/trace_event/trace_event.h"
20 #include "cc/resources/platform_color.h"
21 #include "cc/resources/resource_util.h"
22 #include "cc/resources/returned_resource.h"
23 #include "cc/resources/shared_bitmap_manager.h"
24 #include "cc/resources/transferable_resource.h"
25 #include "gpu/GLES2/gl2extchromium.h"
26 #include "gpu/command_buffer/client/gles2_interface.h"
27 #include "gpu/command_buffer/client/gpu_memory_buffer_manager.h"
28 #include "third_party/khronos/GLES2/gl2.h"
29 #include "third_party/khronos/GLES2/gl2ext.h"
30 #include "third_party/skia/include/core/SkSurface.h"
31 #include "third_party/skia/include/gpu/GrContext.h"
32 #include "third_party/skia/include/gpu/GrTextureProvider.h"
33 #include "ui/gfx/geometry/rect.h"
34 #include "ui/gfx/geometry/vector2d.h"
35 #include "ui/gfx/gpu_memory_buffer.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 gfx::BufferFormat
ToGpuMemoryBufferFormat(ResourceFormat format
) {
123 return gfx::BufferFormat::RGBA_8888
;
125 return gfx::BufferFormat::BGRA_8888
;
127 return gfx::BufferFormat::RGBA_4444
;
136 return gfx::BufferFormat::RGBA_8888
;
139 class ScopedSetActiveTexture
{
141 ScopedSetActiveTexture(GLES2Interface
* gl
, GLenum unit
)
142 : gl_(gl
), unit_(unit
) {
143 DCHECK_EQ(GL_TEXTURE0
, ResourceProvider::GetActiveTextureUnit(gl_
));
145 if (unit_
!= GL_TEXTURE0
)
146 gl_
->ActiveTexture(unit_
);
149 ~ScopedSetActiveTexture() {
150 // Active unit being GL_TEXTURE0 is effectively the ground state.
151 if (unit_
!= GL_TEXTURE0
)
152 gl_
->ActiveTexture(GL_TEXTURE0
);
160 class TextureIdAllocator
: public IdAllocator
{
162 TextureIdAllocator(GLES2Interface
* gl
,
163 size_t texture_id_allocation_chunk_size
)
164 : IdAllocator(gl
, texture_id_allocation_chunk_size
) {}
165 ~TextureIdAllocator() override
{
167 static_cast<int>(id_allocation_chunk_size_
- next_id_index_
),
168 ids_
.get() + next_id_index_
);
171 // Overridden from IdAllocator:
172 GLuint
NextId() override
{
173 if (next_id_index_
== id_allocation_chunk_size_
) {
174 gl_
->GenTextures(static_cast<int>(id_allocation_chunk_size_
), ids_
.get());
178 return ids_
[next_id_index_
++];
182 DISALLOW_COPY_AND_ASSIGN(TextureIdAllocator
);
185 class BufferIdAllocator
: public IdAllocator
{
187 BufferIdAllocator(GLES2Interface
* gl
, size_t buffer_id_allocation_chunk_size
)
188 : IdAllocator(gl
, buffer_id_allocation_chunk_size
) {}
189 ~BufferIdAllocator() override
{
191 static_cast<int>(id_allocation_chunk_size_
- next_id_index_
),
192 ids_
.get() + next_id_index_
);
195 // Overridden from IdAllocator:
196 GLuint
NextId() override
{
197 if (next_id_index_
== id_allocation_chunk_size_
) {
198 gl_
->GenBuffers(static_cast<int>(id_allocation_chunk_size_
), ids_
.get());
202 return ids_
[next_id_index_
++];
206 DISALLOW_COPY_AND_ASSIGN(BufferIdAllocator
);
209 // Query object based fence implementation used to detect completion of copy
210 // texture operations. Fence has passed when query result is available.
211 class CopyTextureFence
: public ResourceProvider::Fence
{
213 CopyTextureFence(gpu::gles2::GLES2Interface
* gl
, unsigned query_id
)
214 : gl_(gl
), query_id_(query_id
) {}
216 // Overridden from ResourceProvider::Fence:
217 void Set() override
{}
218 bool HasPassed() override
{
219 unsigned available
= 1;
220 gl_
->GetQueryObjectuivEXT(
221 query_id_
, GL_QUERY_RESULT_AVAILABLE_EXT
, &available
);
228 void Wait() override
{
229 // ProcessResult() will wait for result to become available.
234 ~CopyTextureFence() override
{}
236 void ProcessResult() {
237 unsigned time_elapsed_us
= 0;
238 gl_
->GetQueryObjectuivEXT(query_id_
, GL_QUERY_RESULT_EXT
, &time_elapsed_us
);
239 UMA_HISTOGRAM_CUSTOM_COUNTS("Renderer4.CopyTextureLatency", time_elapsed_us
,
243 gpu::gles2::GLES2Interface
* gl_
;
246 DISALLOW_COPY_AND_ASSIGN(CopyTextureFence
);
251 ResourceProvider::Resource::~Resource() {}
253 ResourceProvider::Resource::Resource(GLuint texture_id
,
254 const gfx::Size
& size
,
261 ResourceFormat format
)
264 gl_pixel_buffer_id(0),
265 gl_upload_query_id(0),
266 gl_read_lock_query_id(0),
268 lock_for_read_count(0),
272 locked_for_write(false),
274 marked_for_deletion(false),
275 pending_set_pixels(false),
276 set_pixels_completion_forced(false),
278 read_lock_fences_enabled(false),
279 has_shared_bitmap_id(false),
280 read_lock_fence(NULL
),
284 original_filter(filter
),
288 texture_pool(texture_pool
),
289 wrap_mode(wrap_mode
),
291 type(RESOURCE_TYPE_GL_TEXTURE
),
294 gpu_memory_buffer(NULL
) {
295 DCHECK(wrap_mode
== GL_CLAMP_TO_EDGE
|| wrap_mode
== GL_REPEAT
);
296 DCHECK_EQ(origin
== INTERNAL
, !!texture_pool
);
299 ResourceProvider::Resource::Resource(uint8_t* pixels
,
300 SharedBitmap
* bitmap
,
301 const gfx::Size
& size
,
307 gl_pixel_buffer_id(0),
308 gl_upload_query_id(0),
309 gl_read_lock_query_id(0),
311 lock_for_read_count(0),
315 locked_for_write(false),
317 marked_for_deletion(false),
318 pending_set_pixels(false),
319 set_pixels_completion_forced(false),
321 read_lock_fences_enabled(false),
322 has_shared_bitmap_id(!!bitmap
),
323 read_lock_fence(NULL
),
327 original_filter(filter
),
332 wrap_mode(wrap_mode
),
333 hint(TEXTURE_HINT_IMMUTABLE
),
334 type(RESOURCE_TYPE_BITMAP
),
336 shared_bitmap(bitmap
),
337 gpu_memory_buffer(NULL
) {
338 DCHECK(wrap_mode
== GL_CLAMP_TO_EDGE
|| wrap_mode
== GL_REPEAT
);
339 DCHECK(origin
== DELEGATED
|| pixels
);
341 shared_bitmap_id
= bitmap
->id();
344 ResourceProvider::Resource::Resource(const SharedBitmapId
& bitmap_id
,
345 const gfx::Size
& size
,
351 gl_pixel_buffer_id(0),
352 gl_upload_query_id(0),
353 gl_read_lock_query_id(0),
355 lock_for_read_count(0),
359 locked_for_write(false),
361 marked_for_deletion(false),
362 pending_set_pixels(false),
363 set_pixels_completion_forced(false),
365 read_lock_fences_enabled(false),
366 has_shared_bitmap_id(true),
367 read_lock_fence(NULL
),
371 original_filter(filter
),
376 wrap_mode(wrap_mode
),
377 hint(TEXTURE_HINT_IMMUTABLE
),
378 type(RESOURCE_TYPE_BITMAP
),
380 shared_bitmap_id(bitmap_id
),
382 gpu_memory_buffer(NULL
) {
383 DCHECK(wrap_mode
== GL_CLAMP_TO_EDGE
|| wrap_mode
== GL_REPEAT
);
386 ResourceProvider::Child::Child()
387 : marked_for_deletion(false), needs_sync_points(true) {
390 ResourceProvider::Child::~Child() {}
392 scoped_ptr
<ResourceProvider
> ResourceProvider::Create(
393 OutputSurface
* output_surface
,
394 SharedBitmapManager
* shared_bitmap_manager
,
395 gpu::GpuMemoryBufferManager
* gpu_memory_buffer_manager
,
396 BlockingTaskRunner
* blocking_main_thread_task_runner
,
397 int highp_threshold_min
,
398 bool use_rgba_4444_texture_format
,
399 size_t id_allocation_chunk_size
,
400 bool use_persistent_map_for_gpu_memory_buffers
) {
401 scoped_ptr
<ResourceProvider
> resource_provider(new ResourceProvider(
402 output_surface
, shared_bitmap_manager
, gpu_memory_buffer_manager
,
403 blocking_main_thread_task_runner
, highp_threshold_min
,
404 use_rgba_4444_texture_format
, id_allocation_chunk_size
,
405 use_persistent_map_for_gpu_memory_buffers
));
406 resource_provider
->Initialize();
407 return resource_provider
;
410 ResourceProvider::~ResourceProvider() {
411 base::trace_event::MemoryDumpManager::GetInstance()->UnregisterDumpProvider(
414 while (!children_
.empty())
415 DestroyChildInternal(children_
.begin(), FOR_SHUTDOWN
);
416 while (!resources_
.empty())
417 DeleteResourceInternal(resources_
.begin(), FOR_SHUTDOWN
);
419 GLES2Interface
* gl
= ContextGL();
420 if (default_resource_type_
!= RESOURCE_TYPE_GL_TEXTURE
) {
421 // We are not in GL mode, but double check before returning.
428 // Check that all GL resources has been deleted.
429 for (ResourceMap::const_iterator itr
= resources_
.begin();
430 itr
!= resources_
.end(); ++itr
) {
431 DCHECK_NE(RESOURCE_TYPE_GL_TEXTURE
, itr
->second
.type
);
433 #endif // DCHECK_IS_ON()
435 texture_id_allocator_
= nullptr;
436 buffer_id_allocator_
= nullptr;
440 bool ResourceProvider::InUseByConsumer(ResourceId id
) {
441 Resource
* resource
= GetResource(id
);
442 return resource
->lock_for_read_count
> 0 || resource
->exported_count
> 0 ||
446 bool ResourceProvider::IsLost(ResourceId id
) {
447 Resource
* resource
= GetResource(id
);
448 return resource
->lost
;
451 void ResourceProvider::LoseResourceForTesting(ResourceId id
) {
452 Resource
* resource
= GetResource(id
);
454 resource
->lost
= true;
457 ResourceId
ResourceProvider::CreateResource(const gfx::Size
& size
,
460 ResourceFormat format
) {
461 DCHECK(!size
.IsEmpty());
462 switch (default_resource_type_
) {
463 case RESOURCE_TYPE_GL_TEXTURE
:
464 return CreateGLTexture(size
,
466 GL_TEXTURE_POOL_UNMANAGED_CHROMIUM
,
470 case RESOURCE_TYPE_BITMAP
:
471 DCHECK_EQ(RGBA_8888
, format
);
472 return CreateBitmap(size
, wrap_mode
);
475 LOG(FATAL
) << "Invalid default resource type.";
479 ResourceId
ResourceProvider::CreateManagedResource(const gfx::Size
& size
,
483 ResourceFormat format
) {
484 DCHECK(!size
.IsEmpty());
485 switch (default_resource_type_
) {
486 case RESOURCE_TYPE_GL_TEXTURE
:
487 return CreateGLTexture(size
,
489 GL_TEXTURE_POOL_MANAGED_CHROMIUM
,
493 case RESOURCE_TYPE_BITMAP
:
494 DCHECK_EQ(RGBA_8888
, format
);
495 return CreateBitmap(size
, wrap_mode
);
498 LOG(FATAL
) << "Invalid default resource type.";
502 ResourceId
ResourceProvider::CreateGLTexture(const gfx::Size
& size
,
507 ResourceFormat format
) {
508 DCHECK_LE(size
.width(), max_texture_size_
);
509 DCHECK_LE(size
.height(), max_texture_size_
);
510 DCHECK(thread_checker_
.CalledOnValidThread());
512 ResourceId id
= next_id_
++;
513 Resource
* resource
= InsertResource(
514 id
, Resource(0, size
, Resource::INTERNAL
, target
, GL_LINEAR
, texture_pool
,
515 wrap_mode
, hint
, format
));
516 resource
->allocated
= false;
520 ResourceId
ResourceProvider::CreateBitmap(const gfx::Size
& size
,
522 DCHECK(thread_checker_
.CalledOnValidThread());
524 scoped_ptr
<SharedBitmap
> bitmap
=
525 shared_bitmap_manager_
->AllocateSharedBitmap(size
);
526 uint8_t* pixels
= bitmap
->pixels();
529 ResourceId id
= next_id_
++;
531 InsertResource(id
, Resource(pixels
, bitmap
.release(), size
,
532 Resource::INTERNAL
, GL_LINEAR
, wrap_mode
));
533 resource
->allocated
= true;
537 ResourceId
ResourceProvider::CreateResourceFromIOSurface(
538 const gfx::Size
& size
,
539 unsigned io_surface_id
) {
540 DCHECK(thread_checker_
.CalledOnValidThread());
542 ResourceId id
= next_id_
++;
543 Resource
* resource
= InsertResource(
544 id
, Resource(0, gfx::Size(), Resource::INTERNAL
, GL_TEXTURE_RECTANGLE_ARB
,
545 GL_LINEAR
, GL_TEXTURE_POOL_UNMANAGED_CHROMIUM
,
546 GL_CLAMP_TO_EDGE
, TEXTURE_HINT_IMMUTABLE
, RGBA_8888
));
547 LazyCreate(resource
);
548 GLES2Interface
* gl
= ContextGL();
550 gl
->BindTexture(GL_TEXTURE_RECTANGLE_ARB
, resource
->gl_id
);
551 gl
->TexImageIOSurface2DCHROMIUM(
552 GL_TEXTURE_RECTANGLE_ARB
, size
.width(), size
.height(), io_surface_id
, 0);
553 resource
->allocated
= true;
557 ResourceId
ResourceProvider::CreateResourceFromTextureMailbox(
558 const TextureMailbox
& mailbox
,
559 scoped_ptr
<SingleReleaseCallbackImpl
> release_callback_impl
,
560 bool read_lock_fences_enabled
) {
561 DCHECK(thread_checker_
.CalledOnValidThread());
562 // Just store the information. Mailbox will be consumed in LockForRead().
563 ResourceId id
= next_id_
++;
564 DCHECK(mailbox
.IsValid());
565 Resource
* resource
= nullptr;
566 if (mailbox
.IsTexture()) {
567 resource
= InsertResource(
568 id
, Resource(0, gfx::Size(), Resource::EXTERNAL
, mailbox
.target(),
569 mailbox
.nearest_neighbor() ? GL_NEAREST
: GL_LINEAR
, 0,
570 GL_CLAMP_TO_EDGE
, TEXTURE_HINT_IMMUTABLE
, RGBA_8888
));
572 DCHECK(mailbox
.IsSharedMemory());
573 SharedBitmap
* shared_bitmap
= mailbox
.shared_bitmap();
574 uint8_t* pixels
= shared_bitmap
->pixels();
576 resource
= InsertResource(
577 id
, Resource(pixels
, shared_bitmap
, mailbox
.size_in_pixels(),
578 Resource::EXTERNAL
, GL_LINEAR
, GL_CLAMP_TO_EDGE
));
580 resource
->allocated
= true;
581 resource
->mailbox
= mailbox
;
582 resource
->release_callback_impl
=
583 base::Bind(&SingleReleaseCallbackImpl::Run
,
584 base::Owned(release_callback_impl
.release()));
585 resource
->read_lock_fences_enabled
= read_lock_fences_enabled
;
589 ResourceId
ResourceProvider::CreateResourceFromTextureMailbox(
590 const TextureMailbox
& mailbox
,
591 scoped_ptr
<SingleReleaseCallbackImpl
> release_callback_impl
) {
592 return CreateResourceFromTextureMailbox(mailbox
, release_callback_impl
.Pass(),
596 void ResourceProvider::DeleteResource(ResourceId id
) {
597 DCHECK(thread_checker_
.CalledOnValidThread());
598 ResourceMap::iterator it
= resources_
.find(id
);
599 CHECK(it
!= resources_
.end());
600 Resource
* resource
= &it
->second
;
601 DCHECK(!resource
->marked_for_deletion
);
602 DCHECK_EQ(resource
->imported_count
, 0);
603 DCHECK(resource
->pending_set_pixels
|| !resource
->locked_for_write
);
605 if (resource
->exported_count
> 0 || resource
->lock_for_read_count
> 0 ||
606 !ReadLockFenceHasPassed(resource
)) {
607 resource
->marked_for_deletion
= true;
610 DeleteResourceInternal(it
, NORMAL
);
614 void ResourceProvider::DeleteResourceInternal(ResourceMap::iterator it
,
616 TRACE_EVENT0("cc", "ResourceProvider::DeleteResourceInternal");
617 Resource
* resource
= &it
->second
;
618 bool lost_resource
= resource
->lost
;
620 DCHECK(resource
->exported_count
== 0 || style
!= NORMAL
);
621 if (style
== FOR_SHUTDOWN
&& resource
->exported_count
> 0)
622 lost_resource
= true;
624 if (resource
->image_id
) {
625 DCHECK(resource
->origin
== Resource::INTERNAL
);
626 GLES2Interface
* gl
= ContextGL();
628 gl
->DestroyImageCHROMIUM(resource
->image_id
);
630 if (resource
->gl_upload_query_id
) {
631 DCHECK(resource
->origin
== Resource::INTERNAL
);
632 GLES2Interface
* gl
= ContextGL();
634 gl
->DeleteQueriesEXT(1, &resource
->gl_upload_query_id
);
636 if (resource
->gl_read_lock_query_id
) {
637 DCHECK(resource
->origin
== Resource::INTERNAL
);
638 GLES2Interface
* gl
= ContextGL();
640 gl
->DeleteQueriesEXT(1, &resource
->gl_read_lock_query_id
);
642 if (resource
->gl_pixel_buffer_id
) {
643 DCHECK(resource
->origin
== Resource::INTERNAL
);
644 GLES2Interface
* gl
= ContextGL();
646 gl
->DeleteBuffers(1, &resource
->gl_pixel_buffer_id
);
648 if (resource
->origin
== Resource::EXTERNAL
) {
649 DCHECK(resource
->mailbox
.IsValid());
650 GLuint sync_point
= resource
->mailbox
.sync_point();
651 if (resource
->type
== RESOURCE_TYPE_GL_TEXTURE
) {
652 DCHECK(resource
->mailbox
.IsTexture());
653 lost_resource
|= lost_output_surface_
;
654 GLES2Interface
* gl
= ContextGL();
656 if (resource
->gl_id
) {
657 gl
->DeleteTextures(1, &resource
->gl_id
);
660 sync_point
= gl
->InsertSyncPointCHROMIUM();
663 DCHECK(resource
->mailbox
.IsSharedMemory());
664 resource
->shared_bitmap
= nullptr;
665 resource
->pixels
= nullptr;
667 resource
->release_callback_impl
.Run(
668 sync_point
, lost_resource
, blocking_main_thread_task_runner_
);
670 if (resource
->gl_id
) {
671 GLES2Interface
* gl
= ContextGL();
673 gl
->DeleteTextures(1, &resource
->gl_id
);
676 if (resource
->shared_bitmap
) {
677 DCHECK(resource
->origin
!= Resource::EXTERNAL
);
678 DCHECK_EQ(RESOURCE_TYPE_BITMAP
, resource
->type
);
679 delete resource
->shared_bitmap
;
680 resource
->pixels
= NULL
;
682 if (resource
->pixels
) {
683 DCHECK(resource
->origin
== Resource::INTERNAL
);
684 delete[] resource
->pixels
;
685 resource
->pixels
= NULL
;
687 if (resource
->gpu_memory_buffer
) {
688 DCHECK(resource
->origin
== Resource::INTERNAL
);
689 delete resource
->gpu_memory_buffer
;
690 resource
->gpu_memory_buffer
= NULL
;
692 resources_
.erase(it
);
695 ResourceProvider::ResourceType
ResourceProvider::GetResourceType(
697 return GetResource(id
)->type
;
700 void ResourceProvider::CopyToResource(ResourceId id
,
701 const uint8_t* image
,
702 const gfx::Size
& image_size
) {
703 Resource
* resource
= GetResource(id
);
704 DCHECK(!resource
->locked_for_write
);
705 DCHECK(!resource
->lock_for_read_count
);
706 DCHECK(resource
->origin
== Resource::INTERNAL
);
707 DCHECK_EQ(resource
->exported_count
, 0);
708 DCHECK(ReadLockFenceHasPassed(resource
));
709 LazyAllocate(resource
);
711 DCHECK_EQ(image_size
.width(), resource
->size
.width());
712 DCHECK_EQ(image_size
.height(), resource
->size
.height());
714 if (resource
->type
== RESOURCE_TYPE_BITMAP
) {
715 DCHECK_EQ(RESOURCE_TYPE_BITMAP
, resource
->type
);
716 DCHECK(resource
->allocated
);
717 DCHECK_EQ(RGBA_8888
, resource
->format
);
718 SkImageInfo source_info
=
719 SkImageInfo::MakeN32Premul(image_size
.width(), image_size
.height());
720 size_t image_stride
= image_size
.width() * 4;
722 ScopedWriteLockSoftware
lock(this, id
);
723 SkCanvas
dest(lock
.sk_bitmap());
724 dest
.writePixels(source_info
, image
, image_stride
, 0, 0);
726 DCHECK(resource
->gl_id
);
727 DCHECK(!resource
->pending_set_pixels
);
728 DCHECK_EQ(resource
->target
, static_cast<GLenum
>(GL_TEXTURE_2D
));
729 GLES2Interface
* gl
= ContextGL();
731 gl
->BindTexture(GL_TEXTURE_2D
, resource
->gl_id
);
733 if (resource
->format
== ETC1
) {
734 int image_bytes
= ResourceUtil::CheckedSizeInBytes
<int>(image_size
, ETC1
);
735 gl
->CompressedTexImage2D(GL_TEXTURE_2D
, 0, GLInternalFormat(ETC1
),
736 image_size
.width(), image_size
.height(), 0,
739 gl
->TexSubImage2D(GL_TEXTURE_2D
, 0, 0, 0, image_size
.width(),
740 image_size
.height(), GLDataFormat(resource
->format
),
741 GLDataType(resource
->format
), image
);
746 ResourceProvider::Resource
* ResourceProvider::InsertResource(
748 const Resource
& resource
) {
749 std::pair
<ResourceMap::iterator
, bool> result
=
750 resources_
.insert(ResourceMap::value_type(id
, resource
));
751 DCHECK(result
.second
);
752 return &result
.first
->second
;
755 ResourceProvider::Resource
* ResourceProvider::GetResource(ResourceId id
) {
756 DCHECK(thread_checker_
.CalledOnValidThread());
758 ResourceMap::iterator it
= resources_
.find(id
);
759 DCHECK(it
!= resources_
.end());
763 const ResourceProvider::Resource
* ResourceProvider::LockForRead(ResourceId id
) {
764 Resource
* resource
= GetResource(id
);
765 DCHECK(!resource
->locked_for_write
||
766 resource
->set_pixels_completion_forced
) <<
767 "locked for write: " << resource
->locked_for_write
<<
768 " pixels completion forced: " << resource
->set_pixels_completion_forced
;
769 DCHECK_EQ(resource
->exported_count
, 0);
770 // Uninitialized! Call SetPixels or LockForWrite first.
771 DCHECK(resource
->allocated
);
773 LazyCreate(resource
);
775 if (resource
->type
== RESOURCE_TYPE_GL_TEXTURE
&& !resource
->gl_id
) {
776 DCHECK(resource
->origin
!= Resource::INTERNAL
);
777 DCHECK(resource
->mailbox
.IsTexture());
779 // Mailbox sync_points must be processed by a call to
780 // WaitSyncPointIfNeeded() prior to calling LockForRead().
781 DCHECK(!resource
->mailbox
.sync_point());
783 GLES2Interface
* gl
= ContextGL();
785 resource
->gl_id
= gl
->CreateAndConsumeTextureCHROMIUM(
786 resource
->mailbox
.target(), resource
->mailbox
.name());
789 if (!resource
->pixels
&& resource
->has_shared_bitmap_id
&&
790 shared_bitmap_manager_
) {
791 scoped_ptr
<SharedBitmap
> bitmap
=
792 shared_bitmap_manager_
->GetSharedBitmapFromId(
793 resource
->size
, resource
->shared_bitmap_id
);
795 resource
->shared_bitmap
= bitmap
.release();
796 resource
->pixels
= resource
->shared_bitmap
->pixels();
800 resource
->lock_for_read_count
++;
801 if (resource
->read_lock_fences_enabled
) {
802 if (current_read_lock_fence_
.get())
803 current_read_lock_fence_
->Set();
804 resource
->read_lock_fence
= current_read_lock_fence_
;
810 void ResourceProvider::UnlockForRead(ResourceId id
) {
811 DCHECK(thread_checker_
.CalledOnValidThread());
812 ResourceMap::iterator it
= resources_
.find(id
);
813 CHECK(it
!= resources_
.end());
815 Resource
* resource
= &it
->second
;
816 DCHECK_GT(resource
->lock_for_read_count
, 0);
817 DCHECK_EQ(resource
->exported_count
, 0);
818 resource
->lock_for_read_count
--;
819 if (resource
->marked_for_deletion
&& !resource
->lock_for_read_count
) {
820 if (!resource
->child_id
) {
821 // The resource belongs to this ResourceProvider, so it can be destroyed.
822 DeleteResourceInternal(it
, NORMAL
);
824 ChildMap::iterator child_it
= children_
.find(resource
->child_id
);
825 ResourceIdArray unused
;
826 unused
.push_back(id
);
827 DeleteAndReturnUnusedResourcesToChild(child_it
, NORMAL
, unused
);
832 ResourceProvider::Resource
* ResourceProvider::LockForWrite(ResourceId id
) {
833 Resource
* resource
= GetResource(id
);
834 DCHECK(CanLockForWrite(id
));
836 resource
->locked_for_write
= true;
840 bool ResourceProvider::CanLockForWrite(ResourceId id
) {
841 Resource
* resource
= GetResource(id
);
842 return !resource
->locked_for_write
&& !resource
->lock_for_read_count
&&
843 !resource
->exported_count
&& resource
->origin
== Resource::INTERNAL
&&
844 !resource
->lost
&& ReadLockFenceHasPassed(resource
);
847 void ResourceProvider::UnlockForWrite(ResourceProvider::Resource
* resource
) {
848 DCHECK(resource
->locked_for_write
);
849 DCHECK_EQ(resource
->exported_count
, 0);
850 DCHECK(resource
->origin
== Resource::INTERNAL
);
851 resource
->locked_for_write
= false;
854 void ResourceProvider::EnableReadLockFencesForTesting(ResourceId id
) {
855 Resource
* resource
= GetResource(id
);
857 resource
->read_lock_fences_enabled
= true;
860 ResourceProvider::ScopedReadLockGL::ScopedReadLockGL(
861 ResourceProvider
* resource_provider
,
862 ResourceId resource_id
)
863 : resource_provider_(resource_provider
),
864 resource_id_(resource_id
),
865 resource_(resource_provider
->LockForRead(resource_id
)) {
869 ResourceProvider::ScopedReadLockGL::~ScopedReadLockGL() {
870 resource_provider_
->UnlockForRead(resource_id_
);
873 ResourceProvider::ScopedSamplerGL::ScopedSamplerGL(
874 ResourceProvider
* resource_provider
,
875 ResourceId resource_id
,
877 : ScopedReadLockGL(resource_provider
, resource_id
),
879 target_(resource_provider
->BindForSampling(resource_id
, unit_
, filter
)) {
882 ResourceProvider::ScopedSamplerGL::ScopedSamplerGL(
883 ResourceProvider
* resource_provider
,
884 ResourceId resource_id
,
887 : ScopedReadLockGL(resource_provider
, resource_id
),
889 target_(resource_provider
->BindForSampling(resource_id
, unit_
, filter
)) {
892 ResourceProvider::ScopedSamplerGL::~ScopedSamplerGL() {
895 ResourceProvider::ScopedWriteLockGL::ScopedWriteLockGL(
896 ResourceProvider
* resource_provider
,
897 ResourceId resource_id
)
898 : resource_provider_(resource_provider
),
899 resource_(resource_provider
->LockForWrite(resource_id
)) {
900 resource_provider_
->LazyAllocate(resource_
);
901 texture_id_
= resource_
->gl_id
;
905 ResourceProvider::ScopedWriteLockGL::~ScopedWriteLockGL() {
906 resource_provider_
->UnlockForWrite(resource_
);
909 void ResourceProvider::PopulateSkBitmapWithResource(
910 SkBitmap
* sk_bitmap
, const Resource
* resource
) {
911 DCHECK_EQ(RGBA_8888
, resource
->format
);
912 SkImageInfo info
= SkImageInfo::MakeN32Premul(resource
->size
.width(),
913 resource
->size
.height());
914 sk_bitmap
->installPixels(info
, resource
->pixels
, info
.minRowBytes());
917 ResourceProvider::ScopedReadLockSoftware::ScopedReadLockSoftware(
918 ResourceProvider
* resource_provider
,
919 ResourceId resource_id
)
920 : resource_provider_(resource_provider
), resource_id_(resource_id
) {
921 const Resource
* resource
= resource_provider
->LockForRead(resource_id
);
922 wrap_mode_
= resource
->wrap_mode
;
923 ResourceProvider::PopulateSkBitmapWithResource(&sk_bitmap_
, resource
);
926 ResourceProvider::ScopedReadLockSoftware::~ScopedReadLockSoftware() {
927 resource_provider_
->UnlockForRead(resource_id_
);
930 ResourceProvider::ScopedWriteLockSoftware::ScopedWriteLockSoftware(
931 ResourceProvider
* resource_provider
,
932 ResourceId resource_id
)
933 : resource_provider_(resource_provider
),
934 resource_(resource_provider
->LockForWrite(resource_id
)) {
935 ResourceProvider::PopulateSkBitmapWithResource(&sk_bitmap_
, resource_
);
939 ResourceProvider::ScopedWriteLockSoftware::~ScopedWriteLockSoftware() {
940 DCHECK(thread_checker_
.CalledOnValidThread());
941 resource_provider_
->UnlockForWrite(resource_
);
944 ResourceProvider::ScopedWriteLockGpuMemoryBuffer::
945 ScopedWriteLockGpuMemoryBuffer(ResourceProvider
* resource_provider
,
946 ResourceId resource_id
)
947 : resource_provider_(resource_provider
),
948 resource_(resource_provider
->LockForWrite(resource_id
)),
949 gpu_memory_buffer_manager_(resource_provider
->gpu_memory_buffer_manager_
),
950 gpu_memory_buffer_(nullptr),
951 size_(resource_
->size
),
952 format_(resource_
->format
) {
953 DCHECK_EQ(RESOURCE_TYPE_GL_TEXTURE
, resource_
->type
);
954 std::swap(gpu_memory_buffer_
, resource_
->gpu_memory_buffer
);
957 ResourceProvider::ScopedWriteLockGpuMemoryBuffer::
958 ~ScopedWriteLockGpuMemoryBuffer() {
959 DCHECK(thread_checker_
.CalledOnValidThread());
960 resource_provider_
->UnlockForWrite(resource_
);
961 if (!gpu_memory_buffer_
)
964 resource_provider_
->LazyCreate(resource_
);
966 if (!resource_
->image_id
) {
967 GLES2Interface
* gl
= resource_provider_
->ContextGL();
970 #if defined(OS_CHROMEOS)
971 // TODO(reveman): GL_COMMANDS_ISSUED_CHROMIUM is used for synchronization
972 // on ChromeOS to avoid some performance issues. This only works with
973 // shared memory backed buffers. crbug.com/436314
974 DCHECK_EQ(gpu_memory_buffer_
->GetHandle().type
, gfx::SHARED_MEMORY_BUFFER
);
977 resource_
->image_id
= gl
->CreateImageCHROMIUM(
978 gpu_memory_buffer_
->AsClientBuffer(), size_
.width(), size_
.height(),
979 GLInternalFormat(resource_
->format
));
982 std::swap(resource_
->gpu_memory_buffer
, gpu_memory_buffer_
);
983 resource_
->allocated
= true;
984 resource_
->dirty_image
= true;
986 // GpuMemoryBuffer provides direct access to the memory used by the GPU.
987 // Read lock fences are required to ensure that we're not trying to map a
988 // buffer that is currently in-use by the GPU.
989 resource_
->read_lock_fences_enabled
= true;
992 gfx::GpuMemoryBuffer
*
993 ResourceProvider::ScopedWriteLockGpuMemoryBuffer::GetGpuMemoryBuffer() {
994 if (gpu_memory_buffer_
)
995 return gpu_memory_buffer_
;
996 gfx::BufferUsage usage
=
997 resource_provider_
->use_persistent_map_for_gpu_memory_buffers()
998 ? gfx::BufferUsage::PERSISTENT_MAP
999 : gfx::BufferUsage::MAP
;
1000 scoped_ptr
<gfx::GpuMemoryBuffer
> gpu_memory_buffer
=
1001 gpu_memory_buffer_manager_
->AllocateGpuMemoryBuffer(
1002 size_
, ToGpuMemoryBufferFormat(format_
), usage
);
1003 gpu_memory_buffer_
= gpu_memory_buffer
.release();
1004 return gpu_memory_buffer_
;
1007 ResourceProvider::ScopedWriteLockGr::ScopedWriteLockGr(
1008 ResourceProvider
* resource_provider
,
1009 ResourceId resource_id
)
1010 : resource_provider_(resource_provider
),
1011 resource_(resource_provider
->LockForWrite(resource_id
)) {
1012 DCHECK(thread_checker_
.CalledOnValidThread());
1013 resource_provider_
->LazyAllocate(resource_
);
1016 ResourceProvider::ScopedWriteLockGr::~ScopedWriteLockGr() {
1017 DCHECK(thread_checker_
.CalledOnValidThread());
1018 DCHECK(resource_
->locked_for_write
);
1019 resource_provider_
->UnlockForWrite(resource_
);
1022 void ResourceProvider::ScopedWriteLockGr::InitSkSurface(
1023 bool use_distance_field_text
,
1024 bool can_use_lcd_text
,
1025 int msaa_sample_count
) {
1026 DCHECK(resource_
->locked_for_write
);
1028 GrBackendTextureDesc desc
;
1029 desc
.fFlags
= kRenderTarget_GrBackendTextureFlag
;
1030 desc
.fWidth
= resource_
->size
.width();
1031 desc
.fHeight
= resource_
->size
.height();
1032 desc
.fConfig
= ToGrPixelConfig(resource_
->format
);
1033 desc
.fOrigin
= kTopLeft_GrSurfaceOrigin
;
1034 desc
.fTextureHandle
= resource_
->gl_id
;
1035 desc
.fSampleCnt
= msaa_sample_count
;
1037 bool use_worker_context
= true;
1038 class GrContext
* gr_context
=
1039 resource_provider_
->GrContext(use_worker_context
);
1041 use_distance_field_text
? SkSurfaceProps::kUseDistanceFieldFonts_Flag
: 0;
1042 // Use unknown pixel geometry to disable LCD text.
1043 SkSurfaceProps
surface_props(flags
, kUnknown_SkPixelGeometry
);
1044 if (can_use_lcd_text
) {
1045 // LegacyFontHost will get LCD text and skia figures out what type to use.
1047 SkSurfaceProps(flags
, SkSurfaceProps::kLegacyFontHost_InitType
);
1049 sk_surface_
= skia::AdoptRef(
1050 SkSurface::NewWrappedRenderTarget(gr_context
, desc
, &surface_props
));
1053 void ResourceProvider::ScopedWriteLockGr::ReleaseSkSurface() {
1054 sk_surface_
.clear();
1057 ResourceProvider::SynchronousFence::SynchronousFence(
1058 gpu::gles2::GLES2Interface
* gl
)
1059 : gl_(gl
), has_synchronized_(true) {
1062 ResourceProvider::SynchronousFence::~SynchronousFence() {
1065 void ResourceProvider::SynchronousFence::Set() {
1066 has_synchronized_
= false;
1069 bool ResourceProvider::SynchronousFence::HasPassed() {
1070 if (!has_synchronized_
) {
1071 has_synchronized_
= true;
1077 void ResourceProvider::SynchronousFence::Wait() {
1081 void ResourceProvider::SynchronousFence::Synchronize() {
1082 TRACE_EVENT0("cc", "ResourceProvider::SynchronousFence::Synchronize");
1086 ResourceProvider::ResourceProvider(
1087 OutputSurface
* output_surface
,
1088 SharedBitmapManager
* shared_bitmap_manager
,
1089 gpu::GpuMemoryBufferManager
* gpu_memory_buffer_manager
,
1090 BlockingTaskRunner
* blocking_main_thread_task_runner
,
1091 int highp_threshold_min
,
1092 bool use_rgba_4444_texture_format
,
1093 size_t id_allocation_chunk_size
,
1094 bool use_persistent_map_for_gpu_memory_buffers
)
1095 : output_surface_(output_surface
),
1096 shared_bitmap_manager_(shared_bitmap_manager
),
1097 gpu_memory_buffer_manager_(gpu_memory_buffer_manager
),
1098 blocking_main_thread_task_runner_(blocking_main_thread_task_runner
),
1099 lost_output_surface_(false),
1100 highp_threshold_min_(highp_threshold_min
),
1103 default_resource_type_(RESOURCE_TYPE_BITMAP
),
1104 use_texture_storage_ext_(false),
1105 use_texture_format_bgra_(false),
1106 use_texture_usage_hint_(false),
1107 use_compressed_texture_etc1_(false),
1108 yuv_resource_format_(LUMINANCE_8
),
1109 max_texture_size_(0),
1110 best_texture_format_(RGBA_8888
),
1111 best_render_buffer_format_(RGBA_8888
),
1112 use_rgba_4444_texture_format_(use_rgba_4444_texture_format
),
1113 id_allocation_chunk_size_(id_allocation_chunk_size
),
1114 use_sync_query_(false),
1115 use_persistent_map_for_gpu_memory_buffers_(
1116 use_persistent_map_for_gpu_memory_buffers
) {
1117 DCHECK(output_surface_
->HasClient());
1118 DCHECK(id_allocation_chunk_size_
);
1121 void ResourceProvider::Initialize() {
1122 DCHECK(thread_checker_
.CalledOnValidThread());
1124 // In certain cases, ThreadTaskRunnerHandle isn't set (Android Webview).
1125 // Don't register a dump provider in these cases.
1126 // TODO(ericrk): Get this working in Android Webview. crbug.com/517156
1127 if (base::ThreadTaskRunnerHandle::IsSet()) {
1128 base::trace_event::MemoryDumpManager::GetInstance()->RegisterDumpProvider(
1129 this, base::ThreadTaskRunnerHandle::Get());
1132 GLES2Interface
* gl
= ContextGL();
1134 default_resource_type_
= RESOURCE_TYPE_BITMAP
;
1135 // Pick an arbitrary limit here similar to what hardware might.
1136 max_texture_size_
= 16 * 1024;
1137 best_texture_format_
= RGBA_8888
;
1141 DCHECK(!texture_id_allocator_
);
1142 DCHECK(!buffer_id_allocator_
);
1144 const ContextProvider::Capabilities
& caps
=
1145 output_surface_
->context_provider()->ContextCapabilities();
1147 default_resource_type_
= RESOURCE_TYPE_GL_TEXTURE
;
1148 use_texture_storage_ext_
= caps
.gpu
.texture_storage
;
1149 use_texture_format_bgra_
= caps
.gpu
.texture_format_bgra8888
;
1150 use_texture_usage_hint_
= caps
.gpu
.texture_usage
;
1151 use_compressed_texture_etc1_
= caps
.gpu
.texture_format_etc1
;
1152 yuv_resource_format_
= caps
.gpu
.texture_rg
? RED_8
: LUMINANCE_8
;
1153 use_sync_query_
= caps
.gpu
.sync_query
;
1155 max_texture_size_
= 0; // Context expects cleared value.
1156 gl
->GetIntegerv(GL_MAX_TEXTURE_SIZE
, &max_texture_size_
);
1157 best_texture_format_
=
1158 PlatformColor::BestTextureFormat(use_texture_format_bgra_
);
1160 best_render_buffer_format_
=
1161 PlatformColor::BestTextureFormat(caps
.gpu
.render_buffer_format_bgra8888
);
1163 texture_id_allocator_
.reset(
1164 new TextureIdAllocator(gl
, id_allocation_chunk_size_
));
1165 buffer_id_allocator_
.reset(
1166 new BufferIdAllocator(gl
, id_allocation_chunk_size_
));
1169 int ResourceProvider::CreateChild(const ReturnCallback
& return_callback
) {
1170 DCHECK(thread_checker_
.CalledOnValidThread());
1173 child_info
.return_callback
= return_callback
;
1175 int child
= next_child_
++;
1176 children_
[child
] = child_info
;
1180 void ResourceProvider::SetChildNeedsSyncPoints(int child_id
, bool needs
) {
1181 ChildMap::iterator it
= children_
.find(child_id
);
1182 DCHECK(it
!= children_
.end());
1183 it
->second
.needs_sync_points
= needs
;
1186 void ResourceProvider::DestroyChild(int child_id
) {
1187 ChildMap::iterator it
= children_
.find(child_id
);
1188 DCHECK(it
!= children_
.end());
1189 DestroyChildInternal(it
, NORMAL
);
1192 void ResourceProvider::DestroyChildInternal(ChildMap::iterator it
,
1193 DeleteStyle style
) {
1194 DCHECK(thread_checker_
.CalledOnValidThread());
1196 Child
& child
= it
->second
;
1197 DCHECK(style
== FOR_SHUTDOWN
|| !child
.marked_for_deletion
);
1199 ResourceIdArray resources_for_child
;
1201 for (ResourceIdMap::iterator child_it
= child
.child_to_parent_map
.begin();
1202 child_it
!= child
.child_to_parent_map
.end();
1204 ResourceId id
= child_it
->second
;
1205 resources_for_child
.push_back(id
);
1208 child
.marked_for_deletion
= true;
1210 DeleteAndReturnUnusedResourcesToChild(it
, style
, resources_for_child
);
1213 const ResourceProvider::ResourceIdMap
& ResourceProvider::GetChildToParentMap(
1215 DCHECK(thread_checker_
.CalledOnValidThread());
1216 ChildMap::const_iterator it
= children_
.find(child
);
1217 DCHECK(it
!= children_
.end());
1218 DCHECK(!it
->second
.marked_for_deletion
);
1219 return it
->second
.child_to_parent_map
;
1222 void ResourceProvider::PrepareSendToParent(const ResourceIdArray
& resources
,
1223 TransferableResourceArray
* list
) {
1224 DCHECK(thread_checker_
.CalledOnValidThread());
1225 GLES2Interface
* gl
= ContextGL();
1226 bool need_sync_point
= false;
1227 for (ResourceIdArray::const_iterator it
= resources
.begin();
1228 it
!= resources
.end();
1230 TransferableResource resource
;
1231 TransferResource(gl
, *it
, &resource
);
1232 if (!resource
.mailbox_holder
.sync_point
&& !resource
.is_software
)
1233 need_sync_point
= true;
1234 ++resources_
.find(*it
)->second
.exported_count
;
1235 list
->push_back(resource
);
1237 if (need_sync_point
&&
1238 output_surface_
->capabilities().delegated_sync_points_required
) {
1239 GLuint sync_point
= gl
->InsertSyncPointCHROMIUM();
1240 for (TransferableResourceArray::iterator it
= list
->begin();
1243 if (!it
->mailbox_holder
.sync_point
)
1244 it
->mailbox_holder
.sync_point
= sync_point
;
1249 void ResourceProvider::ReceiveFromChild(
1250 int child
, const TransferableResourceArray
& resources
) {
1251 DCHECK(thread_checker_
.CalledOnValidThread());
1252 GLES2Interface
* gl
= ContextGL();
1253 Child
& child_info
= children_
.find(child
)->second
;
1254 DCHECK(!child_info
.marked_for_deletion
);
1255 for (TransferableResourceArray::const_iterator it
= resources
.begin();
1256 it
!= resources
.end();
1258 ResourceIdMap::iterator resource_in_map_it
=
1259 child_info
.child_to_parent_map
.find(it
->id
);
1260 if (resource_in_map_it
!= child_info
.child_to_parent_map
.end()) {
1261 Resource
* resource
= GetResource(resource_in_map_it
->second
);
1262 resource
->marked_for_deletion
= false;
1263 resource
->imported_count
++;
1267 if ((!it
->is_software
&& !gl
) ||
1268 (it
->is_software
&& !shared_bitmap_manager_
)) {
1269 TRACE_EVENT0("cc", "ResourceProvider::ReceiveFromChild dropping invalid");
1270 ReturnedResourceArray to_return
;
1271 to_return
.push_back(it
->ToReturnedResource());
1272 child_info
.return_callback
.Run(to_return
,
1273 blocking_main_thread_task_runner_
);
1277 ResourceId local_id
= next_id_
++;
1278 Resource
* resource
= nullptr;
1279 if (it
->is_software
) {
1280 resource
= InsertResource(
1282 Resource(it
->mailbox_holder
.mailbox
, it
->size
, Resource::DELEGATED
,
1283 GL_LINEAR
, it
->is_repeated
? GL_REPEAT
: GL_CLAMP_TO_EDGE
));
1285 resource
= InsertResource(
1286 local_id
, Resource(0, it
->size
, Resource::DELEGATED
,
1287 it
->mailbox_holder
.texture_target
, it
->filter
, 0,
1288 it
->is_repeated
? GL_REPEAT
: GL_CLAMP_TO_EDGE
,
1289 TEXTURE_HINT_IMMUTABLE
, it
->format
));
1290 resource
->mailbox
= TextureMailbox(it
->mailbox_holder
.mailbox
,
1291 it
->mailbox_holder
.texture_target
,
1292 it
->mailbox_holder
.sync_point
);
1293 resource
->read_lock_fences_enabled
= it
->read_lock_fences_enabled
;
1295 resource
->child_id
= child
;
1296 // Don't allocate a texture for a child.
1297 resource
->allocated
= true;
1298 resource
->imported_count
= 1;
1299 child_info
.parent_to_child_map
[local_id
] = it
->id
;
1300 child_info
.child_to_parent_map
[it
->id
] = local_id
;
1304 void ResourceProvider::DeclareUsedResourcesFromChild(
1306 const ResourceIdSet
& resources_from_child
) {
1307 DCHECK(thread_checker_
.CalledOnValidThread());
1309 ChildMap::iterator child_it
= children_
.find(child
);
1310 DCHECK(child_it
!= children_
.end());
1311 Child
& child_info
= child_it
->second
;
1312 DCHECK(!child_info
.marked_for_deletion
);
1314 ResourceIdArray unused
;
1315 for (ResourceIdMap::iterator it
= child_info
.child_to_parent_map
.begin();
1316 it
!= child_info
.child_to_parent_map
.end();
1318 ResourceId local_id
= it
->second
;
1319 bool resource_is_in_use
= resources_from_child
.count(it
->first
) > 0;
1320 if (!resource_is_in_use
)
1321 unused
.push_back(local_id
);
1323 DeleteAndReturnUnusedResourcesToChild(child_it
, NORMAL
, unused
);
1326 void ResourceProvider::ReceiveReturnsFromParent(
1327 const ReturnedResourceArray
& resources
) {
1328 DCHECK(thread_checker_
.CalledOnValidThread());
1329 GLES2Interface
* gl
= ContextGL();
1331 base::hash_map
<int, ResourceIdArray
> resources_for_child
;
1333 for (const ReturnedResource
& returned
: resources
) {
1334 ResourceId local_id
= returned
.id
;
1335 ResourceMap::iterator map_iterator
= resources_
.find(local_id
);
1336 // Resource was already lost (e.g. it belonged to a child that was
1338 if (map_iterator
== resources_
.end())
1341 Resource
* resource
= &map_iterator
->second
;
1343 CHECK_GE(resource
->exported_count
, returned
.count
);
1344 resource
->exported_count
-= returned
.count
;
1345 resource
->lost
|= returned
.lost
;
1346 if (resource
->exported_count
)
1349 if (returned
.sync_point
) {
1350 DCHECK(!resource
->has_shared_bitmap_id
);
1351 if (resource
->origin
== Resource::INTERNAL
) {
1352 DCHECK(resource
->gl_id
);
1353 gl
->WaitSyncPointCHROMIUM(returned
.sync_point
);
1355 DCHECK(!resource
->gl_id
);
1356 resource
->mailbox
.set_sync_point(returned
.sync_point
);
1360 if (!resource
->marked_for_deletion
)
1363 if (!resource
->child_id
) {
1364 // The resource belongs to this ResourceProvider, so it can be destroyed.
1365 DeleteResourceInternal(map_iterator
, NORMAL
);
1369 DCHECK(resource
->origin
== Resource::DELEGATED
);
1370 resources_for_child
[resource
->child_id
].push_back(local_id
);
1373 for (const auto& children
: resources_for_child
) {
1374 ChildMap::iterator child_it
= children_
.find(children
.first
);
1375 DCHECK(child_it
!= children_
.end());
1376 DeleteAndReturnUnusedResourcesToChild(child_it
, NORMAL
, children
.second
);
1380 void ResourceProvider::TransferResource(GLES2Interface
* gl
,
1382 TransferableResource
* resource
) {
1383 Resource
* source
= GetResource(id
);
1384 DCHECK(!source
->locked_for_write
);
1385 DCHECK(!source
->lock_for_read_count
);
1386 DCHECK(source
->origin
!= Resource::EXTERNAL
|| source
->mailbox
.IsValid());
1387 DCHECK(source
->allocated
);
1389 resource
->format
= source
->format
;
1390 resource
->mailbox_holder
.texture_target
= source
->target
;
1391 resource
->filter
= source
->filter
;
1392 resource
->size
= source
->size
;
1393 resource
->read_lock_fences_enabled
= source
->read_lock_fences_enabled
;
1394 resource
->is_repeated
= (source
->wrap_mode
== GL_REPEAT
);
1396 if (source
->type
== RESOURCE_TYPE_BITMAP
) {
1397 resource
->mailbox_holder
.mailbox
= source
->shared_bitmap_id
;
1398 resource
->is_software
= true;
1399 } else if (!source
->mailbox
.IsValid()) {
1401 DCHECK(source
->gl_id
);
1402 DCHECK(source
->origin
== Resource::INTERNAL
);
1403 if (source
->image_id
) {
1404 DCHECK(source
->dirty_image
);
1405 gl
->BindTexture(resource
->mailbox_holder
.texture_target
, source
->gl_id
);
1406 BindImageForSampling(source
);
1408 // This is a resource allocated by the compositor, we need to produce it.
1409 // Don't set a sync point, the caller will do it.
1410 gl
->GenMailboxCHROMIUM(resource
->mailbox_holder
.mailbox
.name
);
1411 gl
->ProduceTextureDirectCHROMIUM(source
->gl_id
,
1412 resource
->mailbox_holder
.texture_target
,
1413 resource
->mailbox_holder
.mailbox
.name
);
1415 source
->mailbox
= TextureMailbox(resource
->mailbox_holder
);
1417 DCHECK(source
->mailbox
.IsTexture());
1418 if (source
->image_id
&& source
->dirty_image
) {
1419 DCHECK(source
->gl_id
);
1420 DCHECK(source
->origin
== Resource::INTERNAL
);
1421 gl
->BindTexture(resource
->mailbox_holder
.texture_target
, source
->gl_id
);
1422 BindImageForSampling(source
);
1424 // This is either an external resource, or a compositor resource that we
1425 // already exported. Make sure to forward the sync point that we were given.
1426 resource
->mailbox_holder
.mailbox
= source
->mailbox
.mailbox();
1427 resource
->mailbox_holder
.texture_target
= source
->mailbox
.target();
1428 resource
->mailbox_holder
.sync_point
= source
->mailbox
.sync_point();
1429 source
->mailbox
.set_sync_point(0);
1433 void ResourceProvider::DeleteAndReturnUnusedResourcesToChild(
1434 ChildMap::iterator child_it
,
1436 const ResourceIdArray
& unused
) {
1437 DCHECK(thread_checker_
.CalledOnValidThread());
1438 DCHECK(child_it
!= children_
.end());
1439 Child
* child_info
= &child_it
->second
;
1441 if (unused
.empty() && !child_info
->marked_for_deletion
)
1444 ReturnedResourceArray to_return
;
1446 GLES2Interface
* gl
= ContextGL();
1447 bool need_sync_point
= false;
1448 for (size_t i
= 0; i
< unused
.size(); ++i
) {
1449 ResourceId local_id
= unused
[i
];
1451 ResourceMap::iterator it
= resources_
.find(local_id
);
1452 CHECK(it
!= resources_
.end());
1453 Resource
& resource
= it
->second
;
1455 DCHECK(!resource
.locked_for_write
);
1456 DCHECK(child_info
->parent_to_child_map
.count(local_id
));
1458 ResourceId child_id
= child_info
->parent_to_child_map
[local_id
];
1459 DCHECK(child_info
->child_to_parent_map
.count(child_id
));
1463 (resource
.type
== RESOURCE_TYPE_GL_TEXTURE
&& lost_output_surface_
);
1464 if (resource
.exported_count
> 0 || resource
.lock_for_read_count
> 0) {
1465 if (style
!= FOR_SHUTDOWN
) {
1466 // Defer this resource deletion.
1467 resource
.marked_for_deletion
= true;
1470 // We can't postpone the deletion, so we'll have to lose it.
1472 } else if (!ReadLockFenceHasPassed(&resource
)) {
1473 // TODO(dcastagna): see if it's possible to use this logic for
1474 // the branch above too, where the resource is locked or still exported.
1475 if (style
!= FOR_SHUTDOWN
&& !child_info
->marked_for_deletion
) {
1476 // Defer this resource deletion.
1477 resource
.marked_for_deletion
= true;
1480 // We can't postpone the deletion, so we'll have to lose it.
1484 if (gl
&& resource
.filter
!= resource
.original_filter
) {
1485 DCHECK(resource
.target
);
1486 DCHECK(resource
.gl_id
);
1488 gl
->BindTexture(resource
.target
, resource
.gl_id
);
1489 gl
->TexParameteri(resource
.target
, GL_TEXTURE_MIN_FILTER
,
1490 resource
.original_filter
);
1491 gl
->TexParameteri(resource
.target
, GL_TEXTURE_MAG_FILTER
,
1492 resource
.original_filter
);
1495 ReturnedResource returned
;
1496 returned
.id
= child_id
;
1497 returned
.sync_point
= resource
.mailbox
.sync_point();
1498 if (!returned
.sync_point
&& resource
.type
== RESOURCE_TYPE_GL_TEXTURE
)
1499 need_sync_point
= true;
1500 returned
.count
= resource
.imported_count
;
1501 returned
.lost
= is_lost
;
1502 to_return
.push_back(returned
);
1504 child_info
->parent_to_child_map
.erase(local_id
);
1505 child_info
->child_to_parent_map
.erase(child_id
);
1506 resource
.imported_count
= 0;
1507 DeleteResourceInternal(it
, style
);
1509 if (need_sync_point
&& child_info
->needs_sync_points
) {
1511 GLuint sync_point
= gl
->InsertSyncPointCHROMIUM();
1512 for (size_t i
= 0; i
< to_return
.size(); ++i
) {
1513 if (!to_return
[i
].sync_point
)
1514 to_return
[i
].sync_point
= sync_point
;
1518 if (!to_return
.empty())
1519 child_info
->return_callback
.Run(to_return
,
1520 blocking_main_thread_task_runner_
);
1522 if (child_info
->marked_for_deletion
&&
1523 child_info
->parent_to_child_map
.empty()) {
1524 DCHECK(child_info
->child_to_parent_map
.empty());
1525 children_
.erase(child_it
);
1529 void ResourceProvider::AcquirePixelBuffer(ResourceId id
) {
1530 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug"),
1531 "ResourceProvider::AcquirePixelBuffer");
1533 Resource
* resource
= GetResource(id
);
1534 DCHECK(resource
->origin
== Resource::INTERNAL
);
1535 DCHECK_EQ(resource
->exported_count
, 0);
1536 DCHECK(!resource
->image_id
);
1537 DCHECK_NE(ETC1
, resource
->format
);
1539 DCHECK_EQ(RESOURCE_TYPE_GL_TEXTURE
, resource
->type
);
1540 GLES2Interface
* gl
= ContextGL();
1542 if (!resource
->gl_pixel_buffer_id
)
1543 resource
->gl_pixel_buffer_id
= buffer_id_allocator_
->NextId();
1544 gl
->BindBuffer(GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM
,
1545 resource
->gl_pixel_buffer_id
);
1546 size_t resource_bytes
= ResourceUtil::UncheckedSizeInBytesAligned
<size_t>(
1547 resource
->size
, resource
->format
);
1548 gl
->BufferData(GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM
, resource_bytes
, NULL
,
1550 gl
->BindBuffer(GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM
, 0);
1553 void ResourceProvider::ReleasePixelBuffer(ResourceId id
) {
1554 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug"),
1555 "ResourceProvider::ReleasePixelBuffer");
1557 Resource
* resource
= GetResource(id
);
1558 DCHECK(resource
->origin
== Resource::INTERNAL
);
1559 DCHECK_EQ(resource
->exported_count
, 0);
1560 DCHECK(!resource
->image_id
);
1562 // The pixel buffer can be released while there is a pending "set pixels"
1563 // if completion has been forced. Any shared memory associated with this
1564 // pixel buffer will not be freed until the waitAsyncTexImage2DCHROMIUM
1565 // command has been processed on the service side. It is also safe to
1566 // reuse any query id associated with this resource before they complete
1567 // as each new query has a unique submit count.
1568 if (resource
->pending_set_pixels
) {
1569 DCHECK(resource
->set_pixels_completion_forced
);
1570 resource
->pending_set_pixels
= false;
1571 resource
->locked_for_write
= false;
1574 DCHECK_EQ(RESOURCE_TYPE_GL_TEXTURE
, resource
->type
);
1575 if (!resource
->gl_pixel_buffer_id
)
1577 GLES2Interface
* gl
= ContextGL();
1579 gl
->BindBuffer(GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM
,
1580 resource
->gl_pixel_buffer_id
);
1582 GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM
, 0, NULL
, GL_DYNAMIC_DRAW
);
1583 gl
->BindBuffer(GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM
, 0);
1586 uint8_t* ResourceProvider::MapPixelBuffer(ResourceId id
, int* stride
) {
1587 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug"),
1588 "ResourceProvider::MapPixelBuffer");
1590 Resource
* resource
= GetResource(id
);
1591 DCHECK(resource
->origin
== Resource::INTERNAL
);
1592 DCHECK_EQ(resource
->exported_count
, 0);
1593 DCHECK(!resource
->image_id
);
1596 DCHECK_EQ(RESOURCE_TYPE_GL_TEXTURE
, resource
->type
);
1597 GLES2Interface
* gl
= ContextGL();
1599 DCHECK(resource
->gl_pixel_buffer_id
);
1600 gl
->BindBuffer(GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM
,
1601 resource
->gl_pixel_buffer_id
);
1602 uint8_t* image
= static_cast<uint8_t*>(gl
->MapBufferCHROMIUM(
1603 GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM
, GL_WRITE_ONLY
));
1604 gl
->BindBuffer(GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM
, 0);
1605 // Buffer is required to be 4-byte aligned.
1606 CHECK(!(reinterpret_cast<intptr_t>(image
) & 3));
1610 void ResourceProvider::UnmapPixelBuffer(ResourceId id
) {
1611 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug"),
1612 "ResourceProvider::UnmapPixelBuffer");
1614 Resource
* resource
= GetResource(id
);
1615 DCHECK(resource
->origin
== Resource::INTERNAL
);
1616 DCHECK_EQ(resource
->exported_count
, 0);
1617 DCHECK(!resource
->image_id
);
1619 DCHECK_EQ(RESOURCE_TYPE_GL_TEXTURE
, resource
->type
);
1620 GLES2Interface
* gl
= ContextGL();
1622 DCHECK(resource
->gl_pixel_buffer_id
);
1623 gl
->BindBuffer(GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM
,
1624 resource
->gl_pixel_buffer_id
);
1625 gl
->UnmapBufferCHROMIUM(GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM
);
1626 gl
->BindBuffer(GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM
, 0);
1629 GLenum
ResourceProvider::BindForSampling(ResourceId resource_id
,
1632 DCHECK(thread_checker_
.CalledOnValidThread());
1633 GLES2Interface
* gl
= ContextGL();
1634 ResourceMap::iterator it
= resources_
.find(resource_id
);
1635 DCHECK(it
!= resources_
.end());
1636 Resource
* resource
= &it
->second
;
1637 DCHECK(resource
->lock_for_read_count
);
1638 DCHECK(!resource
->locked_for_write
|| resource
->set_pixels_completion_forced
);
1640 ScopedSetActiveTexture
scoped_active_tex(gl
, unit
);
1641 GLenum target
= resource
->target
;
1642 gl
->BindTexture(target
, resource
->gl_id
);
1643 if (filter
!= resource
->filter
) {
1644 gl
->TexParameteri(target
, GL_TEXTURE_MIN_FILTER
, filter
);
1645 gl
->TexParameteri(target
, GL_TEXTURE_MAG_FILTER
, filter
);
1646 resource
->filter
= filter
;
1649 if (resource
->image_id
&& resource
->dirty_image
)
1650 BindImageForSampling(resource
);
1655 void ResourceProvider::BeginSetPixels(ResourceId id
) {
1656 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug"),
1657 "ResourceProvider::BeginSetPixels");
1659 Resource
* resource
= GetResource(id
);
1660 DCHECK(!resource
->pending_set_pixels
);
1662 LazyCreate(resource
);
1663 DCHECK(resource
->origin
== Resource::INTERNAL
);
1664 DCHECK(resource
->gl_id
|| resource
->allocated
);
1665 DCHECK(ReadLockFenceHasPassed(resource
));
1666 DCHECK(!resource
->image_id
);
1668 bool allocate
= !resource
->allocated
;
1669 resource
->allocated
= true;
1672 DCHECK_EQ(RESOURCE_TYPE_GL_TEXTURE
, resource
->type
);
1673 DCHECK(resource
->gl_id
);
1674 GLES2Interface
* gl
= ContextGL();
1676 DCHECK(resource
->gl_pixel_buffer_id
);
1677 DCHECK_EQ(resource
->target
, static_cast<GLenum
>(GL_TEXTURE_2D
));
1678 gl
->BindTexture(GL_TEXTURE_2D
, resource
->gl_id
);
1679 gl
->BindBuffer(GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM
,
1680 resource
->gl_pixel_buffer_id
);
1681 if (!resource
->gl_upload_query_id
)
1682 gl
->GenQueriesEXT(1, &resource
->gl_upload_query_id
);
1683 gl
->BeginQueryEXT(GL_ASYNC_PIXEL_UNPACK_COMPLETED_CHROMIUM
,
1684 resource
->gl_upload_query_id
);
1686 gl
->AsyncTexImage2DCHROMIUM(GL_TEXTURE_2D
,
1688 GLInternalFormat(resource
->format
),
1689 resource
->size
.width(),
1690 resource
->size
.height(),
1692 GLDataFormat(resource
->format
),
1693 GLDataType(resource
->format
),
1696 gl
->AsyncTexSubImage2DCHROMIUM(GL_TEXTURE_2D
,
1700 resource
->size
.width(),
1701 resource
->size
.height(),
1702 GLDataFormat(resource
->format
),
1703 GLDataType(resource
->format
),
1706 gl
->EndQueryEXT(GL_ASYNC_PIXEL_UNPACK_COMPLETED_CHROMIUM
);
1707 gl
->BindBuffer(GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM
, 0);
1709 resource
->pending_set_pixels
= true;
1710 resource
->set_pixels_completion_forced
= false;
1713 void ResourceProvider::ForceSetPixelsToComplete(ResourceId id
) {
1714 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug"),
1715 "ResourceProvider::ForceSetPixelsToComplete");
1717 Resource
* resource
= GetResource(id
);
1719 DCHECK(resource
->locked_for_write
);
1720 DCHECK(resource
->pending_set_pixels
);
1721 DCHECK(!resource
->set_pixels_completion_forced
);
1723 if (resource
->gl_id
) {
1724 GLES2Interface
* gl
= ContextGL();
1725 gl
->BindTexture(GL_TEXTURE_2D
, resource
->gl_id
);
1726 gl
->WaitAsyncTexImage2DCHROMIUM(GL_TEXTURE_2D
);
1727 gl
->BindTexture(GL_TEXTURE_2D
, 0);
1730 resource
->set_pixels_completion_forced
= true;
1733 bool ResourceProvider::DidSetPixelsComplete(ResourceId id
) {
1734 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug"),
1735 "ResourceProvider::DidSetPixelsComplete");
1737 Resource
* resource
= GetResource(id
);
1739 DCHECK(resource
->locked_for_write
);
1740 DCHECK(resource
->pending_set_pixels
);
1742 if (resource
->gl_id
) {
1743 GLES2Interface
* gl
= ContextGL();
1745 DCHECK(resource
->gl_upload_query_id
);
1746 GLuint complete
= 1;
1747 gl
->GetQueryObjectuivEXT(
1748 resource
->gl_upload_query_id
, GL_QUERY_RESULT_AVAILABLE_EXT
, &complete
);
1753 resource
->pending_set_pixels
= false;
1754 UnlockForWrite(resource
);
1756 // Async set pixels commands are not necessarily processed in-sequence with
1757 // drawing commands. Read lock fences are required to ensure that async
1758 // commands don't access the resource while used for drawing.
1759 resource
->read_lock_fences_enabled
= true;
1764 void ResourceProvider::CreateForTesting(ResourceId id
) {
1765 LazyCreate(GetResource(id
));
1768 GLenum
ResourceProvider::TargetForTesting(ResourceId id
) {
1769 Resource
* resource
= GetResource(id
);
1770 return resource
->target
;
1773 void ResourceProvider::LazyCreate(Resource
* resource
) {
1774 if (resource
->type
!= RESOURCE_TYPE_GL_TEXTURE
||
1775 resource
->origin
!= Resource::INTERNAL
)
1778 if (resource
->gl_id
)
1781 DCHECK(resource
->texture_pool
);
1782 DCHECK(resource
->origin
== Resource::INTERNAL
);
1783 DCHECK(!resource
->mailbox
.IsValid());
1784 resource
->gl_id
= texture_id_allocator_
->NextId();
1786 GLES2Interface
* gl
= ContextGL();
1789 // Create and set texture properties. Allocation is delayed until needed.
1790 gl
->BindTexture(resource
->target
, resource
->gl_id
);
1791 gl
->TexParameteri(resource
->target
, GL_TEXTURE_MIN_FILTER
,
1792 resource
->original_filter
);
1793 gl
->TexParameteri(resource
->target
, GL_TEXTURE_MAG_FILTER
,
1794 resource
->original_filter
);
1795 gl
->TexParameteri(resource
->target
, GL_TEXTURE_WRAP_S
, resource
->wrap_mode
);
1796 gl
->TexParameteri(resource
->target
, GL_TEXTURE_WRAP_T
, resource
->wrap_mode
);
1797 gl
->TexParameteri(resource
->target
, GL_TEXTURE_POOL_CHROMIUM
,
1798 resource
->texture_pool
);
1799 if (use_texture_usage_hint_
&& (resource
->hint
& TEXTURE_HINT_FRAMEBUFFER
)) {
1800 gl
->TexParameteri(resource
->target
, GL_TEXTURE_USAGE_ANGLE
,
1801 GL_FRAMEBUFFER_ATTACHMENT_ANGLE
);
1805 void ResourceProvider::AllocateForTesting(ResourceId id
) {
1806 LazyAllocate(GetResource(id
));
1809 void ResourceProvider::LazyAllocate(Resource
* resource
) {
1811 if (resource
->allocated
)
1813 LazyCreate(resource
);
1814 if (!resource
->gl_id
)
1816 resource
->allocated
= true;
1817 GLES2Interface
* gl
= ContextGL();
1818 gfx::Size
& size
= resource
->size
;
1819 ResourceFormat format
= resource
->format
;
1820 gl
->BindTexture(resource
->target
, resource
->gl_id
);
1821 if (use_texture_storage_ext_
&&
1822 IsFormatSupportedForStorage(format
, use_texture_format_bgra_
) &&
1823 (resource
->hint
& TEXTURE_HINT_IMMUTABLE
)) {
1824 GLenum storage_format
= TextureToStorageFormat(format
);
1825 gl
->TexStorage2DEXT(resource
->target
, 1, storage_format
, size
.width(),
1828 // ETC1 does not support preallocation.
1829 if (format
!= ETC1
) {
1830 gl
->TexImage2D(resource
->target
, 0, GLInternalFormat(format
),
1831 size
.width(), size
.height(), 0, GLDataFormat(format
),
1832 GLDataType(format
), NULL
);
1837 void ResourceProvider::BindImageForSampling(Resource
* resource
) {
1838 GLES2Interface
* gl
= ContextGL();
1839 DCHECK(resource
->gl_id
);
1840 DCHECK(resource
->image_id
);
1842 // Release image currently bound to texture.
1843 if (resource
->bound_image_id
)
1844 gl
->ReleaseTexImage2DCHROMIUM(resource
->target
, resource
->bound_image_id
);
1845 gl
->BindTexImage2DCHROMIUM(resource
->target
, resource
->image_id
);
1846 resource
->bound_image_id
= resource
->image_id
;
1847 resource
->dirty_image
= false;
1850 void ResourceProvider::CopyResource(ResourceId source_id
,
1852 const gfx::Rect
& rect
) {
1853 TRACE_EVENT0("cc", "ResourceProvider::CopyResource");
1855 Resource
* source_resource
= GetResource(source_id
);
1856 DCHECK(!source_resource
->lock_for_read_count
);
1857 DCHECK(source_resource
->origin
== Resource::INTERNAL
);
1858 DCHECK_EQ(source_resource
->exported_count
, 0);
1859 DCHECK_EQ(RESOURCE_TYPE_GL_TEXTURE
, source_resource
->type
);
1860 LazyAllocate(source_resource
);
1862 Resource
* dest_resource
= GetResource(dest_id
);
1863 DCHECK(!dest_resource
->locked_for_write
);
1864 DCHECK(!dest_resource
->lock_for_read_count
);
1865 DCHECK(dest_resource
->origin
== Resource::INTERNAL
);
1866 DCHECK_EQ(dest_resource
->exported_count
, 0);
1867 DCHECK_EQ(RESOURCE_TYPE_GL_TEXTURE
, dest_resource
->type
);
1868 LazyAllocate(dest_resource
);
1870 DCHECK_EQ(source_resource
->type
, dest_resource
->type
);
1871 DCHECK_EQ(source_resource
->format
, dest_resource
->format
);
1872 DCHECK(source_resource
->size
== dest_resource
->size
);
1873 DCHECK(gfx::Rect(dest_resource
->size
).Contains(rect
));
1875 GLES2Interface
* gl
= ContextGL();
1877 if (source_resource
->image_id
&& source_resource
->dirty_image
) {
1878 gl
->BindTexture(source_resource
->target
, source_resource
->gl_id
);
1879 BindImageForSampling(source_resource
);
1881 if (use_sync_query_
) {
1882 if (!source_resource
->gl_read_lock_query_id
)
1883 gl
->GenQueriesEXT(1, &source_resource
->gl_read_lock_query_id
);
1884 #if defined(OS_CHROMEOS)
1885 // TODO(reveman): This avoids a performance problem on some ChromeOS
1886 // devices. This needs to be removed to support native GpuMemoryBuffer
1887 // implementations. crbug.com/436314
1888 gl
->BeginQueryEXT(GL_COMMANDS_ISSUED_CHROMIUM
,
1889 source_resource
->gl_read_lock_query_id
);
1891 gl
->BeginQueryEXT(GL_COMMANDS_COMPLETED_CHROMIUM
,
1892 source_resource
->gl_read_lock_query_id
);
1895 DCHECK(!dest_resource
->image_id
);
1896 dest_resource
->allocated
= true;
1897 gl
->CopySubTextureCHROMIUM(dest_resource
->target
, source_resource
->gl_id
,
1898 dest_resource
->gl_id
, rect
.x(), rect
.y(), rect
.x(),
1899 rect
.y(), rect
.width(), rect
.height(),
1900 false, false, false);
1901 if (source_resource
->gl_read_lock_query_id
) {
1902 // End query and create a read lock fence that will prevent access to
1903 // source resource until CopySubTextureCHROMIUM command has completed.
1904 #if defined(OS_CHROMEOS)
1905 gl
->EndQueryEXT(GL_COMMANDS_ISSUED_CHROMIUM
);
1907 gl
->EndQueryEXT(GL_COMMANDS_COMPLETED_CHROMIUM
);
1909 source_resource
->read_lock_fence
= make_scoped_refptr(
1910 new CopyTextureFence(gl
, source_resource
->gl_read_lock_query_id
));
1912 // Create a SynchronousFence when CHROMIUM_sync_query extension is missing.
1913 // Try to use one synchronous fence for as many CopyResource operations as
1914 // possible as that reduce the number of times we have to synchronize with
1916 if (!synchronous_fence_
.get() || synchronous_fence_
->has_synchronized())
1917 synchronous_fence_
= make_scoped_refptr(new SynchronousFence(gl
));
1918 source_resource
->read_lock_fence
= synchronous_fence_
;
1919 source_resource
->read_lock_fence
->Set();
1923 void ResourceProvider::WaitSyncPointIfNeeded(ResourceId id
) {
1924 Resource
* resource
= GetResource(id
);
1925 DCHECK_EQ(resource
->exported_count
, 0);
1926 DCHECK(resource
->allocated
);
1927 if (resource
->type
!= RESOURCE_TYPE_GL_TEXTURE
|| resource
->gl_id
)
1929 if (!resource
->mailbox
.sync_point())
1931 DCHECK(resource
->mailbox
.IsValid());
1932 GLES2Interface
* gl
= ContextGL();
1934 gl
->WaitSyncPointCHROMIUM(resource
->mailbox
.sync_point());
1935 resource
->mailbox
.set_sync_point(0);
1938 void ResourceProvider::WaitReadLockIfNeeded(ResourceId id
) {
1939 Resource
* resource
= GetResource(id
);
1940 DCHECK_EQ(resource
->exported_count
, 0);
1941 if (!resource
->read_lock_fence
.get())
1944 resource
->read_lock_fence
->Wait();
1947 GLint
ResourceProvider::GetActiveTextureUnit(GLES2Interface
* gl
) {
1948 GLint active_unit
= 0;
1949 gl
->GetIntegerv(GL_ACTIVE_TEXTURE
, &active_unit
);
1953 void ResourceProvider::ValidateResource(ResourceId id
) const {
1954 DCHECK(thread_checker_
.CalledOnValidThread());
1956 DCHECK(resources_
.find(id
) != resources_
.end());
1959 GLES2Interface
* ResourceProvider::ContextGL() const {
1960 ContextProvider
* context_provider
= output_surface_
->context_provider();
1961 return context_provider
? context_provider
->ContextGL() : NULL
;
1964 class GrContext
* ResourceProvider::GrContext(bool worker_context
) const {
1965 ContextProvider
* context_provider
=
1966 worker_context
? output_surface_
->worker_context_provider()
1967 : output_surface_
->context_provider();
1968 return context_provider
? context_provider
->GrContext() : NULL
;
1971 bool ResourceProvider::OnMemoryDump(
1972 const base::trace_event::MemoryDumpArgs
& args
,
1973 base::trace_event::ProcessMemoryDump
* pmd
) {
1974 DCHECK(thread_checker_
.CalledOnValidThread());
1976 const uint64 tracing_process_id
=
1977 base::trace_event::MemoryDumpManager::GetInstance()
1978 ->GetTracingProcessId();
1980 for (const auto& resource_entry
: resources_
) {
1981 const auto& resource
= resource_entry
.second
;
1983 // TODO(ericrk): Add per-compositor ID in name.
1984 std::string dump_name
= base::StringPrintf("cc/resource_memory/resource_%d",
1985 resource_entry
.first
);
1986 base::trace_event::MemoryAllocatorDump
* dump
=
1987 pmd
->CreateAllocatorDump(dump_name
);
1989 uint64_t total_bytes
= ResourceUtil::UncheckedSizeInBytesAligned
<size_t>(
1990 resource
.size
, resource
.format
);
1991 dump
->AddScalar(base::trace_event::MemoryAllocatorDump::kNameSize
,
1992 base::trace_event::MemoryAllocatorDump::kUnitsBytes
,
1993 static_cast<uint64_t>(total_bytes
));
1995 // Resources which are shared across processes require a shared GUID to
1996 // prevent double counting the memory. We currently support shared GUIDs for
1997 // GpuMemoryBuffer, SharedBitmap, and GL backed resources.
1998 base::trace_event::MemoryAllocatorDumpGuid guid
;
1999 if (resource
.gpu_memory_buffer
) {
2000 guid
= gfx::GetGpuMemoryBufferGUIDForTracing(
2001 tracing_process_id
, resource
.gpu_memory_buffer
->GetHandle().id
);
2002 } else if (resource
.shared_bitmap
) {
2003 guid
= GetSharedBitmapGUIDForTracing(resource
.shared_bitmap
->id());
2004 } else if (resource
.gl_id
&& resource
.allocated
) {
2006 gfx::GetGLTextureGUIDForTracing(tracing_process_id
, resource
.gl_id
);
2009 if (!guid
.empty()) {
2010 const int kImportance
= 2;
2011 pmd
->CreateSharedGlobalAllocatorDump(guid
);
2012 pmd
->AddOwnershipEdge(dump
->guid(), guid
, kImportance
);