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"
11 #include "base/bind.h"
12 #include "base/containers/hash_tables.h"
13 #include "base/logging.h"
14 #include "base/memory/ref_counted.h"
15 #include "cc/base/scoped_ptr_deque.h"
16 #include "cc/output/output_surface.h"
17 #include "cc/resources/returned_resource.h"
18 #include "cc/resources/shared_bitmap_manager.h"
19 #include "cc/resources/single_release_callback.h"
20 #include "cc/test/fake_output_surface.h"
21 #include "cc/test/fake_output_surface_client.h"
22 #include "cc/test/test_shared_bitmap_manager.h"
23 #include "cc/test/test_texture.h"
24 #include "cc/test/test_web_graphics_context_3d.h"
25 #include "cc/trees/blocking_task_runner.h"
26 #include "gpu/GLES2/gl2extchromium.h"
27 #include "testing/gmock/include/gmock/gmock.h"
28 #include "testing/gtest/include/gtest/gtest.h"
29 #include "third_party/khronos/GLES2/gl2.h"
30 #include "third_party/khronos/GLES2/gl2ext.h"
31 #include "ui/gfx/rect.h"
34 using testing::NiceMock;
35 using testing::Return;
36 using testing::SetArgPointee;
37 using testing::StrictMock;
43 static void EmptyReleaseCallback(uint32 sync_point,
45 BlockingTaskRunner* main_thread_task_runner) {
48 static void ReleaseCallback(
49 uint32* release_sync_point,
50 bool* release_lost_resource,
51 BlockingTaskRunner** release_main_thread_task_runner,
54 BlockingTaskRunner* main_thread_task_runner) {
55 *release_sync_point = sync_point;
56 *release_lost_resource = lost_resource;
57 *release_main_thread_task_runner = main_thread_task_runner;
60 static void SharedMemoryReleaseCallback(
61 scoped_ptr<base::SharedMemory> memory,
64 BlockingTaskRunner* main_thread_task_runner) {
67 static void ReleaseSharedMemoryCallback(
68 scoped_ptr<base::SharedMemory> shared_memory,
70 uint32* release_sync_point,
71 bool* lost_resource_result,
74 BlockingTaskRunner* main_thread_task_runner) {
75 *release_called = true;
76 *release_sync_point = sync_point;
77 *lost_resource_result = lost_resource;
80 static scoped_ptr<base::SharedMemory> CreateAndFillSharedMemory(
81 const gfx::Size& size,
83 scoped_ptr<base::SharedMemory> shared_memory(new base::SharedMemory);
84 CHECK(shared_memory->CreateAndMapAnonymous(4 * size.GetArea()));
85 uint32_t* pixels = reinterpret_cast<uint32_t*>(shared_memory->memory());
87 std::fill_n(pixels, size.GetArea(), value);
88 return shared_memory.Pass();
91 class TextureStateTrackingContext : public TestWebGraphicsContext3D {
93 MOCK_METHOD2(bindTexture, void(GLenum target, GLuint texture));
94 MOCK_METHOD3(texParameteri, void(GLenum target, GLenum pname, GLint param));
95 MOCK_METHOD1(waitSyncPoint, void(GLuint sync_point));
96 MOCK_METHOD0(insertSyncPoint, GLuint(void));
97 MOCK_METHOD2(produceTextureCHROMIUM,
98 void(GLenum target, const GLbyte* mailbox));
99 MOCK_METHOD2(consumeTextureCHROMIUM,
100 void(GLenum target, const GLbyte* mailbox));
102 // Force all textures to be consecutive numbers starting at "1",
103 // so we easily can test for them.
104 virtual GLuint NextTextureId() OVERRIDE {
105 base::AutoLock lock(namespace_->lock);
106 return namespace_->next_texture_id++;
108 virtual void RetireTextureId(GLuint) OVERRIDE {}
111 // Shared data between multiple ResourceProviderContext. This contains mailbox
112 // contents as well as information about sync points.
113 class ContextSharedData {
115 static scoped_ptr<ContextSharedData> Create() {
116 return make_scoped_ptr(new ContextSharedData());
119 uint32 InsertSyncPoint() { return next_sync_point_++; }
121 void GenMailbox(GLbyte* mailbox) {
122 memset(mailbox, 0, GL_MAILBOX_SIZE_CHROMIUM);
123 memcpy(mailbox, &next_mailbox_, sizeof(next_mailbox_));
127 void ProduceTexture(const GLbyte* mailbox_name,
129 scoped_refptr<TestTexture> texture) {
130 unsigned mailbox = 0;
131 memcpy(&mailbox, mailbox_name, sizeof(mailbox));
132 ASSERT_TRUE(mailbox && mailbox < next_mailbox_);
133 textures_[mailbox] = texture;
134 ASSERT_LT(sync_point_for_mailbox_[mailbox], sync_point);
135 sync_point_for_mailbox_[mailbox] = sync_point;
138 scoped_refptr<TestTexture> ConsumeTexture(const GLbyte* mailbox_name,
140 unsigned mailbox = 0;
141 memcpy(&mailbox, mailbox_name, sizeof(mailbox));
142 DCHECK(mailbox && mailbox < next_mailbox_);
144 // If the latest sync point the context has waited on is before the sync
145 // point for when the mailbox was set, pretend we never saw that
147 if (sync_point_for_mailbox_[mailbox] > sync_point) {
149 return scoped_refptr<TestTexture>();
151 return textures_[mailbox];
155 ContextSharedData() : next_sync_point_(1), next_mailbox_(1) {}
157 uint32 next_sync_point_;
158 unsigned next_mailbox_;
159 typedef base::hash_map<unsigned, scoped_refptr<TestTexture> > TextureMap;
160 TextureMap textures_;
161 base::hash_map<unsigned, uint32> sync_point_for_mailbox_;
164 class ResourceProviderContext : public TestWebGraphicsContext3D {
166 static scoped_ptr<ResourceProviderContext> Create(
167 ContextSharedData* shared_data) {
168 return make_scoped_ptr(new ResourceProviderContext(shared_data));
171 virtual GLuint insertSyncPoint() OVERRIDE {
172 uint32 sync_point = shared_data_->InsertSyncPoint();
173 // Commit the produceTextureCHROMIUM calls at this point, so that
174 // they're associated with the sync point.
175 for (PendingProduceTextureList::iterator it =
176 pending_produce_textures_.begin();
177 it != pending_produce_textures_.end();
179 shared_data_->ProduceTexture(
180 (*it)->mailbox, sync_point, (*it)->texture);
182 pending_produce_textures_.clear();
186 virtual void waitSyncPoint(GLuint sync_point) OVERRIDE {
187 last_waited_sync_point_ = std::max(sync_point, last_waited_sync_point_);
190 unsigned last_waited_sync_point() const { return last_waited_sync_point_; }
192 virtual void texStorage2DEXT(GLenum target,
194 GLuint internalformat,
196 GLint height) OVERRIDE {
197 CheckTextureIsBound(target);
198 ASSERT_EQ(static_cast<unsigned>(GL_TEXTURE_2D), target);
199 ASSERT_EQ(1, levels);
200 GLenum format = GL_RGBA;
201 switch (internalformat) {
205 format = GL_BGRA_EXT;
210 AllocateTexture(gfx::Size(width, height), format);
213 virtual void texImage2D(GLenum target,
215 GLenum internalformat,
221 const void* pixels) OVERRIDE {
222 CheckTextureIsBound(target);
223 ASSERT_EQ(static_cast<unsigned>(GL_TEXTURE_2D), target);
225 ASSERT_EQ(internalformat, format);
226 ASSERT_FALSE(border);
227 ASSERT_EQ(static_cast<unsigned>(GL_UNSIGNED_BYTE), type);
228 AllocateTexture(gfx::Size(width, height), format);
230 SetPixels(0, 0, width, height, pixels);
233 virtual void texSubImage2D(GLenum target,
241 const void* pixels) OVERRIDE {
242 CheckTextureIsBound(target);
243 ASSERT_EQ(static_cast<unsigned>(GL_TEXTURE_2D), target);
245 ASSERT_EQ(static_cast<unsigned>(GL_UNSIGNED_BYTE), type);
247 base::AutoLock lock_for_texture_access(namespace_->lock);
248 ASSERT_EQ(GLDataFormat(BoundTexture(target)->format), format);
251 SetPixels(xoffset, yoffset, width, height, pixels);
254 virtual void genMailboxCHROMIUM(GLbyte* mailbox) OVERRIDE {
255 return shared_data_->GenMailbox(mailbox);
258 virtual void produceTextureCHROMIUM(GLenum target,
259 const GLbyte* mailbox) OVERRIDE {
260 CheckTextureIsBound(target);
262 // Delay moving the texture into the mailbox until the next
263 // InsertSyncPoint, so that it is not visible to other contexts that
264 // haven't waited on that sync point.
265 scoped_ptr<PendingProduceTexture> pending(new PendingProduceTexture);
266 memcpy(pending->mailbox, mailbox, sizeof(pending->mailbox));
267 base::AutoLock lock_for_texture_access(namespace_->lock);
268 pending->texture = BoundTexture(target);
269 pending_produce_textures_.push_back(pending.Pass());
272 virtual void consumeTextureCHROMIUM(GLenum target,
273 const GLbyte* mailbox) OVERRIDE {
274 CheckTextureIsBound(target);
275 base::AutoLock lock_for_texture_access(namespace_->lock);
276 scoped_refptr<TestTexture> texture =
277 shared_data_->ConsumeTexture(mailbox, last_waited_sync_point_);
278 namespace_->textures.Replace(BoundTextureId(target), texture);
281 void GetPixels(const gfx::Size& size,
282 ResourceFormat format,
284 CheckTextureIsBound(GL_TEXTURE_2D);
285 base::AutoLock lock_for_texture_access(namespace_->lock);
286 scoped_refptr<TestTexture> texture = BoundTexture(GL_TEXTURE_2D);
287 ASSERT_EQ(texture->size, size);
288 ASSERT_EQ(texture->format, format);
289 memcpy(pixels, texture->data.get(), TextureSizeBytes(size, format));
293 explicit ResourceProviderContext(ContextSharedData* shared_data)
294 : shared_data_(shared_data),
295 last_waited_sync_point_(0) {}
298 void AllocateTexture(const gfx::Size& size, GLenum format) {
299 CheckTextureIsBound(GL_TEXTURE_2D);
300 ResourceFormat texture_format = RGBA_8888;
303 texture_format = RGBA_8888;
306 texture_format = BGRA_8888;
309 base::AutoLock lock_for_texture_access(namespace_->lock);
310 BoundTexture(GL_TEXTURE_2D)->Reallocate(size, texture_format);
313 void SetPixels(int xoffset,
317 const void* pixels) {
318 CheckTextureIsBound(GL_TEXTURE_2D);
319 base::AutoLock lock_for_texture_access(namespace_->lock);
320 scoped_refptr<TestTexture> texture = BoundTexture(GL_TEXTURE_2D);
321 ASSERT_TRUE(texture->data.get());
322 ASSERT_TRUE(xoffset >= 0 && xoffset + width <= texture->size.width());
323 ASSERT_TRUE(yoffset >= 0 && yoffset + height <= texture->size.height());
325 size_t in_pitch = TextureSizeBytes(gfx::Size(width, 1), texture->format);
327 TextureSizeBytes(gfx::Size(texture->size.width(), 1), texture->format);
328 uint8_t* dest = texture->data.get() + yoffset * out_pitch +
329 TextureSizeBytes(gfx::Size(xoffset, 1), texture->format);
330 const uint8_t* src = static_cast<const uint8_t*>(pixels);
331 for (int i = 0; i < height; ++i) {
332 memcpy(dest, src, in_pitch);
338 struct PendingProduceTexture {
339 GLbyte mailbox[GL_MAILBOX_SIZE_CHROMIUM];
340 scoped_refptr<TestTexture> texture;
342 typedef ScopedPtrDeque<PendingProduceTexture> PendingProduceTextureList;
343 ContextSharedData* shared_data_;
344 GLuint last_waited_sync_point_;
345 PendingProduceTextureList pending_produce_textures_;
348 void GetResourcePixels(ResourceProvider* resource_provider,
349 ResourceProviderContext* context,
350 ResourceProvider::ResourceId id,
351 const gfx::Size& size,
352 ResourceFormat format,
354 resource_provider->WaitSyncPointIfNeeded(id);
355 switch (resource_provider->default_resource_type()) {
356 case ResourceProvider::GLTexture: {
357 ResourceProvider::ScopedReadLockGL lock_gl(resource_provider, id);
358 ASSERT_NE(0U, lock_gl.texture_id());
359 context->bindTexture(GL_TEXTURE_2D, lock_gl.texture_id());
360 context->GetPixels(size, format, pixels);
363 case ResourceProvider::Bitmap: {
364 ResourceProvider::ScopedReadLockSoftware lock_software(resource_provider,
367 lock_software.sk_bitmap()->getPixels(),
368 lock_software.sk_bitmap()->getSize());
371 case ResourceProvider::InvalidType:
377 class ResourceProviderTest
378 : public testing::TestWithParam<ResourceProvider::ResourceType> {
380 ResourceProviderTest()
381 : shared_data_(ContextSharedData::Create()),
383 child_context_(NULL),
384 main_thread_task_runner_(BlockingTaskRunner::Create(NULL)) {
385 switch (GetParam()) {
386 case ResourceProvider::GLTexture: {
387 scoped_ptr<ResourceProviderContext> context3d(
388 ResourceProviderContext::Create(shared_data_.get()));
389 context3d_ = context3d.get();
391 scoped_refptr<TestContextProvider> context_provider =
392 TestContextProvider::Create(
393 context3d.PassAs<TestWebGraphicsContext3D>());
395 output_surface_ = FakeOutputSurface::Create3d(context_provider);
397 scoped_ptr<ResourceProviderContext> child_context_owned =
398 ResourceProviderContext::Create(shared_data_.get());
399 child_context_ = child_context_owned.get();
400 child_output_surface_ = FakeOutputSurface::Create3d(
401 child_context_owned.PassAs<TestWebGraphicsContext3D>());
404 case ResourceProvider::Bitmap:
405 output_surface_ = FakeOutputSurface::CreateSoftware(
406 make_scoped_ptr(new SoftwareOutputDevice));
407 child_output_surface_ = FakeOutputSurface::CreateSoftware(
408 make_scoped_ptr(new SoftwareOutputDevice));
410 case ResourceProvider::InvalidType:
414 CHECK(output_surface_->BindToClient(&output_surface_client_));
415 CHECK(child_output_surface_->BindToClient(&child_output_surface_client_));
417 shared_bitmap_manager_.reset(new TestSharedBitmapManager());
420 ResourceProvider::Create(output_surface_.get(),
421 shared_bitmap_manager_.get(),
422 main_thread_task_runner_.get(),
427 child_resource_provider_ =
428 ResourceProvider::Create(child_output_surface_.get(),
429 shared_bitmap_manager_.get(),
430 main_thread_task_runner_.get(),
437 static void CollectResources(ReturnedResourceArray* array,
438 const ReturnedResourceArray& returned,
439 BlockingTaskRunner* main_thread_task_runner) {
440 array->insert(array->end(), returned.begin(), returned.end());
443 static ReturnCallback GetReturnCallback(ReturnedResourceArray* array) {
444 return base::Bind(&ResourceProviderTest::CollectResources, array);
447 static void SetResourceFilter(ResourceProvider* resource_provider,
448 ResourceProvider::ResourceId id,
450 ResourceProvider::ScopedSamplerGL sampler(
451 resource_provider, id, GL_TEXTURE_2D, filter);
454 ResourceProviderContext* context() { return context3d_; }
456 ResourceProvider::ResourceId CreateChildMailbox(uint32* release_sync_point,
458 bool* release_called,
459 uint32* sync_point) {
460 if (GetParam() == ResourceProvider::GLTexture) {
461 unsigned texture = child_context_->createTexture();
462 gpu::Mailbox gpu_mailbox;
463 child_context_->bindTexture(GL_TEXTURE_2D, texture);
464 child_context_->genMailboxCHROMIUM(gpu_mailbox.name);
465 child_context_->produceTextureCHROMIUM(GL_TEXTURE_2D, gpu_mailbox.name);
466 *sync_point = child_context_->insertSyncPoint();
467 EXPECT_LT(0u, *sync_point);
469 scoped_ptr<base::SharedMemory> shared_memory;
470 scoped_ptr<SingleReleaseCallbackImpl> callback =
471 SingleReleaseCallbackImpl::Create(
472 base::Bind(ReleaseSharedMemoryCallback,
473 base::Passed(&shared_memory),
477 return child_resource_provider_->CreateResourceFromTextureMailbox(
478 TextureMailbox(gpu_mailbox, GL_TEXTURE_2D, *sync_point),
481 gfx::Size size(64, 64);
482 scoped_ptr<base::SharedMemory> shared_memory(
483 CreateAndFillSharedMemory(size, 0));
485 base::SharedMemory* shared_memory_ptr = shared_memory.get();
486 scoped_ptr<SingleReleaseCallbackImpl> callback =
487 SingleReleaseCallbackImpl::Create(
488 base::Bind(ReleaseSharedMemoryCallback,
489 base::Passed(&shared_memory),
493 return child_resource_provider_->CreateResourceFromTextureMailbox(
494 TextureMailbox(shared_memory_ptr, size), callback.Pass());
499 scoped_ptr<ContextSharedData> shared_data_;
500 ResourceProviderContext* context3d_;
501 ResourceProviderContext* child_context_;
502 FakeOutputSurfaceClient output_surface_client_;
503 FakeOutputSurfaceClient child_output_surface_client_;
504 scoped_ptr<OutputSurface> output_surface_;
505 scoped_ptr<OutputSurface> child_output_surface_;
506 scoped_ptr<BlockingTaskRunner> main_thread_task_runner_;
507 scoped_ptr<ResourceProvider> resource_provider_;
508 scoped_ptr<ResourceProvider> child_resource_provider_;
509 scoped_ptr<TestSharedBitmapManager> shared_bitmap_manager_;
512 void CheckCreateResource(ResourceProvider::ResourceType expected_default_type,
513 ResourceProvider* resource_provider,
514 ResourceProviderContext* context) {
515 DCHECK_EQ(expected_default_type, resource_provider->default_resource_type());
517 gfx::Size size(1, 1);
518 ResourceFormat format = RGBA_8888;
519 size_t pixel_size = TextureSizeBytes(size, format);
520 ASSERT_EQ(4U, pixel_size);
522 ResourceProvider::ResourceId id = resource_provider->CreateResource(
523 size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureHintImmutable, format);
524 EXPECT_EQ(1, static_cast<int>(resource_provider->num_resources()));
525 if (expected_default_type == ResourceProvider::GLTexture)
526 EXPECT_EQ(0u, context->NumTextures());
528 uint8_t data[4] = { 1, 2, 3, 4 };
529 gfx::Rect rect(size);
530 resource_provider->SetPixels(id, data, rect, rect, gfx::Vector2d());
531 if (expected_default_type == ResourceProvider::GLTexture)
532 EXPECT_EQ(1u, context->NumTextures());
534 uint8_t result[4] = { 0 };
535 GetResourcePixels(resource_provider, context, id, size, format, result);
536 EXPECT_EQ(0, memcmp(data, result, pixel_size));
538 resource_provider->DeleteResource(id);
539 EXPECT_EQ(0, static_cast<int>(resource_provider->num_resources()));
540 if (expected_default_type == ResourceProvider::GLTexture)
541 EXPECT_EQ(0u, context->NumTextures());
544 TEST_P(ResourceProviderTest, Basic) {
545 CheckCreateResource(GetParam(), resource_provider_.get(), context());
548 TEST_P(ResourceProviderTest, Upload) {
549 gfx::Size size(2, 2);
550 ResourceFormat format = RGBA_8888;
551 size_t pixel_size = TextureSizeBytes(size, format);
552 ASSERT_EQ(16U, pixel_size);
554 ResourceProvider::ResourceId id = resource_provider_->CreateResource(
555 size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureHintImmutable, format);
557 uint8_t image[16] = { 0 };
558 gfx::Rect image_rect(size);
559 resource_provider_->SetPixels(
560 id, image, image_rect, image_rect, gfx::Vector2d());
562 for (uint8_t i = 0; i < pixel_size; ++i)
565 uint8_t result[16] = { 0 };
567 gfx::Rect source_rect(0, 0, 1, 1);
568 gfx::Vector2d dest_offset(0, 0);
569 resource_provider_->SetPixels(
570 id, image, image_rect, source_rect, dest_offset);
572 uint8_t expected[16] = { 0, 1, 2, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
574 resource_provider_.get(), context(), id, size, format, result);
575 EXPECT_EQ(0, memcmp(expected, result, pixel_size));
578 gfx::Rect source_rect(0, 0, 1, 1);
579 gfx::Vector2d dest_offset(1, 1);
580 resource_provider_->SetPixels(
581 id, image, image_rect, source_rect, dest_offset);
583 uint8_t expected[16] = { 0, 1, 2, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3 };
585 resource_provider_.get(), context(), id, size, format, result);
586 EXPECT_EQ(0, memcmp(expected, result, pixel_size));
589 gfx::Rect source_rect(1, 0, 1, 1);
590 gfx::Vector2d dest_offset(0, 1);
591 resource_provider_->SetPixels(
592 id, image, image_rect, source_rect, dest_offset);
594 uint8_t expected[16] = { 0, 1, 2, 3, 0, 0, 0, 0, 4, 5, 6, 7, 0, 1, 2, 3 };
596 resource_provider_.get(), context(), id, size, format, result);
597 EXPECT_EQ(0, memcmp(expected, result, pixel_size));
600 gfx::Rect offset_image_rect(gfx::Point(100, 100), size);
601 gfx::Rect source_rect(100, 100, 1, 1);
602 gfx::Vector2d dest_offset(1, 0);
603 resource_provider_->SetPixels(
604 id, image, offset_image_rect, source_rect, dest_offset);
606 uint8_t expected[16] = { 0, 1, 2, 3, 0, 1, 2, 3, 4, 5, 6, 7, 0, 1, 2, 3 };
608 resource_provider_.get(), context(), id, size, format, result);
609 EXPECT_EQ(0, memcmp(expected, result, pixel_size));
612 resource_provider_->DeleteResource(id);
615 TEST_P(ResourceProviderTest, TransferGLResources) {
616 if (GetParam() != ResourceProvider::GLTexture)
618 gfx::Size size(1, 1);
619 ResourceFormat format = RGBA_8888;
620 size_t pixel_size = TextureSizeBytes(size, format);
621 ASSERT_EQ(4U, pixel_size);
623 ResourceProvider::ResourceId id1 = child_resource_provider_->CreateResource(
624 size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureHintImmutable, format);
625 uint8_t data1[4] = { 1, 2, 3, 4 };
626 gfx::Rect rect(size);
627 child_resource_provider_->SetPixels(id1, data1, rect, rect, gfx::Vector2d());
629 ResourceProvider::ResourceId id2 = child_resource_provider_->CreateResource(
630 size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureHintImmutable, format);
631 uint8_t data2[4] = { 5, 5, 5, 5 };
632 child_resource_provider_->SetPixels(id2, data2, rect, rect, gfx::Vector2d());
634 ResourceProvider::ResourceId id3 = child_resource_provider_->CreateResource(
635 size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureHintImmutable, format);
636 child_resource_provider_->AcquireImage(id3);
638 child_resource_provider_->MapImage(id3, &stride);
639 child_resource_provider_->UnmapImage(id3);
641 GLuint external_texture_id = child_context_->createExternalTexture();
642 child_context_->bindTexture(GL_TEXTURE_EXTERNAL_OES, external_texture_id);
644 gpu::Mailbox external_mailbox;
645 child_context_->genMailboxCHROMIUM(external_mailbox.name);
646 child_context_->produceTextureCHROMIUM(GL_TEXTURE_EXTERNAL_OES,
647 external_mailbox.name);
648 const GLuint external_sync_point = child_context_->insertSyncPoint();
649 ResourceProvider::ResourceId id4 =
650 child_resource_provider_->CreateResourceFromTextureMailbox(
652 external_mailbox, GL_TEXTURE_EXTERNAL_OES, external_sync_point),
653 SingleReleaseCallbackImpl::Create(base::Bind(&EmptyReleaseCallback)));
655 ReturnedResourceArray returned_to_child;
657 resource_provider_->CreateChild(GetReturnCallback(&returned_to_child));
659 // Transfer some resources to the parent.
660 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
661 resource_ids_to_transfer.push_back(id1);
662 resource_ids_to_transfer.push_back(id2);
663 resource_ids_to_transfer.push_back(id3);
664 resource_ids_to_transfer.push_back(id4);
665 TransferableResourceArray list;
666 child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
668 ASSERT_EQ(4u, list.size());
669 EXPECT_NE(0u, list[0].mailbox_holder.sync_point);
670 EXPECT_NE(0u, list[1].mailbox_holder.sync_point);
671 EXPECT_EQ(list[0].mailbox_holder.sync_point,
672 list[1].mailbox_holder.sync_point);
673 EXPECT_NE(0u, list[2].mailbox_holder.sync_point);
674 EXPECT_EQ(list[0].mailbox_holder.sync_point,
675 list[2].mailbox_holder.sync_point);
676 EXPECT_EQ(external_sync_point, list[3].mailbox_holder.sync_point);
677 EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_2D),
678 list[0].mailbox_holder.texture_target);
679 EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_2D),
680 list[1].mailbox_holder.texture_target);
681 EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_2D),
682 list[2].mailbox_holder.texture_target);
683 EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_EXTERNAL_OES),
684 list[3].mailbox_holder.texture_target);
685 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id1));
686 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id2));
687 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id3));
688 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id4));
689 resource_provider_->ReceiveFromChild(child_id, list);
690 EXPECT_NE(list[0].mailbox_holder.sync_point,
691 context3d_->last_waited_sync_point());
693 resource_provider_->WaitSyncPointIfNeeded(list[0].id);
694 ResourceProvider::ScopedReadLockGL lock(resource_provider_.get(),
697 EXPECT_EQ(list[0].mailbox_holder.sync_point,
698 context3d_->last_waited_sync_point());
699 resource_provider_->DeclareUsedResourcesFromChild(child_id,
700 resource_ids_to_transfer);
703 EXPECT_EQ(4u, resource_provider_->num_resources());
704 ResourceProvider::ResourceIdMap resource_map =
705 resource_provider_->GetChildToParentMap(child_id);
706 ResourceProvider::ResourceId mapped_id1 = resource_map[id1];
707 ResourceProvider::ResourceId mapped_id2 = resource_map[id2];
708 ResourceProvider::ResourceId mapped_id3 = resource_map[id3];
709 ResourceProvider::ResourceId mapped_id4 = resource_map[id4];
710 EXPECT_NE(0u, mapped_id1);
711 EXPECT_NE(0u, mapped_id2);
712 EXPECT_NE(0u, mapped_id3);
713 EXPECT_NE(0u, mapped_id4);
714 EXPECT_FALSE(resource_provider_->InUseByConsumer(id1));
715 EXPECT_FALSE(resource_provider_->InUseByConsumer(id2));
716 EXPECT_FALSE(resource_provider_->InUseByConsumer(id3));
717 EXPECT_FALSE(resource_provider_->InUseByConsumer(id4));
719 uint8_t result[4] = { 0 };
721 resource_provider_.get(), context(), mapped_id1, size, format, result);
722 EXPECT_EQ(0, memcmp(data1, result, pixel_size));
725 resource_provider_.get(), context(), mapped_id2, size, format, result);
726 EXPECT_EQ(0, memcmp(data2, result, pixel_size));
729 // Check that transfering again the same resource from the child to the
731 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
732 resource_ids_to_transfer.push_back(id1);
733 resource_ids_to_transfer.push_back(id2);
734 resource_ids_to_transfer.push_back(id3);
735 TransferableResourceArray list;
736 child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
738 EXPECT_EQ(3u, list.size());
739 EXPECT_EQ(id1, list[0].id);
740 EXPECT_EQ(id2, list[1].id);
741 EXPECT_EQ(id3, list[2].id);
742 EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_2D),
743 list[0].mailbox_holder.texture_target);
744 EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_2D),
745 list[1].mailbox_holder.texture_target);
746 EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_2D),
747 list[2].mailbox_holder.texture_target);
748 ReturnedResourceArray returned;
749 TransferableResource::ReturnResources(list, &returned);
750 child_resource_provider_->ReceiveReturnsFromParent(returned);
751 // ids were exported twice, we returned them only once, they should still
753 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id1));
754 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id2));
755 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id3));
758 EXPECT_EQ(0u, returned_to_child.size());
760 // Transfer resources back from the parent to the child. Set no resources as
762 ResourceProvider::ResourceIdArray no_resources;
763 resource_provider_->DeclareUsedResourcesFromChild(child_id, no_resources);
765 ASSERT_EQ(4u, returned_to_child.size());
766 EXPECT_NE(0u, returned_to_child[0].sync_point);
767 EXPECT_NE(0u, returned_to_child[1].sync_point);
768 EXPECT_NE(0u, returned_to_child[2].sync_point);
769 EXPECT_NE(0u, returned_to_child[3].sync_point);
770 EXPECT_FALSE(returned_to_child[0].lost);
771 EXPECT_FALSE(returned_to_child[1].lost);
772 EXPECT_FALSE(returned_to_child[2].lost);
773 EXPECT_FALSE(returned_to_child[3].lost);
774 child_resource_provider_->ReceiveReturnsFromParent(returned_to_child);
775 returned_to_child.clear();
777 EXPECT_FALSE(child_resource_provider_->InUseByConsumer(id1));
778 EXPECT_FALSE(child_resource_provider_->InUseByConsumer(id2));
779 EXPECT_FALSE(child_resource_provider_->InUseByConsumer(id3));
780 EXPECT_FALSE(child_resource_provider_->InUseByConsumer(id4));
783 child_resource_provider_->WaitSyncPointIfNeeded(id1);
784 ResourceProvider::ScopedReadLockGL lock(child_resource_provider_.get(),
786 ASSERT_NE(0U, lock.texture_id());
787 child_context_->bindTexture(GL_TEXTURE_2D, lock.texture_id());
788 child_context_->GetPixels(size, format, result);
789 EXPECT_EQ(0, memcmp(data1, result, pixel_size));
792 child_resource_provider_->WaitSyncPointIfNeeded(id2);
793 ResourceProvider::ScopedReadLockGL lock(child_resource_provider_.get(),
795 ASSERT_NE(0U, lock.texture_id());
796 child_context_->bindTexture(GL_TEXTURE_2D, lock.texture_id());
797 child_context_->GetPixels(size, format, result);
798 EXPECT_EQ(0, memcmp(data2, result, pixel_size));
801 child_resource_provider_->WaitSyncPointIfNeeded(id3);
802 ResourceProvider::ScopedReadLockGL lock(child_resource_provider_.get(),
804 ASSERT_NE(0U, lock.texture_id());
805 child_context_->bindTexture(GL_TEXTURE_2D, lock.texture_id());
808 // Transfer resources to the parent again.
809 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
810 resource_ids_to_transfer.push_back(id1);
811 resource_ids_to_transfer.push_back(id2);
812 resource_ids_to_transfer.push_back(id3);
813 resource_ids_to_transfer.push_back(id4);
814 TransferableResourceArray list;
815 child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
817 ASSERT_EQ(4u, list.size());
818 EXPECT_EQ(id1, list[0].id);
819 EXPECT_EQ(id2, list[1].id);
820 EXPECT_EQ(id3, list[2].id);
821 EXPECT_EQ(id4, list[3].id);
822 EXPECT_NE(0u, list[0].mailbox_holder.sync_point);
823 EXPECT_NE(0u, list[1].mailbox_holder.sync_point);
824 EXPECT_NE(0u, list[2].mailbox_holder.sync_point);
825 EXPECT_NE(0u, list[3].mailbox_holder.sync_point);
826 EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_2D),
827 list[0].mailbox_holder.texture_target);
828 EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_2D),
829 list[1].mailbox_holder.texture_target);
830 EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_2D),
831 list[2].mailbox_holder.texture_target);
832 EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_EXTERNAL_OES),
833 list[3].mailbox_holder.texture_target);
834 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id1));
835 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id2));
836 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id3));
837 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id4));
838 resource_provider_->ReceiveFromChild(child_id, list);
839 resource_provider_->DeclareUsedResourcesFromChild(child_id,
840 resource_ids_to_transfer);
843 EXPECT_EQ(0u, returned_to_child.size());
845 EXPECT_EQ(4u, resource_provider_->num_resources());
846 resource_provider_->DestroyChild(child_id);
847 EXPECT_EQ(0u, resource_provider_->num_resources());
849 ASSERT_EQ(4u, returned_to_child.size());
850 EXPECT_NE(0u, returned_to_child[0].sync_point);
851 EXPECT_NE(0u, returned_to_child[1].sync_point);
852 EXPECT_NE(0u, returned_to_child[2].sync_point);
853 EXPECT_NE(0u, returned_to_child[3].sync_point);
854 EXPECT_FALSE(returned_to_child[0].lost);
855 EXPECT_FALSE(returned_to_child[1].lost);
856 EXPECT_FALSE(returned_to_child[2].lost);
857 EXPECT_FALSE(returned_to_child[3].lost);
860 TEST_P(ResourceProviderTest, ReadLockCountStopsReturnToChildOrDelete) {
861 if (GetParam() != ResourceProvider::GLTexture)
863 gfx::Size size(1, 1);
864 ResourceFormat format = RGBA_8888;
866 ResourceProvider::ResourceId id1 = child_resource_provider_->CreateResource(
867 size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureHintImmutable, format);
868 uint8_t data1[4] = {1, 2, 3, 4};
869 gfx::Rect rect(size);
870 child_resource_provider_->SetPixels(id1, data1, rect, rect, gfx::Vector2d());
872 ReturnedResourceArray returned_to_child;
874 resource_provider_->CreateChild(GetReturnCallback(&returned_to_child));
876 // Transfer some resources to the parent.
877 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
878 resource_ids_to_transfer.push_back(id1);
879 TransferableResourceArray list;
880 child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
882 ASSERT_EQ(1u, list.size());
883 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id1));
885 resource_provider_->ReceiveFromChild(child_id, list);
887 resource_provider_->WaitSyncPointIfNeeded(list[0].id);
888 ResourceProvider::ScopedReadLockGL lock(resource_provider_.get(),
891 resource_provider_->DeclareUsedResourcesFromChild(
892 child_id, ResourceProvider::ResourceIdArray());
893 EXPECT_EQ(0u, returned_to_child.size());
896 EXPECT_EQ(1u, returned_to_child.size());
897 child_resource_provider_->ReceiveReturnsFromParent(returned_to_child);
900 child_resource_provider_->WaitSyncPointIfNeeded(id1);
901 ResourceProvider::ScopedReadLockGL lock(child_resource_provider_.get(),
903 child_resource_provider_->DeleteResource(id1);
904 EXPECT_EQ(1u, child_resource_provider_->num_resources());
905 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id1));
908 EXPECT_EQ(0u, child_resource_provider_->num_resources());
909 resource_provider_->DestroyChild(child_id);
912 TEST_P(ResourceProviderTest, AllowOverlayTransfersToParent) {
913 // Overlays only supported on the GL path.
914 if (GetParam() != ResourceProvider::GLTexture)
917 uint32 sync_point = 0;
918 TextureMailbox mailbox(gpu::Mailbox::Generate(), GL_TEXTURE_2D, sync_point);
919 mailbox.set_allow_overlay(true);
920 scoped_ptr<SingleReleaseCallbackImpl> release_callback =
921 SingleReleaseCallbackImpl::Create(base::Bind(&EmptyReleaseCallback));
922 ResourceProvider::ResourceId id1 =
923 child_resource_provider_->CreateResourceFromTextureMailbox(
924 mailbox, release_callback.Pass());
926 TextureMailbox mailbox2(gpu::Mailbox::Generate(), GL_TEXTURE_2D, sync_point);
927 mailbox2.set_allow_overlay(false);
928 scoped_ptr<SingleReleaseCallbackImpl> release_callback2 =
929 SingleReleaseCallbackImpl::Create(base::Bind(&EmptyReleaseCallback));
930 ResourceProvider::ResourceId id2 =
931 child_resource_provider_->CreateResourceFromTextureMailbox(
932 mailbox2, release_callback2.Pass());
934 ReturnedResourceArray returned_to_child;
936 resource_provider_->CreateChild(GetReturnCallback(&returned_to_child));
938 // Transfer some resources to the parent.
939 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
940 resource_ids_to_transfer.push_back(id1);
941 resource_ids_to_transfer.push_back(id2);
942 TransferableResourceArray list;
943 child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
945 ASSERT_EQ(2u, list.size());
946 resource_provider_->ReceiveFromChild(child_id, list);
947 EXPECT_TRUE(resource_provider_->AllowOverlay(list[0].id));
948 EXPECT_FALSE(resource_provider_->AllowOverlay(list[1].id));
950 resource_provider_->DeclareUsedResourcesFromChild(
951 child_id, ResourceProvider::ResourceIdArray());
953 EXPECT_EQ(2u, returned_to_child.size());
954 child_resource_provider_->ReceiveReturnsFromParent(returned_to_child);
956 child_resource_provider_->DeleteResource(id1);
957 child_resource_provider_->DeleteResource(id2);
958 EXPECT_EQ(0u, child_resource_provider_->num_resources());
960 resource_provider_->DestroyChild(child_id);
963 TEST_P(ResourceProviderTest, TransferSoftwareResources) {
964 if (GetParam() != ResourceProvider::Bitmap)
967 gfx::Size size(1, 1);
968 ResourceFormat format = RGBA_8888;
969 size_t pixel_size = TextureSizeBytes(size, format);
970 ASSERT_EQ(4U, pixel_size);
972 ResourceProvider::ResourceId id1 = child_resource_provider_->CreateResource(
973 size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureHintImmutable, format);
974 uint8_t data1[4] = { 1, 2, 3, 4 };
975 gfx::Rect rect(size);
976 child_resource_provider_->SetPixels(id1, data1, rect, rect, gfx::Vector2d());
978 ResourceProvider::ResourceId id2 = child_resource_provider_->CreateResource(
979 size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureHintImmutable, format);
980 uint8_t data2[4] = { 5, 5, 5, 5 };
981 child_resource_provider_->SetPixels(id2, data2, rect, rect, gfx::Vector2d());
983 scoped_ptr<base::SharedMemory> shared_memory(new base::SharedMemory());
984 shared_memory->CreateAndMapAnonymous(1);
985 base::SharedMemory* shared_memory_ptr = shared_memory.get();
986 ResourceProvider::ResourceId id3 =
987 child_resource_provider_->CreateResourceFromTextureMailbox(
988 TextureMailbox(shared_memory_ptr, gfx::Size(1, 1)),
989 SingleReleaseCallbackImpl::Create(base::Bind(
990 &SharedMemoryReleaseCallback, base::Passed(&shared_memory))));
992 ReturnedResourceArray returned_to_child;
994 resource_provider_->CreateChild(GetReturnCallback(&returned_to_child));
996 // Transfer some resources to the parent.
997 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
998 resource_ids_to_transfer.push_back(id1);
999 resource_ids_to_transfer.push_back(id2);
1000 resource_ids_to_transfer.push_back(id3);
1001 TransferableResourceArray list;
1002 child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
1004 ASSERT_EQ(3u, list.size());
1005 EXPECT_EQ(0u, list[0].mailbox_holder.sync_point);
1006 EXPECT_EQ(0u, list[1].mailbox_holder.sync_point);
1007 EXPECT_EQ(0u, list[2].mailbox_holder.sync_point);
1008 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id1));
1009 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id2));
1010 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id3));
1011 resource_provider_->ReceiveFromChild(child_id, list);
1012 resource_provider_->DeclareUsedResourcesFromChild(child_id,
1013 resource_ids_to_transfer);
1016 EXPECT_EQ(3u, resource_provider_->num_resources());
1017 ResourceProvider::ResourceIdMap resource_map =
1018 resource_provider_->GetChildToParentMap(child_id);
1019 ResourceProvider::ResourceId mapped_id1 = resource_map[id1];
1020 ResourceProvider::ResourceId mapped_id2 = resource_map[id2];
1021 ResourceProvider::ResourceId mapped_id3 = resource_map[id3];
1022 EXPECT_NE(0u, mapped_id1);
1023 EXPECT_NE(0u, mapped_id2);
1024 EXPECT_NE(0u, mapped_id3);
1025 EXPECT_FALSE(resource_provider_->InUseByConsumer(id1));
1026 EXPECT_FALSE(resource_provider_->InUseByConsumer(id2));
1027 EXPECT_FALSE(resource_provider_->InUseByConsumer(id3));
1029 uint8_t result[4] = { 0 };
1031 resource_provider_.get(), context(), mapped_id1, size, format, result);
1032 EXPECT_EQ(0, memcmp(data1, result, pixel_size));
1035 resource_provider_.get(), context(), mapped_id2, size, format, result);
1036 EXPECT_EQ(0, memcmp(data2, result, pixel_size));
1039 // Check that transfering again the same resource from the child to the
1041 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
1042 resource_ids_to_transfer.push_back(id1);
1043 resource_ids_to_transfer.push_back(id2);
1044 TransferableResourceArray list;
1045 child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
1047 EXPECT_EQ(2u, list.size());
1048 EXPECT_EQ(id1, list[0].id);
1049 EXPECT_EQ(id2, list[1].id);
1050 ReturnedResourceArray returned;
1051 TransferableResource::ReturnResources(list, &returned);
1052 child_resource_provider_->ReceiveReturnsFromParent(returned);
1053 // ids were exported twice, we returned them only once, they should still
1055 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id1));
1056 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id2));
1059 EXPECT_EQ(0u, returned_to_child.size());
1061 // Transfer resources back from the parent to the child. Set no resources as
1063 ResourceProvider::ResourceIdArray no_resources;
1064 resource_provider_->DeclareUsedResourcesFromChild(child_id, no_resources);
1066 ASSERT_EQ(3u, returned_to_child.size());
1067 EXPECT_EQ(0u, returned_to_child[0].sync_point);
1068 EXPECT_EQ(0u, returned_to_child[1].sync_point);
1069 EXPECT_EQ(0u, returned_to_child[2].sync_point);
1070 std::set<ResourceProvider::ResourceId> expected_ids;
1071 expected_ids.insert(id1);
1072 expected_ids.insert(id2);
1073 expected_ids.insert(id3);
1074 std::set<ResourceProvider::ResourceId> returned_ids;
1075 for (unsigned i = 0; i < 3; i++)
1076 returned_ids.insert(returned_to_child[i].id);
1077 EXPECT_EQ(expected_ids, returned_ids);
1078 EXPECT_FALSE(returned_to_child[0].lost);
1079 EXPECT_FALSE(returned_to_child[1].lost);
1080 EXPECT_FALSE(returned_to_child[2].lost);
1081 child_resource_provider_->ReceiveReturnsFromParent(returned_to_child);
1082 returned_to_child.clear();
1084 EXPECT_FALSE(child_resource_provider_->InUseByConsumer(id1));
1085 EXPECT_FALSE(child_resource_provider_->InUseByConsumer(id2));
1086 EXPECT_FALSE(child_resource_provider_->InUseByConsumer(id3));
1089 ResourceProvider::ScopedReadLockSoftware lock(
1090 child_resource_provider_.get(), id1);
1091 const SkBitmap* sk_bitmap = lock.sk_bitmap();
1092 EXPECT_EQ(sk_bitmap->width(), size.width());
1093 EXPECT_EQ(sk_bitmap->height(), size.height());
1094 EXPECT_EQ(0, memcmp(data1, sk_bitmap->getPixels(), pixel_size));
1097 ResourceProvider::ScopedReadLockSoftware lock(
1098 child_resource_provider_.get(), id2);
1099 const SkBitmap* sk_bitmap = lock.sk_bitmap();
1100 EXPECT_EQ(sk_bitmap->width(), size.width());
1101 EXPECT_EQ(sk_bitmap->height(), size.height());
1102 EXPECT_EQ(0, memcmp(data2, sk_bitmap->getPixels(), pixel_size));
1105 // Transfer resources to the parent again.
1106 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
1107 resource_ids_to_transfer.push_back(id1);
1108 resource_ids_to_transfer.push_back(id2);
1109 resource_ids_to_transfer.push_back(id3);
1110 TransferableResourceArray list;
1111 child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
1113 ASSERT_EQ(3u, list.size());
1114 EXPECT_EQ(id1, list[0].id);
1115 EXPECT_EQ(id2, list[1].id);
1116 EXPECT_EQ(id3, list[2].id);
1117 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id1));
1118 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id2));
1119 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id3));
1120 resource_provider_->ReceiveFromChild(child_id, list);
1121 resource_provider_->DeclareUsedResourcesFromChild(child_id,
1122 resource_ids_to_transfer);
1125 EXPECT_EQ(0u, returned_to_child.size());
1127 EXPECT_EQ(3u, resource_provider_->num_resources());
1128 resource_provider_->DestroyChild(child_id);
1129 EXPECT_EQ(0u, resource_provider_->num_resources());
1131 ASSERT_EQ(3u, returned_to_child.size());
1132 EXPECT_EQ(0u, returned_to_child[0].sync_point);
1133 EXPECT_EQ(0u, returned_to_child[1].sync_point);
1134 EXPECT_EQ(0u, returned_to_child[2].sync_point);
1135 std::set<ResourceProvider::ResourceId> expected_ids;
1136 expected_ids.insert(id1);
1137 expected_ids.insert(id2);
1138 expected_ids.insert(id3);
1139 std::set<ResourceProvider::ResourceId> returned_ids;
1140 for (unsigned i = 0; i < 3; i++)
1141 returned_ids.insert(returned_to_child[i].id);
1142 EXPECT_EQ(expected_ids, returned_ids);
1143 EXPECT_FALSE(returned_to_child[0].lost);
1144 EXPECT_FALSE(returned_to_child[1].lost);
1145 EXPECT_FALSE(returned_to_child[2].lost);
1148 TEST_P(ResourceProviderTest, TransferGLToSoftware) {
1149 if (GetParam() != ResourceProvider::Bitmap)
1152 scoped_ptr<ResourceProviderContext> child_context_owned(
1153 ResourceProviderContext::Create(shared_data_.get()));
1155 FakeOutputSurfaceClient child_output_surface_client;
1156 scoped_ptr<OutputSurface> child_output_surface(FakeOutputSurface::Create3d(
1157 child_context_owned.PassAs<TestWebGraphicsContext3D>()));
1158 CHECK(child_output_surface->BindToClient(&child_output_surface_client));
1160 scoped_ptr<ResourceProvider> child_resource_provider(
1161 ResourceProvider::Create(child_output_surface.get(),
1162 shared_bitmap_manager_.get(),
1169 gfx::Size size(1, 1);
1170 ResourceFormat format = RGBA_8888;
1171 size_t pixel_size = TextureSizeBytes(size, format);
1172 ASSERT_EQ(4U, pixel_size);
1174 ResourceProvider::ResourceId id1 = child_resource_provider->CreateResource(
1175 size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureHintImmutable, format);
1176 uint8_t data1[4] = { 1, 2, 3, 4 };
1177 gfx::Rect rect(size);
1178 child_resource_provider->SetPixels(id1, data1, rect, rect, gfx::Vector2d());
1180 ReturnedResourceArray returned_to_child;
1182 resource_provider_->CreateChild(GetReturnCallback(&returned_to_child));
1184 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
1185 resource_ids_to_transfer.push_back(id1);
1186 TransferableResourceArray list;
1187 child_resource_provider->PrepareSendToParent(resource_ids_to_transfer,
1189 ASSERT_EQ(1u, list.size());
1190 EXPECT_NE(0u, list[0].mailbox_holder.sync_point);
1191 EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_2D),
1192 list[0].mailbox_holder.texture_target);
1193 EXPECT_TRUE(child_resource_provider->InUseByConsumer(id1));
1194 resource_provider_->ReceiveFromChild(child_id, list);
1197 EXPECT_EQ(0u, resource_provider_->num_resources());
1198 ASSERT_EQ(1u, returned_to_child.size());
1199 EXPECT_EQ(returned_to_child[0].id, id1);
1200 ResourceProvider::ResourceIdMap resource_map =
1201 resource_provider_->GetChildToParentMap(child_id);
1202 ResourceProvider::ResourceId mapped_id1 = resource_map[id1];
1203 EXPECT_EQ(0u, mapped_id1);
1205 resource_provider_->DestroyChild(child_id);
1206 EXPECT_EQ(0u, resource_provider_->num_resources());
1208 ASSERT_EQ(1u, returned_to_child.size());
1209 EXPECT_FALSE(returned_to_child[0].lost);
1212 TEST_P(ResourceProviderTest, TransferInvalidSoftware) {
1213 if (GetParam() != ResourceProvider::Bitmap)
1216 gfx::Size size(1, 1);
1217 ResourceFormat format = RGBA_8888;
1218 size_t pixel_size = TextureSizeBytes(size, format);
1219 ASSERT_EQ(4U, pixel_size);
1221 ResourceProvider::ResourceId id1 = child_resource_provider_->CreateResource(
1222 size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureHintImmutable, format);
1223 uint8_t data1[4] = { 1, 2, 3, 4 };
1224 gfx::Rect rect(size);
1225 child_resource_provider_->SetPixels(id1, data1, rect, rect, gfx::Vector2d());
1227 ReturnedResourceArray returned_to_child;
1229 resource_provider_->CreateChild(GetReturnCallback(&returned_to_child));
1231 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
1232 resource_ids_to_transfer.push_back(id1);
1233 TransferableResourceArray list;
1234 child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
1236 ASSERT_EQ(1u, list.size());
1238 list[0].mailbox_holder.mailbox.name[1] = 5;
1239 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id1));
1240 resource_provider_->ReceiveFromChild(child_id, list);
1243 EXPECT_EQ(1u, resource_provider_->num_resources());
1244 EXPECT_EQ(0u, returned_to_child.size());
1246 ResourceProvider::ResourceIdMap resource_map =
1247 resource_provider_->GetChildToParentMap(child_id);
1248 ResourceProvider::ResourceId mapped_id1 = resource_map[id1];
1249 EXPECT_NE(0u, mapped_id1);
1251 ResourceProvider::ScopedReadLockSoftware lock(resource_provider_.get(),
1253 EXPECT_FALSE(lock.valid());
1256 resource_provider_->DestroyChild(child_id);
1257 EXPECT_EQ(0u, resource_provider_->num_resources());
1259 ASSERT_EQ(1u, returned_to_child.size());
1260 EXPECT_FALSE(returned_to_child[0].lost);
1263 TEST_P(ResourceProviderTest, DeleteExportedResources) {
1264 gfx::Size size(1, 1);
1265 ResourceFormat format = RGBA_8888;
1266 size_t pixel_size = TextureSizeBytes(size, format);
1267 ASSERT_EQ(4U, pixel_size);
1269 ResourceProvider::ResourceId id1 = child_resource_provider_->CreateResource(
1270 size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureHintImmutable, format);
1271 uint8_t data1[4] = { 1, 2, 3, 4 };
1272 gfx::Rect rect(size);
1273 child_resource_provider_->SetPixels(id1, data1, rect, rect, gfx::Vector2d());
1275 ResourceProvider::ResourceId id2 = child_resource_provider_->CreateResource(
1276 size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureHintImmutable, format);
1277 uint8_t data2[4] = {5, 5, 5, 5};
1278 child_resource_provider_->SetPixels(id2, data2, rect, rect, gfx::Vector2d());
1280 ReturnedResourceArray returned_to_child;
1282 resource_provider_->CreateChild(GetReturnCallback(&returned_to_child));
1284 // Transfer some resources to the parent.
1285 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
1286 resource_ids_to_transfer.push_back(id1);
1287 resource_ids_to_transfer.push_back(id2);
1288 TransferableResourceArray list;
1289 child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
1291 ASSERT_EQ(2u, list.size());
1292 if (GetParam() == ResourceProvider::GLTexture) {
1293 EXPECT_NE(0u, list[0].mailbox_holder.sync_point);
1294 EXPECT_NE(0u, list[1].mailbox_holder.sync_point);
1296 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id1));
1297 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id2));
1298 resource_provider_->ReceiveFromChild(child_id, list);
1299 resource_provider_->DeclareUsedResourcesFromChild(child_id,
1300 resource_ids_to_transfer);
1303 EXPECT_EQ(2u, resource_provider_->num_resources());
1304 ResourceProvider::ResourceIdMap resource_map =
1305 resource_provider_->GetChildToParentMap(child_id);
1306 ResourceProvider::ResourceId mapped_id1 = resource_map[id1];
1307 ResourceProvider::ResourceId mapped_id2 = resource_map[id2];
1308 EXPECT_NE(0u, mapped_id1);
1309 EXPECT_NE(0u, mapped_id2);
1310 EXPECT_FALSE(resource_provider_->InUseByConsumer(id1));
1311 EXPECT_FALSE(resource_provider_->InUseByConsumer(id2));
1314 // The parent transfers the resources to the grandparent.
1315 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
1316 resource_ids_to_transfer.push_back(mapped_id1);
1317 resource_ids_to_transfer.push_back(mapped_id2);
1318 TransferableResourceArray list;
1319 resource_provider_->PrepareSendToParent(resource_ids_to_transfer, &list);
1321 ASSERT_EQ(2u, list.size());
1322 if (GetParam() == ResourceProvider::GLTexture) {
1323 EXPECT_NE(0u, list[0].mailbox_holder.sync_point);
1324 EXPECT_NE(0u, list[1].mailbox_holder.sync_point);
1326 EXPECT_TRUE(resource_provider_->InUseByConsumer(id1));
1327 EXPECT_TRUE(resource_provider_->InUseByConsumer(id2));
1329 // Release the resource in the parent. Set no resources as being in use. The
1330 // resources are exported so that can't be transferred back yet.
1331 ResourceProvider::ResourceIdArray no_resources;
1332 resource_provider_->DeclareUsedResourcesFromChild(child_id, no_resources);
1334 EXPECT_EQ(0u, returned_to_child.size());
1335 EXPECT_EQ(2u, resource_provider_->num_resources());
1337 // Return the resources from the grandparent to the parent. They should be
1338 // returned to the child then.
1339 EXPECT_EQ(2u, list.size());
1340 EXPECT_EQ(mapped_id1, list[0].id);
1341 EXPECT_EQ(mapped_id2, list[1].id);
1342 ReturnedResourceArray returned;
1343 TransferableResource::ReturnResources(list, &returned);
1344 resource_provider_->ReceiveReturnsFromParent(returned);
1346 EXPECT_EQ(0u, resource_provider_->num_resources());
1347 ASSERT_EQ(2u, returned_to_child.size());
1348 if (GetParam() == ResourceProvider::GLTexture) {
1349 EXPECT_NE(0u, returned_to_child[0].sync_point);
1350 EXPECT_NE(0u, returned_to_child[1].sync_point);
1352 EXPECT_FALSE(returned_to_child[0].lost);
1353 EXPECT_FALSE(returned_to_child[1].lost);
1357 TEST_P(ResourceProviderTest, DestroyChildWithExportedResources) {
1358 gfx::Size size(1, 1);
1359 ResourceFormat format = RGBA_8888;
1360 size_t pixel_size = TextureSizeBytes(size, format);
1361 ASSERT_EQ(4U, pixel_size);
1363 ResourceProvider::ResourceId id1 = child_resource_provider_->CreateResource(
1364 size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureHintImmutable, format);
1365 uint8_t data1[4] = {1, 2, 3, 4};
1366 gfx::Rect rect(size);
1367 child_resource_provider_->SetPixels(id1, data1, rect, rect, gfx::Vector2d());
1369 ResourceProvider::ResourceId id2 = child_resource_provider_->CreateResource(
1370 size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureHintImmutable, format);
1371 uint8_t data2[4] = {5, 5, 5, 5};
1372 child_resource_provider_->SetPixels(id2, data2, rect, rect, gfx::Vector2d());
1374 ReturnedResourceArray returned_to_child;
1376 resource_provider_->CreateChild(GetReturnCallback(&returned_to_child));
1378 // Transfer some resources to the parent.
1379 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
1380 resource_ids_to_transfer.push_back(id1);
1381 resource_ids_to_transfer.push_back(id2);
1382 TransferableResourceArray list;
1383 child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
1385 ASSERT_EQ(2u, list.size());
1386 if (GetParam() == ResourceProvider::GLTexture) {
1387 EXPECT_NE(0u, list[0].mailbox_holder.sync_point);
1388 EXPECT_NE(0u, list[1].mailbox_holder.sync_point);
1390 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id1));
1391 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id2));
1392 resource_provider_->ReceiveFromChild(child_id, list);
1393 resource_provider_->DeclareUsedResourcesFromChild(child_id,
1394 resource_ids_to_transfer);
1397 EXPECT_EQ(2u, resource_provider_->num_resources());
1398 ResourceProvider::ResourceIdMap resource_map =
1399 resource_provider_->GetChildToParentMap(child_id);
1400 ResourceProvider::ResourceId mapped_id1 = resource_map[id1];
1401 ResourceProvider::ResourceId mapped_id2 = resource_map[id2];
1402 EXPECT_NE(0u, mapped_id1);
1403 EXPECT_NE(0u, mapped_id2);
1404 EXPECT_FALSE(resource_provider_->InUseByConsumer(id1));
1405 EXPECT_FALSE(resource_provider_->InUseByConsumer(id2));
1408 // The parent transfers the resources to the grandparent.
1409 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
1410 resource_ids_to_transfer.push_back(mapped_id1);
1411 resource_ids_to_transfer.push_back(mapped_id2);
1412 TransferableResourceArray list;
1413 resource_provider_->PrepareSendToParent(resource_ids_to_transfer, &list);
1415 ASSERT_EQ(2u, list.size());
1416 if (GetParam() == ResourceProvider::GLTexture) {
1417 EXPECT_NE(0u, list[0].mailbox_holder.sync_point);
1418 EXPECT_NE(0u, list[1].mailbox_holder.sync_point);
1420 EXPECT_TRUE(resource_provider_->InUseByConsumer(id1));
1421 EXPECT_TRUE(resource_provider_->InUseByConsumer(id2));
1423 // Release the resource in the parent. Set no resources as being in use. The
1424 // resources are exported so that can't be transferred back yet.
1425 ResourceProvider::ResourceIdArray no_resources;
1426 resource_provider_->DeclareUsedResourcesFromChild(child_id, no_resources);
1428 // Destroy the child, the resources should not be returned yet.
1429 EXPECT_EQ(0u, returned_to_child.size());
1430 EXPECT_EQ(2u, resource_provider_->num_resources());
1432 resource_provider_->DestroyChild(child_id);
1434 EXPECT_EQ(2u, resource_provider_->num_resources());
1435 ASSERT_EQ(0u, returned_to_child.size());
1437 // Return a resource from the grandparent, it should be returned at this
1439 EXPECT_EQ(2u, list.size());
1440 EXPECT_EQ(mapped_id1, list[0].id);
1441 EXPECT_EQ(mapped_id2, list[1].id);
1442 TransferableResourceArray return_list;
1443 return_list.push_back(list[1]);
1445 ReturnedResourceArray returned;
1446 TransferableResource::ReturnResources(return_list, &returned);
1447 resource_provider_->ReceiveReturnsFromParent(returned);
1449 EXPECT_EQ(1u, resource_provider_->num_resources());
1450 ASSERT_EQ(1u, returned_to_child.size());
1451 if (GetParam() == ResourceProvider::GLTexture) {
1452 EXPECT_NE(0u, returned_to_child[0].sync_point);
1454 EXPECT_FALSE(returned_to_child[0].lost);
1455 returned_to_child.clear();
1457 // Destroy the parent resource provider. The resource that's left should be
1458 // lost at this point, and returned.
1459 resource_provider_.reset();
1460 ASSERT_EQ(1u, returned_to_child.size());
1461 if (GetParam() == ResourceProvider::GLTexture) {
1462 EXPECT_NE(0u, returned_to_child[0].sync_point);
1464 EXPECT_TRUE(returned_to_child[0].lost);
1468 TEST_P(ResourceProviderTest, DeleteTransferredResources) {
1469 gfx::Size size(1, 1);
1470 ResourceFormat format = RGBA_8888;
1471 size_t pixel_size = TextureSizeBytes(size, format);
1472 ASSERT_EQ(4U, pixel_size);
1474 ResourceProvider::ResourceId id = child_resource_provider_->CreateResource(
1475 size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureHintImmutable, format);
1476 uint8_t data[4] = { 1, 2, 3, 4 };
1477 gfx::Rect rect(size);
1478 child_resource_provider_->SetPixels(id, data, rect, rect, gfx::Vector2d());
1480 ReturnedResourceArray returned_to_child;
1482 resource_provider_->CreateChild(GetReturnCallback(&returned_to_child));
1484 // Transfer some resource to the parent.
1485 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
1486 resource_ids_to_transfer.push_back(id);
1487 TransferableResourceArray list;
1488 child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
1490 ASSERT_EQ(1u, list.size());
1491 if (GetParam() == ResourceProvider::GLTexture)
1492 EXPECT_NE(0u, list[0].mailbox_holder.sync_point);
1493 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id));
1494 resource_provider_->ReceiveFromChild(child_id, list);
1495 resource_provider_->DeclareUsedResourcesFromChild(child_id,
1496 resource_ids_to_transfer);
1499 // Delete textures in the child, while they are transfered.
1500 child_resource_provider_->DeleteResource(id);
1501 EXPECT_EQ(1u, child_resource_provider_->num_resources());
1503 EXPECT_EQ(0u, returned_to_child.size());
1505 // Transfer resources back from the parent to the child. Set no resources as
1507 ResourceProvider::ResourceIdArray no_resources;
1508 resource_provider_->DeclareUsedResourcesFromChild(child_id, no_resources);
1510 ASSERT_EQ(1u, returned_to_child.size());
1511 if (GetParam() == ResourceProvider::GLTexture)
1512 EXPECT_NE(0u, returned_to_child[0].sync_point);
1513 child_resource_provider_->ReceiveReturnsFromParent(returned_to_child);
1515 EXPECT_EQ(0u, child_resource_provider_->num_resources());
1518 TEST_P(ResourceProviderTest, UnuseTransferredResources) {
1519 gfx::Size size(1, 1);
1520 ResourceFormat format = RGBA_8888;
1521 size_t pixel_size = TextureSizeBytes(size, format);
1522 ASSERT_EQ(4U, pixel_size);
1524 ResourceProvider::ResourceId id = child_resource_provider_->CreateResource(
1525 size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureHintImmutable, format);
1526 uint8_t data[4] = {1, 2, 3, 4};
1527 gfx::Rect rect(size);
1528 child_resource_provider_->SetPixels(id, data, rect, rect, gfx::Vector2d());
1530 ReturnedResourceArray returned_to_child;
1532 resource_provider_->CreateChild(GetReturnCallback(&returned_to_child));
1533 const ResourceProvider::ResourceIdMap& map =
1534 resource_provider_->GetChildToParentMap(child_id);
1536 // Transfer some resource to the parent.
1537 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
1538 resource_ids_to_transfer.push_back(id);
1539 TransferableResourceArray list;
1540 child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
1542 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id));
1543 resource_provider_->ReceiveFromChild(child_id, list);
1544 resource_provider_->DeclareUsedResourcesFromChild(child_id,
1545 resource_ids_to_transfer);
1547 TransferableResourceArray sent_to_top_level;
1549 // Parent transfers to top-level.
1550 ASSERT_TRUE(map.find(id) != map.end());
1551 ResourceProvider::ResourceId parent_id = map.find(id)->second;
1552 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
1553 resource_ids_to_transfer.push_back(parent_id);
1554 resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
1555 &sent_to_top_level);
1556 EXPECT_TRUE(resource_provider_->InUseByConsumer(parent_id));
1559 // Stop using resource.
1560 ResourceProvider::ResourceIdArray empty;
1561 resource_provider_->DeclareUsedResourcesFromChild(child_id, empty);
1562 // Resource is not yet returned to the child, since it's in use by the
1564 EXPECT_TRUE(returned_to_child.empty());
1567 // Send the resource to the parent again.
1568 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
1569 resource_ids_to_transfer.push_back(id);
1570 TransferableResourceArray list;
1571 child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
1573 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id));
1574 resource_provider_->ReceiveFromChild(child_id, list);
1575 resource_provider_->DeclareUsedResourcesFromChild(child_id,
1576 resource_ids_to_transfer);
1579 // Receive returns back from top-level.
1580 ReturnedResourceArray returned;
1581 TransferableResource::ReturnResources(sent_to_top_level, &returned);
1582 resource_provider_->ReceiveReturnsFromParent(returned);
1583 // Resource is still not yet returned to the child, since it's declared used
1585 EXPECT_TRUE(returned_to_child.empty());
1586 ASSERT_TRUE(map.find(id) != map.end());
1587 ResourceProvider::ResourceId parent_id = map.find(id)->second;
1588 EXPECT_FALSE(resource_provider_->InUseByConsumer(parent_id));
1591 sent_to_top_level.clear();
1592 // Parent transfers again to top-level.
1593 ASSERT_TRUE(map.find(id) != map.end());
1594 ResourceProvider::ResourceId parent_id = map.find(id)->second;
1595 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
1596 resource_ids_to_transfer.push_back(parent_id);
1597 resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
1598 &sent_to_top_level);
1599 EXPECT_TRUE(resource_provider_->InUseByConsumer(parent_id));
1602 // Receive returns back from top-level.
1603 ReturnedResourceArray returned;
1604 TransferableResource::ReturnResources(sent_to_top_level, &returned);
1605 resource_provider_->ReceiveReturnsFromParent(returned);
1606 // Resource is still not yet returned to the child, since it's still
1607 // declared used in the parent.
1608 EXPECT_TRUE(returned_to_child.empty());
1609 ASSERT_TRUE(map.find(id) != map.end());
1610 ResourceProvider::ResourceId parent_id = map.find(id)->second;
1611 EXPECT_FALSE(resource_provider_->InUseByConsumer(parent_id));
1614 // Stop using resource.
1615 ResourceProvider::ResourceIdArray empty;
1616 resource_provider_->DeclareUsedResourcesFromChild(child_id, empty);
1617 // Resource should have been returned to the child, since it's no longer in
1618 // use by the top-level.
1619 ASSERT_EQ(1u, returned_to_child.size());
1620 EXPECT_EQ(id, returned_to_child[0].id);
1621 EXPECT_EQ(2, returned_to_child[0].count);
1622 child_resource_provider_->ReceiveReturnsFromParent(returned_to_child);
1623 returned_to_child.clear();
1624 EXPECT_FALSE(child_resource_provider_->InUseByConsumer(id));
1628 class ResourceProviderTestTextureFilters : public ResourceProviderTest {
1630 static void RunTest(GLenum child_filter, GLenum parent_filter) {
1631 scoped_ptr<TextureStateTrackingContext> child_context_owned(
1632 new TextureStateTrackingContext);
1633 TextureStateTrackingContext* child_context = child_context_owned.get();
1635 FakeOutputSurfaceClient child_output_surface_client;
1636 scoped_ptr<OutputSurface> child_output_surface(FakeOutputSurface::Create3d(
1637 child_context_owned.PassAs<TestWebGraphicsContext3D>()));
1638 CHECK(child_output_surface->BindToClient(&child_output_surface_client));
1639 scoped_ptr<SharedBitmapManager> shared_bitmap_manager(
1640 new TestSharedBitmapManager());
1642 scoped_ptr<ResourceProvider> child_resource_provider(
1643 ResourceProvider::Create(child_output_surface.get(),
1644 shared_bitmap_manager.get(),
1651 scoped_ptr<TextureStateTrackingContext> parent_context_owned(
1652 new TextureStateTrackingContext);
1653 TextureStateTrackingContext* parent_context = parent_context_owned.get();
1655 FakeOutputSurfaceClient parent_output_surface_client;
1656 scoped_ptr<OutputSurface> parent_output_surface(FakeOutputSurface::Create3d(
1657 parent_context_owned.PassAs<TestWebGraphicsContext3D>()));
1658 CHECK(parent_output_surface->BindToClient(&parent_output_surface_client));
1660 scoped_ptr<ResourceProvider> parent_resource_provider(
1661 ResourceProvider::Create(parent_output_surface.get(),
1662 shared_bitmap_manager.get(),
1669 gfx::Size size(1, 1);
1670 ResourceFormat format = RGBA_8888;
1671 int child_texture_id = 1;
1672 int parent_texture_id = 2;
1674 size_t pixel_size = TextureSizeBytes(size, format);
1675 ASSERT_EQ(4U, pixel_size);
1677 ResourceProvider::ResourceId id = child_resource_provider->CreateResource(
1678 size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureHintImmutable, format);
1680 // The new texture is created with GL_LINEAR.
1681 EXPECT_CALL(*child_context, bindTexture(GL_TEXTURE_2D, child_texture_id))
1682 .Times(2); // Once to create and once to allocate.
1683 EXPECT_CALL(*child_context,
1684 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
1685 EXPECT_CALL(*child_context,
1686 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR));
1689 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE));
1692 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE));
1693 EXPECT_CALL(*child_context,
1694 texParameteri(GL_TEXTURE_2D,
1695 GL_TEXTURE_POOL_CHROMIUM,
1696 GL_TEXTURE_POOL_UNMANAGED_CHROMIUM));
1697 child_resource_provider->AllocateForTesting(id);
1698 Mock::VerifyAndClearExpectations(child_context);
1700 uint8_t data[4] = { 1, 2, 3, 4 };
1701 gfx::Rect rect(size);
1703 EXPECT_CALL(*child_context, bindTexture(GL_TEXTURE_2D, child_texture_id));
1704 child_resource_provider->SetPixels(id, data, rect, rect, gfx::Vector2d());
1705 Mock::VerifyAndClearExpectations(child_context);
1707 // The texture is set to |child_filter| in the child.
1708 EXPECT_CALL(*child_context, bindTexture(GL_TEXTURE_2D, child_texture_id));
1709 if (child_filter != GL_LINEAR) {
1712 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, child_filter));
1715 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, child_filter));
1717 SetResourceFilter(child_resource_provider.get(), id, child_filter);
1718 Mock::VerifyAndClearExpectations(child_context);
1720 ReturnedResourceArray returned_to_child;
1721 int child_id = parent_resource_provider->CreateChild(
1722 GetReturnCallback(&returned_to_child));
1724 // Transfer some resource to the parent.
1725 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
1726 resource_ids_to_transfer.push_back(id);
1727 TransferableResourceArray list;
1729 EXPECT_CALL(*child_context, bindTexture(GL_TEXTURE_2D, child_texture_id));
1730 EXPECT_CALL(*child_context,
1731 produceTextureCHROMIUM(GL_TEXTURE_2D, _));
1732 EXPECT_CALL(*child_context, insertSyncPoint());
1733 child_resource_provider->PrepareSendToParent(resource_ids_to_transfer,
1735 Mock::VerifyAndClearExpectations(child_context);
1737 ASSERT_EQ(1u, list.size());
1738 EXPECT_EQ(static_cast<unsigned>(child_filter), list[0].filter);
1740 EXPECT_CALL(*parent_context,
1741 bindTexture(GL_TEXTURE_2D, parent_texture_id));
1742 EXPECT_CALL(*parent_context, consumeTextureCHROMIUM(GL_TEXTURE_2D, _));
1743 parent_resource_provider->ReceiveFromChild(child_id, list);
1745 parent_resource_provider->WaitSyncPointIfNeeded(list[0].id);
1746 ResourceProvider::ScopedReadLockGL lock(parent_resource_provider.get(),
1749 Mock::VerifyAndClearExpectations(parent_context);
1751 parent_resource_provider->DeclareUsedResourcesFromChild(
1752 child_id, resource_ids_to_transfer);
1753 Mock::VerifyAndClearExpectations(parent_context);
1755 ResourceProvider::ResourceIdMap resource_map =
1756 parent_resource_provider->GetChildToParentMap(child_id);
1757 ResourceProvider::ResourceId mapped_id = resource_map[id];
1758 EXPECT_NE(0u, mapped_id);
1760 // The texture is set to |parent_filter| in the parent.
1761 EXPECT_CALL(*parent_context, bindTexture(GL_TEXTURE_2D, parent_texture_id));
1764 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, parent_filter));
1767 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, parent_filter));
1768 SetResourceFilter(parent_resource_provider.get(), mapped_id, parent_filter);
1769 Mock::VerifyAndClearExpectations(parent_context);
1771 // The texture should be reset to |child_filter| in the parent when it is
1772 // returned, since that is how it was received.
1773 EXPECT_CALL(*parent_context, bindTexture(GL_TEXTURE_2D, parent_texture_id));
1776 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, child_filter));
1779 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, child_filter));
1782 EXPECT_EQ(0u, returned_to_child.size());
1784 // Transfer resources back from the parent to the child. Set no resources
1786 ResourceProvider::ResourceIdArray no_resources;
1787 EXPECT_CALL(*parent_context, insertSyncPoint());
1788 parent_resource_provider->DeclareUsedResourcesFromChild(child_id,
1790 Mock::VerifyAndClearExpectations(parent_context);
1792 ASSERT_EQ(1u, returned_to_child.size());
1793 child_resource_provider->ReceiveReturnsFromParent(returned_to_child);
1796 // The child remembers the texture filter is set to |child_filter|.
1797 EXPECT_CALL(*child_context, bindTexture(GL_TEXTURE_2D, child_texture_id));
1798 SetResourceFilter(child_resource_provider.get(), id, child_filter);
1799 Mock::VerifyAndClearExpectations(child_context);
1803 TEST_P(ResourceProviderTest, TextureFilters_ChildNearestParentLinear) {
1804 if (GetParam() != ResourceProvider::GLTexture)
1806 ResourceProviderTestTextureFilters::RunTest(GL_NEAREST, GL_LINEAR);
1809 TEST_P(ResourceProviderTest, TextureFilters_ChildLinearParentNearest) {
1810 if (GetParam() != ResourceProvider::GLTexture)
1812 ResourceProviderTestTextureFilters::RunTest(GL_LINEAR, GL_NEAREST);
1815 TEST_P(ResourceProviderTest, TransferMailboxResources) {
1816 // Other mailbox transfers tested elsewhere.
1817 if (GetParam() != ResourceProvider::GLTexture)
1819 unsigned texture = context()->createTexture();
1820 context()->bindTexture(GL_TEXTURE_2D, texture);
1821 uint8_t data[4] = { 1, 2, 3, 4 };
1822 context()->texImage2D(
1823 GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, &data);
1824 gpu::Mailbox mailbox;
1825 context()->genMailboxCHROMIUM(mailbox.name);
1826 context()->produceTextureCHROMIUM(GL_TEXTURE_2D, mailbox.name);
1827 uint32 sync_point = context()->insertSyncPoint();
1829 // All the logic below assumes that the sync points are all positive.
1830 EXPECT_LT(0u, sync_point);
1832 uint32 release_sync_point = 0;
1833 bool lost_resource = false;
1834 BlockingTaskRunner* main_thread_task_runner = NULL;
1835 ReleaseCallbackImpl callback = base::Bind(ReleaseCallback,
1836 &release_sync_point,
1838 &main_thread_task_runner);
1839 ResourceProvider::ResourceId resource =
1840 resource_provider_->CreateResourceFromTextureMailbox(
1841 TextureMailbox(mailbox, GL_TEXTURE_2D, sync_point),
1842 SingleReleaseCallbackImpl::Create(callback));
1843 EXPECT_EQ(1u, context()->NumTextures());
1844 EXPECT_EQ(0u, release_sync_point);
1846 // Transfer the resource, expect the sync points to be consistent.
1847 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
1848 resource_ids_to_transfer.push_back(resource);
1849 TransferableResourceArray list;
1850 resource_provider_->PrepareSendToParent(resource_ids_to_transfer, &list);
1851 ASSERT_EQ(1u, list.size());
1852 EXPECT_LE(sync_point, list[0].mailbox_holder.sync_point);
1854 memcmp(mailbox.name,
1855 list[0].mailbox_holder.mailbox.name,
1856 sizeof(mailbox.name)));
1857 EXPECT_EQ(0u, release_sync_point);
1859 context()->waitSyncPoint(list[0].mailbox_holder.sync_point);
1860 unsigned other_texture = context()->createTexture();
1861 context()->bindTexture(GL_TEXTURE_2D, other_texture);
1862 context()->consumeTextureCHROMIUM(GL_TEXTURE_2D, mailbox.name);
1863 uint8_t test_data[4] = { 0 };
1864 context()->GetPixels(
1865 gfx::Size(1, 1), RGBA_8888, test_data);
1866 EXPECT_EQ(0, memcmp(data, test_data, sizeof(data)));
1867 context()->produceTextureCHROMIUM(GL_TEXTURE_2D, mailbox.name);
1868 context()->deleteTexture(other_texture);
1869 list[0].mailbox_holder.sync_point = context()->insertSyncPoint();
1870 EXPECT_LT(0u, list[0].mailbox_holder.sync_point);
1872 // Receive the resource, then delete it, expect the sync points to be
1874 ReturnedResourceArray returned;
1875 TransferableResource::ReturnResources(list, &returned);
1876 resource_provider_->ReceiveReturnsFromParent(returned);
1877 EXPECT_EQ(1u, context()->NumTextures());
1878 EXPECT_EQ(0u, release_sync_point);
1880 resource_provider_->DeleteResource(resource);
1881 EXPECT_LE(list[0].mailbox_holder.sync_point, release_sync_point);
1882 EXPECT_FALSE(lost_resource);
1883 EXPECT_EQ(main_thread_task_runner_.get(), main_thread_task_runner);
1886 // We're going to do the same thing as above, but testing the case where we
1887 // delete the resource before we receive it back.
1888 sync_point = release_sync_point;
1889 EXPECT_LT(0u, sync_point);
1890 release_sync_point = 0;
1891 resource = resource_provider_->CreateResourceFromTextureMailbox(
1892 TextureMailbox(mailbox, GL_TEXTURE_2D, sync_point),
1893 SingleReleaseCallbackImpl::Create(callback));
1894 EXPECT_EQ(1u, context()->NumTextures());
1895 EXPECT_EQ(0u, release_sync_point);
1897 // Transfer the resource, expect the sync points to be consistent.
1898 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
1899 resource_ids_to_transfer.push_back(resource);
1900 TransferableResourceArray list;
1901 resource_provider_->PrepareSendToParent(resource_ids_to_transfer, &list);
1902 ASSERT_EQ(1u, list.size());
1903 EXPECT_LE(sync_point, list[0].mailbox_holder.sync_point);
1905 memcmp(mailbox.name,
1906 list[0].mailbox_holder.mailbox.name,
1907 sizeof(mailbox.name)));
1908 EXPECT_EQ(0u, release_sync_point);
1910 context()->waitSyncPoint(list[0].mailbox_holder.sync_point);
1911 unsigned other_texture = context()->createTexture();
1912 context()->bindTexture(GL_TEXTURE_2D, other_texture);
1913 context()->consumeTextureCHROMIUM(GL_TEXTURE_2D, mailbox.name);
1914 uint8_t test_data[4] = { 0 };
1915 context()->GetPixels(
1916 gfx::Size(1, 1), RGBA_8888, test_data);
1917 EXPECT_EQ(0, memcmp(data, test_data, sizeof(data)));
1918 context()->produceTextureCHROMIUM(GL_TEXTURE_2D, mailbox.name);
1919 context()->deleteTexture(other_texture);
1920 list[0].mailbox_holder.sync_point = context()->insertSyncPoint();
1921 EXPECT_LT(0u, list[0].mailbox_holder.sync_point);
1923 // Delete the resource, which shouldn't do anything.
1924 resource_provider_->DeleteResource(resource);
1925 EXPECT_EQ(1u, context()->NumTextures());
1926 EXPECT_EQ(0u, release_sync_point);
1928 // Then receive the resource which should release the mailbox, expect the
1929 // sync points to be consistent.
1930 ReturnedResourceArray returned;
1931 TransferableResource::ReturnResources(list, &returned);
1932 resource_provider_->ReceiveReturnsFromParent(returned);
1933 EXPECT_LE(list[0].mailbox_holder.sync_point, release_sync_point);
1934 EXPECT_FALSE(lost_resource);
1935 EXPECT_EQ(main_thread_task_runner_.get(), main_thread_task_runner);
1938 context()->waitSyncPoint(release_sync_point);
1939 context()->bindTexture(GL_TEXTURE_2D, texture);
1940 context()->consumeTextureCHROMIUM(GL_TEXTURE_2D, mailbox.name);
1941 context()->deleteTexture(texture);
1944 TEST_P(ResourceProviderTest, LostResourceInParent) {
1945 gfx::Size size(1, 1);
1946 ResourceFormat format = RGBA_8888;
1947 ResourceProvider::ResourceId resource =
1948 child_resource_provider_->CreateResource(
1951 ResourceProvider::TextureHintImmutable,
1953 child_resource_provider_->AllocateForTesting(resource);
1954 // Expect a GL resource to be lost.
1955 bool should_lose_resource = GetParam() == ResourceProvider::GLTexture;
1957 ReturnedResourceArray returned_to_child;
1959 resource_provider_->CreateChild(GetReturnCallback(&returned_to_child));
1961 // Transfer the resource to the parent.
1962 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
1963 resource_ids_to_transfer.push_back(resource);
1964 TransferableResourceArray list;
1965 child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
1967 EXPECT_EQ(1u, list.size());
1969 resource_provider_->ReceiveFromChild(child_id, list);
1970 resource_provider_->DeclareUsedResourcesFromChild(child_id,
1971 resource_ids_to_transfer);
1974 // Lose the output surface in the parent.
1975 resource_provider_->DidLoseOutputSurface();
1978 EXPECT_EQ(0u, returned_to_child.size());
1980 // Transfer resources back from the parent to the child. Set no resources as
1982 ResourceProvider::ResourceIdArray no_resources;
1983 resource_provider_->DeclareUsedResourcesFromChild(child_id, no_resources);
1985 // Expect a GL resource to be lost.
1986 ASSERT_EQ(1u, returned_to_child.size());
1987 EXPECT_EQ(should_lose_resource, returned_to_child[0].lost);
1988 child_resource_provider_->ReceiveReturnsFromParent(returned_to_child);
1989 returned_to_child.clear();
1992 // A GL resource should be lost.
1993 EXPECT_EQ(should_lose_resource, child_resource_provider_->IsLost(resource));
1995 // Lost resources stay in use in the parent forever.
1996 EXPECT_EQ(should_lose_resource,
1997 child_resource_provider_->InUseByConsumer(resource));
2000 TEST_P(ResourceProviderTest, LostResourceInGrandParent) {
2001 gfx::Size size(1, 1);
2002 ResourceFormat format = RGBA_8888;
2003 ResourceProvider::ResourceId resource =
2004 child_resource_provider_->CreateResource(
2007 ResourceProvider::TextureHintImmutable,
2009 child_resource_provider_->AllocateForTesting(resource);
2011 ReturnedResourceArray returned_to_child;
2013 resource_provider_->CreateChild(GetReturnCallback(&returned_to_child));
2015 // Transfer the resource to the parent.
2016 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
2017 resource_ids_to_transfer.push_back(resource);
2018 TransferableResourceArray list;
2019 child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
2021 EXPECT_EQ(1u, list.size());
2023 resource_provider_->ReceiveFromChild(child_id, list);
2024 resource_provider_->DeclareUsedResourcesFromChild(child_id,
2025 resource_ids_to_transfer);
2029 ResourceProvider::ResourceIdMap resource_map =
2030 resource_provider_->GetChildToParentMap(child_id);
2031 ResourceProvider::ResourceId parent_resource = resource_map[resource];
2032 EXPECT_NE(0u, parent_resource);
2034 // Transfer to a grandparent.
2035 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
2036 resource_ids_to_transfer.push_back(parent_resource);
2037 TransferableResourceArray list;
2038 resource_provider_->PrepareSendToParent(resource_ids_to_transfer, &list);
2040 // Receive back a lost resource from the grandparent.
2041 EXPECT_EQ(1u, list.size());
2042 EXPECT_EQ(parent_resource, list[0].id);
2043 ReturnedResourceArray returned;
2044 TransferableResource::ReturnResources(list, &returned);
2045 EXPECT_EQ(1u, returned.size());
2046 EXPECT_EQ(parent_resource, returned[0].id);
2047 returned[0].lost = true;
2048 resource_provider_->ReceiveReturnsFromParent(returned);
2050 // The resource should be lost.
2051 EXPECT_TRUE(resource_provider_->IsLost(parent_resource));
2053 // Lost resources stay in use in the parent forever.
2054 EXPECT_TRUE(resource_provider_->InUseByConsumer(parent_resource));
2058 EXPECT_EQ(0u, returned_to_child.size());
2060 // Transfer resources back from the parent to the child. Set no resources as
2062 ResourceProvider::ResourceIdArray no_resources;
2063 resource_provider_->DeclareUsedResourcesFromChild(child_id, no_resources);
2065 // Expect the resource to be lost.
2066 ASSERT_EQ(1u, returned_to_child.size());
2067 EXPECT_TRUE(returned_to_child[0].lost);
2068 child_resource_provider_->ReceiveReturnsFromParent(returned_to_child);
2069 returned_to_child.clear();
2072 // The resource should be lost.
2073 EXPECT_TRUE(child_resource_provider_->IsLost(resource));
2075 // Lost resources stay in use in the parent forever.
2076 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(resource));
2079 TEST_P(ResourceProviderTest, LostMailboxInParent) {
2080 uint32 release_sync_point = 0;
2081 bool lost_resource = false;
2082 bool release_called = false;
2083 uint32 sync_point = 0;
2084 ResourceProvider::ResourceId resource = CreateChildMailbox(
2085 &release_sync_point, &lost_resource, &release_called, &sync_point);
2087 ReturnedResourceArray returned_to_child;
2089 resource_provider_->CreateChild(GetReturnCallback(&returned_to_child));
2091 // Transfer the resource to the parent.
2092 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
2093 resource_ids_to_transfer.push_back(resource);
2094 TransferableResourceArray list;
2095 child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
2097 EXPECT_EQ(1u, list.size());
2099 resource_provider_->ReceiveFromChild(child_id, list);
2100 resource_provider_->DeclareUsedResourcesFromChild(child_id,
2101 resource_ids_to_transfer);
2104 // Lose the output surface in the parent.
2105 resource_provider_->DidLoseOutputSurface();
2108 EXPECT_EQ(0u, returned_to_child.size());
2110 // Transfer resources back from the parent to the child. Set no resources as
2112 ResourceProvider::ResourceIdArray no_resources;
2113 resource_provider_->DeclareUsedResourcesFromChild(child_id, no_resources);
2115 ASSERT_EQ(1u, returned_to_child.size());
2116 // Losing an output surface only loses hardware resources.
2117 EXPECT_EQ(returned_to_child[0].lost,
2118 GetParam() == ResourceProvider::GLTexture);
2119 child_resource_provider_->ReceiveReturnsFromParent(returned_to_child);
2120 returned_to_child.clear();
2123 // Delete the resource in the child. Expect the resource to be lost if it's
2125 child_resource_provider_->DeleteResource(resource);
2126 EXPECT_EQ(lost_resource, GetParam() == ResourceProvider::GLTexture);
2129 TEST_P(ResourceProviderTest, LostMailboxInGrandParent) {
2130 uint32 release_sync_point = 0;
2131 bool lost_resource = false;
2132 bool release_called = false;
2133 uint32 sync_point = 0;
2134 ResourceProvider::ResourceId resource = CreateChildMailbox(
2135 &release_sync_point, &lost_resource, &release_called, &sync_point);
2137 ReturnedResourceArray returned_to_child;
2139 resource_provider_->CreateChild(GetReturnCallback(&returned_to_child));
2141 // Transfer the resource to the parent.
2142 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
2143 resource_ids_to_transfer.push_back(resource);
2144 TransferableResourceArray list;
2145 child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
2147 EXPECT_EQ(1u, list.size());
2149 resource_provider_->ReceiveFromChild(child_id, list);
2150 resource_provider_->DeclareUsedResourcesFromChild(child_id,
2151 resource_ids_to_transfer);
2155 ResourceProvider::ResourceIdMap resource_map =
2156 resource_provider_->GetChildToParentMap(child_id);
2157 ResourceProvider::ResourceId parent_resource = resource_map[resource];
2158 EXPECT_NE(0u, parent_resource);
2160 // Transfer to a grandparent.
2161 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
2162 resource_ids_to_transfer.push_back(parent_resource);
2163 TransferableResourceArray list;
2164 resource_provider_->PrepareSendToParent(resource_ids_to_transfer, &list);
2166 // Receive back a lost resource from the grandparent.
2167 EXPECT_EQ(1u, list.size());
2168 EXPECT_EQ(parent_resource, list[0].id);
2169 ReturnedResourceArray returned;
2170 TransferableResource::ReturnResources(list, &returned);
2171 EXPECT_EQ(1u, returned.size());
2172 EXPECT_EQ(parent_resource, returned[0].id);
2173 returned[0].lost = true;
2174 resource_provider_->ReceiveReturnsFromParent(returned);
2178 EXPECT_EQ(0u, returned_to_child.size());
2180 // Transfer resources back from the parent to the child. Set no resources as
2182 ResourceProvider::ResourceIdArray no_resources;
2183 resource_provider_->DeclareUsedResourcesFromChild(child_id, no_resources);
2185 // Expect the resource to be lost.
2186 ASSERT_EQ(1u, returned_to_child.size());
2187 EXPECT_TRUE(returned_to_child[0].lost);
2188 child_resource_provider_->ReceiveReturnsFromParent(returned_to_child);
2189 returned_to_child.clear();
2192 // Delete the resource in the child. Expect the resource to be lost.
2193 child_resource_provider_->DeleteResource(resource);
2194 EXPECT_TRUE(lost_resource);
2197 TEST_P(ResourceProviderTest, Shutdown) {
2198 uint32 release_sync_point = 0;
2199 bool lost_resource = false;
2200 bool release_called = false;
2201 uint32 sync_point = 0;
2203 &release_sync_point, &lost_resource, &release_called, &sync_point);
2205 EXPECT_EQ(0u, release_sync_point);
2206 EXPECT_FALSE(lost_resource);
2208 child_resource_provider_.reset();
2210 if (GetParam() == ResourceProvider::GLTexture) {
2211 EXPECT_LE(sync_point, release_sync_point);
2213 EXPECT_TRUE(release_called);
2214 EXPECT_FALSE(lost_resource);
2217 TEST_P(ResourceProviderTest, ShutdownWithExportedResource) {
2218 uint32 release_sync_point = 0;
2219 bool lost_resource = false;
2220 bool release_called = false;
2221 uint32 sync_point = 0;
2222 ResourceProvider::ResourceId resource = CreateChildMailbox(
2223 &release_sync_point, &lost_resource, &release_called, &sync_point);
2225 // Transfer the resource, so we can't release it properly on shutdown.
2226 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
2227 resource_ids_to_transfer.push_back(resource);
2228 TransferableResourceArray list;
2229 child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
2232 EXPECT_EQ(0u, release_sync_point);
2233 EXPECT_FALSE(lost_resource);
2235 child_resource_provider_.reset();
2237 // Since the resource is in the parent, the child considers it lost.
2238 EXPECT_EQ(0u, release_sync_point);
2239 EXPECT_TRUE(lost_resource);
2242 TEST_P(ResourceProviderTest, LostContext) {
2243 // TextureMailbox callbacks only exist for GL textures for now.
2244 if (GetParam() != ResourceProvider::GLTexture)
2246 unsigned texture = context()->createTexture();
2247 context()->bindTexture(GL_TEXTURE_2D, texture);
2248 gpu::Mailbox mailbox;
2249 context()->genMailboxCHROMIUM(mailbox.name);
2250 context()->produceTextureCHROMIUM(GL_TEXTURE_2D, mailbox.name);
2251 uint32 sync_point = context()->insertSyncPoint();
2253 EXPECT_LT(0u, sync_point);
2255 uint32 release_sync_point = 0;
2256 bool lost_resource = false;
2257 BlockingTaskRunner* main_thread_task_runner = NULL;
2258 scoped_ptr<SingleReleaseCallbackImpl> callback =
2259 SingleReleaseCallbackImpl::Create(base::Bind(ReleaseCallback,
2260 &release_sync_point,
2262 &main_thread_task_runner));
2263 resource_provider_->CreateResourceFromTextureMailbox(
2264 TextureMailbox(mailbox, GL_TEXTURE_2D, sync_point), callback.Pass());
2266 EXPECT_EQ(0u, release_sync_point);
2267 EXPECT_FALSE(lost_resource);
2268 EXPECT_EQ(NULL, main_thread_task_runner);
2270 resource_provider_->DidLoseOutputSurface();
2271 resource_provider_.reset();
2273 EXPECT_LE(sync_point, release_sync_point);
2274 EXPECT_TRUE(lost_resource);
2275 EXPECT_EQ(main_thread_task_runner_.get(), main_thread_task_runner);
2278 TEST_P(ResourceProviderTest, ScopedSampler) {
2279 // Sampling is only supported for GL textures.
2280 if (GetParam() != ResourceProvider::GLTexture)
2283 scoped_ptr<TextureStateTrackingContext> context_owned(
2284 new TextureStateTrackingContext);
2285 TextureStateTrackingContext* context = context_owned.get();
2287 FakeOutputSurfaceClient output_surface_client;
2288 scoped_ptr<OutputSurface> output_surface(FakeOutputSurface::Create3d(
2289 context_owned.PassAs<TestWebGraphicsContext3D>()));
2290 CHECK(output_surface->BindToClient(&output_surface_client));
2292 scoped_ptr<ResourceProvider> resource_provider(
2293 ResourceProvider::Create(output_surface.get(),
2294 shared_bitmap_manager_.get(),
2301 gfx::Size size(1, 1);
2302 ResourceFormat format = RGBA_8888;
2305 ResourceProvider::ResourceId id = resource_provider->CreateResource(
2306 size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureHintImmutable, format);
2308 // Check that the texture gets created with the right sampler settings.
2309 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id))
2310 .Times(2); // Once to create and once to allocate.
2311 EXPECT_CALL(*context,
2312 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
2313 EXPECT_CALL(*context,
2314 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR));
2317 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE));
2320 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE));
2321 EXPECT_CALL(*context,
2322 texParameteri(GL_TEXTURE_2D,
2323 GL_TEXTURE_POOL_CHROMIUM,
2324 GL_TEXTURE_POOL_UNMANAGED_CHROMIUM));
2326 resource_provider->AllocateForTesting(id);
2327 Mock::VerifyAndClearExpectations(context);
2329 // Creating a sampler with the default filter should not change any texture
2332 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id));
2333 ResourceProvider::ScopedSamplerGL sampler(
2334 resource_provider.get(), id, GL_TEXTURE_2D, GL_LINEAR);
2335 Mock::VerifyAndClearExpectations(context);
2338 // Using a different filter should be reflected in the texture parameters.
2340 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id));
2343 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST));
2346 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST));
2347 ResourceProvider::ScopedSamplerGL sampler(
2348 resource_provider.get(), id, GL_TEXTURE_2D, GL_NEAREST);
2349 Mock::VerifyAndClearExpectations(context);
2352 // Test resetting to the default filter.
2354 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id));
2355 EXPECT_CALL(*context,
2356 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
2357 EXPECT_CALL(*context,
2358 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR));
2359 ResourceProvider::ScopedSamplerGL sampler(
2360 resource_provider.get(), id, GL_TEXTURE_2D, GL_LINEAR);
2361 Mock::VerifyAndClearExpectations(context);
2365 TEST_P(ResourceProviderTest, ManagedResource) {
2366 // Sampling is only supported for GL textures.
2367 if (GetParam() != ResourceProvider::GLTexture)
2370 scoped_ptr<TextureStateTrackingContext> context_owned(
2371 new TextureStateTrackingContext);
2372 TextureStateTrackingContext* context = context_owned.get();
2374 FakeOutputSurfaceClient output_surface_client;
2375 scoped_ptr<OutputSurface> output_surface(FakeOutputSurface::Create3d(
2376 context_owned.PassAs<TestWebGraphicsContext3D>()));
2377 CHECK(output_surface->BindToClient(&output_surface_client));
2379 scoped_ptr<ResourceProvider> resource_provider(
2380 ResourceProvider::Create(output_surface.get(),
2381 shared_bitmap_manager_.get(),
2388 gfx::Size size(1, 1);
2389 ResourceFormat format = RGBA_8888;
2392 // Check that the texture gets created with the right sampler settings.
2393 ResourceProvider::ResourceId id = resource_provider->CreateManagedResource(
2397 ResourceProvider::TextureHintImmutable,
2399 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id));
2400 EXPECT_CALL(*context,
2401 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
2402 EXPECT_CALL(*context,
2403 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR));
2406 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE));
2409 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE));
2410 EXPECT_CALL(*context,
2411 texParameteri(GL_TEXTURE_2D,
2412 GL_TEXTURE_POOL_CHROMIUM,
2413 GL_TEXTURE_POOL_MANAGED_CHROMIUM));
2414 resource_provider->CreateForTesting(id);
2417 Mock::VerifyAndClearExpectations(context);
2420 TEST_P(ResourceProviderTest, TextureWrapMode) {
2421 // Sampling is only supported for GL textures.
2422 if (GetParam() != ResourceProvider::GLTexture)
2425 scoped_ptr<TextureStateTrackingContext> context_owned(
2426 new TextureStateTrackingContext);
2427 TextureStateTrackingContext* context = context_owned.get();
2429 FakeOutputSurfaceClient output_surface_client;
2430 scoped_ptr<OutputSurface> output_surface(FakeOutputSurface::Create3d(
2431 context_owned.PassAs<TestWebGraphicsContext3D>()));
2432 CHECK(output_surface->BindToClient(&output_surface_client));
2434 scoped_ptr<ResourceProvider> resource_provider(
2435 ResourceProvider::Create(output_surface.get(),
2436 shared_bitmap_manager_.get(),
2443 gfx::Size size(1, 1);
2444 ResourceFormat format = RGBA_8888;
2445 GLenum texture_pool = GL_TEXTURE_POOL_UNMANAGED_CHROMIUM;
2447 for (int texture_id = 1; texture_id <= 2; ++texture_id) {
2448 GLint wrap_mode = texture_id == 1 ? GL_CLAMP_TO_EDGE : GL_REPEAT;
2449 // Check that the texture gets created with the right sampler settings.
2450 ResourceProvider::ResourceId id = resource_provider->CreateGLTexture(
2455 ResourceProvider::TextureHintImmutable,
2457 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id));
2458 EXPECT_CALL(*context,
2459 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
2460 EXPECT_CALL(*context,
2461 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR));
2462 EXPECT_CALL(*context,
2463 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, wrap_mode));
2464 EXPECT_CALL(*context,
2465 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, wrap_mode));
2466 EXPECT_CALL(*context,
2467 texParameteri(GL_TEXTURE_2D,
2468 GL_TEXTURE_POOL_CHROMIUM,
2469 GL_TEXTURE_POOL_UNMANAGED_CHROMIUM));
2470 resource_provider->CreateForTesting(id);
2473 Mock::VerifyAndClearExpectations(context);
2477 TEST_P(ResourceProviderTest, TextureHint) {
2478 // Sampling is only supported for GL textures.
2479 if (GetParam() != ResourceProvider::GLTexture)
2482 scoped_ptr<TextureStateTrackingContext> context_owned(
2483 new TextureStateTrackingContext);
2484 TextureStateTrackingContext* context = context_owned.get();
2485 context->set_support_texture_storage(true);
2486 context->set_support_texture_usage(true);
2488 FakeOutputSurfaceClient output_surface_client;
2489 scoped_ptr<OutputSurface> output_surface(FakeOutputSurface::Create3d(
2490 context_owned.PassAs<TestWebGraphicsContext3D>()));
2491 CHECK(output_surface->BindToClient(&output_surface_client));
2493 scoped_ptr<ResourceProvider> resource_provider(
2494 ResourceProvider::Create(output_surface.get(),
2495 shared_bitmap_manager_.get(),
2502 gfx::Size size(1, 1);
2503 ResourceFormat format = RGBA_8888;
2504 GLenum texture_pool = GL_TEXTURE_POOL_UNMANAGED_CHROMIUM;
2506 const ResourceProvider::TextureHint hints[4] = {
2507 ResourceProvider::TextureHintDefault,
2508 ResourceProvider::TextureHintImmutable,
2509 ResourceProvider::TextureHintFramebuffer,
2510 ResourceProvider::TextureHintImmutableFramebuffer,
2512 for (GLuint texture_id = 1; texture_id <= arraysize(hints); ++texture_id) {
2513 // Check that the texture gets created with the right sampler settings.
2514 ResourceProvider::ResourceId id =
2515 resource_provider->CreateGLTexture(size,
2519 hints[texture_id - 1],
2521 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id));
2522 EXPECT_CALL(*context,
2523 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
2524 EXPECT_CALL(*context,
2525 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR));
2528 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE));
2531 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE));
2532 EXPECT_CALL(*context,
2533 texParameteri(GL_TEXTURE_2D,
2534 GL_TEXTURE_POOL_CHROMIUM,
2535 GL_TEXTURE_POOL_UNMANAGED_CHROMIUM));
2536 // Check only TextureHintFramebuffer set GL_TEXTURE_USAGE_ANGLE.
2537 bool is_framebuffer_hint =
2538 hints[texture_id - 1] & ResourceProvider::TextureHintFramebuffer;
2539 EXPECT_CALL(*context,
2540 texParameteri(GL_TEXTURE_2D,
2541 GL_TEXTURE_USAGE_ANGLE,
2542 GL_FRAMEBUFFER_ATTACHMENT_ANGLE))
2543 .Times(is_framebuffer_hint ? 1 : 0);
2544 resource_provider->CreateForTesting(id);
2547 Mock::VerifyAndClearExpectations(context);
2551 TEST_P(ResourceProviderTest, TextureMailbox_SharedMemory) {
2552 if (GetParam() != ResourceProvider::Bitmap)
2555 gfx::Size size(64, 64);
2556 const uint32_t kBadBeef = 0xbadbeef;
2557 scoped_ptr<base::SharedMemory> shared_memory(
2558 CreateAndFillSharedMemory(size, kBadBeef));
2560 FakeOutputSurfaceClient output_surface_client;
2561 scoped_ptr<OutputSurface> output_surface(
2562 FakeOutputSurface::CreateSoftware(make_scoped_ptr(
2563 new SoftwareOutputDevice)));
2564 CHECK(output_surface->BindToClient(&output_surface_client));
2566 scoped_ptr<ResourceProvider> resource_provider(
2567 ResourceProvider::Create(output_surface.get(),
2568 shared_bitmap_manager_.get(),
2569 main_thread_task_runner_.get(),
2575 uint32 release_sync_point = 0;
2576 bool lost_resource = false;
2577 BlockingTaskRunner* main_thread_task_runner = NULL;
2578 scoped_ptr<SingleReleaseCallbackImpl> callback =
2579 SingleReleaseCallbackImpl::Create(base::Bind(&ReleaseCallback,
2580 &release_sync_point,
2582 &main_thread_task_runner));
2583 TextureMailbox mailbox(shared_memory.get(), size);
2585 ResourceProvider::ResourceId id =
2586 resource_provider->CreateResourceFromTextureMailbox(
2587 mailbox, callback.Pass());
2591 ResourceProvider::ScopedReadLockSoftware lock(resource_provider.get(), id);
2592 const SkBitmap* sk_bitmap = lock.sk_bitmap();
2593 EXPECT_EQ(sk_bitmap->width(), size.width());
2594 EXPECT_EQ(sk_bitmap->height(), size.height());
2595 EXPECT_EQ(*sk_bitmap->getAddr32(16, 16), kBadBeef);
2598 resource_provider->DeleteResource(id);
2599 EXPECT_EQ(0u, release_sync_point);
2600 EXPECT_FALSE(lost_resource);
2601 EXPECT_EQ(main_thread_task_runner_.get(), main_thread_task_runner);
2604 TEST_P(ResourceProviderTest, TextureMailbox_GLTexture2D) {
2605 // Mailboxing is only supported for GL textures.
2606 if (GetParam() != ResourceProvider::GLTexture)
2609 scoped_ptr<TextureStateTrackingContext> context_owned(
2610 new TextureStateTrackingContext);
2611 TextureStateTrackingContext* context = context_owned.get();
2613 FakeOutputSurfaceClient output_surface_client;
2614 scoped_ptr<OutputSurface> output_surface(FakeOutputSurface::Create3d(
2615 context_owned.PassAs<TestWebGraphicsContext3D>()));
2616 CHECK(output_surface->BindToClient(&output_surface_client));
2618 scoped_ptr<ResourceProvider> resource_provider(
2619 ResourceProvider::Create(output_surface.get(),
2620 shared_bitmap_manager_.get(),
2621 main_thread_task_runner_.get(),
2627 unsigned texture_id = 1;
2628 uint32 sync_point = 30;
2629 unsigned target = GL_TEXTURE_2D;
2631 EXPECT_CALL(*context, bindTexture(_, _)).Times(0);
2632 EXPECT_CALL(*context, waitSyncPoint(_)).Times(0);
2633 EXPECT_CALL(*context, insertSyncPoint()).Times(0);
2634 EXPECT_CALL(*context, produceTextureCHROMIUM(_, _)).Times(0);
2635 EXPECT_CALL(*context, consumeTextureCHROMIUM(_, _)).Times(0);
2637 gpu::Mailbox gpu_mailbox;
2638 memcpy(gpu_mailbox.name, "Hello world", strlen("Hello world") + 1);
2639 uint32 release_sync_point = 0;
2640 bool lost_resource = false;
2641 BlockingTaskRunner* main_thread_task_runner = NULL;
2642 scoped_ptr<SingleReleaseCallbackImpl> callback =
2643 SingleReleaseCallbackImpl::Create(base::Bind(&ReleaseCallback,
2644 &release_sync_point,
2646 &main_thread_task_runner));
2648 TextureMailbox mailbox(gpu_mailbox, target, sync_point);
2650 ResourceProvider::ResourceId id =
2651 resource_provider->CreateResourceFromTextureMailbox(
2652 mailbox, callback.Pass());
2655 Mock::VerifyAndClearExpectations(context);
2658 // Mailbox sync point WaitSyncPoint before using the texture.
2659 EXPECT_CALL(*context, waitSyncPoint(sync_point));
2660 resource_provider->WaitSyncPointIfNeeded(id);
2661 Mock::VerifyAndClearExpectations(context);
2663 // Using the texture does a consume of the mailbox.
2664 EXPECT_CALL(*context, bindTexture(target, texture_id));
2665 EXPECT_CALL(*context, consumeTextureCHROMIUM(target, _));
2667 EXPECT_CALL(*context, insertSyncPoint()).Times(0);
2668 EXPECT_CALL(*context, produceTextureCHROMIUM(_, _)).Times(0);
2670 ResourceProvider::ScopedReadLockGL lock(resource_provider.get(), id);
2671 Mock::VerifyAndClearExpectations(context);
2673 // When done with it, a sync point should be inserted, but no produce is
2675 EXPECT_CALL(*context, bindTexture(_, _)).Times(0);
2676 EXPECT_CALL(*context, insertSyncPoint());
2677 EXPECT_CALL(*context, produceTextureCHROMIUM(_, _)).Times(0);
2679 EXPECT_CALL(*context, waitSyncPoint(_)).Times(0);
2680 EXPECT_CALL(*context, consumeTextureCHROMIUM(_, _)).Times(0);
2683 resource_provider->DeleteResource(id);
2684 EXPECT_EQ(0u, release_sync_point);
2685 EXPECT_FALSE(lost_resource);
2686 EXPECT_EQ(main_thread_task_runner_.get(), main_thread_task_runner);
2689 TEST_P(ResourceProviderTest, TextureMailbox_GLTextureExternalOES) {
2690 // Mailboxing is only supported for GL textures.
2691 if (GetParam() != ResourceProvider::GLTexture)
2694 scoped_ptr<TextureStateTrackingContext> context_owned(
2695 new TextureStateTrackingContext);
2696 TextureStateTrackingContext* context = context_owned.get();
2698 FakeOutputSurfaceClient output_surface_client;
2699 scoped_ptr<OutputSurface> output_surface(FakeOutputSurface::Create3d(
2700 context_owned.PassAs<TestWebGraphicsContext3D>()));
2701 CHECK(output_surface->BindToClient(&output_surface_client));
2703 scoped_ptr<ResourceProvider> resource_provider(
2704 ResourceProvider::Create(output_surface.get(),
2705 shared_bitmap_manager_.get(),
2712 unsigned texture_id = 1;
2713 uint32 sync_point = 30;
2714 unsigned target = GL_TEXTURE_EXTERNAL_OES;
2716 EXPECT_CALL(*context, bindTexture(_, _)).Times(0);
2717 EXPECT_CALL(*context, waitSyncPoint(_)).Times(0);
2718 EXPECT_CALL(*context, insertSyncPoint()).Times(0);
2719 EXPECT_CALL(*context, produceTextureCHROMIUM(_, _)).Times(0);
2720 EXPECT_CALL(*context, consumeTextureCHROMIUM(_, _)).Times(0);
2722 gpu::Mailbox gpu_mailbox;
2723 memcpy(gpu_mailbox.name, "Hello world", strlen("Hello world") + 1);
2724 scoped_ptr<SingleReleaseCallbackImpl> callback =
2725 SingleReleaseCallbackImpl::Create(base::Bind(&EmptyReleaseCallback));
2727 TextureMailbox mailbox(gpu_mailbox, target, sync_point);
2729 ResourceProvider::ResourceId id =
2730 resource_provider->CreateResourceFromTextureMailbox(
2731 mailbox, callback.Pass());
2734 Mock::VerifyAndClearExpectations(context);
2737 // Mailbox sync point WaitSyncPoint before using the texture.
2738 EXPECT_CALL(*context, waitSyncPoint(sync_point));
2739 resource_provider->WaitSyncPointIfNeeded(id);
2740 Mock::VerifyAndClearExpectations(context);
2742 // Using the texture does a consume of the mailbox.
2743 EXPECT_CALL(*context, bindTexture(target, texture_id));
2744 EXPECT_CALL(*context, consumeTextureCHROMIUM(target, _));
2746 EXPECT_CALL(*context, insertSyncPoint()).Times(0);
2747 EXPECT_CALL(*context, produceTextureCHROMIUM(_, _)).Times(0);
2749 ResourceProvider::ScopedReadLockGL lock(resource_provider.get(), id);
2750 Mock::VerifyAndClearExpectations(context);
2752 // When done with it, a sync point should be inserted, but no produce is
2754 EXPECT_CALL(*context, bindTexture(_, _)).Times(0);
2755 EXPECT_CALL(*context, insertSyncPoint());
2756 EXPECT_CALL(*context, produceTextureCHROMIUM(_, _)).Times(0);
2758 EXPECT_CALL(*context, waitSyncPoint(_)).Times(0);
2759 EXPECT_CALL(*context, consumeTextureCHROMIUM(_, _)).Times(0);
2763 TEST_P(ResourceProviderTest,
2764 TextureMailbox_WaitSyncPointIfNeeded_WithSyncPoint) {
2765 // Mailboxing is only supported for GL textures.
2766 if (GetParam() != ResourceProvider::GLTexture)
2769 scoped_ptr<TextureStateTrackingContext> context_owned(
2770 new TextureStateTrackingContext);
2771 TextureStateTrackingContext* context = context_owned.get();
2773 FakeOutputSurfaceClient output_surface_client;
2774 scoped_ptr<OutputSurface> output_surface(FakeOutputSurface::Create3d(
2775 context_owned.PassAs<TestWebGraphicsContext3D>()));
2776 CHECK(output_surface->BindToClient(&output_surface_client));
2778 scoped_ptr<ResourceProvider> resource_provider(
2779 ResourceProvider::Create(output_surface.get(),
2780 shared_bitmap_manager_.get(),
2787 uint32 sync_point = 30;
2788 unsigned target = GL_TEXTURE_2D;
2790 EXPECT_CALL(*context, bindTexture(_, _)).Times(0);
2791 EXPECT_CALL(*context, waitSyncPoint(_)).Times(0);
2792 EXPECT_CALL(*context, insertSyncPoint()).Times(0);
2793 EXPECT_CALL(*context, produceTextureCHROMIUM(_, _)).Times(0);
2794 EXPECT_CALL(*context, consumeTextureCHROMIUM(_, _)).Times(0);
2796 gpu::Mailbox gpu_mailbox;
2797 memcpy(gpu_mailbox.name, "Hello world", strlen("Hello world") + 1);
2798 scoped_ptr<SingleReleaseCallbackImpl> callback =
2799 SingleReleaseCallbackImpl::Create(base::Bind(&EmptyReleaseCallback));
2801 TextureMailbox mailbox(gpu_mailbox, target, sync_point);
2803 ResourceProvider::ResourceId id =
2804 resource_provider->CreateResourceFromTextureMailbox(mailbox,
2808 Mock::VerifyAndClearExpectations(context);
2811 // First call to WaitSyncPointIfNeeded should call waitSyncPoint.
2812 EXPECT_CALL(*context, waitSyncPoint(sync_point));
2813 resource_provider->WaitSyncPointIfNeeded(id);
2814 Mock::VerifyAndClearExpectations(context);
2816 // Subsequent calls to WaitSyncPointIfNeeded shouldn't call waitSyncPoint.
2817 EXPECT_CALL(*context, waitSyncPoint(_)).Times(0);
2818 resource_provider->WaitSyncPointIfNeeded(id);
2819 Mock::VerifyAndClearExpectations(context);
2823 TEST_P(ResourceProviderTest, TextureMailbox_WaitSyncPointIfNeeded_NoSyncPoint) {
2824 // Mailboxing is only supported for GL textures.
2825 if (GetParam() != ResourceProvider::GLTexture)
2828 scoped_ptr<TextureStateTrackingContext> context_owned(
2829 new TextureStateTrackingContext);
2830 TextureStateTrackingContext* context = context_owned.get();
2832 FakeOutputSurfaceClient output_surface_client;
2833 scoped_ptr<OutputSurface> output_surface(FakeOutputSurface::Create3d(
2834 context_owned.PassAs<TestWebGraphicsContext3D>()));
2835 CHECK(output_surface->BindToClient(&output_surface_client));
2837 scoped_ptr<ResourceProvider> resource_provider(
2838 ResourceProvider::Create(output_surface.get(),
2839 shared_bitmap_manager_.get(),
2846 uint32 sync_point = 0;
2847 unsigned target = GL_TEXTURE_2D;
2849 EXPECT_CALL(*context, bindTexture(_, _)).Times(0);
2850 EXPECT_CALL(*context, waitSyncPoint(_)).Times(0);
2851 EXPECT_CALL(*context, insertSyncPoint()).Times(0);
2852 EXPECT_CALL(*context, produceTextureCHROMIUM(_, _)).Times(0);
2853 EXPECT_CALL(*context, consumeTextureCHROMIUM(_, _)).Times(0);
2855 gpu::Mailbox gpu_mailbox;
2856 memcpy(gpu_mailbox.name, "Hello world", strlen("Hello world") + 1);
2857 scoped_ptr<SingleReleaseCallbackImpl> callback =
2858 SingleReleaseCallbackImpl::Create(base::Bind(&EmptyReleaseCallback));
2860 TextureMailbox mailbox(gpu_mailbox, target, sync_point);
2862 ResourceProvider::ResourceId id =
2863 resource_provider->CreateResourceFromTextureMailbox(mailbox,
2867 Mock::VerifyAndClearExpectations(context);
2870 // WaitSyncPointIfNeeded with sync_point == 0 shouldn't call waitSyncPoint.
2871 EXPECT_CALL(*context, waitSyncPoint(_)).Times(0);
2872 resource_provider->WaitSyncPointIfNeeded(id);
2873 Mock::VerifyAndClearExpectations(context);
2877 class AllocationTrackingContext3D : public TestWebGraphicsContext3D {
2879 MOCK_METHOD0(NextTextureId, GLuint());
2880 MOCK_METHOD1(RetireTextureId, void(GLuint id));
2881 MOCK_METHOD2(bindTexture, void(GLenum target, GLuint texture));
2882 MOCK_METHOD5(texStorage2DEXT,
2885 GLuint internalformat,
2888 MOCK_METHOD9(texImage2D,
2891 GLenum internalformat,
2897 const void* pixels));
2898 MOCK_METHOD9(texSubImage2D,
2907 const void* pixels));
2908 MOCK_METHOD9(asyncTexImage2DCHROMIUM,
2911 GLenum internalformat,
2917 const void* pixels));
2918 MOCK_METHOD9(asyncTexSubImage2DCHROMIUM,
2927 const void* pixels));
2928 MOCK_METHOD8(compressedTexImage2D,
2931 GLenum internalformat,
2937 MOCK_METHOD1(waitAsyncTexImage2DCHROMIUM, void(GLenum));
2938 MOCK_METHOD4(createImageCHROMIUM, GLuint(GLsizei, GLsizei, GLenum, GLenum));
2939 MOCK_METHOD1(destroyImageCHROMIUM, void(GLuint));
2940 MOCK_METHOD1(mapImageCHROMIUM, void*(GLuint));
2941 MOCK_METHOD3(getImageParameterivCHROMIUM, void(GLuint, GLenum, GLint*));
2942 MOCK_METHOD1(unmapImageCHROMIUM, void(GLuint));
2943 MOCK_METHOD2(bindTexImage2DCHROMIUM, void(GLenum, GLint));
2944 MOCK_METHOD2(releaseTexImage2DCHROMIUM, void(GLenum, GLint));
2946 // We're mocking bindTexture, so we override
2947 // TestWebGraphicsContext3D::texParameteri to avoid assertions related to the
2948 // currently bound texture.
2949 virtual void texParameteri(GLenum target, GLenum pname, GLint param) {}
2952 TEST_P(ResourceProviderTest, TextureAllocation) {
2953 // Only for GL textures.
2954 if (GetParam() != ResourceProvider::GLTexture)
2956 scoped_ptr<AllocationTrackingContext3D> context_owned(
2957 new StrictMock<AllocationTrackingContext3D>);
2958 AllocationTrackingContext3D* context = context_owned.get();
2960 FakeOutputSurfaceClient output_surface_client;
2961 scoped_ptr<OutputSurface> output_surface(FakeOutputSurface::Create3d(
2962 context_owned.PassAs<TestWebGraphicsContext3D>()));
2963 CHECK(output_surface->BindToClient(&output_surface_client));
2965 scoped_ptr<ResourceProvider> resource_provider(
2966 ResourceProvider::Create(output_surface.get(),
2967 shared_bitmap_manager_.get(),
2974 gfx::Size size(2, 2);
2975 gfx::Vector2d offset(0, 0);
2976 gfx::Rect rect(0, 0, 2, 2);
2977 ResourceFormat format = RGBA_8888;
2978 ResourceProvider::ResourceId id = 0;
2979 uint8_t pixels[16] = { 0 };
2980 int texture_id = 123;
2982 // Lazy allocation. Don't allocate when creating the resource.
2983 id = resource_provider->CreateResource(
2984 size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureHintImmutable, format);
2986 EXPECT_CALL(*context, NextTextureId()).WillOnce(Return(texture_id));
2987 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id)).Times(1);
2988 resource_provider->CreateForTesting(id);
2990 EXPECT_CALL(*context, RetireTextureId(texture_id)).Times(1);
2991 resource_provider->DeleteResource(id);
2993 Mock::VerifyAndClearExpectations(context);
2995 // Do allocate when we set the pixels.
2996 id = resource_provider->CreateResource(
2997 size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureHintImmutable, format);
2999 EXPECT_CALL(*context, NextTextureId()).WillOnce(Return(texture_id));
3000 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id)).Times(3);
3001 EXPECT_CALL(*context, texImage2D(_, _, _, 2, 2, _, _, _, _)).Times(1);
3002 EXPECT_CALL(*context, texSubImage2D(_, _, _, _, 2, 2, _, _, _)).Times(1);
3003 resource_provider->SetPixels(id, pixels, rect, rect, offset);
3005 EXPECT_CALL(*context, RetireTextureId(texture_id)).Times(1);
3006 resource_provider->DeleteResource(id);
3008 Mock::VerifyAndClearExpectations(context);
3010 // Same for async version.
3011 id = resource_provider->CreateResource(
3012 size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureHintImmutable, format);
3013 resource_provider->AcquirePixelBuffer(id);
3015 EXPECT_CALL(*context, NextTextureId()).WillOnce(Return(texture_id));
3016 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id)).Times(2);
3017 EXPECT_CALL(*context, asyncTexImage2DCHROMIUM(_, _, _, 2, 2, _, _, _, _))
3019 resource_provider->BeginSetPixels(id);
3020 ASSERT_TRUE(resource_provider->DidSetPixelsComplete(id));
3022 resource_provider->ReleasePixelBuffer(id);
3024 EXPECT_CALL(*context, RetireTextureId(texture_id)).Times(1);
3025 resource_provider->DeleteResource(id);
3027 Mock::VerifyAndClearExpectations(context);
3030 TEST_P(ResourceProviderTest, TextureAllocationHint) {
3031 // Only for GL textures.
3032 if (GetParam() != ResourceProvider::GLTexture)
3034 scoped_ptr<AllocationTrackingContext3D> context_owned(
3035 new StrictMock<AllocationTrackingContext3D>);
3036 AllocationTrackingContext3D* context = context_owned.get();
3037 context->set_support_texture_storage(true);
3038 context->set_support_texture_usage(true);
3040 FakeOutputSurfaceClient output_surface_client;
3041 scoped_ptr<OutputSurface> output_surface(FakeOutputSurface::Create3d(
3042 context_owned.PassAs<TestWebGraphicsContext3D>()));
3043 CHECK(output_surface->BindToClient(&output_surface_client));
3045 scoped_ptr<ResourceProvider> resource_provider(
3046 ResourceProvider::Create(output_surface.get(),
3047 shared_bitmap_manager_.get(),
3054 gfx::Size size(2, 2);
3056 const ResourceFormat formats[2] = {RGBA_8888, BGRA_8888};
3057 const ResourceProvider::TextureHint hints[4] = {
3058 ResourceProvider::TextureHintDefault,
3059 ResourceProvider::TextureHintImmutable,
3060 ResourceProvider::TextureHintFramebuffer,
3061 ResourceProvider::TextureHintImmutableFramebuffer,
3063 for (size_t i = 0; i < arraysize(formats); ++i) {
3064 for (GLuint texture_id = 1; texture_id <= arraysize(hints); ++texture_id) {
3065 // Lazy allocation. Don't allocate when creating the resource.
3066 ResourceProvider::ResourceId id = resource_provider->CreateResource(
3067 size, GL_CLAMP_TO_EDGE, hints[texture_id - 1], formats[i]);
3069 EXPECT_CALL(*context, NextTextureId()).WillOnce(Return(texture_id));
3070 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id)).Times(2);
3071 bool is_immutable_hint =
3072 hints[texture_id - 1] & ResourceProvider::TextureHintImmutable;
3073 bool support_immutable_texture =
3074 is_immutable_hint && formats[i] == RGBA_8888;
3075 EXPECT_CALL(*context, texStorage2DEXT(_, _, _, 2, 2))
3076 .Times(support_immutable_texture ? 1 : 0);
3077 EXPECT_CALL(*context, texImage2D(_, _, _, 2, 2, _, _, _, _))
3078 .Times(support_immutable_texture ? 0 : 1);
3079 resource_provider->AllocateForTesting(id);
3081 EXPECT_CALL(*context, RetireTextureId(texture_id)).Times(1);
3082 resource_provider->DeleteResource(id);
3084 Mock::VerifyAndClearExpectations(context);
3089 TEST_P(ResourceProviderTest, TextureAllocationHint_BGRA) {
3090 // Only for GL textures.
3091 if (GetParam() != ResourceProvider::GLTexture)
3093 scoped_ptr<AllocationTrackingContext3D> context_owned(
3094 new StrictMock<AllocationTrackingContext3D>);
3095 AllocationTrackingContext3D* context = context_owned.get();
3096 context->set_support_texture_format_bgra8888(true);
3097 context->set_support_texture_storage(true);
3098 context->set_support_texture_usage(true);
3100 FakeOutputSurfaceClient output_surface_client;
3101 scoped_ptr<OutputSurface> output_surface(FakeOutputSurface::Create3d(
3102 context_owned.PassAs<TestWebGraphicsContext3D>()));
3103 CHECK(output_surface->BindToClient(&output_surface_client));
3105 scoped_ptr<ResourceProvider> resource_provider(
3106 ResourceProvider::Create(output_surface.get(),
3107 shared_bitmap_manager_.get(),
3114 gfx::Size size(2, 2);
3115 const ResourceFormat formats[2] = {RGBA_8888, BGRA_8888};
3117 const ResourceProvider::TextureHint hints[4] = {
3118 ResourceProvider::TextureHintDefault,
3119 ResourceProvider::TextureHintImmutable,
3120 ResourceProvider::TextureHintFramebuffer,
3121 ResourceProvider::TextureHintImmutableFramebuffer,
3123 for (size_t i = 0; i < arraysize(formats); ++i) {
3124 for (GLuint texture_id = 1; texture_id <= arraysize(hints); ++texture_id) {
3125 // Lazy allocation. Don't allocate when creating the resource.
3126 ResourceProvider::ResourceId id = resource_provider->CreateResource(
3127 size, GL_CLAMP_TO_EDGE, hints[texture_id - 1], formats[i]);
3129 EXPECT_CALL(*context, NextTextureId()).WillOnce(Return(texture_id));
3130 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id)).Times(2);
3131 bool is_immutable_hint =
3132 hints[texture_id - 1] & ResourceProvider::TextureHintImmutable;
3133 EXPECT_CALL(*context, texStorage2DEXT(_, _, _, 2, 2))
3134 .Times(is_immutable_hint ? 1 : 0);
3135 EXPECT_CALL(*context, texImage2D(_, _, _, 2, 2, _, _, _, _))
3136 .Times(is_immutable_hint ? 0 : 1);
3137 resource_provider->AllocateForTesting(id);
3139 EXPECT_CALL(*context, RetireTextureId(texture_id)).Times(1);
3140 resource_provider->DeleteResource(id);
3142 Mock::VerifyAndClearExpectations(context);
3147 TEST_P(ResourceProviderTest, PixelBuffer_GLTexture) {
3148 if (GetParam() != ResourceProvider::GLTexture)
3150 scoped_ptr<AllocationTrackingContext3D> context_owned(
3151 new StrictMock<AllocationTrackingContext3D>);
3152 AllocationTrackingContext3D* context = context_owned.get();
3154 FakeOutputSurfaceClient output_surface_client;
3155 scoped_ptr<OutputSurface> output_surface(FakeOutputSurface::Create3d(
3156 context_owned.PassAs<TestWebGraphicsContext3D>()));
3157 CHECK(output_surface->BindToClient(&output_surface_client));
3159 gfx::Size size(2, 2);
3160 ResourceFormat format = RGBA_8888;
3161 ResourceProvider::ResourceId id = 0;
3162 int texture_id = 123;
3164 scoped_ptr<ResourceProvider> resource_provider(
3165 ResourceProvider::Create(output_surface.get(),
3166 shared_bitmap_manager_.get(),
3173 id = resource_provider->CreateResource(
3174 size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureHintImmutable, format);
3175 resource_provider->AcquirePixelBuffer(id);
3177 EXPECT_CALL(*context, NextTextureId()).WillOnce(Return(texture_id));
3178 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id)).Times(2);
3179 EXPECT_CALL(*context, asyncTexImage2DCHROMIUM(_, _, _, 2, 2, _, _, _, _))
3181 resource_provider->BeginSetPixels(id);
3183 EXPECT_TRUE(resource_provider->DidSetPixelsComplete(id));
3185 resource_provider->ReleasePixelBuffer(id);
3187 EXPECT_CALL(*context, RetireTextureId(texture_id)).Times(1);
3188 resource_provider->DeleteResource(id);
3190 Mock::VerifyAndClearExpectations(context);
3193 TEST_P(ResourceProviderTest, ForcingAsyncUploadToComplete) {
3194 // Only for GL textures.
3195 if (GetParam() != ResourceProvider::GLTexture)
3197 scoped_ptr<AllocationTrackingContext3D> context_owned(
3198 new StrictMock<AllocationTrackingContext3D>);
3199 AllocationTrackingContext3D* context = context_owned.get();
3201 FakeOutputSurfaceClient output_surface_client;
3202 scoped_ptr<OutputSurface> output_surface(FakeOutputSurface::Create3d(
3203 context_owned.PassAs<TestWebGraphicsContext3D>()));
3204 CHECK(output_surface->BindToClient(&output_surface_client));
3206 gfx::Size size(2, 2);
3207 ResourceFormat format = RGBA_8888;
3208 ResourceProvider::ResourceId id = 0;
3209 int texture_id = 123;
3211 scoped_ptr<ResourceProvider> resource_provider(
3212 ResourceProvider::Create(output_surface.get(),
3213 shared_bitmap_manager_.get(),
3220 id = resource_provider->CreateResource(
3221 size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureHintImmutable, format);
3222 resource_provider->AcquirePixelBuffer(id);
3224 EXPECT_CALL(*context, NextTextureId()).WillOnce(Return(texture_id));
3225 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id)).Times(2);
3226 EXPECT_CALL(*context, asyncTexImage2DCHROMIUM(_, _, _, 2, 2, _, _, _, _))
3228 resource_provider->BeginSetPixels(id);
3230 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id)).Times(1);
3231 EXPECT_CALL(*context, waitAsyncTexImage2DCHROMIUM(GL_TEXTURE_2D)).Times(1);
3232 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, 0)).Times(1);
3233 resource_provider->ForceSetPixelsToComplete(id);
3235 resource_provider->ReleasePixelBuffer(id);
3237 EXPECT_CALL(*context, RetireTextureId(texture_id)).Times(1);
3238 resource_provider->DeleteResource(id);
3240 Mock::VerifyAndClearExpectations(context);
3243 TEST_P(ResourceProviderTest, PixelBufferLostContext) {
3244 scoped_ptr<AllocationTrackingContext3D> context_owned(
3245 new NiceMock<AllocationTrackingContext3D>);
3246 AllocationTrackingContext3D* context = context_owned.get();
3248 FakeOutputSurfaceClient output_surface_client;
3249 scoped_ptr<OutputSurface> output_surface(FakeOutputSurface::Create3d(
3250 context_owned.PassAs<TestWebGraphicsContext3D>()));
3251 CHECK(output_surface->BindToClient(&output_surface_client));
3253 gfx::Size size(2, 2);
3254 ResourceFormat format = RGBA_8888;
3255 ResourceProvider::ResourceId id = 0;
3256 int texture_id = 123;
3258 scoped_ptr<ResourceProvider> resource_provider(
3259 ResourceProvider::Create(output_surface.get(),
3260 shared_bitmap_manager_.get(),
3267 EXPECT_CALL(*context, NextTextureId()).WillRepeatedly(Return(texture_id));
3269 id = resource_provider->CreateResource(
3270 size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureHintImmutable, format);
3271 context->loseContextCHROMIUM(GL_GUILTY_CONTEXT_RESET_ARB,
3272 GL_INNOCENT_CONTEXT_RESET_ARB);
3274 resource_provider->AcquirePixelBuffer(id);
3276 void* buffer = resource_provider->MapPixelBuffer(id, &stride);
3277 EXPECT_FALSE(buffer);
3278 resource_provider->UnmapPixelBuffer(id);
3279 Mock::VerifyAndClearExpectations(context);
3282 TEST_P(ResourceProviderTest, Image_GLTexture) {
3283 // Only for GL textures.
3284 if (GetParam() != ResourceProvider::GLTexture)
3286 scoped_ptr<AllocationTrackingContext3D> context_owned(
3287 new StrictMock<AllocationTrackingContext3D>);
3288 AllocationTrackingContext3D* context = context_owned.get();
3290 FakeOutputSurfaceClient output_surface_client;
3291 scoped_ptr<OutputSurface> output_surface(FakeOutputSurface::Create3d(
3292 context_owned.PassAs<TestWebGraphicsContext3D>()));
3293 CHECK(output_surface->BindToClient(&output_surface_client));
3295 const int kWidth = 2;
3296 const int kHeight = 2;
3297 gfx::Size size(kWidth, kHeight);
3298 ResourceFormat format = RGBA_8888;
3299 ResourceProvider::ResourceId id = 0;
3300 const unsigned kTextureId = 123u;
3301 const unsigned kImageId = 234u;
3303 scoped_ptr<ResourceProvider> resource_provider(
3304 ResourceProvider::Create(output_surface.get(),
3305 shared_bitmap_manager_.get(),
3312 id = resource_provider->CreateResource(
3313 size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureHintImmutable, format);
3315 const int kStride = 4;
3316 void* dummy_mapped_buffer_address = NULL;
3319 createImageCHROMIUM(kWidth, kHeight, GL_RGBA8_OES, GL_IMAGE_MAP_CHROMIUM))
3320 .WillOnce(Return(kImageId))
3321 .RetiresOnSaturation();
3322 resource_provider->AcquireImage(id);
3324 EXPECT_CALL(*context, getImageParameterivCHROMIUM(kImageId,
3325 GL_IMAGE_ROWBYTES_CHROMIUM,
3327 .WillOnce(SetArgPointee<2>(kStride))
3328 .RetiresOnSaturation();
3329 EXPECT_CALL(*context, mapImageCHROMIUM(kImageId))
3330 .WillOnce(Return(dummy_mapped_buffer_address))
3331 .RetiresOnSaturation();
3333 resource_provider->MapImage(id, &stride);
3335 EXPECT_CALL(*context, unmapImageCHROMIUM(kImageId))
3337 .RetiresOnSaturation();
3338 resource_provider->UnmapImage(id);
3340 EXPECT_CALL(*context, NextTextureId())
3341 .WillOnce(Return(kTextureId))
3342 .RetiresOnSaturation();
3343 // Once in CreateTextureId and once in BindForSampling
3344 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, kTextureId)).Times(2)
3345 .RetiresOnSaturation();
3346 EXPECT_CALL(*context, bindTexImage2DCHROMIUM(GL_TEXTURE_2D, kImageId))
3348 .RetiresOnSaturation();
3350 ResourceProvider::ScopedSamplerGL lock_gl(
3351 resource_provider.get(), id, GL_TEXTURE_2D, GL_LINEAR);
3352 EXPECT_EQ(kTextureId, lock_gl.texture_id());
3357 getImageParameterivCHROMIUM(kImageId, GL_IMAGE_ROWBYTES_CHROMIUM, _))
3358 .WillOnce(SetArgPointee<2>(kStride))
3359 .RetiresOnSaturation();
3360 EXPECT_CALL(*context, mapImageCHROMIUM(kImageId))
3361 .WillOnce(Return(dummy_mapped_buffer_address))
3362 .RetiresOnSaturation();
3363 resource_provider->MapImage(id, &stride);
3365 EXPECT_CALL(*context, unmapImageCHROMIUM(kImageId))
3367 .RetiresOnSaturation();
3368 resource_provider->UnmapImage(id);
3370 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, kTextureId)).Times(1)
3371 .RetiresOnSaturation();
3372 EXPECT_CALL(*context, releaseTexImage2DCHROMIUM(GL_TEXTURE_2D, kImageId))
3374 .RetiresOnSaturation();
3375 EXPECT_CALL(*context, bindTexImage2DCHROMIUM(GL_TEXTURE_2D, kImageId))
3377 .RetiresOnSaturation();
3378 EXPECT_CALL(*context, RetireTextureId(kTextureId))
3380 .RetiresOnSaturation();
3382 ResourceProvider::ScopedSamplerGL lock_gl(
3383 resource_provider.get(), id, GL_TEXTURE_2D, GL_LINEAR);
3384 EXPECT_EQ(kTextureId, lock_gl.texture_id());
3387 EXPECT_CALL(*context, destroyImageCHROMIUM(kImageId))
3389 .RetiresOnSaturation();
3392 TEST_P(ResourceProviderTest, CopyResource_GLTexture) {
3393 if (GetParam() != ResourceProvider::GLTexture)
3395 scoped_ptr<AllocationTrackingContext3D> context_owned(
3396 new StrictMock<AllocationTrackingContext3D>);
3397 AllocationTrackingContext3D* context = context_owned.get();
3398 context_owned->set_support_sync_query(true);
3400 FakeOutputSurfaceClient output_surface_client;
3401 scoped_ptr<OutputSurface> output_surface(FakeOutputSurface::Create3d(
3402 context_owned.PassAs<TestWebGraphicsContext3D>()));
3403 ASSERT_TRUE(output_surface->BindToClient(&output_surface_client));
3405 const int kWidth = 2;
3406 const int kHeight = 2;
3407 gfx::Size size(kWidth, kHeight);
3408 ResourceFormat format = RGBA_8888;
3409 ResourceProvider::ResourceId source_id = 0;
3410 ResourceProvider::ResourceId dest_id = 0;
3411 const unsigned kSourceTextureId = 123u;
3412 const unsigned kDestTextureId = 321u;
3413 const unsigned kImageId = 234u;
3415 scoped_ptr<ResourceProvider> resource_provider(
3416 ResourceProvider::Create(output_surface.get(),
3417 shared_bitmap_manager_.get(),
3424 source_id = resource_provider->CreateResource(
3425 size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureHintImmutable, format);
3427 const int kStride = 4;
3428 void* dummy_mapped_buffer_address = NULL;
3431 createImageCHROMIUM(kWidth, kHeight, GL_RGBA8_OES, GL_IMAGE_MAP_CHROMIUM))
3432 .WillOnce(Return(kImageId))
3433 .RetiresOnSaturation();
3436 getImageParameterivCHROMIUM(kImageId, GL_IMAGE_ROWBYTES_CHROMIUM, _))
3437 .WillOnce(SetArgPointee<2>(kStride))
3438 .RetiresOnSaturation();
3439 EXPECT_CALL(*context, mapImageCHROMIUM(kImageId))
3440 .WillOnce(Return(dummy_mapped_buffer_address))
3441 .RetiresOnSaturation();
3442 resource_provider->AcquireImage(source_id);
3444 resource_provider->MapImage(source_id, &stride);
3445 EXPECT_CALL(*context, unmapImageCHROMIUM(kImageId))
3447 .RetiresOnSaturation();
3448 resource_provider->UnmapImage(source_id);
3449 Mock::VerifyAndClearExpectations(context);
3451 dest_id = resource_provider->CreateResource(
3452 size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureHintImmutable, format);
3454 EXPECT_CALL(*context, NextTextureId())
3455 .WillOnce(Return(kDestTextureId))
3456 .RetiresOnSaturation();
3457 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, kDestTextureId))
3459 .RetiresOnSaturation();
3460 EXPECT_CALL(*context, NextTextureId())
3461 .WillOnce(Return(kSourceTextureId))
3462 .RetiresOnSaturation();
3463 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, kSourceTextureId))
3465 .RetiresOnSaturation();
3466 EXPECT_CALL(*context, bindTexImage2DCHROMIUM(GL_TEXTURE_2D, kImageId))
3468 .RetiresOnSaturation();
3469 resource_provider->CopyResource(source_id, dest_id);
3470 Mock::VerifyAndClearExpectations(context);
3472 EXPECT_CALL(*context, destroyImageCHROMIUM(kImageId))
3474 .RetiresOnSaturation();
3475 EXPECT_CALL(*context, RetireTextureId(kSourceTextureId))
3477 .RetiresOnSaturation();
3478 EXPECT_CALL(*context, RetireTextureId(kDestTextureId))
3480 .RetiresOnSaturation();
3481 resource_provider->DeleteResource(source_id);
3482 resource_provider->DeleteResource(dest_id);
3485 void InitializeGLAndCheck(ContextSharedData* shared_data,
3486 ResourceProvider* resource_provider,
3487 FakeOutputSurface* output_surface) {
3488 scoped_ptr<ResourceProviderContext> context_owned =
3489 ResourceProviderContext::Create(shared_data);
3490 ResourceProviderContext* context = context_owned.get();
3492 scoped_refptr<TestContextProvider> context_provider =
3493 TestContextProvider::Create(
3494 context_owned.PassAs<TestWebGraphicsContext3D>());
3495 output_surface->InitializeAndSetContext3d(context_provider);
3496 resource_provider->InitializeGL();
3498 CheckCreateResource(ResourceProvider::GLTexture, resource_provider, context);
3501 TEST(ResourceProviderTest, BasicInitializeGLSoftware) {
3502 scoped_ptr<ContextSharedData> shared_data = ContextSharedData::Create();
3503 bool delegated_rendering = false;
3504 scoped_ptr<FakeOutputSurface> output_surface(
3505 FakeOutputSurface::CreateDeferredGL(
3506 scoped_ptr<SoftwareOutputDevice>(new SoftwareOutputDevice),
3507 delegated_rendering));
3508 FakeOutputSurfaceClient client(output_surface.get());
3509 EXPECT_TRUE(output_surface->BindToClient(&client));
3510 scoped_ptr<SharedBitmapManager> shared_bitmap_manager(
3511 new TestSharedBitmapManager());
3512 scoped_ptr<ResourceProvider> resource_provider(
3513 ResourceProvider::Create(output_surface.get(),
3514 shared_bitmap_manager.get(),
3521 CheckCreateResource(ResourceProvider::Bitmap, resource_provider.get(), NULL);
3523 InitializeGLAndCheck(shared_data.get(),
3524 resource_provider.get(),
3525 output_surface.get());
3527 resource_provider->InitializeSoftware();
3528 output_surface->ReleaseGL();
3529 CheckCreateResource(ResourceProvider::Bitmap, resource_provider.get(), NULL);
3531 InitializeGLAndCheck(shared_data.get(),
3532 resource_provider.get(),
3533 output_surface.get());
3536 TEST_P(ResourceProviderTest, CompressedTextureETC1Allocate) {
3537 if (GetParam() != ResourceProvider::GLTexture)
3540 scoped_ptr<AllocationTrackingContext3D> context_owned(
3541 new AllocationTrackingContext3D);
3542 AllocationTrackingContext3D* context = context_owned.get();
3543 context_owned->set_support_compressed_texture_etc1(true);
3545 FakeOutputSurfaceClient output_surface_client;
3546 scoped_ptr<OutputSurface> output_surface(FakeOutputSurface::Create3d(
3547 context_owned.PassAs<TestWebGraphicsContext3D>()));
3548 CHECK(output_surface->BindToClient(&output_surface_client));
3550 gfx::Size size(4, 4);
3551 scoped_ptr<ResourceProvider> resource_provider(
3552 ResourceProvider::Create(output_surface.get(),
3553 shared_bitmap_manager_.get(),
3559 int texture_id = 123;
3561 ResourceProvider::ResourceId id = resource_provider->CreateResource(
3562 size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureHintImmutable, ETC1);
3564 EXPECT_CALL(*context, NextTextureId()).WillOnce(Return(texture_id));
3565 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id)).Times(2);
3566 resource_provider->AllocateForTesting(id);
3568 EXPECT_CALL(*context, RetireTextureId(texture_id)).Times(1);
3569 resource_provider->DeleteResource(id);
3572 TEST_P(ResourceProviderTest, CompressedTextureETC1SetPixels) {
3573 if (GetParam() != ResourceProvider::GLTexture)
3576 scoped_ptr<AllocationTrackingContext3D> context_owned(
3577 new AllocationTrackingContext3D);
3578 AllocationTrackingContext3D* context = context_owned.get();
3579 context_owned->set_support_compressed_texture_etc1(true);
3581 FakeOutputSurfaceClient output_surface_client;
3582 scoped_ptr<OutputSurface> output_surface(FakeOutputSurface::Create3d(
3583 context_owned.PassAs<TestWebGraphicsContext3D>()));
3584 CHECK(output_surface->BindToClient(&output_surface_client));
3586 gfx::Size size(4, 4);
3587 scoped_ptr<ResourceProvider> resource_provider(
3588 ResourceProvider::Create(output_surface.get(),
3589 shared_bitmap_manager_.get(),
3595 int texture_id = 123;
3598 ResourceProvider::ResourceId id = resource_provider->CreateResource(
3599 size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureHintImmutable, ETC1);
3601 EXPECT_CALL(*context, NextTextureId()).WillOnce(Return(texture_id));
3602 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id)).Times(3);
3603 EXPECT_CALL(*context,
3604 compressedTexImage2D(
3605 _, 0, _, size.width(), size.height(), _, _, _)).Times(1);
3606 resource_provider->SetPixels(
3607 id, pixels, gfx::Rect(size), gfx::Rect(size), gfx::Vector2d(0, 0));
3609 EXPECT_CALL(*context, RetireTextureId(texture_id)).Times(1);
3610 resource_provider->DeleteResource(id);
3613 INSTANTIATE_TEST_CASE_P(
3614 ResourceProviderTests,
3615 ResourceProviderTest,
3616 ::testing::Values(ResourceProvider::GLTexture, ResourceProvider::Bitmap));
3618 class TextureIdAllocationTrackingContext : public TestWebGraphicsContext3D {
3620 virtual GLuint NextTextureId() OVERRIDE {
3621 base::AutoLock lock(namespace_->lock);
3622 return namespace_->next_texture_id++;
3624 virtual void RetireTextureId(GLuint) OVERRIDE {}
3625 GLuint PeekTextureId() {
3626 base::AutoLock lock(namespace_->lock);
3627 return namespace_->next_texture_id;
3631 TEST(ResourceProviderTest, TextureAllocationChunkSize) {
3632 scoped_ptr<TextureIdAllocationTrackingContext> context_owned(
3633 new TextureIdAllocationTrackingContext);
3634 TextureIdAllocationTrackingContext* context = context_owned.get();
3636 FakeOutputSurfaceClient output_surface_client;
3637 scoped_ptr<OutputSurface> output_surface(FakeOutputSurface::Create3d(
3638 context_owned.PassAs<TestWebGraphicsContext3D>()));
3639 CHECK(output_surface->BindToClient(&output_surface_client));
3640 scoped_ptr<SharedBitmapManager> shared_bitmap_manager(
3641 new TestSharedBitmapManager());
3643 gfx::Size size(1, 1);
3644 ResourceFormat format = RGBA_8888;
3647 size_t kTextureAllocationChunkSize = 1;
3648 scoped_ptr<ResourceProvider> resource_provider(
3649 ResourceProvider::Create(output_surface.get(),
3650 shared_bitmap_manager.get(),
3654 kTextureAllocationChunkSize,
3657 ResourceProvider::ResourceId id = resource_provider->CreateResource(
3658 size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureHintImmutable, format);
3659 resource_provider->AllocateForTesting(id);
3660 Mock::VerifyAndClearExpectations(context);
3662 DCHECK_EQ(2u, context->PeekTextureId());
3663 resource_provider->DeleteResource(id);
3667 size_t kTextureAllocationChunkSize = 8;
3668 scoped_ptr<ResourceProvider> resource_provider(
3669 ResourceProvider::Create(output_surface.get(),
3670 shared_bitmap_manager.get(),
3674 kTextureAllocationChunkSize,
3677 ResourceProvider::ResourceId id = resource_provider->CreateResource(
3678 size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureHintImmutable, format);
3679 resource_provider->AllocateForTesting(id);
3680 Mock::VerifyAndClearExpectations(context);
3682 DCHECK_EQ(10u, context->PeekTextureId());
3683 resource_provider->DeleteResource(id);