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/debug/trace_event.h"
12 #include "base/stl_util.h"
13 #include "base/strings/string_split.h"
14 #include "base/strings/string_util.h"
15 #include "cc/base/util.h"
16 #include "cc/output/gl_renderer.h" // For the GLC() macro.
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 "third_party/khronos/GLES2/gl2.h"
25 #include "third_party/khronos/GLES2/gl2ext.h"
26 #include "third_party/skia/include/core/SkSurface.h"
27 #include "third_party/skia/include/gpu/GrContext.h"
28 #include "third_party/skia/include/gpu/SkGpuDevice.h"
29 #include "ui/gfx/frame_time.h"
30 #include "ui/gfx/rect.h"
31 #include "ui/gfx/vector2d.h"
33 using gpu::gles2::GLES2Interface;
39 virtual ~IdAllocator() {}
41 virtual GLuint NextId() = 0;
44 IdAllocator(GLES2Interface* gl, size_t id_allocation_chunk_size)
46 id_allocation_chunk_size_(id_allocation_chunk_size),
47 ids_(new GLuint[id_allocation_chunk_size]),
48 next_id_index_(id_allocation_chunk_size) {
49 DCHECK(id_allocation_chunk_size_);
53 const size_t id_allocation_chunk_size_;
54 scoped_ptr<GLuint[]> ids_;
55 size_t next_id_index_;
60 // Measured in seconds.
61 const double kSoftwareUploadTickRate = 0.000250;
62 const double kTextureUploadTickRate = 0.004;
64 GLenum TextureToStorageFormat(ResourceFormat format) {
65 GLenum storage_format = GL_RGBA8_OES;
70 storage_format = GL_BGRA8_EXT;
80 return storage_format;
83 bool IsFormatSupportedForStorage(ResourceFormat format) {
97 GrPixelConfig ToGrPixelConfig(ResourceFormat format) {
100 return kRGBA_8888_GrPixelConfig;
102 return kBGRA_8888_GrPixelConfig;
104 return kRGBA_4444_GrPixelConfig;
108 DCHECK(false) << "Unsupported resource format.";
109 return kSkia8888_GrPixelConfig;
112 class IdentityAllocator : public SkBitmap::Allocator {
114 explicit IdentityAllocator(void* buffer) : buffer_(buffer) {}
115 virtual bool allocPixelRef(SkBitmap* dst, SkColorTable*) OVERRIDE {
116 dst->setPixels(buffer_);
124 void CopyBitmap(const SkBitmap& src, uint8_t* dst, SkColorType dst_colorType) {
126 IdentityAllocator allocator(dst);
127 src.copyTo(&dst_bitmap, dst_colorType, &allocator);
128 // TODO(kaanb): The GL pipeline assumes a 4-byte alignment for the
129 // bitmap data. This check will be removed once crbug.com/293728 is fixed.
130 CHECK_EQ(0u, dst_bitmap.rowBytes() % 4);
133 class ScopedSetActiveTexture {
135 ScopedSetActiveTexture(GLES2Interface* gl, GLenum unit)
136 : gl_(gl), unit_(unit) {
137 DCHECK_EQ(GL_TEXTURE0, ResourceProvider::GetActiveTextureUnit(gl_));
139 if (unit_ != GL_TEXTURE0)
140 GLC(gl_, gl_->ActiveTexture(unit_));
143 ~ScopedSetActiveTexture() {
144 // Active unit being GL_TEXTURE0 is effectively the ground state.
145 if (unit_ != GL_TEXTURE0)
146 GLC(gl_, gl_->ActiveTexture(GL_TEXTURE0));
154 class TextureIdAllocator : public IdAllocator {
156 TextureIdAllocator(GLES2Interface* gl,
157 size_t texture_id_allocation_chunk_size)
158 : IdAllocator(gl, texture_id_allocation_chunk_size) {}
159 virtual ~TextureIdAllocator() {
160 gl_->DeleteTextures(id_allocation_chunk_size_ - next_id_index_,
161 ids_.get() + next_id_index_);
164 // Overridden from IdAllocator:
165 virtual GLuint NextId() OVERRIDE {
166 if (next_id_index_ == id_allocation_chunk_size_) {
167 gl_->GenTextures(id_allocation_chunk_size_, ids_.get());
171 return ids_[next_id_index_++];
175 DISALLOW_COPY_AND_ASSIGN(TextureIdAllocator);
178 class BufferIdAllocator : public IdAllocator {
180 BufferIdAllocator(GLES2Interface* gl, size_t buffer_id_allocation_chunk_size)
181 : IdAllocator(gl, buffer_id_allocation_chunk_size) {}
182 virtual ~BufferIdAllocator() {
183 gl_->DeleteBuffers(id_allocation_chunk_size_ - next_id_index_,
184 ids_.get() + next_id_index_);
187 // Overridden from IdAllocator:
188 virtual GLuint NextId() OVERRIDE {
189 if (next_id_index_ == id_allocation_chunk_size_) {
190 gl_->GenBuffers(id_allocation_chunk_size_, ids_.get());
194 return ids_[next_id_index_++];
198 DISALLOW_COPY_AND_ASSIGN(BufferIdAllocator);
201 // Generic fence implementation for query objects. Fence has passed when query
202 // result is available.
203 class QueryFence : public ResourceProvider::Fence {
205 QueryFence(gpu::gles2::GLES2Interface* gl, unsigned query_id)
206 : gl_(gl), query_id_(query_id) {}
208 // Overridden from ResourceProvider::Fence:
209 virtual bool HasPassed() OVERRIDE {
210 unsigned available = 1;
211 gl_->GetQueryObjectuivEXT(
212 query_id_, GL_QUERY_RESULT_AVAILABLE_EXT, &available);
217 virtual ~QueryFence() {}
219 gpu::gles2::GLES2Interface* gl_;
222 DISALLOW_COPY_AND_ASSIGN(QueryFence);
227 ResourceProvider::Resource::Resource()
230 gl_pixel_buffer_id(0),
231 gl_upload_query_id(0),
232 gl_read_lock_query_id(0),
234 lock_for_read_count(0),
238 locked_for_write(false),
240 marked_for_deletion(false),
241 pending_set_pixels(false),
242 set_pixels_completion_forced(false),
244 enable_read_lock_fences(false),
245 has_shared_bitmap_id(false),
246 allow_overlay(false),
247 read_lock_fence(NULL),
257 hint(TextureUsageAny),
260 shared_bitmap(NULL) {}
262 ResourceProvider::Resource::~Resource() {}
264 ResourceProvider::Resource::Resource(GLuint texture_id,
265 const gfx::Size& size,
271 TextureUsageHint hint,
272 ResourceFormat format)
275 gl_pixel_buffer_id(0),
276 gl_upload_query_id(0),
277 gl_read_lock_query_id(0),
279 lock_for_read_count(0),
283 locked_for_write(false),
285 marked_for_deletion(false),
286 pending_set_pixels(false),
287 set_pixels_completion_forced(false),
289 enable_read_lock_fences(false),
290 has_shared_bitmap_id(false),
291 allow_overlay(false),
292 read_lock_fence(NULL),
296 original_filter(filter),
300 texture_pool(texture_pool),
301 wrap_mode(wrap_mode),
305 shared_bitmap(NULL) {
306 DCHECK(wrap_mode == GL_CLAMP_TO_EDGE || wrap_mode == GL_REPEAT);
307 DCHECK_EQ(origin == Internal, !!texture_pool);
310 ResourceProvider::Resource::Resource(uint8_t* pixels,
311 SharedBitmap* bitmap,
312 const gfx::Size& size,
318 gl_pixel_buffer_id(0),
319 gl_upload_query_id(0),
320 gl_read_lock_query_id(0),
322 lock_for_read_count(0),
326 locked_for_write(false),
328 marked_for_deletion(false),
329 pending_set_pixels(false),
330 set_pixels_completion_forced(false),
332 enable_read_lock_fences(false),
333 has_shared_bitmap_id(!!bitmap),
334 allow_overlay(false),
335 read_lock_fence(NULL),
339 original_filter(filter),
344 wrap_mode(wrap_mode),
345 hint(TextureUsageAny),
348 shared_bitmap(bitmap) {
349 DCHECK(wrap_mode == GL_CLAMP_TO_EDGE || wrap_mode == GL_REPEAT);
350 DCHECK(origin == Delegated || pixels);
352 shared_bitmap_id = bitmap->id();
355 ResourceProvider::Resource::Resource(const SharedBitmapId& bitmap_id,
356 const gfx::Size& size,
362 gl_pixel_buffer_id(0),
363 gl_upload_query_id(0),
364 gl_read_lock_query_id(0),
366 lock_for_read_count(0),
370 locked_for_write(false),
372 marked_for_deletion(false),
373 pending_set_pixels(false),
374 set_pixels_completion_forced(false),
376 enable_read_lock_fences(false),
377 has_shared_bitmap_id(true),
378 allow_overlay(false),
379 read_lock_fence(NULL),
383 original_filter(filter),
388 wrap_mode(wrap_mode),
389 hint(TextureUsageAny),
392 shared_bitmap_id(bitmap_id),
393 shared_bitmap(NULL) {
394 DCHECK(wrap_mode == GL_CLAMP_TO_EDGE || wrap_mode == GL_REPEAT);
397 ResourceProvider::RasterBuffer::RasterBuffer(
398 const Resource* resource,
399 ResourceProvider* resource_provider)
400 : resource_(resource),
401 resource_provider_(resource_provider),
402 locked_canvas_(NULL),
403 canvas_save_count_(0) {
405 DCHECK(resource_provider_);
408 ResourceProvider::RasterBuffer::~RasterBuffer() {}
410 SkCanvas* ResourceProvider::RasterBuffer::LockForWrite() {
411 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug"),
412 "ResourceProvider::RasterBuffer::LockForWrite");
414 DCHECK(!locked_canvas_);
416 locked_canvas_ = DoLockForWrite();
417 canvas_save_count_ = locked_canvas_ ? locked_canvas_->save() : 0;
418 return locked_canvas_;
421 bool ResourceProvider::RasterBuffer::UnlockForWrite() {
422 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug"),
423 "ResourceProvider::RasterBuffer::UnlockForWrite");
425 if (locked_canvas_) {
426 locked_canvas_->restoreToCount(canvas_save_count_);
427 locked_canvas_ = NULL;
429 return DoUnlockForWrite();
432 ResourceProvider::DirectRasterBuffer::DirectRasterBuffer(
433 const Resource* resource,
434 ResourceProvider* resource_provider,
435 bool use_distance_field_text )
436 : RasterBuffer(resource, resource_provider),
437 surface_generation_id_(0u),
438 use_distance_field_text_(use_distance_field_text) {}
440 ResourceProvider::DirectRasterBuffer::~DirectRasterBuffer() {}
442 SkCanvas* ResourceProvider::DirectRasterBuffer::DoLockForWrite() {
444 surface_ = CreateSurface();
445 surface_generation_id_ = surface_ ? surface_->generationID() : 0u;
446 return surface_ ? surface_->getCanvas() : NULL;
449 bool ResourceProvider::DirectRasterBuffer::DoUnlockForWrite() {
450 // generationID returns a non-zero, unique value corresponding to the content
451 // of surface. Hence, a change since DoLockForWrite was called means the
452 // surface has changed.
453 return surface_ ? surface_generation_id_ != surface_->generationID() : false;
456 skia::RefPtr<SkSurface> ResourceProvider::DirectRasterBuffer::CreateSurface() {
457 skia::RefPtr<SkSurface> surface;
458 switch (resource()->type) {
460 DCHECK(resource()->gl_id);
461 class GrContext* gr_context = resource_provider()->GrContext();
463 GrBackendTextureDesc desc;
464 desc.fFlags = kRenderTarget_GrBackendTextureFlag;
465 desc.fWidth = resource()->size.width();
466 desc.fHeight = resource()->size.height();
467 desc.fConfig = ToGrPixelConfig(resource()->format);
468 desc.fOrigin = kTopLeft_GrSurfaceOrigin;
469 desc.fTextureHandle = resource()->gl_id;
470 skia::RefPtr<GrTexture> gr_texture =
471 skia::AdoptRef(gr_context->wrapBackendTexture(desc));
472 SkSurface::TextRenderMode text_render_mode =
473 use_distance_field_text_ ? SkSurface::kDistanceField_TextRenderMode
474 : SkSurface::kStandard_TextRenderMode;
475 surface = skia::AdoptRef(SkSurface::NewRenderTargetDirect(
476 gr_texture->asRenderTarget(), text_render_mode));
481 DCHECK(resource()->pixels);
482 DCHECK_EQ(RGBA_8888, resource()->format);
483 SkImageInfo image_info = SkImageInfo::MakeN32Premul(
484 resource()->size.width(), resource()->size.height());
485 surface = skia::AdoptRef(SkSurface::NewRasterDirect(
486 image_info, resource()->pixels, image_info.minRowBytes()));
495 ResourceProvider::BitmapRasterBuffer::BitmapRasterBuffer(
496 const Resource* resource,
497 ResourceProvider* resource_provider)
498 : RasterBuffer(resource, resource_provider),
499 mapped_buffer_(NULL),
500 raster_bitmap_generation_id_(0u) {}
502 ResourceProvider::BitmapRasterBuffer::~BitmapRasterBuffer() {}
504 SkCanvas* ResourceProvider::BitmapRasterBuffer::DoLockForWrite() {
505 DCHECK(!mapped_buffer_);
506 DCHECK(!raster_canvas_);
509 mapped_buffer_ = MapBuffer(&stride);
513 switch (resource()->format) {
515 // Use the default stride if we will eventually convert this
517 raster_bitmap_.allocN32Pixels(resource()->size.width(),
518 resource()->size.height());
522 SkImageInfo info = SkImageInfo::MakeN32Premul(resource()->size.width(),
523 resource()->size.height());
525 stride = info.minRowBytes();
526 raster_bitmap_.installPixels(info, mapped_buffer_, stride);
535 raster_canvas_ = skia::AdoptRef(new SkCanvas(raster_bitmap_));
536 raster_bitmap_generation_id_ = raster_bitmap_.getGenerationID();
537 return raster_canvas_.get();
540 bool ResourceProvider::BitmapRasterBuffer::DoUnlockForWrite() {
541 raster_canvas_.clear();
543 // getGenerationID returns a non-zero, unique value corresponding to the
544 // pixels in bitmap. Hence, a change since DoLockForWrite was called means the
545 // bitmap has changed.
546 bool raster_bitmap_changed =
547 raster_bitmap_generation_id_ != raster_bitmap_.getGenerationID();
549 if (raster_bitmap_changed) {
550 SkColorType buffer_colorType =
551 ResourceFormatToSkColorType(resource()->format);
552 if (mapped_buffer_ && (buffer_colorType != raster_bitmap_.colorType()))
553 CopyBitmap(raster_bitmap_, mapped_buffer_, buffer_colorType);
555 raster_bitmap_.reset();
558 mapped_buffer_ = NULL;
559 return raster_bitmap_changed;
562 ResourceProvider::ImageRasterBuffer::ImageRasterBuffer(
563 const Resource* resource,
564 ResourceProvider* resource_provider)
565 : BitmapRasterBuffer(resource, resource_provider) {}
567 ResourceProvider::ImageRasterBuffer::~ImageRasterBuffer() {}
569 uint8_t* ResourceProvider::ImageRasterBuffer::MapBuffer(int* stride) {
570 return resource_provider()->MapImage(resource(), stride);
573 void ResourceProvider::ImageRasterBuffer::UnmapBuffer() {
574 resource_provider()->UnmapImage(resource());
577 ResourceProvider::PixelRasterBuffer::PixelRasterBuffer(
578 const Resource* resource,
579 ResourceProvider* resource_provider)
580 : BitmapRasterBuffer(resource, resource_provider) {}
582 ResourceProvider::PixelRasterBuffer::~PixelRasterBuffer() {}
584 uint8_t* ResourceProvider::PixelRasterBuffer::MapBuffer(int* stride) {
585 return resource_provider()->MapPixelBuffer(resource(), stride);
588 void ResourceProvider::PixelRasterBuffer::UnmapBuffer() {
589 resource_provider()->UnmapPixelBuffer(resource());
592 ResourceProvider::Child::Child() : marked_for_deletion(false) {}
594 ResourceProvider::Child::~Child() {}
596 scoped_ptr<ResourceProvider> ResourceProvider::Create(
597 OutputSurface* output_surface,
598 SharedBitmapManager* shared_bitmap_manager,
599 int highp_threshold_min,
600 bool use_rgba_4444_texture_format,
601 size_t id_allocation_chunk_size,
602 bool use_distance_field_text) {
603 scoped_ptr<ResourceProvider> resource_provider(
604 new ResourceProvider(output_surface,
605 shared_bitmap_manager,
607 use_rgba_4444_texture_format,
608 id_allocation_chunk_size,
609 use_distance_field_text));
611 if (resource_provider->ContextGL())
612 resource_provider->InitializeGL();
614 resource_provider->InitializeSoftware();
616 DCHECK_NE(InvalidType, resource_provider->default_resource_type());
617 return resource_provider.Pass();
620 ResourceProvider::~ResourceProvider() {
621 while (!children_.empty())
622 DestroyChildInternal(children_.begin(), ForShutdown);
623 while (!resources_.empty())
624 DeleteResourceInternal(resources_.begin(), ForShutdown);
629 bool ResourceProvider::InUseByConsumer(ResourceId id) {
630 Resource* resource = GetResource(id);
631 return resource->lock_for_read_count > 0 || resource->exported_count > 0 ||
635 bool ResourceProvider::IsLost(ResourceId id) {
636 Resource* resource = GetResource(id);
637 return resource->lost;
640 bool ResourceProvider::AllowOverlay(ResourceId id) {
641 Resource* resource = GetResource(id);
642 return resource->allow_overlay;
645 ResourceProvider::ResourceId ResourceProvider::CreateResource(
646 const gfx::Size& size,
648 TextureUsageHint hint,
649 ResourceFormat format) {
650 DCHECK(!size.IsEmpty());
651 switch (default_resource_type_) {
653 return CreateGLTexture(size,
655 GL_TEXTURE_POOL_UNMANAGED_CHROMIUM,
660 DCHECK_EQ(RGBA_8888, format);
661 return CreateBitmap(size, wrap_mode);
666 LOG(FATAL) << "Invalid default resource type.";
670 ResourceProvider::ResourceId ResourceProvider::CreateManagedResource(
671 const gfx::Size& size,
674 TextureUsageHint hint,
675 ResourceFormat format) {
676 DCHECK(!size.IsEmpty());
677 switch (default_resource_type_) {
679 return CreateGLTexture(size,
681 GL_TEXTURE_POOL_MANAGED_CHROMIUM,
686 DCHECK_EQ(RGBA_8888, format);
687 return CreateBitmap(size, wrap_mode);
692 LOG(FATAL) << "Invalid default resource type.";
696 ResourceProvider::ResourceId ResourceProvider::CreateGLTexture(
697 const gfx::Size& size,
701 TextureUsageHint hint,
702 ResourceFormat format) {
703 DCHECK_LE(size.width(), max_texture_size_);
704 DCHECK_LE(size.height(), max_texture_size_);
705 DCHECK(thread_checker_.CalledOnValidThread());
707 ResourceId id = next_id_++;
717 resource.allocated = false;
718 resources_[id] = resource;
722 ResourceProvider::ResourceId ResourceProvider::CreateBitmap(
723 const gfx::Size& size, GLint wrap_mode) {
724 DCHECK(thread_checker_.CalledOnValidThread());
726 scoped_ptr<SharedBitmap> bitmap;
727 if (shared_bitmap_manager_)
728 bitmap = shared_bitmap_manager_->AllocateSharedBitmap(size);
732 pixels = bitmap->pixels();
734 size_t bytes = SharedBitmap::CheckedSizeInBytes(size);
735 pixels = new uint8_t[bytes];
739 ResourceId id = next_id_++;
741 pixels, bitmap.release(), size, Resource::Internal, GL_LINEAR, wrap_mode);
742 resource.allocated = true;
743 resources_[id] = resource;
747 ResourceProvider::ResourceId ResourceProvider::CreateResourceFromIOSurface(
748 const gfx::Size& size,
749 unsigned io_surface_id) {
750 DCHECK(thread_checker_.CalledOnValidThread());
752 ResourceId id = next_id_++;
756 GL_TEXTURE_RECTANGLE_ARB,
758 GL_TEXTURE_POOL_UNMANAGED_CHROMIUM,
762 LazyCreate(&resource);
763 GLES2Interface* gl = ContextGL();
765 gl->BindTexture(GL_TEXTURE_RECTANGLE_ARB, resource.gl_id);
766 gl->TexImageIOSurface2DCHROMIUM(
767 GL_TEXTURE_RECTANGLE_ARB, size.width(), size.height(), io_surface_id, 0);
768 resource.allocated = true;
769 resources_[id] = resource;
773 ResourceProvider::ResourceId ResourceProvider::CreateResourceFromTextureMailbox(
774 const TextureMailbox& mailbox,
775 scoped_ptr<SingleReleaseCallback> release_callback) {
776 DCHECK(thread_checker_.CalledOnValidThread());
777 // Just store the information. Mailbox will be consumed in LockForRead().
778 ResourceId id = next_id_++;
779 DCHECK(mailbox.IsValid());
780 Resource& resource = resources_[id];
781 if (mailbox.IsTexture()) {
782 resource = Resource(0,
792 DCHECK(mailbox.IsSharedMemory());
793 base::SharedMemory* shared_memory = mailbox.shared_memory();
794 DCHECK(shared_memory->memory());
795 uint8_t* pixels = reinterpret_cast<uint8_t*>(shared_memory->memory());
797 scoped_ptr<SharedBitmap> shared_bitmap;
798 if (shared_bitmap_manager_) {
800 shared_bitmap_manager_->GetBitmapForSharedMemory(shared_memory);
802 resource = Resource(pixels,
803 shared_bitmap.release(),
804 mailbox.shared_memory_size(),
809 resource.allocated = true;
810 resource.mailbox = mailbox;
811 resource.release_callback =
812 base::Bind(&SingleReleaseCallback::Run,
813 base::Owned(release_callback.release()));
814 resource.allow_overlay = mailbox.allow_overlay();
818 void ResourceProvider::DeleteResource(ResourceId id) {
819 DCHECK(thread_checker_.CalledOnValidThread());
820 ResourceMap::iterator it = resources_.find(id);
821 CHECK(it != resources_.end());
822 Resource* resource = &it->second;
823 DCHECK(!resource->marked_for_deletion);
824 DCHECK_EQ(resource->imported_count, 0);
825 DCHECK(resource->pending_set_pixels || !resource->locked_for_write);
827 if (resource->exported_count > 0 || resource->lock_for_read_count > 0) {
828 resource->marked_for_deletion = true;
831 DeleteResourceInternal(it, Normal);
835 void ResourceProvider::DeleteResourceInternal(ResourceMap::iterator it,
837 TRACE_EVENT0("cc", "ResourceProvider::DeleteResourceInternal");
838 Resource* resource = &it->second;
839 bool lost_resource = resource->lost;
841 DCHECK(resource->exported_count == 0 || style != Normal);
842 if (style == ForShutdown && resource->exported_count > 0)
843 lost_resource = true;
845 resource->direct_raster_buffer.reset();
846 resource->image_raster_buffer.reset();
847 resource->pixel_raster_buffer.reset();
849 if (resource->image_id) {
850 DCHECK(resource->origin == Resource::Internal);
851 GLES2Interface* gl = ContextGL();
853 GLC(gl, gl->DestroyImageCHROMIUM(resource->image_id));
855 if (resource->gl_upload_query_id) {
856 DCHECK(resource->origin == Resource::Internal);
857 GLES2Interface* gl = ContextGL();
859 GLC(gl, gl->DeleteQueriesEXT(1, &resource->gl_upload_query_id));
861 if (resource->gl_read_lock_query_id) {
862 DCHECK(resource->origin == Resource::Internal);
863 GLES2Interface* gl = ContextGL();
865 GLC(gl, gl->DeleteQueriesEXT(1, &resource->gl_read_lock_query_id));
867 if (resource->gl_pixel_buffer_id) {
868 DCHECK(resource->origin == Resource::Internal);
869 GLES2Interface* gl = ContextGL();
871 GLC(gl, gl->DeleteBuffers(1, &resource->gl_pixel_buffer_id));
873 if (resource->origin == Resource::External) {
874 DCHECK(resource->mailbox.IsValid());
875 GLuint sync_point = resource->mailbox.sync_point();
876 if (resource->type == GLTexture) {
877 DCHECK(resource->mailbox.IsTexture());
878 lost_resource |= lost_output_surface_;
879 GLES2Interface* gl = ContextGL();
881 if (resource->gl_id) {
882 GLC(gl, gl->DeleteTextures(1, &resource->gl_id));
885 sync_point = gl->InsertSyncPointCHROMIUM();
888 DCHECK(resource->mailbox.IsSharedMemory());
889 base::SharedMemory* shared_memory = resource->mailbox.shared_memory();
890 if (resource->pixels && shared_memory) {
891 DCHECK(shared_memory->memory() == resource->pixels);
892 resource->pixels = NULL;
893 delete resource->shared_bitmap;
894 resource->shared_bitmap = NULL;
897 resource->release_callback.Run(sync_point, lost_resource);
899 if (resource->gl_id) {
900 GLES2Interface* gl = ContextGL();
902 GLC(gl, gl->DeleteTextures(1, &resource->gl_id));
905 if (resource->shared_bitmap) {
906 DCHECK(resource->origin != Resource::External);
907 DCHECK_EQ(Bitmap, resource->type);
908 delete resource->shared_bitmap;
909 resource->pixels = NULL;
911 if (resource->pixels) {
912 DCHECK(resource->origin == Resource::Internal);
913 delete[] resource->pixels;
915 resources_.erase(it);
918 ResourceProvider::ResourceType ResourceProvider::GetResourceType(
920 return GetResource(id)->type;
923 void ResourceProvider::SetPixels(ResourceId id,
924 const uint8_t* image,
925 const gfx::Rect& image_rect,
926 const gfx::Rect& source_rect,
927 const gfx::Vector2d& dest_offset) {
928 Resource* resource = GetResource(id);
929 DCHECK(!resource->locked_for_write);
930 DCHECK(!resource->lock_for_read_count);
931 DCHECK(resource->origin == Resource::Internal);
932 DCHECK_EQ(resource->exported_count, 0);
933 DCHECK(ReadLockFenceHasPassed(resource));
934 LazyAllocate(resource);
936 if (resource->type == GLTexture) {
937 DCHECK(resource->gl_id);
938 DCHECK(!resource->pending_set_pixels);
939 DCHECK_EQ(resource->target, static_cast<GLenum>(GL_TEXTURE_2D));
940 GLES2Interface* gl = ContextGL();
942 DCHECK(texture_uploader_.get());
943 gl->BindTexture(GL_TEXTURE_2D, resource->gl_id);
944 texture_uploader_->Upload(image,
951 DCHECK_EQ(Bitmap, resource->type);
952 DCHECK(resource->allocated);
953 DCHECK_EQ(RGBA_8888, resource->format);
954 DCHECK(source_rect.x() >= image_rect.x());
955 DCHECK(source_rect.y() >= image_rect.y());
956 DCHECK(source_rect.right() <= image_rect.right());
957 DCHECK(source_rect.bottom() <= image_rect.bottom());
958 SkImageInfo source_info =
959 SkImageInfo::MakeN32Premul(source_rect.width(), source_rect.height());
960 size_t image_row_bytes = image_rect.width() * 4;
961 gfx::Vector2d source_offset = source_rect.origin() - image_rect.origin();
962 image += source_offset.y() * image_row_bytes + source_offset.x() * 4;
964 ScopedWriteLockSoftware lock(this, id);
965 SkCanvas* dest = lock.sk_canvas();
967 source_info, image, image_row_bytes, dest_offset.x(), dest_offset.y());
971 size_t ResourceProvider::NumBlockingUploads() {
972 if (!texture_uploader_)
975 return texture_uploader_->NumBlockingUploads();
978 void ResourceProvider::MarkPendingUploadsAsNonBlocking() {
979 if (!texture_uploader_)
982 texture_uploader_->MarkPendingUploadsAsNonBlocking();
985 size_t ResourceProvider::EstimatedUploadsPerTick() {
986 if (!texture_uploader_)
989 double textures_per_second = texture_uploader_->EstimatedTexturesPerSecond();
990 size_t textures_per_tick = floor(
991 kTextureUploadTickRate * textures_per_second);
992 return textures_per_tick ? textures_per_tick : 1u;
995 void ResourceProvider::FlushUploads() {
996 if (!texture_uploader_)
999 texture_uploader_->Flush();
1002 void ResourceProvider::ReleaseCachedData() {
1003 if (!texture_uploader_)
1006 texture_uploader_->ReleaseCachedQueries();
1009 base::TimeTicks ResourceProvider::EstimatedUploadCompletionTime(
1010 size_t uploads_per_tick) {
1011 if (lost_output_surface_)
1012 return base::TimeTicks();
1014 // Software resource uploads happen on impl thread, so don't bother batching
1015 // them up and trying to wait for them to complete.
1016 if (!texture_uploader_) {
1017 return gfx::FrameTime::Now() + base::TimeDelta::FromMicroseconds(
1018 base::Time::kMicrosecondsPerSecond * kSoftwareUploadTickRate);
1021 base::TimeDelta upload_one_texture_time =
1022 base::TimeDelta::FromMicroseconds(
1023 base::Time::kMicrosecondsPerSecond * kTextureUploadTickRate) /
1026 size_t total_uploads = NumBlockingUploads() + uploads_per_tick;
1027 return gfx::FrameTime::Now() + upload_one_texture_time * total_uploads;
1030 void ResourceProvider::Flush() {
1031 DCHECK(thread_checker_.CalledOnValidThread());
1032 GLES2Interface* gl = ContextGL();
1037 void ResourceProvider::Finish() {
1038 DCHECK(thread_checker_.CalledOnValidThread());
1039 GLES2Interface* gl = ContextGL();
1044 bool ResourceProvider::ShallowFlushIfSupported() {
1045 DCHECK(thread_checker_.CalledOnValidThread());
1046 GLES2Interface* gl = ContextGL();
1050 gl->ShallowFlushCHROMIUM();
1054 ResourceProvider::Resource* ResourceProvider::GetResource(ResourceId id) {
1055 DCHECK(thread_checker_.CalledOnValidThread());
1056 ResourceMap::iterator it = resources_.find(id);
1057 CHECK(it != resources_.end());
1061 const ResourceProvider::Resource* ResourceProvider::LockForRead(ResourceId id) {
1062 Resource* resource = GetResource(id);
1063 DCHECK(!resource->locked_for_write ||
1064 resource->set_pixels_completion_forced) <<
1065 "locked for write: " << resource->locked_for_write <<
1066 " pixels completion forced: " << resource->set_pixels_completion_forced;
1067 DCHECK_EQ(resource->exported_count, 0);
1068 // Uninitialized! Call SetPixels or LockForWrite first.
1069 DCHECK(resource->allocated);
1071 LazyCreate(resource);
1073 if (resource->type == GLTexture && !resource->gl_id) {
1074 DCHECK(resource->origin != Resource::Internal);
1075 DCHECK(resource->mailbox.IsTexture());
1076 GLES2Interface* gl = ContextGL();
1078 if (resource->mailbox.sync_point()) {
1079 GLC(gl, gl->WaitSyncPointCHROMIUM(resource->mailbox.sync_point()));
1080 resource->mailbox.set_sync_point(0);
1082 resource->gl_id = texture_id_allocator_->NextId();
1083 GLC(gl, gl->BindTexture(resource->target, resource->gl_id));
1085 gl->ConsumeTextureCHROMIUM(resource->mailbox.target(),
1086 resource->mailbox.name()));
1089 if (!resource->pixels && resource->has_shared_bitmap_id &&
1090 shared_bitmap_manager_) {
1091 scoped_ptr<SharedBitmap> bitmap =
1092 shared_bitmap_manager_->GetSharedBitmapFromId(
1093 resource->size, resource->shared_bitmap_id);
1095 resource->shared_bitmap = bitmap.release();
1096 resource->pixels = resource->shared_bitmap->pixels();
1100 resource->lock_for_read_count++;
1101 if (resource->enable_read_lock_fences)
1102 resource->read_lock_fence = current_read_lock_fence_;
1107 void ResourceProvider::UnlockForRead(ResourceId id) {
1108 DCHECK(thread_checker_.CalledOnValidThread());
1109 ResourceMap::iterator it = resources_.find(id);
1110 CHECK(it != resources_.end());
1112 Resource* resource = &it->second;
1113 DCHECK_GT(resource->lock_for_read_count, 0);
1114 DCHECK_EQ(resource->exported_count, 0);
1115 resource->lock_for_read_count--;
1116 if (resource->marked_for_deletion && !resource->lock_for_read_count) {
1117 if (!resource->child_id) {
1118 // The resource belongs to this ResourceProvider, so it can be destroyed.
1119 DeleteResourceInternal(it, Normal);
1121 ChildMap::iterator child_it = children_.find(resource->child_id);
1122 ResourceIdArray unused;
1123 unused.push_back(id);
1124 DeleteAndReturnUnusedResourcesToChild(child_it, Normal, unused);
1129 const ResourceProvider::Resource* ResourceProvider::LockForWrite(
1131 Resource* resource = GetResource(id);
1132 DCHECK(!resource->locked_for_write);
1133 DCHECK(!resource->lock_for_read_count);
1134 DCHECK_EQ(resource->exported_count, 0);
1135 DCHECK(resource->origin == Resource::Internal);
1136 DCHECK(!resource->lost);
1137 DCHECK(ReadLockFenceHasPassed(resource));
1138 LazyAllocate(resource);
1140 resource->locked_for_write = true;
1144 bool ResourceProvider::CanLockForWrite(ResourceId id) {
1145 Resource* resource = GetResource(id);
1146 return !resource->locked_for_write && !resource->lock_for_read_count &&
1147 !resource->exported_count && resource->origin == Resource::Internal &&
1148 !resource->lost && ReadLockFenceHasPassed(resource);
1151 void ResourceProvider::UnlockForWrite(ResourceId id) {
1152 Resource* resource = GetResource(id);
1153 DCHECK(resource->locked_for_write);
1154 DCHECK_EQ(resource->exported_count, 0);
1155 DCHECK(resource->origin == Resource::Internal);
1156 resource->locked_for_write = false;
1159 ResourceProvider::ScopedReadLockGL::ScopedReadLockGL(
1160 ResourceProvider* resource_provider,
1161 ResourceProvider::ResourceId resource_id)
1162 : resource_provider_(resource_provider),
1163 resource_id_(resource_id),
1164 texture_id_(resource_provider->LockForRead(resource_id)->gl_id) {
1165 DCHECK(texture_id_);
1168 ResourceProvider::ScopedReadLockGL::~ScopedReadLockGL() {
1169 resource_provider_->UnlockForRead(resource_id_);
1172 ResourceProvider::ScopedSamplerGL::ScopedSamplerGL(
1173 ResourceProvider* resource_provider,
1174 ResourceProvider::ResourceId resource_id,
1176 : ScopedReadLockGL(resource_provider, resource_id),
1178 target_(resource_provider->BindForSampling(resource_id, unit_, filter)) {
1181 ResourceProvider::ScopedSamplerGL::ScopedSamplerGL(
1182 ResourceProvider* resource_provider,
1183 ResourceProvider::ResourceId resource_id,
1186 : ScopedReadLockGL(resource_provider, resource_id),
1188 target_(resource_provider->BindForSampling(resource_id, unit_, filter)) {
1191 ResourceProvider::ScopedSamplerGL::~ScopedSamplerGL() {
1194 ResourceProvider::ScopedWriteLockGL::ScopedWriteLockGL(
1195 ResourceProvider* resource_provider,
1196 ResourceProvider::ResourceId resource_id)
1197 : resource_provider_(resource_provider),
1198 resource_id_(resource_id),
1199 texture_id_(resource_provider->LockForWrite(resource_id)->gl_id) {
1200 DCHECK(texture_id_);
1203 ResourceProvider::ScopedWriteLockGL::~ScopedWriteLockGL() {
1204 resource_provider_->UnlockForWrite(resource_id_);
1207 void ResourceProvider::PopulateSkBitmapWithResource(
1208 SkBitmap* sk_bitmap, const Resource* resource) {
1209 DCHECK_EQ(RGBA_8888, resource->format);
1210 SkImageInfo info = SkImageInfo::MakeN32Premul(resource->size.width(),
1211 resource->size.height());
1212 sk_bitmap->installPixels(info, resource->pixels, info.minRowBytes());
1215 ResourceProvider::ScopedReadLockSoftware::ScopedReadLockSoftware(
1216 ResourceProvider* resource_provider,
1217 ResourceProvider::ResourceId resource_id)
1218 : resource_provider_(resource_provider),
1219 resource_id_(resource_id) {
1220 const Resource* resource = resource_provider->LockForRead(resource_id);
1221 wrap_mode_ = resource->wrap_mode;
1222 ResourceProvider::PopulateSkBitmapWithResource(&sk_bitmap_, resource);
1225 ResourceProvider::ScopedReadLockSoftware::~ScopedReadLockSoftware() {
1226 resource_provider_->UnlockForRead(resource_id_);
1229 ResourceProvider::ScopedWriteLockSoftware::ScopedWriteLockSoftware(
1230 ResourceProvider* resource_provider,
1231 ResourceProvider::ResourceId resource_id)
1232 : resource_provider_(resource_provider),
1233 resource_id_(resource_id) {
1234 ResourceProvider::PopulateSkBitmapWithResource(
1235 &sk_bitmap_, resource_provider->LockForWrite(resource_id));
1237 sk_canvas_.reset(new SkCanvas(sk_bitmap_));
1240 ResourceProvider::ScopedWriteLockSoftware::~ScopedWriteLockSoftware() {
1241 resource_provider_->UnlockForWrite(resource_id_);
1244 ResourceProvider::ResourceProvider(OutputSurface* output_surface,
1245 SharedBitmapManager* shared_bitmap_manager,
1246 int highp_threshold_min,
1247 bool use_rgba_4444_texture_format,
1248 size_t id_allocation_chunk_size,
1249 bool use_distance_field_text)
1250 : output_surface_(output_surface),
1251 shared_bitmap_manager_(shared_bitmap_manager),
1252 lost_output_surface_(false),
1253 highp_threshold_min_(highp_threshold_min),
1256 default_resource_type_(InvalidType),
1257 use_texture_storage_ext_(false),
1258 use_texture_usage_hint_(false),
1259 use_compressed_texture_etc1_(false),
1260 max_texture_size_(0),
1261 best_texture_format_(RGBA_8888),
1262 use_rgba_4444_texture_format_(use_rgba_4444_texture_format),
1263 id_allocation_chunk_size_(id_allocation_chunk_size),
1264 use_sync_query_(false),
1265 use_distance_field_text_(use_distance_field_text) {
1266 DCHECK(output_surface_->HasClient());
1267 DCHECK(id_allocation_chunk_size_);
1270 void ResourceProvider::InitializeSoftware() {
1271 DCHECK(thread_checker_.CalledOnValidThread());
1272 DCHECK_NE(Bitmap, default_resource_type_);
1274 CleanUpGLIfNeeded();
1276 default_resource_type_ = Bitmap;
1277 // Pick an arbitrary limit here similar to what hardware might.
1278 max_texture_size_ = 16 * 1024;
1279 best_texture_format_ = RGBA_8888;
1282 void ResourceProvider::InitializeGL() {
1283 DCHECK(thread_checker_.CalledOnValidThread());
1284 DCHECK(!texture_uploader_);
1285 DCHECK_NE(GLTexture, default_resource_type_);
1286 DCHECK(!texture_id_allocator_);
1287 DCHECK(!buffer_id_allocator_);
1289 default_resource_type_ = GLTexture;
1291 const ContextProvider::Capabilities& caps =
1292 output_surface_->context_provider()->ContextCapabilities();
1294 bool use_bgra = caps.gpu.texture_format_bgra8888;
1295 use_texture_storage_ext_ = caps.gpu.texture_storage;
1296 use_texture_usage_hint_ = caps.gpu.texture_usage;
1297 use_compressed_texture_etc1_ = caps.gpu.texture_format_etc1;
1298 use_sync_query_ = caps.gpu.sync_query;
1300 GLES2Interface* gl = ContextGL();
1303 texture_uploader_ = TextureUploader::Create(gl);
1304 max_texture_size_ = 0; // Context expects cleared value.
1305 GLC(gl, gl->GetIntegerv(GL_MAX_TEXTURE_SIZE, &max_texture_size_));
1306 best_texture_format_ = PlatformColor::BestTextureFormat(use_bgra);
1308 texture_id_allocator_.reset(
1309 new TextureIdAllocator(gl, id_allocation_chunk_size_));
1310 buffer_id_allocator_.reset(
1311 new BufferIdAllocator(gl, id_allocation_chunk_size_));
1314 void ResourceProvider::CleanUpGLIfNeeded() {
1315 GLES2Interface* gl = ContextGL();
1316 if (default_resource_type_ != GLTexture) {
1317 // We are not in GL mode, but double check before returning.
1319 DCHECK(!texture_uploader_);
1324 texture_uploader_.reset();
1325 texture_id_allocator_.reset();
1326 buffer_id_allocator_.reset();
1330 int ResourceProvider::CreateChild(const ReturnCallback& return_callback) {
1331 DCHECK(thread_checker_.CalledOnValidThread());
1334 child_info.return_callback = return_callback;
1336 int child = next_child_++;
1337 children_[child] = child_info;
1341 void ResourceProvider::DestroyChild(int child_id) {
1342 ChildMap::iterator it = children_.find(child_id);
1343 DCHECK(it != children_.end());
1344 DestroyChildInternal(it, Normal);
1347 void ResourceProvider::DestroyChildInternal(ChildMap::iterator it,
1348 DeleteStyle style) {
1349 DCHECK(thread_checker_.CalledOnValidThread());
1351 Child& child = it->second;
1352 DCHECK(style == ForShutdown || !child.marked_for_deletion);
1354 ResourceIdArray resources_for_child;
1356 for (ResourceIdMap::iterator child_it = child.child_to_parent_map.begin();
1357 child_it != child.child_to_parent_map.end();
1359 ResourceId id = child_it->second;
1360 resources_for_child.push_back(id);
1363 // If the child is going away, don't consider any resources in use.
1364 child.in_use_resources.clear();
1365 child.marked_for_deletion = true;
1367 DeleteAndReturnUnusedResourcesToChild(it, style, resources_for_child);
1370 const ResourceProvider::ResourceIdMap& ResourceProvider::GetChildToParentMap(
1372 DCHECK(thread_checker_.CalledOnValidThread());
1373 ChildMap::const_iterator it = children_.find(child);
1374 DCHECK(it != children_.end());
1375 DCHECK(!it->second.marked_for_deletion);
1376 return it->second.child_to_parent_map;
1379 void ResourceProvider::PrepareSendToParent(const ResourceIdArray& resources,
1380 TransferableResourceArray* list) {
1381 DCHECK(thread_checker_.CalledOnValidThread());
1382 GLES2Interface* gl = ContextGL();
1383 bool need_sync_point = false;
1384 for (ResourceIdArray::const_iterator it = resources.begin();
1385 it != resources.end();
1387 TransferableResource resource;
1388 TransferResource(gl, *it, &resource);
1389 if (!resource.mailbox_holder.sync_point && !resource.is_software)
1390 need_sync_point = true;
1391 ++resources_.find(*it)->second.exported_count;
1392 list->push_back(resource);
1394 if (need_sync_point) {
1395 GLuint sync_point = gl->InsertSyncPointCHROMIUM();
1396 for (TransferableResourceArray::iterator it = list->begin();
1399 if (!it->mailbox_holder.sync_point)
1400 it->mailbox_holder.sync_point = sync_point;
1405 void ResourceProvider::ReceiveFromChild(
1406 int child, const TransferableResourceArray& resources) {
1407 DCHECK(thread_checker_.CalledOnValidThread());
1408 GLES2Interface* gl = ContextGL();
1409 Child& child_info = children_.find(child)->second;
1410 DCHECK(!child_info.marked_for_deletion);
1411 for (TransferableResourceArray::const_iterator it = resources.begin();
1412 it != resources.end();
1414 ResourceIdMap::iterator resource_in_map_it =
1415 child_info.child_to_parent_map.find(it->id);
1416 if (resource_in_map_it != child_info.child_to_parent_map.end()) {
1417 Resource& resource = resources_[resource_in_map_it->second];
1418 resource.marked_for_deletion = false;
1419 resource.imported_count++;
1423 if ((!it->is_software && !gl) ||
1424 (it->is_software && !shared_bitmap_manager_)) {
1425 TRACE_EVENT0("cc", "ResourceProvider::ReceiveFromChild dropping invalid");
1426 ReturnedResourceArray to_return;
1427 to_return.push_back(it->ToReturnedResource());
1428 child_info.return_callback.Run(to_return);
1432 ResourceId local_id = next_id_++;
1433 Resource& resource = resources_[local_id];
1434 if (it->is_software) {
1435 resource = Resource(it->mailbox_holder.mailbox,
1437 Resource::Delegated,
1441 resource = Resource(0,
1443 Resource::Delegated,
1444 it->mailbox_holder.texture_target,
1450 resource.mailbox = TextureMailbox(it->mailbox_holder.mailbox,
1451 it->mailbox_holder.texture_target,
1452 it->mailbox_holder.sync_point);
1454 resource.child_id = child;
1455 // Don't allocate a texture for a child.
1456 resource.allocated = true;
1457 resource.imported_count = 1;
1458 child_info.parent_to_child_map[local_id] = it->id;
1459 child_info.child_to_parent_map[it->id] = local_id;
1463 void ResourceProvider::DeclareUsedResourcesFromChild(
1465 const ResourceIdArray& resources_from_child) {
1466 DCHECK(thread_checker_.CalledOnValidThread());
1468 ChildMap::iterator child_it = children_.find(child);
1469 DCHECK(child_it != children_.end());
1470 Child& child_info = child_it->second;
1471 DCHECK(!child_info.marked_for_deletion);
1472 child_info.in_use_resources.clear();
1474 for (size_t i = 0; i < resources_from_child.size(); ++i) {
1475 ResourceIdMap::iterator it =
1476 child_info.child_to_parent_map.find(resources_from_child[i]);
1477 DCHECK(it != child_info.child_to_parent_map.end());
1479 ResourceId local_id = it->second;
1480 DCHECK(!resources_[local_id].marked_for_deletion);
1481 child_info.in_use_resources.insert(local_id);
1484 ResourceIdArray unused;
1485 for (ResourceIdMap::iterator it = child_info.child_to_parent_map.begin();
1486 it != child_info.child_to_parent_map.end();
1488 ResourceId local_id = it->second;
1489 bool resource_is_in_use = child_info.in_use_resources.count(local_id) > 0;
1490 if (!resource_is_in_use)
1491 unused.push_back(local_id);
1493 DeleteAndReturnUnusedResourcesToChild(child_it, Normal, unused);
1497 bool ResourceProvider::CompareResourceMapIteratorsByChildId(
1498 const std::pair<ReturnedResource, ResourceMap::iterator>& a,
1499 const std::pair<ReturnedResource, ResourceMap::iterator>& b) {
1500 const ResourceMap::iterator& a_it = a.second;
1501 const ResourceMap::iterator& b_it = b.second;
1502 const Resource& a_resource = a_it->second;
1503 const Resource& b_resource = b_it->second;
1504 return a_resource.child_id < b_resource.child_id;
1507 void ResourceProvider::ReceiveReturnsFromParent(
1508 const ReturnedResourceArray& resources) {
1509 DCHECK(thread_checker_.CalledOnValidThread());
1510 GLES2Interface* gl = ContextGL();
1513 ResourceIdArray resources_for_child;
1515 std::vector<std::pair<ReturnedResource, ResourceMap::iterator> >
1518 for (ReturnedResourceArray::const_iterator it = resources.begin();
1519 it != resources.end();
1521 ResourceId local_id = it->id;
1522 ResourceMap::iterator map_iterator = resources_.find(local_id);
1524 // Resource was already lost (e.g. it belonged to a child that was
1526 if (map_iterator == resources_.end())
1529 sorted_resources.push_back(
1530 std::pair<ReturnedResource, ResourceMap::iterator>(*it, map_iterator));
1533 std::sort(sorted_resources.begin(),
1534 sorted_resources.end(),
1535 CompareResourceMapIteratorsByChildId);
1537 ChildMap::iterator child_it = children_.end();
1538 for (size_t i = 0; i < sorted_resources.size(); ++i) {
1539 ReturnedResource& returned = sorted_resources[i].first;
1540 ResourceMap::iterator& map_iterator = sorted_resources[i].second;
1541 ResourceId local_id = map_iterator->first;
1542 Resource* resource = &map_iterator->second;
1544 CHECK_GE(resource->exported_count, returned.count);
1545 resource->exported_count -= returned.count;
1546 resource->lost |= returned.lost;
1547 if (resource->exported_count)
1550 // Need to wait for the current read lock fence to pass before we can
1551 // recycle this resource.
1552 if (resource->enable_read_lock_fences)
1553 resource->read_lock_fence = current_read_lock_fence_;
1555 if (returned.sync_point) {
1556 DCHECK(!resource->has_shared_bitmap_id);
1557 if (resource->origin == Resource::Internal) {
1558 DCHECK(resource->gl_id);
1559 GLC(gl, gl->WaitSyncPointCHROMIUM(returned.sync_point));
1561 DCHECK(!resource->gl_id);
1562 resource->mailbox.set_sync_point(returned.sync_point);
1566 if (!resource->marked_for_deletion)
1569 if (!resource->child_id) {
1570 // The resource belongs to this ResourceProvider, so it can be destroyed.
1571 DeleteResourceInternal(map_iterator, Normal);
1575 DCHECK(resource->origin == Resource::Delegated);
1576 // Delete the resource and return it to the child it came from one.
1577 if (resource->child_id != child_id) {
1579 DCHECK_NE(resources_for_child.size(), 0u);
1580 DCHECK(child_it != children_.end());
1581 DeleteAndReturnUnusedResourcesToChild(
1582 child_it, Normal, resources_for_child);
1583 resources_for_child.clear();
1586 child_it = children_.find(resource->child_id);
1587 DCHECK(child_it != children_.end());
1588 child_id = resource->child_id;
1590 resources_for_child.push_back(local_id);
1594 DCHECK_NE(resources_for_child.size(), 0u);
1595 DCHECK(child_it != children_.end());
1596 DeleteAndReturnUnusedResourcesToChild(
1597 child_it, Normal, resources_for_child);
1601 void ResourceProvider::TransferResource(GLES2Interface* gl,
1603 TransferableResource* resource) {
1604 Resource* source = GetResource(id);
1605 DCHECK(!source->locked_for_write);
1606 DCHECK(!source->lock_for_read_count);
1607 DCHECK(source->origin != Resource::External || source->mailbox.IsValid());
1608 DCHECK(source->allocated);
1609 DCHECK_EQ(source->wrap_mode, GL_CLAMP_TO_EDGE);
1611 resource->format = source->format;
1612 resource->mailbox_holder.texture_target = source->target;
1613 resource->filter = source->filter;
1614 resource->size = source->size;
1616 if (source->type == Bitmap) {
1617 resource->mailbox_holder.mailbox = source->shared_bitmap_id;
1618 resource->is_software = true;
1619 } else if (!source->mailbox.IsValid()) {
1621 DCHECK(source->gl_id);
1622 DCHECK(source->origin == Resource::Internal);
1624 gl->BindTexture(resource->mailbox_holder.texture_target,
1626 if (source->image_id) {
1627 DCHECK(source->dirty_image);
1628 BindImageForSampling(source);
1630 // This is a resource allocated by the compositor, we need to produce it.
1631 // Don't set a sync point, the caller will do it.
1632 GLC(gl, gl->GenMailboxCHROMIUM(resource->mailbox_holder.mailbox.name));
1634 gl->ProduceTextureCHROMIUM(resource->mailbox_holder.texture_target,
1635 resource->mailbox_holder.mailbox.name));
1636 source->mailbox = TextureMailbox(resource->mailbox_holder);
1638 DCHECK(source->mailbox.IsTexture());
1639 if (source->image_id && source->dirty_image) {
1640 DCHECK(source->gl_id);
1641 DCHECK(source->origin == Resource::Internal);
1643 gl->BindTexture(resource->mailbox_holder.texture_target,
1645 BindImageForSampling(source);
1647 // This is either an external resource, or a compositor resource that we
1648 // already exported. Make sure to forward the sync point that we were given.
1649 resource->mailbox_holder.mailbox = source->mailbox.mailbox();
1650 resource->mailbox_holder.texture_target = source->mailbox.target();
1651 resource->mailbox_holder.sync_point = source->mailbox.sync_point();
1652 source->mailbox.set_sync_point(0);
1656 void ResourceProvider::DeleteAndReturnUnusedResourcesToChild(
1657 ChildMap::iterator child_it,
1659 const ResourceIdArray& unused) {
1660 DCHECK(thread_checker_.CalledOnValidThread());
1661 DCHECK(child_it != children_.end());
1662 Child* child_info = &child_it->second;
1664 if (unused.empty() && !child_info->marked_for_deletion)
1667 ReturnedResourceArray to_return;
1669 GLES2Interface* gl = ContextGL();
1670 bool need_sync_point = false;
1671 for (size_t i = 0; i < unused.size(); ++i) {
1672 ResourceId local_id = unused[i];
1674 ResourceMap::iterator it = resources_.find(local_id);
1675 CHECK(it != resources_.end());
1676 Resource& resource = it->second;
1678 DCHECK(!resource.locked_for_write);
1679 DCHECK_EQ(0u, child_info->in_use_resources.count(local_id));
1680 DCHECK(child_info->parent_to_child_map.count(local_id));
1682 ResourceId child_id = child_info->parent_to_child_map[local_id];
1683 DCHECK(child_info->child_to_parent_map.count(child_id));
1686 resource.lost || (resource.type == GLTexture && lost_output_surface_);
1687 if (resource.exported_count > 0 || resource.lock_for_read_count > 0) {
1688 if (style != ForShutdown) {
1689 // Defer this until we receive the resource back from the parent or
1690 // the read lock is released.
1691 resource.marked_for_deletion = true;
1695 // We still have an exported_count, so we'll have to lose it.
1699 if (gl && resource.filter != resource.original_filter) {
1700 DCHECK(resource.target);
1701 DCHECK(resource.gl_id);
1703 GLC(gl, gl->BindTexture(resource.target, resource.gl_id));
1705 gl->TexParameteri(resource.target,
1706 GL_TEXTURE_MIN_FILTER,
1707 resource.original_filter));
1709 gl->TexParameteri(resource.target,
1710 GL_TEXTURE_MAG_FILTER,
1711 resource.original_filter));
1714 ReturnedResource returned;
1715 returned.id = child_id;
1716 returned.sync_point = resource.mailbox.sync_point();
1717 if (!returned.sync_point && resource.type == GLTexture)
1718 need_sync_point = true;
1719 returned.count = resource.imported_count;
1720 returned.lost = is_lost;
1721 to_return.push_back(returned);
1723 child_info->parent_to_child_map.erase(local_id);
1724 child_info->child_to_parent_map.erase(child_id);
1725 resource.imported_count = 0;
1726 DeleteResourceInternal(it, style);
1728 if (need_sync_point) {
1730 GLuint sync_point = gl->InsertSyncPointCHROMIUM();
1731 for (size_t i = 0; i < to_return.size(); ++i) {
1732 if (!to_return[i].sync_point)
1733 to_return[i].sync_point = sync_point;
1737 if (!to_return.empty())
1738 child_info->return_callback.Run(to_return);
1740 if (child_info->marked_for_deletion &&
1741 child_info->parent_to_child_map.empty()) {
1742 DCHECK(child_info->child_to_parent_map.empty());
1743 children_.erase(child_it);
1747 SkCanvas* ResourceProvider::MapDirectRasterBuffer(ResourceId id) {
1748 // Resource needs to be locked for write since DirectRasterBuffer writes
1751 Resource* resource = GetResource(id);
1752 if (!resource->direct_raster_buffer.get()) {
1753 resource->direct_raster_buffer.reset(
1754 new DirectRasterBuffer(resource, this, use_distance_field_text_));
1756 return resource->direct_raster_buffer->LockForWrite();
1759 void ResourceProvider::UnmapDirectRasterBuffer(ResourceId id) {
1760 Resource* resource = GetResource(id);
1761 DCHECK(resource->direct_raster_buffer.get());
1762 resource->direct_raster_buffer->UnlockForWrite();
1766 SkCanvas* ResourceProvider::MapImageRasterBuffer(ResourceId id) {
1767 Resource* resource = GetResource(id);
1768 AcquireImage(resource);
1769 if (!resource->image_raster_buffer.get())
1770 resource->image_raster_buffer.reset(new ImageRasterBuffer(resource, this));
1771 return resource->image_raster_buffer->LockForWrite();
1774 bool ResourceProvider::UnmapImageRasterBuffer(ResourceId id) {
1775 Resource* resource = GetResource(id);
1776 resource->dirty_image = true;
1777 return resource->image_raster_buffer->UnlockForWrite();
1780 void ResourceProvider::AcquirePixelRasterBuffer(ResourceId id) {
1781 Resource* resource = GetResource(id);
1782 AcquirePixelBuffer(resource);
1783 resource->pixel_raster_buffer.reset(new PixelRasterBuffer(resource, this));
1786 void ResourceProvider::ReleasePixelRasterBuffer(ResourceId id) {
1787 Resource* resource = GetResource(id);
1788 resource->pixel_raster_buffer.reset();
1789 ReleasePixelBuffer(resource);
1792 SkCanvas* ResourceProvider::MapPixelRasterBuffer(ResourceId id) {
1793 Resource* resource = GetResource(id);
1794 DCHECK(resource->pixel_raster_buffer.get());
1795 return resource->pixel_raster_buffer->LockForWrite();
1798 bool ResourceProvider::UnmapPixelRasterBuffer(ResourceId id) {
1799 Resource* resource = GetResource(id);
1800 DCHECK(resource->pixel_raster_buffer.get());
1801 return resource->pixel_raster_buffer->UnlockForWrite();
1804 void ResourceProvider::AcquirePixelBuffer(Resource* resource) {
1805 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug"),
1806 "ResourceProvider::AcquirePixelBuffer");
1808 DCHECK(resource->origin == Resource::Internal);
1809 DCHECK_EQ(resource->exported_count, 0);
1810 DCHECK(!resource->image_id);
1811 DCHECK_NE(ETC1, resource->format);
1813 DCHECK_EQ(GLTexture, resource->type);
1814 GLES2Interface* gl = ContextGL();
1816 if (!resource->gl_pixel_buffer_id)
1817 resource->gl_pixel_buffer_id = buffer_id_allocator_->NextId();
1818 gl->BindBuffer(GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM,
1819 resource->gl_pixel_buffer_id);
1820 unsigned bytes_per_pixel = BitsPerPixel(resource->format) / 8;
1821 gl->BufferData(GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM,
1822 resource->size.height() *
1823 RoundUp(bytes_per_pixel * resource->size.width(), 4u),
1826 gl->BindBuffer(GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM, 0);
1829 void ResourceProvider::ReleasePixelBuffer(Resource* resource) {
1830 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug"),
1831 "ResourceProvider::ReleasePixelBuffer");
1833 DCHECK(resource->origin == Resource::Internal);
1834 DCHECK_EQ(resource->exported_count, 0);
1835 DCHECK(!resource->image_id);
1837 // The pixel buffer can be released while there is a pending "set pixels"
1838 // if completion has been forced. Any shared memory associated with this
1839 // pixel buffer will not be freed until the waitAsyncTexImage2DCHROMIUM
1840 // command has been processed on the service side. It is also safe to
1841 // reuse any query id associated with this resource before they complete
1842 // as each new query has a unique submit count.
1843 if (resource->pending_set_pixels) {
1844 DCHECK(resource->set_pixels_completion_forced);
1845 resource->pending_set_pixels = false;
1846 resource->locked_for_write = false;
1849 DCHECK_EQ(GLTexture, resource->type);
1850 if (!resource->gl_pixel_buffer_id)
1852 GLES2Interface* gl = ContextGL();
1854 gl->BindBuffer(GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM,
1855 resource->gl_pixel_buffer_id);
1857 GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM, 0, NULL, GL_DYNAMIC_DRAW);
1858 gl->BindBuffer(GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM, 0);
1861 uint8_t* ResourceProvider::MapPixelBuffer(const Resource* resource,
1863 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug"),
1864 "ResourceProvider::MapPixelBuffer");
1866 DCHECK(resource->origin == Resource::Internal);
1867 DCHECK_EQ(resource->exported_count, 0);
1868 DCHECK(!resource->image_id);
1871 DCHECK_EQ(GLTexture, resource->type);
1872 GLES2Interface* gl = ContextGL();
1874 DCHECK(resource->gl_pixel_buffer_id);
1875 gl->BindBuffer(GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM,
1876 resource->gl_pixel_buffer_id);
1877 uint8_t* image = static_cast<uint8_t*>(gl->MapBufferCHROMIUM(
1878 GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM, GL_WRITE_ONLY));
1879 gl->BindBuffer(GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM, 0);
1880 // Buffer is required to be 4-byte aligned.
1881 CHECK(!(reinterpret_cast<intptr_t>(image) & 3));
1885 void ResourceProvider::UnmapPixelBuffer(const Resource* resource) {
1886 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug"),
1887 "ResourceProvider::UnmapPixelBuffer");
1889 DCHECK(resource->origin == Resource::Internal);
1890 DCHECK_EQ(resource->exported_count, 0);
1891 DCHECK(!resource->image_id);
1893 DCHECK_EQ(GLTexture, resource->type);
1894 GLES2Interface* gl = ContextGL();
1896 DCHECK(resource->gl_pixel_buffer_id);
1897 gl->BindBuffer(GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM,
1898 resource->gl_pixel_buffer_id);
1899 gl->UnmapBufferCHROMIUM(GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM);
1900 gl->BindBuffer(GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM, 0);
1903 GLenum ResourceProvider::BindForSampling(
1904 ResourceProvider::ResourceId resource_id,
1907 DCHECK(thread_checker_.CalledOnValidThread());
1908 GLES2Interface* gl = ContextGL();
1909 ResourceMap::iterator it = resources_.find(resource_id);
1910 DCHECK(it != resources_.end());
1911 Resource* resource = &it->second;
1912 DCHECK(resource->lock_for_read_count);
1913 DCHECK(!resource->locked_for_write || resource->set_pixels_completion_forced);
1915 ScopedSetActiveTexture scoped_active_tex(gl, unit);
1916 GLenum target = resource->target;
1917 GLC(gl, gl->BindTexture(target, resource->gl_id));
1918 if (filter != resource->filter) {
1919 GLC(gl, gl->TexParameteri(target, GL_TEXTURE_MIN_FILTER, filter));
1920 GLC(gl, gl->TexParameteri(target, GL_TEXTURE_MAG_FILTER, filter));
1921 resource->filter = filter;
1924 if (resource->image_id && resource->dirty_image)
1925 BindImageForSampling(resource);
1930 void ResourceProvider::BeginSetPixels(ResourceId id) {
1931 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug"),
1932 "ResourceProvider::BeginSetPixels");
1934 Resource* resource = GetResource(id);
1935 DCHECK(!resource->pending_set_pixels);
1937 LazyCreate(resource);
1938 DCHECK(resource->origin == Resource::Internal);
1939 DCHECK(resource->gl_id || resource->allocated);
1940 DCHECK(ReadLockFenceHasPassed(resource));
1941 DCHECK(!resource->image_id);
1943 bool allocate = !resource->allocated;
1944 resource->allocated = true;
1947 DCHECK_EQ(GLTexture, resource->type);
1948 DCHECK(resource->gl_id);
1949 GLES2Interface* gl = ContextGL();
1951 DCHECK(resource->gl_pixel_buffer_id);
1952 DCHECK_EQ(resource->target, static_cast<GLenum>(GL_TEXTURE_2D));
1953 gl->BindTexture(GL_TEXTURE_2D, resource->gl_id);
1954 gl->BindBuffer(GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM,
1955 resource->gl_pixel_buffer_id);
1956 if (!resource->gl_upload_query_id)
1957 gl->GenQueriesEXT(1, &resource->gl_upload_query_id);
1958 gl->BeginQueryEXT(GL_ASYNC_PIXEL_UNPACK_COMPLETED_CHROMIUM,
1959 resource->gl_upload_query_id);
1961 gl->AsyncTexImage2DCHROMIUM(GL_TEXTURE_2D,
1963 GLInternalFormat(resource->format),
1964 resource->size.width(),
1965 resource->size.height(),
1967 GLDataFormat(resource->format),
1968 GLDataType(resource->format),
1971 gl->AsyncTexSubImage2DCHROMIUM(GL_TEXTURE_2D,
1975 resource->size.width(),
1976 resource->size.height(),
1977 GLDataFormat(resource->format),
1978 GLDataType(resource->format),
1981 gl->EndQueryEXT(GL_ASYNC_PIXEL_UNPACK_COMPLETED_CHROMIUM);
1982 gl->BindBuffer(GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM, 0);
1984 resource->pending_set_pixels = true;
1985 resource->set_pixels_completion_forced = false;
1988 void ResourceProvider::ForceSetPixelsToComplete(ResourceId id) {
1989 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug"),
1990 "ResourceProvider::ForceSetPixelsToComplete");
1992 Resource* resource = GetResource(id);
1993 DCHECK(resource->locked_for_write);
1994 DCHECK(resource->pending_set_pixels);
1995 DCHECK(!resource->set_pixels_completion_forced);
1997 if (resource->gl_id) {
1998 GLES2Interface* gl = ContextGL();
1999 GLC(gl, gl->BindTexture(GL_TEXTURE_2D, resource->gl_id));
2000 GLC(gl, gl->WaitAsyncTexImage2DCHROMIUM(GL_TEXTURE_2D));
2001 GLC(gl, gl->BindTexture(GL_TEXTURE_2D, 0));
2004 resource->set_pixels_completion_forced = true;
2007 bool ResourceProvider::DidSetPixelsComplete(ResourceId id) {
2008 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug"),
2009 "ResourceProvider::DidSetPixelsComplete");
2011 Resource* resource = GetResource(id);
2012 DCHECK(resource->locked_for_write);
2013 DCHECK(resource->pending_set_pixels);
2015 if (resource->gl_id) {
2016 GLES2Interface* gl = ContextGL();
2018 DCHECK(resource->gl_upload_query_id);
2019 GLuint complete = 1;
2020 gl->GetQueryObjectuivEXT(
2021 resource->gl_upload_query_id, GL_QUERY_RESULT_AVAILABLE_EXT, &complete);
2026 resource->pending_set_pixels = false;
2032 void ResourceProvider::CreateForTesting(ResourceId id) {
2033 LazyCreate(GetResource(id));
2036 GLenum ResourceProvider::TargetForTesting(ResourceId id) {
2037 Resource* resource = GetResource(id);
2038 return resource->target;
2041 void ResourceProvider::LazyCreate(Resource* resource) {
2042 if (resource->type != GLTexture || resource->origin != Resource::Internal)
2045 if (resource->gl_id)
2048 DCHECK(resource->texture_pool);
2049 DCHECK(resource->origin == Resource::Internal);
2050 DCHECK(!resource->mailbox.IsValid());
2051 resource->gl_id = texture_id_allocator_->NextId();
2053 GLES2Interface* gl = ContextGL();
2056 // Create and set texture properties. Allocation is delayed until needed.
2057 GLC(gl, gl->BindTexture(resource->target, resource->gl_id));
2059 gl->TexParameteri(resource->target, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
2061 gl->TexParameteri(resource->target, GL_TEXTURE_MAG_FILTER, GL_LINEAR));
2064 resource->target, GL_TEXTURE_WRAP_S, resource->wrap_mode));
2067 resource->target, GL_TEXTURE_WRAP_T, resource->wrap_mode));
2070 resource->target, GL_TEXTURE_POOL_CHROMIUM, resource->texture_pool));
2071 if (use_texture_usage_hint_ && resource->hint == TextureUsageFramebuffer) {
2073 gl->TexParameteri(resource->target,
2074 GL_TEXTURE_USAGE_ANGLE,
2075 GL_FRAMEBUFFER_ATTACHMENT_ANGLE));
2079 void ResourceProvider::AllocateForTesting(ResourceId id) {
2080 LazyAllocate(GetResource(id));
2083 void ResourceProvider::LazyAllocate(Resource* resource) {
2085 LazyCreate(resource);
2087 DCHECK(resource->gl_id || resource->allocated);
2088 if (resource->allocated || !resource->gl_id)
2090 resource->allocated = true;
2091 GLES2Interface* gl = ContextGL();
2092 gfx::Size& size = resource->size;
2093 DCHECK_EQ(resource->target, static_cast<GLenum>(GL_TEXTURE_2D));
2094 ResourceFormat format = resource->format;
2095 GLC(gl, gl->BindTexture(GL_TEXTURE_2D, resource->gl_id));
2096 if (use_texture_storage_ext_ && IsFormatSupportedForStorage(format) &&
2097 resource->hint != TextureUsageFramebuffer) {
2098 GLenum storage_format = TextureToStorageFormat(format);
2100 gl->TexStorage2DEXT(
2101 GL_TEXTURE_2D, 1, storage_format, size.width(), size.height()));
2103 // ETC1 does not support preallocation.
2104 if (format != ETC1) {
2106 gl->TexImage2D(GL_TEXTURE_2D,
2108 GLInternalFormat(format),
2112 GLDataFormat(format),
2119 void ResourceProvider::BindImageForSampling(Resource* resource) {
2120 GLES2Interface* gl = ContextGL();
2121 DCHECK(resource->gl_id);
2122 DCHECK(resource->image_id);
2124 // Release image currently bound to texture.
2125 if (resource->bound_image_id)
2126 gl->ReleaseTexImage2DCHROMIUM(resource->target, resource->bound_image_id);
2127 gl->BindTexImage2DCHROMIUM(resource->target, resource->image_id);
2128 resource->bound_image_id = resource->image_id;
2129 resource->dirty_image = false;
2132 void ResourceProvider::EnableReadLockFences(ResourceProvider::ResourceId id,
2134 Resource* resource = GetResource(id);
2135 resource->enable_read_lock_fences = enable;
2138 void ResourceProvider::AcquireImage(Resource* resource) {
2139 DCHECK(resource->origin == Resource::Internal);
2140 DCHECK_EQ(resource->exported_count, 0);
2142 if (resource->type != GLTexture)
2145 if (resource->image_id)
2148 resource->allocated = true;
2149 GLES2Interface* gl = ContextGL();
2151 resource->image_id =
2152 gl->CreateImageCHROMIUM(resource->size.width(),
2153 resource->size.height(),
2154 TextureToStorageFormat(resource->format),
2155 GL_IMAGE_MAP_CHROMIUM);
2156 DCHECK(resource->image_id);
2159 void ResourceProvider::ReleaseImage(Resource* resource) {
2160 DCHECK(resource->origin == Resource::Internal);
2161 DCHECK_EQ(resource->exported_count, 0);
2163 if (!resource->image_id)
2166 GLES2Interface* gl = ContextGL();
2168 gl->DestroyImageCHROMIUM(resource->image_id);
2169 resource->image_id = 0;
2170 resource->bound_image_id = 0;
2171 resource->dirty_image = false;
2172 resource->allocated = false;
2175 uint8_t* ResourceProvider::MapImage(const Resource* resource, int* stride) {
2176 DCHECK(ReadLockFenceHasPassed(resource));
2177 DCHECK(resource->origin == Resource::Internal);
2178 DCHECK_EQ(resource->exported_count, 0);
2180 if (resource->type == GLTexture) {
2181 DCHECK(resource->image_id);
2182 GLES2Interface* gl = ContextGL();
2184 // MapImageCHROMIUM should be called prior to GetImageParameterivCHROMIUM.
2186 static_cast<uint8_t*>(gl->MapImageCHROMIUM(resource->image_id));
2187 gl->GetImageParameterivCHROMIUM(
2188 resource->image_id, GL_IMAGE_ROWBYTES_CHROMIUM, stride);
2191 DCHECK_EQ(Bitmap, resource->type);
2193 return resource->pixels;
2196 void ResourceProvider::UnmapImage(const Resource* resource) {
2197 DCHECK(resource->origin == Resource::Internal);
2198 DCHECK_EQ(resource->exported_count, 0);
2200 if (resource->image_id) {
2201 GLES2Interface* gl = ContextGL();
2203 gl->UnmapImageCHROMIUM(resource->image_id);
2207 void ResourceProvider::CopyResource(ResourceId source_id, ResourceId dest_id) {
2208 TRACE_EVENT0("cc", "ResourceProvider::CopyResource");
2210 Resource* source_resource = GetResource(source_id);
2211 DCHECK(!source_resource->lock_for_read_count);
2212 DCHECK(source_resource->origin == Resource::Internal);
2213 DCHECK_EQ(source_resource->exported_count, 0);
2214 DCHECK(source_resource->allocated);
2215 LazyCreate(source_resource);
2217 Resource* dest_resource = GetResource(dest_id);
2218 DCHECK(!dest_resource->locked_for_write);
2219 DCHECK(!dest_resource->lock_for_read_count);
2220 DCHECK(dest_resource->origin == Resource::Internal);
2221 DCHECK_EQ(dest_resource->exported_count, 0);
2222 LazyCreate(dest_resource);
2224 DCHECK_EQ(source_resource->type, dest_resource->type);
2225 DCHECK_EQ(source_resource->format, dest_resource->format);
2226 DCHECK(source_resource->size == dest_resource->size);
2228 if (source_resource->type == GLTexture) {
2229 GLES2Interface* gl = ContextGL();
2231 if (source_resource->image_id && source_resource->dirty_image) {
2232 gl->BindTexture(source_resource->target, source_resource->gl_id);
2233 BindImageForSampling(source_resource);
2235 DCHECK(use_sync_query_) << "CHROMIUM_sync_query extension missing";
2236 if (!source_resource->gl_read_lock_query_id)
2237 gl->GenQueriesEXT(1, &source_resource->gl_read_lock_query_id);
2238 gl->BeginQueryEXT(GL_COMMANDS_COMPLETED_CHROMIUM,
2239 source_resource->gl_read_lock_query_id);
2240 DCHECK(!dest_resource->image_id);
2241 dest_resource->allocated = true;
2242 gl->CopyTextureCHROMIUM(dest_resource->target,
2243 source_resource->gl_id,
2244 dest_resource->gl_id,
2246 GLInternalFormat(dest_resource->format),
2247 GLDataType(dest_resource->format));
2248 // End query and create a read lock fence that will prevent access to
2249 // source resource until CopyTextureCHROMIUM command has completed.
2250 gl->EndQueryEXT(GL_COMMANDS_COMPLETED_CHROMIUM);
2251 source_resource->read_lock_fence = make_scoped_refptr(
2252 new QueryFence(gl, source_resource->gl_read_lock_query_id));
2254 DCHECK_EQ(Bitmap, source_resource->type);
2255 DCHECK_EQ(RGBA_8888, source_resource->format);
2256 LazyAllocate(dest_resource);
2258 size_t bytes = SharedBitmap::CheckedSizeInBytes(source_resource->size);
2259 memcpy(dest_resource->pixels, source_resource->pixels, bytes);
2263 GLint ResourceProvider::GetActiveTextureUnit(GLES2Interface* gl) {
2264 GLint active_unit = 0;
2265 gl->GetIntegerv(GL_ACTIVE_TEXTURE, &active_unit);
2269 GLES2Interface* ResourceProvider::ContextGL() const {
2270 ContextProvider* context_provider = output_surface_->context_provider();
2271 return context_provider ? context_provider->ContextGL() : NULL;
2274 class GrContext* ResourceProvider::GrContext() const {
2275 ContextProvider* context_provider = output_surface_->context_provider();
2276 return context_provider ? context_provider->GrContext() : NULL;