1 // Copyright 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "cc/resources/resource_provider.h"
10 #include "base/bind.h"
11 #include "base/containers/hash_tables.h"
12 #include "base/logging.h"
13 #include "base/memory/ref_counted.h"
14 #include "cc/base/scoped_ptr_deque.h"
15 #include "cc/output/output_surface.h"
16 #include "cc/resources/returned_resource.h"
17 #include "cc/resources/shared_bitmap_manager.h"
18 #include "cc/resources/single_release_callback.h"
19 #include "cc/test/fake_output_surface.h"
20 #include "cc/test/fake_output_surface_client.h"
21 #include "cc/test/test_texture.h"
22 #include "cc/test/test_web_graphics_context_3d.h"
23 #include "gpu/GLES2/gl2extchromium.h"
24 #include "testing/gmock/include/gmock/gmock.h"
25 #include "testing/gtest/include/gtest/gtest.h"
26 #include "third_party/khronos/GLES2/gl2.h"
27 #include "third_party/khronos/GLES2/gl2ext.h"
28 #include "ui/gfx/rect.h"
31 using testing::NiceMock;
32 using testing::Return;
33 using testing::SetArgPointee;
34 using testing::StrictMock;
40 static void EmptyReleaseCallback(unsigned sync_point, bool lost_resource) {}
42 static void SharedMemoryReleaseCallback(scoped_ptr<base::SharedMemory> memory,
44 bool lost_resource) {}
46 static void ReleaseTextureMailbox(unsigned* release_sync_point,
47 bool* release_lost_resource,
50 *release_sync_point = sync_point;
51 *release_lost_resource = lost_resource;
54 static void ReleaseSharedMemoryCallback(
55 scoped_ptr<base::SharedMemory> shared_memory,
57 unsigned* release_sync_point,
58 bool* lost_resource_result,
61 *release_called = true;
62 *release_sync_point = sync_point;
63 *lost_resource_result = lost_resource;
66 static scoped_ptr<base::SharedMemory> CreateAndFillSharedMemory(
69 scoped_ptr<base::SharedMemory> shared_memory(new base::SharedMemory);
70 CHECK(shared_memory->CreateAndMapAnonymous(4 * size.GetArea()));
71 uint32_t* pixels = reinterpret_cast<uint32_t*>(shared_memory->memory());
73 std::fill_n(pixels, size.GetArea(), value);
74 return shared_memory.Pass();
77 class TextureStateTrackingContext : public TestWebGraphicsContext3D {
79 MOCK_METHOD2(bindTexture, void(GLenum target, GLuint texture));
80 MOCK_METHOD3(texParameteri, void(GLenum target, GLenum pname, GLint param));
81 MOCK_METHOD1(waitSyncPoint, void(unsigned sync_point));
82 MOCK_METHOD0(insertSyncPoint, unsigned(void));
83 MOCK_METHOD2(produceTextureCHROMIUM,
84 void(GLenum target, const GLbyte* mailbox));
85 MOCK_METHOD2(consumeTextureCHROMIUM,
86 void(GLenum target, const GLbyte* mailbox));
88 // Force all textures to be consecutive numbers starting at "1",
89 // so we easily can test for them.
90 virtual GLuint NextTextureId() OVERRIDE {
91 base::AutoLock lock(namespace_->lock);
92 return namespace_->next_texture_id++;
94 virtual void RetireTextureId(GLuint) OVERRIDE {}
97 // Shared data between multiple ResourceProviderContext. This contains mailbox
98 // contents as well as information about sync points.
99 class ContextSharedData {
101 static scoped_ptr<ContextSharedData> Create() {
102 return make_scoped_ptr(new ContextSharedData());
105 unsigned InsertSyncPoint() { return next_sync_point_++; }
107 void GenMailbox(GLbyte* mailbox) {
108 memset(mailbox, 0, sizeof(GLbyte[64]));
109 memcpy(mailbox, &next_mailbox_, sizeof(next_mailbox_));
113 void ProduceTexture(const GLbyte* mailbox_name,
115 scoped_refptr<TestTexture> texture) {
116 unsigned mailbox = 0;
117 memcpy(&mailbox, mailbox_name, sizeof(mailbox));
118 ASSERT_TRUE(mailbox && mailbox < next_mailbox_);
119 textures_[mailbox] = texture;
120 ASSERT_LT(sync_point_for_mailbox_[mailbox], sync_point);
121 sync_point_for_mailbox_[mailbox] = sync_point;
124 scoped_refptr<TestTexture> ConsumeTexture(const GLbyte* mailbox_name,
125 unsigned sync_point) {
126 unsigned mailbox = 0;
127 memcpy(&mailbox, mailbox_name, sizeof(mailbox));
128 DCHECK(mailbox && mailbox < next_mailbox_);
130 // If the latest sync point the context has waited on is before the sync
131 // point for when the mailbox was set, pretend we never saw that
133 if (sync_point_for_mailbox_[mailbox] > sync_point) {
135 return scoped_refptr<TestTexture>();
137 return textures_[mailbox];
141 ContextSharedData() : next_sync_point_(1), next_mailbox_(1) {}
143 unsigned next_sync_point_;
144 unsigned next_mailbox_;
145 typedef base::hash_map<unsigned, scoped_refptr<TestTexture> > TextureMap;
146 TextureMap textures_;
147 base::hash_map<unsigned, unsigned> sync_point_for_mailbox_;
150 class ResourceProviderContext : public TestWebGraphicsContext3D {
152 static scoped_ptr<ResourceProviderContext> Create(
153 ContextSharedData* shared_data) {
154 return make_scoped_ptr(new ResourceProviderContext(shared_data));
157 virtual unsigned insertSyncPoint() OVERRIDE {
158 unsigned sync_point = shared_data_->InsertSyncPoint();
159 // Commit the produceTextureCHROMIUM calls at this point, so that
160 // they're associated with the sync point.
161 for (PendingProduceTextureList::iterator it =
162 pending_produce_textures_.begin();
163 it != pending_produce_textures_.end();
165 shared_data_->ProduceTexture(
166 (*it)->mailbox, sync_point, (*it)->texture);
168 pending_produce_textures_.clear();
172 virtual void waitSyncPoint(unsigned sync_point) OVERRIDE {
173 last_waited_sync_point_ = std::max(sync_point, last_waited_sync_point_);
176 unsigned last_waited_sync_point() const { return last_waited_sync_point_; }
178 virtual void texStorage2DEXT(GLenum target,
180 GLuint internalformat,
182 GLint height) OVERRIDE {
183 CheckTextureIsBound(target);
184 ASSERT_EQ(static_cast<unsigned>(GL_TEXTURE_2D), target);
185 ASSERT_EQ(1, levels);
186 GLenum format = GL_RGBA;
187 switch (internalformat) {
191 format = GL_BGRA_EXT;
196 AllocateTexture(gfx::Size(width, height), format);
199 virtual void texImage2D(GLenum target,
201 GLenum internalformat,
207 const void* pixels) OVERRIDE {
208 CheckTextureIsBound(target);
209 ASSERT_EQ(static_cast<unsigned>(GL_TEXTURE_2D), target);
211 ASSERT_EQ(internalformat, format);
212 ASSERT_FALSE(border);
213 ASSERT_EQ(static_cast<unsigned>(GL_UNSIGNED_BYTE), type);
214 AllocateTexture(gfx::Size(width, height), format);
216 SetPixels(0, 0, width, height, pixels);
219 virtual void texSubImage2D(GLenum target,
227 const void* pixels) OVERRIDE {
228 CheckTextureIsBound(target);
229 ASSERT_EQ(static_cast<unsigned>(GL_TEXTURE_2D), target);
231 ASSERT_EQ(static_cast<unsigned>(GL_UNSIGNED_BYTE), type);
233 base::AutoLock lock_for_texture_access(namespace_->lock);
234 ASSERT_EQ(GLDataFormat(BoundTexture(target)->format), format);
237 SetPixels(xoffset, yoffset, width, height, pixels);
240 virtual void genMailboxCHROMIUM(GLbyte* mailbox) OVERRIDE {
241 return shared_data_->GenMailbox(mailbox);
244 virtual void produceTextureCHROMIUM(GLenum target,
245 const GLbyte* mailbox) OVERRIDE {
246 CheckTextureIsBound(target);
248 // Delay moving the texture into the mailbox until the next
249 // InsertSyncPoint, so that it is not visible to other contexts that
250 // haven't waited on that sync point.
251 scoped_ptr<PendingProduceTexture> pending(new PendingProduceTexture);
252 memcpy(pending->mailbox, mailbox, sizeof(pending->mailbox));
253 base::AutoLock lock_for_texture_access(namespace_->lock);
254 pending->texture = BoundTexture(target);
255 pending_produce_textures_.push_back(pending.Pass());
258 virtual void consumeTextureCHROMIUM(GLenum target,
259 const GLbyte* mailbox) OVERRIDE {
260 CheckTextureIsBound(target);
261 base::AutoLock lock_for_texture_access(namespace_->lock);
262 scoped_refptr<TestTexture> texture =
263 shared_data_->ConsumeTexture(mailbox, last_waited_sync_point_);
264 namespace_->textures.Replace(BoundTextureId(target), texture);
267 void GetPixels(gfx::Size size, ResourceFormat format, uint8_t* pixels) {
268 CheckTextureIsBound(GL_TEXTURE_2D);
269 base::AutoLock lock_for_texture_access(namespace_->lock);
270 scoped_refptr<TestTexture> texture = BoundTexture(GL_TEXTURE_2D);
271 ASSERT_EQ(texture->size, size);
272 ASSERT_EQ(texture->format, format);
273 memcpy(pixels, texture->data.get(), TextureSizeBytes(size, format));
277 explicit ResourceProviderContext(ContextSharedData* shared_data)
278 : shared_data_(shared_data),
279 last_waited_sync_point_(0) {}
282 void AllocateTexture(gfx::Size size, GLenum format) {
283 CheckTextureIsBound(GL_TEXTURE_2D);
284 ResourceFormat texture_format = RGBA_8888;
287 texture_format = RGBA_8888;
290 texture_format = BGRA_8888;
293 base::AutoLock lock_for_texture_access(namespace_->lock);
294 BoundTexture(GL_TEXTURE_2D)->Reallocate(size, texture_format);
297 void SetPixels(int xoffset,
301 const void* pixels) {
302 CheckTextureIsBound(GL_TEXTURE_2D);
303 base::AutoLock lock_for_texture_access(namespace_->lock);
304 scoped_refptr<TestTexture> texture = BoundTexture(GL_TEXTURE_2D);
305 ASSERT_TRUE(texture->data.get());
306 ASSERT_TRUE(xoffset >= 0 && xoffset + width <= texture->size.width());
307 ASSERT_TRUE(yoffset >= 0 && yoffset + height <= texture->size.height());
309 size_t in_pitch = TextureSizeBytes(gfx::Size(width, 1), texture->format);
311 TextureSizeBytes(gfx::Size(texture->size.width(), 1), texture->format);
312 uint8_t* dest = texture->data.get() + yoffset * out_pitch +
313 TextureSizeBytes(gfx::Size(xoffset, 1), texture->format);
314 const uint8_t* src = static_cast<const uint8_t*>(pixels);
315 for (int i = 0; i < height; ++i) {
316 memcpy(dest, src, in_pitch);
322 struct PendingProduceTexture {
324 scoped_refptr<TestTexture> texture;
326 typedef ScopedPtrDeque<PendingProduceTexture> PendingProduceTextureList;
327 ContextSharedData* shared_data_;
328 unsigned last_waited_sync_point_;
329 PendingProduceTextureList pending_produce_textures_;
332 void FreeSharedBitmap(SharedBitmap* shared_bitmap) {
333 delete shared_bitmap->memory();
336 void IgnoreSharedBitmap(SharedBitmap* shared_bitmap) {}
338 class TestSharedBitmapManager : public SharedBitmapManager {
340 TestSharedBitmapManager() : count_(0) {}
341 virtual ~TestSharedBitmapManager() {}
343 virtual scoped_ptr<SharedBitmap> AllocateSharedBitmap(gfx::Size size)
345 scoped_ptr<base::SharedMemory> memory(new base::SharedMemory);
346 memory->CreateAndMapAnonymous(size.GetArea() * 4);
347 int8 name[64] = { 0 };
351 bitmap_map_[id] = memory.get();
352 return scoped_ptr<SharedBitmap>(
353 new SharedBitmap(memory.release(), id, base::Bind(&FreeSharedBitmap)));
356 virtual scoped_ptr<SharedBitmap> GetSharedBitmapFromId(
358 const SharedBitmapId& id) OVERRIDE {
359 if (bitmap_map_.find(id) == bitmap_map_.end())
360 return scoped_ptr<SharedBitmap>();
361 return scoped_ptr<SharedBitmap>(
362 new SharedBitmap(bitmap_map_[id], id, base::Bind(&IgnoreSharedBitmap)));
365 virtual scoped_ptr<SharedBitmap> GetBitmapForSharedMemory(
366 base::SharedMemory* memory) OVERRIDE {
367 int8 name[64] = { 0 };
371 bitmap_map_[id] = memory;
372 return scoped_ptr<SharedBitmap>(
373 new SharedBitmap(memory, id, base::Bind(&IgnoreSharedBitmap)));
378 std::map<SharedBitmapId, base::SharedMemory*> bitmap_map_;
381 void GetResourcePixels(ResourceProvider* resource_provider,
382 ResourceProviderContext* context,
383 ResourceProvider::ResourceId id,
385 ResourceFormat format,
387 switch (resource_provider->default_resource_type()) {
388 case ResourceProvider::GLTexture: {
389 ResourceProvider::ScopedReadLockGL lock_gl(resource_provider, id);
390 ASSERT_NE(0U, lock_gl.texture_id());
391 context->bindTexture(GL_TEXTURE_2D, lock_gl.texture_id());
392 context->GetPixels(size, format, pixels);
395 case ResourceProvider::Bitmap: {
396 ResourceProvider::ScopedReadLockSoftware lock_software(resource_provider,
399 lock_software.sk_bitmap()->getPixels(),
400 lock_software.sk_bitmap()->getSize());
403 case ResourceProvider::InvalidType:
409 class ResourceProviderTest
410 : public testing::TestWithParam<ResourceProvider::ResourceType> {
412 ResourceProviderTest()
413 : shared_data_(ContextSharedData::Create()),
415 child_context_(NULL) {
416 switch (GetParam()) {
417 case ResourceProvider::GLTexture: {
418 scoped_ptr<ResourceProviderContext> context3d(
419 ResourceProviderContext::Create(shared_data_.get()));
420 context3d_ = context3d.get();
422 scoped_refptr<TestContextProvider> context_provider =
423 TestContextProvider::Create(
424 context3d.PassAs<TestWebGraphicsContext3D>());
426 output_surface_ = FakeOutputSurface::Create3d(context_provider);
428 scoped_ptr<ResourceProviderContext> child_context_owned =
429 ResourceProviderContext::Create(shared_data_.get());
430 child_context_ = child_context_owned.get();
431 child_output_surface_ = FakeOutputSurface::Create3d(
432 child_context_owned.PassAs<TestWebGraphicsContext3D>());
435 case ResourceProvider::Bitmap:
436 output_surface_ = FakeOutputSurface::CreateSoftware(
437 make_scoped_ptr(new SoftwareOutputDevice));
438 child_output_surface_ = FakeOutputSurface::CreateSoftware(
439 make_scoped_ptr(new SoftwareOutputDevice));
441 case ResourceProvider::InvalidType:
445 CHECK(output_surface_->BindToClient(&output_surface_client_));
446 CHECK(child_output_surface_->BindToClient(&child_output_surface_client_));
448 shared_bitmap_manager_.reset(new TestSharedBitmapManager());
450 resource_provider_ = ResourceProvider::Create(
451 output_surface_.get(), shared_bitmap_manager_.get(), 0, false, 1);
452 child_resource_provider_ = ResourceProvider::Create(
453 child_output_surface_.get(),
454 shared_bitmap_manager_.get(),
460 static void CollectResources(ReturnedResourceArray* array,
461 const ReturnedResourceArray& returned) {
462 array->insert(array->end(), returned.begin(), returned.end());
465 static ReturnCallback GetReturnCallback(ReturnedResourceArray* array) {
466 return base::Bind(&ResourceProviderTest::CollectResources, array);
469 static void SetResourceFilter(ResourceProvider* resource_provider,
470 ResourceProvider::ResourceId id,
472 ResourceProvider::ScopedSamplerGL sampler(
473 resource_provider, id, GL_TEXTURE_2D, filter);
476 ResourceProviderContext* context() { return context3d_; }
478 ResourceProvider::ResourceId CreateChildMailbox(unsigned* release_sync_point,
480 bool* release_called,
481 unsigned* sync_point) {
482 if (GetParam() == ResourceProvider::GLTexture) {
483 unsigned texture = child_context_->createTexture();
484 gpu::Mailbox gpu_mailbox;
485 child_context_->bindTexture(GL_TEXTURE_2D, texture);
486 child_context_->genMailboxCHROMIUM(gpu_mailbox.name);
487 child_context_->produceTextureCHROMIUM(GL_TEXTURE_2D, gpu_mailbox.name);
488 *sync_point = child_context_->insertSyncPoint();
489 EXPECT_LT(0u, *sync_point);
491 scoped_ptr<base::SharedMemory> shared_memory;
492 scoped_ptr<SingleReleaseCallback> callback =
493 SingleReleaseCallback::Create(base::Bind(ReleaseSharedMemoryCallback,
494 base::Passed(&shared_memory),
498 return child_resource_provider_->CreateResourceFromTextureMailbox(
499 TextureMailbox(gpu_mailbox, *sync_point), callback.Pass());
501 gfx::Size size(64, 64);
502 scoped_ptr<base::SharedMemory> shared_memory(
503 CreateAndFillSharedMemory(size, 0));
505 base::SharedMemory* shared_memory_ptr = shared_memory.get();
506 scoped_ptr<SingleReleaseCallback> callback =
507 SingleReleaseCallback::Create(base::Bind(ReleaseSharedMemoryCallback,
508 base::Passed(&shared_memory),
512 return child_resource_provider_->CreateResourceFromTextureMailbox(
513 TextureMailbox(shared_memory_ptr, size), callback.Pass());
518 scoped_ptr<ContextSharedData> shared_data_;
519 ResourceProviderContext* context3d_;
520 ResourceProviderContext* child_context_;
521 FakeOutputSurfaceClient output_surface_client_;
522 FakeOutputSurfaceClient child_output_surface_client_;
523 scoped_ptr<OutputSurface> output_surface_;
524 scoped_ptr<OutputSurface> child_output_surface_;
525 scoped_ptr<ResourceProvider> resource_provider_;
526 scoped_ptr<ResourceProvider> child_resource_provider_;
527 scoped_ptr<TestSharedBitmapManager> shared_bitmap_manager_;
530 void CheckCreateResource(ResourceProvider::ResourceType expected_default_type,
531 ResourceProvider* resource_provider,
532 ResourceProviderContext* context) {
533 DCHECK_EQ(expected_default_type, resource_provider->default_resource_type());
535 gfx::Size size(1, 1);
536 ResourceFormat format = RGBA_8888;
537 size_t pixel_size = TextureSizeBytes(size, format);
538 ASSERT_EQ(4U, pixel_size);
540 ResourceProvider::ResourceId id = resource_provider->CreateResource(
541 size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureUsageAny, format);
542 EXPECT_EQ(1, static_cast<int>(resource_provider->num_resources()));
543 if (expected_default_type == ResourceProvider::GLTexture)
544 EXPECT_EQ(0u, context->NumTextures());
546 uint8_t data[4] = { 1, 2, 3, 4 };
547 gfx::Rect rect(size);
548 resource_provider->SetPixels(id, data, rect, rect, gfx::Vector2d());
549 if (expected_default_type == ResourceProvider::GLTexture)
550 EXPECT_EQ(1u, context->NumTextures());
552 uint8_t result[4] = { 0 };
553 GetResourcePixels(resource_provider, context, id, size, format, result);
554 EXPECT_EQ(0, memcmp(data, result, pixel_size));
556 resource_provider->DeleteResource(id);
557 EXPECT_EQ(0, static_cast<int>(resource_provider->num_resources()));
558 if (expected_default_type == ResourceProvider::GLTexture)
559 EXPECT_EQ(0u, context->NumTextures());
562 TEST_P(ResourceProviderTest, Basic) {
563 CheckCreateResource(GetParam(), resource_provider_.get(), context());
566 TEST_P(ResourceProviderTest, Upload) {
567 gfx::Size size(2, 2);
568 ResourceFormat format = RGBA_8888;
569 size_t pixel_size = TextureSizeBytes(size, format);
570 ASSERT_EQ(16U, pixel_size);
572 ResourceProvider::ResourceId id = resource_provider_->CreateResource(
573 size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureUsageAny, format);
575 uint8_t image[16] = { 0 };
576 gfx::Rect image_rect(size);
577 resource_provider_->SetPixels(
578 id, image, image_rect, image_rect, gfx::Vector2d());
580 for (uint8_t i = 0; i < pixel_size; ++i)
583 uint8_t result[16] = { 0 };
585 gfx::Rect source_rect(0, 0, 1, 1);
586 gfx::Vector2d dest_offset(0, 0);
587 resource_provider_->SetPixels(
588 id, image, image_rect, source_rect, dest_offset);
590 uint8_t expected[16] = { 0, 1, 2, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
592 resource_provider_.get(), context(), id, size, format, result);
593 EXPECT_EQ(0, memcmp(expected, result, pixel_size));
596 gfx::Rect source_rect(0, 0, 1, 1);
597 gfx::Vector2d dest_offset(1, 1);
598 resource_provider_->SetPixels(
599 id, image, image_rect, source_rect, dest_offset);
601 uint8_t expected[16] = { 0, 1, 2, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3 };
603 resource_provider_.get(), context(), id, size, format, result);
604 EXPECT_EQ(0, memcmp(expected, result, pixel_size));
607 gfx::Rect source_rect(1, 0, 1, 1);
608 gfx::Vector2d dest_offset(0, 1);
609 resource_provider_->SetPixels(
610 id, image, image_rect, source_rect, dest_offset);
612 uint8_t expected[16] = { 0, 1, 2, 3, 0, 0, 0, 0, 4, 5, 6, 7, 0, 1, 2, 3 };
614 resource_provider_.get(), context(), id, size, format, result);
615 EXPECT_EQ(0, memcmp(expected, result, pixel_size));
618 gfx::Rect offset_image_rect(gfx::Point(100, 100), size);
619 gfx::Rect source_rect(100, 100, 1, 1);
620 gfx::Vector2d dest_offset(1, 0);
621 resource_provider_->SetPixels(
622 id, image, offset_image_rect, source_rect, dest_offset);
624 uint8_t expected[16] = { 0, 1, 2, 3, 0, 1, 2, 3, 4, 5, 6, 7, 0, 1, 2, 3 };
626 resource_provider_.get(), context(), id, size, format, result);
627 EXPECT_EQ(0, memcmp(expected, result, pixel_size));
630 resource_provider_->DeleteResource(id);
633 TEST_P(ResourceProviderTest, TransferGLResources) {
634 if (GetParam() != ResourceProvider::GLTexture)
636 gfx::Size size(1, 1);
637 ResourceFormat format = RGBA_8888;
638 size_t pixel_size = TextureSizeBytes(size, format);
639 ASSERT_EQ(4U, pixel_size);
641 ResourceProvider::ResourceId id1 = child_resource_provider_->CreateResource(
642 size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureUsageAny, format);
643 uint8_t data1[4] = { 1, 2, 3, 4 };
644 gfx::Rect rect(size);
645 child_resource_provider_->SetPixels(id1, data1, rect, rect, gfx::Vector2d());
647 ResourceProvider::ResourceId id2 = child_resource_provider_->CreateResource(
648 size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureUsageAny, format);
649 uint8_t data2[4] = { 5, 5, 5, 5 };
650 child_resource_provider_->SetPixels(id2, data2, rect, rect, gfx::Vector2d());
652 ResourceProvider::ResourceId id3 = child_resource_provider_->CreateResource(
653 size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureUsageAny, format);
654 child_resource_provider_->AcquireImage(id3);
655 child_resource_provider_->MapImage(id3);
656 child_resource_provider_->UnmapImage(id3);
658 GLuint external_texture_id = child_context_->createExternalTexture();
659 child_context_->bindTexture(GL_TEXTURE_EXTERNAL_OES, external_texture_id);
661 gpu::Mailbox external_mailbox;
662 child_context_->genMailboxCHROMIUM(external_mailbox.name);
663 child_context_->produceTextureCHROMIUM(GL_TEXTURE_EXTERNAL_OES,
664 external_mailbox.name);
665 const unsigned external_sync_point = child_context_->insertSyncPoint();
666 ResourceProvider::ResourceId id4 =
667 child_resource_provider_->CreateResourceFromTextureMailbox(
669 external_mailbox, GL_TEXTURE_EXTERNAL_OES, external_sync_point),
670 SingleReleaseCallback::Create(base::Bind(&EmptyReleaseCallback)));
672 ReturnedResourceArray returned_to_child;
674 resource_provider_->CreateChild(GetReturnCallback(&returned_to_child));
676 // Transfer some resources to the parent.
677 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
678 resource_ids_to_transfer.push_back(id1);
679 resource_ids_to_transfer.push_back(id2);
680 resource_ids_to_transfer.push_back(id3);
681 resource_ids_to_transfer.push_back(id4);
682 TransferableResourceArray list;
683 child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
685 ASSERT_EQ(4u, list.size());
686 EXPECT_NE(0u, list[0].sync_point);
687 EXPECT_NE(0u, list[1].sync_point);
688 EXPECT_EQ(list[0].sync_point, list[1].sync_point);
689 EXPECT_NE(0u, list[2].sync_point);
690 EXPECT_EQ(list[0].sync_point, list[2].sync_point);
691 EXPECT_EQ(external_sync_point, list[3].sync_point);
692 EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_2D), list[0].target);
693 EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_2D), list[1].target);
694 EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_2D), list[2].target);
695 EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_EXTERNAL_OES), list[3].target);
696 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id1));
697 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id2));
698 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id3));
699 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id4));
700 resource_provider_->ReceiveFromChild(child_id, list);
701 EXPECT_NE(list[0].sync_point, context3d_->last_waited_sync_point());
703 ResourceProvider::ScopedReadLockGL lock(resource_provider_.get(),
706 EXPECT_EQ(list[0].sync_point, context3d_->last_waited_sync_point());
707 resource_provider_->DeclareUsedResourcesFromChild(child_id,
708 resource_ids_to_transfer);
711 EXPECT_EQ(4u, resource_provider_->num_resources());
712 ResourceProvider::ResourceIdMap resource_map =
713 resource_provider_->GetChildToParentMap(child_id);
714 ResourceProvider::ResourceId mapped_id1 = resource_map[id1];
715 ResourceProvider::ResourceId mapped_id2 = resource_map[id2];
716 ResourceProvider::ResourceId mapped_id3 = resource_map[id3];
717 ResourceProvider::ResourceId mapped_id4 = resource_map[id4];
718 EXPECT_NE(0u, mapped_id1);
719 EXPECT_NE(0u, mapped_id2);
720 EXPECT_NE(0u, mapped_id3);
721 EXPECT_NE(0u, mapped_id4);
722 EXPECT_FALSE(resource_provider_->InUseByConsumer(id1));
723 EXPECT_FALSE(resource_provider_->InUseByConsumer(id2));
724 EXPECT_FALSE(resource_provider_->InUseByConsumer(id3));
725 EXPECT_FALSE(resource_provider_->InUseByConsumer(id4));
727 uint8_t result[4] = { 0 };
729 resource_provider_.get(), context(), mapped_id1, size, format, result);
730 EXPECT_EQ(0, memcmp(data1, result, pixel_size));
733 resource_provider_.get(), context(), mapped_id2, size, format, result);
734 EXPECT_EQ(0, memcmp(data2, result, pixel_size));
737 // Check that transfering again the same resource from the child to the
739 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
740 resource_ids_to_transfer.push_back(id1);
741 resource_ids_to_transfer.push_back(id2);
742 resource_ids_to_transfer.push_back(id3);
743 TransferableResourceArray list;
744 child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
746 EXPECT_EQ(3u, list.size());
747 EXPECT_EQ(id1, list[0].id);
748 EXPECT_EQ(id2, list[1].id);
749 EXPECT_EQ(id3, list[2].id);
750 EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_2D), list[0].target);
751 EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_2D), list[1].target);
752 EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_2D), list[2].target);
753 ReturnedResourceArray returned;
754 TransferableResource::ReturnResources(list, &returned);
755 child_resource_provider_->ReceiveReturnsFromParent(returned);
756 // ids were exported twice, we returned them only once, they should still
758 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id1));
759 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id2));
760 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id3));
763 EXPECT_EQ(0u, returned_to_child.size());
765 // Transfer resources back from the parent to the child. Set no resources as
767 ResourceProvider::ResourceIdArray no_resources;
768 resource_provider_->DeclareUsedResourcesFromChild(child_id, no_resources);
770 ASSERT_EQ(4u, returned_to_child.size());
771 EXPECT_NE(0u, returned_to_child[0].sync_point);
772 EXPECT_NE(0u, returned_to_child[1].sync_point);
773 EXPECT_NE(0u, returned_to_child[2].sync_point);
774 EXPECT_NE(0u, returned_to_child[3].sync_point);
775 EXPECT_FALSE(returned_to_child[0].lost);
776 EXPECT_FALSE(returned_to_child[1].lost);
777 EXPECT_FALSE(returned_to_child[2].lost);
778 EXPECT_FALSE(returned_to_child[3].lost);
779 child_resource_provider_->ReceiveReturnsFromParent(returned_to_child);
780 returned_to_child.clear();
782 EXPECT_FALSE(child_resource_provider_->InUseByConsumer(id1));
783 EXPECT_FALSE(child_resource_provider_->InUseByConsumer(id2));
784 EXPECT_FALSE(child_resource_provider_->InUseByConsumer(id3));
785 EXPECT_FALSE(child_resource_provider_->InUseByConsumer(id4));
788 ResourceProvider::ScopedReadLockGL lock(child_resource_provider_.get(),
790 ASSERT_NE(0U, lock.texture_id());
791 child_context_->bindTexture(GL_TEXTURE_2D, lock.texture_id());
792 child_context_->GetPixels(size, format, result);
793 EXPECT_EQ(0, memcmp(data1, result, pixel_size));
796 ResourceProvider::ScopedReadLockGL lock(child_resource_provider_.get(),
798 ASSERT_NE(0U, lock.texture_id());
799 child_context_->bindTexture(GL_TEXTURE_2D, lock.texture_id());
800 child_context_->GetPixels(size, format, result);
801 EXPECT_EQ(0, memcmp(data2, result, pixel_size));
804 ResourceProvider::ScopedReadLockGL lock(child_resource_provider_.get(),
806 ASSERT_NE(0U, lock.texture_id());
807 child_context_->bindTexture(GL_TEXTURE_2D, lock.texture_id());
810 // Transfer resources to the parent again.
811 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
812 resource_ids_to_transfer.push_back(id1);
813 resource_ids_to_transfer.push_back(id2);
814 resource_ids_to_transfer.push_back(id3);
815 resource_ids_to_transfer.push_back(id4);
816 TransferableResourceArray list;
817 child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
819 ASSERT_EQ(4u, list.size());
820 EXPECT_EQ(id1, list[0].id);
821 EXPECT_EQ(id2, list[1].id);
822 EXPECT_EQ(id3, list[2].id);
823 EXPECT_EQ(id4, list[3].id);
824 EXPECT_NE(0u, list[0].sync_point);
825 EXPECT_NE(0u, list[1].sync_point);
826 EXPECT_NE(0u, list[2].sync_point);
827 EXPECT_NE(0u, list[3].sync_point);
828 EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_2D), list[0].target);
829 EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_2D), list[1].target);
830 EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_2D), list[2].target);
831 EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_EXTERNAL_OES), list[3].target);
832 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id1));
833 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id2));
834 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id3));
835 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id4));
836 resource_provider_->ReceiveFromChild(child_id, list);
837 resource_provider_->DeclareUsedResourcesFromChild(child_id,
838 resource_ids_to_transfer);
841 EXPECT_EQ(0u, returned_to_child.size());
843 EXPECT_EQ(4u, resource_provider_->num_resources());
844 resource_provider_->DestroyChild(child_id);
845 EXPECT_EQ(0u, resource_provider_->num_resources());
847 ASSERT_EQ(4u, returned_to_child.size());
848 EXPECT_NE(0u, returned_to_child[0].sync_point);
849 EXPECT_NE(0u, returned_to_child[1].sync_point);
850 EXPECT_NE(0u, returned_to_child[2].sync_point);
851 EXPECT_NE(0u, returned_to_child[3].sync_point);
852 EXPECT_FALSE(returned_to_child[0].lost);
853 EXPECT_FALSE(returned_to_child[1].lost);
854 EXPECT_FALSE(returned_to_child[2].lost);
855 EXPECT_FALSE(returned_to_child[3].lost);
858 TEST_P(ResourceProviderTest, TransferSoftwareResources) {
859 if (GetParam() != ResourceProvider::Bitmap)
862 gfx::Size size(1, 1);
863 ResourceFormat format = RGBA_8888;
864 size_t pixel_size = TextureSizeBytes(size, format);
865 ASSERT_EQ(4U, pixel_size);
867 ResourceProvider::ResourceId id1 = child_resource_provider_->CreateResource(
868 size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureUsageAny, format);
869 uint8_t data1[4] = { 1, 2, 3, 4 };
870 gfx::Rect rect(size);
871 child_resource_provider_->SetPixels(id1, data1, rect, rect, gfx::Vector2d());
873 ResourceProvider::ResourceId id2 = child_resource_provider_->CreateResource(
874 size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureUsageAny, format);
875 uint8_t data2[4] = { 5, 5, 5, 5 };
876 child_resource_provider_->SetPixels(id2, data2, rect, rect, gfx::Vector2d());
878 ResourceProvider::ResourceId id3 = child_resource_provider_->CreateResource(
879 size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureUsageAny, format);
880 child_resource_provider_->AcquireImage(id3);
881 void* data = child_resource_provider_->MapImage(id3);
882 uint8_t data3[4] = { 6, 7, 8, 9 };
883 memcpy(data, data3, sizeof(data3));
884 child_resource_provider_->UnmapImage(id3);
886 scoped_ptr<base::SharedMemory> shared_memory(new base::SharedMemory());
887 shared_memory->CreateAndMapAnonymous(1);
888 base::SharedMemory* shared_memory_ptr = shared_memory.get();
889 ResourceProvider::ResourceId id4 =
890 child_resource_provider_->CreateResourceFromTextureMailbox(
891 TextureMailbox(shared_memory_ptr, gfx::Size(1, 1)),
892 SingleReleaseCallback::Create(base::Bind(
893 &SharedMemoryReleaseCallback, base::Passed(&shared_memory))));
895 ReturnedResourceArray returned_to_child;
897 resource_provider_->CreateChild(GetReturnCallback(&returned_to_child));
899 // Transfer some resources to the parent.
900 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
901 resource_ids_to_transfer.push_back(id1);
902 resource_ids_to_transfer.push_back(id2);
903 resource_ids_to_transfer.push_back(id3);
904 resource_ids_to_transfer.push_back(id4);
905 TransferableResourceArray list;
906 child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
908 ASSERT_EQ(4u, list.size());
909 EXPECT_EQ(0u, list[0].sync_point);
910 EXPECT_EQ(0u, list[1].sync_point);
911 EXPECT_EQ(0u, list[2].sync_point);
912 EXPECT_EQ(0u, list[3].sync_point);
913 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id1));
914 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id2));
915 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id3));
916 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id4));
917 resource_provider_->ReceiveFromChild(child_id, list);
918 resource_provider_->DeclareUsedResourcesFromChild(child_id,
919 resource_ids_to_transfer);
922 EXPECT_EQ(4u, resource_provider_->num_resources());
923 ResourceProvider::ResourceIdMap resource_map =
924 resource_provider_->GetChildToParentMap(child_id);
925 ResourceProvider::ResourceId mapped_id1 = resource_map[id1];
926 ResourceProvider::ResourceId mapped_id2 = resource_map[id2];
927 ResourceProvider::ResourceId mapped_id3 = resource_map[id3];
928 ResourceProvider::ResourceId mapped_id4 = resource_map[id4];
929 EXPECT_NE(0u, mapped_id1);
930 EXPECT_NE(0u, mapped_id2);
931 EXPECT_NE(0u, mapped_id3);
932 EXPECT_NE(0u, mapped_id4);
933 EXPECT_FALSE(resource_provider_->InUseByConsumer(id1));
934 EXPECT_FALSE(resource_provider_->InUseByConsumer(id2));
935 EXPECT_FALSE(resource_provider_->InUseByConsumer(id3));
936 EXPECT_FALSE(resource_provider_->InUseByConsumer(id4));
938 uint8_t result[4] = { 0 };
940 resource_provider_.get(), context(), mapped_id1, size, format, result);
941 EXPECT_EQ(0, memcmp(data1, result, pixel_size));
944 resource_provider_.get(), context(), mapped_id2, size, format, result);
945 EXPECT_EQ(0, memcmp(data2, result, pixel_size));
948 resource_provider_.get(), context(), mapped_id3, size, format, result);
949 EXPECT_EQ(0, memcmp(data3, result, pixel_size));
952 // Check that transfering again the same resource from the child to the
954 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
955 resource_ids_to_transfer.push_back(id1);
956 resource_ids_to_transfer.push_back(id2);
957 resource_ids_to_transfer.push_back(id3);
958 TransferableResourceArray list;
959 child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
961 EXPECT_EQ(3u, list.size());
962 EXPECT_EQ(id1, list[0].id);
963 EXPECT_EQ(id2, list[1].id);
964 EXPECT_EQ(id3, list[2].id);
965 ReturnedResourceArray returned;
966 TransferableResource::ReturnResources(list, &returned);
967 child_resource_provider_->ReceiveReturnsFromParent(returned);
968 // ids were exported twice, we returned them only once, they should still
970 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id1));
971 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id2));
972 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id3));
975 EXPECT_EQ(0u, returned_to_child.size());
977 // Transfer resources back from the parent to the child. Set no resources as
979 ResourceProvider::ResourceIdArray no_resources;
980 resource_provider_->DeclareUsedResourcesFromChild(child_id, no_resources);
982 ASSERT_EQ(4u, returned_to_child.size());
983 EXPECT_EQ(0u, returned_to_child[0].sync_point);
984 EXPECT_EQ(0u, returned_to_child[1].sync_point);
985 EXPECT_EQ(0u, returned_to_child[2].sync_point);
986 EXPECT_EQ(0u, returned_to_child[3].sync_point);
987 EXPECT_EQ(id1, returned_to_child[0].id);
988 EXPECT_EQ(id2, returned_to_child[1].id);
989 EXPECT_EQ(id3, returned_to_child[2].id);
990 EXPECT_EQ(id4, returned_to_child[3].id);
991 EXPECT_FALSE(returned_to_child[0].lost);
992 EXPECT_FALSE(returned_to_child[1].lost);
993 EXPECT_FALSE(returned_to_child[2].lost);
994 EXPECT_FALSE(returned_to_child[3].lost);
995 child_resource_provider_->ReceiveReturnsFromParent(returned_to_child);
996 returned_to_child.clear();
998 EXPECT_FALSE(child_resource_provider_->InUseByConsumer(id1));
999 EXPECT_FALSE(child_resource_provider_->InUseByConsumer(id2));
1000 EXPECT_FALSE(child_resource_provider_->InUseByConsumer(id3));
1001 EXPECT_FALSE(child_resource_provider_->InUseByConsumer(id4));
1004 ResourceProvider::ScopedReadLockSoftware lock(
1005 child_resource_provider_.get(), id1);
1006 const SkBitmap* sk_bitmap = lock.sk_bitmap();
1007 EXPECT_EQ(sk_bitmap->width(), size.width());
1008 EXPECT_EQ(sk_bitmap->height(), size.height());
1009 EXPECT_EQ(0, memcmp(data1, sk_bitmap->getPixels(), pixel_size));
1012 ResourceProvider::ScopedReadLockSoftware lock(
1013 child_resource_provider_.get(), id2);
1014 const SkBitmap* sk_bitmap = lock.sk_bitmap();
1015 EXPECT_EQ(sk_bitmap->width(), size.width());
1016 EXPECT_EQ(sk_bitmap->height(), size.height());
1017 EXPECT_EQ(0, memcmp(data2, sk_bitmap->getPixels(), pixel_size));
1020 ResourceProvider::ScopedReadLockSoftware lock(
1021 child_resource_provider_.get(), id3);
1022 const SkBitmap* sk_bitmap = lock.sk_bitmap();
1023 EXPECT_EQ(sk_bitmap->width(), size.width());
1024 EXPECT_EQ(sk_bitmap->height(), size.height());
1025 EXPECT_EQ(0, memcmp(data3, sk_bitmap->getPixels(), pixel_size));
1028 // Transfer resources to the parent again.
1029 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
1030 resource_ids_to_transfer.push_back(id1);
1031 resource_ids_to_transfer.push_back(id2);
1032 resource_ids_to_transfer.push_back(id3);
1033 resource_ids_to_transfer.push_back(id4);
1034 TransferableResourceArray list;
1035 child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
1037 ASSERT_EQ(4u, list.size());
1038 EXPECT_EQ(id1, list[0].id);
1039 EXPECT_EQ(id2, list[1].id);
1040 EXPECT_EQ(id3, list[2].id);
1041 EXPECT_EQ(id4, list[3].id);
1042 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id1));
1043 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id2));
1044 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id3));
1045 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id4));
1046 resource_provider_->ReceiveFromChild(child_id, list);
1047 resource_provider_->DeclareUsedResourcesFromChild(child_id,
1048 resource_ids_to_transfer);
1051 EXPECT_EQ(0u, returned_to_child.size());
1053 EXPECT_EQ(4u, resource_provider_->num_resources());
1054 resource_provider_->DestroyChild(child_id);
1055 EXPECT_EQ(0u, resource_provider_->num_resources());
1057 ASSERT_EQ(4u, returned_to_child.size());
1058 EXPECT_EQ(0u, returned_to_child[0].sync_point);
1059 EXPECT_EQ(0u, returned_to_child[1].sync_point);
1060 EXPECT_EQ(0u, returned_to_child[2].sync_point);
1061 EXPECT_EQ(0u, returned_to_child[3].sync_point);
1062 EXPECT_EQ(id1, returned_to_child[0].id);
1063 EXPECT_EQ(id2, returned_to_child[1].id);
1064 EXPECT_EQ(id3, returned_to_child[2].id);
1065 EXPECT_EQ(id4, returned_to_child[3].id);
1066 EXPECT_FALSE(returned_to_child[0].lost);
1067 EXPECT_FALSE(returned_to_child[1].lost);
1068 EXPECT_FALSE(returned_to_child[2].lost);
1069 EXPECT_FALSE(returned_to_child[3].lost);
1072 TEST_P(ResourceProviderTest, TransferSoftwareToNonUber) {
1073 // TODO(jbauman): Remove test when shared bitmap manager available
1075 if (GetParam() != ResourceProvider::Bitmap)
1078 scoped_ptr<FakeOutputSurface> parent_output_surface =
1079 FakeOutputSurface::CreateSoftware(
1080 make_scoped_ptr(new SoftwareOutputDevice));
1081 FakeOutputSurfaceClient parent_output_surface_client;
1082 CHECK(parent_output_surface->BindToClient(&parent_output_surface_client));
1084 scoped_ptr<ResourceProvider> parent_resource_provider(
1085 ResourceProvider::Create(parent_output_surface.get(),
1091 gfx::Size size(1, 1);
1092 ResourceFormat format = RGBA_8888;
1093 size_t pixel_size = TextureSizeBytes(size, format);
1094 ASSERT_EQ(4U, pixel_size);
1096 ResourceProvider::ResourceId id1 = resource_provider_->CreateResource(
1097 size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureUsageAny, format);
1098 uint8_t data1[4] = { 1, 2, 3, 4 };
1099 gfx::Rect rect(size);
1100 resource_provider_->SetPixels(id1, data1, rect, rect, gfx::Vector2d());
1102 ReturnedResourceArray returned_to_child;
1103 int child_id = parent_resource_provider->CreateChild(
1104 GetReturnCallback(&returned_to_child));
1106 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
1107 resource_ids_to_transfer.push_back(id1);
1108 TransferableResourceArray list;
1109 resource_provider_->PrepareSendToParent(resource_ids_to_transfer, &list);
1110 ASSERT_EQ(1u, list.size());
1111 EXPECT_TRUE(resource_provider_->InUseByConsumer(id1));
1112 parent_resource_provider->ReceiveFromChild(child_id, list);
1115 EXPECT_EQ(0u, parent_resource_provider->num_resources());
1116 ASSERT_EQ(1u, returned_to_child.size());
1117 EXPECT_EQ(returned_to_child[0].id, id1);
1118 ResourceProvider::ResourceIdMap resource_map =
1119 parent_resource_provider->GetChildToParentMap(child_id);
1120 ResourceProvider::ResourceId mapped_id1 = resource_map[id1];
1121 EXPECT_EQ(0u, mapped_id1);
1123 parent_resource_provider->DestroyChild(child_id);
1124 EXPECT_EQ(0u, parent_resource_provider->num_resources());
1126 ASSERT_EQ(1u, returned_to_child.size());
1127 EXPECT_FALSE(returned_to_child[0].lost);
1130 TEST_P(ResourceProviderTest, TransferGLToSoftware) {
1131 if (GetParam() != ResourceProvider::Bitmap)
1134 scoped_ptr<ResourceProviderContext> child_context_owned(
1135 ResourceProviderContext::Create(shared_data_.get()));
1137 FakeOutputSurfaceClient child_output_surface_client;
1138 scoped_ptr<OutputSurface> child_output_surface(FakeOutputSurface::Create3d(
1139 child_context_owned.PassAs<TestWebGraphicsContext3D>()));
1140 CHECK(child_output_surface->BindToClient(&child_output_surface_client));
1142 scoped_ptr<ResourceProvider> child_resource_provider(
1143 ResourceProvider::Create(child_output_surface.get(),
1149 gfx::Size size(1, 1);
1150 ResourceFormat format = RGBA_8888;
1151 size_t pixel_size = TextureSizeBytes(size, format);
1152 ASSERT_EQ(4U, pixel_size);
1154 ResourceProvider::ResourceId id1 = child_resource_provider->CreateResource(
1155 size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureUsageAny, format);
1156 uint8_t data1[4] = { 1, 2, 3, 4 };
1157 gfx::Rect rect(size);
1158 child_resource_provider->SetPixels(id1, data1, rect, rect, gfx::Vector2d());
1160 ReturnedResourceArray returned_to_child;
1162 resource_provider_->CreateChild(GetReturnCallback(&returned_to_child));
1164 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
1165 resource_ids_to_transfer.push_back(id1);
1166 TransferableResourceArray list;
1167 child_resource_provider->PrepareSendToParent(resource_ids_to_transfer,
1169 ASSERT_EQ(1u, list.size());
1170 EXPECT_NE(0u, list[0].sync_point);
1171 EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_2D), list[0].target);
1172 EXPECT_TRUE(child_resource_provider->InUseByConsumer(id1));
1173 resource_provider_->ReceiveFromChild(child_id, list);
1176 EXPECT_EQ(0u, resource_provider_->num_resources());
1177 ASSERT_EQ(1u, returned_to_child.size());
1178 EXPECT_EQ(returned_to_child[0].id, id1);
1179 ResourceProvider::ResourceIdMap resource_map =
1180 resource_provider_->GetChildToParentMap(child_id);
1181 ResourceProvider::ResourceId mapped_id1 = resource_map[id1];
1182 EXPECT_EQ(0u, mapped_id1);
1184 resource_provider_->DestroyChild(child_id);
1185 EXPECT_EQ(0u, resource_provider_->num_resources());
1187 ASSERT_EQ(1u, returned_to_child.size());
1188 EXPECT_FALSE(returned_to_child[0].lost);
1191 TEST_P(ResourceProviderTest, TransferInvalidSoftware) {
1192 if (GetParam() != ResourceProvider::Bitmap)
1195 gfx::Size size(1, 1);
1196 ResourceFormat format = RGBA_8888;
1197 size_t pixel_size = TextureSizeBytes(size, format);
1198 ASSERT_EQ(4U, pixel_size);
1200 ResourceProvider::ResourceId id1 = child_resource_provider_->CreateResource(
1201 size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureUsageAny, format);
1202 uint8_t data1[4] = { 1, 2, 3, 4 };
1203 gfx::Rect rect(size);
1204 child_resource_provider_->SetPixels(id1, data1, rect, rect, gfx::Vector2d());
1206 ReturnedResourceArray returned_to_child;
1208 resource_provider_->CreateChild(GetReturnCallback(&returned_to_child));
1210 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
1211 resource_ids_to_transfer.push_back(id1);
1212 TransferableResourceArray list;
1213 child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
1215 ASSERT_EQ(1u, list.size());
1217 list[0].mailbox.name[1] = 5;
1218 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id1));
1219 resource_provider_->ReceiveFromChild(child_id, list);
1222 EXPECT_EQ(0u, resource_provider_->num_resources());
1223 ASSERT_EQ(1u, returned_to_child.size());
1224 EXPECT_EQ(returned_to_child[0].id, id1);
1225 ResourceProvider::ResourceIdMap resource_map =
1226 resource_provider_->GetChildToParentMap(child_id);
1227 ResourceProvider::ResourceId mapped_id1 = resource_map[id1];
1228 EXPECT_EQ(0u, mapped_id1);
1230 resource_provider_->DestroyChild(child_id);
1231 EXPECT_EQ(0u, resource_provider_->num_resources());
1233 ASSERT_EQ(1u, returned_to_child.size());
1234 EXPECT_FALSE(returned_to_child[0].lost);
1237 TEST_P(ResourceProviderTest, DeleteExportedResources) {
1238 gfx::Size size(1, 1);
1239 ResourceFormat format = RGBA_8888;
1240 size_t pixel_size = TextureSizeBytes(size, format);
1241 ASSERT_EQ(4U, pixel_size);
1243 ResourceProvider::ResourceId id1 = child_resource_provider_->CreateResource(
1244 size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureUsageAny, format);
1245 uint8_t data1[4] = { 1, 2, 3, 4 };
1246 gfx::Rect rect(size);
1247 child_resource_provider_->SetPixels(id1, data1, rect, rect, gfx::Vector2d());
1249 ResourceProvider::ResourceId id2 = child_resource_provider_->CreateResource(
1250 size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureUsageAny, format);
1251 uint8_t data2[4] = {5, 5, 5, 5};
1252 child_resource_provider_->SetPixels(id2, data2, rect, rect, gfx::Vector2d());
1254 ReturnedResourceArray returned_to_child;
1256 resource_provider_->CreateChild(GetReturnCallback(&returned_to_child));
1258 // Transfer some resources to the parent.
1259 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
1260 resource_ids_to_transfer.push_back(id1);
1261 resource_ids_to_transfer.push_back(id2);
1262 TransferableResourceArray list;
1263 child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
1265 ASSERT_EQ(2u, list.size());
1266 if (GetParam() == ResourceProvider::GLTexture) {
1267 EXPECT_NE(0u, list[0].sync_point);
1268 EXPECT_NE(0u, list[1].sync_point);
1270 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id1));
1271 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id2));
1272 resource_provider_->ReceiveFromChild(child_id, list);
1273 resource_provider_->DeclareUsedResourcesFromChild(child_id,
1274 resource_ids_to_transfer);
1277 EXPECT_EQ(2u, resource_provider_->num_resources());
1278 ResourceProvider::ResourceIdMap resource_map =
1279 resource_provider_->GetChildToParentMap(child_id);
1280 ResourceProvider::ResourceId mapped_id1 = resource_map[id1];
1281 ResourceProvider::ResourceId mapped_id2 = resource_map[id2];
1282 EXPECT_NE(0u, mapped_id1);
1283 EXPECT_NE(0u, mapped_id2);
1284 EXPECT_FALSE(resource_provider_->InUseByConsumer(id1));
1285 EXPECT_FALSE(resource_provider_->InUseByConsumer(id2));
1288 // The parent transfers the resources to the grandparent.
1289 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
1290 resource_ids_to_transfer.push_back(mapped_id1);
1291 resource_ids_to_transfer.push_back(mapped_id2);
1292 TransferableResourceArray list;
1293 resource_provider_->PrepareSendToParent(resource_ids_to_transfer, &list);
1295 ASSERT_EQ(2u, list.size());
1296 if (GetParam() == ResourceProvider::GLTexture) {
1297 EXPECT_NE(0u, list[0].sync_point);
1298 EXPECT_NE(0u, list[1].sync_point);
1300 EXPECT_TRUE(resource_provider_->InUseByConsumer(id1));
1301 EXPECT_TRUE(resource_provider_->InUseByConsumer(id2));
1303 // Release the resource in the parent. Set no resources as being in use. The
1304 // resources are exported so that can't be transferred back yet.
1305 ResourceProvider::ResourceIdArray no_resources;
1306 resource_provider_->DeclareUsedResourcesFromChild(child_id, no_resources);
1308 EXPECT_EQ(0u, returned_to_child.size());
1309 EXPECT_EQ(2u, resource_provider_->num_resources());
1311 // Return the resources from the grandparent to the parent. They should be
1312 // returned to the child then.
1313 EXPECT_EQ(2u, list.size());
1314 EXPECT_EQ(mapped_id1, list[0].id);
1315 EXPECT_EQ(mapped_id2, list[1].id);
1316 ReturnedResourceArray returned;
1317 TransferableResource::ReturnResources(list, &returned);
1318 resource_provider_->ReceiveReturnsFromParent(returned);
1320 EXPECT_EQ(0u, resource_provider_->num_resources());
1321 ASSERT_EQ(2u, returned_to_child.size());
1322 if (GetParam() == ResourceProvider::GLTexture) {
1323 EXPECT_NE(0u, returned_to_child[0].sync_point);
1324 EXPECT_NE(0u, returned_to_child[1].sync_point);
1326 EXPECT_FALSE(returned_to_child[0].lost);
1327 EXPECT_FALSE(returned_to_child[1].lost);
1331 TEST_P(ResourceProviderTest, DestroyChildWithExportedResources) {
1332 gfx::Size size(1, 1);
1333 ResourceFormat format = RGBA_8888;
1334 size_t pixel_size = TextureSizeBytes(size, format);
1335 ASSERT_EQ(4U, pixel_size);
1337 ResourceProvider::ResourceId id1 = child_resource_provider_->CreateResource(
1338 size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureUsageAny, format);
1339 uint8_t data1[4] = {1, 2, 3, 4};
1340 gfx::Rect rect(size);
1341 child_resource_provider_->SetPixels(id1, data1, rect, rect, gfx::Vector2d());
1343 ResourceProvider::ResourceId id2 = child_resource_provider_->CreateResource(
1344 size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureUsageAny, format);
1345 uint8_t data2[4] = {5, 5, 5, 5};
1346 child_resource_provider_->SetPixels(id2, data2, rect, rect, gfx::Vector2d());
1348 ReturnedResourceArray returned_to_child;
1350 resource_provider_->CreateChild(GetReturnCallback(&returned_to_child));
1352 // Transfer some resources to the parent.
1353 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
1354 resource_ids_to_transfer.push_back(id1);
1355 resource_ids_to_transfer.push_back(id2);
1356 TransferableResourceArray list;
1357 child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
1359 ASSERT_EQ(2u, list.size());
1360 if (GetParam() == ResourceProvider::GLTexture) {
1361 EXPECT_NE(0u, list[0].sync_point);
1362 EXPECT_NE(0u, list[1].sync_point);
1364 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id1));
1365 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id2));
1366 resource_provider_->ReceiveFromChild(child_id, list);
1367 resource_provider_->DeclareUsedResourcesFromChild(child_id,
1368 resource_ids_to_transfer);
1371 EXPECT_EQ(2u, resource_provider_->num_resources());
1372 ResourceProvider::ResourceIdMap resource_map =
1373 resource_provider_->GetChildToParentMap(child_id);
1374 ResourceProvider::ResourceId mapped_id1 = resource_map[id1];
1375 ResourceProvider::ResourceId mapped_id2 = resource_map[id2];
1376 EXPECT_NE(0u, mapped_id1);
1377 EXPECT_NE(0u, mapped_id2);
1378 EXPECT_FALSE(resource_provider_->InUseByConsumer(id1));
1379 EXPECT_FALSE(resource_provider_->InUseByConsumer(id2));
1382 // The parent transfers the resources to the grandparent.
1383 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
1384 resource_ids_to_transfer.push_back(mapped_id1);
1385 resource_ids_to_transfer.push_back(mapped_id2);
1386 TransferableResourceArray list;
1387 resource_provider_->PrepareSendToParent(resource_ids_to_transfer, &list);
1389 ASSERT_EQ(2u, list.size());
1390 if (GetParam() == ResourceProvider::GLTexture) {
1391 EXPECT_NE(0u, list[0].sync_point);
1392 EXPECT_NE(0u, list[1].sync_point);
1394 EXPECT_TRUE(resource_provider_->InUseByConsumer(id1));
1395 EXPECT_TRUE(resource_provider_->InUseByConsumer(id2));
1397 // Release the resource in the parent. Set no resources as being in use. The
1398 // resources are exported so that can't be transferred back yet.
1399 ResourceProvider::ResourceIdArray no_resources;
1400 resource_provider_->DeclareUsedResourcesFromChild(child_id, no_resources);
1402 // Destroy the child, the resources should not be returned yet.
1403 EXPECT_EQ(0u, returned_to_child.size());
1404 EXPECT_EQ(2u, resource_provider_->num_resources());
1406 resource_provider_->DestroyChild(child_id);
1408 EXPECT_EQ(2u, resource_provider_->num_resources());
1409 ASSERT_EQ(0u, returned_to_child.size());
1411 // Return a resource from the grandparent, it should be returned at this
1413 EXPECT_EQ(2u, list.size());
1414 EXPECT_EQ(mapped_id1, list[0].id);
1415 EXPECT_EQ(mapped_id2, list[1].id);
1416 TransferableResourceArray return_list;
1417 return_list.push_back(list[1]);
1419 ReturnedResourceArray returned;
1420 TransferableResource::ReturnResources(return_list, &returned);
1421 resource_provider_->ReceiveReturnsFromParent(returned);
1423 EXPECT_EQ(1u, resource_provider_->num_resources());
1424 ASSERT_EQ(1u, returned_to_child.size());
1425 if (GetParam() == ResourceProvider::GLTexture) {
1426 EXPECT_NE(0u, returned_to_child[0].sync_point);
1428 EXPECT_FALSE(returned_to_child[0].lost);
1429 returned_to_child.clear();
1431 // Destroy the parent resource provider. The resource that's left should be
1432 // lost at this point, and returned.
1433 resource_provider_.reset();
1434 ASSERT_EQ(1u, returned_to_child.size());
1435 if (GetParam() == ResourceProvider::GLTexture) {
1436 EXPECT_NE(0u, returned_to_child[0].sync_point);
1438 EXPECT_TRUE(returned_to_child[0].lost);
1442 TEST_P(ResourceProviderTest, DeleteTransferredResources) {
1443 gfx::Size size(1, 1);
1444 ResourceFormat format = RGBA_8888;
1445 size_t pixel_size = TextureSizeBytes(size, format);
1446 ASSERT_EQ(4U, pixel_size);
1448 ResourceProvider::ResourceId id = child_resource_provider_->CreateResource(
1449 size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureUsageAny, format);
1450 uint8_t data[4] = { 1, 2, 3, 4 };
1451 gfx::Rect rect(size);
1452 child_resource_provider_->SetPixels(id, data, rect, rect, gfx::Vector2d());
1454 ReturnedResourceArray returned_to_child;
1456 resource_provider_->CreateChild(GetReturnCallback(&returned_to_child));
1458 // Transfer some resource to the parent.
1459 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
1460 resource_ids_to_transfer.push_back(id);
1461 TransferableResourceArray list;
1462 child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
1464 ASSERT_EQ(1u, list.size());
1465 if (GetParam() == ResourceProvider::GLTexture)
1466 EXPECT_NE(0u, list[0].sync_point);
1467 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id));
1468 resource_provider_->ReceiveFromChild(child_id, list);
1469 resource_provider_->DeclareUsedResourcesFromChild(child_id,
1470 resource_ids_to_transfer);
1473 // Delete textures in the child, while they are transfered.
1474 child_resource_provider_->DeleteResource(id);
1475 EXPECT_EQ(1u, child_resource_provider_->num_resources());
1477 EXPECT_EQ(0u, returned_to_child.size());
1479 // Transfer resources back from the parent to the child. Set no resources as
1481 ResourceProvider::ResourceIdArray no_resources;
1482 resource_provider_->DeclareUsedResourcesFromChild(child_id, no_resources);
1484 ASSERT_EQ(1u, returned_to_child.size());
1485 if (GetParam() == ResourceProvider::GLTexture)
1486 EXPECT_NE(0u, returned_to_child[0].sync_point);
1487 child_resource_provider_->ReceiveReturnsFromParent(returned_to_child);
1489 EXPECT_EQ(0u, child_resource_provider_->num_resources());
1492 class ResourceProviderTestTextureFilters : public ResourceProviderTest {
1494 static void RunTest(GLenum child_filter, GLenum parent_filter) {
1495 scoped_ptr<TextureStateTrackingContext> child_context_owned(
1496 new TextureStateTrackingContext);
1497 TextureStateTrackingContext* child_context = child_context_owned.get();
1499 FakeOutputSurfaceClient child_output_surface_client;
1500 scoped_ptr<OutputSurface> child_output_surface(FakeOutputSurface::Create3d(
1501 child_context_owned.PassAs<TestWebGraphicsContext3D>()));
1502 CHECK(child_output_surface->BindToClient(&child_output_surface_client));
1504 scoped_ptr<ResourceProvider> child_resource_provider(
1505 ResourceProvider::Create(child_output_surface.get(),
1511 scoped_ptr<TextureStateTrackingContext> parent_context_owned(
1512 new TextureStateTrackingContext);
1513 TextureStateTrackingContext* parent_context = parent_context_owned.get();
1515 FakeOutputSurfaceClient parent_output_surface_client;
1516 scoped_ptr<OutputSurface> parent_output_surface(FakeOutputSurface::Create3d(
1517 parent_context_owned.PassAs<TestWebGraphicsContext3D>()));
1518 CHECK(parent_output_surface->BindToClient(&parent_output_surface_client));
1520 scoped_ptr<ResourceProvider> parent_resource_provider(
1521 ResourceProvider::Create(parent_output_surface.get(),
1527 gfx::Size size(1, 1);
1528 ResourceFormat format = RGBA_8888;
1529 int child_texture_id = 1;
1530 int parent_texture_id = 2;
1532 size_t pixel_size = TextureSizeBytes(size, format);
1533 ASSERT_EQ(4U, pixel_size);
1535 ResourceProvider::ResourceId id = child_resource_provider->CreateResource(
1536 size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureUsageAny, format);
1538 // The new texture is created with GL_LINEAR.
1539 EXPECT_CALL(*child_context, bindTexture(GL_TEXTURE_2D, child_texture_id))
1540 .Times(2); // Once to create and once to allocate.
1541 EXPECT_CALL(*child_context,
1542 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
1543 EXPECT_CALL(*child_context,
1544 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR));
1547 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE));
1550 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE));
1551 EXPECT_CALL(*child_context,
1552 texParameteri(GL_TEXTURE_2D,
1553 GL_TEXTURE_POOL_CHROMIUM,
1554 GL_TEXTURE_POOL_UNMANAGED_CHROMIUM));
1555 child_resource_provider->AllocateForTesting(id);
1556 Mock::VerifyAndClearExpectations(child_context);
1558 uint8_t data[4] = { 1, 2, 3, 4 };
1559 gfx::Rect rect(size);
1561 EXPECT_CALL(*child_context, bindTexture(GL_TEXTURE_2D, child_texture_id));
1562 child_resource_provider->SetPixels(id, data, rect, rect, gfx::Vector2d());
1563 Mock::VerifyAndClearExpectations(child_context);
1565 // The texture is set to |child_filter| in the child.
1566 EXPECT_CALL(*child_context, bindTexture(GL_TEXTURE_2D, child_texture_id));
1567 if (child_filter != GL_LINEAR) {
1570 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, child_filter));
1573 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, child_filter));
1575 SetResourceFilter(child_resource_provider.get(), id, child_filter);
1576 Mock::VerifyAndClearExpectations(child_context);
1578 ReturnedResourceArray returned_to_child;
1579 int child_id = parent_resource_provider->CreateChild(
1580 GetReturnCallback(&returned_to_child));
1582 // Transfer some resource to the parent.
1583 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
1584 resource_ids_to_transfer.push_back(id);
1585 TransferableResourceArray list;
1587 EXPECT_CALL(*child_context, bindTexture(GL_TEXTURE_2D, child_texture_id));
1588 EXPECT_CALL(*child_context,
1589 produceTextureCHROMIUM(GL_TEXTURE_2D, _));
1590 EXPECT_CALL(*child_context, insertSyncPoint());
1591 child_resource_provider->PrepareSendToParent(resource_ids_to_transfer,
1593 Mock::VerifyAndClearExpectations(child_context);
1595 ASSERT_EQ(1u, list.size());
1596 EXPECT_EQ(static_cast<unsigned>(child_filter), list[0].filter);
1598 EXPECT_CALL(*parent_context,
1599 bindTexture(GL_TEXTURE_2D, parent_texture_id));
1600 EXPECT_CALL(*parent_context, consumeTextureCHROMIUM(GL_TEXTURE_2D, _));
1601 parent_resource_provider->ReceiveFromChild(child_id, list);
1603 ResourceProvider::ScopedReadLockGL lock(parent_resource_provider.get(),
1606 Mock::VerifyAndClearExpectations(parent_context);
1608 parent_resource_provider->DeclareUsedResourcesFromChild(
1609 child_id, resource_ids_to_transfer);
1610 Mock::VerifyAndClearExpectations(parent_context);
1612 ResourceProvider::ResourceIdMap resource_map =
1613 parent_resource_provider->GetChildToParentMap(child_id);
1614 ResourceProvider::ResourceId mapped_id = resource_map[id];
1615 EXPECT_NE(0u, mapped_id);
1617 // The texture is set to |parent_filter| in the parent.
1618 EXPECT_CALL(*parent_context, bindTexture(GL_TEXTURE_2D, parent_texture_id));
1621 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, parent_filter));
1624 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, parent_filter));
1625 SetResourceFilter(parent_resource_provider.get(), mapped_id, parent_filter);
1626 Mock::VerifyAndClearExpectations(parent_context);
1628 // The texture should be reset to |child_filter| in the parent when it is
1629 // returned, since that is how it was received.
1630 EXPECT_CALL(*parent_context, bindTexture(GL_TEXTURE_2D, parent_texture_id));
1633 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, child_filter));
1636 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, child_filter));
1639 EXPECT_EQ(0u, returned_to_child.size());
1641 // Transfer resources back from the parent to the child. Set no resources
1643 ResourceProvider::ResourceIdArray no_resources;
1644 EXPECT_CALL(*parent_context, insertSyncPoint());
1645 parent_resource_provider->DeclareUsedResourcesFromChild(child_id,
1647 Mock::VerifyAndClearExpectations(parent_context);
1649 ASSERT_EQ(1u, returned_to_child.size());
1650 child_resource_provider->ReceiveReturnsFromParent(returned_to_child);
1653 // The child remembers the texture filter is set to |child_filter|.
1654 EXPECT_CALL(*child_context, bindTexture(GL_TEXTURE_2D, child_texture_id));
1655 SetResourceFilter(child_resource_provider.get(), id, child_filter);
1656 Mock::VerifyAndClearExpectations(child_context);
1660 TEST_P(ResourceProviderTest, TextureFilters_ChildNearestParentLinear) {
1661 if (GetParam() != ResourceProvider::GLTexture)
1663 ResourceProviderTestTextureFilters::RunTest(GL_NEAREST, GL_LINEAR);
1666 TEST_P(ResourceProviderTest, TextureFilters_ChildLinearParentNearest) {
1667 if (GetParam() != ResourceProvider::GLTexture)
1669 ResourceProviderTestTextureFilters::RunTest(GL_LINEAR, GL_NEAREST);
1672 TEST_P(ResourceProviderTest, TransferMailboxResources) {
1673 // Other mailbox transfers tested elsewhere.
1674 if (GetParam() != ResourceProvider::GLTexture)
1676 unsigned texture = context()->createTexture();
1677 context()->bindTexture(GL_TEXTURE_2D, texture);
1678 uint8_t data[4] = { 1, 2, 3, 4 };
1679 context()->texImage2D(
1680 GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, &data);
1681 gpu::Mailbox mailbox;
1682 context()->genMailboxCHROMIUM(mailbox.name);
1683 context()->produceTextureCHROMIUM(GL_TEXTURE_2D, mailbox.name);
1684 unsigned sync_point = context()->insertSyncPoint();
1686 // All the logic below assumes that the sync points are all positive.
1687 EXPECT_LT(0u, sync_point);
1689 unsigned release_sync_point = 0;
1690 bool lost_resource = false;
1691 ReleaseCallback callback =
1692 base::Bind(ReleaseTextureMailbox, &release_sync_point, &lost_resource);
1693 ResourceProvider::ResourceId resource =
1694 resource_provider_->CreateResourceFromTextureMailbox(
1695 TextureMailbox(mailbox, sync_point),
1696 SingleReleaseCallback::Create(callback));
1697 EXPECT_EQ(1u, context()->NumTextures());
1698 EXPECT_EQ(0u, release_sync_point);
1700 // Transfer the resource, expect the sync points to be consistent.
1701 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
1702 resource_ids_to_transfer.push_back(resource);
1703 TransferableResourceArray list;
1704 resource_provider_->PrepareSendToParent(resource_ids_to_transfer, &list);
1705 ASSERT_EQ(1u, list.size());
1706 EXPECT_LE(sync_point, list[0].sync_point);
1708 memcmp(mailbox.name, list[0].mailbox.name, sizeof(mailbox.name)));
1709 EXPECT_EQ(0u, release_sync_point);
1711 context()->waitSyncPoint(list[0].sync_point);
1712 unsigned other_texture = context()->createTexture();
1713 context()->bindTexture(GL_TEXTURE_2D, other_texture);
1714 context()->consumeTextureCHROMIUM(GL_TEXTURE_2D, mailbox.name);
1715 uint8_t test_data[4] = { 0 };
1716 context()->GetPixels(
1717 gfx::Size(1, 1), RGBA_8888, test_data);
1718 EXPECT_EQ(0, memcmp(data, test_data, sizeof(data)));
1719 context()->produceTextureCHROMIUM(GL_TEXTURE_2D, mailbox.name);
1720 context()->deleteTexture(other_texture);
1721 list[0].sync_point = context()->insertSyncPoint();
1722 EXPECT_LT(0u, list[0].sync_point);
1724 // Receive the resource, then delete it, expect the sync points to be
1726 ReturnedResourceArray returned;
1727 TransferableResource::ReturnResources(list, &returned);
1728 resource_provider_->ReceiveReturnsFromParent(returned);
1729 EXPECT_EQ(1u, context()->NumTextures());
1730 EXPECT_EQ(0u, release_sync_point);
1732 resource_provider_->DeleteResource(resource);
1733 EXPECT_LE(list[0].sync_point, release_sync_point);
1734 EXPECT_FALSE(lost_resource);
1737 // We're going to do the same thing as above, but testing the case where we
1738 // delete the resource before we receive it back.
1739 sync_point = release_sync_point;
1740 EXPECT_LT(0u, sync_point);
1741 release_sync_point = 0;
1742 resource = resource_provider_->CreateResourceFromTextureMailbox(
1743 TextureMailbox(mailbox, sync_point),
1744 SingleReleaseCallback::Create(callback));
1745 EXPECT_EQ(1u, context()->NumTextures());
1746 EXPECT_EQ(0u, release_sync_point);
1748 // Transfer the resource, expect the sync points to be consistent.
1749 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
1750 resource_ids_to_transfer.push_back(resource);
1751 TransferableResourceArray list;
1752 resource_provider_->PrepareSendToParent(resource_ids_to_transfer, &list);
1753 ASSERT_EQ(1u, list.size());
1754 EXPECT_LE(sync_point, list[0].sync_point);
1756 memcmp(mailbox.name, list[0].mailbox.name, sizeof(mailbox.name)));
1757 EXPECT_EQ(0u, release_sync_point);
1759 context()->waitSyncPoint(list[0].sync_point);
1760 unsigned other_texture = context()->createTexture();
1761 context()->bindTexture(GL_TEXTURE_2D, other_texture);
1762 context()->consumeTextureCHROMIUM(GL_TEXTURE_2D, mailbox.name);
1763 uint8_t test_data[4] = { 0 };
1764 context()->GetPixels(
1765 gfx::Size(1, 1), RGBA_8888, test_data);
1766 EXPECT_EQ(0, memcmp(data, test_data, sizeof(data)));
1767 context()->produceTextureCHROMIUM(GL_TEXTURE_2D, mailbox.name);
1768 context()->deleteTexture(other_texture);
1769 list[0].sync_point = context()->insertSyncPoint();
1770 EXPECT_LT(0u, list[0].sync_point);
1772 // Delete the resource, which shouldn't do anything.
1773 resource_provider_->DeleteResource(resource);
1774 EXPECT_EQ(1u, context()->NumTextures());
1775 EXPECT_EQ(0u, release_sync_point);
1777 // Then receive the resource which should release the mailbox, expect the
1778 // sync points to be consistent.
1779 ReturnedResourceArray returned;
1780 TransferableResource::ReturnResources(list, &returned);
1781 resource_provider_->ReceiveReturnsFromParent(returned);
1782 EXPECT_LE(list[0].sync_point, release_sync_point);
1783 EXPECT_FALSE(lost_resource);
1786 context()->waitSyncPoint(release_sync_point);
1787 context()->bindTexture(GL_TEXTURE_2D, texture);
1788 context()->consumeTextureCHROMIUM(GL_TEXTURE_2D, mailbox.name);
1789 context()->deleteTexture(texture);
1792 TEST_P(ResourceProviderTest, LostResourceInParent) {
1793 gfx::Size size(1, 1);
1794 ResourceFormat format = RGBA_8888;
1795 ResourceProvider::ResourceId resource =
1796 child_resource_provider_->CreateResource(
1797 size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureUsageAny, format);
1798 child_resource_provider_->AllocateForTesting(resource);
1799 // Expect a GL resource to be lost.
1800 bool should_lose_resource = GetParam() == ResourceProvider::GLTexture;
1802 ReturnedResourceArray returned_to_child;
1804 resource_provider_->CreateChild(GetReturnCallback(&returned_to_child));
1806 // Transfer the resource to the parent.
1807 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
1808 resource_ids_to_transfer.push_back(resource);
1809 TransferableResourceArray list;
1810 child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
1812 EXPECT_EQ(1u, list.size());
1814 resource_provider_->ReceiveFromChild(child_id, list);
1815 resource_provider_->DeclareUsedResourcesFromChild(child_id,
1816 resource_ids_to_transfer);
1819 // Lose the output surface in the parent.
1820 resource_provider_->DidLoseOutputSurface();
1823 EXPECT_EQ(0u, returned_to_child.size());
1825 // Transfer resources back from the parent to the child. Set no resources as
1827 ResourceProvider::ResourceIdArray no_resources;
1828 resource_provider_->DeclareUsedResourcesFromChild(child_id, no_resources);
1830 // Expect a GL resource to be lost.
1831 ASSERT_EQ(1u, returned_to_child.size());
1832 EXPECT_EQ(should_lose_resource, returned_to_child[0].lost);
1833 child_resource_provider_->ReceiveReturnsFromParent(returned_to_child);
1834 returned_to_child.clear();
1837 // A GL resource should be lost.
1838 EXPECT_EQ(should_lose_resource, child_resource_provider_->IsLost(resource));
1840 // Lost resources stay in use in the parent forever.
1841 EXPECT_EQ(should_lose_resource,
1842 child_resource_provider_->InUseByConsumer(resource));
1845 TEST_P(ResourceProviderTest, LostResourceInGrandParent) {
1846 gfx::Size size(1, 1);
1847 ResourceFormat format = RGBA_8888;
1848 ResourceProvider::ResourceId resource =
1849 child_resource_provider_->CreateResource(
1850 size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureUsageAny, format);
1851 child_resource_provider_->AllocateForTesting(resource);
1853 ReturnedResourceArray returned_to_child;
1855 resource_provider_->CreateChild(GetReturnCallback(&returned_to_child));
1857 // Transfer the resource to the parent.
1858 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
1859 resource_ids_to_transfer.push_back(resource);
1860 TransferableResourceArray list;
1861 child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
1863 EXPECT_EQ(1u, list.size());
1865 resource_provider_->ReceiveFromChild(child_id, list);
1866 resource_provider_->DeclareUsedResourcesFromChild(child_id,
1867 resource_ids_to_transfer);
1871 ResourceProvider::ResourceIdMap resource_map =
1872 resource_provider_->GetChildToParentMap(child_id);
1873 ResourceProvider::ResourceId parent_resource = resource_map[resource];
1874 EXPECT_NE(0u, parent_resource);
1876 // Transfer to a grandparent.
1877 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
1878 resource_ids_to_transfer.push_back(parent_resource);
1879 TransferableResourceArray list;
1880 resource_provider_->PrepareSendToParent(resource_ids_to_transfer, &list);
1882 // Receive back a lost resource from the grandparent.
1883 EXPECT_EQ(1u, list.size());
1884 EXPECT_EQ(parent_resource, list[0].id);
1885 ReturnedResourceArray returned;
1886 TransferableResource::ReturnResources(list, &returned);
1887 EXPECT_EQ(1u, returned.size());
1888 EXPECT_EQ(parent_resource, returned[0].id);
1889 returned[0].lost = true;
1890 resource_provider_->ReceiveReturnsFromParent(returned);
1892 // The resource should be lost.
1893 EXPECT_TRUE(resource_provider_->IsLost(parent_resource));
1895 // Lost resources stay in use in the parent forever.
1896 EXPECT_TRUE(resource_provider_->InUseByConsumer(parent_resource));
1900 EXPECT_EQ(0u, returned_to_child.size());
1902 // Transfer resources back from the parent to the child. Set no resources as
1904 ResourceProvider::ResourceIdArray no_resources;
1905 resource_provider_->DeclareUsedResourcesFromChild(child_id, no_resources);
1907 // Expect the resource to be lost.
1908 ASSERT_EQ(1u, returned_to_child.size());
1909 EXPECT_TRUE(returned_to_child[0].lost);
1910 child_resource_provider_->ReceiveReturnsFromParent(returned_to_child);
1911 returned_to_child.clear();
1914 // The resource should be lost.
1915 EXPECT_TRUE(child_resource_provider_->IsLost(resource));
1917 // Lost resources stay in use in the parent forever.
1918 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(resource));
1921 TEST_P(ResourceProviderTest, LostMailboxInParent) {
1922 unsigned release_sync_point = 0;
1923 bool lost_resource = false;
1924 bool release_called = false;
1925 unsigned sync_point = 0;
1926 ResourceProvider::ResourceId resource = CreateChildMailbox(
1927 &release_sync_point, &lost_resource, &release_called, &sync_point);
1929 ReturnedResourceArray returned_to_child;
1931 resource_provider_->CreateChild(GetReturnCallback(&returned_to_child));
1933 // Transfer the resource to the parent.
1934 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
1935 resource_ids_to_transfer.push_back(resource);
1936 TransferableResourceArray list;
1937 child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
1939 EXPECT_EQ(1u, list.size());
1941 resource_provider_->ReceiveFromChild(child_id, list);
1942 resource_provider_->DeclareUsedResourcesFromChild(child_id,
1943 resource_ids_to_transfer);
1946 // Lose the output surface in the parent.
1947 resource_provider_->DidLoseOutputSurface();
1950 EXPECT_EQ(0u, returned_to_child.size());
1952 // Transfer resources back from the parent to the child. Set no resources as
1954 ResourceProvider::ResourceIdArray no_resources;
1955 resource_provider_->DeclareUsedResourcesFromChild(child_id, no_resources);
1957 ASSERT_EQ(1u, returned_to_child.size());
1958 // Losing an output surface only loses hardware resources.
1959 EXPECT_EQ(returned_to_child[0].lost,
1960 GetParam() == ResourceProvider::GLTexture);
1961 child_resource_provider_->ReceiveReturnsFromParent(returned_to_child);
1962 returned_to_child.clear();
1965 // Delete the resource in the child. Expect the resource to be lost if it's
1967 child_resource_provider_->DeleteResource(resource);
1968 EXPECT_EQ(lost_resource, GetParam() == ResourceProvider::GLTexture);
1971 TEST_P(ResourceProviderTest, LostMailboxInGrandParent) {
1972 unsigned release_sync_point = 0;
1973 bool lost_resource = false;
1974 bool release_called = false;
1975 unsigned sync_point = 0;
1976 ResourceProvider::ResourceId resource = CreateChildMailbox(
1977 &release_sync_point, &lost_resource, &release_called, &sync_point);
1979 ReturnedResourceArray returned_to_child;
1981 resource_provider_->CreateChild(GetReturnCallback(&returned_to_child));
1983 // Transfer the resource to the parent.
1984 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
1985 resource_ids_to_transfer.push_back(resource);
1986 TransferableResourceArray list;
1987 child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
1989 EXPECT_EQ(1u, list.size());
1991 resource_provider_->ReceiveFromChild(child_id, list);
1992 resource_provider_->DeclareUsedResourcesFromChild(child_id,
1993 resource_ids_to_transfer);
1997 ResourceProvider::ResourceIdMap resource_map =
1998 resource_provider_->GetChildToParentMap(child_id);
1999 ResourceProvider::ResourceId parent_resource = resource_map[resource];
2000 EXPECT_NE(0u, parent_resource);
2002 // Transfer to a grandparent.
2003 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
2004 resource_ids_to_transfer.push_back(parent_resource);
2005 TransferableResourceArray list;
2006 resource_provider_->PrepareSendToParent(resource_ids_to_transfer, &list);
2008 // Receive back a lost resource from the grandparent.
2009 EXPECT_EQ(1u, list.size());
2010 EXPECT_EQ(parent_resource, list[0].id);
2011 ReturnedResourceArray returned;
2012 TransferableResource::ReturnResources(list, &returned);
2013 EXPECT_EQ(1u, returned.size());
2014 EXPECT_EQ(parent_resource, returned[0].id);
2015 returned[0].lost = true;
2016 resource_provider_->ReceiveReturnsFromParent(returned);
2020 EXPECT_EQ(0u, returned_to_child.size());
2022 // Transfer resources back from the parent to the child. Set no resources as
2024 ResourceProvider::ResourceIdArray no_resources;
2025 resource_provider_->DeclareUsedResourcesFromChild(child_id, no_resources);
2027 // Expect the resource to be lost.
2028 ASSERT_EQ(1u, returned_to_child.size());
2029 EXPECT_TRUE(returned_to_child[0].lost);
2030 child_resource_provider_->ReceiveReturnsFromParent(returned_to_child);
2031 returned_to_child.clear();
2034 // Delete the resource in the child. Expect the resource to be lost.
2035 child_resource_provider_->DeleteResource(resource);
2036 EXPECT_TRUE(lost_resource);
2039 TEST_P(ResourceProviderTest, Shutdown) {
2040 unsigned release_sync_point = 0;
2041 bool lost_resource = false;
2042 bool release_called = false;
2043 unsigned sync_point = 0;
2045 &release_sync_point, &lost_resource, &release_called, &sync_point);
2047 EXPECT_EQ(0u, release_sync_point);
2048 EXPECT_FALSE(lost_resource);
2050 child_resource_provider_.reset();
2052 if (GetParam() == ResourceProvider::GLTexture) {
2053 EXPECT_LE(sync_point, release_sync_point);
2055 EXPECT_TRUE(release_called);
2056 EXPECT_FALSE(lost_resource);
2059 TEST_P(ResourceProviderTest, ShutdownWithExportedResource) {
2060 unsigned release_sync_point = 0;
2061 bool lost_resource = false;
2062 bool release_called = false;
2063 unsigned sync_point = 0;
2064 ResourceProvider::ResourceId resource = CreateChildMailbox(
2065 &release_sync_point, &lost_resource, &release_called, &sync_point);
2067 // Transfer the resource, so we can't release it properly on shutdown.
2068 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
2069 resource_ids_to_transfer.push_back(resource);
2070 TransferableResourceArray list;
2071 child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
2074 EXPECT_EQ(0u, release_sync_point);
2075 EXPECT_FALSE(lost_resource);
2077 child_resource_provider_.reset();
2079 // Since the resource is in the parent, the child considers it lost.
2080 EXPECT_EQ(0u, release_sync_point);
2081 EXPECT_TRUE(lost_resource);
2084 TEST_P(ResourceProviderTest, LostContext) {
2085 // TextureMailbox callbacks only exist for GL textures for now.
2086 if (GetParam() != ResourceProvider::GLTexture)
2088 unsigned texture = context()->createTexture();
2089 context()->bindTexture(GL_TEXTURE_2D, texture);
2090 gpu::Mailbox mailbox;
2091 context()->genMailboxCHROMIUM(mailbox.name);
2092 context()->produceTextureCHROMIUM(GL_TEXTURE_2D, mailbox.name);
2093 unsigned sync_point = context()->insertSyncPoint();
2095 EXPECT_LT(0u, sync_point);
2097 unsigned release_sync_point = 0;
2098 bool lost_resource = false;
2099 scoped_ptr<SingleReleaseCallback> callback = SingleReleaseCallback::Create(
2100 base::Bind(ReleaseTextureMailbox, &release_sync_point, &lost_resource));
2101 resource_provider_->CreateResourceFromTextureMailbox(
2102 TextureMailbox(mailbox, sync_point),
2105 EXPECT_EQ(0u, release_sync_point);
2106 EXPECT_FALSE(lost_resource);
2108 resource_provider_->DidLoseOutputSurface();
2109 resource_provider_.reset();
2111 EXPECT_LE(sync_point, release_sync_point);
2112 EXPECT_TRUE(lost_resource);
2115 TEST_P(ResourceProviderTest, ScopedSampler) {
2116 // Sampling is only supported for GL textures.
2117 if (GetParam() != ResourceProvider::GLTexture)
2120 scoped_ptr<TextureStateTrackingContext> context_owned(
2121 new TextureStateTrackingContext);
2122 TextureStateTrackingContext* context = context_owned.get();
2124 FakeOutputSurfaceClient output_surface_client;
2125 scoped_ptr<OutputSurface> output_surface(FakeOutputSurface::Create3d(
2126 context_owned.PassAs<TestWebGraphicsContext3D>()));
2127 CHECK(output_surface->BindToClient(&output_surface_client));
2129 scoped_ptr<ResourceProvider> resource_provider(
2130 ResourceProvider::Create(output_surface.get(), NULL, 0, false, 1));
2132 gfx::Size size(1, 1);
2133 ResourceFormat format = RGBA_8888;
2136 ResourceProvider::ResourceId id = resource_provider->CreateResource(
2137 size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureUsageAny, format);
2139 // Check that the texture gets created with the right sampler settings.
2140 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id))
2141 .Times(2); // Once to create and once to allocate.
2142 EXPECT_CALL(*context,
2143 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
2144 EXPECT_CALL(*context,
2145 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR));
2148 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE));
2151 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE));
2152 EXPECT_CALL(*context,
2153 texParameteri(GL_TEXTURE_2D,
2154 GL_TEXTURE_POOL_CHROMIUM,
2155 GL_TEXTURE_POOL_UNMANAGED_CHROMIUM));
2157 resource_provider->AllocateForTesting(id);
2158 Mock::VerifyAndClearExpectations(context);
2160 // Creating a sampler with the default filter should not change any texture
2163 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id));
2164 ResourceProvider::ScopedSamplerGL sampler(
2165 resource_provider.get(), id, GL_TEXTURE_2D, GL_LINEAR);
2166 Mock::VerifyAndClearExpectations(context);
2169 // Using a different filter should be reflected in the texture parameters.
2171 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id));
2174 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST));
2177 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST));
2178 ResourceProvider::ScopedSamplerGL sampler(
2179 resource_provider.get(), id, GL_TEXTURE_2D, GL_NEAREST);
2180 Mock::VerifyAndClearExpectations(context);
2183 // Test resetting to the default filter.
2185 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id));
2186 EXPECT_CALL(*context,
2187 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
2188 EXPECT_CALL(*context,
2189 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR));
2190 ResourceProvider::ScopedSamplerGL sampler(
2191 resource_provider.get(), id, GL_TEXTURE_2D, GL_LINEAR);
2192 Mock::VerifyAndClearExpectations(context);
2196 TEST_P(ResourceProviderTest, ManagedResource) {
2197 // Sampling is only supported for GL textures.
2198 if (GetParam() != ResourceProvider::GLTexture)
2201 scoped_ptr<TextureStateTrackingContext> context_owned(
2202 new TextureStateTrackingContext);
2203 TextureStateTrackingContext* context = context_owned.get();
2205 FakeOutputSurfaceClient output_surface_client;
2206 scoped_ptr<OutputSurface> output_surface(FakeOutputSurface::Create3d(
2207 context_owned.PassAs<TestWebGraphicsContext3D>()));
2208 CHECK(output_surface->BindToClient(&output_surface_client));
2210 scoped_ptr<ResourceProvider> resource_provider(
2211 ResourceProvider::Create(output_surface.get(), NULL, 0, false, 1));
2213 gfx::Size size(1, 1);
2214 ResourceFormat format = RGBA_8888;
2217 // Check that the texture gets created with the right sampler settings.
2218 ResourceProvider::ResourceId id = resource_provider->CreateManagedResource(
2222 ResourceProvider::TextureUsageAny,
2224 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id));
2225 EXPECT_CALL(*context,
2226 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
2227 EXPECT_CALL(*context,
2228 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR));
2231 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE));
2234 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE));
2235 EXPECT_CALL(*context,
2236 texParameteri(GL_TEXTURE_2D,
2237 GL_TEXTURE_POOL_CHROMIUM,
2238 GL_TEXTURE_POOL_MANAGED_CHROMIUM));
2239 resource_provider->CreateForTesting(id);
2242 Mock::VerifyAndClearExpectations(context);
2245 TEST_P(ResourceProviderTest, TextureWrapMode) {
2246 // Sampling is only supported for GL textures.
2247 if (GetParam() != ResourceProvider::GLTexture)
2250 scoped_ptr<TextureStateTrackingContext> context_owned(
2251 new TextureStateTrackingContext);
2252 TextureStateTrackingContext* context = context_owned.get();
2254 FakeOutputSurfaceClient output_surface_client;
2255 scoped_ptr<OutputSurface> output_surface(FakeOutputSurface::Create3d(
2256 context_owned.PassAs<TestWebGraphicsContext3D>()));
2257 CHECK(output_surface->BindToClient(&output_surface_client));
2259 scoped_ptr<ResourceProvider> resource_provider(
2260 ResourceProvider::Create(output_surface.get(), NULL, 0, false, 1));
2262 gfx::Size size(1, 1);
2263 ResourceFormat format = RGBA_8888;
2264 GLenum texture_pool = GL_TEXTURE_POOL_UNMANAGED_CHROMIUM;
2266 for (int texture_id = 1; texture_id <= 2; ++texture_id) {
2267 GLint wrap_mode = texture_id == 1 ? GL_CLAMP_TO_EDGE : GL_REPEAT;
2268 // Check that the texture gets created with the right sampler settings.
2269 ResourceProvider::ResourceId id =
2270 resource_provider->CreateGLTexture(size,
2274 ResourceProvider::TextureUsageAny,
2276 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id));
2277 EXPECT_CALL(*context,
2278 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
2279 EXPECT_CALL(*context,
2280 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR));
2283 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, wrap_mode));
2286 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, wrap_mode));
2287 EXPECT_CALL(*context,
2288 texParameteri(GL_TEXTURE_2D,
2289 GL_TEXTURE_POOL_CHROMIUM,
2290 GL_TEXTURE_POOL_UNMANAGED_CHROMIUM));
2291 resource_provider->CreateForTesting(id);
2294 Mock::VerifyAndClearExpectations(context);
2298 TEST_P(ResourceProviderTest, TextureMailbox_SharedMemory) {
2299 if (GetParam() != ResourceProvider::Bitmap)
2302 gfx::Size size(64, 64);
2303 const uint32_t kBadBeef = 0xbadbeef;
2304 scoped_ptr<base::SharedMemory> shared_memory(
2305 CreateAndFillSharedMemory(size, kBadBeef));
2307 FakeOutputSurfaceClient output_surface_client;
2308 scoped_ptr<OutputSurface> output_surface(
2309 FakeOutputSurface::CreateSoftware(make_scoped_ptr(
2310 new SoftwareOutputDevice)));
2311 CHECK(output_surface->BindToClient(&output_surface_client));
2313 scoped_ptr<ResourceProvider> resource_provider(
2314 ResourceProvider::Create(output_surface.get(), NULL, 0, false, 1));
2316 scoped_ptr<SingleReleaseCallback> callback = SingleReleaseCallback::Create(
2317 base::Bind(&EmptyReleaseCallback));
2318 TextureMailbox mailbox(shared_memory.get(), size);
2320 ResourceProvider::ResourceId id =
2321 resource_provider->CreateResourceFromTextureMailbox(
2322 mailbox, callback.Pass());
2326 ResourceProvider::ScopedReadLockSoftware lock(resource_provider.get(), id);
2327 const SkBitmap* sk_bitmap = lock.sk_bitmap();
2328 EXPECT_EQ(sk_bitmap->width(), size.width());
2329 EXPECT_EQ(sk_bitmap->height(), size.height());
2330 EXPECT_EQ(*sk_bitmap->getAddr32(16, 16), kBadBeef);
2334 TEST_P(ResourceProviderTest, TextureMailbox_GLTexture2D) {
2335 // Mailboxing is only supported for GL textures.
2336 if (GetParam() != ResourceProvider::GLTexture)
2339 scoped_ptr<TextureStateTrackingContext> context_owned(
2340 new TextureStateTrackingContext);
2341 TextureStateTrackingContext* context = context_owned.get();
2343 FakeOutputSurfaceClient output_surface_client;
2344 scoped_ptr<OutputSurface> output_surface(FakeOutputSurface::Create3d(
2345 context_owned.PassAs<TestWebGraphicsContext3D>()));
2346 CHECK(output_surface->BindToClient(&output_surface_client));
2348 scoped_ptr<ResourceProvider> resource_provider(
2349 ResourceProvider::Create(output_surface.get(), NULL, 0, false, 1));
2351 unsigned texture_id = 1;
2352 unsigned sync_point = 30;
2353 unsigned target = GL_TEXTURE_2D;
2355 EXPECT_CALL(*context, bindTexture(_, _)).Times(0);
2356 EXPECT_CALL(*context, waitSyncPoint(_)).Times(0);
2357 EXPECT_CALL(*context, insertSyncPoint()).Times(0);
2358 EXPECT_CALL(*context, produceTextureCHROMIUM(_, _)).Times(0);
2359 EXPECT_CALL(*context, consumeTextureCHROMIUM(_, _)).Times(0);
2361 gpu::Mailbox gpu_mailbox;
2362 memcpy(gpu_mailbox.name, "Hello world", strlen("Hello world") + 1);
2363 scoped_ptr<SingleReleaseCallback> callback = SingleReleaseCallback::Create(
2364 base::Bind(&EmptyReleaseCallback));
2366 TextureMailbox mailbox(gpu_mailbox, sync_point);
2368 ResourceProvider::ResourceId id =
2369 resource_provider->CreateResourceFromTextureMailbox(
2370 mailbox, callback.Pass());
2373 Mock::VerifyAndClearExpectations(context);
2376 // Using the texture does a consume of the mailbox.
2377 EXPECT_CALL(*context, bindTexture(target, texture_id));
2378 EXPECT_CALL(*context, waitSyncPoint(sync_point));
2379 EXPECT_CALL(*context, consumeTextureCHROMIUM(target, _));
2381 EXPECT_CALL(*context, insertSyncPoint()).Times(0);
2382 EXPECT_CALL(*context, produceTextureCHROMIUM(_, _)).Times(0);
2384 ResourceProvider::ScopedReadLockGL lock(resource_provider.get(), id);
2385 Mock::VerifyAndClearExpectations(context);
2387 // When done with it, a sync point should be inserted, but no produce is
2389 EXPECT_CALL(*context, bindTexture(_, _)).Times(0);
2390 EXPECT_CALL(*context, insertSyncPoint());
2391 EXPECT_CALL(*context, produceTextureCHROMIUM(_, _)).Times(0);
2393 EXPECT_CALL(*context, waitSyncPoint(_)).Times(0);
2394 EXPECT_CALL(*context, consumeTextureCHROMIUM(_, _)).Times(0);
2398 TEST_P(ResourceProviderTest, TextureMailbox_GLTextureExternalOES) {
2399 // Mailboxing is only supported for GL textures.
2400 if (GetParam() != ResourceProvider::GLTexture)
2403 scoped_ptr<TextureStateTrackingContext> context_owned(
2404 new TextureStateTrackingContext);
2405 TextureStateTrackingContext* context = context_owned.get();
2407 FakeOutputSurfaceClient output_surface_client;
2408 scoped_ptr<OutputSurface> output_surface(FakeOutputSurface::Create3d(
2409 context_owned.PassAs<TestWebGraphicsContext3D>()));
2410 CHECK(output_surface->BindToClient(&output_surface_client));
2412 scoped_ptr<ResourceProvider> resource_provider(
2413 ResourceProvider::Create(output_surface.get(), NULL, 0, false, 1));
2415 unsigned texture_id = 1;
2416 unsigned sync_point = 30;
2417 unsigned target = GL_TEXTURE_EXTERNAL_OES;
2419 EXPECT_CALL(*context, bindTexture(_, _)).Times(0);
2420 EXPECT_CALL(*context, waitSyncPoint(_)).Times(0);
2421 EXPECT_CALL(*context, insertSyncPoint()).Times(0);
2422 EXPECT_CALL(*context, produceTextureCHROMIUM(_, _)).Times(0);
2423 EXPECT_CALL(*context, consumeTextureCHROMIUM(_, _)).Times(0);
2425 gpu::Mailbox gpu_mailbox;
2426 memcpy(gpu_mailbox.name, "Hello world", strlen("Hello world") + 1);
2427 scoped_ptr<SingleReleaseCallback> callback = SingleReleaseCallback::Create(
2428 base::Bind(&EmptyReleaseCallback));
2430 TextureMailbox mailbox(gpu_mailbox, target, sync_point);
2432 ResourceProvider::ResourceId id =
2433 resource_provider->CreateResourceFromTextureMailbox(
2434 mailbox, callback.Pass());
2437 Mock::VerifyAndClearExpectations(context);
2440 // Using the texture does a consume of the mailbox.
2441 EXPECT_CALL(*context, bindTexture(target, texture_id));
2442 EXPECT_CALL(*context, waitSyncPoint(sync_point));
2443 EXPECT_CALL(*context, consumeTextureCHROMIUM(target, _));
2445 EXPECT_CALL(*context, insertSyncPoint()).Times(0);
2446 EXPECT_CALL(*context, produceTextureCHROMIUM(_, _)).Times(0);
2448 ResourceProvider::ScopedReadLockGL lock(resource_provider.get(), id);
2449 Mock::VerifyAndClearExpectations(context);
2451 // When done with it, a sync point should be inserted, but no produce is
2453 EXPECT_CALL(*context, bindTexture(_, _)).Times(0);
2454 EXPECT_CALL(*context, insertSyncPoint());
2455 EXPECT_CALL(*context, produceTextureCHROMIUM(_, _)).Times(0);
2457 EXPECT_CALL(*context, waitSyncPoint(_)).Times(0);
2458 EXPECT_CALL(*context, consumeTextureCHROMIUM(_, _)).Times(0);
2462 class AllocationTrackingContext3D : public TestWebGraphicsContext3D {
2464 MOCK_METHOD0(NextTextureId, GLuint());
2465 MOCK_METHOD1(RetireTextureId, void(GLuint id));
2466 MOCK_METHOD2(bindTexture, void(GLenum target, GLuint texture));
2467 MOCK_METHOD5(texStorage2DEXT,
2470 GLuint internalformat,
2473 MOCK_METHOD9(texImage2D,
2476 GLenum internalformat,
2482 const void* pixels));
2483 MOCK_METHOD9(texSubImage2D,
2492 const void* pixels));
2493 MOCK_METHOD9(asyncTexImage2DCHROMIUM,
2496 GLenum internalformat,
2502 const void* pixels));
2503 MOCK_METHOD9(asyncTexSubImage2DCHROMIUM,
2512 const void* pixels));
2513 MOCK_METHOD8(compressedTexImage2D,
2516 GLenum internalformat,
2522 MOCK_METHOD1(waitAsyncTexImage2DCHROMIUM, void(GLenum));
2523 MOCK_METHOD3(createImageCHROMIUM, GLuint(GLsizei, GLsizei, GLenum));
2524 MOCK_METHOD1(destroyImageCHROMIUM, void(GLuint));
2525 MOCK_METHOD2(mapImageCHROMIUM, void*(GLuint, GLenum));
2526 MOCK_METHOD3(getImageParameterivCHROMIUM, void(GLuint, GLenum, GLint*));
2527 MOCK_METHOD1(unmapImageCHROMIUM, void(GLuint));
2528 MOCK_METHOD2(bindTexImage2DCHROMIUM, void(GLenum, GLint));
2529 MOCK_METHOD2(releaseTexImage2DCHROMIUM, void(GLenum, GLint));
2531 // We're mocking bindTexture, so we override
2532 // TestWebGraphicsContext3D::texParameteri to avoid assertions related to the
2533 // currently bound texture.
2534 virtual void texParameteri(GLenum target, GLenum pname, GLint param) {}
2537 TEST_P(ResourceProviderTest, TextureAllocation) {
2538 // Only for GL textures.
2539 if (GetParam() != ResourceProvider::GLTexture)
2541 scoped_ptr<AllocationTrackingContext3D> context_owned(
2542 new StrictMock<AllocationTrackingContext3D>);
2543 AllocationTrackingContext3D* context = context_owned.get();
2545 FakeOutputSurfaceClient output_surface_client;
2546 scoped_ptr<OutputSurface> output_surface(FakeOutputSurface::Create3d(
2547 context_owned.PassAs<TestWebGraphicsContext3D>()));
2548 CHECK(output_surface->BindToClient(&output_surface_client));
2550 scoped_ptr<ResourceProvider> resource_provider(
2551 ResourceProvider::Create(output_surface.get(), NULL, 0, false, 1));
2553 gfx::Size size(2, 2);
2554 gfx::Vector2d offset(0, 0);
2555 gfx::Rect rect(0, 0, 2, 2);
2556 ResourceFormat format = RGBA_8888;
2557 ResourceProvider::ResourceId id = 0;
2558 uint8_t pixels[16] = { 0 };
2559 int texture_id = 123;
2561 // Lazy allocation. Don't allocate when creating the resource.
2562 id = resource_provider->CreateResource(
2563 size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureUsageAny, format);
2565 EXPECT_CALL(*context, NextTextureId()).WillOnce(Return(texture_id));
2566 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id)).Times(1);
2567 resource_provider->CreateForTesting(id);
2569 EXPECT_CALL(*context, RetireTextureId(texture_id)).Times(1);
2570 resource_provider->DeleteResource(id);
2572 Mock::VerifyAndClearExpectations(context);
2574 // Do allocate when we set the pixels.
2575 id = resource_provider->CreateResource(
2576 size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureUsageAny, format);
2578 EXPECT_CALL(*context, NextTextureId()).WillOnce(Return(texture_id));
2579 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id)).Times(3);
2580 EXPECT_CALL(*context, texImage2D(_, _, _, 2, 2, _, _, _, _)).Times(1);
2581 EXPECT_CALL(*context, texSubImage2D(_, _, _, _, 2, 2, _, _, _)).Times(1);
2582 resource_provider->SetPixels(id, pixels, rect, rect, offset);
2584 EXPECT_CALL(*context, RetireTextureId(texture_id)).Times(1);
2585 resource_provider->DeleteResource(id);
2587 Mock::VerifyAndClearExpectations(context);
2589 // Same for async version.
2590 id = resource_provider->CreateResource(
2591 size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureUsageAny, format);
2592 resource_provider->AcquirePixelBuffer(id);
2594 EXPECT_CALL(*context, NextTextureId()).WillOnce(Return(texture_id));
2595 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id)).Times(2);
2596 EXPECT_CALL(*context, asyncTexImage2DCHROMIUM(_, _, _, 2, 2, _, _, _, _))
2598 resource_provider->BeginSetPixels(id);
2599 ASSERT_TRUE(resource_provider->DidSetPixelsComplete(id));
2601 resource_provider->ReleasePixelBuffer(id);
2603 EXPECT_CALL(*context, RetireTextureId(texture_id)).Times(1);
2604 resource_provider->DeleteResource(id);
2606 Mock::VerifyAndClearExpectations(context);
2609 TEST_P(ResourceProviderTest, TextureAllocationStorageUsageAny) {
2610 // Only for GL textures.
2611 if (GetParam() != ResourceProvider::GLTexture)
2613 scoped_ptr<AllocationTrackingContext3D> context_owned(
2614 new StrictMock<AllocationTrackingContext3D>);
2615 AllocationTrackingContext3D* context = context_owned.get();
2616 context->set_support_texture_storage(true);
2618 FakeOutputSurfaceClient output_surface_client;
2619 scoped_ptr<OutputSurface> output_surface(FakeOutputSurface::Create3d(
2620 context_owned.PassAs<TestWebGraphicsContext3D>()));
2621 CHECK(output_surface->BindToClient(&output_surface_client));
2623 scoped_ptr<ResourceProvider> resource_provider(
2624 ResourceProvider::Create(output_surface.get(), NULL, 0, false, 1));
2626 gfx::Size size(2, 2);
2627 ResourceFormat format = RGBA_8888;
2628 ResourceProvider::ResourceId id = 0;
2629 int texture_id = 123;
2631 // Lazy allocation. Don't allocate when creating the resource.
2632 id = resource_provider->CreateResource(
2633 size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureUsageAny, format);
2635 EXPECT_CALL(*context, NextTextureId()).WillOnce(Return(texture_id));
2636 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id)).Times(2);
2637 EXPECT_CALL(*context, texStorage2DEXT(_, _, _, 2, 2)).Times(1);
2638 resource_provider->AllocateForTesting(id);
2640 EXPECT_CALL(*context, RetireTextureId(texture_id)).Times(1);
2641 resource_provider->DeleteResource(id);
2643 Mock::VerifyAndClearExpectations(context);
2646 TEST_P(ResourceProviderTest, TextureAllocationStorageUsageFramebuffer) {
2647 // Only for GL textures.
2648 if (GetParam() != ResourceProvider::GLTexture)
2650 scoped_ptr<AllocationTrackingContext3D> context_owned(
2651 new StrictMock<AllocationTrackingContext3D>);
2652 AllocationTrackingContext3D* context = context_owned.get();
2653 context->set_support_texture_storage(true);
2655 FakeOutputSurfaceClient output_surface_client;
2656 scoped_ptr<OutputSurface> output_surface(FakeOutputSurface::Create3d(
2657 context_owned.PassAs<TestWebGraphicsContext3D>()));
2658 CHECK(output_surface->BindToClient(&output_surface_client));
2660 scoped_ptr<ResourceProvider> resource_provider(
2661 ResourceProvider::Create(output_surface.get(), NULL, 0, false, 1));
2663 gfx::Size size(2, 2);
2664 ResourceFormat format = RGBA_8888;
2665 ResourceProvider::ResourceId id = 0;
2666 int texture_id = 123;
2668 // Lazy allocation. Don't allocate when creating the resource.
2669 id = resource_provider->CreateResource(
2672 ResourceProvider::TextureUsageFramebuffer,
2675 EXPECT_CALL(*context, NextTextureId()).WillOnce(Return(texture_id));
2676 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id)).Times(2);
2677 EXPECT_CALL(*context, texImage2D(_, _, _, 2, 2, _, _, _, _)).Times(1);
2678 resource_provider->AllocateForTesting(id);
2680 EXPECT_CALL(*context, RetireTextureId(texture_id)).Times(1);
2681 resource_provider->DeleteResource(id);
2683 Mock::VerifyAndClearExpectations(context);
2686 TEST_P(ResourceProviderTest, PixelBuffer_GLTexture) {
2687 if (GetParam() != ResourceProvider::GLTexture)
2689 scoped_ptr<AllocationTrackingContext3D> context_owned(
2690 new StrictMock<AllocationTrackingContext3D>);
2691 AllocationTrackingContext3D* context = context_owned.get();
2693 FakeOutputSurfaceClient output_surface_client;
2694 scoped_ptr<OutputSurface> output_surface(FakeOutputSurface::Create3d(
2695 context_owned.PassAs<TestWebGraphicsContext3D>()));
2696 CHECK(output_surface->BindToClient(&output_surface_client));
2698 gfx::Size size(2, 2);
2699 ResourceFormat format = RGBA_8888;
2700 ResourceProvider::ResourceId id = 0;
2701 int texture_id = 123;
2703 scoped_ptr<ResourceProvider> resource_provider(
2704 ResourceProvider::Create(output_surface.get(), NULL, 0, false, 1));
2706 id = resource_provider->CreateResource(
2707 size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureUsageAny, format);
2708 resource_provider->AcquirePixelBuffer(id);
2710 EXPECT_CALL(*context, NextTextureId()).WillOnce(Return(texture_id));
2711 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id)).Times(2);
2712 EXPECT_CALL(*context, asyncTexImage2DCHROMIUM(_, _, _, 2, 2, _, _, _, _))
2714 resource_provider->BeginSetPixels(id);
2716 EXPECT_TRUE(resource_provider->DidSetPixelsComplete(id));
2718 resource_provider->ReleasePixelBuffer(id);
2720 EXPECT_CALL(*context, RetireTextureId(texture_id)).Times(1);
2721 resource_provider->DeleteResource(id);
2723 Mock::VerifyAndClearExpectations(context);
2726 TEST_P(ResourceProviderTest, PixelBuffer_Bitmap) {
2727 if (GetParam() != ResourceProvider::Bitmap)
2729 FakeOutputSurfaceClient output_surface_client;
2730 scoped_ptr<OutputSurface> output_surface(
2731 FakeOutputSurface::CreateSoftware(make_scoped_ptr(
2732 new SoftwareOutputDevice)));
2733 CHECK(output_surface->BindToClient(&output_surface_client));
2735 gfx::Size size(1, 1);
2736 ResourceFormat format = RGBA_8888;
2737 ResourceProvider::ResourceId id = 0;
2738 const uint32_t kBadBeef = 0xbadbeef;
2740 scoped_ptr<ResourceProvider> resource_provider(
2741 ResourceProvider::Create(output_surface.get(), NULL, 0, false, 1));
2743 id = resource_provider->CreateResource(
2744 size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureUsageAny, format);
2745 resource_provider->AcquirePixelBuffer(id);
2747 void* data = resource_provider->MapPixelBuffer(id);
2748 ASSERT_TRUE(!!data);
2749 memcpy(data, &kBadBeef, sizeof(kBadBeef));
2750 resource_provider->UnmapPixelBuffer(id);
2752 resource_provider->BeginSetPixels(id);
2753 EXPECT_TRUE(resource_provider->DidSetPixelsComplete(id));
2755 resource_provider->ReleasePixelBuffer(id);
2758 ResourceProvider::ScopedReadLockSoftware lock(resource_provider.get(), id);
2759 const SkBitmap* sk_bitmap = lock.sk_bitmap();
2760 EXPECT_EQ(sk_bitmap->width(), size.width());
2761 EXPECT_EQ(sk_bitmap->height(), size.height());
2762 EXPECT_EQ(*sk_bitmap->getAddr32(0, 0), kBadBeef);
2765 resource_provider->DeleteResource(id);
2768 TEST_P(ResourceProviderTest, ForcingAsyncUploadToComplete) {
2769 // Only for GL textures.
2770 if (GetParam() != ResourceProvider::GLTexture)
2772 scoped_ptr<AllocationTrackingContext3D> context_owned(
2773 new StrictMock<AllocationTrackingContext3D>);
2774 AllocationTrackingContext3D* context = context_owned.get();
2776 FakeOutputSurfaceClient output_surface_client;
2777 scoped_ptr<OutputSurface> output_surface(FakeOutputSurface::Create3d(
2778 context_owned.PassAs<TestWebGraphicsContext3D>()));
2779 CHECK(output_surface->BindToClient(&output_surface_client));
2781 gfx::Size size(2, 2);
2782 ResourceFormat format = RGBA_8888;
2783 ResourceProvider::ResourceId id = 0;
2784 int texture_id = 123;
2786 scoped_ptr<ResourceProvider> resource_provider(
2787 ResourceProvider::Create(output_surface.get(), NULL, 0, false, 1));
2789 id = resource_provider->CreateResource(
2790 size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureUsageAny, format);
2791 resource_provider->AcquirePixelBuffer(id);
2793 EXPECT_CALL(*context, NextTextureId()).WillOnce(Return(texture_id));
2794 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id)).Times(2);
2795 EXPECT_CALL(*context, asyncTexImage2DCHROMIUM(_, _, _, 2, 2, _, _, _, _))
2797 resource_provider->BeginSetPixels(id);
2799 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id)).Times(1);
2800 EXPECT_CALL(*context, waitAsyncTexImage2DCHROMIUM(GL_TEXTURE_2D)).Times(1);
2801 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, 0)).Times(1);
2802 resource_provider->ForceSetPixelsToComplete(id);
2804 resource_provider->ReleasePixelBuffer(id);
2806 EXPECT_CALL(*context, RetireTextureId(texture_id)).Times(1);
2807 resource_provider->DeleteResource(id);
2809 Mock::VerifyAndClearExpectations(context);
2812 TEST_P(ResourceProviderTest, PixelBufferLostContext) {
2813 scoped_ptr<AllocationTrackingContext3D> context_owned(
2814 new NiceMock<AllocationTrackingContext3D>);
2815 AllocationTrackingContext3D* context = context_owned.get();
2817 FakeOutputSurfaceClient output_surface_client;
2818 scoped_ptr<OutputSurface> output_surface(FakeOutputSurface::Create3d(
2819 context_owned.PassAs<TestWebGraphicsContext3D>()));
2820 CHECK(output_surface->BindToClient(&output_surface_client));
2822 gfx::Size size(2, 2);
2823 ResourceFormat format = RGBA_8888;
2824 ResourceProvider::ResourceId id = 0;
2825 int texture_id = 123;
2827 scoped_ptr<ResourceProvider> resource_provider(
2828 ResourceProvider::Create(output_surface.get(), NULL, 0, false, 1));
2830 EXPECT_CALL(*context, NextTextureId()).WillRepeatedly(Return(texture_id));
2832 id = resource_provider->CreateResource(
2833 size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureUsageAny, format);
2834 context->loseContextCHROMIUM(GL_GUILTY_CONTEXT_RESET_ARB,
2835 GL_INNOCENT_CONTEXT_RESET_ARB);
2836 resource_provider->AcquirePixelBuffer(id);
2837 uint8_t* buffer = resource_provider->MapPixelBuffer(id);
2838 EXPECT_TRUE(buffer == NULL);
2839 resource_provider->UnmapPixelBuffer(id);
2840 resource_provider->ReleasePixelBuffer(id);
2841 Mock::VerifyAndClearExpectations(context);
2844 TEST_P(ResourceProviderTest, Image_GLTexture) {
2845 // Only for GL textures.
2846 if (GetParam() != ResourceProvider::GLTexture)
2848 scoped_ptr<AllocationTrackingContext3D> context_owned(
2849 new StrictMock<AllocationTrackingContext3D>);
2850 AllocationTrackingContext3D* context = context_owned.get();
2852 FakeOutputSurfaceClient output_surface_client;
2853 scoped_ptr<OutputSurface> output_surface(FakeOutputSurface::Create3d(
2854 context_owned.PassAs<TestWebGraphicsContext3D>()));
2855 CHECK(output_surface->BindToClient(&output_surface_client));
2857 const int kWidth = 2;
2858 const int kHeight = 2;
2859 gfx::Size size(kWidth, kHeight);
2860 ResourceFormat format = RGBA_8888;
2861 ResourceProvider::ResourceId id = 0;
2862 const unsigned kTextureId = 123u;
2863 const unsigned kImageId = 234u;
2865 scoped_ptr<ResourceProvider> resource_provider(
2866 ResourceProvider::Create(output_surface.get(), NULL, 0, false, 1));
2868 id = resource_provider->CreateResource(
2869 size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureUsageAny, format);
2870 EXPECT_CALL(*context, createImageCHROMIUM(kWidth, kHeight, GL_RGBA8_OES))
2871 .WillOnce(Return(kImageId))
2872 .RetiresOnSaturation();
2873 resource_provider->AcquireImage(id);
2875 void* dummy_mapped_buffer_address = NULL;
2876 EXPECT_CALL(*context, mapImageCHROMIUM(kImageId, GL_READ_WRITE))
2877 .WillOnce(Return(dummy_mapped_buffer_address))
2878 .RetiresOnSaturation();
2879 resource_provider->MapImage(id);
2881 const int kStride = 4;
2882 EXPECT_CALL(*context, getImageParameterivCHROMIUM(kImageId,
2883 GL_IMAGE_ROWBYTES_CHROMIUM,
2885 .WillOnce(SetArgPointee<2>(kStride))
2886 .RetiresOnSaturation();
2887 int stride = resource_provider->GetImageStride(id);
2888 EXPECT_EQ(kStride, stride);
2890 EXPECT_CALL(*context, unmapImageCHROMIUM(kImageId))
2892 .RetiresOnSaturation();
2893 resource_provider->UnmapImage(id);
2895 EXPECT_CALL(*context, NextTextureId())
2896 .WillOnce(Return(kTextureId))
2897 .RetiresOnSaturation();
2898 // Once in CreateTextureId and once in BindForSampling
2899 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, kTextureId)).Times(2)
2900 .RetiresOnSaturation();
2901 EXPECT_CALL(*context, bindTexImage2DCHROMIUM(GL_TEXTURE_2D, kImageId))
2903 .RetiresOnSaturation();
2905 ResourceProvider::ScopedSamplerGL lock_gl(
2906 resource_provider.get(), id, GL_TEXTURE_2D, GL_LINEAR);
2907 EXPECT_EQ(kTextureId, lock_gl.texture_id());
2910 EXPECT_CALL(*context, mapImageCHROMIUM(kImageId, GL_READ_WRITE))
2911 .WillOnce(Return(dummy_mapped_buffer_address))
2912 .RetiresOnSaturation();
2913 resource_provider->MapImage(id);
2915 EXPECT_CALL(*context, unmapImageCHROMIUM(kImageId))
2917 .RetiresOnSaturation();
2918 resource_provider->UnmapImage(id);
2920 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, kTextureId)).Times(1)
2921 .RetiresOnSaturation();
2922 EXPECT_CALL(*context, releaseTexImage2DCHROMIUM(GL_TEXTURE_2D, kImageId))
2924 .RetiresOnSaturation();
2925 EXPECT_CALL(*context, bindTexImage2DCHROMIUM(GL_TEXTURE_2D, kImageId))
2927 .RetiresOnSaturation();
2928 EXPECT_CALL(*context, RetireTextureId(kTextureId))
2930 .RetiresOnSaturation();
2932 ResourceProvider::ScopedSamplerGL lock_gl(
2933 resource_provider.get(), id, GL_TEXTURE_2D, GL_LINEAR);
2934 EXPECT_EQ(kTextureId, lock_gl.texture_id());
2937 EXPECT_CALL(*context, destroyImageCHROMIUM(kImageId))
2939 .RetiresOnSaturation();
2940 resource_provider->ReleaseImage(id);
2943 TEST_P(ResourceProviderTest, Image_Bitmap) {
2944 if (GetParam() != ResourceProvider::Bitmap)
2946 FakeOutputSurfaceClient output_surface_client;
2947 scoped_ptr<OutputSurface> output_surface(
2948 FakeOutputSurface::CreateSoftware(make_scoped_ptr(
2949 new SoftwareOutputDevice)));
2950 CHECK(output_surface->BindToClient(&output_surface_client));
2952 gfx::Size size(1, 1);
2953 ResourceFormat format = RGBA_8888;
2954 ResourceProvider::ResourceId id = 0;
2955 const uint32_t kBadBeef = 0xbadbeef;
2957 scoped_ptr<ResourceProvider> resource_provider(
2958 ResourceProvider::Create(output_surface.get(), NULL, 0, false, 1));
2960 id = resource_provider->CreateResource(
2961 size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureUsageAny, format);
2962 resource_provider->AcquireImage(id);
2964 const int kStride = 0;
2965 int stride = resource_provider->GetImageStride(id);
2966 EXPECT_EQ(kStride, stride);
2968 void* data = resource_provider->MapImage(id);
2969 ASSERT_TRUE(!!data);
2970 memcpy(data, &kBadBeef, sizeof(kBadBeef));
2971 resource_provider->UnmapImage(id);
2974 ResourceProvider::ScopedReadLockSoftware lock(resource_provider.get(), id);
2975 const SkBitmap* sk_bitmap = lock.sk_bitmap();
2976 EXPECT_EQ(sk_bitmap->width(), size.width());
2977 EXPECT_EQ(sk_bitmap->height(), size.height());
2978 EXPECT_EQ(*sk_bitmap->getAddr32(0, 0), kBadBeef);
2981 resource_provider->ReleaseImage(id);
2982 resource_provider->DeleteResource(id);
2985 void InitializeGLAndCheck(ContextSharedData* shared_data,
2986 ResourceProvider* resource_provider,
2987 FakeOutputSurface* output_surface) {
2988 scoped_ptr<ResourceProviderContext> context_owned =
2989 ResourceProviderContext::Create(shared_data);
2990 ResourceProviderContext* context = context_owned.get();
2992 scoped_refptr<TestContextProvider> context_provider =
2993 TestContextProvider::Create(
2994 context_owned.PassAs<TestWebGraphicsContext3D>());
2995 output_surface->InitializeAndSetContext3d(context_provider, NULL);
2996 EXPECT_TRUE(resource_provider->InitializeGL());
2998 CheckCreateResource(ResourceProvider::GLTexture, resource_provider, context);
3001 TEST(ResourceProviderTest, BasicInitializeGLSoftware) {
3002 scoped_ptr<ContextSharedData> shared_data = ContextSharedData::Create();
3003 FakeOutputSurfaceClient client;
3004 scoped_ptr<FakeOutputSurface> output_surface(
3005 FakeOutputSurface::CreateDeferredGL(
3006 scoped_ptr<SoftwareOutputDevice>(new SoftwareOutputDevice)));
3007 EXPECT_TRUE(output_surface->BindToClient(&client));
3008 scoped_ptr<ResourceProvider> resource_provider(
3009 ResourceProvider::Create(output_surface.get(), NULL, 0, false, 1));
3011 CheckCreateResource(ResourceProvider::Bitmap, resource_provider.get(), NULL);
3013 InitializeGLAndCheck(shared_data.get(),
3014 resource_provider.get(),
3015 output_surface.get());
3017 resource_provider->InitializeSoftware();
3018 output_surface->ReleaseGL();
3019 CheckCreateResource(ResourceProvider::Bitmap, resource_provider.get(), NULL);
3021 InitializeGLAndCheck(shared_data.get(),
3022 resource_provider.get(),
3023 output_surface.get());
3026 TEST_P(ResourceProviderTest, CompressedTextureETC1Allocate) {
3027 if (GetParam() != ResourceProvider::GLTexture)
3030 scoped_ptr<AllocationTrackingContext3D> context_owned(
3031 new AllocationTrackingContext3D);
3032 AllocationTrackingContext3D* context = context_owned.get();
3033 context_owned->set_support_compressed_texture_etc1(true);
3035 FakeOutputSurfaceClient output_surface_client;
3036 scoped_ptr<OutputSurface> output_surface(FakeOutputSurface::Create3d(
3037 context_owned.PassAs<TestWebGraphicsContext3D>()));
3038 CHECK(output_surface->BindToClient(&output_surface_client));
3040 gfx::Size size(4, 4);
3041 scoped_ptr<ResourceProvider> resource_provider(
3042 ResourceProvider::Create(output_surface.get(),
3043 shared_bitmap_manager_.get(),
3047 int texture_id = 123;
3049 ResourceProvider::ResourceId id = resource_provider->CreateResource(
3050 size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureUsageAny, ETC1);
3052 EXPECT_CALL(*context, NextTextureId()).WillOnce(Return(texture_id));
3053 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id)).Times(2);
3054 resource_provider->AllocateForTesting(id);
3056 EXPECT_CALL(*context, RetireTextureId(texture_id)).Times(1);
3057 resource_provider->DeleteResource(id);
3060 TEST_P(ResourceProviderTest, CompressedTextureETC1SetPixels) {
3061 if (GetParam() != ResourceProvider::GLTexture)
3064 scoped_ptr<AllocationTrackingContext3D> context_owned(
3065 new AllocationTrackingContext3D);
3066 AllocationTrackingContext3D* context = context_owned.get();
3067 context_owned->set_support_compressed_texture_etc1(true);
3069 FakeOutputSurfaceClient output_surface_client;
3070 scoped_ptr<OutputSurface> output_surface(FakeOutputSurface::Create3d(
3071 context_owned.PassAs<TestWebGraphicsContext3D>()));
3072 CHECK(output_surface->BindToClient(&output_surface_client));
3074 gfx::Size size(4, 4);
3075 scoped_ptr<ResourceProvider> resource_provider(
3076 ResourceProvider::Create(output_surface.get(),
3077 shared_bitmap_manager_.get(),
3081 int texture_id = 123;
3084 ResourceProvider::ResourceId id = resource_provider->CreateResource(
3085 size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureUsageAny, ETC1);
3087 EXPECT_CALL(*context, NextTextureId()).WillOnce(Return(texture_id));
3088 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id)).Times(3);
3089 EXPECT_CALL(*context,
3090 compressedTexImage2D(
3091 _, 0, _, size.width(), size.height(), _, _, _)).Times(1);
3092 resource_provider->SetPixels(
3093 id, pixels, gfx::Rect(size), gfx::Rect(size), gfx::Vector2d(0, 0));
3095 EXPECT_CALL(*context, RetireTextureId(texture_id)).Times(1);
3096 resource_provider->DeleteResource(id);
3099 INSTANTIATE_TEST_CASE_P(
3100 ResourceProviderTests,
3101 ResourceProviderTest,
3102 ::testing::Values(ResourceProvider::GLTexture, ResourceProvider::Bitmap));
3104 class TextureIdAllocationTrackingContext : public TestWebGraphicsContext3D {
3106 virtual GLuint NextTextureId() OVERRIDE {
3107 base::AutoLock lock(namespace_->lock);
3108 return namespace_->next_texture_id++;
3110 virtual void RetireTextureId(GLuint) OVERRIDE {}
3111 GLuint PeekTextureId() {
3112 base::AutoLock lock(namespace_->lock);
3113 return namespace_->next_texture_id;
3117 TEST(ResourceProviderTest, TextureAllocationChunkSize) {
3118 scoped_ptr<TextureIdAllocationTrackingContext> context_owned(
3119 new TextureIdAllocationTrackingContext);
3120 TextureIdAllocationTrackingContext* context = context_owned.get();
3122 FakeOutputSurfaceClient output_surface_client;
3123 scoped_ptr<OutputSurface> output_surface(FakeOutputSurface::Create3d(
3124 context_owned.PassAs<TestWebGraphicsContext3D>()));
3125 CHECK(output_surface->BindToClient(&output_surface_client));
3127 gfx::Size size(1, 1);
3128 ResourceFormat format = RGBA_8888;
3131 size_t kTextureAllocationChunkSize = 1;
3132 scoped_ptr<ResourceProvider> resource_provider(
3133 ResourceProvider::Create(output_surface.get(),
3137 kTextureAllocationChunkSize));
3139 ResourceProvider::ResourceId id = resource_provider->CreateResource(
3140 size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureUsageAny, format);
3141 resource_provider->AllocateForTesting(id);
3142 Mock::VerifyAndClearExpectations(context);
3144 DCHECK_EQ(2u, context->PeekTextureId());
3145 resource_provider->DeleteResource(id);
3149 size_t kTextureAllocationChunkSize = 8;
3150 scoped_ptr<ResourceProvider> resource_provider(
3151 ResourceProvider::Create(output_surface.get(),
3155 kTextureAllocationChunkSize));
3157 ResourceProvider::ResourceId id = resource_provider->CreateResource(
3158 size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureUsageAny, format);
3159 resource_provider->AllocateForTesting(id);
3160 Mock::VerifyAndClearExpectations(context);
3162 DCHECK_EQ(10u, context->PeekTextureId());
3163 resource_provider->DeleteResource(id);