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