[refactor] More post-NSS WebCrypto cleanups (utility functions).
[chromium-blink-merge.git] / cc / resources / resource_provider_unittest.cc
blob12075b56c81b091d0dd5b45d772734489791de66
1 // Copyright 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "cc/resources/resource_provider.h"
7 #include <algorithm>
8 #include <map>
9 #include <set>
10 #include <vector>
12 #include "base/bind.h"
13 #include "base/containers/hash_tables.h"
14 #include "base/logging.h"
15 #include "base/memory/ref_counted.h"
16 #include "cc/base/scoped_ptr_deque.h"
17 #include "cc/output/output_surface.h"
18 #include "cc/resources/returned_resource.h"
19 #include "cc/resources/shared_bitmap_manager.h"
20 #include "cc/resources/single_release_callback.h"
21 #include "cc/test/fake_output_surface.h"
22 #include "cc/test/fake_output_surface_client.h"
23 #include "cc/test/test_gpu_memory_buffer_manager.h"
24 #include "cc/test/test_shared_bitmap_manager.h"
25 #include "cc/test/test_texture.h"
26 #include "cc/test/test_web_graphics_context_3d.h"
27 #include "cc/trees/blocking_task_runner.h"
28 #include "gpu/GLES2/gl2extchromium.h"
29 #include "testing/gmock/include/gmock/gmock.h"
30 #include "testing/gtest/include/gtest/gtest.h"
31 #include "third_party/khronos/GLES2/gl2.h"
32 #include "third_party/khronos/GLES2/gl2ext.h"
33 #include "ui/gfx/geometry/rect.h"
34 #include "ui/gfx/gpu_memory_buffer.h"
36 using testing::Mock;
37 using testing::NiceMock;
38 using testing::Return;
39 using testing::SetArgPointee;
40 using testing::StrictMock;
41 using testing::_;
43 namespace cc {
44 namespace {
46 static void EmptyReleaseCallback(uint32 sync_point,
47 bool lost_resource,
48 BlockingTaskRunner* main_thread_task_runner) {
51 static void ReleaseCallback(
52 uint32* release_sync_point,
53 bool* release_lost_resource,
54 BlockingTaskRunner** release_main_thread_task_runner,
55 uint32 sync_point,
56 bool lost_resource,
57 BlockingTaskRunner* main_thread_task_runner) {
58 *release_sync_point = sync_point;
59 *release_lost_resource = lost_resource;
60 *release_main_thread_task_runner = main_thread_task_runner;
63 static void SharedBitmapReleaseCallback(
64 scoped_ptr<SharedBitmap> bitmap,
65 uint32 sync_point,
66 bool lost_resource,
67 BlockingTaskRunner* main_thread_task_runner) {
70 static void ReleaseSharedBitmapCallback(
71 scoped_ptr<SharedBitmap> shared_bitmap,
72 bool* release_called,
73 uint32* release_sync_point,
74 bool* lost_resource_result,
75 uint32 sync_point,
76 bool lost_resource,
77 BlockingTaskRunner* main_thread_task_runner) {
78 *release_called = true;
79 *release_sync_point = sync_point;
80 *lost_resource_result = lost_resource;
83 static scoped_ptr<SharedBitmap> CreateAndFillSharedBitmap(
84 SharedBitmapManager* manager,
85 const gfx::Size& size,
86 uint32_t value) {
87 scoped_ptr<SharedBitmap> shared_bitmap = manager->AllocateSharedBitmap(size);
88 CHECK(shared_bitmap);
89 uint32_t* pixels = reinterpret_cast<uint32_t*>(shared_bitmap->pixels());
90 CHECK(pixels);
91 std::fill_n(pixels, size.GetArea(), value);
92 return shared_bitmap.Pass();
95 class TextureStateTrackingContext : public TestWebGraphicsContext3D {
96 public:
97 MOCK_METHOD2(bindTexture, void(GLenum target, GLuint texture));
98 MOCK_METHOD3(texParameteri, void(GLenum target, GLenum pname, GLint param));
99 MOCK_METHOD1(waitSyncPoint, void(GLuint sync_point));
100 MOCK_METHOD0(insertSyncPoint, GLuint(void));
101 MOCK_METHOD3(produceTextureDirectCHROMIUM,
102 void(GLuint texture, GLenum target, const GLbyte* mailbox));
103 MOCK_METHOD2(createAndConsumeTextureCHROMIUM,
104 unsigned(GLenum target, const GLbyte* mailbox));
106 // Force all textures to be consecutive numbers starting at "1",
107 // so we easily can test for them.
108 GLuint NextTextureId() override {
109 base::AutoLock lock(namespace_->lock);
110 return namespace_->next_texture_id++;
112 void RetireTextureId(GLuint) override {}
115 // Shared data between multiple ResourceProviderContext. This contains mailbox
116 // contents as well as information about sync points.
117 class ContextSharedData {
118 public:
119 static scoped_ptr<ContextSharedData> Create() {
120 return make_scoped_ptr(new ContextSharedData());
123 uint32 InsertSyncPoint() { return next_sync_point_++; }
125 void GenMailbox(GLbyte* mailbox) {
126 memset(mailbox, 0, GL_MAILBOX_SIZE_CHROMIUM);
127 memcpy(mailbox, &next_mailbox_, sizeof(next_mailbox_));
128 ++next_mailbox_;
131 void ProduceTexture(const GLbyte* mailbox_name,
132 uint32 sync_point,
133 scoped_refptr<TestTexture> texture) {
134 unsigned mailbox = 0;
135 memcpy(&mailbox, mailbox_name, sizeof(mailbox));
136 ASSERT_TRUE(mailbox && mailbox < next_mailbox_);
137 textures_[mailbox] = texture;
138 ASSERT_LT(sync_point_for_mailbox_[mailbox], sync_point);
139 sync_point_for_mailbox_[mailbox] = sync_point;
142 scoped_refptr<TestTexture> ConsumeTexture(const GLbyte* mailbox_name,
143 uint32 sync_point) {
144 unsigned mailbox = 0;
145 memcpy(&mailbox, mailbox_name, sizeof(mailbox));
146 DCHECK(mailbox && mailbox < next_mailbox_);
148 // If the latest sync point the context has waited on is before the sync
149 // point for when the mailbox was set, pretend we never saw that
150 // ProduceTexture.
151 if (sync_point_for_mailbox_[mailbox] > sync_point) {
152 NOTREACHED();
153 return scoped_refptr<TestTexture>();
155 return textures_[mailbox];
158 private:
159 ContextSharedData() : next_sync_point_(1), next_mailbox_(1) {}
161 uint32 next_sync_point_;
162 unsigned next_mailbox_;
163 typedef base::hash_map<unsigned, scoped_refptr<TestTexture>> TextureMap;
164 TextureMap textures_;
165 base::hash_map<unsigned, uint32> sync_point_for_mailbox_;
168 class ResourceProviderContext : public TestWebGraphicsContext3D {
169 public:
170 static scoped_ptr<ResourceProviderContext> Create(
171 ContextSharedData* shared_data) {
172 return make_scoped_ptr(new ResourceProviderContext(shared_data));
175 GLuint insertSyncPoint() override {
176 uint32 sync_point = shared_data_->InsertSyncPoint();
177 // Commit the produceTextureCHROMIUM calls at this point, so that
178 // they're associated with the sync point.
179 for (PendingProduceTextureList::iterator it =
180 pending_produce_textures_.begin();
181 it != pending_produce_textures_.end();
182 ++it) {
183 shared_data_->ProduceTexture(
184 (*it)->mailbox, sync_point, (*it)->texture);
186 pending_produce_textures_.clear();
187 return sync_point;
190 void waitSyncPoint(GLuint sync_point) override {
191 last_waited_sync_point_ = std::max(sync_point, last_waited_sync_point_);
194 unsigned last_waited_sync_point() const { return last_waited_sync_point_; }
196 void texStorage2DEXT(GLenum target,
197 GLint levels,
198 GLuint internalformat,
199 GLint width,
200 GLint height) override {
201 CheckTextureIsBound(target);
202 ASSERT_EQ(static_cast<unsigned>(GL_TEXTURE_2D), target);
203 ASSERT_EQ(1, levels);
204 GLenum format = GL_RGBA;
205 switch (internalformat) {
206 case GL_RGBA8_OES:
207 break;
208 case GL_BGRA8_EXT:
209 format = GL_BGRA_EXT;
210 break;
211 default:
212 NOTREACHED();
214 AllocateTexture(gfx::Size(width, height), format);
217 void texImage2D(GLenum target,
218 GLint level,
219 GLenum internalformat,
220 GLsizei width,
221 GLsizei height,
222 GLint border,
223 GLenum format,
224 GLenum type,
225 const void* pixels) override {
226 CheckTextureIsBound(target);
227 ASSERT_EQ(static_cast<unsigned>(GL_TEXTURE_2D), target);
228 ASSERT_FALSE(level);
229 ASSERT_EQ(internalformat, format);
230 ASSERT_FALSE(border);
231 ASSERT_EQ(static_cast<unsigned>(GL_UNSIGNED_BYTE), type);
232 AllocateTexture(gfx::Size(width, height), format);
233 if (pixels)
234 SetPixels(0, 0, width, height, pixels);
237 void texSubImage2D(GLenum target,
238 GLint level,
239 GLint xoffset,
240 GLint yoffset,
241 GLsizei width,
242 GLsizei height,
243 GLenum format,
244 GLenum type,
245 const void* pixels) override {
246 CheckTextureIsBound(target);
247 ASSERT_EQ(static_cast<unsigned>(GL_TEXTURE_2D), target);
248 ASSERT_FALSE(level);
249 ASSERT_EQ(static_cast<unsigned>(GL_UNSIGNED_BYTE), type);
251 base::AutoLock lock_for_texture_access(namespace_->lock);
252 ASSERT_EQ(GLDataFormat(BoundTexture(target)->format), format);
254 ASSERT_TRUE(pixels);
255 SetPixels(xoffset, yoffset, width, height, pixels);
258 void genMailboxCHROMIUM(GLbyte* mailbox) override {
259 return shared_data_->GenMailbox(mailbox);
262 void produceTextureDirectCHROMIUM(GLuint texture,
263 GLenum target,
264 const GLbyte* mailbox) override {
265 // Delay moving the texture into the mailbox until the next
266 // InsertSyncPoint, so that it is not visible to other contexts that
267 // haven't waited on that sync point.
268 scoped_ptr<PendingProduceTexture> pending(new PendingProduceTexture);
269 memcpy(pending->mailbox, mailbox, sizeof(pending->mailbox));
270 base::AutoLock lock_for_texture_access(namespace_->lock);
271 pending->texture = UnboundTexture(texture);
272 pending_produce_textures_.push_back(pending.Pass());
275 GLuint createAndConsumeTextureCHROMIUM(GLenum target,
276 const GLbyte* mailbox) override {
277 GLuint texture_id = createTexture();
278 base::AutoLock lock_for_texture_access(namespace_->lock);
279 scoped_refptr<TestTexture> texture =
280 shared_data_->ConsumeTexture(mailbox, last_waited_sync_point_);
281 namespace_->textures.Replace(texture_id, texture);
282 return texture_id;
285 void GetPixels(const gfx::Size& size,
286 ResourceFormat format,
287 uint8_t* pixels) {
288 CheckTextureIsBound(GL_TEXTURE_2D);
289 base::AutoLock lock_for_texture_access(namespace_->lock);
290 scoped_refptr<TestTexture> texture = BoundTexture(GL_TEXTURE_2D);
291 ASSERT_EQ(texture->size, size);
292 ASSERT_EQ(texture->format, format);
293 memcpy(pixels, texture->data.get(), TextureSizeBytes(size, format));
296 protected:
297 explicit ResourceProviderContext(ContextSharedData* shared_data)
298 : shared_data_(shared_data),
299 last_waited_sync_point_(0) {}
301 private:
302 void AllocateTexture(const gfx::Size& size, GLenum format) {
303 CheckTextureIsBound(GL_TEXTURE_2D);
304 ResourceFormat texture_format = RGBA_8888;
305 switch (format) {
306 case GL_RGBA:
307 texture_format = RGBA_8888;
308 break;
309 case GL_BGRA_EXT:
310 texture_format = BGRA_8888;
311 break;
313 base::AutoLock lock_for_texture_access(namespace_->lock);
314 BoundTexture(GL_TEXTURE_2D)->Reallocate(size, texture_format);
317 void SetPixels(int xoffset,
318 int yoffset,
319 int width,
320 int height,
321 const void* pixels) {
322 CheckTextureIsBound(GL_TEXTURE_2D);
323 base::AutoLock lock_for_texture_access(namespace_->lock);
324 scoped_refptr<TestTexture> texture = BoundTexture(GL_TEXTURE_2D);
325 ASSERT_TRUE(texture->data.get());
326 ASSERT_TRUE(xoffset >= 0 && xoffset + width <= texture->size.width());
327 ASSERT_TRUE(yoffset >= 0 && yoffset + height <= texture->size.height());
328 ASSERT_TRUE(pixels);
329 size_t in_pitch = TextureSizeBytes(gfx::Size(width, 1), texture->format);
330 size_t out_pitch =
331 TextureSizeBytes(gfx::Size(texture->size.width(), 1), texture->format);
332 uint8_t* dest = texture->data.get() + yoffset * out_pitch +
333 TextureSizeBytes(gfx::Size(xoffset, 1), texture->format);
334 const uint8_t* src = static_cast<const uint8_t*>(pixels);
335 for (int i = 0; i < height; ++i) {
336 memcpy(dest, src, in_pitch);
337 dest += out_pitch;
338 src += in_pitch;
342 struct PendingProduceTexture {
343 GLbyte mailbox[GL_MAILBOX_SIZE_CHROMIUM];
344 scoped_refptr<TestTexture> texture;
346 typedef ScopedPtrDeque<PendingProduceTexture> PendingProduceTextureList;
347 ContextSharedData* shared_data_;
348 GLuint last_waited_sync_point_;
349 PendingProduceTextureList pending_produce_textures_;
352 void GetResourcePixels(ResourceProvider* resource_provider,
353 ResourceProviderContext* context,
354 ResourceId id,
355 const gfx::Size& size,
356 ResourceFormat format,
357 uint8_t* pixels) {
358 resource_provider->WaitSyncPointIfNeeded(id);
359 switch (resource_provider->default_resource_type()) {
360 case ResourceProvider::RESOURCE_TYPE_GL_TEXTURE: {
361 ResourceProvider::ScopedReadLockGL lock_gl(resource_provider, id);
362 ASSERT_NE(0U, lock_gl.texture_id());
363 context->bindTexture(GL_TEXTURE_2D, lock_gl.texture_id());
364 context->GetPixels(size, format, pixels);
365 break;
367 case ResourceProvider::RESOURCE_TYPE_BITMAP: {
368 ResourceProvider::ScopedReadLockSoftware lock_software(resource_provider,
369 id);
370 memcpy(pixels,
371 lock_software.sk_bitmap()->getPixels(),
372 lock_software.sk_bitmap()->getSize());
373 break;
378 class ResourceProviderTest
379 : public testing::TestWithParam<ResourceProvider::ResourceType> {
380 public:
381 explicit ResourceProviderTest(bool child_needs_sync_point)
382 : shared_data_(ContextSharedData::Create()),
383 context3d_(NULL),
384 child_context_(NULL),
385 main_thread_task_runner_(BlockingTaskRunner::Create(NULL)) {
386 switch (GetParam()) {
387 case ResourceProvider::RESOURCE_TYPE_GL_TEXTURE: {
388 scoped_ptr<ResourceProviderContext> context3d(
389 ResourceProviderContext::Create(shared_data_.get()));
390 context3d_ = context3d.get();
392 scoped_refptr<TestContextProvider> context_provider =
393 TestContextProvider::Create(context3d.Pass());
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 if (child_needs_sync_point) {
401 child_output_surface_ =
402 FakeOutputSurface::Create3d(child_context_owned.Pass());
403 } else {
404 child_output_surface_ = FakeOutputSurface::CreateNoRequireSyncPoint(
405 child_context_owned.Pass());
407 break;
409 case ResourceProvider::RESOURCE_TYPE_BITMAP:
410 output_surface_ = FakeOutputSurface::CreateSoftware(
411 make_scoped_ptr(new SoftwareOutputDevice));
412 child_output_surface_ = FakeOutputSurface::CreateSoftware(
413 make_scoped_ptr(new SoftwareOutputDevice));
414 break;
416 CHECK(output_surface_->BindToClient(&output_surface_client_));
417 CHECK(child_output_surface_->BindToClient(&child_output_surface_client_));
419 shared_bitmap_manager_.reset(new TestSharedBitmapManager);
420 gpu_memory_buffer_manager_.reset(new TestGpuMemoryBufferManager);
422 resource_provider_ = ResourceProvider::Create(
423 output_surface_.get(), shared_bitmap_manager_.get(),
424 gpu_memory_buffer_manager_.get(), main_thread_task_runner_.get(), 0,
425 false, 1, use_image_texture_targets_);
426 child_resource_provider_ = ResourceProvider::Create(
427 child_output_surface_.get(), shared_bitmap_manager_.get(),
428 gpu_memory_buffer_manager_.get(), main_thread_task_runner_.get(), 0,
429 false, 1, use_image_texture_targets_);
432 ResourceProviderTest() : ResourceProviderTest(true) {}
434 static void CollectResources(ReturnedResourceArray* array,
435 const ReturnedResourceArray& returned,
436 BlockingTaskRunner* main_thread_task_runner) {
437 array->insert(array->end(), returned.begin(), returned.end());
440 static ReturnCallback GetReturnCallback(ReturnedResourceArray* array) {
441 return base::Bind(&ResourceProviderTest::CollectResources, array);
444 static void SetResourceFilter(ResourceProvider* resource_provider,
445 ResourceId id,
446 GLenum filter) {
447 ResourceProvider::ScopedSamplerGL sampler(
448 resource_provider, id, GL_TEXTURE_2D, filter);
451 ResourceProviderContext* context() { return context3d_; }
453 ResourceId CreateChildMailbox(uint32* release_sync_point,
454 bool* lost_resource,
455 bool* release_called,
456 uint32* sync_point) {
457 if (GetParam() == ResourceProvider::RESOURCE_TYPE_GL_TEXTURE) {
458 unsigned texture = child_context_->createTexture();
459 gpu::Mailbox gpu_mailbox;
460 child_context_->genMailboxCHROMIUM(gpu_mailbox.name);
461 child_context_->produceTextureDirectCHROMIUM(texture, GL_TEXTURE_2D,
462 gpu_mailbox.name);
463 *sync_point = child_context_->insertSyncPoint();
464 EXPECT_LT(0u, *sync_point);
466 scoped_ptr<SharedBitmap> shared_bitmap;
467 scoped_ptr<SingleReleaseCallbackImpl> callback =
468 SingleReleaseCallbackImpl::Create(base::Bind(
469 ReleaseSharedBitmapCallback, base::Passed(&shared_bitmap),
470 release_called, release_sync_point, lost_resource));
471 return child_resource_provider_->CreateResourceFromTextureMailbox(
472 TextureMailbox(gpu_mailbox, GL_TEXTURE_2D, *sync_point),
473 callback.Pass());
474 } else {
475 gfx::Size size(64, 64);
476 scoped_ptr<SharedBitmap> shared_bitmap(
477 CreateAndFillSharedBitmap(shared_bitmap_manager_.get(), size, 0));
479 SharedBitmap* shared_bitmap_ptr = shared_bitmap.get();
480 scoped_ptr<SingleReleaseCallbackImpl> callback =
481 SingleReleaseCallbackImpl::Create(base::Bind(
482 ReleaseSharedBitmapCallback, base::Passed(&shared_bitmap),
483 release_called, release_sync_point, lost_resource));
484 return child_resource_provider_->CreateResourceFromTextureMailbox(
485 TextureMailbox(shared_bitmap_ptr, size), callback.Pass());
489 public:
490 static std::vector<unsigned> use_image_texture_targets() {
491 return use_image_texture_targets_;
494 protected:
495 static std::vector<unsigned> use_image_texture_targets_;
496 scoped_ptr<ContextSharedData> shared_data_;
497 ResourceProviderContext* context3d_;
498 ResourceProviderContext* child_context_;
499 FakeOutputSurfaceClient output_surface_client_;
500 FakeOutputSurfaceClient child_output_surface_client_;
501 scoped_ptr<OutputSurface> output_surface_;
502 scoped_ptr<OutputSurface> child_output_surface_;
503 scoped_ptr<BlockingTaskRunner> main_thread_task_runner_;
504 scoped_ptr<ResourceProvider> resource_provider_;
505 scoped_ptr<ResourceProvider> child_resource_provider_;
506 scoped_ptr<TestSharedBitmapManager> shared_bitmap_manager_;
507 scoped_ptr<TestGpuMemoryBufferManager> gpu_memory_buffer_manager_;
510 std::vector<unsigned> ResourceProviderTest::use_image_texture_targets_ =
511 std::vector<unsigned>(static_cast<size_t>(gfx::BufferFormat::LAST) + 1,
512 GL_TEXTURE_2D);
514 void CheckCreateResource(ResourceProvider::ResourceType expected_default_type,
515 ResourceProvider* resource_provider,
516 ResourceProviderContext* context) {
517 DCHECK_EQ(expected_default_type, resource_provider->default_resource_type());
519 gfx::Size size(1, 1);
520 ResourceFormat format = RGBA_8888;
521 size_t pixel_size = TextureSizeBytes(size, format);
522 ASSERT_EQ(4U, pixel_size);
524 ResourceId id = resource_provider->CreateResource(
525 size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE, format);
526 EXPECT_EQ(1, static_cast<int>(resource_provider->num_resources()));
527 if (expected_default_type == ResourceProvider::RESOURCE_TYPE_GL_TEXTURE)
528 EXPECT_EQ(0u, context->NumTextures());
530 uint8_t data[4] = { 1, 2, 3, 4 };
531 resource_provider->CopyToResource(id, data, size);
532 if (expected_default_type == ResourceProvider::RESOURCE_TYPE_GL_TEXTURE)
533 EXPECT_EQ(1u, context->NumTextures());
535 uint8_t result[4] = { 0 };
536 GetResourcePixels(resource_provider, context, id, size, format, result);
537 EXPECT_EQ(0, memcmp(data, result, pixel_size));
539 resource_provider->DeleteResource(id);
540 EXPECT_EQ(0, static_cast<int>(resource_provider->num_resources()));
541 if (expected_default_type == ResourceProvider::RESOURCE_TYPE_GL_TEXTURE)
542 EXPECT_EQ(0u, context->NumTextures());
545 TEST_P(ResourceProviderTest, Basic) {
546 CheckCreateResource(GetParam(), resource_provider_.get(), context());
549 TEST_P(ResourceProviderTest, SimpleUpload) {
550 gfx::Size size(2, 2);
551 ResourceFormat format = RGBA_8888;
552 size_t pixel_size = TextureSizeBytes(size, format);
553 ASSERT_EQ(16U, pixel_size);
555 ResourceId id = resource_provider_->CreateResource(
556 size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE, format);
558 uint8_t image[16] = {0};
559 resource_provider_->CopyToResource(id, image, size);
561 uint8_t result[16] = {0};
562 uint8_t expected[16] = {0};
563 GetResourcePixels(resource_provider_.get(), context(), id, size, format,
564 result);
565 EXPECT_EQ(0, memcmp(expected, result, pixel_size));
568 for (uint8_t i = 0; i < pixel_size; ++i)
569 image[i] = i;
570 resource_provider_->CopyToResource(id, image, size);
572 uint8_t result[16] = {0};
573 uint8_t expected[16] = {
574 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15};
575 GetResourcePixels(resource_provider_.get(), context(), id, size, format,
576 result);
577 EXPECT_EQ(0, memcmp(expected, result, pixel_size));
581 TEST_P(ResourceProviderTest, TransferGLResources) {
582 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE)
583 return;
584 gfx::Size size(1, 1);
585 ResourceFormat format = RGBA_8888;
586 size_t pixel_size = TextureSizeBytes(size, format);
587 ASSERT_EQ(4U, pixel_size);
589 ResourceId id1 = child_resource_provider_->CreateResource(
590 size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE, format);
591 uint8_t data1[4] = { 1, 2, 3, 4 };
592 child_resource_provider_->CopyToResource(id1, data1, size);
594 ResourceId id2 = child_resource_provider_->CreateResource(
595 size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE, format);
596 uint8_t data2[4] = { 5, 5, 5, 5 };
597 child_resource_provider_->CopyToResource(id2, data2, size);
599 ResourceId id3 = child_resource_provider_->CreateResource(
600 size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE, format);
602 ResourceProvider::ScopedWriteLockGpuMemoryBuffer lock(
603 child_resource_provider_.get(), id3);
604 EXPECT_TRUE(lock.GetGpuMemoryBuffer());
607 GLuint external_texture_id = child_context_->createExternalTexture();
609 gpu::Mailbox external_mailbox;
610 child_context_->genMailboxCHROMIUM(external_mailbox.name);
611 child_context_->produceTextureDirectCHROMIUM(
612 external_texture_id, GL_TEXTURE_EXTERNAL_OES, external_mailbox.name);
613 const GLuint external_sync_point = child_context_->insertSyncPoint();
614 ResourceId id4 = child_resource_provider_->CreateResourceFromTextureMailbox(
615 TextureMailbox(external_mailbox, GL_TEXTURE_EXTERNAL_OES,
616 external_sync_point),
617 SingleReleaseCallbackImpl::Create(base::Bind(&EmptyReleaseCallback)));
619 ReturnedResourceArray returned_to_child;
620 int child_id =
621 resource_provider_->CreateChild(GetReturnCallback(&returned_to_child));
623 // Transfer some resources to the parent.
624 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
625 resource_ids_to_transfer.push_back(id1);
626 resource_ids_to_transfer.push_back(id2);
627 resource_ids_to_transfer.push_back(id3);
628 resource_ids_to_transfer.push_back(id4);
629 TransferableResourceArray list;
630 child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
631 &list);
632 ASSERT_EQ(4u, list.size());
633 EXPECT_NE(0u, list[0].mailbox_holder.sync_point);
634 EXPECT_NE(0u, list[1].mailbox_holder.sync_point);
635 EXPECT_EQ(list[0].mailbox_holder.sync_point,
636 list[1].mailbox_holder.sync_point);
637 EXPECT_NE(0u, list[2].mailbox_holder.sync_point);
638 EXPECT_EQ(list[0].mailbox_holder.sync_point,
639 list[2].mailbox_holder.sync_point);
640 EXPECT_EQ(external_sync_point, list[3].mailbox_holder.sync_point);
641 EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_2D),
642 list[0].mailbox_holder.texture_target);
643 EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_2D),
644 list[1].mailbox_holder.texture_target);
645 EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_2D),
646 list[2].mailbox_holder.texture_target);
647 EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_EXTERNAL_OES),
648 list[3].mailbox_holder.texture_target);
649 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id1));
650 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id2));
651 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id3));
652 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id4));
653 resource_provider_->ReceiveFromChild(child_id, list);
654 EXPECT_NE(list[0].mailbox_holder.sync_point,
655 context3d_->last_waited_sync_point());
657 resource_provider_->WaitSyncPointIfNeeded(list[0].id);
658 ResourceProvider::ScopedReadLockGL lock(resource_provider_.get(),
659 list[0].id);
661 EXPECT_EQ(list[0].mailbox_holder.sync_point,
662 context3d_->last_waited_sync_point());
663 ResourceProvider::ResourceIdSet resource_ids_to_receive;
664 resource_ids_to_receive.insert(id1);
665 resource_ids_to_receive.insert(id2);
666 resource_ids_to_receive.insert(id3);
667 resource_ids_to_receive.insert(id4);
668 resource_provider_->DeclareUsedResourcesFromChild(child_id,
669 resource_ids_to_receive);
672 EXPECT_EQ(4u, resource_provider_->num_resources());
673 ResourceProvider::ResourceIdMap resource_map =
674 resource_provider_->GetChildToParentMap(child_id);
675 ResourceId mapped_id1 = resource_map[id1];
676 ResourceId mapped_id2 = resource_map[id2];
677 ResourceId mapped_id3 = resource_map[id3];
678 ResourceId mapped_id4 = resource_map[id4];
679 EXPECT_NE(0u, mapped_id1);
680 EXPECT_NE(0u, mapped_id2);
681 EXPECT_NE(0u, mapped_id3);
682 EXPECT_NE(0u, mapped_id4);
683 EXPECT_FALSE(resource_provider_->InUseByConsumer(id1));
684 EXPECT_FALSE(resource_provider_->InUseByConsumer(id2));
685 EXPECT_FALSE(resource_provider_->InUseByConsumer(id3));
686 EXPECT_FALSE(resource_provider_->InUseByConsumer(id4));
688 uint8_t result[4] = { 0 };
689 GetResourcePixels(
690 resource_provider_.get(), context(), mapped_id1, size, format, result);
691 EXPECT_EQ(0, memcmp(data1, result, pixel_size));
693 GetResourcePixels(
694 resource_provider_.get(), context(), mapped_id2, size, format, result);
695 EXPECT_EQ(0, memcmp(data2, result, pixel_size));
698 // Check that transfering again the same resource from the child to the
699 // parent works.
700 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
701 resource_ids_to_transfer.push_back(id1);
702 resource_ids_to_transfer.push_back(id2);
703 resource_ids_to_transfer.push_back(id3);
704 TransferableResourceArray list;
705 child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
706 &list);
707 EXPECT_EQ(3u, list.size());
708 EXPECT_EQ(id1, list[0].id);
709 EXPECT_EQ(id2, list[1].id);
710 EXPECT_EQ(id3, list[2].id);
711 EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_2D),
712 list[0].mailbox_holder.texture_target);
713 EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_2D),
714 list[1].mailbox_holder.texture_target);
715 EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_2D),
716 list[2].mailbox_holder.texture_target);
717 ReturnedResourceArray returned;
718 TransferableResource::ReturnResources(list, &returned);
719 child_resource_provider_->ReceiveReturnsFromParent(returned);
720 // ids were exported twice, we returned them only once, they should still
721 // be in-use.
722 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id1));
723 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id2));
724 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id3));
727 EXPECT_EQ(0u, returned_to_child.size());
729 // Transfer resources back from the parent to the child. Set no resources as
730 // being in use.
731 ResourceProvider::ResourceIdSet no_resources;
732 resource_provider_->DeclareUsedResourcesFromChild(child_id, no_resources);
734 ASSERT_EQ(4u, returned_to_child.size());
735 EXPECT_NE(0u, returned_to_child[0].sync_point);
736 EXPECT_NE(0u, returned_to_child[1].sync_point);
737 EXPECT_NE(0u, returned_to_child[2].sync_point);
738 EXPECT_NE(0u, returned_to_child[3].sync_point);
739 EXPECT_FALSE(returned_to_child[0].lost);
740 EXPECT_FALSE(returned_to_child[1].lost);
741 EXPECT_FALSE(returned_to_child[2].lost);
742 EXPECT_FALSE(returned_to_child[3].lost);
743 child_resource_provider_->ReceiveReturnsFromParent(returned_to_child);
744 returned_to_child.clear();
746 EXPECT_FALSE(child_resource_provider_->InUseByConsumer(id1));
747 EXPECT_FALSE(child_resource_provider_->InUseByConsumer(id2));
748 EXPECT_FALSE(child_resource_provider_->InUseByConsumer(id3));
749 EXPECT_FALSE(child_resource_provider_->InUseByConsumer(id4));
752 child_resource_provider_->WaitSyncPointIfNeeded(id1);
753 ResourceProvider::ScopedReadLockGL lock(child_resource_provider_.get(),
754 id1);
755 ASSERT_NE(0U, lock.texture_id());
756 child_context_->bindTexture(GL_TEXTURE_2D, lock.texture_id());
757 child_context_->GetPixels(size, format, result);
758 EXPECT_EQ(0, memcmp(data1, result, pixel_size));
761 child_resource_provider_->WaitSyncPointIfNeeded(id2);
762 ResourceProvider::ScopedReadLockGL lock(child_resource_provider_.get(),
763 id2);
764 ASSERT_NE(0U, lock.texture_id());
765 child_context_->bindTexture(GL_TEXTURE_2D, lock.texture_id());
766 child_context_->GetPixels(size, format, result);
767 EXPECT_EQ(0, memcmp(data2, result, pixel_size));
770 child_resource_provider_->WaitSyncPointIfNeeded(id3);
771 ResourceProvider::ScopedReadLockGL lock(child_resource_provider_.get(),
772 id3);
773 ASSERT_NE(0U, lock.texture_id());
774 child_context_->bindTexture(GL_TEXTURE_2D, lock.texture_id());
777 // Transfer resources to the parent again.
778 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
779 resource_ids_to_transfer.push_back(id1);
780 resource_ids_to_transfer.push_back(id2);
781 resource_ids_to_transfer.push_back(id3);
782 resource_ids_to_transfer.push_back(id4);
783 TransferableResourceArray list;
784 child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
785 &list);
786 ASSERT_EQ(4u, list.size());
787 EXPECT_EQ(id1, list[0].id);
788 EXPECT_EQ(id2, list[1].id);
789 EXPECT_EQ(id3, list[2].id);
790 EXPECT_EQ(id4, list[3].id);
791 EXPECT_NE(0u, list[0].mailbox_holder.sync_point);
792 EXPECT_NE(0u, list[1].mailbox_holder.sync_point);
793 EXPECT_NE(0u, list[2].mailbox_holder.sync_point);
794 EXPECT_NE(0u, list[3].mailbox_holder.sync_point);
795 EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_2D),
796 list[0].mailbox_holder.texture_target);
797 EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_2D),
798 list[1].mailbox_holder.texture_target);
799 EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_2D),
800 list[2].mailbox_holder.texture_target);
801 EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_EXTERNAL_OES),
802 list[3].mailbox_holder.texture_target);
803 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id1));
804 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id2));
805 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id3));
806 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id4));
807 resource_provider_->ReceiveFromChild(child_id, list);
808 ResourceProvider::ResourceIdSet resource_ids_to_receive;
809 resource_ids_to_receive.insert(id1);
810 resource_ids_to_receive.insert(id2);
811 resource_ids_to_receive.insert(id3);
812 resource_ids_to_receive.insert(id4);
813 resource_provider_->DeclareUsedResourcesFromChild(child_id,
814 resource_ids_to_receive);
817 EXPECT_EQ(0u, returned_to_child.size());
819 EXPECT_EQ(4u, resource_provider_->num_resources());
820 resource_provider_->DestroyChild(child_id);
821 EXPECT_EQ(0u, resource_provider_->num_resources());
823 ASSERT_EQ(4u, returned_to_child.size());
824 EXPECT_NE(0u, returned_to_child[0].sync_point);
825 EXPECT_NE(0u, returned_to_child[1].sync_point);
826 EXPECT_NE(0u, returned_to_child[2].sync_point);
827 EXPECT_NE(0u, returned_to_child[3].sync_point);
828 EXPECT_FALSE(returned_to_child[0].lost);
829 EXPECT_FALSE(returned_to_child[1].lost);
830 EXPECT_FALSE(returned_to_child[2].lost);
831 EXPECT_FALSE(returned_to_child[3].lost);
834 class ResourceProviderTestNoSyncPoint : public ResourceProviderTest {
835 public:
836 ResourceProviderTestNoSyncPoint() : ResourceProviderTest(false) {
837 EXPECT_EQ(ResourceProvider::RESOURCE_TYPE_GL_TEXTURE, GetParam());
841 TEST_P(ResourceProviderTestNoSyncPoint, TransferGLResources) {
842 gfx::Size size(1, 1);
843 ResourceFormat format = RGBA_8888;
844 size_t pixel_size = TextureSizeBytes(size, format);
845 ASSERT_EQ(4U, pixel_size);
847 ResourceId id1 = child_resource_provider_->CreateResource(
848 size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE, format);
849 uint8_t data1[4] = {1, 2, 3, 4};
850 child_resource_provider_->CopyToResource(id1, data1, size);
852 ResourceId id2 = child_resource_provider_->CreateResource(
853 size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE, format);
855 // Ensure locking the memory buffer doesn't create an unnecessary sync
856 // point.
857 ResourceProvider::ScopedWriteLockGpuMemoryBuffer lock(
858 child_resource_provider_.get(), id2);
859 EXPECT_TRUE(lock.GetGpuMemoryBuffer());
862 GLuint external_texture_id = child_context_->createExternalTexture();
864 // A sync point is specified directly and should be used.
865 gpu::Mailbox external_mailbox;
866 child_context_->genMailboxCHROMIUM(external_mailbox.name);
867 child_context_->produceTextureDirectCHROMIUM(
868 external_texture_id, GL_TEXTURE_EXTERNAL_OES, external_mailbox.name);
869 const GLuint external_sync_point = child_context_->insertSyncPoint();
870 ResourceId id3 = child_resource_provider_->CreateResourceFromTextureMailbox(
871 TextureMailbox(external_mailbox, GL_TEXTURE_EXTERNAL_OES,
872 external_sync_point),
873 SingleReleaseCallbackImpl::Create(base::Bind(&EmptyReleaseCallback)));
875 ReturnedResourceArray returned_to_child;
876 int child_id =
877 resource_provider_->CreateChild(GetReturnCallback(&returned_to_child));
878 resource_provider_->SetChildNeedsSyncPoints(child_id, false);
880 // Transfer some resources to the parent.
881 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
882 resource_ids_to_transfer.push_back(id1);
883 resource_ids_to_transfer.push_back(id2);
884 resource_ids_to_transfer.push_back(id3);
885 TransferableResourceArray list;
886 child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
887 &list);
888 ASSERT_EQ(3u, list.size());
889 // Standard resources shouldn't require creating and sending a sync point.
890 EXPECT_EQ(0u, list[0].mailbox_holder.sync_point);
891 EXPECT_EQ(0u, list[1].mailbox_holder.sync_point);
892 // A given sync point should be passed through.
893 EXPECT_EQ(external_sync_point, list[2].mailbox_holder.sync_point);
894 resource_provider_->ReceiveFromChild(child_id, list);
896 ResourceProvider::ResourceIdSet resource_ids_to_receive;
897 resource_ids_to_receive.insert(id1);
898 resource_ids_to_receive.insert(id2);
899 resource_ids_to_receive.insert(id3);
900 resource_provider_->DeclareUsedResourcesFromChild(child_id,
901 resource_ids_to_receive);
905 EXPECT_EQ(0u, returned_to_child.size());
907 // Transfer resources back from the parent to the child. Set no resources as
908 // being in use.
909 ResourceProvider::ResourceIdSet no_resources;
910 resource_provider_->DeclareUsedResourcesFromChild(child_id, no_resources);
912 ASSERT_EQ(3u, returned_to_child.size());
913 std::map<ResourceId, unsigned int> returned_sync_points;
914 for (const auto& returned : returned_to_child)
915 returned_sync_points[returned.id] = returned.sync_point;
917 EXPECT_TRUE(returned_sync_points.find(id1) != returned_sync_points.end());
918 // No new sync point should be created transferring back.
919 EXPECT_TRUE(returned_sync_points.find(id1) != returned_sync_points.end());
920 EXPECT_EQ(0u, returned_sync_points[id1]);
921 EXPECT_TRUE(returned_sync_points.find(id2) != returned_sync_points.end());
922 EXPECT_EQ(0u, returned_sync_points[id2]);
923 // Original sync point given should be returned.
924 EXPECT_TRUE(returned_sync_points.find(id3) != returned_sync_points.end());
925 EXPECT_EQ(external_sync_point, returned_sync_points[id3]);
926 EXPECT_FALSE(returned_to_child[0].lost);
927 EXPECT_FALSE(returned_to_child[1].lost);
928 EXPECT_FALSE(returned_to_child[2].lost);
929 child_resource_provider_->ReceiveReturnsFromParent(returned_to_child);
930 returned_to_child.clear();
933 resource_provider_->DestroyChild(child_id);
936 INSTANTIATE_TEST_CASE_P(
937 ResourceProviderTests,
938 ResourceProviderTestNoSyncPoint,
939 ::testing::Values(ResourceProvider::RESOURCE_TYPE_GL_TEXTURE));
941 TEST_P(ResourceProviderTest, ReadLockCountStopsReturnToChildOrDelete) {
942 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE)
943 return;
944 gfx::Size size(1, 1);
945 ResourceFormat format = RGBA_8888;
947 ResourceId id1 = child_resource_provider_->CreateResource(
948 size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE, format);
949 uint8_t data1[4] = {1, 2, 3, 4};
950 child_resource_provider_->CopyToResource(id1, data1, size);
952 ReturnedResourceArray returned_to_child;
953 int child_id =
954 resource_provider_->CreateChild(GetReturnCallback(&returned_to_child));
956 // Transfer some resources to the parent.
957 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
958 resource_ids_to_transfer.push_back(id1);
959 TransferableResourceArray list;
960 child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
961 &list);
962 ASSERT_EQ(1u, list.size());
963 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id1));
965 resource_provider_->ReceiveFromChild(child_id, list);
967 resource_provider_->WaitSyncPointIfNeeded(list[0].id);
968 ResourceProvider::ScopedReadLockGL lock(resource_provider_.get(),
969 list[0].id);
971 resource_provider_->DeclareUsedResourcesFromChild(
972 child_id, ResourceProvider::ResourceIdSet());
973 EXPECT_EQ(0u, returned_to_child.size());
976 EXPECT_EQ(1u, returned_to_child.size());
977 child_resource_provider_->ReceiveReturnsFromParent(returned_to_child);
980 child_resource_provider_->WaitSyncPointIfNeeded(id1);
981 ResourceProvider::ScopedReadLockGL lock(child_resource_provider_.get(),
982 id1);
983 child_resource_provider_->DeleteResource(id1);
984 EXPECT_EQ(1u, child_resource_provider_->num_resources());
985 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id1));
988 EXPECT_EQ(0u, child_resource_provider_->num_resources());
989 resource_provider_->DestroyChild(child_id);
992 class TestFence : public ResourceProvider::Fence {
993 public:
994 TestFence() {}
996 void Set() override {}
997 bool HasPassed() override { return passed; }
998 void Wait() override {}
1000 bool passed = false;
1002 private:
1003 ~TestFence() override {}
1006 TEST_P(ResourceProviderTest, ReadLockFenceStopsReturnToChildOrDelete) {
1007 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE)
1008 return;
1009 gfx::Size size(1, 1);
1010 ResourceFormat format = RGBA_8888;
1012 ResourceId id1 = child_resource_provider_->CreateResource(
1013 size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE, format);
1014 uint8_t data1[4] = {1, 2, 3, 4};
1015 child_resource_provider_->CopyToResource(id1, data1, size);
1016 child_resource_provider_->EnableReadLockFencesForTesting(id1);
1017 ReturnedResourceArray returned_to_child;
1018 int child_id =
1019 resource_provider_->CreateChild(GetReturnCallback(&returned_to_child));
1021 // Transfer some resources to the parent.
1022 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
1023 resource_ids_to_transfer.push_back(id1);
1024 TransferableResourceArray list;
1025 child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
1026 &list);
1027 ASSERT_EQ(1u, list.size());
1028 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id1));
1029 EXPECT_TRUE(list[0].read_lock_fences_enabled);
1031 resource_provider_->ReceiveFromChild(child_id, list);
1033 scoped_refptr<TestFence> fence(new TestFence);
1034 resource_provider_->SetReadLockFence(fence.get());
1036 unsigned parent_id = list.front().id;
1037 resource_provider_->WaitSyncPointIfNeeded(parent_id);
1038 ResourceProvider::ScopedReadLockGL lock(resource_provider_.get(),
1039 parent_id);
1041 resource_provider_->DeclareUsedResourcesFromChild(
1042 child_id, ResourceProvider::ResourceIdSet());
1043 EXPECT_EQ(0u, returned_to_child.size());
1045 resource_provider_->DeclareUsedResourcesFromChild(
1046 child_id, ResourceProvider::ResourceIdSet());
1047 EXPECT_EQ(0u, returned_to_child.size());
1048 fence->passed = true;
1050 resource_provider_->DeclareUsedResourcesFromChild(
1051 child_id, ResourceProvider::ResourceIdSet());
1052 EXPECT_EQ(1u, returned_to_child.size());
1054 child_resource_provider_->ReceiveReturnsFromParent(returned_to_child);
1055 child_resource_provider_->DeleteResource(id1);
1056 EXPECT_EQ(0u, child_resource_provider_->num_resources());
1059 TEST_P(ResourceProviderTest, ReadLockFenceDestroyChild) {
1060 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE)
1061 return;
1062 gfx::Size size(1, 1);
1063 ResourceFormat format = RGBA_8888;
1065 ResourceId id1 = child_resource_provider_->CreateResource(
1066 size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE, format);
1067 uint8_t data[4] = {1, 2, 3, 4};
1068 child_resource_provider_->CopyToResource(id1, data, size);
1069 child_resource_provider_->EnableReadLockFencesForTesting(id1);
1071 ResourceId id2 = child_resource_provider_->CreateResource(
1072 size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE, format);
1073 child_resource_provider_->CopyToResource(id2, data, size);
1075 ReturnedResourceArray returned_to_child;
1076 int child_id =
1077 resource_provider_->CreateChild(GetReturnCallback(&returned_to_child));
1079 // Transfer resources to the parent.
1080 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
1081 resource_ids_to_transfer.push_back(id1);
1082 resource_ids_to_transfer.push_back(id2);
1083 TransferableResourceArray list;
1084 child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
1085 &list);
1086 ASSERT_EQ(2u, list.size());
1087 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id1));
1088 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id2));
1090 resource_provider_->ReceiveFromChild(child_id, list);
1092 scoped_refptr<TestFence> fence(new TestFence);
1093 resource_provider_->SetReadLockFence(fence.get());
1095 for (size_t i = 0; i < list.size(); i++) {
1096 unsigned parent_id = list[i].id;
1097 resource_provider_->WaitSyncPointIfNeeded(parent_id);
1098 ResourceProvider::ScopedReadLockGL lock(resource_provider_.get(),
1099 parent_id);
1102 EXPECT_EQ(0u, returned_to_child.size());
1104 EXPECT_EQ(2u, resource_provider_->num_resources());
1106 resource_provider_->DestroyChild(child_id);
1108 EXPECT_EQ(0u, resource_provider_->num_resources());
1109 EXPECT_EQ(2u, returned_to_child.size());
1111 // id1 should be lost and id2 should not.
1112 EXPECT_EQ(returned_to_child[0].lost, returned_to_child[0].id == id1);
1113 EXPECT_EQ(returned_to_child[1].lost, returned_to_child[1].id == id1);
1115 child_resource_provider_->ReceiveReturnsFromParent(returned_to_child);
1116 child_resource_provider_->DeleteResource(id1);
1117 child_resource_provider_->DeleteResource(id2);
1118 EXPECT_EQ(0u, child_resource_provider_->num_resources());
1121 TEST_P(ResourceProviderTest, ReadLockFenceContextLost) {
1122 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE)
1123 return;
1124 gfx::Size size(1, 1);
1125 ResourceFormat format = RGBA_8888;
1127 ResourceId id1 = child_resource_provider_->CreateResource(
1128 size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE, format);
1129 uint8_t data[4] = {1, 2, 3, 4};
1130 child_resource_provider_->CopyToResource(id1, data, size);
1131 child_resource_provider_->EnableReadLockFencesForTesting(id1);
1133 ResourceId id2 = child_resource_provider_->CreateResource(
1134 size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE, format);
1135 child_resource_provider_->CopyToResource(id2, data, size);
1137 ReturnedResourceArray returned_to_child;
1138 int child_id =
1139 resource_provider_->CreateChild(GetReturnCallback(&returned_to_child));
1141 // Transfer resources to the parent.
1142 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
1143 resource_ids_to_transfer.push_back(id1);
1144 resource_ids_to_transfer.push_back(id2);
1145 TransferableResourceArray list;
1146 child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
1147 &list);
1148 ASSERT_EQ(2u, list.size());
1149 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id1));
1150 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id2));
1152 resource_provider_->ReceiveFromChild(child_id, list);
1154 scoped_refptr<TestFence> fence(new TestFence);
1155 resource_provider_->SetReadLockFence(fence.get());
1157 for (size_t i = 0; i < list.size(); i++) {
1158 unsigned parent_id = list[i].id;
1159 resource_provider_->WaitSyncPointIfNeeded(parent_id);
1160 ResourceProvider::ScopedReadLockGL lock(resource_provider_.get(),
1161 parent_id);
1164 EXPECT_EQ(0u, returned_to_child.size());
1166 EXPECT_EQ(2u, resource_provider_->num_resources());
1167 resource_provider_->DidLoseOutputSurface();
1168 resource_provider_ = nullptr;
1170 EXPECT_EQ(2u, returned_to_child.size());
1172 EXPECT_TRUE(returned_to_child[0].lost);
1173 EXPECT_TRUE(returned_to_child[1].lost);
1176 TEST_P(ResourceProviderTest, TransferSoftwareResources) {
1177 if (GetParam() != ResourceProvider::RESOURCE_TYPE_BITMAP)
1178 return;
1180 gfx::Size size(1, 1);
1181 ResourceFormat format = RGBA_8888;
1182 size_t pixel_size = TextureSizeBytes(size, format);
1183 ASSERT_EQ(4U, pixel_size);
1185 ResourceId id1 = child_resource_provider_->CreateResource(
1186 size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE, format);
1187 uint8_t data1[4] = { 1, 2, 3, 4 };
1188 child_resource_provider_->CopyToResource(id1, data1, size);
1190 ResourceId id2 = child_resource_provider_->CreateResource(
1191 size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE, format);
1192 uint8_t data2[4] = { 5, 5, 5, 5 };
1193 child_resource_provider_->CopyToResource(id2, data2, size);
1195 scoped_ptr<SharedBitmap> shared_bitmap(CreateAndFillSharedBitmap(
1196 shared_bitmap_manager_.get(), gfx::Size(1, 1), 0));
1197 SharedBitmap* shared_bitmap_ptr = shared_bitmap.get();
1198 ResourceId id3 = child_resource_provider_->CreateResourceFromTextureMailbox(
1199 TextureMailbox(shared_bitmap_ptr, gfx::Size(1, 1)),
1200 SingleReleaseCallbackImpl::Create(base::Bind(
1201 &SharedBitmapReleaseCallback, base::Passed(&shared_bitmap))));
1203 ReturnedResourceArray returned_to_child;
1204 int child_id =
1205 resource_provider_->CreateChild(GetReturnCallback(&returned_to_child));
1207 // Transfer some resources to the parent.
1208 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
1209 resource_ids_to_transfer.push_back(id1);
1210 resource_ids_to_transfer.push_back(id2);
1211 resource_ids_to_transfer.push_back(id3);
1212 TransferableResourceArray list;
1213 child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
1214 &list);
1215 ASSERT_EQ(3u, list.size());
1216 EXPECT_EQ(0u, list[0].mailbox_holder.sync_point);
1217 EXPECT_EQ(0u, list[1].mailbox_holder.sync_point);
1218 EXPECT_EQ(0u, list[2].mailbox_holder.sync_point);
1219 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id1));
1220 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id2));
1221 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id3));
1222 resource_provider_->ReceiveFromChild(child_id, list);
1223 ResourceProvider::ResourceIdSet resource_ids_to_receive;
1224 resource_ids_to_receive.insert(id1);
1225 resource_ids_to_receive.insert(id2);
1226 resource_ids_to_receive.insert(id3);
1227 resource_provider_->DeclareUsedResourcesFromChild(child_id,
1228 resource_ids_to_receive);
1231 EXPECT_EQ(3u, resource_provider_->num_resources());
1232 ResourceProvider::ResourceIdMap resource_map =
1233 resource_provider_->GetChildToParentMap(child_id);
1234 ResourceId mapped_id1 = resource_map[id1];
1235 ResourceId mapped_id2 = resource_map[id2];
1236 ResourceId mapped_id3 = resource_map[id3];
1237 EXPECT_NE(0u, mapped_id1);
1238 EXPECT_NE(0u, mapped_id2);
1239 EXPECT_NE(0u, mapped_id3);
1240 EXPECT_FALSE(resource_provider_->InUseByConsumer(id1));
1241 EXPECT_FALSE(resource_provider_->InUseByConsumer(id2));
1242 EXPECT_FALSE(resource_provider_->InUseByConsumer(id3));
1244 uint8_t result[4] = { 0 };
1245 GetResourcePixels(
1246 resource_provider_.get(), context(), mapped_id1, size, format, result);
1247 EXPECT_EQ(0, memcmp(data1, result, pixel_size));
1249 GetResourcePixels(
1250 resource_provider_.get(), context(), mapped_id2, size, format, result);
1251 EXPECT_EQ(0, memcmp(data2, result, pixel_size));
1254 // Check that transfering again the same resource from the child to the
1255 // parent works.
1256 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
1257 resource_ids_to_transfer.push_back(id1);
1258 resource_ids_to_transfer.push_back(id2);
1259 TransferableResourceArray list;
1260 child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
1261 &list);
1262 EXPECT_EQ(2u, list.size());
1263 EXPECT_EQ(id1, list[0].id);
1264 EXPECT_EQ(id2, list[1].id);
1265 ReturnedResourceArray returned;
1266 TransferableResource::ReturnResources(list, &returned);
1267 child_resource_provider_->ReceiveReturnsFromParent(returned);
1268 // ids were exported twice, we returned them only once, they should still
1269 // be in-use.
1270 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id1));
1271 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id2));
1274 EXPECT_EQ(0u, returned_to_child.size());
1276 // Transfer resources back from the parent to the child. Set no resources as
1277 // being in use.
1278 ResourceProvider::ResourceIdSet no_resources;
1279 resource_provider_->DeclareUsedResourcesFromChild(child_id, no_resources);
1281 ASSERT_EQ(3u, returned_to_child.size());
1282 EXPECT_EQ(0u, returned_to_child[0].sync_point);
1283 EXPECT_EQ(0u, returned_to_child[1].sync_point);
1284 EXPECT_EQ(0u, returned_to_child[2].sync_point);
1285 std::set<ResourceId> expected_ids;
1286 expected_ids.insert(id1);
1287 expected_ids.insert(id2);
1288 expected_ids.insert(id3);
1289 std::set<ResourceId> returned_ids;
1290 for (unsigned i = 0; i < 3; i++)
1291 returned_ids.insert(returned_to_child[i].id);
1292 EXPECT_EQ(expected_ids, returned_ids);
1293 EXPECT_FALSE(returned_to_child[0].lost);
1294 EXPECT_FALSE(returned_to_child[1].lost);
1295 EXPECT_FALSE(returned_to_child[2].lost);
1296 child_resource_provider_->ReceiveReturnsFromParent(returned_to_child);
1297 returned_to_child.clear();
1299 EXPECT_FALSE(child_resource_provider_->InUseByConsumer(id1));
1300 EXPECT_FALSE(child_resource_provider_->InUseByConsumer(id2));
1301 EXPECT_FALSE(child_resource_provider_->InUseByConsumer(id3));
1304 ResourceProvider::ScopedReadLockSoftware lock(
1305 child_resource_provider_.get(), id1);
1306 const SkBitmap* sk_bitmap = lock.sk_bitmap();
1307 EXPECT_EQ(sk_bitmap->width(), size.width());
1308 EXPECT_EQ(sk_bitmap->height(), size.height());
1309 EXPECT_EQ(0, memcmp(data1, sk_bitmap->getPixels(), pixel_size));
1312 ResourceProvider::ScopedReadLockSoftware lock(
1313 child_resource_provider_.get(), id2);
1314 const SkBitmap* sk_bitmap = lock.sk_bitmap();
1315 EXPECT_EQ(sk_bitmap->width(), size.width());
1316 EXPECT_EQ(sk_bitmap->height(), size.height());
1317 EXPECT_EQ(0, memcmp(data2, sk_bitmap->getPixels(), pixel_size));
1320 // Transfer resources to the parent again.
1321 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
1322 resource_ids_to_transfer.push_back(id1);
1323 resource_ids_to_transfer.push_back(id2);
1324 resource_ids_to_transfer.push_back(id3);
1325 TransferableResourceArray list;
1326 child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
1327 &list);
1328 ASSERT_EQ(3u, list.size());
1329 EXPECT_EQ(id1, list[0].id);
1330 EXPECT_EQ(id2, list[1].id);
1331 EXPECT_EQ(id3, list[2].id);
1332 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id1));
1333 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id2));
1334 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id3));
1335 resource_provider_->ReceiveFromChild(child_id, list);
1336 ResourceProvider::ResourceIdSet resource_ids_to_receive;
1337 resource_ids_to_receive.insert(id1);
1338 resource_ids_to_receive.insert(id2);
1339 resource_ids_to_receive.insert(id3);
1340 resource_provider_->DeclareUsedResourcesFromChild(child_id,
1341 resource_ids_to_receive);
1344 EXPECT_EQ(0u, returned_to_child.size());
1346 EXPECT_EQ(3u, resource_provider_->num_resources());
1347 resource_provider_->DestroyChild(child_id);
1348 EXPECT_EQ(0u, resource_provider_->num_resources());
1350 ASSERT_EQ(3u, returned_to_child.size());
1351 EXPECT_EQ(0u, returned_to_child[0].sync_point);
1352 EXPECT_EQ(0u, returned_to_child[1].sync_point);
1353 EXPECT_EQ(0u, returned_to_child[2].sync_point);
1354 std::set<ResourceId> expected_ids;
1355 expected_ids.insert(id1);
1356 expected_ids.insert(id2);
1357 expected_ids.insert(id3);
1358 std::set<ResourceId> returned_ids;
1359 for (unsigned i = 0; i < 3; i++)
1360 returned_ids.insert(returned_to_child[i].id);
1361 EXPECT_EQ(expected_ids, returned_ids);
1362 EXPECT_FALSE(returned_to_child[0].lost);
1363 EXPECT_FALSE(returned_to_child[1].lost);
1364 EXPECT_FALSE(returned_to_child[2].lost);
1367 TEST_P(ResourceProviderTest, TransferGLToSoftware) {
1368 if (GetParam() != ResourceProvider::RESOURCE_TYPE_BITMAP)
1369 return;
1371 scoped_ptr<ResourceProviderContext> child_context_owned(
1372 ResourceProviderContext::Create(shared_data_.get()));
1374 FakeOutputSurfaceClient child_output_surface_client;
1375 scoped_ptr<OutputSurface> child_output_surface(
1376 FakeOutputSurface::Create3d(child_context_owned.Pass()));
1377 CHECK(child_output_surface->BindToClient(&child_output_surface_client));
1379 scoped_ptr<ResourceProvider> child_resource_provider(ResourceProvider::Create(
1380 child_output_surface.get(), shared_bitmap_manager_.get(),
1381 gpu_memory_buffer_manager_.get(), NULL, 0, false, 1,
1382 use_image_texture_targets_));
1384 gfx::Size size(1, 1);
1385 ResourceFormat format = RGBA_8888;
1386 size_t pixel_size = TextureSizeBytes(size, format);
1387 ASSERT_EQ(4U, pixel_size);
1389 ResourceId id1 = child_resource_provider->CreateResource(
1390 size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE, format);
1391 uint8_t data1[4] = { 1, 2, 3, 4 };
1392 child_resource_provider->CopyToResource(id1, data1, size);
1394 ReturnedResourceArray returned_to_child;
1395 int child_id =
1396 resource_provider_->CreateChild(GetReturnCallback(&returned_to_child));
1398 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
1399 resource_ids_to_transfer.push_back(id1);
1400 TransferableResourceArray list;
1401 child_resource_provider->PrepareSendToParent(resource_ids_to_transfer,
1402 &list);
1403 ASSERT_EQ(1u, list.size());
1404 EXPECT_NE(0u, list[0].mailbox_holder.sync_point);
1405 EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_2D),
1406 list[0].mailbox_holder.texture_target);
1407 EXPECT_TRUE(child_resource_provider->InUseByConsumer(id1));
1408 resource_provider_->ReceiveFromChild(child_id, list);
1411 EXPECT_EQ(0u, resource_provider_->num_resources());
1412 ASSERT_EQ(1u, returned_to_child.size());
1413 EXPECT_EQ(returned_to_child[0].id, id1);
1414 ResourceProvider::ResourceIdMap resource_map =
1415 resource_provider_->GetChildToParentMap(child_id);
1416 ResourceId mapped_id1 = resource_map[id1];
1417 EXPECT_EQ(0u, mapped_id1);
1419 resource_provider_->DestroyChild(child_id);
1420 EXPECT_EQ(0u, resource_provider_->num_resources());
1422 ASSERT_EQ(1u, returned_to_child.size());
1423 EXPECT_FALSE(returned_to_child[0].lost);
1426 TEST_P(ResourceProviderTest, TransferInvalidSoftware) {
1427 if (GetParam() != ResourceProvider::RESOURCE_TYPE_BITMAP)
1428 return;
1430 gfx::Size size(1, 1);
1431 ResourceFormat format = RGBA_8888;
1432 size_t pixel_size = TextureSizeBytes(size, format);
1433 ASSERT_EQ(4U, pixel_size);
1435 ResourceId id1 = child_resource_provider_->CreateResource(
1436 size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE, format);
1437 uint8_t data1[4] = { 1, 2, 3, 4 };
1438 child_resource_provider_->CopyToResource(id1, data1, size);
1440 ReturnedResourceArray returned_to_child;
1441 int child_id =
1442 resource_provider_->CreateChild(GetReturnCallback(&returned_to_child));
1444 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
1445 resource_ids_to_transfer.push_back(id1);
1446 TransferableResourceArray list;
1447 child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
1448 &list);
1449 ASSERT_EQ(1u, list.size());
1450 // Make invalid.
1451 list[0].mailbox_holder.mailbox.name[1] = 5;
1452 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id1));
1453 resource_provider_->ReceiveFromChild(child_id, list);
1456 EXPECT_EQ(1u, resource_provider_->num_resources());
1457 EXPECT_EQ(0u, returned_to_child.size());
1459 ResourceProvider::ResourceIdMap resource_map =
1460 resource_provider_->GetChildToParentMap(child_id);
1461 ResourceId mapped_id1 = resource_map[id1];
1462 EXPECT_NE(0u, mapped_id1);
1464 ResourceProvider::ScopedReadLockSoftware lock(resource_provider_.get(),
1465 mapped_id1);
1466 EXPECT_FALSE(lock.valid());
1469 resource_provider_->DestroyChild(child_id);
1470 EXPECT_EQ(0u, resource_provider_->num_resources());
1472 ASSERT_EQ(1u, returned_to_child.size());
1473 EXPECT_FALSE(returned_to_child[0].lost);
1476 TEST_P(ResourceProviderTest, DeleteExportedResources) {
1477 gfx::Size size(1, 1);
1478 ResourceFormat format = RGBA_8888;
1479 size_t pixel_size = TextureSizeBytes(size, format);
1480 ASSERT_EQ(4U, pixel_size);
1482 ResourceId id1 = child_resource_provider_->CreateResource(
1483 size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE, format);
1484 uint8_t data1[4] = { 1, 2, 3, 4 };
1485 child_resource_provider_->CopyToResource(id1, data1, size);
1487 ResourceId id2 = child_resource_provider_->CreateResource(
1488 size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE, format);
1489 uint8_t data2[4] = {5, 5, 5, 5};
1490 child_resource_provider_->CopyToResource(id2, data2, size);
1492 ReturnedResourceArray returned_to_child;
1493 int child_id =
1494 resource_provider_->CreateChild(GetReturnCallback(&returned_to_child));
1496 // Transfer some resources to the parent.
1497 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
1498 resource_ids_to_transfer.push_back(id1);
1499 resource_ids_to_transfer.push_back(id2);
1500 TransferableResourceArray list;
1501 child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
1502 &list);
1503 ASSERT_EQ(2u, list.size());
1504 if (GetParam() == ResourceProvider::RESOURCE_TYPE_GL_TEXTURE) {
1505 EXPECT_NE(0u, list[0].mailbox_holder.sync_point);
1506 EXPECT_NE(0u, list[1].mailbox_holder.sync_point);
1508 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id1));
1509 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id2));
1510 resource_provider_->ReceiveFromChild(child_id, list);
1511 ResourceProvider::ResourceIdSet resource_ids_to_receive;
1512 resource_ids_to_receive.insert(id1);
1513 resource_ids_to_receive.insert(id2);
1514 resource_provider_->DeclareUsedResourcesFromChild(child_id,
1515 resource_ids_to_receive);
1518 EXPECT_EQ(2u, resource_provider_->num_resources());
1519 ResourceProvider::ResourceIdMap resource_map =
1520 resource_provider_->GetChildToParentMap(child_id);
1521 ResourceId mapped_id1 = resource_map[id1];
1522 ResourceId mapped_id2 = resource_map[id2];
1523 EXPECT_NE(0u, mapped_id1);
1524 EXPECT_NE(0u, mapped_id2);
1525 EXPECT_FALSE(resource_provider_->InUseByConsumer(id1));
1526 EXPECT_FALSE(resource_provider_->InUseByConsumer(id2));
1529 // The parent transfers the resources to the grandparent.
1530 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
1531 resource_ids_to_transfer.push_back(mapped_id1);
1532 resource_ids_to_transfer.push_back(mapped_id2);
1533 TransferableResourceArray list;
1534 resource_provider_->PrepareSendToParent(resource_ids_to_transfer, &list);
1536 ASSERT_EQ(2u, list.size());
1537 if (GetParam() == ResourceProvider::RESOURCE_TYPE_GL_TEXTURE) {
1538 EXPECT_NE(0u, list[0].mailbox_holder.sync_point);
1539 EXPECT_NE(0u, list[1].mailbox_holder.sync_point);
1541 EXPECT_TRUE(resource_provider_->InUseByConsumer(id1));
1542 EXPECT_TRUE(resource_provider_->InUseByConsumer(id2));
1544 // Release the resource in the parent. Set no resources as being in use. The
1545 // resources are exported so that can't be transferred back yet.
1546 ResourceProvider::ResourceIdSet no_resources;
1547 resource_provider_->DeclareUsedResourcesFromChild(child_id, no_resources);
1549 EXPECT_EQ(0u, returned_to_child.size());
1550 EXPECT_EQ(2u, resource_provider_->num_resources());
1552 // Return the resources from the grandparent to the parent. They should be
1553 // returned to the child then.
1554 EXPECT_EQ(2u, list.size());
1555 EXPECT_EQ(mapped_id1, list[0].id);
1556 EXPECT_EQ(mapped_id2, list[1].id);
1557 ReturnedResourceArray returned;
1558 TransferableResource::ReturnResources(list, &returned);
1559 resource_provider_->ReceiveReturnsFromParent(returned);
1561 EXPECT_EQ(0u, resource_provider_->num_resources());
1562 ASSERT_EQ(2u, returned_to_child.size());
1563 if (GetParam() == ResourceProvider::RESOURCE_TYPE_GL_TEXTURE) {
1564 EXPECT_NE(0u, returned_to_child[0].sync_point);
1565 EXPECT_NE(0u, returned_to_child[1].sync_point);
1567 EXPECT_FALSE(returned_to_child[0].lost);
1568 EXPECT_FALSE(returned_to_child[1].lost);
1572 TEST_P(ResourceProviderTest, DestroyChildWithExportedResources) {
1573 gfx::Size size(1, 1);
1574 ResourceFormat format = RGBA_8888;
1575 size_t pixel_size = TextureSizeBytes(size, format);
1576 ASSERT_EQ(4U, pixel_size);
1578 ResourceId id1 = child_resource_provider_->CreateResource(
1579 size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE, format);
1580 uint8_t data1[4] = {1, 2, 3, 4};
1581 child_resource_provider_->CopyToResource(id1, data1, size);
1583 ResourceId id2 = child_resource_provider_->CreateResource(
1584 size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE, format);
1585 uint8_t data2[4] = {5, 5, 5, 5};
1586 child_resource_provider_->CopyToResource(id2, data2, size);
1588 ReturnedResourceArray returned_to_child;
1589 int child_id =
1590 resource_provider_->CreateChild(GetReturnCallback(&returned_to_child));
1592 // Transfer some resources to the parent.
1593 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
1594 resource_ids_to_transfer.push_back(id1);
1595 resource_ids_to_transfer.push_back(id2);
1596 TransferableResourceArray list;
1597 child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
1598 &list);
1599 ASSERT_EQ(2u, list.size());
1600 if (GetParam() == ResourceProvider::RESOURCE_TYPE_GL_TEXTURE) {
1601 EXPECT_NE(0u, list[0].mailbox_holder.sync_point);
1602 EXPECT_NE(0u, list[1].mailbox_holder.sync_point);
1604 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id1));
1605 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id2));
1606 resource_provider_->ReceiveFromChild(child_id, list);
1607 ResourceProvider::ResourceIdSet resource_ids_to_receive;
1608 resource_ids_to_receive.insert(id1);
1609 resource_ids_to_receive.insert(id2);
1610 resource_provider_->DeclareUsedResourcesFromChild(child_id,
1611 resource_ids_to_receive);
1614 EXPECT_EQ(2u, resource_provider_->num_resources());
1615 ResourceProvider::ResourceIdMap resource_map =
1616 resource_provider_->GetChildToParentMap(child_id);
1617 ResourceId mapped_id1 = resource_map[id1];
1618 ResourceId mapped_id2 = resource_map[id2];
1619 EXPECT_NE(0u, mapped_id1);
1620 EXPECT_NE(0u, mapped_id2);
1621 EXPECT_FALSE(resource_provider_->InUseByConsumer(id1));
1622 EXPECT_FALSE(resource_provider_->InUseByConsumer(id2));
1625 // The parent transfers the resources to the grandparent.
1626 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
1627 resource_ids_to_transfer.push_back(mapped_id1);
1628 resource_ids_to_transfer.push_back(mapped_id2);
1629 TransferableResourceArray list;
1630 resource_provider_->PrepareSendToParent(resource_ids_to_transfer, &list);
1632 ASSERT_EQ(2u, list.size());
1633 if (GetParam() == ResourceProvider::RESOURCE_TYPE_GL_TEXTURE) {
1634 EXPECT_NE(0u, list[0].mailbox_holder.sync_point);
1635 EXPECT_NE(0u, list[1].mailbox_holder.sync_point);
1637 EXPECT_TRUE(resource_provider_->InUseByConsumer(id1));
1638 EXPECT_TRUE(resource_provider_->InUseByConsumer(id2));
1640 // Release the resource in the parent. Set no resources as being in use. The
1641 // resources are exported so that can't be transferred back yet.
1642 ResourceProvider::ResourceIdSet no_resources;
1643 resource_provider_->DeclareUsedResourcesFromChild(child_id, no_resources);
1645 // Destroy the child, the resources should not be returned yet.
1646 EXPECT_EQ(0u, returned_to_child.size());
1647 EXPECT_EQ(2u, resource_provider_->num_resources());
1649 resource_provider_->DestroyChild(child_id);
1651 EXPECT_EQ(2u, resource_provider_->num_resources());
1652 ASSERT_EQ(0u, returned_to_child.size());
1654 // Return a resource from the grandparent, it should be returned at this
1655 // point.
1656 EXPECT_EQ(2u, list.size());
1657 EXPECT_EQ(mapped_id1, list[0].id);
1658 EXPECT_EQ(mapped_id2, list[1].id);
1659 TransferableResourceArray return_list;
1660 return_list.push_back(list[1]);
1661 list.pop_back();
1662 ReturnedResourceArray returned;
1663 TransferableResource::ReturnResources(return_list, &returned);
1664 resource_provider_->ReceiveReturnsFromParent(returned);
1666 EXPECT_EQ(1u, resource_provider_->num_resources());
1667 ASSERT_EQ(1u, returned_to_child.size());
1668 if (GetParam() == ResourceProvider::RESOURCE_TYPE_GL_TEXTURE) {
1669 EXPECT_NE(0u, returned_to_child[0].sync_point);
1671 EXPECT_FALSE(returned_to_child[0].lost);
1672 returned_to_child.clear();
1674 // Destroy the parent resource provider. The resource that's left should be
1675 // lost at this point, and returned.
1676 resource_provider_ = nullptr;
1677 ASSERT_EQ(1u, returned_to_child.size());
1678 if (GetParam() == ResourceProvider::RESOURCE_TYPE_GL_TEXTURE) {
1679 EXPECT_NE(0u, returned_to_child[0].sync_point);
1681 EXPECT_TRUE(returned_to_child[0].lost);
1685 TEST_P(ResourceProviderTest, DeleteTransferredResources) {
1686 gfx::Size size(1, 1);
1687 ResourceFormat format = RGBA_8888;
1688 size_t pixel_size = TextureSizeBytes(size, format);
1689 ASSERT_EQ(4U, pixel_size);
1691 ResourceId id = child_resource_provider_->CreateResource(
1692 size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE, format);
1693 uint8_t data[4] = { 1, 2, 3, 4 };
1694 child_resource_provider_->CopyToResource(id, data, size);
1696 ReturnedResourceArray returned_to_child;
1697 int child_id =
1698 resource_provider_->CreateChild(GetReturnCallback(&returned_to_child));
1700 // Transfer some resource to the parent.
1701 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
1702 resource_ids_to_transfer.push_back(id);
1703 TransferableResourceArray list;
1704 child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
1705 &list);
1706 ASSERT_EQ(1u, list.size());
1707 if (GetParam() == ResourceProvider::RESOURCE_TYPE_GL_TEXTURE)
1708 EXPECT_NE(0u, list[0].mailbox_holder.sync_point);
1709 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id));
1710 resource_provider_->ReceiveFromChild(child_id, list);
1711 ResourceProvider::ResourceIdSet resource_ids_to_receive;
1712 resource_ids_to_receive.insert(id);
1713 resource_provider_->DeclareUsedResourcesFromChild(child_id,
1714 resource_ids_to_receive);
1717 // Delete textures in the child, while they are transfered.
1718 child_resource_provider_->DeleteResource(id);
1719 EXPECT_EQ(1u, child_resource_provider_->num_resources());
1721 EXPECT_EQ(0u, returned_to_child.size());
1723 // Transfer resources back from the parent to the child. Set no resources as
1724 // being in use.
1725 ResourceProvider::ResourceIdSet no_resources;
1726 resource_provider_->DeclareUsedResourcesFromChild(child_id, no_resources);
1728 ASSERT_EQ(1u, returned_to_child.size());
1729 if (GetParam() == ResourceProvider::RESOURCE_TYPE_GL_TEXTURE)
1730 EXPECT_NE(0u, returned_to_child[0].sync_point);
1731 child_resource_provider_->ReceiveReturnsFromParent(returned_to_child);
1733 EXPECT_EQ(0u, child_resource_provider_->num_resources());
1736 TEST_P(ResourceProviderTest, UnuseTransferredResources) {
1737 gfx::Size size(1, 1);
1738 ResourceFormat format = RGBA_8888;
1739 size_t pixel_size = TextureSizeBytes(size, format);
1740 ASSERT_EQ(4U, pixel_size);
1742 ResourceId id = child_resource_provider_->CreateResource(
1743 size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE, format);
1744 uint8_t data[4] = {1, 2, 3, 4};
1745 child_resource_provider_->CopyToResource(id, data, size);
1747 ReturnedResourceArray returned_to_child;
1748 int child_id =
1749 resource_provider_->CreateChild(GetReturnCallback(&returned_to_child));
1750 const ResourceProvider::ResourceIdMap& map =
1751 resource_provider_->GetChildToParentMap(child_id);
1753 // Transfer some resource to the parent.
1754 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
1755 resource_ids_to_transfer.push_back(id);
1756 TransferableResourceArray list;
1757 child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
1758 &list);
1759 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id));
1760 resource_provider_->ReceiveFromChild(child_id, list);
1761 ResourceProvider::ResourceIdSet resource_ids_to_receive;
1762 resource_ids_to_receive.insert(id);
1763 resource_provider_->DeclareUsedResourcesFromChild(child_id,
1764 resource_ids_to_receive);
1766 TransferableResourceArray sent_to_top_level;
1768 // Parent transfers to top-level.
1769 ASSERT_TRUE(map.find(id) != map.end());
1770 ResourceId parent_id = map.find(id)->second;
1771 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
1772 resource_ids_to_transfer.push_back(parent_id);
1773 resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
1774 &sent_to_top_level);
1775 EXPECT_TRUE(resource_provider_->InUseByConsumer(parent_id));
1778 // Stop using resource.
1779 ResourceProvider::ResourceIdSet empty;
1780 resource_provider_->DeclareUsedResourcesFromChild(child_id, empty);
1781 // Resource is not yet returned to the child, since it's in use by the
1782 // top-level.
1783 EXPECT_TRUE(returned_to_child.empty());
1786 // Send the resource to the parent again.
1787 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
1788 resource_ids_to_transfer.push_back(id);
1789 TransferableResourceArray list;
1790 child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
1791 &list);
1792 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id));
1793 resource_provider_->ReceiveFromChild(child_id, list);
1794 ResourceProvider::ResourceIdSet resource_ids_to_receive;
1795 resource_ids_to_receive.insert(id);
1796 resource_provider_->DeclareUsedResourcesFromChild(child_id,
1797 resource_ids_to_receive);
1800 // Receive returns back from top-level.
1801 ReturnedResourceArray returned;
1802 TransferableResource::ReturnResources(sent_to_top_level, &returned);
1803 resource_provider_->ReceiveReturnsFromParent(returned);
1804 // Resource is still not yet returned to the child, since it's declared used
1805 // in the parent.
1806 EXPECT_TRUE(returned_to_child.empty());
1807 ASSERT_TRUE(map.find(id) != map.end());
1808 ResourceId parent_id = map.find(id)->second;
1809 EXPECT_FALSE(resource_provider_->InUseByConsumer(parent_id));
1812 sent_to_top_level.clear();
1813 // Parent transfers again to top-level.
1814 ASSERT_TRUE(map.find(id) != map.end());
1815 ResourceId parent_id = map.find(id)->second;
1816 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
1817 resource_ids_to_transfer.push_back(parent_id);
1818 resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
1819 &sent_to_top_level);
1820 EXPECT_TRUE(resource_provider_->InUseByConsumer(parent_id));
1823 // Receive returns back from top-level.
1824 ReturnedResourceArray returned;
1825 TransferableResource::ReturnResources(sent_to_top_level, &returned);
1826 resource_provider_->ReceiveReturnsFromParent(returned);
1827 // Resource is still not yet returned to the child, since it's still
1828 // declared used in the parent.
1829 EXPECT_TRUE(returned_to_child.empty());
1830 ASSERT_TRUE(map.find(id) != map.end());
1831 ResourceId parent_id = map.find(id)->second;
1832 EXPECT_FALSE(resource_provider_->InUseByConsumer(parent_id));
1835 // Stop using resource.
1836 ResourceProvider::ResourceIdSet empty;
1837 resource_provider_->DeclareUsedResourcesFromChild(child_id, empty);
1838 // Resource should have been returned to the child, since it's no longer in
1839 // use by the top-level.
1840 ASSERT_EQ(1u, returned_to_child.size());
1841 EXPECT_EQ(id, returned_to_child[0].id);
1842 EXPECT_EQ(2, returned_to_child[0].count);
1843 child_resource_provider_->ReceiveReturnsFromParent(returned_to_child);
1844 returned_to_child.clear();
1845 EXPECT_FALSE(child_resource_provider_->InUseByConsumer(id));
1849 class ResourceProviderTestTextureFilters : public ResourceProviderTest {
1850 public:
1851 static void RunTest(GLenum child_filter, GLenum parent_filter) {
1852 scoped_ptr<TextureStateTrackingContext> child_context_owned(
1853 new TextureStateTrackingContext);
1854 TextureStateTrackingContext* child_context = child_context_owned.get();
1856 FakeOutputSurfaceClient child_output_surface_client;
1857 scoped_ptr<OutputSurface> child_output_surface(
1858 FakeOutputSurface::Create3d(child_context_owned.Pass()));
1859 CHECK(child_output_surface->BindToClient(&child_output_surface_client));
1860 scoped_ptr<SharedBitmapManager> shared_bitmap_manager(
1861 new TestSharedBitmapManager());
1863 scoped_ptr<ResourceProvider> child_resource_provider(
1864 ResourceProvider::Create(child_output_surface.get(),
1865 shared_bitmap_manager.get(), NULL, NULL, 0,
1866 false, 1, use_image_texture_targets_));
1868 scoped_ptr<TextureStateTrackingContext> parent_context_owned(
1869 new TextureStateTrackingContext);
1870 TextureStateTrackingContext* parent_context = parent_context_owned.get();
1872 FakeOutputSurfaceClient parent_output_surface_client;
1873 scoped_ptr<OutputSurface> parent_output_surface(
1874 FakeOutputSurface::Create3d(parent_context_owned.Pass()));
1875 CHECK(parent_output_surface->BindToClient(&parent_output_surface_client));
1877 scoped_ptr<ResourceProvider> parent_resource_provider(
1878 ResourceProvider::Create(parent_output_surface.get(),
1879 shared_bitmap_manager.get(), NULL, NULL, 0,
1880 false, 1, use_image_texture_targets_));
1882 gfx::Size size(1, 1);
1883 ResourceFormat format = RGBA_8888;
1884 int child_texture_id = 1;
1885 int parent_texture_id = 2;
1887 size_t pixel_size = TextureSizeBytes(size, format);
1888 ASSERT_EQ(4U, pixel_size);
1890 ResourceId id = child_resource_provider->CreateResource(
1891 size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE,
1892 format);
1894 // The new texture is created with GL_LINEAR.
1895 EXPECT_CALL(*child_context, bindTexture(GL_TEXTURE_2D, child_texture_id))
1896 .Times(2); // Once to create and once to allocate.
1897 EXPECT_CALL(*child_context,
1898 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
1899 EXPECT_CALL(*child_context,
1900 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR));
1901 EXPECT_CALL(
1902 *child_context,
1903 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE));
1904 EXPECT_CALL(
1905 *child_context,
1906 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE));
1907 EXPECT_CALL(*child_context,
1908 texParameteri(GL_TEXTURE_2D,
1909 GL_TEXTURE_POOL_CHROMIUM,
1910 GL_TEXTURE_POOL_UNMANAGED_CHROMIUM));
1911 child_resource_provider->AllocateForTesting(id);
1912 Mock::VerifyAndClearExpectations(child_context);
1914 uint8_t data[4] = { 1, 2, 3, 4 };
1916 EXPECT_CALL(*child_context, bindTexture(GL_TEXTURE_2D, child_texture_id));
1917 child_resource_provider->CopyToResource(id, data, size);
1918 Mock::VerifyAndClearExpectations(child_context);
1920 // The texture is set to |child_filter| in the child.
1921 EXPECT_CALL(*child_context, bindTexture(GL_TEXTURE_2D, child_texture_id));
1922 if (child_filter != GL_LINEAR) {
1923 EXPECT_CALL(
1924 *child_context,
1925 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, child_filter));
1926 EXPECT_CALL(
1927 *child_context,
1928 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, child_filter));
1930 SetResourceFilter(child_resource_provider.get(), id, child_filter);
1931 Mock::VerifyAndClearExpectations(child_context);
1933 ReturnedResourceArray returned_to_child;
1934 int child_id = parent_resource_provider->CreateChild(
1935 GetReturnCallback(&returned_to_child));
1937 // Transfer some resource to the parent.
1938 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
1939 resource_ids_to_transfer.push_back(id);
1940 TransferableResourceArray list;
1942 EXPECT_CALL(*child_context,
1943 produceTextureDirectCHROMIUM(_, GL_TEXTURE_2D, _));
1944 EXPECT_CALL(*child_context, insertSyncPoint());
1945 child_resource_provider->PrepareSendToParent(resource_ids_to_transfer,
1946 &list);
1947 Mock::VerifyAndClearExpectations(child_context);
1949 ASSERT_EQ(1u, list.size());
1950 EXPECT_EQ(static_cast<unsigned>(child_filter), list[0].filter);
1952 EXPECT_CALL(*parent_context,
1953 createAndConsumeTextureCHROMIUM(GL_TEXTURE_2D, _))
1954 .WillOnce(Return(parent_texture_id));
1956 parent_resource_provider->ReceiveFromChild(child_id, list);
1958 parent_resource_provider->WaitSyncPointIfNeeded(list[0].id);
1959 ResourceProvider::ScopedReadLockGL lock(parent_resource_provider.get(),
1960 list[0].id);
1962 Mock::VerifyAndClearExpectations(parent_context);
1964 ResourceProvider::ResourceIdSet resource_ids_to_receive;
1965 resource_ids_to_receive.insert(id);
1966 parent_resource_provider->DeclareUsedResourcesFromChild(
1967 child_id, resource_ids_to_receive);
1968 Mock::VerifyAndClearExpectations(parent_context);
1970 ResourceProvider::ResourceIdMap resource_map =
1971 parent_resource_provider->GetChildToParentMap(child_id);
1972 ResourceId mapped_id = resource_map[id];
1973 EXPECT_NE(0u, mapped_id);
1975 // The texture is set to |parent_filter| in the parent.
1976 EXPECT_CALL(*parent_context, bindTexture(GL_TEXTURE_2D, parent_texture_id));
1977 EXPECT_CALL(
1978 *parent_context,
1979 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, parent_filter));
1980 EXPECT_CALL(
1981 *parent_context,
1982 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, parent_filter));
1983 SetResourceFilter(parent_resource_provider.get(), mapped_id, parent_filter);
1984 Mock::VerifyAndClearExpectations(parent_context);
1986 // The texture should be reset to |child_filter| in the parent when it is
1987 // returned, since that is how it was received.
1988 EXPECT_CALL(*parent_context, bindTexture(GL_TEXTURE_2D, parent_texture_id));
1989 EXPECT_CALL(
1990 *parent_context,
1991 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, child_filter));
1992 EXPECT_CALL(
1993 *parent_context,
1994 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, child_filter));
1997 EXPECT_EQ(0u, returned_to_child.size());
1999 // Transfer resources back from the parent to the child. Set no resources
2000 // as being in use.
2001 ResourceProvider::ResourceIdSet no_resources;
2002 EXPECT_CALL(*parent_context, insertSyncPoint());
2003 parent_resource_provider->DeclareUsedResourcesFromChild(child_id,
2004 no_resources);
2005 Mock::VerifyAndClearExpectations(parent_context);
2007 ASSERT_EQ(1u, returned_to_child.size());
2008 child_resource_provider->ReceiveReturnsFromParent(returned_to_child);
2011 // The child remembers the texture filter is set to |child_filter|.
2012 EXPECT_CALL(*child_context, bindTexture(GL_TEXTURE_2D, child_texture_id));
2013 SetResourceFilter(child_resource_provider.get(), id, child_filter);
2014 Mock::VerifyAndClearExpectations(child_context);
2018 TEST_P(ResourceProviderTest, TextureFilters_ChildNearestParentLinear) {
2019 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE)
2020 return;
2021 ResourceProviderTestTextureFilters::RunTest(GL_NEAREST, GL_LINEAR);
2024 TEST_P(ResourceProviderTest, TextureFilters_ChildLinearParentNearest) {
2025 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE)
2026 return;
2027 ResourceProviderTestTextureFilters::RunTest(GL_LINEAR, GL_NEAREST);
2030 TEST_P(ResourceProviderTest, TransferMailboxResources) {
2031 // Other mailbox transfers tested elsewhere.
2032 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE)
2033 return;
2034 unsigned texture = context()->createTexture();
2035 context()->bindTexture(GL_TEXTURE_2D, texture);
2036 uint8_t data[4] = { 1, 2, 3, 4 };
2037 context()->texImage2D(
2038 GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, &data);
2039 gpu::Mailbox mailbox;
2040 context()->genMailboxCHROMIUM(mailbox.name);
2041 context()->produceTextureDirectCHROMIUM(texture, GL_TEXTURE_2D, mailbox.name);
2042 uint32 sync_point = context()->insertSyncPoint();
2044 // All the logic below assumes that the sync points are all positive.
2045 EXPECT_LT(0u, sync_point);
2047 uint32 release_sync_point = 0;
2048 bool lost_resource = false;
2049 BlockingTaskRunner* main_thread_task_runner = NULL;
2050 ReleaseCallbackImpl callback = base::Bind(ReleaseCallback,
2051 &release_sync_point,
2052 &lost_resource,
2053 &main_thread_task_runner);
2054 ResourceId resource = resource_provider_->CreateResourceFromTextureMailbox(
2055 TextureMailbox(mailbox, GL_TEXTURE_2D, sync_point),
2056 SingleReleaseCallbackImpl::Create(callback));
2057 EXPECT_EQ(1u, context()->NumTextures());
2058 EXPECT_EQ(0u, release_sync_point);
2060 // Transfer the resource, expect the sync points to be consistent.
2061 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
2062 resource_ids_to_transfer.push_back(resource);
2063 TransferableResourceArray list;
2064 resource_provider_->PrepareSendToParent(resource_ids_to_transfer, &list);
2065 ASSERT_EQ(1u, list.size());
2066 EXPECT_LE(sync_point, list[0].mailbox_holder.sync_point);
2067 EXPECT_EQ(0,
2068 memcmp(mailbox.name,
2069 list[0].mailbox_holder.mailbox.name,
2070 sizeof(mailbox.name)));
2071 EXPECT_EQ(0u, release_sync_point);
2073 context()->waitSyncPoint(list[0].mailbox_holder.sync_point);
2074 unsigned other_texture =
2075 context()->createAndConsumeTextureCHROMIUM(GL_TEXTURE_2D, mailbox.name);
2076 uint8_t test_data[4] = { 0 };
2077 context()->GetPixels(
2078 gfx::Size(1, 1), RGBA_8888, test_data);
2079 EXPECT_EQ(0, memcmp(data, test_data, sizeof(data)));
2081 context()->produceTextureDirectCHROMIUM(other_texture, GL_TEXTURE_2D,
2082 mailbox.name);
2083 context()->deleteTexture(other_texture);
2084 list[0].mailbox_holder.sync_point = context()->insertSyncPoint();
2085 EXPECT_LT(0u, list[0].mailbox_holder.sync_point);
2087 // Receive the resource, then delete it, expect the sync points to be
2088 // consistent.
2089 ReturnedResourceArray returned;
2090 TransferableResource::ReturnResources(list, &returned);
2091 resource_provider_->ReceiveReturnsFromParent(returned);
2092 EXPECT_EQ(1u, context()->NumTextures());
2093 EXPECT_EQ(0u, release_sync_point);
2095 resource_provider_->DeleteResource(resource);
2096 EXPECT_LE(list[0].mailbox_holder.sync_point, release_sync_point);
2097 EXPECT_FALSE(lost_resource);
2098 EXPECT_EQ(main_thread_task_runner_.get(), main_thread_task_runner);
2101 // We're going to do the same thing as above, but testing the case where we
2102 // delete the resource before we receive it back.
2103 sync_point = release_sync_point;
2104 EXPECT_LT(0u, sync_point);
2105 release_sync_point = 0;
2106 resource = resource_provider_->CreateResourceFromTextureMailbox(
2107 TextureMailbox(mailbox, GL_TEXTURE_2D, sync_point),
2108 SingleReleaseCallbackImpl::Create(callback));
2109 EXPECT_EQ(1u, context()->NumTextures());
2110 EXPECT_EQ(0u, release_sync_point);
2112 // Transfer the resource, expect the sync points to be consistent.
2113 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
2114 resource_ids_to_transfer.push_back(resource);
2115 TransferableResourceArray list;
2116 resource_provider_->PrepareSendToParent(resource_ids_to_transfer, &list);
2117 ASSERT_EQ(1u, list.size());
2118 EXPECT_LE(sync_point, list[0].mailbox_holder.sync_point);
2119 EXPECT_EQ(0,
2120 memcmp(mailbox.name,
2121 list[0].mailbox_holder.mailbox.name,
2122 sizeof(mailbox.name)));
2123 EXPECT_EQ(0u, release_sync_point);
2125 context()->waitSyncPoint(list[0].mailbox_holder.sync_point);
2126 unsigned other_texture =
2127 context()->createAndConsumeTextureCHROMIUM(GL_TEXTURE_2D, mailbox.name);
2128 uint8_t test_data[4] = { 0 };
2129 context()->GetPixels(
2130 gfx::Size(1, 1), RGBA_8888, test_data);
2131 EXPECT_EQ(0, memcmp(data, test_data, sizeof(data)));
2133 context()->produceTextureDirectCHROMIUM(other_texture, GL_TEXTURE_2D,
2134 mailbox.name);
2135 context()->deleteTexture(other_texture);
2136 list[0].mailbox_holder.sync_point = context()->insertSyncPoint();
2137 EXPECT_LT(0u, list[0].mailbox_holder.sync_point);
2139 // Delete the resource, which shouldn't do anything.
2140 resource_provider_->DeleteResource(resource);
2141 EXPECT_EQ(1u, context()->NumTextures());
2142 EXPECT_EQ(0u, release_sync_point);
2144 // Then receive the resource which should release the mailbox, expect the
2145 // sync points to be consistent.
2146 ReturnedResourceArray returned;
2147 TransferableResource::ReturnResources(list, &returned);
2148 resource_provider_->ReceiveReturnsFromParent(returned);
2149 EXPECT_LE(list[0].mailbox_holder.sync_point, release_sync_point);
2150 EXPECT_FALSE(lost_resource);
2151 EXPECT_EQ(main_thread_task_runner_.get(), main_thread_task_runner);
2154 context()->waitSyncPoint(release_sync_point);
2155 texture =
2156 context()->createAndConsumeTextureCHROMIUM(GL_TEXTURE_2D, mailbox.name);
2157 context()->deleteTexture(texture);
2160 TEST_P(ResourceProviderTest, LostResourceInParent) {
2161 gfx::Size size(1, 1);
2162 ResourceFormat format = RGBA_8888;
2163 ResourceId resource = child_resource_provider_->CreateResource(
2164 size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE, format);
2165 child_resource_provider_->AllocateForTesting(resource);
2166 // Expect a GL resource to be lost.
2167 bool should_lose_resource =
2168 GetParam() == ResourceProvider::RESOURCE_TYPE_GL_TEXTURE;
2170 ReturnedResourceArray returned_to_child;
2171 int child_id =
2172 resource_provider_->CreateChild(GetReturnCallback(&returned_to_child));
2174 // Transfer the resource to the parent.
2175 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
2176 resource_ids_to_transfer.push_back(resource);
2177 TransferableResourceArray list;
2178 child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
2179 &list);
2180 EXPECT_EQ(1u, list.size());
2182 resource_provider_->ReceiveFromChild(child_id, list);
2183 ResourceProvider::ResourceIdSet resource_ids_to_receive;
2184 resource_ids_to_receive.insert(resource);
2185 resource_provider_->DeclareUsedResourcesFromChild(child_id,
2186 resource_ids_to_receive);
2189 // Lose the output surface in the parent.
2190 resource_provider_->DidLoseOutputSurface();
2193 EXPECT_EQ(0u, returned_to_child.size());
2195 // Transfer resources back from the parent to the child. Set no resources as
2196 // being in use.
2197 ResourceProvider::ResourceIdSet no_resources;
2198 resource_provider_->DeclareUsedResourcesFromChild(child_id, no_resources);
2200 // Expect a GL resource to be lost.
2201 ASSERT_EQ(1u, returned_to_child.size());
2202 EXPECT_EQ(should_lose_resource, returned_to_child[0].lost);
2203 child_resource_provider_->ReceiveReturnsFromParent(returned_to_child);
2204 returned_to_child.clear();
2207 // A GL resource should be lost.
2208 EXPECT_EQ(should_lose_resource, child_resource_provider_->IsLost(resource));
2210 // Lost resources stay in use in the parent forever.
2211 EXPECT_EQ(should_lose_resource,
2212 child_resource_provider_->InUseByConsumer(resource));
2215 TEST_P(ResourceProviderTest, LostResourceInGrandParent) {
2216 gfx::Size size(1, 1);
2217 ResourceFormat format = RGBA_8888;
2218 ResourceId resource = child_resource_provider_->CreateResource(
2219 size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE, format);
2220 child_resource_provider_->AllocateForTesting(resource);
2222 ReturnedResourceArray returned_to_child;
2223 int child_id =
2224 resource_provider_->CreateChild(GetReturnCallback(&returned_to_child));
2226 // Transfer the resource to the parent.
2227 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
2228 resource_ids_to_transfer.push_back(resource);
2229 TransferableResourceArray list;
2230 child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
2231 &list);
2232 EXPECT_EQ(1u, list.size());
2234 resource_provider_->ReceiveFromChild(child_id, list);
2235 ResourceProvider::ResourceIdSet resource_ids_to_receive;
2236 resource_ids_to_receive.insert(resource);
2237 resource_provider_->DeclareUsedResourcesFromChild(child_id,
2238 resource_ids_to_receive);
2242 ResourceProvider::ResourceIdMap resource_map =
2243 resource_provider_->GetChildToParentMap(child_id);
2244 ResourceId parent_resource = resource_map[resource];
2245 EXPECT_NE(0u, parent_resource);
2247 // Transfer to a grandparent.
2248 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
2249 resource_ids_to_transfer.push_back(parent_resource);
2250 TransferableResourceArray list;
2251 resource_provider_->PrepareSendToParent(resource_ids_to_transfer, &list);
2253 // Receive back a lost resource from the grandparent.
2254 EXPECT_EQ(1u, list.size());
2255 EXPECT_EQ(parent_resource, list[0].id);
2256 ReturnedResourceArray returned;
2257 TransferableResource::ReturnResources(list, &returned);
2258 EXPECT_EQ(1u, returned.size());
2259 EXPECT_EQ(parent_resource, returned[0].id);
2260 returned[0].lost = true;
2261 resource_provider_->ReceiveReturnsFromParent(returned);
2263 // The resource should be lost.
2264 EXPECT_TRUE(resource_provider_->IsLost(parent_resource));
2266 // Lost resources stay in use in the parent forever.
2267 EXPECT_TRUE(resource_provider_->InUseByConsumer(parent_resource));
2271 EXPECT_EQ(0u, returned_to_child.size());
2273 // Transfer resources back from the parent to the child. Set no resources as
2274 // being in use.
2275 ResourceProvider::ResourceIdSet no_resources;
2276 resource_provider_->DeclareUsedResourcesFromChild(child_id, no_resources);
2278 // Expect the resource to be lost.
2279 ASSERT_EQ(1u, returned_to_child.size());
2280 EXPECT_TRUE(returned_to_child[0].lost);
2281 child_resource_provider_->ReceiveReturnsFromParent(returned_to_child);
2282 returned_to_child.clear();
2285 // The resource should be lost.
2286 EXPECT_TRUE(child_resource_provider_->IsLost(resource));
2288 // Lost resources stay in use in the parent forever.
2289 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(resource));
2292 TEST_P(ResourceProviderTest, LostMailboxInParent) {
2293 uint32 release_sync_point = 0;
2294 bool lost_resource = false;
2295 bool release_called = false;
2296 uint32 sync_point = 0;
2297 ResourceId resource = CreateChildMailbox(&release_sync_point, &lost_resource,
2298 &release_called, &sync_point);
2300 ReturnedResourceArray returned_to_child;
2301 int child_id =
2302 resource_provider_->CreateChild(GetReturnCallback(&returned_to_child));
2304 // Transfer the resource to the parent.
2305 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
2306 resource_ids_to_transfer.push_back(resource);
2307 TransferableResourceArray list;
2308 child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
2309 &list);
2310 EXPECT_EQ(1u, list.size());
2312 resource_provider_->ReceiveFromChild(child_id, list);
2313 ResourceProvider::ResourceIdSet resource_ids_to_receive;
2314 resource_ids_to_receive.insert(resource);
2315 resource_provider_->DeclareUsedResourcesFromChild(child_id,
2316 resource_ids_to_receive);
2319 // Lose the output surface in the parent.
2320 resource_provider_->DidLoseOutputSurface();
2323 EXPECT_EQ(0u, returned_to_child.size());
2325 // Transfer resources back from the parent to the child. Set no resources as
2326 // being in use.
2327 ResourceProvider::ResourceIdSet no_resources;
2328 resource_provider_->DeclareUsedResourcesFromChild(child_id, no_resources);
2330 ASSERT_EQ(1u, returned_to_child.size());
2331 // Losing an output surface only loses hardware resources.
2332 EXPECT_EQ(returned_to_child[0].lost,
2333 GetParam() == ResourceProvider::RESOURCE_TYPE_GL_TEXTURE);
2334 child_resource_provider_->ReceiveReturnsFromParent(returned_to_child);
2335 returned_to_child.clear();
2338 // Delete the resource in the child. Expect the resource to be lost if it's
2339 // a GL texture.
2340 child_resource_provider_->DeleteResource(resource);
2341 EXPECT_EQ(lost_resource,
2342 GetParam() == ResourceProvider::RESOURCE_TYPE_GL_TEXTURE);
2345 TEST_P(ResourceProviderTest, LostMailboxInGrandParent) {
2346 uint32 release_sync_point = 0;
2347 bool lost_resource = false;
2348 bool release_called = false;
2349 uint32 sync_point = 0;
2350 ResourceId resource = CreateChildMailbox(&release_sync_point, &lost_resource,
2351 &release_called, &sync_point);
2353 ReturnedResourceArray returned_to_child;
2354 int child_id =
2355 resource_provider_->CreateChild(GetReturnCallback(&returned_to_child));
2357 // Transfer the resource to the parent.
2358 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
2359 resource_ids_to_transfer.push_back(resource);
2360 TransferableResourceArray list;
2361 child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
2362 &list);
2363 EXPECT_EQ(1u, list.size());
2365 resource_provider_->ReceiveFromChild(child_id, list);
2366 ResourceProvider::ResourceIdSet resource_ids_to_receive;
2367 resource_ids_to_receive.insert(resource);
2368 resource_provider_->DeclareUsedResourcesFromChild(child_id,
2369 resource_ids_to_receive);
2373 ResourceProvider::ResourceIdMap resource_map =
2374 resource_provider_->GetChildToParentMap(child_id);
2375 ResourceId parent_resource = resource_map[resource];
2376 EXPECT_NE(0u, parent_resource);
2378 // Transfer to a grandparent.
2379 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
2380 resource_ids_to_transfer.push_back(parent_resource);
2381 TransferableResourceArray list;
2382 resource_provider_->PrepareSendToParent(resource_ids_to_transfer, &list);
2384 // Receive back a lost resource from the grandparent.
2385 EXPECT_EQ(1u, list.size());
2386 EXPECT_EQ(parent_resource, list[0].id);
2387 ReturnedResourceArray returned;
2388 TransferableResource::ReturnResources(list, &returned);
2389 EXPECT_EQ(1u, returned.size());
2390 EXPECT_EQ(parent_resource, returned[0].id);
2391 returned[0].lost = true;
2392 resource_provider_->ReceiveReturnsFromParent(returned);
2396 EXPECT_EQ(0u, returned_to_child.size());
2398 // Transfer resources back from the parent to the child. Set no resources as
2399 // being in use.
2400 ResourceProvider::ResourceIdSet no_resources;
2401 resource_provider_->DeclareUsedResourcesFromChild(child_id, no_resources);
2403 // Expect the resource to be lost.
2404 ASSERT_EQ(1u, returned_to_child.size());
2405 EXPECT_TRUE(returned_to_child[0].lost);
2406 child_resource_provider_->ReceiveReturnsFromParent(returned_to_child);
2407 returned_to_child.clear();
2410 // Delete the resource in the child. Expect the resource to be lost.
2411 child_resource_provider_->DeleteResource(resource);
2412 EXPECT_TRUE(lost_resource);
2415 TEST_P(ResourceProviderTest, Shutdown) {
2416 uint32 release_sync_point = 0;
2417 bool lost_resource = false;
2418 bool release_called = false;
2419 uint32 sync_point = 0;
2420 CreateChildMailbox(
2421 &release_sync_point, &lost_resource, &release_called, &sync_point);
2423 EXPECT_EQ(0u, release_sync_point);
2424 EXPECT_FALSE(lost_resource);
2426 child_resource_provider_ = nullptr;
2428 if (GetParam() == ResourceProvider::RESOURCE_TYPE_GL_TEXTURE) {
2429 EXPECT_LE(sync_point, release_sync_point);
2431 EXPECT_TRUE(release_called);
2432 EXPECT_FALSE(lost_resource);
2435 TEST_P(ResourceProviderTest, ShutdownWithExportedResource) {
2436 uint32 release_sync_point = 0;
2437 bool lost_resource = false;
2438 bool release_called = false;
2439 uint32 sync_point = 0;
2440 ResourceId resource = CreateChildMailbox(&release_sync_point, &lost_resource,
2441 &release_called, &sync_point);
2443 // Transfer the resource, so we can't release it properly on shutdown.
2444 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
2445 resource_ids_to_transfer.push_back(resource);
2446 TransferableResourceArray list;
2447 child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
2448 &list);
2450 EXPECT_EQ(0u, release_sync_point);
2451 EXPECT_FALSE(lost_resource);
2453 child_resource_provider_ = nullptr;
2455 // Since the resource is in the parent, the child considers it lost.
2456 EXPECT_EQ(0u, release_sync_point);
2457 EXPECT_TRUE(lost_resource);
2460 TEST_P(ResourceProviderTest, LostContext) {
2461 // TextureMailbox callbacks only exist for GL textures for now.
2462 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE)
2463 return;
2464 unsigned texture = context()->createTexture();
2465 context()->bindTexture(GL_TEXTURE_2D, texture);
2466 gpu::Mailbox mailbox;
2467 context()->genMailboxCHROMIUM(mailbox.name);
2468 context()->produceTextureDirectCHROMIUM(texture, GL_TEXTURE_2D, mailbox.name);
2469 uint32 sync_point = context()->insertSyncPoint();
2471 EXPECT_LT(0u, sync_point);
2473 uint32 release_sync_point = 0;
2474 bool lost_resource = false;
2475 BlockingTaskRunner* main_thread_task_runner = NULL;
2476 scoped_ptr<SingleReleaseCallbackImpl> callback =
2477 SingleReleaseCallbackImpl::Create(base::Bind(ReleaseCallback,
2478 &release_sync_point,
2479 &lost_resource,
2480 &main_thread_task_runner));
2481 resource_provider_->CreateResourceFromTextureMailbox(
2482 TextureMailbox(mailbox, GL_TEXTURE_2D, sync_point), callback.Pass());
2484 EXPECT_EQ(0u, release_sync_point);
2485 EXPECT_FALSE(lost_resource);
2486 EXPECT_EQ(NULL, main_thread_task_runner);
2488 resource_provider_->DidLoseOutputSurface();
2489 resource_provider_ = nullptr;
2491 EXPECT_LE(sync_point, release_sync_point);
2492 EXPECT_TRUE(lost_resource);
2493 EXPECT_EQ(main_thread_task_runner_.get(), main_thread_task_runner);
2496 TEST_P(ResourceProviderTest, ScopedSampler) {
2497 // Sampling is only supported for GL textures.
2498 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE)
2499 return;
2501 scoped_ptr<TextureStateTrackingContext> context_owned(
2502 new TextureStateTrackingContext);
2503 TextureStateTrackingContext* context = context_owned.get();
2505 FakeOutputSurfaceClient output_surface_client;
2506 scoped_ptr<OutputSurface> output_surface(
2507 FakeOutputSurface::Create3d(context_owned.Pass()));
2508 CHECK(output_surface->BindToClient(&output_surface_client));
2510 scoped_ptr<ResourceProvider> resource_provider(ResourceProvider::Create(
2511 output_surface.get(), shared_bitmap_manager_.get(),
2512 gpu_memory_buffer_manager_.get(), NULL, 0, false, 1,
2513 use_image_texture_targets_));
2515 gfx::Size size(1, 1);
2516 ResourceFormat format = RGBA_8888;
2517 int texture_id = 1;
2519 ResourceId id = resource_provider->CreateResource(
2520 size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE, format);
2522 // Check that the texture gets created with the right sampler settings.
2523 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id))
2524 .Times(2); // Once to create and once to allocate.
2525 EXPECT_CALL(*context,
2526 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
2527 EXPECT_CALL(*context,
2528 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR));
2529 EXPECT_CALL(
2530 *context,
2531 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE));
2532 EXPECT_CALL(
2533 *context,
2534 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE));
2535 EXPECT_CALL(*context,
2536 texParameteri(GL_TEXTURE_2D,
2537 GL_TEXTURE_POOL_CHROMIUM,
2538 GL_TEXTURE_POOL_UNMANAGED_CHROMIUM));
2540 resource_provider->AllocateForTesting(id);
2541 Mock::VerifyAndClearExpectations(context);
2543 // Creating a sampler with the default filter should not change any texture
2544 // parameters.
2546 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id));
2547 ResourceProvider::ScopedSamplerGL sampler(
2548 resource_provider.get(), id, GL_TEXTURE_2D, GL_LINEAR);
2549 Mock::VerifyAndClearExpectations(context);
2552 // Using a different filter should be reflected in the texture parameters.
2554 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id));
2555 EXPECT_CALL(
2556 *context,
2557 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST));
2558 EXPECT_CALL(
2559 *context,
2560 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST));
2561 ResourceProvider::ScopedSamplerGL sampler(
2562 resource_provider.get(), id, GL_TEXTURE_2D, GL_NEAREST);
2563 Mock::VerifyAndClearExpectations(context);
2566 // Test resetting to the default filter.
2568 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id));
2569 EXPECT_CALL(*context,
2570 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
2571 EXPECT_CALL(*context,
2572 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR));
2573 ResourceProvider::ScopedSamplerGL sampler(
2574 resource_provider.get(), id, GL_TEXTURE_2D, GL_LINEAR);
2575 Mock::VerifyAndClearExpectations(context);
2579 TEST_P(ResourceProviderTest, ManagedResource) {
2580 // Sampling is only supported for GL textures.
2581 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE)
2582 return;
2584 scoped_ptr<TextureStateTrackingContext> context_owned(
2585 new TextureStateTrackingContext);
2586 TextureStateTrackingContext* context = context_owned.get();
2588 FakeOutputSurfaceClient output_surface_client;
2589 scoped_ptr<OutputSurface> output_surface(
2590 FakeOutputSurface::Create3d(context_owned.Pass()));
2591 CHECK(output_surface->BindToClient(&output_surface_client));
2593 scoped_ptr<ResourceProvider> resource_provider(ResourceProvider::Create(
2594 output_surface.get(), shared_bitmap_manager_.get(),
2595 gpu_memory_buffer_manager_.get(), NULL, 0, false, 1,
2596 use_image_texture_targets_));
2598 gfx::Size size(1, 1);
2599 ResourceFormat format = RGBA_8888;
2600 int texture_id = 1;
2602 // Check that the texture gets created with the right sampler settings.
2603 ResourceId id = resource_provider->CreateManagedResource(
2604 size, GL_TEXTURE_2D, GL_CLAMP_TO_EDGE,
2605 ResourceProvider::TEXTURE_HINT_IMMUTABLE, format);
2606 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id));
2607 EXPECT_CALL(*context,
2608 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
2609 EXPECT_CALL(*context,
2610 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR));
2611 EXPECT_CALL(
2612 *context,
2613 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE));
2614 EXPECT_CALL(
2615 *context,
2616 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE));
2617 EXPECT_CALL(*context,
2618 texParameteri(GL_TEXTURE_2D,
2619 GL_TEXTURE_POOL_CHROMIUM,
2620 GL_TEXTURE_POOL_MANAGED_CHROMIUM));
2621 resource_provider->CreateForTesting(id);
2622 EXPECT_NE(0u, id);
2624 Mock::VerifyAndClearExpectations(context);
2627 TEST_P(ResourceProviderTest, TextureWrapMode) {
2628 // Sampling is only supported for GL textures.
2629 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE)
2630 return;
2632 scoped_ptr<TextureStateTrackingContext> context_owned(
2633 new TextureStateTrackingContext);
2634 TextureStateTrackingContext* context = context_owned.get();
2636 FakeOutputSurfaceClient output_surface_client;
2637 scoped_ptr<OutputSurface> output_surface(
2638 FakeOutputSurface::Create3d(context_owned.Pass()));
2639 CHECK(output_surface->BindToClient(&output_surface_client));
2641 scoped_ptr<ResourceProvider> resource_provider(ResourceProvider::Create(
2642 output_surface.get(), shared_bitmap_manager_.get(),
2643 gpu_memory_buffer_manager_.get(), NULL, 0, false, 1,
2644 use_image_texture_targets_));
2646 gfx::Size size(1, 1);
2647 ResourceFormat format = RGBA_8888;
2648 GLenum texture_pool = GL_TEXTURE_POOL_UNMANAGED_CHROMIUM;
2650 for (int texture_id = 1; texture_id <= 2; ++texture_id) {
2651 GLint wrap_mode = texture_id == 1 ? GL_CLAMP_TO_EDGE : GL_REPEAT;
2652 // Check that the texture gets created with the right sampler settings.
2653 ResourceId id = resource_provider->CreateGLTexture(
2654 size, GL_TEXTURE_2D, texture_pool, wrap_mode,
2655 ResourceProvider::TEXTURE_HINT_IMMUTABLE, format);
2656 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id));
2657 EXPECT_CALL(*context,
2658 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
2659 EXPECT_CALL(*context,
2660 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR));
2661 EXPECT_CALL(*context,
2662 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, wrap_mode));
2663 EXPECT_CALL(*context,
2664 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, wrap_mode));
2665 EXPECT_CALL(*context,
2666 texParameteri(GL_TEXTURE_2D,
2667 GL_TEXTURE_POOL_CHROMIUM,
2668 GL_TEXTURE_POOL_UNMANAGED_CHROMIUM));
2669 resource_provider->CreateForTesting(id);
2670 EXPECT_NE(0u, id);
2672 Mock::VerifyAndClearExpectations(context);
2676 TEST_P(ResourceProviderTest, TextureHint) {
2677 // Sampling is only supported for GL textures.
2678 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE)
2679 return;
2681 scoped_ptr<TextureStateTrackingContext> context_owned(
2682 new TextureStateTrackingContext);
2683 TextureStateTrackingContext* context = context_owned.get();
2684 context->set_support_texture_storage(true);
2685 context->set_support_texture_usage(true);
2687 FakeOutputSurfaceClient output_surface_client;
2688 scoped_ptr<OutputSurface> output_surface(
2689 FakeOutputSurface::Create3d(context_owned.Pass()));
2690 CHECK(output_surface->BindToClient(&output_surface_client));
2692 scoped_ptr<ResourceProvider> resource_provider(ResourceProvider::Create(
2693 output_surface.get(), shared_bitmap_manager_.get(),
2694 gpu_memory_buffer_manager_.get(), NULL, 0, false, 1,
2695 use_image_texture_targets_));
2697 gfx::Size size(1, 1);
2698 ResourceFormat format = RGBA_8888;
2699 GLenum texture_pool = GL_TEXTURE_POOL_UNMANAGED_CHROMIUM;
2701 const ResourceProvider::TextureHint hints[4] = {
2702 ResourceProvider::TEXTURE_HINT_DEFAULT,
2703 ResourceProvider::TEXTURE_HINT_IMMUTABLE,
2704 ResourceProvider::TEXTURE_HINT_FRAMEBUFFER,
2705 ResourceProvider::TEXTURE_HINT_IMMUTABLE_FRAMEBUFFER,
2707 for (GLuint texture_id = 1; texture_id <= arraysize(hints); ++texture_id) {
2708 // Check that the texture gets created with the right sampler settings.
2709 ResourceId id = resource_provider->CreateGLTexture(
2710 size, GL_TEXTURE_2D, texture_pool, GL_CLAMP_TO_EDGE,
2711 hints[texture_id - 1], format);
2712 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id));
2713 EXPECT_CALL(*context,
2714 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
2715 EXPECT_CALL(*context,
2716 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR));
2717 EXPECT_CALL(
2718 *context,
2719 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE));
2720 EXPECT_CALL(
2721 *context,
2722 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE));
2723 EXPECT_CALL(*context,
2724 texParameteri(GL_TEXTURE_2D,
2725 GL_TEXTURE_POOL_CHROMIUM,
2726 GL_TEXTURE_POOL_UNMANAGED_CHROMIUM));
2727 // Check only TEXTURE_HINT_FRAMEBUFFER set GL_TEXTURE_USAGE_ANGLE.
2728 bool is_framebuffer_hint =
2729 hints[texture_id - 1] & ResourceProvider::TEXTURE_HINT_FRAMEBUFFER;
2730 EXPECT_CALL(*context,
2731 texParameteri(GL_TEXTURE_2D,
2732 GL_TEXTURE_USAGE_ANGLE,
2733 GL_FRAMEBUFFER_ATTACHMENT_ANGLE))
2734 .Times(is_framebuffer_hint ? 1 : 0);
2735 resource_provider->CreateForTesting(id);
2736 EXPECT_NE(0u, id);
2738 Mock::VerifyAndClearExpectations(context);
2742 TEST_P(ResourceProviderTest, TextureMailbox_SharedMemory) {
2743 if (GetParam() != ResourceProvider::RESOURCE_TYPE_BITMAP)
2744 return;
2746 gfx::Size size(64, 64);
2747 const uint32_t kBadBeef = 0xbadbeef;
2748 scoped_ptr<SharedBitmap> shared_bitmap(
2749 CreateAndFillSharedBitmap(shared_bitmap_manager_.get(), size, kBadBeef));
2751 FakeOutputSurfaceClient output_surface_client;
2752 scoped_ptr<OutputSurface> output_surface(
2753 FakeOutputSurface::CreateSoftware(make_scoped_ptr(
2754 new SoftwareOutputDevice)));
2755 CHECK(output_surface->BindToClient(&output_surface_client));
2757 scoped_ptr<ResourceProvider> resource_provider(ResourceProvider::Create(
2758 output_surface.get(), shared_bitmap_manager_.get(),
2759 gpu_memory_buffer_manager_.get(), main_thread_task_runner_.get(), 0,
2760 false, 1, use_image_texture_targets_));
2762 uint32 release_sync_point = 0;
2763 bool lost_resource = false;
2764 BlockingTaskRunner* main_thread_task_runner = NULL;
2765 scoped_ptr<SingleReleaseCallbackImpl> callback =
2766 SingleReleaseCallbackImpl::Create(base::Bind(&ReleaseCallback,
2767 &release_sync_point,
2768 &lost_resource,
2769 &main_thread_task_runner));
2770 TextureMailbox mailbox(shared_bitmap.get(), size);
2772 ResourceId id = resource_provider->CreateResourceFromTextureMailbox(
2773 mailbox, callback.Pass());
2774 EXPECT_NE(0u, id);
2777 ResourceProvider::ScopedReadLockSoftware lock(resource_provider.get(), id);
2778 const SkBitmap* sk_bitmap = lock.sk_bitmap();
2779 EXPECT_EQ(sk_bitmap->width(), size.width());
2780 EXPECT_EQ(sk_bitmap->height(), size.height());
2781 EXPECT_EQ(*sk_bitmap->getAddr32(16, 16), kBadBeef);
2784 resource_provider->DeleteResource(id);
2785 EXPECT_EQ(0u, release_sync_point);
2786 EXPECT_FALSE(lost_resource);
2787 EXPECT_EQ(main_thread_task_runner_.get(), main_thread_task_runner);
2790 class ResourceProviderTestTextureMailboxGLFilters
2791 : public ResourceProviderTest {
2792 public:
2793 static void RunTest(TestSharedBitmapManager* shared_bitmap_manager,
2794 TestGpuMemoryBufferManager* gpu_memory_buffer_manager,
2795 BlockingTaskRunner* main_thread_task_runner,
2796 bool mailbox_nearest_neighbor,
2797 GLenum sampler_filter) {
2798 scoped_ptr<TextureStateTrackingContext> context_owned(
2799 new TextureStateTrackingContext);
2800 TextureStateTrackingContext* context = context_owned.get();
2802 FakeOutputSurfaceClient output_surface_client;
2803 scoped_ptr<OutputSurface> output_surface(
2804 FakeOutputSurface::Create3d(context_owned.Pass()));
2805 CHECK(output_surface->BindToClient(&output_surface_client));
2807 scoped_ptr<ResourceProvider> resource_provider(ResourceProvider::Create(
2808 output_surface.get(), shared_bitmap_manager, gpu_memory_buffer_manager,
2809 main_thread_task_runner, 0, false, 1, use_image_texture_targets_));
2811 unsigned texture_id = 1;
2812 uint32 sync_point = 30;
2813 unsigned target = GL_TEXTURE_2D;
2815 EXPECT_CALL(*context, bindTexture(_, _)).Times(0);
2816 EXPECT_CALL(*context, waitSyncPoint(_)).Times(0);
2817 EXPECT_CALL(*context, insertSyncPoint()).Times(0);
2818 EXPECT_CALL(*context, produceTextureDirectCHROMIUM(_, _, _)).Times(0);
2819 EXPECT_CALL(*context, createAndConsumeTextureCHROMIUM(_, _)).Times(0);
2821 gpu::Mailbox gpu_mailbox;
2822 memcpy(gpu_mailbox.name, "Hello world", strlen("Hello world") + 1);
2823 uint32 release_sync_point = 0;
2824 bool lost_resource = false;
2825 BlockingTaskRunner* mailbox_task_runner = NULL;
2826 scoped_ptr<SingleReleaseCallbackImpl> callback =
2827 SingleReleaseCallbackImpl::Create(base::Bind(&ReleaseCallback,
2828 &release_sync_point,
2829 &lost_resource,
2830 &mailbox_task_runner));
2832 TextureMailbox mailbox(gpu_mailbox, target, sync_point);
2833 mailbox.set_nearest_neighbor(mailbox_nearest_neighbor);
2835 ResourceId id = resource_provider->CreateResourceFromTextureMailbox(
2836 mailbox, callback.Pass());
2837 EXPECT_NE(0u, id);
2839 Mock::VerifyAndClearExpectations(context);
2842 // Mailbox sync point WaitSyncPoint before using the texture.
2843 EXPECT_CALL(*context, waitSyncPoint(sync_point));
2844 resource_provider->WaitSyncPointIfNeeded(id);
2845 Mock::VerifyAndClearExpectations(context);
2847 EXPECT_CALL(*context, createAndConsumeTextureCHROMIUM(target, _))
2848 .WillOnce(Return(texture_id));
2849 EXPECT_CALL(*context, bindTexture(target, texture_id));
2851 EXPECT_CALL(*context, insertSyncPoint()).Times(0);
2852 EXPECT_CALL(*context, produceTextureDirectCHROMIUM(_, _, _)).Times(0);
2854 // The sampler will reset these if |mailbox_nearest_neighbor| does not
2855 // match |sampler_filter|.
2856 if (mailbox_nearest_neighbor != (sampler_filter == GL_NEAREST)) {
2857 EXPECT_CALL(*context, texParameteri(
2858 GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, sampler_filter));
2859 EXPECT_CALL(*context, texParameteri(
2860 GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, sampler_filter));
2863 ResourceProvider::ScopedSamplerGL lock(
2864 resource_provider.get(), id, sampler_filter);
2865 Mock::VerifyAndClearExpectations(context);
2867 // When done with it, a sync point should be inserted, but no produce is
2868 // necessary.
2869 EXPECT_CALL(*context, bindTexture(_, _)).Times(0);
2870 EXPECT_CALL(*context, insertSyncPoint());
2871 EXPECT_CALL(*context, produceTextureDirectCHROMIUM(_, _, _)).Times(0);
2873 EXPECT_CALL(*context, waitSyncPoint(_)).Times(0);
2874 EXPECT_CALL(*context, createAndConsumeTextureCHROMIUM(_, _)).Times(0);
2877 resource_provider->DeleteResource(id);
2878 EXPECT_EQ(0u, release_sync_point);
2879 EXPECT_FALSE(lost_resource);
2880 EXPECT_EQ(main_thread_task_runner, mailbox_task_runner);
2884 TEST_P(ResourceProviderTest, TextureMailbox_GLTexture2D_LinearToLinear) {
2885 // Mailboxing is only supported for GL textures.
2886 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE)
2887 return;
2889 ResourceProviderTestTextureMailboxGLFilters::RunTest(
2890 shared_bitmap_manager_.get(),
2891 gpu_memory_buffer_manager_.get(),
2892 main_thread_task_runner_.get(),
2893 false,
2894 GL_LINEAR);
2897 TEST_P(ResourceProviderTest, TextureMailbox_GLTexture2D_NearestToNearest) {
2898 // Mailboxing is only supported for GL textures.
2899 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE)
2900 return;
2902 ResourceProviderTestTextureMailboxGLFilters::RunTest(
2903 shared_bitmap_manager_.get(),
2904 gpu_memory_buffer_manager_.get(),
2905 main_thread_task_runner_.get(),
2906 true,
2907 GL_NEAREST);
2910 TEST_P(ResourceProviderTest, TextureMailbox_GLTexture2D_NearestToLinear) {
2911 // Mailboxing is only supported for GL textures.
2912 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE)
2913 return;
2915 ResourceProviderTestTextureMailboxGLFilters::RunTest(
2916 shared_bitmap_manager_.get(),
2917 gpu_memory_buffer_manager_.get(),
2918 main_thread_task_runner_.get(),
2919 true,
2920 GL_LINEAR);
2923 TEST_P(ResourceProviderTest, TextureMailbox_GLTexture2D_LinearToNearest) {
2924 // Mailboxing is only supported for GL textures.
2925 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE)
2926 return;
2928 ResourceProviderTestTextureMailboxGLFilters::RunTest(
2929 shared_bitmap_manager_.get(),
2930 gpu_memory_buffer_manager_.get(),
2931 main_thread_task_runner_.get(),
2932 false,
2933 GL_NEAREST);
2936 TEST_P(ResourceProviderTest, TextureMailbox_GLTextureExternalOES) {
2937 // Mailboxing is only supported for GL textures.
2938 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE)
2939 return;
2941 scoped_ptr<TextureStateTrackingContext> context_owned(
2942 new TextureStateTrackingContext);
2943 TextureStateTrackingContext* context = context_owned.get();
2945 FakeOutputSurfaceClient output_surface_client;
2946 scoped_ptr<OutputSurface> output_surface(
2947 FakeOutputSurface::Create3d(context_owned.Pass()));
2948 CHECK(output_surface->BindToClient(&output_surface_client));
2950 scoped_ptr<ResourceProvider> resource_provider(ResourceProvider::Create(
2951 output_surface.get(), shared_bitmap_manager_.get(),
2952 gpu_memory_buffer_manager_.get(), NULL, 0, false, 1,
2953 use_image_texture_targets_));
2955 uint32 sync_point = 30;
2956 unsigned target = GL_TEXTURE_EXTERNAL_OES;
2958 EXPECT_CALL(*context, bindTexture(_, _)).Times(0);
2959 EXPECT_CALL(*context, waitSyncPoint(_)).Times(0);
2960 EXPECT_CALL(*context, insertSyncPoint()).Times(0);
2961 EXPECT_CALL(*context, produceTextureDirectCHROMIUM(_, _, _)).Times(0);
2962 EXPECT_CALL(*context, createAndConsumeTextureCHROMIUM(_, _)).Times(0);
2964 gpu::Mailbox gpu_mailbox;
2965 memcpy(gpu_mailbox.name, "Hello world", strlen("Hello world") + 1);
2966 scoped_ptr<SingleReleaseCallbackImpl> callback =
2967 SingleReleaseCallbackImpl::Create(base::Bind(&EmptyReleaseCallback));
2969 TextureMailbox mailbox(gpu_mailbox, target, sync_point);
2971 ResourceId id = resource_provider->CreateResourceFromTextureMailbox(
2972 mailbox, callback.Pass());
2973 EXPECT_NE(0u, id);
2975 Mock::VerifyAndClearExpectations(context);
2978 // Mailbox sync point WaitSyncPoint before using the texture.
2979 EXPECT_CALL(*context, waitSyncPoint(sync_point));
2980 resource_provider->WaitSyncPointIfNeeded(id);
2981 Mock::VerifyAndClearExpectations(context);
2983 unsigned texture_id = 1;
2985 EXPECT_CALL(*context, createAndConsumeTextureCHROMIUM(target, _))
2986 .WillOnce(Return(texture_id));
2988 EXPECT_CALL(*context, insertSyncPoint()).Times(0);
2989 EXPECT_CALL(*context, produceTextureDirectCHROMIUM(_, _, _)).Times(0);
2991 ResourceProvider::ScopedReadLockGL lock(resource_provider.get(), id);
2992 Mock::VerifyAndClearExpectations(context);
2994 // When done with it, a sync point should be inserted, but no produce is
2995 // necessary.
2996 EXPECT_CALL(*context, bindTexture(_, _)).Times(0);
2997 EXPECT_CALL(*context, insertSyncPoint());
2998 EXPECT_CALL(*context, produceTextureDirectCHROMIUM(_, _, _)).Times(0);
3000 EXPECT_CALL(*context, waitSyncPoint(_)).Times(0);
3001 EXPECT_CALL(*context, createAndConsumeTextureCHROMIUM(_, _)).Times(0);
3005 TEST_P(ResourceProviderTest,
3006 TextureMailbox_WaitSyncPointIfNeeded_WithSyncPoint) {
3007 // Mailboxing is only supported for GL textures.
3008 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE)
3009 return;
3011 scoped_ptr<TextureStateTrackingContext> context_owned(
3012 new TextureStateTrackingContext);
3013 TextureStateTrackingContext* context = context_owned.get();
3015 FakeOutputSurfaceClient output_surface_client;
3016 scoped_ptr<OutputSurface> output_surface(
3017 FakeOutputSurface::Create3d(context_owned.Pass()));
3018 CHECK(output_surface->BindToClient(&output_surface_client));
3020 scoped_ptr<ResourceProvider> resource_provider(ResourceProvider::Create(
3021 output_surface.get(), shared_bitmap_manager_.get(),
3022 gpu_memory_buffer_manager_.get(), NULL, 0, false, 1,
3023 use_image_texture_targets_));
3025 uint32 sync_point = 30;
3026 unsigned target = GL_TEXTURE_2D;
3028 EXPECT_CALL(*context, bindTexture(_, _)).Times(0);
3029 EXPECT_CALL(*context, waitSyncPoint(_)).Times(0);
3030 EXPECT_CALL(*context, insertSyncPoint()).Times(0);
3031 EXPECT_CALL(*context, produceTextureDirectCHROMIUM(_, _, _)).Times(0);
3032 EXPECT_CALL(*context, createAndConsumeTextureCHROMIUM(_, _)).Times(0);
3034 gpu::Mailbox gpu_mailbox;
3035 memcpy(gpu_mailbox.name, "Hello world", strlen("Hello world") + 1);
3036 scoped_ptr<SingleReleaseCallbackImpl> callback =
3037 SingleReleaseCallbackImpl::Create(base::Bind(&EmptyReleaseCallback));
3039 TextureMailbox mailbox(gpu_mailbox, target, sync_point);
3041 ResourceId id = resource_provider->CreateResourceFromTextureMailbox(
3042 mailbox, callback.Pass());
3043 EXPECT_NE(0u, id);
3045 Mock::VerifyAndClearExpectations(context);
3048 // First call to WaitSyncPointIfNeeded should call waitSyncPoint.
3049 EXPECT_CALL(*context, waitSyncPoint(sync_point));
3050 resource_provider->WaitSyncPointIfNeeded(id);
3051 Mock::VerifyAndClearExpectations(context);
3053 // Subsequent calls to WaitSyncPointIfNeeded shouldn't call waitSyncPoint.
3054 EXPECT_CALL(*context, waitSyncPoint(_)).Times(0);
3055 resource_provider->WaitSyncPointIfNeeded(id);
3056 Mock::VerifyAndClearExpectations(context);
3060 TEST_P(ResourceProviderTest, TextureMailbox_WaitSyncPointIfNeeded_NoSyncPoint) {
3061 // Mailboxing is only supported for GL textures.
3062 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE)
3063 return;
3065 scoped_ptr<TextureStateTrackingContext> context_owned(
3066 new TextureStateTrackingContext);
3067 TextureStateTrackingContext* context = context_owned.get();
3069 FakeOutputSurfaceClient output_surface_client;
3070 scoped_ptr<OutputSurface> output_surface(
3071 FakeOutputSurface::Create3d(context_owned.Pass()));
3072 CHECK(output_surface->BindToClient(&output_surface_client));
3074 scoped_ptr<ResourceProvider> resource_provider(ResourceProvider::Create(
3075 output_surface.get(), shared_bitmap_manager_.get(),
3076 gpu_memory_buffer_manager_.get(), NULL, 0, false, 1,
3077 use_image_texture_targets_));
3079 uint32 sync_point = 0;
3080 unsigned target = GL_TEXTURE_2D;
3082 EXPECT_CALL(*context, bindTexture(_, _)).Times(0);
3083 EXPECT_CALL(*context, waitSyncPoint(_)).Times(0);
3084 EXPECT_CALL(*context, insertSyncPoint()).Times(0);
3085 EXPECT_CALL(*context, produceTextureDirectCHROMIUM(_, _, _)).Times(0);
3086 EXPECT_CALL(*context, createAndConsumeTextureCHROMIUM(_, _)).Times(0);
3088 gpu::Mailbox gpu_mailbox;
3089 memcpy(gpu_mailbox.name, "Hello world", strlen("Hello world") + 1);
3090 scoped_ptr<SingleReleaseCallbackImpl> callback =
3091 SingleReleaseCallbackImpl::Create(base::Bind(&EmptyReleaseCallback));
3093 TextureMailbox mailbox(gpu_mailbox, target, sync_point);
3095 ResourceId id = resource_provider->CreateResourceFromTextureMailbox(
3096 mailbox, callback.Pass());
3097 EXPECT_NE(0u, id);
3099 Mock::VerifyAndClearExpectations(context);
3102 // WaitSyncPointIfNeeded with sync_point == 0 shouldn't call waitSyncPoint.
3103 EXPECT_CALL(*context, waitSyncPoint(_)).Times(0);
3104 resource_provider->WaitSyncPointIfNeeded(id);
3105 Mock::VerifyAndClearExpectations(context);
3109 class AllocationTrackingContext3D : public TestWebGraphicsContext3D {
3110 public:
3111 MOCK_METHOD0(NextTextureId, GLuint());
3112 MOCK_METHOD1(RetireTextureId, void(GLuint id));
3113 MOCK_METHOD2(bindTexture, void(GLenum target, GLuint texture));
3114 MOCK_METHOD5(texStorage2DEXT,
3115 void(GLenum target,
3116 GLint levels,
3117 GLuint internalformat,
3118 GLint width,
3119 GLint height));
3120 MOCK_METHOD9(texImage2D,
3121 void(GLenum target,
3122 GLint level,
3123 GLenum internalformat,
3124 GLsizei width,
3125 GLsizei height,
3126 GLint border,
3127 GLenum format,
3128 GLenum type,
3129 const void* pixels));
3130 MOCK_METHOD9(texSubImage2D,
3131 void(GLenum target,
3132 GLint level,
3133 GLint xoffset,
3134 GLint yoffset,
3135 GLsizei width,
3136 GLsizei height,
3137 GLenum format,
3138 GLenum type,
3139 const void* pixels));
3140 MOCK_METHOD9(asyncTexImage2DCHROMIUM,
3141 void(GLenum target,
3142 GLint level,
3143 GLenum internalformat,
3144 GLsizei width,
3145 GLsizei height,
3146 GLint border,
3147 GLenum format,
3148 GLenum type,
3149 const void* pixels));
3150 MOCK_METHOD9(asyncTexSubImage2DCHROMIUM,
3151 void(GLenum target,
3152 GLint level,
3153 GLint xoffset,
3154 GLint yoffset,
3155 GLsizei width,
3156 GLsizei height,
3157 GLenum format,
3158 GLenum type,
3159 const void* pixels));
3160 MOCK_METHOD8(compressedTexImage2D,
3161 void(GLenum target,
3162 GLint level,
3163 GLenum internalformat,
3164 GLsizei width,
3165 GLsizei height,
3166 GLint border,
3167 GLsizei image_size,
3168 const void* data));
3169 MOCK_METHOD1(waitAsyncTexImage2DCHROMIUM, void(GLenum));
3170 MOCK_METHOD4(createImageCHROMIUM,
3171 GLuint(ClientBuffer, GLsizei, GLsizei, GLenum));
3172 MOCK_METHOD1(destroyImageCHROMIUM, void(GLuint));
3173 MOCK_METHOD2(bindTexImage2DCHROMIUM, void(GLenum, GLint));
3174 MOCK_METHOD2(releaseTexImage2DCHROMIUM, void(GLenum, GLint));
3176 // We're mocking bindTexture, so we override
3177 // TestWebGraphicsContext3D::texParameteri to avoid assertions related to the
3178 // currently bound texture.
3179 virtual void texParameteri(GLenum target, GLenum pname, GLint param) {}
3182 TEST_P(ResourceProviderTest, TextureAllocation) {
3183 // Only for GL textures.
3184 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE)
3185 return;
3186 scoped_ptr<AllocationTrackingContext3D> context_owned(
3187 new StrictMock<AllocationTrackingContext3D>);
3188 AllocationTrackingContext3D* context = context_owned.get();
3190 FakeOutputSurfaceClient output_surface_client;
3191 scoped_ptr<OutputSurface> output_surface(
3192 FakeOutputSurface::Create3d(context_owned.Pass()));
3193 CHECK(output_surface->BindToClient(&output_surface_client));
3195 scoped_ptr<ResourceProvider> resource_provider(ResourceProvider::Create(
3196 output_surface.get(), shared_bitmap_manager_.get(),
3197 gpu_memory_buffer_manager_.get(), NULL, 0, false, 1,
3198 use_image_texture_targets_));
3200 gfx::Size size(2, 2);
3201 gfx::Vector2d offset(0, 0);
3202 ResourceFormat format = RGBA_8888;
3203 ResourceId id = 0;
3204 uint8_t pixels[16] = { 0 };
3205 int texture_id = 123;
3207 // Lazy allocation. Don't allocate when creating the resource.
3208 id = resource_provider->CreateResource(
3209 size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE, format);
3211 EXPECT_CALL(*context, NextTextureId()).WillOnce(Return(texture_id));
3212 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id)).Times(1);
3213 resource_provider->CreateForTesting(id);
3215 EXPECT_CALL(*context, RetireTextureId(texture_id)).Times(1);
3216 resource_provider->DeleteResource(id);
3218 Mock::VerifyAndClearExpectations(context);
3220 // Do allocate when we set the pixels.
3221 id = resource_provider->CreateResource(
3222 size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE, format);
3224 EXPECT_CALL(*context, NextTextureId()).WillOnce(Return(texture_id));
3225 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id)).Times(3);
3226 EXPECT_CALL(*context, texImage2D(_, _, _, 2, 2, _, _, _, _)).Times(1);
3227 EXPECT_CALL(*context, texSubImage2D(_, _, _, _, 2, 2, _, _, _)).Times(1);
3228 resource_provider->CopyToResource(id, pixels, size);
3230 EXPECT_CALL(*context, RetireTextureId(texture_id)).Times(1);
3231 resource_provider->DeleteResource(id);
3233 Mock::VerifyAndClearExpectations(context);
3236 TEST_P(ResourceProviderTest, TextureAllocationHint) {
3237 // Only for GL textures.
3238 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE)
3239 return;
3240 scoped_ptr<AllocationTrackingContext3D> context_owned(
3241 new StrictMock<AllocationTrackingContext3D>);
3242 AllocationTrackingContext3D* context = context_owned.get();
3243 context->set_support_texture_storage(true);
3244 context->set_support_texture_usage(true);
3246 FakeOutputSurfaceClient output_surface_client;
3247 scoped_ptr<OutputSurface> output_surface(
3248 FakeOutputSurface::Create3d(context_owned.Pass()));
3249 CHECK(output_surface->BindToClient(&output_surface_client));
3251 scoped_ptr<ResourceProvider> resource_provider(ResourceProvider::Create(
3252 output_surface.get(), shared_bitmap_manager_.get(),
3253 gpu_memory_buffer_manager_.get(), NULL, 0, false, 1,
3254 use_image_texture_targets_));
3256 gfx::Size size(2, 2);
3258 const ResourceFormat formats[2] = {RGBA_8888, BGRA_8888};
3259 const ResourceProvider::TextureHint hints[4] = {
3260 ResourceProvider::TEXTURE_HINT_DEFAULT,
3261 ResourceProvider::TEXTURE_HINT_IMMUTABLE,
3262 ResourceProvider::TEXTURE_HINT_FRAMEBUFFER,
3263 ResourceProvider::TEXTURE_HINT_IMMUTABLE_FRAMEBUFFER,
3265 for (size_t i = 0; i < arraysize(formats); ++i) {
3266 for (GLuint texture_id = 1; texture_id <= arraysize(hints); ++texture_id) {
3267 // Lazy allocation. Don't allocate when creating the resource.
3268 ResourceId id = resource_provider->CreateResource(
3269 size, GL_CLAMP_TO_EDGE, hints[texture_id - 1], formats[i]);
3271 EXPECT_CALL(*context, NextTextureId()).WillOnce(Return(texture_id));
3272 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id)).Times(2);
3273 bool is_immutable_hint =
3274 hints[texture_id - 1] & ResourceProvider::TEXTURE_HINT_IMMUTABLE;
3275 bool support_immutable_texture =
3276 is_immutable_hint && formats[i] == RGBA_8888;
3277 EXPECT_CALL(*context, texStorage2DEXT(_, _, _, 2, 2))
3278 .Times(support_immutable_texture ? 1 : 0);
3279 EXPECT_CALL(*context, texImage2D(_, _, _, 2, 2, _, _, _, _))
3280 .Times(support_immutable_texture ? 0 : 1);
3281 resource_provider->AllocateForTesting(id);
3283 EXPECT_CALL(*context, RetireTextureId(texture_id)).Times(1);
3284 resource_provider->DeleteResource(id);
3286 Mock::VerifyAndClearExpectations(context);
3291 TEST_P(ResourceProviderTest, TextureAllocationHint_BGRA) {
3292 // Only for GL textures.
3293 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE)
3294 return;
3295 scoped_ptr<AllocationTrackingContext3D> context_owned(
3296 new StrictMock<AllocationTrackingContext3D>);
3297 AllocationTrackingContext3D* context = context_owned.get();
3298 context->set_support_texture_format_bgra8888(true);
3299 context->set_support_texture_storage(true);
3300 context->set_support_texture_usage(true);
3302 FakeOutputSurfaceClient output_surface_client;
3303 scoped_ptr<OutputSurface> output_surface(
3304 FakeOutputSurface::Create3d(context_owned.Pass()));
3305 CHECK(output_surface->BindToClient(&output_surface_client));
3307 scoped_ptr<ResourceProvider> resource_provider(ResourceProvider::Create(
3308 output_surface.get(), shared_bitmap_manager_.get(),
3309 gpu_memory_buffer_manager_.get(), NULL, 0, false, 1,
3310 use_image_texture_targets_));
3312 gfx::Size size(2, 2);
3313 const ResourceFormat formats[2] = {RGBA_8888, BGRA_8888};
3315 const ResourceProvider::TextureHint hints[4] = {
3316 ResourceProvider::TEXTURE_HINT_DEFAULT,
3317 ResourceProvider::TEXTURE_HINT_IMMUTABLE,
3318 ResourceProvider::TEXTURE_HINT_FRAMEBUFFER,
3319 ResourceProvider::TEXTURE_HINT_IMMUTABLE_FRAMEBUFFER,
3321 for (size_t i = 0; i < arraysize(formats); ++i) {
3322 for (GLuint texture_id = 1; texture_id <= arraysize(hints); ++texture_id) {
3323 // Lazy allocation. Don't allocate when creating the resource.
3324 ResourceId id = resource_provider->CreateResource(
3325 size, GL_CLAMP_TO_EDGE, hints[texture_id - 1], formats[i]);
3327 EXPECT_CALL(*context, NextTextureId()).WillOnce(Return(texture_id));
3328 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id)).Times(2);
3329 bool is_immutable_hint =
3330 hints[texture_id - 1] & ResourceProvider::TEXTURE_HINT_IMMUTABLE;
3331 EXPECT_CALL(*context, texStorage2DEXT(_, _, _, 2, 2))
3332 .Times(is_immutable_hint ? 1 : 0);
3333 EXPECT_CALL(*context, texImage2D(_, _, _, 2, 2, _, _, _, _))
3334 .Times(is_immutable_hint ? 0 : 1);
3335 resource_provider->AllocateForTesting(id);
3337 EXPECT_CALL(*context, RetireTextureId(texture_id)).Times(1);
3338 resource_provider->DeleteResource(id);
3340 Mock::VerifyAndClearExpectations(context);
3345 TEST_P(ResourceProviderTest, Image_GLTexture) {
3346 // Only for GL textures.
3347 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE)
3348 return;
3349 scoped_ptr<AllocationTrackingContext3D> context_owned(
3350 new StrictMock<AllocationTrackingContext3D>);
3351 AllocationTrackingContext3D* context = context_owned.get();
3353 FakeOutputSurfaceClient output_surface_client;
3354 scoped_ptr<OutputSurface> output_surface(
3355 FakeOutputSurface::Create3d(context_owned.Pass()));
3356 CHECK(output_surface->BindToClient(&output_surface_client));
3358 const int kWidth = 2;
3359 const int kHeight = 2;
3360 gfx::Size size(kWidth, kHeight);
3361 ResourceFormat format = RGBA_8888;
3362 ResourceId id = 0;
3363 const unsigned kTextureId = 123u;
3364 const unsigned kImageId = 234u;
3366 scoped_ptr<ResourceProvider> resource_provider(ResourceProvider::Create(
3367 output_surface.get(), shared_bitmap_manager_.get(),
3368 gpu_memory_buffer_manager_.get(), NULL, 0, false, 1,
3369 use_image_texture_targets_));
3371 id = resource_provider->CreateResource(
3372 size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE, format);
3374 EXPECT_CALL(*context, NextTextureId())
3375 .WillOnce(Return(kTextureId))
3376 .RetiresOnSaturation();
3377 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, kTextureId))
3378 .Times(1)
3379 .RetiresOnSaturation();
3380 EXPECT_CALL(*context, createImageCHROMIUM(_, kWidth, kHeight, GL_RGBA))
3381 .WillOnce(Return(kImageId))
3382 .RetiresOnSaturation();
3384 ResourceProvider::ScopedWriteLockGpuMemoryBuffer lock(
3385 resource_provider.get(), id);
3386 EXPECT_TRUE(lock.GetGpuMemoryBuffer());
3389 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, kTextureId))
3390 .Times(1)
3391 .RetiresOnSaturation();
3392 EXPECT_CALL(*context, bindTexImage2DCHROMIUM(GL_TEXTURE_2D, kImageId))
3393 .Times(1)
3394 .RetiresOnSaturation();
3396 ResourceProvider::ScopedSamplerGL lock_gl(
3397 resource_provider.get(), id, GL_TEXTURE_2D, GL_LINEAR);
3398 EXPECT_EQ(kTextureId, lock_gl.texture_id());
3402 ResourceProvider::ScopedWriteLockGpuMemoryBuffer lock(
3403 resource_provider.get(), id);
3404 EXPECT_TRUE(lock.GetGpuMemoryBuffer());
3407 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, kTextureId)).Times(1)
3408 .RetiresOnSaturation();
3409 EXPECT_CALL(*context, releaseTexImage2DCHROMIUM(GL_TEXTURE_2D, kImageId))
3410 .Times(1)
3411 .RetiresOnSaturation();
3412 EXPECT_CALL(*context, bindTexImage2DCHROMIUM(GL_TEXTURE_2D, kImageId))
3413 .Times(1)
3414 .RetiresOnSaturation();
3415 EXPECT_CALL(*context, RetireTextureId(kTextureId))
3416 .Times(1)
3417 .RetiresOnSaturation();
3419 ResourceProvider::ScopedSamplerGL lock_gl(
3420 resource_provider.get(), id, GL_TEXTURE_2D, GL_LINEAR);
3421 EXPECT_EQ(kTextureId, lock_gl.texture_id());
3424 EXPECT_CALL(*context, destroyImageCHROMIUM(kImageId))
3425 .Times(1)
3426 .RetiresOnSaturation();
3429 TEST_P(ResourceProviderTest, CompressedTextureETC1Allocate) {
3430 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE)
3431 return;
3433 scoped_ptr<AllocationTrackingContext3D> context_owned(
3434 new AllocationTrackingContext3D);
3435 AllocationTrackingContext3D* context = context_owned.get();
3436 context_owned->set_support_compressed_texture_etc1(true);
3438 FakeOutputSurfaceClient output_surface_client;
3439 scoped_ptr<OutputSurface> output_surface(
3440 FakeOutputSurface::Create3d(context_owned.Pass()));
3441 CHECK(output_surface->BindToClient(&output_surface_client));
3443 gfx::Size size(4, 4);
3444 scoped_ptr<ResourceProvider> resource_provider(ResourceProvider::Create(
3445 output_surface.get(), shared_bitmap_manager_.get(),
3446 gpu_memory_buffer_manager_.get(), NULL, 0, false, 1,
3447 use_image_texture_targets_));
3448 int texture_id = 123;
3450 ResourceId id = resource_provider->CreateResource(
3451 size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE, ETC1);
3452 EXPECT_NE(0u, id);
3453 EXPECT_CALL(*context, NextTextureId()).WillOnce(Return(texture_id));
3454 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id)).Times(2);
3455 resource_provider->AllocateForTesting(id);
3457 EXPECT_CALL(*context, RetireTextureId(texture_id)).Times(1);
3458 resource_provider->DeleteResource(id);
3461 TEST_P(ResourceProviderTest, CompressedTextureETC1Upload) {
3462 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE)
3463 return;
3465 scoped_ptr<AllocationTrackingContext3D> context_owned(
3466 new AllocationTrackingContext3D);
3467 AllocationTrackingContext3D* context = context_owned.get();
3468 context_owned->set_support_compressed_texture_etc1(true);
3470 FakeOutputSurfaceClient output_surface_client;
3471 scoped_ptr<OutputSurface> output_surface(
3472 FakeOutputSurface::Create3d(context_owned.Pass()));
3473 CHECK(output_surface->BindToClient(&output_surface_client));
3475 gfx::Size size(4, 4);
3476 scoped_ptr<ResourceProvider> resource_provider(ResourceProvider::Create(
3477 output_surface.get(), shared_bitmap_manager_.get(),
3478 gpu_memory_buffer_manager_.get(), NULL, 0, false, 1,
3479 use_image_texture_targets_));
3480 int texture_id = 123;
3481 uint8_t pixels[8];
3483 ResourceId id = resource_provider->CreateResource(
3484 size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE, ETC1);
3485 EXPECT_NE(0u, id);
3486 EXPECT_CALL(*context, NextTextureId()).WillOnce(Return(texture_id));
3487 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id)).Times(3);
3488 EXPECT_CALL(*context,
3489 compressedTexImage2D(
3490 _, 0, _, size.width(), size.height(), _, _, _)).Times(1);
3491 resource_provider->CopyToResource(id, pixels, size);
3493 EXPECT_CALL(*context, RetireTextureId(texture_id)).Times(1);
3494 resource_provider->DeleteResource(id);
3497 INSTANTIATE_TEST_CASE_P(
3498 ResourceProviderTests,
3499 ResourceProviderTest,
3500 ::testing::Values(ResourceProvider::RESOURCE_TYPE_GL_TEXTURE,
3501 ResourceProvider::RESOURCE_TYPE_BITMAP));
3503 class TextureIdAllocationTrackingContext : public TestWebGraphicsContext3D {
3504 public:
3505 GLuint NextTextureId() override {
3506 base::AutoLock lock(namespace_->lock);
3507 return namespace_->next_texture_id++;
3509 void RetireTextureId(GLuint) override {}
3510 GLuint PeekTextureId() {
3511 base::AutoLock lock(namespace_->lock);
3512 return namespace_->next_texture_id;
3516 TEST(ResourceProviderTest, TextureAllocationChunkSize) {
3517 scoped_ptr<TextureIdAllocationTrackingContext> context_owned(
3518 new TextureIdAllocationTrackingContext);
3519 TextureIdAllocationTrackingContext* context = context_owned.get();
3521 FakeOutputSurfaceClient output_surface_client;
3522 scoped_ptr<OutputSurface> output_surface(
3523 FakeOutputSurface::Create3d(context_owned.Pass()));
3524 CHECK(output_surface->BindToClient(&output_surface_client));
3525 scoped_ptr<SharedBitmapManager> shared_bitmap_manager(
3526 new TestSharedBitmapManager());
3528 gfx::Size size(1, 1);
3529 ResourceFormat format = RGBA_8888;
3532 size_t kTextureAllocationChunkSize = 1;
3533 scoped_ptr<ResourceProvider> resource_provider(ResourceProvider::Create(
3534 output_surface.get(), shared_bitmap_manager.get(), NULL, NULL, 0, false,
3535 kTextureAllocationChunkSize,
3536 ResourceProviderTest::use_image_texture_targets()));
3538 ResourceId id = resource_provider->CreateResource(
3539 size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE,
3540 format);
3541 resource_provider->AllocateForTesting(id);
3542 Mock::VerifyAndClearExpectations(context);
3544 DCHECK_EQ(2u, context->PeekTextureId());
3545 resource_provider->DeleteResource(id);
3549 size_t kTextureAllocationChunkSize = 8;
3550 scoped_ptr<ResourceProvider> resource_provider(ResourceProvider::Create(
3551 output_surface.get(), shared_bitmap_manager.get(), NULL, NULL, 0, false,
3552 kTextureAllocationChunkSize,
3553 ResourceProviderTest::use_image_texture_targets()));
3555 ResourceId id = resource_provider->CreateResource(
3556 size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE,
3557 format);
3558 resource_provider->AllocateForTesting(id);
3559 Mock::VerifyAndClearExpectations(context);
3561 DCHECK_EQ(10u, context->PeekTextureId());
3562 resource_provider->DeleteResource(id);
3566 } // namespace
3567 } // namespace cc