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,
126 SkBitmap::Config dst_config) {
128 IdentityAllocator allocator(dst);
129 src.copyTo(&dst_bitmap, dst_config, &allocator);
130 // TODO(kaanb): The GL pipeline assumes a 4-byte alignment for the
131 // bitmap data. This check will be removed once crbug.com/293728 is fixed.
132 CHECK_EQ(0u, dst_bitmap.rowBytes() % 4);
135 class ScopedSetActiveTexture {
137 ScopedSetActiveTexture(GLES2Interface* gl, GLenum unit)
138 : gl_(gl), unit_(unit) {
139 DCHECK_EQ(GL_TEXTURE0, ResourceProvider::GetActiveTextureUnit(gl_));
141 if (unit_ != GL_TEXTURE0)
142 GLC(gl_, gl_->ActiveTexture(unit_));
145 ~ScopedSetActiveTexture() {
146 // Active unit being GL_TEXTURE0 is effectively the ground state.
147 if (unit_ != GL_TEXTURE0)
148 GLC(gl_, gl_->ActiveTexture(GL_TEXTURE0));
156 class TextureIdAllocator : public IdAllocator {
158 TextureIdAllocator(GLES2Interface* gl,
159 size_t texture_id_allocation_chunk_size)
160 : IdAllocator(gl, texture_id_allocation_chunk_size) {}
161 virtual ~TextureIdAllocator() {
162 gl_->DeleteTextures(id_allocation_chunk_size_ - next_id_index_,
163 ids_.get() + next_id_index_);
166 // Overridden from IdAllocator:
167 virtual GLuint NextId() OVERRIDE {
168 if (next_id_index_ == id_allocation_chunk_size_) {
169 gl_->GenTextures(id_allocation_chunk_size_, ids_.get());
173 return ids_[next_id_index_++];
177 DISALLOW_COPY_AND_ASSIGN(TextureIdAllocator);
180 class BufferIdAllocator : public IdAllocator {
182 BufferIdAllocator(GLES2Interface* gl, size_t buffer_id_allocation_chunk_size)
183 : IdAllocator(gl, buffer_id_allocation_chunk_size) {}
184 virtual ~BufferIdAllocator() {
185 gl_->DeleteBuffers(id_allocation_chunk_size_ - next_id_index_,
186 ids_.get() + next_id_index_);
189 // Overridden from IdAllocator:
190 virtual GLuint NextId() OVERRIDE {
191 if (next_id_index_ == id_allocation_chunk_size_) {
192 gl_->GenBuffers(id_allocation_chunk_size_, ids_.get());
196 return ids_[next_id_index_++];
200 DISALLOW_COPY_AND_ASSIGN(BufferIdAllocator);
205 ResourceProvider::Resource::Resource()
208 gl_pixel_buffer_id(0),
209 gl_upload_query_id(0),
212 lock_for_read_count(0),
215 locked_for_write(false),
217 marked_for_deletion(false),
218 pending_set_pixels(false),
219 set_pixels_completion_forced(false),
221 enable_read_lock_fences(false),
222 read_lock_fence(NULL),
233 hint(TextureUsageAny),
236 has_shared_bitmap_id(false),
237 shared_bitmap(NULL) {}
239 ResourceProvider::Resource::~Resource() {}
241 ResourceProvider::Resource::Resource(GLuint texture_id,
242 const gfx::Size& size,
248 TextureUsageHint hint,
249 ResourceFormat format)
252 gl_pixel_buffer_id(0),
253 gl_upload_query_id(0),
256 lock_for_read_count(0),
259 locked_for_write(false),
261 marked_for_deletion(false),
262 pending_set_pixels(false),
263 set_pixels_completion_forced(false),
265 enable_read_lock_fences(false),
266 read_lock_fence(NULL),
269 original_filter(filter),
274 texture_pool(texture_pool),
275 wrap_mode(wrap_mode),
280 has_shared_bitmap_id(false),
281 shared_bitmap(NULL) {
282 DCHECK(wrap_mode == GL_CLAMP_TO_EDGE || wrap_mode == GL_REPEAT);
283 DCHECK_EQ(origin == Internal, !!texture_pool);
286 ResourceProvider::Resource::Resource(uint8_t* pixels,
287 SharedBitmap* bitmap,
288 const gfx::Size& size,
294 gl_pixel_buffer_id(0),
295 gl_upload_query_id(0),
298 lock_for_read_count(0),
301 locked_for_write(false),
303 marked_for_deletion(false),
304 pending_set_pixels(false),
305 set_pixels_completion_forced(false),
307 enable_read_lock_fences(false),
308 read_lock_fence(NULL),
311 original_filter(filter),
317 wrap_mode(wrap_mode),
319 hint(TextureUsageAny),
322 has_shared_bitmap_id(!!bitmap),
323 shared_bitmap(bitmap) {
324 DCHECK(wrap_mode == GL_CLAMP_TO_EDGE || wrap_mode == GL_REPEAT);
325 DCHECK(origin == Delegated || pixels);
327 shared_bitmap_id = bitmap->id();
330 ResourceProvider::Resource::Resource(const SharedBitmapId& bitmap_id,
331 const gfx::Size& size,
337 gl_pixel_buffer_id(0),
338 gl_upload_query_id(0),
341 lock_for_read_count(0),
344 locked_for_write(false),
346 marked_for_deletion(false),
347 pending_set_pixels(false),
348 set_pixels_completion_forced(false),
350 enable_read_lock_fences(false),
351 read_lock_fence(NULL),
354 original_filter(filter),
360 wrap_mode(wrap_mode),
362 hint(TextureUsageAny),
365 has_shared_bitmap_id(true),
366 shared_bitmap_id(bitmap_id),
367 shared_bitmap(NULL) {
368 DCHECK(wrap_mode == GL_CLAMP_TO_EDGE || wrap_mode == GL_REPEAT);
371 ResourceProvider::RasterBuffer::RasterBuffer(
372 const Resource* resource,
373 ResourceProvider* resource_provider)
374 : resource_(resource),
375 resource_provider_(resource_provider),
376 locked_canvas_(NULL),
377 canvas_save_count_(0) {
379 DCHECK(resource_provider_);
382 ResourceProvider::RasterBuffer::~RasterBuffer() {}
384 SkCanvas* ResourceProvider::RasterBuffer::LockForWrite() {
385 DCHECK(!locked_canvas_);
387 locked_canvas_ = DoLockForWrite();
388 canvas_save_count_ = locked_canvas_ ? locked_canvas_->save() : 0;
389 return locked_canvas_;
392 void ResourceProvider::RasterBuffer::UnlockForWrite() {
393 if (locked_canvas_) {
394 locked_canvas_->restoreToCount(canvas_save_count_);
395 locked_canvas_ = NULL;
400 ResourceProvider::DirectRasterBuffer::DirectRasterBuffer(
401 const Resource* resource,
402 ResourceProvider* resource_provider)
403 : RasterBuffer(resource, resource_provider) {}
405 ResourceProvider::DirectRasterBuffer::~DirectRasterBuffer() {}
407 SkCanvas* ResourceProvider::DirectRasterBuffer::DoLockForWrite() {
409 surface_ = CreateSurface();
410 return surface_ ? surface_->getCanvas() : NULL;
413 void ResourceProvider::DirectRasterBuffer::DoUnlockForWrite() {}
415 skia::RefPtr<SkSurface> ResourceProvider::DirectRasterBuffer::CreateSurface() {
416 skia::RefPtr<SkSurface> surface;
417 switch (resource()->type) {
419 DCHECK(resource()->gl_id);
420 class GrContext* gr_context = resource_provider()->GrContext();
422 GrBackendTextureDesc desc;
423 desc.fFlags = kRenderTarget_GrBackendTextureFlag;
424 desc.fWidth = resource()->size.width();
425 desc.fHeight = resource()->size.height();
426 desc.fConfig = ToGrPixelConfig(resource()->format);
427 desc.fOrigin = kTopLeft_GrSurfaceOrigin;
428 desc.fTextureHandle = resource()->gl_id;
429 skia::RefPtr<GrTexture> gr_texture =
430 skia::AdoptRef(gr_context->wrapBackendTexture(desc));
431 surface = skia::AdoptRef(
432 SkSurface::NewRenderTargetDirect(gr_texture->asRenderTarget()));
437 DCHECK(resource()->pixels);
438 DCHECK_EQ(RGBA_8888, resource()->format);
439 SkImageInfo image_info = SkImageInfo::MakeN32Premul(
440 resource()->size.width(), resource()->size.height());
441 size_t row_bytes = SkBitmap::ComputeRowBytes(SkBitmap::kARGB_8888_Config,
442 resource()->size.width());
443 surface = skia::AdoptRef(SkSurface::NewRasterDirect(
444 image_info, resource()->pixels, row_bytes));
453 ResourceProvider::BitmapRasterBuffer::BitmapRasterBuffer(
454 const Resource* resource,
455 ResourceProvider* resource_provider)
456 : RasterBuffer(resource, resource_provider), mapped_buffer_(NULL) {}
458 ResourceProvider::BitmapRasterBuffer::~BitmapRasterBuffer() {}
460 SkCanvas* ResourceProvider::BitmapRasterBuffer::DoLockForWrite() {
461 DCHECK(!mapped_buffer_);
462 DCHECK(!raster_canvas_);
465 mapped_buffer_ = MapBuffer(&stride);
469 switch (resource()->format) {
471 // Use the default stride if we will eventually convert this
473 raster_bitmap_.setConfig(SkBitmap::kARGB_8888_Config,
474 resource()->size.width(),
475 resource()->size.height());
476 raster_bitmap_.allocPixels();
480 raster_bitmap_.setConfig(SkBitmap::kARGB_8888_Config,
481 resource()->size.width(),
482 resource()->size.height(),
484 raster_bitmap_.setPixels(mapped_buffer_);
492 skia::RefPtr<SkBitmapDevice> device =
493 skia::AdoptRef(new SkBitmapDevice(raster_bitmap_));
494 raster_canvas_ = skia::AdoptRef(new SkCanvas(device.get()));
495 return raster_canvas_.get();
498 void ResourceProvider::BitmapRasterBuffer::DoUnlockForWrite() {
499 raster_canvas_.clear();
501 SkBitmap::Config buffer_config = SkBitmapConfig(resource()->format);
502 if (mapped_buffer_ && (buffer_config != raster_bitmap_.config()))
503 CopyBitmap(raster_bitmap_, mapped_buffer_, buffer_config);
504 raster_bitmap_.reset();
507 mapped_buffer_ = NULL;
510 ResourceProvider::ImageRasterBuffer::ImageRasterBuffer(
511 const Resource* resource,
512 ResourceProvider* resource_provider)
513 : BitmapRasterBuffer(resource, resource_provider) {}
515 ResourceProvider::ImageRasterBuffer::~ImageRasterBuffer() {}
517 uint8_t* ResourceProvider::ImageRasterBuffer::MapBuffer(int* stride) {
518 return resource_provider()->MapImage(resource(), stride);
521 void ResourceProvider::ImageRasterBuffer::UnmapBuffer() {
522 resource_provider()->UnmapImage(resource());
525 ResourceProvider::PixelRasterBuffer::PixelRasterBuffer(
526 const Resource* resource,
527 ResourceProvider* resource_provider)
528 : BitmapRasterBuffer(resource, resource_provider) {}
530 ResourceProvider::PixelRasterBuffer::~PixelRasterBuffer() {}
532 uint8_t* ResourceProvider::PixelRasterBuffer::MapBuffer(int* stride) {
533 return resource_provider()->MapPixelBuffer(resource(), stride);
536 void ResourceProvider::PixelRasterBuffer::UnmapBuffer() {
537 resource_provider()->UnmapPixelBuffer(resource());
540 ResourceProvider::Child::Child() : marked_for_deletion(false) {}
542 ResourceProvider::Child::~Child() {}
544 scoped_ptr<ResourceProvider> ResourceProvider::Create(
545 OutputSurface* output_surface,
546 SharedBitmapManager* shared_bitmap_manager,
547 int highp_threshold_min,
548 bool use_rgba_4444_texture_format,
549 size_t id_allocation_chunk_size) {
550 scoped_ptr<ResourceProvider> resource_provider(
551 new ResourceProvider(output_surface,
552 shared_bitmap_manager,
554 use_rgba_4444_texture_format,
555 id_allocation_chunk_size));
557 bool success = false;
558 if (resource_provider->ContextGL()) {
559 success = resource_provider->InitializeGL();
561 resource_provider->InitializeSoftware();
566 return scoped_ptr<ResourceProvider>();
568 DCHECK_NE(InvalidType, resource_provider->default_resource_type());
569 return resource_provider.Pass();
572 ResourceProvider::~ResourceProvider() {
573 while (!children_.empty())
574 DestroyChildInternal(children_.begin(), ForShutdown);
575 while (!resources_.empty())
576 DeleteResourceInternal(resources_.begin(), ForShutdown);
581 bool ResourceProvider::InUseByConsumer(ResourceId id) {
582 Resource* resource = GetResource(id);
583 return resource->lock_for_read_count > 0 || resource->exported_count > 0 ||
587 bool ResourceProvider::IsLost(ResourceId id) {
588 Resource* resource = GetResource(id);
589 return resource->lost;
592 ResourceProvider::ResourceId ResourceProvider::CreateResource(
593 const gfx::Size& size,
595 TextureUsageHint hint,
596 ResourceFormat format) {
597 DCHECK(!size.IsEmpty());
598 switch (default_resource_type_) {
600 return CreateGLTexture(size,
602 GL_TEXTURE_POOL_UNMANAGED_CHROMIUM,
607 DCHECK_EQ(RGBA_8888, format);
608 return CreateBitmap(size, wrap_mode);
613 LOG(FATAL) << "Invalid default resource type.";
617 ResourceProvider::ResourceId ResourceProvider::CreateManagedResource(
618 const gfx::Size& size,
621 TextureUsageHint hint,
622 ResourceFormat format) {
623 DCHECK(!size.IsEmpty());
624 switch (default_resource_type_) {
626 return CreateGLTexture(size,
628 GL_TEXTURE_POOL_MANAGED_CHROMIUM,
633 DCHECK_EQ(RGBA_8888, format);
634 return CreateBitmap(size, wrap_mode);
639 LOG(FATAL) << "Invalid default resource type.";
643 ResourceProvider::ResourceId ResourceProvider::CreateGLTexture(
644 const gfx::Size& size,
648 TextureUsageHint hint,
649 ResourceFormat format) {
650 DCHECK_LE(size.width(), max_texture_size_);
651 DCHECK_LE(size.height(), max_texture_size_);
652 DCHECK(thread_checker_.CalledOnValidThread());
654 ResourceId id = next_id_++;
664 resource.allocated = false;
665 resources_[id] = resource;
669 ResourceProvider::ResourceId ResourceProvider::CreateBitmap(
670 const gfx::Size& size, GLint wrap_mode) {
671 DCHECK(thread_checker_.CalledOnValidThread());
673 scoped_ptr<SharedBitmap> bitmap;
674 if (shared_bitmap_manager_)
675 bitmap = shared_bitmap_manager_->AllocateSharedBitmap(size);
679 pixels = bitmap->pixels();
681 pixels = new uint8_t[4 * size.GetArea()];
684 ResourceId id = next_id_++;
686 pixels, bitmap.release(), size, Resource::Internal, GL_LINEAR, wrap_mode);
687 resource.allocated = true;
688 resources_[id] = resource;
692 ResourceProvider::ResourceId
693 ResourceProvider::CreateResourceFromExternalTexture(
694 GLuint texture_target,
696 DCHECK(thread_checker_.CalledOnValidThread());
698 DCHECK(texture_target);
700 GLES2Interface* gl = ContextGL();
702 GLC(gl, gl->BindTexture(texture_target, texture_id));
703 GLC(gl, gl->TexParameteri(texture_target, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
704 GLC(gl, gl->TexParameteri(texture_target, GL_TEXTURE_MAG_FILTER, GL_LINEAR));
706 gl->TexParameteri(texture_target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE));
708 gl->TexParameteri(texture_target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE));
710 ResourceId id = next_id_++;
711 Resource resource(texture_id,
720 resource.allocated = true;
721 resources_[id] = resource;
725 ResourceProvider::ResourceId ResourceProvider::CreateResourceFromTextureMailbox(
726 const TextureMailbox& mailbox,
727 scoped_ptr<SingleReleaseCallback> release_callback) {
728 DCHECK(thread_checker_.CalledOnValidThread());
729 // Just store the information. Mailbox will be consumed in LockForRead().
730 ResourceId id = next_id_++;
731 DCHECK(mailbox.IsValid());
732 Resource& resource = resources_[id];
733 if (mailbox.IsTexture()) {
734 resource = Resource(0,
744 DCHECK(mailbox.IsSharedMemory());
745 base::SharedMemory* shared_memory = mailbox.shared_memory();
746 DCHECK(shared_memory->memory());
747 uint8_t* pixels = reinterpret_cast<uint8_t*>(shared_memory->memory());
749 scoped_ptr<SharedBitmap> shared_bitmap;
750 if (shared_bitmap_manager_) {
752 shared_bitmap_manager_->GetBitmapForSharedMemory(shared_memory);
754 resource = Resource(pixels,
755 shared_bitmap.release(),
756 mailbox.shared_memory_size(),
761 resource.allocated = true;
762 resource.mailbox = mailbox;
763 resource.release_callback =
764 base::Bind(&SingleReleaseCallback::Run,
765 base::Owned(release_callback.release()));
769 void ResourceProvider::DeleteResource(ResourceId id) {
770 DCHECK(thread_checker_.CalledOnValidThread());
771 ResourceMap::iterator it = resources_.find(id);
772 CHECK(it != resources_.end());
773 Resource* resource = &it->second;
774 DCHECK(!resource->lock_for_read_count);
775 DCHECK(!resource->marked_for_deletion);
776 DCHECK_EQ(resource->imported_count, 0);
777 DCHECK(resource->pending_set_pixels || !resource->locked_for_write);
779 if (resource->exported_count > 0) {
780 resource->marked_for_deletion = true;
783 DeleteResourceInternal(it, Normal);
787 void ResourceProvider::DeleteResourceInternal(ResourceMap::iterator it,
789 TRACE_EVENT0("cc", "ResourceProvider::DeleteResourceInternal");
790 Resource* resource = &it->second;
791 bool lost_resource = resource->lost;
793 DCHECK(resource->exported_count == 0 || style != Normal);
794 if (style == ForShutdown && resource->exported_count > 0)
795 lost_resource = true;
797 resource->direct_raster_buffer.reset();
798 resource->image_raster_buffer.reset();
799 resource->pixel_raster_buffer.reset();
801 if (resource->image_id) {
802 DCHECK(resource->origin == Resource::Internal);
803 GLES2Interface* gl = ContextGL();
805 GLC(gl, gl->DestroyImageCHROMIUM(resource->image_id));
808 if (resource->gl_upload_query_id) {
809 DCHECK(resource->origin == Resource::Internal);
810 GLES2Interface* gl = ContextGL();
812 GLC(gl, gl->DeleteQueriesEXT(1, &resource->gl_upload_query_id));
814 if (resource->gl_pixel_buffer_id) {
815 DCHECK(resource->origin == Resource::Internal);
816 GLES2Interface* gl = ContextGL();
818 GLC(gl, gl->DeleteBuffers(1, &resource->gl_pixel_buffer_id));
820 if (resource->mailbox.IsValid() && resource->origin == Resource::External) {
821 GLuint sync_point = resource->mailbox.sync_point();
822 if (resource->type == GLTexture) {
823 DCHECK(resource->mailbox.IsTexture());
824 lost_resource |= lost_output_surface_;
825 GLES2Interface* gl = ContextGL();
827 if (resource->gl_id) {
828 GLC(gl, gl->DeleteTextures(1, &resource->gl_id));
831 sync_point = gl->InsertSyncPointCHROMIUM();
834 DCHECK(resource->mailbox.IsSharedMemory());
835 base::SharedMemory* shared_memory = resource->mailbox.shared_memory();
836 if (resource->pixels && shared_memory) {
837 DCHECK(shared_memory->memory() == resource->pixels);
838 resource->pixels = NULL;
839 delete resource->shared_bitmap;
840 resource->shared_bitmap = NULL;
843 resource->release_callback.Run(sync_point, lost_resource);
845 if (resource->gl_id && resource->origin != Resource::External) {
846 GLES2Interface* gl = ContextGL();
848 GLC(gl, gl->DeleteTextures(1, &resource->gl_id));
851 if (resource->shared_bitmap) {
852 DCHECK(resource->origin != Resource::External);
853 DCHECK_EQ(Bitmap, resource->type);
854 delete resource->shared_bitmap;
855 resource->pixels = NULL;
857 if (resource->pixels) {
858 DCHECK(resource->origin == Resource::Internal);
859 delete[] resource->pixels;
861 if (resource->pixel_buffer) {
862 DCHECK(resource->origin == Resource::Internal);
863 delete[] resource->pixel_buffer;
865 // We should never delete the texture for a resource created by
866 // CreateResourceFromExternalTexture().
867 DCHECK(!resource->gl_id || resource->origin == Resource::External);
869 resources_.erase(it);
872 ResourceProvider::ResourceType ResourceProvider::GetResourceType(
874 return GetResource(id)->type;
877 void ResourceProvider::SetPixels(ResourceId id,
878 const uint8_t* image,
879 const gfx::Rect& image_rect,
880 const gfx::Rect& source_rect,
881 const gfx::Vector2d& dest_offset) {
882 Resource* resource = GetResource(id);
883 DCHECK(!resource->locked_for_write);
884 DCHECK(!resource->lock_for_read_count);
885 DCHECK(resource->origin == Resource::Internal);
886 DCHECK_EQ(resource->exported_count, 0);
887 DCHECK(ReadLockFenceHasPassed(resource));
888 LazyAllocate(resource);
890 if (resource->type == GLTexture) {
891 DCHECK(resource->gl_id);
892 DCHECK(!resource->pending_set_pixels);
893 DCHECK_EQ(resource->target, static_cast<GLenum>(GL_TEXTURE_2D));
894 GLES2Interface* gl = ContextGL();
896 DCHECK(texture_uploader_.get());
897 gl->BindTexture(GL_TEXTURE_2D, resource->gl_id);
898 texture_uploader_->Upload(image,
905 DCHECK_EQ(Bitmap, resource->type);
906 DCHECK(resource->allocated);
907 DCHECK_EQ(RGBA_8888, resource->format);
910 SkBitmap::kARGB_8888_Config, image_rect.width(), image_rect.height());
911 src_full.setPixels(const_cast<uint8_t*>(image));
913 SkIRect sk_source_rect = SkIRect::MakeXYWH(source_rect.x(),
916 source_rect.height());
917 sk_source_rect.offset(-image_rect.x(), -image_rect.y());
918 src_full.extractSubset(&src_subset, sk_source_rect);
920 ScopedWriteLockSoftware lock(this, id);
921 SkCanvas* dest = lock.sk_canvas();
922 dest->writePixels(src_subset, dest_offset.x(), dest_offset.y());
926 size_t ResourceProvider::NumBlockingUploads() {
927 if (!texture_uploader_)
930 return texture_uploader_->NumBlockingUploads();
933 void ResourceProvider::MarkPendingUploadsAsNonBlocking() {
934 if (!texture_uploader_)
937 texture_uploader_->MarkPendingUploadsAsNonBlocking();
940 size_t ResourceProvider::EstimatedUploadsPerTick() {
941 if (!texture_uploader_)
944 double textures_per_second = texture_uploader_->EstimatedTexturesPerSecond();
945 size_t textures_per_tick = floor(
946 kTextureUploadTickRate * textures_per_second);
947 return textures_per_tick ? textures_per_tick : 1u;
950 void ResourceProvider::FlushUploads() {
951 if (!texture_uploader_)
954 texture_uploader_->Flush();
957 void ResourceProvider::ReleaseCachedData() {
958 if (!texture_uploader_)
961 texture_uploader_->ReleaseCachedQueries();
964 base::TimeTicks ResourceProvider::EstimatedUploadCompletionTime(
965 size_t uploads_per_tick) {
966 if (lost_output_surface_)
967 return base::TimeTicks();
969 // Software resource uploads happen on impl thread, so don't bother batching
970 // them up and trying to wait for them to complete.
971 if (!texture_uploader_) {
972 return gfx::FrameTime::Now() + base::TimeDelta::FromMicroseconds(
973 base::Time::kMicrosecondsPerSecond * kSoftwareUploadTickRate);
976 base::TimeDelta upload_one_texture_time =
977 base::TimeDelta::FromMicroseconds(
978 base::Time::kMicrosecondsPerSecond * kTextureUploadTickRate) /
981 size_t total_uploads = NumBlockingUploads() + uploads_per_tick;
982 return gfx::FrameTime::Now() + upload_one_texture_time * total_uploads;
985 void ResourceProvider::Flush() {
986 DCHECK(thread_checker_.CalledOnValidThread());
987 GLES2Interface* gl = ContextGL();
992 void ResourceProvider::Finish() {
993 DCHECK(thread_checker_.CalledOnValidThread());
994 GLES2Interface* gl = ContextGL();
999 bool ResourceProvider::ShallowFlushIfSupported() {
1000 DCHECK(thread_checker_.CalledOnValidThread());
1001 GLES2Interface* gl = ContextGL();
1005 gl->ShallowFlushCHROMIUM();
1009 ResourceProvider::Resource* ResourceProvider::GetResource(ResourceId id) {
1010 DCHECK(thread_checker_.CalledOnValidThread());
1011 ResourceMap::iterator it = resources_.find(id);
1012 CHECK(it != resources_.end());
1016 const ResourceProvider::Resource* ResourceProvider::LockForRead(ResourceId id) {
1017 Resource* resource = GetResource(id);
1018 DCHECK(!resource->locked_for_write ||
1019 resource->set_pixels_completion_forced) <<
1020 "locked for write: " << resource->locked_for_write <<
1021 " pixels completion forced: " << resource->set_pixels_completion_forced;
1022 DCHECK_EQ(resource->exported_count, 0);
1023 // Uninitialized! Call SetPixels or LockForWrite first.
1024 DCHECK(resource->allocated);
1026 LazyCreate(resource);
1028 if (resource->type == GLTexture && !resource->gl_id) {
1029 DCHECK(resource->origin != Resource::Internal);
1030 DCHECK(resource->mailbox.IsTexture());
1031 GLES2Interface* gl = ContextGL();
1033 if (resource->mailbox.sync_point()) {
1034 GLC(gl, gl->WaitSyncPointCHROMIUM(resource->mailbox.sync_point()));
1035 resource->mailbox.set_sync_point(0);
1037 resource->gl_id = texture_id_allocator_->NextId();
1038 GLC(gl, gl->BindTexture(resource->target, resource->gl_id));
1040 gl->ConsumeTextureCHROMIUM(resource->mailbox.target(),
1041 resource->mailbox.name()));
1044 if (!resource->pixels && resource->has_shared_bitmap_id &&
1045 shared_bitmap_manager_) {
1046 scoped_ptr<SharedBitmap> bitmap =
1047 shared_bitmap_manager_->GetSharedBitmapFromId(
1048 resource->size, resource->shared_bitmap_id);
1050 resource->shared_bitmap = bitmap.release();
1051 resource->pixels = resource->shared_bitmap->pixels();
1055 resource->lock_for_read_count++;
1056 if (resource->enable_read_lock_fences)
1057 resource->read_lock_fence = current_read_lock_fence_;
1062 void ResourceProvider::UnlockForRead(ResourceId id) {
1063 Resource* resource = GetResource(id);
1064 DCHECK_GT(resource->lock_for_read_count, 0);
1065 DCHECK_EQ(resource->exported_count, 0);
1066 resource->lock_for_read_count--;
1069 const ResourceProvider::Resource* ResourceProvider::LockForWrite(
1071 Resource* resource = GetResource(id);
1072 DCHECK(!resource->locked_for_write);
1073 DCHECK(!resource->lock_for_read_count);
1074 DCHECK_EQ(resource->exported_count, 0);
1075 DCHECK(resource->origin == Resource::Internal);
1076 DCHECK(!resource->lost);
1077 DCHECK(ReadLockFenceHasPassed(resource));
1078 LazyAllocate(resource);
1080 resource->locked_for_write = true;
1084 bool ResourceProvider::CanLockForWrite(ResourceId id) {
1085 Resource* resource = GetResource(id);
1086 return !resource->locked_for_write && !resource->lock_for_read_count &&
1087 !resource->exported_count && resource->origin == Resource::Internal &&
1088 !resource->lost && ReadLockFenceHasPassed(resource);
1091 void ResourceProvider::UnlockForWrite(ResourceId id) {
1092 Resource* resource = GetResource(id);
1093 DCHECK(resource->locked_for_write);
1094 DCHECK_EQ(resource->exported_count, 0);
1095 DCHECK(resource->origin == Resource::Internal);
1096 resource->locked_for_write = false;
1099 ResourceProvider::ScopedReadLockGL::ScopedReadLockGL(
1100 ResourceProvider* resource_provider,
1101 ResourceProvider::ResourceId resource_id)
1102 : resource_provider_(resource_provider),
1103 resource_id_(resource_id),
1104 texture_id_(resource_provider->LockForRead(resource_id)->gl_id) {
1105 DCHECK(texture_id_);
1108 ResourceProvider::ScopedReadLockGL::~ScopedReadLockGL() {
1109 resource_provider_->UnlockForRead(resource_id_);
1112 ResourceProvider::ScopedSamplerGL::ScopedSamplerGL(
1113 ResourceProvider* resource_provider,
1114 ResourceProvider::ResourceId resource_id,
1116 : ScopedReadLockGL(resource_provider, resource_id),
1118 target_(resource_provider->BindForSampling(resource_id, unit_, filter)) {
1121 ResourceProvider::ScopedSamplerGL::ScopedSamplerGL(
1122 ResourceProvider* resource_provider,
1123 ResourceProvider::ResourceId resource_id,
1126 : ScopedReadLockGL(resource_provider, resource_id),
1128 target_(resource_provider->BindForSampling(resource_id, unit_, filter)) {
1131 ResourceProvider::ScopedSamplerGL::~ScopedSamplerGL() {
1134 ResourceProvider::ScopedWriteLockGL::ScopedWriteLockGL(
1135 ResourceProvider* resource_provider,
1136 ResourceProvider::ResourceId resource_id)
1137 : resource_provider_(resource_provider),
1138 resource_id_(resource_id),
1139 texture_id_(resource_provider->LockForWrite(resource_id)->gl_id) {
1140 DCHECK(texture_id_);
1143 ResourceProvider::ScopedWriteLockGL::~ScopedWriteLockGL() {
1144 resource_provider_->UnlockForWrite(resource_id_);
1147 void ResourceProvider::PopulateSkBitmapWithResource(
1148 SkBitmap* sk_bitmap, const Resource* resource) {
1149 DCHECK_EQ(RGBA_8888, resource->format);
1150 sk_bitmap->setConfig(SkBitmap::kARGB_8888_Config,
1151 resource->size.width(),
1152 resource->size.height());
1153 sk_bitmap->setPixels(resource->pixels);
1156 ResourceProvider::ScopedReadLockSoftware::ScopedReadLockSoftware(
1157 ResourceProvider* resource_provider,
1158 ResourceProvider::ResourceId resource_id)
1159 : resource_provider_(resource_provider),
1160 resource_id_(resource_id) {
1161 const Resource* resource = resource_provider->LockForRead(resource_id);
1162 wrap_mode_ = resource->wrap_mode;
1163 ResourceProvider::PopulateSkBitmapWithResource(&sk_bitmap_, resource);
1166 ResourceProvider::ScopedReadLockSoftware::~ScopedReadLockSoftware() {
1167 resource_provider_->UnlockForRead(resource_id_);
1170 ResourceProvider::ScopedWriteLockSoftware::ScopedWriteLockSoftware(
1171 ResourceProvider* resource_provider,
1172 ResourceProvider::ResourceId resource_id)
1173 : resource_provider_(resource_provider),
1174 resource_id_(resource_id) {
1175 ResourceProvider::PopulateSkBitmapWithResource(
1176 &sk_bitmap_, resource_provider->LockForWrite(resource_id));
1178 sk_canvas_.reset(new SkCanvas(sk_bitmap_));
1181 ResourceProvider::ScopedWriteLockSoftware::~ScopedWriteLockSoftware() {
1182 resource_provider_->UnlockForWrite(resource_id_);
1185 ResourceProvider::ResourceProvider(OutputSurface* output_surface,
1186 SharedBitmapManager* shared_bitmap_manager,
1187 int highp_threshold_min,
1188 bool use_rgba_4444_texture_format,
1189 size_t id_allocation_chunk_size)
1190 : output_surface_(output_surface),
1191 shared_bitmap_manager_(shared_bitmap_manager),
1192 lost_output_surface_(false),
1193 highp_threshold_min_(highp_threshold_min),
1196 default_resource_type_(InvalidType),
1197 use_texture_storage_ext_(false),
1198 use_texture_usage_hint_(false),
1199 use_compressed_texture_etc1_(false),
1200 max_texture_size_(0),
1201 best_texture_format_(RGBA_8888),
1202 use_rgba_4444_texture_format_(use_rgba_4444_texture_format),
1203 id_allocation_chunk_size_(id_allocation_chunk_size) {
1204 DCHECK(output_surface_->HasClient());
1205 DCHECK(id_allocation_chunk_size_);
1208 void ResourceProvider::InitializeSoftware() {
1209 DCHECK(thread_checker_.CalledOnValidThread());
1210 DCHECK_NE(Bitmap, default_resource_type_);
1212 CleanUpGLIfNeeded();
1214 default_resource_type_ = Bitmap;
1215 // Pick an arbitrary limit here similar to what hardware might.
1216 max_texture_size_ = 16 * 1024;
1217 best_texture_format_ = RGBA_8888;
1220 bool ResourceProvider::InitializeGL() {
1221 DCHECK(thread_checker_.CalledOnValidThread());
1222 DCHECK(!texture_uploader_);
1223 DCHECK_NE(GLTexture, default_resource_type_);
1224 DCHECK(!texture_id_allocator_);
1225 DCHECK(!buffer_id_allocator_);
1227 default_resource_type_ = GLTexture;
1229 const ContextProvider::Capabilities& caps =
1230 output_surface_->context_provider()->ContextCapabilities();
1232 bool use_bgra = caps.gpu.texture_format_bgra8888;
1233 use_texture_storage_ext_ = caps.gpu.texture_storage;
1234 use_texture_usage_hint_ = caps.gpu.texture_usage;
1235 use_compressed_texture_etc1_ = caps.gpu.texture_format_etc1;
1237 GLES2Interface* gl = ContextGL();
1240 texture_uploader_ = TextureUploader::Create(gl);
1241 max_texture_size_ = 0; // Context expects cleared value.
1242 GLC(gl, gl->GetIntegerv(GL_MAX_TEXTURE_SIZE, &max_texture_size_));
1243 best_texture_format_ = PlatformColor::BestTextureFormat(use_bgra);
1245 texture_id_allocator_.reset(
1246 new TextureIdAllocator(gl, id_allocation_chunk_size_));
1247 buffer_id_allocator_.reset(
1248 new BufferIdAllocator(gl, id_allocation_chunk_size_));
1253 void ResourceProvider::CleanUpGLIfNeeded() {
1254 GLES2Interface* gl = ContextGL();
1255 if (default_resource_type_ != GLTexture) {
1256 // We are not in GL mode, but double check before returning.
1258 DCHECK(!texture_uploader_);
1263 texture_uploader_.reset();
1264 texture_id_allocator_.reset();
1265 buffer_id_allocator_.reset();
1269 int ResourceProvider::CreateChild(const ReturnCallback& return_callback) {
1270 DCHECK(thread_checker_.CalledOnValidThread());
1273 child_info.return_callback = return_callback;
1275 int child = next_child_++;
1276 children_[child] = child_info;
1280 void ResourceProvider::DestroyChild(int child_id) {
1281 ChildMap::iterator it = children_.find(child_id);
1282 DCHECK(it != children_.end());
1283 DestroyChildInternal(it, Normal);
1286 void ResourceProvider::DestroyChildInternal(ChildMap::iterator it,
1287 DeleteStyle style) {
1288 DCHECK(thread_checker_.CalledOnValidThread());
1290 Child& child = it->second;
1291 DCHECK(style == ForShutdown || !child.marked_for_deletion);
1293 ResourceIdArray resources_for_child;
1295 for (ResourceIdMap::iterator child_it = child.child_to_parent_map.begin();
1296 child_it != child.child_to_parent_map.end();
1298 ResourceId id = child_it->second;
1299 resources_for_child.push_back(id);
1302 // If the child is going away, don't consider any resources in use.
1303 child.in_use_resources.clear();
1304 child.marked_for_deletion = true;
1306 DeleteAndReturnUnusedResourcesToChild(it, style, resources_for_child);
1309 const ResourceProvider::ResourceIdMap& ResourceProvider::GetChildToParentMap(
1311 DCHECK(thread_checker_.CalledOnValidThread());
1312 ChildMap::const_iterator it = children_.find(child);
1313 DCHECK(it != children_.end());
1314 DCHECK(!it->second.marked_for_deletion);
1315 return it->second.child_to_parent_map;
1318 void ResourceProvider::PrepareSendToParent(const ResourceIdArray& resources,
1319 TransferableResourceArray* list) {
1320 DCHECK(thread_checker_.CalledOnValidThread());
1321 GLES2Interface* gl = ContextGL();
1322 bool need_sync_point = false;
1323 for (ResourceIdArray::const_iterator it = resources.begin();
1324 it != resources.end();
1326 TransferableResource resource;
1327 TransferResource(gl, *it, &resource);
1328 if (!resource.mailbox_holder.sync_point && !resource.is_software)
1329 need_sync_point = true;
1330 ++resources_.find(*it)->second.exported_count;
1331 list->push_back(resource);
1333 if (need_sync_point) {
1334 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 = resources_[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);
1371 ResourceId local_id = next_id_++;
1372 Resource& resource = resources_[local_id];
1373 if (it->is_software) {
1374 resource = Resource(it->mailbox_holder.mailbox,
1376 Resource::Delegated,
1380 resource = Resource(0,
1382 Resource::Delegated,
1383 it->mailbox_holder.texture_target,
1389 resource.mailbox = TextureMailbox(it->mailbox_holder.mailbox,
1390 it->mailbox_holder.texture_target,
1391 it->mailbox_holder.sync_point);
1393 resource.child_id = child;
1394 // Don't allocate a texture for a child.
1395 resource.allocated = true;
1396 resource.imported_count = 1;
1397 child_info.parent_to_child_map[local_id] = it->id;
1398 child_info.child_to_parent_map[it->id] = local_id;
1402 void ResourceProvider::DeclareUsedResourcesFromChild(
1404 const ResourceIdArray& resources_from_child) {
1405 DCHECK(thread_checker_.CalledOnValidThread());
1407 ChildMap::iterator child_it = children_.find(child);
1408 DCHECK(child_it != children_.end());
1409 Child& child_info = child_it->second;
1410 DCHECK(!child_info.marked_for_deletion);
1411 child_info.in_use_resources.clear();
1413 for (size_t i = 0; i < resources_from_child.size(); ++i) {
1414 ResourceIdMap::iterator it =
1415 child_info.child_to_parent_map.find(resources_from_child[i]);
1416 DCHECK(it != child_info.child_to_parent_map.end());
1418 ResourceId local_id = it->second;
1419 DCHECK(!resources_[local_id].marked_for_deletion);
1420 child_info.in_use_resources.insert(local_id);
1423 ResourceIdArray unused;
1424 for (ResourceIdMap::iterator it = child_info.child_to_parent_map.begin();
1425 it != child_info.child_to_parent_map.end();
1427 ResourceId local_id = it->second;
1428 bool resource_is_in_use = child_info.in_use_resources.count(local_id) > 0;
1429 if (!resource_is_in_use)
1430 unused.push_back(local_id);
1432 DeleteAndReturnUnusedResourcesToChild(child_it, Normal, unused);
1436 bool ResourceProvider::CompareResourceMapIteratorsByChildId(
1437 const std::pair<ReturnedResource, ResourceMap::iterator>& a,
1438 const std::pair<ReturnedResource, ResourceMap::iterator>& b) {
1439 const ResourceMap::iterator& a_it = a.second;
1440 const ResourceMap::iterator& b_it = b.second;
1441 const Resource& a_resource = a_it->second;
1442 const Resource& b_resource = b_it->second;
1443 return a_resource.child_id < b_resource.child_id;
1446 void ResourceProvider::ReceiveReturnsFromParent(
1447 const ReturnedResourceArray& resources) {
1448 DCHECK(thread_checker_.CalledOnValidThread());
1449 GLES2Interface* gl = ContextGL();
1452 ResourceIdArray resources_for_child;
1454 std::vector<std::pair<ReturnedResource, ResourceMap::iterator> >
1457 for (ReturnedResourceArray::const_iterator it = resources.begin();
1458 it != resources.end();
1460 ResourceId local_id = it->id;
1461 ResourceMap::iterator map_iterator = resources_.find(local_id);
1463 // Resource was already lost (e.g. it belonged to a child that was
1465 if (map_iterator == resources_.end())
1468 sorted_resources.push_back(
1469 std::pair<ReturnedResource, ResourceMap::iterator>(*it, map_iterator));
1472 std::sort(sorted_resources.begin(),
1473 sorted_resources.end(),
1474 CompareResourceMapIteratorsByChildId);
1476 ChildMap::iterator child_it = children_.end();
1477 for (size_t i = 0; i < sorted_resources.size(); ++i) {
1478 ReturnedResource& returned = sorted_resources[i].first;
1479 ResourceMap::iterator& map_iterator = sorted_resources[i].second;
1480 ResourceId local_id = map_iterator->first;
1481 Resource* resource = &map_iterator->second;
1483 CHECK_GE(resource->exported_count, returned.count);
1484 resource->exported_count -= returned.count;
1485 resource->lost |= returned.lost;
1486 if (resource->exported_count)
1489 // Need to wait for the current read lock fence to pass before we can
1490 // recycle this resource.
1491 if (resource->enable_read_lock_fences)
1492 resource->read_lock_fence = current_read_lock_fence_;
1494 if (returned.sync_point) {
1495 DCHECK(!resource->has_shared_bitmap_id);
1496 if (resource->origin == Resource::Internal) {
1497 DCHECK(resource->gl_id);
1498 GLC(gl, gl->WaitSyncPointCHROMIUM(returned.sync_point));
1500 // Because CreateResourceFromExternalTexture() never be called,
1501 // when enabling delegated compositor.
1502 DCHECK(!resource->gl_id);
1503 resource->mailbox.set_sync_point(returned.sync_point);
1507 if (!resource->marked_for_deletion)
1510 if (!resource->child_id) {
1511 // The resource belongs to this ResourceProvider, so it can be destroyed.
1512 DeleteResourceInternal(map_iterator, Normal);
1516 DCHECK(resource->origin == Resource::Delegated);
1517 // Delete the resource and return it to the child it came from one.
1518 if (resource->child_id != child_id) {
1520 DCHECK_NE(resources_for_child.size(), 0u);
1521 DCHECK(child_it != children_.end());
1522 DeleteAndReturnUnusedResourcesToChild(
1523 child_it, Normal, resources_for_child);
1524 resources_for_child.clear();
1527 child_it = children_.find(resource->child_id);
1528 DCHECK(child_it != children_.end());
1529 child_id = resource->child_id;
1531 resources_for_child.push_back(local_id);
1535 DCHECK_NE(resources_for_child.size(), 0u);
1536 DCHECK(child_it != children_.end());
1537 DeleteAndReturnUnusedResourcesToChild(
1538 child_it, Normal, resources_for_child);
1542 void ResourceProvider::TransferResource(GLES2Interface* gl,
1544 TransferableResource* resource) {
1545 Resource* source = GetResource(id);
1546 DCHECK(!source->locked_for_write);
1547 DCHECK(!source->lock_for_read_count);
1548 // Because CreateResourceFromExternalTexture() never be called,
1549 // when enabling delegated compositor.
1550 DCHECK(source->origin == Resource::Internal ||
1551 source->origin == Resource::Delegated ||
1552 (source->origin == Resource::External && source->mailbox.IsValid()));
1553 DCHECK(source->allocated);
1554 DCHECK_EQ(source->wrap_mode, GL_CLAMP_TO_EDGE);
1556 resource->format = source->format;
1557 resource->mailbox_holder.texture_target = source->target;
1558 resource->filter = source->filter;
1559 resource->size = source->size;
1561 if (source->type == Bitmap) {
1562 resource->mailbox_holder.mailbox = source->shared_bitmap_id;
1563 resource->is_software = true;
1564 } else if (!source->mailbox.IsValid()) {
1566 DCHECK(source->gl_id);
1567 DCHECK(source->origin == Resource::Internal);
1569 gl->BindTexture(resource->mailbox_holder.texture_target,
1571 if (source->image_id) {
1572 DCHECK(source->dirty_image);
1573 BindImageForSampling(source);
1575 // This is a resource allocated by the compositor, we need to produce it.
1576 // Don't set a sync point, the caller will do it.
1577 GLC(gl, gl->GenMailboxCHROMIUM(resource->mailbox_holder.mailbox.name));
1579 gl->ProduceTextureCHROMIUM(resource->mailbox_holder.texture_target,
1580 resource->mailbox_holder.mailbox.name));
1581 source->mailbox = TextureMailbox(resource->mailbox_holder);
1583 DCHECK(source->mailbox.IsTexture());
1584 if (source->image_id && source->dirty_image) {
1585 DCHECK(source->gl_id);
1586 DCHECK(source->origin == Resource::Internal);
1588 gl->BindTexture(resource->mailbox_holder.texture_target,
1590 BindImageForSampling(source);
1592 // This is either an external resource, or a compositor resource that we
1593 // already exported. Make sure to forward the sync point that we were given.
1594 resource->mailbox_holder.mailbox = source->mailbox.mailbox();
1595 resource->mailbox_holder.texture_target = source->mailbox.target();
1596 resource->mailbox_holder.sync_point = source->mailbox.sync_point();
1597 source->mailbox.set_sync_point(0);
1601 void ResourceProvider::DeleteAndReturnUnusedResourcesToChild(
1602 ChildMap::iterator child_it,
1604 const ResourceIdArray& unused) {
1605 DCHECK(thread_checker_.CalledOnValidThread());
1606 DCHECK(child_it != children_.end());
1607 Child* child_info = &child_it->second;
1609 if (unused.empty() && !child_info->marked_for_deletion)
1612 ReturnedResourceArray to_return;
1614 GLES2Interface* gl = ContextGL();
1615 bool need_sync_point = false;
1616 for (size_t i = 0; i < unused.size(); ++i) {
1617 ResourceId local_id = unused[i];
1619 ResourceMap::iterator it = resources_.find(local_id);
1620 CHECK(it != resources_.end());
1621 Resource& resource = it->second;
1623 DCHECK(!resource.locked_for_write);
1624 DCHECK(!resource.lock_for_read_count);
1625 DCHECK_EQ(0u, child_info->in_use_resources.count(local_id));
1626 DCHECK(child_info->parent_to_child_map.count(local_id));
1628 ResourceId child_id = child_info->parent_to_child_map[local_id];
1629 DCHECK(child_info->child_to_parent_map.count(child_id));
1632 resource.lost || (resource.type == GLTexture && lost_output_surface_);
1633 if (resource.exported_count > 0) {
1634 if (style != ForShutdown) {
1635 // Defer this until we receive the resource back from the parent.
1636 resource.marked_for_deletion = true;
1640 // We still have an exported_count, so we'll have to lose it.
1644 if (gl && resource.filter != resource.original_filter) {
1645 DCHECK(resource.target);
1646 DCHECK(resource.gl_id);
1648 GLC(gl, gl->BindTexture(resource.target, resource.gl_id));
1650 gl->TexParameteri(resource.target,
1651 GL_TEXTURE_MIN_FILTER,
1652 resource.original_filter));
1654 gl->TexParameteri(resource.target,
1655 GL_TEXTURE_MAG_FILTER,
1656 resource.original_filter));
1659 ReturnedResource returned;
1660 returned.id = child_id;
1661 returned.sync_point = resource.mailbox.sync_point();
1662 if (!returned.sync_point && resource.type == GLTexture)
1663 need_sync_point = true;
1664 returned.count = resource.imported_count;
1665 returned.lost = is_lost;
1666 to_return.push_back(returned);
1668 child_info->parent_to_child_map.erase(local_id);
1669 child_info->child_to_parent_map.erase(child_id);
1670 resource.imported_count = 0;
1671 DeleteResourceInternal(it, style);
1673 if (need_sync_point) {
1675 GLuint sync_point = gl->InsertSyncPointCHROMIUM();
1676 for (size_t i = 0; i < to_return.size(); ++i) {
1677 if (!to_return[i].sync_point)
1678 to_return[i].sync_point = sync_point;
1682 if (!to_return.empty())
1683 child_info->return_callback.Run(to_return);
1685 if (child_info->marked_for_deletion &&
1686 child_info->parent_to_child_map.empty()) {
1687 DCHECK(child_info->child_to_parent_map.empty());
1688 children_.erase(child_it);
1692 SkCanvas* ResourceProvider::MapDirectRasterBuffer(ResourceId id) {
1693 // Resource needs to be locked for write since DirectRasterBuffer writes
1696 Resource* resource = GetResource(id);
1697 if (!resource->direct_raster_buffer.get()) {
1698 resource->direct_raster_buffer.reset(
1699 new DirectRasterBuffer(resource, this));
1701 return resource->direct_raster_buffer->LockForWrite();
1704 void ResourceProvider::UnmapDirectRasterBuffer(ResourceId id) {
1705 Resource* resource = GetResource(id);
1706 DCHECK(resource->direct_raster_buffer.get());
1707 resource->direct_raster_buffer->UnlockForWrite();
1711 SkCanvas* ResourceProvider::MapImageRasterBuffer(ResourceId id) {
1712 Resource* resource = GetResource(id);
1713 AcquireImage(resource);
1714 if (!resource->image_raster_buffer.get())
1715 resource->image_raster_buffer.reset(new ImageRasterBuffer(resource, this));
1716 return resource->image_raster_buffer->LockForWrite();
1719 void ResourceProvider::UnmapImageRasterBuffer(ResourceId id) {
1720 Resource* resource = GetResource(id);
1721 resource->image_raster_buffer->UnlockForWrite();
1722 resource->dirty_image = true;
1725 void ResourceProvider::AcquirePixelRasterBuffer(ResourceId id) {
1726 Resource* resource = GetResource(id);
1727 AcquirePixelBuffer(resource);
1728 resource->pixel_raster_buffer.reset(new PixelRasterBuffer(resource, this));
1731 void ResourceProvider::ReleasePixelRasterBuffer(ResourceId id) {
1732 Resource* resource = GetResource(id);
1733 resource->pixel_raster_buffer.reset();
1734 ReleasePixelBuffer(resource);
1737 SkCanvas* ResourceProvider::MapPixelRasterBuffer(ResourceId id) {
1738 Resource* resource = GetResource(id);
1739 DCHECK(resource->pixel_raster_buffer.get());
1740 return resource->pixel_raster_buffer->LockForWrite();
1743 void ResourceProvider::UnmapPixelRasterBuffer(ResourceId id) {
1744 Resource* resource = GetResource(id);
1745 DCHECK(resource->pixel_raster_buffer.get());
1746 resource->pixel_raster_buffer->UnlockForWrite();
1749 void ResourceProvider::AcquirePixelBuffer(Resource* resource) {
1750 DCHECK(resource->origin == Resource::Internal);
1751 DCHECK_EQ(resource->exported_count, 0);
1752 DCHECK(!resource->image_id);
1753 DCHECK_NE(ETC1, resource->format);
1755 if (resource->type == GLTexture) {
1756 GLES2Interface* gl = ContextGL();
1758 if (!resource->gl_pixel_buffer_id)
1759 resource->gl_pixel_buffer_id = buffer_id_allocator_->NextId();
1760 gl->BindBuffer(GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM,
1761 resource->gl_pixel_buffer_id);
1762 unsigned bytes_per_pixel = BitsPerPixel(resource->format) / 8;
1763 gl->BufferData(GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM,
1764 resource->size.height() *
1765 RoundUp(bytes_per_pixel * resource->size.width(), 4u),
1768 gl->BindBuffer(GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM, 0);
1770 DCHECK_EQ(Bitmap, resource->type);
1771 if (resource->pixel_buffer)
1774 resource->pixel_buffer = new uint8_t[4 * resource->size.GetArea()];
1778 void ResourceProvider::ReleasePixelBuffer(Resource* resource) {
1779 DCHECK(resource->origin == Resource::Internal);
1780 DCHECK_EQ(resource->exported_count, 0);
1781 DCHECK(!resource->image_id);
1783 // The pixel buffer can be released while there is a pending "set pixels"
1784 // if completion has been forced. Any shared memory associated with this
1785 // pixel buffer will not be freed until the waitAsyncTexImage2DCHROMIUM
1786 // command has been processed on the service side. It is also safe to
1787 // reuse any query id associated with this resource before they complete
1788 // as each new query has a unique submit count.
1789 if (resource->pending_set_pixels) {
1790 DCHECK(resource->set_pixels_completion_forced);
1791 resource->pending_set_pixels = false;
1792 resource->locked_for_write = false;
1795 if (resource->type == GLTexture) {
1796 if (!resource->gl_pixel_buffer_id)
1798 GLES2Interface* gl = ContextGL();
1800 gl->BindBuffer(GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM,
1801 resource->gl_pixel_buffer_id);
1803 GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM, 0, NULL, GL_DYNAMIC_DRAW);
1804 gl->BindBuffer(GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM, 0);
1806 DCHECK_EQ(Bitmap, resource->type);
1807 if (!resource->pixel_buffer)
1809 delete[] resource->pixel_buffer;
1810 resource->pixel_buffer = NULL;
1814 uint8_t* ResourceProvider::MapPixelBuffer(const Resource* resource,
1816 DCHECK(resource->origin == Resource::Internal);
1817 DCHECK_EQ(resource->exported_count, 0);
1818 DCHECK(!resource->image_id);
1821 if (resource->type == GLTexture) {
1822 GLES2Interface* gl = ContextGL();
1824 DCHECK(resource->gl_pixel_buffer_id);
1825 gl->BindBuffer(GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM,
1826 resource->gl_pixel_buffer_id);
1827 uint8_t* image = static_cast<uint8_t*>(gl->MapBufferCHROMIUM(
1828 GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM, GL_WRITE_ONLY));
1829 gl->BindBuffer(GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM, 0);
1830 // Buffer is required to be 4-byte aligned.
1831 CHECK(!(reinterpret_cast<intptr_t>(image) & 3));
1834 DCHECK_EQ(Bitmap, resource->type);
1835 return resource->pixel_buffer;
1838 void ResourceProvider::UnmapPixelBuffer(const Resource* resource) {
1839 DCHECK(resource->origin == Resource::Internal);
1840 DCHECK_EQ(resource->exported_count, 0);
1841 DCHECK(!resource->image_id);
1843 if (resource->type == GLTexture) {
1844 GLES2Interface* gl = ContextGL();
1846 DCHECK(resource->gl_pixel_buffer_id);
1847 gl->BindBuffer(GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM,
1848 resource->gl_pixel_buffer_id);
1849 gl->UnmapBufferCHROMIUM(GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM);
1850 gl->BindBuffer(GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM, 0);
1854 GLenum ResourceProvider::BindForSampling(
1855 ResourceProvider::ResourceId resource_id,
1858 DCHECK(thread_checker_.CalledOnValidThread());
1859 GLES2Interface* gl = ContextGL();
1860 ResourceMap::iterator it = resources_.find(resource_id);
1861 DCHECK(it != resources_.end());
1862 Resource* resource = &it->second;
1863 DCHECK(resource->lock_for_read_count);
1864 DCHECK(!resource->locked_for_write || resource->set_pixels_completion_forced);
1866 ScopedSetActiveTexture scoped_active_tex(gl, unit);
1867 GLenum target = resource->target;
1868 GLC(gl, gl->BindTexture(target, resource->gl_id));
1869 if (filter != resource->filter) {
1870 GLC(gl, gl->TexParameteri(target, GL_TEXTURE_MIN_FILTER, filter));
1871 GLC(gl, gl->TexParameteri(target, GL_TEXTURE_MAG_FILTER, filter));
1872 resource->filter = filter;
1875 if (resource->image_id && resource->dirty_image)
1876 BindImageForSampling(resource);
1881 void ResourceProvider::BeginSetPixels(ResourceId id) {
1882 Resource* resource = GetResource(id);
1883 DCHECK(!resource->pending_set_pixels);
1885 LazyCreate(resource);
1886 DCHECK(resource->origin == Resource::Internal);
1887 DCHECK(resource->gl_id || resource->allocated);
1888 DCHECK(ReadLockFenceHasPassed(resource));
1889 DCHECK(!resource->image_id);
1891 bool allocate = !resource->allocated;
1892 resource->allocated = true;
1895 if (resource->type == GLTexture) {
1896 DCHECK(resource->gl_id);
1897 GLES2Interface* gl = ContextGL();
1899 DCHECK(resource->gl_pixel_buffer_id);
1900 DCHECK_EQ(resource->target, static_cast<GLenum>(GL_TEXTURE_2D));
1901 gl->BindTexture(GL_TEXTURE_2D, resource->gl_id);
1902 gl->BindBuffer(GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM,
1903 resource->gl_pixel_buffer_id);
1904 if (!resource->gl_upload_query_id)
1905 gl->GenQueriesEXT(1, &resource->gl_upload_query_id);
1906 gl->BeginQueryEXT(GL_ASYNC_PIXEL_UNPACK_COMPLETED_CHROMIUM,
1907 resource->gl_upload_query_id);
1909 gl->AsyncTexImage2DCHROMIUM(GL_TEXTURE_2D,
1911 GLInternalFormat(resource->format),
1912 resource->size.width(),
1913 resource->size.height(),
1915 GLDataFormat(resource->format),
1916 GLDataType(resource->format),
1919 gl->AsyncTexSubImage2DCHROMIUM(GL_TEXTURE_2D,
1923 resource->size.width(),
1924 resource->size.height(),
1925 GLDataFormat(resource->format),
1926 GLDataType(resource->format),
1929 gl->EndQueryEXT(GL_ASYNC_PIXEL_UNPACK_COMPLETED_CHROMIUM);
1930 gl->BindBuffer(GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM, 0);
1932 DCHECK_EQ(Bitmap, resource->type);
1933 DCHECK(!resource->mailbox.IsValid());
1934 DCHECK(resource->pixel_buffer);
1935 DCHECK_EQ(RGBA_8888, resource->format);
1937 std::swap(resource->pixels, resource->pixel_buffer);
1938 delete[] resource->pixel_buffer;
1939 resource->pixel_buffer = NULL;
1942 resource->pending_set_pixels = true;
1943 resource->set_pixels_completion_forced = false;
1946 void ResourceProvider::ForceSetPixelsToComplete(ResourceId id) {
1947 Resource* resource = GetResource(id);
1948 DCHECK(resource->locked_for_write);
1949 DCHECK(resource->pending_set_pixels);
1950 DCHECK(!resource->set_pixels_completion_forced);
1952 if (resource->gl_id) {
1953 GLES2Interface* gl = ContextGL();
1954 GLC(gl, gl->BindTexture(GL_TEXTURE_2D, resource->gl_id));
1955 GLC(gl, gl->WaitAsyncTexImage2DCHROMIUM(GL_TEXTURE_2D));
1956 GLC(gl, gl->BindTexture(GL_TEXTURE_2D, 0));
1959 resource->set_pixels_completion_forced = true;
1962 bool ResourceProvider::DidSetPixelsComplete(ResourceId id) {
1963 Resource* resource = GetResource(id);
1964 DCHECK(resource->locked_for_write);
1965 DCHECK(resource->pending_set_pixels);
1967 if (resource->gl_id) {
1968 GLES2Interface* gl = ContextGL();
1970 DCHECK(resource->gl_upload_query_id);
1971 GLuint complete = 1;
1972 gl->GetQueryObjectuivEXT(
1973 resource->gl_upload_query_id, GL_QUERY_RESULT_AVAILABLE_EXT, &complete);
1978 resource->pending_set_pixels = false;
1984 void ResourceProvider::CreateForTesting(ResourceId id) {
1985 LazyCreate(GetResource(id));
1988 GLenum ResourceProvider::TargetForTesting(ResourceId id) {
1989 Resource* resource = GetResource(id);
1990 return resource->target;
1993 void ResourceProvider::LazyCreate(Resource* resource) {
1994 if (resource->type != GLTexture || resource->origin != Resource::Internal)
1997 if (resource->gl_id)
2000 DCHECK(resource->texture_pool);
2001 DCHECK(resource->origin == Resource::Internal);
2002 DCHECK(!resource->mailbox.IsValid());
2003 resource->gl_id = texture_id_allocator_->NextId();
2005 GLES2Interface* gl = ContextGL();
2008 // Create and set texture properties. Allocation is delayed until needed.
2009 GLC(gl, gl->BindTexture(resource->target, resource->gl_id));
2011 gl->TexParameteri(resource->target, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
2013 gl->TexParameteri(resource->target, GL_TEXTURE_MAG_FILTER, GL_LINEAR));
2016 resource->target, GL_TEXTURE_WRAP_S, resource->wrap_mode));
2019 resource->target, GL_TEXTURE_WRAP_T, resource->wrap_mode));
2022 resource->target, GL_TEXTURE_POOL_CHROMIUM, resource->texture_pool));
2023 if (use_texture_usage_hint_ && resource->hint == TextureUsageFramebuffer) {
2025 gl->TexParameteri(resource->target,
2026 GL_TEXTURE_USAGE_ANGLE,
2027 GL_FRAMEBUFFER_ATTACHMENT_ANGLE));
2031 void ResourceProvider::AllocateForTesting(ResourceId id) {
2032 LazyAllocate(GetResource(id));
2035 void ResourceProvider::LazyAllocate(Resource* resource) {
2037 LazyCreate(resource);
2039 DCHECK(resource->gl_id || resource->allocated);
2040 if (resource->allocated || !resource->gl_id)
2042 resource->allocated = true;
2043 GLES2Interface* gl = ContextGL();
2044 gfx::Size& size = resource->size;
2045 DCHECK_EQ(resource->target, static_cast<GLenum>(GL_TEXTURE_2D));
2046 ResourceFormat format = resource->format;
2047 GLC(gl, gl->BindTexture(GL_TEXTURE_2D, resource->gl_id));
2048 if (use_texture_storage_ext_ && IsFormatSupportedForStorage(format) &&
2049 resource->hint != TextureUsageFramebuffer) {
2050 GLenum storage_format = TextureToStorageFormat(format);
2052 gl->TexStorage2DEXT(
2053 GL_TEXTURE_2D, 1, storage_format, size.width(), size.height()));
2055 // ETC1 does not support preallocation.
2056 if (format != ETC1) {
2058 gl->TexImage2D(GL_TEXTURE_2D,
2060 GLInternalFormat(format),
2064 GLDataFormat(format),
2071 void ResourceProvider::BindImageForSampling(Resource* resource) {
2072 GLES2Interface* gl = ContextGL();
2073 DCHECK(resource->gl_id);
2074 DCHECK(resource->image_id);
2076 // Release image currently bound to texture.
2077 if (resource->bound_image_id)
2078 gl->ReleaseTexImage2DCHROMIUM(resource->target, resource->bound_image_id);
2079 gl->BindTexImage2DCHROMIUM(resource->target, resource->image_id);
2080 resource->bound_image_id = resource->image_id;
2081 resource->dirty_image = false;
2084 void ResourceProvider::EnableReadLockFences(ResourceProvider::ResourceId id,
2086 Resource* resource = GetResource(id);
2087 resource->enable_read_lock_fences = enable;
2090 void ResourceProvider::AcquireImage(Resource* resource) {
2091 DCHECK(resource->origin == Resource::Internal);
2092 DCHECK_EQ(resource->exported_count, 0);
2094 if (resource->type != GLTexture)
2097 if (resource->image_id)
2100 resource->allocated = true;
2101 GLES2Interface* gl = ContextGL();
2103 resource->image_id =
2104 gl->CreateImageCHROMIUM(resource->size.width(),
2105 resource->size.height(),
2106 TextureToStorageFormat(resource->format));
2107 DCHECK(resource->image_id);
2110 void ResourceProvider::ReleaseImage(Resource* resource) {
2111 DCHECK(resource->origin == Resource::Internal);
2112 DCHECK_EQ(resource->exported_count, 0);
2114 if (!resource->image_id)
2117 GLES2Interface* gl = ContextGL();
2119 gl->DestroyImageCHROMIUM(resource->image_id);
2120 resource->image_id = 0;
2121 resource->bound_image_id = 0;
2122 resource->dirty_image = false;
2123 resource->allocated = false;
2126 uint8_t* ResourceProvider::MapImage(const Resource* resource, int* stride) {
2127 DCHECK(ReadLockFenceHasPassed(resource));
2128 DCHECK(resource->origin == Resource::Internal);
2129 DCHECK_EQ(resource->exported_count, 0);
2131 if (resource->type == GLTexture) {
2132 DCHECK(resource->image_id);
2133 GLES2Interface* gl = ContextGL();
2135 gl->GetImageParameterivCHROMIUM(
2136 resource->image_id, GL_IMAGE_ROWBYTES_CHROMIUM, stride);
2137 return static_cast<uint8_t*>(
2138 gl->MapImageCHROMIUM(resource->image_id, GL_READ_WRITE));
2140 DCHECK_EQ(Bitmap, resource->type);
2142 return resource->pixels;
2145 void ResourceProvider::UnmapImage(const Resource* resource) {
2146 DCHECK(resource->origin == Resource::Internal);
2147 DCHECK_EQ(resource->exported_count, 0);
2149 if (resource->image_id) {
2150 GLES2Interface* gl = ContextGL();
2152 gl->UnmapImageCHROMIUM(resource->image_id);
2156 GLint ResourceProvider::GetActiveTextureUnit(GLES2Interface* gl) {
2157 GLint active_unit = 0;
2158 gl->GetIntegerv(GL_ACTIVE_TEXTURE, &active_unit);
2162 GLES2Interface* ResourceProvider::ContextGL() const {
2163 ContextProvider* context_provider = output_surface_->context_provider();
2164 return context_provider ? context_provider->ContextGL() : NULL;
2167 class GrContext* ResourceProvider::GrContext() const {
2168 ContextProvider* context_provider = output_surface_->context_provider();
2169 return context_provider ? context_provider->GrContext() : NULL;