Disable time.com in tough_ad_cases
[chromium-blink-merge.git] / cc / resources / resource_provider.cc
blobbe282b9ae93d738b59629e2e5f07894ad6dc4179
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/gfx/gpu_memory_buffer.h"
37 #include "ui/gl/trace_util.h"
39 using gpu::gles2::GLES2Interface;
41 namespace cc {
43 class IdAllocator {
44 public:
45 virtual ~IdAllocator() {}
47 virtual GLuint NextId() = 0;
49 protected:
50 IdAllocator(GLES2Interface* gl, size_t id_allocation_chunk_size)
51 : gl_(gl),
52 id_allocation_chunk_size_(id_allocation_chunk_size),
53 ids_(new GLuint[id_allocation_chunk_size]),
54 next_id_index_(id_allocation_chunk_size) {
55 DCHECK(id_allocation_chunk_size_);
56 DCHECK_LE(id_allocation_chunk_size_,
57 static_cast<size_t>(std::numeric_limits<int>::max()));
60 GLES2Interface* gl_;
61 const size_t id_allocation_chunk_size_;
62 scoped_ptr<GLuint[]> ids_;
63 size_t next_id_index_;
66 namespace {
68 GLenum TextureToStorageFormat(ResourceFormat format) {
69 GLenum storage_format = GL_RGBA8_OES;
70 switch (format) {
71 case RGBA_8888:
72 break;
73 case BGRA_8888:
74 storage_format = GL_BGRA8_EXT;
75 break;
76 case RGBA_4444:
77 case ALPHA_8:
78 case LUMINANCE_8:
79 case RGB_565:
80 case ETC1:
81 case RED_8:
82 NOTREACHED();
83 break;
86 return storage_format;
89 bool IsFormatSupportedForStorage(ResourceFormat format, bool use_bgra) {
90 switch (format) {
91 case RGBA_8888:
92 return true;
93 case BGRA_8888:
94 return use_bgra;
95 case RGBA_4444:
96 case ALPHA_8:
97 case LUMINANCE_8:
98 case RGB_565:
99 case ETC1:
100 case RED_8:
101 return false;
103 return false;
106 GrPixelConfig ToGrPixelConfig(ResourceFormat format) {
107 switch (format) {
108 case RGBA_8888:
109 return kRGBA_8888_GrPixelConfig;
110 case BGRA_8888:
111 return kBGRA_8888_GrPixelConfig;
112 case RGBA_4444:
113 return kRGBA_4444_GrPixelConfig;
114 default:
115 break;
117 DCHECK(false) << "Unsupported resource format.";
118 return kSkia8888_GrPixelConfig;
121 gfx::BufferFormat ToGpuMemoryBufferFormat(ResourceFormat format) {
122 switch (format) {
123 case RGBA_8888:
124 return gfx::BufferFormat::RGBA_8888;
125 case BGRA_8888:
126 return gfx::BufferFormat::BGRA_8888;
127 case RGBA_4444:
128 return gfx::BufferFormat::RGBA_4444;
129 case ALPHA_8:
130 case LUMINANCE_8:
131 case RGB_565:
132 case ETC1:
133 case RED_8:
134 break;
136 NOTREACHED();
137 return gfx::BufferFormat::RGBA_8888;
140 class ScopedSetActiveTexture {
141 public:
142 ScopedSetActiveTexture(GLES2Interface* gl, GLenum unit)
143 : gl_(gl), unit_(unit) {
144 DCHECK_EQ(GL_TEXTURE0, ResourceProvider::GetActiveTextureUnit(gl_));
146 if (unit_ != GL_TEXTURE0)
147 gl_->ActiveTexture(unit_);
150 ~ScopedSetActiveTexture() {
151 // Active unit being GL_TEXTURE0 is effectively the ground state.
152 if (unit_ != GL_TEXTURE0)
153 gl_->ActiveTexture(GL_TEXTURE0);
156 private:
157 GLES2Interface* gl_;
158 GLenum unit_;
161 class TextureIdAllocator : public IdAllocator {
162 public:
163 TextureIdAllocator(GLES2Interface* gl,
164 size_t texture_id_allocation_chunk_size)
165 : IdAllocator(gl, texture_id_allocation_chunk_size) {}
166 ~TextureIdAllocator() override {
167 gl_->DeleteTextures(
168 static_cast<int>(id_allocation_chunk_size_ - next_id_index_),
169 ids_.get() + next_id_index_);
172 // Overridden from IdAllocator:
173 GLuint NextId() override {
174 if (next_id_index_ == id_allocation_chunk_size_) {
175 gl_->GenTextures(static_cast<int>(id_allocation_chunk_size_), ids_.get());
176 next_id_index_ = 0;
179 return ids_[next_id_index_++];
182 private:
183 DISALLOW_COPY_AND_ASSIGN(TextureIdAllocator);
186 class BufferIdAllocator : public IdAllocator {
187 public:
188 BufferIdAllocator(GLES2Interface* gl, size_t buffer_id_allocation_chunk_size)
189 : IdAllocator(gl, buffer_id_allocation_chunk_size) {}
190 ~BufferIdAllocator() override {
191 gl_->DeleteBuffers(
192 static_cast<int>(id_allocation_chunk_size_ - next_id_index_),
193 ids_.get() + next_id_index_);
196 // Overridden from IdAllocator:
197 GLuint NextId() override {
198 if (next_id_index_ == id_allocation_chunk_size_) {
199 gl_->GenBuffers(static_cast<int>(id_allocation_chunk_size_), ids_.get());
200 next_id_index_ = 0;
203 return ids_[next_id_index_++];
206 private:
207 DISALLOW_COPY_AND_ASSIGN(BufferIdAllocator);
210 // Query object based fence implementation used to detect completion of copy
211 // texture operations. Fence has passed when query result is available.
212 class CopyTextureFence : public ResourceProvider::Fence {
213 public:
214 CopyTextureFence(gpu::gles2::GLES2Interface* gl, unsigned query_id)
215 : gl_(gl), query_id_(query_id) {}
217 // Overridden from ResourceProvider::Fence:
218 void Set() override {}
219 bool HasPassed() override {
220 unsigned available = 1;
221 gl_->GetQueryObjectuivEXT(
222 query_id_, GL_QUERY_RESULT_AVAILABLE_EXT, &available);
223 if (!available)
224 return false;
226 ProcessResult();
227 return true;
229 void Wait() override {
230 // ProcessResult() will wait for result to become available.
231 ProcessResult();
234 private:
235 ~CopyTextureFence() override {}
237 void ProcessResult() {
238 unsigned time_elapsed_us = 0;
239 gl_->GetQueryObjectuivEXT(query_id_, GL_QUERY_RESULT_EXT, &time_elapsed_us);
240 UMA_HISTOGRAM_CUSTOM_COUNTS("Renderer4.CopyTextureLatency", time_elapsed_us,
241 0, 256000, 50);
244 gpu::gles2::GLES2Interface* gl_;
245 unsigned query_id_;
247 DISALLOW_COPY_AND_ASSIGN(CopyTextureFence);
250 // Generates process-unique IDs to use for tracing a ResourceProvider's
251 // resources.
252 base::StaticAtomicSequenceNumber g_next_resource_provider_tracing_id;
254 } // namespace
256 ResourceProvider::Resource::~Resource() {}
258 ResourceProvider::Resource::Resource(GLuint texture_id,
259 const gfx::Size& size,
260 Origin origin,
261 GLenum target,
262 GLenum filter,
263 GLenum texture_pool,
264 GLint wrap_mode,
265 TextureHint hint,
266 ResourceFormat format)
267 : child_id(0),
268 gl_id(texture_id),
269 gl_pixel_buffer_id(0),
270 gl_upload_query_id(0),
271 gl_read_lock_query_id(0),
272 pixels(NULL),
273 lock_for_read_count(0),
274 imported_count(0),
275 exported_count(0),
276 dirty_image(false),
277 locked_for_write(false),
278 lost(false),
279 marked_for_deletion(false),
280 pending_set_pixels(false),
281 set_pixels_completion_forced(false),
282 allocated(false),
283 read_lock_fences_enabled(false),
284 has_shared_bitmap_id(false),
285 read_lock_fence(NULL),
286 size(size),
287 origin(origin),
288 target(target),
289 original_filter(filter),
290 filter(filter),
291 image_id(0),
292 bound_image_id(0),
293 texture_pool(texture_pool),
294 wrap_mode(wrap_mode),
295 hint(hint),
296 type(RESOURCE_TYPE_GL_TEXTURE),
297 format(format),
298 shared_bitmap(NULL),
299 gpu_memory_buffer(NULL) {
300 DCHECK(wrap_mode == GL_CLAMP_TO_EDGE || wrap_mode == GL_REPEAT);
301 DCHECK_EQ(origin == INTERNAL, !!texture_pool);
304 ResourceProvider::Resource::Resource(uint8_t* pixels,
305 SharedBitmap* bitmap,
306 const gfx::Size& size,
307 Origin origin,
308 GLenum filter,
309 GLint wrap_mode)
310 : child_id(0),
311 gl_id(0),
312 gl_pixel_buffer_id(0),
313 gl_upload_query_id(0),
314 gl_read_lock_query_id(0),
315 pixels(pixels),
316 lock_for_read_count(0),
317 imported_count(0),
318 exported_count(0),
319 dirty_image(false),
320 locked_for_write(false),
321 lost(false),
322 marked_for_deletion(false),
323 pending_set_pixels(false),
324 set_pixels_completion_forced(false),
325 allocated(false),
326 read_lock_fences_enabled(false),
327 has_shared_bitmap_id(!!bitmap),
328 read_lock_fence(NULL),
329 size(size),
330 origin(origin),
331 target(0),
332 original_filter(filter),
333 filter(filter),
334 image_id(0),
335 bound_image_id(0),
336 texture_pool(0),
337 wrap_mode(wrap_mode),
338 hint(TEXTURE_HINT_IMMUTABLE),
339 type(RESOURCE_TYPE_BITMAP),
340 format(RGBA_8888),
341 shared_bitmap(bitmap),
342 gpu_memory_buffer(NULL) {
343 DCHECK(wrap_mode == GL_CLAMP_TO_EDGE || wrap_mode == GL_REPEAT);
344 DCHECK(origin == DELEGATED || pixels);
345 if (bitmap)
346 shared_bitmap_id = bitmap->id();
349 ResourceProvider::Resource::Resource(const SharedBitmapId& bitmap_id,
350 const gfx::Size& size,
351 Origin origin,
352 GLenum filter,
353 GLint wrap_mode)
354 : child_id(0),
355 gl_id(0),
356 gl_pixel_buffer_id(0),
357 gl_upload_query_id(0),
358 gl_read_lock_query_id(0),
359 pixels(NULL),
360 lock_for_read_count(0),
361 imported_count(0),
362 exported_count(0),
363 dirty_image(false),
364 locked_for_write(false),
365 lost(false),
366 marked_for_deletion(false),
367 pending_set_pixels(false),
368 set_pixels_completion_forced(false),
369 allocated(false),
370 read_lock_fences_enabled(false),
371 has_shared_bitmap_id(true),
372 read_lock_fence(NULL),
373 size(size),
374 origin(origin),
375 target(0),
376 original_filter(filter),
377 filter(filter),
378 image_id(0),
379 bound_image_id(0),
380 texture_pool(0),
381 wrap_mode(wrap_mode),
382 hint(TEXTURE_HINT_IMMUTABLE),
383 type(RESOURCE_TYPE_BITMAP),
384 format(RGBA_8888),
385 shared_bitmap_id(bitmap_id),
386 shared_bitmap(NULL),
387 gpu_memory_buffer(NULL) {
388 DCHECK(wrap_mode == GL_CLAMP_TO_EDGE || wrap_mode == GL_REPEAT);
391 ResourceProvider::Child::Child()
392 : marked_for_deletion(false), needs_sync_points(true) {
395 ResourceProvider::Child::~Child() {}
397 scoped_ptr<ResourceProvider> ResourceProvider::Create(
398 OutputSurface* output_surface,
399 SharedBitmapManager* shared_bitmap_manager,
400 gpu::GpuMemoryBufferManager* gpu_memory_buffer_manager,
401 BlockingTaskRunner* blocking_main_thread_task_runner,
402 int highp_threshold_min,
403 bool use_rgba_4444_texture_format,
404 size_t id_allocation_chunk_size,
405 bool use_persistent_map_for_gpu_memory_buffers,
406 const std::vector<unsigned>& use_image_texture_targets) {
407 scoped_ptr<ResourceProvider> resource_provider(new ResourceProvider(
408 output_surface, shared_bitmap_manager, gpu_memory_buffer_manager,
409 blocking_main_thread_task_runner, highp_threshold_min,
410 use_rgba_4444_texture_format, id_allocation_chunk_size,
411 use_persistent_map_for_gpu_memory_buffers, use_image_texture_targets));
412 resource_provider->Initialize();
413 return resource_provider;
416 ResourceProvider::~ResourceProvider() {
417 base::trace_event::MemoryDumpManager::GetInstance()->UnregisterDumpProvider(
418 this);
420 while (!children_.empty())
421 DestroyChildInternal(children_.begin(), FOR_SHUTDOWN);
422 while (!resources_.empty())
423 DeleteResourceInternal(resources_.begin(), FOR_SHUTDOWN);
425 GLES2Interface* gl = ContextGL();
426 if (default_resource_type_ != RESOURCE_TYPE_GL_TEXTURE) {
427 // We are not in GL mode, but double check before returning.
428 DCHECK(!gl);
429 return;
432 DCHECK(gl);
433 #if DCHECK_IS_ON()
434 // Check that all GL resources has been deleted.
435 for (ResourceMap::const_iterator itr = resources_.begin();
436 itr != resources_.end(); ++itr) {
437 DCHECK_NE(RESOURCE_TYPE_GL_TEXTURE, itr->second.type);
439 #endif // DCHECK_IS_ON()
441 texture_id_allocator_ = nullptr;
442 buffer_id_allocator_ = nullptr;
443 gl->Finish();
446 bool ResourceProvider::InUseByConsumer(ResourceId id) {
447 Resource* resource = GetResource(id);
448 return resource->lock_for_read_count > 0 || resource->exported_count > 0 ||
449 resource->lost;
452 bool ResourceProvider::IsLost(ResourceId id) {
453 Resource* resource = GetResource(id);
454 return resource->lost;
457 void ResourceProvider::LoseResourceForTesting(ResourceId id) {
458 Resource* resource = GetResource(id);
459 DCHECK(resource);
460 resource->lost = true;
463 ResourceId ResourceProvider::CreateResource(const gfx::Size& size,
464 GLint wrap_mode,
465 TextureHint hint,
466 ResourceFormat format) {
467 DCHECK(!size.IsEmpty());
468 switch (default_resource_type_) {
469 case RESOURCE_TYPE_GL_TEXTURE:
470 return CreateGLTexture(size,
471 GL_TEXTURE_2D,
472 GL_TEXTURE_POOL_UNMANAGED_CHROMIUM,
473 wrap_mode,
474 hint,
475 format);
476 case RESOURCE_TYPE_BITMAP:
477 DCHECK_EQ(RGBA_8888, format);
478 return CreateBitmap(size, wrap_mode);
481 LOG(FATAL) << "Invalid default resource type.";
482 return 0;
485 ResourceId ResourceProvider::CreateManagedResource(const gfx::Size& size,
486 GLenum target,
487 GLint wrap_mode,
488 TextureHint hint,
489 ResourceFormat format) {
490 DCHECK(!size.IsEmpty());
491 switch (default_resource_type_) {
492 case RESOURCE_TYPE_GL_TEXTURE:
493 return CreateGLTexture(size,
494 target,
495 GL_TEXTURE_POOL_MANAGED_CHROMIUM,
496 wrap_mode,
497 hint,
498 format);
499 case RESOURCE_TYPE_BITMAP:
500 DCHECK_EQ(RGBA_8888, format);
501 return CreateBitmap(size, wrap_mode);
504 LOG(FATAL) << "Invalid default resource type.";
505 return 0;
508 ResourceId ResourceProvider::CreateGLTexture(const gfx::Size& size,
509 GLenum target,
510 GLenum texture_pool,
511 GLint wrap_mode,
512 TextureHint hint,
513 ResourceFormat format) {
514 DCHECK_LE(size.width(), max_texture_size_);
515 DCHECK_LE(size.height(), max_texture_size_);
516 DCHECK(thread_checker_.CalledOnValidThread());
518 ResourceId id = next_id_++;
519 Resource* resource = InsertResource(
520 id, Resource(0, size, Resource::INTERNAL, target, GL_LINEAR, texture_pool,
521 wrap_mode, hint, format));
522 resource->allocated = false;
523 return id;
526 ResourceId ResourceProvider::CreateBitmap(const gfx::Size& size,
527 GLint wrap_mode) {
528 DCHECK(thread_checker_.CalledOnValidThread());
530 scoped_ptr<SharedBitmap> bitmap =
531 shared_bitmap_manager_->AllocateSharedBitmap(size);
532 uint8_t* pixels = bitmap->pixels();
533 DCHECK(pixels);
535 ResourceId id = next_id_++;
536 Resource* resource =
537 InsertResource(id, Resource(pixels, bitmap.release(), size,
538 Resource::INTERNAL, GL_LINEAR, wrap_mode));
539 resource->allocated = true;
540 return id;
543 ResourceId ResourceProvider::CreateResourceFromIOSurface(
544 const gfx::Size& size,
545 unsigned io_surface_id) {
546 DCHECK(thread_checker_.CalledOnValidThread());
548 ResourceId id = next_id_++;
549 Resource* resource = InsertResource(
550 id, Resource(0, gfx::Size(), Resource::INTERNAL, GL_TEXTURE_RECTANGLE_ARB,
551 GL_LINEAR, GL_TEXTURE_POOL_UNMANAGED_CHROMIUM,
552 GL_CLAMP_TO_EDGE, TEXTURE_HINT_IMMUTABLE, RGBA_8888));
553 LazyCreate(resource);
554 GLES2Interface* gl = ContextGL();
555 DCHECK(gl);
556 gl->BindTexture(GL_TEXTURE_RECTANGLE_ARB, resource->gl_id);
557 gl->TexImageIOSurface2DCHROMIUM(
558 GL_TEXTURE_RECTANGLE_ARB, size.width(), size.height(), io_surface_id, 0);
559 resource->allocated = true;
560 return id;
563 ResourceId ResourceProvider::CreateResourceFromTextureMailbox(
564 const TextureMailbox& mailbox,
565 scoped_ptr<SingleReleaseCallbackImpl> release_callback_impl,
566 bool read_lock_fences_enabled) {
567 DCHECK(thread_checker_.CalledOnValidThread());
568 // Just store the information. Mailbox will be consumed in LockForRead().
569 ResourceId id = next_id_++;
570 DCHECK(mailbox.IsValid());
571 Resource* resource = nullptr;
572 if (mailbox.IsTexture()) {
573 resource = InsertResource(
574 id, Resource(0, gfx::Size(), Resource::EXTERNAL, mailbox.target(),
575 mailbox.nearest_neighbor() ? GL_NEAREST : GL_LINEAR, 0,
576 GL_CLAMP_TO_EDGE, TEXTURE_HINT_IMMUTABLE, RGBA_8888));
577 } else {
578 DCHECK(mailbox.IsSharedMemory());
579 SharedBitmap* shared_bitmap = mailbox.shared_bitmap();
580 uint8_t* pixels = shared_bitmap->pixels();
581 DCHECK(pixels);
582 resource = InsertResource(
583 id, Resource(pixels, shared_bitmap, mailbox.size_in_pixels(),
584 Resource::EXTERNAL, GL_LINEAR, GL_CLAMP_TO_EDGE));
586 resource->allocated = true;
587 resource->mailbox = mailbox;
588 resource->release_callback_impl =
589 base::Bind(&SingleReleaseCallbackImpl::Run,
590 base::Owned(release_callback_impl.release()));
591 resource->read_lock_fences_enabled = read_lock_fences_enabled;
592 return id;
595 ResourceId ResourceProvider::CreateResourceFromTextureMailbox(
596 const TextureMailbox& mailbox,
597 scoped_ptr<SingleReleaseCallbackImpl> release_callback_impl) {
598 return CreateResourceFromTextureMailbox(mailbox, release_callback_impl.Pass(),
599 false);
602 void ResourceProvider::DeleteResource(ResourceId id) {
603 DCHECK(thread_checker_.CalledOnValidThread());
604 ResourceMap::iterator it = resources_.find(id);
605 CHECK(it != resources_.end());
606 Resource* resource = &it->second;
607 DCHECK(!resource->marked_for_deletion);
608 DCHECK_EQ(resource->imported_count, 0);
609 DCHECK(resource->pending_set_pixels || !resource->locked_for_write);
611 if (resource->exported_count > 0 || resource->lock_for_read_count > 0 ||
612 !ReadLockFenceHasPassed(resource)) {
613 resource->marked_for_deletion = true;
614 return;
615 } else {
616 DeleteResourceInternal(it, NORMAL);
620 void ResourceProvider::DeleteResourceInternal(ResourceMap::iterator it,
621 DeleteStyle style) {
622 TRACE_EVENT0("cc", "ResourceProvider::DeleteResourceInternal");
623 Resource* resource = &it->second;
624 bool lost_resource = resource->lost;
626 DCHECK(resource->exported_count == 0 || style != NORMAL);
627 if (style == FOR_SHUTDOWN && resource->exported_count > 0)
628 lost_resource = true;
630 if (resource->image_id) {
631 DCHECK(resource->origin == Resource::INTERNAL);
632 GLES2Interface* gl = ContextGL();
633 DCHECK(gl);
634 gl->DestroyImageCHROMIUM(resource->image_id);
636 if (resource->gl_upload_query_id) {
637 DCHECK(resource->origin == Resource::INTERNAL);
638 GLES2Interface* gl = ContextGL();
639 DCHECK(gl);
640 gl->DeleteQueriesEXT(1, &resource->gl_upload_query_id);
642 if (resource->gl_read_lock_query_id) {
643 DCHECK(resource->origin == Resource::INTERNAL);
644 GLES2Interface* gl = ContextGL();
645 DCHECK(gl);
646 gl->DeleteQueriesEXT(1, &resource->gl_read_lock_query_id);
648 if (resource->gl_pixel_buffer_id) {
649 DCHECK(resource->origin == Resource::INTERNAL);
650 GLES2Interface* gl = ContextGL();
651 DCHECK(gl);
652 gl->DeleteBuffers(1, &resource->gl_pixel_buffer_id);
654 if (resource->origin == Resource::EXTERNAL) {
655 DCHECK(resource->mailbox.IsValid());
656 GLuint sync_point = resource->mailbox.sync_point();
657 if (resource->type == RESOURCE_TYPE_GL_TEXTURE) {
658 DCHECK(resource->mailbox.IsTexture());
659 lost_resource |= lost_output_surface_;
660 GLES2Interface* gl = ContextGL();
661 DCHECK(gl);
662 if (resource->gl_id) {
663 gl->DeleteTextures(1, &resource->gl_id);
664 resource->gl_id = 0;
665 if (!lost_resource)
666 sync_point = gl->InsertSyncPointCHROMIUM();
668 } else {
669 DCHECK(resource->mailbox.IsSharedMemory());
670 resource->shared_bitmap = nullptr;
671 resource->pixels = nullptr;
673 resource->release_callback_impl.Run(
674 sync_point, lost_resource, blocking_main_thread_task_runner_);
676 if (resource->gl_id) {
677 GLES2Interface* gl = ContextGL();
678 DCHECK(gl);
679 gl->DeleteTextures(1, &resource->gl_id);
680 resource->gl_id = 0;
682 if (resource->shared_bitmap) {
683 DCHECK(resource->origin != Resource::EXTERNAL);
684 DCHECK_EQ(RESOURCE_TYPE_BITMAP, resource->type);
685 delete resource->shared_bitmap;
686 resource->pixels = NULL;
688 if (resource->pixels) {
689 DCHECK(resource->origin == Resource::INTERNAL);
690 delete[] resource->pixels;
691 resource->pixels = NULL;
693 if (resource->gpu_memory_buffer) {
694 DCHECK(resource->origin == Resource::INTERNAL);
695 delete resource->gpu_memory_buffer;
696 resource->gpu_memory_buffer = NULL;
698 resources_.erase(it);
701 ResourceProvider::ResourceType ResourceProvider::GetResourceType(
702 ResourceId id) {
703 return GetResource(id)->type;
706 void ResourceProvider::CopyToResource(ResourceId id,
707 const uint8_t* image,
708 const gfx::Size& image_size) {
709 Resource* resource = GetResource(id);
710 DCHECK(!resource->locked_for_write);
711 DCHECK(!resource->lock_for_read_count);
712 DCHECK(resource->origin == Resource::INTERNAL);
713 DCHECK_EQ(resource->exported_count, 0);
714 DCHECK(ReadLockFenceHasPassed(resource));
715 LazyAllocate(resource);
717 DCHECK_EQ(image_size.width(), resource->size.width());
718 DCHECK_EQ(image_size.height(), resource->size.height());
720 if (resource->type == RESOURCE_TYPE_BITMAP) {
721 DCHECK_EQ(RESOURCE_TYPE_BITMAP, resource->type);
722 DCHECK(resource->allocated);
723 DCHECK_EQ(RGBA_8888, resource->format);
724 SkImageInfo source_info =
725 SkImageInfo::MakeN32Premul(image_size.width(), image_size.height());
726 size_t image_stride = image_size.width() * 4;
728 ScopedWriteLockSoftware lock(this, id);
729 SkCanvas dest(lock.sk_bitmap());
730 dest.writePixels(source_info, image, image_stride, 0, 0);
731 } else {
732 DCHECK(resource->gl_id);
733 DCHECK(!resource->pending_set_pixels);
734 DCHECK_EQ(resource->target, static_cast<GLenum>(GL_TEXTURE_2D));
735 GLES2Interface* gl = ContextGL();
736 DCHECK(gl);
737 gl->BindTexture(GL_TEXTURE_2D, resource->gl_id);
739 if (resource->format == ETC1) {
740 int image_bytes = ResourceUtil::CheckedSizeInBytes<int>(image_size, ETC1);
741 gl->CompressedTexImage2D(GL_TEXTURE_2D, 0, GLInternalFormat(ETC1),
742 image_size.width(), image_size.height(), 0,
743 image_bytes, image);
744 } else {
745 gl->TexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, image_size.width(),
746 image_size.height(), GLDataFormat(resource->format),
747 GLDataType(resource->format), image);
752 ResourceProvider::Resource* ResourceProvider::InsertResource(
753 ResourceId id,
754 const Resource& resource) {
755 std::pair<ResourceMap::iterator, bool> result =
756 resources_.insert(ResourceMap::value_type(id, resource));
757 DCHECK(result.second);
758 return &result.first->second;
761 ResourceProvider::Resource* ResourceProvider::GetResource(ResourceId id) {
762 DCHECK(thread_checker_.CalledOnValidThread());
763 DCHECK(id);
764 ResourceMap::iterator it = resources_.find(id);
765 DCHECK(it != resources_.end());
766 return &it->second;
769 const ResourceProvider::Resource* ResourceProvider::LockForRead(ResourceId id) {
770 Resource* resource = GetResource(id);
771 DCHECK(!resource->locked_for_write ||
772 resource->set_pixels_completion_forced) <<
773 "locked for write: " << resource->locked_for_write <<
774 " pixels completion forced: " << resource->set_pixels_completion_forced;
775 DCHECK_EQ(resource->exported_count, 0);
776 // Uninitialized! Call SetPixels or LockForWrite first.
777 DCHECK(resource->allocated);
779 LazyCreate(resource);
781 if (resource->type == RESOURCE_TYPE_GL_TEXTURE && !resource->gl_id) {
782 DCHECK(resource->origin != Resource::INTERNAL);
783 DCHECK(resource->mailbox.IsTexture());
785 // Mailbox sync_points must be processed by a call to
786 // WaitSyncPointIfNeeded() prior to calling LockForRead().
787 DCHECK(!resource->mailbox.sync_point());
789 GLES2Interface* gl = ContextGL();
790 DCHECK(gl);
791 resource->gl_id = gl->CreateAndConsumeTextureCHROMIUM(
792 resource->mailbox.target(), resource->mailbox.name());
795 if (!resource->pixels && resource->has_shared_bitmap_id &&
796 shared_bitmap_manager_) {
797 scoped_ptr<SharedBitmap> bitmap =
798 shared_bitmap_manager_->GetSharedBitmapFromId(
799 resource->size, resource->shared_bitmap_id);
800 if (bitmap) {
801 resource->shared_bitmap = bitmap.release();
802 resource->pixels = resource->shared_bitmap->pixels();
806 resource->lock_for_read_count++;
807 if (resource->read_lock_fences_enabled) {
808 if (current_read_lock_fence_.get())
809 current_read_lock_fence_->Set();
810 resource->read_lock_fence = current_read_lock_fence_;
813 return resource;
816 void ResourceProvider::UnlockForRead(ResourceId id) {
817 DCHECK(thread_checker_.CalledOnValidThread());
818 ResourceMap::iterator it = resources_.find(id);
819 CHECK(it != resources_.end());
821 Resource* resource = &it->second;
822 DCHECK_GT(resource->lock_for_read_count, 0);
823 DCHECK_EQ(resource->exported_count, 0);
824 resource->lock_for_read_count--;
825 if (resource->marked_for_deletion && !resource->lock_for_read_count) {
826 if (!resource->child_id) {
827 // The resource belongs to this ResourceProvider, so it can be destroyed.
828 DeleteResourceInternal(it, NORMAL);
829 } else {
830 ChildMap::iterator child_it = children_.find(resource->child_id);
831 ResourceIdArray unused;
832 unused.push_back(id);
833 DeleteAndReturnUnusedResourcesToChild(child_it, NORMAL, unused);
838 ResourceProvider::Resource* ResourceProvider::LockForWrite(ResourceId id) {
839 Resource* resource = GetResource(id);
840 DCHECK(CanLockForWrite(id));
842 resource->locked_for_write = true;
843 return resource;
846 bool ResourceProvider::CanLockForWrite(ResourceId id) {
847 Resource* resource = GetResource(id);
848 return !resource->locked_for_write && !resource->lock_for_read_count &&
849 !resource->exported_count && resource->origin == Resource::INTERNAL &&
850 !resource->lost && ReadLockFenceHasPassed(resource);
853 void ResourceProvider::UnlockForWrite(ResourceProvider::Resource* resource) {
854 DCHECK(resource->locked_for_write);
855 DCHECK_EQ(resource->exported_count, 0);
856 DCHECK(resource->origin == Resource::INTERNAL);
857 resource->locked_for_write = false;
860 void ResourceProvider::EnableReadLockFencesForTesting(ResourceId id) {
861 Resource* resource = GetResource(id);
862 DCHECK(resource);
863 resource->read_lock_fences_enabled = true;
866 ResourceProvider::ScopedReadLockGL::ScopedReadLockGL(
867 ResourceProvider* resource_provider,
868 ResourceId resource_id)
869 : resource_provider_(resource_provider),
870 resource_id_(resource_id),
871 resource_(resource_provider->LockForRead(resource_id)) {
872 DCHECK(resource_);
875 ResourceProvider::ScopedReadLockGL::~ScopedReadLockGL() {
876 resource_provider_->UnlockForRead(resource_id_);
879 ResourceProvider::ScopedSamplerGL::ScopedSamplerGL(
880 ResourceProvider* resource_provider,
881 ResourceId resource_id,
882 GLenum filter)
883 : ScopedReadLockGL(resource_provider, resource_id),
884 unit_(GL_TEXTURE0),
885 target_(resource_provider->BindForSampling(resource_id, unit_, filter)) {
888 ResourceProvider::ScopedSamplerGL::ScopedSamplerGL(
889 ResourceProvider* resource_provider,
890 ResourceId resource_id,
891 GLenum unit,
892 GLenum filter)
893 : ScopedReadLockGL(resource_provider, resource_id),
894 unit_(unit),
895 target_(resource_provider->BindForSampling(resource_id, unit_, filter)) {
898 ResourceProvider::ScopedSamplerGL::~ScopedSamplerGL() {
901 ResourceProvider::ScopedWriteLockGL::ScopedWriteLockGL(
902 ResourceProvider* resource_provider,
903 ResourceId resource_id)
904 : resource_provider_(resource_provider),
905 resource_(resource_provider->LockForWrite(resource_id)) {
906 resource_provider_->LazyAllocate(resource_);
907 texture_id_ = resource_->gl_id;
908 DCHECK(texture_id_);
911 ResourceProvider::ScopedWriteLockGL::~ScopedWriteLockGL() {
912 resource_provider_->UnlockForWrite(resource_);
915 void ResourceProvider::PopulateSkBitmapWithResource(
916 SkBitmap* sk_bitmap, const Resource* resource) {
917 DCHECK_EQ(RGBA_8888, resource->format);
918 SkImageInfo info = SkImageInfo::MakeN32Premul(resource->size.width(),
919 resource->size.height());
920 sk_bitmap->installPixels(info, resource->pixels, info.minRowBytes());
923 ResourceProvider::ScopedReadLockSoftware::ScopedReadLockSoftware(
924 ResourceProvider* resource_provider,
925 ResourceId resource_id)
926 : resource_provider_(resource_provider), resource_id_(resource_id) {
927 const Resource* resource = resource_provider->LockForRead(resource_id);
928 wrap_mode_ = resource->wrap_mode;
929 ResourceProvider::PopulateSkBitmapWithResource(&sk_bitmap_, resource);
932 ResourceProvider::ScopedReadLockSoftware::~ScopedReadLockSoftware() {
933 resource_provider_->UnlockForRead(resource_id_);
936 ResourceProvider::ScopedWriteLockSoftware::ScopedWriteLockSoftware(
937 ResourceProvider* resource_provider,
938 ResourceId resource_id)
939 : resource_provider_(resource_provider),
940 resource_(resource_provider->LockForWrite(resource_id)) {
941 ResourceProvider::PopulateSkBitmapWithResource(&sk_bitmap_, resource_);
942 DCHECK(valid());
945 ResourceProvider::ScopedWriteLockSoftware::~ScopedWriteLockSoftware() {
946 DCHECK(thread_checker_.CalledOnValidThread());
947 resource_provider_->UnlockForWrite(resource_);
950 ResourceProvider::ScopedWriteLockGpuMemoryBuffer::
951 ScopedWriteLockGpuMemoryBuffer(ResourceProvider* resource_provider,
952 ResourceId resource_id)
953 : resource_provider_(resource_provider),
954 resource_(resource_provider->LockForWrite(resource_id)),
955 gpu_memory_buffer_manager_(resource_provider->gpu_memory_buffer_manager_),
956 gpu_memory_buffer_(nullptr),
957 size_(resource_->size),
958 format_(resource_->format) {
959 DCHECK_EQ(RESOURCE_TYPE_GL_TEXTURE, resource_->type);
960 std::swap(gpu_memory_buffer_, resource_->gpu_memory_buffer);
963 ResourceProvider::ScopedWriteLockGpuMemoryBuffer::
964 ~ScopedWriteLockGpuMemoryBuffer() {
965 DCHECK(thread_checker_.CalledOnValidThread());
966 resource_provider_->UnlockForWrite(resource_);
967 if (!gpu_memory_buffer_)
968 return;
970 resource_provider_->LazyCreate(resource_);
972 if (!resource_->image_id) {
973 GLES2Interface* gl = resource_provider_->ContextGL();
974 DCHECK(gl);
976 #if defined(OS_CHROMEOS)
977 // TODO(reveman): GL_COMMANDS_ISSUED_CHROMIUM is used for synchronization
978 // on ChromeOS to avoid some performance issues. This only works with
979 // shared memory backed buffers. crbug.com/436314
980 DCHECK_EQ(gpu_memory_buffer_->GetHandle().type, gfx::SHARED_MEMORY_BUFFER);
981 #endif
983 resource_->image_id = gl->CreateImageCHROMIUM(
984 gpu_memory_buffer_->AsClientBuffer(), size_.width(), size_.height(),
985 GLInternalFormat(resource_->format));
988 std::swap(resource_->gpu_memory_buffer, gpu_memory_buffer_);
989 resource_->allocated = true;
990 resource_->dirty_image = true;
992 // GpuMemoryBuffer provides direct access to the memory used by the GPU.
993 // Read lock fences are required to ensure that we're not trying to map a
994 // buffer that is currently in-use by the GPU.
995 resource_->read_lock_fences_enabled = true;
998 gfx::GpuMemoryBuffer*
999 ResourceProvider::ScopedWriteLockGpuMemoryBuffer::GetGpuMemoryBuffer() {
1000 if (gpu_memory_buffer_)
1001 return gpu_memory_buffer_;
1002 gfx::BufferUsage usage =
1003 resource_provider_->use_persistent_map_for_gpu_memory_buffers()
1004 ? gfx::BufferUsage::PERSISTENT_MAP
1005 : gfx::BufferUsage::MAP;
1006 scoped_ptr<gfx::GpuMemoryBuffer> gpu_memory_buffer =
1007 gpu_memory_buffer_manager_->AllocateGpuMemoryBuffer(
1008 size_, ToGpuMemoryBufferFormat(format_), usage);
1009 gpu_memory_buffer_ = gpu_memory_buffer.release();
1010 return gpu_memory_buffer_;
1013 ResourceProvider::ScopedWriteLockGr::ScopedWriteLockGr(
1014 ResourceProvider* resource_provider,
1015 ResourceId resource_id)
1016 : resource_provider_(resource_provider),
1017 resource_(resource_provider->LockForWrite(resource_id)) {
1018 DCHECK(thread_checker_.CalledOnValidThread());
1019 resource_provider_->LazyAllocate(resource_);
1022 ResourceProvider::ScopedWriteLockGr::~ScopedWriteLockGr() {
1023 DCHECK(thread_checker_.CalledOnValidThread());
1024 DCHECK(resource_->locked_for_write);
1025 resource_provider_->UnlockForWrite(resource_);
1028 void ResourceProvider::ScopedWriteLockGr::InitSkSurface(
1029 bool use_distance_field_text,
1030 bool can_use_lcd_text,
1031 int msaa_sample_count) {
1032 DCHECK(resource_->locked_for_write);
1034 GrBackendTextureDesc desc;
1035 desc.fFlags = kRenderTarget_GrBackendTextureFlag;
1036 desc.fWidth = resource_->size.width();
1037 desc.fHeight = resource_->size.height();
1038 desc.fConfig = ToGrPixelConfig(resource_->format);
1039 desc.fOrigin = kTopLeft_GrSurfaceOrigin;
1040 desc.fTextureHandle = resource_->gl_id;
1041 desc.fSampleCnt = msaa_sample_count;
1043 bool use_worker_context = true;
1044 class GrContext* gr_context =
1045 resource_provider_->GrContext(use_worker_context);
1046 uint32_t flags =
1047 use_distance_field_text ? SkSurfaceProps::kUseDistanceFieldFonts_Flag : 0;
1048 // Use unknown pixel geometry to disable LCD text.
1049 SkSurfaceProps surface_props(flags, kUnknown_SkPixelGeometry);
1050 if (can_use_lcd_text) {
1051 // LegacyFontHost will get LCD text and skia figures out what type to use.
1052 surface_props =
1053 SkSurfaceProps(flags, SkSurfaceProps::kLegacyFontHost_InitType);
1055 sk_surface_ = skia::AdoptRef(
1056 SkSurface::NewWrappedRenderTarget(gr_context, desc, &surface_props));
1059 void ResourceProvider::ScopedWriteLockGr::ReleaseSkSurface() {
1060 sk_surface_.clear();
1063 ResourceProvider::SynchronousFence::SynchronousFence(
1064 gpu::gles2::GLES2Interface* gl)
1065 : gl_(gl), has_synchronized_(true) {
1068 ResourceProvider::SynchronousFence::~SynchronousFence() {
1071 void ResourceProvider::SynchronousFence::Set() {
1072 has_synchronized_ = false;
1075 bool ResourceProvider::SynchronousFence::HasPassed() {
1076 if (!has_synchronized_) {
1077 has_synchronized_ = true;
1078 Synchronize();
1080 return true;
1083 void ResourceProvider::SynchronousFence::Wait() {
1084 HasPassed();
1087 void ResourceProvider::SynchronousFence::Synchronize() {
1088 TRACE_EVENT0("cc", "ResourceProvider::SynchronousFence::Synchronize");
1089 gl_->Finish();
1092 ResourceProvider::ResourceProvider(
1093 OutputSurface* output_surface,
1094 SharedBitmapManager* shared_bitmap_manager,
1095 gpu::GpuMemoryBufferManager* gpu_memory_buffer_manager,
1096 BlockingTaskRunner* blocking_main_thread_task_runner,
1097 int highp_threshold_min,
1098 bool use_rgba_4444_texture_format,
1099 size_t id_allocation_chunk_size,
1100 bool use_persistent_map_for_gpu_memory_buffers,
1101 const std::vector<unsigned>& use_image_texture_targets)
1102 : output_surface_(output_surface),
1103 shared_bitmap_manager_(shared_bitmap_manager),
1104 gpu_memory_buffer_manager_(gpu_memory_buffer_manager),
1105 blocking_main_thread_task_runner_(blocking_main_thread_task_runner),
1106 lost_output_surface_(false),
1107 highp_threshold_min_(highp_threshold_min),
1108 next_id_(1),
1109 next_child_(1),
1110 default_resource_type_(RESOURCE_TYPE_BITMAP),
1111 use_texture_storage_ext_(false),
1112 use_texture_format_bgra_(false),
1113 use_texture_usage_hint_(false),
1114 use_compressed_texture_etc1_(false),
1115 yuv_resource_format_(LUMINANCE_8),
1116 max_texture_size_(0),
1117 best_texture_format_(RGBA_8888),
1118 best_render_buffer_format_(RGBA_8888),
1119 use_rgba_4444_texture_format_(use_rgba_4444_texture_format),
1120 id_allocation_chunk_size_(id_allocation_chunk_size),
1121 use_sync_query_(false),
1122 use_persistent_map_for_gpu_memory_buffers_(
1123 use_persistent_map_for_gpu_memory_buffers),
1124 use_image_texture_targets_(use_image_texture_targets),
1125 tracing_id_(g_next_resource_provider_tracing_id.GetNext()) {
1126 DCHECK(output_surface_->HasClient());
1127 DCHECK(id_allocation_chunk_size_);
1130 void ResourceProvider::Initialize() {
1131 DCHECK(thread_checker_.CalledOnValidThread());
1133 // In certain cases, ThreadTaskRunnerHandle isn't set (Android Webview).
1134 // Don't register a dump provider in these cases.
1135 // TODO(ericrk): Get this working in Android Webview. crbug.com/517156
1136 if (base::ThreadTaskRunnerHandle::IsSet()) {
1137 base::trace_event::MemoryDumpManager::GetInstance()->RegisterDumpProvider(
1138 this, base::ThreadTaskRunnerHandle::Get());
1141 GLES2Interface* gl = ContextGL();
1142 if (!gl) {
1143 default_resource_type_ = RESOURCE_TYPE_BITMAP;
1144 // Pick an arbitrary limit here similar to what hardware might.
1145 max_texture_size_ = 16 * 1024;
1146 best_texture_format_ = RGBA_8888;
1147 return;
1150 DCHECK(!texture_id_allocator_);
1151 DCHECK(!buffer_id_allocator_);
1153 const ContextProvider::Capabilities& caps =
1154 output_surface_->context_provider()->ContextCapabilities();
1156 default_resource_type_ = RESOURCE_TYPE_GL_TEXTURE;
1157 use_texture_storage_ext_ = caps.gpu.texture_storage;
1158 use_texture_format_bgra_ = caps.gpu.texture_format_bgra8888;
1159 use_texture_usage_hint_ = caps.gpu.texture_usage;
1160 use_compressed_texture_etc1_ = caps.gpu.texture_format_etc1;
1161 yuv_resource_format_ = caps.gpu.texture_rg ? RED_8 : LUMINANCE_8;
1162 use_sync_query_ = caps.gpu.sync_query;
1164 max_texture_size_ = 0; // Context expects cleared value.
1165 gl->GetIntegerv(GL_MAX_TEXTURE_SIZE, &max_texture_size_);
1166 best_texture_format_ =
1167 PlatformColor::BestTextureFormat(use_texture_format_bgra_);
1169 best_render_buffer_format_ =
1170 PlatformColor::BestTextureFormat(caps.gpu.render_buffer_format_bgra8888);
1172 texture_id_allocator_.reset(
1173 new TextureIdAllocator(gl, id_allocation_chunk_size_));
1174 buffer_id_allocator_.reset(
1175 new BufferIdAllocator(gl, id_allocation_chunk_size_));
1178 int ResourceProvider::CreateChild(const ReturnCallback& return_callback) {
1179 DCHECK(thread_checker_.CalledOnValidThread());
1181 Child child_info;
1182 child_info.return_callback = return_callback;
1184 int child = next_child_++;
1185 children_[child] = child_info;
1186 return child;
1189 void ResourceProvider::SetChildNeedsSyncPoints(int child_id, bool needs) {
1190 ChildMap::iterator it = children_.find(child_id);
1191 DCHECK(it != children_.end());
1192 it->second.needs_sync_points = needs;
1195 void ResourceProvider::DestroyChild(int child_id) {
1196 ChildMap::iterator it = children_.find(child_id);
1197 DCHECK(it != children_.end());
1198 DestroyChildInternal(it, NORMAL);
1201 void ResourceProvider::DestroyChildInternal(ChildMap::iterator it,
1202 DeleteStyle style) {
1203 DCHECK(thread_checker_.CalledOnValidThread());
1205 Child& child = it->second;
1206 DCHECK(style == FOR_SHUTDOWN || !child.marked_for_deletion);
1208 ResourceIdArray resources_for_child;
1210 for (ResourceIdMap::iterator child_it = child.child_to_parent_map.begin();
1211 child_it != child.child_to_parent_map.end();
1212 ++child_it) {
1213 ResourceId id = child_it->second;
1214 resources_for_child.push_back(id);
1217 child.marked_for_deletion = true;
1219 DeleteAndReturnUnusedResourcesToChild(it, style, resources_for_child);
1222 const ResourceProvider::ResourceIdMap& ResourceProvider::GetChildToParentMap(
1223 int child) const {
1224 DCHECK(thread_checker_.CalledOnValidThread());
1225 ChildMap::const_iterator it = children_.find(child);
1226 DCHECK(it != children_.end());
1227 DCHECK(!it->second.marked_for_deletion);
1228 return it->second.child_to_parent_map;
1231 void ResourceProvider::PrepareSendToParent(const ResourceIdArray& resources,
1232 TransferableResourceArray* list) {
1233 DCHECK(thread_checker_.CalledOnValidThread());
1234 GLES2Interface* gl = ContextGL();
1235 bool need_sync_point = false;
1236 for (ResourceIdArray::const_iterator it = resources.begin();
1237 it != resources.end();
1238 ++it) {
1239 TransferableResource resource;
1240 TransferResource(gl, *it, &resource);
1241 if (!resource.mailbox_holder.sync_point && !resource.is_software)
1242 need_sync_point = true;
1243 ++resources_.find(*it)->second.exported_count;
1244 list->push_back(resource);
1246 if (need_sync_point &&
1247 output_surface_->capabilities().delegated_sync_points_required) {
1248 GLuint sync_point = gl->InsertSyncPointCHROMIUM();
1249 for (TransferableResourceArray::iterator it = list->begin();
1250 it != list->end();
1251 ++it) {
1252 if (!it->mailbox_holder.sync_point)
1253 it->mailbox_holder.sync_point = sync_point;
1258 void ResourceProvider::ReceiveFromChild(
1259 int child, const TransferableResourceArray& resources) {
1260 DCHECK(thread_checker_.CalledOnValidThread());
1261 GLES2Interface* gl = ContextGL();
1262 Child& child_info = children_.find(child)->second;
1263 DCHECK(!child_info.marked_for_deletion);
1264 for (TransferableResourceArray::const_iterator it = resources.begin();
1265 it != resources.end();
1266 ++it) {
1267 ResourceIdMap::iterator resource_in_map_it =
1268 child_info.child_to_parent_map.find(it->id);
1269 if (resource_in_map_it != child_info.child_to_parent_map.end()) {
1270 Resource* resource = GetResource(resource_in_map_it->second);
1271 resource->marked_for_deletion = false;
1272 resource->imported_count++;
1273 continue;
1276 if ((!it->is_software && !gl) ||
1277 (it->is_software && !shared_bitmap_manager_)) {
1278 TRACE_EVENT0("cc", "ResourceProvider::ReceiveFromChild dropping invalid");
1279 ReturnedResourceArray to_return;
1280 to_return.push_back(it->ToReturnedResource());
1281 child_info.return_callback.Run(to_return,
1282 blocking_main_thread_task_runner_);
1283 continue;
1286 ResourceId local_id = next_id_++;
1287 Resource* resource = nullptr;
1288 if (it->is_software) {
1289 resource = InsertResource(
1290 local_id,
1291 Resource(it->mailbox_holder.mailbox, it->size, Resource::DELEGATED,
1292 GL_LINEAR, it->is_repeated ? GL_REPEAT : GL_CLAMP_TO_EDGE));
1293 } else {
1294 resource = InsertResource(
1295 local_id, Resource(0, it->size, Resource::DELEGATED,
1296 it->mailbox_holder.texture_target, it->filter, 0,
1297 it->is_repeated ? GL_REPEAT : GL_CLAMP_TO_EDGE,
1298 TEXTURE_HINT_IMMUTABLE, it->format));
1299 resource->mailbox = TextureMailbox(it->mailbox_holder.mailbox,
1300 it->mailbox_holder.texture_target,
1301 it->mailbox_holder.sync_point);
1302 resource->read_lock_fences_enabled = it->read_lock_fences_enabled;
1304 resource->child_id = child;
1305 // Don't allocate a texture for a child.
1306 resource->allocated = true;
1307 resource->imported_count = 1;
1308 child_info.parent_to_child_map[local_id] = it->id;
1309 child_info.child_to_parent_map[it->id] = local_id;
1313 void ResourceProvider::DeclareUsedResourcesFromChild(
1314 int child,
1315 const ResourceIdSet& resources_from_child) {
1316 DCHECK(thread_checker_.CalledOnValidThread());
1318 ChildMap::iterator child_it = children_.find(child);
1319 DCHECK(child_it != children_.end());
1320 Child& child_info = child_it->second;
1321 DCHECK(!child_info.marked_for_deletion);
1323 ResourceIdArray unused;
1324 for (ResourceIdMap::iterator it = child_info.child_to_parent_map.begin();
1325 it != child_info.child_to_parent_map.end();
1326 ++it) {
1327 ResourceId local_id = it->second;
1328 bool resource_is_in_use = resources_from_child.count(it->first) > 0;
1329 if (!resource_is_in_use)
1330 unused.push_back(local_id);
1332 DeleteAndReturnUnusedResourcesToChild(child_it, NORMAL, unused);
1335 void ResourceProvider::ReceiveReturnsFromParent(
1336 const ReturnedResourceArray& resources) {
1337 DCHECK(thread_checker_.CalledOnValidThread());
1338 GLES2Interface* gl = ContextGL();
1340 base::hash_map<int, ResourceIdArray> resources_for_child;
1342 for (const ReturnedResource& returned : resources) {
1343 ResourceId local_id = returned.id;
1344 ResourceMap::iterator map_iterator = resources_.find(local_id);
1345 // Resource was already lost (e.g. it belonged to a child that was
1346 // destroyed).
1347 if (map_iterator == resources_.end())
1348 continue;
1350 Resource* resource = &map_iterator->second;
1352 CHECK_GE(resource->exported_count, returned.count);
1353 resource->exported_count -= returned.count;
1354 resource->lost |= returned.lost;
1355 if (resource->exported_count)
1356 continue;
1358 if (returned.sync_point) {
1359 DCHECK(!resource->has_shared_bitmap_id);
1360 if (resource->origin == Resource::INTERNAL) {
1361 DCHECK(resource->gl_id);
1362 gl->WaitSyncPointCHROMIUM(returned.sync_point);
1363 } else {
1364 DCHECK(!resource->gl_id);
1365 resource->mailbox.set_sync_point(returned.sync_point);
1369 if (!resource->marked_for_deletion)
1370 continue;
1372 if (!resource->child_id) {
1373 // The resource belongs to this ResourceProvider, so it can be destroyed.
1374 DeleteResourceInternal(map_iterator, NORMAL);
1375 continue;
1378 DCHECK(resource->origin == Resource::DELEGATED);
1379 resources_for_child[resource->child_id].push_back(local_id);
1382 for (const auto& children : resources_for_child) {
1383 ChildMap::iterator child_it = children_.find(children.first);
1384 DCHECK(child_it != children_.end());
1385 DeleteAndReturnUnusedResourcesToChild(child_it, NORMAL, children.second);
1389 void ResourceProvider::TransferResource(GLES2Interface* gl,
1390 ResourceId id,
1391 TransferableResource* resource) {
1392 Resource* source = GetResource(id);
1393 DCHECK(!source->locked_for_write);
1394 DCHECK(!source->lock_for_read_count);
1395 DCHECK(source->origin != Resource::EXTERNAL || source->mailbox.IsValid());
1396 DCHECK(source->allocated);
1397 resource->id = id;
1398 resource->format = source->format;
1399 resource->mailbox_holder.texture_target = source->target;
1400 resource->filter = source->filter;
1401 resource->size = source->size;
1402 resource->read_lock_fences_enabled = source->read_lock_fences_enabled;
1403 resource->is_repeated = (source->wrap_mode == GL_REPEAT);
1405 if (source->type == RESOURCE_TYPE_BITMAP) {
1406 resource->mailbox_holder.mailbox = source->shared_bitmap_id;
1407 resource->is_software = true;
1408 } else if (!source->mailbox.IsValid()) {
1409 LazyCreate(source);
1410 DCHECK(source->gl_id);
1411 DCHECK(source->origin == Resource::INTERNAL);
1412 if (source->image_id) {
1413 DCHECK(source->dirty_image);
1414 gl->BindTexture(resource->mailbox_holder.texture_target, source->gl_id);
1415 BindImageForSampling(source);
1417 // This is a resource allocated by the compositor, we need to produce it.
1418 // Don't set a sync point, the caller will do it.
1419 gl->GenMailboxCHROMIUM(resource->mailbox_holder.mailbox.name);
1420 gl->ProduceTextureDirectCHROMIUM(source->gl_id,
1421 resource->mailbox_holder.texture_target,
1422 resource->mailbox_holder.mailbox.name);
1424 source->mailbox = TextureMailbox(resource->mailbox_holder);
1425 } else {
1426 DCHECK(source->mailbox.IsTexture());
1427 if (source->image_id && source->dirty_image) {
1428 DCHECK(source->gl_id);
1429 DCHECK(source->origin == Resource::INTERNAL);
1430 gl->BindTexture(resource->mailbox_holder.texture_target, source->gl_id);
1431 BindImageForSampling(source);
1433 // This is either an external resource, or a compositor resource that we
1434 // already exported. Make sure to forward the sync point that we were given.
1435 resource->mailbox_holder.mailbox = source->mailbox.mailbox();
1436 resource->mailbox_holder.texture_target = source->mailbox.target();
1437 resource->mailbox_holder.sync_point = source->mailbox.sync_point();
1438 source->mailbox.set_sync_point(0);
1442 void ResourceProvider::DeleteAndReturnUnusedResourcesToChild(
1443 ChildMap::iterator child_it,
1444 DeleteStyle style,
1445 const ResourceIdArray& unused) {
1446 DCHECK(thread_checker_.CalledOnValidThread());
1447 DCHECK(child_it != children_.end());
1448 Child* child_info = &child_it->second;
1450 if (unused.empty() && !child_info->marked_for_deletion)
1451 return;
1453 ReturnedResourceArray to_return;
1455 GLES2Interface* gl = ContextGL();
1456 bool need_sync_point = false;
1457 for (size_t i = 0; i < unused.size(); ++i) {
1458 ResourceId local_id = unused[i];
1460 ResourceMap::iterator it = resources_.find(local_id);
1461 CHECK(it != resources_.end());
1462 Resource& resource = it->second;
1464 DCHECK(!resource.locked_for_write);
1465 DCHECK(child_info->parent_to_child_map.count(local_id));
1467 ResourceId child_id = child_info->parent_to_child_map[local_id];
1468 DCHECK(child_info->child_to_parent_map.count(child_id));
1470 bool is_lost =
1471 resource.lost ||
1472 (resource.type == RESOURCE_TYPE_GL_TEXTURE && lost_output_surface_);
1473 if (resource.exported_count > 0 || resource.lock_for_read_count > 0) {
1474 if (style != FOR_SHUTDOWN) {
1475 // Defer this resource deletion.
1476 resource.marked_for_deletion = true;
1477 continue;
1479 // We can't postpone the deletion, so we'll have to lose it.
1480 is_lost = true;
1481 } else if (!ReadLockFenceHasPassed(&resource)) {
1482 // TODO(dcastagna): see if it's possible to use this logic for
1483 // the branch above too, where the resource is locked or still exported.
1484 if (style != FOR_SHUTDOWN && !child_info->marked_for_deletion) {
1485 // Defer this resource deletion.
1486 resource.marked_for_deletion = true;
1487 continue;
1489 // We can't postpone the deletion, so we'll have to lose it.
1490 is_lost = true;
1493 if (gl && resource.filter != resource.original_filter) {
1494 DCHECK(resource.target);
1495 DCHECK(resource.gl_id);
1497 gl->BindTexture(resource.target, resource.gl_id);
1498 gl->TexParameteri(resource.target, GL_TEXTURE_MIN_FILTER,
1499 resource.original_filter);
1500 gl->TexParameteri(resource.target, GL_TEXTURE_MAG_FILTER,
1501 resource.original_filter);
1504 ReturnedResource returned;
1505 returned.id = child_id;
1506 returned.sync_point = resource.mailbox.sync_point();
1507 if (!returned.sync_point && resource.type == RESOURCE_TYPE_GL_TEXTURE)
1508 need_sync_point = true;
1509 returned.count = resource.imported_count;
1510 returned.lost = is_lost;
1511 to_return.push_back(returned);
1513 child_info->parent_to_child_map.erase(local_id);
1514 child_info->child_to_parent_map.erase(child_id);
1515 resource.imported_count = 0;
1516 DeleteResourceInternal(it, style);
1518 if (need_sync_point && child_info->needs_sync_points) {
1519 DCHECK(gl);
1520 GLuint sync_point = gl->InsertSyncPointCHROMIUM();
1521 for (size_t i = 0; i < to_return.size(); ++i) {
1522 if (!to_return[i].sync_point)
1523 to_return[i].sync_point = sync_point;
1527 if (!to_return.empty())
1528 child_info->return_callback.Run(to_return,
1529 blocking_main_thread_task_runner_);
1531 if (child_info->marked_for_deletion &&
1532 child_info->parent_to_child_map.empty()) {
1533 DCHECK(child_info->child_to_parent_map.empty());
1534 children_.erase(child_it);
1538 void ResourceProvider::AcquirePixelBuffer(ResourceId id) {
1539 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug"),
1540 "ResourceProvider::AcquirePixelBuffer");
1542 Resource* resource = GetResource(id);
1543 DCHECK(resource->origin == Resource::INTERNAL);
1544 DCHECK_EQ(resource->exported_count, 0);
1545 DCHECK(!resource->image_id);
1546 DCHECK_NE(ETC1, resource->format);
1548 DCHECK_EQ(RESOURCE_TYPE_GL_TEXTURE, resource->type);
1549 GLES2Interface* gl = ContextGL();
1550 DCHECK(gl);
1551 if (!resource->gl_pixel_buffer_id)
1552 resource->gl_pixel_buffer_id = buffer_id_allocator_->NextId();
1553 gl->BindBuffer(GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM,
1554 resource->gl_pixel_buffer_id);
1555 size_t resource_bytes = ResourceUtil::UncheckedSizeInBytesAligned<size_t>(
1556 resource->size, resource->format);
1557 gl->BufferData(GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM, resource_bytes, NULL,
1558 GL_DYNAMIC_DRAW);
1559 gl->BindBuffer(GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM, 0);
1562 void ResourceProvider::ReleasePixelBuffer(ResourceId id) {
1563 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug"),
1564 "ResourceProvider::ReleasePixelBuffer");
1566 Resource* resource = GetResource(id);
1567 DCHECK(resource->origin == Resource::INTERNAL);
1568 DCHECK_EQ(resource->exported_count, 0);
1569 DCHECK(!resource->image_id);
1571 // The pixel buffer can be released while there is a pending "set pixels"
1572 // if completion has been forced. Any shared memory associated with this
1573 // pixel buffer will not be freed until the waitAsyncTexImage2DCHROMIUM
1574 // command has been processed on the service side. It is also safe to
1575 // reuse any query id associated with this resource before they complete
1576 // as each new query has a unique submit count.
1577 if (resource->pending_set_pixels) {
1578 DCHECK(resource->set_pixels_completion_forced);
1579 resource->pending_set_pixels = false;
1580 resource->locked_for_write = false;
1583 DCHECK_EQ(RESOURCE_TYPE_GL_TEXTURE, resource->type);
1584 if (!resource->gl_pixel_buffer_id)
1585 return;
1586 GLES2Interface* gl = ContextGL();
1587 DCHECK(gl);
1588 gl->BindBuffer(GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM,
1589 resource->gl_pixel_buffer_id);
1590 gl->BufferData(
1591 GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM, 0, NULL, GL_DYNAMIC_DRAW);
1592 gl->BindBuffer(GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM, 0);
1595 uint8_t* ResourceProvider::MapPixelBuffer(ResourceId id, int* stride) {
1596 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug"),
1597 "ResourceProvider::MapPixelBuffer");
1599 Resource* resource = GetResource(id);
1600 DCHECK(resource->origin == Resource::INTERNAL);
1601 DCHECK_EQ(resource->exported_count, 0);
1602 DCHECK(!resource->image_id);
1604 *stride = 0;
1605 DCHECK_EQ(RESOURCE_TYPE_GL_TEXTURE, resource->type);
1606 GLES2Interface* gl = ContextGL();
1607 DCHECK(gl);
1608 DCHECK(resource->gl_pixel_buffer_id);
1609 gl->BindBuffer(GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM,
1610 resource->gl_pixel_buffer_id);
1611 uint8_t* image = static_cast<uint8_t*>(gl->MapBufferCHROMIUM(
1612 GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM, GL_WRITE_ONLY));
1613 gl->BindBuffer(GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM, 0);
1614 // Buffer is required to be 4-byte aligned.
1615 CHECK(!(reinterpret_cast<intptr_t>(image) & 3));
1616 return image;
1619 void ResourceProvider::UnmapPixelBuffer(ResourceId id) {
1620 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug"),
1621 "ResourceProvider::UnmapPixelBuffer");
1623 Resource* resource = GetResource(id);
1624 DCHECK(resource->origin == Resource::INTERNAL);
1625 DCHECK_EQ(resource->exported_count, 0);
1626 DCHECK(!resource->image_id);
1628 DCHECK_EQ(RESOURCE_TYPE_GL_TEXTURE, resource->type);
1629 GLES2Interface* gl = ContextGL();
1630 DCHECK(gl);
1631 DCHECK(resource->gl_pixel_buffer_id);
1632 gl->BindBuffer(GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM,
1633 resource->gl_pixel_buffer_id);
1634 gl->UnmapBufferCHROMIUM(GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM);
1635 gl->BindBuffer(GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM, 0);
1638 GLenum ResourceProvider::BindForSampling(ResourceId resource_id,
1639 GLenum unit,
1640 GLenum filter) {
1641 DCHECK(thread_checker_.CalledOnValidThread());
1642 GLES2Interface* gl = ContextGL();
1643 ResourceMap::iterator it = resources_.find(resource_id);
1644 DCHECK(it != resources_.end());
1645 Resource* resource = &it->second;
1646 DCHECK(resource->lock_for_read_count);
1647 DCHECK(!resource->locked_for_write || resource->set_pixels_completion_forced);
1649 ScopedSetActiveTexture scoped_active_tex(gl, unit);
1650 GLenum target = resource->target;
1651 gl->BindTexture(target, resource->gl_id);
1652 if (filter != resource->filter) {
1653 gl->TexParameteri(target, GL_TEXTURE_MIN_FILTER, filter);
1654 gl->TexParameteri(target, GL_TEXTURE_MAG_FILTER, filter);
1655 resource->filter = filter;
1658 if (resource->image_id && resource->dirty_image)
1659 BindImageForSampling(resource);
1661 return target;
1664 void ResourceProvider::BeginSetPixels(ResourceId id) {
1665 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug"),
1666 "ResourceProvider::BeginSetPixels");
1668 Resource* resource = GetResource(id);
1669 DCHECK(!resource->pending_set_pixels);
1671 LazyCreate(resource);
1672 DCHECK(resource->origin == Resource::INTERNAL);
1673 DCHECK(resource->gl_id || resource->allocated);
1674 DCHECK(ReadLockFenceHasPassed(resource));
1675 DCHECK(!resource->image_id);
1677 bool allocate = !resource->allocated;
1678 resource->allocated = true;
1679 LockForWrite(id);
1681 DCHECK_EQ(RESOURCE_TYPE_GL_TEXTURE, resource->type);
1682 DCHECK(resource->gl_id);
1683 GLES2Interface* gl = ContextGL();
1684 DCHECK(gl);
1685 DCHECK(resource->gl_pixel_buffer_id);
1686 DCHECK_EQ(resource->target, static_cast<GLenum>(GL_TEXTURE_2D));
1687 gl->BindTexture(GL_TEXTURE_2D, resource->gl_id);
1688 gl->BindBuffer(GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM,
1689 resource->gl_pixel_buffer_id);
1690 if (!resource->gl_upload_query_id)
1691 gl->GenQueriesEXT(1, &resource->gl_upload_query_id);
1692 gl->BeginQueryEXT(GL_ASYNC_PIXEL_UNPACK_COMPLETED_CHROMIUM,
1693 resource->gl_upload_query_id);
1694 if (allocate) {
1695 gl->AsyncTexImage2DCHROMIUM(GL_TEXTURE_2D,
1696 0, /* level */
1697 GLInternalFormat(resource->format),
1698 resource->size.width(),
1699 resource->size.height(),
1700 0, /* border */
1701 GLDataFormat(resource->format),
1702 GLDataType(resource->format),
1703 NULL);
1704 } else {
1705 gl->AsyncTexSubImage2DCHROMIUM(GL_TEXTURE_2D,
1706 0, /* level */
1707 0, /* x */
1708 0, /* y */
1709 resource->size.width(),
1710 resource->size.height(),
1711 GLDataFormat(resource->format),
1712 GLDataType(resource->format),
1713 NULL);
1715 gl->EndQueryEXT(GL_ASYNC_PIXEL_UNPACK_COMPLETED_CHROMIUM);
1716 gl->BindBuffer(GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM, 0);
1718 resource->pending_set_pixels = true;
1719 resource->set_pixels_completion_forced = false;
1722 void ResourceProvider::ForceSetPixelsToComplete(ResourceId id) {
1723 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug"),
1724 "ResourceProvider::ForceSetPixelsToComplete");
1726 Resource* resource = GetResource(id);
1728 DCHECK(resource->locked_for_write);
1729 DCHECK(resource->pending_set_pixels);
1730 DCHECK(!resource->set_pixels_completion_forced);
1732 if (resource->gl_id) {
1733 GLES2Interface* gl = ContextGL();
1734 gl->BindTexture(GL_TEXTURE_2D, resource->gl_id);
1735 gl->WaitAsyncTexImage2DCHROMIUM(GL_TEXTURE_2D);
1736 gl->BindTexture(GL_TEXTURE_2D, 0);
1739 resource->set_pixels_completion_forced = true;
1742 bool ResourceProvider::DidSetPixelsComplete(ResourceId id) {
1743 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug"),
1744 "ResourceProvider::DidSetPixelsComplete");
1746 Resource* resource = GetResource(id);
1748 DCHECK(resource->locked_for_write);
1749 DCHECK(resource->pending_set_pixels);
1751 if (resource->gl_id) {
1752 GLES2Interface* gl = ContextGL();
1753 DCHECK(gl);
1754 DCHECK(resource->gl_upload_query_id);
1755 GLuint complete = 1;
1756 gl->GetQueryObjectuivEXT(
1757 resource->gl_upload_query_id, GL_QUERY_RESULT_AVAILABLE_EXT, &complete);
1758 if (!complete)
1759 return false;
1762 resource->pending_set_pixels = false;
1763 UnlockForWrite(resource);
1765 // Async set pixels commands are not necessarily processed in-sequence with
1766 // drawing commands. Read lock fences are required to ensure that async
1767 // commands don't access the resource while used for drawing.
1768 resource->read_lock_fences_enabled = true;
1770 return true;
1773 void ResourceProvider::CreateForTesting(ResourceId id) {
1774 LazyCreate(GetResource(id));
1777 GLenum ResourceProvider::TargetForTesting(ResourceId id) {
1778 Resource* resource = GetResource(id);
1779 return resource->target;
1782 void ResourceProvider::LazyCreate(Resource* resource) {
1783 if (resource->type != RESOURCE_TYPE_GL_TEXTURE ||
1784 resource->origin != Resource::INTERNAL)
1785 return;
1787 if (resource->gl_id)
1788 return;
1790 DCHECK(resource->texture_pool);
1791 DCHECK(resource->origin == Resource::INTERNAL);
1792 DCHECK(!resource->mailbox.IsValid());
1793 resource->gl_id = texture_id_allocator_->NextId();
1795 GLES2Interface* gl = ContextGL();
1796 DCHECK(gl);
1798 // Create and set texture properties. Allocation is delayed until needed.
1799 gl->BindTexture(resource->target, resource->gl_id);
1800 gl->TexParameteri(resource->target, GL_TEXTURE_MIN_FILTER,
1801 resource->original_filter);
1802 gl->TexParameteri(resource->target, GL_TEXTURE_MAG_FILTER,
1803 resource->original_filter);
1804 gl->TexParameteri(resource->target, GL_TEXTURE_WRAP_S, resource->wrap_mode);
1805 gl->TexParameteri(resource->target, GL_TEXTURE_WRAP_T, resource->wrap_mode);
1806 gl->TexParameteri(resource->target, GL_TEXTURE_POOL_CHROMIUM,
1807 resource->texture_pool);
1808 if (use_texture_usage_hint_ && (resource->hint & TEXTURE_HINT_FRAMEBUFFER)) {
1809 gl->TexParameteri(resource->target, GL_TEXTURE_USAGE_ANGLE,
1810 GL_FRAMEBUFFER_ATTACHMENT_ANGLE);
1814 void ResourceProvider::AllocateForTesting(ResourceId id) {
1815 LazyAllocate(GetResource(id));
1818 void ResourceProvider::LazyAllocate(Resource* resource) {
1819 DCHECK(resource);
1820 if (resource->allocated)
1821 return;
1822 LazyCreate(resource);
1823 if (!resource->gl_id)
1824 return;
1825 resource->allocated = true;
1826 GLES2Interface* gl = ContextGL();
1827 gfx::Size& size = resource->size;
1828 ResourceFormat format = resource->format;
1829 gl->BindTexture(resource->target, resource->gl_id);
1830 if (use_texture_storage_ext_ &&
1831 IsFormatSupportedForStorage(format, use_texture_format_bgra_) &&
1832 (resource->hint & TEXTURE_HINT_IMMUTABLE)) {
1833 GLenum storage_format = TextureToStorageFormat(format);
1834 gl->TexStorage2DEXT(resource->target, 1, storage_format, size.width(),
1835 size.height());
1836 } else {
1837 // ETC1 does not support preallocation.
1838 if (format != ETC1) {
1839 gl->TexImage2D(resource->target, 0, GLInternalFormat(format),
1840 size.width(), size.height(), 0, GLDataFormat(format),
1841 GLDataType(format), NULL);
1846 void ResourceProvider::BindImageForSampling(Resource* resource) {
1847 GLES2Interface* gl = ContextGL();
1848 DCHECK(resource->gl_id);
1849 DCHECK(resource->image_id);
1851 // Release image currently bound to texture.
1852 if (resource->bound_image_id)
1853 gl->ReleaseTexImage2DCHROMIUM(resource->target, resource->bound_image_id);
1854 gl->BindTexImage2DCHROMIUM(resource->target, resource->image_id);
1855 resource->bound_image_id = resource->image_id;
1856 resource->dirty_image = false;
1859 void ResourceProvider::CopyResource(ResourceId source_id,
1860 ResourceId dest_id,
1861 const gfx::Rect& rect) {
1862 TRACE_EVENT0("cc", "ResourceProvider::CopyResource");
1864 Resource* source_resource = GetResource(source_id);
1865 DCHECK(!source_resource->lock_for_read_count);
1866 DCHECK(source_resource->origin == Resource::INTERNAL);
1867 DCHECK_EQ(source_resource->exported_count, 0);
1868 DCHECK_EQ(RESOURCE_TYPE_GL_TEXTURE, source_resource->type);
1869 LazyAllocate(source_resource);
1871 Resource* dest_resource = GetResource(dest_id);
1872 DCHECK(!dest_resource->locked_for_write);
1873 DCHECK(!dest_resource->lock_for_read_count);
1874 DCHECK(dest_resource->origin == Resource::INTERNAL);
1875 DCHECK_EQ(dest_resource->exported_count, 0);
1876 DCHECK_EQ(RESOURCE_TYPE_GL_TEXTURE, dest_resource->type);
1877 LazyAllocate(dest_resource);
1879 DCHECK_EQ(source_resource->type, dest_resource->type);
1880 DCHECK_EQ(source_resource->format, dest_resource->format);
1881 DCHECK(source_resource->size == dest_resource->size);
1882 DCHECK(gfx::Rect(dest_resource->size).Contains(rect));
1884 GLES2Interface* gl = ContextGL();
1885 DCHECK(gl);
1886 if (source_resource->image_id && source_resource->dirty_image) {
1887 gl->BindTexture(source_resource->target, source_resource->gl_id);
1888 BindImageForSampling(source_resource);
1890 if (use_sync_query_) {
1891 if (!source_resource->gl_read_lock_query_id)
1892 gl->GenQueriesEXT(1, &source_resource->gl_read_lock_query_id);
1893 #if defined(OS_CHROMEOS)
1894 // TODO(reveman): This avoids a performance problem on some ChromeOS
1895 // devices. This needs to be removed to support native GpuMemoryBuffer
1896 // implementations. crbug.com/436314
1897 gl->BeginQueryEXT(GL_COMMANDS_ISSUED_CHROMIUM,
1898 source_resource->gl_read_lock_query_id);
1899 #else
1900 gl->BeginQueryEXT(GL_COMMANDS_COMPLETED_CHROMIUM,
1901 source_resource->gl_read_lock_query_id);
1902 #endif
1904 DCHECK(!dest_resource->image_id);
1905 dest_resource->allocated = true;
1906 gl->CopySubTextureCHROMIUM(dest_resource->target, source_resource->gl_id,
1907 dest_resource->gl_id, rect.x(), rect.y(), rect.x(),
1908 rect.y(), rect.width(), rect.height(),
1909 false, false, false);
1910 if (source_resource->gl_read_lock_query_id) {
1911 // End query and create a read lock fence that will prevent access to
1912 // source resource until CopySubTextureCHROMIUM command has completed.
1913 #if defined(OS_CHROMEOS)
1914 gl->EndQueryEXT(GL_COMMANDS_ISSUED_CHROMIUM);
1915 #else
1916 gl->EndQueryEXT(GL_COMMANDS_COMPLETED_CHROMIUM);
1917 #endif
1918 source_resource->read_lock_fence = make_scoped_refptr(
1919 new CopyTextureFence(gl, source_resource->gl_read_lock_query_id));
1920 } else {
1921 // Create a SynchronousFence when CHROMIUM_sync_query extension is missing.
1922 // Try to use one synchronous fence for as many CopyResource operations as
1923 // possible as that reduce the number of times we have to synchronize with
1924 // the GL.
1925 if (!synchronous_fence_.get() || synchronous_fence_->has_synchronized())
1926 synchronous_fence_ = make_scoped_refptr(new SynchronousFence(gl));
1927 source_resource->read_lock_fence = synchronous_fence_;
1928 source_resource->read_lock_fence->Set();
1932 void ResourceProvider::WaitSyncPointIfNeeded(ResourceId id) {
1933 Resource* resource = GetResource(id);
1934 DCHECK_EQ(resource->exported_count, 0);
1935 DCHECK(resource->allocated);
1936 if (resource->type != RESOURCE_TYPE_GL_TEXTURE || resource->gl_id)
1937 return;
1938 if (!resource->mailbox.sync_point())
1939 return;
1940 DCHECK(resource->mailbox.IsValid());
1941 GLES2Interface* gl = ContextGL();
1942 DCHECK(gl);
1943 gl->WaitSyncPointCHROMIUM(resource->mailbox.sync_point());
1944 resource->mailbox.set_sync_point(0);
1947 void ResourceProvider::WaitReadLockIfNeeded(ResourceId id) {
1948 Resource* resource = GetResource(id);
1949 DCHECK_EQ(resource->exported_count, 0);
1950 if (!resource->read_lock_fence.get())
1951 return;
1953 resource->read_lock_fence->Wait();
1956 GLint ResourceProvider::GetActiveTextureUnit(GLES2Interface* gl) {
1957 GLint active_unit = 0;
1958 gl->GetIntegerv(GL_ACTIVE_TEXTURE, &active_unit);
1959 return active_unit;
1962 GLenum ResourceProvider::GetImageTextureTarget(ResourceFormat format) {
1963 gfx::BufferFormat buffer_format = ToGpuMemoryBufferFormat(format);
1964 DCHECK_GT(use_image_texture_targets_.size(),
1965 static_cast<size_t>(buffer_format));
1966 return use_image_texture_targets_[static_cast<size_t>(buffer_format)];
1969 void ResourceProvider::ValidateResource(ResourceId id) const {
1970 DCHECK(thread_checker_.CalledOnValidThread());
1971 DCHECK(id);
1972 DCHECK(resources_.find(id) != resources_.end());
1975 GLES2Interface* ResourceProvider::ContextGL() const {
1976 ContextProvider* context_provider = output_surface_->context_provider();
1977 return context_provider ? context_provider->ContextGL() : NULL;
1980 class GrContext* ResourceProvider::GrContext(bool worker_context) const {
1981 ContextProvider* context_provider =
1982 worker_context ? output_surface_->worker_context_provider()
1983 : output_surface_->context_provider();
1984 return context_provider ? context_provider->GrContext() : NULL;
1987 bool ResourceProvider::OnMemoryDump(
1988 const base::trace_event::MemoryDumpArgs& args,
1989 base::trace_event::ProcessMemoryDump* pmd) {
1990 DCHECK(thread_checker_.CalledOnValidThread());
1992 const uint64 tracing_process_id =
1993 base::trace_event::MemoryDumpManager::GetInstance()
1994 ->GetTracingProcessId();
1996 for (const auto& resource_entry : resources_) {
1997 const auto& resource = resource_entry.second;
1999 // Resource IDs are not process-unique, so log with the ResourceProvider's
2000 // unique id.
2001 std::string dump_name = base::StringPrintf(
2002 "cc/resource_memory/resource_provider_%d/resource_%d", tracing_id_,
2003 resource_entry.first);
2004 base::trace_event::MemoryAllocatorDump* dump =
2005 pmd->CreateAllocatorDump(dump_name);
2007 uint64_t total_bytes = ResourceUtil::UncheckedSizeInBytesAligned<size_t>(
2008 resource.size, resource.format);
2009 dump->AddScalar(base::trace_event::MemoryAllocatorDump::kNameSize,
2010 base::trace_event::MemoryAllocatorDump::kUnitsBytes,
2011 static_cast<uint64_t>(total_bytes));
2013 // Resources which are shared across processes require a shared GUID to
2014 // prevent double counting the memory. We currently support shared GUIDs for
2015 // GpuMemoryBuffer, SharedBitmap, and GL backed resources.
2016 base::trace_event::MemoryAllocatorDumpGuid guid;
2017 if (resource.gpu_memory_buffer) {
2018 guid = gfx::GetGpuMemoryBufferGUIDForTracing(
2019 tracing_process_id, resource.gpu_memory_buffer->GetHandle().id);
2020 } else if (resource.shared_bitmap) {
2021 guid = GetSharedBitmapGUIDForTracing(resource.shared_bitmap->id());
2022 } else if (resource.gl_id && resource.allocated) {
2023 guid =
2024 gfx::GetGLTextureGUIDForTracing(tracing_process_id, resource.gl_id);
2027 if (!guid.empty()) {
2028 const int kImportance = 2;
2029 pmd->CreateSharedGlobalAllocatorDump(guid);
2030 pmd->AddOwnershipEdge(dump->guid(), guid, kImportance);
2034 return true;
2037 } // namespace cc