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 "third_party/skia/include/gpu/GrTextureProvider.h"
30 #include "ui/gfx/frame_time.h"
31 #include "ui/gfx/geometry/rect.h"
32 #include "ui/gfx/geometry/vector2d.h"
33 #include "ui/gfx/gpu_memory_buffer.h"
35 using gpu::gles2::GLES2Interface
;
41 virtual ~IdAllocator() {}
43 virtual GLuint
NextId() = 0;
46 IdAllocator(GLES2Interface
* gl
, size_t id_allocation_chunk_size
)
48 id_allocation_chunk_size_(id_allocation_chunk_size
),
49 ids_(new GLuint
[id_allocation_chunk_size
]),
50 next_id_index_(id_allocation_chunk_size
) {
51 DCHECK(id_allocation_chunk_size_
);
55 const size_t id_allocation_chunk_size_
;
56 scoped_ptr
<GLuint
[]> ids_
;
57 size_t next_id_index_
;
62 // Measured in seconds.
63 const double kSoftwareUploadTickRate
= 0.000250;
64 const double kTextureUploadTickRate
= 0.004;
66 GLenum
TextureToStorageFormat(ResourceFormat format
) {
67 GLenum storage_format
= GL_RGBA8_OES
;
72 storage_format
= GL_BGRA8_EXT
;
84 return storage_format
;
87 bool IsFormatSupportedForStorage(ResourceFormat format
, bool use_bgra
) {
104 GrPixelConfig
ToGrPixelConfig(ResourceFormat format
) {
107 return kRGBA_8888_GrPixelConfig
;
109 return kBGRA_8888_GrPixelConfig
;
111 return kRGBA_4444_GrPixelConfig
;
115 DCHECK(false) << "Unsupported resource format.";
116 return kSkia8888_GrPixelConfig
;
119 gfx::GpuMemoryBuffer::Format
ToGpuMemoryBufferFormat(ResourceFormat format
) {
122 return gfx::GpuMemoryBuffer::Format::RGBA_8888
;
124 return gfx::GpuMemoryBuffer::Format::BGRA_8888
;
134 return gfx::GpuMemoryBuffer::Format::RGBA_8888
;
137 class ScopedSetActiveTexture
{
139 ScopedSetActiveTexture(GLES2Interface
* gl
, GLenum unit
)
140 : gl_(gl
), unit_(unit
) {
141 DCHECK_EQ(GL_TEXTURE0
, ResourceProvider::GetActiveTextureUnit(gl_
));
143 if (unit_
!= GL_TEXTURE0
)
144 gl_
->ActiveTexture(unit_
);
147 ~ScopedSetActiveTexture() {
148 // Active unit being GL_TEXTURE0 is effectively the ground state.
149 if (unit_
!= GL_TEXTURE0
)
150 gl_
->ActiveTexture(GL_TEXTURE0
);
158 class TextureIdAllocator
: public IdAllocator
{
160 TextureIdAllocator(GLES2Interface
* gl
,
161 size_t texture_id_allocation_chunk_size
)
162 : IdAllocator(gl
, texture_id_allocation_chunk_size
) {}
163 ~TextureIdAllocator() override
{
164 gl_
->DeleteTextures(id_allocation_chunk_size_
- next_id_index_
,
165 ids_
.get() + next_id_index_
);
168 // Overridden from IdAllocator:
169 GLuint
NextId() override
{
170 if (next_id_index_
== id_allocation_chunk_size_
) {
171 gl_
->GenTextures(id_allocation_chunk_size_
, ids_
.get());
175 return ids_
[next_id_index_
++];
179 DISALLOW_COPY_AND_ASSIGN(TextureIdAllocator
);
182 class BufferIdAllocator
: public IdAllocator
{
184 BufferIdAllocator(GLES2Interface
* gl
, size_t buffer_id_allocation_chunk_size
)
185 : IdAllocator(gl
, buffer_id_allocation_chunk_size
) {}
186 ~BufferIdAllocator() override
{
187 gl_
->DeleteBuffers(id_allocation_chunk_size_
- next_id_index_
,
188 ids_
.get() + next_id_index_
);
191 // Overridden from IdAllocator:
192 GLuint
NextId() override
{
193 if (next_id_index_
== id_allocation_chunk_size_
) {
194 gl_
->GenBuffers(id_allocation_chunk_size_
, ids_
.get());
198 return ids_
[next_id_index_
++];
202 DISALLOW_COPY_AND_ASSIGN(BufferIdAllocator
);
205 // Query object based fence implementation used to detect completion of copy
206 // texture operations. Fence has passed when query result is available.
207 class CopyTextureFence
: public ResourceProvider::Fence
{
209 CopyTextureFence(gpu::gles2::GLES2Interface
* gl
, unsigned query_id
)
210 : gl_(gl
), query_id_(query_id
) {}
212 // Overridden from ResourceProvider::Fence:
213 void Set() override
{}
214 bool HasPassed() override
{
215 unsigned available
= 1;
216 gl_
->GetQueryObjectuivEXT(
217 query_id_
, GL_QUERY_RESULT_AVAILABLE_EXT
, &available
);
224 void Wait() override
{
225 // ProcessResult() will wait for result to become available.
230 ~CopyTextureFence() override
{}
232 void ProcessResult() {
233 unsigned time_elapsed_us
= 0;
234 gl_
->GetQueryObjectuivEXT(query_id_
, GL_QUERY_RESULT_EXT
, &time_elapsed_us
);
235 UMA_HISTOGRAM_CUSTOM_COUNTS("Renderer4.CopyTextureLatency", time_elapsed_us
,
239 gpu::gles2::GLES2Interface
* gl_
;
242 DISALLOW_COPY_AND_ASSIGN(CopyTextureFence
);
247 ResourceProvider::Resource::~Resource() {}
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 allow_overlay(false),
277 read_lock_fence(NULL
),
281 original_filter(filter
),
285 texture_pool(texture_pool
),
286 wrap_mode(wrap_mode
),
288 type(RESOURCE_TYPE_GL_TEXTURE
),
291 gpu_memory_buffer(NULL
) {
292 DCHECK(wrap_mode
== GL_CLAMP_TO_EDGE
|| wrap_mode
== GL_REPEAT
);
293 DCHECK_EQ(origin
== INTERNAL
, !!texture_pool
);
296 ResourceProvider::Resource::Resource(uint8_t* pixels
,
297 SharedBitmap
* bitmap
,
298 const gfx::Size
& size
,
304 gl_pixel_buffer_id(0),
305 gl_upload_query_id(0),
306 gl_read_lock_query_id(0),
308 lock_for_read_count(0),
312 locked_for_write(false),
314 marked_for_deletion(false),
315 pending_set_pixels(false),
316 set_pixels_completion_forced(false),
318 read_lock_fences_enabled(false),
319 has_shared_bitmap_id(!!bitmap
),
320 allow_overlay(false),
321 read_lock_fence(NULL
),
325 original_filter(filter
),
330 wrap_mode(wrap_mode
),
331 hint(TEXTURE_HINT_IMMUTABLE
),
332 type(RESOURCE_TYPE_BITMAP
),
334 shared_bitmap(bitmap
),
335 gpu_memory_buffer(NULL
) {
336 DCHECK(wrap_mode
== GL_CLAMP_TO_EDGE
|| wrap_mode
== GL_REPEAT
);
337 DCHECK(origin
== DELEGATED
|| pixels
);
339 shared_bitmap_id
= bitmap
->id();
342 ResourceProvider::Resource::Resource(const SharedBitmapId
& bitmap_id
,
343 const gfx::Size
& size
,
349 gl_pixel_buffer_id(0),
350 gl_upload_query_id(0),
351 gl_read_lock_query_id(0),
353 lock_for_read_count(0),
357 locked_for_write(false),
359 marked_for_deletion(false),
360 pending_set_pixels(false),
361 set_pixels_completion_forced(false),
363 read_lock_fences_enabled(false),
364 has_shared_bitmap_id(true),
365 allow_overlay(false),
366 read_lock_fence(NULL
),
370 original_filter(filter
),
375 wrap_mode(wrap_mode
),
376 hint(TEXTURE_HINT_IMMUTABLE
),
377 type(RESOURCE_TYPE_BITMAP
),
379 shared_bitmap_id(bitmap_id
),
381 gpu_memory_buffer(NULL
) {
382 DCHECK(wrap_mode
== GL_CLAMP_TO_EDGE
|| wrap_mode
== GL_REPEAT
);
385 ResourceProvider::Child::Child()
386 : marked_for_deletion(false), needs_sync_points(true) {
389 ResourceProvider::Child::~Child() {}
391 scoped_ptr
<ResourceProvider
> ResourceProvider::Create(
392 OutputSurface
* output_surface
,
393 SharedBitmapManager
* shared_bitmap_manager
,
394 gpu::GpuMemoryBufferManager
* gpu_memory_buffer_manager
,
395 BlockingTaskRunner
* blocking_main_thread_task_runner
,
396 int highp_threshold_min
,
397 bool use_rgba_4444_texture_format
,
398 size_t id_allocation_chunk_size
) {
399 ContextProvider
* context_provider
= output_surface
->context_provider();
401 context_provider
? context_provider
->ContextGL() : nullptr;
402 ResourceType default_resource_type
=
403 gl
? RESOURCE_TYPE_GL_TEXTURE
: RESOURCE_TYPE_BITMAP
;
405 scoped_ptr
<ResourceProvider
> resource_provider(new ResourceProvider(
406 output_surface
, shared_bitmap_manager
, gpu_memory_buffer_manager
,
407 blocking_main_thread_task_runner
, highp_threshold_min
,
408 default_resource_type
, use_rgba_4444_texture_format
,
409 id_allocation_chunk_size
));
412 resource_provider
->InitializeGL();
414 resource_provider
->InitializeSoftware();
416 return resource_provider
.Pass();
419 ResourceProvider::~ResourceProvider() {
420 while (!children_
.empty())
421 DestroyChildInternal(children_
.begin(), FOR_SHUTDOWN
);
422 while (!resources_
.empty())
423 DeleteResourceInternal(resources_
.begin(), FOR_SHUTDOWN
);
425 GLES2Interface
* gl
= ContextGL();
426 if (default_resource_type_
!= RESOURCE_TYPE_GL_TEXTURE
) {
427 // We are not in GL mode, but double check before returning.
429 DCHECK(!texture_uploader_
);
435 // Check that all GL resources has been deleted.
436 for (ResourceMap::const_iterator itr
= resources_
.begin();
437 itr
!= resources_
.end(); ++itr
) {
438 DCHECK_NE(RESOURCE_TYPE_GL_TEXTURE
, itr
->second
.type
);
440 #endif // DCHECK_IS_ON()
442 texture_uploader_
= nullptr;
443 texture_id_allocator_
= nullptr;
444 buffer_id_allocator_
= nullptr;
448 bool ResourceProvider::InUseByConsumer(ResourceId id
) {
449 Resource
* resource
= GetResource(id
);
450 return resource
->lock_for_read_count
> 0 || resource
->exported_count
> 0 ||
454 bool ResourceProvider::IsLost(ResourceId id
) {
455 Resource
* resource
= GetResource(id
);
456 return resource
->lost
;
459 bool ResourceProvider::AllowOverlay(ResourceId id
) {
460 Resource
* resource
= GetResource(id
);
461 return resource
->allow_overlay
;
464 ResourceProvider::ResourceId
ResourceProvider::CreateResource(
465 const gfx::Size
& size
,
468 ResourceFormat format
) {
469 DCHECK(!size
.IsEmpty());
470 switch (default_resource_type_
) {
471 case RESOURCE_TYPE_GL_TEXTURE
:
472 return CreateGLTexture(size
,
474 GL_TEXTURE_POOL_UNMANAGED_CHROMIUM
,
478 case RESOURCE_TYPE_BITMAP
:
479 DCHECK_EQ(RGBA_8888
, format
);
480 return CreateBitmap(size
, wrap_mode
);
483 LOG(FATAL
) << "Invalid default resource type.";
487 ResourceProvider::ResourceId
ResourceProvider::CreateManagedResource(
488 const gfx::Size
& size
,
492 ResourceFormat format
) {
493 DCHECK(!size
.IsEmpty());
494 switch (default_resource_type_
) {
495 case RESOURCE_TYPE_GL_TEXTURE
:
496 return CreateGLTexture(size
,
498 GL_TEXTURE_POOL_MANAGED_CHROMIUM
,
502 case RESOURCE_TYPE_BITMAP
:
503 DCHECK_EQ(RGBA_8888
, format
);
504 return CreateBitmap(size
, wrap_mode
);
507 LOG(FATAL
) << "Invalid default resource type.";
511 ResourceProvider::ResourceId
ResourceProvider::CreateGLTexture(
512 const gfx::Size
& size
,
517 ResourceFormat format
) {
518 DCHECK_LE(size
.width(), max_texture_size_
);
519 DCHECK_LE(size
.height(), max_texture_size_
);
520 DCHECK(thread_checker_
.CalledOnValidThread());
522 ResourceId id
= next_id_
++;
523 Resource
* resource
= InsertResource(
524 id
, Resource(0, size
, Resource::INTERNAL
, target
, GL_LINEAR
, texture_pool
,
525 wrap_mode
, hint
, format
));
526 resource
->allocated
= false;
530 ResourceProvider::ResourceId
ResourceProvider::CreateBitmap(
531 const gfx::Size
& size
, GLint wrap_mode
) {
532 DCHECK(thread_checker_
.CalledOnValidThread());
534 scoped_ptr
<SharedBitmap
> bitmap
=
535 shared_bitmap_manager_
->AllocateSharedBitmap(size
);
536 uint8_t* pixels
= bitmap
->pixels();
539 ResourceId id
= next_id_
++;
541 InsertResource(id
, Resource(pixels
, bitmap
.release(), size
,
542 Resource::INTERNAL
, GL_LINEAR
, wrap_mode
));
543 resource
->allocated
= true;
547 ResourceProvider::ResourceId
ResourceProvider::CreateResourceFromIOSurface(
548 const gfx::Size
& size
,
549 unsigned io_surface_id
) {
550 DCHECK(thread_checker_
.CalledOnValidThread());
552 ResourceId id
= next_id_
++;
553 Resource
* resource
= InsertResource(
554 id
, Resource(0, gfx::Size(), Resource::INTERNAL
, GL_TEXTURE_RECTANGLE_ARB
,
555 GL_LINEAR
, GL_TEXTURE_POOL_UNMANAGED_CHROMIUM
,
556 GL_CLAMP_TO_EDGE
, TEXTURE_HINT_IMMUTABLE
, RGBA_8888
));
557 LazyCreate(resource
);
558 GLES2Interface
* gl
= ContextGL();
560 gl
->BindTexture(GL_TEXTURE_RECTANGLE_ARB
, resource
->gl_id
);
561 gl
->TexImageIOSurface2DCHROMIUM(
562 GL_TEXTURE_RECTANGLE_ARB
, size
.width(), size
.height(), io_surface_id
, 0);
563 resource
->allocated
= true;
567 ResourceProvider::ResourceId
ResourceProvider::CreateResourceFromTextureMailbox(
568 const TextureMailbox
& mailbox
,
569 scoped_ptr
<SingleReleaseCallbackImpl
> release_callback_impl
) {
570 DCHECK(thread_checker_
.CalledOnValidThread());
571 // Just store the information. Mailbox will be consumed in LockForRead().
572 ResourceId id
= next_id_
++;
573 DCHECK(mailbox
.IsValid());
574 Resource
* resource
= nullptr;
575 if (mailbox
.IsTexture()) {
576 resource
= InsertResource(
577 id
, Resource(0, gfx::Size(), Resource::EXTERNAL
, mailbox
.target(),
578 mailbox
.nearest_neighbor() ? GL_NEAREST
: GL_LINEAR
, 0,
579 GL_CLAMP_TO_EDGE
, TEXTURE_HINT_IMMUTABLE
, RGBA_8888
));
581 DCHECK(mailbox
.IsSharedMemory());
582 SharedBitmap
* shared_bitmap
= mailbox
.shared_bitmap();
583 uint8_t* pixels
= shared_bitmap
->pixels();
585 resource
= InsertResource(
586 id
, Resource(pixels
, shared_bitmap
, mailbox
.shared_memory_size(),
587 Resource::EXTERNAL
, GL_LINEAR
, GL_CLAMP_TO_EDGE
));
589 resource
->allocated
= true;
590 resource
->mailbox
= mailbox
;
591 resource
->release_callback_impl
=
592 base::Bind(&SingleReleaseCallbackImpl::Run
,
593 base::Owned(release_callback_impl
.release()));
594 resource
->allow_overlay
= mailbox
.allow_overlay();
598 void ResourceProvider::DeleteResource(ResourceId id
) {
599 DCHECK(thread_checker_
.CalledOnValidThread());
600 ResourceMap::iterator it
= resources_
.find(id
);
601 CHECK(it
!= resources_
.end());
602 Resource
* resource
= &it
->second
;
603 DCHECK(!resource
->marked_for_deletion
);
604 DCHECK_EQ(resource
->imported_count
, 0);
605 DCHECK(resource
->pending_set_pixels
|| !resource
->locked_for_write
);
607 if (resource
->exported_count
> 0 || resource
->lock_for_read_count
> 0) {
608 resource
->marked_for_deletion
= true;
611 DeleteResourceInternal(it
, NORMAL
);
615 void ResourceProvider::DeleteResourceInternal(ResourceMap::iterator it
,
617 TRACE_EVENT0("cc", "ResourceProvider::DeleteResourceInternal");
618 Resource
* resource
= &it
->second
;
619 bool lost_resource
= resource
->lost
;
621 DCHECK(resource
->exported_count
== 0 || style
!= NORMAL
);
622 if (style
== FOR_SHUTDOWN
&& resource
->exported_count
> 0)
623 lost_resource
= true;
625 if (resource
->image_id
) {
626 DCHECK(resource
->origin
== Resource::INTERNAL
);
627 GLES2Interface
* gl
= ContextGL();
629 gl
->DestroyImageCHROMIUM(resource
->image_id
);
631 if (resource
->gl_upload_query_id
) {
632 DCHECK(resource
->origin
== Resource::INTERNAL
);
633 GLES2Interface
* gl
= ContextGL();
635 gl
->DeleteQueriesEXT(1, &resource
->gl_upload_query_id
);
637 if (resource
->gl_read_lock_query_id
) {
638 DCHECK(resource
->origin
== Resource::INTERNAL
);
639 GLES2Interface
* gl
= ContextGL();
641 gl
->DeleteQueriesEXT(1, &resource
->gl_read_lock_query_id
);
643 if (resource
->gl_pixel_buffer_id
) {
644 DCHECK(resource
->origin
== Resource::INTERNAL
);
645 GLES2Interface
* gl
= ContextGL();
647 gl
->DeleteBuffers(1, &resource
->gl_pixel_buffer_id
);
649 if (resource
->origin
== Resource::EXTERNAL
) {
650 DCHECK(resource
->mailbox
.IsValid());
651 GLuint sync_point
= resource
->mailbox
.sync_point();
652 if (resource
->type
== RESOURCE_TYPE_GL_TEXTURE
) {
653 DCHECK(resource
->mailbox
.IsTexture());
654 lost_resource
|= lost_output_surface_
;
655 GLES2Interface
* gl
= ContextGL();
657 if (resource
->gl_id
) {
658 gl
->DeleteTextures(1, &resource
->gl_id
);
661 sync_point
= gl
->InsertSyncPointCHROMIUM();
664 DCHECK(resource
->mailbox
.IsSharedMemory());
665 resource
->shared_bitmap
= nullptr;
666 resource
->pixels
= nullptr;
668 resource
->release_callback_impl
.Run(
669 sync_point
, lost_resource
, blocking_main_thread_task_runner_
);
671 if (resource
->gl_id
) {
672 GLES2Interface
* gl
= ContextGL();
674 gl
->DeleteTextures(1, &resource
->gl_id
);
677 if (resource
->shared_bitmap
) {
678 DCHECK(resource
->origin
!= Resource::EXTERNAL
);
679 DCHECK_EQ(RESOURCE_TYPE_BITMAP
, resource
->type
);
680 delete resource
->shared_bitmap
;
681 resource
->pixels
= NULL
;
683 if (resource
->pixels
) {
684 DCHECK(resource
->origin
== Resource::INTERNAL
);
685 delete[] resource
->pixels
;
686 resource
->pixels
= NULL
;
688 if (resource
->gpu_memory_buffer
) {
689 DCHECK(resource
->origin
== Resource::INTERNAL
);
690 delete resource
->gpu_memory_buffer
;
691 resource
->gpu_memory_buffer
= NULL
;
693 resources_
.erase(it
);
696 ResourceProvider::ResourceType
ResourceProvider::GetResourceType(
698 return GetResource(id
)->type
;
701 void ResourceProvider::SetPixels(ResourceId id
,
702 const uint8_t* image
,
703 const gfx::Rect
& image_rect
,
704 const gfx::Rect
& source_rect
,
705 const gfx::Vector2d
& dest_offset
) {
706 Resource
* resource
= GetResource(id
);
707 DCHECK(!resource
->locked_for_write
);
708 DCHECK(!resource
->lock_for_read_count
);
709 DCHECK(resource
->origin
== Resource::INTERNAL
);
710 DCHECK_EQ(resource
->exported_count
, 0);
711 DCHECK(ReadLockFenceHasPassed(resource
));
712 LazyAllocate(resource
);
714 if (resource
->type
== RESOURCE_TYPE_GL_TEXTURE
) {
715 DCHECK(resource
->gl_id
);
716 DCHECK(!resource
->pending_set_pixels
);
717 DCHECK_EQ(resource
->target
, static_cast<GLenum
>(GL_TEXTURE_2D
));
718 GLES2Interface
* gl
= ContextGL();
720 DCHECK(texture_uploader_
.get());
721 gl
->BindTexture(GL_TEXTURE_2D
, resource
->gl_id
);
722 texture_uploader_
->Upload(image
,
729 DCHECK_EQ(RESOURCE_TYPE_BITMAP
, resource
->type
);
730 DCHECK(resource
->allocated
);
731 DCHECK_EQ(RGBA_8888
, resource
->format
);
732 DCHECK(source_rect
.x() >= image_rect
.x());
733 DCHECK(source_rect
.y() >= image_rect
.y());
734 DCHECK(source_rect
.right() <= image_rect
.right());
735 DCHECK(source_rect
.bottom() <= image_rect
.bottom());
736 SkImageInfo source_info
=
737 SkImageInfo::MakeN32Premul(source_rect
.width(), source_rect
.height());
738 size_t image_row_bytes
= image_rect
.width() * 4;
739 gfx::Vector2d source_offset
= source_rect
.origin() - image_rect
.origin();
740 image
+= source_offset
.y() * image_row_bytes
+ source_offset
.x() * 4;
742 ScopedWriteLockSoftware
lock(this, id
);
743 SkCanvas
dest(lock
.sk_bitmap());
744 dest
.writePixels(source_info
, image
, image_row_bytes
, dest_offset
.x(),
749 void ResourceProvider::CopyToResource(ResourceId id
,
750 const uint8_t* image
,
751 const gfx::Size
& image_size
) {
752 Resource
* resource
= GetResource(id
);
753 DCHECK(!resource
->locked_for_write
);
754 DCHECK(!resource
->lock_for_read_count
);
755 DCHECK(resource
->origin
== Resource::INTERNAL
);
756 DCHECK_EQ(resource
->exported_count
, 0);
757 DCHECK(ReadLockFenceHasPassed(resource
));
758 LazyAllocate(resource
);
760 DCHECK_EQ(image_size
.width(), resource
->size
.width());
761 DCHECK_EQ(image_size
.height(), resource
->size
.height());
763 if (resource
->type
== RESOURCE_TYPE_BITMAP
) {
764 DCHECK_EQ(RESOURCE_TYPE_BITMAP
, resource
->type
);
765 DCHECK(resource
->allocated
);
766 DCHECK_EQ(RGBA_8888
, resource
->format
);
767 SkImageInfo source_info
=
768 SkImageInfo::MakeN32Premul(image_size
.width(), image_size
.height());
769 size_t image_stride
= image_size
.width() * 4;
771 ScopedWriteLockSoftware
lock(this, id
);
772 SkCanvas
dest(lock
.sk_bitmap());
773 dest
.writePixels(source_info
, image
, image_stride
, 0, 0);
775 DCHECK(resource
->gl_id
);
776 DCHECK(!resource
->pending_set_pixels
);
777 DCHECK_EQ(resource
->target
, static_cast<GLenum
>(GL_TEXTURE_2D
));
778 GLES2Interface
* gl
= ContextGL();
780 DCHECK(texture_uploader_
.get());
781 gl
->BindTexture(GL_TEXTURE_2D
, resource
->gl_id
);
783 if (resource
->format
== ETC1
) {
784 size_t num_bytes
= static_cast<size_t>(image_size
.width()) *
785 image_size
.height() * BitsPerPixel(ETC1
) / 8;
786 gl
->CompressedTexImage2D(GL_TEXTURE_2D
, 0, GLInternalFormat(ETC1
),
787 image_size
.width(), image_size
.height(), 0,
790 gl
->TexSubImage2D(GL_TEXTURE_2D
, 0, 0, 0, image_size
.width(),
791 image_size
.height(), GLDataFormat(resource
->format
),
792 GLDataType(resource
->format
), image
);
797 size_t ResourceProvider::NumBlockingUploads() {
798 if (!texture_uploader_
)
801 return texture_uploader_
->NumBlockingUploads();
804 void ResourceProvider::MarkPendingUploadsAsNonBlocking() {
805 if (!texture_uploader_
)
808 texture_uploader_
->MarkPendingUploadsAsNonBlocking();
811 size_t ResourceProvider::EstimatedUploadsPerTick() {
812 if (!texture_uploader_
)
815 double textures_per_second
= texture_uploader_
->EstimatedTexturesPerSecond();
816 size_t textures_per_tick
= floor(
817 kTextureUploadTickRate
* textures_per_second
);
818 return textures_per_tick
? textures_per_tick
: 1u;
821 void ResourceProvider::FlushUploads() {
822 if (!texture_uploader_
)
825 texture_uploader_
->Flush();
828 void ResourceProvider::ReleaseCachedData() {
829 if (!texture_uploader_
)
832 texture_uploader_
->ReleaseCachedQueries();
835 base::TimeTicks
ResourceProvider::EstimatedUploadCompletionTime(
836 size_t uploads_per_tick
) {
837 if (lost_output_surface_
)
838 return base::TimeTicks();
840 // Software resource uploads happen on impl thread, so don't bother batching
841 // them up and trying to wait for them to complete.
842 if (!texture_uploader_
) {
843 return gfx::FrameTime::Now() + base::TimeDelta::FromMicroseconds(
844 base::Time::kMicrosecondsPerSecond
* kSoftwareUploadTickRate
);
847 base::TimeDelta upload_one_texture_time
=
848 base::TimeDelta::FromMicroseconds(
849 base::Time::kMicrosecondsPerSecond
* kTextureUploadTickRate
) /
852 size_t total_uploads
= NumBlockingUploads() + uploads_per_tick
;
853 return gfx::FrameTime::Now() + upload_one_texture_time
* total_uploads
;
856 ResourceProvider::Resource
* ResourceProvider::InsertResource(
858 const Resource
& resource
) {
859 std::pair
<ResourceMap::iterator
, bool> result
=
860 resources_
.insert(ResourceMap::value_type(id
, resource
));
861 DCHECK(result
.second
);
862 return &result
.first
->second
;
865 ResourceProvider::Resource
* ResourceProvider::GetResource(ResourceId id
) {
866 DCHECK(thread_checker_
.CalledOnValidThread());
868 ResourceMap::iterator it
= resources_
.find(id
);
869 DCHECK(it
!= resources_
.end());
873 const ResourceProvider::Resource
* ResourceProvider::LockForRead(ResourceId id
) {
874 Resource
* resource
= GetResource(id
);
875 DCHECK(!resource
->locked_for_write
||
876 resource
->set_pixels_completion_forced
) <<
877 "locked for write: " << resource
->locked_for_write
<<
878 " pixels completion forced: " << resource
->set_pixels_completion_forced
;
879 DCHECK_EQ(resource
->exported_count
, 0);
880 // Uninitialized! Call SetPixels or LockForWrite first.
881 DCHECK(resource
->allocated
);
883 LazyCreate(resource
);
885 if (resource
->type
== RESOURCE_TYPE_GL_TEXTURE
&& !resource
->gl_id
) {
886 DCHECK(resource
->origin
!= Resource::INTERNAL
);
887 DCHECK(resource
->mailbox
.IsTexture());
889 // Mailbox sync_points must be processed by a call to
890 // WaitSyncPointIfNeeded() prior to calling LockForRead().
891 DCHECK(!resource
->mailbox
.sync_point());
893 GLES2Interface
* gl
= ContextGL();
895 resource
->gl_id
= gl
->CreateAndConsumeTextureCHROMIUM(
896 resource
->mailbox
.target(), resource
->mailbox
.name());
899 if (!resource
->pixels
&& resource
->has_shared_bitmap_id
&&
900 shared_bitmap_manager_
) {
901 scoped_ptr
<SharedBitmap
> bitmap
=
902 shared_bitmap_manager_
->GetSharedBitmapFromId(
903 resource
->size
, resource
->shared_bitmap_id
);
905 resource
->shared_bitmap
= bitmap
.release();
906 resource
->pixels
= resource
->shared_bitmap
->pixels();
910 resource
->lock_for_read_count
++;
911 if (resource
->read_lock_fences_enabled
) {
912 if (current_read_lock_fence_
.get())
913 current_read_lock_fence_
->Set();
914 resource
->read_lock_fence
= current_read_lock_fence_
;
920 void ResourceProvider::UnlockForRead(ResourceId id
) {
921 DCHECK(thread_checker_
.CalledOnValidThread());
922 ResourceMap::iterator it
= resources_
.find(id
);
923 CHECK(it
!= resources_
.end());
925 Resource
* resource
= &it
->second
;
926 DCHECK_GT(resource
->lock_for_read_count
, 0);
927 DCHECK_EQ(resource
->exported_count
, 0);
928 resource
->lock_for_read_count
--;
929 if (resource
->marked_for_deletion
&& !resource
->lock_for_read_count
) {
930 if (!resource
->child_id
) {
931 // The resource belongs to this ResourceProvider, so it can be destroyed.
932 DeleteResourceInternal(it
, NORMAL
);
934 ChildMap::iterator child_it
= children_
.find(resource
->child_id
);
935 ResourceIdArray unused
;
936 unused
.push_back(id
);
937 DeleteAndReturnUnusedResourcesToChild(child_it
, NORMAL
, unused
);
942 ResourceProvider::Resource
* ResourceProvider::LockForWrite(ResourceId id
) {
943 Resource
* resource
= GetResource(id
);
944 DCHECK(CanLockForWrite(id
));
946 resource
->locked_for_write
= true;
950 bool ResourceProvider::CanLockForWrite(ResourceId id
) {
951 Resource
* resource
= GetResource(id
);
952 return !resource
->locked_for_write
&& !resource
->lock_for_read_count
&&
953 !resource
->exported_count
&& resource
->origin
== Resource::INTERNAL
&&
954 !resource
->lost
&& ReadLockFenceHasPassed(resource
);
957 void ResourceProvider::UnlockForWrite(ResourceProvider::Resource
* resource
) {
958 DCHECK(resource
->locked_for_write
);
959 DCHECK_EQ(resource
->exported_count
, 0);
960 DCHECK(resource
->origin
== Resource::INTERNAL
);
961 resource
->locked_for_write
= false;
964 ResourceProvider::ScopedReadLockGL::ScopedReadLockGL(
965 ResourceProvider
* resource_provider
,
966 ResourceProvider::ResourceId resource_id
)
967 : resource_provider_(resource_provider
),
968 resource_id_(resource_id
),
969 resource_(resource_provider
->LockForRead(resource_id
)) {
973 ResourceProvider::ScopedReadLockGL::~ScopedReadLockGL() {
974 resource_provider_
->UnlockForRead(resource_id_
);
977 ResourceProvider::ScopedSamplerGL::ScopedSamplerGL(
978 ResourceProvider
* resource_provider
,
979 ResourceProvider::ResourceId resource_id
,
981 : ScopedReadLockGL(resource_provider
, resource_id
),
983 target_(resource_provider
->BindForSampling(resource_id
, unit_
, filter
)) {
986 ResourceProvider::ScopedSamplerGL::ScopedSamplerGL(
987 ResourceProvider
* resource_provider
,
988 ResourceProvider::ResourceId resource_id
,
991 : ScopedReadLockGL(resource_provider
, resource_id
),
993 target_(resource_provider
->BindForSampling(resource_id
, unit_
, filter
)) {
996 ResourceProvider::ScopedSamplerGL::~ScopedSamplerGL() {
999 ResourceProvider::ScopedWriteLockGL::ScopedWriteLockGL(
1000 ResourceProvider
* resource_provider
,
1001 ResourceProvider::ResourceId resource_id
)
1002 : resource_provider_(resource_provider
),
1003 resource_(resource_provider
->LockForWrite(resource_id
)) {
1004 resource_provider_
->LazyAllocate(resource_
);
1005 texture_id_
= resource_
->gl_id
;
1006 DCHECK(texture_id_
);
1009 ResourceProvider::ScopedWriteLockGL::~ScopedWriteLockGL() {
1010 resource_provider_
->UnlockForWrite(resource_
);
1013 void ResourceProvider::PopulateSkBitmapWithResource(
1014 SkBitmap
* sk_bitmap
, const Resource
* resource
) {
1015 DCHECK_EQ(RGBA_8888
, resource
->format
);
1016 SkImageInfo info
= SkImageInfo::MakeN32Premul(resource
->size
.width(),
1017 resource
->size
.height());
1018 sk_bitmap
->installPixels(info
, resource
->pixels
, info
.minRowBytes());
1021 ResourceProvider::ScopedReadLockSoftware::ScopedReadLockSoftware(
1022 ResourceProvider
* resource_provider
,
1023 ResourceProvider::ResourceId resource_id
)
1024 : resource_provider_(resource_provider
),
1025 resource_id_(resource_id
) {
1026 const Resource
* resource
= resource_provider
->LockForRead(resource_id
);
1027 wrap_mode_
= resource
->wrap_mode
;
1028 ResourceProvider::PopulateSkBitmapWithResource(&sk_bitmap_
, resource
);
1031 ResourceProvider::ScopedReadLockSoftware::~ScopedReadLockSoftware() {
1032 resource_provider_
->UnlockForRead(resource_id_
);
1035 ResourceProvider::ScopedWriteLockSoftware::ScopedWriteLockSoftware(
1036 ResourceProvider
* resource_provider
,
1037 ResourceProvider::ResourceId resource_id
)
1038 : resource_provider_(resource_provider
),
1039 resource_(resource_provider
->LockForWrite(resource_id
)) {
1040 ResourceProvider::PopulateSkBitmapWithResource(&sk_bitmap_
, resource_
);
1044 ResourceProvider::ScopedWriteLockSoftware::~ScopedWriteLockSoftware() {
1045 DCHECK(thread_checker_
.CalledOnValidThread());
1046 resource_provider_
->UnlockForWrite(resource_
);
1049 ResourceProvider::ScopedWriteLockGpuMemoryBuffer::
1050 ScopedWriteLockGpuMemoryBuffer(ResourceProvider
* resource_provider
,
1051 ResourceProvider::ResourceId resource_id
)
1052 : resource_provider_(resource_provider
),
1053 resource_(resource_provider
->LockForWrite(resource_id
)),
1054 gpu_memory_buffer_manager_(resource_provider
->gpu_memory_buffer_manager_
),
1055 gpu_memory_buffer_(nullptr),
1056 size_(resource_
->size
),
1057 format_(resource_
->format
) {
1058 DCHECK_EQ(RESOURCE_TYPE_GL_TEXTURE
, resource_
->type
);
1059 std::swap(gpu_memory_buffer_
, resource_
->gpu_memory_buffer
);
1062 ResourceProvider::ScopedWriteLockGpuMemoryBuffer::
1063 ~ScopedWriteLockGpuMemoryBuffer() {
1064 DCHECK(thread_checker_
.CalledOnValidThread());
1065 resource_provider_
->UnlockForWrite(resource_
);
1066 if (!gpu_memory_buffer_
)
1069 if (!resource_
->image_id
) {
1070 GLES2Interface
* gl
= resource_provider_
->ContextGL();
1073 #if defined(OS_CHROMEOS)
1074 // TODO(reveman): GL_COMMANDS_ISSUED_CHROMIUM is used for synchronization
1075 // on ChromeOS to avoid some performance issues. This only works with
1076 // shared memory backed buffers. crbug.com/436314
1077 DCHECK_EQ(gpu_memory_buffer_
->GetHandle().type
, gfx::SHARED_MEMORY_BUFFER
);
1080 resource_
->image_id
= gl
->CreateImageCHROMIUM(
1081 gpu_memory_buffer_
->AsClientBuffer(), size_
.width(), size_
.height(),
1082 GLInternalFormat(resource_
->format
));
1085 std::swap(resource_
->gpu_memory_buffer
, gpu_memory_buffer_
);
1086 resource_
->allocated
= true;
1087 resource_
->dirty_image
= true;
1089 // GpuMemoryBuffer provides direct access to the memory used by the GPU.
1090 // Read lock fences are required to ensure that we're not trying to map a
1091 // buffer that is currently in-use by the GPU.
1092 resource_
->read_lock_fences_enabled
= true;
1095 gfx::GpuMemoryBuffer
*
1096 ResourceProvider::ScopedWriteLockGpuMemoryBuffer::GetGpuMemoryBuffer() {
1097 if (!gpu_memory_buffer_
) {
1098 scoped_ptr
<gfx::GpuMemoryBuffer
> gpu_memory_buffer
=
1099 gpu_memory_buffer_manager_
->AllocateGpuMemoryBuffer(
1100 size_
, ToGpuMemoryBufferFormat(format_
), gfx::GpuMemoryBuffer::MAP
);
1101 gpu_memory_buffer_
= gpu_memory_buffer
.release();
1104 return gpu_memory_buffer_
;
1107 ResourceProvider::ScopedWriteLockGr::ScopedWriteLockGr(
1108 ResourceProvider
* resource_provider
,
1109 ResourceProvider::ResourceId resource_id
)
1110 : resource_provider_(resource_provider
),
1111 resource_(resource_provider
->LockForWrite(resource_id
)) {
1112 DCHECK(thread_checker_
.CalledOnValidThread());
1113 resource_provider_
->LazyAllocate(resource_
);
1116 ResourceProvider::ScopedWriteLockGr::~ScopedWriteLockGr() {
1117 DCHECK(thread_checker_
.CalledOnValidThread());
1118 DCHECK(resource_
->locked_for_write
);
1119 resource_provider_
->UnlockForWrite(resource_
);
1122 void ResourceProvider::ScopedWriteLockGr::InitSkSurface(
1123 bool use_distance_field_text
,
1124 bool can_use_lcd_text
,
1125 int msaa_sample_count
) {
1126 DCHECK(resource_
->locked_for_write
);
1128 GrBackendTextureDesc desc
;
1129 desc
.fFlags
= kRenderTarget_GrBackendTextureFlag
;
1130 desc
.fWidth
= resource_
->size
.width();
1131 desc
.fHeight
= resource_
->size
.height();
1132 desc
.fConfig
= ToGrPixelConfig(resource_
->format
);
1133 desc
.fOrigin
= kTopLeft_GrSurfaceOrigin
;
1134 desc
.fTextureHandle
= resource_
->gl_id
;
1135 desc
.fSampleCnt
= msaa_sample_count
;
1137 bool use_worker_context
= true;
1138 class GrContext
* gr_context
=
1139 resource_provider_
->GrContext(use_worker_context
);
1140 skia::RefPtr
<GrTexture
> gr_texture
=
1141 skia::AdoptRef(gr_context
->textureProvider()->wrapBackendTexture(desc
));
1143 uint32_t flags
= use_distance_field_text
1144 ? SkSurfaceProps::kUseDistanceFieldFonts_Flag
1146 // Use unknown pixel geometry to disable LCD text.
1147 SkSurfaceProps
surface_props(flags
, kUnknown_SkPixelGeometry
);
1148 if (can_use_lcd_text
) {
1149 // LegacyFontHost will get LCD text and skia figures out what type to use.
1151 SkSurfaceProps(flags
, SkSurfaceProps::kLegacyFontHost_InitType
);
1153 sk_surface_
= skia::AdoptRef(SkSurface::NewRenderTargetDirect(
1154 gr_texture
->asRenderTarget(), &surface_props
));
1157 sk_surface_
.clear();
1160 void ResourceProvider::ScopedWriteLockGr::ReleaseSkSurface() {
1161 sk_surface_
.clear();
1164 ResourceProvider::SynchronousFence::SynchronousFence(
1165 gpu::gles2::GLES2Interface
* gl
)
1166 : gl_(gl
), has_synchronized_(true) {
1169 ResourceProvider::SynchronousFence::~SynchronousFence() {
1172 void ResourceProvider::SynchronousFence::Set() {
1173 has_synchronized_
= false;
1176 bool ResourceProvider::SynchronousFence::HasPassed() {
1177 if (!has_synchronized_
) {
1178 has_synchronized_
= true;
1184 void ResourceProvider::SynchronousFence::Wait() {
1188 void ResourceProvider::SynchronousFence::Synchronize() {
1189 TRACE_EVENT0("cc", "ResourceProvider::SynchronousFence::Synchronize");
1193 ResourceProvider::ResourceProvider(
1194 OutputSurface
* output_surface
,
1195 SharedBitmapManager
* shared_bitmap_manager
,
1196 gpu::GpuMemoryBufferManager
* gpu_memory_buffer_manager
,
1197 BlockingTaskRunner
* blocking_main_thread_task_runner
,
1198 int highp_threshold_min
,
1199 ResourceType default_resource_type
,
1200 bool use_rgba_4444_texture_format
,
1201 size_t id_allocation_chunk_size
)
1202 : output_surface_(output_surface
),
1203 shared_bitmap_manager_(shared_bitmap_manager
),
1204 gpu_memory_buffer_manager_(gpu_memory_buffer_manager
),
1205 blocking_main_thread_task_runner_(blocking_main_thread_task_runner
),
1206 lost_output_surface_(false),
1207 highp_threshold_min_(highp_threshold_min
),
1210 default_resource_type_(default_resource_type
),
1211 use_texture_storage_ext_(false),
1212 use_texture_format_bgra_(false),
1213 use_texture_usage_hint_(false),
1214 use_compressed_texture_etc1_(false),
1215 yuv_resource_format_(LUMINANCE_8
),
1216 max_texture_size_(0),
1217 best_texture_format_(RGBA_8888
),
1218 use_rgba_4444_texture_format_(use_rgba_4444_texture_format
),
1219 id_allocation_chunk_size_(id_allocation_chunk_size
),
1220 use_sync_query_(false) {
1221 DCHECK(output_surface_
->HasClient());
1222 DCHECK(id_allocation_chunk_size_
);
1225 void ResourceProvider::InitializeSoftware() {
1226 DCHECK(thread_checker_
.CalledOnValidThread());
1227 DCHECK_EQ(default_resource_type_
, RESOURCE_TYPE_BITMAP
);
1228 // Pick an arbitrary limit here similar to what hardware might.
1229 max_texture_size_
= 16 * 1024;
1230 best_texture_format_
= RGBA_8888
;
1233 void ResourceProvider::InitializeGL() {
1234 DCHECK(thread_checker_
.CalledOnValidThread());
1235 DCHECK_EQ(default_resource_type_
, RESOURCE_TYPE_GL_TEXTURE
);
1236 DCHECK(!texture_uploader_
);
1237 DCHECK(!texture_id_allocator_
);
1238 DCHECK(!buffer_id_allocator_
);
1240 const ContextProvider::Capabilities
& caps
=
1241 output_surface_
->context_provider()->ContextCapabilities();
1243 bool use_bgra
= caps
.gpu
.texture_format_bgra8888
;
1244 use_texture_storage_ext_
= caps
.gpu
.texture_storage
;
1245 use_texture_format_bgra_
= caps
.gpu
.texture_format_bgra8888
;
1246 use_texture_usage_hint_
= caps
.gpu
.texture_usage
;
1247 use_compressed_texture_etc1_
= caps
.gpu
.texture_format_etc1
;
1248 yuv_resource_format_
= caps
.gpu
.texture_rg
? RED_8
: LUMINANCE_8
;
1249 use_sync_query_
= caps
.gpu
.sync_query
;
1251 GLES2Interface
* gl
= ContextGL();
1254 texture_uploader_
= TextureUploader::Create(gl
);
1255 max_texture_size_
= 0; // Context expects cleared value.
1256 gl
->GetIntegerv(GL_MAX_TEXTURE_SIZE
, &max_texture_size_
);
1257 best_texture_format_
= PlatformColor::BestTextureFormat(use_bgra
);
1259 texture_id_allocator_
.reset(
1260 new TextureIdAllocator(gl
, id_allocation_chunk_size_
));
1261 buffer_id_allocator_
.reset(
1262 new BufferIdAllocator(gl
, id_allocation_chunk_size_
));
1265 int ResourceProvider::CreateChild(const ReturnCallback
& return_callback
) {
1266 DCHECK(thread_checker_
.CalledOnValidThread());
1269 child_info
.return_callback
= return_callback
;
1271 int child
= next_child_
++;
1272 children_
[child
] = child_info
;
1276 void ResourceProvider::SetChildNeedsSyncPoints(int child_id
, bool needs
) {
1277 ChildMap::iterator it
= children_
.find(child_id
);
1278 DCHECK(it
!= children_
.end());
1279 it
->second
.needs_sync_points
= needs
;
1282 void ResourceProvider::DestroyChild(int child_id
) {
1283 ChildMap::iterator it
= children_
.find(child_id
);
1284 DCHECK(it
!= children_
.end());
1285 DestroyChildInternal(it
, NORMAL
);
1288 void ResourceProvider::DestroyChildInternal(ChildMap::iterator it
,
1289 DeleteStyle style
) {
1290 DCHECK(thread_checker_
.CalledOnValidThread());
1292 Child
& child
= it
->second
;
1293 DCHECK(style
== FOR_SHUTDOWN
|| !child
.marked_for_deletion
);
1295 ResourceIdArray resources_for_child
;
1297 for (ResourceIdMap::iterator child_it
= child
.child_to_parent_map
.begin();
1298 child_it
!= child
.child_to_parent_map
.end();
1300 ResourceId id
= child_it
->second
;
1301 resources_for_child
.push_back(id
);
1304 child
.marked_for_deletion
= true;
1306 DeleteAndReturnUnusedResourcesToChild(it
, style
, resources_for_child
);
1309 const ResourceProvider::ResourceIdMap
& ResourceProvider::GetChildToParentMap(
1311 DCHECK(thread_checker_
.CalledOnValidThread());
1312 ChildMap::const_iterator it
= children_
.find(child
);
1313 DCHECK(it
!= children_
.end());
1314 DCHECK(!it
->second
.marked_for_deletion
);
1315 return it
->second
.child_to_parent_map
;
1318 void ResourceProvider::PrepareSendToParent(const ResourceIdArray
& resources
,
1319 TransferableResourceArray
* list
) {
1320 DCHECK(thread_checker_
.CalledOnValidThread());
1321 GLES2Interface
* gl
= ContextGL();
1322 bool need_sync_point
= false;
1323 for (ResourceIdArray::const_iterator it
= resources
.begin();
1324 it
!= resources
.end();
1326 TransferableResource resource
;
1327 TransferResource(gl
, *it
, &resource
);
1328 if (!resource
.mailbox_holder
.sync_point
&& !resource
.is_software
)
1329 need_sync_point
= true;
1330 ++resources_
.find(*it
)->second
.exported_count
;
1331 list
->push_back(resource
);
1333 if (need_sync_point
&&
1334 output_surface_
->capabilities().delegated_sync_points_required
) {
1335 GLuint sync_point
= gl
->InsertSyncPointCHROMIUM();
1336 for (TransferableResourceArray::iterator it
= list
->begin();
1339 if (!it
->mailbox_holder
.sync_point
)
1340 it
->mailbox_holder
.sync_point
= sync_point
;
1345 void ResourceProvider::ReceiveFromChild(
1346 int child
, const TransferableResourceArray
& resources
) {
1347 DCHECK(thread_checker_
.CalledOnValidThread());
1348 GLES2Interface
* gl
= ContextGL();
1349 Child
& child_info
= children_
.find(child
)->second
;
1350 DCHECK(!child_info
.marked_for_deletion
);
1351 for (TransferableResourceArray::const_iterator it
= resources
.begin();
1352 it
!= resources
.end();
1354 ResourceIdMap::iterator resource_in_map_it
=
1355 child_info
.child_to_parent_map
.find(it
->id
);
1356 if (resource_in_map_it
!= child_info
.child_to_parent_map
.end()) {
1357 Resource
* resource
= GetResource(resource_in_map_it
->second
);
1358 resource
->marked_for_deletion
= false;
1359 resource
->imported_count
++;
1363 if ((!it
->is_software
&& !gl
) ||
1364 (it
->is_software
&& !shared_bitmap_manager_
)) {
1365 TRACE_EVENT0("cc", "ResourceProvider::ReceiveFromChild dropping invalid");
1366 ReturnedResourceArray to_return
;
1367 to_return
.push_back(it
->ToReturnedResource());
1368 child_info
.return_callback
.Run(to_return
,
1369 blocking_main_thread_task_runner_
);
1373 ResourceId local_id
= next_id_
++;
1374 Resource
* resource
= nullptr;
1375 if (it
->is_software
) {
1376 resource
= InsertResource(
1378 Resource(it
->mailbox_holder
.mailbox
, it
->size
, Resource::DELEGATED
,
1379 GL_LINEAR
, it
->is_repeated
? GL_REPEAT
: GL_CLAMP_TO_EDGE
));
1381 resource
= InsertResource(
1382 local_id
, Resource(0, it
->size
, Resource::DELEGATED
,
1383 it
->mailbox_holder
.texture_target
, it
->filter
, 0,
1384 it
->is_repeated
? GL_REPEAT
: GL_CLAMP_TO_EDGE
,
1385 TEXTURE_HINT_IMMUTABLE
, it
->format
));
1386 resource
->mailbox
= TextureMailbox(it
->mailbox_holder
.mailbox
,
1387 it
->mailbox_holder
.texture_target
,
1388 it
->mailbox_holder
.sync_point
);
1390 resource
->child_id
= child
;
1391 // Don't allocate a texture for a child.
1392 resource
->allocated
= true;
1393 resource
->imported_count
= 1;
1394 resource
->allow_overlay
= it
->allow_overlay
;
1395 child_info
.parent_to_child_map
[local_id
] = it
->id
;
1396 child_info
.child_to_parent_map
[it
->id
] = local_id
;
1400 void ResourceProvider::DeclareUsedResourcesFromChild(
1402 const ResourceIdSet
& resources_from_child
) {
1403 DCHECK(thread_checker_
.CalledOnValidThread());
1405 ChildMap::iterator child_it
= children_
.find(child
);
1406 DCHECK(child_it
!= children_
.end());
1407 Child
& child_info
= child_it
->second
;
1408 DCHECK(!child_info
.marked_for_deletion
);
1410 ResourceIdArray unused
;
1411 for (ResourceIdMap::iterator it
= child_info
.child_to_parent_map
.begin();
1412 it
!= child_info
.child_to_parent_map
.end();
1414 ResourceId local_id
= it
->second
;
1415 bool resource_is_in_use
= resources_from_child
.count(it
->first
) > 0;
1416 if (!resource_is_in_use
)
1417 unused
.push_back(local_id
);
1419 DeleteAndReturnUnusedResourcesToChild(child_it
, NORMAL
, unused
);
1422 void ResourceProvider::ReceiveReturnsFromParent(
1423 const ReturnedResourceArray
& resources
) {
1424 DCHECK(thread_checker_
.CalledOnValidThread());
1425 GLES2Interface
* gl
= ContextGL();
1427 base::hash_map
<int, ResourceIdArray
> resources_for_child
;
1429 for (const ReturnedResource
& returned
: resources
) {
1430 ResourceId local_id
= returned
.id
;
1431 ResourceMap::iterator map_iterator
= resources_
.find(local_id
);
1432 // Resource was already lost (e.g. it belonged to a child that was
1434 if (map_iterator
== resources_
.end())
1437 Resource
* resource
= &map_iterator
->second
;
1439 CHECK_GE(resource
->exported_count
, returned
.count
);
1440 resource
->exported_count
-= returned
.count
;
1441 resource
->lost
|= returned
.lost
;
1442 if (resource
->exported_count
)
1445 // Need to wait for the current read lock fence to pass before we can
1446 // recycle this resource.
1447 if (resource
->read_lock_fences_enabled
) {
1448 if (current_read_lock_fence_
.get())
1449 current_read_lock_fence_
->Set();
1450 resource
->read_lock_fence
= current_read_lock_fence_
;
1453 if (returned
.sync_point
) {
1454 DCHECK(!resource
->has_shared_bitmap_id
);
1455 if (resource
->origin
== Resource::INTERNAL
) {
1456 DCHECK(resource
->gl_id
);
1457 gl
->WaitSyncPointCHROMIUM(returned
.sync_point
);
1459 DCHECK(!resource
->gl_id
);
1460 resource
->mailbox
.set_sync_point(returned
.sync_point
);
1464 if (!resource
->marked_for_deletion
)
1467 if (!resource
->child_id
) {
1468 // The resource belongs to this ResourceProvider, so it can be destroyed.
1469 DeleteResourceInternal(map_iterator
, NORMAL
);
1473 DCHECK(resource
->origin
== Resource::DELEGATED
);
1474 resources_for_child
[resource
->child_id
].push_back(local_id
);
1477 for (const auto& children
: resources_for_child
) {
1478 ChildMap::iterator child_it
= children_
.find(children
.first
);
1479 DCHECK(child_it
!= children_
.end());
1480 DeleteAndReturnUnusedResourcesToChild(child_it
, NORMAL
, children
.second
);
1484 void ResourceProvider::TransferResource(GLES2Interface
* gl
,
1486 TransferableResource
* resource
) {
1487 Resource
* source
= GetResource(id
);
1488 DCHECK(!source
->locked_for_write
);
1489 DCHECK(!source
->lock_for_read_count
);
1490 DCHECK(source
->origin
!= Resource::EXTERNAL
|| source
->mailbox
.IsValid());
1491 DCHECK(source
->allocated
);
1493 resource
->format
= source
->format
;
1494 resource
->mailbox_holder
.texture_target
= source
->target
;
1495 resource
->filter
= source
->filter
;
1496 resource
->size
= source
->size
;
1497 resource
->is_repeated
= (source
->wrap_mode
== GL_REPEAT
);
1498 resource
->allow_overlay
= source
->allow_overlay
;
1500 if (source
->type
== RESOURCE_TYPE_BITMAP
) {
1501 resource
->mailbox_holder
.mailbox
= source
->shared_bitmap_id
;
1502 resource
->is_software
= true;
1503 } else if (!source
->mailbox
.IsValid()) {
1505 DCHECK(source
->gl_id
);
1506 DCHECK(source
->origin
== Resource::INTERNAL
);
1507 if (source
->image_id
) {
1508 DCHECK(source
->dirty_image
);
1509 BindImageForSampling(source
);
1511 // This is a resource allocated by the compositor, we need to produce it.
1512 // Don't set a sync point, the caller will do it.
1513 gl
->GenMailboxCHROMIUM(resource
->mailbox_holder
.mailbox
.name
);
1514 gl
->ProduceTextureDirectCHROMIUM(source
->gl_id
,
1515 resource
->mailbox_holder
.texture_target
,
1516 resource
->mailbox_holder
.mailbox
.name
);
1518 source
->mailbox
= TextureMailbox(resource
->mailbox_holder
);
1520 DCHECK(source
->mailbox
.IsTexture());
1521 if (source
->image_id
&& source
->dirty_image
) {
1522 DCHECK(source
->gl_id
);
1523 DCHECK(source
->origin
== Resource::INTERNAL
);
1524 gl
->BindTexture(resource
->mailbox_holder
.texture_target
, source
->gl_id
);
1525 BindImageForSampling(source
);
1527 // This is either an external resource, or a compositor resource that we
1528 // already exported. Make sure to forward the sync point that we were given.
1529 resource
->mailbox_holder
.mailbox
= source
->mailbox
.mailbox();
1530 resource
->mailbox_holder
.texture_target
= source
->mailbox
.target();
1531 resource
->mailbox_holder
.sync_point
= source
->mailbox
.sync_point();
1532 source
->mailbox
.set_sync_point(0);
1536 void ResourceProvider::DeleteAndReturnUnusedResourcesToChild(
1537 ChildMap::iterator child_it
,
1539 const ResourceIdArray
& unused
) {
1540 DCHECK(thread_checker_
.CalledOnValidThread());
1541 DCHECK(child_it
!= children_
.end());
1542 Child
* child_info
= &child_it
->second
;
1544 if (unused
.empty() && !child_info
->marked_for_deletion
)
1547 ReturnedResourceArray to_return
;
1549 GLES2Interface
* gl
= ContextGL();
1550 bool need_sync_point
= false;
1551 for (size_t i
= 0; i
< unused
.size(); ++i
) {
1552 ResourceId local_id
= unused
[i
];
1554 ResourceMap::iterator it
= resources_
.find(local_id
);
1555 CHECK(it
!= resources_
.end());
1556 Resource
& resource
= it
->second
;
1558 DCHECK(!resource
.locked_for_write
);
1559 DCHECK(child_info
->parent_to_child_map
.count(local_id
));
1561 ResourceId child_id
= child_info
->parent_to_child_map
[local_id
];
1562 DCHECK(child_info
->child_to_parent_map
.count(child_id
));
1566 (resource
.type
== RESOURCE_TYPE_GL_TEXTURE
&& lost_output_surface_
);
1567 if (resource
.exported_count
> 0 || resource
.lock_for_read_count
> 0) {
1568 if (style
!= FOR_SHUTDOWN
) {
1569 // Defer this until we receive the resource back from the parent or
1570 // the read lock is released.
1571 resource
.marked_for_deletion
= true;
1575 // We still have an exported_count, so we'll have to lose it.
1579 if (gl
&& resource
.filter
!= resource
.original_filter
) {
1580 DCHECK(resource
.target
);
1581 DCHECK(resource
.gl_id
);
1583 gl
->BindTexture(resource
.target
, resource
.gl_id
);
1584 gl
->TexParameteri(resource
.target
, GL_TEXTURE_MIN_FILTER
,
1585 resource
.original_filter
);
1586 gl
->TexParameteri(resource
.target
, GL_TEXTURE_MAG_FILTER
,
1587 resource
.original_filter
);
1590 ReturnedResource returned
;
1591 returned
.id
= child_id
;
1592 returned
.sync_point
= resource
.mailbox
.sync_point();
1593 if (!returned
.sync_point
&& resource
.type
== RESOURCE_TYPE_GL_TEXTURE
)
1594 need_sync_point
= true;
1595 returned
.count
= resource
.imported_count
;
1596 returned
.lost
= is_lost
;
1597 to_return
.push_back(returned
);
1599 child_info
->parent_to_child_map
.erase(local_id
);
1600 child_info
->child_to_parent_map
.erase(child_id
);
1601 resource
.imported_count
= 0;
1602 DeleteResourceInternal(it
, style
);
1604 if (need_sync_point
&& child_info
->needs_sync_points
) {
1606 GLuint sync_point
= gl
->InsertSyncPointCHROMIUM();
1607 for (size_t i
= 0; i
< to_return
.size(); ++i
) {
1608 if (!to_return
[i
].sync_point
)
1609 to_return
[i
].sync_point
= sync_point
;
1613 if (!to_return
.empty())
1614 child_info
->return_callback
.Run(to_return
,
1615 blocking_main_thread_task_runner_
);
1617 if (child_info
->marked_for_deletion
&&
1618 child_info
->parent_to_child_map
.empty()) {
1619 DCHECK(child_info
->child_to_parent_map
.empty());
1620 children_
.erase(child_it
);
1624 void ResourceProvider::AcquirePixelBuffer(ResourceId id
) {
1625 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug"),
1626 "ResourceProvider::AcquirePixelBuffer");
1628 Resource
* resource
= GetResource(id
);
1629 DCHECK(resource
->origin
== Resource::INTERNAL
);
1630 DCHECK_EQ(resource
->exported_count
, 0);
1631 DCHECK(!resource
->image_id
);
1632 DCHECK_NE(ETC1
, resource
->format
);
1634 DCHECK_EQ(RESOURCE_TYPE_GL_TEXTURE
, resource
->type
);
1635 GLES2Interface
* gl
= ContextGL();
1637 if (!resource
->gl_pixel_buffer_id
)
1638 resource
->gl_pixel_buffer_id
= buffer_id_allocator_
->NextId();
1639 gl
->BindBuffer(GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM
,
1640 resource
->gl_pixel_buffer_id
);
1641 unsigned bytes_per_pixel
= BitsPerPixel(resource
->format
) / 8;
1642 gl
->BufferData(GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM
,
1643 resource
->size
.height() *
1644 RoundUp(bytes_per_pixel
* resource
->size
.width(), 4u),
1647 gl
->BindBuffer(GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM
, 0);
1650 void ResourceProvider::ReleasePixelBuffer(ResourceId id
) {
1651 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug"),
1652 "ResourceProvider::ReleasePixelBuffer");
1654 Resource
* resource
= GetResource(id
);
1655 DCHECK(resource
->origin
== Resource::INTERNAL
);
1656 DCHECK_EQ(resource
->exported_count
, 0);
1657 DCHECK(!resource
->image_id
);
1659 // The pixel buffer can be released while there is a pending "set pixels"
1660 // if completion has been forced. Any shared memory associated with this
1661 // pixel buffer will not be freed until the waitAsyncTexImage2DCHROMIUM
1662 // command has been processed on the service side. It is also safe to
1663 // reuse any query id associated with this resource before they complete
1664 // as each new query has a unique submit count.
1665 if (resource
->pending_set_pixels
) {
1666 DCHECK(resource
->set_pixels_completion_forced
);
1667 resource
->pending_set_pixels
= false;
1668 resource
->locked_for_write
= false;
1671 DCHECK_EQ(RESOURCE_TYPE_GL_TEXTURE
, resource
->type
);
1672 if (!resource
->gl_pixel_buffer_id
)
1674 GLES2Interface
* gl
= ContextGL();
1676 gl
->BindBuffer(GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM
,
1677 resource
->gl_pixel_buffer_id
);
1679 GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM
, 0, NULL
, GL_DYNAMIC_DRAW
);
1680 gl
->BindBuffer(GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM
, 0);
1683 uint8_t* ResourceProvider::MapPixelBuffer(ResourceId id
, int* stride
) {
1684 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug"),
1685 "ResourceProvider::MapPixelBuffer");
1687 Resource
* resource
= GetResource(id
);
1688 DCHECK(resource
->origin
== Resource::INTERNAL
);
1689 DCHECK_EQ(resource
->exported_count
, 0);
1690 DCHECK(!resource
->image_id
);
1693 DCHECK_EQ(RESOURCE_TYPE_GL_TEXTURE
, resource
->type
);
1694 GLES2Interface
* gl
= ContextGL();
1696 DCHECK(resource
->gl_pixel_buffer_id
);
1697 gl
->BindBuffer(GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM
,
1698 resource
->gl_pixel_buffer_id
);
1699 uint8_t* image
= static_cast<uint8_t*>(gl
->MapBufferCHROMIUM(
1700 GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM
, GL_WRITE_ONLY
));
1701 gl
->BindBuffer(GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM
, 0);
1702 // Buffer is required to be 4-byte aligned.
1703 CHECK(!(reinterpret_cast<intptr_t>(image
) & 3));
1707 void ResourceProvider::UnmapPixelBuffer(ResourceId id
) {
1708 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug"),
1709 "ResourceProvider::UnmapPixelBuffer");
1711 Resource
* resource
= GetResource(id
);
1712 DCHECK(resource
->origin
== Resource::INTERNAL
);
1713 DCHECK_EQ(resource
->exported_count
, 0);
1714 DCHECK(!resource
->image_id
);
1716 DCHECK_EQ(RESOURCE_TYPE_GL_TEXTURE
, resource
->type
);
1717 GLES2Interface
* gl
= ContextGL();
1719 DCHECK(resource
->gl_pixel_buffer_id
);
1720 gl
->BindBuffer(GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM
,
1721 resource
->gl_pixel_buffer_id
);
1722 gl
->UnmapBufferCHROMIUM(GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM
);
1723 gl
->BindBuffer(GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM
, 0);
1726 GLenum
ResourceProvider::BindForSampling(ResourceId resource_id
,
1729 DCHECK(thread_checker_
.CalledOnValidThread());
1730 GLES2Interface
* gl
= ContextGL();
1731 ResourceMap::iterator it
= resources_
.find(resource_id
);
1732 DCHECK(it
!= resources_
.end());
1733 Resource
* resource
= &it
->second
;
1734 DCHECK(resource
->lock_for_read_count
);
1735 DCHECK(!resource
->locked_for_write
|| resource
->set_pixels_completion_forced
);
1737 ScopedSetActiveTexture
scoped_active_tex(gl
, unit
);
1738 GLenum target
= resource
->target
;
1739 gl
->BindTexture(target
, resource
->gl_id
);
1740 if (filter
!= resource
->filter
) {
1741 gl
->TexParameteri(target
, GL_TEXTURE_MIN_FILTER
, filter
);
1742 gl
->TexParameteri(target
, GL_TEXTURE_MAG_FILTER
, filter
);
1743 resource
->filter
= filter
;
1746 if (resource
->image_id
&& resource
->dirty_image
)
1747 BindImageForSampling(resource
);
1752 void ResourceProvider::BeginSetPixels(ResourceId id
) {
1753 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug"),
1754 "ResourceProvider::BeginSetPixels");
1756 Resource
* resource
= GetResource(id
);
1757 DCHECK(!resource
->pending_set_pixels
);
1759 LazyCreate(resource
);
1760 DCHECK(resource
->origin
== Resource::INTERNAL
);
1761 DCHECK(resource
->gl_id
|| resource
->allocated
);
1762 DCHECK(ReadLockFenceHasPassed(resource
));
1763 DCHECK(!resource
->image_id
);
1765 bool allocate
= !resource
->allocated
;
1766 resource
->allocated
= true;
1769 DCHECK_EQ(RESOURCE_TYPE_GL_TEXTURE
, resource
->type
);
1770 DCHECK(resource
->gl_id
);
1771 GLES2Interface
* gl
= ContextGL();
1773 DCHECK(resource
->gl_pixel_buffer_id
);
1774 DCHECK_EQ(resource
->target
, static_cast<GLenum
>(GL_TEXTURE_2D
));
1775 gl
->BindTexture(GL_TEXTURE_2D
, resource
->gl_id
);
1776 gl
->BindBuffer(GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM
,
1777 resource
->gl_pixel_buffer_id
);
1778 if (!resource
->gl_upload_query_id
)
1779 gl
->GenQueriesEXT(1, &resource
->gl_upload_query_id
);
1780 gl
->BeginQueryEXT(GL_ASYNC_PIXEL_UNPACK_COMPLETED_CHROMIUM
,
1781 resource
->gl_upload_query_id
);
1783 gl
->AsyncTexImage2DCHROMIUM(GL_TEXTURE_2D
,
1785 GLInternalFormat(resource
->format
),
1786 resource
->size
.width(),
1787 resource
->size
.height(),
1789 GLDataFormat(resource
->format
),
1790 GLDataType(resource
->format
),
1793 gl
->AsyncTexSubImage2DCHROMIUM(GL_TEXTURE_2D
,
1797 resource
->size
.width(),
1798 resource
->size
.height(),
1799 GLDataFormat(resource
->format
),
1800 GLDataType(resource
->format
),
1803 gl
->EndQueryEXT(GL_ASYNC_PIXEL_UNPACK_COMPLETED_CHROMIUM
);
1804 gl
->BindBuffer(GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM
, 0);
1806 resource
->pending_set_pixels
= true;
1807 resource
->set_pixels_completion_forced
= false;
1810 void ResourceProvider::ForceSetPixelsToComplete(ResourceId id
) {
1811 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug"),
1812 "ResourceProvider::ForceSetPixelsToComplete");
1814 Resource
* resource
= GetResource(id
);
1816 DCHECK(resource
->locked_for_write
);
1817 DCHECK(resource
->pending_set_pixels
);
1818 DCHECK(!resource
->set_pixels_completion_forced
);
1820 if (resource
->gl_id
) {
1821 GLES2Interface
* gl
= ContextGL();
1822 gl
->BindTexture(GL_TEXTURE_2D
, resource
->gl_id
);
1823 gl
->WaitAsyncTexImage2DCHROMIUM(GL_TEXTURE_2D
);
1824 gl
->BindTexture(GL_TEXTURE_2D
, 0);
1827 resource
->set_pixels_completion_forced
= true;
1830 bool ResourceProvider::DidSetPixelsComplete(ResourceId id
) {
1831 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug"),
1832 "ResourceProvider::DidSetPixelsComplete");
1834 Resource
* resource
= GetResource(id
);
1836 DCHECK(resource
->locked_for_write
);
1837 DCHECK(resource
->pending_set_pixels
);
1839 if (resource
->gl_id
) {
1840 GLES2Interface
* gl
= ContextGL();
1842 DCHECK(resource
->gl_upload_query_id
);
1843 GLuint complete
= 1;
1844 gl
->GetQueryObjectuivEXT(
1845 resource
->gl_upload_query_id
, GL_QUERY_RESULT_AVAILABLE_EXT
, &complete
);
1850 resource
->pending_set_pixels
= false;
1851 UnlockForWrite(resource
);
1853 // Async set pixels commands are not necessarily processed in-sequence with
1854 // drawing commands. Read lock fences are required to ensure that async
1855 // commands don't access the resource while used for drawing.
1856 resource
->read_lock_fences_enabled
= true;
1861 void ResourceProvider::CreateForTesting(ResourceId id
) {
1862 LazyCreate(GetResource(id
));
1865 GLenum
ResourceProvider::TargetForTesting(ResourceId id
) {
1866 Resource
* resource
= GetResource(id
);
1867 return resource
->target
;
1870 void ResourceProvider::LazyCreate(Resource
* resource
) {
1871 if (resource
->type
!= RESOURCE_TYPE_GL_TEXTURE
||
1872 resource
->origin
!= Resource::INTERNAL
)
1875 if (resource
->gl_id
)
1878 DCHECK(resource
->texture_pool
);
1879 DCHECK(resource
->origin
== Resource::INTERNAL
);
1880 DCHECK(!resource
->mailbox
.IsValid());
1881 resource
->gl_id
= texture_id_allocator_
->NextId();
1883 GLES2Interface
* gl
= ContextGL();
1886 // Create and set texture properties. Allocation is delayed until needed.
1887 gl
->BindTexture(resource
->target
, resource
->gl_id
);
1888 gl
->TexParameteri(resource
->target
, GL_TEXTURE_MIN_FILTER
,
1889 resource
->original_filter
);
1890 gl
->TexParameteri(resource
->target
, GL_TEXTURE_MAG_FILTER
,
1891 resource
->original_filter
);
1892 gl
->TexParameteri(resource
->target
, GL_TEXTURE_WRAP_S
, resource
->wrap_mode
);
1893 gl
->TexParameteri(resource
->target
, GL_TEXTURE_WRAP_T
, resource
->wrap_mode
);
1894 gl
->TexParameteri(resource
->target
, GL_TEXTURE_POOL_CHROMIUM
,
1895 resource
->texture_pool
);
1896 if (use_texture_usage_hint_
&& (resource
->hint
& TEXTURE_HINT_FRAMEBUFFER
)) {
1897 gl
->TexParameteri(resource
->target
, GL_TEXTURE_USAGE_ANGLE
,
1898 GL_FRAMEBUFFER_ATTACHMENT_ANGLE
);
1902 void ResourceProvider::AllocateForTesting(ResourceId id
) {
1903 LazyAllocate(GetResource(id
));
1906 void ResourceProvider::LazyAllocate(Resource
* resource
) {
1908 if (resource
->allocated
)
1910 LazyCreate(resource
);
1911 if (!resource
->gl_id
)
1913 resource
->allocated
= true;
1914 GLES2Interface
* gl
= ContextGL();
1915 gfx::Size
& size
= resource
->size
;
1916 DCHECK_EQ(resource
->target
, static_cast<GLenum
>(GL_TEXTURE_2D
));
1917 ResourceFormat format
= resource
->format
;
1918 gl
->BindTexture(GL_TEXTURE_2D
, resource
->gl_id
);
1919 if (use_texture_storage_ext_
&&
1920 IsFormatSupportedForStorage(format
, use_texture_format_bgra_
) &&
1921 (resource
->hint
& TEXTURE_HINT_IMMUTABLE
)) {
1922 GLenum storage_format
= TextureToStorageFormat(format
);
1923 gl
->TexStorage2DEXT(GL_TEXTURE_2D
, 1, storage_format
, size
.width(),
1926 // ETC1 does not support preallocation.
1927 if (format
!= ETC1
) {
1928 gl
->TexImage2D(GL_TEXTURE_2D
, 0, GLInternalFormat(format
), size
.width(),
1929 size
.height(), 0, GLDataFormat(format
), GLDataType(format
),
1935 void ResourceProvider::BindImageForSampling(Resource
* resource
) {
1936 GLES2Interface
* gl
= ContextGL();
1937 DCHECK(resource
->gl_id
);
1938 DCHECK(resource
->image_id
);
1940 // Release image currently bound to texture.
1941 if (resource
->bound_image_id
)
1942 gl
->ReleaseTexImage2DCHROMIUM(resource
->target
, resource
->bound_image_id
);
1943 gl
->BindTexImage2DCHROMIUM(resource
->target
, resource
->image_id
);
1944 resource
->bound_image_id
= resource
->image_id
;
1945 resource
->dirty_image
= false;
1948 void ResourceProvider::CopyResource(ResourceId source_id
, ResourceId dest_id
) {
1949 TRACE_EVENT0("cc", "ResourceProvider::CopyResource");
1951 Resource
* source_resource
= GetResource(source_id
);
1952 DCHECK(!source_resource
->lock_for_read_count
);
1953 DCHECK(source_resource
->origin
== Resource::INTERNAL
);
1954 DCHECK_EQ(source_resource
->exported_count
, 0);
1955 DCHECK_EQ(RESOURCE_TYPE_GL_TEXTURE
, source_resource
->type
);
1956 DCHECK(source_resource
->allocated
);
1957 LazyCreate(source_resource
);
1959 Resource
* dest_resource
= GetResource(dest_id
);
1960 DCHECK(!dest_resource
->locked_for_write
);
1961 DCHECK(!dest_resource
->lock_for_read_count
);
1962 DCHECK(dest_resource
->origin
== Resource::INTERNAL
);
1963 DCHECK_EQ(dest_resource
->exported_count
, 0);
1964 DCHECK_EQ(RESOURCE_TYPE_GL_TEXTURE
, dest_resource
->type
);
1965 LazyAllocate(dest_resource
);
1967 DCHECK_EQ(source_resource
->type
, dest_resource
->type
);
1968 DCHECK_EQ(source_resource
->format
, dest_resource
->format
);
1969 DCHECK(source_resource
->size
== dest_resource
->size
);
1971 GLES2Interface
* gl
= ContextGL();
1973 if (source_resource
->image_id
&& source_resource
->dirty_image
) {
1974 gl
->BindTexture(source_resource
->target
, source_resource
->gl_id
);
1975 BindImageForSampling(source_resource
);
1977 if (use_sync_query_
) {
1978 if (!source_resource
->gl_read_lock_query_id
)
1979 gl
->GenQueriesEXT(1, &source_resource
->gl_read_lock_query_id
);
1980 #if defined(OS_CHROMEOS)
1981 // TODO(reveman): This avoids a performance problem on some ChromeOS
1982 // devices. This needs to be removed to support native GpuMemoryBuffer
1983 // implementations. crbug.com/436314
1984 gl
->BeginQueryEXT(GL_COMMANDS_ISSUED_CHROMIUM
,
1985 source_resource
->gl_read_lock_query_id
);
1987 gl
->BeginQueryEXT(GL_COMMANDS_COMPLETED_CHROMIUM
,
1988 source_resource
->gl_read_lock_query_id
);
1991 DCHECK(!dest_resource
->image_id
);
1992 dest_resource
->allocated
= true;
1993 gl
->CopySubTextureCHROMIUM(dest_resource
->target
, source_resource
->gl_id
,
1994 dest_resource
->gl_id
, 0, 0);
1995 if (source_resource
->gl_read_lock_query_id
) {
1996 // End query and create a read lock fence that will prevent access to
1997 // source resource until CopySubTextureCHROMIUM command has completed.
1998 #if defined(OS_CHROMEOS)
1999 gl
->EndQueryEXT(GL_COMMANDS_ISSUED_CHROMIUM
);
2001 gl
->EndQueryEXT(GL_COMMANDS_COMPLETED_CHROMIUM
);
2003 source_resource
->read_lock_fence
= make_scoped_refptr(
2004 new CopyTextureFence(gl
, source_resource
->gl_read_lock_query_id
));
2006 // Create a SynchronousFence when CHROMIUM_sync_query extension is missing.
2007 // Try to use one synchronous fence for as many CopyResource operations as
2008 // possible as that reduce the number of times we have to synchronize with
2010 if (!synchronous_fence_
.get() || synchronous_fence_
->has_synchronized())
2011 synchronous_fence_
= make_scoped_refptr(new SynchronousFence(gl
));
2012 source_resource
->read_lock_fence
= synchronous_fence_
;
2013 source_resource
->read_lock_fence
->Set();
2017 void ResourceProvider::WaitSyncPointIfNeeded(ResourceId id
) {
2018 Resource
* resource
= GetResource(id
);
2019 DCHECK_EQ(resource
->exported_count
, 0);
2020 DCHECK(resource
->allocated
);
2021 if (resource
->type
!= RESOURCE_TYPE_GL_TEXTURE
|| resource
->gl_id
)
2023 if (!resource
->mailbox
.sync_point())
2025 DCHECK(resource
->mailbox
.IsValid());
2026 GLES2Interface
* gl
= ContextGL();
2028 gl
->WaitSyncPointCHROMIUM(resource
->mailbox
.sync_point());
2029 resource
->mailbox
.set_sync_point(0);
2032 void ResourceProvider::WaitReadLockIfNeeded(ResourceId id
) {
2033 Resource
* resource
= GetResource(id
);
2034 DCHECK_EQ(resource
->exported_count
, 0);
2035 if (!resource
->read_lock_fence
.get())
2038 resource
->read_lock_fence
->Wait();
2041 GLint
ResourceProvider::GetActiveTextureUnit(GLES2Interface
* gl
) {
2042 GLint active_unit
= 0;
2043 gl
->GetIntegerv(GL_ACTIVE_TEXTURE
, &active_unit
);
2047 void ResourceProvider::ValidateResource(ResourceId id
) const {
2048 DCHECK(thread_checker_
.CalledOnValidThread());
2050 DCHECK(resources_
.find(id
) != resources_
.end());
2053 GLES2Interface
* ResourceProvider::ContextGL() const {
2054 ContextProvider
* context_provider
= output_surface_
->context_provider();
2055 return context_provider
? context_provider
->ContextGL() : NULL
;
2058 class GrContext
* ResourceProvider::GrContext(bool worker_context
) const {
2059 ContextProvider
* context_provider
=
2060 worker_context
? output_surface_
->worker_context_provider()
2061 : output_surface_
->context_provider();
2062 return context_provider
? context_provider
->GrContext() : NULL
;