1 // Copyright 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "cc/resources/resource_provider.h"
10 #include "base/containers/hash_tables.h"
11 #include "base/metrics/histogram.h"
12 #include "base/stl_util.h"
13 #include "base/strings/string_split.h"
14 #include "base/strings/string_util.h"
15 #include "base/trace_event/trace_event.h"
16 #include "cc/base/util.h"
17 #include "cc/resources/platform_color.h"
18 #include "cc/resources/returned_resource.h"
19 #include "cc/resources/shared_bitmap_manager.h"
20 #include "cc/resources/texture_uploader.h"
21 #include "cc/resources/transferable_resource.h"
22 #include "gpu/GLES2/gl2extchromium.h"
23 #include "gpu/command_buffer/client/gles2_interface.h"
24 #include "gpu/command_buffer/client/gpu_memory_buffer_manager.h"
25 #include "third_party/khronos/GLES2/gl2.h"
26 #include "third_party/khronos/GLES2/gl2ext.h"
27 #include "third_party/skia/include/core/SkSurface.h"
28 #include "third_party/skia/include/gpu/GrContext.h"
29 #include "ui/gfx/frame_time.h"
30 #include "ui/gfx/geometry/rect.h"
31 #include "ui/gfx/geometry/vector2d.h"
32 #include "ui/gfx/gpu_memory_buffer.h"
34 using gpu::gles2::GLES2Interface
;
40 virtual ~IdAllocator() {}
42 virtual GLuint
NextId() = 0;
45 IdAllocator(GLES2Interface
* gl
, size_t id_allocation_chunk_size
)
47 id_allocation_chunk_size_(id_allocation_chunk_size
),
48 ids_(new GLuint
[id_allocation_chunk_size
]),
49 next_id_index_(id_allocation_chunk_size
) {
50 DCHECK(id_allocation_chunk_size_
);
54 const size_t id_allocation_chunk_size_
;
55 scoped_ptr
<GLuint
[]> ids_
;
56 size_t next_id_index_
;
61 // Measured in seconds.
62 const double kSoftwareUploadTickRate
= 0.000250;
63 const double kTextureUploadTickRate
= 0.004;
65 GLenum
TextureToStorageFormat(ResourceFormat format
) {
66 GLenum storage_format
= GL_RGBA8_OES
;
71 storage_format
= GL_BGRA8_EXT
;
83 return storage_format
;
86 bool IsFormatSupportedForStorage(ResourceFormat format
, bool use_bgra
) {
103 GrPixelConfig
ToGrPixelConfig(ResourceFormat format
) {
106 return kRGBA_8888_GrPixelConfig
;
108 return kBGRA_8888_GrPixelConfig
;
110 return kRGBA_4444_GrPixelConfig
;
114 DCHECK(false) << "Unsupported resource format.";
115 return kSkia8888_GrPixelConfig
;
118 gfx::GpuMemoryBuffer::Format
ToGpuMemoryBufferFormat(ResourceFormat format
) {
121 return gfx::GpuMemoryBuffer::Format::RGBA_8888
;
123 return gfx::GpuMemoryBuffer::Format::BGRA_8888
;
133 return gfx::GpuMemoryBuffer::Format::RGBA_8888
;
136 class ScopedSetActiveTexture
{
138 ScopedSetActiveTexture(GLES2Interface
* gl
, GLenum unit
)
139 : gl_(gl
), unit_(unit
) {
140 DCHECK_EQ(GL_TEXTURE0
, ResourceProvider::GetActiveTextureUnit(gl_
));
142 if (unit_
!= GL_TEXTURE0
)
143 gl_
->ActiveTexture(unit_
);
146 ~ScopedSetActiveTexture() {
147 // Active unit being GL_TEXTURE0 is effectively the ground state.
148 if (unit_
!= GL_TEXTURE0
)
149 gl_
->ActiveTexture(GL_TEXTURE0
);
157 class TextureIdAllocator
: public IdAllocator
{
159 TextureIdAllocator(GLES2Interface
* gl
,
160 size_t texture_id_allocation_chunk_size
)
161 : IdAllocator(gl
, texture_id_allocation_chunk_size
) {}
162 ~TextureIdAllocator() override
{
163 gl_
->DeleteTextures(id_allocation_chunk_size_
- next_id_index_
,
164 ids_
.get() + next_id_index_
);
167 // Overridden from IdAllocator:
168 GLuint
NextId() override
{
169 if (next_id_index_
== id_allocation_chunk_size_
) {
170 gl_
->GenTextures(id_allocation_chunk_size_
, ids_
.get());
174 return ids_
[next_id_index_
++];
178 DISALLOW_COPY_AND_ASSIGN(TextureIdAllocator
);
181 class BufferIdAllocator
: public IdAllocator
{
183 BufferIdAllocator(GLES2Interface
* gl
, size_t buffer_id_allocation_chunk_size
)
184 : IdAllocator(gl
, buffer_id_allocation_chunk_size
) {}
185 ~BufferIdAllocator() override
{
186 gl_
->DeleteBuffers(id_allocation_chunk_size_
- next_id_index_
,
187 ids_
.get() + next_id_index_
);
190 // Overridden from IdAllocator:
191 GLuint
NextId() override
{
192 if (next_id_index_
== id_allocation_chunk_size_
) {
193 gl_
->GenBuffers(id_allocation_chunk_size_
, ids_
.get());
197 return ids_
[next_id_index_
++];
201 DISALLOW_COPY_AND_ASSIGN(BufferIdAllocator
);
204 // Query object based fence implementation used to detect completion of copy
205 // texture operations. Fence has passed when query result is available.
206 class CopyTextureFence
: public ResourceProvider::Fence
{
208 CopyTextureFence(gpu::gles2::GLES2Interface
* gl
, unsigned query_id
)
209 : gl_(gl
), query_id_(query_id
) {}
211 // Overridden from ResourceProvider::Fence:
212 void Set() override
{}
213 bool HasPassed() override
{
214 unsigned available
= 1;
215 gl_
->GetQueryObjectuivEXT(
216 query_id_
, GL_QUERY_RESULT_AVAILABLE_EXT
, &available
);
223 void Wait() override
{
224 // ProcessResult() will wait for result to become available.
229 ~CopyTextureFence() override
{}
231 void ProcessResult() {
232 unsigned time_elapsed_us
= 0;
233 gl_
->GetQueryObjectuivEXT(query_id_
, GL_QUERY_RESULT_EXT
, &time_elapsed_us
);
234 UMA_HISTOGRAM_CUSTOM_COUNTS("Renderer4.CopyTextureLatency", time_elapsed_us
,
238 gpu::gles2::GLES2Interface
* gl_
;
241 DISALLOW_COPY_AND_ASSIGN(CopyTextureFence
);
246 ResourceProvider::Resource::~Resource() {}
248 ResourceProvider::Resource::Resource(GLuint texture_id
,
249 const gfx::Size
& size
,
256 ResourceFormat format
)
259 gl_pixel_buffer_id(0),
260 gl_upload_query_id(0),
261 gl_read_lock_query_id(0),
263 lock_for_read_count(0),
267 locked_for_write(false),
269 marked_for_deletion(false),
270 pending_set_pixels(false),
271 set_pixels_completion_forced(false),
273 read_lock_fences_enabled(false),
274 has_shared_bitmap_id(false),
275 allow_overlay(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 allow_overlay(false),
320 read_lock_fence(NULL
),
324 original_filter(filter
),
329 wrap_mode(wrap_mode
),
330 hint(TEXTURE_HINT_IMMUTABLE
),
331 type(RESOURCE_TYPE_BITMAP
),
333 shared_bitmap(bitmap
),
334 gpu_memory_buffer(NULL
) {
335 DCHECK(wrap_mode
== GL_CLAMP_TO_EDGE
|| wrap_mode
== GL_REPEAT
);
336 DCHECK(origin
== DELEGATED
|| pixels
);
338 shared_bitmap_id
= bitmap
->id();
341 ResourceProvider::Resource::Resource(const SharedBitmapId
& bitmap_id
,
342 const gfx::Size
& size
,
348 gl_pixel_buffer_id(0),
349 gl_upload_query_id(0),
350 gl_read_lock_query_id(0),
352 lock_for_read_count(0),
356 locked_for_write(false),
358 marked_for_deletion(false),
359 pending_set_pixels(false),
360 set_pixels_completion_forced(false),
362 read_lock_fences_enabled(false),
363 has_shared_bitmap_id(true),
364 allow_overlay(false),
365 read_lock_fence(NULL
),
369 original_filter(filter
),
374 wrap_mode(wrap_mode
),
375 hint(TEXTURE_HINT_IMMUTABLE
),
376 type(RESOURCE_TYPE_BITMAP
),
378 shared_bitmap_id(bitmap_id
),
380 gpu_memory_buffer(NULL
) {
381 DCHECK(wrap_mode
== GL_CLAMP_TO_EDGE
|| wrap_mode
== GL_REPEAT
);
384 ResourceProvider::Child::Child()
385 : marked_for_deletion(false), needs_sync_points(true) {
388 ResourceProvider::Child::~Child() {}
390 scoped_ptr
<ResourceProvider
> ResourceProvider::Create(
391 OutputSurface
* output_surface
,
392 SharedBitmapManager
* shared_bitmap_manager
,
393 gpu::GpuMemoryBufferManager
* gpu_memory_buffer_manager
,
394 BlockingTaskRunner
* blocking_main_thread_task_runner
,
395 int highp_threshold_min
,
396 bool use_rgba_4444_texture_format
,
397 size_t id_allocation_chunk_size
) {
398 ContextProvider
* context_provider
= output_surface
->context_provider();
400 context_provider
? context_provider
->ContextGL() : nullptr;
401 ResourceType default_resource_type
=
402 gl
? RESOURCE_TYPE_GL_TEXTURE
: RESOURCE_TYPE_BITMAP
;
404 scoped_ptr
<ResourceProvider
> resource_provider(new ResourceProvider(
405 output_surface
, shared_bitmap_manager
, gpu_memory_buffer_manager
,
406 blocking_main_thread_task_runner
, highp_threshold_min
,
407 default_resource_type
, use_rgba_4444_texture_format
,
408 id_allocation_chunk_size
));
411 resource_provider
->InitializeGL();
413 resource_provider
->InitializeSoftware();
415 return resource_provider
.Pass();
418 ResourceProvider::~ResourceProvider() {
419 while (!children_
.empty())
420 DestroyChildInternal(children_
.begin(), FOR_SHUTDOWN
);
421 while (!resources_
.empty())
422 DeleteResourceInternal(resources_
.begin(), FOR_SHUTDOWN
);
424 GLES2Interface
* gl
= ContextGL();
425 if (default_resource_type_
!= RESOURCE_TYPE_GL_TEXTURE
) {
426 // We are not in GL mode, but double check before returning.
428 DCHECK(!texture_uploader_
);
434 // Check that all GL resources has been deleted.
435 for (ResourceMap::const_iterator itr
= resources_
.begin();
436 itr
!= resources_
.end(); ++itr
) {
437 DCHECK_NE(RESOURCE_TYPE_GL_TEXTURE
, itr
->second
.type
);
439 #endif // DCHECK_IS_ON()
441 texture_uploader_
= nullptr;
442 texture_id_allocator_
= nullptr;
443 buffer_id_allocator_
= nullptr;
447 bool ResourceProvider::InUseByConsumer(ResourceId id
) {
448 Resource
* resource
= GetResource(id
);
449 return resource
->lock_for_read_count
> 0 || resource
->exported_count
> 0 ||
453 bool ResourceProvider::IsLost(ResourceId id
) {
454 Resource
* resource
= GetResource(id
);
455 return resource
->lost
;
458 bool ResourceProvider::AllowOverlay(ResourceId id
) {
459 Resource
* resource
= GetResource(id
);
460 return resource
->allow_overlay
;
463 ResourceProvider::ResourceId
ResourceProvider::CreateResource(
464 const gfx::Size
& size
,
467 ResourceFormat format
) {
468 DCHECK(!size
.IsEmpty());
469 switch (default_resource_type_
) {
470 case RESOURCE_TYPE_GL_TEXTURE
:
471 return CreateGLTexture(size
,
473 GL_TEXTURE_POOL_UNMANAGED_CHROMIUM
,
477 case RESOURCE_TYPE_BITMAP
:
478 DCHECK_EQ(RGBA_8888
, format
);
479 return CreateBitmap(size
, wrap_mode
);
482 LOG(FATAL
) << "Invalid default resource type.";
486 ResourceProvider::ResourceId
ResourceProvider::CreateManagedResource(
487 const gfx::Size
& size
,
491 ResourceFormat format
) {
492 DCHECK(!size
.IsEmpty());
493 switch (default_resource_type_
) {
494 case RESOURCE_TYPE_GL_TEXTURE
:
495 return CreateGLTexture(size
,
497 GL_TEXTURE_POOL_MANAGED_CHROMIUM
,
501 case RESOURCE_TYPE_BITMAP
:
502 DCHECK_EQ(RGBA_8888
, format
);
503 return CreateBitmap(size
, wrap_mode
);
506 LOG(FATAL
) << "Invalid default resource type.";
510 ResourceProvider::ResourceId
ResourceProvider::CreateGLTexture(
511 const gfx::Size
& size
,
516 ResourceFormat format
) {
517 DCHECK_LE(size
.width(), max_texture_size_
);
518 DCHECK_LE(size
.height(), max_texture_size_
);
519 DCHECK(thread_checker_
.CalledOnValidThread());
521 ResourceId id
= next_id_
++;
522 Resource
* resource
= InsertResource(
523 id
, Resource(0, size
, Resource::INTERNAL
, target
, GL_LINEAR
, texture_pool
,
524 wrap_mode
, hint
, format
));
525 resource
->allocated
= false;
529 ResourceProvider::ResourceId
ResourceProvider::CreateBitmap(
530 const gfx::Size
& size
, GLint wrap_mode
) {
531 DCHECK(thread_checker_
.CalledOnValidThread());
533 scoped_ptr
<SharedBitmap
> bitmap
=
534 shared_bitmap_manager_
->AllocateSharedBitmap(size
);
535 uint8_t* pixels
= bitmap
->pixels();
538 ResourceId id
= next_id_
++;
540 InsertResource(id
, Resource(pixels
, bitmap
.release(), size
,
541 Resource::INTERNAL
, GL_LINEAR
, wrap_mode
));
542 resource
->allocated
= true;
546 ResourceProvider::ResourceId
ResourceProvider::CreateResourceFromIOSurface(
547 const gfx::Size
& size
,
548 unsigned io_surface_id
) {
549 DCHECK(thread_checker_
.CalledOnValidThread());
551 ResourceId id
= next_id_
++;
552 Resource
* resource
= InsertResource(
553 id
, Resource(0, gfx::Size(), Resource::INTERNAL
, GL_TEXTURE_RECTANGLE_ARB
,
554 GL_LINEAR
, GL_TEXTURE_POOL_UNMANAGED_CHROMIUM
,
555 GL_CLAMP_TO_EDGE
, TEXTURE_HINT_IMMUTABLE
, RGBA_8888
));
556 LazyCreate(resource
);
557 GLES2Interface
* gl
= ContextGL();
559 gl
->BindTexture(GL_TEXTURE_RECTANGLE_ARB
, resource
->gl_id
);
560 gl
->TexImageIOSurface2DCHROMIUM(
561 GL_TEXTURE_RECTANGLE_ARB
, size
.width(), size
.height(), io_surface_id
, 0);
562 resource
->allocated
= true;
566 ResourceProvider::ResourceId
ResourceProvider::CreateResourceFromTextureMailbox(
567 const TextureMailbox
& mailbox
,
568 scoped_ptr
<SingleReleaseCallbackImpl
> release_callback_impl
) {
569 DCHECK(thread_checker_
.CalledOnValidThread());
570 // Just store the information. Mailbox will be consumed in LockForRead().
571 ResourceId id
= next_id_
++;
572 DCHECK(mailbox
.IsValid());
573 Resource
* resource
= nullptr;
574 if (mailbox
.IsTexture()) {
575 resource
= InsertResource(
576 id
, Resource(0, gfx::Size(), Resource::EXTERNAL
, mailbox
.target(),
577 mailbox
.nearest_neighbor() ? GL_NEAREST
: GL_LINEAR
, 0,
578 GL_CLAMP_TO_EDGE
, TEXTURE_HINT_IMMUTABLE
, RGBA_8888
));
580 DCHECK(mailbox
.IsSharedMemory());
581 SharedBitmap
* shared_bitmap
= mailbox
.shared_bitmap();
582 uint8_t* pixels
= shared_bitmap
->pixels();
584 resource
= InsertResource(
585 id
, Resource(pixels
, shared_bitmap
, mailbox
.shared_memory_size(),
586 Resource::EXTERNAL
, GL_LINEAR
, GL_CLAMP_TO_EDGE
));
588 resource
->allocated
= true;
589 resource
->mailbox
= mailbox
;
590 resource
->release_callback_impl
=
591 base::Bind(&SingleReleaseCallbackImpl::Run
,
592 base::Owned(release_callback_impl
.release()));
593 resource
->allow_overlay
= mailbox
.allow_overlay();
597 void ResourceProvider::DeleteResource(ResourceId id
) {
598 DCHECK(thread_checker_
.CalledOnValidThread());
599 ResourceMap::iterator it
= resources_
.find(id
);
600 CHECK(it
!= resources_
.end());
601 Resource
* resource
= &it
->second
;
602 DCHECK(!resource
->marked_for_deletion
);
603 DCHECK_EQ(resource
->imported_count
, 0);
604 DCHECK(resource
->pending_set_pixels
|| !resource
->locked_for_write
);
606 if (resource
->exported_count
> 0 || resource
->lock_for_read_count
> 0) {
607 resource
->marked_for_deletion
= true;
610 DeleteResourceInternal(it
, NORMAL
);
614 void ResourceProvider::DeleteResourceInternal(ResourceMap::iterator it
,
616 TRACE_EVENT0("cc", "ResourceProvider::DeleteResourceInternal");
617 Resource
* resource
= &it
->second
;
618 bool lost_resource
= resource
->lost
;
620 DCHECK(resource
->exported_count
== 0 || style
!= NORMAL
);
621 if (style
== FOR_SHUTDOWN
&& resource
->exported_count
> 0)
622 lost_resource
= true;
624 if (resource
->image_id
) {
625 DCHECK(resource
->origin
== Resource::INTERNAL
);
626 GLES2Interface
* gl
= ContextGL();
628 gl
->DestroyImageCHROMIUM(resource
->image_id
);
630 if (resource
->gl_upload_query_id
) {
631 DCHECK(resource
->origin
== Resource::INTERNAL
);
632 GLES2Interface
* gl
= ContextGL();
634 gl
->DeleteQueriesEXT(1, &resource
->gl_upload_query_id
);
636 if (resource
->gl_read_lock_query_id
) {
637 DCHECK(resource
->origin
== Resource::INTERNAL
);
638 GLES2Interface
* gl
= ContextGL();
640 gl
->DeleteQueriesEXT(1, &resource
->gl_read_lock_query_id
);
642 if (resource
->gl_pixel_buffer_id
) {
643 DCHECK(resource
->origin
== Resource::INTERNAL
);
644 GLES2Interface
* gl
= ContextGL();
646 gl
->DeleteBuffers(1, &resource
->gl_pixel_buffer_id
);
648 if (resource
->origin
== Resource::EXTERNAL
) {
649 DCHECK(resource
->mailbox
.IsValid());
650 GLuint sync_point
= resource
->mailbox
.sync_point();
651 if (resource
->type
== RESOURCE_TYPE_GL_TEXTURE
) {
652 DCHECK(resource
->mailbox
.IsTexture());
653 lost_resource
|= lost_output_surface_
;
654 GLES2Interface
* gl
= ContextGL();
656 if (resource
->gl_id
) {
657 gl
->DeleteTextures(1, &resource
->gl_id
);
660 sync_point
= gl
->InsertSyncPointCHROMIUM();
663 DCHECK(resource
->mailbox
.IsSharedMemory());
664 resource
->shared_bitmap
= nullptr;
665 resource
->pixels
= nullptr;
667 resource
->release_callback_impl
.Run(
668 sync_point
, lost_resource
, blocking_main_thread_task_runner_
);
670 if (resource
->gl_id
) {
671 GLES2Interface
* gl
= ContextGL();
673 gl
->DeleteTextures(1, &resource
->gl_id
);
676 if (resource
->shared_bitmap
) {
677 DCHECK(resource
->origin
!= Resource::EXTERNAL
);
678 DCHECK_EQ(RESOURCE_TYPE_BITMAP
, resource
->type
);
679 delete resource
->shared_bitmap
;
680 resource
->pixels
= NULL
;
682 if (resource
->pixels
) {
683 DCHECK(resource
->origin
== Resource::INTERNAL
);
684 delete[] resource
->pixels
;
685 resource
->pixels
= NULL
;
687 if (resource
->gpu_memory_buffer
) {
688 DCHECK(resource
->origin
== Resource::INTERNAL
);
689 delete resource
->gpu_memory_buffer
;
690 resource
->gpu_memory_buffer
= NULL
;
692 resources_
.erase(it
);
695 ResourceProvider::ResourceType
ResourceProvider::GetResourceType(
697 return GetResource(id
)->type
;
700 void ResourceProvider::SetPixels(ResourceId id
,
701 const uint8_t* image
,
702 const gfx::Rect
& image_rect
,
703 const gfx::Rect
& source_rect
,
704 const gfx::Vector2d
& dest_offset
) {
705 Resource
* resource
= GetResource(id
);
706 DCHECK(!resource
->locked_for_write
);
707 DCHECK(!resource
->lock_for_read_count
);
708 DCHECK(resource
->origin
== Resource::INTERNAL
);
709 DCHECK_EQ(resource
->exported_count
, 0);
710 DCHECK(ReadLockFenceHasPassed(resource
));
711 LazyAllocate(resource
);
713 if (resource
->type
== RESOURCE_TYPE_GL_TEXTURE
) {
714 DCHECK(resource
->gl_id
);
715 DCHECK(!resource
->pending_set_pixels
);
716 DCHECK_EQ(resource
->target
, static_cast<GLenum
>(GL_TEXTURE_2D
));
717 GLES2Interface
* gl
= ContextGL();
719 DCHECK(texture_uploader_
.get());
720 gl
->BindTexture(GL_TEXTURE_2D
, resource
->gl_id
);
721 texture_uploader_
->Upload(image
,
728 DCHECK_EQ(RESOURCE_TYPE_BITMAP
, resource
->type
);
729 DCHECK(resource
->allocated
);
730 DCHECK_EQ(RGBA_8888
, resource
->format
);
731 DCHECK(source_rect
.x() >= image_rect
.x());
732 DCHECK(source_rect
.y() >= image_rect
.y());
733 DCHECK(source_rect
.right() <= image_rect
.right());
734 DCHECK(source_rect
.bottom() <= image_rect
.bottom());
735 SkImageInfo source_info
=
736 SkImageInfo::MakeN32Premul(source_rect
.width(), source_rect
.height());
737 size_t image_row_bytes
= image_rect
.width() * 4;
738 gfx::Vector2d source_offset
= source_rect
.origin() - image_rect
.origin();
739 image
+= source_offset
.y() * image_row_bytes
+ source_offset
.x() * 4;
741 ScopedWriteLockSoftware
lock(this, id
);
742 SkCanvas
dest(lock
.sk_bitmap());
743 dest
.writePixels(source_info
, image
, image_row_bytes
, dest_offset
.x(),
748 void ResourceProvider::CopyToResource(ResourceId id
,
749 const uint8_t* image
,
750 const gfx::Size
& image_size
) {
751 Resource
* resource
= GetResource(id
);
752 DCHECK(!resource
->locked_for_write
);
753 DCHECK(!resource
->lock_for_read_count
);
754 DCHECK(resource
->origin
== Resource::INTERNAL
);
755 DCHECK_EQ(resource
->exported_count
, 0);
756 DCHECK(ReadLockFenceHasPassed(resource
));
757 LazyAllocate(resource
);
759 DCHECK_EQ(image_size
.width(), resource
->size
.width());
760 DCHECK_EQ(image_size
.height(), resource
->size
.height());
762 if (resource
->type
== RESOURCE_TYPE_BITMAP
) {
763 DCHECK_EQ(RESOURCE_TYPE_BITMAP
, resource
->type
);
764 DCHECK(resource
->allocated
);
765 DCHECK_EQ(RGBA_8888
, resource
->format
);
766 SkImageInfo source_info
=
767 SkImageInfo::MakeN32Premul(image_size
.width(), image_size
.height());
768 size_t image_stride
= image_size
.width() * 4;
770 ScopedWriteLockSoftware
lock(this, id
);
771 SkCanvas
dest(lock
.sk_bitmap());
772 dest
.writePixels(source_info
, image
, image_stride
, 0, 0);
774 DCHECK(resource
->gl_id
);
775 DCHECK(!resource
->pending_set_pixels
);
776 DCHECK_EQ(resource
->target
, static_cast<GLenum
>(GL_TEXTURE_2D
));
777 GLES2Interface
* gl
= ContextGL();
779 DCHECK(texture_uploader_
.get());
780 gl
->BindTexture(GL_TEXTURE_2D
, resource
->gl_id
);
782 if (resource
->format
== ETC1
) {
783 size_t num_bytes
= static_cast<size_t>(image_size
.width()) *
784 image_size
.height() * BitsPerPixel(ETC1
) / 8;
785 gl
->CompressedTexImage2D(GL_TEXTURE_2D
, 0, GLInternalFormat(ETC1
),
786 image_size
.width(), image_size
.height(), 0,
789 gl
->TexSubImage2D(GL_TEXTURE_2D
, 0, 0, 0, image_size
.width(),
790 image_size
.height(), GLDataFormat(resource
->format
),
791 GLDataType(resource
->format
), image
);
796 size_t ResourceProvider::NumBlockingUploads() {
797 if (!texture_uploader_
)
800 return texture_uploader_
->NumBlockingUploads();
803 void ResourceProvider::MarkPendingUploadsAsNonBlocking() {
804 if (!texture_uploader_
)
807 texture_uploader_
->MarkPendingUploadsAsNonBlocking();
810 size_t ResourceProvider::EstimatedUploadsPerTick() {
811 if (!texture_uploader_
)
814 double textures_per_second
= texture_uploader_
->EstimatedTexturesPerSecond();
815 size_t textures_per_tick
= floor(
816 kTextureUploadTickRate
* textures_per_second
);
817 return textures_per_tick
? textures_per_tick
: 1u;
820 void ResourceProvider::FlushUploads() {
821 if (!texture_uploader_
)
824 texture_uploader_
->Flush();
827 void ResourceProvider::ReleaseCachedData() {
828 if (!texture_uploader_
)
831 texture_uploader_
->ReleaseCachedQueries();
834 base::TimeTicks
ResourceProvider::EstimatedUploadCompletionTime(
835 size_t uploads_per_tick
) {
836 if (lost_output_surface_
)
837 return base::TimeTicks();
839 // Software resource uploads happen on impl thread, so don't bother batching
840 // them up and trying to wait for them to complete.
841 if (!texture_uploader_
) {
842 return gfx::FrameTime::Now() + base::TimeDelta::FromMicroseconds(
843 base::Time::kMicrosecondsPerSecond
* kSoftwareUploadTickRate
);
846 base::TimeDelta upload_one_texture_time
=
847 base::TimeDelta::FromMicroseconds(
848 base::Time::kMicrosecondsPerSecond
* kTextureUploadTickRate
) /
851 size_t total_uploads
= NumBlockingUploads() + uploads_per_tick
;
852 return gfx::FrameTime::Now() + upload_one_texture_time
* total_uploads
;
855 ResourceProvider::Resource
* ResourceProvider::InsertResource(
857 const Resource
& resource
) {
858 std::pair
<ResourceMap::iterator
, bool> result
=
859 resources_
.insert(ResourceMap::value_type(id
, resource
));
860 DCHECK(result
.second
);
861 return &result
.first
->second
;
864 ResourceProvider::Resource
* ResourceProvider::GetResource(ResourceId id
) {
865 DCHECK(thread_checker_
.CalledOnValidThread());
867 ResourceMap::iterator it
= resources_
.find(id
);
868 DCHECK(it
!= resources_
.end());
872 const ResourceProvider::Resource
* ResourceProvider::LockForRead(ResourceId id
) {
873 Resource
* resource
= GetResource(id
);
874 DCHECK(!resource
->locked_for_write
||
875 resource
->set_pixels_completion_forced
) <<
876 "locked for write: " << resource
->locked_for_write
<<
877 " pixels completion forced: " << resource
->set_pixels_completion_forced
;
878 DCHECK_EQ(resource
->exported_count
, 0);
879 // Uninitialized! Call SetPixels or LockForWrite first.
880 DCHECK(resource
->allocated
);
882 LazyCreate(resource
);
884 if (resource
->type
== RESOURCE_TYPE_GL_TEXTURE
&& !resource
->gl_id
) {
885 DCHECK(resource
->origin
!= Resource::INTERNAL
);
886 DCHECK(resource
->mailbox
.IsTexture());
888 // Mailbox sync_points must be processed by a call to
889 // WaitSyncPointIfNeeded() prior to calling LockForRead().
890 DCHECK(!resource
->mailbox
.sync_point());
892 GLES2Interface
* gl
= ContextGL();
894 resource
->gl_id
= gl
->CreateAndConsumeTextureCHROMIUM(
895 resource
->mailbox
.target(), resource
->mailbox
.name());
898 if (!resource
->pixels
&& resource
->has_shared_bitmap_id
&&
899 shared_bitmap_manager_
) {
900 scoped_ptr
<SharedBitmap
> bitmap
=
901 shared_bitmap_manager_
->GetSharedBitmapFromId(
902 resource
->size
, resource
->shared_bitmap_id
);
904 resource
->shared_bitmap
= bitmap
.release();
905 resource
->pixels
= resource
->shared_bitmap
->pixels();
909 resource
->lock_for_read_count
++;
910 if (resource
->read_lock_fences_enabled
) {
911 if (current_read_lock_fence_
.get())
912 current_read_lock_fence_
->Set();
913 resource
->read_lock_fence
= current_read_lock_fence_
;
919 void ResourceProvider::UnlockForRead(ResourceId id
) {
920 DCHECK(thread_checker_
.CalledOnValidThread());
921 ResourceMap::iterator it
= resources_
.find(id
);
922 CHECK(it
!= resources_
.end());
924 Resource
* resource
= &it
->second
;
925 DCHECK_GT(resource
->lock_for_read_count
, 0);
926 DCHECK_EQ(resource
->exported_count
, 0);
927 resource
->lock_for_read_count
--;
928 if (resource
->marked_for_deletion
&& !resource
->lock_for_read_count
) {
929 if (!resource
->child_id
) {
930 // The resource belongs to this ResourceProvider, so it can be destroyed.
931 DeleteResourceInternal(it
, NORMAL
);
933 ChildMap::iterator child_it
= children_
.find(resource
->child_id
);
934 ResourceIdArray unused
;
935 unused
.push_back(id
);
936 DeleteAndReturnUnusedResourcesToChild(child_it
, NORMAL
, unused
);
941 ResourceProvider::Resource
* ResourceProvider::LockForWrite(ResourceId id
) {
942 Resource
* resource
= GetResource(id
);
943 DCHECK(CanLockForWrite(id
));
945 resource
->locked_for_write
= true;
949 bool ResourceProvider::CanLockForWrite(ResourceId id
) {
950 Resource
* resource
= GetResource(id
);
951 return !resource
->locked_for_write
&& !resource
->lock_for_read_count
&&
952 !resource
->exported_count
&& resource
->origin
== Resource::INTERNAL
&&
953 !resource
->lost
&& ReadLockFenceHasPassed(resource
);
956 void ResourceProvider::UnlockForWrite(ResourceProvider::Resource
* resource
) {
957 DCHECK(resource
->locked_for_write
);
958 DCHECK_EQ(resource
->exported_count
, 0);
959 DCHECK(resource
->origin
== Resource::INTERNAL
);
960 resource
->locked_for_write
= false;
963 ResourceProvider::ScopedReadLockGL::ScopedReadLockGL(
964 ResourceProvider
* resource_provider
,
965 ResourceProvider::ResourceId resource_id
)
966 : resource_provider_(resource_provider
),
967 resource_id_(resource_id
),
968 texture_id_(resource_provider
->LockForRead(resource_id
)->gl_id
) {
972 ResourceProvider::ScopedReadLockGL::~ScopedReadLockGL() {
973 resource_provider_
->UnlockForRead(resource_id_
);
976 ResourceProvider::ScopedSamplerGL::ScopedSamplerGL(
977 ResourceProvider
* resource_provider
,
978 ResourceProvider::ResourceId resource_id
,
980 : ScopedReadLockGL(resource_provider
, resource_id
),
982 target_(resource_provider
->BindForSampling(resource_id
, unit_
, filter
)) {
985 ResourceProvider::ScopedSamplerGL::ScopedSamplerGL(
986 ResourceProvider
* resource_provider
,
987 ResourceProvider::ResourceId resource_id
,
990 : ScopedReadLockGL(resource_provider
, resource_id
),
992 target_(resource_provider
->BindForSampling(resource_id
, unit_
, filter
)) {
995 ResourceProvider::ScopedSamplerGL::~ScopedSamplerGL() {
998 ResourceProvider::ScopedWriteLockGL::ScopedWriteLockGL(
999 ResourceProvider
* resource_provider
,
1000 ResourceProvider::ResourceId resource_id
)
1001 : resource_provider_(resource_provider
),
1002 resource_(resource_provider
->LockForWrite(resource_id
)) {
1003 resource_provider_
->LazyAllocate(resource_
);
1004 texture_id_
= resource_
->gl_id
;
1005 DCHECK(texture_id_
);
1008 ResourceProvider::ScopedWriteLockGL::~ScopedWriteLockGL() {
1009 resource_provider_
->UnlockForWrite(resource_
);
1012 void ResourceProvider::PopulateSkBitmapWithResource(
1013 SkBitmap
* sk_bitmap
, const Resource
* resource
) {
1014 DCHECK_EQ(RGBA_8888
, resource
->format
);
1015 SkImageInfo info
= SkImageInfo::MakeN32Premul(resource
->size
.width(),
1016 resource
->size
.height());
1017 sk_bitmap
->installPixels(info
, resource
->pixels
, info
.minRowBytes());
1020 ResourceProvider::ScopedReadLockSoftware::ScopedReadLockSoftware(
1021 ResourceProvider
* resource_provider
,
1022 ResourceProvider::ResourceId resource_id
)
1023 : resource_provider_(resource_provider
),
1024 resource_id_(resource_id
) {
1025 const Resource
* resource
= resource_provider
->LockForRead(resource_id
);
1026 wrap_mode_
= resource
->wrap_mode
;
1027 ResourceProvider::PopulateSkBitmapWithResource(&sk_bitmap_
, resource
);
1030 ResourceProvider::ScopedReadLockSoftware::~ScopedReadLockSoftware() {
1031 resource_provider_
->UnlockForRead(resource_id_
);
1034 ResourceProvider::ScopedWriteLockSoftware::ScopedWriteLockSoftware(
1035 ResourceProvider
* resource_provider
,
1036 ResourceProvider::ResourceId resource_id
)
1037 : resource_provider_(resource_provider
),
1038 resource_(resource_provider
->LockForWrite(resource_id
)) {
1039 ResourceProvider::PopulateSkBitmapWithResource(&sk_bitmap_
, resource_
);
1043 ResourceProvider::ScopedWriteLockSoftware::~ScopedWriteLockSoftware() {
1044 DCHECK(thread_checker_
.CalledOnValidThread());
1045 resource_provider_
->UnlockForWrite(resource_
);
1048 ResourceProvider::ScopedWriteLockGpuMemoryBuffer::
1049 ScopedWriteLockGpuMemoryBuffer(ResourceProvider
* resource_provider
,
1050 ResourceProvider::ResourceId resource_id
)
1051 : resource_provider_(resource_provider
),
1052 resource_(resource_provider
->LockForWrite(resource_id
)),
1053 gpu_memory_buffer_manager_(resource_provider
->gpu_memory_buffer_manager_
),
1054 gpu_memory_buffer_(nullptr),
1055 size_(resource_
->size
),
1056 format_(resource_
->format
) {
1057 DCHECK_EQ(RESOURCE_TYPE_GL_TEXTURE
, resource_
->type
);
1058 std::swap(gpu_memory_buffer_
, resource_
->gpu_memory_buffer
);
1061 ResourceProvider::ScopedWriteLockGpuMemoryBuffer::
1062 ~ScopedWriteLockGpuMemoryBuffer() {
1063 DCHECK(thread_checker_
.CalledOnValidThread());
1064 resource_provider_
->UnlockForWrite(resource_
);
1065 if (!gpu_memory_buffer_
)
1068 if (!resource_
->image_id
) {
1069 GLES2Interface
* gl
= resource_provider_
->ContextGL();
1072 #if defined(OS_CHROMEOS)
1073 // TODO(reveman): GL_COMMANDS_ISSUED_CHROMIUM is used for synchronization
1074 // on ChromeOS to avoid some performance issues. This only works with
1075 // shared memory backed buffers. crbug.com/436314
1076 DCHECK_EQ(gpu_memory_buffer_
->GetHandle().type
, gfx::SHARED_MEMORY_BUFFER
);
1079 resource_
->image_id
= gl
->CreateImageCHROMIUM(
1080 gpu_memory_buffer_
->AsClientBuffer(), size_
.width(), size_
.height(),
1081 GLInternalFormat(resource_
->format
));
1084 std::swap(resource_
->gpu_memory_buffer
, gpu_memory_buffer_
);
1085 resource_
->allocated
= true;
1086 resource_
->dirty_image
= true;
1088 // GpuMemoryBuffer provides direct access to the memory used by the GPU.
1089 // Read lock fences are required to ensure that we're not trying to map a
1090 // buffer that is currently in-use by the GPU.
1091 resource_
->read_lock_fences_enabled
= true;
1094 gfx::GpuMemoryBuffer
*
1095 ResourceProvider::ScopedWriteLockGpuMemoryBuffer::GetGpuMemoryBuffer() {
1096 if (!gpu_memory_buffer_
) {
1097 scoped_ptr
<gfx::GpuMemoryBuffer
> gpu_memory_buffer
=
1098 gpu_memory_buffer_manager_
->AllocateGpuMemoryBuffer(
1099 size_
, ToGpuMemoryBufferFormat(format_
), gfx::GpuMemoryBuffer::MAP
);
1100 gpu_memory_buffer_
= gpu_memory_buffer
.release();
1103 return gpu_memory_buffer_
;
1106 ResourceProvider::ScopedWriteLockGr::ScopedWriteLockGr(
1107 ResourceProvider
* resource_provider
,
1108 ResourceProvider::ResourceId resource_id
)
1109 : resource_provider_(resource_provider
),
1110 resource_(resource_provider
->LockForWrite(resource_id
)) {
1111 DCHECK(thread_checker_
.CalledOnValidThread());
1112 resource_provider_
->LazyAllocate(resource_
);
1115 ResourceProvider::ScopedWriteLockGr::~ScopedWriteLockGr() {
1116 DCHECK(thread_checker_
.CalledOnValidThread());
1117 DCHECK(resource_
->locked_for_write
);
1118 resource_provider_
->UnlockForWrite(resource_
);
1121 void ResourceProvider::ScopedWriteLockGr::InitSkSurface(
1122 bool use_distance_field_text
,
1123 bool can_use_lcd_text
,
1124 int msaa_sample_count
) {
1125 DCHECK(resource_
->locked_for_write
);
1127 GrBackendTextureDesc desc
;
1128 desc
.fFlags
= kRenderTarget_GrBackendTextureFlag
;
1129 desc
.fWidth
= resource_
->size
.width();
1130 desc
.fHeight
= resource_
->size
.height();
1131 desc
.fConfig
= ToGrPixelConfig(resource_
->format
);
1132 desc
.fOrigin
= kTopLeft_GrSurfaceOrigin
;
1133 desc
.fTextureHandle
= resource_
->gl_id
;
1134 desc
.fSampleCnt
= msaa_sample_count
;
1136 bool use_worker_context
= true;
1137 class GrContext
* gr_context
=
1138 resource_provider_
->GrContext(use_worker_context
);
1139 skia::RefPtr
<GrTexture
> gr_texture
=
1140 skia::AdoptRef(gr_context
->wrapBackendTexture(desc
));
1142 uint32_t flags
= use_distance_field_text
1143 ? SkSurfaceProps::kUseDistanceFieldFonts_Flag
1145 // Use unknown pixel geometry to disable LCD text.
1146 SkSurfaceProps
surface_props(flags
, kUnknown_SkPixelGeometry
);
1147 if (can_use_lcd_text
) {
1148 // LegacyFontHost will get LCD text and skia figures out what type to use.
1150 SkSurfaceProps(flags
, SkSurfaceProps::kLegacyFontHost_InitType
);
1152 sk_surface_
= skia::AdoptRef(SkSurface::NewRenderTargetDirect(
1153 gr_texture
->asRenderTarget(), &surface_props
));
1156 sk_surface_
.clear();
1159 void ResourceProvider::ScopedWriteLockGr::ReleaseSkSurface() {
1160 sk_surface_
.clear();
1163 ResourceProvider::SynchronousFence::SynchronousFence(
1164 gpu::gles2::GLES2Interface
* gl
)
1165 : gl_(gl
), has_synchronized_(true) {
1168 ResourceProvider::SynchronousFence::~SynchronousFence() {
1171 void ResourceProvider::SynchronousFence::Set() {
1172 has_synchronized_
= false;
1175 bool ResourceProvider::SynchronousFence::HasPassed() {
1176 if (!has_synchronized_
) {
1177 has_synchronized_
= true;
1183 void ResourceProvider::SynchronousFence::Wait() {
1187 void ResourceProvider::SynchronousFence::Synchronize() {
1188 TRACE_EVENT0("cc", "ResourceProvider::SynchronousFence::Synchronize");
1192 ResourceProvider::ResourceProvider(
1193 OutputSurface
* output_surface
,
1194 SharedBitmapManager
* shared_bitmap_manager
,
1195 gpu::GpuMemoryBufferManager
* gpu_memory_buffer_manager
,
1196 BlockingTaskRunner
* blocking_main_thread_task_runner
,
1197 int highp_threshold_min
,
1198 ResourceType default_resource_type
,
1199 bool use_rgba_4444_texture_format
,
1200 size_t id_allocation_chunk_size
)
1201 : output_surface_(output_surface
),
1202 shared_bitmap_manager_(shared_bitmap_manager
),
1203 gpu_memory_buffer_manager_(gpu_memory_buffer_manager
),
1204 blocking_main_thread_task_runner_(blocking_main_thread_task_runner
),
1205 lost_output_surface_(false),
1206 highp_threshold_min_(highp_threshold_min
),
1209 default_resource_type_(default_resource_type
),
1210 use_texture_storage_ext_(false),
1211 use_texture_format_bgra_(false),
1212 use_texture_usage_hint_(false),
1213 use_compressed_texture_etc1_(false),
1214 yuv_resource_format_(LUMINANCE_8
),
1215 max_texture_size_(0),
1216 best_texture_format_(RGBA_8888
),
1217 use_rgba_4444_texture_format_(use_rgba_4444_texture_format
),
1218 id_allocation_chunk_size_(id_allocation_chunk_size
),
1219 use_sync_query_(false) {
1220 DCHECK(output_surface_
->HasClient());
1221 DCHECK(id_allocation_chunk_size_
);
1224 void ResourceProvider::InitializeSoftware() {
1225 DCHECK(thread_checker_
.CalledOnValidThread());
1226 DCHECK_EQ(default_resource_type_
, RESOURCE_TYPE_BITMAP
);
1227 // Pick an arbitrary limit here similar to what hardware might.
1228 max_texture_size_
= 16 * 1024;
1229 best_texture_format_
= RGBA_8888
;
1232 void ResourceProvider::InitializeGL() {
1233 DCHECK(thread_checker_
.CalledOnValidThread());
1234 DCHECK_EQ(default_resource_type_
, RESOURCE_TYPE_GL_TEXTURE
);
1235 DCHECK(!texture_uploader_
);
1236 DCHECK(!texture_id_allocator_
);
1237 DCHECK(!buffer_id_allocator_
);
1239 const ContextProvider::Capabilities
& caps
=
1240 output_surface_
->context_provider()->ContextCapabilities();
1242 bool use_bgra
= caps
.gpu
.texture_format_bgra8888
;
1243 use_texture_storage_ext_
= caps
.gpu
.texture_storage
;
1244 use_texture_format_bgra_
= caps
.gpu
.texture_format_bgra8888
;
1245 use_texture_usage_hint_
= caps
.gpu
.texture_usage
;
1246 use_compressed_texture_etc1_
= caps
.gpu
.texture_format_etc1
;
1247 yuv_resource_format_
= caps
.gpu
.texture_rg
? RED_8
: LUMINANCE_8
;
1248 use_sync_query_
= caps
.gpu
.sync_query
;
1250 GLES2Interface
* gl
= ContextGL();
1253 texture_uploader_
= TextureUploader::Create(gl
);
1254 max_texture_size_
= 0; // Context expects cleared value.
1255 gl
->GetIntegerv(GL_MAX_TEXTURE_SIZE
, &max_texture_size_
);
1256 best_texture_format_
= PlatformColor::BestTextureFormat(use_bgra
);
1258 texture_id_allocator_
.reset(
1259 new TextureIdAllocator(gl
, id_allocation_chunk_size_
));
1260 buffer_id_allocator_
.reset(
1261 new BufferIdAllocator(gl
, id_allocation_chunk_size_
));
1264 int ResourceProvider::CreateChild(const ReturnCallback
& return_callback
) {
1265 DCHECK(thread_checker_
.CalledOnValidThread());
1268 child_info
.return_callback
= return_callback
;
1270 int child
= next_child_
++;
1271 children_
[child
] = child_info
;
1275 void ResourceProvider::SetChildNeedsSyncPoints(int child_id
, bool needs
) {
1276 ChildMap::iterator it
= children_
.find(child_id
);
1277 DCHECK(it
!= children_
.end());
1278 it
->second
.needs_sync_points
= needs
;
1281 void ResourceProvider::DestroyChild(int child_id
) {
1282 ChildMap::iterator it
= children_
.find(child_id
);
1283 DCHECK(it
!= children_
.end());
1284 DestroyChildInternal(it
, NORMAL
);
1287 void ResourceProvider::DestroyChildInternal(ChildMap::iterator it
,
1288 DeleteStyle style
) {
1289 DCHECK(thread_checker_
.CalledOnValidThread());
1291 Child
& child
= it
->second
;
1292 DCHECK(style
== FOR_SHUTDOWN
|| !child
.marked_for_deletion
);
1294 ResourceIdArray resources_for_child
;
1296 for (ResourceIdMap::iterator child_it
= child
.child_to_parent_map
.begin();
1297 child_it
!= child
.child_to_parent_map
.end();
1299 ResourceId id
= child_it
->second
;
1300 resources_for_child
.push_back(id
);
1303 child
.marked_for_deletion
= true;
1305 DeleteAndReturnUnusedResourcesToChild(it
, style
, resources_for_child
);
1308 const ResourceProvider::ResourceIdMap
& ResourceProvider::GetChildToParentMap(
1310 DCHECK(thread_checker_
.CalledOnValidThread());
1311 ChildMap::const_iterator it
= children_
.find(child
);
1312 DCHECK(it
!= children_
.end());
1313 DCHECK(!it
->second
.marked_for_deletion
);
1314 return it
->second
.child_to_parent_map
;
1317 void ResourceProvider::PrepareSendToParent(const ResourceIdArray
& resources
,
1318 TransferableResourceArray
* list
) {
1319 DCHECK(thread_checker_
.CalledOnValidThread());
1320 GLES2Interface
* gl
= ContextGL();
1321 bool need_sync_point
= false;
1322 for (ResourceIdArray::const_iterator it
= resources
.begin();
1323 it
!= resources
.end();
1325 TransferableResource resource
;
1326 TransferResource(gl
, *it
, &resource
);
1327 if (!resource
.mailbox_holder
.sync_point
&& !resource
.is_software
)
1328 need_sync_point
= true;
1329 ++resources_
.find(*it
)->second
.exported_count
;
1330 list
->push_back(resource
);
1332 if (need_sync_point
&&
1333 output_surface_
->capabilities().delegated_sync_points_required
) {
1334 GLuint sync_point
= gl
->InsertSyncPointCHROMIUM();
1335 for (TransferableResourceArray::iterator it
= list
->begin();
1338 if (!it
->mailbox_holder
.sync_point
)
1339 it
->mailbox_holder
.sync_point
= sync_point
;
1344 void ResourceProvider::ReceiveFromChild(
1345 int child
, const TransferableResourceArray
& resources
) {
1346 DCHECK(thread_checker_
.CalledOnValidThread());
1347 GLES2Interface
* gl
= ContextGL();
1348 Child
& child_info
= children_
.find(child
)->second
;
1349 DCHECK(!child_info
.marked_for_deletion
);
1350 for (TransferableResourceArray::const_iterator it
= resources
.begin();
1351 it
!= resources
.end();
1353 ResourceIdMap::iterator resource_in_map_it
=
1354 child_info
.child_to_parent_map
.find(it
->id
);
1355 if (resource_in_map_it
!= child_info
.child_to_parent_map
.end()) {
1356 Resource
* resource
= GetResource(resource_in_map_it
->second
);
1357 resource
->marked_for_deletion
= false;
1358 resource
->imported_count
++;
1362 if ((!it
->is_software
&& !gl
) ||
1363 (it
->is_software
&& !shared_bitmap_manager_
)) {
1364 TRACE_EVENT0("cc", "ResourceProvider::ReceiveFromChild dropping invalid");
1365 ReturnedResourceArray to_return
;
1366 to_return
.push_back(it
->ToReturnedResource());
1367 child_info
.return_callback
.Run(to_return
,
1368 blocking_main_thread_task_runner_
);
1372 ResourceId local_id
= next_id_
++;
1373 Resource
* resource
= nullptr;
1374 if (it
->is_software
) {
1375 resource
= InsertResource(
1377 Resource(it
->mailbox_holder
.mailbox
, it
->size
, Resource::DELEGATED
,
1378 GL_LINEAR
, it
->is_repeated
? GL_REPEAT
: GL_CLAMP_TO_EDGE
));
1380 resource
= InsertResource(
1381 local_id
, Resource(0, it
->size
, Resource::DELEGATED
,
1382 it
->mailbox_holder
.texture_target
, it
->filter
, 0,
1383 it
->is_repeated
? GL_REPEAT
: GL_CLAMP_TO_EDGE
,
1384 TEXTURE_HINT_IMMUTABLE
, it
->format
));
1385 resource
->mailbox
= TextureMailbox(it
->mailbox_holder
.mailbox
,
1386 it
->mailbox_holder
.texture_target
,
1387 it
->mailbox_holder
.sync_point
);
1389 resource
->child_id
= child
;
1390 // Don't allocate a texture for a child.
1391 resource
->allocated
= true;
1392 resource
->imported_count
= 1;
1393 resource
->allow_overlay
= it
->allow_overlay
;
1394 child_info
.parent_to_child_map
[local_id
] = it
->id
;
1395 child_info
.child_to_parent_map
[it
->id
] = local_id
;
1399 void ResourceProvider::DeclareUsedResourcesFromChild(
1401 const ResourceIdSet
& resources_from_child
) {
1402 DCHECK(thread_checker_
.CalledOnValidThread());
1404 ChildMap::iterator child_it
= children_
.find(child
);
1405 DCHECK(child_it
!= children_
.end());
1406 Child
& child_info
= child_it
->second
;
1407 DCHECK(!child_info
.marked_for_deletion
);
1409 ResourceIdArray unused
;
1410 for (ResourceIdMap::iterator it
= child_info
.child_to_parent_map
.begin();
1411 it
!= child_info
.child_to_parent_map
.end();
1413 ResourceId local_id
= it
->second
;
1414 bool resource_is_in_use
= resources_from_child
.count(it
->first
) > 0;
1415 if (!resource_is_in_use
)
1416 unused
.push_back(local_id
);
1418 DeleteAndReturnUnusedResourcesToChild(child_it
, NORMAL
, unused
);
1421 void ResourceProvider::ReceiveReturnsFromParent(
1422 const ReturnedResourceArray
& resources
) {
1423 DCHECK(thread_checker_
.CalledOnValidThread());
1424 GLES2Interface
* gl
= ContextGL();
1426 base::hash_map
<int, ResourceIdArray
> resources_for_child
;
1428 for (const ReturnedResource
& returned
: resources
) {
1429 ResourceId local_id
= returned
.id
;
1430 ResourceMap::iterator map_iterator
= resources_
.find(local_id
);
1431 // Resource was already lost (e.g. it belonged to a child that was
1433 if (map_iterator
== resources_
.end())
1436 Resource
* resource
= &map_iterator
->second
;
1438 CHECK_GE(resource
->exported_count
, returned
.count
);
1439 resource
->exported_count
-= returned
.count
;
1440 resource
->lost
|= returned
.lost
;
1441 if (resource
->exported_count
)
1444 // Need to wait for the current read lock fence to pass before we can
1445 // recycle this resource.
1446 if (resource
->read_lock_fences_enabled
) {
1447 if (current_read_lock_fence_
.get())
1448 current_read_lock_fence_
->Set();
1449 resource
->read_lock_fence
= current_read_lock_fence_
;
1452 if (returned
.sync_point
) {
1453 DCHECK(!resource
->has_shared_bitmap_id
);
1454 if (resource
->origin
== Resource::INTERNAL
) {
1455 DCHECK(resource
->gl_id
);
1456 gl
->WaitSyncPointCHROMIUM(returned
.sync_point
);
1458 DCHECK(!resource
->gl_id
);
1459 resource
->mailbox
.set_sync_point(returned
.sync_point
);
1463 if (!resource
->marked_for_deletion
)
1466 if (!resource
->child_id
) {
1467 // The resource belongs to this ResourceProvider, so it can be destroyed.
1468 DeleteResourceInternal(map_iterator
, NORMAL
);
1472 DCHECK(resource
->origin
== Resource::DELEGATED
);
1473 resources_for_child
[resource
->child_id
].push_back(local_id
);
1476 for (const auto& children
: resources_for_child
) {
1477 ChildMap::iterator child_it
= children_
.find(children
.first
);
1478 DCHECK(child_it
!= children_
.end());
1479 DeleteAndReturnUnusedResourcesToChild(child_it
, NORMAL
, children
.second
);
1483 void ResourceProvider::TransferResource(GLES2Interface
* gl
,
1485 TransferableResource
* resource
) {
1486 Resource
* source
= GetResource(id
);
1487 DCHECK(!source
->locked_for_write
);
1488 DCHECK(!source
->lock_for_read_count
);
1489 DCHECK(source
->origin
!= Resource::EXTERNAL
|| source
->mailbox
.IsValid());
1490 DCHECK(source
->allocated
);
1492 resource
->format
= source
->format
;
1493 resource
->mailbox_holder
.texture_target
= source
->target
;
1494 resource
->filter
= source
->filter
;
1495 resource
->size
= source
->size
;
1496 resource
->is_repeated
= (source
->wrap_mode
== GL_REPEAT
);
1497 resource
->allow_overlay
= source
->allow_overlay
;
1499 if (source
->type
== RESOURCE_TYPE_BITMAP
) {
1500 resource
->mailbox_holder
.mailbox
= source
->shared_bitmap_id
;
1501 resource
->is_software
= true;
1502 } else if (!source
->mailbox
.IsValid()) {
1504 DCHECK(source
->gl_id
);
1505 DCHECK(source
->origin
== Resource::INTERNAL
);
1506 if (source
->image_id
) {
1507 DCHECK(source
->dirty_image
);
1508 BindImageForSampling(source
);
1510 // This is a resource allocated by the compositor, we need to produce it.
1511 // Don't set a sync point, the caller will do it.
1512 gl
->GenMailboxCHROMIUM(resource
->mailbox_holder
.mailbox
.name
);
1513 gl
->ProduceTextureDirectCHROMIUM(source
->gl_id
,
1514 resource
->mailbox_holder
.texture_target
,
1515 resource
->mailbox_holder
.mailbox
.name
);
1517 source
->mailbox
= TextureMailbox(resource
->mailbox_holder
);
1519 DCHECK(source
->mailbox
.IsTexture());
1520 if (source
->image_id
&& source
->dirty_image
) {
1521 DCHECK(source
->gl_id
);
1522 DCHECK(source
->origin
== Resource::INTERNAL
);
1523 gl
->BindTexture(resource
->mailbox_holder
.texture_target
, source
->gl_id
);
1524 BindImageForSampling(source
);
1526 // This is either an external resource, or a compositor resource that we
1527 // already exported. Make sure to forward the sync point that we were given.
1528 resource
->mailbox_holder
.mailbox
= source
->mailbox
.mailbox();
1529 resource
->mailbox_holder
.texture_target
= source
->mailbox
.target();
1530 resource
->mailbox_holder
.sync_point
= source
->mailbox
.sync_point();
1531 source
->mailbox
.set_sync_point(0);
1535 void ResourceProvider::DeleteAndReturnUnusedResourcesToChild(
1536 ChildMap::iterator child_it
,
1538 const ResourceIdArray
& unused
) {
1539 DCHECK(thread_checker_
.CalledOnValidThread());
1540 DCHECK(child_it
!= children_
.end());
1541 Child
* child_info
= &child_it
->second
;
1543 if (unused
.empty() && !child_info
->marked_for_deletion
)
1546 ReturnedResourceArray to_return
;
1548 GLES2Interface
* gl
= ContextGL();
1549 bool need_sync_point
= false;
1550 for (size_t i
= 0; i
< unused
.size(); ++i
) {
1551 ResourceId local_id
= unused
[i
];
1553 ResourceMap::iterator it
= resources_
.find(local_id
);
1554 CHECK(it
!= resources_
.end());
1555 Resource
& resource
= it
->second
;
1557 DCHECK(!resource
.locked_for_write
);
1558 DCHECK(child_info
->parent_to_child_map
.count(local_id
));
1560 ResourceId child_id
= child_info
->parent_to_child_map
[local_id
];
1561 DCHECK(child_info
->child_to_parent_map
.count(child_id
));
1565 (resource
.type
== RESOURCE_TYPE_GL_TEXTURE
&& lost_output_surface_
);
1566 if (resource
.exported_count
> 0 || resource
.lock_for_read_count
> 0) {
1567 if (style
!= FOR_SHUTDOWN
) {
1568 // Defer this until we receive the resource back from the parent or
1569 // the read lock is released.
1570 resource
.marked_for_deletion
= true;
1574 // We still have an exported_count, so we'll have to lose it.
1578 if (gl
&& resource
.filter
!= resource
.original_filter
) {
1579 DCHECK(resource
.target
);
1580 DCHECK(resource
.gl_id
);
1582 gl
->BindTexture(resource
.target
, resource
.gl_id
);
1583 gl
->TexParameteri(resource
.target
, GL_TEXTURE_MIN_FILTER
,
1584 resource
.original_filter
);
1585 gl
->TexParameteri(resource
.target
, GL_TEXTURE_MAG_FILTER
,
1586 resource
.original_filter
);
1589 ReturnedResource returned
;
1590 returned
.id
= child_id
;
1591 returned
.sync_point
= resource
.mailbox
.sync_point();
1592 if (!returned
.sync_point
&& resource
.type
== RESOURCE_TYPE_GL_TEXTURE
)
1593 need_sync_point
= true;
1594 returned
.count
= resource
.imported_count
;
1595 returned
.lost
= is_lost
;
1596 to_return
.push_back(returned
);
1598 child_info
->parent_to_child_map
.erase(local_id
);
1599 child_info
->child_to_parent_map
.erase(child_id
);
1600 resource
.imported_count
= 0;
1601 DeleteResourceInternal(it
, style
);
1603 if (need_sync_point
&& child_info
->needs_sync_points
) {
1605 GLuint sync_point
= gl
->InsertSyncPointCHROMIUM();
1606 for (size_t i
= 0; i
< to_return
.size(); ++i
) {
1607 if (!to_return
[i
].sync_point
)
1608 to_return
[i
].sync_point
= sync_point
;
1612 if (!to_return
.empty())
1613 child_info
->return_callback
.Run(to_return
,
1614 blocking_main_thread_task_runner_
);
1616 if (child_info
->marked_for_deletion
&&
1617 child_info
->parent_to_child_map
.empty()) {
1618 DCHECK(child_info
->child_to_parent_map
.empty());
1619 children_
.erase(child_it
);
1623 void ResourceProvider::AcquirePixelBuffer(ResourceId id
) {
1624 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug"),
1625 "ResourceProvider::AcquirePixelBuffer");
1627 Resource
* resource
= GetResource(id
);
1628 DCHECK(resource
->origin
== Resource::INTERNAL
);
1629 DCHECK_EQ(resource
->exported_count
, 0);
1630 DCHECK(!resource
->image_id
);
1631 DCHECK_NE(ETC1
, resource
->format
);
1633 DCHECK_EQ(RESOURCE_TYPE_GL_TEXTURE
, resource
->type
);
1634 GLES2Interface
* gl
= ContextGL();
1636 if (!resource
->gl_pixel_buffer_id
)
1637 resource
->gl_pixel_buffer_id
= buffer_id_allocator_
->NextId();
1638 gl
->BindBuffer(GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM
,
1639 resource
->gl_pixel_buffer_id
);
1640 unsigned bytes_per_pixel
= BitsPerPixel(resource
->format
) / 8;
1641 gl
->BufferData(GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM
,
1642 resource
->size
.height() *
1643 RoundUp(bytes_per_pixel
* resource
->size
.width(), 4u),
1646 gl
->BindBuffer(GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM
, 0);
1649 void ResourceProvider::ReleasePixelBuffer(ResourceId id
) {
1650 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug"),
1651 "ResourceProvider::ReleasePixelBuffer");
1653 Resource
* resource
= GetResource(id
);
1654 DCHECK(resource
->origin
== Resource::INTERNAL
);
1655 DCHECK_EQ(resource
->exported_count
, 0);
1656 DCHECK(!resource
->image_id
);
1658 // The pixel buffer can be released while there is a pending "set pixels"
1659 // if completion has been forced. Any shared memory associated with this
1660 // pixel buffer will not be freed until the waitAsyncTexImage2DCHROMIUM
1661 // command has been processed on the service side. It is also safe to
1662 // reuse any query id associated with this resource before they complete
1663 // as each new query has a unique submit count.
1664 if (resource
->pending_set_pixels
) {
1665 DCHECK(resource
->set_pixels_completion_forced
);
1666 resource
->pending_set_pixels
= false;
1667 resource
->locked_for_write
= false;
1670 DCHECK_EQ(RESOURCE_TYPE_GL_TEXTURE
, resource
->type
);
1671 if (!resource
->gl_pixel_buffer_id
)
1673 GLES2Interface
* gl
= ContextGL();
1675 gl
->BindBuffer(GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM
,
1676 resource
->gl_pixel_buffer_id
);
1678 GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM
, 0, NULL
, GL_DYNAMIC_DRAW
);
1679 gl
->BindBuffer(GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM
, 0);
1682 uint8_t* ResourceProvider::MapPixelBuffer(ResourceId id
, int* stride
) {
1683 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug"),
1684 "ResourceProvider::MapPixelBuffer");
1686 Resource
* resource
= GetResource(id
);
1687 DCHECK(resource
->origin
== Resource::INTERNAL
);
1688 DCHECK_EQ(resource
->exported_count
, 0);
1689 DCHECK(!resource
->image_id
);
1692 DCHECK_EQ(RESOURCE_TYPE_GL_TEXTURE
, resource
->type
);
1693 GLES2Interface
* gl
= ContextGL();
1695 DCHECK(resource
->gl_pixel_buffer_id
);
1696 gl
->BindBuffer(GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM
,
1697 resource
->gl_pixel_buffer_id
);
1698 uint8_t* image
= static_cast<uint8_t*>(gl
->MapBufferCHROMIUM(
1699 GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM
, GL_WRITE_ONLY
));
1700 gl
->BindBuffer(GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM
, 0);
1701 // Buffer is required to be 4-byte aligned.
1702 CHECK(!(reinterpret_cast<intptr_t>(image
) & 3));
1706 void ResourceProvider::UnmapPixelBuffer(ResourceId id
) {
1707 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug"),
1708 "ResourceProvider::UnmapPixelBuffer");
1710 Resource
* resource
= GetResource(id
);
1711 DCHECK(resource
->origin
== Resource::INTERNAL
);
1712 DCHECK_EQ(resource
->exported_count
, 0);
1713 DCHECK(!resource
->image_id
);
1715 DCHECK_EQ(RESOURCE_TYPE_GL_TEXTURE
, resource
->type
);
1716 GLES2Interface
* gl
= ContextGL();
1718 DCHECK(resource
->gl_pixel_buffer_id
);
1719 gl
->BindBuffer(GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM
,
1720 resource
->gl_pixel_buffer_id
);
1721 gl
->UnmapBufferCHROMIUM(GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM
);
1722 gl
->BindBuffer(GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM
, 0);
1725 GLenum
ResourceProvider::BindForSampling(ResourceId resource_id
,
1728 DCHECK(thread_checker_
.CalledOnValidThread());
1729 GLES2Interface
* gl
= ContextGL();
1730 ResourceMap::iterator it
= resources_
.find(resource_id
);
1731 DCHECK(it
!= resources_
.end());
1732 Resource
* resource
= &it
->second
;
1733 DCHECK(resource
->lock_for_read_count
);
1734 DCHECK(!resource
->locked_for_write
|| resource
->set_pixels_completion_forced
);
1736 ScopedSetActiveTexture
scoped_active_tex(gl
, unit
);
1737 GLenum target
= resource
->target
;
1738 gl
->BindTexture(target
, resource
->gl_id
);
1739 if (filter
!= resource
->filter
) {
1740 gl
->TexParameteri(target
, GL_TEXTURE_MIN_FILTER
, filter
);
1741 gl
->TexParameteri(target
, GL_TEXTURE_MAG_FILTER
, filter
);
1742 resource
->filter
= filter
;
1745 if (resource
->image_id
&& resource
->dirty_image
)
1746 BindImageForSampling(resource
);
1751 void ResourceProvider::BeginSetPixels(ResourceId id
) {
1752 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug"),
1753 "ResourceProvider::BeginSetPixels");
1755 Resource
* resource
= GetResource(id
);
1756 DCHECK(!resource
->pending_set_pixels
);
1758 LazyCreate(resource
);
1759 DCHECK(resource
->origin
== Resource::INTERNAL
);
1760 DCHECK(resource
->gl_id
|| resource
->allocated
);
1761 DCHECK(ReadLockFenceHasPassed(resource
));
1762 DCHECK(!resource
->image_id
);
1764 bool allocate
= !resource
->allocated
;
1765 resource
->allocated
= true;
1768 DCHECK_EQ(RESOURCE_TYPE_GL_TEXTURE
, resource
->type
);
1769 DCHECK(resource
->gl_id
);
1770 GLES2Interface
* gl
= ContextGL();
1772 DCHECK(resource
->gl_pixel_buffer_id
);
1773 DCHECK_EQ(resource
->target
, static_cast<GLenum
>(GL_TEXTURE_2D
));
1774 gl
->BindTexture(GL_TEXTURE_2D
, resource
->gl_id
);
1775 gl
->BindBuffer(GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM
,
1776 resource
->gl_pixel_buffer_id
);
1777 if (!resource
->gl_upload_query_id
)
1778 gl
->GenQueriesEXT(1, &resource
->gl_upload_query_id
);
1779 gl
->BeginQueryEXT(GL_ASYNC_PIXEL_UNPACK_COMPLETED_CHROMIUM
,
1780 resource
->gl_upload_query_id
);
1782 gl
->AsyncTexImage2DCHROMIUM(GL_TEXTURE_2D
,
1784 GLInternalFormat(resource
->format
),
1785 resource
->size
.width(),
1786 resource
->size
.height(),
1788 GLDataFormat(resource
->format
),
1789 GLDataType(resource
->format
),
1792 gl
->AsyncTexSubImage2DCHROMIUM(GL_TEXTURE_2D
,
1796 resource
->size
.width(),
1797 resource
->size
.height(),
1798 GLDataFormat(resource
->format
),
1799 GLDataType(resource
->format
),
1802 gl
->EndQueryEXT(GL_ASYNC_PIXEL_UNPACK_COMPLETED_CHROMIUM
);
1803 gl
->BindBuffer(GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM
, 0);
1805 resource
->pending_set_pixels
= true;
1806 resource
->set_pixels_completion_forced
= false;
1809 void ResourceProvider::ForceSetPixelsToComplete(ResourceId id
) {
1810 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug"),
1811 "ResourceProvider::ForceSetPixelsToComplete");
1813 Resource
* resource
= GetResource(id
);
1815 DCHECK(resource
->locked_for_write
);
1816 DCHECK(resource
->pending_set_pixels
);
1817 DCHECK(!resource
->set_pixels_completion_forced
);
1819 if (resource
->gl_id
) {
1820 GLES2Interface
* gl
= ContextGL();
1821 gl
->BindTexture(GL_TEXTURE_2D
, resource
->gl_id
);
1822 gl
->WaitAsyncTexImage2DCHROMIUM(GL_TEXTURE_2D
);
1823 gl
->BindTexture(GL_TEXTURE_2D
, 0);
1826 resource
->set_pixels_completion_forced
= true;
1829 bool ResourceProvider::DidSetPixelsComplete(ResourceId id
) {
1830 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug"),
1831 "ResourceProvider::DidSetPixelsComplete");
1833 Resource
* resource
= GetResource(id
);
1835 DCHECK(resource
->locked_for_write
);
1836 DCHECK(resource
->pending_set_pixels
);
1838 if (resource
->gl_id
) {
1839 GLES2Interface
* gl
= ContextGL();
1841 DCHECK(resource
->gl_upload_query_id
);
1842 GLuint complete
= 1;
1843 gl
->GetQueryObjectuivEXT(
1844 resource
->gl_upload_query_id
, GL_QUERY_RESULT_AVAILABLE_EXT
, &complete
);
1849 resource
->pending_set_pixels
= false;
1850 UnlockForWrite(resource
);
1852 // Async set pixels commands are not necessarily processed in-sequence with
1853 // drawing commands. Read lock fences are required to ensure that async
1854 // commands don't access the resource while used for drawing.
1855 resource
->read_lock_fences_enabled
= true;
1860 void ResourceProvider::CreateForTesting(ResourceId id
) {
1861 LazyCreate(GetResource(id
));
1864 GLenum
ResourceProvider::TargetForTesting(ResourceId id
) {
1865 Resource
* resource
= GetResource(id
);
1866 return resource
->target
;
1869 void ResourceProvider::LazyCreate(Resource
* resource
) {
1870 if (resource
->type
!= RESOURCE_TYPE_GL_TEXTURE
||
1871 resource
->origin
!= Resource::INTERNAL
)
1874 if (resource
->gl_id
)
1877 DCHECK(resource
->texture_pool
);
1878 DCHECK(resource
->origin
== Resource::INTERNAL
);
1879 DCHECK(!resource
->mailbox
.IsValid());
1880 resource
->gl_id
= texture_id_allocator_
->NextId();
1882 GLES2Interface
* gl
= ContextGL();
1885 // Create and set texture properties. Allocation is delayed until needed.
1886 gl
->BindTexture(resource
->target
, resource
->gl_id
);
1887 gl
->TexParameteri(resource
->target
, GL_TEXTURE_MIN_FILTER
,
1888 resource
->original_filter
);
1889 gl
->TexParameteri(resource
->target
, GL_TEXTURE_MAG_FILTER
,
1890 resource
->original_filter
);
1891 gl
->TexParameteri(resource
->target
, GL_TEXTURE_WRAP_S
, resource
->wrap_mode
);
1892 gl
->TexParameteri(resource
->target
, GL_TEXTURE_WRAP_T
, resource
->wrap_mode
);
1893 gl
->TexParameteri(resource
->target
, GL_TEXTURE_POOL_CHROMIUM
,
1894 resource
->texture_pool
);
1895 if (use_texture_usage_hint_
&& (resource
->hint
& TEXTURE_HINT_FRAMEBUFFER
)) {
1896 gl
->TexParameteri(resource
->target
, GL_TEXTURE_USAGE_ANGLE
,
1897 GL_FRAMEBUFFER_ATTACHMENT_ANGLE
);
1901 void ResourceProvider::AllocateForTesting(ResourceId id
) {
1902 LazyAllocate(GetResource(id
));
1905 void ResourceProvider::LazyAllocate(Resource
* resource
) {
1907 if (resource
->allocated
)
1909 LazyCreate(resource
);
1910 if (!resource
->gl_id
)
1912 resource
->allocated
= true;
1913 GLES2Interface
* gl
= ContextGL();
1914 gfx::Size
& size
= resource
->size
;
1915 DCHECK_EQ(resource
->target
, static_cast<GLenum
>(GL_TEXTURE_2D
));
1916 ResourceFormat format
= resource
->format
;
1917 gl
->BindTexture(GL_TEXTURE_2D
, resource
->gl_id
);
1918 if (use_texture_storage_ext_
&&
1919 IsFormatSupportedForStorage(format
, use_texture_format_bgra_
) &&
1920 (resource
->hint
& TEXTURE_HINT_IMMUTABLE
)) {
1921 GLenum storage_format
= TextureToStorageFormat(format
);
1922 gl
->TexStorage2DEXT(GL_TEXTURE_2D
, 1, storage_format
, size
.width(),
1925 // ETC1 does not support preallocation.
1926 if (format
!= ETC1
) {
1927 gl
->TexImage2D(GL_TEXTURE_2D
, 0, GLInternalFormat(format
), size
.width(),
1928 size
.height(), 0, GLDataFormat(format
), GLDataType(format
),
1934 void ResourceProvider::BindImageForSampling(Resource
* resource
) {
1935 GLES2Interface
* gl
= ContextGL();
1936 DCHECK(resource
->gl_id
);
1937 DCHECK(resource
->image_id
);
1939 // Release image currently bound to texture.
1940 if (resource
->bound_image_id
)
1941 gl
->ReleaseTexImage2DCHROMIUM(resource
->target
, resource
->bound_image_id
);
1942 gl
->BindTexImage2DCHROMIUM(resource
->target
, resource
->image_id
);
1943 resource
->bound_image_id
= resource
->image_id
;
1944 resource
->dirty_image
= false;
1947 void ResourceProvider::CopyResource(ResourceId source_id
, ResourceId dest_id
) {
1948 TRACE_EVENT0("cc", "ResourceProvider::CopyResource");
1950 Resource
* source_resource
= GetResource(source_id
);
1951 DCHECK(!source_resource
->lock_for_read_count
);
1952 DCHECK(source_resource
->origin
== Resource::INTERNAL
);
1953 DCHECK_EQ(source_resource
->exported_count
, 0);
1954 DCHECK_EQ(RESOURCE_TYPE_GL_TEXTURE
, source_resource
->type
);
1955 DCHECK(source_resource
->allocated
);
1956 LazyCreate(source_resource
);
1958 Resource
* dest_resource
= GetResource(dest_id
);
1959 DCHECK(!dest_resource
->locked_for_write
);
1960 DCHECK(!dest_resource
->lock_for_read_count
);
1961 DCHECK(dest_resource
->origin
== Resource::INTERNAL
);
1962 DCHECK_EQ(dest_resource
->exported_count
, 0);
1963 DCHECK_EQ(RESOURCE_TYPE_GL_TEXTURE
, dest_resource
->type
);
1964 LazyAllocate(dest_resource
);
1966 DCHECK_EQ(source_resource
->type
, dest_resource
->type
);
1967 DCHECK_EQ(source_resource
->format
, dest_resource
->format
);
1968 DCHECK(source_resource
->size
== dest_resource
->size
);
1970 GLES2Interface
* gl
= ContextGL();
1972 if (source_resource
->image_id
&& source_resource
->dirty_image
) {
1973 gl
->BindTexture(source_resource
->target
, source_resource
->gl_id
);
1974 BindImageForSampling(source_resource
);
1976 if (use_sync_query_
) {
1977 if (!source_resource
->gl_read_lock_query_id
)
1978 gl
->GenQueriesEXT(1, &source_resource
->gl_read_lock_query_id
);
1979 #if defined(OS_CHROMEOS)
1980 // TODO(reveman): This avoids a performance problem on some ChromeOS
1981 // devices. This needs to be removed to support native GpuMemoryBuffer
1982 // implementations. crbug.com/436314
1983 gl
->BeginQueryEXT(GL_COMMANDS_ISSUED_CHROMIUM
,
1984 source_resource
->gl_read_lock_query_id
);
1986 gl
->BeginQueryEXT(GL_COMMANDS_COMPLETED_CHROMIUM
,
1987 source_resource
->gl_read_lock_query_id
);
1990 DCHECK(!dest_resource
->image_id
);
1991 dest_resource
->allocated
= true;
1992 gl
->CopySubTextureCHROMIUM(dest_resource
->target
, source_resource
->gl_id
,
1993 dest_resource
->gl_id
, 0, 0);
1994 if (source_resource
->gl_read_lock_query_id
) {
1995 // End query and create a read lock fence that will prevent access to
1996 // source resource until CopySubTextureCHROMIUM command has completed.
1997 #if defined(OS_CHROMEOS)
1998 gl
->EndQueryEXT(GL_COMMANDS_ISSUED_CHROMIUM
);
2000 gl
->EndQueryEXT(GL_COMMANDS_COMPLETED_CHROMIUM
);
2002 source_resource
->read_lock_fence
= make_scoped_refptr(
2003 new CopyTextureFence(gl
, source_resource
->gl_read_lock_query_id
));
2005 // Create a SynchronousFence when CHROMIUM_sync_query extension is missing.
2006 // Try to use one synchronous fence for as many CopyResource operations as
2007 // possible as that reduce the number of times we have to synchronize with
2009 if (!synchronous_fence_
.get() || synchronous_fence_
->has_synchronized())
2010 synchronous_fence_
= make_scoped_refptr(new SynchronousFence(gl
));
2011 source_resource
->read_lock_fence
= synchronous_fence_
;
2012 source_resource
->read_lock_fence
->Set();
2016 void ResourceProvider::WaitSyncPointIfNeeded(ResourceId id
) {
2017 Resource
* resource
= GetResource(id
);
2018 DCHECK_EQ(resource
->exported_count
, 0);
2019 DCHECK(resource
->allocated
);
2020 if (resource
->type
!= RESOURCE_TYPE_GL_TEXTURE
|| resource
->gl_id
)
2022 if (!resource
->mailbox
.sync_point())
2024 DCHECK(resource
->mailbox
.IsValid());
2025 GLES2Interface
* gl
= ContextGL();
2027 gl
->WaitSyncPointCHROMIUM(resource
->mailbox
.sync_point());
2028 resource
->mailbox
.set_sync_point(0);
2031 void ResourceProvider::WaitReadLockIfNeeded(ResourceId id
) {
2032 Resource
* resource
= GetResource(id
);
2033 DCHECK_EQ(resource
->exported_count
, 0);
2034 if (!resource
->read_lock_fence
.get())
2037 resource
->read_lock_fence
->Wait();
2040 GLint
ResourceProvider::GetActiveTextureUnit(GLES2Interface
* gl
) {
2041 GLint active_unit
= 0;
2042 gl
->GetIntegerv(GL_ACTIVE_TEXTURE
, &active_unit
);
2046 void ResourceProvider::ValidateResource(ResourceId id
) const {
2047 DCHECK(thread_checker_
.CalledOnValidThread());
2049 DCHECK(resources_
.find(id
) != resources_
.end());
2052 GLES2Interface
* ResourceProvider::ContextGL() const {
2053 ContextProvider
* context_provider
= output_surface_
->context_provider();
2054 return context_provider
? context_provider
->ContextGL() : NULL
;
2057 class GrContext
* ResourceProvider::GrContext(bool worker_context
) const {
2058 ContextProvider
* context_provider
=
2059 worker_context
? output_surface_
->worker_context_provider()
2060 : output_surface_
->context_provider();
2061 return context_provider
? context_provider
->GrContext() : NULL
;