aw: Move SharedRendererState out of AwContents
[chromium-blink-merge.git] / cc / resources / resource_provider.cc
blob023a1cdbf068832875073a5601c29420043d74b5
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/containers/hash_tables.h"
11 #include "base/debug/trace_event.h"
12 #include "base/stl_util.h"
13 #include "base/strings/string_split.h"
14 #include "base/strings/string_util.h"
15 #include "cc/base/util.h"
16 #include "cc/output/gl_renderer.h" // For the GLC() macro.
17 #include "cc/resources/platform_color.h"
18 #include "cc/resources/returned_resource.h"
19 #include "cc/resources/shared_bitmap_manager.h"
20 #include "cc/resources/texture_uploader.h"
21 #include "cc/resources/transferable_resource.h"
22 #include "gpu/GLES2/gl2extchromium.h"
23 #include "gpu/command_buffer/client/gles2_interface.h"
24 #include "gpu/command_buffer/client/gpu_memory_buffer_manager.h"
25 #include "third_party/khronos/GLES2/gl2.h"
26 #include "third_party/khronos/GLES2/gl2ext.h"
27 #include "third_party/skia/include/core/SkSurface.h"
28 #include "third_party/skia/include/gpu/GrContext.h"
29 #include "ui/gfx/frame_time.h"
30 #include "ui/gfx/geometry/rect.h"
31 #include "ui/gfx/geometry/vector2d.h"
32 #include "ui/gfx/gpu_memory_buffer.h"
34 using gpu::gles2::GLES2Interface;
36 namespace cc {
38 class IdAllocator {
39 public:
40 virtual ~IdAllocator() {}
42 virtual GLuint NextId() = 0;
44 protected:
45 IdAllocator(GLES2Interface* gl, size_t id_allocation_chunk_size)
46 : gl_(gl),
47 id_allocation_chunk_size_(id_allocation_chunk_size),
48 ids_(new GLuint[id_allocation_chunk_size]),
49 next_id_index_(id_allocation_chunk_size) {
50 DCHECK(id_allocation_chunk_size_);
53 GLES2Interface* gl_;
54 const size_t id_allocation_chunk_size_;
55 scoped_ptr<GLuint[]> ids_;
56 size_t next_id_index_;
59 namespace {
61 // Measured in seconds.
62 const double kSoftwareUploadTickRate = 0.000250;
63 const double kTextureUploadTickRate = 0.004;
65 GLenum TextureToStorageFormat(ResourceFormat format) {
66 GLenum storage_format = GL_RGBA8_OES;
67 switch (format) {
68 case RGBA_8888:
69 break;
70 case BGRA_8888:
71 storage_format = GL_BGRA8_EXT;
72 break;
73 case RGBA_4444:
74 case ALPHA_8:
75 case LUMINANCE_8:
76 case RGB_565:
77 case ETC1:
78 NOTREACHED();
79 break;
82 return storage_format;
85 bool IsFormatSupportedForStorage(ResourceFormat format, bool use_bgra) {
86 switch (format) {
87 case RGBA_8888:
88 return true;
89 case BGRA_8888:
90 return use_bgra;
91 case RGBA_4444:
92 case ALPHA_8:
93 case LUMINANCE_8:
94 case RGB_565:
95 case ETC1:
96 return false;
98 return false;
101 GrPixelConfig ToGrPixelConfig(ResourceFormat format) {
102 switch (format) {
103 case RGBA_8888:
104 return kRGBA_8888_GrPixelConfig;
105 case BGRA_8888:
106 return kBGRA_8888_GrPixelConfig;
107 case RGBA_4444:
108 return kRGBA_4444_GrPixelConfig;
109 default:
110 break;
112 DCHECK(false) << "Unsupported resource format.";
113 return kSkia8888_GrPixelConfig;
116 gfx::GpuMemoryBuffer::Format ToGpuMemoryBufferFormat(ResourceFormat format) {
117 switch (format) {
118 case RGBA_8888:
119 return gfx::GpuMemoryBuffer::Format::RGBA_8888;
120 case BGRA_8888:
121 return gfx::GpuMemoryBuffer::Format::BGRA_8888;
122 case RGBA_4444:
123 case ALPHA_8:
124 case LUMINANCE_8:
125 case RGB_565:
126 case ETC1:
127 break;
129 NOTREACHED();
130 return gfx::GpuMemoryBuffer::Format::RGBA_8888;
133 class ScopedSetActiveTexture {
134 public:
135 ScopedSetActiveTexture(GLES2Interface* gl, GLenum unit)
136 : gl_(gl), unit_(unit) {
137 DCHECK_EQ(GL_TEXTURE0, ResourceProvider::GetActiveTextureUnit(gl_));
139 if (unit_ != GL_TEXTURE0)
140 GLC(gl_, gl_->ActiveTexture(unit_));
143 ~ScopedSetActiveTexture() {
144 // Active unit being GL_TEXTURE0 is effectively the ground state.
145 if (unit_ != GL_TEXTURE0)
146 GLC(gl_, gl_->ActiveTexture(GL_TEXTURE0));
149 private:
150 GLES2Interface* gl_;
151 GLenum unit_;
154 class TextureIdAllocator : public IdAllocator {
155 public:
156 TextureIdAllocator(GLES2Interface* gl,
157 size_t texture_id_allocation_chunk_size)
158 : IdAllocator(gl, texture_id_allocation_chunk_size) {}
159 ~TextureIdAllocator() override {
160 gl_->DeleteTextures(id_allocation_chunk_size_ - next_id_index_,
161 ids_.get() + next_id_index_);
164 // Overridden from IdAllocator:
165 GLuint NextId() override {
166 if (next_id_index_ == id_allocation_chunk_size_) {
167 gl_->GenTextures(id_allocation_chunk_size_, ids_.get());
168 next_id_index_ = 0;
171 return ids_[next_id_index_++];
174 private:
175 DISALLOW_COPY_AND_ASSIGN(TextureIdAllocator);
178 class BufferIdAllocator : public IdAllocator {
179 public:
180 BufferIdAllocator(GLES2Interface* gl, size_t buffer_id_allocation_chunk_size)
181 : IdAllocator(gl, buffer_id_allocation_chunk_size) {}
182 ~BufferIdAllocator() override {
183 gl_->DeleteBuffers(id_allocation_chunk_size_ - next_id_index_,
184 ids_.get() + next_id_index_);
187 // Overridden from IdAllocator:
188 GLuint NextId() override {
189 if (next_id_index_ == id_allocation_chunk_size_) {
190 gl_->GenBuffers(id_allocation_chunk_size_, ids_.get());
191 next_id_index_ = 0;
194 return ids_[next_id_index_++];
197 private:
198 DISALLOW_COPY_AND_ASSIGN(BufferIdAllocator);
201 // Generic fence implementation for query objects. Fence has passed when query
202 // result is available.
203 class QueryFence : public ResourceProvider::Fence {
204 public:
205 QueryFence(gpu::gles2::GLES2Interface* gl, unsigned query_id)
206 : gl_(gl), query_id_(query_id) {}
208 // Overridden from ResourceProvider::Fence:
209 void Set() override {}
210 bool HasPassed() override {
211 unsigned available = 1;
212 gl_->GetQueryObjectuivEXT(
213 query_id_, GL_QUERY_RESULT_AVAILABLE_EXT, &available);
214 return !!available;
216 void Wait() override {
217 unsigned result = 0;
218 gl_->GetQueryObjectuivEXT(query_id_, GL_QUERY_RESULT_EXT, &result);
221 private:
222 ~QueryFence() override {}
224 gpu::gles2::GLES2Interface* gl_;
225 unsigned query_id_;
227 DISALLOW_COPY_AND_ASSIGN(QueryFence);
230 } // namespace
232 ResourceProvider::Resource::Resource()
233 : child_id(0),
234 gl_id(0),
235 gl_pixel_buffer_id(0),
236 gl_upload_query_id(0),
237 gl_read_lock_query_id(0),
238 pixels(NULL),
239 lock_for_read_count(0),
240 imported_count(0),
241 exported_count(0),
242 dirty_image(false),
243 locked_for_write(false),
244 lost(false),
245 marked_for_deletion(false),
246 pending_set_pixels(false),
247 set_pixels_completion_forced(false),
248 allocated(false),
249 read_lock_fences_enabled(false),
250 has_shared_bitmap_id(false),
251 allow_overlay(false),
252 read_lock_fence(NULL),
253 size(),
254 origin(Internal),
255 target(0),
256 original_filter(0),
257 filter(0),
258 image_id(0),
259 bound_image_id(0),
260 texture_pool(0),
261 wrap_mode(0),
262 hint(TextureHintImmutable),
263 type(InvalidType),
264 format(RGBA_8888),
265 shared_bitmap(NULL),
266 gpu_memory_buffer(NULL) {
269 ResourceProvider::Resource::~Resource() {}
271 ResourceProvider::Resource::Resource(GLuint texture_id,
272 const gfx::Size& size,
273 Origin origin,
274 GLenum target,
275 GLenum filter,
276 GLenum texture_pool,
277 GLint wrap_mode,
278 TextureHint hint,
279 ResourceFormat format)
280 : child_id(0),
281 gl_id(texture_id),
282 gl_pixel_buffer_id(0),
283 gl_upload_query_id(0),
284 gl_read_lock_query_id(0),
285 pixels(NULL),
286 lock_for_read_count(0),
287 imported_count(0),
288 exported_count(0),
289 dirty_image(false),
290 locked_for_write(false),
291 lost(false),
292 marked_for_deletion(false),
293 pending_set_pixels(false),
294 set_pixels_completion_forced(false),
295 allocated(false),
296 read_lock_fences_enabled(false),
297 has_shared_bitmap_id(false),
298 allow_overlay(false),
299 read_lock_fence(NULL),
300 size(size),
301 origin(origin),
302 target(target),
303 original_filter(filter),
304 filter(filter),
305 image_id(0),
306 bound_image_id(0),
307 texture_pool(texture_pool),
308 wrap_mode(wrap_mode),
309 hint(hint),
310 type(GLTexture),
311 format(format),
312 shared_bitmap(NULL),
313 gpu_memory_buffer(NULL) {
314 DCHECK(wrap_mode == GL_CLAMP_TO_EDGE || wrap_mode == GL_REPEAT);
315 DCHECK_EQ(origin == Internal, !!texture_pool);
318 ResourceProvider::Resource::Resource(uint8_t* pixels,
319 SharedBitmap* bitmap,
320 const gfx::Size& size,
321 Origin origin,
322 GLenum filter,
323 GLint wrap_mode)
324 : child_id(0),
325 gl_id(0),
326 gl_pixel_buffer_id(0),
327 gl_upload_query_id(0),
328 gl_read_lock_query_id(0),
329 pixels(pixels),
330 lock_for_read_count(0),
331 imported_count(0),
332 exported_count(0),
333 dirty_image(false),
334 locked_for_write(false),
335 lost(false),
336 marked_for_deletion(false),
337 pending_set_pixels(false),
338 set_pixels_completion_forced(false),
339 allocated(false),
340 read_lock_fences_enabled(false),
341 has_shared_bitmap_id(!!bitmap),
342 allow_overlay(false),
343 read_lock_fence(NULL),
344 size(size),
345 origin(origin),
346 target(0),
347 original_filter(filter),
348 filter(filter),
349 image_id(0),
350 bound_image_id(0),
351 texture_pool(0),
352 wrap_mode(wrap_mode),
353 hint(TextureHintImmutable),
354 type(Bitmap),
355 format(RGBA_8888),
356 shared_bitmap(bitmap),
357 gpu_memory_buffer(NULL) {
358 DCHECK(wrap_mode == GL_CLAMP_TO_EDGE || wrap_mode == GL_REPEAT);
359 DCHECK(origin == Delegated || pixels);
360 if (bitmap)
361 shared_bitmap_id = bitmap->id();
364 ResourceProvider::Resource::Resource(const SharedBitmapId& bitmap_id,
365 const gfx::Size& size,
366 Origin origin,
367 GLenum filter,
368 GLint wrap_mode)
369 : child_id(0),
370 gl_id(0),
371 gl_pixel_buffer_id(0),
372 gl_upload_query_id(0),
373 gl_read_lock_query_id(0),
374 pixels(NULL),
375 lock_for_read_count(0),
376 imported_count(0),
377 exported_count(0),
378 dirty_image(false),
379 locked_for_write(false),
380 lost(false),
381 marked_for_deletion(false),
382 pending_set_pixels(false),
383 set_pixels_completion_forced(false),
384 allocated(false),
385 read_lock_fences_enabled(false),
386 has_shared_bitmap_id(true),
387 allow_overlay(false),
388 read_lock_fence(NULL),
389 size(size),
390 origin(origin),
391 target(0),
392 original_filter(filter),
393 filter(filter),
394 image_id(0),
395 bound_image_id(0),
396 texture_pool(0),
397 wrap_mode(wrap_mode),
398 hint(TextureHintImmutable),
399 type(Bitmap),
400 format(RGBA_8888),
401 shared_bitmap_id(bitmap_id),
402 shared_bitmap(NULL),
403 gpu_memory_buffer(NULL) {
404 DCHECK(wrap_mode == GL_CLAMP_TO_EDGE || wrap_mode == GL_REPEAT);
407 ResourceProvider::Child::Child() : marked_for_deletion(false) {}
409 ResourceProvider::Child::~Child() {}
411 scoped_ptr<ResourceProvider> ResourceProvider::Create(
412 OutputSurface* output_surface,
413 SharedBitmapManager* shared_bitmap_manager,
414 gpu::GpuMemoryBufferManager* gpu_memory_buffer_manager,
415 BlockingTaskRunner* blocking_main_thread_task_runner,
416 int highp_threshold_min,
417 bool use_rgba_4444_texture_format,
418 size_t id_allocation_chunk_size) {
419 scoped_ptr<ResourceProvider> resource_provider(
420 new ResourceProvider(output_surface,
421 shared_bitmap_manager,
422 gpu_memory_buffer_manager,
423 blocking_main_thread_task_runner,
424 highp_threshold_min,
425 use_rgba_4444_texture_format,
426 id_allocation_chunk_size));
428 if (resource_provider->ContextGL())
429 resource_provider->InitializeGL();
430 else
431 resource_provider->InitializeSoftware();
433 DCHECK_NE(InvalidType, resource_provider->default_resource_type());
434 return resource_provider.Pass();
437 ResourceProvider::~ResourceProvider() {
438 while (!children_.empty())
439 DestroyChildInternal(children_.begin(), ForShutdown);
440 while (!resources_.empty())
441 DeleteResourceInternal(resources_.begin(), ForShutdown);
443 CleanUpGLIfNeeded();
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 bool ResourceProvider::AllowOverlay(ResourceId id) {
458 Resource* resource = GetResource(id);
459 return resource->allow_overlay;
462 ResourceProvider::ResourceId ResourceProvider::CreateResource(
463 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 GLTexture:
470 return CreateGLTexture(size,
471 GL_TEXTURE_2D,
472 GL_TEXTURE_POOL_UNMANAGED_CHROMIUM,
473 wrap_mode,
474 hint,
475 format);
476 case Bitmap:
477 DCHECK_EQ(RGBA_8888, format);
478 return CreateBitmap(size, wrap_mode);
479 case InvalidType:
480 break;
483 LOG(FATAL) << "Invalid default resource type.";
484 return 0;
487 ResourceProvider::ResourceId ResourceProvider::CreateManagedResource(
488 const gfx::Size& size,
489 GLenum target,
490 GLint wrap_mode,
491 TextureHint hint,
492 ResourceFormat format) {
493 DCHECK(!size.IsEmpty());
494 switch (default_resource_type_) {
495 case GLTexture:
496 return CreateGLTexture(size,
497 target,
498 GL_TEXTURE_POOL_MANAGED_CHROMIUM,
499 wrap_mode,
500 hint,
501 format);
502 case Bitmap:
503 DCHECK_EQ(RGBA_8888, format);
504 return CreateBitmap(size, wrap_mode);
505 case InvalidType:
506 break;
509 LOG(FATAL) << "Invalid default resource type.";
510 return 0;
513 ResourceProvider::ResourceId ResourceProvider::CreateGLTexture(
514 const gfx::Size& size,
515 GLenum target,
516 GLenum texture_pool,
517 GLint wrap_mode,
518 TextureHint hint,
519 ResourceFormat format) {
520 DCHECK_LE(size.width(), max_texture_size_);
521 DCHECK_LE(size.height(), max_texture_size_);
522 DCHECK(thread_checker_.CalledOnValidThread());
524 ResourceId id = next_id_++;
525 Resource resource(0,
526 size,
527 Resource::Internal,
528 target,
529 GL_LINEAR,
530 texture_pool,
531 wrap_mode,
532 hint,
533 format);
534 resource.allocated = false;
535 resources_[id] = resource;
536 return id;
539 ResourceProvider::ResourceId ResourceProvider::CreateBitmap(
540 const gfx::Size& size, GLint wrap_mode) {
541 DCHECK(thread_checker_.CalledOnValidThread());
543 scoped_ptr<SharedBitmap> bitmap;
544 if (shared_bitmap_manager_)
545 bitmap = shared_bitmap_manager_->AllocateSharedBitmap(size);
547 uint8_t* pixels;
548 if (bitmap) {
549 pixels = bitmap->pixels();
550 } else {
551 size_t bytes = SharedBitmap::CheckedSizeInBytes(size);
552 pixels = new uint8_t[bytes];
554 DCHECK(pixels);
556 ResourceId id = next_id_++;
557 Resource resource(
558 pixels, bitmap.release(), size, Resource::Internal, GL_LINEAR, wrap_mode);
559 resource.allocated = true;
560 resources_[id] = resource;
561 return id;
564 ResourceProvider::ResourceId ResourceProvider::CreateResourceFromIOSurface(
565 const gfx::Size& size,
566 unsigned io_surface_id) {
567 DCHECK(thread_checker_.CalledOnValidThread());
569 ResourceId id = next_id_++;
570 Resource resource(0,
571 gfx::Size(),
572 Resource::Internal,
573 GL_TEXTURE_RECTANGLE_ARB,
574 GL_LINEAR,
575 GL_TEXTURE_POOL_UNMANAGED_CHROMIUM,
576 GL_CLAMP_TO_EDGE,
577 TextureHintImmutable,
578 RGBA_8888);
579 LazyCreate(&resource);
580 GLES2Interface* gl = ContextGL();
581 DCHECK(gl);
582 gl->BindTexture(GL_TEXTURE_RECTANGLE_ARB, resource.gl_id);
583 gl->TexImageIOSurface2DCHROMIUM(
584 GL_TEXTURE_RECTANGLE_ARB, size.width(), size.height(), io_surface_id, 0);
585 resource.allocated = true;
586 resources_[id] = resource;
587 return id;
590 ResourceProvider::ResourceId ResourceProvider::CreateResourceFromTextureMailbox(
591 const TextureMailbox& mailbox,
592 scoped_ptr<SingleReleaseCallbackImpl> release_callback_impl) {
593 DCHECK(thread_checker_.CalledOnValidThread());
594 // Just store the information. Mailbox will be consumed in LockForRead().
595 ResourceId id = next_id_++;
596 DCHECK(mailbox.IsValid());
597 Resource& resource = resources_[id];
598 if (mailbox.IsTexture()) {
599 resource = Resource(0,
600 gfx::Size(),
601 Resource::External,
602 mailbox.target(),
603 GL_LINEAR,
605 GL_CLAMP_TO_EDGE,
606 TextureHintImmutable,
607 RGBA_8888);
608 } else {
609 DCHECK(mailbox.IsSharedMemory());
610 base::SharedMemory* shared_memory = mailbox.shared_memory();
611 DCHECK(shared_memory->memory());
612 uint8_t* pixels = reinterpret_cast<uint8_t*>(shared_memory->memory());
613 DCHECK(pixels);
614 scoped_ptr<SharedBitmap> shared_bitmap;
615 if (shared_bitmap_manager_) {
616 shared_bitmap =
617 shared_bitmap_manager_->GetBitmapForSharedMemory(shared_memory);
619 resource = Resource(pixels,
620 shared_bitmap.release(),
621 mailbox.shared_memory_size(),
622 Resource::External,
623 GL_LINEAR,
624 GL_CLAMP_TO_EDGE);
626 resource.allocated = true;
627 resource.mailbox = mailbox;
628 resource.release_callback_impl =
629 base::Bind(&SingleReleaseCallbackImpl::Run,
630 base::Owned(release_callback_impl.release()));
631 resource.allow_overlay = mailbox.allow_overlay();
632 return id;
635 void ResourceProvider::DeleteResource(ResourceId id) {
636 DCHECK(thread_checker_.CalledOnValidThread());
637 ResourceMap::iterator it = resources_.find(id);
638 CHECK(it != resources_.end());
639 Resource* resource = &it->second;
640 DCHECK(!resource->marked_for_deletion);
641 DCHECK_EQ(resource->imported_count, 0);
642 DCHECK(resource->pending_set_pixels || !resource->locked_for_write);
644 if (resource->exported_count > 0 || resource->lock_for_read_count > 0) {
645 resource->marked_for_deletion = true;
646 return;
647 } else {
648 DeleteResourceInternal(it, Normal);
652 void ResourceProvider::DeleteResourceInternal(ResourceMap::iterator it,
653 DeleteStyle style) {
654 TRACE_EVENT0("cc", "ResourceProvider::DeleteResourceInternal");
655 Resource* resource = &it->second;
656 bool lost_resource = resource->lost;
658 DCHECK(resource->exported_count == 0 || style != Normal);
659 if (style == ForShutdown && resource->exported_count > 0)
660 lost_resource = true;
662 if (resource->image_id) {
663 DCHECK(resource->origin == Resource::Internal);
664 GLES2Interface* gl = ContextGL();
665 DCHECK(gl);
666 GLC(gl, gl->DestroyImageCHROMIUM(resource->image_id));
668 if (resource->gl_upload_query_id) {
669 DCHECK(resource->origin == Resource::Internal);
670 GLES2Interface* gl = ContextGL();
671 DCHECK(gl);
672 GLC(gl, gl->DeleteQueriesEXT(1, &resource->gl_upload_query_id));
674 if (resource->gl_read_lock_query_id) {
675 DCHECK(resource->origin == Resource::Internal);
676 GLES2Interface* gl = ContextGL();
677 DCHECK(gl);
678 GLC(gl, gl->DeleteQueriesEXT(1, &resource->gl_read_lock_query_id));
680 if (resource->gl_pixel_buffer_id) {
681 DCHECK(resource->origin == Resource::Internal);
682 GLES2Interface* gl = ContextGL();
683 DCHECK(gl);
684 GLC(gl, gl->DeleteBuffers(1, &resource->gl_pixel_buffer_id));
686 if (resource->origin == Resource::External) {
687 DCHECK(resource->mailbox.IsValid());
688 GLuint sync_point = resource->mailbox.sync_point();
689 if (resource->type == GLTexture) {
690 DCHECK(resource->mailbox.IsTexture());
691 lost_resource |= lost_output_surface_;
692 GLES2Interface* gl = ContextGL();
693 DCHECK(gl);
694 if (resource->gl_id) {
695 GLC(gl, gl->DeleteTextures(1, &resource->gl_id));
696 resource->gl_id = 0;
697 if (!lost_resource)
698 sync_point = gl->InsertSyncPointCHROMIUM();
700 } else {
701 DCHECK(resource->mailbox.IsSharedMemory());
702 base::SharedMemory* shared_memory = resource->mailbox.shared_memory();
703 if (resource->pixels && shared_memory) {
704 DCHECK(shared_memory->memory() == resource->pixels);
705 resource->pixels = NULL;
706 delete resource->shared_bitmap;
707 resource->shared_bitmap = NULL;
710 resource->release_callback_impl.Run(
711 sync_point, lost_resource, blocking_main_thread_task_runner_);
713 if (resource->gl_id) {
714 GLES2Interface* gl = ContextGL();
715 DCHECK(gl);
716 GLC(gl, gl->DeleteTextures(1, &resource->gl_id));
717 resource->gl_id = 0;
719 if (resource->shared_bitmap) {
720 DCHECK(resource->origin != Resource::External);
721 DCHECK_EQ(Bitmap, resource->type);
722 delete resource->shared_bitmap;
723 resource->pixels = NULL;
725 if (resource->pixels) {
726 DCHECK(resource->origin == Resource::Internal);
727 delete[] resource->pixels;
728 resource->pixels = NULL;
730 if (resource->gpu_memory_buffer) {
731 DCHECK(resource->origin == Resource::Internal);
732 delete resource->gpu_memory_buffer;
733 resource->gpu_memory_buffer = NULL;
735 resources_.erase(it);
738 ResourceProvider::ResourceType ResourceProvider::GetResourceType(
739 ResourceId id) {
740 return GetResource(id)->type;
743 void ResourceProvider::SetPixels(ResourceId id,
744 const uint8_t* image,
745 const gfx::Rect& image_rect,
746 const gfx::Rect& source_rect,
747 const gfx::Vector2d& dest_offset) {
748 Resource* resource = GetResource(id);
749 DCHECK(!resource->locked_for_write);
750 DCHECK(!resource->lock_for_read_count);
751 DCHECK(resource->origin == Resource::Internal);
752 DCHECK_EQ(resource->exported_count, 0);
753 DCHECK(ReadLockFenceHasPassed(resource));
754 LazyAllocate(resource);
756 if (resource->type == GLTexture) {
757 DCHECK(resource->gl_id);
758 DCHECK(!resource->pending_set_pixels);
759 DCHECK_EQ(resource->target, static_cast<GLenum>(GL_TEXTURE_2D));
760 GLES2Interface* gl = ContextGL();
761 DCHECK(gl);
762 DCHECK(texture_uploader_.get());
763 gl->BindTexture(GL_TEXTURE_2D, resource->gl_id);
764 texture_uploader_->Upload(image,
765 image_rect,
766 source_rect,
767 dest_offset,
768 resource->format,
769 resource->size);
770 } else {
771 DCHECK_EQ(Bitmap, resource->type);
772 DCHECK(resource->allocated);
773 DCHECK_EQ(RGBA_8888, resource->format);
774 DCHECK(source_rect.x() >= image_rect.x());
775 DCHECK(source_rect.y() >= image_rect.y());
776 DCHECK(source_rect.right() <= image_rect.right());
777 DCHECK(source_rect.bottom() <= image_rect.bottom());
778 SkImageInfo source_info =
779 SkImageInfo::MakeN32Premul(source_rect.width(), source_rect.height());
780 size_t image_row_bytes = image_rect.width() * 4;
781 gfx::Vector2d source_offset = source_rect.origin() - image_rect.origin();
782 image += source_offset.y() * image_row_bytes + source_offset.x() * 4;
784 ScopedWriteLockSoftware lock(this, id);
785 SkCanvas* dest = lock.sk_canvas();
786 dest->writePixels(
787 source_info, image, image_row_bytes, dest_offset.x(), dest_offset.y());
791 size_t ResourceProvider::NumBlockingUploads() {
792 if (!texture_uploader_)
793 return 0;
795 return texture_uploader_->NumBlockingUploads();
798 void ResourceProvider::MarkPendingUploadsAsNonBlocking() {
799 if (!texture_uploader_)
800 return;
802 texture_uploader_->MarkPendingUploadsAsNonBlocking();
805 size_t ResourceProvider::EstimatedUploadsPerTick() {
806 if (!texture_uploader_)
807 return 1u;
809 double textures_per_second = texture_uploader_->EstimatedTexturesPerSecond();
810 size_t textures_per_tick = floor(
811 kTextureUploadTickRate * textures_per_second);
812 return textures_per_tick ? textures_per_tick : 1u;
815 void ResourceProvider::FlushUploads() {
816 if (!texture_uploader_)
817 return;
819 texture_uploader_->Flush();
822 void ResourceProvider::ReleaseCachedData() {
823 if (!texture_uploader_)
824 return;
826 texture_uploader_->ReleaseCachedQueries();
829 base::TimeTicks ResourceProvider::EstimatedUploadCompletionTime(
830 size_t uploads_per_tick) {
831 if (lost_output_surface_)
832 return base::TimeTicks();
834 // Software resource uploads happen on impl thread, so don't bother batching
835 // them up and trying to wait for them to complete.
836 if (!texture_uploader_) {
837 return gfx::FrameTime::Now() + base::TimeDelta::FromMicroseconds(
838 base::Time::kMicrosecondsPerSecond * kSoftwareUploadTickRate);
841 base::TimeDelta upload_one_texture_time =
842 base::TimeDelta::FromMicroseconds(
843 base::Time::kMicrosecondsPerSecond * kTextureUploadTickRate) /
844 uploads_per_tick;
846 size_t total_uploads = NumBlockingUploads() + uploads_per_tick;
847 return gfx::FrameTime::Now() + upload_one_texture_time * total_uploads;
850 ResourceProvider::Resource* ResourceProvider::GetResource(ResourceId id) {
851 DCHECK(thread_checker_.CalledOnValidThread());
852 ResourceMap::iterator it = resources_.find(id);
853 CHECK(it != resources_.end());
854 return &it->second;
857 const ResourceProvider::Resource* ResourceProvider::LockForRead(ResourceId id) {
858 Resource* resource = GetResource(id);
859 DCHECK(!resource->locked_for_write ||
860 resource->set_pixels_completion_forced) <<
861 "locked for write: " << resource->locked_for_write <<
862 " pixels completion forced: " << resource->set_pixels_completion_forced;
863 DCHECK_EQ(resource->exported_count, 0);
864 // Uninitialized! Call SetPixels or LockForWrite first.
865 DCHECK(resource->allocated);
867 LazyCreate(resource);
869 if (resource->type == GLTexture && !resource->gl_id) {
870 DCHECK(resource->origin != Resource::Internal);
871 DCHECK(resource->mailbox.IsTexture());
873 // Mailbox sync_points must be processed by a call to
874 // WaitSyncPointIfNeeded() prior to calling LockForRead().
875 DCHECK(!resource->mailbox.sync_point());
877 GLES2Interface* gl = ContextGL();
878 DCHECK(gl);
879 resource->gl_id = texture_id_allocator_->NextId();
880 GLC(gl, gl->BindTexture(resource->target, resource->gl_id));
881 GLC(gl,
882 gl->ConsumeTextureCHROMIUM(resource->mailbox.target(),
883 resource->mailbox.name()));
886 if (!resource->pixels && resource->has_shared_bitmap_id &&
887 shared_bitmap_manager_) {
888 scoped_ptr<SharedBitmap> bitmap =
889 shared_bitmap_manager_->GetSharedBitmapFromId(
890 resource->size, resource->shared_bitmap_id);
891 if (bitmap) {
892 resource->shared_bitmap = bitmap.release();
893 resource->pixels = resource->shared_bitmap->pixels();
897 resource->lock_for_read_count++;
898 if (resource->read_lock_fences_enabled) {
899 if (current_read_lock_fence_.get())
900 current_read_lock_fence_->Set();
901 resource->read_lock_fence = current_read_lock_fence_;
904 return resource;
907 void ResourceProvider::UnlockForRead(ResourceId id) {
908 DCHECK(thread_checker_.CalledOnValidThread());
909 ResourceMap::iterator it = resources_.find(id);
910 CHECK(it != resources_.end());
912 Resource* resource = &it->second;
913 DCHECK_GT(resource->lock_for_read_count, 0);
914 DCHECK_EQ(resource->exported_count, 0);
915 resource->lock_for_read_count--;
916 if (resource->marked_for_deletion && !resource->lock_for_read_count) {
917 if (!resource->child_id) {
918 // The resource belongs to this ResourceProvider, so it can be destroyed.
919 DeleteResourceInternal(it, Normal);
920 } else {
921 ChildMap::iterator child_it = children_.find(resource->child_id);
922 ResourceIdArray unused;
923 unused.push_back(id);
924 DeleteAndReturnUnusedResourcesToChild(child_it, Normal, unused);
929 ResourceProvider::Resource* ResourceProvider::LockForWrite(ResourceId id) {
930 Resource* resource = GetResource(id);
931 DCHECK(CanLockForWrite(id));
933 resource->locked_for_write = true;
934 return resource;
937 bool ResourceProvider::CanLockForWrite(ResourceId id) {
938 Resource* resource = GetResource(id);
939 return !resource->locked_for_write && !resource->lock_for_read_count &&
940 !resource->exported_count && resource->origin == Resource::Internal &&
941 !resource->lost && ReadLockFenceHasPassed(resource);
944 void ResourceProvider::UnlockForWrite(ResourceProvider::Resource* resource) {
945 DCHECK(resource->locked_for_write);
946 DCHECK_EQ(resource->exported_count, 0);
947 DCHECK(resource->origin == Resource::Internal);
948 resource->locked_for_write = false;
951 ResourceProvider::ScopedReadLockGL::ScopedReadLockGL(
952 ResourceProvider* resource_provider,
953 ResourceProvider::ResourceId resource_id)
954 : resource_provider_(resource_provider),
955 resource_id_(resource_id),
956 texture_id_(resource_provider->LockForRead(resource_id)->gl_id) {
957 DCHECK(texture_id_);
960 ResourceProvider::ScopedReadLockGL::~ScopedReadLockGL() {
961 resource_provider_->UnlockForRead(resource_id_);
964 ResourceProvider::ScopedSamplerGL::ScopedSamplerGL(
965 ResourceProvider* resource_provider,
966 ResourceProvider::ResourceId resource_id,
967 GLenum filter)
968 : ScopedReadLockGL(resource_provider, resource_id),
969 unit_(GL_TEXTURE0),
970 target_(resource_provider->BindForSampling(resource_id, unit_, filter)) {
973 ResourceProvider::ScopedSamplerGL::ScopedSamplerGL(
974 ResourceProvider* resource_provider,
975 ResourceProvider::ResourceId resource_id,
976 GLenum unit,
977 GLenum filter)
978 : ScopedReadLockGL(resource_provider, resource_id),
979 unit_(unit),
980 target_(resource_provider->BindForSampling(resource_id, unit_, filter)) {
983 ResourceProvider::ScopedSamplerGL::~ScopedSamplerGL() {
986 ResourceProvider::ScopedWriteLockGL::ScopedWriteLockGL(
987 ResourceProvider* resource_provider,
988 ResourceProvider::ResourceId resource_id)
989 : resource_provider_(resource_provider),
990 resource_(resource_provider->LockForWrite(resource_id)) {
991 resource_provider_->LazyAllocate(resource_);
992 texture_id_ = resource_->gl_id;
993 DCHECK(texture_id_);
996 ResourceProvider::ScopedWriteLockGL::~ScopedWriteLockGL() {
997 resource_provider_->UnlockForWrite(resource_);
1000 void ResourceProvider::PopulateSkBitmapWithResource(
1001 SkBitmap* sk_bitmap, const Resource* resource) {
1002 DCHECK_EQ(RGBA_8888, resource->format);
1003 SkImageInfo info = SkImageInfo::MakeN32Premul(resource->size.width(),
1004 resource->size.height());
1005 sk_bitmap->installPixels(info, resource->pixels, info.minRowBytes());
1008 ResourceProvider::ScopedReadLockSoftware::ScopedReadLockSoftware(
1009 ResourceProvider* resource_provider,
1010 ResourceProvider::ResourceId resource_id)
1011 : resource_provider_(resource_provider),
1012 resource_id_(resource_id) {
1013 const Resource* resource = resource_provider->LockForRead(resource_id);
1014 wrap_mode_ = resource->wrap_mode;
1015 ResourceProvider::PopulateSkBitmapWithResource(&sk_bitmap_, resource);
1018 ResourceProvider::ScopedReadLockSoftware::~ScopedReadLockSoftware() {
1019 resource_provider_->UnlockForRead(resource_id_);
1022 ResourceProvider::ScopedWriteLockSoftware::ScopedWriteLockSoftware(
1023 ResourceProvider* resource_provider,
1024 ResourceProvider::ResourceId resource_id)
1025 : resource_provider_(resource_provider),
1026 resource_(resource_provider->LockForWrite(resource_id)) {
1027 ResourceProvider::PopulateSkBitmapWithResource(&sk_bitmap_, resource_);
1028 DCHECK(valid());
1029 sk_canvas_.reset(new SkCanvas(sk_bitmap_));
1032 ResourceProvider::ScopedWriteLockSoftware::~ScopedWriteLockSoftware() {
1033 DCHECK(thread_checker_.CalledOnValidThread());
1034 resource_provider_->UnlockForWrite(resource_);
1037 ResourceProvider::ScopedWriteLockGpuMemoryBuffer::
1038 ScopedWriteLockGpuMemoryBuffer(ResourceProvider* resource_provider,
1039 ResourceProvider::ResourceId resource_id)
1040 : resource_provider_(resource_provider),
1041 resource_(resource_provider->LockForWrite(resource_id)),
1042 gpu_memory_buffer_manager_(resource_provider->gpu_memory_buffer_manager_),
1043 gpu_memory_buffer_(nullptr),
1044 size_(resource_->size),
1045 format_(resource_->format) {
1046 DCHECK_EQ(GLTexture, resource_->type);
1047 std::swap(gpu_memory_buffer_, resource_->gpu_memory_buffer);
1050 ResourceProvider::ScopedWriteLockGpuMemoryBuffer::
1051 ~ScopedWriteLockGpuMemoryBuffer() {
1052 DCHECK(thread_checker_.CalledOnValidThread());
1053 resource_provider_->UnlockForWrite(resource_);
1054 if (!gpu_memory_buffer_)
1055 return;
1057 if (!resource_->image_id) {
1058 GLES2Interface* gl = resource_provider_->ContextGL();
1059 DCHECK(gl);
1061 resource_->image_id =
1062 gl->CreateImageCHROMIUM(gpu_memory_buffer_->AsClientBuffer(),
1063 size_.width(),
1064 size_.height(),
1065 GL_RGBA);
1068 std::swap(resource_->gpu_memory_buffer, gpu_memory_buffer_);
1069 resource_->allocated = true;
1070 resource_->dirty_image = true;
1072 // GpuMemoryBuffer provides direct access to the memory used by the GPU.
1073 // Read lock fences are required to ensure that we're not trying to map a
1074 // buffer that is currently in-use by the GPU.
1075 resource_->read_lock_fences_enabled = true;
1078 gfx::GpuMemoryBuffer*
1079 ResourceProvider::ScopedWriteLockGpuMemoryBuffer::GetGpuMemoryBuffer() {
1080 if (!gpu_memory_buffer_) {
1081 scoped_ptr<gfx::GpuMemoryBuffer> gpu_memory_buffer =
1082 gpu_memory_buffer_manager_->AllocateGpuMemoryBuffer(
1083 size_, ToGpuMemoryBufferFormat(format_), gfx::GpuMemoryBuffer::MAP);
1084 gpu_memory_buffer_ = gpu_memory_buffer.release();
1087 return gpu_memory_buffer_;
1090 ResourceProvider::ScopedWriteLockGr::ScopedWriteLockGr(
1091 ResourceProvider* resource_provider,
1092 ResourceProvider::ResourceId resource_id)
1093 : resource_provider_(resource_provider),
1094 resource_(resource_provider->LockForWrite(resource_id)) {
1097 ResourceProvider::ScopedWriteLockGr::~ScopedWriteLockGr() {
1098 DCHECK(thread_checker_.CalledOnValidThread());
1099 resource_provider_->UnlockForWrite(resource_);
1102 SkSurface* ResourceProvider::ScopedWriteLockGr::GetSkSurface(
1103 bool use_distance_field_text) {
1104 DCHECK(thread_checker_.CalledOnValidThread());
1105 DCHECK(resource_->locked_for_write);
1107 // If the surface doesn't exist, or doesn't have the correct dff setting,
1108 // recreate the surface within the resource.
1109 if (!resource_->sk_surface ||
1110 use_distance_field_text !=
1111 resource_->sk_surface->props().isUseDistanceFieldFonts()) {
1112 class GrContext* gr_context = resource_provider_->GrContext();
1113 // TODO(alokp): Implement TestContextProvider::GrContext().
1114 if (!gr_context)
1115 return nullptr;
1117 resource_provider_->LazyAllocate(resource_);
1119 GrBackendTextureDesc desc;
1120 desc.fFlags = kRenderTarget_GrBackendTextureFlag;
1121 desc.fWidth = resource_->size.width();
1122 desc.fHeight = resource_->size.height();
1123 desc.fConfig = ToGrPixelConfig(resource_->format);
1124 desc.fOrigin = kTopLeft_GrSurfaceOrigin;
1125 desc.fTextureHandle = resource_->gl_id;
1126 skia::RefPtr<GrTexture> gr_texture =
1127 skia::AdoptRef(gr_context->wrapBackendTexture(desc));
1128 if (!gr_texture)
1129 return nullptr;
1130 SkSurface::TextRenderMode text_render_mode =
1131 use_distance_field_text ? SkSurface::kDistanceField_TextRenderMode
1132 : SkSurface::kStandard_TextRenderMode;
1133 resource_->sk_surface = skia::AdoptRef(SkSurface::NewRenderTargetDirect(
1134 gr_texture->asRenderTarget(), text_render_mode));
1136 return resource_->sk_surface.get();
1139 ResourceProvider::SynchronousFence::SynchronousFence(
1140 gpu::gles2::GLES2Interface* gl)
1141 : gl_(gl), has_synchronized_(true) {
1144 ResourceProvider::SynchronousFence::~SynchronousFence() {
1147 void ResourceProvider::SynchronousFence::Set() {
1148 has_synchronized_ = false;
1151 bool ResourceProvider::SynchronousFence::HasPassed() {
1152 if (!has_synchronized_) {
1153 has_synchronized_ = true;
1154 Synchronize();
1156 return true;
1159 void ResourceProvider::SynchronousFence::Wait() {
1160 HasPassed();
1163 void ResourceProvider::SynchronousFence::Synchronize() {
1164 TRACE_EVENT0("cc", "ResourceProvider::SynchronousFence::Synchronize");
1165 gl_->Finish();
1168 ResourceProvider::ResourceProvider(
1169 OutputSurface* output_surface,
1170 SharedBitmapManager* shared_bitmap_manager,
1171 gpu::GpuMemoryBufferManager* gpu_memory_buffer_manager,
1172 BlockingTaskRunner* blocking_main_thread_task_runner,
1173 int highp_threshold_min,
1174 bool use_rgba_4444_texture_format,
1175 size_t id_allocation_chunk_size)
1176 : output_surface_(output_surface),
1177 shared_bitmap_manager_(shared_bitmap_manager),
1178 gpu_memory_buffer_manager_(gpu_memory_buffer_manager),
1179 blocking_main_thread_task_runner_(blocking_main_thread_task_runner),
1180 lost_output_surface_(false),
1181 highp_threshold_min_(highp_threshold_min),
1182 next_id_(1),
1183 next_child_(1),
1184 default_resource_type_(InvalidType),
1185 use_texture_storage_ext_(false),
1186 use_texture_format_bgra_(false),
1187 use_texture_usage_hint_(false),
1188 use_compressed_texture_etc1_(false),
1189 max_texture_size_(0),
1190 best_texture_format_(RGBA_8888),
1191 use_rgba_4444_texture_format_(use_rgba_4444_texture_format),
1192 id_allocation_chunk_size_(id_allocation_chunk_size),
1193 use_sync_query_(false) {
1194 DCHECK(output_surface_->HasClient());
1195 DCHECK(id_allocation_chunk_size_);
1198 void ResourceProvider::InitializeSoftware() {
1199 DCHECK(thread_checker_.CalledOnValidThread());
1200 DCHECK_NE(Bitmap, default_resource_type_);
1202 CleanUpGLIfNeeded();
1204 default_resource_type_ = Bitmap;
1205 // Pick an arbitrary limit here similar to what hardware might.
1206 max_texture_size_ = 16 * 1024;
1207 best_texture_format_ = RGBA_8888;
1210 void ResourceProvider::InitializeGL() {
1211 DCHECK(thread_checker_.CalledOnValidThread());
1212 DCHECK(!texture_uploader_);
1213 DCHECK_NE(GLTexture, default_resource_type_);
1214 DCHECK(!texture_id_allocator_);
1215 DCHECK(!buffer_id_allocator_);
1217 default_resource_type_ = GLTexture;
1219 const ContextProvider::Capabilities& caps =
1220 output_surface_->context_provider()->ContextCapabilities();
1222 bool use_bgra = caps.gpu.texture_format_bgra8888;
1223 use_texture_storage_ext_ = caps.gpu.texture_storage;
1224 use_texture_format_bgra_ = caps.gpu.texture_format_bgra8888;
1225 use_texture_usage_hint_ = caps.gpu.texture_usage;
1226 use_compressed_texture_etc1_ = caps.gpu.texture_format_etc1;
1227 use_sync_query_ = caps.gpu.sync_query;
1229 GLES2Interface* gl = ContextGL();
1230 DCHECK(gl);
1232 texture_uploader_ = TextureUploader::Create(gl);
1233 max_texture_size_ = 0; // Context expects cleared value.
1234 GLC(gl, gl->GetIntegerv(GL_MAX_TEXTURE_SIZE, &max_texture_size_));
1235 best_texture_format_ = PlatformColor::BestTextureFormat(use_bgra);
1237 texture_id_allocator_.reset(
1238 new TextureIdAllocator(gl, id_allocation_chunk_size_));
1239 buffer_id_allocator_.reset(
1240 new BufferIdAllocator(gl, id_allocation_chunk_size_));
1243 void ResourceProvider::CleanUpGLIfNeeded() {
1244 GLES2Interface* gl = ContextGL();
1245 if (default_resource_type_ != GLTexture) {
1246 // We are not in GL mode, but double check before returning.
1247 DCHECK(!gl);
1248 DCHECK(!texture_uploader_);
1249 return;
1252 DCHECK(gl);
1253 #if DCHECK_IS_ON
1254 // Check that all GL resources has been deleted.
1255 for (ResourceMap::const_iterator itr = resources_.begin();
1256 itr != resources_.end();
1257 ++itr) {
1258 DCHECK_NE(GLTexture, itr->second.type);
1260 #endif // DCHECK_IS_ON
1262 texture_uploader_ = nullptr;
1263 texture_id_allocator_ = nullptr;
1264 buffer_id_allocator_ = nullptr;
1265 gl->Finish();
1268 int ResourceProvider::CreateChild(const ReturnCallback& return_callback) {
1269 DCHECK(thread_checker_.CalledOnValidThread());
1271 Child child_info;
1272 child_info.return_callback = return_callback;
1274 int child = next_child_++;
1275 children_[child] = child_info;
1276 return child;
1279 void ResourceProvider::DestroyChild(int child_id) {
1280 ChildMap::iterator it = children_.find(child_id);
1281 DCHECK(it != children_.end());
1282 DestroyChildInternal(it, Normal);
1285 void ResourceProvider::DestroyChildInternal(ChildMap::iterator it,
1286 DeleteStyle style) {
1287 DCHECK(thread_checker_.CalledOnValidThread());
1289 Child& child = it->second;
1290 DCHECK(style == ForShutdown || !child.marked_for_deletion);
1292 ResourceIdArray resources_for_child;
1294 for (ResourceIdMap::iterator child_it = child.child_to_parent_map.begin();
1295 child_it != child.child_to_parent_map.end();
1296 ++child_it) {
1297 ResourceId id = child_it->second;
1298 resources_for_child.push_back(id);
1301 // If the child is going away, don't consider any resources in use.
1302 child.in_use_resources.clear();
1303 child.marked_for_deletion = true;
1305 DeleteAndReturnUnusedResourcesToChild(it, style, resources_for_child);
1308 const ResourceProvider::ResourceIdMap& ResourceProvider::GetChildToParentMap(
1309 int child) const {
1310 DCHECK(thread_checker_.CalledOnValidThread());
1311 ChildMap::const_iterator it = children_.find(child);
1312 DCHECK(it != children_.end());
1313 DCHECK(!it->second.marked_for_deletion);
1314 return it->second.child_to_parent_map;
1317 void ResourceProvider::PrepareSendToParent(const ResourceIdArray& resources,
1318 TransferableResourceArray* list) {
1319 DCHECK(thread_checker_.CalledOnValidThread());
1320 GLES2Interface* gl = ContextGL();
1321 bool need_sync_point = false;
1322 for (ResourceIdArray::const_iterator it = resources.begin();
1323 it != resources.end();
1324 ++it) {
1325 TransferableResource resource;
1326 TransferResource(gl, *it, &resource);
1327 if (!resource.mailbox_holder.sync_point && !resource.is_software)
1328 need_sync_point = true;
1329 ++resources_.find(*it)->second.exported_count;
1330 list->push_back(resource);
1332 if (need_sync_point) {
1333 GLuint sync_point = gl->InsertSyncPointCHROMIUM();
1334 for (TransferableResourceArray::iterator it = list->begin();
1335 it != list->end();
1336 ++it) {
1337 if (!it->mailbox_holder.sync_point)
1338 it->mailbox_holder.sync_point = sync_point;
1343 void ResourceProvider::ReceiveFromChild(
1344 int child, const TransferableResourceArray& resources) {
1345 DCHECK(thread_checker_.CalledOnValidThread());
1346 GLES2Interface* gl = ContextGL();
1347 Child& child_info = children_.find(child)->second;
1348 DCHECK(!child_info.marked_for_deletion);
1349 for (TransferableResourceArray::const_iterator it = resources.begin();
1350 it != resources.end();
1351 ++it) {
1352 ResourceIdMap::iterator resource_in_map_it =
1353 child_info.child_to_parent_map.find(it->id);
1354 if (resource_in_map_it != child_info.child_to_parent_map.end()) {
1355 Resource& resource = resources_[resource_in_map_it->second];
1356 resource.marked_for_deletion = false;
1357 resource.imported_count++;
1358 continue;
1361 if ((!it->is_software && !gl) ||
1362 (it->is_software && !shared_bitmap_manager_)) {
1363 TRACE_EVENT0("cc", "ResourceProvider::ReceiveFromChild dropping invalid");
1364 ReturnedResourceArray to_return;
1365 to_return.push_back(it->ToReturnedResource());
1366 child_info.return_callback.Run(to_return,
1367 blocking_main_thread_task_runner_);
1368 continue;
1371 ResourceId local_id = next_id_++;
1372 Resource& resource = resources_[local_id];
1373 if (it->is_software) {
1374 resource = Resource(it->mailbox_holder.mailbox,
1375 it->size,
1376 Resource::Delegated,
1377 GL_LINEAR,
1378 it->is_repeated ? GL_REPEAT : GL_CLAMP_TO_EDGE);
1379 } else {
1380 resource = Resource(0,
1381 it->size,
1382 Resource::Delegated,
1383 it->mailbox_holder.texture_target,
1384 it->filter,
1386 it->is_repeated ? GL_REPEAT : GL_CLAMP_TO_EDGE,
1387 TextureHintImmutable,
1388 it->format);
1389 resource.mailbox = TextureMailbox(it->mailbox_holder.mailbox,
1390 it->mailbox_holder.texture_target,
1391 it->mailbox_holder.sync_point);
1393 resource.child_id = child;
1394 // Don't allocate a texture for a child.
1395 resource.allocated = true;
1396 resource.imported_count = 1;
1397 resource.allow_overlay = it->allow_overlay;
1398 child_info.parent_to_child_map[local_id] = it->id;
1399 child_info.child_to_parent_map[it->id] = local_id;
1403 void ResourceProvider::DeclareUsedResourcesFromChild(
1404 int child,
1405 const ResourceIdArray& resources_from_child) {
1406 DCHECK(thread_checker_.CalledOnValidThread());
1408 ChildMap::iterator child_it = children_.find(child);
1409 DCHECK(child_it != children_.end());
1410 Child& child_info = child_it->second;
1411 DCHECK(!child_info.marked_for_deletion);
1412 child_info.in_use_resources.clear();
1414 for (size_t i = 0; i < resources_from_child.size(); ++i) {
1415 ResourceIdMap::iterator it =
1416 child_info.child_to_parent_map.find(resources_from_child[i]);
1417 DCHECK(it != child_info.child_to_parent_map.end());
1419 ResourceId local_id = it->second;
1420 DCHECK(!resources_[local_id].marked_for_deletion);
1421 child_info.in_use_resources.insert(local_id);
1424 ResourceIdArray unused;
1425 for (ResourceIdMap::iterator it = child_info.child_to_parent_map.begin();
1426 it != child_info.child_to_parent_map.end();
1427 ++it) {
1428 ResourceId local_id = it->second;
1429 bool resource_is_in_use = child_info.in_use_resources.count(local_id) > 0;
1430 if (!resource_is_in_use)
1431 unused.push_back(local_id);
1433 DeleteAndReturnUnusedResourcesToChild(child_it, Normal, unused);
1436 // static
1437 bool ResourceProvider::CompareResourceMapIteratorsByChildId(
1438 const std::pair<ReturnedResource, ResourceMap::iterator>& a,
1439 const std::pair<ReturnedResource, ResourceMap::iterator>& b) {
1440 const ResourceMap::iterator& a_it = a.second;
1441 const ResourceMap::iterator& b_it = b.second;
1442 const Resource& a_resource = a_it->second;
1443 const Resource& b_resource = b_it->second;
1444 return a_resource.child_id < b_resource.child_id;
1447 void ResourceProvider::ReceiveReturnsFromParent(
1448 const ReturnedResourceArray& resources) {
1449 DCHECK(thread_checker_.CalledOnValidThread());
1450 GLES2Interface* gl = ContextGL();
1452 int child_id = 0;
1453 ResourceIdArray resources_for_child;
1455 std::vector<std::pair<ReturnedResource, ResourceMap::iterator>>
1456 sorted_resources;
1458 for (ReturnedResourceArray::const_iterator it = resources.begin();
1459 it != resources.end();
1460 ++it) {
1461 ResourceId local_id = it->id;
1462 ResourceMap::iterator map_iterator = resources_.find(local_id);
1464 // Resource was already lost (e.g. it belonged to a child that was
1465 // destroyed).
1466 if (map_iterator == resources_.end())
1467 continue;
1469 sorted_resources.push_back(
1470 std::pair<ReturnedResource, ResourceMap::iterator>(*it, map_iterator));
1473 std::sort(sorted_resources.begin(),
1474 sorted_resources.end(),
1475 CompareResourceMapIteratorsByChildId);
1477 ChildMap::iterator child_it = children_.end();
1478 for (size_t i = 0; i < sorted_resources.size(); ++i) {
1479 ReturnedResource& returned = sorted_resources[i].first;
1480 ResourceMap::iterator& map_iterator = sorted_resources[i].second;
1481 ResourceId local_id = map_iterator->first;
1482 Resource* resource = &map_iterator->second;
1484 CHECK_GE(resource->exported_count, returned.count);
1485 resource->exported_count -= returned.count;
1486 resource->lost |= returned.lost;
1487 if (resource->exported_count)
1488 continue;
1490 // Need to wait for the current read lock fence to pass before we can
1491 // recycle this resource.
1492 if (resource->read_lock_fences_enabled) {
1493 if (current_read_lock_fence_.get())
1494 current_read_lock_fence_->Set();
1495 resource->read_lock_fence = current_read_lock_fence_;
1498 if (returned.sync_point) {
1499 DCHECK(!resource->has_shared_bitmap_id);
1500 if (resource->origin == Resource::Internal) {
1501 DCHECK(resource->gl_id);
1502 GLC(gl, gl->WaitSyncPointCHROMIUM(returned.sync_point));
1503 } else {
1504 DCHECK(!resource->gl_id);
1505 resource->mailbox.set_sync_point(returned.sync_point);
1509 if (!resource->marked_for_deletion)
1510 continue;
1512 if (!resource->child_id) {
1513 // The resource belongs to this ResourceProvider, so it can be destroyed.
1514 DeleteResourceInternal(map_iterator, Normal);
1515 continue;
1518 DCHECK(resource->origin == Resource::Delegated);
1519 // Delete the resource and return it to the child it came from one.
1520 if (resource->child_id != child_id) {
1521 if (child_id) {
1522 DCHECK_NE(resources_for_child.size(), 0u);
1523 DCHECK(child_it != children_.end());
1524 DeleteAndReturnUnusedResourcesToChild(
1525 child_it, Normal, resources_for_child);
1526 resources_for_child.clear();
1529 child_it = children_.find(resource->child_id);
1530 DCHECK(child_it != children_.end());
1531 child_id = resource->child_id;
1533 resources_for_child.push_back(local_id);
1536 if (child_id) {
1537 DCHECK_NE(resources_for_child.size(), 0u);
1538 DCHECK(child_it != children_.end());
1539 DeleteAndReturnUnusedResourcesToChild(
1540 child_it, Normal, resources_for_child);
1544 void ResourceProvider::TransferResource(GLES2Interface* gl,
1545 ResourceId id,
1546 TransferableResource* resource) {
1547 Resource* source = GetResource(id);
1548 DCHECK(!source->locked_for_write);
1549 DCHECK(!source->lock_for_read_count);
1550 DCHECK(source->origin != Resource::External || source->mailbox.IsValid());
1551 DCHECK(source->allocated);
1552 resource->id = id;
1553 resource->format = source->format;
1554 resource->mailbox_holder.texture_target = source->target;
1555 resource->filter = source->filter;
1556 resource->size = source->size;
1557 resource->is_repeated = (source->wrap_mode == GL_REPEAT);
1558 resource->allow_overlay = source->allow_overlay;
1560 if (source->type == Bitmap) {
1561 resource->mailbox_holder.mailbox = source->shared_bitmap_id;
1562 resource->is_software = true;
1563 } else if (!source->mailbox.IsValid()) {
1564 LazyCreate(source);
1565 DCHECK(source->gl_id);
1566 DCHECK(source->origin == Resource::Internal);
1567 GLC(gl,
1568 gl->BindTexture(resource->mailbox_holder.texture_target,
1569 source->gl_id));
1570 if (source->image_id) {
1571 DCHECK(source->dirty_image);
1572 BindImageForSampling(source);
1574 // This is a resource allocated by the compositor, we need to produce it.
1575 // Don't set a sync point, the caller will do it.
1576 GLC(gl, gl->GenMailboxCHROMIUM(resource->mailbox_holder.mailbox.name));
1577 GLC(gl,
1578 gl->ProduceTextureCHROMIUM(resource->mailbox_holder.texture_target,
1579 resource->mailbox_holder.mailbox.name));
1580 source->mailbox = TextureMailbox(resource->mailbox_holder);
1581 } else {
1582 DCHECK(source->mailbox.IsTexture());
1583 if (source->image_id && source->dirty_image) {
1584 DCHECK(source->gl_id);
1585 DCHECK(source->origin == Resource::Internal);
1586 GLC(gl,
1587 gl->BindTexture(resource->mailbox_holder.texture_target,
1588 source->gl_id));
1589 BindImageForSampling(source);
1591 // This is either an external resource, or a compositor resource that we
1592 // already exported. Make sure to forward the sync point that we were given.
1593 resource->mailbox_holder.mailbox = source->mailbox.mailbox();
1594 resource->mailbox_holder.texture_target = source->mailbox.target();
1595 resource->mailbox_holder.sync_point = source->mailbox.sync_point();
1596 source->mailbox.set_sync_point(0);
1600 void ResourceProvider::DeleteAndReturnUnusedResourcesToChild(
1601 ChildMap::iterator child_it,
1602 DeleteStyle style,
1603 const ResourceIdArray& unused) {
1604 DCHECK(thread_checker_.CalledOnValidThread());
1605 DCHECK(child_it != children_.end());
1606 Child* child_info = &child_it->second;
1608 if (unused.empty() && !child_info->marked_for_deletion)
1609 return;
1611 ReturnedResourceArray to_return;
1613 GLES2Interface* gl = ContextGL();
1614 bool need_sync_point = false;
1615 for (size_t i = 0; i < unused.size(); ++i) {
1616 ResourceId local_id = unused[i];
1618 ResourceMap::iterator it = resources_.find(local_id);
1619 CHECK(it != resources_.end());
1620 Resource& resource = it->second;
1622 DCHECK(!resource.locked_for_write);
1623 DCHECK_EQ(0u, child_info->in_use_resources.count(local_id));
1624 DCHECK(child_info->parent_to_child_map.count(local_id));
1626 ResourceId child_id = child_info->parent_to_child_map[local_id];
1627 DCHECK(child_info->child_to_parent_map.count(child_id));
1629 bool is_lost =
1630 resource.lost || (resource.type == GLTexture && lost_output_surface_);
1631 if (resource.exported_count > 0 || resource.lock_for_read_count > 0) {
1632 if (style != ForShutdown) {
1633 // Defer this until we receive the resource back from the parent or
1634 // the read lock is released.
1635 resource.marked_for_deletion = true;
1636 continue;
1639 // We still have an exported_count, so we'll have to lose it.
1640 is_lost = true;
1643 if (gl && resource.filter != resource.original_filter) {
1644 DCHECK(resource.target);
1645 DCHECK(resource.gl_id);
1647 GLC(gl, gl->BindTexture(resource.target, resource.gl_id));
1648 GLC(gl,
1649 gl->TexParameteri(resource.target,
1650 GL_TEXTURE_MIN_FILTER,
1651 resource.original_filter));
1652 GLC(gl,
1653 gl->TexParameteri(resource.target,
1654 GL_TEXTURE_MAG_FILTER,
1655 resource.original_filter));
1658 ReturnedResource returned;
1659 returned.id = child_id;
1660 returned.sync_point = resource.mailbox.sync_point();
1661 if (!returned.sync_point && resource.type == GLTexture)
1662 need_sync_point = true;
1663 returned.count = resource.imported_count;
1664 returned.lost = is_lost;
1665 to_return.push_back(returned);
1667 child_info->parent_to_child_map.erase(local_id);
1668 child_info->child_to_parent_map.erase(child_id);
1669 resource.imported_count = 0;
1670 DeleteResourceInternal(it, style);
1672 if (need_sync_point) {
1673 DCHECK(gl);
1674 GLuint sync_point = gl->InsertSyncPointCHROMIUM();
1675 for (size_t i = 0; i < to_return.size(); ++i) {
1676 if (!to_return[i].sync_point)
1677 to_return[i].sync_point = sync_point;
1681 if (!to_return.empty())
1682 child_info->return_callback.Run(to_return,
1683 blocking_main_thread_task_runner_);
1685 if (child_info->marked_for_deletion &&
1686 child_info->parent_to_child_map.empty()) {
1687 DCHECK(child_info->child_to_parent_map.empty());
1688 children_.erase(child_it);
1692 void ResourceProvider::AcquirePixelBuffer(ResourceId id) {
1693 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug"),
1694 "ResourceProvider::AcquirePixelBuffer");
1696 Resource* resource = GetResource(id);
1697 DCHECK(resource->origin == Resource::Internal);
1698 DCHECK_EQ(resource->exported_count, 0);
1699 DCHECK(!resource->image_id);
1700 DCHECK_NE(ETC1, resource->format);
1702 DCHECK_EQ(GLTexture, resource->type);
1703 GLES2Interface* gl = ContextGL();
1704 DCHECK(gl);
1705 if (!resource->gl_pixel_buffer_id)
1706 resource->gl_pixel_buffer_id = buffer_id_allocator_->NextId();
1707 gl->BindBuffer(GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM,
1708 resource->gl_pixel_buffer_id);
1709 unsigned bytes_per_pixel = BitsPerPixel(resource->format) / 8;
1710 gl->BufferData(GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM,
1711 resource->size.height() *
1712 RoundUp(bytes_per_pixel * resource->size.width(), 4u),
1713 NULL,
1714 GL_DYNAMIC_DRAW);
1715 gl->BindBuffer(GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM, 0);
1718 void ResourceProvider::ReleasePixelBuffer(ResourceId id) {
1719 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug"),
1720 "ResourceProvider::ReleasePixelBuffer");
1722 Resource* resource = GetResource(id);
1723 DCHECK(resource->origin == Resource::Internal);
1724 DCHECK_EQ(resource->exported_count, 0);
1725 DCHECK(!resource->image_id);
1727 // The pixel buffer can be released while there is a pending "set pixels"
1728 // if completion has been forced. Any shared memory associated with this
1729 // pixel buffer will not be freed until the waitAsyncTexImage2DCHROMIUM
1730 // command has been processed on the service side. It is also safe to
1731 // reuse any query id associated with this resource before they complete
1732 // as each new query has a unique submit count.
1733 if (resource->pending_set_pixels) {
1734 DCHECK(resource->set_pixels_completion_forced);
1735 resource->pending_set_pixels = false;
1736 resource->locked_for_write = false;
1739 DCHECK_EQ(GLTexture, resource->type);
1740 if (!resource->gl_pixel_buffer_id)
1741 return;
1742 GLES2Interface* gl = ContextGL();
1743 DCHECK(gl);
1744 gl->BindBuffer(GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM,
1745 resource->gl_pixel_buffer_id);
1746 gl->BufferData(
1747 GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM, 0, NULL, GL_DYNAMIC_DRAW);
1748 gl->BindBuffer(GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM, 0);
1751 uint8_t* ResourceProvider::MapPixelBuffer(ResourceId id, int* stride) {
1752 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug"),
1753 "ResourceProvider::MapPixelBuffer");
1755 Resource* resource = GetResource(id);
1756 DCHECK(resource->origin == Resource::Internal);
1757 DCHECK_EQ(resource->exported_count, 0);
1758 DCHECK(!resource->image_id);
1760 *stride = 0;
1761 DCHECK_EQ(GLTexture, resource->type);
1762 GLES2Interface* gl = ContextGL();
1763 DCHECK(gl);
1764 DCHECK(resource->gl_pixel_buffer_id);
1765 gl->BindBuffer(GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM,
1766 resource->gl_pixel_buffer_id);
1767 uint8_t* image = static_cast<uint8_t*>(gl->MapBufferCHROMIUM(
1768 GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM, GL_WRITE_ONLY));
1769 gl->BindBuffer(GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM, 0);
1770 // Buffer is required to be 4-byte aligned.
1771 CHECK(!(reinterpret_cast<intptr_t>(image) & 3));
1772 return image;
1775 void ResourceProvider::UnmapPixelBuffer(ResourceId id) {
1776 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug"),
1777 "ResourceProvider::UnmapPixelBuffer");
1779 Resource* resource = GetResource(id);
1780 DCHECK(resource->origin == Resource::Internal);
1781 DCHECK_EQ(resource->exported_count, 0);
1782 DCHECK(!resource->image_id);
1784 DCHECK_EQ(GLTexture, resource->type);
1785 GLES2Interface* gl = ContextGL();
1786 DCHECK(gl);
1787 DCHECK(resource->gl_pixel_buffer_id);
1788 gl->BindBuffer(GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM,
1789 resource->gl_pixel_buffer_id);
1790 gl->UnmapBufferCHROMIUM(GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM);
1791 gl->BindBuffer(GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM, 0);
1794 GLenum ResourceProvider::BindForSampling(ResourceId resource_id,
1795 GLenum unit,
1796 GLenum filter) {
1797 DCHECK(thread_checker_.CalledOnValidThread());
1798 GLES2Interface* gl = ContextGL();
1799 ResourceMap::iterator it = resources_.find(resource_id);
1800 DCHECK(it != resources_.end());
1801 Resource* resource = &it->second;
1802 DCHECK(resource->lock_for_read_count);
1803 DCHECK(!resource->locked_for_write || resource->set_pixels_completion_forced);
1805 ScopedSetActiveTexture scoped_active_tex(gl, unit);
1806 GLenum target = resource->target;
1807 GLC(gl, gl->BindTexture(target, resource->gl_id));
1808 if (filter != resource->filter) {
1809 GLC(gl, gl->TexParameteri(target, GL_TEXTURE_MIN_FILTER, filter));
1810 GLC(gl, gl->TexParameteri(target, GL_TEXTURE_MAG_FILTER, filter));
1811 resource->filter = filter;
1814 if (resource->image_id && resource->dirty_image)
1815 BindImageForSampling(resource);
1817 return target;
1820 void ResourceProvider::BeginSetPixels(ResourceId id) {
1821 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug"),
1822 "ResourceProvider::BeginSetPixels");
1824 Resource* resource = GetResource(id);
1825 DCHECK(!resource->pending_set_pixels);
1827 LazyCreate(resource);
1828 DCHECK(resource->origin == Resource::Internal);
1829 DCHECK(resource->gl_id || resource->allocated);
1830 DCHECK(ReadLockFenceHasPassed(resource));
1831 DCHECK(!resource->image_id);
1833 bool allocate = !resource->allocated;
1834 resource->allocated = true;
1835 LockForWrite(id);
1837 DCHECK_EQ(GLTexture, resource->type);
1838 DCHECK(resource->gl_id);
1839 GLES2Interface* gl = ContextGL();
1840 DCHECK(gl);
1841 DCHECK(resource->gl_pixel_buffer_id);
1842 DCHECK_EQ(resource->target, static_cast<GLenum>(GL_TEXTURE_2D));
1843 gl->BindTexture(GL_TEXTURE_2D, resource->gl_id);
1844 gl->BindBuffer(GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM,
1845 resource->gl_pixel_buffer_id);
1846 if (!resource->gl_upload_query_id)
1847 gl->GenQueriesEXT(1, &resource->gl_upload_query_id);
1848 gl->BeginQueryEXT(GL_ASYNC_PIXEL_UNPACK_COMPLETED_CHROMIUM,
1849 resource->gl_upload_query_id);
1850 if (allocate) {
1851 gl->AsyncTexImage2DCHROMIUM(GL_TEXTURE_2D,
1852 0, /* level */
1853 GLInternalFormat(resource->format),
1854 resource->size.width(),
1855 resource->size.height(),
1856 0, /* border */
1857 GLDataFormat(resource->format),
1858 GLDataType(resource->format),
1859 NULL);
1860 } else {
1861 gl->AsyncTexSubImage2DCHROMIUM(GL_TEXTURE_2D,
1862 0, /* level */
1863 0, /* x */
1864 0, /* y */
1865 resource->size.width(),
1866 resource->size.height(),
1867 GLDataFormat(resource->format),
1868 GLDataType(resource->format),
1869 NULL);
1871 gl->EndQueryEXT(GL_ASYNC_PIXEL_UNPACK_COMPLETED_CHROMIUM);
1872 gl->BindBuffer(GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM, 0);
1874 resource->pending_set_pixels = true;
1875 resource->set_pixels_completion_forced = false;
1878 void ResourceProvider::ForceSetPixelsToComplete(ResourceId id) {
1879 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug"),
1880 "ResourceProvider::ForceSetPixelsToComplete");
1882 Resource* resource = GetResource(id);
1884 DCHECK(resource->locked_for_write);
1885 DCHECK(resource->pending_set_pixels);
1886 DCHECK(!resource->set_pixels_completion_forced);
1888 if (resource->gl_id) {
1889 GLES2Interface* gl = ContextGL();
1890 GLC(gl, gl->BindTexture(GL_TEXTURE_2D, resource->gl_id));
1891 GLC(gl, gl->WaitAsyncTexImage2DCHROMIUM(GL_TEXTURE_2D));
1892 GLC(gl, gl->BindTexture(GL_TEXTURE_2D, 0));
1895 resource->set_pixels_completion_forced = true;
1898 bool ResourceProvider::DidSetPixelsComplete(ResourceId id) {
1899 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug"),
1900 "ResourceProvider::DidSetPixelsComplete");
1902 Resource* resource = GetResource(id);
1904 DCHECK(resource->locked_for_write);
1905 DCHECK(resource->pending_set_pixels);
1907 if (resource->gl_id) {
1908 GLES2Interface* gl = ContextGL();
1909 DCHECK(gl);
1910 DCHECK(resource->gl_upload_query_id);
1911 GLuint complete = 1;
1912 gl->GetQueryObjectuivEXT(
1913 resource->gl_upload_query_id, GL_QUERY_RESULT_AVAILABLE_EXT, &complete);
1914 if (!complete)
1915 return false;
1918 resource->pending_set_pixels = false;
1919 UnlockForWrite(resource);
1921 // Async set pixels commands are not necessarily processed in-sequence with
1922 // drawing commands. Read lock fences are required to ensure that async
1923 // commands don't access the resource while used for drawing.
1924 resource->read_lock_fences_enabled = true;
1926 return true;
1929 void ResourceProvider::CreateForTesting(ResourceId id) {
1930 LazyCreate(GetResource(id));
1933 GLenum ResourceProvider::TargetForTesting(ResourceId id) {
1934 Resource* resource = GetResource(id);
1935 return resource->target;
1938 void ResourceProvider::LazyCreate(Resource* resource) {
1939 if (resource->type != GLTexture || resource->origin != Resource::Internal)
1940 return;
1942 if (resource->gl_id)
1943 return;
1945 DCHECK(resource->texture_pool);
1946 DCHECK(resource->origin == Resource::Internal);
1947 DCHECK(!resource->mailbox.IsValid());
1948 resource->gl_id = texture_id_allocator_->NextId();
1950 GLES2Interface* gl = ContextGL();
1951 DCHECK(gl);
1953 // Create and set texture properties. Allocation is delayed until needed.
1954 GLC(gl, gl->BindTexture(resource->target, resource->gl_id));
1955 GLC(gl,
1956 gl->TexParameteri(
1957 resource->target, GL_TEXTURE_MIN_FILTER, resource->original_filter));
1958 GLC(gl,
1959 gl->TexParameteri(
1960 resource->target, GL_TEXTURE_MAG_FILTER, resource->original_filter));
1961 GLC(gl,
1962 gl->TexParameteri(
1963 resource->target, GL_TEXTURE_WRAP_S, resource->wrap_mode));
1964 GLC(gl,
1965 gl->TexParameteri(
1966 resource->target, GL_TEXTURE_WRAP_T, resource->wrap_mode));
1967 GLC(gl,
1968 gl->TexParameteri(
1969 resource->target, GL_TEXTURE_POOL_CHROMIUM, resource->texture_pool));
1970 if (use_texture_usage_hint_ && (resource->hint & TextureHintFramebuffer)) {
1971 GLC(gl,
1972 gl->TexParameteri(resource->target,
1973 GL_TEXTURE_USAGE_ANGLE,
1974 GL_FRAMEBUFFER_ATTACHMENT_ANGLE));
1978 void ResourceProvider::AllocateForTesting(ResourceId id) {
1979 LazyAllocate(GetResource(id));
1982 void ResourceProvider::LazyAllocate(Resource* resource) {
1983 DCHECK(resource);
1984 if (resource->allocated)
1985 return;
1986 LazyCreate(resource);
1987 if (!resource->gl_id)
1988 return;
1989 resource->allocated = true;
1990 GLES2Interface* gl = ContextGL();
1991 gfx::Size& size = resource->size;
1992 DCHECK_EQ(resource->target, static_cast<GLenum>(GL_TEXTURE_2D));
1993 ResourceFormat format = resource->format;
1994 GLC(gl, gl->BindTexture(GL_TEXTURE_2D, resource->gl_id));
1995 if (use_texture_storage_ext_ &&
1996 IsFormatSupportedForStorage(format, use_texture_format_bgra_) &&
1997 (resource->hint & TextureHintImmutable)) {
1998 GLenum storage_format = TextureToStorageFormat(format);
1999 GLC(gl,
2000 gl->TexStorage2DEXT(
2001 GL_TEXTURE_2D, 1, storage_format, size.width(), size.height()));
2002 } else {
2003 // ETC1 does not support preallocation.
2004 if (format != ETC1) {
2005 GLC(gl,
2006 gl->TexImage2D(GL_TEXTURE_2D,
2008 GLInternalFormat(format),
2009 size.width(),
2010 size.height(),
2012 GLDataFormat(format),
2013 GLDataType(format),
2014 NULL));
2019 void ResourceProvider::BindImageForSampling(Resource* resource) {
2020 GLES2Interface* gl = ContextGL();
2021 DCHECK(resource->gl_id);
2022 DCHECK(resource->image_id);
2024 // Release image currently bound to texture.
2025 if (resource->bound_image_id)
2026 gl->ReleaseTexImage2DCHROMIUM(resource->target, resource->bound_image_id);
2027 gl->BindTexImage2DCHROMIUM(resource->target, resource->image_id);
2028 resource->bound_image_id = resource->image_id;
2029 resource->dirty_image = false;
2032 void ResourceProvider::CopyResource(ResourceId source_id, ResourceId dest_id) {
2033 TRACE_EVENT0("cc", "ResourceProvider::CopyResource");
2035 Resource* source_resource = GetResource(source_id);
2036 DCHECK(!source_resource->lock_for_read_count);
2037 DCHECK(source_resource->origin == Resource::Internal);
2038 DCHECK_EQ(source_resource->exported_count, 0);
2039 DCHECK_EQ(GLTexture, source_resource->type);
2040 DCHECK(source_resource->allocated);
2041 LazyCreate(source_resource);
2043 Resource* dest_resource = GetResource(dest_id);
2044 DCHECK(!dest_resource->locked_for_write);
2045 DCHECK(!dest_resource->lock_for_read_count);
2046 DCHECK(dest_resource->origin == Resource::Internal);
2047 DCHECK_EQ(dest_resource->exported_count, 0);
2048 DCHECK_EQ(GLTexture, dest_resource->type);
2049 LazyCreate(dest_resource);
2051 DCHECK_EQ(source_resource->type, dest_resource->type);
2052 DCHECK_EQ(source_resource->format, dest_resource->format);
2053 DCHECK(source_resource->size == dest_resource->size);
2055 GLES2Interface* gl = ContextGL();
2056 DCHECK(gl);
2057 if (source_resource->image_id && source_resource->dirty_image) {
2058 gl->BindTexture(source_resource->target, source_resource->gl_id);
2059 BindImageForSampling(source_resource);
2061 if (use_sync_query_) {
2062 if (!source_resource->gl_read_lock_query_id)
2063 gl->GenQueriesEXT(1, &source_resource->gl_read_lock_query_id);
2064 gl->BeginQueryEXT(GL_COMMANDS_COMPLETED_CHROMIUM,
2065 source_resource->gl_read_lock_query_id);
2067 DCHECK(!dest_resource->image_id);
2068 dest_resource->allocated = true;
2069 gl->CopyTextureCHROMIUM(dest_resource->target,
2070 source_resource->gl_id,
2071 dest_resource->gl_id,
2073 GLInternalFormat(dest_resource->format),
2074 GLDataType(dest_resource->format));
2075 if (source_resource->gl_read_lock_query_id) {
2076 // End query and create a read lock fence that will prevent access to
2077 // source resource until CopyTextureCHROMIUM command has completed.
2078 gl->EndQueryEXT(GL_COMMANDS_COMPLETED_CHROMIUM);
2079 source_resource->read_lock_fence = make_scoped_refptr(
2080 new QueryFence(gl, source_resource->gl_read_lock_query_id));
2081 } else {
2082 // Create a SynchronousFence when CHROMIUM_sync_query extension is missing.
2083 // Try to use one synchronous fence for as many CopyResource operations as
2084 // possible as that reduce the number of times we have to synchronize with
2085 // the GL.
2086 if (!synchronous_fence_.get() || synchronous_fence_->has_synchronized())
2087 synchronous_fence_ = make_scoped_refptr(new SynchronousFence(gl));
2088 source_resource->read_lock_fence = synchronous_fence_;
2089 source_resource->read_lock_fence->Set();
2093 void ResourceProvider::WaitSyncPointIfNeeded(ResourceId id) {
2094 Resource* resource = GetResource(id);
2095 DCHECK_EQ(resource->exported_count, 0);
2096 DCHECK(resource->allocated);
2097 if (resource->type != GLTexture || resource->gl_id)
2098 return;
2099 if (!resource->mailbox.sync_point())
2100 return;
2101 DCHECK(resource->mailbox.IsValid());
2102 GLES2Interface* gl = ContextGL();
2103 DCHECK(gl);
2104 GLC(gl, gl->WaitSyncPointCHROMIUM(resource->mailbox.sync_point()));
2105 resource->mailbox.set_sync_point(0);
2108 void ResourceProvider::WaitReadLockIfNeeded(ResourceId id) {
2109 Resource* resource = GetResource(id);
2110 DCHECK_EQ(resource->exported_count, 0);
2111 if (!resource->read_lock_fence.get())
2112 return;
2114 resource->read_lock_fence->Wait();
2117 GLint ResourceProvider::GetActiveTextureUnit(GLES2Interface* gl) {
2118 GLint active_unit = 0;
2119 gl->GetIntegerv(GL_ACTIVE_TEXTURE, &active_unit);
2120 return active_unit;
2123 GLES2Interface* ResourceProvider::ContextGL() const {
2124 ContextProvider* context_provider = output_surface_->context_provider();
2125 return context_provider ? context_provider->ContextGL() : NULL;
2128 class GrContext* ResourceProvider::GrContext() const {
2129 ContextProvider* context_provider = output_surface_->context_provider();
2130 return context_provider ? context_provider->GrContext() : NULL;
2133 } // namespace cc