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;
81 return storage_format;
84 bool IsFormatSupportedForStorage(ResourceFormat format) {
99 GrPixelConfig ToGrPixelConfig(ResourceFormat format) {
102 return kRGBA_8888_GrPixelConfig;
104 return kBGRA_8888_GrPixelConfig;
106 return kRGBA_4444_GrPixelConfig;
110 DCHECK(false) << "Unsupported resource format.";
111 return kSkia8888_GrPixelConfig;
114 void CopyBitmap(const SkBitmap& src, uint8_t* dst, SkColorType dst_color_type) {
115 SkImageInfo dst_info = src.info();
116 dst_info.fColorType = dst_color_type;
117 // TODO(kaanb): The GL pipeline assumes a 4-byte alignment for the
118 // bitmap data. There will be no need to call SkAlign4 once crbug.com/293728
120 const size_t dst_row_bytes = SkAlign4(dst_info.minRowBytes());
121 CHECK_EQ(0u, dst_row_bytes % 4);
122 bool success = src.readPixels(dst_info, dst, dst_row_bytes, 0, 0);
123 CHECK_EQ(true, success);
126 class ScopedSetActiveTexture {
128 ScopedSetActiveTexture(GLES2Interface* gl, GLenum unit)
129 : gl_(gl), unit_(unit) {
130 DCHECK_EQ(GL_TEXTURE0, ResourceProvider::GetActiveTextureUnit(gl_));
132 if (unit_ != GL_TEXTURE0)
133 GLC(gl_, gl_->ActiveTexture(unit_));
136 ~ScopedSetActiveTexture() {
137 // Active unit being GL_TEXTURE0 is effectively the ground state.
138 if (unit_ != GL_TEXTURE0)
139 GLC(gl_, gl_->ActiveTexture(GL_TEXTURE0));
147 class TextureIdAllocator : public IdAllocator {
149 TextureIdAllocator(GLES2Interface* gl,
150 size_t texture_id_allocation_chunk_size)
151 : IdAllocator(gl, texture_id_allocation_chunk_size) {}
152 virtual ~TextureIdAllocator() {
153 gl_->DeleteTextures(id_allocation_chunk_size_ - next_id_index_,
154 ids_.get() + next_id_index_);
157 // Overridden from IdAllocator:
158 virtual GLuint NextId() OVERRIDE {
159 if (next_id_index_ == id_allocation_chunk_size_) {
160 gl_->GenTextures(id_allocation_chunk_size_, ids_.get());
164 return ids_[next_id_index_++];
168 DISALLOW_COPY_AND_ASSIGN(TextureIdAllocator);
171 class BufferIdAllocator : public IdAllocator {
173 BufferIdAllocator(GLES2Interface* gl, size_t buffer_id_allocation_chunk_size)
174 : IdAllocator(gl, buffer_id_allocation_chunk_size) {}
175 virtual ~BufferIdAllocator() {
176 gl_->DeleteBuffers(id_allocation_chunk_size_ - next_id_index_,
177 ids_.get() + next_id_index_);
180 // Overridden from IdAllocator:
181 virtual GLuint NextId() OVERRIDE {
182 if (next_id_index_ == id_allocation_chunk_size_) {
183 gl_->GenBuffers(id_allocation_chunk_size_, ids_.get());
187 return ids_[next_id_index_++];
191 DISALLOW_COPY_AND_ASSIGN(BufferIdAllocator);
194 // Generic fence implementation for query objects. Fence has passed when query
195 // result is available.
196 class QueryFence : public ResourceProvider::Fence {
198 QueryFence(gpu::gles2::GLES2Interface* gl, unsigned query_id)
199 : gl_(gl), query_id_(query_id) {}
201 // Overridden from ResourceProvider::Fence:
202 virtual void Set() OVERRIDE {}
203 virtual bool HasPassed() OVERRIDE {
204 unsigned available = 1;
205 gl_->GetQueryObjectuivEXT(
206 query_id_, GL_QUERY_RESULT_AVAILABLE_EXT, &available);
211 virtual ~QueryFence() {}
213 gpu::gles2::GLES2Interface* gl_;
216 DISALLOW_COPY_AND_ASSIGN(QueryFence);
221 ResourceProvider::Resource::Resource()
224 gl_pixel_buffer_id(0),
225 gl_upload_query_id(0),
226 gl_read_lock_query_id(0),
228 lock_for_read_count(0),
232 locked_for_write(false),
234 marked_for_deletion(false),
235 pending_set_pixels(false),
236 set_pixels_completion_forced(false),
238 read_lock_fences_enabled(false),
239 has_shared_bitmap_id(false),
240 allow_overlay(false),
241 read_lock_fence(NULL),
251 hint(TextureUsageAny),
254 shared_bitmap(NULL) {
257 ResourceProvider::Resource::~Resource() {}
259 ResourceProvider::Resource::Resource(GLuint texture_id,
260 const gfx::Size& size,
266 TextureUsageHint hint,
267 ResourceFormat format)
270 gl_pixel_buffer_id(0),
271 gl_upload_query_id(0),
272 gl_read_lock_query_id(0),
274 lock_for_read_count(0),
278 locked_for_write(false),
280 marked_for_deletion(false),
281 pending_set_pixels(false),
282 set_pixels_completion_forced(false),
284 read_lock_fences_enabled(false),
285 has_shared_bitmap_id(false),
286 allow_overlay(false),
287 read_lock_fence(NULL),
291 original_filter(filter),
295 texture_pool(texture_pool),
296 wrap_mode(wrap_mode),
300 shared_bitmap(NULL) {
301 DCHECK(wrap_mode == GL_CLAMP_TO_EDGE || wrap_mode == GL_REPEAT);
302 DCHECK_EQ(origin == Internal, !!texture_pool);
305 ResourceProvider::Resource::Resource(uint8_t* pixels,
306 SharedBitmap* bitmap,
307 const gfx::Size& size,
313 gl_pixel_buffer_id(0),
314 gl_upload_query_id(0),
315 gl_read_lock_query_id(0),
317 lock_for_read_count(0),
321 locked_for_write(false),
323 marked_for_deletion(false),
324 pending_set_pixels(false),
325 set_pixels_completion_forced(false),
327 read_lock_fences_enabled(false),
328 has_shared_bitmap_id(!!bitmap),
329 allow_overlay(false),
330 read_lock_fence(NULL),
334 original_filter(filter),
339 wrap_mode(wrap_mode),
340 hint(TextureUsageAny),
343 shared_bitmap(bitmap) {
344 DCHECK(wrap_mode == GL_CLAMP_TO_EDGE || wrap_mode == GL_REPEAT);
345 DCHECK(origin == Delegated || pixels);
347 shared_bitmap_id = bitmap->id();
350 ResourceProvider::Resource::Resource(const SharedBitmapId& bitmap_id,
351 const gfx::Size& size,
357 gl_pixel_buffer_id(0),
358 gl_upload_query_id(0),
359 gl_read_lock_query_id(0),
361 lock_for_read_count(0),
365 locked_for_write(false),
367 marked_for_deletion(false),
368 pending_set_pixels(false),
369 set_pixels_completion_forced(false),
371 read_lock_fences_enabled(false),
372 has_shared_bitmap_id(true),
373 allow_overlay(false),
374 read_lock_fence(NULL),
378 original_filter(filter),
383 wrap_mode(wrap_mode),
384 hint(TextureUsageAny),
387 shared_bitmap_id(bitmap_id),
388 shared_bitmap(NULL) {
389 DCHECK(wrap_mode == GL_CLAMP_TO_EDGE || wrap_mode == GL_REPEAT);
392 ResourceProvider::RasterBuffer::RasterBuffer(
393 const Resource* resource,
394 ResourceProvider* resource_provider)
395 : resource_(resource),
396 resource_provider_(resource_provider),
397 locked_canvas_(NULL),
398 canvas_save_count_(0) {
400 DCHECK(resource_provider_);
403 ResourceProvider::RasterBuffer::~RasterBuffer() {}
405 SkCanvas* ResourceProvider::RasterBuffer::LockForWrite() {
406 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug"),
407 "ResourceProvider::RasterBuffer::LockForWrite");
409 DCHECK(!locked_canvas_);
411 locked_canvas_ = DoLockForWrite();
412 canvas_save_count_ = locked_canvas_ ? locked_canvas_->save() : 0;
413 return locked_canvas_;
416 bool ResourceProvider::RasterBuffer::UnlockForWrite() {
417 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug"),
418 "ResourceProvider::RasterBuffer::UnlockForWrite");
420 if (locked_canvas_) {
421 locked_canvas_->restoreToCount(canvas_save_count_);
422 locked_canvas_ = NULL;
424 return DoUnlockForWrite();
427 ResourceProvider::GpuRasterBuffer::GpuRasterBuffer(
428 const Resource* resource,
429 ResourceProvider* resource_provider,
430 bool use_distance_field_text)
431 : RasterBuffer(resource, resource_provider),
432 surface_generation_id_(0u),
433 use_distance_field_text_(use_distance_field_text) {
436 ResourceProvider::GpuRasterBuffer::~GpuRasterBuffer() {
439 SkCanvas* ResourceProvider::GpuRasterBuffer::DoLockForWrite() {
441 surface_ = CreateSurface();
442 surface_generation_id_ = surface_ ? surface_->generationID() : 0u;
443 return surface_ ? surface_->getCanvas() : NULL;
446 bool ResourceProvider::GpuRasterBuffer::DoUnlockForWrite() {
447 // generationID returns a non-zero, unique value corresponding to the content
448 // of surface. Hence, a change since DoLockForWrite was called means the
449 // surface has changed.
450 return surface_ ? surface_generation_id_ != surface_->generationID() : false;
453 skia::RefPtr<SkSurface> ResourceProvider::GpuRasterBuffer::CreateSurface() {
454 DCHECK_EQ(GLTexture, resource()->type);
455 DCHECK(resource()->gl_id);
457 class GrContext* gr_context = resource_provider()->GrContext();
458 // TODO(alokp): Implement TestContextProvider::GrContext().
460 return skia::RefPtr<SkSurface>();
462 GrBackendTextureDesc desc;
463 desc.fFlags = kRenderTarget_GrBackendTextureFlag;
464 desc.fWidth = resource()->size.width();
465 desc.fHeight = resource()->size.height();
466 desc.fConfig = ToGrPixelConfig(resource()->format);
467 desc.fOrigin = kTopLeft_GrSurfaceOrigin;
468 desc.fTextureHandle = resource()->gl_id;
469 skia::RefPtr<GrTexture> gr_texture =
470 skia::AdoptRef(gr_context->wrapBackendTexture(desc));
471 SkSurface::TextRenderMode text_render_mode =
472 use_distance_field_text_ ? SkSurface::kDistanceField_TextRenderMode
473 : SkSurface::kStandard_TextRenderMode;
474 return skia::AdoptRef(SkSurface::NewRenderTargetDirect(
475 gr_texture->asRenderTarget(), text_render_mode));
478 ResourceProvider::BitmapRasterBuffer::BitmapRasterBuffer(
479 const Resource* resource,
480 ResourceProvider* resource_provider)
481 : RasterBuffer(resource, resource_provider),
482 mapped_buffer_(NULL),
483 raster_bitmap_generation_id_(0u) {}
485 ResourceProvider::BitmapRasterBuffer::~BitmapRasterBuffer() {}
487 SkCanvas* ResourceProvider::BitmapRasterBuffer::DoLockForWrite() {
488 DCHECK(!mapped_buffer_);
489 DCHECK(!raster_canvas_);
492 mapped_buffer_ = MapBuffer(&stride);
496 switch (resource()->format) {
498 // Use the default stride if we will eventually convert this
500 raster_bitmap_.allocN32Pixels(resource()->size.width(),
501 resource()->size.height());
505 SkImageInfo info = SkImageInfo::MakeN32Premul(resource()->size.width(),
506 resource()->size.height());
508 stride = info.minRowBytes();
509 raster_bitmap_.installPixels(info, mapped_buffer_, stride);
519 raster_canvas_ = skia::AdoptRef(new SkCanvas(raster_bitmap_));
520 raster_bitmap_generation_id_ = raster_bitmap_.getGenerationID();
521 return raster_canvas_.get();
524 bool ResourceProvider::BitmapRasterBuffer::DoUnlockForWrite() {
525 raster_canvas_.clear();
527 // getGenerationID returns a non-zero, unique value corresponding to the
528 // pixels in bitmap. Hence, a change since DoLockForWrite was called means the
529 // bitmap has changed.
530 bool raster_bitmap_changed =
531 raster_bitmap_generation_id_ != raster_bitmap_.getGenerationID();
533 if (raster_bitmap_changed) {
534 SkColorType buffer_colorType =
535 ResourceFormatToSkColorType(resource()->format);
536 if (mapped_buffer_ && (buffer_colorType != raster_bitmap_.colorType()))
537 CopyBitmap(raster_bitmap_, mapped_buffer_, buffer_colorType);
539 raster_bitmap_.reset();
542 mapped_buffer_ = NULL;
543 return raster_bitmap_changed;
546 ResourceProvider::ImageRasterBuffer::ImageRasterBuffer(
547 const Resource* resource,
548 ResourceProvider* resource_provider)
549 : BitmapRasterBuffer(resource, resource_provider) {}
551 ResourceProvider::ImageRasterBuffer::~ImageRasterBuffer() {}
553 uint8_t* ResourceProvider::ImageRasterBuffer::MapBuffer(int* stride) {
554 return resource_provider()->MapImage(resource(), stride);
557 void ResourceProvider::ImageRasterBuffer::UnmapBuffer() {
558 resource_provider()->UnmapImage(resource());
561 ResourceProvider::PixelRasterBuffer::PixelRasterBuffer(
562 const Resource* resource,
563 ResourceProvider* resource_provider)
564 : BitmapRasterBuffer(resource, resource_provider) {}
566 ResourceProvider::PixelRasterBuffer::~PixelRasterBuffer() {}
568 uint8_t* ResourceProvider::PixelRasterBuffer::MapBuffer(int* stride) {
569 return resource_provider()->MapPixelBuffer(resource(), stride);
572 void ResourceProvider::PixelRasterBuffer::UnmapBuffer() {
573 resource_provider()->UnmapPixelBuffer(resource());
576 ResourceProvider::Child::Child() : marked_for_deletion(false) {}
578 ResourceProvider::Child::~Child() {}
580 scoped_ptr<ResourceProvider> ResourceProvider::Create(
581 OutputSurface* output_surface,
582 SharedBitmapManager* shared_bitmap_manager,
583 int highp_threshold_min,
584 bool use_rgba_4444_texture_format,
585 size_t id_allocation_chunk_size,
586 bool use_distance_field_text) {
587 scoped_ptr<ResourceProvider> resource_provider(
588 new ResourceProvider(output_surface,
589 shared_bitmap_manager,
591 use_rgba_4444_texture_format,
592 id_allocation_chunk_size,
593 use_distance_field_text));
595 if (resource_provider->ContextGL())
596 resource_provider->InitializeGL();
598 resource_provider->InitializeSoftware();
600 DCHECK_NE(InvalidType, resource_provider->default_resource_type());
601 return resource_provider.Pass();
604 ResourceProvider::~ResourceProvider() {
605 while (!children_.empty())
606 DestroyChildInternal(children_.begin(), ForShutdown);
607 while (!resources_.empty())
608 DeleteResourceInternal(resources_.begin(), ForShutdown);
613 bool ResourceProvider::InUseByConsumer(ResourceId id) {
614 Resource* resource = GetResource(id);
615 return resource->lock_for_read_count > 0 || resource->exported_count > 0 ||
619 bool ResourceProvider::IsLost(ResourceId id) {
620 Resource* resource = GetResource(id);
621 return resource->lost;
624 bool ResourceProvider::AllowOverlay(ResourceId id) {
625 Resource* resource = GetResource(id);
626 return resource->allow_overlay;
629 ResourceProvider::ResourceId ResourceProvider::CreateResource(
630 const gfx::Size& size,
632 TextureUsageHint hint,
633 ResourceFormat format) {
634 DCHECK(!size.IsEmpty());
635 switch (default_resource_type_) {
637 return CreateGLTexture(size,
639 GL_TEXTURE_POOL_UNMANAGED_CHROMIUM,
644 DCHECK_EQ(RGBA_8888, format);
645 return CreateBitmap(size, wrap_mode);
650 LOG(FATAL) << "Invalid default resource type.";
654 ResourceProvider::ResourceId ResourceProvider::CreateManagedResource(
655 const gfx::Size& size,
658 TextureUsageHint hint,
659 ResourceFormat format) {
660 DCHECK(!size.IsEmpty());
661 switch (default_resource_type_) {
663 return CreateGLTexture(size,
665 GL_TEXTURE_POOL_MANAGED_CHROMIUM,
670 DCHECK_EQ(RGBA_8888, format);
671 return CreateBitmap(size, wrap_mode);
676 LOG(FATAL) << "Invalid default resource type.";
680 ResourceProvider::ResourceId ResourceProvider::CreateGLTexture(
681 const gfx::Size& size,
685 TextureUsageHint hint,
686 ResourceFormat format) {
687 DCHECK_LE(size.width(), max_texture_size_);
688 DCHECK_LE(size.height(), max_texture_size_);
689 DCHECK(thread_checker_.CalledOnValidThread());
691 ResourceId id = next_id_++;
701 resource.allocated = false;
702 resources_[id] = resource;
706 ResourceProvider::ResourceId ResourceProvider::CreateBitmap(
707 const gfx::Size& size, GLint wrap_mode) {
708 DCHECK(thread_checker_.CalledOnValidThread());
710 scoped_ptr<SharedBitmap> bitmap;
711 if (shared_bitmap_manager_)
712 bitmap = shared_bitmap_manager_->AllocateSharedBitmap(size);
716 pixels = bitmap->pixels();
718 size_t bytes = SharedBitmap::CheckedSizeInBytes(size);
719 pixels = new uint8_t[bytes];
723 ResourceId id = next_id_++;
725 pixels, bitmap.release(), size, Resource::Internal, GL_LINEAR, wrap_mode);
726 resource.allocated = true;
727 resources_[id] = resource;
731 ResourceProvider::ResourceId ResourceProvider::CreateResourceFromIOSurface(
732 const gfx::Size& size,
733 unsigned io_surface_id) {
734 DCHECK(thread_checker_.CalledOnValidThread());
736 ResourceId id = next_id_++;
740 GL_TEXTURE_RECTANGLE_ARB,
742 GL_TEXTURE_POOL_UNMANAGED_CHROMIUM,
746 LazyCreate(&resource);
747 GLES2Interface* gl = ContextGL();
749 gl->BindTexture(GL_TEXTURE_RECTANGLE_ARB, resource.gl_id);
750 gl->TexImageIOSurface2DCHROMIUM(
751 GL_TEXTURE_RECTANGLE_ARB, size.width(), size.height(), io_surface_id, 0);
752 resource.allocated = true;
753 resources_[id] = resource;
757 ResourceProvider::ResourceId ResourceProvider::CreateResourceFromTextureMailbox(
758 const TextureMailbox& mailbox,
759 scoped_ptr<SingleReleaseCallback> release_callback) {
760 DCHECK(thread_checker_.CalledOnValidThread());
761 // Just store the information. Mailbox will be consumed in LockForRead().
762 ResourceId id = next_id_++;
763 DCHECK(mailbox.IsValid());
764 Resource& resource = resources_[id];
765 if (mailbox.IsTexture()) {
766 resource = Resource(0,
776 DCHECK(mailbox.IsSharedMemory());
777 base::SharedMemory* shared_memory = mailbox.shared_memory();
778 DCHECK(shared_memory->memory());
779 uint8_t* pixels = reinterpret_cast<uint8_t*>(shared_memory->memory());
781 scoped_ptr<SharedBitmap> shared_bitmap;
782 if (shared_bitmap_manager_) {
784 shared_bitmap_manager_->GetBitmapForSharedMemory(shared_memory);
786 resource = Resource(pixels,
787 shared_bitmap.release(),
788 mailbox.shared_memory_size(),
793 resource.allocated = true;
794 resource.mailbox = mailbox;
795 resource.release_callback =
796 base::Bind(&SingleReleaseCallback::Run,
797 base::Owned(release_callback.release()));
798 resource.allow_overlay = mailbox.allow_overlay();
802 void ResourceProvider::DeleteResource(ResourceId id) {
803 DCHECK(thread_checker_.CalledOnValidThread());
804 ResourceMap::iterator it = resources_.find(id);
805 CHECK(it != resources_.end());
806 Resource* resource = &it->second;
807 DCHECK(!resource->marked_for_deletion);
808 DCHECK_EQ(resource->imported_count, 0);
809 DCHECK(resource->pending_set_pixels || !resource->locked_for_write);
811 if (resource->exported_count > 0 || resource->lock_for_read_count > 0) {
812 resource->marked_for_deletion = true;
815 DeleteResourceInternal(it, Normal);
819 void ResourceProvider::DeleteResourceInternal(ResourceMap::iterator it,
821 TRACE_EVENT0("cc", "ResourceProvider::DeleteResourceInternal");
822 Resource* resource = &it->second;
823 bool lost_resource = resource->lost;
825 DCHECK(resource->exported_count == 0 || style != Normal);
826 if (style == ForShutdown && resource->exported_count > 0)
827 lost_resource = true;
829 resource->gpu_raster_buffer.reset();
830 resource->image_raster_buffer.reset();
831 resource->pixel_raster_buffer.reset();
833 if (resource->image_id) {
834 DCHECK(resource->origin == Resource::Internal);
835 GLES2Interface* gl = ContextGL();
837 GLC(gl, gl->DestroyImageCHROMIUM(resource->image_id));
839 if (resource->gl_upload_query_id) {
840 DCHECK(resource->origin == Resource::Internal);
841 GLES2Interface* gl = ContextGL();
843 GLC(gl, gl->DeleteQueriesEXT(1, &resource->gl_upload_query_id));
845 if (resource->gl_read_lock_query_id) {
846 DCHECK(resource->origin == Resource::Internal);
847 GLES2Interface* gl = ContextGL();
849 GLC(gl, gl->DeleteQueriesEXT(1, &resource->gl_read_lock_query_id));
851 if (resource->gl_pixel_buffer_id) {
852 DCHECK(resource->origin == Resource::Internal);
853 GLES2Interface* gl = ContextGL();
855 GLC(gl, gl->DeleteBuffers(1, &resource->gl_pixel_buffer_id));
857 if (resource->origin == Resource::External) {
858 DCHECK(resource->mailbox.IsValid());
859 GLuint sync_point = resource->mailbox.sync_point();
860 if (resource->type == GLTexture) {
861 DCHECK(resource->mailbox.IsTexture());
862 lost_resource |= lost_output_surface_;
863 GLES2Interface* gl = ContextGL();
865 if (resource->gl_id) {
866 GLC(gl, gl->DeleteTextures(1, &resource->gl_id));
869 sync_point = gl->InsertSyncPointCHROMIUM();
872 DCHECK(resource->mailbox.IsSharedMemory());
873 base::SharedMemory* shared_memory = resource->mailbox.shared_memory();
874 if (resource->pixels && shared_memory) {
875 DCHECK(shared_memory->memory() == resource->pixels);
876 resource->pixels = NULL;
877 delete resource->shared_bitmap;
878 resource->shared_bitmap = NULL;
881 resource->release_callback.Run(sync_point, lost_resource);
883 if (resource->gl_id) {
884 GLES2Interface* gl = ContextGL();
886 GLC(gl, gl->DeleteTextures(1, &resource->gl_id));
889 if (resource->shared_bitmap) {
890 DCHECK(resource->origin != Resource::External);
891 DCHECK_EQ(Bitmap, resource->type);
892 delete resource->shared_bitmap;
893 resource->pixels = NULL;
895 if (resource->pixels) {
896 DCHECK(resource->origin == Resource::Internal);
897 delete[] resource->pixels;
899 resources_.erase(it);
902 ResourceProvider::ResourceType ResourceProvider::GetResourceType(
904 return GetResource(id)->type;
907 void ResourceProvider::SetPixels(ResourceId id,
908 const uint8_t* image,
909 const gfx::Rect& image_rect,
910 const gfx::Rect& source_rect,
911 const gfx::Vector2d& dest_offset) {
912 Resource* resource = GetResource(id);
913 DCHECK(!resource->locked_for_write);
914 DCHECK(!resource->lock_for_read_count);
915 DCHECK(resource->origin == Resource::Internal);
916 DCHECK_EQ(resource->exported_count, 0);
917 DCHECK(ReadLockFenceHasPassed(resource));
918 LazyAllocate(resource);
920 if (resource->type == GLTexture) {
921 DCHECK(resource->gl_id);
922 DCHECK(!resource->pending_set_pixels);
923 DCHECK_EQ(resource->target, static_cast<GLenum>(GL_TEXTURE_2D));
924 GLES2Interface* gl = ContextGL();
926 DCHECK(texture_uploader_.get());
927 gl->BindTexture(GL_TEXTURE_2D, resource->gl_id);
928 texture_uploader_->Upload(image,
935 DCHECK_EQ(Bitmap, resource->type);
936 DCHECK(resource->allocated);
937 DCHECK_EQ(RGBA_8888, resource->format);
938 DCHECK(source_rect.x() >= image_rect.x());
939 DCHECK(source_rect.y() >= image_rect.y());
940 DCHECK(source_rect.right() <= image_rect.right());
941 DCHECK(source_rect.bottom() <= image_rect.bottom());
942 SkImageInfo source_info =
943 SkImageInfo::MakeN32Premul(source_rect.width(), source_rect.height());
944 size_t image_row_bytes = image_rect.width() * 4;
945 gfx::Vector2d source_offset = source_rect.origin() - image_rect.origin();
946 image += source_offset.y() * image_row_bytes + source_offset.x() * 4;
948 ScopedWriteLockSoftware lock(this, id);
949 SkCanvas* dest = lock.sk_canvas();
951 source_info, image, image_row_bytes, dest_offset.x(), dest_offset.y());
955 size_t ResourceProvider::NumBlockingUploads() {
956 if (!texture_uploader_)
959 return texture_uploader_->NumBlockingUploads();
962 void ResourceProvider::MarkPendingUploadsAsNonBlocking() {
963 if (!texture_uploader_)
966 texture_uploader_->MarkPendingUploadsAsNonBlocking();
969 size_t ResourceProvider::EstimatedUploadsPerTick() {
970 if (!texture_uploader_)
973 double textures_per_second = texture_uploader_->EstimatedTexturesPerSecond();
974 size_t textures_per_tick = floor(
975 kTextureUploadTickRate * textures_per_second);
976 return textures_per_tick ? textures_per_tick : 1u;
979 void ResourceProvider::FlushUploads() {
980 if (!texture_uploader_)
983 texture_uploader_->Flush();
986 void ResourceProvider::ReleaseCachedData() {
987 if (!texture_uploader_)
990 texture_uploader_->ReleaseCachedQueries();
993 base::TimeTicks ResourceProvider::EstimatedUploadCompletionTime(
994 size_t uploads_per_tick) {
995 if (lost_output_surface_)
996 return base::TimeTicks();
998 // Software resource uploads happen on impl thread, so don't bother batching
999 // them up and trying to wait for them to complete.
1000 if (!texture_uploader_) {
1001 return gfx::FrameTime::Now() + base::TimeDelta::FromMicroseconds(
1002 base::Time::kMicrosecondsPerSecond * kSoftwareUploadTickRate);
1005 base::TimeDelta upload_one_texture_time =
1006 base::TimeDelta::FromMicroseconds(
1007 base::Time::kMicrosecondsPerSecond * kTextureUploadTickRate) /
1010 size_t total_uploads = NumBlockingUploads() + uploads_per_tick;
1011 return gfx::FrameTime::Now() + upload_one_texture_time * total_uploads;
1014 ResourceProvider::Resource* ResourceProvider::GetResource(ResourceId id) {
1015 DCHECK(thread_checker_.CalledOnValidThread());
1016 ResourceMap::iterator it = resources_.find(id);
1017 CHECK(it != resources_.end());
1021 const ResourceProvider::Resource* ResourceProvider::LockForRead(ResourceId id) {
1022 Resource* resource = GetResource(id);
1023 DCHECK(!resource->locked_for_write ||
1024 resource->set_pixels_completion_forced) <<
1025 "locked for write: " << resource->locked_for_write <<
1026 " pixels completion forced: " << resource->set_pixels_completion_forced;
1027 DCHECK_EQ(resource->exported_count, 0);
1028 // Uninitialized! Call SetPixels or LockForWrite first.
1029 DCHECK(resource->allocated);
1031 LazyCreate(resource);
1033 if (resource->type == GLTexture && !resource->gl_id) {
1034 DCHECK(resource->origin != Resource::Internal);
1035 DCHECK(resource->mailbox.IsTexture());
1036 GLES2Interface* gl = ContextGL();
1038 if (resource->mailbox.sync_point()) {
1039 GLC(gl, gl->WaitSyncPointCHROMIUM(resource->mailbox.sync_point()));
1040 resource->mailbox.set_sync_point(0);
1042 resource->gl_id = texture_id_allocator_->NextId();
1043 GLC(gl, gl->BindTexture(resource->target, resource->gl_id));
1045 gl->ConsumeTextureCHROMIUM(resource->mailbox.target(),
1046 resource->mailbox.name()));
1049 if (!resource->pixels && resource->has_shared_bitmap_id &&
1050 shared_bitmap_manager_) {
1051 scoped_ptr<SharedBitmap> bitmap =
1052 shared_bitmap_manager_->GetSharedBitmapFromId(
1053 resource->size, resource->shared_bitmap_id);
1055 resource->shared_bitmap = bitmap.release();
1056 resource->pixels = resource->shared_bitmap->pixels();
1060 resource->lock_for_read_count++;
1061 if (resource->read_lock_fences_enabled) {
1062 if (current_read_lock_fence_)
1063 current_read_lock_fence_->Set();
1064 resource->read_lock_fence = current_read_lock_fence_;
1070 void ResourceProvider::UnlockForRead(ResourceId id) {
1071 DCHECK(thread_checker_.CalledOnValidThread());
1072 ResourceMap::iterator it = resources_.find(id);
1073 CHECK(it != resources_.end());
1075 Resource* resource = &it->second;
1076 DCHECK_GT(resource->lock_for_read_count, 0);
1077 DCHECK_EQ(resource->exported_count, 0);
1078 resource->lock_for_read_count--;
1079 if (resource->marked_for_deletion && !resource->lock_for_read_count) {
1080 if (!resource->child_id) {
1081 // The resource belongs to this ResourceProvider, so it can be destroyed.
1082 DeleteResourceInternal(it, Normal);
1084 ChildMap::iterator child_it = children_.find(resource->child_id);
1085 ResourceIdArray unused;
1086 unused.push_back(id);
1087 DeleteAndReturnUnusedResourcesToChild(child_it, Normal, unused);
1092 const ResourceProvider::Resource* ResourceProvider::LockForWrite(
1094 Resource* resource = GetResource(id);
1095 DCHECK(!resource->locked_for_write);
1096 DCHECK(!resource->lock_for_read_count);
1097 DCHECK_EQ(resource->exported_count, 0);
1098 DCHECK(resource->origin == Resource::Internal);
1099 DCHECK(!resource->lost);
1100 DCHECK(ReadLockFenceHasPassed(resource));
1101 LazyAllocate(resource);
1103 resource->locked_for_write = true;
1107 bool ResourceProvider::CanLockForWrite(ResourceId id) {
1108 Resource* resource = GetResource(id);
1109 return !resource->locked_for_write && !resource->lock_for_read_count &&
1110 !resource->exported_count && resource->origin == Resource::Internal &&
1111 !resource->lost && ReadLockFenceHasPassed(resource);
1114 void ResourceProvider::UnlockForWrite(ResourceId id) {
1115 Resource* resource = GetResource(id);
1116 DCHECK(resource->locked_for_write);
1117 DCHECK_EQ(resource->exported_count, 0);
1118 DCHECK(resource->origin == Resource::Internal);
1119 resource->locked_for_write = false;
1122 ResourceProvider::ScopedReadLockGL::ScopedReadLockGL(
1123 ResourceProvider* resource_provider,
1124 ResourceProvider::ResourceId resource_id)
1125 : resource_provider_(resource_provider),
1126 resource_id_(resource_id),
1127 texture_id_(resource_provider->LockForRead(resource_id)->gl_id) {
1128 DCHECK(texture_id_);
1131 ResourceProvider::ScopedReadLockGL::~ScopedReadLockGL() {
1132 resource_provider_->UnlockForRead(resource_id_);
1135 ResourceProvider::ScopedSamplerGL::ScopedSamplerGL(
1136 ResourceProvider* resource_provider,
1137 ResourceProvider::ResourceId resource_id,
1139 : ScopedReadLockGL(resource_provider, resource_id),
1141 target_(resource_provider->BindForSampling(resource_id, unit_, filter)) {
1144 ResourceProvider::ScopedSamplerGL::ScopedSamplerGL(
1145 ResourceProvider* resource_provider,
1146 ResourceProvider::ResourceId resource_id,
1149 : ScopedReadLockGL(resource_provider, resource_id),
1151 target_(resource_provider->BindForSampling(resource_id, unit_, filter)) {
1154 ResourceProvider::ScopedSamplerGL::~ScopedSamplerGL() {
1157 ResourceProvider::ScopedWriteLockGL::ScopedWriteLockGL(
1158 ResourceProvider* resource_provider,
1159 ResourceProvider::ResourceId resource_id)
1160 : resource_provider_(resource_provider),
1161 resource_id_(resource_id),
1162 texture_id_(resource_provider->LockForWrite(resource_id)->gl_id) {
1163 DCHECK(texture_id_);
1166 ResourceProvider::ScopedWriteLockGL::~ScopedWriteLockGL() {
1167 resource_provider_->UnlockForWrite(resource_id_);
1170 void ResourceProvider::PopulateSkBitmapWithResource(
1171 SkBitmap* sk_bitmap, const Resource* resource) {
1172 DCHECK_EQ(RGBA_8888, resource->format);
1173 SkImageInfo info = SkImageInfo::MakeN32Premul(resource->size.width(),
1174 resource->size.height());
1175 sk_bitmap->installPixels(info, resource->pixels, info.minRowBytes());
1178 ResourceProvider::ScopedReadLockSoftware::ScopedReadLockSoftware(
1179 ResourceProvider* resource_provider,
1180 ResourceProvider::ResourceId resource_id)
1181 : resource_provider_(resource_provider),
1182 resource_id_(resource_id) {
1183 const Resource* resource = resource_provider->LockForRead(resource_id);
1184 wrap_mode_ = resource->wrap_mode;
1185 ResourceProvider::PopulateSkBitmapWithResource(&sk_bitmap_, resource);
1188 ResourceProvider::ScopedReadLockSoftware::~ScopedReadLockSoftware() {
1189 resource_provider_->UnlockForRead(resource_id_);
1192 ResourceProvider::ScopedWriteLockSoftware::ScopedWriteLockSoftware(
1193 ResourceProvider* resource_provider,
1194 ResourceProvider::ResourceId resource_id)
1195 : resource_provider_(resource_provider),
1196 resource_id_(resource_id) {
1197 ResourceProvider::PopulateSkBitmapWithResource(
1198 &sk_bitmap_, resource_provider->LockForWrite(resource_id));
1200 sk_canvas_.reset(new SkCanvas(sk_bitmap_));
1203 ResourceProvider::ScopedWriteLockSoftware::~ScopedWriteLockSoftware() {
1204 resource_provider_->UnlockForWrite(resource_id_);
1207 ResourceProvider::ResourceProvider(OutputSurface* output_surface,
1208 SharedBitmapManager* shared_bitmap_manager,
1209 int highp_threshold_min,
1210 bool use_rgba_4444_texture_format,
1211 size_t id_allocation_chunk_size,
1212 bool use_distance_field_text)
1213 : output_surface_(output_surface),
1214 shared_bitmap_manager_(shared_bitmap_manager),
1215 lost_output_surface_(false),
1216 highp_threshold_min_(highp_threshold_min),
1219 default_resource_type_(InvalidType),
1220 use_texture_storage_ext_(false),
1221 use_texture_usage_hint_(false),
1222 use_compressed_texture_etc1_(false),
1223 max_texture_size_(0),
1224 best_texture_format_(RGBA_8888),
1225 use_rgba_4444_texture_format_(use_rgba_4444_texture_format),
1226 id_allocation_chunk_size_(id_allocation_chunk_size),
1227 use_sync_query_(false),
1228 use_distance_field_text_(use_distance_field_text) {
1229 DCHECK(output_surface_->HasClient());
1230 DCHECK(id_allocation_chunk_size_);
1233 void ResourceProvider::InitializeSoftware() {
1234 DCHECK(thread_checker_.CalledOnValidThread());
1235 DCHECK_NE(Bitmap, default_resource_type_);
1237 CleanUpGLIfNeeded();
1239 default_resource_type_ = Bitmap;
1240 // Pick an arbitrary limit here similar to what hardware might.
1241 max_texture_size_ = 16 * 1024;
1242 best_texture_format_ = RGBA_8888;
1245 void ResourceProvider::InitializeGL() {
1246 DCHECK(thread_checker_.CalledOnValidThread());
1247 DCHECK(!texture_uploader_);
1248 DCHECK_NE(GLTexture, default_resource_type_);
1249 DCHECK(!texture_id_allocator_);
1250 DCHECK(!buffer_id_allocator_);
1252 default_resource_type_ = GLTexture;
1254 const ContextProvider::Capabilities& caps =
1255 output_surface_->context_provider()->ContextCapabilities();
1257 bool use_bgra = caps.gpu.texture_format_bgra8888;
1258 use_texture_storage_ext_ = caps.gpu.texture_storage;
1259 use_texture_usage_hint_ = caps.gpu.texture_usage;
1260 use_compressed_texture_etc1_ = caps.gpu.texture_format_etc1;
1261 use_sync_query_ = caps.gpu.sync_query;
1263 GLES2Interface* gl = ContextGL();
1266 texture_uploader_ = TextureUploader::Create(gl);
1267 max_texture_size_ = 0; // Context expects cleared value.
1268 GLC(gl, gl->GetIntegerv(GL_MAX_TEXTURE_SIZE, &max_texture_size_));
1269 best_texture_format_ = PlatformColor::BestTextureFormat(use_bgra);
1271 texture_id_allocator_.reset(
1272 new TextureIdAllocator(gl, id_allocation_chunk_size_));
1273 buffer_id_allocator_.reset(
1274 new BufferIdAllocator(gl, id_allocation_chunk_size_));
1277 void ResourceProvider::CleanUpGLIfNeeded() {
1278 GLES2Interface* gl = ContextGL();
1279 if (default_resource_type_ != GLTexture) {
1280 // We are not in GL mode, but double check before returning.
1282 DCHECK(!texture_uploader_);
1288 // Check that all GL resources has been deleted.
1289 for (ResourceMap::const_iterator itr = resources_.begin();
1290 itr != resources_.end();
1292 DCHECK_NE(GLTexture, itr->second.type);
1294 #endif // DCHECK_IS_ON
1296 texture_uploader_.reset();
1297 texture_id_allocator_.reset();
1298 buffer_id_allocator_.reset();
1302 int ResourceProvider::CreateChild(const ReturnCallback& return_callback) {
1303 DCHECK(thread_checker_.CalledOnValidThread());
1306 child_info.return_callback = return_callback;
1308 int child = next_child_++;
1309 children_[child] = child_info;
1313 void ResourceProvider::DestroyChild(int child_id) {
1314 ChildMap::iterator it = children_.find(child_id);
1315 DCHECK(it != children_.end());
1316 DestroyChildInternal(it, Normal);
1319 void ResourceProvider::DestroyChildInternal(ChildMap::iterator it,
1320 DeleteStyle style) {
1321 DCHECK(thread_checker_.CalledOnValidThread());
1323 Child& child = it->second;
1324 DCHECK(style == ForShutdown || !child.marked_for_deletion);
1326 ResourceIdArray resources_for_child;
1328 for (ResourceIdMap::iterator child_it = child.child_to_parent_map.begin();
1329 child_it != child.child_to_parent_map.end();
1331 ResourceId id = child_it->second;
1332 resources_for_child.push_back(id);
1335 // If the child is going away, don't consider any resources in use.
1336 child.in_use_resources.clear();
1337 child.marked_for_deletion = true;
1339 DeleteAndReturnUnusedResourcesToChild(it, style, resources_for_child);
1342 const ResourceProvider::ResourceIdMap& ResourceProvider::GetChildToParentMap(
1344 DCHECK(thread_checker_.CalledOnValidThread());
1345 ChildMap::const_iterator it = children_.find(child);
1346 DCHECK(it != children_.end());
1347 DCHECK(!it->second.marked_for_deletion);
1348 return it->second.child_to_parent_map;
1351 void ResourceProvider::PrepareSendToParent(const ResourceIdArray& resources,
1352 TransferableResourceArray* list) {
1353 DCHECK(thread_checker_.CalledOnValidThread());
1354 GLES2Interface* gl = ContextGL();
1355 bool need_sync_point = false;
1356 for (ResourceIdArray::const_iterator it = resources.begin();
1357 it != resources.end();
1359 TransferableResource resource;
1360 TransferResource(gl, *it, &resource);
1361 if (!resource.mailbox_holder.sync_point && !resource.is_software)
1362 need_sync_point = true;
1363 ++resources_.find(*it)->second.exported_count;
1364 list->push_back(resource);
1366 if (need_sync_point) {
1367 GLuint sync_point = gl->InsertSyncPointCHROMIUM();
1368 for (TransferableResourceArray::iterator it = list->begin();
1371 if (!it->mailbox_holder.sync_point)
1372 it->mailbox_holder.sync_point = sync_point;
1377 void ResourceProvider::ReceiveFromChild(
1378 int child, const TransferableResourceArray& resources) {
1379 DCHECK(thread_checker_.CalledOnValidThread());
1380 GLES2Interface* gl = ContextGL();
1381 Child& child_info = children_.find(child)->second;
1382 DCHECK(!child_info.marked_for_deletion);
1383 for (TransferableResourceArray::const_iterator it = resources.begin();
1384 it != resources.end();
1386 ResourceIdMap::iterator resource_in_map_it =
1387 child_info.child_to_parent_map.find(it->id);
1388 if (resource_in_map_it != child_info.child_to_parent_map.end()) {
1389 Resource& resource = resources_[resource_in_map_it->second];
1390 resource.marked_for_deletion = false;
1391 resource.imported_count++;
1395 if ((!it->is_software && !gl) ||
1396 (it->is_software && !shared_bitmap_manager_)) {
1397 TRACE_EVENT0("cc", "ResourceProvider::ReceiveFromChild dropping invalid");
1398 ReturnedResourceArray to_return;
1399 to_return.push_back(it->ToReturnedResource());
1400 child_info.return_callback.Run(to_return);
1404 ResourceId local_id = next_id_++;
1405 Resource& resource = resources_[local_id];
1406 if (it->is_software) {
1407 resource = Resource(it->mailbox_holder.mailbox,
1409 Resource::Delegated,
1411 it->is_repeated ? GL_REPEAT : GL_CLAMP_TO_EDGE);
1413 resource = Resource(0,
1415 Resource::Delegated,
1416 it->mailbox_holder.texture_target,
1419 it->is_repeated ? GL_REPEAT : GL_CLAMP_TO_EDGE,
1422 resource.mailbox = TextureMailbox(it->mailbox_holder.mailbox,
1423 it->mailbox_holder.texture_target,
1424 it->mailbox_holder.sync_point);
1426 resource.child_id = child;
1427 // Don't allocate a texture for a child.
1428 resource.allocated = true;
1429 resource.imported_count = 1;
1430 resource.allow_overlay = it->allow_overlay;
1431 child_info.parent_to_child_map[local_id] = it->id;
1432 child_info.child_to_parent_map[it->id] = local_id;
1436 void ResourceProvider::DeclareUsedResourcesFromChild(
1438 const ResourceIdArray& resources_from_child) {
1439 DCHECK(thread_checker_.CalledOnValidThread());
1441 ChildMap::iterator child_it = children_.find(child);
1442 DCHECK(child_it != children_.end());
1443 Child& child_info = child_it->second;
1444 DCHECK(!child_info.marked_for_deletion);
1445 child_info.in_use_resources.clear();
1447 for (size_t i = 0; i < resources_from_child.size(); ++i) {
1448 ResourceIdMap::iterator it =
1449 child_info.child_to_parent_map.find(resources_from_child[i]);
1450 DCHECK(it != child_info.child_to_parent_map.end());
1452 ResourceId local_id = it->second;
1453 DCHECK(!resources_[local_id].marked_for_deletion);
1454 child_info.in_use_resources.insert(local_id);
1457 ResourceIdArray unused;
1458 for (ResourceIdMap::iterator it = child_info.child_to_parent_map.begin();
1459 it != child_info.child_to_parent_map.end();
1461 ResourceId local_id = it->second;
1462 bool resource_is_in_use = child_info.in_use_resources.count(local_id) > 0;
1463 if (!resource_is_in_use)
1464 unused.push_back(local_id);
1466 DeleteAndReturnUnusedResourcesToChild(child_it, Normal, unused);
1470 bool ResourceProvider::CompareResourceMapIteratorsByChildId(
1471 const std::pair<ReturnedResource, ResourceMap::iterator>& a,
1472 const std::pair<ReturnedResource, ResourceMap::iterator>& b) {
1473 const ResourceMap::iterator& a_it = a.second;
1474 const ResourceMap::iterator& b_it = b.second;
1475 const Resource& a_resource = a_it->second;
1476 const Resource& b_resource = b_it->second;
1477 return a_resource.child_id < b_resource.child_id;
1480 void ResourceProvider::ReceiveReturnsFromParent(
1481 const ReturnedResourceArray& resources) {
1482 DCHECK(thread_checker_.CalledOnValidThread());
1483 GLES2Interface* gl = ContextGL();
1486 ResourceIdArray resources_for_child;
1488 std::vector<std::pair<ReturnedResource, ResourceMap::iterator> >
1491 for (ReturnedResourceArray::const_iterator it = resources.begin();
1492 it != resources.end();
1494 ResourceId local_id = it->id;
1495 ResourceMap::iterator map_iterator = resources_.find(local_id);
1497 // Resource was already lost (e.g. it belonged to a child that was
1499 if (map_iterator == resources_.end())
1502 sorted_resources.push_back(
1503 std::pair<ReturnedResource, ResourceMap::iterator>(*it, map_iterator));
1506 std::sort(sorted_resources.begin(),
1507 sorted_resources.end(),
1508 CompareResourceMapIteratorsByChildId);
1510 ChildMap::iterator child_it = children_.end();
1511 for (size_t i = 0; i < sorted_resources.size(); ++i) {
1512 ReturnedResource& returned = sorted_resources[i].first;
1513 ResourceMap::iterator& map_iterator = sorted_resources[i].second;
1514 ResourceId local_id = map_iterator->first;
1515 Resource* resource = &map_iterator->second;
1517 CHECK_GE(resource->exported_count, returned.count);
1518 resource->exported_count -= returned.count;
1519 resource->lost |= returned.lost;
1520 if (resource->exported_count)
1523 // Need to wait for the current read lock fence to pass before we can
1524 // recycle this resource.
1525 if (resource->read_lock_fences_enabled) {
1526 if (current_read_lock_fence_)
1527 current_read_lock_fence_->Set();
1528 resource->read_lock_fence = current_read_lock_fence_;
1531 if (returned.sync_point) {
1532 DCHECK(!resource->has_shared_bitmap_id);
1533 if (resource->origin == Resource::Internal) {
1534 DCHECK(resource->gl_id);
1535 GLC(gl, gl->WaitSyncPointCHROMIUM(returned.sync_point));
1537 DCHECK(!resource->gl_id);
1538 resource->mailbox.set_sync_point(returned.sync_point);
1542 if (!resource->marked_for_deletion)
1545 if (!resource->child_id) {
1546 // The resource belongs to this ResourceProvider, so it can be destroyed.
1547 DeleteResourceInternal(map_iterator, Normal);
1551 DCHECK(resource->origin == Resource::Delegated);
1552 // Delete the resource and return it to the child it came from one.
1553 if (resource->child_id != child_id) {
1555 DCHECK_NE(resources_for_child.size(), 0u);
1556 DCHECK(child_it != children_.end());
1557 DeleteAndReturnUnusedResourcesToChild(
1558 child_it, Normal, resources_for_child);
1559 resources_for_child.clear();
1562 child_it = children_.find(resource->child_id);
1563 DCHECK(child_it != children_.end());
1564 child_id = resource->child_id;
1566 resources_for_child.push_back(local_id);
1570 DCHECK_NE(resources_for_child.size(), 0u);
1571 DCHECK(child_it != children_.end());
1572 DeleteAndReturnUnusedResourcesToChild(
1573 child_it, Normal, resources_for_child);
1577 void ResourceProvider::TransferResource(GLES2Interface* gl,
1579 TransferableResource* resource) {
1580 Resource* source = GetResource(id);
1581 DCHECK(!source->locked_for_write);
1582 DCHECK(!source->lock_for_read_count);
1583 DCHECK(source->origin != Resource::External || source->mailbox.IsValid());
1584 DCHECK(source->allocated);
1586 resource->format = source->format;
1587 resource->mailbox_holder.texture_target = source->target;
1588 resource->filter = source->filter;
1589 resource->size = source->size;
1590 resource->is_repeated = (source->wrap_mode == GL_REPEAT);
1591 resource->allow_overlay = source->allow_overlay;
1593 if (source->type == Bitmap) {
1594 resource->mailbox_holder.mailbox = source->shared_bitmap_id;
1595 resource->is_software = true;
1596 } else if (!source->mailbox.IsValid()) {
1598 DCHECK(source->gl_id);
1599 DCHECK(source->origin == Resource::Internal);
1601 gl->BindTexture(resource->mailbox_holder.texture_target,
1603 if (source->image_id) {
1604 DCHECK(source->dirty_image);
1605 BindImageForSampling(source);
1607 // This is a resource allocated by the compositor, we need to produce it.
1608 // Don't set a sync point, the caller will do it.
1609 GLC(gl, gl->GenMailboxCHROMIUM(resource->mailbox_holder.mailbox.name));
1611 gl->ProduceTextureCHROMIUM(resource->mailbox_holder.texture_target,
1612 resource->mailbox_holder.mailbox.name));
1613 source->mailbox = TextureMailbox(resource->mailbox_holder);
1615 DCHECK(source->mailbox.IsTexture());
1616 if (source->image_id && source->dirty_image) {
1617 DCHECK(source->gl_id);
1618 DCHECK(source->origin == Resource::Internal);
1620 gl->BindTexture(resource->mailbox_holder.texture_target,
1622 BindImageForSampling(source);
1624 // This is either an external resource, or a compositor resource that we
1625 // already exported. Make sure to forward the sync point that we were given.
1626 resource->mailbox_holder.mailbox = source->mailbox.mailbox();
1627 resource->mailbox_holder.texture_target = source->mailbox.target();
1628 resource->mailbox_holder.sync_point = source->mailbox.sync_point();
1629 source->mailbox.set_sync_point(0);
1633 void ResourceProvider::DeleteAndReturnUnusedResourcesToChild(
1634 ChildMap::iterator child_it,
1636 const ResourceIdArray& unused) {
1637 DCHECK(thread_checker_.CalledOnValidThread());
1638 DCHECK(child_it != children_.end());
1639 Child* child_info = &child_it->second;
1641 if (unused.empty() && !child_info->marked_for_deletion)
1644 ReturnedResourceArray to_return;
1646 GLES2Interface* gl = ContextGL();
1647 bool need_sync_point = false;
1648 for (size_t i = 0; i < unused.size(); ++i) {
1649 ResourceId local_id = unused[i];
1651 ResourceMap::iterator it = resources_.find(local_id);
1652 CHECK(it != resources_.end());
1653 Resource& resource = it->second;
1655 DCHECK(!resource.locked_for_write);
1656 DCHECK_EQ(0u, child_info->in_use_resources.count(local_id));
1657 DCHECK(child_info->parent_to_child_map.count(local_id));
1659 ResourceId child_id = child_info->parent_to_child_map[local_id];
1660 DCHECK(child_info->child_to_parent_map.count(child_id));
1663 resource.lost || (resource.type == GLTexture && lost_output_surface_);
1664 if (resource.exported_count > 0 || resource.lock_for_read_count > 0) {
1665 if (style != ForShutdown) {
1666 // Defer this until we receive the resource back from the parent or
1667 // the read lock is released.
1668 resource.marked_for_deletion = true;
1672 // We still have an exported_count, so we'll have to lose it.
1676 if (gl && resource.filter != resource.original_filter) {
1677 DCHECK(resource.target);
1678 DCHECK(resource.gl_id);
1680 GLC(gl, gl->BindTexture(resource.target, resource.gl_id));
1682 gl->TexParameteri(resource.target,
1683 GL_TEXTURE_MIN_FILTER,
1684 resource.original_filter));
1686 gl->TexParameteri(resource.target,
1687 GL_TEXTURE_MAG_FILTER,
1688 resource.original_filter));
1691 ReturnedResource returned;
1692 returned.id = child_id;
1693 returned.sync_point = resource.mailbox.sync_point();
1694 if (!returned.sync_point && resource.type == GLTexture)
1695 need_sync_point = true;
1696 returned.count = resource.imported_count;
1697 returned.lost = is_lost;
1698 to_return.push_back(returned);
1700 child_info->parent_to_child_map.erase(local_id);
1701 child_info->child_to_parent_map.erase(child_id);
1702 resource.imported_count = 0;
1703 DeleteResourceInternal(it, style);
1705 if (need_sync_point) {
1707 GLuint sync_point = gl->InsertSyncPointCHROMIUM();
1708 for (size_t i = 0; i < to_return.size(); ++i) {
1709 if (!to_return[i].sync_point)
1710 to_return[i].sync_point = sync_point;
1714 if (!to_return.empty())
1715 child_info->return_callback.Run(to_return);
1717 if (child_info->marked_for_deletion &&
1718 child_info->parent_to_child_map.empty()) {
1719 DCHECK(child_info->child_to_parent_map.empty());
1720 children_.erase(child_it);
1724 SkCanvas* ResourceProvider::MapGpuRasterBuffer(ResourceId id) {
1725 // Resource needs to be locked for write since GpuRasterBuffer writes
1728 Resource* resource = GetResource(id);
1729 if (!resource->gpu_raster_buffer.get()) {
1730 resource->gpu_raster_buffer.reset(
1731 new GpuRasterBuffer(resource, this, use_distance_field_text_));
1733 return resource->gpu_raster_buffer->LockForWrite();
1736 void ResourceProvider::UnmapGpuRasterBuffer(ResourceId id) {
1737 Resource* resource = GetResource(id);
1738 DCHECK(resource->gpu_raster_buffer.get());
1739 resource->gpu_raster_buffer->UnlockForWrite();
1743 SkCanvas* ResourceProvider::MapImageRasterBuffer(ResourceId id) {
1744 Resource* resource = GetResource(id);
1745 AcquireImage(resource);
1746 if (!resource->image_raster_buffer.get())
1747 resource->image_raster_buffer.reset(new ImageRasterBuffer(resource, this));
1748 return resource->image_raster_buffer->LockForWrite();
1751 bool ResourceProvider::UnmapImageRasterBuffer(ResourceId id) {
1752 Resource* resource = GetResource(id);
1753 resource->dirty_image = true;
1754 return resource->image_raster_buffer->UnlockForWrite();
1757 void ResourceProvider::AcquirePixelRasterBuffer(ResourceId id) {
1758 Resource* resource = GetResource(id);
1759 AcquirePixelBuffer(resource);
1760 resource->pixel_raster_buffer.reset(new PixelRasterBuffer(resource, this));
1763 void ResourceProvider::ReleasePixelRasterBuffer(ResourceId id) {
1764 Resource* resource = GetResource(id);
1765 resource->pixel_raster_buffer.reset();
1766 ReleasePixelBuffer(resource);
1769 SkCanvas* ResourceProvider::MapPixelRasterBuffer(ResourceId id) {
1770 Resource* resource = GetResource(id);
1771 DCHECK(resource->pixel_raster_buffer.get());
1772 return resource->pixel_raster_buffer->LockForWrite();
1775 bool ResourceProvider::UnmapPixelRasterBuffer(ResourceId id) {
1776 Resource* resource = GetResource(id);
1777 DCHECK(resource->pixel_raster_buffer.get());
1778 return resource->pixel_raster_buffer->UnlockForWrite();
1781 void ResourceProvider::AcquirePixelBuffer(Resource* resource) {
1782 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug"),
1783 "ResourceProvider::AcquirePixelBuffer");
1785 DCHECK(resource->origin == Resource::Internal);
1786 DCHECK_EQ(resource->exported_count, 0);
1787 DCHECK(!resource->image_id);
1788 DCHECK_NE(ETC1, resource->format);
1790 DCHECK_EQ(GLTexture, resource->type);
1791 GLES2Interface* gl = ContextGL();
1793 if (!resource->gl_pixel_buffer_id)
1794 resource->gl_pixel_buffer_id = buffer_id_allocator_->NextId();
1795 gl->BindBuffer(GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM,
1796 resource->gl_pixel_buffer_id);
1797 unsigned bytes_per_pixel = BitsPerPixel(resource->format) / 8;
1798 gl->BufferData(GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM,
1799 resource->size.height() *
1800 RoundUp(bytes_per_pixel * resource->size.width(), 4u),
1803 gl->BindBuffer(GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM, 0);
1806 void ResourceProvider::ReleasePixelBuffer(Resource* resource) {
1807 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug"),
1808 "ResourceProvider::ReleasePixelBuffer");
1810 DCHECK(resource->origin == Resource::Internal);
1811 DCHECK_EQ(resource->exported_count, 0);
1812 DCHECK(!resource->image_id);
1814 // The pixel buffer can be released while there is a pending "set pixels"
1815 // if completion has been forced. Any shared memory associated with this
1816 // pixel buffer will not be freed until the waitAsyncTexImage2DCHROMIUM
1817 // command has been processed on the service side. It is also safe to
1818 // reuse any query id associated with this resource before they complete
1819 // as each new query has a unique submit count.
1820 if (resource->pending_set_pixels) {
1821 DCHECK(resource->set_pixels_completion_forced);
1822 resource->pending_set_pixels = false;
1823 resource->locked_for_write = false;
1826 DCHECK_EQ(GLTexture, resource->type);
1827 if (!resource->gl_pixel_buffer_id)
1829 GLES2Interface* gl = ContextGL();
1831 gl->BindBuffer(GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM,
1832 resource->gl_pixel_buffer_id);
1834 GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM, 0, NULL, GL_DYNAMIC_DRAW);
1835 gl->BindBuffer(GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM, 0);
1838 uint8_t* ResourceProvider::MapPixelBuffer(const Resource* resource,
1840 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug"),
1841 "ResourceProvider::MapPixelBuffer");
1843 DCHECK(resource->origin == Resource::Internal);
1844 DCHECK_EQ(resource->exported_count, 0);
1845 DCHECK(!resource->image_id);
1848 DCHECK_EQ(GLTexture, resource->type);
1849 GLES2Interface* gl = ContextGL();
1851 DCHECK(resource->gl_pixel_buffer_id);
1852 gl->BindBuffer(GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM,
1853 resource->gl_pixel_buffer_id);
1854 uint8_t* image = static_cast<uint8_t*>(gl->MapBufferCHROMIUM(
1855 GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM, GL_WRITE_ONLY));
1856 gl->BindBuffer(GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM, 0);
1857 // Buffer is required to be 4-byte aligned.
1858 CHECK(!(reinterpret_cast<intptr_t>(image) & 3));
1862 void ResourceProvider::UnmapPixelBuffer(const Resource* resource) {
1863 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug"),
1864 "ResourceProvider::UnmapPixelBuffer");
1866 DCHECK(resource->origin == Resource::Internal);
1867 DCHECK_EQ(resource->exported_count, 0);
1868 DCHECK(!resource->image_id);
1870 DCHECK_EQ(GLTexture, resource->type);
1871 GLES2Interface* gl = ContextGL();
1873 DCHECK(resource->gl_pixel_buffer_id);
1874 gl->BindBuffer(GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM,
1875 resource->gl_pixel_buffer_id);
1876 gl->UnmapBufferCHROMIUM(GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM);
1877 gl->BindBuffer(GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM, 0);
1880 GLenum ResourceProvider::BindForSampling(
1881 ResourceProvider::ResourceId resource_id,
1884 DCHECK(thread_checker_.CalledOnValidThread());
1885 GLES2Interface* gl = ContextGL();
1886 ResourceMap::iterator it = resources_.find(resource_id);
1887 DCHECK(it != resources_.end());
1888 Resource* resource = &it->second;
1889 DCHECK(resource->lock_for_read_count);
1890 DCHECK(!resource->locked_for_write || resource->set_pixels_completion_forced);
1892 ScopedSetActiveTexture scoped_active_tex(gl, unit);
1893 GLenum target = resource->target;
1894 GLC(gl, gl->BindTexture(target, resource->gl_id));
1895 if (filter != resource->filter) {
1896 GLC(gl, gl->TexParameteri(target, GL_TEXTURE_MIN_FILTER, filter));
1897 GLC(gl, gl->TexParameteri(target, GL_TEXTURE_MAG_FILTER, filter));
1898 resource->filter = filter;
1901 if (resource->image_id && resource->dirty_image)
1902 BindImageForSampling(resource);
1907 void ResourceProvider::BeginSetPixels(ResourceId id) {
1908 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug"),
1909 "ResourceProvider::BeginSetPixels");
1911 Resource* resource = GetResource(id);
1912 DCHECK(!resource->pending_set_pixels);
1914 LazyCreate(resource);
1915 DCHECK(resource->origin == Resource::Internal);
1916 DCHECK(resource->gl_id || resource->allocated);
1917 DCHECK(ReadLockFenceHasPassed(resource));
1918 DCHECK(!resource->image_id);
1920 bool allocate = !resource->allocated;
1921 resource->allocated = true;
1924 DCHECK_EQ(GLTexture, resource->type);
1925 DCHECK(resource->gl_id);
1926 GLES2Interface* gl = ContextGL();
1928 DCHECK(resource->gl_pixel_buffer_id);
1929 DCHECK_EQ(resource->target, static_cast<GLenum>(GL_TEXTURE_2D));
1930 gl->BindTexture(GL_TEXTURE_2D, resource->gl_id);
1931 gl->BindBuffer(GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM,
1932 resource->gl_pixel_buffer_id);
1933 if (!resource->gl_upload_query_id)
1934 gl->GenQueriesEXT(1, &resource->gl_upload_query_id);
1935 gl->BeginQueryEXT(GL_ASYNC_PIXEL_UNPACK_COMPLETED_CHROMIUM,
1936 resource->gl_upload_query_id);
1938 gl->AsyncTexImage2DCHROMIUM(GL_TEXTURE_2D,
1940 GLInternalFormat(resource->format),
1941 resource->size.width(),
1942 resource->size.height(),
1944 GLDataFormat(resource->format),
1945 GLDataType(resource->format),
1948 gl->AsyncTexSubImage2DCHROMIUM(GL_TEXTURE_2D,
1952 resource->size.width(),
1953 resource->size.height(),
1954 GLDataFormat(resource->format),
1955 GLDataType(resource->format),
1958 gl->EndQueryEXT(GL_ASYNC_PIXEL_UNPACK_COMPLETED_CHROMIUM);
1959 gl->BindBuffer(GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM, 0);
1961 resource->pending_set_pixels = true;
1962 resource->set_pixels_completion_forced = false;
1965 void ResourceProvider::ForceSetPixelsToComplete(ResourceId id) {
1966 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug"),
1967 "ResourceProvider::ForceSetPixelsToComplete");
1969 Resource* resource = GetResource(id);
1970 DCHECK(resource->locked_for_write);
1971 DCHECK(resource->pending_set_pixels);
1972 DCHECK(!resource->set_pixels_completion_forced);
1974 if (resource->gl_id) {
1975 GLES2Interface* gl = ContextGL();
1976 GLC(gl, gl->BindTexture(GL_TEXTURE_2D, resource->gl_id));
1977 GLC(gl, gl->WaitAsyncTexImage2DCHROMIUM(GL_TEXTURE_2D));
1978 GLC(gl, gl->BindTexture(GL_TEXTURE_2D, 0));
1981 resource->set_pixels_completion_forced = true;
1984 bool ResourceProvider::DidSetPixelsComplete(ResourceId id) {
1985 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug"),
1986 "ResourceProvider::DidSetPixelsComplete");
1988 Resource* resource = GetResource(id);
1989 DCHECK(resource->locked_for_write);
1990 DCHECK(resource->pending_set_pixels);
1992 if (resource->gl_id) {
1993 GLES2Interface* gl = ContextGL();
1995 DCHECK(resource->gl_upload_query_id);
1996 GLuint complete = 1;
1997 gl->GetQueryObjectuivEXT(
1998 resource->gl_upload_query_id, GL_QUERY_RESULT_AVAILABLE_EXT, &complete);
2003 resource->pending_set_pixels = false;
2009 void ResourceProvider::CreateForTesting(ResourceId id) {
2010 LazyCreate(GetResource(id));
2013 GLenum ResourceProvider::TargetForTesting(ResourceId id) {
2014 Resource* resource = GetResource(id);
2015 return resource->target;
2018 void ResourceProvider::LazyCreate(Resource* resource) {
2019 if (resource->type != GLTexture || resource->origin != Resource::Internal)
2022 if (resource->gl_id)
2025 DCHECK(resource->texture_pool);
2026 DCHECK(resource->origin == Resource::Internal);
2027 DCHECK(!resource->mailbox.IsValid());
2028 resource->gl_id = texture_id_allocator_->NextId();
2030 GLES2Interface* gl = ContextGL();
2033 // Create and set texture properties. Allocation is delayed until needed.
2034 GLC(gl, gl->BindTexture(resource->target, resource->gl_id));
2036 gl->TexParameteri(resource->target, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
2038 gl->TexParameteri(resource->target, GL_TEXTURE_MAG_FILTER, GL_LINEAR));
2041 resource->target, GL_TEXTURE_WRAP_S, resource->wrap_mode));
2044 resource->target, GL_TEXTURE_WRAP_T, resource->wrap_mode));
2047 resource->target, GL_TEXTURE_POOL_CHROMIUM, resource->texture_pool));
2048 if (use_texture_usage_hint_ && resource->hint == TextureUsageFramebuffer) {
2050 gl->TexParameteri(resource->target,
2051 GL_TEXTURE_USAGE_ANGLE,
2052 GL_FRAMEBUFFER_ATTACHMENT_ANGLE));
2056 void ResourceProvider::AllocateForTesting(ResourceId id) {
2057 LazyAllocate(GetResource(id));
2060 void ResourceProvider::LazyAllocate(Resource* resource) {
2062 LazyCreate(resource);
2064 DCHECK(resource->gl_id || resource->allocated);
2065 if (resource->allocated || !resource->gl_id)
2067 resource->allocated = true;
2068 GLES2Interface* gl = ContextGL();
2069 gfx::Size& size = resource->size;
2070 DCHECK_EQ(resource->target, static_cast<GLenum>(GL_TEXTURE_2D));
2071 ResourceFormat format = resource->format;
2072 GLC(gl, gl->BindTexture(GL_TEXTURE_2D, resource->gl_id));
2073 if (use_texture_storage_ext_ && IsFormatSupportedForStorage(format) &&
2074 resource->hint != TextureUsageFramebuffer) {
2075 GLenum storage_format = TextureToStorageFormat(format);
2077 gl->TexStorage2DEXT(
2078 GL_TEXTURE_2D, 1, storage_format, size.width(), size.height()));
2080 // ETC1 does not support preallocation.
2081 if (format != ETC1) {
2083 gl->TexImage2D(GL_TEXTURE_2D,
2085 GLInternalFormat(format),
2089 GLDataFormat(format),
2096 void ResourceProvider::BindImageForSampling(Resource* resource) {
2097 GLES2Interface* gl = ContextGL();
2098 DCHECK(resource->gl_id);
2099 DCHECK(resource->image_id);
2101 // Release image currently bound to texture.
2102 if (resource->bound_image_id)
2103 gl->ReleaseTexImage2DCHROMIUM(resource->target, resource->bound_image_id);
2104 gl->BindTexImage2DCHROMIUM(resource->target, resource->image_id);
2105 resource->bound_image_id = resource->image_id;
2106 resource->dirty_image = false;
2109 void ResourceProvider::EnableReadLockFences(ResourceProvider::ResourceId id) {
2110 Resource* resource = GetResource(id);
2111 resource->read_lock_fences_enabled = true;
2114 void ResourceProvider::AcquireImage(Resource* resource) {
2115 DCHECK(resource->origin == Resource::Internal);
2116 DCHECK_EQ(resource->exported_count, 0);
2118 if (resource->type != GLTexture)
2121 if (resource->image_id)
2124 resource->allocated = true;
2125 GLES2Interface* gl = ContextGL();
2127 resource->image_id =
2128 gl->CreateImageCHROMIUM(resource->size.width(),
2129 resource->size.height(),
2130 TextureToStorageFormat(resource->format),
2131 GL_IMAGE_MAP_CHROMIUM);
2132 DCHECK(resource->image_id);
2135 void ResourceProvider::ReleaseImage(Resource* resource) {
2136 DCHECK(resource->origin == Resource::Internal);
2137 DCHECK_EQ(resource->exported_count, 0);
2139 if (!resource->image_id)
2142 GLES2Interface* gl = ContextGL();
2144 gl->DestroyImageCHROMIUM(resource->image_id);
2145 resource->image_id = 0;
2146 resource->bound_image_id = 0;
2147 resource->dirty_image = false;
2148 resource->allocated = false;
2151 uint8_t* ResourceProvider::MapImage(const Resource* resource, int* stride) {
2152 DCHECK(ReadLockFenceHasPassed(resource));
2153 DCHECK(resource->origin == Resource::Internal);
2154 DCHECK_EQ(resource->exported_count, 0);
2156 if (resource->type == GLTexture) {
2157 DCHECK(resource->image_id);
2158 GLES2Interface* gl = ContextGL();
2160 // MapImageCHROMIUM should be called prior to GetImageParameterivCHROMIUM.
2162 static_cast<uint8_t*>(gl->MapImageCHROMIUM(resource->image_id));
2163 gl->GetImageParameterivCHROMIUM(
2164 resource->image_id, GL_IMAGE_ROWBYTES_CHROMIUM, stride);
2167 DCHECK_EQ(Bitmap, resource->type);
2169 return resource->pixels;
2172 void ResourceProvider::UnmapImage(const Resource* resource) {
2173 DCHECK(resource->origin == Resource::Internal);
2174 DCHECK_EQ(resource->exported_count, 0);
2176 if (resource->image_id) {
2177 GLES2Interface* gl = ContextGL();
2179 gl->UnmapImageCHROMIUM(resource->image_id);
2183 void ResourceProvider::CopyResource(ResourceId source_id, ResourceId dest_id) {
2184 TRACE_EVENT0("cc", "ResourceProvider::CopyResource");
2186 Resource* source_resource = GetResource(source_id);
2187 DCHECK(!source_resource->lock_for_read_count);
2188 DCHECK(source_resource->origin == Resource::Internal);
2189 DCHECK_EQ(source_resource->exported_count, 0);
2190 DCHECK(source_resource->allocated);
2191 LazyCreate(source_resource);
2193 Resource* dest_resource = GetResource(dest_id);
2194 DCHECK(!dest_resource->locked_for_write);
2195 DCHECK(!dest_resource->lock_for_read_count);
2196 DCHECK(dest_resource->origin == Resource::Internal);
2197 DCHECK_EQ(dest_resource->exported_count, 0);
2198 LazyCreate(dest_resource);
2200 DCHECK_EQ(source_resource->type, dest_resource->type);
2201 DCHECK_EQ(source_resource->format, dest_resource->format);
2202 DCHECK(source_resource->size == dest_resource->size);
2204 if (source_resource->type == GLTexture) {
2205 GLES2Interface* gl = ContextGL();
2207 if (source_resource->image_id && source_resource->dirty_image) {
2208 gl->BindTexture(source_resource->target, source_resource->gl_id);
2209 BindImageForSampling(source_resource);
2211 DCHECK(use_sync_query_) << "CHROMIUM_sync_query extension missing";
2212 if (!source_resource->gl_read_lock_query_id)
2213 gl->GenQueriesEXT(1, &source_resource->gl_read_lock_query_id);
2214 gl->BeginQueryEXT(GL_COMMANDS_COMPLETED_CHROMIUM,
2215 source_resource->gl_read_lock_query_id);
2216 DCHECK(!dest_resource->image_id);
2217 dest_resource->allocated = true;
2218 gl->CopyTextureCHROMIUM(dest_resource->target,
2219 source_resource->gl_id,
2220 dest_resource->gl_id,
2222 GLInternalFormat(dest_resource->format),
2223 GLDataType(dest_resource->format));
2224 // End query and create a read lock fence that will prevent access to
2225 // source resource until CopyTextureCHROMIUM command has completed.
2226 gl->EndQueryEXT(GL_COMMANDS_COMPLETED_CHROMIUM);
2227 source_resource->read_lock_fence = make_scoped_refptr(
2228 new QueryFence(gl, source_resource->gl_read_lock_query_id));
2230 DCHECK_EQ(Bitmap, source_resource->type);
2231 DCHECK_EQ(RGBA_8888, source_resource->format);
2232 LazyAllocate(dest_resource);
2234 size_t bytes = SharedBitmap::CheckedSizeInBytes(source_resource->size);
2235 memcpy(dest_resource->pixels, source_resource->pixels, bytes);
2239 GLint ResourceProvider::GetActiveTextureUnit(GLES2Interface* gl) {
2240 GLint active_unit = 0;
2241 gl->GetIntegerv(GL_ACTIVE_TEXTURE, &active_unit);
2245 GLES2Interface* ResourceProvider::ContextGL() const {
2246 ContextProvider* context_provider = output_surface_->context_provider();
2247 return context_provider ? context_provider->ContextGL() : NULL;
2250 class GrContext* ResourceProvider::GrContext() const {
2251 ContextProvider* context_provider = output_surface_->context_provider();
2252 return context_provider ? context_provider->GrContext() : NULL;