1 // Copyright 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "cc/resources/resource_provider.h"
10 #include "base/containers/hash_tables.h"
11 #include "base/metrics/histogram.h"
12 #include "base/numerics/safe_math.h"
13 #include "base/stl_util.h"
14 #include "base/strings/string_split.h"
15 #include "base/strings/string_util.h"
16 #include "base/trace_event/trace_event.h"
17 #include "cc/base/math_util.h"
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/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 "third_party/skia/include/gpu/GrTextureProvider.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_
);
51 DCHECK_LE(id_allocation_chunk_size_
,
52 static_cast<size_t>(std::numeric_limits
<int>::max()));
56 const size_t id_allocation_chunk_size_
;
57 scoped_ptr
<GLuint
[]> ids_
;
58 size_t next_id_index_
;
63 GLenum
TextureToStorageFormat(ResourceFormat format
) {
64 GLenum storage_format
= GL_RGBA8_OES
;
69 storage_format
= GL_BGRA8_EXT
;
81 return storage_format
;
84 bool IsFormatSupportedForStorage(ResourceFormat format
, bool use_bgra
) {
101 GrPixelConfig
ToGrPixelConfig(ResourceFormat format
) {
104 return kRGBA_8888_GrPixelConfig
;
106 return kBGRA_8888_GrPixelConfig
;
108 return kRGBA_4444_GrPixelConfig
;
112 DCHECK(false) << "Unsupported resource format.";
113 return kSkia8888_GrPixelConfig
;
116 gfx::GpuMemoryBuffer::Format
ToGpuMemoryBufferFormat(ResourceFormat format
) {
119 return gfx::GpuMemoryBuffer::RGBA_8888
;
121 return gfx::GpuMemoryBuffer::BGRA_8888
;
123 return gfx::GpuMemoryBuffer::RGBA_4444
;
132 return gfx::GpuMemoryBuffer::RGBA_8888
;
135 class ScopedSetActiveTexture
{
137 ScopedSetActiveTexture(GLES2Interface
* gl
, GLenum unit
)
138 : gl_(gl
), unit_(unit
) {
139 DCHECK_EQ(GL_TEXTURE0
, ResourceProvider::GetActiveTextureUnit(gl_
));
141 if (unit_
!= GL_TEXTURE0
)
142 gl_
->ActiveTexture(unit_
);
145 ~ScopedSetActiveTexture() {
146 // Active unit being GL_TEXTURE0 is effectively the ground state.
147 if (unit_
!= GL_TEXTURE0
)
148 gl_
->ActiveTexture(GL_TEXTURE0
);
156 class TextureIdAllocator
: public IdAllocator
{
158 TextureIdAllocator(GLES2Interface
* gl
,
159 size_t texture_id_allocation_chunk_size
)
160 : IdAllocator(gl
, texture_id_allocation_chunk_size
) {}
161 ~TextureIdAllocator() override
{
163 static_cast<int>(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(static_cast<int>(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
{
187 static_cast<int>(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(static_cast<int>(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() {}
249 ResourceProvider::Resource::Resource(GLuint texture_id
,
250 const gfx::Size
& size
,
257 ResourceFormat format
)
260 gl_pixel_buffer_id(0),
261 gl_upload_query_id(0),
262 gl_read_lock_query_id(0),
264 lock_for_read_count(0),
268 locked_for_write(false),
270 marked_for_deletion(false),
271 pending_set_pixels(false),
272 set_pixels_completion_forced(false),
274 read_lock_fences_enabled(false),
275 has_shared_bitmap_id(false),
276 read_lock_fence(NULL
),
280 original_filter(filter
),
284 texture_pool(texture_pool
),
285 wrap_mode(wrap_mode
),
287 type(RESOURCE_TYPE_GL_TEXTURE
),
290 gpu_memory_buffer(NULL
) {
291 DCHECK(wrap_mode
== GL_CLAMP_TO_EDGE
|| wrap_mode
== GL_REPEAT
);
292 DCHECK_EQ(origin
== INTERNAL
, !!texture_pool
);
295 ResourceProvider::Resource::Resource(uint8_t* pixels
,
296 SharedBitmap
* bitmap
,
297 const gfx::Size
& size
,
303 gl_pixel_buffer_id(0),
304 gl_upload_query_id(0),
305 gl_read_lock_query_id(0),
307 lock_for_read_count(0),
311 locked_for_write(false),
313 marked_for_deletion(false),
314 pending_set_pixels(false),
315 set_pixels_completion_forced(false),
317 read_lock_fences_enabled(false),
318 has_shared_bitmap_id(!!bitmap
),
319 read_lock_fence(NULL
),
323 original_filter(filter
),
328 wrap_mode(wrap_mode
),
329 hint(TEXTURE_HINT_IMMUTABLE
),
330 type(RESOURCE_TYPE_BITMAP
),
332 shared_bitmap(bitmap
),
333 gpu_memory_buffer(NULL
) {
334 DCHECK(wrap_mode
== GL_CLAMP_TO_EDGE
|| wrap_mode
== GL_REPEAT
);
335 DCHECK(origin
== DELEGATED
|| pixels
);
337 shared_bitmap_id
= bitmap
->id();
340 ResourceProvider::Resource::Resource(const SharedBitmapId
& bitmap_id
,
341 const gfx::Size
& size
,
347 gl_pixel_buffer_id(0),
348 gl_upload_query_id(0),
349 gl_read_lock_query_id(0),
351 lock_for_read_count(0),
355 locked_for_write(false),
357 marked_for_deletion(false),
358 pending_set_pixels(false),
359 set_pixels_completion_forced(false),
361 read_lock_fences_enabled(false),
362 has_shared_bitmap_id(true),
363 read_lock_fence(NULL
),
367 original_filter(filter
),
372 wrap_mode(wrap_mode
),
373 hint(TEXTURE_HINT_IMMUTABLE
),
374 type(RESOURCE_TYPE_BITMAP
),
376 shared_bitmap_id(bitmap_id
),
378 gpu_memory_buffer(NULL
) {
379 DCHECK(wrap_mode
== GL_CLAMP_TO_EDGE
|| wrap_mode
== GL_REPEAT
);
382 ResourceProvider::Child::Child()
383 : marked_for_deletion(false), needs_sync_points(true) {
386 ResourceProvider::Child::~Child() {}
388 scoped_ptr
<ResourceProvider
> ResourceProvider::Create(
389 OutputSurface
* output_surface
,
390 SharedBitmapManager
* shared_bitmap_manager
,
391 gpu::GpuMemoryBufferManager
* gpu_memory_buffer_manager
,
392 BlockingTaskRunner
* blocking_main_thread_task_runner
,
393 int highp_threshold_min
,
394 bool use_rgba_4444_texture_format
,
395 size_t id_allocation_chunk_size
,
396 bool use_persistent_map_for_gpu_memory_buffers
) {
397 scoped_ptr
<ResourceProvider
> resource_provider(new ResourceProvider(
398 output_surface
, shared_bitmap_manager
, gpu_memory_buffer_manager
,
399 blocking_main_thread_task_runner
, highp_threshold_min
,
400 use_rgba_4444_texture_format
, id_allocation_chunk_size
,
401 use_persistent_map_for_gpu_memory_buffers
));
402 resource_provider
->Initialize();
403 return resource_provider
;
406 ResourceProvider::~ResourceProvider() {
407 while (!children_
.empty())
408 DestroyChildInternal(children_
.begin(), FOR_SHUTDOWN
);
409 while (!resources_
.empty())
410 DeleteResourceInternal(resources_
.begin(), FOR_SHUTDOWN
);
412 GLES2Interface
* gl
= ContextGL();
413 if (default_resource_type_
!= RESOURCE_TYPE_GL_TEXTURE
) {
414 // We are not in GL mode, but double check before returning.
421 // Check that all GL resources has been deleted.
422 for (ResourceMap::const_iterator itr
= resources_
.begin();
423 itr
!= resources_
.end(); ++itr
) {
424 DCHECK_NE(RESOURCE_TYPE_GL_TEXTURE
, itr
->second
.type
);
426 #endif // DCHECK_IS_ON()
428 texture_id_allocator_
= nullptr;
429 buffer_id_allocator_
= nullptr;
433 bool ResourceProvider::InUseByConsumer(ResourceId id
) {
434 Resource
* resource
= GetResource(id
);
435 return resource
->lock_for_read_count
> 0 || resource
->exported_count
> 0 ||
439 bool ResourceProvider::IsLost(ResourceId id
) {
440 Resource
* resource
= GetResource(id
);
441 return resource
->lost
;
444 void ResourceProvider::LoseResourceForTesting(ResourceId id
) {
445 Resource
* resource
= GetResource(id
);
447 resource
->lost
= true;
450 ResourceId
ResourceProvider::CreateResource(const gfx::Size
& size
,
453 ResourceFormat format
) {
454 DCHECK(!size
.IsEmpty());
455 switch (default_resource_type_
) {
456 case RESOURCE_TYPE_GL_TEXTURE
:
457 return CreateGLTexture(size
,
459 GL_TEXTURE_POOL_UNMANAGED_CHROMIUM
,
463 case RESOURCE_TYPE_BITMAP
:
464 DCHECK_EQ(RGBA_8888
, format
);
465 return CreateBitmap(size
, wrap_mode
);
468 LOG(FATAL
) << "Invalid default resource type.";
472 ResourceId
ResourceProvider::CreateManagedResource(const gfx::Size
& size
,
476 ResourceFormat format
) {
477 DCHECK(!size
.IsEmpty());
478 switch (default_resource_type_
) {
479 case RESOURCE_TYPE_GL_TEXTURE
:
480 return CreateGLTexture(size
,
482 GL_TEXTURE_POOL_MANAGED_CHROMIUM
,
486 case RESOURCE_TYPE_BITMAP
:
487 DCHECK_EQ(RGBA_8888
, format
);
488 return CreateBitmap(size
, wrap_mode
);
491 LOG(FATAL
) << "Invalid default resource type.";
495 ResourceId
ResourceProvider::CreateGLTexture(const gfx::Size
& size
,
500 ResourceFormat format
) {
501 DCHECK_LE(size
.width(), max_texture_size_
);
502 DCHECK_LE(size
.height(), max_texture_size_
);
503 DCHECK(thread_checker_
.CalledOnValidThread());
505 ResourceId id
= next_id_
++;
506 Resource
* resource
= InsertResource(
507 id
, Resource(0, size
, Resource::INTERNAL
, target
, GL_LINEAR
, texture_pool
,
508 wrap_mode
, hint
, format
));
509 resource
->allocated
= false;
513 ResourceId
ResourceProvider::CreateBitmap(const gfx::Size
& size
,
515 DCHECK(thread_checker_
.CalledOnValidThread());
517 scoped_ptr
<SharedBitmap
> bitmap
=
518 shared_bitmap_manager_
->AllocateSharedBitmap(size
);
519 uint8_t* pixels
= bitmap
->pixels();
522 ResourceId id
= next_id_
++;
524 InsertResource(id
, Resource(pixels
, bitmap
.release(), size
,
525 Resource::INTERNAL
, GL_LINEAR
, wrap_mode
));
526 resource
->allocated
= true;
530 ResourceId
ResourceProvider::CreateResourceFromIOSurface(
531 const gfx::Size
& size
,
532 unsigned io_surface_id
) {
533 DCHECK(thread_checker_
.CalledOnValidThread());
535 ResourceId id
= next_id_
++;
536 Resource
* resource
= InsertResource(
537 id
, Resource(0, gfx::Size(), Resource::INTERNAL
, GL_TEXTURE_RECTANGLE_ARB
,
538 GL_LINEAR
, GL_TEXTURE_POOL_UNMANAGED_CHROMIUM
,
539 GL_CLAMP_TO_EDGE
, TEXTURE_HINT_IMMUTABLE
, RGBA_8888
));
540 LazyCreate(resource
);
541 GLES2Interface
* gl
= ContextGL();
543 gl
->BindTexture(GL_TEXTURE_RECTANGLE_ARB
, resource
->gl_id
);
544 gl
->TexImageIOSurface2DCHROMIUM(
545 GL_TEXTURE_RECTANGLE_ARB
, size
.width(), size
.height(), io_surface_id
, 0);
546 resource
->allocated
= true;
550 ResourceId
ResourceProvider::CreateResourceFromTextureMailbox(
551 const TextureMailbox
& mailbox
,
552 scoped_ptr
<SingleReleaseCallbackImpl
> release_callback_impl
,
553 bool read_lock_fences_enabled
) {
554 DCHECK(thread_checker_
.CalledOnValidThread());
555 // Just store the information. Mailbox will be consumed in LockForRead().
556 ResourceId id
= next_id_
++;
557 DCHECK(mailbox
.IsValid());
558 Resource
* resource
= nullptr;
559 if (mailbox
.IsTexture()) {
560 resource
= InsertResource(
561 id
, Resource(0, gfx::Size(), Resource::EXTERNAL
, mailbox
.target(),
562 mailbox
.nearest_neighbor() ? GL_NEAREST
: GL_LINEAR
, 0,
563 GL_CLAMP_TO_EDGE
, TEXTURE_HINT_IMMUTABLE
, RGBA_8888
));
565 DCHECK(mailbox
.IsSharedMemory());
566 SharedBitmap
* shared_bitmap
= mailbox
.shared_bitmap();
567 uint8_t* pixels
= shared_bitmap
->pixels();
569 resource
= InsertResource(
570 id
, Resource(pixels
, shared_bitmap
, mailbox
.size_in_pixels(),
571 Resource::EXTERNAL
, GL_LINEAR
, GL_CLAMP_TO_EDGE
));
573 resource
->allocated
= true;
574 resource
->mailbox
= mailbox
;
575 resource
->release_callback_impl
=
576 base::Bind(&SingleReleaseCallbackImpl::Run
,
577 base::Owned(release_callback_impl
.release()));
578 resource
->read_lock_fences_enabled
= read_lock_fences_enabled
;
582 ResourceId
ResourceProvider::CreateResourceFromTextureMailbox(
583 const TextureMailbox
& mailbox
,
584 scoped_ptr
<SingleReleaseCallbackImpl
> release_callback_impl
) {
585 return CreateResourceFromTextureMailbox(mailbox
, release_callback_impl
.Pass(),
589 void ResourceProvider::DeleteResource(ResourceId id
) {
590 DCHECK(thread_checker_
.CalledOnValidThread());
591 ResourceMap::iterator it
= resources_
.find(id
);
592 CHECK(it
!= resources_
.end());
593 Resource
* resource
= &it
->second
;
594 DCHECK(!resource
->marked_for_deletion
);
595 DCHECK_EQ(resource
->imported_count
, 0);
596 DCHECK(resource
->pending_set_pixels
|| !resource
->locked_for_write
);
598 if (resource
->exported_count
> 0 || resource
->lock_for_read_count
> 0 ||
599 !ReadLockFenceHasPassed(resource
)) {
600 resource
->marked_for_deletion
= true;
603 DeleteResourceInternal(it
, NORMAL
);
607 void ResourceProvider::DeleteResourceInternal(ResourceMap::iterator it
,
609 TRACE_EVENT0("cc", "ResourceProvider::DeleteResourceInternal");
610 Resource
* resource
= &it
->second
;
611 bool lost_resource
= resource
->lost
;
613 DCHECK(resource
->exported_count
== 0 || style
!= NORMAL
);
614 if (style
== FOR_SHUTDOWN
&& resource
->exported_count
> 0)
615 lost_resource
= true;
617 if (resource
->image_id
) {
618 DCHECK(resource
->origin
== Resource::INTERNAL
);
619 GLES2Interface
* gl
= ContextGL();
621 gl
->DestroyImageCHROMIUM(resource
->image_id
);
623 if (resource
->gl_upload_query_id
) {
624 DCHECK(resource
->origin
== Resource::INTERNAL
);
625 GLES2Interface
* gl
= ContextGL();
627 gl
->DeleteQueriesEXT(1, &resource
->gl_upload_query_id
);
629 if (resource
->gl_read_lock_query_id
) {
630 DCHECK(resource
->origin
== Resource::INTERNAL
);
631 GLES2Interface
* gl
= ContextGL();
633 gl
->DeleteQueriesEXT(1, &resource
->gl_read_lock_query_id
);
635 if (resource
->gl_pixel_buffer_id
) {
636 DCHECK(resource
->origin
== Resource::INTERNAL
);
637 GLES2Interface
* gl
= ContextGL();
639 gl
->DeleteBuffers(1, &resource
->gl_pixel_buffer_id
);
641 if (resource
->origin
== Resource::EXTERNAL
) {
642 DCHECK(resource
->mailbox
.IsValid());
643 GLuint sync_point
= resource
->mailbox
.sync_point();
644 if (resource
->type
== RESOURCE_TYPE_GL_TEXTURE
) {
645 DCHECK(resource
->mailbox
.IsTexture());
646 lost_resource
|= lost_output_surface_
;
647 GLES2Interface
* gl
= ContextGL();
649 if (resource
->gl_id
) {
650 gl
->DeleteTextures(1, &resource
->gl_id
);
653 sync_point
= gl
->InsertSyncPointCHROMIUM();
656 DCHECK(resource
->mailbox
.IsSharedMemory());
657 resource
->shared_bitmap
= nullptr;
658 resource
->pixels
= nullptr;
660 resource
->release_callback_impl
.Run(
661 sync_point
, lost_resource
, blocking_main_thread_task_runner_
);
663 if (resource
->gl_id
) {
664 GLES2Interface
* gl
= ContextGL();
666 gl
->DeleteTextures(1, &resource
->gl_id
);
669 if (resource
->shared_bitmap
) {
670 DCHECK(resource
->origin
!= Resource::EXTERNAL
);
671 DCHECK_EQ(RESOURCE_TYPE_BITMAP
, resource
->type
);
672 delete resource
->shared_bitmap
;
673 resource
->pixels
= NULL
;
675 if (resource
->pixels
) {
676 DCHECK(resource
->origin
== Resource::INTERNAL
);
677 delete[] resource
->pixels
;
678 resource
->pixels
= NULL
;
680 if (resource
->gpu_memory_buffer
) {
681 DCHECK(resource
->origin
== Resource::INTERNAL
);
682 delete resource
->gpu_memory_buffer
;
683 resource
->gpu_memory_buffer
= NULL
;
685 resources_
.erase(it
);
688 ResourceProvider::ResourceType
ResourceProvider::GetResourceType(
690 return GetResource(id
)->type
;
693 void ResourceProvider::CopyToResource(ResourceId id
,
694 const uint8_t* image
,
695 const gfx::Size
& image_size
) {
696 Resource
* resource
= GetResource(id
);
697 DCHECK(!resource
->locked_for_write
);
698 DCHECK(!resource
->lock_for_read_count
);
699 DCHECK(resource
->origin
== Resource::INTERNAL
);
700 DCHECK_EQ(resource
->exported_count
, 0);
701 DCHECK(ReadLockFenceHasPassed(resource
));
702 LazyAllocate(resource
);
704 DCHECK_EQ(image_size
.width(), resource
->size
.width());
705 DCHECK_EQ(image_size
.height(), resource
->size
.height());
707 if (resource
->type
== RESOURCE_TYPE_BITMAP
) {
708 DCHECK_EQ(RESOURCE_TYPE_BITMAP
, resource
->type
);
709 DCHECK(resource
->allocated
);
710 DCHECK_EQ(RGBA_8888
, resource
->format
);
711 SkImageInfo source_info
=
712 SkImageInfo::MakeN32Premul(image_size
.width(), image_size
.height());
713 size_t image_stride
= image_size
.width() * 4;
715 ScopedWriteLockSoftware
lock(this, id
);
716 SkCanvas
dest(lock
.sk_bitmap());
717 dest
.writePixels(source_info
, image
, image_stride
, 0, 0);
719 DCHECK(resource
->gl_id
);
720 DCHECK(!resource
->pending_set_pixels
);
721 DCHECK_EQ(resource
->target
, static_cast<GLenum
>(GL_TEXTURE_2D
));
722 GLES2Interface
* gl
= ContextGL();
724 gl
->BindTexture(GL_TEXTURE_2D
, resource
->gl_id
);
726 if (resource
->format
== ETC1
) {
727 base::CheckedNumeric
<int> num_bytes
= BitsPerPixel(ETC1
);
728 num_bytes
*= image_size
.width();
729 num_bytes
*= image_size
.height();
731 gl
->CompressedTexImage2D(GL_TEXTURE_2D
, 0, GLInternalFormat(ETC1
),
732 image_size
.width(), image_size
.height(), 0,
733 num_bytes
.ValueOrDie(), image
);
735 gl
->TexSubImage2D(GL_TEXTURE_2D
, 0, 0, 0, image_size
.width(),
736 image_size
.height(), GLDataFormat(resource
->format
),
737 GLDataType(resource
->format
), image
);
742 ResourceProvider::Resource
* ResourceProvider::InsertResource(
744 const Resource
& resource
) {
745 std::pair
<ResourceMap::iterator
, bool> result
=
746 resources_
.insert(ResourceMap::value_type(id
, resource
));
747 DCHECK(result
.second
);
748 return &result
.first
->second
;
751 ResourceProvider::Resource
* ResourceProvider::GetResource(ResourceId id
) {
752 DCHECK(thread_checker_
.CalledOnValidThread());
754 ResourceMap::iterator it
= resources_
.find(id
);
755 DCHECK(it
!= resources_
.end());
759 const ResourceProvider::Resource
* ResourceProvider::LockForRead(ResourceId id
) {
760 Resource
* resource
= GetResource(id
);
761 DCHECK(!resource
->locked_for_write
||
762 resource
->set_pixels_completion_forced
) <<
763 "locked for write: " << resource
->locked_for_write
<<
764 " pixels completion forced: " << resource
->set_pixels_completion_forced
;
765 DCHECK_EQ(resource
->exported_count
, 0);
766 // Uninitialized! Call SetPixels or LockForWrite first.
767 DCHECK(resource
->allocated
);
769 LazyCreate(resource
);
771 if (resource
->type
== RESOURCE_TYPE_GL_TEXTURE
&& !resource
->gl_id
) {
772 DCHECK(resource
->origin
!= Resource::INTERNAL
);
773 DCHECK(resource
->mailbox
.IsTexture());
775 // Mailbox sync_points must be processed by a call to
776 // WaitSyncPointIfNeeded() prior to calling LockForRead().
777 DCHECK(!resource
->mailbox
.sync_point());
779 GLES2Interface
* gl
= ContextGL();
781 resource
->gl_id
= gl
->CreateAndConsumeTextureCHROMIUM(
782 resource
->mailbox
.target(), resource
->mailbox
.name());
785 if (!resource
->pixels
&& resource
->has_shared_bitmap_id
&&
786 shared_bitmap_manager_
) {
787 scoped_ptr
<SharedBitmap
> bitmap
=
788 shared_bitmap_manager_
->GetSharedBitmapFromId(
789 resource
->size
, resource
->shared_bitmap_id
);
791 resource
->shared_bitmap
= bitmap
.release();
792 resource
->pixels
= resource
->shared_bitmap
->pixels();
796 resource
->lock_for_read_count
++;
797 if (resource
->read_lock_fences_enabled
) {
798 if (current_read_lock_fence_
.get())
799 current_read_lock_fence_
->Set();
800 resource
->read_lock_fence
= current_read_lock_fence_
;
806 void ResourceProvider::UnlockForRead(ResourceId id
) {
807 DCHECK(thread_checker_
.CalledOnValidThread());
808 ResourceMap::iterator it
= resources_
.find(id
);
809 CHECK(it
!= resources_
.end());
811 Resource
* resource
= &it
->second
;
812 DCHECK_GT(resource
->lock_for_read_count
, 0);
813 DCHECK_EQ(resource
->exported_count
, 0);
814 resource
->lock_for_read_count
--;
815 if (resource
->marked_for_deletion
&& !resource
->lock_for_read_count
) {
816 if (!resource
->child_id
) {
817 // The resource belongs to this ResourceProvider, so it can be destroyed.
818 DeleteResourceInternal(it
, NORMAL
);
820 ChildMap::iterator child_it
= children_
.find(resource
->child_id
);
821 ResourceIdArray unused
;
822 unused
.push_back(id
);
823 DeleteAndReturnUnusedResourcesToChild(child_it
, NORMAL
, unused
);
828 ResourceProvider::Resource
* ResourceProvider::LockForWrite(ResourceId id
) {
829 Resource
* resource
= GetResource(id
);
830 DCHECK(CanLockForWrite(id
));
832 resource
->locked_for_write
= true;
836 bool ResourceProvider::CanLockForWrite(ResourceId id
) {
837 Resource
* resource
= GetResource(id
);
838 return !resource
->locked_for_write
&& !resource
->lock_for_read_count
&&
839 !resource
->exported_count
&& resource
->origin
== Resource::INTERNAL
&&
840 !resource
->lost
&& ReadLockFenceHasPassed(resource
);
843 void ResourceProvider::UnlockForWrite(ResourceProvider::Resource
* resource
) {
844 DCHECK(resource
->locked_for_write
);
845 DCHECK_EQ(resource
->exported_count
, 0);
846 DCHECK(resource
->origin
== Resource::INTERNAL
);
847 resource
->locked_for_write
= false;
850 void ResourceProvider::EnableReadLockFencesForTesting(ResourceId id
) {
851 Resource
* resource
= GetResource(id
);
853 resource
->read_lock_fences_enabled
= true;
856 ResourceProvider::ScopedReadLockGL::ScopedReadLockGL(
857 ResourceProvider
* resource_provider
,
858 ResourceId resource_id
)
859 : resource_provider_(resource_provider
),
860 resource_id_(resource_id
),
861 resource_(resource_provider
->LockForRead(resource_id
)) {
865 ResourceProvider::ScopedReadLockGL::~ScopedReadLockGL() {
866 resource_provider_
->UnlockForRead(resource_id_
);
869 ResourceProvider::ScopedSamplerGL::ScopedSamplerGL(
870 ResourceProvider
* resource_provider
,
871 ResourceId resource_id
,
873 : ScopedReadLockGL(resource_provider
, resource_id
),
875 target_(resource_provider
->BindForSampling(resource_id
, unit_
, filter
)) {
878 ResourceProvider::ScopedSamplerGL::ScopedSamplerGL(
879 ResourceProvider
* resource_provider
,
880 ResourceId resource_id
,
883 : ScopedReadLockGL(resource_provider
, resource_id
),
885 target_(resource_provider
->BindForSampling(resource_id
, unit_
, filter
)) {
888 ResourceProvider::ScopedSamplerGL::~ScopedSamplerGL() {
891 ResourceProvider::ScopedWriteLockGL::ScopedWriteLockGL(
892 ResourceProvider
* resource_provider
,
893 ResourceId resource_id
)
894 : resource_provider_(resource_provider
),
895 resource_(resource_provider
->LockForWrite(resource_id
)) {
896 resource_provider_
->LazyAllocate(resource_
);
897 texture_id_
= resource_
->gl_id
;
901 ResourceProvider::ScopedWriteLockGL::~ScopedWriteLockGL() {
902 resource_provider_
->UnlockForWrite(resource_
);
905 void ResourceProvider::PopulateSkBitmapWithResource(
906 SkBitmap
* sk_bitmap
, const Resource
* resource
) {
907 DCHECK_EQ(RGBA_8888
, resource
->format
);
908 SkImageInfo info
= SkImageInfo::MakeN32Premul(resource
->size
.width(),
909 resource
->size
.height());
910 sk_bitmap
->installPixels(info
, resource
->pixels
, info
.minRowBytes());
913 ResourceProvider::ScopedReadLockSoftware::ScopedReadLockSoftware(
914 ResourceProvider
* resource_provider
,
915 ResourceId resource_id
)
916 : resource_provider_(resource_provider
), resource_id_(resource_id
) {
917 const Resource
* resource
= resource_provider
->LockForRead(resource_id
);
918 wrap_mode_
= resource
->wrap_mode
;
919 ResourceProvider::PopulateSkBitmapWithResource(&sk_bitmap_
, resource
);
922 ResourceProvider::ScopedReadLockSoftware::~ScopedReadLockSoftware() {
923 resource_provider_
->UnlockForRead(resource_id_
);
926 ResourceProvider::ScopedWriteLockSoftware::ScopedWriteLockSoftware(
927 ResourceProvider
* resource_provider
,
928 ResourceId resource_id
)
929 : resource_provider_(resource_provider
),
930 resource_(resource_provider
->LockForWrite(resource_id
)) {
931 ResourceProvider::PopulateSkBitmapWithResource(&sk_bitmap_
, resource_
);
935 ResourceProvider::ScopedWriteLockSoftware::~ScopedWriteLockSoftware() {
936 DCHECK(thread_checker_
.CalledOnValidThread());
937 resource_provider_
->UnlockForWrite(resource_
);
940 ResourceProvider::ScopedWriteLockGpuMemoryBuffer::
941 ScopedWriteLockGpuMemoryBuffer(ResourceProvider
* resource_provider
,
942 ResourceId resource_id
)
943 : resource_provider_(resource_provider
),
944 resource_(resource_provider
->LockForWrite(resource_id
)),
945 gpu_memory_buffer_manager_(resource_provider
->gpu_memory_buffer_manager_
),
946 gpu_memory_buffer_(nullptr),
947 size_(resource_
->size
),
948 format_(resource_
->format
) {
949 DCHECK_EQ(RESOURCE_TYPE_GL_TEXTURE
, resource_
->type
);
950 std::swap(gpu_memory_buffer_
, resource_
->gpu_memory_buffer
);
953 ResourceProvider::ScopedWriteLockGpuMemoryBuffer::
954 ~ScopedWriteLockGpuMemoryBuffer() {
955 DCHECK(thread_checker_
.CalledOnValidThread());
956 resource_provider_
->UnlockForWrite(resource_
);
957 if (!gpu_memory_buffer_
)
960 resource_provider_
->LazyCreate(resource_
);
962 if (!resource_
->image_id
) {
963 GLES2Interface
* gl
= resource_provider_
->ContextGL();
966 #if defined(OS_CHROMEOS)
967 // TODO(reveman): GL_COMMANDS_ISSUED_CHROMIUM is used for synchronization
968 // on ChromeOS to avoid some performance issues. This only works with
969 // shared memory backed buffers. crbug.com/436314
970 DCHECK_EQ(gpu_memory_buffer_
->GetHandle().type
, gfx::SHARED_MEMORY_BUFFER
);
973 resource_
->image_id
= gl
->CreateImageCHROMIUM(
974 gpu_memory_buffer_
->AsClientBuffer(), size_
.width(), size_
.height(),
975 GLInternalFormat(resource_
->format
));
978 std::swap(resource_
->gpu_memory_buffer
, gpu_memory_buffer_
);
979 resource_
->allocated
= true;
980 resource_
->dirty_image
= true;
982 // GpuMemoryBuffer provides direct access to the memory used by the GPU.
983 // Read lock fences are required to ensure that we're not trying to map a
984 // buffer that is currently in-use by the GPU.
985 resource_
->read_lock_fences_enabled
= true;
988 gfx::GpuMemoryBuffer
*
989 ResourceProvider::ScopedWriteLockGpuMemoryBuffer::GetGpuMemoryBuffer() {
990 if (gpu_memory_buffer_
)
991 return gpu_memory_buffer_
;
992 gfx::GpuMemoryBuffer::Usage usage
=
993 resource_provider_
->use_persistent_map_for_gpu_memory_buffers()
994 ? gfx::GpuMemoryBuffer::PERSISTENT_MAP
995 : gfx::GpuMemoryBuffer::MAP
;
996 scoped_ptr
<gfx::GpuMemoryBuffer
> gpu_memory_buffer
=
997 gpu_memory_buffer_manager_
->AllocateGpuMemoryBuffer(
998 size_
, ToGpuMemoryBufferFormat(format_
), usage
);
999 gpu_memory_buffer_
= gpu_memory_buffer
.release();
1000 return gpu_memory_buffer_
;
1003 ResourceProvider::ScopedWriteLockGr::ScopedWriteLockGr(
1004 ResourceProvider
* resource_provider
,
1005 ResourceId resource_id
)
1006 : resource_provider_(resource_provider
),
1007 resource_(resource_provider
->LockForWrite(resource_id
)) {
1008 DCHECK(thread_checker_
.CalledOnValidThread());
1009 resource_provider_
->LazyAllocate(resource_
);
1012 ResourceProvider::ScopedWriteLockGr::~ScopedWriteLockGr() {
1013 DCHECK(thread_checker_
.CalledOnValidThread());
1014 DCHECK(resource_
->locked_for_write
);
1015 resource_provider_
->UnlockForWrite(resource_
);
1018 void ResourceProvider::ScopedWriteLockGr::InitSkSurface(
1019 bool use_distance_field_text
,
1020 bool can_use_lcd_text
,
1021 int msaa_sample_count
) {
1022 DCHECK(resource_
->locked_for_write
);
1024 GrBackendTextureDesc desc
;
1025 desc
.fFlags
= kRenderTarget_GrBackendTextureFlag
;
1026 desc
.fWidth
= resource_
->size
.width();
1027 desc
.fHeight
= resource_
->size
.height();
1028 desc
.fConfig
= ToGrPixelConfig(resource_
->format
);
1029 desc
.fOrigin
= kTopLeft_GrSurfaceOrigin
;
1030 desc
.fTextureHandle
= resource_
->gl_id
;
1031 desc
.fSampleCnt
= msaa_sample_count
;
1033 bool use_worker_context
= true;
1034 class GrContext
* gr_context
=
1035 resource_provider_
->GrContext(use_worker_context
);
1037 use_distance_field_text
? SkSurfaceProps::kUseDistanceFieldFonts_Flag
: 0;
1038 // Use unknown pixel geometry to disable LCD text.
1039 SkSurfaceProps
surface_props(flags
, kUnknown_SkPixelGeometry
);
1040 if (can_use_lcd_text
) {
1041 // LegacyFontHost will get LCD text and skia figures out what type to use.
1043 SkSurfaceProps(flags
, SkSurfaceProps::kLegacyFontHost_InitType
);
1045 sk_surface_
= skia::AdoptRef(
1046 SkSurface::NewWrappedRenderTarget(gr_context
, desc
, &surface_props
));
1049 void ResourceProvider::ScopedWriteLockGr::ReleaseSkSurface() {
1050 sk_surface_
.clear();
1053 ResourceProvider::SynchronousFence::SynchronousFence(
1054 gpu::gles2::GLES2Interface
* gl
)
1055 : gl_(gl
), has_synchronized_(true) {
1058 ResourceProvider::SynchronousFence::~SynchronousFence() {
1061 void ResourceProvider::SynchronousFence::Set() {
1062 has_synchronized_
= false;
1065 bool ResourceProvider::SynchronousFence::HasPassed() {
1066 if (!has_synchronized_
) {
1067 has_synchronized_
= true;
1073 void ResourceProvider::SynchronousFence::Wait() {
1077 void ResourceProvider::SynchronousFence::Synchronize() {
1078 TRACE_EVENT0("cc", "ResourceProvider::SynchronousFence::Synchronize");
1082 ResourceProvider::ResourceProvider(
1083 OutputSurface
* output_surface
,
1084 SharedBitmapManager
* shared_bitmap_manager
,
1085 gpu::GpuMemoryBufferManager
* gpu_memory_buffer_manager
,
1086 BlockingTaskRunner
* blocking_main_thread_task_runner
,
1087 int highp_threshold_min
,
1088 bool use_rgba_4444_texture_format
,
1089 size_t id_allocation_chunk_size
,
1090 bool use_persistent_map_for_gpu_memory_buffers
)
1091 : output_surface_(output_surface
),
1092 shared_bitmap_manager_(shared_bitmap_manager
),
1093 gpu_memory_buffer_manager_(gpu_memory_buffer_manager
),
1094 blocking_main_thread_task_runner_(blocking_main_thread_task_runner
),
1095 lost_output_surface_(false),
1096 highp_threshold_min_(highp_threshold_min
),
1099 default_resource_type_(RESOURCE_TYPE_BITMAP
),
1100 use_texture_storage_ext_(false),
1101 use_texture_format_bgra_(false),
1102 use_texture_usage_hint_(false),
1103 use_compressed_texture_etc1_(false),
1104 yuv_resource_format_(LUMINANCE_8
),
1105 max_texture_size_(0),
1106 best_texture_format_(RGBA_8888
),
1107 best_render_buffer_format_(RGBA_8888
),
1108 use_rgba_4444_texture_format_(use_rgba_4444_texture_format
),
1109 id_allocation_chunk_size_(id_allocation_chunk_size
),
1110 use_sync_query_(false),
1111 use_persistent_map_for_gpu_memory_buffers_(
1112 use_persistent_map_for_gpu_memory_buffers
) {
1113 DCHECK(output_surface_
->HasClient());
1114 DCHECK(id_allocation_chunk_size_
);
1117 void ResourceProvider::Initialize() {
1118 DCHECK(thread_checker_
.CalledOnValidThread());
1120 GLES2Interface
* gl
= ContextGL();
1122 default_resource_type_
= RESOURCE_TYPE_BITMAP
;
1123 // Pick an arbitrary limit here similar to what hardware might.
1124 max_texture_size_
= 16 * 1024;
1125 best_texture_format_
= RGBA_8888
;
1129 DCHECK(!texture_id_allocator_
);
1130 DCHECK(!buffer_id_allocator_
);
1132 const ContextProvider::Capabilities
& caps
=
1133 output_surface_
->context_provider()->ContextCapabilities();
1135 default_resource_type_
= RESOURCE_TYPE_GL_TEXTURE
;
1136 use_texture_storage_ext_
= caps
.gpu
.texture_storage
;
1137 use_texture_format_bgra_
= caps
.gpu
.texture_format_bgra8888
;
1138 use_texture_usage_hint_
= caps
.gpu
.texture_usage
;
1139 use_compressed_texture_etc1_
= caps
.gpu
.texture_format_etc1
;
1140 yuv_resource_format_
= caps
.gpu
.texture_rg
? RED_8
: LUMINANCE_8
;
1141 use_sync_query_
= caps
.gpu
.sync_query
;
1143 max_texture_size_
= 0; // Context expects cleared value.
1144 gl
->GetIntegerv(GL_MAX_TEXTURE_SIZE
, &max_texture_size_
);
1145 best_texture_format_
=
1146 PlatformColor::BestTextureFormat(use_texture_format_bgra_
);
1148 best_render_buffer_format_
=
1149 PlatformColor::BestTextureFormat(caps
.gpu
.render_buffer_format_bgra8888
);
1151 texture_id_allocator_
.reset(
1152 new TextureIdAllocator(gl
, id_allocation_chunk_size_
));
1153 buffer_id_allocator_
.reset(
1154 new BufferIdAllocator(gl
, id_allocation_chunk_size_
));
1157 int ResourceProvider::CreateChild(const ReturnCallback
& return_callback
) {
1158 DCHECK(thread_checker_
.CalledOnValidThread());
1161 child_info
.return_callback
= return_callback
;
1163 int child
= next_child_
++;
1164 children_
[child
] = child_info
;
1168 void ResourceProvider::SetChildNeedsSyncPoints(int child_id
, bool needs
) {
1169 ChildMap::iterator it
= children_
.find(child_id
);
1170 DCHECK(it
!= children_
.end());
1171 it
->second
.needs_sync_points
= needs
;
1174 void ResourceProvider::DestroyChild(int child_id
) {
1175 ChildMap::iterator it
= children_
.find(child_id
);
1176 DCHECK(it
!= children_
.end());
1177 DestroyChildInternal(it
, NORMAL
);
1180 void ResourceProvider::DestroyChildInternal(ChildMap::iterator it
,
1181 DeleteStyle style
) {
1182 DCHECK(thread_checker_
.CalledOnValidThread());
1184 Child
& child
= it
->second
;
1185 DCHECK(style
== FOR_SHUTDOWN
|| !child
.marked_for_deletion
);
1187 ResourceIdArray resources_for_child
;
1189 for (ResourceIdMap::iterator child_it
= child
.child_to_parent_map
.begin();
1190 child_it
!= child
.child_to_parent_map
.end();
1192 ResourceId id
= child_it
->second
;
1193 resources_for_child
.push_back(id
);
1196 child
.marked_for_deletion
= true;
1198 DeleteAndReturnUnusedResourcesToChild(it
, style
, resources_for_child
);
1201 const ResourceProvider::ResourceIdMap
& ResourceProvider::GetChildToParentMap(
1203 DCHECK(thread_checker_
.CalledOnValidThread());
1204 ChildMap::const_iterator it
= children_
.find(child
);
1205 DCHECK(it
!= children_
.end());
1206 DCHECK(!it
->second
.marked_for_deletion
);
1207 return it
->second
.child_to_parent_map
;
1210 void ResourceProvider::PrepareSendToParent(const ResourceIdArray
& resources
,
1211 TransferableResourceArray
* list
) {
1212 DCHECK(thread_checker_
.CalledOnValidThread());
1213 GLES2Interface
* gl
= ContextGL();
1214 bool need_sync_point
= false;
1215 for (ResourceIdArray::const_iterator it
= resources
.begin();
1216 it
!= resources
.end();
1218 TransferableResource resource
;
1219 TransferResource(gl
, *it
, &resource
);
1220 if (!resource
.mailbox_holder
.sync_point
&& !resource
.is_software
)
1221 need_sync_point
= true;
1222 ++resources_
.find(*it
)->second
.exported_count
;
1223 list
->push_back(resource
);
1225 if (need_sync_point
&&
1226 output_surface_
->capabilities().delegated_sync_points_required
) {
1227 GLuint sync_point
= gl
->InsertSyncPointCHROMIUM();
1228 for (TransferableResourceArray::iterator it
= list
->begin();
1231 if (!it
->mailbox_holder
.sync_point
)
1232 it
->mailbox_holder
.sync_point
= sync_point
;
1237 void ResourceProvider::ReceiveFromChild(
1238 int child
, const TransferableResourceArray
& resources
) {
1239 DCHECK(thread_checker_
.CalledOnValidThread());
1240 GLES2Interface
* gl
= ContextGL();
1241 Child
& child_info
= children_
.find(child
)->second
;
1242 DCHECK(!child_info
.marked_for_deletion
);
1243 for (TransferableResourceArray::const_iterator it
= resources
.begin();
1244 it
!= resources
.end();
1246 ResourceIdMap::iterator resource_in_map_it
=
1247 child_info
.child_to_parent_map
.find(it
->id
);
1248 if (resource_in_map_it
!= child_info
.child_to_parent_map
.end()) {
1249 Resource
* resource
= GetResource(resource_in_map_it
->second
);
1250 resource
->marked_for_deletion
= false;
1251 resource
->imported_count
++;
1255 if ((!it
->is_software
&& !gl
) ||
1256 (it
->is_software
&& !shared_bitmap_manager_
)) {
1257 TRACE_EVENT0("cc", "ResourceProvider::ReceiveFromChild dropping invalid");
1258 ReturnedResourceArray to_return
;
1259 to_return
.push_back(it
->ToReturnedResource());
1260 child_info
.return_callback
.Run(to_return
,
1261 blocking_main_thread_task_runner_
);
1265 ResourceId local_id
= next_id_
++;
1266 Resource
* resource
= nullptr;
1267 if (it
->is_software
) {
1268 resource
= InsertResource(
1270 Resource(it
->mailbox_holder
.mailbox
, it
->size
, Resource::DELEGATED
,
1271 GL_LINEAR
, it
->is_repeated
? GL_REPEAT
: GL_CLAMP_TO_EDGE
));
1273 resource
= InsertResource(
1274 local_id
, Resource(0, it
->size
, Resource::DELEGATED
,
1275 it
->mailbox_holder
.texture_target
, it
->filter
, 0,
1276 it
->is_repeated
? GL_REPEAT
: GL_CLAMP_TO_EDGE
,
1277 TEXTURE_HINT_IMMUTABLE
, it
->format
));
1278 resource
->mailbox
= TextureMailbox(it
->mailbox_holder
.mailbox
,
1279 it
->mailbox_holder
.texture_target
,
1280 it
->mailbox_holder
.sync_point
);
1281 resource
->read_lock_fences_enabled
= it
->read_lock_fences_enabled
;
1283 resource
->child_id
= child
;
1284 // Don't allocate a texture for a child.
1285 resource
->allocated
= true;
1286 resource
->imported_count
= 1;
1287 child_info
.parent_to_child_map
[local_id
] = it
->id
;
1288 child_info
.child_to_parent_map
[it
->id
] = local_id
;
1292 void ResourceProvider::DeclareUsedResourcesFromChild(
1294 const ResourceIdSet
& resources_from_child
) {
1295 DCHECK(thread_checker_
.CalledOnValidThread());
1297 ChildMap::iterator child_it
= children_
.find(child
);
1298 DCHECK(child_it
!= children_
.end());
1299 Child
& child_info
= child_it
->second
;
1300 DCHECK(!child_info
.marked_for_deletion
);
1302 ResourceIdArray unused
;
1303 for (ResourceIdMap::iterator it
= child_info
.child_to_parent_map
.begin();
1304 it
!= child_info
.child_to_parent_map
.end();
1306 ResourceId local_id
= it
->second
;
1307 bool resource_is_in_use
= resources_from_child
.count(it
->first
) > 0;
1308 if (!resource_is_in_use
)
1309 unused
.push_back(local_id
);
1311 DeleteAndReturnUnusedResourcesToChild(child_it
, NORMAL
, unused
);
1314 void ResourceProvider::ReceiveReturnsFromParent(
1315 const ReturnedResourceArray
& resources
) {
1316 DCHECK(thread_checker_
.CalledOnValidThread());
1317 GLES2Interface
* gl
= ContextGL();
1319 base::hash_map
<int, ResourceIdArray
> resources_for_child
;
1321 for (const ReturnedResource
& returned
: resources
) {
1322 ResourceId local_id
= returned
.id
;
1323 ResourceMap::iterator map_iterator
= resources_
.find(local_id
);
1324 // Resource was already lost (e.g. it belonged to a child that was
1326 if (map_iterator
== resources_
.end())
1329 Resource
* resource
= &map_iterator
->second
;
1331 CHECK_GE(resource
->exported_count
, returned
.count
);
1332 resource
->exported_count
-= returned
.count
;
1333 resource
->lost
|= returned
.lost
;
1334 if (resource
->exported_count
)
1337 if (returned
.sync_point
) {
1338 DCHECK(!resource
->has_shared_bitmap_id
);
1339 if (resource
->origin
== Resource::INTERNAL
) {
1340 DCHECK(resource
->gl_id
);
1341 gl
->WaitSyncPointCHROMIUM(returned
.sync_point
);
1343 DCHECK(!resource
->gl_id
);
1344 resource
->mailbox
.set_sync_point(returned
.sync_point
);
1348 if (!resource
->marked_for_deletion
)
1351 if (!resource
->child_id
) {
1352 // The resource belongs to this ResourceProvider, so it can be destroyed.
1353 DeleteResourceInternal(map_iterator
, NORMAL
);
1357 DCHECK(resource
->origin
== Resource::DELEGATED
);
1358 resources_for_child
[resource
->child_id
].push_back(local_id
);
1361 for (const auto& children
: resources_for_child
) {
1362 ChildMap::iterator child_it
= children_
.find(children
.first
);
1363 DCHECK(child_it
!= children_
.end());
1364 DeleteAndReturnUnusedResourcesToChild(child_it
, NORMAL
, children
.second
);
1368 void ResourceProvider::TransferResource(GLES2Interface
* gl
,
1370 TransferableResource
* resource
) {
1371 Resource
* source
= GetResource(id
);
1372 DCHECK(!source
->locked_for_write
);
1373 DCHECK(!source
->lock_for_read_count
);
1374 DCHECK(source
->origin
!= Resource::EXTERNAL
|| source
->mailbox
.IsValid());
1375 DCHECK(source
->allocated
);
1377 resource
->format
= source
->format
;
1378 resource
->mailbox_holder
.texture_target
= source
->target
;
1379 resource
->filter
= source
->filter
;
1380 resource
->size
= source
->size
;
1381 resource
->read_lock_fences_enabled
= source
->read_lock_fences_enabled
;
1382 resource
->is_repeated
= (source
->wrap_mode
== GL_REPEAT
);
1384 if (source
->type
== RESOURCE_TYPE_BITMAP
) {
1385 resource
->mailbox_holder
.mailbox
= source
->shared_bitmap_id
;
1386 resource
->is_software
= true;
1387 } else if (!source
->mailbox
.IsValid()) {
1389 DCHECK(source
->gl_id
);
1390 DCHECK(source
->origin
== Resource::INTERNAL
);
1391 if (source
->image_id
) {
1392 DCHECK(source
->dirty_image
);
1393 gl
->BindTexture(resource
->mailbox_holder
.texture_target
, source
->gl_id
);
1394 BindImageForSampling(source
);
1396 // This is a resource allocated by the compositor, we need to produce it.
1397 // Don't set a sync point, the caller will do it.
1398 gl
->GenMailboxCHROMIUM(resource
->mailbox_holder
.mailbox
.name
);
1399 gl
->ProduceTextureDirectCHROMIUM(source
->gl_id
,
1400 resource
->mailbox_holder
.texture_target
,
1401 resource
->mailbox_holder
.mailbox
.name
);
1403 source
->mailbox
= TextureMailbox(resource
->mailbox_holder
);
1405 DCHECK(source
->mailbox
.IsTexture());
1406 if (source
->image_id
&& source
->dirty_image
) {
1407 DCHECK(source
->gl_id
);
1408 DCHECK(source
->origin
== Resource::INTERNAL
);
1409 gl
->BindTexture(resource
->mailbox_holder
.texture_target
, source
->gl_id
);
1410 BindImageForSampling(source
);
1412 // This is either an external resource, or a compositor resource that we
1413 // already exported. Make sure to forward the sync point that we were given.
1414 resource
->mailbox_holder
.mailbox
= source
->mailbox
.mailbox();
1415 resource
->mailbox_holder
.texture_target
= source
->mailbox
.target();
1416 resource
->mailbox_holder
.sync_point
= source
->mailbox
.sync_point();
1417 source
->mailbox
.set_sync_point(0);
1421 void ResourceProvider::DeleteAndReturnUnusedResourcesToChild(
1422 ChildMap::iterator child_it
,
1424 const ResourceIdArray
& unused
) {
1425 DCHECK(thread_checker_
.CalledOnValidThread());
1426 DCHECK(child_it
!= children_
.end());
1427 Child
* child_info
= &child_it
->second
;
1429 if (unused
.empty() && !child_info
->marked_for_deletion
)
1432 ReturnedResourceArray to_return
;
1434 GLES2Interface
* gl
= ContextGL();
1435 bool need_sync_point
= false;
1436 for (size_t i
= 0; i
< unused
.size(); ++i
) {
1437 ResourceId local_id
= unused
[i
];
1439 ResourceMap::iterator it
= resources_
.find(local_id
);
1440 CHECK(it
!= resources_
.end());
1441 Resource
& resource
= it
->second
;
1443 DCHECK(!resource
.locked_for_write
);
1444 DCHECK(child_info
->parent_to_child_map
.count(local_id
));
1446 ResourceId child_id
= child_info
->parent_to_child_map
[local_id
];
1447 DCHECK(child_info
->child_to_parent_map
.count(child_id
));
1451 (resource
.type
== RESOURCE_TYPE_GL_TEXTURE
&& lost_output_surface_
);
1452 if (resource
.exported_count
> 0 || resource
.lock_for_read_count
> 0) {
1453 if (style
!= FOR_SHUTDOWN
) {
1454 // Defer this resource deletion.
1455 resource
.marked_for_deletion
= true;
1458 // We can't postpone the deletion, so we'll have to lose it.
1460 } else if (!ReadLockFenceHasPassed(&resource
)) {
1461 // TODO(dcastagna): see if it's possible to use this logic for
1462 // the branch above too, where the resource is locked or still exported.
1463 if (style
!= FOR_SHUTDOWN
&& !child_info
->marked_for_deletion
) {
1464 // Defer this resource deletion.
1465 resource
.marked_for_deletion
= true;
1468 // We can't postpone the deletion, so we'll have to lose it.
1472 if (gl
&& resource
.filter
!= resource
.original_filter
) {
1473 DCHECK(resource
.target
);
1474 DCHECK(resource
.gl_id
);
1476 gl
->BindTexture(resource
.target
, resource
.gl_id
);
1477 gl
->TexParameteri(resource
.target
, GL_TEXTURE_MIN_FILTER
,
1478 resource
.original_filter
);
1479 gl
->TexParameteri(resource
.target
, GL_TEXTURE_MAG_FILTER
,
1480 resource
.original_filter
);
1483 ReturnedResource returned
;
1484 returned
.id
= child_id
;
1485 returned
.sync_point
= resource
.mailbox
.sync_point();
1486 if (!returned
.sync_point
&& resource
.type
== RESOURCE_TYPE_GL_TEXTURE
)
1487 need_sync_point
= true;
1488 returned
.count
= resource
.imported_count
;
1489 returned
.lost
= is_lost
;
1490 to_return
.push_back(returned
);
1492 child_info
->parent_to_child_map
.erase(local_id
);
1493 child_info
->child_to_parent_map
.erase(child_id
);
1494 resource
.imported_count
= 0;
1495 DeleteResourceInternal(it
, style
);
1497 if (need_sync_point
&& child_info
->needs_sync_points
) {
1499 GLuint sync_point
= gl
->InsertSyncPointCHROMIUM();
1500 for (size_t i
= 0; i
< to_return
.size(); ++i
) {
1501 if (!to_return
[i
].sync_point
)
1502 to_return
[i
].sync_point
= sync_point
;
1506 if (!to_return
.empty())
1507 child_info
->return_callback
.Run(to_return
,
1508 blocking_main_thread_task_runner_
);
1510 if (child_info
->marked_for_deletion
&&
1511 child_info
->parent_to_child_map
.empty()) {
1512 DCHECK(child_info
->child_to_parent_map
.empty());
1513 children_
.erase(child_it
);
1517 void ResourceProvider::AcquirePixelBuffer(ResourceId id
) {
1518 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug"),
1519 "ResourceProvider::AcquirePixelBuffer");
1521 Resource
* resource
= GetResource(id
);
1522 DCHECK(resource
->origin
== Resource::INTERNAL
);
1523 DCHECK_EQ(resource
->exported_count
, 0);
1524 DCHECK(!resource
->image_id
);
1525 DCHECK_NE(ETC1
, resource
->format
);
1527 DCHECK_EQ(RESOURCE_TYPE_GL_TEXTURE
, resource
->type
);
1528 GLES2Interface
* gl
= ContextGL();
1530 if (!resource
->gl_pixel_buffer_id
)
1531 resource
->gl_pixel_buffer_id
= buffer_id_allocator_
->NextId();
1532 gl
->BindBuffer(GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM
,
1533 resource
->gl_pixel_buffer_id
);
1534 unsigned bytes_per_pixel
= BitsPerPixel(resource
->format
) / 8;
1536 GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM
,
1537 resource
->size
.height() *
1538 MathUtil::RoundUp(bytes_per_pixel
* resource
->size
.width(), 4u),
1539 NULL
, GL_DYNAMIC_DRAW
);
1540 gl
->BindBuffer(GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM
, 0);
1543 void ResourceProvider::ReleasePixelBuffer(ResourceId id
) {
1544 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug"),
1545 "ResourceProvider::ReleasePixelBuffer");
1547 Resource
* resource
= GetResource(id
);
1548 DCHECK(resource
->origin
== Resource::INTERNAL
);
1549 DCHECK_EQ(resource
->exported_count
, 0);
1550 DCHECK(!resource
->image_id
);
1552 // The pixel buffer can be released while there is a pending "set pixels"
1553 // if completion has been forced. Any shared memory associated with this
1554 // pixel buffer will not be freed until the waitAsyncTexImage2DCHROMIUM
1555 // command has been processed on the service side. It is also safe to
1556 // reuse any query id associated with this resource before they complete
1557 // as each new query has a unique submit count.
1558 if (resource
->pending_set_pixels
) {
1559 DCHECK(resource
->set_pixels_completion_forced
);
1560 resource
->pending_set_pixels
= false;
1561 resource
->locked_for_write
= false;
1564 DCHECK_EQ(RESOURCE_TYPE_GL_TEXTURE
, resource
->type
);
1565 if (!resource
->gl_pixel_buffer_id
)
1567 GLES2Interface
* gl
= ContextGL();
1569 gl
->BindBuffer(GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM
,
1570 resource
->gl_pixel_buffer_id
);
1572 GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM
, 0, NULL
, GL_DYNAMIC_DRAW
);
1573 gl
->BindBuffer(GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM
, 0);
1576 uint8_t* ResourceProvider::MapPixelBuffer(ResourceId id
, int* stride
) {
1577 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug"),
1578 "ResourceProvider::MapPixelBuffer");
1580 Resource
* resource
= GetResource(id
);
1581 DCHECK(resource
->origin
== Resource::INTERNAL
);
1582 DCHECK_EQ(resource
->exported_count
, 0);
1583 DCHECK(!resource
->image_id
);
1586 DCHECK_EQ(RESOURCE_TYPE_GL_TEXTURE
, resource
->type
);
1587 GLES2Interface
* gl
= ContextGL();
1589 DCHECK(resource
->gl_pixel_buffer_id
);
1590 gl
->BindBuffer(GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM
,
1591 resource
->gl_pixel_buffer_id
);
1592 uint8_t* image
= static_cast<uint8_t*>(gl
->MapBufferCHROMIUM(
1593 GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM
, GL_WRITE_ONLY
));
1594 gl
->BindBuffer(GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM
, 0);
1595 // Buffer is required to be 4-byte aligned.
1596 CHECK(!(reinterpret_cast<intptr_t>(image
) & 3));
1600 void ResourceProvider::UnmapPixelBuffer(ResourceId id
) {
1601 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug"),
1602 "ResourceProvider::UnmapPixelBuffer");
1604 Resource
* resource
= GetResource(id
);
1605 DCHECK(resource
->origin
== Resource::INTERNAL
);
1606 DCHECK_EQ(resource
->exported_count
, 0);
1607 DCHECK(!resource
->image_id
);
1609 DCHECK_EQ(RESOURCE_TYPE_GL_TEXTURE
, resource
->type
);
1610 GLES2Interface
* gl
= ContextGL();
1612 DCHECK(resource
->gl_pixel_buffer_id
);
1613 gl
->BindBuffer(GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM
,
1614 resource
->gl_pixel_buffer_id
);
1615 gl
->UnmapBufferCHROMIUM(GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM
);
1616 gl
->BindBuffer(GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM
, 0);
1619 GLenum
ResourceProvider::BindForSampling(ResourceId resource_id
,
1622 DCHECK(thread_checker_
.CalledOnValidThread());
1623 GLES2Interface
* gl
= ContextGL();
1624 ResourceMap::iterator it
= resources_
.find(resource_id
);
1625 DCHECK(it
!= resources_
.end());
1626 Resource
* resource
= &it
->second
;
1627 DCHECK(resource
->lock_for_read_count
);
1628 DCHECK(!resource
->locked_for_write
|| resource
->set_pixels_completion_forced
);
1630 ScopedSetActiveTexture
scoped_active_tex(gl
, unit
);
1631 GLenum target
= resource
->target
;
1632 gl
->BindTexture(target
, resource
->gl_id
);
1633 if (filter
!= resource
->filter
) {
1634 gl
->TexParameteri(target
, GL_TEXTURE_MIN_FILTER
, filter
);
1635 gl
->TexParameteri(target
, GL_TEXTURE_MAG_FILTER
, filter
);
1636 resource
->filter
= filter
;
1639 if (resource
->image_id
&& resource
->dirty_image
)
1640 BindImageForSampling(resource
);
1645 void ResourceProvider::BeginSetPixels(ResourceId id
) {
1646 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug"),
1647 "ResourceProvider::BeginSetPixels");
1649 Resource
* resource
= GetResource(id
);
1650 DCHECK(!resource
->pending_set_pixels
);
1652 LazyCreate(resource
);
1653 DCHECK(resource
->origin
== Resource::INTERNAL
);
1654 DCHECK(resource
->gl_id
|| resource
->allocated
);
1655 DCHECK(ReadLockFenceHasPassed(resource
));
1656 DCHECK(!resource
->image_id
);
1658 bool allocate
= !resource
->allocated
;
1659 resource
->allocated
= true;
1662 DCHECK_EQ(RESOURCE_TYPE_GL_TEXTURE
, resource
->type
);
1663 DCHECK(resource
->gl_id
);
1664 GLES2Interface
* gl
= ContextGL();
1666 DCHECK(resource
->gl_pixel_buffer_id
);
1667 DCHECK_EQ(resource
->target
, static_cast<GLenum
>(GL_TEXTURE_2D
));
1668 gl
->BindTexture(GL_TEXTURE_2D
, resource
->gl_id
);
1669 gl
->BindBuffer(GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM
,
1670 resource
->gl_pixel_buffer_id
);
1671 if (!resource
->gl_upload_query_id
)
1672 gl
->GenQueriesEXT(1, &resource
->gl_upload_query_id
);
1673 gl
->BeginQueryEXT(GL_ASYNC_PIXEL_UNPACK_COMPLETED_CHROMIUM
,
1674 resource
->gl_upload_query_id
);
1676 gl
->AsyncTexImage2DCHROMIUM(GL_TEXTURE_2D
,
1678 GLInternalFormat(resource
->format
),
1679 resource
->size
.width(),
1680 resource
->size
.height(),
1682 GLDataFormat(resource
->format
),
1683 GLDataType(resource
->format
),
1686 gl
->AsyncTexSubImage2DCHROMIUM(GL_TEXTURE_2D
,
1690 resource
->size
.width(),
1691 resource
->size
.height(),
1692 GLDataFormat(resource
->format
),
1693 GLDataType(resource
->format
),
1696 gl
->EndQueryEXT(GL_ASYNC_PIXEL_UNPACK_COMPLETED_CHROMIUM
);
1697 gl
->BindBuffer(GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM
, 0);
1699 resource
->pending_set_pixels
= true;
1700 resource
->set_pixels_completion_forced
= false;
1703 void ResourceProvider::ForceSetPixelsToComplete(ResourceId id
) {
1704 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug"),
1705 "ResourceProvider::ForceSetPixelsToComplete");
1707 Resource
* resource
= GetResource(id
);
1709 DCHECK(resource
->locked_for_write
);
1710 DCHECK(resource
->pending_set_pixels
);
1711 DCHECK(!resource
->set_pixels_completion_forced
);
1713 if (resource
->gl_id
) {
1714 GLES2Interface
* gl
= ContextGL();
1715 gl
->BindTexture(GL_TEXTURE_2D
, resource
->gl_id
);
1716 gl
->WaitAsyncTexImage2DCHROMIUM(GL_TEXTURE_2D
);
1717 gl
->BindTexture(GL_TEXTURE_2D
, 0);
1720 resource
->set_pixels_completion_forced
= true;
1723 bool ResourceProvider::DidSetPixelsComplete(ResourceId id
) {
1724 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug"),
1725 "ResourceProvider::DidSetPixelsComplete");
1727 Resource
* resource
= GetResource(id
);
1729 DCHECK(resource
->locked_for_write
);
1730 DCHECK(resource
->pending_set_pixels
);
1732 if (resource
->gl_id
) {
1733 GLES2Interface
* gl
= ContextGL();
1735 DCHECK(resource
->gl_upload_query_id
);
1736 GLuint complete
= 1;
1737 gl
->GetQueryObjectuivEXT(
1738 resource
->gl_upload_query_id
, GL_QUERY_RESULT_AVAILABLE_EXT
, &complete
);
1743 resource
->pending_set_pixels
= false;
1744 UnlockForWrite(resource
);
1746 // Async set pixels commands are not necessarily processed in-sequence with
1747 // drawing commands. Read lock fences are required to ensure that async
1748 // commands don't access the resource while used for drawing.
1749 resource
->read_lock_fences_enabled
= true;
1754 void ResourceProvider::CreateForTesting(ResourceId id
) {
1755 LazyCreate(GetResource(id
));
1758 GLenum
ResourceProvider::TargetForTesting(ResourceId id
) {
1759 Resource
* resource
= GetResource(id
);
1760 return resource
->target
;
1763 void ResourceProvider::LazyCreate(Resource
* resource
) {
1764 if (resource
->type
!= RESOURCE_TYPE_GL_TEXTURE
||
1765 resource
->origin
!= Resource::INTERNAL
)
1768 if (resource
->gl_id
)
1771 DCHECK(resource
->texture_pool
);
1772 DCHECK(resource
->origin
== Resource::INTERNAL
);
1773 DCHECK(!resource
->mailbox
.IsValid());
1774 resource
->gl_id
= texture_id_allocator_
->NextId();
1776 GLES2Interface
* gl
= ContextGL();
1779 // Create and set texture properties. Allocation is delayed until needed.
1780 gl
->BindTexture(resource
->target
, resource
->gl_id
);
1781 gl
->TexParameteri(resource
->target
, GL_TEXTURE_MIN_FILTER
,
1782 resource
->original_filter
);
1783 gl
->TexParameteri(resource
->target
, GL_TEXTURE_MAG_FILTER
,
1784 resource
->original_filter
);
1785 gl
->TexParameteri(resource
->target
, GL_TEXTURE_WRAP_S
, resource
->wrap_mode
);
1786 gl
->TexParameteri(resource
->target
, GL_TEXTURE_WRAP_T
, resource
->wrap_mode
);
1787 gl
->TexParameteri(resource
->target
, GL_TEXTURE_POOL_CHROMIUM
,
1788 resource
->texture_pool
);
1789 if (use_texture_usage_hint_
&& (resource
->hint
& TEXTURE_HINT_FRAMEBUFFER
)) {
1790 gl
->TexParameteri(resource
->target
, GL_TEXTURE_USAGE_ANGLE
,
1791 GL_FRAMEBUFFER_ATTACHMENT_ANGLE
);
1795 void ResourceProvider::AllocateForTesting(ResourceId id
) {
1796 LazyAllocate(GetResource(id
));
1799 void ResourceProvider::LazyAllocate(Resource
* resource
) {
1801 if (resource
->allocated
)
1803 LazyCreate(resource
);
1804 if (!resource
->gl_id
)
1806 resource
->allocated
= true;
1807 GLES2Interface
* gl
= ContextGL();
1808 gfx::Size
& size
= resource
->size
;
1809 ResourceFormat format
= resource
->format
;
1810 gl
->BindTexture(resource
->target
, resource
->gl_id
);
1811 if (use_texture_storage_ext_
&&
1812 IsFormatSupportedForStorage(format
, use_texture_format_bgra_
) &&
1813 (resource
->hint
& TEXTURE_HINT_IMMUTABLE
)) {
1814 GLenum storage_format
= TextureToStorageFormat(format
);
1815 gl
->TexStorage2DEXT(resource
->target
, 1, storage_format
, size
.width(),
1818 // ETC1 does not support preallocation.
1819 if (format
!= ETC1
) {
1820 gl
->TexImage2D(resource
->target
, 0, GLInternalFormat(format
),
1821 size
.width(), size
.height(), 0, GLDataFormat(format
),
1822 GLDataType(format
), NULL
);
1827 void ResourceProvider::BindImageForSampling(Resource
* resource
) {
1828 GLES2Interface
* gl
= ContextGL();
1829 DCHECK(resource
->gl_id
);
1830 DCHECK(resource
->image_id
);
1832 // Release image currently bound to texture.
1833 if (resource
->bound_image_id
)
1834 gl
->ReleaseTexImage2DCHROMIUM(resource
->target
, resource
->bound_image_id
);
1835 gl
->BindTexImage2DCHROMIUM(resource
->target
, resource
->image_id
);
1836 resource
->bound_image_id
= resource
->image_id
;
1837 resource
->dirty_image
= false;
1840 void ResourceProvider::CopyResource(ResourceId source_id
,
1842 const gfx::Rect
& rect
) {
1843 TRACE_EVENT0("cc", "ResourceProvider::CopyResource");
1845 Resource
* source_resource
= GetResource(source_id
);
1846 DCHECK(!source_resource
->lock_for_read_count
);
1847 DCHECK(source_resource
->origin
== Resource::INTERNAL
);
1848 DCHECK_EQ(source_resource
->exported_count
, 0);
1849 DCHECK_EQ(RESOURCE_TYPE_GL_TEXTURE
, source_resource
->type
);
1850 LazyAllocate(source_resource
);
1852 Resource
* dest_resource
= GetResource(dest_id
);
1853 DCHECK(!dest_resource
->locked_for_write
);
1854 DCHECK(!dest_resource
->lock_for_read_count
);
1855 DCHECK(dest_resource
->origin
== Resource::INTERNAL
);
1856 DCHECK_EQ(dest_resource
->exported_count
, 0);
1857 DCHECK_EQ(RESOURCE_TYPE_GL_TEXTURE
, dest_resource
->type
);
1858 LazyAllocate(dest_resource
);
1860 DCHECK_EQ(source_resource
->type
, dest_resource
->type
);
1861 DCHECK_EQ(source_resource
->format
, dest_resource
->format
);
1862 DCHECK(source_resource
->size
== dest_resource
->size
);
1863 DCHECK(gfx::Rect(dest_resource
->size
).Contains(rect
));
1865 GLES2Interface
* gl
= ContextGL();
1867 if (source_resource
->image_id
&& source_resource
->dirty_image
) {
1868 gl
->BindTexture(source_resource
->target
, source_resource
->gl_id
);
1869 BindImageForSampling(source_resource
);
1871 if (use_sync_query_
) {
1872 if (!source_resource
->gl_read_lock_query_id
)
1873 gl
->GenQueriesEXT(1, &source_resource
->gl_read_lock_query_id
);
1874 #if defined(OS_CHROMEOS)
1875 // TODO(reveman): This avoids a performance problem on some ChromeOS
1876 // devices. This needs to be removed to support native GpuMemoryBuffer
1877 // implementations. crbug.com/436314
1878 gl
->BeginQueryEXT(GL_COMMANDS_ISSUED_CHROMIUM
,
1879 source_resource
->gl_read_lock_query_id
);
1881 gl
->BeginQueryEXT(GL_COMMANDS_COMPLETED_CHROMIUM
,
1882 source_resource
->gl_read_lock_query_id
);
1885 DCHECK(!dest_resource
->image_id
);
1886 dest_resource
->allocated
= true;
1887 gl
->CopySubTextureCHROMIUM(dest_resource
->target
, source_resource
->gl_id
,
1888 dest_resource
->gl_id
, rect
.x(), rect
.y(), rect
.x(),
1889 rect
.y(), rect
.width(), rect
.height(),
1890 false, false, false);
1891 if (source_resource
->gl_read_lock_query_id
) {
1892 // End query and create a read lock fence that will prevent access to
1893 // source resource until CopySubTextureCHROMIUM command has completed.
1894 #if defined(OS_CHROMEOS)
1895 gl
->EndQueryEXT(GL_COMMANDS_ISSUED_CHROMIUM
);
1897 gl
->EndQueryEXT(GL_COMMANDS_COMPLETED_CHROMIUM
);
1899 source_resource
->read_lock_fence
= make_scoped_refptr(
1900 new CopyTextureFence(gl
, source_resource
->gl_read_lock_query_id
));
1902 // Create a SynchronousFence when CHROMIUM_sync_query extension is missing.
1903 // Try to use one synchronous fence for as many CopyResource operations as
1904 // possible as that reduce the number of times we have to synchronize with
1906 if (!synchronous_fence_
.get() || synchronous_fence_
->has_synchronized())
1907 synchronous_fence_
= make_scoped_refptr(new SynchronousFence(gl
));
1908 source_resource
->read_lock_fence
= synchronous_fence_
;
1909 source_resource
->read_lock_fence
->Set();
1913 void ResourceProvider::WaitSyncPointIfNeeded(ResourceId id
) {
1914 Resource
* resource
= GetResource(id
);
1915 DCHECK_EQ(resource
->exported_count
, 0);
1916 DCHECK(resource
->allocated
);
1917 if (resource
->type
!= RESOURCE_TYPE_GL_TEXTURE
|| resource
->gl_id
)
1919 if (!resource
->mailbox
.sync_point())
1921 DCHECK(resource
->mailbox
.IsValid());
1922 GLES2Interface
* gl
= ContextGL();
1924 gl
->WaitSyncPointCHROMIUM(resource
->mailbox
.sync_point());
1925 resource
->mailbox
.set_sync_point(0);
1928 void ResourceProvider::WaitReadLockIfNeeded(ResourceId id
) {
1929 Resource
* resource
= GetResource(id
);
1930 DCHECK_EQ(resource
->exported_count
, 0);
1931 if (!resource
->read_lock_fence
.get())
1934 resource
->read_lock_fence
->Wait();
1937 GLint
ResourceProvider::GetActiveTextureUnit(GLES2Interface
* gl
) {
1938 GLint active_unit
= 0;
1939 gl
->GetIntegerv(GL_ACTIVE_TEXTURE
, &active_unit
);
1943 void ResourceProvider::ValidateResource(ResourceId id
) const {
1944 DCHECK(thread_checker_
.CalledOnValidThread());
1946 DCHECK(resources_
.find(id
) != resources_
.end());
1949 GLES2Interface
* ResourceProvider::ContextGL() const {
1950 ContextProvider
* context_provider
= output_surface_
->context_provider();
1951 return context_provider
? context_provider
->ContextGL() : NULL
;
1954 class GrContext
* ResourceProvider::GrContext(bool worker_context
) const {
1955 ContextProvider
* context_provider
=
1956 worker_context
? output_surface_
->worker_context_provider()
1957 : output_surface_
->context_provider();
1958 return context_provider
? context_provider
->GrContext() : NULL
;