Partially componentize chrome/common/variations/variations_util.{cc,h}.
[chromium-blink-merge.git] / cc / resources / resource_provider.cc
blob848524f014356e3b2bb49e947ed0fed61aa9ddb0
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"
7 #include <algorithm>
8 #include <limits>
10 #include "base/atomic_sequence_num.h"
11 #include "base/containers/hash_tables.h"
12 #include "base/metrics/histogram.h"
13 #include "base/numerics/safe_math.h"
14 #include "base/stl_util.h"
15 #include "base/strings/string_split.h"
16 #include "base/strings/string_util.h"
17 #include "base/strings/stringprintf.h"
18 #include "base/thread_task_runner_handle.h"
19 #include "base/trace_event/memory_dump_manager.h"
20 #include "base/trace_event/trace_event.h"
21 #include "cc/resources/platform_color.h"
22 #include "cc/resources/resource_util.h"
23 #include "cc/resources/returned_resource.h"
24 #include "cc/resources/shared_bitmap_manager.h"
25 #include "cc/resources/transferable_resource.h"
26 #include "gpu/GLES2/gl2extchromium.h"
27 #include "gpu/command_buffer/client/gles2_interface.h"
28 #include "gpu/command_buffer/client/gpu_memory_buffer_manager.h"
29 #include "third_party/khronos/GLES2/gl2.h"
30 #include "third_party/khronos/GLES2/gl2ext.h"
31 #include "third_party/skia/include/core/SkSurface.h"
32 #include "third_party/skia/include/gpu/GrContext.h"
33 #include "third_party/skia/include/gpu/GrTextureProvider.h"
34 #include "ui/gfx/geometry/rect.h"
35 #include "ui/gfx/geometry/vector2d.h"
36 #include "ui/gl/trace_util.h"
38 using gpu::gles2::GLES2Interface;
40 namespace cc {
42 class IdAllocator {
43 public:
44 virtual ~IdAllocator() {}
46 virtual GLuint NextId() = 0;
48 protected:
49 IdAllocator(GLES2Interface* gl, size_t id_allocation_chunk_size)
50 : gl_(gl),
51 id_allocation_chunk_size_(id_allocation_chunk_size),
52 ids_(new GLuint[id_allocation_chunk_size]),
53 next_id_index_(id_allocation_chunk_size) {
54 DCHECK(id_allocation_chunk_size_);
55 DCHECK_LE(id_allocation_chunk_size_,
56 static_cast<size_t>(std::numeric_limits<int>::max()));
59 GLES2Interface* gl_;
60 const size_t id_allocation_chunk_size_;
61 scoped_ptr<GLuint[]> ids_;
62 size_t next_id_index_;
65 namespace {
67 GLenum TextureToStorageFormat(ResourceFormat format) {
68 GLenum storage_format = GL_RGBA8_OES;
69 switch (format) {
70 case RGBA_8888:
71 break;
72 case BGRA_8888:
73 storage_format = GL_BGRA8_EXT;
74 break;
75 case RGBA_4444:
76 case ALPHA_8:
77 case LUMINANCE_8:
78 case RGB_565:
79 case ETC1:
80 case RED_8:
81 NOTREACHED();
82 break;
85 return storage_format;
88 bool IsFormatSupportedForStorage(ResourceFormat format, bool use_bgra) {
89 switch (format) {
90 case RGBA_8888:
91 return true;
92 case BGRA_8888:
93 return use_bgra;
94 case RGBA_4444:
95 case ALPHA_8:
96 case LUMINANCE_8:
97 case RGB_565:
98 case ETC1:
99 case RED_8:
100 return false;
102 return false;
105 GrPixelConfig ToGrPixelConfig(ResourceFormat format) {
106 switch (format) {
107 case RGBA_8888:
108 return kRGBA_8888_GrPixelConfig;
109 case BGRA_8888:
110 return kBGRA_8888_GrPixelConfig;
111 case RGBA_4444:
112 return kRGBA_4444_GrPixelConfig;
113 default:
114 break;
116 DCHECK(false) << "Unsupported resource format.";
117 return kSkia8888_GrPixelConfig;
120 class ScopedSetActiveTexture {
121 public:
122 ScopedSetActiveTexture(GLES2Interface* gl, GLenum unit)
123 : gl_(gl), unit_(unit) {
124 DCHECK_EQ(GL_TEXTURE0, ResourceProvider::GetActiveTextureUnit(gl_));
126 if (unit_ != GL_TEXTURE0)
127 gl_->ActiveTexture(unit_);
130 ~ScopedSetActiveTexture() {
131 // Active unit being GL_TEXTURE0 is effectively the ground state.
132 if (unit_ != GL_TEXTURE0)
133 gl_->ActiveTexture(GL_TEXTURE0);
136 private:
137 GLES2Interface* gl_;
138 GLenum unit_;
141 class TextureIdAllocator : public IdAllocator {
142 public:
143 TextureIdAllocator(GLES2Interface* gl,
144 size_t texture_id_allocation_chunk_size)
145 : IdAllocator(gl, texture_id_allocation_chunk_size) {}
146 ~TextureIdAllocator() override {
147 gl_->DeleteTextures(
148 static_cast<int>(id_allocation_chunk_size_ - next_id_index_),
149 ids_.get() + next_id_index_);
152 // Overridden from IdAllocator:
153 GLuint NextId() override {
154 if (next_id_index_ == id_allocation_chunk_size_) {
155 gl_->GenTextures(static_cast<int>(id_allocation_chunk_size_), ids_.get());
156 next_id_index_ = 0;
159 return ids_[next_id_index_++];
162 private:
163 DISALLOW_COPY_AND_ASSIGN(TextureIdAllocator);
166 class BufferIdAllocator : public IdAllocator {
167 public:
168 BufferIdAllocator(GLES2Interface* gl, size_t buffer_id_allocation_chunk_size)
169 : IdAllocator(gl, buffer_id_allocation_chunk_size) {}
170 ~BufferIdAllocator() override {
171 gl_->DeleteBuffers(
172 static_cast<int>(id_allocation_chunk_size_ - next_id_index_),
173 ids_.get() + next_id_index_);
176 // Overridden from IdAllocator:
177 GLuint NextId() override {
178 if (next_id_index_ == id_allocation_chunk_size_) {
179 gl_->GenBuffers(static_cast<int>(id_allocation_chunk_size_), ids_.get());
180 next_id_index_ = 0;
183 return ids_[next_id_index_++];
186 private:
187 DISALLOW_COPY_AND_ASSIGN(BufferIdAllocator);
190 // Generates process-unique IDs to use for tracing a ResourceProvider's
191 // resources.
192 base::StaticAtomicSequenceNumber g_next_resource_provider_tracing_id;
194 } // namespace
196 ResourceProvider::Resource::~Resource() {}
198 ResourceProvider::Resource::Resource(GLuint texture_id,
199 const gfx::Size& size,
200 Origin origin,
201 GLenum target,
202 GLenum filter,
203 GLenum texture_pool,
204 GLint wrap_mode,
205 TextureHint hint,
206 ResourceFormat format)
207 : child_id(0),
208 gl_id(texture_id),
209 gl_pixel_buffer_id(0),
210 gl_upload_query_id(0),
211 gl_read_lock_query_id(0),
212 pixels(NULL),
213 lock_for_read_count(0),
214 imported_count(0),
215 exported_count(0),
216 dirty_image(false),
217 locked_for_write(false),
218 lost(false),
219 marked_for_deletion(false),
220 pending_set_pixels(false),
221 set_pixels_completion_forced(false),
222 allocated(false),
223 read_lock_fences_enabled(false),
224 has_shared_bitmap_id(false),
225 read_lock_fence(NULL),
226 size(size),
227 origin(origin),
228 target(target),
229 original_filter(filter),
230 filter(filter),
231 image_id(0),
232 bound_image_id(0),
233 texture_pool(texture_pool),
234 wrap_mode(wrap_mode),
235 hint(hint),
236 type(RESOURCE_TYPE_GL_TEXTURE),
237 format(format),
238 shared_bitmap(NULL),
239 gpu_memory_buffer(NULL) {
240 DCHECK(wrap_mode == GL_CLAMP_TO_EDGE || wrap_mode == GL_REPEAT);
241 DCHECK_EQ(origin == INTERNAL, !!texture_pool);
244 ResourceProvider::Resource::Resource(uint8_t* pixels,
245 SharedBitmap* bitmap,
246 const gfx::Size& size,
247 Origin origin,
248 GLenum filter,
249 GLint wrap_mode)
250 : child_id(0),
251 gl_id(0),
252 gl_pixel_buffer_id(0),
253 gl_upload_query_id(0),
254 gl_read_lock_query_id(0),
255 pixels(pixels),
256 lock_for_read_count(0),
257 imported_count(0),
258 exported_count(0),
259 dirty_image(false),
260 locked_for_write(false),
261 lost(false),
262 marked_for_deletion(false),
263 pending_set_pixels(false),
264 set_pixels_completion_forced(false),
265 allocated(false),
266 read_lock_fences_enabled(false),
267 has_shared_bitmap_id(!!bitmap),
268 read_lock_fence(NULL),
269 size(size),
270 origin(origin),
271 target(0),
272 original_filter(filter),
273 filter(filter),
274 image_id(0),
275 bound_image_id(0),
276 texture_pool(0),
277 wrap_mode(wrap_mode),
278 hint(TEXTURE_HINT_IMMUTABLE),
279 type(RESOURCE_TYPE_BITMAP),
280 format(RGBA_8888),
281 shared_bitmap(bitmap),
282 gpu_memory_buffer(NULL) {
283 DCHECK(wrap_mode == GL_CLAMP_TO_EDGE || wrap_mode == GL_REPEAT);
284 DCHECK(origin == DELEGATED || pixels);
285 if (bitmap)
286 shared_bitmap_id = bitmap->id();
289 ResourceProvider::Resource::Resource(const SharedBitmapId& bitmap_id,
290 const gfx::Size& size,
291 Origin origin,
292 GLenum filter,
293 GLint wrap_mode)
294 : child_id(0),
295 gl_id(0),
296 gl_pixel_buffer_id(0),
297 gl_upload_query_id(0),
298 gl_read_lock_query_id(0),
299 pixels(NULL),
300 lock_for_read_count(0),
301 imported_count(0),
302 exported_count(0),
303 dirty_image(false),
304 locked_for_write(false),
305 lost(false),
306 marked_for_deletion(false),
307 pending_set_pixels(false),
308 set_pixels_completion_forced(false),
309 allocated(false),
310 read_lock_fences_enabled(false),
311 has_shared_bitmap_id(true),
312 read_lock_fence(NULL),
313 size(size),
314 origin(origin),
315 target(0),
316 original_filter(filter),
317 filter(filter),
318 image_id(0),
319 bound_image_id(0),
320 texture_pool(0),
321 wrap_mode(wrap_mode),
322 hint(TEXTURE_HINT_IMMUTABLE),
323 type(RESOURCE_TYPE_BITMAP),
324 format(RGBA_8888),
325 shared_bitmap_id(bitmap_id),
326 shared_bitmap(NULL),
327 gpu_memory_buffer(NULL) {
328 DCHECK(wrap_mode == GL_CLAMP_TO_EDGE || wrap_mode == GL_REPEAT);
331 ResourceProvider::Child::Child()
332 : marked_for_deletion(false), needs_sync_points(true) {
335 ResourceProvider::Child::~Child() {}
337 scoped_ptr<ResourceProvider> ResourceProvider::Create(
338 OutputSurface* output_surface,
339 SharedBitmapManager* shared_bitmap_manager,
340 gpu::GpuMemoryBufferManager* gpu_memory_buffer_manager,
341 BlockingTaskRunner* blocking_main_thread_task_runner,
342 int highp_threshold_min,
343 bool use_rgba_4444_texture_format,
344 size_t id_allocation_chunk_size,
345 const std::vector<unsigned>& use_image_texture_targets) {
346 scoped_ptr<ResourceProvider> resource_provider(new ResourceProvider(
347 output_surface, shared_bitmap_manager, gpu_memory_buffer_manager,
348 blocking_main_thread_task_runner, highp_threshold_min,
349 use_rgba_4444_texture_format, id_allocation_chunk_size,
350 use_image_texture_targets));
351 resource_provider->Initialize();
352 return resource_provider;
355 ResourceProvider::~ResourceProvider() {
356 base::trace_event::MemoryDumpManager::GetInstance()->UnregisterDumpProvider(
357 this);
359 while (!children_.empty())
360 DestroyChildInternal(children_.begin(), FOR_SHUTDOWN);
361 while (!resources_.empty())
362 DeleteResourceInternal(resources_.begin(), FOR_SHUTDOWN);
364 GLES2Interface* gl = ContextGL();
365 if (default_resource_type_ != RESOURCE_TYPE_GL_TEXTURE) {
366 // We are not in GL mode, but double check before returning.
367 DCHECK(!gl);
368 return;
371 DCHECK(gl);
372 #if DCHECK_IS_ON()
373 // Check that all GL resources has been deleted.
374 for (ResourceMap::const_iterator itr = resources_.begin();
375 itr != resources_.end(); ++itr) {
376 DCHECK_NE(RESOURCE_TYPE_GL_TEXTURE, itr->second.type);
378 #endif // DCHECK_IS_ON()
380 texture_id_allocator_ = nullptr;
381 buffer_id_allocator_ = nullptr;
382 gl->Finish();
385 bool ResourceProvider::InUseByConsumer(ResourceId id) {
386 Resource* resource = GetResource(id);
387 return resource->lock_for_read_count > 0 || resource->exported_count > 0 ||
388 resource->lost;
391 bool ResourceProvider::IsLost(ResourceId id) {
392 Resource* resource = GetResource(id);
393 return resource->lost;
396 void ResourceProvider::LoseResourceForTesting(ResourceId id) {
397 Resource* resource = GetResource(id);
398 DCHECK(resource);
399 resource->lost = true;
402 ResourceId ResourceProvider::CreateResource(const gfx::Size& size,
403 GLint wrap_mode,
404 TextureHint hint,
405 ResourceFormat format) {
406 DCHECK(!size.IsEmpty());
407 switch (default_resource_type_) {
408 case RESOURCE_TYPE_GL_TEXTURE:
409 return CreateGLTexture(size,
410 GL_TEXTURE_2D,
411 GL_TEXTURE_POOL_UNMANAGED_CHROMIUM,
412 wrap_mode,
413 hint,
414 format);
415 case RESOURCE_TYPE_BITMAP:
416 DCHECK_EQ(RGBA_8888, format);
417 return CreateBitmap(size, wrap_mode);
420 LOG(FATAL) << "Invalid default resource type.";
421 return 0;
424 ResourceId ResourceProvider::CreateManagedResource(const gfx::Size& size,
425 GLenum target,
426 GLint wrap_mode,
427 TextureHint hint,
428 ResourceFormat format) {
429 DCHECK(!size.IsEmpty());
430 switch (default_resource_type_) {
431 case RESOURCE_TYPE_GL_TEXTURE:
432 return CreateGLTexture(size,
433 target,
434 GL_TEXTURE_POOL_MANAGED_CHROMIUM,
435 wrap_mode,
436 hint,
437 format);
438 case RESOURCE_TYPE_BITMAP:
439 DCHECK_EQ(RGBA_8888, format);
440 return CreateBitmap(size, wrap_mode);
443 LOG(FATAL) << "Invalid default resource type.";
444 return 0;
447 ResourceId ResourceProvider::CreateGLTexture(const gfx::Size& size,
448 GLenum target,
449 GLenum texture_pool,
450 GLint wrap_mode,
451 TextureHint hint,
452 ResourceFormat format) {
453 DCHECK_LE(size.width(), max_texture_size_);
454 DCHECK_LE(size.height(), max_texture_size_);
455 DCHECK(thread_checker_.CalledOnValidThread());
457 ResourceId id = next_id_++;
458 Resource* resource = InsertResource(
459 id, Resource(0, size, Resource::INTERNAL, target, GL_LINEAR, texture_pool,
460 wrap_mode, hint, format));
461 resource->allocated = false;
462 return id;
465 ResourceId ResourceProvider::CreateBitmap(const gfx::Size& size,
466 GLint wrap_mode) {
467 DCHECK(thread_checker_.CalledOnValidThread());
469 scoped_ptr<SharedBitmap> bitmap =
470 shared_bitmap_manager_->AllocateSharedBitmap(size);
471 uint8_t* pixels = bitmap->pixels();
472 DCHECK(pixels);
474 ResourceId id = next_id_++;
475 Resource* resource =
476 InsertResource(id, Resource(pixels, bitmap.release(), size,
477 Resource::INTERNAL, GL_LINEAR, wrap_mode));
478 resource->allocated = true;
479 return id;
482 ResourceId ResourceProvider::CreateResourceFromIOSurface(
483 const gfx::Size& size,
484 unsigned io_surface_id) {
485 DCHECK(thread_checker_.CalledOnValidThread());
487 ResourceId id = next_id_++;
488 Resource* resource = InsertResource(
489 id, Resource(0, gfx::Size(), Resource::INTERNAL, GL_TEXTURE_RECTANGLE_ARB,
490 GL_LINEAR, GL_TEXTURE_POOL_UNMANAGED_CHROMIUM,
491 GL_CLAMP_TO_EDGE, TEXTURE_HINT_IMMUTABLE, RGBA_8888));
492 LazyCreate(resource);
493 GLES2Interface* gl = ContextGL();
494 DCHECK(gl);
495 gl->BindTexture(GL_TEXTURE_RECTANGLE_ARB, resource->gl_id);
496 gl->TexImageIOSurface2DCHROMIUM(
497 GL_TEXTURE_RECTANGLE_ARB, size.width(), size.height(), io_surface_id, 0);
498 resource->allocated = true;
499 return id;
502 ResourceId ResourceProvider::CreateResourceFromTextureMailbox(
503 const TextureMailbox& mailbox,
504 scoped_ptr<SingleReleaseCallbackImpl> release_callback_impl,
505 bool read_lock_fences_enabled) {
506 DCHECK(thread_checker_.CalledOnValidThread());
507 // Just store the information. Mailbox will be consumed in LockForRead().
508 ResourceId id = next_id_++;
509 DCHECK(mailbox.IsValid());
510 Resource* resource = nullptr;
511 if (mailbox.IsTexture()) {
512 resource = InsertResource(
513 id, Resource(0, gfx::Size(), Resource::EXTERNAL, mailbox.target(),
514 mailbox.nearest_neighbor() ? GL_NEAREST : GL_LINEAR, 0,
515 GL_CLAMP_TO_EDGE, TEXTURE_HINT_IMMUTABLE, RGBA_8888));
516 } else {
517 DCHECK(mailbox.IsSharedMemory());
518 SharedBitmap* shared_bitmap = mailbox.shared_bitmap();
519 uint8_t* pixels = shared_bitmap->pixels();
520 DCHECK(pixels);
521 resource = InsertResource(
522 id, Resource(pixels, shared_bitmap, mailbox.size_in_pixels(),
523 Resource::EXTERNAL, GL_LINEAR, GL_CLAMP_TO_EDGE));
525 resource->allocated = true;
526 resource->mailbox = mailbox;
527 resource->release_callback_impl =
528 base::Bind(&SingleReleaseCallbackImpl::Run,
529 base::Owned(release_callback_impl.release()));
530 resource->read_lock_fences_enabled = read_lock_fences_enabled;
531 return id;
534 ResourceId ResourceProvider::CreateResourceFromTextureMailbox(
535 const TextureMailbox& mailbox,
536 scoped_ptr<SingleReleaseCallbackImpl> release_callback_impl) {
537 return CreateResourceFromTextureMailbox(mailbox, release_callback_impl.Pass(),
538 false);
541 void ResourceProvider::DeleteResource(ResourceId id) {
542 DCHECK(thread_checker_.CalledOnValidThread());
543 ResourceMap::iterator it = resources_.find(id);
544 CHECK(it != resources_.end());
545 Resource* resource = &it->second;
546 DCHECK(!resource->marked_for_deletion);
547 DCHECK_EQ(resource->imported_count, 0);
548 DCHECK(resource->pending_set_pixels || !resource->locked_for_write);
550 if (resource->exported_count > 0 || resource->lock_for_read_count > 0 ||
551 !ReadLockFenceHasPassed(resource)) {
552 resource->marked_for_deletion = true;
553 return;
554 } else {
555 DeleteResourceInternal(it, NORMAL);
559 void ResourceProvider::DeleteResourceInternal(ResourceMap::iterator it,
560 DeleteStyle style) {
561 TRACE_EVENT0("cc", "ResourceProvider::DeleteResourceInternal");
562 Resource* resource = &it->second;
563 bool lost_resource = resource->lost;
565 DCHECK(resource->exported_count == 0 || style != NORMAL);
566 if (style == FOR_SHUTDOWN && resource->exported_count > 0)
567 lost_resource = true;
569 if (resource->image_id) {
570 DCHECK(resource->origin == Resource::INTERNAL);
571 GLES2Interface* gl = ContextGL();
572 DCHECK(gl);
573 gl->DestroyImageCHROMIUM(resource->image_id);
575 if (resource->gl_upload_query_id) {
576 DCHECK(resource->origin == Resource::INTERNAL);
577 GLES2Interface* gl = ContextGL();
578 DCHECK(gl);
579 gl->DeleteQueriesEXT(1, &resource->gl_upload_query_id);
581 if (resource->gl_read_lock_query_id) {
582 DCHECK(resource->origin == Resource::INTERNAL);
583 GLES2Interface* gl = ContextGL();
584 DCHECK(gl);
585 gl->DeleteQueriesEXT(1, &resource->gl_read_lock_query_id);
587 if (resource->gl_pixel_buffer_id) {
588 DCHECK(resource->origin == Resource::INTERNAL);
589 GLES2Interface* gl = ContextGL();
590 DCHECK(gl);
591 gl->DeleteBuffers(1, &resource->gl_pixel_buffer_id);
593 if (resource->origin == Resource::EXTERNAL) {
594 DCHECK(resource->mailbox.IsValid());
595 GLuint sync_point = resource->mailbox.sync_point();
596 if (resource->type == RESOURCE_TYPE_GL_TEXTURE) {
597 DCHECK(resource->mailbox.IsTexture());
598 lost_resource |= lost_output_surface_;
599 GLES2Interface* gl = ContextGL();
600 DCHECK(gl);
601 if (resource->gl_id) {
602 gl->DeleteTextures(1, &resource->gl_id);
603 resource->gl_id = 0;
604 if (!lost_resource)
605 sync_point = gl->InsertSyncPointCHROMIUM();
607 } else {
608 DCHECK(resource->mailbox.IsSharedMemory());
609 resource->shared_bitmap = nullptr;
610 resource->pixels = nullptr;
612 resource->release_callback_impl.Run(
613 sync_point, lost_resource, blocking_main_thread_task_runner_);
615 if (resource->gl_id) {
616 GLES2Interface* gl = ContextGL();
617 DCHECK(gl);
618 gl->DeleteTextures(1, &resource->gl_id);
619 resource->gl_id = 0;
621 if (resource->shared_bitmap) {
622 DCHECK(resource->origin != Resource::EXTERNAL);
623 DCHECK_EQ(RESOURCE_TYPE_BITMAP, resource->type);
624 delete resource->shared_bitmap;
625 resource->pixels = NULL;
627 if (resource->pixels) {
628 DCHECK(resource->origin == Resource::INTERNAL);
629 delete[] resource->pixels;
630 resource->pixels = NULL;
632 if (resource->gpu_memory_buffer) {
633 DCHECK(resource->origin == Resource::INTERNAL);
634 delete resource->gpu_memory_buffer;
635 resource->gpu_memory_buffer = NULL;
637 resources_.erase(it);
640 ResourceProvider::ResourceType ResourceProvider::GetResourceType(
641 ResourceId id) {
642 return GetResource(id)->type;
645 void ResourceProvider::CopyToResource(ResourceId id,
646 const uint8_t* image,
647 const gfx::Size& image_size) {
648 Resource* resource = GetResource(id);
649 DCHECK(!resource->locked_for_write);
650 DCHECK(!resource->lock_for_read_count);
651 DCHECK(resource->origin == Resource::INTERNAL);
652 DCHECK_EQ(resource->exported_count, 0);
653 DCHECK(ReadLockFenceHasPassed(resource));
654 LazyAllocate(resource);
656 DCHECK_EQ(image_size.width(), resource->size.width());
657 DCHECK_EQ(image_size.height(), resource->size.height());
659 if (resource->type == RESOURCE_TYPE_BITMAP) {
660 DCHECK_EQ(RESOURCE_TYPE_BITMAP, resource->type);
661 DCHECK(resource->allocated);
662 DCHECK_EQ(RGBA_8888, resource->format);
663 SkImageInfo source_info =
664 SkImageInfo::MakeN32Premul(image_size.width(), image_size.height());
665 size_t image_stride = image_size.width() * 4;
667 ScopedWriteLockSoftware lock(this, id);
668 SkCanvas dest(lock.sk_bitmap());
669 dest.writePixels(source_info, image, image_stride, 0, 0);
670 } else {
671 DCHECK(resource->gl_id);
672 DCHECK(!resource->pending_set_pixels);
673 DCHECK_EQ(resource->target, static_cast<GLenum>(GL_TEXTURE_2D));
674 GLES2Interface* gl = ContextGL();
675 DCHECK(gl);
676 gl->BindTexture(GL_TEXTURE_2D, resource->gl_id);
678 if (resource->format == ETC1) {
679 int image_bytes = ResourceUtil::CheckedSizeInBytes<int>(image_size, ETC1);
680 gl->CompressedTexImage2D(GL_TEXTURE_2D, 0, GLInternalFormat(ETC1),
681 image_size.width(), image_size.height(), 0,
682 image_bytes, image);
683 } else {
684 gl->TexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, image_size.width(),
685 image_size.height(), GLDataFormat(resource->format),
686 GLDataType(resource->format), image);
691 ResourceProvider::Resource* ResourceProvider::InsertResource(
692 ResourceId id,
693 const Resource& resource) {
694 std::pair<ResourceMap::iterator, bool> result =
695 resources_.insert(ResourceMap::value_type(id, resource));
696 DCHECK(result.second);
697 return &result.first->second;
700 ResourceProvider::Resource* ResourceProvider::GetResource(ResourceId id) {
701 DCHECK(thread_checker_.CalledOnValidThread());
702 DCHECK(id);
703 ResourceMap::iterator it = resources_.find(id);
704 DCHECK(it != resources_.end());
705 return &it->second;
708 const ResourceProvider::Resource* ResourceProvider::LockForRead(ResourceId id) {
709 Resource* resource = GetResource(id);
710 DCHECK(!resource->locked_for_write ||
711 resource->set_pixels_completion_forced) <<
712 "locked for write: " << resource->locked_for_write <<
713 " pixels completion forced: " << resource->set_pixels_completion_forced;
714 DCHECK_EQ(resource->exported_count, 0);
715 // Uninitialized! Call SetPixels or LockForWrite first.
716 DCHECK(resource->allocated);
718 LazyCreate(resource);
720 if (resource->type == RESOURCE_TYPE_GL_TEXTURE && !resource->gl_id) {
721 DCHECK(resource->origin != Resource::INTERNAL);
722 DCHECK(resource->mailbox.IsTexture());
724 // Mailbox sync_points must be processed by a call to
725 // WaitSyncPointIfNeeded() prior to calling LockForRead().
726 DCHECK(!resource->mailbox.sync_point());
728 GLES2Interface* gl = ContextGL();
729 DCHECK(gl);
730 resource->gl_id = gl->CreateAndConsumeTextureCHROMIUM(
731 resource->mailbox.target(), resource->mailbox.name());
734 if (!resource->pixels && resource->has_shared_bitmap_id &&
735 shared_bitmap_manager_) {
736 scoped_ptr<SharedBitmap> bitmap =
737 shared_bitmap_manager_->GetSharedBitmapFromId(
738 resource->size, resource->shared_bitmap_id);
739 if (bitmap) {
740 resource->shared_bitmap = bitmap.release();
741 resource->pixels = resource->shared_bitmap->pixels();
745 resource->lock_for_read_count++;
746 if (resource->read_lock_fences_enabled) {
747 if (current_read_lock_fence_.get())
748 current_read_lock_fence_->Set();
749 resource->read_lock_fence = current_read_lock_fence_;
752 return resource;
755 void ResourceProvider::UnlockForRead(ResourceId id) {
756 DCHECK(thread_checker_.CalledOnValidThread());
757 ResourceMap::iterator it = resources_.find(id);
758 CHECK(it != resources_.end());
760 Resource* resource = &it->second;
761 DCHECK_GT(resource->lock_for_read_count, 0);
762 DCHECK_EQ(resource->exported_count, 0);
763 resource->lock_for_read_count--;
764 if (resource->marked_for_deletion && !resource->lock_for_read_count) {
765 if (!resource->child_id) {
766 // The resource belongs to this ResourceProvider, so it can be destroyed.
767 DeleteResourceInternal(it, NORMAL);
768 } else {
769 ChildMap::iterator child_it = children_.find(resource->child_id);
770 ResourceIdArray unused;
771 unused.push_back(id);
772 DeleteAndReturnUnusedResourcesToChild(child_it, NORMAL, unused);
777 ResourceProvider::Resource* ResourceProvider::LockForWrite(ResourceId id) {
778 Resource* resource = GetResource(id);
779 DCHECK(CanLockForWrite(id));
781 resource->locked_for_write = true;
782 return resource;
785 bool ResourceProvider::CanLockForWrite(ResourceId id) {
786 Resource* resource = GetResource(id);
787 return !resource->locked_for_write && !resource->lock_for_read_count &&
788 !resource->exported_count && resource->origin == Resource::INTERNAL &&
789 !resource->lost && ReadLockFenceHasPassed(resource);
792 void ResourceProvider::UnlockForWrite(ResourceProvider::Resource* resource) {
793 DCHECK(resource->locked_for_write);
794 DCHECK_EQ(resource->exported_count, 0);
795 DCHECK(resource->origin == Resource::INTERNAL);
796 resource->locked_for_write = false;
799 void ResourceProvider::EnableReadLockFencesForTesting(ResourceId id) {
800 Resource* resource = GetResource(id);
801 DCHECK(resource);
802 resource->read_lock_fences_enabled = true;
805 ResourceProvider::ScopedReadLockGL::ScopedReadLockGL(
806 ResourceProvider* resource_provider,
807 ResourceId resource_id)
808 : resource_provider_(resource_provider),
809 resource_id_(resource_id),
810 resource_(resource_provider->LockForRead(resource_id)) {
811 DCHECK(resource_);
814 ResourceProvider::ScopedReadLockGL::~ScopedReadLockGL() {
815 resource_provider_->UnlockForRead(resource_id_);
818 ResourceProvider::ScopedSamplerGL::ScopedSamplerGL(
819 ResourceProvider* resource_provider,
820 ResourceId resource_id,
821 GLenum filter)
822 : ScopedReadLockGL(resource_provider, resource_id),
823 unit_(GL_TEXTURE0),
824 target_(resource_provider->BindForSampling(resource_id, unit_, filter)) {
827 ResourceProvider::ScopedSamplerGL::ScopedSamplerGL(
828 ResourceProvider* resource_provider,
829 ResourceId resource_id,
830 GLenum unit,
831 GLenum filter)
832 : ScopedReadLockGL(resource_provider, resource_id),
833 unit_(unit),
834 target_(resource_provider->BindForSampling(resource_id, unit_, filter)) {
837 ResourceProvider::ScopedSamplerGL::~ScopedSamplerGL() {
840 ResourceProvider::ScopedWriteLockGL::ScopedWriteLockGL(
841 ResourceProvider* resource_provider,
842 ResourceId resource_id)
843 : resource_provider_(resource_provider),
844 resource_(resource_provider->LockForWrite(resource_id)) {
845 resource_provider_->LazyAllocate(resource_);
846 texture_id_ = resource_->gl_id;
847 DCHECK(texture_id_);
850 ResourceProvider::ScopedWriteLockGL::~ScopedWriteLockGL() {
851 resource_provider_->UnlockForWrite(resource_);
854 void ResourceProvider::PopulateSkBitmapWithResource(
855 SkBitmap* sk_bitmap, const Resource* resource) {
856 DCHECK_EQ(RGBA_8888, resource->format);
857 SkImageInfo info = SkImageInfo::MakeN32Premul(resource->size.width(),
858 resource->size.height());
859 sk_bitmap->installPixels(info, resource->pixels, info.minRowBytes());
862 ResourceProvider::ScopedReadLockSoftware::ScopedReadLockSoftware(
863 ResourceProvider* resource_provider,
864 ResourceId resource_id)
865 : resource_provider_(resource_provider), resource_id_(resource_id) {
866 const Resource* resource = resource_provider->LockForRead(resource_id);
867 wrap_mode_ = resource->wrap_mode;
868 ResourceProvider::PopulateSkBitmapWithResource(&sk_bitmap_, resource);
871 ResourceProvider::ScopedReadLockSoftware::~ScopedReadLockSoftware() {
872 resource_provider_->UnlockForRead(resource_id_);
875 ResourceProvider::ScopedWriteLockSoftware::ScopedWriteLockSoftware(
876 ResourceProvider* resource_provider,
877 ResourceId resource_id)
878 : resource_provider_(resource_provider),
879 resource_(resource_provider->LockForWrite(resource_id)) {
880 ResourceProvider::PopulateSkBitmapWithResource(&sk_bitmap_, resource_);
881 DCHECK(valid());
884 ResourceProvider::ScopedWriteLockSoftware::~ScopedWriteLockSoftware() {
885 DCHECK(thread_checker_.CalledOnValidThread());
886 resource_provider_->UnlockForWrite(resource_);
889 ResourceProvider::ScopedWriteLockGpuMemoryBuffer::
890 ScopedWriteLockGpuMemoryBuffer(ResourceProvider* resource_provider,
891 ResourceId resource_id)
892 : resource_provider_(resource_provider),
893 resource_(resource_provider->LockForWrite(resource_id)),
894 gpu_memory_buffer_manager_(resource_provider->gpu_memory_buffer_manager_),
895 gpu_memory_buffer_(nullptr),
896 size_(resource_->size),
897 format_(resource_->format) {
898 DCHECK_EQ(RESOURCE_TYPE_GL_TEXTURE, resource_->type);
899 std::swap(gpu_memory_buffer_, resource_->gpu_memory_buffer);
902 ResourceProvider::ScopedWriteLockGpuMemoryBuffer::
903 ~ScopedWriteLockGpuMemoryBuffer() {
904 DCHECK(thread_checker_.CalledOnValidThread());
905 resource_provider_->UnlockForWrite(resource_);
906 if (!gpu_memory_buffer_)
907 return;
909 resource_provider_->LazyCreate(resource_);
911 if (!resource_->image_id) {
912 GLES2Interface* gl = resource_provider_->ContextGL();
913 DCHECK(gl);
915 #if defined(OS_CHROMEOS)
916 // TODO(reveman): GL_COMMANDS_ISSUED_CHROMIUM is used for synchronization
917 // on ChromeOS to avoid some performance issues. This only works with
918 // shared memory backed buffers. crbug.com/436314
919 DCHECK_EQ(gpu_memory_buffer_->GetHandle().type, gfx::SHARED_MEMORY_BUFFER);
920 #endif
922 resource_->image_id = gl->CreateImageCHROMIUM(
923 gpu_memory_buffer_->AsClientBuffer(), size_.width(), size_.height(),
924 GLInternalFormat(resource_->format));
927 std::swap(resource_->gpu_memory_buffer, gpu_memory_buffer_);
928 resource_->allocated = true;
929 resource_->dirty_image = true;
931 // GpuMemoryBuffer provides direct access to the memory used by the GPU.
932 // Read lock fences are required to ensure that we're not trying to map a
933 // buffer that is currently in-use by the GPU.
934 resource_->read_lock_fences_enabled = true;
937 gfx::GpuMemoryBuffer*
938 ResourceProvider::ScopedWriteLockGpuMemoryBuffer::GetGpuMemoryBuffer() {
939 if (gpu_memory_buffer_)
940 return gpu_memory_buffer_;
941 scoped_ptr<gfx::GpuMemoryBuffer> gpu_memory_buffer =
942 gpu_memory_buffer_manager_->AllocateGpuMemoryBuffer(
943 size_, BufferFormat(format_), gfx::BufferUsage::MAP);
944 gpu_memory_buffer_ = gpu_memory_buffer.release();
945 return gpu_memory_buffer_;
948 ResourceProvider::ScopedWriteLockGr::ScopedWriteLockGr(
949 ResourceProvider* resource_provider,
950 ResourceId resource_id)
951 : resource_provider_(resource_provider),
952 resource_(resource_provider->LockForWrite(resource_id)) {
953 DCHECK(thread_checker_.CalledOnValidThread());
954 resource_provider_->LazyAllocate(resource_);
957 ResourceProvider::ScopedWriteLockGr::~ScopedWriteLockGr() {
958 DCHECK(thread_checker_.CalledOnValidThread());
959 DCHECK(resource_->locked_for_write);
960 resource_provider_->UnlockForWrite(resource_);
963 void ResourceProvider::ScopedWriteLockGr::InitSkSurface(
964 bool use_distance_field_text,
965 bool can_use_lcd_text,
966 int msaa_sample_count) {
967 DCHECK(resource_->locked_for_write);
969 GrBackendTextureDesc desc;
970 desc.fFlags = kRenderTarget_GrBackendTextureFlag;
971 desc.fWidth = resource_->size.width();
972 desc.fHeight = resource_->size.height();
973 desc.fConfig = ToGrPixelConfig(resource_->format);
974 desc.fOrigin = kTopLeft_GrSurfaceOrigin;
975 desc.fTextureHandle = resource_->gl_id;
976 desc.fSampleCnt = msaa_sample_count;
978 bool use_worker_context = true;
979 class GrContext* gr_context =
980 resource_provider_->GrContext(use_worker_context);
981 uint32_t flags =
982 use_distance_field_text ? SkSurfaceProps::kUseDistanceFieldFonts_Flag : 0;
983 // Use unknown pixel geometry to disable LCD text.
984 SkSurfaceProps surface_props(flags, kUnknown_SkPixelGeometry);
985 if (can_use_lcd_text) {
986 // LegacyFontHost will get LCD text and skia figures out what type to use.
987 surface_props =
988 SkSurfaceProps(flags, SkSurfaceProps::kLegacyFontHost_InitType);
990 sk_surface_ = skia::AdoptRef(
991 SkSurface::NewWrappedRenderTarget(gr_context, desc, &surface_props));
994 void ResourceProvider::ScopedWriteLockGr::ReleaseSkSurface() {
995 sk_surface_.clear();
998 ResourceProvider::SynchronousFence::SynchronousFence(
999 gpu::gles2::GLES2Interface* gl)
1000 : gl_(gl), has_synchronized_(true) {
1003 ResourceProvider::SynchronousFence::~SynchronousFence() {
1006 void ResourceProvider::SynchronousFence::Set() {
1007 has_synchronized_ = false;
1010 bool ResourceProvider::SynchronousFence::HasPassed() {
1011 if (!has_synchronized_) {
1012 has_synchronized_ = true;
1013 Synchronize();
1015 return true;
1018 void ResourceProvider::SynchronousFence::Wait() {
1019 HasPassed();
1022 void ResourceProvider::SynchronousFence::Synchronize() {
1023 TRACE_EVENT0("cc", "ResourceProvider::SynchronousFence::Synchronize");
1024 gl_->Finish();
1027 ResourceProvider::ResourceProvider(
1028 OutputSurface* output_surface,
1029 SharedBitmapManager* shared_bitmap_manager,
1030 gpu::GpuMemoryBufferManager* gpu_memory_buffer_manager,
1031 BlockingTaskRunner* blocking_main_thread_task_runner,
1032 int highp_threshold_min,
1033 bool use_rgba_4444_texture_format,
1034 size_t id_allocation_chunk_size,
1035 const std::vector<unsigned>& use_image_texture_targets)
1036 : output_surface_(output_surface),
1037 shared_bitmap_manager_(shared_bitmap_manager),
1038 gpu_memory_buffer_manager_(gpu_memory_buffer_manager),
1039 blocking_main_thread_task_runner_(blocking_main_thread_task_runner),
1040 lost_output_surface_(false),
1041 highp_threshold_min_(highp_threshold_min),
1042 next_id_(1),
1043 next_child_(1),
1044 default_resource_type_(RESOURCE_TYPE_BITMAP),
1045 use_texture_storage_ext_(false),
1046 use_texture_format_bgra_(false),
1047 use_texture_usage_hint_(false),
1048 use_compressed_texture_etc1_(false),
1049 yuv_resource_format_(LUMINANCE_8),
1050 max_texture_size_(0),
1051 best_texture_format_(RGBA_8888),
1052 best_render_buffer_format_(RGBA_8888),
1053 use_rgba_4444_texture_format_(use_rgba_4444_texture_format),
1054 id_allocation_chunk_size_(id_allocation_chunk_size),
1055 use_sync_query_(false),
1056 use_image_texture_targets_(use_image_texture_targets),
1057 tracing_id_(g_next_resource_provider_tracing_id.GetNext()) {
1058 DCHECK(output_surface_->HasClient());
1059 DCHECK(id_allocation_chunk_size_);
1062 void ResourceProvider::Initialize() {
1063 DCHECK(thread_checker_.CalledOnValidThread());
1065 // In certain cases, ThreadTaskRunnerHandle isn't set (Android Webview).
1066 // Don't register a dump provider in these cases.
1067 // TODO(ericrk): Get this working in Android Webview. crbug.com/517156
1068 if (base::ThreadTaskRunnerHandle::IsSet()) {
1069 base::trace_event::MemoryDumpManager::GetInstance()->RegisterDumpProvider(
1070 this, base::ThreadTaskRunnerHandle::Get());
1073 GLES2Interface* gl = ContextGL();
1074 if (!gl) {
1075 default_resource_type_ = RESOURCE_TYPE_BITMAP;
1076 // Pick an arbitrary limit here similar to what hardware might.
1077 max_texture_size_ = 16 * 1024;
1078 best_texture_format_ = RGBA_8888;
1079 return;
1082 DCHECK(!texture_id_allocator_);
1083 DCHECK(!buffer_id_allocator_);
1085 const ContextProvider::Capabilities& caps =
1086 output_surface_->context_provider()->ContextCapabilities();
1088 default_resource_type_ = RESOURCE_TYPE_GL_TEXTURE;
1089 use_texture_storage_ext_ = caps.gpu.texture_storage;
1090 use_texture_format_bgra_ = caps.gpu.texture_format_bgra8888;
1091 use_texture_usage_hint_ = caps.gpu.texture_usage;
1092 use_compressed_texture_etc1_ = caps.gpu.texture_format_etc1;
1093 yuv_resource_format_ = caps.gpu.texture_rg ? RED_8 : LUMINANCE_8;
1094 use_sync_query_ = caps.gpu.sync_query;
1096 max_texture_size_ = 0; // Context expects cleared value.
1097 gl->GetIntegerv(GL_MAX_TEXTURE_SIZE, &max_texture_size_);
1098 best_texture_format_ =
1099 PlatformColor::BestTextureFormat(use_texture_format_bgra_);
1101 best_render_buffer_format_ =
1102 PlatformColor::BestTextureFormat(caps.gpu.render_buffer_format_bgra8888);
1104 texture_id_allocator_.reset(
1105 new TextureIdAllocator(gl, id_allocation_chunk_size_));
1106 buffer_id_allocator_.reset(
1107 new BufferIdAllocator(gl, id_allocation_chunk_size_));
1110 int ResourceProvider::CreateChild(const ReturnCallback& return_callback) {
1111 DCHECK(thread_checker_.CalledOnValidThread());
1113 Child child_info;
1114 child_info.return_callback = return_callback;
1116 int child = next_child_++;
1117 children_[child] = child_info;
1118 return child;
1121 void ResourceProvider::SetChildNeedsSyncPoints(int child_id, bool needs) {
1122 ChildMap::iterator it = children_.find(child_id);
1123 DCHECK(it != children_.end());
1124 it->second.needs_sync_points = needs;
1127 void ResourceProvider::DestroyChild(int child_id) {
1128 ChildMap::iterator it = children_.find(child_id);
1129 DCHECK(it != children_.end());
1130 DestroyChildInternal(it, NORMAL);
1133 void ResourceProvider::DestroyChildInternal(ChildMap::iterator it,
1134 DeleteStyle style) {
1135 DCHECK(thread_checker_.CalledOnValidThread());
1137 Child& child = it->second;
1138 DCHECK(style == FOR_SHUTDOWN || !child.marked_for_deletion);
1140 ResourceIdArray resources_for_child;
1142 for (ResourceIdMap::iterator child_it = child.child_to_parent_map.begin();
1143 child_it != child.child_to_parent_map.end();
1144 ++child_it) {
1145 ResourceId id = child_it->second;
1146 resources_for_child.push_back(id);
1149 child.marked_for_deletion = true;
1151 DeleteAndReturnUnusedResourcesToChild(it, style, resources_for_child);
1154 const ResourceProvider::ResourceIdMap& ResourceProvider::GetChildToParentMap(
1155 int child) const {
1156 DCHECK(thread_checker_.CalledOnValidThread());
1157 ChildMap::const_iterator it = children_.find(child);
1158 DCHECK(it != children_.end());
1159 DCHECK(!it->second.marked_for_deletion);
1160 return it->second.child_to_parent_map;
1163 void ResourceProvider::PrepareSendToParent(const ResourceIdArray& resources,
1164 TransferableResourceArray* list) {
1165 DCHECK(thread_checker_.CalledOnValidThread());
1166 GLES2Interface* gl = ContextGL();
1167 bool need_sync_point = false;
1168 for (ResourceIdArray::const_iterator it = resources.begin();
1169 it != resources.end();
1170 ++it) {
1171 TransferableResource resource;
1172 TransferResource(gl, *it, &resource);
1173 if (!resource.mailbox_holder.sync_point && !resource.is_software)
1174 need_sync_point = true;
1175 ++resources_.find(*it)->second.exported_count;
1176 list->push_back(resource);
1178 if (need_sync_point &&
1179 output_surface_->capabilities().delegated_sync_points_required) {
1180 GLuint sync_point = gl->InsertSyncPointCHROMIUM();
1181 for (TransferableResourceArray::iterator it = list->begin();
1182 it != list->end();
1183 ++it) {
1184 if (!it->mailbox_holder.sync_point)
1185 it->mailbox_holder.sync_point = sync_point;
1190 void ResourceProvider::ReceiveFromChild(
1191 int child, const TransferableResourceArray& resources) {
1192 DCHECK(thread_checker_.CalledOnValidThread());
1193 GLES2Interface* gl = ContextGL();
1194 Child& child_info = children_.find(child)->second;
1195 DCHECK(!child_info.marked_for_deletion);
1196 for (TransferableResourceArray::const_iterator it = resources.begin();
1197 it != resources.end();
1198 ++it) {
1199 ResourceIdMap::iterator resource_in_map_it =
1200 child_info.child_to_parent_map.find(it->id);
1201 if (resource_in_map_it != child_info.child_to_parent_map.end()) {
1202 Resource* resource = GetResource(resource_in_map_it->second);
1203 resource->marked_for_deletion = false;
1204 resource->imported_count++;
1205 continue;
1208 if ((!it->is_software && !gl) ||
1209 (it->is_software && !shared_bitmap_manager_)) {
1210 TRACE_EVENT0("cc", "ResourceProvider::ReceiveFromChild dropping invalid");
1211 ReturnedResourceArray to_return;
1212 to_return.push_back(it->ToReturnedResource());
1213 child_info.return_callback.Run(to_return,
1214 blocking_main_thread_task_runner_);
1215 continue;
1218 ResourceId local_id = next_id_++;
1219 Resource* resource = nullptr;
1220 if (it->is_software) {
1221 resource = InsertResource(
1222 local_id,
1223 Resource(it->mailbox_holder.mailbox, it->size, Resource::DELEGATED,
1224 GL_LINEAR, it->is_repeated ? GL_REPEAT : GL_CLAMP_TO_EDGE));
1225 } else {
1226 resource = InsertResource(
1227 local_id, Resource(0, it->size, Resource::DELEGATED,
1228 it->mailbox_holder.texture_target, it->filter, 0,
1229 it->is_repeated ? GL_REPEAT : GL_CLAMP_TO_EDGE,
1230 TEXTURE_HINT_IMMUTABLE, it->format));
1231 resource->mailbox = TextureMailbox(it->mailbox_holder.mailbox,
1232 it->mailbox_holder.texture_target,
1233 it->mailbox_holder.sync_point);
1234 resource->read_lock_fences_enabled = it->read_lock_fences_enabled;
1236 resource->child_id = child;
1237 // Don't allocate a texture for a child.
1238 resource->allocated = true;
1239 resource->imported_count = 1;
1240 child_info.parent_to_child_map[local_id] = it->id;
1241 child_info.child_to_parent_map[it->id] = local_id;
1245 void ResourceProvider::DeclareUsedResourcesFromChild(
1246 int child,
1247 const ResourceIdSet& resources_from_child) {
1248 DCHECK(thread_checker_.CalledOnValidThread());
1250 ChildMap::iterator child_it = children_.find(child);
1251 DCHECK(child_it != children_.end());
1252 Child& child_info = child_it->second;
1253 DCHECK(!child_info.marked_for_deletion);
1255 ResourceIdArray unused;
1256 for (ResourceIdMap::iterator it = child_info.child_to_parent_map.begin();
1257 it != child_info.child_to_parent_map.end();
1258 ++it) {
1259 ResourceId local_id = it->second;
1260 bool resource_is_in_use = resources_from_child.count(it->first) > 0;
1261 if (!resource_is_in_use)
1262 unused.push_back(local_id);
1264 DeleteAndReturnUnusedResourcesToChild(child_it, NORMAL, unused);
1267 void ResourceProvider::ReceiveReturnsFromParent(
1268 const ReturnedResourceArray& resources) {
1269 DCHECK(thread_checker_.CalledOnValidThread());
1270 GLES2Interface* gl = ContextGL();
1272 base::hash_map<int, ResourceIdArray> resources_for_child;
1274 for (const ReturnedResource& returned : resources) {
1275 ResourceId local_id = returned.id;
1276 ResourceMap::iterator map_iterator = resources_.find(local_id);
1277 // Resource was already lost (e.g. it belonged to a child that was
1278 // destroyed).
1279 if (map_iterator == resources_.end())
1280 continue;
1282 Resource* resource = &map_iterator->second;
1284 CHECK_GE(resource->exported_count, returned.count);
1285 resource->exported_count -= returned.count;
1286 resource->lost |= returned.lost;
1287 if (resource->exported_count)
1288 continue;
1290 if (returned.sync_point) {
1291 DCHECK(!resource->has_shared_bitmap_id);
1292 if (resource->origin == Resource::INTERNAL) {
1293 DCHECK(resource->gl_id);
1294 gl->WaitSyncPointCHROMIUM(returned.sync_point);
1295 } else {
1296 DCHECK(!resource->gl_id);
1297 resource->mailbox.set_sync_point(returned.sync_point);
1301 if (!resource->marked_for_deletion)
1302 continue;
1304 if (!resource->child_id) {
1305 // The resource belongs to this ResourceProvider, so it can be destroyed.
1306 DeleteResourceInternal(map_iterator, NORMAL);
1307 continue;
1310 DCHECK(resource->origin == Resource::DELEGATED);
1311 resources_for_child[resource->child_id].push_back(local_id);
1314 for (const auto& children : resources_for_child) {
1315 ChildMap::iterator child_it = children_.find(children.first);
1316 DCHECK(child_it != children_.end());
1317 DeleteAndReturnUnusedResourcesToChild(child_it, NORMAL, children.second);
1321 void ResourceProvider::TransferResource(GLES2Interface* gl,
1322 ResourceId id,
1323 TransferableResource* resource) {
1324 Resource* source = GetResource(id);
1325 DCHECK(!source->locked_for_write);
1326 DCHECK(!source->lock_for_read_count);
1327 DCHECK(source->origin != Resource::EXTERNAL || source->mailbox.IsValid());
1328 DCHECK(source->allocated);
1329 resource->id = id;
1330 resource->format = source->format;
1331 resource->mailbox_holder.texture_target = source->target;
1332 resource->filter = source->filter;
1333 resource->size = source->size;
1334 resource->read_lock_fences_enabled = source->read_lock_fences_enabled;
1335 resource->is_repeated = (source->wrap_mode == GL_REPEAT);
1337 if (source->type == RESOURCE_TYPE_BITMAP) {
1338 resource->mailbox_holder.mailbox = source->shared_bitmap_id;
1339 resource->is_software = true;
1340 } else if (!source->mailbox.IsValid()) {
1341 LazyCreate(source);
1342 DCHECK(source->gl_id);
1343 DCHECK(source->origin == Resource::INTERNAL);
1344 if (source->image_id) {
1345 DCHECK(source->dirty_image);
1346 gl->BindTexture(resource->mailbox_holder.texture_target, source->gl_id);
1347 BindImageForSampling(source);
1349 // This is a resource allocated by the compositor, we need to produce it.
1350 // Don't set a sync point, the caller will do it.
1351 gl->GenMailboxCHROMIUM(resource->mailbox_holder.mailbox.name);
1352 gl->ProduceTextureDirectCHROMIUM(source->gl_id,
1353 resource->mailbox_holder.texture_target,
1354 resource->mailbox_holder.mailbox.name);
1356 source->mailbox = TextureMailbox(resource->mailbox_holder);
1357 } else {
1358 DCHECK(source->mailbox.IsTexture());
1359 if (source->image_id && source->dirty_image) {
1360 DCHECK(source->gl_id);
1361 DCHECK(source->origin == Resource::INTERNAL);
1362 gl->BindTexture(resource->mailbox_holder.texture_target, source->gl_id);
1363 BindImageForSampling(source);
1365 // This is either an external resource, or a compositor resource that we
1366 // already exported. Make sure to forward the sync point that we were given.
1367 resource->mailbox_holder.mailbox = source->mailbox.mailbox();
1368 resource->mailbox_holder.texture_target = source->mailbox.target();
1369 resource->mailbox_holder.sync_point = source->mailbox.sync_point();
1370 source->mailbox.set_sync_point(0);
1374 void ResourceProvider::DeleteAndReturnUnusedResourcesToChild(
1375 ChildMap::iterator child_it,
1376 DeleteStyle style,
1377 const ResourceIdArray& unused) {
1378 DCHECK(thread_checker_.CalledOnValidThread());
1379 DCHECK(child_it != children_.end());
1380 Child* child_info = &child_it->second;
1382 if (unused.empty() && !child_info->marked_for_deletion)
1383 return;
1385 ReturnedResourceArray to_return;
1387 GLES2Interface* gl = ContextGL();
1388 bool need_sync_point = false;
1389 for (size_t i = 0; i < unused.size(); ++i) {
1390 ResourceId local_id = unused[i];
1392 ResourceMap::iterator it = resources_.find(local_id);
1393 CHECK(it != resources_.end());
1394 Resource& resource = it->second;
1396 DCHECK(!resource.locked_for_write);
1397 DCHECK(child_info->parent_to_child_map.count(local_id));
1399 ResourceId child_id = child_info->parent_to_child_map[local_id];
1400 DCHECK(child_info->child_to_parent_map.count(child_id));
1402 bool is_lost =
1403 resource.lost ||
1404 (resource.type == RESOURCE_TYPE_GL_TEXTURE && lost_output_surface_);
1405 if (resource.exported_count > 0 || resource.lock_for_read_count > 0) {
1406 if (style != FOR_SHUTDOWN) {
1407 // Defer this resource deletion.
1408 resource.marked_for_deletion = true;
1409 continue;
1411 // We can't postpone the deletion, so we'll have to lose it.
1412 is_lost = true;
1413 } else if (!ReadLockFenceHasPassed(&resource)) {
1414 // TODO(dcastagna): see if it's possible to use this logic for
1415 // the branch above too, where the resource is locked or still exported.
1416 if (style != FOR_SHUTDOWN && !child_info->marked_for_deletion) {
1417 // Defer this resource deletion.
1418 resource.marked_for_deletion = true;
1419 continue;
1421 // We can't postpone the deletion, so we'll have to lose it.
1422 is_lost = true;
1425 if (gl && resource.filter != resource.original_filter) {
1426 DCHECK(resource.target);
1427 DCHECK(resource.gl_id);
1429 gl->BindTexture(resource.target, resource.gl_id);
1430 gl->TexParameteri(resource.target, GL_TEXTURE_MIN_FILTER,
1431 resource.original_filter);
1432 gl->TexParameteri(resource.target, GL_TEXTURE_MAG_FILTER,
1433 resource.original_filter);
1436 ReturnedResource returned;
1437 returned.id = child_id;
1438 returned.sync_point = resource.mailbox.sync_point();
1439 if (!returned.sync_point && resource.type == RESOURCE_TYPE_GL_TEXTURE)
1440 need_sync_point = true;
1441 returned.count = resource.imported_count;
1442 returned.lost = is_lost;
1443 to_return.push_back(returned);
1445 child_info->parent_to_child_map.erase(local_id);
1446 child_info->child_to_parent_map.erase(child_id);
1447 resource.imported_count = 0;
1448 DeleteResourceInternal(it, style);
1450 if (need_sync_point && child_info->needs_sync_points) {
1451 DCHECK(gl);
1452 GLuint sync_point = gl->InsertSyncPointCHROMIUM();
1453 for (size_t i = 0; i < to_return.size(); ++i) {
1454 if (!to_return[i].sync_point)
1455 to_return[i].sync_point = sync_point;
1459 if (!to_return.empty())
1460 child_info->return_callback.Run(to_return,
1461 blocking_main_thread_task_runner_);
1463 if (child_info->marked_for_deletion &&
1464 child_info->parent_to_child_map.empty()) {
1465 DCHECK(child_info->child_to_parent_map.empty());
1466 children_.erase(child_it);
1470 void ResourceProvider::AcquirePixelBuffer(ResourceId id) {
1471 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug"),
1472 "ResourceProvider::AcquirePixelBuffer");
1474 Resource* resource = GetResource(id);
1475 DCHECK(resource->origin == Resource::INTERNAL);
1476 DCHECK_EQ(resource->exported_count, 0);
1477 DCHECK(!resource->image_id);
1478 DCHECK_NE(ETC1, resource->format);
1480 DCHECK_EQ(RESOURCE_TYPE_GL_TEXTURE, resource->type);
1481 GLES2Interface* gl = ContextGL();
1482 DCHECK(gl);
1483 if (!resource->gl_pixel_buffer_id)
1484 resource->gl_pixel_buffer_id = buffer_id_allocator_->NextId();
1485 gl->BindBuffer(GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM,
1486 resource->gl_pixel_buffer_id);
1487 size_t resource_bytes = ResourceUtil::UncheckedSizeInBytesAligned<size_t>(
1488 resource->size, resource->format);
1489 gl->BufferData(GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM, resource_bytes, NULL,
1490 GL_DYNAMIC_DRAW);
1491 gl->BindBuffer(GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM, 0);
1494 void ResourceProvider::ReleasePixelBuffer(ResourceId id) {
1495 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug"),
1496 "ResourceProvider::ReleasePixelBuffer");
1498 Resource* resource = GetResource(id);
1499 DCHECK(resource->origin == Resource::INTERNAL);
1500 DCHECK_EQ(resource->exported_count, 0);
1501 DCHECK(!resource->image_id);
1503 // The pixel buffer can be released while there is a pending "set pixels"
1504 // if completion has been forced. Any shared memory associated with this
1505 // pixel buffer will not be freed until the waitAsyncTexImage2DCHROMIUM
1506 // command has been processed on the service side. It is also safe to
1507 // reuse any query id associated with this resource before they complete
1508 // as each new query has a unique submit count.
1509 if (resource->pending_set_pixels) {
1510 DCHECK(resource->set_pixels_completion_forced);
1511 resource->pending_set_pixels = false;
1512 resource->locked_for_write = false;
1515 DCHECK_EQ(RESOURCE_TYPE_GL_TEXTURE, resource->type);
1516 if (!resource->gl_pixel_buffer_id)
1517 return;
1518 GLES2Interface* gl = ContextGL();
1519 DCHECK(gl);
1520 gl->BindBuffer(GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM,
1521 resource->gl_pixel_buffer_id);
1522 gl->BufferData(
1523 GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM, 0, NULL, GL_DYNAMIC_DRAW);
1524 gl->BindBuffer(GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM, 0);
1527 uint8_t* ResourceProvider::MapPixelBuffer(ResourceId id, int* stride) {
1528 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug"),
1529 "ResourceProvider::MapPixelBuffer");
1531 Resource* resource = GetResource(id);
1532 DCHECK(resource->origin == Resource::INTERNAL);
1533 DCHECK_EQ(resource->exported_count, 0);
1534 DCHECK(!resource->image_id);
1536 *stride = 0;
1537 DCHECK_EQ(RESOURCE_TYPE_GL_TEXTURE, resource->type);
1538 GLES2Interface* gl = ContextGL();
1539 DCHECK(gl);
1540 DCHECK(resource->gl_pixel_buffer_id);
1541 gl->BindBuffer(GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM,
1542 resource->gl_pixel_buffer_id);
1543 uint8_t* image = static_cast<uint8_t*>(gl->MapBufferCHROMIUM(
1544 GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM, GL_WRITE_ONLY));
1545 gl->BindBuffer(GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM, 0);
1546 // Buffer is required to be 4-byte aligned.
1547 CHECK(!(reinterpret_cast<intptr_t>(image) & 3));
1548 return image;
1551 void ResourceProvider::UnmapPixelBuffer(ResourceId id) {
1552 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug"),
1553 "ResourceProvider::UnmapPixelBuffer");
1555 Resource* resource = GetResource(id);
1556 DCHECK(resource->origin == Resource::INTERNAL);
1557 DCHECK_EQ(resource->exported_count, 0);
1558 DCHECK(!resource->image_id);
1560 DCHECK_EQ(RESOURCE_TYPE_GL_TEXTURE, resource->type);
1561 GLES2Interface* gl = ContextGL();
1562 DCHECK(gl);
1563 DCHECK(resource->gl_pixel_buffer_id);
1564 gl->BindBuffer(GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM,
1565 resource->gl_pixel_buffer_id);
1566 gl->UnmapBufferCHROMIUM(GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM);
1567 gl->BindBuffer(GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM, 0);
1570 GLenum ResourceProvider::BindForSampling(ResourceId resource_id,
1571 GLenum unit,
1572 GLenum filter) {
1573 DCHECK(thread_checker_.CalledOnValidThread());
1574 GLES2Interface* gl = ContextGL();
1575 ResourceMap::iterator it = resources_.find(resource_id);
1576 DCHECK(it != resources_.end());
1577 Resource* resource = &it->second;
1578 DCHECK(resource->lock_for_read_count);
1579 DCHECK(!resource->locked_for_write || resource->set_pixels_completion_forced);
1581 ScopedSetActiveTexture scoped_active_tex(gl, unit);
1582 GLenum target = resource->target;
1583 gl->BindTexture(target, resource->gl_id);
1584 if (filter != resource->filter) {
1585 gl->TexParameteri(target, GL_TEXTURE_MIN_FILTER, filter);
1586 gl->TexParameteri(target, GL_TEXTURE_MAG_FILTER, filter);
1587 resource->filter = filter;
1590 if (resource->image_id && resource->dirty_image)
1591 BindImageForSampling(resource);
1593 return target;
1596 void ResourceProvider::BeginSetPixels(ResourceId id) {
1597 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug"),
1598 "ResourceProvider::BeginSetPixels");
1600 Resource* resource = GetResource(id);
1601 DCHECK(!resource->pending_set_pixels);
1603 LazyCreate(resource);
1604 DCHECK(resource->origin == Resource::INTERNAL);
1605 DCHECK(resource->gl_id || resource->allocated);
1606 DCHECK(ReadLockFenceHasPassed(resource));
1607 DCHECK(!resource->image_id);
1609 bool allocate = !resource->allocated;
1610 resource->allocated = true;
1611 LockForWrite(id);
1613 DCHECK_EQ(RESOURCE_TYPE_GL_TEXTURE, resource->type);
1614 DCHECK(resource->gl_id);
1615 GLES2Interface* gl = ContextGL();
1616 DCHECK(gl);
1617 DCHECK(resource->gl_pixel_buffer_id);
1618 DCHECK_EQ(resource->target, static_cast<GLenum>(GL_TEXTURE_2D));
1619 gl->BindTexture(GL_TEXTURE_2D, resource->gl_id);
1620 gl->BindBuffer(GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM,
1621 resource->gl_pixel_buffer_id);
1622 if (!resource->gl_upload_query_id)
1623 gl->GenQueriesEXT(1, &resource->gl_upload_query_id);
1624 gl->BeginQueryEXT(GL_ASYNC_PIXEL_UNPACK_COMPLETED_CHROMIUM,
1625 resource->gl_upload_query_id);
1626 if (allocate) {
1627 gl->AsyncTexImage2DCHROMIUM(GL_TEXTURE_2D,
1628 0, /* level */
1629 GLInternalFormat(resource->format),
1630 resource->size.width(),
1631 resource->size.height(),
1632 0, /* border */
1633 GLDataFormat(resource->format),
1634 GLDataType(resource->format),
1635 NULL);
1636 } else {
1637 gl->AsyncTexSubImage2DCHROMIUM(GL_TEXTURE_2D,
1638 0, /* level */
1639 0, /* x */
1640 0, /* y */
1641 resource->size.width(),
1642 resource->size.height(),
1643 GLDataFormat(resource->format),
1644 GLDataType(resource->format),
1645 NULL);
1647 gl->EndQueryEXT(GL_ASYNC_PIXEL_UNPACK_COMPLETED_CHROMIUM);
1648 gl->BindBuffer(GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM, 0);
1650 resource->pending_set_pixels = true;
1651 resource->set_pixels_completion_forced = false;
1654 void ResourceProvider::ForceSetPixelsToComplete(ResourceId id) {
1655 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug"),
1656 "ResourceProvider::ForceSetPixelsToComplete");
1658 Resource* resource = GetResource(id);
1660 DCHECK(resource->locked_for_write);
1661 DCHECK(resource->pending_set_pixels);
1662 DCHECK(!resource->set_pixels_completion_forced);
1664 if (resource->gl_id) {
1665 GLES2Interface* gl = ContextGL();
1666 gl->BindTexture(GL_TEXTURE_2D, resource->gl_id);
1667 gl->WaitAsyncTexImage2DCHROMIUM(GL_TEXTURE_2D);
1668 gl->BindTexture(GL_TEXTURE_2D, 0);
1671 resource->set_pixels_completion_forced = true;
1674 bool ResourceProvider::DidSetPixelsComplete(ResourceId id) {
1675 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug"),
1676 "ResourceProvider::DidSetPixelsComplete");
1678 Resource* resource = GetResource(id);
1680 DCHECK(resource->locked_for_write);
1681 DCHECK(resource->pending_set_pixels);
1683 if (resource->gl_id) {
1684 GLES2Interface* gl = ContextGL();
1685 DCHECK(gl);
1686 DCHECK(resource->gl_upload_query_id);
1687 GLuint complete = 1;
1688 gl->GetQueryObjectuivEXT(
1689 resource->gl_upload_query_id, GL_QUERY_RESULT_AVAILABLE_EXT, &complete);
1690 if (!complete)
1691 return false;
1694 resource->pending_set_pixels = false;
1695 UnlockForWrite(resource);
1697 // Async set pixels commands are not necessarily processed in-sequence with
1698 // drawing commands. Read lock fences are required to ensure that async
1699 // commands don't access the resource while used for drawing.
1700 resource->read_lock_fences_enabled = true;
1702 return true;
1705 void ResourceProvider::CreateForTesting(ResourceId id) {
1706 LazyCreate(GetResource(id));
1709 GLenum ResourceProvider::TargetForTesting(ResourceId id) {
1710 Resource* resource = GetResource(id);
1711 return resource->target;
1714 void ResourceProvider::LazyCreate(Resource* resource) {
1715 if (resource->type != RESOURCE_TYPE_GL_TEXTURE ||
1716 resource->origin != Resource::INTERNAL)
1717 return;
1719 if (resource->gl_id)
1720 return;
1722 DCHECK(resource->texture_pool);
1723 DCHECK(resource->origin == Resource::INTERNAL);
1724 DCHECK(!resource->mailbox.IsValid());
1725 resource->gl_id = texture_id_allocator_->NextId();
1727 GLES2Interface* gl = ContextGL();
1728 DCHECK(gl);
1730 // Create and set texture properties. Allocation is delayed until needed.
1731 gl->BindTexture(resource->target, resource->gl_id);
1732 gl->TexParameteri(resource->target, GL_TEXTURE_MIN_FILTER,
1733 resource->original_filter);
1734 gl->TexParameteri(resource->target, GL_TEXTURE_MAG_FILTER,
1735 resource->original_filter);
1736 gl->TexParameteri(resource->target, GL_TEXTURE_WRAP_S, resource->wrap_mode);
1737 gl->TexParameteri(resource->target, GL_TEXTURE_WRAP_T, resource->wrap_mode);
1738 gl->TexParameteri(resource->target, GL_TEXTURE_POOL_CHROMIUM,
1739 resource->texture_pool);
1740 if (use_texture_usage_hint_ && (resource->hint & TEXTURE_HINT_FRAMEBUFFER)) {
1741 gl->TexParameteri(resource->target, GL_TEXTURE_USAGE_ANGLE,
1742 GL_FRAMEBUFFER_ATTACHMENT_ANGLE);
1746 void ResourceProvider::AllocateForTesting(ResourceId id) {
1747 LazyAllocate(GetResource(id));
1750 void ResourceProvider::LazyAllocate(Resource* resource) {
1751 DCHECK(resource);
1752 if (resource->allocated)
1753 return;
1754 LazyCreate(resource);
1755 if (!resource->gl_id)
1756 return;
1757 resource->allocated = true;
1758 GLES2Interface* gl = ContextGL();
1759 gfx::Size& size = resource->size;
1760 ResourceFormat format = resource->format;
1761 gl->BindTexture(resource->target, resource->gl_id);
1762 if (use_texture_storage_ext_ &&
1763 IsFormatSupportedForStorage(format, use_texture_format_bgra_) &&
1764 (resource->hint & TEXTURE_HINT_IMMUTABLE)) {
1765 GLenum storage_format = TextureToStorageFormat(format);
1766 gl->TexStorage2DEXT(resource->target, 1, storage_format, size.width(),
1767 size.height());
1768 } else {
1769 // ETC1 does not support preallocation.
1770 if (format != ETC1) {
1771 gl->TexImage2D(resource->target, 0, GLInternalFormat(format),
1772 size.width(), size.height(), 0, GLDataFormat(format),
1773 GLDataType(format), NULL);
1778 void ResourceProvider::BindImageForSampling(Resource* resource) {
1779 GLES2Interface* gl = ContextGL();
1780 DCHECK(resource->gl_id);
1781 DCHECK(resource->image_id);
1783 // Release image currently bound to texture.
1784 if (resource->bound_image_id)
1785 gl->ReleaseTexImage2DCHROMIUM(resource->target, resource->bound_image_id);
1786 gl->BindTexImage2DCHROMIUM(resource->target, resource->image_id);
1787 resource->bound_image_id = resource->image_id;
1788 resource->dirty_image = false;
1791 void ResourceProvider::WaitSyncPointIfNeeded(ResourceId id) {
1792 Resource* resource = GetResource(id);
1793 DCHECK_EQ(resource->exported_count, 0);
1794 DCHECK(resource->allocated);
1795 if (resource->type != RESOURCE_TYPE_GL_TEXTURE || resource->gl_id)
1796 return;
1797 if (!resource->mailbox.sync_point())
1798 return;
1799 DCHECK(resource->mailbox.IsValid());
1800 GLES2Interface* gl = ContextGL();
1801 DCHECK(gl);
1802 gl->WaitSyncPointCHROMIUM(resource->mailbox.sync_point());
1803 resource->mailbox.set_sync_point(0);
1806 GLint ResourceProvider::GetActiveTextureUnit(GLES2Interface* gl) {
1807 GLint active_unit = 0;
1808 gl->GetIntegerv(GL_ACTIVE_TEXTURE, &active_unit);
1809 return active_unit;
1812 GLenum ResourceProvider::GetImageTextureTarget(ResourceFormat format) {
1813 gfx::BufferFormat buffer_format = BufferFormat(format);
1814 DCHECK_GT(use_image_texture_targets_.size(),
1815 static_cast<size_t>(buffer_format));
1816 return use_image_texture_targets_[static_cast<size_t>(buffer_format)];
1819 void ResourceProvider::ValidateResource(ResourceId id) const {
1820 DCHECK(thread_checker_.CalledOnValidThread());
1821 DCHECK(id);
1822 DCHECK(resources_.find(id) != resources_.end());
1825 GLES2Interface* ResourceProvider::ContextGL() const {
1826 ContextProvider* context_provider = output_surface_->context_provider();
1827 return context_provider ? context_provider->ContextGL() : NULL;
1830 class GrContext* ResourceProvider::GrContext(bool worker_context) const {
1831 ContextProvider* context_provider =
1832 worker_context ? output_surface_->worker_context_provider()
1833 : output_surface_->context_provider();
1834 return context_provider ? context_provider->GrContext() : NULL;
1837 bool ResourceProvider::OnMemoryDump(
1838 const base::trace_event::MemoryDumpArgs& args,
1839 base::trace_event::ProcessMemoryDump* pmd) {
1840 DCHECK(thread_checker_.CalledOnValidThread());
1842 const uint64 tracing_process_id =
1843 base::trace_event::MemoryDumpManager::GetInstance()
1844 ->GetTracingProcessId();
1846 for (const auto& resource_entry : resources_) {
1847 const auto& resource = resource_entry.second;
1849 // Resource IDs are not process-unique, so log with the ResourceProvider's
1850 // unique id.
1851 std::string dump_name =
1852 base::StringPrintf("cc/resource_memory/provider_%d/resource_%d",
1853 tracing_id_, resource_entry.first);
1854 base::trace_event::MemoryAllocatorDump* dump =
1855 pmd->CreateAllocatorDump(dump_name);
1857 uint64_t total_bytes = ResourceUtil::UncheckedSizeInBytesAligned<size_t>(
1858 resource.size, resource.format);
1859 dump->AddScalar(base::trace_event::MemoryAllocatorDump::kNameSize,
1860 base::trace_event::MemoryAllocatorDump::kUnitsBytes,
1861 static_cast<uint64_t>(total_bytes));
1863 // Resources which are shared across processes require a shared GUID to
1864 // prevent double counting the memory. We currently support shared GUIDs for
1865 // GpuMemoryBuffer, SharedBitmap, and GL backed resources.
1866 base::trace_event::MemoryAllocatorDumpGuid guid;
1867 if (resource.gpu_memory_buffer) {
1868 guid = gfx::GetGpuMemoryBufferGUIDForTracing(
1869 tracing_process_id, resource.gpu_memory_buffer->GetHandle().id);
1870 } else if (resource.shared_bitmap) {
1871 guid = GetSharedBitmapGUIDForTracing(resource.shared_bitmap->id());
1872 } else if (resource.gl_id && resource.allocated) {
1873 guid =
1874 gfx::GetGLTextureGUIDForTracing(tracing_process_id, resource.gl_id);
1877 if (!guid.empty()) {
1878 const int kImportance = 2;
1879 pmd->CreateSharedGlobalAllocatorDump(guid);
1880 pmd->AddOwnershipEdge(dump->guid(), guid, kImportance);
1884 return true;
1887 } // namespace cc