[Do not revert] Roll-back V8 to version 4.4.63.
[chromium-blink-merge.git] / cc / resources / resource_provider.cc
blobeb774fe10b3bd8d2ce217aa806d90a7158e3ca11
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/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 "third_party/skia/include/gpu/GrTextureProvider.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 gl_->ActiveTexture(unit_);
147 ~ScopedSetActiveTexture() {
148 // Active unit being GL_TEXTURE0 is effectively the ground state.
149 if (unit_ != GL_TEXTURE0)
150 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() {}
249 ResourceProvider::Resource::Resource(GLuint texture_id,
250 const gfx::Size& size,
251 Origin origin,
252 GLenum target,
253 GLenum filter,
254 GLenum texture_pool,
255 GLint wrap_mode,
256 TextureHint hint,
257 ResourceFormat format)
258 : child_id(0),
259 gl_id(texture_id),
260 gl_pixel_buffer_id(0),
261 gl_upload_query_id(0),
262 gl_read_lock_query_id(0),
263 pixels(NULL),
264 lock_for_read_count(0),
265 imported_count(0),
266 exported_count(0),
267 dirty_image(false),
268 locked_for_write(false),
269 lost(false),
270 marked_for_deletion(false),
271 pending_set_pixels(false),
272 set_pixels_completion_forced(false),
273 allocated(false),
274 read_lock_fences_enabled(false),
275 has_shared_bitmap_id(false),
276 allow_overlay(false),
277 read_lock_fence(NULL),
278 size(size),
279 origin(origin),
280 target(target),
281 original_filter(filter),
282 filter(filter),
283 image_id(0),
284 bound_image_id(0),
285 texture_pool(texture_pool),
286 wrap_mode(wrap_mode),
287 hint(hint),
288 type(RESOURCE_TYPE_GL_TEXTURE),
289 format(format),
290 shared_bitmap(NULL),
291 gpu_memory_buffer(NULL) {
292 DCHECK(wrap_mode == GL_CLAMP_TO_EDGE || wrap_mode == GL_REPEAT);
293 DCHECK_EQ(origin == INTERNAL, !!texture_pool);
296 ResourceProvider::Resource::Resource(uint8_t* pixels,
297 SharedBitmap* bitmap,
298 const gfx::Size& size,
299 Origin origin,
300 GLenum filter,
301 GLint wrap_mode)
302 : child_id(0),
303 gl_id(0),
304 gl_pixel_buffer_id(0),
305 gl_upload_query_id(0),
306 gl_read_lock_query_id(0),
307 pixels(pixels),
308 lock_for_read_count(0),
309 imported_count(0),
310 exported_count(0),
311 dirty_image(false),
312 locked_for_write(false),
313 lost(false),
314 marked_for_deletion(false),
315 pending_set_pixels(false),
316 set_pixels_completion_forced(false),
317 allocated(false),
318 read_lock_fences_enabled(false),
319 has_shared_bitmap_id(!!bitmap),
320 allow_overlay(false),
321 read_lock_fence(NULL),
322 size(size),
323 origin(origin),
324 target(0),
325 original_filter(filter),
326 filter(filter),
327 image_id(0),
328 bound_image_id(0),
329 texture_pool(0),
330 wrap_mode(wrap_mode),
331 hint(TEXTURE_HINT_IMMUTABLE),
332 type(RESOURCE_TYPE_BITMAP),
333 format(RGBA_8888),
334 shared_bitmap(bitmap),
335 gpu_memory_buffer(NULL) {
336 DCHECK(wrap_mode == GL_CLAMP_TO_EDGE || wrap_mode == GL_REPEAT);
337 DCHECK(origin == DELEGATED || pixels);
338 if (bitmap)
339 shared_bitmap_id = bitmap->id();
342 ResourceProvider::Resource::Resource(const SharedBitmapId& bitmap_id,
343 const gfx::Size& size,
344 Origin origin,
345 GLenum filter,
346 GLint wrap_mode)
347 : child_id(0),
348 gl_id(0),
349 gl_pixel_buffer_id(0),
350 gl_upload_query_id(0),
351 gl_read_lock_query_id(0),
352 pixels(NULL),
353 lock_for_read_count(0),
354 imported_count(0),
355 exported_count(0),
356 dirty_image(false),
357 locked_for_write(false),
358 lost(false),
359 marked_for_deletion(false),
360 pending_set_pixels(false),
361 set_pixels_completion_forced(false),
362 allocated(false),
363 read_lock_fences_enabled(false),
364 has_shared_bitmap_id(true),
365 allow_overlay(false),
366 read_lock_fence(NULL),
367 size(size),
368 origin(origin),
369 target(0),
370 original_filter(filter),
371 filter(filter),
372 image_id(0),
373 bound_image_id(0),
374 texture_pool(0),
375 wrap_mode(wrap_mode),
376 hint(TEXTURE_HINT_IMMUTABLE),
377 type(RESOURCE_TYPE_BITMAP),
378 format(RGBA_8888),
379 shared_bitmap_id(bitmap_id),
380 shared_bitmap(NULL),
381 gpu_memory_buffer(NULL) {
382 DCHECK(wrap_mode == GL_CLAMP_TO_EDGE || wrap_mode == GL_REPEAT);
385 ResourceProvider::Child::Child()
386 : marked_for_deletion(false), needs_sync_points(true) {
389 ResourceProvider::Child::~Child() {}
391 scoped_ptr<ResourceProvider> ResourceProvider::Create(
392 OutputSurface* output_surface,
393 SharedBitmapManager* shared_bitmap_manager,
394 gpu::GpuMemoryBufferManager* gpu_memory_buffer_manager,
395 BlockingTaskRunner* blocking_main_thread_task_runner,
396 int highp_threshold_min,
397 bool use_rgba_4444_texture_format,
398 size_t id_allocation_chunk_size) {
399 ContextProvider* context_provider = output_surface->context_provider();
400 GLES2Interface* gl =
401 context_provider ? context_provider->ContextGL() : nullptr;
402 ResourceType default_resource_type =
403 gl ? RESOURCE_TYPE_GL_TEXTURE : RESOURCE_TYPE_BITMAP;
405 scoped_ptr<ResourceProvider> resource_provider(new ResourceProvider(
406 output_surface, shared_bitmap_manager, gpu_memory_buffer_manager,
407 blocking_main_thread_task_runner, highp_threshold_min,
408 default_resource_type, use_rgba_4444_texture_format,
409 id_allocation_chunk_size));
411 if (gl)
412 resource_provider->InitializeGL();
413 else
414 resource_provider->InitializeSoftware();
416 return resource_provider.Pass();
419 ResourceProvider::~ResourceProvider() {
420 while (!children_.empty())
421 DestroyChildInternal(children_.begin(), FOR_SHUTDOWN);
422 while (!resources_.empty())
423 DeleteResourceInternal(resources_.begin(), FOR_SHUTDOWN);
425 GLES2Interface* gl = ContextGL();
426 if (default_resource_type_ != RESOURCE_TYPE_GL_TEXTURE) {
427 // We are not in GL mode, but double check before returning.
428 DCHECK(!gl);
429 DCHECK(!texture_uploader_);
430 return;
433 DCHECK(gl);
434 #if DCHECK_IS_ON()
435 // Check that all GL resources has been deleted.
436 for (ResourceMap::const_iterator itr = resources_.begin();
437 itr != resources_.end(); ++itr) {
438 DCHECK_NE(RESOURCE_TYPE_GL_TEXTURE, itr->second.type);
440 #endif // DCHECK_IS_ON()
442 texture_uploader_ = nullptr;
443 texture_id_allocator_ = nullptr;
444 buffer_id_allocator_ = nullptr;
445 gl->Finish();
448 bool ResourceProvider::InUseByConsumer(ResourceId id) {
449 Resource* resource = GetResource(id);
450 return resource->lock_for_read_count > 0 || resource->exported_count > 0 ||
451 resource->lost;
454 bool ResourceProvider::IsLost(ResourceId id) {
455 Resource* resource = GetResource(id);
456 return resource->lost;
459 bool ResourceProvider::AllowOverlay(ResourceId id) {
460 Resource* resource = GetResource(id);
461 return resource->allow_overlay;
464 ResourceProvider::ResourceId ResourceProvider::CreateResource(
465 const gfx::Size& size,
466 GLint wrap_mode,
467 TextureHint hint,
468 ResourceFormat format) {
469 DCHECK(!size.IsEmpty());
470 switch (default_resource_type_) {
471 case RESOURCE_TYPE_GL_TEXTURE:
472 return CreateGLTexture(size,
473 GL_TEXTURE_2D,
474 GL_TEXTURE_POOL_UNMANAGED_CHROMIUM,
475 wrap_mode,
476 hint,
477 format);
478 case RESOURCE_TYPE_BITMAP:
479 DCHECK_EQ(RGBA_8888, format);
480 return CreateBitmap(size, wrap_mode);
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 RESOURCE_TYPE_GL_TEXTURE:
496 return CreateGLTexture(size,
497 target,
498 GL_TEXTURE_POOL_MANAGED_CHROMIUM,
499 wrap_mode,
500 hint,
501 format);
502 case RESOURCE_TYPE_BITMAP:
503 DCHECK_EQ(RGBA_8888, format);
504 return CreateBitmap(size, wrap_mode);
507 LOG(FATAL) << "Invalid default resource type.";
508 return 0;
511 ResourceProvider::ResourceId ResourceProvider::CreateGLTexture(
512 const gfx::Size& size,
513 GLenum target,
514 GLenum texture_pool,
515 GLint wrap_mode,
516 TextureHint hint,
517 ResourceFormat format) {
518 DCHECK_LE(size.width(), max_texture_size_);
519 DCHECK_LE(size.height(), max_texture_size_);
520 DCHECK(thread_checker_.CalledOnValidThread());
522 ResourceId id = next_id_++;
523 Resource* resource = InsertResource(
524 id, Resource(0, size, Resource::INTERNAL, target, GL_LINEAR, texture_pool,
525 wrap_mode, hint, format));
526 resource->allocated = false;
527 return id;
530 ResourceProvider::ResourceId ResourceProvider::CreateBitmap(
531 const gfx::Size& size, GLint wrap_mode) {
532 DCHECK(thread_checker_.CalledOnValidThread());
534 scoped_ptr<SharedBitmap> bitmap =
535 shared_bitmap_manager_->AllocateSharedBitmap(size);
536 uint8_t* pixels = bitmap->pixels();
537 DCHECK(pixels);
539 ResourceId id = next_id_++;
540 Resource* resource =
541 InsertResource(id, Resource(pixels, bitmap.release(), size,
542 Resource::INTERNAL, GL_LINEAR, wrap_mode));
543 resource->allocated = true;
544 return id;
547 ResourceProvider::ResourceId ResourceProvider::CreateResourceFromIOSurface(
548 const gfx::Size& size,
549 unsigned io_surface_id) {
550 DCHECK(thread_checker_.CalledOnValidThread());
552 ResourceId id = next_id_++;
553 Resource* resource = InsertResource(
554 id, Resource(0, gfx::Size(), Resource::INTERNAL, GL_TEXTURE_RECTANGLE_ARB,
555 GL_LINEAR, GL_TEXTURE_POOL_UNMANAGED_CHROMIUM,
556 GL_CLAMP_TO_EDGE, TEXTURE_HINT_IMMUTABLE, RGBA_8888));
557 LazyCreate(resource);
558 GLES2Interface* gl = ContextGL();
559 DCHECK(gl);
560 gl->BindTexture(GL_TEXTURE_RECTANGLE_ARB, resource->gl_id);
561 gl->TexImageIOSurface2DCHROMIUM(
562 GL_TEXTURE_RECTANGLE_ARB, size.width(), size.height(), io_surface_id, 0);
563 resource->allocated = true;
564 return id;
567 ResourceProvider::ResourceId ResourceProvider::CreateResourceFromTextureMailbox(
568 const TextureMailbox& mailbox,
569 scoped_ptr<SingleReleaseCallbackImpl> release_callback_impl) {
570 DCHECK(thread_checker_.CalledOnValidThread());
571 // Just store the information. Mailbox will be consumed in LockForRead().
572 ResourceId id = next_id_++;
573 DCHECK(mailbox.IsValid());
574 Resource* resource = nullptr;
575 if (mailbox.IsTexture()) {
576 resource = InsertResource(
577 id, Resource(0, gfx::Size(), Resource::EXTERNAL, mailbox.target(),
578 mailbox.nearest_neighbor() ? GL_NEAREST : GL_LINEAR, 0,
579 GL_CLAMP_TO_EDGE, TEXTURE_HINT_IMMUTABLE, RGBA_8888));
580 } else {
581 DCHECK(mailbox.IsSharedMemory());
582 SharedBitmap* shared_bitmap = mailbox.shared_bitmap();
583 uint8_t* pixels = shared_bitmap->pixels();
584 DCHECK(pixels);
585 resource = InsertResource(
586 id, Resource(pixels, shared_bitmap, mailbox.shared_memory_size(),
587 Resource::EXTERNAL, GL_LINEAR, GL_CLAMP_TO_EDGE));
589 resource->allocated = true;
590 resource->mailbox = mailbox;
591 resource->release_callback_impl =
592 base::Bind(&SingleReleaseCallbackImpl::Run,
593 base::Owned(release_callback_impl.release()));
594 resource->allow_overlay = mailbox.allow_overlay();
595 return id;
598 void ResourceProvider::DeleteResource(ResourceId id) {
599 DCHECK(thread_checker_.CalledOnValidThread());
600 ResourceMap::iterator it = resources_.find(id);
601 CHECK(it != resources_.end());
602 Resource* resource = &it->second;
603 DCHECK(!resource->marked_for_deletion);
604 DCHECK_EQ(resource->imported_count, 0);
605 DCHECK(resource->pending_set_pixels || !resource->locked_for_write);
607 if (resource->exported_count > 0 || resource->lock_for_read_count > 0) {
608 resource->marked_for_deletion = true;
609 return;
610 } else {
611 DeleteResourceInternal(it, NORMAL);
615 void ResourceProvider::DeleteResourceInternal(ResourceMap::iterator it,
616 DeleteStyle style) {
617 TRACE_EVENT0("cc", "ResourceProvider::DeleteResourceInternal");
618 Resource* resource = &it->second;
619 bool lost_resource = resource->lost;
621 DCHECK(resource->exported_count == 0 || style != NORMAL);
622 if (style == FOR_SHUTDOWN && resource->exported_count > 0)
623 lost_resource = true;
625 if (resource->image_id) {
626 DCHECK(resource->origin == Resource::INTERNAL);
627 GLES2Interface* gl = ContextGL();
628 DCHECK(gl);
629 gl->DestroyImageCHROMIUM(resource->image_id);
631 if (resource->gl_upload_query_id) {
632 DCHECK(resource->origin == Resource::INTERNAL);
633 GLES2Interface* gl = ContextGL();
634 DCHECK(gl);
635 gl->DeleteQueriesEXT(1, &resource->gl_upload_query_id);
637 if (resource->gl_read_lock_query_id) {
638 DCHECK(resource->origin == Resource::INTERNAL);
639 GLES2Interface* gl = ContextGL();
640 DCHECK(gl);
641 gl->DeleteQueriesEXT(1, &resource->gl_read_lock_query_id);
643 if (resource->gl_pixel_buffer_id) {
644 DCHECK(resource->origin == Resource::INTERNAL);
645 GLES2Interface* gl = ContextGL();
646 DCHECK(gl);
647 gl->DeleteBuffers(1, &resource->gl_pixel_buffer_id);
649 if (resource->origin == Resource::EXTERNAL) {
650 DCHECK(resource->mailbox.IsValid());
651 GLuint sync_point = resource->mailbox.sync_point();
652 if (resource->type == RESOURCE_TYPE_GL_TEXTURE) {
653 DCHECK(resource->mailbox.IsTexture());
654 lost_resource |= lost_output_surface_;
655 GLES2Interface* gl = ContextGL();
656 DCHECK(gl);
657 if (resource->gl_id) {
658 gl->DeleteTextures(1, &resource->gl_id);
659 resource->gl_id = 0;
660 if (!lost_resource)
661 sync_point = gl->InsertSyncPointCHROMIUM();
663 } else {
664 DCHECK(resource->mailbox.IsSharedMemory());
665 resource->shared_bitmap = nullptr;
666 resource->pixels = nullptr;
668 resource->release_callback_impl.Run(
669 sync_point, lost_resource, blocking_main_thread_task_runner_);
671 if (resource->gl_id) {
672 GLES2Interface* gl = ContextGL();
673 DCHECK(gl);
674 gl->DeleteTextures(1, &resource->gl_id);
675 resource->gl_id = 0;
677 if (resource->shared_bitmap) {
678 DCHECK(resource->origin != Resource::EXTERNAL);
679 DCHECK_EQ(RESOURCE_TYPE_BITMAP, resource->type);
680 delete resource->shared_bitmap;
681 resource->pixels = NULL;
683 if (resource->pixels) {
684 DCHECK(resource->origin == Resource::INTERNAL);
685 delete[] resource->pixels;
686 resource->pixels = NULL;
688 if (resource->gpu_memory_buffer) {
689 DCHECK(resource->origin == Resource::INTERNAL);
690 delete resource->gpu_memory_buffer;
691 resource->gpu_memory_buffer = NULL;
693 resources_.erase(it);
696 ResourceProvider::ResourceType ResourceProvider::GetResourceType(
697 ResourceId id) {
698 return GetResource(id)->type;
701 void ResourceProvider::SetPixels(ResourceId id,
702 const uint8_t* image,
703 const gfx::Rect& image_rect,
704 const gfx::Rect& source_rect,
705 const gfx::Vector2d& dest_offset) {
706 Resource* resource = GetResource(id);
707 DCHECK(!resource->locked_for_write);
708 DCHECK(!resource->lock_for_read_count);
709 DCHECK(resource->origin == Resource::INTERNAL);
710 DCHECK_EQ(resource->exported_count, 0);
711 DCHECK(ReadLockFenceHasPassed(resource));
712 LazyAllocate(resource);
714 if (resource->type == RESOURCE_TYPE_GL_TEXTURE) {
715 DCHECK(resource->gl_id);
716 DCHECK(!resource->pending_set_pixels);
717 DCHECK_EQ(resource->target, static_cast<GLenum>(GL_TEXTURE_2D));
718 GLES2Interface* gl = ContextGL();
719 DCHECK(gl);
720 DCHECK(texture_uploader_.get());
721 gl->BindTexture(GL_TEXTURE_2D, resource->gl_id);
722 texture_uploader_->Upload(image,
723 image_rect,
724 source_rect,
725 dest_offset,
726 resource->format,
727 resource->size);
728 } else {
729 DCHECK_EQ(RESOURCE_TYPE_BITMAP, resource->type);
730 DCHECK(resource->allocated);
731 DCHECK_EQ(RGBA_8888, resource->format);
732 DCHECK(source_rect.x() >= image_rect.x());
733 DCHECK(source_rect.y() >= image_rect.y());
734 DCHECK(source_rect.right() <= image_rect.right());
735 DCHECK(source_rect.bottom() <= image_rect.bottom());
736 SkImageInfo source_info =
737 SkImageInfo::MakeN32Premul(source_rect.width(), source_rect.height());
738 size_t image_row_bytes = image_rect.width() * 4;
739 gfx::Vector2d source_offset = source_rect.origin() - image_rect.origin();
740 image += source_offset.y() * image_row_bytes + source_offset.x() * 4;
742 ScopedWriteLockSoftware lock(this, id);
743 SkCanvas dest(lock.sk_bitmap());
744 dest.writePixels(source_info, image, image_row_bytes, dest_offset.x(),
745 dest_offset.y());
749 void ResourceProvider::CopyToResource(ResourceId id,
750 const uint8_t* image,
751 const gfx::Size& image_size) {
752 Resource* resource = GetResource(id);
753 DCHECK(!resource->locked_for_write);
754 DCHECK(!resource->lock_for_read_count);
755 DCHECK(resource->origin == Resource::INTERNAL);
756 DCHECK_EQ(resource->exported_count, 0);
757 DCHECK(ReadLockFenceHasPassed(resource));
758 LazyAllocate(resource);
760 DCHECK_EQ(image_size.width(), resource->size.width());
761 DCHECK_EQ(image_size.height(), resource->size.height());
763 if (resource->type == RESOURCE_TYPE_BITMAP) {
764 DCHECK_EQ(RESOURCE_TYPE_BITMAP, resource->type);
765 DCHECK(resource->allocated);
766 DCHECK_EQ(RGBA_8888, resource->format);
767 SkImageInfo source_info =
768 SkImageInfo::MakeN32Premul(image_size.width(), image_size.height());
769 size_t image_stride = image_size.width() * 4;
771 ScopedWriteLockSoftware lock(this, id);
772 SkCanvas dest(lock.sk_bitmap());
773 dest.writePixels(source_info, image, image_stride, 0, 0);
774 } else {
775 DCHECK(resource->gl_id);
776 DCHECK(!resource->pending_set_pixels);
777 DCHECK_EQ(resource->target, static_cast<GLenum>(GL_TEXTURE_2D));
778 GLES2Interface* gl = ContextGL();
779 DCHECK(gl);
780 DCHECK(texture_uploader_.get());
781 gl->BindTexture(GL_TEXTURE_2D, resource->gl_id);
783 if (resource->format == ETC1) {
784 size_t num_bytes = static_cast<size_t>(image_size.width()) *
785 image_size.height() * BitsPerPixel(ETC1) / 8;
786 gl->CompressedTexImage2D(GL_TEXTURE_2D, 0, GLInternalFormat(ETC1),
787 image_size.width(), image_size.height(), 0,
788 num_bytes, image);
789 } else {
790 gl->TexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, image_size.width(),
791 image_size.height(), GLDataFormat(resource->format),
792 GLDataType(resource->format), image);
797 size_t ResourceProvider::NumBlockingUploads() {
798 if (!texture_uploader_)
799 return 0;
801 return texture_uploader_->NumBlockingUploads();
804 void ResourceProvider::MarkPendingUploadsAsNonBlocking() {
805 if (!texture_uploader_)
806 return;
808 texture_uploader_->MarkPendingUploadsAsNonBlocking();
811 size_t ResourceProvider::EstimatedUploadsPerTick() {
812 if (!texture_uploader_)
813 return 1u;
815 double textures_per_second = texture_uploader_->EstimatedTexturesPerSecond();
816 size_t textures_per_tick = floor(
817 kTextureUploadTickRate * textures_per_second);
818 return textures_per_tick ? textures_per_tick : 1u;
821 void ResourceProvider::FlushUploads() {
822 if (!texture_uploader_)
823 return;
825 texture_uploader_->Flush();
828 void ResourceProvider::ReleaseCachedData() {
829 if (!texture_uploader_)
830 return;
832 texture_uploader_->ReleaseCachedQueries();
835 base::TimeTicks ResourceProvider::EstimatedUploadCompletionTime(
836 size_t uploads_per_tick) {
837 if (lost_output_surface_)
838 return base::TimeTicks();
840 // Software resource uploads happen on impl thread, so don't bother batching
841 // them up and trying to wait for them to complete.
842 if (!texture_uploader_) {
843 return gfx::FrameTime::Now() + base::TimeDelta::FromMicroseconds(
844 base::Time::kMicrosecondsPerSecond * kSoftwareUploadTickRate);
847 base::TimeDelta upload_one_texture_time =
848 base::TimeDelta::FromMicroseconds(
849 base::Time::kMicrosecondsPerSecond * kTextureUploadTickRate) /
850 uploads_per_tick;
852 size_t total_uploads = NumBlockingUploads() + uploads_per_tick;
853 return gfx::FrameTime::Now() + upload_one_texture_time * total_uploads;
856 ResourceProvider::Resource* ResourceProvider::InsertResource(
857 ResourceId id,
858 const Resource& resource) {
859 std::pair<ResourceMap::iterator, bool> result =
860 resources_.insert(ResourceMap::value_type(id, resource));
861 DCHECK(result.second);
862 return &result.first->second;
865 ResourceProvider::Resource* ResourceProvider::GetResource(ResourceId id) {
866 DCHECK(thread_checker_.CalledOnValidThread());
867 DCHECK(id);
868 ResourceMap::iterator it = resources_.find(id);
869 DCHECK(it != resources_.end());
870 return &it->second;
873 const ResourceProvider::Resource* ResourceProvider::LockForRead(ResourceId id) {
874 Resource* resource = GetResource(id);
875 DCHECK(!resource->locked_for_write ||
876 resource->set_pixels_completion_forced) <<
877 "locked for write: " << resource->locked_for_write <<
878 " pixels completion forced: " << resource->set_pixels_completion_forced;
879 DCHECK_EQ(resource->exported_count, 0);
880 // Uninitialized! Call SetPixels or LockForWrite first.
881 DCHECK(resource->allocated);
883 LazyCreate(resource);
885 if (resource->type == RESOURCE_TYPE_GL_TEXTURE && !resource->gl_id) {
886 DCHECK(resource->origin != Resource::INTERNAL);
887 DCHECK(resource->mailbox.IsTexture());
889 // Mailbox sync_points must be processed by a call to
890 // WaitSyncPointIfNeeded() prior to calling LockForRead().
891 DCHECK(!resource->mailbox.sync_point());
893 GLES2Interface* gl = ContextGL();
894 DCHECK(gl);
895 resource->gl_id = gl->CreateAndConsumeTextureCHROMIUM(
896 resource->mailbox.target(), resource->mailbox.name());
899 if (!resource->pixels && resource->has_shared_bitmap_id &&
900 shared_bitmap_manager_) {
901 scoped_ptr<SharedBitmap> bitmap =
902 shared_bitmap_manager_->GetSharedBitmapFromId(
903 resource->size, resource->shared_bitmap_id);
904 if (bitmap) {
905 resource->shared_bitmap = bitmap.release();
906 resource->pixels = resource->shared_bitmap->pixels();
910 resource->lock_for_read_count++;
911 if (resource->read_lock_fences_enabled) {
912 if (current_read_lock_fence_.get())
913 current_read_lock_fence_->Set();
914 resource->read_lock_fence = current_read_lock_fence_;
917 return resource;
920 void ResourceProvider::UnlockForRead(ResourceId id) {
921 DCHECK(thread_checker_.CalledOnValidThread());
922 ResourceMap::iterator it = resources_.find(id);
923 CHECK(it != resources_.end());
925 Resource* resource = &it->second;
926 DCHECK_GT(resource->lock_for_read_count, 0);
927 DCHECK_EQ(resource->exported_count, 0);
928 resource->lock_for_read_count--;
929 if (resource->marked_for_deletion && !resource->lock_for_read_count) {
930 if (!resource->child_id) {
931 // The resource belongs to this ResourceProvider, so it can be destroyed.
932 DeleteResourceInternal(it, NORMAL);
933 } else {
934 ChildMap::iterator child_it = children_.find(resource->child_id);
935 ResourceIdArray unused;
936 unused.push_back(id);
937 DeleteAndReturnUnusedResourcesToChild(child_it, NORMAL, unused);
942 ResourceProvider::Resource* ResourceProvider::LockForWrite(ResourceId id) {
943 Resource* resource = GetResource(id);
944 DCHECK(CanLockForWrite(id));
946 resource->locked_for_write = true;
947 return resource;
950 bool ResourceProvider::CanLockForWrite(ResourceId id) {
951 Resource* resource = GetResource(id);
952 return !resource->locked_for_write && !resource->lock_for_read_count &&
953 !resource->exported_count && resource->origin == Resource::INTERNAL &&
954 !resource->lost && ReadLockFenceHasPassed(resource);
957 void ResourceProvider::UnlockForWrite(ResourceProvider::Resource* resource) {
958 DCHECK(resource->locked_for_write);
959 DCHECK_EQ(resource->exported_count, 0);
960 DCHECK(resource->origin == Resource::INTERNAL);
961 resource->locked_for_write = false;
964 ResourceProvider::ScopedReadLockGL::ScopedReadLockGL(
965 ResourceProvider* resource_provider,
966 ResourceProvider::ResourceId resource_id)
967 : resource_provider_(resource_provider),
968 resource_id_(resource_id),
969 resource_(resource_provider->LockForRead(resource_id)) {
970 DCHECK(resource_);
973 ResourceProvider::ScopedReadLockGL::~ScopedReadLockGL() {
974 resource_provider_->UnlockForRead(resource_id_);
977 ResourceProvider::ScopedSamplerGL::ScopedSamplerGL(
978 ResourceProvider* resource_provider,
979 ResourceProvider::ResourceId resource_id,
980 GLenum filter)
981 : ScopedReadLockGL(resource_provider, resource_id),
982 unit_(GL_TEXTURE0),
983 target_(resource_provider->BindForSampling(resource_id, unit_, filter)) {
986 ResourceProvider::ScopedSamplerGL::ScopedSamplerGL(
987 ResourceProvider* resource_provider,
988 ResourceProvider::ResourceId resource_id,
989 GLenum unit,
990 GLenum filter)
991 : ScopedReadLockGL(resource_provider, resource_id),
992 unit_(unit),
993 target_(resource_provider->BindForSampling(resource_id, unit_, filter)) {
996 ResourceProvider::ScopedSamplerGL::~ScopedSamplerGL() {
999 ResourceProvider::ScopedWriteLockGL::ScopedWriteLockGL(
1000 ResourceProvider* resource_provider,
1001 ResourceProvider::ResourceId resource_id)
1002 : resource_provider_(resource_provider),
1003 resource_(resource_provider->LockForWrite(resource_id)) {
1004 resource_provider_->LazyAllocate(resource_);
1005 texture_id_ = resource_->gl_id;
1006 DCHECK(texture_id_);
1009 ResourceProvider::ScopedWriteLockGL::~ScopedWriteLockGL() {
1010 resource_provider_->UnlockForWrite(resource_);
1013 void ResourceProvider::PopulateSkBitmapWithResource(
1014 SkBitmap* sk_bitmap, const Resource* resource) {
1015 DCHECK_EQ(RGBA_8888, resource->format);
1016 SkImageInfo info = SkImageInfo::MakeN32Premul(resource->size.width(),
1017 resource->size.height());
1018 sk_bitmap->installPixels(info, resource->pixels, info.minRowBytes());
1021 ResourceProvider::ScopedReadLockSoftware::ScopedReadLockSoftware(
1022 ResourceProvider* resource_provider,
1023 ResourceProvider::ResourceId resource_id)
1024 : resource_provider_(resource_provider),
1025 resource_id_(resource_id) {
1026 const Resource* resource = resource_provider->LockForRead(resource_id);
1027 wrap_mode_ = resource->wrap_mode;
1028 ResourceProvider::PopulateSkBitmapWithResource(&sk_bitmap_, resource);
1031 ResourceProvider::ScopedReadLockSoftware::~ScopedReadLockSoftware() {
1032 resource_provider_->UnlockForRead(resource_id_);
1035 ResourceProvider::ScopedWriteLockSoftware::ScopedWriteLockSoftware(
1036 ResourceProvider* resource_provider,
1037 ResourceProvider::ResourceId resource_id)
1038 : resource_provider_(resource_provider),
1039 resource_(resource_provider->LockForWrite(resource_id)) {
1040 ResourceProvider::PopulateSkBitmapWithResource(&sk_bitmap_, resource_);
1041 DCHECK(valid());
1044 ResourceProvider::ScopedWriteLockSoftware::~ScopedWriteLockSoftware() {
1045 DCHECK(thread_checker_.CalledOnValidThread());
1046 resource_provider_->UnlockForWrite(resource_);
1049 ResourceProvider::ScopedWriteLockGpuMemoryBuffer::
1050 ScopedWriteLockGpuMemoryBuffer(ResourceProvider* resource_provider,
1051 ResourceProvider::ResourceId resource_id)
1052 : resource_provider_(resource_provider),
1053 resource_(resource_provider->LockForWrite(resource_id)),
1054 gpu_memory_buffer_manager_(resource_provider->gpu_memory_buffer_manager_),
1055 gpu_memory_buffer_(nullptr),
1056 size_(resource_->size),
1057 format_(resource_->format) {
1058 DCHECK_EQ(RESOURCE_TYPE_GL_TEXTURE, resource_->type);
1059 std::swap(gpu_memory_buffer_, resource_->gpu_memory_buffer);
1062 ResourceProvider::ScopedWriteLockGpuMemoryBuffer::
1063 ~ScopedWriteLockGpuMemoryBuffer() {
1064 DCHECK(thread_checker_.CalledOnValidThread());
1065 resource_provider_->UnlockForWrite(resource_);
1066 if (!gpu_memory_buffer_)
1067 return;
1069 if (!resource_->image_id) {
1070 GLES2Interface* gl = resource_provider_->ContextGL();
1071 DCHECK(gl);
1073 #if defined(OS_CHROMEOS)
1074 // TODO(reveman): GL_COMMANDS_ISSUED_CHROMIUM is used for synchronization
1075 // on ChromeOS to avoid some performance issues. This only works with
1076 // shared memory backed buffers. crbug.com/436314
1077 DCHECK_EQ(gpu_memory_buffer_->GetHandle().type, gfx::SHARED_MEMORY_BUFFER);
1078 #endif
1080 resource_->image_id = gl->CreateImageCHROMIUM(
1081 gpu_memory_buffer_->AsClientBuffer(), size_.width(), size_.height(),
1082 GLInternalFormat(resource_->format));
1085 std::swap(resource_->gpu_memory_buffer, gpu_memory_buffer_);
1086 resource_->allocated = true;
1087 resource_->dirty_image = true;
1089 // GpuMemoryBuffer provides direct access to the memory used by the GPU.
1090 // Read lock fences are required to ensure that we're not trying to map a
1091 // buffer that is currently in-use by the GPU.
1092 resource_->read_lock_fences_enabled = true;
1095 gfx::GpuMemoryBuffer*
1096 ResourceProvider::ScopedWriteLockGpuMemoryBuffer::GetGpuMemoryBuffer() {
1097 if (!gpu_memory_buffer_) {
1098 scoped_ptr<gfx::GpuMemoryBuffer> gpu_memory_buffer =
1099 gpu_memory_buffer_manager_->AllocateGpuMemoryBuffer(
1100 size_, ToGpuMemoryBufferFormat(format_), gfx::GpuMemoryBuffer::MAP);
1101 gpu_memory_buffer_ = gpu_memory_buffer.release();
1104 return gpu_memory_buffer_;
1107 ResourceProvider::ScopedWriteLockGr::ScopedWriteLockGr(
1108 ResourceProvider* resource_provider,
1109 ResourceProvider::ResourceId resource_id)
1110 : resource_provider_(resource_provider),
1111 resource_(resource_provider->LockForWrite(resource_id)) {
1112 DCHECK(thread_checker_.CalledOnValidThread());
1113 resource_provider_->LazyAllocate(resource_);
1116 ResourceProvider::ScopedWriteLockGr::~ScopedWriteLockGr() {
1117 DCHECK(thread_checker_.CalledOnValidThread());
1118 DCHECK(resource_->locked_for_write);
1119 resource_provider_->UnlockForWrite(resource_);
1122 void ResourceProvider::ScopedWriteLockGr::InitSkSurface(
1123 bool use_distance_field_text,
1124 bool can_use_lcd_text,
1125 int msaa_sample_count) {
1126 DCHECK(resource_->locked_for_write);
1128 GrBackendTextureDesc desc;
1129 desc.fFlags = kRenderTarget_GrBackendTextureFlag;
1130 desc.fWidth = resource_->size.width();
1131 desc.fHeight = resource_->size.height();
1132 desc.fConfig = ToGrPixelConfig(resource_->format);
1133 desc.fOrigin = kTopLeft_GrSurfaceOrigin;
1134 desc.fTextureHandle = resource_->gl_id;
1135 desc.fSampleCnt = msaa_sample_count;
1137 bool use_worker_context = true;
1138 class GrContext* gr_context =
1139 resource_provider_->GrContext(use_worker_context);
1140 skia::RefPtr<GrTexture> gr_texture =
1141 skia::AdoptRef(gr_context->textureProvider()->wrapBackendTexture(desc));
1142 if (gr_texture) {
1143 uint32_t flags = use_distance_field_text
1144 ? SkSurfaceProps::kUseDistanceFieldFonts_Flag
1145 : 0;
1146 // Use unknown pixel geometry to disable LCD text.
1147 SkSurfaceProps surface_props(flags, kUnknown_SkPixelGeometry);
1148 if (can_use_lcd_text) {
1149 // LegacyFontHost will get LCD text and skia figures out what type to use.
1150 surface_props =
1151 SkSurfaceProps(flags, SkSurfaceProps::kLegacyFontHost_InitType);
1153 sk_surface_ = skia::AdoptRef(SkSurface::NewRenderTargetDirect(
1154 gr_texture->asRenderTarget(), &surface_props));
1155 return;
1157 sk_surface_.clear();
1160 void ResourceProvider::ScopedWriteLockGr::ReleaseSkSurface() {
1161 sk_surface_.clear();
1164 ResourceProvider::SynchronousFence::SynchronousFence(
1165 gpu::gles2::GLES2Interface* gl)
1166 : gl_(gl), has_synchronized_(true) {
1169 ResourceProvider::SynchronousFence::~SynchronousFence() {
1172 void ResourceProvider::SynchronousFence::Set() {
1173 has_synchronized_ = false;
1176 bool ResourceProvider::SynchronousFence::HasPassed() {
1177 if (!has_synchronized_) {
1178 has_synchronized_ = true;
1179 Synchronize();
1181 return true;
1184 void ResourceProvider::SynchronousFence::Wait() {
1185 HasPassed();
1188 void ResourceProvider::SynchronousFence::Synchronize() {
1189 TRACE_EVENT0("cc", "ResourceProvider::SynchronousFence::Synchronize");
1190 gl_->Finish();
1193 ResourceProvider::ResourceProvider(
1194 OutputSurface* output_surface,
1195 SharedBitmapManager* shared_bitmap_manager,
1196 gpu::GpuMemoryBufferManager* gpu_memory_buffer_manager,
1197 BlockingTaskRunner* blocking_main_thread_task_runner,
1198 int highp_threshold_min,
1199 ResourceType default_resource_type,
1200 bool use_rgba_4444_texture_format,
1201 size_t id_allocation_chunk_size)
1202 : output_surface_(output_surface),
1203 shared_bitmap_manager_(shared_bitmap_manager),
1204 gpu_memory_buffer_manager_(gpu_memory_buffer_manager),
1205 blocking_main_thread_task_runner_(blocking_main_thread_task_runner),
1206 lost_output_surface_(false),
1207 highp_threshold_min_(highp_threshold_min),
1208 next_id_(1),
1209 next_child_(1),
1210 default_resource_type_(default_resource_type),
1211 use_texture_storage_ext_(false),
1212 use_texture_format_bgra_(false),
1213 use_texture_usage_hint_(false),
1214 use_compressed_texture_etc1_(false),
1215 yuv_resource_format_(LUMINANCE_8),
1216 max_texture_size_(0),
1217 best_texture_format_(RGBA_8888),
1218 use_rgba_4444_texture_format_(use_rgba_4444_texture_format),
1219 id_allocation_chunk_size_(id_allocation_chunk_size),
1220 use_sync_query_(false) {
1221 DCHECK(output_surface_->HasClient());
1222 DCHECK(id_allocation_chunk_size_);
1225 void ResourceProvider::InitializeSoftware() {
1226 DCHECK(thread_checker_.CalledOnValidThread());
1227 DCHECK_EQ(default_resource_type_, RESOURCE_TYPE_BITMAP);
1228 // Pick an arbitrary limit here similar to what hardware might.
1229 max_texture_size_ = 16 * 1024;
1230 best_texture_format_ = RGBA_8888;
1233 void ResourceProvider::InitializeGL() {
1234 DCHECK(thread_checker_.CalledOnValidThread());
1235 DCHECK_EQ(default_resource_type_, RESOURCE_TYPE_GL_TEXTURE);
1236 DCHECK(!texture_uploader_);
1237 DCHECK(!texture_id_allocator_);
1238 DCHECK(!buffer_id_allocator_);
1240 const ContextProvider::Capabilities& caps =
1241 output_surface_->context_provider()->ContextCapabilities();
1243 bool use_bgra = caps.gpu.texture_format_bgra8888;
1244 use_texture_storage_ext_ = caps.gpu.texture_storage;
1245 use_texture_format_bgra_ = caps.gpu.texture_format_bgra8888;
1246 use_texture_usage_hint_ = caps.gpu.texture_usage;
1247 use_compressed_texture_etc1_ = caps.gpu.texture_format_etc1;
1248 yuv_resource_format_ = caps.gpu.texture_rg ? RED_8 : LUMINANCE_8;
1249 use_sync_query_ = caps.gpu.sync_query;
1251 GLES2Interface* gl = ContextGL();
1252 DCHECK(gl);
1254 texture_uploader_ = TextureUploader::Create(gl);
1255 max_texture_size_ = 0; // Context expects cleared value.
1256 gl->GetIntegerv(GL_MAX_TEXTURE_SIZE, &max_texture_size_);
1257 best_texture_format_ = PlatformColor::BestTextureFormat(use_bgra);
1259 texture_id_allocator_.reset(
1260 new TextureIdAllocator(gl, id_allocation_chunk_size_));
1261 buffer_id_allocator_.reset(
1262 new BufferIdAllocator(gl, id_allocation_chunk_size_));
1265 int ResourceProvider::CreateChild(const ReturnCallback& return_callback) {
1266 DCHECK(thread_checker_.CalledOnValidThread());
1268 Child child_info;
1269 child_info.return_callback = return_callback;
1271 int child = next_child_++;
1272 children_[child] = child_info;
1273 return child;
1276 void ResourceProvider::SetChildNeedsSyncPoints(int child_id, bool needs) {
1277 ChildMap::iterator it = children_.find(child_id);
1278 DCHECK(it != children_.end());
1279 it->second.needs_sync_points = needs;
1282 void ResourceProvider::DestroyChild(int child_id) {
1283 ChildMap::iterator it = children_.find(child_id);
1284 DCHECK(it != children_.end());
1285 DestroyChildInternal(it, NORMAL);
1288 void ResourceProvider::DestroyChildInternal(ChildMap::iterator it,
1289 DeleteStyle style) {
1290 DCHECK(thread_checker_.CalledOnValidThread());
1292 Child& child = it->second;
1293 DCHECK(style == FOR_SHUTDOWN || !child.marked_for_deletion);
1295 ResourceIdArray resources_for_child;
1297 for (ResourceIdMap::iterator child_it = child.child_to_parent_map.begin();
1298 child_it != child.child_to_parent_map.end();
1299 ++child_it) {
1300 ResourceId id = child_it->second;
1301 resources_for_child.push_back(id);
1304 child.marked_for_deletion = true;
1306 DeleteAndReturnUnusedResourcesToChild(it, style, resources_for_child);
1309 const ResourceProvider::ResourceIdMap& ResourceProvider::GetChildToParentMap(
1310 int child) const {
1311 DCHECK(thread_checker_.CalledOnValidThread());
1312 ChildMap::const_iterator it = children_.find(child);
1313 DCHECK(it != children_.end());
1314 DCHECK(!it->second.marked_for_deletion);
1315 return it->second.child_to_parent_map;
1318 void ResourceProvider::PrepareSendToParent(const ResourceIdArray& resources,
1319 TransferableResourceArray* list) {
1320 DCHECK(thread_checker_.CalledOnValidThread());
1321 GLES2Interface* gl = ContextGL();
1322 bool need_sync_point = false;
1323 for (ResourceIdArray::const_iterator it = resources.begin();
1324 it != resources.end();
1325 ++it) {
1326 TransferableResource resource;
1327 TransferResource(gl, *it, &resource);
1328 if (!resource.mailbox_holder.sync_point && !resource.is_software)
1329 need_sync_point = true;
1330 ++resources_.find(*it)->second.exported_count;
1331 list->push_back(resource);
1333 if (need_sync_point &&
1334 output_surface_->capabilities().delegated_sync_points_required) {
1335 GLuint sync_point = gl->InsertSyncPointCHROMIUM();
1336 for (TransferableResourceArray::iterator it = list->begin();
1337 it != list->end();
1338 ++it) {
1339 if (!it->mailbox_holder.sync_point)
1340 it->mailbox_holder.sync_point = sync_point;
1345 void ResourceProvider::ReceiveFromChild(
1346 int child, const TransferableResourceArray& resources) {
1347 DCHECK(thread_checker_.CalledOnValidThread());
1348 GLES2Interface* gl = ContextGL();
1349 Child& child_info = children_.find(child)->second;
1350 DCHECK(!child_info.marked_for_deletion);
1351 for (TransferableResourceArray::const_iterator it = resources.begin();
1352 it != resources.end();
1353 ++it) {
1354 ResourceIdMap::iterator resource_in_map_it =
1355 child_info.child_to_parent_map.find(it->id);
1356 if (resource_in_map_it != child_info.child_to_parent_map.end()) {
1357 Resource* resource = GetResource(resource_in_map_it->second);
1358 resource->marked_for_deletion = false;
1359 resource->imported_count++;
1360 continue;
1363 if ((!it->is_software && !gl) ||
1364 (it->is_software && !shared_bitmap_manager_)) {
1365 TRACE_EVENT0("cc", "ResourceProvider::ReceiveFromChild dropping invalid");
1366 ReturnedResourceArray to_return;
1367 to_return.push_back(it->ToReturnedResource());
1368 child_info.return_callback.Run(to_return,
1369 blocking_main_thread_task_runner_);
1370 continue;
1373 ResourceId local_id = next_id_++;
1374 Resource* resource = nullptr;
1375 if (it->is_software) {
1376 resource = InsertResource(
1377 local_id,
1378 Resource(it->mailbox_holder.mailbox, it->size, Resource::DELEGATED,
1379 GL_LINEAR, it->is_repeated ? GL_REPEAT : GL_CLAMP_TO_EDGE));
1380 } else {
1381 resource = InsertResource(
1382 local_id, Resource(0, it->size, Resource::DELEGATED,
1383 it->mailbox_holder.texture_target, it->filter, 0,
1384 it->is_repeated ? GL_REPEAT : GL_CLAMP_TO_EDGE,
1385 TEXTURE_HINT_IMMUTABLE, it->format));
1386 resource->mailbox = TextureMailbox(it->mailbox_holder.mailbox,
1387 it->mailbox_holder.texture_target,
1388 it->mailbox_holder.sync_point);
1390 resource->child_id = child;
1391 // Don't allocate a texture for a child.
1392 resource->allocated = true;
1393 resource->imported_count = 1;
1394 resource->allow_overlay = it->allow_overlay;
1395 child_info.parent_to_child_map[local_id] = it->id;
1396 child_info.child_to_parent_map[it->id] = local_id;
1400 void ResourceProvider::DeclareUsedResourcesFromChild(
1401 int child,
1402 const ResourceIdSet& resources_from_child) {
1403 DCHECK(thread_checker_.CalledOnValidThread());
1405 ChildMap::iterator child_it = children_.find(child);
1406 DCHECK(child_it != children_.end());
1407 Child& child_info = child_it->second;
1408 DCHECK(!child_info.marked_for_deletion);
1410 ResourceIdArray unused;
1411 for (ResourceIdMap::iterator it = child_info.child_to_parent_map.begin();
1412 it != child_info.child_to_parent_map.end();
1413 ++it) {
1414 ResourceId local_id = it->second;
1415 bool resource_is_in_use = resources_from_child.count(it->first) > 0;
1416 if (!resource_is_in_use)
1417 unused.push_back(local_id);
1419 DeleteAndReturnUnusedResourcesToChild(child_it, NORMAL, unused);
1422 void ResourceProvider::ReceiveReturnsFromParent(
1423 const ReturnedResourceArray& resources) {
1424 DCHECK(thread_checker_.CalledOnValidThread());
1425 GLES2Interface* gl = ContextGL();
1427 base::hash_map<int, ResourceIdArray> resources_for_child;
1429 for (const ReturnedResource& returned : resources) {
1430 ResourceId local_id = returned.id;
1431 ResourceMap::iterator map_iterator = resources_.find(local_id);
1432 // Resource was already lost (e.g. it belonged to a child that was
1433 // destroyed).
1434 if (map_iterator == resources_.end())
1435 continue;
1437 Resource* resource = &map_iterator->second;
1439 CHECK_GE(resource->exported_count, returned.count);
1440 resource->exported_count -= returned.count;
1441 resource->lost |= returned.lost;
1442 if (resource->exported_count)
1443 continue;
1445 // Need to wait for the current read lock fence to pass before we can
1446 // recycle this resource.
1447 if (resource->read_lock_fences_enabled) {
1448 if (current_read_lock_fence_.get())
1449 current_read_lock_fence_->Set();
1450 resource->read_lock_fence = current_read_lock_fence_;
1453 if (returned.sync_point) {
1454 DCHECK(!resource->has_shared_bitmap_id);
1455 if (resource->origin == Resource::INTERNAL) {
1456 DCHECK(resource->gl_id);
1457 gl->WaitSyncPointCHROMIUM(returned.sync_point);
1458 } else {
1459 DCHECK(!resource->gl_id);
1460 resource->mailbox.set_sync_point(returned.sync_point);
1464 if (!resource->marked_for_deletion)
1465 continue;
1467 if (!resource->child_id) {
1468 // The resource belongs to this ResourceProvider, so it can be destroyed.
1469 DeleteResourceInternal(map_iterator, NORMAL);
1470 continue;
1473 DCHECK(resource->origin == Resource::DELEGATED);
1474 resources_for_child[resource->child_id].push_back(local_id);
1477 for (const auto& children : resources_for_child) {
1478 ChildMap::iterator child_it = children_.find(children.first);
1479 DCHECK(child_it != children_.end());
1480 DeleteAndReturnUnusedResourcesToChild(child_it, NORMAL, children.second);
1484 void ResourceProvider::TransferResource(GLES2Interface* gl,
1485 ResourceId id,
1486 TransferableResource* resource) {
1487 Resource* source = GetResource(id);
1488 DCHECK(!source->locked_for_write);
1489 DCHECK(!source->lock_for_read_count);
1490 DCHECK(source->origin != Resource::EXTERNAL || source->mailbox.IsValid());
1491 DCHECK(source->allocated);
1492 resource->id = id;
1493 resource->format = source->format;
1494 resource->mailbox_holder.texture_target = source->target;
1495 resource->filter = source->filter;
1496 resource->size = source->size;
1497 resource->is_repeated = (source->wrap_mode == GL_REPEAT);
1498 resource->allow_overlay = source->allow_overlay;
1500 if (source->type == RESOURCE_TYPE_BITMAP) {
1501 resource->mailbox_holder.mailbox = source->shared_bitmap_id;
1502 resource->is_software = true;
1503 } else if (!source->mailbox.IsValid()) {
1504 LazyCreate(source);
1505 DCHECK(source->gl_id);
1506 DCHECK(source->origin == Resource::INTERNAL);
1507 if (source->image_id) {
1508 DCHECK(source->dirty_image);
1509 BindImageForSampling(source);
1511 // This is a resource allocated by the compositor, we need to produce it.
1512 // Don't set a sync point, the caller will do it.
1513 gl->GenMailboxCHROMIUM(resource->mailbox_holder.mailbox.name);
1514 gl->ProduceTextureDirectCHROMIUM(source->gl_id,
1515 resource->mailbox_holder.texture_target,
1516 resource->mailbox_holder.mailbox.name);
1518 source->mailbox = TextureMailbox(resource->mailbox_holder);
1519 } else {
1520 DCHECK(source->mailbox.IsTexture());
1521 if (source->image_id && source->dirty_image) {
1522 DCHECK(source->gl_id);
1523 DCHECK(source->origin == Resource::INTERNAL);
1524 gl->BindTexture(resource->mailbox_holder.texture_target, source->gl_id);
1525 BindImageForSampling(source);
1527 // This is either an external resource, or a compositor resource that we
1528 // already exported. Make sure to forward the sync point that we were given.
1529 resource->mailbox_holder.mailbox = source->mailbox.mailbox();
1530 resource->mailbox_holder.texture_target = source->mailbox.target();
1531 resource->mailbox_holder.sync_point = source->mailbox.sync_point();
1532 source->mailbox.set_sync_point(0);
1536 void ResourceProvider::DeleteAndReturnUnusedResourcesToChild(
1537 ChildMap::iterator child_it,
1538 DeleteStyle style,
1539 const ResourceIdArray& unused) {
1540 DCHECK(thread_checker_.CalledOnValidThread());
1541 DCHECK(child_it != children_.end());
1542 Child* child_info = &child_it->second;
1544 if (unused.empty() && !child_info->marked_for_deletion)
1545 return;
1547 ReturnedResourceArray to_return;
1549 GLES2Interface* gl = ContextGL();
1550 bool need_sync_point = false;
1551 for (size_t i = 0; i < unused.size(); ++i) {
1552 ResourceId local_id = unused[i];
1554 ResourceMap::iterator it = resources_.find(local_id);
1555 CHECK(it != resources_.end());
1556 Resource& resource = it->second;
1558 DCHECK(!resource.locked_for_write);
1559 DCHECK(child_info->parent_to_child_map.count(local_id));
1561 ResourceId child_id = child_info->parent_to_child_map[local_id];
1562 DCHECK(child_info->child_to_parent_map.count(child_id));
1564 bool is_lost =
1565 resource.lost ||
1566 (resource.type == RESOURCE_TYPE_GL_TEXTURE && lost_output_surface_);
1567 if (resource.exported_count > 0 || resource.lock_for_read_count > 0) {
1568 if (style != FOR_SHUTDOWN) {
1569 // Defer this until we receive the resource back from the parent or
1570 // the read lock is released.
1571 resource.marked_for_deletion = true;
1572 continue;
1575 // We still have an exported_count, so we'll have to lose it.
1576 is_lost = true;
1579 if (gl && resource.filter != resource.original_filter) {
1580 DCHECK(resource.target);
1581 DCHECK(resource.gl_id);
1583 gl->BindTexture(resource.target, resource.gl_id);
1584 gl->TexParameteri(resource.target, GL_TEXTURE_MIN_FILTER,
1585 resource.original_filter);
1586 gl->TexParameteri(resource.target, GL_TEXTURE_MAG_FILTER,
1587 resource.original_filter);
1590 ReturnedResource returned;
1591 returned.id = child_id;
1592 returned.sync_point = resource.mailbox.sync_point();
1593 if (!returned.sync_point && resource.type == RESOURCE_TYPE_GL_TEXTURE)
1594 need_sync_point = true;
1595 returned.count = resource.imported_count;
1596 returned.lost = is_lost;
1597 to_return.push_back(returned);
1599 child_info->parent_to_child_map.erase(local_id);
1600 child_info->child_to_parent_map.erase(child_id);
1601 resource.imported_count = 0;
1602 DeleteResourceInternal(it, style);
1604 if (need_sync_point && child_info->needs_sync_points) {
1605 DCHECK(gl);
1606 GLuint sync_point = gl->InsertSyncPointCHROMIUM();
1607 for (size_t i = 0; i < to_return.size(); ++i) {
1608 if (!to_return[i].sync_point)
1609 to_return[i].sync_point = sync_point;
1613 if (!to_return.empty())
1614 child_info->return_callback.Run(to_return,
1615 blocking_main_thread_task_runner_);
1617 if (child_info->marked_for_deletion &&
1618 child_info->parent_to_child_map.empty()) {
1619 DCHECK(child_info->child_to_parent_map.empty());
1620 children_.erase(child_it);
1624 void ResourceProvider::AcquirePixelBuffer(ResourceId id) {
1625 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug"),
1626 "ResourceProvider::AcquirePixelBuffer");
1628 Resource* resource = GetResource(id);
1629 DCHECK(resource->origin == Resource::INTERNAL);
1630 DCHECK_EQ(resource->exported_count, 0);
1631 DCHECK(!resource->image_id);
1632 DCHECK_NE(ETC1, resource->format);
1634 DCHECK_EQ(RESOURCE_TYPE_GL_TEXTURE, resource->type);
1635 GLES2Interface* gl = ContextGL();
1636 DCHECK(gl);
1637 if (!resource->gl_pixel_buffer_id)
1638 resource->gl_pixel_buffer_id = buffer_id_allocator_->NextId();
1639 gl->BindBuffer(GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM,
1640 resource->gl_pixel_buffer_id);
1641 unsigned bytes_per_pixel = BitsPerPixel(resource->format) / 8;
1642 gl->BufferData(GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM,
1643 resource->size.height() *
1644 RoundUp(bytes_per_pixel * resource->size.width(), 4u),
1645 NULL,
1646 GL_DYNAMIC_DRAW);
1647 gl->BindBuffer(GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM, 0);
1650 void ResourceProvider::ReleasePixelBuffer(ResourceId id) {
1651 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug"),
1652 "ResourceProvider::ReleasePixelBuffer");
1654 Resource* resource = GetResource(id);
1655 DCHECK(resource->origin == Resource::INTERNAL);
1656 DCHECK_EQ(resource->exported_count, 0);
1657 DCHECK(!resource->image_id);
1659 // The pixel buffer can be released while there is a pending "set pixels"
1660 // if completion has been forced. Any shared memory associated with this
1661 // pixel buffer will not be freed until the waitAsyncTexImage2DCHROMIUM
1662 // command has been processed on the service side. It is also safe to
1663 // reuse any query id associated with this resource before they complete
1664 // as each new query has a unique submit count.
1665 if (resource->pending_set_pixels) {
1666 DCHECK(resource->set_pixels_completion_forced);
1667 resource->pending_set_pixels = false;
1668 resource->locked_for_write = false;
1671 DCHECK_EQ(RESOURCE_TYPE_GL_TEXTURE, resource->type);
1672 if (!resource->gl_pixel_buffer_id)
1673 return;
1674 GLES2Interface* gl = ContextGL();
1675 DCHECK(gl);
1676 gl->BindBuffer(GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM,
1677 resource->gl_pixel_buffer_id);
1678 gl->BufferData(
1679 GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM, 0, NULL, GL_DYNAMIC_DRAW);
1680 gl->BindBuffer(GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM, 0);
1683 uint8_t* ResourceProvider::MapPixelBuffer(ResourceId id, int* stride) {
1684 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug"),
1685 "ResourceProvider::MapPixelBuffer");
1687 Resource* resource = GetResource(id);
1688 DCHECK(resource->origin == Resource::INTERNAL);
1689 DCHECK_EQ(resource->exported_count, 0);
1690 DCHECK(!resource->image_id);
1692 *stride = 0;
1693 DCHECK_EQ(RESOURCE_TYPE_GL_TEXTURE, resource->type);
1694 GLES2Interface* gl = ContextGL();
1695 DCHECK(gl);
1696 DCHECK(resource->gl_pixel_buffer_id);
1697 gl->BindBuffer(GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM,
1698 resource->gl_pixel_buffer_id);
1699 uint8_t* image = static_cast<uint8_t*>(gl->MapBufferCHROMIUM(
1700 GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM, GL_WRITE_ONLY));
1701 gl->BindBuffer(GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM, 0);
1702 // Buffer is required to be 4-byte aligned.
1703 CHECK(!(reinterpret_cast<intptr_t>(image) & 3));
1704 return image;
1707 void ResourceProvider::UnmapPixelBuffer(ResourceId id) {
1708 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug"),
1709 "ResourceProvider::UnmapPixelBuffer");
1711 Resource* resource = GetResource(id);
1712 DCHECK(resource->origin == Resource::INTERNAL);
1713 DCHECK_EQ(resource->exported_count, 0);
1714 DCHECK(!resource->image_id);
1716 DCHECK_EQ(RESOURCE_TYPE_GL_TEXTURE, resource->type);
1717 GLES2Interface* gl = ContextGL();
1718 DCHECK(gl);
1719 DCHECK(resource->gl_pixel_buffer_id);
1720 gl->BindBuffer(GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM,
1721 resource->gl_pixel_buffer_id);
1722 gl->UnmapBufferCHROMIUM(GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM);
1723 gl->BindBuffer(GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM, 0);
1726 GLenum ResourceProvider::BindForSampling(ResourceId resource_id,
1727 GLenum unit,
1728 GLenum filter) {
1729 DCHECK(thread_checker_.CalledOnValidThread());
1730 GLES2Interface* gl = ContextGL();
1731 ResourceMap::iterator it = resources_.find(resource_id);
1732 DCHECK(it != resources_.end());
1733 Resource* resource = &it->second;
1734 DCHECK(resource->lock_for_read_count);
1735 DCHECK(!resource->locked_for_write || resource->set_pixels_completion_forced);
1737 ScopedSetActiveTexture scoped_active_tex(gl, unit);
1738 GLenum target = resource->target;
1739 gl->BindTexture(target, resource->gl_id);
1740 if (filter != resource->filter) {
1741 gl->TexParameteri(target, GL_TEXTURE_MIN_FILTER, filter);
1742 gl->TexParameteri(target, GL_TEXTURE_MAG_FILTER, filter);
1743 resource->filter = filter;
1746 if (resource->image_id && resource->dirty_image)
1747 BindImageForSampling(resource);
1749 return target;
1752 void ResourceProvider::BeginSetPixels(ResourceId id) {
1753 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug"),
1754 "ResourceProvider::BeginSetPixels");
1756 Resource* resource = GetResource(id);
1757 DCHECK(!resource->pending_set_pixels);
1759 LazyCreate(resource);
1760 DCHECK(resource->origin == Resource::INTERNAL);
1761 DCHECK(resource->gl_id || resource->allocated);
1762 DCHECK(ReadLockFenceHasPassed(resource));
1763 DCHECK(!resource->image_id);
1765 bool allocate = !resource->allocated;
1766 resource->allocated = true;
1767 LockForWrite(id);
1769 DCHECK_EQ(RESOURCE_TYPE_GL_TEXTURE, resource->type);
1770 DCHECK(resource->gl_id);
1771 GLES2Interface* gl = ContextGL();
1772 DCHECK(gl);
1773 DCHECK(resource->gl_pixel_buffer_id);
1774 DCHECK_EQ(resource->target, static_cast<GLenum>(GL_TEXTURE_2D));
1775 gl->BindTexture(GL_TEXTURE_2D, resource->gl_id);
1776 gl->BindBuffer(GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM,
1777 resource->gl_pixel_buffer_id);
1778 if (!resource->gl_upload_query_id)
1779 gl->GenQueriesEXT(1, &resource->gl_upload_query_id);
1780 gl->BeginQueryEXT(GL_ASYNC_PIXEL_UNPACK_COMPLETED_CHROMIUM,
1781 resource->gl_upload_query_id);
1782 if (allocate) {
1783 gl->AsyncTexImage2DCHROMIUM(GL_TEXTURE_2D,
1784 0, /* level */
1785 GLInternalFormat(resource->format),
1786 resource->size.width(),
1787 resource->size.height(),
1788 0, /* border */
1789 GLDataFormat(resource->format),
1790 GLDataType(resource->format),
1791 NULL);
1792 } else {
1793 gl->AsyncTexSubImage2DCHROMIUM(GL_TEXTURE_2D,
1794 0, /* level */
1795 0, /* x */
1796 0, /* y */
1797 resource->size.width(),
1798 resource->size.height(),
1799 GLDataFormat(resource->format),
1800 GLDataType(resource->format),
1801 NULL);
1803 gl->EndQueryEXT(GL_ASYNC_PIXEL_UNPACK_COMPLETED_CHROMIUM);
1804 gl->BindBuffer(GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM, 0);
1806 resource->pending_set_pixels = true;
1807 resource->set_pixels_completion_forced = false;
1810 void ResourceProvider::ForceSetPixelsToComplete(ResourceId id) {
1811 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug"),
1812 "ResourceProvider::ForceSetPixelsToComplete");
1814 Resource* resource = GetResource(id);
1816 DCHECK(resource->locked_for_write);
1817 DCHECK(resource->pending_set_pixels);
1818 DCHECK(!resource->set_pixels_completion_forced);
1820 if (resource->gl_id) {
1821 GLES2Interface* gl = ContextGL();
1822 gl->BindTexture(GL_TEXTURE_2D, resource->gl_id);
1823 gl->WaitAsyncTexImage2DCHROMIUM(GL_TEXTURE_2D);
1824 gl->BindTexture(GL_TEXTURE_2D, 0);
1827 resource->set_pixels_completion_forced = true;
1830 bool ResourceProvider::DidSetPixelsComplete(ResourceId id) {
1831 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug"),
1832 "ResourceProvider::DidSetPixelsComplete");
1834 Resource* resource = GetResource(id);
1836 DCHECK(resource->locked_for_write);
1837 DCHECK(resource->pending_set_pixels);
1839 if (resource->gl_id) {
1840 GLES2Interface* gl = ContextGL();
1841 DCHECK(gl);
1842 DCHECK(resource->gl_upload_query_id);
1843 GLuint complete = 1;
1844 gl->GetQueryObjectuivEXT(
1845 resource->gl_upload_query_id, GL_QUERY_RESULT_AVAILABLE_EXT, &complete);
1846 if (!complete)
1847 return false;
1850 resource->pending_set_pixels = false;
1851 UnlockForWrite(resource);
1853 // Async set pixels commands are not necessarily processed in-sequence with
1854 // drawing commands. Read lock fences are required to ensure that async
1855 // commands don't access the resource while used for drawing.
1856 resource->read_lock_fences_enabled = true;
1858 return true;
1861 void ResourceProvider::CreateForTesting(ResourceId id) {
1862 LazyCreate(GetResource(id));
1865 GLenum ResourceProvider::TargetForTesting(ResourceId id) {
1866 Resource* resource = GetResource(id);
1867 return resource->target;
1870 void ResourceProvider::LazyCreate(Resource* resource) {
1871 if (resource->type != RESOURCE_TYPE_GL_TEXTURE ||
1872 resource->origin != Resource::INTERNAL)
1873 return;
1875 if (resource->gl_id)
1876 return;
1878 DCHECK(resource->texture_pool);
1879 DCHECK(resource->origin == Resource::INTERNAL);
1880 DCHECK(!resource->mailbox.IsValid());
1881 resource->gl_id = texture_id_allocator_->NextId();
1883 GLES2Interface* gl = ContextGL();
1884 DCHECK(gl);
1886 // Create and set texture properties. Allocation is delayed until needed.
1887 gl->BindTexture(resource->target, resource->gl_id);
1888 gl->TexParameteri(resource->target, GL_TEXTURE_MIN_FILTER,
1889 resource->original_filter);
1890 gl->TexParameteri(resource->target, GL_TEXTURE_MAG_FILTER,
1891 resource->original_filter);
1892 gl->TexParameteri(resource->target, GL_TEXTURE_WRAP_S, resource->wrap_mode);
1893 gl->TexParameteri(resource->target, GL_TEXTURE_WRAP_T, resource->wrap_mode);
1894 gl->TexParameteri(resource->target, GL_TEXTURE_POOL_CHROMIUM,
1895 resource->texture_pool);
1896 if (use_texture_usage_hint_ && (resource->hint & TEXTURE_HINT_FRAMEBUFFER)) {
1897 gl->TexParameteri(resource->target, GL_TEXTURE_USAGE_ANGLE,
1898 GL_FRAMEBUFFER_ATTACHMENT_ANGLE);
1902 void ResourceProvider::AllocateForTesting(ResourceId id) {
1903 LazyAllocate(GetResource(id));
1906 void ResourceProvider::LazyAllocate(Resource* resource) {
1907 DCHECK(resource);
1908 if (resource->allocated)
1909 return;
1910 LazyCreate(resource);
1911 if (!resource->gl_id)
1912 return;
1913 resource->allocated = true;
1914 GLES2Interface* gl = ContextGL();
1915 gfx::Size& size = resource->size;
1916 DCHECK_EQ(resource->target, static_cast<GLenum>(GL_TEXTURE_2D));
1917 ResourceFormat format = resource->format;
1918 gl->BindTexture(GL_TEXTURE_2D, resource->gl_id);
1919 if (use_texture_storage_ext_ &&
1920 IsFormatSupportedForStorage(format, use_texture_format_bgra_) &&
1921 (resource->hint & TEXTURE_HINT_IMMUTABLE)) {
1922 GLenum storage_format = TextureToStorageFormat(format);
1923 gl->TexStorage2DEXT(GL_TEXTURE_2D, 1, storage_format, size.width(),
1924 size.height());
1925 } else {
1926 // ETC1 does not support preallocation.
1927 if (format != ETC1) {
1928 gl->TexImage2D(GL_TEXTURE_2D, 0, GLInternalFormat(format), size.width(),
1929 size.height(), 0, GLDataFormat(format), GLDataType(format),
1930 NULL);
1935 void ResourceProvider::BindImageForSampling(Resource* resource) {
1936 GLES2Interface* gl = ContextGL();
1937 DCHECK(resource->gl_id);
1938 DCHECK(resource->image_id);
1940 // Release image currently bound to texture.
1941 if (resource->bound_image_id)
1942 gl->ReleaseTexImage2DCHROMIUM(resource->target, resource->bound_image_id);
1943 gl->BindTexImage2DCHROMIUM(resource->target, resource->image_id);
1944 resource->bound_image_id = resource->image_id;
1945 resource->dirty_image = false;
1948 void ResourceProvider::CopyResource(ResourceId source_id, ResourceId dest_id) {
1949 TRACE_EVENT0("cc", "ResourceProvider::CopyResource");
1951 Resource* source_resource = GetResource(source_id);
1952 DCHECK(!source_resource->lock_for_read_count);
1953 DCHECK(source_resource->origin == Resource::INTERNAL);
1954 DCHECK_EQ(source_resource->exported_count, 0);
1955 DCHECK_EQ(RESOURCE_TYPE_GL_TEXTURE, source_resource->type);
1956 DCHECK(source_resource->allocated);
1957 LazyCreate(source_resource);
1959 Resource* dest_resource = GetResource(dest_id);
1960 DCHECK(!dest_resource->locked_for_write);
1961 DCHECK(!dest_resource->lock_for_read_count);
1962 DCHECK(dest_resource->origin == Resource::INTERNAL);
1963 DCHECK_EQ(dest_resource->exported_count, 0);
1964 DCHECK_EQ(RESOURCE_TYPE_GL_TEXTURE, dest_resource->type);
1965 LazyAllocate(dest_resource);
1967 DCHECK_EQ(source_resource->type, dest_resource->type);
1968 DCHECK_EQ(source_resource->format, dest_resource->format);
1969 DCHECK(source_resource->size == dest_resource->size);
1971 GLES2Interface* gl = ContextGL();
1972 DCHECK(gl);
1973 if (source_resource->image_id && source_resource->dirty_image) {
1974 gl->BindTexture(source_resource->target, source_resource->gl_id);
1975 BindImageForSampling(source_resource);
1977 if (use_sync_query_) {
1978 if (!source_resource->gl_read_lock_query_id)
1979 gl->GenQueriesEXT(1, &source_resource->gl_read_lock_query_id);
1980 #if defined(OS_CHROMEOS)
1981 // TODO(reveman): This avoids a performance problem on some ChromeOS
1982 // devices. This needs to be removed to support native GpuMemoryBuffer
1983 // implementations. crbug.com/436314
1984 gl->BeginQueryEXT(GL_COMMANDS_ISSUED_CHROMIUM,
1985 source_resource->gl_read_lock_query_id);
1986 #else
1987 gl->BeginQueryEXT(GL_COMMANDS_COMPLETED_CHROMIUM,
1988 source_resource->gl_read_lock_query_id);
1989 #endif
1991 DCHECK(!dest_resource->image_id);
1992 dest_resource->allocated = true;
1993 gl->CopySubTextureCHROMIUM(dest_resource->target, source_resource->gl_id,
1994 dest_resource->gl_id, 0, 0);
1995 if (source_resource->gl_read_lock_query_id) {
1996 // End query and create a read lock fence that will prevent access to
1997 // source resource until CopySubTextureCHROMIUM command has completed.
1998 #if defined(OS_CHROMEOS)
1999 gl->EndQueryEXT(GL_COMMANDS_ISSUED_CHROMIUM);
2000 #else
2001 gl->EndQueryEXT(GL_COMMANDS_COMPLETED_CHROMIUM);
2002 #endif
2003 source_resource->read_lock_fence = make_scoped_refptr(
2004 new CopyTextureFence(gl, source_resource->gl_read_lock_query_id));
2005 } else {
2006 // Create a SynchronousFence when CHROMIUM_sync_query extension is missing.
2007 // Try to use one synchronous fence for as many CopyResource operations as
2008 // possible as that reduce the number of times we have to synchronize with
2009 // the GL.
2010 if (!synchronous_fence_.get() || synchronous_fence_->has_synchronized())
2011 synchronous_fence_ = make_scoped_refptr(new SynchronousFence(gl));
2012 source_resource->read_lock_fence = synchronous_fence_;
2013 source_resource->read_lock_fence->Set();
2017 void ResourceProvider::WaitSyncPointIfNeeded(ResourceId id) {
2018 Resource* resource = GetResource(id);
2019 DCHECK_EQ(resource->exported_count, 0);
2020 DCHECK(resource->allocated);
2021 if (resource->type != RESOURCE_TYPE_GL_TEXTURE || resource->gl_id)
2022 return;
2023 if (!resource->mailbox.sync_point())
2024 return;
2025 DCHECK(resource->mailbox.IsValid());
2026 GLES2Interface* gl = ContextGL();
2027 DCHECK(gl);
2028 gl->WaitSyncPointCHROMIUM(resource->mailbox.sync_point());
2029 resource->mailbox.set_sync_point(0);
2032 void ResourceProvider::WaitReadLockIfNeeded(ResourceId id) {
2033 Resource* resource = GetResource(id);
2034 DCHECK_EQ(resource->exported_count, 0);
2035 if (!resource->read_lock_fence.get())
2036 return;
2038 resource->read_lock_fence->Wait();
2041 GLint ResourceProvider::GetActiveTextureUnit(GLES2Interface* gl) {
2042 GLint active_unit = 0;
2043 gl->GetIntegerv(GL_ACTIVE_TEXTURE, &active_unit);
2044 return active_unit;
2047 void ResourceProvider::ValidateResource(ResourceId id) const {
2048 DCHECK(thread_checker_.CalledOnValidThread());
2049 DCHECK(id);
2050 DCHECK(resources_.find(id) != resources_.end());
2053 GLES2Interface* ResourceProvider::ContextGL() const {
2054 ContextProvider* context_provider = output_surface_->context_provider();
2055 return context_provider ? context_provider->ContextGL() : NULL;
2058 class GrContext* ResourceProvider::GrContext(bool worker_context) const {
2059 ContextProvider* context_provider =
2060 worker_context ? output_surface_->worker_context_provider()
2061 : output_surface_->context_provider();
2062 return context_provider ? context_provider->GrContext() : NULL;
2065 } // namespace cc