Revert of Linux MSan: enable swarming/sharding for browser_tests. (patchset #1 id...
[chromium-blink-merge.git] / cc / resources / resource_provider.cc
blobb90b59477376960656266cdb0f60b87d0d8173b0
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/metrics/histogram.h"
12 #include "base/stl_util.h"
13 #include "base/strings/string_split.h"
14 #include "base/strings/string_util.h"
15 #include "base/trace_event/trace_event.h"
16 #include "cc/base/util.h"
17 #include "cc/output/gl_renderer.h" // For the GLC() macro.
18 #include "cc/resources/platform_color.h"
19 #include "cc/resources/returned_resource.h"
20 #include "cc/resources/shared_bitmap_manager.h"
21 #include "cc/resources/texture_uploader.h"
22 #include "cc/resources/transferable_resource.h"
23 #include "gpu/GLES2/gl2extchromium.h"
24 #include "gpu/command_buffer/client/gles2_interface.h"
25 #include "gpu/command_buffer/client/gpu_memory_buffer_manager.h"
26 #include "third_party/khronos/GLES2/gl2.h"
27 #include "third_party/khronos/GLES2/gl2ext.h"
28 #include "third_party/skia/include/core/SkSurface.h"
29 #include "third_party/skia/include/gpu/GrContext.h"
30 #include "ui/gfx/frame_time.h"
31 #include "ui/gfx/geometry/rect.h"
32 #include "ui/gfx/geometry/vector2d.h"
33 #include "ui/gfx/gpu_memory_buffer.h"
35 using gpu::gles2::GLES2Interface;
37 namespace cc {
39 class IdAllocator {
40 public:
41 virtual ~IdAllocator() {}
43 virtual GLuint NextId() = 0;
45 protected:
46 IdAllocator(GLES2Interface* gl, size_t id_allocation_chunk_size)
47 : gl_(gl),
48 id_allocation_chunk_size_(id_allocation_chunk_size),
49 ids_(new GLuint[id_allocation_chunk_size]),
50 next_id_index_(id_allocation_chunk_size) {
51 DCHECK(id_allocation_chunk_size_);
54 GLES2Interface* gl_;
55 const size_t id_allocation_chunk_size_;
56 scoped_ptr<GLuint[]> ids_;
57 size_t next_id_index_;
60 namespace {
62 // Measured in seconds.
63 const double kSoftwareUploadTickRate = 0.000250;
64 const double kTextureUploadTickRate = 0.004;
66 GLenum TextureToStorageFormat(ResourceFormat format) {
67 GLenum storage_format = GL_RGBA8_OES;
68 switch (format) {
69 case RGBA_8888:
70 break;
71 case BGRA_8888:
72 storage_format = GL_BGRA8_EXT;
73 break;
74 case RGBA_4444:
75 case ALPHA_8:
76 case LUMINANCE_8:
77 case RGB_565:
78 case ETC1:
79 case RED_8:
80 NOTREACHED();
81 break;
84 return storage_format;
87 bool IsFormatSupportedForStorage(ResourceFormat format, bool use_bgra) {
88 switch (format) {
89 case RGBA_8888:
90 return true;
91 case BGRA_8888:
92 return use_bgra;
93 case RGBA_4444:
94 case ALPHA_8:
95 case LUMINANCE_8:
96 case RGB_565:
97 case ETC1:
98 case RED_8:
99 return false;
101 return false;
104 GrPixelConfig ToGrPixelConfig(ResourceFormat format) {
105 switch (format) {
106 case RGBA_8888:
107 return kRGBA_8888_GrPixelConfig;
108 case BGRA_8888:
109 return kBGRA_8888_GrPixelConfig;
110 case RGBA_4444:
111 return kRGBA_4444_GrPixelConfig;
112 default:
113 break;
115 DCHECK(false) << "Unsupported resource format.";
116 return kSkia8888_GrPixelConfig;
119 gfx::GpuMemoryBuffer::Format ToGpuMemoryBufferFormat(ResourceFormat format) {
120 switch (format) {
121 case RGBA_8888:
122 return gfx::GpuMemoryBuffer::Format::RGBA_8888;
123 case BGRA_8888:
124 return gfx::GpuMemoryBuffer::Format::BGRA_8888;
125 case RGBA_4444:
126 case ALPHA_8:
127 case LUMINANCE_8:
128 case RGB_565:
129 case ETC1:
130 case RED_8:
131 break;
133 NOTREACHED();
134 return gfx::GpuMemoryBuffer::Format::RGBA_8888;
137 class ScopedSetActiveTexture {
138 public:
139 ScopedSetActiveTexture(GLES2Interface* gl, GLenum unit)
140 : gl_(gl), unit_(unit) {
141 DCHECK_EQ(GL_TEXTURE0, ResourceProvider::GetActiveTextureUnit(gl_));
143 if (unit_ != GL_TEXTURE0)
144 GLC(gl_, gl_->ActiveTexture(unit_));
147 ~ScopedSetActiveTexture() {
148 // Active unit being GL_TEXTURE0 is effectively the ground state.
149 if (unit_ != GL_TEXTURE0)
150 GLC(gl_, gl_->ActiveTexture(GL_TEXTURE0));
153 private:
154 GLES2Interface* gl_;
155 GLenum unit_;
158 class TextureIdAllocator : public IdAllocator {
159 public:
160 TextureIdAllocator(GLES2Interface* gl,
161 size_t texture_id_allocation_chunk_size)
162 : IdAllocator(gl, texture_id_allocation_chunk_size) {}
163 ~TextureIdAllocator() override {
164 gl_->DeleteTextures(id_allocation_chunk_size_ - next_id_index_,
165 ids_.get() + next_id_index_);
168 // Overridden from IdAllocator:
169 GLuint NextId() override {
170 if (next_id_index_ == id_allocation_chunk_size_) {
171 gl_->GenTextures(id_allocation_chunk_size_, ids_.get());
172 next_id_index_ = 0;
175 return ids_[next_id_index_++];
178 private:
179 DISALLOW_COPY_AND_ASSIGN(TextureIdAllocator);
182 class BufferIdAllocator : public IdAllocator {
183 public:
184 BufferIdAllocator(GLES2Interface* gl, size_t buffer_id_allocation_chunk_size)
185 : IdAllocator(gl, buffer_id_allocation_chunk_size) {}
186 ~BufferIdAllocator() override {
187 gl_->DeleteBuffers(id_allocation_chunk_size_ - next_id_index_,
188 ids_.get() + next_id_index_);
191 // Overridden from IdAllocator:
192 GLuint NextId() override {
193 if (next_id_index_ == id_allocation_chunk_size_) {
194 gl_->GenBuffers(id_allocation_chunk_size_, ids_.get());
195 next_id_index_ = 0;
198 return ids_[next_id_index_++];
201 private:
202 DISALLOW_COPY_AND_ASSIGN(BufferIdAllocator);
205 // Query object based fence implementation used to detect completion of copy
206 // texture operations. Fence has passed when query result is available.
207 class CopyTextureFence : public ResourceProvider::Fence {
208 public:
209 CopyTextureFence(gpu::gles2::GLES2Interface* gl, unsigned query_id)
210 : gl_(gl), query_id_(query_id) {}
212 // Overridden from ResourceProvider::Fence:
213 void Set() override {}
214 bool HasPassed() override {
215 unsigned available = 1;
216 gl_->GetQueryObjectuivEXT(
217 query_id_, GL_QUERY_RESULT_AVAILABLE_EXT, &available);
218 if (!available)
219 return false;
221 ProcessResult();
222 return true;
224 void Wait() override {
225 // ProcessResult() will wait for result to become available.
226 ProcessResult();
229 private:
230 ~CopyTextureFence() override {}
232 void ProcessResult() {
233 unsigned time_elapsed_us = 0;
234 gl_->GetQueryObjectuivEXT(query_id_, GL_QUERY_RESULT_EXT, &time_elapsed_us);
235 UMA_HISTOGRAM_CUSTOM_COUNTS("Renderer4.CopyTextureLatency", time_elapsed_us,
236 0, 256000, 50);
239 gpu::gles2::GLES2Interface* gl_;
240 unsigned query_id_;
242 DISALLOW_COPY_AND_ASSIGN(CopyTextureFence);
245 } // namespace
247 ResourceProvider::Resource::Resource()
248 : child_id(0),
249 gl_id(0),
250 gl_pixel_buffer_id(0),
251 gl_upload_query_id(0),
252 gl_read_lock_query_id(0),
253 pixels(NULL),
254 lock_for_read_count(0),
255 imported_count(0),
256 exported_count(0),
257 dirty_image(false),
258 locked_for_write(false),
259 lost(false),
260 marked_for_deletion(false),
261 pending_set_pixels(false),
262 set_pixels_completion_forced(false),
263 allocated(false),
264 read_lock_fences_enabled(false),
265 has_shared_bitmap_id(false),
266 allow_overlay(false),
267 read_lock_fence(NULL),
268 size(),
269 origin(Internal),
270 target(0),
271 original_filter(0),
272 filter(0),
273 image_id(0),
274 bound_image_id(0),
275 texture_pool(0),
276 wrap_mode(0),
277 hint(TextureHintImmutable),
278 type(InvalidType),
279 format(RGBA_8888),
280 shared_bitmap(NULL),
281 gpu_memory_buffer(NULL) {
284 ResourceProvider::Resource::~Resource() {}
286 ResourceProvider::Resource::Resource(GLuint texture_id,
287 const gfx::Size& size,
288 Origin origin,
289 GLenum target,
290 GLenum filter,
291 GLenum texture_pool,
292 GLint wrap_mode,
293 TextureHint hint,
294 ResourceFormat format)
295 : child_id(0),
296 gl_id(texture_id),
297 gl_pixel_buffer_id(0),
298 gl_upload_query_id(0),
299 gl_read_lock_query_id(0),
300 pixels(NULL),
301 lock_for_read_count(0),
302 imported_count(0),
303 exported_count(0),
304 dirty_image(false),
305 locked_for_write(false),
306 lost(false),
307 marked_for_deletion(false),
308 pending_set_pixels(false),
309 set_pixels_completion_forced(false),
310 allocated(false),
311 read_lock_fences_enabled(false),
312 has_shared_bitmap_id(false),
313 allow_overlay(false),
314 read_lock_fence(NULL),
315 size(size),
316 origin(origin),
317 target(target),
318 original_filter(filter),
319 filter(filter),
320 image_id(0),
321 bound_image_id(0),
322 texture_pool(texture_pool),
323 wrap_mode(wrap_mode),
324 hint(hint),
325 type(GLTexture),
326 format(format),
327 shared_bitmap(NULL),
328 gpu_memory_buffer(NULL) {
329 DCHECK(wrap_mode == GL_CLAMP_TO_EDGE || wrap_mode == GL_REPEAT);
330 DCHECK_EQ(origin == Internal, !!texture_pool);
333 ResourceProvider::Resource::Resource(uint8_t* pixels,
334 SharedBitmap* bitmap,
335 const gfx::Size& size,
336 Origin origin,
337 GLenum filter,
338 GLint wrap_mode)
339 : child_id(0),
340 gl_id(0),
341 gl_pixel_buffer_id(0),
342 gl_upload_query_id(0),
343 gl_read_lock_query_id(0),
344 pixels(pixels),
345 lock_for_read_count(0),
346 imported_count(0),
347 exported_count(0),
348 dirty_image(false),
349 locked_for_write(false),
350 lost(false),
351 marked_for_deletion(false),
352 pending_set_pixels(false),
353 set_pixels_completion_forced(false),
354 allocated(false),
355 read_lock_fences_enabled(false),
356 has_shared_bitmap_id(!!bitmap),
357 allow_overlay(false),
358 read_lock_fence(NULL),
359 size(size),
360 origin(origin),
361 target(0),
362 original_filter(filter),
363 filter(filter),
364 image_id(0),
365 bound_image_id(0),
366 texture_pool(0),
367 wrap_mode(wrap_mode),
368 hint(TextureHintImmutable),
369 type(Bitmap),
370 format(RGBA_8888),
371 shared_bitmap(bitmap),
372 gpu_memory_buffer(NULL) {
373 DCHECK(wrap_mode == GL_CLAMP_TO_EDGE || wrap_mode == GL_REPEAT);
374 DCHECK(origin == Delegated || pixels);
375 if (bitmap)
376 shared_bitmap_id = bitmap->id();
379 ResourceProvider::Resource::Resource(const SharedBitmapId& bitmap_id,
380 const gfx::Size& size,
381 Origin origin,
382 GLenum filter,
383 GLint wrap_mode)
384 : child_id(0),
385 gl_id(0),
386 gl_pixel_buffer_id(0),
387 gl_upload_query_id(0),
388 gl_read_lock_query_id(0),
389 pixels(NULL),
390 lock_for_read_count(0),
391 imported_count(0),
392 exported_count(0),
393 dirty_image(false),
394 locked_for_write(false),
395 lost(false),
396 marked_for_deletion(false),
397 pending_set_pixels(false),
398 set_pixels_completion_forced(false),
399 allocated(false),
400 read_lock_fences_enabled(false),
401 has_shared_bitmap_id(true),
402 allow_overlay(false),
403 read_lock_fence(NULL),
404 size(size),
405 origin(origin),
406 target(0),
407 original_filter(filter),
408 filter(filter),
409 image_id(0),
410 bound_image_id(0),
411 texture_pool(0),
412 wrap_mode(wrap_mode),
413 hint(TextureHintImmutable),
414 type(Bitmap),
415 format(RGBA_8888),
416 shared_bitmap_id(bitmap_id),
417 shared_bitmap(NULL),
418 gpu_memory_buffer(NULL) {
419 DCHECK(wrap_mode == GL_CLAMP_TO_EDGE || wrap_mode == GL_REPEAT);
422 ResourceProvider::Child::Child() : marked_for_deletion(false) {}
424 ResourceProvider::Child::~Child() {}
426 scoped_ptr<ResourceProvider> ResourceProvider::Create(
427 OutputSurface* output_surface,
428 SharedBitmapManager* shared_bitmap_manager,
429 gpu::GpuMemoryBufferManager* gpu_memory_buffer_manager,
430 BlockingTaskRunner* blocking_main_thread_task_runner,
431 int highp_threshold_min,
432 bool use_rgba_4444_texture_format,
433 size_t id_allocation_chunk_size) {
434 scoped_ptr<ResourceProvider> resource_provider(
435 new ResourceProvider(output_surface,
436 shared_bitmap_manager,
437 gpu_memory_buffer_manager,
438 blocking_main_thread_task_runner,
439 highp_threshold_min,
440 use_rgba_4444_texture_format,
441 id_allocation_chunk_size));
443 if (resource_provider->ContextGL())
444 resource_provider->InitializeGL();
445 else
446 resource_provider->InitializeSoftware();
448 DCHECK_NE(InvalidType, resource_provider->default_resource_type());
449 return resource_provider.Pass();
452 ResourceProvider::~ResourceProvider() {
453 while (!children_.empty())
454 DestroyChildInternal(children_.begin(), ForShutdown);
455 while (!resources_.empty())
456 DeleteResourceInternal(resources_.begin(), ForShutdown);
458 CleanUpGLIfNeeded();
461 bool ResourceProvider::InUseByConsumer(ResourceId id) {
462 Resource* resource = GetResource(id);
463 return resource->lock_for_read_count > 0 || resource->exported_count > 0 ||
464 resource->lost;
467 bool ResourceProvider::IsLost(ResourceId id) {
468 Resource* resource = GetResource(id);
469 return resource->lost;
472 bool ResourceProvider::AllowOverlay(ResourceId id) {
473 Resource* resource = GetResource(id);
474 return resource->allow_overlay;
477 ResourceProvider::ResourceId ResourceProvider::CreateResource(
478 const gfx::Size& size,
479 GLint wrap_mode,
480 TextureHint hint,
481 ResourceFormat format) {
482 DCHECK(!size.IsEmpty());
483 switch (default_resource_type_) {
484 case GLTexture:
485 return CreateGLTexture(size,
486 GL_TEXTURE_2D,
487 GL_TEXTURE_POOL_UNMANAGED_CHROMIUM,
488 wrap_mode,
489 hint,
490 format);
491 case Bitmap:
492 DCHECK_EQ(RGBA_8888, format);
493 return CreateBitmap(size, wrap_mode);
494 case InvalidType:
495 break;
498 LOG(FATAL) << "Invalid default resource type.";
499 return 0;
502 ResourceProvider::ResourceId ResourceProvider::CreateManagedResource(
503 const gfx::Size& size,
504 GLenum target,
505 GLint wrap_mode,
506 TextureHint hint,
507 ResourceFormat format) {
508 DCHECK(!size.IsEmpty());
509 switch (default_resource_type_) {
510 case GLTexture:
511 return CreateGLTexture(size,
512 target,
513 GL_TEXTURE_POOL_MANAGED_CHROMIUM,
514 wrap_mode,
515 hint,
516 format);
517 case Bitmap:
518 DCHECK_EQ(RGBA_8888, format);
519 return CreateBitmap(size, wrap_mode);
520 case InvalidType:
521 break;
524 LOG(FATAL) << "Invalid default resource type.";
525 return 0;
528 ResourceProvider::ResourceId ResourceProvider::CreateGLTexture(
529 const gfx::Size& size,
530 GLenum target,
531 GLenum texture_pool,
532 GLint wrap_mode,
533 TextureHint hint,
534 ResourceFormat format) {
535 DCHECK_LE(size.width(), max_texture_size_);
536 DCHECK_LE(size.height(), max_texture_size_);
537 DCHECK(thread_checker_.CalledOnValidThread());
539 ResourceId id = next_id_++;
540 Resource resource(0,
541 size,
542 Resource::Internal,
543 target,
544 GL_LINEAR,
545 texture_pool,
546 wrap_mode,
547 hint,
548 format);
549 resource.allocated = false;
550 resources_[id] = resource;
551 return id;
554 ResourceProvider::ResourceId ResourceProvider::CreateBitmap(
555 const gfx::Size& size, GLint wrap_mode) {
556 DCHECK(thread_checker_.CalledOnValidThread());
558 scoped_ptr<SharedBitmap> bitmap =
559 shared_bitmap_manager_->AllocateSharedBitmap(size);
560 uint8_t* pixels = bitmap->pixels();
561 DCHECK(pixels);
563 ResourceId id = next_id_++;
564 Resource resource(
565 pixels, bitmap.release(), size, Resource::Internal, GL_LINEAR, wrap_mode);
566 resource.allocated = true;
567 resources_[id] = resource;
568 return id;
571 ResourceProvider::ResourceId ResourceProvider::CreateResourceFromIOSurface(
572 const gfx::Size& size,
573 unsigned io_surface_id) {
574 DCHECK(thread_checker_.CalledOnValidThread());
576 ResourceId id = next_id_++;
577 Resource resource(0,
578 gfx::Size(),
579 Resource::Internal,
580 GL_TEXTURE_RECTANGLE_ARB,
581 GL_LINEAR,
582 GL_TEXTURE_POOL_UNMANAGED_CHROMIUM,
583 GL_CLAMP_TO_EDGE,
584 TextureHintImmutable,
585 RGBA_8888);
586 LazyCreate(&resource);
587 GLES2Interface* gl = ContextGL();
588 DCHECK(gl);
589 gl->BindTexture(GL_TEXTURE_RECTANGLE_ARB, resource.gl_id);
590 gl->TexImageIOSurface2DCHROMIUM(
591 GL_TEXTURE_RECTANGLE_ARB, size.width(), size.height(), io_surface_id, 0);
592 resource.allocated = true;
593 resources_[id] = resource;
594 return id;
597 ResourceProvider::ResourceId ResourceProvider::CreateResourceFromTextureMailbox(
598 const TextureMailbox& mailbox,
599 scoped_ptr<SingleReleaseCallbackImpl> release_callback_impl) {
600 DCHECK(thread_checker_.CalledOnValidThread());
601 // Just store the information. Mailbox will be consumed in LockForRead().
602 ResourceId id = next_id_++;
603 DCHECK(mailbox.IsValid());
604 Resource& resource = resources_[id];
605 if (mailbox.IsTexture()) {
606 resource = Resource(0,
607 gfx::Size(),
608 Resource::External,
609 mailbox.target(),
610 mailbox.nearest_neighbor() ? GL_NEAREST : GL_LINEAR,
612 GL_CLAMP_TO_EDGE,
613 TextureHintImmutable,
614 RGBA_8888);
615 } else {
616 DCHECK(mailbox.IsSharedMemory());
617 SharedBitmap* shared_bitmap = mailbox.shared_bitmap();
618 uint8_t* pixels = shared_bitmap->pixels();
619 DCHECK(pixels);
620 resource = Resource(pixels, shared_bitmap, mailbox.shared_memory_size(),
621 Resource::External, GL_LINEAR, GL_CLAMP_TO_EDGE);
623 resource.allocated = true;
624 resource.mailbox = mailbox;
625 resource.release_callback_impl =
626 base::Bind(&SingleReleaseCallbackImpl::Run,
627 base::Owned(release_callback_impl.release()));
628 resource.allow_overlay = mailbox.allow_overlay();
629 return id;
632 void ResourceProvider::DeleteResource(ResourceId id) {
633 DCHECK(thread_checker_.CalledOnValidThread());
634 ResourceMap::iterator it = resources_.find(id);
635 CHECK(it != resources_.end());
636 Resource* resource = &it->second;
637 DCHECK(!resource->marked_for_deletion);
638 DCHECK_EQ(resource->imported_count, 0);
639 DCHECK(resource->pending_set_pixels || !resource->locked_for_write);
641 if (resource->exported_count > 0 || resource->lock_for_read_count > 0) {
642 resource->marked_for_deletion = true;
643 return;
644 } else {
645 DeleteResourceInternal(it, Normal);
649 void ResourceProvider::DeleteResourceInternal(ResourceMap::iterator it,
650 DeleteStyle style) {
651 TRACE_EVENT0("cc", "ResourceProvider::DeleteResourceInternal");
652 Resource* resource = &it->second;
653 bool lost_resource = resource->lost;
655 DCHECK(resource->exported_count == 0 || style != Normal);
656 if (style == ForShutdown && resource->exported_count > 0)
657 lost_resource = true;
659 if (resource->image_id) {
660 DCHECK(resource->origin == Resource::Internal);
661 GLES2Interface* gl = ContextGL();
662 DCHECK(gl);
663 GLC(gl, gl->DestroyImageCHROMIUM(resource->image_id));
665 if (resource->gl_upload_query_id) {
666 DCHECK(resource->origin == Resource::Internal);
667 GLES2Interface* gl = ContextGL();
668 DCHECK(gl);
669 GLC(gl, gl->DeleteQueriesEXT(1, &resource->gl_upload_query_id));
671 if (resource->gl_read_lock_query_id) {
672 DCHECK(resource->origin == Resource::Internal);
673 GLES2Interface* gl = ContextGL();
674 DCHECK(gl);
675 GLC(gl, gl->DeleteQueriesEXT(1, &resource->gl_read_lock_query_id));
677 if (resource->gl_pixel_buffer_id) {
678 DCHECK(resource->origin == Resource::Internal);
679 GLES2Interface* gl = ContextGL();
680 DCHECK(gl);
681 GLC(gl, gl->DeleteBuffers(1, &resource->gl_pixel_buffer_id));
683 if (resource->origin == Resource::External) {
684 DCHECK(resource->mailbox.IsValid());
685 GLuint sync_point = resource->mailbox.sync_point();
686 if (resource->type == GLTexture) {
687 DCHECK(resource->mailbox.IsTexture());
688 lost_resource |= lost_output_surface_;
689 GLES2Interface* gl = ContextGL();
690 DCHECK(gl);
691 if (resource->gl_id) {
692 GLC(gl, gl->DeleteTextures(1, &resource->gl_id));
693 resource->gl_id = 0;
694 if (!lost_resource)
695 sync_point = gl->InsertSyncPointCHROMIUM();
697 } else {
698 DCHECK(resource->mailbox.IsSharedMemory());
699 resource->shared_bitmap = nullptr;
700 resource->pixels = nullptr;
702 resource->release_callback_impl.Run(
703 sync_point, lost_resource, blocking_main_thread_task_runner_);
705 if (resource->gl_id) {
706 GLES2Interface* gl = ContextGL();
707 DCHECK(gl);
708 GLC(gl, gl->DeleteTextures(1, &resource->gl_id));
709 resource->gl_id = 0;
711 if (resource->shared_bitmap) {
712 DCHECK(resource->origin != Resource::External);
713 DCHECK_EQ(Bitmap, resource->type);
714 delete resource->shared_bitmap;
715 resource->pixels = NULL;
717 if (resource->pixels) {
718 DCHECK(resource->origin == Resource::Internal);
719 delete[] resource->pixels;
720 resource->pixels = NULL;
722 if (resource->gpu_memory_buffer) {
723 DCHECK(resource->origin == Resource::Internal);
724 delete resource->gpu_memory_buffer;
725 resource->gpu_memory_buffer = NULL;
727 resources_.erase(it);
730 ResourceProvider::ResourceType ResourceProvider::GetResourceType(
731 ResourceId id) {
732 return GetResource(id)->type;
735 void ResourceProvider::SetPixels(ResourceId id,
736 const uint8_t* image,
737 const gfx::Rect& image_rect,
738 const gfx::Rect& source_rect,
739 const gfx::Vector2d& dest_offset) {
740 Resource* resource = GetResource(id);
741 DCHECK(!resource->locked_for_write);
742 DCHECK(!resource->lock_for_read_count);
743 DCHECK(resource->origin == Resource::Internal);
744 DCHECK_EQ(resource->exported_count, 0);
745 DCHECK(ReadLockFenceHasPassed(resource));
746 LazyAllocate(resource);
748 if (resource->type == GLTexture) {
749 DCHECK(resource->gl_id);
750 DCHECK(!resource->pending_set_pixels);
751 DCHECK_EQ(resource->target, static_cast<GLenum>(GL_TEXTURE_2D));
752 GLES2Interface* gl = ContextGL();
753 DCHECK(gl);
754 DCHECK(texture_uploader_.get());
755 gl->BindTexture(GL_TEXTURE_2D, resource->gl_id);
756 texture_uploader_->Upload(image,
757 image_rect,
758 source_rect,
759 dest_offset,
760 resource->format,
761 resource->size);
762 } else {
763 DCHECK_EQ(Bitmap, resource->type);
764 DCHECK(resource->allocated);
765 DCHECK_EQ(RGBA_8888, resource->format);
766 DCHECK(source_rect.x() >= image_rect.x());
767 DCHECK(source_rect.y() >= image_rect.y());
768 DCHECK(source_rect.right() <= image_rect.right());
769 DCHECK(source_rect.bottom() <= image_rect.bottom());
770 SkImageInfo source_info =
771 SkImageInfo::MakeN32Premul(source_rect.width(), source_rect.height());
772 size_t image_row_bytes = image_rect.width() * 4;
773 gfx::Vector2d source_offset = source_rect.origin() - image_rect.origin();
774 image += source_offset.y() * image_row_bytes + source_offset.x() * 4;
776 ScopedWriteLockSoftware lock(this, id);
777 SkCanvas dest(lock.sk_bitmap());
778 dest.writePixels(source_info, image, image_row_bytes, dest_offset.x(),
779 dest_offset.y());
783 size_t ResourceProvider::NumBlockingUploads() {
784 if (!texture_uploader_)
785 return 0;
787 return texture_uploader_->NumBlockingUploads();
790 void ResourceProvider::MarkPendingUploadsAsNonBlocking() {
791 if (!texture_uploader_)
792 return;
794 texture_uploader_->MarkPendingUploadsAsNonBlocking();
797 size_t ResourceProvider::EstimatedUploadsPerTick() {
798 if (!texture_uploader_)
799 return 1u;
801 double textures_per_second = texture_uploader_->EstimatedTexturesPerSecond();
802 size_t textures_per_tick = floor(
803 kTextureUploadTickRate * textures_per_second);
804 return textures_per_tick ? textures_per_tick : 1u;
807 void ResourceProvider::FlushUploads() {
808 if (!texture_uploader_)
809 return;
811 texture_uploader_->Flush();
814 void ResourceProvider::ReleaseCachedData() {
815 if (!texture_uploader_)
816 return;
818 texture_uploader_->ReleaseCachedQueries();
821 base::TimeTicks ResourceProvider::EstimatedUploadCompletionTime(
822 size_t uploads_per_tick) {
823 if (lost_output_surface_)
824 return base::TimeTicks();
826 // Software resource uploads happen on impl thread, so don't bother batching
827 // them up and trying to wait for them to complete.
828 if (!texture_uploader_) {
829 return gfx::FrameTime::Now() + base::TimeDelta::FromMicroseconds(
830 base::Time::kMicrosecondsPerSecond * kSoftwareUploadTickRate);
833 base::TimeDelta upload_one_texture_time =
834 base::TimeDelta::FromMicroseconds(
835 base::Time::kMicrosecondsPerSecond * kTextureUploadTickRate) /
836 uploads_per_tick;
838 size_t total_uploads = NumBlockingUploads() + uploads_per_tick;
839 return gfx::FrameTime::Now() + upload_one_texture_time * total_uploads;
842 ResourceProvider::Resource* ResourceProvider::GetResource(ResourceId id) {
843 DCHECK(thread_checker_.CalledOnValidThread());
844 ResourceMap::iterator it = resources_.find(id);
845 CHECK(it != resources_.end());
846 return &it->second;
849 const ResourceProvider::Resource* ResourceProvider::LockForRead(ResourceId id) {
850 Resource* resource = GetResource(id);
851 DCHECK(!resource->locked_for_write ||
852 resource->set_pixels_completion_forced) <<
853 "locked for write: " << resource->locked_for_write <<
854 " pixels completion forced: " << resource->set_pixels_completion_forced;
855 DCHECK_EQ(resource->exported_count, 0);
856 // Uninitialized! Call SetPixels or LockForWrite first.
857 DCHECK(resource->allocated);
859 LazyCreate(resource);
861 if (resource->type == GLTexture && !resource->gl_id) {
862 DCHECK(resource->origin != Resource::Internal);
863 DCHECK(resource->mailbox.IsTexture());
865 // Mailbox sync_points must be processed by a call to
866 // WaitSyncPointIfNeeded() prior to calling LockForRead().
867 DCHECK(!resource->mailbox.sync_point());
869 GLES2Interface* gl = ContextGL();
870 DCHECK(gl);
871 resource->gl_id = texture_id_allocator_->NextId();
872 GLC(gl, gl->BindTexture(resource->target, resource->gl_id));
873 GLC(gl,
874 gl->ConsumeTextureCHROMIUM(resource->mailbox.target(),
875 resource->mailbox.name()));
878 if (!resource->pixels && resource->has_shared_bitmap_id &&
879 shared_bitmap_manager_) {
880 scoped_ptr<SharedBitmap> bitmap =
881 shared_bitmap_manager_->GetSharedBitmapFromId(
882 resource->size, resource->shared_bitmap_id);
883 if (bitmap) {
884 resource->shared_bitmap = bitmap.release();
885 resource->pixels = resource->shared_bitmap->pixels();
889 resource->lock_for_read_count++;
890 if (resource->read_lock_fences_enabled) {
891 if (current_read_lock_fence_.get())
892 current_read_lock_fence_->Set();
893 resource->read_lock_fence = current_read_lock_fence_;
896 return resource;
899 void ResourceProvider::UnlockForRead(ResourceId id) {
900 DCHECK(thread_checker_.CalledOnValidThread());
901 ResourceMap::iterator it = resources_.find(id);
902 CHECK(it != resources_.end());
904 Resource* resource = &it->second;
905 DCHECK_GT(resource->lock_for_read_count, 0);
906 DCHECK_EQ(resource->exported_count, 0);
907 resource->lock_for_read_count--;
908 if (resource->marked_for_deletion && !resource->lock_for_read_count) {
909 if (!resource->child_id) {
910 // The resource belongs to this ResourceProvider, so it can be destroyed.
911 DeleteResourceInternal(it, Normal);
912 } else {
913 ChildMap::iterator child_it = children_.find(resource->child_id);
914 ResourceIdArray unused;
915 unused.push_back(id);
916 DeleteAndReturnUnusedResourcesToChild(child_it, Normal, unused);
921 ResourceProvider::Resource* ResourceProvider::LockForWrite(ResourceId id) {
922 Resource* resource = GetResource(id);
923 DCHECK(CanLockForWrite(id));
925 resource->locked_for_write = true;
926 return resource;
929 bool ResourceProvider::CanLockForWrite(ResourceId id) {
930 Resource* resource = GetResource(id);
931 return !resource->locked_for_write && !resource->lock_for_read_count &&
932 !resource->exported_count && resource->origin == Resource::Internal &&
933 !resource->lost && ReadLockFenceHasPassed(resource);
936 void ResourceProvider::UnlockForWrite(ResourceProvider::Resource* resource) {
937 DCHECK(resource->locked_for_write);
938 DCHECK_EQ(resource->exported_count, 0);
939 DCHECK(resource->origin == Resource::Internal);
940 resource->locked_for_write = false;
943 ResourceProvider::ScopedReadLockGL::ScopedReadLockGL(
944 ResourceProvider* resource_provider,
945 ResourceProvider::ResourceId resource_id)
946 : resource_provider_(resource_provider),
947 resource_id_(resource_id),
948 texture_id_(resource_provider->LockForRead(resource_id)->gl_id) {
949 DCHECK(texture_id_);
952 ResourceProvider::ScopedReadLockGL::~ScopedReadLockGL() {
953 resource_provider_->UnlockForRead(resource_id_);
956 ResourceProvider::ScopedSamplerGL::ScopedSamplerGL(
957 ResourceProvider* resource_provider,
958 ResourceProvider::ResourceId resource_id,
959 GLenum filter)
960 : ScopedReadLockGL(resource_provider, resource_id),
961 unit_(GL_TEXTURE0),
962 target_(resource_provider->BindForSampling(resource_id, unit_, filter)) {
965 ResourceProvider::ScopedSamplerGL::ScopedSamplerGL(
966 ResourceProvider* resource_provider,
967 ResourceProvider::ResourceId resource_id,
968 GLenum unit,
969 GLenum filter)
970 : ScopedReadLockGL(resource_provider, resource_id),
971 unit_(unit),
972 target_(resource_provider->BindForSampling(resource_id, unit_, filter)) {
975 ResourceProvider::ScopedSamplerGL::~ScopedSamplerGL() {
978 ResourceProvider::ScopedWriteLockGL::ScopedWriteLockGL(
979 ResourceProvider* resource_provider,
980 ResourceProvider::ResourceId resource_id)
981 : resource_provider_(resource_provider),
982 resource_(resource_provider->LockForWrite(resource_id)) {
983 resource_provider_->LazyAllocate(resource_);
984 texture_id_ = resource_->gl_id;
985 DCHECK(texture_id_);
988 ResourceProvider::ScopedWriteLockGL::~ScopedWriteLockGL() {
989 resource_provider_->UnlockForWrite(resource_);
992 void ResourceProvider::PopulateSkBitmapWithResource(
993 SkBitmap* sk_bitmap, const Resource* resource) {
994 DCHECK_EQ(RGBA_8888, resource->format);
995 SkImageInfo info = SkImageInfo::MakeN32Premul(resource->size.width(),
996 resource->size.height());
997 sk_bitmap->installPixels(info, resource->pixels, info.minRowBytes());
1000 ResourceProvider::ScopedReadLockSoftware::ScopedReadLockSoftware(
1001 ResourceProvider* resource_provider,
1002 ResourceProvider::ResourceId resource_id)
1003 : resource_provider_(resource_provider),
1004 resource_id_(resource_id) {
1005 const Resource* resource = resource_provider->LockForRead(resource_id);
1006 wrap_mode_ = resource->wrap_mode;
1007 ResourceProvider::PopulateSkBitmapWithResource(&sk_bitmap_, resource);
1010 ResourceProvider::ScopedReadLockSoftware::~ScopedReadLockSoftware() {
1011 resource_provider_->UnlockForRead(resource_id_);
1014 ResourceProvider::ScopedWriteLockSoftware::ScopedWriteLockSoftware(
1015 ResourceProvider* resource_provider,
1016 ResourceProvider::ResourceId resource_id)
1017 : resource_provider_(resource_provider),
1018 resource_(resource_provider->LockForWrite(resource_id)) {
1019 ResourceProvider::PopulateSkBitmapWithResource(&sk_bitmap_, resource_);
1020 DCHECK(valid());
1023 ResourceProvider::ScopedWriteLockSoftware::~ScopedWriteLockSoftware() {
1024 DCHECK(thread_checker_.CalledOnValidThread());
1025 resource_provider_->UnlockForWrite(resource_);
1028 ResourceProvider::ScopedWriteLockGpuMemoryBuffer::
1029 ScopedWriteLockGpuMemoryBuffer(ResourceProvider* resource_provider,
1030 ResourceProvider::ResourceId resource_id)
1031 : resource_provider_(resource_provider),
1032 resource_(resource_provider->LockForWrite(resource_id)),
1033 gpu_memory_buffer_manager_(resource_provider->gpu_memory_buffer_manager_),
1034 gpu_memory_buffer_(nullptr),
1035 size_(resource_->size),
1036 format_(resource_->format) {
1037 DCHECK_EQ(GLTexture, resource_->type);
1038 std::swap(gpu_memory_buffer_, resource_->gpu_memory_buffer);
1041 ResourceProvider::ScopedWriteLockGpuMemoryBuffer::
1042 ~ScopedWriteLockGpuMemoryBuffer() {
1043 DCHECK(thread_checker_.CalledOnValidThread());
1044 resource_provider_->UnlockForWrite(resource_);
1045 if (!gpu_memory_buffer_)
1046 return;
1048 if (!resource_->image_id) {
1049 GLES2Interface* gl = resource_provider_->ContextGL();
1050 DCHECK(gl);
1052 #if defined(OS_CHROMEOS)
1053 // TODO(reveman): GL_COMMANDS_ISSUED_CHROMIUM is used for synchronization
1054 // on ChromeOS to avoid some performance issues. This only works with
1055 // shared memory backed buffers. crbug.com/436314
1056 DCHECK_EQ(gpu_memory_buffer_->GetHandle().type, gfx::SHARED_MEMORY_BUFFER);
1057 #endif
1059 resource_->image_id =
1060 gl->CreateImageCHROMIUM(gpu_memory_buffer_->AsClientBuffer(),
1061 size_.width(),
1062 size_.height(),
1063 GL_RGBA);
1066 std::swap(resource_->gpu_memory_buffer, gpu_memory_buffer_);
1067 resource_->allocated = true;
1068 resource_->dirty_image = true;
1070 // GpuMemoryBuffer provides direct access to the memory used by the GPU.
1071 // Read lock fences are required to ensure that we're not trying to map a
1072 // buffer that is currently in-use by the GPU.
1073 resource_->read_lock_fences_enabled = true;
1076 gfx::GpuMemoryBuffer*
1077 ResourceProvider::ScopedWriteLockGpuMemoryBuffer::GetGpuMemoryBuffer() {
1078 if (!gpu_memory_buffer_) {
1079 scoped_ptr<gfx::GpuMemoryBuffer> gpu_memory_buffer =
1080 gpu_memory_buffer_manager_->AllocateGpuMemoryBuffer(
1081 size_, ToGpuMemoryBufferFormat(format_), gfx::GpuMemoryBuffer::MAP);
1082 gpu_memory_buffer_ = gpu_memory_buffer.release();
1085 return gpu_memory_buffer_;
1088 ResourceProvider::ScopedWriteLockGr::ScopedWriteLockGr(
1089 ResourceProvider* resource_provider,
1090 ResourceProvider::ResourceId resource_id,
1091 bool use_distance_field_text,
1092 bool can_use_lcd_text,
1093 int msaa_sample_count)
1094 : resource_provider_(resource_provider),
1095 resource_(resource_provider->LockForWrite(resource_id)) {
1096 // Create the sk_surface.
1097 DCHECK(thread_checker_.CalledOnValidThread());
1098 DCHECK(resource_->locked_for_write);
1100 resource_provider_->LazyAllocate(resource_);
1102 GrBackendTextureDesc desc;
1103 desc.fFlags = kRenderTarget_GrBackendTextureFlag;
1104 desc.fWidth = resource_->size.width();
1105 desc.fHeight = resource_->size.height();
1106 desc.fConfig = ToGrPixelConfig(resource_->format);
1107 desc.fOrigin = kTopLeft_GrSurfaceOrigin;
1108 desc.fTextureHandle = resource_->gl_id;
1109 desc.fSampleCnt = msaa_sample_count;
1111 class GrContext* gr_context = resource_provider_->GrContext();
1112 skia::RefPtr<GrTexture> gr_texture =
1113 skia::AdoptRef(gr_context->wrapBackendTexture(desc));
1114 if (gr_texture) {
1115 uint32_t flags = use_distance_field_text
1116 ? SkSurfaceProps::kUseDistanceFieldFonts_Flag
1117 : 0;
1118 // Use unknown pixel geometry to disable LCD text.
1119 SkSurfaceProps surface_props(flags, kUnknown_SkPixelGeometry);
1120 if (can_use_lcd_text) {
1121 // LegacyFontHost will get LCD text and skia figures out what type to use.
1122 surface_props =
1123 SkSurfaceProps(flags, SkSurfaceProps::kLegacyFontHost_InitType);
1125 sk_surface_ = skia::AdoptRef(SkSurface::NewRenderTargetDirect(
1126 gr_texture->asRenderTarget(), &surface_props));
1130 ResourceProvider::ScopedWriteLockGr::~ScopedWriteLockGr() {
1131 DCHECK(thread_checker_.CalledOnValidThread());
1132 resource_provider_->UnlockForWrite(resource_);
1135 ResourceProvider::SynchronousFence::SynchronousFence(
1136 gpu::gles2::GLES2Interface* gl)
1137 : gl_(gl), has_synchronized_(true) {
1140 ResourceProvider::SynchronousFence::~SynchronousFence() {
1143 void ResourceProvider::SynchronousFence::Set() {
1144 has_synchronized_ = false;
1147 bool ResourceProvider::SynchronousFence::HasPassed() {
1148 if (!has_synchronized_) {
1149 has_synchronized_ = true;
1150 Synchronize();
1152 return true;
1155 void ResourceProvider::SynchronousFence::Wait() {
1156 HasPassed();
1159 void ResourceProvider::SynchronousFence::Synchronize() {
1160 TRACE_EVENT0("cc", "ResourceProvider::SynchronousFence::Synchronize");
1161 gl_->Finish();
1164 ResourceProvider::ResourceProvider(
1165 OutputSurface* output_surface,
1166 SharedBitmapManager* shared_bitmap_manager,
1167 gpu::GpuMemoryBufferManager* gpu_memory_buffer_manager,
1168 BlockingTaskRunner* blocking_main_thread_task_runner,
1169 int highp_threshold_min,
1170 bool use_rgba_4444_texture_format,
1171 size_t id_allocation_chunk_size)
1172 : output_surface_(output_surface),
1173 shared_bitmap_manager_(shared_bitmap_manager),
1174 gpu_memory_buffer_manager_(gpu_memory_buffer_manager),
1175 blocking_main_thread_task_runner_(blocking_main_thread_task_runner),
1176 lost_output_surface_(false),
1177 highp_threshold_min_(highp_threshold_min),
1178 next_id_(1),
1179 next_child_(1),
1180 default_resource_type_(InvalidType),
1181 use_texture_storage_ext_(false),
1182 use_texture_format_bgra_(false),
1183 use_texture_usage_hint_(false),
1184 use_compressed_texture_etc1_(false),
1185 yuv_resource_format_(LUMINANCE_8),
1186 max_texture_size_(0),
1187 best_texture_format_(RGBA_8888),
1188 use_rgba_4444_texture_format_(use_rgba_4444_texture_format),
1189 id_allocation_chunk_size_(id_allocation_chunk_size),
1190 use_sync_query_(false) {
1191 DCHECK(output_surface_->HasClient());
1192 DCHECK(id_allocation_chunk_size_);
1195 void ResourceProvider::InitializeSoftware() {
1196 DCHECK(thread_checker_.CalledOnValidThread());
1197 DCHECK_NE(Bitmap, default_resource_type_);
1199 CleanUpGLIfNeeded();
1201 default_resource_type_ = Bitmap;
1202 // Pick an arbitrary limit here similar to what hardware might.
1203 max_texture_size_ = 16 * 1024;
1204 best_texture_format_ = RGBA_8888;
1207 void ResourceProvider::InitializeGL() {
1208 DCHECK(thread_checker_.CalledOnValidThread());
1209 DCHECK(!texture_uploader_);
1210 DCHECK_NE(GLTexture, default_resource_type_);
1211 DCHECK(!texture_id_allocator_);
1212 DCHECK(!buffer_id_allocator_);
1214 default_resource_type_ = GLTexture;
1216 const ContextProvider::Capabilities& caps =
1217 output_surface_->context_provider()->ContextCapabilities();
1219 bool use_bgra = caps.gpu.texture_format_bgra8888;
1220 use_texture_storage_ext_ = caps.gpu.texture_storage;
1221 use_texture_format_bgra_ = caps.gpu.texture_format_bgra8888;
1222 use_texture_usage_hint_ = caps.gpu.texture_usage;
1223 use_compressed_texture_etc1_ = caps.gpu.texture_format_etc1;
1224 yuv_resource_format_ = caps.gpu.texture_rg ? RED_8 : LUMINANCE_8;
1225 use_sync_query_ = caps.gpu.sync_query;
1227 GLES2Interface* gl = ContextGL();
1228 DCHECK(gl);
1230 texture_uploader_ = TextureUploader::Create(gl);
1231 max_texture_size_ = 0; // Context expects cleared value.
1232 GLC(gl, gl->GetIntegerv(GL_MAX_TEXTURE_SIZE, &max_texture_size_));
1233 best_texture_format_ = PlatformColor::BestTextureFormat(use_bgra);
1235 texture_id_allocator_.reset(
1236 new TextureIdAllocator(gl, id_allocation_chunk_size_));
1237 buffer_id_allocator_.reset(
1238 new BufferIdAllocator(gl, id_allocation_chunk_size_));
1241 void ResourceProvider::CleanUpGLIfNeeded() {
1242 GLES2Interface* gl = ContextGL();
1243 if (default_resource_type_ != GLTexture) {
1244 // We are not in GL mode, but double check before returning.
1245 DCHECK(!gl);
1246 DCHECK(!texture_uploader_);
1247 return;
1250 DCHECK(gl);
1251 #if DCHECK_IS_ON()
1252 // Check that all GL resources has been deleted.
1253 for (ResourceMap::const_iterator itr = resources_.begin();
1254 itr != resources_.end();
1255 ++itr) {
1256 DCHECK_NE(GLTexture, itr->second.type);
1258 #endif // DCHECK_IS_ON()
1260 texture_uploader_ = nullptr;
1261 texture_id_allocator_ = nullptr;
1262 buffer_id_allocator_ = nullptr;
1263 gl->Finish();
1266 int ResourceProvider::CreateChild(const ReturnCallback& return_callback) {
1267 DCHECK(thread_checker_.CalledOnValidThread());
1269 Child child_info;
1270 child_info.return_callback = return_callback;
1272 int child = next_child_++;
1273 children_[child] = child_info;
1274 return child;
1277 void ResourceProvider::DestroyChild(int child_id) {
1278 ChildMap::iterator it = children_.find(child_id);
1279 DCHECK(it != children_.end());
1280 DestroyChildInternal(it, Normal);
1283 void ResourceProvider::DestroyChildInternal(ChildMap::iterator it,
1284 DeleteStyle style) {
1285 DCHECK(thread_checker_.CalledOnValidThread());
1287 Child& child = it->second;
1288 DCHECK(style == ForShutdown || !child.marked_for_deletion);
1290 ResourceIdArray resources_for_child;
1292 for (ResourceIdMap::iterator child_it = child.child_to_parent_map.begin();
1293 child_it != child.child_to_parent_map.end();
1294 ++child_it) {
1295 ResourceId id = child_it->second;
1296 resources_for_child.push_back(id);
1299 // If the child is going away, don't consider any resources in use.
1300 child.in_use_resources.clear();
1301 child.marked_for_deletion = true;
1303 DeleteAndReturnUnusedResourcesToChild(it, style, resources_for_child);
1306 const ResourceProvider::ResourceIdMap& ResourceProvider::GetChildToParentMap(
1307 int child) const {
1308 DCHECK(thread_checker_.CalledOnValidThread());
1309 ChildMap::const_iterator it = children_.find(child);
1310 DCHECK(it != children_.end());
1311 DCHECK(!it->second.marked_for_deletion);
1312 return it->second.child_to_parent_map;
1315 void ResourceProvider::PrepareSendToParent(const ResourceIdArray& resources,
1316 TransferableResourceArray* list) {
1317 DCHECK(thread_checker_.CalledOnValidThread());
1318 GLES2Interface* gl = ContextGL();
1319 bool need_sync_point = false;
1320 for (ResourceIdArray::const_iterator it = resources.begin();
1321 it != resources.end();
1322 ++it) {
1323 TransferableResource resource;
1324 TransferResource(gl, *it, &resource);
1325 if (!resource.mailbox_holder.sync_point && !resource.is_software)
1326 need_sync_point = true;
1327 ++resources_.find(*it)->second.exported_count;
1328 list->push_back(resource);
1330 if (need_sync_point) {
1331 GLuint sync_point = gl->InsertSyncPointCHROMIUM();
1332 for (TransferableResourceArray::iterator it = list->begin();
1333 it != list->end();
1334 ++it) {
1335 if (!it->mailbox_holder.sync_point)
1336 it->mailbox_holder.sync_point = sync_point;
1341 void ResourceProvider::ReceiveFromChild(
1342 int child, const TransferableResourceArray& resources) {
1343 DCHECK(thread_checker_.CalledOnValidThread());
1344 GLES2Interface* gl = ContextGL();
1345 Child& child_info = children_.find(child)->second;
1346 DCHECK(!child_info.marked_for_deletion);
1347 for (TransferableResourceArray::const_iterator it = resources.begin();
1348 it != resources.end();
1349 ++it) {
1350 ResourceIdMap::iterator resource_in_map_it =
1351 child_info.child_to_parent_map.find(it->id);
1352 if (resource_in_map_it != child_info.child_to_parent_map.end()) {
1353 Resource& resource = resources_[resource_in_map_it->second];
1354 resource.marked_for_deletion = false;
1355 resource.imported_count++;
1356 continue;
1359 if ((!it->is_software && !gl) ||
1360 (it->is_software && !shared_bitmap_manager_)) {
1361 TRACE_EVENT0("cc", "ResourceProvider::ReceiveFromChild dropping invalid");
1362 ReturnedResourceArray to_return;
1363 to_return.push_back(it->ToReturnedResource());
1364 child_info.return_callback.Run(to_return,
1365 blocking_main_thread_task_runner_);
1366 continue;
1369 ResourceId local_id = next_id_++;
1370 Resource& resource = resources_[local_id];
1371 if (it->is_software) {
1372 resource = Resource(it->mailbox_holder.mailbox,
1373 it->size,
1374 Resource::Delegated,
1375 GL_LINEAR,
1376 it->is_repeated ? GL_REPEAT : GL_CLAMP_TO_EDGE);
1377 } else {
1378 resource = Resource(0,
1379 it->size,
1380 Resource::Delegated,
1381 it->mailbox_holder.texture_target,
1382 it->filter,
1384 it->is_repeated ? GL_REPEAT : GL_CLAMP_TO_EDGE,
1385 TextureHintImmutable,
1386 it->format);
1387 resource.mailbox = TextureMailbox(it->mailbox_holder.mailbox,
1388 it->mailbox_holder.texture_target,
1389 it->mailbox_holder.sync_point);
1391 resource.child_id = child;
1392 // Don't allocate a texture for a child.
1393 resource.allocated = true;
1394 resource.imported_count = 1;
1395 resource.allow_overlay = it->allow_overlay;
1396 child_info.parent_to_child_map[local_id] = it->id;
1397 child_info.child_to_parent_map[it->id] = local_id;
1401 void ResourceProvider::DeclareUsedResourcesFromChild(
1402 int child,
1403 const ResourceIdArray& resources_from_child) {
1404 DCHECK(thread_checker_.CalledOnValidThread());
1406 ChildMap::iterator child_it = children_.find(child);
1407 DCHECK(child_it != children_.end());
1408 Child& child_info = child_it->second;
1409 DCHECK(!child_info.marked_for_deletion);
1410 child_info.in_use_resources.clear();
1412 for (size_t i = 0; i < resources_from_child.size(); ++i) {
1413 ResourceIdMap::iterator it =
1414 child_info.child_to_parent_map.find(resources_from_child[i]);
1415 DCHECK(it != child_info.child_to_parent_map.end());
1417 ResourceId local_id = it->second;
1418 DCHECK(!resources_[local_id].marked_for_deletion);
1419 child_info.in_use_resources.insert(local_id);
1422 ResourceIdArray unused;
1423 for (ResourceIdMap::iterator it = child_info.child_to_parent_map.begin();
1424 it != child_info.child_to_parent_map.end();
1425 ++it) {
1426 ResourceId local_id = it->second;
1427 bool resource_is_in_use = child_info.in_use_resources.count(local_id) > 0;
1428 if (!resource_is_in_use)
1429 unused.push_back(local_id);
1431 DeleteAndReturnUnusedResourcesToChild(child_it, Normal, unused);
1434 // static
1435 bool ResourceProvider::CompareResourceMapIteratorsByChildId(
1436 const std::pair<ReturnedResource, ResourceMap::iterator>& a,
1437 const std::pair<ReturnedResource, ResourceMap::iterator>& b) {
1438 const ResourceMap::iterator& a_it = a.second;
1439 const ResourceMap::iterator& b_it = b.second;
1440 const Resource& a_resource = a_it->second;
1441 const Resource& b_resource = b_it->second;
1442 return a_resource.child_id < b_resource.child_id;
1445 void ResourceProvider::ReceiveReturnsFromParent(
1446 const ReturnedResourceArray& resources) {
1447 DCHECK(thread_checker_.CalledOnValidThread());
1448 GLES2Interface* gl = ContextGL();
1450 int child_id = 0;
1451 ResourceIdArray resources_for_child;
1453 std::vector<std::pair<ReturnedResource, ResourceMap::iterator>>
1454 sorted_resources;
1456 for (ReturnedResourceArray::const_iterator it = resources.begin();
1457 it != resources.end();
1458 ++it) {
1459 ResourceId local_id = it->id;
1460 ResourceMap::iterator map_iterator = resources_.find(local_id);
1462 // Resource was already lost (e.g. it belonged to a child that was
1463 // destroyed).
1464 if (map_iterator == resources_.end())
1465 continue;
1467 sorted_resources.push_back(
1468 std::pair<ReturnedResource, ResourceMap::iterator>(*it, map_iterator));
1471 std::sort(sorted_resources.begin(),
1472 sorted_resources.end(),
1473 CompareResourceMapIteratorsByChildId);
1475 ChildMap::iterator child_it = children_.end();
1476 for (size_t i = 0; i < sorted_resources.size(); ++i) {
1477 ReturnedResource& returned = sorted_resources[i].first;
1478 ResourceMap::iterator& map_iterator = sorted_resources[i].second;
1479 ResourceId local_id = map_iterator->first;
1480 Resource* resource = &map_iterator->second;
1482 CHECK_GE(resource->exported_count, returned.count);
1483 resource->exported_count -= returned.count;
1484 resource->lost |= returned.lost;
1485 if (resource->exported_count)
1486 continue;
1488 // Need to wait for the current read lock fence to pass before we can
1489 // recycle this resource.
1490 if (resource->read_lock_fences_enabled) {
1491 if (current_read_lock_fence_.get())
1492 current_read_lock_fence_->Set();
1493 resource->read_lock_fence = current_read_lock_fence_;
1496 if (returned.sync_point) {
1497 DCHECK(!resource->has_shared_bitmap_id);
1498 if (resource->origin == Resource::Internal) {
1499 DCHECK(resource->gl_id);
1500 GLC(gl, gl->WaitSyncPointCHROMIUM(returned.sync_point));
1501 } else {
1502 DCHECK(!resource->gl_id);
1503 resource->mailbox.set_sync_point(returned.sync_point);
1507 if (!resource->marked_for_deletion)
1508 continue;
1510 if (!resource->child_id) {
1511 // The resource belongs to this ResourceProvider, so it can be destroyed.
1512 DeleteResourceInternal(map_iterator, Normal);
1513 continue;
1516 DCHECK(resource->origin == Resource::Delegated);
1517 // Delete the resource and return it to the child it came from one.
1518 if (resource->child_id != child_id) {
1519 if (child_id) {
1520 DCHECK_NE(resources_for_child.size(), 0u);
1521 DCHECK(child_it != children_.end());
1522 DeleteAndReturnUnusedResourcesToChild(
1523 child_it, Normal, resources_for_child);
1524 resources_for_child.clear();
1527 child_it = children_.find(resource->child_id);
1528 DCHECK(child_it != children_.end());
1529 child_id = resource->child_id;
1531 resources_for_child.push_back(local_id);
1534 if (child_id) {
1535 DCHECK_NE(resources_for_child.size(), 0u);
1536 DCHECK(child_it != children_.end());
1537 DeleteAndReturnUnusedResourcesToChild(
1538 child_it, Normal, resources_for_child);
1542 void ResourceProvider::TransferResource(GLES2Interface* gl,
1543 ResourceId id,
1544 TransferableResource* resource) {
1545 Resource* source = GetResource(id);
1546 DCHECK(!source->locked_for_write);
1547 DCHECK(!source->lock_for_read_count);
1548 DCHECK(source->origin != Resource::External || source->mailbox.IsValid());
1549 DCHECK(source->allocated);
1550 resource->id = id;
1551 resource->format = source->format;
1552 resource->mailbox_holder.texture_target = source->target;
1553 resource->filter = source->filter;
1554 resource->size = source->size;
1555 resource->is_repeated = (source->wrap_mode == GL_REPEAT);
1556 resource->allow_overlay = source->allow_overlay;
1558 if (source->type == Bitmap) {
1559 resource->mailbox_holder.mailbox = source->shared_bitmap_id;
1560 resource->is_software = true;
1561 } else if (!source->mailbox.IsValid()) {
1562 LazyCreate(source);
1563 DCHECK(source->gl_id);
1564 DCHECK(source->origin == Resource::Internal);
1565 GLC(gl,
1566 gl->BindTexture(resource->mailbox_holder.texture_target,
1567 source->gl_id));
1568 if (source->image_id) {
1569 DCHECK(source->dirty_image);
1570 BindImageForSampling(source);
1572 // This is a resource allocated by the compositor, we need to produce it.
1573 // Don't set a sync point, the caller will do it.
1574 GLC(gl, gl->GenMailboxCHROMIUM(resource->mailbox_holder.mailbox.name));
1575 GLC(gl,
1576 gl->ProduceTextureCHROMIUM(resource->mailbox_holder.texture_target,
1577 resource->mailbox_holder.mailbox.name));
1578 source->mailbox = TextureMailbox(resource->mailbox_holder);
1579 } else {
1580 DCHECK(source->mailbox.IsTexture());
1581 if (source->image_id && source->dirty_image) {
1582 DCHECK(source->gl_id);
1583 DCHECK(source->origin == Resource::Internal);
1584 GLC(gl,
1585 gl->BindTexture(resource->mailbox_holder.texture_target,
1586 source->gl_id));
1587 BindImageForSampling(source);
1589 // This is either an external resource, or a compositor resource that we
1590 // already exported. Make sure to forward the sync point that we were given.
1591 resource->mailbox_holder.mailbox = source->mailbox.mailbox();
1592 resource->mailbox_holder.texture_target = source->mailbox.target();
1593 resource->mailbox_holder.sync_point = source->mailbox.sync_point();
1594 source->mailbox.set_sync_point(0);
1598 void ResourceProvider::DeleteAndReturnUnusedResourcesToChild(
1599 ChildMap::iterator child_it,
1600 DeleteStyle style,
1601 const ResourceIdArray& unused) {
1602 DCHECK(thread_checker_.CalledOnValidThread());
1603 DCHECK(child_it != children_.end());
1604 Child* child_info = &child_it->second;
1606 if (unused.empty() && !child_info->marked_for_deletion)
1607 return;
1609 ReturnedResourceArray to_return;
1611 GLES2Interface* gl = ContextGL();
1612 bool need_sync_point = false;
1613 for (size_t i = 0; i < unused.size(); ++i) {
1614 ResourceId local_id = unused[i];
1616 ResourceMap::iterator it = resources_.find(local_id);
1617 CHECK(it != resources_.end());
1618 Resource& resource = it->second;
1620 DCHECK(!resource.locked_for_write);
1621 DCHECK_EQ(0u, child_info->in_use_resources.count(local_id));
1622 DCHECK(child_info->parent_to_child_map.count(local_id));
1624 ResourceId child_id = child_info->parent_to_child_map[local_id];
1625 DCHECK(child_info->child_to_parent_map.count(child_id));
1627 bool is_lost =
1628 resource.lost || (resource.type == GLTexture && lost_output_surface_);
1629 if (resource.exported_count > 0 || resource.lock_for_read_count > 0) {
1630 if (style != ForShutdown) {
1631 // Defer this until we receive the resource back from the parent or
1632 // the read lock is released.
1633 resource.marked_for_deletion = true;
1634 continue;
1637 // We still have an exported_count, so we'll have to lose it.
1638 is_lost = true;
1641 if (gl && resource.filter != resource.original_filter) {
1642 DCHECK(resource.target);
1643 DCHECK(resource.gl_id);
1645 GLC(gl, gl->BindTexture(resource.target, resource.gl_id));
1646 GLC(gl,
1647 gl->TexParameteri(resource.target,
1648 GL_TEXTURE_MIN_FILTER,
1649 resource.original_filter));
1650 GLC(gl,
1651 gl->TexParameteri(resource.target,
1652 GL_TEXTURE_MAG_FILTER,
1653 resource.original_filter));
1656 ReturnedResource returned;
1657 returned.id = child_id;
1658 returned.sync_point = resource.mailbox.sync_point();
1659 if (!returned.sync_point && resource.type == GLTexture)
1660 need_sync_point = true;
1661 returned.count = resource.imported_count;
1662 returned.lost = is_lost;
1663 to_return.push_back(returned);
1665 child_info->parent_to_child_map.erase(local_id);
1666 child_info->child_to_parent_map.erase(child_id);
1667 resource.imported_count = 0;
1668 DeleteResourceInternal(it, style);
1670 if (need_sync_point) {
1671 DCHECK(gl);
1672 GLuint sync_point = gl->InsertSyncPointCHROMIUM();
1673 for (size_t i = 0; i < to_return.size(); ++i) {
1674 if (!to_return[i].sync_point)
1675 to_return[i].sync_point = sync_point;
1679 if (!to_return.empty())
1680 child_info->return_callback.Run(to_return,
1681 blocking_main_thread_task_runner_);
1683 if (child_info->marked_for_deletion &&
1684 child_info->parent_to_child_map.empty()) {
1685 DCHECK(child_info->child_to_parent_map.empty());
1686 children_.erase(child_it);
1690 void ResourceProvider::AcquirePixelBuffer(ResourceId id) {
1691 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug"),
1692 "ResourceProvider::AcquirePixelBuffer");
1694 Resource* resource = GetResource(id);
1695 DCHECK(resource->origin == Resource::Internal);
1696 DCHECK_EQ(resource->exported_count, 0);
1697 DCHECK(!resource->image_id);
1698 DCHECK_NE(ETC1, resource->format);
1700 DCHECK_EQ(GLTexture, resource->type);
1701 GLES2Interface* gl = ContextGL();
1702 DCHECK(gl);
1703 if (!resource->gl_pixel_buffer_id)
1704 resource->gl_pixel_buffer_id = buffer_id_allocator_->NextId();
1705 gl->BindBuffer(GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM,
1706 resource->gl_pixel_buffer_id);
1707 unsigned bytes_per_pixel = BitsPerPixel(resource->format) / 8;
1708 gl->BufferData(GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM,
1709 resource->size.height() *
1710 RoundUp(bytes_per_pixel * resource->size.width(), 4u),
1711 NULL,
1712 GL_DYNAMIC_DRAW);
1713 gl->BindBuffer(GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM, 0);
1716 void ResourceProvider::ReleasePixelBuffer(ResourceId id) {
1717 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug"),
1718 "ResourceProvider::ReleasePixelBuffer");
1720 Resource* resource = GetResource(id);
1721 DCHECK(resource->origin == Resource::Internal);
1722 DCHECK_EQ(resource->exported_count, 0);
1723 DCHECK(!resource->image_id);
1725 // The pixel buffer can be released while there is a pending "set pixels"
1726 // if completion has been forced. Any shared memory associated with this
1727 // pixel buffer will not be freed until the waitAsyncTexImage2DCHROMIUM
1728 // command has been processed on the service side. It is also safe to
1729 // reuse any query id associated with this resource before they complete
1730 // as each new query has a unique submit count.
1731 if (resource->pending_set_pixels) {
1732 DCHECK(resource->set_pixels_completion_forced);
1733 resource->pending_set_pixels = false;
1734 resource->locked_for_write = false;
1737 DCHECK_EQ(GLTexture, resource->type);
1738 if (!resource->gl_pixel_buffer_id)
1739 return;
1740 GLES2Interface* gl = ContextGL();
1741 DCHECK(gl);
1742 gl->BindBuffer(GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM,
1743 resource->gl_pixel_buffer_id);
1744 gl->BufferData(
1745 GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM, 0, NULL, GL_DYNAMIC_DRAW);
1746 gl->BindBuffer(GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM, 0);
1749 uint8_t* ResourceProvider::MapPixelBuffer(ResourceId id, int* stride) {
1750 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug"),
1751 "ResourceProvider::MapPixelBuffer");
1753 Resource* resource = GetResource(id);
1754 DCHECK(resource->origin == Resource::Internal);
1755 DCHECK_EQ(resource->exported_count, 0);
1756 DCHECK(!resource->image_id);
1758 *stride = 0;
1759 DCHECK_EQ(GLTexture, resource->type);
1760 GLES2Interface* gl = ContextGL();
1761 DCHECK(gl);
1762 DCHECK(resource->gl_pixel_buffer_id);
1763 gl->BindBuffer(GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM,
1764 resource->gl_pixel_buffer_id);
1765 uint8_t* image = static_cast<uint8_t*>(gl->MapBufferCHROMIUM(
1766 GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM, GL_WRITE_ONLY));
1767 gl->BindBuffer(GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM, 0);
1768 // Buffer is required to be 4-byte aligned.
1769 CHECK(!(reinterpret_cast<intptr_t>(image) & 3));
1770 return image;
1773 void ResourceProvider::UnmapPixelBuffer(ResourceId id) {
1774 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug"),
1775 "ResourceProvider::UnmapPixelBuffer");
1777 Resource* resource = GetResource(id);
1778 DCHECK(resource->origin == Resource::Internal);
1779 DCHECK_EQ(resource->exported_count, 0);
1780 DCHECK(!resource->image_id);
1782 DCHECK_EQ(GLTexture, resource->type);
1783 GLES2Interface* gl = ContextGL();
1784 DCHECK(gl);
1785 DCHECK(resource->gl_pixel_buffer_id);
1786 gl->BindBuffer(GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM,
1787 resource->gl_pixel_buffer_id);
1788 gl->UnmapBufferCHROMIUM(GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM);
1789 gl->BindBuffer(GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM, 0);
1792 GLenum ResourceProvider::BindForSampling(ResourceId resource_id,
1793 GLenum unit,
1794 GLenum filter) {
1795 DCHECK(thread_checker_.CalledOnValidThread());
1796 GLES2Interface* gl = ContextGL();
1797 ResourceMap::iterator it = resources_.find(resource_id);
1798 DCHECK(it != resources_.end());
1799 Resource* resource = &it->second;
1800 DCHECK(resource->lock_for_read_count);
1801 DCHECK(!resource->locked_for_write || resource->set_pixels_completion_forced);
1803 ScopedSetActiveTexture scoped_active_tex(gl, unit);
1804 GLenum target = resource->target;
1805 GLC(gl, gl->BindTexture(target, resource->gl_id));
1806 if (filter != resource->filter) {
1807 GLC(gl, gl->TexParameteri(target, GL_TEXTURE_MIN_FILTER, filter));
1808 GLC(gl, gl->TexParameteri(target, GL_TEXTURE_MAG_FILTER, filter));
1809 resource->filter = filter;
1812 if (resource->image_id && resource->dirty_image)
1813 BindImageForSampling(resource);
1815 return target;
1818 void ResourceProvider::BeginSetPixels(ResourceId id) {
1819 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug"),
1820 "ResourceProvider::BeginSetPixels");
1822 Resource* resource = GetResource(id);
1823 DCHECK(!resource->pending_set_pixels);
1825 LazyCreate(resource);
1826 DCHECK(resource->origin == Resource::Internal);
1827 DCHECK(resource->gl_id || resource->allocated);
1828 DCHECK(ReadLockFenceHasPassed(resource));
1829 DCHECK(!resource->image_id);
1831 bool allocate = !resource->allocated;
1832 resource->allocated = true;
1833 LockForWrite(id);
1835 DCHECK_EQ(GLTexture, resource->type);
1836 DCHECK(resource->gl_id);
1837 GLES2Interface* gl = ContextGL();
1838 DCHECK(gl);
1839 DCHECK(resource->gl_pixel_buffer_id);
1840 DCHECK_EQ(resource->target, static_cast<GLenum>(GL_TEXTURE_2D));
1841 gl->BindTexture(GL_TEXTURE_2D, resource->gl_id);
1842 gl->BindBuffer(GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM,
1843 resource->gl_pixel_buffer_id);
1844 if (!resource->gl_upload_query_id)
1845 gl->GenQueriesEXT(1, &resource->gl_upload_query_id);
1846 gl->BeginQueryEXT(GL_ASYNC_PIXEL_UNPACK_COMPLETED_CHROMIUM,
1847 resource->gl_upload_query_id);
1848 if (allocate) {
1849 gl->AsyncTexImage2DCHROMIUM(GL_TEXTURE_2D,
1850 0, /* level */
1851 GLInternalFormat(resource->format),
1852 resource->size.width(),
1853 resource->size.height(),
1854 0, /* border */
1855 GLDataFormat(resource->format),
1856 GLDataType(resource->format),
1857 NULL);
1858 } else {
1859 gl->AsyncTexSubImage2DCHROMIUM(GL_TEXTURE_2D,
1860 0, /* level */
1861 0, /* x */
1862 0, /* y */
1863 resource->size.width(),
1864 resource->size.height(),
1865 GLDataFormat(resource->format),
1866 GLDataType(resource->format),
1867 NULL);
1869 gl->EndQueryEXT(GL_ASYNC_PIXEL_UNPACK_COMPLETED_CHROMIUM);
1870 gl->BindBuffer(GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM, 0);
1872 resource->pending_set_pixels = true;
1873 resource->set_pixels_completion_forced = false;
1876 void ResourceProvider::ForceSetPixelsToComplete(ResourceId id) {
1877 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug"),
1878 "ResourceProvider::ForceSetPixelsToComplete");
1880 Resource* resource = GetResource(id);
1882 DCHECK(resource->locked_for_write);
1883 DCHECK(resource->pending_set_pixels);
1884 DCHECK(!resource->set_pixels_completion_forced);
1886 if (resource->gl_id) {
1887 GLES2Interface* gl = ContextGL();
1888 GLC(gl, gl->BindTexture(GL_TEXTURE_2D, resource->gl_id));
1889 GLC(gl, gl->WaitAsyncTexImage2DCHROMIUM(GL_TEXTURE_2D));
1890 GLC(gl, gl->BindTexture(GL_TEXTURE_2D, 0));
1893 resource->set_pixels_completion_forced = true;
1896 bool ResourceProvider::DidSetPixelsComplete(ResourceId id) {
1897 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug"),
1898 "ResourceProvider::DidSetPixelsComplete");
1900 Resource* resource = GetResource(id);
1902 DCHECK(resource->locked_for_write);
1903 DCHECK(resource->pending_set_pixels);
1905 if (resource->gl_id) {
1906 GLES2Interface* gl = ContextGL();
1907 DCHECK(gl);
1908 DCHECK(resource->gl_upload_query_id);
1909 GLuint complete = 1;
1910 gl->GetQueryObjectuivEXT(
1911 resource->gl_upload_query_id, GL_QUERY_RESULT_AVAILABLE_EXT, &complete);
1912 if (!complete)
1913 return false;
1916 resource->pending_set_pixels = false;
1917 UnlockForWrite(resource);
1919 // Async set pixels commands are not necessarily processed in-sequence with
1920 // drawing commands. Read lock fences are required to ensure that async
1921 // commands don't access the resource while used for drawing.
1922 resource->read_lock_fences_enabled = true;
1924 return true;
1927 void ResourceProvider::CreateForTesting(ResourceId id) {
1928 LazyCreate(GetResource(id));
1931 GLenum ResourceProvider::TargetForTesting(ResourceId id) {
1932 Resource* resource = GetResource(id);
1933 return resource->target;
1936 void ResourceProvider::LazyCreate(Resource* resource) {
1937 if (resource->type != GLTexture || resource->origin != Resource::Internal)
1938 return;
1940 if (resource->gl_id)
1941 return;
1943 DCHECK(resource->texture_pool);
1944 DCHECK(resource->origin == Resource::Internal);
1945 DCHECK(!resource->mailbox.IsValid());
1946 resource->gl_id = texture_id_allocator_->NextId();
1948 GLES2Interface* gl = ContextGL();
1949 DCHECK(gl);
1951 // Create and set texture properties. Allocation is delayed until needed.
1952 GLC(gl, gl->BindTexture(resource->target, resource->gl_id));
1953 GLC(gl,
1954 gl->TexParameteri(
1955 resource->target, GL_TEXTURE_MIN_FILTER, resource->original_filter));
1956 GLC(gl,
1957 gl->TexParameteri(
1958 resource->target, GL_TEXTURE_MAG_FILTER, resource->original_filter));
1959 GLC(gl,
1960 gl->TexParameteri(
1961 resource->target, GL_TEXTURE_WRAP_S, resource->wrap_mode));
1962 GLC(gl,
1963 gl->TexParameteri(
1964 resource->target, GL_TEXTURE_WRAP_T, resource->wrap_mode));
1965 GLC(gl,
1966 gl->TexParameteri(
1967 resource->target, GL_TEXTURE_POOL_CHROMIUM, resource->texture_pool));
1968 if (use_texture_usage_hint_ && (resource->hint & TextureHintFramebuffer)) {
1969 GLC(gl,
1970 gl->TexParameteri(resource->target,
1971 GL_TEXTURE_USAGE_ANGLE,
1972 GL_FRAMEBUFFER_ATTACHMENT_ANGLE));
1976 void ResourceProvider::AllocateForTesting(ResourceId id) {
1977 LazyAllocate(GetResource(id));
1980 void ResourceProvider::LazyAllocate(Resource* resource) {
1981 DCHECK(resource);
1982 if (resource->allocated)
1983 return;
1984 LazyCreate(resource);
1985 if (!resource->gl_id)
1986 return;
1987 resource->allocated = true;
1988 GLES2Interface* gl = ContextGL();
1989 gfx::Size& size = resource->size;
1990 DCHECK_EQ(resource->target, static_cast<GLenum>(GL_TEXTURE_2D));
1991 ResourceFormat format = resource->format;
1992 GLC(gl, gl->BindTexture(GL_TEXTURE_2D, resource->gl_id));
1993 if (use_texture_storage_ext_ &&
1994 IsFormatSupportedForStorage(format, use_texture_format_bgra_) &&
1995 (resource->hint & TextureHintImmutable)) {
1996 GLenum storage_format = TextureToStorageFormat(format);
1997 GLC(gl,
1998 gl->TexStorage2DEXT(
1999 GL_TEXTURE_2D, 1, storage_format, size.width(), size.height()));
2000 } else {
2001 // ETC1 does not support preallocation.
2002 if (format != ETC1) {
2003 GLC(gl,
2004 gl->TexImage2D(GL_TEXTURE_2D,
2006 GLInternalFormat(format),
2007 size.width(),
2008 size.height(),
2010 GLDataFormat(format),
2011 GLDataType(format),
2012 NULL));
2017 void ResourceProvider::BindImageForSampling(Resource* resource) {
2018 GLES2Interface* gl = ContextGL();
2019 DCHECK(resource->gl_id);
2020 DCHECK(resource->image_id);
2022 // Release image currently bound to texture.
2023 if (resource->bound_image_id)
2024 gl->ReleaseTexImage2DCHROMIUM(resource->target, resource->bound_image_id);
2025 gl->BindTexImage2DCHROMIUM(resource->target, resource->image_id);
2026 resource->bound_image_id = resource->image_id;
2027 resource->dirty_image = false;
2030 void ResourceProvider::CopyResource(ResourceId source_id, ResourceId dest_id) {
2031 TRACE_EVENT0("cc", "ResourceProvider::CopyResource");
2033 Resource* source_resource = GetResource(source_id);
2034 DCHECK(!source_resource->lock_for_read_count);
2035 DCHECK(source_resource->origin == Resource::Internal);
2036 DCHECK_EQ(source_resource->exported_count, 0);
2037 DCHECK_EQ(GLTexture, source_resource->type);
2038 DCHECK(source_resource->allocated);
2039 LazyCreate(source_resource);
2041 Resource* dest_resource = GetResource(dest_id);
2042 DCHECK(!dest_resource->locked_for_write);
2043 DCHECK(!dest_resource->lock_for_read_count);
2044 DCHECK(dest_resource->origin == Resource::Internal);
2045 DCHECK_EQ(dest_resource->exported_count, 0);
2046 DCHECK_EQ(GLTexture, dest_resource->type);
2047 LazyAllocate(dest_resource);
2049 DCHECK_EQ(source_resource->type, dest_resource->type);
2050 DCHECK_EQ(source_resource->format, dest_resource->format);
2051 DCHECK(source_resource->size == dest_resource->size);
2053 GLES2Interface* gl = ContextGL();
2054 DCHECK(gl);
2055 if (source_resource->image_id && source_resource->dirty_image) {
2056 gl->BindTexture(source_resource->target, source_resource->gl_id);
2057 BindImageForSampling(source_resource);
2059 if (use_sync_query_) {
2060 if (!source_resource->gl_read_lock_query_id)
2061 gl->GenQueriesEXT(1, &source_resource->gl_read_lock_query_id);
2062 #if defined(OS_CHROMEOS)
2063 // TODO(reveman): This avoids a performance problem on some ChromeOS
2064 // devices. This needs to be removed to support native GpuMemoryBuffer
2065 // implementations. crbug.com/436314
2066 gl->BeginQueryEXT(GL_COMMANDS_ISSUED_CHROMIUM,
2067 source_resource->gl_read_lock_query_id);
2068 #else
2069 gl->BeginQueryEXT(GL_COMMANDS_COMPLETED_CHROMIUM,
2070 source_resource->gl_read_lock_query_id);
2071 #endif
2073 DCHECK(!dest_resource->image_id);
2074 dest_resource->allocated = true;
2075 gl->CopyTextureCHROMIUM(dest_resource->target,
2076 source_resource->gl_id,
2077 dest_resource->gl_id,
2079 GLInternalFormat(dest_resource->format),
2080 GLDataType(dest_resource->format));
2081 if (source_resource->gl_read_lock_query_id) {
2082 // End query and create a read lock fence that will prevent access to
2083 // source resource until CopyTextureCHROMIUM command has completed.
2084 #if defined(OS_CHROMEOS)
2085 gl->EndQueryEXT(GL_COMMANDS_ISSUED_CHROMIUM);
2086 #else
2087 gl->EndQueryEXT(GL_COMMANDS_COMPLETED_CHROMIUM);
2088 #endif
2089 source_resource->read_lock_fence = make_scoped_refptr(
2090 new CopyTextureFence(gl, source_resource->gl_read_lock_query_id));
2091 } else {
2092 // Create a SynchronousFence when CHROMIUM_sync_query extension is missing.
2093 // Try to use one synchronous fence for as many CopyResource operations as
2094 // possible as that reduce the number of times we have to synchronize with
2095 // the GL.
2096 if (!synchronous_fence_.get() || synchronous_fence_->has_synchronized())
2097 synchronous_fence_ = make_scoped_refptr(new SynchronousFence(gl));
2098 source_resource->read_lock_fence = synchronous_fence_;
2099 source_resource->read_lock_fence->Set();
2103 void ResourceProvider::WaitSyncPointIfNeeded(ResourceId id) {
2104 Resource* resource = GetResource(id);
2105 DCHECK_EQ(resource->exported_count, 0);
2106 DCHECK(resource->allocated);
2107 if (resource->type != GLTexture || resource->gl_id)
2108 return;
2109 if (!resource->mailbox.sync_point())
2110 return;
2111 DCHECK(resource->mailbox.IsValid());
2112 GLES2Interface* gl = ContextGL();
2113 DCHECK(gl);
2114 GLC(gl, gl->WaitSyncPointCHROMIUM(resource->mailbox.sync_point()));
2115 resource->mailbox.set_sync_point(0);
2118 void ResourceProvider::WaitReadLockIfNeeded(ResourceId id) {
2119 Resource* resource = GetResource(id);
2120 DCHECK_EQ(resource->exported_count, 0);
2121 if (!resource->read_lock_fence.get())
2122 return;
2124 resource->read_lock_fence->Wait();
2127 GLint ResourceProvider::GetActiveTextureUnit(GLES2Interface* gl) {
2128 GLint active_unit = 0;
2129 gl->GetIntegerv(GL_ACTIVE_TEXTURE, &active_unit);
2130 return active_unit;
2133 GLES2Interface* ResourceProvider::ContextGL() const {
2134 ContextProvider* context_provider = output_surface_->context_provider();
2135 return context_provider ? context_provider->ContextGL() : NULL;
2138 class GrContext* ResourceProvider::GrContext() const {
2139 ContextProvider* context_provider = output_surface_->context_provider();
2140 return context_provider ? context_provider->GrContext() : NULL;
2143 } // namespace cc