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