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/stl_util.h"
13 #include "base/strings/string_split.h"
14 #include "base/strings/string_util.h"
15 #include "base/trace_event/trace_event.h"
16 #include "cc/base/util.h"
17 #include "cc/output/gl_renderer.h" // For the GLC() macro.
18 #include "cc/resources/platform_color.h"
19 #include "cc/resources/returned_resource.h"
20 #include "cc/resources/shared_bitmap_manager.h"
21 #include "cc/resources/texture_uploader.h"
22 #include "cc/resources/transferable_resource.h"
23 #include "gpu/GLES2/gl2extchromium.h"
24 #include "gpu/command_buffer/client/gles2_interface.h"
25 #include "gpu/command_buffer/client/gpu_memory_buffer_manager.h"
26 #include "third_party/khronos/GLES2/gl2.h"
27 #include "third_party/khronos/GLES2/gl2ext.h"
28 #include "third_party/skia/include/core/SkSurface.h"
29 #include "third_party/skia/include/gpu/GrContext.h"
30 #include "ui/gfx/frame_time.h"
31 #include "ui/gfx/geometry/rect.h"
32 #include "ui/gfx/geometry/vector2d.h"
33 #include "ui/gfx/gpu_memory_buffer.h"
35 using gpu::gles2::GLES2Interface
;
41 virtual ~IdAllocator() {}
43 virtual GLuint
NextId() = 0;
46 IdAllocator(GLES2Interface
* gl
, size_t id_allocation_chunk_size
)
48 id_allocation_chunk_size_(id_allocation_chunk_size
),
49 ids_(new GLuint
[id_allocation_chunk_size
]),
50 next_id_index_(id_allocation_chunk_size
) {
51 DCHECK(id_allocation_chunk_size_
);
55 const size_t id_allocation_chunk_size_
;
56 scoped_ptr
<GLuint
[]> ids_
;
57 size_t next_id_index_
;
62 // Measured in seconds.
63 const double kSoftwareUploadTickRate
= 0.000250;
64 const double kTextureUploadTickRate
= 0.004;
66 GLenum
TextureToStorageFormat(ResourceFormat format
) {
67 GLenum storage_format
= GL_RGBA8_OES
;
72 storage_format
= GL_BGRA8_EXT
;
84 return storage_format
;
87 bool IsFormatSupportedForStorage(ResourceFormat format
, bool use_bgra
) {
104 GrPixelConfig
ToGrPixelConfig(ResourceFormat format
) {
107 return kRGBA_8888_GrPixelConfig
;
109 return kBGRA_8888_GrPixelConfig
;
111 return kRGBA_4444_GrPixelConfig
;
115 DCHECK(false) << "Unsupported resource format.";
116 return kSkia8888_GrPixelConfig
;
119 gfx::GpuMemoryBuffer::Format
ToGpuMemoryBufferFormat(ResourceFormat format
) {
122 return gfx::GpuMemoryBuffer::Format::RGBA_8888
;
124 return gfx::GpuMemoryBuffer::Format::BGRA_8888
;
134 return gfx::GpuMemoryBuffer::Format::RGBA_8888
;
137 class ScopedSetActiveTexture
{
139 ScopedSetActiveTexture(GLES2Interface
* gl
, GLenum unit
)
140 : gl_(gl
), unit_(unit
) {
141 DCHECK_EQ(GL_TEXTURE0
, ResourceProvider::GetActiveTextureUnit(gl_
));
143 if (unit_
!= GL_TEXTURE0
)
144 GLC(gl_
, gl_
->ActiveTexture(unit_
));
147 ~ScopedSetActiveTexture() {
148 // Active unit being GL_TEXTURE0 is effectively the ground state.
149 if (unit_
!= GL_TEXTURE0
)
150 GLC(gl_
, gl_
->ActiveTexture(GL_TEXTURE0
));
158 class TextureIdAllocator
: public IdAllocator
{
160 TextureIdAllocator(GLES2Interface
* gl
,
161 size_t texture_id_allocation_chunk_size
)
162 : IdAllocator(gl
, texture_id_allocation_chunk_size
) {}
163 ~TextureIdAllocator() override
{
164 gl_
->DeleteTextures(id_allocation_chunk_size_
- next_id_index_
,
165 ids_
.get() + next_id_index_
);
168 // Overridden from IdAllocator:
169 GLuint
NextId() override
{
170 if (next_id_index_
== id_allocation_chunk_size_
) {
171 gl_
->GenTextures(id_allocation_chunk_size_
, ids_
.get());
175 return ids_
[next_id_index_
++];
179 DISALLOW_COPY_AND_ASSIGN(TextureIdAllocator
);
182 class BufferIdAllocator
: public IdAllocator
{
184 BufferIdAllocator(GLES2Interface
* gl
, size_t buffer_id_allocation_chunk_size
)
185 : IdAllocator(gl
, buffer_id_allocation_chunk_size
) {}
186 ~BufferIdAllocator() override
{
187 gl_
->DeleteBuffers(id_allocation_chunk_size_
- next_id_index_
,
188 ids_
.get() + next_id_index_
);
191 // Overridden from IdAllocator:
192 GLuint
NextId() override
{
193 if (next_id_index_
== id_allocation_chunk_size_
) {
194 gl_
->GenBuffers(id_allocation_chunk_size_
, ids_
.get());
198 return ids_
[next_id_index_
++];
202 DISALLOW_COPY_AND_ASSIGN(BufferIdAllocator
);
205 // Query object based fence implementation used to detect completion of copy
206 // texture operations. Fence has passed when query result is available.
207 class CopyTextureFence
: public ResourceProvider::Fence
{
209 CopyTextureFence(gpu::gles2::GLES2Interface
* gl
, unsigned query_id
)
210 : gl_(gl
), query_id_(query_id
) {}
212 // Overridden from ResourceProvider::Fence:
213 void Set() override
{}
214 bool HasPassed() override
{
215 unsigned available
= 1;
216 gl_
->GetQueryObjectuivEXT(
217 query_id_
, GL_QUERY_RESULT_AVAILABLE_EXT
, &available
);
224 void Wait() override
{
225 // ProcessResult() will wait for result to become available.
230 ~CopyTextureFence() override
{}
232 void ProcessResult() {
233 unsigned time_elapsed_us
= 0;
234 gl_
->GetQueryObjectuivEXT(query_id_
, GL_QUERY_RESULT_EXT
, &time_elapsed_us
);
235 UMA_HISTOGRAM_CUSTOM_COUNTS("Renderer4.CopyTextureLatency", time_elapsed_us
,
239 gpu::gles2::GLES2Interface
* gl_
;
242 DISALLOW_COPY_AND_ASSIGN(CopyTextureFence
);
247 ResourceProvider::Resource::Resource()
250 gl_pixel_buffer_id(0),
251 gl_upload_query_id(0),
252 gl_read_lock_query_id(0),
254 lock_for_read_count(0),
258 locked_for_write(false),
260 marked_for_deletion(false),
261 pending_set_pixels(false),
262 set_pixels_completion_forced(false),
264 read_lock_fences_enabled(false),
265 has_shared_bitmap_id(false),
266 allow_overlay(false),
267 read_lock_fence(NULL
),
277 hint(TextureHintImmutable
),
281 gpu_memory_buffer(NULL
) {
284 ResourceProvider::Resource::~Resource() {}
286 ResourceProvider::Resource::Resource(GLuint texture_id
,
287 const gfx::Size
& size
,
294 ResourceFormat format
)
297 gl_pixel_buffer_id(0),
298 gl_upload_query_id(0),
299 gl_read_lock_query_id(0),
301 lock_for_read_count(0),
305 locked_for_write(false),
307 marked_for_deletion(false),
308 pending_set_pixels(false),
309 set_pixels_completion_forced(false),
311 read_lock_fences_enabled(false),
312 has_shared_bitmap_id(false),
313 allow_overlay(false),
314 read_lock_fence(NULL
),
318 original_filter(filter
),
322 texture_pool(texture_pool
),
323 wrap_mode(wrap_mode
),
328 gpu_memory_buffer(NULL
) {
329 DCHECK(wrap_mode
== GL_CLAMP_TO_EDGE
|| wrap_mode
== GL_REPEAT
);
330 DCHECK_EQ(origin
== Internal
, !!texture_pool
);
333 ResourceProvider::Resource::Resource(uint8_t* pixels
,
334 SharedBitmap
* bitmap
,
335 const gfx::Size
& size
,
341 gl_pixel_buffer_id(0),
342 gl_upload_query_id(0),
343 gl_read_lock_query_id(0),
345 lock_for_read_count(0),
349 locked_for_write(false),
351 marked_for_deletion(false),
352 pending_set_pixels(false),
353 set_pixels_completion_forced(false),
355 read_lock_fences_enabled(false),
356 has_shared_bitmap_id(!!bitmap
),
357 allow_overlay(false),
358 read_lock_fence(NULL
),
362 original_filter(filter
),
367 wrap_mode(wrap_mode
),
368 hint(TextureHintImmutable
),
371 shared_bitmap(bitmap
),
372 gpu_memory_buffer(NULL
) {
373 DCHECK(wrap_mode
== GL_CLAMP_TO_EDGE
|| wrap_mode
== GL_REPEAT
);
374 DCHECK(origin
== Delegated
|| pixels
);
376 shared_bitmap_id
= bitmap
->id();
379 ResourceProvider::Resource::Resource(const SharedBitmapId
& bitmap_id
,
380 const gfx::Size
& size
,
386 gl_pixel_buffer_id(0),
387 gl_upload_query_id(0),
388 gl_read_lock_query_id(0),
390 lock_for_read_count(0),
394 locked_for_write(false),
396 marked_for_deletion(false),
397 pending_set_pixels(false),
398 set_pixels_completion_forced(false),
400 read_lock_fences_enabled(false),
401 has_shared_bitmap_id(true),
402 allow_overlay(false),
403 read_lock_fence(NULL
),
407 original_filter(filter
),
412 wrap_mode(wrap_mode
),
413 hint(TextureHintImmutable
),
416 shared_bitmap_id(bitmap_id
),
418 gpu_memory_buffer(NULL
) {
419 DCHECK(wrap_mode
== GL_CLAMP_TO_EDGE
|| wrap_mode
== GL_REPEAT
);
422 ResourceProvider::Child::Child() : marked_for_deletion(false) {}
424 ResourceProvider::Child::~Child() {}
426 scoped_ptr
<ResourceProvider
> ResourceProvider::Create(
427 OutputSurface
* output_surface
,
428 SharedBitmapManager
* shared_bitmap_manager
,
429 gpu::GpuMemoryBufferManager
* gpu_memory_buffer_manager
,
430 BlockingTaskRunner
* blocking_main_thread_task_runner
,
431 int highp_threshold_min
,
432 bool use_rgba_4444_texture_format
,
433 size_t id_allocation_chunk_size
) {
434 scoped_ptr
<ResourceProvider
> resource_provider(
435 new ResourceProvider(output_surface
,
436 shared_bitmap_manager
,
437 gpu_memory_buffer_manager
,
438 blocking_main_thread_task_runner
,
440 use_rgba_4444_texture_format
,
441 id_allocation_chunk_size
));
443 if (resource_provider
->ContextGL())
444 resource_provider
->InitializeGL();
446 resource_provider
->InitializeSoftware();
448 DCHECK_NE(InvalidType
, resource_provider
->default_resource_type());
449 return resource_provider
.Pass();
452 ResourceProvider::~ResourceProvider() {
453 while (!children_
.empty())
454 DestroyChildInternal(children_
.begin(), ForShutdown
);
455 while (!resources_
.empty())
456 DeleteResourceInternal(resources_
.begin(), ForShutdown
);
461 bool ResourceProvider::InUseByConsumer(ResourceId id
) {
462 Resource
* resource
= GetResource(id
);
463 return resource
->lock_for_read_count
> 0 || resource
->exported_count
> 0 ||
467 bool ResourceProvider::IsLost(ResourceId id
) {
468 Resource
* resource
= GetResource(id
);
469 return resource
->lost
;
472 bool ResourceProvider::AllowOverlay(ResourceId id
) {
473 Resource
* resource
= GetResource(id
);
474 return resource
->allow_overlay
;
477 ResourceProvider::ResourceId
ResourceProvider::CreateResource(
478 const gfx::Size
& size
,
481 ResourceFormat format
) {
482 DCHECK(!size
.IsEmpty());
483 switch (default_resource_type_
) {
485 return CreateGLTexture(size
,
487 GL_TEXTURE_POOL_UNMANAGED_CHROMIUM
,
492 DCHECK_EQ(RGBA_8888
, format
);
493 return CreateBitmap(size
, wrap_mode
);
498 LOG(FATAL
) << "Invalid default resource type.";
502 ResourceProvider::ResourceId
ResourceProvider::CreateManagedResource(
503 const gfx::Size
& size
,
507 ResourceFormat format
) {
508 DCHECK(!size
.IsEmpty());
509 switch (default_resource_type_
) {
511 return CreateGLTexture(size
,
513 GL_TEXTURE_POOL_MANAGED_CHROMIUM
,
518 DCHECK_EQ(RGBA_8888
, format
);
519 return CreateBitmap(size
, wrap_mode
);
524 LOG(FATAL
) << "Invalid default resource type.";
528 ResourceProvider::ResourceId
ResourceProvider::CreateGLTexture(
529 const gfx::Size
& size
,
534 ResourceFormat format
) {
535 DCHECK_LE(size
.width(), max_texture_size_
);
536 DCHECK_LE(size
.height(), max_texture_size_
);
537 DCHECK(thread_checker_
.CalledOnValidThread());
539 ResourceId id
= next_id_
++;
549 resource
.allocated
= false;
550 resources_
[id
] = resource
;
554 ResourceProvider::ResourceId
ResourceProvider::CreateBitmap(
555 const gfx::Size
& size
, GLint wrap_mode
) {
556 DCHECK(thread_checker_
.CalledOnValidThread());
558 scoped_ptr
<SharedBitmap
> bitmap
=
559 shared_bitmap_manager_
->AllocateSharedBitmap(size
);
560 uint8_t* pixels
= bitmap
->pixels();
563 ResourceId id
= next_id_
++;
565 pixels
, bitmap
.release(), size
, Resource::Internal
, GL_LINEAR
, wrap_mode
);
566 resource
.allocated
= true;
567 resources_
[id
] = resource
;
571 ResourceProvider::ResourceId
ResourceProvider::CreateResourceFromIOSurface(
572 const gfx::Size
& size
,
573 unsigned io_surface_id
) {
574 DCHECK(thread_checker_
.CalledOnValidThread());
576 ResourceId id
= next_id_
++;
580 GL_TEXTURE_RECTANGLE_ARB
,
582 GL_TEXTURE_POOL_UNMANAGED_CHROMIUM
,
584 TextureHintImmutable
,
586 LazyCreate(&resource
);
587 GLES2Interface
* gl
= ContextGL();
589 gl
->BindTexture(GL_TEXTURE_RECTANGLE_ARB
, resource
.gl_id
);
590 gl
->TexImageIOSurface2DCHROMIUM(
591 GL_TEXTURE_RECTANGLE_ARB
, size
.width(), size
.height(), io_surface_id
, 0);
592 resource
.allocated
= true;
593 resources_
[id
] = resource
;
597 ResourceProvider::ResourceId
ResourceProvider::CreateResourceFromTextureMailbox(
598 const TextureMailbox
& mailbox
,
599 scoped_ptr
<SingleReleaseCallbackImpl
> release_callback_impl
) {
600 DCHECK(thread_checker_
.CalledOnValidThread());
601 // Just store the information. Mailbox will be consumed in LockForRead().
602 ResourceId id
= next_id_
++;
603 DCHECK(mailbox
.IsValid());
604 Resource
& resource
= resources_
[id
];
605 if (mailbox
.IsTexture()) {
606 resource
= Resource(0,
610 mailbox
.nearest_neighbor() ? GL_NEAREST
: GL_LINEAR
,
613 TextureHintImmutable
,
616 DCHECK(mailbox
.IsSharedMemory());
617 SharedBitmap
* shared_bitmap
= mailbox
.shared_bitmap();
618 uint8_t* pixels
= shared_bitmap
->pixels();
620 resource
= Resource(pixels
, shared_bitmap
, mailbox
.shared_memory_size(),
621 Resource::External
, GL_LINEAR
, GL_CLAMP_TO_EDGE
);
623 resource
.allocated
= true;
624 resource
.mailbox
= mailbox
;
625 resource
.release_callback_impl
=
626 base::Bind(&SingleReleaseCallbackImpl::Run
,
627 base::Owned(release_callback_impl
.release()));
628 resource
.allow_overlay
= mailbox
.allow_overlay();
632 void ResourceProvider::DeleteResource(ResourceId id
) {
633 DCHECK(thread_checker_
.CalledOnValidThread());
634 ResourceMap::iterator it
= resources_
.find(id
);
635 CHECK(it
!= resources_
.end());
636 Resource
* resource
= &it
->second
;
637 DCHECK(!resource
->marked_for_deletion
);
638 DCHECK_EQ(resource
->imported_count
, 0);
639 DCHECK(resource
->pending_set_pixels
|| !resource
->locked_for_write
);
641 if (resource
->exported_count
> 0 || resource
->lock_for_read_count
> 0) {
642 resource
->marked_for_deletion
= true;
645 DeleteResourceInternal(it
, Normal
);
649 void ResourceProvider::DeleteResourceInternal(ResourceMap::iterator it
,
651 TRACE_EVENT0("cc", "ResourceProvider::DeleteResourceInternal");
652 Resource
* resource
= &it
->second
;
653 bool lost_resource
= resource
->lost
;
655 DCHECK(resource
->exported_count
== 0 || style
!= Normal
);
656 if (style
== ForShutdown
&& resource
->exported_count
> 0)
657 lost_resource
= true;
659 if (resource
->image_id
) {
660 DCHECK(resource
->origin
== Resource::Internal
);
661 GLES2Interface
* gl
= ContextGL();
663 GLC(gl
, gl
->DestroyImageCHROMIUM(resource
->image_id
));
665 if (resource
->gl_upload_query_id
) {
666 DCHECK(resource
->origin
== Resource::Internal
);
667 GLES2Interface
* gl
= ContextGL();
669 GLC(gl
, gl
->DeleteQueriesEXT(1, &resource
->gl_upload_query_id
));
671 if (resource
->gl_read_lock_query_id
) {
672 DCHECK(resource
->origin
== Resource::Internal
);
673 GLES2Interface
* gl
= ContextGL();
675 GLC(gl
, gl
->DeleteQueriesEXT(1, &resource
->gl_read_lock_query_id
));
677 if (resource
->gl_pixel_buffer_id
) {
678 DCHECK(resource
->origin
== Resource::Internal
);
679 GLES2Interface
* gl
= ContextGL();
681 GLC(gl
, gl
->DeleteBuffers(1, &resource
->gl_pixel_buffer_id
));
683 if (resource
->origin
== Resource::External
) {
684 DCHECK(resource
->mailbox
.IsValid());
685 GLuint sync_point
= resource
->mailbox
.sync_point();
686 if (resource
->type
== GLTexture
) {
687 DCHECK(resource
->mailbox
.IsTexture());
688 lost_resource
|= lost_output_surface_
;
689 GLES2Interface
* gl
= ContextGL();
691 if (resource
->gl_id
) {
692 GLC(gl
, gl
->DeleteTextures(1, &resource
->gl_id
));
695 sync_point
= gl
->InsertSyncPointCHROMIUM();
698 DCHECK(resource
->mailbox
.IsSharedMemory());
699 resource
->shared_bitmap
= nullptr;
700 resource
->pixels
= nullptr;
702 resource
->release_callback_impl
.Run(
703 sync_point
, lost_resource
, blocking_main_thread_task_runner_
);
705 if (resource
->gl_id
) {
706 GLES2Interface
* gl
= ContextGL();
708 GLC(gl
, gl
->DeleteTextures(1, &resource
->gl_id
));
711 if (resource
->shared_bitmap
) {
712 DCHECK(resource
->origin
!= Resource::External
);
713 DCHECK_EQ(Bitmap
, resource
->type
);
714 delete resource
->shared_bitmap
;
715 resource
->pixels
= NULL
;
717 if (resource
->pixels
) {
718 DCHECK(resource
->origin
== Resource::Internal
);
719 delete[] resource
->pixels
;
720 resource
->pixels
= NULL
;
722 if (resource
->gpu_memory_buffer
) {
723 DCHECK(resource
->origin
== Resource::Internal
);
724 delete resource
->gpu_memory_buffer
;
725 resource
->gpu_memory_buffer
= NULL
;
727 resources_
.erase(it
);
730 ResourceProvider::ResourceType
ResourceProvider::GetResourceType(
732 return GetResource(id
)->type
;
735 void ResourceProvider::SetPixels(ResourceId id
,
736 const uint8_t* image
,
737 const gfx::Rect
& image_rect
,
738 const gfx::Rect
& source_rect
,
739 const gfx::Vector2d
& dest_offset
) {
740 Resource
* resource
= GetResource(id
);
741 DCHECK(!resource
->locked_for_write
);
742 DCHECK(!resource
->lock_for_read_count
);
743 DCHECK(resource
->origin
== Resource::Internal
);
744 DCHECK_EQ(resource
->exported_count
, 0);
745 DCHECK(ReadLockFenceHasPassed(resource
));
746 LazyAllocate(resource
);
748 if (resource
->type
== GLTexture
) {
749 DCHECK(resource
->gl_id
);
750 DCHECK(!resource
->pending_set_pixels
);
751 DCHECK_EQ(resource
->target
, static_cast<GLenum
>(GL_TEXTURE_2D
));
752 GLES2Interface
* gl
= ContextGL();
754 DCHECK(texture_uploader_
.get());
755 gl
->BindTexture(GL_TEXTURE_2D
, resource
->gl_id
);
756 texture_uploader_
->Upload(image
,
763 DCHECK_EQ(Bitmap
, resource
->type
);
764 DCHECK(resource
->allocated
);
765 DCHECK_EQ(RGBA_8888
, resource
->format
);
766 DCHECK(source_rect
.x() >= image_rect
.x());
767 DCHECK(source_rect
.y() >= image_rect
.y());
768 DCHECK(source_rect
.right() <= image_rect
.right());
769 DCHECK(source_rect
.bottom() <= image_rect
.bottom());
770 SkImageInfo source_info
=
771 SkImageInfo::MakeN32Premul(source_rect
.width(), source_rect
.height());
772 size_t image_row_bytes
= image_rect
.width() * 4;
773 gfx::Vector2d source_offset
= source_rect
.origin() - image_rect
.origin();
774 image
+= source_offset
.y() * image_row_bytes
+ source_offset
.x() * 4;
776 ScopedWriteLockSoftware
lock(this, id
);
777 SkCanvas
dest(lock
.sk_bitmap());
778 dest
.writePixels(source_info
, image
, image_row_bytes
, dest_offset
.x(),
783 size_t ResourceProvider::NumBlockingUploads() {
784 if (!texture_uploader_
)
787 return texture_uploader_
->NumBlockingUploads();
790 void ResourceProvider::MarkPendingUploadsAsNonBlocking() {
791 if (!texture_uploader_
)
794 texture_uploader_
->MarkPendingUploadsAsNonBlocking();
797 size_t ResourceProvider::EstimatedUploadsPerTick() {
798 if (!texture_uploader_
)
801 double textures_per_second
= texture_uploader_
->EstimatedTexturesPerSecond();
802 size_t textures_per_tick
= floor(
803 kTextureUploadTickRate
* textures_per_second
);
804 return textures_per_tick
? textures_per_tick
: 1u;
807 void ResourceProvider::FlushUploads() {
808 if (!texture_uploader_
)
811 texture_uploader_
->Flush();
814 void ResourceProvider::ReleaseCachedData() {
815 if (!texture_uploader_
)
818 texture_uploader_
->ReleaseCachedQueries();
821 base::TimeTicks
ResourceProvider::EstimatedUploadCompletionTime(
822 size_t uploads_per_tick
) {
823 if (lost_output_surface_
)
824 return base::TimeTicks();
826 // Software resource uploads happen on impl thread, so don't bother batching
827 // them up and trying to wait for them to complete.
828 if (!texture_uploader_
) {
829 return gfx::FrameTime::Now() + base::TimeDelta::FromMicroseconds(
830 base::Time::kMicrosecondsPerSecond
* kSoftwareUploadTickRate
);
833 base::TimeDelta upload_one_texture_time
=
834 base::TimeDelta::FromMicroseconds(
835 base::Time::kMicrosecondsPerSecond
* kTextureUploadTickRate
) /
838 size_t total_uploads
= NumBlockingUploads() + uploads_per_tick
;
839 return gfx::FrameTime::Now() + upload_one_texture_time
* total_uploads
;
842 ResourceProvider::Resource
* ResourceProvider::GetResource(ResourceId id
) {
843 DCHECK(thread_checker_
.CalledOnValidThread());
844 ResourceMap::iterator it
= resources_
.find(id
);
845 CHECK(it
!= resources_
.end());
849 const ResourceProvider::Resource
* ResourceProvider::LockForRead(ResourceId id
) {
850 Resource
* resource
= GetResource(id
);
851 DCHECK(!resource
->locked_for_write
||
852 resource
->set_pixels_completion_forced
) <<
853 "locked for write: " << resource
->locked_for_write
<<
854 " pixels completion forced: " << resource
->set_pixels_completion_forced
;
855 DCHECK_EQ(resource
->exported_count
, 0);
856 // Uninitialized! Call SetPixels or LockForWrite first.
857 DCHECK(resource
->allocated
);
859 LazyCreate(resource
);
861 if (resource
->type
== GLTexture
&& !resource
->gl_id
) {
862 DCHECK(resource
->origin
!= Resource::Internal
);
863 DCHECK(resource
->mailbox
.IsTexture());
865 // Mailbox sync_points must be processed by a call to
866 // WaitSyncPointIfNeeded() prior to calling LockForRead().
867 DCHECK(!resource
->mailbox
.sync_point());
869 GLES2Interface
* gl
= ContextGL();
871 resource
->gl_id
= texture_id_allocator_
->NextId();
872 GLC(gl
, gl
->BindTexture(resource
->target
, resource
->gl_id
));
874 gl
->ConsumeTextureCHROMIUM(resource
->mailbox
.target(),
875 resource
->mailbox
.name()));
878 if (!resource
->pixels
&& resource
->has_shared_bitmap_id
&&
879 shared_bitmap_manager_
) {
880 scoped_ptr
<SharedBitmap
> bitmap
=
881 shared_bitmap_manager_
->GetSharedBitmapFromId(
882 resource
->size
, resource
->shared_bitmap_id
);
884 resource
->shared_bitmap
= bitmap
.release();
885 resource
->pixels
= resource
->shared_bitmap
->pixels();
889 resource
->lock_for_read_count
++;
890 if (resource
->read_lock_fences_enabled
) {
891 if (current_read_lock_fence_
.get())
892 current_read_lock_fence_
->Set();
893 resource
->read_lock_fence
= current_read_lock_fence_
;
899 void ResourceProvider::UnlockForRead(ResourceId id
) {
900 DCHECK(thread_checker_
.CalledOnValidThread());
901 ResourceMap::iterator it
= resources_
.find(id
);
902 CHECK(it
!= resources_
.end());
904 Resource
* resource
= &it
->second
;
905 DCHECK_GT(resource
->lock_for_read_count
, 0);
906 DCHECK_EQ(resource
->exported_count
, 0);
907 resource
->lock_for_read_count
--;
908 if (resource
->marked_for_deletion
&& !resource
->lock_for_read_count
) {
909 if (!resource
->child_id
) {
910 // The resource belongs to this ResourceProvider, so it can be destroyed.
911 DeleteResourceInternal(it
, Normal
);
913 ChildMap::iterator child_it
= children_
.find(resource
->child_id
);
914 ResourceIdArray unused
;
915 unused
.push_back(id
);
916 DeleteAndReturnUnusedResourcesToChild(child_it
, Normal
, unused
);
921 ResourceProvider::Resource
* ResourceProvider::LockForWrite(ResourceId id
) {
922 Resource
* resource
= GetResource(id
);
923 DCHECK(CanLockForWrite(id
));
925 resource
->locked_for_write
= true;
929 bool ResourceProvider::CanLockForWrite(ResourceId id
) {
930 Resource
* resource
= GetResource(id
);
931 return !resource
->locked_for_write
&& !resource
->lock_for_read_count
&&
932 !resource
->exported_count
&& resource
->origin
== Resource::Internal
&&
933 !resource
->lost
&& ReadLockFenceHasPassed(resource
);
936 void ResourceProvider::UnlockForWrite(ResourceProvider::Resource
* resource
) {
937 DCHECK(resource
->locked_for_write
);
938 DCHECK_EQ(resource
->exported_count
, 0);
939 DCHECK(resource
->origin
== Resource::Internal
);
940 resource
->locked_for_write
= false;
943 ResourceProvider::ScopedReadLockGL::ScopedReadLockGL(
944 ResourceProvider
* resource_provider
,
945 ResourceProvider::ResourceId resource_id
)
946 : resource_provider_(resource_provider
),
947 resource_id_(resource_id
),
948 texture_id_(resource_provider
->LockForRead(resource_id
)->gl_id
) {
952 ResourceProvider::ScopedReadLockGL::~ScopedReadLockGL() {
953 resource_provider_
->UnlockForRead(resource_id_
);
956 ResourceProvider::ScopedSamplerGL::ScopedSamplerGL(
957 ResourceProvider
* resource_provider
,
958 ResourceProvider::ResourceId resource_id
,
960 : ScopedReadLockGL(resource_provider
, resource_id
),
962 target_(resource_provider
->BindForSampling(resource_id
, unit_
, filter
)) {
965 ResourceProvider::ScopedSamplerGL::ScopedSamplerGL(
966 ResourceProvider
* resource_provider
,
967 ResourceProvider::ResourceId resource_id
,
970 : ScopedReadLockGL(resource_provider
, resource_id
),
972 target_(resource_provider
->BindForSampling(resource_id
, unit_
, filter
)) {
975 ResourceProvider::ScopedSamplerGL::~ScopedSamplerGL() {
978 ResourceProvider::ScopedWriteLockGL::ScopedWriteLockGL(
979 ResourceProvider
* resource_provider
,
980 ResourceProvider::ResourceId resource_id
)
981 : resource_provider_(resource_provider
),
982 resource_(resource_provider
->LockForWrite(resource_id
)) {
983 resource_provider_
->LazyAllocate(resource_
);
984 texture_id_
= resource_
->gl_id
;
988 ResourceProvider::ScopedWriteLockGL::~ScopedWriteLockGL() {
989 resource_provider_
->UnlockForWrite(resource_
);
992 void ResourceProvider::PopulateSkBitmapWithResource(
993 SkBitmap
* sk_bitmap
, const Resource
* resource
) {
994 DCHECK_EQ(RGBA_8888
, resource
->format
);
995 SkImageInfo info
= SkImageInfo::MakeN32Premul(resource
->size
.width(),
996 resource
->size
.height());
997 sk_bitmap
->installPixels(info
, resource
->pixels
, info
.minRowBytes());
1000 ResourceProvider::ScopedReadLockSoftware::ScopedReadLockSoftware(
1001 ResourceProvider
* resource_provider
,
1002 ResourceProvider::ResourceId resource_id
)
1003 : resource_provider_(resource_provider
),
1004 resource_id_(resource_id
) {
1005 const Resource
* resource
= resource_provider
->LockForRead(resource_id
);
1006 wrap_mode_
= resource
->wrap_mode
;
1007 ResourceProvider::PopulateSkBitmapWithResource(&sk_bitmap_
, resource
);
1010 ResourceProvider::ScopedReadLockSoftware::~ScopedReadLockSoftware() {
1011 resource_provider_
->UnlockForRead(resource_id_
);
1014 ResourceProvider::ScopedWriteLockSoftware::ScopedWriteLockSoftware(
1015 ResourceProvider
* resource_provider
,
1016 ResourceProvider::ResourceId resource_id
)
1017 : resource_provider_(resource_provider
),
1018 resource_(resource_provider
->LockForWrite(resource_id
)) {
1019 ResourceProvider::PopulateSkBitmapWithResource(&sk_bitmap_
, resource_
);
1023 ResourceProvider::ScopedWriteLockSoftware::~ScopedWriteLockSoftware() {
1024 DCHECK(thread_checker_
.CalledOnValidThread());
1025 resource_provider_
->UnlockForWrite(resource_
);
1028 ResourceProvider::ScopedWriteLockGpuMemoryBuffer::
1029 ScopedWriteLockGpuMemoryBuffer(ResourceProvider
* resource_provider
,
1030 ResourceProvider::ResourceId resource_id
)
1031 : resource_provider_(resource_provider
),
1032 resource_(resource_provider
->LockForWrite(resource_id
)),
1033 gpu_memory_buffer_manager_(resource_provider
->gpu_memory_buffer_manager_
),
1034 gpu_memory_buffer_(nullptr),
1035 size_(resource_
->size
),
1036 format_(resource_
->format
) {
1037 DCHECK_EQ(GLTexture
, resource_
->type
);
1038 std::swap(gpu_memory_buffer_
, resource_
->gpu_memory_buffer
);
1041 ResourceProvider::ScopedWriteLockGpuMemoryBuffer::
1042 ~ScopedWriteLockGpuMemoryBuffer() {
1043 DCHECK(thread_checker_
.CalledOnValidThread());
1044 resource_provider_
->UnlockForWrite(resource_
);
1045 if (!gpu_memory_buffer_
)
1048 if (!resource_
->image_id
) {
1049 GLES2Interface
* gl
= resource_provider_
->ContextGL();
1052 #if defined(OS_CHROMEOS)
1053 // TODO(reveman): GL_COMMANDS_ISSUED_CHROMIUM is used for synchronization
1054 // on ChromeOS to avoid some performance issues. This only works with
1055 // shared memory backed buffers. crbug.com/436314
1056 DCHECK_EQ(gpu_memory_buffer_
->GetHandle().type
, gfx::SHARED_MEMORY_BUFFER
);
1059 resource_
->image_id
=
1060 gl
->CreateImageCHROMIUM(gpu_memory_buffer_
->AsClientBuffer(),
1066 std::swap(resource_
->gpu_memory_buffer
, gpu_memory_buffer_
);
1067 resource_
->allocated
= true;
1068 resource_
->dirty_image
= true;
1070 // GpuMemoryBuffer provides direct access to the memory used by the GPU.
1071 // Read lock fences are required to ensure that we're not trying to map a
1072 // buffer that is currently in-use by the GPU.
1073 resource_
->read_lock_fences_enabled
= true;
1076 gfx::GpuMemoryBuffer
*
1077 ResourceProvider::ScopedWriteLockGpuMemoryBuffer::GetGpuMemoryBuffer() {
1078 if (!gpu_memory_buffer_
) {
1079 scoped_ptr
<gfx::GpuMemoryBuffer
> gpu_memory_buffer
=
1080 gpu_memory_buffer_manager_
->AllocateGpuMemoryBuffer(
1081 size_
, ToGpuMemoryBufferFormat(format_
), gfx::GpuMemoryBuffer::MAP
);
1082 gpu_memory_buffer_
= gpu_memory_buffer
.release();
1085 return gpu_memory_buffer_
;
1088 ResourceProvider::ScopedWriteLockGr::ScopedWriteLockGr(
1089 ResourceProvider
* resource_provider
,
1090 ResourceProvider::ResourceId resource_id
,
1091 bool use_distance_field_text
,
1092 bool can_use_lcd_text
,
1093 int msaa_sample_count
)
1094 : resource_provider_(resource_provider
),
1095 resource_(resource_provider
->LockForWrite(resource_id
)) {
1096 // Create the sk_surface.
1097 DCHECK(thread_checker_
.CalledOnValidThread());
1098 DCHECK(resource_
->locked_for_write
);
1100 resource_provider_
->LazyAllocate(resource_
);
1102 GrBackendTextureDesc desc
;
1103 desc
.fFlags
= kRenderTarget_GrBackendTextureFlag
;
1104 desc
.fWidth
= resource_
->size
.width();
1105 desc
.fHeight
= resource_
->size
.height();
1106 desc
.fConfig
= ToGrPixelConfig(resource_
->format
);
1107 desc
.fOrigin
= kTopLeft_GrSurfaceOrigin
;
1108 desc
.fTextureHandle
= resource_
->gl_id
;
1109 desc
.fSampleCnt
= msaa_sample_count
;
1111 class GrContext
* gr_context
= resource_provider_
->GrContext();
1112 skia::RefPtr
<GrTexture
> gr_texture
=
1113 skia::AdoptRef(gr_context
->wrapBackendTexture(desc
));
1115 uint32_t flags
= use_distance_field_text
1116 ? SkSurfaceProps::kUseDistanceFieldFonts_Flag
1118 // Use unknown pixel geometry to disable LCD text.
1119 SkSurfaceProps
surface_props(flags
, kUnknown_SkPixelGeometry
);
1120 if (can_use_lcd_text
) {
1121 // LegacyFontHost will get LCD text and skia figures out what type to use.
1123 SkSurfaceProps(flags
, SkSurfaceProps::kLegacyFontHost_InitType
);
1125 sk_surface_
= skia::AdoptRef(SkSurface::NewRenderTargetDirect(
1126 gr_texture
->asRenderTarget(), &surface_props
));
1130 ResourceProvider::ScopedWriteLockGr::~ScopedWriteLockGr() {
1131 DCHECK(thread_checker_
.CalledOnValidThread());
1132 resource_provider_
->UnlockForWrite(resource_
);
1135 ResourceProvider::SynchronousFence::SynchronousFence(
1136 gpu::gles2::GLES2Interface
* gl
)
1137 : gl_(gl
), has_synchronized_(true) {
1140 ResourceProvider::SynchronousFence::~SynchronousFence() {
1143 void ResourceProvider::SynchronousFence::Set() {
1144 has_synchronized_
= false;
1147 bool ResourceProvider::SynchronousFence::HasPassed() {
1148 if (!has_synchronized_
) {
1149 has_synchronized_
= true;
1155 void ResourceProvider::SynchronousFence::Wait() {
1159 void ResourceProvider::SynchronousFence::Synchronize() {
1160 TRACE_EVENT0("cc", "ResourceProvider::SynchronousFence::Synchronize");
1164 ResourceProvider::ResourceProvider(
1165 OutputSurface
* output_surface
,
1166 SharedBitmapManager
* shared_bitmap_manager
,
1167 gpu::GpuMemoryBufferManager
* gpu_memory_buffer_manager
,
1168 BlockingTaskRunner
* blocking_main_thread_task_runner
,
1169 int highp_threshold_min
,
1170 bool use_rgba_4444_texture_format
,
1171 size_t id_allocation_chunk_size
)
1172 : output_surface_(output_surface
),
1173 shared_bitmap_manager_(shared_bitmap_manager
),
1174 gpu_memory_buffer_manager_(gpu_memory_buffer_manager
),
1175 blocking_main_thread_task_runner_(blocking_main_thread_task_runner
),
1176 lost_output_surface_(false),
1177 highp_threshold_min_(highp_threshold_min
),
1180 default_resource_type_(InvalidType
),
1181 use_texture_storage_ext_(false),
1182 use_texture_format_bgra_(false),
1183 use_texture_usage_hint_(false),
1184 use_compressed_texture_etc1_(false),
1185 yuv_resource_format_(LUMINANCE_8
),
1186 max_texture_size_(0),
1187 best_texture_format_(RGBA_8888
),
1188 use_rgba_4444_texture_format_(use_rgba_4444_texture_format
),
1189 id_allocation_chunk_size_(id_allocation_chunk_size
),
1190 use_sync_query_(false) {
1191 DCHECK(output_surface_
->HasClient());
1192 DCHECK(id_allocation_chunk_size_
);
1195 void ResourceProvider::InitializeSoftware() {
1196 DCHECK(thread_checker_
.CalledOnValidThread());
1197 DCHECK_NE(Bitmap
, default_resource_type_
);
1199 CleanUpGLIfNeeded();
1201 default_resource_type_
= Bitmap
;
1202 // Pick an arbitrary limit here similar to what hardware might.
1203 max_texture_size_
= 16 * 1024;
1204 best_texture_format_
= RGBA_8888
;
1207 void ResourceProvider::InitializeGL() {
1208 DCHECK(thread_checker_
.CalledOnValidThread());
1209 DCHECK(!texture_uploader_
);
1210 DCHECK_NE(GLTexture
, default_resource_type_
);
1211 DCHECK(!texture_id_allocator_
);
1212 DCHECK(!buffer_id_allocator_
);
1214 default_resource_type_
= GLTexture
;
1216 const ContextProvider::Capabilities
& caps
=
1217 output_surface_
->context_provider()->ContextCapabilities();
1219 bool use_bgra
= caps
.gpu
.texture_format_bgra8888
;
1220 use_texture_storage_ext_
= caps
.gpu
.texture_storage
;
1221 use_texture_format_bgra_
= caps
.gpu
.texture_format_bgra8888
;
1222 use_texture_usage_hint_
= caps
.gpu
.texture_usage
;
1223 use_compressed_texture_etc1_
= caps
.gpu
.texture_format_etc1
;
1224 yuv_resource_format_
= caps
.gpu
.texture_rg
? RED_8
: LUMINANCE_8
;
1225 use_sync_query_
= caps
.gpu
.sync_query
;
1227 GLES2Interface
* gl
= ContextGL();
1230 texture_uploader_
= TextureUploader::Create(gl
);
1231 max_texture_size_
= 0; // Context expects cleared value.
1232 GLC(gl
, gl
->GetIntegerv(GL_MAX_TEXTURE_SIZE
, &max_texture_size_
));
1233 best_texture_format_
= PlatformColor::BestTextureFormat(use_bgra
);
1235 texture_id_allocator_
.reset(
1236 new TextureIdAllocator(gl
, id_allocation_chunk_size_
));
1237 buffer_id_allocator_
.reset(
1238 new BufferIdAllocator(gl
, id_allocation_chunk_size_
));
1241 void ResourceProvider::CleanUpGLIfNeeded() {
1242 GLES2Interface
* gl
= ContextGL();
1243 if (default_resource_type_
!= GLTexture
) {
1244 // We are not in GL mode, but double check before returning.
1246 DCHECK(!texture_uploader_
);
1252 // Check that all GL resources has been deleted.
1253 for (ResourceMap::const_iterator itr
= resources_
.begin();
1254 itr
!= resources_
.end();
1256 DCHECK_NE(GLTexture
, itr
->second
.type
);
1258 #endif // DCHECK_IS_ON()
1260 texture_uploader_
= nullptr;
1261 texture_id_allocator_
= nullptr;
1262 buffer_id_allocator_
= nullptr;
1266 int ResourceProvider::CreateChild(const ReturnCallback
& return_callback
) {
1267 DCHECK(thread_checker_
.CalledOnValidThread());
1270 child_info
.return_callback
= return_callback
;
1272 int child
= next_child_
++;
1273 children_
[child
] = child_info
;
1277 void ResourceProvider::DestroyChild(int child_id
) {
1278 ChildMap::iterator it
= children_
.find(child_id
);
1279 DCHECK(it
!= children_
.end());
1280 DestroyChildInternal(it
, Normal
);
1283 void ResourceProvider::DestroyChildInternal(ChildMap::iterator it
,
1284 DeleteStyle style
) {
1285 DCHECK(thread_checker_
.CalledOnValidThread());
1287 Child
& child
= it
->second
;
1288 DCHECK(style
== ForShutdown
|| !child
.marked_for_deletion
);
1290 ResourceIdArray resources_for_child
;
1292 for (ResourceIdMap::iterator child_it
= child
.child_to_parent_map
.begin();
1293 child_it
!= child
.child_to_parent_map
.end();
1295 ResourceId id
= child_it
->second
;
1296 resources_for_child
.push_back(id
);
1299 // If the child is going away, don't consider any resources in use.
1300 child
.in_use_resources
.clear();
1301 child
.marked_for_deletion
= true;
1303 DeleteAndReturnUnusedResourcesToChild(it
, style
, resources_for_child
);
1306 const ResourceProvider::ResourceIdMap
& ResourceProvider::GetChildToParentMap(
1308 DCHECK(thread_checker_
.CalledOnValidThread());
1309 ChildMap::const_iterator it
= children_
.find(child
);
1310 DCHECK(it
!= children_
.end());
1311 DCHECK(!it
->second
.marked_for_deletion
);
1312 return it
->second
.child_to_parent_map
;
1315 void ResourceProvider::PrepareSendToParent(const ResourceIdArray
& resources
,
1316 TransferableResourceArray
* list
) {
1317 DCHECK(thread_checker_
.CalledOnValidThread());
1318 GLES2Interface
* gl
= ContextGL();
1319 bool need_sync_point
= false;
1320 for (ResourceIdArray::const_iterator it
= resources
.begin();
1321 it
!= resources
.end();
1323 TransferableResource resource
;
1324 TransferResource(gl
, *it
, &resource
);
1325 if (!resource
.mailbox_holder
.sync_point
&& !resource
.is_software
)
1326 need_sync_point
= true;
1327 ++resources_
.find(*it
)->second
.exported_count
;
1328 list
->push_back(resource
);
1330 if (need_sync_point
) {
1331 GLuint sync_point
= gl
->InsertSyncPointCHROMIUM();
1332 for (TransferableResourceArray::iterator it
= list
->begin();
1335 if (!it
->mailbox_holder
.sync_point
)
1336 it
->mailbox_holder
.sync_point
= sync_point
;
1341 void ResourceProvider::ReceiveFromChild(
1342 int child
, const TransferableResourceArray
& resources
) {
1343 DCHECK(thread_checker_
.CalledOnValidThread());
1344 GLES2Interface
* gl
= ContextGL();
1345 Child
& child_info
= children_
.find(child
)->second
;
1346 DCHECK(!child_info
.marked_for_deletion
);
1347 for (TransferableResourceArray::const_iterator it
= resources
.begin();
1348 it
!= resources
.end();
1350 ResourceIdMap::iterator resource_in_map_it
=
1351 child_info
.child_to_parent_map
.find(it
->id
);
1352 if (resource_in_map_it
!= child_info
.child_to_parent_map
.end()) {
1353 Resource
& resource
= resources_
[resource_in_map_it
->second
];
1354 resource
.marked_for_deletion
= false;
1355 resource
.imported_count
++;
1359 if ((!it
->is_software
&& !gl
) ||
1360 (it
->is_software
&& !shared_bitmap_manager_
)) {
1361 TRACE_EVENT0("cc", "ResourceProvider::ReceiveFromChild dropping invalid");
1362 ReturnedResourceArray to_return
;
1363 to_return
.push_back(it
->ToReturnedResource());
1364 child_info
.return_callback
.Run(to_return
,
1365 blocking_main_thread_task_runner_
);
1369 ResourceId local_id
= next_id_
++;
1370 Resource
& resource
= resources_
[local_id
];
1371 if (it
->is_software
) {
1372 resource
= Resource(it
->mailbox_holder
.mailbox
,
1374 Resource::Delegated
,
1376 it
->is_repeated
? GL_REPEAT
: GL_CLAMP_TO_EDGE
);
1378 resource
= Resource(0,
1380 Resource::Delegated
,
1381 it
->mailbox_holder
.texture_target
,
1384 it
->is_repeated
? GL_REPEAT
: GL_CLAMP_TO_EDGE
,
1385 TextureHintImmutable
,
1387 resource
.mailbox
= TextureMailbox(it
->mailbox_holder
.mailbox
,
1388 it
->mailbox_holder
.texture_target
,
1389 it
->mailbox_holder
.sync_point
);
1391 resource
.child_id
= child
;
1392 // Don't allocate a texture for a child.
1393 resource
.allocated
= true;
1394 resource
.imported_count
= 1;
1395 resource
.allow_overlay
= it
->allow_overlay
;
1396 child_info
.parent_to_child_map
[local_id
] = it
->id
;
1397 child_info
.child_to_parent_map
[it
->id
] = local_id
;
1401 void ResourceProvider::DeclareUsedResourcesFromChild(
1403 const ResourceIdArray
& resources_from_child
) {
1404 DCHECK(thread_checker_
.CalledOnValidThread());
1406 ChildMap::iterator child_it
= children_
.find(child
);
1407 DCHECK(child_it
!= children_
.end());
1408 Child
& child_info
= child_it
->second
;
1409 DCHECK(!child_info
.marked_for_deletion
);
1410 child_info
.in_use_resources
.clear();
1412 for (size_t i
= 0; i
< resources_from_child
.size(); ++i
) {
1413 ResourceIdMap::iterator it
=
1414 child_info
.child_to_parent_map
.find(resources_from_child
[i
]);
1415 DCHECK(it
!= child_info
.child_to_parent_map
.end());
1417 ResourceId local_id
= it
->second
;
1418 DCHECK(!resources_
[local_id
].marked_for_deletion
);
1419 child_info
.in_use_resources
.insert(local_id
);
1422 ResourceIdArray unused
;
1423 for (ResourceIdMap::iterator it
= child_info
.child_to_parent_map
.begin();
1424 it
!= child_info
.child_to_parent_map
.end();
1426 ResourceId local_id
= it
->second
;
1427 bool resource_is_in_use
= child_info
.in_use_resources
.count(local_id
) > 0;
1428 if (!resource_is_in_use
)
1429 unused
.push_back(local_id
);
1431 DeleteAndReturnUnusedResourcesToChild(child_it
, Normal
, unused
);
1435 bool ResourceProvider::CompareResourceMapIteratorsByChildId(
1436 const std::pair
<ReturnedResource
, ResourceMap::iterator
>& a
,
1437 const std::pair
<ReturnedResource
, ResourceMap::iterator
>& b
) {
1438 const ResourceMap::iterator
& a_it
= a
.second
;
1439 const ResourceMap::iterator
& b_it
= b
.second
;
1440 const Resource
& a_resource
= a_it
->second
;
1441 const Resource
& b_resource
= b_it
->second
;
1442 return a_resource
.child_id
< b_resource
.child_id
;
1445 void ResourceProvider::ReceiveReturnsFromParent(
1446 const ReturnedResourceArray
& resources
) {
1447 DCHECK(thread_checker_
.CalledOnValidThread());
1448 GLES2Interface
* gl
= ContextGL();
1451 ResourceIdArray resources_for_child
;
1453 std::vector
<std::pair
<ReturnedResource
, ResourceMap::iterator
>>
1456 for (ReturnedResourceArray::const_iterator it
= resources
.begin();
1457 it
!= resources
.end();
1459 ResourceId local_id
= it
->id
;
1460 ResourceMap::iterator map_iterator
= resources_
.find(local_id
);
1462 // Resource was already lost (e.g. it belonged to a child that was
1464 if (map_iterator
== resources_
.end())
1467 sorted_resources
.push_back(
1468 std::pair
<ReturnedResource
, ResourceMap::iterator
>(*it
, map_iterator
));
1471 std::sort(sorted_resources
.begin(),
1472 sorted_resources
.end(),
1473 CompareResourceMapIteratorsByChildId
);
1475 ChildMap::iterator child_it
= children_
.end();
1476 for (size_t i
= 0; i
< sorted_resources
.size(); ++i
) {
1477 ReturnedResource
& returned
= sorted_resources
[i
].first
;
1478 ResourceMap::iterator
& map_iterator
= sorted_resources
[i
].second
;
1479 ResourceId local_id
= map_iterator
->first
;
1480 Resource
* resource
= &map_iterator
->second
;
1482 CHECK_GE(resource
->exported_count
, returned
.count
);
1483 resource
->exported_count
-= returned
.count
;
1484 resource
->lost
|= returned
.lost
;
1485 if (resource
->exported_count
)
1488 // Need to wait for the current read lock fence to pass before we can
1489 // recycle this resource.
1490 if (resource
->read_lock_fences_enabled
) {
1491 if (current_read_lock_fence_
.get())
1492 current_read_lock_fence_
->Set();
1493 resource
->read_lock_fence
= current_read_lock_fence_
;
1496 if (returned
.sync_point
) {
1497 DCHECK(!resource
->has_shared_bitmap_id
);
1498 if (resource
->origin
== Resource::Internal
) {
1499 DCHECK(resource
->gl_id
);
1500 GLC(gl
, gl
->WaitSyncPointCHROMIUM(returned
.sync_point
));
1502 DCHECK(!resource
->gl_id
);
1503 resource
->mailbox
.set_sync_point(returned
.sync_point
);
1507 if (!resource
->marked_for_deletion
)
1510 if (!resource
->child_id
) {
1511 // The resource belongs to this ResourceProvider, so it can be destroyed.
1512 DeleteResourceInternal(map_iterator
, Normal
);
1516 DCHECK(resource
->origin
== Resource::Delegated
);
1517 // Delete the resource and return it to the child it came from one.
1518 if (resource
->child_id
!= child_id
) {
1520 DCHECK_NE(resources_for_child
.size(), 0u);
1521 DCHECK(child_it
!= children_
.end());
1522 DeleteAndReturnUnusedResourcesToChild(
1523 child_it
, Normal
, resources_for_child
);
1524 resources_for_child
.clear();
1527 child_it
= children_
.find(resource
->child_id
);
1528 DCHECK(child_it
!= children_
.end());
1529 child_id
= resource
->child_id
;
1531 resources_for_child
.push_back(local_id
);
1535 DCHECK_NE(resources_for_child
.size(), 0u);
1536 DCHECK(child_it
!= children_
.end());
1537 DeleteAndReturnUnusedResourcesToChild(
1538 child_it
, Normal
, resources_for_child
);
1542 void ResourceProvider::TransferResource(GLES2Interface
* gl
,
1544 TransferableResource
* resource
) {
1545 Resource
* source
= GetResource(id
);
1546 DCHECK(!source
->locked_for_write
);
1547 DCHECK(!source
->lock_for_read_count
);
1548 DCHECK(source
->origin
!= Resource::External
|| source
->mailbox
.IsValid());
1549 DCHECK(source
->allocated
);
1551 resource
->format
= source
->format
;
1552 resource
->mailbox_holder
.texture_target
= source
->target
;
1553 resource
->filter
= source
->filter
;
1554 resource
->size
= source
->size
;
1555 resource
->is_repeated
= (source
->wrap_mode
== GL_REPEAT
);
1556 resource
->allow_overlay
= source
->allow_overlay
;
1558 if (source
->type
== Bitmap
) {
1559 resource
->mailbox_holder
.mailbox
= source
->shared_bitmap_id
;
1560 resource
->is_software
= true;
1561 } else if (!source
->mailbox
.IsValid()) {
1563 DCHECK(source
->gl_id
);
1564 DCHECK(source
->origin
== Resource::Internal
);
1566 gl
->BindTexture(resource
->mailbox_holder
.texture_target
,
1568 if (source
->image_id
) {
1569 DCHECK(source
->dirty_image
);
1570 BindImageForSampling(source
);
1572 // This is a resource allocated by the compositor, we need to produce it.
1573 // Don't set a sync point, the caller will do it.
1574 GLC(gl
, gl
->GenMailboxCHROMIUM(resource
->mailbox_holder
.mailbox
.name
));
1576 gl
->ProduceTextureCHROMIUM(resource
->mailbox_holder
.texture_target
,
1577 resource
->mailbox_holder
.mailbox
.name
));
1578 source
->mailbox
= TextureMailbox(resource
->mailbox_holder
);
1580 DCHECK(source
->mailbox
.IsTexture());
1581 if (source
->image_id
&& source
->dirty_image
) {
1582 DCHECK(source
->gl_id
);
1583 DCHECK(source
->origin
== Resource::Internal
);
1585 gl
->BindTexture(resource
->mailbox_holder
.texture_target
,
1587 BindImageForSampling(source
);
1589 // This is either an external resource, or a compositor resource that we
1590 // already exported. Make sure to forward the sync point that we were given.
1591 resource
->mailbox_holder
.mailbox
= source
->mailbox
.mailbox();
1592 resource
->mailbox_holder
.texture_target
= source
->mailbox
.target();
1593 resource
->mailbox_holder
.sync_point
= source
->mailbox
.sync_point();
1594 source
->mailbox
.set_sync_point(0);
1598 void ResourceProvider::DeleteAndReturnUnusedResourcesToChild(
1599 ChildMap::iterator child_it
,
1601 const ResourceIdArray
& unused
) {
1602 DCHECK(thread_checker_
.CalledOnValidThread());
1603 DCHECK(child_it
!= children_
.end());
1604 Child
* child_info
= &child_it
->second
;
1606 if (unused
.empty() && !child_info
->marked_for_deletion
)
1609 ReturnedResourceArray to_return
;
1611 GLES2Interface
* gl
= ContextGL();
1612 bool need_sync_point
= false;
1613 for (size_t i
= 0; i
< unused
.size(); ++i
) {
1614 ResourceId local_id
= unused
[i
];
1616 ResourceMap::iterator it
= resources_
.find(local_id
);
1617 CHECK(it
!= resources_
.end());
1618 Resource
& resource
= it
->second
;
1620 DCHECK(!resource
.locked_for_write
);
1621 DCHECK_EQ(0u, child_info
->in_use_resources
.count(local_id
));
1622 DCHECK(child_info
->parent_to_child_map
.count(local_id
));
1624 ResourceId child_id
= child_info
->parent_to_child_map
[local_id
];
1625 DCHECK(child_info
->child_to_parent_map
.count(child_id
));
1628 resource
.lost
|| (resource
.type
== GLTexture
&& lost_output_surface_
);
1629 if (resource
.exported_count
> 0 || resource
.lock_for_read_count
> 0) {
1630 if (style
!= ForShutdown
) {
1631 // Defer this until we receive the resource back from the parent or
1632 // the read lock is released.
1633 resource
.marked_for_deletion
= true;
1637 // We still have an exported_count, so we'll have to lose it.
1641 if (gl
&& resource
.filter
!= resource
.original_filter
) {
1642 DCHECK(resource
.target
);
1643 DCHECK(resource
.gl_id
);
1645 GLC(gl
, gl
->BindTexture(resource
.target
, resource
.gl_id
));
1647 gl
->TexParameteri(resource
.target
,
1648 GL_TEXTURE_MIN_FILTER
,
1649 resource
.original_filter
));
1651 gl
->TexParameteri(resource
.target
,
1652 GL_TEXTURE_MAG_FILTER
,
1653 resource
.original_filter
));
1656 ReturnedResource returned
;
1657 returned
.id
= child_id
;
1658 returned
.sync_point
= resource
.mailbox
.sync_point();
1659 if (!returned
.sync_point
&& resource
.type
== GLTexture
)
1660 need_sync_point
= true;
1661 returned
.count
= resource
.imported_count
;
1662 returned
.lost
= is_lost
;
1663 to_return
.push_back(returned
);
1665 child_info
->parent_to_child_map
.erase(local_id
);
1666 child_info
->child_to_parent_map
.erase(child_id
);
1667 resource
.imported_count
= 0;
1668 DeleteResourceInternal(it
, style
);
1670 if (need_sync_point
) {
1672 GLuint sync_point
= gl
->InsertSyncPointCHROMIUM();
1673 for (size_t i
= 0; i
< to_return
.size(); ++i
) {
1674 if (!to_return
[i
].sync_point
)
1675 to_return
[i
].sync_point
= sync_point
;
1679 if (!to_return
.empty())
1680 child_info
->return_callback
.Run(to_return
,
1681 blocking_main_thread_task_runner_
);
1683 if (child_info
->marked_for_deletion
&&
1684 child_info
->parent_to_child_map
.empty()) {
1685 DCHECK(child_info
->child_to_parent_map
.empty());
1686 children_
.erase(child_it
);
1690 void ResourceProvider::AcquirePixelBuffer(ResourceId id
) {
1691 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug"),
1692 "ResourceProvider::AcquirePixelBuffer");
1694 Resource
* resource
= GetResource(id
);
1695 DCHECK(resource
->origin
== Resource::Internal
);
1696 DCHECK_EQ(resource
->exported_count
, 0);
1697 DCHECK(!resource
->image_id
);
1698 DCHECK_NE(ETC1
, resource
->format
);
1700 DCHECK_EQ(GLTexture
, resource
->type
);
1701 GLES2Interface
* gl
= ContextGL();
1703 if (!resource
->gl_pixel_buffer_id
)
1704 resource
->gl_pixel_buffer_id
= buffer_id_allocator_
->NextId();
1705 gl
->BindBuffer(GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM
,
1706 resource
->gl_pixel_buffer_id
);
1707 unsigned bytes_per_pixel
= BitsPerPixel(resource
->format
) / 8;
1708 gl
->BufferData(GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM
,
1709 resource
->size
.height() *
1710 RoundUp(bytes_per_pixel
* resource
->size
.width(), 4u),
1713 gl
->BindBuffer(GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM
, 0);
1716 void ResourceProvider::ReleasePixelBuffer(ResourceId id
) {
1717 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug"),
1718 "ResourceProvider::ReleasePixelBuffer");
1720 Resource
* resource
= GetResource(id
);
1721 DCHECK(resource
->origin
== Resource::Internal
);
1722 DCHECK_EQ(resource
->exported_count
, 0);
1723 DCHECK(!resource
->image_id
);
1725 // The pixel buffer can be released while there is a pending "set pixels"
1726 // if completion has been forced. Any shared memory associated with this
1727 // pixel buffer will not be freed until the waitAsyncTexImage2DCHROMIUM
1728 // command has been processed on the service side. It is also safe to
1729 // reuse any query id associated with this resource before they complete
1730 // as each new query has a unique submit count.
1731 if (resource
->pending_set_pixels
) {
1732 DCHECK(resource
->set_pixels_completion_forced
);
1733 resource
->pending_set_pixels
= false;
1734 resource
->locked_for_write
= false;
1737 DCHECK_EQ(GLTexture
, resource
->type
);
1738 if (!resource
->gl_pixel_buffer_id
)
1740 GLES2Interface
* gl
= ContextGL();
1742 gl
->BindBuffer(GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM
,
1743 resource
->gl_pixel_buffer_id
);
1745 GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM
, 0, NULL
, GL_DYNAMIC_DRAW
);
1746 gl
->BindBuffer(GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM
, 0);
1749 uint8_t* ResourceProvider::MapPixelBuffer(ResourceId id
, int* stride
) {
1750 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug"),
1751 "ResourceProvider::MapPixelBuffer");
1753 Resource
* resource
= GetResource(id
);
1754 DCHECK(resource
->origin
== Resource::Internal
);
1755 DCHECK_EQ(resource
->exported_count
, 0);
1756 DCHECK(!resource
->image_id
);
1759 DCHECK_EQ(GLTexture
, resource
->type
);
1760 GLES2Interface
* gl
= ContextGL();
1762 DCHECK(resource
->gl_pixel_buffer_id
);
1763 gl
->BindBuffer(GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM
,
1764 resource
->gl_pixel_buffer_id
);
1765 uint8_t* image
= static_cast<uint8_t*>(gl
->MapBufferCHROMIUM(
1766 GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM
, GL_WRITE_ONLY
));
1767 gl
->BindBuffer(GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM
, 0);
1768 // Buffer is required to be 4-byte aligned.
1769 CHECK(!(reinterpret_cast<intptr_t>(image
) & 3));
1773 void ResourceProvider::UnmapPixelBuffer(ResourceId id
) {
1774 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug"),
1775 "ResourceProvider::UnmapPixelBuffer");
1777 Resource
* resource
= GetResource(id
);
1778 DCHECK(resource
->origin
== Resource::Internal
);
1779 DCHECK_EQ(resource
->exported_count
, 0);
1780 DCHECK(!resource
->image_id
);
1782 DCHECK_EQ(GLTexture
, resource
->type
);
1783 GLES2Interface
* gl
= ContextGL();
1785 DCHECK(resource
->gl_pixel_buffer_id
);
1786 gl
->BindBuffer(GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM
,
1787 resource
->gl_pixel_buffer_id
);
1788 gl
->UnmapBufferCHROMIUM(GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM
);
1789 gl
->BindBuffer(GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM
, 0);
1792 GLenum
ResourceProvider::BindForSampling(ResourceId resource_id
,
1795 DCHECK(thread_checker_
.CalledOnValidThread());
1796 GLES2Interface
* gl
= ContextGL();
1797 ResourceMap::iterator it
= resources_
.find(resource_id
);
1798 DCHECK(it
!= resources_
.end());
1799 Resource
* resource
= &it
->second
;
1800 DCHECK(resource
->lock_for_read_count
);
1801 DCHECK(!resource
->locked_for_write
|| resource
->set_pixels_completion_forced
);
1803 ScopedSetActiveTexture
scoped_active_tex(gl
, unit
);
1804 GLenum target
= resource
->target
;
1805 GLC(gl
, gl
->BindTexture(target
, resource
->gl_id
));
1806 if (filter
!= resource
->filter
) {
1807 GLC(gl
, gl
->TexParameteri(target
, GL_TEXTURE_MIN_FILTER
, filter
));
1808 GLC(gl
, gl
->TexParameteri(target
, GL_TEXTURE_MAG_FILTER
, filter
));
1809 resource
->filter
= filter
;
1812 if (resource
->image_id
&& resource
->dirty_image
)
1813 BindImageForSampling(resource
);
1818 void ResourceProvider::BeginSetPixels(ResourceId id
) {
1819 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug"),
1820 "ResourceProvider::BeginSetPixels");
1822 Resource
* resource
= GetResource(id
);
1823 DCHECK(!resource
->pending_set_pixels
);
1825 LazyCreate(resource
);
1826 DCHECK(resource
->origin
== Resource::Internal
);
1827 DCHECK(resource
->gl_id
|| resource
->allocated
);
1828 DCHECK(ReadLockFenceHasPassed(resource
));
1829 DCHECK(!resource
->image_id
);
1831 bool allocate
= !resource
->allocated
;
1832 resource
->allocated
= true;
1835 DCHECK_EQ(GLTexture
, resource
->type
);
1836 DCHECK(resource
->gl_id
);
1837 GLES2Interface
* gl
= ContextGL();
1839 DCHECK(resource
->gl_pixel_buffer_id
);
1840 DCHECK_EQ(resource
->target
, static_cast<GLenum
>(GL_TEXTURE_2D
));
1841 gl
->BindTexture(GL_TEXTURE_2D
, resource
->gl_id
);
1842 gl
->BindBuffer(GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM
,
1843 resource
->gl_pixel_buffer_id
);
1844 if (!resource
->gl_upload_query_id
)
1845 gl
->GenQueriesEXT(1, &resource
->gl_upload_query_id
);
1846 gl
->BeginQueryEXT(GL_ASYNC_PIXEL_UNPACK_COMPLETED_CHROMIUM
,
1847 resource
->gl_upload_query_id
);
1849 gl
->AsyncTexImage2DCHROMIUM(GL_TEXTURE_2D
,
1851 GLInternalFormat(resource
->format
),
1852 resource
->size
.width(),
1853 resource
->size
.height(),
1855 GLDataFormat(resource
->format
),
1856 GLDataType(resource
->format
),
1859 gl
->AsyncTexSubImage2DCHROMIUM(GL_TEXTURE_2D
,
1863 resource
->size
.width(),
1864 resource
->size
.height(),
1865 GLDataFormat(resource
->format
),
1866 GLDataType(resource
->format
),
1869 gl
->EndQueryEXT(GL_ASYNC_PIXEL_UNPACK_COMPLETED_CHROMIUM
);
1870 gl
->BindBuffer(GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM
, 0);
1872 resource
->pending_set_pixels
= true;
1873 resource
->set_pixels_completion_forced
= false;
1876 void ResourceProvider::ForceSetPixelsToComplete(ResourceId id
) {
1877 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug"),
1878 "ResourceProvider::ForceSetPixelsToComplete");
1880 Resource
* resource
= GetResource(id
);
1882 DCHECK(resource
->locked_for_write
);
1883 DCHECK(resource
->pending_set_pixels
);
1884 DCHECK(!resource
->set_pixels_completion_forced
);
1886 if (resource
->gl_id
) {
1887 GLES2Interface
* gl
= ContextGL();
1888 GLC(gl
, gl
->BindTexture(GL_TEXTURE_2D
, resource
->gl_id
));
1889 GLC(gl
, gl
->WaitAsyncTexImage2DCHROMIUM(GL_TEXTURE_2D
));
1890 GLC(gl
, gl
->BindTexture(GL_TEXTURE_2D
, 0));
1893 resource
->set_pixels_completion_forced
= true;
1896 bool ResourceProvider::DidSetPixelsComplete(ResourceId id
) {
1897 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug"),
1898 "ResourceProvider::DidSetPixelsComplete");
1900 Resource
* resource
= GetResource(id
);
1902 DCHECK(resource
->locked_for_write
);
1903 DCHECK(resource
->pending_set_pixels
);
1905 if (resource
->gl_id
) {
1906 GLES2Interface
* gl
= ContextGL();
1908 DCHECK(resource
->gl_upload_query_id
);
1909 GLuint complete
= 1;
1910 gl
->GetQueryObjectuivEXT(
1911 resource
->gl_upload_query_id
, GL_QUERY_RESULT_AVAILABLE_EXT
, &complete
);
1916 resource
->pending_set_pixels
= false;
1917 UnlockForWrite(resource
);
1919 // Async set pixels commands are not necessarily processed in-sequence with
1920 // drawing commands. Read lock fences are required to ensure that async
1921 // commands don't access the resource while used for drawing.
1922 resource
->read_lock_fences_enabled
= true;
1927 void ResourceProvider::CreateForTesting(ResourceId id
) {
1928 LazyCreate(GetResource(id
));
1931 GLenum
ResourceProvider::TargetForTesting(ResourceId id
) {
1932 Resource
* resource
= GetResource(id
);
1933 return resource
->target
;
1936 void ResourceProvider::LazyCreate(Resource
* resource
) {
1937 if (resource
->type
!= GLTexture
|| resource
->origin
!= Resource::Internal
)
1940 if (resource
->gl_id
)
1943 DCHECK(resource
->texture_pool
);
1944 DCHECK(resource
->origin
== Resource::Internal
);
1945 DCHECK(!resource
->mailbox
.IsValid());
1946 resource
->gl_id
= texture_id_allocator_
->NextId();
1948 GLES2Interface
* gl
= ContextGL();
1951 // Create and set texture properties. Allocation is delayed until needed.
1952 GLC(gl
, gl
->BindTexture(resource
->target
, resource
->gl_id
));
1955 resource
->target
, GL_TEXTURE_MIN_FILTER
, resource
->original_filter
));
1958 resource
->target
, GL_TEXTURE_MAG_FILTER
, resource
->original_filter
));
1961 resource
->target
, GL_TEXTURE_WRAP_S
, resource
->wrap_mode
));
1964 resource
->target
, GL_TEXTURE_WRAP_T
, resource
->wrap_mode
));
1967 resource
->target
, GL_TEXTURE_POOL_CHROMIUM
, resource
->texture_pool
));
1968 if (use_texture_usage_hint_
&& (resource
->hint
& TextureHintFramebuffer
)) {
1970 gl
->TexParameteri(resource
->target
,
1971 GL_TEXTURE_USAGE_ANGLE
,
1972 GL_FRAMEBUFFER_ATTACHMENT_ANGLE
));
1976 void ResourceProvider::AllocateForTesting(ResourceId id
) {
1977 LazyAllocate(GetResource(id
));
1980 void ResourceProvider::LazyAllocate(Resource
* resource
) {
1982 if (resource
->allocated
)
1984 LazyCreate(resource
);
1985 if (!resource
->gl_id
)
1987 resource
->allocated
= true;
1988 GLES2Interface
* gl
= ContextGL();
1989 gfx::Size
& size
= resource
->size
;
1990 DCHECK_EQ(resource
->target
, static_cast<GLenum
>(GL_TEXTURE_2D
));
1991 ResourceFormat format
= resource
->format
;
1992 GLC(gl
, gl
->BindTexture(GL_TEXTURE_2D
, resource
->gl_id
));
1993 if (use_texture_storage_ext_
&&
1994 IsFormatSupportedForStorage(format
, use_texture_format_bgra_
) &&
1995 (resource
->hint
& TextureHintImmutable
)) {
1996 GLenum storage_format
= TextureToStorageFormat(format
);
1998 gl
->TexStorage2DEXT(
1999 GL_TEXTURE_2D
, 1, storage_format
, size
.width(), size
.height()));
2001 // ETC1 does not support preallocation.
2002 if (format
!= ETC1
) {
2004 gl
->TexImage2D(GL_TEXTURE_2D
,
2006 GLInternalFormat(format
),
2010 GLDataFormat(format
),
2017 void ResourceProvider::BindImageForSampling(Resource
* resource
) {
2018 GLES2Interface
* gl
= ContextGL();
2019 DCHECK(resource
->gl_id
);
2020 DCHECK(resource
->image_id
);
2022 // Release image currently bound to texture.
2023 if (resource
->bound_image_id
)
2024 gl
->ReleaseTexImage2DCHROMIUM(resource
->target
, resource
->bound_image_id
);
2025 gl
->BindTexImage2DCHROMIUM(resource
->target
, resource
->image_id
);
2026 resource
->bound_image_id
= resource
->image_id
;
2027 resource
->dirty_image
= false;
2030 void ResourceProvider::CopyResource(ResourceId source_id
, ResourceId dest_id
) {
2031 TRACE_EVENT0("cc", "ResourceProvider::CopyResource");
2033 Resource
* source_resource
= GetResource(source_id
);
2034 DCHECK(!source_resource
->lock_for_read_count
);
2035 DCHECK(source_resource
->origin
== Resource::Internal
);
2036 DCHECK_EQ(source_resource
->exported_count
, 0);
2037 DCHECK_EQ(GLTexture
, source_resource
->type
);
2038 DCHECK(source_resource
->allocated
);
2039 LazyCreate(source_resource
);
2041 Resource
* dest_resource
= GetResource(dest_id
);
2042 DCHECK(!dest_resource
->locked_for_write
);
2043 DCHECK(!dest_resource
->lock_for_read_count
);
2044 DCHECK(dest_resource
->origin
== Resource::Internal
);
2045 DCHECK_EQ(dest_resource
->exported_count
, 0);
2046 DCHECK_EQ(GLTexture
, dest_resource
->type
);
2047 LazyAllocate(dest_resource
);
2049 DCHECK_EQ(source_resource
->type
, dest_resource
->type
);
2050 DCHECK_EQ(source_resource
->format
, dest_resource
->format
);
2051 DCHECK(source_resource
->size
== dest_resource
->size
);
2053 GLES2Interface
* gl
= ContextGL();
2055 if (source_resource
->image_id
&& source_resource
->dirty_image
) {
2056 gl
->BindTexture(source_resource
->target
, source_resource
->gl_id
);
2057 BindImageForSampling(source_resource
);
2059 if (use_sync_query_
) {
2060 if (!source_resource
->gl_read_lock_query_id
)
2061 gl
->GenQueriesEXT(1, &source_resource
->gl_read_lock_query_id
);
2062 #if defined(OS_CHROMEOS)
2063 // TODO(reveman): This avoids a performance problem on some ChromeOS
2064 // devices. This needs to be removed to support native GpuMemoryBuffer
2065 // implementations. crbug.com/436314
2066 gl
->BeginQueryEXT(GL_COMMANDS_ISSUED_CHROMIUM
,
2067 source_resource
->gl_read_lock_query_id
);
2069 gl
->BeginQueryEXT(GL_COMMANDS_COMPLETED_CHROMIUM
,
2070 source_resource
->gl_read_lock_query_id
);
2073 DCHECK(!dest_resource
->image_id
);
2074 dest_resource
->allocated
= true;
2075 gl
->CopyTextureCHROMIUM(dest_resource
->target
,
2076 source_resource
->gl_id
,
2077 dest_resource
->gl_id
,
2079 GLInternalFormat(dest_resource
->format
),
2080 GLDataType(dest_resource
->format
));
2081 if (source_resource
->gl_read_lock_query_id
) {
2082 // End query and create a read lock fence that will prevent access to
2083 // source resource until CopyTextureCHROMIUM command has completed.
2084 #if defined(OS_CHROMEOS)
2085 gl
->EndQueryEXT(GL_COMMANDS_ISSUED_CHROMIUM
);
2087 gl
->EndQueryEXT(GL_COMMANDS_COMPLETED_CHROMIUM
);
2089 source_resource
->read_lock_fence
= make_scoped_refptr(
2090 new CopyTextureFence(gl
, source_resource
->gl_read_lock_query_id
));
2092 // Create a SynchronousFence when CHROMIUM_sync_query extension is missing.
2093 // Try to use one synchronous fence for as many CopyResource operations as
2094 // possible as that reduce the number of times we have to synchronize with
2096 if (!synchronous_fence_
.get() || synchronous_fence_
->has_synchronized())
2097 synchronous_fence_
= make_scoped_refptr(new SynchronousFence(gl
));
2098 source_resource
->read_lock_fence
= synchronous_fence_
;
2099 source_resource
->read_lock_fence
->Set();
2103 void ResourceProvider::WaitSyncPointIfNeeded(ResourceId id
) {
2104 Resource
* resource
= GetResource(id
);
2105 DCHECK_EQ(resource
->exported_count
, 0);
2106 DCHECK(resource
->allocated
);
2107 if (resource
->type
!= GLTexture
|| resource
->gl_id
)
2109 if (!resource
->mailbox
.sync_point())
2111 DCHECK(resource
->mailbox
.IsValid());
2112 GLES2Interface
* gl
= ContextGL();
2114 GLC(gl
, gl
->WaitSyncPointCHROMIUM(resource
->mailbox
.sync_point()));
2115 resource
->mailbox
.set_sync_point(0);
2118 void ResourceProvider::WaitReadLockIfNeeded(ResourceId id
) {
2119 Resource
* resource
= GetResource(id
);
2120 DCHECK_EQ(resource
->exported_count
, 0);
2121 if (!resource
->read_lock_fence
.get())
2124 resource
->read_lock_fence
->Wait();
2127 GLint
ResourceProvider::GetActiveTextureUnit(GLES2Interface
* gl
) {
2128 GLint active_unit
= 0;
2129 gl
->GetIntegerv(GL_ACTIVE_TEXTURE
, &active_unit
);
2133 GLES2Interface
* ResourceProvider::ContextGL() const {
2134 ContextProvider
* context_provider
= output_surface_
->context_provider();
2135 return context_provider
? context_provider
->ContextGL() : NULL
;
2138 class GrContext
* ResourceProvider::GrContext() const {
2139 ContextProvider
* context_provider
= output_surface_
->context_provider();
2140 return context_provider
? context_provider
->GrContext() : NULL
;