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/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
;
83 return storage_format
;
86 bool IsFormatSupportedForStorage(ResourceFormat format
, bool use_bgra
) {
103 GrPixelConfig
ToGrPixelConfig(ResourceFormat format
) {
106 return kRGBA_8888_GrPixelConfig
;
108 return kBGRA_8888_GrPixelConfig
;
110 return kRGBA_4444_GrPixelConfig
;
114 DCHECK(false) << "Unsupported resource format.";
115 return kSkia8888_GrPixelConfig
;
118 gfx::GpuMemoryBuffer::Format
ToGpuMemoryBufferFormat(ResourceFormat format
) {
121 return gfx::GpuMemoryBuffer::Format::RGBA_8888
;
123 return gfx::GpuMemoryBuffer::Format::BGRA_8888
;
133 return gfx::GpuMemoryBuffer::Format::RGBA_8888
;
136 class ScopedSetActiveTexture
{
138 ScopedSetActiveTexture(GLES2Interface
* gl
, GLenum unit
)
139 : gl_(gl
), unit_(unit
) {
140 DCHECK_EQ(GL_TEXTURE0
, ResourceProvider::GetActiveTextureUnit(gl_
));
142 if (unit_
!= GL_TEXTURE0
)
143 gl_
->ActiveTexture(unit_
);
146 ~ScopedSetActiveTexture() {
147 // Active unit being GL_TEXTURE0 is effectively the ground state.
148 if (unit_
!= GL_TEXTURE0
)
149 gl_
->ActiveTexture(GL_TEXTURE0
);
157 class TextureIdAllocator
: public IdAllocator
{
159 TextureIdAllocator(GLES2Interface
* gl
,
160 size_t texture_id_allocation_chunk_size
)
161 : IdAllocator(gl
, texture_id_allocation_chunk_size
) {}
162 ~TextureIdAllocator() override
{
163 gl_
->DeleteTextures(id_allocation_chunk_size_
- next_id_index_
,
164 ids_
.get() + next_id_index_
);
167 // Overridden from IdAllocator:
168 GLuint
NextId() override
{
169 if (next_id_index_
== id_allocation_chunk_size_
) {
170 gl_
->GenTextures(id_allocation_chunk_size_
, ids_
.get());
174 return ids_
[next_id_index_
++];
178 DISALLOW_COPY_AND_ASSIGN(TextureIdAllocator
);
181 class BufferIdAllocator
: public IdAllocator
{
183 BufferIdAllocator(GLES2Interface
* gl
, size_t buffer_id_allocation_chunk_size
)
184 : IdAllocator(gl
, buffer_id_allocation_chunk_size
) {}
185 ~BufferIdAllocator() override
{
186 gl_
->DeleteBuffers(id_allocation_chunk_size_
- next_id_index_
,
187 ids_
.get() + next_id_index_
);
190 // Overridden from IdAllocator:
191 GLuint
NextId() override
{
192 if (next_id_index_
== id_allocation_chunk_size_
) {
193 gl_
->GenBuffers(id_allocation_chunk_size_
, ids_
.get());
197 return ids_
[next_id_index_
++];
201 DISALLOW_COPY_AND_ASSIGN(BufferIdAllocator
);
204 // Query object based fence implementation used to detect completion of copy
205 // texture operations. Fence has passed when query result is available.
206 class CopyTextureFence
: public ResourceProvider::Fence
{
208 CopyTextureFence(gpu::gles2::GLES2Interface
* gl
, unsigned query_id
)
209 : gl_(gl
), query_id_(query_id
) {}
211 // Overridden from ResourceProvider::Fence:
212 void Set() override
{}
213 bool HasPassed() override
{
214 unsigned available
= 1;
215 gl_
->GetQueryObjectuivEXT(
216 query_id_
, GL_QUERY_RESULT_AVAILABLE_EXT
, &available
);
223 void Wait() override
{
224 // ProcessResult() will wait for result to become available.
229 ~CopyTextureFence() override
{}
231 void ProcessResult() {
232 unsigned time_elapsed_us
= 0;
233 gl_
->GetQueryObjectuivEXT(query_id_
, GL_QUERY_RESULT_EXT
, &time_elapsed_us
);
234 UMA_HISTOGRAM_CUSTOM_COUNTS("Renderer4.CopyTextureLatency", time_elapsed_us
,
238 gpu::gles2::GLES2Interface
* gl_
;
241 DISALLOW_COPY_AND_ASSIGN(CopyTextureFence
);
246 ResourceProvider::Resource::Resource()
249 gl_pixel_buffer_id(0),
250 gl_upload_query_id(0),
251 gl_read_lock_query_id(0),
253 lock_for_read_count(0),
257 locked_for_write(false),
259 marked_for_deletion(false),
260 pending_set_pixels(false),
261 set_pixels_completion_forced(false),
263 read_lock_fences_enabled(false),
264 has_shared_bitmap_id(false),
265 allow_overlay(false),
266 read_lock_fence(NULL
),
276 hint(TEXTURE_HINT_IMMUTABLE
),
277 type(RESOURCE_TYPE_INVALID
),
280 gpu_memory_buffer(NULL
) {
283 ResourceProvider::Resource::~Resource() {}
285 ResourceProvider::Resource::Resource(GLuint texture_id
,
286 const gfx::Size
& size
,
293 ResourceFormat format
)
296 gl_pixel_buffer_id(0),
297 gl_upload_query_id(0),
298 gl_read_lock_query_id(0),
300 lock_for_read_count(0),
304 locked_for_write(false),
306 marked_for_deletion(false),
307 pending_set_pixels(false),
308 set_pixels_completion_forced(false),
310 read_lock_fences_enabled(false),
311 has_shared_bitmap_id(false),
312 allow_overlay(false),
313 read_lock_fence(NULL
),
317 original_filter(filter
),
321 texture_pool(texture_pool
),
322 wrap_mode(wrap_mode
),
324 type(RESOURCE_TYPE_GL_TEXTURE
),
327 gpu_memory_buffer(NULL
) {
328 DCHECK(wrap_mode
== GL_CLAMP_TO_EDGE
|| wrap_mode
== GL_REPEAT
);
329 DCHECK_EQ(origin
== INTERNAL
, !!texture_pool
);
332 ResourceProvider::Resource::Resource(uint8_t* pixels
,
333 SharedBitmap
* bitmap
,
334 const gfx::Size
& size
,
340 gl_pixel_buffer_id(0),
341 gl_upload_query_id(0),
342 gl_read_lock_query_id(0),
344 lock_for_read_count(0),
348 locked_for_write(false),
350 marked_for_deletion(false),
351 pending_set_pixels(false),
352 set_pixels_completion_forced(false),
354 read_lock_fences_enabled(false),
355 has_shared_bitmap_id(!!bitmap
),
356 allow_overlay(false),
357 read_lock_fence(NULL
),
361 original_filter(filter
),
366 wrap_mode(wrap_mode
),
367 hint(TEXTURE_HINT_IMMUTABLE
),
368 type(RESOURCE_TYPE_BITMAP
),
370 shared_bitmap(bitmap
),
371 gpu_memory_buffer(NULL
) {
372 DCHECK(wrap_mode
== GL_CLAMP_TO_EDGE
|| wrap_mode
== GL_REPEAT
);
373 DCHECK(origin
== DELEGATED
|| pixels
);
375 shared_bitmap_id
= bitmap
->id();
378 ResourceProvider::Resource::Resource(const SharedBitmapId
& bitmap_id
,
379 const gfx::Size
& size
,
385 gl_pixel_buffer_id(0),
386 gl_upload_query_id(0),
387 gl_read_lock_query_id(0),
389 lock_for_read_count(0),
393 locked_for_write(false),
395 marked_for_deletion(false),
396 pending_set_pixels(false),
397 set_pixels_completion_forced(false),
399 read_lock_fences_enabled(false),
400 has_shared_bitmap_id(true),
401 allow_overlay(false),
402 read_lock_fence(NULL
),
406 original_filter(filter
),
411 wrap_mode(wrap_mode
),
412 hint(TEXTURE_HINT_IMMUTABLE
),
413 type(RESOURCE_TYPE_BITMAP
),
415 shared_bitmap_id(bitmap_id
),
417 gpu_memory_buffer(NULL
) {
418 DCHECK(wrap_mode
== GL_CLAMP_TO_EDGE
|| wrap_mode
== GL_REPEAT
);
421 ResourceProvider::Child::Child() : marked_for_deletion(false) {}
423 ResourceProvider::Child::~Child() {}
425 scoped_ptr
<ResourceProvider
> ResourceProvider::Create(
426 OutputSurface
* output_surface
,
427 SharedBitmapManager
* shared_bitmap_manager
,
428 gpu::GpuMemoryBufferManager
* gpu_memory_buffer_manager
,
429 BlockingTaskRunner
* blocking_main_thread_task_runner
,
430 int highp_threshold_min
,
431 bool use_rgba_4444_texture_format
,
432 size_t id_allocation_chunk_size
) {
433 scoped_ptr
<ResourceProvider
> resource_provider(
434 new ResourceProvider(output_surface
,
435 shared_bitmap_manager
,
436 gpu_memory_buffer_manager
,
437 blocking_main_thread_task_runner
,
439 use_rgba_4444_texture_format
,
440 id_allocation_chunk_size
));
442 if (resource_provider
->ContextGL())
443 resource_provider
->InitializeGL();
445 resource_provider
->InitializeSoftware();
447 DCHECK_NE(RESOURCE_TYPE_INVALID
, resource_provider
->default_resource_type());
448 return resource_provider
.Pass();
451 ResourceProvider::~ResourceProvider() {
452 while (!children_
.empty())
453 DestroyChildInternal(children_
.begin(), FOR_SHUTDOWN
);
454 while (!resources_
.empty())
455 DeleteResourceInternal(resources_
.begin(), FOR_SHUTDOWN
);
460 bool ResourceProvider::InUseByConsumer(ResourceId id
) {
461 Resource
* resource
= GetResource(id
);
462 return resource
->lock_for_read_count
> 0 || resource
->exported_count
> 0 ||
466 bool ResourceProvider::IsLost(ResourceId id
) {
467 Resource
* resource
= GetResource(id
);
468 return resource
->lost
;
471 bool ResourceProvider::AllowOverlay(ResourceId id
) {
472 Resource
* resource
= GetResource(id
);
473 return resource
->allow_overlay
;
476 ResourceProvider::ResourceId
ResourceProvider::CreateResource(
477 const gfx::Size
& size
,
480 ResourceFormat format
) {
481 DCHECK(!size
.IsEmpty());
482 switch (default_resource_type_
) {
483 case RESOURCE_TYPE_GL_TEXTURE
:
484 return CreateGLTexture(size
,
486 GL_TEXTURE_POOL_UNMANAGED_CHROMIUM
,
490 case RESOURCE_TYPE_BITMAP
:
491 DCHECK_EQ(RGBA_8888
, format
);
492 return CreateBitmap(size
, wrap_mode
);
493 case RESOURCE_TYPE_INVALID
:
497 LOG(FATAL
) << "Invalid default resource type.";
501 ResourceProvider::ResourceId
ResourceProvider::CreateManagedResource(
502 const gfx::Size
& size
,
506 ResourceFormat format
) {
507 DCHECK(!size
.IsEmpty());
508 switch (default_resource_type_
) {
509 case RESOURCE_TYPE_GL_TEXTURE
:
510 return CreateGLTexture(size
,
512 GL_TEXTURE_POOL_MANAGED_CHROMIUM
,
516 case RESOURCE_TYPE_BITMAP
:
517 DCHECK_EQ(RGBA_8888
, format
);
518 return CreateBitmap(size
, wrap_mode
);
519 case RESOURCE_TYPE_INVALID
:
523 LOG(FATAL
) << "Invalid default resource type.";
527 ResourceProvider::ResourceId
ResourceProvider::CreateGLTexture(
528 const gfx::Size
& size
,
533 ResourceFormat format
) {
534 DCHECK_LE(size
.width(), max_texture_size_
);
535 DCHECK_LE(size
.height(), max_texture_size_
);
536 DCHECK(thread_checker_
.CalledOnValidThread());
538 ResourceId id
= next_id_
++;
539 Resource
resource(0, size
, Resource::INTERNAL
, target
, GL_LINEAR
,
540 texture_pool
, wrap_mode
, hint
, format
);
541 resource
.allocated
= false;
542 resources_
[id
] = resource
;
546 ResourceProvider::ResourceId
ResourceProvider::CreateBitmap(
547 const gfx::Size
& size
, GLint wrap_mode
) {
548 DCHECK(thread_checker_
.CalledOnValidThread());
550 scoped_ptr
<SharedBitmap
> bitmap
=
551 shared_bitmap_manager_
->AllocateSharedBitmap(size
);
552 uint8_t* pixels
= bitmap
->pixels();
555 ResourceId id
= next_id_
++;
556 Resource
resource(pixels
, bitmap
.release(), size
, Resource::INTERNAL
,
557 GL_LINEAR
, wrap_mode
);
558 resource
.allocated
= true;
559 resources_
[id
] = resource
;
563 ResourceProvider::ResourceId
ResourceProvider::CreateResourceFromIOSurface(
564 const gfx::Size
& size
,
565 unsigned io_surface_id
) {
566 DCHECK(thread_checker_
.CalledOnValidThread());
568 ResourceId id
= next_id_
++;
569 Resource
resource(0, gfx::Size(), Resource::INTERNAL
,
570 GL_TEXTURE_RECTANGLE_ARB
, GL_LINEAR
,
571 GL_TEXTURE_POOL_UNMANAGED_CHROMIUM
, GL_CLAMP_TO_EDGE
,
572 TEXTURE_HINT_IMMUTABLE
, RGBA_8888
);
573 LazyCreate(&resource
);
574 GLES2Interface
* gl
= ContextGL();
576 gl
->BindTexture(GL_TEXTURE_RECTANGLE_ARB
, resource
.gl_id
);
577 gl
->TexImageIOSurface2DCHROMIUM(
578 GL_TEXTURE_RECTANGLE_ARB
, size
.width(), size
.height(), io_surface_id
, 0);
579 resource
.allocated
= true;
580 resources_
[id
] = resource
;
584 ResourceProvider::ResourceId
ResourceProvider::CreateResourceFromTextureMailbox(
585 const TextureMailbox
& mailbox
,
586 scoped_ptr
<SingleReleaseCallbackImpl
> release_callback_impl
) {
587 DCHECK(thread_checker_
.CalledOnValidThread());
588 // Just store the information. Mailbox will be consumed in LockForRead().
589 ResourceId id
= next_id_
++;
590 DCHECK(mailbox
.IsValid());
591 Resource
& resource
= resources_
[id
];
592 if (mailbox
.IsTexture()) {
593 resource
= Resource(0, gfx::Size(), Resource::EXTERNAL
, mailbox
.target(),
594 mailbox
.nearest_neighbor() ? GL_NEAREST
: GL_LINEAR
, 0,
595 GL_CLAMP_TO_EDGE
, TEXTURE_HINT_IMMUTABLE
, RGBA_8888
);
597 DCHECK(mailbox
.IsSharedMemory());
598 SharedBitmap
* shared_bitmap
= mailbox
.shared_bitmap();
599 uint8_t* pixels
= shared_bitmap
->pixels();
601 resource
= Resource(pixels
, shared_bitmap
, mailbox
.shared_memory_size(),
602 Resource::EXTERNAL
, GL_LINEAR
, GL_CLAMP_TO_EDGE
);
604 resource
.allocated
= true;
605 resource
.mailbox
= mailbox
;
606 resource
.release_callback_impl
=
607 base::Bind(&SingleReleaseCallbackImpl::Run
,
608 base::Owned(release_callback_impl
.release()));
609 resource
.allow_overlay
= mailbox
.allow_overlay();
613 void ResourceProvider::DeleteResource(ResourceId id
) {
614 DCHECK(thread_checker_
.CalledOnValidThread());
615 ResourceMap::iterator it
= resources_
.find(id
);
616 CHECK(it
!= resources_
.end());
617 Resource
* resource
= &it
->second
;
618 DCHECK(!resource
->marked_for_deletion
);
619 DCHECK_EQ(resource
->imported_count
, 0);
620 DCHECK(resource
->pending_set_pixels
|| !resource
->locked_for_write
);
622 if (resource
->exported_count
> 0 || resource
->lock_for_read_count
> 0) {
623 resource
->marked_for_deletion
= true;
626 DeleteResourceInternal(it
, NORMAL
);
630 void ResourceProvider::DeleteResourceInternal(ResourceMap::iterator it
,
632 TRACE_EVENT0("cc", "ResourceProvider::DeleteResourceInternal");
633 Resource
* resource
= &it
->second
;
634 bool lost_resource
= resource
->lost
;
636 DCHECK(resource
->exported_count
== 0 || style
!= NORMAL
);
637 if (style
== FOR_SHUTDOWN
&& resource
->exported_count
> 0)
638 lost_resource
= true;
640 if (resource
->image_id
) {
641 DCHECK(resource
->origin
== Resource::INTERNAL
);
642 GLES2Interface
* gl
= ContextGL();
644 gl
->DestroyImageCHROMIUM(resource
->image_id
);
646 if (resource
->gl_upload_query_id
) {
647 DCHECK(resource
->origin
== Resource::INTERNAL
);
648 GLES2Interface
* gl
= ContextGL();
650 gl
->DeleteQueriesEXT(1, &resource
->gl_upload_query_id
);
652 if (resource
->gl_read_lock_query_id
) {
653 DCHECK(resource
->origin
== Resource::INTERNAL
);
654 GLES2Interface
* gl
= ContextGL();
656 gl
->DeleteQueriesEXT(1, &resource
->gl_read_lock_query_id
);
658 if (resource
->gl_pixel_buffer_id
) {
659 DCHECK(resource
->origin
== Resource::INTERNAL
);
660 GLES2Interface
* gl
= ContextGL();
662 gl
->DeleteBuffers(1, &resource
->gl_pixel_buffer_id
);
664 if (resource
->origin
== Resource::EXTERNAL
) {
665 DCHECK(resource
->mailbox
.IsValid());
666 GLuint sync_point
= resource
->mailbox
.sync_point();
667 if (resource
->type
== RESOURCE_TYPE_GL_TEXTURE
) {
668 DCHECK(resource
->mailbox
.IsTexture());
669 lost_resource
|= lost_output_surface_
;
670 GLES2Interface
* gl
= ContextGL();
672 if (resource
->gl_id
) {
673 gl
->DeleteTextures(1, &resource
->gl_id
);
676 sync_point
= gl
->InsertSyncPointCHROMIUM();
679 DCHECK(resource
->mailbox
.IsSharedMemory());
680 resource
->shared_bitmap
= nullptr;
681 resource
->pixels
= nullptr;
683 resource
->release_callback_impl
.Run(
684 sync_point
, lost_resource
, blocking_main_thread_task_runner_
);
686 if (resource
->gl_id
) {
687 GLES2Interface
* gl
= ContextGL();
689 gl
->DeleteTextures(1, &resource
->gl_id
);
692 if (resource
->shared_bitmap
) {
693 DCHECK(resource
->origin
!= Resource::EXTERNAL
);
694 DCHECK_EQ(RESOURCE_TYPE_BITMAP
, resource
->type
);
695 delete resource
->shared_bitmap
;
696 resource
->pixels
= NULL
;
698 if (resource
->pixels
) {
699 DCHECK(resource
->origin
== Resource::INTERNAL
);
700 delete[] resource
->pixels
;
701 resource
->pixels
= NULL
;
703 if (resource
->gpu_memory_buffer
) {
704 DCHECK(resource
->origin
== Resource::INTERNAL
);
705 delete resource
->gpu_memory_buffer
;
706 resource
->gpu_memory_buffer
= NULL
;
708 resources_
.erase(it
);
711 ResourceProvider::ResourceType
ResourceProvider::GetResourceType(
713 return GetResource(id
)->type
;
716 void ResourceProvider::SetPixels(ResourceId id
,
717 const uint8_t* image
,
718 const gfx::Rect
& image_rect
,
719 const gfx::Rect
& source_rect
,
720 const gfx::Vector2d
& dest_offset
) {
721 Resource
* resource
= GetResource(id
);
722 DCHECK(!resource
->locked_for_write
);
723 DCHECK(!resource
->lock_for_read_count
);
724 DCHECK(resource
->origin
== Resource::INTERNAL
);
725 DCHECK_EQ(resource
->exported_count
, 0);
726 DCHECK(ReadLockFenceHasPassed(resource
));
727 LazyAllocate(resource
);
729 if (resource
->type
== RESOURCE_TYPE_GL_TEXTURE
) {
730 DCHECK(resource
->gl_id
);
731 DCHECK(!resource
->pending_set_pixels
);
732 DCHECK_EQ(resource
->target
, static_cast<GLenum
>(GL_TEXTURE_2D
));
733 GLES2Interface
* gl
= ContextGL();
735 DCHECK(texture_uploader_
.get());
736 gl
->BindTexture(GL_TEXTURE_2D
, resource
->gl_id
);
737 texture_uploader_
->Upload(image
,
744 DCHECK_EQ(RESOURCE_TYPE_BITMAP
, resource
->type
);
745 DCHECK(resource
->allocated
);
746 DCHECK_EQ(RGBA_8888
, resource
->format
);
747 DCHECK(source_rect
.x() >= image_rect
.x());
748 DCHECK(source_rect
.y() >= image_rect
.y());
749 DCHECK(source_rect
.right() <= image_rect
.right());
750 DCHECK(source_rect
.bottom() <= image_rect
.bottom());
751 SkImageInfo source_info
=
752 SkImageInfo::MakeN32Premul(source_rect
.width(), source_rect
.height());
753 size_t image_row_bytes
= image_rect
.width() * 4;
754 gfx::Vector2d source_offset
= source_rect
.origin() - image_rect
.origin();
755 image
+= source_offset
.y() * image_row_bytes
+ source_offset
.x() * 4;
757 ScopedWriteLockSoftware
lock(this, id
);
758 SkCanvas
dest(lock
.sk_bitmap());
759 dest
.writePixels(source_info
, image
, image_row_bytes
, dest_offset
.x(),
764 void ResourceProvider::CopyToResource(ResourceId id
,
765 const uint8_t* image
,
766 const gfx::Size
& image_size
) {
767 Resource
* resource
= GetResource(id
);
768 DCHECK(!resource
->locked_for_write
);
769 DCHECK(!resource
->lock_for_read_count
);
770 DCHECK(resource
->origin
== Resource::INTERNAL
);
771 DCHECK_EQ(resource
->exported_count
, 0);
772 DCHECK(ReadLockFenceHasPassed(resource
));
773 LazyAllocate(resource
);
775 DCHECK_EQ(image_size
.width(), resource
->size
.width());
776 DCHECK_EQ(image_size
.height(), resource
->size
.height());
778 if (resource
->type
== RESOURCE_TYPE_BITMAP
) {
779 DCHECK_EQ(RESOURCE_TYPE_BITMAP
, resource
->type
);
780 DCHECK(resource
->allocated
);
781 DCHECK_EQ(RGBA_8888
, resource
->format
);
782 SkImageInfo source_info
=
783 SkImageInfo::MakeN32Premul(image_size
.width(), image_size
.height());
784 size_t image_stride
= image_size
.width() * 4;
786 ScopedWriteLockSoftware
lock(this, id
);
787 SkCanvas
dest(lock
.sk_bitmap());
788 dest
.writePixels(source_info
, image
, image_stride
, 0, 0);
790 DCHECK(resource
->gl_id
);
791 DCHECK(!resource
->pending_set_pixels
);
792 DCHECK_EQ(resource
->target
, static_cast<GLenum
>(GL_TEXTURE_2D
));
793 GLES2Interface
* gl
= ContextGL();
795 DCHECK(texture_uploader_
.get());
796 gl
->BindTexture(GL_TEXTURE_2D
, resource
->gl_id
);
798 if (resource
->format
== ETC1
) {
799 size_t num_bytes
= static_cast<size_t>(image_size
.width()) *
800 image_size
.height() * BitsPerPixel(ETC1
) / 8;
801 gl
->CompressedTexImage2D(GL_TEXTURE_2D
, 0, GLInternalFormat(ETC1
),
802 image_size
.width(), image_size
.height(), 0,
805 gl
->TexSubImage2D(GL_TEXTURE_2D
, 0, 0, 0, image_size
.width(),
806 image_size
.height(), GLDataFormat(resource
->format
),
807 GLDataType(resource
->format
), image
);
812 size_t ResourceProvider::NumBlockingUploads() {
813 if (!texture_uploader_
)
816 return texture_uploader_
->NumBlockingUploads();
819 void ResourceProvider::MarkPendingUploadsAsNonBlocking() {
820 if (!texture_uploader_
)
823 texture_uploader_
->MarkPendingUploadsAsNonBlocking();
826 size_t ResourceProvider::EstimatedUploadsPerTick() {
827 if (!texture_uploader_
)
830 double textures_per_second
= texture_uploader_
->EstimatedTexturesPerSecond();
831 size_t textures_per_tick
= floor(
832 kTextureUploadTickRate
* textures_per_second
);
833 return textures_per_tick
? textures_per_tick
: 1u;
836 void ResourceProvider::FlushUploads() {
837 if (!texture_uploader_
)
840 texture_uploader_
->Flush();
843 void ResourceProvider::ReleaseCachedData() {
844 if (!texture_uploader_
)
847 texture_uploader_
->ReleaseCachedQueries();
850 base::TimeTicks
ResourceProvider::EstimatedUploadCompletionTime(
851 size_t uploads_per_tick
) {
852 if (lost_output_surface_
)
853 return base::TimeTicks();
855 // Software resource uploads happen on impl thread, so don't bother batching
856 // them up and trying to wait for them to complete.
857 if (!texture_uploader_
) {
858 return gfx::FrameTime::Now() + base::TimeDelta::FromMicroseconds(
859 base::Time::kMicrosecondsPerSecond
* kSoftwareUploadTickRate
);
862 base::TimeDelta upload_one_texture_time
=
863 base::TimeDelta::FromMicroseconds(
864 base::Time::kMicrosecondsPerSecond
* kTextureUploadTickRate
) /
867 size_t total_uploads
= NumBlockingUploads() + uploads_per_tick
;
868 return gfx::FrameTime::Now() + upload_one_texture_time
* total_uploads
;
871 ResourceProvider::Resource
* ResourceProvider::GetResource(ResourceId id
) {
872 DCHECK(thread_checker_
.CalledOnValidThread());
873 // TODO(danakj): crbug.com/455931
875 ResourceMap::iterator it
= resources_
.find(id
);
876 CHECK(it
!= resources_
.end());
880 const ResourceProvider::Resource
* ResourceProvider::LockForRead(ResourceId id
) {
881 Resource
* resource
= GetResource(id
);
882 DCHECK(!resource
->locked_for_write
||
883 resource
->set_pixels_completion_forced
) <<
884 "locked for write: " << resource
->locked_for_write
<<
885 " pixels completion forced: " << resource
->set_pixels_completion_forced
;
886 DCHECK_EQ(resource
->exported_count
, 0);
887 // Uninitialized! Call SetPixels or LockForWrite first.
888 DCHECK(resource
->allocated
);
890 LazyCreate(resource
);
892 if (resource
->type
== RESOURCE_TYPE_GL_TEXTURE
&& !resource
->gl_id
) {
893 DCHECK(resource
->origin
!= Resource::INTERNAL
);
894 DCHECK(resource
->mailbox
.IsTexture());
896 // Mailbox sync_points must be processed by a call to
897 // WaitSyncPointIfNeeded() prior to calling LockForRead().
898 DCHECK(!resource
->mailbox
.sync_point());
900 GLES2Interface
* gl
= ContextGL();
902 resource
->gl_id
= gl
->CreateAndConsumeTextureCHROMIUM(
903 resource
->mailbox
.target(), resource
->mailbox
.name());
906 if (!resource
->pixels
&& resource
->has_shared_bitmap_id
&&
907 shared_bitmap_manager_
) {
908 scoped_ptr
<SharedBitmap
> bitmap
=
909 shared_bitmap_manager_
->GetSharedBitmapFromId(
910 resource
->size
, resource
->shared_bitmap_id
);
912 resource
->shared_bitmap
= bitmap
.release();
913 resource
->pixels
= resource
->shared_bitmap
->pixels();
917 resource
->lock_for_read_count
++;
918 if (resource
->read_lock_fences_enabled
) {
919 if (current_read_lock_fence_
.get())
920 current_read_lock_fence_
->Set();
921 resource
->read_lock_fence
= current_read_lock_fence_
;
927 void ResourceProvider::UnlockForRead(ResourceId id
) {
928 DCHECK(thread_checker_
.CalledOnValidThread());
929 ResourceMap::iterator it
= resources_
.find(id
);
930 CHECK(it
!= resources_
.end());
932 Resource
* resource
= &it
->second
;
933 DCHECK_GT(resource
->lock_for_read_count
, 0);
934 DCHECK_EQ(resource
->exported_count
, 0);
935 resource
->lock_for_read_count
--;
936 if (resource
->marked_for_deletion
&& !resource
->lock_for_read_count
) {
937 if (!resource
->child_id
) {
938 // The resource belongs to this ResourceProvider, so it can be destroyed.
939 DeleteResourceInternal(it
, NORMAL
);
941 ChildMap::iterator child_it
= children_
.find(resource
->child_id
);
942 ResourceIdArray unused
;
943 unused
.push_back(id
);
944 DeleteAndReturnUnusedResourcesToChild(child_it
, NORMAL
, unused
);
949 ResourceProvider::Resource
* ResourceProvider::LockForWrite(ResourceId id
) {
950 Resource
* resource
= GetResource(id
);
951 DCHECK(CanLockForWrite(id
));
953 resource
->locked_for_write
= true;
957 bool ResourceProvider::CanLockForWrite(ResourceId id
) {
958 Resource
* resource
= GetResource(id
);
959 return !resource
->locked_for_write
&& !resource
->lock_for_read_count
&&
960 !resource
->exported_count
&& resource
->origin
== Resource::INTERNAL
&&
961 !resource
->lost
&& ReadLockFenceHasPassed(resource
);
964 void ResourceProvider::UnlockForWrite(ResourceProvider::Resource
* resource
) {
965 DCHECK(resource
->locked_for_write
);
966 DCHECK_EQ(resource
->exported_count
, 0);
967 DCHECK(resource
->origin
== Resource::INTERNAL
);
968 resource
->locked_for_write
= false;
971 ResourceProvider::ScopedReadLockGL::ScopedReadLockGL(
972 ResourceProvider
* resource_provider
,
973 ResourceProvider::ResourceId resource_id
)
974 : resource_provider_(resource_provider
),
975 resource_id_(resource_id
),
976 texture_id_(resource_provider
->LockForRead(resource_id
)->gl_id
) {
980 ResourceProvider::ScopedReadLockGL::~ScopedReadLockGL() {
981 resource_provider_
->UnlockForRead(resource_id_
);
984 ResourceProvider::ScopedSamplerGL::ScopedSamplerGL(
985 ResourceProvider
* resource_provider
,
986 ResourceProvider::ResourceId resource_id
,
988 : ScopedReadLockGL(resource_provider
, resource_id
),
990 target_(resource_provider
->BindForSampling(resource_id
, unit_
, filter
)) {
993 ResourceProvider::ScopedSamplerGL::ScopedSamplerGL(
994 ResourceProvider
* resource_provider
,
995 ResourceProvider::ResourceId resource_id
,
998 : ScopedReadLockGL(resource_provider
, resource_id
),
1000 target_(resource_provider
->BindForSampling(resource_id
, unit_
, filter
)) {
1003 ResourceProvider::ScopedSamplerGL::~ScopedSamplerGL() {
1006 ResourceProvider::ScopedWriteLockGL::ScopedWriteLockGL(
1007 ResourceProvider
* resource_provider
,
1008 ResourceProvider::ResourceId resource_id
)
1009 : resource_provider_(resource_provider
),
1010 resource_(resource_provider
->LockForWrite(resource_id
)) {
1011 resource_provider_
->LazyAllocate(resource_
);
1012 texture_id_
= resource_
->gl_id
;
1013 DCHECK(texture_id_
);
1016 ResourceProvider::ScopedWriteLockGL::~ScopedWriteLockGL() {
1017 resource_provider_
->UnlockForWrite(resource_
);
1020 void ResourceProvider::PopulateSkBitmapWithResource(
1021 SkBitmap
* sk_bitmap
, const Resource
* resource
) {
1022 DCHECK_EQ(RGBA_8888
, resource
->format
);
1023 SkImageInfo info
= SkImageInfo::MakeN32Premul(resource
->size
.width(),
1024 resource
->size
.height());
1025 sk_bitmap
->installPixels(info
, resource
->pixels
, info
.minRowBytes());
1028 ResourceProvider::ScopedReadLockSoftware::ScopedReadLockSoftware(
1029 ResourceProvider
* resource_provider
,
1030 ResourceProvider::ResourceId resource_id
)
1031 : resource_provider_(resource_provider
),
1032 resource_id_(resource_id
) {
1033 const Resource
* resource
= resource_provider
->LockForRead(resource_id
);
1034 wrap_mode_
= resource
->wrap_mode
;
1035 ResourceProvider::PopulateSkBitmapWithResource(&sk_bitmap_
, resource
);
1038 ResourceProvider::ScopedReadLockSoftware::~ScopedReadLockSoftware() {
1039 resource_provider_
->UnlockForRead(resource_id_
);
1042 ResourceProvider::ScopedWriteLockSoftware::ScopedWriteLockSoftware(
1043 ResourceProvider
* resource_provider
,
1044 ResourceProvider::ResourceId resource_id
)
1045 : resource_provider_(resource_provider
),
1046 resource_(resource_provider
->LockForWrite(resource_id
)) {
1047 ResourceProvider::PopulateSkBitmapWithResource(&sk_bitmap_
, resource_
);
1051 ResourceProvider::ScopedWriteLockSoftware::~ScopedWriteLockSoftware() {
1052 DCHECK(thread_checker_
.CalledOnValidThread());
1053 resource_provider_
->UnlockForWrite(resource_
);
1056 ResourceProvider::ScopedWriteLockGpuMemoryBuffer::
1057 ScopedWriteLockGpuMemoryBuffer(ResourceProvider
* resource_provider
,
1058 ResourceProvider::ResourceId resource_id
)
1059 : resource_provider_(resource_provider
),
1060 resource_(resource_provider
->LockForWrite(resource_id
)),
1061 gpu_memory_buffer_manager_(resource_provider
->gpu_memory_buffer_manager_
),
1062 gpu_memory_buffer_(nullptr),
1063 size_(resource_
->size
),
1064 format_(resource_
->format
) {
1065 DCHECK_EQ(RESOURCE_TYPE_GL_TEXTURE
, resource_
->type
);
1066 std::swap(gpu_memory_buffer_
, resource_
->gpu_memory_buffer
);
1069 ResourceProvider::ScopedWriteLockGpuMemoryBuffer::
1070 ~ScopedWriteLockGpuMemoryBuffer() {
1071 DCHECK(thread_checker_
.CalledOnValidThread());
1072 resource_provider_
->UnlockForWrite(resource_
);
1073 if (!gpu_memory_buffer_
)
1076 if (!resource_
->image_id
) {
1077 GLES2Interface
* gl
= resource_provider_
->ContextGL();
1080 #if defined(OS_CHROMEOS)
1081 // TODO(reveman): GL_COMMANDS_ISSUED_CHROMIUM is used for synchronization
1082 // on ChromeOS to avoid some performance issues. This only works with
1083 // shared memory backed buffers. crbug.com/436314
1084 DCHECK_EQ(gpu_memory_buffer_
->GetHandle().type
, gfx::SHARED_MEMORY_BUFFER
);
1087 resource_
->image_id
= gl
->CreateImageCHROMIUM(
1088 gpu_memory_buffer_
->AsClientBuffer(), size_
.width(), size_
.height(),
1089 GLInternalFormat(resource_
->format
));
1092 std::swap(resource_
->gpu_memory_buffer
, gpu_memory_buffer_
);
1093 resource_
->allocated
= true;
1094 resource_
->dirty_image
= true;
1096 // GpuMemoryBuffer provides direct access to the memory used by the GPU.
1097 // Read lock fences are required to ensure that we're not trying to map a
1098 // buffer that is currently in-use by the GPU.
1099 resource_
->read_lock_fences_enabled
= true;
1102 gfx::GpuMemoryBuffer
*
1103 ResourceProvider::ScopedWriteLockGpuMemoryBuffer::GetGpuMemoryBuffer() {
1104 if (!gpu_memory_buffer_
) {
1105 scoped_ptr
<gfx::GpuMemoryBuffer
> gpu_memory_buffer
=
1106 gpu_memory_buffer_manager_
->AllocateGpuMemoryBuffer(
1107 size_
, ToGpuMemoryBufferFormat(format_
), gfx::GpuMemoryBuffer::MAP
);
1108 gpu_memory_buffer_
= gpu_memory_buffer
.release();
1111 return gpu_memory_buffer_
;
1114 ResourceProvider::ScopedWriteLockGr::ScopedWriteLockGr(
1115 ResourceProvider
* resource_provider
,
1116 ResourceProvider::ResourceId resource_id
)
1117 : resource_provider_(resource_provider
),
1118 resource_(resource_provider
->LockForWrite(resource_id
)) {
1119 DCHECK(thread_checker_
.CalledOnValidThread());
1120 resource_provider_
->LazyAllocate(resource_
);
1123 ResourceProvider::ScopedWriteLockGr::~ScopedWriteLockGr() {
1124 DCHECK(thread_checker_
.CalledOnValidThread());
1125 DCHECK(resource_
->locked_for_write
);
1126 resource_provider_
->UnlockForWrite(resource_
);
1129 void ResourceProvider::ScopedWriteLockGr::InitSkSurface(
1130 bool use_distance_field_text
,
1131 bool can_use_lcd_text
,
1132 int msaa_sample_count
) {
1133 DCHECK(resource_
->locked_for_write
);
1135 GrBackendTextureDesc desc
;
1136 desc
.fFlags
= kRenderTarget_GrBackendTextureFlag
;
1137 desc
.fWidth
= resource_
->size
.width();
1138 desc
.fHeight
= resource_
->size
.height();
1139 desc
.fConfig
= ToGrPixelConfig(resource_
->format
);
1140 desc
.fOrigin
= kTopLeft_GrSurfaceOrigin
;
1141 desc
.fTextureHandle
= resource_
->gl_id
;
1142 desc
.fSampleCnt
= msaa_sample_count
;
1144 bool use_worker_context
= true;
1145 class GrContext
* gr_context
=
1146 resource_provider_
->GrContext(use_worker_context
);
1147 skia::RefPtr
<GrTexture
> gr_texture
=
1148 skia::AdoptRef(gr_context
->wrapBackendTexture(desc
));
1150 uint32_t flags
= use_distance_field_text
1151 ? SkSurfaceProps::kUseDistanceFieldFonts_Flag
1153 // Use unknown pixel geometry to disable LCD text.
1154 SkSurfaceProps
surface_props(flags
, kUnknown_SkPixelGeometry
);
1155 if (can_use_lcd_text
) {
1156 // LegacyFontHost will get LCD text and skia figures out what type to use.
1158 SkSurfaceProps(flags
, SkSurfaceProps::kLegacyFontHost_InitType
);
1160 sk_surface_
= skia::AdoptRef(SkSurface::NewRenderTargetDirect(
1161 gr_texture
->asRenderTarget(), &surface_props
));
1164 sk_surface_
.clear();
1167 void ResourceProvider::ScopedWriteLockGr::ReleaseSkSurface() {
1168 sk_surface_
.clear();
1171 ResourceProvider::SynchronousFence::SynchronousFence(
1172 gpu::gles2::GLES2Interface
* gl
)
1173 : gl_(gl
), has_synchronized_(true) {
1176 ResourceProvider::SynchronousFence::~SynchronousFence() {
1179 void ResourceProvider::SynchronousFence::Set() {
1180 has_synchronized_
= false;
1183 bool ResourceProvider::SynchronousFence::HasPassed() {
1184 if (!has_synchronized_
) {
1185 has_synchronized_
= true;
1191 void ResourceProvider::SynchronousFence::Wait() {
1195 void ResourceProvider::SynchronousFence::Synchronize() {
1196 TRACE_EVENT0("cc", "ResourceProvider::SynchronousFence::Synchronize");
1200 ResourceProvider::ResourceProvider(
1201 OutputSurface
* output_surface
,
1202 SharedBitmapManager
* shared_bitmap_manager
,
1203 gpu::GpuMemoryBufferManager
* gpu_memory_buffer_manager
,
1204 BlockingTaskRunner
* blocking_main_thread_task_runner
,
1205 int highp_threshold_min
,
1206 bool use_rgba_4444_texture_format
,
1207 size_t id_allocation_chunk_size
)
1208 : output_surface_(output_surface
),
1209 shared_bitmap_manager_(shared_bitmap_manager
),
1210 gpu_memory_buffer_manager_(gpu_memory_buffer_manager
),
1211 blocking_main_thread_task_runner_(blocking_main_thread_task_runner
),
1212 lost_output_surface_(false),
1213 highp_threshold_min_(highp_threshold_min
),
1216 default_resource_type_(RESOURCE_TYPE_INVALID
),
1217 use_texture_storage_ext_(false),
1218 use_texture_format_bgra_(false),
1219 use_texture_usage_hint_(false),
1220 use_compressed_texture_etc1_(false),
1221 yuv_resource_format_(LUMINANCE_8
),
1222 max_texture_size_(0),
1223 best_texture_format_(RGBA_8888
),
1224 use_rgba_4444_texture_format_(use_rgba_4444_texture_format
),
1225 id_allocation_chunk_size_(id_allocation_chunk_size
),
1226 use_sync_query_(false) {
1227 DCHECK(output_surface_
->HasClient());
1228 DCHECK(id_allocation_chunk_size_
);
1231 void ResourceProvider::InitializeSoftware() {
1232 DCHECK(thread_checker_
.CalledOnValidThread());
1233 DCHECK_NE(RESOURCE_TYPE_BITMAP
, default_resource_type_
);
1235 CleanUpGLIfNeeded();
1237 default_resource_type_
= RESOURCE_TYPE_BITMAP
;
1238 // Pick an arbitrary limit here similar to what hardware might.
1239 max_texture_size_
= 16 * 1024;
1240 best_texture_format_
= RGBA_8888
;
1243 void ResourceProvider::InitializeGL() {
1244 DCHECK(thread_checker_
.CalledOnValidThread());
1245 DCHECK(!texture_uploader_
);
1246 DCHECK_NE(RESOURCE_TYPE_GL_TEXTURE
, default_resource_type_
);
1247 DCHECK(!texture_id_allocator_
);
1248 DCHECK(!buffer_id_allocator_
);
1250 default_resource_type_
= RESOURCE_TYPE_GL_TEXTURE
;
1252 const ContextProvider::Capabilities
& caps
=
1253 output_surface_
->context_provider()->ContextCapabilities();
1255 bool use_bgra
= caps
.gpu
.texture_format_bgra8888
;
1256 use_texture_storage_ext_
= caps
.gpu
.texture_storage
;
1257 use_texture_format_bgra_
= caps
.gpu
.texture_format_bgra8888
;
1258 use_texture_usage_hint_
= caps
.gpu
.texture_usage
;
1259 use_compressed_texture_etc1_
= caps
.gpu
.texture_format_etc1
;
1260 yuv_resource_format_
= caps
.gpu
.texture_rg
? RED_8
: LUMINANCE_8
;
1261 use_sync_query_
= caps
.gpu
.sync_query
;
1263 GLES2Interface
* gl
= ContextGL();
1266 texture_uploader_
= TextureUploader::Create(gl
);
1267 max_texture_size_
= 0; // Context expects cleared value.
1268 gl
->GetIntegerv(GL_MAX_TEXTURE_SIZE
, &max_texture_size_
);
1269 best_texture_format_
= PlatformColor::BestTextureFormat(use_bgra
);
1271 texture_id_allocator_
.reset(
1272 new TextureIdAllocator(gl
, id_allocation_chunk_size_
));
1273 buffer_id_allocator_
.reset(
1274 new BufferIdAllocator(gl
, id_allocation_chunk_size_
));
1277 void ResourceProvider::CleanUpGLIfNeeded() {
1278 GLES2Interface
* gl
= ContextGL();
1279 if (default_resource_type_
!= RESOURCE_TYPE_GL_TEXTURE
) {
1280 // We are not in GL mode, but double check before returning.
1282 DCHECK(!texture_uploader_
);
1288 // Check that all GL resources has been deleted.
1289 for (ResourceMap::const_iterator itr
= resources_
.begin();
1290 itr
!= resources_
.end();
1292 DCHECK_NE(RESOURCE_TYPE_GL_TEXTURE
, itr
->second
.type
);
1294 #endif // DCHECK_IS_ON()
1296 texture_uploader_
= nullptr;
1297 texture_id_allocator_
= nullptr;
1298 buffer_id_allocator_
= nullptr;
1302 int ResourceProvider::CreateChild(const ReturnCallback
& return_callback
) {
1303 DCHECK(thread_checker_
.CalledOnValidThread());
1306 child_info
.return_callback
= return_callback
;
1308 int child
= next_child_
++;
1309 children_
[child
] = child_info
;
1313 void ResourceProvider::DestroyChild(int child_id
) {
1314 ChildMap::iterator it
= children_
.find(child_id
);
1315 DCHECK(it
!= children_
.end());
1316 DestroyChildInternal(it
, NORMAL
);
1319 void ResourceProvider::DestroyChildInternal(ChildMap::iterator it
,
1320 DeleteStyle style
) {
1321 DCHECK(thread_checker_
.CalledOnValidThread());
1323 Child
& child
= it
->second
;
1324 DCHECK(style
== FOR_SHUTDOWN
|| !child
.marked_for_deletion
);
1326 ResourceIdArray resources_for_child
;
1328 for (ResourceIdMap::iterator child_it
= child
.child_to_parent_map
.begin();
1329 child_it
!= child
.child_to_parent_map
.end();
1331 ResourceId id
= child_it
->second
;
1332 resources_for_child
.push_back(id
);
1335 // If the child is going away, don't consider any resources in use.
1336 child
.in_use_resources
.clear();
1337 child
.marked_for_deletion
= true;
1339 DeleteAndReturnUnusedResourcesToChild(it
, style
, resources_for_child
);
1342 const ResourceProvider::ResourceIdMap
& ResourceProvider::GetChildToParentMap(
1344 DCHECK(thread_checker_
.CalledOnValidThread());
1345 ChildMap::const_iterator it
= children_
.find(child
);
1346 DCHECK(it
!= children_
.end());
1347 DCHECK(!it
->second
.marked_for_deletion
);
1348 return it
->second
.child_to_parent_map
;
1351 void ResourceProvider::PrepareSendToParent(const ResourceIdArray
& resources
,
1352 TransferableResourceArray
* list
) {
1353 DCHECK(thread_checker_
.CalledOnValidThread());
1354 GLES2Interface
* gl
= ContextGL();
1355 bool need_sync_point
= false;
1356 for (ResourceIdArray::const_iterator it
= resources
.begin();
1357 it
!= resources
.end();
1359 TransferableResource resource
;
1360 TransferResource(gl
, *it
, &resource
);
1361 if (!resource
.mailbox_holder
.sync_point
&& !resource
.is_software
)
1362 need_sync_point
= true;
1363 ++resources_
.find(*it
)->second
.exported_count
;
1364 list
->push_back(resource
);
1366 if (need_sync_point
) {
1367 GLuint sync_point
= gl
->InsertSyncPointCHROMIUM();
1368 for (TransferableResourceArray::iterator it
= list
->begin();
1371 if (!it
->mailbox_holder
.sync_point
)
1372 it
->mailbox_holder
.sync_point
= sync_point
;
1377 void ResourceProvider::ReceiveFromChild(
1378 int child
, const TransferableResourceArray
& resources
) {
1379 DCHECK(thread_checker_
.CalledOnValidThread());
1380 GLES2Interface
* gl
= ContextGL();
1381 Child
& child_info
= children_
.find(child
)->second
;
1382 DCHECK(!child_info
.marked_for_deletion
);
1383 for (TransferableResourceArray::const_iterator it
= resources
.begin();
1384 it
!= resources
.end();
1386 ResourceIdMap::iterator resource_in_map_it
=
1387 child_info
.child_to_parent_map
.find(it
->id
);
1388 if (resource_in_map_it
!= child_info
.child_to_parent_map
.end()) {
1389 Resource
& resource
= resources_
[resource_in_map_it
->second
];
1390 resource
.marked_for_deletion
= false;
1391 resource
.imported_count
++;
1395 if ((!it
->is_software
&& !gl
) ||
1396 (it
->is_software
&& !shared_bitmap_manager_
)) {
1397 TRACE_EVENT0("cc", "ResourceProvider::ReceiveFromChild dropping invalid");
1398 ReturnedResourceArray to_return
;
1399 to_return
.push_back(it
->ToReturnedResource());
1400 child_info
.return_callback
.Run(to_return
,
1401 blocking_main_thread_task_runner_
);
1405 ResourceId local_id
= next_id_
++;
1406 Resource
& resource
= resources_
[local_id
];
1407 if (it
->is_software
) {
1409 Resource(it
->mailbox_holder
.mailbox
, it
->size
, Resource::DELEGATED
,
1410 GL_LINEAR
, it
->is_repeated
? GL_REPEAT
: GL_CLAMP_TO_EDGE
);
1412 resource
= Resource(0, it
->size
, Resource::DELEGATED
,
1413 it
->mailbox_holder
.texture_target
, it
->filter
, 0,
1414 it
->is_repeated
? GL_REPEAT
: GL_CLAMP_TO_EDGE
,
1415 TEXTURE_HINT_IMMUTABLE
, it
->format
);
1416 resource
.mailbox
= TextureMailbox(it
->mailbox_holder
.mailbox
,
1417 it
->mailbox_holder
.texture_target
,
1418 it
->mailbox_holder
.sync_point
);
1420 resource
.child_id
= child
;
1421 // Don't allocate a texture for a child.
1422 resource
.allocated
= true;
1423 resource
.imported_count
= 1;
1424 resource
.allow_overlay
= it
->allow_overlay
;
1425 child_info
.parent_to_child_map
[local_id
] = it
->id
;
1426 child_info
.child_to_parent_map
[it
->id
] = local_id
;
1430 void ResourceProvider::DeclareUsedResourcesFromChild(
1432 const ResourceIdArray
& resources_from_child
) {
1433 DCHECK(thread_checker_
.CalledOnValidThread());
1435 ChildMap::iterator child_it
= children_
.find(child
);
1436 DCHECK(child_it
!= children_
.end());
1437 Child
& child_info
= child_it
->second
;
1438 DCHECK(!child_info
.marked_for_deletion
);
1439 child_info
.in_use_resources
.clear();
1441 for (size_t i
= 0; i
< resources_from_child
.size(); ++i
) {
1442 ResourceIdMap::iterator it
=
1443 child_info
.child_to_parent_map
.find(resources_from_child
[i
]);
1444 DCHECK(it
!= child_info
.child_to_parent_map
.end());
1446 ResourceId local_id
= it
->second
;
1447 DCHECK(!resources_
[local_id
].marked_for_deletion
);
1448 child_info
.in_use_resources
.insert(local_id
);
1451 ResourceIdArray unused
;
1452 for (ResourceIdMap::iterator it
= child_info
.child_to_parent_map
.begin();
1453 it
!= child_info
.child_to_parent_map
.end();
1455 ResourceId local_id
= it
->second
;
1456 bool resource_is_in_use
= child_info
.in_use_resources
.count(local_id
) > 0;
1457 if (!resource_is_in_use
)
1458 unused
.push_back(local_id
);
1460 DeleteAndReturnUnusedResourcesToChild(child_it
, NORMAL
, unused
);
1464 bool ResourceProvider::CompareResourceMapIteratorsByChildId(
1465 const std::pair
<ReturnedResource
, ResourceMap::iterator
>& a
,
1466 const std::pair
<ReturnedResource
, ResourceMap::iterator
>& b
) {
1467 const ResourceMap::iterator
& a_it
= a
.second
;
1468 const ResourceMap::iterator
& b_it
= b
.second
;
1469 const Resource
& a_resource
= a_it
->second
;
1470 const Resource
& b_resource
= b_it
->second
;
1471 return a_resource
.child_id
< b_resource
.child_id
;
1474 void ResourceProvider::ReceiveReturnsFromParent(
1475 const ReturnedResourceArray
& resources
) {
1476 DCHECK(thread_checker_
.CalledOnValidThread());
1477 GLES2Interface
* gl
= ContextGL();
1480 ResourceIdArray resources_for_child
;
1482 std::vector
<std::pair
<ReturnedResource
, ResourceMap::iterator
>>
1485 for (ReturnedResourceArray::const_iterator it
= resources
.begin();
1486 it
!= resources
.end();
1488 ResourceId local_id
= it
->id
;
1489 ResourceMap::iterator map_iterator
= resources_
.find(local_id
);
1491 // Resource was already lost (e.g. it belonged to a child that was
1493 if (map_iterator
== resources_
.end())
1496 sorted_resources
.push_back(
1497 std::pair
<ReturnedResource
, ResourceMap::iterator
>(*it
, map_iterator
));
1500 std::sort(sorted_resources
.begin(),
1501 sorted_resources
.end(),
1502 CompareResourceMapIteratorsByChildId
);
1504 ChildMap::iterator child_it
= children_
.end();
1505 for (size_t i
= 0; i
< sorted_resources
.size(); ++i
) {
1506 ReturnedResource
& returned
= sorted_resources
[i
].first
;
1507 ResourceMap::iterator
& map_iterator
= sorted_resources
[i
].second
;
1508 ResourceId local_id
= map_iterator
->first
;
1509 Resource
* resource
= &map_iterator
->second
;
1511 CHECK_GE(resource
->exported_count
, returned
.count
);
1512 resource
->exported_count
-= returned
.count
;
1513 resource
->lost
|= returned
.lost
;
1514 if (resource
->exported_count
)
1517 // Need to wait for the current read lock fence to pass before we can
1518 // recycle this resource.
1519 if (resource
->read_lock_fences_enabled
) {
1520 if (current_read_lock_fence_
.get())
1521 current_read_lock_fence_
->Set();
1522 resource
->read_lock_fence
= current_read_lock_fence_
;
1525 if (returned
.sync_point
) {
1526 DCHECK(!resource
->has_shared_bitmap_id
);
1527 if (resource
->origin
== Resource::INTERNAL
) {
1528 DCHECK(resource
->gl_id
);
1529 gl
->WaitSyncPointCHROMIUM(returned
.sync_point
);
1531 DCHECK(!resource
->gl_id
);
1532 resource
->mailbox
.set_sync_point(returned
.sync_point
);
1536 if (!resource
->marked_for_deletion
)
1539 if (!resource
->child_id
) {
1540 // The resource belongs to this ResourceProvider, so it can be destroyed.
1541 DeleteResourceInternal(map_iterator
, NORMAL
);
1545 DCHECK(resource
->origin
== Resource::DELEGATED
);
1546 // Delete the resource and return it to the child it came from one.
1547 if (resource
->child_id
!= child_id
) {
1549 DCHECK_NE(resources_for_child
.size(), 0u);
1550 DCHECK(child_it
!= children_
.end());
1551 DeleteAndReturnUnusedResourcesToChild(child_it
, NORMAL
,
1552 resources_for_child
);
1553 resources_for_child
.clear();
1556 child_it
= children_
.find(resource
->child_id
);
1557 DCHECK(child_it
!= children_
.end());
1558 child_id
= resource
->child_id
;
1560 resources_for_child
.push_back(local_id
);
1564 DCHECK_NE(resources_for_child
.size(), 0u);
1565 DCHECK(child_it
!= children_
.end());
1566 DeleteAndReturnUnusedResourcesToChild(child_it
, NORMAL
,
1567 resources_for_child
);
1571 void ResourceProvider::TransferResource(GLES2Interface
* gl
,
1573 TransferableResource
* resource
) {
1574 Resource
* source
= GetResource(id
);
1575 DCHECK(!source
->locked_for_write
);
1576 DCHECK(!source
->lock_for_read_count
);
1577 DCHECK(source
->origin
!= Resource::EXTERNAL
|| source
->mailbox
.IsValid());
1578 DCHECK(source
->allocated
);
1580 resource
->format
= source
->format
;
1581 resource
->mailbox_holder
.texture_target
= source
->target
;
1582 resource
->filter
= source
->filter
;
1583 resource
->size
= source
->size
;
1584 resource
->is_repeated
= (source
->wrap_mode
== GL_REPEAT
);
1585 resource
->allow_overlay
= source
->allow_overlay
;
1587 if (source
->type
== RESOURCE_TYPE_BITMAP
) {
1588 resource
->mailbox_holder
.mailbox
= source
->shared_bitmap_id
;
1589 resource
->is_software
= true;
1590 } else if (!source
->mailbox
.IsValid()) {
1592 DCHECK(source
->gl_id
);
1593 DCHECK(source
->origin
== Resource::INTERNAL
);
1594 if (source
->image_id
) {
1595 DCHECK(source
->dirty_image
);
1596 BindImageForSampling(source
);
1598 // This is a resource allocated by the compositor, we need to produce it.
1599 // Don't set a sync point, the caller will do it.
1600 gl
->GenMailboxCHROMIUM(resource
->mailbox_holder
.mailbox
.name
);
1601 gl
->ProduceTextureDirectCHROMIUM(source
->gl_id
,
1602 resource
->mailbox_holder
.texture_target
,
1603 resource
->mailbox_holder
.mailbox
.name
);
1605 source
->mailbox
= TextureMailbox(resource
->mailbox_holder
);
1607 DCHECK(source
->mailbox
.IsTexture());
1608 if (source
->image_id
&& source
->dirty_image
) {
1609 DCHECK(source
->gl_id
);
1610 DCHECK(source
->origin
== Resource::INTERNAL
);
1611 gl
->BindTexture(resource
->mailbox_holder
.texture_target
, source
->gl_id
);
1612 BindImageForSampling(source
);
1614 // This is either an external resource, or a compositor resource that we
1615 // already exported. Make sure to forward the sync point that we were given.
1616 resource
->mailbox_holder
.mailbox
= source
->mailbox
.mailbox();
1617 resource
->mailbox_holder
.texture_target
= source
->mailbox
.target();
1618 resource
->mailbox_holder
.sync_point
= source
->mailbox
.sync_point();
1619 source
->mailbox
.set_sync_point(0);
1623 void ResourceProvider::DeleteAndReturnUnusedResourcesToChild(
1624 ChildMap::iterator child_it
,
1626 const ResourceIdArray
& unused
) {
1627 DCHECK(thread_checker_
.CalledOnValidThread());
1628 DCHECK(child_it
!= children_
.end());
1629 Child
* child_info
= &child_it
->second
;
1631 if (unused
.empty() && !child_info
->marked_for_deletion
)
1634 ReturnedResourceArray to_return
;
1636 GLES2Interface
* gl
= ContextGL();
1637 bool need_sync_point
= false;
1638 for (size_t i
= 0; i
< unused
.size(); ++i
) {
1639 ResourceId local_id
= unused
[i
];
1641 ResourceMap::iterator it
= resources_
.find(local_id
);
1642 CHECK(it
!= resources_
.end());
1643 Resource
& resource
= it
->second
;
1645 DCHECK(!resource
.locked_for_write
);
1646 DCHECK_EQ(0u, child_info
->in_use_resources
.count(local_id
));
1647 DCHECK(child_info
->parent_to_child_map
.count(local_id
));
1649 ResourceId child_id
= child_info
->parent_to_child_map
[local_id
];
1650 DCHECK(child_info
->child_to_parent_map
.count(child_id
));
1654 (resource
.type
== RESOURCE_TYPE_GL_TEXTURE
&& lost_output_surface_
);
1655 if (resource
.exported_count
> 0 || resource
.lock_for_read_count
> 0) {
1656 if (style
!= FOR_SHUTDOWN
) {
1657 // Defer this until we receive the resource back from the parent or
1658 // the read lock is released.
1659 resource
.marked_for_deletion
= true;
1663 // We still have an exported_count, so we'll have to lose it.
1667 if (gl
&& resource
.filter
!= resource
.original_filter
) {
1668 DCHECK(resource
.target
);
1669 DCHECK(resource
.gl_id
);
1671 gl
->BindTexture(resource
.target
, resource
.gl_id
);
1672 gl
->TexParameteri(resource
.target
, GL_TEXTURE_MIN_FILTER
,
1673 resource
.original_filter
);
1674 gl
->TexParameteri(resource
.target
, GL_TEXTURE_MAG_FILTER
,
1675 resource
.original_filter
);
1678 ReturnedResource returned
;
1679 returned
.id
= child_id
;
1680 returned
.sync_point
= resource
.mailbox
.sync_point();
1681 if (!returned
.sync_point
&& resource
.type
== RESOURCE_TYPE_GL_TEXTURE
)
1682 need_sync_point
= true;
1683 returned
.count
= resource
.imported_count
;
1684 returned
.lost
= is_lost
;
1685 to_return
.push_back(returned
);
1687 child_info
->parent_to_child_map
.erase(local_id
);
1688 child_info
->child_to_parent_map
.erase(child_id
);
1689 resource
.imported_count
= 0;
1690 DeleteResourceInternal(it
, style
);
1692 if (need_sync_point
) {
1694 GLuint sync_point
= gl
->InsertSyncPointCHROMIUM();
1695 for (size_t i
= 0; i
< to_return
.size(); ++i
) {
1696 if (!to_return
[i
].sync_point
)
1697 to_return
[i
].sync_point
= sync_point
;
1701 if (!to_return
.empty())
1702 child_info
->return_callback
.Run(to_return
,
1703 blocking_main_thread_task_runner_
);
1705 if (child_info
->marked_for_deletion
&&
1706 child_info
->parent_to_child_map
.empty()) {
1707 DCHECK(child_info
->child_to_parent_map
.empty());
1708 children_
.erase(child_it
);
1712 void ResourceProvider::AcquirePixelBuffer(ResourceId id
) {
1713 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug"),
1714 "ResourceProvider::AcquirePixelBuffer");
1716 Resource
* resource
= GetResource(id
);
1717 DCHECK(resource
->origin
== Resource::INTERNAL
);
1718 DCHECK_EQ(resource
->exported_count
, 0);
1719 DCHECK(!resource
->image_id
);
1720 DCHECK_NE(ETC1
, resource
->format
);
1722 DCHECK_EQ(RESOURCE_TYPE_GL_TEXTURE
, resource
->type
);
1723 GLES2Interface
* gl
= ContextGL();
1725 if (!resource
->gl_pixel_buffer_id
)
1726 resource
->gl_pixel_buffer_id
= buffer_id_allocator_
->NextId();
1727 gl
->BindBuffer(GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM
,
1728 resource
->gl_pixel_buffer_id
);
1729 unsigned bytes_per_pixel
= BitsPerPixel(resource
->format
) / 8;
1730 gl
->BufferData(GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM
,
1731 resource
->size
.height() *
1732 RoundUp(bytes_per_pixel
* resource
->size
.width(), 4u),
1735 gl
->BindBuffer(GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM
, 0);
1738 void ResourceProvider::ReleasePixelBuffer(ResourceId id
) {
1739 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug"),
1740 "ResourceProvider::ReleasePixelBuffer");
1742 Resource
* resource
= GetResource(id
);
1743 DCHECK(resource
->origin
== Resource::INTERNAL
);
1744 DCHECK_EQ(resource
->exported_count
, 0);
1745 DCHECK(!resource
->image_id
);
1747 // The pixel buffer can be released while there is a pending "set pixels"
1748 // if completion has been forced. Any shared memory associated with this
1749 // pixel buffer will not be freed until the waitAsyncTexImage2DCHROMIUM
1750 // command has been processed on the service side. It is also safe to
1751 // reuse any query id associated with this resource before they complete
1752 // as each new query has a unique submit count.
1753 if (resource
->pending_set_pixels
) {
1754 DCHECK(resource
->set_pixels_completion_forced
);
1755 resource
->pending_set_pixels
= false;
1756 resource
->locked_for_write
= false;
1759 DCHECK_EQ(RESOURCE_TYPE_GL_TEXTURE
, resource
->type
);
1760 if (!resource
->gl_pixel_buffer_id
)
1762 GLES2Interface
* gl
= ContextGL();
1764 gl
->BindBuffer(GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM
,
1765 resource
->gl_pixel_buffer_id
);
1767 GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM
, 0, NULL
, GL_DYNAMIC_DRAW
);
1768 gl
->BindBuffer(GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM
, 0);
1771 uint8_t* ResourceProvider::MapPixelBuffer(ResourceId id
, int* stride
) {
1772 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug"),
1773 "ResourceProvider::MapPixelBuffer");
1775 Resource
* resource
= GetResource(id
);
1776 DCHECK(resource
->origin
== Resource::INTERNAL
);
1777 DCHECK_EQ(resource
->exported_count
, 0);
1778 DCHECK(!resource
->image_id
);
1781 DCHECK_EQ(RESOURCE_TYPE_GL_TEXTURE
, resource
->type
);
1782 GLES2Interface
* gl
= ContextGL();
1784 DCHECK(resource
->gl_pixel_buffer_id
);
1785 gl
->BindBuffer(GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM
,
1786 resource
->gl_pixel_buffer_id
);
1787 uint8_t* image
= static_cast<uint8_t*>(gl
->MapBufferCHROMIUM(
1788 GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM
, GL_WRITE_ONLY
));
1789 gl
->BindBuffer(GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM
, 0);
1790 // Buffer is required to be 4-byte aligned.
1791 CHECK(!(reinterpret_cast<intptr_t>(image
) & 3));
1795 void ResourceProvider::UnmapPixelBuffer(ResourceId id
) {
1796 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug"),
1797 "ResourceProvider::UnmapPixelBuffer");
1799 Resource
* resource
= GetResource(id
);
1800 DCHECK(resource
->origin
== Resource::INTERNAL
);
1801 DCHECK_EQ(resource
->exported_count
, 0);
1802 DCHECK(!resource
->image_id
);
1804 DCHECK_EQ(RESOURCE_TYPE_GL_TEXTURE
, resource
->type
);
1805 GLES2Interface
* gl
= ContextGL();
1807 DCHECK(resource
->gl_pixel_buffer_id
);
1808 gl
->BindBuffer(GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM
,
1809 resource
->gl_pixel_buffer_id
);
1810 gl
->UnmapBufferCHROMIUM(GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM
);
1811 gl
->BindBuffer(GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM
, 0);
1814 GLenum
ResourceProvider::BindForSampling(ResourceId resource_id
,
1817 DCHECK(thread_checker_
.CalledOnValidThread());
1818 GLES2Interface
* gl
= ContextGL();
1819 ResourceMap::iterator it
= resources_
.find(resource_id
);
1820 DCHECK(it
!= resources_
.end());
1821 Resource
* resource
= &it
->second
;
1822 DCHECK(resource
->lock_for_read_count
);
1823 DCHECK(!resource
->locked_for_write
|| resource
->set_pixels_completion_forced
);
1825 ScopedSetActiveTexture
scoped_active_tex(gl
, unit
);
1826 GLenum target
= resource
->target
;
1827 gl
->BindTexture(target
, resource
->gl_id
);
1828 if (filter
!= resource
->filter
) {
1829 gl
->TexParameteri(target
, GL_TEXTURE_MIN_FILTER
, filter
);
1830 gl
->TexParameteri(target
, GL_TEXTURE_MAG_FILTER
, filter
);
1831 resource
->filter
= filter
;
1834 if (resource
->image_id
&& resource
->dirty_image
)
1835 BindImageForSampling(resource
);
1840 void ResourceProvider::BeginSetPixels(ResourceId id
) {
1841 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug"),
1842 "ResourceProvider::BeginSetPixels");
1844 Resource
* resource
= GetResource(id
);
1845 DCHECK(!resource
->pending_set_pixels
);
1847 LazyCreate(resource
);
1848 DCHECK(resource
->origin
== Resource::INTERNAL
);
1849 DCHECK(resource
->gl_id
|| resource
->allocated
);
1850 DCHECK(ReadLockFenceHasPassed(resource
));
1851 DCHECK(!resource
->image_id
);
1853 bool allocate
= !resource
->allocated
;
1854 resource
->allocated
= true;
1857 DCHECK_EQ(RESOURCE_TYPE_GL_TEXTURE
, resource
->type
);
1858 DCHECK(resource
->gl_id
);
1859 GLES2Interface
* gl
= ContextGL();
1861 DCHECK(resource
->gl_pixel_buffer_id
);
1862 DCHECK_EQ(resource
->target
, static_cast<GLenum
>(GL_TEXTURE_2D
));
1863 gl
->BindTexture(GL_TEXTURE_2D
, resource
->gl_id
);
1864 gl
->BindBuffer(GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM
,
1865 resource
->gl_pixel_buffer_id
);
1866 if (!resource
->gl_upload_query_id
)
1867 gl
->GenQueriesEXT(1, &resource
->gl_upload_query_id
);
1868 gl
->BeginQueryEXT(GL_ASYNC_PIXEL_UNPACK_COMPLETED_CHROMIUM
,
1869 resource
->gl_upload_query_id
);
1871 gl
->AsyncTexImage2DCHROMIUM(GL_TEXTURE_2D
,
1873 GLInternalFormat(resource
->format
),
1874 resource
->size
.width(),
1875 resource
->size
.height(),
1877 GLDataFormat(resource
->format
),
1878 GLDataType(resource
->format
),
1881 gl
->AsyncTexSubImage2DCHROMIUM(GL_TEXTURE_2D
,
1885 resource
->size
.width(),
1886 resource
->size
.height(),
1887 GLDataFormat(resource
->format
),
1888 GLDataType(resource
->format
),
1891 gl
->EndQueryEXT(GL_ASYNC_PIXEL_UNPACK_COMPLETED_CHROMIUM
);
1892 gl
->BindBuffer(GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM
, 0);
1894 resource
->pending_set_pixels
= true;
1895 resource
->set_pixels_completion_forced
= false;
1898 void ResourceProvider::ForceSetPixelsToComplete(ResourceId id
) {
1899 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug"),
1900 "ResourceProvider::ForceSetPixelsToComplete");
1902 Resource
* resource
= GetResource(id
);
1904 DCHECK(resource
->locked_for_write
);
1905 DCHECK(resource
->pending_set_pixels
);
1906 DCHECK(!resource
->set_pixels_completion_forced
);
1908 if (resource
->gl_id
) {
1909 GLES2Interface
* gl
= ContextGL();
1910 gl
->BindTexture(GL_TEXTURE_2D
, resource
->gl_id
);
1911 gl
->WaitAsyncTexImage2DCHROMIUM(GL_TEXTURE_2D
);
1912 gl
->BindTexture(GL_TEXTURE_2D
, 0);
1915 resource
->set_pixels_completion_forced
= true;
1918 bool ResourceProvider::DidSetPixelsComplete(ResourceId id
) {
1919 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug"),
1920 "ResourceProvider::DidSetPixelsComplete");
1922 Resource
* resource
= GetResource(id
);
1924 DCHECK(resource
->locked_for_write
);
1925 DCHECK(resource
->pending_set_pixels
);
1927 if (resource
->gl_id
) {
1928 GLES2Interface
* gl
= ContextGL();
1930 DCHECK(resource
->gl_upload_query_id
);
1931 GLuint complete
= 1;
1932 gl
->GetQueryObjectuivEXT(
1933 resource
->gl_upload_query_id
, GL_QUERY_RESULT_AVAILABLE_EXT
, &complete
);
1938 resource
->pending_set_pixels
= false;
1939 UnlockForWrite(resource
);
1941 // Async set pixels commands are not necessarily processed in-sequence with
1942 // drawing commands. Read lock fences are required to ensure that async
1943 // commands don't access the resource while used for drawing.
1944 resource
->read_lock_fences_enabled
= true;
1949 void ResourceProvider::CreateForTesting(ResourceId id
) {
1950 LazyCreate(GetResource(id
));
1953 GLenum
ResourceProvider::TargetForTesting(ResourceId id
) {
1954 Resource
* resource
= GetResource(id
);
1955 return resource
->target
;
1958 void ResourceProvider::LazyCreate(Resource
* resource
) {
1959 if (resource
->type
!= RESOURCE_TYPE_GL_TEXTURE
||
1960 resource
->origin
!= Resource::INTERNAL
)
1963 if (resource
->gl_id
)
1966 DCHECK(resource
->texture_pool
);
1967 DCHECK(resource
->origin
== Resource::INTERNAL
);
1968 DCHECK(!resource
->mailbox
.IsValid());
1969 resource
->gl_id
= texture_id_allocator_
->NextId();
1971 GLES2Interface
* gl
= ContextGL();
1974 // Create and set texture properties. Allocation is delayed until needed.
1975 gl
->BindTexture(resource
->target
, resource
->gl_id
);
1976 gl
->TexParameteri(resource
->target
, GL_TEXTURE_MIN_FILTER
,
1977 resource
->original_filter
);
1978 gl
->TexParameteri(resource
->target
, GL_TEXTURE_MAG_FILTER
,
1979 resource
->original_filter
);
1980 gl
->TexParameteri(resource
->target
, GL_TEXTURE_WRAP_S
, resource
->wrap_mode
);
1981 gl
->TexParameteri(resource
->target
, GL_TEXTURE_WRAP_T
, resource
->wrap_mode
);
1982 gl
->TexParameteri(resource
->target
, GL_TEXTURE_POOL_CHROMIUM
,
1983 resource
->texture_pool
);
1984 if (use_texture_usage_hint_
&& (resource
->hint
& TEXTURE_HINT_FRAMEBUFFER
)) {
1985 gl
->TexParameteri(resource
->target
, GL_TEXTURE_USAGE_ANGLE
,
1986 GL_FRAMEBUFFER_ATTACHMENT_ANGLE
);
1990 void ResourceProvider::AllocateForTesting(ResourceId id
) {
1991 LazyAllocate(GetResource(id
));
1994 void ResourceProvider::LazyAllocate(Resource
* resource
) {
1996 if (resource
->allocated
)
1998 LazyCreate(resource
);
1999 if (!resource
->gl_id
)
2001 resource
->allocated
= true;
2002 GLES2Interface
* gl
= ContextGL();
2003 gfx::Size
& size
= resource
->size
;
2004 DCHECK_EQ(resource
->target
, static_cast<GLenum
>(GL_TEXTURE_2D
));
2005 ResourceFormat format
= resource
->format
;
2006 gl
->BindTexture(GL_TEXTURE_2D
, resource
->gl_id
);
2007 if (use_texture_storage_ext_
&&
2008 IsFormatSupportedForStorage(format
, use_texture_format_bgra_
) &&
2009 (resource
->hint
& TEXTURE_HINT_IMMUTABLE
)) {
2010 GLenum storage_format
= TextureToStorageFormat(format
);
2011 gl
->TexStorage2DEXT(GL_TEXTURE_2D
, 1, storage_format
, size
.width(),
2014 // ETC1 does not support preallocation.
2015 if (format
!= ETC1
) {
2016 gl
->TexImage2D(GL_TEXTURE_2D
, 0, GLInternalFormat(format
), size
.width(),
2017 size
.height(), 0, GLDataFormat(format
), GLDataType(format
),
2023 void ResourceProvider::BindImageForSampling(Resource
* resource
) {
2024 GLES2Interface
* gl
= ContextGL();
2025 DCHECK(resource
->gl_id
);
2026 DCHECK(resource
->image_id
);
2028 // Release image currently bound to texture.
2029 if (resource
->bound_image_id
)
2030 gl
->ReleaseTexImage2DCHROMIUM(resource
->target
, resource
->bound_image_id
);
2031 gl
->BindTexImage2DCHROMIUM(resource
->target
, resource
->image_id
);
2032 resource
->bound_image_id
= resource
->image_id
;
2033 resource
->dirty_image
= false;
2036 void ResourceProvider::CopyResource(ResourceId source_id
, ResourceId dest_id
) {
2037 TRACE_EVENT0("cc", "ResourceProvider::CopyResource");
2039 Resource
* source_resource
= GetResource(source_id
);
2040 DCHECK(!source_resource
->lock_for_read_count
);
2041 DCHECK(source_resource
->origin
== Resource::INTERNAL
);
2042 DCHECK_EQ(source_resource
->exported_count
, 0);
2043 DCHECK_EQ(RESOURCE_TYPE_GL_TEXTURE
, source_resource
->type
);
2044 DCHECK(source_resource
->allocated
);
2045 LazyCreate(source_resource
);
2047 Resource
* dest_resource
= GetResource(dest_id
);
2048 DCHECK(!dest_resource
->locked_for_write
);
2049 DCHECK(!dest_resource
->lock_for_read_count
);
2050 DCHECK(dest_resource
->origin
== Resource::INTERNAL
);
2051 DCHECK_EQ(dest_resource
->exported_count
, 0);
2052 DCHECK_EQ(RESOURCE_TYPE_GL_TEXTURE
, dest_resource
->type
);
2053 LazyAllocate(dest_resource
);
2055 DCHECK_EQ(source_resource
->type
, dest_resource
->type
);
2056 DCHECK_EQ(source_resource
->format
, dest_resource
->format
);
2057 DCHECK(source_resource
->size
== dest_resource
->size
);
2059 GLES2Interface
* gl
= ContextGL();
2061 if (source_resource
->image_id
&& source_resource
->dirty_image
) {
2062 gl
->BindTexture(source_resource
->target
, source_resource
->gl_id
);
2063 BindImageForSampling(source_resource
);
2065 if (use_sync_query_
) {
2066 if (!source_resource
->gl_read_lock_query_id
)
2067 gl
->GenQueriesEXT(1, &source_resource
->gl_read_lock_query_id
);
2068 #if defined(OS_CHROMEOS)
2069 // TODO(reveman): This avoids a performance problem on some ChromeOS
2070 // devices. This needs to be removed to support native GpuMemoryBuffer
2071 // implementations. crbug.com/436314
2072 gl
->BeginQueryEXT(GL_COMMANDS_ISSUED_CHROMIUM
,
2073 source_resource
->gl_read_lock_query_id
);
2075 gl
->BeginQueryEXT(GL_COMMANDS_COMPLETED_CHROMIUM
,
2076 source_resource
->gl_read_lock_query_id
);
2079 DCHECK(!dest_resource
->image_id
);
2080 dest_resource
->allocated
= true;
2081 gl
->CopySubTextureCHROMIUM(dest_resource
->target
, source_resource
->gl_id
,
2082 dest_resource
->gl_id
, 0, 0);
2083 if (source_resource
->gl_read_lock_query_id
) {
2084 // End query and create a read lock fence that will prevent access to
2085 // source resource until CopySubTextureCHROMIUM command has completed.
2086 #if defined(OS_CHROMEOS)
2087 gl
->EndQueryEXT(GL_COMMANDS_ISSUED_CHROMIUM
);
2089 gl
->EndQueryEXT(GL_COMMANDS_COMPLETED_CHROMIUM
);
2091 source_resource
->read_lock_fence
= make_scoped_refptr(
2092 new CopyTextureFence(gl
, source_resource
->gl_read_lock_query_id
));
2094 // Create a SynchronousFence when CHROMIUM_sync_query extension is missing.
2095 // Try to use one synchronous fence for as many CopyResource operations as
2096 // possible as that reduce the number of times we have to synchronize with
2098 if (!synchronous_fence_
.get() || synchronous_fence_
->has_synchronized())
2099 synchronous_fence_
= make_scoped_refptr(new SynchronousFence(gl
));
2100 source_resource
->read_lock_fence
= synchronous_fence_
;
2101 source_resource
->read_lock_fence
->Set();
2105 void ResourceProvider::WaitSyncPointIfNeeded(ResourceId id
) {
2106 Resource
* resource
= GetResource(id
);
2107 DCHECK_EQ(resource
->exported_count
, 0);
2108 DCHECK(resource
->allocated
);
2109 if (resource
->type
!= RESOURCE_TYPE_GL_TEXTURE
|| resource
->gl_id
)
2111 if (!resource
->mailbox
.sync_point())
2113 DCHECK(resource
->mailbox
.IsValid());
2114 GLES2Interface
* gl
= ContextGL();
2116 gl
->WaitSyncPointCHROMIUM(resource
->mailbox
.sync_point());
2117 resource
->mailbox
.set_sync_point(0);
2120 void ResourceProvider::WaitReadLockIfNeeded(ResourceId id
) {
2121 Resource
* resource
= GetResource(id
);
2122 DCHECK_EQ(resource
->exported_count
, 0);
2123 if (!resource
->read_lock_fence
.get())
2126 resource
->read_lock_fence
->Wait();
2129 GLint
ResourceProvider::GetActiveTextureUnit(GLES2Interface
* gl
) {
2130 GLint active_unit
= 0;
2131 gl
->GetIntegerv(GL_ACTIVE_TEXTURE
, &active_unit
);
2135 void ResourceProvider::ValidateResource(ResourceId id
) {
2136 DCHECK(thread_checker_
.CalledOnValidThread());
2138 ResourceMap::iterator it
= resources_
.find(id
);
2139 CHECK(it
!= resources_
.end());
2142 GLES2Interface
* ResourceProvider::ContextGL() const {
2143 ContextProvider
* context_provider
= output_surface_
->context_provider();
2144 return context_provider
? context_provider
->ContextGL() : NULL
;
2147 class GrContext
* ResourceProvider::GrContext(bool worker_context
) const {
2148 ContextProvider
* context_provider
=
2149 worker_context
? output_surface_
->worker_context_provider()
2150 : output_surface_
->context_provider();
2151 return context_provider
? context_provider
->GrContext() : NULL
;