1 // Copyright 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "cc/resources/resource_provider.h"
10 #include "base/containers/hash_tables.h"
11 #include "base/debug/trace_event.h"
12 #include "base/stl_util.h"
13 #include "base/strings/string_split.h"
14 #include "base/strings/string_util.h"
15 #include "cc/base/util.h"
16 #include "cc/output/gl_renderer.h" // For the GLC() macro.
17 #include "cc/resources/platform_color.h"
18 #include "cc/resources/returned_resource.h"
19 #include "cc/resources/shared_bitmap_manager.h"
20 #include "cc/resources/texture_uploader.h"
21 #include "cc/resources/transferable_resource.h"
22 #include "gpu/GLES2/gl2extchromium.h"
23 #include "gpu/command_buffer/client/gles2_interface.h"
24 #include "gpu/command_buffer/client/gpu_memory_buffer_manager.h"
25 #include "third_party/khronos/GLES2/gl2.h"
26 #include "third_party/khronos/GLES2/gl2ext.h"
27 #include "third_party/skia/include/core/SkSurface.h"
28 #include "third_party/skia/include/gpu/GrContext.h"
29 #include "ui/gfx/frame_time.h"
30 #include "ui/gfx/geometry/rect.h"
31 #include "ui/gfx/geometry/vector2d.h"
32 #include "ui/gfx/gpu_memory_buffer.h"
34 using gpu::gles2::GLES2Interface
;
40 virtual ~IdAllocator() {}
42 virtual GLuint
NextId() = 0;
45 IdAllocator(GLES2Interface
* gl
, size_t id_allocation_chunk_size
)
47 id_allocation_chunk_size_(id_allocation_chunk_size
),
48 ids_(new GLuint
[id_allocation_chunk_size
]),
49 next_id_index_(id_allocation_chunk_size
) {
50 DCHECK(id_allocation_chunk_size_
);
54 const size_t id_allocation_chunk_size_
;
55 scoped_ptr
<GLuint
[]> ids_
;
56 size_t next_id_index_
;
61 // Measured in seconds.
62 const double kSoftwareUploadTickRate
= 0.000250;
63 const double kTextureUploadTickRate
= 0.004;
65 GLenum
TextureToStorageFormat(ResourceFormat format
) {
66 GLenum storage_format
= GL_RGBA8_OES
;
71 storage_format
= GL_BGRA8_EXT
;
82 return storage_format
;
85 bool IsFormatSupportedForStorage(ResourceFormat format
, bool use_bgra
) {
101 GrPixelConfig
ToGrPixelConfig(ResourceFormat format
) {
104 return kRGBA_8888_GrPixelConfig
;
106 return kBGRA_8888_GrPixelConfig
;
108 return kRGBA_4444_GrPixelConfig
;
112 DCHECK(false) << "Unsupported resource format.";
113 return kSkia8888_GrPixelConfig
;
116 gfx::GpuMemoryBuffer::Format
ToGpuMemoryBufferFormat(ResourceFormat format
) {
119 return gfx::GpuMemoryBuffer::Format::RGBA_8888
;
121 return gfx::GpuMemoryBuffer::Format::BGRA_8888
;
130 return gfx::GpuMemoryBuffer::Format::RGBA_8888
;
133 class ScopedSetActiveTexture
{
135 ScopedSetActiveTexture(GLES2Interface
* gl
, GLenum unit
)
136 : gl_(gl
), unit_(unit
) {
137 DCHECK_EQ(GL_TEXTURE0
, ResourceProvider::GetActiveTextureUnit(gl_
));
139 if (unit_
!= GL_TEXTURE0
)
140 GLC(gl_
, gl_
->ActiveTexture(unit_
));
143 ~ScopedSetActiveTexture() {
144 // Active unit being GL_TEXTURE0 is effectively the ground state.
145 if (unit_
!= GL_TEXTURE0
)
146 GLC(gl_
, gl_
->ActiveTexture(GL_TEXTURE0
));
154 class TextureIdAllocator
: public IdAllocator
{
156 TextureIdAllocator(GLES2Interface
* gl
,
157 size_t texture_id_allocation_chunk_size
)
158 : IdAllocator(gl
, texture_id_allocation_chunk_size
) {}
159 ~TextureIdAllocator() override
{
160 gl_
->DeleteTextures(id_allocation_chunk_size_
- next_id_index_
,
161 ids_
.get() + next_id_index_
);
164 // Overridden from IdAllocator:
165 GLuint
NextId() override
{
166 if (next_id_index_
== id_allocation_chunk_size_
) {
167 gl_
->GenTextures(id_allocation_chunk_size_
, ids_
.get());
171 return ids_
[next_id_index_
++];
175 DISALLOW_COPY_AND_ASSIGN(TextureIdAllocator
);
178 class BufferIdAllocator
: public IdAllocator
{
180 BufferIdAllocator(GLES2Interface
* gl
, size_t buffer_id_allocation_chunk_size
)
181 : IdAllocator(gl
, buffer_id_allocation_chunk_size
) {}
182 ~BufferIdAllocator() override
{
183 gl_
->DeleteBuffers(id_allocation_chunk_size_
- next_id_index_
,
184 ids_
.get() + next_id_index_
);
187 // Overridden from IdAllocator:
188 GLuint
NextId() override
{
189 if (next_id_index_
== id_allocation_chunk_size_
) {
190 gl_
->GenBuffers(id_allocation_chunk_size_
, ids_
.get());
194 return ids_
[next_id_index_
++];
198 DISALLOW_COPY_AND_ASSIGN(BufferIdAllocator
);
201 // Generic fence implementation for query objects. Fence has passed when query
202 // result is available.
203 class QueryFence
: public ResourceProvider::Fence
{
205 QueryFence(gpu::gles2::GLES2Interface
* gl
, unsigned query_id
)
206 : gl_(gl
), query_id_(query_id
) {}
208 // Overridden from ResourceProvider::Fence:
209 void Set() override
{}
210 bool HasPassed() override
{
211 unsigned available
= 1;
212 gl_
->GetQueryObjectuivEXT(
213 query_id_
, GL_QUERY_RESULT_AVAILABLE_EXT
, &available
);
216 void Wait() override
{
218 gl_
->GetQueryObjectuivEXT(query_id_
, GL_QUERY_RESULT_EXT
, &result
);
222 ~QueryFence() override
{}
224 gpu::gles2::GLES2Interface
* gl_
;
227 DISALLOW_COPY_AND_ASSIGN(QueryFence
);
232 ResourceProvider::Resource::Resource()
235 gl_pixel_buffer_id(0),
236 gl_upload_query_id(0),
237 gl_read_lock_query_id(0),
239 lock_for_read_count(0),
243 locked_for_write(false),
245 marked_for_deletion(false),
246 pending_set_pixels(false),
247 set_pixels_completion_forced(false),
249 read_lock_fences_enabled(false),
250 has_shared_bitmap_id(false),
251 allow_overlay(false),
252 read_lock_fence(NULL
),
262 hint(TextureHintImmutable
),
266 gpu_memory_buffer(NULL
) {
269 ResourceProvider::Resource::~Resource() {}
271 ResourceProvider::Resource::Resource(GLuint texture_id
,
272 const gfx::Size
& size
,
279 ResourceFormat format
)
282 gl_pixel_buffer_id(0),
283 gl_upload_query_id(0),
284 gl_read_lock_query_id(0),
286 lock_for_read_count(0),
290 locked_for_write(false),
292 marked_for_deletion(false),
293 pending_set_pixels(false),
294 set_pixels_completion_forced(false),
296 read_lock_fences_enabled(false),
297 has_shared_bitmap_id(false),
298 allow_overlay(false),
299 read_lock_fence(NULL
),
303 original_filter(filter
),
307 texture_pool(texture_pool
),
308 wrap_mode(wrap_mode
),
313 gpu_memory_buffer(NULL
) {
314 DCHECK(wrap_mode
== GL_CLAMP_TO_EDGE
|| wrap_mode
== GL_REPEAT
);
315 DCHECK_EQ(origin
== Internal
, !!texture_pool
);
318 ResourceProvider::Resource::Resource(uint8_t* pixels
,
319 SharedBitmap
* bitmap
,
320 const gfx::Size
& size
,
326 gl_pixel_buffer_id(0),
327 gl_upload_query_id(0),
328 gl_read_lock_query_id(0),
330 lock_for_read_count(0),
334 locked_for_write(false),
336 marked_for_deletion(false),
337 pending_set_pixels(false),
338 set_pixels_completion_forced(false),
340 read_lock_fences_enabled(false),
341 has_shared_bitmap_id(!!bitmap
),
342 allow_overlay(false),
343 read_lock_fence(NULL
),
347 original_filter(filter
),
352 wrap_mode(wrap_mode
),
353 hint(TextureHintImmutable
),
356 shared_bitmap(bitmap
),
357 gpu_memory_buffer(NULL
) {
358 DCHECK(wrap_mode
== GL_CLAMP_TO_EDGE
|| wrap_mode
== GL_REPEAT
);
359 DCHECK(origin
== Delegated
|| pixels
);
361 shared_bitmap_id
= bitmap
->id();
364 ResourceProvider::Resource::Resource(const SharedBitmapId
& bitmap_id
,
365 const gfx::Size
& size
,
371 gl_pixel_buffer_id(0),
372 gl_upload_query_id(0),
373 gl_read_lock_query_id(0),
375 lock_for_read_count(0),
379 locked_for_write(false),
381 marked_for_deletion(false),
382 pending_set_pixels(false),
383 set_pixels_completion_forced(false),
385 read_lock_fences_enabled(false),
386 has_shared_bitmap_id(true),
387 allow_overlay(false),
388 read_lock_fence(NULL
),
392 original_filter(filter
),
397 wrap_mode(wrap_mode
),
398 hint(TextureHintImmutable
),
401 shared_bitmap_id(bitmap_id
),
403 gpu_memory_buffer(NULL
) {
404 DCHECK(wrap_mode
== GL_CLAMP_TO_EDGE
|| wrap_mode
== GL_REPEAT
);
407 ResourceProvider::Child::Child() : marked_for_deletion(false) {}
409 ResourceProvider::Child::~Child() {}
411 scoped_ptr
<ResourceProvider
> ResourceProvider::Create(
412 OutputSurface
* output_surface
,
413 SharedBitmapManager
* shared_bitmap_manager
,
414 gpu::GpuMemoryBufferManager
* gpu_memory_buffer_manager
,
415 BlockingTaskRunner
* blocking_main_thread_task_runner
,
416 int highp_threshold_min
,
417 bool use_rgba_4444_texture_format
,
418 size_t id_allocation_chunk_size
) {
419 scoped_ptr
<ResourceProvider
> resource_provider(
420 new ResourceProvider(output_surface
,
421 shared_bitmap_manager
,
422 gpu_memory_buffer_manager
,
423 blocking_main_thread_task_runner
,
425 use_rgba_4444_texture_format
,
426 id_allocation_chunk_size
));
428 if (resource_provider
->ContextGL())
429 resource_provider
->InitializeGL();
431 resource_provider
->InitializeSoftware();
433 DCHECK_NE(InvalidType
, resource_provider
->default_resource_type());
434 return resource_provider
.Pass();
437 ResourceProvider::~ResourceProvider() {
438 while (!children_
.empty())
439 DestroyChildInternal(children_
.begin(), ForShutdown
);
440 while (!resources_
.empty())
441 DeleteResourceInternal(resources_
.begin(), ForShutdown
);
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 bool ResourceProvider::AllowOverlay(ResourceId id
) {
458 Resource
* resource
= GetResource(id
);
459 return resource
->allow_overlay
;
462 ResourceProvider::ResourceId
ResourceProvider::CreateResource(
463 const gfx::Size
& size
,
466 ResourceFormat format
) {
467 DCHECK(!size
.IsEmpty());
468 switch (default_resource_type_
) {
470 return CreateGLTexture(size
,
472 GL_TEXTURE_POOL_UNMANAGED_CHROMIUM
,
477 DCHECK_EQ(RGBA_8888
, format
);
478 return CreateBitmap(size
, wrap_mode
);
483 LOG(FATAL
) << "Invalid default resource type.";
487 ResourceProvider::ResourceId
ResourceProvider::CreateManagedResource(
488 const gfx::Size
& size
,
492 ResourceFormat format
) {
493 DCHECK(!size
.IsEmpty());
494 switch (default_resource_type_
) {
496 return CreateGLTexture(size
,
498 GL_TEXTURE_POOL_MANAGED_CHROMIUM
,
503 DCHECK_EQ(RGBA_8888
, format
);
504 return CreateBitmap(size
, wrap_mode
);
509 LOG(FATAL
) << "Invalid default resource type.";
513 ResourceProvider::ResourceId
ResourceProvider::CreateGLTexture(
514 const gfx::Size
& size
,
519 ResourceFormat format
) {
520 DCHECK_LE(size
.width(), max_texture_size_
);
521 DCHECK_LE(size
.height(), max_texture_size_
);
522 DCHECK(thread_checker_
.CalledOnValidThread());
524 ResourceId id
= next_id_
++;
534 resource
.allocated
= false;
535 resources_
[id
] = resource
;
539 ResourceProvider::ResourceId
ResourceProvider::CreateBitmap(
540 const gfx::Size
& size
, GLint wrap_mode
) {
541 DCHECK(thread_checker_
.CalledOnValidThread());
543 scoped_ptr
<SharedBitmap
> bitmap
;
544 if (shared_bitmap_manager_
)
545 bitmap
= shared_bitmap_manager_
->AllocateSharedBitmap(size
);
549 pixels
= bitmap
->pixels();
551 size_t bytes
= SharedBitmap::CheckedSizeInBytes(size
);
552 pixels
= new uint8_t[bytes
];
556 ResourceId id
= next_id_
++;
558 pixels
, bitmap
.release(), size
, Resource::Internal
, GL_LINEAR
, wrap_mode
);
559 resource
.allocated
= true;
560 resources_
[id
] = resource
;
564 ResourceProvider::ResourceId
ResourceProvider::CreateResourceFromIOSurface(
565 const gfx::Size
& size
,
566 unsigned io_surface_id
) {
567 DCHECK(thread_checker_
.CalledOnValidThread());
569 ResourceId id
= next_id_
++;
573 GL_TEXTURE_RECTANGLE_ARB
,
575 GL_TEXTURE_POOL_UNMANAGED_CHROMIUM
,
577 TextureHintImmutable
,
579 LazyCreate(&resource
);
580 GLES2Interface
* gl
= ContextGL();
582 gl
->BindTexture(GL_TEXTURE_RECTANGLE_ARB
, resource
.gl_id
);
583 gl
->TexImageIOSurface2DCHROMIUM(
584 GL_TEXTURE_RECTANGLE_ARB
, size
.width(), size
.height(), io_surface_id
, 0);
585 resource
.allocated
= true;
586 resources_
[id
] = resource
;
590 ResourceProvider::ResourceId
ResourceProvider::CreateResourceFromTextureMailbox(
591 const TextureMailbox
& mailbox
,
592 scoped_ptr
<SingleReleaseCallbackImpl
> release_callback_impl
) {
593 DCHECK(thread_checker_
.CalledOnValidThread());
594 // Just store the information. Mailbox will be consumed in LockForRead().
595 ResourceId id
= next_id_
++;
596 DCHECK(mailbox
.IsValid());
597 Resource
& resource
= resources_
[id
];
598 if (mailbox
.IsTexture()) {
599 resource
= Resource(0,
606 TextureHintImmutable
,
609 DCHECK(mailbox
.IsSharedMemory());
610 base::SharedMemory
* shared_memory
= mailbox
.shared_memory();
611 DCHECK(shared_memory
->memory());
612 uint8_t* pixels
= reinterpret_cast<uint8_t*>(shared_memory
->memory());
614 scoped_ptr
<SharedBitmap
> shared_bitmap
;
615 if (shared_bitmap_manager_
) {
617 shared_bitmap_manager_
->GetBitmapForSharedMemory(shared_memory
);
619 resource
= Resource(pixels
,
620 shared_bitmap
.release(),
621 mailbox
.shared_memory_size(),
626 resource
.allocated
= true;
627 resource
.mailbox
= mailbox
;
628 resource
.release_callback_impl
=
629 base::Bind(&SingleReleaseCallbackImpl::Run
,
630 base::Owned(release_callback_impl
.release()));
631 resource
.allow_overlay
= mailbox
.allow_overlay();
635 void ResourceProvider::DeleteResource(ResourceId id
) {
636 DCHECK(thread_checker_
.CalledOnValidThread());
637 ResourceMap::iterator it
= resources_
.find(id
);
638 CHECK(it
!= resources_
.end());
639 Resource
* resource
= &it
->second
;
640 DCHECK(!resource
->marked_for_deletion
);
641 DCHECK_EQ(resource
->imported_count
, 0);
642 DCHECK(resource
->pending_set_pixels
|| !resource
->locked_for_write
);
644 if (resource
->exported_count
> 0 || resource
->lock_for_read_count
> 0) {
645 resource
->marked_for_deletion
= true;
648 DeleteResourceInternal(it
, Normal
);
652 void ResourceProvider::DeleteResourceInternal(ResourceMap::iterator it
,
654 TRACE_EVENT0("cc", "ResourceProvider::DeleteResourceInternal");
655 Resource
* resource
= &it
->second
;
656 bool lost_resource
= resource
->lost
;
658 DCHECK(resource
->exported_count
== 0 || style
!= Normal
);
659 if (style
== ForShutdown
&& resource
->exported_count
> 0)
660 lost_resource
= true;
662 if (resource
->image_id
) {
663 DCHECK(resource
->origin
== Resource::Internal
);
664 GLES2Interface
* gl
= ContextGL();
666 GLC(gl
, gl
->DestroyImageCHROMIUM(resource
->image_id
));
668 if (resource
->gl_upload_query_id
) {
669 DCHECK(resource
->origin
== Resource::Internal
);
670 GLES2Interface
* gl
= ContextGL();
672 GLC(gl
, gl
->DeleteQueriesEXT(1, &resource
->gl_upload_query_id
));
674 if (resource
->gl_read_lock_query_id
) {
675 DCHECK(resource
->origin
== Resource::Internal
);
676 GLES2Interface
* gl
= ContextGL();
678 GLC(gl
, gl
->DeleteQueriesEXT(1, &resource
->gl_read_lock_query_id
));
680 if (resource
->gl_pixel_buffer_id
) {
681 DCHECK(resource
->origin
== Resource::Internal
);
682 GLES2Interface
* gl
= ContextGL();
684 GLC(gl
, gl
->DeleteBuffers(1, &resource
->gl_pixel_buffer_id
));
686 if (resource
->origin
== Resource::External
) {
687 DCHECK(resource
->mailbox
.IsValid());
688 GLuint sync_point
= resource
->mailbox
.sync_point();
689 if (resource
->type
== GLTexture
) {
690 DCHECK(resource
->mailbox
.IsTexture());
691 lost_resource
|= lost_output_surface_
;
692 GLES2Interface
* gl
= ContextGL();
694 if (resource
->gl_id
) {
695 GLC(gl
, gl
->DeleteTextures(1, &resource
->gl_id
));
698 sync_point
= gl
->InsertSyncPointCHROMIUM();
701 DCHECK(resource
->mailbox
.IsSharedMemory());
702 base::SharedMemory
* shared_memory
= resource
->mailbox
.shared_memory();
703 if (resource
->pixels
&& shared_memory
) {
704 DCHECK(shared_memory
->memory() == resource
->pixels
);
705 resource
->pixels
= NULL
;
706 delete resource
->shared_bitmap
;
707 resource
->shared_bitmap
= NULL
;
710 resource
->release_callback_impl
.Run(
711 sync_point
, lost_resource
, blocking_main_thread_task_runner_
);
713 if (resource
->gl_id
) {
714 GLES2Interface
* gl
= ContextGL();
716 GLC(gl
, gl
->DeleteTextures(1, &resource
->gl_id
));
719 if (resource
->shared_bitmap
) {
720 DCHECK(resource
->origin
!= Resource::External
);
721 DCHECK_EQ(Bitmap
, resource
->type
);
722 delete resource
->shared_bitmap
;
723 resource
->pixels
= NULL
;
725 if (resource
->pixels
) {
726 DCHECK(resource
->origin
== Resource::Internal
);
727 delete[] resource
->pixels
;
728 resource
->pixels
= NULL
;
730 if (resource
->gpu_memory_buffer
) {
731 DCHECK(resource
->origin
== Resource::Internal
);
732 delete resource
->gpu_memory_buffer
;
733 resource
->gpu_memory_buffer
= NULL
;
735 resources_
.erase(it
);
738 ResourceProvider::ResourceType
ResourceProvider::GetResourceType(
740 return GetResource(id
)->type
;
743 void ResourceProvider::SetPixels(ResourceId id
,
744 const uint8_t* image
,
745 const gfx::Rect
& image_rect
,
746 const gfx::Rect
& source_rect
,
747 const gfx::Vector2d
& dest_offset
) {
748 Resource
* resource
= GetResource(id
);
749 DCHECK(!resource
->locked_for_write
);
750 DCHECK(!resource
->lock_for_read_count
);
751 DCHECK(resource
->origin
== Resource::Internal
);
752 DCHECK_EQ(resource
->exported_count
, 0);
753 DCHECK(ReadLockFenceHasPassed(resource
));
754 LazyAllocate(resource
);
756 if (resource
->type
== GLTexture
) {
757 DCHECK(resource
->gl_id
);
758 DCHECK(!resource
->pending_set_pixels
);
759 DCHECK_EQ(resource
->target
, static_cast<GLenum
>(GL_TEXTURE_2D
));
760 GLES2Interface
* gl
= ContextGL();
762 DCHECK(texture_uploader_
.get());
763 gl
->BindTexture(GL_TEXTURE_2D
, resource
->gl_id
);
764 texture_uploader_
->Upload(image
,
771 DCHECK_EQ(Bitmap
, resource
->type
);
772 DCHECK(resource
->allocated
);
773 DCHECK_EQ(RGBA_8888
, resource
->format
);
774 DCHECK(source_rect
.x() >= image_rect
.x());
775 DCHECK(source_rect
.y() >= image_rect
.y());
776 DCHECK(source_rect
.right() <= image_rect
.right());
777 DCHECK(source_rect
.bottom() <= image_rect
.bottom());
778 SkImageInfo source_info
=
779 SkImageInfo::MakeN32Premul(source_rect
.width(), source_rect
.height());
780 size_t image_row_bytes
= image_rect
.width() * 4;
781 gfx::Vector2d source_offset
= source_rect
.origin() - image_rect
.origin();
782 image
+= source_offset
.y() * image_row_bytes
+ source_offset
.x() * 4;
784 ScopedWriteLockSoftware
lock(this, id
);
785 SkCanvas
* dest
= lock
.sk_canvas();
787 source_info
, image
, image_row_bytes
, dest_offset
.x(), dest_offset
.y());
791 size_t ResourceProvider::NumBlockingUploads() {
792 if (!texture_uploader_
)
795 return texture_uploader_
->NumBlockingUploads();
798 void ResourceProvider::MarkPendingUploadsAsNonBlocking() {
799 if (!texture_uploader_
)
802 texture_uploader_
->MarkPendingUploadsAsNonBlocking();
805 size_t ResourceProvider::EstimatedUploadsPerTick() {
806 if (!texture_uploader_
)
809 double textures_per_second
= texture_uploader_
->EstimatedTexturesPerSecond();
810 size_t textures_per_tick
= floor(
811 kTextureUploadTickRate
* textures_per_second
);
812 return textures_per_tick
? textures_per_tick
: 1u;
815 void ResourceProvider::FlushUploads() {
816 if (!texture_uploader_
)
819 texture_uploader_
->Flush();
822 void ResourceProvider::ReleaseCachedData() {
823 if (!texture_uploader_
)
826 texture_uploader_
->ReleaseCachedQueries();
829 base::TimeTicks
ResourceProvider::EstimatedUploadCompletionTime(
830 size_t uploads_per_tick
) {
831 if (lost_output_surface_
)
832 return base::TimeTicks();
834 // Software resource uploads happen on impl thread, so don't bother batching
835 // them up and trying to wait for them to complete.
836 if (!texture_uploader_
) {
837 return gfx::FrameTime::Now() + base::TimeDelta::FromMicroseconds(
838 base::Time::kMicrosecondsPerSecond
* kSoftwareUploadTickRate
);
841 base::TimeDelta upload_one_texture_time
=
842 base::TimeDelta::FromMicroseconds(
843 base::Time::kMicrosecondsPerSecond
* kTextureUploadTickRate
) /
846 size_t total_uploads
= NumBlockingUploads() + uploads_per_tick
;
847 return gfx::FrameTime::Now() + upload_one_texture_time
* total_uploads
;
850 ResourceProvider::Resource
* ResourceProvider::GetResource(ResourceId id
) {
851 DCHECK(thread_checker_
.CalledOnValidThread());
852 ResourceMap::iterator it
= resources_
.find(id
);
853 CHECK(it
!= resources_
.end());
857 const ResourceProvider::Resource
* ResourceProvider::LockForRead(ResourceId id
) {
858 Resource
* resource
= GetResource(id
);
859 DCHECK(!resource
->locked_for_write
||
860 resource
->set_pixels_completion_forced
) <<
861 "locked for write: " << resource
->locked_for_write
<<
862 " pixels completion forced: " << resource
->set_pixels_completion_forced
;
863 DCHECK_EQ(resource
->exported_count
, 0);
864 // Uninitialized! Call SetPixels or LockForWrite first.
865 DCHECK(resource
->allocated
);
867 LazyCreate(resource
);
869 if (resource
->type
== GLTexture
&& !resource
->gl_id
) {
870 DCHECK(resource
->origin
!= Resource::Internal
);
871 DCHECK(resource
->mailbox
.IsTexture());
873 // Mailbox sync_points must be processed by a call to
874 // WaitSyncPointIfNeeded() prior to calling LockForRead().
875 DCHECK(!resource
->mailbox
.sync_point());
877 GLES2Interface
* gl
= ContextGL();
879 resource
->gl_id
= texture_id_allocator_
->NextId();
880 GLC(gl
, gl
->BindTexture(resource
->target
, resource
->gl_id
));
882 gl
->ConsumeTextureCHROMIUM(resource
->mailbox
.target(),
883 resource
->mailbox
.name()));
886 if (!resource
->pixels
&& resource
->has_shared_bitmap_id
&&
887 shared_bitmap_manager_
) {
888 scoped_ptr
<SharedBitmap
> bitmap
=
889 shared_bitmap_manager_
->GetSharedBitmapFromId(
890 resource
->size
, resource
->shared_bitmap_id
);
892 resource
->shared_bitmap
= bitmap
.release();
893 resource
->pixels
= resource
->shared_bitmap
->pixels();
897 resource
->lock_for_read_count
++;
898 if (resource
->read_lock_fences_enabled
) {
899 if (current_read_lock_fence_
.get())
900 current_read_lock_fence_
->Set();
901 resource
->read_lock_fence
= current_read_lock_fence_
;
907 void ResourceProvider::UnlockForRead(ResourceId id
) {
908 DCHECK(thread_checker_
.CalledOnValidThread());
909 ResourceMap::iterator it
= resources_
.find(id
);
910 CHECK(it
!= resources_
.end());
912 Resource
* resource
= &it
->second
;
913 DCHECK_GT(resource
->lock_for_read_count
, 0);
914 DCHECK_EQ(resource
->exported_count
, 0);
915 resource
->lock_for_read_count
--;
916 if (resource
->marked_for_deletion
&& !resource
->lock_for_read_count
) {
917 if (!resource
->child_id
) {
918 // The resource belongs to this ResourceProvider, so it can be destroyed.
919 DeleteResourceInternal(it
, Normal
);
921 ChildMap::iterator child_it
= children_
.find(resource
->child_id
);
922 ResourceIdArray unused
;
923 unused
.push_back(id
);
924 DeleteAndReturnUnusedResourcesToChild(child_it
, Normal
, unused
);
929 ResourceProvider::Resource
* ResourceProvider::LockForWrite(ResourceId id
) {
930 Resource
* resource
= GetResource(id
);
931 DCHECK(CanLockForWrite(id
));
933 resource
->locked_for_write
= true;
937 bool ResourceProvider::CanLockForWrite(ResourceId id
) {
938 Resource
* resource
= GetResource(id
);
939 return !resource
->locked_for_write
&& !resource
->lock_for_read_count
&&
940 !resource
->exported_count
&& resource
->origin
== Resource::Internal
&&
941 !resource
->lost
&& ReadLockFenceHasPassed(resource
);
944 void ResourceProvider::UnlockForWrite(ResourceProvider::Resource
* resource
) {
945 DCHECK(resource
->locked_for_write
);
946 DCHECK_EQ(resource
->exported_count
, 0);
947 DCHECK(resource
->origin
== Resource::Internal
);
948 resource
->locked_for_write
= false;
951 ResourceProvider::ScopedReadLockGL::ScopedReadLockGL(
952 ResourceProvider
* resource_provider
,
953 ResourceProvider::ResourceId resource_id
)
954 : resource_provider_(resource_provider
),
955 resource_id_(resource_id
),
956 texture_id_(resource_provider
->LockForRead(resource_id
)->gl_id
) {
960 ResourceProvider::ScopedReadLockGL::~ScopedReadLockGL() {
961 resource_provider_
->UnlockForRead(resource_id_
);
964 ResourceProvider::ScopedSamplerGL::ScopedSamplerGL(
965 ResourceProvider
* resource_provider
,
966 ResourceProvider::ResourceId resource_id
,
968 : ScopedReadLockGL(resource_provider
, resource_id
),
970 target_(resource_provider
->BindForSampling(resource_id
, unit_
, filter
)) {
973 ResourceProvider::ScopedSamplerGL::ScopedSamplerGL(
974 ResourceProvider
* resource_provider
,
975 ResourceProvider::ResourceId resource_id
,
978 : ScopedReadLockGL(resource_provider
, resource_id
),
980 target_(resource_provider
->BindForSampling(resource_id
, unit_
, filter
)) {
983 ResourceProvider::ScopedSamplerGL::~ScopedSamplerGL() {
986 ResourceProvider::ScopedWriteLockGL::ScopedWriteLockGL(
987 ResourceProvider
* resource_provider
,
988 ResourceProvider::ResourceId resource_id
)
989 : resource_provider_(resource_provider
),
990 resource_(resource_provider
->LockForWrite(resource_id
)) {
991 resource_provider_
->LazyAllocate(resource_
);
992 texture_id_
= resource_
->gl_id
;
996 ResourceProvider::ScopedWriteLockGL::~ScopedWriteLockGL() {
997 resource_provider_
->UnlockForWrite(resource_
);
1000 void ResourceProvider::PopulateSkBitmapWithResource(
1001 SkBitmap
* sk_bitmap
, const Resource
* resource
) {
1002 DCHECK_EQ(RGBA_8888
, resource
->format
);
1003 SkImageInfo info
= SkImageInfo::MakeN32Premul(resource
->size
.width(),
1004 resource
->size
.height());
1005 sk_bitmap
->installPixels(info
, resource
->pixels
, info
.minRowBytes());
1008 ResourceProvider::ScopedReadLockSoftware::ScopedReadLockSoftware(
1009 ResourceProvider
* resource_provider
,
1010 ResourceProvider::ResourceId resource_id
)
1011 : resource_provider_(resource_provider
),
1012 resource_id_(resource_id
) {
1013 const Resource
* resource
= resource_provider
->LockForRead(resource_id
);
1014 wrap_mode_
= resource
->wrap_mode
;
1015 ResourceProvider::PopulateSkBitmapWithResource(&sk_bitmap_
, resource
);
1018 ResourceProvider::ScopedReadLockSoftware::~ScopedReadLockSoftware() {
1019 resource_provider_
->UnlockForRead(resource_id_
);
1022 ResourceProvider::ScopedWriteLockSoftware::ScopedWriteLockSoftware(
1023 ResourceProvider
* resource_provider
,
1024 ResourceProvider::ResourceId resource_id
)
1025 : resource_provider_(resource_provider
),
1026 resource_(resource_provider
->LockForWrite(resource_id
)) {
1027 ResourceProvider::PopulateSkBitmapWithResource(&sk_bitmap_
, resource_
);
1029 sk_canvas_
.reset(new SkCanvas(sk_bitmap_
));
1032 ResourceProvider::ScopedWriteLockSoftware::~ScopedWriteLockSoftware() {
1033 DCHECK(thread_checker_
.CalledOnValidThread());
1034 resource_provider_
->UnlockForWrite(resource_
);
1037 ResourceProvider::ScopedWriteLockGpuMemoryBuffer::
1038 ScopedWriteLockGpuMemoryBuffer(ResourceProvider
* resource_provider
,
1039 ResourceProvider::ResourceId resource_id
)
1040 : resource_provider_(resource_provider
),
1041 resource_(resource_provider
->LockForWrite(resource_id
)),
1042 gpu_memory_buffer_manager_(resource_provider
->gpu_memory_buffer_manager_
),
1043 gpu_memory_buffer_(nullptr),
1044 size_(resource_
->size
),
1045 format_(resource_
->format
) {
1046 DCHECK_EQ(GLTexture
, resource_
->type
);
1047 std::swap(gpu_memory_buffer_
, resource_
->gpu_memory_buffer
);
1050 ResourceProvider::ScopedWriteLockGpuMemoryBuffer::
1051 ~ScopedWriteLockGpuMemoryBuffer() {
1052 DCHECK(thread_checker_
.CalledOnValidThread());
1053 resource_provider_
->UnlockForWrite(resource_
);
1054 if (!gpu_memory_buffer_
)
1057 if (!resource_
->image_id
) {
1058 GLES2Interface
* gl
= resource_provider_
->ContextGL();
1061 resource_
->image_id
=
1062 gl
->CreateImageCHROMIUM(gpu_memory_buffer_
->AsClientBuffer(),
1068 std::swap(resource_
->gpu_memory_buffer
, gpu_memory_buffer_
);
1069 resource_
->allocated
= true;
1070 resource_
->dirty_image
= true;
1072 // GpuMemoryBuffer provides direct access to the memory used by the GPU.
1073 // Read lock fences are required to ensure that we're not trying to map a
1074 // buffer that is currently in-use by the GPU.
1075 resource_
->read_lock_fences_enabled
= true;
1078 gfx::GpuMemoryBuffer
*
1079 ResourceProvider::ScopedWriteLockGpuMemoryBuffer::GetGpuMemoryBuffer() {
1080 if (!gpu_memory_buffer_
) {
1081 scoped_ptr
<gfx::GpuMemoryBuffer
> gpu_memory_buffer
=
1082 gpu_memory_buffer_manager_
->AllocateGpuMemoryBuffer(
1083 size_
, ToGpuMemoryBufferFormat(format_
), gfx::GpuMemoryBuffer::MAP
);
1084 gpu_memory_buffer_
= gpu_memory_buffer
.release();
1087 return gpu_memory_buffer_
;
1090 ResourceProvider::ScopedWriteLockGr::ScopedWriteLockGr(
1091 ResourceProvider
* resource_provider
,
1092 ResourceProvider::ResourceId resource_id
)
1093 : resource_provider_(resource_provider
),
1094 resource_(resource_provider
->LockForWrite(resource_id
)) {
1097 ResourceProvider::ScopedWriteLockGr::~ScopedWriteLockGr() {
1098 DCHECK(thread_checker_
.CalledOnValidThread());
1099 resource_provider_
->UnlockForWrite(resource_
);
1102 SkSurface
* ResourceProvider::ScopedWriteLockGr::GetSkSurface(
1103 bool use_distance_field_text
) {
1104 DCHECK(thread_checker_
.CalledOnValidThread());
1105 DCHECK(resource_
->locked_for_write
);
1107 // If the surface doesn't exist, or doesn't have the correct dff setting,
1108 // recreate the surface within the resource.
1109 if (!resource_
->sk_surface
||
1110 use_distance_field_text
!=
1111 resource_
->sk_surface
->props().isUseDistanceFieldFonts()) {
1112 class GrContext
* gr_context
= resource_provider_
->GrContext();
1113 // TODO(alokp): Implement TestContextProvider::GrContext().
1117 resource_provider_
->LazyAllocate(resource_
);
1119 GrBackendTextureDesc desc
;
1120 desc
.fFlags
= kRenderTarget_GrBackendTextureFlag
;
1121 desc
.fWidth
= resource_
->size
.width();
1122 desc
.fHeight
= resource_
->size
.height();
1123 desc
.fConfig
= ToGrPixelConfig(resource_
->format
);
1124 desc
.fOrigin
= kTopLeft_GrSurfaceOrigin
;
1125 desc
.fTextureHandle
= resource_
->gl_id
;
1126 skia::RefPtr
<GrTexture
> gr_texture
=
1127 skia::AdoptRef(gr_context
->wrapBackendTexture(desc
));
1130 SkSurface::TextRenderMode text_render_mode
=
1131 use_distance_field_text
? SkSurface::kDistanceField_TextRenderMode
1132 : SkSurface::kStandard_TextRenderMode
;
1133 resource_
->sk_surface
= skia::AdoptRef(SkSurface::NewRenderTargetDirect(
1134 gr_texture
->asRenderTarget(), text_render_mode
));
1136 return resource_
->sk_surface
.get();
1139 ResourceProvider::SynchronousFence::SynchronousFence(
1140 gpu::gles2::GLES2Interface
* gl
)
1141 : gl_(gl
), has_synchronized_(true) {
1144 ResourceProvider::SynchronousFence::~SynchronousFence() {
1147 void ResourceProvider::SynchronousFence::Set() {
1148 has_synchronized_
= false;
1151 bool ResourceProvider::SynchronousFence::HasPassed() {
1152 if (!has_synchronized_
) {
1153 has_synchronized_
= true;
1159 void ResourceProvider::SynchronousFence::Wait() {
1163 void ResourceProvider::SynchronousFence::Synchronize() {
1164 TRACE_EVENT0("cc", "ResourceProvider::SynchronousFence::Synchronize");
1168 ResourceProvider::ResourceProvider(
1169 OutputSurface
* output_surface
,
1170 SharedBitmapManager
* shared_bitmap_manager
,
1171 gpu::GpuMemoryBufferManager
* gpu_memory_buffer_manager
,
1172 BlockingTaskRunner
* blocking_main_thread_task_runner
,
1173 int highp_threshold_min
,
1174 bool use_rgba_4444_texture_format
,
1175 size_t id_allocation_chunk_size
)
1176 : output_surface_(output_surface
),
1177 shared_bitmap_manager_(shared_bitmap_manager
),
1178 gpu_memory_buffer_manager_(gpu_memory_buffer_manager
),
1179 blocking_main_thread_task_runner_(blocking_main_thread_task_runner
),
1180 lost_output_surface_(false),
1181 highp_threshold_min_(highp_threshold_min
),
1184 default_resource_type_(InvalidType
),
1185 use_texture_storage_ext_(false),
1186 use_texture_format_bgra_(false),
1187 use_texture_usage_hint_(false),
1188 use_compressed_texture_etc1_(false),
1189 max_texture_size_(0),
1190 best_texture_format_(RGBA_8888
),
1191 use_rgba_4444_texture_format_(use_rgba_4444_texture_format
),
1192 id_allocation_chunk_size_(id_allocation_chunk_size
),
1193 use_sync_query_(false) {
1194 DCHECK(output_surface_
->HasClient());
1195 DCHECK(id_allocation_chunk_size_
);
1198 void ResourceProvider::InitializeSoftware() {
1199 DCHECK(thread_checker_
.CalledOnValidThread());
1200 DCHECK_NE(Bitmap
, default_resource_type_
);
1202 CleanUpGLIfNeeded();
1204 default_resource_type_
= Bitmap
;
1205 // Pick an arbitrary limit here similar to what hardware might.
1206 max_texture_size_
= 16 * 1024;
1207 best_texture_format_
= RGBA_8888
;
1210 void ResourceProvider::InitializeGL() {
1211 DCHECK(thread_checker_
.CalledOnValidThread());
1212 DCHECK(!texture_uploader_
);
1213 DCHECK_NE(GLTexture
, default_resource_type_
);
1214 DCHECK(!texture_id_allocator_
);
1215 DCHECK(!buffer_id_allocator_
);
1217 default_resource_type_
= GLTexture
;
1219 const ContextProvider::Capabilities
& caps
=
1220 output_surface_
->context_provider()->ContextCapabilities();
1222 bool use_bgra
= caps
.gpu
.texture_format_bgra8888
;
1223 use_texture_storage_ext_
= caps
.gpu
.texture_storage
;
1224 use_texture_format_bgra_
= caps
.gpu
.texture_format_bgra8888
;
1225 use_texture_usage_hint_
= caps
.gpu
.texture_usage
;
1226 use_compressed_texture_etc1_
= caps
.gpu
.texture_format_etc1
;
1227 use_sync_query_
= caps
.gpu
.sync_query
;
1229 GLES2Interface
* gl
= ContextGL();
1232 texture_uploader_
= TextureUploader::Create(gl
);
1233 max_texture_size_
= 0; // Context expects cleared value.
1234 GLC(gl
, gl
->GetIntegerv(GL_MAX_TEXTURE_SIZE
, &max_texture_size_
));
1235 best_texture_format_
= PlatformColor::BestTextureFormat(use_bgra
);
1237 texture_id_allocator_
.reset(
1238 new TextureIdAllocator(gl
, id_allocation_chunk_size_
));
1239 buffer_id_allocator_
.reset(
1240 new BufferIdAllocator(gl
, id_allocation_chunk_size_
));
1243 void ResourceProvider::CleanUpGLIfNeeded() {
1244 GLES2Interface
* gl
= ContextGL();
1245 if (default_resource_type_
!= GLTexture
) {
1246 // We are not in GL mode, but double check before returning.
1248 DCHECK(!texture_uploader_
);
1254 // Check that all GL resources has been deleted.
1255 for (ResourceMap::const_iterator itr
= resources_
.begin();
1256 itr
!= resources_
.end();
1258 DCHECK_NE(GLTexture
, itr
->second
.type
);
1260 #endif // DCHECK_IS_ON
1262 texture_uploader_
= nullptr;
1263 texture_id_allocator_
= nullptr;
1264 buffer_id_allocator_
= nullptr;
1268 int ResourceProvider::CreateChild(const ReturnCallback
& return_callback
) {
1269 DCHECK(thread_checker_
.CalledOnValidThread());
1272 child_info
.return_callback
= return_callback
;
1274 int child
= next_child_
++;
1275 children_
[child
] = child_info
;
1279 void ResourceProvider::DestroyChild(int child_id
) {
1280 ChildMap::iterator it
= children_
.find(child_id
);
1281 DCHECK(it
!= children_
.end());
1282 DestroyChildInternal(it
, Normal
);
1285 void ResourceProvider::DestroyChildInternal(ChildMap::iterator it
,
1286 DeleteStyle style
) {
1287 DCHECK(thread_checker_
.CalledOnValidThread());
1289 Child
& child
= it
->second
;
1290 DCHECK(style
== ForShutdown
|| !child
.marked_for_deletion
);
1292 ResourceIdArray resources_for_child
;
1294 for (ResourceIdMap::iterator child_it
= child
.child_to_parent_map
.begin();
1295 child_it
!= child
.child_to_parent_map
.end();
1297 ResourceId id
= child_it
->second
;
1298 resources_for_child
.push_back(id
);
1301 // If the child is going away, don't consider any resources in use.
1302 child
.in_use_resources
.clear();
1303 child
.marked_for_deletion
= true;
1305 DeleteAndReturnUnusedResourcesToChild(it
, style
, resources_for_child
);
1308 const ResourceProvider::ResourceIdMap
& ResourceProvider::GetChildToParentMap(
1310 DCHECK(thread_checker_
.CalledOnValidThread());
1311 ChildMap::const_iterator it
= children_
.find(child
);
1312 DCHECK(it
!= children_
.end());
1313 DCHECK(!it
->second
.marked_for_deletion
);
1314 return it
->second
.child_to_parent_map
;
1317 void ResourceProvider::PrepareSendToParent(const ResourceIdArray
& resources
,
1318 TransferableResourceArray
* list
) {
1319 DCHECK(thread_checker_
.CalledOnValidThread());
1320 GLES2Interface
* gl
= ContextGL();
1321 bool need_sync_point
= false;
1322 for (ResourceIdArray::const_iterator it
= resources
.begin();
1323 it
!= resources
.end();
1325 TransferableResource resource
;
1326 TransferResource(gl
, *it
, &resource
);
1327 if (!resource
.mailbox_holder
.sync_point
&& !resource
.is_software
)
1328 need_sync_point
= true;
1329 ++resources_
.find(*it
)->second
.exported_count
;
1330 list
->push_back(resource
);
1332 if (need_sync_point
) {
1333 GLuint sync_point
= gl
->InsertSyncPointCHROMIUM();
1334 for (TransferableResourceArray::iterator it
= list
->begin();
1337 if (!it
->mailbox_holder
.sync_point
)
1338 it
->mailbox_holder
.sync_point
= sync_point
;
1343 void ResourceProvider::ReceiveFromChild(
1344 int child
, const TransferableResourceArray
& resources
) {
1345 DCHECK(thread_checker_
.CalledOnValidThread());
1346 GLES2Interface
* gl
= ContextGL();
1347 Child
& child_info
= children_
.find(child
)->second
;
1348 DCHECK(!child_info
.marked_for_deletion
);
1349 for (TransferableResourceArray::const_iterator it
= resources
.begin();
1350 it
!= resources
.end();
1352 ResourceIdMap::iterator resource_in_map_it
=
1353 child_info
.child_to_parent_map
.find(it
->id
);
1354 if (resource_in_map_it
!= child_info
.child_to_parent_map
.end()) {
1355 Resource
& resource
= resources_
[resource_in_map_it
->second
];
1356 resource
.marked_for_deletion
= false;
1357 resource
.imported_count
++;
1361 if ((!it
->is_software
&& !gl
) ||
1362 (it
->is_software
&& !shared_bitmap_manager_
)) {
1363 TRACE_EVENT0("cc", "ResourceProvider::ReceiveFromChild dropping invalid");
1364 ReturnedResourceArray to_return
;
1365 to_return
.push_back(it
->ToReturnedResource());
1366 child_info
.return_callback
.Run(to_return
,
1367 blocking_main_thread_task_runner_
);
1371 ResourceId local_id
= next_id_
++;
1372 Resource
& resource
= resources_
[local_id
];
1373 if (it
->is_software
) {
1374 resource
= Resource(it
->mailbox_holder
.mailbox
,
1376 Resource::Delegated
,
1378 it
->is_repeated
? GL_REPEAT
: GL_CLAMP_TO_EDGE
);
1380 resource
= Resource(0,
1382 Resource::Delegated
,
1383 it
->mailbox_holder
.texture_target
,
1386 it
->is_repeated
? GL_REPEAT
: GL_CLAMP_TO_EDGE
,
1387 TextureHintImmutable
,
1389 resource
.mailbox
= TextureMailbox(it
->mailbox_holder
.mailbox
,
1390 it
->mailbox_holder
.texture_target
,
1391 it
->mailbox_holder
.sync_point
);
1393 resource
.child_id
= child
;
1394 // Don't allocate a texture for a child.
1395 resource
.allocated
= true;
1396 resource
.imported_count
= 1;
1397 resource
.allow_overlay
= it
->allow_overlay
;
1398 child_info
.parent_to_child_map
[local_id
] = it
->id
;
1399 child_info
.child_to_parent_map
[it
->id
] = local_id
;
1403 void ResourceProvider::DeclareUsedResourcesFromChild(
1405 const ResourceIdArray
& resources_from_child
) {
1406 DCHECK(thread_checker_
.CalledOnValidThread());
1408 ChildMap::iterator child_it
= children_
.find(child
);
1409 DCHECK(child_it
!= children_
.end());
1410 Child
& child_info
= child_it
->second
;
1411 DCHECK(!child_info
.marked_for_deletion
);
1412 child_info
.in_use_resources
.clear();
1414 for (size_t i
= 0; i
< resources_from_child
.size(); ++i
) {
1415 ResourceIdMap::iterator it
=
1416 child_info
.child_to_parent_map
.find(resources_from_child
[i
]);
1417 DCHECK(it
!= child_info
.child_to_parent_map
.end());
1419 ResourceId local_id
= it
->second
;
1420 DCHECK(!resources_
[local_id
].marked_for_deletion
);
1421 child_info
.in_use_resources
.insert(local_id
);
1424 ResourceIdArray unused
;
1425 for (ResourceIdMap::iterator it
= child_info
.child_to_parent_map
.begin();
1426 it
!= child_info
.child_to_parent_map
.end();
1428 ResourceId local_id
= it
->second
;
1429 bool resource_is_in_use
= child_info
.in_use_resources
.count(local_id
) > 0;
1430 if (!resource_is_in_use
)
1431 unused
.push_back(local_id
);
1433 DeleteAndReturnUnusedResourcesToChild(child_it
, Normal
, unused
);
1437 bool ResourceProvider::CompareResourceMapIteratorsByChildId(
1438 const std::pair
<ReturnedResource
, ResourceMap::iterator
>& a
,
1439 const std::pair
<ReturnedResource
, ResourceMap::iterator
>& b
) {
1440 const ResourceMap::iterator
& a_it
= a
.second
;
1441 const ResourceMap::iterator
& b_it
= b
.second
;
1442 const Resource
& a_resource
= a_it
->second
;
1443 const Resource
& b_resource
= b_it
->second
;
1444 return a_resource
.child_id
< b_resource
.child_id
;
1447 void ResourceProvider::ReceiveReturnsFromParent(
1448 const ReturnedResourceArray
& resources
) {
1449 DCHECK(thread_checker_
.CalledOnValidThread());
1450 GLES2Interface
* gl
= ContextGL();
1453 ResourceIdArray resources_for_child
;
1455 std::vector
<std::pair
<ReturnedResource
, ResourceMap::iterator
>>
1458 for (ReturnedResourceArray::const_iterator it
= resources
.begin();
1459 it
!= resources
.end();
1461 ResourceId local_id
= it
->id
;
1462 ResourceMap::iterator map_iterator
= resources_
.find(local_id
);
1464 // Resource was already lost (e.g. it belonged to a child that was
1466 if (map_iterator
== resources_
.end())
1469 sorted_resources
.push_back(
1470 std::pair
<ReturnedResource
, ResourceMap::iterator
>(*it
, map_iterator
));
1473 std::sort(sorted_resources
.begin(),
1474 sorted_resources
.end(),
1475 CompareResourceMapIteratorsByChildId
);
1477 ChildMap::iterator child_it
= children_
.end();
1478 for (size_t i
= 0; i
< sorted_resources
.size(); ++i
) {
1479 ReturnedResource
& returned
= sorted_resources
[i
].first
;
1480 ResourceMap::iterator
& map_iterator
= sorted_resources
[i
].second
;
1481 ResourceId local_id
= map_iterator
->first
;
1482 Resource
* resource
= &map_iterator
->second
;
1484 CHECK_GE(resource
->exported_count
, returned
.count
);
1485 resource
->exported_count
-= returned
.count
;
1486 resource
->lost
|= returned
.lost
;
1487 if (resource
->exported_count
)
1490 // Need to wait for the current read lock fence to pass before we can
1491 // recycle this resource.
1492 if (resource
->read_lock_fences_enabled
) {
1493 if (current_read_lock_fence_
.get())
1494 current_read_lock_fence_
->Set();
1495 resource
->read_lock_fence
= current_read_lock_fence_
;
1498 if (returned
.sync_point
) {
1499 DCHECK(!resource
->has_shared_bitmap_id
);
1500 if (resource
->origin
== Resource::Internal
) {
1501 DCHECK(resource
->gl_id
);
1502 GLC(gl
, gl
->WaitSyncPointCHROMIUM(returned
.sync_point
));
1504 DCHECK(!resource
->gl_id
);
1505 resource
->mailbox
.set_sync_point(returned
.sync_point
);
1509 if (!resource
->marked_for_deletion
)
1512 if (!resource
->child_id
) {
1513 // The resource belongs to this ResourceProvider, so it can be destroyed.
1514 DeleteResourceInternal(map_iterator
, Normal
);
1518 DCHECK(resource
->origin
== Resource::Delegated
);
1519 // Delete the resource and return it to the child it came from one.
1520 if (resource
->child_id
!= child_id
) {
1522 DCHECK_NE(resources_for_child
.size(), 0u);
1523 DCHECK(child_it
!= children_
.end());
1524 DeleteAndReturnUnusedResourcesToChild(
1525 child_it
, Normal
, resources_for_child
);
1526 resources_for_child
.clear();
1529 child_it
= children_
.find(resource
->child_id
);
1530 DCHECK(child_it
!= children_
.end());
1531 child_id
= resource
->child_id
;
1533 resources_for_child
.push_back(local_id
);
1537 DCHECK_NE(resources_for_child
.size(), 0u);
1538 DCHECK(child_it
!= children_
.end());
1539 DeleteAndReturnUnusedResourcesToChild(
1540 child_it
, Normal
, resources_for_child
);
1544 void ResourceProvider::TransferResource(GLES2Interface
* gl
,
1546 TransferableResource
* resource
) {
1547 Resource
* source
= GetResource(id
);
1548 DCHECK(!source
->locked_for_write
);
1549 DCHECK(!source
->lock_for_read_count
);
1550 DCHECK(source
->origin
!= Resource::External
|| source
->mailbox
.IsValid());
1551 DCHECK(source
->allocated
);
1553 resource
->format
= source
->format
;
1554 resource
->mailbox_holder
.texture_target
= source
->target
;
1555 resource
->filter
= source
->filter
;
1556 resource
->size
= source
->size
;
1557 resource
->is_repeated
= (source
->wrap_mode
== GL_REPEAT
);
1558 resource
->allow_overlay
= source
->allow_overlay
;
1560 if (source
->type
== Bitmap
) {
1561 resource
->mailbox_holder
.mailbox
= source
->shared_bitmap_id
;
1562 resource
->is_software
= true;
1563 } else if (!source
->mailbox
.IsValid()) {
1565 DCHECK(source
->gl_id
);
1566 DCHECK(source
->origin
== Resource::Internal
);
1568 gl
->BindTexture(resource
->mailbox_holder
.texture_target
,
1570 if (source
->image_id
) {
1571 DCHECK(source
->dirty_image
);
1572 BindImageForSampling(source
);
1574 // This is a resource allocated by the compositor, we need to produce it.
1575 // Don't set a sync point, the caller will do it.
1576 GLC(gl
, gl
->GenMailboxCHROMIUM(resource
->mailbox_holder
.mailbox
.name
));
1578 gl
->ProduceTextureCHROMIUM(resource
->mailbox_holder
.texture_target
,
1579 resource
->mailbox_holder
.mailbox
.name
));
1580 source
->mailbox
= TextureMailbox(resource
->mailbox_holder
);
1582 DCHECK(source
->mailbox
.IsTexture());
1583 if (source
->image_id
&& source
->dirty_image
) {
1584 DCHECK(source
->gl_id
);
1585 DCHECK(source
->origin
== Resource::Internal
);
1587 gl
->BindTexture(resource
->mailbox_holder
.texture_target
,
1589 BindImageForSampling(source
);
1591 // This is either an external resource, or a compositor resource that we
1592 // already exported. Make sure to forward the sync point that we were given.
1593 resource
->mailbox_holder
.mailbox
= source
->mailbox
.mailbox();
1594 resource
->mailbox_holder
.texture_target
= source
->mailbox
.target();
1595 resource
->mailbox_holder
.sync_point
= source
->mailbox
.sync_point();
1596 source
->mailbox
.set_sync_point(0);
1600 void ResourceProvider::DeleteAndReturnUnusedResourcesToChild(
1601 ChildMap::iterator child_it
,
1603 const ResourceIdArray
& unused
) {
1604 DCHECK(thread_checker_
.CalledOnValidThread());
1605 DCHECK(child_it
!= children_
.end());
1606 Child
* child_info
= &child_it
->second
;
1608 if (unused
.empty() && !child_info
->marked_for_deletion
)
1611 ReturnedResourceArray to_return
;
1613 GLES2Interface
* gl
= ContextGL();
1614 bool need_sync_point
= false;
1615 for (size_t i
= 0; i
< unused
.size(); ++i
) {
1616 ResourceId local_id
= unused
[i
];
1618 ResourceMap::iterator it
= resources_
.find(local_id
);
1619 CHECK(it
!= resources_
.end());
1620 Resource
& resource
= it
->second
;
1622 DCHECK(!resource
.locked_for_write
);
1623 DCHECK_EQ(0u, child_info
->in_use_resources
.count(local_id
));
1624 DCHECK(child_info
->parent_to_child_map
.count(local_id
));
1626 ResourceId child_id
= child_info
->parent_to_child_map
[local_id
];
1627 DCHECK(child_info
->child_to_parent_map
.count(child_id
));
1630 resource
.lost
|| (resource
.type
== GLTexture
&& lost_output_surface_
);
1631 if (resource
.exported_count
> 0 || resource
.lock_for_read_count
> 0) {
1632 if (style
!= ForShutdown
) {
1633 // Defer this until we receive the resource back from the parent or
1634 // the read lock is released.
1635 resource
.marked_for_deletion
= true;
1639 // We still have an exported_count, so we'll have to lose it.
1643 if (gl
&& resource
.filter
!= resource
.original_filter
) {
1644 DCHECK(resource
.target
);
1645 DCHECK(resource
.gl_id
);
1647 GLC(gl
, gl
->BindTexture(resource
.target
, resource
.gl_id
));
1649 gl
->TexParameteri(resource
.target
,
1650 GL_TEXTURE_MIN_FILTER
,
1651 resource
.original_filter
));
1653 gl
->TexParameteri(resource
.target
,
1654 GL_TEXTURE_MAG_FILTER
,
1655 resource
.original_filter
));
1658 ReturnedResource returned
;
1659 returned
.id
= child_id
;
1660 returned
.sync_point
= resource
.mailbox
.sync_point();
1661 if (!returned
.sync_point
&& resource
.type
== GLTexture
)
1662 need_sync_point
= true;
1663 returned
.count
= resource
.imported_count
;
1664 returned
.lost
= is_lost
;
1665 to_return
.push_back(returned
);
1667 child_info
->parent_to_child_map
.erase(local_id
);
1668 child_info
->child_to_parent_map
.erase(child_id
);
1669 resource
.imported_count
= 0;
1670 DeleteResourceInternal(it
, style
);
1672 if (need_sync_point
) {
1674 GLuint sync_point
= gl
->InsertSyncPointCHROMIUM();
1675 for (size_t i
= 0; i
< to_return
.size(); ++i
) {
1676 if (!to_return
[i
].sync_point
)
1677 to_return
[i
].sync_point
= sync_point
;
1681 if (!to_return
.empty())
1682 child_info
->return_callback
.Run(to_return
,
1683 blocking_main_thread_task_runner_
);
1685 if (child_info
->marked_for_deletion
&&
1686 child_info
->parent_to_child_map
.empty()) {
1687 DCHECK(child_info
->child_to_parent_map
.empty());
1688 children_
.erase(child_it
);
1692 void ResourceProvider::AcquirePixelBuffer(ResourceId id
) {
1693 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug"),
1694 "ResourceProvider::AcquirePixelBuffer");
1696 Resource
* resource
= GetResource(id
);
1697 DCHECK(resource
->origin
== Resource::Internal
);
1698 DCHECK_EQ(resource
->exported_count
, 0);
1699 DCHECK(!resource
->image_id
);
1700 DCHECK_NE(ETC1
, resource
->format
);
1702 DCHECK_EQ(GLTexture
, resource
->type
);
1703 GLES2Interface
* gl
= ContextGL();
1705 if (!resource
->gl_pixel_buffer_id
)
1706 resource
->gl_pixel_buffer_id
= buffer_id_allocator_
->NextId();
1707 gl
->BindBuffer(GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM
,
1708 resource
->gl_pixel_buffer_id
);
1709 unsigned bytes_per_pixel
= BitsPerPixel(resource
->format
) / 8;
1710 gl
->BufferData(GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM
,
1711 resource
->size
.height() *
1712 RoundUp(bytes_per_pixel
* resource
->size
.width(), 4u),
1715 gl
->BindBuffer(GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM
, 0);
1718 void ResourceProvider::ReleasePixelBuffer(ResourceId id
) {
1719 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug"),
1720 "ResourceProvider::ReleasePixelBuffer");
1722 Resource
* resource
= GetResource(id
);
1723 DCHECK(resource
->origin
== Resource::Internal
);
1724 DCHECK_EQ(resource
->exported_count
, 0);
1725 DCHECK(!resource
->image_id
);
1727 // The pixel buffer can be released while there is a pending "set pixels"
1728 // if completion has been forced. Any shared memory associated with this
1729 // pixel buffer will not be freed until the waitAsyncTexImage2DCHROMIUM
1730 // command has been processed on the service side. It is also safe to
1731 // reuse any query id associated with this resource before they complete
1732 // as each new query has a unique submit count.
1733 if (resource
->pending_set_pixels
) {
1734 DCHECK(resource
->set_pixels_completion_forced
);
1735 resource
->pending_set_pixels
= false;
1736 resource
->locked_for_write
= false;
1739 DCHECK_EQ(GLTexture
, resource
->type
);
1740 if (!resource
->gl_pixel_buffer_id
)
1742 GLES2Interface
* gl
= ContextGL();
1744 gl
->BindBuffer(GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM
,
1745 resource
->gl_pixel_buffer_id
);
1747 GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM
, 0, NULL
, GL_DYNAMIC_DRAW
);
1748 gl
->BindBuffer(GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM
, 0);
1751 uint8_t* ResourceProvider::MapPixelBuffer(ResourceId id
, int* stride
) {
1752 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug"),
1753 "ResourceProvider::MapPixelBuffer");
1755 Resource
* resource
= GetResource(id
);
1756 DCHECK(resource
->origin
== Resource::Internal
);
1757 DCHECK_EQ(resource
->exported_count
, 0);
1758 DCHECK(!resource
->image_id
);
1761 DCHECK_EQ(GLTexture
, resource
->type
);
1762 GLES2Interface
* gl
= ContextGL();
1764 DCHECK(resource
->gl_pixel_buffer_id
);
1765 gl
->BindBuffer(GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM
,
1766 resource
->gl_pixel_buffer_id
);
1767 uint8_t* image
= static_cast<uint8_t*>(gl
->MapBufferCHROMIUM(
1768 GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM
, GL_WRITE_ONLY
));
1769 gl
->BindBuffer(GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM
, 0);
1770 // Buffer is required to be 4-byte aligned.
1771 CHECK(!(reinterpret_cast<intptr_t>(image
) & 3));
1775 void ResourceProvider::UnmapPixelBuffer(ResourceId id
) {
1776 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug"),
1777 "ResourceProvider::UnmapPixelBuffer");
1779 Resource
* resource
= GetResource(id
);
1780 DCHECK(resource
->origin
== Resource::Internal
);
1781 DCHECK_EQ(resource
->exported_count
, 0);
1782 DCHECK(!resource
->image_id
);
1784 DCHECK_EQ(GLTexture
, resource
->type
);
1785 GLES2Interface
* gl
= ContextGL();
1787 DCHECK(resource
->gl_pixel_buffer_id
);
1788 gl
->BindBuffer(GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM
,
1789 resource
->gl_pixel_buffer_id
);
1790 gl
->UnmapBufferCHROMIUM(GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM
);
1791 gl
->BindBuffer(GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM
, 0);
1794 GLenum
ResourceProvider::BindForSampling(ResourceId resource_id
,
1797 DCHECK(thread_checker_
.CalledOnValidThread());
1798 GLES2Interface
* gl
= ContextGL();
1799 ResourceMap::iterator it
= resources_
.find(resource_id
);
1800 DCHECK(it
!= resources_
.end());
1801 Resource
* resource
= &it
->second
;
1802 DCHECK(resource
->lock_for_read_count
);
1803 DCHECK(!resource
->locked_for_write
|| resource
->set_pixels_completion_forced
);
1805 ScopedSetActiveTexture
scoped_active_tex(gl
, unit
);
1806 GLenum target
= resource
->target
;
1807 GLC(gl
, gl
->BindTexture(target
, resource
->gl_id
));
1808 if (filter
!= resource
->filter
) {
1809 GLC(gl
, gl
->TexParameteri(target
, GL_TEXTURE_MIN_FILTER
, filter
));
1810 GLC(gl
, gl
->TexParameteri(target
, GL_TEXTURE_MAG_FILTER
, filter
));
1811 resource
->filter
= filter
;
1814 if (resource
->image_id
&& resource
->dirty_image
)
1815 BindImageForSampling(resource
);
1820 void ResourceProvider::BeginSetPixels(ResourceId id
) {
1821 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug"),
1822 "ResourceProvider::BeginSetPixels");
1824 Resource
* resource
= GetResource(id
);
1825 DCHECK(!resource
->pending_set_pixels
);
1827 LazyCreate(resource
);
1828 DCHECK(resource
->origin
== Resource::Internal
);
1829 DCHECK(resource
->gl_id
|| resource
->allocated
);
1830 DCHECK(ReadLockFenceHasPassed(resource
));
1831 DCHECK(!resource
->image_id
);
1833 bool allocate
= !resource
->allocated
;
1834 resource
->allocated
= true;
1837 DCHECK_EQ(GLTexture
, resource
->type
);
1838 DCHECK(resource
->gl_id
);
1839 GLES2Interface
* gl
= ContextGL();
1841 DCHECK(resource
->gl_pixel_buffer_id
);
1842 DCHECK_EQ(resource
->target
, static_cast<GLenum
>(GL_TEXTURE_2D
));
1843 gl
->BindTexture(GL_TEXTURE_2D
, resource
->gl_id
);
1844 gl
->BindBuffer(GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM
,
1845 resource
->gl_pixel_buffer_id
);
1846 if (!resource
->gl_upload_query_id
)
1847 gl
->GenQueriesEXT(1, &resource
->gl_upload_query_id
);
1848 gl
->BeginQueryEXT(GL_ASYNC_PIXEL_UNPACK_COMPLETED_CHROMIUM
,
1849 resource
->gl_upload_query_id
);
1851 gl
->AsyncTexImage2DCHROMIUM(GL_TEXTURE_2D
,
1853 GLInternalFormat(resource
->format
),
1854 resource
->size
.width(),
1855 resource
->size
.height(),
1857 GLDataFormat(resource
->format
),
1858 GLDataType(resource
->format
),
1861 gl
->AsyncTexSubImage2DCHROMIUM(GL_TEXTURE_2D
,
1865 resource
->size
.width(),
1866 resource
->size
.height(),
1867 GLDataFormat(resource
->format
),
1868 GLDataType(resource
->format
),
1871 gl
->EndQueryEXT(GL_ASYNC_PIXEL_UNPACK_COMPLETED_CHROMIUM
);
1872 gl
->BindBuffer(GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM
, 0);
1874 resource
->pending_set_pixels
= true;
1875 resource
->set_pixels_completion_forced
= false;
1878 void ResourceProvider::ForceSetPixelsToComplete(ResourceId id
) {
1879 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug"),
1880 "ResourceProvider::ForceSetPixelsToComplete");
1882 Resource
* resource
= GetResource(id
);
1884 DCHECK(resource
->locked_for_write
);
1885 DCHECK(resource
->pending_set_pixels
);
1886 DCHECK(!resource
->set_pixels_completion_forced
);
1888 if (resource
->gl_id
) {
1889 GLES2Interface
* gl
= ContextGL();
1890 GLC(gl
, gl
->BindTexture(GL_TEXTURE_2D
, resource
->gl_id
));
1891 GLC(gl
, gl
->WaitAsyncTexImage2DCHROMIUM(GL_TEXTURE_2D
));
1892 GLC(gl
, gl
->BindTexture(GL_TEXTURE_2D
, 0));
1895 resource
->set_pixels_completion_forced
= true;
1898 bool ResourceProvider::DidSetPixelsComplete(ResourceId id
) {
1899 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug"),
1900 "ResourceProvider::DidSetPixelsComplete");
1902 Resource
* resource
= GetResource(id
);
1904 DCHECK(resource
->locked_for_write
);
1905 DCHECK(resource
->pending_set_pixels
);
1907 if (resource
->gl_id
) {
1908 GLES2Interface
* gl
= ContextGL();
1910 DCHECK(resource
->gl_upload_query_id
);
1911 GLuint complete
= 1;
1912 gl
->GetQueryObjectuivEXT(
1913 resource
->gl_upload_query_id
, GL_QUERY_RESULT_AVAILABLE_EXT
, &complete
);
1918 resource
->pending_set_pixels
= false;
1919 UnlockForWrite(resource
);
1921 // Async set pixels commands are not necessarily processed in-sequence with
1922 // drawing commands. Read lock fences are required to ensure that async
1923 // commands don't access the resource while used for drawing.
1924 resource
->read_lock_fences_enabled
= true;
1929 void ResourceProvider::CreateForTesting(ResourceId id
) {
1930 LazyCreate(GetResource(id
));
1933 GLenum
ResourceProvider::TargetForTesting(ResourceId id
) {
1934 Resource
* resource
= GetResource(id
);
1935 return resource
->target
;
1938 void ResourceProvider::LazyCreate(Resource
* resource
) {
1939 if (resource
->type
!= GLTexture
|| resource
->origin
!= Resource::Internal
)
1942 if (resource
->gl_id
)
1945 DCHECK(resource
->texture_pool
);
1946 DCHECK(resource
->origin
== Resource::Internal
);
1947 DCHECK(!resource
->mailbox
.IsValid());
1948 resource
->gl_id
= texture_id_allocator_
->NextId();
1950 GLES2Interface
* gl
= ContextGL();
1953 // Create and set texture properties. Allocation is delayed until needed.
1954 GLC(gl
, gl
->BindTexture(resource
->target
, resource
->gl_id
));
1957 resource
->target
, GL_TEXTURE_MIN_FILTER
, resource
->original_filter
));
1960 resource
->target
, GL_TEXTURE_MAG_FILTER
, resource
->original_filter
));
1963 resource
->target
, GL_TEXTURE_WRAP_S
, resource
->wrap_mode
));
1966 resource
->target
, GL_TEXTURE_WRAP_T
, resource
->wrap_mode
));
1969 resource
->target
, GL_TEXTURE_POOL_CHROMIUM
, resource
->texture_pool
));
1970 if (use_texture_usage_hint_
&& (resource
->hint
& TextureHintFramebuffer
)) {
1972 gl
->TexParameteri(resource
->target
,
1973 GL_TEXTURE_USAGE_ANGLE
,
1974 GL_FRAMEBUFFER_ATTACHMENT_ANGLE
));
1978 void ResourceProvider::AllocateForTesting(ResourceId id
) {
1979 LazyAllocate(GetResource(id
));
1982 void ResourceProvider::LazyAllocate(Resource
* resource
) {
1984 if (resource
->allocated
)
1986 LazyCreate(resource
);
1987 if (!resource
->gl_id
)
1989 resource
->allocated
= true;
1990 GLES2Interface
* gl
= ContextGL();
1991 gfx::Size
& size
= resource
->size
;
1992 DCHECK_EQ(resource
->target
, static_cast<GLenum
>(GL_TEXTURE_2D
));
1993 ResourceFormat format
= resource
->format
;
1994 GLC(gl
, gl
->BindTexture(GL_TEXTURE_2D
, resource
->gl_id
));
1995 if (use_texture_storage_ext_
&&
1996 IsFormatSupportedForStorage(format
, use_texture_format_bgra_
) &&
1997 (resource
->hint
& TextureHintImmutable
)) {
1998 GLenum storage_format
= TextureToStorageFormat(format
);
2000 gl
->TexStorage2DEXT(
2001 GL_TEXTURE_2D
, 1, storage_format
, size
.width(), size
.height()));
2003 // ETC1 does not support preallocation.
2004 if (format
!= ETC1
) {
2006 gl
->TexImage2D(GL_TEXTURE_2D
,
2008 GLInternalFormat(format
),
2012 GLDataFormat(format
),
2019 void ResourceProvider::BindImageForSampling(Resource
* resource
) {
2020 GLES2Interface
* gl
= ContextGL();
2021 DCHECK(resource
->gl_id
);
2022 DCHECK(resource
->image_id
);
2024 // Release image currently bound to texture.
2025 if (resource
->bound_image_id
)
2026 gl
->ReleaseTexImage2DCHROMIUM(resource
->target
, resource
->bound_image_id
);
2027 gl
->BindTexImage2DCHROMIUM(resource
->target
, resource
->image_id
);
2028 resource
->bound_image_id
= resource
->image_id
;
2029 resource
->dirty_image
= false;
2032 void ResourceProvider::CopyResource(ResourceId source_id
, ResourceId dest_id
) {
2033 TRACE_EVENT0("cc", "ResourceProvider::CopyResource");
2035 Resource
* source_resource
= GetResource(source_id
);
2036 DCHECK(!source_resource
->lock_for_read_count
);
2037 DCHECK(source_resource
->origin
== Resource::Internal
);
2038 DCHECK_EQ(source_resource
->exported_count
, 0);
2039 DCHECK_EQ(GLTexture
, source_resource
->type
);
2040 DCHECK(source_resource
->allocated
);
2041 LazyCreate(source_resource
);
2043 Resource
* dest_resource
= GetResource(dest_id
);
2044 DCHECK(!dest_resource
->locked_for_write
);
2045 DCHECK(!dest_resource
->lock_for_read_count
);
2046 DCHECK(dest_resource
->origin
== Resource::Internal
);
2047 DCHECK_EQ(dest_resource
->exported_count
, 0);
2048 DCHECK_EQ(GLTexture
, dest_resource
->type
);
2049 LazyCreate(dest_resource
);
2051 DCHECK_EQ(source_resource
->type
, dest_resource
->type
);
2052 DCHECK_EQ(source_resource
->format
, dest_resource
->format
);
2053 DCHECK(source_resource
->size
== dest_resource
->size
);
2055 GLES2Interface
* gl
= ContextGL();
2057 if (source_resource
->image_id
&& source_resource
->dirty_image
) {
2058 gl
->BindTexture(source_resource
->target
, source_resource
->gl_id
);
2059 BindImageForSampling(source_resource
);
2061 if (use_sync_query_
) {
2062 if (!source_resource
->gl_read_lock_query_id
)
2063 gl
->GenQueriesEXT(1, &source_resource
->gl_read_lock_query_id
);
2064 gl
->BeginQueryEXT(GL_COMMANDS_COMPLETED_CHROMIUM
,
2065 source_resource
->gl_read_lock_query_id
);
2067 DCHECK(!dest_resource
->image_id
);
2068 dest_resource
->allocated
= true;
2069 gl
->CopyTextureCHROMIUM(dest_resource
->target
,
2070 source_resource
->gl_id
,
2071 dest_resource
->gl_id
,
2073 GLInternalFormat(dest_resource
->format
),
2074 GLDataType(dest_resource
->format
));
2075 if (source_resource
->gl_read_lock_query_id
) {
2076 // End query and create a read lock fence that will prevent access to
2077 // source resource until CopyTextureCHROMIUM command has completed.
2078 gl
->EndQueryEXT(GL_COMMANDS_COMPLETED_CHROMIUM
);
2079 source_resource
->read_lock_fence
= make_scoped_refptr(
2080 new QueryFence(gl
, source_resource
->gl_read_lock_query_id
));
2082 // Create a SynchronousFence when CHROMIUM_sync_query extension is missing.
2083 // Try to use one synchronous fence for as many CopyResource operations as
2084 // possible as that reduce the number of times we have to synchronize with
2086 if (!synchronous_fence_
.get() || synchronous_fence_
->has_synchronized())
2087 synchronous_fence_
= make_scoped_refptr(new SynchronousFence(gl
));
2088 source_resource
->read_lock_fence
= synchronous_fence_
;
2089 source_resource
->read_lock_fence
->Set();
2093 void ResourceProvider::WaitSyncPointIfNeeded(ResourceId id
) {
2094 Resource
* resource
= GetResource(id
);
2095 DCHECK_EQ(resource
->exported_count
, 0);
2096 DCHECK(resource
->allocated
);
2097 if (resource
->type
!= GLTexture
|| resource
->gl_id
)
2099 if (!resource
->mailbox
.sync_point())
2101 DCHECK(resource
->mailbox
.IsValid());
2102 GLES2Interface
* gl
= ContextGL();
2104 GLC(gl
, gl
->WaitSyncPointCHROMIUM(resource
->mailbox
.sync_point()));
2105 resource
->mailbox
.set_sync_point(0);
2108 void ResourceProvider::WaitReadLockIfNeeded(ResourceId id
) {
2109 Resource
* resource
= GetResource(id
);
2110 DCHECK_EQ(resource
->exported_count
, 0);
2111 if (!resource
->read_lock_fence
.get())
2114 resource
->read_lock_fence
->Wait();
2117 GLint
ResourceProvider::GetActiveTextureUnit(GLES2Interface
* gl
) {
2118 GLint active_unit
= 0;
2119 gl
->GetIntegerv(GL_ACTIVE_TEXTURE
, &active_unit
);
2123 GLES2Interface
* ResourceProvider::ContextGL() const {
2124 ContextProvider
* context_provider
= output_surface_
->context_provider();
2125 return context_provider
? context_provider
->ContextGL() : NULL
;
2128 class GrContext
* ResourceProvider::GrContext() const {
2129 ContextProvider
* context_provider
= output_surface_
->context_provider();
2130 return context_provider
? context_provider
->GrContext() : NULL
;